diff options
author | George Hazan <george.hazan@gmail.com> | 2024-01-14 18:43:24 +0300 |
---|---|---|
committer | George Hazan <george.hazan@gmail.com> | 2024-01-14 18:43:24 +0300 |
commit | a8c9c34bead54d469f126db194b571e2fe90b078 (patch) | |
tree | e4348568eb8a966f4d87abf50beb98b2808a78b2 /protocols | |
parent | a76d633fcee305009b2c8798d577e16f8dd0d931 (diff) |
Discord: add MFA support
Diffstat (limited to 'protocols')
-rw-r--r-- | protocols/Discord/discord.vcxproj | 1 | ||||
-rw-r--r-- | protocols/Discord/discord.vcxproj.filters | 3 | ||||
-rw-r--r-- | protocols/Discord/res/discord.rc | 26 | ||||
-rw-r--r-- | protocols/Discord/src/http.cpp | 2 | ||||
-rw-r--r-- | protocols/Discord/src/mfa.cpp | 112 | ||||
-rw-r--r-- | protocols/Discord/src/options.cpp | 4 | ||||
-rw-r--r-- | protocols/Discord/src/proto.h | 10 | ||||
-rw-r--r-- | protocols/Discord/src/resource.h | 10 | ||||
-rw-r--r-- | protocols/Discord/src/server.cpp | 17 |
9 files changed, 173 insertions, 12 deletions
diff --git a/protocols/Discord/discord.vcxproj b/protocols/Discord/discord.vcxproj index 59139a349e..dc4a3679bc 100644 --- a/protocols/Discord/discord.vcxproj +++ b/protocols/Discord/discord.vcxproj @@ -35,6 +35,7 @@ <ClCompile Include="src\http.cpp" />
<ClCompile Include="src\main.cpp" />
<ClCompile Include="src\menus.cpp" />
+ <ClCompile Include="src\mfa.cpp" />
<ClCompile Include="src\options.cpp" />
<ClCompile Include="src\proto.cpp" />
<ClCompile Include="src\server.cpp" />
diff --git a/protocols/Discord/discord.vcxproj.filters b/protocols/Discord/discord.vcxproj.filters index f8b955739b..61ee857295 100644 --- a/protocols/Discord/discord.vcxproj.filters +++ b/protocols/Discord/discord.vcxproj.filters @@ -47,6 +47,9 @@ <ClCompile Include="src\voice.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="src\mfa.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\proto.h">
diff --git a/protocols/Discord/res/discord.rc b/protocols/Discord/res/discord.rc index 780cae5613..ce433c060f 100644 --- a/protocols/Discord/res/discord.rc +++ b/protocols/Discord/res/discord.rc @@ -112,6 +112,19 @@ BEGIN EDITTEXT IDC_NICK,3,18,103,12,0,WS_EX_CLIENTEDGE
END
+IDD_MFA DIALOGEX 0, 0, 316, 52
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_APPWINDOW
+CAPTION "2-step verification"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,205,31,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,259,31,50,14
+ LTEXT "",IDC_LABEL,7,8,238,12
+ EDITTEXT IDC_CODE,250,7,59,16,ES_AUTOHSCROLL
+ PUSHBUTTON "Use another method",IDC_ANOTHER,7,31,131,14
+END
+
/////////////////////////////////////////////////////////////////////////////
//
@@ -128,6 +141,14 @@ BEGIN IDD_OPTIONS_ACCMGR, DIALOG
BEGIN
END
+
+ IDD_MFA, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 309
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 45
+ END
END
#endif // APSTUDIO_INVOKED
@@ -142,6 +163,11 @@ BEGIN 0
END
+IDD_MFA AFX_DIALOG_LAYOUT
+BEGIN
+ 0
+END
+
#endif // English (United States) resources
/////////////////////////////////////////////////////////////////////////////
diff --git a/protocols/Discord/src/http.cpp b/protocols/Discord/src/http.cpp index 82e8d495d0..70cfe9db80 100644 --- a/protocols/Discord/src/http.cpp +++ b/protocols/Discord/src/http.cpp @@ -41,7 +41,7 @@ static LONG g_reqNum = 0; AsyncHttpRequest::AsyncHttpRequest(CDiscordProto *ppro, int iRequestType, LPCSTR _url, MTHttpRequestHandler pFunc, JSONNode *pRoot)
{
if (*_url == '/') { // relative url leads to a site
- m_szUrl = "https://discord.com/api/v8";
+ m_szUrl = "https://discord.com/api/v9";
m_szUrl += _url;
m_bMainSite = true;
}
diff --git a/protocols/Discord/src/mfa.cpp b/protocols/Discord/src/mfa.cpp new file mode 100644 index 0000000000..9de79283fa --- /dev/null +++ b/protocols/Discord/src/mfa.cpp @@ -0,0 +1,112 @@ +/* +Copyright © 2016-22 Miranda NG team + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "stdafx.h" + +///////////////////////////////////////////////////////////////////////////////////////// + +class CMfaDialog : public CDiscordDlgBase +{ + bool m_bHasSms, m_bHasTotp, m_bUseTotp = true; + CMStringA m_szTicket; + + CCtrlBase m_label; + CCtrlEdit edtCode; + CCtrlButton btnCancel, btnAnother; + +public: + CMfaDialog(CDiscordProto *ppro, const JSONNode &pRoot) : + CDiscordDlgBase(ppro, IDD_MFA), + m_label(this, IDC_LABEL), + edtCode(this, IDC_CODE), + btnCancel(this, IDCANCEL), + btnAnother(this, IDC_ANOTHER) + { + m_bHasSms = pRoot["sms"].as_bool(); + m_bHasTotp = pRoot["totp"].as_bool(); + m_szTicket = pRoot["ticket"].as_mstring(); + } + + bool OnInitDialog() override + { + if (m_bUseTotp) + m_label.SetText(TranslateT("Enter Discord verification code:")); + else + m_label.SetText(TranslateT("Enter SMS code")); + + // if (!m_bHasSms) + btnAnother.Disable(); + return true; + } + + bool OnApply() override + { + ptrW wszCode(edtCode.GetText()); + + if (m_bUseTotp) { + JSONNode root; + root << WCHAR_PARAM("code", wszCode) << CHAR_PARAM("ticket", m_szTicket); + + auto *pReq = new AsyncHttpRequest(m_proto, REQUEST_POST, "/auth/mfa/totp", &CDiscordProto::OnSendTotp, &root); + pReq->pUserInfo = this; + m_proto->Push(pReq); + } + return false; + } + + void onClick_Cancel() + { + m_proto->ConnectionFailed(LOGINERR_WRONGPASSWORD); + } + + void WrongCode() + { + edtCode.SetText(L""); + Beep(470, 200); + } +}; + +static void CALLBACK LaunchDialog(void *param) +{ + ((CMfaDialog *)param)->Show(); +} + +void CDiscordProto::ShowMfaDialog(const JSONNode &pRoot) +{ + CallFunctionAsync(LaunchDialog, new CMfaDialog(this, pRoot)); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void CDiscordProto::OnSendTotp(MHttpResponse *pReply, struct AsyncHttpRequest *pReq) +{ + auto *pDlg = (CMfaDialog *)pReq->pUserInfo; + + JsonReply root(pReply); + if (!root) { + pDlg->WrongCode(); + return; + } + + pDlg->Close(); + + auto &data = root.data(); + CMStringA szToken = data["token"].as_mstring(); + m_szAccessToken = szToken.Detach(); + setString("AccessToken", m_szAccessToken); + RetrieveMyInfo(); +} diff --git a/protocols/Discord/src/options.cpp b/protocols/Discord/src/options.cpp index 4716584b96..dc4a6d60b5 100644 --- a/protocols/Discord/src/options.cpp +++ b/protocols/Discord/src/options.cpp @@ -19,7 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. /////////////////////////////////////////////////////////////////////////////////////////
-class CDiscardAccountOptions : public CProtoDlgBase<CDiscordProto>
+class CDiscardAccountOptions : public CDiscordDlgBase
{
CCtrlCheck chkUseChats, chkHideChats, chkUseGroups, chkDeleteMsgs;
CCtrlEdit m_edGroup, m_edUserName, m_edPassword;
@@ -27,7 +27,7 @@ class CDiscardAccountOptions : public CProtoDlgBase<CDiscordProto> public:
CDiscardAccountOptions(CDiscordProto *ppro, int iDlgID, bool bFullDlg) :
- CProtoDlgBase<CDiscordProto>(ppro, iDlgID),
+ CDiscordDlgBase(ppro, iDlgID),
m_edGroup(this, IDC_GROUP),
m_edUserName(this, IDC_USERNAME),
m_edPassword(this, IDC_PASSWORD),
diff --git a/protocols/Discord/src/proto.h b/protocols/Discord/src/proto.h index fdb5e6a33b..bb99d2efbc 100644 --- a/protocols/Discord/src/proto.h +++ b/protocols/Discord/src/proto.h @@ -227,6 +227,7 @@ class CDiscordProto : public PROTO<CDiscordProto> {
friend struct AsyncHttpRequest;
friend class CDiscardAccountOptions;
+ friend class CMfaDialog;
class CDiscordProtoImpl
{
@@ -395,6 +396,13 @@ class CDiscordProto : public PROTO<CDiscordProto> void ParseSpecialChars(SESSION_INFO *si, CMStringW &str);
//////////////////////////////////////////////////////////////////////////////////////
+ // two-factor auth
+
+ void ShowMfaDialog(const JSONNode &pRoot);
+
+ void OnSendTotp(MHttpResponse *, struct AsyncHttpRequest *);
+
+ //////////////////////////////////////////////////////////////////////////////////////
// misc methods
SnowFlake getId(const char *szName);
@@ -526,6 +534,8 @@ public: void CheckAvatarChange(MCONTACT hContact, const CMStringW &wszNewHash);
};
+typedef CProtoDlgBase<CDiscordProto> CDiscordDlgBase;
+
/////////////////////////////////////////////////////////////////////////////////////////
struct CMPlugin : public ACCPROTOPLUGIN<CDiscordProto>
diff --git a/protocols/Discord/src/resource.h b/protocols/Discord/src/resource.h index 099a4af3af..dc1c9706f1 100644 --- a/protocols/Discord/src/resource.h +++ b/protocols/Discord/src/resource.h @@ -1,6 +1,6 @@ //{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
-// Used by w:\miranda-ng\protocols\Discord\res\discord.rc
+// Used by W:\miranda-ng\protocols\Discord\res\discord.rc
//
#define IDI_MAIN 101
#define IDI_GROUPCHAT 102
@@ -9,6 +9,7 @@ #define IDD_OPTIONS_ACCMGR 105
#define IDI_VOICE_CALL 106
#define IDI_VOICE_ENDED 107
+#define IDD_MFA 108
#define IDC_PASSWORD 1001
#define IDC_USERNAME 1002
#define IDC_GROUP 1003
@@ -16,15 +17,18 @@ #define IDC_HIDECHATS 1005
#define IDC_USEGROUPS 1006
#define IDC_USEGUILDS 1007
+#define IDC_CODE 1008
#define IDC_DELETE_MSGS 1009
+#define IDC_ANOTHER 1009
+#define IDC_LABEL 1010
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 104
+#define _APS_NEXT_RESOURCE_VALUE 108
#define _APS_NEXT_COMMAND_VALUE 40001
-#define _APS_NEXT_CONTROL_VALUE 1008
+#define _APS_NEXT_CONTROL_VALUE 1011
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
diff --git a/protocols/Discord/src/server.cpp b/protocols/Discord/src/server.cpp index 104d45435d..75167a7a60 100644 --- a/protocols/Discord/src/server.cpp +++ b/protocols/Discord/src/server.cpp @@ -281,13 +281,18 @@ void CDiscordProto::OnReceiveToken(MHttpResponse *pReply, AsyncHttpRequest*) }
auto &data = root.data();
- CMStringA szToken = data["token"].as_mstring();
- if (szToken.IsEmpty()) {
- debugLogA("Strange empty token received, exiting");
+ if (auto &token = data["token"]) {
+ CMStringA szToken = token.as_mstring();
+ m_szAccessToken = szToken.Detach();
+ setString("AccessToken", m_szAccessToken);
+ RetrieveMyInfo();
return;
}
- m_szAccessToken = szToken.Detach();
- setString("AccessToken", m_szAccessToken);
- RetrieveMyInfo();
+ if (data["mfa"].as_bool())
+ ShowMfaDialog(data);
+ else {
+ ConnectionFailed(LOGINERR_WRONGPASSWORD);
+ debugLogA("Strange empty token received, exiting");
+ }
}
|