From 092bd6e814c5112e19fcffb8716e1a02938f8803 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20P=C3=B6sel?= Date: Thu, 30 Jun 2016 08:29:55 +0000 Subject: Steam: Implement two factor (mobile) authentization; version bump git-svn-id: http://svn.miranda-ng.org/main/trunk@17052 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/Steam/res/Resource.rc | 19 ++++++++++ protocols/Steam/src/api/authorization.h | 4 +-- protocols/Steam/src/resource.h | 3 +- protocols/Steam/src/steam_dialogs.cpp | 38 ++++++++++++++++++++ protocols/Steam/src/steam_dialogs.h | 21 +++++++++++ protocols/Steam/src/steam_login.cpp | 64 +++++++++++++++++++++++---------- protocols/Steam/src/steam_proto.h | 1 + protocols/Steam/src/version.h | 4 +-- 8 files changed, 130 insertions(+), 24 deletions(-) diff --git a/protocols/Steam/res/Resource.rc b/protocols/Steam/res/Resource.rc index 054d9b2660..2cb5633c29 100644 --- a/protocols/Steam/res/Resource.rc +++ b/protocols/Steam/res/Resource.rc @@ -157,6 +157,17 @@ BEGIN LTEXT "Enter the password to continue.",IDC_STATIC,7,5,197,18 END +IDD_TWOFACTOR DIALOGEX 0, 0, 193, 83 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Steam Guard" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + EDITTEXT IDC_TEXT,7,41,179,14,ES_AUTOHSCROLL + DEFPUSHBUTTON "OK",IDOK,75,62,50,14 + PUSHBUTTON "Cancel",IDCANCEL,136,62,50,14 + LTEXT "As an added account security measure, you'll need to grant access by entering the SMS code we've just sent to your mobile phone.",IDC_STATIC,7,7,179,26 +END + ///////////////////////////////////////////////////////////////////////////// // @@ -215,6 +226,14 @@ BEGIN IDD_PASSWORD_EDITOR, DIALOG BEGIN END + + IDD_TWOFACTOR, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 186 + TOPMARGIN, 7 + BOTTOMMARGIN, 76 + END END #endif // APSTUDIO_INVOKED diff --git a/protocols/Steam/src/api/authorization.h b/protocols/Steam/src/api/authorization.h index 20e9f3ced9..87bff30afd 100644 --- a/protocols/Steam/src/api/authorization.h +++ b/protocols/Steam/src/api/authorization.h @@ -4,7 +4,7 @@ class AuthorizationRequest : public HttpRequest { public: - AuthorizationRequest(const char *username, const char *password, const char *timestamp, const char *twofactorcode, const char *guardCode, const char *guardId = "", const char *captchaId = "-1", const char *captchaText = "") : + AuthorizationRequest(const char *username, const char *password, const char *timestamp, const char *twoFactorCode, const char *guardCode, const char *guardId = "", const char *captchaId = "-1", const char *captchaText = "") : HttpRequest(REQUEST_POST, STEAM_WEB_URL "/mobilelogin/dologin/") { flags = NLHRF_HTTP11 | NLHRF_SSL | NLHRF_NODUMP; @@ -17,7 +17,7 @@ public: data.AppendFormat("password=%s&username=%s&twofactorcode=%s&emailauth=%s&loginfriendlyname=%s&oauth_client_id=3638BFB1&captchagid=%s&captcha_text=%s&emailsteamid=%s&rsatimestamp=%s&rememberlogin=false&donotcache=%lld", ptrA(mir_urlEncode(password)), ptrA(mir_urlEncode(username)), - twofactorcode, + twoFactorCode, guardCode, "Miranda%20NG", captchaId, diff --git a/protocols/Steam/src/resource.h b/protocols/Steam/src/resource.h index 6532c01025..bafc927a3b 100644 --- a/protocols/Steam/src/resource.h +++ b/protocols/Steam/src/resource.h @@ -13,6 +13,7 @@ #define IDC_SAVEPERMANENTLY 108 #define IDD_CAPTCHA 118 #define IDD_GUARD 119 +#define IDD_TWOFACTOR 120 #define IDC_SN 1001 #define IDC_PW 1002 #define IDC_PASSWORD 1002 @@ -38,7 +39,7 @@ // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 120 +#define _APS_NEXT_RESOURCE_VALUE 121 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1085 #define _APS_NEXT_SYMED_VALUE 101 diff --git a/protocols/Steam/src/steam_dialogs.cpp b/protocols/Steam/src/steam_dialogs.cpp index c9bfb2540b..a51193f9cf 100644 --- a/protocols/Steam/src/steam_dialogs.cpp +++ b/protocols/Steam/src/steam_dialogs.cpp @@ -76,6 +76,44 @@ const char* CSteamGuardDialog::GetGuardCode() ///////////////////////////////////////////////////////////////////////////////// +CSteamTwoFactorDialog::CSteamTwoFactorDialog(CSteamProto *proto) +: CSteamDlgBase(proto, IDD_TWOFACTOR, false), +m_ok(this, IDOK), +m_text(this, IDC_TEXT) +{ + memset(m_twoFactorCode, 0, sizeof(m_twoFactorCode)); + m_ok.OnClick = Callback(this, &CSteamTwoFactorDialog::OnOk); +} + +void CSteamTwoFactorDialog::OnInitDialog() +{ + char iconName[100]; + mir_snprintf(iconName, "%s_%s", MODULE, "main"); + Window_SetIcon_IcoLib(m_hwnd, IcoLib_GetIconHandle(iconName)); + + SendMessage(m_text.GetHwnd(), EM_LIMITTEXT, 5, 0); + + Utils_RestoreWindowPosition(m_hwnd, NULL, m_proto->m_szModuleName, "TwoFactorWindow"); +} + +void CSteamTwoFactorDialog::OnOk(CCtrlButton*) +{ + mir_strncpy(m_twoFactorCode, ptrA(m_text.GetTextA()), _countof(m_twoFactorCode)); + EndDialog(m_hwnd, DIALOG_RESULT_OK); +} + +void CSteamTwoFactorDialog::OnClose() +{ + Utils_SaveWindowPosition(m_hwnd, NULL, m_proto->m_szModuleName, "TwoFactorWindow"); +} + +const char* CSteamTwoFactorDialog::GetTwoFactorCode() +{ + return m_twoFactorCode; +} + +///////////////////////////////////////////////////////////////////////////////// + CSteamCaptchaDialog::CSteamCaptchaDialog(CSteamProto *proto, BYTE *captchaImage, int captchaImageSize) : CSteamDlgBase(proto, IDD_CAPTCHA, false), m_ok(this, IDOK), m_text(this, IDC_TEXT), diff --git a/protocols/Steam/src/steam_dialogs.h b/protocols/Steam/src/steam_dialogs.h index 5bc4d6ecd3..133c19f414 100644 --- a/protocols/Steam/src/steam_dialogs.h +++ b/protocols/Steam/src/steam_dialogs.h @@ -49,6 +49,27 @@ public: ///////////////////////////////////////////////////////////////////////////////// +class CSteamTwoFactorDialog : public CSteamDlgBase +{ +private: + char m_twoFactorCode[6]; + + CCtrlEdit m_text; + CCtrlButton m_ok; + +protected: + void OnInitDialog(); + void OnOk(CCtrlButton*); + void OnClose(); + +public: + CSteamTwoFactorDialog(CSteamProto *proto); + + const char *GetTwoFactorCode(); +}; + +///////////////////////////////////////////////////////////////////////////////// + class CSteamCaptchaDialog : public CSteamDlgBase { private: diff --git a/protocols/Steam/src/steam_login.cpp b/protocols/Steam/src/steam_login.cpp index 8a4e5c8255..979fc03c7e 100644 --- a/protocols/Steam/src/steam_login.cpp +++ b/protocols/Steam/src/steam_login.cpp @@ -94,6 +94,9 @@ void CSteamProto::OnGotRsaKey(const HttpResponse *response) // run authorization request T2Utf username(getTStringA("Username")); + ptrA twoFactorCode(getStringA("TwoFactorCode")); + if (!twoFactorCode) twoFactorCode = mir_strdup(""); + ptrA guardId(getStringA("GuardId")); if (!guardId) guardId = mir_strdup(""); ptrA guardCode(getStringA("GuardCode")); @@ -105,7 +108,7 @@ void CSteamProto::OnGotRsaKey(const HttpResponse *response) if (!captchaText) captchaText = mir_strdup(""); PushRequest( - new AuthorizationRequest(username, base64RsaEncryptedPassword, timestamp.c_str(), "", guardCode, guardId, captchaId, captchaText), + new AuthorizationRequest(username, base64RsaEncryptedPassword, timestamp.c_str(), twoFactorCode, guardCode, guardId, captchaId, captchaText), &CSteamProto::OnAuthorization); } @@ -133,17 +136,25 @@ void CSteamProto::OnAuthorization(const HttpResponse *response) OnAuthorizationSuccess(root); } +void CSteamProto::DeleteAuthSettings() +{ + delSetting("TwoFactorCode"); + delSetting("GuardId"); + delSetting("GuardCode"); + delSetting("CaptchaId"); + delSetting("CaptchaText"); +} + void CSteamProto::OnAuthorizationError(const JSONNode &node) { std::string message = node["message"].as_string(); ptrT messageT(mir_utf8decodeT(message.c_str())); + debugLogA("CSteamProto::OnAuthorizationError: %s", 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"); + DeleteAuthSettings(); SetStatus(ID_STATUS_OFFLINE); return; } @@ -152,11 +163,34 @@ void CSteamProto::OnAuthorizationError(const JSONNode &node) if (node["requires_twofactor"].as_bool()) { + debugLogA("CSteamProto::OnAuthorizationError: requires twofactor"); + + CSteamTwoFactorDialog twoFactorDialog(this); + if (twoFactorDialog.DoModal() != DIALOG_RESULT_OK) + { + DeleteAuthSettings(); + SetStatus(ID_STATUS_OFFLINE); + return; + } + + setString("TwoFactorCode", twoFactorDialog.GetTwoFactorCode()); + + PushRequest( + new GetRsaKeyRequest(username), + &CSteamProto::OnGotRsaKey); + return; + } + + if (node["clear_password_field"].as_bool()) + { + debugLogA("CSteamProto::OnAuthorizationError: clear password field"); return; } if (node["emailauth_needed"].as_bool()) { + debugLogA("CSteamProto::OnAuthorizationError: emailauth needed"); + std::string guardId = node["emailsteamid"].as_string(); ptrA oldGuardId(getStringA("GuardId")); if (mir_strcmp(guardId.c_str(), oldGuardId) == 0) @@ -178,10 +212,7 @@ void CSteamProto::OnAuthorizationError(const JSONNode &node) CSteamGuardDialog guardDialog(this, domain.c_str()); if (guardDialog.DoModal() != DIALOG_RESULT_OK) { - delSetting("GuardId"); - delSetting("GuardCode"); - delSetting("CaptchaId"); - delSetting("CaptchaText"); + DeleteAuthSettings(); SetStatus(ID_STATUS_OFFLINE); return; } @@ -197,6 +228,8 @@ void CSteamProto::OnAuthorizationError(const JSONNode &node) if (node["captcha_needed"].as_bool()) { + debugLogA("CSteamProto::OnAuthorizationError: captcha needed"); + std::string captchaId = node["captcha_gid"].as_string(); GetCaptchaRequest *request = new GetCaptchaRequest(captchaId.c_str()); @@ -207,8 +240,7 @@ void CSteamProto::OnAuthorizationError(const JSONNode &node) delete response; if (captchaDialog.DoModal() != DIALOG_RESULT_OK) { - delSetting("CaptchaId"); - delSetting("CaptchaText"); + DeleteAuthSettings(); SetStatus(ID_STATUS_OFFLINE); return; } @@ -222,19 +254,13 @@ void CSteamProto::OnAuthorizationError(const JSONNode &node) return; } - delSetting("GuardId"); - delSetting("GuardCode"); - delSetting("CaptchaId"); - delSetting("CaptchaText"); + DeleteAuthSettings(); SetStatus(ID_STATUS_OFFLINE); } void CSteamProto::OnAuthorizationSuccess(const JSONNode &node) { - delSetting("GuardId"); - delSetting("GuardCode"); - delSetting("CaptchaId"); - delSetting("CaptchaText"); + DeleteAuthSettings(); if (!node["login_complete"].as_bool()) { diff --git a/protocols/Steam/src/steam_proto.h b/protocols/Steam/src/steam_proto.h index 4f47883aa2..672f500451 100644 --- a/protocols/Steam/src/steam_proto.h +++ b/protocols/Steam/src/steam_proto.h @@ -129,6 +129,7 @@ protected: void OnLoggedOn(const HttpResponse *response); void HandleTokenExpired(); + void DeleteAuthSettings(); // contacts void SetContactStatus(MCONTACT hContact, WORD status); diff --git a/protocols/Steam/src/version.h b/protocols/Steam/src/version.h index 3403cb5e45..12dd9db18e 100644 --- a/protocols/Steam/src/version.h +++ b/protocols/Steam/src/version.h @@ -1,7 +1,7 @@ #define __MAJOR_VERSION 0 #define __MINOR_VERSION 11 -#define __RELEASE_NUM 5 -#define __BUILD_NUM 1 +#define __RELEASE_NUM 6 +#define __BUILD_NUM 0 #include -- cgit v1.2.3