zauth.cpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. /*-------------------------------------------------------------------------
  2. zauth.cpp
  3. implementation of IZoneAuthClient and IZoneAuthServer
  4. Owner:
  5. Copyright 1986-2000 Microsoft Corporation, All Rights Reserved
  6. *-----------------------------------------------------------------------*/
  7. #include "pch.h"
  8. #include "zauth.h"
  9. const int cTokensMax = 500;
  10. class CZoneAuthServer : public IZoneAuthServer
  11. {
  12. public:
  13. CZoneAuthServer() :
  14. m_pzt(NULL),
  15. m_fInit(false)
  16. {
  17. }
  18. HRESULT Init()
  19. {
  20. assert(!m_fInit);
  21. HRESULT hr = CoCreateInstance( CLSID_ZoneAuthDecrypt, NULL, CLSCTX_INPROC_SERVER,
  22. IID_IZoneAuthDecrypt, (LPVOID*)&m_pzad);
  23. if (SUCCEEDED(hr))
  24. hr = CoCreateInstance(CLSID_ZoneAuth, NULL, CLSCTX_INPROC_SERVER, IID_IZoneAuth, (LPVOID*)&m_pZoneAuth);
  25. ZSucceeded(hr);
  26. m_ztkey.cbSize = sizeof(m_ztkey);
  27. m_ztkey.nVersion = ZONETICKET_CURRENT_VERSION;
  28. if (SUCCEEDED(hr))
  29. hr = m_pzad->GenerateKey(OBLIVION_ZONE_KEY, &m_ztkey);
  30. ZSucceeded(hr);
  31. m_fInit = SUCCEEDED(hr);
  32. return hr;
  33. }
  34. /*-------------------------------------------------------------------------
  35. * CZoneAuthServer.DecryptTicket
  36. *-------------------------------------------------------------------------
  37. Purpose:
  38. Crack the ticket the client passes in
  39. */
  40. HRESULT DecryptTicket(LPBYTE pbTicket, DWORD cbTicket)
  41. {
  42. assert(m_fInit);
  43. DWORD cbZT = sizeof(m_rgchZT);
  44. m_pzt = (ZONETICKET *) m_rgchZT;
  45. HRESULT hr = m_pzad->DecryptTicket(&m_ztkey, pbTicket, cbTicket, m_pzt, &cbZT);
  46. assert(IMPLIES(FAILED(hr), ZT_E_AUTH_INVALID_TICKET)); // this is the only failure we should be getting
  47. if (SUCCEEDED(hr))
  48. {
  49. assert (ZONETICKET_CURRENT_VERSION == m_pzt->nVersion);
  50. assert(sizeof(*m_pzt) <= m_pzt->cbSize);
  51. }
  52. return hr;
  53. }
  54. /*-------------------------------------------------------------------------
  55. * HasToken
  56. *-------------------------------------------------------------------------
  57. Purpose:
  58. Find out whether a certain token set has a desired token,
  59. AND whether it's valid now
  60. Returns just whether the token EXISTS. You should not consider the account active
  61. unless they have the token AND it's valid now. Use the combination in order
  62. to give a useful message
  63. */
  64. bool HasToken(LPSTR szToken, bool * pfValidNow)
  65. {
  66. assert(m_fInit);
  67. assert(szToken);
  68. if (pfValidNow)
  69. *pfValidNow = false;
  70. if (!m_pzt)
  71. return false;
  72. if (!*szToken) // If they just want a blank token, then everyone has that.
  73. {
  74. *pfValidNow = true;
  75. return true;
  76. }
  77. for(DWORD i = 0; i < m_pzt->nTokens; i++)
  78. if (!lstrcmpi(szToken, m_pzt->token_list[i].szToken))
  79. {
  80. time_t timeNow;
  81. time(&timeNow);
  82. double dSec = difftime(timeNow, m_pzt->tTicketIssued);
  83. *pfValidNow = // do I need this??? dSec > m_pzt->token_list[i].secTokenStart &&
  84. dSec < m_pzt->token_list[i].secTokenEnd;
  85. return true;
  86. }
  87. return false;
  88. }
  89. LPCSTR GetName()
  90. {
  91. assert(m_fInit);
  92. return m_pzt ? m_pzt->szUserName : NULL;
  93. }
  94. LPCSTR GetAuthServer()
  95. {
  96. assert(m_fInit);
  97. return m_pzt ? m_pzt->szZoneServer : NULL;
  98. }
  99. unsigned long GetAccountID()
  100. {
  101. assert(m_fInit);
  102. return m_pzt ? m_pzt->nAccountID : NULL;
  103. }
  104. private:
  105. TRef<IZoneAuthDecrypt> m_pzad;
  106. ZONETICKET_KEY m_ztkey;
  107. TRef<IZoneAuth> m_pZoneAuth;
  108. BYTE m_rgchZT[sizeof(ZONETICKET) + cTokensMax * sizeof(ZONETICKET_TOKEN)];
  109. ZONETICKET * m_pzt;
  110. bool m_fInit;
  111. };
  112. class CZoneAuthClient : public IZoneAuthClient
  113. {
  114. public:
  115. CZoneAuthClient() :
  116. m_strAuthServer("auth.zone.com"),
  117. m_fInit(false)
  118. {
  119. }
  120. HRESULT Init()
  121. {
  122. assert(!m_fInit);
  123. HRESULT hr = CoInitialize(NULL); // we ALREADY DID THIS, but on RBonny's machine, something has uninitialized us, so try again
  124. if (SUCCEEDED(hr))
  125. hr = CoCreateInstance( CLSID_ZoneAuth, NULL, CLSCTX_INPROC_SERVER, IID_IZoneAuth, (LPVOID*)&m_pZoneAuth);
  126. ZSucceeded(hr);
  127. m_fInit = SUCCEEDED(hr);
  128. return hr;
  129. }
  130. HRESULT IsAuthenticated(DWORD msTimeout)
  131. {
  132. assert(m_fInit);
  133. if (!m_pZoneAuth)
  134. {
  135. return E_FAIL;
  136. }
  137. // TODO: Get the server name from somewhere
  138. HANDLE hFinished = CreateEvent(NULL, FALSE, FALSE, NULL);
  139. HRESULT hr = m_pZoneAuth->ReAuthenticate(m_strAuthServer, OBLIVION_TOKEN_GROUP, //$ CRASHGUARD
  140. FEDSRV_GUID, hFinished, &m_pzas);
  141. if (SUCCEEDED(hr))
  142. {
  143. DWORD dwObj = WaitForSingleObject(hFinished, INFINITE); // msTimeout);
  144. if (WAIT_OBJECT_0 == dwObj)
  145. {
  146. IZoneAuthSession::STATUS status;
  147. m_pzas->GetStatus(&status);
  148. if (IZoneAuthSession::STATUS_COMPLETED != status)
  149. hr = m_pzas->GetError();
  150. }
  151. else
  152. {
  153. m_pzas->Cancel();
  154. hr = ZT_E_AUTH_TIMEOUT; // it's not that the zone timed out, it's that we timed out wrt the specified timeout
  155. }
  156. }
  157. else
  158. m_pzas = NULL;
  159. CloseHandle(hFinished);
  160. if (ZT_NO_ERROR == hr) // hopefully the compiler will optimize this out as long as ZT_NO_ERROR == S_OK
  161. hr = S_OK;
  162. return hr;
  163. }
  164. HRESULT Authenticate(LPSTR szName, LPSTR szPW, bool fPWChanged, BOOL fRememberPW, DWORD msTimeout)
  165. {
  166. assert(m_fInit);
  167. assert (m_pZoneAuth);
  168. // TODO: Get the server name from somewhere
  169. HANDLE hFinished = CreateEvent(NULL, FALSE, FALSE, NULL);
  170. HRESULT hr = m_pZoneAuth->Authenticate(m_strAuthServer, OBLIVION_TOKEN_GROUP,
  171. FEDSRV_GUID, szName, szPW, fPWChanged, fRememberPW, hFinished, &m_pzas);
  172. if (SUCCEEDED(hr))
  173. {
  174. // The cancel thing doesn't work without having to wait again, so that's pointless. Just wait now.
  175. DWORD dwObj = WaitForSingleObject(hFinished, INFINITE); //msTimeout);
  176. if (WAIT_OBJECT_0 == dwObj)
  177. {
  178. IZoneAuthSession::STATUS status;
  179. hr = m_pzas->GetStatus(&status);
  180. if (IZoneAuthSession::STATUS_COMPLETED != status)
  181. hr = m_pzas->GetError();
  182. }
  183. else
  184. {
  185. m_pzas->Cancel();
  186. DWORD dwObj = WaitForSingleObject(hFinished, INFINITE);
  187. hr = ZT_E_AUTH_TIMEOUT; // it's not that the zone timed out, it's that we timed out wrt the specified timeout
  188. }
  189. }
  190. else
  191. m_pzas = NULL;
  192. CloseHandle(hFinished);
  193. return hr;
  194. }
  195. void GetDefaultLogonInfo(OUT char * szName, OUT char * szPW, OUT BOOL * pfRememberPW)
  196. {
  197. assert(m_fInit);
  198. ZeroMemory(szName, c_cbName);
  199. ZeroMemory(szPW, c_cbName);
  200. HRESULT hr = m_pZoneAuth->GetLoginInfo(szName, c_cbName, szPW, c_cbName, pfRememberPW);
  201. if (ZT_E_AUTH_NO_LOGIN_INFO == hr)
  202. {
  203. *szName = 0;
  204. *szPW = 0;
  205. *pfRememberPW = false;
  206. }
  207. else
  208. ZSucceeded(hr);
  209. }
  210. HRESULT GetTicket(OUT LPBYTE * ppBuffer, OUT DWORD * pcbBuffer, OUT LPSTR szLogin, IN OUT DWORD * pcbLogin)
  211. {
  212. assert(m_fInit);
  213. assert(m_pzas);
  214. assert(pcbBuffer);
  215. // Call GetTicket first just to get the buffer sizes
  216. char chStupid; // I have to pass a valid buffer just to find out that
  217. // it's too small and find out the real size it needs to be. I reported this as a bug,
  218. // x fixed it, then somebody else unfixed it.
  219. *pcbBuffer = sizeof(chStupid);
  220. HRESULT hr = m_pzas->GetTicket((BYTE*)&chStupid, pcbBuffer, NULL, NULL, NULL, NULL); //$ CRASHGUARD -- just find out the size
  221. if (FAILED(hr) && ZT_E_BUFFER_TOO_SMALL != hr)
  222. return hr;
  223. *ppBuffer = static_cast<LPBYTE>(HeapAlloc(GetProcessHeap(), 0, *pcbBuffer));
  224. assert (*ppBuffer);
  225. ZSucceeded(m_pzas->GetTicket(*ppBuffer, pcbBuffer, szLogin, pcbLogin, NULL, NULL));
  226. return ZT_NO_ERROR;
  227. }
  228. ZString & GetAuthServer()
  229. {
  230. assert(m_fInit);
  231. return m_strAuthServer;
  232. }
  233. void SetAuthServer(ZString strAuthServer)
  234. {
  235. assert(m_fInit);
  236. m_strAuthServer = strAuthServer;
  237. }
  238. bool HasInterface(REFIID iid)
  239. {
  240. assert(m_pZoneAuth);
  241. TRef<IUnknown> punk = NULL;
  242. HRESULT hr = m_pZoneAuth->QueryInterface(iid, (void**) &punk);
  243. return SUCCEEDED(hr);
  244. }
  245. private:
  246. ~CZoneAuthClient() {} //$ CRASHGUARD
  247. TRef<IZoneAuth> m_pZoneAuth;
  248. TRef<IZoneAuthSession> m_pzas;
  249. ZString m_strAuthServer;
  250. bool m_fInit;
  251. };
  252. TRef<IZoneAuthClient> CreateZoneAuthClient()
  253. {
  254. TRef<CZoneAuthClient> pzac = new CZoneAuthClient();
  255. assert(pzac);
  256. if (pzac && FAILED(pzac->Init()))
  257. pzac = NULL;
  258. return pzac;
  259. }
  260. TRef<IZoneAuthServer> CreateZoneAuthServer()
  261. {
  262. TRef<CZoneAuthServer> pzas = new CZoneAuthServer();
  263. assert(pzas);
  264. if (pzas && FAILED(pzas->Init()))
  265. pzas = NULL;
  266. return pzas;
  267. }