| 2232 | struct yahoo_https_auth_data |
| 2233 | { |
| 2234 | struct yahoo_input_data *yid; |
| 2235 | char *chal; |
| 2236 | }; |
| 2237 | |
| 2238 | static void yahoo_https_auth_token_init(struct yahoo_https_auth_data *had); |
| 2239 | static void yahoo_https_auth_token_finish(struct http_request *req); |
| 2240 | static void yahoo_https_auth_init(struct yahoo_https_auth_data *had); |
| 2241 | static void yahoo_https_auth_finish(struct http_request *req); |
| 2242 | |
| 2243 | /* Extract a value from a login.yahoo.com response. Assume CRLF-linebreaks |
| 2244 | and FAIL miserably if they're not there... */ |
| 2245 | static char *yahoo_ha_find_key(char *response, char *key) |
| 2246 | { |
| 2247 | char *s, *end; |
| 2248 | int len = strlen(key); |
| 2249 | |
| 2250 | s = response; |
| 2251 | do { |
| 2252 | if (strncmp(s, key, len) == 0 && s[len] == '=') { |
| 2253 | s += len + 1; |
| 2254 | if ((end = strchr(s, '\r'))) |
| 2255 | return g_strndup(s, end - s); |
| 2256 | else |
| 2257 | return g_strdup(s); |
| 2258 | } |
| 2259 | |
| 2260 | if ((s = strchr(s, '\n'))) |
| 2261 | s ++; |
| 2262 | } while (s && *s); |
| 2263 | |
| 2264 | return NULL; |
| 2265 | } |
| 2266 | |
| 2267 | static void yahoo_https_auth(struct yahoo_input_data *yid, const char *seed, const char *sn) |
| 2268 | { |
| 2269 | struct yahoo_data *yd = yid->yd; |
| 2270 | struct yahoo_https_auth_data *had = g_new0(struct yahoo_https_auth_data, 1); |
| 2271 | |
| 2272 | had->yid = yid; |
| 2273 | had->chal = g_strdup(seed); |
| 2274 | |
| 2275 | if (yd->token == NULL) { |
| 2276 | yahoo_https_auth_token_init(had); |
| 2277 | } else { |
| 2278 | yahoo_https_auth_init(had); |
| 2279 | } |
| 2280 | } |
| 2281 | |
| 2282 | static void yahoo_https_auth_token_init(struct yahoo_https_auth_data *had) |
| 2283 | { |
| 2284 | struct yahoo_input_data *yid = had->yid; |
| 2285 | struct yahoo_data *yd = yid->yd; |
| 2286 | struct http_request *req; |
| 2287 | char *login, *passwd, *chal; |
| 2288 | char *url; |
| 2289 | |
| 2290 | login = g_strndup(yd->user, 3 * strlen(yd->user)); |
| 2291 | http_encode(login); |
| 2292 | passwd = g_strndup(yd->password, 3 * strlen(yd->password)); |
| 2293 | http_encode(passwd); |
| 2294 | chal = g_strndup(had->chal, 3 * strlen(had->chal)); |
| 2295 | http_encode(chal); |
| 2296 | |
| 2297 | url = g_strdup_printf("https://login.yahoo.com/config/pwtoken_get?src=ymsgr&ts=%d&login=%s&passwd=%s&chal=%s", |
| 2298 | (int) time(NULL), login, passwd, chal); |
| 2299 | |
| 2300 | req = http_dorequest_url(url, yahoo_https_auth_token_finish, had); |
| 2301 | |
| 2302 | g_free(url); |
| 2303 | } |
| 2304 | |
| 2305 | static void yahoo_https_auth_token_finish(struct http_request *req) |
| 2306 | { |
| 2307 | struct yahoo_https_auth_data *had = req->data; |
| 2308 | struct yahoo_input_data *yid = had->yid; |
| 2309 | struct yahoo_data *yd = yid->yd; |
| 2310 | int st; |
| 2311 | |
| 2312 | if (req->status_code != 200) { |
| 2313 | YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, YAHOO_LOGIN_LOGOFF, NULL); |
| 2314 | goto fail; |
| 2315 | } |
| 2316 | |
| 2317 | if (sscanf(req->reply_body, "%d", &st) != 1 || st != 0) { |
| 2318 | YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, st == 1212 ? YAHOO_LOGIN_PASSWD : |
| 2319 | st == 1235 ? YAHOO_LOGIN_UNAME : |
| 2320 | YAHOO_LOGIN_LOGOFF, NULL); |
| 2321 | goto fail; |
| 2322 | } |
| 2323 | |
| 2324 | if ((yd->token = yahoo_ha_find_key(req->reply_body, "ymsgr")) == NULL) { |
| 2325 | YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, YAHOO_LOGIN_LOGOFF, NULL); |
| 2326 | goto fail; |
| 2327 | } |
| 2328 | |
| 2329 | return yahoo_https_auth_init(had); |
| 2330 | |
| 2331 | fail: |
| 2332 | g_free(had->chal); |
| 2333 | g_free(had); |
| 2334 | } |
| 2335 | |
| 2336 | static void yahoo_https_auth_init(struct yahoo_https_auth_data *had) |
| 2337 | { |
| 2338 | struct yahoo_input_data *yid = had->yid; |
| 2339 | struct yahoo_data *yd = yid->yd; |
| 2340 | struct http_request *req; |
| 2341 | char *url; |
| 2342 | |
| 2343 | url = g_strdup_printf("https://login.yahoo.com/config/pwtoken_login?src=ymsgr&ts=%d&token=%s", |
| 2344 | (int) time(NULL), yd->token); |
| 2345 | |
| 2346 | req = http_dorequest_url(url, yahoo_https_auth_finish, had); |
| 2347 | |
| 2348 | g_free(url); |
| 2349 | } |
| 2350 | |
| 2351 | static void yahoo_https_auth_finish(struct http_request *req) |
| 2352 | { |
| 2353 | struct yahoo_https_auth_data *had = req->data; |
| 2354 | struct yahoo_input_data *yid = had->yid; |
| 2355 | struct yahoo_data *yd = yid->yd; |
| 2356 | struct yahoo_packet *pack; |
| 2357 | char *crumb; |
| 2358 | int st; |
| 2359 | |
| 2360 | md5_byte_t result[16]; |
| 2361 | md5_state_t ctx; |
| 2362 | |
| 2363 | unsigned char yhash[32]; |
| 2364 | |
| 2365 | if (req->status_code != 200) { |
| 2366 | YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, YAHOO_LOGIN_LOGOFF, NULL); |
| 2367 | goto fail; |
| 2368 | } |
| 2369 | |
| 2370 | if (sscanf(req->reply_body, "%d", &st) != 1 || st != 0) { |
| 2371 | YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, st == 1212 ? YAHOO_LOGIN_PASSWD : |
| 2372 | st == 1235 ? YAHOO_LOGIN_UNAME : |
| 2373 | YAHOO_LOGIN_LOGOFF, NULL); |
| 2374 | goto fail; |
| 2375 | } |
| 2376 | |
| 2377 | if ((yd->cookie_y = yahoo_ha_find_key(req->reply_body, "Y")) == NULL || |
| 2378 | (yd->cookie_t = yahoo_ha_find_key(req->reply_body, "T")) == NULL || |
| 2379 | (crumb = yahoo_ha_find_key(req->reply_body, "crumb")) == NULL) { |
| 2380 | YAHOO_CALLBACK(ext_yahoo_login_response)(yd->client_id, YAHOO_LOGIN_LOGOFF, NULL); |
| 2381 | goto fail; |
| 2382 | } |
| 2383 | |
| 2384 | md5_init(&ctx); |
| 2385 | md5_append(&ctx, crumb, 11); |
| 2386 | md5_append(&ctx, had->chal, strlen(had->chal)); |
| 2387 | md5_finish(&ctx, result); |
| 2388 | to_y64(yhash, result, 16); |
| 2389 | |
| 2390 | pack = yahoo_packet_new(YAHOO_SERVICE_AUTHRESP, yd->initial_status, yd->session_id); |
| 2391 | yahoo_packet_hash(pack, 0, yd->user); |
| 2392 | yahoo_packet_hash(pack, 277, yd->cookie_y); |
| 2393 | yahoo_packet_hash(pack, 278, yd->cookie_t); |
| 2394 | yahoo_packet_hash(pack, 307, yhash); |
| 2395 | yahoo_packet_hash(pack, 244, "524223"); |
| 2396 | yahoo_packet_hash(pack, 2, yd->user); |
| 2397 | yahoo_packet_hash(pack, 98, "us"); |
| 2398 | yahoo_packet_hash(pack, 135, "7.5.0.647"); |
| 2399 | |
| 2400 | yahoo_send_packet(yid, pack, 0); |
| 2401 | |
| 2402 | yahoo_packet_free(pack); |
| 2403 | |
| 2404 | return; |
| 2405 | |
| 2406 | fail: |
| 2407 | g_free(had->chal); |
| 2408 | g_free(had); |
| 2409 | } |
| 2410 | |