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.

797 lines
18 KiB

  1. /**********************************************************************/
  2. /** Microsoft Passport **/
  3. /** Copyright(c) Microsoft Corporation, 1999 - 2001 **/
  4. /**********************************************************************/
  5. /*
  6. PassportCrypt.cpp
  7. FILE HISTORY:
  8. */
  9. // PassportCrypt.cpp : Implementation of CCrypt
  10. #include "stdafx.h"
  11. #include "Passport.h"
  12. #include "PassportCrypt.h"
  13. #include <time.h>
  14. /* moved into passport.idl -- so consumer of the COM API can see it
  15. // max blocks + 10 should be multiples of 3 for simplicity
  16. #define ENC_MAX_SIZE 2045
  17. // I don't trust the compiler... (((2045+10)*4)/3)+9 = 2749 * sizeof(wchar)
  18. #define DEC_MAX_SIZE 5498
  19. */
  20. //===========================================================================
  21. //
  22. // CCrypt
  23. //
  24. CCrypt::CCrypt() : m_crypt(NULL), m_szSiteName(NULL), m_szHostName(NULL)
  25. {
  26. m_pUnkMarshaler = NULL;
  27. m_keyVersion = 0;
  28. CRegistryConfig* crc = g_config->checkoutRegistryConfig();
  29. if( crc )
  30. {
  31. m_keyVersion = crc->getCurrentCryptVersion();
  32. crc->getCrypt(m_keyVersion, &m_validUntil);
  33. crc->Release();
  34. }
  35. }
  36. /////////////////////////////////////////////////////////////////////////////
  37. // CCrypt
  38. //===========================================================================
  39. //
  40. // InterfaceSupportsErrorInfo
  41. //
  42. STDMETHODIMP CCrypt::InterfaceSupportsErrorInfo(REFIID riid)
  43. {
  44. static const IID* arr[] =
  45. {
  46. &IID_IPassportCrypt,
  47. };
  48. for (int i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
  49. {
  50. if (InlineIsEqualGUID(*arr[i],riid))
  51. return S_OK;
  52. }
  53. return S_FALSE;
  54. }
  55. //===========================================================================
  56. //
  57. // OnStartPage
  58. //
  59. STDMETHODIMP CCrypt::OnStartPage(IUnknown* piUnk)
  60. {
  61. BOOL bHasPort;
  62. DWORD dwServerNameLen;
  63. HRESULT hr = S_OK;
  64. BOOL bVariantInited = FALSE;
  65. // param needs to cleanup
  66. IRequestPtr piRequest ;
  67. IRequestDictionaryPtr piServerVariables ;
  68. _variant_t vtItemName;
  69. _variant_t vtServerName;
  70. _variant_t vtServerPort;
  71. _variant_t vtHTTPS;
  72. // WCHAR szServerName = NULL;
  73. // CHAR* szServerName_A = NULL;
  74. CRegistryConfig* crc = NULL;
  75. if(!piUnk)
  76. {
  77. hr = E_POINTER;
  78. goto exit;
  79. }
  80. if (!g_config->isValid()) // Guarantees config is non-null
  81. {
  82. AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
  83. IID_IPassportManager, PP_E_NOT_CONFIGURED);
  84. hr = PP_E_NOT_CONFIGURED;
  85. }
  86. try
  87. {
  88. // Get Request Object Pointer
  89. piRequest = ((IScriptingContextPtr)piUnk)->Request;
  90. //
  91. // Use the request object to get the server name being requested
  92. // so we can get the correct registry config. But only do this
  93. // if we have some configured sites.
  94. //
  95. if(g_config->HasSites())
  96. {
  97. piRequest->get_ServerVariables(&piServerVariables);
  98. vtItemName.vt = VT_BSTR;
  99. vtItemName.bstrVal = SysAllocString(L"SERVER_NAME");
  100. if (NULL == vtItemName.bstrVal)
  101. {
  102. hr = E_OUTOFMEMORY;
  103. goto exit;
  104. }
  105. piServerVariables->get_Item(vtItemName, &vtServerName);
  106. if(vtServerName.vt != VT_BSTR)
  107. VariantChangeType(&vtServerName, &vtServerName, 0, VT_BSTR);
  108. VariantClear(&vtItemName);
  109. vtItemName.vt = VT_BSTR;
  110. vtItemName.bstrVal = SysAllocString(L"SERVER_PORT");
  111. if (NULL == vtItemName.bstrVal)
  112. {
  113. hr = E_OUTOFMEMORY;
  114. goto exit;
  115. }
  116. piServerVariables->get_Item(vtItemName, &vtServerPort);
  117. if(vtServerPort.vt != VT_BSTR)
  118. VariantChangeType(&vtServerPort, &vtServerPort, 0, VT_BSTR);
  119. VariantClear(&vtItemName);
  120. vtItemName.vt = VT_BSTR;
  121. vtItemName.bstrVal = SysAllocString(L"HTTPS");
  122. if (NULL == vtItemName.bstrVal)
  123. {
  124. hr = E_OUTOFMEMORY;
  125. goto exit;
  126. }
  127. hr = piServerVariables->get_Item(vtItemName, &vtHTTPS);
  128. if(vtHTTPS.vt != VT_BSTR)
  129. VariantChangeType(&vtHTTPS, &vtHTTPS, 0, VT_BSTR);
  130. // If not default port, append ":port" to server name.
  131. bHasPort = (lstrcmpiW(L"off", vtHTTPS.bstrVal) == 0 &&
  132. lstrcmpW(L"80", vtServerPort.bstrVal) != 0) ||
  133. (lstrcmpiW(L"on", vtHTTPS.bstrVal) == 0 &&
  134. lstrcmpW(L"443", vtServerPort.bstrVal) != 0);
  135. dwServerNameLen = bHasPort ?
  136. lstrlenW(vtServerName.bstrVal) + lstrlenW(vtServerPort.bstrVal) + 2 :
  137. lstrlenW(vtServerName.bstrVal) + 1;
  138. m_szHostName = new CHAR[dwServerNameLen];
  139. if( !m_szHostName )
  140. {
  141. hr = E_OUTOFMEMORY;
  142. goto exit;
  143. }
  144. WideCharToMultiByte(CP_ACP, 0, vtServerName.bstrVal, -1,
  145. m_szHostName, dwServerNameLen,
  146. NULL,
  147. NULL);
  148. if(bHasPort)
  149. {
  150. USES_CONVERSION;
  151. lstrcatA(m_szHostName, ":");
  152. lstrcatA(m_szHostName, W2A(vtServerPort.bstrVal));
  153. }
  154. crc = g_config->checkoutRegistryConfig(m_szHostName);
  155. }
  156. else
  157. {
  158. crc = g_config->checkoutRegistryConfig();
  159. }
  160. m_keyVersion = 0;
  161. if (crc)
  162. {
  163. m_keyVersion = crc->getCurrentCryptVersion();
  164. crc->getCrypt(m_keyVersion,&m_validUntil);
  165. }
  166. }
  167. catch(...)
  168. {
  169. hr = S_OK;
  170. }
  171. exit:
  172. if( crc )
  173. crc->Release();
  174. return hr;
  175. }
  176. //===========================================================================
  177. //
  178. // Encrypt
  179. //
  180. STDMETHODIMP CCrypt::Encrypt(BSTR rawData, BSTR *pEncrypted)
  181. {
  182. if (!rawData)
  183. return E_INVALIDARG;
  184. if (SysStringLen(rawData) > ENC_MAX_SIZE)
  185. {
  186. AtlReportError(CLSID_Crypt, L"Passport.Crypt: Data too large",
  187. IID_IPassportCrypt, E_FAIL);
  188. return E_FAIL;
  189. }
  190. if (m_crypt)
  191. {
  192. if (!m_crypt->Encrypt(m_keyVersion, (LPSTR)rawData, SysStringByteLen(rawData), pEncrypted))
  193. {
  194. AtlReportError(CLSID_Crypt,
  195. L"Encryption failed", IID_IPassportCrypt, E_FAIL);
  196. return E_FAIL;
  197. }
  198. }
  199. else
  200. {
  201. CRegistryConfig* crc = ObtainCRC();
  202. if (!crc)
  203. {
  204. AtlReportError(CLSID_Crypt,
  205. L"Passport misconfigured", IID_IPassportCrypt, E_FAIL);
  206. return E_FAIL;
  207. }
  208. CCoCrypt *cr = crc->getCrypt(m_keyVersion,&m_validUntil);
  209. if (!cr)
  210. {
  211. AtlReportError(CLSID_Crypt,
  212. L"No such key version", IID_IPassportCrypt, E_FAIL);
  213. crc->Release();
  214. return E_FAIL;
  215. }
  216. if (!cr->Encrypt(m_keyVersion,(LPSTR)rawData,SysStringByteLen(rawData),pEncrypted))
  217. {
  218. AtlReportError(CLSID_Crypt,
  219. L"Encryption failed", IID_IPassportCrypt, E_FAIL);
  220. crc->Release();
  221. return E_FAIL;
  222. }
  223. crc->Release();
  224. }
  225. return S_OK;
  226. }
  227. //===========================================================================
  228. //
  229. // Decrypt
  230. //
  231. STDMETHODIMP CCrypt::Decrypt(BSTR rawData, BSTR *pUnencrypted)
  232. {
  233. if (rawData == NULL)
  234. {
  235. *pUnencrypted = NULL;
  236. return S_OK;
  237. }
  238. if (SysStringLen(rawData) > DEC_MAX_SIZE)
  239. {
  240. AtlReportError(CLSID_Crypt, L"Passport.Crypt: Data too large",
  241. IID_IPassportCrypt, E_FAIL);
  242. return E_FAIL;
  243. }
  244. if (m_crypt) // Just do our job, no questions
  245. {
  246. if (m_crypt->Decrypt(rawData, SysStringByteLen(rawData), pUnencrypted))
  247. {
  248. return S_OK;
  249. }
  250. if(g_pAlert)
  251. g_pAlert->report(PassportAlertInterface::WARNING_TYPE, PM_FAILED_DECRYPT);
  252. *pUnencrypted = NULL;
  253. return S_OK;
  254. }
  255. // First find the key version
  256. int kv = CCoCrypt::getKeyVersion(rawData);
  257. time_t vU, now;
  258. CRegistryConfig* crc = ObtainCRC();
  259. if (!crc)
  260. {
  261. AtlReportError(CLSID_Crypt,
  262. L"Passport misconfigured", IID_IPassportCrypt, PP_E_NOT_CONFIGURED);
  263. return PP_E_NOT_CONFIGURED;
  264. }
  265. CCoCrypt *cr = crc->getCrypt(kv, &vU);
  266. time(&now);
  267. if ((vU != 0 && now > vU) || cr == NULL)
  268. {
  269. *pUnencrypted = NULL;
  270. if(g_pAlert)
  271. g_pAlert->report(PassportAlertInterface::WARNING_TYPE, PM_FAILED_DECRYPT);
  272. crc->Release();
  273. return S_OK;
  274. }
  275. if (cr->Decrypt(rawData, SysStringByteLen(rawData), pUnencrypted))
  276. {
  277. crc->Release();
  278. return S_OK;
  279. }
  280. if(g_pAlert)
  281. g_pAlert->report(PassportAlertInterface::WARNING_TYPE, PM_FAILED_DECRYPT);
  282. crc->Release();
  283. *pUnencrypted = NULL;
  284. return S_OK;
  285. }
  286. //===========================================================================
  287. //
  288. // get_keyVersion
  289. //
  290. STDMETHODIMP CCrypt::get_keyVersion(int *pVal)
  291. {
  292. *pVal = m_keyVersion;
  293. return S_OK;
  294. }
  295. //===========================================================================
  296. //
  297. // put_keyVersion
  298. //
  299. STDMETHODIMP CCrypt::put_keyVersion(int newVal)
  300. {
  301. m_keyVersion = newVal;
  302. if (m_crypt)
  303. {
  304. delete m_crypt;
  305. m_crypt = NULL;
  306. }
  307. return S_OK;
  308. }
  309. //===========================================================================
  310. //
  311. // vget_IsValid
  312. //
  313. STDMETHODIMP CCrypt::get_IsValid(VARIANT_BOOL *pVal)
  314. {
  315. // fix 6695 PassportCrypt.IsValid is inconsistent to end users.
  316. // *pVal = (m_crypt != NULL) ? VARIANT_TRUE : VARIANT_FALSE;
  317. *pVal = (g_config->isValid()) ? VARIANT_TRUE : VARIANT_FALSE;
  318. return S_OK;
  319. }
  320. //===========================================================================
  321. //
  322. // put_keyMaterial
  323. //
  324. STDMETHODIMP CCrypt::put_keyMaterial(BSTR newVal)
  325. {
  326. CCoCrypt *pcccTemp = new CCoCrypt();
  327. if (pcccTemp == NULL)
  328. {
  329. return E_OUTOFMEMORY;
  330. }
  331. if (m_crypt)
  332. {
  333. delete m_crypt;
  334. }
  335. m_crypt = pcccTemp;
  336. m_crypt->setKeyMaterial(newVal);
  337. return S_OK;
  338. }
  339. //===========================================================================
  340. //
  341. // Compress
  342. //
  343. STDMETHODIMP CCrypt::Compress(
  344. BSTR bstrIn,
  345. BSTR* pbstrCompressed
  346. )
  347. {
  348. HRESULT hr;
  349. UINT nInLen;
  350. //
  351. // Check inputs.
  352. //
  353. if(bstrIn == NULL ||
  354. pbstrCompressed == NULL)
  355. {
  356. hr = E_POINTER;
  357. goto Cleanup;
  358. }
  359. //
  360. // nInLen does not include the terminating NULL.
  361. //
  362. nInLen = SysStringLen(bstrIn);
  363. //
  364. // Always want to allocate an even number of bytes
  365. // so that the corresponding decompress does not
  366. // lose characters.
  367. //
  368. if(nInLen & 0x1)
  369. nInLen++;
  370. //
  371. // Allocate a BSTR of the correct length.
  372. //
  373. *pbstrCompressed = SysAllocStringByteLen(NULL, nInLen);
  374. if(*pbstrCompressed == NULL)
  375. {
  376. hr = E_OUTOFMEMORY;
  377. goto Cleanup;
  378. }
  379. //
  380. // We allocated a total of nInLen + 2 bytes. Zero it out.
  381. //
  382. memset(*pbstrCompressed, 0, nInLen + sizeof(OLECHAR));
  383. //
  384. // Convert to multibyte.
  385. //
  386. if (0 == WideCharToMultiByte(CP_ACP, 0, bstrIn, nInLen, (LPSTR)*pbstrCompressed,
  387. nInLen + 1, // this is how many bytes were allocated by
  388. // SysAllocStringByteLen
  389. NULL, NULL))
  390. {
  391. hr = E_FAIL;
  392. }
  393. else
  394. {
  395. hr = S_OK;
  396. }
  397. Cleanup:
  398. return hr;
  399. }
  400. //===========================================================================
  401. //
  402. // Decompress
  403. //
  404. STDMETHODIMP CCrypt::Decompress(
  405. BSTR bstrIn,
  406. BSTR* pbstrDecompressed
  407. )
  408. {
  409. HRESULT hr;
  410. CHAR *pch;
  411. UINT nInLen;
  412. if(bstrIn == NULL ||
  413. pbstrDecompressed == NULL)
  414. {
  415. hr = E_POINTER;
  416. goto Cleanup;
  417. }
  418. //
  419. // nInLen is number of mbc's, and does not include the terminating NULL.
  420. //
  421. nInLen = SysStringByteLen(bstrIn);
  422. //
  423. // 13386: return NULL if 0 length
  424. //
  425. if (nInLen == 0)
  426. {
  427. *pbstrDecompressed = NULL;
  428. hr = S_OK;
  429. goto Cleanup;
  430. }
  431. pch = (CHAR*)bstrIn;
  432. if ('\0' == pch[nInLen - 1])
  433. {
  434. nInLen--;
  435. }
  436. //
  437. // Allocate a BSTR of the correct length.
  438. //
  439. *pbstrDecompressed = SysAllocStringLen(NULL, nInLen);
  440. if(*pbstrDecompressed == NULL)
  441. {
  442. hr = E_OUTOFMEMORY;
  443. goto Cleanup;
  444. }
  445. //
  446. // We allocated a total of (nOutLen+1) * sizeof(OLECHAR) bytes, since
  447. // SysAllocStringLen allocs an extra character. Zero it all out.
  448. //
  449. memset(*pbstrDecompressed, 0, (nInLen + 1) * sizeof(OLECHAR));
  450. //
  451. // Convert to wide.
  452. //
  453. if (0 == MultiByteToWideChar(CP_ACP, 0, (LPCSTR)bstrIn, -1, *pbstrDecompressed, nInLen + 1))
  454. {
  455. hr = E_FAIL;
  456. }
  457. else
  458. {
  459. hr = S_OK;
  460. }
  461. Cleanup:
  462. return hr;
  463. }
  464. //===========================================================================
  465. //
  466. // put_site
  467. //
  468. STDMETHODIMP
  469. CCrypt::put_site(
  470. BSTR bstrSiteName
  471. )
  472. {
  473. HRESULT hr;
  474. int nLen;
  475. LPSTR szNewSiteName;
  476. CRegistryConfig* crc;
  477. if(!bstrSiteName)
  478. {
  479. if(m_szSiteName)
  480. delete [] m_szSiteName;
  481. m_szSiteName = NULL;
  482. }
  483. else
  484. {
  485. nLen = SysStringLen(bstrSiteName) + 1;
  486. szNewSiteName = new CHAR[nLen];
  487. if(!szNewSiteName)
  488. {
  489. hr = E_OUTOFMEMORY;
  490. goto Cleanup;
  491. }
  492. WideCharToMultiByte(CP_ACP, 0, bstrSiteName, -1,
  493. szNewSiteName, nLen,
  494. NULL,
  495. NULL);
  496. Cleanup();
  497. m_szSiteName = szNewSiteName;
  498. }
  499. crc = ObtainCRC();
  500. if (!crc)
  501. {
  502. m_keyVersion = 0;
  503. }
  504. else
  505. {
  506. m_keyVersion = crc->getCurrentCryptVersion();
  507. crc->getCrypt(m_keyVersion,&m_validUntil);
  508. crc->Release();
  509. }
  510. hr = S_OK;
  511. Cleanup:
  512. return hr;
  513. }
  514. //===========================================================================
  515. //
  516. // put_host
  517. //
  518. STDMETHODIMP
  519. CCrypt::put_host(
  520. BSTR bstrHostName
  521. )
  522. {
  523. HRESULT hr;
  524. int nLen;
  525. LPSTR szNewHostName;
  526. CRegistryConfig* crc;
  527. if(!bstrHostName)
  528. {
  529. if(m_szHostName)
  530. delete [] m_szHostName;
  531. m_szHostName = NULL;
  532. }
  533. else
  534. {
  535. nLen = SysStringLen(bstrHostName) + 1;
  536. szNewHostName = new CHAR[nLen];
  537. if(!szNewHostName)
  538. {
  539. hr = E_OUTOFMEMORY;
  540. goto Cleanup;
  541. }
  542. WideCharToMultiByte(CP_ACP, 0, bstrHostName, -1,
  543. szNewHostName, nLen,
  544. NULL,
  545. NULL);
  546. Cleanup();
  547. m_szHostName = szNewHostName;
  548. crc = ObtainCRC();
  549. if (!crc)
  550. {
  551. m_keyVersion = 0;
  552. }
  553. else
  554. {
  555. m_keyVersion = crc->getCurrentCryptVersion();
  556. crc->getCrypt(m_keyVersion,&m_validUntil);
  557. crc->Release();
  558. }
  559. }
  560. hr = S_OK;
  561. Cleanup:
  562. return hr;
  563. }
  564. //===========================================================================
  565. //
  566. // Cleanup
  567. //
  568. void CCrypt::Cleanup()
  569. {
  570. if( m_szSiteName )
  571. {
  572. delete [] m_szSiteName;
  573. m_szSiteName = NULL;
  574. }
  575. if( m_szHostName )
  576. {
  577. delete [] m_szHostName;
  578. m_szHostName = NULL;
  579. }
  580. }
  581. //===========================================================================
  582. //
  583. // ObtainCRC
  584. //
  585. CRegistryConfig* CCrypt::ObtainCRC()
  586. {
  587. CRegistryConfig* crc = NULL;
  588. if( m_szHostName && m_szSiteName )
  589. {
  590. // we are in bad state now
  591. Cleanup();
  592. goto exit;
  593. }
  594. if( m_szHostName )
  595. crc = g_config->checkoutRegistryConfig(m_szHostName);
  596. if( m_szSiteName )
  597. crc = g_config->checkoutRegistryConfigBySite(m_szSiteName);
  598. // if we still can't get crc at this moment, try the default one
  599. if( !crc )
  600. crc = g_config->checkoutRegistryConfig();
  601. exit:
  602. return crc;
  603. }
  604. /////////////////////////////////////////////////////////////////////////////
  605. // IPassportService implementation
  606. //===========================================================================
  607. //
  608. // Initialize
  609. //
  610. STDMETHODIMP CCrypt::Initialize(BSTR configfile, IServiceProvider* p)
  611. {
  612. HRESULT hr;
  613. // Initialize.
  614. if (!g_config->isValid())
  615. {
  616. AtlReportError(CLSID_Crypt, PP_E_NOT_CONFIGUREDSTR,
  617. IID_IPassportService, PP_E_NOT_CONFIGURED);
  618. hr = PP_E_NOT_CONFIGURED;
  619. goto Cleanup;
  620. }
  621. hr = S_OK;
  622. Cleanup:
  623. return hr;
  624. }
  625. //===========================================================================
  626. //
  627. // Shutdown
  628. //
  629. STDMETHODIMP CCrypt::Shutdown()
  630. {
  631. return S_OK;
  632. }
  633. //===========================================================================
  634. //
  635. // ReloadState
  636. //
  637. STDMETHODIMP CCrypt::ReloadState(IServiceProvider*)
  638. {
  639. return S_OK;
  640. }
  641. //===========================================================================
  642. //
  643. // CommitState
  644. //
  645. STDMETHODIMP CCrypt::CommitState(IServiceProvider*)
  646. {
  647. return S_OK;
  648. }
  649. //===========================================================================
  650. //
  651. // DumpState
  652. //
  653. STDMETHODIMP CCrypt::DumpState(BSTR* pbstrState)
  654. {
  655. ATLASSERT( *pbstrState != NULL &&
  656. "CCrypt:DumpState - "
  657. "Are you sure you want to hand me a non-null BSTR?" );
  658. HRESULT hr = S_OK;
  659. return hr;
  660. }