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.

1580 lines
46 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. Logon.cpp
  5. Abstract:
  6. Author:
  7. Biao Wang (biaow) 01-Oct-2000
  8. --*/
  9. #include "PPdefs.h"
  10. #include "passport.h"
  11. typedef int INTERNET_SCHEME;
  12. #include "session.h"
  13. #include "ole2.h"
  14. #include "logon.h"
  15. #include "wincrypt.h"
  16. #define SIZE_OF_SALT 37
  17. #define SALT_SHIFT 2
  18. WCHAR g_szSalt[] = L"82BD0E67-9FEA-4748-8672-D5EFE5B779B0";
  19. // #include "wininet.h"
  20. #define INTERNET_MAX_USER_NAME_LENGTH 128
  21. #include "shlwapi.h"
  22. #include <stdio.h>
  23. // #include "logon.tmh"
  24. #define HTTP_STATUS_DENIED 401 // access denied
  25. #define HTTP_STATUS_OK 200 // request completed
  26. #define HTTP_QUERY_FLAG_NUMBER 0x20000000
  27. #define HTTP_QUERY_STATUS_CODE 19 // special: part of status line
  28. #define HTTP_QUERY_AUTHENTICATION_INFO 76
  29. #define HTTP_QUERY_WWW_AUTHENTICATE 40
  30. #define HTTP_QUERY_RAW_HEADERS_CRLF 22 // special: all headers
  31. #define HTTP_QUERY_PASSPORT_CONFIG 78
  32. // NOTE*** below we assume(!) the WinInet & WinHttp shared the same error VALUE
  33. #define ERROR_HTTP_HEADER_NOT_FOUND 12150L
  34. #define ERROR_INTERNET_INVALID_CA 12045L
  35. #define INTERNET_OPTION_SECURITY_FLAGS 31
  36. #define SECURITY_FLAG_IGNORE_REVOCATION 0x00000080
  37. #define SECURITY_FLAG_IGNORE_UNKNOWN_CA 0x00000100
  38. #define SECURITY_FLAG_IGNORE_WRONG_USAGE 0x00000200
  39. #define INTERNET_FLAG_IGNORE_CERT_CN_INVALID 0x00001000 // bad common name in X509 Cert.
  40. #define INTERNET_FLAG_IGNORE_CERT_DATE_INVALID 0x00002000 // expired X509 Cert.
  41. #define SECURITY_FLAG_IGNORE_CERT_CN_INVALID INTERNET_FLAG_IGNORE_CERT_CN_INVALID
  42. #define SECURITY_FLAG_IGNORE_CERT_DATE_INVALID INTERNET_FLAG_IGNORE_CERT_DATE_INVALID
  43. #define SECURITY_SET_MASK (SECURITY_FLAG_IGNORE_REVOCATION |\
  44. SECURITY_FLAG_IGNORE_UNKNOWN_CA |\
  45. SECURITY_FLAG_IGNORE_CERT_CN_INVALID |\
  46. SECURITY_FLAG_IGNORE_CERT_DATE_INVALID |\
  47. SECURITY_FLAG_IGNORE_WRONG_USAGE)
  48. #define INTERNET_DEFAULT_HTTP_PORT 80 // " " HTTP "
  49. #define INTERNET_DEFAULT_HTTPS_PORT 443 // " " HTTPS "
  50. #define INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS 0x00004000 // ex: http:// to https://
  51. #define INTERNET_STATUS_REDIRECT 110
  52. #define HTTP_ADDREQ_FLAG_ADD 0x20000000
  53. #define HTTP_ADDREQ_FLAG_REPLACE 0x80000000
  54. #define INTERNET_FLAG_SECURE 0x00800000 // use PCT/SSL if applicable (HTTP)
  55. #define INTERNET_STATUS_COOKIE_SENT 320
  56. #define INTERNET_STATUS_COOKIE_RECEIVED 321
  57. typedef struct {
  58. int cSession; // Session cookies received
  59. int cPersistent; // Persistent cookies received
  60. int cAccepted; // Number of cookies accepted
  61. int cLeashed; // ... leashed
  62. int cDowngraded; // ... converted to session-cookies
  63. int cBlocked; // ... rejected
  64. const char *pszLocation; // Optional: URL associated with reported cookie events
  65. // This can be used to override request URL
  66. }
  67. IncomingCookieState;
  68. typedef struct {
  69. int cSent;
  70. int cSuppressed;
  71. const char *pszLocation; // Optional: URL associated with reported cookie events
  72. // This can be used to override request URL
  73. }
  74. OutgoingCookieState;
  75. LOGON::LOGON(SESSION* pSession, DWORD dwParentFlags)
  76. : m_pSession(pSession)
  77. {
  78. m_pSession->AddRef();
  79. m_hConnect = NULL;
  80. m_fCredsPresent = FALSE;
  81. m_pwszSignIn = NULL;
  82. m_pwszTicketRequest = NULL;
  83. m_pwszAuthInfo = NULL;
  84. m_pwszReturnUrl = NULL;
  85. m_hBitmap = NULL;
  86. m_fPrompt = FALSE;
  87. m_wTimeSkew[0] = L'\0';
  88. m_wNewDAUrl[0] = 0;
  89. m_dwParentFlags = dwParentFlags;
  90. m_p401Content = NULL;
  91. m_pwszCbtxt = NULL;
  92. InitializeListHead(&m_PrivacyEventList);
  93. }
  94. LOGON::~LOGON(void)
  95. {
  96. while (!IsListEmpty(&m_PrivacyEventList))
  97. {
  98. PLIST_ENTRY pEntry = RemoveHeadList(&m_PrivacyEventList);
  99. PRIVACY_EVENT* pEvent = (PRIVACY_EVENT*)pEntry;
  100. if (pEvent->dwStatus == INTERNET_STATUS_COOKIE_SENT)
  101. {
  102. delete [] ((OutgoingCookieState*)(pEvent->lpvInfo))->pszLocation;
  103. ((OutgoingCookieState*)(pEvent->lpvInfo))->pszLocation = NULL;
  104. }
  105. else
  106. {
  107. delete [] ((IncomingCookieState*)(pEvent->lpvInfo))->pszLocation;
  108. ((OutgoingCookieState*)(pEvent->lpvInfo))->pszLocation = NULL;
  109. }
  110. delete [] pEvent->lpvInfo;
  111. delete pEvent;
  112. }
  113. if (m_pwszAuthInfo)
  114. {
  115. delete [] m_pwszAuthInfo;
  116. }
  117. if (m_pwszSignIn)
  118. {
  119. delete [] m_pwszSignIn;
  120. }
  121. if (m_pwszTicketRequest)
  122. {
  123. delete [] m_pwszTicketRequest;
  124. }
  125. if (m_pwszAuthHeader)
  126. {
  127. SecureZeroMemory(m_pwszAuthHeader, ::wcslen(m_pwszAuthHeader) * sizeof(WCHAR));
  128. delete [] m_pwszAuthHeader;
  129. }
  130. m_pSession->RemoveRef();
  131. if (m_p401Content)
  132. {
  133. m_p401Content->Release();
  134. }
  135. if (m_pwszCbtxt)
  136. {
  137. delete [] m_pwszCbtxt;
  138. }
  139. if (m_hBitmap)
  140. DeleteObject(m_hBitmap);
  141. }
  142. // -----------------------------------------------------------------------------
  143. BOOL LOGON::Open(
  144. PCWSTR pwszPartnerInfo // in the form of "WWW-Authenticate: Passport1.4 ..."
  145. )
  146. {
  147. PP_ASSERT(pwszPartnerInfo != NULL);
  148. // locate the auth scheme name, i.e. Passport1.4
  149. PCWSTR pwszTicketRequest = ::wcsstr(pwszPartnerInfo, L"Passport1.4");
  150. if (pwszTicketRequest == NULL)
  151. {
  152. DoTraceMessage(PP_LOG_ERROR, "LOGON::Open() failed; Passport1.4 scheme not found");
  153. return FALSE;
  154. }
  155. pwszTicketRequest += ::wcslen(L"Passport1.4");
  156. // skip white spaces between the scheme name and the Ticket Request (TR)
  157. while (*pwszTicketRequest == (L" ")[0]) { ++pwszTicketRequest; }
  158. if (pwszTicketRequest == NULL)
  159. {
  160. DoTraceMessage(PP_LOG_ERROR, "LOGON::Open() failed; Ticket Request missing");
  161. return FALSE;
  162. }
  163. // save the TR
  164. DWORD dwTrLen = ::wcslen(pwszTicketRequest);
  165. m_pwszTicketRequest = new WCHAR[dwTrLen + 1];
  166. if (m_pwszTicketRequest == NULL)
  167. {
  168. DoTraceMessage(PP_LOG_ERROR, "LOGON::Open() failed; not enough memory");
  169. return FALSE;
  170. }
  171. ::wcscpy(m_pwszTicketRequest, pwszTicketRequest);
  172. m_pwszAuthHeader = new WCHAR[dwTrLen +
  173. 2048 + // Prepared for long creds
  174. 512 + // some more head room
  175. 1];
  176. if (m_pwszAuthHeader == NULL)
  177. {
  178. DoTraceMessage(PP_LOG_ERROR, "LOGON::Open() failed; not enough memory");
  179. return FALSE;
  180. }
  181. DoTraceMessage(PP_LOG_INFO, "LOGON::Open() succeed");
  182. return TRUE;
  183. }
  184. void LOGON::Close(void)
  185. {
  186. PP_ASSERT(m_hConnect != NULL);
  187. PP_ASSERT(m_pSession != NULL);
  188. m_pSession->CloseHandle(m_hConnect);
  189. m_hConnect = NULL;
  190. }
  191. // pClearPassword is assumed to be at least 256 chars
  192. void DecryptPassword ( WCHAR* pClearPassword, PVOID pPassword, DWORD cbSize )
  193. {
  194. BOOL bOrigEncrypted = FALSE;
  195. DATA_BLOB InBlob;
  196. DATA_BLOB OutBlob;
  197. LPWSTR pszDesc;
  198. if ( pClearPassword == NULL )
  199. return;
  200. if ( cbSize == 0 )
  201. {
  202. // CryptUnprotectData doesn't like to be sent a zero-length buffer
  203. pClearPassword[0] = L'\0';
  204. return;
  205. }
  206. InBlob.pbData = (BYTE*)pPassword;
  207. InBlob.cbData = cbSize;
  208. DATA_BLOB EntropyBlob;
  209. WCHAR szSalt[SIZE_OF_SALT];
  210. wcscpy ( szSalt, g_szSalt);
  211. for ( int i = 0; i < SIZE_OF_SALT; i++ )
  212. szSalt[i] <<= SALT_SHIFT;
  213. EntropyBlob.pbData = (BYTE*)szSalt;
  214. EntropyBlob.cbData = sizeof(WCHAR)*(wcslen(szSalt)+1);
  215. // Should be assumed that client won't get this far without
  216. // having initialized for SSL via LoadSecurity().
  217. if ( CryptUnprotectData ( &InBlob,
  218. &pszDesc,
  219. &EntropyBlob,
  220. // NULL,
  221. NULL,
  222. NULL,
  223. CRYPTPROTECT_UI_FORBIDDEN,
  224. &OutBlob ) )
  225. {
  226. if ( wcscmp (L"SSOCred", pszDesc) == 0 )
  227. {
  228. DWORD dwOutChars = OutBlob.cbData/sizeof(WCHAR);
  229. if ( dwOutChars < 256 )
  230. {
  231. wcsncpy ( pClearPassword, (WCHAR*)OutBlob.pbData, dwOutChars );
  232. pClearPassword[dwOutChars] = L'\0';
  233. }
  234. bOrigEncrypted = TRUE;
  235. }
  236. LocalFree ( pszDesc );
  237. LocalFree ( OutBlob.pbData );
  238. }
  239. memset ( szSalt, 0, SIZE_OF_SALT);
  240. if ( !bOrigEncrypted )
  241. {
  242. // copy the plain text
  243. wcsncpy ( pClearPassword, (WCHAR*)pPassword, 256 );
  244. pClearPassword[cbSize/sizeof(WCHAR)] = L'\0';
  245. }
  246. return;
  247. }
  248. void LOGON::GetCachedCreds(
  249. PCWSTR pwszRealm,
  250. PCWSTR pwszTarget,
  251. PCREDENTIALW** pppCreds,
  252. DWORD* pdwCreds
  253. )
  254. {
  255. if (m_pSession->GetCachedCreds(pwszRealm,pwszTarget,pppCreds,pdwCreds) != FALSE)
  256. {
  257. PCREDENTIALW pCredToUse = *pppCreds[0];
  258. ::FileTimeToSystemTime(&(pCredToUse->LastWritten), &m_TimeCredsEntered);
  259. }
  260. }
  261. // -----------------------------------------------------------------------------
  262. BOOL LOGON::SetCredentials(
  263. PCWSTR pwszRealm,
  264. PCWSTR pwszTarget,
  265. PCWSTR pwszSignIn,
  266. PCWSTR pwszPassword,
  267. PSYSTEMTIME pTimeCredsEntered
  268. )
  269. {
  270. WCHAR wPass[256];
  271. PCREDENTIALW* ppCred = NULL;
  272. DWORD dwCreds = 0;
  273. PCREDENTIALW pCredToUse = NULL;
  274. if ((!pwszSignIn) && (!pwszPassword))
  275. {
  276. pTimeCredsEntered = NULL; // invalidate this parameter if cached creds are to be used
  277. GetCachedCreds(pwszRealm, pwszTarget, &ppCred, &dwCreds);
  278. if (dwCreds > 0 && ppCred[0] != NULL )
  279. {
  280. for ( DWORD idx = 0; idx < dwCreds; idx++ )
  281. {
  282. if ( ppCred[idx]->Type == CRED_TYPE_DOMAIN_VISIBLE_PASSWORD )
  283. {
  284. // check to see if prompt bit is set. If set, keep looking, only use if
  285. // the prompt bit isn't set.
  286. if ( !(ppCred[idx]->Flags & CRED_FLAGS_PROMPT_NOW) )
  287. {
  288. pCredToUse = ppCred[idx];
  289. break;
  290. }
  291. }
  292. }
  293. }
  294. if (pCredToUse == NULL)
  295. {
  296. return FALSE;
  297. }
  298. DecryptPassword(wPass,
  299. PVOID(pCredToUse->CredentialBlob),
  300. pCredToUse->CredentialBlobSize);
  301. pwszSignIn = pCredToUse->UserName;
  302. pwszPassword = wPass;
  303. }
  304. else
  305. {
  306. if (pTimeCredsEntered == NULL)
  307. {
  308. DoTraceMessage(PP_LOG_ERROR, "LOGON::SetCredentials() failed; Timestamp not specified");
  309. return FALSE;
  310. }
  311. }
  312. if (m_pwszSignIn)
  313. {
  314. delete [] m_pwszSignIn;
  315. }
  316. DWORD dwSignInLen = ::wcslen(pwszSignIn);
  317. m_pwszSignIn = new WCHAR[dwSignInLen + 1];
  318. if (m_pwszSignIn == NULL)
  319. {
  320. DoTraceMessage(PP_LOG_ERROR, "LOGON::SetCredentials() failed; not enough memory");
  321. return FALSE;
  322. }
  323. ::wcscpy(m_pwszSignIn, pwszSignIn);
  324. if (!m_Password.SetData(pwszPassword))
  325. {
  326. DoTraceMessage(PP_LOG_ERROR, "LOGON::SetCredentials() failed; not enough memory");
  327. delete [] m_pwszSignIn;
  328. m_pwszSignIn = NULL;
  329. return FALSE;
  330. }
  331. if (pTimeCredsEntered)
  332. {
  333. m_TimeCredsEntered = *pTimeCredsEntered;
  334. }
  335. m_fCredsPresent = TRUE;
  336. if (ppCred)
  337. {
  338. if (m_pSession->m_pfnCredFree)
  339. {
  340. m_pSession->m_pfnCredFree(ppCred);
  341. }
  342. }
  343. return TRUE;
  344. }
  345. BOOL Gif2Bmp(LPSTREAM pStream, HBITMAP* phBmp);
  346. // -----------------------------------------------------------------------------
  347. BOOL LOGON::DownLoadCoBrandBitmap(
  348. PWSTR pwszChallenge
  349. )
  350. {
  351. PP_ASSERT(pwszChallenge != NULL);
  352. PWSTR pwszCbUrl = NULL;
  353. BOOL fRet = FALSE;
  354. WCHAR Delimiters[] = L",";
  355. PWSTR Token = ::wcstok(pwszChallenge, Delimiters);
  356. while (Token != NULL)
  357. {
  358. // skip leading white spaces
  359. while (*Token == (L" ")[0]) { ++Token; }
  360. if (Token == NULL)
  361. {
  362. DoTraceMessage(PP_LOG_WARNING, "LOGON::DownLoadCoBrandBitmap() : no text in between commas");
  363. goto next_token;
  364. }
  365. // find cburl
  366. if (!::_wcsnicmp(Token, L"cburl", ::wcslen(L"cburl")))
  367. {
  368. PWSTR CbUrl = ::wcsstr(Token, L"=");
  369. if (CbUrl == NULL)
  370. {
  371. DoTraceMessage(PP_LOG_WARNING, "LOGON::DownLoadCoBrandBitmap() : no = after cburl");
  372. goto next_token;
  373. }
  374. CbUrl++; // skip "="
  375. while (*CbUrl == (L" ")[0]) { ++CbUrl; } // skip leading white spaces
  376. pwszCbUrl = new WCHAR[::wcslen(CbUrl)+1];
  377. if (pwszCbUrl == NULL)
  378. {
  379. DoTraceMessage(PP_LOG_ERROR, "LOGON::DownLoadCoBrandBitmap() failed; not enough memory");
  380. goto exit;
  381. }
  382. ::wcscpy(pwszCbUrl, CbUrl);
  383. DoTraceMessage(PP_LOG_INFO, "CoBrand URL %ws found", pwszCbUrl);
  384. }
  385. else if (!::_wcsnicmp(Token, L"ts", ::wcslen(L"ts")))
  386. {
  387. ::wcscpy(m_wTimeSkew, Token);
  388. }
  389. else if (!::_wcsnicmp(Token, L"srealm", ::wcslen(L"srealm")))
  390. {
  391. PWSTR pwszRealm = ::wcsstr(Token, L"=");
  392. if (pwszRealm == NULL)
  393. {
  394. DoTraceMessage(PP_LOG_WARNING, "LOGON::DownLoadCoBrandBitmap() : no = after cburl");
  395. goto next_token;
  396. }
  397. pwszRealm++; // skip "="
  398. while (*pwszRealm == (L" ")[0]) { ++pwszRealm; } // skip leading white spaces
  399. ::wcscpy( m_wRealm, pwszRealm);
  400. DoTraceMessage(PP_LOG_INFO, "sRealm URL %ws found", pwszCbUrl);
  401. }
  402. else if (!::_wcsnicmp(Token, L"cbtxt", ::wcslen(L"cbtxt")))
  403. {
  404. PWSTR pwszCbTxt = ::wcsstr(Token, L"=");
  405. if (pwszCbTxt == NULL)
  406. {
  407. DoTraceMessage(PP_LOG_WARNING, "LOGON::DownLoadCoBrandBitmap() : no = after cbtxt");
  408. goto next_token;
  409. }
  410. pwszCbTxt++; // skip "="
  411. while (*pwszCbTxt == (L" ")[0]) { ++pwszCbTxt; } // skip leading white spaces
  412. if (m_pwszCbtxt)
  413. {
  414. delete [] m_pwszCbtxt;
  415. }
  416. m_pwszCbtxt = new WCHAR[wcslen(pwszCbTxt)+1];
  417. if (m_pwszCbtxt)
  418. {
  419. ::wcscpy( m_pwszCbtxt, pwszCbTxt);
  420. DoTraceMessage(PP_LOG_INFO, "cbtxt %ws found", m_pwszCbtxt);
  421. }
  422. }
  423. next_token:
  424. Token = ::wcstok(NULL, Delimiters);
  425. }
  426. if (pwszCbUrl)
  427. {
  428. HINTERNET hCbUrl = m_pSession->OpenUrl(pwszCbUrl, NULL, 0, 0);
  429. if (hCbUrl == NULL)
  430. {
  431. DWORD dwErrorCode = ::GetLastError();
  432. DoTraceMessage(PP_LOG_ERROR, "LOGON::DownLoadCoBrandBitmap() failed; can not open URL %ws",
  433. pwszCbUrl);
  434. goto exit;
  435. }
  436. {
  437. LPSTREAM pStream;
  438. if (CreateStreamOnHGlobal(NULL, TRUE, &pStream) != S_OK)
  439. {
  440. DoTraceMessage(PP_LOG_ERROR, "CreateStreamOnHGlobal() failed");
  441. m_pSession->CloseHandle(hCbUrl);
  442. goto exit;
  443. }
  444. {
  445. DWORD cbRead = 0;
  446. PBYTE bBuf = new BYTE[1024];
  447. if (bBuf == NULL)
  448. {
  449. DoTraceMessage(PP_LOG_ERROR, "CreateStreamOnHGlobal() failed; out of memory");
  450. m_pSession->CloseHandle(hCbUrl);
  451. goto exit;
  452. }
  453. DWORD cbBuf = 1024;
  454. while (m_pSession->ReadFile(hCbUrl, bBuf, cbBuf, &cbRead) && cbRead)
  455. pStream->Write(bBuf, cbRead, NULL);
  456. delete [] bBuf;
  457. }
  458. LARGE_INTEGER Zero = {0};
  459. pStream->Seek(Zero, STREAM_SEEK_SET, NULL); // seek to the beginning of the stream
  460. DoTraceMessage(PP_LOG_INFO, "CoBrand Graphic %ws downloaded", pwszCbUrl);
  461. if (m_hBitmap)
  462. {
  463. DeleteObject(m_hBitmap);
  464. m_hBitmap = NULL;
  465. }
  466. if (Gif2Bmp(pStream, &m_hBitmap) == FALSE)
  467. {
  468. DoTraceMessage(PP_LOG_ERROR, "Gif2Bmp() failed");
  469. m_pSession->CloseHandle(hCbUrl);
  470. goto exit;
  471. }
  472. pStream->Release();
  473. m_pSession->CloseHandle(hCbUrl);
  474. fRet = TRUE;
  475. DoTraceMessage(PP_LOG_INFO, "CoBrand Bitmap created");
  476. }
  477. }
  478. exit:
  479. if (pwszCbUrl)
  480. {
  481. delete [] pwszCbUrl;
  482. }
  483. return fRet;
  484. }
  485. // -----------------------------------------------------------------------------
  486. DWORD LOGON::Handle401FromDA(
  487. HINTERNET hRequest,
  488. BOOL fTicketRequest
  489. )
  490. {
  491. PP_ASSERT(hRequest != NULL);
  492. DWORD dwRetVal = PP_GENERIC_ERROR;
  493. PWSTR pwszRawHeaders = NULL;
  494. PSTR pszRawHeaders = NULL;
  495. PWSTR pwszChallenge = NULL;
  496. PWSTR pwszChallengeEnd = NULL;
  497. DWORD ChallengeLength = 0;
  498. if(m_pSession->QueryHeaders(hRequest,
  499. HTTP_QUERY_RAW_HEADERS_CRLF,
  500. 0,
  501. &ChallengeLength) == FALSE)
  502. {
  503. if ((::GetLastError() != ERROR_INSUFFICIENT_BUFFER) || (ChallengeLength == 0))
  504. {
  505. DWORD dwErrorCode = ::GetLastError();
  506. DoTraceMessage(PP_LOG_ERROR, "Handle401FromDA() failed; QueryHeaders() failed; Error Code = %d",
  507. dwErrorCode);
  508. goto exit;
  509. }
  510. }
  511. else
  512. {
  513. PP_ASSERT(TRUE); // control should not reach here
  514. }
  515. pwszRawHeaders = new WCHAR[ChallengeLength];
  516. if (pwszRawHeaders == NULL)
  517. {
  518. DoTraceMessage(PP_LOG_ERROR, "Handle401FromDA() failed; out of memory");
  519. goto exit;
  520. }
  521. if(m_pSession->QueryHeaders(hRequest,
  522. HTTP_QUERY_RAW_HEADERS_CRLF,
  523. pwszRawHeaders,
  524. &ChallengeLength) == FALSE)
  525. {
  526. DWORD dwErrorCode = ::GetLastError();
  527. DoTraceMessage(PP_LOG_ERROR, "Handle401FromDA() failed; QueryHeaders() failed; Error Code = %d",
  528. dwErrorCode);
  529. goto exit;
  530. }
  531. if ((pwszChallenge = ::wcsstr(pwszRawHeaders, L"Passport1.4")) == NULL)
  532. {
  533. DoTraceMessage(PP_LOG_ERROR, "Handle401FromDA() failed; Passport1.4 auth header not found");
  534. goto exit;
  535. }
  536. if (pwszChallengeEnd = ::wcsstr(pwszChallenge, L"\r\n"))
  537. {
  538. *pwszChallengeEnd = 0;
  539. }
  540. if (::wcsstr(pwszChallenge, L"noretry"))
  541. {
  542. dwRetVal = PP_LOGON_FAILED; // Login Request Failed; bad news!
  543. DoTraceMessage(PP_LOG_WARNING, "Handle401FromDA() : Logon failed");
  544. }
  545. else if (::wcsstr(pwszChallenge, L"retry"))
  546. {
  547. // biaow-todo: not yet implemented
  548. PP_ASSERT(TRUE); // shouldn't reach here
  549. dwRetVal = PP_LOGON_REQUIRED;
  550. }
  551. else if (::wcsstr(pwszChallenge, L"failed"))
  552. {
  553. // if (fTicketRequest)
  554. // {
  555. dwRetVal = PP_LOGON_REQUIRED;
  556. DoTraceMessage(PP_LOG_INFO, "Handle401FromDA() : Logon required by DA");
  557. // }
  558. // else
  559. // {
  560. // dwRetVal = PP_LOGON_FAILED; // Login Request Failed; bad news!
  561. // DoTraceMessage(PP_LOG_WARNING, "Handle401FromDA() : Logon failed");
  562. // }
  563. }
  564. else
  565. {
  566. DoTraceMessage(PP_LOG_ERROR, "Handle401FromDA() failed; no valid DA status");
  567. goto exit;
  568. }
  569. if (dwRetVal == PP_LOGON_REQUIRED || dwRetVal == PP_LOGON_FAILED)
  570. {
  571. if (::wcsstr(pwszChallenge, L"prompt"))
  572. {
  573. m_fPrompt = TRUE;
  574. }
  575. else
  576. {
  577. m_fPrompt = FALSE;
  578. }
  579. if (CreateStreamOnHGlobal(NULL, TRUE, &m_p401Content) != S_OK)
  580. {
  581. DoTraceMessage(PP_LOG_ERROR, "CreateStreamOnHGlobal() failed");
  582. goto exit;
  583. }
  584. if (pwszChallengeEnd)
  585. {
  586. PP_ASSERT(*pwszChallengeEnd == 0);
  587. *pwszChallengeEnd = L'\r';
  588. }
  589. pszRawHeaders = new CHAR[2048];
  590. if (pszRawHeaders == NULL)
  591. {
  592. DoTraceMessage(PP_LOG_ERROR, "CreateStreamOnHGlobal() failed, out of memory");
  593. goto exit;
  594. }
  595. ::WideCharToMultiByte(CP_ACP, 0, pwszRawHeaders, -1, pszRawHeaders, 2048, NULL, NULL);
  596. m_p401Content->Write(pszRawHeaders, strlen(pszRawHeaders), NULL);
  597. {
  598. DWORD cbRead = 0;
  599. PBYTE bBuf = new BYTE [1024];
  600. if (bBuf == NULL)
  601. {
  602. DoTraceMessage(PP_LOG_ERROR, "CreateStreamOnHGlobal() failed, out of memory");
  603. goto exit;
  604. }
  605. DWORD cbBuf = 1024;
  606. while (m_pSession->ReadFile(hRequest, bBuf, cbBuf, &cbRead) && cbRead)
  607. m_p401Content->Write(bBuf, cbRead, NULL);
  608. delete [] bBuf;
  609. }
  610. LARGE_INTEGER Zero = {0};
  611. m_p401Content->Seek(Zero, STREAM_SEEK_SET, NULL); // seek to the beginning of the stream
  612. if (pwszChallengeEnd)
  613. {
  614. *pwszChallengeEnd = 0;
  615. }
  616. DownLoadCoBrandBitmap(pwszChallenge);
  617. }
  618. exit:
  619. if (pwszRawHeaders)
  620. {
  621. delete [] pwszRawHeaders;
  622. }
  623. if (pszRawHeaders)
  624. {
  625. delete [] pszRawHeaders;
  626. }
  627. return dwRetVal;
  628. }
  629. // -----------------------------------------------------------------------------
  630. DWORD LOGON::Handle200FromDA(
  631. HINTERNET hRequest
  632. )
  633. {
  634. PP_ASSERT(hRequest != NULL);
  635. DWORD dwRetVal = PP_GENERIC_ERROR;
  636. PWSTR pwszBuffer = NULL;
  637. DWORD dwBuffer = 0;
  638. if((!m_pSession->QueryHeaders(hRequest,
  639. HTTP_QUERY_AUTHENTICATION_INFO,
  640. pwszBuffer,
  641. &dwBuffer))
  642. && (::GetLastError() == ERROR_INSUFFICIENT_BUFFER))
  643. {
  644. pwszBuffer = new WCHAR[dwBuffer];
  645. if (pwszBuffer == NULL)
  646. {
  647. DoTraceMessage(PP_LOG_ERROR, "LOGON::Handle200FromDA() failed; not enough memory");
  648. goto exit;
  649. }
  650. if (!m_pSession->QueryHeaders(hRequest,
  651. HTTP_QUERY_AUTHENTICATION_INFO,
  652. pwszBuffer,
  653. &dwBuffer))
  654. {
  655. DoTraceMessage(PP_LOG_ERROR, "LOGON::Handle200FromDA() failed; no Authenticate-Info header found");
  656. goto exit;
  657. }
  658. WCHAR Delimiters[] = L",";
  659. PWSTR Token = ::wcstok(pwszBuffer, Delimiters);
  660. while (Token != NULL)
  661. {
  662. while (*Token == (L" ")[0]) { ++Token; }
  663. if (Token == NULL)
  664. {
  665. DoTraceMessage(PP_LOG_WARNING, "LOGON::Handle200FromDA() : no text in between commas");
  666. goto next_token;
  667. }
  668. if (!::_wcsnicmp(Token, L"ru", ::wcslen(L"ru")))
  669. {
  670. PWSTR ReturnUrl = ::wcsstr(Token, L"=");
  671. if (ReturnUrl == NULL)
  672. {
  673. DoTraceMessage(PP_LOG_ERROR, "LOGON::Handle200FromDA() : no = after cburl");
  674. goto exit;
  675. }
  676. ReturnUrl++; // skip =
  677. while (*ReturnUrl == (L" ")[0]) { ++ReturnUrl; } // skip leading white spaces
  678. m_pwszReturnUrl = new WCHAR[::wcslen(ReturnUrl)+1];
  679. if (m_pwszReturnUrl == NULL)
  680. {
  681. DoTraceMessage(PP_LOG_ERROR, "LOGON::Handle200FromDA() failed; not enough memory");
  682. goto exit;
  683. }
  684. ::wcscpy(m_pwszReturnUrl, ReturnUrl);
  685. }
  686. else if (!::_wcsnicmp(Token, L"from-pp", ::wcslen(L"from-pp")))
  687. {
  688. m_pwszAuthInfo = new WCHAR[::wcslen(Token)+1];
  689. if (m_pwszAuthInfo == NULL)
  690. {
  691. DoTraceMessage(PP_LOG_ERROR, "LOGON::Handle200FromDA() failed; not enough memory");
  692. goto exit;
  693. }
  694. ::wcscpy(m_pwszAuthInfo, Token);
  695. }
  696. next_token:
  697. Token = ::wcstok(NULL, Delimiters);
  698. }
  699. dwRetVal = PP_LOGON_SUCCESS;
  700. g_fCurrentProcessLoggedOn = TRUE;
  701. }
  702. else
  703. {
  704. PP_ASSERT(TRUE); // shouldn't reach here
  705. goto exit;
  706. }
  707. exit:
  708. if (pwszBuffer)
  709. {
  710. delete [] pwszBuffer;
  711. }
  712. return dwRetVal;
  713. }
  714. void LOGON::CheckForVersionChange(
  715. HINTERNET hRequest
  716. )
  717. {
  718. WCHAR wszBuffer[256];
  719. DWORD dwBufferLen = sizeof(wszBuffer) / sizeof(WCHAR);
  720. BOOL fDownloadNewNexusConfig = FALSE;
  721. if (!m_pSession->QueryHeaders(hRequest,
  722. HTTP_QUERY_PASSPORT_CONFIG,
  723. wszBuffer,
  724. &dwBufferLen))
  725. {
  726. DoTraceMessage(PP_LOG_ERROR, "LOGON::CheckForVersionChange() failed; no PassportConfig header found");
  727. goto exit;
  728. }
  729. WCHAR Delimiters[] = L",";
  730. PWSTR Token = ::wcstok(wszBuffer, Delimiters);
  731. while (Token != NULL)
  732. {
  733. // skip leading white spaces
  734. while (*Token == (L" ")[0]) { ++Token; }
  735. if (Token == NULL)
  736. {
  737. DoTraceMessage(PP_LOG_WARNING, "LOGON::CheckForVersionChange() : no text in between commas");
  738. goto next_token;
  739. }
  740. if (!::_wcsnicmp(Token, L"ConfigVersion", ::wcslen(L"ConfigVersion")))
  741. {
  742. PWSTR pwszConfigVersion = ::wcsstr(Token, L"=");
  743. if (pwszConfigVersion == NULL)
  744. {
  745. DoTraceMessage(PP_LOG_WARNING, "LOGON::CheckForVersionChange() : no = after ConfigVersion");
  746. goto next_token;
  747. }
  748. pwszConfigVersion++; // skip "="
  749. while (*pwszConfigVersion == (L" ")[0]) { ++pwszConfigVersion; } // skip leading white spaces
  750. if ((DWORD)_wtoi(pwszConfigVersion) > m_pSession->GetNexusVersion())
  751. {
  752. fDownloadNewNexusConfig = TRUE;
  753. }
  754. DoTraceMessage(PP_LOG_INFO, "ConfigVersion URL %ws found", pwszConfigVersion);
  755. }
  756. next_token:
  757. Token = ::wcstok(NULL, Delimiters);
  758. }
  759. if (fDownloadNewNexusConfig)
  760. {
  761. m_pSession->GetDAInfoFromPPNexus(FALSE, // don't force connection establishment if nexus not reachable
  762. NULL,
  763. 0,
  764. NULL,
  765. 0);
  766. }
  767. exit:
  768. return;
  769. }
  770. VOID PrvLogonStatusCallback(
  771. IN HINTERNET hInternet,
  772. IN DWORD_PTR dwContext,
  773. IN DWORD dwInternetStatus,
  774. IN LPVOID lpvStatusInformation,
  775. IN DWORD dwStatusInformationLength
  776. )
  777. {
  778. LOGON* pLogon = reinterpret_cast<LOGON*>(dwContext);
  779. pLogon->StatusCallback(hInternet,
  780. dwInternetStatus,
  781. lpvStatusInformation,
  782. dwStatusInformationLength);
  783. }
  784. VOID LOGON::StatusCallback(
  785. IN HINTERNET hInternet,
  786. IN DWORD dwInternetStatus,
  787. IN LPVOID lpvStatusInformation,
  788. IN DWORD dwStatusInformationLength)
  789. {
  790. if (dwInternetStatus == INTERNET_STATUS_REDIRECT)
  791. {
  792. ::wcscpy(m_wNewDAUrl, (LPCWSTR)lpvStatusInformation);
  793. BOOL fRet = m_pSession->AddHeaders(hInternet,
  794. m_pwszAuthHeader,
  795. ::wcslen(m_pwszAuthHeader),
  796. HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE
  797. );
  798. PP_ASSERT(fRet == TRUE);
  799. }
  800. else if ((dwInternetStatus == INTERNET_STATUS_COOKIE_SENT) ||
  801. (dwInternetStatus == INTERNET_STATUS_COOKIE_RECEIVED))
  802. {
  803. PVOID lpvInfo = new BYTE [dwStatusInformationLength];
  804. if (lpvInfo == 0)
  805. {
  806. return;
  807. }
  808. memcpy(lpvInfo, lpvStatusInformation, dwStatusInformationLength);
  809. LPCWSTR pwszLocation = m_wNewDAUrl[0] ? m_wNewDAUrl : m_pSession->GetCurrentDAUrl();
  810. LPSTR pszLocation = NULL;
  811. DWORD dwLocationLen = 0;
  812. if (dwLocationLen = wcslen(pwszLocation))
  813. {
  814. pszLocation = new CHAR[dwLocationLen + 1];
  815. if (pszLocation == 0)
  816. {
  817. return;
  818. }
  819. ::WideCharToMultiByte(CP_ACP, 0, pwszLocation, -1, pszLocation, dwLocationLen + 1, NULL, NULL);
  820. if (dwInternetStatus == INTERNET_STATUS_COOKIE_SENT)
  821. {
  822. ((OutgoingCookieState*)lpvInfo)->pszLocation = pszLocation;
  823. }
  824. else
  825. {
  826. ((IncomingCookieState*)lpvInfo)->pszLocation = pszLocation;
  827. }
  828. }
  829. PRIVACY_EVENT* pEvent = new PRIVACY_EVENT;
  830. if (pEvent != NULL)
  831. {
  832. pEvent->dwStatus = dwInternetStatus;
  833. pEvent->lpvInfo = lpvInfo;
  834. pEvent->dwInfoLength = dwStatusInformationLength;
  835. InsertTailList(&m_PrivacyEventList, &(pEvent->List));
  836. }
  837. }
  838. }
  839. BOOL LOGON::GetLogonHost(
  840. PWSTR pwszHostName,
  841. OUT PDWORD pdwHostNameLen
  842. ) const
  843. {
  844. if (*pdwHostNameLen < DWORD(::wcslen(m_wDAHostName) + 1))
  845. {
  846. *pdwHostNameLen = ::wcslen(m_wDAHostName) + 1;
  847. return FALSE;
  848. }
  849. PP_ASSERT(pwszHostName != NULL);
  850. ::wcscpy(pwszHostName, m_wDAHostName);
  851. *pdwHostNameLen = ::wcslen(m_wDAHostName) + 1;
  852. return TRUE;
  853. }
  854. BOOL PPEscapeUrl(LPCSTR lpszStringIn,
  855. LPSTR lpszStringOut,
  856. DWORD* pdwStrLen,
  857. DWORD dwMaxLength,
  858. DWORD dwFlags);
  859. // -----------------------------------------------------------------------------
  860. DWORD LOGON::Logon(
  861. BOOL fAnonymous
  862. )
  863. {
  864. PP_ASSERT(m_pSession != NULL);
  865. DWORD dwRetVal = PP_GENERIC_ERROR;
  866. BOOL fTicketRequest;
  867. HINTERNET hRequest = 0;
  868. DWORD dwFlags = 0;
  869. ::wcscpy(m_pwszAuthHeader, L"Authorization: Passport1.4 ");
  870. LPWSTR pwszPassword = m_Password.GetUnencryptedString();
  871. if (m_fCredsPresent && !fAnonymous)
  872. {
  873. if (m_pSession->GetNexusVersion() >= 10)
  874. {
  875. DWORD dwUTF8CredLen = max(::wcslen(m_pwszSignIn), ::wcslen(pwszPassword)) * 3;
  876. DWORD dwEscCredLen = dwUTF8CredLen * 3;
  877. DWORD dwActualEscCredLen;
  878. PSTR pszUTF8Cred = new CHAR[dwUTF8CredLen];
  879. if (pszUTF8Cred == NULL)
  880. {
  881. goto exit;
  882. }
  883. PSTR pszEscCred = new CHAR[dwEscCredLen];
  884. if (pszEscCred == NULL)
  885. {
  886. delete [] pszUTF8Cred;
  887. goto exit;
  888. }
  889. PWSTR pwszEscCred = new WCHAR[dwEscCredLen];
  890. if (pwszEscCred == NULL)
  891. {
  892. delete [] pszEscCred;
  893. delete [] pszUTF8Cred;
  894. goto exit;
  895. }
  896. ::WideCharToMultiByte(CP_UTF8, 0, m_pwszSignIn, -1, pszUTF8Cred, dwUTF8CredLen, NULL, NULL);
  897. ::PPEscapeUrl(pszUTF8Cred, pszEscCred, &dwActualEscCredLen, dwEscCredLen, 0);
  898. int cchEscCred = ::MultiByteToWideChar(CP_ACP, 0, pszEscCred, -1, pwszEscCred, dwEscCredLen);
  899. if ((cchEscCred - 1) > 1024)
  900. {
  901. pwszEscCred[1024] = L'\0';
  902. }
  903. ::wcscat(m_pwszAuthHeader, L"sign-in=");
  904. ::wcscat(m_pwszAuthHeader, pwszEscCred);
  905. ::wcscat(m_pwszAuthHeader, L",");
  906. ::WideCharToMultiByte(CP_UTF8, 0, pwszPassword, -1, pszUTF8Cred, dwUTF8CredLen, NULL, NULL);
  907. ::PPEscapeUrl(pszUTF8Cred, pszEscCred, &dwActualEscCredLen, dwEscCredLen, 0);
  908. cchEscCred = ::MultiByteToWideChar(CP_ACP, 0, pszEscCred, -1, pwszEscCred, dwEscCredLen);
  909. if ((cchEscCred - 1) > 1024)
  910. {
  911. pwszEscCred[1024] = L'\0';
  912. }
  913. ::wcscat(m_pwszAuthHeader, L"pwd=");
  914. ::wcscat(m_pwszAuthHeader, pwszEscCred);
  915. ::wcscat(m_pwszAuthHeader, L",");
  916. delete [] pwszEscCred;
  917. delete [] pszEscCred;
  918. delete [] pszUTF8Cred;
  919. }
  920. else
  921. {
  922. if (::wcslen(m_pwszSignIn) > 1024)
  923. {
  924. m_pwszSignIn[1024] = L'\0';
  925. }
  926. ::wcscat(m_pwszAuthHeader, L"sign-in=");
  927. ::wcscat(m_pwszAuthHeader, m_pwszSignIn);
  928. ::wcscat(m_pwszAuthHeader, L",");
  929. if (::wcslen(pwszPassword) > 1024)
  930. {
  931. pwszPassword[1024] = L'\0';
  932. }
  933. ::wcscat(m_pwszAuthHeader, L"pwd=");
  934. ::wcscat(m_pwszAuthHeader, pwszPassword);
  935. ::wcscat(m_pwszAuthHeader, L",");
  936. }
  937. FILETIME ftCredsEntered;
  938. ::SystemTimeToFileTime(&m_TimeCredsEntered, &ftCredsEntered);
  939. SYSTEMTIME stCurrent;
  940. ::GetSystemTime(&stCurrent);
  941. FILETIME ftCurrent;
  942. ::SystemTimeToFileTime(&stCurrent, &ftCurrent);
  943. LONGLONG llElapsedTime;
  944. llElapsedTime = (*(LONGLONG *)&ftCurrent) - (*(LONGLONG *)&ftCredsEntered);
  945. llElapsedTime /= (LONGLONG)10000000;
  946. DWORD dwElapsedTime = (DWORD)llElapsedTime;
  947. WCHAR wElapsedTime[16];
  948. ::wsprintfW(wElapsedTime, L"%d", dwElapsedTime);
  949. ::wcscat(m_pwszAuthHeader, L"elapsed-time=");
  950. ::wcscat(m_pwszAuthHeader, wElapsedTime);
  951. ::wcscat(m_pwszAuthHeader, L",");
  952. if (m_wTimeSkew[0])
  953. {
  954. ::wcscat(m_pwszAuthHeader, m_wTimeSkew);
  955. ::wcscat(m_pwszAuthHeader, L",");
  956. }
  957. fTicketRequest = FALSE; // this is a login request, since we've gather credentials
  958. // save off the sign-in name
  959. if ( ::wcslen ( m_pwszSignIn ) < INTERNET_MAX_USER_NAME_LENGTH )
  960. ::wcscpy ( g_szUserNameLoggedOn, m_pwszSignIn );
  961. }
  962. else
  963. {
  964. ::wcscat(m_pwszAuthHeader, L"tname = , ");
  965. fTicketRequest = TRUE;
  966. }
  967. ::wcscat(m_pwszAuthHeader, m_pwszTicketRequest);
  968. if (pwszPassword != NULL)
  969. {
  970. SecureZeroMemory(pwszPassword, ::wcslen(pwszPassword) * sizeof(WCHAR));
  971. delete [] pwszPassword;
  972. pwszPassword = NULL;
  973. }
  974. retry:
  975. // attempt connecting to the Passport DA
  976. if (m_hConnect)
  977. {
  978. m_pSession->CloseHandle(m_hConnect);
  979. }
  980. WCHAR wDATargetObj[256];
  981. DWORD fStstus = m_pSession->GetDAInfo(m_pwszSignIn,
  982. m_wDAHostName, 256,
  983. wDATargetObj, 256);
  984. if (fStstus == FALSE)
  985. {
  986. goto exit;
  987. }
  988. m_hConnect = m_pSession->Connect(m_wDAHostName/*m_pSession->GetLoginHost()*/,
  989. #ifdef DISABLE_SSL
  990. INTERNET_DEFAULT_HTTP_PORT
  991. #else
  992. INTERNET_DEFAULT_HTTPS_PORT
  993. #endif
  994. );
  995. if (m_hConnect == NULL)
  996. {
  997. DWORD dwErrorCode = ::GetLastError();
  998. DoTraceMessage(PP_LOG_ERROR, "LOGON::Open() failed; can not connect to %ws, Error = %d",
  999. m_wDAHostName, dwErrorCode);
  1000. goto exit;
  1001. }
  1002. if (hRequest)
  1003. {
  1004. m_pSession->CloseHandle(hRequest);
  1005. }
  1006. dwFlags = m_dwParentFlags;
  1007. hRequest = m_pSession->OpenRequest(m_hConnect,
  1008. NULL, // "GET"
  1009. wDATargetObj/*m_pSession->GetLoginTarget()*/,
  1010. #ifdef DISABLE_SSL
  1011. dwFlags | INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS,
  1012. #else
  1013. dwFlags | INTERNET_FLAG_SECURE,
  1014. #endif
  1015. (DWORD_PTR)this
  1016. );
  1017. if (hRequest == NULL)
  1018. {
  1019. DWORD dwErrorCode = ::GetLastError();
  1020. DoTraceMessage(PP_LOG_ERROR, "LOGON::Logon() failed; OpenRequest() to %ws failed, Error Code = %d",
  1021. wDATargetObj, dwErrorCode);
  1022. goto exit;
  1023. }
  1024. m_wNewDAUrl[0] = 0;
  1025. m_pSession->SetStatusCallback(hRequest, PrvLogonStatusCallback);
  1026. if (!m_pSession->SendRequest(hRequest,
  1027. m_pwszAuthHeader,
  1028. ::wcslen(m_pwszAuthHeader),
  1029. (DWORD_PTR)this))
  1030. {
  1031. DWORD dwErrorCode = ::GetLastError();
  1032. #ifdef BAD_CERT_OK
  1033. if (dwErrorCode == ERROR_INTERNET_INVALID_CA)
  1034. {
  1035. DWORD dwSecFlags;
  1036. DWORD dwSecurityFlagsSize = sizeof(dwSecFlags);
  1037. if (!m_pSession->QueryOption(hRequest,
  1038. INTERNET_OPTION_SECURITY_FLAGS,
  1039. &dwSecFlags,
  1040. &dwSecurityFlagsSize))
  1041. {
  1042. dwSecFlags = 0;
  1043. }
  1044. else
  1045. {
  1046. dwSecFlags |= SECURITY_SET_MASK;
  1047. }
  1048. if (!m_pSession->SetOption(hRequest,
  1049. INTERNET_OPTION_SECURITY_FLAGS,
  1050. &dwSecFlags,
  1051. dwSecurityFlagsSize))
  1052. {
  1053. PP_ASSERT(TRUE); // shouldn't reach here
  1054. goto exit;
  1055. }
  1056. else
  1057. {
  1058. if (!m_pSession->SendRequest(hRequest, NULL, 0))
  1059. {
  1060. dwErrorCode = ::GetLastError();
  1061. DoTraceMessage(PP_LOG_ERROR, "LOGON::Logon() failed; SendRequest() failed, Error Code = %d",
  1062. dwErrorCode);
  1063. goto exit;
  1064. }
  1065. else
  1066. {
  1067. dwErrorCode = ERROR_SUCCESS;
  1068. }
  1069. }
  1070. }
  1071. #endif // BAD_CERT_OK
  1072. if (dwErrorCode != ERROR_SUCCESS)
  1073. {
  1074. DoTraceMessage(PP_LOG_ERROR, "LOGON::Logon() failed; SendRequest() failed, Error Code = %d",
  1075. dwErrorCode);
  1076. m_pSession->PurgeDAInfo(m_pwszSignIn);
  1077. if (m_pSession->GetDAInfoFromPPNexus(FALSE, // don't force connection establishment if nexus not reachable
  1078. NULL,
  1079. 0,
  1080. NULL,
  1081. 0) == TRUE)
  1082. {
  1083. goto retry;
  1084. }
  1085. goto exit;
  1086. }
  1087. }
  1088. {
  1089. DWORD dwStatus, dwStatusLen;
  1090. dwStatusLen = sizeof(dwStatus);
  1091. if (!m_pSession->QueryHeaders(hRequest,
  1092. HTTP_QUERY_FLAG_NUMBER | HTTP_QUERY_STATUS_CODE,
  1093. &dwStatus,
  1094. &dwStatusLen))
  1095. {
  1096. DWORD dwErrorCode = ::GetLastError();
  1097. DoTraceMessage(PP_LOG_ERROR, "LOGON::Logon() failed; can not retrieve Status Code, Error Code = %d",
  1098. dwErrorCode);
  1099. goto exit;
  1100. }
  1101. if (dwStatus == HTTP_STATUS_DENIED)
  1102. {
  1103. dwRetVal = Handle401FromDA(hRequest, fTicketRequest);
  1104. }
  1105. else if (dwStatus == HTTP_STATUS_OK)
  1106. {
  1107. dwRetVal = Handle200FromDA(hRequest);
  1108. }
  1109. else
  1110. {
  1111. //PP_ASSERT(TRUE); // shouldn't reach here
  1112. //goto exit;
  1113. }
  1114. CheckForVersionChange(hRequest);
  1115. if (dwRetVal == PP_GENERIC_ERROR)
  1116. {
  1117. m_pSession->PurgeDAInfo(m_pwszSignIn);
  1118. if (m_pSession->GetDAInfoFromPPNexus(FALSE, // don't force connection establishment if nexus not reachable
  1119. NULL,
  1120. 0,
  1121. NULL,
  1122. 0) == TRUE)
  1123. {
  1124. goto retry;
  1125. }
  1126. }
  1127. else
  1128. {
  1129. if (m_wNewDAUrl[0])
  1130. {
  1131. m_pSession->UpdateDAInfo(m_pwszSignIn,
  1132. m_wNewDAUrl);
  1133. m_wNewDAUrl[0] = 0;
  1134. }
  1135. }
  1136. }
  1137. exit:
  1138. if (hRequest)
  1139. {
  1140. m_pSession->CloseHandle(hRequest);
  1141. }
  1142. if (pwszPassword)
  1143. {
  1144. SecureZeroMemory(pwszPassword, ::wcslen(pwszPassword) * sizeof(WCHAR));
  1145. delete [] pwszPassword;
  1146. }
  1147. return dwRetVal;
  1148. }
  1149. // -----------------------------------------------------------------------------
  1150. BOOL LOGON::GetChallengeInfo(
  1151. HBITMAP* phBitmap,
  1152. PBOOL pfPrompt,
  1153. PWSTR pwszCbText,
  1154. PDWORD pdwTextLen,
  1155. PWSTR pwszRealm,
  1156. DWORD dwMaxRealmLen,
  1157. PWSTR pwszReqUserName,
  1158. PDWORD pdwReqUserNameLen
  1159. ) const
  1160. {
  1161. if (phBitmap)
  1162. {
  1163. *phBitmap = m_hBitmap;
  1164. }
  1165. if (pfPrompt)
  1166. {
  1167. *pfPrompt = m_fPrompt;
  1168. }
  1169. // *pdwTextLen = 0; // biaow-todo:
  1170. if (pwszRealm)
  1171. {
  1172. ::wcsncpy(pwszRealm, m_wRealm, dwMaxRealmLen-1);
  1173. }
  1174. if (m_pwszCbtxt == NULL)
  1175. {
  1176. if (pdwTextLen)
  1177. {
  1178. // tell them how much is needed
  1179. *pdwTextLen = 0;
  1180. }
  1181. goto CheckReqUserName;
  1182. }
  1183. if (pwszCbText && pdwTextLen )
  1184. {
  1185. // only copy if they gave us enough bytes.
  1186. if ( *pdwTextLen >= ::wcslen(m_pwszCbtxt) )
  1187. ::wcsncpy(pwszCbText, m_pwszCbtxt, *pdwTextLen);
  1188. }
  1189. if (pdwTextLen)
  1190. {
  1191. // tell them how much is needed
  1192. *pdwTextLen = ::wcslen(m_pwszCbtxt);
  1193. }
  1194. CheckReqUserName:
  1195. // username
  1196. if (pdwReqUserNameLen)
  1197. {
  1198. if (m_fPrompt && g_fCurrentProcessLoggedOn)
  1199. {
  1200. if ( *pdwReqUserNameLen >= ::wcslen (g_szUserNameLoggedOn) )
  1201. {
  1202. if ( pwszReqUserName != NULL )
  1203. {
  1204. wcsncpy ( pwszReqUserName, g_szUserNameLoggedOn, *pdwReqUserNameLen );
  1205. }
  1206. }
  1207. // tell them how much is needed
  1208. *pdwReqUserNameLen = ::wcslen (g_szUserNameLoggedOn) + 1;
  1209. }
  1210. else
  1211. {
  1212. // nothing is needed
  1213. *pdwReqUserNameLen = 0;
  1214. }
  1215. }
  1216. return TRUE;
  1217. }
  1218. BOOL LOGON::GetChallengeContent(
  1219. PBYTE pContent,
  1220. OUT PDWORD pdwContentLen
  1221. ) const
  1222. {
  1223. if (m_p401Content == NULL)
  1224. {
  1225. *pdwContentLen = 0;
  1226. return FALSE;
  1227. }
  1228. HGLOBAL hContent;
  1229. if (GetHGlobalFromStream(m_p401Content, &hContent) != S_OK)
  1230. {
  1231. *pdwContentLen = 0;
  1232. return FALSE;
  1233. }
  1234. DWORD dwContentLen = (DWORD)GlobalSize(hContent);
  1235. if (*pdwContentLen < dwContentLen)
  1236. {
  1237. *pdwContentLen = dwContentLen;
  1238. return FALSE;
  1239. }
  1240. LPVOID pvContent = GlobalLock(hContent);
  1241. memcpy(pContent, pvContent, dwContentLen);
  1242. GlobalUnlock(hContent);
  1243. *pdwContentLen = dwContentLen;
  1244. return TRUE;
  1245. }
  1246. // -----------------------------------------------------------------------------
  1247. BOOL LOGON::GetAuthorizationInfo(
  1248. PWSTR pwszTicket,
  1249. PDWORD pdwTicketLen,
  1250. PBOOL pfKeepVerb,
  1251. PWSTR pwszUrl,
  1252. PDWORD pdwUrlLen
  1253. ) const
  1254. {
  1255. if (*pdwTicketLen < DWORD(::wcslen(m_pwszAuthInfo) + 1))
  1256. {
  1257. *pdwTicketLen = ::wcslen(m_pwszAuthInfo) + 1;
  1258. return FALSE;
  1259. }
  1260. PP_ASSERT(pwszTicket != NULL);
  1261. ::wcscpy(pwszTicket, m_pwszAuthInfo);
  1262. *pdwTicketLen = ::wcslen(m_pwszAuthInfo) + 1;
  1263. if (m_pwszReturnUrl == NULL)
  1264. {
  1265. if (pfKeepVerb)
  1266. {
  1267. *pfKeepVerb = TRUE;
  1268. }
  1269. *pdwUrlLen = 0;
  1270. return TRUE;
  1271. }
  1272. if (*pdwUrlLen < DWORD(::wcslen(m_pwszReturnUrl) + 1))
  1273. {
  1274. *pdwUrlLen = ::wcslen(m_pwszReturnUrl) + 1;
  1275. return FALSE;
  1276. }
  1277. PP_ASSERT(pwszUrl != NULL);
  1278. ::wcscpy(pwszUrl, m_pwszReturnUrl);
  1279. if (pfKeepVerb)
  1280. {
  1281. *pfKeepVerb = FALSE;
  1282. }
  1283. *pdwUrlLen = ::wcslen(m_pwszReturnUrl) + 1;
  1284. return TRUE;
  1285. }