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.

4859 lines
142 KiB

  1. /**********************************************************************/
  2. /** Microsoft Passport **/
  3. /** Copyright(c) Microsoft Corporation, 1999 - 2001 **/
  4. /**********************************************************************/
  5. /*
  6. manager.cpp
  7. COM object for manager interface
  8. FILE HISTORY:
  9. */
  10. // Manager.cpp : Implementation of CManager
  11. #include "stdafx.h"
  12. #include <httpext.h>
  13. #include "Manager.h"
  14. #include <httpfilt.h>
  15. #include <time.h>
  16. #include <malloc.h>
  17. #include <wininet.h>
  18. #include <nsconst.h>
  19. #include "VariantUtils.h"
  20. #include "HelperFuncs.h"
  21. #include "RegistryConfig.h"
  22. #include "PassportService_i.c"
  23. #include "atlbase.h"
  24. PWSTR GetVersionString();
  25. //using namespace ATL;
  26. // gmarks
  27. #include "Monitoring.h"
  28. /////////////////////////////////////////////////////////////////////////////
  29. // CManager
  30. #include "passporttypes.h"
  31. // static utility func
  32. static VOID GetTicketAndProfileFromHeader(PWSTR pszAuthHeader,
  33. PWSTR& pszTicket,
  34. PWSTR& pszProfile,
  35. PWSTR& pszF);
  36. // Used for cookie expiration.
  37. const DATE g_dtExpire = 365*137;
  38. const DATE g_dtExpired = 365*81;
  39. //===========================================================================
  40. //
  41. // CManager
  42. //
  43. CManager::CManager() :
  44. m_fromQueryString(false), m_ticketValid(VARIANT_FALSE),
  45. m_profileValid(VARIANT_FALSE), m_lNetworkError(0),
  46. m_pRegistryConfig(NULL), m_pECB(NULL), m_pFC(NULL),
  47. m_bIsTweenerCapable(FALSE),
  48. m_bSecureTransported(false)
  49. {
  50. PPTraceFuncV func(PPTRACE_FUNC, "CManager");
  51. // ticket object
  52. m_pUnkMarshaler = NULL;
  53. try
  54. {
  55. m_piTicket = new CComObject<CTicket>();
  56. }
  57. catch(...)
  58. {
  59. m_piTicket = NULL;
  60. }
  61. if(m_piTicket)
  62. m_piTicket->AddRef();
  63. // profile object
  64. try
  65. {
  66. m_piProfile = new CComObject<CProfile>();
  67. }
  68. catch(...)
  69. {
  70. m_piProfile = NULL;
  71. }
  72. if(m_piProfile)
  73. m_piProfile->AddRef();
  74. m_bOnStartPageCalled = false;
  75. }
  76. //===========================================================================
  77. //
  78. // ~CManager
  79. //
  80. CManager::~CManager()
  81. {
  82. PPTraceFuncV func(PPTRACE_FUNC, "~CManager");
  83. if(m_pRegistryConfig)
  84. m_pRegistryConfig->Release();
  85. if (m_piTicket) m_piTicket->Release();
  86. if (m_piProfile) m_piProfile->Release();
  87. }
  88. //===========================================================================
  89. //
  90. // IfConsentCookie -- if a consent cookie should be sent back
  91. // return value: S_OK -- has consent cookie; S_FALSE -- no consent cookie
  92. // output param: The consent cookie
  93. //
  94. HRESULT CManager::IfConsentCookie(BSTR* pMSPConsent)
  95. {
  96. BSTR bstrRawConsent = NULL;
  97. HRESULT hr = S_FALSE;
  98. PPTraceFunc<HRESULT>
  99. func(
  100. PPTRACE_FUNC,
  101. hr,
  102. "IfConsentCookie"," <<<< %lx",
  103. pMSPConsent
  104. );
  105. if (!m_piTicket || !m_piProfile || !m_pRegistryConfig)
  106. {
  107. hr = E_OUTOFMEMORY;
  108. goto Cleanup;
  109. }
  110. LPCSTR domain = m_pRegistryConfig->getTicketDomain();
  111. LPCSTR path = m_pRegistryConfig->getTicketPath();
  112. LPCSTR tertiaryDomain = m_pRegistryConfig->getProfileDomain();
  113. LPCSTR tertiaryPath = m_pRegistryConfig->getProfilePath();
  114. if (!tertiaryPath) tertiaryPath = "/";
  115. if(!domain) domain = "";
  116. if(!path) path = "";
  117. if(!tertiaryDomain) tertiaryDomain = "";
  118. if(!tertiaryPath) tertiaryPath = "";
  119. //
  120. // if a separate consent cookie is necessary
  121. if((lstrcmpiA(domain, tertiaryDomain) || lstrcmpiA(path, tertiaryPath)) &&
  122. (m_piTicket->GetPassportFlags() & k_ulFlagsConsentCookieNeeded) &&
  123. !m_pRegistryConfig->bInDA() )
  124. {
  125. if (pMSPConsent == NULL) // no output param
  126. hr = S_OK;
  127. else
  128. {
  129. *pMSPConsent = NULL;
  130. CCoCrypt* crypt = m_pRegistryConfig->getCurrentCrypt();
  131. if (!crypt)
  132. {
  133. hr = E_FAIL;
  134. goto Cleanup;
  135. }
  136. // get the consent cookie from ticket
  137. hr = m_piTicket->get_unencryptedCookie(CTicket::MSPConsent, 0, &bstrRawConsent);
  138. if (FAILED(hr))
  139. goto Cleanup;
  140. // encrypt it with partner's key
  141. if (!crypt->Encrypt(m_pRegistryConfig->getCurrentCryptVersion(),
  142. (LPSTR)bstrRawConsent,
  143. SysStringByteLen(bstrRawConsent),
  144. pMSPConsent))
  145. {
  146. hr = E_FAIL;
  147. goto Cleanup;
  148. }
  149. }
  150. }
  151. Cleanup:
  152. if (bstrRawConsent)
  153. {
  154. SysFreeString(bstrRawConsent);
  155. }
  156. if(pMSPConsent)
  157. PPTracePrint(PPTRACE_RAW, ">>> pMSPConsent:%ws", PPF_WCHAR(*pMSPConsent));
  158. return hr;
  159. }
  160. //===========================================================================
  161. //
  162. // IfAlterAuthCookie
  163. //
  164. // return S_OK -- when auth cookie is different from t (altered), should use
  165. // the cookie and secAuth cookie returned
  166. // S_FALSE -- not altered -- can use the t as auth cookie
  167. // if MSPSecAuth != NULL, write the secure cookie
  168. HRESULT CManager::IfAlterAuthCookie(BSTR* pMSPAuth, BSTR* pMSPSecAuth)
  169. {
  170. _ASSERT(pMSPAuth && pMSPSecAuth);
  171. *pMSPAuth = NULL;
  172. *pMSPSecAuth = NULL;
  173. HRESULT hr = S_FALSE;
  174. PPTraceFunc<HRESULT> func(PPTRACE_FUNC, hr,
  175. "IfAlterAuthCookie", "<<< %lx, %lx",
  176. pMSPAuth, pMSPSecAuth);
  177. if (!m_piTicket || !m_piProfile || !m_pRegistryConfig)
  178. {
  179. return E_OUTOFMEMORY;
  180. }
  181. if (!(m_piTicket->GetPassportFlags() & k_ulFlagsSecuredTransportedTicket)
  182. || !m_bSecureTransported)
  183. {
  184. return hr;
  185. }
  186. BSTR bstrRawAuth = NULL;
  187. BSTR bstrRawSecAuth = NULL;
  188. CCoCrypt* crypt = m_pRegistryConfig->getCurrentCrypt();
  189. if (!crypt)
  190. {
  191. hr = PM_CANT_DECRYPT_CONFIG;
  192. goto Cleanup;
  193. }
  194. hr = m_piTicket->get_unencryptedCookie(CTicket::MSPAuth, 0, &bstrRawAuth);
  195. if (FAILED(hr))
  196. goto Cleanup;
  197. if (!crypt->Encrypt(m_pRegistryConfig->getCurrentCryptVersion(),
  198. (LPSTR)bstrRawAuth,
  199. SysStringByteLen(bstrRawAuth),
  200. pMSPAuth))
  201. {
  202. hr = PM_CANT_DECRYPT_CONFIG;
  203. goto Cleanup;
  204. }
  205. hr = m_piTicket->get_unencryptedCookie(CTicket::MSPSecAuth, 0, &bstrRawSecAuth);
  206. if (FAILED(hr))
  207. goto Cleanup;
  208. if (!crypt->Encrypt(m_pRegistryConfig->getCurrentCryptVersion(),
  209. (LPSTR)bstrRawSecAuth,
  210. SysStringByteLen(bstrRawSecAuth),
  211. pMSPSecAuth))
  212. {
  213. hr = PM_CANT_DECRYPT_CONFIG;
  214. goto Cleanup;
  215. }
  216. Cleanup:
  217. if (bstrRawAuth)
  218. {
  219. SysFreeString(bstrRawAuth);
  220. }
  221. if (bstrRawSecAuth)
  222. {
  223. SysFreeString(bstrRawSecAuth);
  224. }
  225. PPTracePrint(PPTRACE_RAW,
  226. ">>> pMSPAuth:%ws, pMSPSecAuth:%ws",
  227. PPF_WCHAR(*pMSPAuth),
  228. PPF_WCHAR(*pMSPSecAuth));
  229. return hr;
  230. }
  231. //===========================================================================
  232. //
  233. // wipeState -- cleanup teh state of manager object
  234. //
  235. void
  236. CManager::wipeState()
  237. {
  238. PPTraceFuncV func(PPTRACE_FUNC, "wipeState");
  239. m_pECB = NULL;
  240. m_pFC = NULL;
  241. m_bIsTweenerCapable = FALSE;
  242. m_bOnStartPageCalled = false;
  243. m_fromQueryString = false;
  244. m_lNetworkError = 0;
  245. m_ticketValid = VARIANT_FALSE;
  246. m_profileValid = VARIANT_FALSE;
  247. m_piRequest = NULL;
  248. m_piResponse = NULL;
  249. // cleanup ticket content
  250. if(m_piTicket) m_piTicket->put_unencryptedTicket(NULL);
  251. // cleanup profile content
  252. if(m_piProfile) m_piProfile->put_unencryptedProfile(NULL);
  253. // cleanup buffered registry config
  254. if(m_pRegistryConfig)
  255. {
  256. m_pRegistryConfig->Release();
  257. m_pRegistryConfig = NULL;
  258. }
  259. }
  260. //===========================================================================
  261. //
  262. // InterfaceSupportsErrorInfo
  263. //
  264. STDMETHODIMP CManager::InterfaceSupportsErrorInfo(REFIID riid)
  265. {
  266. PPTraceFuncV func(PPTRACE_FUNC, "InterfaceSupportsErrorInfo");
  267. static const IID* arr[] =
  268. {
  269. &IID_IPassportManager,
  270. &IID_IPassportManager2,
  271. &IID_IPassportManager3,
  272. &IID_IDomainMap,
  273. };
  274. for (int i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
  275. {
  276. if (InlineIsEqualGUID(*arr[i],riid))
  277. return S_OK;
  278. }
  279. return S_FALSE;
  280. }
  281. //===========================================================================
  282. //
  283. // OnStartPage -- called by ASP pages automatically by IIS when declared on the page
  284. //
  285. STDMETHODIMP CManager::OnStartPage (IUnknown* pUnk)
  286. {
  287. HRESULT hr = S_OK;
  288. PPTraceFunc<HRESULT> func(PPTRACE_FUNC, hr,
  289. "OnStartPage"," <<< %lx",
  290. pUnk);
  291. if(!pUnk)
  292. {
  293. return hr = E_POINTER;
  294. }
  295. IScriptingContextPtr spContext;
  296. spContext = pUnk;
  297. // Get Request Object Pointer
  298. hr = OnStartPageASP(spContext->Request, spContext->Response);
  299. return hr;
  300. }
  301. BSTR
  302. MyA2W(
  303. char *src
  304. )
  305. {
  306. if (src == NULL)
  307. {
  308. return NULL;
  309. }
  310. BSTR str = NULL;
  311. int nConvertedLen = MultiByteToWideChar(GetACP(), 0, src, -1, NULL, NULL);
  312. str = ::SysAllocStringLen(NULL, nConvertedLen - 1);
  313. if (str != NULL)
  314. {
  315. if (!MultiByteToWideChar(GetACP(), 0, src, -1, str, nConvertedLen))
  316. {
  317. SysFreeString(str);
  318. str = NULL;
  319. }
  320. }
  321. return str;
  322. }
  323. //===========================================================================
  324. //
  325. // OnStartPageASP -- called by asp pages when created by using factory object
  326. // FUTURE --- should change the OnStartPage function to use this function
  327. //
  328. STDMETHODIMP CManager::OnStartPageASP(
  329. IDispatch* piRequest,
  330. IDispatch* piResponse
  331. )
  332. {
  333. HRESULT hr = S_OK;
  334. char* spBuf = NULL;
  335. BSTR bstrName=NULL;
  336. BSTR bstrValue=NULL;
  337. PPTraceFunc<HRESULT> func(PPTRACE_FUNC, hr,
  338. "OnStartPageASP",
  339. " <<< %lx, %lx", piRequest, piResponse);
  340. PassportLog("CManager::OnStartPageASP Enter:\r\n");
  341. if(!piRequest || !piResponse)
  342. return hr = E_INVALIDARG;
  343. USES_CONVERSION;
  344. try
  345. {
  346. IRequestDictionaryPtr piServerVariables;
  347. _variant_t vtItemName;
  348. _variant_t vtHTTPS;
  349. _variant_t vtMethod;
  350. _variant_t vtPath;
  351. _variant_t vtQs;
  352. _variant_t vtServerPort;
  353. _variant_t vtHeaders;
  354. CComQIPtr<IResponse> spResponse;
  355. CComQIPtr<IRequest> spRequest;
  356. // Get Request Object Pointer
  357. spRequest = piRequest;
  358. spResponse = piResponse;
  359. //
  360. // Get the server variables collection.
  361. //
  362. spRequest->get_ServerVariables(&piServerVariables);
  363. //
  364. // now see if that's a special redirect
  365. // requiring challenge generation
  366. // if so processing stops here ....
  367. //
  368. if (checkForPassportChallenge(piServerVariables))
  369. {
  370. PPTracePrint(PPTRACE_RAW, "special redirect for Challenge");
  371. return S_OK;
  372. }
  373. //
  374. // Might need this for multi-site, or secure ticket/profile
  375. //
  376. vtItemName = L"HTTPS";
  377. piServerVariables->get_Item(vtItemName, &vtHTTPS);
  378. if(vtHTTPS.vt != VT_BSTR)
  379. vtHTTPS.ChangeType(VT_BSTR);
  380. DWORD flags = 0;
  381. if(vtHTTPS.bstrVal && lstrcmpiW(L"on", vtHTTPS.bstrVal) == 0)
  382. flags |= PASSPORT_HEADER_FLAGS_HTTPS;
  383. // headers
  384. vtItemName.Clear();
  385. vtItemName = L"ALL_RAW";
  386. piServerVariables->get_Item(vtItemName, &vtHeaders);
  387. if(vtHeaders.vt != VT_BSTR){
  388. vtHeaders.ChangeType(VT_BSTR);
  389. }
  390. // path
  391. vtItemName.Clear();
  392. vtItemName = L"PATH_INFO";
  393. piServerVariables->get_Item(vtItemName, &vtPath);
  394. if(vtPath.vt != VT_BSTR)
  395. vtPath.ChangeType(VT_BSTR);
  396. // vtMethod
  397. vtItemName.Clear();
  398. vtItemName = L"REQUEST_METHOD";
  399. piServerVariables->get_Item(vtItemName, &vtMethod);
  400. if(vtMethod.vt != VT_BSTR)
  401. vtMethod.ChangeType(VT_BSTR);
  402. // QUERY_STRING
  403. vtItemName.Clear();
  404. vtItemName = L"QUERY_STRING";
  405. piServerVariables->get_Item(vtItemName, &vtQs);
  406. if(vtQs.vt != VT_BSTR)
  407. vtQs.ChangeType(VT_BSTR);
  408. DWORD bufSize = 0;
  409. DWORD requiredBufSize = MAX_URL_LENGTH;
  410. // make sure the size if sufficient
  411. while(bufSize < requiredBufSize)
  412. {
  413. if (spBuf)
  414. {
  415. free(spBuf);
  416. }
  417. if(NULL == (spBuf = (char *)malloc(requiredBufSize)))
  418. {
  419. hr = E_OUTOFMEMORY;
  420. goto exit;
  421. }
  422. bufSize = requiredBufSize;
  423. hr = OnStartPageHTTPRawEx(W2A(vtMethod.bstrVal),
  424. W2A(vtPath.bstrVal),
  425. W2A(vtQs.bstrVal),
  426. NULL, // version
  427. W2A(vtHeaders.bstrVal),
  428. flags,
  429. &requiredBufSize,
  430. spBuf);
  431. }
  432. // write the cookies
  433. if(hr == S_OK && requiredBufSize && *spBuf)
  434. {
  435. char* pNext = spBuf;
  436. while(pNext != NULL)
  437. {
  438. char* pName = pNext;
  439. char* pValue = strchr(pName, ':');
  440. if(pValue)
  441. {
  442. // make temp sub string
  443. TempSubStr tsN(pName, pValue - pName);
  444. bstrName = MyA2W(pName);
  445. if (bstrName) {
  446. ++pValue;
  447. pNext = strstr(pValue, "\r\n"); // new line
  448. if(pNext)
  449. {
  450. // make temp sub string
  451. TempSubStr tsV(pValue, pNext - pValue);
  452. pNext += 2;
  453. bstrValue = MyA2W(pValue);
  454. }
  455. else
  456. {
  457. bstrValue = MyA2W(pValue);
  458. }
  459. if (bstrValue)
  460. {
  461. spResponse->raw_AddHeader(bstrName, bstrValue);
  462. }
  463. }
  464. }
  465. else
  466. {
  467. pNext = pValue;
  468. }
  469. if (bstrName) {
  470. SysFreeString(bstrName);
  471. bstrName = NULL;
  472. }
  473. if (bstrValue) {
  474. SysFreeString(bstrValue);
  475. bstrValue = NULL;
  476. }
  477. }
  478. }
  479. if (spBuf) {
  480. free(spBuf);
  481. spBuf = NULL;
  482. }
  483. // Get Request Object Pointer
  484. m_piRequest = piRequest;
  485. // Get Response Object Pointer
  486. m_piResponse = piResponse;
  487. }
  488. catch (...)
  489. {
  490. if (m_piRequest.GetInterfacePtr() != NULL)
  491. m_piRequest.Release();
  492. if (m_piResponse.GetInterfacePtr() != NULL)
  493. m_piResponse.Release();
  494. m_bOnStartPageCalled = false;
  495. if (spBuf) {
  496. free(spBuf);
  497. }
  498. if (bstrName) {
  499. SysFreeString(bstrName);
  500. }
  501. if (bstrValue) {
  502. SysFreeString(bstrValue);
  503. }
  504. }
  505. exit:
  506. return hr = S_OK;
  507. }
  508. //===========================================================================
  509. //
  510. // OnStartPageManual -- authenticate with t, and p, MSPAuth, MSPProf, MSPConsent, MSPsecAuth
  511. // not recommended to use, will be depracated
  512. //
  513. STDMETHODIMP CManager::OnStartPageManual(
  514. BSTR qsT,
  515. BSTR qsP,
  516. BSTR mspauth,
  517. BSTR mspprof,
  518. BSTR mspconsent,
  519. VARIANT mspsec,
  520. VARIANT* pCookies
  521. )
  522. {
  523. int hasSec;
  524. BSTR bstrSec;
  525. BSTR bstrConsent = NULL;
  526. BSTR bstrNewAuth = NULL;
  527. BSTR bstrNewSecAuth = NULL;
  528. HRESULT hr = S_OK;
  529. PPTraceFunc<HRESULT> func(PPTRACE_FUNC, hr,
  530. "OnStartPageManual",
  531. " <<< %ws, %ws, %ws, %ws, %ws", qsT, qsP, mspauth, mspprof, mspconsent);
  532. PassportLog("CManager::OnStartPageManual Enter: T = %ws, P = %ws, A = %ws, PR = %ws\r\n",
  533. qsT, qsP, mspauth, mspprof);
  534. if (!g_config->isValid()) // Guarantees config is non-null
  535. {
  536. AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
  537. IID_IPassportManager, PP_E_NOT_CONFIGURED);
  538. return PP_E_NOT_CONFIGURED;
  539. }
  540. if (!m_piTicket || !m_piProfile)
  541. {
  542. return E_OUTOFMEMORY;
  543. }
  544. wipeState();
  545. if(m_pRegistryConfig)
  546. m_pRegistryConfig->Release();
  547. m_pRegistryConfig = g_config->checkoutRegistryConfig();
  548. // Auth with Query String T & P first
  549. if (handleQueryStringData(qsT, qsP))
  550. {
  551. VARIANT_BOOL persist;
  552. _bstr_t domain;
  553. _bstr_t path;
  554. _bstr_t bstrAuth;
  555. _bstr_t bstrProf;
  556. bstrAuth.Assign(qsT);
  557. bstrProf.Assign(qsP);
  558. if (pCookies)
  559. {
  560. VariantInit(pCookies);
  561. if (m_pRegistryConfig->getTicketPath())
  562. path = m_pRegistryConfig->getTicketPath();
  563. else
  564. path = L"/";
  565. m_piTicket->get_HasSavedPassword(&persist);
  566. BOOL bSetConsent = (S_OK == IfConsentCookie(&bstrConsent));
  567. SAFEARRAYBOUND rgsabound;
  568. rgsabound.lLbound = 0;
  569. rgsabound.cElements = 2;
  570. // secure cookie
  571. if (m_bSecureTransported)
  572. rgsabound.cElements++;
  573. if(bSetConsent)
  574. rgsabound.cElements++;
  575. SAFEARRAY *sa = SafeArrayCreate(VT_VARIANT, 1, &rgsabound);
  576. if (!sa)
  577. {
  578. hr = E_OUTOFMEMORY;
  579. goto Cleanup;
  580. }
  581. pCookies->vt = VT_ARRAY | VT_VARIANT;
  582. pCookies->parray = sa;
  583. WCHAR buf[4096];
  584. DWORD bufSize;
  585. long spot = 0;
  586. VARIANT *vArray;
  587. SafeArrayAccessData(sa, (void**)&vArray);
  588. // write Auth cookies
  589. BSTR auth, secAuth; // do not call SysFreeString on them, they are skin level copy
  590. if (S_OK == IfAlterAuthCookie(&bstrNewAuth, &bstrNewSecAuth))
  591. {
  592. auth = bstrNewAuth;
  593. secAuth = bstrNewSecAuth;
  594. }
  595. else
  596. {
  597. auth = bstrAuth;
  598. secAuth = NULL;
  599. }
  600. domain = m_pRegistryConfig->getTicketDomain();
  601. // add MSPAuth
  602. if (domain.length())
  603. {
  604. bufSize = _snwprintf(buf, 4096,
  605. L"Set-Cookie: MSPAuth=%s; path=%s; domain=%s; %s\r\n",
  606. (LPWSTR)auth, (LPWSTR)path, (LPWSTR)domain,
  607. persist ? W_COOKIE_EXPIRES(EXPIRE_FUTURE) : L"");
  608. }
  609. else
  610. {
  611. bufSize = _snwprintf(buf, 4096,
  612. L"Set-Cookie: MSPAuth=%s; path=%s; %s\r\n",
  613. (LPWSTR)auth, (LPWSTR)path,
  614. persist ? W_COOKIE_EXPIRES(EXPIRE_FUTURE) : L"");
  615. }
  616. buf[4095] = L'\0';
  617. vArray[spot].vt = VT_BSTR;
  618. vArray[spot].bstrVal = ALLOC_AND_GIVEAWAY_BSTR_LEN(buf, bufSize);
  619. spot++;
  620. // add MSPSecAuth
  621. if (m_bSecureTransported)
  622. {
  623. _bstr_t secDomain = m_pRegistryConfig->getSecureDomain();
  624. _bstr_t secPath;
  625. if (m_pRegistryConfig->getSecurePath())
  626. secPath = m_pRegistryConfig->getSecurePath();
  627. else
  628. secPath = L"/";
  629. if (secDomain.length())
  630. {
  631. bufSize = _snwprintf(buf, 4096,
  632. L"Set-Cookie: MSPSecAuth=%s; path=%s; domain=%s; %s; secure\r\n",
  633. ((secAuth && *secAuth) ? (LPWSTR)secAuth : L""), (LPWSTR)secPath, (LPWSTR)secDomain,
  634. ((!secAuth || *secAuth == 0) ? W_COOKIE_EXPIRES(EXPIRE_PAST)
  635. : L""));
  636. }
  637. else
  638. {
  639. bufSize = _snwprintf(buf, 4096,
  640. L"Set-Cookie: MSPSecAuth=%s; path=%s; %s; secure\r\n",
  641. ((secAuth && *secAuth) ? (LPWSTR)secAuth : L""), (LPWSTR)secPath,
  642. ((!secAuth || *secAuth == 0) ? W_COOKIE_EXPIRES(EXPIRE_PAST)
  643. : L""));
  644. }
  645. buf[4095] = L'\0';
  646. vArray[spot].vt = VT_BSTR;
  647. vArray[spot].bstrVal = ALLOC_AND_GIVEAWAY_BSTR_LEN(buf, bufSize);
  648. spot++;
  649. }
  650. if (domain.length())
  651. {
  652. bufSize = _snwprintf(buf, 4096,
  653. L"Set-Cookie: MSPProf=%s; path=%s; domain=%s; %s\r\n",
  654. (LPWSTR)bstrProf, (LPWSTR)path, (LPWSTR)domain,
  655. persist ? W_COOKIE_EXPIRES(EXPIRE_FUTURE) : L"");
  656. }
  657. else
  658. {
  659. bufSize = _snwprintf(buf, 4096,
  660. L"Set-Cookie: MSPProf=%s; path=%s; %s\r\n",
  661. (LPWSTR)bstrProf, (LPWSTR)path,
  662. persist ? W_COOKIE_EXPIRES(EXPIRE_FUTURE) : L"");
  663. }
  664. buf[4095] = L'\0';
  665. vArray[spot].vt = VT_BSTR;
  666. vArray[spot].bstrVal = ALLOC_AND_GIVEAWAY_BSTR_LEN(buf, bufSize);
  667. spot++;
  668. if(bSetConsent)
  669. {
  670. if (m_pRegistryConfig->getProfilePath())
  671. path = m_pRegistryConfig->getProfilePath();
  672. else
  673. path = L"/";
  674. domain = m_pRegistryConfig->getProfileDomain();
  675. if (domain.length())
  676. {
  677. bufSize = _snwprintf(buf, 4096,
  678. L"Set-Cookie: MSPConsent=%s; path=%s; domain=%s; %s\r\n",
  679. bSetConsent ? (LPWSTR)bstrConsent : L"", (LPWSTR)path, (LPWSTR)domain,
  680. bSetConsent ? (persist ? W_COOKIE_EXPIRES(EXPIRE_FUTURE) : L"")
  681. : W_COOKIE_EXPIRES(EXPIRE_PAST));
  682. }
  683. else
  684. {
  685. bufSize = _snwprintf(buf, 4096,
  686. L"Set-Cookie: MSPConsent=%s; path=%s; %s\r\n",
  687. bSetConsent ? (LPWSTR)bstrConsent : L"", (LPWSTR)path,
  688. bSetConsent ? (persist ? W_COOKIE_EXPIRES(EXPIRE_FUTURE) : L"")
  689. : W_COOKIE_EXPIRES(EXPIRE_PAST));
  690. }
  691. buf[4095] = L'\0';
  692. vArray[spot].vt = VT_BSTR;
  693. vArray[spot].bstrVal = ALLOC_AND_GIVEAWAY_BSTR_LEN(buf, bufSize);
  694. spot++;
  695. }
  696. SafeArrayUnaccessData(sa);
  697. }
  698. }
  699. // Now, check the cookies
  700. if (!m_fromQueryString)
  701. {
  702. hasSec = GetBstrArg(mspsec, &bstrSec);
  703. if(hasSec == CV_DEFAULT || hasSec == CV_BAD)
  704. bstrSec = NULL;
  705. handleCookieData(mspauth, mspprof, mspconsent, bstrSec);
  706. if(hasSec == CV_FREE)
  707. SysFreeString(bstrSec);
  708. }
  709. hr = S_OK;
  710. Cleanup:
  711. if (bstrNewAuth)
  712. {
  713. SysFreeString(bstrNewAuth);
  714. }
  715. if (bstrNewSecAuth)
  716. {
  717. SysFreeString(bstrNewSecAuth);
  718. }
  719. if (bstrConsent)
  720. {
  721. SysFreeString(bstrConsent);
  722. }
  723. PassportLog("CManager::OnStartPageManual Exit:\r\n");
  724. return hr;
  725. }
  726. //===========================================================================
  727. //
  728. // OnStartPageECB -- Authenticate with ECB -- for ISAPI extensions
  729. //
  730. STDMETHODIMP CManager::OnStartPageECB(
  731. LPBYTE pvECB,
  732. DWORD* bufSize,
  733. LPSTR pCookieHeader
  734. )
  735. {
  736. if (!pvECB) return E_INVALIDARG;
  737. EXTENSION_CONTROL_BLOCK* pECB = (EXTENSION_CONTROL_BLOCK*) pvECB;
  738. HRESULT hr = S_OK;
  739. PPTraceFunc<HRESULT> func(PPTRACE_FUNC, hr,
  740. "OnStartPageECB",
  741. " <<< %lx, %lx, %d, %lx", pvECB, bufSize, *bufSize, pCookieHeader);
  742. ATL::CAutoVectorPtr<CHAR> spHTTPS;
  743. ATL::CAutoVectorPtr<CHAR> spheaders;
  744. spheaders.Attach(GetServerVariableECB(pECB, "ALL_RAW"));
  745. spHTTPS.Attach(GetServerVariableECB(pECB, "HTTPS"));
  746. DWORD flags = 0;
  747. if((CHAR*)spHTTPS && lstrcmpiA("on", (CHAR*)spHTTPS) == 0)
  748. flags |= PASSPORT_HEADER_FLAGS_HTTPS;
  749. hr = OnStartPageHTTPRawEx(pECB->lpszMethod,
  750. pECB->lpszPathInfo,
  751. pECB->lpszQueryString,
  752. NULL, // version
  753. (CHAR*)spheaders,
  754. flags, bufSize,
  755. pCookieHeader);
  756. m_pECB = pECB;
  757. return hr;
  758. }
  759. //===========================================================================
  760. //
  761. // OnStartPageHTTPRaw -- Authenticate with HTTP request-line and headers
  762. // returns response headers as output parameters
  763. //
  764. STDMETHODIMP CManager::OnStartPageHTTPRaw(
  765. /* [string][in] */ LPCSTR request_line,
  766. /* [string][in] */ LPCSTR headers,
  767. /* [in] */ DWORD flags,
  768. /* [out][in] */ DWORD *bufSize,
  769. /* [size_is][out] */ LPSTR pCookieHeader)
  770. {
  771. // an old client, let's try the QS
  772. DWORD dwSize;
  773. HRESULT hr = S_OK;
  774. PPTraceFunc<HRESULT> func(PPTRACE_FUNC, hr,
  775. "OnStartPageHTTPRaw",
  776. " <<< %s, %s, %lx, %lx, %d, %lx", request_line, headers, flags, bufSize, *bufSize, pCookieHeader);
  777. LPCSTR pBuffer = GetRawQueryString(request_line, &dwSize);
  778. if (pBuffer)
  779. {
  780. TempSubStr tss(pBuffer, dwSize);
  781. hr = OnStartPageHTTPRawEx(NULL, NULL, pBuffer, NULL, headers, flags, bufSize, pCookieHeader);
  782. }
  783. else
  784. hr = OnStartPageHTTPRawEx(NULL, NULL, NULL, NULL, headers, flags, bufSize, pCookieHeader);
  785. return hr;
  786. }
  787. //===========================================================================
  788. //
  789. // @func OnStartPageHTTPRawEx -- Authenticate with HTTP request-line and headers
  790. // returns response headers as output parameters. If *bufsize is not smaller
  791. // the required length or pCookieHeader is NULL, the required length is returned
  792. // in bufsize. In this case, an empty string is written into pCookieHeader if
  793. // it is not NULL.
  794. // method, path, HTTPVer are not being used in this version of the API
  795. //
  796. // @rdesc returns one of these values
  797. // @flag E_POINTER | NULL bufSize
  798. // @flag E_POINTER | not writable buffer given by pCookieHeader
  799. // @flag PP_E_NOT_CONFIGURED | not valid state to call this method
  800. // @flag S_OK
  801. //
  802. STDMETHODIMP CManager::OnStartPageHTTPRawEx(
  803. /* [string][in] */ LPCSTR method,
  804. /* [string][in] */ LPCSTR path,
  805. /* [string][in] */ LPCSTR QS,
  806. /* [string][in] */ LPCSTR HTTPVer,
  807. /* [string][in] */ LPCSTR headers,
  808. /* [in] */ DWORD flags,
  809. /* [out][in] */ DWORD *bufSize, //@parm retuns the length of the headers. Could be 0 to ask for the req. len.
  810. /* [size_is][out]*/ LPSTR pCookieHeader) //@parm buffer to hold the headers. Could be NULL to ask for the req. len
  811. {
  812. USES_CONVERSION;
  813. if(bufSize == NULL)
  814. return E_POINTER;
  815. HRESULT hr = S_OK;
  816. PPTraceFunc<HRESULT> func(PPTRACE_FUNC, hr,
  817. "OnStartPageHTTPRawEx",
  818. " <<< %s, %s, %s, %s, %s, %lx, %lx, %d, %lx", method, path, QS, HTTPVer, headers, flags, bufSize, *bufSize, pCookieHeader);
  819. PassportLog("CManager::OnStartPageHTTPRawEx Enter:\r\n");
  820. //
  821. // 12002: if *bufSize is 0, we will not be writing into pCookieHeader
  822. //
  823. if(*bufSize == 0)
  824. pCookieHeader = NULL;
  825. if(pCookieHeader && IsBadWritePtr(pCookieHeader, *bufSize))
  826. return E_POINTER;
  827. if (!g_config || !g_config->isValid()) // Guarantees config is non-null
  828. {
  829. AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
  830. IID_IPassportManager, PP_E_NOT_CONFIGURED);
  831. return PP_E_NOT_CONFIGURED;
  832. }
  833. if (!m_piTicket || !m_piProfile)
  834. {
  835. return E_OUTOFMEMORY;
  836. }
  837. wipeState();
  838. DWORD dwSize;
  839. LPCSTR pBuffer;
  840. // used to convert to wide ...
  841. WCHAR *pwszBuf = NULL;
  842. enum {
  843. header_Host,
  844. header_Accept_Auth,
  845. header_Authorization,
  846. header_Cookie,
  847. header_total
  848. };
  849. LPCSTR headerNames[header_total] = { "Host", "Accept-Auth", "Authorization", "Cookie"};
  850. DWORD headerSizes[header_total];
  851. LPCSTR headerValues[header_total] = {0};
  852. GetRawHeaders(headers, headerNames, headerValues, headerSizes, header_total);
  853. //
  854. // Use the header to get the server name being requested
  855. // so we can get the correct registry config. But only do this
  856. // if we have some configured sites.
  857. //
  858. if(m_pRegistryConfig)
  859. m_pRegistryConfig->Release();
  860. pBuffer = headerValues[header_Host];
  861. if(g_config->HasSites() && pBuffer)
  862. {
  863. TempSubStr tss(pBuffer, headerSizes[header_Host]);
  864. TempSubStr tssRemovePort;
  865. LPSTR pPort = strstr(pBuffer, ":");
  866. if(pPort)
  867. {
  868. ++pPort;
  869. DWORD dwPort = atoi(pPort);
  870. if(dwPort == 80 || dwPort == 443)
  871. {
  872. tssRemovePort.Set(pBuffer, pPort - pBuffer - 1);
  873. }
  874. }
  875. // for port 80 and 443, this should be removed
  876. PPTracePrint(PPTRACE_RAW, "SiteName %s", PPF_CHAR(pBuffer));
  877. m_pRegistryConfig = g_config->checkoutRegistryConfig((LPSTR)pBuffer);
  878. }
  879. else
  880. {
  881. PPTracePrint(PPTRACE_RAW, "Default Site");
  882. m_pRegistryConfig = g_config->checkoutRegistryConfig(NULL);
  883. }
  884. if (pCookieHeader)
  885. *pCookieHeader = '\0';
  886. //
  887. // If we have a secure ticket/profile and the url is SSL,
  888. // then tack on the MSPPuid cookie.
  889. //
  890. if(PASSPORT_HEADER_FLAGS_HTTPS & flags)
  891. m_bSecureTransported = true;
  892. else
  893. m_bSecureTransported = false;
  894. PPTracePrint(PPTRACE_RAW, "HTTPS:%d", m_bSecureTransported);
  895. // see if client understands passport
  896. pBuffer = headerValues[header_Accept_Auth];
  897. if (pBuffer)
  898. {
  899. TempSubStr tss(pBuffer, headerSizes[header_Accept_Auth]);
  900. if (strstr(pBuffer, PASSPORT_PROT14_A))
  901. {
  902. m_bIsTweenerCapable = TRUE;
  903. PPTracePrint(PPTRACE_RAW, "PASSPORT_PROT14 capable");
  904. }
  905. }
  906. BSTR ret = NULL;
  907. CCoCrypt* crypt = NULL;
  908. BOOL fParseSuccess = FALSE;
  909. pBuffer = headerValues[header_Authorization];
  910. PWSTR pwszTicket = NULL, pwszProfile = NULL, pwszF = NULL;
  911. // use these when t&p come from qs
  912. BSTR QSAuth = NULL, QSProf = NULL, QSErrflag = NULL;
  913. BSTR bstrConsent = NULL;
  914. BSTR bstrNewAuth = NULL;
  915. BSTR bstrNewSecAuth = NULL;
  916. if (pBuffer)
  917. {
  918. TempSubStr tss(pBuffer, headerSizes[header_Authorization]);
  919. // has passport auth header
  920. if(strstr(pBuffer, PASSPORT_PROT14_A))
  921. {
  922. // convert to wide ...
  923. int cch = MultiByteToWideChar(GetACP(), 0, pBuffer, -1, NULL, NULL);
  924. pwszBuf = (WCHAR*)LocalAlloc(LMEM_FIXED, (cch + 1) * sizeof (WCHAR));
  925. if (NULL != pwszBuf)
  926. {
  927. if (0 != MultiByteToWideChar(GetACP(), 0, pBuffer, -1, pwszBuf, cch))
  928. {
  929. BSTR bstrT = NULL;
  930. BSTR bstrP = NULL;
  931. GetTicketAndProfileFromHeader(pwszBuf, pwszTicket, pwszProfile, pwszF);
  932. // due to the fact that handleQueryStringData wants BSTRs we can't use
  933. // the direct pointers we just got, so we have to make copies.
  934. if( pwszTicket == NULL )
  935. {
  936. bstrT = NULL;
  937. }
  938. else
  939. {
  940. bstrT = SysAllocString(pwszTicket);
  941. if (NULL == bstrT)
  942. {
  943. hr = E_OUTOFMEMORY;
  944. goto Cleanup;
  945. }
  946. }
  947. if( pwszProfile == NULL )
  948. {
  949. bstrP = NULL;
  950. }
  951. else
  952. {
  953. bstrP = SysAllocString(pwszProfile);
  954. if (NULL == bstrP)
  955. {
  956. SysFreeString(bstrT);
  957. hr = E_OUTOFMEMORY;
  958. goto Cleanup;
  959. }
  960. }
  961. // make ticket and profile BSTRs
  962. PPTracePrint(PPTRACE_RAW,
  963. "PASSPORT_PROT14 Authorization <<< header:%ws, t:%ws, p:%ws, f:%ws",
  964. pwszBuf, pwszTicket, pwszProfile, pwszF);
  965. fParseSuccess = handleQueryStringData(bstrT, bstrP);
  966. if (pwszF)
  967. m_lNetworkError = _wtol(pwszF);
  968. SysFreeString(bstrT);
  969. SysFreeString(bstrP);
  970. }
  971. }
  972. }
  973. else
  974. {
  975. // not our header. BUGBUG could there be multiple headers ???
  976. pBuffer = NULL;
  977. }
  978. }
  979. if (!pBuffer)
  980. {
  981. // an old client, let's try the QS
  982. if (QS)
  983. {
  984. // get ticket and profile ...
  985. // BUGBUG This could be optimized to avoid wide/short conversions, but later...
  986. GetQueryData(QS, &QSAuth, &QSProf, &QSErrflag);
  987. fParseSuccess = handleQueryStringData(QSAuth,QSProf);
  988. if(QSErrflag != NULL)
  989. m_lNetworkError = _wtol(QSErrflag);
  990. PPTracePrint(PPTRACE_RAW,
  991. "QueryString <<< t:%ws, p:%ws, f:%ws",
  992. QSAuth, QSProf, QSErrflag);
  993. }
  994. }
  995. if (fParseSuccess)
  996. {
  997. //
  998. // If we got secure ticket or profile, then
  999. // we need to re-encrypt the insecure version
  1000. // before setting the cookie headers.
  1001. //
  1002. PPTracePrint(PPTRACE_RAW, "Authenticated");
  1003. // Set the cookies
  1004. LPSTR ticketDomain = m_pRegistryConfig->getTicketDomain();
  1005. LPSTR profileDomain = m_pRegistryConfig->getProfileDomain();
  1006. LPSTR secureDomain = m_pRegistryConfig->getSecureDomain();
  1007. LPSTR ticketPath = m_pRegistryConfig->getTicketPath();
  1008. LPSTR profilePath = m_pRegistryConfig->getProfilePath();
  1009. LPSTR securePath = m_pRegistryConfig->getSecurePath();
  1010. VARIANT_BOOL persist;
  1011. m_piTicket->get_HasSavedPassword(&persist);
  1012. // MSPConsent cookie
  1013. BOOL bSetConsent = (S_OK == IfConsentCookie(&bstrConsent));
  1014. // Build the cookie headers.
  1015. // the authentication cookies
  1016. BSTR auth, secAuth; // do not call SysFreeString on them, they are skin level copy
  1017. if (S_OK == IfAlterAuthCookie(&bstrNewAuth, &bstrNewSecAuth))
  1018. {
  1019. auth = bstrNewAuth;
  1020. secAuth = bstrNewSecAuth;
  1021. }
  1022. else
  1023. {
  1024. if (pwszTicket)
  1025. {
  1026. auth = pwszTicket;
  1027. }
  1028. else
  1029. {
  1030. auth = QSAuth;
  1031. }
  1032. secAuth = NULL;
  1033. }
  1034. // build cookies for output
  1035. BuildCookieHeaders(W2A(auth),
  1036. (pwszProfile ? W2A(pwszProfile) : (QSProf ? W2A(QSProf) : NULL)),
  1037. (bSetConsent ? W2A(bstrConsent) : NULL),
  1038. (secAuth ? W2A(secAuth) : NULL),
  1039. ticketDomain,
  1040. ticketPath,
  1041. profileDomain,
  1042. profilePath,
  1043. secureDomain,
  1044. securePath,
  1045. persist,
  1046. pCookieHeader,
  1047. bufSize,
  1048. !m_pRegistryConfig->getNotUseHTTPOnly());
  1049. PPTracePrint(PPTRACE_RAW,
  1050. "Cookie headers >>> %s",PPF_CHAR(pCookieHeader));
  1051. }
  1052. if (QSAuth) FREE_BSTR(QSAuth);
  1053. if (QSProf) FREE_BSTR(QSProf);
  1054. if (QSErrflag) FREE_BSTR(QSErrflag);
  1055. if (bstrNewAuth)
  1056. {
  1057. SysFreeString(bstrNewAuth);
  1058. }
  1059. if (bstrNewSecAuth)
  1060. {
  1061. SysFreeString(bstrNewSecAuth);
  1062. }
  1063. if (bstrConsent)
  1064. {
  1065. SysFreeString(bstrConsent);
  1066. }
  1067. // Now, check the cookies
  1068. if (!m_fromQueryString)
  1069. {
  1070. BSTR CookieAuth = NULL, CookieProf = NULL, CookieConsent = NULL, CookieSecure = NULL;
  1071. pBuffer = headerValues[header_Cookie];
  1072. if(pBuffer)
  1073. {
  1074. TempSubStr tss(pBuffer, headerSizes[header_Cookie]);
  1075. GetCookie(pBuffer, "MSPAuth", &CookieAuth); // GetCookie has URLDecode in it
  1076. GetCookie(pBuffer, "MSPProf", &CookieProf);
  1077. GetCookie(pBuffer, "MSPConsent", &CookieConsent);
  1078. GetCookie(pBuffer, "MSPSecAuth", &CookieSecure);
  1079. handleCookieData(CookieAuth,CookieProf,CookieConsent,CookieSecure);
  1080. PPTracePrint(PPTRACE_RAW,
  1081. "Cookies <<< t:%ws, p:%ws, c:%ws, s:%ws",
  1082. CookieAuth, CookieProf, CookieConsent, CookieSecure);
  1083. if (CookieAuth) FREE_BSTR(CookieAuth);
  1084. if (CookieProf) FREE_BSTR(CookieProf);
  1085. if (CookieConsent) FREE_BSTR(CookieConsent);
  1086. if (CookieSecure) FREE_BSTR(CookieSecure);
  1087. }
  1088. // we are not returning cookie info back
  1089. if (pCookieHeader)
  1090. *pCookieHeader = 0;
  1091. *bufSize = 0;
  1092. }
  1093. PassportLog("CManager::OnStartPageHTTPRawEx Exit:\r\n");
  1094. hr = S_OK;
  1095. Cleanup:
  1096. if (NULL != pwszBuf)
  1097. {
  1098. // free the memory since we no longer need it
  1099. LocalFree(pwszBuf);
  1100. }
  1101. return hr;
  1102. }
  1103. //===========================================================================
  1104. //
  1105. // ContinueStartPageBody
  1106. // -- when OnStartPageHTTPRaw returns PP_E_HTTP_BODY_REQUIRED, this func is expected to call
  1107. // not doing anything for 2.0 release
  1108. STDMETHODIMP CManager::ContinueStartPageHTTPRaw(
  1109. /* [in] */ DWORD bodyLen,
  1110. /* [size_is][in] */ byte *body,
  1111. /* [out][in] */ DWORD *pBufSize,
  1112. /* [size_is][out] */ LPSTR pRespHeaders,
  1113. /* [out][in] */ DWORD *pRespBodyLen,
  1114. /* [size_is][out] */ byte *pRespBody)
  1115. {
  1116. return E_NOTIMPL;
  1117. }
  1118. //===========================================================================
  1119. //
  1120. // OnStartPageFilter -- for ISAPI filters
  1121. //
  1122. STDMETHODIMP CManager::OnStartPageFilter(
  1123. LPBYTE pvPFC,
  1124. DWORD* bufSize,
  1125. LPSTR pCookieHeader
  1126. )
  1127. {
  1128. if (!pvPFC) return E_INVALIDARG;
  1129. PHTTP_FILTER_CONTEXT pfc = (PHTTP_FILTER_CONTEXT) pvPFC;
  1130. HRESULT hr = S_OK;
  1131. PPTraceFunc<HRESULT> func(PPTRACE_FUNC, hr,
  1132. "OnStartPageFilter",
  1133. " <<< %lx, %lx, %d, %lx", pvPFC, bufSize, *bufSize, pCookieHeader);
  1134. ATL::CAutoVectorPtr<CHAR> spheaders;
  1135. ATL::CAutoVectorPtr<CHAR> spHTTPS;
  1136. ATL::CAutoVectorPtr<CHAR> spQS;
  1137. spheaders.Attach(GetServerVariablePFC(pfc, "ALL_RAW"));
  1138. spHTTPS.Attach(GetServerVariablePFC(pfc, "HTTPS"));
  1139. spQS.Attach(GetServerVariablePFC(pfc, "QUERY_STRING"));
  1140. DWORD flags = 0;
  1141. if((CHAR*)spHTTPS && lstrcmpiA("on", (CHAR*)spHTTPS) == 0)
  1142. flags |= PASSPORT_HEADER_FLAGS_HTTPS;
  1143. hr = OnStartPageHTTPRawEx(NULL, NULL, (CHAR*)spQS, NULL, (CHAR*)spheaders, flags, bufSize, pCookieHeader);
  1144. m_pFC = pfc;
  1145. return hr;
  1146. }
  1147. //===========================================================================
  1148. //
  1149. // OnEndPage
  1150. //
  1151. STDMETHODIMP CManager::OnEndPage ()
  1152. {
  1153. PassportLog("CManager::OnEndPage Enter:\r\n");
  1154. if (m_bOnStartPageCalled)
  1155. {
  1156. m_bOnStartPageCalled = false;
  1157. // Release all interfaces
  1158. m_piRequest.Release();
  1159. m_piResponse.Release();
  1160. }
  1161. if (!m_piTicket || !m_piProfile)
  1162. {
  1163. return E_OUTOFMEMORY;
  1164. }
  1165. // Just in case...
  1166. m_piTicket->put_unencryptedTicket(NULL);
  1167. m_piProfile->put_unencryptedProfile(NULL);
  1168. m_profileValid = m_ticketValid = VARIANT_FALSE;
  1169. m_fromQueryString = false;
  1170. if(m_pRegistryConfig)
  1171. {
  1172. m_pRegistryConfig->Release();
  1173. m_pRegistryConfig = NULL;
  1174. }
  1175. PassportLog("CManager::OnEndPage Exit:\r\n");
  1176. return S_OK;
  1177. }
  1178. //===========================================================================
  1179. //
  1180. // AuthURL
  1181. //
  1182. //
  1183. // Old API. Auth URL is pointing to the login server
  1184. //
  1185. STDMETHODIMP
  1186. CManager::AuthURL(
  1187. VARIANT vRU,
  1188. VARIANT vTimeWindow,
  1189. VARIANT vForceLogin,
  1190. VARIANT vCoBrand,
  1191. VARIANT vLCID,
  1192. VARIANT vNameSpace,
  1193. VARIANT vKPP,
  1194. VARIANT vSecureLevel,
  1195. BSTR *pAuthUrl)
  1196. {
  1197. CComVariant vEmpty(_T(""));
  1198. return CommonAuthURL(vRU, vTimeWindow, vForceLogin,
  1199. vCoBrand, vLCID, vNameSpace,
  1200. vKPP, vSecureLevel,
  1201. FALSE, vEmpty, pAuthUrl);
  1202. }
  1203. //===========================================================================
  1204. //
  1205. // AuthURL2
  1206. //
  1207. //
  1208. // new API. return URL is to the login server
  1209. //
  1210. STDMETHODIMP
  1211. CManager::AuthURL2(
  1212. VARIANT vRU,
  1213. VARIANT vTimeWindow,
  1214. VARIANT vForceLogin,
  1215. VARIANT vCoBrand,
  1216. VARIANT vLCID,
  1217. VARIANT vNameSpace,
  1218. VARIANT vKPP,
  1219. VARIANT vSecureLevel,
  1220. BSTR *pAuthUrl)
  1221. {
  1222. CComVariant vEmpty(_T(""));
  1223. return CommonAuthURL(vRU, vTimeWindow, vForceLogin,
  1224. vCoBrand, vLCID, vNameSpace,
  1225. vKPP, vSecureLevel,
  1226. TRUE, vEmpty, pAuthUrl);
  1227. }
  1228. //===========================================================================
  1229. //
  1230. // CommonAuthURL
  1231. //
  1232. //
  1233. // AuthURL implementation
  1234. //
  1235. STDMETHODIMP
  1236. CManager::CommonAuthURL(
  1237. VARIANT vRU,
  1238. VARIANT vTimeWindow,
  1239. VARIANT vForceLogin,
  1240. VARIANT vCoBrand,
  1241. VARIANT vLCID,
  1242. VARIANT vNameSpace,
  1243. VARIANT vKPP,
  1244. VARIANT vSecureLevel,
  1245. BOOL fRedirToSelf,
  1246. VARIANT vFunctionArea, // BSTR: e.g. Wireless
  1247. BSTR *pAuthUrl)
  1248. {
  1249. USES_CONVERSION;
  1250. time_t ct;
  1251. WCHAR url[MAX_URL_LENGTH] = L"";
  1252. VARIANT freeMe;
  1253. UINT TimeWindow;
  1254. int nKPP;
  1255. VARIANT_BOOL ForceLogin = VARIANT_FALSE;
  1256. ULONG ulSecureLevel = 0;
  1257. BSTR CBT = NULL, returnUrl = NULL, bstrNameSpace = NULL;
  1258. int hasCB, hasRU, hasLCID, hasTW, hasFL, hasNameSpace, hasKPP, hasUseSec;
  1259. USHORT Lang;
  1260. HRESULT hr = S_OK;
  1261. BSTR bstrFunctionArea = NULL;
  1262. int hasFunctionArea;
  1263. CNexusConfig* cnc = NULL;
  1264. PassportLog("CManager::CommonAuthURL Enter:\r\n");
  1265. if (!g_config) // Guarantees config is non-null
  1266. {
  1267. AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
  1268. IID_IPassportManager, PP_E_NOT_CONFIGURED);
  1269. return PP_E_NOT_CONFIGURED;
  1270. }
  1271. if (!m_pRegistryConfig)
  1272. m_pRegistryConfig = g_config->checkoutRegistryConfig();
  1273. if (!g_config->isValid() || !m_pRegistryConfig) // Guarantees config is non-null
  1274. {
  1275. AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
  1276. IID_IPassportManager, PP_E_NOT_CONFIGURED);
  1277. return PP_E_NOT_CONFIGURED;
  1278. }
  1279. // Make sure args are of the right type
  1280. if ((hasTW = GetIntArg(vTimeWindow, (int*) &TimeWindow)) == CV_BAD)
  1281. return E_INVALIDARG;
  1282. if ((hasFL = GetBoolArg(vForceLogin, &ForceLogin)) == CV_BAD)
  1283. return E_INVALIDARG;
  1284. if ((hasUseSec = GetIntArg(vSecureLevel, (int*)&ulSecureLevel)) == CV_BAD)
  1285. return E_INVALIDARG;
  1286. if ((hasLCID = GetShortArg(vLCID,&Lang)) == CV_BAD)
  1287. return E_INVALIDARG;
  1288. if ((hasKPP = GetIntArg(vKPP, &nKPP)) == CV_BAD)
  1289. return E_INVALIDARG;
  1290. hasCB = GetBstrArg(vCoBrand, &CBT);
  1291. if (hasCB == CV_BAD)
  1292. return E_INVALIDARG;
  1293. if (hasCB == CV_FREE)
  1294. {
  1295. TAKEOVER_BSTR(CBT);
  1296. }
  1297. hasRU = GetBstrArg(vRU, &returnUrl);
  1298. if (hasRU == CV_BAD)
  1299. {
  1300. if (hasCB == CV_FREE && CBT)
  1301. FREE_BSTR(CBT);
  1302. return E_INVALIDARG;
  1303. }
  1304. if (hasRU == CV_FREE)
  1305. {
  1306. TAKEOVER_BSTR(returnUrl);
  1307. }
  1308. hasNameSpace = GetBstrArg(vNameSpace, &bstrNameSpace);
  1309. if (hasNameSpace == CV_BAD)
  1310. {
  1311. if (hasCB == CV_FREE && CBT)
  1312. SysFreeString(CBT);
  1313. if (hasRU == CV_FREE && returnUrl)
  1314. SysFreeString(returnUrl);
  1315. return E_INVALIDARG;
  1316. }
  1317. if (hasNameSpace == CV_FREE)
  1318. {
  1319. TAKEOVER_BSTR(bstrNameSpace);
  1320. }
  1321. if (hasNameSpace == CV_DEFAULT)
  1322. {
  1323. bstrNameSpace = m_pRegistryConfig->getNameSpace();
  1324. }
  1325. // **************************************************
  1326. // Logging
  1327. if (NULL != returnUrl)
  1328. {
  1329. PassportLog(" RU = %ws\n", returnUrl);
  1330. }
  1331. PassportLog(" TW = %X, SL = %X, L = %d, KPP = %X\r\n", TimeWindow, ulSecureLevel, Lang, nKPP);
  1332. if (NULL != bstrNameSpace)
  1333. {
  1334. PassportLog(" NS = %ws\r\n", bstrNameSpace);
  1335. }
  1336. if (NULL != CBT)
  1337. {
  1338. PassportLog(" CBT = %ws\r\n", CBT);
  1339. }
  1340. // **************************************************
  1341. hasFunctionArea = GetBstrArg(vFunctionArea, &bstrFunctionArea);
  1342. if (hasFunctionArea == CV_FREE)
  1343. {
  1344. TAKEOVER_BSTR(bstrFunctionArea);
  1345. }
  1346. if(hasUseSec == CV_DEFAULT)
  1347. ulSecureLevel = m_pRegistryConfig->getSecureLevel();
  1348. WCHAR *szAUAttrName;
  1349. if (SECURELEVEL_USE_HTTPS(ulSecureLevel))
  1350. szAUAttrName = L"AuthSecure";
  1351. else
  1352. szAUAttrName = L"Auth";
  1353. BSTR szAttrName_FuncArea = NULL;
  1354. if (bstrFunctionArea != NULL)
  1355. {
  1356. szAttrName_FuncArea = SysAllocStringLen(NULL, wcslen(bstrFunctionArea) + wcslen(szAUAttrName));
  1357. if (NULL == szAttrName_FuncArea)
  1358. {
  1359. hr = E_OUTOFMEMORY;
  1360. goto Cleanup;
  1361. }
  1362. wcscpy(szAttrName_FuncArea, bstrFunctionArea);
  1363. wcscat(szAttrName_FuncArea, szAUAttrName);
  1364. }
  1365. cnc = g_config->checkoutNexusConfig();
  1366. if (hasLCID == CV_DEFAULT)
  1367. Lang = m_pRegistryConfig->getDefaultLCID();
  1368. if (hasKPP == CV_DEFAULT)
  1369. nKPP = m_pRegistryConfig->getKPP();
  1370. VariantInit(&freeMe);
  1371. if (!m_pRegistryConfig->DisasterModeP())
  1372. {
  1373. // If I'm authenticated, get my domain specific url
  1374. if (m_ticketValid && m_profileValid)
  1375. {
  1376. HRESULT hr = m_piProfile->get_ByIndex(MEMBERNAME_INDEX, &freeMe);
  1377. if (hr != S_OK || freeMe.vt != VT_BSTR)
  1378. {
  1379. if (bstrFunctionArea)
  1380. {
  1381. cnc->getDomainAttribute(L"Default",
  1382. szAttrName_FuncArea,
  1383. sizeof(url) / sizeof(WCHAR),
  1384. url,
  1385. Lang);
  1386. }
  1387. if (*url == 0) // nothing is in URL string
  1388. {
  1389. cnc->getDomainAttribute(L"Default",
  1390. szAUAttrName,
  1391. sizeof(url) / sizeof(WCHAR),
  1392. url,
  1393. Lang);
  1394. }
  1395. }
  1396. else
  1397. {
  1398. LPCWSTR psz = wcsrchr(freeMe.bstrVal, L'@');
  1399. if (bstrFunctionArea)
  1400. {
  1401. cnc->getDomainAttribute(psz ? psz+1 : L"Default",
  1402. szAttrName_FuncArea,
  1403. sizeof(url) / sizeof(WCHAR),
  1404. url,
  1405. Lang);
  1406. }
  1407. if (*url == 0) // nothing is in URL string
  1408. {
  1409. cnc->getDomainAttribute(psz ? psz+1 : L"Default",
  1410. szAUAttrName,
  1411. sizeof(url) / sizeof(WCHAR),
  1412. url,
  1413. Lang);
  1414. }
  1415. }
  1416. }
  1417. else
  1418. {
  1419. if (bstrFunctionArea)
  1420. {
  1421. cnc->getDomainAttribute(L"Default",
  1422. szAttrName_FuncArea,
  1423. sizeof(url) / sizeof(WCHAR),
  1424. url,
  1425. Lang);
  1426. }
  1427. }
  1428. if(*url == 0) // nothing in URL string
  1429. {
  1430. cnc->getDomainAttribute(L"Default",
  1431. szAUAttrName,
  1432. sizeof(url) / sizeof(WCHAR),
  1433. url,
  1434. Lang);
  1435. }
  1436. }
  1437. else
  1438. lstrcpynW(url, m_pRegistryConfig->getDisasterUrl(), sizeof(url) / sizeof(WCHAR));
  1439. time(&ct);
  1440. if (*url == L'\0')
  1441. {
  1442. hr = S_OK;
  1443. goto Cleanup;
  1444. }
  1445. if (hasTW == CV_DEFAULT)
  1446. TimeWindow = m_pRegistryConfig->getDefaultTicketAge();
  1447. if (hasFL == CV_DEFAULT)
  1448. ForceLogin = m_pRegistryConfig->forceLoginP() ? VARIANT_TRUE : VARIANT_FALSE;
  1449. if (hasCB == CV_DEFAULT)
  1450. CBT = m_pRegistryConfig->getDefaultCoBrand();
  1451. if (hasRU == CV_DEFAULT)
  1452. returnUrl = m_pRegistryConfig->getDefaultRU();
  1453. if (returnUrl == NULL)
  1454. returnUrl = L"";
  1455. if(ulSecureLevel == VARIANT_TRUE) // special case for backward compatible
  1456. ulSecureLevel = k_iSeclevelSecureChannel;
  1457. if ((TimeWindow != 0 && TimeWindow < PPM_TIMEWINDOW_MIN) || TimeWindow > PPM_TIMEWINDOW_MAX)
  1458. {
  1459. WCHAR buf[20];
  1460. _itow(TimeWindow,buf,10);
  1461. AtlReportError(CLSID_Manager, (LPCOLESTR) PP_E_INVALID_TIMEWINDOWSTR,
  1462. IID_IPassportManager, PP_E_INVALID_TIMEWINDOW);
  1463. hr = PP_E_INVALID_TIMEWINDOW;
  1464. goto Cleanup;
  1465. }
  1466. if (NULL == pAuthUrl)
  1467. {
  1468. hr = E_INVALIDARG;
  1469. goto Cleanup;
  1470. }
  1471. *pAuthUrl = FormatAuthURL(
  1472. url,
  1473. m_pRegistryConfig->getSiteId(),
  1474. returnUrl,
  1475. TimeWindow,
  1476. ForceLogin,
  1477. m_pRegistryConfig->getCurrentCryptVersion(),
  1478. ct,
  1479. CBT,
  1480. bstrNameSpace,
  1481. nKPP,
  1482. Lang,
  1483. ulSecureLevel,
  1484. m_pRegistryConfig,
  1485. fRedirToSelf,
  1486. IfCreateTPF()
  1487. );
  1488. if (NULL == *pAuthUrl)
  1489. {
  1490. hr = E_OUTOFMEMORY;
  1491. goto Cleanup;
  1492. }
  1493. hr = S_OK;
  1494. Cleanup:
  1495. if (szAttrName_FuncArea)
  1496. {
  1497. SysFreeString(szAttrName_FuncArea);
  1498. }
  1499. if (NULL != cnc)
  1500. {
  1501. cnc->Release();
  1502. }
  1503. if (hasFunctionArea== CV_FREE && bstrFunctionArea)
  1504. FREE_BSTR(bstrFunctionArea);
  1505. if (hasRU == CV_FREE && returnUrl)
  1506. FREE_BSTR(returnUrl);
  1507. if (hasCB == CV_FREE && CBT)
  1508. FREE_BSTR(CBT);
  1509. // !!! need to confirmation
  1510. if (hasNameSpace == CV_FREE && bstrNameSpace)
  1511. FREE_BSTR(bstrNameSpace);
  1512. VariantClear(&freeMe);
  1513. PassportLog("CManager::CommonAuthURL Exit: %X\r\n", hr);
  1514. return hr;
  1515. }
  1516. //===========================================================================
  1517. //
  1518. // GetLoginChallenge
  1519. // return AuthURL,
  1520. // output parameter: tweener authHeader
  1521. //
  1522. // get AuthURL and AuthHeaders
  1523. //
  1524. STDMETHODIMP CManager::GetLoginChallenge(VARIANT vReturnUrl,
  1525. VARIANT vTimeWindow,
  1526. VARIANT vForceLogin,
  1527. VARIANT vCoBrandTemplate,
  1528. VARIANT vLCID,
  1529. VARIANT vNameSpace,
  1530. VARIANT vKPP,
  1531. VARIANT vSecureLevel,
  1532. VARIANT vExtraParams,
  1533. BSTR* pAuthHeader
  1534. )
  1535. {
  1536. if (!pAuthHeader) return E_INVALIDARG;
  1537. VARIANT vHeader;
  1538. VariantInit(&vHeader);
  1539. HRESULT hr = GetLoginChallengeInternal(
  1540. vReturnUrl,
  1541. vTimeWindow,
  1542. vForceLogin,
  1543. vCoBrandTemplate,
  1544. vLCID,
  1545. vNameSpace,
  1546. vKPP,
  1547. vSecureLevel,
  1548. vExtraParams,
  1549. &vHeader,
  1550. NULL);
  1551. if(S_OK == hr && V_VT(&vHeader) == VT_BSTR && V_BSTR(&vHeader))
  1552. {
  1553. *pAuthHeader = V_BSTR(&vHeader);
  1554. VariantInit(&vHeader);
  1555. }
  1556. else
  1557. VariantClear(&vHeader);
  1558. return hr;
  1559. }
  1560. //===========================================================================
  1561. //
  1562. // GetLoginChallengeInternal
  1563. // return AuthURL,
  1564. // output parameter: tweener authHeader
  1565. //
  1566. // get AuthURL and AuthHeaders
  1567. //
  1568. STDMETHODIMP CManager::GetLoginChallengeInternal(VARIANT vReturnUrl,
  1569. VARIANT vTimeWindow,
  1570. VARIANT vForceLogin,
  1571. VARIANT vCoBrandTemplate,
  1572. VARIANT vLCID,
  1573. VARIANT vNameSpace,
  1574. VARIANT vKPP,
  1575. VARIANT vSecureLevel,
  1576. VARIANT vExtraParams,
  1577. VARIANT *pAuthHeader,
  1578. BSTR* pAuthVal
  1579. )
  1580. {
  1581. HRESULT hr = S_OK;
  1582. if (pAuthVal)
  1583. {
  1584. *pAuthVal = NULL;
  1585. }
  1586. if (pAuthHeader)
  1587. {
  1588. V_BSTR(pAuthHeader) = NULL;
  1589. }
  1590. _bstr_t strAuthHeader;
  1591. try
  1592. {
  1593. // format qs and WWW-Authenticate header ....
  1594. _bstr_t strUrl, strRetUrl, strCBT, strNameSpace;
  1595. UINT TimeWindow;
  1596. int nKPP;
  1597. time_t ct;
  1598. VARIANT_BOOL ForceLogin;
  1599. ULONG ulSecureLevel;
  1600. WCHAR rgLCID[10];
  1601. hr = GetLoginParams(vReturnUrl,
  1602. vTimeWindow,
  1603. vForceLogin,
  1604. vCoBrandTemplate,
  1605. vLCID,
  1606. vNameSpace,
  1607. vKPP,
  1608. vSecureLevel,
  1609. strUrl,
  1610. strRetUrl,
  1611. TimeWindow,
  1612. ForceLogin,
  1613. ct,
  1614. strCBT,
  1615. strNameSpace,
  1616. nKPP,
  1617. ulSecureLevel,
  1618. rgLCID);
  1619. if (S_OK == hr && strUrl.length() != 0)
  1620. {
  1621. WCHAR szBuf[MAX_QS_LENGTH] = L"";
  1622. // prepare redirect URL to the login server for
  1623. // downlevel clients
  1624. if (NULL == FormatAuthURLParameters(strUrl,
  1625. m_pRegistryConfig->getSiteId(),
  1626. strRetUrl,
  1627. TimeWindow,
  1628. ForceLogin,
  1629. m_pRegistryConfig->getCurrentCryptVersion(),
  1630. ct,
  1631. strCBT,
  1632. strNameSpace,
  1633. nKPP,
  1634. szBuf,
  1635. sizeof(szBuf)/sizeof(WCHAR),
  1636. 0, // lang does not matter ....
  1637. ulSecureLevel,
  1638. m_pRegistryConfig,
  1639. FALSE,
  1640. IfCreateTPF()
  1641. )) // do not redirect to self!
  1642. {
  1643. hr = E_OUTOFMEMORY;
  1644. goto Cleanup;
  1645. }
  1646. // insert the WWW-Authenticate header ...
  1647. hr = FormatAuthHeaderFromParams(strUrl,
  1648. strRetUrl,
  1649. TimeWindow,
  1650. ForceLogin,
  1651. ct,
  1652. strCBT,
  1653. strNameSpace,
  1654. nKPP,
  1655. rgLCID,
  1656. ulSecureLevel,
  1657. strAuthHeader);
  1658. if (S_OK != hr)
  1659. {
  1660. goto Cleanup;
  1661. }
  1662. // and add the extra ....
  1663. BSTR strExtra = NULL;
  1664. int res = GetBstrArg(vExtraParams, &strExtra);
  1665. if (res != CV_BAD)
  1666. {
  1667. if (res == CV_DEFAULT)
  1668. {
  1669. strExtra = m_pRegistryConfig->getExtraParams();
  1670. }
  1671. if (NULL != strExtra)
  1672. {
  1673. strAuthHeader += _bstr_t(L",") + strExtra;
  1674. }
  1675. }
  1676. if (res == CV_FREE)
  1677. ::SysFreeString(strExtra);
  1678. // set return values
  1679. if (pAuthHeader && (WCHAR*)strAuthHeader != NULL)
  1680. {
  1681. V_VT(pAuthHeader) = VT_BSTR;
  1682. // TODO: should avoid this SysAllocString
  1683. V_BSTR(pAuthHeader) = ::SysAllocString((WCHAR*)strAuthHeader);
  1684. if (NULL == V_BSTR(pAuthHeader))
  1685. {
  1686. hr = E_OUTOFMEMORY;
  1687. goto Cleanup;
  1688. }
  1689. }
  1690. if (pAuthVal)
  1691. {
  1692. *pAuthVal = ::SysAllocString(szBuf);
  1693. if (NULL == *pAuthVal)
  1694. {
  1695. hr = E_OUTOFMEMORY;
  1696. goto Cleanup;
  1697. }
  1698. }
  1699. }
  1700. }
  1701. catch(...)
  1702. {
  1703. hr = E_OUTOFMEMORY;
  1704. }
  1705. Cleanup:
  1706. return hr;
  1707. }
  1708. //===========================================================================
  1709. //
  1710. // LoginUser
  1711. //
  1712. //
  1713. // client logon method
  1714. // vExtraParams: coBranding text is passed as cbtxt=cobrandingtext
  1715. // the content of the input parameter should be UTF8 encoded, and
  1716. // properly URL escapted before passing into this function
  1717. //
  1718. STDMETHODIMP CManager::LoginUser(VARIANT vReturnUrl,
  1719. VARIANT vTimeWindow,
  1720. VARIANT vForceLogin,
  1721. VARIANT vCoBrandTemplate,
  1722. VARIANT vLCID,
  1723. VARIANT vNameSpace,
  1724. VARIANT vKPP,
  1725. VARIANT vSecureLevel,
  1726. VARIANT vExtraParams)
  1727. {
  1728. // format qs and WWW-Authenticate header ....
  1729. BSTR authURL = NULL;
  1730. CComVariant authHeader;
  1731. PassportLog("CManager::LoginUser Enter:\r\n");
  1732. HRESULT hr = GetLoginChallengeInternal( vReturnUrl,
  1733. vTimeWindow,
  1734. vForceLogin,
  1735. vCoBrandTemplate,
  1736. vLCID,
  1737. vNameSpace,
  1738. vKPP,
  1739. vSecureLevel,
  1740. vExtraParams,
  1741. &authHeader,
  1742. &authURL);
  1743. if (S_OK == hr)
  1744. {
  1745. _ASSERT(V_VT(&authHeader) == VT_BSTR);
  1746. _ASSERT(authURL);
  1747. _ASSERT(V_BSTR(&authHeader));
  1748. // TODO: _bstr_t should be removed globaly in ppm
  1749. if (m_piResponse)
  1750. {
  1751. m_piResponse->AddHeader(L"WWW-Authenticate", V_BSTR(&authHeader));
  1752. _bstr_t authURL1 = authURL;
  1753. // and redirect!
  1754. if (!m_bIsTweenerCapable)
  1755. m_piResponse->Redirect(authURL1);
  1756. else
  1757. {
  1758. // send a 401
  1759. m_piResponse->put_Status(L"401 Unauthorized");
  1760. m_piResponse->End();
  1761. }
  1762. }
  1763. else if (m_pECB || m_pFC)
  1764. {
  1765. // use ECB of Filter interfaces
  1766. // 4k whould be enough ....
  1767. char buffer[4096],
  1768. status[25] = "302 Object moved",
  1769. *psz=buffer,
  1770. rgszTemplate[] = "Content-Type: text/html\r\nLocation: %ws\r\n"
  1771. "Content-Length: 0\r\n"
  1772. "WWW-Authenticate: %ws\r\n\r\n";
  1773. DWORD cbTotalLength = strlen(rgszTemplate);
  1774. //
  1775. // This is a hack fix, unfortunately we can succeed the call to GetChallengeInternal but
  1776. // have a NULL authHeader, it seemed a bit risky to try and fix GetLoginParams which
  1777. // seems to be the function which returns success when allocations are failing.
  1778. //
  1779. if ((NULL == V_BSTR(&authHeader)) || (NULL == (BSTR)authURL))
  1780. {
  1781. hr = E_OUTOFMEMORY;
  1782. goto Cleanup;
  1783. }
  1784. cbTotalLength += wcslen(V_BSTR(&authHeader)) + wcslen(authURL);
  1785. if (m_bIsTweenerCapable)
  1786. strcpy(status, "401 Unauthorized");
  1787. if (cbTotalLength >= sizeof(buffer))
  1788. {
  1789. // if not ...
  1790. // need to alloc
  1791. psz = new CHAR[cbTotalLength];
  1792. _ASSERT(psz);
  1793. }
  1794. if (psz)
  1795. {
  1796. sprintf(psz,
  1797. rgszTemplate,
  1798. authURL,
  1799. V_BSTR(&authHeader));
  1800. if (m_pECB)
  1801. {
  1802. // extension
  1803. HSE_SEND_HEADER_EX_INFO Headers =
  1804. {
  1805. status,
  1806. psz,
  1807. strlen(status),
  1808. strlen(psz),
  1809. TRUE
  1810. };
  1811. if (!m_pECB->ServerSupportFunction(m_pECB->ConnID,
  1812. HSE_REQ_SEND_RESPONSE_HEADER_EX,
  1813. &Headers,
  1814. NULL,
  1815. NULL))
  1816. {
  1817. hr = HRESULT_FROM_WIN32(GetLastError());
  1818. }
  1819. }
  1820. else
  1821. {
  1822. // filter
  1823. if (!m_pFC->ServerSupportFunction(m_pFC,
  1824. SF_REQ_SEND_RESPONSE_HEADER,
  1825. status,
  1826. (ULONG_PTR) psz,
  1827. NULL))
  1828. {
  1829. hr = HRESULT_FROM_WIN32(GetLastError());
  1830. }
  1831. }
  1832. if (psz != buffer)
  1833. // if we had to allocate
  1834. delete[] psz;
  1835. }
  1836. else
  1837. {
  1838. hr = E_OUTOFMEMORY;
  1839. }
  1840. }
  1841. }
  1842. Cleanup:
  1843. if (authURL)
  1844. {
  1845. SysFreeString(authURL);
  1846. }
  1847. PassportLog("CManager::LoginUser Exit: %X\r\n", hr);
  1848. return hr;
  1849. }
  1850. //===========================================================================
  1851. //
  1852. // IsAuthenticated -- determine if authenticated with specified SecureLevel
  1853. //
  1854. STDMETHODIMP CManager::IsAuthenticated(
  1855. VARIANT vTimeWindow,
  1856. VARIANT vForceLogin,
  1857. VARIANT SecureLevel,
  1858. VARIANT_BOOL *pVal)
  1859. {
  1860. HRESULT hr;
  1861. ULONG TimeWindow;
  1862. VARIANT_BOOL ForceLogin;
  1863. ATL::CComVariant vSecureLevel;
  1864. ULONG ulSecureLevel;
  1865. int hasTW, hasFL, hasSecureLevel;
  1866. PassportLog("CManager::IsAuthenticated Enter:\r\n");
  1867. PPTraceFunc<HRESULT> func(PPTRACE_FUNC, hr,
  1868. "IsAuthenticated", "<<< %lx, %lx, %1x, %1x",
  1869. V_I4(&vTimeWindow), V_I4(&vForceLogin), V_I4(&SecureLevel), pVal);
  1870. if (!m_piTicket || !m_piProfile)
  1871. {
  1872. hr = E_OUTOFMEMORY;
  1873. goto Cleanup;
  1874. }
  1875. if (!g_config) // Guarantees config is non-null
  1876. {
  1877. AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
  1878. IID_IPassportManager, PP_E_NOT_CONFIGURED);
  1879. hr = PP_E_NOT_CONFIGURED;
  1880. goto Cleanup;
  1881. }
  1882. if (!m_pRegistryConfig)
  1883. m_pRegistryConfig = g_config->checkoutRegistryConfig();
  1884. if (!g_config->isValid() || !m_pRegistryConfig) // Guarantees config is non-null
  1885. {
  1886. AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
  1887. IID_IPassportManager, PP_E_NOT_CONFIGURED);
  1888. hr = PP_E_NOT_CONFIGURED;
  1889. goto Cleanup;
  1890. }
  1891. if ((hasTW = GetIntArg(vTimeWindow,(int*)&TimeWindow)) == CV_BAD)
  1892. {
  1893. hr = E_INVALIDARG;
  1894. goto Cleanup;
  1895. }
  1896. if (hasTW == CV_DEFAULT)
  1897. TimeWindow = m_pRegistryConfig->getDefaultTicketAge();
  1898. if ((hasFL = GetBoolArg(vForceLogin, &ForceLogin)) == CV_BAD)
  1899. {
  1900. hr = E_INVALIDARG;
  1901. goto Cleanup;
  1902. }
  1903. if (hasFL == CV_DEFAULT)
  1904. ForceLogin = m_pRegistryConfig->forceLoginP() ? VARIANT_TRUE : VARIANT_FALSE;
  1905. hasSecureLevel = GetIntArg(SecureLevel, (int*)&ulSecureLevel);
  1906. if(hasSecureLevel == CV_BAD) // try the legacy type VT_BOOL, map VARIANT_TRUE to SecureChannel
  1907. {
  1908. hr = E_INVALIDARG;
  1909. goto Cleanup;
  1910. }
  1911. else if (hasSecureLevel == CV_DEFAULT)
  1912. {
  1913. ulSecureLevel = m_pRegistryConfig->getSecureLevel();
  1914. }
  1915. if(ulSecureLevel == VARIANT_TRUE)// backward compatible with 1.3X
  1916. {
  1917. ulSecureLevel = k_iSeclevelSecureChannel;
  1918. }
  1919. vSecureLevel = ulSecureLevel;
  1920. // Logging
  1921. PassportLog(" TW = %X, SL = %X\r\n", TimeWindow, ulSecureLevel);
  1922. hr = m_piTicket->get_IsAuthenticated(TimeWindow, ForceLogin, vSecureLevel, pVal);
  1923. PPTracePrint(PPTRACE_RAW, "IsAuthenticated Params: %d, %d, %d, %lx", TimeWindow, ForceLogin, ulSecureLevel, *pVal);
  1924. Cleanup:
  1925. if(g_pPerf)
  1926. {
  1927. if (*pVal)
  1928. {
  1929. g_pPerf->incrementCounter(PM_AUTHSUCCESS_TOTAL);
  1930. g_pPerf->incrementCounter(PM_AUTHSUCCESS_SEC);
  1931. }
  1932. else
  1933. {
  1934. g_pPerf->incrementCounter(PM_AUTHFAILURE_TOTAL);
  1935. g_pPerf->incrementCounter(PM_AUTHFAILURE_SEC);
  1936. }
  1937. }
  1938. else
  1939. {
  1940. _ASSERT(g_pPerf);
  1941. }
  1942. PassportLog("CManager::IsAuthenticated Exit: %X\r\n", hr);
  1943. return hr;
  1944. }
  1945. //===========================================================================
  1946. //
  1947. // LogoTag
  1948. //
  1949. //
  1950. // old PM API. The URL is pointing to login server
  1951. //
  1952. STDMETHODIMP
  1953. CManager::LogoTag(
  1954. VARIANT vRU,
  1955. VARIANT vTimeWindow,
  1956. VARIANT vForceLogin,
  1957. VARIANT vCoBrand,
  1958. VARIANT vLCID,
  1959. VARIANT vSecure,
  1960. VARIANT vNameSpace,
  1961. VARIANT vKPP,
  1962. VARIANT vSecureLevel,
  1963. BSTR *pVal)
  1964. {
  1965. return CommonLogoTag(vRU, vTimeWindow, vForceLogin,
  1966. vCoBrand, vLCID, vSecure,
  1967. vNameSpace, vKPP, vSecureLevel,
  1968. FALSE, pVal);
  1969. }
  1970. //===========================================================================
  1971. //
  1972. // LogoTag2
  1973. //
  1974. //
  1975. // new PM API. The URL is pointing to the partner site
  1976. //
  1977. STDMETHODIMP
  1978. CManager::LogoTag2(
  1979. VARIANT vRU,
  1980. VARIANT vTimeWindow,
  1981. VARIANT vForceLogin,
  1982. VARIANT vCoBrand,
  1983. VARIANT vLCID,
  1984. VARIANT vSecure,
  1985. VARIANT vNameSpace,
  1986. VARIANT vKPP,
  1987. VARIANT vSecureLevel,
  1988. BSTR *pVal)
  1989. {
  1990. return CommonLogoTag(vRU, vTimeWindow, vForceLogin,
  1991. vCoBrand, vLCID, vSecure,
  1992. vNameSpace, vKPP, vSecureLevel,
  1993. TRUE, pVal);
  1994. }
  1995. //===========================================================================
  1996. //
  1997. // CommonLogoTag
  1998. //
  1999. STDMETHODIMP
  2000. CManager::CommonLogoTag(
  2001. VARIANT vRU,
  2002. VARIANT vTimeWindow,
  2003. VARIANT vForceLogin,
  2004. VARIANT vCoBrand,
  2005. VARIANT vLCID,
  2006. VARIANT vSecure,
  2007. VARIANT vNameSpace,
  2008. VARIANT vKPP,
  2009. VARIANT vSecureLevel,
  2010. BOOL fRedirToSelf,
  2011. BSTR *pVal)
  2012. {
  2013. time_t ct;
  2014. ULONG TimeWindow;
  2015. int nKPP;
  2016. VARIANT_BOOL ForceLogin, bSecure = VARIANT_FALSE;
  2017. ULONG ulSecureLevel = 0;
  2018. BSTR CBT = NULL, returnUrl = NULL, NameSpace = NULL;
  2019. int hasCB = -1, hasRU = -1, hasLCID, hasTW, hasFL, hasSec, hasUseSec, hasNameSpace = -1, hasKPP;
  2020. USHORT Lang;
  2021. LPWSTR pszNewURL = NULL;
  2022. BSTR upd = NULL;
  2023. CNexusConfig* cnc = NULL;
  2024. HRESULT hr = S_OK;
  2025. USES_CONVERSION;
  2026. PassportLog("CManager::CommonLogoTag Enter:\r\n");
  2027. time(&ct);
  2028. if (NULL == pVal)
  2029. {
  2030. hr = E_INVALIDARG;
  2031. goto Cleanup;
  2032. }
  2033. *pVal = NULL;
  2034. if (!g_config) // Guarantees config is non-null
  2035. {
  2036. AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
  2037. IID_IPassportManager, PP_E_NOT_CONFIGURED);
  2038. hr = PP_E_NOT_CONFIGURED;
  2039. goto Cleanup;
  2040. }
  2041. if (!m_pRegistryConfig)
  2042. m_pRegistryConfig = g_config->checkoutRegistryConfig();
  2043. if (!g_config->isValid() || !m_pRegistryConfig) // Guarantees config is non-null
  2044. {
  2045. AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
  2046. IID_IPassportManager, PP_E_NOT_CONFIGURED);
  2047. hr = PP_E_NOT_CONFIGURED;
  2048. goto Cleanup;
  2049. }
  2050. //
  2051. // parameters parsing ...
  2052. // Make sure args are of the right type
  2053. if ( ((hasTW = GetIntArg(vTimeWindow, (int*) &TimeWindow)) == CV_BAD) ||
  2054. ((hasFL = GetBoolArg(vForceLogin, &ForceLogin)) == CV_BAD) ||
  2055. ((hasSec = GetBoolArg(vSecure,&bSecure)) == CV_BAD) ||
  2056. // FUTURE: should introduce a new func: GetLongArg ...
  2057. ((hasUseSec = GetIntArg(vSecureLevel,(int*)&ulSecureLevel)) == CV_BAD) ||
  2058. ((hasLCID = GetShortArg(vLCID,&Lang)) == CV_BAD) ||
  2059. ((hasKPP = GetIntArg(vKPP, &nKPP)) == CV_BAD) )
  2060. {
  2061. hr = E_INVALIDARG;
  2062. goto Cleanup;
  2063. }
  2064. hasCB = GetBstrArg(vCoBrand, &CBT);
  2065. if (hasCB == CV_BAD)
  2066. {
  2067. hr = E_INVALIDARG;
  2068. goto Cleanup;
  2069. }
  2070. if (hasCB == CV_FREE)
  2071. {
  2072. TAKEOVER_BSTR(CBT);
  2073. }
  2074. hasRU = GetBstrArg(vRU, &returnUrl);
  2075. if (hasRU == CV_BAD)
  2076. {
  2077. hr = E_INVALIDARG;
  2078. goto Cleanup;
  2079. }
  2080. if (hasRU == CV_FREE)
  2081. {
  2082. TAKEOVER_BSTR(returnUrl);
  2083. }
  2084. hasNameSpace = GetBstrArg(vNameSpace, &NameSpace);
  2085. if (hasNameSpace == CV_BAD)
  2086. {
  2087. hr = E_INVALIDARG;
  2088. goto Cleanup;
  2089. }
  2090. if (hasNameSpace == CV_FREE)
  2091. {
  2092. TAKEOVER_BSTR(NameSpace);
  2093. }
  2094. if (hasNameSpace == CV_DEFAULT)
  2095. {
  2096. NameSpace = m_pRegistryConfig->getNameSpace();
  2097. }
  2098. WCHAR *szSIAttrName, *szSOAttrName;
  2099. if (hasSec == CV_OK && bSecure == VARIANT_TRUE)
  2100. {
  2101. szSIAttrName = L"SecureSigninLogo";
  2102. szSOAttrName = L"SecureSignoutLogo";
  2103. }
  2104. else
  2105. {
  2106. szSIAttrName = L"SigninLogo";
  2107. szSOAttrName = L"SignoutLogo";
  2108. }
  2109. if(hasUseSec == CV_DEFAULT)
  2110. ulSecureLevel = m_pRegistryConfig->getSecureLevel();
  2111. if(ulSecureLevel == VARIANT_TRUE) // special case for backward compatible
  2112. ulSecureLevel = k_iSeclevelSecureChannel;
  2113. WCHAR *szAUAttrName;
  2114. if (SECURELEVEL_USE_HTTPS(ulSecureLevel))
  2115. szAUAttrName = L"AuthSecure";
  2116. else
  2117. szAUAttrName = L"Auth";
  2118. cnc = g_config->checkoutNexusConfig();
  2119. if (NULL == cnc)
  2120. {
  2121. hr = PP_E_NOT_CONFIGURED;
  2122. goto Cleanup;
  2123. }
  2124. if (hasLCID == CV_DEFAULT)
  2125. Lang = m_pRegistryConfig->getDefaultLCID();
  2126. if (hasTW == CV_DEFAULT)
  2127. TimeWindow = m_pRegistryConfig->getDefaultTicketAge();
  2128. if (hasFL == CV_DEFAULT)
  2129. ForceLogin = m_pRegistryConfig->forceLoginP() ? VARIANT_TRUE : VARIANT_FALSE;
  2130. if (hasCB == CV_DEFAULT)
  2131. CBT = m_pRegistryConfig->getDefaultCoBrand();
  2132. if (hasRU == CV_DEFAULT)
  2133. returnUrl = m_pRegistryConfig->getDefaultRU();
  2134. if (hasKPP == CV_DEFAULT)
  2135. nKPP = m_pRegistryConfig->getKPP();
  2136. if (returnUrl == NULL)
  2137. returnUrl = L"";
  2138. // **************************************************
  2139. // Logging
  2140. PassportLog(" RU = %ws\r\n", returnUrl);
  2141. PassportLog(" TW = %X, SL = %X, L = %d, KPP = %X\r\n", TimeWindow, ulSecureLevel, Lang, nKPP);
  2142. if (NULL != NameSpace)
  2143. {
  2144. PassportLog(" NS = %ws\r\n", NameSpace);
  2145. }
  2146. if (NULL != CBT)
  2147. {
  2148. PassportLog(" CBT = %ws\r\n", CBT);
  2149. }
  2150. // **************************************************
  2151. if ((TimeWindow != 0 && TimeWindow < PPM_TIMEWINDOW_MIN) || TimeWindow > PPM_TIMEWINDOW_MAX)
  2152. {
  2153. WCHAR buf[20];
  2154. _itow(TimeWindow,buf,10);
  2155. AtlReportError(CLSID_Manager, (LPCOLESTR) PP_E_INVALID_TIMEWINDOWSTR,
  2156. IID_IPassportManager, PP_E_INVALID_TIMEWINDOW);
  2157. hr = PP_E_INVALID_TIMEWINDOW;
  2158. goto Cleanup;
  2159. }
  2160. if (m_ticketValid)
  2161. {
  2162. LPCWSTR domain = NULL;
  2163. WCHAR url[MAX_URL_LENGTH];
  2164. VARIANT freeMe;
  2165. VariantInit(&freeMe);
  2166. if (m_pRegistryConfig->DisasterModeP())
  2167. lstrcpynW(url, m_pRegistryConfig->getDisasterUrl(), sizeof(url)/sizeof(WCHAR));
  2168. else
  2169. {
  2170. if (m_profileValid &&
  2171. m_piProfile->get_ByIndex(MEMBERNAME_INDEX, &freeMe) == S_OK &&
  2172. freeMe.vt == VT_BSTR)
  2173. {
  2174. domain = wcsrchr(freeMe.bstrVal, L'@');
  2175. }
  2176. cnc->getDomainAttribute(L"Default",
  2177. L"Logout",
  2178. sizeof(url)/sizeof(WCHAR),
  2179. url,
  2180. Lang);
  2181. }
  2182. // find out if there are any updates
  2183. m_piProfile->get_updateString(&upd);
  2184. if (upd)
  2185. {
  2186. TAKEOVER_BSTR(upd);
  2187. // form the appropriate URL
  2188. CCoCrypt* crypt = NULL;
  2189. BSTR newCH = NULL;
  2190. crypt = m_pRegistryConfig->getCurrentCrypt(); // IsValid ensures this is non-null
  2191. if (!crypt->Encrypt(m_pRegistryConfig->getCurrentCryptVersion(),
  2192. (LPSTR)upd,
  2193. SysStringByteLen(upd),
  2194. &newCH))
  2195. {
  2196. AtlReportError(CLSID_Manager, (LPCOLESTR) PP_E_UNABLE_TO_ENCRYPTSTR,
  2197. IID_IPassportManager, PP_E_UNABLE_TO_ENCRYPT);
  2198. hr = PP_E_UNABLE_TO_ENCRYPT;
  2199. goto Cleanup;
  2200. }
  2201. TAKEOVER_BSTR(newCH);
  2202. WCHAR iurlbuf[1024] = L"";
  2203. LPCWSTR iurl;
  2204. cnc->getDomainAttribute(domain ? domain+1 : L"Default",
  2205. L"Update",
  2206. sizeof(iurlbuf) >> 1,
  2207. iurlbuf,
  2208. Lang);
  2209. if(*iurlbuf == 0)
  2210. {
  2211. cnc->getDomainAttribute(L"Default",
  2212. L"Update",
  2213. sizeof(iurlbuf) >> 1,
  2214. iurlbuf,
  2215. Lang);
  2216. }
  2217. // convert this url to https as appropriate
  2218. if(!bSecure)
  2219. iurl = iurlbuf;
  2220. else
  2221. {
  2222. LPWSTR psz;
  2223. pszNewURL = SysAllocStringByteLen(NULL, (lstrlenW(iurlbuf) + 2) * sizeof(WCHAR));
  2224. if(pszNewURL)
  2225. {
  2226. psz = wcsstr(iurlbuf, L"http:");
  2227. if(psz != NULL)
  2228. {
  2229. psz += 4;
  2230. lstrcpynW(pszNewURL, iurlbuf, (psz - iurlbuf + 1));
  2231. lstrcatW(pszNewURL, L"s");
  2232. lstrcatW(pszNewURL, psz);
  2233. iurl = pszNewURL;
  2234. }
  2235. }
  2236. }
  2237. // This is a bit gross... we need to find the $1 in the update url...
  2238. LPCWSTR ins = iurl ? (wcsstr(iurl, L"$1")) : NULL;
  2239. // We'll break if null, but won't crash...
  2240. if (ins && *url != L'\0')
  2241. {
  2242. *pVal = FormatUpdateLogoTag(
  2243. url,
  2244. m_pRegistryConfig->getSiteId(),
  2245. returnUrl,
  2246. TimeWindow,
  2247. ForceLogin,
  2248. m_pRegistryConfig->getCurrentCryptVersion(),
  2249. ct,
  2250. CBT,
  2251. nKPP,
  2252. iurl,
  2253. bSecure,
  2254. newCH,
  2255. PM_LOGOTYPE_SIGNOUT,
  2256. ulSecureLevel,
  2257. m_pRegistryConfig,
  2258. IfCreateTPF()
  2259. );
  2260. }
  2261. FREE_BSTR(newCH);
  2262. }
  2263. else
  2264. {
  2265. WCHAR iurl[MAX_URL_LENGTH] = L"";
  2266. cnc->getDomainAttribute(L"Default",
  2267. szSOAttrName,
  2268. sizeof(iurl)/sizeof(WCHAR),
  2269. iurl,
  2270. Lang);
  2271. if (*iurl != L'\0')
  2272. {
  2273. *pVal = FormatNormalLogoTag(
  2274. url,
  2275. m_pRegistryConfig->getSiteId(),
  2276. returnUrl,
  2277. TimeWindow,
  2278. ForceLogin,
  2279. m_pRegistryConfig->getCurrentCryptVersion(),
  2280. ct,
  2281. CBT,
  2282. iurl,
  2283. NULL,
  2284. nKPP,
  2285. PM_LOGOTYPE_SIGNOUT,
  2286. Lang,
  2287. ulSecureLevel,
  2288. m_pRegistryConfig,
  2289. fRedirToSelf,
  2290. IfCreateTPF()
  2291. );
  2292. }
  2293. }
  2294. VariantClear(&freeMe);
  2295. if (NULL == *pVal)
  2296. {
  2297. hr = E_OUTOFMEMORY;
  2298. goto Cleanup;
  2299. }
  2300. }
  2301. else
  2302. {
  2303. WCHAR url[MAX_URL_LENGTH];
  2304. if (!(m_pRegistryConfig->DisasterModeP()))
  2305. cnc->getDomainAttribute(L"Default",
  2306. szAUAttrName,
  2307. sizeof(url)/sizeof(WCHAR),
  2308. url,
  2309. Lang);
  2310. else
  2311. lstrcpynW(url, m_pRegistryConfig->getDisasterUrl(), sizeof(url)/sizeof(WCHAR));
  2312. WCHAR iurl[MAX_URL_LENGTH];
  2313. cnc->getDomainAttribute(L"Default",
  2314. szSIAttrName,
  2315. sizeof(iurl)/sizeof(WCHAR),
  2316. iurl,
  2317. Lang);
  2318. if (*iurl != L'\0')
  2319. {
  2320. *pVal = FormatNormalLogoTag(
  2321. url,
  2322. m_pRegistryConfig->getSiteId(),
  2323. returnUrl,
  2324. TimeWindow,
  2325. ForceLogin,
  2326. m_pRegistryConfig->getCurrentCryptVersion(),
  2327. ct,
  2328. CBT,
  2329. iurl,
  2330. NameSpace,
  2331. nKPP,
  2332. PM_LOGOTYPE_SIGNIN,
  2333. Lang,
  2334. ulSecureLevel,
  2335. m_pRegistryConfig,
  2336. fRedirToSelf,
  2337. IfCreateTPF()
  2338. );
  2339. if (NULL == *pVal)
  2340. {
  2341. hr = E_OUTOFMEMORY;
  2342. goto Cleanup;
  2343. }
  2344. }
  2345. }
  2346. Cleanup:
  2347. if (NULL != cnc)
  2348. {
  2349. cnc->Release();
  2350. }
  2351. if (NULL != upd)
  2352. FREE_BSTR(upd);
  2353. if (pszNewURL)
  2354. SysFreeString(pszNewURL);
  2355. if (hasRU == CV_FREE && returnUrl)
  2356. FREE_BSTR(returnUrl);
  2357. if (hasCB == CV_FREE && CBT)
  2358. FREE_BSTR(CBT);
  2359. if (hasNameSpace == CV_FREE && NameSpace)
  2360. FREE_BSTR(NameSpace);
  2361. PassportLog("CManager::CommonLogoTag Exit: %X\r\n", hr);
  2362. return hr;
  2363. }
  2364. //===========================================================================
  2365. //
  2366. // HasProfile -- if valid profile is present
  2367. //
  2368. STDMETHODIMP CManager::HasProfile(VARIANT var, VARIANT_BOOL *pVal)
  2369. {
  2370. LPWSTR profileName;
  2371. PassportLog("CManager::HasProfile Enter:\r\n");
  2372. if (var.vt == (VT_BSTR | VT_BYREF))
  2373. profileName = *var.pbstrVal;
  2374. else if (var.vt == VT_BSTR)
  2375. profileName = var.bstrVal;
  2376. else if (var.vt == (VT_VARIANT | VT_BYREF))
  2377. {
  2378. return HasProfile(*(var.pvarVal), pVal);
  2379. }
  2380. else
  2381. profileName = NULL;
  2382. if ((!profileName) || (!_wcsicmp(profileName, L"core")))
  2383. {
  2384. HRESULT ok = m_piProfile->get_IsValid(pVal);
  2385. if (ok != S_OK)
  2386. *pVal = VARIANT_FALSE;
  2387. }
  2388. else
  2389. {
  2390. VARIANT vAtt;
  2391. VariantInit(&vAtt);
  2392. PassportLog(" %ws\r\n", profileName);
  2393. HRESULT ok = m_piProfile->get_Attribute(profileName, &vAtt);
  2394. if (ok != S_OK)
  2395. {
  2396. if (g_pAlert)
  2397. g_pAlert->report(PassportAlertInterface::ERROR_TYPE, PM_INVALID_PROFILETYPE);
  2398. *pVal = VARIANT_FALSE;
  2399. }
  2400. else
  2401. {
  2402. if (vAtt.vt == VT_I4)
  2403. *pVal = vAtt.lVal > 0 ? VARIANT_TRUE : VARIANT_FALSE;
  2404. else if (vAtt.vt == VT_I2)
  2405. *pVal = vAtt.iVal > 0 ? VARIANT_TRUE : VARIANT_FALSE;
  2406. else
  2407. {
  2408. if (g_pAlert)
  2409. g_pAlert->report(PassportAlertInterface::ERROR_TYPE, PM_INVALID_PROFILETYPE);
  2410. }
  2411. VariantClear(&vAtt);
  2412. }
  2413. }
  2414. PassportLog("CManager::HasProfile Exit: %X\r\n", *pVal);
  2415. return(S_OK);
  2416. }
  2417. //===========================================================================
  2418. //
  2419. // get_HasTicket
  2420. //
  2421. STDMETHODIMP CManager::get_HasTicket(VARIANT_BOOL *pVal)
  2422. {
  2423. PassportLog("CManager::get_HasTicket:\r\n");
  2424. if(!pVal) return E_POINTER;
  2425. *pVal = m_ticketValid ? VARIANT_TRUE : VARIANT_FALSE;
  2426. return S_OK;
  2427. }
  2428. //===========================================================================
  2429. //
  2430. // get_FromNetworkServer -- if it's authenticated by QueryString
  2431. //
  2432. STDMETHODIMP CManager::get_FromNetworkServer(VARIANT_BOOL *pVal)
  2433. {
  2434. PassportLog("CManager::get_FromNetworkServer:\r\n");
  2435. *pVal = (m_fromQueryString &&
  2436. m_ticketValid) ? VARIANT_TRUE : VARIANT_FALSE;
  2437. return S_OK;
  2438. }
  2439. //===========================================================================
  2440. //
  2441. // HasFlag -- obsolete function
  2442. //
  2443. STDMETHODIMP CManager::HasFlag(VARIANT var, VARIANT_BOOL *pVal)
  2444. {
  2445. PassportLog("CManager::HasFlag:\r\n");
  2446. AtlReportError(CLSID_Manager, PP_E_GETFLAGS_OBSOLETESTR,
  2447. IID_IPassportManager, E_NOTIMPL);
  2448. return E_NOTIMPL;
  2449. }
  2450. //===========================================================================
  2451. //
  2452. // get_TicketAge -- get how long has passed since ticket was created
  2453. //
  2454. STDMETHODIMP CManager::get_TicketAge(int *pVal)
  2455. {
  2456. PassportLog("CManager::get_TicketAge:\r\n");
  2457. if (!m_piTicket)
  2458. {
  2459. return E_OUTOFMEMORY;
  2460. }
  2461. return m_piTicket->get_TicketAge(pVal);
  2462. }
  2463. //===========================================================================
  2464. //
  2465. // get_TicketTime -- get when the ticket was created
  2466. //
  2467. STDMETHODIMP CManager::get_TicketTime(long *pVal)
  2468. {
  2469. PassportLog("CManager::get_TicketTime:\r\n");
  2470. if (!m_piTicket)
  2471. {
  2472. return E_OUTOFMEMORY;
  2473. }
  2474. return m_piTicket->get_TicketTime(pVal);
  2475. }
  2476. //===========================================================================
  2477. //
  2478. // get_SignInTime -- get last signin time
  2479. //
  2480. STDMETHODIMP CManager::get_SignInTime(long *pVal)
  2481. {
  2482. PassportLog("CManager::get_SignInTime:\r\n");
  2483. if (!m_piTicket)
  2484. {
  2485. return E_OUTOFMEMORY;
  2486. }
  2487. return m_piTicket->get_SignInTime(pVal);
  2488. }
  2489. //===========================================================================
  2490. //
  2491. // get_TimeSinceSignIn -- time passed since last signin
  2492. //
  2493. STDMETHODIMP CManager::get_TimeSinceSignIn(int *pVal)
  2494. {
  2495. PassportLog("CManager::get_TimeSinceSignIn:\r\n");
  2496. if (!m_piTicket)
  2497. {
  2498. return E_OUTOFMEMORY;
  2499. }
  2500. return m_piTicket->get_TimeSinceSignIn(pVal);
  2501. }
  2502. //===========================================================================
  2503. //
  2504. // GetDomainAttribute -- return information defined in partner.xml file
  2505. //
  2506. STDMETHODIMP CManager::GetDomainAttribute(BSTR attributeName, VARIANT lcid, VARIANT domain, BSTR *pAttrVal)
  2507. {
  2508. HRESULT hr = S_OK;
  2509. PassportLog("CManager::GetDomainAttribute Enter:\r\n");
  2510. if(attributeName == NULL || *attributeName == 0)
  2511. return E_INVALIDARG;
  2512. PassportLog(" %ws\r\n", attributeName);
  2513. if (!g_config || !g_config->isValid()) // Guarantees config is non-null
  2514. {
  2515. AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
  2516. IID_IPassportManager, PP_E_NOT_CONFIGURED);
  2517. return PP_E_NOT_CONFIGURED;
  2518. }
  2519. if (!m_pRegistryConfig)
  2520. m_pRegistryConfig = g_config->checkoutRegistryConfig();
  2521. if (!m_pRegistryConfig) // Guarantees config is non-null
  2522. {
  2523. AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
  2524. IID_IPassportManager, PP_E_NOT_CONFIGURED);
  2525. return PP_E_NOT_CONFIGURED;
  2526. }
  2527. LPWSTR d;
  2528. BSTR dn = NULL;
  2529. if (domain.vt == (VT_BSTR | VT_BYREF))
  2530. d = *domain.pbstrVal;
  2531. else if (domain.vt == VT_BSTR)
  2532. d = domain.bstrVal;
  2533. else if (domain.vt == (VT_VARIANT | VT_BYREF))
  2534. {
  2535. return GetDomainAttribute(attributeName, lcid, *(domain.pvarVal), pAttrVal);
  2536. }
  2537. else
  2538. {
  2539. // domain best be not filled in this case, that's why we reuse it here
  2540. // if not, let dfmn generate the error
  2541. HRESULT hr = DomainFromMemberName(domain, &dn);
  2542. if (hr != S_OK)
  2543. return hr;
  2544. TAKEOVER_BSTR(dn);
  2545. d = dn;
  2546. }
  2547. if (NULL != d)
  2548. {
  2549. PassportLog(" %ws\r\n", d);
  2550. }
  2551. CNexusConfig* cnc = g_config->checkoutNexusConfig();
  2552. USHORT sLcid = 0;
  2553. VARIANT innerLC;
  2554. VariantInit(&innerLC);
  2555. if (lcid.vt != VT_ERROR && VariantChangeType(&innerLC, &lcid, 0, VT_UI2) == S_OK)
  2556. sLcid = innerLC.iVal;
  2557. else
  2558. {
  2559. sLcid = m_pRegistryConfig->getDefaultLCID();
  2560. // Check user profile
  2561. if (!sLcid && m_profileValid)
  2562. {
  2563. m_piProfile->get_ByIndex(LANGPREF_INDEX, &innerLC);
  2564. if (innerLC.vt == VT_I2 || innerLC.vt == VT_UI2)
  2565. sLcid = innerLC.iVal;
  2566. VariantClear(&innerLC);
  2567. }
  2568. }
  2569. WCHAR data[PP_MAX_ATTRIBUTE_LENGTH] = L"";
  2570. cnc->getDomainAttribute(d,
  2571. attributeName,
  2572. sizeof(data)/sizeof(WCHAR),
  2573. data,
  2574. sLcid);
  2575. // try default domain
  2576. if (!(*data) && (!d || !(*d) || lstrcmpiW(d, L"Default")))
  2577. {
  2578. cnc->getDomainAttribute(L"Default",
  2579. attributeName,
  2580. sizeof(data)/sizeof(WCHAR),
  2581. data,
  2582. sLcid);
  2583. }
  2584. if (*data)
  2585. {
  2586. *pAttrVal = ALLOC_AND_GIVEAWAY_BSTR(data);
  2587. }
  2588. else
  2589. {
  2590. /* fix bug: 12102 -- for backward compitible, not to return error
  2591. hr = E_INVALIDARG;
  2592. */
  2593. *pAttrVal = NULL;
  2594. }
  2595. cnc->Release();
  2596. if (dn) FREE_BSTR(dn);
  2597. PassportLog("CManager::GetDomainAttribute Exit: %X, %ws\r\n", hr, pAttrVal);
  2598. return hr;
  2599. }
  2600. //===========================================================================
  2601. //
  2602. // DomainFromMemberName -- returns domain name with given user id
  2603. //
  2604. STDMETHODIMP CManager::DomainFromMemberName(VARIANT var, BSTR *pDomainName)
  2605. {
  2606. HRESULT hr;
  2607. LPWSTR psz, memberName;
  2608. VARIANT intoVar;
  2609. PassportLog("CManager::DomainFromMemberName Enter:\r\n");
  2610. VariantInit(&intoVar);
  2611. if (var.vt == (VT_BSTR | VT_BYREF))
  2612. memberName = *var.pbstrVal;
  2613. else if (var.vt == VT_BSTR)
  2614. memberName = var.bstrVal;
  2615. else if (var.vt == (VT_VARIANT | VT_BYREF))
  2616. {
  2617. return DomainFromMemberName(*(var.pvarVal), pDomainName);
  2618. }
  2619. else
  2620. {
  2621. // Try to get it from the profile
  2622. if (!m_profileValid)
  2623. {
  2624. *pDomainName = ALLOC_AND_GIVEAWAY_BSTR(L"Default");
  2625. return S_OK;
  2626. }
  2627. HRESULT hr = m_piProfile->get_Attribute(L"internalmembername", &intoVar);
  2628. if (hr != S_OK)
  2629. {
  2630. *pDomainName = NULL;
  2631. return hr;
  2632. }
  2633. if (VariantChangeType(&intoVar,&intoVar, 0, VT_BSTR) != S_OK)
  2634. {
  2635. AtlReportError(CLSID_Manager, L"PassportManager: Couldn't convert memberName to string. Call partner support.",
  2636. IID_IPassportManager, E_FAIL);
  2637. return E_FAIL;
  2638. }
  2639. memberName = intoVar.bstrVal;
  2640. }
  2641. if(memberName == NULL)
  2642. {
  2643. hr = E_POINTER;
  2644. goto Cleanup;
  2645. }
  2646. PassportLog(" %ws\r\n", memberName);
  2647. psz = wcsrchr(memberName, L'@');
  2648. if(psz == NULL)
  2649. {
  2650. // fix bug: 13380
  2651. // hr = E_INVALIDARG;
  2652. // goto Cleanup;
  2653. psz = L"@Default";
  2654. }
  2655. psz++;
  2656. *pDomainName = ALLOC_AND_GIVEAWAY_BSTR(psz);
  2657. hr = S_OK;
  2658. Cleanup:
  2659. VariantClear(&intoVar);
  2660. PassportLog("CManager::DomainFromMemberName Exit: %X\r\n", hr);
  2661. if (S_OK == hr)
  2662. {
  2663. PassportLog(" %ws\r\n", *pDomainName);
  2664. }
  2665. return hr;
  2666. }
  2667. //===========================================================================
  2668. //
  2669. // get_Profile -- get property from profile property bag
  2670. //
  2671. STDMETHODIMP CManager::get_Profile(BSTR attributeName, VARIANT *pVal)
  2672. {
  2673. HRESULT hr = m_piProfile->get_Attribute(attributeName,pVal);
  2674. PassportLog("CManager::get_Profile: %ws\r\n", attributeName);
  2675. if(hr == S_OK && pVal->vt != VT_EMPTY)
  2676. {
  2677. if(g_pPerf)
  2678. {
  2679. g_pPerf->incrementCounter(PM_VALIDPROFILEREQ_SEC);
  2680. g_pPerf->incrementCounter(PM_VALIDPROFILEREQ_TOTAL);
  2681. }
  2682. else
  2683. {
  2684. _ASSERT(g_pPerf);
  2685. }
  2686. }
  2687. return hr;
  2688. }
  2689. //===========================================================================
  2690. //
  2691. // put_Profile -- put property in profile property bag -- obselete
  2692. //
  2693. STDMETHODIMP CManager::put_Profile(BSTR attributeName, VARIANT newVal)
  2694. {
  2695. if (!m_piProfile)
  2696. {
  2697. return E_OUTOFMEMORY;
  2698. }
  2699. PassportLog("CManager::put_Profile: %ws\r\n", attributeName);
  2700. return m_piProfile->put_Attribute(attributeName,newVal);
  2701. }
  2702. //===========================================================================
  2703. //
  2704. // get_HexPUID
  2705. //
  2706. STDMETHODIMP CManager::get_HexPUID(BSTR *pVal)
  2707. {
  2708. PassportLog("CManager::get_HexPUID:\r\n");
  2709. if(!pVal) return E_INVALIDARG;
  2710. if (!m_piTicket)
  2711. {
  2712. return E_OUTOFMEMORY;
  2713. }
  2714. if(m_piTicket)
  2715. return m_piTicket->get_MemberId(pVal);
  2716. else
  2717. {
  2718. AtlReportError(CLSID_Manager, PP_E_INVALID_TICKETSTR,
  2719. IID_IPassportManager, PP_E_INVALID_TICKET);
  2720. return PP_E_INVALID_TICKET;
  2721. }
  2722. }
  2723. //===========================================================================
  2724. //
  2725. // get_PUID
  2726. //
  2727. STDMETHODIMP CManager::get_PUID(BSTR *pVal)
  2728. {
  2729. PassportLog("CManager::get_HexPUID:\r\n");
  2730. if(!pVal) return E_INVALIDARG;
  2731. if(m_piTicket)
  2732. {
  2733. HRESULT hr = S_OK;
  2734. WCHAR id[64] = L"0";
  2735. int l = 0;
  2736. int h = 0;
  2737. LARGE_INTEGER ui64;
  2738. hr = m_piTicket->get_MemberIdLow(&l);
  2739. if (S_OK != hr) return hr;
  2740. hr = m_piTicket->get_MemberIdHigh(&h);
  2741. if (S_OK != hr) return hr;
  2742. ui64.HighPart = h;
  2743. ui64.LowPart = l;
  2744. _ui64tow(ui64.QuadPart, id, 10);
  2745. *pVal = SysAllocString(id);
  2746. if(*pVal == NULL)
  2747. {
  2748. hr = E_OUTOFMEMORY;
  2749. }
  2750. return hr;
  2751. }
  2752. else
  2753. {
  2754. AtlReportError(CLSID_Manager, PP_E_INVALID_TICKETSTR,
  2755. IID_IPassportManager, PP_E_INVALID_TICKET);
  2756. return PP_E_INVALID_TICKET;
  2757. }
  2758. }
  2759. STDMETHODIMP CManager::get_Option(
  2760. /* [in] */ BSTR name,
  2761. /* [retval][out] */ VARIANT *pVal)
  2762. {
  2763. if (!name || _wcsicmp(name, L"iMode") != 0 || !pVal)
  2764. return E_INVALIDARG;
  2765. VariantCopy(pVal, (VARIANT*)&m_iModeOption);
  2766. return S_OK;
  2767. }
  2768. STDMETHODIMP CManager::put_Option(
  2769. /* [in] */ BSTR name,
  2770. /* [in] */ VARIANT newVal)
  2771. {
  2772. // support only this option for now.
  2773. if (!name || _wcsicmp(name, L"iMode") != 0)
  2774. return E_INVALIDARG;
  2775. m_iModeOption = newVal;
  2776. return S_OK;
  2777. }
  2778. //===========================================================================
  2779. //
  2780. // get_Ticket -- get new introduced ticket property from the bag.
  2781. //
  2782. STDMETHODIMP CManager::get_Ticket(BSTR attributeName, VARIANT *pVal)
  2783. {
  2784. if (!m_piTicket)
  2785. {
  2786. return E_OUTOFMEMORY;
  2787. }
  2788. return m_piTicket->GetProperty(attributeName,pVal);
  2789. }
  2790. //===========================================================================
  2791. //
  2792. // LogoutURL -- returns LogoutURL with given parameters
  2793. //
  2794. STDMETHODIMP CManager::LogoutURL(
  2795. /* [optional][in] */ VARIANT vRU,
  2796. /* [optional][in] */ VARIANT vCoBrand,
  2797. /* [optional][in] */ VARIANT lang_id,
  2798. /* [optional][in] */ VARIANT Namespace,
  2799. /* [optional][in] */ VARIANT bSecure,
  2800. /* [retval][out] */ BSTR __RPC_FAR *pVal)
  2801. {
  2802. HRESULT hr = S_OK;
  2803. VARIANT_BOOL bUseSecure = VARIANT_FALSE;
  2804. BSTR CBT = NULL, returnUrl = NULL, bstrNameSpace = NULL;
  2805. int hasCB, hasRU, hasLCID, hasNameSpace, hasUseSec;
  2806. USHORT Lang;
  2807. WCHAR nameSpace[MAX_PATH] = L"";
  2808. bool bUrlFromSecureKey = false;
  2809. WCHAR UrlBuf[MAX_URL_LENGTH] = L"";
  2810. WCHAR retUrlBuf[MAX_URL_LENGTH] = L"";
  2811. DWORD bufLen = MAX_URL_LENGTH;
  2812. WCHAR qsLeadCh = L'?';
  2813. CNexusConfig* cnc = NULL;
  2814. int iRet = 0;
  2815. if (!pVal) return E_INVALIDARG;
  2816. if (!g_config)
  2817. {
  2818. return PP_E_NOT_CONFIGURED;
  2819. }
  2820. cnc = g_config->checkoutNexusConfig();
  2821. if (!m_pRegistryConfig)
  2822. m_pRegistryConfig = g_config->checkoutRegistryConfig();
  2823. if ((hasUseSec = GetBoolArg(bSecure, &bUseSecure)) == CV_BAD)
  2824. {
  2825. hr = E_INVALIDARG;
  2826. goto Cleanup;
  2827. }
  2828. if ((hasLCID = GetShortArg(lang_id,&Lang)) == CV_BAD)
  2829. {
  2830. hr = E_INVALIDARG;
  2831. goto Cleanup;
  2832. }
  2833. if (hasLCID == CV_DEFAULT)
  2834. Lang = m_pRegistryConfig->getDefaultLCID();
  2835. hasCB = GetBstrArg(vCoBrand, &CBT);
  2836. if (hasCB == CV_BAD)
  2837. {
  2838. hr = E_INVALIDARG;
  2839. goto Cleanup;
  2840. }
  2841. hasRU = GetBstrArg(vRU, &returnUrl);
  2842. if (hasRU == CV_BAD)
  2843. {
  2844. hr = E_INVALIDARG;
  2845. goto Cleanup;
  2846. }
  2847. hasNameSpace = GetBstrArg(Namespace, &bstrNameSpace);
  2848. if (hasNameSpace == CV_BAD)
  2849. {
  2850. hr = E_INVALIDARG;
  2851. goto Cleanup;
  2852. }
  2853. // get the right URL -- namespace, secure
  2854. // namespace
  2855. if (!IsEmptyString(bstrNameSpace))
  2856. {
  2857. if(0 == _snwprintf(nameSpace, sizeof(nameSpace) / sizeof(WCHAR), L"%s", bstrNameSpace))
  2858. {
  2859. hr = HRESULT_FROM_WIN32(GetLastError());
  2860. if FAILED(hr)
  2861. goto Cleanup;
  2862. }
  2863. }
  2864. if (hasCB == CV_DEFAULT)
  2865. CBT = m_pRegistryConfig->getDefaultCoBrand();
  2866. if (hasRU == CV_DEFAULT)
  2867. returnUrl = m_pRegistryConfig->getDefaultRU();
  2868. if (returnUrl == NULL)
  2869. returnUrl = L"";
  2870. if (*nameSpace == 0) // 0 length string
  2871. wcscpy(nameSpace, L"Default");
  2872. if(hasUseSec == CV_DEFAULT)
  2873. {
  2874. ULONG ulSecureLevel = m_pRegistryConfig->getSecureLevel();
  2875. bUseSecure = (SECURELEVEL_USE_HTTPS(ulSecureLevel)) ? VARIANT_TRUE : VARIANT_FALSE;
  2876. }
  2877. // secure
  2878. if(bUseSecure == VARIANT_TRUE)
  2879. {
  2880. cnc->getDomainAttribute(nameSpace,
  2881. L"LogoutSecure",
  2882. sizeof(UrlBuf)/sizeof(WCHAR),
  2883. UrlBuf,
  2884. Lang);
  2885. if (*UrlBuf != 0)
  2886. {
  2887. bUrlFromSecureKey = true;
  2888. }
  2889. }
  2890. // insecure
  2891. if (*UrlBuf == 0)
  2892. {
  2893. cnc->getDomainAttribute(nameSpace,
  2894. L"Logout",
  2895. sizeof(UrlBuf)/sizeof(WCHAR),
  2896. UrlBuf,
  2897. Lang);
  2898. }
  2899. // error case
  2900. if(*UrlBuf == 0)
  2901. {
  2902. AtlReportError(CLSID_Profile, PP_E_LOGOUTURL_NOTDEFINEDSTR,
  2903. IID_IPassportProfile, PP_E_LOGOUTURL_NOTDEFINED);
  2904. hr = PP_E_LOGOUTURL_NOTDEFINED;
  2905. goto Cleanup;
  2906. }
  2907. if(bUseSecure == VARIANT_TRUE && !bUrlFromSecureKey) // translate from http to https
  2908. {
  2909. if (_wcsnicmp(UrlBuf, L"http:", 5) == 0) // replace with HTTPS
  2910. {
  2911. memmove(UrlBuf + 5, UrlBuf + 4, sizeof(UrlBuf) - 5 * sizeof(WCHAR));
  2912. memcpy(UrlBuf, L"https", 5 * sizeof(WCHAR));
  2913. }
  2914. }
  2915. // us common function to append the thing one by one ...
  2916. if (wcsstr(UrlBuf, L"?")) // ? already exists in the URL, use & to start
  2917. qsLeadCh = L'&';
  2918. if (CBT)
  2919. _snwprintf(retUrlBuf, sizeof(retUrlBuf) / sizeof(WCHAR), L"%s%cid=%-d&ru=%s&lcid=%-d&cb=%s",
  2920. UrlBuf, qsLeadCh, m_pRegistryConfig->getSiteId(), returnUrl, Lang, CBT);
  2921. else
  2922. _snwprintf(retUrlBuf, sizeof(retUrlBuf) / sizeof(WCHAR), L"%s%cid=%-d&ru=%s&lcid=%-d",
  2923. UrlBuf, qsLeadCh, m_pRegistryConfig->getSiteId(), returnUrl, Lang);
  2924. *pVal = ALLOC_AND_GIVEAWAY_BSTR(retUrlBuf);
  2925. Cleanup:
  2926. if (NULL != cnc)
  2927. {
  2928. cnc->Release();
  2929. }
  2930. return hr;
  2931. }
  2932. //===========================================================================
  2933. //
  2934. // get_ProfileByIndex -- get property value by index of the property
  2935. //
  2936. STDMETHODIMP CManager::get_ProfileByIndex(int index, VARIANT *pVal)
  2937. {
  2938. HRESULT hr = m_piProfile->get_ByIndex(index,pVal);
  2939. if(hr == S_OK && pVal->vt != VT_EMPTY)
  2940. {
  2941. if(g_pPerf)
  2942. {
  2943. g_pPerf->incrementCounter(PM_VALIDPROFILEREQ_SEC);
  2944. g_pPerf->incrementCounter(PM_VALIDPROFILEREQ_TOTAL);
  2945. }
  2946. else
  2947. {
  2948. _ASSERT(g_pPerf);
  2949. }
  2950. }
  2951. return hr;
  2952. }
  2953. //===========================================================================
  2954. //
  2955. // put_ProfileByIndex -- put property value by index
  2956. //
  2957. STDMETHODIMP CManager::put_ProfileByIndex(int index, VARIANT newVal)
  2958. {
  2959. return m_piProfile->put_ByIndex(index,newVal);
  2960. }
  2961. //===========================================================================
  2962. //
  2963. // handleQueryStringData -- authenticate with T & P from Query String
  2964. //
  2965. BOOL CManager::handleQueryStringData(BSTR a, BSTR p)
  2966. {
  2967. BOOL retVal; //whither to set cookies
  2968. HRESULT hr;
  2969. VARIANT vFalse;
  2970. _variant_t vFlags;
  2971. //
  2972. // check for empty ticket
  2973. //
  2974. if (!a || !*a)
  2975. return FALSE;
  2976. if (!m_piTicket || !m_piProfile)
  2977. {
  2978. return FALSE;
  2979. }
  2980. hr = DecryptTicketAndProfile(a, p, FALSE, NULL, m_pRegistryConfig, m_piTicket, m_piProfile);
  2981. if(hr != S_OK)
  2982. {
  2983. m_ticketValid = VARIANT_FALSE;
  2984. m_profileValid = VARIANT_FALSE;
  2985. retVal = FALSE;
  2986. goto Cleanup;
  2987. }
  2988. VariantInit(&vFalse);
  2989. vFalse.vt = VT_BOOL;
  2990. vFalse.boolVal = VARIANT_FALSE;
  2991. m_piTicket->get_IsAuthenticated(0,
  2992. VARIANT_FALSE,
  2993. vFalse,
  2994. &m_ticketValid);
  2995. if(!m_bSecureTransported) // secure bit should NOI set
  2996. {
  2997. if (S_OK == m_piTicket->GetProperty(ATTR_PASSPORTFLAGS, &vFlags))
  2998. { // the bit should NOT set
  2999. if ( vFlags.vt == VT_I4 && (vFlags.lVal & k_ulFlagsSecuredTransportedTicket) != 0)
  3000. m_ticketValid = VARIANT_FALSE;
  3001. }
  3002. }
  3003. // let the ticket to valid if secure signin
  3004. if(m_ticketValid)
  3005. m_piTicket->DoSecureCheckInTicket(m_bSecureTransported);
  3006. // profile stuff
  3007. m_piProfile->get_IsValid(&m_profileValid);
  3008. if (m_ticketValid)
  3009. {
  3010. m_fromQueryString = true;
  3011. // Set the cookies
  3012. if (!m_pRegistryConfig->setCookiesP())
  3013. {
  3014. retVal = FALSE;
  3015. goto Cleanup;
  3016. }
  3017. }
  3018. else
  3019. {
  3020. retVal = FALSE;
  3021. goto Cleanup;
  3022. }
  3023. retVal = TRUE;
  3024. Cleanup:
  3025. return retVal;
  3026. }
  3027. //===========================================================================
  3028. //
  3029. // handleCookieData -- authenticate with cookies
  3030. //
  3031. BOOL CManager::handleCookieData(
  3032. BSTR auth,
  3033. BSTR prof,
  3034. BSTR consent,
  3035. BSTR secAuth
  3036. )
  3037. {
  3038. BOOL retVal;
  3039. HRESULT hr;
  3040. VARIANT vDoSecureCheck;
  3041. VARIANT_BOOL bValid;
  3042. _variant_t vFlags;
  3043. // bail out on empty cookie
  3044. if (!auth || !*auth)
  3045. return FALSE;
  3046. if (!m_piTicket || !m_piProfile)
  3047. {
  3048. return FALSE;
  3049. }
  3050. // the consent cookie
  3051. if(consent != NULL && SysStringLen(consent) != 0)
  3052. {
  3053. hr = DecryptTicketAndProfile( auth,
  3054. prof,
  3055. !(m_pRegistryConfig->bInDA()),
  3056. consent,
  3057. m_pRegistryConfig,
  3058. m_piTicket,
  3059. m_piProfile);
  3060. }
  3061. else
  3062. {
  3063. //
  3064. // If regular cookie domain/path is identical to consent cookie domain/path, then
  3065. // MSPProf cookie is equivalent to consent cookie, and we should set m_bUsingConsentCookie
  3066. // to true
  3067. //
  3068. BOOL bCheckConsentCookie = (
  3069. lstrcmpA(m_pRegistryConfig->getTicketDomain(), m_pRegistryConfig->getProfileDomain())
  3070. || lstrcmpA(m_pRegistryConfig->getTicketPath(), m_pRegistryConfig->getProfilePath())
  3071. );
  3072. hr = DecryptTicketAndProfile( auth,
  3073. prof,
  3074. !(m_pRegistryConfig->bInDA()) && bCheckConsentCookie,
  3075. NULL,
  3076. m_pRegistryConfig,
  3077. m_piTicket,
  3078. m_piProfile);
  3079. }
  3080. if(hr != S_OK)
  3081. {
  3082. m_ticketValid = VARIANT_FALSE;
  3083. m_profileValid = VARIANT_FALSE;
  3084. retVal = FALSE;
  3085. goto Cleanup;
  3086. }
  3087. VariantInit(&vDoSecureCheck);
  3088. vDoSecureCheck.vt = VT_BOOL;
  3089. if(secAuth && secAuth[0] && m_bSecureTransported)
  3090. {
  3091. if(DoSecureCheck(secAuth, m_pRegistryConfig, m_piTicket) == S_OK)
  3092. vDoSecureCheck.boolVal = VARIANT_TRUE;
  3093. else
  3094. vDoSecureCheck.boolVal = VARIANT_FALSE;
  3095. }
  3096. else
  3097. vDoSecureCheck.boolVal = VARIANT_FALSE;
  3098. m_piTicket->get_IsAuthenticated(0,
  3099. VARIANT_FALSE,
  3100. vDoSecureCheck,
  3101. &m_ticketValid);
  3102. // a partner cookie should not include the secure bit
  3103. if (!m_pRegistryConfig->bInDA() && S_OK == m_piTicket->GetProperty(ATTR_PASSPORTFLAGS, &vFlags))
  3104. { // the bit should NOT set
  3105. if ( vFlags.vt == VT_I4 && (vFlags.lVal & k_ulFlagsSecuredTransportedTicket) != 0)
  3106. m_ticketValid = VARIANT_FALSE;
  3107. }
  3108. // for insecure case, the secure cookie should not come
  3109. if(!m_bSecureTransported && (secAuth && secAuth[0])) // this should not come
  3110. {
  3111. m_ticketValid = VARIANT_FALSE;
  3112. }
  3113. // profile stuff
  3114. m_piProfile->get_IsValid(&m_profileValid);
  3115. if(!m_ticketValid)
  3116. {
  3117. retVal = FALSE;
  3118. goto Cleanup;
  3119. }
  3120. retVal = TRUE;
  3121. Cleanup:
  3122. return retVal;
  3123. }
  3124. //===========================================================================
  3125. //
  3126. // get_HasSavedPassword -- if users chooses to persiste cookies
  3127. //
  3128. STDMETHODIMP CManager::get_HasSavedPassword(VARIANT_BOOL *pVal)
  3129. {
  3130. if (!m_piTicket)
  3131. {
  3132. return E_OUTOFMEMORY;
  3133. }
  3134. PassportLog("CManager::get_HasSavedPassword:\r\n");
  3135. // TODO: using flags for this
  3136. return m_piTicket->get_HasSavedPassword(pVal);
  3137. }
  3138. //===========================================================================
  3139. //
  3140. // Commit -- post changes of profile back to the cookie
  3141. //
  3142. STDMETHODIMP CManager::Commit(BSTR *pNewProfileCookie)
  3143. {
  3144. PassportLog("CManager::Commit:\r\n");
  3145. if (!g_config) // Guarantees config is non-null
  3146. {
  3147. AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
  3148. IID_IPassportManager, PP_E_NOT_CONFIGURED);
  3149. return PP_E_NOT_CONFIGURED;
  3150. }
  3151. if (!m_pRegistryConfig)
  3152. m_pRegistryConfig = g_config->checkoutRegistryConfig();
  3153. if (!g_config->isValid() || !m_pRegistryConfig) // Guarantees config is non-null
  3154. {
  3155. AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
  3156. IID_IPassportManager, PP_E_NOT_CONFIGURED);
  3157. return PP_E_NOT_CONFIGURED;
  3158. }
  3159. if (!m_piTicket || !m_piProfile)
  3160. {
  3161. return E_OUTOFMEMORY;
  3162. }
  3163. if (!m_ticketValid || !m_profileValid)
  3164. {
  3165. AtlReportError(CLSID_Manager, PP_E_IT_FOR_COMMITSTR,
  3166. IID_IPassportManager, PP_E_INVALID_TICKET);
  3167. return PP_E_INVALID_TICKET;
  3168. }
  3169. // Write new passport profile cookie...
  3170. // return a safearray if we aren't used from ASP
  3171. BSTR newP = NULL;
  3172. HRESULT hr = m_piProfile->incrementVersion();
  3173. hr = m_piProfile->get_unencryptedProfile(&newP);
  3174. TAKEOVER_BSTR(newP);
  3175. if (hr != S_OK || newP == NULL)
  3176. {
  3177. AtlReportError(CLSID_Manager,
  3178. L"PassportManager.Commit: unknown failure.",
  3179. IID_IPassportManager, E_FAIL);
  3180. return E_FAIL;
  3181. }
  3182. CCoCrypt* crypt = NULL;
  3183. BSTR newCH = NULL;
  3184. crypt = m_pRegistryConfig->getCurrentCrypt(); // IsValid ensures this is non-null
  3185. if ((!crypt->Encrypt(m_pRegistryConfig->getCurrentCryptVersion(),
  3186. (LPSTR)newP,
  3187. SysStringByteLen(newP),
  3188. &newCH)) ||
  3189. !newCH)
  3190. {
  3191. AtlReportError(CLSID_Manager,
  3192. L"PassportManager.Commit: encryption failure.",
  3193. IID_IPassportManager, E_FAIL);
  3194. FREE_BSTR(newP);
  3195. return E_FAIL;
  3196. }
  3197. FREE_BSTR(newP);
  3198. TAKEOVER_BSTR(newCH);
  3199. if (m_bOnStartPageCalled)
  3200. {
  3201. if (m_pRegistryConfig->setCookiesP())
  3202. {
  3203. try
  3204. {
  3205. VARIANT_BOOL persist;
  3206. _bstr_t domain;
  3207. _bstr_t path;
  3208. if (m_pRegistryConfig->getTicketPath())
  3209. path = m_pRegistryConfig->getTicketPath();
  3210. else
  3211. path = L"/";
  3212. m_piTicket->get_HasSavedPassword(&persist);
  3213. IRequestDictionaryPtr piCookies = m_piResponse->Cookies;
  3214. VARIANT vtNoParam;
  3215. VariantInit(&vtNoParam);
  3216. vtNoParam.vt = VT_ERROR;
  3217. vtNoParam.scode = DISP_E_PARAMNOTFOUND;
  3218. IWriteCookiePtr piCookie = piCookies->Item[L"MSPProf"];
  3219. piCookie->Item[vtNoParam] = newCH;
  3220. domain = m_pRegistryConfig->getTicketDomain();
  3221. if (domain.length())
  3222. piCookie->put_Domain(domain);
  3223. if (persist)
  3224. piCookie->put_Expires(g_dtExpire);
  3225. piCookie->put_Path(path);
  3226. }
  3227. catch (...)
  3228. {
  3229. FREE_BSTR(newCH);
  3230. return E_FAIL;
  3231. }
  3232. }
  3233. }
  3234. GIVEAWAY_BSTR(newCH);
  3235. *pNewProfileCookie = newCH;
  3236. if(g_pPerf)
  3237. {
  3238. g_pPerf->incrementCounter(PM_PROFILECOMMITS_SEC);
  3239. g_pPerf->incrementCounter(PM_PROFILECOMMITS_TOTAL);
  3240. }
  3241. else
  3242. {
  3243. _ASSERT(g_pPerf);
  3244. }
  3245. return S_OK;
  3246. }
  3247. //===========================================================================
  3248. //
  3249. // _Ticket -- ticket object property
  3250. //
  3251. STDMETHODIMP CManager::_Ticket(IPassportTicket** piTicket)
  3252. {
  3253. if (!m_piTicket)
  3254. {
  3255. return E_OUTOFMEMORY;
  3256. }
  3257. return m_piTicket->QueryInterface(IID_IPassportTicket,(void**)piTicket);
  3258. }
  3259. //===========================================================================
  3260. //
  3261. // _Profile
  3262. //
  3263. STDMETHODIMP CManager::_Profile(IPassportProfile** piProfile)
  3264. {
  3265. return m_piProfile->QueryInterface(IID_IPassportProfile,(void**)piProfile);
  3266. }
  3267. //===========================================================================
  3268. //
  3269. // DomainExists -- if a domain exists
  3270. //
  3271. STDMETHODIMP CManager::DomainExists(
  3272. BSTR bstrDomainName,
  3273. VARIANT_BOOL* pbExists
  3274. )
  3275. {
  3276. PassportLog("CManager::DomainExists Enter:\r\n");
  3277. if(!pbExists)
  3278. return E_INVALIDARG;
  3279. if(!bstrDomainName || (bstrDomainName[0] == L'\0'))
  3280. return E_INVALIDARG;
  3281. if(!g_config || !g_config->isValid())
  3282. {
  3283. AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
  3284. IID_IPassportManager, PP_E_NOT_CONFIGURED);
  3285. return PP_E_NOT_CONFIGURED;
  3286. }
  3287. CNexusConfig* cnc = g_config->checkoutNexusConfig();
  3288. *pbExists = cnc->DomainExists(bstrDomainName) ? VARIANT_TRUE : VARIANT_FALSE;
  3289. cnc->Release();
  3290. PassportLog("CManager::DomainExists Exit:\r\n");
  3291. return S_OK;
  3292. }
  3293. //===========================================================================
  3294. //
  3295. // get_Domains -- get a list of domains
  3296. //
  3297. STDMETHODIMP CManager::get_Domains(VARIANT *pArrayVal)
  3298. {
  3299. CNexusConfig* cnc = NULL;
  3300. LPCWSTR* arr = NULL;
  3301. int iArr = 0;
  3302. HRESULT hr;
  3303. PassportLog("CManager::get_Domains Enter:\r\n");
  3304. if (!pArrayVal)
  3305. return E_INVALIDARG;
  3306. if (!g_config || !g_config->isValid()) // Guarantees config is non-null
  3307. {
  3308. AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
  3309. IID_IPassportManager, PP_E_NOT_CONFIGURED);
  3310. return PP_E_NOT_CONFIGURED;
  3311. }
  3312. cnc = g_config->checkoutNexusConfig();
  3313. arr = cnc->getDomains(&iArr);
  3314. if (!arr || iArr == 0)
  3315. {
  3316. VariantClear(pArrayVal);
  3317. hr = S_OK;
  3318. goto Cleanup;
  3319. }
  3320. // Make a safearray with all the goods
  3321. SAFEARRAYBOUND rgsabound;
  3322. rgsabound.lLbound = 0;
  3323. rgsabound.cElements = iArr;
  3324. SAFEARRAY *sa = SafeArrayCreate(VT_VARIANT, 1, &rgsabound);
  3325. if (!sa)
  3326. {
  3327. hr = E_OUTOFMEMORY;
  3328. goto Cleanup;
  3329. }
  3330. VariantInit(pArrayVal);
  3331. pArrayVal->vt = VT_ARRAY | VT_VARIANT;
  3332. pArrayVal->parray = sa;
  3333. VARIANT *vArray;
  3334. SafeArrayAccessData(sa, (void**)&vArray);
  3335. for (long i = 0; i < iArr; i++)
  3336. {
  3337. vArray[i].vt = VT_BSTR;
  3338. vArray[i].bstrVal = ALLOC_AND_GIVEAWAY_BSTR(arr[i]);
  3339. }
  3340. SafeArrayUnaccessData(sa);
  3341. hr = S_OK;
  3342. Cleanup:
  3343. if (arr)
  3344. {
  3345. delete[] arr;
  3346. }
  3347. if (NULL != cnc)
  3348. {
  3349. cnc->Release();
  3350. }
  3351. PassportLog("CManager::DomainExists Exit:\r\n");
  3352. return hr;
  3353. }
  3354. //===========================================================================
  3355. //
  3356. // get_Error -- get the error returned with &f query parameter
  3357. //
  3358. STDMETHODIMP CManager::get_Error(long* plError)
  3359. {
  3360. if(plError == NULL)
  3361. return E_INVALIDARG;
  3362. if(m_ticketValid)
  3363. {
  3364. if (!m_piTicket)
  3365. {
  3366. return E_OUTOFMEMORY;
  3367. }
  3368. m_piTicket->get_Error(plError);
  3369. if(*plError == 0)
  3370. *plError = m_lNetworkError;
  3371. }
  3372. else
  3373. {
  3374. *plError = m_lNetworkError;
  3375. }
  3376. PassportLog("CManager::get_Error: %X\r\n", *plError);
  3377. return S_OK;
  3378. }
  3379. //===========================================================================
  3380. //
  3381. // GetServerInfo
  3382. //
  3383. STDMETHODIMP CManager::GetServerInfo(BSTR *pbstrOut)
  3384. {
  3385. if (!g_config || !g_config->isValid()) // Guarantees config is non-null
  3386. {
  3387. AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
  3388. IID_IPassportManager, PP_E_NOT_CONFIGURED);
  3389. return PP_E_NOT_CONFIGURED;
  3390. }
  3391. if(!m_pRegistryConfig)
  3392. // This only happens when OnStartPage was not called first.
  3393. m_pRegistryConfig = g_config->checkoutRegistryConfig();
  3394. if (!m_pRegistryConfig)
  3395. {
  3396. AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
  3397. IID_IPassportManager, PP_E_NOT_CONFIGURED);
  3398. return PP_E_NOT_CONFIGURED;
  3399. }
  3400. CNexusConfig* cnc = g_config->checkoutNexusConfig();
  3401. BSTR bstrVersion = cnc->GetXMLInfo();
  3402. cnc->Release();
  3403. WCHAR wszName[MAX_COMPUTERNAME_LENGTH+1];
  3404. DWORD dwSize = MAX_COMPUTERNAME_LENGTH+1;
  3405. GetComputerName(wszName, &dwSize);
  3406. *pbstrOut = ALLOC_AND_GIVEAWAY_BSTR_LEN(NULL,
  3407. wcslen(wszName) + ::SysStringLen(bstrVersion) + 2);
  3408. if (NULL == *pbstrOut)
  3409. {
  3410. return E_OUTOFMEMORY;
  3411. }
  3412. wcscpy(*pbstrOut, wszName);
  3413. BSTR p = *pbstrOut + wcslen(wszName);
  3414. *p = L' ';
  3415. wcsncpy(p+1, bstrVersion, ::SysStringLen(bstrVersion) + 1);
  3416. return S_OK;
  3417. }
  3418. //===========================================================================
  3419. //
  3420. // HaveConsent -- if the user has the specified consent
  3421. //
  3422. STDMETHODIMP
  3423. CManager::HaveConsent(
  3424. VARIANT_BOOL bNeedFullConsent,
  3425. VARIANT_BOOL bNeedBirthdate,
  3426. VARIANT_BOOL* pbHaveConsent)
  3427. {
  3428. HRESULT hr;
  3429. ULONG flags = 0;
  3430. VARIANT vBdayPrecision;
  3431. BOOL bKid;
  3432. BOOL bConsentSatisfied;
  3433. ConsentStatusEnum ConsentCode = ConsentStatus_Unknown;
  3434. VARIANT_BOOL bRequireConsentCookie;
  3435. if(pbHaveConsent == NULL)
  3436. {
  3437. hr = E_POINTER;
  3438. goto Cleanup;
  3439. }
  3440. *pbHaveConsent = VARIANT_FALSE;
  3441. VariantInit(&vBdayPrecision);
  3442. if (!m_piTicket || !m_piProfile || !m_pRegistryConfig)
  3443. {
  3444. hr = E_OUTOFMEMORY;
  3445. goto Cleanup;
  3446. }
  3447. // If the cookies came in on the query string then there is no consent cookie yet so don't
  3448. // require one. Otherwise check to see if the consent cookie domain or path is set
  3449. // differently than the cookie domain or path. If so (and we aren't in the DA domain) then
  3450. // the consent cookie is required.
  3451. bRequireConsentCookie = !m_fromQueryString &&
  3452. ((lstrcmpA(m_pRegistryConfig->getTicketDomain(), m_pRegistryConfig->getProfileDomain())
  3453. || lstrcmpA(m_pRegistryConfig->getTicketPath(), m_pRegistryConfig->getProfilePath()))
  3454. && !(m_pRegistryConfig->bInDA())) ? VARIANT_TRUE : VARIANT_FALSE;
  3455. //
  3456. // Get flags.
  3457. //
  3458. hr = m_piTicket->ConsentStatus(bRequireConsentCookie, &flags, &ConsentCode); // ignore return value
  3459. if (hr != S_OK)
  3460. {
  3461. hr = S_OK;
  3462. goto Cleanup;
  3463. }
  3464. // if old ticket, we get the consent info from the profile
  3465. if(ConsentCode == ConsentStatus_NotDefinedInTicket)
  3466. {
  3467. // then we get from profile
  3468. VARIANT_BOOL bValid;
  3469. CComVariant vFlags;
  3470. m_piProfile->get_IsValid(&bValid);
  3471. if(bValid == VARIANT_FALSE)
  3472. {
  3473. hr = S_OK;
  3474. goto Cleanup;
  3475. }
  3476. hr = m_piProfile->get_Attribute(L"flags", &vFlags);
  3477. if(hr != S_OK)
  3478. goto Cleanup;
  3479. bKid = ((V_I4(&vFlags) & k_ulFlagsAccountType) == k_ulFlagsAccountTypeKid);
  3480. }
  3481. else
  3482. bKid = ((flags & k_ulFlagsAccountType) == k_ulFlagsAccountTypeKid);
  3483. // we should have the flags by now
  3484. //
  3485. // Do we have the requested level of consent?
  3486. //
  3487. bConsentSatisfied = bNeedFullConsent ? (flags & 0x60) == 0x40 :
  3488. (flags & 0x60) != 0;
  3489. if(bKid)
  3490. {
  3491. *pbHaveConsent = (bConsentSatisfied) ? VARIANT_TRUE : VARIANT_FALSE;
  3492. }
  3493. else
  3494. {
  3495. //
  3496. // Make sure we have birthday if it was requested.
  3497. //
  3498. // no return value check need here, always returns S_OK.
  3499. VARIANT_BOOL bValid;
  3500. m_piProfile->get_IsValid(&bValid);
  3501. // if profile is not valid, then we don't have consent.
  3502. // return.
  3503. if(bValid == VARIANT_FALSE)
  3504. {
  3505. hr = S_OK;
  3506. goto Cleanup;
  3507. }
  3508. if(bNeedBirthdate)
  3509. {
  3510. hr = m_piProfile->get_Attribute(L"bday_precision", &vBdayPrecision);
  3511. if(hr != S_OK)
  3512. goto Cleanup;
  3513. *pbHaveConsent = (vBdayPrecision.iVal != 0 && vBdayPrecision.iVal != 3) ?
  3514. VARIANT_TRUE : VARIANT_FALSE;
  3515. }
  3516. else
  3517. *pbHaveConsent = VARIANT_TRUE;
  3518. }
  3519. hr = S_OK;
  3520. Cleanup:
  3521. VariantClear(&vBdayPrecision);
  3522. return hr;
  3523. }
  3524. //===========================================================================
  3525. //
  3526. // checkForPassportChallenge
  3527. //
  3528. //
  3529. // check the qs parameter. if challenge is requested,
  3530. // build the auth header and redirect with a modified qs
  3531. //
  3532. BOOL CManager::checkForPassportChallenge(IRequestDictionaryPtr piServerVariables)
  3533. {
  3534. BOOL fReturn = FALSE;
  3535. BSTR bstrBuf = NULL;
  3536. // just need the request string
  3537. _variant_t vtItemName, vtQueryString;
  3538. vtItemName = L"QUERY_STRING";
  3539. piServerVariables->get_Item(vtItemName, &vtQueryString);
  3540. if(vtQueryString.vt != VT_BSTR)
  3541. vtQueryString.ChangeType(VT_BSTR);
  3542. if (vtQueryString.bstrVal && *vtQueryString.bstrVal)
  3543. {
  3544. // check if pchg=1 is there. It is the first parameter ....
  3545. PWSTR psz = wcsstr(vtQueryString.bstrVal, L"pchg=1");
  3546. if (psz)
  3547. {
  3548. // we are in business. reformat the URL, insert the headers and
  3549. // redirect
  3550. psz = wcsstr(psz, PPLOGIN_PARAM);
  3551. _ASSERT(psz);
  3552. if (psz)
  3553. {
  3554. psz += wcslen(PPLOGIN_PARAM);
  3555. PWSTR pszEndLoginUrl = wcsstr(psz, L"&");
  3556. _ASSERT(pszEndLoginUrl);
  3557. if (pszEndLoginUrl)
  3558. {
  3559. *pszEndLoginUrl = L'\0';
  3560. // unescape the URL
  3561. // use temp buffer ...
  3562. DWORD cch = wcslen(psz) + 1;
  3563. bstrBuf = SysAllocStringLen(NULL, cch);
  3564. if (NULL == bstrBuf)
  3565. {
  3566. goto Cleanup;
  3567. }
  3568. if(!InternetCanonicalizeUrl(psz,
  3569. bstrBuf,
  3570. &cch,
  3571. ICU_DECODE | ICU_NO_ENCODE))
  3572. {
  3573. // what else can be done ???
  3574. _ASSERT(FALSE);
  3575. }
  3576. else
  3577. {
  3578. // copy the unescaped URL to the orig buffer
  3579. wcscpy(psz, (BSTR)bstrBuf);
  3580. // set headers first ...
  3581. // just use the qs param with some reformatting
  3582. _bstr_t bstrHeader;
  3583. if (HeaderFromQS(wcsstr(psz, L"?"), bstrHeader))
  3584. {
  3585. m_piResponse->AddHeader(L"WWW-Authenticate", bstrHeader);
  3586. // Url is ready, redirect ...
  3587. m_piResponse->Redirect(psz);
  3588. fReturn = TRUE;
  3589. }
  3590. }
  3591. }
  3592. }
  3593. }
  3594. }
  3595. Cleanup:
  3596. if (bstrBuf)
  3597. {
  3598. SysFreeString(bstrBuf);
  3599. }
  3600. return fReturn;
  3601. }
  3602. //===========================================================================
  3603. //
  3604. // HeaderFromQS
  3605. //
  3606. //
  3607. // given a queryString, format the www-authenticate header
  3608. //
  3609. BOOL
  3610. CManager::HeaderFromQS(PWSTR pszQS, _bstr_t& bstrHeader)
  3611. {
  3612. // common header start ...
  3613. bstrHeader = PASSPORT_PROT14;
  3614. BOOL fSuccess = TRUE;
  3615. BSTR signature = NULL;
  3616. // advance thru any leading junk ...
  3617. while(!iswalnum(*pszQS) && *pszQS) pszQS++;
  3618. if (!*pszQS)
  3619. {
  3620. fSuccess = FALSE;
  3621. goto Cleanup;
  3622. }
  3623. WCHAR rgszValue[1000]; // buffer large enough for most values ...
  3624. PCWSTR psz = pszQS, pszNext = pszQS;
  3625. while(TRUE)
  3626. {
  3627. // no param name is more than 10 ....
  3628. WCHAR rgszName[10];
  3629. LONG cch = sizeof(rgszName)/sizeof(WCHAR);
  3630. PCWSTR pszName = psz;
  3631. while(*pszNext && *pszNext != L'&') pszNext++;
  3632. // grab the next qsparam
  3633. // name first
  3634. while(*pszName != L'=' && pszName < pszNext) pszName++;
  3635. _ASSERT(pszName != pszNext); // this should never happen
  3636. if (pszName == pszNext)
  3637. {
  3638. // and if it does, skip this parameter and return FALSE ...
  3639. fSuccess = FALSE;
  3640. goto Cleanup;
  3641. }
  3642. else
  3643. {
  3644. PWSTR pszVal = rgszValue;
  3645. ULONG cchVal;
  3646. _ASSERT((pszName - psz) <= cch);
  3647. wcsncpy(rgszName, psz, cch - 1);
  3648. rgszName[cch - 1] = L'\0';
  3649. // next comes the value
  3650. pszName++;
  3651. cchVal = (pszNext - pszName); // note these are PWSTR pointers so the result is length in characters
  3652. if (cchVal >= (sizeof(rgszValue) / sizeof(rgszValue[0])) )
  3653. {
  3654. // have to allocate ...
  3655. pszVal = new WCHAR[cchVal + 1];
  3656. if (!pszVal)
  3657. {
  3658. fSuccess = FALSE;
  3659. goto Cleanup;
  3660. }
  3661. }
  3662. // copy the value ...
  3663. wcsncpy(pszVal, pszName, cchVal );
  3664. pszVal[cchVal] = L'\0';
  3665. // and insert in the header ...
  3666. if (psz != pszQS)
  3667. // this is not the first param
  3668. bstrHeader += L",";
  3669. else
  3670. // first separator is a space ...
  3671. bstrHeader += L" ";
  3672. bstrHeader += _bstr_t(rgszName) + L"=" + pszVal;
  3673. if (pszVal != rgszValue)
  3674. // it was alloc'd
  3675. delete[] pszVal;
  3676. } // else '=' found
  3677. // leave loop
  3678. if (!*pszNext)
  3679. break;
  3680. psz = ++pszNext;
  3681. } // while
  3682. // sign the header
  3683. // actually the signature is on the qs
  3684. HRESULT hr = PartnerHash(m_pRegistryConfig,
  3685. m_pRegistryConfig->getCurrentCryptVersion(),
  3686. pszQS,
  3687. wcslen(pszQS),
  3688. &signature);
  3689. if (S_OK == hr)
  3690. {
  3691. bstrHeader += _bstr_t(L",tpf=") + (BSTR)signature;
  3692. }
  3693. else
  3694. {
  3695. fSuccess = FALSE;
  3696. }
  3697. Cleanup:
  3698. if (signature)
  3699. {
  3700. SysFreeString(signature);
  3701. }
  3702. return fSuccess;
  3703. }
  3704. //===========================================================================
  3705. //
  3706. // FormatAuthHeaderFromParams
  3707. //
  3708. //
  3709. // format WWW-Auth from parameters
  3710. //
  3711. STDMETHODIMP CManager::FormatAuthHeaderFromParams(PCWSTR pszLoginUrl, // unused for now
  3712. PCWSTR pszRetUrl,
  3713. ULONG ulTimeWindow,
  3714. BOOL fForceLogin,
  3715. time_t ct,
  3716. PCWSTR pszCBT, // unused for now
  3717. PCWSTR pszNamespace,
  3718. int nKpp,
  3719. PWSTR pszLCID, // tweener needs the LCID
  3720. ULONG ulSecureLevel,
  3721. _bstr_t& strHeader // return result
  3722. )
  3723. {
  3724. WCHAR temp[40];
  3725. // based on the spec ...
  3726. // lcid is not really needed, however it is present when
  3727. // header is created from qs and it's used
  3728. strHeader = _bstr_t(PASSPORT_PROT14) + L" lc=" + pszLCID;
  3729. // site=
  3730. strHeader += "&id=";
  3731. _ultow(m_pRegistryConfig->getSiteId(), temp, 10);
  3732. strHeader += temp;
  3733. // rtw=
  3734. strHeader += "&tw=";
  3735. _ultow(ulTimeWindow, temp, 10);
  3736. strHeader += temp;
  3737. if (fForceLogin)
  3738. {
  3739. strHeader += _bstr_t("&fs=1");
  3740. }
  3741. if (pszNamespace && *pszNamespace)
  3742. {
  3743. strHeader += _bstr_t("&ns=") + pszNamespace;
  3744. }
  3745. // ru=
  3746. strHeader += _bstr_t("&ru=") + pszRetUrl;
  3747. // ct=
  3748. _ultow(ct, temp, 10);
  3749. strHeader += _bstr_t(L"&ct=") + temp;
  3750. // kpp
  3751. if (nKpp != -1)
  3752. {
  3753. _ultow(nKpp, temp, 10);
  3754. strHeader += _bstr_t(L"&kpp=") + temp;
  3755. }
  3756. // key version and version
  3757. _ultow(m_pRegistryConfig->getCurrentCryptVersion(), temp, 10);
  3758. strHeader += _bstr_t(L"&kv=") + temp;
  3759. strHeader += _bstr_t(L"&ver=") + GetVersionString();
  3760. // secure level
  3761. if (ulSecureLevel)
  3762. {
  3763. strHeader += _bstr_t(L"&seclog=") + _ultow(ulSecureLevel, temp, 10);
  3764. }
  3765. // sign the header
  3766. BSTR signature = NULL;
  3767. PWSTR szStart = wcsstr(strHeader, L"lc=");
  3768. HRESULT hr = PartnerHash(m_pRegistryConfig,
  3769. m_pRegistryConfig->getCurrentCryptVersion(),
  3770. szStart,
  3771. strHeader.length() - (szStart - strHeader),
  3772. &signature);
  3773. // replace '&' with ','
  3774. BSTR psz = (BSTR)strHeader;
  3775. while (*psz)
  3776. {
  3777. if (*psz == L'&') *psz = L',';
  3778. psz++;
  3779. }
  3780. if (S_OK == hr)
  3781. {
  3782. strHeader += _bstr_t(L",tpf=") + (BSTR)signature;
  3783. }
  3784. if (signature)
  3785. {
  3786. SysFreeString(signature);
  3787. }
  3788. return hr;
  3789. }
  3790. //===========================================================================
  3791. //
  3792. // GetLoginParams
  3793. //
  3794. //
  3795. // common code to parse user's parameters
  3796. // and get defaults from registry config
  3797. //
  3798. STDMETHODIMP CManager::GetLoginParams(VARIANT vRU,
  3799. VARIANT vTimeWindow,
  3800. VARIANT vForceLogin,
  3801. VARIANT vCoBrand,
  3802. VARIANT vLCID,
  3803. VARIANT vNameSpace,
  3804. VARIANT vKPP,
  3805. VARIANT vSecureLevel,
  3806. // these are the processed values
  3807. _bstr_t& strUrl,
  3808. _bstr_t& strReturnUrl,
  3809. UINT& TimeWindow,
  3810. VARIANT_BOOL& ForceLogin,
  3811. time_t& ct,
  3812. _bstr_t& strCBT,
  3813. _bstr_t& strNameSpace,
  3814. int& nKpp,
  3815. ULONG& ulSecureLevel,
  3816. PWSTR pszLCID)
  3817. {
  3818. USES_CONVERSION;
  3819. LPCWSTR url;
  3820. VARIANT freeMe;
  3821. BSTR CBT = NULL, returnUrl = NULL, bstrNameSpace = NULL;
  3822. int hasCB, hasRU, hasLCID, hasTW, hasFL, hasNameSpace, hasKPP, hasUseSec;
  3823. USHORT Lang;
  3824. CNexusConfig* cnc = NULL;
  3825. HRESULT hr = S_OK;
  3826. PassportLog("CManager::GetLoginParams Enter:\r\n");
  3827. if (!g_config) // Guarantees config is non-null
  3828. {
  3829. AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
  3830. IID_IPassportManager, PP_E_NOT_CONFIGURED);
  3831. return PP_E_NOT_CONFIGURED;
  3832. }
  3833. if (!m_pRegistryConfig)
  3834. m_pRegistryConfig = g_config->checkoutRegistryConfig();
  3835. if (!g_config->isValid() || !m_pRegistryConfig) // Guarantees config is non-null
  3836. {
  3837. AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
  3838. IID_IPassportManager, PP_E_NOT_CONFIGURED);
  3839. return PP_E_NOT_CONFIGURED;
  3840. }
  3841. // Make sure args are of the right type
  3842. if ((hasTW = GetIntArg(vTimeWindow, (int*) &TimeWindow)) == CV_BAD)
  3843. return E_INVALIDARG;
  3844. if ((hasFL = GetBoolArg(vForceLogin, &ForceLogin)) == CV_BAD)
  3845. return E_INVALIDARG;
  3846. if ((hasUseSec = GetIntArg(vSecureLevel, (int*)&ulSecureLevel)) == CV_BAD)
  3847. return E_INVALIDARG;
  3848. if ((hasLCID = GetShortArg(vLCID, &Lang)) == CV_BAD)
  3849. return E_INVALIDARG;
  3850. if ((hasKPP = GetIntArg(vKPP, &nKpp)) == CV_BAD)
  3851. return E_INVALIDARG;
  3852. hasCB = GetBstrArg(vCoBrand, &CBT);
  3853. if (hasCB == CV_BAD)
  3854. return E_INVALIDARG;
  3855. strCBT = CBT;
  3856. if (hasCB == CV_FREE)
  3857. {
  3858. TAKEOVER_BSTR(CBT);
  3859. }
  3860. hasRU = GetBstrArg(vRU, &returnUrl);
  3861. if (hasRU == CV_BAD)
  3862. {
  3863. if (hasCB == CV_FREE && CBT)
  3864. FREE_BSTR(CBT);
  3865. return E_INVALIDARG;
  3866. }
  3867. strReturnUrl = returnUrl;
  3868. if (hasRU == CV_FREE)
  3869. {
  3870. FREE_BSTR(returnUrl);
  3871. }
  3872. hasNameSpace = GetBstrArg(vNameSpace, &bstrNameSpace);
  3873. if (hasNameSpace == CV_BAD)
  3874. {
  3875. if (hasCB == CV_FREE && CBT)
  3876. FREE_BSTR(CBT);
  3877. return E_INVALIDARG;
  3878. }
  3879. if (hasNameSpace == CV_OK)
  3880. strNameSpace = bstrNameSpace;
  3881. if (hasNameSpace == CV_FREE)
  3882. {
  3883. FREE_BSTR(bstrNameSpace);
  3884. }
  3885. if (hasNameSpace == CV_DEFAULT)
  3886. {
  3887. if (NULL == m_pRegistryConfig->getNameSpace())
  3888. {
  3889. strNameSpace = L"";
  3890. }
  3891. else
  3892. {
  3893. strNameSpace = m_pRegistryConfig->getNameSpace();
  3894. }
  3895. }
  3896. if(hasUseSec == CV_DEFAULT)
  3897. ulSecureLevel = m_pRegistryConfig->getSecureLevel();
  3898. if(ulSecureLevel == VARIANT_TRUE) // special case for backward compatible
  3899. ulSecureLevel = k_iSeclevelSecureChannel;
  3900. WCHAR *szAUAttrName;
  3901. if (SECURELEVEL_USE_HTTPS(ulSecureLevel))
  3902. szAUAttrName = L"AuthSecure";
  3903. else
  3904. szAUAttrName = L"Auth";
  3905. cnc = g_config->checkoutNexusConfig();
  3906. if (hasLCID == CV_DEFAULT)
  3907. Lang = m_pRegistryConfig->getDefaultLCID();
  3908. if (hasKPP == CV_DEFAULT)
  3909. nKpp = m_pRegistryConfig->getKPP();
  3910. // convert the LCID to str for tweener ...
  3911. _itow((int)Lang, pszLCID, 10);
  3912. VariantInit(&freeMe);
  3913. // **************************************************
  3914. // Logging
  3915. if (NULL != returnUrl)
  3916. {
  3917. PassportLog(" RU = %ws\r\n", returnUrl);
  3918. }
  3919. PassportLog(" TW = %X, SL = %X, L = %d, KPP = %X\r\n", TimeWindow, ulSecureLevel, Lang, nKpp);
  3920. if (NULL != CBT)
  3921. {
  3922. PassportLog(" CBT = %ws\r\n", CBT);
  3923. }
  3924. // **************************************************
  3925. if (!m_pRegistryConfig->DisasterModeP())
  3926. {
  3927. // If I'm authenticated, get my domain specific url
  3928. WCHAR UrlBuf[MAX_URL_LENGTH];
  3929. if (m_ticketValid && m_profileValid)
  3930. {
  3931. HRESULT hr = m_piProfile->get_ByIndex(MEMBERNAME_INDEX, &freeMe);
  3932. if (hr != S_OK || freeMe.vt != VT_BSTR)
  3933. {
  3934. cnc->getDomainAttribute(L"Default",
  3935. szAUAttrName,
  3936. sizeof(UrlBuf)/sizeof(WCHAR),
  3937. UrlBuf,
  3938. Lang);
  3939. strUrl = UrlBuf;
  3940. }
  3941. else
  3942. {
  3943. LPCWSTR psz = wcsrchr(freeMe.bstrVal, L'@');
  3944. cnc->getDomainAttribute(psz ? psz+1 : L"Default",
  3945. szAUAttrName,
  3946. sizeof(UrlBuf)/sizeof(WCHAR),
  3947. UrlBuf,
  3948. Lang);
  3949. strUrl = UrlBuf;
  3950. }
  3951. }
  3952. if (strUrl.length() == 0)
  3953. {
  3954. cnc->getDomainAttribute(L"Default",
  3955. szAUAttrName,
  3956. sizeof(UrlBuf)/sizeof(WCHAR),
  3957. UrlBuf,
  3958. Lang);
  3959. strUrl = UrlBuf;
  3960. }
  3961. }
  3962. else
  3963. strUrl = m_pRegistryConfig->getDisasterUrl();
  3964. _ASSERT(strUrl.length() != 0);
  3965. time(&ct);
  3966. if (hasTW == CV_DEFAULT)
  3967. TimeWindow = m_pRegistryConfig->getDefaultTicketAge();
  3968. if (hasFL == CV_DEFAULT)
  3969. ForceLogin = m_pRegistryConfig->forceLoginP() ? VARIANT_TRUE : VARIANT_FALSE;
  3970. if (hasCB == CV_DEFAULT)
  3971. strCBT = m_pRegistryConfig->getDefaultCoBrand();
  3972. if (hasRU == CV_DEFAULT)
  3973. strReturnUrl = m_pRegistryConfig->getDefaultRU() ?
  3974. m_pRegistryConfig->getDefaultRU() : L"";
  3975. if ((TimeWindow != 0 && TimeWindow < PPM_TIMEWINDOW_MIN) || TimeWindow > PPM_TIMEWINDOW_MAX)
  3976. {
  3977. AtlReportError(CLSID_Manager, (LPCOLESTR) PP_E_INVALID_TIMEWINDOWSTR,
  3978. IID_IPassportManager, PP_E_INVALID_TIMEWINDOW);
  3979. hr = PP_E_INVALID_TIMEWINDOW;
  3980. goto Cleanup;
  3981. }
  3982. Cleanup:
  3983. if (NULL != cnc)
  3984. {
  3985. cnc->Release();
  3986. }
  3987. VariantClear(&freeMe);
  3988. PassportLog("CManager::GetLoginParams Exit: %X\r\n", hr);
  3989. return hr;
  3990. }
  3991. //===========================================================================
  3992. //
  3993. // GetTicketAndProfileFromHeader
  3994. //
  3995. //
  3996. // get ticket & profile from auth header
  3997. // params:
  3998. // AuthHeader - [in/out] contents of HTTP_Authorization header
  3999. // pszTicket - [out] ptr to the ticket part in the header
  4000. // pszProfile -[out] ptr to the profile
  4001. // pwszF - [out] ptr to error coming in the header
  4002. // Auth header contents is changed as a side effect of the function
  4003. //
  4004. static VOID GetTicketAndProfileFromHeader(PWSTR pszAuthHeader,
  4005. PWSTR& pszTicket,
  4006. PWSTR& pszProfile,
  4007. PWSTR& pszF)
  4008. {
  4009. // check for t=, p=, and f=
  4010. if (pszAuthHeader && *pszAuthHeader)
  4011. {
  4012. // format is 'Authorization: from-PP='t=xxx&p=xxx'
  4013. PWSTR pwsz = wcsstr(pszAuthHeader, L"from-PP");
  4014. if (pwsz)
  4015. {
  4016. // ticket and profile are enclosed in ''. Not very strict parsing indeed ....
  4017. while(*pwsz != L'\'' && *pwsz)
  4018. pwsz++;
  4019. if (*pwsz++)
  4020. {
  4021. if (*pwsz == L'f')
  4022. {
  4023. pwsz++;
  4024. if (*pwsz == L'=')
  4025. {
  4026. pwsz++;
  4027. // error case
  4028. pszF = pwsz;
  4029. }
  4030. }
  4031. else
  4032. {
  4033. // ticket and profile ...
  4034. _ASSERT(*pwsz == L't');
  4035. if (*pwsz == L't')
  4036. {
  4037. pwsz++;
  4038. if (*pwsz == L'=')
  4039. {
  4040. pwsz++;
  4041. pszTicket = pwsz;
  4042. }
  4043. }
  4044. while(*pwsz != L'&' && *pwsz)
  4045. pwsz++;
  4046. if (*pwsz)
  4047. *pwsz++ = L'\0';
  4048. if (*pwsz == L'p')
  4049. {
  4050. pwsz++;
  4051. if (*pwsz == L'=')
  4052. {
  4053. pwsz++;
  4054. pszProfile = pwsz;
  4055. }
  4056. }
  4057. // finally remove the last '
  4058. }
  4059. // set \0 terminator
  4060. while(*pwsz != L'\'' && *pwsz)
  4061. pwsz++;
  4062. if (*pwsz)
  4063. *pwsz = L'\0';
  4064. }
  4065. }
  4066. }
  4067. }
  4068. /////////////////////////////////////////////////////////////////////////////
  4069. // IPassportService implementation
  4070. //===========================================================================
  4071. //
  4072. // Initialize
  4073. //
  4074. STDMETHODIMP CManager::Initialize(BSTR configfile, IServiceProvider* p)
  4075. {
  4076. HRESULT hr;
  4077. // Initialized?
  4078. if (!g_config || !g_config->isValid()) // This calls UpdateNow if not yet initialized.
  4079. {
  4080. AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
  4081. IID_IPassportService, PP_E_NOT_CONFIGURED);
  4082. hr = PP_E_NOT_CONFIGURED;
  4083. goto Cleanup;
  4084. }
  4085. hr = S_OK;
  4086. Cleanup:
  4087. return hr;
  4088. }
  4089. //===========================================================================
  4090. //
  4091. // Shutdown
  4092. //
  4093. STDMETHODIMP CManager::Shutdown()
  4094. {
  4095. return S_OK;
  4096. }
  4097. //===========================================================================
  4098. //
  4099. // ReloadState
  4100. //
  4101. STDMETHODIMP CManager::ReloadState(IServiceProvider*)
  4102. {
  4103. HRESULT hr;
  4104. // Initialize.
  4105. if(!g_config || !g_config->PrepareUpdate(TRUE))
  4106. {
  4107. AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
  4108. IID_IPassportService, PP_E_NOT_CONFIGURED);
  4109. hr = PP_E_NOT_CONFIGURED;
  4110. goto Cleanup;
  4111. }
  4112. hr = S_OK;
  4113. Cleanup:
  4114. return hr;
  4115. }
  4116. //===========================================================================
  4117. //
  4118. // CommitState
  4119. //
  4120. STDMETHODIMP CManager::CommitState(IServiceProvider*)
  4121. {
  4122. HRESULT hr;
  4123. // Finish the two phase update.
  4124. if(!g_config || !g_config->CommitUpdate())
  4125. {
  4126. AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
  4127. IID_IPassportService, PP_E_NOT_CONFIGURED);
  4128. hr = PP_E_NOT_CONFIGURED;
  4129. goto Cleanup;
  4130. }
  4131. hr = S_OK;
  4132. Cleanup:
  4133. return hr;
  4134. }
  4135. //===========================================================================
  4136. //
  4137. // DumpState
  4138. //
  4139. STDMETHODIMP CManager::DumpState(BSTR* pbstrState)
  4140. {
  4141. ATLASSERT( *pbstrState != NULL &&
  4142. "CManager:DumpState - "
  4143. "Are you sure you want to hand me a non-null BSTR?" );
  4144. if(!g_config)
  4145. {
  4146. return PP_E_NOT_CONFIGURED;
  4147. }
  4148. g_config->Dump(pbstrState);
  4149. return S_OK;
  4150. }