Mercurial > pidgin.yaz
comparison libpurple/protocols/jabber/auth.c @ 23266:2b997b690500
A patch from QuLogic to eliminate duplicated HMAC-MD5 code in the Jabber
prpl by using the cipher API.
Fixes #5976
committer: Richard Laager <rlaager@wiktel.com>
author | Elliott Sales de Andrade <qulogic@pidgin.im> |
---|---|
date | Mon, 02 Jun 2008 05:06:58 +0000 |
parents | 73b86c478d37 |
children | 5c70d953a497 |
comparison
equal
deleted
inserted
replaced
23265:6c4db8059e91 | 23266:2b997b690500 |
---|---|
587 purple_connection_error_reason (js->gc, reason, msg); | 587 purple_connection_error_reason (js->gc, reason, msg); |
588 g_free(msg); | 588 g_free(msg); |
589 } | 589 } |
590 } | 590 } |
591 | 591 |
592 /*! | |
593 * @brief Given the server challenge (message) and the key (password), calculate the HMAC-MD5 digest | |
594 * | |
595 * This is the crammd5 response. Inspired by cyrus-sasl's _sasl_hmac_md5() | |
596 */ | |
597 static void | |
598 auth_hmac_md5(const char *challenge, size_t challenge_len, const char *key, size_t key_len, guchar *digest) | |
599 { | |
600 PurpleCipher *cipher; | |
601 PurpleCipherContext *context; | |
602 int i; | |
603 /* inner padding - key XORd with ipad */ | |
604 unsigned char k_ipad[65]; | |
605 /* outer padding - key XORd with opad */ | |
606 unsigned char k_opad[65]; | |
607 | |
608 cipher = purple_ciphers_find_cipher("md5"); | |
609 | |
610 /* if key is longer than 64 bytes reset it to key=MD5(key) */ | |
611 if (strlen(key) > 64) { | |
612 guchar keydigest[16]; | |
613 | |
614 context = purple_cipher_context_new(cipher, NULL); | |
615 purple_cipher_context_append(context, (const guchar *)key, strlen(key)); | |
616 purple_cipher_context_digest(context, 16, keydigest, NULL); | |
617 purple_cipher_context_destroy(context); | |
618 | |
619 key = (char *)keydigest; | |
620 key_len = 16; | |
621 } | |
622 | |
623 /* | |
624 * the HMAC_MD5 transform looks like: | |
625 * | |
626 * MD5(K XOR opad, MD5(K XOR ipad, text)) | |
627 * | |
628 * where K is an n byte key | |
629 * ipad is the byte 0x36 repeated 64 times | |
630 * opad is the byte 0x5c repeated 64 times | |
631 * and text is the data being protected | |
632 */ | |
633 | |
634 /* start out by storing key in pads */ | |
635 memset(k_ipad, '\0', sizeof k_ipad); | |
636 memset(k_opad, '\0', sizeof k_opad); | |
637 memcpy(k_ipad, (void *)key, key_len); | |
638 memcpy(k_opad, (void *)key, key_len); | |
639 | |
640 /* XOR key with ipad and opad values */ | |
641 for (i=0; i<64; i++) { | |
642 k_ipad[i] ^= 0x36; | |
643 k_opad[i] ^= 0x5c; | |
644 } | |
645 | |
646 /* perform inner MD5 */ | |
647 context = purple_cipher_context_new(cipher, NULL); | |
648 purple_cipher_context_append(context, k_ipad, 64); /* start with inner pad */ | |
649 purple_cipher_context_append(context, (const guchar *)challenge, challenge_len); /* then text of datagram */ | |
650 purple_cipher_context_digest(context, 16, digest, NULL); /* finish up 1st pass */ | |
651 purple_cipher_context_destroy(context); | |
652 | |
653 /* perform outer MD5 */ | |
654 context = purple_cipher_context_new(cipher, NULL); | |
655 purple_cipher_context_append(context, k_opad, 64); /* start with outer pad */ | |
656 purple_cipher_context_append(context, digest, 16); /* then results of 1st hash */ | |
657 purple_cipher_context_digest(context, 16, digest, NULL); /* finish up 2nd pass */ | |
658 purple_cipher_context_destroy(context); | |
659 } | |
660 | |
661 static void auth_old_cb(JabberStream *js, xmlnode *packet, gpointer data) | 592 static void auth_old_cb(JabberStream *js, xmlnode *packet, gpointer data) |
662 { | 593 { |
663 JabberIq *iq; | 594 JabberIq *iq; |
664 xmlnode *query, *x; | 595 xmlnode *query, *x; |
665 const char *type = xmlnode_get_attrib(packet, "type"); | 596 const char *type = xmlnode_get_attrib(packet, "type"); |
701 xmlnode_insert_data(x, h, -1); | 632 xmlnode_insert_data(x, h, -1); |
702 g_free(s); | 633 g_free(s); |
703 jabber_iq_set_callback(iq, auth_old_result_cb, NULL); | 634 jabber_iq_set_callback(iq, auth_old_result_cb, NULL); |
704 jabber_iq_send(iq); | 635 jabber_iq_send(iq); |
705 | 636 |
706 } else if(js->stream_id && xmlnode_get_child(query, "crammd5")) { | 637 } else if(js->stream_id && (x = xmlnode_get_child(query, "crammd5"))) { |
707 const char *challenge; | 638 const char *challenge; |
708 guchar digest[16]; | 639 gchar digest[33]; |
709 char h[33], *p; | 640 PurpleCipherContext *hmac; |
710 int i; | 641 |
711 | 642 /* Calculate the MHAC-MD5 digest */ |
712 challenge = xmlnode_get_attrib(xmlnode_get_child(query, "crammd5"), "challenge"); | 643 challenge = xmlnode_get_attrib(x, "challenge"); |
713 auth_hmac_md5(challenge, strlen(challenge), pw, strlen(pw), digest); | 644 hmac = purple_cipher_context_new_by_name("hmac", NULL); |
645 purple_cipher_context_set_option(hmac, "hash", "md5"); | |
646 purple_cipher_context_set_key(hmac, (guchar *)pw); | |
647 purple_cipher_context_append(hmac, (guchar *)challenge, strlen(challenge)); | |
648 purple_cipher_context_digest_to_str(hmac, 33, digest, NULL); | |
649 purple_cipher_context_destroy(hmac); | |
714 | 650 |
715 /* Create the response query */ | 651 /* Create the response query */ |
716 iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:auth"); | 652 iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:auth"); |
717 query = xmlnode_get_child(iq->node, "query"); | 653 query = xmlnode_get_child(iq->node, "query"); |
718 | 654 |
721 x = xmlnode_new_child(query, "resource"); | 657 x = xmlnode_new_child(query, "resource"); |
722 xmlnode_insert_data(x, js->user->resource, -1); | 658 xmlnode_insert_data(x, js->user->resource, -1); |
723 | 659 |
724 x = xmlnode_new_child(query, "crammd5"); | 660 x = xmlnode_new_child(query, "crammd5"); |
725 | 661 |
726 /* Translate the digest to a hexadecimal notation */ | 662 xmlnode_insert_data(x, digest, 32); |
727 p = h; | |
728 for(i=0; i<16; i++, p+=2) | |
729 snprintf(p, 3, "%02x", digest[i]); | |
730 xmlnode_insert_data(x, h, -1); | |
731 | 663 |
732 jabber_iq_set_callback(iq, auth_old_result_cb, NULL); | 664 jabber_iq_set_callback(iq, auth_old_result_cb, NULL); |
733 jabber_iq_send(iq); | 665 jabber_iq_send(iq); |
734 | 666 |
735 } else if(xmlnode_get_child(query, "password")) { | 667 } else if(xmlnode_get_child(query, "password")) { |