Changes in protocols/msn/ns.c [70ac477:5848675]
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
protocols/msn/ns.c
r70ac477 r5848675 2 2 * BitlBee -- An IRC to other IM-networks gateway * 3 3 * * 4 * Copyright 2002-20 04Wilmer van der Gaast and others *4 * Copyright 2002-2010 Wilmer van der Gaast and others * 5 5 \********************************************************************/ 6 6 … … 27 27 #include "nogaim.h" 28 28 #include "msn.h" 29 #include "passport.h"30 29 #include "md5.h" 30 #include "soap.h" 31 #include "xmltree.h" 31 32 32 33 static gboolean msn_ns_callback( gpointer data, gint source, b_input_condition cond ); … … 34 35 static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int num_parts ); 35 36 36 static void msn_auth_got_passport_token( struct msn_auth_data *mad ); 37 static gboolean msn_ns_got_display_name( struct im_connection *ic, char *name ); 37 static void msn_ns_send_adl( struct im_connection *ic ); 38 38 39 39 gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ) … … 73 73 md->handler->rxq = g_new0( char, 1 ); 74 74 75 g_snprintf( s, sizeof( s ), "VER %d MSNP8 CVR0\r\n", ++md->trId);75 g_snprintf( s, sizeof( s ), "VER %d %s CVR0\r\n", ++md->trId, MSNP_VER ); 76 76 if( msn_write( ic, s, strlen( s ) ) ) 77 77 { … … 113 113 if( strcmp( cmd[0], "VER" ) == 0 ) 114 114 { 115 if( cmd[2] && strncmp( cmd[2], "MSNP8", 5 ) != 0 )115 if( cmd[2] && strncmp( cmd[2], MSNP_VER, 5 ) != 0 ) 116 116 { 117 117 imcb_error( ic, "Unsupported protocol" ); … … 127 127 { 128 128 /* We don't give a damn about the information we just received */ 129 g_snprintf( buf, sizeof( buf ), "USR %d TWNI %s\r\n", ++md->trId, ic->acc->user );129 g_snprintf( buf, sizeof( buf ), "USR %d SSO I %s\r\n", ++md->trId, ic->acc->user ); 130 130 return( msn_write( ic, buf, strlen( buf ) ) ); 131 131 } … … 135 135 int port; 136 136 137 if( num_parts == 6 && strcmp( cmd[2], "NS" ) == 0 )137 if( num_parts >= 6 && strcmp( cmd[2], "NS" ) == 0 ) 138 138 { 139 139 b_event_remove( ic->inpa ); … … 156 156 md->fd = proxy_connect( server, port, msn_ns_connected, ic ); 157 157 } 158 else if( num_parts == 6 && strcmp( cmd[2], "SB" ) == 0 )158 else if( num_parts >= 6 && strcmp( cmd[2], "SB" ) == 0 ) 159 159 { 160 160 struct msn_switchboard *sb; … … 220 220 else if( strcmp( cmd[0], "USR" ) == 0 ) 221 221 { 222 if( num_parts == 5 && strcmp( cmd[2], "TWN" ) == 0 && strcmp( cmd[3], "S" ) == 0 ) 223 { 224 /* Time for some Passport black magic... */ 225 if( !passport_get_token( msn_auth_got_passport_token, ic, ic->acc->user, ic->acc->pass, cmd[4] ) ) 226 { 227 imcb_error( ic, "Error while contacting Passport server" ); 228 imc_logout( ic, TRUE ); 229 return( 0 ); 230 } 231 } 232 else if( num_parts >= 7 && strcmp( cmd[2], "OK" ) == 0 ) 233 { 234 if( num_parts == 7 ) 235 msn_ns_got_display_name( ic, cmd[4] ); 236 else 237 imcb_log( ic, "Warning: Friendly name in server response was corrupted" ); 238 222 if( num_parts >= 6 && strcmp( cmd[2], "SSO" ) == 0 && 223 strcmp( cmd[3], "S" ) == 0 ) 224 { 225 msn_soap_passport_sso_request( ic, cmd[4], cmd[5] ); 226 } 227 else if( strcmp( cmd[2], "OK" ) == 0 ) 228 { 239 229 imcb_log( ic, "Authenticated, getting buddy list" ); 240 241 g_snprintf( buf, sizeof( buf ), "SYN %d 0\r\n", ++md->trId ); 242 return( msn_write( ic, buf, strlen( buf ) ) ); 230 msn_soap_memlist_request( ic ); 243 231 } 244 232 else … … 251 239 else if( strcmp( cmd[0], "MSG" ) == 0 ) 252 240 { 253 if( num_parts !=4 )241 if( num_parts < 4 ) 254 242 { 255 243 imcb_error( ic, "Syntax error" ); … … 267 255 } 268 256 } 269 else if( strcmp( cmd[0], "SYN" ) == 0 ) 270 { 271 if( num_parts == 5 ) 272 { 273 int i, groupcount; 274 275 groupcount = atoi( cmd[4] ); 276 if( groupcount > 0 ) 277 { 278 /* valgrind says this is leaking memory, I'm guessing 279 that this happens during server redirects. */ 280 if( md->grouplist ) 281 { 282 for( i = 0; i < md->groupcount; i ++ ) 283 g_free( md->grouplist[i] ); 284 g_free( md->grouplist ); 285 } 286 287 md->groupcount = groupcount; 288 md->grouplist = g_new0( char *, md->groupcount ); 289 } 290 291 md->buddycount = atoi( cmd[3] ); 292 if( !*cmd[3] || md->buddycount == 0 ) 293 msn_logged_in( ic ); 294 } 295 else 296 { 297 /* Hrrm... This SYN reply doesn't really look like something we expected. 298 Let's assume everything is okay. */ 299 300 msn_logged_in( ic ); 301 } 302 } 303 else if( strcmp( cmd[0], "LST" ) == 0 ) 304 { 305 int list; 306 307 if( num_parts != 4 && num_parts != 5 ) 308 { 309 imcb_error( ic, "Syntax error" ); 310 imc_logout( ic, TRUE ); 311 return( 0 ); 312 } 313 314 http_decode( cmd[2] ); 315 list = atoi( cmd[3] ); 316 317 if( list & 1 ) /* FL */ 318 { 319 char *group = NULL; 320 int num; 321 322 if( cmd[4] != NULL && sscanf( cmd[4], "%d", &num ) == 1 && num < md->groupcount ) 323 group = md->grouplist[num]; 324 325 imcb_add_buddy( ic, cmd[1], group ); 326 imcb_rename_buddy( ic, cmd[1], cmd[2] ); 327 } 328 if( list & 2 ) /* AL */ 329 { 330 ic->permit = g_slist_append( ic->permit, g_strdup( cmd[1] ) ); 331 } 332 if( list & 4 ) /* BL */ 333 { 334 ic->deny = g_slist_append( ic->deny, g_strdup( cmd[1] ) ); 335 } 336 if( list & 8 ) /* RL */ 337 { 338 if( ( list & 6 ) == 0 ) 339 msn_buddy_ask( ic, cmd[1], cmd[2] ); 340 } 341 342 if( --md->buddycount == 0 ) 343 { 344 if( ic->flags & OPT_LOGGED_IN ) 345 { 346 imcb_log( ic, "Successfully transferred to different server" ); 347 g_snprintf( buf, sizeof( buf ), "CHG %d %s %d\r\n", ++md->trId, md->away_state->code, 0 ); 348 return( msn_write( ic, buf, strlen( buf ) ) ); 349 } 350 else 351 { 352 msn_logged_in( ic ); 353 } 354 } 355 } 356 else if( strcmp( cmd[0], "LSG" ) == 0 ) 357 { 358 int num; 359 360 if( num_parts != 4 ) 361 { 362 imcb_error( ic, "Syntax error" ); 363 imc_logout( ic, TRUE ); 364 return( 0 ); 365 } 366 367 http_decode( cmd[2] ); 368 num = atoi( cmd[1] ); 369 370 if( num < md->groupcount ) 371 md->grouplist[num] = g_strdup( cmd[2] ); 257 else if( strcmp( cmd[0], "BLP" ) == 0 ) 258 { 259 msn_ns_send_adl( ic ); 260 } 261 else if( strcmp( cmd[0], "ADL" ) == 0 ) 262 { 263 if( num_parts >= 3 && strcmp( cmd[2], "OK" ) == 0 ) 264 { 265 char buf[1024]; 266 char *fn_raw = set_getstr( &ic->acc->set, "display_name" ); 267 char *fn; 268 269 if( fn_raw == NULL ) 270 fn_raw = ic->acc->user; 271 fn = g_malloc( strlen( fn_raw ) * 3 + 1 ); 272 strcpy( fn, fn_raw ); 273 http_encode( fn ); 274 275 g_snprintf( buf, sizeof( buf ), "PRP %d MFN %s\r\n", 276 ++md->trId, fn ); 277 g_free( fn ); 278 279 msn_write( ic, buf, strlen( buf ) ); 280 } 281 } 282 else if( strcmp( cmd[0], "PRP" ) == 0 ) 283 { 284 imcb_connected( ic ); 372 285 } 373 286 else if( strcmp( cmd[0], "CHL" ) == 0 ) 374 287 { 375 md5_state_t state; 376 md5_byte_t digest[16]; 377 int i; 378 379 if( num_parts != 3 ) 380 { 381 imcb_error( ic, "Syntax error" ); 382 imc_logout( ic, TRUE ); 383 return( 0 ); 384 } 385 386 md5_init( &state ); 387 md5_append( &state, (const md5_byte_t *) cmd[2], strlen( cmd[2] ) ); 388 md5_append( &state, (const md5_byte_t *) QRY_CODE, strlen( QRY_CODE ) ); 389 md5_finish( &state, digest ); 390 391 g_snprintf( buf, sizeof( buf ), "QRY %d %s %d\r\n", ++md->trId, QRY_NAME, 32 ); 392 for( i = 0; i < 16; i ++ ) 393 g_snprintf( buf + strlen( buf ), 3, "%02x", digest[i] ); 288 char *resp; 289 290 if( num_parts < 3 ) 291 { 292 imcb_error( ic, "Syntax error" ); 293 imc_logout( ic, TRUE ); 294 return( 0 ); 295 } 296 297 resp = msn_p11_challenge( cmd[2] ); 298 g_snprintf( buf, sizeof( buf ), "QRY %d %s %zd\r\n%s", 299 ++md->trId, MSNP11_PROD_ID, 300 strlen( resp ), resp ); 301 g_free( resp ); 394 302 395 303 return( msn_write( ic, buf, strlen( buf ) ) ); … … 399 307 const struct msn_away_state *st; 400 308 401 if( num_parts !=6 )402 { 403 imcb_error( ic, "Syntax error" ); 404 imc_logout( ic, TRUE ); 405 return( 0 ); 406 } 407 408 http_decode( cmd[ 4] );409 imcb_rename_buddy( ic, cmd[3], cmd[ 4] );309 if( num_parts < 6 ) 310 { 311 imcb_error( ic, "Syntax error" ); 312 imc_logout( ic, TRUE ); 313 return( 0 ); 314 } 315 316 http_decode( cmd[5] ); 317 imcb_rename_buddy( ic, cmd[3], cmd[5] ); 410 318 411 319 st = msn_away_state_by_code( cmd[2] ); … … 433 341 const struct msn_away_state *st; 434 342 435 if( num_parts !=5 )436 { 437 imcb_error( ic, "Syntax error" ); 438 imc_logout( ic, TRUE ); 439 return( 0 ); 440 } 441 442 http_decode( cmd[ 3] );443 imcb_rename_buddy( ic, cmd[2], cmd[ 3] );343 if( num_parts < 5 ) 344 { 345 imcb_error( ic, "Syntax error" ); 346 imc_logout( ic, TRUE ); 347 return( 0 ); 348 } 349 350 http_decode( cmd[4] ); 351 imcb_rename_buddy( ic, cmd[2], cmd[4] ); 444 352 445 353 st = msn_away_state_by_code( cmd[1] ); … … 462 370 int session, port; 463 371 464 if( num_parts !=7 )372 if( num_parts < 7 ) 465 373 { 466 374 imcb_error( ic, "Syntax error" ); … … 506 414 else if( strcmp( cmd[0], "ADD" ) == 0 ) 507 415 { 508 if( num_parts == 6 && strcmp( cmd[2], "RL" ) == 0 )416 if( num_parts >= 6 && strcmp( cmd[2], "RL" ) == 0 ) 509 417 { 510 418 GSList *l; … … 565 473 return( 0 ); 566 474 } 567 #if 0568 /* Discard this one completely for now since I don't care about the ack569 and since MSN servers can apparently screw up the formatting. */570 else if( strcmp( cmd[0], "REA" ) == 0 )571 {572 if( num_parts != 5 )573 {574 imcb_error( ic, "Syntax error" );575 imc_logout( ic, TRUE );576 return( 0 );577 }578 579 if( g_strcasecmp( cmd[3], ic->acc->user ) == 0 )580 {581 set_t *s;582 583 http_decode( cmd[4] );584 strncpy( ic->displayname, cmd[4], sizeof( ic->displayname ) );585 ic->displayname[sizeof(ic->displayname)-1] = 0;586 587 if( ( s = set_find( &ic->acc->set, "display_name" ) ) )588 {589 g_free( s->value );590 s->value = g_strdup( cmd[4] );591 }592 }593 else594 {595 /* This is not supposed to happen, but let's handle it anyway... */596 http_decode( cmd[4] );597 imcb_rename_buddy( ic, cmd[3], cmd[4] );598 }599 }600 #endif601 475 else if( strcmp( cmd[0], "IPG" ) == 0 ) 602 476 { … … 655 529 } 656 530 } 531 } 532 else if( strcmp( cmd[0], "GCF" ) == 0 ) 533 { 534 /* Coming up is cmd[2] bytes of stuff we're supposed to 535 censore. Meh. */ 536 md->handler->msglen = atoi( cmd[2] ); 537 } 538 else if( strcmp( cmd[0], "UBX" ) == 0 ) 539 { 540 /* Status message. Parser coming soon. */ 541 if( num_parts >= 4 ) 542 md->handler->msglen = atoi( cmd[3] ); 543 } 544 else if( strcmp( cmd[0], "NOT" ) == 0 ) 545 { 546 /* Some kind of notification, not sure if it still exists 547 but we have to skip the payload or stuff breaks. */ 548 if( num_parts >= 3 ) 549 md->handler->msglen = atoi( cmd[2] ); 657 550 } 658 551 else if( isdigit( cmd[0][0] ) ) … … 765 658 } 766 659 } 660 else if( strcmp( cmd[0], "UBX" ) == 0 ) 661 { 662 struct xt_node *psm; 663 char *psm_text = NULL; 664 665 psm = xt_from_string( msg ); 666 if( psm && strcmp( psm->name, "Data" ) == 0 && 667 ( psm = xt_find_node( psm->children, "PSM" ) ) ) 668 psm_text = psm->text; 669 670 imcb_buddy_status_msg( ic, cmd[1], psm_text ); 671 xt_free_node( psm ); 672 } 767 673 768 674 return( 1 ); 769 675 } 770 676 771 static void msn_auth_got_passport_token( struct msn_auth_data *mad)677 void msn_auth_got_passport_token( struct im_connection *ic, char *token ) 772 678 { 773 struct im_connection *ic = mad->data;774 679 struct msn_data *md; 775 680 … … 779 684 780 685 md = ic->proto_data; 781 if( mad->token )686 782 687 { 783 688 char buf[1024]; 784 689 785 g_snprintf( buf, sizeof( buf ), "USR %d TWN S %s\r\n", ++md->trId, mad->token );690 g_snprintf( buf, sizeof( buf ), "USR %d SSO S %s %s\r\n", ++md->trId, md->tokens[0], token ); 786 691 msn_write( ic, buf, strlen( buf ) ); 787 692 } 788 else789 {790 imcb_error( ic, "Error during Passport authentication: %s", mad->error );791 imc_logout( ic, TRUE );792 }793 693 } 794 694 795 static gboolean msn_ns_got_display_name( struct im_connection *ic, char *name)695 void msn_auth_got_contact_list( struct im_connection *ic ) 796 696 { 797 set_t *s; 798 799 if( ( s = set_find( &ic->acc->set, "display_name" ) ) == NULL ) 800 return FALSE; /* Shouldn't happen.. */ 801 802 http_decode( name ); 803 804 if( s->value && strcmp( s->value, name ) == 0 ) 805 { 806 return TRUE; 807 /* The names match, nothing to worry about. */ 808 } 809 else if( s->value != NULL && 810 ( strcmp( name, ic->acc->user ) == 0 || 811 set_getbool( &ic->acc->set, "local_display_name" ) ) ) 812 { 813 /* The server thinks our display name is our e-mail address 814 which is probably wrong, or the user *wants* us to do this: 815 Always use the locally set display_name. */ 816 return msn_set_display_name( ic, s->value ); 817 } 818 else 819 { 820 if( s->value && *s->value ) 821 imcb_log( ic, "BitlBee thinks your display name is `%s' but " 822 "the MSN server says it's `%s'. Using the MSN " 823 "server's name. Set local_display_name to true " 824 "to use the local name.", s->value, name ); 825 826 if( g_utf8_validate( name, -1, NULL ) ) 827 { 828 g_free( s->value ); 829 s->value = g_strdup( name ); 830 } 831 else 832 { 833 imcb_log( ic, "Warning: Friendly name in server response was corrupted" ); 834 } 835 836 return TRUE; 837 } 697 char buf[64]; 698 struct msn_data *md; 699 700 /* Dead connection? */ 701 if( g_slist_find( msn_connections, ic ) == NULL ) 702 return; 703 704 md = ic->proto_data; 705 706 707 g_snprintf( buf, sizeof( buf ), "BLP %d %s\r\n", ++md->trId, "BL" ); 708 msn_write( ic, buf, strlen( buf ) ); 838 709 } 710 711 static gboolean msn_ns_send_adl_1( gpointer key, gpointer value, gpointer data ) 712 { 713 struct xt_node *adl = data, *d, *c; 714 struct bee_user *bu = value; 715 struct msn_buddy_data *bd = bu->data; 716 char handle[strlen(bu->handle)]; 717 char *domain; 718 char l[4]; 719 720 strcpy( handle, bu->handle ); 721 if( ( domain = strchr( handle, '@' ) ) == NULL ) /* WTF */ 722 return FALSE; 723 *domain = '\0'; 724 domain ++; 725 726 if( ( d = adl->children ) == NULL || 727 g_strcasecmp( xt_find_attr( d, "n" ), domain ) != 0 ) 728 { 729 d = xt_new_node( "d", NULL, NULL ); 730 xt_add_attr( d, "n", domain ); 731 xt_insert_child( adl, d ); 732 } 733 734 g_snprintf( l, sizeof( l ), "%d", bd->flags & 7 ); 735 c = xt_new_node( "c", NULL, NULL ); 736 xt_add_attr( c, "n", handle ); 737 xt_add_attr( c, "l", l ); 738 xt_add_attr( c, "t", "1" ); /* 1 means normal, 4 means mobile? */ 739 xt_insert_child( d, c ); 740 741 return FALSE; 742 } 743 744 static void msn_ns_send_adl( struct im_connection *ic ) 745 { 746 struct xt_node *adl; 747 struct msn_data *md; 748 char *adls, buf[64]; 749 750 /* Dead connection? */ 751 if( g_slist_find( msn_connections, ic ) == NULL ) 752 return; 753 754 md = ic->proto_data; 755 756 adl = xt_new_node( "ml", NULL, NULL ); 757 xt_add_attr( adl, "l", "1" ); 758 g_tree_foreach( md->domaintree, msn_ns_send_adl_1, adl ); 759 adls = xt_to_string( adl ); 760 761 g_snprintf( buf, sizeof( buf ), "ADL %d %zd\r\n", ++md->trId, strlen( adls ) ); 762 if( msn_write( ic, buf, strlen( buf ) ) ) 763 msn_write( ic, adls, strlen( adls ) ); 764 765 g_free( adls ); 766 xt_free_node( adl ); 767 }
Note: See TracChangeset
for help on using the changeset viewer.