From 46fe69de9b4049c5c4bf6fddb3dfba4480b13caa Mon Sep 17 00:00:00 2001 From: Paul Fariello Date: Tue, 6 Jul 2021 17:47:33 +0200 Subject: [PATCH 1/7] Ensure devicelist access model is configured before updating it --- src/omemo/omemo.c | 4 +- src/xmpp/omemo.c | 117 ++++++++++++++++++++++++++++++++++++---------- src/xmpp/omemo.h | 1 + 3 files changed, 97 insertions(+), 25 deletions(-) diff --git a/src/omemo/omemo.c b/src/omemo/omemo.c index 952fea89..05f543f6 100644 --- a/src/omemo/omemo.c +++ b/src/omemo/omemo.c @@ -386,10 +386,12 @@ omemo_publish_crypto_materials(void) char* barejid = connection_get_barejid(); + /* Ensure device list is properly configured */ + omemo_devicelist_configure_and_request(); + /* Ensure we get our current device list, and it gets updated with our * device_id */ g_hash_table_insert(omemo_ctx.device_list_handler, strdup(barejid), _handle_own_device_list); - omemo_devicelist_request(barejid); omemo_bundle_publish(true); diff --git a/src/xmpp/omemo.c b/src/xmpp/omemo.c index 54cd12ad..20bf251a 100644 --- a/src/xmpp/omemo.c +++ b/src/xmpp/omemo.c @@ -47,12 +47,13 @@ #include "omemo/omemo.h" static int _omemo_receive_devicelist(xmpp_stanza_t* const stanza, void* const userdata); +static int _omemo_devicelist_publish_result(xmpp_stanza_t* const stanza, void* const userdata); +static int _omemo_devicelist_configure(xmpp_stanza_t* const stanza, void* const userdata); +static int _omemo_devicelist_configure_result(xmpp_stanza_t* const stanza, void* const userdata); static int _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); static int _omemo_bundle_publish_configure_result(xmpp_stanza_t* const stanza, void* const userdata); -static int _omemo_device_list_publish_result(xmpp_stanza_t* const stanza, void* const userdata); - void omemo_devicelist_subscribe(void) { @@ -69,16 +70,30 @@ omemo_devicelist_publish(GList* device_list) log_debug("[OMEMO] publish device list"); - if (connection_supports(XMPP_FEATURE_PUBSUB_PUBLISH_OPTIONS)) { - stanza_attach_publish_options(ctx, iq, "pubsub#access_model", "open"); - } - - iq_id_handler_add(xmpp_stanza_get_id(iq), _omemo_device_list_publish_result, NULL, NULL); + iq_id_handler_add(xmpp_stanza_get_id(iq), _omemo_devicelist_publish_result, NULL, NULL); iq_send_stanza(iq); xmpp_stanza_release(iq); } +void +omemo_devicelist_configure_and_request(void) +{ + xmpp_ctx_t* const ctx = connection_get_ctx(); + char* id = connection_create_stanza_id(); + Jid* jid = jid_create(connection_get_fulljid()); + + xmpp_stanza_t* iq = stanza_create_pubsub_configure_request(ctx, id, jid->barejid, STANZA_NS_OMEMO_DEVICELIST); + + iq_id_handler_add(id, _omemo_devicelist_configure, NULL, NULL); + + iq_send_stanza(iq); + + xmpp_stanza_release(iq); + free(id); + jid_destroy(jid); +} + void omemo_devicelist_request(const char* const jid) { @@ -512,6 +527,76 @@ _omemo_receive_devicelist(xmpp_stanza_t* const stanza, void* const userdata) return 1; } +static int +_omemo_devicelist_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) { + cons_show_error("Unable to publish own OMEMO device list"); + log_error("[OMEMO] Publishing device list failed"); + return 0; + } + return 0; +} + +static int +_omemo_devicelist_configure(xmpp_stanza_t* const stanza, void* const userdata) +{ + log_debug("[OMEMO] _omemo_devicelist_configure()"); + + 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); + form_set_value(form, "pubsub#access_model", "open"); + + xmpp_ctx_t* const ctx = connection_get_ctx(); + Jid* jid = jid_create(connection_get_fulljid()); + char* id = connection_create_stanza_id(); + xmpp_stanza_t* iq = stanza_create_pubsub_configure_submit(ctx, id, jid->barejid, STANZA_NS_OMEMO_DEVICELIST, form); + + iq_id_handler_add(id, _omemo_devicelist_configure_result, NULL, NULL); + + iq_send_stanza(iq); + + xmpp_stanza_release(iq); + free(id); + jid_destroy(jid); + return 0; +} + +static int +_omemo_devicelist_configure_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] cannot configure device list to an open access model: Result error"); + return 0; + } + + log_debug("[OMEMO] node configured"); + + // Try to publish + char* barejid = connection_get_barejid(); + omemo_devicelist_request(barejid); + + return 0; +} + static int _omemo_bundle_publish_result(xmpp_stanza_t* const stanza, void* const userdata) @@ -572,11 +657,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_error("[OMEMO] cannot configure bundle to an open access model"); - return 0; - } + form_set_value(form, "pubsub#access_model", "open"); xmpp_ctx_t* const ctx = connection_get_ctx(); Jid* jid = jid_create(connection_get_fulljid()); @@ -612,15 +693,3 @@ _omemo_bundle_publish_configure_result(xmpp_stanza_t* const stanza, void* const return 0; } - -static int -_omemo_device_list_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) { - cons_show_error("Unable to publish own OMEMO device list"); - log_error("[OMEMO] Publishing device list failed"); - return 0; - } - return 0; -} diff --git a/src/xmpp/omemo.h b/src/xmpp/omemo.h index 31021ab4..9f29cb96 100644 --- a/src/xmpp/omemo.h +++ b/src/xmpp/omemo.h @@ -38,6 +38,7 @@ #include "xmpp/iq.h" void omemo_devicelist_subscribe(void); +void omemo_devicelist_configure_and_request(void); void omemo_devicelist_publish(GList* device_list); void omemo_devicelist_request(const char* const jid); void omemo_bundle_publish(gboolean first); From 0b6cf20183b07b8d3a9c09356e2365d4a21803f7 Mon Sep 17 00:00:00 2001 From: Paul Fariello Date: Wed, 18 Aug 2021 12:07:09 +0200 Subject: [PATCH 2/7] OMEMO: try device list creation and reconfigure on precondition-not-met --- src/omemo/omemo.c | 3 +-- src/xmpp/omemo.c | 30 ++++++++++++++++++++++++------ src/xmpp/stanza.h | 1 + 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/omemo/omemo.c b/src/omemo/omemo.c index 05f543f6..b5213d6a 100644 --- a/src/omemo/omemo.c +++ b/src/omemo/omemo.c @@ -386,12 +386,11 @@ omemo_publish_crypto_materials(void) char* barejid = connection_get_barejid(); - /* Ensure device list is properly configured */ - omemo_devicelist_configure_and_request(); /* Ensure we get our current device list, and it gets updated with our * device_id */ g_hash_table_insert(omemo_ctx.device_list_handler, strdup(barejid), _handle_own_device_list); + omemo_devicelist_request(barejid); omemo_bundle_publish(true); diff --git a/src/xmpp/omemo.c b/src/xmpp/omemo.c index 20bf251a..e0f79c9e 100644 --- a/src/xmpp/omemo.c +++ b/src/xmpp/omemo.c @@ -48,7 +48,7 @@ static int _omemo_receive_devicelist(xmpp_stanza_t* const stanza, void* const userdata); static int _omemo_devicelist_publish_result(xmpp_stanza_t* const stanza, void* const userdata); -static int _omemo_devicelist_configure(xmpp_stanza_t* const stanza, void* const userdata); +static int _omemo_devicelist_configure_submit(xmpp_stanza_t* const stanza, void* const userdata); static int _omemo_devicelist_configure_result(xmpp_stanza_t* const stanza, void* const userdata); static int _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); @@ -70,6 +70,10 @@ omemo_devicelist_publish(GList* device_list) log_debug("[OMEMO] publish device list"); + if (connection_supports(XMPP_FEATURE_PUBSUB_PUBLISH_OPTIONS)) { + stanza_attach_publish_options(ctx, iq, "pubsub#access_model", "open"); + } + iq_id_handler_add(xmpp_stanza_get_id(iq), _omemo_devicelist_publish_result, NULL, NULL); iq_send_stanza(iq); @@ -77,7 +81,7 @@ omemo_devicelist_publish(GList* device_list) } void -omemo_devicelist_configure_and_request(void) +omemo_devicelist_configure(void) { xmpp_ctx_t* const ctx = connection_get_ctx(); char* id = connection_create_stanza_id(); @@ -85,7 +89,7 @@ omemo_devicelist_configure_and_request(void) xmpp_stanza_t* iq = stanza_create_pubsub_configure_request(ctx, id, jid->barejid, STANZA_NS_OMEMO_DEVICELIST); - iq_id_handler_add(id, _omemo_devicelist_configure, NULL, NULL); + iq_id_handler_add(id, _omemo_devicelist_configure_submit, NULL, NULL); iq_send_stanza(iq); @@ -534,15 +538,29 @@ _omemo_devicelist_publish_result(xmpp_stanza_t* const stanza, void* const userda if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) { cons_show_error("Unable to publish own OMEMO device list"); log_error("[OMEMO] Publishing device list failed"); - return 0; + + xmpp_stanza_t *error = xmpp_stanza_get_child_by_name(stanza, "error"); + if (!error) { + log_error("[OMEMO] Missing error element in device list publication result"); + return 0; + } + + xmpp_stanza_t *pubsub_error = xmpp_stanza_get_child_by_ns(error, STANZA_NS_PUBSUB_ERROR); + if (!pubsub_error) { + return 0; + } + + if (g_strcmp0(xmpp_stanza_get_name(pubsub_error), "precondition-not-met") == 0) { + omemo_devicelist_configure(); + } } return 0; } static int -_omemo_devicelist_configure(xmpp_stanza_t* const stanza, void* const userdata) +_omemo_devicelist_configure_submit(xmpp_stanza_t* const stanza, void* const userdata) { - log_debug("[OMEMO] _omemo_devicelist_configure()"); + log_debug("[OMEMO] _omemo_devicelist_configure_submit()"); xmpp_stanza_t* pubsub = xmpp_stanza_get_child_by_name(stanza, "pubsub"); if (!pubsub) { diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h index 52008b1c..7a95629e 100644 --- a/src/xmpp/stanza.h +++ b/src/xmpp/stanza.h @@ -216,6 +216,7 @@ #define STANZA_NS_PUBSUB "http://jabber.org/protocol/pubsub" #define STANZA_NS_PUBSUB_OWNER "http://jabber.org/protocol/pubsub#owner" #define STANZA_NS_PUBSUB_EVENT "http://jabber.org/protocol/pubsub#event" +#define STANZA_NS_PUBSUB_ERROR "http://jabber.org/protocol/pubsub#error" #define STANZA_NS_CARBONS "urn:xmpp:carbons:2" #define STANZA_NS_HINTS "urn:xmpp:hints" #define STANZA_NS_FORWARD "urn:xmpp:forward:0" From d8cee98cc7ce1d76f340c0a24389b32689aea578 Mon Sep 17 00:00:00 2001 From: Paul Fariello Date: Wed, 18 Aug 2021 18:12:15 +0200 Subject: [PATCH 3/7] Create devicelist if it doesn't exists --- src/xmpp/omemo.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/xmpp/omemo.c b/src/xmpp/omemo.c index e0f79c9e..05882936 100644 --- a/src/xmpp/omemo.c +++ b/src/xmpp/omemo.c @@ -459,8 +459,25 @@ out: static int _omemo_receive_devicelist(xmpp_stanza_t* const stanza, void* const userdata) { - GList* device_list = NULL; const char* from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM); + const char* type = xmpp_stanza_get_type(stanza); + + GList* device_list = NULL; + + if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) { + log_error("[OMEMO] can't get OMEMO device list"); + xmpp_stanza_t* error = xmpp_stanza_get_child_by_name(stanza, "error"); + if (!error) { + log_error("[OMEMO] missing error element in device list response"); + return 1; + } + + const char* code = xmpp_stanza_get_attribute(error, "code"); + if (g_strcmp0(code, "404") == 0) { + omemo_set_device_list(from, device_list); + return 1; + } + } xmpp_stanza_t* root = NULL; xmpp_stanza_t* event = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_PUBSUB_EVENT); From 4d93df4aba232c6999a8edd6fd0fbdc0174f9e07 Mon Sep 17 00:00:00 2001 From: Paul Fariello Date: Thu, 19 Aug 2021 09:57:19 +0200 Subject: [PATCH 4/7] OMEMO: Fix precondition-not-met handling --- src/xmpp/omemo.c | 19 ++++++++++++++----- src/xmpp/stanza.h | 2 +- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/xmpp/omemo.c b/src/xmpp/omemo.c index 05882936..3db6337d 100644 --- a/src/xmpp/omemo.c +++ b/src/xmpp/omemo.c @@ -474,8 +474,7 @@ _omemo_receive_devicelist(xmpp_stanza_t* const stanza, void* const userdata) const char* code = xmpp_stanza_get_attribute(error, "code"); if (g_strcmp0(code, "404") == 0) { - omemo_set_device_list(from, device_list); - return 1; + goto out; } } @@ -521,7 +520,7 @@ _omemo_receive_devicelist(xmpp_stanza_t* const stanza, void* const userdata) log_warning("[OMEMO] User %s has a non 'current' device item list: %s.", from, xmpp_stanza_get_id(first)); item = first; } else { - return 1; + goto out; } xmpp_stanza_t* list = xmpp_stanza_get_child_by_ns(item, STANZA_NS_OMEMO); @@ -543,6 +542,7 @@ _omemo_receive_devicelist(xmpp_stanza_t* const stanza, void* const userdata) } } +out: omemo_set_device_list(from, device_list); return 1; @@ -553,7 +553,6 @@ _omemo_devicelist_publish_result(xmpp_stanza_t* const stanza, void* const userda { const char* type = xmpp_stanza_get_type(stanza); if (g_strcmp0(type, STANZA_TYPE_ERROR) == 0) { - cons_show_error("Unable to publish own OMEMO device list"); log_error("[OMEMO] Publishing device list failed"); xmpp_stanza_t *error = xmpp_stanza_get_child_by_name(stanza, "error"); @@ -564,11 +563,21 @@ _omemo_devicelist_publish_result(xmpp_stanza_t* const stanza, void* const userda xmpp_stanza_t *pubsub_error = xmpp_stanza_get_child_by_ns(error, STANZA_NS_PUBSUB_ERROR); if (!pubsub_error) { + // TODO return 0; } if (g_strcmp0(xmpp_stanza_get_name(pubsub_error), "precondition-not-met") == 0) { - omemo_devicelist_configure(); + static gboolean reconfigured = false; + if (!reconfigured) { + reconfigured = true; + cons_show_error("Unable to publish own OMEMO device list, reconfiguring node"); + log_error("[OMEMO] Unable to publish own OMEMO device list, reconfiguring node"); + omemo_devicelist_configure(); + } else { + cons_show_error("Unable to publish own OMEMO device list, previous reconfiguration failed. Giving up."); + log_error("[OMEMO] Unable to publish own OMEMO device list, previous reconfiguration failed. Giving up."); + } } } return 0; diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h index 7a95629e..c58395bb 100644 --- a/src/xmpp/stanza.h +++ b/src/xmpp/stanza.h @@ -216,7 +216,7 @@ #define STANZA_NS_PUBSUB "http://jabber.org/protocol/pubsub" #define STANZA_NS_PUBSUB_OWNER "http://jabber.org/protocol/pubsub#owner" #define STANZA_NS_PUBSUB_EVENT "http://jabber.org/protocol/pubsub#event" -#define STANZA_NS_PUBSUB_ERROR "http://jabber.org/protocol/pubsub#error" +#define STANZA_NS_PUBSUB_ERROR "http://jabber.org/protocol/pubsub#errors" #define STANZA_NS_CARBONS "urn:xmpp:carbons:2" #define STANZA_NS_HINTS "urn:xmpp:hints" #define STANZA_NS_FORWARD "urn:xmpp:forward:0" From 6f33706e926406e12f6ac8aab94c0e5466250898 Mon Sep 17 00:00:00 2001 From: Paul Fariello Date: Fri, 20 Aug 2021 15:29:30 +0200 Subject: [PATCH 5/7] Cosmetic --- src/omemo/omemo.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/omemo/omemo.c b/src/omemo/omemo.c index b5213d6a..952fea89 100644 --- a/src/omemo/omemo.c +++ b/src/omemo/omemo.c @@ -386,7 +386,6 @@ omemo_publish_crypto_materials(void) char* barejid = connection_get_barejid(); - /* Ensure we get our current device list, and it gets updated with our * device_id */ g_hash_table_insert(omemo_ctx.device_list_handler, strdup(barejid), _handle_own_device_list); From 35814d8bd06bc49a59e92a676a55e579aaa7415c Mon Sep 17 00:00:00 2001 From: Paul Fariello Date: Fri, 20 Aug 2021 15:32:00 +0200 Subject: [PATCH 6/7] Log error received while publishing OMEMO device list --- src/xmpp/omemo.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/xmpp/omemo.c b/src/xmpp/omemo.c index 3db6337d..4114c4ea 100644 --- a/src/xmpp/omemo.c +++ b/src/xmpp/omemo.c @@ -563,7 +563,8 @@ _omemo_devicelist_publish_result(xmpp_stanza_t* const stanza, void* const userda xmpp_stanza_t *pubsub_error = xmpp_stanza_get_child_by_ns(error, STANZA_NS_PUBSUB_ERROR); if (!pubsub_error) { - // TODO + log_error("[OMEMO] Unknown error while publishing our own device list"); + cons_show_error("Unknown error while publishing our own device list"); return 0; } From 314d0034edf9065319388c388355076aa53d8346 Mon Sep 17 00:00:00 2001 From: Paul Fariello Date: Fri, 20 Aug 2021 15:33:31 +0200 Subject: [PATCH 7/7] Fix memleak --- src/xmpp/omemo.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/xmpp/omemo.c b/src/xmpp/omemo.c index 4114c4ea..549c88a6 100644 --- a/src/xmpp/omemo.c +++ b/src/xmpp/omemo.c @@ -639,6 +639,8 @@ _omemo_devicelist_configure_result(xmpp_stanza_t* const stanza, void* const user char* barejid = connection_get_barejid(); omemo_devicelist_request(barejid); + free(barejid); + return 0; }