Mercurial > pidgin.yaz
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; |