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
4859 lines
142 KiB
/**********************************************************************/
|
|
/** Microsoft Passport **/
|
|
/** Copyright(c) Microsoft Corporation, 1999 - 2001 **/
|
|
/**********************************************************************/
|
|
|
|
/*
|
|
manager.cpp
|
|
COM object for manager interface
|
|
|
|
|
|
FILE HISTORY:
|
|
|
|
*/
|
|
|
|
|
|
// Manager.cpp : Implementation of CManager
|
|
#include "stdafx.h"
|
|
#include <httpext.h>
|
|
#include "Manager.h"
|
|
#include <httpfilt.h>
|
|
#include <time.h>
|
|
#include <malloc.h>
|
|
#include <wininet.h>
|
|
|
|
#include <nsconst.h>
|
|
#include "VariantUtils.h"
|
|
#include "HelperFuncs.h"
|
|
#include "RegistryConfig.h"
|
|
#include "PassportService_i.c"
|
|
#include "atlbase.h"
|
|
|
|
PWSTR GetVersionString();
|
|
|
|
//using namespace ATL;
|
|
|
|
// gmarks
|
|
#include "Monitoring.h"
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CManager
|
|
|
|
#include "passporttypes.h"
|
|
|
|
// static utility func
|
|
static VOID GetTicketAndProfileFromHeader(PWSTR pszAuthHeader,
|
|
PWSTR& pszTicket,
|
|
PWSTR& pszProfile,
|
|
PWSTR& pszF);
|
|
|
|
// Used for cookie expiration.
|
|
const DATE g_dtExpire = 365*137;
|
|
const DATE g_dtExpired = 365*81;
|
|
|
|
|
|
//===========================================================================
|
|
//
|
|
// CManager
|
|
//
|
|
CManager::CManager() :
|
|
m_fromQueryString(false), m_ticketValid(VARIANT_FALSE),
|
|
m_profileValid(VARIANT_FALSE), m_lNetworkError(0),
|
|
m_pRegistryConfig(NULL), m_pECB(NULL), m_pFC(NULL),
|
|
m_bIsTweenerCapable(FALSE),
|
|
m_bSecureTransported(false)
|
|
{
|
|
PPTraceFuncV func(PPTRACE_FUNC, "CManager");
|
|
|
|
|
|
// ticket object
|
|
m_pUnkMarshaler = NULL;
|
|
try
|
|
{
|
|
m_piTicket = new CComObject<CTicket>();
|
|
}
|
|
catch(...)
|
|
{
|
|
m_piTicket = NULL;
|
|
}
|
|
if(m_piTicket)
|
|
m_piTicket->AddRef();
|
|
|
|
// profile object
|
|
try
|
|
{
|
|
m_piProfile = new CComObject<CProfile>();
|
|
}
|
|
catch(...)
|
|
{
|
|
m_piProfile = NULL;
|
|
}
|
|
|
|
if(m_piProfile)
|
|
m_piProfile->AddRef();
|
|
|
|
m_bOnStartPageCalled = false;
|
|
|
|
}
|
|
|
|
|
|
//===========================================================================
|
|
//
|
|
// ~CManager
|
|
//
|
|
CManager::~CManager()
|
|
{
|
|
PPTraceFuncV func(PPTRACE_FUNC, "~CManager");
|
|
if(m_pRegistryConfig)
|
|
m_pRegistryConfig->Release();
|
|
if (m_piTicket) m_piTicket->Release();
|
|
if (m_piProfile) m_piProfile->Release();
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// IfConsentCookie -- if a consent cookie should be sent back
|
|
// return value: S_OK -- has consent cookie; S_FALSE -- no consent cookie
|
|
// output param: The consent cookie
|
|
//
|
|
HRESULT CManager::IfConsentCookie(BSTR* pMSPConsent)
|
|
{
|
|
BSTR bstrRawConsent = NULL;
|
|
|
|
HRESULT hr = S_FALSE;
|
|
PPTraceFunc<HRESULT>
|
|
func(
|
|
PPTRACE_FUNC,
|
|
hr,
|
|
"IfConsentCookie"," <<<< %lx",
|
|
pMSPConsent
|
|
);
|
|
|
|
if (!m_piTicket || !m_piProfile || !m_pRegistryConfig)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
LPCSTR domain = m_pRegistryConfig->getTicketDomain();
|
|
LPCSTR path = m_pRegistryConfig->getTicketPath();
|
|
LPCSTR tertiaryDomain = m_pRegistryConfig->getProfileDomain();
|
|
LPCSTR tertiaryPath = m_pRegistryConfig->getProfilePath();
|
|
|
|
if (!tertiaryPath) tertiaryPath = "/";
|
|
|
|
if(!domain) domain = "";
|
|
if(!path) path = "";
|
|
|
|
if(!tertiaryDomain) tertiaryDomain = "";
|
|
if(!tertiaryPath) tertiaryPath = "";
|
|
|
|
//
|
|
// if a separate consent cookie is necessary
|
|
if((lstrcmpiA(domain, tertiaryDomain) || lstrcmpiA(path, tertiaryPath)) &&
|
|
(m_piTicket->GetPassportFlags() & k_ulFlagsConsentCookieNeeded) &&
|
|
!m_pRegistryConfig->bInDA() )
|
|
{
|
|
if (pMSPConsent == NULL) // no output param
|
|
hr = S_OK;
|
|
else
|
|
{
|
|
*pMSPConsent = NULL;
|
|
|
|
CCoCrypt* crypt = m_pRegistryConfig->getCurrentCrypt();
|
|
if (!crypt)
|
|
{
|
|
hr = E_FAIL;
|
|
goto Cleanup;
|
|
}
|
|
|
|
// get the consent cookie from ticket
|
|
hr = m_piTicket->get_unencryptedCookie(CTicket::MSPConsent, 0, &bstrRawConsent);
|
|
if (FAILED(hr))
|
|
goto Cleanup;
|
|
|
|
// encrypt it with partner's key
|
|
if (!crypt->Encrypt(m_pRegistryConfig->getCurrentCryptVersion(),
|
|
(LPSTR)bstrRawConsent,
|
|
SysStringByteLen(bstrRawConsent),
|
|
pMSPConsent))
|
|
{
|
|
hr = E_FAIL;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
}
|
|
|
|
Cleanup:
|
|
if (bstrRawConsent)
|
|
{
|
|
SysFreeString(bstrRawConsent);
|
|
}
|
|
|
|
if(pMSPConsent)
|
|
PPTracePrint(PPTRACE_RAW, ">>> pMSPConsent:%ws", PPF_WCHAR(*pMSPConsent));
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//===========================================================================
|
|
//
|
|
// IfAlterAuthCookie
|
|
//
|
|
// return S_OK -- when auth cookie is different from t (altered), should use
|
|
// the cookie and secAuth cookie returned
|
|
// S_FALSE -- not altered -- can use the t as auth cookie
|
|
// if MSPSecAuth != NULL, write the secure cookie
|
|
HRESULT CManager::IfAlterAuthCookie(BSTR* pMSPAuth, BSTR* pMSPSecAuth)
|
|
{
|
|
_ASSERT(pMSPAuth && pMSPSecAuth);
|
|
|
|
*pMSPAuth = NULL;
|
|
*pMSPSecAuth = NULL;
|
|
|
|
HRESULT hr = S_FALSE;
|
|
|
|
PPTraceFunc<HRESULT> func(PPTRACE_FUNC, hr,
|
|
"IfAlterAuthCookie", "<<< %lx, %lx",
|
|
pMSPAuth, pMSPSecAuth);
|
|
|
|
if (!m_piTicket || !m_piProfile || !m_pRegistryConfig)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
if (!(m_piTicket->GetPassportFlags() & k_ulFlagsSecuredTransportedTicket)
|
|
|| !m_bSecureTransported)
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
BSTR bstrRawAuth = NULL;
|
|
BSTR bstrRawSecAuth = NULL;
|
|
|
|
CCoCrypt* crypt = m_pRegistryConfig->getCurrentCrypt();
|
|
if (!crypt)
|
|
{
|
|
hr = PM_CANT_DECRYPT_CONFIG;
|
|
goto Cleanup;
|
|
}
|
|
|
|
hr = m_piTicket->get_unencryptedCookie(CTicket::MSPAuth, 0, &bstrRawAuth);
|
|
if (FAILED(hr))
|
|
goto Cleanup;
|
|
|
|
if (!crypt->Encrypt(m_pRegistryConfig->getCurrentCryptVersion(),
|
|
(LPSTR)bstrRawAuth,
|
|
SysStringByteLen(bstrRawAuth),
|
|
pMSPAuth))
|
|
{
|
|
hr = PM_CANT_DECRYPT_CONFIG;
|
|
goto Cleanup;
|
|
}
|
|
|
|
hr = m_piTicket->get_unencryptedCookie(CTicket::MSPSecAuth, 0, &bstrRawSecAuth);
|
|
if (FAILED(hr))
|
|
goto Cleanup;
|
|
|
|
if (!crypt->Encrypt(m_pRegistryConfig->getCurrentCryptVersion(),
|
|
(LPSTR)bstrRawSecAuth,
|
|
SysStringByteLen(bstrRawSecAuth),
|
|
pMSPSecAuth))
|
|
{
|
|
hr = PM_CANT_DECRYPT_CONFIG;
|
|
goto Cleanup;
|
|
}
|
|
|
|
Cleanup:
|
|
if (bstrRawAuth)
|
|
{
|
|
SysFreeString(bstrRawAuth);
|
|
}
|
|
if (bstrRawSecAuth)
|
|
{
|
|
SysFreeString(bstrRawSecAuth);
|
|
}
|
|
|
|
PPTracePrint(PPTRACE_RAW,
|
|
">>> pMSPAuth:%ws, pMSPSecAuth:%ws",
|
|
PPF_WCHAR(*pMSPAuth),
|
|
PPF_WCHAR(*pMSPSecAuth));
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//===========================================================================
|
|
//
|
|
// wipeState -- cleanup teh state of manager object
|
|
//
|
|
void
|
|
CManager::wipeState()
|
|
{
|
|
PPTraceFuncV func(PPTRACE_FUNC, "wipeState");
|
|
|
|
m_pECB = NULL;
|
|
m_pFC = NULL;
|
|
m_bIsTweenerCapable = FALSE;
|
|
m_bOnStartPageCalled = false;
|
|
m_fromQueryString = false;
|
|
m_lNetworkError = 0;
|
|
m_ticketValid = VARIANT_FALSE;
|
|
m_profileValid = VARIANT_FALSE;
|
|
m_piRequest = NULL;
|
|
m_piResponse = NULL;
|
|
|
|
// cleanup ticket content
|
|
if(m_piTicket) m_piTicket->put_unencryptedTicket(NULL);
|
|
|
|
// cleanup profile content
|
|
if(m_piProfile) m_piProfile->put_unencryptedProfile(NULL);
|
|
|
|
// cleanup buffered registry config
|
|
if(m_pRegistryConfig)
|
|
{
|
|
m_pRegistryConfig->Release();
|
|
m_pRegistryConfig = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
//===========================================================================
|
|
//
|
|
// InterfaceSupportsErrorInfo
|
|
//
|
|
STDMETHODIMP CManager::InterfaceSupportsErrorInfo(REFIID riid)
|
|
{
|
|
PPTraceFuncV func(PPTRACE_FUNC, "InterfaceSupportsErrorInfo");
|
|
|
|
static const IID* arr[] =
|
|
{
|
|
&IID_IPassportManager,
|
|
&IID_IPassportManager2,
|
|
&IID_IPassportManager3,
|
|
&IID_IDomainMap,
|
|
};
|
|
for (int i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
|
|
{
|
|
if (InlineIsEqualGUID(*arr[i],riid))
|
|
return S_OK;
|
|
}
|
|
return S_FALSE;
|
|
}
|
|
//===========================================================================
|
|
//
|
|
// OnStartPage -- called by ASP pages automatically by IIS when declared on the page
|
|
//
|
|
STDMETHODIMP CManager::OnStartPage (IUnknown* pUnk)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
PPTraceFunc<HRESULT> func(PPTRACE_FUNC, hr,
|
|
"OnStartPage"," <<< %lx",
|
|
pUnk);
|
|
|
|
if(!pUnk)
|
|
{
|
|
return hr = E_POINTER;
|
|
}
|
|
|
|
IScriptingContextPtr spContext;
|
|
|
|
spContext = pUnk;
|
|
// Get Request Object Pointer
|
|
hr = OnStartPageASP(spContext->Request, spContext->Response);
|
|
|
|
return hr;
|
|
}
|
|
|
|
BSTR
|
|
MyA2W(
|
|
char *src
|
|
)
|
|
{
|
|
|
|
if (src == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
BSTR str = NULL;
|
|
|
|
int nConvertedLen = MultiByteToWideChar(GetACP(), 0, src, -1, NULL, NULL);
|
|
|
|
str = ::SysAllocStringLen(NULL, nConvertedLen - 1);
|
|
if (str != NULL)
|
|
{
|
|
if (!MultiByteToWideChar(GetACP(), 0, src, -1, str, nConvertedLen))
|
|
{
|
|
SysFreeString(str);
|
|
str = NULL;
|
|
}
|
|
}
|
|
return str;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// OnStartPageASP -- called by asp pages when created by using factory object
|
|
// FUTURE --- should change the OnStartPage function to use this function
|
|
//
|
|
STDMETHODIMP CManager::OnStartPageASP(
|
|
IDispatch* piRequest,
|
|
IDispatch* piResponse
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
char* spBuf = NULL;
|
|
BSTR bstrName=NULL;
|
|
BSTR bstrValue=NULL;
|
|
|
|
PPTraceFunc<HRESULT> func(PPTRACE_FUNC, hr,
|
|
"OnStartPageASP",
|
|
" <<< %lx, %lx", piRequest, piResponse);
|
|
PassportLog("CManager::OnStartPageASP Enter:\r\n");
|
|
|
|
if(!piRequest || !piResponse)
|
|
return hr = E_INVALIDARG;
|
|
|
|
USES_CONVERSION;
|
|
|
|
try
|
|
{
|
|
IRequestDictionaryPtr piServerVariables;
|
|
_variant_t vtItemName;
|
|
_variant_t vtHTTPS;
|
|
_variant_t vtMethod;
|
|
_variant_t vtPath;
|
|
_variant_t vtQs;
|
|
_variant_t vtServerPort;
|
|
_variant_t vtHeaders;
|
|
|
|
CComQIPtr<IResponse> spResponse;
|
|
CComQIPtr<IRequest> spRequest;
|
|
|
|
// Get Request Object Pointer
|
|
spRequest = piRequest;
|
|
spResponse = piResponse;
|
|
|
|
//
|
|
// Get the server variables collection.
|
|
//
|
|
|
|
spRequest->get_ServerVariables(&piServerVariables);
|
|
|
|
|
|
//
|
|
// now see if that's a special redirect
|
|
// requiring challenge generation
|
|
// if so processing stops here ....
|
|
//
|
|
if (checkForPassportChallenge(piServerVariables))
|
|
{
|
|
PPTracePrint(PPTRACE_RAW, "special redirect for Challenge");
|
|
return S_OK;
|
|
}
|
|
|
|
//
|
|
// Might need this for multi-site, or secure ticket/profile
|
|
//
|
|
|
|
vtItemName = L"HTTPS";
|
|
|
|
piServerVariables->get_Item(vtItemName, &vtHTTPS);
|
|
if(vtHTTPS.vt != VT_BSTR)
|
|
vtHTTPS.ChangeType(VT_BSTR);
|
|
|
|
DWORD flags = 0;
|
|
if(vtHTTPS.bstrVal && lstrcmpiW(L"on", vtHTTPS.bstrVal) == 0)
|
|
flags |= PASSPORT_HEADER_FLAGS_HTTPS;
|
|
|
|
// headers
|
|
vtItemName.Clear();
|
|
vtItemName = L"ALL_RAW";
|
|
|
|
piServerVariables->get_Item(vtItemName, &vtHeaders);
|
|
if(vtHeaders.vt != VT_BSTR){
|
|
vtHeaders.ChangeType(VT_BSTR);
|
|
}
|
|
|
|
// path
|
|
vtItemName.Clear();
|
|
vtItemName = L"PATH_INFO";
|
|
|
|
piServerVariables->get_Item(vtItemName, &vtPath);
|
|
if(vtPath.vt != VT_BSTR)
|
|
vtPath.ChangeType(VT_BSTR);
|
|
|
|
// vtMethod
|
|
vtItemName.Clear();
|
|
vtItemName = L"REQUEST_METHOD";
|
|
|
|
piServerVariables->get_Item(vtItemName, &vtMethod);
|
|
if(vtMethod.vt != VT_BSTR)
|
|
vtMethod.ChangeType(VT_BSTR);
|
|
|
|
// QUERY_STRING
|
|
vtItemName.Clear();
|
|
vtItemName = L"QUERY_STRING";
|
|
|
|
piServerVariables->get_Item(vtItemName, &vtQs);
|
|
if(vtQs.vt != VT_BSTR)
|
|
vtQs.ChangeType(VT_BSTR);
|
|
|
|
DWORD bufSize = 0;
|
|
DWORD requiredBufSize = MAX_URL_LENGTH;
|
|
|
|
|
|
// make sure the size if sufficient
|
|
while(bufSize < requiredBufSize)
|
|
{
|
|
if (spBuf)
|
|
{
|
|
free(spBuf);
|
|
}
|
|
if(NULL == (spBuf = (char *)malloc(requiredBufSize)))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto exit;
|
|
}
|
|
|
|
bufSize = requiredBufSize;
|
|
|
|
hr = OnStartPageHTTPRawEx(W2A(vtMethod.bstrVal),
|
|
W2A(vtPath.bstrVal),
|
|
W2A(vtQs.bstrVal),
|
|
NULL, // version
|
|
W2A(vtHeaders.bstrVal),
|
|
flags,
|
|
&requiredBufSize,
|
|
spBuf);
|
|
}
|
|
|
|
// write the cookies
|
|
if(hr == S_OK && requiredBufSize && *spBuf)
|
|
{
|
|
char* pNext = spBuf;
|
|
while(pNext != NULL)
|
|
{
|
|
char* pName = pNext;
|
|
char* pValue = strchr(pName, ':');
|
|
if(pValue)
|
|
{
|
|
// make temp sub string
|
|
TempSubStr tsN(pName, pValue - pName);
|
|
bstrName = MyA2W(pName);
|
|
if (bstrName) {
|
|
++pValue;
|
|
pNext = strstr(pValue, "\r\n"); // new line
|
|
if(pNext)
|
|
{
|
|
// make temp sub string
|
|
TempSubStr tsV(pValue, pNext - pValue);
|
|
pNext += 2;
|
|
bstrValue = MyA2W(pValue);
|
|
|
|
}
|
|
else
|
|
{
|
|
bstrValue = MyA2W(pValue);
|
|
}
|
|
if (bstrValue)
|
|
{
|
|
spResponse->raw_AddHeader(bstrName, bstrValue);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pNext = pValue;
|
|
}
|
|
if (bstrName) {
|
|
SysFreeString(bstrName);
|
|
bstrName = NULL;
|
|
}
|
|
if (bstrValue) {
|
|
SysFreeString(bstrValue);
|
|
bstrValue = NULL;
|
|
}
|
|
}
|
|
}
|
|
if (spBuf) {
|
|
free(spBuf);
|
|
spBuf = NULL;
|
|
}
|
|
|
|
// Get Request Object Pointer
|
|
m_piRequest = piRequest;
|
|
// Get Response Object Pointer
|
|
m_piResponse = piResponse;
|
|
|
|
}
|
|
catch (...)
|
|
{
|
|
if (m_piRequest.GetInterfacePtr() != NULL)
|
|
m_piRequest.Release();
|
|
if (m_piResponse.GetInterfacePtr() != NULL)
|
|
m_piResponse.Release();
|
|
m_bOnStartPageCalled = false;
|
|
if (spBuf) {
|
|
free(spBuf);
|
|
}
|
|
if (bstrName) {
|
|
SysFreeString(bstrName);
|
|
}
|
|
if (bstrValue) {
|
|
SysFreeString(bstrValue);
|
|
}
|
|
}
|
|
|
|
exit:
|
|
return hr = S_OK;
|
|
}
|
|
|
|
|
|
//===========================================================================
|
|
//
|
|
// OnStartPageManual -- authenticate with t, and p, MSPAuth, MSPProf, MSPConsent, MSPsecAuth
|
|
// not recommended to use, will be depracated
|
|
//
|
|
STDMETHODIMP CManager::OnStartPageManual(
|
|
BSTR qsT,
|
|
BSTR qsP,
|
|
BSTR mspauth,
|
|
BSTR mspprof,
|
|
BSTR mspconsent,
|
|
VARIANT mspsec,
|
|
VARIANT* pCookies
|
|
)
|
|
{
|
|
int hasSec;
|
|
BSTR bstrSec;
|
|
BSTR bstrConsent = NULL;
|
|
BSTR bstrNewAuth = NULL;
|
|
BSTR bstrNewSecAuth = NULL;
|
|
|
|
HRESULT hr = S_OK;
|
|
PPTraceFunc<HRESULT> func(PPTRACE_FUNC, hr,
|
|
"OnStartPageManual",
|
|
" <<< %ws, %ws, %ws, %ws, %ws", qsT, qsP, mspauth, mspprof, mspconsent);
|
|
|
|
PassportLog("CManager::OnStartPageManual Enter: T = %ws, P = %ws, A = %ws, PR = %ws\r\n",
|
|
qsT, qsP, mspauth, mspprof);
|
|
|
|
if (!g_config->isValid()) // Guarantees config is non-null
|
|
{
|
|
AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
|
|
IID_IPassportManager, PP_E_NOT_CONFIGURED);
|
|
return PP_E_NOT_CONFIGURED;
|
|
}
|
|
|
|
if (!m_piTicket || !m_piProfile)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
wipeState();
|
|
|
|
if(m_pRegistryConfig)
|
|
m_pRegistryConfig->Release();
|
|
m_pRegistryConfig = g_config->checkoutRegistryConfig();
|
|
|
|
// Auth with Query String T & P first
|
|
if (handleQueryStringData(qsT, qsP))
|
|
{
|
|
VARIANT_BOOL persist;
|
|
_bstr_t domain;
|
|
_bstr_t path;
|
|
_bstr_t bstrAuth;
|
|
_bstr_t bstrProf;
|
|
|
|
|
|
bstrAuth.Assign(qsT);
|
|
|
|
bstrProf.Assign(qsP);
|
|
|
|
|
|
if (pCookies)
|
|
{
|
|
VariantInit(pCookies);
|
|
|
|
if (m_pRegistryConfig->getTicketPath())
|
|
path = m_pRegistryConfig->getTicketPath();
|
|
else
|
|
path = L"/";
|
|
|
|
m_piTicket->get_HasSavedPassword(&persist);
|
|
|
|
BOOL bSetConsent = (S_OK == IfConsentCookie(&bstrConsent));
|
|
|
|
SAFEARRAYBOUND rgsabound;
|
|
rgsabound.lLbound = 0;
|
|
rgsabound.cElements = 2;
|
|
|
|
// secure cookie
|
|
if (m_bSecureTransported)
|
|
rgsabound.cElements++;
|
|
|
|
if(bSetConsent)
|
|
rgsabound.cElements++;
|
|
SAFEARRAY *sa = SafeArrayCreate(VT_VARIANT, 1, &rgsabound);
|
|
|
|
if (!sa)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
pCookies->vt = VT_ARRAY | VT_VARIANT;
|
|
pCookies->parray = sa;
|
|
|
|
WCHAR buf[4096];
|
|
DWORD bufSize;
|
|
long spot = 0;
|
|
|
|
VARIANT *vArray;
|
|
SafeArrayAccessData(sa, (void**)&vArray);
|
|
|
|
// write Auth cookies
|
|
BSTR auth, secAuth; // do not call SysFreeString on them, they are skin level copy
|
|
|
|
if (S_OK == IfAlterAuthCookie(&bstrNewAuth, &bstrNewSecAuth))
|
|
{
|
|
auth = bstrNewAuth;
|
|
secAuth = bstrNewSecAuth;
|
|
}
|
|
else
|
|
{
|
|
auth = bstrAuth;
|
|
secAuth = NULL;
|
|
}
|
|
|
|
|
|
domain = m_pRegistryConfig->getTicketDomain();
|
|
|
|
// add MSPAuth
|
|
if (domain.length())
|
|
{
|
|
bufSize = _snwprintf(buf, 4096,
|
|
L"Set-Cookie: MSPAuth=%s; path=%s; domain=%s; %s\r\n",
|
|
(LPWSTR)auth, (LPWSTR)path, (LPWSTR)domain,
|
|
persist ? W_COOKIE_EXPIRES(EXPIRE_FUTURE) : L"");
|
|
}
|
|
else
|
|
{
|
|
bufSize = _snwprintf(buf, 4096,
|
|
L"Set-Cookie: MSPAuth=%s; path=%s; %s\r\n",
|
|
(LPWSTR)auth, (LPWSTR)path,
|
|
persist ? W_COOKIE_EXPIRES(EXPIRE_FUTURE) : L"");
|
|
}
|
|
buf[4095] = L'\0';
|
|
|
|
vArray[spot].vt = VT_BSTR;
|
|
vArray[spot].bstrVal = ALLOC_AND_GIVEAWAY_BSTR_LEN(buf, bufSize);
|
|
spot++;
|
|
|
|
// add MSPSecAuth
|
|
if (m_bSecureTransported)
|
|
{
|
|
|
|
_bstr_t secDomain = m_pRegistryConfig->getSecureDomain();
|
|
_bstr_t secPath;
|
|
|
|
if (m_pRegistryConfig->getSecurePath())
|
|
secPath = m_pRegistryConfig->getSecurePath();
|
|
else
|
|
secPath = L"/";
|
|
|
|
|
|
if (secDomain.length())
|
|
{
|
|
bufSize = _snwprintf(buf, 4096,
|
|
L"Set-Cookie: MSPSecAuth=%s; path=%s; domain=%s; %s; secure\r\n",
|
|
((secAuth && *secAuth) ? (LPWSTR)secAuth : L""), (LPWSTR)secPath, (LPWSTR)secDomain,
|
|
((!secAuth || *secAuth == 0) ? W_COOKIE_EXPIRES(EXPIRE_PAST)
|
|
: L""));
|
|
}
|
|
else
|
|
{
|
|
bufSize = _snwprintf(buf, 4096,
|
|
L"Set-Cookie: MSPSecAuth=%s; path=%s; %s; secure\r\n",
|
|
((secAuth && *secAuth) ? (LPWSTR)secAuth : L""), (LPWSTR)secPath,
|
|
((!secAuth || *secAuth == 0) ? W_COOKIE_EXPIRES(EXPIRE_PAST)
|
|
: L""));
|
|
}
|
|
buf[4095] = L'\0';
|
|
|
|
vArray[spot].vt = VT_BSTR;
|
|
vArray[spot].bstrVal = ALLOC_AND_GIVEAWAY_BSTR_LEN(buf, bufSize);
|
|
spot++;
|
|
}
|
|
|
|
|
|
if (domain.length())
|
|
{
|
|
bufSize = _snwprintf(buf, 4096,
|
|
L"Set-Cookie: MSPProf=%s; path=%s; domain=%s; %s\r\n",
|
|
(LPWSTR)bstrProf, (LPWSTR)path, (LPWSTR)domain,
|
|
persist ? W_COOKIE_EXPIRES(EXPIRE_FUTURE) : L"");
|
|
}
|
|
else
|
|
{
|
|
bufSize = _snwprintf(buf, 4096,
|
|
L"Set-Cookie: MSPProf=%s; path=%s; %s\r\n",
|
|
(LPWSTR)bstrProf, (LPWSTR)path,
|
|
persist ? W_COOKIE_EXPIRES(EXPIRE_FUTURE) : L"");
|
|
}
|
|
buf[4095] = L'\0';
|
|
|
|
vArray[spot].vt = VT_BSTR;
|
|
vArray[spot].bstrVal = ALLOC_AND_GIVEAWAY_BSTR_LEN(buf, bufSize);
|
|
spot++;
|
|
|
|
if(bSetConsent)
|
|
{
|
|
if (m_pRegistryConfig->getProfilePath())
|
|
path = m_pRegistryConfig->getProfilePath();
|
|
else
|
|
path = L"/";
|
|
domain = m_pRegistryConfig->getProfileDomain();
|
|
|
|
if (domain.length())
|
|
{
|
|
bufSize = _snwprintf(buf, 4096,
|
|
L"Set-Cookie: MSPConsent=%s; path=%s; domain=%s; %s\r\n",
|
|
bSetConsent ? (LPWSTR)bstrConsent : L"", (LPWSTR)path, (LPWSTR)domain,
|
|
bSetConsent ? (persist ? W_COOKIE_EXPIRES(EXPIRE_FUTURE) : L"")
|
|
: W_COOKIE_EXPIRES(EXPIRE_PAST));
|
|
}
|
|
else
|
|
{
|
|
bufSize = _snwprintf(buf, 4096,
|
|
L"Set-Cookie: MSPConsent=%s; path=%s; %s\r\n",
|
|
bSetConsent ? (LPWSTR)bstrConsent : L"", (LPWSTR)path,
|
|
bSetConsent ? (persist ? W_COOKIE_EXPIRES(EXPIRE_FUTURE) : L"")
|
|
: W_COOKIE_EXPIRES(EXPIRE_PAST));
|
|
}
|
|
buf[4095] = L'\0';
|
|
|
|
vArray[spot].vt = VT_BSTR;
|
|
vArray[spot].bstrVal = ALLOC_AND_GIVEAWAY_BSTR_LEN(buf, bufSize);
|
|
spot++;
|
|
}
|
|
|
|
SafeArrayUnaccessData(sa);
|
|
}
|
|
}
|
|
|
|
// Now, check the cookies
|
|
if (!m_fromQueryString)
|
|
{
|
|
hasSec = GetBstrArg(mspsec, &bstrSec);
|
|
if(hasSec == CV_DEFAULT || hasSec == CV_BAD)
|
|
bstrSec = NULL;
|
|
|
|
handleCookieData(mspauth, mspprof, mspconsent, bstrSec);
|
|
|
|
if(hasSec == CV_FREE)
|
|
SysFreeString(bstrSec);
|
|
}
|
|
|
|
hr = S_OK;
|
|
Cleanup:
|
|
if (bstrNewAuth)
|
|
{
|
|
SysFreeString(bstrNewAuth);
|
|
}
|
|
if (bstrNewSecAuth)
|
|
{
|
|
SysFreeString(bstrNewSecAuth);
|
|
}
|
|
if (bstrConsent)
|
|
{
|
|
SysFreeString(bstrConsent);
|
|
}
|
|
|
|
PassportLog("CManager::OnStartPageManual Exit:\r\n");
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//===========================================================================
|
|
//
|
|
// OnStartPageECB -- Authenticate with ECB -- for ISAPI extensions
|
|
//
|
|
STDMETHODIMP CManager::OnStartPageECB(
|
|
LPBYTE pvECB,
|
|
DWORD* bufSize,
|
|
LPSTR pCookieHeader
|
|
)
|
|
{
|
|
if (!pvECB) return E_INVALIDARG;
|
|
|
|
EXTENSION_CONTROL_BLOCK* pECB = (EXTENSION_CONTROL_BLOCK*) pvECB;
|
|
HRESULT hr = S_OK;
|
|
PPTraceFunc<HRESULT> func(PPTRACE_FUNC, hr,
|
|
"OnStartPageECB",
|
|
" <<< %lx, %lx, %d, %lx", pvECB, bufSize, *bufSize, pCookieHeader);
|
|
|
|
ATL::CAutoVectorPtr<CHAR> spHTTPS;
|
|
ATL::CAutoVectorPtr<CHAR> spheaders;
|
|
|
|
spheaders.Attach(GetServerVariableECB(pECB, "ALL_RAW"));
|
|
spHTTPS.Attach(GetServerVariableECB(pECB, "HTTPS"));
|
|
|
|
DWORD flags = 0;
|
|
if((CHAR*)spHTTPS && lstrcmpiA("on", (CHAR*)spHTTPS) == 0)
|
|
flags |= PASSPORT_HEADER_FLAGS_HTTPS;
|
|
|
|
hr = OnStartPageHTTPRawEx(pECB->lpszMethod,
|
|
pECB->lpszPathInfo,
|
|
pECB->lpszQueryString,
|
|
NULL, // version
|
|
(CHAR*)spheaders,
|
|
flags, bufSize,
|
|
pCookieHeader);
|
|
|
|
m_pECB = pECB;
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//===========================================================================
|
|
//
|
|
// OnStartPageHTTPRaw -- Authenticate with HTTP request-line and headers
|
|
// returns response headers as output parameters
|
|
//
|
|
STDMETHODIMP CManager::OnStartPageHTTPRaw(
|
|
/* [string][in] */ LPCSTR request_line,
|
|
/* [string][in] */ LPCSTR headers,
|
|
/* [in] */ DWORD flags,
|
|
/* [out][in] */ DWORD *bufSize,
|
|
/* [size_is][out] */ LPSTR pCookieHeader)
|
|
{
|
|
// an old client, let's try the QS
|
|
DWORD dwSize;
|
|
HRESULT hr = S_OK;
|
|
PPTraceFunc<HRESULT> func(PPTRACE_FUNC, hr,
|
|
"OnStartPageHTTPRaw",
|
|
" <<< %s, %s, %lx, %lx, %d, %lx", request_line, headers, flags, bufSize, *bufSize, pCookieHeader);
|
|
LPCSTR pBuffer = GetRawQueryString(request_line, &dwSize);
|
|
if (pBuffer)
|
|
{
|
|
TempSubStr tss(pBuffer, dwSize);
|
|
|
|
hr = OnStartPageHTTPRawEx(NULL, NULL, pBuffer, NULL, headers, flags, bufSize, pCookieHeader);
|
|
}
|
|
else
|
|
hr = OnStartPageHTTPRawEx(NULL, NULL, NULL, NULL, headers, flags, bufSize, pCookieHeader);
|
|
|
|
return hr;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// @func OnStartPageHTTPRawEx -- Authenticate with HTTP request-line and headers
|
|
// returns response headers as output parameters. If *bufsize is not smaller
|
|
// the required length or pCookieHeader is NULL, the required length is returned
|
|
// in bufsize. In this case, an empty string is written into pCookieHeader if
|
|
// it is not NULL.
|
|
// method, path, HTTPVer are not being used in this version of the API
|
|
//
|
|
// @rdesc returns one of these values
|
|
// @flag E_POINTER | NULL bufSize
|
|
// @flag E_POINTER | not writable buffer given by pCookieHeader
|
|
// @flag PP_E_NOT_CONFIGURED | not valid state to call this method
|
|
// @flag S_OK
|
|
//
|
|
STDMETHODIMP CManager::OnStartPageHTTPRawEx(
|
|
/* [string][in] */ LPCSTR method,
|
|
/* [string][in] */ LPCSTR path,
|
|
/* [string][in] */ LPCSTR QS,
|
|
/* [string][in] */ LPCSTR HTTPVer,
|
|
/* [string][in] */ LPCSTR headers,
|
|
/* [in] */ DWORD flags,
|
|
/* [out][in] */ DWORD *bufSize, //@parm retuns the length of the headers. Could be 0 to ask for the req. len.
|
|
/* [size_is][out]*/ LPSTR pCookieHeader) //@parm buffer to hold the headers. Could be NULL to ask for the req. len
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
if(bufSize == NULL)
|
|
return E_POINTER;
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
PPTraceFunc<HRESULT> func(PPTRACE_FUNC, hr,
|
|
"OnStartPageHTTPRawEx",
|
|
" <<< %s, %s, %s, %s, %s, %lx, %lx, %d, %lx", method, path, QS, HTTPVer, headers, flags, bufSize, *bufSize, pCookieHeader);
|
|
|
|
PassportLog("CManager::OnStartPageHTTPRawEx Enter:\r\n");
|
|
|
|
//
|
|
// 12002: if *bufSize is 0, we will not be writing into pCookieHeader
|
|
//
|
|
if(*bufSize == 0)
|
|
pCookieHeader = NULL;
|
|
|
|
if(pCookieHeader && IsBadWritePtr(pCookieHeader, *bufSize))
|
|
return E_POINTER;
|
|
|
|
if (!g_config || !g_config->isValid()) // Guarantees config is non-null
|
|
{
|
|
AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
|
|
IID_IPassportManager, PP_E_NOT_CONFIGURED);
|
|
return PP_E_NOT_CONFIGURED;
|
|
}
|
|
|
|
if (!m_piTicket || !m_piProfile)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
wipeState();
|
|
|
|
DWORD dwSize;
|
|
LPCSTR pBuffer;
|
|
|
|
// used to convert to wide ...
|
|
WCHAR *pwszBuf = NULL;
|
|
|
|
enum {
|
|
header_Host,
|
|
header_Accept_Auth,
|
|
header_Authorization,
|
|
header_Cookie,
|
|
header_total
|
|
|
|
};
|
|
LPCSTR headerNames[header_total] = { "Host", "Accept-Auth", "Authorization", "Cookie"};
|
|
DWORD headerSizes[header_total];
|
|
LPCSTR headerValues[header_total] = {0};
|
|
|
|
GetRawHeaders(headers, headerNames, headerValues, headerSizes, header_total);
|
|
|
|
//
|
|
// Use the header to get the server name being requested
|
|
// so we can get the correct registry config. But only do this
|
|
// if we have some configured sites.
|
|
//
|
|
if(m_pRegistryConfig)
|
|
m_pRegistryConfig->Release();
|
|
pBuffer = headerValues[header_Host];
|
|
if(g_config->HasSites() && pBuffer)
|
|
{
|
|
TempSubStr tss(pBuffer, headerSizes[header_Host]);
|
|
TempSubStr tssRemovePort;
|
|
|
|
LPSTR pPort = strstr(pBuffer, ":");
|
|
if(pPort)
|
|
{
|
|
++pPort;
|
|
DWORD dwPort = atoi(pPort);
|
|
if(dwPort == 80 || dwPort == 443)
|
|
{
|
|
tssRemovePort.Set(pBuffer, pPort - pBuffer - 1);
|
|
}
|
|
}
|
|
|
|
// for port 80 and 443, this should be removed
|
|
PPTracePrint(PPTRACE_RAW, "SiteName %s", PPF_CHAR(pBuffer));
|
|
m_pRegistryConfig = g_config->checkoutRegistryConfig((LPSTR)pBuffer);
|
|
}
|
|
else
|
|
{
|
|
PPTracePrint(PPTRACE_RAW, "Default Site");
|
|
m_pRegistryConfig = g_config->checkoutRegistryConfig(NULL);
|
|
}
|
|
|
|
if (pCookieHeader)
|
|
*pCookieHeader = '\0';
|
|
|
|
//
|
|
// If we have a secure ticket/profile and the url is SSL,
|
|
// then tack on the MSPPuid cookie.
|
|
//
|
|
|
|
if(PASSPORT_HEADER_FLAGS_HTTPS & flags)
|
|
m_bSecureTransported = true;
|
|
else
|
|
m_bSecureTransported = false;
|
|
|
|
PPTracePrint(PPTRACE_RAW, "HTTPS:%d", m_bSecureTransported);
|
|
|
|
// see if client understands passport
|
|
pBuffer = headerValues[header_Accept_Auth];
|
|
if (pBuffer)
|
|
{
|
|
TempSubStr tss(pBuffer, headerSizes[header_Accept_Auth]);
|
|
|
|
if (strstr(pBuffer, PASSPORT_PROT14_A))
|
|
{
|
|
m_bIsTweenerCapable = TRUE;
|
|
PPTracePrint(PPTRACE_RAW, "PASSPORT_PROT14 capable");
|
|
}
|
|
|
|
}
|
|
|
|
BSTR ret = NULL;
|
|
CCoCrypt* crypt = NULL;
|
|
|
|
BOOL fParseSuccess = FALSE;
|
|
pBuffer = headerValues[header_Authorization];
|
|
PWSTR pwszTicket = NULL, pwszProfile = NULL, pwszF = NULL;
|
|
// use these when t&p come from qs
|
|
BSTR QSAuth = NULL, QSProf = NULL, QSErrflag = NULL;
|
|
BSTR bstrConsent = NULL;
|
|
BSTR bstrNewAuth = NULL;
|
|
BSTR bstrNewSecAuth = NULL;
|
|
|
|
|
|
if (pBuffer)
|
|
{
|
|
TempSubStr tss(pBuffer, headerSizes[header_Authorization]);
|
|
|
|
// has passport auth header
|
|
if(strstr(pBuffer, PASSPORT_PROT14_A))
|
|
{
|
|
// convert to wide ...
|
|
int cch = MultiByteToWideChar(GetACP(), 0, pBuffer, -1, NULL, NULL);
|
|
|
|
pwszBuf = (WCHAR*)LocalAlloc(LMEM_FIXED, (cch + 1) * sizeof (WCHAR));
|
|
if (NULL != pwszBuf)
|
|
{
|
|
if (0 != MultiByteToWideChar(GetACP(), 0, pBuffer, -1, pwszBuf, cch))
|
|
{
|
|
BSTR bstrT = NULL;
|
|
BSTR bstrP = NULL;
|
|
|
|
GetTicketAndProfileFromHeader(pwszBuf, pwszTicket, pwszProfile, pwszF);
|
|
|
|
// due to the fact that handleQueryStringData wants BSTRs we can't use
|
|
// the direct pointers we just got, so we have to make copies.
|
|
|
|
if( pwszTicket == NULL )
|
|
{
|
|
bstrT = NULL;
|
|
}
|
|
else
|
|
{
|
|
bstrT = SysAllocString(pwszTicket);
|
|
if (NULL == bstrT)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
if( pwszProfile == NULL )
|
|
{
|
|
bstrP = NULL;
|
|
}
|
|
else
|
|
{
|
|
bstrP = SysAllocString(pwszProfile);
|
|
if (NULL == bstrP)
|
|
{
|
|
SysFreeString(bstrT);
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
// make ticket and profile BSTRs
|
|
PPTracePrint(PPTRACE_RAW,
|
|
"PASSPORT_PROT14 Authorization <<< header:%ws, t:%ws, p:%ws, f:%ws",
|
|
pwszBuf, pwszTicket, pwszProfile, pwszF);
|
|
|
|
fParseSuccess = handleQueryStringData(bstrT, bstrP);
|
|
if (pwszF)
|
|
m_lNetworkError = _wtol(pwszF);
|
|
|
|
SysFreeString(bstrT);
|
|
SysFreeString(bstrP);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// not our header. BUGBUG could there be multiple headers ???
|
|
pBuffer = NULL;
|
|
|
|
}
|
|
}
|
|
if (!pBuffer)
|
|
{
|
|
// an old client, let's try the QS
|
|
if (QS)
|
|
{
|
|
// get ticket and profile ...
|
|
// BUGBUG This could be optimized to avoid wide/short conversions, but later...
|
|
GetQueryData(QS, &QSAuth, &QSProf, &QSErrflag);
|
|
|
|
fParseSuccess = handleQueryStringData(QSAuth,QSProf);
|
|
if(QSErrflag != NULL)
|
|
m_lNetworkError = _wtol(QSErrflag);
|
|
|
|
|
|
PPTracePrint(PPTRACE_RAW,
|
|
"QueryString <<< t:%ws, p:%ws, f:%ws",
|
|
QSAuth, QSProf, QSErrflag);
|
|
}
|
|
}
|
|
|
|
if (fParseSuccess)
|
|
{
|
|
//
|
|
// If we got secure ticket or profile, then
|
|
// we need to re-encrypt the insecure version
|
|
// before setting the cookie headers.
|
|
//
|
|
|
|
PPTracePrint(PPTRACE_RAW, "Authenticated");
|
|
|
|
// Set the cookies
|
|
LPSTR ticketDomain = m_pRegistryConfig->getTicketDomain();
|
|
LPSTR profileDomain = m_pRegistryConfig->getProfileDomain();
|
|
LPSTR secureDomain = m_pRegistryConfig->getSecureDomain();
|
|
LPSTR ticketPath = m_pRegistryConfig->getTicketPath();
|
|
LPSTR profilePath = m_pRegistryConfig->getProfilePath();
|
|
LPSTR securePath = m_pRegistryConfig->getSecurePath();
|
|
VARIANT_BOOL persist;
|
|
m_piTicket->get_HasSavedPassword(&persist);
|
|
|
|
// MSPConsent cookie
|
|
BOOL bSetConsent = (S_OK == IfConsentCookie(&bstrConsent));
|
|
|
|
// Build the cookie headers.
|
|
|
|
// the authentication cookies
|
|
BSTR auth, secAuth; // do not call SysFreeString on them, they are skin level copy
|
|
|
|
if (S_OK == IfAlterAuthCookie(&bstrNewAuth, &bstrNewSecAuth))
|
|
{
|
|
auth = bstrNewAuth;
|
|
secAuth = bstrNewSecAuth;
|
|
}
|
|
else
|
|
{
|
|
if (pwszTicket)
|
|
{
|
|
auth = pwszTicket;
|
|
}
|
|
else
|
|
{
|
|
auth = QSAuth;
|
|
}
|
|
secAuth = NULL;
|
|
}
|
|
|
|
// build cookies for output
|
|
BuildCookieHeaders(W2A(auth),
|
|
(pwszProfile ? W2A(pwszProfile) : (QSProf ? W2A(QSProf) : NULL)),
|
|
(bSetConsent ? W2A(bstrConsent) : NULL),
|
|
(secAuth ? W2A(secAuth) : NULL),
|
|
ticketDomain,
|
|
ticketPath,
|
|
profileDomain,
|
|
profilePath,
|
|
secureDomain,
|
|
securePath,
|
|
persist,
|
|
pCookieHeader,
|
|
bufSize,
|
|
!m_pRegistryConfig->getNotUseHTTPOnly());
|
|
|
|
PPTracePrint(PPTRACE_RAW,
|
|
"Cookie headers >>> %s",PPF_CHAR(pCookieHeader));
|
|
|
|
|
|
}
|
|
|
|
if (QSAuth) FREE_BSTR(QSAuth);
|
|
if (QSProf) FREE_BSTR(QSProf);
|
|
if (QSErrflag) FREE_BSTR(QSErrflag);
|
|
|
|
if (bstrNewAuth)
|
|
{
|
|
SysFreeString(bstrNewAuth);
|
|
}
|
|
if (bstrNewSecAuth)
|
|
{
|
|
SysFreeString(bstrNewSecAuth);
|
|
}
|
|
if (bstrConsent)
|
|
{
|
|
SysFreeString(bstrConsent);
|
|
}
|
|
|
|
// Now, check the cookies
|
|
if (!m_fromQueryString)
|
|
{
|
|
BSTR CookieAuth = NULL, CookieProf = NULL, CookieConsent = NULL, CookieSecure = NULL;
|
|
pBuffer = headerValues[header_Cookie];
|
|
if(pBuffer)
|
|
{
|
|
TempSubStr tss(pBuffer, headerSizes[header_Cookie]);
|
|
|
|
GetCookie(pBuffer, "MSPAuth", &CookieAuth); // GetCookie has URLDecode in it
|
|
GetCookie(pBuffer, "MSPProf", &CookieProf);
|
|
GetCookie(pBuffer, "MSPConsent", &CookieConsent);
|
|
GetCookie(pBuffer, "MSPSecAuth", &CookieSecure);
|
|
|
|
handleCookieData(CookieAuth,CookieProf,CookieConsent,CookieSecure);
|
|
|
|
PPTracePrint(PPTRACE_RAW,
|
|
"Cookies <<< t:%ws, p:%ws, c:%ws, s:%ws",
|
|
CookieAuth, CookieProf, CookieConsent, CookieSecure);
|
|
|
|
if (CookieAuth) FREE_BSTR(CookieAuth);
|
|
if (CookieProf) FREE_BSTR(CookieProf);
|
|
if (CookieConsent) FREE_BSTR(CookieConsent);
|
|
if (CookieSecure) FREE_BSTR(CookieSecure);
|
|
}
|
|
|
|
// we are not returning cookie info back
|
|
if (pCookieHeader)
|
|
*pCookieHeader = 0;
|
|
*bufSize = 0;
|
|
}
|
|
|
|
PassportLog("CManager::OnStartPageHTTPRawEx Exit:\r\n");
|
|
hr = S_OK;
|
|
Cleanup:
|
|
if (NULL != pwszBuf)
|
|
{
|
|
// free the memory since we no longer need it
|
|
LocalFree(pwszBuf);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// ContinueStartPageBody
|
|
// -- when OnStartPageHTTPRaw returns PP_E_HTTP_BODY_REQUIRED, this func is expected to call
|
|
// not doing anything for 2.0 release
|
|
STDMETHODIMP CManager::ContinueStartPageHTTPRaw(
|
|
/* [in] */ DWORD bodyLen,
|
|
/* [size_is][in] */ byte *body,
|
|
/* [out][in] */ DWORD *pBufSize,
|
|
/* [size_is][out] */ LPSTR pRespHeaders,
|
|
/* [out][in] */ DWORD *pRespBodyLen,
|
|
/* [size_is][out] */ byte *pRespBody)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// OnStartPageFilter -- for ISAPI filters
|
|
//
|
|
STDMETHODIMP CManager::OnStartPageFilter(
|
|
LPBYTE pvPFC,
|
|
DWORD* bufSize,
|
|
LPSTR pCookieHeader
|
|
)
|
|
{
|
|
if (!pvPFC) return E_INVALIDARG;
|
|
|
|
PHTTP_FILTER_CONTEXT pfc = (PHTTP_FILTER_CONTEXT) pvPFC;
|
|
|
|
HRESULT hr = S_OK;
|
|
PPTraceFunc<HRESULT> func(PPTRACE_FUNC, hr,
|
|
"OnStartPageFilter",
|
|
" <<< %lx, %lx, %d, %lx", pvPFC, bufSize, *bufSize, pCookieHeader);
|
|
|
|
ATL::CAutoVectorPtr<CHAR> spheaders;
|
|
ATL::CAutoVectorPtr<CHAR> spHTTPS;
|
|
ATL::CAutoVectorPtr<CHAR> spQS;
|
|
|
|
spheaders.Attach(GetServerVariablePFC(pfc, "ALL_RAW"));
|
|
spHTTPS.Attach(GetServerVariablePFC(pfc, "HTTPS"));
|
|
spQS.Attach(GetServerVariablePFC(pfc, "QUERY_STRING"));
|
|
|
|
DWORD flags = 0;
|
|
if((CHAR*)spHTTPS && lstrcmpiA("on", (CHAR*)spHTTPS) == 0)
|
|
flags |= PASSPORT_HEADER_FLAGS_HTTPS;
|
|
|
|
hr = OnStartPageHTTPRawEx(NULL, NULL, (CHAR*)spQS, NULL, (CHAR*)spheaders, flags, bufSize, pCookieHeader);
|
|
|
|
m_pFC = pfc;
|
|
|
|
return hr;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// OnEndPage
|
|
//
|
|
STDMETHODIMP CManager::OnEndPage ()
|
|
{
|
|
PassportLog("CManager::OnEndPage Enter:\r\n");
|
|
|
|
if (m_bOnStartPageCalled)
|
|
{
|
|
m_bOnStartPageCalled = false;
|
|
// Release all interfaces
|
|
m_piRequest.Release();
|
|
m_piResponse.Release();
|
|
}
|
|
|
|
if (!m_piTicket || !m_piProfile)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
// Just in case...
|
|
m_piTicket->put_unencryptedTicket(NULL);
|
|
m_piProfile->put_unencryptedProfile(NULL);
|
|
m_profileValid = m_ticketValid = VARIANT_FALSE;
|
|
m_fromQueryString = false;
|
|
|
|
if(m_pRegistryConfig)
|
|
{
|
|
m_pRegistryConfig->Release();
|
|
m_pRegistryConfig = NULL;
|
|
}
|
|
|
|
PassportLog("CManager::OnEndPage Exit:\r\n");
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// AuthURL
|
|
//
|
|
//
|
|
// Old API. Auth URL is pointing to the login server
|
|
//
|
|
STDMETHODIMP
|
|
CManager::AuthURL(
|
|
VARIANT vRU,
|
|
VARIANT vTimeWindow,
|
|
VARIANT vForceLogin,
|
|
VARIANT vCoBrand,
|
|
VARIANT vLCID,
|
|
VARIANT vNameSpace,
|
|
VARIANT vKPP,
|
|
VARIANT vSecureLevel,
|
|
BSTR *pAuthUrl)
|
|
{
|
|
CComVariant vEmpty(_T(""));
|
|
return CommonAuthURL(vRU, vTimeWindow, vForceLogin,
|
|
vCoBrand, vLCID, vNameSpace,
|
|
vKPP, vSecureLevel,
|
|
FALSE, vEmpty, pAuthUrl);
|
|
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// AuthURL2
|
|
//
|
|
//
|
|
// new API. return URL is to the login server
|
|
//
|
|
STDMETHODIMP
|
|
CManager::AuthURL2(
|
|
VARIANT vRU,
|
|
VARIANT vTimeWindow,
|
|
VARIANT vForceLogin,
|
|
VARIANT vCoBrand,
|
|
VARIANT vLCID,
|
|
VARIANT vNameSpace,
|
|
VARIANT vKPP,
|
|
VARIANT vSecureLevel,
|
|
BSTR *pAuthUrl)
|
|
{
|
|
CComVariant vEmpty(_T(""));
|
|
return CommonAuthURL(vRU, vTimeWindow, vForceLogin,
|
|
vCoBrand, vLCID, vNameSpace,
|
|
vKPP, vSecureLevel,
|
|
TRUE, vEmpty, pAuthUrl);
|
|
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// CommonAuthURL
|
|
//
|
|
//
|
|
// AuthURL implementation
|
|
//
|
|
STDMETHODIMP
|
|
CManager::CommonAuthURL(
|
|
VARIANT vRU,
|
|
VARIANT vTimeWindow,
|
|
VARIANT vForceLogin,
|
|
VARIANT vCoBrand,
|
|
VARIANT vLCID,
|
|
VARIANT vNameSpace,
|
|
VARIANT vKPP,
|
|
VARIANT vSecureLevel,
|
|
BOOL fRedirToSelf,
|
|
VARIANT vFunctionArea, // BSTR: e.g. Wireless
|
|
BSTR *pAuthUrl)
|
|
{
|
|
USES_CONVERSION;
|
|
time_t ct;
|
|
WCHAR url[MAX_URL_LENGTH] = L"";
|
|
VARIANT freeMe;
|
|
UINT TimeWindow;
|
|
int nKPP;
|
|
VARIANT_BOOL ForceLogin = VARIANT_FALSE;
|
|
ULONG ulSecureLevel = 0;
|
|
BSTR CBT = NULL, returnUrl = NULL, bstrNameSpace = NULL;
|
|
int hasCB, hasRU, hasLCID, hasTW, hasFL, hasNameSpace, hasKPP, hasUseSec;
|
|
USHORT Lang;
|
|
HRESULT hr = S_OK;
|
|
|
|
BSTR bstrFunctionArea = NULL;
|
|
int hasFunctionArea;
|
|
CNexusConfig* cnc = NULL;
|
|
|
|
PassportLog("CManager::CommonAuthURL Enter:\r\n");
|
|
|
|
if (!g_config) // Guarantees config is non-null
|
|
{
|
|
AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
|
|
IID_IPassportManager, PP_E_NOT_CONFIGURED);
|
|
return PP_E_NOT_CONFIGURED;
|
|
}
|
|
|
|
if (!m_pRegistryConfig)
|
|
m_pRegistryConfig = g_config->checkoutRegistryConfig();
|
|
|
|
if (!g_config->isValid() || !m_pRegistryConfig) // Guarantees config is non-null
|
|
{
|
|
AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
|
|
IID_IPassportManager, PP_E_NOT_CONFIGURED);
|
|
return PP_E_NOT_CONFIGURED;
|
|
}
|
|
|
|
// Make sure args are of the right type
|
|
if ((hasTW = GetIntArg(vTimeWindow, (int*) &TimeWindow)) == CV_BAD)
|
|
return E_INVALIDARG;
|
|
if ((hasFL = GetBoolArg(vForceLogin, &ForceLogin)) == CV_BAD)
|
|
return E_INVALIDARG;
|
|
if ((hasUseSec = GetIntArg(vSecureLevel, (int*)&ulSecureLevel)) == CV_BAD)
|
|
return E_INVALIDARG;
|
|
if ((hasLCID = GetShortArg(vLCID,&Lang)) == CV_BAD)
|
|
return E_INVALIDARG;
|
|
if ((hasKPP = GetIntArg(vKPP, &nKPP)) == CV_BAD)
|
|
return E_INVALIDARG;
|
|
hasCB = GetBstrArg(vCoBrand, &CBT);
|
|
if (hasCB == CV_BAD)
|
|
return E_INVALIDARG;
|
|
if (hasCB == CV_FREE)
|
|
{
|
|
TAKEOVER_BSTR(CBT);
|
|
}
|
|
|
|
hasRU = GetBstrArg(vRU, &returnUrl);
|
|
if (hasRU == CV_BAD)
|
|
{
|
|
if (hasCB == CV_FREE && CBT)
|
|
FREE_BSTR(CBT);
|
|
return E_INVALIDARG;
|
|
}
|
|
if (hasRU == CV_FREE)
|
|
{
|
|
TAKEOVER_BSTR(returnUrl);
|
|
}
|
|
|
|
hasNameSpace = GetBstrArg(vNameSpace, &bstrNameSpace);
|
|
if (hasNameSpace == CV_BAD)
|
|
{
|
|
if (hasCB == CV_FREE && CBT)
|
|
SysFreeString(CBT);
|
|
if (hasRU == CV_FREE && returnUrl)
|
|
SysFreeString(returnUrl);
|
|
return E_INVALIDARG;
|
|
}
|
|
if (hasNameSpace == CV_FREE)
|
|
{
|
|
TAKEOVER_BSTR(bstrNameSpace);
|
|
}
|
|
if (hasNameSpace == CV_DEFAULT)
|
|
{
|
|
bstrNameSpace = m_pRegistryConfig->getNameSpace();
|
|
}
|
|
|
|
// **************************************************
|
|
// Logging
|
|
if (NULL != returnUrl)
|
|
{
|
|
PassportLog(" RU = %ws\n", returnUrl);
|
|
}
|
|
PassportLog(" TW = %X, SL = %X, L = %d, KPP = %X\r\n", TimeWindow, ulSecureLevel, Lang, nKPP);
|
|
if (NULL != bstrNameSpace)
|
|
{
|
|
PassportLog(" NS = %ws\r\n", bstrNameSpace);
|
|
}
|
|
if (NULL != CBT)
|
|
{
|
|
PassportLog(" CBT = %ws\r\n", CBT);
|
|
}
|
|
// **************************************************
|
|
|
|
hasFunctionArea = GetBstrArg(vFunctionArea, &bstrFunctionArea);
|
|
if (hasFunctionArea == CV_FREE)
|
|
{
|
|
TAKEOVER_BSTR(bstrFunctionArea);
|
|
}
|
|
|
|
if(hasUseSec == CV_DEFAULT)
|
|
ulSecureLevel = m_pRegistryConfig->getSecureLevel();
|
|
|
|
WCHAR *szAUAttrName;
|
|
|
|
if (SECURELEVEL_USE_HTTPS(ulSecureLevel))
|
|
szAUAttrName = L"AuthSecure";
|
|
else
|
|
szAUAttrName = L"Auth";
|
|
|
|
BSTR szAttrName_FuncArea = NULL;
|
|
if (bstrFunctionArea != NULL)
|
|
{
|
|
szAttrName_FuncArea = SysAllocStringLen(NULL, wcslen(bstrFunctionArea) + wcslen(szAUAttrName));
|
|
if (NULL == szAttrName_FuncArea)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
wcscpy(szAttrName_FuncArea, bstrFunctionArea);
|
|
wcscat(szAttrName_FuncArea, szAUAttrName);
|
|
}
|
|
|
|
cnc = g_config->checkoutNexusConfig();
|
|
|
|
if (hasLCID == CV_DEFAULT)
|
|
Lang = m_pRegistryConfig->getDefaultLCID();
|
|
if (hasKPP == CV_DEFAULT)
|
|
nKPP = m_pRegistryConfig->getKPP();
|
|
VariantInit(&freeMe);
|
|
|
|
if (!m_pRegistryConfig->DisasterModeP())
|
|
{
|
|
// If I'm authenticated, get my domain specific url
|
|
if (m_ticketValid && m_profileValid)
|
|
{
|
|
HRESULT hr = m_piProfile->get_ByIndex(MEMBERNAME_INDEX, &freeMe);
|
|
if (hr != S_OK || freeMe.vt != VT_BSTR)
|
|
{
|
|
if (bstrFunctionArea)
|
|
{
|
|
cnc->getDomainAttribute(L"Default",
|
|
szAttrName_FuncArea,
|
|
sizeof(url) / sizeof(WCHAR),
|
|
url,
|
|
Lang);
|
|
}
|
|
|
|
if (*url == 0) // nothing is in URL string
|
|
{
|
|
cnc->getDomainAttribute(L"Default",
|
|
szAUAttrName,
|
|
sizeof(url) / sizeof(WCHAR),
|
|
url,
|
|
Lang);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LPCWSTR psz = wcsrchr(freeMe.bstrVal, L'@');
|
|
if (bstrFunctionArea)
|
|
{
|
|
cnc->getDomainAttribute(psz ? psz+1 : L"Default",
|
|
szAttrName_FuncArea,
|
|
sizeof(url) / sizeof(WCHAR),
|
|
url,
|
|
Lang);
|
|
}
|
|
|
|
if (*url == 0) // nothing is in URL string
|
|
{
|
|
cnc->getDomainAttribute(psz ? psz+1 : L"Default",
|
|
szAUAttrName,
|
|
sizeof(url) / sizeof(WCHAR),
|
|
url,
|
|
Lang);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (bstrFunctionArea)
|
|
{
|
|
cnc->getDomainAttribute(L"Default",
|
|
szAttrName_FuncArea,
|
|
sizeof(url) / sizeof(WCHAR),
|
|
url,
|
|
Lang);
|
|
}
|
|
}
|
|
if(*url == 0) // nothing in URL string
|
|
{
|
|
cnc->getDomainAttribute(L"Default",
|
|
szAUAttrName,
|
|
sizeof(url) / sizeof(WCHAR),
|
|
url,
|
|
Lang);
|
|
}
|
|
}
|
|
else
|
|
lstrcpynW(url, m_pRegistryConfig->getDisasterUrl(), sizeof(url) / sizeof(WCHAR));
|
|
|
|
time(&ct);
|
|
|
|
if (*url == L'\0')
|
|
{
|
|
hr = S_OK;
|
|
goto Cleanup;
|
|
}
|
|
|
|
if (hasTW == CV_DEFAULT)
|
|
TimeWindow = m_pRegistryConfig->getDefaultTicketAge();
|
|
if (hasFL == CV_DEFAULT)
|
|
ForceLogin = m_pRegistryConfig->forceLoginP() ? VARIANT_TRUE : VARIANT_FALSE;
|
|
if (hasCB == CV_DEFAULT)
|
|
CBT = m_pRegistryConfig->getDefaultCoBrand();
|
|
if (hasRU == CV_DEFAULT)
|
|
returnUrl = m_pRegistryConfig->getDefaultRU();
|
|
if (returnUrl == NULL)
|
|
returnUrl = L"";
|
|
|
|
if(ulSecureLevel == VARIANT_TRUE) // special case for backward compatible
|
|
ulSecureLevel = k_iSeclevelSecureChannel;
|
|
|
|
if ((TimeWindow != 0 && TimeWindow < PPM_TIMEWINDOW_MIN) || TimeWindow > PPM_TIMEWINDOW_MAX)
|
|
{
|
|
WCHAR buf[20];
|
|
_itow(TimeWindow,buf,10);
|
|
AtlReportError(CLSID_Manager, (LPCOLESTR) PP_E_INVALID_TIMEWINDOWSTR,
|
|
IID_IPassportManager, PP_E_INVALID_TIMEWINDOW);
|
|
hr = PP_E_INVALID_TIMEWINDOW;
|
|
goto Cleanup;
|
|
}
|
|
|
|
if (NULL == pAuthUrl)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto Cleanup;
|
|
}
|
|
|
|
*pAuthUrl = FormatAuthURL(
|
|
url,
|
|
m_pRegistryConfig->getSiteId(),
|
|
returnUrl,
|
|
TimeWindow,
|
|
ForceLogin,
|
|
m_pRegistryConfig->getCurrentCryptVersion(),
|
|
ct,
|
|
CBT,
|
|
bstrNameSpace,
|
|
nKPP,
|
|
Lang,
|
|
ulSecureLevel,
|
|
m_pRegistryConfig,
|
|
fRedirToSelf,
|
|
IfCreateTPF()
|
|
|
|
);
|
|
if (NULL == *pAuthUrl)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
Cleanup:
|
|
if (szAttrName_FuncArea)
|
|
{
|
|
SysFreeString(szAttrName_FuncArea);
|
|
}
|
|
|
|
if (NULL != cnc)
|
|
{
|
|
cnc->Release();
|
|
}
|
|
if (hasFunctionArea== CV_FREE && bstrFunctionArea)
|
|
FREE_BSTR(bstrFunctionArea);
|
|
|
|
if (hasRU == CV_FREE && returnUrl)
|
|
FREE_BSTR(returnUrl);
|
|
|
|
if (hasCB == CV_FREE && CBT)
|
|
FREE_BSTR(CBT);
|
|
|
|
// !!! need to confirmation
|
|
if (hasNameSpace == CV_FREE && bstrNameSpace)
|
|
FREE_BSTR(bstrNameSpace);
|
|
|
|
VariantClear(&freeMe);
|
|
|
|
PassportLog("CManager::CommonAuthURL Exit: %X\r\n", hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// GetLoginChallenge
|
|
// return AuthURL,
|
|
// output parameter: tweener authHeader
|
|
//
|
|
// get AuthURL and AuthHeaders
|
|
//
|
|
STDMETHODIMP CManager::GetLoginChallenge(VARIANT vReturnUrl,
|
|
VARIANT vTimeWindow,
|
|
VARIANT vForceLogin,
|
|
VARIANT vCoBrandTemplate,
|
|
VARIANT vLCID,
|
|
VARIANT vNameSpace,
|
|
VARIANT vKPP,
|
|
VARIANT vSecureLevel,
|
|
VARIANT vExtraParams,
|
|
BSTR* pAuthHeader
|
|
)
|
|
{
|
|
if (!pAuthHeader) return E_INVALIDARG;
|
|
VARIANT vHeader;
|
|
|
|
VariantInit(&vHeader);
|
|
HRESULT hr = GetLoginChallengeInternal(
|
|
vReturnUrl,
|
|
vTimeWindow,
|
|
vForceLogin,
|
|
vCoBrandTemplate,
|
|
vLCID,
|
|
vNameSpace,
|
|
vKPP,
|
|
vSecureLevel,
|
|
vExtraParams,
|
|
&vHeader,
|
|
NULL);
|
|
|
|
if(S_OK == hr && V_VT(&vHeader) == VT_BSTR && V_BSTR(&vHeader))
|
|
{
|
|
*pAuthHeader = V_BSTR(&vHeader);
|
|
VariantInit(&vHeader);
|
|
}
|
|
else
|
|
VariantClear(&vHeader);
|
|
return hr;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// GetLoginChallengeInternal
|
|
// return AuthURL,
|
|
// output parameter: tweener authHeader
|
|
//
|
|
// get AuthURL and AuthHeaders
|
|
//
|
|
STDMETHODIMP CManager::GetLoginChallengeInternal(VARIANT vReturnUrl,
|
|
VARIANT vTimeWindow,
|
|
VARIANT vForceLogin,
|
|
VARIANT vCoBrandTemplate,
|
|
VARIANT vLCID,
|
|
VARIANT vNameSpace,
|
|
VARIANT vKPP,
|
|
VARIANT vSecureLevel,
|
|
VARIANT vExtraParams,
|
|
VARIANT *pAuthHeader,
|
|
BSTR* pAuthVal
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (pAuthVal)
|
|
{
|
|
*pAuthVal = NULL;
|
|
}
|
|
if (pAuthHeader)
|
|
{
|
|
V_BSTR(pAuthHeader) = NULL;
|
|
}
|
|
|
|
_bstr_t strAuthHeader;
|
|
|
|
try
|
|
{
|
|
// format qs and WWW-Authenticate header ....
|
|
_bstr_t strUrl, strRetUrl, strCBT, strNameSpace;
|
|
UINT TimeWindow;
|
|
int nKPP;
|
|
time_t ct;
|
|
VARIANT_BOOL ForceLogin;
|
|
ULONG ulSecureLevel;
|
|
WCHAR rgLCID[10];
|
|
hr = GetLoginParams(vReturnUrl,
|
|
vTimeWindow,
|
|
vForceLogin,
|
|
vCoBrandTemplate,
|
|
vLCID,
|
|
vNameSpace,
|
|
vKPP,
|
|
vSecureLevel,
|
|
strUrl,
|
|
strRetUrl,
|
|
TimeWindow,
|
|
ForceLogin,
|
|
ct,
|
|
strCBT,
|
|
strNameSpace,
|
|
nKPP,
|
|
ulSecureLevel,
|
|
rgLCID);
|
|
|
|
if (S_OK == hr && strUrl.length() != 0)
|
|
{
|
|
WCHAR szBuf[MAX_QS_LENGTH] = L"";
|
|
// prepare redirect URL to the login server for
|
|
// downlevel clients
|
|
if (NULL == FormatAuthURLParameters(strUrl,
|
|
m_pRegistryConfig->getSiteId(),
|
|
strRetUrl,
|
|
TimeWindow,
|
|
ForceLogin,
|
|
m_pRegistryConfig->getCurrentCryptVersion(),
|
|
ct,
|
|
strCBT,
|
|
strNameSpace,
|
|
nKPP,
|
|
szBuf,
|
|
sizeof(szBuf)/sizeof(WCHAR),
|
|
0, // lang does not matter ....
|
|
ulSecureLevel,
|
|
m_pRegistryConfig,
|
|
FALSE,
|
|
IfCreateTPF()
|
|
)) // do not redirect to self!
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
// insert the WWW-Authenticate header ...
|
|
hr = FormatAuthHeaderFromParams(strUrl,
|
|
strRetUrl,
|
|
TimeWindow,
|
|
ForceLogin,
|
|
ct,
|
|
strCBT,
|
|
strNameSpace,
|
|
nKPP,
|
|
rgLCID,
|
|
ulSecureLevel,
|
|
strAuthHeader);
|
|
if (S_OK != hr)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
// and add the extra ....
|
|
BSTR strExtra = NULL;
|
|
int res = GetBstrArg(vExtraParams, &strExtra);
|
|
|
|
if (res != CV_BAD)
|
|
{
|
|
if (res == CV_DEFAULT)
|
|
{
|
|
strExtra = m_pRegistryConfig->getExtraParams();
|
|
}
|
|
if (NULL != strExtra)
|
|
{
|
|
strAuthHeader += _bstr_t(L",") + strExtra;
|
|
}
|
|
}
|
|
|
|
if (res == CV_FREE)
|
|
::SysFreeString(strExtra);
|
|
|
|
// set return values
|
|
if (pAuthHeader && (WCHAR*)strAuthHeader != NULL)
|
|
{
|
|
V_VT(pAuthHeader) = VT_BSTR;
|
|
// TODO: should avoid this SysAllocString
|
|
V_BSTR(pAuthHeader) = ::SysAllocString((WCHAR*)strAuthHeader);
|
|
if (NULL == V_BSTR(pAuthHeader))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
if (pAuthVal)
|
|
{
|
|
*pAuthVal = ::SysAllocString(szBuf);
|
|
if (NULL == *pAuthVal)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
Cleanup:
|
|
return hr;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// LoginUser
|
|
//
|
|
//
|
|
// client logon method
|
|
// vExtraParams: coBranding text is passed as cbtxt=cobrandingtext
|
|
// the content of the input parameter should be UTF8 encoded, and
|
|
// properly URL escapted before passing into this function
|
|
//
|
|
STDMETHODIMP CManager::LoginUser(VARIANT vReturnUrl,
|
|
VARIANT vTimeWindow,
|
|
VARIANT vForceLogin,
|
|
VARIANT vCoBrandTemplate,
|
|
VARIANT vLCID,
|
|
VARIANT vNameSpace,
|
|
VARIANT vKPP,
|
|
VARIANT vSecureLevel,
|
|
VARIANT vExtraParams)
|
|
{
|
|
// format qs and WWW-Authenticate header ....
|
|
BSTR authURL = NULL;
|
|
CComVariant authHeader;
|
|
|
|
PassportLog("CManager::LoginUser Enter:\r\n");
|
|
|
|
HRESULT hr = GetLoginChallengeInternal( vReturnUrl,
|
|
vTimeWindow,
|
|
vForceLogin,
|
|
vCoBrandTemplate,
|
|
vLCID,
|
|
vNameSpace,
|
|
vKPP,
|
|
vSecureLevel,
|
|
vExtraParams,
|
|
&authHeader,
|
|
&authURL);
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
_ASSERT(V_VT(&authHeader) == VT_BSTR);
|
|
_ASSERT(authURL);
|
|
_ASSERT(V_BSTR(&authHeader));
|
|
|
|
// TODO: _bstr_t should be removed globaly in ppm
|
|
if (m_piResponse)
|
|
{
|
|
m_piResponse->AddHeader(L"WWW-Authenticate", V_BSTR(&authHeader));
|
|
|
|
_bstr_t authURL1 = authURL;
|
|
|
|
// and redirect!
|
|
if (!m_bIsTweenerCapable)
|
|
m_piResponse->Redirect(authURL1);
|
|
else
|
|
{
|
|
// send a 401
|
|
m_piResponse->put_Status(L"401 Unauthorized");
|
|
m_piResponse->End();
|
|
}
|
|
}
|
|
else if (m_pECB || m_pFC)
|
|
{
|
|
// use ECB of Filter interfaces
|
|
// 4k whould be enough ....
|
|
char buffer[4096],
|
|
status[25] = "302 Object moved",
|
|
*psz=buffer,
|
|
rgszTemplate[] = "Content-Type: text/html\r\nLocation: %ws\r\n"
|
|
"Content-Length: 0\r\n"
|
|
"WWW-Authenticate: %ws\r\n\r\n";
|
|
DWORD cbTotalLength = strlen(rgszTemplate);
|
|
|
|
//
|
|
// This is a hack fix, unfortunately we can succeed the call to GetChallengeInternal but
|
|
// have a NULL authHeader, it seemed a bit risky to try and fix GetLoginParams which
|
|
// seems to be the function which returns success when allocations are failing.
|
|
//
|
|
if ((NULL == V_BSTR(&authHeader)) || (NULL == (BSTR)authURL))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
cbTotalLength += wcslen(V_BSTR(&authHeader)) + wcslen(authURL);
|
|
|
|
if (m_bIsTweenerCapable)
|
|
strcpy(status, "401 Unauthorized");
|
|
if (cbTotalLength >= sizeof(buffer))
|
|
{
|
|
// if not ...
|
|
// need to alloc
|
|
psz = new CHAR[cbTotalLength];
|
|
_ASSERT(psz);
|
|
}
|
|
|
|
if (psz)
|
|
{
|
|
sprintf(psz,
|
|
rgszTemplate,
|
|
authURL,
|
|
V_BSTR(&authHeader));
|
|
if (m_pECB)
|
|
{
|
|
// extension
|
|
HSE_SEND_HEADER_EX_INFO Headers =
|
|
{
|
|
status,
|
|
psz,
|
|
strlen(status),
|
|
strlen(psz),
|
|
TRUE
|
|
};
|
|
if (!m_pECB->ServerSupportFunction(m_pECB->ConnID,
|
|
HSE_REQ_SEND_RESPONSE_HEADER_EX,
|
|
&Headers,
|
|
NULL,
|
|
NULL))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// filter
|
|
if (!m_pFC->ServerSupportFunction(m_pFC,
|
|
SF_REQ_SEND_RESPONSE_HEADER,
|
|
status,
|
|
(ULONG_PTR) psz,
|
|
NULL))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
}
|
|
|
|
if (psz != buffer)
|
|
// if we had to allocate
|
|
delete[] psz;
|
|
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
}
|
|
|
|
Cleanup:
|
|
if (authURL)
|
|
{
|
|
SysFreeString(authURL);
|
|
}
|
|
|
|
PassportLog("CManager::LoginUser Exit: %X\r\n", hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
//
|
|
// IsAuthenticated -- determine if authenticated with specified SecureLevel
|
|
//
|
|
STDMETHODIMP CManager::IsAuthenticated(
|
|
VARIANT vTimeWindow,
|
|
VARIANT vForceLogin,
|
|
VARIANT SecureLevel,
|
|
VARIANT_BOOL *pVal)
|
|
{
|
|
HRESULT hr;
|
|
ULONG TimeWindow;
|
|
VARIANT_BOOL ForceLogin;
|
|
ATL::CComVariant vSecureLevel;
|
|
ULONG ulSecureLevel;
|
|
int hasTW, hasFL, hasSecureLevel;
|
|
|
|
PassportLog("CManager::IsAuthenticated Enter:\r\n");
|
|
|
|
PPTraceFunc<HRESULT> func(PPTRACE_FUNC, hr,
|
|
"IsAuthenticated", "<<< %lx, %lx, %1x, %1x",
|
|
V_I4(&vTimeWindow), V_I4(&vForceLogin), V_I4(&SecureLevel), pVal);
|
|
|
|
if (!m_piTicket || !m_piProfile)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
if (!g_config) // Guarantees config is non-null
|
|
{
|
|
AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
|
|
IID_IPassportManager, PP_E_NOT_CONFIGURED);
|
|
hr = PP_E_NOT_CONFIGURED;
|
|
goto Cleanup;
|
|
}
|
|
|
|
if (!m_pRegistryConfig)
|
|
m_pRegistryConfig = g_config->checkoutRegistryConfig();
|
|
|
|
if (!g_config->isValid() || !m_pRegistryConfig) // Guarantees config is non-null
|
|
{
|
|
AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
|
|
IID_IPassportManager, PP_E_NOT_CONFIGURED);
|
|
hr = PP_E_NOT_CONFIGURED;
|
|
goto Cleanup;
|
|
}
|
|
|
|
if ((hasTW = GetIntArg(vTimeWindow,(int*)&TimeWindow)) == CV_BAD)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto Cleanup;
|
|
}
|
|
if (hasTW == CV_DEFAULT)
|
|
TimeWindow = m_pRegistryConfig->getDefaultTicketAge();
|
|
|
|
if ((hasFL = GetBoolArg(vForceLogin, &ForceLogin)) == CV_BAD)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto Cleanup;
|
|
}
|
|
if (hasFL == CV_DEFAULT)
|
|
ForceLogin = m_pRegistryConfig->forceLoginP() ? VARIANT_TRUE : VARIANT_FALSE;
|
|
|
|
hasSecureLevel = GetIntArg(SecureLevel, (int*)&ulSecureLevel);
|
|
if(hasSecureLevel == CV_BAD) // try the legacy type VT_BOOL, map VARIANT_TRUE to SecureChannel
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto Cleanup;
|
|
}
|
|
else if (hasSecureLevel == CV_DEFAULT)
|
|
{
|
|
ulSecureLevel = m_pRegistryConfig->getSecureLevel();
|
|
}
|
|
|
|
if(ulSecureLevel == VARIANT_TRUE)// backward compatible with 1.3X
|
|
{
|
|
ulSecureLevel = k_iSeclevelSecureChannel;
|
|
}
|
|
|
|
vSecureLevel = ulSecureLevel;
|
|
|
|
// Logging
|
|
PassportLog(" TW = %X, SL = %X\r\n", TimeWindow, ulSecureLevel);
|
|
|
|
hr = m_piTicket->get_IsAuthenticated(TimeWindow, ForceLogin, vSecureLevel, pVal);
|
|
PPTracePrint(PPTRACE_RAW, "IsAuthenticated Params: %d, %d, %d, %lx", TimeWindow, ForceLogin, ulSecureLevel, *pVal);
|
|
|
|
Cleanup:
|
|
|
|
if(g_pPerf)
|
|
{
|
|
if (*pVal)
|
|
{
|
|
g_pPerf->incrementCounter(PM_AUTHSUCCESS_TOTAL);
|
|
g_pPerf->incrementCounter(PM_AUTHSUCCESS_SEC);
|
|
}
|
|
else
|
|
{
|
|
g_pPerf->incrementCounter(PM_AUTHFAILURE_TOTAL);
|
|
g_pPerf->incrementCounter(PM_AUTHFAILURE_SEC);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_ASSERT(g_pPerf);
|
|
}
|
|
|
|
PassportLog("CManager::IsAuthenticated Exit: %X\r\n", hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// LogoTag
|
|
//
|
|
//
|
|
// old PM API. The URL is pointing to login server
|
|
//
|
|
STDMETHODIMP
|
|
CManager::LogoTag(
|
|
VARIANT vRU,
|
|
VARIANT vTimeWindow,
|
|
VARIANT vForceLogin,
|
|
VARIANT vCoBrand,
|
|
VARIANT vLCID,
|
|
VARIANT vSecure,
|
|
VARIANT vNameSpace,
|
|
VARIANT vKPP,
|
|
VARIANT vSecureLevel,
|
|
BSTR *pVal)
|
|
{
|
|
return CommonLogoTag(vRU, vTimeWindow, vForceLogin,
|
|
vCoBrand, vLCID, vSecure,
|
|
vNameSpace, vKPP, vSecureLevel,
|
|
FALSE, pVal);
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// LogoTag2
|
|
//
|
|
//
|
|
// new PM API. The URL is pointing to the partner site
|
|
//
|
|
STDMETHODIMP
|
|
CManager::LogoTag2(
|
|
VARIANT vRU,
|
|
VARIANT vTimeWindow,
|
|
VARIANT vForceLogin,
|
|
VARIANT vCoBrand,
|
|
VARIANT vLCID,
|
|
VARIANT vSecure,
|
|
VARIANT vNameSpace,
|
|
VARIANT vKPP,
|
|
VARIANT vSecureLevel,
|
|
BSTR *pVal)
|
|
{
|
|
return CommonLogoTag(vRU, vTimeWindow, vForceLogin,
|
|
vCoBrand, vLCID, vSecure,
|
|
vNameSpace, vKPP, vSecureLevel,
|
|
TRUE, pVal);
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// CommonLogoTag
|
|
//
|
|
STDMETHODIMP
|
|
CManager::CommonLogoTag(
|
|
VARIANT vRU,
|
|
VARIANT vTimeWindow,
|
|
VARIANT vForceLogin,
|
|
VARIANT vCoBrand,
|
|
VARIANT vLCID,
|
|
VARIANT vSecure,
|
|
VARIANT vNameSpace,
|
|
VARIANT vKPP,
|
|
VARIANT vSecureLevel,
|
|
BOOL fRedirToSelf,
|
|
BSTR *pVal)
|
|
{
|
|
time_t ct;
|
|
ULONG TimeWindow;
|
|
int nKPP;
|
|
VARIANT_BOOL ForceLogin, bSecure = VARIANT_FALSE;
|
|
ULONG ulSecureLevel = 0;
|
|
BSTR CBT = NULL, returnUrl = NULL, NameSpace = NULL;
|
|
int hasCB = -1, hasRU = -1, hasLCID, hasTW, hasFL, hasSec, hasUseSec, hasNameSpace = -1, hasKPP;
|
|
USHORT Lang;
|
|
LPWSTR pszNewURL = NULL;
|
|
BSTR upd = NULL;
|
|
CNexusConfig* cnc = NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
USES_CONVERSION;
|
|
|
|
PassportLog("CManager::CommonLogoTag Enter:\r\n");
|
|
|
|
time(&ct);
|
|
|
|
if (NULL == pVal)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto Cleanup;
|
|
}
|
|
*pVal = NULL;
|
|
|
|
if (!g_config) // Guarantees config is non-null
|
|
{
|
|
AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
|
|
IID_IPassportManager, PP_E_NOT_CONFIGURED);
|
|
hr = PP_E_NOT_CONFIGURED;
|
|
goto Cleanup;
|
|
}
|
|
|
|
if (!m_pRegistryConfig)
|
|
m_pRegistryConfig = g_config->checkoutRegistryConfig();
|
|
|
|
if (!g_config->isValid() || !m_pRegistryConfig) // Guarantees config is non-null
|
|
{
|
|
AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
|
|
IID_IPassportManager, PP_E_NOT_CONFIGURED);
|
|
hr = PP_E_NOT_CONFIGURED;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// parameters parsing ...
|
|
|
|
// Make sure args are of the right type
|
|
if ( ((hasTW = GetIntArg(vTimeWindow, (int*) &TimeWindow)) == CV_BAD) ||
|
|
((hasFL = GetBoolArg(vForceLogin, &ForceLogin)) == CV_BAD) ||
|
|
((hasSec = GetBoolArg(vSecure,&bSecure)) == CV_BAD) ||
|
|
// FUTURE: should introduce a new func: GetLongArg ...
|
|
((hasUseSec = GetIntArg(vSecureLevel,(int*)&ulSecureLevel)) == CV_BAD) ||
|
|
((hasLCID = GetShortArg(vLCID,&Lang)) == CV_BAD) ||
|
|
((hasKPP = GetIntArg(vKPP, &nKPP)) == CV_BAD) )
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto Cleanup;
|
|
}
|
|
|
|
hasCB = GetBstrArg(vCoBrand, &CBT);
|
|
if (hasCB == CV_BAD)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto Cleanup;
|
|
}
|
|
if (hasCB == CV_FREE)
|
|
{
|
|
TAKEOVER_BSTR(CBT);
|
|
}
|
|
hasRU = GetBstrArg(vRU, &returnUrl);
|
|
if (hasRU == CV_BAD)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto Cleanup;
|
|
}
|
|
if (hasRU == CV_FREE)
|
|
{
|
|
TAKEOVER_BSTR(returnUrl);
|
|
}
|
|
hasNameSpace = GetBstrArg(vNameSpace, &NameSpace);
|
|
if (hasNameSpace == CV_BAD)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto Cleanup;
|
|
}
|
|
if (hasNameSpace == CV_FREE)
|
|
{
|
|
TAKEOVER_BSTR(NameSpace);
|
|
}
|
|
if (hasNameSpace == CV_DEFAULT)
|
|
{
|
|
NameSpace = m_pRegistryConfig->getNameSpace();
|
|
}
|
|
|
|
WCHAR *szSIAttrName, *szSOAttrName;
|
|
if (hasSec == CV_OK && bSecure == VARIANT_TRUE)
|
|
{
|
|
szSIAttrName = L"SecureSigninLogo";
|
|
szSOAttrName = L"SecureSignoutLogo";
|
|
}
|
|
else
|
|
{
|
|
szSIAttrName = L"SigninLogo";
|
|
szSOAttrName = L"SignoutLogo";
|
|
}
|
|
|
|
if(hasUseSec == CV_DEFAULT)
|
|
ulSecureLevel = m_pRegistryConfig->getSecureLevel();
|
|
|
|
if(ulSecureLevel == VARIANT_TRUE) // special case for backward compatible
|
|
ulSecureLevel = k_iSeclevelSecureChannel;
|
|
|
|
|
|
WCHAR *szAUAttrName;
|
|
if (SECURELEVEL_USE_HTTPS(ulSecureLevel))
|
|
szAUAttrName = L"AuthSecure";
|
|
else
|
|
szAUAttrName = L"Auth";
|
|
|
|
cnc = g_config->checkoutNexusConfig();
|
|
if (NULL == cnc)
|
|
{
|
|
hr = PP_E_NOT_CONFIGURED;
|
|
goto Cleanup;
|
|
}
|
|
|
|
if (hasLCID == CV_DEFAULT)
|
|
Lang = m_pRegistryConfig->getDefaultLCID();
|
|
|
|
if (hasTW == CV_DEFAULT)
|
|
TimeWindow = m_pRegistryConfig->getDefaultTicketAge();
|
|
if (hasFL == CV_DEFAULT)
|
|
ForceLogin = m_pRegistryConfig->forceLoginP() ? VARIANT_TRUE : VARIANT_FALSE;
|
|
if (hasCB == CV_DEFAULT)
|
|
CBT = m_pRegistryConfig->getDefaultCoBrand();
|
|
if (hasRU == CV_DEFAULT)
|
|
returnUrl = m_pRegistryConfig->getDefaultRU();
|
|
if (hasKPP == CV_DEFAULT)
|
|
nKPP = m_pRegistryConfig->getKPP();
|
|
if (returnUrl == NULL)
|
|
returnUrl = L"";
|
|
|
|
// **************************************************
|
|
// Logging
|
|
PassportLog(" RU = %ws\r\n", returnUrl);
|
|
PassportLog(" TW = %X, SL = %X, L = %d, KPP = %X\r\n", TimeWindow, ulSecureLevel, Lang, nKPP);
|
|
if (NULL != NameSpace)
|
|
{
|
|
PassportLog(" NS = %ws\r\n", NameSpace);
|
|
}
|
|
if (NULL != CBT)
|
|
{
|
|
PassportLog(" CBT = %ws\r\n", CBT);
|
|
}
|
|
// **************************************************
|
|
|
|
if ((TimeWindow != 0 && TimeWindow < PPM_TIMEWINDOW_MIN) || TimeWindow > PPM_TIMEWINDOW_MAX)
|
|
{
|
|
WCHAR buf[20];
|
|
_itow(TimeWindow,buf,10);
|
|
AtlReportError(CLSID_Manager, (LPCOLESTR) PP_E_INVALID_TIMEWINDOWSTR,
|
|
IID_IPassportManager, PP_E_INVALID_TIMEWINDOW);
|
|
hr = PP_E_INVALID_TIMEWINDOW;
|
|
goto Cleanup;
|
|
}
|
|
|
|
if (m_ticketValid)
|
|
{
|
|
LPCWSTR domain = NULL;
|
|
WCHAR url[MAX_URL_LENGTH];
|
|
VARIANT freeMe;
|
|
VariantInit(&freeMe);
|
|
|
|
if (m_pRegistryConfig->DisasterModeP())
|
|
lstrcpynW(url, m_pRegistryConfig->getDisasterUrl(), sizeof(url)/sizeof(WCHAR));
|
|
else
|
|
{
|
|
if (m_profileValid &&
|
|
m_piProfile->get_ByIndex(MEMBERNAME_INDEX, &freeMe) == S_OK &&
|
|
freeMe.vt == VT_BSTR)
|
|
{
|
|
domain = wcsrchr(freeMe.bstrVal, L'@');
|
|
}
|
|
|
|
cnc->getDomainAttribute(L"Default",
|
|
L"Logout",
|
|
sizeof(url)/sizeof(WCHAR),
|
|
url,
|
|
Lang);
|
|
}
|
|
|
|
// find out if there are any updates
|
|
m_piProfile->get_updateString(&upd);
|
|
|
|
if (upd)
|
|
{
|
|
TAKEOVER_BSTR(upd);
|
|
// form the appropriate URL
|
|
CCoCrypt* crypt = NULL;
|
|
BSTR newCH = NULL;
|
|
crypt = m_pRegistryConfig->getCurrentCrypt(); // IsValid ensures this is non-null
|
|
|
|
if (!crypt->Encrypt(m_pRegistryConfig->getCurrentCryptVersion(),
|
|
(LPSTR)upd,
|
|
SysStringByteLen(upd),
|
|
&newCH))
|
|
{
|
|
AtlReportError(CLSID_Manager, (LPCOLESTR) PP_E_UNABLE_TO_ENCRYPTSTR,
|
|
IID_IPassportManager, PP_E_UNABLE_TO_ENCRYPT);
|
|
hr = PP_E_UNABLE_TO_ENCRYPT;
|
|
goto Cleanup;
|
|
}
|
|
TAKEOVER_BSTR(newCH);
|
|
WCHAR iurlbuf[1024] = L"";
|
|
LPCWSTR iurl;
|
|
cnc->getDomainAttribute(domain ? domain+1 : L"Default",
|
|
L"Update",
|
|
sizeof(iurlbuf) >> 1,
|
|
iurlbuf,
|
|
Lang);
|
|
|
|
if(*iurlbuf == 0)
|
|
{
|
|
cnc->getDomainAttribute(L"Default",
|
|
L"Update",
|
|
sizeof(iurlbuf) >> 1,
|
|
iurlbuf,
|
|
Lang);
|
|
}
|
|
// convert this url to https as appropriate
|
|
if(!bSecure)
|
|
iurl = iurlbuf;
|
|
else
|
|
{
|
|
LPWSTR psz;
|
|
|
|
pszNewURL = SysAllocStringByteLen(NULL, (lstrlenW(iurlbuf) + 2) * sizeof(WCHAR));
|
|
|
|
if(pszNewURL)
|
|
{
|
|
psz = wcsstr(iurlbuf, L"http:");
|
|
if(psz != NULL)
|
|
{
|
|
psz += 4;
|
|
|
|
lstrcpynW(pszNewURL, iurlbuf, (psz - iurlbuf + 1));
|
|
lstrcatW(pszNewURL, L"s");
|
|
lstrcatW(pszNewURL, psz);
|
|
|
|
iurl = pszNewURL;
|
|
}
|
|
}
|
|
}
|
|
|
|
// This is a bit gross... we need to find the $1 in the update url...
|
|
LPCWSTR ins = iurl ? (wcsstr(iurl, L"$1")) : NULL;
|
|
// We'll break if null, but won't crash...
|
|
if (ins && *url != L'\0')
|
|
{
|
|
*pVal = FormatUpdateLogoTag(
|
|
url,
|
|
m_pRegistryConfig->getSiteId(),
|
|
returnUrl,
|
|
TimeWindow,
|
|
ForceLogin,
|
|
m_pRegistryConfig->getCurrentCryptVersion(),
|
|
ct,
|
|
CBT,
|
|
nKPP,
|
|
iurl,
|
|
bSecure,
|
|
newCH,
|
|
PM_LOGOTYPE_SIGNOUT,
|
|
ulSecureLevel,
|
|
m_pRegistryConfig,
|
|
IfCreateTPF()
|
|
);
|
|
}
|
|
FREE_BSTR(newCH);
|
|
}
|
|
else
|
|
{
|
|
WCHAR iurl[MAX_URL_LENGTH] = L"";
|
|
cnc->getDomainAttribute(L"Default",
|
|
szSOAttrName,
|
|
sizeof(iurl)/sizeof(WCHAR),
|
|
iurl,
|
|
Lang);
|
|
if (*iurl != L'\0')
|
|
{
|
|
*pVal = FormatNormalLogoTag(
|
|
url,
|
|
m_pRegistryConfig->getSiteId(),
|
|
returnUrl,
|
|
TimeWindow,
|
|
ForceLogin,
|
|
m_pRegistryConfig->getCurrentCryptVersion(),
|
|
ct,
|
|
CBT,
|
|
iurl,
|
|
NULL,
|
|
nKPP,
|
|
PM_LOGOTYPE_SIGNOUT,
|
|
Lang,
|
|
ulSecureLevel,
|
|
m_pRegistryConfig,
|
|
fRedirToSelf,
|
|
IfCreateTPF()
|
|
);
|
|
}
|
|
}
|
|
VariantClear(&freeMe);
|
|
if (NULL == *pVal)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WCHAR url[MAX_URL_LENGTH];
|
|
if (!(m_pRegistryConfig->DisasterModeP()))
|
|
cnc->getDomainAttribute(L"Default",
|
|
szAUAttrName,
|
|
sizeof(url)/sizeof(WCHAR),
|
|
url,
|
|
Lang);
|
|
else
|
|
lstrcpynW(url, m_pRegistryConfig->getDisasterUrl(), sizeof(url)/sizeof(WCHAR));
|
|
|
|
WCHAR iurl[MAX_URL_LENGTH];
|
|
cnc->getDomainAttribute(L"Default",
|
|
szSIAttrName,
|
|
sizeof(iurl)/sizeof(WCHAR),
|
|
iurl,
|
|
Lang);
|
|
if (*iurl != L'\0')
|
|
{
|
|
*pVal = FormatNormalLogoTag(
|
|
url,
|
|
m_pRegistryConfig->getSiteId(),
|
|
returnUrl,
|
|
TimeWindow,
|
|
ForceLogin,
|
|
m_pRegistryConfig->getCurrentCryptVersion(),
|
|
ct,
|
|
CBT,
|
|
iurl,
|
|
NameSpace,
|
|
nKPP,
|
|
PM_LOGOTYPE_SIGNIN,
|
|
Lang,
|
|
ulSecureLevel,
|
|
m_pRegistryConfig,
|
|
fRedirToSelf,
|
|
IfCreateTPF()
|
|
);
|
|
if (NULL == *pVal)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
}
|
|
Cleanup:
|
|
if (NULL != cnc)
|
|
{
|
|
cnc->Release();
|
|
}
|
|
|
|
if (NULL != upd)
|
|
FREE_BSTR(upd);
|
|
if (pszNewURL)
|
|
SysFreeString(pszNewURL);
|
|
if (hasRU == CV_FREE && returnUrl)
|
|
FREE_BSTR(returnUrl);
|
|
if (hasCB == CV_FREE && CBT)
|
|
FREE_BSTR(CBT);
|
|
if (hasNameSpace == CV_FREE && NameSpace)
|
|
FREE_BSTR(NameSpace);
|
|
|
|
PassportLog("CManager::CommonLogoTag Exit: %X\r\n", hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// HasProfile -- if valid profile is present
|
|
//
|
|
STDMETHODIMP CManager::HasProfile(VARIANT var, VARIANT_BOOL *pVal)
|
|
{
|
|
LPWSTR profileName;
|
|
|
|
PassportLog("CManager::HasProfile Enter:\r\n");
|
|
|
|
if (var.vt == (VT_BSTR | VT_BYREF))
|
|
profileName = *var.pbstrVal;
|
|
else if (var.vt == VT_BSTR)
|
|
profileName = var.bstrVal;
|
|
else if (var.vt == (VT_VARIANT | VT_BYREF))
|
|
{
|
|
return HasProfile(*(var.pvarVal), pVal);
|
|
}
|
|
else
|
|
profileName = NULL;
|
|
|
|
if ((!profileName) || (!_wcsicmp(profileName, L"core")))
|
|
{
|
|
HRESULT ok = m_piProfile->get_IsValid(pVal);
|
|
if (ok != S_OK)
|
|
*pVal = VARIANT_FALSE;
|
|
}
|
|
else
|
|
{
|
|
VARIANT vAtt;
|
|
VariantInit(&vAtt);
|
|
|
|
PassportLog(" %ws\r\n", profileName);
|
|
|
|
HRESULT ok = m_piProfile->get_Attribute(profileName, &vAtt);
|
|
if (ok != S_OK)
|
|
{
|
|
if (g_pAlert)
|
|
g_pAlert->report(PassportAlertInterface::ERROR_TYPE, PM_INVALID_PROFILETYPE);
|
|
*pVal = VARIANT_FALSE;
|
|
}
|
|
else
|
|
{
|
|
if (vAtt.vt == VT_I4)
|
|
*pVal = vAtt.lVal > 0 ? VARIANT_TRUE : VARIANT_FALSE;
|
|
else if (vAtt.vt == VT_I2)
|
|
*pVal = vAtt.iVal > 0 ? VARIANT_TRUE : VARIANT_FALSE;
|
|
else
|
|
{
|
|
if (g_pAlert)
|
|
g_pAlert->report(PassportAlertInterface::ERROR_TYPE, PM_INVALID_PROFILETYPE);
|
|
}
|
|
VariantClear(&vAtt);
|
|
}
|
|
}
|
|
|
|
PassportLog("CManager::HasProfile Exit: %X\r\n", *pVal);
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// get_HasTicket
|
|
//
|
|
STDMETHODIMP CManager::get_HasTicket(VARIANT_BOOL *pVal)
|
|
{
|
|
PassportLog("CManager::get_HasTicket:\r\n");
|
|
|
|
if(!pVal) return E_POINTER;
|
|
|
|
*pVal = m_ticketValid ? VARIANT_TRUE : VARIANT_FALSE;
|
|
return S_OK;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// get_FromNetworkServer -- if it's authenticated by QueryString
|
|
//
|
|
STDMETHODIMP CManager::get_FromNetworkServer(VARIANT_BOOL *pVal)
|
|
{
|
|
PassportLog("CManager::get_FromNetworkServer:\r\n");
|
|
|
|
*pVal = (m_fromQueryString &&
|
|
m_ticketValid) ? VARIANT_TRUE : VARIANT_FALSE;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// HasFlag -- obsolete function
|
|
//
|
|
STDMETHODIMP CManager::HasFlag(VARIANT var, VARIANT_BOOL *pVal)
|
|
{
|
|
PassportLog("CManager::HasFlag:\r\n");
|
|
|
|
AtlReportError(CLSID_Manager, PP_E_GETFLAGS_OBSOLETESTR,
|
|
IID_IPassportManager, E_NOTIMPL);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// get_TicketAge -- get how long has passed since ticket was created
|
|
//
|
|
STDMETHODIMP CManager::get_TicketAge(int *pVal)
|
|
{
|
|
PassportLog("CManager::get_TicketAge:\r\n");
|
|
|
|
if (!m_piTicket)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
return m_piTicket->get_TicketAge(pVal);
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// get_TicketTime -- get when the ticket was created
|
|
//
|
|
|
|
STDMETHODIMP CManager::get_TicketTime(long *pVal)
|
|
{
|
|
PassportLog("CManager::get_TicketTime:\r\n");
|
|
|
|
if (!m_piTicket)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
return m_piTicket->get_TicketTime(pVal);
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// get_SignInTime -- get last signin time
|
|
//
|
|
STDMETHODIMP CManager::get_SignInTime(long *pVal)
|
|
{
|
|
PassportLog("CManager::get_SignInTime:\r\n");
|
|
|
|
if (!m_piTicket)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
return m_piTicket->get_SignInTime(pVal);
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// get_TimeSinceSignIn -- time passed since last signin
|
|
//
|
|
STDMETHODIMP CManager::get_TimeSinceSignIn(int *pVal)
|
|
{
|
|
PassportLog("CManager::get_TimeSinceSignIn:\r\n");
|
|
|
|
if (!m_piTicket)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
return m_piTicket->get_TimeSinceSignIn(pVal);
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// GetDomainAttribute -- return information defined in partner.xml file
|
|
//
|
|
STDMETHODIMP CManager::GetDomainAttribute(BSTR attributeName, VARIANT lcid, VARIANT domain, BSTR *pAttrVal)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
PassportLog("CManager::GetDomainAttribute Enter:\r\n");
|
|
|
|
if(attributeName == NULL || *attributeName == 0)
|
|
return E_INVALIDARG;
|
|
|
|
PassportLog(" %ws\r\n", attributeName);
|
|
|
|
if (!g_config || !g_config->isValid()) // Guarantees config is non-null
|
|
{
|
|
AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
|
|
IID_IPassportManager, PP_E_NOT_CONFIGURED);
|
|
return PP_E_NOT_CONFIGURED;
|
|
}
|
|
|
|
if (!m_pRegistryConfig)
|
|
m_pRegistryConfig = g_config->checkoutRegistryConfig();
|
|
|
|
if (!m_pRegistryConfig) // Guarantees config is non-null
|
|
{
|
|
AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
|
|
IID_IPassportManager, PP_E_NOT_CONFIGURED);
|
|
return PP_E_NOT_CONFIGURED;
|
|
}
|
|
|
|
LPWSTR d;
|
|
BSTR dn = NULL;
|
|
if (domain.vt == (VT_BSTR | VT_BYREF))
|
|
d = *domain.pbstrVal;
|
|
else if (domain.vt == VT_BSTR)
|
|
d = domain.bstrVal;
|
|
else if (domain.vt == (VT_VARIANT | VT_BYREF))
|
|
{
|
|
return GetDomainAttribute(attributeName, lcid, *(domain.pvarVal), pAttrVal);
|
|
}
|
|
else
|
|
{
|
|
// domain best be not filled in this case, that's why we reuse it here
|
|
// if not, let dfmn generate the error
|
|
HRESULT hr = DomainFromMemberName(domain, &dn);
|
|
if (hr != S_OK)
|
|
return hr;
|
|
TAKEOVER_BSTR(dn);
|
|
d = dn;
|
|
}
|
|
|
|
if (NULL != d)
|
|
{
|
|
PassportLog(" %ws\r\n", d);
|
|
}
|
|
|
|
CNexusConfig* cnc = g_config->checkoutNexusConfig();
|
|
USHORT sLcid = 0;
|
|
VARIANT innerLC;
|
|
VariantInit(&innerLC);
|
|
|
|
if (lcid.vt != VT_ERROR && VariantChangeType(&innerLC, &lcid, 0, VT_UI2) == S_OK)
|
|
sLcid = innerLC.iVal;
|
|
else
|
|
{
|
|
sLcid = m_pRegistryConfig->getDefaultLCID();
|
|
|
|
// Check user profile
|
|
if (!sLcid && m_profileValid)
|
|
{
|
|
m_piProfile->get_ByIndex(LANGPREF_INDEX, &innerLC);
|
|
if (innerLC.vt == VT_I2 || innerLC.vt == VT_UI2)
|
|
sLcid = innerLC.iVal;
|
|
VariantClear(&innerLC);
|
|
}
|
|
}
|
|
|
|
WCHAR data[PP_MAX_ATTRIBUTE_LENGTH] = L"";
|
|
cnc->getDomainAttribute(d,
|
|
attributeName,
|
|
sizeof(data)/sizeof(WCHAR),
|
|
data,
|
|
sLcid);
|
|
|
|
// try default domain
|
|
if (!(*data) && (!d || !(*d) || lstrcmpiW(d, L"Default")))
|
|
{
|
|
cnc->getDomainAttribute(L"Default",
|
|
attributeName,
|
|
sizeof(data)/sizeof(WCHAR),
|
|
data,
|
|
sLcid);
|
|
|
|
}
|
|
|
|
if (*data)
|
|
{
|
|
*pAttrVal = ALLOC_AND_GIVEAWAY_BSTR(data);
|
|
}
|
|
else
|
|
{
|
|
/* fix bug: 12102 -- for backward compitible, not to return error
|
|
hr = E_INVALIDARG;
|
|
*/
|
|
*pAttrVal = NULL;
|
|
}
|
|
cnc->Release();
|
|
if (dn) FREE_BSTR(dn);
|
|
|
|
PassportLog("CManager::GetDomainAttribute Exit: %X, %ws\r\n", hr, pAttrVal);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//===========================================================================
|
|
//
|
|
// DomainFromMemberName -- returns domain name with given user id
|
|
//
|
|
STDMETHODIMP CManager::DomainFromMemberName(VARIANT var, BSTR *pDomainName)
|
|
{
|
|
HRESULT hr;
|
|
LPWSTR psz, memberName;
|
|
VARIANT intoVar;
|
|
|
|
PassportLog("CManager::DomainFromMemberName Enter:\r\n");
|
|
|
|
VariantInit(&intoVar);
|
|
|
|
if (var.vt == (VT_BSTR | VT_BYREF))
|
|
memberName = *var.pbstrVal;
|
|
else if (var.vt == VT_BSTR)
|
|
memberName = var.bstrVal;
|
|
else if (var.vt == (VT_VARIANT | VT_BYREF))
|
|
{
|
|
return DomainFromMemberName(*(var.pvarVal), pDomainName);
|
|
}
|
|
else
|
|
{
|
|
// Try to get it from the profile
|
|
if (!m_profileValid)
|
|
{
|
|
*pDomainName = ALLOC_AND_GIVEAWAY_BSTR(L"Default");
|
|
return S_OK;
|
|
}
|
|
HRESULT hr = m_piProfile->get_Attribute(L"internalmembername", &intoVar);
|
|
if (hr != S_OK)
|
|
{
|
|
*pDomainName = NULL;
|
|
return hr;
|
|
}
|
|
if (VariantChangeType(&intoVar,&intoVar, 0, VT_BSTR) != S_OK)
|
|
{
|
|
AtlReportError(CLSID_Manager, L"PassportManager: Couldn't convert memberName to string. Call partner support.",
|
|
IID_IPassportManager, E_FAIL);
|
|
return E_FAIL;
|
|
}
|
|
memberName = intoVar.bstrVal;
|
|
}
|
|
|
|
|
|
if(memberName == NULL)
|
|
{
|
|
hr = E_POINTER;
|
|
goto Cleanup;
|
|
}
|
|
|
|
PassportLog(" %ws\r\n", memberName);
|
|
|
|
psz = wcsrchr(memberName, L'@');
|
|
if(psz == NULL)
|
|
{
|
|
// fix bug: 13380
|
|
// hr = E_INVALIDARG;
|
|
// goto Cleanup;
|
|
psz = L"@Default";
|
|
}
|
|
|
|
psz++;
|
|
|
|
*pDomainName = ALLOC_AND_GIVEAWAY_BSTR(psz);
|
|
hr = S_OK;
|
|
|
|
Cleanup:
|
|
VariantClear(&intoVar);
|
|
|
|
PassportLog("CManager::DomainFromMemberName Exit: %X\r\n", hr);
|
|
if (S_OK == hr)
|
|
{
|
|
PassportLog(" %ws\r\n", *pDomainName);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// get_Profile -- get property from profile property bag
|
|
//
|
|
STDMETHODIMP CManager::get_Profile(BSTR attributeName, VARIANT *pVal)
|
|
{
|
|
HRESULT hr = m_piProfile->get_Attribute(attributeName,pVal);
|
|
|
|
PassportLog("CManager::get_Profile: %ws\r\n", attributeName);
|
|
|
|
if(hr == S_OK && pVal->vt != VT_EMPTY)
|
|
{
|
|
if(g_pPerf)
|
|
{
|
|
g_pPerf->incrementCounter(PM_VALIDPROFILEREQ_SEC);
|
|
g_pPerf->incrementCounter(PM_VALIDPROFILEREQ_TOTAL);
|
|
}
|
|
else
|
|
{
|
|
_ASSERT(g_pPerf);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// put_Profile -- put property in profile property bag -- obselete
|
|
//
|
|
STDMETHODIMP CManager::put_Profile(BSTR attributeName, VARIANT newVal)
|
|
{
|
|
if (!m_piProfile)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
PassportLog("CManager::put_Profile: %ws\r\n", attributeName);
|
|
|
|
return m_piProfile->put_Attribute(attributeName,newVal);
|
|
}
|
|
|
|
|
|
//===========================================================================
|
|
//
|
|
// get_HexPUID
|
|
//
|
|
STDMETHODIMP CManager::get_HexPUID(BSTR *pVal)
|
|
{
|
|
PassportLog("CManager::get_HexPUID:\r\n");
|
|
|
|
if(!pVal) return E_INVALIDARG;
|
|
|
|
if (!m_piTicket)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
|
|
if(m_piTicket)
|
|
return m_piTicket->get_MemberId(pVal);
|
|
else
|
|
{
|
|
AtlReportError(CLSID_Manager, PP_E_INVALID_TICKETSTR,
|
|
IID_IPassportManager, PP_E_INVALID_TICKET);
|
|
return PP_E_INVALID_TICKET;
|
|
}
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// get_PUID
|
|
//
|
|
STDMETHODIMP CManager::get_PUID(BSTR *pVal)
|
|
{
|
|
PassportLog("CManager::get_HexPUID:\r\n");
|
|
|
|
if(!pVal) return E_INVALIDARG;
|
|
|
|
if(m_piTicket)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
WCHAR id[64] = L"0";
|
|
int l = 0;
|
|
int h = 0;
|
|
LARGE_INTEGER ui64;
|
|
|
|
|
|
hr = m_piTicket->get_MemberIdLow(&l);
|
|
if (S_OK != hr) return hr;
|
|
hr = m_piTicket->get_MemberIdHigh(&h);
|
|
if (S_OK != hr) return hr;
|
|
|
|
ui64.HighPart = h;
|
|
ui64.LowPart = l;
|
|
|
|
_ui64tow(ui64.QuadPart, id, 10);
|
|
|
|
*pVal = SysAllocString(id);
|
|
|
|
if(*pVal == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
else
|
|
{
|
|
AtlReportError(CLSID_Manager, PP_E_INVALID_TICKETSTR,
|
|
IID_IPassportManager, PP_E_INVALID_TICKET);
|
|
return PP_E_INVALID_TICKET;
|
|
}
|
|
}
|
|
|
|
STDMETHODIMP CManager::get_Option(
|
|
/* [in] */ BSTR name,
|
|
/* [retval][out] */ VARIANT *pVal)
|
|
{
|
|
if (!name || _wcsicmp(name, L"iMode") != 0 || !pVal)
|
|
return E_INVALIDARG;
|
|
VariantCopy(pVal, (VARIANT*)&m_iModeOption);
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CManager::put_Option(
|
|
/* [in] */ BSTR name,
|
|
/* [in] */ VARIANT newVal)
|
|
|
|
{
|
|
// support only this option for now.
|
|
if (!name || _wcsicmp(name, L"iMode") != 0)
|
|
return E_INVALIDARG;
|
|
m_iModeOption = newVal;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//===========================================================================
|
|
//
|
|
// get_Ticket -- get new introduced ticket property from the bag.
|
|
//
|
|
STDMETHODIMP CManager::get_Ticket(BSTR attributeName, VARIANT *pVal)
|
|
{
|
|
if (!m_piTicket)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
return m_piTicket->GetProperty(attributeName,pVal);
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// LogoutURL -- returns LogoutURL with given parameters
|
|
//
|
|
STDMETHODIMP CManager::LogoutURL(
|
|
/* [optional][in] */ VARIANT vRU,
|
|
/* [optional][in] */ VARIANT vCoBrand,
|
|
/* [optional][in] */ VARIANT lang_id,
|
|
/* [optional][in] */ VARIANT Namespace,
|
|
/* [optional][in] */ VARIANT bSecure,
|
|
/* [retval][out] */ BSTR __RPC_FAR *pVal)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
VARIANT_BOOL bUseSecure = VARIANT_FALSE;
|
|
BSTR CBT = NULL, returnUrl = NULL, bstrNameSpace = NULL;
|
|
int hasCB, hasRU, hasLCID, hasNameSpace, hasUseSec;
|
|
USHORT Lang;
|
|
WCHAR nameSpace[MAX_PATH] = L"";
|
|
bool bUrlFromSecureKey = false;
|
|
WCHAR UrlBuf[MAX_URL_LENGTH] = L"";
|
|
WCHAR retUrlBuf[MAX_URL_LENGTH] = L"";
|
|
DWORD bufLen = MAX_URL_LENGTH;
|
|
WCHAR qsLeadCh = L'?';
|
|
CNexusConfig* cnc = NULL;
|
|
int iRet = 0;
|
|
|
|
if (!pVal) return E_INVALIDARG;
|
|
|
|
if (!g_config)
|
|
{
|
|
return PP_E_NOT_CONFIGURED;
|
|
}
|
|
|
|
cnc = g_config->checkoutNexusConfig();
|
|
|
|
if (!m_pRegistryConfig)
|
|
m_pRegistryConfig = g_config->checkoutRegistryConfig();
|
|
|
|
|
|
if ((hasUseSec = GetBoolArg(bSecure, &bUseSecure)) == CV_BAD)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto Cleanup;
|
|
}
|
|
|
|
if ((hasLCID = GetShortArg(lang_id,&Lang)) == CV_BAD)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto Cleanup;
|
|
}
|
|
|
|
if (hasLCID == CV_DEFAULT)
|
|
Lang = m_pRegistryConfig->getDefaultLCID();
|
|
|
|
hasCB = GetBstrArg(vCoBrand, &CBT);
|
|
if (hasCB == CV_BAD)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto Cleanup;
|
|
}
|
|
|
|
hasRU = GetBstrArg(vRU, &returnUrl);
|
|
if (hasRU == CV_BAD)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto Cleanup;
|
|
}
|
|
|
|
hasNameSpace = GetBstrArg(Namespace, &bstrNameSpace);
|
|
if (hasNameSpace == CV_BAD)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto Cleanup;
|
|
}
|
|
// get the right URL -- namespace, secure
|
|
|
|
// namespace
|
|
if (!IsEmptyString(bstrNameSpace))
|
|
{
|
|
if(0 == _snwprintf(nameSpace, sizeof(nameSpace) / sizeof(WCHAR), L"%s", bstrNameSpace))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
if FAILED(hr)
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
if (hasCB == CV_DEFAULT)
|
|
CBT = m_pRegistryConfig->getDefaultCoBrand();
|
|
if (hasRU == CV_DEFAULT)
|
|
returnUrl = m_pRegistryConfig->getDefaultRU();
|
|
if (returnUrl == NULL)
|
|
returnUrl = L"";
|
|
|
|
|
|
|
|
if (*nameSpace == 0) // 0 length string
|
|
wcscpy(nameSpace, L"Default");
|
|
|
|
if(hasUseSec == CV_DEFAULT)
|
|
{
|
|
ULONG ulSecureLevel = m_pRegistryConfig->getSecureLevel();
|
|
bUseSecure = (SECURELEVEL_USE_HTTPS(ulSecureLevel)) ? VARIANT_TRUE : VARIANT_FALSE;
|
|
}
|
|
|
|
|
|
// secure
|
|
if(bUseSecure == VARIANT_TRUE)
|
|
{
|
|
cnc->getDomainAttribute(nameSpace,
|
|
L"LogoutSecure",
|
|
sizeof(UrlBuf)/sizeof(WCHAR),
|
|
UrlBuf,
|
|
Lang);
|
|
if (*UrlBuf != 0)
|
|
{
|
|
bUrlFromSecureKey = true;
|
|
}
|
|
}
|
|
|
|
// insecure
|
|
if (*UrlBuf == 0)
|
|
{
|
|
cnc->getDomainAttribute(nameSpace,
|
|
L"Logout",
|
|
sizeof(UrlBuf)/sizeof(WCHAR),
|
|
UrlBuf,
|
|
Lang);
|
|
}
|
|
// error case
|
|
if(*UrlBuf == 0)
|
|
{
|
|
AtlReportError(CLSID_Profile, PP_E_LOGOUTURL_NOTDEFINEDSTR,
|
|
IID_IPassportProfile, PP_E_LOGOUTURL_NOTDEFINED);
|
|
hr = PP_E_LOGOUTURL_NOTDEFINED;
|
|
goto Cleanup;
|
|
}
|
|
|
|
if(bUseSecure == VARIANT_TRUE && !bUrlFromSecureKey) // translate from http to https
|
|
{
|
|
if (_wcsnicmp(UrlBuf, L"http:", 5) == 0) // replace with HTTPS
|
|
{
|
|
memmove(UrlBuf + 5, UrlBuf + 4, sizeof(UrlBuf) - 5 * sizeof(WCHAR));
|
|
memcpy(UrlBuf, L"https", 5 * sizeof(WCHAR));
|
|
}
|
|
}
|
|
|
|
// us common function to append the thing one by one ...
|
|
if (wcsstr(UrlBuf, L"?")) // ? already exists in the URL, use & to start
|
|
qsLeadCh = L'&';
|
|
if (CBT)
|
|
_snwprintf(retUrlBuf, sizeof(retUrlBuf) / sizeof(WCHAR), L"%s%cid=%-d&ru=%s&lcid=%-d&cb=%s",
|
|
UrlBuf, qsLeadCh, m_pRegistryConfig->getSiteId(), returnUrl, Lang, CBT);
|
|
else
|
|
_snwprintf(retUrlBuf, sizeof(retUrlBuf) / sizeof(WCHAR), L"%s%cid=%-d&ru=%s&lcid=%-d",
|
|
UrlBuf, qsLeadCh, m_pRegistryConfig->getSiteId(), returnUrl, Lang);
|
|
|
|
|
|
*pVal = ALLOC_AND_GIVEAWAY_BSTR(retUrlBuf);
|
|
Cleanup:
|
|
if (NULL != cnc)
|
|
{
|
|
cnc->Release();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// get_ProfileByIndex -- get property value by index of the property
|
|
//
|
|
STDMETHODIMP CManager::get_ProfileByIndex(int index, VARIANT *pVal)
|
|
{
|
|
HRESULT hr = m_piProfile->get_ByIndex(index,pVal);
|
|
|
|
if(hr == S_OK && pVal->vt != VT_EMPTY)
|
|
{
|
|
if(g_pPerf)
|
|
{
|
|
g_pPerf->incrementCounter(PM_VALIDPROFILEREQ_SEC);
|
|
g_pPerf->incrementCounter(PM_VALIDPROFILEREQ_TOTAL);
|
|
}
|
|
else
|
|
{
|
|
_ASSERT(g_pPerf);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// put_ProfileByIndex -- put property value by index
|
|
//
|
|
STDMETHODIMP CManager::put_ProfileByIndex(int index, VARIANT newVal)
|
|
{
|
|
return m_piProfile->put_ByIndex(index,newVal);
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// handleQueryStringData -- authenticate with T & P from Query String
|
|
//
|
|
BOOL CManager::handleQueryStringData(BSTR a, BSTR p)
|
|
{
|
|
BOOL retVal; //whither to set cookies
|
|
HRESULT hr;
|
|
VARIANT vFalse;
|
|
_variant_t vFlags;
|
|
|
|
//
|
|
// check for empty ticket
|
|
//
|
|
if (!a || !*a)
|
|
return FALSE;
|
|
|
|
if (!m_piTicket || !m_piProfile)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
hr = DecryptTicketAndProfile(a, p, FALSE, NULL, m_pRegistryConfig, m_piTicket, m_piProfile);
|
|
|
|
if(hr != S_OK)
|
|
{
|
|
m_ticketValid = VARIANT_FALSE;
|
|
m_profileValid = VARIANT_FALSE;
|
|
retVal = FALSE;
|
|
goto Cleanup;
|
|
}
|
|
|
|
VariantInit(&vFalse);
|
|
vFalse.vt = VT_BOOL;
|
|
vFalse.boolVal = VARIANT_FALSE;
|
|
|
|
m_piTicket->get_IsAuthenticated(0,
|
|
VARIANT_FALSE,
|
|
vFalse,
|
|
&m_ticketValid);
|
|
|
|
if(!m_bSecureTransported) // secure bit should NOI set
|
|
{
|
|
if (S_OK == m_piTicket->GetProperty(ATTR_PASSPORTFLAGS, &vFlags))
|
|
{ // the bit should NOT set
|
|
if ( vFlags.vt == VT_I4 && (vFlags.lVal & k_ulFlagsSecuredTransportedTicket) != 0)
|
|
m_ticketValid = VARIANT_FALSE;
|
|
}
|
|
|
|
}
|
|
|
|
// let the ticket to valid if secure signin
|
|
if(m_ticketValid)
|
|
m_piTicket->DoSecureCheckInTicket(m_bSecureTransported);
|
|
|
|
// profile stuff
|
|
m_piProfile->get_IsValid(&m_profileValid);
|
|
|
|
if (m_ticketValid)
|
|
{
|
|
m_fromQueryString = true;
|
|
|
|
// Set the cookies
|
|
if (!m_pRegistryConfig->setCookiesP())
|
|
{
|
|
retVal = FALSE;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
retVal = FALSE;
|
|
goto Cleanup;
|
|
}
|
|
|
|
retVal = TRUE;
|
|
|
|
Cleanup:
|
|
|
|
return retVal;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// handleCookieData -- authenticate with cookies
|
|
//
|
|
BOOL CManager::handleCookieData(
|
|
BSTR auth,
|
|
BSTR prof,
|
|
BSTR consent,
|
|
BSTR secAuth
|
|
)
|
|
{
|
|
BOOL retVal;
|
|
HRESULT hr;
|
|
VARIANT vDoSecureCheck;
|
|
VARIANT_BOOL bValid;
|
|
_variant_t vFlags;
|
|
|
|
// bail out on empty cookie
|
|
if (!auth || !*auth)
|
|
return FALSE;
|
|
|
|
if (!m_piTicket || !m_piProfile)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// the consent cookie
|
|
if(consent != NULL && SysStringLen(consent) != 0)
|
|
{
|
|
hr = DecryptTicketAndProfile( auth,
|
|
prof,
|
|
!(m_pRegistryConfig->bInDA()),
|
|
consent,
|
|
m_pRegistryConfig,
|
|
m_piTicket,
|
|
m_piProfile);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// If regular cookie domain/path is identical to consent cookie domain/path, then
|
|
// MSPProf cookie is equivalent to consent cookie, and we should set m_bUsingConsentCookie
|
|
// to true
|
|
//
|
|
|
|
BOOL bCheckConsentCookie = (
|
|
lstrcmpA(m_pRegistryConfig->getTicketDomain(), m_pRegistryConfig->getProfileDomain())
|
|
|| lstrcmpA(m_pRegistryConfig->getTicketPath(), m_pRegistryConfig->getProfilePath())
|
|
);
|
|
|
|
hr = DecryptTicketAndProfile( auth,
|
|
prof,
|
|
!(m_pRegistryConfig->bInDA()) && bCheckConsentCookie,
|
|
NULL,
|
|
m_pRegistryConfig,
|
|
m_piTicket,
|
|
m_piProfile);
|
|
}
|
|
|
|
if(hr != S_OK)
|
|
{
|
|
m_ticketValid = VARIANT_FALSE;
|
|
m_profileValid = VARIANT_FALSE;
|
|
retVal = FALSE;
|
|
goto Cleanup;
|
|
}
|
|
|
|
VariantInit(&vDoSecureCheck);
|
|
vDoSecureCheck.vt = VT_BOOL;
|
|
|
|
if(secAuth && secAuth[0] && m_bSecureTransported)
|
|
{
|
|
if(DoSecureCheck(secAuth, m_pRegistryConfig, m_piTicket) == S_OK)
|
|
vDoSecureCheck.boolVal = VARIANT_TRUE;
|
|
else
|
|
vDoSecureCheck.boolVal = VARIANT_FALSE;
|
|
}
|
|
else
|
|
vDoSecureCheck.boolVal = VARIANT_FALSE;
|
|
|
|
m_piTicket->get_IsAuthenticated(0,
|
|
VARIANT_FALSE,
|
|
vDoSecureCheck,
|
|
&m_ticketValid);
|
|
|
|
// a partner cookie should not include the secure bit
|
|
if (!m_pRegistryConfig->bInDA() && S_OK == m_piTicket->GetProperty(ATTR_PASSPORTFLAGS, &vFlags))
|
|
{ // the bit should NOT set
|
|
if ( vFlags.vt == VT_I4 && (vFlags.lVal & k_ulFlagsSecuredTransportedTicket) != 0)
|
|
m_ticketValid = VARIANT_FALSE;
|
|
}
|
|
|
|
// for insecure case, the secure cookie should not come
|
|
if(!m_bSecureTransported && (secAuth && secAuth[0])) // this should not come
|
|
{
|
|
m_ticketValid = VARIANT_FALSE;
|
|
}
|
|
|
|
// profile stuff
|
|
m_piProfile->get_IsValid(&m_profileValid);
|
|
|
|
if(!m_ticketValid)
|
|
{
|
|
retVal = FALSE;
|
|
goto Cleanup;
|
|
}
|
|
|
|
retVal = TRUE;
|
|
|
|
Cleanup:
|
|
|
|
return retVal;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// get_HasSavedPassword -- if users chooses to persiste cookies
|
|
//
|
|
STDMETHODIMP CManager::get_HasSavedPassword(VARIANT_BOOL *pVal)
|
|
{
|
|
if (!m_piTicket)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
PassportLog("CManager::get_HasSavedPassword:\r\n");
|
|
|
|
// TODO: using flags for this
|
|
return m_piTicket->get_HasSavedPassword(pVal);
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// Commit -- post changes of profile back to the cookie
|
|
//
|
|
STDMETHODIMP CManager::Commit(BSTR *pNewProfileCookie)
|
|
{
|
|
PassportLog("CManager::Commit:\r\n");
|
|
|
|
if (!g_config) // Guarantees config is non-null
|
|
{
|
|
AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
|
|
IID_IPassportManager, PP_E_NOT_CONFIGURED);
|
|
return PP_E_NOT_CONFIGURED;
|
|
}
|
|
|
|
if (!m_pRegistryConfig)
|
|
m_pRegistryConfig = g_config->checkoutRegistryConfig();
|
|
|
|
if (!g_config->isValid() || !m_pRegistryConfig) // Guarantees config is non-null
|
|
{
|
|
AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
|
|
IID_IPassportManager, PP_E_NOT_CONFIGURED);
|
|
return PP_E_NOT_CONFIGURED;
|
|
}
|
|
|
|
if (!m_piTicket || !m_piProfile)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
if (!m_ticketValid || !m_profileValid)
|
|
{
|
|
AtlReportError(CLSID_Manager, PP_E_IT_FOR_COMMITSTR,
|
|
IID_IPassportManager, PP_E_INVALID_TICKET);
|
|
return PP_E_INVALID_TICKET;
|
|
}
|
|
|
|
// Write new passport profile cookie...
|
|
// return a safearray if we aren't used from ASP
|
|
BSTR newP = NULL;
|
|
HRESULT hr = m_piProfile->incrementVersion();
|
|
hr = m_piProfile->get_unencryptedProfile(&newP);
|
|
TAKEOVER_BSTR(newP);
|
|
|
|
if (hr != S_OK || newP == NULL)
|
|
{
|
|
AtlReportError(CLSID_Manager,
|
|
L"PassportManager.Commit: unknown failure.",
|
|
IID_IPassportManager, E_FAIL);
|
|
return E_FAIL;
|
|
}
|
|
|
|
CCoCrypt* crypt = NULL;
|
|
BSTR newCH = NULL;
|
|
crypt = m_pRegistryConfig->getCurrentCrypt(); // IsValid ensures this is non-null
|
|
if ((!crypt->Encrypt(m_pRegistryConfig->getCurrentCryptVersion(),
|
|
(LPSTR)newP,
|
|
SysStringByteLen(newP),
|
|
&newCH)) ||
|
|
!newCH)
|
|
{
|
|
AtlReportError(CLSID_Manager,
|
|
L"PassportManager.Commit: encryption failure.",
|
|
IID_IPassportManager, E_FAIL);
|
|
FREE_BSTR(newP);
|
|
return E_FAIL;
|
|
}
|
|
FREE_BSTR(newP);
|
|
TAKEOVER_BSTR(newCH);
|
|
|
|
if (m_bOnStartPageCalled)
|
|
{
|
|
if (m_pRegistryConfig->setCookiesP())
|
|
{
|
|
try
|
|
{
|
|
VARIANT_BOOL persist;
|
|
_bstr_t domain;
|
|
_bstr_t path;
|
|
|
|
if (m_pRegistryConfig->getTicketPath())
|
|
path = m_pRegistryConfig->getTicketPath();
|
|
else
|
|
path = L"/";
|
|
|
|
m_piTicket->get_HasSavedPassword(&persist);
|
|
IRequestDictionaryPtr piCookies = m_piResponse->Cookies;
|
|
|
|
VARIANT vtNoParam;
|
|
VariantInit(&vtNoParam);
|
|
vtNoParam.vt = VT_ERROR;
|
|
vtNoParam.scode = DISP_E_PARAMNOTFOUND;
|
|
|
|
IWriteCookiePtr piCookie = piCookies->Item[L"MSPProf"];
|
|
piCookie->Item[vtNoParam] = newCH;
|
|
domain = m_pRegistryConfig->getTicketDomain();
|
|
if (domain.length())
|
|
piCookie->put_Domain(domain);
|
|
if (persist)
|
|
piCookie->put_Expires(g_dtExpire);
|
|
piCookie->put_Path(path);
|
|
|
|
}
|
|
catch (...)
|
|
{
|
|
FREE_BSTR(newCH);
|
|
return E_FAIL;
|
|
}
|
|
}
|
|
}
|
|
GIVEAWAY_BSTR(newCH);
|
|
*pNewProfileCookie = newCH;
|
|
|
|
if(g_pPerf)
|
|
{
|
|
g_pPerf->incrementCounter(PM_PROFILECOMMITS_SEC);
|
|
g_pPerf->incrementCounter(PM_PROFILECOMMITS_TOTAL);
|
|
}
|
|
else
|
|
{
|
|
_ASSERT(g_pPerf);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// _Ticket -- ticket object property
|
|
//
|
|
STDMETHODIMP CManager::_Ticket(IPassportTicket** piTicket)
|
|
{
|
|
if (!m_piTicket)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
return m_piTicket->QueryInterface(IID_IPassportTicket,(void**)piTicket);
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// _Profile
|
|
//
|
|
STDMETHODIMP CManager::_Profile(IPassportProfile** piProfile)
|
|
{
|
|
return m_piProfile->QueryInterface(IID_IPassportProfile,(void**)piProfile);
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// DomainExists -- if a domain exists
|
|
//
|
|
STDMETHODIMP CManager::DomainExists(
|
|
BSTR bstrDomainName,
|
|
VARIANT_BOOL* pbExists
|
|
)
|
|
{
|
|
PassportLog("CManager::DomainExists Enter:\r\n");
|
|
|
|
if(!pbExists)
|
|
return E_INVALIDARG;
|
|
|
|
if(!bstrDomainName || (bstrDomainName[0] == L'\0'))
|
|
return E_INVALIDARG;
|
|
|
|
if(!g_config || !g_config->isValid())
|
|
{
|
|
AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
|
|
IID_IPassportManager, PP_E_NOT_CONFIGURED);
|
|
return PP_E_NOT_CONFIGURED;
|
|
}
|
|
|
|
CNexusConfig* cnc = g_config->checkoutNexusConfig();
|
|
|
|
*pbExists = cnc->DomainExists(bstrDomainName) ? VARIANT_TRUE : VARIANT_FALSE;
|
|
|
|
cnc->Release();
|
|
|
|
PassportLog("CManager::DomainExists Exit:\r\n");
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// get_Domains -- get a list of domains
|
|
//
|
|
STDMETHODIMP CManager::get_Domains(VARIANT *pArrayVal)
|
|
{
|
|
CNexusConfig* cnc = NULL;
|
|
LPCWSTR* arr = NULL;
|
|
int iArr = 0;
|
|
HRESULT hr;
|
|
|
|
PassportLog("CManager::get_Domains Enter:\r\n");
|
|
|
|
if (!pArrayVal)
|
|
return E_INVALIDARG;
|
|
|
|
if (!g_config || !g_config->isValid()) // Guarantees config is non-null
|
|
{
|
|
AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
|
|
IID_IPassportManager, PP_E_NOT_CONFIGURED);
|
|
return PP_E_NOT_CONFIGURED;
|
|
}
|
|
|
|
cnc = g_config->checkoutNexusConfig();
|
|
|
|
arr = cnc->getDomains(&iArr);
|
|
|
|
if (!arr || iArr == 0)
|
|
{
|
|
VariantClear(pArrayVal);
|
|
hr = S_OK;
|
|
goto Cleanup;
|
|
}
|
|
|
|
// Make a safearray with all the goods
|
|
SAFEARRAYBOUND rgsabound;
|
|
rgsabound.lLbound = 0;
|
|
rgsabound.cElements = iArr;
|
|
SAFEARRAY *sa = SafeArrayCreate(VT_VARIANT, 1, &rgsabound);
|
|
|
|
if (!sa)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
VariantInit(pArrayVal);
|
|
pArrayVal->vt = VT_ARRAY | VT_VARIANT;
|
|
pArrayVal->parray = sa;
|
|
|
|
VARIANT *vArray;
|
|
SafeArrayAccessData(sa, (void**)&vArray);
|
|
|
|
for (long i = 0; i < iArr; i++)
|
|
{
|
|
vArray[i].vt = VT_BSTR;
|
|
vArray[i].bstrVal = ALLOC_AND_GIVEAWAY_BSTR(arr[i]);
|
|
}
|
|
SafeArrayUnaccessData(sa);
|
|
|
|
hr = S_OK;
|
|
Cleanup:
|
|
if (arr)
|
|
{
|
|
delete[] arr;
|
|
}
|
|
if (NULL != cnc)
|
|
{
|
|
cnc->Release();
|
|
}
|
|
|
|
PassportLog("CManager::DomainExists Exit:\r\n");
|
|
|
|
return hr;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// get_Error -- get the error returned with &f query parameter
|
|
//
|
|
STDMETHODIMP CManager::get_Error(long* plError)
|
|
{
|
|
if(plError == NULL)
|
|
return E_INVALIDARG;
|
|
|
|
if(m_ticketValid)
|
|
{
|
|
if (!m_piTicket)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
m_piTicket->get_Error(plError);
|
|
if(*plError == 0)
|
|
*plError = m_lNetworkError;
|
|
}
|
|
else
|
|
{
|
|
*plError = m_lNetworkError;
|
|
}
|
|
|
|
PassportLog("CManager::get_Error: %X\r\n", *plError);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// GetServerInfo
|
|
//
|
|
STDMETHODIMP CManager::GetServerInfo(BSTR *pbstrOut)
|
|
{
|
|
if (!g_config || !g_config->isValid()) // Guarantees config is non-null
|
|
{
|
|
AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
|
|
IID_IPassportManager, PP_E_NOT_CONFIGURED);
|
|
return PP_E_NOT_CONFIGURED;
|
|
}
|
|
|
|
if(!m_pRegistryConfig)
|
|
// This only happens when OnStartPage was not called first.
|
|
m_pRegistryConfig = g_config->checkoutRegistryConfig();
|
|
|
|
if (!m_pRegistryConfig)
|
|
{
|
|
AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
|
|
IID_IPassportManager, PP_E_NOT_CONFIGURED);
|
|
return PP_E_NOT_CONFIGURED;
|
|
}
|
|
|
|
CNexusConfig* cnc = g_config->checkoutNexusConfig();
|
|
BSTR bstrVersion = cnc->GetXMLInfo();
|
|
cnc->Release();
|
|
|
|
WCHAR wszName[MAX_COMPUTERNAME_LENGTH+1];
|
|
DWORD dwSize = MAX_COMPUTERNAME_LENGTH+1;
|
|
GetComputerName(wszName, &dwSize);
|
|
|
|
*pbstrOut = ALLOC_AND_GIVEAWAY_BSTR_LEN(NULL,
|
|
wcslen(wszName) + ::SysStringLen(bstrVersion) + 2);
|
|
|
|
if (NULL == *pbstrOut)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
wcscpy(*pbstrOut, wszName);
|
|
BSTR p = *pbstrOut + wcslen(wszName);
|
|
*p = L' ';
|
|
wcsncpy(p+1, bstrVersion, ::SysStringLen(bstrVersion) + 1);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// HaveConsent -- if the user has the specified consent
|
|
//
|
|
STDMETHODIMP
|
|
CManager::HaveConsent(
|
|
VARIANT_BOOL bNeedFullConsent,
|
|
VARIANT_BOOL bNeedBirthdate,
|
|
VARIANT_BOOL* pbHaveConsent)
|
|
{
|
|
HRESULT hr;
|
|
ULONG flags = 0;
|
|
VARIANT vBdayPrecision;
|
|
BOOL bKid;
|
|
BOOL bConsentSatisfied;
|
|
ConsentStatusEnum ConsentCode = ConsentStatus_Unknown;
|
|
VARIANT_BOOL bRequireConsentCookie;
|
|
|
|
if(pbHaveConsent == NULL)
|
|
{
|
|
hr = E_POINTER;
|
|
goto Cleanup;
|
|
}
|
|
*pbHaveConsent = VARIANT_FALSE;
|
|
|
|
VariantInit(&vBdayPrecision);
|
|
|
|
if (!m_piTicket || !m_piProfile || !m_pRegistryConfig)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
// If the cookies came in on the query string then there is no consent cookie yet so don't
|
|
// require one. Otherwise check to see if the consent cookie domain or path is set
|
|
// differently than the cookie domain or path. If so (and we aren't in the DA domain) then
|
|
// the consent cookie is required.
|
|
bRequireConsentCookie = !m_fromQueryString &&
|
|
((lstrcmpA(m_pRegistryConfig->getTicketDomain(), m_pRegistryConfig->getProfileDomain())
|
|
|| lstrcmpA(m_pRegistryConfig->getTicketPath(), m_pRegistryConfig->getProfilePath()))
|
|
&& !(m_pRegistryConfig->bInDA())) ? VARIANT_TRUE : VARIANT_FALSE;
|
|
|
|
//
|
|
// Get flags.
|
|
//
|
|
|
|
hr = m_piTicket->ConsentStatus(bRequireConsentCookie, &flags, &ConsentCode); // ignore return value
|
|
|
|
if (hr != S_OK)
|
|
{
|
|
hr = S_OK;
|
|
goto Cleanup;
|
|
}
|
|
|
|
// if old ticket, we get the consent info from the profile
|
|
if(ConsentCode == ConsentStatus_NotDefinedInTicket)
|
|
{
|
|
// then we get from profile
|
|
VARIANT_BOOL bValid;
|
|
CComVariant vFlags;
|
|
m_piProfile->get_IsValid(&bValid);
|
|
|
|
if(bValid == VARIANT_FALSE)
|
|
{
|
|
hr = S_OK;
|
|
goto Cleanup;
|
|
}
|
|
|
|
hr = m_piProfile->get_Attribute(L"flags", &vFlags);
|
|
|
|
if(hr != S_OK)
|
|
goto Cleanup;
|
|
|
|
bKid = ((V_I4(&vFlags) & k_ulFlagsAccountType) == k_ulFlagsAccountTypeKid);
|
|
}
|
|
else
|
|
bKid = ((flags & k_ulFlagsAccountType) == k_ulFlagsAccountTypeKid);
|
|
|
|
// we should have the flags by now
|
|
//
|
|
// Do we have the requested level of consent?
|
|
//
|
|
|
|
bConsentSatisfied = bNeedFullConsent ? (flags & 0x60) == 0x40 :
|
|
(flags & 0x60) != 0;
|
|
|
|
if(bKid)
|
|
{
|
|
*pbHaveConsent = (bConsentSatisfied) ? VARIANT_TRUE : VARIANT_FALSE;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Make sure we have birthday if it was requested.
|
|
//
|
|
// no return value check need here, always returns S_OK.
|
|
VARIANT_BOOL bValid;
|
|
m_piProfile->get_IsValid(&bValid);
|
|
|
|
// if profile is not valid, then we don't have consent.
|
|
// return.
|
|
if(bValid == VARIANT_FALSE)
|
|
{
|
|
hr = S_OK;
|
|
goto Cleanup;
|
|
}
|
|
|
|
if(bNeedBirthdate)
|
|
{
|
|
hr = m_piProfile->get_Attribute(L"bday_precision", &vBdayPrecision);
|
|
if(hr != S_OK)
|
|
goto Cleanup;
|
|
|
|
*pbHaveConsent = (vBdayPrecision.iVal != 0 && vBdayPrecision.iVal != 3) ?
|
|
VARIANT_TRUE : VARIANT_FALSE;
|
|
}
|
|
else
|
|
*pbHaveConsent = VARIANT_TRUE;
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
Cleanup:
|
|
|
|
VariantClear(&vBdayPrecision);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//===========================================================================
|
|
//
|
|
// checkForPassportChallenge
|
|
//
|
|
//
|
|
// check the qs parameter. if challenge is requested,
|
|
// build the auth header and redirect with a modified qs
|
|
//
|
|
BOOL CManager::checkForPassportChallenge(IRequestDictionaryPtr piServerVariables)
|
|
{
|
|
BOOL fReturn = FALSE;
|
|
BSTR bstrBuf = NULL;
|
|
|
|
// just need the request string
|
|
_variant_t vtItemName, vtQueryString;
|
|
vtItemName = L"QUERY_STRING";
|
|
|
|
piServerVariables->get_Item(vtItemName, &vtQueryString);
|
|
if(vtQueryString.vt != VT_BSTR)
|
|
vtQueryString.ChangeType(VT_BSTR);
|
|
|
|
if (vtQueryString.bstrVal && *vtQueryString.bstrVal)
|
|
{
|
|
// check if pchg=1 is there. It is the first parameter ....
|
|
PWSTR psz = wcsstr(vtQueryString.bstrVal, L"pchg=1");
|
|
if (psz)
|
|
{
|
|
|
|
// we are in business. reformat the URL, insert the headers and
|
|
// redirect
|
|
psz = wcsstr(psz, PPLOGIN_PARAM);
|
|
_ASSERT(psz);
|
|
if (psz)
|
|
{
|
|
psz += wcslen(PPLOGIN_PARAM);
|
|
PWSTR pszEndLoginUrl = wcsstr(psz, L"&");
|
|
_ASSERT(pszEndLoginUrl);
|
|
if (pszEndLoginUrl)
|
|
{
|
|
*pszEndLoginUrl = L'\0';
|
|
// unescape the URL
|
|
// use temp buffer ...
|
|
DWORD cch = wcslen(psz) + 1;
|
|
bstrBuf = SysAllocStringLen(NULL, cch);
|
|
if (NULL == bstrBuf)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
if(!InternetCanonicalizeUrl(psz,
|
|
bstrBuf,
|
|
&cch,
|
|
ICU_DECODE | ICU_NO_ENCODE))
|
|
{
|
|
// what else can be done ???
|
|
_ASSERT(FALSE);
|
|
}
|
|
else
|
|
{
|
|
// copy the unescaped URL to the orig buffer
|
|
wcscpy(psz, (BSTR)bstrBuf);
|
|
// set headers first ...
|
|
// just use the qs param with some reformatting
|
|
_bstr_t bstrHeader;
|
|
|
|
if (HeaderFromQS(wcsstr(psz, L"?"), bstrHeader))
|
|
{
|
|
m_piResponse->AddHeader(L"WWW-Authenticate", bstrHeader);
|
|
// Url is ready, redirect ...
|
|
m_piResponse->Redirect(psz);
|
|
fReturn = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Cleanup:
|
|
if (bstrBuf)
|
|
{
|
|
SysFreeString(bstrBuf);
|
|
}
|
|
|
|
return fReturn;
|
|
}
|
|
|
|
|
|
//===========================================================================
|
|
//
|
|
// HeaderFromQS
|
|
//
|
|
//
|
|
// given a queryString, format the www-authenticate header
|
|
//
|
|
BOOL
|
|
CManager::HeaderFromQS(PWSTR pszQS, _bstr_t& bstrHeader)
|
|
{
|
|
// common header start ...
|
|
bstrHeader = PASSPORT_PROT14;
|
|
BOOL fSuccess = TRUE;
|
|
BSTR signature = NULL;
|
|
|
|
// advance thru any leading junk ...
|
|
while(!iswalnum(*pszQS) && *pszQS) pszQS++;
|
|
if (!*pszQS)
|
|
{
|
|
fSuccess = FALSE;
|
|
goto Cleanup;
|
|
}
|
|
|
|
WCHAR rgszValue[1000]; // buffer large enough for most values ...
|
|
PCWSTR psz = pszQS, pszNext = pszQS;
|
|
|
|
while(TRUE)
|
|
{
|
|
// no param name is more than 10 ....
|
|
WCHAR rgszName[10];
|
|
LONG cch = sizeof(rgszName)/sizeof(WCHAR);
|
|
PCWSTR pszName = psz;
|
|
|
|
while(*pszNext && *pszNext != L'&') pszNext++;
|
|
|
|
// grab the next qsparam
|
|
// name first
|
|
while(*pszName != L'=' && pszName < pszNext) pszName++;
|
|
|
|
_ASSERT(pszName != pszNext); // this should never happen
|
|
if (pszName == pszNext)
|
|
{
|
|
// and if it does, skip this parameter and return FALSE ...
|
|
fSuccess = FALSE;
|
|
goto Cleanup;
|
|
}
|
|
else
|
|
{
|
|
PWSTR pszVal = rgszValue;
|
|
ULONG cchVal;
|
|
|
|
_ASSERT((pszName - psz) <= cch);
|
|
wcsncpy(rgszName, psz, cch - 1);
|
|
rgszName[cch - 1] = L'\0';
|
|
|
|
// next comes the value
|
|
pszName++;
|
|
cchVal = (pszNext - pszName); // note these are PWSTR pointers so the result is length in characters
|
|
if (cchVal >= (sizeof(rgszValue) / sizeof(rgszValue[0])) )
|
|
{
|
|
// have to allocate ...
|
|
pszVal = new WCHAR[cchVal + 1];
|
|
if (!pszVal)
|
|
{
|
|
fSuccess = FALSE;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
// copy the value ...
|
|
wcsncpy(pszVal, pszName, cchVal );
|
|
pszVal[cchVal] = L'\0';
|
|
// and insert in the header ...
|
|
if (psz != pszQS)
|
|
// this is not the first param
|
|
bstrHeader += L",";
|
|
else
|
|
// first separator is a space ...
|
|
bstrHeader += L" ";
|
|
|
|
bstrHeader += _bstr_t(rgszName) + L"=" + pszVal;
|
|
|
|
if (pszVal != rgszValue)
|
|
// it was alloc'd
|
|
delete[] pszVal;
|
|
} // else '=' found
|
|
|
|
// leave loop
|
|
if (!*pszNext)
|
|
break;
|
|
psz = ++pszNext;
|
|
} // while
|
|
|
|
// sign the header
|
|
// actually the signature is on the qs
|
|
HRESULT hr = PartnerHash(m_pRegistryConfig,
|
|
m_pRegistryConfig->getCurrentCryptVersion(),
|
|
pszQS,
|
|
wcslen(pszQS),
|
|
&signature);
|
|
if (S_OK == hr)
|
|
{
|
|
bstrHeader += _bstr_t(L",tpf=") + (BSTR)signature;
|
|
}
|
|
else
|
|
{
|
|
fSuccess = FALSE;
|
|
}
|
|
|
|
Cleanup:
|
|
if (signature)
|
|
{
|
|
SysFreeString(signature);
|
|
}
|
|
return fSuccess;
|
|
}
|
|
|
|
|
|
//===========================================================================
|
|
//
|
|
// FormatAuthHeaderFromParams
|
|
//
|
|
//
|
|
// format WWW-Auth from parameters
|
|
//
|
|
STDMETHODIMP CManager::FormatAuthHeaderFromParams(PCWSTR pszLoginUrl, // unused for now
|
|
PCWSTR pszRetUrl,
|
|
ULONG ulTimeWindow,
|
|
BOOL fForceLogin,
|
|
time_t ct,
|
|
PCWSTR pszCBT, // unused for now
|
|
PCWSTR pszNamespace,
|
|
int nKpp,
|
|
PWSTR pszLCID, // tweener needs the LCID
|
|
ULONG ulSecureLevel,
|
|
_bstr_t& strHeader // return result
|
|
)
|
|
{
|
|
WCHAR temp[40];
|
|
|
|
// based on the spec ...
|
|
// lcid is not really needed, however it is present when
|
|
// header is created from qs and it's used
|
|
strHeader = _bstr_t(PASSPORT_PROT14) + L" lc=" + pszLCID;
|
|
|
|
// site=
|
|
strHeader += "&id=";
|
|
_ultow(m_pRegistryConfig->getSiteId(), temp, 10);
|
|
strHeader += temp;
|
|
|
|
// rtw=
|
|
strHeader += "&tw=";
|
|
_ultow(ulTimeWindow, temp, 10);
|
|
strHeader += temp;
|
|
|
|
if (fForceLogin)
|
|
{
|
|
strHeader += _bstr_t("&fs=1");
|
|
}
|
|
if (pszNamespace && *pszNamespace)
|
|
{
|
|
strHeader += _bstr_t("&ns=") + pszNamespace;
|
|
}
|
|
// ru=
|
|
strHeader += _bstr_t("&ru=") + pszRetUrl;
|
|
|
|
// ct=
|
|
_ultow(ct, temp, 10);
|
|
strHeader += _bstr_t(L"&ct=") + temp;
|
|
|
|
// kpp
|
|
if (nKpp != -1)
|
|
{
|
|
_ultow(nKpp, temp, 10);
|
|
strHeader += _bstr_t(L"&kpp=") + temp;
|
|
}
|
|
|
|
// key version and version
|
|
_ultow(m_pRegistryConfig->getCurrentCryptVersion(), temp, 10);
|
|
strHeader += _bstr_t(L"&kv=") + temp;
|
|
strHeader += _bstr_t(L"&ver=") + GetVersionString();
|
|
|
|
// secure level
|
|
if (ulSecureLevel)
|
|
{
|
|
strHeader += _bstr_t(L"&seclog=") + _ultow(ulSecureLevel, temp, 10);
|
|
}
|
|
|
|
// sign the header
|
|
BSTR signature = NULL;
|
|
PWSTR szStart = wcsstr(strHeader, L"lc=");
|
|
HRESULT hr = PartnerHash(m_pRegistryConfig,
|
|
m_pRegistryConfig->getCurrentCryptVersion(),
|
|
szStart,
|
|
strHeader.length() - (szStart - strHeader),
|
|
&signature);
|
|
// replace '&' with ','
|
|
BSTR psz = (BSTR)strHeader;
|
|
while (*psz)
|
|
{
|
|
if (*psz == L'&') *psz = L',';
|
|
psz++;
|
|
}
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
strHeader += _bstr_t(L",tpf=") + (BSTR)signature;
|
|
}
|
|
|
|
if (signature)
|
|
{
|
|
SysFreeString(signature);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
//
|
|
// GetLoginParams
|
|
//
|
|
//
|
|
// common code to parse user's parameters
|
|
// and get defaults from registry config
|
|
//
|
|
STDMETHODIMP CManager::GetLoginParams(VARIANT vRU,
|
|
VARIANT vTimeWindow,
|
|
VARIANT vForceLogin,
|
|
VARIANT vCoBrand,
|
|
VARIANT vLCID,
|
|
VARIANT vNameSpace,
|
|
VARIANT vKPP,
|
|
VARIANT vSecureLevel,
|
|
// these are the processed values
|
|
_bstr_t& strUrl,
|
|
_bstr_t& strReturnUrl,
|
|
UINT& TimeWindow,
|
|
VARIANT_BOOL& ForceLogin,
|
|
time_t& ct,
|
|
_bstr_t& strCBT,
|
|
_bstr_t& strNameSpace,
|
|
int& nKpp,
|
|
ULONG& ulSecureLevel,
|
|
PWSTR pszLCID)
|
|
{
|
|
USES_CONVERSION;
|
|
LPCWSTR url;
|
|
VARIANT freeMe;
|
|
BSTR CBT = NULL, returnUrl = NULL, bstrNameSpace = NULL;
|
|
int hasCB, hasRU, hasLCID, hasTW, hasFL, hasNameSpace, hasKPP, hasUseSec;
|
|
USHORT Lang;
|
|
CNexusConfig* cnc = NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
PassportLog("CManager::GetLoginParams Enter:\r\n");
|
|
|
|
if (!g_config) // Guarantees config is non-null
|
|
{
|
|
AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
|
|
IID_IPassportManager, PP_E_NOT_CONFIGURED);
|
|
return PP_E_NOT_CONFIGURED;
|
|
}
|
|
|
|
if (!m_pRegistryConfig)
|
|
m_pRegistryConfig = g_config->checkoutRegistryConfig();
|
|
|
|
if (!g_config->isValid() || !m_pRegistryConfig) // Guarantees config is non-null
|
|
{
|
|
AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
|
|
IID_IPassportManager, PP_E_NOT_CONFIGURED);
|
|
return PP_E_NOT_CONFIGURED;
|
|
}
|
|
|
|
// Make sure args are of the right type
|
|
if ((hasTW = GetIntArg(vTimeWindow, (int*) &TimeWindow)) == CV_BAD)
|
|
return E_INVALIDARG;
|
|
if ((hasFL = GetBoolArg(vForceLogin, &ForceLogin)) == CV_BAD)
|
|
return E_INVALIDARG;
|
|
if ((hasUseSec = GetIntArg(vSecureLevel, (int*)&ulSecureLevel)) == CV_BAD)
|
|
return E_INVALIDARG;
|
|
if ((hasLCID = GetShortArg(vLCID, &Lang)) == CV_BAD)
|
|
return E_INVALIDARG;
|
|
if ((hasKPP = GetIntArg(vKPP, &nKpp)) == CV_BAD)
|
|
return E_INVALIDARG;
|
|
hasCB = GetBstrArg(vCoBrand, &CBT);
|
|
if (hasCB == CV_BAD)
|
|
return E_INVALIDARG;
|
|
strCBT = CBT;
|
|
if (hasCB == CV_FREE)
|
|
{
|
|
TAKEOVER_BSTR(CBT);
|
|
}
|
|
|
|
hasRU = GetBstrArg(vRU, &returnUrl);
|
|
if (hasRU == CV_BAD)
|
|
{
|
|
if (hasCB == CV_FREE && CBT)
|
|
FREE_BSTR(CBT);
|
|
return E_INVALIDARG;
|
|
}
|
|
strReturnUrl = returnUrl;
|
|
if (hasRU == CV_FREE)
|
|
{
|
|
FREE_BSTR(returnUrl);
|
|
}
|
|
|
|
hasNameSpace = GetBstrArg(vNameSpace, &bstrNameSpace);
|
|
if (hasNameSpace == CV_BAD)
|
|
{
|
|
if (hasCB == CV_FREE && CBT)
|
|
FREE_BSTR(CBT);
|
|
return E_INVALIDARG;
|
|
}
|
|
if (hasNameSpace == CV_OK)
|
|
strNameSpace = bstrNameSpace;
|
|
if (hasNameSpace == CV_FREE)
|
|
{
|
|
FREE_BSTR(bstrNameSpace);
|
|
}
|
|
if (hasNameSpace == CV_DEFAULT)
|
|
{
|
|
if (NULL == m_pRegistryConfig->getNameSpace())
|
|
{
|
|
strNameSpace = L"";
|
|
}
|
|
else
|
|
{
|
|
strNameSpace = m_pRegistryConfig->getNameSpace();
|
|
}
|
|
}
|
|
|
|
if(hasUseSec == CV_DEFAULT)
|
|
ulSecureLevel = m_pRegistryConfig->getSecureLevel();
|
|
|
|
if(ulSecureLevel == VARIANT_TRUE) // special case for backward compatible
|
|
ulSecureLevel = k_iSeclevelSecureChannel;
|
|
|
|
WCHAR *szAUAttrName;
|
|
if (SECURELEVEL_USE_HTTPS(ulSecureLevel))
|
|
szAUAttrName = L"AuthSecure";
|
|
else
|
|
szAUAttrName = L"Auth";
|
|
|
|
cnc = g_config->checkoutNexusConfig();
|
|
|
|
if (hasLCID == CV_DEFAULT)
|
|
Lang = m_pRegistryConfig->getDefaultLCID();
|
|
if (hasKPP == CV_DEFAULT)
|
|
nKpp = m_pRegistryConfig->getKPP();
|
|
|
|
// convert the LCID to str for tweener ...
|
|
_itow((int)Lang, pszLCID, 10);
|
|
VariantInit(&freeMe);
|
|
|
|
// **************************************************
|
|
// Logging
|
|
if (NULL != returnUrl)
|
|
{
|
|
PassportLog(" RU = %ws\r\n", returnUrl);
|
|
}
|
|
PassportLog(" TW = %X, SL = %X, L = %d, KPP = %X\r\n", TimeWindow, ulSecureLevel, Lang, nKpp);
|
|
if (NULL != CBT)
|
|
{
|
|
PassportLog(" CBT = %ws\r\n", CBT);
|
|
}
|
|
// **************************************************
|
|
|
|
if (!m_pRegistryConfig->DisasterModeP())
|
|
{
|
|
// If I'm authenticated, get my domain specific url
|
|
WCHAR UrlBuf[MAX_URL_LENGTH];
|
|
if (m_ticketValid && m_profileValid)
|
|
{
|
|
HRESULT hr = m_piProfile->get_ByIndex(MEMBERNAME_INDEX, &freeMe);
|
|
if (hr != S_OK || freeMe.vt != VT_BSTR)
|
|
{
|
|
cnc->getDomainAttribute(L"Default",
|
|
szAUAttrName,
|
|
sizeof(UrlBuf)/sizeof(WCHAR),
|
|
UrlBuf,
|
|
Lang);
|
|
strUrl = UrlBuf;
|
|
}
|
|
else
|
|
{
|
|
LPCWSTR psz = wcsrchr(freeMe.bstrVal, L'@');
|
|
cnc->getDomainAttribute(psz ? psz+1 : L"Default",
|
|
szAUAttrName,
|
|
sizeof(UrlBuf)/sizeof(WCHAR),
|
|
UrlBuf,
|
|
Lang);
|
|
strUrl = UrlBuf;
|
|
}
|
|
}
|
|
if (strUrl.length() == 0)
|
|
{
|
|
cnc->getDomainAttribute(L"Default",
|
|
szAUAttrName,
|
|
sizeof(UrlBuf)/sizeof(WCHAR),
|
|
UrlBuf,
|
|
Lang);
|
|
strUrl = UrlBuf;
|
|
}
|
|
}
|
|
else
|
|
strUrl = m_pRegistryConfig->getDisasterUrl();
|
|
|
|
_ASSERT(strUrl.length() != 0);
|
|
|
|
time(&ct);
|
|
|
|
if (hasTW == CV_DEFAULT)
|
|
TimeWindow = m_pRegistryConfig->getDefaultTicketAge();
|
|
if (hasFL == CV_DEFAULT)
|
|
ForceLogin = m_pRegistryConfig->forceLoginP() ? VARIANT_TRUE : VARIANT_FALSE;
|
|
if (hasCB == CV_DEFAULT)
|
|
strCBT = m_pRegistryConfig->getDefaultCoBrand();
|
|
if (hasRU == CV_DEFAULT)
|
|
strReturnUrl = m_pRegistryConfig->getDefaultRU() ?
|
|
m_pRegistryConfig->getDefaultRU() : L"";
|
|
|
|
if ((TimeWindow != 0 && TimeWindow < PPM_TIMEWINDOW_MIN) || TimeWindow > PPM_TIMEWINDOW_MAX)
|
|
{
|
|
AtlReportError(CLSID_Manager, (LPCOLESTR) PP_E_INVALID_TIMEWINDOWSTR,
|
|
IID_IPassportManager, PP_E_INVALID_TIMEWINDOW);
|
|
hr = PP_E_INVALID_TIMEWINDOW;
|
|
goto Cleanup;
|
|
}
|
|
|
|
Cleanup:
|
|
if (NULL != cnc)
|
|
{
|
|
cnc->Release();
|
|
}
|
|
|
|
VariantClear(&freeMe);
|
|
|
|
PassportLog("CManager::GetLoginParams Exit: %X\r\n", hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// GetTicketAndProfileFromHeader
|
|
//
|
|
//
|
|
// get ticket & profile from auth header
|
|
// params:
|
|
// AuthHeader - [in/out] contents of HTTP_Authorization header
|
|
// pszTicket - [out] ptr to the ticket part in the header
|
|
// pszProfile -[out] ptr to the profile
|
|
// pwszF - [out] ptr to error coming in the header
|
|
// Auth header contents is changed as a side effect of the function
|
|
//
|
|
static VOID GetTicketAndProfileFromHeader(PWSTR pszAuthHeader,
|
|
PWSTR& pszTicket,
|
|
PWSTR& pszProfile,
|
|
PWSTR& pszF)
|
|
{
|
|
// check for t=, p=, and f=
|
|
if (pszAuthHeader && *pszAuthHeader)
|
|
{
|
|
// format is 'Authorization: from-PP='t=xxx&p=xxx'
|
|
PWSTR pwsz = wcsstr(pszAuthHeader, L"from-PP");
|
|
if (pwsz)
|
|
{
|
|
// ticket and profile are enclosed in ''. Not very strict parsing indeed ....
|
|
while(*pwsz != L'\'' && *pwsz)
|
|
pwsz++;
|
|
if (*pwsz++)
|
|
{
|
|
if (*pwsz == L'f')
|
|
{
|
|
pwsz++;
|
|
if (*pwsz == L'=')
|
|
{
|
|
pwsz++;
|
|
// error case
|
|
pszF = pwsz;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// ticket and profile ...
|
|
_ASSERT(*pwsz == L't');
|
|
if (*pwsz == L't')
|
|
{
|
|
pwsz++;
|
|
if (*pwsz == L'=')
|
|
{
|
|
pwsz++;
|
|
pszTicket = pwsz;
|
|
}
|
|
}
|
|
|
|
while(*pwsz != L'&' && *pwsz)
|
|
pwsz++;
|
|
|
|
if (*pwsz)
|
|
*pwsz++ = L'\0';
|
|
|
|
if (*pwsz == L'p')
|
|
{
|
|
pwsz++;
|
|
if (*pwsz == L'=')
|
|
{
|
|
pwsz++;
|
|
pszProfile = pwsz;
|
|
}
|
|
}
|
|
// finally remove the last '
|
|
}
|
|
// set \0 terminator
|
|
while(*pwsz != L'\'' && *pwsz)
|
|
pwsz++;
|
|
if (*pwsz)
|
|
*pwsz = L'\0';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// IPassportService implementation
|
|
|
|
//===========================================================================
|
|
//
|
|
// Initialize
|
|
//
|
|
STDMETHODIMP CManager::Initialize(BSTR configfile, IServiceProvider* p)
|
|
{
|
|
HRESULT hr;
|
|
|
|
// Initialized?
|
|
if (!g_config || !g_config->isValid()) // This calls UpdateNow if not yet initialized.
|
|
{
|
|
AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
|
|
IID_IPassportService, PP_E_NOT_CONFIGURED);
|
|
hr = PP_E_NOT_CONFIGURED;
|
|
goto Cleanup;
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
Cleanup:
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//===========================================================================
|
|
//
|
|
// Shutdown
|
|
//
|
|
STDMETHODIMP CManager::Shutdown()
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//===========================================================================
|
|
//
|
|
// ReloadState
|
|
//
|
|
STDMETHODIMP CManager::ReloadState(IServiceProvider*)
|
|
{
|
|
HRESULT hr;
|
|
|
|
// Initialize.
|
|
|
|
if(!g_config || !g_config->PrepareUpdate(TRUE))
|
|
{
|
|
AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
|
|
IID_IPassportService, PP_E_NOT_CONFIGURED);
|
|
hr = PP_E_NOT_CONFIGURED;
|
|
goto Cleanup;
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
Cleanup:
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//===========================================================================
|
|
//
|
|
// CommitState
|
|
//
|
|
STDMETHODIMP CManager::CommitState(IServiceProvider*)
|
|
{
|
|
HRESULT hr;
|
|
|
|
// Finish the two phase update.
|
|
if(!g_config || !g_config->CommitUpdate())
|
|
{
|
|
AtlReportError(CLSID_Manager, PP_E_NOT_CONFIGUREDSTR,
|
|
IID_IPassportService, PP_E_NOT_CONFIGURED);
|
|
hr = PP_E_NOT_CONFIGURED;
|
|
goto Cleanup;
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
Cleanup:
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//===========================================================================
|
|
//
|
|
// DumpState
|
|
//
|
|
STDMETHODIMP CManager::DumpState(BSTR* pbstrState)
|
|
{
|
|
ATLASSERT( *pbstrState != NULL &&
|
|
"CManager:DumpState - "
|
|
"Are you sure you want to hand me a non-null BSTR?" );
|
|
|
|
if(!g_config)
|
|
{
|
|
return PP_E_NOT_CONFIGURED;
|
|
}
|
|
|
|
g_config->Dump(pbstrState);
|
|
|
|
return S_OK;
|
|
}
|