summaryrefslogtreecommitdiff
path: root/protocols/WhatsApp/src/WhatsAPI++/WALogin.cpp
diff options
context:
space:
mode:
authorGeorge Hazan <george.hazan@gmail.com>2015-01-24 16:35:14 +0000
committerGeorge Hazan <george.hazan@gmail.com>2015-01-24 16:35:14 +0000
commitc47ca004ba979d23a86211393c9e35deadd66c46 (patch)
treece49a57e87bf5caac81d2d54a590e3aea3d61ea3 /protocols/WhatsApp/src/WhatsAPI++/WALogin.cpp
parent126f606ea6a845d914e3ff074dc725443bb57bf0 (diff)
adaptation of WhatsApp for protocol version 1.5/2.0
git-svn-id: http://svn.miranda-ng.org/main/trunk@11898 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'protocols/WhatsApp/src/WhatsAPI++/WALogin.cpp')
-rw-r--r--protocols/WhatsApp/src/WhatsAPI++/WALogin.cpp180
1 files changed, 71 insertions, 109 deletions
diff --git a/protocols/WhatsApp/src/WhatsAPI++/WALogin.cpp b/protocols/WhatsApp/src/WhatsAPI++/WALogin.cpp
index 311edc70a5..459cc7efe9 100644
--- a/protocols/WhatsApp/src/WhatsAPI++/WALogin.cpp
+++ b/protocols/WhatsApp/src/WhatsAPI++/WALogin.cpp
@@ -7,7 +7,6 @@
#include "WALogin.h"
#include "ByteArray.h"
-//#include "ApplicationData.h"
#include "ProtocolTreeNode.h"
#include "WAException.h"
#include <iostream>
@@ -56,86 +55,26 @@ std::vector<unsigned char>* WALogin::login(const std::vector<unsigned char>& aut
return this->readFeaturesUntilChallengeOrSuccess();
}
-BinTreeNodeReader* WALogin::getTreeNodeReader() {
+BinTreeNodeReader* WALogin::getTreeNodeReader()
+{
return this->inn;
}
-BinTreeNodeWriter* WALogin::getTreeNodeWriter() {
+BinTreeNodeWriter* WALogin::getTreeNodeWriter()
+{
return this->out;
}
-std::string WALogin::getResponse(const std::string& challenge) {
- unsigned char md5_buffer[16];
-
- size_t i = challenge.find(WALogin::NONCE_KEY);
- i += WALogin::NONCE_KEY.length();
-
- size_t j = challenge.find('"', i);
- std::string nonce = challenge.substr(i,j-i);
-
- std::string cnonce = str(absLong(randLong()), 36);
- _LOGDATA("cnonce = %s", cnonce.c_str());
- std::string nc = "00000001";
- std::string cinfo(this->user + ":" + this->domain + ":" + this->password);
-
- _LOGDATA("cinfo = %s", cinfo.c_str());
-
- ByteArrayOutputStream bos;
- bos.write(utils::md5string(cinfo, md5_buffer), SIZEOF(md5_buffer));
- bos.write(58);
- bos.write(nonce);
- bos.write(58);
- bos.write(cnonce);
- // bos.print();
-
- std::string digest_uri = "xmpp/" + this->domain;
- std::vector<unsigned char>* A1 = bos.toByteArray();
- std::string A2 = "AUTHENTICATE:" + digest_uri;
- std::string KD = bytesToHex(utils::md5string(&A1->front(), (int)A1->size(), md5_buffer), SIZEOF(md5_buffer));
- KD += + ":" + nonce + ":" + nc + ":" + cnonce + ":auth:" + bytesToHex(utils::md5string(A2, md5_buffer), SIZEOF(md5_buffer));
-
- _LOGDATA("KD = %s", KD.c_str());
-
- std::string response = bytesToHex(utils::md5string(KD, md5_buffer), SIZEOF(md5_buffer));
-
- _LOGDATA("response = %s", response.c_str());
-
- std::string bigger_response;
- bigger_response.append("realm=\"");
- bigger_response.append(this->domain);
- bigger_response.append("\",response=");
- bigger_response.append(response);
- bigger_response.append(",nonce=\"");
- bigger_response.append(nonce);
- bigger_response.append("\",digest-uri=\"");
- bigger_response.append(digest_uri);
- bigger_response.append("\",cnonce=\"");
- bigger_response.append(cnonce);
- bigger_response.append("\",qop=auth");
- bigger_response.append(",username=\"");
- bigger_response.append(this->user);
- bigger_response.append("\",nc=");
- bigger_response.append(nc);
-
- _LOGDATA("biggerresponse = %s", bigger_response.c_str());
-
- delete A1;
-
- return bigger_response;
-}
-
void WALogin::sendResponse(const std::vector<unsigned char>& challengeData) {
std::vector<unsigned char>* authBlob = this->getAuthBlob(challengeData);
- // std::string response = this->getResponse(challengeData);
- std::map<string, string> *attributes = new std::map<string,string>();
- (*attributes)["xmlns"] = "urn:ietf:params:xml:ns:xmpp-sasl";
- ProtocolTreeNode node("response", attributes, authBlob);
+ ProtocolTreeNode node("response", NULL, authBlob);
this->out->write(&node);
}
-void WALogin::sendFeatures() {
+void WALogin::sendFeatures()
+{
ProtocolTreeNode* child = new ProtocolTreeNode("receipt_acks", NULL);
std::vector<ProtocolTreeNode*>* children = new std::vector<ProtocolTreeNode*>();
children->push_back(child);
@@ -151,47 +90,47 @@ void WALogin::sendFeatures() {
this->out->write(&node, true);
}
-void WALogin::sendAuth(const std::vector<unsigned char>& existingChallenge) {
+void WALogin::sendAuth(const std::vector<unsigned char>& existingChallenge)
+{
std::vector<unsigned char>* data = NULL;
if (!existingChallenge.empty()) {
data = this->getAuthBlob(existingChallenge);
}
std::map<string, string>* attributes = new std::map<string, string>();
- (*attributes)["xmlns"] = "urn:ietf:params:xml:ns:xmpp-sasl";
- (*attributes)["mechanism"] = "WAUTH-1";
+ (*attributes)["mechanism"] = "WAUTH-2";
(*attributes)["user"] = this->user;
ProtocolTreeNode node("auth", attributes, data, NULL);
this->out->write(&node, true);
}
-std::vector<unsigned char>* WALogin::getAuthBlob(const std::vector<unsigned char>& nonce) {
- unsigned char out[20];
+std::vector<unsigned char>* WALogin::getAuthBlob(const std::vector<unsigned char>& nonce)
+{
+ unsigned char out[4*20];
KeyStream::keyFromPasswordAndNonce(this->password, nonce, out);
if (this->connection->inputKey != NULL)
delete this->connection->inputKey;
- this->connection->inputKey = new KeyStream(out, 20);
+ this->connection->inputKey = new KeyStream(out + 40, out + 60);
if (this->outputKey != NULL)
delete this->outputKey;
+ this->outputKey = new KeyStream(out, out + 20);
- this->outputKey = new KeyStream(out, 20);
std::vector<unsigned char>* list = new std::vector<unsigned char>(0);
for (int i = 0; i < 4; i++)
list->push_back(0);
list->insert(list->end(), this->user.begin(), this->user.end());
list->insert(list->end(), nonce.begin(), nonce.end());
- std::string strTime = Utilities::intToStr( time(NULL));
- list->insert(list->end(), strTime.begin(), strTime.end());
this->outputKey->encodeMessage(&((*list)[0]), 0, 4, (int)list->size() - 4);
return list;
}
-std::vector<unsigned char>* WALogin::readFeaturesUntilChallengeOrSuccess() {
+std::vector<unsigned char>* WALogin::readFeaturesUntilChallengeOrSuccess()
+{
ProtocolTreeNode* root;
while ((root = this->inn->nextTree()) != NULL) {
if (ProtocolTreeNode::tagEquals(root, "stream:features")) {
@@ -221,7 +160,8 @@ std::vector<unsigned char>* WALogin::readFeaturesUntilChallengeOrSuccess() {
throw WAException("fell out of loop in readFeaturesAndChallenge", WAException::CORRUPT_STREAM_EX, 0);
}
-void WALogin::parseSuccessNode(ProtocolTreeNode* node) {
+void WALogin::parseSuccessNode(ProtocolTreeNode* node)
+{
const string &expiration = node->getAttributeValue("expiration");
if (!expiration.empty()) {
this->expire_date = atol(expiration.c_str());
@@ -242,7 +182,8 @@ void WALogin::parseSuccessNode(ProtocolTreeNode* node) {
this->connection->outputKey = this->outputKey;
}
-std::vector<unsigned char> WALogin::readSuccess() {
+std::vector<unsigned char> WALogin::readSuccess()
+{
ProtocolTreeNode* node = this->inn->nextTree();
if (ProtocolTreeNode::tagEquals(node, "failure")) {
@@ -271,58 +212,79 @@ std::vector<unsigned char> WALogin::readSuccess() {
return data;
}
-WALogin::~WALogin() {
-}
+WALogin::~WALogin()
+{}
-KeyStream::KeyStream(unsigned char* key, size_t keyLength) {
- unsigned char drop[256];
+KeyStream::KeyStream(unsigned char* _key, unsigned char* _keyMac) :
+ seq(0)
+{
+ memcpy(key, _key, 20);
+ memcpy(keyMac, _keyMac, 20);
- this->key = new unsigned char[keyLength];
- memcpy(this->key, key, keyLength);
- this->keyLength = (int)keyLength;
+ RC4_set_key(&this->rc4, 20, this->key);
- RC4_set_key(&this->rc4, this->keyLength, this->key);
- RC4(&this->rc4, 256, drop, drop);
- HMAC_CTX_init(&this->hmac);
+ unsigned char drop[768];
+ RC4(&this->rc4, sizeof(drop), drop, drop);
+
+ HMAC_CTX_init(&hmac);
}
-KeyStream::~KeyStream() {
- delete [] this->key;
- HMAC_CTX_cleanup(&this->hmac);
+KeyStream::~KeyStream()
+{
+ HMAC_CTX_cleanup(&hmac);
}
-void KeyStream::keyFromPasswordAndNonce(const std::string& pass, const std::vector<unsigned char>& nonce, unsigned char *out) {
- PKCS5_PBKDF2_HMAC_SHA1(pass.data(), (int)pass.size(), nonce.data(), (int)nonce.size(), 16, 20, out);
+void KeyStream::keyFromPasswordAndNonce(const std::string& pass, const std::vector<unsigned char>& nonce, unsigned char *out)
+{
+ size_t cbSize = nonce.size();
+
+ uint8_t *pNonce = (uint8_t*)_alloca(cbSize + 1);
+ memcpy(pNonce, nonce.data(), cbSize);
+
+ for (int i = 0; i < 4; i++) {
+ pNonce[cbSize] = i + 1;
+ PKCS5_PBKDF2_HMAC_SHA1(pass.data(), (int)pass.size(), pNonce, (int)cbSize+1, 2, 20, out + i*20);
+ }
}
-void KeyStream::decodeMessage(unsigned char* buffer, int macOffset, int offset, const int length) {
+void KeyStream::decodeMessage(unsigned char* buffer, int macOffset, int offset, const int length)
+{
unsigned char digest[20];
this->hmacsha1(buffer + offset, length, digest);
- for (int i = 0; i < 4; i++) {
- if (buffer[macOffset + i] != digest[i]) {
- throw WAException("invalid MAC", WAException::CORRUPT_STREAM_EX, 0);
- }
- }
- unsigned char* out = new unsigned char[length];
+ if (memcmp(&buffer[macOffset], digest, 4))
+ throw WAException("invalid MAC", WAException::CORRUPT_STREAM_EX, 0);
+
+ unsigned char* out = (unsigned char*)_alloca(length);
RC4(&this->rc4, length, buffer + offset, out);
memcpy(buffer + offset, out, length);
- delete[] out;
}
-void KeyStream::encodeMessage(unsigned char* buffer, int macOffset, int offset, const int length) {
- unsigned char* out = new unsigned char[length];
+void KeyStream::encodeMessage(unsigned char* buffer, int macOffset, int offset, const int length)
+{
+ unsigned char* out = (unsigned char*)_alloca(length);
RC4(&this->rc4, length, buffer + offset, out);
memcpy(buffer + offset, out, length);
- delete[] out;
unsigned char digest[20];
this->hmacsha1(buffer + offset, length, digest);
-
memcpy(buffer + macOffset, digest, 4);
}
-void KeyStream::hmacsha1(unsigned char* text, int textLength, unsigned char *out) {
+void KeyStream::hmacsha1(unsigned char* text, int textLength, unsigned char *out)
+{
+ HMAC_Init(&hmac, this->keyMac, 20, EVP_sha1());
+ HMAC_Update(&hmac, text, textLength);
+
+ unsigned char hmacInt[4];
+ hmacInt[0] = (this->seq >> 24);
+ hmacInt[1] = (this->seq >> 16);
+ hmacInt[2] = (this->seq >> 8);
+ hmacInt[3] = (this->seq);
+ HMAC_Update(&hmac, hmacInt, sizeof(hmacInt));
+
unsigned int mdLength;
- HMAC(EVP_sha1(), this->key, this->keyLength, text, textLength, out, &mdLength);
+ HMAC_Final(&hmac, out, &mdLength);
+
+ this->seq++;
}