Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

721 lines
20 KiB

/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
InetSess.cpp
Abstract:
Implements the Passport Session that uses WinInet as the underlying transport.
Author:
Biao Wang (biaow) 01-Oct-2000
--*/
#include "PPdefs.h"
#include "session.h"
// #include "inetsess.tmh"
SESSION* CreateWinHttpSession(void);
// -----------------------------------------------------------------------------
BOOL SESSION::CreateObject(PCWSTR pwszHttpStack, HINTERNET hSession,
PCWSTR pwszProxyUser,
PCWSTR pwszProxyPass,
SESSION*& pSess)
{
PP_ASSERT(pwszHttpStack != NULL);
pSess = NULL;
if (!::_wcsicmp(pwszHttpStack, L"WinInet.dll") ||
!::_wcsicmp(pwszHttpStack, L"WinInet"))
{
PP_ASSERT(FALSE);
pSess = NULL; // new WININET_SESSION();
}
else
{
pSess = ::CreateWinHttpSession();
}
if (pSess)
{
pSess->SetProxyCreds(pwszProxyUser, pwszProxyPass);
return pSess->Open(pwszHttpStack, hSession);
}
else
{
DoTraceMessage(PP_LOG_ERROR, "CreateObject() failed; not enough memory");
return FALSE;
}
}
// -----------------------------------------------------------------------------
SESSION::SESSION(void)
{
m_hHttpStack = 0;
m_hCredUI = 0;
m_RefCount = 0;
m_pfnReadDomainCred = NULL;
m_pfnCredFree = NULL;
m_hKeyLM = NULL;
m_fLogout = FALSE;
m_wDefaultDAUrl[0] = 0;
m_wCurrentDAUrl[0] = 0;
m_wCurrentDAHost[0] = 0;
m_wDARealm[0] = 0;
m_LastNexusDownloadTime = 0xFFFFFFFF;
m_pwszProxyUser = NULL;
m_pwszProxyPass = NULL;
m_dwVersion = 0;
InitializeListHead(&m_DAMap);
}
// -----------------------------------------------------------------------------
SESSION::~SESSION(void)
{
if (m_pwszProxyUser)
{
SecureZeroMemory((void*)m_pwszProxyUser,sizeof(m_pwszProxyUser[0])*wcslen(m_pwszProxyUser));
delete [] m_pwszProxyUser;
}
if (m_pwszProxyPass)
{
SecureZeroMemory((void*)m_pwszProxyPass,sizeof(m_pwszProxyPass[0])*wcslen(m_pwszProxyPass));
delete [] m_pwszProxyPass;
}
}
BOOL SESSION::GetDAInfoFromPPNexus(
)
{
BOOL fRetVal = FALSE;
HINTERNET hRequest = NULL;
HINTERNET hConnect = NULL;
DWORD dwError;
WCHAR wNexusHost[128] = L"nexus.passport.com";
DWORD dwHostLen = sizeof(wNexusHost); // note: size of the buffer, not # of UNICODE characters
WCHAR wNexusObj[128] = L"rdr/pprdr.asp";
DWORD dwObjLen = sizeof(wNexusObj);
PWSTR pwszPassportUrls = NULL;
DWORD dwUrlsLen = 0;
DWORD dwValueType;
WCHAR Delimiters[] = L",";
PWSTR Token = NULL;
// we allow only one Nexus contact per session to avoid infinite loop due to Nexus misconfiguration
DWORD dwCurrentTime = ::GetTickCount();
if ((dwCurrentTime >= m_LastNexusDownloadTime) &&
(dwCurrentTime - m_LastNexusDownloadTime < 5*60*1000)) // 5 minutes
{
DoTraceMessage(PP_LOG_WARNING, "SESSION::GetDAInfoFromPPNexus() failed: Nexus info already downloaded");
goto exit;
}
if (m_hKeyLM)
{
dwError = ::RegQueryValueExW(m_hKeyLM,
L"NexusHost",
0,
&dwValueType,
reinterpret_cast<LPBYTE>(wNexusHost),
&dwHostLen);
PP_ASSERT(!(dwError == ERROR_MORE_DATA));
dwError = ::RegQueryValueExW(m_hKeyLM,
L"NexusObj",
0,
&dwValueType,
reinterpret_cast<LPBYTE>(wNexusObj),
&dwObjLen);
PP_ASSERT(!(dwError == ERROR_MORE_DATA));
}
hConnect = Connect(wNexusHost,
INTERNET_DEFAULT_HTTPS_PORT
);
if (hConnect == NULL)
{
DWORD dwErrorCode = ::GetLastError();
DoTraceMessage(PP_LOG_ERROR,
"SESSION::GetDAInfoFromPPNexus(): failed to connect to %ws; Error = %d",
wNexusHost, dwErrorCode);
goto exit;
}
hRequest = OpenRequest(hConnect,
NULL,
wNexusObj,
WINHTTP_FLAG_SECURE
);
if (hRequest == NULL)
{
DWORD dwErrorCode = ::GetLastError();
DoTraceMessage(PP_LOG_ERROR, "SESSION::GetDAInfoFromPPNexus() failed; OpenRequest() to %ws failed, Error Code = %d",
wNexusObj, dwErrorCode);
goto exit;
}
if (m_pwszProxyUser && m_pwszProxyPass)
{
SetOption(hRequest, WINHTTP_OPTION_PROXY_USERNAME, (void*)m_pwszProxyUser, wcslen(m_pwszProxyUser) + 1);
SetOption(hRequest, WINHTTP_OPTION_PROXY_PASSWORD, (void*)m_pwszProxyPass, wcslen(m_pwszProxyPass) + 1);
}
if (!SendRequest(hRequest, NULL, 0))
{
DoTraceMessage(PP_LOG_ERROR, "SESSION::GetDAInfoFromPPNexus(): failed");
goto exit;
}
if (ReceiveResponse(hRequest) == FALSE)
{
DWORD dwErrorCode = ::GetLastError();
DoTraceMessage(PP_LOG_ERROR, "SESSION::GetDAInfoFromPPNexus() failed; ReceiveResponse() failed, Error Code = %d",
dwErrorCode);
goto exit;
}
if (QueryHeaders(hRequest,
WINHTTP_QUERY_PASSPORT_URLS,
0,
&dwUrlsLen) == FALSE)
{
if ((::GetLastError() != ERROR_INSUFFICIENT_BUFFER) || (dwUrlsLen == 0))
{
DoTraceMessage(PP_LOG_ERROR, "SESSION::GetDAInfoFromPPNexus() failed; PassportUrls header not found");
goto exit;
}
}
else
{
PP_ASSERT(FALSE); // should not reach here
}
pwszPassportUrls = new WCHAR[dwUrlsLen];
if (pwszPassportUrls == NULL)
{
DoTraceMessage(PP_LOG_ERROR, "SESSION::GetDAInfoFromPPNexus() failed; insufficient memory");
goto exit;
}
if (QueryHeaders(hRequest,
WINHTTP_QUERY_PASSPORT_URLS,
pwszPassportUrls,
&dwUrlsLen) == FALSE)
{
DoTraceMessage(PP_LOG_ERROR, "SESSION::GetDAInfoFromPPNexus() failed; PassportUrls header not found");
goto exit;
}
Token = ::wcstok(pwszPassportUrls, Delimiters);
while (Token != NULL)
{
// skip leading white spaces
while (*Token == (L" ")[0]) { ++Token; }
if (*Token == L'\0')
{
DoTraceMessage(PP_LOG_WARNING, "SESSION::GetDAInfoFromPPNexus() : no text in between commas");
goto next_token;
}
// find DALocation
if (!::_wcsnicmp(Token, L"DALogin", ::wcslen(L"DALogin")))
{
PWSTR pwszDAUrl = ::wcsstr(Token, L"=");
if (pwszDAUrl == NULL)
{
DoTraceMessage(PP_LOG_WARNING, "SESSION::GetDAInfoFromPPNexus() : no = after DALocation");
goto exit;
}
pwszDAUrl++; // skip "="
while (*pwszDAUrl == (L" ")[0]) { ++pwszDAUrl; } // skip leading white spaces
if (*pwszDAUrl == L'\0')
{
goto exit;
}
::wcscpy(m_wDefaultDAUrl, L"https://");
::wcsncat(m_wDefaultDAUrl, pwszDAUrl, MAX_PASSPORT_URL_LENGTH - 8);
m_LastNexusDownloadTime = ::GetTickCount();
fRetVal = TRUE;
DoTraceMessage(PP_LOG_INFO, "DALocation URL %ws found", m_wDefaultDAUrl);
}
else if (!::_wcsnicmp(Token, L"DARealm", ::wcslen(L"DARealm")))
{
PWSTR pwszDARealm = ::wcsstr(Token, L"=");
if (pwszDARealm == NULL)
{
DoTraceMessage(PP_LOG_WARNING, "SESSION::GetDAInfoFromPPNexus() : no = after DARealm");
goto exit;
}
pwszDARealm++; // skip "="
while (*pwszDARealm == (L" ")[0]) { ++pwszDARealm; } // skip leading white spaces
if (*pwszDARealm == L'\0')
{
goto exit;
}
::wcsncpy(m_wDARealm, pwszDARealm, MAX_PASSPORT_REALM_LENGTH);
m_wDARealm[MAX_PASSPORT_REALM_LENGTH] = 0;
DoTraceMessage(PP_LOG_INFO, "DARealm URL %ws found", m_wDefaultDAUrl);
}
else if (!::_wcsnicmp(Token, L"ConfigVersion", ::wcslen(L"ConfigVersion")))
{
PWSTR pwszConfigVersion = ::wcsstr(Token, L"=");
if (pwszConfigVersion == NULL)
{
DoTraceMessage(PP_LOG_WARNING, "SESSION::GetDAInfoFromPPNexus() : no = after ConfigVersion");
goto exit;
}
pwszConfigVersion++; // skip "="
while (*pwszConfigVersion == (L" ")[0]) { ++pwszConfigVersion; } // skip leading white spaces
if (*pwszConfigVersion == L'\0')
{
goto exit;
}
m_dwVersion = _wtoi(pwszConfigVersion);
DoTraceMessage(PP_LOG_INFO, "ConfigVersion URL %ws found", m_wDefaultDAUrl);
}
next_token:
Token = ::wcstok(NULL, Delimiters);
}
exit:
if (pwszPassportUrls)
{
delete [] pwszPassportUrls;
}
if (hRequest)
{
CloseHandle(hRequest);
}
if (hConnect)
{
CloseHandle(hConnect);
}
return fRetVal;
}
BOOL SESSION::GetRealm(
PWSTR pwszRealm, // user supplied buffer ...
PDWORD pdwRealmLen // ... and length (will be updated to actual length
// on successful return)
) const
{
DWORD RealmLen = sizeof(m_wDARealm);
DWORD dwValueType;
PWSTR pwszDARealm = const_cast<PWSTR>(&m_wDARealm[0]);
if (m_hKeyLM && ::RegQueryValueExW(m_hKeyLM,
L"LoginServerRealm",
0,
&dwValueType,
reinterpret_cast<LPBYTE>(pwszDARealm),
&RealmLen) == ERROR_SUCCESS)
{
;
}
if (!m_wDARealm[0])
{
*pdwRealmLen = 0;
return FALSE;
}
if (!pwszRealm)
{
*pdwRealmLen = ::wcslen(m_wDARealm) + 1;
return FALSE;
}
if (*pdwRealmLen < (DWORD)::wcslen(m_wDARealm) + 1)
{
*pdwRealmLen = ::wcslen(m_wDARealm) + 1;
return FALSE;
}
::wcscpy(pwszRealm, m_wDARealm);
*pdwRealmLen = ::wcslen(m_wDARealm) + 1;
return TRUE;
}
DWORD SESSION::GetNexusVersion(void)
{
DWORD dwValueType;
DWORD dwVerLen = sizeof(m_dwVersion);
if (m_hKeyLM && ::RegQueryValueExW(m_hKeyLM,
L"ConfigVersion",
0,
&dwValueType,
reinterpret_cast<LPBYTE>(&m_dwVersion),
&dwVerLen) == ERROR_SUCCESS)
{
;
}
return m_dwVersion;
}
BOOL SESSION::UpdateDAInfo(
PCWSTR pwszSignIn,
PCWSTR pwszDAUrl
)
{
BOOL fRet = FALSE;
if (pwszSignIn)
{
LPCWSTR pwszDomain = ::wcsstr(pwszSignIn, L"@");
if (pwszDomain)
{
BOOL fFound = FALSE;
for (PLIST_ENTRY entry = (&m_DAMap)->Flink;
entry != (PLIST_ENTRY)&((&m_DAMap)->Flink);
entry = entry->Flink)
{
P_DA_ENTRY pDAEntry = (P_DA_ENTRY)entry;
if (!::_wcsicmp(pDAEntry->wDomain, pwszDomain))
{
fFound = TRUE;
::wcsncpy(pDAEntry->wDA, pwszDAUrl, MAX_PASSPORT_URL_LENGTH);
pDAEntry->wDA[MAX_PASSPORT_URL_LENGTH] = 0;
fRet = TRUE;
break;
}
}
if (!fFound)
{
P_DA_ENTRY pDAEntry = new DA_ENTRY;
if (pDAEntry)
{
::wcsncpy(pDAEntry->wDomain, pwszDomain, MAX_PASSPORT_DOMAIN_LENGTH);
pDAEntry->wDomain[MAX_PASSPORT_DOMAIN_LENGTH] = 0;
::wcsncpy(pDAEntry->wDA, pwszDAUrl, MAX_PASSPORT_URL_LENGTH);
pDAEntry->wDA[MAX_PASSPORT_URL_LENGTH] = 0;
InsertHeadList(&m_DAMap, (PLIST_ENTRY)pDAEntry);
fRet = TRUE;
}
}
}
}
return fRet;
}
BOOL SESSION::PurgeDAInfo(PCWSTR pwszSignIn)
{
if (pwszSignIn == NULL)
{
return TRUE;
}
LPCWSTR pwszDomain = ::wcsstr(pwszSignIn, L"@");
if (pwszDomain)
{
for (PLIST_ENTRY entry = (&m_DAMap)->Flink;
entry != (PLIST_ENTRY)&((&m_DAMap)->Flink);
entry = entry->Flink)
{
P_DA_ENTRY pDAEntry = (P_DA_ENTRY)entry;
if (!::_wcsicmp(pDAEntry->wDomain, pwszDomain))
{
RemoveEntryList(entry);
delete pDAEntry;
break;
}
}
}
return TRUE;
}
BOOL SESSION::GetDAInfo(PCWSTR pwszSignIn,
LPWSTR pwszDAHostName,
DWORD HostNameLen,
LPWSTR pwszDAHostObj,
DWORD HostObjLen)
{
LPCWSTR pwszDAUrl = m_wDefaultDAUrl;
if (pwszSignIn)
{
LPCWSTR pwszDomain = ::wcsstr(pwszSignIn, L"@");
if (pwszDomain)
{
for (PLIST_ENTRY entry = (&m_DAMap)->Flink;
entry != (PLIST_ENTRY)&((&m_DAMap)->Flink);
entry = entry->Flink)
{
P_DA_ENTRY pDAEntry = (P_DA_ENTRY)entry;
if (!::_wcsicmp(pDAEntry->wDomain, pwszDomain))
{
pwszDAUrl = pDAEntry->wDA;
break;
}
}
}
}
::wcsncpy(m_wCurrentDAUrl, pwszDAUrl, MAX_PASSPORT_URL_LENGTH);
m_wCurrentDAUrl[MAX_PASSPORT_URL_LENGTH] = 0;
URL_COMPONENTSW UrlComps;
::memset(&UrlComps, 0, sizeof(UrlComps));
UrlComps.dwStructSize = sizeof(UrlComps);
UrlComps.lpszHostName = pwszDAHostName;
UrlComps.dwHostNameLength = HostNameLen;
UrlComps.lpszUrlPath = pwszDAHostObj;
UrlComps.dwUrlPathLength = HostObjLen;
if (CrackUrl(pwszDAUrl,
0,
0,
&UrlComps) == FALSE)
{
DoTraceMessage(PP_LOG_ERROR,
"WININET_SESSION::GetDAInfo() failed; can not crack the URL %ws",
pwszDAUrl);
return FALSE;
}
::wcsncpy(m_wCurrentDAHost, UrlComps.lpszHostName, MAX_PASSPORT_HOST_LENGTH);
m_wCurrentDAHost[MAX_PASSPORT_HOST_LENGTH] = 0;
return TRUE;
}
BOOL SESSION::GetCachedCreds(
PCWSTR pwszRealm,
PCWSTR pwszTarget,
PCREDENTIALW** pppCreds,
DWORD* pdwCreds
)
{
*pppCreds = NULL;
*pdwCreds = 0;
if (m_pfnReadDomainCred == NULL)
{
return FALSE;
}
ULONG CredTypes = CRED_TYPE_DOMAIN_VISIBLE_PASSWORD;
DWORD dwFlags = CRED_CACHE_TARGET_INFORMATION;
CREDENTIAL_TARGET_INFORMATIONW TargetInfo;
memset ( (void*)&TargetInfo, 0, sizeof(CREDENTIAL_TARGET_INFORMATIONW));
TargetInfo.TargetName = const_cast<PWSTR>(pwszTarget);
TargetInfo.DnsDomainName = const_cast<PWSTR>(pwszRealm);
TargetInfo.PackageName = L"Passport1.4";
TargetInfo.Flags = 0;
TargetInfo.CredTypeCount = 1;
TargetInfo.CredTypes = &CredTypes;
if ((*m_pfnReadDomainCred)(&TargetInfo,
dwFlags,
pdwCreds,
pppCreds ) != TRUE)
{
*pppCreds = NULL;
*pdwCreds = 0;
}
else
{
if (IsLoggedOut())
{
FILETIME LogoutTimestamp;
::SystemTimeToFileTime(GetLogoutTimeStamp(), &LogoutTimestamp);
if (::CompareFileTime(&((**pppCreds)->LastWritten), &LogoutTimestamp) == -1)
{
// the cred is entered/created earlier (less) than the Logout request. It is no good.
m_pfnCredFree(*pppCreds);
*pppCreds = NULL;
*pdwCreds = 0;
}
else
{
ResetLogoutFlag();
}
}
}
return (*pppCreds != NULL );
}
BOOL SESSION::Open(PCWSTR /*pwszHttpStack*/, HINTERNET)
{
BOOL fRetVal = FALSE;
DWORD dwValueType;
DWORD dwUrlLen = sizeof(m_wDefaultDAUrl); // note: size of the buffer, not # of UNICODE characters
BOOL fDAInfoCached = FALSE; // assume NO DA info's cached locally
::RegCreateKeyExW(HKEY_LOCAL_MACHINE,
L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\WinHttp\\Passport Test",
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_READ,
NULL,
&m_hKeyLM,
NULL);
if (m_hKeyLM && ::RegQueryValueExW(m_hKeyLM,
L"LoginServerUrl",
0,
&dwValueType,
reinterpret_cast<LPBYTE>(m_wDefaultDAUrl),
&dwUrlLen) == ERROR_SUCCESS)
{
fDAInfoCached = TRUE;
}
if (!fDAInfoCached || (::wcslen(m_wDefaultDAUrl) == ::wcslen(L"")))
{
if (GetDAInfoFromPPNexus() == FALSE)
{
goto exit;
}
}
m_hCredUI = ::LoadLibraryW(L"advapi32.dll");
if (m_hCredUI)
{
m_pfnReadDomainCred =
reinterpret_cast<PFN_READ_DOMAIN_CRED_W>(::GetProcAddress(m_hCredUI, "CredReadDomainCredentialsW"));
if (m_pfnReadDomainCred == NULL)
{
DoTraceMessage(PP_LOG_WARNING, "failed to bind to CredReadDomainCredentialsW()");
}
m_pfnCredFree =
reinterpret_cast<PFN_CRED_FREE>(::GetProcAddress(m_hCredUI, "CredFree"));
if (m_pfnCredFree == NULL)
{
DoTraceMessage(PP_LOG_WARNING, "failed to bind to CredFree()");
}
}
fRetVal = TRUE;
exit:
return fRetVal;
}
void SESSION::Logout(void)
{
if (!m_fLogout)
{
m_fLogout = TRUE;
::GetSystemTime(&m_LogoutTimeStamp);
SetOption(m_hInternet,
WINHTTP_OPTION_PASSPORT_SIGN_OUT,
m_wCurrentDAUrl,
::wcslen(m_wCurrentDAUrl) + 1);
}
}
BOOL SESSION::IsLoggedOut(void) const
{
return m_fLogout;
}
void SESSION::ResetLogoutFlag(void)
{
m_fLogout = FALSE;
}
const SYSTEMTIME* SESSION::GetLogoutTimeStamp(void) const
{
return &m_LogoutTimeStamp;
}
void SESSION::Close(void)
{
if (m_hCredUI)
{
::FreeLibrary(m_hCredUI);
m_hCredUI = NULL;
}
if (m_hKeyLM)
{
::RegCloseKey(m_hKeyLM);
}
PurgeAllDAInfo();
}
BOOL SESSION::PurgeAllDAInfo(void)
{
while (!IsListEmpty(&m_DAMap))
{
PLIST_ENTRY pEntry = RemoveHeadList(&m_DAMap);
P_DA_ENTRY pDAEntry = (P_DA_ENTRY)pEntry;
delete pDAEntry;
}
return TRUE;
}