changeset 29688:9f482e11f066

Rework the Yahoo auth16 sutff a bit such that we now retrieve and use the necessary portion of the B cookie. This isn't strictly required to log in, but it does make us look more like the official client.
author John Bailey <rekkanoryo@rekkanoryo.org>
date Thu, 08 Apr 2010 03:21:27 +0000
parents 911f51eb04fd
children 18042a99d213
files libpurple/protocols/yahoo/libymsg.c libpurple/protocols/yahoo/libymsg.h
diffstat 2 files changed, 95 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/protocols/yahoo/libymsg.c	Mon Apr 05 00:09:37 2010 +0000
+++ b/libpurple/protocols/yahoo/libymsg.c	Thu Apr 08 03:21:27 2010 +0000
@@ -1727,18 +1727,32 @@
 	purple_debug_info("yahoo", "yahoo status: %d\n", yd->current_status);
 	pkt = yahoo_packet_new(YAHOO_SERVICE_AUTHRESP, yd->current_status, yd->session_id);
 	
-	yahoo_packet_hash(pkt, "sssssssss",
-				1, name,
-				0, name,
-				277, yd->cookie_y,
-				278, yd->cookie_t,
-				307, base64_string,
-				244, yd->jp ? YAHOOJP_CLIENT_VERSION_ID : YAHOO_CLIENT_VERSION_ID,
-				2, name,
-				2, "1",
-				/* Should send key 59, value of bcookie here--need to fetch it first! */
-				98, purple_account_get_string(account, "room_list_locale", yd->jp ? "jp" : "us"),
-				135, yd->jp ? YAHOOJP_CLIENT_VERSION : YAHOO_CLIENT_VERSION);
+	if(yd->cookie_b) { /* send B cookie if we have it */
+		yahoo_packet_hash(pkt, "ssssssssss",
+					1, name,
+					0, name,
+					277, yd->cookie_y,
+					278, yd->cookie_t,
+					307, base64_string,
+					244, yd->jp ? YAHOOJP_CLIENT_VERSION_ID : YAHOO_CLIENT_VERSION_ID,
+					2, name,
+					2, "1",
+					59, yd->cookie_b,
+					98, purple_account_get_string(account, "room_list_locale", yd->jp ? "jp" : "us"),
+					135, yd->jp ? YAHOOJP_CLIENT_VERSION : YAHOO_CLIENT_VERSION);
+	} else { /* don't try to send an empty B cookie - the server will be mad */
+		yahoo_packet_hash(pkt, "sssssssss",
+					1, name,
+					0, name,
+					277, yd->cookie_y,
+					278, yd->cookie_t,
+					307, base64_string,
+					244, yd->jp ? YAHOOJP_CLIENT_VERSION_ID : YAHOO_CLIENT_VERSION_ID,
+					2, name,
+					2, "1",
+					98, purple_account_get_string(account, "room_list_locale", yd->jp ? "jp" : "us"),
+					135, yd->jp ? YAHOOJP_CLIENT_VERSION : YAHOO_CLIENT_VERSION);
+	}
 
 	if (yd->picture_checksum)
 		yahoo_packet_hash_int(pkt, 192, yd->picture_checksum);
@@ -1747,6 +1761,31 @@
 	purple_cipher_context_destroy(md5_ctx);
 }
 
