about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/omemo/omemo.c12
-rw-r--r--src/omemo/omemo.h1
-rw-r--r--src/profanity.c3
-rw-r--r--src/xmpp/iq.c16
-rw-r--r--src/xmpp/omemo.c67
5 files changed, 72 insertions, 27 deletions
diff --git a/src/omemo/omemo.c b/src/omemo/omemo.c
index 96d2d65a..02107432 100644
--- a/src/omemo/omemo.c
+++ b/src/omemo/omemo.c
@@ -128,6 +128,15 @@ omemo_init(void)
 }
 
 void
+omemo_close(void)
+{
+    if (omemo_ctx.fingerprint_ac) {
+        autocomplete_free(omemo_ctx.fingerprint_ac);
+        omemo_ctx.fingerprint_ac = NULL;
+    }
+}
+
+void
 omemo_on_connect(ProfAccount *account)
 {
     GError *error = NULL;
@@ -217,8 +226,6 @@ omemo_on_connect(ProfAccount *account)
     omemo_ctx.device_list_handler = g_hash_table_new_full(g_str_hash, g_str_equal, free, NULL);
     omemo_ctx.known_devices = g_hash_table_new_full(g_str_hash, g_str_equal, free, (GDestroyNotify)_g_hash_table_free);
 
-    omemo_ctx.fingerprint_ac = autocomplete_new();
-
     char *omemodir = files_get_data_path(DIR_OMEMO);
     GString *basedir = g_string_new(omemodir);
     free(omemodir);
@@ -298,6 +305,7 @@ omemo_on_disconnect(void)
 
     _g_hash_table_free(omemo_ctx.signed_pre_key_store);
     _g_hash_table_free(omemo_ctx.pre_key_store);
+    _g_hash_table_free(omemo_ctx.device_list_handler);
 
     g_string_free(omemo_ctx.identity_filename, TRUE);
     g_key_file_free(omemo_ctx.identity_keyfile);
diff --git a/src/omemo/omemo.h b/src/omemo/omemo.h
index ae25b5ba..abe21be5 100644
--- a/src/omemo/omemo.h
+++ b/src/omemo/omemo.h
@@ -56,6 +56,7 @@ typedef struct omemo_key {
 } omemo_key_t;
 
 void omemo_init(void);
+void omemo_close(void);
 void omemo_on_connect(ProfAccount *account);
 void omemo_on_disconnect(void);
 void omemo_generate_crypto_materials(ProfAccount *account);
diff --git a/src/profanity.c b/src/profanity.c
index a9824729..324aa36d 100644
--- a/src/profanity.c
+++ b/src/profanity.c
@@ -242,6 +242,9 @@ _shutdown(void)
 #ifdef HAVE_LIBGPGME
     p_gpg_close();
 #endif
+#ifdef HAVE_OMEMO
+    omemo_close();
+#endif
     chat_log_close();
     theme_close();
     accounts_close();
diff --git a/src/xmpp/iq.c b/src/xmpp/iq.c
index 91acc212..e31f3269 100644
--- a/src/xmpp/iq.c
+++ b/src/xmpp/iq.c
@@ -134,6 +134,7 @@ static int _command_exec_response_handler(xmpp_stanza_t *const stanza, void *con
 
 static void _iq_free_room_data(ProfRoomInfoData *roominfo);
 static void _iq_free_affiliation_set(ProfPrivilegeSet *affiliation_set);
+static void _iq_id_handler_free(ProfIqHandler *handler);
 
 // scheduled
 static int _autoping_timed_send(xmpp_conn_t *const conn, void *const userdata);
@@ -247,7 +248,7 @@ iq_handlers_init(void)
         g_list_free(keys);
         g_hash_table_destroy(id_handlers);
     }
-    id_handlers = g_hash_table_new_full(g_str_hash, g_str_equal, free, NULL);
+    id_handlers = g_hash_table_new_full(g_str_hash, g_str_equal, free, (GDestroyNotify)_iq_id_handler_free);
     rooms_cache = g_hash_table_new_full(g_str_hash, g_str_equal, free, (GDestroyNotify)xmpp_stanza_release);
 }
 
