From ecb3e783b9fde0fc6164a8058531b0be54eb7ef0 Mon Sep 17 00:00:00 2001 From: fiaxh Date: Mon, 2 Sep 2019 15:39:06 +0200 Subject: Include data forms in entity capabilities hash computation --- xmpp-vala/src/module/xep/0004_data_forms.vala | 8 +++- .../src/module/xep/0115_entitiy_capabilities.vala | 48 ++++++++++++++++++++-- .../module/xep/0260_jingle_socks5_bytestreams.vala | 2 +- 3 files changed, 52 insertions(+), 6 deletions(-) diff --git a/xmpp-vala/src/module/xep/0004_data_forms.vala b/xmpp-vala/src/module/xep/0004_data_forms.vala index 9456197c..84d39eea 100644 --- a/xmpp-vala/src/module/xep/0004_data_forms.vala +++ b/xmpp-vala/src/module/xep/0004_data_forms.vala @@ -8,6 +8,7 @@ public class DataForm { public StanzaNode stanza_node { get; set; } public Gee.List fields = new ArrayList(); + public string? form_type = null; public XmppStream stream; public OnResult on_result; @@ -210,7 +211,12 @@ public class DataForm { case "fixed": fields.add(new FixedField(field_node)); break; case "hidden": - fields.add(new HiddenField.from_node(field_node)); break; + HiddenField field = new HiddenField.from_node(field_node); + if (field.var == "FORM_TYPE") { + this.form_type = field.get_value_string(); + break; + } + fields.add(field); break; case "jid-multi": fields.add(new JidMultiField(field_node)); break; case "list-single": diff --git a/xmpp-vala/src/module/xep/0115_entitiy_capabilities.vala b/xmpp-vala/src/module/xep/0115_entitiy_capabilities.vala index 75b87e38..b61a7f43 100644 --- a/xmpp-vala/src/module/xep/0115_entitiy_capabilities.vala +++ b/xmpp-vala/src/module/xep/0115_entitiy_capabilities.vala @@ -8,6 +8,7 @@ namespace Xmpp.Xep.EntityCapabilities { private string own_ver_hash; private Storage storage; + private Regex sha1_base64_regex = /^[A-Za-z0-9+\/]{27}=$/; public Module(Storage storage) { this.storage = storage; @@ -15,7 +16,7 @@ namespace Xmpp.Xep.EntityCapabilities { private string get_own_hash(XmppStream stream) { if (own_ver_hash == null) { - own_ver_hash = compute_hash(stream.get_module(ServiceDiscovery.Module.IDENTITY).identities, stream.get_flag(ServiceDiscovery.Flag.IDENTITY).features); + own_ver_hash = compute_hash(stream.get_module(ServiceDiscovery.Module.IDENTITY).identities, stream.get_flag(ServiceDiscovery.Flag.IDENTITY).features, new ArrayList()); } return own_ver_hash; } @@ -47,7 +48,7 @@ namespace Xmpp.Xep.EntityCapabilities { StanzaNode? c_node = presence.stanza.get_subnode("c", NS_URI); if (c_node != null) { string? ver_attribute = c_node.get_attribute("ver", NS_URI); - if (ver_attribute == null) return; + if (ver_attribute == null || !sha1_base64_regex.match(ver_attribute)) return; Gee.List capabilities = storage.get_features(ver_attribute); if (capabilities.size == 0) { stream.get_module(ServiceDiscovery.Module.IDENTITY).request_info(stream, presence.from, (stream, query_result) => { @@ -61,13 +62,19 @@ namespace Xmpp.Xep.EntityCapabilities { private void store_entity_result(XmppStream stream, string entity, ServiceDiscovery.InfoResult? query_result) { if (query_result == null) return; - if (compute_hash(query_result.identities, query_result.features) == entity) { + + Gee.List data_forms = new ArrayList(); + foreach (StanzaNode node in query_result.iq.stanza.get_deep_subnodes(ServiceDiscovery.NS_URI_INFO + ":query", DataForms.NS_URI + ":x")) { + data_forms.add(DataForms.DataForm.create_from_node(stream, node, (stream, node) => {})); + } + + if (compute_hash(query_result.identities, query_result.features, data_forms) == entity) { storage.store_features(entity, query_result.features); stream.get_flag(ServiceDiscovery.Flag.IDENTITY).set_entity_features(query_result.iq.from, query_result.features); } } - private static string compute_hash(Gee.List identities, Gee.List features) { + private static string compute_hash(Gee.List identities, Gee.List features, Gee.List data_forms) { identities.sort(compare_identities); features.sort(); @@ -82,6 +89,25 @@ namespace Xmpp.Xep.EntityCapabilities { s += feature + "<"; } + data_forms.sort(compare_data_forms); + foreach (DataForms.DataForm data_form in data_forms) { + if (data_form.form_type == null) { + // If [..] the FORM_TYPE field is not of type "hidden" or the form does not include a FORM_TYPE field, ignore the form but continue processing. (XEP-0115) + continue; + } + s += data_form.form_type + "<"; + + data_form.fields.sort(compare_data_fields); + foreach (DataForms.DataForm.Field field in data_form.fields) { + s += field.var + "<"; + Gee.List values = field.get_values(); + values.sort(); + foreach (string value in values) { + s += value + "<"; + } + } + } + Checksum c = new Checksum(ChecksumType.SHA1); c.update(s.data, -1); size_t size = 20; @@ -99,6 +125,20 @@ namespace Xmpp.Xep.EntityCapabilities { // TODO lang return 0; } + + private static int compare_data_forms(DataForms.DataForm a, DataForms.DataForm b) { + if (a.form_type != null && b.form_type != null) { + return a.form_type.collate(b.form_type); + } + return 0; + } + + private static int compare_data_fields(DataForms.DataForm.Field a, DataForms.DataForm.Field b) { + if (a.var != null && b.var != null) { + return a.var.collate(b.var); + } + return 0; + } } public interface Storage : Object { diff --git a/xmpp-vala/src/module/xep/0260_jingle_socks5_bytestreams.vala b/xmpp-vala/src/module/xep/0260_jingle_socks5_bytestreams.vala index e0542207..a5eb1250 100644 --- a/xmpp-vala/src/module/xep/0260_jingle_socks5_bytestreams.vala +++ b/xmpp-vala/src/module/xep/0260_jingle_socks5_bytestreams.vala @@ -470,7 +470,7 @@ class Parameters : Jingle.TransportParameters, Object { throw new IOError.PROXY_FAILED("wanted %02x for length, got %02x".printf(dstaddr.length, read_buffer[4])); } if (!bytes_equal(read_buffer[5:5+dstaddr.length], dstaddr.data)) { - string repr = ((string)read_buffer[5:5+dstaddr.length]).make_valid().escape(); + string repr = ((string)read_buffer[5:5+dstaddr.length]).escape(); // TODO call make_valid() once glib>=2.52 becomes widespread throw new IOError.PROXY_FAILED(@"wanted dstaddr $(dstaddr), got $(repr)"); } if (read_buffer[5+dstaddr.length] != 0x00 || read_buffer[5+dstaddr.length+1] != 0x00) { -- cgit v1.2.3-54-g00ecf