changeset 12382:cfc808463763

[gaim-migrate @ 14688] Reimplement HTTP Digest Authentication (RFC 2617) as part of the Cipher API committer: Tailor Script <tailor@pidgin.im>
author Richard Laager <rlaager@wiktel.com>
date Wed, 07 Dec 2005 04:50:36 +0000
parents 29e237c4141b
children 3f70719e375d
files plugins/ciphertest.c src/cipher.c src/cipher.h src/protocols/simple/Makefile.am src/protocols/simple/Makefile.mingw src/protocols/simple/digcalc.c src/protocols/simple/digcalc.h src/protocols/simple/simple.c src/protocols/simple/simple.h
diffstat 9 files changed, 293 insertions(+), 224 deletions(-) [+]
line wrap: on
line diff
--- 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;
 }
--- 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);
+}
--- 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
--- 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) 
 
--- 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
 
 
--- 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 <string.h>
-#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);
-};
--- 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 */
-    );
--- 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;
 }
--- 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 <glib.h>
 #include <time.h>
+
+#include <cipher.h>
 #include <prpl.h>
-#include <digcalc.h>
+
 #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;
 };