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.

1426 lines
46 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows NT Security
  4. // Copyright (C) Microsoft Corporation, 1997 - 1999
  5. //
  6. // File: inetsp.cpp
  7. //
  8. // Contents: Inet Scheme Provider for Remote Object Retrieval
  9. //
  10. // History: 06-Aug-97 kirtd Created
  11. // 01-Jan-02 philh Moved from wininet to winhttp
  12. //
  13. //----------------------------------------------------------------------------
  14. #include <global.hxx>
  15. #include "cryptver.h"
  16. #include <dbgdef.h>
  17. //+---------------------------------------------------------------------------
  18. //
  19. // Function: InetRetrieveEncodedObject
  20. //
  21. // Synopsis: retrieve encoded object via HTTP, HTTPS protocols
  22. //
  23. //----------------------------------------------------------------------------
  24. BOOL WINAPI InetRetrieveEncodedObject (
  25. IN LPCWSTR pwszUrl,
  26. IN LPCSTR pszObjectOid,
  27. IN DWORD dwRetrievalFlags,
  28. IN DWORD dwTimeout,
  29. OUT PCRYPT_BLOB_ARRAY pObject,
  30. OUT PFN_FREE_ENCODED_OBJECT_FUNC* ppfnFreeObject,
  31. OUT LPVOID* ppvFreeContext,
  32. IN HCRYPTASYNC hAsyncRetrieve,
  33. IN PCRYPT_CREDENTIALS pCredentials,
  34. IN PCRYPT_RETRIEVE_AUX_INFO pAuxInfo
  35. )
  36. {
  37. BOOL fResult;
  38. IObjectRetriever* por = NULL;
  39. if ( !( dwRetrievalFlags & CRYPT_ASYNC_RETRIEVAL ) )
  40. {
  41. por = new CInetSynchronousRetriever;
  42. }
  43. if ( por == NULL )
  44. {
  45. SetLastError( (DWORD) E_OUTOFMEMORY );
  46. return( FALSE );
  47. }
  48. fResult = por->RetrieveObjectByUrl(
  49. pwszUrl,
  50. pszObjectOid,
  51. dwRetrievalFlags,
  52. dwTimeout,
  53. (LPVOID *)pObject,
  54. ppfnFreeObject,
  55. ppvFreeContext,
  56. hAsyncRetrieve,
  57. pCredentials,
  58. NULL,
  59. pAuxInfo
  60. );
  61. por->Release();
  62. return( fResult );
  63. }
  64. //+---------------------------------------------------------------------------
  65. //
  66. // Function: InetFreeEncodedObject
  67. //
  68. // Synopsis: free encoded object retrieved via InetRetrieveEncodedObject
  69. //
  70. //----------------------------------------------------------------------------
  71. VOID WINAPI InetFreeEncodedObject (
  72. IN LPCSTR pszObjectOid,
  73. IN PCRYPT_BLOB_ARRAY pObject,
  74. IN LPVOID pvFreeContext
  75. )
  76. {
  77. assert( pvFreeContext == NULL );
  78. InetFreeCryptBlobArray( pObject );
  79. }
  80. //+---------------------------------------------------------------------------
  81. //
  82. // Function: InetCancelAsyncRetrieval
  83. //
  84. // Synopsis: cancel asynchronous object retrieval
  85. //
  86. //----------------------------------------------------------------------------
  87. BOOL WINAPI InetCancelAsyncRetrieval (
  88. IN HCRYPTASYNC hAsyncRetrieve
  89. )
  90. {
  91. SetLastError( (DWORD) E_NOTIMPL );
  92. return( FALSE );
  93. }
  94. //+---------------------------------------------------------------------------
  95. //
  96. // Member: CInetSynchronousRetriever::CInetSynchronousRetriever, public
  97. //
  98. // Synopsis: Constructor
  99. //
  100. //----------------------------------------------------------------------------
  101. CInetSynchronousRetriever::CInetSynchronousRetriever ()
  102. {
  103. m_cRefs = 1;
  104. }
  105. //+---------------------------------------------------------------------------
  106. //
  107. // Member: CInetSynchronousRetriever::~CInetSynchronousRetriever, public
  108. //
  109. // Synopsis: Destructor
  110. //
  111. //----------------------------------------------------------------------------
  112. CInetSynchronousRetriever::~CInetSynchronousRetriever ()
  113. {
  114. }
  115. //+---------------------------------------------------------------------------
  116. //
  117. // Member: CInetSynchronousRetriever::AddRef, public
  118. //
  119. // Synopsis: IRefCountedObject::AddRef
  120. //
  121. //----------------------------------------------------------------------------
  122. VOID
  123. CInetSynchronousRetriever::AddRef ()
  124. {
  125. InterlockedIncrement( (LONG *)&m_cRefs );
  126. }
  127. //+---------------------------------------------------------------------------
  128. //
  129. // Member: CInetSynchronousRetriever::Release, public
  130. //
  131. // Synopsis: IRefCountedObject::Release
  132. //
  133. //----------------------------------------------------------------------------
  134. VOID
  135. CInetSynchronousRetriever::Release ()
  136. {
  137. if ( InterlockedDecrement( (LONG *)&m_cRefs ) == 0 )
  138. {
  139. delete this;
  140. }
  141. }
  142. //+---------------------------------------------------------------------------
  143. //
  144. // Member: CInetSynchronousRetriever::RetrieveObjectByUrl, public
  145. //
  146. // Synopsis: IObjectRetriever::RetrieveObjectByUrl
  147. //
  148. //----------------------------------------------------------------------------
  149. BOOL
  150. CInetSynchronousRetriever::RetrieveObjectByUrl (
  151. LPCWSTR pwszUrl,
  152. LPCSTR pszObjectOid,
  153. DWORD dwRetrievalFlags,
  154. DWORD dwTimeout,
  155. LPVOID* ppvObject,
  156. PFN_FREE_ENCODED_OBJECT_FUNC* ppfnFreeObject,
  157. LPVOID* ppvFreeContext,
  158. HCRYPTASYNC hAsyncRetrieve,
  159. PCRYPT_CREDENTIALS pCredentials,
  160. LPVOID pvVerify,
  161. PCRYPT_RETRIEVE_AUX_INFO pAuxInfo
  162. )
  163. {
  164. BOOL fResult;
  165. DWORD LastError = 0;
  166. HINTERNET hInetSession = NULL;
  167. assert( hAsyncRetrieve == NULL );
  168. if ( ( dwRetrievalFlags & CRYPT_CACHE_ONLY_RETRIEVAL ) )
  169. {
  170. return( SchemeRetrieveCachedCryptBlobArray(
  171. pwszUrl,
  172. dwRetrievalFlags,
  173. (PCRYPT_BLOB_ARRAY)ppvObject,
  174. ppfnFreeObject,
  175. ppvFreeContext,
  176. pAuxInfo
  177. ) );
  178. }
  179. fResult = InetGetBindings(
  180. pwszUrl,
  181. dwRetrievalFlags,
  182. dwTimeout,
  183. &hInetSession
  184. );
  185. if ( fResult == TRUE )
  186. {
  187. fResult = InetSendReceiveUrlRequest(
  188. hInetSession,
  189. pwszUrl,
  190. dwRetrievalFlags,
  191. pCredentials,
  192. (PCRYPT_BLOB_ARRAY)ppvObject,
  193. pAuxInfo
  194. );
  195. }
  196. if ( fResult == TRUE )
  197. {
  198. *ppfnFreeObject = InetFreeEncodedObject;
  199. *ppvFreeContext = NULL;
  200. }
  201. else
  202. {
  203. LastError = GetLastError();
  204. }
  205. InetFreeBindings( hInetSession );
  206. SetLastError( LastError );
  207. return( fResult );
  208. }
  209. //+---------------------------------------------------------------------------
  210. //
  211. // Member: CInetSynchronousRetriever::CancelAsyncRetrieval, public
  212. //
  213. // Synopsis: IObjectRetriever::CancelAsyncRetrieval
  214. //
  215. //----------------------------------------------------------------------------
  216. BOOL
  217. CInetSynchronousRetriever::CancelAsyncRetrieval ()
  218. {
  219. SetLastError( (DWORD) E_NOTIMPL );
  220. return( FALSE );
  221. }
  222. //+---------------------------------------------------------------------------
  223. //
  224. // Function: InetGetBindings
  225. //
  226. // Synopsis: get the session bindings
  227. //
  228. //----------------------------------------------------------------------------
  229. BOOL
  230. InetGetBindings (
  231. LPCWSTR pwszUrl,
  232. DWORD dwRetrievalFlags,
  233. DWORD dwTimeout,
  234. HINTERNET* phInetSession
  235. )
  236. {
  237. BOOL fResult = TRUE;
  238. DWORD LastError = 0;
  239. HINTERNET hInetSession;
  240. WCHAR wszUserAgent[64];
  241. const DWORD cchUserAgent = sizeof(wszUserAgent) / sizeof(wszUserAgent[0]);
  242. _snwprintf(wszUserAgent, cchUserAgent - 1,
  243. L"Microsoft-CryptoAPI/%S", VER_PRODUCTVERSION_STR);
  244. wszUserAgent[cchUserAgent - 1] = L'\0';
  245. hInetSession = WinHttpOpen(
  246. wszUserAgent,
  247. WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, // dwAccessType
  248. WINHTTP_NO_PROXY_NAME, // pwszProxyName OPTIONAL
  249. WINHTTP_NO_PROXY_BYPASS, // pwszProxyBypass OPTIONAL
  250. 0 // dwFlags
  251. );
  252. if ( hInetSession == NULL )
  253. {
  254. return( FALSE );
  255. }
  256. if ( ( fResult == TRUE ) && ( dwTimeout != 0 ) )
  257. {
  258. int iTimeout = (int) dwTimeout;
  259. fResult = WinHttpSetTimeouts(
  260. hInetSession,
  261. iTimeout, // nResolveTimeout
  262. iTimeout, // nConnectTimeout
  263. iTimeout, // nSendTimeout
  264. iTimeout // nReceiveTimeout
  265. );
  266. }
  267. if ( fResult == TRUE )
  268. {
  269. DWORD dwOptionFlag;
  270. dwOptionFlag = WINHTTP_DISABLE_PASSPORT_AUTH;
  271. WinHttpSetOption(
  272. hInetSession,
  273. WINHTTP_OPTION_CONFIGURE_PASSPORT_AUTH,
  274. &dwOptionFlag,
  275. sizeof(dwOptionFlag)
  276. );
  277. }
  278. if ( fResult == TRUE )
  279. {
  280. *phInetSession = hInetSession;
  281. }
  282. else
  283. {
  284. LastError = GetLastError();
  285. WinHttpCloseHandle( hInetSession );
  286. }
  287. SetLastError( LastError );
  288. return( fResult );
  289. }
  290. //+---------------------------------------------------------------------------
  291. //
  292. // Function: InetFreeBindings
  293. //
  294. // Synopsis: free the inet session bindings
  295. //
  296. //----------------------------------------------------------------------------
  297. VOID
  298. InetFreeBindings (
  299. HINTERNET hInetSession
  300. )
  301. {
  302. if ( hInetSession != NULL )
  303. {
  304. WinHttpCloseHandle( hInetSession );
  305. }
  306. }
  307. //+=========================================================================
  308. // WinHttp doesn't support proxy failure rollover to the next proxy in
  309. // the list. When this is fixed, we can revert back to OLD_InetSetProxy.
  310. //-=========================================================================
  311. //+-------------------------------------------------------------------------
  312. // Calls the WinHttp proxy APIs to get the list of one or more proxy
  313. // servers.
  314. //
  315. // The returned *ppProxyInfo must be freed by calling PkiFree()
  316. //
  317. // For no proxy servers, TRUE is returned with *ppProxyInfo set to NULL.
  318. //--------------------------------------------------------------------------
  319. BOOL
  320. InetGetProxy(
  321. IN HINTERNET hInetSession,
  322. IN HINTERNET hInetRequest,
  323. IN LPCWSTR pwszUrl,
  324. IN DWORD dwRetrievalFlags,
  325. OUT WINHTTP_PROXY_INFO **ppProxyInfo
  326. )
  327. {
  328. BOOL fResult = TRUE;
  329. WINHTTP_PROXY_INFO *pProxyInfo = NULL;
  330. //
  331. // Detect IE settings and look up proxy if necessary.
  332. // Boilerplate from Stephen Sulzer.
  333. //
  334. // I copied from CACHED_AUTOPROXY::Generate() at
  335. // \admin\services\drizzle\newjob\downloader.cpp
  336. //
  337. WINHTTP_PROXY_INFO ProxyInfo;
  338. WINHTTP_AUTOPROXY_OPTIONS AutoProxyOptions;
  339. WINHTTP_CURRENT_USER_IE_PROXY_CONFIG IEProxyConfig;
  340. BOOL fTryAutoProxy = FALSE;
  341. BOOL fSuccess = FALSE;
  342. ZeroMemory(&ProxyInfo, sizeof(ProxyInfo));
  343. ZeroMemory(&AutoProxyOptions, sizeof(AutoProxyOptions));
  344. ZeroMemory(&IEProxyConfig, sizeof(IEProxyConfig));
  345. if (WinHttpGetIEProxyConfigForCurrentUser(&IEProxyConfig)) {
  346. if (IEProxyConfig.fAutoDetect) {
  347. AutoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
  348. fTryAutoProxy = TRUE;
  349. }
  350. if (IEProxyConfig.lpszAutoConfigUrl) {
  351. AutoProxyOptions.dwFlags |= WINHTTP_AUTOPROXY_CONFIG_URL;
  352. AutoProxyOptions.lpszAutoConfigUrl = IEProxyConfig.lpszAutoConfigUrl;
  353. fTryAutoProxy = TRUE;
  354. }
  355. AutoProxyOptions.fAutoLogonIfChallenged = TRUE;
  356. } else {
  357. // WinHttpGetIEProxyForCurrentUser failed, try autodetection anyway...
  358. AutoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
  359. fTryAutoProxy = TRUE;
  360. }
  361. if (fTryAutoProxy) {
  362. if (AutoProxyOptions.dwFlags & WINHTTP_AUTOPROXY_AUTO_DETECT) {
  363. // First try using the faster DNS_A option
  364. AutoProxyOptions.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DNS_A;
  365. fSuccess = WinHttpGetProxyForUrl( hInetSession,
  366. pwszUrl,
  367. &AutoProxyOptions,
  368. &ProxyInfo
  369. );
  370. if (!fSuccess) {
  371. DWORD dwLastErr = GetLastError();
  372. I_CryptNetDebugErrorPrintfA(
  373. "CRYPTNET.DLL --> WinHttpGetProxyForUrl(DNS) failed: %d (0x%x)\n",
  374. dwLastErr, dwLastErr);
  375. // Try again using the slower DHCP
  376. AutoProxyOptions.dwAutoDetectFlags |=
  377. WINHTTP_AUTO_DETECT_TYPE_DHCP;
  378. }
  379. }
  380. if (!fSuccess)
  381. fSuccess = WinHttpGetProxyForUrl( hInetSession,
  382. pwszUrl,
  383. &AutoProxyOptions,
  384. &ProxyInfo
  385. );
  386. if (fSuccess &&
  387. WINHTTP_ACCESS_TYPE_NO_PROXY == ProxyInfo.dwAccessType &&
  388. !(dwRetrievalFlags & CRYPT_NO_AUTH_RETRIEVAL))
  389. {
  390. // Need to set to low to allow access to such internal sites as:
  391. // http://msw, http://hrweb
  392. DWORD dwOptionFlag = WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW;
  393. if (!WinHttpSetOption(
  394. hInetRequest,
  395. WINHTTP_OPTION_AUTOLOGON_POLICY,
  396. &dwOptionFlag,
  397. sizeof(dwOptionFlag)
  398. ))
  399. {
  400. DWORD dwLastErr = GetLastError();
  401. I_CryptNetDebugErrorPrintfA(
  402. "CRYPTNET.DLL --> WinHttpSetOption(WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW) failed: %d (0x%x)\n",
  403. dwLastErr, dwLastErr);
  404. }
  405. }
  406. }
  407. // If we didn't do autoproxy or if it failed, see
  408. // if there's an explicit proxy server in the IE
  409. // proxy configuration...
  410. //
  411. // This is where the WinHttpGetIEProxyConfigForCurrentUser API
  412. // really comes in handy: in environments in which autoproxy is
  413. // not supported and so the user's IE browser must be
  414. // configured with an explicit proxy server.
  415. //
  416. if (!fTryAutoProxy || !fSuccess) {
  417. if (IEProxyConfig.lpszProxy) {
  418. ProxyInfo.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
  419. ProxyInfo.lpszProxy = IEProxyConfig.lpszProxy;
  420. IEProxyConfig.lpszProxy = NULL;
  421. ProxyInfo.lpszProxyBypass = IEProxyConfig.lpszProxyBypass;
  422. IEProxyConfig.lpszProxyBypass = NULL;
  423. }
  424. }
  425. I_CryptNetDebugTracePrintfA(
  426. "CRYPTNET.DLL --> ProxyInfo:: AccessType:%d Proxy:%S ProxyByPass:%S\n",
  427. ProxyInfo.dwAccessType,
  428. ProxyInfo.lpszProxy,
  429. ProxyInfo.lpszProxyBypass
  430. );
  431. if (NULL != ProxyInfo.lpszProxy) {
  432. DWORD cbProxyInfo;
  433. DWORD cchProxy; // including NULL terminator
  434. DWORD cchProxyBypass; // including NULL terminator
  435. cchProxy = wcslen(ProxyInfo.lpszProxy) + 1;
  436. if (NULL != ProxyInfo.lpszProxyBypass) {
  437. cchProxyBypass = wcslen(ProxyInfo.lpszProxyBypass) + 1;
  438. } else {
  439. cchProxyBypass = 0;
  440. }
  441. cbProxyInfo = sizeof(ProxyInfo) +
  442. (cchProxy + cchProxyBypass) * sizeof(WCHAR);
  443. pProxyInfo = (WINHTTP_PROXY_INFO *) PkiNonzeroAlloc(cbProxyInfo);
  444. if (NULL == pProxyInfo) {
  445. fResult = FALSE;
  446. } else {
  447. *pProxyInfo = ProxyInfo;
  448. pProxyInfo->lpszProxy = (LPWSTR) &pProxyInfo[1];
  449. memcpy(pProxyInfo->lpszProxy, ProxyInfo.lpszProxy,
  450. cchProxy * sizeof(WCHAR));
  451. if (0 != cchProxyBypass) {
  452. pProxyInfo->lpszProxyBypass = pProxyInfo->lpszProxy + cchProxy;
  453. memcpy(pProxyInfo->lpszProxyBypass, ProxyInfo.lpszProxyBypass,
  454. cchProxyBypass * sizeof(WCHAR));
  455. } else {
  456. assert(NULL == pProxyInfo->lpszProxyBypass);
  457. }
  458. }
  459. }
  460. if (IEProxyConfig.lpszAutoConfigUrl)
  461. GlobalFree(IEProxyConfig.lpszAutoConfigUrl);
  462. if (IEProxyConfig.lpszProxy)
  463. GlobalFree(IEProxyConfig.lpszProxy);
  464. if (IEProxyConfig.lpszProxyBypass)
  465. GlobalFree(IEProxyConfig.lpszProxyBypass);
  466. if (ProxyInfo.lpszProxy)
  467. GlobalFree(ProxyInfo.lpszProxy);
  468. if (ProxyInfo.lpszProxyBypass)
  469. GlobalFree(ProxyInfo.lpszProxyBypass);
  470. *ppProxyInfo = pProxyInfo;
  471. return fResult;
  472. }
  473. //+-------------------------------------------------------------------------
  474. // Update both the Session and Request handles with proxy list.
  475. // Currently, WinHttp only uses the first proxy server in the list.
  476. //
  477. // Also, for proxies to work using https, it must also be set on the
  478. // session handle.
  479. //--------------------------------------------------------------------------
  480. BOOL
  481. InetSetProxy(
  482. IN HINTERNET hInetSession,
  483. IN HINTERNET hInetRequest,
  484. IN WINHTTP_PROXY_INFO *pProxyInfo
  485. )
  486. {
  487. BOOL fResult;
  488. if (NULL == pProxyInfo || NULL == pProxyInfo->lpszProxy) {
  489. return TRUE;
  490. }
  491. //
  492. // Set the proxy on the session handle
  493. //
  494. fResult = WinHttpSetOption( hInetSession,
  495. WINHTTP_OPTION_PROXY,
  496. pProxyInfo,
  497. sizeof(*pProxyInfo)
  498. );
  499. if (fResult) {
  500. //
  501. // Now set the proxy on the request handle.
  502. //
  503. fResult = WinHttpSetOption( hInetRequest,
  504. WINHTTP_OPTION_PROXY,
  505. pProxyInfo,
  506. sizeof(*pProxyInfo)
  507. );
  508. }
  509. return fResult;
  510. }
  511. //+-------------------------------------------------------------------------
  512. // Since WinHttp doesn't support proxy rollover we will advance to the
  513. // next proxy if WinHttpSendRequest returns one of the following errors.
  514. //--------------------------------------------------------------------------
  515. BOOL
  516. InetIsPossibleBadProxy(
  517. IN DWORD dwErr
  518. )
  519. {
  520. switch (dwErr) {
  521. case ERROR_WINHTTP_NAME_NOT_RESOLVED:
  522. case ERROR_WINHTTP_CANNOT_CONNECT:
  523. case ERROR_WINHTTP_CONNECTION_ERROR:
  524. case ERROR_WINHTTP_TIMEOUT:
  525. return TRUE;
  526. default:
  527. return FALSE;
  528. }
  529. }
  530. //+-------------------------------------------------------------------------
  531. // Advances the lpszProxy to point to the next proxy in the list. Assumes
  532. // that ";" is the delimiter and no proxy server contains this in their
  533. // name.
  534. //
  535. // LastError is preserved. Returns TRUE if successfully found and set the
  536. // next proxy.
  537. //--------------------------------------------------------------------------
  538. BOOL
  539. InetSetNextProxy(
  540. IN HINTERNET hInetSession,
  541. IN HINTERNET hInetRequest,
  542. IN OUT WINHTTP_PROXY_INFO *pProxyInfo
  543. )
  544. {
  545. BOOL fResult = FALSE;
  546. if (NULL != pProxyInfo && NULL != pProxyInfo->lpszProxy) {
  547. DWORD dwLastError = GetLastError();
  548. LPWSTR lpszProxy = pProxyInfo->lpszProxy;
  549. I_CryptNetDebugErrorPrintfA(
  550. "CRYPTNET.DLL --> Error:: %d (0x%x) Bad Proxy:%S\n",
  551. dwLastError, dwLastError, lpszProxy);
  552. // Assumption:: L';' is used to separater proxy names
  553. while (L'\0' != *lpszProxy && L';' != *lpszProxy) {
  554. lpszProxy++;
  555. }
  556. if (L';' == *lpszProxy) {
  557. lpszProxy++;
  558. // Skip any leading whitespace
  559. while (iswspace(*lpszProxy)) {
  560. lpszProxy++;
  561. }
  562. }
  563. if (L'\0' == *lpszProxy) {
  564. pProxyInfo->lpszProxy = NULL;
  565. } else {
  566. pProxyInfo->lpszProxy = lpszProxy;
  567. fResult = InetSetProxy(
  568. hInetSession,
  569. hInetRequest,
  570. pProxyInfo
  571. );
  572. }
  573. SetLastError(dwLastError);
  574. }
  575. return fResult;
  576. }
  577. #if 0
  578. //+-------------------------------------------------------------------------
  579. // When WinHttp is fixed to support proxy fail rollover, we can revert
  580. // back to this simpler proxy function.
  581. //--------------------------------------------------------------------------
  582. BOOL
  583. OLD_InetSetProxy(
  584. IN HINTERNET hInetSession,
  585. IN HINTERNET hInetRequest,
  586. IN LPCWSTR pwszUrl,
  587. IN DWORD dwRetrievalFlags
  588. )
  589. {
  590. BOOL fResult = TRUE;
  591. //
  592. // Detect IE settings and look up proxy if necessary.
  593. // Boilerplate from Stephen Sulzer.
  594. //
  595. // I copied from CACHED_AUTOPROXY::Generate() at
  596. // \admin\services\drizzle\newjob\downloader.cpp
  597. //
  598. WINHTTP_PROXY_INFO ProxyInfo;
  599. WINHTTP_AUTOPROXY_OPTIONS AutoProxyOptions;
  600. WINHTTP_CURRENT_USER_IE_PROXY_CONFIG IEProxyConfig;
  601. BOOL fTryAutoProxy = FALSE;
  602. BOOL fSuccess = FALSE;
  603. ZeroMemory(&ProxyInfo, sizeof(ProxyInfo));
  604. ZeroMemory(&AutoProxyOptions, sizeof(AutoProxyOptions));
  605. ZeroMemory(&IEProxyConfig, sizeof(IEProxyConfig));
  606. if (WinHttpGetIEProxyConfigForCurrentUser(&IEProxyConfig)) {
  607. if (IEProxyConfig.fAutoDetect) {
  608. AutoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
  609. fTryAutoProxy = TRUE;
  610. }
  611. if (IEProxyConfig.lpszAutoConfigUrl) {
  612. AutoProxyOptions.dwFlags |= WINHTTP_AUTOPROXY_CONFIG_URL;
  613. AutoProxyOptions.lpszAutoConfigUrl = IEProxyConfig.lpszAutoConfigUrl;
  614. fTryAutoProxy = TRUE;
  615. }
  616. AutoProxyOptions.fAutoLogonIfChallenged = TRUE;
  617. } else {
  618. // WinHttpGetIEProxyForCurrentUser failed, try autodetection anyway...
  619. AutoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
  620. fTryAutoProxy = TRUE;
  621. }
  622. if (fTryAutoProxy) {
  623. if (AutoProxyOptions.dwFlags & WINHTTP_AUTOPROXY_AUTO_DETECT) {
  624. // First try using the faster DNS_A option
  625. AutoProxyOptions.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DNS_A;
  626. fSuccess = WinHttpGetProxyForUrl( hInetSession,
  627. pwszUrl,
  628. &AutoProxyOptions,
  629. &ProxyInfo
  630. );
  631. if (!fSuccess) {
  632. DWORD dwLastErr = GetLastError();
  633. I_CryptNetDebugErrorPrintfA(
  634. "CRYPTNET.DLL --> WinHttpGetProxyForUrl(DNS) failed: %d (0x%x)\n",
  635. dwLastErr, dwLastErr);
  636. // Try again using the slower DHCP
  637. AutoProxyOptions.dwAutoDetectFlags |=
  638. WINHTTP_AUTO_DETECT_TYPE_DHCP;
  639. }
  640. }
  641. if (!fSuccess)
  642. fSuccess = WinHttpGetProxyForUrl( hInetSession,
  643. pwszUrl,
  644. &AutoProxyOptions,
  645. &ProxyInfo
  646. );
  647. if (fSuccess &&
  648. WINHTTP_ACCESS_TYPE_NO_PROXY == ProxyInfo.dwAccessType &&
  649. !(dwRetrievalFlags & CRYPT_NO_AUTH_RETRIEVAL))
  650. {
  651. // Need to set to low to allow access to such internal sites as:
  652. // http://msw, http://hrweb
  653. DWORD dwOptionFlag = WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW;
  654. if (!WinHttpSetOption(
  655. hInetRequest,
  656. WINHTTP_OPTION_AUTOLOGON_POLICY,
  657. &dwOptionFlag,
  658. sizeof(dwOptionFlag)
  659. ))
  660. {
  661. DWORD dwLastErr = GetLastError();
  662. I_CryptNetDebugErrorPrintfA(
  663. "CRYPTNET.DLL --> WinHttpSetOption(WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW) failed: %d (0x%x)\n",
  664. dwLastErr, dwLastErr);
  665. }
  666. }
  667. }
  668. // If we didn't do autoproxy or if it failed, see
  669. // if there's an explicit proxy server in the IE
  670. // proxy configuration...
  671. //
  672. // This is where the WinHttpGetIEProxyConfigForCurrentUser API
  673. // really comes in handy: in environments in which autoproxy is
  674. // not supported and so the user's IE browser must be
  675. // configured with an explicit proxy server.
  676. //
  677. if (!fTryAutoProxy || !fSuccess) {
  678. if (IEProxyConfig.lpszProxy) {
  679. ProxyInfo.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
  680. ProxyInfo.lpszProxy = IEProxyConfig.lpszProxy;
  681. IEProxyConfig.lpszProxy = NULL;
  682. ProxyInfo.lpszProxyBypass = IEProxyConfig.lpszProxyBypass;
  683. IEProxyConfig.lpszProxyBypass = NULL;
  684. }
  685. }
  686. I_CryptNetDebugTracePrintfA(
  687. "CRYPTNET.DLL --> ProxyInfo:: AccessType:%d Proxy:%S ProxyByPass:%S\n",
  688. ProxyInfo.dwAccessType,
  689. ProxyInfo.lpszProxy,
  690. ProxyInfo.lpszProxyBypass
  691. );
  692. if (NULL != ProxyInfo.lpszProxy) {
  693. //
  694. // Set the proxy on the session handle
  695. //
  696. fResult = WinHttpSetOption( hInetSession,
  697. WINHTTP_OPTION_PROXY,
  698. &ProxyInfo,
  699. sizeof(ProxyInfo)
  700. );
  701. if (fResult)
  702. //
  703. // Now set the proxy on the request handle.
  704. //
  705. fResult = WinHttpSetOption( hInetRequest,
  706. WINHTTP_OPTION_PROXY,
  707. &ProxyInfo,
  708. sizeof(ProxyInfo)
  709. );
  710. }
  711. if (IEProxyConfig.lpszAutoConfigUrl)
  712. GlobalFree(IEProxyConfig.lpszAutoConfigUrl);
  713. if (IEProxyConfig.lpszProxy)
  714. GlobalFree(IEProxyConfig.lpszProxy);
  715. if (IEProxyConfig.lpszProxyBypass)
  716. GlobalFree(IEProxyConfig.lpszProxyBypass);
  717. if (ProxyInfo.lpszProxy)
  718. GlobalFree(ProxyInfo.lpszProxy);
  719. if (ProxyInfo.lpszProxyBypass)
  720. GlobalFree(ProxyInfo.lpszProxyBypass);
  721. return fResult;
  722. }
  723. #endif
  724. //+-------------------------------------------------------------------------
  725. // Handles all of the possible errors that WinHttp can return
  726. // when sending the request.
  727. //--------------------------------------------------------------------------
  728. BOOL
  729. InetSendAuthenticatedRequestAndReceiveResponse(
  730. IN HINTERNET hInetSession,
  731. IN HINTERNET hInetRequest,
  732. IN LPCWSTR pwszUrl,
  733. IN DWORD dwRetrievalFlags,
  734. IN PCRYPT_CREDENTIALS pCredentials
  735. )
  736. {
  737. BOOL fResult;
  738. DWORD dwLastError = 0;
  739. DWORD dwStatus = HTTP_STATUS_BAD_REQUEST;
  740. CRYPT_PASSWORD_CREDENTIALSW PasswordCredentials;
  741. BOOL fFreeCredentials = FALSE;
  742. LPWSTR pwszUserName = NULL; // not allocated
  743. LPWSTR pwszPassword = NULL; // not allocated
  744. #define INET_MAX_RESEND_REQUEST_COUNT 5
  745. DWORD dwResendRequestCount = 0;
  746. #define INET_SET_PROXY_OR_SERVER_CRED_STATE 0
  747. #define INET_SET_ONLY_SERVER_CRED_STATE 1
  748. #define INET_SET_NO_CRED_STATE 2
  749. DWORD dwSetCredState = INET_SET_NO_CRED_STATE;
  750. #define INET_MAX_BAD_PROXY_COUNT 3
  751. DWORD dwBadProxyCount = 0;
  752. WINHTTP_PROXY_INFO *pProxyInfo = NULL;
  753. if (NULL != pCredentials) {
  754. memset( &PasswordCredentials, 0, sizeof( PasswordCredentials ) );
  755. PasswordCredentials.cbSize = sizeof( PasswordCredentials );
  756. if (!SchemeGetPasswordCredentialsW(
  757. pCredentials,
  758. &PasswordCredentials,
  759. &fFreeCredentials
  760. ))
  761. goto GetPasswordCredentialsError;
  762. pwszUserName = PasswordCredentials.pszUsername;
  763. pwszPassword = PasswordCredentials.pszPassword;
  764. dwSetCredState = INET_SET_PROXY_OR_SERVER_CRED_STATE;
  765. }
  766. if (!InetGetProxy(
  767. hInetSession,
  768. hInetRequest,
  769. pwszUrl,
  770. dwRetrievalFlags,
  771. &pProxyInfo
  772. ))
  773. goto GetProxyError;
  774. if (!InetSetProxy(
  775. hInetSession,
  776. hInetRequest,
  777. pProxyInfo
  778. ))
  779. goto SetProxyError;
  780. while (TRUE) {
  781. DWORD dwSizeofStatus;
  782. DWORD dwIndex;
  783. DWORD dwSetCredAuthTarget;
  784. if (!WinHttpSendRequest(
  785. hInetRequest,
  786. WINHTTP_NO_ADDITIONAL_HEADERS, // pwszHeaders
  787. 0, // dwHeadersLength
  788. WINHTTP_NO_REQUEST_DATA, // lpOptional
  789. 0, // dwOptionalLength
  790. 0, // dwTotalLength
  791. 0 // dwContext
  792. )) {
  793. dwLastError = GetLastError();
  794. if (ERROR_WINHTTP_RESEND_REQUEST == dwLastError) {
  795. dwResendRequestCount++;
  796. if (INET_MAX_RESEND_REQUEST_COUNT < dwResendRequestCount)
  797. goto ExceededMaxResendRequestCount;
  798. else
  799. continue;
  800. } else if (InetIsPossibleBadProxy(dwLastError)) {
  801. dwBadProxyCount++;
  802. if (INET_MAX_BAD_PROXY_COUNT <= dwBadProxyCount)
  803. goto ExceededMaxBadProxyCount;
  804. if (InetSetNextProxy(
  805. hInetSession,
  806. hInetRequest,
  807. pProxyInfo
  808. ))
  809. continue;
  810. }
  811. goto WinHttpSendRequestError;
  812. }
  813. dwResendRequestCount = 0;
  814. if (!WinHttpReceiveResponse(
  815. hInetRequest,
  816. NULL // lpReserved
  817. ))
  818. goto WinHttpReceiveResponseError;
  819. if (I_CryptNetIsDebugTracePrintEnabled()) {
  820. for (DWORD i = 0; i < 2; i++) {
  821. BYTE rgbBuf[4096];
  822. DWORD cbBuf;
  823. DWORD dwInfo;
  824. memset(rgbBuf, 0, sizeof(rgbBuf));
  825. cbBuf = sizeof(rgbBuf);
  826. dwInfo = WINHTTP_QUERY_RAW_HEADERS_CRLF;
  827. if (0 == i)
  828. dwInfo |= WINHTTP_QUERY_FLAG_REQUEST_HEADERS;
  829. dwIndex = 0;
  830. if (WinHttpQueryHeaders(
  831. hInetRequest,
  832. dwInfo,
  833. WINHTTP_HEADER_NAME_BY_INDEX, // pwszName OPTIONAL
  834. rgbBuf,
  835. &cbBuf,
  836. &dwIndex
  837. )) {
  838. if (0 == i)
  839. I_CryptNetDebugPrintfA(
  840. "CRYPTNET.DLL --> Request Headers::\n");
  841. else
  842. I_CryptNetDebugPrintfA(
  843. "CRYPTNET.DLL --> Response Headers::\n");
  844. I_CryptNetDebugPrintfA("%S", rgbBuf);
  845. }
  846. }
  847. }
  848. dwSizeofStatus = sizeof( dwStatus );
  849. dwIndex = 0;
  850. if (!WinHttpQueryHeaders(
  851. hInetRequest,
  852. WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
  853. WINHTTP_HEADER_NAME_BY_INDEX, // pwszName OPTIONAL
  854. &dwStatus,
  855. &dwSizeofStatus,
  856. &dwIndex
  857. ))
  858. goto WinHttpQueryStatusCodeError;
  859. switch (dwStatus) {
  860. case HTTP_STATUS_OK:
  861. goto SuccessReturn;
  862. break;
  863. case HTTP_STATUS_PROXY_AUTH_REQ:
  864. if (INET_SET_PROXY_OR_SERVER_CRED_STATE < dwSetCredState)
  865. goto BadHttpProxyAuthStatus;
  866. dwSetCredState = INET_SET_ONLY_SERVER_CRED_STATE;
  867. dwSetCredAuthTarget = WINHTTP_AUTH_TARGET_PROXY;
  868. break;
  869. case HTTP_STATUS_DENIED:
  870. if (INET_SET_ONLY_SERVER_CRED_STATE < dwSetCredState)
  871. goto BadHttpServerAuthStatus;
  872. dwSetCredState = INET_SET_NO_CRED_STATE;
  873. dwSetCredAuthTarget = WINHTTP_AUTH_TARGET_SERVER;
  874. break;
  875. default:
  876. goto BadHttpStatus;
  877. }
  878. {
  879. DWORD dwSupportedSchemes = 0;
  880. DWORD dwPreferredScheme = 0;
  881. DWORD dwAuthTarget = 0;
  882. DWORD dwSetCredScheme;
  883. assert(HTTP_STATUS_PROXY_AUTH_REQ == dwStatus ||
  884. HTTP_STATUS_DENIED == dwStatus);
  885. if (!WinHttpQueryAuthSchemes(
  886. hInetRequest,
  887. &dwSupportedSchemes,
  888. &dwPreferredScheme,
  889. &dwAuthTarget
  890. ))
  891. goto WinHttpQueryAuthSchemesError;
  892. if (dwAuthTarget != dwSetCredAuthTarget)
  893. goto InvalidQueryAuthTarget;
  894. if (dwSupportedSchemes & WINHTTP_AUTH_SCHEME_NEGOTIATE)
  895. dwSetCredScheme = WINHTTP_AUTH_SCHEME_NEGOTIATE;
  896. else if (dwSupportedSchemes & WINHTTP_AUTH_SCHEME_NTLM)
  897. dwSetCredScheme = WINHTTP_AUTH_SCHEME_NTLM;
  898. else
  899. goto UnsupportedAuthScheme;
  900. if (!WinHttpSetCredentials(
  901. hInetRequest,
  902. dwSetCredAuthTarget,
  903. dwSetCredScheme,
  904. pwszUserName,
  905. pwszPassword,
  906. NULL // pvAuthParams
  907. ))
  908. goto WinHttpSetCredentialsError;
  909. }
  910. }
  911. SuccessReturn:
  912. fResult = TRUE;
  913. CommonReturn:
  914. PkiFree(pProxyInfo);
  915. if (fFreeCredentials)
  916. SchemeFreePasswordCredentialsW(&PasswordCredentials);
  917. SetLastError(dwLastError);
  918. return fResult;
  919. ErrorReturn:
  920. fResult = FALSE;
  921. dwLastError = GetLastError();
  922. goto CommonReturn;
  923. TRACE_ERROR(GetPasswordCredentialsError)
  924. TRACE_ERROR(GetProxyError)
  925. TRACE_ERROR(SetProxyError)
  926. TRACE_ERROR(ExceededMaxResendRequestCount)
  927. TRACE_ERROR(ExceededMaxBadProxyCount)
  928. TRACE_ERROR(WinHttpSendRequestError)
  929. TRACE_ERROR(WinHttpReceiveResponseError)
  930. TRACE_ERROR(WinHttpQueryStatusCodeError)
  931. TRACE_ERROR(WinHttpQueryAuthSchemesError)
  932. TRACE_ERROR(WinHttpSetCredentialsError)
  933. SET_ERROR_VAR(BadHttpStatus, dwStatus)
  934. SET_ERROR_VAR(BadHttpProxyAuthStatus, dwStatus)
  935. SET_ERROR_VAR(BadHttpServerAuthStatus, dwStatus)
  936. SET_ERROR_VAR(InvalidQueryAuthTarget, dwStatus)
  937. SET_ERROR_VAR(UnsupportedAuthScheme, dwStatus)
  938. }
  939. //+---------------------------------------------------------------------------
  940. //
  941. // Function: InetSendReceiveUrlRequest
  942. //
  943. // Synopsis: synchronous processing of an URL via WinInet
  944. //
  945. //----------------------------------------------------------------------------
  946. BOOL
  947. InetSendReceiveUrlRequest (
  948. HINTERNET hInetSession,
  949. LPCWSTR pwszUrl,
  950. DWORD dwRetrievalFlags,
  951. PCRYPT_CREDENTIALS pCredentials,
  952. PCRYPT_BLOB_ARRAY pcba,
  953. PCRYPT_RETRIEVE_AUX_INFO pAuxInfo
  954. )
  955. {
  956. BOOL fResult;
  957. DWORD dwLastError = 0;
  958. HINTERNET hInetConnect = NULL;
  959. HINTERNET hInetRequest = NULL;;
  960. URL_COMPONENTS UrlComponents;
  961. PCRYPTNET_CANCEL_BLOCK pCancelBlock=NULL;
  962. LPCWSTR pwszEmpty = L"";
  963. LPWSTR pwszHostName = NULL;
  964. LPWSTR pwszUrlPathPlusExtraInfo = NULL;
  965. LPCWSTR rgpwszAcceptTypes[] = { L"*/*", NULL };
  966. DWORD dwOpenRequestFlags = 0;
  967. LPBYTE pb = NULL;
  968. ULONG cbRead;
  969. ULONG cb;
  970. DWORD dwMaxUrlRetrievalByteCount = 0; // 0 => no max
  971. BOOL fCacheBlob;
  972. if (pAuxInfo &&
  973. offsetof(CRYPT_RETRIEVE_AUX_INFO, dwMaxUrlRetrievalByteCount) <
  974. pAuxInfo->cbSize)
  975. dwMaxUrlRetrievalByteCount = pAuxInfo->dwMaxUrlRetrievalByteCount;
  976. // Extract the HostName and UrlPath from the URL string
  977. memset( &UrlComponents, 0, sizeof( UrlComponents ) );
  978. UrlComponents.dwStructSize = sizeof( UrlComponents );
  979. UrlComponents.dwHostNameLength = (DWORD) -1;
  980. UrlComponents.dwUrlPathLength = (DWORD) -1;
  981. UrlComponents.dwExtraInfoLength = (DWORD) -1;
  982. if (!WinHttpCrackUrl(
  983. pwszUrl,
  984. 0, // dwUrlLength, 0 implies null terminated
  985. 0, // dwCanonicalizeFlags
  986. &UrlComponents
  987. ))
  988. goto WinHttpCrackUrlError;
  989. if (NULL == UrlComponents.lpszHostName) {
  990. UrlComponents.dwHostNameLength = 0;
  991. UrlComponents.lpszHostName = (LPWSTR) pwszEmpty;
  992. }
  993. if (NULL == UrlComponents.lpszUrlPath) {
  994. UrlComponents.dwUrlPathLength = 0;
  995. UrlComponents.lpszUrlPath = (LPWSTR) pwszEmpty;
  996. }
  997. if (NULL == UrlComponents.lpszExtraInfo) {
  998. UrlComponents.dwExtraInfoLength = 0;
  999. UrlComponents.lpszExtraInfo = (LPWSTR) pwszEmpty;
  1000. }
  1001. pwszHostName = (LPWSTR) PkiNonzeroAlloc(
  1002. (UrlComponents.dwHostNameLength + 1) * sizeof(WCHAR));
  1003. pwszUrlPathPlusExtraInfo = (LPWSTR) PkiNonzeroAlloc(
  1004. (UrlComponents.dwUrlPathLength +
  1005. UrlComponents.dwExtraInfoLength + 1) * sizeof(WCHAR));
  1006. if (NULL == pwszHostName || NULL == pwszUrlPathPlusExtraInfo)
  1007. goto OutOfMemory;
  1008. memcpy(pwszHostName, UrlComponents.lpszHostName,
  1009. UrlComponents.dwHostNameLength * sizeof(WCHAR));
  1010. pwszHostName[UrlComponents.dwHostNameLength] = L'\0';
  1011. memcpy(pwszUrlPathPlusExtraInfo, UrlComponents.lpszUrlPath,
  1012. UrlComponents.dwUrlPathLength * sizeof(WCHAR));
  1013. memcpy(pwszUrlPathPlusExtraInfo + UrlComponents.dwUrlPathLength,
  1014. UrlComponents.lpszExtraInfo,
  1015. UrlComponents.dwExtraInfoLength * sizeof(WCHAR));
  1016. pwszUrlPathPlusExtraInfo[
  1017. UrlComponents.dwUrlPathLength +
  1018. UrlComponents.dwExtraInfoLength] = L'\0';
  1019. hInetConnect = WinHttpConnect(
  1020. hInetSession,
  1021. pwszHostName,
  1022. UrlComponents.nPort,
  1023. 0 // dwReserved
  1024. );
  1025. if (NULL == hInetConnect)
  1026. goto WinHttpConnectError;
  1027. if ( !(dwRetrievalFlags & CRYPT_AIA_RETRIEVAL) ) {
  1028. dwOpenRequestFlags |= WINHTTP_FLAG_BYPASS_PROXY_CACHE;
  1029. }
  1030. hInetRequest = WinHttpOpenRequest(
  1031. hInetConnect,
  1032. NULL, // pwszVerb, NULL implies GET
  1033. pwszUrlPathPlusExtraInfo, // pwszObjectName
  1034. NULL, // pwszVersion, NULL implies HTTP/1.1
  1035. WINHTTP_NO_REFERER, // pwszReferrer
  1036. rgpwszAcceptTypes,
  1037. dwOpenRequestFlags
  1038. );
  1039. if (NULL == hInetRequest)
  1040. goto WinHttpOpenRequestError;
  1041. if (dwRetrievalFlags & CRYPT_NO_AUTH_RETRIEVAL) {
  1042. DWORD dwOptionFlag;
  1043. dwOptionFlag = WINHTTP_AUTOLOGON_SECURITY_LEVEL_HIGH;
  1044. if (!WinHttpSetOption(
  1045. hInetRequest,
  1046. WINHTTP_OPTION_AUTOLOGON_POLICY,
  1047. &dwOptionFlag,
  1048. sizeof(dwOptionFlag)
  1049. ))
  1050. goto SetAutoLogonSecurityOptionError;
  1051. dwOptionFlag = WINHTTP_DISABLE_AUTHENTICATION;
  1052. if (!WinHttpSetOption(
  1053. hInetRequest,
  1054. WINHTTP_OPTION_DISABLE_FEATURE,
  1055. &dwOptionFlag,
  1056. sizeof(dwOptionFlag)
  1057. ))
  1058. goto SetDisableAuthenticationOptionError;
  1059. }
  1060. #if 0
  1061. if (!OLD_InetSetProxy(hInetSession, hInetRequest, pwszUrl, dwRetrievalFlags))
  1062. goto SetProxyError;
  1063. #endif
  1064. if (!InetSendAuthenticatedRequestAndReceiveResponse(
  1065. hInetSession,
  1066. hInetRequest,
  1067. pwszUrl,
  1068. dwRetrievalFlags,
  1069. pCredentials
  1070. ))
  1071. goto InetSendAuthenticatedRequestAndReceiveResponseError;
  1072. cbRead = 0;
  1073. cb = INET_INITIAL_DATA_BUFFER_SIZE;
  1074. pb = CCryptBlobArray::AllocBlob( cb );
  1075. if (NULL == pb)
  1076. goto OutOfMemory;
  1077. pCancelBlock=(PCRYPTNET_CANCEL_BLOCK)I_CryptGetTls(hCryptNetCancelTls);
  1078. while (TRUE) {
  1079. ULONG cbData;
  1080. ULONG cbPerRead;
  1081. if (pCancelBlock) {
  1082. if (pCancelBlock->pfnCancel(0, pCancelBlock->pvArg))
  1083. goto CanceledRead;
  1084. }
  1085. cbData = 0;
  1086. if (!WinHttpQueryDataAvailable(hInetRequest, &cbData) || 0 == cbData)
  1087. break;
  1088. if (0 != dwMaxUrlRetrievalByteCount &&
  1089. (cbRead + cbData) > dwMaxUrlRetrievalByteCount) {
  1090. I_CryptNetDebugErrorPrintfA(
  1091. "CRYPTNET.DLL --> Exceeded MaxUrlRetrievalByteCount for: %S\n",
  1092. pwszUrl);
  1093. goto ExceededMaxUrlRetrievalByteCount;
  1094. }
  1095. if (cb < (cbRead + cbData)) {
  1096. BYTE *pbRealloc;
  1097. pbRealloc = CCryptBlobArray::ReallocBlob(
  1098. pb,
  1099. cb + cbData + INET_GROW_DATA_BUFFER_SIZE
  1100. );
  1101. if (NULL == pbRealloc)
  1102. goto OutOfMemory;
  1103. pb = pbRealloc;
  1104. cb += cbData + INET_GROW_DATA_BUFFER_SIZE;
  1105. }
  1106. cbPerRead = 0;
  1107. if (!WinHttpReadData(
  1108. hInetRequest,
  1109. pb+cbRead,
  1110. cbData,
  1111. &cbPerRead
  1112. ))
  1113. goto WinHttpReadDataError;
  1114. cbRead += cbPerRead;
  1115. }
  1116. {
  1117. fResult = TRUE;
  1118. CCryptBlobArray cba( 1, 1, fResult );
  1119. if (fResult)
  1120. fResult = cba.AddBlob( cbRead, pb, FALSE );
  1121. if (fResult)
  1122. cba.GetArrayInNativeForm(pcba);
  1123. else {
  1124. cba.FreeArray( FALSE );
  1125. goto OutOfMemory;
  1126. }
  1127. }
  1128. fCacheBlob = FALSE;
  1129. if ( !( dwRetrievalFlags & CRYPT_DONT_CACHE_RESULT ) ) {
  1130. if ( dwRetrievalFlags & CRYPT_AIA_RETRIEVAL ) {
  1131. assert(0 < pcba->cBlob);
  1132. // Only cache if we are able to decode it.
  1133. fCacheBlob = CryptQueryObject(
  1134. CERT_QUERY_OBJECT_BLOB,
  1135. (const void *) &(pcba->rgBlob[0]),
  1136. CERT_QUERY_CONTENT_FLAG_CERT |
  1137. CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED |
  1138. CERT_QUERY_CONTENT_FLAG_CERT_PAIR,
  1139. CERT_QUERY_FORMAT_FLAG_ALL,
  1140. 0, // dwFlags
  1141. NULL, // pdwMsgAndCertEncodingType
  1142. NULL, // pdwContentType
  1143. NULL, // pdwFormatType
  1144. NULL, // phCertStore
  1145. NULL, // phMsg
  1146. NULL // ppvContext
  1147. );
  1148. if (!fCacheBlob) {
  1149. I_CryptNetDebugErrorPrintfA(
  1150. "CRYPTNET.DLL --> Invalid AIA content, no caching: %S\n",
  1151. pwszUrl);
  1152. }
  1153. } else {
  1154. fCacheBlob = TRUE;
  1155. }
  1156. if (fCacheBlob)
  1157. fCacheBlob = SchemeCacheCryptBlobArray(
  1158. pwszUrl,
  1159. dwRetrievalFlags,
  1160. pcba,
  1161. pAuxInfo
  1162. );
  1163. }
  1164. if (!fCacheBlob) {
  1165. if (!SchemeRetrieveUncachedAuxInfo(pAuxInfo))
  1166. goto RetrieveUncachedAuxInfoError;
  1167. }
  1168. fResult = TRUE;
  1169. CommonReturn:
  1170. WinHttpCloseHandle(hInetRequest);
  1171. WinHttpCloseHandle(hInetConnect);
  1172. PkiFree(pwszHostName);
  1173. PkiFree(pwszUrlPathPlusExtraInfo);
  1174. SetLastError(dwLastError);
  1175. return fResult;
  1176. ErrorReturn:
  1177. if (NULL != pb)
  1178. CCryptBlobArray::FreeBlob(pb);
  1179. dwLastError = GetLastError();
  1180. fResult = FALSE;
  1181. goto CommonReturn;
  1182. TRACE_ERROR(WinHttpCrackUrlError)
  1183. SET_ERROR(OutOfMemory, E_OUTOFMEMORY)
  1184. TRACE_ERROR(WinHttpConnectError)
  1185. TRACE_ERROR(WinHttpOpenRequestError)
  1186. TRACE_ERROR(SetAutoLogonSecurityOptionError)
  1187. TRACE_ERROR(SetDisableAuthenticationOptionError)
  1188. TRACE_ERROR(InetSendAuthenticatedRequestAndReceiveResponseError)
  1189. SET_ERROR(CanceledRead, ERROR_CANCELLED)
  1190. SET_ERROR(ExceededMaxUrlRetrievalByteCount, ERROR_INVALID_DATA)
  1191. TRACE_ERROR(WinHttpReadDataError)
  1192. TRACE_ERROR(RetrieveUncachedAuxInfoError)
  1193. }
  1194. //+---------------------------------------------------------------------------
  1195. //
  1196. // Function: InetFreeCryptBlobArray
  1197. //
  1198. // Synopsis: free the crypt blob array
  1199. //
  1200. //----------------------------------------------------------------------------
  1201. VOID
  1202. InetFreeCryptBlobArray (
  1203. PCRYPT_BLOB_ARRAY pcba
  1204. )
  1205. {
  1206. CCryptBlobArray cba( pcba, 0 );
  1207. cba.FreeArray( TRUE );
  1208. }
  1209. //+---------------------------------------------------------------------------
  1210. //
  1211. // Function: InetAsyncStatusCallback
  1212. //
  1213. // Synopsis: status callback for async
  1214. //
  1215. //----------------------------------------------------------------------------
  1216. VOID WINAPI
  1217. InetAsyncStatusCallback (
  1218. HINTERNET hInet,
  1219. DWORD dwContext,
  1220. DWORD dwInternetStatus,
  1221. LPVOID pvStatusInfo,
  1222. DWORD dwStatusLength
  1223. )
  1224. {
  1225. return;
  1226. }