comparison src/protocols/yahoo/yahoo.c @ 11077:9f526e2e511e

[gaim-migrate @ 13087] Whitespace committer: Tailor Script <tailor@pidgin.im>
author Mark Doliner <mark@kingant.net>
date Sat, 09 Jul 2005 20:07:25 +0000
parents 75be3005640e
children 12f029b89956
comparison
equal deleted inserted replaced
11076:75be3005640e 11077:9f526e2e511e
487 static void yahoo_process_cookie(struct yahoo_data *yd, char *c) 487 static void yahoo_process_cookie(struct yahoo_data *yd, char *c)
488 { 488 {
489 if (c[0] == 'Y') { 489 if (c[0] == 'Y') {
490 if (yd->cookie_y) 490 if (yd->cookie_y)
491 g_free(yd->cookie_y); 491 g_free(yd->cookie_y);
492 yd->cookie_y = _getcookie(c); 492 yd->cookie_y = _getcookie(c);
493 } else if (c[0] == 'T') { 493 } else if (c[0] == 'T') {
494 if (yd->cookie_t) 494 if (yd->cookie_t)
495 g_free(yd->cookie_t); 495 g_free(yd->cookie_t);
496 yd->cookie_t = _getcookie(c); 496 yd->cookie_t = _getcookie(c);
497 } 497 }
1143 GaimAccount *account = gaim_connection_get_account(gc); 1143 GaimAccount *account = gaim_connection_get_account(gc);
1144 const char *name = gaim_normalize(account, gaim_account_get_username(account)); 1144 const char *name = gaim_normalize(account, gaim_account_get_username(account));
1145 const char *pass = gaim_connection_get_password(gc); 1145 const char *pass = gaim_connection_get_password(gc);
1146 struct yahoo_data *yd = gc->proto_data; 1146 struct yahoo_data *yd = gc->proto_data;
1147 1147
1148 GaimCipher *md5_cipher; 1148 GaimCipher *md5_cipher;
1149 GaimCipherContext *md5_ctx; 1149 GaimCipherContext *md5_ctx;
1150 guint8 md5_digest[16]; 1150 guint8 md5_digest[16];
1151 1151
1152 GaimCipher *sha1_cipher; 1152 GaimCipher *sha1_cipher;
1153 GaimCipherContext *sha1_ctx1; 1153 GaimCipherContext *sha1_ctx1;
1171 char resp_6[100]; 1171 char resp_6[100];
1172 char resp_96[100]; 1172 char resp_96[100];
1173 1173
1174 unsigned char digest1[20]; 1174 unsigned char digest1[20];
1175 unsigned char digest2[20]; 1175 unsigned char digest2[20];
1176 unsigned char comparison_src[20]; 1176 unsigned char comparison_src[20];
1177 unsigned char magic_key_char[4]; 1177 unsigned char magic_key_char[4];
1178 const unsigned char *magic_ptr; 1178 const unsigned char *magic_ptr;
1179 1179
1180 unsigned int magic[64]; 1180 unsigned int magic[64];
1181 unsigned int magic_work = 0; 1181 unsigned int magic_work = 0;
1206 1206
1207 sha1_cipher = gaim_ciphers_find_cipher("sha1"); 1207 sha1_cipher = gaim_ciphers_find_cipher("sha1");
1208 sha1_ctx1 = gaim_cipher_context_new(sha1_cipher, NULL); 1208 sha1_ctx1 = gaim_cipher_context_new(sha1_cipher, NULL);
1209 sha1_ctx2 = gaim_cipher_context_new(sha1_cipher, NULL); 1209 sha1_ctx2 = gaim_cipher_context_new(sha1_cipher, NULL);
1210 1210
1211 /* 1211 /*
1212 * Magic: Phase 1. Generate what seems to be a 30 byte value (could change if base64 1212 * Magic: Phase 1. Generate what seems to be a 30 byte value (could change if base64
1213 * ends up differently? I don't remember and I'm tired, so use a 64 byte buffer. 1213 * ends up differently? I don't remember and I'm tired, so use a 64 byte buffer.
1214 */ 1214 */
1215 1215
1216 magic_ptr = seed; 1216 magic_ptr = seed;
1217 1217
1218 while (*magic_ptr != (int)NULL) { 1218 while (*magic_ptr != (int)NULL) {
1219 char *loc; 1219 char *loc;
1220 1220
1221 /* Ignore parentheses. 1221 /* Ignore parentheses.
1222 */ 1222 */
1223 1223
1224 if (*magic_ptr == '(' || *magic_ptr == ')') { 1224 if (*magic_ptr == '(' || *magic_ptr == ')') {
1225 magic_ptr++; 1225 magic_ptr++;
1226 continue; 1226 continue;
1227 } 1227 }
1228 1228
1229 /* Characters and digits verify against the challenge lookup. 1229 /* Characters and digits verify against the challenge lookup.
1230 */ 1230 */
1231 1231
1232 if (isalpha(*magic_ptr) || isdigit(*magic_ptr)) { 1232 if (isalpha(*magic_ptr) || isdigit(*magic_ptr)) {
1233 loc = strchr(challenge_lookup, *magic_ptr); 1233 loc = strchr(challenge_lookup, *magic_ptr);
1234 if (!loc) { 1234 if (!loc) {
1235 /* SME XXX Error - disconnect here */ 1235 /* SME XXX Error - disconnect here */
1236 } 1236 }
1237 1237
1238 /* Get offset into lookup table and shl 3. 1238 /* Get offset into lookup table and shl 3.
1239 */ 1239 */
1240 1240
1241 magic_work = loc - challenge_lookup; 1241 magic_work = loc - challenge_lookup;
1242 magic_work <<= 3; 1242 magic_work <<= 3;
1243 1243
1244 magic_ptr++; 1244 magic_ptr++;
1245 continue; 1245 continue;
1246 } else { 1246 } else {
1247 unsigned int local_store; 1247 unsigned int local_store;
1248 1248
1249 loc = strchr(operand_lookup, *magic_ptr); 1249 loc = strchr(operand_lookup, *magic_ptr);
1250 if (!loc) { 1250 if (!loc) {
1251 /* SME XXX Disconnect */ 1251 /* SME XXX Disconnect */
1252 } 1252 }
1253 1253
1254 local_store = loc - operand_lookup; 1254 local_store = loc - operand_lookup;
1255 1255
1256 /* Oops; how did this happen? 1256 /* Oops; how did this happen?
1257 */ 1257 */
1258 1258
1259 if (magic_cnt >= 64) 1259 if (magic_cnt >= 64)
1260 break; 1260 break;
1261 1261
1262 magic[magic_cnt++] = magic_work | local_store; 1262 magic[magic_cnt++] = magic_work | local_store;
1263 magic_ptr++; 1263 magic_ptr++;
1264 continue; 1264 continue;
1265 } 1265 }
1266 } 1266 }
1267 1267
1268 magic_len = magic_cnt; 1268 magic_len = magic_cnt;
1269 magic_cnt = 0; 1269 magic_cnt = 0;
1270 1270
1271 /* Magic: Phase 2. Take generated magic value and sprinkle fairy dust on the values. 1271 /* Magic: Phase 2. Take generated magic value and sprinkle fairy dust on the values.
1272 */ 1272 */
1273 1273
1274 for (magic_cnt = magic_len-2; magic_cnt >= 0; magic_cnt--) { 1274 for (magic_cnt = magic_len-2; magic_cnt >= 0; magic_cnt--) {
1275 unsigned char byte1; 1275 unsigned char byte1;
1276 unsigned char byte2; 1276 unsigned char byte2;
1277 1277
1278 /* Bad. Abort. 1278 /* Bad. Abort.
1279 */ 1279 */
1280 1280
1281 if ((magic_cnt + 1 > magic_len) || (magic_cnt > magic_len)) 1281 if ((magic_cnt + 1 > magic_len) || (magic_cnt > magic_len))
1282 break; 1282 break;
1283 1283
1284 byte1 = magic[magic_cnt]; 1284 byte1 = magic[magic_cnt];
1285 byte2 = magic[magic_cnt+1]; 1285 byte2 = magic[magic_cnt+1];
1286 1286
1287 byte1 *= 0xcd; 1287 byte1 *= 0xcd;
1288 byte1 ^= byte2; 1288 byte1 ^= byte2;
1289 1289
1290 magic[magic_cnt+1] = byte1; 1290 magic[magic_cnt+1] = byte1;
1291 } 1291 }
1292 1292
1293 /* 1293 /*
1294 * Magic: Phase 3. This computes 20 bytes. The first 4 bytes are used as our magic 1294 * Magic: Phase 3. This computes 20 bytes. The first 4 bytes are used as our magic
1295 * key (and may be changed later); the next 16 bytes are an MD5 sum of the magic key 1295 * key (and may be changed later); the next 16 bytes are an MD5 sum of the magic key
1296 * plus 3 bytes. The 3 bytes are found by looping, and they represent the offsets 1296 * plus 3 bytes. The 3 bytes are found by looping, and they represent the offsets
1297 * into particular functions we'll later call to potentially alter the magic key. 1297 * into particular functions we'll later call to potentially alter the magic key.
1298 * 1298 *
1299 * %-) 1299 * %-)
1300 */ 1300 */
1301 1301
1302 magic_cnt = 1; 1302 magic_cnt = 1;
1303 x = 0; 1303 x = 0;
1304 1304
1305 do { 1305 do {
1306 unsigned int bl = 0; 1306 unsigned int bl = 0;
1307 unsigned int cl = magic[magic_cnt++]; 1307 unsigned int cl = magic[magic_cnt++];
1308 1308
1309 if (magic_cnt >= magic_len) 1309 if (magic_cnt >= magic_len)
1310 break; 1310 break;
1311 1311
1312 if (cl > 0x7F) { 1312 if (cl > 0x7F) {
1313 if (cl < 0xe0) 1313 if (cl < 0xe0)
1314 bl = cl = (cl & 0x1f) << 6; 1314 bl = cl = (cl & 0x1f) << 6;
1315 else { 1315 else {
1316 bl = magic[magic_cnt++]; 1316 bl = magic[magic_cnt++];
1317 cl = (cl & 0x0f) << 6; 1317 cl = (cl & 0x0f) << 6;
1318 bl = ((bl & 0x3f) + cl) << 6; 1318 bl = ((bl & 0x3f) + cl) << 6;
1319 } 1319 }
1320 1320
1321 cl = magic[magic_cnt++]; 1321 cl = magic[magic_cnt++];
1322 bl = (cl & 0x3f) + bl; 1322 bl = (cl & 0x3f) + bl;
1323 } else 1323 } else
1324 bl = cl; 1324 bl = cl;
1325 1325
1326 comparison_src[x++] = (bl & 0xff00) >> 8; 1326 comparison_src[x++] = (bl & 0xff00) >> 8;
1327 comparison_src[x++] = bl & 0xff; 1327 comparison_src[x++] = bl & 0xff;
1328 } while (x < 20); 1328 } while (x < 20);
1329 1329
1330 /* First four bytes are magic key. */ 1330 /* First four bytes are magic key. */
1331 memcpy(&magic_key_char[0], comparison_src, 4); 1331 memcpy(&magic_key_char[0], comparison_src, 4);
1332 magic_4 = magic_key_char[0] | (magic_key_char[1]<<8) | (magic_key_char[2]<<16) | (magic_key_char[3]<<24); 1332 magic_4 = magic_key_char[0] | (magic_key_char[1]<<8) | (magic_key_char[2]<<16) | (magic_key_char[3]<<24);
1333 1333
1334 /* 1334 /*
1335 * Magic: Phase 4. Determine what function to use later by getting outside/inside 1335 * Magic: Phase 4. Determine what function to use later by getting outside/inside
1336 * loop values until we match our previous buffer. 1336 * loop values until we match our previous buffer.
1337 */ 1337 */
1338 for (x = 0; x < 65535; x++) { 1338 for (x = 0; x < 65535; x++) {
1339 int leave = 0; 1339 int leave = 0;
1343 1343
1344 /* Calculate buffer. */ 1344 /* Calculate buffer. */
1345 test[0] = x; 1345 test[0] = x;
1346 test[1] = x >> 8; 1346 test[1] = x >> 8;
1347 test[2] = y; 1347 test[2] = y;
1348 1348
1349 gaim_cipher_context_reset(md5_ctx, NULL); 1349 gaim_cipher_context_reset(md5_ctx, NULL);
1350 gaim_cipher_context_append(md5_ctx, magic_key_char, 4); 1350 gaim_cipher_context_append(md5_ctx, magic_key_char, 4);
1351 gaim_cipher_context_append(md5_ctx, test, 3); 1351 gaim_cipher_context_append(md5_ctx, test, 3);
1352 gaim_cipher_context_digest(md5_ctx, sizeof(md5_digest), 1352 gaim_cipher_context_digest(md5_ctx, sizeof(md5_digest),
1353 md5_digest, NULL); 1353 md5_digest, NULL);
1354 1354
1355 if (!memcmp(md5_digest, comparison_src+4, 16)) { 1355 if (!memcmp(md5_digest, comparison_src+4, 16)) {
1356 leave = 1; 1356 leave = 1;
1357 break; 1357 break;
1358 } 1358 }
1359 } 1359 }
1360 1360
1361 if (leave == 1) 1361 if (leave == 1)
1362 break; 1362 break;
1363 } 1363 }
1364 1364
1365 /* If y != 0, we need some help. */ 1365 /* If y != 0, we need some help. */
1366 if (y != 0) { 1366 if (y != 0) {
1367 unsigned int updated_key; 1367 unsigned int updated_key;
1368 1368
1369 /* Update magic stuff. 1369 /* Update magic stuff.
1374 1374
1375 magic_key_char[0] = updated_key & 0xff; 1375 magic_key_char[0] = updated_key & 0xff;
1376 magic_key_char[1] = (updated_key >> 8) & 0xff; 1376 magic_key_char[1] = (updated_key >> 8) & 0xff;
1377 magic_key_char[2] = (updated_key >> 16) & 0xff; 1377 magic_key_char[2] = (updated_key >> 16) & 0xff;
1378 magic_key_char[3] = (updated_key >> 24) & 0xff; 1378 magic_key_char[3] = (updated_key >> 24) & 0xff;
1379 } 1379 }
1380 1380
1381 /* Get password and crypt hashes as per usual. */ 1381 /* Get password and crypt hashes as per usual. */
1382 gaim_cipher_context_reset(md5_ctx, NULL); 1382 gaim_cipher_context_reset(md5_ctx, NULL);
1383 gaim_cipher_context_append(md5_ctx, pass, strlen(pass)); 1383 gaim_cipher_context_append(md5_ctx, pass, strlen(pass));
1384 gaim_cipher_context_digest(md5_ctx, sizeof(md5_digest), 1384 gaim_cipher_context_digest(md5_ctx, sizeof(md5_digest),
1385 md5_digest, NULL); 1385 md5_digest, NULL);
1386 to_y64(password_hash, md5_digest, 16); 1386 to_y64(password_hash, md5_digest, 16);
1387 1387
1388 crypt_result = yahoo_crypt(pass, "$1$_2S43d5f$"); 1388 crypt_result = yahoo_crypt(pass, "$1$_2S43d5f$");
1389 gaim_cipher_context_reset(md5_ctx, NULL); 1389 gaim_cipher_context_reset(md5_ctx, NULL);
1390 gaim_cipher_context_append(md5_ctx, crypt_result, strlen(crypt_result)); 1390 gaim_cipher_context_append(md5_ctx, crypt_result, strlen(crypt_result));
1391 gaim_cipher_context_digest(md5_ctx, sizeof(md5_digest), 1391 gaim_cipher_context_digest(md5_ctx, sizeof(md5_digest),
1392 md5_digest, NULL); 1392 md5_digest, NULL);
1393 to_y64(crypt_hash, md5_digest, 16); 1393 to_y64(crypt_hash, md5_digest, 16);
1394 1394
1395 /* Our first authentication response is based off of the password hash. */ 1395 /* Our first authentication response is based off of the password hash. */
1396 for (x = 0; x < (int)strlen(password_hash); x++) 1396 for (x = 0; x < (int)strlen(password_hash); x++)
1397 pass_hash_xor1[cnt++] = password_hash[x] ^ 0x36; 1397 pass_hash_xor1[cnt++] = password_hash[x] ^ 0x36;
1398 1398
1399 if (cnt < 64) 1399 if (cnt < 64)
1400 memset(&(pass_hash_xor1[cnt]), 0x36, 64-cnt); 1400 memset(&(pass_hash_xor1[cnt]), 0x36, 64-cnt);
1401 1401
1402 cnt = 0; 1402 cnt = 0;
1403 1403
1404 for (x = 0; x < (int)strlen(password_hash); x++) 1404 for (x = 0; x < (int)strlen(password_hash); x++)
1405 pass_hash_xor2[cnt++] = password_hash[x] ^ 0x5c; 1405 pass_hash_xor2[cnt++] = password_hash[x] ^ 0x5c;
1406 1406
1407 if (cnt < 64) 1407 if (cnt < 64)
1408 memset(&(pass_hash_xor2[cnt]), 0x5c, 64-cnt); 1408 memset(&(pass_hash_xor2[cnt]), 0x5c, 64-cnt);
1409 1409
1410 /* 1410 /*
1411 * The first context gets the password hash XORed with 0x36 plus a magic value 1411 * The first context gets the password hash XORed with 0x36 plus a magic value
1412 * which we previously extrapolated from our challenge. 1412 * which we previously extrapolated from our challenge.
1413 */ 1413 */
1414 1414
1415 gaim_cipher_context_append(sha1_ctx1, pass_hash_xor1, 64); 1415 gaim_cipher_context_append(sha1_ctx1, pass_hash_xor1, 64);
1416 if (y >= 3) 1416 if (y >= 3)
1417 gaim_cipher_context_set_option(sha1_ctx1, "sizeLo", GINT_TO_POINTER(0x1ff)); 1417 gaim_cipher_context_set_option(sha1_ctx1, "sizeLo", GINT_TO_POINTER(0x1ff));
1418 gaim_cipher_context_append(sha1_ctx1, magic_key_char, 4); 1418 gaim_cipher_context_append(sha1_ctx1, magic_key_char, 4);
1419 gaim_cipher_context_digest(sha1_ctx1, sizeof(digest1), digest1, NULL); 1419 gaim_cipher_context_digest(sha1_ctx1, sizeof(digest1), digest1, NULL);
1420 1420
1421 /* 1421 /*
1422 * The second context gets the password hash XORed with 0x5c plus the SHA-1 digest 1422 * The second context gets the password hash XORed with 0x5c plus the SHA-1 digest
1423 * of the first context. 1423 * of the first context.
1424 */ 1424 */
1425 1425
1426 gaim_cipher_context_append(sha1_ctx2, pass_hash_xor2, 64); 1426 gaim_cipher_context_append(sha1_ctx2, pass_hash_xor2, 64);
1427 gaim_cipher_context_append(sha1_ctx2, digest1, 20); 1427 gaim_cipher_context_append(sha1_ctx2, digest1, 20);
1428 gaim_cipher_context_digest(sha1_ctx2, sizeof(digest2), digest2, NULL); 1428 gaim_cipher_context_digest(sha1_ctx2, sizeof(digest2), digest2, NULL);
1429 1429
1430 /* 1430 /*
1431 * Now that we have digest2, use it to fetch characters from an alphabet to construct 1431 * Now that we have digest2, use it to fetch characters from an alphabet to construct
1432 * our first authentication response. 1432 * our first authentication response.
1433 */ 1433 */
1434 1434
1435 for (x = 0; x < 20; x += 2) { 1435 for (x = 0; x < 20; x += 2) {
1436 unsigned int val = 0; 1436 unsigned int val = 0;
1437 unsigned int lookup = 0; 1437 unsigned int lookup = 0;
1438 1438
1439 char byte[6]; 1439 char byte[6];
1440 1440
1441 memset(&byte, 0, 6); 1441 memset(&byte, 0, 6);
1442 1442
1443 /* First two bytes of digest stuffed together. 1443 /* First two bytes of digest stuffed together.
1444 */ 1444 */
1445 1445
1446 val = digest2[x]; 1446 val = digest2[x];
1447 val <<= 8; 1447 val <<= 8;
1448 val += digest2[x+1]; 1448 val += digest2[x+1];
1449 1449
1450 lookup = (val >> 0x0b); 1450 lookup = (val >> 0x0b);
1451 lookup &= 0x1f; 1451 lookup &= 0x1f;
1452 if (lookup >= strlen(alphabet1)) 1452 if (lookup >= strlen(alphabet1))
1453 break; 1453 break;
1454 sprintf(byte, "%c", alphabet1[lookup]); 1454 sprintf(byte, "%c", alphabet1[lookup]);
1459 lookup &= 0x1f; 1459 lookup &= 0x1f;
1460 if (lookup >= strlen(alphabet2)) 1460 if (lookup >= strlen(alphabet2))
1461 break; 1461 break;
1462 sprintf(byte, "%c", alphabet2[lookup]); 1462 sprintf(byte, "%c", alphabet2[lookup]);
1463 strcat(resp_6, byte); 1463 strcat(resp_6, byte);
1464 1464
1465 lookup = (val >> 0x01); 1465 lookup = (val >> 0x01);
1466 lookup &= 0x1f; 1466 lookup &= 0x1f;
1467 if (lookup >= strlen(alphabet2)) 1467 if (lookup >= strlen(alphabet2))
1468 break; 1468 break;
1469 sprintf(byte, "%c", alphabet2[lookup]); 1469 sprintf(byte, "%c", alphabet2[lookup]);
1473 if (lookup >= strlen(delimit_lookup)) 1473 if (lookup >= strlen(delimit_lookup))
1474 break; 1474 break;
1475 sprintf(byte, "%c", delimit_lookup[lookup]); 1475 sprintf(byte, "%c", delimit_lookup[lookup]);
1476 strcat(resp_6, byte); 1476 strcat(resp_6, byte);
1477 } 1477 }
1478 1478
1479 /* Our second authentication response is based off of the crypto hash. 1479 /* Our second authentication response is based off of the crypto hash.
1480 */ 1480 */
1481 1481
1482 cnt = 0; 1482 cnt = 0;
1483 memset(&digest1, 0, 20); 1483 memset(&digest1, 0, 20);
1484 memset(&digest2, 0, 20); 1484 memset(&digest2, 0, 20);
1485 1485
1486 for (x = 0; x < (int)strlen(crypt_hash); x++) 1486 for (x = 0; x < (int)strlen(crypt_hash); x++)
1487 crypt_hash_xor1[cnt++] = crypt_hash[x] ^ 0x36; 1487 crypt_hash_xor1[cnt++] = crypt_hash[x] ^ 0x36;
1488 1488
1489 if (cnt < 64) 1489 if (cnt < 64)
1490 memset(&(crypt_hash_xor1[cnt]), 0x36, 64-cnt); 1490 memset(&(crypt_hash_xor1[cnt]), 0x36, 64-cnt);
1491 1491
1492 cnt = 0; 1492 cnt = 0;
1493 1493
1494 for (x = 0; x < (int)strlen(crypt_hash); x++) 1494 for (x = 0; x < (int)strlen(crypt_hash); x++)
1495 crypt_hash_xor2[cnt++] = crypt_hash[x] ^ 0x5c; 1495 crypt_hash_xor2[cnt++] = crypt_hash[x] ^ 0x5c;
1496 1496
1497 if (cnt < 64) 1497 if (cnt < 64)
1498 memset(&(crypt_hash_xor2[cnt]), 0x5c, 64-cnt); 1498 memset(&(crypt_hash_xor2[cnt]), 0x5c, 64-cnt);
1499 1499
1500 gaim_cipher_context_reset(sha1_ctx1, NULL); 1500 gaim_cipher_context_reset(sha1_ctx1, NULL);
1501 gaim_cipher_context_reset(sha1_ctx2, NULL); 1501 gaim_cipher_context_reset(sha1_ctx2, NULL);
1502 1502
1503 /* 1503 /*
1504 * The first context gets the password hash XORed with 0x36 plus a magic value 1504 * The first context gets the password hash XORed with 0x36 plus a magic value
1505 * which we previously extrapolated from our challenge. 1505 * which we previously extrapolated from our challenge.
1506 */ 1506 */
1507 1507
1508 gaim_cipher_context_append(sha1_ctx1, crypt_hash_xor1, 64); 1508 gaim_cipher_context_append(sha1_ctx1, crypt_hash_xor1, 64);
1509 if (y >= 3) { 1509 if (y >= 3) {
1510 gaim_cipher_context_set_option(sha1_ctx1, "sizeLo", 1510 gaim_cipher_context_set_option(sha1_ctx1, "sizeLo",
1511 GINT_TO_POINTER(0x1ff)); 1511 GINT_TO_POINTER(0x1ff));
1512 } 1512 }
1513 gaim_cipher_context_append(sha1_ctx1, magic_key_char, 4); 1513 gaim_cipher_context_append(sha1_ctx1, magic_key_char, 4);
1514 gaim_cipher_context_digest(sha1_ctx1, sizeof(digest1), digest1, NULL); 1514 gaim_cipher_context_digest(sha1_ctx1, sizeof(digest1), digest1, NULL);
1515 1515
1516 /* 1516 /*
1517 * The second context gets the password hash XORed with 0x5c plus the SHA-1 digest 1517 * The second context gets the password hash XORed with 0x5c plus the SHA-1 digest
1518 * of the first context. 1518 * of the first context.
1519 */ 1519 */
1520 1520
1521 gaim_cipher_context_append(sha1_ctx2, crypt_hash_xor2, 64); 1521 gaim_cipher_context_append(sha1_ctx2, crypt_hash_xor2, 64);
1522 gaim_cipher_context_append(sha1_ctx2, digest1, 20); 1522 gaim_cipher_context_append(sha1_ctx2, digest1, 20);
1523 gaim_cipher_context_digest(sha1_ctx2, sizeof(digest2), digest2, NULL); 1523 gaim_cipher_context_digest(sha1_ctx2, sizeof(digest2), digest2, NULL);
1524 1524
1525 /* 1525 /*
1526 * Now that we have digest2, use it to fetch characters from an alphabet to construct 1526 * Now that we have digest2, use it to fetch characters from an alphabet to construct
1527 * our first authentication response. 1527 * our first authentication response.
1528 */ 1528 */
1529 1529
1530 for (x = 0; x < 20; x += 2) { 1530 for (x = 0; x < 20; x += 2) {
1531 unsigned int val = 0; 1531 unsigned int val = 0;
1532 unsigned int lookup = 0; 1532 unsigned int lookup = 0;
1533 1533
1534 char byte[6]; 1534 char byte[6];
1535 1535
1536 memset(&byte, 0, 6); 1536 memset(&byte, 0, 6);
1537 1537
1538 /* First two bytes of digest stuffed together. 1538 /* First two bytes of digest stuffed together.
1539 */ 1539 */
1540 1540
1541 val = digest2[x]; 1541 val = digest2[x];
1542 val <<= 8; 1542 val <<= 8;
1543 val += digest2[x+1]; 1543 val += digest2[x+1];
1544 1544
1545 lookup = (val >> 0x0b); 1545 lookup = (val >> 0x0b);
1547 if (lookup >= strlen(alphabet1)) 1547 if (lookup >= strlen(alphabet1))
1548 break; 1548 break;
1549 sprintf(byte, "%c", alphabet1[lookup]); 1549 sprintf(byte, "%c", alphabet1[lookup]);
1550 strcat(resp_96, byte); 1550 strcat(resp_96, byte);
1551 strcat(resp_96, "="); 1551 strcat(resp_96, "=");
1552 1552
1553 lookup = (val >> 0x06); 1553 lookup = (val >> 0x06);
1554 lookup &= 0x1f; 1554 lookup &= 0x1f;
1555 if (lookup >= strlen(alphabet2)) 1555 if (lookup >= strlen(alphabet2))
1556 break; 1556 break;
1557 sprintf(byte, "%c", alphabet2[lookup]); 1557 sprintf(byte, "%c", alphabet2[lookup]);
1558 strcat(resp_96, byte); 1558 strcat(resp_96, byte);
1559 1559
1560 lookup = (val >> 0x01); 1560 lookup = (val >> 0x01);
1561 lookup &= 0x1f; 1561 lookup &= 0x1f;
1562 if (lookup >= strlen(alphabet2)) 1562 if (lookup >= strlen(alphabet2))
1563 break; 1563 break;
1564 sprintf(byte, "%c", alphabet2[lookup]); 1564 sprintf(byte, "%c", alphabet2[lookup]);
1565 strcat(resp_96, byte); 1565 strcat(resp_96, byte);
1566 1566
1567 lookup = (val & 0x01); 1567 lookup = (val & 0x01);
1568 if (lookup >= strlen(delimit_lookup)) 1568 if (lookup >= strlen(delimit_lookup))
1569 break; 1569 break;
1570 sprintf(byte, "%c", delimit_lookup[lookup]); 1570 sprintf(byte, "%c", delimit_lookup[lookup]);
1571 strcat(resp_96, byte); 1571 strcat(resp_96, byte);
1572 } 1572 }
1573 gaim_debug_info("yahoo", "yahoo status: %d\n", yd->current_status); 1573 gaim_debug_info("yahoo", "yahoo status: %d\n", yd->current_status);
1574 pack = yahoo_packet_new(YAHOO_SERVICE_AUTHRESP, yd->current_status, 0); 1574 pack = yahoo_packet_new(YAHOO_SERVICE_AUTHRESP, yd->current_status, 0);
1575 yahoo_packet_hash(pack, "sssss", 0, name, 6, resp_6, 96, resp_96, 1, 1575 yahoo_packet_hash(pack, "sssss", 0, name, 6, resp_6, 96, resp_96, 1,
1576 name, 135, "6,0,0,1710"); 1576 name, 135, "6,0,0,1710");
1577 if (yd->picture_checksum) 1577 if (yd->picture_checksum)
1578 yahoo_packet_hash_int(pack, 192, yd->picture_checksum); 1578 yahoo_packet_hash_int(pack, 192, yd->picture_checksum);
1579 1579
1580 yahoo_packet_send_and_free(pack, yd); 1580 yahoo_packet_send_and_free(pack, yd);
1581 1581
1582 gaim_cipher_context_destroy(md5_ctx); 1582 gaim_cipher_context_destroy(md5_ctx);
1583 gaim_cipher_context_destroy(sha1_ctx1); 1583 gaim_cipher_context_destroy(sha1_ctx1);
1584 gaim_cipher_context_destroy(sha1_ctx2); 1584 gaim_cipher_context_destroy(sha1_ctx2);
2147 } 2147 }
2148 2148
2149 yd = gc->proto_data; 2149 yd = gc->proto_data;
2150 yd->fd = source; 2150 yd->fd = source;
2151 2151
2152 pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH, yd->current_status, 0); 2152 pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH, YAHOO_STATUS_AVAILABLE, 0);
2153 2153
2154 yahoo_packet_hash_str(pkt, 1, gaim_normalize(gc->account, gaim_account_get_username(gaim_connection_get_account(gc)))); 2154 yahoo_packet_hash_str(pkt, 1, gaim_normalize(gc->account, gaim_account_get_username(gaim_connection_get_account(gc))));
2155 yahoo_packet_send_and_free(pkt, yd); 2155 yahoo_packet_send_and_free(pkt, yd);
2156 2156
2157 gc->inpa = gaim_input_add(yd->fd, GAIM_INPUT_READ, yahoo_pending, gc); 2157 gc->inpa = gaim_input_add(yd->fd, GAIM_INPUT_READ, yahoo_pending, gc);
2222 if (gaim_proxy_connect(account, "wcs2.msg.dcn.yahoo.com", 2222 if (gaim_proxy_connect(account, "wcs2.msg.dcn.yahoo.com",
2223 gaim_account_get_int(account, "port", YAHOO_PAGER_PORT), 2223 gaim_account_get_int(account, "port", YAHOO_PAGER_PORT),
2224 yahoo_got_web_connected, gc) != 0) { 2224 yahoo_got_web_connected, gc) != 0) {
2225 gaim_connection_error(gc, _("Connection problem")); 2225 gaim_connection_error(gc, _("Connection problem"));
2226 return; 2226 return;
2227 } 2227 }
2228 } 2228 }
2229 2229
2230 static void yahoo_got_cookies(gpointer data, gint source, GaimInputCondition cond) 2230 static void yahoo_got_cookies(gpointer data, gint source, GaimInputCondition cond)
2231 { 2231 {
2232 GaimConnection *gc = data; 2232 GaimConnection *gc = data;
2262 char *d; 2262 char *d;
2263 char name[64], value[64]; 2263 char name[64], value[64];
2264 int count = sizeof(name)-1; 2264 int count = sizeof(name)-1;
2265 while ((c < (buf + len)) && (c = strstr(c, "<input "))) { 2265 while ((c < (buf + len)) && (c = strstr(c, "<input "))) {
2266 c = strstr(c, "name=\"") + strlen("name=\""); 2266 c = strstr(c, "name=\"") + strlen("name=\"");
2267 for (d = name; *c!='"' && count; c++, d++, count--) 2267 for (d = name; *c!='"' && count; c++, d++, count--)
2268 *d = *c; 2268 *d = *c;
2269 *d = '\0'; 2269 *d = '\0';
2270 count = sizeof(value)-1; 2270 count = sizeof(value)-1;
2271 d = strstr(c, "value=\"") + strlen("value=\""); 2271 d = strstr(c, "value=\"") + strlen("value=\"");
2272 if (strchr(c, '>') < d) 2272 if (strchr(c, '>') < d)
2328 g_snprintf(hashp, 3, "%02x", digest[i]); 2328 g_snprintf(hashp, 3, "%02x", digest[i]);
2329 hashp += 2; 2329 hashp += 2;
2330 } 2330 }
2331 */ 2331 */
2332 g_free(chal); 2332 g_free(chal);
2333 2333
2334 url = g_string_append(url, md5); 2334 url = g_string_append(url, md5);
2335 g_hash_table_foreach(hash, (GHFunc)yahoo_login_page_hash_iter, url); 2335 g_hash_table_foreach(hash, (GHFunc)yahoo_login_page_hash_iter, url);
2336 2336
2337 url = g_string_append(url, "&.hash=1&.md5=1 HTTP/1.1\r\n" 2337 url = g_string_append(url, "&.hash=1&.md5=1 HTTP/1.1\r\n"
2338 "Host: login.yahoo.com\r\n\r\n"); 2338 "Host: login.yahoo.com\r\n\r\n");
2339 g_hash_table_destroy(hash); 2339 g_hash_table_destroy(hash);
2340 yd->auth = g_string_free(url, FALSE); 2340 yd->auth = g_string_free(url, FALSE);
2341 if (gaim_proxy_connect(account, "login.yahoo.com", 80, yahoo_got_cookies, gc) != 0) { 2341 if (gaim_proxy_connect(account, "login.yahoo.com", 80, yahoo_got_cookies, gc) != 0) {
2494 GaimPresence *presence; 2494 GaimPresence *presence;
2495 GaimStatus *status; 2495 GaimStatus *status;
2496 const char *status_id; 2496 const char *status_id;
2497 2497
2498 if (!b || !(account = b->account) || !(gc = gaim_account_get_connection(account)) || 2498 if (!b || !(account = b->account) || !(gc = gaim_account_get_connection(account)) ||
2499 !(yd = gc->proto_data)) 2499 !(yd = gc->proto_data))
2500 return; 2500 return;
2501 2501
2502 f = yahoo_friend_find(gc, b->name); 2502 f = yahoo_friend_find(gc, b->name);
2503 if (!f) { 2503 if (!f) {
2504 *se = "notauthorized"; 2504 *se = "notauthorized";
2652 return NULL; 2652 return NULL;
2653 return g_markup_escape_text(msg, strlen(msg)); 2653 return g_markup_escape_text(msg, strlen(msg));
2654 2654
2655 default: 2655 default:
2656 return g_strdup(yahoo_get_status_string(f->status)); 2656 return g_strdup(yahoo_get_status_string(f->status));
2657 } 2657 }
2658 } 2658 }
2659 2659
2660 char *yahoo_tooltip_text(GaimBuddy *b) 2660 char *yahoo_tooltip_text(GaimBuddy *b)
2661 { 2661 {
2662 YahooFriend *f; 2662 YahooFriend *f;
3437 "Trying to join %s \n", args[0]); 3437 "Trying to join %s \n", args[0]);
3438 3438
3439 comp = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); 3439 comp = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
3440 g_hash_table_replace(comp, g_strdup("room"), 3440 g_hash_table_replace(comp, g_strdup("room"),
3441 g_strdup_printf("%s", g_ascii_strdown(args[0], strlen(args[0])))); 3441 g_strdup_printf("%s", g_ascii_strdown(args[0], strlen(args[0]))));
3442 g_hash_table_replace(comp, g_strdup("type"), g_strdup("Chat")); 3442 g_hash_table_replace(comp, g_strdup("type"), g_strdup("Chat"));
3443 3443
3444 yahoo_c_join(gc, comp); 3444 yahoo_c_join(gc, comp);
3445 3445
3446 g_hash_table_destroy(comp); 3446 g_hash_table_destroy(comp);
3447 return GAIM_CMD_RET_OK; 3447 return GAIM_CMD_RET_OK;