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.

881 lines
22 KiB

  1. //Copyright (c) 1998 - 1999 Microsoft Corporation
  2. #include "stdafx.h"
  3. #include "connode.h"
  4. #include "resource.h"
  5. #include "license.h"
  6. #include "tssec.h"
  7. #include "defaults.h"
  8. #include "wincrypt.h"
  9. #define NO_PASSWORD_VALUE_LEN 4
  10. #define NO_PASSWORD_VALUE 0x45628275
  11. CConNode::CConNode()
  12. {
  13. m_bConnected = FALSE;
  14. m_bConnectionInitialized = FALSE;
  15. m_szServer[0] = NULL;
  16. m_szDescription[0] = NULL;
  17. m_szUserName[0] = NULL;
  18. m_szDomain[0] = NULL;
  19. m_bSavePassword = FALSE;
  20. m_resType = SCREEN_RES_FILL_MMC;
  21. m_Width = DEFAULT_RES_WIDTH;
  22. m_Height = DEFAULT_RES_HEIGHT;
  23. m_szProgramPath[0] = NULL;
  24. m_szProgramStartIn[0] = NULL;
  25. m_pMhostCtl = NULL;
  26. m_pTsClientCtl = NULL;
  27. m_bConnectToConsole = FALSE;
  28. m_bRedirectDrives = FALSE;
  29. m_pIComponent = NULL;
  30. m_fPasswordSpecified = FALSE;
  31. _blobEncryptedPassword.cbData = 0;
  32. _blobEncryptedPassword.pbData = 0;
  33. }
  34. CConNode::~CConNode()
  35. {
  36. if (m_pIComponent)
  37. {
  38. m_pIComponent->Release();
  39. m_pIComponent = NULL;
  40. }
  41. if (_blobEncryptedPassword.pbData && _blobEncryptedPassword.cbData) {
  42. LocalFree(_blobEncryptedPassword.pbData);
  43. _blobEncryptedPassword.pbData = NULL;
  44. _blobEncryptedPassword.cbData = 0;
  45. }
  46. }
  47. BOOL CConNode::SetServerName( LPTSTR szServerName)
  48. {
  49. ASSERT(szServerName);
  50. if (szServerName != NULL)
  51. {
  52. lstrcpy(m_szServer, szServerName);
  53. }
  54. else
  55. {
  56. m_szServer[0] = NULL;
  57. }
  58. return TRUE;
  59. }
  60. BOOL CConNode::SetDescription( LPTSTR szDescription)
  61. {
  62. ASSERT(szDescription);
  63. if (szDescription != NULL)
  64. {
  65. lstrcpy(m_szDescription, szDescription);
  66. }
  67. else
  68. {
  69. m_szDescription[0] = NULL;
  70. }
  71. return TRUE;
  72. }
  73. BOOL CConNode::SetUserName( LPTSTR szUserName)
  74. {
  75. ASSERT(szUserName);
  76. if (szUserName != NULL)
  77. {
  78. lstrcpy(m_szUserName, szUserName);
  79. }
  80. else
  81. {
  82. m_szUserName[0] = NULL;
  83. }
  84. return TRUE;
  85. }
  86. BOOL CConNode::SetDomain(LPTSTR szDomain)
  87. {
  88. ASSERT(szDomain);
  89. if (szDomain != NULL)
  90. {
  91. lstrcpy(m_szDomain, szDomain);
  92. }
  93. else
  94. {
  95. m_szDomain[0] = NULL;
  96. }
  97. return TRUE;
  98. }
  99. //
  100. // DataProtect
  101. // Protect data for persistence using data protection API
  102. // params:
  103. // pInData - (in) input bytes to protect
  104. // cbLen - (in) length of pInData in bytes
  105. // ppOutData - (out) output bytes
  106. // pcbOutLen - (out) length of output
  107. // returns: bool status
  108. //
  109. BOOL CConNode::DataProtect(PBYTE pInData, DWORD cbLen, PBYTE* ppOutData, PDWORD pcbOutLen)
  110. {
  111. DATA_BLOB DataIn;
  112. DATA_BLOB DataOut;
  113. ASSERT(pInData && cbLen);
  114. ASSERT(ppOutData);
  115. ASSERT(pcbOutLen);
  116. if (pInData && cbLen && ppOutData && pcbOutLen)
  117. {
  118. DataIn.pbData = pInData;
  119. DataIn.cbData = cbLen;
  120. if (CryptProtectData( &DataIn,
  121. TEXT("ps"), // DESCRIPTION STRING.
  122. NULL, // optional entropy
  123. NULL, // reserved
  124. NULL, // NO prompting
  125. CRYPTPROTECT_UI_FORBIDDEN, //don't pop UI
  126. &DataOut ))
  127. {
  128. *ppOutData = (PBYTE)LocalAlloc(LPTR, DataOut.cbData);
  129. if (*ppOutData)
  130. {
  131. //copy the output data
  132. memcpy(*ppOutData, DataOut.pbData, DataOut.cbData);
  133. *pcbOutLen = DataOut.cbData;
  134. LocalFree(DataOut.pbData);
  135. return TRUE;
  136. }
  137. else
  138. {
  139. LocalFree(DataOut.pbData);
  140. return FALSE;
  141. }
  142. }
  143. else
  144. {
  145. DWORD dwLastErr = GetLastError();
  146. DBGMSG( L"CryptProtectData FAILED error:%d\n",dwLastErr);
  147. return FALSE;
  148. }
  149. }
  150. else
  151. {
  152. return FALSE;
  153. }
  154. }
  155. //
  156. // DataUnprotect
  157. // UnProtect persisted out data using data protection API
  158. // params:
  159. // pInData - (in) input bytes to UN protect
  160. // cbLen - (in) length of pInData in bytes
  161. // ppOutData - (out) output bytes
  162. // pcbOutLen - (out) length of output
  163. // returns: bool status
  164. //
  165. //
  166. BOOL CConNode::DataUnprotect(PBYTE pInData, DWORD cbLen, PBYTE* ppOutData, PDWORD pcbOutLen)
  167. {
  168. DATA_BLOB DataIn;
  169. DATA_BLOB DataOut;
  170. ASSERT(pInData && cbLen && ppOutData && pcbOutLen);
  171. if (pInData && cbLen && ppOutData && pcbOutLen)
  172. {
  173. DataIn.pbData = pInData;
  174. DataIn.cbData = cbLen;
  175. if (CryptUnprotectData( &DataIn,
  176. NULL, // NO DESCRIPTION STRING
  177. NULL, // optional entropy
  178. NULL, // reserved
  179. NULL, // NO prompting
  180. CRYPTPROTECT_UI_FORBIDDEN, //don't pop UI
  181. &DataOut ))
  182. {
  183. *ppOutData = (PBYTE)LocalAlloc(LPTR, DataOut.cbData);
  184. if (*ppOutData)
  185. {
  186. //copy the output data
  187. memcpy(*ppOutData, DataOut.pbData, DataOut.cbData);
  188. *pcbOutLen = DataOut.cbData;
  189. LocalFree(DataOut.pbData);
  190. return TRUE;
  191. }
  192. else
  193. {
  194. LocalFree(DataOut.pbData);
  195. return FALSE;
  196. }
  197. }
  198. else
  199. {
  200. DWORD dwLastErr = GetLastError();
  201. DBGMSG( L"CryptUnprotectData FAILED error:%d\n",dwLastErr);
  202. return FALSE;
  203. }
  204. }
  205. else
  206. {
  207. return FALSE;
  208. }
  209. }
  210. HRESULT CConNode::PersistToStream( IStream* pStm)
  211. {
  212. //
  213. // Persist the data of this connection node to the stream
  214. //
  215. // The data is persisted started at the current seek position
  216. // of the stream.
  217. HRESULT hr;
  218. ULONG cbWritten;
  219. ASSERT(pStm);
  220. if (!pStm)
  221. {
  222. return E_FAIL;
  223. }
  224. //
  225. //Persist info version
  226. //
  227. int persist_ver = CONNODE_PERSIST_INFO_VERSION;
  228. hr = pStm->Write( &persist_ver, sizeof(persist_ver), &cbWritten);
  229. HR_RET_IF_FAIL(hr);
  230. //
  231. //server
  232. //
  233. hr = pStm->Write( &m_szServer, sizeof(m_szServer), &cbWritten);
  234. HR_RET_IF_FAIL(hr);
  235. //
  236. //description
  237. //
  238. hr = pStm->Write( &m_szDescription, sizeof(m_szDescription), &cbWritten);
  239. HR_RET_IF_FAIL(hr);
  240. //
  241. //user name
  242. //
  243. hr = pStm->Write( &m_szUserName, sizeof(m_szUserName), &cbWritten);
  244. HR_RET_IF_FAIL(hr);
  245. //
  246. //encrypted password
  247. //
  248. //Intentional ignore of failure code as crypto may fail
  249. hr = WriteProtectedPassword( pStm);
  250. //
  251. //domain
  252. //
  253. hr = pStm->Write( &m_szDomain, sizeof(m_szDomain), &cbWritten);
  254. HR_RET_IF_FAIL(hr);
  255. //
  256. //Password specified flag
  257. //
  258. BOOL fWritePassword = GetPasswordSpecified() && GetSavePassword();
  259. hr = pStm->Write( &fWritePassword, sizeof(fWritePassword), &cbWritten);
  260. HR_RET_IF_FAIL(hr);
  261. //
  262. // Screen resolution
  263. //
  264. hr = pStm->Write( &m_resType, sizeof(m_resType), &cbWritten);
  265. HR_RET_IF_FAIL(hr);
  266. hr = pStm->Write( &m_Width, sizeof(m_Width), &cbWritten);
  267. HR_RET_IF_FAIL(hr);
  268. hr = pStm->Write( &m_Height, sizeof(m_Height), &cbWritten);
  269. HR_RET_IF_FAIL(hr);
  270. //
  271. // Start program
  272. //
  273. hr = pStm->Write( &m_szProgramPath, sizeof(m_szProgramPath), &cbWritten);
  274. HR_RET_IF_FAIL(hr);
  275. //
  276. // Work dir
  277. //
  278. hr = pStm->Write( &m_szProgramStartIn, sizeof(m_szProgramStartIn), &cbWritten);
  279. HR_RET_IF_FAIL(hr);
  280. //
  281. // Connect to console
  282. //
  283. hr = pStm->Write( &m_bConnectToConsole, sizeof(m_bConnectToConsole), &cbWritten);
  284. HR_RET_IF_FAIL(hr);
  285. hr = pStm->Write( &m_bRedirectDrives, sizeof(m_bRedirectDrives), &cbWritten);
  286. HR_RET_IF_FAIL(hr);
  287. //
  288. // PADDING for future extension
  289. //
  290. DWORD dwPad = (DWORD)-1;
  291. hr = pStm->Write( &dwPad, sizeof(dwPad), &cbWritten);
  292. HR_RET_IF_FAIL(hr);
  293. hr = pStm->Write( &dwPad, sizeof(dwPad), &cbWritten);
  294. HR_RET_IF_FAIL(hr);
  295. hr = pStm->Write( &dwPad, sizeof(dwPad), &cbWritten);
  296. HR_RET_IF_FAIL(hr);
  297. return S_OK;
  298. }
  299. HRESULT CConNode::InitFromStream( IStream* pStm)
  300. {
  301. //
  302. // Reads in the data for this connection node from the stream
  303. // starting at the current seek position in the stream.
  304. //
  305. HRESULT hr;
  306. ULONG cbRead;
  307. ASSERT(pStm);
  308. if (!pStm)
  309. {
  310. return E_FAIL;
  311. }
  312. int persist_info_version;
  313. //
  314. //Persist info version
  315. //
  316. hr = pStm->Read( &persist_info_version, sizeof(persist_info_version), &cbRead);
  317. HR_RET_IF_FAIL(hr);
  318. if (persist_info_version <= CONNODE_PERSIST_INFO_VERSION_TSAC_BETA)
  319. {
  320. //
  321. // Unsupported perist version
  322. //
  323. return E_FAIL;
  324. }
  325. //
  326. //server
  327. //
  328. hr = pStm->Read( &m_szServer, sizeof(m_szServer), &cbRead);
  329. m_szServer[sizeof(m_szServer) / sizeof(TCHAR) - 1] = NULL;
  330. HR_RET_IF_FAIL(hr);
  331. //
  332. //description
  333. //
  334. hr = pStm->Read( &m_szDescription, sizeof(m_szDescription), &cbRead);
  335. m_szDescription[sizeof(m_szDescription) / sizeof(TCHAR) - 1] = NULL;
  336. HR_RET_IF_FAIL(hr);
  337. //
  338. //user name
  339. //
  340. hr = pStm->Read( &m_szUserName, sizeof(m_szUserName), &cbRead);
  341. m_szUserName[sizeof(m_szUserName) / sizeof(TCHAR) - 1] = NULL;
  342. HR_RET_IF_FAIL(hr);
  343. //
  344. // Password
  345. //
  346. BOOL fGotPassword = FALSE;
  347. if (CONNODE_PERSIST_INFO_VERSION_TSAC_BETA == persist_info_version)
  348. {
  349. //
  350. // We drop the password if it's in TSAC format as we dropped
  351. // support for that format
  352. //
  353. //
  354. // Just seek past the correct number of bytes
  355. //
  356. LARGE_INTEGER seekDelta = {0, CL_OLD_PASSWORD_LENGTH + CL_SALT_LENGTH};
  357. hr = pStm->Seek(seekDelta,
  358. STREAM_SEEK_CUR,
  359. NULL);
  360. HR_RET_IF_FAIL(hr);
  361. }
  362. else if (persist_info_version <= CONNODE_PERSIST_INFO_VERSION_DOTNET_BETA3) {
  363. //
  364. // We drop support for the legacy DPAPI+Control obfuscation formats
  365. //
  366. DWORD cbSecureLen = 0;
  367. //
  368. //encrypted bytes length
  369. //
  370. hr = pStm->Read( &cbSecureLen, sizeof(cbSecureLen), &cbRead);
  371. HR_RET_IF_FAIL(hr);
  372. //
  373. // Just seek ahead in the stream
  374. //
  375. LARGE_INTEGER seekDelta;
  376. seekDelta.LowPart = cbSecureLen;
  377. seekDelta.HighPart = 0;
  378. hr = pStm->Seek(seekDelta,
  379. STREAM_SEEK_CUR,
  380. NULL);
  381. HR_RET_IF_FAIL(hr);
  382. }
  383. else
  384. {
  385. //Read the new more secure format
  386. hr = ReadProtectedPassword(pStm);
  387. if(SUCCEEDED(hr)) {
  388. fGotPassword = TRUE;
  389. }
  390. else {
  391. ODS(TEXT("Failed to ReadProtectedPassword\n"));
  392. }
  393. }
  394. //
  395. //domain
  396. //
  397. if(persist_info_version >= CONNODE_PERSIST_INFO_VERSION_DOTNET_BETA3)
  398. {
  399. hr = pStm->Read( &m_szDomain, sizeof(m_szDomain), &cbRead);
  400. m_szDomain[sizeof(m_szDomain) / sizeof(TCHAR) - 1] = NULL;
  401. HR_RET_IF_FAIL(hr);
  402. }
  403. else
  404. {
  405. //Old length for domain
  406. hr = pStm->Read( &m_szDomain, CL_OLD_DOMAIN_LENGTH * sizeof(TCHAR),
  407. &cbRead);
  408. m_szDomain[CL_OLD_DOMAIN_LENGTH - 1] = NULL;
  409. HR_RET_IF_FAIL(hr);
  410. }
  411. //
  412. //Password specified flag
  413. //
  414. hr = pStm->Read( &m_fPasswordSpecified, sizeof(m_fPasswordSpecified), &cbRead);
  415. HR_RET_IF_FAIL(hr);
  416. //
  417. // Override the autologon flag if we failed to
  418. // get a password, e.g if we were unable to decrypt
  419. // it because the current user doesn't match credentials
  420. //
  421. if(!fGotPassword)
  422. {
  423. m_fPasswordSpecified = FALSE;
  424. }
  425. //
  426. // If the password was specified in the file
  427. // it means we want it saved
  428. //
  429. m_bSavePassword = m_fPasswordSpecified;
  430. //
  431. // Screen resolution
  432. //
  433. hr = pStm->Read( &m_resType, sizeof(m_resType), &cbRead);
  434. HR_RET_IF_FAIL(hr);
  435. hr = pStm->Read( &m_Width, sizeof(m_Width), &cbRead);
  436. HR_RET_IF_FAIL(hr);
  437. hr = pStm->Read( &m_Height, sizeof(m_Height), &cbRead);
  438. HR_RET_IF_FAIL(hr);
  439. //
  440. // Start program
  441. //
  442. hr = pStm->Read( &m_szProgramPath, sizeof(m_szProgramPath), &cbRead);
  443. m_szProgramPath[sizeof(m_szProgramPath) / sizeof(TCHAR) - 1] = NULL;
  444. HR_RET_IF_FAIL(hr);
  445. //
  446. // Work dir
  447. //
  448. hr = pStm->Read( &m_szProgramStartIn, sizeof(m_szProgramStartIn), &cbRead);
  449. m_szProgramStartIn[sizeof(m_szProgramStartIn) / sizeof(TCHAR) - 1] = NULL;
  450. HR_RET_IF_FAIL(hr);
  451. if(persist_info_version >= CONNODE_PERSIST_INFO_VERSION_WHISTLER_BETA1)
  452. {
  453. //
  454. // Connect to console
  455. //
  456. hr = pStm->Read( &m_bConnectToConsole, sizeof(m_bConnectToConsole), &cbRead);
  457. HR_RET_IF_FAIL(hr);
  458. hr = pStm->Read( &m_bRedirectDrives, sizeof(m_bRedirectDrives), &cbRead);
  459. HR_RET_IF_FAIL(hr);
  460. //
  461. // PADDING for future extension
  462. //
  463. DWORD dwPad;
  464. hr = pStm->Read( &dwPad, sizeof(dwPad), &cbRead);
  465. HR_RET_IF_FAIL(hr);
  466. hr = pStm->Read( &dwPad, sizeof(dwPad), &cbRead);
  467. HR_RET_IF_FAIL(hr);
  468. hr = pStm->Read( &dwPad, sizeof(dwPad), &cbRead);
  469. HR_RET_IF_FAIL(hr);
  470. }
  471. return S_OK;
  472. }
  473. HRESULT CConNode::ReadProtectedPassword(IStream* pStm)
  474. {
  475. HRESULT hr = E_FAIL;
  476. ULONG cbRead;
  477. if (pStm)
  478. {
  479. //
  480. // NOTE: About password encryption
  481. // at runtime the password is passed around in DPAPI form
  482. //
  483. // Legacy formats had the password first encrypted with the
  484. // control's password obfuscation - we got rid of those.
  485. //
  486. // persistence format is
  487. // -DWORD giving size of encrypted data field
  488. // -Data protection ENCRYPTED BYTES of encryptedpass+salt concatenation
  489. //
  490. DWORD cbSecureLen = 0;
  491. //
  492. //encrypted bytes length
  493. //
  494. hr = pStm->Read( &cbSecureLen, sizeof(cbSecureLen), &cbRead);
  495. HR_RET_IF_FAIL(hr);
  496. if (cbSecureLen == 0) {
  497. return E_FAIL;
  498. }
  499. PBYTE pEncryptedBytes = (PBYTE) LocalAlloc(LPTR, cbSecureLen);
  500. if (!pEncryptedBytes) {
  501. return E_OUTOFMEMORY;
  502. }
  503. //
  504. //read in the encrypted pass+salt combo
  505. //
  506. hr = pStm->Read( pEncryptedBytes, cbSecureLen, &cbRead);
  507. HR_RET_IF_FAIL(hr);
  508. if (cbSecureLen != cbRead)
  509. {
  510. LocalFree(pEncryptedBytes);
  511. return E_FAIL;
  512. }
  513. if (cbSecureLen == NO_PASSWORD_VALUE_LEN)
  514. {
  515. ODS(TEXT("Read cbSecurLen of NO_PASSWORD_VALUE_LEN. No password."));
  516. LocalFree(pEncryptedBytes);
  517. return E_FAIL;
  518. }
  519. //
  520. // DPAPI decrypt the persisted secure bytes to test if the decryption
  521. // succeeds
  522. //
  523. PBYTE pUnSecureBytes;
  524. DWORD cbUnSecureLen;
  525. if (!DataUnprotect( (PBYTE)pEncryptedBytes, cbSecureLen,
  526. &pUnSecureBytes, &cbUnSecureLen))
  527. {
  528. //DPAPI Password encryption failed
  529. ODS(TEXT("DataUnProtect encryption FAILED\n"));
  530. LocalFree(pEncryptedBytes);
  531. return E_FAIL;
  532. }
  533. //
  534. // Free any existing data in the blob
  535. //
  536. if (_blobEncryptedPassword.pbData && _blobEncryptedPassword.cbData) {
  537. LocalFree(_blobEncryptedPassword.pbData);
  538. _blobEncryptedPassword.pbData = NULL;
  539. _blobEncryptedPassword.cbData = 0;
  540. }
  541. //
  542. // Do not free the encrypted bytes, they are kept around
  543. // in the data blob in DPAPI format - ConNode will take care
  544. // of correctly freeing the bytes when they are no longer needed.
  545. //
  546. _blobEncryptedPassword.pbData = pEncryptedBytes;
  547. _blobEncryptedPassword.cbData = cbSecureLen;
  548. SecureZeroMemory(pUnSecureBytes, cbUnSecureLen);
  549. LocalFree(pUnSecureBytes);
  550. return hr;
  551. }
  552. else
  553. {
  554. return E_INVALIDARG;
  555. }
  556. }
  557. //
  558. // Write a DPAPI protected password out to the stream
  559. //
  560. HRESULT CConNode::WriteProtectedPassword(IStream* pStm)
  561. {
  562. HRESULT hr = E_FAIL;
  563. ULONG cbWritten;
  564. if (pStm)
  565. {
  566. //
  567. // NOTE: About password encryption
  568. // at runtime the password is passed around in DPAPI form
  569. //
  570. // Save the password/salt in the following format
  571. // -DWORD giving size of encrypted data field
  572. // -Data protection ENCRYPTED BYTES of encryptedpass+salt concatenation
  573. //
  574. PBYTE pSecureBytes = NULL;
  575. DWORD cbSecureLen = NULL;
  576. BOOL fFreeSecureBytes = FALSE;
  577. DWORD dwDummyBytes = NO_PASSWORD_VALUE;
  578. //
  579. // Don't save the password if the setting is not selected or if there
  580. // isn't any data to save.
  581. //
  582. if (!GetSavePassword() || 0 == _blobEncryptedPassword.cbData) {
  583. //
  584. // User chose not to save the password, write 4 bytes
  585. //
  586. cbSecureLen = 4;
  587. pSecureBytes = (PBYTE)&dwDummyBytes;
  588. }
  589. //
  590. //encrypted bytes length
  591. //
  592. cbSecureLen = _blobEncryptedPassword.cbData;
  593. hr = pStm->Write(&cbSecureLen, sizeof(cbSecureLen), &cbWritten);
  594. //
  595. //write out secured bytes
  596. //
  597. if (SUCCEEDED(hr)) {
  598. pSecureBytes = _blobEncryptedPassword.pbData;
  599. hr = pStm->Write(pSecureBytes, cbSecureLen, &cbWritten);
  600. }
  601. }
  602. else
  603. {
  604. hr = E_INVALIDARG;
  605. }
  606. return hr;
  607. }
  608. IMsRdpClient* CConNode::GetTsClient()
  609. {
  610. if (m_pTsClientCtl)
  611. {
  612. m_pTsClientCtl->AddRef();
  613. }
  614. return m_pTsClientCtl;
  615. }
  616. void CConNode::SetTsClient(IMsRdpClient* pTs)
  617. {
  618. if (NULL == pTs)
  619. {
  620. if (m_pTsClientCtl)
  621. {
  622. m_pTsClientCtl->Release();
  623. m_pTsClientCtl = NULL;
  624. }
  625. }
  626. else
  627. {
  628. m_pTsClientCtl = pTs;
  629. m_pTsClientCtl->AddRef();
  630. }
  631. }
  632. IMstscMhst* CConNode::GetMultiHostCtl()
  633. {
  634. if (m_pMhostCtl)
  635. {
  636. m_pMhostCtl->AddRef();
  637. }
  638. return m_pMhostCtl;
  639. }
  640. void CConNode::SetMultiHostCtl(IMstscMhst* pMhst)
  641. {
  642. if (NULL == pMhst)
  643. {
  644. if (m_pMhostCtl)
  645. {
  646. m_pMhostCtl->Release();
  647. }
  648. m_pMhostCtl = NULL;
  649. }
  650. else
  651. {
  652. m_pMhostCtl = pMhst;
  653. m_pMhostCtl->AddRef();
  654. }
  655. }
  656. IComponent* CConNode::GetView()
  657. {
  658. if (m_pIComponent)
  659. {
  660. m_pIComponent->AddRef();
  661. }
  662. return m_pIComponent;
  663. }
  664. void CConNode::SetView(IComponent* pView)
  665. {
  666. if (!pView)
  667. {
  668. if (m_pIComponent)
  669. {
  670. m_pIComponent->Release();
  671. m_pIComponent = NULL;
  672. }
  673. }
  674. else
  675. {
  676. if (m_pIComponent)
  677. {
  678. ODS( L"Clobbering IComponent interface, could be leaking\n" );
  679. }
  680. pView->AddRef();
  681. m_pIComponent = pView;
  682. }
  683. }
  684. //
  685. // Store a clear text password in encrypted form
  686. //
  687. HRESULT
  688. CConNode::SetClearTextPass(LPCTSTR szClearPass)
  689. {
  690. HRESULT hr = E_FAIL;
  691. DATA_BLOB din;
  692. din.cbData = _tcslen(szClearPass) * sizeof(TCHAR);
  693. din.pbData = (PBYTE)szClearPass;
  694. if (_blobEncryptedPassword.pbData)
  695. {
  696. LocalFree(_blobEncryptedPassword.pbData);
  697. _blobEncryptedPassword.pbData = NULL;
  698. _blobEncryptedPassword.cbData = 0;
  699. }
  700. if (din.cbData)
  701. {
  702. if (CryptProtectData(&din,
  703. TEXT("ps"), // DESCRIPTION STRING.
  704. NULL, // optional entropy
  705. NULL, // reserved
  706. NULL, // NO prompting
  707. CRYPTPROTECT_UI_FORBIDDEN, //don't pop UI
  708. &_blobEncryptedPassword))
  709. {
  710. hr = S_OK;
  711. }
  712. else
  713. {
  714. ODS((_T("DataProtect failed")));
  715. hr = E_FAIL;
  716. }
  717. }
  718. else
  719. {
  720. ODS((_T("0 length password, not encrypting")));
  721. hr = S_OK;
  722. }
  723. return hr;
  724. }
  725. //
  726. // Retrieve a clear text password
  727. //
  728. //
  729. // Params
  730. // [out] szBuffer - receives decrypted password
  731. // [int] cbLen - length of szBuffer
  732. //
  733. HRESULT
  734. CConNode::GetClearTextPass(LPTSTR szBuffer, INT cbLen)
  735. {
  736. HRESULT hr = E_FAIL;
  737. DATA_BLOB dout;
  738. dout.cbData = 0;
  739. dout.pbData = NULL;
  740. if (_blobEncryptedPassword.cbData)
  741. {
  742. memset(szBuffer, 0, cbLen);
  743. if (CryptUnprotectData(&_blobEncryptedPassword,
  744. NULL, // NO DESCRIPTION STRING
  745. NULL, // optional entropy
  746. NULL, // reserved
  747. NULL, // NO prompting
  748. CRYPTPROTECT_UI_FORBIDDEN, //don't pop UI
  749. &dout))
  750. {
  751. memcpy(szBuffer, dout.pbData,
  752. min( dout.cbData,(UINT)cbLen-sizeof(TCHAR)));
  753. //
  754. // Nuke the original copy
  755. //
  756. SecureZeroMemory(dout.pbData, dout.cbData);
  757. LocalFree( dout.pbData );
  758. hr = S_OK;
  759. }
  760. else
  761. {
  762. ODS((_T("DataUnprotect failed")));
  763. hr = E_FAIL;
  764. }
  765. }
  766. else
  767. {
  768. ODS(_T("0 length encrypted pass, not decrypting"));
  769. //
  770. // Just reset the output buffer
  771. //
  772. memset(szBuffer, 0, cbLen);
  773. hr = S_OK;
  774. }
  775. return hr;
  776. }