summaryrefslogtreecommitdiff
path: root/protocols
diff options
context:
space:
mode:
authorRobert Pösel <robyer@seznam.cz>2016-04-17 11:14:33 +0000
committerRobert Pösel <robyer@seznam.cz>2016-04-17 11:14:33 +0000
commit1218cb54337c4683baf728bec19701da1f10e5ac (patch)
tree925726d9fbed53764efebbe7e1bbbbf2bd8339f9 /protocols
parent0c1facf5ca73994ad269fd18a88e5b8fe68551c8 (diff)
Facebook: Implement login with two-way authorization
It shows dialog that asks for verification code. User can press button to request code via SMS. Allows 3 attempts to entering correct code, then plugin disconnects. git-svn-id: http://svn.miranda-ng.org/main/trunk@16685 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'protocols')
-rw-r--r--protocols/FacebookRM/res/facebook.rc20
-rw-r--r--protocols/FacebookRM/src/client.h1
-rw-r--r--protocols/FacebookRM/src/communication.cpp95
-rw-r--r--protocols/FacebookRM/src/constants.h3
-rw-r--r--protocols/FacebookRM/src/dialogs.cpp46
-rw-r--r--protocols/FacebookRM/src/dialogs.h28
-rw-r--r--protocols/FacebookRM/src/resource.h7
-rw-r--r--protocols/FacebookRM/src/stdafx.h1
8 files changed, 176 insertions, 25 deletions
diff --git a/protocols/FacebookRM/res/facebook.rc b/protocols/FacebookRM/res/facebook.rc
index b6d0fcc0d8..fb1ed5cd1a 100644
--- a/protocols/FacebookRM/res/facebook.rc
+++ b/protocols/FacebookRM/res/facebook.rc
@@ -120,7 +120,7 @@ BEGIN
CONTROL "Automatically set 'Ignore status change' flag",IDC_SET_IGNORE_STATUS,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,17,107,271,10
CONTROL "Use bigger avatars",IDC_BIGGER_AVATARS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,17,120,271,10
- CONTROL "Prefer real names instead of nicknames",IDC_NAME_AS_NICK,
+ CONTROL "Prefer real names instead of nicknames",IDC_NAME_AS_NICK,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,17,134,271,10
END
@@ -209,6 +209,18 @@ BEGIN
CONTROL "",IDC_MESSAGES_COUNT_SPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,283,160,11,14
END
+IDD_GUARD DIALOGEX 0, 0, 193, 94
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Facebook Login Approval"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ LTEXT "Your security settings requires to input a security code to access your account from unknown browsers.\n\nYou can get the code via Facebook application on your phone or click button below to receive it via SMS.", IDC_STATIC, 7, 7, 179, 40
+ PUSHBUTTON "Send SMS", IDSMS, 7, 53, 59, 15
+ EDITTEXT IDC_TEXT, 72, 54, 114, 12, ES_AUTOHSCROLL | ES_NUMBER
+ DEFPUSHBUTTON "OK",IDOK,82,75,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,136,75,50,14
+END
+
/////////////////////////////////////////////////////////////////////////////
//
@@ -296,6 +308,12 @@ BEGIN
TOPMARGIN, 7
BOTTOMMARGIN, 224
END
+
+ IDD_GUARD, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ TOPMARGIN, 7
+ END
END
#endif // APSTUDIO_INVOKED
diff --git a/protocols/FacebookRM/src/client.h b/protocols/FacebookRM/src/client.h
index f393aa0a67..3aedecceac 100644
--- a/protocols/FacebookRM/src/client.h
+++ b/protocols/FacebookRM/src/client.h
@@ -167,6 +167,7 @@ public:
bool login(const char *username, const char *password);
bool logout();
+ bool sms_code(const char *fb_dtsg);
const std::string & get_username() const;
diff --git a/protocols/FacebookRM/src/communication.cpp b/protocols/FacebookRM/src/communication.cpp
index 179d9ee273..602c7892e1 100644
--- a/protocols/FacebookRM/src/communication.cpp
+++ b/protocols/FacebookRM/src/communication.cpp
@@ -276,6 +276,7 @@ std::string facebook_client::choose_server(RequestType request_type)
// case REQUEST_FRIENDSHIP:
// case REQUEST_UNREAD_THREADS:
// case REQUEST_ON_THIS_DAY:
+ // case REQUEST_LOGIN_SMS:
default:
return FACEBOOK_SERVER_REGULAR;
}
@@ -526,6 +527,11 @@ std::string facebook_client::choose_action(RequestType request_type, std::string
return action;
}
+ case REQUEST_LOGIN_SMS:
+ {
+ return "/ajax/login/approvals/send_sms?dpr=1";
+ }
+
default:
return "/?_fb_noscript=1";
}
@@ -823,17 +829,8 @@ bool facebook_client::login(const char *username, const char *password)
return handle_error("login", FORCE_QUIT);
}
- // Check whether some Facebook things are required
- if (location.find("help.php") != std::string::npos)
- {
- client_notify(TranslateT("Login error: Some Facebook things are required."));
- parent->debugLogA("!!! Login error: Some Facebook things are required.");
- // return handle_error("login", FORCE_QUIT);
- }
-
- // Check whether setting Machine name is required
- if (location.find("/checkpoint/") != std::string::npos)
- {
+ // Check whether login checks are required
+ if (location.find("/checkpoint/") != std::string::npos) {
resp = flap(REQUEST_SETUP_MACHINE, NULL, NULL);
if (resp.data.find("login_approvals_no_phones") != std::string::npos) {
@@ -842,9 +839,48 @@ bool facebook_client::login(const char *username, const char *password)
return handle_error("login", FORCE_QUIT);
}
- std::string inner_data;
if (resp.data.find("name=\"submit[Continue]\"") != std::string::npos) {
+ std::string inner_data;
+
+ int attempt = 0;
+ // Check if we need to put approval code (aka "two-factor auth")
+ while (resp.data.find("id=\"approvals_code\"") != std::string::npos) {
+ parent->debugLogA(" Login info: Approval code required.");
+
+ std::string fb_dtsg = utils::url::encode(utils::text::source_get_value(&resp.data, 3, "name=\"fb_dtsg\"", "value=\"", "\""));
+
+ CFacebookGuardDialog guardDialog(parent, fb_dtsg.c_str());
+ if (guardDialog.DoModal() != DIALOG_RESULT_OK) {
+ parent->SetStatus(ID_STATUS_OFFLINE);
+ return false;
+ }
+
+ // We need verification code from user (he can get it via Facebook application on phone or by requesting code via SMS)
+ std::string givenCode = guardDialog.GetCode();
+
+ inner_data = "submit[Continue]=Continue";
+ inner_data += "&nh=" + utils::text::source_get_value(&resp.data, 3, "name=\"nh\"", "value=\"", "\"");
+ inner_data += "&fb_dtsg=" + fb_dtsg;
+ inner_data += "&approvals_code=" + givenCode;
+ resp = flap(REQUEST_SETUP_MACHINE, &inner_data);
+ if (resp.data.find("id=\"approvals_code\"") != std::string::npos) {
+ // We get no error message if we put wrong code. Facebook just shows same form again.
+ if (++attempt >= 3) {
+ client_notify(TranslateT("You entered too many invalid verification codes. Plugin will disconnect."));
+ parent->debugLogA("!!! Login error: Too many invalid attempts to verification code.");
+ return handle_error("login", FORCE_QUIT);
+ }
+ else {
+ client_notify(TranslateT("You entered wrong verification code. Try it again."));
+ }
+ }
+ else {
+ // After successfull verification is showed different page - classic form to save device (as handled at the bottom)
+ break;
+ }
+ }
+
// Check if we need to approve also last unapproved device
if (resp.data.find("name=\"name_action_selected\"") == std::string::npos) {
// 1) Continue
@@ -876,21 +912,13 @@ bool facebook_client::login(const char *username, const char *password)
inner_data += "&name_action_selected=save_device"; // Save device - or "dont_save"
resp = flap(REQUEST_SETUP_MACHINE, &inner_data);
}
-
+
// Save this actual device
inner_data = "submit[Continue]=Continue";
inner_data += "&nh=" + utils::text::source_get_value(&resp.data, 3, "name=\"nh\"", "value=\"", "\"");
inner_data += "&fb_dtsg=" + utils::url::encode(utils::text::source_get_value(&resp.data, 3, "name=\"fb_dtsg\"", "value=\"", "\""));
inner_data += "&name_action_selected=save_device"; // Save device - or "dont_save"
resp = flap(REQUEST_SETUP_MACHINE, &inner_data);
-
- }
- else if (resp.data.find("name=\"submit[OK]\"") != std::string::npos) {
- // TODO: not sure this branch could happen anymore
- inner_data = "submit[OK]=OK";
- inner_data += "&nh=" + utils::text::source_get_value(&resp.data, 3, "name=\"nh\"", "value=\"", "\"");
- inner_data += "&fb_dtsg=" + utils::url::encode(utils::text::source_get_value(&resp.data, 3, "name=\"fb_dtsg\"", "value=\"", "\""));
- resp = flap(REQUEST_SETUP_MACHINE, &inner_data);
}
else if (resp.data.find("name=\"submit[Get Started]\"") != std::string::npos) {
if (!parent->getBool(FACEBOOK_KEY_TRIED_DELETING_DEVICE_ID)) {
@@ -1599,3 +1627,28 @@ bool facebook_client::save_url(const std::string &url, const std::tstring &filen
return ret;
}
+
+bool facebook_client::sms_code(const char *fb_dtsg)
+{
+ std::string inner_data = "method_requested=sms_requested";
+ inner_data += "&current_time=" + (utils::time::unix_timestamp() + ".000");
+ inner_data += "&__a=1";
+ inner_data += "&__user=0";
+ inner_data += "&__dyn=" + __dyn();
+ inner_data += "&__req=" + __req();
+ inner_data += "&__be=0";
+ inner_data += "&__pc=EXP1:DEFAULT";
+ inner_data += "&fb_dtsg=" + std::string(fb_dtsg);
+ inner_data += "&ttstamp=" + ttstamp_;
+ inner_data += "&__rev=" + __rev();
+ http::response resp = flap(REQUEST_LOGIN_SMS, &inner_data);
+
+ if (resp.data.find("\"is_valid\":true", 0) == std::string::npos) {
+ // Code wasn't send
+ client_notify(TranslateT("Error occurred when requesting verification SMS code."));
+ return false;
+ }
+
+ parent->NotifyEvent(parent->m_tszUserName, TranslateT("Verification SMS code was sent to your mobile phone."), NULL, FACEBOOK_EVENT_OTHER);
+ return true;
+} \ No newline at end of file
diff --git a/protocols/FacebookRM/src/constants.h b/protocols/FacebookRM/src/constants.h
index 0f55b97a98..aa25defd68 100644
--- a/protocols/FacebookRM/src/constants.h
+++ b/protocols/FacebookRM/src/constants.h
@@ -128,7 +128,8 @@ enum RequestType {
REQUEST_VISIBILITY, // setting chat visibility
REQUEST_IDENTITY_SWITCH, // changing identity to post status for pages
REQUEST_CAPTCHA_REFRESH, // refreshing captcha dialog (changing captcha type)
-
+ REQUEST_LOGIN_SMS, // request to receive login code via SMS
+
REQUEST_FEEDS, // getting feeds
REQUEST_NOTIFICATIONS, // getting notifications
REQUEST_LOAD_FRIENDSHIPS, // getting friendship requests
diff --git a/protocols/FacebookRM/src/dialogs.cpp b/protocols/FacebookRM/src/dialogs.cpp
index 2b8ec51728..9ce23811a7 100644
--- a/protocols/FacebookRM/src/dialogs.cpp
+++ b/protocols/FacebookRM/src/dialogs.cpp
@@ -635,3 +635,49 @@ INT_PTR CALLBACK FBOptionsMessagingProc(HWND hwnd, UINT message, WPARAM wparam,
return FALSE;
}
+
+/////////////////////////////////////////////////////////////////////////////////
+
+CFacebookGuardDialog::CFacebookGuardDialog(FacebookProto *proto, const char *fb_dtsg)
+ : CFacebookDlgBase(proto, IDD_GUARD, false),
+ m_ok(this, IDOK),
+ m_sms(this, IDSMS),
+ m_text(this, IDC_TEXT),
+ m_fb_dtsg(fb_dtsg)
+{
+ memset(m_code, 0, sizeof(m_code));
+ m_ok.OnClick = Callback(this, &CFacebookGuardDialog::OnOk);
+ m_sms.OnClick = Callback(this, &CFacebookGuardDialog::OnSms);
+}
+
+void CFacebookGuardDialog::OnInitDialog()
+{
+ SendMessage(m_hwnd, WM_SETICON, ICON_BIG, (LPARAM)IcoLib_GetIconByHandle(GetIconHandle("facebook"), TRUE));
+ SendMessage(m_hwnd, WM_SETICON, ICON_SMALL, (LPARAM)IcoLib_GetIconByHandle(GetIconHandle("facebook")));
+
+ SendMessage(m_text.GetHwnd(), EM_LIMITTEXT, 6, 0);
+
+ Utils_RestoreWindowPosition(m_hwnd, NULL, m_proto->m_szModuleName, "GuardWindow");
+}
+
+void CFacebookGuardDialog::OnOk(CCtrlButton*)
+{
+ mir_strncpy(m_code, ptrA(m_text.GetTextA()), _countof(m_code));
+ EndDialog(m_hwnd, DIALOG_RESULT_OK);
+}
+
+void CFacebookGuardDialog::OnSms(CCtrlButton *btn)
+{
+ btn->Disable();
+ m_proto->facy.sms_code(m_fb_dtsg);
+}
+
+void CFacebookGuardDialog::OnClose()
+{
+ Utils_SaveWindowPosition(m_hwnd, NULL, m_proto->m_szModuleName, "GuardWindow");
+}
+
+const char* CFacebookGuardDialog::GetCode()
+{
+ return m_code;
+}
diff --git a/protocols/FacebookRM/src/dialogs.h b/protocols/FacebookRM/src/dialogs.h
index 41c5e8006b..ee7d4da144 100644
--- a/protocols/FacebookRM/src/dialogs.h
+++ b/protocols/FacebookRM/src/dialogs.h
@@ -28,3 +28,31 @@ INT_PTR CALLBACK FBOptionsProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lp
INT_PTR CALLBACK FBOptionsMessagingProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);
INT_PTR CALLBACK FBOptionsEventsProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);
INT_PTR CALLBACK FBOptionsStatusesProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);
+
+/////////////////////////////////////////////////////////////////////////////////
+
+typedef CProtoDlgBase<FacebookProto> CFacebookDlgBase;
+
+#define DIALOG_RESULT_OK 1
+
+class CFacebookGuardDialog : public CFacebookDlgBase
+{
+private:
+ const char *m_fb_dtsg;
+ char m_code[7];
+
+ CCtrlEdit m_text;
+ CCtrlButton m_ok;
+ CCtrlButton m_sms;
+
+protected:
+ void OnInitDialog();
+ void OnOk(CCtrlButton*);
+ void OnSms(CCtrlButton*);
+ void OnClose();
+
+public:
+ CFacebookGuardDialog(FacebookProto *proto, const char *fb_dtsg);
+
+ const char *GetCode();
+};
diff --git a/protocols/FacebookRM/src/resource.h b/protocols/FacebookRM/src/resource.h
index 0c89884724..ba66e994a0 100644
--- a/protocols/FacebookRM/src/resource.h
+++ b/protocols/FacebookRM/src/resource.h
@@ -19,6 +19,7 @@
#define IDI_CONVERSATION 131
#define IDI_READ 132
#define IDI_KEYS 133
+#define IDD_GUARD 134
#define IDC_UN 1001
#define IDC_PW 1002
#define IDC_NEWACCOUNTLINK 1003
@@ -65,14 +66,16 @@
#define IDC_INSTRUCTION 1214
#define IDC_FRAME1 1215
#define IDC_FRAME2 1216
+#define IDC_TEXT 1217
+#define IDC_SEND_SMS 1218
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 134
+#define _APS_NEXT_RESOURCE_VALUE 135
#define _APS_NEXT_COMMAND_VALUE 40001
-#define _APS_NEXT_CONTROL_VALUE 1218
+#define _APS_NEXT_CONTROL_VALUE 1219
#define _APS_NEXT_SYMED_VALUE 134
#endif
#endif
diff --git a/protocols/FacebookRM/src/stdafx.h b/protocols/FacebookRM/src/stdafx.h
index 23868df198..1549e7ccf9 100644
--- a/protocols/FacebookRM/src/stdafx.h
+++ b/protocols/FacebookRM/src/stdafx.h
@@ -61,6 +61,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <m_imgsrvc.h>
#include <m_http.h>
#include <m_messagestate.h>
+#include <m_gui.h>
class FacebookProto;