From 4b995116ce095091a2141605c1958bd5b10cce46 Mon Sep 17 00:00:00 2001
From: magnum <magnum>
Date: Mon, 17 Oct 2011 02:34:21 +0200
Subject: [PATCH] --mkpc=N option (peg keys_per_crypt to N)

---
 doc/OPTIONS   |   11 +++++++++++
 src/formats.c |   11 +++++++++++
 src/options.c |    3 +++
 src/options.h |    3 +++
 4 files changed, 28 insertions(+), 0 deletions(-)

diff --git a/doc/OPTIONS b/doc/OPTIONS
index 424b2a8..d3b70f2 100644
--- a/doc/OPTIONS
+++ b/doc/OPTIONS
@@ -265,6 +265,17 @@ This will automagically emit a status line at every cracked password. This is
 mostly for testing.
 
 
+--mkpc=N                force min/max keys per crypt to N
+
+This option is for certain kinds of testing and is not mentioned in the usage
+blob. Many formats perform the crypts in batches of several (sometimes
+thousands or even tens of thousands) candidates. This option forces it down
+from the format's default. For most purposes, you would use 1. One good
+example is for studying which rules give most "hits": Without this options,
+you can't know for sure which rule produced a successful guess when analyzing
+the log file.
+
+
 	Additional utilities.
 
 There are some related utilities in John's run directory:
diff --git a/src/formats.c b/src/formats.c
index 9461e41..8cbd9ac 100644
--- a/src/formats.c
+++ b/src/formats.c
@@ -10,6 +10,7 @@
 
 #include "params.h"
 #include "formats.h"
+#include "options.h"
 
 struct fmt_main *fmt_list = NULL;
 static struct fmt_main **fmt_tail = &fmt_list;
@@ -28,6 +29,16 @@ void fmt_init(struct fmt_main *format)
 		format->methods.init(format);
 		format->private.initialized = 1;
 	}
+	if (options.mkpc) {
+		if (options.mkpc <= format->params.max_keys_per_crypt)
+			format->params.min_keys_per_crypt =
+				format->params.max_keys_per_crypt =
+				options.mkpc;
+		else {
+			fprintf(stderr, "Can't set mkpc larger than %u for %s format\n", format->params.max_keys_per_crypt, format->params.label);
+			error();
+		}
+	}
 }
 
 char *fmt_self_test(struct fmt_main *format)
diff --git a/src/options.c b/src/options.c
index b9e2daf..a83c363 100644
--- a/src/options.c
+++ b/src/options.c
@@ -122,6 +122,8 @@ static struct opt_entry opt_list[] = {
 		OPT_FMT_STR_ALLOC, &options.config},
 	{"nolog", FLG_NOLOG, FLG_NOLOG},
 	{"crack-status", FLG_CRKSTAT, FLG_CRKSTAT},
+	{"mkpc", FLG_NONE, FLG_NONE, 0, OPT_REQ_PARAM,
+		"%u", &options.mkpc},
 	{NULL}
 };
 
@@ -236,6 +238,7 @@ void opt_init(char *name, int argc, char **argv)
 	options.loader.field_sep_char = options.field_sep_char = ':';
 	options.loader.max_fix_state_delay = 0;
 	options.loader.max_wordfile_memory = 5000000;
+	options.mkpc = 0;
 
 	list_init(&options.passwd);
 
diff --git a/src/options.h b/src/options.h
index fc1edfa..44959ae 100644
--- a/src/options.h
+++ b/src/options.h
@@ -185,6 +185,9 @@ struct options_main {
 /* List of dll files to load for additional formats */
 	struct list_main *fmt_dlls;
 #endif
+
+/* Forced min/max_keys_per_crypt (for testing purposes) */
+	int mkpc;
 };
 
 extern struct options_main options;
-- 
1.7.4.1

