Changeset e71cfbc for protocols/yahoo/libyahoo2.c
- Timestamp:
- 2009-10-13T22:33:12Z (15 years ago)
- Branches:
- master
- Children:
- 99c8f13
- Parents:
- 7ea8697
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
protocols/yahoo/libyahoo2.c
r7ea8697 re71cfbc 90 90 #include "base64.h" 91 91 #include "http_client.h" 92 93 static void yahoo_process_auth_response(struct http_request *req);94 92 95 93 #ifdef USE_STRUCT_CALLBACKS … … 2309 2307 } 2310 2308 2309 struct yahoo_https_auth_data 2310 { 2311 struct yahoo_input_data *yid; 2312 char *token; 2313 char *chal; 2314 }; 2315 2316 static void yahoo_https_auth_token_init(struct yahoo_https_auth_data *had); 2317 static void yahoo_https_auth_token_finish(struct http_request *req); 2318 static void yahoo_https_auth_init(struct yahoo_https_auth_data *had); 2319 static void yahoo_https_auth_finish(struct http_request *req); 2320 2321 /* Extract a value from a login.yahoo.com response. Assume CRLF-linebreaks 2322 and FAIL miserably if they're not there... */ 2323 static char *yahoo_ha_find_key(char *response, char *key) 2324 { 2325 char *s, *end; 2326 int len = strlen(key); 2327 2328 s = response; 2329 do { 2330 if (strncmp(s, key, len) == 0 && s[len] == '=') { 2331 s += len + 1; 2332 if ((end = strchr(s, '\r'))) 2333 return g_strndup(s, end - s); 2334 else 2335 return g_strdup(s); 2336 } 2337 2338 if ((s = strchr(s, '\n'))) 2339 s ++; 2340 } while (s && *s); 2341 2342 return NULL; 2343 } 2344 2345 static enum yahoo_status yahoo_https_status_parse(int code) 2346 { 2347 switch (code) 2348 { 2349 case 1212: return YAHOO_LOGIN_PASSWD; 2350 case 1213: return YAHOO_LOGIN_LOCK; 2351 case 1235: return YAHOO_LOGIN_UNAME; 2352 default: return (enum yahoo_status) code; 2353 } 2354 } 2355 2311 2356 static void yahoo_process_auth_0x10(struct yahoo_input_data *yid, const char *seed, const char *sn) 2312 2357 { 2358 struct yahoo_https_auth_data *had = g_new0(struct yahoo_https_auth_data, 1); 2359 2360 had->yid = yid; 2361 had->chal = g_strdup(seed); 2362 2363 yahoo_https_auth_token_init(had); 2364 } 2365 2366 static void yahoo_https_auth_token_init(struct yahoo_https_auth_data *had) 2367 { 2368 struct yahoo_input_data *yid = had->yid; 2369 struct yahoo_data *yd = yid->yd; 2370 struct http_request *req; 2371 char *login, *passwd, *chal; 2313 2372 char *url; 2314 2315 yid->yd->login_cookie = strdup(seed); 2316 2317 url = g_strdup_printf( 2318 "https://login.yahoo.com/config/pwtoken_get?" 2319 "src=ymsgr&ts=&login=%s&passwd=%s&chal=%s", 2320 yid->yd->user, yid->yd->password, seed); 2321 2322 http_dorequest_url(url, yahoo_process_auth_response, yid); 2373 2374 login = g_strndup(yd->user, 3 * strlen(yd->user)); 2375 http_encode(login); 2376 passwd = g_strndup(yd->password, 3 * strlen(yd->password)); 2377 http_encode(passwd); 2378 chal = g_strndup(had->chal, 3 * strlen(had->chal)); 2379 http_encode(chal); 2380 2381 url = g_strdup_printf("https://login.yahoo.com/config/pwtoken_get?src=ymsgr&ts=%d&login=%s&passwd=%s&chal=%s", 2382 (int) time(NULL), login, passwd, chal); 2383 2384 req = http_dorequest_url(url, yahoo_https_auth_token_finish, had); 2323 2385 2324 2386 g_free(url); 2387 g_free(chal); 2388 g_free(passwd); 2389 g_free(login); 2390 } 2391 2392 static void yahoo_https_auth_token_finish(struct http_request *req) 2393 { 2394 struct yahoo_https_auth_data *had = req->data; 2395 struct yahoo_input_data *yid = had->yid; 2396 struct yahoo_data *yd = yid->yd; 2397 int st; 2398 2399 if (req->status_code != 200) { 2400 YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, 2000 + req->status_code, NULL); 2401 goto fail; 2402 } 2403 2404 if (sscanf(req->reply_body, "%d", &st) != 1 || st != 0) { 2405 YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, yahoo_https_status_parse(st), NULL); 2406 goto fail; 2407 } 2408 2409 if ((had->token = yahoo_ha_find_key(req->reply_body, "ymsgr")) == NULL) { 2410 YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, 3001, NULL); 2411 goto fail; 2412 } 2413 2414 return yahoo_https_auth_init(had); 2415 2416 fail: 2417 g_free(had->token); 2418 g_free(had->chal); 2419 g_free(had); 2420 } 2421 2422 static void yahoo_https_auth_init(struct yahoo_https_auth_data *had) 2423 { 2424 struct http_request *req; 2425 char *url; 2426 2427 url = g_strdup_printf("https://login.yahoo.com/config/pwtoken_login?src=ymsgr&ts=%d&token=%s", 2428 (int) time(NULL), had->token); 2429 2430 req = http_dorequest_url(url, yahoo_https_auth_finish, had); 2431 2432 g_free(url); 2433 } 2434 2435 static void yahoo_https_auth_finish(struct http_request *req) 2436 { 2437 struct yahoo_https_auth_data *had = req->data; 2438 struct yahoo_input_data *yid = had->yid; 2439 struct yahoo_data *yd = yid->yd; 2440 struct yahoo_packet *pack; 2441 char *crumb; 2442 int st; 2443 2444 md5_byte_t result[16]; 2445 md5_state_t ctx; 2446 2447 unsigned char yhash[32]; 2448 2449 if (req->status_code != 200) { 2450 YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, 2000 + req->status_code, NULL); 2451 goto fail; 2452 } 2453 2454 if (sscanf(req->reply_body, "%d", &st) != 1 || st != 0) { 2455 YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, yahoo_https_status_parse(st), NULL); 2456 goto fail; 2457 } 2458 2459 if ((yd->cookie_y = yahoo_ha_find_key(req->reply_body, "Y")) == NULL || 2460 (yd->cookie_t = yahoo_ha_find_key(req->reply_body, "T")) == NULL || 2461 (crumb = yahoo_ha_find_key(req->reply_body, "crumb")) == NULL) { 2462 YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, 3002, NULL); 2463 goto fail; 2464 } 2465 2466 md5_init(&ctx); 2467 md5_append(&ctx, (unsigned char*) crumb, 11); 2468 md5_append(&ctx, (unsigned char*) had->chal, strlen(had->chal)); 2469 md5_finish(&ctx, result); 2470 to_y64(yhash, result, 16); 2471 2472 pack = yahoo_packet_new(YAHOO_SERVICE_AUTHRESP, yd->initial_status, yd->session_id); 2473 yahoo_packet_hash(pack, 1, yd->user); 2474 yahoo_packet_hash(pack, 0, yd->user); 2475 yahoo_packet_hash(pack, 277, yd->cookie_y); 2476 yahoo_packet_hash(pack, 278, yd->cookie_t); 2477 yahoo_packet_hash(pack, 307, (char*) yhash); 2478 yahoo_packet_hash(pack, 244, "524223"); 2479 yahoo_packet_hash(pack, 2, yd->user); 2480 yahoo_packet_hash(pack, 2, "1"); 2481 yahoo_packet_hash(pack, 98, "us"); 2482 yahoo_packet_hash(pack, 135, "7.5.0.647"); 2483 2484 yahoo_send_packet(yid, pack, 0); 2485 2486 yahoo_packet_free(pack); 2487 2488 return; 2489 2490 fail: 2491 g_free(had->token); 2492 g_free(had->chal); 2493 g_free(had); 2325 2494 } 2326 2495 … … 2354 2523 break; 2355 2524 case 2: 2356 /* HTTPS */2357 2525 yahoo_process_auth_0x10(yid, seed, sn); 2358 2526 break; … … 3663 3831 } 3664 3832 3665 /* #define LOG(x...) printf x */3666 3667 static void yahoo_process_auth_response(struct http_request *req)3668 {3669 char *line_end;3670 char *token;3671 char *cookie;3672 3673 int error_code = 0;3674 int is_ymsgr = 0;3675 3676 struct yahoo_input_data *yid = req->data;3677 3678 char crypt_hash[25];3679 3680 md5_byte_t result[16];3681 md5_state_t ctx;3682 3683 struct yahoo_packet *packet = NULL;3684 3685 if (y_list_find(inputs, yid) == NULL)3686 return;3687 3688 if (req->status_code != 200) {3689 error_code = 3000 + req->status_code;3690 goto FAIL;3691 }3692 3693 token = req->reply_body;3694 line_end = strstr(token, "\r\n");3695 3696 if (line_end) {3697 *line_end = '\0';3698 3699 line_end += 2;3700 }3701 3702 if (sscanf(token, "%d", &error_code) != 1) {3703 error_code = 3000;3704 goto FAIL;3705 }3706 3707 switch(error_code) {3708 case 0:3709 /* successful */3710 break;3711 3712 case 1212:3713 LOG(("Incorrect ID or password\n"));3714 error_code = YAHOO_LOGIN_PASSWD;3715 goto FAIL;3716 3717 case 1213:3718 LOG(("Security lock from too many failed login attempts\n"));3719 error_code = YAHOO_LOGIN_LOCK;3720 goto FAIL;3721 3722 case 1214:3723 LOG(("Security lock\n"));3724 goto FAIL;3725 3726 case 1235:3727 LOG(("User ID not taken yet\n"));3728 error_code = YAHOO_LOGIN_UNAME;3729 goto FAIL;3730 3731 case 1216:3732 LOG(("Seems to be a lock, but shows the same generic User ID/Password failure\n"));3733 goto FAIL;3734 3735 default:3736 /* Unknown error code */3737 LOG(("Unknown Error\n"));3738 goto FAIL;3739 }3740 3741 if ( !strncmp(line_end, "ymsgr=", 6) ) {3742 is_ymsgr = 1;3743 }3744 else if ( strncmp(line_end, "crumb=", 6) ) {3745 LOG(("Oops! There was no ymsgr=. Where do I get my token from now :("));3746 LOG(("I got this:\n\n%s\n",line_end));3747 error_code = 2201;3748 goto FAIL;3749 }3750 3751 token = line_end+6;3752 3753 line_end = strstr(token, "\r\n");3754 3755 if(line_end) {3756 *line_end = '\0';3757 line_end += 2;3758 }3759 3760 /* Go for the crumb */3761 if(is_ymsgr) {3762 char *url;3763 3764 url = g_strdup_printf(3765 "https://login.yahoo.com/config/pwtoken_login?"3766 "src=ymsgr&ts=&token=%s", token);3767 3768 http_dorequest_url(url, yahoo_process_auth_response, yid);3769 3770 g_free(url);3771 3772 return;3773 }3774 3775 /* token is actually crumb */3776 3777 if(!line_end) {3778 /* We did not get our cookies. Cry. */3779 }3780 3781 if((cookie = strstr(req->reply_headers, "Set-Cookie: Y=")) &&3782 (line_end = strstr(cookie + 14, "\r\n"))) {3783 *line_end = '\0';3784 yid->yd->cookie_y = strdup(cookie + 14);3785 *line_end = ';';3786 } else {3787 /* Cry. */3788 LOG(("NO Y Cookie!"));3789 error_code = 2202;3790 goto FAIL;3791 }3792 3793 if((cookie = strstr(req->reply_headers, "Set-Cookie: T=")) &&3794 (line_end = strstr(cookie + 14, "\r\n"))) {3795 *line_end = '\0';3796 yid->yd->cookie_t = strdup(cookie + 14);3797 *line_end = ';';3798 } else {3799 /* Cry. */3800 LOG(("NO T Cookie!"));3801 error_code = 2203;3802 goto FAIL;3803 }3804 3805 md5_init(&ctx);3806 md5_append(&ctx, (md5_byte_t *)token, strlen(token));3807 md5_append(&ctx, (md5_byte_t *)yid->yd->login_cookie, strlen(yid->yd->login_cookie));3808 md5_finish(&ctx, result);3809 3810 to_y64((unsigned char*)crypt_hash, result, 16);3811 3812 packet = yahoo_packet_new(YAHOO_SERVICE_AUTHRESP, yid->yd->initial_status, yid->yd->session_id);3813 yahoo_packet_hash(packet, 1, yid->yd->user);3814 yahoo_packet_hash(packet, 0, yid->yd->user);3815 yahoo_packet_hash(packet, 277, yid->yd->cookie_y);3816 yahoo_packet_hash(packet, 278, yid->yd->cookie_t);3817 yahoo_packet_hash(packet, 307, crypt_hash);3818 yahoo_packet_hash(packet, 244, "2097087"); /* Rekkanoryo says this is the build number */3819 yahoo_packet_hash(packet, 2, yid->yd->user);3820 yahoo_packet_hash(packet, 2, "1");3821 yahoo_packet_hash(packet, 98, "us"); /* TODO Put country code */3822 yahoo_packet_hash(packet, 135, "9.0.0.1389");3823 3824 yahoo_send_packet(yid, packet, 0);3825 3826 yahoo_packet_free(packet);3827 3828 /* We don't need this anymore */3829 free(yid->yd->login_cookie);3830 yid->yd->login_cookie = NULL;3831 3832 return;3833 3834 FAIL:3835 YAHOO_CALLBACK(ext_yahoo_login_response)(yid->yd->client_id, error_code, NULL);3836 }3837 3838 3839 3833 static void (*yahoo_process_connection[])(struct yahoo_input_data *, int over) = { 3840 3834 yahoo_process_pager_connection,
Note: See TracChangeset
for help on using the changeset viewer.