comparison libpurple/protocols/msn/msnutils.c @ 23541:54f7e507ea7d

Fix calculating the response to MSN Challenge strings that are an exact multiple of 8 characters long. This seems to happen sporadically when sending OIM's. Also, clean up the mess that is msn_handle_chl. No more 2-tab indent, more consistent whitespace, and broke up some really long lines. Made reference to the wiki on imfreedom.org instead of msnpiki, since it's newer and I re-wrote it ;) References #5379.
author Elliott Sales de Andrade <qulogic@pidgin.im>
date Sun, 22 Jun 2008 01:52:04 +0000
parents 1ac5faa72c8d
children 7bceac816e19
comparison
equal deleted inserted replaced
23540:0fc1d2df836e 23541:54f7e507ea7d
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA 22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
23 */ 23 */
24 #include "msn.h" 24 #include "msn.h"
25 #include "msnutils.h" 25 #include "msnutils.h"
26 #include "time.h" 26 #include "time.h"
27 //#include <openssl/md5.h> 27
28 #include "cipher.h"
28 29
29 char *rand_guid(void); 30 char *rand_guid(void);
30 31
31 /************************************************************************** 32 /**************************************************************************
32 * Util 33 * Util
463 char *c; 464 char *c;
464 int port; 465 int port;
465 466
466 host = g_strdup(str); 467 host = g_strdup(str);
467 468
468 if ((c = strchr(host, ':')) != NULL){ 469 if ((c = strchr(host, ':')) != NULL) {
469 *c = '\0'; 470 *c = '\0';
470 port = atoi(c + 1); 471 port = atoi(c + 1);
471 }else{ 472 } else {
472 port = 1863; 473 port = 1863;
473 } 474 }
474 475
475 *ret_host = host; 476 *ret_host = host;
476 *ret_port = port; 477 *ret_port = port;
503 /*************************************************************************** 504 /***************************************************************************
504 * MSN Challenge Computing Function 505 * MSN Challenge Computing Function
505 ***************************************************************************/ 506 ***************************************************************************/
506 507
507 /* 508 /*
508 * Handle MSN Chanllege computation 509 * Handle MSN Challenge computation
509 *This algorithm reference with http://msnpiki.msnfanatic.com/index.php/MSNP11:Challenges 510 * This algorithm references
511 * http://imfreedom.org/wiki/index.php/MSN:NS/Challenges
510 */ 512 */
511 #define BUFSIZE 256 513 #define BUFSIZE 256
512 void 514 void
513 msn_handle_chl(char *input, char *output) 515 msn_handle_chl(char *input, char *output)
514 { 516 {
515 PurpleCipher *cipher; 517 PurpleCipher *cipher;
516 PurpleCipherContext *context; 518 PurpleCipherContext *context;
517 char *productKey = MSNP15_WLM_PRODUCT_KEY, 519 const guchar productKey[] = MSNP15_WLM_PRODUCT_KEY;
518 *productID = MSNP15_WLM_PRODUCT_ID, 520 const guchar productID[] = MSNP15_WLM_PRODUCT_ID;
519 *hexChars = "0123456789abcdef", 521 const char hexChars[] = "0123456789abcdef";
520 buf[BUFSIZE]; 522 char buf[BUFSIZE];
521 unsigned char md5Hash[16], *newHash; 523 unsigned char md5Hash[16];
522 unsigned int *md5Parts, *chlStringParts, newHashParts[5]; 524 unsigned char *newHash;
523 525 unsigned int *md5Parts;
524 long long nHigh=0, nLow=0; 526 unsigned int *chlStringParts;
525 527 unsigned int newHashParts[5];
526 int i; 528
527 529 long long nHigh = 0, nLow = 0;
528 /* Create the MD5 hash by using Purple MD5 algorithm*/ 530
529 cipher = purple_ciphers_find_cipher("md5"); 531 int len;
530 context = purple_cipher_context_new(cipher, NULL); 532 int i;
531 533
532 purple_cipher_context_append(context, (const guchar *)input, 534 /* Create the MD5 hash by using Purple MD5 algorithm */
533 strlen(input)); 535 cipher = purple_ciphers_find_cipher("md5");
534 purple_cipher_context_append(context, (const guchar *)productKey, 536 context = purple_cipher_context_new(cipher, NULL);
535 strlen(productKey)); 537
536 purple_cipher_context_digest(context, sizeof(md5Hash), md5Hash, NULL); 538 purple_cipher_context_append(context, (guchar *)input, strlen(input));
537 purple_cipher_context_destroy(context); 539 purple_cipher_context_append(context, productKey, sizeof(productKey) - 1);
538 540 purple_cipher_context_digest(context, sizeof(md5Hash), md5Hash, NULL);
539 /* Split it into four integers */ 541 purple_cipher_context_destroy(context);
540 md5Parts = (unsigned int *)md5Hash; 542
541 for(i=0; i<4; i++){ 543 /* Split it into four integers */
542 /* adjust endianess */ 544 md5Parts = (unsigned int *)md5Hash;
543 md5Parts[i] = GUINT_TO_LE(md5Parts[i]); 545 for (i = 0; i < 4; i++) {
544 546 /* adjust endianess */
545 /* & each integer with 0x7FFFFFFF */ 547 md5Parts[i] = GUINT_TO_LE(md5Parts[i]);
546 /* and save one unmodified array for later */ 548
547 newHashParts[i] = md5Parts[i]; 549 /* & each integer with 0x7FFFFFFF */
548 md5Parts[i] &= 0x7FFFFFFF; 550 /* and save one unmodified array for later */
549 } 551 newHashParts[i] = md5Parts[i];
550 552 md5Parts[i] &= 0x7FFFFFFF;
551 /* make a new string and pad with '0' */ 553 }
552 snprintf(buf, BUFSIZE-5, "%s%s", input, productID); 554
553 i = strlen(buf); 555 /* make a new string and pad with '0' to length that's a multiple of 8 */
554 memset(&buf[i], '0', 8 - (i % 8)); 556 snprintf(buf, BUFSIZE - 5, "%s%s", input, productID);
555 buf[i + (8 - (i % 8))]='\0'; 557 len = strlen(buf);
556 558 if ((len % 8) != 0) {
557 /* split into integers */ 559 int fix = 8 - (len % 8);
558 chlStringParts = (unsigned int *)buf; 560 memset(&buf[len], '0', fix);
559 561 buf[len + fix] = '\0';
560 /* this is magic */ 562 len += fix;
561 for (i=0; i<(strlen(buf)/4)-1; i+=2){ 563 }
562 long long temp; 564
563 565 /* split into integers */
564 chlStringParts[i] = GUINT_TO_LE(chlStringParts[i]); 566 chlStringParts = (unsigned int *)buf;
565 chlStringParts[i+1] = GUINT_TO_LE(chlStringParts[i+1]); 567
566 568 /* this is magic */
567 temp=(md5Parts[0] * (((0x0E79A9C1 * (long long)chlStringParts[i]) % 0x7FFFFFFF)+nHigh) + md5Parts[1])%0x7FFFFFFF; 569 for (i = 0; i < (strlen(buf) / 4); i += 2) {
568 nHigh=(md5Parts[2] * (((long long)chlStringParts[i+1]+temp) % 0x7FFFFFFF) + md5Parts[3]) % 0x7FFFFFFF; 570 long long temp;
569 nLow=nLow + nHigh + temp; 571
570 } 572 chlStringParts[i] = GUINT_TO_LE(chlStringParts[i]);
571 nHigh=(nHigh+md5Parts[1]) % 0x7FFFFFFF; 573 chlStringParts[i + 1] = GUINT_TO_LE(chlStringParts[i + 1]);
572 nLow=(nLow+md5Parts[3]) % 0x7FFFFFFF; 574
573 575 temp = (0x0E79A9C1 * (long long)chlStringParts[i]) % 0x7FFFFFFF;
574 newHashParts[0]^=nHigh; 576 temp = (md5Parts[0] * (temp + nLow) + md5Parts[1]) % 0x7FFFFFFF;
575 newHashParts[1]^=nLow; 577 nHigh += temp;
576 newHashParts[2]^=nHigh; 578
577 newHashParts[3]^=nLow; 579 temp = ((long long)chlStringParts[i + 1] + temp) % 0x7FFFFFFF;
578 580 nLow = (md5Parts[2] * temp + md5Parts[3]) % 0x7FFFFFFF;
579 /* adjust endianness */ 581 nHigh += nLow;
580 for(i=0; i<4; i++) 582 }
581 newHashParts[i] = GUINT_TO_LE(newHashParts[i]); 583 nLow = (nLow + md5Parts[1]) % 0x7FFFFFFF;
582 584 nHigh = (nHigh + md5Parts[3]) % 0x7FFFFFFF;
583 /* make a string of the parts */ 585
584 newHash = (unsigned char *)newHashParts; 586 newHashParts[0] ^= nLow;
585 587 newHashParts[1] ^= nHigh;
586 /* convert to hexadecimal */ 588 newHashParts[2] ^= nLow;
587 for (i=0; i<16; i++) 589 newHashParts[3] ^= nHigh;
588 { 590
589 output[i*2]=hexChars[(newHash[i]>>4)&0xF]; 591 /* adjust endianness */
590 output[(i*2)+1]=hexChars[newHash[i]&0xF]; 592 for(i = 0; i < 4; i++)
591 } 593 newHashParts[i] = GUINT_TO_LE(newHashParts[i]);
592 594
593 output[32]='\0'; 595 /* make a string of the parts */
594 596 newHash = (unsigned char *)newHashParts;
595 // purple_debug_info("MSNP14","chl output{%s}\n",output); 597
596 } 598 /* convert to hexadecimal */
599 for (i = 0; i < 16; i++)
600 {
601 output[i * 2] = hexChars[(newHash[i] >> 4) & 0xF];
602 output[(i * 2) + 1] = hexChars[newHash[i] & 0xF];
603 }
604
605 output[32] = '\0';
606 }
607