pidgin.2.5.7: 85b74016: *** Plucked rev d0e53002eb30c6dbf9735ca5...

rekkanoryo at pidgin.im rekkanoryo at pidgin.im
Fri Jun 19 17:40:44 EDT 2009


-----------------------------------------------------------------
Revision: 85b7401615acafde6e25abdfe4fa536d8db7fb99
Ancestor: 8c0d4e373d8ccb0a601421c161181cc86dd135ab
Author: rekkanoryo at pidgin.im
Date: 2009-06-19T00:56:37
Branch: im.pidgin.pidgin.2.5.7
URL: http://d.pidgin.im/viewmtn/revision/info/85b7401615acafde6e25abdfe4fa536d8db7fb99

Deleted entries:
        libpurple/protocols/yahoo/yahoo_auth.c
        libpurple/protocols/yahoo/yahoo_auth.h
        libpurple/protocols/yahoo/yahoo_crypt.c
        libpurple/protocols/yahoo/yahoo_crypt.h
Modified files:
        ChangeLog configure.ac libpurple/protocols/yahoo/Makefile.am
        libpurple/protocols/yahoo/Makefile.mingw
        libpurple/protocols/yahoo/yahoo.c
        libpurple/protocols/yahoo/yahoo.h
        libpurple/protocols/yahoo/yahoo_doodle.c
        libpurple/protocols/yahoo/yahoo_packet.h

ChangeLog: 

*** Plucked rev d0e53002eb30c6dbf9735ca50784d42141dfc96a (sulabh at soc.pidgin.im):
Yahoo version 16 login. ---yet to do: prevent password from being displayed in debug logs---

*** Plucked rev 398170eb3baade1ddeeca492dbb74d023c6d8a27 (sulabh at soc.pidgin.im):
Inform user that he wont be able to use Yahoo! in case of absence of ssl 
support

*** Backported rev a6ccff1d5368c712499f9b2f3671fa017f8efca2 (rekkanoryo at pidgin.im):
Support logging into Yahoo! Japan with protocol 16.  It seems not to care
what version bytes are sent once you use the right URL's to log in.

Also changelogged the fact that we have support for Yahoo 16 login.

-------------- next part --------------
============================================================
--- ChangeLog	390d732443c519c8dc4b758bc96a8f0255a37ede
+++ ChangeLog	b7caaa4f1cadea41b4071f2c4e3c49e45a0454e0
@@ -1,6 +1,9 @@ version 2.5.7 (06/18/2009):
 Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul
 
 version 2.5.7 (06/18/2009):
+	* Yahoo Protocol 16 support, including new HTTPS login method; this should
+	  fix a number of login problems that have recently cropped up.  (Sulabh
+	  Mahajan, Mike "Maiku" Ruprecht)
 
 version 2.5.6 (05/19/2009):
 	libpurple:
============================================================
--- configure.ac	08b8d7677c79b14bfdb6571d31cea97573450015
+++ configure.ac	62f547d4296fe5e862cb31146176c25396da8f7a
@@ -1616,7 +1616,7 @@ AC_ARG_ENABLE(nss,
 	[enable_nss="$enableval"],
 	[enable_nss="yes"])
 
-msg_ssl="None. MSN, Novell Groupwise and Google Talk will not work without GnuTLS or NSS. OpenSSL is NOT usable!"
+msg_ssl="None. MSN, Novell Groupwise, Yahoo! and Google Talk will not work without GnuTLS or NSS. OpenSSL is NOT usable!"
 looked_for_gnutls="no"
 dnl #
 dnl # Check for GnuTLS if it's specified.
============================================================
--- libpurple/protocols/yahoo/Makefile.am	eaf9c3dc7fa9d6426f3911a238c9bc6c39ad806a
+++ libpurple/protocols/yahoo/Makefile.am	aabcd64b33d9f8ef54737c57e6c2a4b440b8b43b
@@ -11,10 +11,6 @@ YAHOOSOURCES = \
 	yahoochat.c \
 	yahoo_aliases.c \
 	yahoo_aliases.h \
-	yahoo_auth.c \
-	yahoo_auth.h \
-	yahoo_crypt.h \
-	yahoo_crypt.c \
 	yahoo_doodle.h \
 	yahoo_doodle.c \
 	yahoo_filexfer.h \
============================================================
--- libpurple/protocols/yahoo/Makefile.mingw	7484dd539cfd2f0ce6bd8202f9c2aece4af99fab
+++ libpurple/protocols/yahoo/Makefile.mingw	ea2b65dfce8eb07ef7176b059f599ab6c4c69192
@@ -41,8 +41,6 @@ C_SRC =			util.c \
 			yahoo.c \
 			yahoochat.c \
 			yahoo_aliases.c \
-			yahoo_auth.c \
-			yahoo_crypt.c \
 			yahoo_doodle.c \
 			yahoo_filexfer.c \
 			yahoo_friend.c \
============================================================
--- libpurple/protocols/yahoo/yahoo.c	03c184f4f1a7af6b30ab3b17e3ce1522420dec22
+++ libpurple/protocols/yahoo/yahoo.c	5eac78df860e361fab0cdad9a6579fecaec537f8
@@ -42,8 +42,6 @@
 #include "yahoo.h"
 #include "yahoochat.h"
 #include "yahoo_aliases.h"