@@ -259,6 +260,19 @@ iq_handlers_clear()
     }
 }
 
+static void
+_iq_id_handler_free(ProfIqHandler *handler)
+{
+    if (handler == NULL) {
+        return;
+    }
+    if (handler->free_func && handler->userdata) {
+        handler->free_func(handler->userdata);
+    }
+    free(handler);
+    handler = NULL;
+}
+
 void
 iq_id_handler_add(const char *const id, ProfIqCallback func, ProfIqFreeCallback free_func, void *userdata)
 {
diff --git a/src/xmpp/omemo.c b/src/xmpp/omemo.c
index cfa3f84c..e44cc00e 100644
--- a/src/xmpp/omemo.c
+++ b/src/xmpp/omemo.c
@@ -111,8 +111,13 @@ omemo_bundle_request(const char * const jid, uint32_t device_id, ProfIqCallback
 int
 omemo_start_device_session_handle_bundle(xmpp_stanza_t *const stanza, void *const userdata)
 {
+    GList *prekeys_list = NULL;
+    unsigned char *signed_prekey_raw = NULL;
+    unsigned char *signed_prekey_signature_raw = NULL;
     char *from = NULL;
+
     const char *from_attr = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
+
     if (!from_attr) {
         Jid *jid = jid_create(connection_get_fulljid());
         from = strdup(jid->barejid);
@@ -122,55 +127,59 @@ omemo_start_device_session_handle_bundle(xmpp_stanza_t *const stanza, void *cons
     }
 
     if (g_strcmp0(from, userdata) != 0) {
-        return 1;
+        goto out;
     }
 
     xmpp_stanza_t *pubsub = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_PUBSUB);
     if (!pubsub) {
-        return 1;
+        goto out;
     }
 
     xmpp_stanza_t *items = xmpp_stanza_get_child_by_name(pubsub, "items");
     if (!items) {
-        return 1;
+        goto out;
     }
     const char *node = xmpp_stanza_get_attribute(items, "node");
     char *device_id_str = strstr(node, ":");
     if (!device_id_str) {
-        return 1;
+        goto out;
     }
 
     uint32_t device_id = strtoul(++device_id_str, NULL, 10);
 
     xmpp_stanza_t *item = xmpp_stanza_get_child_by_name(items, "item");
     if (!item) {
-        return 1;
+        goto out;
     }
 
     xmpp_stanza_t *bundle = xmpp_stanza_get_child_by_ns(item, STANZA_NS_OMEMO);
     if (!bundle) {
-        return 1;
+        goto out;
     }
 
     xmpp_stanza_t *prekeys = xmpp_stanza_get_child_by_name(bundle, "prekeys");
     if (!prekeys) {
-        return 1;
+        goto out;
     }
 
-    GList *prekeys_list = NULL;
     xmpp_stanza_t *prekey;
     for (prekey = xmpp_stanza_get_children(prekeys); prekey != NULL; prekey = xmpp_stanza_get_next(prekey)) {
         omemo_key_t *key = malloc(sizeof(omemo_key_t));
 
         const char *prekey_id_text = xmpp_stanza_get_attribute(prekey, "preKeyId");
         if (!prekey_id_text) {
-            return 1;
+            omemo_key_free(key);
+            goto out;
         }
+
         key->id = strtoul(prekey_id_text, NULL, 10);
         xmpp_stanza_t *prekey_text = xmpp_stanza_get_children(prekey);
+
         if (!prekey_text) {
-            return 1;
+            omemo_key_free(key);
+            goto out;
         }
+
         char *prekey_b64 = xmpp_stanza_get_text(prekey_text);
         key->data = g_base64_decode(prekey_b64, &key->length);
         free(prekey_b64);
@@ -182,42 +191,44 @@ omemo_start_device_session_handle_bundle(xmpp_stanza_t *const stanza, void *cons
 
     xmpp_stanza_t *signed_prekey = xmpp_stanza_get_child_by_name(bundle, "signedPreKeyPublic");
     if (!signed_prekey) {
-        return 1;
+        goto out;
     }
     const char *signed_prekey_id_text = xmpp_stanza_get_attribute(signed_prekey, "signedPreKeyId");
     if (!signed_prekey_id_text) {
-        return 1;
+        goto out;
     }
+
     uint32_t signed_prekey_id = strtoul(signed_prekey_id_text, NULL, 10);
     xmpp_stanza_t *signed_prekey_text = xmpp_stanza_get_children(signed_prekey);
     if (!signed_prekey_text) {
-        return 1;
+        goto out;
     }
+
     size_t signed_prekey_len;
     char *signed_prekey_b64 = xmpp_stanza_get_text(signed_prekey_text);
-    unsigned char *signed_prekey_raw = g_base64_decode(signed_prekey_b64, &signed_prekey_len);
+    signed_prekey_raw = g_base64_decode(signed_prekey_b64, &signed_prekey_len);
     free(signed_prekey_b64);
 
     xmpp_stanza_t *signed_prekey_signature = xmpp_stanza_get_child_by_name(bundle, "signedPreKeySignature");
     if (!signed_prekey_signature) {
-        return 1;
+        goto out;
     }
     xmpp_stanza_t *signed_prekey_signature_text = xmpp_stanza_get_children(signed_prekey_signature);
     if (!signed_prekey_signature_text) {
-        return 1;
+        goto out;
     }
     size_t signed_prekey_signature_len;
     char *signed_prekey_signature_b64 = xmpp_stanza_get_text(signed_prekey_signature_text);
-    unsigned char *signed_prekey_signature_raw = g_base64_decode(signed_prekey_signature_b64, &signed_prekey_signature_len);
+    signed_prekey_signature_raw = g_base64_decode(signed_prekey_signature_b64, &signed_prekey_signature_len);
     free(signed_prekey_signature_b64);
 
     xmpp_stanza_t *identity_key = xmpp_stanza_get_child_by_name(bundle, "identityKey");
     if (!identity_key) {
-        return 1;
+        goto out;
     }
     xmpp_stanza_t *identity_key_text = xmpp_stanza_get_children(identity_key);
     if (!identity_key_text) {
-        return 1;
+        goto out;
     }
     size_t identity_key_len;
     char *identity_key_b64 = xmpp_stanza_get_text(identity_key_text);
@@ -228,11 +239,19 @@ omemo_start_device_session_handle_bundle(xmpp_stanza_t *const stanza, void *cons
         signed_prekey_raw, signed_prekey_len, signed_prekey_signature_raw,
         signed_prekey_signature_len, identity_key_raw, identity_key_len);
 
-    free(from);
-    g_list_free_full(prekeys_list, (GDestroyNotify)omemo_key_free);
-    g_free(signed_prekey_raw);
     g_free(identity_key_raw);
-    g_free(signed_prekey_signature_raw);
+
+out:
+    free(from);
+    if (signed_prekey_raw) {
+        g_free(signed_prekey_raw);
+    }
+    if (signed_prekey_signature_raw) {
+        g_free(signed_prekey_signature_raw);
+    }
+    if (prekeys_list) {
+        g_list_free_full(prekeys_list, (GDestroyNotify)omemo_key_free);
+    }
     return 1;
 }
 
@@ -292,12 +311,12 @@ omemo_receive_message(xmpp_stanza_t *const stanza, gboolean *trusted)
             goto skip;
         }
 
-
         const char *rid_text = xmpp_stanza_get_attribute(key_stanza, "rid");
         key->device_id = strtoul(rid_text, NULL, 10);
         if (!key->device_id) {
             goto skip;
         }
+
         key->data = g_base64_decode(key_text, &key->length);
         free(key_text);
         key->prekey = g_strcmp0(xmpp_stanza_get_attribute(key_stanza, "prekey"), "true") == 0;