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 @@ -127,6 +127,15 @@ omemo_init(void) omemo_ctx.fingerprint_ac = autocomplete_new(); } +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) { @@ -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 @@ -241,6 +241,9 @@ _shutdown(void) #endif #ifdef HAVE_LIBGPGME p_gpg_close(); +#endif +#ifdef HAVE_OMEMO + omemo_close(); #endif chat_log_close(); theme_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;