From 562302846af07cb7b7bde894741840419a6b42dd Mon Sep 17 00:00:00 2001 From: Paul Fariello Date: Thu, 28 Mar 2019 23:30:28 +0100 Subject: [PATCH] Handle bundle publication error on publish-options We try to reconfigure node and publish again. If it fails again then we give up. --- src/omemo/omemo.c | 4 +- src/xmpp/omemo.c | 113 +++++++++++++++++++++++++++++++++++++++++----- src/xmpp/omemo.h | 2 +- src/xmpp/stanza.c | 65 ++++++++++++++++++++++---- src/xmpp/stanza.h | 7 ++- 5 files changed, 167 insertions(+), 24 deletions(-) diff --git a/src/omemo/omemo.c b/src/omemo/omemo.c index 9e46058e..580416f8 100644 --- a/src/omemo/omemo.c +++ b/src/omemo/omemo.c @@ -314,7 +314,7 @@ omemo_generate_short_term_crypto_materials(ProfAccount *account) g_hash_table_insert(omemo_ctx.device_list_handler, strdup(account->jid), handle_own_device_list); omemo_devicelist_request(account->jid); - omemo_bundle_publish(); + omemo_bundle_publish(true); } void @@ -791,7 +791,7 @@ omemo_on_message_recv(const char *const from_jid, uint32_t sid, SIGNAL_UNREF(new_pre_key); SIGNAL_UNREF(message); SIGNAL_UNREF(ec_pair); - omemo_bundle_publish(); + omemo_bundle_publish(true); if (res == 0) { /* Start a new session */ diff --git a/src/xmpp/omemo.c b/src/xmpp/omemo.c index 98509ff1..66b0ebcc 100644 --- a/src/xmpp/omemo.c +++ b/src/xmpp/omemo.c @@ -1,13 +1,18 @@ #include +#include "log.h" #include "xmpp/connection.h" -#include "xmpp/message.h" +#include "xmpp/form.h" #include "xmpp/iq.h" +#include "xmpp/message.h" #include "xmpp/stanza.h" #include "omemo/omemo.h" static int _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); +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); void omemo_devicelist_subscribe(void) @@ -45,7 +50,7 @@ omemo_devicelist_request(const char * const jid) } void -omemo_bundle_publish(void) +omemo_bundle_publish(gboolean first) { xmpp_ctx_t * const ctx = connection_get_ctx(); unsigned char *identity_key = NULL; @@ -61,10 +66,11 @@ omemo_bundle_publish(void) omemo_signed_prekey_signature(&signed_prekey_signature, &signed_prekey_signature_length); omemo_prekeys(&prekeys, &ids, &lengths); - xmpp_stanza_t *iq = stanza_create_omemo_bundle_publish(ctx, omemo_device_id(), - identity_key, identity_key_length, signed_prekey, signed_prekey_length, - signed_prekey_signature, signed_prekey_signature_length, - prekeys, ids, lengths); + char *id = connection_create_stanza_id("omemo_bundle_publish"); + xmpp_stanza_t *iq = stanza_create_omemo_bundle_publish(ctx, id, + omemo_device_id(), identity_key, identity_key_length, signed_prekey, + signed_prekey_length, signed_prekey_signature, + signed_prekey_signature_length, prekeys, ids, lengths); g_list_free_full(prekeys, free); g_list_free(lengths); @@ -72,12 +78,15 @@ omemo_bundle_publish(void) stanza_attach_publish_options(ctx, iq, "pubsub#access_model", "open"); - iq_send_stanza(iq); - xmpp_stanza_release(iq); + iq_id_handler_add(id, _omemo_bundle_publish_result, NULL, GINT_TO_POINTER(first)); + iq_send_stanza(iq); + + xmpp_stanza_release(iq); free(identity_key); free(signed_prekey); free(signed_prekey_signature); + free(id); } void @@ -322,19 +331,19 @@ _omemo_receive_devicelist(xmpp_stanza_t *const stanza, void *const userdata) } if (!root) { - return 1; + return 0; } xmpp_stanza_t *items = xmpp_stanza_get_child_by_name(root, "items"); if (!items) { - return 1; + return 0; } xmpp_stanza_t *item = xmpp_stanza_get_child_by_name(items, "item"); if (item) { xmpp_stanza_t *list = xmpp_stanza_get_child_by_ns(item, STANZA_NS_OMEMO); if (!list) { - return 1; + return 0; } xmpp_stanza_t *device; @@ -345,5 +354,85 @@ _omemo_receive_devicelist(xmpp_stanza_t *const stanza, void *const userdata) } omemo_set_device_list(from, device_list); - return 1; + return 0; +} + +static int +_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) { + return 0; + } + + if (!GPOINTER_TO_INT(userdata)) { + 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"); + xmpp_ctx_t * const ctx = connection_get_ctx(); + Jid *jid = jid_create(connection_get_fulljid()); + char *id = connection_create_stanza_id("omemo_bundle_node_configure_request"); + char *node = g_strdup_printf("%s:%d", STANZA_NS_OMEMO_BUNDLES, omemo_device_id()); + 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); + + iq_send_stanza(iq); + + xmpp_stanza_release(iq); + free(id); + jid_destroy(jid); + return 0; +} + +static int +_omemo_bundle_publish_configure(xmpp_stanza_t *const stanza, void *const userdata) +{ + /* TODO handle error */ + xmpp_stanza_t *pubsub = xmpp_stanza_get_child_by_name(stanza, "pubsub"); + xmpp_stanza_t *configure = xmpp_stanza_get_child_by_name(pubsub, STANZA_NAME_CONFIGURE); + xmpp_stanza_t *x = xmpp_stanza_get_child_by_name(configure, "x"); + + 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"); + return 0; + } + form_set_value(form, tag, "open"); + + xmpp_ctx_t * const ctx = connection_get_ctx(); + Jid *jid = jid_create(connection_get_fulljid()); + char *id = connection_create_stanza_id("omemo_bundle_node_configure_submit"); + char *node = g_strdup_printf("%s:%d", STANZA_NS_OMEMO_BUNDLES, omemo_device_id()); + xmpp_stanza_t *iq = stanza_create_pubsub_configure_submit(ctx, id, jid->barejid, node, form); + g_free(node); + + iq_id_handler_add(id, _omemo_bundle_publish_configure_result, NULL, userdata); + + iq_send_stanza(iq); + + xmpp_stanza_release(iq); + free(id); + jid_destroy(jid); + return 0; +} + +static int +_omemo_bundle_publish_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 bundle to an open access model"); + return 0; + } + + omemo_bundle_publish(TRUE); + + return 0; } diff --git a/src/xmpp/omemo.h b/src/xmpp/omemo.h index 81c3b979..f1fff7b7 100644 --- a/src/xmpp/omemo.h +++ b/src/xmpp/omemo.h @@ -5,7 +5,7 @@ void omemo_devicelist_subscribe(void); void omemo_devicelist_publish(GList *device_list); void omemo_devicelist_request(const char * const jid); -void omemo_bundle_publish(void); +void omemo_bundle_publish(gboolean first); void omemo_bundle_request(const char * const jid, uint32_t device_id, ProfIqCallback func, ProfIqFreeCallback free_func, void *userdata); int omemo_start_device_session_handle_bundle(xmpp_stanza_t *const stanza, void *const userdata); char * omemo_receive_message(xmpp_stanza_t *const stanza); diff --git a/src/xmpp/stanza.c b/src/xmpp/stanza.c index b6992e82..f4fd8aa8 100644 --- a/src/xmpp/stanza.c +++ b/src/xmpp/stanza.c @@ -2156,7 +2156,7 @@ stanza_create_omemo_devicelist_request(xmpp_ctx_t *ctx, const char *const id, xmpp_stanza_t *items = xmpp_stanza_new(ctx); xmpp_stanza_set_name(items, "items"); - xmpp_stanza_set_attribute(items, "node", STANZA_NS_OMEMO_DEVICELIST); + xmpp_stanza_set_attribute(items, STANZA_ATTR_NODE, STANZA_NS_OMEMO_DEVICELIST); xmpp_stanza_add_child(pubsub, items); xmpp_stanza_add_child(iq, pubsub); @@ -2180,7 +2180,7 @@ stanza_create_omemo_devicelist_subscribe(xmpp_ctx_t *ctx, const char *const jid) xmpp_stanza_t *subscribe = xmpp_stanza_new(ctx); xmpp_stanza_set_name(subscribe, STANZA_NAME_SUBSCRIBE); - xmpp_stanza_set_attribute(subscribe, "node", STANZA_NS_OMEMO_DEVICELIST); + xmpp_stanza_set_attribute(subscribe, STANZA_ATTR_NODE, STANZA_NS_OMEMO_DEVICELIST); xmpp_stanza_set_attribute(subscribe, "jid", jid); xmpp_stanza_add_child(pubsub, subscribe); @@ -2205,7 +2205,7 @@ stanza_create_omemo_devicelist_publish(xmpp_ctx_t *ctx, GList *const ids) xmpp_stanza_t *publish = xmpp_stanza_new(ctx); xmpp_stanza_set_name(publish, STANZA_NAME_PUBLISH); - xmpp_stanza_set_attribute(publish, "node", STANZA_NS_OMEMO_DEVICELIST); + xmpp_stanza_set_attribute(publish, STANZA_ATTR_NODE, STANZA_NS_OMEMO_DEVICELIST); xmpp_stanza_t *item = xmpp_stanza_new(ctx); xmpp_stanza_set_name(item, STANZA_NAME_ITEM); @@ -2241,15 +2241,14 @@ stanza_create_omemo_devicelist_publish(xmpp_ctx_t *ctx, GList *const ids) } xmpp_stanza_t* -stanza_create_omemo_bundle_publish(xmpp_ctx_t *ctx, uint32_t device_id, +stanza_create_omemo_bundle_publish(xmpp_ctx_t *ctx, const char *const id, + uint32_t device_id, const unsigned char * const identity_key, size_t identity_key_length, const unsigned char * const signed_prekey, size_t signed_prekey_length, const unsigned char * const signed_prekey_signature, size_t signed_prekey_signature_length, GList *const prekeys, GList *const prekeys_id, GList *const prekeys_length) { - char *id = connection_create_stanza_id("omemo_bundle_publish"); xmpp_stanza_t *iq = xmpp_iq_new(ctx, STANZA_TYPE_SET, id); - free(id); xmpp_stanza_t *pubsub = xmpp_stanza_new(ctx); xmpp_stanza_set_name(pubsub, STANZA_NAME_PUBSUB); @@ -2258,7 +2257,7 @@ stanza_create_omemo_bundle_publish(xmpp_ctx_t *ctx, uint32_t device_id, xmpp_stanza_t *publish = xmpp_stanza_new(ctx); xmpp_stanza_set_name(publish, STANZA_NAME_PUBLISH); char *node = g_strdup_printf("%s:%d", "eu.siacs.conversations.axolotl.bundles", device_id); - xmpp_stanza_set_attribute(publish, "node", node); + xmpp_stanza_set_attribute(publish, STANZA_ATTR_NODE, node); g_free(node); xmpp_stanza_t *item = xmpp_stanza_new(ctx); @@ -2356,7 +2355,7 @@ stanza_create_omemo_bundle_request(xmpp_ctx_t *ctx, const char *const id, const xmpp_stanza_t *items = xmpp_stanza_new(ctx); xmpp_stanza_set_name(items, "items"); char *node = g_strdup_printf("%s:%d", STANZA_NS_OMEMO_BUNDLES, device_id); - xmpp_stanza_set_attribute(items, "node", node); + xmpp_stanza_set_attribute(items, STANZA_ATTR_NODE, node); g_free(node); xmpp_stanza_add_child(pubsub, items); @@ -2368,6 +2367,56 @@ stanza_create_omemo_bundle_request(xmpp_ctx_t *ctx, const char *const id, const return iq; } +xmpp_stanza_t* +stanza_create_pubsub_configure_request(xmpp_ctx_t *ctx, const char *const id, const char *const jid, const char *const node) +{ + xmpp_stanza_t *iq = xmpp_iq_new(ctx, STANZA_TYPE_GET, id); + xmpp_stanza_set_to(iq, jid); + + xmpp_stanza_t *pubsub = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(pubsub, STANZA_NAME_PUBSUB); + xmpp_stanza_set_ns(pubsub, STANZA_NS_PUBSUB_OWNER); + + xmpp_stanza_t *configure = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(configure, STANZA_NAME_CONFIGURE); + xmpp_stanza_set_attribute(configure, STANZA_ATTR_NODE, node); + + xmpp_stanza_add_child(pubsub, configure); + xmpp_stanza_add_child(iq, pubsub); + + xmpp_stanza_release(configure); + xmpp_stanza_release(pubsub); + + return iq; +} + +xmpp_stanza_t* +stanza_create_pubsub_configure_submit(xmpp_ctx_t *ctx, const char *const id, const char *const jid, const char *const node, DataForm *form) +{ + xmpp_stanza_t *iq = xmpp_iq_new(ctx, STANZA_TYPE_SET, id); + xmpp_stanza_set_to(iq, jid); + + xmpp_stanza_t *pubsub = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(pubsub, STANZA_NAME_PUBSUB); + xmpp_stanza_set_ns(pubsub, STANZA_NS_PUBSUB_OWNER); + + xmpp_stanza_t *configure = xmpp_stanza_new(ctx); + xmpp_stanza_set_name(configure, STANZA_NAME_CONFIGURE); + xmpp_stanza_set_attribute(configure, STANZA_ATTR_NODE, node); + + xmpp_stanza_t *x = form_create_submission(form); + + xmpp_stanza_add_child(configure, x); + xmpp_stanza_add_child(pubsub, configure); + xmpp_stanza_add_child(iq, pubsub); + + xmpp_stanza_release(x); + xmpp_stanza_release(configure); + xmpp_stanza_release(pubsub); + + return iq; +} + static void _stanza_add_unique_id(xmpp_stanza_t *stanza, char *prefix) { diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h index 2efb4cff..eaf76a27 100644 --- a/src/xmpp/stanza.h +++ b/src/xmpp/stanza.h @@ -101,6 +101,7 @@ #define STANZA_NAME_GET "get" #define STANZA_NAME_URL "url" #define STANZA_NAME_COMMAND "command" +#define STANZA_NAME_CONFIGURE "configure" // error conditions #define STANZA_NAME_BAD_REQUEST "bad-request" @@ -180,6 +181,7 @@ #define STANZA_NS_CONFERENCE "jabber:x:conference" #define STANZA_NS_CAPTCHA "urn:xmpp:captcha" #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_CARBONS "urn:xmpp:carbons:2" #define STANZA_NS_HINTS "urn:xmpp:hints" @@ -295,9 +297,12 @@ void stanza_attach_publish_options(xmpp_ctx_t *const ctx, xmpp_stanza_t *const p 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); xmpp_stanza_t* stanza_create_omemo_devicelist_publish(xmpp_ctx_t *ctx, GList *const ids); -xmpp_stanza_t* stanza_create_omemo_bundle_publish(xmpp_ctx_t *ctx, uint32_t device_id, const unsigned char * const identity_key, size_t identity_key_length, const unsigned char * const signed_prekey, size_t signed_prekey_length, const unsigned char * const signed_prekey_signature, size_t signed_prekey_signature_length, GList *const prekeys, GList *const prekeys_id, GList *const prekeys_length); +xmpp_stanza_t* stanza_create_omemo_bundle_publish(xmpp_ctx_t *ctx, const char *const id, uint32_t device_id, const unsigned char * const identity_key, size_t identity_key_length, const unsigned char * const signed_prekey, size_t signed_prekey_length, const unsigned char * const signed_prekey_signature, size_t signed_prekey_signature_length, GList *const prekeys, GList *const prekeys_id, GList *const prekeys_length); xmpp_stanza_t* stanza_create_omemo_bundle_request(xmpp_ctx_t *ctx, const char *const id, const char *const jid, uint32_t device_id); +xmpp_stanza_t* stanza_create_pubsub_configure_request(xmpp_ctx_t *ctx, const char *const id, const char *const jid, const char *const node); +xmpp_stanza_t* stanza_create_pubsub_configure_submit(xmpp_ctx_t *ctx, const char *const id, const char *const jid, const char *const node, DataForm *form); + int stanza_get_idle_time(xmpp_stanza_t *const stanza); void stanza_attach_priority(xmpp_ctx_t *const ctx, xmpp_stanza_t *const presence, const int pri);