diff -urp john-1.7.9.4/src/AFS_fmt.c john-1.7.9.4-newform/src/AFS_fmt.c --- john-1.7.9.4/src/AFS_fmt.c 2012-01-29 00:48:58 +0000 +++ john-1.7.9.4-newform/src/AFS_fmt.c 2012-07-13 02:51:23 +0000 @@ -90,7 +90,7 @@ static union { } AFS_long_KS; static DES_binary AFS_long_IV_binary; -static void init(void) +static void init(struct fmt_main *self) { ARCH_WORD_32 block[2]; #if !ARCH_LITTLE_ENDIAN @@ -113,7 +113,7 @@ static void init(void) memcpy(AFS_long_IV_binary, DES_IV, sizeof(DES_binary)); } -static int valid(char *ciphertext) +static int valid(char *ciphertext, struct fmt_main *self) { char *pos; int index, count; @@ -445,6 +445,7 @@ struct fmt_main fmt_AFS = { tests }, { init, + fmt_default_prepare, valid, fmt_default_split, get_binary, diff -urp john-1.7.9.4/src/BF_fmt.c john-1.7.9.4-newform/src/BF_fmt.c --- john-1.7.9.4/src/BF_fmt.c 2012-01-29 00:48:58 +0000 +++ john-1.7.9.4-newform/src/BF_fmt.c 2012-07-13 02:51:51 +0000 @@ -86,7 +86,7 @@ static BF_salt saved_salt; struct fmt_main fmt_BF; #endif -static void init(void) +static void init(struct fmt_main *self) { #ifdef _OPENMP int n = BF_Nmin * omp_get_max_threads(), max; @@ -105,7 +105,7 @@ static void init(void) sign_extension_bug = 0; } -static int valid(char *ciphertext) +static int valid(char *ciphertext, struct fmt_main *self) { int rounds; char *pos; @@ -288,6 +288,7 @@ struct fmt_main fmt_BF = { tests }, { init, + fmt_default_prepare, valid, fmt_default_split, BF_std_get_binary, diff -urp john-1.7.9.4/src/BSDI_fmt.c john-1.7.9.4-newform/src/BSDI_fmt.c --- john-1.7.9.4/src/BSDI_fmt.c 2012-01-29 00:48:58 +0000 +++ john-1.7.9.4-newform/src/BSDI_fmt.c 2012-07-13 02:52:04 +0000 @@ -74,7 +74,7 @@ static struct { struct fmt_main fmt_BSDI; -static void init(void) +static void init(struct fmt_main *self) { DES_std_init(); @@ -96,7 +96,7 @@ static void init(void) MEM_ALIGN_CACHE); } -static int valid(char *ciphertext) +static int valid(char *ciphertext, struct fmt_main *self) { char *pos; @@ -400,6 +400,7 @@ struct fmt_main fmt_BSDI = { tests }, { init, + fmt_default_prepare, valid, fmt_default_split, (void *(*)(char *)) diff -urp john-1.7.9.4/src/DES_fmt.c john-1.7.9.4-newform/src/DES_fmt.c --- john-1.7.9.4/src/DES_fmt.c 2012-01-29 00:48:58 +0000 +++ john-1.7.9.4-newform/src/DES_fmt.c 2012-07-13 02:52:20 +0000 @@ -74,7 +74,7 @@ static struct { struct fmt_main fmt_DES; #endif -static void init(void) +static void init(struct fmt_main *self) { DES_bs_init(0, DES_bs_cpt); #if DES_bs_mt @@ -85,7 +85,7 @@ static void init(void) #endif -static int valid(char *ciphertext) +static int valid(char *ciphertext, struct fmt_main *self) { char *pos; @@ -109,7 +109,7 @@ static int valid(char *ciphertext) } } -static char *split(char *ciphertext, int index) +static char *split(char *ciphertext, int index, struct fmt_main *self) { static char out[14]; @@ -363,6 +363,7 @@ struct fmt_main fmt_DES = { #else DES_std_init, #endif + fmt_default_prepare, valid, split, (void *(*)(char *)) diff -urp john-1.7.9.4/src/LM_fmt.c john-1.7.9.4-newform/src/LM_fmt.c --- john-1.7.9.4/src/LM_fmt.c 2012-01-29 00:48:58 +0000 +++ john-1.7.9.4-newform/src/LM_fmt.c 2012-07-13 06:24:18 +0000 @@ -48,7 +48,7 @@ static struct fmt_tests tests[] = { struct fmt_main fmt_LM; #endif -static void init(void) +static void init(struct fmt_main *self) { DES_bs_init(1, DES_bs_cpt); #if DES_bs_mt @@ -57,7 +57,14 @@ static void init(void) #endif } -static int valid(char *ciphertext) +static char *prepare(char *fields[10], struct fmt_main *self) +{ + if (fields[2] && strlen(fields[2]) == 32) + return fields[2]; + return fields[1]; +} + +static int valid(char *ciphertext, struct fmt_main *self) { char *pos; char lower[CIPHERTEXT_LENGTH - 16 + 1]; @@ -80,7 +87,7 @@ static int valid(char *ciphertext) return 1; } -static char *split(char *ciphertext, int index) +static char *split(char *ciphertext, int index, struct fmt_main *self) { static char out[21]; @@ -194,6 +201,7 @@ struct fmt_main fmt_LM = { tests }, { init, + prepare, valid, split, get_binary, diff -urp john-1.7.9.4/src/MD5_fmt.c john-1.7.9.4-newform/src/MD5_fmt.c --- john-1.7.9.4/src/MD5_fmt.c 2012-01-29 00:48:58 +0000 +++ john-1.7.9.4-newform/src/MD5_fmt.c 2012-07-13 02:52:44 +0000 @@ -46,7 +46,7 @@ static char (*saved_key)[PLAINTEXT_LENGT struct fmt_main fmt_MD5; -static void init(void) +static void init(struct fmt_main *self) { MD5_std_init(); @@ -60,7 +60,7 @@ static void init(void) MEM_ALIGN_CACHE); } -static int valid(char *ciphertext) +static int valid(char *ciphertext, struct fmt_main *self) { char *pos, *start; @@ -243,6 +243,7 @@ struct fmt_main fmt_MD5 = { tests }, { init, + fmt_default_prepare, valid, fmt_default_split, (void *(*)(char *))MD5_std_get_binary, diff -urp john-1.7.9.4/src/bench.c john-1.7.9.4-newform/src/bench.c --- john-1.7.9.4/src/bench.c 2012-01-29 00:48:58 +0000 +++ john-1.7.9.4-newform/src/bench.c 2012-07-13 03:13:44 +0000 @@ -1,6 +1,6 @@ /* * This file is part of John the Ripper password cracker, - * Copyright (c) 1996-2001,2003,2004,2006,2008-2010,2011 by Solar Designer + * Copyright (c) 1996-2001,2003,2004,2006,2008-2012 by Solar Designer */ #define _XOPEN_SOURCE 500 /* for setitimer(2) */ @@ -119,9 +119,14 @@ char *benchmark_format(struct fmt_main * for (index = 0; index < 2; index++) { two_salts[index] = mem_alloc(format->params.salt_size); - if ((ciphertext = format->params.tests[index].ciphertext)) + if ((ciphertext = format->params.tests[index].ciphertext)) { + char **fields = format->params.tests[index].fields; + if (!fields[1]) + fields[1] = ciphertext; + ciphertext = format->methods.split( + format->methods.prepare(fields, format), 0, format); salt = format->methods.salt(ciphertext); - else + } else salt = two_salts[0]; memcpy(two_salts[index], salt, format->params.salt_size); diff -urp john-1.7.9.4/src/c3_fmt.c john-1.7.9.4-newform/src/c3_fmt.c --- john-1.7.9.4/src/c3_fmt.c 2012-01-29 00:48:58 +0000 +++ john-1.7.9.4-newform/src/c3_fmt.c 2012-07-13 02:52:52 +0000 @@ -62,7 +62,7 @@ static char crypt_out[MAX_KEYS_PER_CRYPT static struct crypt_data *crypt_data[MAX_THREADS]; #endif -static int valid(char *ciphertext) +static int valid(char *ciphertext, struct fmt_main *self) { int length, count_base64, id, pw_length; char pw[PLAINTEXT_LENGTH + 1], *new_ciphertext; @@ -430,6 +430,7 @@ struct fmt_main fmt_crypt = { tests }, { fmt_default_init, + fmt_default_prepare, valid, fmt_default_split, binary, diff -urp john-1.7.9.4/src/dummy.c john-1.7.9.4-newform/src/dummy.c --- john-1.7.9.4/src/dummy.c 2012-01-29 00:48:58 +0000 +++ john-1.7.9.4-newform/src/dummy.c 2012-07-13 02:51:03 +0000 @@ -38,7 +38,7 @@ static struct fmt_tests tests[] = { static char saved_key[MAX_KEYS_PER_CRYPT][PLAINTEXT_LENGTH + 1]; -static int valid(char *ciphertext) +static int valid(char *ciphertext, struct fmt_main *self) { char *p, *q, c; @@ -272,6 +272,7 @@ struct fmt_main fmt_dummy = { tests }, { fmt_default_init, + fmt_default_prepare, valid, fmt_default_split, binary, diff -urp john-1.7.9.4/src/formats.c john-1.7.9.4-newform/src/formats.c --- john-1.7.9.4/src/formats.c 2012-01-29 00:48:58 +0000 +++ john-1.7.9.4-newform/src/formats.c 2012-07-13 03:11:14 +0000 @@ -24,7 +24,7 @@ void fmt_register(struct fmt_main *forma void fmt_init(struct fmt_main *format) { if (!format->private.initialized) { - format->methods.init(); + format->methods.init(format); format->private.initialized = 1; } } @@ -54,7 +54,7 @@ static char *fmt_self_test_body(struct f if (format->params.plaintext_length > PLAINTEXT_BUFFER_SIZE - 3) return "length"; - if (format->methods.valid("*")) return "valid"; + if (format->methods.valid("*", format)) return "valid"; fmt_init(format); @@ -67,9 +67,14 @@ static char *fmt_self_test_body(struct f done = 0; index = 0; max = format->params.max_keys_per_crypt; do { - if (format->methods.valid(current->ciphertext) != 1) + if (!current->fields[1]) + current->fields[1] = current->ciphertext; + ciphertext = format->methods.prepare(current->fields, format); + if (!ciphertext || strlen(ciphertext) < 7) + return "prepare"; + if (format->methods.valid(ciphertext, format) != 1) return "valid"; - ciphertext = format->methods.split(current->ciphertext, 0); + ciphertext = format->methods.split(ciphertext, 0, format); plaintext = current->plaintext; /* @@ -182,16 +187,21 @@ char *fmt_self_test(struct fmt_main *for return retval; } -void fmt_default_init(void) +void fmt_default_init(struct fmt_main *self) { } -int fmt_default_valid(char *ciphertext) +char *fmt_default_prepare(char *fields[10], struct fmt_main *self) +{ + return fields[1]; +} + +int fmt_default_valid(char *ciphertext, struct fmt_main *self) { return 0; } -char *fmt_default_split(char *ciphertext, int index) +char *fmt_default_split(char *ciphertext, int index, struct fmt_main *self) { return ciphertext; } diff -urp john-1.7.9.4/src/formats.h john-1.7.9.4-newform/src/formats.h --- john-1.7.9.4/src/formats.h 2011-04-01 21:38:09 +0000 +++ john-1.7.9.4-newform/src/formats.h 2012-07-13 04:51:58 +0000 @@ -1,6 +1,6 @@ /* * This file is part of John the Ripper password cracker, - * Copyright (c) 1996-2001,2005,2010,2011 by Solar Designer + * Copyright (c) 1996-2001,2005,2010-2012 by Solar Designer */ /* @@ -37,6 +37,7 @@ */ struct fmt_tests { char *ciphertext, *plaintext; + char *fields[10]; }; /* @@ -81,22 +82,39 @@ struct fmt_params { }; /* + * fmt_main is declared for real further down this file, but we refer to it in + * function prototypes in fmt_methods. + */ +struct fmt_main; + +/* * Functions to implement a cracking algorithm. * * When passing binary ciphertexts or salts in internal representation, these - * should be word aligned; the functions may assume such alignment. + * should be ARCH_WORD aligned if their size is that of ARCH_WORD or larger, + * 4-byte aligned if they are smaller than ARCH_WORD but are at least 4 bytes, + * or not necessarily aligned otherwise. The functions may assume such + * alignment. */ struct fmt_methods { -/* Initializes the algorithm's internal structures; valid() and split() are - * the only methods that are allowed to be called before a call to init(). - * Note that initializing an algorithm might de-initialize some others (if - * a shared underlying resource is used). */ - void (*init)(void); +/* Initializes the algorithm's internal structures. + * prepare(), valid(), and split() are the only methods that are allowed to be + * called before a call to init(). + * Note that initializing an algorithm might de-initialize some others (if a + * shared underlying resource is used). */ + void (*init)(struct fmt_main *self); + +/* 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 + * /etc/passwd format files) or/and it may also extract and include the + * username, etc. */ + char *(*prepare)(char *fields[10], struct fmt_main *self); -/* Checks if an ASCII ciphertext is valid for this format. Returns zero for - * invalid ciphertexts, or a number of parts the ciphertext should be split +/* Checks if an ASCII ciphertext is valid for this format. Returns zero for + * invalid ciphertexts, or the number of parts the ciphertext should be split * into (up to 9, will usually be 1). */ - int (*valid)(char *ciphertext); + int (*valid)(char *ciphertext, struct fmt_main *self); /* Splits a ciphertext into several pieces and returns the piece with given * index, starting from 0 (will usually return the ciphertext unchanged). @@ -104,7 +122,7 @@ struct fmt_methods { * irrespective of the case of characters (upper/lower/mixed) used in their * encoding, split() must unify the case (e.g., convert to all-lowercase) * and FMT_SPLIT_UNIFIES_CASE must be set. */ - char *(*split)(char *ciphertext, int index); + char *(*split)(char *ciphertext, int index, struct fmt_main *self); /* Converts an ASCII ciphertext to binary, possibly using the salt */ void *(*binary)(char *ciphertext); @@ -198,9 +216,11 @@ extern char *fmt_self_test(struct fmt_ma /* * Default methods. */ -extern void fmt_default_init(void); -extern int fmt_default_valid(char *ciphertext); -extern char *fmt_default_split(char *ciphertext, int index); +extern void fmt_default_init(struct fmt_main *self); +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, + struct fmt_main *self); extern void *fmt_default_binary(char *ciphertext); extern void *fmt_default_salt(char *ciphertext); extern int fmt_default_binary_hash(void *binary); diff -urp john-1.7.9.4/src/loader.c john-1.7.9.4-newform/src/loader.c --- john-1.7.9.4/src/loader.c 2012-01-29 00:48:58 +0000 +++ john-1.7.9.4-newform/src/loader.c 2012-07-13 06:33:19 +0000 @@ -217,11 +217,11 @@ static int ldr_split_line(char **login, struct db_options *options, char *line) { struct fmt_main *alt; - char *uid = NULL, *gid = NULL, *shell = NULL; - int retval; + char *fields[10], *uid, *gid, *shell; + int i, retval; - *login = ldr_get_field(&line); - *ciphertext = ldr_get_field(&line); + fields[0] = *login = ldr_get_field(&line); + fields[1] = *ciphertext = ldr_get_field(&line); /* Check for NIS stuff */ if ((!strcmp(*login, "+") || !strncmp(*login, "+@", 2)) && @@ -255,32 +255,51 @@ static int ldr_split_line(char **login, *login = no_username; } - if (source) strcpy(source, line ? line : ""); - - uid = ldr_get_field(&line); - - if (strlen(uid) == 32) { - char *tmp = *ciphertext; - *ciphertext = uid; - uid = tmp; + if (source) + strcpy(source, line ? line : ""); + if ((options->flags & DB_WORDS) || options->shells->head) { + for (i = 2; i < 10; i++) + fields[i] = ldr_get_field(&line); + } else { + for (i = 2; i < 4; i++) + fields[i] = ldr_get_field(&line); + for (; i < 10; i++) + fields[i] = "/"; + } + + /* /etc/passwd */ + uid = fields[2]; + gid = fields[3]; + *gecos = fields[4]; + *home = fields[5]; + shell = fields[6]; + + if (fields[5][0] != '/' && + ((!strcmp(fields[5], "0") && !strcmp(fields[6], "0")) || + fields[8][0] == '/' || + fields[9][0] == '/')) { + /* /etc/master.passwd */ + *gecos = fields[7]; + *home = fields[8]; + shell = fields[9]; + } else if (fields[3] - fields[2] == 32 + 1) { + /* PWDUMP */ + uid = fields[1]; + *ciphertext = fields[2]; if (!strncmp(*ciphertext, "NO PASSWORD", 11)) *ciphertext = ""; - - if (source) sprintf(source, "%s:%s", uid, line); - } - - if ((options->flags & DB_WORDS) || options->shells->head) { - gid = ldr_get_field(&line); - do { - *gecos = ldr_get_field(&line); - *home = ldr_get_field(&line); - shell = ldr_get_field(&line); - } while (!**gecos && - !strcmp(*home, "0") && !strcmp(shell, "0")); - } else - if (options->groups->head) { - gid = ldr_get_field(&line); + gid = shell = ""; + *gecos = fields[4]; + *home = fields[5]; + + /* Re-introduce the previously removed uid field */ + if (source) { + int shift = strlen(uid); + memmove(source + shift, source, strlen(source) + 1); + memcpy(source, uid, shift); + source[shift] = ':'; + } } if (ldr_check_list(options->users, *login, uid)) return 0; @@ -288,48 +307,60 @@ static int ldr_split_line(char **login, if (ldr_check_shells(options->shells, shell)) return 0; if (*format) { - int valid = (*format)->methods.valid(*ciphertext); - if (!valid) { - alt = fmt_list; - do { - if (alt == *format) - continue; - if (alt->params.flags & FMT_WARNED) - continue; + char *prepared; + int valid; + + prepared = (*format)->methods.prepare(fields, *format); + if (prepared) + valid = (*format)->methods.valid(prepared, *format); + else + valid = 0; + + if (valid) { + *ciphertext = prepared; + return valid; + } + + alt = fmt_list; + do { + if (alt == *format) + continue; + if (alt->params.flags & FMT_WARNED) + continue; #ifdef HAVE_CRYPT - if (alt == &fmt_crypt && + if (alt == &fmt_crypt && #ifdef __sun - strncmp(*ciphertext, "$md5$", 5) && - strncmp(*ciphertext, "$md5,", 5) && + strncmp(*ciphertext, "$md5$", 5) && + strncmp(*ciphertext, "$md5,", 5) && #endif - strncmp(*ciphertext, "$5$", 3) && - strncmp(*ciphertext, "$6$", 3)) - continue; + strncmp(*ciphertext, "$5$", 3) && + strncmp(*ciphertext, "$6$", 3)) + continue; #endif - if (alt->methods.valid(*ciphertext)) { - alt->params.flags |= FMT_WARNED; - fprintf(stderr, - "Warning: only loading hashes " - "of type \"%s\", but also saw " - "type \"%s\"\n" - "Use the " - "\"--format=%s\" option to force " - "loading hashes of that type " - "instead\n", - (*format)->params.label, - alt->params.label, - alt->params.label); - break; - } - } while ((alt = alt->next)); - } - return valid; + prepared = alt->methods.prepare(fields, alt); + if (alt->methods.valid(prepared, alt)) { + alt->params.flags |= FMT_WARNED; + fprintf(stderr, + "Warning: only loading hashes of type " + "\"%s\", but also saw type \"%s\"\n" + "Use the \"--format=%s\" option to force " + "loading hashes of that type instead\n", + (*format)->params.label, + alt->params.label, + alt->params.label); + break; + } + } while ((alt = alt->next)); + + return 0; } retval = -1; if ((alt = fmt_list)) do { + char *prepared; int valid; + #ifdef HAVE_CRYPT /* * Only probe for support by the current system's crypt(3) if this is forced @@ -347,11 +378,18 @@ static int ldr_split_line(char **login, strncmp(*ciphertext, "$6$", 3)) continue; #endif - if (!(valid = alt->methods.valid(*ciphertext))) + + prepared = alt->methods.prepare(fields, alt); + if (!prepared) continue; + valid = alt->methods.valid(prepared, alt); + if (!valid) + continue; + if (retval < 0) { - fmt_init(*format = alt); retval = valid; + *ciphertext = prepared; + fmt_init(*format = alt); #ifdef LDR_WARN_AMBIGUOUS if (!source) /* not --show */ continue; @@ -467,7 +505,7 @@ static void ldr_load_pw_line(struct db_m ldr_init_password_hash(db); for (index = 0; index < count; index++) { - piece = format->methods.split(ciphertext, index); + piece = format->methods.split(ciphertext, index, format); binary = format->methods.binary(piece); pw_hash = db->password_hash_func(binary); @@ -593,9 +631,9 @@ static void ldr_load_pot_line(struct db_ struct db_password *current; ciphertext = ldr_get_field(&line); - if (format->methods.valid(ciphertext) != 1) return; + if (format->methods.valid(ciphertext, format) != 1) return; - ciphertext = format->methods.split(ciphertext, 0); + ciphertext = format->methods.split(ciphertext, 0, format); binary = format->methods.binary(ciphertext); hash = db->password_hash_func(binary); @@ -856,7 +894,7 @@ static void ldr_show_pot_line(struct db_ if (line) { /* If just one format was forced on the command line, insist on it */ if (!fmt_list->next && - !fmt_list->methods.valid(ciphertext)) + !fmt_list->methods.valid(ciphertext, fmt_list)) return; pos = line; @@ -898,7 +936,7 @@ static void ldr_show_pw_line(struct db_m int show; char source[LINE_BUFFER_SIZE]; struct fmt_main *format; - char *(*split)(char *ciphertext, int index); + char *(*split)(char *ciphertext, int index, struct fmt_main *self); int index, count, unify; char *login, *ciphertext, *gecos, *home; char *piece; @@ -933,7 +971,7 @@ static void ldr_show_pw_line(struct db_m } else for (found = pass = 0; pass == 0 || (pass == 1 && found); pass++) for (index = 0; index < count; index++) { - piece = split(ciphertext, index); + piece = split(ciphertext, index, format); if (unify) piece = strcpy(mem_alloc(strlen(piece) + 1), piece); @@ -941,15 +979,16 @@ static void ldr_show_pw_line(struct db_m if ((current = db->cracked_hash[hash])) do { - if (!strcmp(current->ciphertext, piece)) + char *pot = current->ciphertext; + if (!strcmp(pot, piece)) break; /* This extra check, along with ldr_cracked_hash() being case-insensitive, * is only needed for matching some pot file records produced by older * versions of John and contributed patches where split() didn't unify the * case of hex-encoded hashes. */ if (unify && - format->methods.valid(current->ciphertext) == 1 && - !strcmp(split(current->ciphertext, 0), piece)) + format->methods.valid(pot, format) == 1 && + !strcmp(split(pot, 0, format), piece)) break; } while ((current = current->next)); diff -urp john-1.7.9.4/src/trip_fmt.c john-1.7.9.4-newform/src/trip_fmt.c --- john-1.7.9.4/src/trip_fmt.c 2012-01-25 23:57:20 +0000 +++ john-1.7.9.4-newform/src/trip_fmt.c 2012-07-13 02:53:13 +0000 @@ -84,7 +84,7 @@ static unsigned char salt_map[0x100]; struct fmt_main fmt_trip; -static void init(void) +static void init(struct fmt_main *self) { #if !DES_BS char fake_crypt[14]; @@ -147,7 +147,7 @@ static void init(void) } } -static int valid(char *ciphertext) +static int valid(char *ciphertext, struct fmt_main *self) { char *pos; @@ -587,6 +587,7 @@ struct fmt_main fmt_trip = { tests }, { init, + fmt_default_prepare, valid, fmt_default_split, get_binary,