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

2788 lines
81 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. dwRet = ERROR_SUCCESS;
  620. }
  621. else
  622. {
  623. lstrcpyU(RasCredentials.szPassword, pszData);
  624. bClearPassword = (TEXT('\0') == pszData[0]);
  625. }
  626. }
  627. else
  628. {
  629. CmFree(pszConnectoid);
  630. return ERROR_INVALID_PARAMETER;
  631. }
  632. if (fSavePassword)
  633. {
  634. dwRet = pArgs->rlsRasLink.pfnSetCredentials(pszPhoneBook, pszConnectoid, &RasCredentials, bClearPassword);
  635. if (ERROR_CANNOT_FIND_PHONEBOOK_ENTRY == dwRet)
  636. {
  637. //
  638. // Then the phonebook entry doesn't exist yet, lets create it.
  639. //
  640. LPRASENTRY pRasEntry = (LPRASENTRY)CmMalloc(sizeof(RASENTRY));
  641. if (pRasEntry && pArgs->rlsRasLink.pfnSetEntryProperties)
  642. {
  643. pRasEntry->dwSize = sizeof(RASENTRY);
  644. dwRet = pArgs->rlsRasLink.pfnSetEntryProperties(pszPhoneBook, pszConnectoid, pRasEntry, pRasEntry->dwSize, NULL, 0);
  645. //
  646. // Lets try to set the credentials one more time ...
  647. //
  648. if (ERROR_SUCCESS == dwRet)
  649. {
  650. dwRet = pArgs->rlsRasLink.pfnSetCredentials(pszPhoneBook, pszConnectoid, &RasCredentials, bClearPassword);
  651. }
  652. CmFree(pRasEntry);
  653. }
  654. }
  655. }
  656. CmWipePassword(RasCredentials.szPassword);
  657. CmFree(pszConnectoid);
  658. }
  659. }
  660. return dwRet;
  661. }
  662. //+---------------------------------------------------------------------------
  663. //
  664. // Function: WriteUserInfoToRas
  665. //
  666. // Synopsis: Write a userinfo data to ras credential storage
  667. //
  668. // Arguments: pArgs ptr to ArgsStruct
  669. // uiDataID the resource ID associated with the data
  670. // pvData userinfo data
  671. //
  672. // Returns: int TRUE = success, FALSE = failure, returns -1 if RAS
  673. // doesn't cache this piece of data and it should be put
  674. // in the registry instead.
  675. //
  676. //----------------------------------------------------------------------------
  677. int WriteUserInfoToRas(
  678. ArgsStruct *pArgs,
  679. UINT uiDataID,
  680. PVOID pvData)
  681. {
  682. int iReturn = -1;
  683. if (OS_NT5 && pArgs && pArgs->bUseRasCredStore)
  684. {
  685. DWORD dwMask;
  686. LPTSTR pszPhoneBook = NULL;
  687. switch (uiDataID)
  688. {
  689. case UD_ID_USERNAME:
  690. dwMask = RASCM_UserName;
  691. iReturn = (ERROR_SUCCESS == RasSetCredsWrapper(pArgs, pArgs->pszRasPbk, dwMask, (LPCTSTR)pvData));
  692. break;
  693. case UD_ID_PASSWORD:
  694. dwMask = RASCM_Password;
  695. iReturn = (ERROR_SUCCESS == RasSetCredsWrapper(pArgs, pArgs->pszRasPbk, dwMask, (LPCTSTR)pvData));
  696. MYDBGASSERT(iReturn);
  697. //
  698. // Note that if we are using the same username then we want to write the password to both the
  699. // password and the InetPassword storage. This is because we don't actually have a password, just
  700. // 16 *'s. This tells RAS to look in its internal store for the password. The trouble is that if
  701. // we don't cache the real password when we hand RAS the 16 *'s, it looks and finds a NULL password.
  702. // Thus we keep both passwords the same and this avoids that problem.
  703. //
  704. if (pArgs->piniService->GPPB(c_pszCmSection, c_pszCmEntryUseSameUserName))
  705. {
  706. pszPhoneBook = CreateRasPrivatePbk(pArgs);
  707. if (pszPhoneBook)
  708. {
  709. iReturn = (ERROR_SUCCESS == RasSetCredsWrapper(pArgs, pszPhoneBook, dwMask, (LPCTSTR)pvData));
  710. CmFree(pszPhoneBook);
  711. }
  712. }
  713. break;
  714. case UD_ID_DOMAIN:
  715. dwMask = RASCM_Domain;
  716. iReturn = (ERROR_SUCCESS == RasSetCredsWrapper(pArgs, pArgs->pszRasPbk, dwMask, (LPCTSTR)pvData));
  717. break;
  718. case UD_ID_INET_PASSWORD:
  719. dwMask = RASCM_Password;
  720. pszPhoneBook = CreateRasPrivatePbk(pArgs);
  721. if (pszPhoneBook)
  722. {
  723. iReturn = (ERROR_SUCCESS == RasSetCredsWrapper(pArgs, pszPhoneBook, dwMask, (LPCTSTR)pvData));
  724. CmFree(pszPhoneBook);
  725. }
  726. break;
  727. case UD_ID_INET_USERNAME:
  728. dwMask = RASCM_UserName;
  729. pszPhoneBook = CreateRasPrivatePbk(pArgs);
  730. if (pszPhoneBook)
  731. {
  732. iReturn = (ERROR_SUCCESS == RasSetCredsWrapper(pArgs, pszPhoneBook, dwMask, (LPCTSTR)pvData));
  733. CmFree(pszPhoneBook);
  734. }
  735. break;
  736. default:
  737. break;
  738. }
  739. }
  740. if ((0 != iReturn) && (-1 != iReturn))
  741. {
  742. if (CM_CREDS_GLOBAL == pArgs->dwCurrentCredentialType)
  743. {
  744. CMTRACE1(TEXT("WriteUserInfoToRas() - %s saved to the Global RAS Credential store"), TranslateUserDataID(uiDataID));
  745. }
  746. else
  747. {
  748. CMTRACE1(TEXT("WriteUserInfoToRas() - %s saved to the User RAS Credential store"), TranslateUserDataID(uiDataID));
  749. }
  750. }
  751. return iReturn;
  752. }
  753. //+---------------------------------------------------------------------------
  754. //
  755. // Function: WriteUserInfoToReg
  756. //
  757. // Synopsis: Write a userinfo data to the registry.
  758. //
  759. // Arguments: pArgs ptr to ArgsStruct
  760. // uiDataID the resource ID associated with the data
  761. // pvData userinfo data
  762. //
  763. // Returns: BOOL TRUE = success, FALSE = failure
  764. //
  765. //----------------------------------------------------------------------------
  766. BOOL WriteUserInfoToReg(
  767. ArgsStruct *pArgs,
  768. UINT uiDataID,
  769. PVOID pvData)
  770. {
  771. MYDBGASSERT(pArgs);
  772. MYDBGASSERT(pvData);
  773. BOOL fRet = FALSE;
  774. UINT uiID = uiDataID; // can be changed in switch
  775. BYTE *lpData;
  776. if (NULL == pArgs || NULL == pvData)
  777. {
  778. return FALSE;
  779. }
  780. //
  781. // Determine Reg params based upon uiDataID
  782. //
  783. switch (uiID)
  784. {
  785. case UD_ID_USERNAME:
  786. case UD_ID_INET_USERNAME:
  787. case UD_ID_DOMAIN:
  788. case UD_ID_CURRENTACCESSPOINT:
  789. {
  790. //
  791. // Store as strings
  792. //
  793. DWORD dwSize = (lstrlenU((LPTSTR)pvData) + 1) * sizeof(TCHAR);
  794. MYDBGASSERT(dwSize <= (UNLEN + sizeof(TCHAR))); // Make sure size is reasonable
  795. lpData = (BYTE *) pvData;
  796. fRet = WriteDataToReg(pArgs->szServiceName, uiID, REG_SZ, lpData, dwSize, pArgs->fAllUser);
  797. break;
  798. }
  799. case UD_ID_PASSWORD:
  800. case UD_ID_INET_PASSWORD:
  801. {
  802. DWORD dwBufLen = 0;
  803. DWORD dwCrypt = 0;
  804. LPTSTR pszSubKey = BuildUserInfoSubKey(pArgs->szServiceName, pArgs->fAllUser);
  805. LPSTR pszAnsiSubKey = WzToSzWithAlloc(pszSubKey);
  806. if (UD_ID_INET_PASSWORD == uiID)
  807. {
  808. dwCrypt |= CMSECURE_ET_USE_SECOND_RND_KEY;
  809. }
  810. //
  811. // Encrypt
  812. //
  813. LPTSTR pszEncryptedData = EncryptPassword(pArgs, (LPTSTR) pvData, &dwBufLen, &dwCrypt, TRUE, pszAnsiSubKey);
  814. //
  815. // Free in case we return if the function failed
  816. //
  817. CmFree(pszSubKey);
  818. CmFree(pszAnsiSubKey);
  819. if (!pszEncryptedData)
  820. {
  821. return FALSE;
  822. }
  823. MYDBGASSERT(dwBufLen <= CM_MAX_PWD); // Can't read it out otherwise
  824. //
  825. // Write the password and the encryption type on success
  826. //
  827. if (WriteDataToReg(pArgs->szServiceName, uiID, REG_BINARY, (BYTE *) pszEncryptedData, dwBufLen, pArgs->fAllUser))
  828. {
  829. //
  830. // A second write for the encryption type. Written as a DWORD.
  831. //
  832. uiID = UD_ID_PCS;
  833. //
  834. // Now that we're UNICODE enabled, we will always be encrypting
  835. // a UNICODE string, so update the crypt type, so that it can be
  836. // properly decrypted.
  837. //
  838. dwCrypt = AnsiToUnicodePcs(dwCrypt);
  839. lpData = (BYTE *) &dwCrypt;
  840. fRet = WriteDataToReg(pArgs->szServiceName, uiID, REG_DWORD, lpData, sizeof(DWORD), pArgs->fAllUser);
  841. }
  842. //
  843. // Release the buffer before we go
  844. //
  845. CmFree(pszEncryptedData);
  846. break;
  847. }
  848. case UD_ID_NOPROMPT:
  849. case UD_ID_REMEMBER_PWD:
  850. case UD_ID_REMEMBER_INET_PASSWORD:
  851. case UD_ID_ACCESSPOINTENABLED:
  852. {
  853. //
  854. // Store BOOL as DWORD
  855. //
  856. DWORD dwTmp = *(LPBOOL)pvData;
  857. lpData = (BYTE *) &dwTmp;
  858. fRet = WriteDataToReg(pArgs->szServiceName, uiID, REG_DWORD, lpData, sizeof(DWORD), pArgs->fAllUser);
  859. break;
  860. }
  861. default:
  862. break;
  863. }
  864. MYDBGASSERT(fRet);
  865. return fRet;
  866. }
  867. //+----------------------------------------------------------------------------
  868. //
  869. // Function: WriteDataToReg
  870. //
  871. // Synopsis: Stores the specified data as the specifed value under the
  872. // specified key under the userinfo root.
  873. //
  874. // Arguments: LPCTSTR pszKey - The key name (service name)
  875. // UINT uiDataID - The resource ID, used to name the value
  876. // DWORD dwType - The registry data type
  877. // CONST BYTE *lpData - Ptr to the data to be stored
  878. // DWORD cbData - The size of the data buffer
  879. // BOOL fAllUser - Flag indicating that profile is All-User
  880. //
  881. // Returns: BOOL - TRUE on success, otherwise FALSE
  882. //
  883. // History: nickball Created 5/21/98
  884. //
  885. //+----------------------------------------------------------------------------
  886. BOOL WriteDataToReg(
  887. LPCTSTR pszKey,
  888. UINT uiDataID,
  889. DWORD dwType,
  890. CONST BYTE *lpData,
  891. DWORD cbData,
  892. BOOL fAllUser)
  893. {
  894. MYDBGASSERT(pszKey && *pszKey);
  895. MYDBGASSERT(lpData);
  896. HKEY hKeyCm;
  897. DWORD dwDisposition;
  898. DWORD dwRes = 1;
  899. LPTSTR pszSubKey;
  900. if (NULL == pszKey || !*pszKey || NULL == lpData)
  901. {
  902. return FALSE;
  903. }
  904. //
  905. // Per-user data is always stored under HKEY_CURRENT_USER
  906. // Build the sub key to be opened.
  907. //
  908. pszSubKey = BuildUserInfoSubKey(pszKey, fAllUser);
  909. if (NULL == pszSubKey)
  910. {
  911. return FALSE;
  912. }
  913. //
  914. // Open the sub key under HKCU
  915. //
  916. dwRes = RegCreateKeyExU(HKEY_CURRENT_USER,
  917. pszSubKey,
  918. 0,
  919. TEXT(""),
  920. REG_OPTION_NON_VOLATILE,
  921. KEY_SET_VALUE,
  922. NULL,
  923. &hKeyCm,
  924. &dwDisposition);
  925. //
  926. // If we opened the key successfully, write the value
  927. //
  928. if (ERROR_SUCCESS == dwRes)
  929. {
  930. dwRes = RegSetValueExU(hKeyCm,
  931. TranslateUserDataID(uiDataID),
  932. NULL,
  933. dwType,
  934. lpData,
  935. cbData);
  936. #ifdef DEBUG
  937. if (ERROR_SUCCESS == dwRes)
  938. {
  939. CMTRACE1(TEXT("WriteDataToReg() - %s written to registry"), TranslateUserDataID(uiDataID));
  940. }
  941. #endif
  942. RegCloseKey(hKeyCm);
  943. }
  944. CmFree(pszSubKey);
  945. return (ERROR_SUCCESS == dwRes);
  946. }
  947. //+----------------------------------------------------------------------------
  948. //
  949. // Function: DeleteDataFromReg
  950. //
  951. // Synopsis: Deletes the specified value under the specified by uiDataID
  952. //
  953. // Arguments: LPCTSTR pszKey - The key name (service name)
  954. // UINT uiDataID - The resource ID, used to name the value
  955. // BOOL fAllUser - Flag indicating that profile is All-User
  956. //
  957. // Returns: BOOL - TRUE on success, otherwise FALSE
  958. //
  959. // History: nickball Created 5/21/98
  960. //
  961. //+----------------------------------------------------------------------------
  962. BOOL DeleteDataFromReg(
  963. LPCTSTR pszKey,
  964. UINT uiDataID,
  965. BOOL fAllUser)
  966. {
  967. MYDBGASSERT(pszKey && *pszKey);
  968. HKEY hKeyCm;
  969. DWORD dwRes = 1;
  970. LPTSTR pszSubKey;
  971. if (NULL == pszKey || !*pszKey)
  972. {
  973. return FALSE;
  974. }
  975. //
  976. // Per-user data is always stored under HKEY_CURRENT_USER
  977. // Build the sub key to be opened.
  978. //
  979. pszSubKey = BuildUserInfoSubKey(pszKey, fAllUser);
  980. if (NULL == pszSubKey)
  981. {
  982. return FALSE;
  983. }
  984. //
  985. // Open the sub key under HKCU
  986. //
  987. dwRes = RegOpenKeyExU(HKEY_CURRENT_USER,
  988. pszSubKey,
  989. 0,
  990. KEY_SET_VALUE,
  991. &hKeyCm);
  992. //
  993. // If we opened the key successfully, delete the value
  994. //
  995. if (ERROR_SUCCESS == dwRes)
  996. {
  997. dwRes = RegDeleteValueU(hKeyCm, TranslateUserDataID(uiDataID));
  998. //
  999. // Delete the key used for encrypting the passwords
  1000. //
  1001. if (UD_ID_PASSWORD == uiDataID)
  1002. {
  1003. dwRes = RegDeleteValueU(hKeyCm, c_pszCmRegKeyEncryptedPasswordKey);
  1004. }
  1005. if (UD_ID_INET_PASSWORD == uiDataID)
  1006. {
  1007. dwRes = RegDeleteValueU(hKeyCm, c_pszCmRegKeyEncryptedInternetPasswordKey);
  1008. }
  1009. #ifdef DEBUG
  1010. if (ERROR_SUCCESS == dwRes)
  1011. {
  1012. CMTRACE1(TEXT("DeleteDataFromReg() - %s removed from registry"), TranslateUserDataID(uiDataID));
  1013. }
  1014. #endif
  1015. RegCloseKey(hKeyCm);
  1016. }
  1017. CmFree(pszSubKey);
  1018. return (ERROR_SUCCESS == dwRes);
  1019. }
  1020. //+----------------------------------------------------------------------------
  1021. //
  1022. // Function: GetDataFromReg
  1023. //
  1024. // Synopsis: Allocates a buffer for and retrieves the specifed data from the
  1025. // registry.
  1026. //
  1027. // Arguments: LPCTSTR pszKey - The key name (service name)
  1028. // UINT uiDataID - The resource ID, used to name the value
  1029. // DWORD dwType - The registry data type
  1030. // DWORD dwSize - Numbrt of bytes in the data buffer
  1031. // BOOL fAllUser - Flag indicating that profile is All-User
  1032. //
  1033. // Returns: LPBYTE - Ptr to retrieved data, NULL on error
  1034. //
  1035. // History: nickball Created 5/21/98
  1036. //
  1037. //+----------------------------------------------------------------------------
  1038. LPBYTE GetDataFromReg(
  1039. LPCTSTR pszKey,
  1040. UINT uiDataID,
  1041. DWORD dwType,
  1042. DWORD dwSize,
  1043. BOOL fAllUser)
  1044. {
  1045. MYDBGASSERT(pszKey);
  1046. DWORD dwSizeTmp = dwSize;
  1047. DWORD dwTypeTmp = dwType;
  1048. if (NULL == pszKey || !*pszKey)
  1049. {
  1050. return NULL;
  1051. }
  1052. //
  1053. // Allocate a buffer of the desired size
  1054. //
  1055. LPBYTE lpData = (BYTE *) CmMalloc(dwSize);
  1056. if (NULL == lpData)
  1057. {
  1058. return FALSE;
  1059. }
  1060. //
  1061. // Read the data from the registry
  1062. //
  1063. if (!ReadDataFromReg(pszKey, uiDataID, &dwTypeTmp, lpData, &dwSizeTmp, fAllUser))
  1064. {
  1065. CmFree(lpData);
  1066. lpData = NULL;
  1067. }
  1068. return lpData;
  1069. }
  1070. //+---------------------------------------------------------------------------
  1071. //
  1072. // Function: ReadUserInfoFromReg
  1073. //
  1074. // Synopsis: Read the specified userinfo data from the registry.
  1075. //
  1076. // Arguments: pArgs ptr to ArgsStruct
  1077. // uiDataID the resource ID associated with the data
  1078. // ppvData ptr to ptr to be allocated and filled
  1079. //
  1080. // Returns: BOOL TRUE = success, FALSE = failure
  1081. //
  1082. //----------------------------------------------------------------------------
  1083. BOOL ReadUserInfoFromReg(
  1084. ArgsStruct *pArgs,
  1085. UINT uiDataID,
  1086. PVOID *ppvData)
  1087. {
  1088. MYDBGASSERT(pArgs);
  1089. MYDBGASSERT(ppvData);
  1090. BYTE *lpData = NULL;
  1091. if (NULL == pArgs || NULL == ppvData)
  1092. {
  1093. return FALSE;
  1094. }
  1095. //
  1096. // Set size and type as appropriate
  1097. //
  1098. switch (uiDataID)
  1099. {
  1100. case UD_ID_USERNAME:
  1101. case UD_ID_INET_USERNAME:
  1102. case UD_ID_DOMAIN:
  1103. case UD_ID_CURRENTACCESSPOINT:
  1104. {
  1105. lpData = GetDataFromReg(pArgs->szServiceName, uiDataID, REG_SZ, (UNLEN + 1) * sizeof(TCHAR), pArgs->fAllUser);
  1106. if (lpData)
  1107. {
  1108. *ppvData = lpData;
  1109. }
  1110. break;
  1111. }
  1112. case UD_ID_PASSWORD:
  1113. case UD_ID_INET_PASSWORD:
  1114. {
  1115. BYTE *lpTmp = NULL;
  1116. //
  1117. // Get the encryption type
  1118. //
  1119. lpData = GetDataFromReg(pArgs->szServiceName, UD_ID_PCS, REG_DWORD, sizeof(DWORD), pArgs->fAllUser);
  1120. if (!lpData)
  1121. {
  1122. return FALSE;
  1123. }
  1124. //
  1125. // Since we know the return value in this case is a DWORD, then cast it to DWORD pointer
  1126. // and get the value
  1127. //
  1128. DWORD dwCrypt = *((DWORD*)lpData);
  1129. CmFree(lpData);
  1130. //
  1131. // Now retrieve the encrypted password
  1132. //
  1133. lpData = GetDataFromReg(pArgs->szServiceName, uiDataID, REG_BINARY, CM_MAX_PWD, pArgs->fAllUser);
  1134. if (!lpData)
  1135. {
  1136. return FALSE;
  1137. }
  1138. //
  1139. // Decrypt it
  1140. //
  1141. DWORD dwSize = lstrlenU((LPTSTR)lpData)*sizeof(TCHAR);
  1142. //
  1143. // Crypt routines only know about Ansi PCS values, so convert as necessary
  1144. //
  1145. LPTSTR pszSubKey = BuildUserInfoSubKey(pArgs->szServiceName, pArgs->fAllUser);
  1146. LPSTR pszAnsiSubKey = WzToSzWithAlloc(pszSubKey);
  1147. if (UD_ID_INET_PASSWORD == uiDataID)
  1148. {
  1149. dwCrypt |= CMSECURE_ET_USE_SECOND_RND_KEY;
  1150. }
  1151. lpTmp = DecryptPassword(pArgs, (LPBYTE)lpData, UnicodeToAnsiPcs(dwCrypt), dwSize, TRUE, pszAnsiSubKey);
  1152. //
  1153. // Free the buffer for the reg query
  1154. //
  1155. CmFree(lpData);
  1156. //
  1157. // We're Unicode now, so if the password was encrypted
  1158. // as an Ansi string convert the data to a UNICODE string.
  1159. // Otherwise, just update the supplied buffer.
  1160. //
  1161. if (IsAnsiPcs(dwCrypt) && lpTmp)
  1162. {
  1163. *ppvData = SzToWzWithAlloc((LPSTR)lpTmp);
  1164. CmFree(lpTmp);
  1165. }
  1166. else
  1167. {
  1168. *ppvData = lpTmp;
  1169. }
  1170. //
  1171. // Assign lpData for return purposes
  1172. //
  1173. lpData = (BYTE*) *ppvData; // NULL on failure
  1174. CmFree(pszSubKey);
  1175. CmFree(pszAnsiSubKey);
  1176. break;
  1177. }
  1178. case UD_ID_NOPROMPT:
  1179. case UD_ID_REMEMBER_PWD:
  1180. case UD_ID_REMEMBER_INET_PASSWORD:
  1181. case UD_ID_ACCESSPOINTENABLED:
  1182. {
  1183. lpData = GetDataFromReg(pArgs->szServiceName, uiDataID, REG_DWORD, sizeof(DWORD), pArgs->fAllUser);
  1184. if (lpData)
  1185. {
  1186. //
  1187. // Translate to DWORD pointer and check the value
  1188. //
  1189. if (*((DWORD*)lpData))
  1190. {
  1191. *(BOOL *)*ppvData = TRUE;
  1192. }
  1193. else
  1194. {
  1195. *(BOOL *)*ppvData = FALSE;
  1196. }
  1197. CmFree(lpData);
  1198. }
  1199. break;
  1200. }
  1201. default:
  1202. MYDBGASSERT(FALSE);
  1203. return FALSE;
  1204. }
  1205. return (NULL != lpData);
  1206. }
  1207. //+----------------------------------------------------------------------------
  1208. //
  1209. // Function: ReadDataFromReg
  1210. //
  1211. // Synopsis: Retrieves the data from the specifed value under the
  1212. // specified key under the userinfo root.
  1213. //
  1214. // Arguments: LPCTSTR pszKey - The key name (service name)
  1215. // UINT uiDataID - The resource ID, used to name the value
  1216. // LPDWORD lpdwType - The registry data type expected, and returned
  1217. // CONST BYTE *lpData - Ptr to buffer for data
  1218. // LPDWORD lpcbData - The size of the data buffer
  1219. // BOOL fAllUser - Flag indicating that profile is All-User
  1220. //
  1221. // Returns: BOOL - TRUE on success, otherwise FALSE
  1222. //
  1223. // History: nickball Created 5/21/98
  1224. //
  1225. //+----------------------------------------------------------------------------
  1226. BOOL ReadDataFromReg(
  1227. LPCTSTR pszKey,
  1228. UINT uiDataID,
  1229. LPDWORD lpdwType,
  1230. BYTE *lpData,
  1231. LPDWORD lpcbData,
  1232. BOOL fAllUser)
  1233. {
  1234. MYDBGASSERT(pszKey && *pszKey);
  1235. MYDBGASSERT(lpData);
  1236. MYDBGASSERT(lpcbData);
  1237. MYDBGASSERT(lpdwType);
  1238. HKEY hKeyCm;
  1239. DWORD dwRes = 1;
  1240. DWORD dwTypeTmp; // the value returned by query
  1241. LPTSTR pszSubKey;
  1242. if (NULL == pszKey || !*pszKey || NULL == lpData)
  1243. {
  1244. return FALSE;
  1245. }
  1246. //
  1247. // Per-user data is always stored under HKEY_CURRENT_USER
  1248. // Build the sub key to be opened.
  1249. //
  1250. pszSubKey = BuildUserInfoSubKey(pszKey, fAllUser);
  1251. if (NULL == pszSubKey)
  1252. {
  1253. return FALSE;
  1254. }
  1255. //
  1256. // Open the sub key under HKCU
  1257. //
  1258. dwRes = RegOpenKeyExU(HKEY_CURRENT_USER,
  1259. pszSubKey,
  1260. 0,
  1261. KEY_QUERY_VALUE,
  1262. &hKeyCm);
  1263. //
  1264. // If we opened the key successfully, retrieve the value
  1265. //
  1266. if (ERROR_SUCCESS == dwRes)
  1267. {
  1268. dwRes = RegQueryValueExU(hKeyCm,
  1269. TranslateUserDataID(uiDataID),
  1270. NULL,
  1271. &dwTypeTmp,
  1272. lpData,
  1273. lpcbData);
  1274. if (ERROR_SUCCESS == dwRes)
  1275. {
  1276. CMTRACE1(TEXT("ReadDataFromReg() - %s read from registry"), TranslateUserDataID(uiDataID));
  1277. MYDBGASSERT(*lpdwType == dwTypeTmp);
  1278. if (*lpdwType == dwTypeTmp)
  1279. {
  1280. *lpdwType = dwTypeTmp;
  1281. }
  1282. }
  1283. RegCloseKey(hKeyCm);
  1284. }
  1285. CmFree(pszSubKey);
  1286. return (ERROR_SUCCESS == dwRes && (*lpdwType == dwTypeTmp)); // sanity check that type was expected
  1287. }
  1288. //+---------------------------------------------------------------------------
  1289. //
  1290. // Function: DeleteUserInfoFromReg
  1291. //
  1292. // Synopsis: Delete userinfo data from registry
  1293. //
  1294. // Arguments: pArgs ptr to ArgsStruct
  1295. // uiEntry cmp field entry id
  1296. //
  1297. // Returns: BOOL TRUE = success, FALSE = failure
  1298. //
  1299. //----------------------------------------------------------------------------
  1300. BOOL DeleteUserInfoFromReg(
  1301. ArgsStruct *pArgs,
  1302. UINT uiEntry
  1303. )
  1304. {
  1305. return DeleteDataFromReg(pArgs->szServiceName, uiEntry, pArgs->fAllUser);
  1306. }
  1307. //+---------------------------------------------------------------------------
  1308. //
  1309. // Function: DeleteUserInfoFromRas
  1310. //
  1311. // Synopsis: Delete userinfo data from the RAS credential cache
  1312. //
  1313. // Arguments: pArgs ptr to ArgsStruct
  1314. // uiEntry cmp field entry id
  1315. //
  1316. // Returns: int TRUE = success, FALSE = failure, -1 if RAS doesn't
  1317. // store this info
  1318. //
  1319. //----------------------------------------------------------------------------
  1320. int DeleteUserInfoFromRas(
  1321. ArgsStruct *pArgs,
  1322. UINT uiEntry
  1323. )
  1324. {
  1325. LPTSTR pszEmpty = TEXT("");
  1326. return WriteUserInfoToRas(pArgs, uiEntry, pszEmpty);
  1327. }
  1328. //+---------------------------------------------------------------------------
  1329. //
  1330. // Function: ReadPasswordFromCmp
  1331. //
  1332. // Synopsis: Read a null terminated password string from Cmp.
  1333. //
  1334. // Arguments: pArgs ptr to ArgsStruct
  1335. // uiEntry cmp entry name
  1336. // ppszPassword ptr to ptr of the password buffer.
  1337. //
  1338. // Returns: BOOL TRUE = success, FALSE = failure
  1339. //
  1340. //----------------------------------------------------------------------------
  1341. BOOL ReadPasswordFromCmp(
  1342. ArgsStruct *pArgs,
  1343. UINT uiEntry,
  1344. LPTSTR *ppszPassword
  1345. )
  1346. {
  1347. MYDBGASSERT(pArgs);
  1348. MYDBGASSERT(ppszPassword);
  1349. if (NULL == pArgs || NULL == ppszPassword)
  1350. {
  1351. return FALSE;
  1352. }
  1353. //
  1354. // Read in password from profile
  1355. //
  1356. BOOL fOk = FALSE;
  1357. LPTSTR pszEncryptedData = pArgs->piniProfile->GPPS(c_pszCmSection, TranslateUserDataID(uiEntry));
  1358. if (*pszEncryptedData)
  1359. {
  1360. //
  1361. // Trim away all the spaces at both ends
  1362. //
  1363. CmStrTrim(pszEncryptedData);
  1364. //
  1365. // Get the type and decrypt
  1366. //
  1367. DWORD dwEncryptionType = (DWORD)pArgs->piniProfile->GPPI(c_pszCmSection,
  1368. c_pszCmEntryPcs,
  1369. CMSECURE_ET_RC2); // default
  1370. //
  1371. // Since this was saved in the CMP in Ansi form, we need to convert the characters back to
  1372. // Ansi form so that we can decrypt them. We still may not be able to (if we cannot
  1373. // round trip the Unicode conversion for instance) but then we will fail and display a
  1374. // blank password. Not the end of the world but hopefully avoidable.
  1375. //
  1376. LPSTR pszAnsiEncryptedData;
  1377. LPSTR pszAnsiUnEncryptedData;
  1378. pszAnsiEncryptedData = WzToSzWithAlloc(pszEncryptedData);
  1379. if (NULL != pszAnsiEncryptedData)
  1380. {
  1381. DWORD dwSize = lstrlenA(pszAnsiEncryptedData)*sizeof(TCHAR);
  1382. //
  1383. // Here we don't need to differentiate between main password and internet password
  1384. // because we are reading this from a file and the mask is used when reading to/from
  1385. // registry.
  1386. //
  1387. pszAnsiUnEncryptedData = (LPSTR)DecryptPassword(pArgs,
  1388. (LPBYTE)pszAnsiEncryptedData,
  1389. dwEncryptionType,
  1390. dwSize,
  1391. FALSE,
  1392. NULL);
  1393. if (pszAnsiUnEncryptedData)
  1394. {
  1395. *ppszPassword = SzToWzWithAlloc(pszAnsiUnEncryptedData);
  1396. if (NULL != *ppszPassword)
  1397. {
  1398. fOk = ((BOOL)**ppszPassword);
  1399. }
  1400. CmWipePasswordA(pszAnsiUnEncryptedData);
  1401. CmFree(pszAnsiUnEncryptedData);
  1402. }
  1403. }
  1404. CmFree(pszAnsiEncryptedData);
  1405. }
  1406. CmFree(pszEncryptedData);
  1407. return fOk;
  1408. }
  1409. //+---------------------------------------------------------------------------
  1410. //
  1411. // Function: ReadUserInfoFromCmp
  1412. //
  1413. // Synopsis: Read a userinfo data from cmp.
  1414. //
  1415. // Arguments: pArgs ptr to ArgsStruct
  1416. // uiEntry the cmp file entry
  1417. // ppvData ptr to ptr to the data buffer. If the userinfo
  1418. // is multiple byte(e.g. password), the func allocs
  1419. // the buffer.
  1420. //
  1421. // Returns: BOOL TRUE = success, FALSE = failure
  1422. //
  1423. //----------------------------------------------------------------------------
  1424. BOOL ReadUserInfoFromCmp(
  1425. ArgsStruct *pArgs,
  1426. UINT uiEntry,
  1427. PVOID *ppvData
  1428. )
  1429. {
  1430. switch (uiEntry)
  1431. {
  1432. case UD_ID_USERNAME:
  1433. case UD_ID_INET_USERNAME:
  1434. case UD_ID_DOMAIN:
  1435. *ppvData = (PVOID)pArgs->piniProfile->GPPS(c_pszCmSection, TranslateUserDataID(uiEntry));
  1436. break;
  1437. case UD_ID_PASSWORD:
  1438. case UD_ID_INET_PASSWORD:
  1439. return ReadPasswordFromCmp(pArgs, uiEntry, (LPTSTR *)ppvData);
  1440. break;
  1441. case UD_ID_NOPROMPT:
  1442. case UD_ID_REMEMBER_PWD:
  1443. case UD_ID_REMEMBER_INET_PASSWORD:
  1444. *(BOOL *)(*ppvData) = pArgs->piniProfile->GPPB(c_pszCmSection, TranslateUserDataID(uiEntry));
  1445. break;
  1446. //
  1447. // None of these should be in the CMP by this point. Return a failure value.
  1448. //
  1449. case UD_ID_PCS:
  1450. case UD_ID_ACCESSPOINTENABLED:
  1451. case UD_ID_CURRENTACCESSPOINT: // if we are trying to read the access point
  1452. CMASSERTMSG(FALSE, TEXT("ReadUserInfoFromCmp -- trying to read a value that should never be in the cmp, why?"));
  1453. *ppvData = NULL;
  1454. return FALSE;
  1455. break;
  1456. default:
  1457. MYDBGASSERT(0);
  1458. break;
  1459. }
  1460. return TRUE;
  1461. }
  1462. //+---------------------------------------------------------------------------
  1463. //
  1464. // Function: DeleteUserInfoFromCmp
  1465. //
  1466. // Synopsis: Deletes userinfo data from cmp.
  1467. //
  1468. // Arguments: pArgs ptr to ArgsStruct
  1469. // uiEntry the cmp file entry
  1470. //
  1471. // Returns: BOOL TRUE = success, FALSE = failure
  1472. //
  1473. //----------------------------------------------------------------------------
  1474. BOOL DeleteUserInfoFromCmp(
  1475. ArgsStruct *pArgs,
  1476. UINT uiEntry
  1477. )
  1478. {
  1479. BOOL bReturn = FALSE;
  1480. UINT uiKeepDefCreds = 0;
  1481. const TCHAR* const c_pszKeepDefaultCredentials = TEXT("KeepDefaultCredentials");
  1482. if (NULL == pArgs)
  1483. {
  1484. return bReturn;
  1485. }
  1486. switch (uiEntry)
  1487. {
  1488. case UD_ID_USERNAME:
  1489. case UD_ID_DOMAIN:
  1490. case UD_ID_INET_USERNAME:
  1491. case UD_ID_NOPROMPT:
  1492. case UD_ID_REMEMBER_PWD:
  1493. case UD_ID_REMEMBER_INET_PASSWORD:
  1494. case UD_ID_PASSWORD:
  1495. case UD_ID_INET_PASSWORD:
  1496. //
  1497. // Get KeepDefaultCredentials value from CMP
  1498. //
  1499. uiKeepDefCreds = GetPrivateProfileIntU(c_pszCmSection, c_pszKeepDefaultCredentials, 0,
  1500. pArgs->piniProfile->GetFile());
  1501. if (0 == uiKeepDefCreds)
  1502. {
  1503. if (WritePrivateProfileStringU(c_pszCmSection, TranslateUserDataID(uiEntry),
  1504. NULL, pArgs->piniProfile->GetFile()))
  1505. {
  1506. bReturn = TRUE;
  1507. }
  1508. }
  1509. break;
  1510. default:
  1511. MYDBGASSERT(0);
  1512. break;
  1513. }
  1514. return bReturn;
  1515. }
  1516. //+---------------------------------------------------------------------------
  1517. //
  1518. // Function: RasGetCredsWrapper
  1519. //
  1520. // Synopsis: Wrapper function to call RasGetCredentials. The function
  1521. // calls RasGetCredentials and then copies the appropriate data
  1522. // from the RASCREDENTIALS struct into the buffer pointed to by
  1523. // *ppvData (allocated on the caller behalf). Note that the value
  1524. // set in dwMask determines which data item is retrieved from the
  1525. // credentials cache. Currently, dwMask must be one of RASCM_UserName,
  1526. // RASCM_Domain, or RASCM_Password.
  1527. //
  1528. // Arguments: pArgs ptr to ArgsStruct
  1529. // pszPhoneBook full path to the phonebook file to get the
  1530. // data from, or NULL to use the all user default pbk
  1531. // dwMask dwMask value for the RASCREDENTIALS struct
  1532. // ppvData ptr to ptr to the data buffer. If the userinfo
  1533. // is multiple byte(e.g. password), the func allocs
  1534. // the buffer.
  1535. //
  1536. // Returns: DWORD ERROR_SUCCESS on success, winerror on failure
  1537. //
  1538. //----------------------------------------------------------------------------
  1539. DWORD RasGetCredsWrapper(
  1540. ArgsStruct *pArgs,
  1541. LPCTSTR pszPhoneBook,
  1542. DWORD dwMask,
  1543. PVOID *ppvData
  1544. )
  1545. {
  1546. DWORD dwRet = ERROR_INVALID_PARAMETER;
  1547. MYDBGASSERT(pArgs && pArgs->rlsRasLink.pfnGetCredentials);
  1548. MYDBGASSERT(ppvData);
  1549. MYDBGASSERT((RASCM_UserName == dwMask) || (RASCM_Domain == dwMask) || (RASCM_Password == dwMask));
  1550. if (pArgs && ppvData && pArgs->rlsRasLink.pfnGetCredentials)
  1551. {
  1552. LPTSTR pszConnectoid = GetRasConnectoidName(pArgs, pArgs->piniService, FALSE);
  1553. if (pszConnectoid)
  1554. {
  1555. RASCREDENTIALS RasCredentials = {0};
  1556. RasCredentials.dwSize = sizeof(RasCredentials);
  1557. if (CM_CREDS_GLOBAL == pArgs->dwCurrentCredentialType)
  1558. {
  1559. RasCredentials.dwMask = dwMask | RASCM_DefaultCreds;
  1560. }
  1561. else
  1562. {
  1563. RasCredentials.dwMask = dwMask;
  1564. }
  1565. dwRet = pArgs->rlsRasLink.pfnGetCredentials(pszPhoneBook, pszConnectoid, &RasCredentials);
  1566. if (ERROR_SUCCESS == dwRet)
  1567. {
  1568. LPTSTR pszData = NULL;
  1569. if (RASCM_UserName == dwMask)
  1570. {
  1571. pszData = RasCredentials.szUserName;
  1572. }
  1573. else if (RASCM_Domain == dwMask)
  1574. {
  1575. pszData = RasCredentials.szDomain;
  1576. }
  1577. else if (RASCM_Password == dwMask)
  1578. {
  1579. pszData = RasCredentials.szPassword;
  1580. }
  1581. LPTSTR pszReturn = CmStrCpyAlloc(pszData);
  1582. if (NULL == pszReturn)
  1583. {
  1584. dwRet = ERROR_NOT_ENOUGH_MEMORY;
  1585. }
  1586. else
  1587. {
  1588. *ppvData = pszReturn;
  1589. }
  1590. }
  1591. CmWipePassword(RasCredentials.szPassword);
  1592. CmFree(pszConnectoid);
  1593. }
  1594. }
  1595. return dwRet;
  1596. }
  1597. //+---------------------------------------------------------------------------
  1598. //
  1599. // Function: ReadUserInfoFromRas
  1600. //
  1601. // Synopsis: Read userinfo data from the RAS credentials cache
  1602. //
  1603. // Arguments: pArgs ptr to ArgsStruct
  1604. // uiEntry the cmp file entry
  1605. // ppvData ptr to ptr to the data buffer. If the userinfo
  1606. // is multiple byte(e.g. password), the func allocs
  1607. // the buffer.
  1608. //
  1609. // Returns: BOOL TRUE = success, FALSE = failure
  1610. //
  1611. //----------------------------------------------------------------------------
  1612. BOOL ReadUserInfoFromRas(
  1613. ArgsStruct *pArgs,
  1614. UINT uiEntry,
  1615. PVOID *ppvData
  1616. )
  1617. {
  1618. BOOL bReturn = FALSE;
  1619. if (OS_NT5 && pArgs && pArgs->bUseRasCredStore)
  1620. {
  1621. DWORD dwMask;
  1622. LPTSTR pszPhoneBook = NULL;
  1623. switch (uiEntry)
  1624. {
  1625. case UD_ID_USERNAME:
  1626. dwMask = RASCM_UserName;
  1627. bReturn = (ERROR_SUCCESS == RasGetCredsWrapper(pArgs, pArgs->pszRasPbk, dwMask, ppvData));
  1628. break;
  1629. case UD_ID_PASSWORD:
  1630. dwMask = RASCM_Password;
  1631. bReturn = (ERROR_SUCCESS == RasGetCredsWrapper(pArgs, pArgs->pszRasPbk, dwMask, ppvData));
  1632. break;
  1633. case UD_ID_DOMAIN:
  1634. dwMask = RASCM_Domain;
  1635. bReturn = (ERROR_SUCCESS == RasGetCredsWrapper(pArgs, pArgs->pszRasPbk, dwMask, ppvData));
  1636. break;
  1637. case UD_ID_INET_PASSWORD:
  1638. dwMask = RASCM_Password;
  1639. pszPhoneBook = CreateRasPrivatePbk(pArgs);
  1640. if (pszPhoneBook)
  1641. {
  1642. bReturn = (ERROR_SUCCESS == RasGetCredsWrapper(pArgs, pszPhoneBook, dwMask, ppvData));
  1643. CmFree(pszPhoneBook);
  1644. }
  1645. break;
  1646. case UD_ID_INET_USERNAME:
  1647. dwMask = RASCM_UserName;
  1648. pszPhoneBook = CreateRasPrivatePbk(pArgs);
  1649. if (pszPhoneBook)
  1650. {
  1651. bReturn = (ERROR_SUCCESS == RasGetCredsWrapper(pArgs, pszPhoneBook, dwMask, ppvData));
  1652. CmFree(pszPhoneBook);
  1653. }
  1654. break;
  1655. }
  1656. }
  1657. if (bReturn)
  1658. {
  1659. if (CM_CREDS_GLOBAL == pArgs->dwCurrentCredentialType)
  1660. {
  1661. CMTRACE1(TEXT("ReadUserInfoFromRas() - %s retrieved from the Global RAS Credential store"), TranslateUserDataID(uiEntry));
  1662. }
  1663. else
  1664. {
  1665. CMTRACE1(TEXT("ReadUserInfoFromRas() - %s retrieved from the User RAS Credential store"), TranslateUserDataID(uiEntry));
  1666. }
  1667. }
  1668. return bReturn;
  1669. }
  1670. //+---------------------------------------------------------------------------
  1671. //
  1672. // Function: GetUserInfo
  1673. //
  1674. // Synopsis: Get an userinfo. The user info can reside in either the
  1675. // cache, cmp, or registry. This functions hides this from the
  1676. // user.
  1677. //
  1678. // We first try the cmp file. If that fails, we try the cache.
  1679. // We'll get the following user info:
  1680. // username,
  1681. // password,
  1682. // domain,
  1683. // remember main passwd,
  1684. // dial automatically,
  1685. // inet username,
  1686. // inet passwd
  1687. // remember inet password
  1688. // inet use same user name
  1689. //
  1690. // Arguments: pArgs ptr to ArgsStruct
  1691. // uiEntry the cmp file entry
  1692. // pvData ptr to ptr to the data buffer. If the userinfo
  1693. // is multiple byte(e.g. password), the func allocs
  1694. // the buffer.
  1695. //
  1696. // Returns: BOOL TRUE = success, FALSE = failure
  1697. //
  1698. //----------------------------------------------------------------------------
  1699. BOOL GetUserInfo(
  1700. ArgsStruct *pArgs,
  1701. UINT uiEntry,
  1702. PVOID *ppvData
  1703. )
  1704. {
  1705. BOOL bReturn = ReadUserInfoFromRas(pArgs, uiEntry, ppvData);
  1706. if (!bReturn)
  1707. {
  1708. bReturn = ReadUserInfoFromReg(pArgs, uiEntry, ppvData);
  1709. }
  1710. if (!bReturn)
  1711. {
  1712. bReturn = ReadUserInfoFromCmp(pArgs, uiEntry, ppvData);
  1713. }
  1714. return bReturn;
  1715. }
  1716. //+---------------------------------------------------------------------------
  1717. //
  1718. // Function: SaveUserInfo
  1719. //
  1720. // Synopsis: Save an userinfo. The user info can reside in either the
  1721. // RAS cred cache or the registry. This functions abstracts
  1722. // this from the user.
  1723. //
  1724. // We first try the RAS cred cache. If the RAS cred cache doesn't hold that
  1725. // piece of info we then save it in the registry.
  1726. // We'll save the following user info:
  1727. // username,
  1728. // password,
  1729. // domain,
  1730. // remember main passwd,
  1731. // dial automatically,
  1732. // inet username,
  1733. // inet passwd
  1734. // remember inet password
  1735. // inet use same user name
  1736. //
  1737. // Arguments: pArgs ptr to ArgsStruct
  1738. // uiEntry the cmp file entry
  1739. // pvData ptr to the data buffer. If the userinfo is
  1740. // multiple byte(e.g. password), the func allocs
  1741. // the buffer.
  1742. //
  1743. // Returns: BOOL TRUE = success, FALSE = failure
  1744. //
  1745. //----------------------------------------------------------------------------
  1746. BOOL SaveUserInfo(
  1747. ArgsStruct *pArgs,
  1748. UINT uiEntry,
  1749. PVOID pvData
  1750. )
  1751. {
  1752. //
  1753. // Try giving the Data to RAS first. If the function returns
  1754. // -1, then this is data that RAS doesn't hold for us and we will
  1755. // have to put it in the registry instead.
  1756. //
  1757. int iReturn = WriteUserInfoToRas(pArgs, uiEntry, pvData);
  1758. if (-1 == iReturn)
  1759. {
  1760. //
  1761. // Just write the data to the registry. Use CMP only as
  1762. // an upgrade reference for UserInfo data post CM 1.1
  1763. //
  1764. iReturn = WriteUserInfoToReg(pArgs, uiEntry, pvData);
  1765. }
  1766. return iReturn;
  1767. }
  1768. //+---------------------------------------------------------------------------
  1769. //
  1770. // Function: DeleteUserInfo
  1771. //
  1772. // Synopsis: Delete an userinfo. The user info can reside in either the
  1773. // RAS Cred cache or the registry. This functions abstracts
  1774. // this from the user.
  1775. //
  1776. // We first try the RAS cache first. If that piece of info isn't stored
  1777. // in the RAS cache then we try the registry.
  1778. //
  1779. // We'll delete the following user info:
  1780. // username,
  1781. // password,
  1782. // domain,
  1783. // remember main passwd,
  1784. // dial automatically,
  1785. // inet username,
  1786. // inet passwd
  1787. // remember inet password
  1788. // inet use same user name
  1789. //
  1790. // Arguments: pArgs ptr to ArgsStruct
  1791. // uiEntry the cmp file entry
  1792. //
  1793. // Returns: BOOL TRUE = success, FALSE = failure
  1794. //
  1795. //----------------------------------------------------------------------------
  1796. BOOL DeleteUserInfo(
  1797. ArgsStruct *pArgs,
  1798. UINT uiEntry
  1799. )
  1800. {
  1801. int iReturn = DeleteUserInfoFromRas(pArgs, uiEntry);
  1802. if (-1 == iReturn)
  1803. {
  1804. iReturn = DeleteUserInfoFromReg(pArgs, uiEntry);
  1805. }
  1806. return iReturn;
  1807. }
  1808. //+---------------------------------------------------------------------------
  1809. //
  1810. // Function: NeedToUpgradeUserInfo
  1811. //
  1812. // Synopsis: Do we need to upgrade the cm 1.0/1.1 userinfo to the cm 1.2 format?
  1813. //
  1814. // Arguments: pArgs - Ptr to global args struct
  1815. //
  1816. // Returns: BOOL TRUE = success, FALSE = failure
  1817. //
  1818. //----------------------------------------------------------------------------
  1819. int NeedToUpgradeUserInfo(
  1820. ArgsStruct *pArgs)
  1821. {
  1822. MYDBGASSERT(pArgs);
  1823. DWORD dwRes;
  1824. HKEY hKeyCm;
  1825. LPTSTR pszSubKey;
  1826. int iReturn = c_iNoUpgradeRequired;
  1827. if (pArgs)
  1828. {
  1829. //
  1830. // If this is NT5 or greater, we want to be storing our credentials with RAS
  1831. // instead of the registry.
  1832. //
  1833. // If this isn't NT5 we still want to upgrade the user to using the registry as
  1834. // storage instead of the cmp if they haven't already
  1835. // been upgraded. Thus the simple test is to open the service name key in HKCU.
  1836. // This key will exist, if the user has already run 1.2 bits.
  1837. //
  1838. pszSubKey = BuildUserInfoSubKey(pArgs->szServiceName, pArgs->fAllUser);
  1839. dwRes = RegOpenKeyExU(HKEY_CURRENT_USER,
  1840. pszSubKey,
  1841. 0,
  1842. KEY_QUERY_VALUE,
  1843. &hKeyCm);
  1844. if (ERROR_SUCCESS == dwRes)
  1845. {
  1846. //
  1847. // Then we have the registry method, unless we are supposed to be using the RAS
  1848. // cred store we are done. If we are supposed to be using the RAS cred store
  1849. // we need to check to make sure that we are using it. Note we could have a problem
  1850. // here if the user has registry cred data and then their registry gets write protected.
  1851. // This would allow us to read from it but not delete the old data. Thus the user
  1852. // would never be able to save any changes because we would always think they needed
  1853. // to upgrade. An unlikely scenario but possible ...
  1854. //
  1855. if (pArgs->bUseRasCredStore)
  1856. {
  1857. LPTSTR pszUserName = NULL;
  1858. BOOL bRet = ReadUserInfoFromReg(pArgs, UD_ID_USERNAME, (PVOID*)&pszUserName);
  1859. if (bRet && (NULL != pszUserName) && (TEXT('\0') != pszUserName[0]))
  1860. {
  1861. //
  1862. // Then we have the username in the registry. Lets upgrade to the RAS
  1863. // credential store.
  1864. //
  1865. iReturn = c_iUpgradeFromRegToRas;
  1866. }
  1867. CmFree(pszUserName);
  1868. }
  1869. RegCloseKey(hKeyCm);
  1870. }
  1871. else
  1872. {
  1873. iReturn = c_iUpgradeFromCmp;
  1874. }
  1875. CmFree(pszSubKey);
  1876. }
  1877. else
  1878. {
  1879. CMASSERTMSG(FALSE, TEXT("NeedToUpgradeUserInfo -- NULL pArgs passed"));
  1880. }
  1881. //
  1882. // We don't want to upgrade if it's ICS. This prevents from adding info to the registry.
  1883. //
  1884. if (CM_LOGON_TYPE_ICS == pArgs->dwWinLogonType)
  1885. {
  1886. iReturn = c_iNoUpgradeRequired;
  1887. }
  1888. return iReturn;
  1889. }
  1890. //+---------------------------------------------------------------------------
  1891. //
  1892. // Function: UpgradeUserInfoFromRegToRasAndReg
  1893. //
  1894. // Synopsis: Upgrade the userinfo from CM 1.2 registry only format to the
  1895. // CM 1.3 format which uses both RAS credential storage and
  1896. // the registry.
  1897. //
  1898. // Arguments: pArgs ptr to ArgsStruct
  1899. //
  1900. // Returns: BOOL TRUE = success, FALSE = failure
  1901. //
  1902. //----------------------------------------------------------------------------
  1903. BOOL UpgradeUserInfoFromRegToRasAndReg(
  1904. ArgsStruct *pArgs
  1905. )
  1906. {
  1907. BOOL bReturn = FALSE;
  1908. if (OS_NT5)
  1909. {
  1910. LPTSTR pszTmp;
  1911. pszTmp = NULL;
  1912. //
  1913. // If we get an empty string "" from ReadUserInfoFromReg we don't want to
  1914. // save the empty string to the RAS Credstore because it might overwrite
  1915. // global credentials information. This can happen if User1 saves global
  1916. // credentials and User2 tries using the same profile. Since User2 is running
  1917. // this profile for the 1st time, he'll run through an upgrade path and if global
  1918. // creds exist we don't want to null them out.
  1919. //
  1920. if (ReadUserInfoFromReg(pArgs, UD_ID_INET_USERNAME, (PVOID*)&pszTmp))
  1921. {
  1922. DeleteUserInfoFromReg(pArgs, UD_ID_INET_USERNAME);
  1923. if (pszTmp && lstrlenU(pszTmp))
  1924. {
  1925. WriteUserInfoToRas(pArgs, UD_ID_INET_USERNAME, pszTmp);
  1926. }
  1927. CmFree(pszTmp);
  1928. }
  1929. pszTmp = NULL;
  1930. if (ReadUserInfoFromReg(pArgs, UD_ID_INET_PASSWORD, (PVOID*)&pszTmp))
  1931. {
  1932. DeleteUserInfoFromReg(pArgs, UD_ID_INET_PASSWORD);
  1933. if (pszTmp && lstrlenU(pszTmp))
  1934. {
  1935. WriteUserInfoToRas(pArgs, UD_ID_INET_PASSWORD, pszTmp);
  1936. }
  1937. CmFree(pszTmp);
  1938. }
  1939. pszTmp = NULL;
  1940. if (ReadUserInfoFromReg(pArgs, UD_ID_USERNAME, (PVOID*)&pszTmp))
  1941. {
  1942. DeleteUserInfoFromReg(pArgs, UD_ID_USERNAME);
  1943. if (pszTmp && lstrlenU(pszTmp))
  1944. {
  1945. WriteUserInfoToRas(pArgs, UD_ID_USERNAME, pszTmp);
  1946. }
  1947. CmFree(pszTmp);
  1948. }
  1949. pszTmp = NULL;
  1950. if (ReadUserInfoFromReg(pArgs, UD_ID_DOMAIN, (PVOID*)&pszTmp))
  1951. {
  1952. DeleteUserInfoFromReg(pArgs, UD_ID_DOMAIN);
  1953. if (pszTmp && lstrlenU(pszTmp))
  1954. {
  1955. WriteUserInfoToRas(pArgs, UD_ID_DOMAIN, pszTmp);
  1956. }
  1957. CmFree(pszTmp);
  1958. }
  1959. pszTmp = NULL;
  1960. if (ReadUserInfoFromReg(pArgs, UD_ID_PASSWORD, (PVOID*)&pszTmp))
  1961. {
  1962. DeleteUserInfoFromReg(pArgs, UD_ID_PASSWORD);
  1963. if (pszTmp && lstrlenU(pszTmp))
  1964. {
  1965. WriteUserInfoToRas(pArgs, UD_ID_PASSWORD, pszTmp);
  1966. }
  1967. CmFree(pszTmp);
  1968. }
  1969. //
  1970. // Now delete the PCS value as it is no longer meaningful
  1971. //
  1972. DeleteUserInfoFromReg(pArgs, UD_ID_PCS);
  1973. }
  1974. else
  1975. {
  1976. MYDBGASSERT(FALSE);
  1977. }
  1978. return bReturn;
  1979. }
  1980. //+---------------------------------------------------------------------------
  1981. //
  1982. // Function: UpgradeUserInfoFromCmp
  1983. //
  1984. // Synopsis: Upgrade the userinfo from cm1.0/1,1 format to 1.3 format.
  1985. //
  1986. // Arguments: pArgs ptr to ArgsStruct
  1987. //
  1988. // Returns: BOOL TRUE = success, FALSE = failure
  1989. //
  1990. //----------------------------------------------------------------------------
  1991. BOOL UpgradeUserInfoFromCmp(
  1992. ArgsStruct *pArgs
  1993. )
  1994. {
  1995. LPTSTR pszTmp;
  1996. BOOL fTmp;
  1997. PVOID pv;
  1998. //
  1999. // First retrieve each of the non-cached data items
  2000. // Then delete username, internetusername, domain, password,
  2001. // internetpassword, remember password, remember internet password
  2002. // and noprompt (dial automatically) from the CMP file.
  2003. // If the KeepDefaultCredentials is set to 1 in the .CMP file then the
  2004. // DeleteUserInfoFromCmp function does not actually delete the values from
  2005. // the file.
  2006. // If we get an empty string "" from ReadUserInfoFromCmp we don't want to
  2007. // save the empty string to the RAS Credstore because it might overwrite
  2008. // global credentials information. This can happen if User1 saves global
  2009. // credentials and User2 tries using the same profile. Since User2 is running
  2010. // this profile for the 1st time, he'll run through an upgrade path and if global
  2011. // creds exist we don't want to null them out.
  2012. //
  2013. pszTmp = NULL;
  2014. ReadUserInfoFromCmp(pArgs, UD_ID_USERNAME, (PVOID*)&pszTmp);
  2015. if (pszTmp && lstrlenU(pszTmp))
  2016. {
  2017. SaveUserInfo(pArgs, UD_ID_USERNAME, pszTmp);
  2018. }
  2019. DeleteUserInfoFromCmp(pArgs, UD_ID_USERNAME);
  2020. CmFree(pszTmp);
  2021. pszTmp = NULL;
  2022. ReadUserInfoFromCmp(pArgs, UD_ID_DOMAIN, (PVOID*)&pszTmp);
  2023. if (pszTmp && lstrlenU(pszTmp))
  2024. {
  2025. SaveUserInfo(pArgs, UD_ID_DOMAIN, pszTmp);
  2026. }
  2027. DeleteUserInfoFromCmp(pArgs, UD_ID_DOMAIN);
  2028. CmFree(pszTmp);
  2029. pszTmp = NULL;
  2030. ReadUserInfoFromCmp(pArgs, UD_ID_INET_USERNAME, (PVOID*)&pszTmp);
  2031. if (pszTmp && lstrlenU(pszTmp))
  2032. {
  2033. SaveUserInfo(pArgs, UD_ID_INET_USERNAME, pszTmp);
  2034. }
  2035. DeleteUserInfoFromCmp(pArgs, UD_ID_INET_USERNAME);
  2036. CmFree(pszTmp);
  2037. pv = &fTmp;
  2038. ReadUserInfoFromCmp(pArgs, UD_ID_NOPROMPT, &pv);
  2039. SaveUserInfo(pArgs, UD_ID_NOPROMPT, pv);
  2040. DeleteUserInfoFromCmp(pArgs, UD_ID_NOPROMPT);
  2041. pv = &fTmp;
  2042. ReadUserInfoFromCmp(pArgs, UD_ID_REMEMBER_PWD, &pv);
  2043. SaveUserInfo(pArgs, UD_ID_REMEMBER_PWD, pv);
  2044. DeleteUserInfoFromCmp(pArgs, UD_ID_REMEMBER_PWD);
  2045. pv = &fTmp;
  2046. ReadUserInfoFromCmp(pArgs, UD_ID_REMEMBER_INET_PASSWORD, &pv);
  2047. SaveUserInfo(pArgs, UD_ID_REMEMBER_INET_PASSWORD, pv);
  2048. DeleteUserInfoFromCmp(pArgs, UD_ID_REMEMBER_INET_PASSWORD);
  2049. //
  2050. // Construct old cache entry name
  2051. //
  2052. LPTSTR pszCacheEntryName = GetLegacyKeyName(pArgs);
  2053. //
  2054. // main passwd
  2055. //
  2056. pszTmp = NULL;
  2057. //
  2058. // To get the passwords, the cm 1.1 logic is that we first try the cmp, then the cache.
  2059. //
  2060. if (ReadUserInfoFromCmp(pArgs, UD_ID_PASSWORD, (PVOID*)&pszTmp))
  2061. {
  2062. if (pszTmp && lstrlenU(pszTmp))
  2063. {
  2064. SaveUserInfo(pArgs, UD_ID_PASSWORD, pszTmp);
  2065. }
  2066. }
  2067. else
  2068. {
  2069. CmFree(pszTmp);
  2070. pszTmp = NULL;
  2071. #ifdef TEST_USERINFO_UPGRADE
  2072. MYVERIFY(WriteStringToCache(pArgs, pszCacheEntryName, TEXT("CM 1.1 main password")));
  2073. #endif
  2074. //
  2075. // Try to read it from cache
  2076. //
  2077. if (ReadStringFromCache(pArgs, pszCacheEntryName, &pszTmp))
  2078. {
  2079. if (pszTmp && lstrlenU(pszTmp))
  2080. {
  2081. if (SaveUserInfo(pArgs, UD_ID_PASSWORD, pszTmp))
  2082. {
  2083. #ifdef TEST_USERINFO_UPGRADE
  2084. MYVERIFY(DeleteStringFromCache(pArgs, pszCacheEntryName));
  2085. #endif
  2086. }
  2087. }
  2088. }
  2089. }
  2090. DeleteUserInfoFromCmp(pArgs, UD_ID_PASSWORD);
  2091. CmFree(pszTmp);
  2092. //
  2093. // inet passwd
  2094. //
  2095. pszTmp = NULL;
  2096. if (ReadUserInfoFromCmp(pArgs, UD_ID_INET_PASSWORD, (PVOID*)&pszTmp))
  2097. {
  2098. if (pszTmp && lstrlenU(pszTmp))
  2099. {
  2100. SaveUserInfo(pArgs, UD_ID_INET_PASSWORD, pszTmp);
  2101. }
  2102. }
  2103. else
  2104. {
  2105. CmFree(pszTmp);
  2106. pszTmp = NULL;
  2107. //
  2108. // Build tunnel entry name and read string from cache
  2109. //
  2110. pszCacheEntryName = CmStrCatAlloc(&pszCacheEntryName, TEXT("-tunnel"));
  2111. #ifdef TEST_USERINFO_UPGRADE
  2112. MYVERIFY(WriteStringToCache(pArgs, pszCacheEntryName, TEXT("CM 1.1 internet password")));
  2113. #endif
  2114. if (ReadStringFromCache(pArgs, pszCacheEntryName, &pszTmp))
  2115. {
  2116. if (pszTmp && lstrlenU(pszTmp))
  2117. {
  2118. if (SaveUserInfo(pArgs, UD_ID_INET_PASSWORD, pszTmp))
  2119. {
  2120. #ifdef TEST_USERINFO_UPGRADE
  2121. MYVERIFY(DeleteStringFromCache(pArgs, pszCacheEntryName));
  2122. #endif
  2123. }
  2124. }
  2125. }
  2126. }
  2127. DeleteUserInfoFromCmp(pArgs, UD_ID_INET_PASSWORD);
  2128. CmFree(pszTmp);
  2129. CmFree(pszCacheEntryName);
  2130. return TRUE; // MarkUserInfoUpgraded(pArgs);
  2131. }
  2132. //+----------------------------------------------------------------------------
  2133. //
  2134. // Function: GetLegacyKeyName
  2135. //
  2136. // Synopsis: Builds the string fragment used to build cache entry name. The "
  2137. // sign-in" prefix is maintained for legacy compatibility
  2138. //
  2139. // Arguments: ArgsStruct *pArgs - Ptr to global args struct
  2140. //
  2141. // Returns: LPTSTR - Ptr to allocated string containing "<service name> - Sign-In"
  2142. //
  2143. // Note: Used exclusively for cache entry name construction
  2144. //
  2145. // History: nickball Created Header 4/16/98
  2146. //
  2147. //+----------------------------------------------------------------------------
  2148. LPTSTR GetLegacyKeyName(ArgsStruct *pArgs)
  2149. {
  2150. MYDBGASSERT(pArgs);
  2151. //
  2152. // Service name is the basis of the key name. We also include
  2153. // IDMSG_TITLESERVICE and append a suffix of " (Connection Manager)"
  2154. //
  2155. LPTSTR pszRes = CmFmtMsg(g_hInst, IDMSG_TITLESERVICE, pArgs->szServiceName);
  2156. MYDBGASSERT(pszRes && *pszRes);
  2157. if (pszRes)
  2158. {
  2159. pszRes = CmStrCatAlloc(&pszRes, c_pszCacheEntryNameSuffix);
  2160. }
  2161. return (pszRes);
  2162. }
  2163. //+----------------------------------------------------------------------------
  2164. //
  2165. // Function: EncryptPassword
  2166. //
  2167. // Synopsis: Wrapper for encrypting password
  2168. //
  2169. // Arguments: ArgsStruct *pArgs - Ptr to global args struct
  2170. // LPCTSTR pszPassword - The password to be encrypted
  2171. // LPDWORD lpdwBufSize - Buffer for size of the encrypted buffer - optional
  2172. // LPDWORD lpdwCryptType - Buffer for crypto type used
  2173. // BOOL fReg - Password is disguised for registry storage
  2174. //
  2175. // Returns: LPTSTR - Ptr to allocated buffer containing encrypted form of password
  2176. //
  2177. // History: nickball Created Header 5/22/98
  2178. //
  2179. //+----------------------------------------------------------------------------
  2180. LPTSTR EncryptPassword(
  2181. ArgsStruct *pArgs,
  2182. LPCTSTR pszPassword,
  2183. LPDWORD lpdwBufSize,
  2184. LPDWORD lpdwCryptType,
  2185. BOOL /*fReg*/,
  2186. LPSTR pszSubKey)
  2187. {
  2188. MYDBGASSERT(pArgs);
  2189. MYDBGASSERT(pszPassword);
  2190. MYDBGASSERT(lpdwCryptType);
  2191. DWORD dwEncryptedBufferLen;
  2192. DWORD dwSize = 0;
  2193. LPTSTR pszEncryptedData = NULL;
  2194. TCHAR szSourceData[PWLEN + 1];
  2195. if (NULL == pArgs || NULL == pszPassword || NULL == lpdwCryptType)
  2196. {
  2197. return NULL;
  2198. }
  2199. //
  2200. // Standard encryption, copy the password
  2201. //
  2202. lstrcpyU(szSourceData, pszPassword);
  2203. //
  2204. // It is not safe to call InitSecure more than once
  2205. //
  2206. if (!pArgs->fInitSecureCalled)
  2207. {
  2208. pArgs->fInitSecureCalled = TRUE;
  2209. InitSecure(FALSE); // don't use fast encryption anymore
  2210. }
  2211. //
  2212. // Encrypt the provided password
  2213. //
  2214. if (EncryptData(
  2215. (LPBYTE)szSourceData,
  2216. (lstrlenU(szSourceData)+1) * sizeof(TCHAR),
  2217. (LPBYTE*)&pszEncryptedData,
  2218. &dwEncryptedBufferLen,
  2219. lpdwCryptType,
  2220. #if defined(DEBUG) && defined(DEBUG_MEM)
  2221. (PFN_CMSECUREALLOC)AllocDebugMem, // Give the DEBUG_MEM version of alloc/free
  2222. (PFN_CMSECUREFREE)FreeDebugMem, // Not quit right, AllocDebugMem takes 3 param
  2223. pszSubKey))
  2224. #else
  2225. (PFN_CMSECUREALLOC)CmMalloc,
  2226. (PFN_CMSECUREFREE)CmFree,
  2227. pszSubKey))
  2228. #endif
  2229. {
  2230. if (lpdwBufSize)
  2231. {
  2232. *lpdwBufSize = dwEncryptedBufferLen;
  2233. }
  2234. }
  2235. MYDBGASSERT(pszEncryptedData);
  2236. CmWipePassword(szSourceData);
  2237. return pszEncryptedData;
  2238. }
  2239. //+----------------------------------------------------------------------------
  2240. //
  2241. // Function: DecryptPassword
  2242. //
  2243. // Synopsis: Wrapper to decrypt password
  2244. //
  2245. // Arguments: ArgsStruct *pArgs - Ptr to global args struct
  2246. // LPCTSTR pszEncryptedData - The encrypted data
  2247. // DWORD dwEncryptionType - The encryption type of the data
  2248. // BOOL fReg - Password is disguised for registry storage
  2249. //
  2250. // Returns: LPTSTR - Ptr to a buffer containing the decrypted form of the password.
  2251. //
  2252. // History: nickball Created 5/22/98
  2253. //
  2254. //+----------------------------------------------------------------------------
  2255. LPBYTE DecryptPassword(
  2256. ArgsStruct *pArgs,
  2257. LPBYTE pszEncryptedData,
  2258. DWORD dwEncryptionType,
  2259. DWORD dwEncryptedBytes,
  2260. BOOL /*fReg*/,
  2261. LPSTR pszSubKey)
  2262. {
  2263. MYDBGASSERT(pArgs);
  2264. MYDBGASSERT(pszEncryptedData);
  2265. DWORD dwDecryptedBufferLen;
  2266. LPBYTE pszDecryptedData = NULL;
  2267. if (NULL == pArgs || NULL == pszEncryptedData)
  2268. {
  2269. return NULL;
  2270. }
  2271. //
  2272. // It is not safe to call InitSecure more than once
  2273. //
  2274. if (!pArgs->fInitSecureCalled)
  2275. {
  2276. pArgs->fInitSecureCalled = TRUE;
  2277. InitSecure(FALSE); // don't use fast encryption anymore
  2278. }
  2279. if (DecryptData(pszEncryptedData, dwEncryptedBytes, &pszDecryptedData, &dwDecryptedBufferLen,
  2280. dwEncryptionType,
  2281. #if defined(DEBUG) && defined(DEBUG_MEM)
  2282. (PFN_CMSECUREALLOC)AllocDebugMem, // Give the DEBUG_MEM version of alloc/free
  2283. (PFN_CMSECUREFREE)FreeDebugMem, // Not quit right, AllocDebugMem takes 3 param
  2284. pszSubKey))
  2285. #else
  2286. (PFN_CMSECUREALLOC)CmMalloc,
  2287. (PFN_CMSECUREFREE)CmFree,
  2288. pszSubKey))
  2289. #endif
  2290. {
  2291. return pszDecryptedData;
  2292. }
  2293. return NULL;
  2294. }
  2295. //+----------------------------------------------------------------------------
  2296. //
  2297. // Function: TranslateUserDataID
  2298. //
  2299. // Synopsis: Wrapper to map user data ID to string name of .CMP entry
  2300. //
  2301. // Arguments: UINT uiDataID - UserInfo data ID to be translated
  2302. //
  2303. // Returns: LPCTSTR - Ptr to a constant containing the .CMP entry flag
  2304. //
  2305. // History: nickball Created 10/13/98
  2306. //
  2307. //+----------------------------------------------------------------------------
  2308. LPCTSTR TranslateUserDataID(UINT uiDataID)
  2309. {
  2310. switch(uiDataID)
  2311. {
  2312. case UD_ID_USERNAME:
  2313. return c_pszCmEntryUserName;
  2314. break;
  2315. case UD_ID_INET_USERNAME:
  2316. return c_pszCmEntryInetUserName;
  2317. break;
  2318. case UD_ID_DOMAIN:
  2319. return c_pszCmEntryDomain;
  2320. break;
  2321. case UD_ID_PASSWORD:
  2322. return c_pszCmEntryPassword;
  2323. break;
  2324. case UD_ID_INET_PASSWORD:
  2325. return c_pszCmEntryInetPassword;
  2326. break;
  2327. case UD_ID_NOPROMPT:
  2328. return c_pszCmEntryNoPrompt;
  2329. break;
  2330. case UD_ID_REMEMBER_PWD:
  2331. return c_pszCmEntryRememberPwd;
  2332. break;
  2333. case UD_ID_REMEMBER_INET_PASSWORD:
  2334. return c_pszCmEntryRememberInetPwd;
  2335. break;
  2336. case UD_ID_PCS:
  2337. return c_pszCmEntryPcs;
  2338. break;
  2339. case UD_ID_ACCESSPOINTENABLED:
  2340. return c_pszCmEntryAccessPointsEnabled;
  2341. break;
  2342. case UD_ID_CURRENTACCESSPOINT:
  2343. return c_pszCmEntryCurrentAccessPoint;
  2344. break;
  2345. default:
  2346. break;
  2347. }
  2348. MYDBGASSERT(FALSE);
  2349. return NULL;
  2350. }