diff -urp john-1.7.9.6/src/AFS_fmt.c john-1.7.9.6-newform/src/AFS_fmt.c --- john-1.7.9.6/src/AFS_fmt.c 2012-07-15 09:32:01 +0000 +++ john-1.7.9.6-newform/src/AFS_fmt.c 2012-07-18 01:45:58 +0000 @@ -449,6 +449,8 @@ struct fmt_main fmt_AFS = { tests }, { init, + fmt_default_done, + fmt_default_reset, fmt_default_prepare, valid, fmt_default_split, diff -urp john-1.7.9.6/src/BF_fmt.c john-1.7.9.6-newform/src/BF_fmt.c --- john-1.7.9.6/src/BF_fmt.c 2012-07-15 09:33:40 +0000 +++ john-1.7.9.6-newform/src/BF_fmt.c 2012-07-18 01:46:04 +0000 @@ -292,6 +292,8 @@ struct fmt_main fmt_BF = { tests }, { init, + fmt_default_done, + fmt_default_reset, fmt_default_prepare, valid, fmt_default_split, diff -urp john-1.7.9.6/src/BSDI_fmt.c john-1.7.9.6-newform/src/BSDI_fmt.c --- john-1.7.9.6/src/BSDI_fmt.c 2012-07-15 09:35:10 +0000 +++ john-1.7.9.6-newform/src/BSDI_fmt.c 2012-07-18 01:46:06 +0000 @@ -406,6 +406,8 @@ struct fmt_main fmt_BSDI = { tests }, { init, + fmt_default_done, + fmt_default_reset, fmt_default_prepare, valid, fmt_default_split, diff -urp john-1.7.9.6/src/DES_fmt.c john-1.7.9.6-newform/src/DES_fmt.c --- john-1.7.9.6/src/DES_fmt.c 2012-07-15 09:36:35 +0000 +++ john-1.7.9.6-newform/src/DES_fmt.c 2012-07-18 01:46:10 +0000 @@ -369,6 +369,8 @@ struct fmt_main fmt_DES = { #else DES_std_init, #endif + fmt_default_done, + fmt_default_reset, fmt_default_prepare, valid, split, diff -urp john-1.7.9.6/src/LM_fmt.c john-1.7.9.6-newform/src/LM_fmt.c --- john-1.7.9.6/src/LM_fmt.c 2012-07-15 09:37:34 +0000 +++ john-1.7.9.6-newform/src/LM_fmt.c 2012-07-18 01:46:12 +0000 @@ -210,6 +210,8 @@ struct fmt_main fmt_LM = { tests }, { init, + fmt_default_done, + fmt_default_reset, prepare, valid, split, diff -urp john-1.7.9.6/src/MD5_fmt.c john-1.7.9.6-newform/src/MD5_fmt.c --- john-1.7.9.6/src/MD5_fmt.c 2012-07-15 09:39:00 +0000 +++ john-1.7.9.6-newform/src/MD5_fmt.c 2012-07-18 01:46:15 +0000 @@ -247,6 +247,8 @@ struct fmt_main fmt_MD5 = { tests }, { init, + fmt_default_done, + fmt_default_reset, fmt_default_prepare, valid, fmt_default_split, diff -urp john-1.7.9.6/src/bench.c john-1.7.9.6-newform/src/bench.c --- john-1.7.9.6/src/bench.c 2012-07-14 13:18:54 +0000 +++ john-1.7.9.6-newform/src/bench.c 2012-07-17 16:51:27 +0000 @@ -270,14 +270,14 @@ int benchmark_all(void) &results_m))) { puts(result); failed++; - continue; + goto next; } if (msg_1) if ((result = benchmark_format(format, 1, &results_1))) { puts(result); failed++; - continue; + goto next; } puts("DONE"); @@ -294,7 +294,7 @@ int benchmark_all(void) if (!msg_1) { putchar('\n'); - continue; + goto next; } benchmark_cps(&results_1.count, results_1.real, s_real); @@ -306,6 +306,9 @@ int benchmark_all(void) printf("%s:\t%s c/s\n\n", msg_1, s_real); #endif + +next: + fmt_done(format); } while ((format = format->next) && !event_abort); if (failed && total > 1 && !event_abort) diff -urp john-1.7.9.6/src/best.c john-1.7.9.6-newform/src/best.c --- john-1.7.9.6/src/best.c 2011-11-06 11:19:06 +0000 +++ john-1.7.9.6-newform/src/best.c 2012-07-17 16:53:12 +0000 @@ -80,6 +80,8 @@ int main(int argc, char **argv) s_real, s_virtual); } + fmt_done(format); + printf("%lu\n", virtual); return virtual ? 0 : 1; diff -urp john-1.7.9.6/src/c3_fmt.c john-1.7.9.6-newform/src/c3_fmt.c --- john-1.7.9.6/src/c3_fmt.c 2012-07-15 09:39:28 +0000 +++ john-1.7.9.6-newform/src/c3_fmt.c 2012-07-18 01:46:18 +0000 @@ -434,6 +434,8 @@ struct fmt_main fmt_crypt = { tests }, { fmt_default_init, + fmt_default_done, + fmt_default_reset, fmt_default_prepare, valid, fmt_default_split, diff -urp john-1.7.9.6/src/cracker.c john-1.7.9.6-newform/src/cracker.c --- john-1.7.9.6/src/cracker.c 2012-07-14 13:36:44 +0000 +++ john-1.7.9.6-newform/src/cracker.c 2012-07-18 01:59:45 +0000 @@ -56,7 +56,15 @@ void crk_init(struct db_main *db, void ( char *where; size_t size; - if (db->loaded) +/* + * We should have already called fmt_self_test() from john.c. This redundant + * self-test is only to catch some more obscure bugs in debugging builds (it + * is a no-op in normal builds). Additionally, we skip it even in debugging + * builds if we're running in --stdout mode (there's no format involved then) + * or if the format has a custom reset() method (we've already called reset(db) + * from john.c, and we don't want to mess with the format's state). + */ + if (db->loaded && db->format->methods.reset == fmt_default_reset) if ((where = fmt_self_test(db->format))) { log_event("! Self test failed (%s)", where); fprintf(stderr, "Self test failed (%s)\n", where); diff -urp john-1.7.9.6/src/dummy.c john-1.7.9.6-newform/src/dummy.c --- john-1.7.9.6/src/dummy.c 2012-07-15 09:42:38 +0000 +++ john-1.7.9.6-newform/src/dummy.c 2012-07-18 01:46:22 +0000 @@ -276,6 +276,8 @@ struct fmt_main fmt_dummy = { tests }, { fmt_default_init, + fmt_default_done, + fmt_default_reset, fmt_default_prepare, valid, fmt_default_split, diff -urp john-1.7.9.6/src/formats.c john-1.7.9.6-newform/src/formats.c --- john-1.7.9.6/src/formats.c 2012-07-17 12:44:49 +0000 +++ john-1.7.9.6-newform/src/formats.c 2012-07-18 01:48:21 +0000 @@ -29,6 +29,14 @@ void fmt_init(struct fmt_main *format) } } +void fmt_done(struct fmt_main *format) +{ + if (format->private.initialized) { + format->methods.done(); + format->private.initialized = 0; + } +} + static int is_poweroftwo(size_t align) { return align != 0 && (align & (align - 1)) == 0; @@ -49,6 +57,14 @@ static char *fmt_self_test_body(struct f void *binary, *salt; int binary_align_warned = 0, salt_align_warned = 0; +/* + * Test each format just once unless we're debugging. + */ +#ifndef DEBUG + if (format->private.initialized == 2) + return NULL; +#endif + if (format->params.plaintext_length < 1 || format->params.plaintext_length > PLAINTEXT_BUFFER_SIZE - 3) return "plaintext_length"; @@ -64,6 +80,8 @@ static char *fmt_self_test_body(struct f fmt_init(format); + format->methods.reset(NULL); + if (!(current = format->params.tests)) return NULL; ntests = 0; while ((current++)->ciphertext) @@ -166,6 +184,8 @@ static char *fmt_self_test_body(struct f } } while (done != 3); + format->private.initialized = 2; + return NULL; } @@ -214,6 +234,14 @@ void fmt_default_init(struct fmt_main *s { } +void fmt_default_done(void) +{ +} + +void fmt_default_reset(struct db_main *db) +{ +} + char *fmt_default_prepare(char *fields[10], struct fmt_main *self) { return fields[1]; diff -urp john-1.7.9.6/src/formats.h john-1.7.9.6-newform/src/formats.h --- john-1.7.9.6/src/formats.h 2012-07-15 09:00:07 +0000 +++ john-1.7.9.6-newform/src/formats.h 2012-07-18 01:44:33 +0000 @@ -13,6 +13,12 @@ #include "params.h" /* + * The reset() format method accepts a pointer to struct db_main, yet we can't + * just include loader.h here because that would be a circular dependency. + */ +struct db_main; + +/* * Format property flags. */ /* Uses case-sensitive passwords */ @@ -100,6 +106,17 @@ struct fmt_methods { * shared underlying resource is used). */ void (*init)(struct fmt_main *self); +/* De-initializes this format, which must have been previously initialized */ + void (*done)(void); + +/* Called whenever the set of password hashes being cracked changes, such as + * after self-test, but before actual cracking starts. When called before a + * self-test or benchmark rather than before actual cracking, db may be NULL. + * Normally, this is a no-op since a format implementation shouldn't mess with + * the database unnecessarily. However, when there is a good reason to do so + * this may e.g. transfer the salts and hashes onto a GPU card. */ + void (*reset)(struct db_main *db); + /* Extracts the ciphertext string out of the input file fields. Normally, this * will simply return field[1], but in some special cases it may use another * field (e.g., when the hash type is commonly used with PWDUMP rather than @@ -208,6 +225,11 @@ extern void fmt_register(struct fmt_main extern void fmt_init(struct fmt_main *format); /* + * De-initializes this format if it was previously initialized. + */ +extern void fmt_done(struct fmt_main *format); + +/* * Tests the format's methods for correct operation. Returns NULL on * success, method name on error. */ @@ -217,6 +239,8 @@ extern char *fmt_self_test(struct fmt_ma * Default methods. */ extern void fmt_default_init(struct fmt_main *self); +extern void fmt_default_done(void); +extern void fmt_default_reset(struct db_main *db); extern char *fmt_default_prepare(char *fields[10], struct fmt_main *self); extern int fmt_default_valid(char *ciphertext, struct fmt_main *self); extern char *fmt_default_split(char *ciphertext, int index, diff -urp john-1.7.9.6/src/john.c john-1.7.9.6-newform/src/john.c --- john-1.7.9.6/src/john.c 2011-11-23 02:46:59 +0000 +++ john-1.7.9.6-newform/src/john.c 2012-07-18 02:00:20 +0000 @@ -1,6 +1,6 @@ /* * This file is part of John the Ripper password cracker, - * Copyright (c) 1996-2004,2006,2009-2011 by Solar Designer + * Copyright (c) 1996-2004,2006,2009-2012 by Solar Designer */ #include @@ -316,8 +316,15 @@ static void john_run(void) int remaining = database.password_count; if (!(options.flags & FLG_STDOUT)) { - status_init(NULL, 1); + char *where = fmt_self_test(database.format); + if (where) { + fprintf(stderr, "Self test failed (%s)\n", + where); + error(); + } + database.format->methods.reset(&database); log_init(LOG_NAME, POT_NAME, options.session); + status_init(NULL, 1); john_log_format(); if (idle_requested(database.format)) log_event("- Configured to use otherwise idle " @@ -368,16 +375,18 @@ static void john_run(void) static void john_done(void) { - path_done(); - - if ((options.flags & FLG_CRACKING_CHK) && - !(options.flags & FLG_STDOUT)) { + if ((options.flags & (FLG_CRACKING_CHK | FLG_STDOUT)) == + FLG_CRACKING_CHK) { if (event_abort) log_event("Session aborted"); else log_event("Session completed"); + fmt_done(database.format); } log_done(); + + path_done(); + check_abort(0); } diff -urp john-1.7.9.6/src/trip_fmt.c john-1.7.9.6-newform/src/trip_fmt.c --- john-1.7.9.6/src/trip_fmt.c 2012-07-15 09:41:42 +0000 +++ john-1.7.9.6-newform/src/trip_fmt.c 2012-07-18 01:46:20 +0000 @@ -592,6 +592,8 @@ struct fmt_main fmt_trip = { tests }, { init, + fmt_default_done, + fmt_default_reset, fmt_default_prepare, valid, fmt_default_split,