| 310 5, MSN_CONNECT_STEPS); |
278 5, MSN_CONNECT_STEPS); |
| 311 |
279 |
| 312 return TRUE; |
280 return TRUE; |
| 313 } |
281 } |
| 314 |
282 |
| 315 static void |
|
| 316 login_error_cb(GaimSslConnection *gsc, GaimSslErrorType error, void *data) |
|
| 317 { |
|
| 318 MsnServConn *servconn = (MsnServConn *)data; |
|
| 319 GaimAccount *account = servconn->session->account; |
|
| 320 GaimConnection *gc = gaim_account_get_connection(account); |
|
| 321 |
|
| 322 gaim_connection_error(gc, _("Unable to connect to server")); |
|
| 323 } |
|
| 324 |
|
| 325 static void |
|
| 326 login_connect_cb(gpointer data, GaimSslConnection *gsc, |
|
| 327 GaimInputCondition cond) |
|
| 328 { |
|
| 329 MsnServConn *servconn = (MsnServConn *)data; |
|
| 330 MsnSession *session = servconn->session; |
|
| 331 GaimConnection *gc = gaim_account_get_connection(session->account); |
|
| 332 char *username, *password; |
|
| 333 char *request_str; |
|
| 334 char *buffer = NULL; |
|
| 335 char *tpf; |
|
| 336 size_t s; |
|
| 337 |
|
| 338 username = |
|
| 339 g_strdup(gaim_url_encode(gaim_account_get_username(session->account))); |
|
| 340 password = |
|
| 341 g_strdup(gaim_url_encode(gaim_account_get_password(session->account))); |
|
| 342 |
|
| 343 tpf = (char *)g_hash_table_lookup(session->ssl_challenge_data, "tpf"); |
|
| 344 |
|
| 345 request_str = g_strdup_printf( |
|
| 346 "GET %s HTTP/1.1\r\n" |
|
| 347 "Authorization: Passport1.4 OrgVerb=GET,OrgURL=%s,sign-in=%s,pwd=%s," |
|
| 348 "lc=%s,id=%s,tw=%s,fs=%s,ru=%s,ct=%s,kpp=%s,kv=%s,ver=%s,tpf=%s\r\n" |
|
| 349 "User-Agent: MSMSGS\r\n" |
|
| 350 "Host: %s\r\n" |
|
| 351 "Connection: Keep-Alive\r\n" |
|
| 352 "Cache-Control: no-cache\r\n" |
|
| 353 "\r\n", |
|
| 354 session->ssl_login_path, |
|
| 355 (char *)g_hash_table_lookup(session->ssl_challenge_data, "ru"), |
|
| 356 username, password, |
|
| 357 (char *)g_hash_table_lookup(session->ssl_challenge_data, "lc"), |
|
| 358 (char *)g_hash_table_lookup(session->ssl_challenge_data, "id"), |
|
| 359 (char *)g_hash_table_lookup(session->ssl_challenge_data, "tw"), |
|
| 360 (char *)g_hash_table_lookup(session->ssl_challenge_data, "fs"), |
|
| 361 (char *)g_hash_table_lookup(session->ssl_challenge_data, "ru"), |
|
| 362 (char *)g_hash_table_lookup(session->ssl_challenge_data, "ct"), |
|
| 363 (char *)g_hash_table_lookup(session->ssl_challenge_data, "kpp"), |
|
| 364 (char *)g_hash_table_lookup(session->ssl_challenge_data, "kv"), |
|
| 365 (char *)g_hash_table_lookup(session->ssl_challenge_data, "ver"), |
|
| 366 (tpf == NULL ? "" : tpf), |
|
| 367 session->ssl_login_host); |
|
| 368 |
|
| 369 gaim_debug(GAIM_DEBUG_MISC, "msn", "Sending: {%s}\n", request_str); |
|
| 370 |
|
| 371 g_free(username); |
|
| 372 g_free(password); |
|
| 373 |
|
| 374 if ((s = gaim_ssl_write(gsc, request_str, strlen(request_str))) <= 0) |
|
| 375 { |
|
| 376 g_free(request_str); |
|
| 377 gaim_connection_error(gc, _("Unable to write to MSN Nexus server.")); |
|
| 378 |
|
| 379 return; |
|
| 380 } |
|
| 381 |
|
| 382 g_free(request_str); |
|
| 383 |
|
| 384 if ((s = msn_ssl_read(gsc, &buffer)) <= 0) |
|
| 385 { |
|
| 386 gaim_connection_error(gc, _("Unable to read from MSN Nexus server.")); |
|
| 387 |
|
| 388 if (buffer != NULL) |
|
| 389 g_free(buffer); |
|
| 390 |
|
| 391 return; |
|
| 392 } |
|
| 393 |
|
| 394 gaim_ssl_close(gsc); |
|
| 395 |
|
| 396 gaim_debug(GAIM_DEBUG_MISC, "msn", "ssl buffer: {%s}", buffer); |
|
| 397 |
|
| 398 if (strstr(buffer, "HTTP/1.1 302") != NULL) |
|
| 399 { |
|
| 400 /* Redirect. */ |
|
| 401 char *location, *c; |
|
| 402 |
|
| 403 if ((location = strstr(buffer, "Location: ")) == NULL) |
|
| 404 { |
|
| 405 gaim_connection_error(gc, |
|
| 406 _("MSN Nexus server returned invalid redirect information.")); |
|
| 407 |
|
| 408 g_free(buffer); |
|
| 409 |
|
| 410 return; |
|
| 411 } |
|
| 412 |
|
| 413 location = strchr(location, ' ') + 1; |
|
| 414 |
|
| 415 if ((c = strchr(location, '\r')) != NULL) |
|
| 416 *c = '\0'; |
|
| 417 |
|
| 418 /* Skip the http:// */ |
|
| 419 if ((c = strchr(location, '/')) != NULL) |
|
| 420 location = c + 2; |
|
| 421 |
|
| 422 if ((c = strchr(location, '/')) != NULL) |
|
| 423 { |
|
| 424 session->ssl_login_path = g_strdup(c); |
|
| 425 |
|
| 426 *c = '\0'; |
|
| 427 } |
|
| 428 |
|
| 429 session->ssl_login_host = g_strdup(location); |
|
| 430 |
|
| 431 session->ssl_conn = gaim_ssl_connect(session->account, |
|
| 432 session->ssl_login_host, |
|
| 433 GAIM_SSL_DEFAULT_PORT, |
|
| 434 login_connect_cb, login_error_cb, |
|
| 435 servconn); |
|
| 436 } |
|
| 437 else if (strstr(buffer, "HTTP/1.1 401 Unauthorized") != NULL) |
|
| 438 { |
|
| 439 const char *error, *c; |
|
| 440 char *temp; |
|
| 441 |
|
| 442 if ((error = strstr(buffer, "WWW-Authenticate")) != NULL) |
|
| 443 { |
|
| 444 if ((error = strstr(error, "cbtxt=")) != NULL) |
|
| 445 { |
|
| 446 error += strlen("cbtxt="); |
|
| 447 |
|
| 448 if ((c = strchr(error, '\n')) == NULL) |
|
| 449 c = error + strlen(error); |
|
| 450 |
|
| 451 temp = g_strndup(error, c - error); |
|
| 452 error = gaim_url_decode(temp); |
|
| 453 g_free(temp); |
|
| 454 } |
|
| 455 } |
|
| 456 |
|
| 457 if (error == NULL) |
|
| 458 { |
|
| 459 gaim_connection_error(gc, |
|
| 460 _("Unknown error when attempting to authorize with " |
|
| 461 "MSN login server.")); |
|
| 462 } |
|
| 463 else |
|
| 464 gaim_connection_error(gc, error); |
|
| 465 } |
|
| 466 else |
|
| 467 { |
|
| 468 char *base, *c; |
|
| 469 char outparams[MSN_BUF_LEN]; |
|
| 470 |
|
| 471 g_free(session->ssl_login_host); |
|
| 472 g_free(session->ssl_login_path); |
|
| 473 g_hash_table_destroy(session->ssl_challenge_data); |
|
| 474 |
|
| 475 session->ssl_login_host = NULL; |
|
| 476 session->ssl_login_path = NULL; |
|
| 477 session->ssl_challenge_data = NULL; |
|
| 478 |
|
| 479 #if 0 |
|
| 480 /* All your base are belong to us. */ |
|
| 481 base = buffer; |
|
| 482 |
|
| 483 /* For great cookie! */ |
|
| 484 while ((base = strstr(base, "Set-Cookie: ")) != NULL) |
|
| 485 { |
|
| 486 base += strlen("Set-Cookie: "); |
|
| 487 |
|
| 488 c = strchr(base, ';'); |
|
| 489 |
|
| 490 session->login_cookies = |
|
| 491 g_list_append(session->login_cookies, |
|
| 492 g_strndup(base, c - base)); |
|
| 493 } |
|
| 494 #endif |
|
| 495 |
|
| 496 if ((base = strstr(buffer, "Authentication-Info: ")) == NULL) |
|
| 497 { |
|
| 498 gaim_debug(GAIM_DEBUG_ERROR, "msn", |
|
| 499 "Authentication information was not found. This did " |
|
| 500 "not just happen, but if it did, you're screwed. " |
|
| 501 "Report this.\n"); |
|
| 502 |
|
| 503 return; |
|
| 504 } |
|
| 505 |
|
| 506 base = strstr(base, "from-PP='"); |
|
| 507 base += strlen("from-PP='"); |
|
| 508 c = strchr(base, '\''); |
|
| 509 |
|
| 510 session->ssl_login_params = g_strndup(base, c - base); |
|
| 511 |
|
| 512 g_snprintf(outparams, sizeof(outparams), |
|
| 513 "TWN S %s", session->ssl_login_params); |
|
| 514 |
|
| 515 g_free(session->ssl_login_params); |
|
| 516 session->ssl_login_params = NULL; |
|
| 517 |
|
| 518 if (!msn_servconn_send_command(session->notification_conn, "USR", |
|
| 519 outparams)) |
|
| 520 { |
|
| 521 gaim_connection_error(gc, _("Unable to request USR\n")); |
|
| 522 } |
|
| 523 } |
|
| 524 |
|
| 525 g_free(buffer); |
|
| 526 } |
|
| 527 |
|
| 528 static void |
|
| 529 nexus_connect_cb(gpointer data, GaimSslConnection *gsc, |
|
| 530 GaimInputCondition cond) |
|
| 531 { |
|
| 532 MsnServConn *servconn = (MsnServConn *)data; |
|
| 533 MsnSession *session = servconn->session; |
|
| 534 GaimConnection *gc = gaim_account_get_connection(session->account); |
|
| 535 char *request_str; |
|
| 536 char *da_login; |
|
| 537 char *base, *c; |
|
| 538 char *buffer = NULL; |
|
| 539 size_t s; |
|
| 540 |
|
| 541 request_str = g_strdup_printf("GET /rdr/pprdr.asp\r\n\r\n"); |
|
| 542 |
|
| 543 if ((s = gaim_ssl_write(gsc, request_str, strlen(request_str))) <= 0) |
|
| 544 { |
|
| 545 g_free(request_str); |
|
| 546 gaim_connection_error(gc, _("Unable to write to MSN Nexus server.")); |
|
| 547 return; |
|
| 548 } |
|
| 549 |
|
| 550 g_free(request_str); |
|
| 551 |
|
| 552 if (session->ssl_url != NULL) |
|
| 553 { |
|
| 554 g_free(session->ssl_url); |
|
| 555 session->ssl_url = NULL; |
|
| 556 } |
|
| 557 |
|
| 558 /* Get the PassportURLs line. */ |
|
| 559 if ((s = msn_ssl_read(gsc, &buffer)) <= 0) |
|
| 560 { |
|
| 561 gaim_connection_error(gc, _("Unable to read from MSN Nexus server.")); |
|
| 562 |
|
| 563 if (buffer != NULL) |
|
| 564 g_free(buffer); |
|
| 565 |
|
| 566 return; |
|
| 567 } |
|
| 568 |
|
| 569 if ((base = strstr(buffer, "PassportURLs")) == NULL) |
|
| 570 { |
|
| 571 gaim_connection_error(gc, |
|
| 572 _("MSN Nexus server returned invalid information.")); |
|
| 573 |
|
| 574 g_free(buffer); |
|
| 575 |
|
| 576 return; |
|
| 577 } |
|
| 578 |
|
| 579 if ((da_login = strstr(base, "DALogin=")) != NULL) |
|
| 580 { |
|
| 581 if ((da_login = strchr(da_login, '=')) != NULL) |
|
| 582 da_login++; |
|
| 583 |
|
| 584 if ((c = strchr(da_login, ',')) != NULL) |
|
| 585 *c = '\0'; |
|
| 586 |
|
| 587 if ((c = strchr(da_login, '/')) != NULL) |
|
| 588 { |
|
| 589 session->ssl_login_path = g_strdup(c); |
|
| 590 |
|
| 591 *c = '\0'; |
|
| 592 } |
|
| 593 |
|
| 594 session->ssl_login_host = g_strdup(da_login); |
|
| 595 } |
|
| 596 |
|
| 597 g_free(buffer); |
|
| 598 |
|
| 599 gaim_ssl_close(gsc); |
|
| 600 |
|
| 601 /* Now begin the connection to the login server. */ |
|
| 602 session->ssl_conn = gaim_ssl_connect(session->account, |
|
| 603 session->ssl_login_host, |
|
| 604 GAIM_SSL_DEFAULT_PORT, |
|
| 605 login_connect_cb, login_error_cb, |
|
| 606 servconn); |
|
| 607 } |
|
| 608 |
|
| 609 static gboolean |
283 static gboolean |
| 610 usr_cmd(MsnServConn *servconn, const char *command, const char **params, |
284 usr_cmd(MsnServConn *servconn, const char *command, const char **params, |
| 611 size_t param_count) |
285 size_t param_count) |
| 612 { |
286 { |
| 613 MsnSession *session = servconn->session; |
287 MsnSession *session = servconn->session; |
| 641 gaim_connection_update_progress(gc, _("Retrieving buddy list"), |
315 gaim_connection_update_progress(gc, _("Retrieving buddy list"), |
| 642 7, MSN_CONNECT_STEPS); |
316 7, MSN_CONNECT_STEPS); |
| 643 } |
317 } |
| 644 else if (!g_ascii_strcasecmp(params[1], "TWN")) |
318 else if (!g_ascii_strcasecmp(params[1], "TWN")) |
| 645 { |
319 { |
| |
320 char **elems, **cur, **tokens; |
| |
321 |
| 646 /* Passport authentication */ |
322 /* Passport authentication */ |
| 647 char *challenge_data; |
323 session->nexus = msn_nexus_new(session); |
| 648 char *key, *value = NULL; |
|
| 649 char *c; |
|
| 650 |
|
| 651 if (session->ssl_challenge_data != NULL) |
|
| 652 g_hash_table_destroy(session->ssl_challenge_data); |
|
| 653 |
|
| 654 session->ssl_challenge_data = |
|
| 655 g_hash_table_new_full(g_str_hash, g_str_equal, |
|
| 656 g_free, g_free); |
|
| 657 |
324 |
| 658 /* Parse the challenge data. */ |
325 /* Parse the challenge data. */ |
| 659 |
326 elems = g_strsplit(params[3], ",", 0); |
| 660 challenge_data = g_strdup(params[3]); |
327 |
| 661 |
328 for (cur = elems; *cur != NULL; cur++) |
| 662 for (c = challenge_data, key = challenge_data; *c != '\0'; c++) |
329 { |
| 663 { |
330 tokens = g_strsplit(*cur, "=", 2); |
| 664 if (*c == '=') |
331 g_hash_table_insert(session->nexus->challenge_data, tokens[0], tokens[1]); |
| 665 { |
332 /* Don't free each of the tokens, only the array. */ |
| 666 *c = '\0'; |
333 g_free(tokens); |
| 667 |
334 } |
| 668 value = c + 1; |
335 |
| 669 } |
336 g_strfreev(elems); |
| 670 else if (*c == ',') |
337 |
| 671 { |
338 msn_nexus_connect(session->nexus); |
| 672 *c = '\0'; |
|
| 673 |
|
| 674 g_hash_table_insert(session->ssl_challenge_data, |
|
| 675 g_strdup(key), g_strdup(value)); |
|
| 676 |
|
| 677 key = c + 1; |
|
| 678 } |
|
| 679 } |
|
| 680 |
|
| 681 if (key < value) |
|
| 682 { |
|
| 683 /* Let's not forget the last one, it doesn't end with a ',' */ |
|
| 684 g_hash_table_insert(session->ssl_challenge_data, |
|
| 685 g_strdup(key), g_strdup(value)); |
|
| 686 } |
|
| 687 |
|
| 688 g_free(challenge_data); |
|
| 689 |
|
| 690 #if 0 |
|
| 691 passport_str = g_strdup(gaim_url_decode(params[3])); |
|
| 692 |
|
| 693 for (c = passport_str; *c != '\0'; c++) |
|
| 694 { |
|
| 695 if (*c == ',') |
|
| 696 *c = '&'; |
|
| 697 } |
|
| 698 |
|
| 699 session->ssl_url = passport_str; |
|
| 700 #endif |
|
| 701 |
|
| 702 session->ssl_conn = gaim_ssl_connect(session->account, |
|
| 703 "nexus.passport.com", |
|
| 704 GAIM_SSL_DEFAULT_PORT, |
|
| 705 nexus_connect_cb, login_error_cb, |
|
| 706 servconn); |
|
| 707 |
|
| 708 if (session->ssl_conn == NULL) |
|
| 709 { |
|
| 710 gaim_connection_error(gc, |
|
| 711 _("Unable to connect to passport server")); |
|
| 712 |
|
| 713 return FALSE; |
|
| 714 } |
|
| 715 |
339 |
| 716 gaim_connection_update_progress(gc, _("Password sent"), |
340 gaim_connection_update_progress(gc, _("Password sent"), |
| 717 6, MSN_CONNECT_STEPS); |
341 6, MSN_CONNECT_STEPS); |
| 718 } |
342 } |
| 719 else if (!g_ascii_strcasecmp(params[1], "MD5")) |
343 else if (!g_ascii_strcasecmp(params[1], "MD5")) |