diff -urpN john-1.7.2-orig/src/john.c john-1.7.2/src/john.c --- john-1.7.2-orig/src/john.c 2006-05-08 14:48:48.000000000 +0000 +++ john-1.7.2/src/john.c 2008-06-19 12:01:26.000000000 +0000 @@ -36,7 +36,7 @@ extern int CPU_detect(void); #endif -extern struct fmt_main fmt_DES, fmt_BSDI, fmt_MD5, fmt_BF; +extern struct fmt_main fmt_DES, fmt_BSDI, fmt_MD5, fmt_BF, fmt_NS; extern struct fmt_main fmt_AFS, fmt_LM; extern int unshadow(int argc, char **argv); @@ -64,6 +64,7 @@ static void john_register_all(void) john_register_one(&fmt_BF); john_register_one(&fmt_AFS); john_register_one(&fmt_LM); + john_register_one(&fmt_NS); if (!fmt_list) { fprintf(stderr, "Unknown ciphertext format name requested\n"); diff -urpN john-1.7.2-orig/src/Makefile john-1.7.2/src/Makefile --- john-1.7.2-orig/src/Makefile 2006-05-15 16:38:00.000000000 +0000 +++ john-1.7.2/src/Makefile 2008-06-20 10:31:12.000000000 +0000 @@ -17,7 +17,7 @@ NULL = /dev/null CPPFLAGS = -E CFLAGS = -c -Wall -O2 -fomit-frame-pointer ASFLAGS = -c -LDFLAGS = -s +LDFLAGS = -s OPT_NORMAL = -funroll-loops OPT_INLINE = -finline-functions @@ -34,7 +34,9 @@ JOHN_OBJS_MINIMAL = \ recovery.o rpp.o rules.o signals.o single.o status.o tty.o wordlist.o \ unshadow.o \ unafs.o \ - unique.o + unique.o \ + md5.o \ + NS_fmt.o JOHN_OBJS_ORIG = \ $(JOHN_OBJS_MINIMAL) \ @@ -60,7 +62,7 @@ BENCH_BF_OBJS_DEPEND = \ BENCH_OBJS = \ $(BENCH_DES_OBJS_DEPEND) \ - DES_bs.o $(BENCH_DES_BS_OBJS_DEPEND) \ + DES_bs.o $(BENCH_DES_BS_OBJS_DEPEND) NS_fmt.o \ $(BENCH_MD5_OBJS_DEPEND) \ BF_fmt.o $(BENCH_BF_OBJS_DEPEND) \ bench.o best.o common.o config.o formats.o math.o memory.o miscnl.o \ diff -urpN john-1.7.2-orig/src/md5.c john-1.7.2/src/md5.c --- john-1.7.2-orig/src/md5.c 1970-01-01 00:00:00.000000000 +0000 +++ john-1.7.2/src/md5.c 2006-11-15 06:51:55.000000000 +0000 @@ -0,0 +1,275 @@ +/* + * This is an OpenSSL-compatible implementation of the RSA Data Security, + * Inc. MD5 Message-Digest Algorithm (RFC 1321). + * + * Written by Solar Designer in 2001, and placed + * in the public domain. There's absolutely no warranty. + * + * This differs from Colin Plumb's older public domain implementation in + * that no 32-bit integer data type is required, there's no compile-time + * endianness configuration, and the function prototypes match OpenSSL's. + * The primary goals are portability and ease of use. + * + * This implementation is meant to be fast, but not as fast as possible. + * Some known optimizations are not included to reduce source code size + * and avoid compile-time configuration. + */ + +#ifndef HAVE_OPENSSL + +#include + +#include "md5.h" + +/* + * The basic MD5 functions. + * + * F and G are optimized compared to their RFC 1321 definitions for + * architectures that lack an AND-NOT instruction, just like in Colin Plumb's + * implementation. + */ +#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) +#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y)))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | ~(z))) + +/* + * The MD5 transformation for all four rounds. + */ +#define STEP(f, a, b, c, d, x, t, s) \ + (a) += f((b), (c), (d)) + (x) + (t); \ + (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \ + (a) += (b); + +/* + * SET reads 4 input bytes in little-endian byte order and stores them + * in a properly aligned word in host byte order. + * + * The check for little-endian architectures that tolerate unaligned + * memory accesses is just an optimization. Nothing will break if it + * doesn't work. + */ +#if defined(__i386__) || defined(__x86_64__) || defined(__vax__) +#define SET(n) \ + (*(MD5_u32plus *)&ptr[(n) * 4]) +#define GET(n) \ + SET(n) +#else +#define SET(n) \ + (ctx->block[(n)] = \ + (MD5_u32plus)ptr[(n) * 4] | \ + ((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \ + ((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \ + ((MD5_u32plus)ptr[(n) * 4 + 3] << 24)) +#define GET(n) \ + (ctx->block[(n)]) +#endif + +/* + * This processes one or more 64-byte data blocks, but does NOT update + * the bit counters. There are no alignment requirements. + */ +static void *body(MD5_CTX *ctx, void *data, unsigned long size) +{ + unsigned char *ptr; + MD5_u32plus a, b, c, d; + MD5_u32plus saved_a, saved_b, saved_c, saved_d; + + ptr = data; + + a = ctx->a; + b = ctx->b; + c = ctx->c; + d = ctx->d; + + do { + saved_a = a; + saved_b = b; + saved_c = c; + saved_d = d; + +/* Round 1 */ + STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7) + STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12) + STEP(F, c, d, a, b, SET(2), 0x242070db, 17) + STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22) + STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7) + STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12) + STEP(F, c, d, a, b, SET(6), 0xa8304613, 17) + STEP(F, b, c, d, a, SET(7), 0xfd469501, 22) + STEP(F, a, b, c, d, SET(8), 0x698098d8, 7) + STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12) + STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17) + STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22) + STEP(F, a, b, c, d, SET(12), 0x6b901122, 7) + STEP(F, d, a, b, c, SET(13), 0xfd987193, 12) + STEP(F, c, d, a, b, SET(14), 0xa679438e, 17) + STEP(F, b, c, d, a, SET(15), 0x49b40821, 22) + +/* Round 2 */ + STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5) + STEP(G, d, a, b, c, GET(6), 0xc040b340, 9) + STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14) + STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20) + STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5) + STEP(G, d, a, b, c, GET(10), 0x02441453, 9) + STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14) + STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20) + STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5) + STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9) + STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14) + STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20) + STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5) + STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9) + STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14) + STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20) + +/* Round 3 */ + STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4) + STEP(H, d, a, b, c, GET(8), 0x8771f681, 11) + STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16) + STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23) + STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4) + STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11) + STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16) + STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23) + STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4) + STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11) + STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16) + STEP(H, b, c, d, a, GET(6), 0x04881d05, 23) + STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4) + STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11) + STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16) + STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23) + +/* Round 4 */ + STEP(I, a, b, c, d, GET(0), 0xf4292244, 6) + STEP(I, d, a, b, c, GET(7), 0x432aff97, 10) + STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15) + STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21) + STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6) + STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10) + STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15) + STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21) + STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6) + STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10) + STEP(I, c, d, a, b, GET(6), 0xa3014314, 15) + STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21) + STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6) + STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10) + STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15) + STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21) + + a += saved_a; + b += saved_b; + c += saved_c; + d += saved_d; + + ptr += 64; + } while (size -= 64); + + ctx->a = a; + ctx->b = b; + ctx->c = c; + ctx->d = d; + + return ptr; +} + +void MD5_Init(MD5_CTX *ctx) +{ + ctx->a = 0x67452301; + ctx->b = 0xefcdab89; + ctx->c = 0x98badcfe; + ctx->d = 0x10325476; + + ctx->lo = 0; + ctx->hi = 0; +} + +void MD5_Update(MD5_CTX *ctx, void *data, unsigned long size) +{ + MD5_u32plus saved_lo; + unsigned long used, free; + + saved_lo = ctx->lo; + if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo) + ctx->hi++; + ctx->hi += size >> 29; + + used = saved_lo & 0x3f; + + if (used) { + free = 64 - used; + + if (size < free) { + memcpy(&ctx->buffer[used], data, size); + return; + } + + memcpy(&ctx->buffer[used], data, free); + data = (unsigned char *)data + free; + size -= free; + body(ctx, ctx->buffer, 64); + } + + if (size >= 64) { + data = body(ctx, data, size & ~(unsigned long)0x3f); + size &= 0x3f; + } + + memcpy(ctx->buffer, data, size); +} + +void MD5_Final(unsigned char *result, MD5_CTX *ctx) +{ + unsigned long used, free; + + used = ctx->lo & 0x3f; + + ctx->buffer[used++] = 0x80; + + free = 64 - used; + + if (free < 8) { + memset(&ctx->buffer[used], 0, free); + body(ctx, ctx->buffer, 64); + used = 0; + free = 64; + } + + memset(&ctx->buffer[used], 0, free - 8); + + ctx->lo <<= 3; + ctx->buffer[56] = ctx->lo; + ctx->buffer[57] = ctx->lo >> 8; + ctx->buffer[58] = ctx->lo >> 16; + ctx->buffer[59] = ctx->lo >> 24; + ctx->buffer[60] = ctx->hi; + ctx->buffer[61] = ctx->hi >> 8; + ctx->buffer[62] = ctx->hi >> 16; + ctx->buffer[63] = ctx->hi >> 24; + + body(ctx, ctx->buffer, 64); + + result[0] = ctx->a; + result[1] = ctx->a >> 8; + result[2] = ctx->a >> 16; + result[3] = ctx->a >> 24; + result[4] = ctx->b; + result[5] = ctx->b >> 8; + result[6] = ctx->b >> 16; + result[7] = ctx->b >> 24; + result[8] = ctx->c; + result[9] = ctx->c >> 8; + result[10] = ctx->c >> 16; + result[11] = ctx->c >> 24; + result[12] = ctx->d; + result[13] = ctx->d >> 8; + result[14] = ctx->d >> 16; + result[15] = ctx->d >> 24; + + memset(ctx, 0, sizeof(*ctx)); +} + +#endif Binary files john-1.7.2-orig/src/.MD5_fmt.c.swp and john-1.7.2/src/.MD5_fmt.c.swp differ diff -urpN john-1.7.2-orig/src/md5.h john-1.7.2/src/md5.h --- john-1.7.2-orig/src/md5.h 1970-01-01 00:00:00.000000000 +0000 +++ john-1.7.2/src/md5.h 2006-10-23 13:13:35.000000000 +0000 @@ -0,0 +1,30 @@ +/* + * This is an OpenSSL-compatible implementation of the RSA Data Security, + * Inc. MD5 Message-Digest Algorithm (RFC 1321). + * + * Written by Solar Designer in 2001, and placed + * in the public domain. There's absolutely no warranty. + * + * See md5.c for more information. + */ + +#ifdef HAVE_OPENSSL +#include +#elif !defined(_MD5_H) +#define _MD5_H + +/* Any 32-bit or wider unsigned integer data type will do */ +typedef unsigned int MD5_u32plus; + +typedef struct { + MD5_u32plus lo, hi; + MD5_u32plus a, b, c, d; + unsigned char buffer[64]; + MD5_u32plus block[16]; +} MD5_CTX; + +extern void MD5_Init(MD5_CTX *ctx); +extern void MD5_Update(MD5_CTX *ctx, void *data, unsigned long size); +extern void MD5_Final(unsigned char *result, MD5_CTX *ctx); + +#endif diff -urpN john-1.7.2-orig/src/NS_fmt.c john-1.7.2/src/NS_fmt.c --- john-1.7.2-orig/src/NS_fmt.c 1970-01-01 00:00:00.000000000 +0000 +++ john-1.7.2/src/NS_fmt.c 2008-06-23 10:58:42.000000000 +0000 @@ -0,0 +1,289 @@ +/* + * NS_fmt.c + * Written by Samuel Monux in 2008, and placed + * in the public domain. There's absolutely no warranty. + * + * Netscreen OS password module. Passwords must be in this format + * :$ + * + * which appear in Netscreen config file + * + * set admin name "" + * set admin password "" + * + * username is needed because is used as part of the salt. + * + * Cryptedpass is generated this way (pseudocode): + * + * b64 = array([A-Za-z0-9+/]) + * md5_binary = MD5(":Administration Tools:") + * + * md5_ascii = "" + * for every 16bits word "w" in md5_binary: + * append(md5_ascii, b64[ w >> 12 & 0xf ]) + * append(md5_ascii, b64[ w >> 6 & 0x3f ]) + * append(md5_ascii, b64[ w & 0x3f ]) + * + * ciphertext = md5_ascii + * for every c,p ("nrcstn", [0, 6, 12, 17, 23, 29]): + * interpolate character "c" in position "p" in ciphertext + * + */ + +#include + +#include "arch.h" +#include "misc.h" +#include "md5.h" +#include "common.h" +#include "formats.h" + +#define FORMAT_LABEL "md5ns" +#define FORMAT_NAME "Netscreen MD5" +#define NS_ALGORITHM_NAME "NS MD5" + +#define BENCHMARK_COMMENT "" +#define BENCHMARK_LENGTH -1 + +#define PLAINTEXT_LENGTH 15 +#define CIPHERTEXT_LENGTH 50 + +#define BINARY_SIZE 16 +#define SALT_SIZE 32 + +#define MIN_KEYS_PER_CRYPT 1 +#define MAX_KEYS_PER_CRYPT 1 + + +static struct fmt_tests tests[] = { + {"admin$nMjFM0rdC9iOc+xIFsGEm3LtAeGZhn", "password"}, + {"a$nMf9FkrCIgHGccRAxsBAwxBtDtPHfn", "netscreen"}, + {NULL} +}; + +static unsigned short e64toshort[256]; + +#define ADM_LEN 22 +static int salt_len, key_len; +static char cipher_salt[ SALT_SIZE ]; +static char cipher_key[ PLAINTEXT_LENGTH + 1 ]; +static char *adm = ":Administration Tools:"; +static char tocipher[ SALT_SIZE + ADM_LEN + PLAINTEXT_LENGTH ]; +static MD5_u32plus crypted[4]; + + +static void NS_init() +{ + int i; + static char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + char *pos; + for (pos = b64, i = 0 ; *pos != 0 ; pos++, i++) + e64toshort[(int)*pos] = i; +} + +static int NS_valid(char *ciphertext) +{ + char *password; + static char *netscreen = "nrcstn" ; + static int p[] = { 0, 6, 12, 17, 23, 29 }; + int i; + + password = ciphertext; + + while ((*password != '$') && (*password != '\0' )) + password++; + if (*password == '\0') return 0; + password++; + + if (strlen(password) != 30) return 0; + for (i = 0; i < 6 ; i++) + if (netscreen[i] != password[p[i]]) return 0; + + for (i = 0; i < 30 ; i++) { + char c = password[i]; + if (((c >= 'A') && ( c <= 'Z')) || + ((c >= 'a') && ( c <= 'z')) || + ((c >= '0') && ( c <= '9')) || + (c == '+') || ( c == '/')) + continue; + return 0; + } + return 1; +} + +static MD5_u32plus *NS_std_get_binary(char *ciphertext) +{ + static union { + MD5_u32plus w[4]; + char b[16]; + } out; + char unscrambled[24]; + int i; + MD5_u32plus a, b, c; + MD5_u32plus d, e, f; + char *pos; +#if ARCH_LITTLE_ENDIAN + MD5_u32plus temp; +#endif + + pos = ciphertext; + while (*pos++ != '$'); + + memcpy(unscrambled, pos + 1, 6 ); + memcpy(unscrambled + 5, pos + 7, 6 ); + memcpy(unscrambled + 10, pos + 13, 5 ); + memcpy(unscrambled + 14, pos + 18, 6 ); + memcpy(unscrambled + 19, pos + 24, 5 ); + + for ( i = 0 ; i < 4 ; i++ ) { + a = e64toshort[ARCH_INDEX(unscrambled[6*i])]; + b = e64toshort[ARCH_INDEX(unscrambled[6*i + 1 ])]; + c = e64toshort[ARCH_INDEX(unscrambled[6*i + 2 ])]; + d = e64toshort[ARCH_INDEX(unscrambled[6*i + 3 ])]; + e = e64toshort[ARCH_INDEX(unscrambled[6*i + 4 ])]; + f = e64toshort[ARCH_INDEX(unscrambled[6*i + 5 ])]; +#if ARCH_LITTLE_ENDIAN + temp = (((a << 12) | (b << 6) | (c)) << 16) | + ((d << 12) | (e << 6) | (f)); + out.w[i] = ((temp << 24) & 0xff000000 ) | + ((temp << 8) & 0x00ff0000 ) | + ((temp >> 8) & 0x0000ff00 ) | + ((temp >> 24) & 0x000000ff ); +#else + out.w[i] = (((a << 12) | (b << 6) | (c)) << 16) | + ((d << 12) | (e << 6) | (f)); +#endif + } + + return out.w; + +} + +static int binary_hash_0(void *binary) +{ + return *(unsigned int *)binary &0xf; +} + +static int binary_hash_1(void *binary) +{ + return *(unsigned int *)binary &0xff; +} + +static int binary_hash_2(void *binary) +{ + return *(unsigned int *)binary &0xfff; +} + +static int get_hash_0(int index) +{ + return ((unsigned int *)crypted)[index] & 0xf; +} + +static int get_hash_1(int index) +{ + return ((unsigned int *)crypted)[index] & 0xff; +} + +static int get_hash_2(int index) +{ + return ((unsigned int *)crypted)[index] & 0xfff; +} + +char *NS_std_get_salt(char *ciphertext) +{ + static char out[SALT_SIZE + 1]; + char *ipos, *opos; + + ipos = ciphertext; + opos = out; + while (*ipos != '$') *opos++ = *ipos++; + *opos = '\0'; + + return out; +} + +void NS_std_set_salt (void *salt) +{ + salt_len = strlen((char *) salt); + memcpy(cipher_salt, salt , salt_len); +} + +static void NS_set_key(char *key, int index) +{ + key_len = strlen((char *) key); + memcpy(cipher_key, key, strlen(key) + 1 ); +} + +static char *NS_get_key() +{ + return cipher_key; +} + +static void NS_std_crypt() +{ + MD5_CTX ctx; + MD5_Init(&ctx); + memcpy(tocipher, cipher_salt, salt_len); + memcpy(tocipher + salt_len, adm, ADM_LEN); + memcpy(tocipher + salt_len + ADM_LEN, cipher_key, key_len); + MD5_Update(&ctx , tocipher, salt_len + ADM_LEN + key_len); + MD5_Final((void*)crypted, &ctx); +} + +static int NS_cmp_all(void *binary, int index) +{ + int i; + for ( i = 0 ; i < 4 ; i++ ) { + if(((MD5_u32plus *)binary)[i]!=((MD5_u32plus*)crypted)[i]) { + return 0; + } + } + return 1; +} + +static int NS_cmp_exact(char *source, int index) +{ + return 1; +} + +struct fmt_main fmt_NS = { + { + FORMAT_LABEL, + FORMAT_NAME, + NS_ALGORITHM_NAME, + BENCHMARK_COMMENT, + BENCHMARK_LENGTH, + PLAINTEXT_LENGTH, + BINARY_SIZE, + SALT_SIZE, + MIN_KEYS_PER_CRYPT, + MAX_KEYS_PER_CRYPT, + FMT_CASE | FMT_8_BIT, + tests + }, { + NS_init, + NS_valid, + fmt_default_split, + (void *(*)(char *))NS_std_get_binary, + (void *(*)(char *))NS_std_get_salt, + { + binary_hash_0, + binary_hash_1, + binary_hash_2 + }, + fmt_default_salt_hash, + NS_std_set_salt, + NS_set_key, + NS_get_key, + fmt_default_clear_keys, + NS_std_crypt, + { + get_hash_0, + get_hash_1, + get_hash_2 + }, + NS_cmp_all, + NS_cmp_all, + NS_cmp_exact + } +}; Binary files john-1.7.2-orig/src/.NS_fmt.c.swp and john-1.7.2/src/.NS_fmt.c.swp differ diff -urpN john-1.7.2-orig/src/options.c john-1.7.2/src/options.c --- john-1.7.2-orig/src/options.c 2006-01-09 14:35:00.000000000 +0000 +++ john-1.7.2/src/options.c 2008-06-23 10:08:05.000000000 +0000 @@ -101,7 +101,7 @@ static struct opt_entry opt_list[] = { "--salts=[-]COUNT load salts with[out] at least COUNT passwords " \ "only\n" \ "--format=NAME force ciphertext format NAME: " \ - "DES/BSDI/MD5/BF/AFS/LM\n" \ + "DES/BSDI/MD5/BF/AFS/LM/md5ns\n" \ "--save-memory=LEVEL enable memory saving, at LEVEL 1..3\n" void opt_init(char *name, int argc, char **argv)