From b460d427bc132aa088f5787a17d045d2ece172d5 Mon Sep 17 00:00:00 2001 From: Stefan Date: Mon, 15 Feb 2021 19:52:53 +0100 Subject: [PATCH 1/7] OMEMO - Removed start session after roster received Reduce the request during startup of profanity Removed omemo_start_sessions from sv_ev_roster_received --- src/event/server_events.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/event/server_events.c b/src/event/server_events.c index d297b103..152c0ac6 100644 --- a/src/event/server_events.c +++ b/src/event/server_events.c @@ -195,10 +195,6 @@ sv_ev_roster_received(void) const char* fulljid = connection_get_fulljid(); plugins_on_connect(account_name, fulljid); - -#ifdef HAVE_OMEMO - omemo_start_sessions(); -#endif } void From fb4aec752f67788729a46d5f814627ba9309f3a9 Mon Sep 17 00:00:00 2001 From: Stefan Date: Sat, 6 Mar 2021 19:51:34 +0100 Subject: [PATCH 2/7] Changes logging format to [OMEMO] --- src/omemo/omemo.c | 97 ++++++++++++++++++++++++----------------------- 1 file changed, 49 insertions(+), 48 deletions(-) diff --git a/src/omemo/omemo.c b/src/omemo/omemo.c index 1c6a1c8b..69c96003 100644 --- a/src/omemo/omemo.c +++ b/src/omemo/omemo.c @@ -118,7 +118,7 @@ static omemo_context omemo_ctx; void omemo_init(void) { - log_info("OMEMO: initialising"); + log_info("[OMEMO] initialising"); if (omemo_crypto_init() != 0) { cons_show("Error initializing OMEMO crypto: gcry_check_version() failed"); } @@ -244,9 +244,9 @@ omemo_on_connect(ProfAccount* account) if (res == -1) { const char* errmsg = strerror(errno); if (errmsg) { - log_error("OMEMO: error creating directory: %s, %s", omemo_dir, errmsg); + log_error("[OMEMO] error creating directory: %s, %s", omemo_dir, errmsg); } else { - log_error("OMEMO: creating directory: %s", omemo_dir); + log_error("[OMEMO] creating directory: %s", omemo_dir); } } @@ -264,7 +264,7 @@ omemo_on_connect(ProfAccount* account) return; } } else if (error->code != G_FILE_ERROR_NOENT) { - log_warning("OMEMO: error loading identity from: %s, %s", omemo_ctx.identity_filename->str, error->message); + log_warning("[OMEMO] error loading identity from: %s, %s", omemo_ctx.identity_filename->str, error->message); g_error_free(error); return; } @@ -273,7 +273,7 @@ omemo_on_connect(ProfAccount* account) if (g_key_file_load_from_file(omemo_ctx.trust_keyfile, omemo_ctx.trust_filename->str, G_KEY_FILE_KEEP_COMMENTS, &error)) { _load_trust(); } else if (error->code != G_FILE_ERROR_NOENT) { - log_warning("OMEMO: error loading trust from: %s, %s", omemo_ctx.trust_filename->str, error->message); + log_warning("[OMEMO] error loading trust from: %s, %s", omemo_ctx.trust_filename->str, error->message); g_error_free(error); } @@ -281,7 +281,7 @@ omemo_on_connect(ProfAccount* account) if (g_key_file_load_from_file(omemo_ctx.sessions_keyfile, omemo_ctx.sessions_filename->str, G_KEY_FILE_KEEP_COMMENTS, &error)) { _load_sessions(); } else if (error->code != G_FILE_ERROR_NOENT) { - log_warning("OMEMO: error loading sessions from: %s, %s", omemo_ctx.sessions_filename->str, error->message); + log_warning("[OMEMO] error loading sessions from: %s, %s", omemo_ctx.sessions_filename->str, error->message); g_error_free(error); } @@ -289,7 +289,7 @@ omemo_on_connect(ProfAccount* account) if (g_key_file_load_from_file(omemo_ctx.known_devices_keyfile, omemo_ctx.known_devices_filename->str, G_KEY_FILE_KEEP_COMMENTS, &error)) { _load_known_devices(); } else if (error->code != G_FILE_ERROR_NOENT) { - log_warning("OMEMO: error loading known devices from: %s, %s", omemo_ctx.known_devices_filename->str, error->message); + log_warning("[OMEMO] error loading known devices from: %s, %s", omemo_ctx.known_devices_filename->str, error->message); g_error_free(error); } } @@ -329,7 +329,7 @@ omemo_generate_crypto_materials(ProfAccount* account) gcry_randomize(&omemo_ctx.device_id, 4, GCRY_VERY_STRONG_RANDOM); omemo_ctx.device_id &= 0x7fffffff; g_key_file_set_uint64(omemo_ctx.identity_keyfile, OMEMO_STORE_GROUP_IDENTITY, OMEMO_STORE_KEY_DEVICE_ID, omemo_ctx.device_id); - log_info("OMEMO: device id: %d", omemo_ctx.device_id); + log_info("[OMEMO] device id: %d", omemo_ctx.device_id); /* Identity key */ signal_protocol_key_helper_generate_identity_key_pair(&omemo_ctx.identity_key_pair, omemo_ctx.signal); @@ -366,7 +366,8 @@ void omemo_publish_crypto_materials(void) { if (loaded != TRUE) { - log_error("OMEMO: cannot publish crypto materials before they are generated"); + cons_show("OMEMO: cannot publish crypto materials before they are generated"); + log_error("[OMEMO] cannot publish crypto materials before they are generated"); return; } @@ -401,10 +402,10 @@ void omemo_start_session(const char* const barejid) { if (omemo_loaded()) { - log_info("OMEMO: start session with %s", barejid); + log_info("[OMEMO] start session with %s", barejid); GList* device_list = g_hash_table_lookup(omemo_ctx.device_list, barejid); if (!device_list) { - log_info("OMEMO: missing device list for %s", barejid); + log_info("[OMEMO] missing device list for %s", barejid); omemo_devicelist_request(barejid); g_hash_table_insert(omemo_ctx.device_list_handler, strdup(barejid), _handle_device_list_start_session); return; @@ -554,7 +555,7 @@ omemo_identity_keyfile_save(void) GError* error = NULL; if (!g_key_file_save_to_file(omemo_ctx.identity_keyfile, omemo_ctx.identity_filename->str, &error)) { - log_error("OMEMO: error saving identity to: %s, %s", omemo_ctx.identity_filename->str, error->message); + log_error("[OMEMO] error saving identity to: %s, %s", omemo_ctx.identity_filename->str, error->message); } } @@ -570,7 +571,7 @@ omemo_trust_keyfile_save(void) GError* error = NULL; if (!g_key_file_save_to_file(omemo_ctx.trust_keyfile, omemo_ctx.trust_filename->str, &error)) { - log_error("OMEMO: error saving trust to: %s, %s", omemo_ctx.trust_filename->str, error->message); + log_error("[OMEMO] error saving trust to: %s, %s", omemo_ctx.trust_filename->str, error->message); } } @@ -586,7 +587,7 @@ omemo_sessions_keyfile_save(void) GError* error = NULL; if (!g_key_file_save_to_file(omemo_ctx.sessions_keyfile, omemo_ctx.sessions_filename->str, &error)) { - log_error("OMEMO: error saving sessions to: %s, %s", omemo_ctx.sessions_filename->str, error->message); + log_error("[OMEMO] error saving sessions to: %s, %s", omemo_ctx.sessions_filename->str, error->message); } } @@ -596,7 +597,7 @@ omemo_known_devices_keyfile_save(void) GError* error = NULL; if (!g_key_file_save_to_file(omemo_ctx.known_devices_keyfile, omemo_ctx.known_devices_filename->str, &error)) { - log_error("OMEMO: error saving known devices to: %s, %s", omemo_ctx.known_devices_filename->str, error->message); + log_error("[OMEMO] error saving known devices to: %s, %s", omemo_ctx.known_devices_filename->str, error->message); } } @@ -636,7 +637,7 @@ omemo_start_device_session(const char* const jid, uint32_t device_id, session_builder* builder; res = session_builder_create(&builder, omemo_ctx.store, address, omemo_ctx.signal); if (res != 0) { - log_error("OMEMO: cannot create session builder for %s device %d", jid, device_id); + log_error("[OMEMO] cannot create session builder for %s device %d", jid, device_id); goto out; } @@ -652,17 +653,17 @@ omemo_start_device_session(const char* const jid, uint32_t device_id, res = session_pre_key_bundle_create(&bundle, 0, device_id, prekey->id, prekey_public, signed_prekey_id, signed_prekey, signature, signature_len, identity_key); if (res != 0) { - log_error("OMEMO: cannot create pre key bundle for %s device %d", jid, device_id); + log_error("[OMEMO] cannot create pre key bundle for %s device %d", jid, device_id); goto out; } res = session_builder_process_pre_key_bundle(builder, bundle); if (res != 0) { - log_error("OMEMO: cannot process pre key bundle for %s device %d", jid, device_id); + log_error("[OMEMO] cannot process pre key bundle for %s device %d", jid, device_id); goto out; } - log_info("OMEMO: create session with %s device %d", jid, device_id); + log_info("[OMEMO] create session with %s device %d", jid, device_id); } out: @@ -695,7 +696,7 @@ omemo_on_message_send(ProfWin* win, const char* const message, gboolean request_ res = aes128gcm_encrypt(ciphertext, &ciphertext_len, tag, &tag_len, (const unsigned char* const)message, strlen(message), iv, key); if (res != 0) { - log_error("OMEMO: cannot encrypt message"); + log_error("[OMEMO] cannot encrypt message"); goto out; } @@ -729,7 +730,7 @@ omemo_on_message_send(ProfWin* win, const char* const message, gboolean request_ GList* recipient_device_id = NULL; recipient_device_id = g_hash_table_lookup(omemo_ctx.device_list, recipients_iter->data); if (!recipient_device_id) { - log_warning("OMEMO: cannot find device ids for %s", recipients_iter->data); + log_warning("[OMEMO] cannot find device ids for %s", recipients_iter->data); continue; } @@ -745,14 +746,14 @@ omemo_on_message_send(ProfWin* win, const char* const message, gboolean request_ res = session_cipher_create(&cipher, omemo_ctx.store, &address, omemo_ctx.signal); if (res != 0) { - log_error("OMEMO: cannot create cipher for %s device id %d", address.name, address.device_id); + log_error("[OMEMO] cannot create cipher for %s device id %d", address.name, address.device_id); continue; } res = session_cipher_encrypt(cipher, key_tag, AES128_GCM_KEY_LENGTH + AES128_GCM_TAG_LENGTH, &ciphertext); session_cipher_free(cipher); if (res != 0) { - log_error("OMEMO: cannot encrypt key for %s device id %d", address.name, address.device_id); + log_error("[OMEMO] cannot encrypt key for %s device id %d", address.name, address.device_id); continue; } signal_buffer* buffer = ciphertext_message_get_serialized(ciphertext); @@ -783,14 +784,14 @@ omemo_on_message_send(ProfWin* win, const char* const message, gboolean request_ res = session_cipher_create(&cipher, omemo_ctx.store, &address, omemo_ctx.signal); if (res != 0) { - log_error("OMEMO: cannot create cipher for %s device id %d", address.name, address.device_id); + log_error("[OMEMO] cannot create cipher for %s device id %d", address.name, address.device_id); continue; } res = session_cipher_encrypt(cipher, key_tag, AES128_GCM_KEY_LENGTH + AES128_GCM_TAG_LENGTH, &ciphertext); session_cipher_free(cipher); if (res != 0) { - log_error("OMEMO: cannot encrypt key for %s device id %d", address.name, address.device_id); + log_error("[OMEMO] cannot encrypt key for %s device id %d", address.name, address.device_id); continue; } signal_buffer* buffer = ciphertext_message_get_serialized(ciphertext); @@ -851,7 +852,7 @@ omemo_on_message_recv(const char* const from_jid, uint32_t sid, } if (!key) { - log_warning("OMEMO: received a message with no corresponding key"); + log_warning("[OMEMO] received a message with no corresponding key"); goto out; } @@ -867,7 +868,7 @@ omemo_on_message_recv(const char* const from_jid, uint32_t sid, } g_list_free(roster); if (!sender) { - log_warning("OMEMO: cannot find MUC message sender fulljid"); + log_warning("[OMEMO] cannot find MUC message sender fulljid"); goto out; } } else { @@ -884,12 +885,12 @@ omemo_on_message_recv(const char* const from_jid, uint32_t sid, res = session_cipher_create(&cipher, omemo_ctx.store, &address, omemo_ctx.signal); if (res != 0) { - log_error("OMEMO: cannot create session cipher"); + log_error("[OMEMO] cannot create session cipher"); goto out; } if (key->prekey) { - log_debug("OMEMO: decrypting message with prekey"); + log_debug("[OMEMO] decrypting message with prekey"); pre_key_signal_message* message; ec_public_key* their_identity_key; signal_buffer* identity_buffer = NULL; @@ -925,13 +926,13 @@ omemo_on_message_recv(const char* const from_jid, uint32_t sid, omemo_bundle_request(sender->barejid, sid, omemo_start_device_session_handle_bundle, free, strdup(sender->barejid)); } } else { - log_debug("OMEMO: decrypting message with existing session"); + log_debug("[OMEMO] decrypting message with existing session"); signal_message* message = NULL; res = signal_message_deserialize(&message, key->data, key->length, omemo_ctx.signal); if (res < 0) { - log_error("OMEMO: cannot deserialize message"); + log_error("[OMEMO] cannot deserialize message"); } else { res = session_cipher_decrypt_signal_message(cipher, message, NULL, &plaintext_key); *trusted = true; @@ -941,12 +942,12 @@ omemo_on_message_recv(const char* const from_jid, uint32_t sid, session_cipher_free(cipher); if (res != 0) { - log_error("OMEMO: cannot decrypt message key"); + log_error("[OMEMO] cannot decrypt message key"); goto out; } if (signal_buffer_len(plaintext_key) != AES128_GCM_KEY_LENGTH + AES128_GCM_TAG_LENGTH) { - log_error("OMEMO: invalid key length"); + log_error("[OMEMO] invalid key length"); signal_buffer_free(plaintext_key); goto out; } @@ -958,7 +959,7 @@ omemo_on_message_recv(const char* const from_jid, uint32_t sid, signal_buffer_data(plaintext_key) + AES128_GCM_KEY_LENGTH); signal_buffer_free(plaintext_key); if (res != 0) { - log_error("OMEMO: cannot decrypt message: %s", gcry_strerror(res)); + log_error("[OMEMO] cannot decrypt message: %s", gcry_strerror(res)); free(plaintext); plaintext = NULL; goto out; @@ -1132,7 +1133,7 @@ omemo_trust(const char* const jid, const char* const fingerprint_formatted) GHashTable* known_identities = g_hash_table_lookup(omemo_ctx.known_devices, jid); if (!known_identities) { - log_warning("OMEMO: cannot trust unknown device: %s", fingerprint_formatted); + log_warning("[OMEMO] cannot trust unknown device: %s", fingerprint_formatted); cons_show("Cannot trust unknown device: %s", fingerprint_formatted); return; } @@ -1143,7 +1144,7 @@ omemo_trust(const char* const jid, const char* const fingerprint_formatted) free(fingerprint); if (!device_id) { - log_warning("OMEMO: cannot trust unknown device: %s", fingerprint_formatted); + log_warning("[OMEMO] cannot trust unknown device: %s", fingerprint_formatted); cons_show("Cannot trust unknown device: %s", fingerprint_formatted); return; } @@ -1200,13 +1201,13 @@ omemo_untrust(const char* const jid, const char* const fingerprint_formatted) /* Remove existing session */ GHashTable* known_identities = g_hash_table_lookup(omemo_ctx.known_devices, jid); if (!known_identities) { - log_error("OMEMO: cannot find known device while untrusting a fingerprint"); + log_error("[OMEMO] cannot find known device while untrusting a fingerprint"); goto out; } uint32_t device_id = GPOINTER_TO_INT(g_hash_table_lookup(known_identities, fingerprint)); if (!device_id) { - log_error("OMEMO: cannot find device id while untrusting a fingerprint"); + log_error("[OMEMO] cannot find device id while untrusting a fingerprint"); goto out; } signal_protocol_address address = { @@ -1246,17 +1247,17 @@ _omemo_log(int level, const char* message, size_t len, void* user_data) { switch (level) { case SG_LOG_ERROR: - log_error("OMEMO: %s", message); + log_error("[OMEMO] %s", message); break; case SG_LOG_WARNING: - log_warning("OMEMO: %s", message); + log_warning("[OMEMO] %s", message); break; case SG_LOG_NOTICE: case SG_LOG_INFO: - log_info("OMEMO: %s", message); + log_info("[OMEMO] %s", message); break; case SG_LOG_DEBUG: - log_debug("OMEMO: %s", message); + log_debug("[OMEMO] %s", message); break; } } @@ -1393,16 +1394,16 @@ _load_identity(void) error = NULL; omemo_ctx.device_id = g_key_file_get_uint64(omemo_ctx.identity_keyfile, OMEMO_STORE_GROUP_IDENTITY, OMEMO_STORE_KEY_DEVICE_ID, &error); if (error != NULL) { - log_error("OMEMO: cannot load device id: %s", error->message); + log_error("[OMEMO] cannot load device id: %s", error->message); return FALSE; } - log_info("OMEMO: device id: %d", omemo_ctx.device_id); + log_info("[OMEMO] device id: %d", omemo_ctx.device_id); /* Registration ID */ error = NULL; omemo_ctx.registration_id = g_key_file_get_uint64(omemo_ctx.identity_keyfile, OMEMO_STORE_GROUP_IDENTITY, OMEMO_STORE_KEY_REGISTRATION_ID, &error); if (error != NULL) { - log_error("OMEMO: cannot load registration id: %s", error->message); + log_error("[OMEMO] cannot load registration id: %s", error->message); return FALSE; } @@ -1410,7 +1411,7 @@ _load_identity(void) error = NULL; char* identity_key_public_b64 = g_key_file_get_string(omemo_ctx.identity_keyfile, OMEMO_STORE_GROUP_IDENTITY, OMEMO_STORE_KEY_IDENTITY_KEY_PUBLIC, &error); if (!identity_key_public_b64) { - log_error("OMEMO: cannot load identity public key: %s", error->message); + log_error("[OMEMO] cannot load identity public key: %s", error->message); return FALSE; } @@ -1422,7 +1423,7 @@ _load_identity(void) error = NULL; char* identity_key_private_b64 = g_key_file_get_string(omemo_ctx.identity_keyfile, OMEMO_STORE_GROUP_IDENTITY, OMEMO_STORE_KEY_IDENTITY_KEY_PRIVATE, &error); if (!identity_key_private_b64) { - log_error("OMEMO: cannot load identity private key: %s", error->message); + log_error("[OMEMO] cannot load identity private key: %s", error->message); return FALSE; } @@ -1599,7 +1600,7 @@ _cache_device_identity(const char* const jid, uint32_t device_id, ec_public_key* } char* fingerprint = _omemo_fingerprint(identity, FALSE); - log_info("OMEMO: cache identity for %s:%d: %s", jid, device_id, fingerprint); + log_info("[OMEMO] cache identity for %s:%d: %s", jid, device_id, fingerprint); g_hash_table_insert(known_identities, strdup(fingerprint), GINT_TO_POINTER(device_id)); char* device_id_str = g_strdup_printf("%d", device_id); From 637c2c2d6202b6b6caaff65942be293e234fd9de Mon Sep 17 00:00:00 2001 From: Stefan Date: Sat, 6 Mar 2021 19:55:22 +0100 Subject: [PATCH 3/7] Logging [CONNECTION] --- src/xmpp/connection.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/xmpp/connection.c b/src/xmpp/connection.c index 0bcab020..d34f9a4f 100644 --- a/src/xmpp/connection.c +++ b/src/xmpp/connection.c @@ -454,6 +454,7 @@ connection_get_barejid(void) void connection_features_received(const char* const jid) { + log_info("[CONNECTION] connection_features_received %s", jid); if (g_hash_table_remove(conn.requested_features, jid) && g_hash_table_size(conn.requested_features) == 0) { sv_ev_connection_features_received(); } From 848169870569dab48a1ef7b2751d0e4b52e87e09 Mon Sep 17 00:00:00 2001 From: Maximilian Wuttke Date: Tue, 9 Mar 2021 17:47:27 +0100 Subject: [PATCH 4/7] Logging [OMEMO] --- src/xmpp/omemo.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/xmpp/omemo.c b/src/xmpp/omemo.c index e527d4c7..8058d8f2 100644 --- a/src/xmpp/omemo.c +++ b/src/xmpp/omemo.c @@ -89,6 +89,7 @@ omemo_devicelist_request(const char* const jid) void omemo_bundle_publish(gboolean first) { + log_info("[OMEMO] publish omemo bundle"); xmpp_ctx_t* const ctx = connection_get_ctx(); unsigned char* identity_key = NULL; size_t identity_key_length; @@ -459,7 +460,7 @@ _omemo_receive_devicelist(xmpp_stanza_t* const stanza, void* const userdata) if (current) { item = current; } else if (first) { - log_warning("OMEMO: User %s has a non 'current' device item list: %s.", from, xmpp_stanza_get_id(first)); + log_warning("[OMEMO] User %s has a non 'current' device item list: %s.", from, xmpp_stanza_get_id(first)); item = first; } else { return 1; @@ -480,7 +481,7 @@ _omemo_receive_devicelist(xmpp_stanza_t* const stanza, void* const userdata) if (id != NULL) { device_list = g_list_append(device_list, GINT_TO_POINTER(strtoul(id, NULL, 10))); } else { - log_error("OMEMO: received device without ID"); + log_error("[OMEMO] received device without ID"); } } @@ -495,19 +496,22 @@ _omemo_bundle_publish_result(xmpp_stanza_t* const stanza, void* const userdata) const char* type = xmpp_stanza_get_type(stanza); if (g_strcmp0(type, STANZA_TYPE_ERROR) != 0) { + log_error("[OMEMO] Error for bundle publish"); return 0; } if (!GPOINTER_TO_INT(userdata)) { - log_error("OMEMO: definitely cannot publish bundle with an open access model"); + log_error("[OMEMO] definitely cannot publish bundle with an open access model"); return 0; } - log_info("OMEMO: cannot publish bundle with open access model, trying to configure node"); + log_info("[OMEMO] cannot publish bundle with open access model, trying to configure node"); xmpp_ctx_t* const ctx = connection_get_ctx(); Jid* jid = jid_create(connection_get_fulljid()); char* id = connection_create_stanza_id(); char* node = g_strdup_printf("%s:%d", STANZA_NS_OMEMO_BUNDLES, omemo_device_id()); + log_info("[OMEMO] node: %s", node); + xmpp_stanza_t* iq = stanza_create_pubsub_configure_request(ctx, id, jid->barejid, node); g_free(node); @@ -532,7 +536,7 @@ _omemo_bundle_publish_configure(xmpp_stanza_t* const stanza, void* const userdat DataForm* form = form_create(x); char* tag = g_hash_table_lookup(form->var_to_tag, "pubsub#access_model"); if (!tag) { - log_info("OMEMO: cannot configure bundle to an open access model"); + log_error("[OMEMO] cannot configure bundle to an open access model"); return 0; } form_set_value(form, tag, "open"); @@ -560,7 +564,7 @@ _omemo_bundle_publish_configure_result(xmpp_stanza_t* const stanza, void* const const char* type = xmpp_stanza_get_type(stanza); if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) { - log_error("OMEMO: cannot configure bundle to an open access model"); + log_error("[OMEMO] cannot configure bundle to an open access model: Result error"); return 0; } From 412485610085fd4b521c9699a964eb6b39255c1c Mon Sep 17 00:00:00 2001 From: Maximilian Wuttke Date: Tue, 9 Mar 2021 17:47:37 +0100 Subject: [PATCH 5/7] Variadic version of `stanza_attach_publish_options` --- src/xmpp/stanza.c | 49 ++++++++++++++++++++++++++++++++--------------- src/xmpp/stanza.h | 4 +++- 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/src/xmpp/stanza.c b/src/xmpp/stanza.c index 06615aa9..2b39a023 100644 --- a/src/xmpp/stanza.c +++ b/src/xmpp/stanza.c @@ -1940,8 +1940,9 @@ stanza_get_error_message(xmpp_stanza_t* stanza) return strdup("unknown"); } +// Note that the `count' must be 2 * number of key/value pairs void -stanza_attach_publish_options(xmpp_ctx_t* const ctx, xmpp_stanza_t* const iq, const char* const option, const char* const value) +stanza_attach_publish_options_va(xmpp_ctx_t* const ctx, xmpp_stanza_t* const iq, int count, ...) { xmpp_stanza_t* publish_options = xmpp_stanza_new(ctx); xmpp_stanza_set_name(publish_options, STANZA_NAME_PUBLISH_OPTIONS); @@ -1964,23 +1965,34 @@ stanza_attach_publish_options(xmpp_ctx_t* const ctx, xmpp_stanza_t* const iq, co xmpp_stanza_add_child(form_type, form_type_value); xmpp_stanza_add_child(x, form_type); - xmpp_stanza_t* access_model = xmpp_stanza_new(ctx); - xmpp_stanza_set_name(access_model, STANZA_NAME_FIELD); - xmpp_stanza_set_attribute(access_model, STANZA_ATTR_VAR, option); - xmpp_stanza_t* access_model_value = xmpp_stanza_new(ctx); - xmpp_stanza_set_name(access_model_value, STANZA_NAME_VALUE); - xmpp_stanza_t* access_model_value_text = xmpp_stanza_new(ctx); - xmpp_stanza_set_text(access_model_value_text, value); - xmpp_stanza_add_child(access_model_value, access_model_value_text); - xmpp_stanza_add_child(access_model, access_model_value); - xmpp_stanza_add_child(x, access_model); - xmpp_stanza_t* pubsub = xmpp_stanza_get_child_by_ns(iq, STANZA_NS_PUBSUB); xmpp_stanza_add_child(pubsub, publish_options); - xmpp_stanza_release(access_model_value_text); - xmpp_stanza_release(access_model_value); - xmpp_stanza_release(access_model); + va_list ap; + va_start(ap, count); + int j; + for (j = 0; j < count; j += 2) { + const char* const option = va_arg(ap, char* const); + const char* const value = va_arg(ap, char* const); + + xmpp_stanza_t* field = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(field, STANZA_NAME_FIELD); + xmpp_stanza_set_attribute(field, STANZA_ATTR_VAR, option); + xmpp_stanza_t* field_value = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(field_value, STANZA_NAME_VALUE); + xmpp_stanza_t* field_value_text = xmpp_stanza_new(ctx); + xmpp_stanza_set_text(field_value_text, value); + xmpp_stanza_add_child(field_value, field_value_text); + xmpp_stanza_add_child(field, field_value); + xmpp_stanza_add_child(x, field); + + xmpp_stanza_release(field_value_text); + xmpp_stanza_release(field_value); + xmpp_stanza_release(field); + } + va_end(ap); + + xmpp_stanza_release(form_type_value_text); xmpp_stanza_release(form_type_value); xmpp_stanza_release(form_type); @@ -1988,6 +2000,13 @@ stanza_attach_publish_options(xmpp_ctx_t* const ctx, xmpp_stanza_t* const iq, co xmpp_stanza_release(publish_options); } +void +stanza_attach_publish_options(xmpp_ctx_t* const ctx, xmpp_stanza_t* const iq, const char* const option, const char* const value) +{ + stanza_attach_publish_options_va(ctx, iq, 2, option, value); +} + + void stanza_attach_priority(xmpp_ctx_t* const ctx, xmpp_stanza_t* const presence, const int pri) { diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h index e35b4bcc..a4ac6b33 100644 --- a/src/xmpp/stanza.h +++ b/src/xmpp/stanza.h @@ -326,7 +326,9 @@ xmpp_stanza_t* stanza_create_room_kick_iq(xmpp_ctx_t* const ctx, const char* con xmpp_stanza_t* stanza_create_command_exec_iq(xmpp_ctx_t* ctx, const char* const target, const char* const node); xmpp_stanza_t* stanza_create_command_config_submit_iq(xmpp_ctx_t* ctx, const char* const room, const char* const node, const char* const sessionid, DataForm* form); -void stanza_attach_publish_options(xmpp_ctx_t* const ctx, xmpp_stanza_t* const publish, const char* const option, const char* const value); +void stanza_attach_publish_options_va(xmpp_ctx_t* const ctx, xmpp_stanza_t* const iq, int count, ...); +void stanza_attach_publish_options(xmpp_ctx_t* const ctx, xmpp_stanza_t* const iq, const char* const option, const char* const value); + xmpp_stanza_t* stanza_create_omemo_devicelist_request(xmpp_ctx_t* ctx, const char* const id, const char* const jid); xmpp_stanza_t* stanza_create_omemo_devicelist_subscribe(xmpp_ctx_t* ctx, const char* const jid); From 68469149cd960a5a8fb9cd6ec4a5dd4ca139a4a7 Mon Sep 17 00:00:00 2001 From: Maximilian Wuttke Date: Tue, 9 Mar 2021 17:47:43 +0100 Subject: [PATCH 6/7] Logging [OMEMO] Also "handle" some errors in `_omemo_bundle_publish_configure` if the stanzas can't be found --- src/xmpp/omemo.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/xmpp/omemo.c b/src/xmpp/omemo.c index 8058d8f2..b51335b5 100644 --- a/src/xmpp/omemo.c +++ b/src/xmpp/omemo.c @@ -63,8 +63,11 @@ omemo_devicelist_publish(GList* device_list) xmpp_ctx_t* const ctx = connection_get_ctx(); xmpp_stanza_t* iq = stanza_create_omemo_devicelist_publish(ctx, device_list); + log_debug("[OMEMO] omemo_devicelist_publish()"); + if (connection_supports(XMPP_FEATURE_PUBSUB_PUBLISH_OPTIONS)) { stanza_attach_publish_options(ctx, iq, "pubsub#access_model", "open"); + // stanza_attach_publish_options(ctx, iq, "pubsub#max_items", "max"); } iq_send_stanza(iq); @@ -99,6 +102,8 @@ omemo_bundle_publish(gboolean first) size_t signed_prekey_signature_length; GList *prekeys = NULL, *ids = NULL, *lengths = NULL; + log_debug("OMEMO: omemo_bundle_publish()"); + omemo_identity_key(&identity_key, &identity_key_length); omemo_signed_prekey(&signed_prekey, &signed_prekey_length); omemo_signed_prekey_signature(&signed_prekey_signature, &signed_prekey_signature_length); @@ -493,6 +498,8 @@ _omemo_receive_devicelist(xmpp_stanza_t* const stanza, void* const userdata) static int _omemo_bundle_publish_result(xmpp_stanza_t* const stanza, void* const userdata) { + log_debug("[OMEMO] _omemo_bundle_publish_result()"); + const char* type = xmpp_stanza_get_type(stanza); if (g_strcmp0(type, STANZA_TYPE_ERROR) != 0) { @@ -510,14 +517,16 @@ _omemo_bundle_publish_result(xmpp_stanza_t* const stanza, void* const userdata) Jid* jid = jid_create(connection_get_fulljid()); char* id = connection_create_stanza_id(); char* node = g_strdup_printf("%s:%d", STANZA_NS_OMEMO_BUNDLES, omemo_device_id()); - log_info("[OMEMO] node: %s", node); + log_info("[OMEMO] node: %s", node); xmpp_stanza_t* iq = stanza_create_pubsub_configure_request(ctx, id, jid->barejid, node); g_free(node); iq_id_handler_add(id, _omemo_bundle_publish_configure, NULL, userdata); + log_debug("[OMEMO] _omemo_bundle_publish_result(): sending pubsub conf request"); iq_send_stanza(iq); + log_debug("[OMEMO] _omemo_bundle_publish_result(): sent pubsub conf request"); xmpp_stanza_release(iq); free(id); @@ -528,10 +537,24 @@ _omemo_bundle_publish_result(xmpp_stanza_t* const stanza, void* const userdata) static int _omemo_bundle_publish_configure(xmpp_stanza_t* const stanza, void* const userdata) { + log_debug("[OMEMO] _omemo_bundle_publish_configure()"); + /* TODO handle error */ xmpp_stanza_t* pubsub = xmpp_stanza_get_child_by_name(stanza, "pubsub"); + if (!pubsub) { + log_error("[OMEMO] The stanza doesn't contain a 'pubsub' child"); + return 0; + } xmpp_stanza_t* configure = xmpp_stanza_get_child_by_name(pubsub, STANZA_NAME_CONFIGURE); + if (!configure) { + log_error("[OMEMO] The stanza doesn't contain a 'configure' child"); + return 0; + } xmpp_stanza_t* x = xmpp_stanza_get_child_by_name(configure, "x"); + if (!x) { + log_error("[OMEMO] The stanza doesn't contain an 'x' child"); + return 0; + } DataForm* form = form_create(x); char* tag = g_hash_table_lookup(form->var_to_tag, "pubsub#access_model"); @@ -552,6 +575,8 @@ _omemo_bundle_publish_configure(xmpp_stanza_t* const stanza, void* const userdat iq_send_stanza(iq); + log_debug("[OMEMO] _omemo_bundle_publish_configure() done"); + xmpp_stanza_release(iq); free(id); jid_destroy(jid); From 2b1ada772256a9a661eabedf723702af5f6bfa83 Mon Sep 17 00:00:00 2001 From: Maximilian Wuttke Date: Tue, 9 Mar 2021 17:48:29 +0100 Subject: [PATCH 7/7] [OMEMO]: Fix bundle publishing Use the following options in `omemo_bundle_publish()`: - "pubsub#persist_items" = "true" - "pubsub#access_model" = "open" The same options are also used in Gajim. I've tested this on two different servers. The bundle was successfully added as a new PEP node. Test cases: 1. Normal use on my main account 2. Log in into a fresh tesst account on a different server 3. `/omemo clear_device_list`. In this case, the client(s) may have to be restarted. Note: In `_omemo_bundle_publish_result`, there's a route that is taken when the bundle publish stanza failed. In this case, the node is configured manually, i.e. the access_model is set to 'open'. I have manually tested this case, but this case didn't naturally occur for me. Note: The option "pubsub#max_items=max" is REQUIRED for the bundle publication, as per XEP-0384. However, this is not done in other clients (I've checked the source code of Gajim and Conversations), and it is also not supported by Prosody. Cf. . --- src/xmpp/omemo.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/xmpp/omemo.c b/src/xmpp/omemo.c index b51335b5..917e6f19 100644 --- a/src/xmpp/omemo.c +++ b/src/xmpp/omemo.c @@ -63,11 +63,10 @@ omemo_devicelist_publish(GList* device_list) xmpp_ctx_t* const ctx = connection_get_ctx(); xmpp_stanza_t* iq = stanza_create_omemo_devicelist_publish(ctx, device_list); - log_debug("[OMEMO] omemo_devicelist_publish()"); + log_info("[OMEMO] publish device list"); if (connection_supports(XMPP_FEATURE_PUBSUB_PUBLISH_OPTIONS)) { stanza_attach_publish_options(ctx, iq, "pubsub#access_model", "open"); - // stanza_attach_publish_options(ctx, iq, "pubsub#max_items", "max"); } iq_send_stanza(iq); @@ -80,6 +79,8 @@ omemo_devicelist_request(const char* const jid) xmpp_ctx_t* const ctx = connection_get_ctx(); char* id = connection_create_stanza_id(); + log_info("[OMEMO] request device list for jid: %s", jid); + xmpp_stanza_t* iq = stanza_create_omemo_devicelist_request(ctx, id, jid); iq_id_handler_add(id, _omemo_receive_devicelist, NULL, NULL); @@ -92,7 +93,7 @@ omemo_devicelist_request(const char* const jid) void omemo_bundle_publish(gboolean first) { - log_info("[OMEMO] publish omemo bundle"); + log_info("[OMEMO] publish own OMEMO bundle"); xmpp_ctx_t* const ctx = connection_get_ctx(); unsigned char* identity_key = NULL; size_t identity_key_length; @@ -102,8 +103,6 @@ omemo_bundle_publish(gboolean first) size_t signed_prekey_signature_length; GList *prekeys = NULL, *ids = NULL, *lengths = NULL; - log_debug("OMEMO: omemo_bundle_publish()"); - omemo_identity_key(&identity_key, &identity_key_length); omemo_signed_prekey(&signed_prekey, &signed_prekey_length); omemo_signed_prekey_signature(&signed_prekey_signature, &signed_prekey_signature_length); @@ -120,7 +119,10 @@ omemo_bundle_publish(gboolean first) g_list_free(ids); if (connection_supports(XMPP_FEATURE_PUBSUB_PUBLISH_OPTIONS)) { - stanza_attach_publish_options(ctx, iq, "pubsub#access_model", "open"); + stanza_attach_publish_options_va(ctx, iq, + 4, // 2 * number of key-value pairs + "pubsub#persist_items", "true", + "pubsub#access_model", "open"); } iq_id_handler_add(id, _omemo_bundle_publish_result, NULL, GINT_TO_POINTER(first)); @@ -140,6 +142,8 @@ omemo_bundle_request(const char* const jid, uint32_t device_id, ProfIqCallback f xmpp_ctx_t* const ctx = connection_get_ctx(); char* id = connection_create_stanza_id(); + log_info("[OMEMO] request omemo bundle (jid: %s, deivce: %d)", jid, device_id); + xmpp_stanza_t* iq = stanza_create_omemo_bundle_request(ctx, id, jid, device_id); iq_id_handler_add(id, func, free_func, userdata); @@ -495,6 +499,7 @@ _omemo_receive_devicelist(xmpp_stanza_t* const stanza, void* const userdata) return 1; } + static int _omemo_bundle_publish_result(xmpp_stanza_t* const stanza, void* const userdata) { @@ -502,8 +507,8 @@ _omemo_bundle_publish_result(xmpp_stanza_t* const stanza, void* const userdata) const char* type = xmpp_stanza_get_type(stanza); - if (g_strcmp0(type, STANZA_TYPE_ERROR) != 0) { - log_error("[OMEMO] Error for bundle publish"); + if (g_strcmp0(type, STANZA_TYPE_RESULT) == 0) { + log_info("[OMEMO] bundle published successfully"); return 0; } @@ -524,9 +529,7 @@ _omemo_bundle_publish_result(xmpp_stanza_t* const stanza, void* const userdata) iq_id_handler_add(id, _omemo_bundle_publish_configure, NULL, userdata); - log_debug("[OMEMO] _omemo_bundle_publish_result(): sending pubsub conf request"); iq_send_stanza(iq); - log_debug("[OMEMO] _omemo_bundle_publish_result(): sent pubsub conf request"); xmpp_stanza_release(iq); free(id); @@ -539,7 +542,6 @@ _omemo_bundle_publish_configure(xmpp_stanza_t* const stanza, void* const userdat { log_debug("[OMEMO] _omemo_bundle_publish_configure()"); - /* TODO handle error */ xmpp_stanza_t* pubsub = xmpp_stanza_get_child_by_name(stanza, "pubsub"); if (!pubsub) { log_error("[OMEMO] The stanza doesn't contain a 'pubsub' child"); @@ -562,7 +564,6 @@ _omemo_bundle_publish_configure(xmpp_stanza_t* const stanza, void* const userdat log_error("[OMEMO] cannot configure bundle to an open access model"); return 0; } - form_set_value(form, tag, "open"); xmpp_ctx_t* const ctx = connection_get_ctx(); Jid* jid = jid_create(connection_get_fulljid()); @@ -575,8 +576,6 @@ _omemo_bundle_publish_configure(xmpp_stanza_t* const stanza, void* const userdat iq_send_stanza(iq); - log_debug("[OMEMO] _omemo_bundle_publish_configure() done"); - xmpp_stanza_release(iq); free(id); jid_destroy(jid); @@ -593,6 +592,9 @@ _omemo_bundle_publish_configure_result(xmpp_stanza_t* const stanza, void* const return 0; } + log_info("[OMEMO] node configured"); + + // Try to publish again omemo_bundle_publish(TRUE); return 0;