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.

1476 lines
41 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. John Hawkins (Johnhaw) 01-Oct-2000
  9. --*/
  10. #include "PPdefs.h"
  11. #include "session.h"
  12. #include "logon.h"
  13. #ifndef CRYPT_UNPROTECT_DATA_FN_DEFINE
  14. #define CRYPT_UNPROTECT_DATA_FN_DEFINE
  15. typedef BOOL
  16. (WINAPI *CRYPT_UNPROTECT_DATA_FN)
  17. (IN DATA_BLOB *pDataIn,
  18. OUT OPTIONAL LPWSTR *ppszDataDescr,
  19. IN DATA_BLOB *pOptionalEntropy,
  20. IN PVOID pvReserved,
  21. IN OPTIONAL CRYPTPROTECT_PROMPTSTRUCT *pPromptStruct,
  22. IN DWORD dwFlags,
  23. OUT DATA_BLOB *pDataOut
  24. );
  25. #endif
  26. extern CRYPT_UNPROTECT_DATA_FN g_pfnCryptUnprotectData;
  27. #define SIZE_OF_SALT 37
  28. #define SALT_SHIFT 2
  29. WCHAR g_szSalt[] = L"82BD0E67-9FEA-4748-8672-D5EFE5B779B0";
  30. // #include "logon.tmh"
  31. LOGON::LOGON(SESSION* pSession, DWORD dwParentFlags, PCWSTR pwszProxyUser, PCWSTR pwszProxyPass)
  32. : m_pSession(pSession)
  33. {
  34. m_pwszProxyUser = pwszProxyUser;
  35. m_pwszProxyPass = pwszProxyPass;
  36. m_pSession->AddRef();
  37. m_hConnect = NULL;
  38. m_fCredsPresent = FALSE;
  39. m_pwszSignIn = NULL;
  40. m_pwszPassword = NULL;
  41. m_pwszTicketRequest = NULL;
  42. m_pwszAuthInfo = NULL;
  43. m_pwszReturnUrl = NULL;
  44. m_pBitmap = NULL;
  45. m_fPrompt = FALSE;
  46. m_wTimeSkew[0] = L'\0';
  47. m_wNewDAUrl[0] = 0;
  48. m_dwParentFlags = dwParentFlags;
  49. m_p401Content = NULL;
  50. m_pwszCbtxt = NULL;
  51. m_pwszCbUrl = NULL;
  52. }
  53. LOGON::~LOGON(void)
  54. {
  55. if (m_pwszAuthInfo)
  56. {
  57. delete [] m_pwszAuthInfo;
  58. }
  59. if (m_pwszSignIn)
  60. {
  61. SecureZeroMemory(m_pwszSignIn, ::wcslen(m_pwszSignIn) * sizeof(WCHAR));
  62. delete [] m_pwszSignIn;
  63. }
  64. if (m_pwszPassword)
  65. {
  66. SecureZeroMemory(m_pwszPassword, ::wcslen(m_pwszPassword) * sizeof(WCHAR));
  67. delete [] m_pwszPassword;
  68. }
  69. if (m_pwszTicketRequest)
  70. {
  71. delete [] m_pwszTicketRequest;
  72. }
  73. if (m_pwszAuthHeader)
  74. {
  75. delete [] m_pwszAuthHeader;
  76. }
  77. m_pSession->RemoveRef();
  78. if (m_p401Content)
  79. {
  80. m_p401Content->Release();
  81. }
  82. if (m_pwszCbtxt)
  83. {
  84. delete [] m_pwszCbtxt;
  85. }
  86. if (m_pwszCbUrl)
  87. {
  88. delete [] m_pwszCbUrl;
  89. }
  90. if (m_pwszProxyUser)
  91. {
  92. SecureZeroMemory((void*)m_pwszProxyUser, sizeof(m_pwszProxyUser[0]) * wcslen(m_pwszProxyUser));
  93. delete [] m_pwszProxyUser;
  94. }
  95. if (m_pwszProxyPass)
  96. {
  97. SecureZeroMemory((void*)m_pwszProxyPass, sizeof(m_pwszProxyPass[0]) * wcslen(m_pwszProxyPass));
  98. delete [] m_pwszProxyPass;
  99. }
  100. }
  101. // -----------------------------------------------------------------------------
  102. BOOL LOGON::Open(
  103. PCWSTR pwszPartnerInfo // in the form of "WWW-Authenticate: Passport1.4 ..."
  104. )
  105. {
  106. PP_ASSERT(pwszPartnerInfo != NULL);
  107. // locate the auth scheme name, i.e. Passport1.4
  108. PCWSTR pwszTicketRequest = ::wcsstr(pwszPartnerInfo, L"Passport1.4");
  109. if (pwszTicketRequest == NULL)
  110. {
  111. DoTraceMessage(PP_LOG_ERROR, "LOGON::Open() failed; Passport1.4 scheme not found");
  112. return FALSE;
  113. }
  114. pwszTicketRequest += ::wcslen(L"Passport1.4");
  115. // skip white spaces between the scheme name and the Ticket Request (TR)
  116. while (*pwszTicketRequest == (L" ")[0]) { ++pwszTicketRequest; }
  117. if (*pwszTicketRequest == L'\0')
  118. {
  119. DoTraceMessage(PP_LOG_ERROR, "LOGON::Open() failed; Ticket Request missing");
  120. return FALSE;
  121. }
  122. // save the TR
  123. DWORD dwTrLen = ::wcslen(pwszTicketRequest);
  124. m_pwszTicketRequest = new WCHAR[dwTrLen + 1];
  125. if (m_pwszTicketRequest == NULL)
  126. {
  127. DoTraceMessage(PP_LOG_ERROR, "LOGON::Open() failed; not enough memory");
  128. return FALSE;
  129. }
  130. ::wcscpy(m_pwszTicketRequest, pwszTicketRequest);
  131. m_pwszAuthHeader = new WCHAR[dwTrLen +
  132. MAX_PASSPORT_USERNAME_LENGTH +
  133. MAX_PASSPORT_PASSWORD_LENGTH +
  134. MAX_PASSPORT_TIME_SKEW_LENGTH +
  135. 256 + // some buffer for the worst case
  136. 1];
  137. if (m_pwszAuthHeader == NULL)
  138. {
  139. DoTraceMessage(PP_LOG_ERROR, "LOGON::Open() failed; not enough memory");
  140. return FALSE;
  141. }
  142. DoTraceMessage(PP_LOG_INFO, "LOGON::Open() succeed");
  143. return TRUE;
  144. }
  145. void LOGON::Close(void)
  146. {
  147. PP_ASSERT(m_hConnect != NULL);
  148. PP_ASSERT(m_pSession != NULL);
  149. m_pSession->CloseHandle(m_hConnect);
  150. m_hConnect = NULL;
  151. }
  152. DWORD
  153. LoadSecurity(
  154. VOID
  155. );
  156. // pClearPassword is assumed to be at least 256 chars
  157. void DecryptPassword ( WCHAR* pClearPassword, PVOID pPassword, DWORD cbSize )
  158. {
  159. BOOL bOrigEncrypted = FALSE;
  160. DATA_BLOB InBlob;
  161. DATA_BLOB OutBlob;
  162. LPWSTR pszDesc;
  163. if ( pClearPassword == NULL )
  164. return;
  165. if ( cbSize == 0 )
  166. {
  167. // CryptUnprotectData doesn't like to be sent a zero-length buffer
  168. pClearPassword[0] = L'\0';
  169. return;
  170. }
  171. InBlob.pbData = (BYTE*)pPassword;
  172. InBlob.cbData = cbSize;
  173. DATA_BLOB EntropyBlob;
  174. WCHAR szSalt[SIZE_OF_SALT];
  175. wcscpy ( szSalt, g_szSalt);
  176. for ( int i = 0; i < SIZE_OF_SALT; i++ )
  177. szSalt[i] <<= SALT_SHIFT;
  178. EntropyBlob.pbData = (BYTE*)szSalt;
  179. EntropyBlob.cbData = sizeof(WCHAR)*(wcslen(szSalt)+1);
  180. // Guaranteed to have a logon context if we've gotten this far.
  181. // Consequently, a previously successful call to LoadSecurity can
  182. // be assumed.
  183. LoadSecurity();
  184. PP_ASSERT(g_pfnCryptUnprotectData);
  185. if ( (*g_pfnCryptUnprotectData) ( &InBlob,
  186. &pszDesc,
  187. &EntropyBlob,
  188. NULL,
  189. NULL,
  190. CRYPTPROTECT_UI_FORBIDDEN,
  191. &OutBlob ) )
  192. {
  193. if ( wcscmp (L"SSOCred", pszDesc) == 0 )
  194. {
  195. DWORD dwOutChars = OutBlob.cbData/sizeof(WCHAR);
  196. if ( dwOutChars < 256 )
  197. {
  198. wcsncpy ( pClearPassword, (WCHAR*)OutBlob.pbData, dwOutChars );
  199. pClearPassword[dwOutChars] = L'\0';
  200. }
  201. bOrigEncrypted = TRUE;
  202. }
  203. LocalFree ( pszDesc );
  204. LocalFree ( OutBlob.pbData );
  205. }
  206. SecureZeroMemory ( szSalt, SIZE_OF_SALT);
  207. if ( !bOrigEncrypted )
  208. {
  209. // copy the plain text
  210. wcsncpy ( pClearPassword, (WCHAR*)pPassword, MAX_PASSPORT_PASSWORD_LENGTH );
  211. pClearPassword[MAX_PASSPORT_PASSWORD_LENGTH] = 0;
  212. pClearPassword[cbSize/sizeof(WCHAR)] = L'\0';
  213. }
  214. return;
  215. }
  216. void LOGON::GetCachedCreds(
  217. PCWSTR pwszRealm,
  218. PCWSTR pwszTarget,
  219. PCREDENTIALW** pppCreds,
  220. DWORD* pdwCreds
  221. )
  222. {
  223. if (m_pSession->GetCachedCreds(pwszRealm,pwszTarget,pppCreds,pdwCreds) != FALSE)
  224. {
  225. PCREDENTIALW pCredToUse = *pppCreds[0];
  226. ::FileTimeToSystemTime(&(pCredToUse->LastWritten), &m_TimeCredsEntered);
  227. }
  228. }
  229. // -----------------------------------------------------------------------------
  230. BOOL LOGON::SetCredentials(
  231. PCWSTR pwszRealm,
  232. PCWSTR pwszTarget,
  233. PCWSTR pwszSignIn,
  234. PCWSTR pwszPassword,
  235. PSYSTEMTIME pTimeCredsEntered
  236. )
  237. {
  238. WCHAR wPass[MAX_PASSPORT_PASSWORD_LENGTH + 1];
  239. wPass[0] = 0;
  240. PCREDENTIALW* ppCred = NULL;
  241. DWORD dwCreds = 0;
  242. PCREDENTIALW pCredToUse = NULL;
  243. if ((!pwszSignIn) && (!pwszPassword))
  244. {
  245. pTimeCredsEntered = NULL; // invalidate this parameter if cached creds are to be used
  246. GetCachedCreds(pwszRealm, pwszTarget, &ppCred, &dwCreds);
  247. if (dwCreds > 0 && ppCred[0] != NULL )
  248. {
  249. for ( DWORD idx = 0; idx < dwCreds; idx++ )
  250. {
  251. if ( ppCred[idx]->Type == CRED_TYPE_DOMAIN_VISIBLE_PASSWORD )
  252. {
  253. // check to see if prompt bit is set. If set, keep looking, only use if
  254. // the prompt bit isn't set.
  255. if ( !(ppCred[idx]->Flags & CRED_FLAGS_PROMPT_NOW) )
  256. {
  257. pCredToUse = ppCred[idx];
  258. break;
  259. }
  260. }
  261. }
  262. }
  263. if (pCredToUse == NULL)
  264. {
  265. return FALSE;
  266. }
  267. DecryptPassword(wPass,
  268. PVOID(pCredToUse->CredentialBlob),
  269. pCredToUse->CredentialBlobSize);
  270. pwszSignIn = pCredToUse->UserName;
  271. pwszPassword = wPass;
  272. }
  273. else
  274. {
  275. m_pSession->ResetLogoutFlag();
  276. if (pTimeCredsEntered == NULL)
  277. {
  278. DoTraceMessage(PP_LOG_ERROR, "LOGON::SetCredentials() failed; Timestamp not specified");
  279. return FALSE;
  280. }
  281. }
  282. if (m_pwszSignIn)
  283. {
  284. SecureZeroMemory(m_pwszSignIn, ::wcslen(m_pwszSignIn) * sizeof(WCHAR));
  285. delete [] m_pwszSignIn;
  286. }
  287. DWORD dwSignInLen = ::wcslen(pwszSignIn);
  288. m_pwszSignIn = new WCHAR[dwSignInLen + 1];
  289. if (m_pwszSignIn == NULL)
  290. {
  291. DoTraceMessage(PP_LOG_ERROR, "LOGON::SetCredentials() failed; not enough memory");
  292. return FALSE;
  293. }
  294. ::wcscpy(m_pwszSignIn, pwszSignIn);
  295. if (m_pwszPassword)
  296. {
  297. SecureZeroMemory(m_pwszPassword, ::wcslen(m_pwszPassword) * sizeof(WCHAR));
  298. delete [] m_pwszPassword;
  299. }
  300. DWORD dwPasswordLen = ::wcslen(pwszPassword);
  301. m_pwszPassword = new WCHAR[dwPasswordLen + 1];
  302. if (m_pwszPassword == NULL)
  303. {
  304. DoTraceMessage(PP_LOG_ERROR, "LOGON::SetCredentials() failed; not enough memory");
  305. SecureZeroMemory(m_pwszSignIn, ::wcslen(m_pwszSignIn) * sizeof(WCHAR));
  306. delete [] m_pwszSignIn;
  307. m_pwszSignIn = NULL;
  308. return FALSE;
  309. }
  310. ::wcscpy(m_pwszPassword, pwszPassword);
  311. SecureZeroMemory(wPass, ::wcslen(wPass) * sizeof(WCHAR));
  312. if (pTimeCredsEntered)
  313. {
  314. m_TimeCredsEntered = *pTimeCredsEntered;
  315. }
  316. m_fCredsPresent = TRUE;
  317. if (ppCred)
  318. {
  319. if (m_pSession->m_pfnCredFree)
  320. {
  321. m_pSession->m_pfnCredFree(ppCred);
  322. }
  323. }
  324. return TRUE;
  325. }
  326. // -----------------------------------------------------------------------------
  327. BOOL LOGON::ParseChallengeInfo(
  328. PWSTR pwszChallenge
  329. )
  330. {
  331. PP_ASSERT(pwszChallenge != NULL);
  332. BOOL fRet = FALSE;
  333. WCHAR Delimiters[] = L",";
  334. PWSTR Token = ::wcstok(pwszChallenge, Delimiters);
  335. while (Token != NULL)
  336. {
  337. // skip leading white spaces
  338. while (*Token == (L" ")[0]) { ++Token; }
  339. if (*Token == L'\0')
  340. {
  341. DoTraceMessage(PP_LOG_WARNING, "LOGON::DownLoadCoBrandBitmap() : no text in between commas");
  342. goto next_token;
  343. }
  344. // find cburl
  345. if (!::_wcsnicmp(Token, L"cburl", ::wcslen(L"cburl")))
  346. {
  347. PWSTR CbUrl = ::wcsstr(Token, L"=");
  348. if (CbUrl == NULL)
  349. {
  350. DoTraceMessage(PP_LOG_WARNING, "LOGON::DownLoadCoBrandBitmap() : no = after cburl");
  351. goto next_token;
  352. }
  353. CbUrl++; // skip "="
  354. while (*CbUrl == (L" ")[0]) { ++CbUrl; } // skip leading white spaces
  355. if (*CbUrl == L'\0')
  356. {
  357. goto next_token;
  358. }
  359. m_pwszCbUrl = new WCHAR[::wcslen(CbUrl)+1];
  360. if (m_pwszCbUrl == NULL)
  361. {
  362. DoTraceMessage(PP_LOG_ERROR, "LOGON::DownLoadCoBrandBitmap() failed; not enough memory");
  363. goto exit;
  364. }
  365. ::wcscpy(m_pwszCbUrl, CbUrl);
  366. DoTraceMessage(PP_LOG_INFO, "CoBrand URL %ws found", m_pwszCbUrl);
  367. }
  368. else if (!::_wcsnicmp(Token, L"ts", ::wcslen(L"ts")))
  369. {
  370. ::wcsncpy(m_wTimeSkew, Token, MAX_PASSPORT_TIME_SKEW_LENGTH);
  371. m_wTimeSkew[MAX_PASSPORT_TIME_SKEW_LENGTH] = 0;
  372. }
  373. else if (!::_wcsnicmp(Token, L"srealm", ::wcslen(L"srealm")))
  374. {
  375. PWSTR pwszRealm = ::wcsstr(Token, L"=");
  376. if (pwszRealm == NULL)
  377. {
  378. DoTraceMessage(PP_LOG_WARNING, "LOGON::DownLoadCoBrandBitmap() : no = after cburl");
  379. goto next_token;
  380. }
  381. pwszRealm++; // skip "="
  382. while (*pwszRealm == (L" ")[0]) { ++pwszRealm; } // skip leading white spaces
  383. if (*pwszRealm == L'\0')
  384. {
  385. goto next_token;
  386. }
  387. ::wcsncpy(m_wRealm, pwszRealm, MAX_PASSPORT_REALM_LENGTH);
  388. m_wRealm[MAX_PASSPORT_REALM_LENGTH] = 0;
  389. DoTraceMessage(PP_LOG_INFO, "sRealm URL %ws found", pwszRealm);
  390. }
  391. else if (!::_wcsnicmp(Token, L"cbtxt", ::wcslen(L"cbtxt")))
  392. {
  393. PWSTR pwszCbTxt = ::wcsstr(Token, L"=");
  394. if (pwszCbTxt == NULL)
  395. {
  396. DoTraceMessage(PP_LOG_WARNING, "LOGON::DownLoadCoBrandBitmap() : no = after cbtxt");
  397. goto next_token;
  398. }
  399. pwszCbTxt++; // skip "="
  400. while (*pwszCbTxt == (L" ")[0]) { ++pwszCbTxt; } // skip leading white spaces
  401. if (*pwszCbTxt == L'\0')
  402. {
  403. goto next_token;
  404. }
  405. if (m_pwszCbtxt)
  406. {
  407. delete [] m_pwszCbtxt;
  408. }
  409. m_pwszCbtxt = new WCHAR[wcslen(pwszCbTxt)+1];
  410. if (m_pwszCbtxt)
  411. {
  412. ::wcscpy( m_pwszCbtxt, pwszCbTxt);
  413. DoTraceMessage(PP_LOG_INFO, "cbtxt %ws found", m_pwszCbtxt);
  414. }
  415. }
  416. next_token:
  417. Token = ::wcstok(NULL, Delimiters);
  418. }
  419. exit:
  420. return fRet;
  421. }
  422. // -----------------------------------------------------------------------------
  423. DWORD LOGON::Handle401FromDA(
  424. HINTERNET hRequest,
  425. BOOL fTicketRequest
  426. )
  427. {
  428. UNREFERENCED_PARAMETER(fTicketRequest);
  429. PP_ASSERT(hRequest != NULL);
  430. DWORD dwRetVal = (DWORD)PP_GENERIC_ERROR;
  431. PWSTR pwszRawHeaders = NULL;
  432. PSTR pszRawHeaders = NULL;
  433. PWSTR pwszChallenge = NULL;
  434. PWSTR pwszChallengeEnd = NULL;
  435. DWORD ChallengeLength = 0;
  436. if(!DelayLoad( &g_moduleOle32))
  437. goto exit;
  438. if(m_pSession->QueryHeaders(hRequest,
  439. WINHTTP_QUERY_RAW_HEADERS_CRLF,
  440. 0,
  441. &ChallengeLength) == FALSE)
  442. {
  443. if ((::GetLastError() != ERROR_INSUFFICIENT_BUFFER) || (ChallengeLength == 0))
  444. {
  445. DWORD dwErrorCode = ::GetLastError();
  446. DoTraceMessage(PP_LOG_ERROR, "Handle401FromDA() failed; QueryHeaders() failed; Error Code = %d",
  447. dwErrorCode);
  448. goto exit;
  449. }
  450. }
  451. else
  452. {
  453. PP_ASSERT(FALSE); // control should not reach here
  454. }
  455. pwszRawHeaders = new WCHAR[ChallengeLength];
  456. if (pwszRawHeaders == NULL)
  457. {
  458. DoTraceMessage(PP_LOG_ERROR, "Handle401FromDA() failed; out of memory");
  459. goto exit;
  460. }
  461. if(m_pSession->QueryHeaders(hRequest,
  462. WINHTTP_QUERY_RAW_HEADERS_CRLF,
  463. pwszRawHeaders,
  464. &ChallengeLength) == FALSE)
  465. {
  466. DWORD dwErrorCode = ::GetLastError();
  467. DoTraceMessage(PP_LOG_ERROR, "Handle401FromDA() failed; QueryHeaders() failed; Error Code = %d",
  468. dwErrorCode);
  469. goto exit;
  470. }
  471. if ((pwszChallenge = ::wcsstr(pwszRawHeaders, L"Passport1.4")) == NULL)
  472. {
  473. DoTraceMessage(PP_LOG_ERROR, "Handle401FromDA() failed; Passport1.4 auth header not found");
  474. goto exit;
  475. }
  476. if ((pwszChallengeEnd = ::wcsstr(pwszChallenge, L"\r\n")) != NULL)
  477. {
  478. *pwszChallengeEnd = 0;
  479. }
  480. if (::wcsstr(pwszChallenge, L"noretry"))
  481. {
  482. dwRetVal = PP_LOGON_FAILED; // Login Request Failed; bad news!
  483. DoTraceMessage(PP_LOG_WARNING, "Handle401FromDA() : Logon failed");
  484. }
  485. else if (::wcsstr(pwszChallenge, L"retry"))
  486. {
  487. // biaow-todo: not yet implemented
  488. // PP_ASSERT(FALSE); // shouldn't reach here
  489. dwRetVal = PP_LOGON_REQUIRED;
  490. }
  491. else if (::wcsstr(pwszChallenge, L"failed"))
  492. {
  493. // if (fTicketRequest)
  494. // {
  495. dwRetVal = PP_LOGON_REQUIRED;
  496. DoTraceMessage(PP_LOG_INFO, "Handle401FromDA() : Logon required by DA");
  497. // }
  498. // else
  499. // {
  500. // dwRetVal = PP_LOGON_FAILED; // Login Request Failed; bad news!
  501. // DoTraceMessage(PP_LOG_WARNING, "Handle401FromDA() : Logon failed");
  502. // }
  503. }
  504. else
  505. {
  506. DoTraceMessage(PP_LOG_ERROR, "Handle401FromDA() failed; no valid DA status");
  507. goto exit;
  508. }
  509. if (dwRetVal == PP_LOGON_REQUIRED || dwRetVal == PP_LOGON_FAILED)
  510. {
  511. if (::wcsstr(pwszChallenge, L"prompt"))
  512. {
  513. m_fPrompt = TRUE;
  514. }
  515. else
  516. {
  517. m_fPrompt = FALSE;
  518. }
  519. if (DL(CreateStreamOnHGlobal)(NULL, TRUE, &m_p401Content) != S_OK)
  520. {
  521. DoTraceMessage(PP_LOG_ERROR, "DL(CreateStreamOnHGlobal)() failed");
  522. goto exit;
  523. }
  524. if (pwszChallengeEnd)
  525. {
  526. PP_ASSERT(*pwszChallengeEnd == 0);
  527. *pwszChallengeEnd = L'\r';
  528. }
  529. pszRawHeaders = new CHAR[ChallengeLength * 2];
  530. if (pszRawHeaders == NULL)
  531. {
  532. DoTraceMessage(PP_LOG_ERROR, "DL(CreateStreamOnHGlobal)() failed, out of memory");
  533. goto exit;
  534. }
  535. ::WideCharToMultiByte(CP_ACP, 0, pwszRawHeaders, -1, pszRawHeaders, ChallengeLength * 2, NULL, NULL);
  536. m_p401Content->Write(pszRawHeaders, strlen(pszRawHeaders), NULL);
  537. {
  538. DWORD cbRead = 0;
  539. PBYTE bBuf = new BYTE [1024];
  540. if (bBuf == NULL)
  541. {
  542. DoTraceMessage(PP_LOG_ERROR, "DL(CreateStreamOnHGlobal)() failed, out of memory");
  543. goto exit;
  544. }
  545. DWORD cbBuf = 1024;
  546. while (m_pSession->ReadFile(hRequest, bBuf, cbBuf, &cbRead) && cbRead)
  547. m_p401Content->Write(bBuf, cbRead, NULL);
  548. delete [] bBuf;
  549. }
  550. LARGE_INTEGER Zero = {0};
  551. m_p401Content->Seek(Zero, STREAM_SEEK_SET, NULL); // seek to the beginning of the stream
  552. if (pwszChallengeEnd)
  553. {
  554. *pwszChallengeEnd = 0;
  555. }
  556. ParseChallengeInfo(pwszChallenge);
  557. }
  558. exit:
  559. if (pwszRawHeaders)
  560. {
  561. delete [] pwszRawHeaders;
  562. }
  563. if (pszRawHeaders)
  564. {
  565. delete [] pszRawHeaders;
  566. }
  567. return dwRetVal;
  568. }
  569. // -----------------------------------------------------------------------------
  570. DWORD LOGON::Handle200FromDA(
  571. HINTERNET hRequest
  572. )
  573. {
  574. PP_ASSERT(hRequest != NULL);
  575. DWORD dwRetVal = (DWORD)PP_GENERIC_ERROR;
  576. PWSTR pwszBuffer = NULL;
  577. DWORD dwBuffer = 0;
  578. if((!m_pSession->QueryHeaders(hRequest,
  579. WINHTTP_QUERY_AUTHENTICATION_INFO,
  580. pwszBuffer,
  581. &dwBuffer))
  582. && (::GetLastError() == ERROR_INSUFFICIENT_BUFFER))
  583. {
  584. pwszBuffer = new WCHAR[dwBuffer];
  585. if (pwszBuffer == NULL)
  586. {
  587. DoTraceMessage(PP_LOG_ERROR, "LOGON::Handle200FromDA() failed; not enough memory");
  588. goto exit;
  589. }
  590. if (!m_pSession->QueryHeaders(hRequest,
  591. HTTP_QUERY_AUTHENTICATION_INFO,
  592. pwszBuffer,
  593. &dwBuffer))
  594. {
  595. DoTraceMessage(PP_LOG_ERROR, "LOGON::Handle200FromDA() failed; no Authenticate-Info header found");
  596. goto exit;
  597. }
  598. WCHAR Delimiters[] = L",";
  599. PWSTR Token = ::wcstok(pwszBuffer, Delimiters);
  600. while (Token != NULL)
  601. {
  602. while (*Token == (L" ")[0]) { ++Token; }
  603. if (*Token == L'\0')
  604. {
  605. DoTraceMessage(PP_LOG_WARNING, "LOGON::Handle200FromDA() : no text in between commas");
  606. goto next_token;
  607. }
  608. if (!::_wcsnicmp(Token, L"ru", ::wcslen(L"ru")))
  609. {
  610. PWSTR ReturnUrl = ::wcsstr(Token, L"=");
  611. if (ReturnUrl == NULL)
  612. {
  613. DoTraceMessage(PP_LOG_ERROR, "LOGON::Handle200FromDA() : no = after cburl");
  614. goto exit;
  615. }
  616. ReturnUrl++; // skip =
  617. while (*ReturnUrl == (L" ")[0]) { ++ReturnUrl; } // skip leading white spaces
  618. if (*ReturnUrl == L'\0')
  619. {
  620. goto exit;
  621. }
  622. m_pwszReturnUrl = new WCHAR[::wcslen(ReturnUrl)+1];
  623. if (m_pwszReturnUrl == NULL)
  624. {
  625. DoTraceMessage(PP_LOG_ERROR, "LOGON::Handle200FromDA() failed; not enough memory");
  626. goto exit;
  627. }
  628. ::wcscpy(m_pwszReturnUrl, ReturnUrl);
  629. }
  630. else if (!::_wcsnicmp(Token, L"from-pp", ::wcslen(L"from-pp")))
  631. {
  632. m_pwszAuthInfo = new WCHAR[::wcslen(Token)+1];
  633. if (m_pwszAuthInfo == NULL)
  634. {
  635. DoTraceMessage(PP_LOG_ERROR, "LOGON::Handle200FromDA() failed; not enough memory");
  636. goto exit;
  637. }
  638. ::wcscpy(m_pwszAuthInfo, Token);
  639. }
  640. next_token:
  641. Token = ::wcstok(NULL, Delimiters);
  642. }
  643. dwRetVal = PP_LOGON_SUCCESS;
  644. }
  645. else
  646. {
  647. PP_ASSERT(FALSE); // shouldn't reach here
  648. goto exit;
  649. }
  650. exit:
  651. if (pwszBuffer)
  652. {
  653. delete [] pwszBuffer;
  654. }
  655. return dwRetVal;
  656. }
  657. void LOGON::CheckForVersionChange(
  658. HINTERNET hRequest
  659. )
  660. {
  661. WCHAR wszBuffer[256];
  662. DWORD dwBufferLen = sizeof(wszBuffer) / sizeof(WCHAR);
  663. BOOL fDownloadNewNexusConfig = FALSE;
  664. if (!m_pSession->QueryHeaders(hRequest,
  665. WINHTTP_QUERY_PASSPORT_CONFIG,
  666. wszBuffer,
  667. &dwBufferLen))
  668. {
  669. DoTraceMessage(PP_LOG_ERROR, "LOGON::CheckForVersionChange() failed; no PassportConfig header found");
  670. goto exit;
  671. }
  672. WCHAR Delimiters[] = L",";
  673. PWSTR Token = ::wcstok(wszBuffer, Delimiters);
  674. while (Token != NULL)
  675. {
  676. // skip leading white spaces
  677. while (*Token == (L" ")[0]) { ++Token; }
  678. if (*Token == L'\0')
  679. {
  680. DoTraceMessage(PP_LOG_WARNING, "LOGON::CheckForVersionChange() : no text in between commas");
  681. goto next_token;
  682. }
  683. if (!::_wcsnicmp(Token, L"ConfigVersion", ::wcslen(L"ConfigVersion")))
  684. {
  685. PWSTR pwszConfigVersion = ::wcsstr(Token, L"=");
  686. if (pwszConfigVersion == NULL)
  687. {
  688. DoTraceMessage(PP_LOG_WARNING, "LOGON::CheckForVersionChange() : no = after ConfigVersion");
  689. goto next_token;
  690. }
  691. pwszConfigVersion++; // skip "="
  692. while (*pwszConfigVersion == (L" ")[0]) { ++pwszConfigVersion; } // skip leading white spaces
  693. if (*pwszConfigVersion == L'\0')
  694. {
  695. goto next_token;
  696. }
  697. if ((DWORD)_wtoi(pwszConfigVersion) > m_pSession->GetNexusVersion())
  698. {
  699. fDownloadNewNexusConfig = TRUE;
  700. }
  701. DoTraceMessage(PP_LOG_INFO, "ConfigVersion URL %ws found", pwszConfigVersion);
  702. }
  703. next_token:
  704. Token = ::wcstok(NULL, Delimiters);
  705. }
  706. if (fDownloadNewNexusConfig)
  707. {
  708. m_pSession->PurgeAllDAInfo();
  709. m_pSession->GetDAInfoFromPPNexus();
  710. }
  711. exit:
  712. return;
  713. }
  714. VOID PrvLogonStatusCallback(
  715. IN HINTERNET hInternet,
  716. IN DWORD_PTR dwContext,
  717. IN DWORD dwInternetStatus,
  718. IN LPVOID lpvStatusInformation,
  719. IN DWORD dwStatusInformationLength
  720. )
  721. {
  722. LOGON* pLogon = reinterpret_cast<LOGON*>(dwContext);
  723. pLogon->StatusCallback(hInternet,
  724. dwInternetStatus,
  725. lpvStatusInformation,
  726. dwStatusInformationLength);
  727. }
  728. VOID LOGON::StatusCallback(
  729. IN HINTERNET hInternet,
  730. IN DWORD dwInternetStatus,
  731. IN LPVOID lpvStatusInformation,
  732. IN DWORD dwStatusInformationLength)
  733. {
  734. UNREFERENCED_PARAMETER(dwStatusInformationLength);
  735. if (dwInternetStatus == WINHTTP_CALLBACK_STATUS_REDIRECT)
  736. {
  737. ::wcsncpy(m_wNewDAUrl, (LPCWSTR)lpvStatusInformation, MAX_PASSPORT_URL_LENGTH);
  738. m_wNewDAUrl[MAX_PASSPORT_URL_LENGTH] = 0;
  739. #ifdef DBG
  740. BOOL fRet =
  741. #else
  742. (VOID)
  743. #endif
  744. m_pSession->AddHeaders(hInternet,
  745. m_pwszAuthHeader,
  746. ::wcslen(m_pwszAuthHeader),
  747. WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE
  748. );
  749. PP_ASSERT(fRet == TRUE);
  750. }
  751. }
  752. BOOL LOGON::GetLogonHost(
  753. PWSTR pwszHostName,
  754. OUT PDWORD pdwHostNameLen
  755. ) const
  756. {
  757. if (*pdwHostNameLen < DWORD(::wcslen(m_wDAHostName) + 1))
  758. {
  759. *pdwHostNameLen = ::wcslen(m_wDAHostName) + 1;
  760. return FALSE;
  761. }
  762. PP_ASSERT(pwszHostName != NULL);
  763. ::wcscpy(pwszHostName, m_wDAHostName);
  764. *pdwHostNameLen = ::wcslen(m_wDAHostName) + 1;
  765. return TRUE;
  766. }
  767. //Determine if the character is unsafe under the URI RFC document
  768. inline BOOL PPIsUnsafeUrlChar(TCHAR chIn) throw()
  769. {
  770. unsigned char ch = (unsigned char)chIn;
  771. switch(ch)
  772. {
  773. case ';': case '\\': case '?': case '@': case '&':
  774. case '=': case '+': case '$': case ',': case ' ':
  775. case '<': case '>': case '#': case '%': case '\"':
  776. case '{': case '}': case '|':
  777. case '^': case '[': case ']': case '`':
  778. return TRUE;
  779. default:
  780. {
  781. if (ch < 32 || ch > 126)
  782. return TRUE;
  783. return FALSE;
  784. }
  785. }
  786. }
  787. BOOL PPEscapeUrl(LPCSTR lpszStringIn,
  788. LPSTR lpszStringOut,
  789. DWORD* pdwStrLen,
  790. DWORD dwMaxLength,
  791. DWORD dwFlags)
  792. {
  793. TCHAR ch;
  794. DWORD dwLen = 0;
  795. BOOL bRet = TRUE;
  796. UNREFERENCED_PARAMETER(dwFlags);
  797. while((ch = *lpszStringIn++) != '\0')
  798. {
  799. //if we are at the maximum length, set bRet to FALSE
  800. //this ensures no more data is written to lpszStringOut, but
  801. //the length of the string is still updated, so the user
  802. //knows how much space to allocate
  803. if (dwLen == dwMaxLength)
  804. {
  805. bRet = FALSE;
  806. }
  807. //if we are encoding and it is an unsafe character
  808. if (PPIsUnsafeUrlChar(ch))
  809. {
  810. {
  811. //if there is not enough space for the escape sequence
  812. if (dwLen >= (dwMaxLength-3))
  813. {
  814. bRet = FALSE;
  815. }
  816. if (bRet)
  817. {
  818. //output the percent, followed by the hex value of the character
  819. *lpszStringOut++ = '%';
  820. sprintf(lpszStringOut, "%.2X", (unsigned char)(ch));
  821. lpszStringOut+= 2;
  822. }
  823. dwLen += 2;
  824. }
  825. }
  826. else //safe character
  827. {
  828. if (bRet)
  829. *lpszStringOut++ = ch;
  830. }
  831. dwLen++;
  832. }
  833. if (bRet)
  834. *lpszStringOut = '\0';
  835. *pdwStrLen = dwLen;
  836. return bRet;
  837. }
  838. // -----------------------------------------------------------------------------
  839. DWORD LOGON::Logon(
  840. BOOL fAnonymous
  841. )
  842. {
  843. PP_ASSERT(m_pSession != NULL);
  844. DWORD dwRetVal = (DWORD)PP_GENERIC_ERROR;
  845. BOOL fTicketRequest;
  846. HINTERNET hRequest = 0;
  847. DWORD dwFlags = 0;
  848. ::wcscpy(m_pwszAuthHeader, L"Authorization: Passport1.4 ");
  849. if (m_fCredsPresent && !fAnonymous)
  850. {
  851. if (m_pSession->GetNexusVersion() >= 10)
  852. {
  853. DWORD dwUTF8CredLen = max(::wcslen(m_pwszSignIn), ::wcslen(m_pwszPassword)) * 3;
  854. DWORD dwEscCredLen = dwUTF8CredLen * 3;
  855. DWORD dwActualEscCredLen;
  856. PSTR pszUTF8Cred = NULL;
  857. PSTR pszEscCred = NULL;
  858. PWSTR pwszEscCred = NULL;
  859. BOOL fExit = TRUE;
  860. pszUTF8Cred = new CHAR[dwUTF8CredLen];
  861. if (pszUTF8Cred == NULL)
  862. {
  863. goto local_cleanup;
  864. }
  865. pszUTF8Cred[0] = 0;
  866. pszEscCred = new CHAR[dwEscCredLen];
  867. if (pszEscCred == NULL)
  868. {
  869. goto local_cleanup;
  870. }
  871. pszEscCred[0] = 0;
  872. pwszEscCred = new WCHAR[dwEscCredLen];
  873. if (pwszEscCred == NULL)
  874. {
  875. goto local_cleanup;
  876. }
  877. pwszEscCred[0] = 0;
  878. ::WideCharToMultiByte(CP_UTF8, 0, m_pwszSignIn, -1, pszUTF8Cred, dwUTF8CredLen, NULL, NULL);
  879. ::PPEscapeUrl(pszUTF8Cred, pszEscCred, &dwActualEscCredLen, dwEscCredLen, 0);
  880. int UsernameLength = ::MultiByteToWideChar(CP_ACP, 0, pszEscCred, -1, pwszEscCred, dwEscCredLen);
  881. if (UsernameLength > MAX_PASSPORT_USERNAME_LENGTH)
  882. {
  883. goto local_cleanup;
  884. }
  885. ::wcscat(m_pwszAuthHeader, L"sign-in=");
  886. ::wcscat(m_pwszAuthHeader, pwszEscCred);
  887. ::wcscat(m_pwszAuthHeader, L",");
  888. ::WideCharToMultiByte(CP_UTF8, 0, m_pwszPassword, -1, pszUTF8Cred, dwUTF8CredLen, NULL, NULL);
  889. ::PPEscapeUrl(pszUTF8Cred, pszEscCred, &dwActualEscCredLen, dwEscCredLen, 0);
  890. int PasswordLength = ::MultiByteToWideChar(CP_ACP, 0, pszEscCred, -1, pwszEscCred, dwEscCredLen);
  891. if (PasswordLength > MAX_PASSPORT_PASSWORD_LENGTH)
  892. {
  893. goto local_cleanup;
  894. }
  895. ::wcscat(m_pwszAuthHeader, L"pwd=");
  896. ::wcscat(m_pwszAuthHeader, pwszEscCred);
  897. ::wcscat(m_pwszAuthHeader, L",");
  898. fExit = FALSE;
  899. local_cleanup:
  900. if (pwszEscCred)
  901. {
  902. SecureZeroMemory(pwszEscCred, ::wcslen(pwszEscCred) * sizeof(WCHAR));
  903. delete [] pwszEscCred;
  904. }
  905. if (pszEscCred)
  906. {
  907. SecureZeroMemory(pszEscCred, ::strlen(pszEscCred));
  908. delete [] pszEscCred;
  909. }
  910. if (pszUTF8Cred)
  911. {
  912. SecureZeroMemory(pszUTF8Cred, ::strlen(pszUTF8Cred));
  913. delete [] pszUTF8Cred;
  914. }
  915. if (fExit)
  916. {
  917. goto exit;
  918. }
  919. }
  920. else
  921. {
  922. if (::wcslen(m_pwszSignIn) > MAX_PASSPORT_USERNAME_LENGTH)
  923. {
  924. goto exit;
  925. }
  926. ::wcscat(m_pwszAuthHeader, L"sign-in=");
  927. ::wcscat(m_pwszAuthHeader, m_pwszSignIn);
  928. ::wcscat(m_pwszAuthHeader, L",");
  929. if (::wcslen(m_pwszPassword) > MAX_PASSPORT_PASSWORD_LENGTH)
  930. {
  931. goto exit;
  932. }
  933. ::wcscat(m_pwszAuthHeader, L"pwd=");
  934. ::wcscat(m_pwszAuthHeader, m_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] && (::wcslen(m_wTimeSkew) <= MAX_PASSPORT_TIME_SKEW_LENGTH))
  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. }
  959. else
  960. {
  961. ::wcscat(m_pwszAuthHeader, L"tname = , ");
  962. fTicketRequest = TRUE;
  963. }
  964. ::wcscat(m_pwszAuthHeader, m_pwszTicketRequest);
  965. retry:
  966. // attempt connecting to the Passport DA
  967. if (m_hConnect)
  968. {
  969. m_pSession->CloseHandle(m_hConnect);
  970. }
  971. WCHAR wDATargetObj[256];
  972. DWORD fStstus = m_pSession->GetDAInfo(m_pwszSignIn,
  973. m_wDAHostName, MAX_PASSPORT_HOST_LENGTH,
  974. wDATargetObj, 256);
  975. if (fStstus == FALSE)
  976. {
  977. goto exit;
  978. }
  979. m_hConnect = m_pSession->Connect(m_wDAHostName/*m_pSession->GetLoginHost()*/,
  980. INTERNET_DEFAULT_HTTPS_PORT);
  981. if (m_hConnect == NULL)
  982. {
  983. DWORD dwErrorCode = ::GetLastError();
  984. DoTraceMessage(PP_LOG_ERROR, "LOGON::Open() failed; can not connect to %ws, Error = %d",
  985. m_wDAHostName, dwErrorCode);
  986. goto exit;
  987. }
  988. if (hRequest)
  989. {
  990. m_pSession->CloseHandle(hRequest);
  991. }
  992. dwFlags = m_dwParentFlags & ~INTERNET_FLAG_NO_COOKIES;
  993. hRequest = m_pSession->OpenRequest(m_hConnect,
  994. NULL, // "GET"
  995. wDATargetObj/*m_pSession->GetLoginTarget()*/,
  996. dwFlags | WINHTTP_FLAG_SECURE,
  997. (DWORD_PTR)this
  998. );
  999. if (hRequest == NULL)
  1000. {
  1001. DWORD dwErrorCode = ::GetLastError();
  1002. DoTraceMessage(PP_LOG_ERROR, "LOGON::Logon() failed; OpenRequest() to %ws failed, Error Code = %d",
  1003. wDATargetObj, dwErrorCode);
  1004. goto exit;
  1005. }
  1006. if (m_dwParentFlags & INTERNET_FLAG_NO_COOKIES)
  1007. {
  1008. ULONG ulParam = WINHTTP_DISABLE_COOKIES;
  1009. if (!WinHttpSetOption (hRequest, WINHTTP_OPTION_DISABLE_FEATURE , &ulParam, sizeof(ulParam)))
  1010. {
  1011. DWORD dwErrorCode = GetLastError();
  1012. DoTraceMessage(PP_LOG_ERROR, "LOGON::Logon() failed; WinHttpSetOption(WINHTTP_OPTION_DISABLE_FEATURE, NO_COOKIES), Error Code = %d", dwErrorCode);
  1013. goto exit;
  1014. }
  1015. }
  1016. if (m_pSession->m_pwszProxyUser && m_pSession->m_pwszProxyPass)
  1017. {
  1018. m_pSession->SetOption(hRequest, WINHTTP_OPTION_PROXY_USERNAME, (void*)m_pSession->m_pwszProxyUser, wcslen(m_pSession->m_pwszProxyUser) + 1);
  1019. m_pSession->SetOption(hRequest, WINHTTP_OPTION_PROXY_PASSWORD, (void*)m_pSession->m_pwszProxyPass, wcslen(m_pSession->m_pwszProxyPass) + 1);
  1020. }
  1021. m_wNewDAUrl[0] = 0;
  1022. m_pSession->SetStatusCallback(hRequest, PrvLogonStatusCallback);
  1023. if (!m_pSession->SendRequest(hRequest,
  1024. m_pwszAuthHeader,
  1025. ::wcslen(m_pwszAuthHeader),
  1026. (DWORD_PTR)this))
  1027. {
  1028. DWORD dwErrorCode = ::GetLastError();
  1029. if (dwErrorCode != ERROR_SUCCESS)
  1030. {
  1031. DoTraceMessage(PP_LOG_ERROR, "LOGON::Logon() failed; SendRequest() failed, Error Code = %d",
  1032. dwErrorCode);
  1033. m_pSession->PurgeDAInfo(m_pwszSignIn);
  1034. if (m_pSession->GetDAInfoFromPPNexus() == TRUE)
  1035. {
  1036. goto retry;
  1037. }
  1038. goto exit;
  1039. }
  1040. }
  1041. if (m_pSession->ReceiveResponse(hRequest) == FALSE)
  1042. {
  1043. DWORD dwErrorCode = ::GetLastError();
  1044. DoTraceMessage(PP_LOG_ERROR, "LOGON::Logon() failed; ReceiveResponse() failed, Error Code = %d",
  1045. dwErrorCode);
  1046. goto exit;
  1047. }
  1048. {
  1049. DWORD dwStatus, dwStatusLen;
  1050. dwStatusLen = sizeof(dwStatus);
  1051. if (!m_pSession->QueryHeaders(hRequest,
  1052. WINHTTP_QUERY_FLAG_NUMBER | WINHTTP_QUERY_STATUS_CODE,
  1053. &dwStatus,
  1054. &dwStatusLen))
  1055. {
  1056. DWORD dwErrorCode = ::GetLastError();
  1057. DoTraceMessage(PP_LOG_ERROR, "LOGON::Logon() failed; can not retrieve Status Code, Error Code = %d",
  1058. dwErrorCode);
  1059. goto exit;
  1060. }
  1061. if (dwStatus == HTTP_STATUS_DENIED)
  1062. {
  1063. dwRetVal = Handle401FromDA(hRequest, fTicketRequest);
  1064. }
  1065. else if (dwStatus == HTTP_STATUS_OK)
  1066. {
  1067. dwRetVal = Handle200FromDA(hRequest);
  1068. }
  1069. else
  1070. {
  1071. //PP_ASSERT(TRUE); // shouldn't reach here
  1072. //goto exit;
  1073. }
  1074. CheckForVersionChange(hRequest);
  1075. if (dwRetVal == PP_GENERIC_ERROR)
  1076. {
  1077. m_pSession->PurgeDAInfo(m_pwszSignIn);
  1078. if (m_pSession->GetDAInfoFromPPNexus() == TRUE)
  1079. {
  1080. goto retry;
  1081. }
  1082. }
  1083. else
  1084. {
  1085. if (m_wNewDAUrl[0])
  1086. {
  1087. m_pSession->UpdateDAInfo(m_pwszSignIn,
  1088. m_wNewDAUrl);
  1089. m_wNewDAUrl[0] = 0;
  1090. }
  1091. }
  1092. }
  1093. exit:
  1094. if (hRequest)
  1095. {
  1096. m_pSession->CloseHandle(hRequest);
  1097. }
  1098. return dwRetVal;
  1099. }
  1100. // -----------------------------------------------------------------------------
  1101. BOOL LOGON::GetChallengeInfo(
  1102. PBOOL pfPrompt,
  1103. PWSTR pwszCbUrl,
  1104. PDWORD pdwCbUrlLen,
  1105. PWSTR pwszCbText,
  1106. PDWORD pdwTextLen,
  1107. PWSTR pwszRealm,
  1108. DWORD dwMaxRealmLen
  1109. ) const
  1110. {
  1111. if (pfPrompt)
  1112. {
  1113. *pfPrompt = m_fPrompt;
  1114. }
  1115. if (m_pwszCbtxt == NULL)
  1116. {
  1117. *pdwTextLen = 0;
  1118. }
  1119. else
  1120. {
  1121. if (*pdwTextLen < DWORD(::wcslen(m_pwszCbtxt) + 1))
  1122. {
  1123. *pdwTextLen = ::wcslen(m_pwszCbtxt) + 1;
  1124. }else
  1125. {
  1126. ::wcscpy(pwszCbText, m_pwszCbtxt);
  1127. }
  1128. }
  1129. if (m_pwszCbUrl == NULL)
  1130. {
  1131. *pdwCbUrlLen = 0;
  1132. }
  1133. else
  1134. {
  1135. if (*pdwCbUrlLen < DWORD(::wcslen(m_pwszCbUrl) + 1))
  1136. {
  1137. *pdwCbUrlLen = ::wcslen(m_pwszCbUrl) + 1;
  1138. }
  1139. else
  1140. {
  1141. ::wcscpy(pwszCbUrl, m_pwszCbUrl);
  1142. }
  1143. }
  1144. if (pwszRealm)
  1145. {
  1146. ::wcsncpy(pwszRealm, m_wRealm, dwMaxRealmLen-1);
  1147. }
  1148. return TRUE;
  1149. }
  1150. BOOL LOGON::GetChallengeContent(
  1151. PBYTE pContent,
  1152. OUT PDWORD pdwContentLen
  1153. ) const
  1154. {
  1155. if(!DelayLoad( &g_moduleOle32))
  1156. {
  1157. *pdwContentLen = 0;
  1158. return FALSE;
  1159. }
  1160. if (m_p401Content == NULL)
  1161. {
  1162. *pdwContentLen = 0;
  1163. return FALSE;
  1164. }
  1165. HGLOBAL hContent;
  1166. if (DL(GetHGlobalFromStream)(m_p401Content, &hContent) != S_OK)
  1167. {
  1168. *pdwContentLen = 0;
  1169. return FALSE;
  1170. }
  1171. DWORD dwContentLen = (DWORD)GlobalSize(hContent);
  1172. if (*pdwContentLen < dwContentLen)
  1173. {
  1174. *pdwContentLen = dwContentLen;
  1175. return FALSE;
  1176. }
  1177. LPVOID pvContent = GlobalLock(hContent);
  1178. memcpy(pContent, pvContent, dwContentLen);
  1179. GlobalUnlock(hContent);
  1180. *pdwContentLen = dwContentLen;
  1181. return TRUE;
  1182. }
  1183. // -----------------------------------------------------------------------------
  1184. BOOL LOGON::GetAuthorizationInfo(
  1185. PWSTR pwszTicket,
  1186. PDWORD pdwTicketLen,
  1187. PBOOL pfKeepVerb,
  1188. PWSTR pwszUrl,
  1189. PDWORD pdwUrlLen
  1190. ) const
  1191. {
  1192. if (*pdwTicketLen < DWORD(::wcslen(m_pwszAuthInfo) + 1))
  1193. {
  1194. *pdwTicketLen = ::wcslen(m_pwszAuthInfo) + 1;
  1195. return FALSE;
  1196. }
  1197. PP_ASSERT(pwszTicket != NULL);
  1198. ::wcscpy(pwszTicket, m_pwszAuthInfo);
  1199. *pdwTicketLen = ::wcslen(m_pwszAuthInfo) + 1;
  1200. if (m_pwszReturnUrl == NULL)
  1201. {
  1202. if (pfKeepVerb)
  1203. {
  1204. *pfKeepVerb = TRUE;
  1205. }
  1206. *pdwUrlLen = 0;
  1207. return TRUE;
  1208. }
  1209. if (*pdwUrlLen < DWORD(::wcslen(m_pwszReturnUrl) + 1))
  1210. {
  1211. *pdwUrlLen = ::wcslen(m_pwszReturnUrl) + 1;
  1212. return FALSE;
  1213. }
  1214. PP_ASSERT(pwszUrl != NULL);
  1215. ::wcscpy(pwszUrl, m_pwszReturnUrl);
  1216. if (pfKeepVerb)
  1217. {
  1218. *pfKeepVerb = FALSE;
  1219. }
  1220. *pdwUrlLen = ::wcslen(m_pwszReturnUrl) + 1;
  1221. return TRUE;
  1222. }