aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--matrix-e2e.c107
1 files changed, 102 insertions, 5 deletions
diff --git a/matrix-e2e.c b/matrix-e2e.c
index 2c59888..2782b93 100644
--- a/matrix-e2e.c
+++ b/matrix-e2e.c
@@ -145,17 +145,24 @@ static void olm_hash_key_destroy(gpointer k)
g_free(ok);
}
+static void free_matrix_olm_session(MatrixOlmSession *msession,
+ gboolean free_session)
+{
+ g_free(msession->sender_id);
+ g_free(msession->sender_key);
+ if (free_session) {
+ olm_clear_session(msession->session);
+ g_free(msession->session);
+ }
+}
+
static void olm_hash_value_destroy(gpointer v)
{
MatrixOlmSession *os = v;
while (os) {
MatrixOlmSession *next = os->next;
- olm_clear_session(os->session);
- g_free(os->session);
- g_free(os->sender_key);
- g_free(os->sender_id);
- g_free(os);
+ free_matrix_olm_session(os, TRUE);
os = next;
}
}
@@ -402,6 +409,91 @@ bad_sql:
return result;
}
+/* Save a new olm session into the database */
+static MatrixOlmSession *store_olm_session(MatrixConnectionData *conn,
+ OlmSession *session,
+ const char *sender_id,
+ const char *sender_key)
+{
+ MatrixOlmSession *cur_entry = g_new0(MatrixOlmSession, 1);
+ size_t pickle_len = olm_pickle_session_length(session);
+ gchar *pickle = g_malloc(pickle_len+1);
+ sqlite3_stmt *dbstmt = NULL;
+
+ pickle_len = olm_pickle_session(session, "!", 1, pickle, pickle_len);
+ if (pickle_len == olm_error()) {
+ purple_debug_warning("matrixprpl",
+ "%s: Failed to pickle session for %s/%s: %s\n",
+ __func__, sender_id, sender_key,
+ olm_session_last_error(session));
+ goto err;
+ }
+ pickle[pickle_len] = '\0';
+
+ cur_entry->sender_id = g_strdup(sender_id);
+ cur_entry->sender_key = g_strdup(sender_key);
+ cur_entry->session = session;
+
+ const char *query = "INSERT into olmsessions "
+ "(sender_name, sender_key, session_pickle) "
+ "VALUES (?, ?, ?)";
+
+ int ret = sqlite3_prepare_v2(conn->e2e->db, query, -1, &dbstmt, NULL);
+ if (ret != SQLITE_OK || !dbstmt) {
+ purple_debug_warning("matrixprpl",
+ "%s: Failed to prep insert %d '%s'\n",
+ __func__, ret, query);
+ goto err;
+ }
+ ret = sqlite3_bind_text(dbstmt, 1, sender_id, -1, NULL);
+ if (ret == SQLITE_OK) {
+ ret = sqlite3_bind_text(dbstmt, 2, sender_key, -1, NULL);
+ }
+ if (ret == SQLITE_OK) {
+ ret = sqlite3_bind_text(dbstmt, 3, pickle, -1, NULL);
+ }
+ if (ret != SQLITE_OK) {
+ purple_debug_warning("matrixprpl",
+ "%s: Failed to bind %d\n", __func__, ret);
+ goto err;
+ }
+
+ ret = sqlite3_step(dbstmt);
+ if (ret != SQLITE_DONE) {
+ purple_debug_warning("matrixprpl",
+ "%s: Insert failed %d (%s)\n", __func__,
+ ret, query);
+ goto err;
+ }
+ sqlite3_finalize(dbstmt);
+ cur_entry->unique = sqlite3_last_insert_rowid(conn->e2e->db);
+
+ MatrixHashKeyOlm match;
+ match.sender_key = (gchar *)sender_key;
+ match.sender_id = (gchar *)sender_id;
+ MatrixOlmSession *hash_result = (MatrixOlmSession *)g_hash_table_lookup(
+ conn->e2e->olm_session_hash, &match);
+ if (hash_result) {
+ /* If there's already an entry, insert it after the head */
+ cur_entry->next = hash_result->next;
+ hash_result->next = cur_entry;
+ } else {
+ /* No entry, we need to stuff it into the hash table */
+ MatrixHashKeyOlm *key = g_new0(MatrixHashKeyOlm, 1);
+ key->sender_key = g_strdup(sender_key);
+ key->sender_id = g_strdup(sender_id);
+ /* We loaded entries where there were none before, set the hash */
+ g_hash_table_insert(conn->e2e->olm_session_hash, key, cur_entry);
+ }
+
+ return cur_entry;
+
+err:
+ g_free(pickle);
+ free_matrix_olm_session(cur_entry, FALSE);
+ return NULL;
+}
+
/* Sign the JsonObject with olm_account_sign and add it to the object
* as a 'signatures' member of the top level object.
* 0 on success
@@ -1281,6 +1373,11 @@ static void decrypt_olm(PurpleConnection *pc, MatrixConnectionData *conn, JsonOb
g_free(session);
goto err;
}
+ mos = store_olm_session(conn, session, cevent_sender, sender_key);
+ if (!mos) {
+ g_free(session);
+ goto err;
+ }
if (matrix_store_e2e_account(conn)) {
g_free(session);
goto err;