src/protocols/yahoo/yahoo.c

changeset 6986
40613e58e3d6
parent 6982
12f08de92674
child 6989
fb667be9732c
equal deleted inserted replaced
6985:7600c07510d4 6986:40613e58e3d6
33 #include "request.h" 33 #include "request.h"
34 #include "server.h" 34 #include "server.h"
35 #include "util.h" 35 #include "util.h"
36 #include "html.h" 36 #include "html.h"
37 37
38 #include "sha.h"
38 #include "yahoo.h" 39 #include "yahoo.h"
39 #include "yahoochat.h" 40 #include "yahoochat.h"
40 #include "md5.h" 41 #include "md5.h"
41 42
42 /* XXX */ 43 /* XXX */
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;

mercurial