diff options
author | Jason Wever <weeve@gentoo.org> | 2003-10-05 21:08:26 +0000 |
---|---|---|
committer | Jason Wever <weeve@gentoo.org> | 2003-10-05 21:08:26 +0000 |
commit | 313fdf0461a321873da8ba12c0fa51acbff43fee (patch) | |
tree | 93189988479d5547411ebe9b2874e25615781ec9 /net-im/bitlbee | |
parent | Revision bump, adds the yahoo patch from bitlbee's website. (diff) | |
download | gentoo-2-313fdf0461a321873da8ba12c0fa51acbff43fee.tar.gz gentoo-2-313fdf0461a321873da8ba12c0fa51acbff43fee.tar.bz2 gentoo-2-313fdf0461a321873da8ba12c0fa51acbff43fee.zip |
Revision bump, adds the yahoo patch from bitlbee's website.
Diffstat (limited to 'net-im/bitlbee')
-rw-r--r-- | net-im/bitlbee/ChangeLog | 8 | ||||
-rw-r--r-- | net-im/bitlbee/Manifest | 4 | ||||
-rw-r--r-- | net-im/bitlbee/bitlbee-0.80-r2.ebuild | 64 | ||||
-rw-r--r-- | net-im/bitlbee/files/digest-bitlbee-0.80-r2 | 1 | ||||
-rw-r--r-- | net-im/bitlbee/files/yahoo.diff | 919 |
5 files changed, 993 insertions, 3 deletions
diff --git a/net-im/bitlbee/ChangeLog b/net-im/bitlbee/ChangeLog index 6117b2f98d52..6fdb4d86353f 100644 --- a/net-im/bitlbee/ChangeLog +++ b/net-im/bitlbee/ChangeLog @@ -1,6 +1,12 @@ # ChangeLog for net-im/bitlbee # Copyright 2000-2003 Gentoo Technologies, Inc.; Distributed under the GPL v2 -# $Header: /var/cvsroot/gentoo-x86/net-im/bitlbee/ChangeLog,v 1.15 2003/10/01 19:59:22 taviso Exp $ +# $Header: /var/cvsroot/gentoo-x86/net-im/bitlbee/ChangeLog,v 1.16 2003/10/05 21:08:22 weeve Exp $ + +*bitlbee-0.80-r2 (05 Oct 2003) + + 05 Oct 2003; Jason Wever <weeve@gentoo.org> bitlbee-0.80-r2.ebuild, + files/yahoo.diff: + Revision bump, adds the yahoo patch from bitlbee's website. 01 Oct 2003; Tavis Ormandy <taviso@gentoo.org> bitlbee-0.80-r1.ebuild: Stable on alpha diff --git a/net-im/bitlbee/Manifest b/net-im/bitlbee/Manifest index 093e98a71d90..7fd00d0b37fb 100644 --- a/net-im/bitlbee/Manifest +++ b/net-im/bitlbee/Manifest @@ -1,4 +1,4 @@ -MD5 da14a0ca97481a7c8b4f211088a1f4cb ChangeLog 2235 +MD5 2bb8d733c2900cc2ec41b4fca7604339 ChangeLog 2419 MD5 b870fd31387b2c349eca82cb901b870e bitlbee-0.72.ebuild 1089 MD5 494046f3b577301770f06c6e4bc06c5d bitlbee-0.73-r1.ebuild 1329 MD5 2436faed029fde54669d7c71fda8dd4d bitlbee-0.73.ebuild 1089 @@ -6,7 +6,7 @@ MD5 c5dcd7f7f902927880a7e10011bc8f66 bitlbee-0.74a.ebuild 1327 MD5 c4f5a4975c9788e23b9f2590fcebbdaa bitlbee-0.80-r1.ebuild 1450 MD5 0395435f5921975e399b54e471ea6541 bitlbee-0.80.ebuild 1305 MD5 fc51bd6f3a89c98a4a447e9b1725e488 metadata.xml 465 -MD5 defe161404c6409524496f74bd2baa0d bitlbee-0.80-r2.ebuild 1481 +MD5 85996dfc72437a4c0c148be20eb18cb4 bitlbee-0.80-r2.ebuild 1489 MD5 6668146d14da88ef8240b49671db3e9b files/yahoo.diff 25463 MD5 348ecbcec9cf34e7164b0f0189ea5963 files/bitlbee-0.80-xinetd.patch 730 MD5 144e462c0af1d82a3412a237519b32ca files/bitlbee-xinetd.patch 519 diff --git a/net-im/bitlbee/bitlbee-0.80-r2.ebuild b/net-im/bitlbee/bitlbee-0.80-r2.ebuild new file mode 100644 index 000000000000..a60af3835350 --- /dev/null +++ b/net-im/bitlbee/bitlbee-0.80-r2.ebuild @@ -0,0 +1,64 @@ +# Copyright 1999-2003 Gentoo Technologies, Inc. +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-x86/net-im/bitlbee/bitlbee-0.80-r2.ebuild,v 1.1 2003/10/05 21:08:22 weeve Exp $ + +inherit eutils + +DESCRIPTION="Bitlbee is an irc to IM gateway that support mutliple IM protocols" +HOMEPAGE="http://www.lintux.cx/bitlbee.html" +SRC_URI="http://www.lintux.cx/downloads/${P}.tar.gz" + +LICENSE="GPL-2" +SLOT="0" +KEYWORDS="x86 sparc alpha" +IUSE="" + +DEPEND="virtual/glibc" + +src_unpack() { + unpack ${P}.tar.gz + + # Patch the default xinetd file to add/adjust values to Gentoo defaults + cd ${S}/doc + epatch ${FILESDIR}/${P}-xinetd.patch + cd ${S} + epatch ${FILESDIR}/yahoo.diff +} + +src_compile() { + econf --datadir=/usr/share/bitlbee --etcdir=/etc + emake || die "make failed" + + # make bitlbeed forking server + cd utils + [ -n "${CC}" ] \ + && ${CC} ${CFLAGS} bitlbeed.c -o bitlbeed \ + || gcc ${CFLAGS} bitlbeed.c -o bitlbeed + +} + +src_install() { + mkdir -p ${D}/var/lib/bitlbee + make install DESTDIR=${D} || die "install failed" + + dodoc COPYING + dodoc doc/{AUTHORS,CHANGES,CREDITS,FAQ,README,TODO} + dohtml -A sgml doc/*.sgml + doman doc/bitlbee.8 + + dobin utils/bitlbeed + + insinto /etc/xinetd.d + newins doc/bitlbee.xinetd bitlbee + + exeinto /etc/init.d + newexe ${FILESDIR}/bitlbeed.init bitlbeed || die + + insinto /etc/conf.d + newins ${FILESDIR}/bitlbeed.confd bitlbeed || die +} + +pkg_postinst() { + chown nobody:nobody /var/lib/bitlbee + chmod 700 /var/lib/bitlbee +} diff --git a/net-im/bitlbee/files/digest-bitlbee-0.80-r2 b/net-im/bitlbee/files/digest-bitlbee-0.80-r2 new file mode 100644 index 000000000000..84df83fac49a --- /dev/null +++ b/net-im/bitlbee/files/digest-bitlbee-0.80-r2 @@ -0,0 +1 @@ +MD5 96d947bef8c6c40c865beaeee59737eb bitlbee-0.80.tar.gz 351775 diff --git a/net-im/bitlbee/files/yahoo.diff b/net-im/bitlbee/files/yahoo.diff new file mode 100644 index 000000000000..3f7e4bcf7dcf --- /dev/null +++ b/net-im/bitlbee/files/yahoo.diff @@ -0,0 +1,919 @@ +diff -uNr bitlbee-0.80/protocols/yahoo/sha.h y/bitlbee-0.81/protocols/yahoo/sha.h +--- bitlbee-0.80/protocols/yahoo/sha.h Thu Jan 1 01:00:00 1970 ++++ y/bitlbee-0.81/protocols/yahoo/sha.h Tue Sep 30 20:44:20 2003 +@@ -0,0 +1,22 @@ ++#if (SIZEOF_INT == 4) ++typedef unsigned int uint32; ++#elif (SIZEOF_SHORT == 4) ++typedef unsigned short uint32; ++#else ++typedef unsigned int uint32; ++#endif /* HAVEUINT32 */ ++ ++int strprintsha(char *dest, int *hashval); ++ ++typedef struct { ++ unsigned long H[5]; ++ unsigned long W[80]; ++ int lenW; ++ unsigned long sizeHi,sizeLo; ++} SHA_CTX; ++ ++void shaInit(SHA_CTX *ctx); ++void shaUpdate(SHA_CTX *ctx, unsigned char *dataIn, int len); ++void shaFinal(SHA_CTX *ctx, unsigned char hashout[20]); ++void shaBlock(unsigned char *dataIn, int len, unsigned char hashout[20]); ++ +diff -uNr bitlbee-0.80/protocols/yahoo/yahoo.c y/bitlbee-0.81/protocols/yahoo/yahoo.c +--- bitlbee-0.80/protocols/yahoo/yahoo.c Wed May 21 11:37:04 2003 ++++ y/bitlbee-0.81/protocols/yahoo/yahoo.c Wed Oct 1 21:41:00 2003 +@@ -38,6 +38,7 @@ + #include <sys/stat.h> + #include <ctype.h> + #include "nogaim.h" ++#include "sha.h" + #include "proxy.h" + #include "md5.h" + +@@ -52,7 +53,7 @@ + #define USEROPT_PAGERPORT 4 + #define YAHOO_PAGER_PORT 5050 + +-#define YAHOO_PROTO_VER 0x0900 ++#define YAHOO_PROTO_VER 0x000b + + enum yahoo_service { /* these are easier to see in hex */ + YAHOO_SERVICE_LOGON = 1, +@@ -73,7 +74,7 @@ + YAHOO_SERVICE_ADDIDENT, /* 0x10 */ + YAHOO_SERVICE_ADDIGNORE, + YAHOO_SERVICE_PING, +- YAHOO_SERVICE_GROUPRENAME, ++ YAHOO_SERVICE_GOTGROUPRENAME, + YAHOO_SERVICE_SYSMESSAGE = 0x14, + YAHOO_SERVICE_PASSTHROUGH2 = 0x16, + YAHOO_SERVICE_CONFINVITE = 0x18, +@@ -89,12 +90,30 @@ + YAHOO_SERVICE_GAMELOGOFF, + YAHOO_SERVICE_GAMEMSG = 0x2a, + YAHOO_SERVICE_FILETRANSFER = 0x46, ++ YAHOO_SERVICE_VOICECHAT = 0x4A, + YAHOO_SERVICE_NOTIFY = 0x4B, ++ YAHOO_SERVICE_VERIFY, ++ YAHOO_SERVICE_P2PFILEXFER, ++ YAHOO_SERVICE_PEEPTOPEER = 0x4F, ++ YAHOO_SERVICE_WEBCAM, + YAHOO_SERVICE_AUTHRESP = 0x54, + YAHOO_SERVICE_LIST = 0x55, + YAHOO_SERVICE_AUTH = 0x57, + YAHOO_SERVICE_ADDBUDDY = 0x83, +- YAHOO_SERVICE_REMBUDDY = 0x84 ++ YAHOO_SERVICE_REMBUDDY = 0x84, ++ YAHOO_SERVICE_IGNORECONTACT, /* > 1, 7, 13 < 1, 66, 13, 0*/ ++ YAHOO_SERVICE_REJECTCONTACT, ++ YAHOO_SERVICE_GROUPRENAME = 0x89, /* > 1, 65(new), 66(0), 67(old) */ ++ /* YAHOO_SERVICE_??? = 0x8A, */ ++ YAHOO_SERVICE_CHATONLINE = 0x96, /* > 109(id), 1, 6(abcde) < 0,1*/ ++ YAHOO_SERVICE_CHATGOTO, ++ YAHOO_SERVICE_CHATJOIN, /* > 1 104-room 129-1600326591 62-2 */ ++ YAHOO_SERVICE_CHATLEAVE, ++ YAHOO_SERVICE_CHATEXIT = 0x9b, ++ YAHOO_SERVICE_CHATADDINVITE = 0x9d, ++ YAHOO_SERVICE_CHATLOGOUT = 0xa0, ++ YAHOO_SERVICE_CHATPING, ++ YAHOO_SERVICE_COMMENT = 0xa8 + }; + + enum yahoo_status { +@@ -114,8 +133,12 @@ + YAHOO_STATUS_OFFLINE = 0x5a55aa56, /* don't ask */ + YAHOO_STATUS_TYPING = 0x16 + }; ++ ++ + #define YAHOO_STATUS_GAME 0x2 /* Games don't fit into the regular status model */ + ++static void yahoo_close(struct gaim_connection *gc); ++ + struct yahoo_data { + int fd; + guchar *rxqueue; +@@ -185,6 +208,8 @@ + + return len; + } ++static struct prpl *my_protocol = NULL; ++ + + /* sometimes i wish prpls could #include things from other prpls. then i could just + * use the routines from libfaim and not have to admit to knowing how they work. */ +@@ -376,21 +401,20 @@ + break; + case 13: /* in pager? */ + if (pkt->service == YAHOO_SERVICE_LOGOFF || +- strtol(pair->value, NULL, 10) == 0) { +- serv_got_update(gc, name, 0, 0, 0, 0, 0, 0); ++ strtol(pair->value, NULL, 10) == 0) { serv_got_update(gc, gc->username, 0, 0, 0, 0, 0, 0); + break; + } +- if (g_hash_table_lookup(yd->games, name)) ++ if (g_hash_table_lookup(yd->games, gc->username)) + gamestate = YAHOO_STATUS_GAME; + if (state == YAHOO_STATUS_AVAILABLE) +- serv_got_update(gc, name, 1, 0, 0, 0, gamestate, 0); ++ serv_got_update(gc, gc->username, 1, 0, 0, 0, gamestate, 0); + else +- serv_got_update(gc, name, 1, 0, 0, 0, (state << 2) | UC_UNAVAILABLE | gamestate, 0); ++ serv_got_update(gc, gc->username, 1, 0, 0, 0, (state << 2) | UC_UNAVAILABLE | gamestate, 0); + if (state == YAHOO_STATUS_CUSTOM) { +- gpointer val = g_hash_table_lookup(yd->hash, name); ++ gpointer val = g_hash_table_lookup(yd->hash, gc->username); + if (val) { + g_free(val); +- g_hash_table_insert(yd->hash, name, ++ g_hash_table_insert(yd->hash, gc->username, + msg ? g_strdup(msg) : g_malloc0(1)); + } else + g_hash_table_insert(yd->hash, g_strdup(name), +@@ -581,16 +605,16 @@ + show_got_added(gc, id, who, NULL, msg); + if (name) { + if (state == YAHOO_STATUS_AVAILABLE) +- serv_got_update(gc, name, 1, 0, 0, 0, 0, 0); ++ serv_got_update(gc, gc->username, 1, 0, 0, 0, 0, 0); + else if (state == YAHOO_STATUS_IDLE) +- serv_got_update(gc, name, 1, 0, 0, time(NULL) - 600, (state << 2), 0); ++ serv_got_update(gc, gc->username, 1, 0, 0, time(NULL) - 600, (state << 2), 0); + else +- serv_got_update(gc, name, 1, 0, 0, 0, (state << 2) | UC_UNAVAILABLE, 0); ++ serv_got_update(gc, gc->username, 1, 0, 0, 0, (state << 2) | UC_UNAVAILABLE, 0); + if (state == YAHOO_STATUS_CUSTOM) { +- gpointer val = g_hash_table_lookup(yd->hash, name); ++ gpointer val = g_hash_table_lookup(yd->hash, gc->username); + if (val) { + g_free(val); +- g_hash_table_insert(yd->hash, name, ++ g_hash_table_insert(yd->hash,gc->username, + msg ? g_strdup(msg) : g_malloc0(1)); + } else + g_hash_table_insert(yd->hash, g_strdup(name), +@@ -630,12 +654,523 @@ + *out = '\0'; + } + ++ ++static void yahoo_process_auth_new(struct gaim_connection *gc, const char *seed) ++{ ++ struct yahoo_packet *pack = NULL; ++ 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"; ++ ++ char *challenge_lookup = "qzec2tb3um1olpar8whx4dfgijknsvy5"; ++ char *operand_lookup = "+|&%/*^-"; ++ char *delimit_lookup = ",;"; ++ ++ 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; ++ unsigned int value = 0; ++ ++ int x; ++ int cnt = 0; ++ int magic_cnt = 0; ++ int magic_len; ++ int times = 0; ++ ++ 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); ++ ++ /* ++ * 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; ++ ++ /* Ignore parentheses. */ ++ ++ if (*magic_ptr == '(' || *magic_ptr == ')') { ++ magic_ptr++; ++ continue; ++ } ++ ++ /* 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 */ ++ } ++ ++ /* Get offset into lookup table and lsh 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) { ++ /* Also not good. */ ++ } ++ ++ 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. Final phase; this gives us our ++ * key. */ ++ ++ magic_cnt = 1; ++ ++ for (;;) { ++ unsigned int cl = magic[magic_cnt] & 0xff; ++ unsigned int bl = magic[magic_cnt+1] & 0xff; ++ ++ if (!bl || !cl) ++ break; ++ ++ if (magic_cnt > magic_len) ++ break; ++ ++ if (cl <= 0x7f) ++ bl = cl; ++ else { ++ if (cl >= 0x0e0) { ++ cl = cl & 0x0f; ++ cl = cl << 6; ++ bl = bl & 0x3f; ++ bl = cl + bl; ++ bl = bl << 6; ++ } else { ++ cl = cl & 0x1f; ++ cl = cl << 6; ++ bl = cl; ++ } ++ ++ cl = magic[magic_cnt+2]; ++ ++ if (!cl) ++ break; ++ ++ cl = cl & 0x3f; ++ bl = bl + cl; ++ } ++ ++ /* Result is bl. ++ */ ++ ++ magic_cnt += 3; ++ ++ if (times == 0) { ++ value |= (bl & 0xff) << 8; ++ value |= (bl & 0xff00) >> 8; ++ } else { ++ value |= (bl & 0xff) << 24; ++ value |= (bl & 0xff00) << 8; ++ break; ++ } ++ ++ times++; ++ } ++ ++ /* Dump magic key into a char for SHA1 action. */ ++ ++ memcpy(&magic_key_char[0], &value, sizeof(int)); ++ ++ /* Get password and crypt hashes as per usual. */ ++ md5_init(&ctx); ++ md5_append(&ctx, gc->password, strlen(gc->password)); ++ md5_finish(&ctx, result); ++ to_y64(password_hash, result, 16); ++ ++ md5_init(&ctx); ++ crypt_result = yahoo_crypt(gc->password, "$1$_2S43d5f$"); ++ 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. */ ++ ++ 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); ++ ++ 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. */ ++ ++ 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. */ ++ ++ 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. */ ++ ++ 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); ++ ++ 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. */ ++ ++ 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. */ ++ ++ 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. */ ++ ++ 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); ++ } ++ ++ pack = yahoo_packet_new(YAHOO_SERVICE_AUTHRESP, YAHOO_STATUS_AVAILABLE, 0); ++ yahoo_packet_hash(pack, 0, gc->username); ++ yahoo_packet_hash(pack, 6, resp_6); ++ yahoo_packet_hash(pack, 96, resp_96); ++ yahoo_packet_hash(pack, 1, gc->username); ++ yahoo_send_packet(yd, pack); ++ yahoo_packet_free(pack); ++ ++ free(password_hash); ++ free(crypt_hash); ++} ++ ++ ++ ++ ++static void yahoo_process_auth_old(struct gaim_connection *gc, const char *seed) ++{ ++ struct yahoo_packet *pack; ++ struct yahoo_data *yd = gc->proto_data; ++ ++ /* 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 ++ * bizzare, convoluted, inordinately complicated. It's also no more secure than ++ * crypt() was. The only purpose this scheme could serve is to prevent third ++ * part clients from connecting to their servers. ++ * ++ * Sorry, Yahoo. ++ */ ++ ++ md5_byte_t result[16]; ++ md5_state_t ctx; ++ ++ char *crypt_result; ++ char password_hash[25]; ++ char crypt_hash[25]; ++ char *hash_string_p = g_malloc(50 + strlen(gc->username)); ++ char *hash_string_c = g_malloc(50 + strlen(gc->username)); ++ ++ char checksum; ++ ++ int sv; ++ ++ char result6[25]; ++ char result96[25]; ++ ++ sv = seed[15]; ++ sv = sv % 8; ++ ++ md5_init(&ctx); ++ md5_append(&ctx, gc->password, strlen(gc->password)); ++ md5_finish(&ctx, result); ++ to_y64(password_hash, result, 16); ++ ++ md5_init(&ctx); ++ crypt_result = yahoo_crypt(gc->password, "$1$_2S43d5f$"); ++ md5_append(&ctx, crypt_result, strlen(crypt_result)); ++ md5_finish(&ctx, result); ++ to_y64(crypt_hash, result, 16); ++ ++ switch (sv) { ++ case 1: ++ case 6: ++ checksum = seed[seed[9] % 16]; ++ g_snprintf(hash_string_p, strlen(gc->username) + 50, ++ "%c%s%s%s", checksum, gc->username, seed, password_hash); ++ g_snprintf(hash_string_c, strlen(gc->username) + 50, ++ "%c%s%s%s", checksum, gc->username, seed, crypt_hash); ++ break; ++ case 2: ++ case 7: ++ checksum = seed[seed[15] % 16]; ++ g_snprintf(hash_string_p, strlen(gc->username) + 50, ++ "%c%s%s%s", checksum, seed, password_hash, gc->username); ++ g_snprintf(hash_string_c, strlen(gc->username) + 50, ++ "%c%s%s%s", checksum, seed, crypt_hash, gc->username); ++ break; ++ case 3: ++ checksum = seed[seed[1] % 16]; ++ g_snprintf(hash_string_p, strlen(gc->username) + 50, ++ "%c%s%s%s", checksum, gc->username, password_hash, seed); ++ g_snprintf(hash_string_c, strlen(gc->username) + 50, ++ "%c%s%s%s", checksum, gc->username, crypt_hash, seed); ++ break; ++ case 4: ++ checksum = seed[seed[3] % 16]; ++ g_snprintf(hash_string_p, strlen(gc->username) + 50, ++ "%c%s%s%s", checksum, password_hash, seed, gc->username); ++ g_snprintf(hash_string_c, strlen(gc->username) + 50, ++ "%c%s%s%s", checksum, crypt_hash, seed, gc->username); ++ break; ++ case 0: ++ case 5: ++ checksum = seed[seed[7] % 16]; ++ g_snprintf(hash_string_p, strlen(gc->username) + 50, ++ "%c%s%s%s", checksum, password_hash, gc->username, seed); ++ g_snprintf(hash_string_c, strlen(gc->username) + 50, ++ "%c%s%s%s", checksum, crypt_hash, gc->username, seed); ++ break; ++ } ++ ++ md5_init(&ctx); ++ md5_append(&ctx, hash_string_p, strlen(hash_string_p)); ++ md5_finish(&ctx, result); ++ to_y64(result6, result, 16); ++ ++ md5_init(&ctx); ++ md5_append(&ctx, hash_string_c, strlen(hash_string_c)); ++ md5_finish(&ctx, result); ++ to_y64(result96, result, 16); ++ ++ pack = yahoo_packet_new(YAHOO_SERVICE_AUTHRESP, YAHOO_STATUS_AVAILABLE, 0); ++ yahoo_packet_hash(pack, 0, gc->username); ++ yahoo_packet_hash(pack, 6, result6); ++ yahoo_packet_hash(pack, 96, result96); ++ yahoo_packet_hash(pack, 1, gc->username); ++ ++ yahoo_send_packet(yd, pack); ++ ++ g_free(hash_string_p); ++ g_free(hash_string_c); ++ ++ yahoo_packet_free(pack); ++ ++} ++ ++ + static void yahoo_process_auth(struct gaim_connection *gc, struct yahoo_packet *pkt) + { + char *seed = NULL; + char *sn = NULL; + GSList *l = pkt->hash; +- struct yahoo_data *yd = gc->proto_data; ++ int m = 1; ++ + + while (l) { + struct yahoo_pair *pair = l->data; +@@ -643,122 +1178,44 @@ + seed = pair->value; + if (pair->key == 1) + sn = pair->value; ++ if (pair->key == 13) ++ m = atoi(pair->value); + l = l->next; + } + + if (seed) { +- struct yahoo_packet *pack; +- +- /* 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 +- * bizzare, convoluted, inordinately complicated. It's also no more secure than +- * crypt() was. The only purpose this scheme could serve is to prevent third +- * part clients from connecting to their servers. +- * +- * Sorry, Yahoo. +- */ +- +- md5_byte_t result[16]; +- md5_state_t ctx; +- char *crypt_result; +- char *password_hash = g_malloc(25); +- char *crypt_hash = g_malloc(25); +- char *hash_string_p = g_malloc(50 + strlen(sn)); +- char *hash_string_c = g_malloc(50 + strlen(sn)); +- +- char checksum; +- +- int sv; +- +- char *result6 = g_malloc(25); +- char *result96 = g_malloc(25); +- +- sv = seed[15]; +- sv = sv % 8; +- +- md5_init(&ctx); +- md5_append(&ctx, gc->password, strlen(gc->password)); +- md5_finish(&ctx, result); +- to_y64(password_hash, result, 16); +- +- md5_init(&ctx); +- crypt_result = yahoo_crypt(gc->password, "$1$_2S43d5f$"); +- md5_append(&ctx, crypt_result, strlen(crypt_result)); +- md5_finish(&ctx, result); +- to_y64(crypt_hash, result, 16); +- +- switch (sv) { +- case 1: +- case 6: +- checksum = seed[seed[9] % 16]; +- g_snprintf(hash_string_p, strlen(sn) + 50, +- "%c%s%s%s", checksum, gc->username, seed, password_hash); +- g_snprintf(hash_string_c, strlen(sn) + 50, +- "%c%s%s%s", checksum, gc->username, seed, crypt_hash); +- break; +- case 2: +- case 7: +- checksum = seed[seed[15] % 16]; +- g_snprintf(hash_string_p, strlen(sn) + 50, +- "%c%s%s%s", checksum, seed, password_hash, gc->username); +- g_snprintf(hash_string_c, strlen(sn) + 50, +- "%c%s%s%s", checksum, seed, crypt_hash, gc->username); +- break; +- case 3: +- checksum = seed[seed[1] % 16]; +- g_snprintf(hash_string_p, strlen(sn) + 50, +- "%c%s%s%s", checksum, gc->username, password_hash, seed); +- g_snprintf(hash_string_c, strlen(sn) + 50, +- "%c%s%s%s", checksum, gc->username, crypt_hash, seed); +- break; +- case 4: +- checksum = seed[seed[3] % 16]; +- g_snprintf(hash_string_p, strlen(sn) + 50, +- "%c%s%s%s", checksum, password_hash, seed, gc->username); +- g_snprintf(hash_string_c, strlen(sn) + 50, +- "%c%s%s%s", checksum, crypt_hash, seed, gc->username); +- break; ++ switch (m) { + case 0: +- case 5: +- checksum = seed[seed[7] % 16]; +- g_snprintf(hash_string_p, strlen(sn) + 50, +- "%c%s%s%s", checksum, password_hash, gc->username, seed); +- g_snprintf(hash_string_c, strlen(sn) + 50, +- "%c%s%s%s", checksum, crypt_hash, gc->username, seed); ++ yahoo_process_auth_old(gc, seed); + break; ++ case 1: ++ yahoo_process_auth_new(gc, seed); ++ break; ++ default: ++ yahoo_process_auth_new(gc, seed); /* Can't hurt to try it anyway. */ + } +- +- md5_init(&ctx); +- md5_append(&ctx, hash_string_p, strlen(hash_string_p)); +- md5_finish(&ctx, result); +- to_y64(result6, result, 16); +- +- md5_init(&ctx); +- md5_append(&ctx, hash_string_c, strlen(hash_string_c)); +- md5_finish(&ctx, result); +- to_y64(result96, result, 16); +- +- pack = yahoo_packet_new(YAHOO_SERVICE_AUTHRESP, YAHOO_STATUS_AVAILABLE, 0); +- yahoo_packet_hash(pack, 0, gc->username); +- yahoo_packet_hash(pack, 6, result6); +- yahoo_packet_hash(pack, 96, result96); +- yahoo_packet_hash(pack, 1, gc->username); +- +- yahoo_send_packet(yd, pack); +- +- g_free(result6); +- g_free(result96); +- g_free(password_hash); +- g_free(crypt_hash); +- g_free(hash_string_p); +- g_free(hash_string_c); ++ } ++} + +- yahoo_packet_free(pack); ++static void yahoo_process_authresp(struct gaim_connection *gc, struct ++yahoo_packet *pkt) ++{ ++ GSList *l = pkt->hash; ++ int err = 0; ++ ++ while (l) { ++ struct yahoo_pair *pair = l->data; ++ ++ if (pair->key == 66) ++ err = strtol(pair->value, NULL, 10); ++ ++ l = l->next; + } ++ ++ + } + ++ + static void yahoo_packet_process(struct gaim_connection *gc, struct yahoo_packet *pkt) + { + switch (pkt->service) +@@ -781,6 +1238,9 @@ + case YAHOO_SERVICE_NEWMAIL: + // yahoo_process_mail(gc, pkt); + break; ++ case YAHOO_SERVICE_AUTHRESP: ++ yahoo_process_authresp(gc, pkt); ++ break; + case YAHOO_SERVICE_NEWCONTACT: + yahoo_process_contact(gc, pkt); + break; +@@ -795,18 +1255,20 @@ + } + } + ++ + static void yahoo_pending(gpointer data, gint source, GaimInputCondition cond) + { + struct gaim_connection *gc = data; + struct yahoo_data *yd = gc->proto_data; + char buf[1024]; + int len; ++ + + len = read(yd->fd, buf, sizeof(buf)); + + if (len <= 0) { + hide_login_progress_error(gc, "Unable to read"); +- signoff(gc); ++ yahoo_close(gc); + return; + } + +@@ -857,6 +1319,7 @@ + } + } + ++ + static void yahoo_got_connected(gpointer data, gint source, GaimInputCondition cond) + { + struct gaim_connection *gc = data; +@@ -878,10 +1341,10 @@ + yd->fd = source; + + pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH, YAHOO_STATUS_AVAILABLE, 0); +- + yahoo_packet_hash(pkt, 1, gc->username); + yahoo_send_packet(yd, pkt); + ++ + yahoo_packet_free(pkt); + + gc->inpa = gaim_input_add(yd->fd, GAIM_INPUT_READ, yahoo_pending, gc); +@@ -894,17 +1357,14 @@ + set_login_progress(gc, 1, "Connecting"); + + yd->fd = -1; +- yd->hash = g_hash_table_new(g_str_hash, g_str_equal); ++ yd->hash= g_hash_table_new(g_str_hash, g_str_equal); + yd->games = g_hash_table_new(g_str_hash, g_str_equal); ++ if (!g_strncasecmp(user->proto_opt[USEROPT_PAGERHOST], "cs.yahoo.com", strlen("cs.yahoo.com"))) { ++ /* Figured out the new auth method -- cs.yahoo.com likes to disconnect on buddy remove and add now */ ++ g_snprintf(user->proto_opt[USEROPT_PAGERHOST], strlen("scs.yahoo.com") + 1, "scs.yahoo.com"); ++// save_prefs(); ++ } + +- +- if (!g_strncasecmp(user->proto_opt[USEROPT_PAGERHOST], "cs.yahoo.com", strlen("cs.yahoo.com"))) { +- /* Figured out the new auth method -- cs.yahoo.com likes to disconnect on buddy remove and add now */ +- g_snprintf(user->proto_opt[USEROPT_PAGERHOST], strlen("scs.yahoo.com") + 1, "scs.yahoo.com"); +-// save_prefs(); +- } +- +- + if (proxy_connect(user->proto_opt[USEROPT_PAGERHOST][0] ? + user->proto_opt[USEROPT_PAGERHOST] : YAHOO_PAGER_HOST, + user->proto_opt[USEROPT_PAGERPORT][0] ? +@@ -1186,8 +1646,6 @@ + yahoo_send_packet(yd, pkt); + yahoo_packet_free(pkt); + } +- +-static struct prpl *my_protocol = NULL; + + void yahoo_init(struct prpl *ret) { + ret->protocol = PROTO_YAHOO; |