From ccbbf2c0fc0978ecdca89258e045b71327235079 Mon Sep 17 00:00:00 2001 From: Prasenjit Kumar Shaw Date: Sat, 20 Jul 2019 23:43:26 +0530 Subject: [PATCH] Add method to fetch sync Master Key and upload device name --- src/lib/CMakeLists.txt | 1 + src/lib/preferences/syncoptions.cpp | 2 +- src/lib/sync/fxalogin.cpp | 1 - src/lib/sync/synccrypto.cpp | 157 ++++++++++++ src/lib/sync/synccrypto.h | 9 + src/lib/sync/syncmanager.cpp | 261 ++++++++++++++++---- src/lib/sync/syncmanager.h | 23 +- src/lib/sync/syncrequest.cpp | 56 ----- src/lib/sync/syncutils.cpp | 40 +++ src/lib/sync/{syncrequest.h => syncutils.h} | 28 +-- 10 files changed, 445 insertions(+), 133 deletions(-) delete mode 100644 src/lib/sync/syncrequest.cpp create mode 100644 src/lib/sync/syncutils.cpp rename src/lib/sync/{syncrequest.h => syncutils.h} (61%) diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index 540eccd89..cca3883b0 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -223,6 +223,7 @@ set(SRCS ${SRCS} sync/synccrypto.cpp sync/hawk/hawk.cpp sync/syncmanager.cpp + sync/syncutils.cpp tabwidget/combotabbar.cpp tabwidget/tabbar.cpp tabwidget/tabicon.cpp diff --git a/src/lib/preferences/syncoptions.cpp b/src/lib/preferences/syncoptions.cpp index 363a54f98..a31b053ce 100644 --- a/src/lib/preferences/syncoptions.cpp +++ b/src/lib/preferences/syncoptions.cpp @@ -34,7 +34,7 @@ SyncOptions::SyncOptions(QWidget* parent) loginPage = new FxALoginPage(this); ui->fxaloginframe->addWidget(loginPage); - connect(ui->btnSyncNow, &QPushButton::clicked, mApp->syncManager(), &SyncManager::sync); + connect(ui->btnSyncNow, &QPushButton::clicked, mApp->syncManager(), &SyncManager::startSync); } SyncOptions::~SyncOptions() diff --git a/src/lib/sync/fxalogin.cpp b/src/lib/sync/fxalogin.cpp index 6cf29bd98..37497714f 100644 --- a/src/lib/sync/fxalogin.cpp +++ b/src/lib/sync/fxalogin.cpp @@ -100,7 +100,6 @@ void FxALoginPage::parseMessage(QJsonObject *msg) settings.setValue(QSL("KeyFetchToken"), key_fetch_token); settings.setValue(QSL("UnwrapBKey"), unwrap_kb); settings.endGroup(); - // derive the various tokens and save into settings right here and instead of synccreds, create a user_data object } } diff --git a/src/lib/sync/synccrypto.cpp b/src/lib/sync/synccrypto.cpp index 61cfdbade..e0b234beb 100644 --- a/src/lib/sync/synccrypto.cpp +++ b/src/lib/sync/synccrypto.cpp @@ -16,6 +16,7 @@ * along with this program. If not, see . * ============================================================ */ #include "synccrypto.h" +#include "syncutils.h" #include #include @@ -26,6 +27,7 @@ #include #include #include +#include #include @@ -153,3 +155,158 @@ RSAKeyPair *generateRSAKeyPair() return keyPair; } + +QByteArray *createBowserIdAssertion(QByteArray *certificate, QByteArray *audience, qint64 seconds, RSAKeyPair *keyPair) +{ + QByteArray *assertion = new QByteArray(); + mpz_t signature; + + QString tempHeader("{\"alg\": \"RS256\"}"); + QByteArray header = QByteArray(tempHeader.toUtf8()); + header.toBase64(); + + qint64 expiry = QDateTime::currentMSecsSinceEpoch() + seconds * 1000; + QString tempBody = QString("{\"exp\": %1, \"aud\": \"%2\"}").arg(expiry).arg(audience->data()); + QByteArray body = QByteArray(tempBody.toUtf8()); + body.toBase64(); + + QByteArray toSign = QByteArray((QString("%1.%2").arg(header.data()).arg(header.data())).toUtf8()); + u_char *digest = new u_char[SHA256_DIGEST_SIZE]; + sha256_ctx *ctx = new sha256_ctx; + sha256_init(ctx); + sha256_update(ctx, toSign.size(), (u_char *)(toSign.data())); + sha256_digest(ctx, SHA256_DIGEST_SIZE, digest); + delete ctx; + + mpz_init(signature); + int success = nettle_rsa_sha256_sign_digest_tr(&(keyPair->m_publicKey), &(keyPair->m_privateKey), nullptr, generateRandomBytes, digest, signature); + Q_ASSERT(success); + + size_t expectedSize = (mpz_sizeinbase(signature, 2) + 7) / 8; + size_t count; + u_char *sig = new u_char[expectedSize]; + mpz_export(sig, &count, 1, sizeof(quint8), 0, 0, signature); + Q_ASSERT(count == expectedSize); + + QByteArray sigBase64 = QByteArray::fromRawData((const char *)sig, count); + sigBase64.toBase64(); + + assertion->append((QString("%1~%2.%3.%4").arg(certificate->data()).arg(header.data()).arg(body.data()).arg(sigBase64.data())).toUtf8()); + + mpz_clear(signature); + delete digest; + delete sig; + return assertion; +} + + +QByteArray *xorQByteArray(QByteArray *a, QByteArray *b, size_t len) +{ + QByteArray *xored = new QByteArray(); + + char *aData = a->data(); + char *bData = b->data(); + char *xorData = new char[len]; + + for(int i = 0; i < len; ++i) { + xorData[i] = aData[i] ^ bData[i]; + } + xored->append(xorData, len); + + return xored; +} + +bool deriveMasterKey(QByteArray *bundleHex, QByteArray *respHMACKey, QByteArray *respXORKey, QByteArray *unwrapKb, QByteArray *ka, QByteArray *kb) +{ + bool returnVal = true; + QByteArray *bundle = new QByteArray(QByteArray::fromHex(bundleHex->data())); + size_t masterKeyLen = 32; + QByteArray *cipherText = new QByteArray(bundle->data()); + cipherText->chop(masterKeyLen); + QByteArray *respHMAC = new QByteArray(bundle->right(masterKeyLen).data()); + + hmac_sha256_ctx *ctx = new hmac_sha256_ctx; + hmac_sha256_set_key(ctx, respHMACKey->size(), (u_char *)respHMACKey->data()); + hmac_sha256_update(ctx, cipherText->length(), (u_char *)cipherText->data()); + u_char *out = new u_char[SHA256_DIGEST_SIZE]; + hmac_sha256_digest(ctx, SHA256_DIGEST_SIZE, out); + QByteArray *respHMAC2 = new QByteArray(QByteArray::fromRawData((const char *)out, SHA256_DIGEST_SIZE)); + + + QByteArray mac(respHMAC->data()); + QByteArray mac2(respHMAC2->data()); + qDebug() << "mac: " << mac.toHex().data() << "\ndigest:" << mac2.toHex().data(); + + if (*respHMAC == *respHMAC2) { + QByteArray *xored = xorQByteArray(cipherText, respXORKey, 2 * masterKeyLen); + ka->append(xored->data()); + ka->chop(masterKeyLen); + QByteArray *wrapKb = new QByteArray(xored->right(masterKeyLen)); + QByteArray *xored2 = xorQByteArray(unwrapKb, wrapKb, masterKeyLen); + kb->append(xored2->data()); + + delete xored; + delete wrapKb; + delete xored2; + } else { + returnVal = false; + } + + delete bundle; + delete cipherText; + delete respHMAC; + delete ctx; + + return returnVal; +} + + +void testDeriveMasterKey() +{ + bool returnVal = true; + QByteArray bundle(QByteArray::fromHex("ee5c58845c7c9412b11bbd20920c2fddd83c33c9cd2c2de2d66b222613364636fc7e59d854d599f10e212801de3a47c34333f3b838ee3471e0f285649c332bbb4c17f42a0b319bbba327d2b326ad23e937219b4de32e3ec7b3e3f740522ad6ef")); + size_t masterKeyLen = 32; + QByteArray cipherText(bundle.data()); + cipherText.chop(masterKeyLen); + QByteArray respHMAC(bundle.right(masterKeyLen).data()); + + QByteArray respHMACKey(QByteArray::fromHex("f824d2953aab9faf51a1cb65ba9e7f9e5bf91c8d8fd1ac1c8c2d31853a8a1210")); + QByteArray respXORKey(QByteArray::fromHex("ce7d7aa77859b2359932970bbe2101f2e80d01faf9191bd5ee52181d2f0b78098281ba8cff3925433a89f7c3095e0c89900a469d60790c833281c4df1a11c763")); + + QByteArray unwrapKb(QByteArray::fromHex("de6a2648b78284fcb9ffa81ba95803309cfba7af583c01a8a1a63e567234dd28")); + + hmac_sha256_ctx *ctx = new hmac_sha256_ctx; + hmac_sha256_set_key(ctx, respHMACKey.size(), (u_char *)respHMACKey.data()); + hmac_sha256_update(ctx, cipherText.length(), (u_char *)cipherText.data()); + u_char *out = new u_char[SHA256_DIGEST_SIZE]; + hmac_sha256_digest(ctx, SHA256_DIGEST_SIZE, out); + QByteArray respHMAC2(QByteArray::fromRawData((const char *)out, SHA256_DIGEST_SIZE)); + + + QByteArray mac(respHMAC.data()); + QByteArray mac2(respHMAC2.data()); + qDebug() << "mac: " << mac.toHex().data() << "\ndigest:" << mac2.toHex().data() << "\nequal? " << (respHMAC == respHMAC2); + + if (respHMAC == respHMAC2) { + QByteArray *xored = xorQByteArray(&cipherText, &respXORKey, 2 * masterKeyLen); + QByteArray ka(xored->data()); + ka.chop(masterKeyLen); + QByteArray *wrapKb = new QByteArray(xored->right(masterKeyLen)); + QByteArray *xored2 = xorQByteArray(&unwrapKb, wrapKb, masterKeyLen); + QByteArray kb(xored2->data()); + + QByteArray expectedKa(QByteArray::fromHex("202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f")); + QByteArray expectedKb(("a095c51c1c6e384e8d5777d97e3c487a4fc2128a00ab395a73d57fedf41631f0")); + + qDebug() << "ka? " << (ka == expectedKa) << "\nkb? " << (kb == expectedKb); + + delete xored; + delete wrapKb; + delete xored2; + } else { + returnVal = false; + } + + delete ctx; + delete out; +} diff --git a/src/lib/sync/synccrypto.h b/src/lib/sync/synccrypto.h index 932986854..2c215a5d9 100644 --- a/src/lib/sync/synccrypto.h +++ b/src/lib/sync/synccrypto.h @@ -29,8 +29,17 @@ struct RSAKeyPair { }; void generateRandomBytes(void *randomCtx, size_t numBytes, u_char *out); + u_char *syncCryptoHkdf(QByteArray *in, QByteArray *info, size_t out_len); void syncCryptoKW(QByteArray *kw, QString name); + void deriveSessionToken(QByteArray *sessionToken, QByteArray *tokenId, QByteArray *reqHMACKey, QByteArray *reqKey); void deriveKeyFetchToken(QByteArray *keyFetchToken, QByteArray *tokenId, QByteArray *reqHMACKey, QByteArray *respHMACKey, QByteArray *respXORKey); +bool deriveMasterKey(QByteArray *bundleHex, QByteArray *respHMACKey, QByteArray *respXORKey, QByteArray *unwrapKb, QByteArray *ka, QByteArray *kb); + RSAKeyPair *generateRSAKeyPair(); + +QByteArray *createBowserIdAssertion(QByteArray *certificate, QByteArray *audience, qint64 seconds, RSAKeyPair *keyPair); + +QByteArray *xorQByteArray(QByteArray *a, QByteArray *b, size_t len); +void testDeriveMasterKey(); diff --git a/src/lib/sync/syncmanager.cpp b/src/lib/sync/syncmanager.cpp index 7d93ab617..dd454edf9 100644 --- a/src/lib/sync/syncmanager.cpp +++ b/src/lib/sync/syncmanager.cpp @@ -16,8 +16,8 @@ * along with this program. If not, see . * ============================================================ */ #include "syncmanager.h" -#include "syncrequest.h" #include "synccrypto.h" +#include "syncutils.h" #include "settings.h" #include "hawk.h" #include "mainapplication.h" @@ -79,7 +79,7 @@ SyncState::~SyncState() void SyncState::saveSyncState(bool syncSuccess) { if (syncSuccess) { - *m_lastSyncTime = QDateTime::currentDateTimeUtc(); + *m_lastSyncTime = QDateTime::currentDateTime(); m_isInitialSync = false; Settings settings; settings.beginGroup(QSL("SyncState")); @@ -107,14 +107,19 @@ SyncManager::SyncManager(QObject *parent) m_syncState = new SyncState(); m_networkManager = new QNetworkAccessManager(this); m_keyPair = generateRSAKeyPair(); + m_browserCertificate = new QByteArray(); + + testDeriveMasterKey(); } SyncManager::~SyncManager() { saveSyncState(); + m_networkManager->deleteLater(); delete m_syncCreds; delete m_syncState; delete m_keyPair; + delete m_browserCertificate; } void SyncManager::saveSyncState() @@ -124,35 +129,49 @@ void SyncManager::saveSyncState() void SyncManager::sync() { - bool error = false; - if (m_storageCredentialsExpired) { - error = getBrowserSignedCertificate(); - if (!error) { - m_storageCredentialsExpired = false; - } - } else { - qDebug() << "Getting Crypto Keys"; - getCryptoKeys(); + switch(m_syncStep) { + case enum_ERROR: + qWarning() << "Error occured in Sync Process."; + m_syncSuccess = false; + saveSyncState(); + break; + case enum_FetchBrowserId: + getBrowserSignedCertificate(); + break; + case enum_TradeBrowserIdAssertion: + tradeBrowserIdAssertion(); + break; + case enum_FetchAccountKeys: + getCryptoKeys(); + break; + case enum_UploadDevice: + uploadDevice(); + break; + case enum_NoRequestPending: + qDebug() << "No sync requests pending."; + m_syncSuccess = true; + saveSyncState(); + break; + default: + saveSyncState(); + break; } - - if (error) { - m_syncSuccess = false; - qDebug() << "Sync Failed"; - } else { - m_syncSuccess = true; - } - saveSyncState(); } void SyncManager::startSync() { + if(m_syncState->isInitialSync()) { + qDebug() << "is initial sync, going to uploadDevice"; + m_syncStep = enum_UploadDevice; + } else { + qDebug() << "not initial sync, going to fetchBrowserId"; + m_syncStep = enum_FetchBrowserId; + } sync(); } -bool SyncManager::getBrowserSignedCertificate() +void SyncManager::getBrowserSignedCertificate() { - bool error = false; - QString endpoint("certificate/sign"); QByteArray *sessionToken = new QByteArray(QByteArray::fromHex(m_syncCreds->getValue("SessionToken").toUtf8().data())); @@ -182,7 +201,7 @@ bool SyncManager::getBrowserSignedCertificate() QNetworkRequest request = createHawkPostReqeuest(endpoint, tokenIdHex, requestHMACKey, 32, data); QNetworkReply *reply = m_networkManager->post(request, *data); - connect(reply, &QNetworkReply::finished, this, &SyncManager::recievedBrowserSignedCertificate); + connect(reply, &QNetworkReply::finished, this, &SyncManager::callback_getBrowserSignedCertificate); qDebug() << "Hawk POST Request sent to /certificate/sign endpoint."; @@ -194,25 +213,27 @@ bool SyncManager::getBrowserSignedCertificate() delete n; delete e; delete data; - - return error; } -void SyncManager::recievedBrowserSignedCertificate() +void SyncManager::callback_getBrowserSignedCertificate() { QNetworkReply* reply = qobject_cast(sender()); if (!reply) { + m_syncStep = enum_ERROR; + sync(); return; } if (reply->error() != QNetworkReply::NoError) { - qWarning() << "Error in recieving Browser Signed Certificate for Firefox Sync."; + qWarning() << "Error in receiving Browser Signed Certificate for Firefox Sync."; reply->close(); reply->deleteLater(); + m_syncStep = enum_ERROR; + sync(); return; } - QByteArray response = reply->readAll(); + QByteArray response(reply->readAll().data()); QJsonDocument doc = QJsonDocument::fromJson(response); QJsonObject obj = doc.object(); @@ -221,15 +242,24 @@ void SyncManager::recievedBrowserSignedCertificate() if (verifyBrowserSignedCertificate(&certificate)) { qDebug() << "Valid Browser Signed Certificate Response."; m_storageCredentialsExpired = false; - sync(); + m_browserCertificate->clear(); + m_browserCertificate->append(certificate.data()); + if (m_syncState->isInitialSync()) { + m_syncStep = enum_FetchAccountKeys; + } else { + m_syncStep = enum_TradeBrowserIdAssertion; + } } else { - qWarning() << "Invalid Browser ID Assertion Response Recieved."; + qWarning() << "Invalid Browser ID Assertion Response Received."; + m_syncStep = enum_ERROR; } } else { - qWarning() << "Invalid Browser ID Assertion Response Recieved."; + qWarning() << "Invalid Browser ID Assertion Response Received."; + m_syncStep = enum_ERROR; } reply->deleteLater(); + sync(); } bool SyncManager::verifyBrowserSignedCertificate(QByteArray* certificate) @@ -268,9 +298,16 @@ bool SyncManager::verifyBrowserSignedCertificate(QByteArray* certificate) return true; } - -bool SyncManager::getCryptoKeys() +void SyncManager::tradeBrowserIdAssertion() { + + m_syncStep = enum_NoRequestPending; + sync(); +} + +void SyncManager::getCryptoKeys() +{ + qDebug() << "getCryptoKeys"; QString endpoint("account/keys"); QByteArray *keyFetchToken = new QByteArray(QByteArray::fromHex(m_syncCreds->getValue("KeyFetchToken").toUtf8().data())); QByteArray *tokenId = new QByteArray(); @@ -278,33 +315,163 @@ bool SyncManager::getCryptoKeys() QByteArray *respHMACKey = new QByteArray(); QByteArray *respXorKey = new QByteArray(); deriveKeyFetchToken(keyFetchToken, tokenId, reqHMACKey, respHMACKey, respXorKey); - + + QByteArray respHMACKeyHex(respHMACKey->toHex().data()); + QByteArray reqHMACKeyHex(reqHMACKey->toHex().data()); + QByteArray respXorKeyHex(respXorKey->toHex().data()); + + m_syncCreds->addSyncCredentials(QString("RespHMACKey"), QString(respHMACKeyHex.data())); + m_syncCreds->addSyncCredentials(QString("ReqHMACKey"), QString(reqHMACKeyHex.data())); + m_syncCreds->addSyncCredentials(QString("RespXORKey"), QString(respXorKeyHex.data())); + qDebug() << "derived keyFetchToken"; QByteArray *tokenIdHex = new QByteArray(tokenId->toHex().data()); QNetworkRequest request = createHawkGetRequest(endpoint, tokenIdHex, reqHMACKey, 32); - + qDebug() << "Request created"; QNetworkReply *reply = m_networkManager->get(request); - connect(reply, &QNetworkReply::finished, this, [ = ]() { - if (reply->error() != QNetworkReply::NoError) { - qWarning() << "Reply Error" << reply->error() << reply->errorString(); - qDebug() << "Reply: " << reply->readAll(); - reply->deleteLater(); - return; - } - qDebug() << "Reply: " << reply->readAll(); - reply->deleteLater(); - }); + connect(reply, &QNetworkReply::finished, this, &SyncManager::callback_getCryptoKeys); + qDebug() << "Hawk POST Request sent to /account/keys endpoint."; + delete keyFetchToken; delete tokenId; delete reqHMACKey; delete respHMACKey; delete respXorKey; delete tokenIdHex; - - return false; } +void SyncManager::callback_getCryptoKeys() +{ + QNetworkReply* reply = qobject_cast(sender()); + qDebug() << "Received reply"; + if (!reply) { + qDebug()<< "No reply"; + m_syncStep = enum_ERROR; + sync(); + return; + } + + if (reply->error() != QNetworkReply::NoError) { + qWarning() << "Error in receiving Crypto Keys for Firefox Sync."; + qDebug() << reply->readAll(); + reply->close(); + reply->deleteLater(); + m_syncStep = enum_ERROR; + sync(); + return; + } + + qDebug() << "received bundle"; + QByteArray response(reply->readAll().data()); + qDebug() << "account/keys response:\n" << response; + QJsonDocument doc = QJsonDocument::fromJson(response); + QJsonObject obj = doc.object(); + + if (obj.contains(QString("bundle"))) { + QByteArray *bundle = new QByteArray(obj.value(QString("bundle")).toString().toUtf8()); + qDebug() << "bundle: " << bundle->data(); + m_syncCreds->addSyncCredentials(QString("Bundle"), QString(bundle->data())); + QByteArray *ka = new QByteArray(); + QByteArray *kb = new QByteArray(); + QByteArray *unwrapKb = new QByteArray(QByteArray::fromHex(m_syncCreds->getValue(QString("UnwrapBKey")).toUtf8())); + QByteArray *respHMACKey = new QByteArray(QByteArray::fromHex(m_syncCreds->getValue(QString("RespHMACKey")).toUtf8())); + QByteArray *respXorKey = new QByteArray(QByteArray::fromHex(m_syncCreds->getValue(QString("RespXORKey")).toUtf8())); + if(!deriveMasterKey(bundle, respHMACKey, respXorKey, unwrapKb, ka, kb)) { + qWarning() << "Failed to retrieve Sync Key."; + m_syncStep = enum_ERROR; + } else { + m_syncCreds->addSyncCredentials(QString("MasterKey"), QString(kb->toHex().data())); + m_syncStep = enum_TradeBrowserIdAssertion; + } + delete bundle; + delete ka; + delete kb; + delete unwrapKb; + delete respHMACKey; + delete respXorKey; + } else { + qWarning() << "Invalid Crypto Keys Response Recieved."; + m_syncStep = enum_ERROR; + } + + reply->deleteLater(); + sync(); +} + + +void SyncManager::uploadDevice() +{ + QString endpoint("account/device"); + + QJsonObject obj; + obj.insert(QString("name"), QString("Falkon")); + obj.insert(QString("type"), QString("desktop")); + QJsonDocument doc(obj); + QByteArray *data = new QByteArray(doc.toJson(QJsonDocument::Compact)); + + QByteArray *sessionToken = new QByteArray(QByteArray::fromHex(m_syncCreds->getValue("SessionToken").toUtf8().data())); + QByteArray *tokenId = new QByteArray(); + QByteArray *requestHMACKey = new QByteArray(); + QByteArray *requestKey = new QByteArray(); + deriveSessionToken(sessionToken, tokenId, requestHMACKey, requestKey); + + QByteArray *tokenIdHex = new QByteArray(tokenId->toHex().data()); + + QNetworkRequest request = createHawkPostReqeuest(endpoint, tokenIdHex, requestHMACKey, 32, data); + QNetworkReply *reply = m_networkManager->post(request, *data); + connect(reply, &QNetworkReply::finished, this, &SyncManager::callback_uploadDevice); + + qDebug() << "Hawk POST Request sent to /account/device endpoint."; + + + delete sessionToken; + delete tokenId; + delete requestHMACKey; + delete requestKey; + delete tokenIdHex; + delete data; +} + +void SyncManager::callback_uploadDevice() +{ + QNetworkReply* reply = qobject_cast(sender()); + qDebug() << "Received reply"; + if (!reply) { + qDebug()<< "No reply"; + m_syncStep = enum_ERROR; + sync(); + return; + } + + if (reply->error() != QNetworkReply::NoError) { + qWarning() << "Error in uploading Device Name to Firefox Sync."; + qDebug() << reply->readAll(); + reply->close(); + reply->deleteLater(); + m_syncStep = enum_ERROR; + sync(); + return; + } + + QByteArray response(reply->readAll().data()); + qDebug() << "account/device response:\n" << response; + QJsonDocument doc = QJsonDocument::fromJson(response); + QJsonObject obj = doc.object(); + + if (obj.contains(QString("id"))) { + QString id = obj.value(QString("id")).toString(); + qDebug() << "id of device:" << id; + m_syncCreds->addSyncCredentials(QString("DeviceId"), id); + m_syncStep = enum_FetchBrowserId; + } else { + qWarning() << "Invalid Upload Device Response Recieved."; + m_syncStep = enum_ERROR; + } + + reply->deleteLater(); + sync(); +} QNetworkRequest SyncManager::createHawkGetRequest(QString endpoint, QByteArray* id, QByteArray* key, size_t keyLen) { diff --git a/src/lib/sync/syncmanager.h b/src/lib/sync/syncmanager.h index a08addaa1..c5a43dc8a 100644 --- a/src/lib/sync/syncmanager.h +++ b/src/lib/sync/syncmanager.h @@ -58,6 +58,15 @@ class SyncManager : public QObject Q_OBJECT public: + enum SyncStep { + enum_ERROR = 0, + enum_NoRequestPending = 1, + enum_FetchBrowserId = 2, + enum_UploadDevice = 3, + enum_TradeBrowserIdAssertion = 4, + enum_FetchAccountKeys = 5 + }; + explicit SyncManager(QObject *parent = nullptr); ~SyncManager(); void sync(); @@ -67,11 +76,15 @@ public Q_SLOTS: void startSync(); private Q_SLOTS: - void recievedBrowserSignedCertificate(); + void callback_getBrowserSignedCertificate(); + void callback_getCryptoKeys(); + void callback_uploadDevice(); private: - bool getBrowserSignedCertificate(); - bool getCryptoKeys(); + void getBrowserSignedCertificate(); + void tradeBrowserIdAssertion(); + void getCryptoKeys(); + void uploadDevice(); bool verifyBrowserSignedCertificate(QByteArray *certificate); @@ -88,4 +101,8 @@ private: SyncCredentials *m_syncCreds; SyncState *m_syncState; RSAKeyPair *m_keyPair; + + QByteArray *m_browserCertificate; + + uint m_syncStep = enum_FetchBrowserId; }; diff --git a/src/lib/sync/syncrequest.cpp b/src/lib/sync/syncrequest.cpp deleted file mode 100644 index f00b19d6a..000000000 --- a/src/lib/sync/syncrequest.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* ============================================================ -* Falkon - Qt web browser -* Copyright (C) 2019 Prasenjit Kumar Shaw -* -* 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 3 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 . -* ============================================================ */ - -#include "syncrequest.h" - -#include -#include -#include -#include -#include - -SyncRequestManager::SyncRequestManager(QObject* parent) - : QObject(parent) -{ - m_requestManager = new QNetworkAccessManager(this); - m_requestQueue = new QQueue(); - startRequests = false; -} - -void SyncRequestManager::addRequest(QNetworkRequest *request, bool post) -{ - RequestPair temp = {*request, post}; - m_requestQueue->enqueue(temp); -} - -void SyncRequestManager::startSync(bool start) -{ - startRequests = start; - if (startRequests) { - if (!m_requestQueue->isEmpty()) { - RequestPair req = m_requestQueue->dequeue(); - QNetworkRequest request = req.request; - QNetworkReply *reply = nullptr; - if (req.post) { - reply = m_requestManager->get(request); - } else { - reply = m_requestManager->get(request); - } - } - } -} diff --git a/src/lib/sync/syncutils.cpp b/src/lib/sync/syncutils.cpp new file mode 100644 index 000000000..c274593c4 --- /dev/null +++ b/src/lib/sync/syncutils.cpp @@ -0,0 +1,40 @@ +/* ============================================================ +* Falkon - Qt web browser +* Copyright (C) 2019 Prasenjit Kumar Shaw +* +* 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 3 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 . +* ============================================================ */ + +#include "syncutils.h" + +#include +#include +#include + +QString getAudience(QUrl url) +{ + QString host = url.host(); + QString scheme = url.scheme(); + + qint64 port = url.port(0); + + QString audience; + if(port == 0) { + audience = QSL("%s://%s").arg(scheme).arg(host); + } + else { + audience = QSL("%s://%s:%s").arg(scheme).arg(host).arg(port); + } + return audience; +} diff --git a/src/lib/sync/syncrequest.h b/src/lib/sync/syncutils.h similarity index 61% rename from src/lib/sync/syncrequest.h rename to src/lib/sync/syncutils.h index f706cb54a..aea5fe2c8 100644 --- a/src/lib/sync/syncrequest.h +++ b/src/lib/sync/syncutils.h @@ -15,31 +15,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . * ============================================================ */ - #pragma once -#include -#include -#include -#include -#include +#include +#include -class SyncRequestManager : public QObject -{ - Q_OBJECT - -public: - explicit SyncRequestManager(QObject *parent = nullptr); - void addRequest(QNetworkRequest *request, bool post); - void startSync(bool start); - -private: - struct RequestPair { - QNetworkRequest request; - bool post; - }; - - QNetworkAccessManager *m_requestManager; - QQueue *m_requestQueue; - bool startRequests; -}; +QString getAudience(QUrl url);