| 847 *out++ = '-'; |
848 *out++ = '-'; |
| 848 } |
849 } |
| 849 *out = '\0'; |
850 *out = '\0'; |
| 850 } |
851 } |
| 851 |
852 |
| |
853 static void yahoo_process_auth_old(GaimConnection *gc, const char *seed) |
| |
854 { |
| |
855 struct yahoo_packet *pack; |
| |
856 GaimAccount *account = gaim_connection_get_account(gc); |
| |
857 const char *name = normalize(gaim_account_get_username(account)); |
| |
858 const char *pass = gaim_account_get_password(account); |
| |
859 struct yahoo_data *yd = gc->proto_data; |
| |
860 |
| |
861 /* So, Yahoo has stopped supporting its older clients in India, and undoubtedly |
| |
862 * will soon do so in the rest of the world. |
| |
863 * |
| |
864 * The new clients use this authentication method. I warn you in advance, it's |
| |
865 * bizzare, convoluted, inordinately complicated. It's also no more secure than |
| |
866 * crypt() was. The only purpose this scheme could serve is to prevent third |
| |
867 * part clients from connecting to their servers. |
| |
868 * |
| |
869 * Sorry, Yahoo. |
| |
870 */ |
| |
871 |
| |
872 md5_byte_t result[16]; |
| |
873 md5_state_t ctx; |
| |
874 |
| |
875 char *crypt_result; |
| |
876 char password_hash[25]; |
| |
877 char crypt_hash[25]; |
| |
878 char *hash_string_p = g_malloc(50 + strlen(name)); |
| |
879 char *hash_string_c = g_malloc(50 + strlen(name)); |
| |
880 |
| |
881 char checksum; |
| |
882 |
| |
883 int sv; |
| |
884 |
| |
885 char result6[25]; |
| |
886 char result96[25]; |
| |
887 |
| |
888 sv = seed[15]; |
| |
889 sv = sv % 8; |
| |
890 |
| |
891 md5_init(&ctx); |
| |
892 md5_append(&ctx, pass, strlen(pass)); |
| |
893 md5_finish(&ctx, result); |
| |
894 to_y64(password_hash, result, 16); |
| |
895 |
| |
896 md5_init(&ctx); |
| |
897 crypt_result = yahoo_crypt(pass, "$1$_2S43d5f$"); |
| |
898 md5_append(&ctx, crypt_result, strlen(crypt_result)); |
| |
899 md5_finish(&ctx, result); |
| |
900 to_y64(crypt_hash, result, 16); |
| |
901 |
| |
902 switch (sv) { |
| |
903 case 1: |
| |
904 case 6: |
| |
905 checksum = seed[seed[9] % 16]; |
| |
906 g_snprintf(hash_string_p, strlen(name) + 50, |
| |
907 "%c%s%s%s", checksum, name, seed, password_hash); |
| |
908 g_snprintf(hash_string_c, strlen(name) + 50, |
| |
909 "%c%s%s%s", checksum, name, seed, crypt_hash); |
| |
910 break; |
| |
911 case 2: |
| |
912 case 7: |
| |
913 checksum = seed[seed[15] % 16]; |
| |
914 g_snprintf(hash_string_p, strlen(name) + 50, |
| |
915 "%c%s%s%s", checksum, seed, password_hash, name); |
| |
916 g_snprintf(hash_string_c, strlen(name) + 50, |
| |
917 "%c%s%s%s", checksum, seed, crypt_hash, name); |
| |
918 break; |
| |
919 case 3: |
| |
920 checksum = seed[seed[1] % 16]; |
| |
921 g_snprintf(hash_string_p, strlen(name) + 50, |
| |
922 "%c%s%s%s", checksum, name, password_hash, seed); |
| |
923 g_snprintf(hash_string_c, strlen(name) + 50, |
| |
924 "%c%s%s%s", checksum, name, crypt_hash, seed); |
| |
925 break; |
| |
926 case 4: |
| |
927 checksum = seed[seed[3] % 16]; |
| |
928 g_snprintf(hash_string_p, strlen(name) + 50, |
| |
929 "%c%s%s%s", checksum, password_hash, seed, name); |
| |
930 g_snprintf(hash_string_c, strlen(name) + 50, |
| |
931 "%c%s%s%s", checksum, crypt_hash, seed, name); |
| |
932 break; |
| |
933 case 0: |
| |
934 case 5: |
| |
935 checksum = seed[seed[7] % 16]; |
| |
936 g_snprintf(hash_string_p, strlen(name) + 50, |
| |
937 "%c%s%s%s", checksum, password_hash, name, seed); |
| |
938 g_snprintf(hash_string_c, strlen(name) + 50, |
| |
939 "%c%s%s%s", checksum, crypt_hash, name, seed); |
| |
940 break; |
| |
941 } |
| |
942 |
| |
943 md5_init(&ctx); |
| |
944 md5_append(&ctx, hash_string_p, strlen(hash_string_p)); |
| |
945 md5_finish(&ctx, result); |
| |
946 to_y64(result6, result, 16); |
| |
947 |
| |
948 md5_init(&ctx); |
| |
949 md5_append(&ctx, hash_string_c, strlen(hash_string_c)); |
| |
950 md5_finish(&ctx, result); |
| |
951 to_y64(result96, result, 16); |
| |
952 |
| |
953 pack = yahoo_packet_new(YAHOO_SERVICE_AUTHRESP, YAHOO_STATUS_AVAILABLE, 0); |
| |
954 yahoo_packet_hash(pack, 0, name); |
| |
955 yahoo_packet_hash(pack, 6, result6); |
| |
956 yahoo_packet_hash(pack, 96, result96); |
| |
957 yahoo_packet_hash(pack, 1, name); |
| |
958 |
| |
959 yahoo_send_packet(yd, pack); |
| |
960 |
| |
961 g_free(hash_string_p); |
| |
962 g_free(hash_string_c); |
| |
963 |
| |
964 yahoo_packet_free(pack); |
| |
965 |
| |
966 } |
| |
967 |
| |
968 static void yahoo_process_auth_new(GaimConnection *gc, const char *seed) |
| |
969 { |
| |
970 struct yahoo_packet *pack = NULL; |
| |
971 GaimAccount *account = gaim_connection_get_account(gc); |
| |
972 const char *name = normalize(gaim_account_get_username(account)); |
| |
973 const char *pass = gaim_account_get_password(account); |
| |
974 struct yahoo_data *yd = gc->proto_data; |
| |
975 |
| |
976 md5_byte_t result[16]; |
| |
977 md5_state_t ctx; |
| |
978 |
| |
979 SHA_CTX ctx1; |
| |
980 SHA_CTX ctx2; |
| |
981 |
| |
982 char *alphabet1 = "FBZDWAGHrJTLMNOPpRSKUVEXYChImkwQ"; |
| |
983 char *alphabet2 = "F0E1D2C3B4A59687abcdefghijklmnop"; |
| |
984 |
| |
985 char *challenge_lookup = "qzec2tb3um1olpar8whx4dfgijknsvy5"; |
| |
986 char *operand_lookup = "+|&%/*^-"; |
| |
987 char *delimit_lookup = ",;"; |
| |
988 |
| |
989 char *password_hash = g_malloc0(25); |
| |
990 char *crypt_hash = g_malloc0(25); |
| |
991 char *crypt_result = NULL; |
| |
992 char pass_hash_xor1[64]; |
| |
993 char pass_hash_xor2[64]; |
| |
994 char crypt_hash_xor1[64]; |
| |
995 char crypt_hash_xor2[64]; |
| |
996 char resp_6[100]; |
| |
997 char resp_96[100]; |
| |
998 |
| |
999 unsigned char digest1[20]; |
| |
1000 unsigned char digest2[20]; |
| |
1001 unsigned char magic_key_char[4]; |
| |
1002 unsigned char *magic_ptr; |
| |
1003 |
| |
1004 unsigned int magic[64]; |
| |
1005 unsigned int magic_work; |
| |
1006 unsigned int value = 0; |
| |
1007 |
| |
1008 int x; |
| |
1009 int cnt = 0; |
| |
1010 int magic_cnt = 0; |
| |
1011 int magic_len; |
| |
1012 int times = 0; |
| |
1013 |
| |
1014 memset(&pass_hash_xor1, 0, 64); |
| |
1015 memset(&pass_hash_xor2, 0, 64); |
| |
1016 memset(&crypt_hash_xor1, 0, 64); |
| |
1017 memset(&crypt_hash_xor2, 0, 64); |
| |
1018 memset(&digest1, 0, 20); |
| |
1019 memset(&digest2, 0, 20); |
| |
1020 memset(&magic, 0, 64); |
| |
1021 memset(&resp_6, 0, 100); |
| |
1022 memset(&resp_96, 0, 100); |
| |
1023 memset(&magic_key_char, 0, 4); |
| |
1024 |
| |
1025 /* |
| |
1026 * Magic: Phase 1. Generate what seems to be a 30 |
| |
1027 * byte value (could change if base64 |
| |
1028 * ends up differently? I don't remember and I'm |
| |
1029 * tired, so use a 64 byte buffer. |
| |
1030 */ |
| |
1031 |
| |
1032 magic_ptr = seed; |
| |
1033 |
| |
1034 while (*magic_ptr != (int)NULL) { |
| |
1035 char *loc; |
| |
1036 |
| |
1037 /* Ignore parentheses. */ |
| |
1038 |
| |
1039 if (*magic_ptr == '(' || *magic_ptr == ')') { |
| |
1040 magic_ptr++; |
| |
1041 continue; |
| |
1042 } |
| |
1043 |
| |
1044 /* Characters and digits verify against |
| |
1045 the challenge lookup. |
| |
1046 */ |
| |
1047 |
| |
1048 if (isalpha(*magic_ptr) || isdigit(*magic_ptr)) { |
| |
1049 loc = strchr(challenge_lookup, *magic_ptr); |
| |
1050 if (!loc) { |
| |
1051 /* This isn't good */ |
| |
1052 } |
| |
1053 |
| |
1054 /* Get offset into lookup table and lsh 3. */ |
| |
1055 |
| |
1056 magic_work = loc - challenge_lookup; |
| |
1057 magic_work <<= 3; |
| |
1058 |
| |
1059 magic_ptr++; |
| |
1060 continue; |
| |
1061 } else { |
| |
1062 unsigned int local_store; |
| |
1063 |
| |
1064 loc = strchr(operand_lookup, *magic_ptr); |
| |
1065 if (!loc) { |
| |
1066 /* Also not good. */ |
| |
1067 } |
| |
1068 |
| |
1069 local_store = loc - operand_lookup; |
| |
1070 |
| |
1071 /* Oops; how did this happen? */ |
| |
1072 if (magic_cnt >= 64) |
| |
1073 break; |
| |
1074 |
| |
1075 magic[magic_cnt++] = magic_work | local_store; |
| |
1076 magic_ptr++; |
| |
1077 continue; |
| |
1078 } |
| |
1079 } |
| |
1080 |
| |
1081 magic_len = magic_cnt; |
| |
1082 magic_cnt = 0; |
| |
1083 |
| |
1084 /* Magic: Phase 2. Take generated magic value and |
| |
1085 * sprinkle fairy dust on the values. */ |
| |
1086 |
| |
1087 for (magic_cnt = magic_len-2; magic_cnt >= 0; magic_cnt--) { |
| |
1088 unsigned char byte1; |
| |
1089 unsigned char byte2; |
| |
1090 |
| |
1091 /* Bad. Abort. |
| |
1092 */ |
| |
1093 if ((magic_cnt + 1 > magic_len) || |
| |
1094 (magic_cnt > magic_len)) |
| |
1095 break; |
| |
1096 |
| |
1097 byte1 = magic[magic_cnt]; |
| |
1098 byte2 = magic[magic_cnt+1]; |
| |
1099 |
| |
1100 byte1 *= 0xcd; |
| |
1101 byte1 ^= byte2; |
| |
1102 |
| |
1103 magic[magic_cnt+1] = byte1; |
| |
1104 } |
| |
1105 |
| |
1106 /* Magic: Phase 3. Final phase; this gives us our |
| |
1107 * key. */ |
| |
1108 |
| |
1109 magic_cnt = 1; |
| |
1110 |
| |
1111 for (;;) { |
| |
1112 unsigned int cl = magic[magic_cnt] & 0xff; |
| |
1113 unsigned int bl = magic[magic_cnt+1] & 0xff; |
| |
1114 |
| |
1115 if (!bl || !cl) |
| |
1116 break; |
| |
1117 |
| |
1118 if (magic_cnt > magic_len) |
| |
1119 break; |
| |
1120 |
| |
1121 if (cl <= 0x7f) |
| |
1122 bl = cl; |
| |
1123 else { |
| |
1124 if (cl >= 0x0e0) { |
| |
1125 cl = cl & 0x0f; |
| |
1126 cl = cl << 6; |
| |
1127 bl = bl & 0x3f; |
| |
1128 bl = cl + bl; |
| |
1129 bl = bl << 6; |
| |
1130 } else { |
| |
1131 cl = cl & 0x1f; |
| |
1132 cl = cl << 6; |
| |
1133 bl = cl; |
| |
1134 } |
| |
1135 |
| |
1136 cl = magic[magic_cnt+2]; |
| |
1137 |
| |
1138 if (!cl) |
| |
1139 break; |
| |
1140 |
| |
1141 cl = cl & 0x3f; |
| |
1142 bl = bl + cl; |
| |
1143 } |
| |
1144 |
| |
1145 /* Result is bl. |
| |
1146 */ |
| |
1147 |
| |
1148 magic_cnt += 3; |
| |
1149 |
| |
1150 if (times == 0) { |
| |
1151 value |= (bl & 0xff) << 8; |
| |
1152 value |= (bl & 0xff00) >> 8; |
| |
1153 } else { |
| |
1154 value |= (bl & 0xff) << 24; |
| |
1155 value |= (bl & 0xff00) << 8; |
| |
1156 break; |
| |
1157 } |
| |
1158 |
| |
1159 times++; |
| |
1160 } |
| |
1161 |
| |
1162 /* Dump magic key into a char for SHA1 action. */ |
| |
1163 |
| |
1164 memcpy(&magic_key_char[0], &value, sizeof(int)); |
| |
1165 |
| |
1166 /* Get password and crypt hashes as per usual. */ |
| |
1167 md5_init(&ctx); |
| |
1168 md5_append(&ctx, pass, strlen(pass)); |
| |
1169 md5_finish(&ctx, result); |
| |
1170 to_y64(password_hash, result, 16); |
| |
1171 |
| |
1172 md5_init(&ctx); |
| |
1173 crypt_result = yahoo_crypt(pass, "$1$_2S43d5f$"); |
| |
1174 md5_append(&ctx, crypt_result, strlen(crypt_result)); |
| |
1175 md5_finish(&ctx, result); |
| |
1176 to_y64(crypt_hash, result, 16); |
| |
1177 |
| |
1178 /* Our first authentication response is based off |
| |
1179 * of the password hash. */ |
| |
1180 |
| |
1181 for (x = 0; x < (int)strlen(password_hash); x++) |
| |
1182 pass_hash_xor1[cnt++] = password_hash[x] ^ 0x36; |
| |
1183 |
| |
1184 if (cnt < 64) |
| |
1185 memset(&(pass_hash_xor1[cnt]), 0x36, 64-cnt); |
| |
1186 |
| |
1187 cnt = 0; |
| |
1188 |
| |
1189 for (x = 0; x < (int)strlen(password_hash); x++) |
| |
1190 pass_hash_xor2[cnt++] = password_hash[x] ^ 0x5c; |
| |
1191 |
| |
1192 if (cnt < 64) |
| |
1193 memset(&(pass_hash_xor2[cnt]), 0x5c, 64-cnt); |
| |
1194 |
| |
1195 shaInit(&ctx1); |
| |
1196 shaInit(&ctx2); |
| |
1197 |
| |
1198 /* The first context gets the password hash XORed |
| |
1199 * with 0x36 plus a magic value |
| |
1200 * which we previously extrapolated from our |
| |
1201 * challenge. */ |
| |
1202 |
| |
1203 shaUpdate(&ctx1, pass_hash_xor1, 64); |
| |
1204 shaUpdate(&ctx1, magic_key_char, 4); |
| |
1205 shaFinal(&ctx1, digest1); |
| |
1206 |
| |
1207 /* The second context gets the password hash XORed |
| |
1208 * with 0x5c plus the SHA-1 digest |
| |
1209 * of the first context. */ |
| |
1210 |
| |
1211 shaUpdate(&ctx2, pass_hash_xor2, 64); |
| |
1212 shaUpdate(&ctx2, digest1, 20); |
| |
1213 shaFinal(&ctx2, digest2); |
| |
1214 |
| |
1215 /* Now that we have digest2, use it to fetch |
| |
1216 * characters from an alphabet to construct |
| |
1217 * our first authentication response. */ |
| |
1218 |
| |
1219 for (x = 0; x < 20; x += 2) { |
| |
1220 unsigned int val = 0; |
| |
1221 unsigned int lookup = 0; |
| |
1222 char byte[6]; |
| |
1223 |
| |
1224 memset(&byte, 0, 6); |
| |
1225 |
| |
1226 /* First two bytes of digest stuffed |
| |
1227 * together. |
| |
1228 */ |
| |
1229 |
| |
1230 val = digest2[x]; |
| |
1231 val <<= 8; |
| |
1232 val += digest2[x+1]; |
| |
1233 |
| |
1234 lookup = (val >> 0x0b); |
| |
1235 lookup &= 0x1f; |
| |
1236 if (lookup >= strlen(alphabet1)) |
| |
1237 break; |
| |
1238 sprintf(byte, "%c", alphabet1[lookup]); |
| |
1239 strcat(resp_6, byte); |
| |
1240 strcat(resp_6, "="); |
| |
1241 |
| |
1242 lookup = (val >> 0x06); |
| |
1243 lookup &= 0x1f; |
| |
1244 if (lookup >= strlen(alphabet2)) |
| |
1245 break; |
| |
1246 sprintf(byte, "%c", alphabet2[lookup]); |
| |
1247 strcat(resp_6, byte); |
| |
1248 |
| |
1249 lookup = (val >> 0x01); |
| |
1250 lookup &= 0x1f; |
| |
1251 if (lookup >= strlen(alphabet2)) |
| |
1252 break; |
| |
1253 sprintf(byte, "%c", alphabet2[lookup]); |
| |
1254 strcat(resp_6, byte); |
| |
1255 |
| |
1256 lookup = (val & 0x01); |
| |
1257 if (lookup >= strlen(delimit_lookup)) |
| |
1258 break; |
| |
1259 sprintf(byte, "%c", delimit_lookup[lookup]); |
| |
1260 strcat(resp_6, byte); |
| |
1261 } |
| |
1262 |
| |
1263 /* Our second authentication response is based off |
| |
1264 * of the crypto hash. */ |
| |
1265 |
| |
1266 cnt = 0; |
| |
1267 memset(&digest1, 0, 20); |
| |
1268 memset(&digest2, 0, 20); |
| |
1269 |
| |
1270 for (x = 0; x < (int)strlen(crypt_hash); x++) |
| |
1271 crypt_hash_xor1[cnt++] = crypt_hash[x] ^ 0x36; |
| |
1272 |
| |
1273 if (cnt < 64) |
| |
1274 memset(&(crypt_hash_xor1[cnt]), 0x36, 64-cnt); |
| |
1275 |
| |
1276 cnt = 0; |
| |
1277 |
| |
1278 for (x = 0; x < (int)strlen(crypt_hash); x++) |
| |
1279 crypt_hash_xor2[cnt++] = crypt_hash[x] ^ 0x5c; |
| |
1280 |
| |
1281 if (cnt < 64) |
| |
1282 memset(&(crypt_hash_xor2[cnt]), 0x5c, 64-cnt); |
| |
1283 |
| |
1284 shaInit(&ctx1); |
| |
1285 shaInit(&ctx2); |
| |
1286 |
| |
1287 /* The first context gets the password hash XORed |
| |
1288 * with 0x36 plus a magic value |
| |
1289 * which we previously extrapolated from our |
| |
1290 * challenge. */ |
| |
1291 |
| |
1292 shaUpdate(&ctx1, crypt_hash_xor1, 64); |
| |
1293 shaUpdate(&ctx1, magic_key_char, 4); |
| |
1294 shaFinal(&ctx1, digest1); |
| |
1295 |
| |
1296 /* The second context gets the password hash XORed |
| |
1297 * with 0x5c plus the SHA-1 digest |
| |
1298 * of the first context. */ |
| |
1299 |
| |
1300 shaUpdate(&ctx2, crypt_hash_xor2, 64); |
| |
1301 shaUpdate(&ctx2, digest1, 20); |
| |
1302 shaFinal(&ctx2, digest2); |
| |
1303 |
| |
1304 /* Now that we have digest2, use it to fetch |
| |
1305 * characters from an alphabet to construct |
| |
1306 * our first authentication response. */ |
| |
1307 |
| |
1308 for (x = 0; x < 20; x += 2) { |
| |
1309 unsigned int val = 0; |
| |
1310 unsigned int lookup = 0; |
| |
1311 |
| |
1312 char byte[6]; |
| |
1313 |
| |
1314 memset(&byte, 0, 6); |
| |
1315 |
| |
1316 /* First two bytes of digest stuffed |
| |
1317 * together. */ |
| |
1318 |
| |
1319 val = digest2[x]; |
| |
1320 val <<= 8; |
| |
1321 val += digest2[x+1]; |
| |
1322 |
| |
1323 lookup = (val >> 0x0b); |
| |
1324 lookup &= 0x1f; |
| |
1325 if (lookup >= strlen(alphabet1)) |
| |
1326 break; |
| |
1327 sprintf(byte, "%c", alphabet1[lookup]); |
| |
1328 strcat(resp_96, byte); |
| |
1329 strcat(resp_96, "="); |
| |
1330 |
| |
1331 lookup = (val >> 0x06); |
| |
1332 lookup &= 0x1f; |
| |
1333 if (lookup >= strlen(alphabet2)) |
| |
1334 break; |
| |
1335 sprintf(byte, "%c", alphabet2[lookup]); |
| |
1336 strcat(resp_96, byte); |
| |
1337 |
| |
1338 lookup = (val >> 0x01); |
| |
1339 lookup &= 0x1f; |
| |
1340 if (lookup >= strlen(alphabet2)) |
| |
1341 break; |
| |
1342 sprintf(byte, "%c", alphabet2[lookup]); |
| |
1343 strcat(resp_96, byte); |
| |
1344 |
| |
1345 lookup = (val & 0x01); |
| |
1346 if (lookup >= strlen(delimit_lookup)) |
| |
1347 break; |
| |
1348 sprintf(byte, "%c", delimit_lookup[lookup]); |
| |
1349 strcat(resp_96, byte); |
| |
1350 } |
| |
1351 |
| |
1352 pack = yahoo_packet_new(YAHOO_SERVICE_AUTHRESP, YAHOO_STATUS_AVAILABLE, 0); |
| |
1353 yahoo_packet_hash(pack, 0, name); |
| |
1354 yahoo_packet_hash(pack, 6, resp_6); |
| |
1355 yahoo_packet_hash(pack, 96, resp_96); |
| |
1356 yahoo_packet_hash(pack, 1, name); |
| |
1357 yahoo_send_packet(yd, pack); |
| |
1358 yahoo_packet_free(pack); |
| |
1359 |
| |
1360 free(password_hash); |
| |
1361 free(crypt_hash); |
| |
1362 } |
| |
1363 |
| 852 static void yahoo_process_auth(GaimConnection *gc, struct yahoo_packet *pkt) |
1364 static void yahoo_process_auth(GaimConnection *gc, struct yahoo_packet *pkt) |
| 853 { |
1365 { |
| 854 char *seed = NULL; |
1366 char *seed = NULL; |
| 855 char *sn = NULL; |
1367 char *sn = NULL; |
| 856 GSList *l = pkt->hash; |
1368 GSList *l = pkt->hash; |
| 857 struct yahoo_data *yd = gc->proto_data; |
1369 int m = 1; |
| 858 GaimAccount *account = gaim_connection_get_account(gc); |
1370 |
| 859 |
1371 |
| 860 while (l) { |
1372 while (l) { |
| 861 struct yahoo_pair *pair = l->data; |
1373 struct yahoo_pair *pair = l->data; |
| 862 if (pair->key == 94) |
1374 if (pair->key == 94) |
| 863 seed = pair->value; |
1375 seed = pair->value; |
| 864 if (pair->key == 1) |
1376 if (pair->key == 1) |
| 865 sn = pair->value; |
1377 sn = pair->value; |
| |
1378 if (pair->key == 13) |
| |
1379 m = atoi(pair->value); |
| 866 l = l->next; |
1380 l = l->next; |
| 867 } |
1381 } |
| 868 |
1382 |
| 869 if (seed) { |
1383 if (seed) { |
| 870 struct yahoo_packet *pack; |
1384 switch (m) { |
| 871 const char *name = normalize(gaim_account_get_username(account)); |
1385 case 0: |
| 872 const char *pass = gaim_account_get_password(account); |
1386 yahoo_process_auth_old(gc, seed); |
| 873 |
1387 break; |
| 874 /* So, Yahoo has stopped supporting its older clients in India, and undoubtedly |
|
| 875 * will soon do so in the rest of the world. |
|
| 876 * |
|
| 877 * The new clients use this authentication method. I warn you in advance, it's |
|
| 878 * bizzare, convoluted, inordinately complicated. It's also no more secure than |
|
| 879 * crypt() was. The only purpose this scheme could serve is to prevent third |
|
| 880 * part clients from connecting to their servers. |
|
| 881 * |
|
| 882 * Sorry, Yahoo. |
|
| 883 */ |
|
| 884 |
|
| 885 md5_byte_t result[16]; |
|
| 886 md5_state_t ctx; |
|
| 887 |
|
| 888 char *crypt_result; |
|
| 889 char password_hash[25]; |
|
| 890 char crypt_hash[25]; |
|
| 891 char *hash_string_p = g_malloc(50 + strlen(sn)); |
|
| 892 char *hash_string_c = g_malloc(50 + strlen(sn)); |
|
| 893 |
|
| 894 char checksum; |
|
| 895 |
|
| 896 int sv; |
|
| 897 |
|
| 898 char result6[25]; |
|
| 899 char result96[25]; |
|
| 900 |
|
| 901 sv = seed[15]; |
|
| 902 sv = sv % 8; |
|
| 903 |
|
| 904 md5_init(&ctx); |
|
| 905 md5_append(&ctx, pass, strlen(pass)); |
|
| 906 md5_finish(&ctx, result); |
|
| 907 to_y64(password_hash, result, 16); |
|
| 908 |
|
| 909 md5_init(&ctx); |
|
| 910 crypt_result = yahoo_crypt(pass, "$1$_2S43d5f$"); |
|
| 911 md5_append(&ctx, crypt_result, strlen(crypt_result)); |
|
| 912 md5_finish(&ctx, result); |
|
| 913 to_y64(crypt_hash, result, 16); |
|
| 914 |
|
| 915 switch (sv) { |
|
| 916 case 1: |
1388 case 1: |
| 917 case 6: |
1389 yahoo_process_auth_new(gc, seed); |
| 918 checksum = seed[seed[9] % 16]; |
1390 break; |
| 919 g_snprintf(hash_string_p, strlen(sn) + 50, |
1391 default: |
| 920 "%c%s%s%s", checksum, name, seed, password_hash); |
1392 gaim_notify_error(gc, "", _("Failed Yahoo! Authentication"), |
| 921 g_snprintf(hash_string_c, strlen(sn) + 50, |
1393 _("The Yahoo server has requested the use of an unrecognized " |
| 922 "%c%s%s%s", checksum, name, seed, crypt_hash); |
1394 "authentication method. This version of Gaim will likely not be able" |
| 923 break; |
1395 "to successfully sign on to Yahoo. Check " GAIM_WEBSITE " for updates.")); |
| 924 case 2: |
1396 yahoo_process_auth_new(gc, seed); /* Can't hurt to try it anyway. */ |
| 925 case 7: |
1397 } |
| 926 checksum = seed[seed[15] % 16]; |
|
| 927 g_snprintf(hash_string_p, strlen(sn) + 50, |
|
| 928 "%c%s%s%s", checksum, seed, password_hash, name); |
|
| 929 g_snprintf(hash_string_c, strlen(sn) + 50, |
|
| 930 "%c%s%s%s", checksum, seed, crypt_hash, name); |
|
| 931 break; |
|
| 932 case 3: |
|
| 933 checksum = seed[seed[1] % 16]; |
|
| 934 g_snprintf(hash_string_p, strlen(sn) + 50, |
|
| 935 "%c%s%s%s", checksum, name, password_hash, seed); |
|
| 936 g_snprintf(hash_string_c, strlen(sn) + 50, |
|
| 937 "%c%s%s%s", checksum, name, crypt_hash, seed); |
|
| 938 break; |
|
| 939 case 4: |
|
| 940 checksum = seed[seed[3] % 16]; |
|
| 941 g_snprintf(hash_string_p, strlen(sn) + 50, |
|
| 942 "%c%s%s%s", checksum, password_hash, seed, name); |
|
| 943 g_snprintf(hash_string_c, strlen(sn) + 50, |
|
| 944 "%c%s%s%s", checksum, crypt_hash, seed, name); |
|
| 945 break; |
|
| 946 case 0: |
|
| 947 case 5: |
|
| 948 checksum = seed[seed[7] % 16]; |
|
| 949 g_snprintf(hash_string_p, strlen(sn) + 50, |
|
| 950 "%c%s%s%s", checksum, password_hash, name, seed); |
|
| 951 g_snprintf(hash_string_c, strlen(sn) + 50, |
|
| 952 "%c%s%s%s", checksum, crypt_hash, name, seed); |
|
| 953 break; |
|
| 954 } |
|
| 955 |
|
| 956 md5_init(&ctx); |
|
| 957 md5_append(&ctx, hash_string_p, strlen(hash_string_p)); |
|
| 958 md5_finish(&ctx, result); |
|
| 959 to_y64(result6, result, 16); |
|
| 960 |
|
| 961 md5_init(&ctx); |
|
| 962 md5_append(&ctx, hash_string_c, strlen(hash_string_c)); |
|
| 963 md5_finish(&ctx, result); |
|
| 964 to_y64(result96, result, 16); |
|
| 965 |
|
| 966 pack = yahoo_packet_new(YAHOO_SERVICE_AUTHRESP, YAHOO_STATUS_AVAILABLE, 0); |
|
| 967 yahoo_packet_hash(pack, 0, name); |
|
| 968 yahoo_packet_hash(pack, 6, result6); |
|
| 969 yahoo_packet_hash(pack, 96, result96); |
|
| 970 yahoo_packet_hash(pack, 1, name); |
|
| 971 |
|
| 972 yahoo_send_packet(yd, pack); |
|
| 973 |
|
| 974 g_free(hash_string_p); |
|
| 975 g_free(hash_string_c); |
|
| 976 |
|
| 977 yahoo_packet_free(pack); |
|
| 978 } |
1398 } |
| 979 } |
1399 } |
| 980 |
1400 |
| 981 static void ignore_buddy(GaimBuddy *b) { |
1401 static void ignore_buddy(GaimBuddy *b) { |
| 982 GaimGroup *g; |
1402 GaimGroup *g; |