cpw.sulabh.yahoo_16: d0e53002: Yahoo version 16 login. ---yet to do: pr...
sulabh at soc.pidgin.im
sulabh at soc.pidgin.im
Wed May 6 14:50:32 EDT 2009
-----------------------------------------------------------------
Revision: d0e53002eb30c6dbf9735ca50784d42141dfc96a
Ancestor: 0cb6e54b872e187a678895961106518e55aab987
Author: sulabh at soc.pidgin.im
Date: 2009-05-06T08:48:57
Branch: im.pidgin.cpw.sulabh.yahoo_16
URL: http://d.pidgin.im/viewmtn/revision/info/d0e53002eb30c6dbf9735ca50784d42141dfc96a
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:
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:
Yahoo version 16 login. ---yet to do: prevent password from being displayed in debug logs---
-------------- next part --------------
============================================================
--- 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 e55a2de00eb1107425a90f982389ed96af3ae3fb
+++ libpurple/protocols/yahoo/yahoo.c 0a2ae02c9798c43ff1891a28cfbde2976e761ce6
@@ -44,8 +44,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"
@@ -1527,11 +1525,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) */
{
@@ -1558,605 +1564,247 @@ 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;
- }
-
- /*
- * 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.
- *
- * %-)
- */
-
- magic_cnt = 1;
- x = 0;
-
- do {
- unsigned int bl = 0;
- unsigned int cl = magic[magic_cnt++];
-
- if (magic_cnt >= magic_len)
- break;
-
- 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;
- }
-
- 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) || try_login_on_error) {
+ crypt = g_strconcat(crumb, auth_data->seed, NULL);
+ yahoo_auth16_stage3(gc, crypt);
+ g_free(crumb);
}
-
- if (leave == 1)
- break;
}
+ g_free(auth_data->seed);
+ g_free(auth_data);
+}
- /* If y != 0, we need some help. */
- if (y != 0) {
- unsigned int updated_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;
- /* 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_cb\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;
- }
+ g_return_if_fail(PURPLE_CONNECTION_IS_VALID(gc));
- enc_pass = yahoo_string_encode(gc, pass, NULL);
-
- /* 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);
-
- 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);
+ 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;
- /* Our second authentication response is based off of the crypto hash. */
+ g_strfreev(split_data);
- 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));
+ 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 = g_strdup_printf("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);
+ }
}
- 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.
- */
+static void yahoo_auth16_stage1(PurpleConnection *gc, const char *seed)
+{
+ PurpleUtilFetchUrlData *url_data;
+ struct yahoo_auth_data *auth_data = NULL;
+ char *url = NULL;
- 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);
+ purple_debug_info("yahoo","Authentication: In yahoo_auth16_stage1\n");
- /*
- * 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);
+ 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;
}
- 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);
- }
+ auth_data = g_new0(struct yahoo_auth_data, 1);
+ auth_data->gc = gc;
+ auth_data->seed = g_strdup(seed);
- if (yd->picture_checksum)
- yahoo_packet_hash_int(pack, 192, yd->picture_checksum);
+ url = g_strdup_printf("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);
- 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)
@@ -2181,11 +1829,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:
{
@@ -2198,7 +1845,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 30e914fd5a298ef8af0c992d4efe57271669e73f
+++ libpurple/protocols/yahoo/yahoo.h b419a255b56b09e4bff8143dbe268a1338a9db75
@@ -79,8 +79,8 @@
#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"
============================================================
--- 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 8e9c2ff523731785e8d9ad1f5d9c04fd9a920ee6
+++ libpurple/protocols/yahoo/yahoo_packet.h dd4eaf1713d9ac88b89cee6c2ebaa8a429d05d1d
@@ -125,8 +125,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