#include "pch.h"
#include <comdef.h>
#include "zauth.h"
const int cTokensMax = 500;
class CZoneAuthServer : public IZoneAuthServer
{
public:
CZoneAuthServer() :
m_pzt(NULL),
m_fInit(false)
{
}
HRESULT Init()
{
assert(!m_fInit);
HRESULT hr = CoCreateInstance( CLSID_ZoneAuthDecrypt, NULL, CLSCTX_INPROC_SERVER,
IID_IZoneAuthDecrypt, (LPVOID*)&m_pzad);
if (SUCCEEDED(hr))
hr = CoCreateInstance(CLSID_ZoneAuth, NULL, CLSCTX_INPROC_SERVER, IID_IZoneAuth, (LPVOID*)&m_pZoneAuth);
ZSucceeded(hr);
m_ztkey.cbSize = sizeof(m_ztkey);
m_ztkey.nVersion = ZONETICKET_CURRENT_VERSION;
if (SUCCEEDED(hr))
hr = m_pzad->GenerateKey(OBLIVION_ZONE_KEY, &m_ztkey);
ZSucceeded(hr);
m_fInit = SUCCEEDED(hr);
return hr;
}
HRESULT DecryptTicket(LPBYTE pbTicket, DWORD cbTicket)
{
assert(m_fInit);
DWORD cbZT = sizeof(m_rgchZT);
m_pzt = (ZONETICKET *) m_rgchZT;
HRESULT hr = m_pzad->DecryptTicket(&m_ztkey, pbTicket, cbTicket, m_pzt, &cbZT);
assert(IMPLIES(FAILED(hr), ZT_E_AUTH_INVALID_TICKET)); if (SUCCEEDED(hr))
{
assert (ZONETICKET_CURRENT_VERSION == m_pzt->nVersion);
assert(sizeof(*m_pzt) <= m_pzt->cbSize);
}
return hr;
}
bool HasToken(LPSTR szToken, bool * pfValidNow)
{
assert(m_fInit);
assert(szToken);
if (pfValidNow)
*pfValidNow = false;
if (!m_pzt)
return false;
if (!*szToken) {
*pfValidNow = true;
return true;
}
for(DWORD i = 0; i < m_pzt->nTokens; i++)
if (!lstrcmpi(szToken, m_pzt->token_list[i].szToken))
{
time_t timeNow;
time(&timeNow);
double dSec = difftime(timeNow, m_pzt->tTicketIssued);
*pfValidNow = dSec < m_pzt->token_list[i].secTokenEnd;
return true;
}
return false;
}
LPCSTR GetName()
{
assert(m_fInit);
return m_pzt ? m_pzt->szUserName : NULL;
}
LPCSTR GetAuthServer()
{
assert(m_fInit);
return m_pzt ? m_pzt->szZoneServer : NULL;
}
unsigned long GetAccountID()
{
assert(m_fInit);
return m_pzt ? m_pzt->nAccountID : NULL;
}
private:
TRef<IZoneAuthDecrypt> m_pzad;
ZONETICKET_KEY m_ztkey;
TRef<IZoneAuth> m_pZoneAuth;
BYTE m_rgchZT[sizeof(ZONETICKET) + cTokensMax * sizeof(ZONETICKET_TOKEN)];
ZONETICKET * m_pzt;
bool m_fInit;
};
class CZoneAuthClient : public IZoneAuthClient
{
public:
CZoneAuthClient() :
m_strAuthServer("auth.zone.com"),
m_fInit(false)
{
}
HRESULT Init()
{
assert(!m_fInit);
HRESULT hr = CoInitialize(NULL); if (SUCCEEDED(hr))
hr = CoCreateInstance( CLSID_ZoneAuth, NULL, CLSCTX_INPROC_SERVER, IID_IZoneAuth, (LPVOID*)&m_pZoneAuth);
ZSucceeded(hr);
m_fInit = SUCCEEDED(hr);
return hr;
}
HRESULT IsAuthenticated(DWORD msTimeout)
{
assert(m_fInit);
if (!m_pZoneAuth)
{
return E_FAIL;
}
HANDLE hFinished = CreateEvent(NULL, FALSE, FALSE, NULL);
HRESULT hr = m_pZoneAuth->ReAuthenticate(m_strAuthServer, OBLIVION_TOKEN_GROUP, FEDSRV_GUID, (ULONG *) hFinished, &m_pzas);
if (SUCCEEDED(hr))
{
DWORD dwObj = WaitForSingleObject(hFinished, INFINITE); if (WAIT_OBJECT_0 == dwObj)
{
STATUS status;
m_pzas->GetStatus(&status);
if (STATUS_COMPLETED != status)
hr = m_pzas->GetError();
}
else
{
m_pzas->Cancel();
hr = ZT_E_AUTH_TIMEOUT; }
}
else
m_pzas = NULL;
CloseHandle(hFinished);
if (ZT_NO_ERROR == hr) hr = S_OK;
return hr;
}
HRESULT Authenticate(LPSTR szName, LPSTR szPW, bool fPWChanged, BOOL fRememberPW, DWORD msTimeout)
{
assert(m_fInit);
assert (m_pZoneAuth);
HANDLE hFinished = CreateEvent(NULL, FALSE, FALSE, NULL);
HRESULT hr;
try {
hr = m_pZoneAuth->Authenticate(m_strAuthServer, OBLIVION_TOKEN_GROUP,
FEDSRV_GUID, szName, szPW, fPWChanged, fRememberPW, (ULONG *)hFinished, &m_pzas);
} catch (_com_error &c) {
hr = c.Error();
};
if (SUCCEEDED(hr))
{
DWORD dwObj = WaitForSingleObject(hFinished, INFINITE); if (WAIT_OBJECT_0 == dwObj)
{
STATUS status;
hr = m_pzas->GetStatus(&status);
if (STATUS_COMPLETED != status)
hr = m_pzas->GetError();
}
else
{
m_pzas->Cancel();
DWORD dwObj = WaitForSingleObject(hFinished, INFINITE);
hr = ZT_E_AUTH_TIMEOUT; }
}
else
m_pzas = NULL;
CloseHandle(hFinished);
return hr;
}
void GetDefaultLogonInfo(OUT char * szName, OUT char * szPW, OUT BOOL * pfRememberPW)
{
assert(m_fInit);
ZeroMemory(szName, c_cbName);
ZeroMemory(szPW, c_cbName);
HRESULT hr = m_pZoneAuth->GetLoginInfo(szName, c_cbName, szPW, c_cbName, pfRememberPW);
if (ZT_E_AUTH_NO_LOGIN_INFO == hr)
{
*szName = 0;
*szPW = 0;
*pfRememberPW = false;
}
else
ZSucceeded(hr);
}
HRESULT GetTicket(OUT LPBYTE * ppBuffer, OUT DWORD * pcbBuffer, OUT LPSTR szLogin, IN OUT DWORD * pcbLogin)
{
assert(m_fInit);
assert(m_pzas);
assert(pcbBuffer);
char chStupid; *pcbBuffer = sizeof(chStupid);
HRESULT hr = m_pzas->GetTicket((BYTE*)&chStupid, pcbBuffer, NULL, NULL, NULL, NULL);
if (FAILED(hr) && ZT_E_BUFFER_TOO_SMALL != hr)
return hr;
*ppBuffer = static_cast<LPBYTE>(HeapAlloc(GetProcessHeap(), 0, *pcbBuffer));
assert (*ppBuffer);
ZSucceeded(m_pzas->GetTicket(*ppBuffer, pcbBuffer, szLogin, pcbLogin, NULL, NULL));
return ZT_NO_ERROR;
}
ZString & GetAuthServer()
{
assert(m_fInit);
return m_strAuthServer;
}
void SetAuthServer(ZString strAuthServer)
{
assert(m_fInit);
m_strAuthServer = strAuthServer;
}
bool HasInterface(REFIID iid)
{
assert(m_pZoneAuth);
TRef<IUnknown> punk = NULL;
HRESULT hr = m_pZoneAuth->QueryInterface(iid, (void**) &punk);
return SUCCEEDED(hr);
}
private:
~CZoneAuthClient()
{
if (m_pzas)
m_pzas->Cancel();
}
TRef<IZoneAuth> m_pZoneAuth;
TRef<IZoneAuthSession> m_pzas;
ZString m_strAuthServer;
bool m_fInit;
};
TRef<IZoneAuthClient> CreateZoneAuthClient()
{
TRef<CZoneAuthClient> pzac = new CZoneAuthClient();
assert(pzac);
if (pzac && FAILED(pzac->Init()))
pzac = NULL;
return pzac;
}
TRef<IZoneAuthServer> CreateZoneAuthServer()
{
TRef<CZoneAuthServer> pzas = new CZoneAuthServer();
assert(pzas);
if (pzas && FAILED(pzas->Init()))
pzas = NULL;
return pzas;
}
#include <FreeZoneAuth_i.c>