From c7e01fcdfd407083fb186dd277c4a08b7636ebbe Mon Sep 17 00:00:00 2001
From: magnum <magnum>
Date: Wed, 17 Aug 2011 23:56:37 +0200
Subject: [PATCH 19/19] DMD5 improved a little

---
 src/DMD5_fmt_plug.c |  133 ++++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 100 insertions(+), 33 deletions(-)

diff --git a/src/DMD5_fmt_plug.c b/src/DMD5_fmt_plug.c
index 83c4566..2fe89d0 100644
--- a/src/DMD5_fmt_plug.c
+++ b/src/DMD5_fmt_plug.c
@@ -1,14 +1,17 @@
 /*
- * DMD5_fmt.c (version 1)
+ * DMD5_fmt.c
+ *
+ * Modified by magnum 2011 (original version had no self test and could only
+ * crack one set of authentication, hard-coded in this file).
+ * No rights reserved.
+ *
+ * Input format:
+ * $DIGEST-MD5$ username $ realm $ nonce $ digest_uri $ cnonce $ nc $ qop $ response [ $ authzid ]
  *
  * DIGEST-MD5 authentication module for Solar Designer's John the Ripper
  * Uses Solar Designer's MD5 implementation.
  * regenrecht@o2.pl, Jan 2006
  *
- * You need to sniff authentication data sent by client (all important values
- * are sent in ASCII text) and fill up coresponding hard coded values below.
- * Then simply run john against password file which contains single line:
- * "username:$DIGEST-MD5$" (without quotes...)
  */
 
 #include <string.h>
@@ -22,10 +25,9 @@
 #define FORMAT_LABEL		"dmd5"
 #define FORMAT_NAME		"DIGEST-MD5"
 #define ALGORITHM_NAME		"DIGEST-MD5 authentication"
-#define DMD5_TEST		0
 
 #define BENCHMARK_COMMENT	""
-#define BENCHMARK_LENGTH	-1
+#define BENCHMARK_LENGTH	0
 
 #define A1_x_MAX_LEN		1024
 #define A2_MAX_LEN		1024
@@ -42,18 +44,6 @@
 #define MIN_KEYS_PER_CRYPT	1
 #define MAX_KEYS_PER_CRYPT	1
 
-/* ------------- so what's yer poison? 'test' ------------ */
-static char *username	= "s3443";
-static char *realm	= "pjwstk";
-static char *nonce	= "00";
-static char *digest_uri	= "ldap/10.253.34.43";
-static char *cnonce	= "0734d94ad9abd5bd7fc5e7e77bcf49a8";
-static char *nc		= "00000001";
-static char *qop	= "auth-int";
-static char *response	= "dd98347e6da3efd6c4ff2263a729ef77";
-static char *authzid	= 0;
-/* ------------------------------------------------------- */
-
 static char itoa16_shr_04[] =
 	"0000000000000000"
 	"1111111111111111"
@@ -115,9 +105,97 @@ static MD5_CTX ctx;
 #define snprintf sprintf_s
 #endif
 
-static void dmd5_init(struct fmt_main *pFmt)
+static struct fmt_tests tests[] = {
+	{"$DIGEST-MD5$s3443$pjwstk$00$ldap/10.253.34.43$0734d94ad9abd5bd7fc5e7e77bcf49a8$00000001$auth-int$dd98347e6da3efd6c4ff2263a729ef77", "test"},
+	{NULL}
+};
+
+static int dmd5_valid(char *ciphertext, struct fmt_main *pFmt)
+{
+	if (strncmp(ciphertext, "$DIGEST-MD5$", 12) != 0)
+		return 0;
+
+	unsigned char *c = (unsigned char *)ciphertext + 12;
+	unsigned char f = 0;
+
+	while(*c)
+		if (*c++ == '$')
+			f++;
+
+	if (f < 7 || f > 8) // last field is optional
+		return 0;
+
+	return 1;
+}
+
+static void *dmd5_binary(char *ciphertext)
 {
+	char username[64];
+	char realm[64];
+	char nonce[64];
+	char digest_uri[256];
+	char cnonce[33];
+	char nc[9];
+	char qop[9];
+	char response[33];
+	char authzid[8];
 	unsigned char *ptr_src, *ptr_dst, v, i;
+	char *p, *data = ciphertext + 12;
+
+	p = strchr(data, '$');
+	if (!p)
+		return NULL;
+	strnzcpy(username, data, p - data + 1);
+	data = p + 1;
+
+	p = strchr(data, '$');
+	if (!p)
+		return NULL;
+	strnzcpy(realm, data, p - data + 1);
+	data = p + 1;
+
+	p = strchr(data, '$');
+	if (!p)
+		return NULL;
+	strnzcpy(nonce, data, p - data + 1);
+	data = p + 1;
+
+	p = strchr(data, '$');
+	if (!p)
+		return NULL;
+	strnzcpy(digest_uri, data, p - data + 1);
+	data = p + 1;
+
+	p = strchr(data, '$');
+	if (!p)
+		return NULL;
+	strnzcpy(cnonce, data, p - data + 1);
+	data = p + 1;
+
+	p = strchr(data, '$');
+	if (!p)
+		return NULL;
+	strnzcpy(nc, data, p - data + 1);
+	data = p + 1;
+
+	p = strchr(data, '$');
+	if (!p)
+		return NULL;
+	strnzcpy(qop, data, p - data + 1);
+	data = p + 1;
+
+	p = strchr(data, '$');
+	if (p) {
+		strnzcpy(response, data, p - data + 1);
+		data = p + 1;
+		if (*data)
+			strnzcpy(authzid, data, sizeof(authzid));
+		else
+			*authzid = 0;
+	} else {
+		strnzcpy(response, data, sizeof(response));
+		*authzid = 0;
+	}
 
 	if (!strcmp(qop, "auth"))
 		snprintf((char *)A2, A2_MAX_LEN, "AUTHENTICATE:%s", digest_uri);
@@ -165,18 +243,7 @@ static void dmd5_init(struct fmt_main *pFmt)
 		binary_response[i] =
 			(atoi16[ARCH_INDEX(response[i*2])] << 4)
 			+ atoi16[ARCH_INDEX(response[i*2+1])];
-}
 
-static int dmd5_valid(char *ciphertext, struct fmt_main *pFmt)
-{
-	if (strncmp(ciphertext, "$DIGEST-MD5$", 12) != 0)
-		return 0;
-
-	return 1;
-}
-
-static void *dmd5_binary(char *ciphertext)
-{
 	return (void *)binary_response;
 }
 
@@ -243,10 +310,10 @@ struct fmt_main fmt_DMD5 = {
 		MIN_KEYS_PER_CRYPT,
 		MAX_KEYS_PER_CRYPT,
 		FMT_CASE | FMT_8_BIT,
-		DMD5_TEST
+		tests
 	},
 	{
-		dmd5_init,
+		fmt_default_init,
 		fmt_default_prepare,
 		dmd5_valid,
 		fmt_default_split,
-- 
1.7.4.1

