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);