-#include "yahoo_auth.h"
-#include "yahoo_crypt.h"
 #include "yahoo_doodle.h"
 #include "yahoo_filexfer.h"
 #include "yahoo_friend.h"
@@ -1340,11 +1338,19 @@ static void yahoo_process_mail(PurpleCon
 						   NULL, NULL);
 	}
 }
+
+/* We use this structure once while we authenticate */
+struct yahoo_auth_data
+{
+	PurpleConnection *gc;
+	char *seed;
+};
+
 /* This is the y64 alphabet... it's like base64, but has a . and a _ */
 static const char base64digits[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._";
 
-/* This is taken from Sylpheed by Hiroyuki Yamamoto.  We have our own tobase64 function
- * in util.c, but it has a bug I don't feel like finding right now ;) */
+/* This is taken from Sylpheed by Hiroyuki Yamamoto. We have our own tobase64 function
+ * in util.c, but it is different from the one yahoo uses */
 static void to_y64(char *out, const unsigned char *in, gsize inlen)
      /* raw bytes in quasi-big-endian order to base 64 string (NUL-terminated) */
 {
@@ -1371,605 +1377,261 @@ static void to_y64(char *out, const unsi
 	*out = '\0';
 }
 
-static void yahoo_process_auth_old(PurpleConnection *gc, const char *seed)
+static void yahoo_auth16_stage3(PurpleConnection *gc, char *crypt)
 {
-	struct yahoo_packet *pack;
+	struct yahoo_data *yd = gc->proto_data;
 	PurpleAccount *account = purple_connection_get_account(gc);
 	const char *name = purple_normalize(account, purple_account_get_username(account));
-	const char *pass = purple_connection_get_password(gc);
-	struct yahoo_data *yd = gc->proto_data;
+	PurpleCipher *md5_cipher;
+	PurpleCipherContext *md5_ctx;
+	guchar md5_digest[16];
+	gchar base64_string[25];
+	struct yahoo_packet *pkt;
 
-	/* So, Yahoo has stopped supporting its older clients in India, and undoubtedly
-	 * will soon do so in the rest of the world.
-	 *
-	 * The new clients use this authentication method.  I warn you in advance, it's
-	 * bizarre, convoluted, inordinately complicated.  It's also no more secure than
-	 * crypt() was.  The only purpose this scheme could serve is to prevent third
-	 * party clients from connecting to their servers.
-	 *
-	 * Sorry, Yahoo.
-	 */
+	purple_debug_info("yahoo","Authentication: In yahoo_auth16_stage3\n");
 
-	PurpleCipher *cipher;
-	PurpleCipherContext *context;
-	guchar digest[16];
+	md5_cipher = purple_ciphers_find_cipher("md5");
+	md5_ctx = purple_cipher_context_new(md5_cipher, NULL);
+	purple_cipher_context_append(md5_ctx,(guchar *)crypt, strlen(crypt));
+	purple_cipher_context_digest(md5_ctx, sizeof(md5_digest),md5_digest, NULL);
 
-	char *crypt_result;
-	char password_hash[25];
-	char crypt_hash[25];
-	char *hash_string_p = g_malloc(50 + strlen(name));
-	char *hash_string_c = g_malloc(50 + strlen(name));
+	to_y64(base64_string, md5_digest, 16);
 
-	char checksum;
-
-	int sv;
-
-	char result6[25];
-	char result96[25];
-
-	sv = seed[15];
-	sv = sv % 8;
-
-	cipher = purple_ciphers_find_cipher("md5");
-	context = purple_cipher_context_new(cipher, NULL);
-
-	purple_cipher_context_append(context, (const guchar *)pass, strlen(pass));
-	purple_cipher_context_digest(context, sizeof(digest), digest, NULL);
-
-	to_y64(password_hash, digest, 16);
-
-	crypt_result = yahoo_crypt(pass, "$1$_2S43d5f$");
-
-	purple_cipher_context_reset(context, NULL);
-	purple_cipher_context_append(context, (const guchar *)crypt_result, strlen(crypt_result));
-	purple_cipher_context_digest(context, sizeof(digest), digest, NULL);
-	to_y64(crypt_hash, digest, 16);
-
-	switch (sv) {
-	case 1:
-	case 6:
-		checksum = seed[seed[9] % 16];
-		g_snprintf(hash_string_p, strlen(name) + 50,
-			   "%c%s%s%s", checksum, name, seed, password_hash);
-		g_snprintf(hash_string_c, strlen(name) + 50,
-			   "%c%s%s%s", checksum, name, seed, crypt_hash);
-		break;
-	case 2:
-	case 7:
-		checksum = seed[seed[15] % 16];
-		g_snprintf(hash_string_p, strlen(name) + 50,
-			   "%c%s%s%s", checksum, seed, password_hash, name);
-		g_snprintf(hash_string_c, strlen(name) + 50,
-			   "%c%s%s%s", checksum, seed, crypt_hash, name);
-		break;
-	case 3:
-		checksum = seed[seed[1] % 16];
-		g_snprintf(hash_string_p, strlen(name) + 50,
-			   "%c%s%s%s", checksum, name, password_hash, seed);
-		g_snprintf(hash_string_c, strlen(name) + 50,
-			   "%c%s%s%s", checksum, name, crypt_hash, seed);
-		break;
-	case 4:
-		checksum = seed[seed[3] % 16];
-		g_snprintf(hash_string_p, strlen(name) + 50,
-			   "%c%s%s%s", checksum, password_hash, seed, name);
-		g_snprintf(hash_string_c, strlen(name) + 50,
-			   "%c%s%s%s", checksum, crypt_hash, seed, name);
-		break;
-	case 0:
-	case 5:
-		checksum = seed[seed[7] % 16];
-			g_snprintf(hash_string_p, strlen(name) + 50,
-                                   "%c%s%s%s", checksum, password_hash, name, seed);
-                        g_snprintf(hash_string_c, strlen(name) + 50,
-				   "%c%s%s%s", checksum, crypt_hash, name, seed);
-			break;
-	}
-
-	purple_cipher_context_reset(context, NULL);
-	purple_cipher_context_append(context, (const guchar *)hash_string_p, strlen(hash_string_p));
-	purple_cipher_context_digest(context, sizeof(digest), digest, NULL);
-	to_y64(result6, digest, 16);
-
-	purple_cipher_context_reset(context, NULL);
-	purple_cipher_context_append(context, (const guchar *)hash_string_c, strlen(hash_string_c));
-	purple_cipher_context_digest(context, sizeof(digest), digest, NULL);
-	purple_cipher_context_destroy(context);
-	to_y64(result96, digest, 16);
-
-	pack = yahoo_packet_new(YAHOO_SERVICE_AUTHRESP,	YAHOO_STATUS_AVAILABLE, 0);
-
+	pkt = yahoo_packet_new(YAHOO_SERVICE_AUTHRESP, YAHOO_STATUS_WEBLOGIN, yd->session_id);
 	if(yd->jp) {
-		yahoo_packet_hash(pack, "sssss",
-						  0, name,
-						  6, result6,
-						  96, result96,
-						  1, name,
-						  135, YAHOOJP_CLIENT_VERSION);
-	} else {
-		yahoo_packet_hash(pack, "ssssss",
-						  0, name,
-						  6, result6,
-						  96, result96,
-						  1, name,
-						  244, YAHOO_CLIENT_VERSION_ID,
-						  135, YAHOO_CLIENT_VERSION);
+		yahoo_packet_hash(pkt, "ssssssss",
+					1, name,
+					0, name,
+					277, yd->cookie_y,
+					278, yd->cookie_t,
+					307, base64_string,
+					2, name,
+					2, "1",
+					135, YAHOOJP_CLIENT_VERSION);
+	} else	{
+		yahoo_packet_hash(pkt, "sssssssss",
+					1, name,
+					0, name,
+					277, yd->cookie_y,
+					278, yd->cookie_t,
+					307, base64_string,
+					244, YAHOO_CLIENT_VERSION_ID,
+					2, name,
+					2, "1",
+					135, YAHOO_CLIENT_VERSION);
 	}
+	if (yd->picture_checksum)
+		yahoo_packet_hash_int(pkt, 192, yd->picture_checksum);
+	yahoo_packet_send_and_free(pkt, yd);
 
-	yahoo_packet_send_and_free(pack, yd);
-
-	g_free(hash_string_p);
-	g_free(hash_string_c);
+	purple_cipher_context_destroy(md5_ctx);
+	g_free(crypt);	
 }
 
-/* I'm dishing out some uber-mad props to Cerulean Studios for cracking this
- * and sending the fix!  Thanks guys. */
-
-static void yahoo_process_auth_new(PurpleConnection *gc, const char *seed)
+static void yahoo_auth16_stage2(PurpleUtilFetchUrlData *url_data2, gpointer user_data, const gchar *ret_data, size_t len, const gchar *error_message)
 {
-	struct yahoo_packet *pack = NULL;
-	PurpleAccount *account = purple_connection_get_account(gc);
-	const char *name = purple_normalize(account, purple_account_get_username(account));
-	const char *pass = purple_connection_get_password(gc);
-	char *enc_pass;
-	struct yahoo_data *yd = gc->proto_data;
+	struct yahoo_auth_data *auth_data = user_data;
+	PurpleConnection *gc = auth_data->gc;
+	struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;
+	gchar **split_data = NULL;
+	int totalelements;
+	int response_no;
+	char *crumb = NULL;
+	char *error_reason = NULL;
+	char *crypt = NULL;
+	gboolean try_login_on_error = FALSE;
 
-	PurpleCipher		*md5_cipher;
-	PurpleCipherContext	*md5_ctx;
-	guchar				md5_digest[16];
+	purple_debug_info("yahoo","Authentication: In yahoo_auth16_stage2\n");
 
-	PurpleCipher		*sha1_cipher;
-	PurpleCipherContext	*sha1_ctx1;
-	PurpleCipherContext	*sha1_ctx2;
+	g_return_if_fail(PURPLE_CONNECTION_IS_VALID(gc));
 
-	char				*alphabet1			= "FBZDWAGHrJTLMNOPpRSKUVEXYChImkwQ";
-	char				*alphabet2			= "F0E1D2C3B4A59687abcdefghijklmnop";
-
-	char				*challenge_lookup	= "qzec2tb3um1olpar8whx4dfgijknsvy5";
-	char				*operand_lookup		= "+|&%/*^-";
-	char				*delimit_lookup		= ",;";
-
-	char				*password_hash		= (char *)g_malloc(25);
-	char				*crypt_hash			= (char *)g_malloc(25);
-	char				*crypt_result		= NULL;
-
-	unsigned char		pass_hash_xor1[64];
-	unsigned char		pass_hash_xor2[64];
-	unsigned char		crypt_hash_xor1[64];
-	unsigned char		crypt_hash_xor2[64];
-	char				resp_6[100];
-	char				resp_96[100];
-
-	unsigned char		digest1[20];
-	unsigned char		digest2[20];
-	unsigned char		comparison_src[20];
-	unsigned char		magic_key_char[4];
-	const char			*magic_ptr;
-
-	unsigned int		magic[64];
-	unsigned int		magic_work = 0;
-	unsigned int		magic_4 = 0;
-
-	int					x;
-	int					y;
-	int					cnt = 0;
-	int					magic_cnt = 0;
-	int					magic_len;
-
-	memset(password_hash, 0, 25);
-	memset(crypt_hash, 0, 25);
-	memset(&pass_hash_xor1, 0, 64);
-	memset(&pass_hash_xor2, 0, 64);
-	memset(&crypt_hash_xor1, 0, 64);
-	memset(&crypt_hash_xor2, 0, 64);
-	memset(&digest1, 0, 20);
-	memset(&digest2, 0, 20);
-	memset(&magic, 0, 64);
-	memset(&resp_6, 0, 100);
-	memset(&resp_96, 0, 100);
-	memset(&magic_key_char, 0, 4);
-	memset(&comparison_src, 0, 20);
-
-	md5_cipher = purple_ciphers_find_cipher("md5");
-	md5_ctx = purple_cipher_context_new(md5_cipher, NULL);
-
-	sha1_cipher = purple_ciphers_find_cipher("sha1");
-	sha1_ctx1 = purple_cipher_context_new(sha1_cipher, NULL);
-	sha1_ctx2 = purple_cipher_context_new(sha1_cipher, NULL);
-
-	/*
-	 * Magic: Phase 1.  Generate what seems to be a 30 byte value (could change if base64
-	 * ends up differently?  I don't remember and I'm tired, so use a 64 byte buffer.
-	 */
-
-	magic_ptr = seed;
-
-	while (*magic_ptr != '\0') {
-		char   *loc;
-
-		/* Ignore parentheses. */
-
-		if (*magic_ptr == '(' || *magic_ptr == ')') {
-			magic_ptr++;
-			continue;
+	if (error_message != NULL)	{
+		purple_debug_error("yahoo", "Login Failed, unable to retrieve stage 2 url: %s\n", error_message);
+		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, error_message);
+		g_free(auth_data->seed);
+		g_free(auth_data);	
+		return;
+	}
+	else if (len > 0 && ret_data && *ret_data) {
+		split_data = g_strsplit(ret_data, "\r\n", -1);
+		totalelements = g_strv_length(split_data);
+		if(totalelements >= 5)	{
+			response_no = strtol(*(split_data+1), NULL, 10);
+			crumb = g_strdup(*(split_data+2)+6);
+			yd->cookie_y = g_strdup(*(split_data+3)+2);
+			yd->cookie_t = g_strdup(*(split_data+4)+2);
 		}
+		else
+			response_no = -1;
 
-		/* Characters and digits verify against the challenge lookup. */
+		g_strfreev(split_data);
 
-		if (isalpha(*magic_ptr) || isdigit(*magic_ptr)) {
-			loc = strchr(challenge_lookup, *magic_ptr);
-			if (!loc) {
-			  /* SME XXX Error - disconnect here */
+		if(response_no != 0)	{
+			/* Some error in the login process */
+			PurpleConnectionError error;
+			switch(response_no)	{
+				case -1:
+					/* Some error in the received stream */
+					error_reason = g_strdup(_("Error in the received data"));
+					error = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
+					break;
+				case 100:
+					/* Unknown error */
+					error_reason = g_strdup(_("Unknown error"));
+					error = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
+					break;
+				default:
+					/* if we have everything we need, why not try to login irrespective of response */
+					if((crumb != NULL) && (yd->cookie_y != NULL) && (yd->cookie_t != NULL))	{
+						try_login_on_error = TRUE;
+						break;
+					}
+					error_reason = g_strdup(_("Unknown error"));
+					error = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
+					break;
 			}
-
-			/* Get offset into lookup table and shl 3. */
-
-			magic_work = loc - challenge_lookup;
-			magic_work <<= 3;
-
-			magic_ptr++;
-			continue;
-		} else {
-			unsigned int	local_store;
-
-			loc = strchr(operand_lookup, *magic_ptr);
-			if (!loc) {
-				/* SME XXX Disconnect */
+			if(error_reason)	{
+				purple_debug_error("yahoo","Authentication error: %s", error_reason);
+				purple_connection_error_reason(gc, error, error_reason);
+				g_free(error_reason);
 			}
-
-			local_store = loc - operand_lookup;
-
-			/* Oops; how did this happen? */
-
-			if (magic_cnt >= 64)
-				break;
-
-			magic[magic_cnt++] = magic_work | local_store;
-			magic_ptr++;
-			continue;
 		}
-			}
-
-	magic_len = magic_cnt;
-	magic_cnt = 0;
-
-	/* Magic: Phase 2.  Take generated magic value and sprinkle fairy
-	 * dust on the values.
-	 */
-
-	for (magic_cnt = magic_len - 2; magic_cnt >= 0; magic_cnt--) {
-		unsigned char	byte1;
-		unsigned char	byte2;
-
-		/* Bad.  Abort. */
-
-		if ((magic_cnt + 1 > magic_len) || (magic_cnt > magic_len))
-			break;
-
-		byte1 = magic[magic_cnt];
-		byte2 = magic[magic_cnt+1];
-
-		byte1 *= 0xcd;
-		byte1 ^= byte2;
-
-		magic[magic_cnt+1] = byte1;
+		if((response_no == 0) || try_login_on_error)	{
+			crypt = g_strconcat(crumb, auth_data->seed, NULL);
+			yahoo_auth16_stage3(gc, crypt);
+			g_free(crumb);
+		}
 	}
+	g_free(auth_data->seed);
+	g_free(auth_data);
+}
 
-	/*
-	 * Magic: Phase 3.  This computes 20 bytes.  The first 4 bytes are used as our magic
-	 * key (and may be changed later); the next 16 bytes are an MD5 sum of the magic key
-	 * plus 3 bytes.  The 3 bytes are found by looping, and they represent the offsets
-	 * into particular functions we'll later call to potentially alter the magic key.
-	 *
-	 * %-)
-	 */
+static void yahoo_auth16_stage1_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *ret_data, size_t len, const gchar *error_message)
+{
+	struct yahoo_auth_data *auth_data = user_data;
+	PurpleConnection *gc = auth_data->gc;
+	gchar **split_data = NULL;
+	int response_no;
+	int totalelements;
+	char *error_reason = NULL;
+	PurpleUtilFetchUrlData *url_data2 = NULL;
+	char *token = NULL;
 
-	magic_cnt = 1;
-	x = 0;
+	purple_debug_info("yahoo","Authentication: In yahoo_auth16_stage1_cb\n");
 
-	do {
-		unsigned int bl = 0;
-		unsigned int cl = magic[magic_cnt++];
+	g_return_if_fail(PURPLE_CONNECTION_IS_VALID(gc));
 
-		if (magic_cnt >= magic_len)
-			break;
+	if (error_message != NULL)	{
+		purple_debug_error("yahoo", "Login Failed, unable to retrieve login url: %s\n", error_message);
+		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, error_message);
+		g_free(auth_data->seed);
+		g_free(auth_data);
+		return;
+	}
+	else if (len > 0 && ret_data && *ret_data) {
+		split_data = g_strsplit(ret_data, "\r\n", -1);
+		totalelements = g_strv_length(split_data);
+		
+		if(totalelements >= 5)	{
+			response_no = strtol(*(split_data+1), NULL, 10);
+			token = g_strdup(*(split_data+2)+6);
+		}
+		else
+			response_no = -1;
 
-		if (cl > 0x7F) {
-			if (cl < 0xe0)
-				bl = cl = (cl & 0x1f) << 6;
-			else {
-				bl = magic[magic_cnt++];
-				cl = (cl & 0x0f) << 6;
-				bl = ((bl & 0x3f) + cl) << 6;
-			}
+		g_strfreev(split_data);
 
-			cl = magic[magic_cnt++];
-			bl = (cl & 0x3f) + bl;
-		} else
-			bl = cl;
-
-		comparison_src[x++] = (bl & 0xff00) >> 8;
-		comparison_src[x++] = bl & 0xff;
-	} while (x < 20);
-
-	/* First four bytes are magic key. */
-	memcpy(&magic_key_char[0], comparison_src, 4);
-	magic_4 = magic_key_char[0] | (magic_key_char[1] << 8) |
-			(magic_key_char[2] << 16) | (magic_key_char[3] << 24);
-
-	/*
-	 * Magic: Phase 4.  Determine what function to use later by getting outside/inside
-	 * loop values until we match our previous buffer.
-	 */
-	for (x = 0; x < 65535; x++) {
-		int leave = 0;
-
-		for (y = 0; y < 5; y++) {
-			unsigned char test[3];
-
-			/* Calculate buffer. */
-			test[0] = x;
-			test[1] = x >> 8;
-			test[2] = y;
-
-			purple_cipher_context_reset(md5_ctx, NULL);
-			purple_cipher_context_append(md5_ctx, magic_key_char, 4);
-			purple_cipher_context_append(md5_ctx, test, 3);
-			purple_cipher_context_digest(md5_ctx, sizeof(md5_digest),
-									   md5_digest, NULL);
-
-			if (!memcmp(md5_digest, comparison_src+4, 16)) {
-				leave = 1;
-				break;
+		if(response_no != 0)	{
+			/* Some error in the login process */
+			PurpleConnectionError error;
+			switch(response_no)	{
+				case -1:
+					/* Some error in the received stream */
+					error_reason = g_strdup(_("Error in the received data"));
+					error = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
+					break;
+				case 1212:
+					/* Password incorrect */
+					error_reason = g_strdup(_("Incorrect Password"));
+					error = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
+					break;
+				case 1213:
+					/* security lock from too many failed login attempts */
+					error_reason = g_strdup(_("Login locked: Too many failed login attempts"));
+					error = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
+					break;
+				case 1235:
+					/* the username does not exist */
+					error_reason = g_strdup(_("Username does not exist"));
+					error = PURPLE_CONNECTION_ERROR_INVALID_USERNAME;
+					break;
+				case 1236:
+					/* indicates a lock of some description */
+					error_reason = g_strdup(_("Login locked: See the debug log"));
+					error = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
+					break;
+				case 100:
+					/* username or password missing */
+					error_reason = g_strdup(_("Username or password missing"));
+					error = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
+					break;
+				default:
+					/* Unknown error! */
+					error_reason = g_strdup(_("Unkown error"));
+					error = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
+					break;
 			}
+			purple_debug_error("yahoo","Authentication error: %s", error_reason);
+			purple_connection_error_reason(gc, error, error_reason);
+			g_free(error_reason);
+			g_free(auth_data->seed);
+			g_free(auth_data);
 		}
+		else	{
+			/* OK to login, correct information provided */
+			char *url = NULL;
+			gboolean yahoojp = purple_account_get_bool(purple_connection_get_account(gc),
+				"yahoojp", 0);
 
-		if (leave == 1)
-			break;
+			url = g_strdup_printf(yahoojp ?
+					"https://login.yahoo.co.jp/config/pwtoken_login?src=ymsgr&ts=&token=%s" : 
+					"https://login.yahoo.com/config/pwtoken_login?src=ymsgr&ts=&token=%s",
+					token);
+			url_data2 = purple_util_fetch_url_request(url, TRUE, "Mozilla/4.0 (compatible; MSIE 5.5)", TRUE, NULL, FALSE, yahoo_auth16_stage2, auth_data);
+			g_free(url);
+			g_free(token);
+		}
 	}
+}
 
-	/* If y != 0, we need some help. */
-	if (y != 0) {
-		unsigned int	updated_key;
+static void yahoo_auth16_stage1(PurpleConnection *gc, const char *seed)
+{
+	PurpleUtilFetchUrlData *url_data = NULL;
+	struct yahoo_auth_data *auth_data = NULL;
+	char *url = NULL;
+	gboolean yahoojp;
 
-		/* Update magic stuff.
-		 * Call it twice because Yahoo's encryption is super bad ass.
-		 */
-		updated_key = yahoo_auth_finalCountdown(magic_4, 0x60, y, x);
-		updated_key = yahoo_auth_finalCountdown(updated_key, 0x60, y, x);
+	purple_debug_info("yahoo","Authentication: In yahoo_auth16_stage1\n");
 
-		magic_key_char[0] = updated_key & 0xff;
-		magic_key_char[1] = (updated_key >> 8) & 0xff;
-		magic_key_char[2] = (updated_key >> 16) & 0xff;
-		magic_key_char[3] = (updated_key >> 24) & 0xff;
+	if(!purple_ssl_is_supported()) {
+		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT, _("Server requires TLS/SSL for login.  No TLS/SSL support found."));
+		return;
 	}
 
-	enc_pass = yahoo_string_encode(gc, pass, NULL);
+	yahoojp =  purple_account_get_bool(purple_connection_get_account(gc),
+			"yahoojp", 0);
+	auth_data = g_new0(struct yahoo_auth_data, 1);
+	auth_data->gc = gc;
+	auth_data->seed = g_strdup(seed);
 
-	/* Get password and crypt hashes as per usual. */
-	purple_cipher_context_reset(md5_ctx, NULL);
-	purple_cipher_context_append(md5_ctx, (const guchar *)enc_pass, strlen(enc_pass));
-	purple_cipher_context_digest(md5_ctx, sizeof(md5_digest),
-							   md5_digest, NULL);
-	to_y64(password_hash, md5_digest, 16);
+	url = g_strdup_printf(yahoojp ?
+			"https://login.yahoo.co.jp/config/pwtoken_get?src=ymsgr&ts=&login=%s&passwd=%s&chal=%s" :
+			"https://login.yahoo.com/config/pwtoken_get?src=ymsgr&ts=&login=%s&passwd=%s&chal=%s",
+			purple_account_get_username(purple_connection_get_account(gc)),
+			purple_connection_get_password(gc), seed);
 
-	crypt_result = yahoo_crypt(enc_pass, "$1$_2S43d5f$");
-
-	g_free(enc_pass);
-	enc_pass = NULL;
-
-	purple_cipher_context_reset(md5_ctx, NULL);
-	purple_cipher_context_append(md5_ctx, (const guchar *)crypt_result, strlen(crypt_result));
-	purple_cipher_context_digest(md5_ctx, sizeof(md5_digest),
-							   md5_digest, NULL);
-	to_y64(crypt_hash, md5_digest, 16);
-
-	/* Our first authentication response is based off of the password hash. */
-	for (x = 0; x < (int)strlen(password_hash); x++)
-		pass_hash_xor1[cnt++] = password_hash[x] ^ 0x36;
-
-	if (cnt < 64)
-		memset(&(pass_hash_xor1[cnt]), 0x36, 64-cnt);
-
-	cnt = 0;
-
-	for (x = 0; x < (int)strlen(password_hash); x++)
-		pass_hash_xor2[cnt++] = password_hash[x] ^ 0x5c;
-
-	if (cnt < 64)
-		memset(&(pass_hash_xor2[cnt]), 0x5c, 64-cnt);
-
-	/*
-	 * The first context gets the password hash XORed with 0x36 plus a magic value
-	 * which we previously extrapolated from our challenge.
-	 */
-
-	purple_cipher_context_append(sha1_ctx1, pass_hash_xor1, 64);
-	if (y >= 3)
-		purple_cipher_context_set_option(sha1_ctx1, "sizeLo", GINT_TO_POINTER(0x1ff));
-	purple_cipher_context_append(sha1_ctx1, magic_key_char, 4);
-	purple_cipher_context_digest(sha1_ctx1, sizeof(digest1), digest1, NULL);
-
-	/*
-	 * The second context gets the password hash XORed with 0x5c plus the SHA-1 digest
-	 * of the first context.
-	 */
-
-	purple_cipher_context_append(sha1_ctx2, pass_hash_xor2, 64);
-	purple_cipher_context_append(sha1_ctx2, digest1, 20);
-	purple_cipher_context_digest(sha1_ctx2, sizeof(digest2), digest2, NULL);
-
-	/*
-	 * Now that we have digest2, use it to fetch characters from an alphabet to construct
-	 * our first authentication response.
-	 */
-
-	for (x = 0; x < 20; x += 2) {
-		unsigned int	val = 0;
-		unsigned int	lookup = 0;
-
-		char			byte[6];
-
-		memset(&byte, 0, 6);
-
-		/* First two bytes of digest stuffed together. */
-
-		val = digest2[x];
-		val <<= 8;
-		val += digest2[x+1];
-
-		lookup = (val >> 0x0b);
-		lookup &= 0x1f;
-		if (lookup >= strlen(alphabet1))
-			break;
-		sprintf(byte, "%c", alphabet1[lookup]);
-		strcat(resp_6, byte);
-		strcat(resp_6, "=");
-
-		lookup = (val >> 0x06);
-		lookup &= 0x1f;
-		if (lookup >= strlen(alphabet2))
-			break;
-		sprintf(byte, "%c", alphabet2[lookup]);
-		strcat(resp_6, byte);
-
-		lookup = (val >> 0x01);
-		lookup &= 0x1f;
-		if (lookup >= strlen(alphabet2))
-			break;
-		sprintf(byte, "%c", alphabet2[lookup]);
-		strcat(resp_6, byte);
-
-		lookup = (val & 0x01);
-		if (lookup >= strlen(delimit_lookup))
-			break;
-		sprintf(byte, "%c", delimit_lookup[lookup]);
-		strcat(resp_6, byte);
-	}
-
-	/* Our second authentication response is based off of the crypto hash. */
-
-	cnt = 0;
-	memset(&digest1, 0, 20);
-	memset(&digest2, 0, 20);
-
-	for (x = 0; x < (int)strlen(crypt_hash); x++)
-		crypt_hash_xor1[cnt++] = crypt_hash[x] ^ 0x36;
-
-	if (cnt < 64)
-		memset(&(crypt_hash_xor1[cnt]), 0x36, 64-cnt);
-
-	cnt = 0;
-
-	for (x = 0; x < (int)strlen(crypt_hash); x++)
-		crypt_hash_xor2[cnt++] = crypt_hash[x] ^ 0x5c;
-
-	if (cnt < 64)
-		memset(&(crypt_hash_xor2[cnt]), 0x5c, 64-cnt);
-
-	purple_cipher_context_reset(sha1_ctx1, NULL);
-	purple_cipher_context_reset(sha1_ctx2, NULL);
-
-	/*
-	 * The first context gets the password hash XORed with 0x36 plus a magic value
-	 * which we previously extrapolated from our challenge.
-	 */
-
-	purple_cipher_context_append(sha1_ctx1, crypt_hash_xor1, 64);
-	if (y >= 3) {
-		purple_cipher_context_set_option(sha1_ctx1, "sizeLo",
-									   GINT_TO_POINTER(0x1ff));
-	}
-	purple_cipher_context_append(sha1_ctx1, magic_key_char, 4);
-	purple_cipher_context_digest(sha1_ctx1, sizeof(digest1), digest1, NULL);
-
-	/*
-	 * The second context gets the password hash XORed with 0x5c plus the SHA-1 digest
-	 * of the first context.
-	 */
-
-	purple_cipher_context_append(sha1_ctx2, crypt_hash_xor2, 64);
-	purple_cipher_context_append(sha1_ctx2, digest1, 20);
-	purple_cipher_context_digest(sha1_ctx2, sizeof(digest2), digest2, NULL);
-
-	/*
-	 * Now that we have digest2, use it to fetch characters from an alphabet to construct
-	 * our first authentication response.
-	 */
-
-	for (x = 0; x < 20; x += 2) {
-		unsigned int	val = 0;
-		unsigned int	lookup = 0;
-
-		char			byte[6];
-
-		memset(&byte, 0, 6);
-
-		/* First two bytes of digest stuffed together. */
-
-		val = digest2[x];
-		val <<= 8;
-		val += digest2[x+1];
-
-		lookup = (val >> 0x0b);
-		lookup &= 0x1f;
-		if (lookup >= strlen(alphabet1))
-			break;
-		sprintf(byte, "%c", alphabet1[lookup]);
-		strcat(resp_96, byte);
-		strcat(resp_96, "=");
-
-		lookup = (val >> 0x06);
-		lookup &= 0x1f;
-		if (lookup >= strlen(alphabet2))
-			break;
-		sprintf(byte, "%c", alphabet2[lookup]);
-		strcat(resp_96, byte);
-
-		lookup = (val >> 0x01);
-		lookup &= 0x1f;
-		if (lookup >= strlen(alphabet2))
-			break;
-		sprintf(byte, "%c", alphabet2[lookup]);
-		strcat(resp_96, byte);
-
-		lookup = (val & 0x01);
-		if (lookup >= strlen(delimit_lookup))
-			break;
-		sprintf(byte, "%c", delimit_lookup[lookup]);
-		strcat(resp_96, byte);
-	}
-	purple_debug_info("yahoo", "yahoo status: %d\n", yd->current_status);
-	pack = yahoo_packet_new(YAHOO_SERVICE_AUTHRESP,	yd->current_status, 0);
-
-	if(yd->jp) {
-		yahoo_packet_hash(pack, "sssss",
-						  0, name,
-						  6, resp_6,
-						  96, resp_96,
-						  1, name,
-						  135, YAHOOJP_CLIENT_VERSION);
-	} else {
-		yahoo_packet_hash(pack, "ssssss",
-						  0, name,
-						  6, resp_6,
-						  96, resp_96,
-						  1, name,
-						  244, YAHOO_CLIENT_VERSION_ID,
-						  135, YAHOO_CLIENT_VERSION);
-	}
-
-	if (yd->picture_checksum)
-		yahoo_packet_hash_int(pack, 192, yd->picture_checksum);
-
-	yahoo_packet_send_and_free(pack, yd);
-
-	purple_cipher_context_destroy(md5_ctx);
-	purple_cipher_context_destroy(sha1_ctx1);
-	purple_cipher_context_destroy(sha1_ctx2);
-
-	g_free(password_hash);
-	g_free(crypt_hash);
+	url_data = purple_util_fetch_url_request(url, TRUE, "Mozilla/4.0 (compatible; MSIE 5.5)", TRUE, NULL, FALSE, yahoo_auth16_stage1_cb, auth_data);
+	g_free(url);
 }
 
 static void yahoo_process_auth(PurpleConnection *gc, struct yahoo_packet *pkt)
@@ -1994,11 +1656,10 @@ static void yahoo_process_auth(PurpleCon
 	if (seed) {
 		switch (m) {
 		case 0:
-			yahoo_process_auth_old(gc, seed);
-			break;
+			/* used to be for really old auth routine, dont support now */
 		case 1:
-		case 2: /* This case seems to work, could probably use testing */
-			yahoo_process_auth_new(gc, seed);
+		case 2: /* Yahoo ver 16 authentication */
+			yahoo_auth16_stage1(gc, seed);
 			break;
 		default:
 			{
@@ -2011,7 +1672,7 @@ static void yahoo_process_auth(PurpleCon
 				purple_notify_error(gc, "", _("Failed Yahoo! Authentication"),
 							buf);
 				g_free(buf);
-				yahoo_process_auth_new(gc, seed); /* Can't hurt to try it anyway. */
+				yahoo_auth16_stage1(gc, seed); /* Can't hurt to try it anyway. */
 				break;
 			}
 		}
============================================================
--- libpurple/protocols/yahoo/yahoo.h	10214c200f19cccda1b266feaf214eafc9c35089
+++ libpurple/protocols/yahoo/yahoo.h	ff1b084a6bb065d5c269847e1d5ec73a4b219432
@@ -74,11 +74,11 @@
 #define YAHOO_STATUS_TYPE_INVISIBLE "invisible"
 #define YAHOO_STATUS_TYPE_MOBILE "mobile"
 
-#define YAHOO_CLIENT_VERSION_ID "2097087"
-#define YAHOO_CLIENT_VERSION "8.1.0.421"
+#define YAHOO_CLIENT_VERSION_ID "4194239"
+#define YAHOO_CLIENT_VERSION "9.0.0.2152"
 
-#define YAHOOJP_CLIENT_VERSION_ID "524223"
-#define YAHOOJP_CLIENT_VERSION "7,0,1,1"
+#define YAHOOJP_CLIENT_VERSION_ID "4194239"
+#define YAHOOJP_CLIENT_VERSION "9.0.0.2152"
 
 
 /* Index into attention types list. */
============================================================
--- libpurple/protocols/yahoo/yahoo_doodle.c	4a86f7fd0511ca34bc48ecc2129cc568103f79cd
+++ libpurple/protocols/yahoo/yahoo_doodle.c	bc916afb3fa84e1825080db91c564eda2fc975ad
@@ -46,7 +46,6 @@
 #include "yahoo_friend.h"
 #include "yahoochat.h"
 #include "ycht.h"
-#include "yahoo_auth.h"
 #include "yahoo_filexfer.h"
 #include "yahoo_picture.h"
 
============================================================
--- libpurple/protocols/yahoo/yahoo_packet.h	73ca2470ec14b98bfa34d11bb2634e83039c3b30
+++ libpurple/protocols/yahoo/yahoo_packet.h	60efa55ccc9f1fa4f439f1695d30ca976b1e8f1e
@@ -122,8 +122,8 @@ struct yahoo_packet {
 };
 
 #define YAHOO_WEBMESSENGER_PROTO_VER 0x0065
-#define YAHOO_PROTO_VER 0x000f
-#define YAHOO_PROTO_VER_JAPAN 0x000f
+#define YAHOO_PROTO_VER 0x0010
+#define YAHOO_PROTO_VER_JAPAN 0x0010
 
 #define YAHOO_PACKET_HDRLEN (4 + 2 + 2 + 2 + 2 + 4 + 4)
 


More information about the Commits mailing list