pidgin: d92e5065: Fix up the XMPP User Avatar SHA1 hashing...
rekkanoryo at pidgin.im
rekkanoryo at pidgin.im
Thu Dec 11 03:46:28 EST 2008
-----------------------------------------------------------------
Revision: d92e50656580c151c2dfbc58cc25da3be3b390b4
Ancestor: 0877e1f3bc6b944c67c5b352a8f04fddcb6c54e1
Author: paul at aurich.com
Date: 2008-12-11T08:08:02
Branch: im.pidgin.pidgin
URL: http://d.pidgin.im/viewmtn/revision/info/d92e50656580c151c2dfbc58cc25da3be3b390b4
Modified 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
ChangeLog:
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.
-------------- next part --------------
============================================================
--- ChangeLog d941afc72172e82da8d50685b6f77b2a2076b737
+++ ChangeLog cd26b03b11abdb2a6cd4261320c945cf29859286
@@ -46,6 +46,8 @@ version 2.5.3 (??/??/????):
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)
============================================================
--- libpurple/protocols/jabber/auth.c d75ceb2ff8ff43a28fbff6f6ed10961ee65c96e9
+++ libpurple/protocols/jabber/auth.c f2ff11e621fda2d79838697334eb2f0c82e114a8
@@ -613,9 +613,7 @@ static void auth_old_cb(JabberStream *js
} 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 @@ static void auth_old_cb(JabberStream *js
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);
============================================================
--- libpurple/protocols/jabber/buddy.c 5c155be406acbc3fc604806bbd0cc5b02884f101
+++ libpurple/protocols/jabber/buddy.c 2867b3f51329b7b20a8ee44d97879fb5242b9031
@@ -19,7 +19,6 @@
*
*/
#include "internal.h"
-#include "cipher.h"
#include "debug.h"
#include "imgstore.h"
#include "prpl.h"
@@ -451,9 +450,6 @@ void jabber_set_info(PurpleConnection *g
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,17 +469,8 @@ void jabber_set_info(PurpleConnection *g
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);
+ js->avatar_hash = jabber_calculate_data_sha1sum(avatar_data, avatar_len);
- 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);
-
xmlnode_insert_data(binval, enc, -1);
g_free(enc);
}
@@ -545,19 +532,9 @@ void jabber_set_buddy_icon(PurpleConnect
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 @@ static void jabber_vcard_parse(JabberStr
(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);
============================================================
--- libpurple/protocols/jabber/jutil.c 59fdee9620caa6845b0d9e8c206f328eb34e6136
+++ libpurple/protocols/jabber/jutil.c 6acada4142410f97e4e9887ac31e1ce6d4e575f7
@@ -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 @@ jabber_find_unnormalized_conv(const char
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);
+}
+
============================================================
--- libpurple/protocols/jabber/jutil.h febd712fa491d0cb59f5aea97d930405ea662706
+++ libpurple/protocols/jabber/jutil.h 0a047f7a52efe4f5972f05ce012bd7e636e344c3
@@ -42,4 +42,5 @@ PurpleConversation *jabber_find_unnormal
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_ */
============================================================
--- libpurple/protocols/jabber/presence.c ebb63e249f0ece723d0f1b7053b35eee7022a6fa
+++ libpurple/protocols/jabber/presence.c 48a8f3d90123149ab50561e55a5c4e317e4f4a64
@@ -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 @@ static void jabber_vcard_parse_avatar(Ja
(( (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);
}
}
============================================================
--- libpurple/protocols/jabber/si.c fe72d83ab5a71b250c2726d7016a5eed4455ba95
+++ libpurple/protocols/jabber/si.c 89f1f349908491771cadac3c2ba0fbf7c247688b
@@ -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 @@ static void jabber_si_bytestreams_attemp
{
JabberSIXfer *jsx = xfer->data;
JabberBytestreamsStreamhost *streamhost;
- char *dstaddr, *p;
- int i;
- unsigned char hashval[20];
JabberID *dstjid;
if(!jsx->streamhosts) {
@@ -221,6 +217,7 @@ static void jabber_si_bytestreams_attemp
/* 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 @@ static void jabber_si_bytestreams_attemp
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 @@ jabber_si_xfer_bytestreams_send_read_aga
{
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 @@ jabber_si_xfer_bytestreams_send_read_aga
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);
More information about the Commits
mailing list