Mercurial > pidgin.yaz
changeset 24641:61e0924de04a
Fix up the XMPP User Avatar SHA1 hashing so that we don't mess up the checksum
when bytes in the checksum start with 0 (for example, 430902... would become
4392...). Refs #7734, which has a second patch needing more detailed review.
committer: John Bailey <rekkanoryo@rekkanoryo.org>
author | Paul Aurich <paul@darkrain42.org> |
---|---|
date | Thu, 11 Dec 2008 08:08:02 +0000 |
parents | 915b1cafa3d1 |
children | e4b1ba7c351c |
files | ChangeLog libpurple/protocols/jabber/auth.c libpurple/protocols/jabber/buddy.c libpurple/protocols/jabber/jutil.c libpurple/protocols/jabber/jutil.h libpurple/protocols/jabber/presence.c libpurple/protocols/jabber/si.c |
diffstat | 7 files changed, 55 insertions(+), 80 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Thu Dec 11 07:38:20 2008 +0000 +++ b/ChangeLog Thu Dec 11 08:08:02 2008 +0000 @@ -46,6 +46,8 @@ wrong domain for his/her account. * Support new <metadata/> element to indicate no XEP-0084 User Avatar (Paul Aurich) + * Fix SHA1 avatar checksum errors that occur when one of the bytes in a + checksum begins with 0 (Paul Aurich) Zephyr: * Enable auto-reply, to emulate 'zaway' (Toby Schaffer)
--- a/libpurple/protocols/jabber/auth.c Thu Dec 11 07:38:20 2008 +0000 +++ b/libpurple/protocols/jabber/auth.c Thu Dec 11 08:08:02 2008 +0000 @@ -613,9 +613,7 @@ } else if(!strcmp(type, "result")) { query = xmlnode_get_child(packet, "query"); if(js->stream_id && xmlnode_get_child(query, "digest")) { - unsigned char hashval[20]; - char *s, h[41], *p; - int i; + char *s, *hash; iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:auth"); query = xmlnode_get_child(iq->node, "query"); @@ -626,14 +624,9 @@ x = xmlnode_new_child(query, "digest"); s = g_strdup_printf("%s%s", js->stream_id, pw); - - purple_cipher_digest_region("sha1", (guchar *)s, strlen(s), - sizeof(hashval), hashval, NULL); - - p = h; - for(i=0; i<20; i++, p+=2) - snprintf(p, 3, "%02x", hashval[i]); - xmlnode_insert_data(x, h, -1); + hash = jabber_calculate_data_sha1sum(s, strlen(s)); + xmlnode_insert_data(x, hash, -1); + g_free(hash); g_free(s); jabber_iq_set_callback(iq, auth_old_result_cb, NULL); jabber_iq_send(iq);
--- a/libpurple/protocols/jabber/buddy.c Thu Dec 11 07:38:20 2008 +0000 +++ b/libpurple/protocols/jabber/buddy.c Thu Dec 11 08:08:02 2008 +0000 @@ -19,7 +19,6 @@ * */ #include "internal.h" -#include "cipher.h" #include "debug.h" #include "imgstore.h" #include "prpl.h" @@ -451,9 +450,6 @@ gsize avatar_len; xmlnode *photo, *binval, *type; gchar *enc; - int i; - unsigned char hashval[20]; - char *p, hash[41]; if(!vc_node) { vc_node = xmlnode_new("vCard"); @@ -473,16 +469,7 @@ binval = xmlnode_new_child(photo, "BINVAL"); enc = purple_base64_encode(avatar_data, avatar_len); - purple_cipher_digest_region("sha1", avatar_data, - avatar_len, sizeof(hashval), - hashval, NULL); - - purple_imgstore_unref(img); - - p = hash; - for(i=0; i<20; i++, p+=2) - snprintf(p, 3, "%02x", hashval[i]); - js->avatar_hash = g_strdup(hash); + js->avatar_hash = jabber_calculate_data_sha1sum(avatar_data, avatar_len); xmlnode_insert_data(binval, enc, -1); g_free(enc); @@ -545,19 +532,9 @@ char *lengthstring, *widthstring, *heightstring; /* compute the sha1 hash */ - PurpleCipherContext *ctx; - unsigned char digest[20]; - char *hash; + char *hash = jabber_calculate_data_sha1sum(purple_imgstore_get_data(img), purple_imgstore_get_size(img)); char *base64avatar; - ctx = purple_cipher_context_new_by_name("sha1", NULL); - purple_cipher_context_append(ctx, purple_imgstore_get_data(img), purple_imgstore_get_size(img)); - purple_cipher_context_digest(ctx, sizeof(digest), digest, NULL); - purple_cipher_context_destroy(ctx); - - /* convert digest to a string */ - hash = g_strdup_printf("%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x",digest[0],digest[1],digest[2],digest[3],digest[4],digest[5],digest[6],digest[7],digest[8],digest[9],digest[10],digest[11],digest[12],digest[13],digest[14],digest[15],digest[16],digest[17],digest[18],digest[19]); - publish = xmlnode_new("publish"); xmlnode_set_attrib(publish,"node",AVATARNAMESPACEDATA); @@ -1407,31 +1384,25 @@ (bintext = xmlnode_get_data(child))) { gsize size; guchar *data; - int i; - unsigned char hashval[20]; - char *p, hash[41]; gboolean photo = (strcmp(child->name, "PHOTO") == 0); data = purple_base64_decode(bintext, &size); if (data) { char *img_text; + char *hash; jbi->vcard_imgids = g_slist_prepend(jbi->vcard_imgids, GINT_TO_POINTER(purple_imgstore_add_with_id(g_memdup(data, size), size, "logo.png"))); img_text = g_strdup_printf("<img id='%d'>", GPOINTER_TO_INT(jbi->vcard_imgids->data)); purple_notify_user_info_add_pair(user_info, (photo ? _("Photo") : _("Logo")), img_text); - purple_cipher_digest_region("sha1", (guchar *)data, size, - sizeof(hashval), hashval, NULL); - p = hash; - for(i=0; i<20; i++, p+=2) - snprintf(p, 3, "%02x", hashval[i]); - + hash = jabber_calculate_data_sha1sum(data, size); purple_buddy_icons_set_for_user(js->gc->account, bare_jid, data, size, hash); - g_free(bintext); + g_free(hash); g_free(img_text); } + g_free(bintext); } } g_free(text);
--- a/libpurple/protocols/jabber/jutil.c Thu Dec 11 07:38:20 2008 +0000 +++ b/libpurple/protocols/jabber/jutil.c Thu Dec 11 08:08:02 2008 +0000 @@ -20,7 +20,9 @@ */ #include "internal.h" #include "account.h" +#include "cipher.h" #include "conversation.h" +#include "debug.h" #include "server.h" #include "util.h" #include "xmlnode.h" @@ -236,3 +238,29 @@ return NULL; } +/* The same as purple_util_get_image_checksum, but guaranteed to remain SHA1 */ +char * +jabber_calculate_data_sha1sum(gconstpointer data, size_t len) +{ + PurpleCipherContext *context; + static gchar digest[41]; + + context = purple_cipher_context_new_by_name("sha1", NULL); + if (context == NULL) + { + purple_debug_error("jabber", "Could not find sha1 cipher\n"); + g_return_val_if_reached(NULL); + } + + /* Hash the data */ + purple_cipher_context_append(context, data, len); + if (!purple_cipher_context_digest_to_str(context, sizeof(digest), digest, NULL)) + { + purple_debug_error("jabber", "Failed to get SHA-1 digest.\n"); + g_return_val_if_reached(NULL); + } + purple_cipher_context_destroy(context); + + return g_strdup(digest); +} +
--- a/libpurple/protocols/jabber/jutil.h Thu Dec 11 07:38:20 2008 +0000 +++ b/libpurple/protocols/jabber/jutil.h Thu Dec 11 08:08:02 2008 +0000 @@ -42,4 +42,5 @@ PurpleConversation *jabber_find_unnormalized_conv(const char *name, PurpleAccount *account); +char *jabber_calculate_data_sha1sum(gconstpointer data, size_t len); #endif /* _PURPLE_JABBER_JUTIL_H_ */
--- a/libpurple/protocols/jabber/presence.c Thu Dec 11 07:38:20 2008 +0000 +++ b/libpurple/protocols/jabber/presence.c Thu Dec 11 08:08:02 2008 +0000 @@ -21,7 +21,6 @@ #include "internal.h" #include "account.h" -#include "cipher.h" #include "conversation.h" #include "debug.h" #include "notify.h" @@ -349,19 +348,12 @@ (( (binval = xmlnode_get_child(photo, "BINVAL")) && (text = xmlnode_get_data(binval))) || (text = xmlnode_get_data(photo)))) { - unsigned char hashval[20]; - char hash[41], *p; - int i; + char *hash; data = purple_base64_decode(text, &size); - - purple_cipher_digest_region("sha1", data, size, - sizeof(hashval), hashval, NULL); - p = hash; - for(i=0; i<20; i++, p+=2) - snprintf(p, 3, "%02x", hashval[i]); - + hash = jabber_calculate_data_sha1sum(data, size); purple_buddy_icons_set_for_user(js->gc->account, from, data, size, hash); + g_free(hash); g_free(text); } }
--- a/libpurple/protocols/jabber/si.c Thu Dec 11 07:38:20 2008 +0000 +++ b/libpurple/protocols/jabber/si.c Thu Dec 11 08:08:02 2008 +0000 @@ -23,7 +23,6 @@ #include "internal.h" #include "blist.h" -#include "cipher.h" #include "debug.h" #include "ft.h" #include "request.h" @@ -183,9 +182,6 @@ { JabberSIXfer *jsx = xfer->data; JabberBytestreamsStreamhost *streamhost; - char *dstaddr, *p; - int i; - unsigned char hashval[20]; JabberID *dstjid; if(!jsx->streamhosts) { @@ -221,6 +217,7 @@ /* TODO: Deal with zeroconf */ if(dstjid != NULL && streamhost->host && streamhost->port > 0) { + char *dstaddr, *hash; jsx->gpi = purple_proxy_info_new(); purple_proxy_info_set_type(jsx->gpi, PURPLE_PROXY_SOCKS5); purple_proxy_info_set_host(jsx->gpi, streamhost->host); @@ -234,17 +231,13 @@ dstaddr = g_strdup_printf("%s%s@%s/%s%s@%s/%s", jsx->stream_id, dstjid->node, dstjid->domain, dstjid->resource, jsx->js->user->node, jsx->js->user->domain, jsx->js->user->resource); - purple_cipher_digest_region("sha1", (guchar *)dstaddr, strlen(dstaddr), - sizeof(hashval), hashval, NULL); - g_free(dstaddr); - dstaddr = g_malloc(41); - p = dstaddr; - for(i=0; i<20; i++, p+=2) - snprintf(p, 3, "%02x", hashval[i]); + /* Per XEP-0065, the 'host' must be SHA1(SID + from JID + to JID) */ + hash = jabber_calculate_data_sha1sum(dstaddr, strlen(dstaddr)); jsx->connect_data = purple_proxy_connect_socks5(NULL, jsx->gpi, - dstaddr, 0, + hash, 0, jabber_si_bytestreams_connect_cb, xfer); + g_free(hash); g_free(dstaddr); /* When selecting a streamhost, timeout after STREAMHOST_CONNECT_TIMEOUT seconds, otherwise it takes forever */ @@ -361,11 +354,9 @@ { PurpleXfer *xfer = data; JabberSIXfer *jsx = xfer->data; - int i; char buffer[256]; int len; - char *dstaddr, *p; - unsigned char hashval[20]; + char *dstaddr, *hash; const char *host; purple_debug_info("jabber", "in jabber_si_xfer_bytestreams_send_read_again_cb\n"); @@ -421,23 +412,20 @@ jsx->js->user->node, jsx->js->user->domain, jsx->js->user->resource, xfer->who); - purple_cipher_digest_region("sha1", (guchar *)dstaddr, strlen(dstaddr), - sizeof(hashval), hashval, NULL); - g_free(dstaddr); - dstaddr = g_malloc(41); - p = dstaddr; - for(i=0; i<20; i++, p+=2) - snprintf(p, 3, "%02x", hashval[i]); + /* Per XEP-0065, the 'host' must be SHA1(SID + from JID + to JID) */ + hash = jabber_calculate_data_sha1sum(dstaddr, strlen(dstaddr)); - if(jsx->rxqueue[4] != 40 || strncmp(dstaddr, jsx->rxqueue+5, 40) || + if(jsx->rxqueue[4] != 40 || strncmp(hash, jsx->rxqueue+5, 40) || jsx->rxqueue[45] != 0x00 || jsx->rxqueue[46] != 0x00) { purple_debug_error("jabber", "someone connected with the wrong info!\n"); close(source); purple_xfer_cancel_remote(xfer); + g_free(hash); g_free(dstaddr); return; } + g_free(hash); g_free(dstaddr); g_free(jsx->rxqueue);