--- a/libpurple/protocols/jabber/caps.c Fri Jun 30 17:31:16 2017 +0300 +++ b/libpurple/protocols/jabber/caps.c Fri Jun 30 17:36:48 2017 +0300 @@ -30,9 +30,6 @@ #include "util.h" #include "xdata.h" -#include "ciphers/md5hash.h" -#include "ciphers/sha1hash.h" - #define JABBER_CAPS_FILENAME "xmpp-caps.xml" typedef struct _JabberDataFormField { @@ -95,8 +92,8 @@ const JabberCapsTuple *name1 = v1; const JabberCapsTuple *name2 = v2; - return g_str_equal(name1->node, name2->node) && - g_str_equal(name1->ver, name2->ver) && + return purple_strequal(name1->node, name2->node) && + purple_strequal(name1->ver, name2->ver) && purple_strequal(name1->hash, name2->hash); } @@ -236,7 +233,7 @@ if(!capsdata) return; - if (!g_str_equal(capsdata->name, "capabilities")) { + if (!purple_strequal(capsdata->name, "capabilities")) { purple_xmlnode_free(capsdata); return; } @@ -244,7 +241,7 @@ for (client = capsdata->child; client; client = client->next) { if (client->type != PURPLE_XMLNODE_TYPE_TAG) continue; - if (g_str_equal(client->name, "client")) { + if (purple_strequal(client->name, "client")) { JabberCapsClientInfo *value = g_new0(JabberCapsClientInfo, 1); JabberCapsTuple *key = (JabberCapsTuple*)&value->tuple; PurpleXmlNode *child; @@ -260,12 +257,12 @@ for (child = client->child; child; child = child->next) { if (child->type != PURPLE_XMLNODE_TYPE_TAG) continue; - if (g_str_equal(child->name, "feature")) { + if (purple_strequal(child->name, "feature")) { const char *var = purple_xmlnode_get_attrib(child, "var"); if(!var) continue; value->features = g_list_append(value->features,g_strdup(var)); - } else if (g_str_equal(child->name, "identity")) { + } else if (purple_strequal(child->name, "identity")) { const char *category = purple_xmlnode_get_attrib(child, "category"); const char *type = purple_xmlnode_get_attrib(child, "type"); const char *name = purple_xmlnode_get_attrib(child, "name"); @@ -282,13 +279,13 @@ id->lang = g_strdup(lang); value->identities = g_list_append(value->identities,id); - } else if (g_str_equal(child->name, "x")) { + } else if (purple_strequal(child->name, "x")) { /* TODO: See #7814 -- this might cause problems if anyone * ever actually specifies forms. In fact, for this to * work properly, that bug needs to be fixed in * purple_xmlnode_from_str, not the output version... */ value->forms = g_list_append(value->forms, purple_xmlnode_copy(child)); - } else if (g_str_equal(child->name, "ext")) { + } else if (purple_strequal(child->name, "ext")) { if (key->hash != NULL) purple_debug_warning("jabber", "Ignoring exts when reading new-style caps\n"); else { @@ -303,7 +300,7 @@ for (node = child->child; node; node = node->next) { if (node->type != PURPLE_XMLNODE_TYPE_TAG) continue; - if (g_str_equal(node->name, "feature")) { + if (purple_strequal(node->name, "feature")) { const char *var = purple_xmlnode_get_attrib(node, "var"); if (!var) continue; @@ -361,7 +358,7 @@ for (i = 0; exts[i]; ++i) { /* Hack since we advertise the ext along with v1.5 caps but don't * store any exts */ - if (g_str_equal(exts[i], "voice-v1") && !info->exts) + if (purple_strequal(exts[i], "voice-v1") && !info->exts) continue; if (!info->exts || !g_hash_table_lookup(info->exts->exts, exts[i])) @@ -459,21 +456,22 @@ /* Only validate if these are v1.5 capabilities */ if (userdata->hash) { gchar *hash = NULL; - PurpleHash *hasher = NULL; - /* - * TODO: If you add *any* hash here, make sure the checksum buffer - * size in jabber_caps_calculate_hash is large enough. The cipher API - * doesn't seem to offer a "Get the hash size" function(?). - */ - if (g_str_equal(userdata->hash, "sha-1")) { - hasher = purple_sha1_hash_new(); - } else if (g_str_equal(userdata->hash, "md5")) { - hasher = purple_md5_hash_new(); + GChecksumType hash_type; + gboolean supported_hash = TRUE; + + if (purple_strequal(userdata->hash, "sha-1")) { + hash_type = G_CHECKSUM_SHA1; + } else if (purple_strequal(userdata->hash, "md5")) { + hash_type = G_CHECKSUM_MD5; + } else { + supported_hash = FALSE; } - hash = jabber_caps_calculate_hash(info, hasher); - g_object_unref(hasher); - if (!hash || !g_str_equal(hash, userdata->ver)) { + if (supported_hash) { + hash = jabber_caps_calculate_hash(info, hash_type); + } + + if (!hash || !purple_strequal(hash, userdata->ver)) { purple_debug_warning("jabber", "Could not validate caps info from " "%s. Expected %s, got %s\n", purple_xmlnode_get_attrib(packet, "from"), @@ -742,7 +740,7 @@ PurpleXmlNode *child; JabberCapsClientInfo *info; - if (!query || !g_str_equal(query->name, "query") || + if (!query || !purple_strequal(query->name, "query") || !purple_strequal(query->xmlns, NS_DISCO_INFO)) return NULL; @@ -751,7 +749,7 @@ for(child = query->child; child; child = child->next) { if (child->type != PURPLE_XMLNODE_TYPE_TAG) continue; - if (g_str_equal(child->name, "identity")) { + if (purple_strequal(child->name, "identity")) { /* parse identity */ const char *category = purple_xmlnode_get_attrib(child, "category"); const char *type = purple_xmlnode_get_attrib(child, "type"); @@ -769,12 +767,12 @@ id->lang = g_strdup(lang); info->identities = g_list_append(info->identities, id); - } else if (g_str_equal(child->name, "feature")) { + } else if (purple_strequal(child->name, "feature")) { /* parse feature */ const char *var = purple_xmlnode_get_attrib(child, "var"); if (var) info->features = g_list_prepend(info->features, g_strdup(var)); - } else if (g_str_equal(child->name, "x")) { + } else if (purple_strequal(child->name, "x")) { if (purple_strequal(child->xmlns, "jabber:x:data")) { /* x-data form */ PurpleXmlNode *dataform = purple_xmlnode_copy(child); @@ -820,27 +818,29 @@ } static void -append_escaped_string(PurpleHash *hash, const gchar *str) +append_escaped_string(GChecksum *hash, const gchar *str) { g_return_if_fail(hash != NULL); if (str && *str) { char *tmp = g_markup_escape_text(str, -1); - purple_hash_append(hash, (const guchar *)tmp, strlen(tmp)); + g_checksum_update(hash, (const guchar *)tmp, -1); g_free(tmp); } - purple_hash_append(hash, (const guchar *)"<", 1); + g_checksum_update(hash, (const guchar *)"<", -1); } -gchar *jabber_caps_calculate_hash(JabberCapsClientInfo *info, PurpleHash *hash) +gchar *jabber_caps_calculate_hash(JabberCapsClientInfo *info, + GChecksumType hash_type) { + GChecksum *hash; GList *node; - guint8 checksum[20]; - gsize checksum_size = 20; - gboolean success; + guint8 *checksum; + gsize checksum_size; + gchar *ret; - if (!info || !hash) + if (!info) return NULL; /* sort identities, features and x-data forms */ @@ -848,6 +848,12 @@ info->features = g_list_sort(info->features, (GCompareFunc)strcmp); info->forms = g_list_sort(info->forms, jabber_xdata_compare); + hash = g_checksum_new(hash_type); + + if (hash == NULL) { + return NULL; + } + /* Add identities to the hash data */ for (node = info->identities; node; node = node->next) { JabberIdentity *id = (JabberIdentity*)node->data; @@ -865,7 +871,7 @@ tmp = g_strconcat(category, "/", type, "/", lang ? lang : "", "/", name ? name : "", "<", NULL); - purple_hash_append(hash, (const guchar *)tmp, strlen(tmp)); + g_checksum_update(hash, (const guchar *)tmp, -1); g_free(tmp); g_free(category); @@ -892,7 +898,7 @@ while (fields) { JabberDataFormField *field = (JabberDataFormField*)fields->data; - if (!g_str_equal(field->var, "FORM_TYPE")) { + if (!purple_strequal(field->var, "FORM_TYPE")) { /* Append the "var" attribute */ append_escaped_string(hash, field->var); /* Append <value/> elements' cdata */ @@ -914,16 +920,20 @@ } } + checksum_size = g_checksum_type_get_length(hash_type); + checksum = g_new(guint8, checksum_size); + /* generate hash */ - success = purple_hash_digest(hash, checksum, checksum_size); - checksum_size = purple_hash_get_digest_size(hash); + g_checksum_get_digest(hash, checksum, &checksum_size); - return (success ? purple_base64_encode(checksum, checksum_size) : NULL); + ret = g_base64_encode(checksum, checksum_size); + g_free(checksum); + + return ret; } void jabber_caps_calculate_own_hash(JabberStream *js) { JabberCapsClientInfo info; - PurpleHash *hasher; GList *iter = NULL; GList *features = NULL; @@ -954,9 +964,7 @@ info.forms = NULL; g_free(js->caps_hash); - hasher = purple_sha1_hash_new(); - js->caps_hash = jabber_caps_calculate_hash(&info, hasher); - g_object_unref(hasher); + js->caps_hash = jabber_caps_calculate_hash(&info, G_CHECKSUM_SHA1); g_list_free(info.identities); g_list_free(info.features); } @@ -976,7 +984,7 @@ for (node = accounts; node; node = node->next) { PurpleAccount *account = node->data; const char *protocol_id = purple_account_get_protocol_id(account); - if (g_str_equal("prpl-jabber", protocol_id) && purple_account_is_connected(account)) { + if (purple_strequal("prpl-jabber", protocol_id) && purple_account_is_connected(account)) { PurpleConnection *gc = purple_account_get_connection(account); jabber_presence_send(purple_connection_get_protocol_data(gc), TRUE); }