+static gchar *yahoo_auth16_get_cookie_b(gchar *headers)
+{
+	gchar **splits = g_strsplit(headers, "\r\n", -1);
+	gchar *tmp = NULL, *tmp2 = NULL, *sem = NULL;
+	int elements = g_strv_length(splits), i;
+
+	if(elements > 1) {
+		for(i = 0; i < elements; i++) {
+			if(g_ascii_strncasecmp(splits[i], "Set-Cookie: B=", 14) == 0) {
+				tmp = &splits[i][14];
+				sem = strchr(tmp, ';');
+
+				if(tmp != NULL) {
+					tmp2 = g_strndup(tmp, sem - tmp);
+					purple_debug_info("yahoo", "Got needed part of B cookie: %s\n",
+							tmp2 ? tmp2 : "(null)");
+					break;
+				}
+			}
+		}
+	}
+
+	return tmp2;
+}
+
 static void yahoo_auth16_stage2(PurpleUtilFetchUrlData *unused, gpointer user_data, const gchar *ret_data, size_t len, const gchar *error_message)
 {
 	struct yahoo_auth_data *auth_data = user_data;
@@ -1772,26 +1811,56 @@
 		return;
 	}
 	else if (len > 0 && ret_data && *ret_data) {
-		gchar **split_data = g_strsplit(ret_data, "\r\n", -1);
+		gchar **splits = g_strsplit(ret_data, "\r\n\r\n", -1), **split_data = NULL;
 		int totalelements = 0;
 		int response_no = -1;
 		char *crumb = NULL;
 		char *crypt = NULL;
-
-		totalelements = g_strv_length(split_data);
+		
+		if(g_strv_length(splits) > 1) {
+			yd->cookie_b = yahoo_auth16_get_cookie_b(splits[0]);
+			split_data = g_strsplit(splits[1], "\r\n", -1);
+			totalelements = g_strv_length(split_data);
+		}
 
 		if (totalelements >= 4) {
-			response_no = strtol(split_data[0], NULL, 10);
-			crumb = g_strdup(split_data[1] + strlen("crumb="));
-			yd->cookie_y = g_strdup(split_data[2] + strlen("Y="));
-			yd->cookie_t = g_strdup(split_data[3] + strlen("T="));
-
-			if(purple_debug_is_unsafe())
-				purple_debug_info("yahoo", "Got crumb, Y cookie, and T "
-						"cookie:\ncrumb=%s\nY=%s\nT=%s\n", crumb, yd->cookie_y,
-						yd->cookie_t);
+			int i;
+
+			for(i = 0; i < totalelements; i++) {
+				/* I'm not exactly a fan of the magic numbers, but it's obvious,
+				 * so no sense in wasting a bajillion vars or calls to strlen */
+
+				if(g_ascii_isdigit(split_data[i][0])) {
+					/* if the current line and the next line both start with numbers,
+					 * the current line is the length of the body, so skip.  If not,
+					 * then the current line is the response code from the login process. */
+					if(!g_ascii_isdigit(split_data[i + 1][0])) {
+						response_no = strtol(split_data[i], NULL, 10);
+						purple_debug_info("yahoo", "Got auth16 stage 2 response code: %d\n",
+								response_no);
+					}
+				} else if(strncmp(split_data[i], "crumb=", 6) == 0) {
+					crumb = g_strdup(&split_data[i][6]);
+
+					if(purple_debug_is_unsafe())
+						purple_debug_info("yahoo", "Got crumb: %s\n", crumb);
+
+				} else if(strncmp(split_data[i], "Y=", 2) == 0) {
+					yd->cookie_y = g_strdup(&split_data[i][2]);
+
+					if(purple_debug_is_unsafe())
+						purple_debug_info("yahoo", "Got Y cookie: %s\n", yd->cookie_y);
+
+				} else if(strncmp(split_data[i], "T=", 2) == 0) {
+					yd->cookie_t = g_strdup(&split_data[i][2]);
+
+					if(purple_debug_is_unsafe())
+						purple_debug_info("yahoo", "Got T cookie: %s\n", yd->cookie_t);
+				}
+			}
 		}
 
+		g_strfreev(splits);
 		g_strfreev(split_data);
 
 		if(response_no != 0) {
@@ -1952,7 +2021,7 @@
 			url = g_strdup_printf(yahoojp ? YAHOOJP_LOGIN_URL : YAHOO_LOGIN_URL, token);
 			url_data = purple_util_fetch_url_request_len_with_account(
 					proxy_ssl ? account : NULL, url, TRUE, YAHOO_CLIENT_USERAGENT,
-					TRUE, NULL, FALSE, -1, yahoo_auth16_stage2, auth_data);
+					TRUE, NULL, TRUE, -1, yahoo_auth16_stage2, auth_data);
 			g_free(url);
 			g_free(token);
 		}
--- a/libpurple/protocols/yahoo/libymsg.h	Mon Apr 05 00:09:37 2010 +0000
+++ b/libpurple/protocols/yahoo/libymsg.h	Thu Apr 08 03:21:27 2010 +0000
@@ -220,6 +220,7 @@
 	gsize auth_written;
 	char *cookie_y;
 	char *cookie_t;
+	char *cookie_b;
 	int session_id;
 	gboolean jp;
 	gboolean wm; /* connected w/ web messenger method */