# HG changeset patch # User Richard Laager # Date 1133931036 0 # Node ID cfc808463763043101dde86614fbf4b4d2f7ad60 # Parent 29e237c4141b78ab277efd275a2356b537f5ff69 [gaim-migrate @ 14688] Reimplement HTTP Digest Authentication (RFC 2617) as part of the Cipher API committer: Tailor Script diff -r 29e237c4141b -r cfc808463763 plugins/ciphertest.c --- a/plugins/ciphertest.c Wed Dec 07 01:47:31 2005 +0000 +++ b/plugins/ciphertest.c Wed Dec 07 04:50:36 2005 +0000 @@ -38,8 +38,8 @@ #include "version.h" struct test { - const guchar *question; - const guchar *answer; + const gchar *question; + const gchar *answer; }; /************************************************************************** @@ -83,7 +83,7 @@ gaim_debug_info("cipher-test", "Test %02d:\n", i); gaim_debug_info("cipher-test", "Testing '%s'\n", md5_tests[i].question); - gaim_cipher_context_append(context, md5_tests[i].question, + gaim_cipher_context_append(context, (guchar *)md5_tests[i].question, strlen(md5_tests[i].question)); ret = gaim_cipher_context_digest_to_str(context, sizeof(digest), @@ -143,7 +143,7 @@ sha1_tests[i].question : "'a'x1000, 1000 times"); if(sha1_tests[i].question) { - gaim_cipher_context_append(context, sha1_tests[i].question, + gaim_cipher_context_append(context, (guchar *)sha1_tests[i].question, strlen(sha1_tests[i].question)); } else { gint j; @@ -174,6 +174,65 @@ gaim_debug_info("cipher-test", "sha1 tests completed\n\n"); } + +static void +cipher_test_digest() +{ + const gchar *nonce = "dcd98b7102dd2f0e8b11d0f600bfb0c093"; + const gchar *client_nonce = "0a4f113b"; + const gchar *username = "Mufasa"; + const gchar *realm = "testrealm@host.com"; + const gchar *password = "Circle Of Life"; + const gchar *algorithm = "md5"; + const gchar nonce_count[] = "00000001"; + const gchar *method = "GET"; + const gchar *qop = "auth"; + const gchar *digest_uri = "/dir/index.html"; + const gchar *hashed_entity = ""; + size_t hashed_entity_len = 0; + + gchar *session_key; + + gaim_debug_info("cipher-test", "Running HTTP Digest tests\n"); + + session_key = gaim_cipher_http_digest_calculate_session_key( + algorithm, username, realm, password, + nonce, client_nonce); + + if (session_key == NULL) + { + gaim_debug_info("cipher-test", + "gaim_cipher_http_digest_calculate_session_key failed.\n"); + } + else + { + gchar *response; + + gaim_debug_info("cipher-test", "\tsession_key: Got: %s\n", session_key); + gaim_debug_info("cipher-test", "\tsession_key: Wanted: %s\n", "939e7578ed9e3c518a452acee763bce9"); + + response = gaim_cipher_http_digest_calculate_response( + algorithm, method, digest_uri, qop, + hashed_entity, hashed_entity_len, nonce, + nonce_count, client_nonce, session_key); + + g_free(session_key); + + if (response == NULL) + { + gaim_debug_info("cipher-test", + "gaim_cipher_http_digest_calculate_session_key failed.\n"); + } + else + { + gaim_debug_info("cipher-test", "\tresponse: Got: %s\n", response); + gaim_debug_info("cipher-test", "\tresponse: Wanted: %s\n", "6629fae49393a05397450978507c4ef1"); + } + } + + gaim_debug_info("cipher-test", "HTTP Digest tests completed\n\n"); +} + /************************************************************************** * Plugin stuff **************************************************************************/ @@ -181,6 +240,7 @@ plugin_load(GaimPlugin *plugin) { cipher_test_md5(); cipher_test_sha1(); + cipher_test_digest(); return TRUE; } diff -r 29e237c4141b -r cfc808463763 src/cipher.c --- a/src/cipher.c Wed Dec 07 01:47:31 2005 +0000 +++ b/src/cipher.c Wed Dec 07 04:50:36 2005 +0000 @@ -1780,3 +1780,165 @@ return context->data; } + +gchar *gaim_cipher_http_digest_calculate_session_key( + const gchar *algorithm, + const gchar *username, + const gchar *realm, + const gchar *password, + const gchar *nonce, + const gchar *client_nonce) +{ + GaimCipher *cipher; + GaimCipherContext *context; + gchar hash[32]; /* We only support MD5. */ + + g_return_val_if_fail(username != NULL, NULL); + g_return_val_if_fail(realm != NULL, NULL); + g_return_val_if_fail(password != NULL, NULL); + g_return_val_if_fail(nonce != NULL, NULL); + + /* Check for a supported algorithm. */ + g_return_val_if_fail(algorithm == NULL || + *algorithm == '\0' || + strcasecmp(algorithm, "MD5") || + strcasecmp(algorithm, "MD5-sess"), NULL); + + cipher = gaim_ciphers_find_cipher("md5"); + g_return_val_if_fail(cipher != NULL, NULL); + + context = gaim_cipher_context_new(cipher, NULL); + + gaim_cipher_context_append(context, (guchar *)username, strlen(username)); + gaim_cipher_context_append(context, (guchar *)":", 1); + gaim_cipher_context_append(context, (guchar *)realm, strlen(realm)); + gaim_cipher_context_append(context, (guchar *)":", 1); + gaim_cipher_context_append(context, (guchar *)password, strlen(password)); + + if (algorithm != NULL && !strcasecmp(algorithm, "MD5-sess")) + { + guchar digest[16]; + + if (client_nonce == NULL) + { + gaim_cipher_context_destroy(context); + gaim_debug_error("cipher", "Required client_nonce missing for MD5-sess digest calculation."); + return NULL; + } + + gaim_cipher_context_digest(context, sizeof(digest), digest, NULL); + gaim_cipher_context_destroy(context); + + context = gaim_cipher_context_new(cipher, NULL); + gaim_cipher_context_append(context, digest, sizeof(digest)); + gaim_cipher_context_append(context, (guchar *)":", 1); + gaim_cipher_context_append(context, (guchar *)nonce, strlen(nonce)); + gaim_cipher_context_append(context, (guchar *)":", 1); + gaim_cipher_context_append(context, (guchar *)client_nonce, strlen(client_nonce)); + } + + gaim_cipher_context_digest_to_str(context, sizeof(hash), hash, NULL); + gaim_cipher_context_destroy(context); + + return g_strdup(hash); +} + +gchar *gaim_cipher_http_digest_calculate_response( + const gchar *algorithm, + const gchar *method, + const gchar *digest_uri, + const gchar *qop, + const gchar *hashed_entity, + size_t hashed_entity_len, + const gchar *nonce, + const gchar *nonce_count, + const gchar *client_nonce, + const gchar *session_key) +{ + GaimCipher *cipher; + GaimCipherContext *context; + gchar hash2[32]; /* We only support MD5. */ + + g_return_val_if_fail(method != NULL, NULL); + g_return_val_if_fail(digest_uri != NULL, NULL); + g_return_val_if_fail(nonce != NULL, NULL); + g_return_val_if_fail(session_key != NULL, NULL); + + /* Check for a supported algorithm. */ + g_return_val_if_fail(algorithm == NULL || + *algorithm == '\0' || + strcasecmp(algorithm, "MD5") || + strcasecmp(algorithm, "MD5-sess"), NULL); + + /* Check for a supported "quality of protection". */ + g_return_val_if_fail(qop == NULL || + *qop == '\0' || + strcasecmp(qop, "auth") || + strcasecmp(qop, "auth-int"), NULL); + + cipher = gaim_ciphers_find_cipher("md5"); + g_return_val_if_fail(cipher != NULL, NULL); + + context = gaim_cipher_context_new(cipher, NULL); + + gaim_cipher_context_append(context, (guchar *)method, strlen(method)); + gaim_cipher_context_append(context, (guchar *)":", 1); + gaim_cipher_context_append(context, (guchar *)digest_uri, strlen(digest_uri)); + + if (qop != NULL && !strcasecmp(qop, "auth-int")) + { + if (hashed_entity == NULL) + { + gaim_cipher_context_destroy(context); + gaim_debug_error("cipher", "Required hashed_entity missing for auth-int digest calculation."); + return NULL; + } + + gaim_cipher_context_append(context, (guchar *)":", 1); + gaim_cipher_context_append(context, (guchar *)hashed_entity, hashed_entity_len); + } + + gaim_cipher_context_digest_to_str(context, sizeof(hash2), hash2, NULL); + gaim_cipher_context_destroy(context); + + context = gaim_cipher_context_new(cipher, NULL); + gaim_cipher_context_append(context, (guchar *)session_key, strlen(session_key)); + gaim_cipher_context_append(context, (guchar *)":", 1); + gaim_cipher_context_append(context, (guchar *)nonce, strlen(nonce)); + gaim_cipher_context_append(context, (guchar *)":", 1); + + if (qop != NULL && *qop != '\0') + { + if (nonce_count == NULL) + { + gaim_cipher_context_destroy(context); + gaim_debug_error("cipher", "Required nonce_count missing for digest calculation."); + return NULL; + } + + if (client_nonce == NULL) + { + gaim_cipher_context_destroy(context); + gaim_debug_error("cipher", "Required client_nonce missing for digest calculation."); + return NULL; + } + + gaim_cipher_context_append(context, (guchar *)nonce_count, strlen(nonce_count)); + gaim_cipher_context_append(context, (guchar *)":", 1); + gaim_cipher_context_append(context, (guchar *)client_nonce, strlen(client_nonce)); + gaim_cipher_context_append(context, (guchar *)":", 1); + + if (qop != NULL) + gaim_cipher_context_append(context, (guchar *)qop, strlen(qop)); + else + gaim_cipher_context_append(context, (guchar *)"", 0); + + gaim_cipher_context_append(context, (guchar *)":", 1); + } + + gaim_cipher_context_append(context, (guchar *)hash2, strlen(hash2)); + gaim_cipher_context_digest_to_str(context, sizeof(hash2), hash2, NULL); + gaim_cipher_context_destroy(context); + + return g_strdup(hash2); +} diff -r 29e237c4141b -r cfc808463763 src/cipher.h --- a/src/cipher.h Wed Dec 07 01:47:31 2005 +0000 +++ b/src/cipher.h Wed Dec 07 04:50:36 2005 +0000 @@ -386,6 +386,49 @@ */ gpointer gaim_cipher_context_get_data(GaimCipherContext *context); +/** + * Calculates a session key for HTTP Digest authentation + * + * See RFC 2617 for more information. + * + * @param algorithm The hash algorithm to use + * @param username The username provided by the user + * @param realm The authentication realm provided by the server + * @param password The password provided by the user + * @param nonce The nonce provided by the server + * @param client_nonce The nonce provided by the client + * + * @return The session key, or @c NULL if an error occurred. + */ +gchar *gaim_cipher_http_digest_calculate_session_key( + const gchar *algorithm, const gchar *username, + const gchar *realm, const gchar *password, + const gchar *nonce, const gchar *client_nonce); + +/** Calculate a response for HTTP Digest authentication + * + * See RFC 2617 for more information. + * + * @param algorithm The hash algorithm to use + * @param method The HTTP method in use + * @param digest_uri The URI from the initial request + * @param qop The "quality of protection" + * @param hashed_entity The hashed entity body + * @param hashed_entity_len The length of the data in @a hashed_entity + * @param nonce The nonce provided by the server + * @param nonce_count The nonce count + * @param client_nonce The nonce provided by the client + * @param session_key The session key from gaim_cipher_http_digest_calculate_session_key() + * + * @return The hashed response, or @c NULL if an error occurred. + */ +gchar *gaim_cipher_http_digest_calculate_response( + const gchar *algorithm, const gchar *method, + const gchar *digest_uri, const gchar *qop, + const gchar *hashed_entity, size_t hashed_entity_len, + const gchar *nonce, const gchar *nonce_count, + const gchar *client_nonce, const gchar *session_key); + /*@}*/ #ifdef __cplusplus diff -r 29e237c4141b -r cfc808463763 src/protocols/simple/Makefile.am --- a/src/protocols/simple/Makefile.am Wed Dec 07 01:47:31 2005 +0000 +++ b/src/protocols/simple/Makefile.am Wed Dec 07 04:50:36 2005 +0000 @@ -4,9 +4,7 @@ simple.c \ simple.h \ sipmsg.c \ - sipmsg.h \ - digcalc.c \ - digcalc.h + sipmsg.h AM_CFLAGS = $(st) diff -r 29e237c4141b -r cfc808463763 src/protocols/simple/Makefile.mingw --- a/src/protocols/simple/Makefile.mingw Wed Dec 07 01:47:31 2005 +0000 +++ b/src/protocols/simple/Makefile.mingw Wed Dec 07 04:50:36 2005 +0000 @@ -68,8 +68,7 @@ ## SOURCES, OBJECTS ## -C_SRC = digcalc.c \ - simple.c \ +C_SRC = simple.c \ sipmsg.c diff -r 29e237c4141b -r cfc808463763 src/protocols/simple/digcalc.c --- a/src/protocols/simple/digcalc.c Wed Dec 07 01:47:31 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,144 +0,0 @@ -/* - * Taken from RFC 2617 - * Copyright (C) The Internet Society (1999). All Rights Reserved. - - This document and translations of it may be copied and furnished to - others, and derivative works that comment on or otherwise explain it - or assist in its implementation may be prepared, copied, published - and distributed, in whole or in part, without restriction of any - kind, provided that the above copyright notice and this paragraph are - included on all such copies and derivative works. However, this - document itself may not be modified in any way, such as by removing - the copyright notice or references to the Internet Society or other - Internet organizations, except as needed for the purpose of - developing Internet standards in which case the procedures for - copyrights defined in the Internet Standards process must be - followed, or as required to translate it into languages other than - English. - - The limited permissions granted above are perpetual and will not be - revoked by the Internet Society or its successors or assigns. - - This document and the information contained herein is provided on an - "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING - TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING - BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION - HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF - MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. -*/ -#include "cipher.h" - -#include -#include "digcalc.h" - -void CvtHex( - IN HASH Bin, - OUT HASHHEX Hex - ) -{ - unsigned short i; - unsigned char j; - - for (i = 0; i < HASHLEN; i++) { - j = (Bin[i] >> 4) & 0xf; - if (j <= 9) - Hex[i*2] = (j + '0'); - else - Hex[i*2] = (j + 'a' - 10); - j = Bin[i] & 0xf; - if (j <= 9) - Hex[i*2+1] = (j + '0'); - else - Hex[i*2+1] = (j + 'a' - 10); - }; - Hex[HASHHEXLEN] = '\0'; -}; - -/* calculate H(A1) as per spec */ -void DigestCalcHA1( - IN char * pszAlg, - IN char * pszUserName, - IN char * pszRealm, - IN char * pszPassword, - IN char * pszNonce, - IN char * pszCNonce, - OUT HASHHEX SessionKey - ) -{ - GaimCipher *cipher; - GaimCipherContext *context; - HASH HA1; - - cipher = gaim_ciphers_find_cipher("md5"); - context = gaim_cipher_context_new(cipher, NULL); - gaim_cipher_context_append(context, (guchar *)pszUserName, strlen(pszUserName)); - gaim_cipher_context_append(context, (guchar *)":", 1); - gaim_cipher_context_append(context, (guchar *)pszRealm, strlen(pszRealm)); - gaim_cipher_context_append(context, (guchar *)":", 1); - gaim_cipher_context_append(context, (guchar *)pszPassword, strlen(pszPassword)); - gaim_cipher_context_digest(context, sizeof(HA1), HA1, NULL); - if (strcmp(pszAlg, "md5-sess") == 0) { - context = gaim_cipher_context_new(cipher, NULL); - gaim_cipher_context_append(context, HA1, HASHLEN); - gaim_cipher_context_append(context, (guchar *)":", 1); - gaim_cipher_context_append(context, (guchar *)pszNonce, strlen(pszNonce)); - gaim_cipher_context_append(context, (guchar *)":", 1); - gaim_cipher_context_append(context, (guchar *)pszCNonce, strlen(pszCNonce)); - gaim_cipher_context_digest(context, sizeof(HA1), HA1, NULL); - }; - CvtHex(HA1, SessionKey); - gaim_cipher_context_destroy(context); -}; - -/* calculate request-digest/response-digest as per HTTP Digest spec */ -void DigestCalcResponse( - IN HASHHEX HA1, /* H(A1) */ - IN char * pszNonce, /* nonce from server */ - IN char * pszNonceCount, /* 8 hex digits */ - IN char * pszCNonce, /* client nonce */ - IN char * pszQop, /* qop-value: "", "auth", "auth-int" */ - IN char * pszMethod, /* method from the request */ - IN char * pszDigestUri, /* requested URL */ - IN HASHHEX HEntity, /* H(entity body) if qop="auth-int" */ - OUT HASHHEX Response /* request-digest or response-digest */ - ) -{ - GaimCipher *cipher; - GaimCipherContext *context; - HASH HA2; - HASH RespHash; - HASHHEX HA2Hex; - - /* calculate H(A2) */ - cipher = gaim_ciphers_find_cipher("md5"); - context = gaim_cipher_context_new(cipher, NULL); - gaim_cipher_context_append(context, (guchar *)pszMethod, strlen(pszMethod)); - gaim_cipher_context_append(context, (guchar *)":", 1); - gaim_cipher_context_append(context, (guchar *)pszDigestUri, strlen(pszDigestUri)); - if (strcmp(pszQop, "auth-int") == 0) { - gaim_cipher_context_append(context, (guchar *)":", 1); - gaim_cipher_context_append(context, HEntity, HASHHEXLEN); - }; - gaim_cipher_context_digest(context, sizeof(HA2), HA2, NULL); - CvtHex(HA2, HA2Hex); - - gaim_cipher_context_destroy(context); - /* calculate response */ - context = gaim_cipher_context_new(cipher, NULL); - gaim_cipher_context_append(context, HA1, HASHHEXLEN); - gaim_cipher_context_append(context, (guchar *)":", 1); - gaim_cipher_context_append(context, (guchar *)pszNonce, strlen(pszNonce)); - gaim_cipher_context_append(context, (guchar *)":", 1); - if (*pszQop) { - gaim_cipher_context_append(context, (guchar *)pszNonceCount, strlen(pszNonceCount)); - gaim_cipher_context_append(context, (guchar *)":", 1); - gaim_cipher_context_append(context, (guchar *)pszCNonce, strlen(pszCNonce)); - gaim_cipher_context_append(context, (guchar *)":", 1); - gaim_cipher_context_append(context, (guchar *)pszQop, strlen(pszQop)); - gaim_cipher_context_append(context, (guchar *)":", 1); - }; - gaim_cipher_context_append(context, HA2Hex, HASHHEXLEN); - gaim_cipher_context_digest(context, sizeof(RespHash), RespHash, NULL); - CvtHex(RespHash, Response); - gaim_cipher_context_destroy(context); -}; diff -r 29e237c4141b -r cfc808463763 src/protocols/simple/digcalc.h --- a/src/protocols/simple/digcalc.h Wed Dec 07 01:47:31 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -/* - * Taken from RFC 2617 - * Copyright (C) The Internet Society (1999). All Rights Reserved. - - This document and translations of it may be copied and furnished to - others, and derivative works that comment on or otherwise explain it - or assist in its implementation may be prepared, copied, published - and distributed, in whole or in part, without restriction of any - kind, provided that the above copyright notice and this paragraph are - included on all such copies and derivative works. However, this - document itself may not be modified in any way, such as by removing - the copyright notice or references to the Internet Society or other - Internet organizations, except as needed for the purpose of - developing Internet standards in which case the procedures for - copyrights defined in the Internet Standards process must be - followed, or as required to translate it into languages other than - English. - - The limited permissions granted above are perpetual and will not be - revoked by the Internet Society or its successors or assigns. - - This document and the information contained herein is provided on an - "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING - TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING - BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION - HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF - MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. -*/ - -#define HASHLEN 16 -typedef guchar HASH[HASHLEN]; -#define HASHHEXLEN 32 -typedef guchar HASHHEX[HASHHEXLEN+1]; -#define IN -#define OUT - -/* calculate H(A1) as per HTTP Digest spec */ -void DigestCalcHA1( - IN char * pszAlg, - IN char * pszUserName, - IN char * pszRealm, - IN char * pszPassword, - IN char * pszNonce, - IN char * pszCNonce, - OUT HASHHEX SessionKey - ); - -/* calculate request-digest/response-digest as per HTTP Digest spec */ -void DigestCalcResponse( - IN HASHHEX HA1, /* H(A1) */ - IN char * pszNonce, /* nonce from server */ - IN char * pszNonceCount, /* 8 hex digits */ - IN char * pszCNonce, /* client nonce */ - IN char * pszQop, /* qop-value: "", "auth", "auth-int" */ - IN char * pszMethod, /* method from the request */ - IN char * pszDigestUri, /* requested URL */ - IN HASHHEX HEntity, /* H(entity body) if qop="auth-int" */ - OUT HASHHEX Response /* request-digest or response-digest */ - ); diff -r 29e237c4141b -r cfc808463763 src/protocols/simple/simple.c --- a/src/protocols/simple/simple.c Wed Dec 07 01:47:31 2005 +0000 +++ b/src/protocols/simple/simple.c Wed Dec 07 04:50:36 2005 +0000 @@ -260,21 +260,24 @@ static gchar *auth_header(struct simple_account_data *sip, struct sip_auth *auth, gchar *method, gchar *target) { gchar noncecount[9]; - HASHHEX HA2; - HASHHEX response; + gchar *response; gchar *ret; gchar *tmp; if(auth->type == 1) { /* Digest */ sprintf(noncecount, "%08d", auth->nc++); - DigestCalcResponse(auth->HA1, auth->nonce, noncecount, "", "", method, target, HA2, response); + response = gaim_cipher_http_digest_calculate_response( + "md5", method, target, NULL, NULL, 0, + auth->nonce, noncecount, NULL, auth->digest_session_key); gaim_debug(GAIM_DEBUG_MISC, "simple", "response %s\n", response); - ret = g_strdup_printf("Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", nc=\"%s\", response=\"%s\"\r\n",sip->username, auth->realm, auth->nonce, target, noncecount, response); + + ret = g_strdup_printf("Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", nc=\"%s\", response=\"%s\"\r\n", sip->username, auth->realm, auth->nonce, target, noncecount, response); + g_free(response); return ret; } else if(auth->type == 2) { /* NTLM */ if(auth->nc == 3) { ret = gaim_ntlm_gen_type3(sip->username, sip->password, "gaim", sip->servername, auth->nonce); - tmp = g_strdup_printf("NTLM qop=\"auth\" realm=\"%s\" targetname=\"%s\" response=\"%s\"\r\n",auth->realm, auth->target, ret); + tmp = g_strdup_printf("NTLM qop=\"auth\" realm=\"%s\" targetname=\"%s\" response=\"%s\"\r\n", auth->realm, auth->target, ret); g_free(ret); return tmp; } @@ -285,9 +288,13 @@ } sprintf(noncecount, "%08d", auth->nc++); - DigestCalcResponse(auth->HA1, auth->nonce, noncecount, "", "", method, target, HA2, response); + response = gaim_cipher_http_digest_calculate_response( + "md5", method, target, NULL, NULL, 0, + auth->nonce, noncecount, NULL, auth->digest_session_key); gaim_debug(GAIM_DEBUG_MISC, "simple", "response %s\n", response); - ret = g_strdup_printf("Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", nc=\"%s\", response=\"%s\"\r\n",sip->username, auth->realm, auth->nonce, target, noncecount, response); + + ret = g_strdup_printf("Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", nc=\"%s\", response=\"%s\"\r\n", sip->username, auth->realm, auth->nonce, target, noncecount, response); + g_free(response); return ret; } @@ -346,7 +353,8 @@ gaim_debug(GAIM_DEBUG_MISC, "simple", "nonce: %s realm: %s ", auth->nonce, auth->realm); - DigestCalcHA1("md5", sip->username, auth->realm, sip->password, auth->nonce, "", auth->HA1); + auth->digest_session_key = gaim_cipher_http_digest_calculate_session_key( + "md5", sip->username, auth->realm, sip->password, auth->nonce, NULL); auth->nc=1; } diff -r 29e237c4141b -r cfc808463763 src/protocols/simple/simple.h --- a/src/protocols/simple/simple.h Wed Dec 07 01:47:31 2005 +0000 +++ b/src/protocols/simple/simple.h Wed Dec 07 04:50:36 2005 +0000 @@ -25,8 +25,10 @@ #include #include + +#include #include -#include + #include "sipmsg.h" #define SIMPLE_BUF_INC 1024 @@ -50,11 +52,11 @@ struct sip_auth { int type; /* 1 = Digest / 2 = NTLM */ - gchar *nonce; - gchar *realm; + gchar *nonce; + gchar *realm; gchar *target; int nc; - HASHHEX HA1; + gchar *digest_session_key; int retries; };