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.

1086 lines
31 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. ierrui.cxx
  5. Abstract:
  6. Contains immplimentation of generic Error UI API.
  7. Contents:
  8. InternetErrorDlg
  9. InternetConfirmZoneCrossing
  10. (wErrorUIInvalidPassword)
  11. Author:
  12. Arthur L Bierer (arthurbi) 04-Apr-1996
  13. Revision History:
  14. 04-Apr-1996 arthurbi
  15. Created
  16. --*/
  17. #include <wininetp.h>
  18. #include <persist.h>
  19. #include "ierrui.hxx"
  20. //
  21. // private prototypes
  22. //
  23. PRIVATE
  24. DWORD
  25. wErrorUIInvalidPassword(
  26. IN HWND hWnd,
  27. IN OUT HINTERNET hRequest,
  28. IN DWORD dwError,
  29. IN DWORD dwFlags,
  30. IN OUT LPVOID *lppvData
  31. );
  32. //
  33. // public functions
  34. //
  35. INTERNETAPI_(DWORD) InternetErrorDlg(IN HWND hWnd,
  36. IN OUT HINTERNET hRequest,
  37. IN DWORD dwError,
  38. IN DWORD dwFlags,
  39. IN OUT LPVOID *lppvData
  40. )
  41. /*++
  42. Routine Description:
  43. Creates an Error Dialog informing the User of a problem with a WinINet HttpSendRequest.
  44. Can optionally store the results of dialog in the HTTP handle.
  45. Data may be specified in the lppvData pointer, or optionally InternetErrorDlg
  46. will gather the information from the HTTP handle
  47. Arguments:
  48. hWnd - Window handle to be used as the parent window of a Error Dialog.
  49. hRequest - An open HTTP request handle
  50. where headers will be added if needed.
  51. dwError - The Error code to which the appropriate UI will be shown for.
  52. dwFlags - Can be any of all of the following Flags:
  53. FLAGS_ERROR_UI_FLAGS_GENERATE_DATA - generates lppvData, and queries
  54. internet handle for information.
  55. FLAGS_ERROR_UI_FILTER_FOR_ERRORS - scans the returned headers,
  56. and determines if there is a "hidden" error, such as an authentication
  57. failure.
  58. FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS - On successful return of the dialog,
  59. this flag will causes the results to be stored in the handle.
  60. FLAGS_ERROR_UI_SERIALIZE_DIALOGS - display only one auth dlg and
  61. notify subsequent threads when the dialog has been dismissed.
  62. lppvData - Contains a Pointer to a Pointer where a stucture is stored containing
  63. error specific data, and Dialog results.
  64. Return Value:
  65. DWORD
  66. Success - ERROR_SUCCESS
  67. Failure - One of Serveral Error codes defined in winerror.h or wininet.w
  68. Comments:
  69. BUGBUG - need to look into multiple authentication scheme handling, and
  70. how it relates to the UI
  71. --*/
  72. {
  73. DEBUG_ENTER_API((DBG_HTTP,
  74. Dword,
  75. "InternetErrorDlg",
  76. "%#x, %#x, %s (%d), %#x, %#x",
  77. hWnd,
  78. hRequest,
  79. InternetMapError(dwError),
  80. dwError,
  81. dwFlags,
  82. lppvData
  83. ));
  84. DWORD dwStatusCode = HTTP_STATUS_OK;
  85. DWORD error = ERROR_SUCCESS;
  86. HINTERNET hMappedRequestHandle = NULL;
  87. HINTERNET_HANDLE_TYPE handleType;
  88. HTTP_REQUEST_HANDLE_OBJECT *lpRequest;
  89. LPVOID lpVoidData;
  90. //
  91. // Check Parameters
  92. //
  93. if ( !(dwFlags & FLAGS_ERROR_UI_FLAGS_NO_UI) &&
  94. !IsWindow(hWnd) )
  95. {
  96. error = ERROR_INVALID_HANDLE;
  97. goto quit;
  98. }
  99. if (!GlobalDataInitialized) {
  100. error = GlobalDataInitialize();
  101. if (error != ERROR_SUCCESS) {
  102. goto quit;
  103. }
  104. }
  105. if ( hRequest )
  106. {
  107. error = MapHandleToAddress(hRequest, (LPVOID *)&hMappedRequestHandle, FALSE);
  108. if ( error != ERROR_SUCCESS )
  109. goto quit;
  110. //
  111. // We only support HttpRequestHandles for this form of UI.
  112. //
  113. error = RGetHandleType(hMappedRequestHandle, &handleType);
  114. if ( error != ERROR_SUCCESS || handleType != TypeHttpRequestHandle )
  115. goto quit;
  116. lpRequest = (HTTP_REQUEST_HANDLE_OBJECT *) hMappedRequestHandle;
  117. //
  118. // See if we can detect an error if needed
  119. //
  120. if ( dwFlags & FLAGS_ERROR_UI_FILTER_FOR_ERRORS )
  121. {
  122. dwStatusCode = lpRequest->GetStatusCode();
  123. if ( dwStatusCode == HTTP_STATUS_DENIED || dwStatusCode == HTTP_STATUS_PROXY_AUTH_REQ )
  124. dwError = ERROR_INTERNET_INCORRECT_PASSWORD;
  125. if ( lpRequest->GetBlockingFilter())
  126. dwError = ERROR_INTERNET_NEED_UI;
  127. }
  128. }
  129. else
  130. {
  131. if( ERROR_INTERNET_NEED_UI == dwError ||
  132. ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED == dwError ||
  133. ERROR_INTERNET_INSERT_CDROM == dwError ||
  134. ERROR_INTERNET_INCORRECT_PASSWORD == dwError )
  135. {
  136. error = ERROR_INVALID_PARAMETER;
  137. goto quit;
  138. }
  139. }
  140. //
  141. // If the Caller didn't pass us anything, then we create our own
  142. // structure. Lets NULL it, and then allocate it later
  143. //
  144. //
  145. if ( !lppvData )
  146. {
  147. lppvData = &lpVoidData;
  148. *lppvData = NULL;
  149. }
  150. if ( dwFlags & FLAGS_ERROR_UI_FLAGS_GENERATE_DATA
  151. && !(dwFlags & FLAGS_ERROR_UI_SERIALIZE_DIALOGS))
  152. {
  153. *lppvData = NULL;
  154. }
  155. //
  156. // Determine what Function to handle this based on what error where given
  157. //
  158. BOOL fRet;
  159. switch ( dwError )
  160. {
  161. case ERROR_INTERNET_NEED_UI:
  162. fRet = HttpFiltOnBlockingOps
  163. (lpRequest, hRequest, hWnd);
  164. error = fRet? ERROR_SUCCESS : GetLastError();
  165. break;
  166. case ERROR_INTERNET_INCORRECT_PASSWORD:
  167. error = wErrorUIInvalidPassword(hWnd,
  168. hMappedRequestHandle,
  169. dwError,
  170. dwFlags,
  171. lppvData);
  172. break;
  173. case ERROR_HTTP_COOKIE_NEEDS_CONFIRMATION:
  174. // If we are in silent mode, we will have to
  175. // decline the cookie without throwing up a
  176. // dialog
  177. if((dwFlags & FLAGS_ERROR_UI_FLAGS_NO_UI))
  178. {
  179. error = ERROR_HTTP_COOKIE_DECLINED;
  180. }
  181. else
  182. {
  183. COOKIE_DLG_INFO info;
  184. memset(&info, 0, sizeof(info));
  185. info.dwOperation = COOKIE_OP_SET;
  186. info.pic = (INTERNET_COOKIE*)(*lppvData);
  187. if(info.pic->dwFlags & INTERNET_COOKIE_IS_SESSION)
  188. {
  189. info.dwOperation |= COOKIE_OP_SESSION;
  190. }
  191. error = ConfirmCookie(hWnd,
  192. lpRequest,
  193. &info);
  194. }
  195. break;
  196. case ERROR_HTTP_COOKIE_NEEDS_CONFIRMATION_EX:
  197. // If we are in silent mode, we will have to
  198. // decline the cookie without throwing up a
  199. // dialog
  200. if((dwFlags & FLAGS_ERROR_UI_FLAGS_NO_UI))
  201. {
  202. error = ERROR_HTTP_COOKIE_DECLINED;
  203. }
  204. else
  205. {
  206. error = ConfirmCookie(hWnd,
  207. lpRequest,
  208. (COOKIE_DLG_INFO *)(*lppvData));
  209. }
  210. break;
  211. case ERROR_INTERNET_FORTEZZA_LOGIN_NEEDED:
  212. //
  213. // Call the function which gets the cert context from the
  214. // Fortezza CSP.
  215. error = FortezzaLogOn(hWnd);
  216. break;
  217. case ERROR_INTERNET_SEC_CERT_REVOKED:
  218. {
  219. static WCHAR szMsgBoxText[128] = L"\0";
  220. static WCHAR szCaption[64] = L"\0";
  221. if (!szCaption[0])
  222. {
  223. LoadStringWrapW(GlobalDllHandle, IDS_CERT_REVOKED, szMsgBoxText, sizeof(szMsgBoxText));
  224. LoadStringWrapW(GlobalDllHandle, IDS_SECURITY_CAPTION, szCaption, sizeof(szCaption));
  225. }
  226. MessageBoxWrapW(hWnd, szMsgBoxText, szCaption, MB_OK | MB_ICONWARNING);
  227. error = ERROR_CANCELLED;
  228. }
  229. break;
  230. case ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR:
  231. case ERROR_INTERNET_HTTPS_TO_HTTP_ON_REDIR:
  232. //
  233. // Read the registry, and check to make sure
  234. // the user hasn't overriden this.
  235. //
  236. GlobalDataReadWarningUIFlags();
  237. if ( ! GlobalWarnOnZoneCrossing )
  238. break;
  239. //
  240. // fall through to launch dlg code.
  241. //
  242. goto l_launchdlg;
  243. case ERROR_HTTP_REDIRECT_NEEDS_CONFIRMATION:
  244. //
  245. // Read the registry, and check to make sure
  246. // the user hasn't overriden this.
  247. //
  248. GlobalDataReadWarningUIFlags();
  249. if ( ! GlobalWarnOnPostRedirect )
  250. break;
  251. //
  252. // fall through to launch dlg code.
  253. //
  254. goto l_launchdlg;
  255. case ERROR_INTERNET_POST_IS_NON_SECURE:
  256. case ERROR_INTERNET_CHG_POST_IS_NON_SECURE:
  257. //
  258. // Read the registry, and check to make sure
  259. // the user hasn't overriden this.
  260. //
  261. GlobalDataReadWarningUIFlags();
  262. if ( ! GlobalWarnOnPost )
  263. break;
  264. //
  265. // If we're not warning always, ie only warning
  266. // if the user actually changed some fields, then
  267. // bail out, and don't warn.
  268. //
  269. if ( ! GlobalWarnAlways &&
  270. dwError == ERROR_INTERNET_POST_IS_NON_SECURE )
  271. break;
  272. //
  273. // fall through to launch dlg code.
  274. //
  275. goto l_launchdlg;
  276. case ERROR_INTERNET_SEC_CERT_DATE_INVALID:
  277. case ERROR_INTERNET_SEC_CERT_CN_INVALID:
  278. case ERROR_INTERNET_MIXED_SECURITY:
  279. case ERROR_INTERNET_INVALID_CA:
  280. case ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED:
  281. case ERROR_INTERNET_BAD_AUTO_PROXY_SCRIPT:
  282. case ERROR_INTERNET_UNABLE_TO_DOWNLOAD_SCRIPT:
  283. case ERROR_INTERNET_HTTPS_HTTP_SUBMIT_REDIR:
  284. case ERROR_INTERNET_INSERT_CDROM:
  285. case ERROR_INTERNET_SEC_CERT_ERRORS:
  286. case ERROR_INTERNET_SEC_CERT_REV_FAILED:
  287. l_launchdlg:
  288. // if silent flag is set, we can just pass
  289. // ERROR_CANCELLED back without throwing up
  290. // a dialog
  291. if ((dwFlags & FLAGS_ERROR_UI_FLAGS_NO_UI))
  292. {
  293. error = ERROR_CANCELLED;
  294. }
  295. else
  296. {
  297. ERRORINFODLGTYPE ErrorInfoDlgInfo;
  298. DLGPROC pDlgProc;
  299. MapWininetErrorToDlgId(
  300. dwError,
  301. &ErrorInfoDlgInfo.dwDlgId,
  302. &ErrorInfoDlgInfo.dwDlgFlags,
  303. &pDlgProc
  304. );
  305. INET_ASSERT(pDlgProc);
  306. ErrorInfoDlgInfo.hInternetMapped =
  307. hMappedRequestHandle;
  308. if (ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED == dwError)
  309. {
  310. CERT_CONTEXT_ARRAY* pCertContextArray =
  311. ((HTTP_REQUEST_HANDLE_OBJECT *)hMappedRequestHandle)->GetCertContextArray();
  312. if (pCertContextArray)
  313. {
  314. const DWORD c_dwArraySize = pCertContextArray->GetArraySize();
  315. if (1 == c_dwArraySize || 0 == c_dwArraySize)
  316. {
  317. const BOOL fRestricted =
  318. lpRequest->GetOpenFlags() & INTERNET_FLAG_RESTRICTED_ZONE;
  319. const DWORD dwClientCertPromptPolicy =
  320. ::GetClientCertPromptPolicy(lpRequest->GetURL(), fRestricted);
  321. if (dwClientCertPromptPolicy == URLPOLICY_ALLOW)
  322. {
  323. // If 1, select index 0, otherwise -1 if none
  324. pCertContextArray->SelectCertContext(c_dwArraySize ? 0 : -1);
  325. error = ERROR_SUCCESS;
  326. break;
  327. }
  328. }
  329. }
  330. }
  331. error = LaunchDlg(
  332. hWnd,
  333. (LPVOID) &ErrorInfoDlgInfo,
  334. ErrorInfoDlgInfo.dwDlgId,
  335. pDlgProc
  336. );
  337. }
  338. break;
  339. default:
  340. //
  341. // if we're filtering for errors, then its not an error
  342. // since we're intented to process all errors
  343. //
  344. if ( ! (dwFlags & FLAGS_ERROR_UI_FILTER_FOR_ERRORS) )
  345. error = ERROR_NOT_SUPPORTED;
  346. break;
  347. }
  348. quit:
  349. if ( hMappedRequestHandle != NULL )
  350. DereferenceObject((LPVOID)hMappedRequestHandle);
  351. DEBUG_LEAVE_API(error);
  352. return error;
  353. }
  354. INTERNETAPI_(DWORD) InternetConfirmZoneCrossingA(
  355. IN HWND hWnd,
  356. IN LPSTR szUrlPrev,
  357. IN LPSTR szUrlNew,
  358. BOOL bPost
  359. )
  360. /*++
  361. Routine Description:
  362. Creates an Error Dialog informing the User of a zone crossing ( going
  363. between HTTPS to HTTP or HTTPS to HTTP ) when one is detected.
  364. Arguments:
  365. hWnd - Window handle to be used as the parent window of a Error Dialog.
  366. szUrlPrev - Previous URL string.
  367. szUrlNew - New URL string that the User is about to go to.
  368. bPost - TRUE if a POST is being done, FALSE otherwise.
  369. Return Value:
  370. DWORD
  371. Success - ERROR_SUCCESS
  372. ( user either confirmed OK to continue, or there was no
  373. UI needed )
  374. Failure - ERROR_CANCELLED ( user canceled, we want to stop )
  375. ERROR_NOT_ENOUGH_MEMORY
  376. Comments:
  377. none.
  378. --*/
  379. {
  380. DEBUG_ENTER_API((DBG_API,
  381. Dword,
  382. "InternetConfirmZoneCrossingA",
  383. "%#x, %q, %q, %d",
  384. hWnd,
  385. szUrlPrev,
  386. szUrlNew,
  387. bPost));
  388. DWORD error = ERROR_SUCCESS;
  389. INTERNET_SCHEME ustPrevScheme;
  390. INTERNET_SCHEME ustNewScheme;
  391. INET_ASSERT(szUrlNew);
  392. //
  393. // If the Previous one is NULL, then we could be starting out
  394. // for the first time
  395. //
  396. if ( szUrlPrev == NULL )
  397. goto quit;
  398. error = CrackUrl(szUrlPrev,
  399. lstrlen(szUrlPrev),
  400. FALSE,
  401. &ustPrevScheme,
  402. NULL, // Scheme Name
  403. NULL, // Scheme Length
  404. NULL, // Host Name
  405. NULL, // Host Length
  406. NULL, // Internet Port
  407. NULL, // UserName
  408. NULL, // UserName Length
  409. NULL, // Password
  410. NULL, // Password Length
  411. NULL, // Path
  412. NULL, // Path Length
  413. NULL, // Extra
  414. NULL, // Extra Length
  415. NULL
  416. );
  417. if ( error != ERROR_SUCCESS )
  418. {
  419. error = ERROR_SUCCESS;
  420. ustPrevScheme = INTERNET_SCHEME_UNKNOWN;
  421. }
  422. error = CrackUrl(szUrlNew,
  423. lstrlen(szUrlNew),
  424. FALSE,
  425. &ustNewScheme,
  426. NULL, // Scheme Name
  427. NULL, // Scheme Length
  428. NULL, // Host Name
  429. NULL, // Host Length
  430. NULL, // Internet Port
  431. NULL, // UserName
  432. NULL, // UserName Length
  433. NULL, // Password
  434. NULL, // Password Length
  435. NULL, // Path
  436. NULL, // Path Length
  437. NULL, // Extra
  438. NULL, // Extra Length
  439. NULL
  440. );
  441. if ( error != ERROR_SUCCESS )
  442. {
  443. error = ERROR_SUCCESS;
  444. ustNewScheme = INTERNET_SCHEME_UNKNOWN;
  445. }
  446. //
  447. // First Eliminate the obvious.
  448. //
  449. if ( ustPrevScheme == ustNewScheme )
  450. goto quit;
  451. //
  452. // Next, if it wasn't HTTPS, and it is now
  453. // we've caught one zone cross.
  454. //
  455. if ( ustPrevScheme != INTERNET_SCHEME_HTTPS &&
  456. ustNewScheme == INTERNET_SCHEME_HTTPS )
  457. {
  458. error = ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR;
  459. }
  460. //
  461. // Otherwise, if it was HTTPS, and it is now
  462. // no longer HTTPS, we also flag it.
  463. //
  464. else if ((ustPrevScheme == INTERNET_SCHEME_HTTPS)
  465. && ((ustNewScheme != INTERNET_SCHEME_HTTPS)
  466. && (ustNewScheme != INTERNET_SCHEME_JAVASCRIPT)
  467. && (ustNewScheme != INTERNET_SCHEME_VBSCRIPT))) {
  468. error = ERROR_INTERNET_HTTPS_TO_HTTP_ON_REDIR;
  469. }
  470. if ( error != ERROR_SUCCESS &&
  471. hWnd )
  472. {
  473. error = InternetErrorDlg(
  474. hWnd,
  475. NULL, // hRequest
  476. error,
  477. 0,
  478. NULL // non Data structure to pass.
  479. );
  480. }
  481. quit:
  482. DEBUG_LEAVE_API(error);
  483. return error;
  484. }
  485. //
  486. // private functions
  487. //
  488. PRIVATE
  489. DWORD
  490. wErrorUIInvalidPassword(IN HWND hWnd,
  491. IN HINTERNET hRequest,
  492. IN DWORD dwError,
  493. IN DWORD dwFlags,
  494. IN OUT LPVOID *lppvData
  495. )
  496. /*++
  497. Routine Description:
  498. Creates an Error Dialog asking the User for his Username and Password.
  499. Arguments:
  500. hWnd - Window handle to be used as the parent window of a Error Dialog.
  501. hRequest - An open HTTP request handle, that is MAPPED,
  502. where headers will be added if needed.
  503. dwError - The Error code to which the appropriate UI will be shown for.
  504. dwFlags - Can be any of all of the following Flags:
  505. FLAGS_ERROR_UI_FLAGS_GENERATE_DATA - generates lppvData, and queries
  506. internet handle for information.
  507. FLAGS_ERROR_UI_FILTER_FOR_ERRORS - scans the returned headers,
  508. and determines if there is a "hidden" error, such as an authentication
  509. failure.
  510. FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS - On successful return of the dialog,
  511. this flag will causes the results to be stored in the handle.
  512. FLAGS_ERROR_UI_FLAGS_NO_UI - Don't show any User interface. Silently,
  513. accepts the Username, and Password that is passed in.
  514. lppvData - Contains a Pointer to a Pointer where a stucture is stored containing
  515. error specific data, and Dialog results.
  516. Return Value:
  517. DWORD
  518. Success - ERROR_SUCCESS
  519. Failure - One of Serveral Error codes defined in winerror.h or wininet.w
  520. Comments:
  521. BUGBUG - need to look into multiple authentication scheme handling, and
  522. how it relates to the UI
  523. BUGBUG - need to handle case where one thread calls into this function,
  524. and a second threads also calls in to put up UI on the same User-Pass Info
  525. as the first.
  526. --*/
  527. {
  528. DEBUG_ENTER((DBG_INET,
  529. Dword,
  530. "wErrorUIInvalidPassword",
  531. "%#x, %#x, %d (%s), %#x, %#x",
  532. hWnd,
  533. hRequest,
  534. dwError,
  535. InternetMapError(dwError),
  536. dwFlags,
  537. lppvData
  538. ));
  539. DWORD error = ERROR_SUCCESS;
  540. BOOL fMustLock = FALSE;
  541. InvalidPassType ipt;
  542. ipt.lpszPassword = NULL;
  543. // Get the request handle and connect handle.
  544. HTTP_REQUEST_HANDLE_OBJECT *pRequest =
  545. (HTTP_REQUEST_HANDLE_OBJECT *) hRequest;
  546. INTERNET_CONNECT_HANDLE_OBJECT *pConnect =
  547. (INTERNET_CONNECT_HANDLE_OBJECT *) pRequest->GetParent();
  548. // Validate parameters.
  549. if (!pConnect || (!(dwFlags & FLAGS_ERROR_UI_FLAGS_NO_UI) && !IsWindow(hWnd)))
  550. {
  551. error = ERROR_INVALID_PARAMETER;
  552. goto quit;
  553. }
  554. // Get the authentication context.
  555. AUTHCTX *pAuthCtx;
  556. pAuthCtx = pRequest->GetAuthCtx();
  557. if (!pAuthCtx)
  558. {
  559. pAuthCtx = pRequest->GetTunnelAuthCtx();
  560. if (!pAuthCtx)
  561. {
  562. error = ERROR_SUCCESS;
  563. goto quit;
  564. }
  565. }
  566. PWC *pwc;
  567. pwc = pAuthCtx->_pPWC;
  568. // INET_ASSERT (pwc && pwc->nLockCount); w/ Passport, this is no longer true
  569. //
  570. // Initialize InvalidPassType struct
  571. //
  572. if (pAuthCtx->GetSchemeType() != AUTHCTX::SCHEME_PASSPORT)
  573. {
  574. char szUserBuf[MAX_FIELD_LENGTH], szPassBuf[MAX_FIELD_LENGTH];
  575. ipt.ulMaxField = MAX_FIELD_LENGTH - 1;
  576. ipt.lpszPassword = szUserBuf;
  577. ipt.lpszUsername = szPassBuf;
  578. if (pAuthCtx->_pszFQDN)
  579. {
  580. ipt.lpszHost = (LPSTR)pAuthCtx->_pszFQDN;
  581. }
  582. else
  583. {
  584. ipt.lpszHost = pAuthCtx->_pPWC->lpszHost;
  585. }
  586. ipt.fIsProxy = pAuthCtx->_fIsProxy;
  587. //
  588. // Transfer password cache entry fields to UI structure.
  589. //
  590. AuthLock();
  591. LPSTR lpszPass = pwc->GetPass();
  592. if (pwc->lpszUser)
  593. lstrcpyn (ipt.lpszUsername, pwc->lpszUser, MAX_FIELD_LENGTH);
  594. else
  595. ipt.lpszUsername[0] = 0;
  596. if (lpszPass)
  597. lstrcpyn (ipt.lpszPassword, lpszPass, MAX_FIELD_LENGTH);
  598. else
  599. ipt.lpszPassword[0] = 0;
  600. ipt.lpszRealm = pwc->lpszRealm;
  601. if (lpszPass)
  602. {
  603. SecureZeroMemory(lpszPass, strlen(lpszPass));
  604. FREE_MEMORY(lpszPass);
  605. }
  606. AuthUnlock();
  607. }
  608. if (dwFlags & FLAGS_ERROR_UI_SERIALIZE_DIALOGS)
  609. {
  610. // Queue this thread if we're already in a dialog.
  611. INET_ASSERT (lppvData);
  612. INTERNET_AUTH_NOTIFY_DATA *pNotify =
  613. (INTERNET_AUTH_NOTIFY_DATA *) *lppvData;
  614. if (IsBadReadPtr (pNotify, sizeof(*pNotify)))
  615. {
  616. error = ERROR_INVALID_PARAMETER;
  617. goto quit;
  618. }
  619. if (AuthInDialog (pAuthCtx, pNotify, &fMustLock))
  620. {
  621. // The auth context maintains a context handle
  622. // to correctly process the 'stale' subheader.
  623. // Setting _nRetries to 0 will cause no context handle to
  624. // be passed into the package and restart auth for this context
  625. // from scratch. Therefore, no attempt will be made to parse the
  626. // stale header which is the correct behavior.
  627. if (pAuthCtx->GetSchemeType() == AUTHCTX::SCHEME_DIGEST)
  628. {
  629. ((DIGEST_CTX*)pAuthCtx)->_nRetries = 0;
  630. }
  631. error = ERROR_INTERNET_DIALOG_PENDING;
  632. goto quit;
  633. }
  634. }
  635. if ((dwFlags & FLAGS_ERROR_UI_FLAGS_NO_UI))
  636. {
  637. // No UI - retrieve any persisted credentials.
  638. error = InetGetCachedCredentials(pwc->lpszHost, pwc->lpszRealm,
  639. ipt.lpszUsername, ipt.lpszPassword);
  640. }
  641. else // Launch the appropriate dialog.
  642. {
  643. if ((pAuthCtx->GetFlags() & PLUGIN_AUTH_FLAGS_CAN_HANDLE_UI))
  644. {
  645. // If auth package handles its own UI, let it.
  646. error = LaunchAuthPlugInDlg
  647. (pRequest, pAuthCtx, hWnd, dwError, dwFlags, &ipt);
  648. }
  649. else
  650. {
  651. if (pAuthCtx->GetSchemeType() == AUTHCTX::SCHEME_BASIC
  652. || pAuthCtx->GetSchemeType() == AUTHCTX::SCHEME_DIGEST)
  653. {
  654. ipt.eAuthType = REALM_AUTH;
  655. }
  656. else if (pAuthCtx->GetSchemeType() == AUTHCTX::SCHEME_PASSPORT)
  657. {
  658. ipt.eAuthType = PASSPORT_AUTH;
  659. }
  660. else
  661. {
  662. INET_ASSERT(pAuthCtx->GetSchemeType() == AUTHCTX::SCHEME_NTLM
  663. || pAuthCtx->GetSchemeType() == AUTHCTX::SCHEME_KERBEROS
  664. || pAuthCtx->GetSchemeType() == AUTHCTX::SCHEME_NEGOTIATE);
  665. ipt.eAuthType = NTLM_AUTH;
  666. }
  667. CREDINFODLGTYPE CredInfoDlgInfo;
  668. CredInfoDlgInfo.pipt = &ipt;
  669. CredInfoDlgInfo.pRequest = pRequest;
  670. CredInfoDlgInfo.pAuthCtx = pAuthCtx;
  671. if (ipt.eAuthType == REALM_AUTH)
  672. error = LaunchDlg (hWnd,(LPVOID) &CredInfoDlgInfo, IDD_REALM_AUTH, NULL);
  673. else if (ipt.eAuthType == PASSPORT_AUTH)
  674. error = LaunchDlg (hWnd,(LPVOID) &CredInfoDlgInfo, 0, NULL);
  675. else
  676. error = LaunchDlg (hWnd,(LPVOID) &CredInfoDlgInfo, IDD_NTLM_AUTH, NULL);
  677. }
  678. }
  679. // If dialog was OK, return as follows.
  680. if (error == ERROR_SUCCESS)
  681. {
  682. AuthLock();
  683. if (ipt.eAuthType == NTLM_AUTH)
  684. {
  685. // Update user/pass which would overwrite PWC.
  686. pRequest->SetUserOrPass (ipt.lpszUsername, IS_USER, pAuthCtx->_fIsProxy);
  687. pRequest->SetUserOrPass (ipt.lpszPassword, IS_PASS, pAuthCtx->_fIsProxy);
  688. // Update PWC so related requests will be retried.
  689. pwc->SetUser (ipt.lpszUsername);
  690. pwc->SetPass (ipt.lpszPassword);
  691. }
  692. else if (pAuthCtx->GetSchemeType() != AUTHCTX::SCHEME_PASSPORT)
  693. {
  694. // Update user/pass which would overwrite PWC.
  695. // Update PWC so related requests will be retried.
  696. //if (ipt.lpszUsername[0])
  697. {
  698. pRequest->SetUserOrPass (ipt.lpszUsername, IS_USER, pAuthCtx->_fIsProxy);
  699. pwc->SetUser (ipt.lpszUsername);
  700. }
  701. //if (ipt.lpszPassword[0])
  702. {
  703. pRequest->SetUserOrPass (ipt.lpszPassword, IS_PASS, pAuthCtx->_fIsProxy);
  704. pwc->SetPass (ipt.lpszPassword);
  705. }
  706. }
  707. AuthUnlock();
  708. // Retry this request.
  709. error = ERROR_INTERNET_FORCE_RETRY;
  710. }
  711. // Notify any waiting threads.
  712. if (dwFlags & FLAGS_ERROR_UI_SERIALIZE_DIALOGS)
  713. {
  714. if (fMustLock)
  715. {
  716. // fMustLock will have been set by AuthInDialog if this is
  717. // a reentrant call to InternetErrorDlg by AuthNotify. If this
  718. // is the case, acquire the lock and do not call AuthNotify.
  719. // so that when control is returned to AuthNotify the lock will
  720. // already be correctly acquired.
  721. AuthLock();
  722. }
  723. else
  724. {
  725. AuthNotify (pwc, error);
  726. }
  727. }
  728. quit:
  729. if (ipt.lpszPassword)
  730. {
  731. SecureZeroMemory(ipt.lpszPassword, strlen(ipt.lpszPassword));
  732. }
  733. //
  734. // IE30 compat: must return ERROR_SUCCESS to avoid bogus dialog.
  735. //
  736. if ( error == ERROR_CANCELLED )
  737. error = ERROR_SUCCESS;
  738. DEBUG_LEAVE(error);
  739. return error;
  740. }
  741. #define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
  742. DWORD
  743. ConfirmCookie(
  744. HWND hwnd,
  745. HTTP_REQUEST_HANDLE_OBJECT *lpRequest,
  746. COOKIE_DLG_INFO *pcdi
  747. )
  748. {
  749. DWORD dw;
  750. BYTE *buf = NULL;
  751. //
  752. // Get the server name
  753. //
  754. WCHAR wszServer[INTERNET_MAX_HOST_NAME_LENGTH + 1];
  755. if (lpRequest)
  756. {
  757. DEBUG_ONLY(lpRequest->GetHostName(&dw));
  758. INET_ASSERT(dw <= ARRAYSIZE(wszServer));
  759. CHAR szServerTmp[INTERNET_MAX_HOST_NAME_LENGTH + 1];
  760. lpRequest->CopyHostName(szServerTmp);
  761. if(SHAnsiToUnicode(szServerTmp, wszServer, ARRAYSIZE(wszServer)))
  762. pcdi->pszServer = wszServer;
  763. }
  764. else if(pcdi->pic)
  765. {
  766. if(SHAnsiToUnicode(pcdi->pic->pszDomain, wszServer, ARRAYSIZE(wszServer)))
  767. pcdi->pszServer = wszServer;
  768. }
  769. /* Consult per-site decisions one more time.
  770. By the time the prompt is being displayed, another instance
  771. of the cookie-prompt MAY have already written a decision. */
  772. unsigned long dwPerSiteDecision = COOKIE_STATE_UNKNOWN;
  773. if (InternetGetPerSiteCookieDecisionW(pcdi->pszServer, &dwPerSiteDecision) &&
  774. dwPerSiteDecision!=COOKIE_STATE_UNKNOWN)
  775. {
  776. if (dwPerSiteDecision==COOKIE_STATE_ACCEPT)
  777. return ERROR_SUCCESS;
  778. else
  779. return ERROR_HTTP_COOKIE_DECLINED;
  780. }
  781. ULONG_PTR uCookie = 0;
  782. SHActivateContext(&uCookie);
  783. // Can typecast as long as "CookieDialogProc" only returns true or false
  784. dw = (BOOL ) DialogBoxParamWrapW(GetModuleHandle("WININET.DLL"),
  785. MAKEINTRESOURCEW(IDD_CONFIRM_COOKIE),
  786. hwnd,
  787. CookieDialogProc,
  788. (LPARAM) pcdi);
  789. if (uCookie)
  790. {
  791. SHDeactivateContext(uCookie);
  792. }
  793. return dw;
  794. }
  795. INTERNETAPI_(DWORD) InternetConfirmZoneCrossingW(
  796. IN HWND hWnd,
  797. IN LPWSTR szUrlPrev,
  798. IN LPWSTR szUrlNew,
  799. BOOL bPost
  800. )
  801. /*++
  802. Routine Description:
  803. Creates an Error Dialog informing the User of a zone crossing ( going
  804. between HTTPS to HTTP or HTTPS to HTTP ) when one is detected.
  805. Arguments:
  806. hWnd - Window handle to be used as the parent window of a Error Dialog.
  807. szUrlPrev - Previous URL string.
  808. szUrlNew - New URL string that the User is about to go to.
  809. bPost - TRUE if a POST is being done, FALSE otherwise.
  810. Return Value:
  811. DWORD
  812. Success - ERROR_SUCCESS
  813. ( user either confirmed OK to continue, or there was no
  814. UI needed )
  815. Failure - ERROR_CANCELLED ( user canceled, we want to stop )
  816. ERROR_NOT_ENOUGH_MEMORY
  817. Comments:
  818. none.
  819. --*/
  820. {
  821. DEBUG_ENTER_API((DBG_API,
  822. Dword,
  823. "InternetConfirmZoneCrossingW",
  824. "%wq, %wq, %d",
  825. szUrlPrev,
  826. szUrlNew,
  827. bPost));
  828. DWORD dwErr = ERROR_SUCCESS;
  829. MEMORYPACKET mpNew, mpPrev;
  830. if (!(szUrlPrev && szUrlNew))
  831. {
  832. dwErr = ERROR_INVALID_PARAMETER;
  833. goto cleanup;
  834. }
  835. ALLOC_MB(szUrlPrev,0,mpPrev);
  836. ALLOC_MB(szUrlNew,0,mpNew);
  837. if (!(mpPrev.psStr && mpNew.psStr))
  838. {
  839. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  840. goto cleanup;
  841. }
  842. UNICODE_TO_ANSI(szUrlPrev,mpPrev);
  843. UNICODE_TO_ANSI(szUrlNew,mpNew);
  844. dwErr = InternetConfirmZoneCrossingA(hWnd, mpPrev.psStr, mpNew.psStr, bPost);
  845. cleanup:
  846. if (dwErr!=ERROR_SUCCESS)
  847. {
  848. SetLastError(dwErr);
  849. DEBUG_ERROR(INET, dwErr);
  850. }
  851. DEBUG_LEAVE_API(dwErr);
  852. return dwErr;
  853. }