From b621abd5fa5c6e452d6627b362b62e415246684d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20P=C3=B6sel?= Date: Sat, 19 Dec 2015 17:05:44 +0000 Subject: Steam: Try to login again on PollThread's "Not Logged On" error git-svn-id: http://svn.miranda-ng.org/main/trunk@15897 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/Steam/src/steam_login.cpp | 656 ++++++++++++++++++---------------- protocols/Steam/src/steam_polling.cpp | 24 +- protocols/Steam/src/steam_proto.h | 2 + 3 files changed, 362 insertions(+), 320 deletions(-) (limited to 'protocols') diff --git a/protocols/Steam/src/steam_login.cpp b/protocols/Steam/src/steam_login.cpp index 112bad8592..612af3496c 100644 --- a/protocols/Steam/src/steam_login.cpp +++ b/protocols/Steam/src/steam_login.cpp @@ -1,311 +1,347 @@ -#include "stdafx.h" - -bool CSteamProto::IsOnline() -{ - return m_iStatus > ID_STATUS_OFFLINE && m_hPollingThread; -} - -bool CSteamProto::IsMe(const char *steamId) -{ - ptrA mySteamId(getStringA("SteamID")); - if (!lstrcmpA(steamId, mySteamId)) - return true; - - return false; -} - -void CSteamProto::OnGotRsaKey(const HttpResponse *response) -{ - if (!CheckResponse(response)) - return; - - // load rsa key parts - JSONNode root = JSONNode::parse(response->pData); - if (!root) - return; - - if (!root["success"].as_bool()) - return; - - std::string modulus = root["publickey_mod"].as_string(); - // exponent "010001" is used as constant in CSteamProto::RsaEncrypt - //std::string exponent = root["publickey_exp"].as_string(); - - std::string timestamp = root["timestamp"].as_string(); - - // encrcrypt password - ptrA base64RsaEncryptedPassword; - ptrA szPassword(getStringA("Password")); - - DWORD error = 0; - DWORD encryptedSize = 0; - if ((error = RsaEncrypt(modulus.c_str(), szPassword, NULL, encryptedSize)) != 0) - { - debugLogA("CSteamProto::OnGotRsaKey: encryption error (%lu)", error); - return; - } - - BYTE *encryptedPassword = (BYTE*)mir_calloc(encryptedSize); - if ((error = RsaEncrypt(modulus.c_str(), szPassword, encryptedPassword, encryptedSize)) != 0) - { - debugLogA("CSteamProto::OnGotRsaKey: encryption error (%lu)", error); - return; - } - - base64RsaEncryptedPassword = mir_base64_encode(encryptedPassword, encryptedSize); - mir_free(encryptedPassword); - - // run authorization request - T2Utf username(getTStringA("Username")); - - ptrA guardId(getStringA("GuardId")); - if (!guardId) guardId = mir_strdup(""); - ptrA guardCode(getStringA("GuardCode")); - if (!guardCode) guardCode = mir_strdup(""); - - ptrA captchaId(getStringA("CaptchaId")); - if (!captchaId) captchaId = mir_strdup("-1"); - ptrA captchaText(getStringA("CaptchaText")); - if (!captchaText) captchaText = mir_strdup(""); - - PushRequest( - new AuthorizationRequest(username, base64RsaEncryptedPassword, timestamp.c_str(), "", guardCode, guardId, captchaId, captchaText), - &CSteamProto::OnAuthorization); -} - -void CSteamProto::OnAuthorization(const HttpResponse *response) -{ - if (!CheckResponse(response)) - { - SetStatus(ID_STATUS_OFFLINE); - return; - } - - JSONNode root = JSONNode::parse(response->pData); - if (!root) - { - SetStatus(ID_STATUS_OFFLINE); - return; - } - - if (!root["success"].as_bool()) - { - OnAuthorizationError(root); - return; - } - - OnAuthorizationSuccess(root); -} - -void CSteamProto::OnAuthorizationError(const JSONNode &node) -{ - std::string message = node["message"].as_string(); - ptrT messageT(mir_utf8decodeT(message.c_str())); - if (!mir_tstrcmpi(messageT, _T("Incorrect login."))) - { - // We can't continue with incorrect login/password - delSetting("GuardId"); - delSetting("GuardCode"); - delSetting("CaptchaId"); - delSetting("CaptchaText"); - SetStatus(ID_STATUS_OFFLINE); - return; - } - - T2Utf username(getTStringA("Username")); - - if (node["requires_twofactor"].as_bool()) - { - return; - } - - if (node["emailauth_needed"].as_bool()) - { - std::string guardId = node["emailsteamid"].as_string(); - ptrA oldGuardId(getStringA("GuardId")); - if (mir_strcmp(guardId.c_str(), oldGuardId) == 0) - { - delSetting("GuardId"); - delSetting("GuardCode"); - PushRequest( - new GetRsaKeyRequest(username), - &CSteamProto::OnGotRsaKey); - return; - } - - std::string domain = node["emaildomain"].as_string(); - - CSteamGuardDialog guardDialog(this, domain.c_str()); - if (guardDialog.DoModal() != DIALOG_RESULT_OK) - { - delSetting("GuardId"); - delSetting("GuardCode"); - delSetting("CaptchaId"); - delSetting("CaptchaText"); - SetStatus(ID_STATUS_OFFLINE); - return; - } - - setString("GuardId", guardId.c_str()); - setString("GuardCode", guardDialog.GetGuardCode()); - - PushRequest( - new GetRsaKeyRequest(username), - &CSteamProto::OnGotRsaKey); - return; - } - - if (node["captcha_needed"].as_bool()) - { - std::string captchaId = node["captcha_gid"].as_string(); - - GetCaptchaRequest *request = new GetCaptchaRequest(captchaId.c_str()); - HttpResponse *response = request->Send(m_hNetlibUser); - delete request; - - CSteamCaptchaDialog captchaDialog(this, (BYTE*)response->pData, response->dataLength); - delete response; - if (captchaDialog.DoModal() != DIALOG_RESULT_OK) - { - delSetting("CaptchaId"); - delSetting("CaptchaText"); - SetStatus(ID_STATUS_OFFLINE); - return; - } - - setString("CaptchaId", captchaId.c_str()); - setString("CaptchaText", captchaDialog.GetCaptchaText()); - - PushRequest( - new GetRsaKeyRequest(username), - &CSteamProto::OnGotRsaKey); - return; - } - - delSetting("GuardId"); - delSetting("GuardCode"); - delSetting("CaptchaId"); - delSetting("CaptchaText"); - SetStatus(ID_STATUS_OFFLINE); -} - -void CSteamProto::OnAuthorizationSuccess(const JSONNode &node) -{ - delSetting("GuardId"); - delSetting("GuardCode"); - delSetting("CaptchaId"); - delSetting("CaptchaText"); - - if (!node["login_complete"].as_bool()) - { - SetStatus(ID_STATUS_OFFLINE); - return; - } - - std::string oauth = node["oauth"].as_string(); - JSONNode root = JSONNode::parse(oauth.c_str()); - if (!root) - { - SetStatus(ID_STATUS_OFFLINE); - return; - } - - std::string steamId = root["steamid"].as_string(); - setString("SteamID", steamId.c_str()); - - std::string token = root["oauth_token"].as_string(); - setString("TokenSecret", token.c_str()); - - std::string cookie = root["webcookie"].as_string(); - - PushRequest( - new GetSessionRequest(token.c_str(), steamId.c_str(), cookie.c_str()), - &CSteamProto::OnGotSession); - - PushRequest( - new LogonRequest(token.c_str()), - &CSteamProto::OnLoggedOn); -} - -void CSteamProto::OnGotSession(const HttpResponse *response) -{ - if(!response) - return; - - for (int i = 0; i < response->headersCount; i++) - { - if (lstrcmpiA(response->headers[i].szName, "Set-Cookie")) - continue; - - std::string cookies = response->headers[i].szValue; - size_t start = cookies.find("sessionid=") + 10; - size_t end = cookies.substr(start).find(';'); - std::string sessionId = cookies.substr(start, end - start + 10); - setString("SessionID", sessionId.c_str()); - break; - } -} - -void CSteamProto::HandleTokenExpired() -{ - // Notify error to user - ShowNotification(_T("Steam"), TranslateT("Connection token expired. Please login again.")); - - // Delete expired token - delSetting("TokenSecret"); - - // Set status to offline - SetStatus(ID_STATUS_OFFLINE); - - // TODO: Try to login again acutomatically (at least once) -} - -void CSteamProto::OnLoggedOn(const HttpResponse *response) -{ - if (!CheckResponse(response)) - { - if (response->resultCode == HTTP_CODE_UNAUTHORIZED) - { - // Probably expired TokenSecret - HandleTokenExpired(); - return; - } - - // Probably timeout or no connection, we can do nothing here - ShowNotification(_T("Steam"), TranslateT("Unknown login error.")); - - SetStatus(ID_STATUS_OFFLINE); - return; - } - - JSONROOT root(response->pData); - - JSONNode *node = json_get(root, "error"); - ptrT error(json_as_string(node)); - if (mir_tstrcmpi(error, _T("OK"))) - { - // Probably expired TokenSecret - HandleTokenExpired(); - return; - } - - node = json_get(root, "umqid"); - setString("UMQID", ptrA(mir_u2a(ptrT(json_as_string(node))))); - - node = json_get(root, "message"); - setDword("MessageID", json_as_int(node)); - - // load contact list - ptrA token(getStringA("TokenSecret")); - ptrA steamId(getStringA("SteamID")); - - PushRequest( - new GetFriendListRequest(token, steamId), - &CSteamProto::OnGotFriendList); - - // start polling thread - m_hPollingThread = ForkThreadEx(&CSteamProto::PollingThread, 0, NULL); - - // go to online now - ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)ID_STATUS_CONNECTING, m_iStatus = m_iDesiredStatus); +#include "stdafx.h" + +bool CSteamProto::IsOnline() +{ + return m_iStatus > ID_STATUS_OFFLINE && m_hPollingThread; +} + +bool CSteamProto::IsMe(const char *steamId) +{ + ptrA mySteamId(getStringA("SteamID")); + if (!lstrcmpA(steamId, mySteamId)) + return true; + + return false; +} + +bool CSteamProto::Relogin() +{ + ptrA token(getStringA("TokenSecret")); + if (mir_strlen(token) <= 0) + return false; + + HttpRequest *request = new LogonRequest(token); + HttpResponse *response = request->Send(m_hNetlibUser); + + bool success = false; + if (CheckResponse(response)) + { + JSONROOT root(response->pData); + if (root != NULL) { + JSONNode *node = json_get(root, "error"); + + ptrT error(json_as_string(node)); + if (!mir_tstrcmpi(error, _T("OK"))) + { + node = json_get(root, "umqid"); + setString("UMQID", ptrA(mir_u2a(ptrT(json_as_string(node))))); + + node = json_get(root, "message"); + setDword("MessageID", json_as_int(node)); + + success = true; + } + } + } + + delete request; + delete response; + + return success; +} + +void CSteamProto::OnGotRsaKey(const HttpResponse *response) +{ + if (!CheckResponse(response)) + return; + + // load rsa key parts + JSONNode root = JSONNode::parse(response->pData); + if (!root) + return; + + if (!root["success"].as_bool()) + return; + + std::string modulus = root["publickey_mod"].as_string(); + // exponent "010001" is used as constant in CSteamProto::RsaEncrypt + //std::string exponent = root["publickey_exp"].as_string(); + + std::string timestamp = root["timestamp"].as_string(); + + // encrcrypt password + ptrA base64RsaEncryptedPassword; + ptrA szPassword(getStringA("Password")); + + DWORD error = 0; + DWORD encryptedSize = 0; + if ((error = RsaEncrypt(modulus.c_str(), szPassword, NULL, encryptedSize)) != 0) + { + debugLogA("CSteamProto::OnGotRsaKey: encryption error (%lu)", error); + return; + } + + BYTE *encryptedPassword = (BYTE*)mir_calloc(encryptedSize); + if ((error = RsaEncrypt(modulus.c_str(), szPassword, encryptedPassword, encryptedSize)) != 0) + { + debugLogA("CSteamProto::OnGotRsaKey: encryption error (%lu)", error); + return; + } + + base64RsaEncryptedPassword = mir_base64_encode(encryptedPassword, encryptedSize); + mir_free(encryptedPassword); + + // run authorization request + T2Utf username(getTStringA("Username")); + + ptrA guardId(getStringA("GuardId")); + if (!guardId) guardId = mir_strdup(""); + ptrA guardCode(getStringA("GuardCode")); + if (!guardCode) guardCode = mir_strdup(""); + + ptrA captchaId(getStringA("CaptchaId")); + if (!captchaId) captchaId = mir_strdup("-1"); + ptrA captchaText(getStringA("CaptchaText")); + if (!captchaText) captchaText = mir_strdup(""); + + PushRequest( + new AuthorizationRequest(username, base64RsaEncryptedPassword, timestamp.c_str(), "", guardCode, guardId, captchaId, captchaText), + &CSteamProto::OnAuthorization); +} + +void CSteamProto::OnAuthorization(const HttpResponse *response) +{ + if (!CheckResponse(response)) + { + SetStatus(ID_STATUS_OFFLINE); + return; + } + + JSONNode root = JSONNode::parse(response->pData); + if (!root) + { + SetStatus(ID_STATUS_OFFLINE); + return; + } + + if (!root["success"].as_bool()) + { + OnAuthorizationError(root); + return; + } + + OnAuthorizationSuccess(root); +} + +void CSteamProto::OnAuthorizationError(const JSONNode &node) +{ + std::string message = node["message"].as_string(); + ptrT messageT(mir_utf8decodeT(message.c_str())); + if (!mir_tstrcmpi(messageT, _T("Incorrect login."))) + { + // We can't continue with incorrect login/password + delSetting("GuardId"); + delSetting("GuardCode"); + delSetting("CaptchaId"); + delSetting("CaptchaText"); + SetStatus(ID_STATUS_OFFLINE); + return; + } + + T2Utf username(getTStringA("Username")); + + if (node["requires_twofactor"].as_bool()) + { + return; + } + + if (node["emailauth_needed"].as_bool()) + { + std::string guardId = node["emailsteamid"].as_string(); + ptrA oldGuardId(getStringA("GuardId")); + if (mir_strcmp(guardId.c_str(), oldGuardId) == 0) + { + delSetting("GuardId"); + delSetting("GuardCode"); + PushRequest( + new GetRsaKeyRequest(username), + &CSteamProto::OnGotRsaKey); + return; + } + + std::string domain = node["emaildomain"].as_string(); + + CSteamGuardDialog guardDialog(this, domain.c_str()); + if (guardDialog.DoModal() != DIALOG_RESULT_OK) + { + delSetting("GuardId"); + delSetting("GuardCode"); + delSetting("CaptchaId"); + delSetting("CaptchaText"); + SetStatus(ID_STATUS_OFFLINE); + return; + } + + setString("GuardId", guardId.c_str()); + setString("GuardCode", guardDialog.GetGuardCode()); + + PushRequest( + new GetRsaKeyRequest(username), + &CSteamProto::OnGotRsaKey); + return; + } + + if (node["captcha_needed"].as_bool()) + { + std::string captchaId = node["captcha_gid"].as_string(); + + GetCaptchaRequest *request = new GetCaptchaRequest(captchaId.c_str()); + HttpResponse *response = request->Send(m_hNetlibUser); + delete request; + + CSteamCaptchaDialog captchaDialog(this, (BYTE*)response->pData, response->dataLength); + delete response; + if (captchaDialog.DoModal() != DIALOG_RESULT_OK) + { + delSetting("CaptchaId"); + delSetting("CaptchaText"); + SetStatus(ID_STATUS_OFFLINE); + return; + } + + setString("CaptchaId", captchaId.c_str()); + setString("CaptchaText", captchaDialog.GetCaptchaText()); + + PushRequest( + new GetRsaKeyRequest(username), + &CSteamProto::OnGotRsaKey); + return; + } + + delSetting("GuardId"); + delSetting("GuardCode"); + delSetting("CaptchaId"); + delSetting("CaptchaText"); + SetStatus(ID_STATUS_OFFLINE); +} + +void CSteamProto::OnAuthorizationSuccess(const JSONNode &node) +{ + delSetting("GuardId"); + delSetting("GuardCode"); + delSetting("CaptchaId"); + delSetting("CaptchaText"); + + if (!node["login_complete"].as_bool()) + { + SetStatus(ID_STATUS_OFFLINE); + return; + } + + std::string oauth = node["oauth"].as_string(); + JSONNode root = JSONNode::parse(oauth.c_str()); + if (!root) + { + SetStatus(ID_STATUS_OFFLINE); + return; + } + + std::string steamId = root["steamid"].as_string(); + setString("SteamID", steamId.c_str()); + + std::string token = root["oauth_token"].as_string(); + setString("TokenSecret", token.c_str()); + + std::string cookie = root["webcookie"].as_string(); + + PushRequest( + new GetSessionRequest(token.c_str(), steamId.c_str(), cookie.c_str()), + &CSteamProto::OnGotSession); + + PushRequest( + new LogonRequest(token.c_str()), + &CSteamProto::OnLoggedOn); +} + +void CSteamProto::OnGotSession(const HttpResponse *response) +{ + if(!response) + return; + + for (int i = 0; i < response->headersCount; i++) + { + if (lstrcmpiA(response->headers[i].szName, "Set-Cookie")) + continue; + + std::string cookies = response->headers[i].szValue; + size_t start = cookies.find("sessionid=") + 10; + size_t end = cookies.substr(start).find(';'); + std::string sessionId = cookies.substr(start, end - start + 10); + setString("SessionID", sessionId.c_str()); + break; + } +} + +void CSteamProto::HandleTokenExpired() +{ + // Notify error to user + ShowNotification(_T("Steam"), TranslateT("Connection token expired. Please login again.")); + + // Delete expired token + delSetting("TokenSecret"); + + // Set status to offline + SetStatus(ID_STATUS_OFFLINE); + + // TODO: Try to login again acutomatically (at least once) +} + +void CSteamProto::OnLoggedOn(const HttpResponse *response) +{ + if (!CheckResponse(response)) + { + if (response->resultCode == HTTP_CODE_UNAUTHORIZED) + { + // Probably expired TokenSecret + HandleTokenExpired(); + return; + } + + // Probably timeout or no connection, we can do nothing here + ShowNotification(_T("Steam"), TranslateT("Unknown login error.")); + + SetStatus(ID_STATUS_OFFLINE); + return; + } + + JSONROOT root(response->pData); + + JSONNode *node = json_get(root, "error"); + ptrT error(json_as_string(node)); + if (mir_tstrcmpi(error, _T("OK"))) + { + // Probably expired TokenSecret + HandleTokenExpired(); + return; + } + + node = json_get(root, "umqid"); + setString("UMQID", ptrA(mir_u2a(ptrT(json_as_string(node))))); + + node = json_get(root, "message"); + setDword("MessageID", json_as_int(node)); + + // load contact list + ptrA token(getStringA("TokenSecret")); + ptrA steamId(getStringA("SteamID")); + + PushRequest( + new GetFriendListRequest(token, steamId), + &CSteamProto::OnGotFriendList); + + // start polling thread + m_hPollingThread = ForkThreadEx(&CSteamProto::PollingThread, 0, NULL); + + // go to online now + ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)ID_STATUS_CONNECTING, m_iStatus = m_iDesiredStatus); } \ No newline at end of file diff --git a/protocols/Steam/src/steam_polling.cpp b/protocols/Steam/src/steam_polling.cpp index 0078009e15..0d278ee946 100644 --- a/protocols/Steam/src/steam_polling.cpp +++ b/protocols/Steam/src/steam_polling.cpp @@ -222,19 +222,23 @@ void CSteamProto::PollingThread(void*) { // Do nothing as this is not necessarily an error } - /*else if (!lstrcmpi(error, _T("Not Logged On"))) // 'else' below will handle this error, we don't need this particular check right now + else if (!lstrcmpi(error, _T("Not Logged On"))) // 'else' below will handle this error, we don't need this particular check right now { - if (!IsOnline()) - { - // need to relogin - debugLog(_T("CSteamProto::PollingThread: not logged on")); + // need to relogin + debugLog(_T("CSteamProto::PollingThread: Not Logged On")); - SetStatus(ID_STATUS_OFFLINE); + if (Relogin()) + { + // load umqId and messageId again + umqId = getStringA("UMQID"); // it's ptrA so we can assign it without fearing a memory leak + messageId = getDword("MessageID", 0); } - - // let it jump out of further processing - errors = errorsLimit; - }*/ + else + { + // let it jump out of further processing + errors = errorsLimit; + } + } else { // something wrong diff --git a/protocols/Steam/src/steam_proto.h b/protocols/Steam/src/steam_proto.h index e7a6844153..650675edfd 100644 --- a/protocols/Steam/src/steam_proto.h +++ b/protocols/Steam/src/steam_proto.h @@ -106,6 +106,8 @@ protected: // account bool IsOnline(); bool IsMe(const char *steamId); + + bool Relogin(); void OnGotRsaKey(const HttpResponse *response); -- cgit v1.2.3