diff options
author | George Hazan <ghazan@miranda.im> | 2019-10-15 13:06:52 +0300 |
---|---|---|
committer | George Hazan <ghazan@miranda.im> | 2019-10-15 13:06:52 +0300 |
commit | 71c1ad117340f089d4820bf7c7bddce20a5e113a (patch) | |
tree | fb53900b4db14e958d3445c8ebd634073835d6f6 | |
parent | fb3fad1e6519b029cd06e7c7113fc948aaef6770 (diff) |
WhatsAppWeb: session restoration code
-rw-r--r-- | protocols/WhatsAppWeb/src/proto.h | 6 | ||||
-rw-r--r-- | protocols/WhatsAppWeb/src/server.cpp | 61 | ||||
-rw-r--r-- | protocols/WhatsAppWeb/src/stdafx.h | 1 |
3 files changed, 68 insertions, 0 deletions
diff --git a/protocols/WhatsAppWeb/src/proto.h b/protocols/WhatsAppWeb/src/proto.h index 06f8c7609f..7f8cff994a 100644 --- a/protocols/WhatsAppWeb/src/proto.h +++ b/protocols/WhatsAppWeb/src/proto.h @@ -40,6 +40,8 @@ class WhatsAppProto : public PROTO<WhatsAppProto> CMStringA m_szJid, m_szClientId, m_szClientToken; CMStringW m_tszAvatarFolder; + MBinBuffer mac_key, enc_key; + EVP_PKEY *m_pKeys; // private & public keys bool ShowQrCode(const CMStringA &ref); @@ -62,11 +64,15 @@ class WhatsAppProto : public PROTO<WhatsAppProto> void StartSession(void); void ShutdownSession(void); + void ProcessChallenge(const CMStringA &szChallenge); + /// Request handlers /////////////////////////////////////////////////////////////////// + void OnRestoreSession(const JSONNode &node); void OnStartSession(const JSONNode &node); void ProcessPacket(const JSONNode &node); + void ProcessCmd(const JSONNode &node); void ProcessConn(const JSONNode &node); /// Avatars //////////////////////////////////////////////////////////////////////////// diff --git a/protocols/WhatsAppWeb/src/server.cpp b/protocols/WhatsAppWeb/src/server.cpp index 3a682e00fa..be9fc55200 100644 --- a/protocols/WhatsAppWeb/src/server.cpp +++ b/protocols/WhatsAppWeb/src/server.cpp @@ -199,10 +199,57 @@ void WhatsAppProto::OnLoggedOut(void) setAllContactStatuses(ID_STATUS_OFFLINE, false); } +////////////////////////////////////////////////////////////////////////////////////// + +void WhatsAppProto::ProcessChallenge(const CMStringA &szChallenge) +{ + if (mac_key.isEmpty()) { + ShutdownSession(); + return; + } + + size_t cbLen; + void *pChallenge = mir_base64_decode(szChallenge, &cbLen); + + BYTE digest[32]; + unsigned cbResult = sizeof(digest); + HMAC(EVP_sha256(), mac_key.data(), mac_key.length(), (BYTE*)pChallenge, cbLen, digest, &cbResult); + + ptrA szServer(getStringA(DBKEY_SERVER_TOKEN)); + CMStringA payload(FORMAT, "[\"admin\",\"challenge\",\"%s\",\"%s\",\"%s\"]", + ptrA(mir_base64_encode(digest, cbResult)).get(), szServer.get(), m_szClientId.c_str()); + WSSend(payload); +} + +////////////////////////////////////////////////////////////////////////////////////// + void WhatsAppProto::RestoreSession() { + ptrA szClient(getStringA(DBKEY_CLIENT_TOKEN)), szServer(getStringA(DBKEY_SERVER_TOKEN)); + if (szClient == nullptr || szServer == nullptr) { + ShutdownSession(); + return; + } + + CMStringA payload(FORMAT, "[\"admin\",\"login\",\"%s\",\"%s\",\"%s\",\"takeover\"]", szClient.get(), szServer.get(), m_szClientId.c_str()); + WSSend(payload, &WhatsAppProto::OnRestoreSession); +} + +void WhatsAppProto::OnRestoreSession(const JSONNode &root) +{ + int status = root["status"].as_int(); + if (status != 200) { + debugLogA("Attmept to restore session failed with error %d", status); + delSetting(DBKEY_CLIENT_TOKEN); + delSetting(DBKEY_SERVER_TOKEN); + + ShutdownSession(); + return; + } } +////////////////////////////////////////////////////////////////////////////////////// + void WhatsAppProto::ShutdownSession() { if (m_bTerminated) @@ -217,6 +264,8 @@ void WhatsAppProto::ShutdownSession() OnLoggedOut(); } +////////////////////////////////////////////////////////////////////////////////////// + void WhatsAppProto::StartSession() { CMStringA payload(FORMAT, "[\"admin\",\"init\",[0,3,4940],[\"Windows\",\"Chrome\",\"10\"],\"%s\",true]", m_szClientId.c_str()); @@ -400,6 +449,18 @@ void WhatsAppProto::ProcessPacket(const JSONNode &root) if (szType == "Conn") ProcessConn(content); + else if (szType == "Cmd") + ProcessCmd(content); +} + +void WhatsAppProto::ProcessCmd(const JSONNode &root) +{ + CMStringW wszType(root["type"].as_mstring()); + if (wszType == L"challenge") { + CMStringA szChallenge(root["challenge"].as_mstring()); + if (!szChallenge.IsEmpty()) + ProcessChallenge(szChallenge); + } } void WhatsAppProto::ProcessConn(const JSONNode &root) diff --git a/protocols/WhatsAppWeb/src/stdafx.h b/protocols/WhatsAppWeb/src/stdafx.h index 171e384674..82f1e715c0 100644 --- a/protocols/WhatsAppWeb/src/stdafx.h +++ b/protocols/WhatsAppWeb/src/stdafx.h @@ -43,6 +43,7 @@ Copyright © 2019 George Hazan #include <m_gui.h> #include <openssl/evp.h> +#include <openssl/hmac.h> #include "../../libs/libqrencode/src/qrencode.h" #include "../../libs/libsignal/src/curve.h" |