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.

1066 lines
29 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. #include "session.h"
  12. #include "logon.h"
  13. #include "ole2.h"
  14. #include "wincrypt.h"
  15. // #include "logon.tmh"
  16. #define HTTP_STATUS_DENIED 401 // access denied
  17. #define HTTP_STATUS_OK 200 // request completed
  18. #define HTTP_QUERY_FLAG_NUMBER 0x20000000
  19. #define HTTP_QUERY_STATUS_CODE 19 // special: part of status line
  20. #define HTTP_QUERY_AUTHENTICATION_INFO 76
  21. #define HTTP_QUERY_WWW_AUTHENTICATE 40
  22. // NOTE*** below we assume(!) the WinInet & WinHttp shared the same error VALUE
  23. #define ERROR_HTTP_HEADER_NOT_FOUND 12150L
  24. #define ERROR_INTERNET_INVALID_CA 12045L
  25. #define INTERNET_OPTION_SECURITY_FLAGS 31
  26. #define SECURITY_FLAG_IGNORE_REVOCATION 0x00000080
  27. #define SECURITY_FLAG_IGNORE_UNKNOWN_CA 0x00000100
  28. #define SECURITY_FLAG_IGNORE_WRONG_USAGE 0x00000200
  29. #define INTERNET_FLAG_IGNORE_CERT_CN_INVALID 0x00001000 // bad common name in X509 Cert.
  30. #define INTERNET_FLAG_IGNORE_CERT_DATE_INVALID 0x00002000 // expired X509 Cert.
  31. #define SECURITY_FLAG_IGNORE_CERT_CN_INVALID INTERNET_FLAG_IGNORE_CERT_CN_INVALID
  32. #define SECURITY_FLAG_IGNORE_CERT_DATE_INVALID INTERNET_FLAG_IGNORE_CERT_DATE_INVALID
  33. #define SECURITY_SET_MASK (SECURITY_FLAG_IGNORE_REVOCATION |\
  34. SECURITY_FLAG_IGNORE_UNKNOWN_CA |\
  35. SECURITY_FLAG_IGNORE_CERT_CN_INVALID |\
  36. SECURITY_FLAG_IGNORE_CERT_DATE_INVALID |\
  37. SECURITY_FLAG_IGNORE_WRONG_USAGE)
  38. #define INTERNET_DEFAULT_HTTP_PORT 80 // " " HTTP "
  39. #define INTERNET_DEFAULT_HTTPS_PORT 443 // " " HTTPS "
  40. #define INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS 0x00004000 // ex: http:// to https://
  41. #define INTERNET_STATUS_REDIRECT 110
  42. #define HTTP_ADDREQ_FLAG_ADD 0x20000000
  43. #define HTTP_ADDREQ_FLAG_REPLACE 0x80000000
  44. #define INTERNET_FLAG_SECURE 0x00800000 // use PCT/SSL if applicable (HTTP)
  45. LOGON::LOGON(SESSION* pSession, DWORD dwParentFlags)
  46. : m_pSession(pSession)
  47. {
  48. m_pSession->AddRef();
  49. m_hConnect = NULL;
  50. m_fCredsPresent = FALSE;
  51. m_pwszSignIn = NULL;
  52. m_pwszPassword = NULL;
  53. m_pwszTicketRequest = NULL;
  54. m_pwszAuthInfo = NULL;
  55. m_pwszReturnUrl = NULL;
  56. m_pBitmap = NULL;
  57. m_fPrompt = FALSE;
  58. m_wTimeSkew[0] = L'\0';
  59. m_wNewDAUrl[0] = 0;
  60. m_dwParentFlags = dwParentFlags;
  61. }
  62. LOGON::~LOGON(void)
  63. {
  64. if (m_pwszAuthInfo)
  65. {
  66. delete [] m_pwszAuthInfo;
  67. }
  68. if (m_pwszSignIn)
  69. {
  70. delete [] m_pwszSignIn;
  71. }
  72. if (m_pwszPassword)
  73. {
  74. delete [] m_pwszPassword;
  75. }
  76. if (m_pwszTicketRequest)
  77. {
  78. delete [] m_pwszTicketRequest;
  79. }
  80. if (m_pwszAuthHeader)
  81. {
  82. delete [] m_pwszAuthHeader;
  83. }
  84. m_pSession->RemoveRef();
  85. }
  86. // -----------------------------------------------------------------------------
  87. BOOL LOGON::Open(
  88. PCWSTR pwszPartnerInfo // in the form of "WWW-Authenticate: Passport1.4 ..."
  89. )
  90. {
  91. PP_ASSERT(pwszPartnerInfo != NULL);
  92. // locate the auth scheme name, i.e. Passport1.4
  93. PCWSTR pwszTicketRequest = ::wcsstr(pwszPartnerInfo, L"Passport1.4");
  94. if (pwszTicketRequest == NULL)
  95. {
  96. DoTraceMessage(PP_LOG_ERROR, "LOGON::Open() failed; Passport1.4 scheme not found");
  97. return FALSE;
  98. }
  99. pwszTicketRequest += ::wcslen(L"Passport1.4");
  100. // skip white spaces between the scheme name and the Ticket Request (TR)
  101. while (*pwszTicketRequest == (L" ")[0]) { ++pwszTicketRequest; }
  102. if (pwszTicketRequest == NULL)
  103. {
  104. DoTraceMessage(PP_LOG_ERROR, "LOGON::Open() failed; Ticket Request missing");
  105. return FALSE;
  106. }
  107. // save the TR
  108. DWORD dwTrLen = ::wcslen(pwszTicketRequest);
  109. m_pwszTicketRequest = new WCHAR[dwTrLen + 1];
  110. if (m_pwszTicketRequest == NULL)
  111. {
  112. DoTraceMessage(PP_LOG_ERROR, "LOGON::Open() failed; not enough memory");
  113. return FALSE;
  114. }
  115. ::wcscpy(m_pwszTicketRequest, pwszTicketRequest);
  116. m_pwszAuthHeader = new WCHAR[dwTrLen + 2048/*Prepared for long creds*/ + 1];
  117. if (m_pwszAuthHeader == NULL)
  118. {
  119. DoTraceMessage(PP_LOG_ERROR, "LOGON::Open() failed; not enough memory");
  120. return FALSE;
  121. }
  122. DoTraceMessage(PP_LOG_INFO, "LOGON::Open() succeed");
  123. return TRUE;
  124. }
  125. void LOGON::Close(void)
  126. {
  127. PP_ASSERT(m_hConnect != NULL);
  128. PP_ASSERT(m_pSession != NULL);
  129. m_pSession->CloseHandle(m_hConnect);
  130. m_hConnect = NULL;
  131. }
  132. // pClearPassword is assumed to be at least 256 chars
  133. void DecryptPassword ( WCHAR* pClearPassword, PVOID pPassword, DWORD cbSize )
  134. {
  135. BOOL bOrigEncrypted = FALSE;
  136. DATA_BLOB InBlob;
  137. DATA_BLOB OutBlob;
  138. LPWSTR pszDesc;
  139. if ( pClearPassword == NULL )
  140. return;
  141. if ( cbSize == 0 )
  142. {
  143. // CryptUnprotectData doesn't like to be sent a zero-length buffer
  144. pClearPassword[0] = L'\0';
  145. return;
  146. }
  147. InBlob.pbData = (BYTE*)pPassword;
  148. InBlob.cbData = cbSize;
  149. if ( CryptUnprotectData ( &InBlob,
  150. &pszDesc,
  151. NULL,
  152. NULL,
  153. NULL,
  154. CRYPTPROTECT_UI_FORBIDDEN,
  155. &OutBlob ) )
  156. {
  157. if ( wcscmp (L"SSOCred", pszDesc) == 0 )
  158. {
  159. DWORD dwOutChars = OutBlob.cbData/sizeof(WCHAR);
  160. if ( dwOutChars < 256 )
  161. {
  162. wcsncpy ( pClearPassword, (WCHAR*)OutBlob.pbData, dwOutChars );
  163. pClearPassword[dwOutChars] = L'\0';
  164. }
  165. bOrigEncrypted = TRUE;
  166. }
  167. LocalFree ( pszDesc );
  168. LocalFree ( OutBlob.pbData );
  169. }
  170. if ( !bOrigEncrypted )
  171. {
  172. // copy the plain text
  173. wcsncpy ( pClearPassword, (WCHAR*)pPassword, 256 );
  174. }
  175. return;
  176. }
  177. void LOGON::GetCachedCreds(
  178. PCWSTR pwszRealm,
  179. PCWSTR pwszTarget,
  180. PCREDENTIALW** pppCreds,
  181. DWORD* pdwCreds
  182. )
  183. {
  184. *pppCreds = NULL;
  185. *pdwCreds = 0;
  186. if (m_pSession->m_pfnReadDomainCred == NULL)
  187. {
  188. return;
  189. }
  190. ULONG CredTypes = CRED_TYPE_DOMAIN_VISIBLE_PASSWORD;
  191. DWORD dwFlags = CRED_CACHE_TARGET_INFORMATION;
  192. CREDENTIAL_TARGET_INFORMATIONW TargetInfo;
  193. memset ( (void*)&TargetInfo, 0, sizeof(CREDENTIAL_TARGET_INFORMATIONW));
  194. TargetInfo.TargetName = const_cast<PWSTR>(pwszTarget);
  195. TargetInfo.DnsDomainName = const_cast<PWSTR>(pwszRealm);
  196. TargetInfo.PackageName = L"Passport1.4";
  197. TargetInfo.Flags = 0;
  198. TargetInfo.CredTypeCount = 1;
  199. TargetInfo.CredTypes = &CredTypes;
  200. if ((*m_pSession->m_pfnReadDomainCred)(&TargetInfo,
  201. dwFlags,
  202. pdwCreds,
  203. pppCreds ) != TRUE)
  204. {
  205. *pppCreds = NULL;
  206. *pdwCreds = 0;
  207. }
  208. else
  209. {
  210. if (m_pSession->IsLoggedOut())
  211. {
  212. FILETIME LogoutTimestamp;
  213. ::SystemTimeToFileTime(m_pSession->GetLogoutTimeStamp(), &LogoutTimestamp);
  214. if (CompareFileTime(&((**pppCreds)->LastWritten), &LogoutTimestamp) == -1)
  215. {
  216. // the cred is entered/created earlier (less) than the Logout request. It is no good.
  217. m_pSession->m_pfnCredFree(*pppCreds);
  218. *pppCreds = NULL;
  219. *pdwCreds = 0;
  220. }
  221. else
  222. {
  223. m_pSession->ResetLogoutFlag();
  224. }
  225. }
  226. }
  227. return;
  228. }
  229. // -----------------------------------------------------------------------------
  230. BOOL LOGON::SetCredentials(
  231. PCWSTR pwszRealm,
  232. PCWSTR pwszTarget,
  233. PCWSTR pwszSignIn,
  234. PCWSTR pwszPassword
  235. )
  236. {
  237. WCHAR wPass[256];
  238. PCREDENTIALW* ppCred = NULL;
  239. DWORD dwCreds = 0;
  240. PCREDENTIALW pCredToUse = NULL;
  241. if ((!pwszSignIn) && (!pwszPassword))
  242. {
  243. GetCachedCreds(pwszRealm, pwszTarget, &ppCred, &dwCreds);
  244. if (dwCreds > 0 && ppCred[0] != NULL )
  245. {
  246. for ( DWORD idx = 0; idx < dwCreds; idx++ )
  247. {
  248. if ( ppCred[idx]->Type == CRED_TYPE_DOMAIN_VISIBLE_PASSWORD )
  249. {
  250. // check to see if prompt bit is set. If set, keep looking, only use if
  251. // the prompt bit isn't set.
  252. if ( !(ppCred[idx]->Flags & CRED_FLAGS_PROMPT_NOW) )
  253. {
  254. pCredToUse = ppCred[idx];
  255. break;
  256. }
  257. }
  258. }
  259. }
  260. if (pCredToUse == NULL)
  261. {
  262. return FALSE;
  263. }
  264. DecryptPassword(wPass,
  265. PVOID(pCredToUse->CredentialBlob),
  266. pCredToUse->CredentialBlobSize);
  267. pwszSignIn = pCredToUse->UserName;
  268. pwszPassword = wPass;
  269. }
  270. if (m_pwszSignIn)
  271. {
  272. delete [] m_pwszSignIn;
  273. }
  274. DWORD dwSignInLen = ::wcslen(pwszSignIn);
  275. m_pwszSignIn = new WCHAR[dwSignInLen + 1];
  276. if (m_pwszSignIn == NULL)
  277. {
  278. DoTraceMessage(PP_LOG_ERROR, "LOGON::SetCredentials() failed; not enough memory");
  279. return FALSE;
  280. }
  281. ::wcscpy(m_pwszSignIn, pwszSignIn);
  282. if (m_pwszPassword)
  283. {
  284. delete [] m_pwszPassword;
  285. }
  286. DWORD dwPasswordLen = ::wcslen(pwszPassword);
  287. m_pwszPassword = new WCHAR[dwPasswordLen + 1];
  288. if (m_pwszPassword == NULL)
  289. {
  290. DoTraceMessage(PP_LOG_ERROR, "LOGON::SetCredentials() failed; not enough memory");
  291. delete [] m_pwszSignIn;
  292. m_pwszSignIn = NULL;
  293. return FALSE;
  294. }
  295. ::wcscpy(m_pwszPassword, pwszPassword);
  296. m_fCredsPresent = TRUE;
  297. if (ppCred)
  298. {
  299. if (m_pSession->m_pfnCredFree)
  300. {
  301. m_pSession->m_pfnCredFree(ppCred);
  302. }
  303. }
  304. return TRUE;
  305. }
  306. BOOL Gif2Bmp(LPSTREAM pStream, HBITMAP** ppBmp);
  307. // -----------------------------------------------------------------------------
  308. BOOL LOGON::DownLoadCoBrandBitmap(
  309. PWSTR pwszChallenge
  310. )
  311. {
  312. PP_ASSERT(pwszChallenge != NULL);
  313. PWSTR pwszCbUrl = NULL;
  314. BOOL fRet = FALSE;
  315. WCHAR Delimiters[] = L",";
  316. PWSTR Token = ::wcstok(pwszChallenge, Delimiters);
  317. while (Token != NULL)
  318. {
  319. // skip leading white spaces
  320. while (*Token == (L" ")[0]) { ++Token; }
  321. if (Token == NULL)
  322. {
  323. DoTraceMessage(PP_LOG_WARNING, "LOGON::DownLoadCoBrandBitmap() : no text in between commas");
  324. goto next_token;
  325. }
  326. // find cburl
  327. if (!::_wcsnicmp(Token, L"cburl", ::wcslen(L"cburl")))
  328. {
  329. PWSTR CbUrl = ::wcsstr(Token, L"=");
  330. if (CbUrl == NULL)
  331. {
  332. DoTraceMessage(PP_LOG_WARNING, "LOGON::DownLoadCoBrandBitmap() : no = after cburl");
  333. goto next_token;
  334. }
  335. CbUrl++; // skip "="
  336. while (*CbUrl == (L" ")[0]) { ++CbUrl; } // skip leading white spaces
  337. pwszCbUrl = new WCHAR[::wcslen(CbUrl)+1];
  338. if (pwszCbUrl == NULL)
  339. {
  340. DoTraceMessage(PP_LOG_ERROR, "LOGON::DownLoadCoBrandBitmap() failed; not enough memory");
  341. goto exit;
  342. }
  343. ::wcscpy(pwszCbUrl, CbUrl);
  344. DoTraceMessage(PP_LOG_INFO, "CoBrand URL %ws found", pwszCbUrl);
  345. }
  346. else if (!::_wcsnicmp(Token, L"ts", ::wcslen(L"ts")))
  347. {
  348. ::wcscpy(m_wTimeSkew, Token);
  349. }
  350. else if (!::_wcsnicmp(Token, L"srealm", ::wcslen(L"srealm")))
  351. {
  352. PWSTR pwszRealm = ::wcsstr(Token, L"=");
  353. if (pwszRealm == NULL)
  354. {
  355. DoTraceMessage(PP_LOG_WARNING, "LOGON::DownLoadCoBrandBitmap() : no = after cburl");
  356. goto next_token;
  357. }
  358. pwszRealm++; // skip "="
  359. while (*pwszRealm == (L" ")[0]) { ++pwszRealm; } // skip leading white spaces
  360. ::wcscpy(m_wRealm, pwszRealm);
  361. DoTraceMessage(PP_LOG_INFO, "sRealm URL %ws found", pwszCbUrl);
  362. }
  363. next_token:
  364. Token = ::wcstok(NULL, Delimiters);
  365. }
  366. if (pwszCbUrl)
  367. {
  368. HINTERNET hCbUrl = m_pSession->OpenUrl(pwszCbUrl, NULL, 0, 0);
  369. if (hCbUrl == NULL)
  370. {
  371. DWORD dwErrorCode = ::GetLastError();
  372. DoTraceMessage(PP_LOG_ERROR, "LOGON::DownLoadCoBrandBitmap() failed; can not open URL %ws",
  373. pwszCbUrl);
  374. goto exit;
  375. }
  376. {
  377. BYTE bBuf[1024];
  378. DWORD cbBuf = sizeof(bBuf);
  379. DWORD cbRead = 0;
  380. LPSTREAM pStream;
  381. if (CreateStreamOnHGlobal(NULL, TRUE, &pStream) != S_OK)
  382. {
  383. DoTraceMessage(PP_LOG_ERROR, "CreateStreamOnHGlobal() failed");
  384. m_pSession->CloseHandle(hCbUrl);
  385. goto exit;
  386. }
  387. while (m_pSession->ReadFile(hCbUrl, bBuf, cbBuf, &cbRead) && cbRead)
  388. pStream->Write(bBuf, cbRead, NULL);
  389. LARGE_INTEGER Zero = {0};
  390. pStream->Seek(Zero, STREAM_SEEK_SET, NULL); // seek to the beginning of the stream
  391. DoTraceMessage(PP_LOG_INFO, "CoBrand Graphic %ws downloaded", pwszCbUrl);
  392. if (Gif2Bmp(pStream, &m_pBitmap) == FALSE)
  393. {
  394. DoTraceMessage(PP_LOG_ERROR, "Gif2Bmp() failed");
  395. m_pSession->CloseHandle(hCbUrl);
  396. goto exit;
  397. }
  398. pStream->Release();
  399. m_pSession->CloseHandle(hCbUrl);
  400. fRet = TRUE;
  401. DoTraceMessage(PP_LOG_INFO, "CoBrand Bitmap created");
  402. }
  403. }
  404. exit:
  405. if (pwszCbUrl)
  406. {
  407. delete [] pwszCbUrl;
  408. }
  409. return fRet;
  410. }
  411. // -----------------------------------------------------------------------------
  412. DWORD LOGON::Handle401FromDA(
  413. HINTERNET hRequest,
  414. BOOL fTicketRequest
  415. )
  416. {
  417. PP_ASSERT(hRequest != NULL);
  418. DWORD dwRetVal = PP_GENERIC_ERROR;
  419. DWORD dwIndex = 0;
  420. BOOL fFound = FALSE;
  421. WCHAR Challenge[2048];
  422. while (dwIndex != ERROR_HTTP_HEADER_NOT_FOUND)
  423. {
  424. DWORD ChallengeLength = sizeof(Challenge) / sizeof(WCHAR);
  425. if(m_pSession->QueryHeaders(hRequest,
  426. HTTP_QUERY_WWW_AUTHENTICATE,
  427. Challenge,
  428. &ChallengeLength,
  429. &dwIndex))
  430. {
  431. if (::wcsstr(::_wcslwr(Challenge), L"passport1.4"))
  432. {
  433. fFound = TRUE;
  434. break;
  435. }
  436. }
  437. else
  438. {
  439. DWORD dwErrorCode = ::GetLastError();
  440. DoTraceMessage(PP_LOG_ERROR, "Handle401FromDA() failed; QueryHeaders() failed; Error Code = %d",
  441. dwErrorCode);
  442. break;
  443. }
  444. }
  445. if (!fFound)
  446. {
  447. DoTraceMessage(PP_LOG_ERROR, "Handle401FromDA() failed; Passport1.4 auth header not found");
  448. goto exit;
  449. }
  450. if (::wcsstr(::_wcslwr(Challenge), L"retry"))
  451. {
  452. // biaow-todo: not yet implemented
  453. PP_ASSERT(TRUE); // shouldn't reach here
  454. dwRetVal = PP_LOGON_REQUIRED;
  455. }
  456. else if (::wcsstr(::_wcslwr(Challenge), L"failed"))
  457. {
  458. if (fTicketRequest)
  459. {
  460. dwRetVal = PP_LOGON_REQUIRED;
  461. DoTraceMessage(PP_LOG_INFO, "Handle401FromDA() : Logon required by DA");
  462. }
  463. else
  464. {
  465. dwRetVal = PP_LOGON_FAILED; // Login Request Failed; bad news!
  466. DoTraceMessage(PP_LOG_WARNING, "Handle401FromDA() : Logon failed");
  467. }
  468. }
  469. else
  470. {
  471. DoTraceMessage(PP_LOG_ERROR, "Handle401FromDA() failed; no valid DA status");
  472. goto exit;
  473. }
  474. if (dwRetVal == PP_LOGON_REQUIRED)
  475. {
  476. if (::wcsstr(::_wcslwr(Challenge), L"prompt"))
  477. {
  478. m_fPrompt = TRUE;
  479. }
  480. else
  481. {
  482. m_fPrompt = FALSE;
  483. }
  484. DownLoadCoBrandBitmap(Challenge);
  485. }
  486. exit:
  487. return dwRetVal;
  488. }
  489. // -----------------------------------------------------------------------------
  490. DWORD LOGON::Handle200FromDA(
  491. HINTERNET hRequest
  492. )
  493. {
  494. PP_ASSERT(hRequest != NULL);
  495. DWORD dwRetVal = PP_GENERIC_ERROR;
  496. PWSTR pwszBuffer = NULL;
  497. DWORD dwBuffer = 0;
  498. if((!m_pSession->QueryHeaders(hRequest,
  499. HTTP_QUERY_AUTHENTICATION_INFO,
  500. pwszBuffer,
  501. &dwBuffer))
  502. && (::GetLastError() == ERROR_INSUFFICIENT_BUFFER))
  503. {
  504. pwszBuffer = new WCHAR[dwBuffer];
  505. if (pwszBuffer == NULL)
  506. {
  507. DoTraceMessage(PP_LOG_ERROR, "LOGON::Handle200FromDA() failed; not enough memory");
  508. goto exit;
  509. }
  510. if (!m_pSession->QueryHeaders(hRequest,
  511. HTTP_QUERY_AUTHENTICATION_INFO,
  512. pwszBuffer,
  513. &dwBuffer))
  514. {
  515. DoTraceMessage(PP_LOG_ERROR, "LOGON::Handle200FromDA() failed; no Authenticate-Info header found");
  516. goto exit;
  517. }
  518. WCHAR Delimiters[] = L",";
  519. PWSTR Token = ::wcstok(pwszBuffer, Delimiters);
  520. while (Token != NULL)
  521. {
  522. while (*Token == (L" ")[0]) { ++Token; }
  523. if (Token == NULL)
  524. {
  525. DoTraceMessage(PP_LOG_WARNING, "LOGON::Handle200FromDA() : no text in between commas");
  526. goto next_token;
  527. }
  528. if (!::_wcsnicmp(Token, L"ru", ::wcslen(L"ru")))
  529. {
  530. PWSTR ReturnUrl = ::wcsstr(Token, L"=");
  531. if (ReturnUrl == NULL)
  532. {
  533. DoTraceMessage(PP_LOG_ERROR, "LOGON::Handle200FromDA() : no = after cburl");
  534. goto exit;
  535. }
  536. ReturnUrl++; // skip =
  537. while (*ReturnUrl == (L" ")[0]) { ++ReturnUrl; } // skip leading white spaces
  538. m_pwszReturnUrl = new WCHAR[::wcslen(ReturnUrl)+1];
  539. if (m_pwszReturnUrl == NULL)
  540. {
  541. DoTraceMessage(PP_LOG_ERROR, "LOGON::Handle200FromDA() failed; not enough memory");
  542. goto exit;
  543. }
  544. ::wcscpy(m_pwszReturnUrl, ReturnUrl);
  545. }
  546. else if (!::_wcsnicmp(Token, L"from-pp", ::wcslen(L"from-pp")))
  547. {
  548. m_pwszAuthInfo = new WCHAR[::wcslen(Token)+1];
  549. if (m_pwszAuthInfo == NULL)
  550. {
  551. DoTraceMessage(PP_LOG_ERROR, "LOGON::Handle200FromDA() failed; not enough memory");
  552. goto exit;
  553. }
  554. ::wcscpy(m_pwszAuthInfo, Token);
  555. }
  556. next_token:
  557. Token = ::wcstok(NULL, Delimiters);
  558. }
  559. dwRetVal = PP_LOGON_SUCCESS;
  560. }
  561. else
  562. {
  563. PP_ASSERT(TRUE); // shouldn't reach here
  564. goto exit;
  565. }
  566. exit:
  567. if (pwszBuffer)
  568. {
  569. delete [] pwszBuffer;
  570. }
  571. return dwRetVal;
  572. }
  573. VOID PrvLogonStatusCallback(
  574. IN HINTERNET hInternet,
  575. IN DWORD_PTR dwContext,
  576. IN DWORD dwInternetStatus,
  577. IN LPVOID lpvStatusInformation,
  578. IN DWORD dwStatusInformationLength
  579. )
  580. {
  581. LOGON* pLogon = reinterpret_cast<LOGON*>(dwContext);
  582. pLogon->StatusCallback(hInternet,
  583. dwInternetStatus,
  584. lpvStatusInformation,
  585. dwStatusInformationLength);
  586. }
  587. VOID LOGON::StatusCallback(
  588. IN HINTERNET hInternet,
  589. IN DWORD dwInternetStatus,
  590. IN LPVOID lpvStatusInformation,
  591. IN DWORD dwStatusInformationLength)
  592. {
  593. if (dwInternetStatus == INTERNET_STATUS_REDIRECT)
  594. {
  595. ::wcscpy(m_wNewDAUrl, (LPCWSTR)lpvStatusInformation);
  596. BOOL fRet = m_pSession->AddHeaders(hInternet,
  597. m_pwszAuthHeader,
  598. ::wcslen(m_pwszAuthHeader),
  599. HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE
  600. );
  601. PP_ASSERT(fRet == TRUE);
  602. }
  603. }
  604. BOOL LOGON::GetLogonHost(
  605. PWSTR pwszHostName,
  606. OUT PDWORD pdwHostNameLen
  607. ) const
  608. {
  609. if (*pdwHostNameLen < DWORD(::wcslen(m_wDAHostName) + 1))
  610. {
  611. *pdwHostNameLen = ::wcslen(m_wDAHostName) + 1;
  612. return FALSE;
  613. }
  614. PP_ASSERT(pwszHostName != NULL);
  615. ::wcscpy(pwszHostName, m_wDAHostName);
  616. *pdwHostNameLen = ::wcslen(m_wDAHostName) + 1;
  617. return TRUE;
  618. }
  619. // -----------------------------------------------------------------------------
  620. DWORD LOGON::Logon(
  621. void
  622. )
  623. {
  624. PP_ASSERT(m_pSession != NULL);
  625. DWORD dwRetVal = PP_GENERIC_ERROR;
  626. BOOL fTicketRequest;
  627. HINTERNET hRequest = 0;
  628. DWORD dwFlags = 0;
  629. ::wcscpy(m_pwszAuthHeader, L"Authorization: Passport1.4 ");
  630. if (m_fCredsPresent)
  631. {
  632. ::wcscat(m_pwszAuthHeader, L"sign-in=");
  633. ::wcscat(m_pwszAuthHeader, m_pwszSignIn);
  634. ::wcscat(m_pwszAuthHeader, L",");
  635. ::wcscat(m_pwszAuthHeader, L"pwd=");
  636. ::wcscat(m_pwszAuthHeader, m_pwszPassword);
  637. ::wcscat(m_pwszAuthHeader, L",");
  638. if (m_wTimeSkew[0])
  639. {
  640. ::wcscat(m_pwszAuthHeader, m_wTimeSkew);
  641. ::wcscat(m_pwszAuthHeader, L",");
  642. }
  643. fTicketRequest = FALSE; // this is a login request, since we've gather credentials
  644. }
  645. else
  646. {
  647. ::wcscat(m_pwszAuthHeader, L"tname = , ");
  648. fTicketRequest = TRUE;
  649. }
  650. ::wcscat(m_pwszAuthHeader, m_pwszTicketRequest);
  651. retry:
  652. // attempt connecting to the Passport DA
  653. if (m_hConnect)
  654. {
  655. m_pSession->CloseHandle(m_hConnect);
  656. }
  657. WCHAR wDATargetObj[256];
  658. DWORD fStstus = m_pSession->GetDAInfo(m_pwszSignIn,
  659. m_wDAHostName, 256,
  660. wDATargetObj, 256);
  661. PP_ASSERT(fStstus == TRUE);
  662. m_hConnect = m_pSession->Connect(m_wDAHostName/*m_pSession->GetLoginHost()*/,
  663. #ifdef DISABLE_SSL
  664. INTERNET_DEFAULT_HTTP_PORT
  665. #else
  666. INTERNET_DEFAULT_HTTPS_PORT
  667. #endif
  668. );
  669. if (m_hConnect == NULL)
  670. {
  671. DWORD dwErrorCode = ::GetLastError();
  672. DoTraceMessage(PP_LOG_ERROR, "LOGON::Open() failed; can not connect to %ws, Error = %d",
  673. m_wDAHostName, dwErrorCode);
  674. goto exit;
  675. }
  676. if (hRequest)
  677. {
  678. m_pSession->CloseHandle(hRequest);
  679. }
  680. dwFlags = m_dwParentFlags;
  681. hRequest = m_pSession->OpenRequest(m_hConnect,
  682. NULL, // "GET"
  683. wDATargetObj/*m_pSession->GetLoginTarget()*/,
  684. #ifdef DISABLE_SSL
  685. dwFlags | INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS,
  686. #else
  687. dwFlags | INTERNET_FLAG_SECURE,
  688. #endif
  689. (DWORD_PTR)this
  690. );
  691. if (hRequest == NULL)
  692. {
  693. DWORD dwErrorCode = ::GetLastError();
  694. DoTraceMessage(PP_LOG_ERROR, "LOGON::Logon() failed; OpenRequest() to %ws failed, Error Code = %d",
  695. wDATargetObj, dwErrorCode);
  696. goto exit;
  697. }
  698. m_wNewDAUrl[0] = 0;
  699. m_pSession->SetStatusCallback(hRequest, PrvLogonStatusCallback);
  700. if (!m_pSession->SendRequest(hRequest,
  701. m_pwszAuthHeader,
  702. ::wcslen(m_pwszAuthHeader),
  703. (DWORD_PTR)this))
  704. {
  705. DWORD dwErrorCode = ::GetLastError();
  706. #ifdef BAD_CERT_OK
  707. if (dwErrorCode == ERROR_INTERNET_INVALID_CA)
  708. {
  709. DWORD dwSecFlags;
  710. DWORD dwSecurityFlagsSize = sizeof(dwSecFlags);
  711. if (!m_pSession->QueryOption(hRequest,
  712. INTERNET_OPTION_SECURITY_FLAGS,
  713. &dwSecFlags,
  714. &dwSecurityFlagsSize))
  715. {
  716. dwSecFlags = 0;
  717. }
  718. else
  719. {
  720. dwSecFlags |= SECURITY_SET_MASK;
  721. }
  722. if (!m_pSession->SetOption(hRequest,
  723. INTERNET_OPTION_SECURITY_FLAGS,
  724. &dwSecFlags,
  725. dwSecurityFlagsSize))
  726. {
  727. PP_ASSERT(TRUE); // shouldn't reach here
  728. goto exit;
  729. }
  730. else
  731. {
  732. if (!m_pSession->SendRequest(hRequest, NULL, 0))
  733. {
  734. dwErrorCode = ::GetLastError();
  735. DoTraceMessage(PP_LOG_ERROR, "LOGON::Logon() failed; SendRequest() failed, Error Code = %d",
  736. dwErrorCode);
  737. goto exit;
  738. }
  739. else
  740. {
  741. dwErrorCode = ERROR_SUCCESS;
  742. }
  743. }
  744. }
  745. #endif // BAD_CERT_OK
  746. if (dwErrorCode != ERROR_SUCCESS)
  747. {
  748. DoTraceMessage(PP_LOG_ERROR, "LOGON::Logon() failed; SendRequest() failed, Error Code = %d",
  749. dwErrorCode);
  750. if (m_pSession->GetDAInfoFromPPNexus(NULL, 0, NULL, 0) == TRUE)
  751. {
  752. goto retry;
  753. }
  754. goto exit;
  755. }
  756. }
  757. {
  758. DWORD dwStatus, dwStatusLen;
  759. dwStatusLen = sizeof(dwStatus);
  760. if (!m_pSession->QueryHeaders(hRequest,
  761. HTTP_QUERY_FLAG_NUMBER | HTTP_QUERY_STATUS_CODE,
  762. &dwStatus,
  763. &dwStatusLen))
  764. {
  765. DWORD dwErrorCode = ::GetLastError();
  766. DoTraceMessage(PP_LOG_ERROR, "LOGON::Logon() failed; can not retrieve Status Code, Error Code = %d",
  767. dwErrorCode);
  768. goto exit;
  769. }
  770. if (dwStatus == HTTP_STATUS_DENIED)
  771. {
  772. dwRetVal = Handle401FromDA(hRequest, fTicketRequest);
  773. }
  774. else if (dwStatus == HTTP_STATUS_OK)
  775. {
  776. dwRetVal = Handle200FromDA(hRequest);
  777. }
  778. else
  779. {
  780. //PP_ASSERT(TRUE); // shouldn't reach here
  781. //goto exit;
  782. }
  783. if (dwRetVal == PP_GENERIC_ERROR)
  784. {
  785. if (m_pSession->GetDAInfoFromPPNexus(NULL, 0, NULL, 0) == TRUE)
  786. {
  787. goto retry;
  788. }
  789. }
  790. else
  791. {
  792. if (m_wNewDAUrl[0])
  793. {
  794. m_pSession->UpdateDAInfo(m_pwszSignIn,
  795. m_wNewDAUrl);
  796. m_wNewDAUrl[0] = 0;
  797. }
  798. }
  799. }
  800. exit:
  801. if (hRequest)
  802. {
  803. m_pSession->CloseHandle(hRequest);
  804. }
  805. return dwRetVal;
  806. }
  807. // -----------------------------------------------------------------------------
  808. BOOL LOGON::GetChallengeInfo(
  809. HBITMAP** ppBitmap,
  810. PBOOL pfPrompt,
  811. PWSTR pwszCbText,
  812. PDWORD pdwTextLen,
  813. PWSTR pwszRealm,
  814. DWORD dwMaxRealmLen
  815. ) const
  816. {
  817. if (ppBitmap)
  818. {
  819. *ppBitmap = m_pBitmap;
  820. }
  821. if (pfPrompt)
  822. {
  823. *pfPrompt = m_fPrompt;
  824. }
  825. // *pdwTextLen = 0; // biaow-todo:
  826. if (pwszRealm)
  827. {
  828. ::wcsncpy(pwszRealm, m_wRealm, dwMaxRealmLen-1);
  829. }
  830. return TRUE;
  831. }
  832. // -----------------------------------------------------------------------------
  833. BOOL LOGON::GetAuthorizationInfo(
  834. PWSTR pwszTicket,
  835. PDWORD pdwTicketLen,
  836. PBOOL pfKeepVerb,
  837. PWSTR pwszUrl,
  838. PDWORD pdwUrlLen
  839. ) const
  840. {
  841. if (m_pwszReturnUrl == NULL)
  842. {
  843. *pfKeepVerb = TRUE;
  844. *pdwUrlLen = 0;
  845. return TRUE;
  846. }
  847. if (*pdwUrlLen < DWORD(::wcslen(m_pwszReturnUrl) + 1))
  848. {
  849. *pdwUrlLen = ::wcslen(m_pwszReturnUrl) + 1;
  850. return FALSE;
  851. }
  852. PP_ASSERT(pwszUrl != NULL);
  853. ::wcscpy(pwszUrl, m_pwszReturnUrl);
  854. *pfKeepVerb = FALSE;
  855. *pdwUrlLen = ::wcslen(m_pwszReturnUrl) + 1;
  856. if (*pdwTicketLen < DWORD(::wcslen(m_pwszAuthInfo) + 1))
  857. {
  858. *pdwTicketLen = ::wcslen(m_pwszAuthInfo) + 1;
  859. return FALSE;
  860. }
  861. PP_ASSERT(pwszTicket != NULL);
  862. ::wcscpy(pwszTicket, m_pwszAuthInfo);
  863. *pdwTicketLen = ::wcslen(m_pwszAuthInfo) + 1;
  864. return TRUE;
  865. }