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.
923 lines
24 KiB
923 lines
24 KiB
/**********************************************************************/
|
|
/** Microsoft Passport **/
|
|
/** Copyright(c) Microsoft Corporation, 1999 - 2001 **/
|
|
/**********************************************************************/
|
|
|
|
/*
|
|
Ticket.cpp
|
|
|
|
|
|
FILE HISTORY:
|
|
|
|
*/
|
|
|
|
|
|
// Ticket.cpp : Implementation of CTicket
|
|
#include "stdafx.h"
|
|
#include "Passport.h"
|
|
#include "Ticket.h"
|
|
#include <time.h>
|
|
#include <nsconst.h>
|
|
#include "variantutils.h"
|
|
#include "helperfuncs.h"
|
|
|
|
// gmarks
|
|
#include "Monitoring.h"
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CTicket
|
|
|
|
//===========================================================================
|
|
//
|
|
// InterfaceSupportsErrorInfo
|
|
//
|
|
STDMETHODIMP CTicket::InterfaceSupportsErrorInfo(REFIID riid)
|
|
{
|
|
static const IID* arr[] =
|
|
{
|
|
&IID_IPassportTicket,
|
|
&IID_IPassportTicket2
|
|
};
|
|
for (int i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
|
|
{
|
|
if (InlineIsEqualGUID(*arr[i],riid))
|
|
return S_OK;
|
|
}
|
|
return S_FALSE;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// SetTertiaryConsent
|
|
//
|
|
STDMETHODIMP CTicket::SetTertiaryConsent(BSTR bstrConsent)
|
|
{
|
|
_ASSERT(m_raw);
|
|
|
|
if(!m_valid ) return S_FALSE;
|
|
if(!bstrConsent) return E_INVALIDARG;
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if(SysStringByteLen(bstrConsent) != sizeof(long) * 4 ||
|
|
memcmp(m_raw, bstrConsent, sizeof(long) * 2) != 0 )
|
|
hr = E_INVALIDARG;
|
|
else
|
|
{
|
|
try{
|
|
m_bstrTertiaryConsent = bstrConsent;
|
|
}
|
|
catch(...)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// needConsent -- if consent cookie is needed,
|
|
// return the flags related to kids passport
|
|
//
|
|
HRESULT CTicket::ConsentStatus(
|
|
VARIANT_BOOL bRequireConsentCookie,
|
|
ULONG* pStatus,
|
|
ConsentStatusEnum* pConsentCode)
|
|
{
|
|
ConsentStatusEnum ret = ConsentStatus_Unknown;
|
|
ULONG status = 0;
|
|
u_long ulTmp;
|
|
|
|
if (m_bstrTertiaryConsent &&
|
|
SysStringByteLen(m_bstrTertiaryConsent) >= sizeof(long) * 4)
|
|
{
|
|
ULONG* pData = (ULONG*)(BSTR)m_bstrTertiaryConsent;
|
|
memcpy((PBYTE)&ulTmp, (PBYTE)(pData + 3), sizeof(ulTmp));
|
|
status = (ntohl(ulTmp) & k_ulFlagsConsentCookieMask);
|
|
ret = ConsentStatus_Known;
|
|
}
|
|
else
|
|
{
|
|
TicketProperty prop;
|
|
|
|
// 1.X ticket, with no flags in it
|
|
if (S_OK != m_PropBag.GetProperty(ATTR_PASSPORTFLAGS, prop))
|
|
{
|
|
ret = ConsentStatus_NotDefinedInTicket;
|
|
goto Exit;
|
|
}
|
|
|
|
ULONG flags = GetPassportFlags();
|
|
|
|
if(flags & k_ulFlagsConsentCookieNeeded)
|
|
{
|
|
if (bRequireConsentCookie)
|
|
{
|
|
ret = ConsentStatus_Unknown;
|
|
flags = flags & k_ulFlagsAccountType;
|
|
}
|
|
else
|
|
{
|
|
ret = ConsentStatus_Known;
|
|
}
|
|
}
|
|
else
|
|
ret = ConsentStatus_DoNotNeed;
|
|
|
|
status = (flags & k_ulFlagsConsentCookieMask);
|
|
}
|
|
|
|
Exit:
|
|
if(pConsentCode)
|
|
*pConsentCode = ret;
|
|
|
|
if (pStatus)
|
|
*pStatus = status;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// get_unencryptedCookie
|
|
//
|
|
STDMETHODIMP
|
|
CTicket::get_unencryptedCookie(ULONG cookieType, ULONG flags, BSTR *pVal)
|
|
{
|
|
PassportLog("CTicket::get_unencryptedCookie :\r\n");
|
|
|
|
if (!m_raw) return S_FALSE;
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if (!pVal || flags != 0) return E_INVALIDARG;
|
|
|
|
switch(cookieType)
|
|
{
|
|
case MSPAuth:
|
|
*pVal = SysAllocStringByteLen((LPSTR)m_raw, SysStringByteLen(m_raw));
|
|
|
|
if (*pVal)
|
|
{
|
|
// if the secure flags is on, we should turn it off for this cookie always
|
|
TicketProperty prop;
|
|
|
|
if (S_OK == m_PropBag.GetProperty(ATTR_PASSPORTFLAGS, prop))
|
|
{
|
|
if (prop.value.vt == VT_I4
|
|
&& ((prop.value.lVal & k_ulFlagsSecuredTransportedTicket) != 0))
|
|
// we need to turn off the bit
|
|
{
|
|
ULONG l = prop.value.lVal;
|
|
l &= (~k_ulFlagsSecuredTransportedTicket); // unset the bit
|
|
|
|
// put the modified flags into the buffer.
|
|
u_long ulTmp;
|
|
ulTmp = htonl(l);
|
|
memcpy(((PBYTE)(*pVal)) + m_schemaDrivenOffset + prop.offset, (PBYTE)&ulTmp, sizeof(ulTmp));
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case MSPSecAuth:
|
|
|
|
// ticket should be long enough
|
|
_ASSERT(SysStringByteLen(m_raw) > sizeof(long) * 3);
|
|
|
|
// the first 3 long fields of the ticket
|
|
// format:
|
|
// four bytes network long - low memberId bytes
|
|
// four bytes network long - high memberId bytes
|
|
// four bytes network long - time of last refresh
|
|
//
|
|
|
|
// generate a shorter version of the cookie for secure signin
|
|
*pVal = SysAllocStringByteLen((LPSTR)m_raw, sizeof(long) * 3);
|
|
|
|
break;
|
|
|
|
case MSPConsent:
|
|
|
|
// ticket should be long enough
|
|
_ASSERT(SysStringByteLen(m_raw) > sizeof(long) * 3);
|
|
|
|
// check if there is consent
|
|
// if (GetPassportFlags() & k_ulFlagsConsentStatus)
|
|
// we always write consent cookie even if there is no consent
|
|
if (GetPassportFlags() & k_ulFlagsConsentCookieNeeded)
|
|
{
|
|
// the first 3 long fields of the ticket
|
|
// format:
|
|
// four bytes network long - low memberId bytes
|
|
// four bytes network long - high memberId bytes
|
|
// four bytes network long - time of last refresh
|
|
//
|
|
// plus the consent flags -- long
|
|
//
|
|
|
|
// generate a shorter version of the cookie for secure signin
|
|
*pVal = SysAllocStringByteLen((LPSTR)m_raw, sizeof(long) * 4);
|
|
|
|
// plus the consent flags -- long
|
|
//
|
|
if (*pVal)
|
|
{
|
|
long* pl = (long*)pVal;
|
|
// we mask the flags, and put into the cookie
|
|
*(pl + 3) = htonl(GetPassportFlags() & k_ulFlagsConsentCookieMask);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*pVal = NULL;
|
|
hr = S_FALSE;
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
hr = E_INVALIDARG;
|
|
break;
|
|
}
|
|
|
|
if (*pVal == 0 && hr == S_OK)
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
return hr;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// get_unencryptedTicket
|
|
//
|
|
STDMETHODIMP CTicket::get_unencryptedTicket(BSTR *pVal)
|
|
{
|
|
PassportLog("CTicket::get_unencryptedTicket :\r\n");
|
|
|
|
*pVal = SysAllocStringByteLen((LPSTR)m_raw, SysStringByteLen(m_raw));
|
|
|
|
PassportLog(" %ws\r\n", m_raw);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// put_unencryptedTicket
|
|
//
|
|
STDMETHODIMP CTicket::put_unencryptedTicket(BSTR newVal)
|
|
{
|
|
DWORD dw13Xlen = 0;
|
|
|
|
PassportLog("CTicket::put_unencryptedTicket Enter:\r\n");
|
|
|
|
if (m_raw)
|
|
{
|
|
PassportLog(" T = %ws\r\n", m_raw);
|
|
|
|
SysFreeString(m_raw);
|
|
m_raw = NULL;
|
|
}
|
|
|
|
if (!newVal)
|
|
{
|
|
m_valid = FALSE;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
m_bSecureCheckSucceeded = FALSE;
|
|
|
|
// BOY do you have to be careful here. If you don't
|
|
// call BYTE version, it truncates at first pair of NULLs
|
|
// we also need to go past the key version byte
|
|
DWORD dwByteLen = SysStringByteLen(newVal);
|
|
{
|
|
m_raw = SysAllocStringByteLen((LPSTR)newVal,
|
|
dwByteLen);
|
|
if (NULL == m_raw)
|
|
{
|
|
m_valid = FALSE;
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
PPTracePrintBlob(PPTRACE_RAW, "Ticket:", (LPBYTE)newVal, dwByteLen, TRUE);
|
|
|
|
// parse the 1.3X ticket data
|
|
parse(m_raw, dwByteLen, &dw13Xlen);
|
|
|
|
PPTracePrint(PPTRACE_RAW, "ticket: len=%d, len1.x=%d, len2=%d", dwByteLen, dw13Xlen, dwByteLen - dw13Xlen);
|
|
|
|
// parse the schema driven data
|
|
if (dwByteLen > dw13Xlen) // more data to parse
|
|
{
|
|
// the offset related to the raw data
|
|
m_schemaDrivenOffset = dw13Xlen;
|
|
|
|
// parse the schema driven properties
|
|
LPCSTR pData = (LPCSTR)(LPWSTR)m_raw;
|
|
pData += dw13Xlen;
|
|
dwByteLen -= dw13Xlen;
|
|
|
|
// parse the schema driven fields
|
|
CNexusConfig* cnc = g_config->checkoutNexusConfig();
|
|
if (NULL == cnc)
|
|
{
|
|
m_valid = FALSE;
|
|
return S_FALSE;
|
|
}
|
|
|
|
CTicketSchema* pSchema = cnc->getTicketSchema(NULL);
|
|
|
|
if ( pSchema )
|
|
{
|
|
HRESULT hr = pSchema->parseTicket(pData, dwByteLen, m_PropBag);
|
|
|
|
// passport flags is useful, should treat it special
|
|
TicketProperty prop;
|
|
if (S_OK == m_PropBag.GetProperty(ATTR_PASSPORTFLAGS, prop))
|
|
{
|
|
if (prop.value.vt == VT_I4)
|
|
m_passportFlags = prop.value.lVal;
|
|
}
|
|
|
|
/*
|
|
if (FAILED(hr) )
|
|
event log
|
|
*/
|
|
}
|
|
cnc->Release();
|
|
|
|
}
|
|
|
|
PPTracePrint(PPTRACE_RAW, "ticket propertybag: size=%d, flags=%lx", m_PropBag.Size(), m_passportFlags);
|
|
|
|
PassportLog("CTicket::put_unencryptedTicket Exit:\r\n");
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// get_IsAuthenticated
|
|
//
|
|
STDMETHODIMP CTicket::get_IsAuthenticated(
|
|
ULONG timeWindow,
|
|
VARIANT_BOOL forceLogin,
|
|
VARIANT SecureLevel,
|
|
VARIANT_BOOL* pVal
|
|
)
|
|
{
|
|
int hasSecureLevel = CV_DEFAULT;
|
|
|
|
PassportLog("CTicket::get_IsAuthenticated Enter:\r\n");
|
|
|
|
PPTraceFunc<VARIANT_BOOL> func(PPTRACE_FUNC, *pVal,
|
|
"get_IsAuthenticated", "<<< %lx, %lx, %1x, %p",
|
|
timeWindow, forceLogin, V_I4(&SecureLevel), pVal);
|
|
|
|
if(!pVal)
|
|
return E_INVALIDARG;
|
|
|
|
*pVal = VARIANT_FALSE;
|
|
|
|
if ((timeWindow != 0 && timeWindow < PPM_TIMEWINDOW_MIN) || timeWindow > PPM_TIMEWINDOW_MAX)
|
|
{
|
|
AtlReportError(CLSID_Ticket, (LPCOLESTR) PP_E_INVALID_TIMEWINDOWSTR,
|
|
IID_IPassportTicket, PP_E_INVALID_TIMEWINDOW);
|
|
return PP_E_INVALID_TIMEWINDOW;
|
|
}
|
|
|
|
if (m_valid == FALSE)
|
|
{
|
|
*pVal = VARIANT_FALSE;
|
|
return S_OK;
|
|
}
|
|
|
|
long lSecureLevel = 0;
|
|
time_t now;
|
|
long interval = 0;
|
|
|
|
PassportLog(" TW = %X, LT = %X, TT = %X\r\n", timeWindow, m_lastSignInTime, m_ticketTime);
|
|
|
|
// time window checking
|
|
if (timeWindow != 0) // check time window
|
|
{
|
|
time(&now);
|
|
|
|
interval = forceLogin ? now - m_lastSignInTime :
|
|
now - m_ticketTime;
|
|
|
|
if (interval < 0) interval = 0;
|
|
|
|
PPTracePrint(PPTRACE_RAW, "timwindow:%ld, interval:%ld", timeWindow, interval);
|
|
|
|
if ((unsigned long)(interval) > timeWindow)
|
|
{
|
|
// Make sure we're not in standalone mode
|
|
CRegistryConfig* crc = g_config->checkoutRegistryConfig();
|
|
if ((!crc) || (crc->DisasterModeP() == FALSE))
|
|
{
|
|
if(forceLogin)
|
|
{
|
|
if(g_pPerf)
|
|
{
|
|
g_pPerf->incrementCounter(PM_FORCEDSIGNIN_TOTAL);
|
|
g_pPerf->incrementCounter(PM_FORCEDSIGNIN_SEC);
|
|
}
|
|
else
|
|
{
|
|
_ASSERT(g_pPerf);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
*pVal = VARIANT_TRUE; // we're in disaster mode, any cookie is good.
|
|
if (crc) crc->Release();
|
|
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
// check secureLevel stuff
|
|
hasSecureLevel = GetIntArg(SecureLevel, (int*)&lSecureLevel);
|
|
if(hasSecureLevel == CV_BAD) // try the legacy type VT_BOOL, map VARIANT_TRUE to SecureChannel
|
|
{
|
|
PPTracePrint(PPTRACE_RAW, "SecureLevel Bad Param");
|
|
return E_INVALIDARG;
|
|
}
|
|
else if (hasSecureLevel == CV_DEFAULT)
|
|
{
|
|
// Make sure we're not in standalone mode
|
|
CRegistryConfig* crc = g_config->checkoutRegistryConfig();
|
|
if(crc)
|
|
lSecureLevel = crc->getSecureLevel();
|
|
}
|
|
|
|
PPTracePrint(PPTRACE_RAW, "check secureLevel:%ld", lSecureLevel);
|
|
|
|
if(lSecureLevel != 0)
|
|
{
|
|
VARIANT_BOOL bCheckSecure = ( SECURELEVEL_USE_HTTPS(lSecureLevel) ?
|
|
VARIANT_TRUE : VARIANT_FALSE );
|
|
PPTracePrint(PPTRACE_RAW, "secure checked OK?:%ld", m_bSecureCheckSucceeded);
|
|
|
|
// SSL checking
|
|
if(bCheckSecure && !m_bSecureCheckSucceeded)
|
|
goto Cleanup;
|
|
|
|
// securelevel checking
|
|
{
|
|
TicketProperty prop;
|
|
HRESULT hr = m_PropBag.GetProperty(ATTR_SECURELEVEL, prop);
|
|
|
|
PPTracePrint(PPTRACE_RAW, "secure level in ticket:%ld, %lx", (long) (prop.value), hr);
|
|
|
|
// secure level is not good enough
|
|
if(hr != S_OK || SecureLevelFromSecProp((int) (long) (prop.value)) < lSecureLevel)
|
|
goto Cleanup;
|
|
|
|
// time window checking against pin time -- if Pin signin
|
|
if(SecureLevelFromSecProp((int) (long) (prop.value)) == k_iSeclevelStrongCreds)
|
|
{
|
|
hr = m_PropBag.GetProperty(ATTR_PINTIME, prop);
|
|
|
|
PPTracePrint(PPTRACE_RAW, "pin time:%ld, %lx", (long) (prop.value), hr);
|
|
if (hr != S_OK)
|
|
goto Cleanup;
|
|
|
|
interval = now - (long) (prop.value);
|
|
|
|
if (interval < 0) interval = 0;
|
|
|
|
PPTracePrint(PPTRACE_RAW, "timewindow:%ld, pin-interval:%ld", timeWindow, interval);
|
|
if ((unsigned long)(interval) > timeWindow)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// if code can reach here, is authenticated
|
|
*pVal = VARIANT_TRUE;
|
|
|
|
Cleanup:
|
|
PassportLog("CTicket::get_IsAuthenticated Exit: %X\r\n", *pVal);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// get_TicketAge
|
|
//
|
|
STDMETHODIMP CTicket::get_TicketAge(int *pVal)
|
|
{
|
|
PassportLog("CTicket::get_TicketAge Enter: %X\r\n", m_ticketTime);
|
|
|
|
if (m_valid == FALSE)
|
|
{
|
|
AtlReportError(CLSID_Ticket, (LPCOLESTR) PP_E_INVALID_TICKETSTR,
|
|
IID_IPassportTicket, PP_E_INVALID_TICKET);
|
|
return PP_E_INVALID_TICKET;
|
|
}
|
|
|
|
time_t now;
|
|
time(&now);
|
|
*pVal = now - m_ticketTime;
|
|
|
|
if (*pVal < 0)
|
|
*pVal = 0;
|
|
|
|
PassportLog("CTicket::get_TicketAge Exit: %X\r\n", *pVal);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// get_TimeSinceSignIn
|
|
//
|
|
STDMETHODIMP CTicket::get_TimeSinceSignIn(int *pVal)
|
|
{
|
|
PassportLog("CTicket::get_TimeSinceSignIn Enter: %X\r\n", m_lastSignInTime);
|
|
|
|
if (m_valid == FALSE)
|
|
{
|
|
AtlReportError(CLSID_Ticket, (LPCOLESTR) PP_E_INVALID_TICKETSTR,
|
|
IID_IPassportTicket, PP_E_INVALID_TICKET);
|
|
return PP_E_INVALID_TICKET;
|
|
}
|
|
|
|
time_t now;
|
|
time(&now);
|
|
*pVal = now - m_lastSignInTime;
|
|
|
|
if (*pVal < 0)
|
|
*pVal = 0;
|
|
|
|
PassportLog("CTicket::get_TimeSinceSignIn Exit: %X\r\n", *pVal);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// get_MemberId
|
|
//
|
|
STDMETHODIMP CTicket::get_MemberId(BSTR *pVal)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (m_valid == FALSE)
|
|
{
|
|
AtlReportError(CLSID_Ticket, (LPCOLESTR) PP_E_INVALID_TICKETSTR,
|
|
IID_IPassportTicket, PP_E_INVALID_TICKET);
|
|
hr = PP_E_INVALID_TICKET;
|
|
goto Cleanup;
|
|
}
|
|
|
|
if(pVal == NULL)
|
|
{
|
|
hr = E_POINTER;
|
|
goto Cleanup;
|
|
}
|
|
|
|
*pVal = SysAllocString(m_memberId);
|
|
if(*pVal == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
Cleanup:
|
|
|
|
return hr;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// get_MemberIdLow
|
|
//
|
|
STDMETHODIMP CTicket::get_MemberIdLow(int *pVal)
|
|
{
|
|
if (m_valid == FALSE)
|
|
{
|
|
AtlReportError(CLSID_Ticket, (LPCOLESTR) PP_E_INVALID_TICKETSTR,
|
|
IID_IPassportTicket, PP_E_INVALID_TICKET);
|
|
return PP_E_INVALID_TICKET;
|
|
}
|
|
|
|
PassportLog("CTicket::get_MemberIdLow: %X\r\n", m_mIdLow);
|
|
|
|
*pVal = m_mIdLow;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// get_MemberIdHigh
|
|
//
|
|
STDMETHODIMP CTicket::get_MemberIdHigh(int *pVal)
|
|
{
|
|
if (m_valid == FALSE)
|
|
{
|
|
AtlReportError(CLSID_Ticket, (LPCOLESTR) PP_E_INVALID_TICKETSTR,
|
|
IID_IPassportTicket, PP_E_INVALID_TICKET);
|
|
return PP_E_INVALID_TICKET;
|
|
}
|
|
|
|
PassportLog("CTicket::get_MemberIdHigh: %X\r\n", m_mIdHigh);
|
|
|
|
*pVal = m_mIdHigh;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// get_HasSavedPassword
|
|
//
|
|
STDMETHODIMP CTicket::get_HasSavedPassword(VARIANT_BOOL *pVal)
|
|
{
|
|
if (m_valid == FALSE)
|
|
{
|
|
AtlReportError(CLSID_Ticket, (LPCOLESTR) PP_E_INVALID_TICKETSTR,
|
|
IID_IPassportTicket, PP_E_INVALID_TICKET);
|
|
return PP_E_INVALID_TICKET;
|
|
}
|
|
|
|
PassportLog("CTicket::get_HasSavedPassword: %X\r\n", m_savedPwd);
|
|
|
|
*pVal = m_savedPwd ? VARIANT_TRUE : VARIANT_FALSE;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// get_SignInServer
|
|
//
|
|
STDMETHODIMP CTicket::get_SignInServer(BSTR *pVal)
|
|
{
|
|
if (m_valid == FALSE)
|
|
{
|
|
AtlReportError(CLSID_Ticket, (LPCOLESTR) PP_E_INVALID_TICKETSTR,
|
|
IID_IPassportTicket, PP_E_INVALID_TICKET);
|
|
return PP_E_INVALID_TICKET;
|
|
}
|
|
|
|
// BUGBUG
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// parse
|
|
//
|
|
// parse the 1.3X ticket fields
|
|
void CTicket::parse(
|
|
LPCOLESTR raw,
|
|
DWORD dwByteLen,
|
|
DWORD* pcParsed
|
|
)
|
|
{
|
|
LPSTR lpBase;
|
|
UINT byteLen, spot=0;
|
|
long curTime;
|
|
time_t curTime_t;
|
|
u_long ulTmp;
|
|
|
|
if (!raw)
|
|
{
|
|
m_valid = false;
|
|
goto Cleanup;
|
|
}
|
|
|
|
// format:
|
|
// four bytes network long - low memberId bytes
|
|
// four bytes network long - high memberId bytes
|
|
// four bytes network long - time of last refresh
|
|
// four bytes network long - time of last password entry
|
|
// four bytes network long - time of ticket generation
|
|
// one byte - is this a saved password (Y/N)
|
|
// four bytes network long - flags
|
|
|
|
lpBase = (LPSTR)(LPWSTR) raw;
|
|
byteLen = dwByteLen;
|
|
spot=0;
|
|
|
|
// 1.3x ticket length, excluding HM which is 1 long shorter
|
|
DWORD dw13XLen = sizeof(u_long)*6 + sizeof(char);
|
|
if (byteLen < dw13XLen && byteLen != dw13XLen - sizeof(u_long))
|
|
{
|
|
m_valid = FALSE;
|
|
goto Cleanup;
|
|
}
|
|
|
|
memcpy((PBYTE)&ulTmp, lpBase, sizeof(ulTmp));
|
|
m_mIdLow = ntohl(ulTmp);
|
|
spot += sizeof(u_long);
|
|
|
|
memcpy((PBYTE)&ulTmp, lpBase + spot, sizeof(ulTmp));
|
|
m_mIdHigh = ntohl(ulTmp);
|
|
spot += sizeof(u_long);
|
|
|
|
wsprintfW(m_memberId, L"%08X%08X", m_mIdHigh, m_mIdLow);
|
|
|
|
memcpy((PBYTE)&ulTmp, lpBase + spot, sizeof(ulTmp));
|
|
m_ticketTime = ntohl(ulTmp);
|
|
spot += sizeof(u_long);
|
|
|
|
memcpy((PBYTE)&ulTmp, lpBase + spot, sizeof(ulTmp));
|
|
m_lastSignInTime = ntohl(ulTmp);
|
|
spot += sizeof(u_long);
|
|
|
|
time(&curTime_t);
|
|
|
|
curTime = (ULONG) curTime_t;
|
|
|
|
// If the current time is "too" negative, bail (5 mins)
|
|
memcpy((PBYTE)&ulTmp, lpBase + spot, sizeof(ulTmp));
|
|
if ((unsigned long)(curTime+300) < ntohl(ulTmp))
|
|
{
|
|
if (g_pAlert)
|
|
{
|
|
memcpy((PBYTE)&ulTmp, lpBase + spot, sizeof(ulTmp));
|
|
DWORD dwTimes[2] = { curTime, ntohl(ulTmp) };
|
|
g_pAlert->report(PassportAlertInterface::ERROR_TYPE, PM_TIMESTAMP_BAD,
|
|
0, NULL, sizeof(DWORD) << 1, (LPVOID)dwTimes);
|
|
}
|
|
|
|
m_valid = FALSE;
|
|
goto Cleanup;
|
|
}
|
|
spot += sizeof(u_long);
|
|
|
|
m_savedPwd = (*(char*)(lpBase+spot)) == 'Y' ? TRUE : FALSE;
|
|
spot += sizeof(char);
|
|
|
|
if (dwByteLen == dw13XLen)
|
|
{
|
|
memcpy((PBYTE)&ulTmp, lpBase + spot, sizeof(ulTmp));
|
|
m_flags = ntohl(ulTmp);
|
|
}
|
|
else
|
|
{
|
|
// HM cookie
|
|
m_flags = 0;
|
|
}
|
|
spot += sizeof(u_long);
|
|
|
|
m_valid = TRUE;
|
|
if(pcParsed) *pcParsed = spot;
|
|
|
|
Cleanup:
|
|
if (m_valid == FALSE)
|
|
{
|
|
if(g_pAlert)
|
|
g_pAlert->report(PassportAlertInterface::WARNING_TYPE, PM_INVALID_TICKET);
|
|
if(g_pPerf)
|
|
{
|
|
g_pPerf->incrementCounter(PM_INVALIDREQUESTS_TOTAL);
|
|
g_pPerf->incrementCounter(PM_INVALIDREQUESTS_SEC);
|
|
}
|
|
else
|
|
{
|
|
_ASSERT(g_pPerf);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// get_TicketTime
|
|
//
|
|
STDMETHODIMP CTicket::get_TicketTime(long *pVal)
|
|
{
|
|
PassportLog("CTicket::get_TicketTime: %X\r\n", m_ticketTime);
|
|
*pVal = m_ticketTime;
|
|
return S_OK;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// get_SignInTime
|
|
//
|
|
STDMETHODIMP CTicket::get_SignInTime(long *pVal)
|
|
{
|
|
PassportLog("CTicket::get_SignInTime: %X\r\n", m_lastSignInTime);
|
|
*pVal = m_lastSignInTime;
|
|
return S_OK;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// get_Error
|
|
//
|
|
STDMETHODIMP CTicket::get_Error(long* pVal)
|
|
{
|
|
PassportLog("CTicket::get_Error: %X\r\n", m_flags);
|
|
*pVal = m_flags;
|
|
return S_OK;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// GetPassportFlags
|
|
//
|
|
ULONG CTicket::GetPassportFlags()
|
|
{
|
|
return m_passportFlags;
|
|
}
|
|
|
|
|
|
//===========================================================================
|
|
//
|
|
// IsSecure
|
|
//
|
|
BOOL CTicket::IsSecure()
|
|
{
|
|
return ((m_passportFlags & k_ulFlagsSecuredTransportedTicket) != 0);
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// DoSecureCheckInTicket -- use the information in the ticket to determine if secure signin
|
|
//
|
|
STDMETHODIMP CTicket::DoSecureCheckInTicket(/* [in] */ BOOL fSecureTransported)
|
|
{
|
|
m_bSecureCheckSucceeded =
|
|
(fSecureTransported
|
|
&& (m_passportFlags & k_ulFlagsSecuredTransportedTicket) != 0);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// DoSecureCheck
|
|
//
|
|
STDMETHODIMP CTicket::DoSecureCheck(BSTR bstrSec)
|
|
{
|
|
if(bstrSec == NULL)
|
|
return E_INVALIDARG;
|
|
|
|
// make sure that the member id in the ticket
|
|
// matches the member id in the secure cookie.
|
|
m_bSecureCheckSucceeded = (memcmp(bstrSec, m_raw, sizeof(long) * 3) == 0);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// GetProperty
|
|
//
|
|
STDMETHODIMP CTicket::GetProperty(BSTR propName, VARIANT* pVal)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
TicketProperty prop;
|
|
if (m_valid == FALSE)
|
|
{
|
|
AtlReportError(CLSID_Ticket, (LPCOLESTR) PP_E_INVALID_TICKETSTR,
|
|
IID_IPassportTicket, PP_E_INVALID_TICKET);
|
|
return PP_E_INVALID_TICKET;
|
|
}
|
|
|
|
if (!pVal) return E_POINTER;
|
|
|
|
VariantInit(pVal);
|
|
|
|
hr = m_PropBag.GetProperty(propName, prop);
|
|
|
|
if (FAILED(hr)) goto Cleanup;
|
|
|
|
if (hr == S_FALSE) // no such property back
|
|
{
|
|
AtlReportError(CLSID_Ticket, (LPCOLESTR) PP_E_NO_ATTRIBUTESTR,
|
|
IID_IPassportTicket, PP_E_NO_ATTRIBUTE);
|
|
|
|
hr = PP_E_NO_SUCH_ATTRIBUTE;
|
|
goto Cleanup;
|
|
}
|
|
|
|
if (hr == S_OK)
|
|
{
|
|
// if(prop.flags & TPF_NO_RETRIEVE)
|
|
*pVal = prop.value; // skin level copy
|
|
prop.value.Detach();
|
|
}
|
|
Cleanup:
|
|
|
|
return hr;
|
|
}
|
|
|