[epiphany/wip/sync: 24/31] sync-service: Handle missing metaglobal and cryptokeys records
- From: Gabriel Ivașcu <gabrielivascu src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [epiphany/wip/sync: 24/31] sync-service: Handle missing metaglobal and cryptokeys records
- Date: Fri, 14 Apr 2017 15:53:34 +0000 (UTC)
commit ae565fc9de3e37f4349a53c80459c54e5329ed20
Author: Gabriel Ivascu <ivascu gabriel59 gmail com>
Date: Thu Apr 13 15:07:49 2017 +0300
sync-service: Handle missing metaglobal and cryptokeys records
src/sync/ephy-sync-crypto.c | 41 ++++++++++++
src/sync/ephy-sync-crypto.h | 1 +
src/sync/ephy-sync-service.c | 139 ++++++++++++++++++++++++++++++++++++++----
3 files changed, 168 insertions(+), 13 deletions(-)
---
diff --git a/src/sync/ephy-sync-crypto.c b/src/sync/ephy-sync-crypto.c
index eb58971..7133bef 100644
--- a/src/sync/ephy-sync-crypto.c
+++ b/src/sync/ephy-sync-crypto.c
@@ -926,6 +926,47 @@ ephy_sync_crypto_derive_key_bundle (const guint8 *key,
}
char *
+ephy_sync_crypto_generate_crypto_keys (gsize key_len)
+{
+ JsonNode *node;
+ JsonObject *object;
+ JsonArray *array;
+ guint8 *aes_key;
+ guint8 *hmac_key;
+ char *aes_key_b64;
+ char *hmac_key_b64;
+ char *payload;
+
+ aes_key = g_malloc (key_len);
+ ephy_sync_crypto_random_bytes_gen (NULL, key_len, aes_key);
+ aes_key_b64 = g_base64_encode (aes_key, key_len);
+ hmac_key = g_malloc (key_len);
+ ephy_sync_crypto_random_bytes_gen (NULL, key_len, hmac_key);
+ hmac_key_b64 = g_base64_encode (hmac_key, key_len);
+
+ node = json_node_new (JSON_NODE_OBJECT);
+ object = json_object_new ();
+ array = json_array_new ();
+ json_array_add_string_element (array, aes_key_b64);
+ json_array_add_string_element (array, hmac_key_b64);
+ json_object_set_array_member (object, "default", array);
+ json_object_set_object_member (object, "collections", json_object_new ());
+ json_object_set_string_member (object, "collection", "crypto");
+ json_object_set_string_member (object, "id", "keys");
+ json_node_set_object (node, object);
+ payload = json_to_string (node, FALSE);
+
+ json_object_unref (object);
+ json_node_unref (node);
+ g_free (hmac_key_b64);
+ g_free (hmac_key);
+ g_free (aes_key_b64);
+ g_free (aes_key);
+
+ return payload;
+}
+
+char *
ephy_sync_crypto_decrypt_record (const char *payload,
SyncCryptoKeyBundle *bundle)
{
diff --git a/src/sync/ephy-sync-crypto.h b/src/sync/ephy-sync-crypto.h
index ce2b33c..ef3365a 100644
--- a/src/sync/ephy-sync-crypto.h
+++ b/src/sync/ephy-sync-crypto.h
@@ -100,6 +100,7 @@ gboolean ephy_sync_crypto_compute_sync_keys (const char
gsize key_len);
SyncCryptoKeyBundle *ephy_sync_crypto_derive_key_bundle (const guint8 *key,
gsize key_len);
+char *ephy_sync_crypto_generate_crypto_keys (gsize key_len);
char *ephy_sync_crypto_decrypt_record (const char *payload,
SyncCryptoKeyBundle *bundle);
char *ephy_sync_crypto_encrypt_record (const char *cleartext,
diff --git a/src/sync/ephy-sync-service.c b/src/sync/ephy-sync-service.c
index 2ae7b38..3cfc543 100644
--- a/src/sync/ephy-sync-service.c
+++ b/src/sync/ephy-sync-service.c
@@ -1470,27 +1470,65 @@ ephy_sync_service_report_sign_in_error (EphySyncService *self,
}
}
+static char *
+ephy_sync_service_upload_crypto_keys_record (EphySyncService *self)
+{
+ SyncCryptoKeyBundle *bundle;
+ JsonNode *node;
+ JsonObject *record;
+ char *payload_clear;
+ char *payload_cipher;
+ char *body;
+ guint8 *master_key;
+
+ g_assert (EPHY_IS_SYNC_SERVICE (self));
+ g_assert (ephy_sync_service_get_secret (self, secrets[MASTER_KEY]));
+
+ node = json_node_new (JSON_NODE_OBJECT);
+ record = json_object_new ();
+ payload_clear = ephy_sync_crypto_generate_crypto_keys (TOKEN_LENGTH);
+ master_key = ephy_sync_crypto_decode_hex (ephy_sync_service_get_secret (self, secrets[MASTER_KEY]));
+ bundle = ephy_sync_crypto_derive_key_bundle (master_key, TOKEN_LENGTH);
+ payload_cipher = ephy_sync_crypto_encrypt_record (payload_clear, bundle);
+ json_object_set_string_member (record, "payload", payload_cipher);
+ json_object_set_string_member (record, "id", "keys");
+ json_node_set_object (node, record);
+ body = json_to_string (node, FALSE);
+
+ ephy_sync_service_queue_storage_request (self, "storage/crypto/keys",
+ SOUP_METHOD_PUT, body,
+ -1, -1, NULL, NULL);
+
+ g_free (body);
+ g_free (payload_cipher);
+ ephy_sync_crypto_key_bundle_free (bundle);
+ g_free (master_key);
+ json_object_unref (record);
+ json_node_unref (node);
+
+ return payload_clear;
+}
+
static void
obtain_crypto_keys_cb (SoupSession *session,
SoupMessage *msg,
gpointer user_data)
{
EphySyncService *self;
- SyncCryptoKeyBundle *bundle;
+ SyncCryptoKeyBundle *bundle = NULL;
JsonObject *json;
- JsonNode *node;
+ JsonNode *node = NULL;
GError *error = NULL;
const char *payload;
char *crypto_keys;
- guint8 *kB;
+ guint8 *kB = NULL;
gboolean is_internal_error = TRUE;
self = ephy_shell_get_sync_service (ephy_shell_get_default ());
if (msg->status_code == 404) {
- /* TODO: Generate and upload new sync key bundles. */
- is_internal_error = FALSE;
- goto out;
+ crypto_keys = ephy_sync_service_upload_crypto_keys_record (self);
+ goto store_secrets;
}
if (msg->status_code != 200) {
@@ -1527,17 +1565,19 @@ obtain_crypto_keys_cb (SoupSession *session,
goto free_bundle;
}
- /* Proceed to store secrets. */
+store_secrets:
ephy_sync_service_set_secret (self, secrets[CRYPTO_KEYS], crypto_keys);
ephy_sync_secret_store_secrets (self);
is_internal_error = FALSE;
g_free (crypto_keys);
free_bundle:
- ephy_sync_crypto_key_bundle_free (bundle);
+ if (bundle)
+ ephy_sync_crypto_key_bundle_free (bundle);
g_free (kB);
free_node:
- json_node_unref (node);
+ if (node)
+ json_node_unref (node);
out:
if (is_internal_error)
ephy_sync_service_report_sign_in_error (self,
@@ -1555,22 +1595,94 @@ ephy_sync_service_obtain_crypto_keys (EphySyncService *self)
obtain_crypto_keys_cb, NULL);
}
+static JsonObject *
+make_engine_object (int version)
+{
+ JsonObject *object;
+ char *sync_id;
+
+ object = json_object_new ();
+ sync_id = ephy_sync_crypto_get_random_sync_id ();
+ json_object_set_int_member (object, "version", version);
+ json_object_set_string_member (object, "syncID", sync_id);
+
+ g_free (sync_id);
+
+ return object;
+}
+
+static void
+ephy_sync_service_upload_meta_global_record (EphySyncService *self)
+{
+ JsonNode *node;
+ JsonObject *record;
+ JsonObject *payload;
+ JsonObject *engines;
+ JsonArray *declined;
+ char *sync_id;
+ char *payload_str;
+ char *body;
+
+ g_assert (EPHY_IS_SYNC_SERVICE (self));
+
+ node = json_node_new (JSON_NODE_OBJECT);
+ record = json_object_new ();
+ payload = json_object_new ();
+ engines = json_object_new ();
+ declined = json_array_new ();
+ json_array_add_string_element (declined, "addons");
+ json_array_add_string_element (declined, "prefs");
+ json_array_add_string_element (declined, "tabs");
+ json_object_set_array_member (payload, "declined", declined);
+ json_object_set_object_member (engines, "clients", make_engine_object (1));
+ json_object_set_object_member (engines, "bookmarks", make_engine_object (2));
+ json_object_set_object_member (engines, "history", make_engine_object (1));
+ json_object_set_object_member (engines, "passwords", make_engine_object (1));
+ json_object_set_object_member (engines, "forms", make_engine_object (1));
+ json_object_set_object_member (payload, "engines", engines);
+ json_object_set_int_member (payload, "storageVersion", STORAGE_VERSION);
+ sync_id = ephy_sync_crypto_get_random_sync_id ();
+ json_object_set_string_member (payload, "syncID", sync_id);
+ json_node_set_object (node, payload);
+ payload_str = json_to_string (node, FALSE);
+ json_object_set_string_member (record, "payload", payload_str);
+ json_object_set_string_member (record, "id", "global");
+ json_node_set_object (node, record);
+ body = json_to_string (node, FALSE);
+
+ ephy_sync_service_queue_storage_request (self, "storage/meta/global",
+ SOUP_METHOD_PUT, body,
+ -1, -1, NULL, NULL);
+
+ g_free (body);
+ g_free (payload_str);
+ g_free (sync_id);
+ json_object_unref (payload);
+ json_object_unref (record);
+ json_node_unref (node);
+}
+
static void
check_storage_version_cb (SoupSession *session,
SoupMessage *msg,
gpointer user_data)
{
EphySyncService *self;
- JsonParser *parser;
+ JsonParser *parser = NULL;
JsonObject *json;
GError *error = NULL;
- char *payload;
+ char *payload = NULL;
char *message = NULL;
int storage_version;
gboolean is_internal_error = TRUE;
self = ephy_shell_get_sync_service (ephy_shell_get_default ());
+ if (msg->status_code == 404) {
+ ephy_sync_service_upload_meta_global_record (self);
+ goto obtain_crypto_keys;
+ }
+
if (msg->status_code != 200) {
g_warning ("Failed to check storage version. Status code: %u, response: %s",
msg->status_code, msg->response_body->data);
@@ -1623,14 +1735,15 @@ check_storage_version_cb (SoupSession *session,
goto free_payload;
}
- /* Proceed to obtain the crypto keys. */
+obtain_crypto_keys:
ephy_sync_service_obtain_crypto_keys (self);
is_internal_error = FALSE;
free_payload:
g_free (payload);
free_parser:
- g_object_unref (parser);
+ if (parser)
+ g_object_unref (parser);
out:
if (is_internal_error) {
ephy_sync_service_report_sign_in_error (self,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]