Mercurial > pidgin.yaz
diff src/protocols/yahoo/yahoo.c @ 8349:f1ca7e06e8de
[gaim-migrate @ 9073]
Thanks again, Trillian.
committer: Tailor Script <tailor@pidgin.im>
author | Sean Egan <seanegan@gmail.com> |
---|---|
date | Fri, 27 Feb 2004 00:24:21 +0000 |
parents | 217643616a74 |
children | 1f56ea865926 |
line wrap: on
line diff
--- a/src/protocols/yahoo/yahoo.c Thu Feb 26 17:54:40 2004 +0000 +++ b/src/protocols/yahoo/yahoo.c Fri Feb 27 00:24:21 2004 +0000 @@ -38,6 +38,7 @@ #include "sha.h" #include "yahoo.h" #include "yahoochat.h" +#include "yahoo_auth.h" #include "yahoo_filexfer.h" #include "md5.h" @@ -1105,44 +1106,49 @@ const char *name = gaim_normalize(account, gaim_account_get_username(account)); const char *pass = gaim_account_get_password(account); struct yahoo_data *yd = gc->proto_data; - - md5_byte_t result[16]; - md5_state_t ctx; - SHA_CTX ctx1; - SHA_CTX ctx2; - - char *alphabet1 = "FBZDWAGHrJTLMNOPpRSKUVEXYChImkwQ"; - char *alphabet2 = "F0E1D2C3B4A59687abcdefghijklmnop"; + md5_byte_t result[16]; + md5_state_t ctx; - char *challenge_lookup = "qzec2tb3um1olpar8whx4dfgijknsvy5"; - char *operand_lookup = "+|&%/*^-"; - char *delimit_lookup = ",;"; + SHA_CTX ctx1; + SHA_CTX ctx2; - char *password_hash = g_malloc0(25); - char *crypt_hash = g_malloc0(25); - char *crypt_result = NULL; - char pass_hash_xor1[64]; - char pass_hash_xor2[64]; - char crypt_hash_xor1[64]; - char crypt_hash_xor2[64]; - char resp_6[100]; - char resp_96[100]; - - unsigned char digest1[20]; - unsigned char digest2[20]; - unsigned char magic_key_char[4]; - const unsigned char *magic_ptr; - - unsigned int magic[64]; - unsigned int magic_work = 0; - - char comparison_src[20]; - int x; - int cnt = 0; - int magic_cnt = 0; - int magic_len; - + 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; + + char pass_hash_xor1[64]; + char pass_hash_xor2[64]; + char crypt_hash_xor1[64]; + 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]; + unsigned 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); @@ -1153,37 +1159,37 @@ memset(&resp_6, 0, 100); memset(&resp_96, 0, 100); memset(&magic_key_char, 0, 4); + memset(&comparison_src, 0, 20); /* - * 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: 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 != (int)NULL) { - char *loc; + char *loc; - /* Ignore parentheses. */ + /* Ignore parentheses. + */ if (*magic_ptr == '(' || *magic_ptr == ')') { magic_ptr++; continue; } - /* Characters and digits verify against - the challenge lookup. - */ + /* Characters and digits verify against the challenge lookup. + */ if (isalpha(*magic_ptr) || isdigit(*magic_ptr)) { loc = strchr(challenge_lookup, *magic_ptr); if (!loc) { - /* This isn't good */ + /* SME XXX Error - disconnect here */ } - /* Get offset into lookup table and lsh 3. */ + /* Get offset into lookup table and shl 3. + */ magic_work = loc - challenge_lookup; magic_work <<= 3; @@ -1191,94 +1197,154 @@ magic_ptr++; continue; } else { - unsigned int local_store; + unsigned int local_store; loc = strchr(operand_lookup, *magic_ptr); if (!loc) { - /* Also not good. */ + /* SME XXX Disconnect */ } local_store = loc - operand_lookup; - - /* Oops; how did this happen? */ + + /* 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. */ - + /* 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; + unsigned char byte1; + unsigned char byte2; /* Bad. Abort. */ - if ((magic_cnt + 1 > magic_len) || - (magic_cnt > magic_len)) + + 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); + memcpy(&magic_4, comparison_src, 4); + + /* + * 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++) { + md5_byte_t result[16]; + md5_state_t ctx; + + unsigned char test[3]; + + memset(&result, 0, 16); + memset(&test, 0, 3); + + /* Calculate buffer. + */ + + test[0] = x; + test[1] = x >> 8; + test[2] = y; + + md5_init(&ctx); + md5_append(&ctx, magic_key_char, 4); + md5_append(&ctx, test, 3); + md5_finish(&ctx, result); + + if (!memcmp(result, comparison_src+4, 16)) { + leave = 1; + break; + } + } + + if (leave == 1) + break; } - /* 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. - * - * %-) - */ + /* If y != 0, we need some help. + */ - magic_cnt = 1; - x = 0; - - do { - unsigned int bl = 0; - unsigned int cl = magic[magic_cnt++]; + if (y != 0) { + unsigned int updated_key; - if (magic_cnt >= magic_len) - break; + /* Update magic stuff. Call it twice because Yahoo's encryption is super bad ass. + */ - 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; + updated_key = yahoo_auth_finalCountdown(magic_4, 0x60, y, x); + updated_key = yahoo_auth_finalCountdown(updated_key, 0x60, y, x); - comparison_src[x++] = (bl & 0xff00) >> 8; - comparison_src[x++] = bl & 0xff; - } while (x < 20); + memcpy(&magic_key_char[0], &updated_key, 4); + } - /* First four bytes are magic key. */ - for (x = 0; x < 4; x++) - magic_key_char[x] = comparison_src[x]; - - - /* Get password and crypt hashes as per usual. */ +/* Get password and crypt hashes as per usual. + */ + md5_init(&ctx); - md5_append(&ctx, pass, strlen(pass)); + md5_append(&ctx, pass, strlen(pass)); md5_finish(&ctx, result); to_y64(password_hash, result, 16); @@ -1287,16 +1353,16 @@ md5_append(&ctx, crypt_result, strlen(crypt_result)); md5_finish(&ctx, result); to_y64(crypt_hash, result, 16); - - /* Our first authentication response is based off - * of the password hash. */ + + /* 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++) @@ -1308,36 +1374,38 @@ shaInit(&ctx1); shaInit(&ctx2); - /* The first context gets the password hash XORed - * with 0x36 plus a magic value - * which we previously extrapolated from our - * challenge. */ + /* + * The first context gets the password hash XORed with 0x36 plus a magic value + * which we previously extrapolated from our challenge. + */ shaUpdate(&ctx1, pass_hash_xor1, 64); shaUpdate(&ctx1, magic_key_char, 4); shaFinal(&ctx1, digest1); - /* The second context gets the password hash XORed - * with 0x5c plus the SHA-1 digest - * of the first context. */ + /* + * The second context gets the password hash XORed with 0x5c plus the SHA-1 digest + * of the first context. + */ shaUpdate(&ctx2, pass_hash_xor2, 64); shaUpdate(&ctx2, digest1, 20); shaFinal(&ctx2, digest2); - /* Now that we have digest2, use it to fetch - * characters from an alphabet to construct - * our first authentication response. */ - + /* + * 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]; + unsigned int val = 0; + unsigned int lookup = 0; + char byte[6]; + memset(&byte, 0, 6); - - /* First two bytes of digest stuffed - * together. + + /* First two bytes of digest stuffed together. */ val = digest2[x]; @@ -1351,7 +1419,7 @@ sprintf(byte, "%c", alphabet1[lookup]); strcat(resp_6, byte); strcat(resp_6, "="); - + lookup = (val >> 0x06); lookup &= 0x1f; if (lookup >= strlen(alphabet2)) @@ -1365,7 +1433,7 @@ break; sprintf(byte, "%c", alphabet2[lookup]); strcat(resp_6, byte); - + lookup = (val & 0x01); if (lookup >= strlen(delimit_lookup)) break; @@ -1373,8 +1441,8 @@ strcat(resp_6, byte); } - /* Our second authentication response is based off - * of the crypto hash. */ + /* Our second authentication response is based off of the crypto hash. + */ cnt = 0; memset(&digest1, 0, 20); @@ -1385,7 +1453,7 @@ if (cnt < 64) memset(&(crypt_hash_xor1[cnt]), 0x36, 64-cnt); - + cnt = 0; for (x = 0; x < (int)strlen(crypt_hash); x++) @@ -1397,42 +1465,44 @@ shaInit(&ctx1); shaInit(&ctx2); - /* The first context gets the password hash XORed - * with 0x36 plus a magic value - * which we previously extrapolated from our - * challenge. */ + /* + * The first context gets the password hash XORed with 0x36 plus a magic value + * which we previously extrapolated from our challenge. + */ shaUpdate(&ctx1, crypt_hash_xor1, 64); shaUpdate(&ctx1, magic_key_char, 4); shaFinal(&ctx1, digest1); - /* The second context gets the password hash XORed - * with 0x5c plus the SHA-1 digest - * of the first context. */ + /* + * The second context gets the password hash XORed with 0x5c plus the SHA-1 digest + * of the first context. + */ shaUpdate(&ctx2, crypt_hash_xor2, 64); shaUpdate(&ctx2, digest1, 20); shaFinal(&ctx2, digest2); - /* Now that we have digest2, use it to fetch - * characters from an alphabet to construct - * our first authentication response. */ + /* + * 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; + unsigned int val = 0; + unsigned int lookup = 0; - char byte[6]; + char byte[6]; memset(&byte, 0, 6); - /* First two bytes of digest stuffed - * together. */ + /* 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))