diff -ruN src/BFEgg_fmt.c src-patched/BFEgg_fmt.c --- src/BFEgg_fmt.c 1969-12-31 19:00:00.000000000 -0500 +++ src-patched/BFEgg_fmt.c 2006-02-18 17:25:21.000000000 -0500 @@ -0,0 +1,124 @@ +/* + * This file is part of Eggdrop blowfish patch for John The Ripper. + * Copyright (c) 2002 by Sun-Zero + * This is a free software distributable under terms of the GNU GPL. + */ + +#include + +#include "misc.h" +#include "formats.h" +#include "common.h" +#include "blowfish.c" + +#define FORMAT_LABEL "bfegg" +#define FORMAT_NAME "Eggdrop" +#define ALG_NAME "blowfish" + +#define BENCHMARK_COMMENT "" +#define BENCHMARK_LENGTH -1 + +#define PLAINTEXT_LENGTH 31 +#define CIPHERTEXT_LENGTH 33 + +#define BINARY_SIZE 13 +#define SALT_SIZE 0 + +#define MIN_KEYS_PER_CRYPT 1 +#define MAX_KEYS_PER_CRYPT 1 + +static struct fmt_tests tests[] = { + {"+9F93o1OxwgK1", "123456"}, + {"+C/.8o.Wuph9.", "qwerty"}, + {"+EEHgy/MBLDd0", "walkman"}, + {"+vPBrs07OTXE/", "tesztuser"}, + {"+zIvO/1nDsd9.", "654321"}, + {NULL} +}; + +int zerolengthkey = 0; + +static char crypt_key[BINARY_SIZE]; +static char saved_key[PLAINTEXT_LENGTH + 1]; + +static int valid(char *ciphertext) { + if (strncmp(ciphertext, "+", 1) != 0) return 0; + if (strlen(ciphertext) != 13) return 0; + + return 1; +} + +void init() { + blowfish_first_init(); +} + + +static void set_key(char *key, int index) { + strnzcpy(saved_key, key, PLAINTEXT_LENGTH+1); +} + +static char *get_key(int index) { + return saved_key; +} + +static int cmp_all(void *binary, int index) { + if (zerolengthkey) return 0; + return !memcmp(binary, crypt_key, BINARY_SIZE); +} + +static int cmp_exact(char *source, int index) { + return 1; +} + +static void set_salt(void *salt) { } + +static void crypt_all(int count) { + if (saved_key[0] == '\0') { + zerolengthkey = 1; + } else { + zerolengthkey = 0; + blowfish_encrypt_pass(saved_key, crypt_key); + } +} + +struct fmt_main fmt_BFEgg = { + { + FORMAT_LABEL, + FORMAT_NAME, + ALG_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 + }, { + init, + valid, + fmt_default_split, + fmt_default_binary, + fmt_default_salt, + { + fmt_default_binary_hash, + fmt_default_binary_hash, + fmt_default_binary_hash, + }, + fmt_default_salt_hash, + set_salt, + set_key, + get_key, + fmt_default_clear_keys, + crypt_all, + { + fmt_default_get_hash, + fmt_default_get_hash, + fmt_default_get_hash, + }, + cmp_all, + cmp_all, + cmp_exact + } +}; \ No newline at end of file diff -ruN src/DOMINOSEC_fmt.c src-patched/DOMINOSEC_fmt.c --- src/DOMINOSEC_fmt.c 1969-12-31 19:00:00.000000000 -0500 +++ src-patched/DOMINOSEC_fmt.c 2006-02-18 17:25:21.000000000 -0500 @@ -0,0 +1,456 @@ +/* + * DOMINOSEC_fmt.c (version 3) + * + * Notes/Domino More Secure Internet Password module for Solar Designer's JtR + * by regenrecht@o2.pl, Dec 2005. + * Algorithm discovery by regenrecht@o2.pl, bartavelle@bandecon.com. + * + * Short description. + * 1. Make 128bit digest of key. (128/8=16 bytes) + * 2. Do bin2hex() of key digest and put braces around it. (16*2+2=34 bytes) + * 3. Concat output of previous step to 5 bytes of salt. (5+34=39 bytes) + * 4. Make 128bit digest of first 34 bytes (out of 39 bytes). (128/8=16 bytes) + * 5. Compare first 10 bytes (out of 16) to check if the key was correct. + * + * Password file should have form of: + * TomaszJegerman:(GKjXibCW2Ml6juyQHUoP) + * RubasznyJan:(GrixoFHOckC/2CnHrHtM) + */ + +#include +#include + +#include "misc.h" +#include "formats.h" +#include "common.h" + +#define FORMAT_LABEL "dominosec" +#define FORMAT_NAME "More Secure Internet Password" +#define ALGORITHM_NAME "RSA MD defined by BSAFE 1.x" + +#define BENCHMARK_COMMENT "" +#define BENCHMARK_LENGTH -1 + +#define PLAINTEXT_LENGTH 64 +#define CIPHERTEXT_LENGTH 22 +#define BINARY_SIZE 9 /* oh, well :P */ +#define SALT_SIZE 5 + +#define DIGEST_SIZE 16 +#define BINARY_BUFFER_SIZE (DIGEST_SIZE-SALT_SIZE) +#define ASCII_DIGEST_LENGTH (DIGEST_SIZE*2) +#define MIN_KEYS_PER_CRYPT 1 +#define MAX_KEYS_PER_CRYPT 1 + +static unsigned char key_digest[DIGEST_SIZE]; +static char saved_key[PLAINTEXT_LENGTH+1]; +static unsigned char crypted_key[DIGEST_SIZE]; +static unsigned char salt_and_digest[SALT_SIZE+1+ASCII_DIGEST_LENGTH+1+1] = + "saalt(................................)"; +static unsigned int saved_key_len; + +static const char *hex_table[] = { + "00", "01", "02", "03", "04", "05", "06", "07", + "08", "09", "0A", "0B", "0C", "0D", "0E", "0F", + "10", "11", "12", "13", "14", "15", "16", "17", + "18", "19", "1A", "1B", "1C", "1D", "1E", "1F", + "20", "21", "22", "23", "24", "25", "26", "27", + "28", "29", "2A", "2B", "2C", "2D", "2E", "2F", + "30", "31", "32", "33", "34", "35", "36", "37", + "38", "39", "3A", "3B", "3C", "3D", "3E", "3F", + "40", "41", "42", "43", "44", "45", "46", "47", + "48", "49", "4A", "4B", "4C", "4D", "4E", "4F", + "50", "51", "52", "53", "54", "55", "56", "57", + "58", "59", "5A", "5B", "5C", "5D", "5E", "5F", + "60", "61", "62", "63", "64", "65", "66", "67", + "68", "69", "6A", "6B", "6C", "6D", "6E", "6F", + "70", "71", "72", "73", "74", "75", "76", "77", + "78", "79", "7A", "7B", "7C", "7D", "7E", "7F", + "80", "81", "82", "83", "84", "85", "86", "87", + "88", "89", "8A", "8B", "8C", "8D", "8E", "8F", + "90", "91", "92", "93", "94", "95", "96", "97", + "98", "99", "9A", "9B", "9C", "9D", "9E", "9F", + "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", + "A8", "A9", "AA", "AB", "AC", "AD", "AE", "AF", + "B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", + "B8", "B9", "BA", "BB", "BC", "BD", "BE", "BF", + "C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", + "C8", "C9", "CA", "CB", "CC", "CD", "CE", "CF", + "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", + "D8", "D9", "DA", "DB", "DC", "DD", "DE", "DF", + "E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7", + "E8", "E9", "EA", "EB", "EC", "ED", "EE", "EF", + "F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", + "F8", "F9", "FA", "FB", "FC", "FD", "FE", "FF" +}; + +static const char lotus_magic_table[] = { + 0xbd, 0x56, 0xea, 0xf2, 0xa2, 0xf1, 0xac, 0x2a, + 0xb0, 0x93, 0xd1, 0x9c, 0x1b, 0x33, 0xfd, 0xd0, + 0x30, 0x04, 0xb6, 0xdc, 0x7d, 0xdf, 0x32, 0x4b, + 0xf7, 0xcb, 0x45, 0x9b, 0x31, 0xbb, 0x21, 0x5a, + 0x41, 0x9f, 0xe1, 0xd9, 0x4a, 0x4d, 0x9e, 0xda, + 0xa0, 0x68, 0x2c, 0xc3, 0x27, 0x5f, 0x80, 0x36, + 0x3e, 0xee, 0xfb, 0x95, 0x1a, 0xfe, 0xce, 0xa8, + 0x34, 0xa9, 0x13, 0xf0, 0xa6, 0x3f, 0xd8, 0x0c, + 0x78, 0x24, 0xaf, 0x23, 0x52, 0xc1, 0x67, 0x17, + 0xf5, 0x66, 0x90, 0xe7, 0xe8, 0x07, 0xb8, 0x60, + 0x48, 0xe6, 0x1e, 0x53, 0xf3, 0x92, 0xa4, 0x72, + 0x8c, 0x08, 0x15, 0x6e, 0x86, 0x00, 0x84, 0xfa, + 0xf4, 0x7f, 0x8a, 0x42, 0x19, 0xf6, 0xdb, 0xcd, + 0x14, 0x8d, 0x50, 0x12, 0xba, 0x3c, 0x06, 0x4e, + 0xec, 0xb3, 0x35, 0x11, 0xa1, 0x88, 0x8e, 0x2b, + 0x94, 0x99, 0xb7, 0x71, 0x74, 0xd3, 0xe4, 0xbf, + 0x3a, 0xde, 0x96, 0x0e, 0xbc, 0x0a, 0xed, 0x77, + 0xfc, 0x37, 0x6b, 0x03, 0x79, 0x89, 0x62, 0xc6, + 0xd7, 0xc0, 0xd2, 0x7c, 0x6a, 0x8b, 0x22, 0xa3, + 0x5b, 0x05, 0x5d, 0x02, 0x75, 0xd5, 0x61, 0xe3, + 0x18, 0x8f, 0x55, 0x51, 0xad, 0x1f, 0x0b, 0x5e, + 0x85, 0xe5, 0xc2, 0x57, 0x63, 0xca, 0x3d, 0x6c, + 0xb4, 0xc5, 0xcc, 0x70, 0xb2, 0x91, 0x59, 0x0d, + 0x47, 0x20, 0xc8, 0x4f, 0x58, 0xe0, 0x01, 0xe2, + 0x16, 0x38, 0xc4, 0x6f, 0x3b, 0x0f, 0x65, 0x46, + 0xbe, 0x7e, 0x2d, 0x7b, 0x82, 0xf9, 0x40, 0xb5, + 0x1d, 0x73, 0xf8, 0xeb, 0x26, 0xc7, 0x87, 0x97, + 0x25, 0x54, 0xb1, 0x28, 0xaa, 0x98, 0x9d, 0xa5, + 0x64, 0x6d, 0x7a, 0xd4, 0x10, 0x81, 0x44, 0xef, + 0x49, 0xd6, 0xae, 0x2e, 0xdd, 0x76, 0x5c, 0x2f, + 0xa7, 0x1c, 0xc9, 0x09, 0x69, 0x9a, 0x83, 0xcf, + 0x29, 0x39, 0xb9, 0xe9, 0x4c, 0xff, 0x43, 0xab, + /* double power! */ + 0xbd, 0x56, 0xea, 0xf2, 0xa2, 0xf1, 0xac, 0x2a, + 0xb0, 0x93, 0xd1, 0x9c, 0x1b, 0x33, 0xfd, 0xd0, + 0x30, 0x04, 0xb6, 0xdc, 0x7d, 0xdf, 0x32, 0x4b, + 0xf7, 0xcb, 0x45, 0x9b, 0x31, 0xbb, 0x21, 0x5a, + 0x41, 0x9f, 0xe1, 0xd9, 0x4a, 0x4d, 0x9e, 0xda, + 0xa0, 0x68, 0x2c, 0xc3, 0x27, 0x5f, 0x80, 0x36, + 0x3e, 0xee, 0xfb, 0x95, 0x1a, 0xfe, 0xce, 0xa8, + 0x34, 0xa9, 0x13, 0xf0, 0xa6, 0x3f, 0xd8, 0x0c, + 0x78, 0x24, 0xaf, 0x23, 0x52, 0xc1, 0x67, 0x17, + 0xf5, 0x66, 0x90, 0xe7, 0xe8, 0x07, 0xb8, 0x60, + 0x48, 0xe6, 0x1e, 0x53, 0xf3, 0x92, 0xa4, 0x72, + 0x8c, 0x08, 0x15, 0x6e, 0x86, 0x00, 0x84, 0xfa, + 0xf4, 0x7f, 0x8a, 0x42, 0x19, 0xf6, 0xdb, 0xcd, + 0x14, 0x8d, 0x50, 0x12, 0xba, 0x3c, 0x06, 0x4e, + 0xec, 0xb3, 0x35, 0x11, 0xa1, 0x88, 0x8e, 0x2b, + 0x94, 0x99, 0xb7, 0x71, 0x74, 0xd3, 0xe4, 0xbf, + 0x3a, 0xde, 0x96, 0x0e, 0xbc, 0x0a, 0xed, 0x77, + 0xfc, 0x37, 0x6b, 0x03, 0x79, 0x89, 0x62, 0xc6, + 0xd7, 0xc0, 0xd2, 0x7c, 0x6a, 0x8b, 0x22, 0xa3, + 0x5b, 0x05, 0x5d, 0x02, 0x75, 0xd5, 0x61, 0xe3, + 0x18, 0x8f, 0x55, 0x51, 0xad, 0x1f, 0x0b, 0x5e, + 0x85, 0xe5, 0xc2, 0x57, 0x63, 0xca, 0x3d, 0x6c, + 0xb4, 0xc5, 0xcc, 0x70, 0xb2, 0x91, 0x59, 0x0d, + 0x47, 0x20, 0xc8, 0x4f, 0x58, 0xe0, 0x01, 0xe2, + 0x16, 0x38, 0xc4, 0x6f, 0x3b, 0x0f, 0x65, 0x46, + 0xbe, 0x7e, 0x2d, 0x7b, 0x82, 0xf9, 0x40, 0xb5, + 0x1d, 0x73, 0xf8, 0xeb, 0x26, 0xc7, 0x87, 0x97, + 0x25, 0x54, 0xb1, 0x28, 0xaa, 0x98, 0x9d, 0xa5, + 0x64, 0x6d, 0x7a, 0xd4, 0x10, 0x81, 0x44, 0xef, + 0x49, 0xd6, 0xae, 0x2e, 0xdd, 0x76, 0x5c, 0x2f, + 0xa7, 0x1c, 0xc9, 0x09, 0x69, 0x9a, 0x83, 0xcf, + 0x29, 0x39, 0xb9, 0xe9, 0x4c, 0xff, 0x43, 0xab, +}; + +static struct fmt_tests dominosec_tests[] = { + {"(GVMroLzc50YK/Yd+L8KH)", ""}, + {"(GqnUDNNGNUz5HRoelmLU)", "x"}, + {"(GNBpcGJRYpBe9orUOpmZ)", "dupaaa123"}, + {"(G0xjUQzdKxvHpUYqo5hU)", "koziolekmatolek"}, + {"(G+dfECo845XxUw+nFVYD)", "szesnascieznakow"}, + {"(GowT5I2hVHZpRWpvGmux)", "terazjakiesdwadziesciacos"}, + {"(Gq2bAtpguiTSSycy6dhu)", "trzydziescidwamozesieudaojnieuda"}, + {"(G82TtgNcqcHGkpEo7wQp)", "looongrandominputdataforfunbutnotonlyoi!"}, + {NULL} +}; + +struct cipher_binary_struct { + unsigned char salt[SALT_SIZE]; + unsigned char hash[BINARY_BUFFER_SIZE]; +} cipher_binary; + +static void mdtransform(unsigned char state[16], unsigned char checksum[16], unsigned char block[16]) +{ + unsigned char x[48]; + unsigned int t = 0; + unsigned int i,j; + unsigned char * pt; + unsigned char c; + + memcpy(x, state, 16); + memcpy(x+16, block, 16); + + for(i=0;i<16;i++) + x[i+32] = state[i] ^ block[i]; + + for (i = 0; i < 18; ++i) + { + pt = (unsigned char*)&x; + for (j = 48; j > 0; j--) + { + *pt ^= lotus_magic_table[j+t]; + t = *pt; + pt++; + } + } + + memcpy(state, x, 16); + + t = checksum[15]; + for (i = 0; i < 16; i++) + { + c = lotus_magic_table[block[i]^t]; + checksum[i] ^= c; + t = checksum[i]; + } +} + +static void mdtransform_norecalc(unsigned char state[16], unsigned char block[16]) +{ + unsigned char x[48], *pt; + unsigned int t = 0; + unsigned int i,j; + + memcpy(x, state, 16); + memcpy(x+16, block, 16); + + for(i=0;i<16;i++) + x[i+32] = state[i] ^ block[i]; + + for(i = 0; i < 18; ++i) + { + pt = (unsigned char*)&x; + for (j = 48; j > 0; j--) + { + *pt ^= lotus_magic_table[j+t]; + t = *pt; + pt++; + } + } + + memcpy(state, x, 16); +} + +static void domino_big_md(unsigned char * saved_key, int size, unsigned char * crypt_key) +{ + unsigned char state[16] = {0}; + unsigned char checksum[16] = {0}; + unsigned char block[16]; + unsigned int x; + unsigned int curpos = 0; + + while(curpos + 15 < size) + { + memcpy(block, saved_key + curpos, 16); + mdtransform(state, checksum, block); + curpos += 16; + } + + if(curpos != size) + { + x = size - curpos; + memcpy(block, saved_key + curpos, x); + memset(block + x, 16 - x, 16 - x); + mdtransform(state, checksum, block); + } + else + { + memset(block, 16, 16); + mdtransform(state, checksum, block); + } + + mdtransform_norecalc(state, checksum); + + memcpy(crypt_key, state, 16); +} + +static int dominosec_valid(char *ciphertext) +{ + unsigned int i; + unsigned char ch; + + if (strlen(ciphertext) != CIPHERTEXT_LENGTH) + return 0; + + if (ciphertext[0] != '(' || + ciphertext[1] != 'G' || + ciphertext[CIPHERTEXT_LENGTH-1] != ')') + return 0; + + for (i = 1; i < CIPHERTEXT_LENGTH-1; ++i) { + ch = ciphertext[i]; + if (!isalnum(ch) && ch != '+' && ch != '/') + return 0; + } + + return 1; +} + +/* +static unsigned int dominosec_proper_mul(int delta_apsik) +{ + __asm__("movl $0xAAAAAAAB, %eax \n" + "movl 0x8(%ebp), %edx \n" + "mul %edx \n" + "shr $0x2,%edx \n" + "movl %edx, %eax \n"); +} +*/ + +static void dominosec_decode(unsigned char *ascii_cipher, unsigned char *binary) +{ + unsigned int out = 0, apsik = 0, loop; + unsigned int i; + unsigned char ch; + + ascii_cipher += 2; + i = 0; + do { + if (apsik < 8) { + /* should be using proper_mul, but what the heck... + it's nearly the same :] */ + loop = 2; /* ~ loop = proper_mul(13 - apsik); */ + apsik += loop*6; + + do { + out <<= 6; + ch = *ascii_cipher; + + if (ch < '0' || ch > '9') + if (ch < 'A' || ch > 'Z') + if (ch < 'a' || ch > 'z') + if (ch != '+') + if (ch == '/') + out += '?'; + else + ; /* shit happens */ + else + out += '>'; + else + out += ch-'='; + else + out += ch-'7'; + else + out += ch-'0'; + ++ascii_cipher; + } while (--loop); + } + + loop = apsik-8; + ch = out >> loop; + *(binary+i) = ch; + ch <<= loop; + apsik = loop; + out -= ch; + } while (++i < 15); + + binary[3] += -4; +} + +static void *dominosec_binary(char *ciphertext) +{ + dominosec_decode((unsigned char*)ciphertext, (unsigned char*)&cipher_binary); + return (void*)cipher_binary.hash; +} + +static void *dominosec_salt(char *ciphertext) +{ + return cipher_binary.salt; +} + +static void dominosec_set_salt(void *salt) +{ + memcpy(salt_and_digest, salt, SALT_SIZE); +} + +static void dominosec_set_key(char *key, int index) +{ + unsigned char *offset = salt_and_digest+6; + unsigned int i; + + saved_key_len = strlen(key); + strnzcpy(saved_key, key, PLAINTEXT_LENGTH); + + domino_big_md((unsigned char*)key, saved_key_len, key_digest); + + i = 0; + do { + memcpy(offset, *(hex_table+*(key_digest+i)), 2); + offset += 2; + } while (++i < 14); + + /* + * Not (++i < 16) ! + * Domino will do hash of first 34 bytes ignoring The Fact that now + * there is a salt at a beginning of buffer. This means that last 5 + * bytes "EEFF)" of password digest are meaningless. + */ +} + +static char *dominosec_get_key(int index) +{ + return saved_key; +} + +static void dominosec_crypt_all(int count) +{ + domino_big_md(salt_and_digest, 34, crypted_key); +} + +static int dominosec_cmp_all(void *binary, int count) +{ + /* + * Only 10 bytes of digest are to be checked. + * 48 bits are left alone. + * Funny that. + */ + return !memcmp(crypted_key, binary, BINARY_SIZE); +} + +static int dominosec_cmp_exact(char *source, int index) +{ + return 1; +} + +struct fmt_main fmt_DOMINOSEC = { + { + FORMAT_LABEL, + FORMAT_NAME, + 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, + dominosec_tests + }, + { + fmt_default_init, + dominosec_valid, + fmt_default_split, + dominosec_binary, + dominosec_salt, + { + fmt_default_binary_hash, + fmt_default_binary_hash, + fmt_default_binary_hash + }, + fmt_default_salt_hash, + dominosec_set_salt, + dominosec_set_key, + dominosec_get_key, + fmt_default_clear_keys, + dominosec_crypt_all, + { + fmt_default_get_hash, + fmt_default_get_hash, + fmt_default_get_hash + }, + dominosec_cmp_all, + dominosec_cmp_all, + dominosec_cmp_exact + } +}; diff -ruN src/IPB2_fmt.c src-patched/IPB2_fmt.c --- src/IPB2_fmt.c 1969-12-31 19:00:00.000000000 -0500 +++ src-patched/IPB2_fmt.c 2006-02-18 17:25:21.000000000 -0500 @@ -0,0 +1,252 @@ +/* + * IPB2_fmt.c (version 4) + * + * Invision Power Board 2.x salted MD5 module for Solar Designer's JtR + * Uses Solar Designer's MD5 implementation. + * regenrecht@o2.pl, Jan 2006 + * + * Hashes list should have form of username:$IPB2$salt$hash + * Values to be taken from IPB database, where: + * salt = bin2hex(ibf_members_converge.converge_pass_salt) + * hash = ibf_members_converge.converge_pass_hash + */ + +#include + +#include "arch.h" +#include "misc.h" +#include "md5.h" +#include "common.h" +#include "formats.h" + +#define FORMAT_LABEL "ipb2" +#define FORMAT_NAME "IPB2 MD5" +#define ALGORITHM_NAME "Invision Power Board 2.x salted MD5" + +#define BENCHMARK_COMMENT "" +#define BENCHMARK_LENGTH -1 + +#define MD5_BINARY_SIZE 16 +#define MD5_HEX_SIZE (MD5_BINARY_SIZE * 2) + +#define BINARY_SIZE MD5_BINARY_SIZE + +#define SALT_SIZE 5 +#define PROCESSED_SALT_SIZE MD5_HEX_SIZE + +#define PLAINTEXT_LENGTH 32 +#define CIPHERTEXT_LENGTH (1 + 4 + 1 + SALT_SIZE * 2 + 1 + MD5_HEX_SIZE) + +#define MIN_KEYS_PER_CRYPT 1 +#define MAX_KEYS_PER_CRYPT 1 + +static struct fmt_tests ipb2_tests[] = { + {"$IPB2$2e75504633$d891f03a7327639bc632d62a7f302604", "welcome"}, + {"$IPB2$735a213a4e$4f23de7bb115139660db5e953153f28a", "enter"}, + {"$IPB2$5d75343455$de98ba8ca7bb16f43af05e9e4fb8afee", "matrix"}, + {"$IPB2$556c576c39$16d4f29c71b05bd75e61d0254800bfa3", "123456"}, + {NULL} +}; + +static char itoa16_shr_04[] = + "0000000000000000" + "1111111111111111" + "2222222222222222" + "3333333333333333" + "4444444444444444" + "5555555555555555" + "6666666666666666" + "7777777777777777" + "8888888888888888" + "9999999999999999" + "aaaaaaaaaaaaaaaa" + "bbbbbbbbbbbbbbbb" + "cccccccccccccccc" + "dddddddddddddddd" + "eeeeeeeeeeeeeeee" + "ffffffffffffffff"; + +static char itoa16_and_0f[] = + "0123456789abcdef" + "0123456789abcdef" + "0123456789abcdef" + "0123456789abcdef" + "0123456789abcdef" + "0123456789abcdef" + "0123456789abcdef" + "0123456789abcdef" + "0123456789abcdef" + "0123456789abcdef" + "0123456789abcdef" + "0123456789abcdef" + "0123456789abcdef" + "0123456789abcdef" + "0123456789abcdef" + "0123456789abcdef"; + +static MD5_CTX ctx; +static char saved_key[PLAINTEXT_LENGTH + 1]; +static int saved_key_len; +static char workspace[MD5_HEX_SIZE * 2]; +static char output[MD5_BINARY_SIZE]; + +static int ipb2_valid(char *ciphertext) +{ + if (strlen(ciphertext) != CIPHERTEXT_LENGTH) + return 0; + + if (strncmp(ciphertext, "$IPB2$", 6) != 0) + return 0; + + if (ciphertext[16] != '$') + return 0; + + if (strspn(ciphertext+6, itoa16) != SALT_SIZE*2) + return 0; + + if (strspn(ciphertext+17, itoa16) != MD5_HEX_SIZE) + return 0; + + return 1; +} + +static void *ipb2_binary(char *ciphertext) +{ + static unsigned char binary_cipher[BINARY_SIZE]; + int i; + + ciphertext += 17; + for (i = 0; i < MD5_HEX_SIZE; ++i) + binary_cipher[i] = + (atoi16[ARCH_INDEX(ciphertext[i*2])] << 4) + + atoi16[ARCH_INDEX(ciphertext[i*2+1])]; + + return (void *)binary_cipher; +} + +static void *ipb2_salt(char *ciphertext) +{ + static unsigned char binary_salt[SALT_SIZE]; + static unsigned char salt_hash[MD5_BINARY_SIZE]; + static unsigned char hex_salt[MD5_HEX_SIZE]; + int i; + + ciphertext += 6; + for (i = 0; i < SALT_SIZE; ++i) + binary_salt[i] = + (atoi16[ARCH_INDEX(ciphertext[i*2])] << 4) + + atoi16[ARCH_INDEX(ciphertext[i*2+1])]; + + MD5_Init(&ctx); + MD5_Update(&ctx, binary_salt, SALT_SIZE); + MD5_Final(salt_hash, &ctx); + + for (i = 0; i < MD5_BINARY_SIZE; ++i) { + hex_salt[i*2] = itoa16[ARCH_INDEX(salt_hash[i] >> 4)]; + hex_salt[i*2+1] = itoa16[ARCH_INDEX(salt_hash[i] & 0x0f)]; + } + + return (void*)hex_salt; +} + +static void ipb2_set_salt(void *salt) +{ + memcpy((char*)workspace, (char*)salt, PROCESSED_SALT_SIZE); +} + +static int strnfcpy_count(char *dst, char *src, int size) +{ + char *dptr = dst, *sptr = src; + int count = size; + + while (count--) + if (!(*dptr++ = *sptr++)) break; + + return size-count-1; +} + +static void ipb2_set_key(char *key, int index) +{ + static unsigned char key_hash[MD5_BINARY_SIZE]; + unsigned char *kh = key_hash; + unsigned char *workspace_ptr = workspace + PROCESSED_SALT_SIZE; + unsigned char v; + int i; + + saved_key_len = strnfcpy_count(saved_key, key, PLAINTEXT_LENGTH); + + MD5_Init(&ctx); + MD5_Update(&ctx, saved_key, saved_key_len); + MD5_Final(key_hash, &ctx); + + for (i = 0; i < MD5_BINARY_SIZE; ++i) { + v = *kh++; + *workspace_ptr++ = itoa16_shr_04[ARCH_INDEX(v)]; + *workspace_ptr++ = itoa16_and_0f[ARCH_INDEX(v)]; + } +} + +static char *ipb2_get_key(int index) +{ + return saved_key; +} + +static void ipb2_crypt_all(int count) +{ + MD5_Init(&ctx); + MD5_Update(&ctx, workspace, MD5_HEX_SIZE * 2); + MD5_Final(output, &ctx); +} + +static int ipb2_cmp_all(void *binary, int index) +{ + return !memcmp(binary, output, MD5_BINARY_SIZE); +} + +static int ipb2_cmp_exact(char *source, int index) +{ + return 1; +} + +struct fmt_main fmt_IPB2 = { + { + FORMAT_LABEL, + FORMAT_NAME, + ALGORITHM_NAME, + BENCHMARK_COMMENT, + BENCHMARK_LENGTH, + PLAINTEXT_LENGTH, + BINARY_SIZE, + PROCESSED_SALT_SIZE, + MIN_KEYS_PER_CRYPT, + MAX_KEYS_PER_CRYPT, + FMT_CASE | FMT_8_BIT, + ipb2_tests + }, + { + fmt_default_init, + ipb2_valid, + fmt_default_split, + ipb2_binary, + ipb2_salt, + { + fmt_default_binary_hash, + fmt_default_binary_hash, + fmt_default_binary_hash + }, + fmt_default_salt_hash, + ipb2_set_salt, + ipb2_set_key, + ipb2_get_key, + fmt_default_clear_keys, + ipb2_crypt_all, + { + fmt_default_get_hash, + fmt_default_get_hash, + fmt_default_get_hash + }, + ipb2_cmp_all, + ipb2_cmp_all, + ipb2_cmp_exact + } +}; diff -ruN src/KRB5_fmt.c src-patched/KRB5_fmt.c --- src/KRB5_fmt.c 1969-12-31 19:00:00.000000000 -0500 +++ src-patched/KRB5_fmt.c 2006-02-18 21:39:38.000000000 -0500 @@ -0,0 +1,353 @@ +/* + * KRB5_fmt.c + * + * Kerberos 5 module for John the Ripper by Solar Designer, based on the + * KRB4 module by Dug Soug. + * + * Author: Nasko Oskov + * + * Licensing: + * + * The module contains code derived or copied from the Heimdal project. + * + * Copyright (c) 1997-2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Which is distribution of Kerberos based on M.I.T. implementation. + * + * Copyright (C) 1990 by the Massachusetts Institute of Technology + * + */ + +#include + +#include +#include +#include +#include + +#include +#include + +#include + +#include "arch.h" +#include "misc.h" +#include "formats.h" // needed for format structs +#include "KRB5_std.h" + + +// defines // {{{ +#define MAGIC_PREFIX "$krb5$" +#define MAX_REALM_LEN 64 +#define TGT_SIZE 228 +#define MAX_USER_LEN 64 +#define MAX_PASS_LEN 64 + +#define FORMAT_LABEL "krb5" +#define FORMAT_NAME "Kerberos v5 TGT" +#define ALGORITHM_NAME "krb5 3DES (des3-cbc-sha1)" +#define BENCHMARK_COMMENT "" +#define BENCHMARK_LENGTH -1 +#define PLAINTEXT_LENGTH 32 +#define BINARY_SIZE 0 +#define MIN_KEYS_PER_CRYPT 1 +#define MAX_KEYS_PER_CRYPT 1 + +#define DES3_KEY_SIZE 24 +#define DES3_KEY_BITS 168 +#define DES3_KEY_SCHED_SIZE 384 + +#define KRBTGT "krbtgt" +// }}} + + +/** + * structure to hold the self tests // {{{ + */ +static struct fmt_tests KRB5_fmt_tests[] = { + {"$krb5$oskov$ACM.UIUC.EDU$4730d7249765615d6f3652321c4fb76d09fb9cd06faeb0c31b8737f9fdfcde4bd4259c31cb1dff25df39173b09abdff08373302d99ac09802a290915243d9f0ea0313fdedc7f8d1fae0d9df8f0ee6233818d317f03a72c2e77b480b2bc50d1ca14fba85133ea00e472c50dbc825291e2853bd60a969ddb69dae35b604b34ea2c2265a4ffc72e9fb811da17c7f2887ccb17e2f87cd1f6c28a9afc0c083a9356a9ee2a28d2e4a01fc7ea90cc8836b8e25650c3a1409b811d0bad42a59aa418143291d42d7b1e6cb5b1876a4cc758d721323a762e943f774630385c9faa68df6f3a94422f97", "p4ssW0rd"}, + {"$krb5$oskov$ACM.UIUC.EDU$6cba0316d38e31ba028f87394792baade516afdfd8c5a964b6a7677adbad7815d778b297beb238394aa97a4d495adb7c9b7298ba7c2a2062fb6c9a4297f12f83755060f4f58a1ea4c7026df585cdfa02372ad619ab1a4ec617ad23e76d6e37e36268d9aa0abcf83f11fa8092b4328c5e6c577f7ec6f1c1684d9c99a309eee1f5bd764c4158a2cf311cded8794b2de83131c3dc51303d5300e563a2b7a230eac67e85b4593e561bf6b88c77b82c729e7ba7f3d2f99b8dc85b07873e40335aff4647833a87681ee557fbd1ffa1a458a5673d1bd3c1587eceeabaebf4e44c24d9a8ac8c1d89", "Nask0Oskov"}, + {NULL} +}; +// }}} + +/** + * struct to save the salt into + */ +struct salt { // {{{ + char realm[MAX_REALM_LEN]; + char user[MAX_USER_LEN]; + char tgt_ebin[TGT_SIZE]; + char passwd[MAX_PASS_LEN]; +}; +#define SALT_SIZE sizeof(struct salt) +// }}} + +struct key { // {{{ + char passwd[MAX_PASS_LEN]; + char key[MAX_PASS_LEN]; + DES_key_schedule sched[3]; +}; +// }}} + +static struct salt *psalt = NULL; +static struct key skey; + +static char username[MAX_USER_LEN]; +static char realm[MAX_REALM_LEN]; +static char password[MAX_PASS_LEN]; + +// initialization vector for des +static DES_cblock ivec; + +krb5_key _krb5key; +krb5_key *krb5key = &_krb5key; + +/** + * hex2bin // {{{ + */ +static void hex2bin(char *src, u_char *dst, int outsize) { + char *p, *pe; + u_char *q, *qe, ch, cl; + + pe = src + strlen(src); + qe = dst + outsize; + + for (p = src, q = dst; p < pe && q < qe && isxdigit((int)*p); p += 2) { + ch = tolower(p[0]); + cl = tolower(p[1]); + + if ((ch >= '0') && (ch <= '9')) ch -= '0'; + else if ((ch >= 'a') && (ch <= 'f')) ch -= 'a' - 10; + else return; + + if ((cl >= '0') && (cl <= '9')) cl -= '0'; + else if ((cl >= 'a') && (cl <= 'f')) cl -= 'a' - 10; + else return; + + *q++ = (ch << 4) | cl; + } +} +// }}} + +/** + * krb5_decrypt_compare // {{{ + * + */ +int krb5_decrypt_compare() { + + char plain[TGT_SIZE]; + int i; + + memset(krb5key->key, 0x00, DES3_KEY_SIZE); + memset(krb5key->schedule, 0x00, DES3_KEY_SCHED_SIZE); + + memset(username, 0x00, MAX_USER_LEN); + memcpy(username, psalt->user, strlen(psalt->user)); + memset(realm, 0x00, MAX_REALM_LEN); + memcpy(realm, psalt->realm, strlen(psalt->realm)); + memset(password, 0x00, MAX_PASS_LEN); + memcpy(password, skey.passwd, strlen(skey.passwd)); + + // do str2key + str2key(username, realm, password, krb5key); + + des3_decrypt(krb5key, psalt->tgt_ebin, plain, TGT_SIZE); + + for(i=0;ipasswd, 0x00, MAX_PASS_LEN); + strncpy(psalt->passwd, skey.passwd, strlen(skey.passwd)); + return 1; + } + return 0; +} +// }}} + +/** + * int krb5_valid // {{{ + * + */ +static int krb5_valid(char *ciphertext) { + + if (strncmp(ciphertext, MAGIC_PREFIX, strlen(MAGIC_PREFIX)) != 0) + return 0; + + return 1; +} +// }}} + +/** + * void * krb5_salt // {{{ + * + */ +static void * krb5_salt(char *ciphertext) { + + struct salt *salt = NULL; + char *data = ciphertext, *p; + + // check the presence of $krb5$ + if (strncmp(data, MAGIC_PREFIX, strlen(MAGIC_PREFIX)) == 0) { + // advance past the $krb5$ string + data += strlen(MAGIC_PREFIX); + + // allocate memory for the struct + salt = malloc(sizeof(struct salt)); + if (salt == NULL) + return NULL; + + // find and copy the user field + p = strchr(data, '$'); + strnzcpy(salt->user, data, (p - data) + 1); + data = p + 1; + + // find and copy the realm field + p = strchr(data, '$'); + strnzcpy(salt->realm, data, (p - data) + 1); + data = p + 1; + + // copy over the TGT in a binary form to the salt struct + hex2bin(data, salt->tgt_ebin, TGT_SIZE); + } + return salt; +} +// }}} + +/** + * void krb5_set_salt // {{{ + * + */ +static void krb5_set_salt(void *salt) { + psalt = (struct salt *) salt; +} +// }}} + +/** + * void krb5_set_key // {{{ + * + */ +static void krb5_set_key(char *key, int index) { + + // copy the string key to the saved key + memset(skey.passwd, 0x00, MAX_PASS_LEN); + strnzcpy(skey.passwd, key, sizeof(skey.passwd)); + +} +// }}} + +/** + * char * krb5_get_key // {{{ + * + */ +static char * krb5_get_key(int index) { + return skey.passwd; +} +// }}} + +/** + * void krb5_crypt_all // {{{ + * + */ +static void krb5_crypt_all(int count) { + // do nothing +} +// }}} + +/** + * int krb5_cmp_all // {{{ + * + */ +static inline int krb5_cmp_all(void *binary, int count) { + + return krb5_decrypt_compare(); + +} +// }}} + +/** + * int krb5_cmp_one // {{{ + * + */ +static int krb5_cmp_one(void *binary, int count) { + + return krb5_decrypt_compare(); + +} +// }}} + +/** + * int krb5_cmp_exact // {{{ + * + */ +static int krb5_cmp_exact(char *source, int index) { + return 1; +} +// }}} + +/** + * void krb5_init // {{{ + * + */ +static void krb5_init() { + + memset(&ivec, 0x00, sizeof(ivec)); + memset(&skey, 0x00, sizeof(skey)); + memset(krb5key, 0x00, sizeof(krb5_key)); + + krb5key->key = (char *) malloc(DES3_KEY_SIZE); + krb5key->schedule = (char *) malloc(DES3_KEY_SCHED_SIZE); + memset(krb5key->key, 0x00, DES3_KEY_SIZE); + memset(krb5key->schedule, 0x00, DES3_KEY_SCHED_SIZE); + +} +// }}} + +/** + * fmt_main struct with KRB5 values // {{{ + */ +struct fmt_main fmt_KRB5 = { + { + FORMAT_LABEL, + FORMAT_NAME, + 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, + KRB5_fmt_tests + }, { + krb5_init, + krb5_valid, + fmt_default_split, + fmt_default_binary, + krb5_salt, + { + fmt_default_binary_hash, + fmt_default_binary_hash, + fmt_default_binary_hash + }, + fmt_default_salt_hash, + krb5_set_salt, + krb5_set_key, + krb5_get_key, + fmt_default_clear_keys, + krb5_crypt_all, + { + fmt_default_get_hash, + fmt_default_get_hash, + fmt_default_get_hash + }, + krb5_cmp_all, + krb5_cmp_one, + krb5_cmp_exact + } +}; +// }}} + diff -ruN src/KRB5_std.c src-patched/KRB5_std.c --- src/KRB5_std.c 1969-12-31 19:00:00.000000000 -0500 +++ src-patched/KRB5_std.c 2006-02-18 21:48:09.000000000 -0500 @@ -0,0 +1,278 @@ +/* + * KRB5_std.c + * + * Kerberos 5 module for John the Ripper by Solar Designer, based on the + * KRB4 module by Dug Soug. + * + * Author: Nasko Oskov + * + * Licensing: + * + * The module contains code derived or copied from the Heimdal project. + * + * Copyright (c) 1997-2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Which is distribution of Kerberos based on M.I.T. implementation. + * + * Copyright (C) 1990 by the Massachusetts Institute of Technology + * + */ + + +#include +#include + +#include "KRB5_std.h" + +static DES_cblock ivec; +static const char derive_const[5] = "\x00\x00\x00\x03\xaa"; + +/** + * Heimdal rr13 function // {{{ + */ +static inline void rr13(unsigned char *buf, int len) { + + unsigned char *tmp; + int bytes = (len + 7) / 8; + int i; + + int bb; + int b1, s1, b2, s2; + + const int bits = 13 % len; + const int lbit = len % 8; + + if(len == 0) + return; + + tmp = (unsigned char *) malloc(bytes); + memcpy(tmp, buf, bytes); + if(lbit) { + // pad final byte with inital bits + tmp[bytes - 1] &= 0xff << (8 - lbit); + for(i = lbit; i < 8; i += len) + tmp[bytes - 1] |= buf[0] >> i; + } + for(i = 0; i < bytes; i++) { + // calculate first bit position of this byte + bb = 8 * i - bits; + while(bb < 0) + bb += len; + // byte offset and shift count + b1 = bb / 8; + s1 = bb % 8; + + if(bb + 8 > bytes * 8) + // watch for wraparound + s2 = (len + 8 - s1) % 8; + else + s2 = 8 - s1; + b2 = (b1 + 1) % bytes; + buf[i] = (tmp[b1] << s1) | (tmp[b2] >> s2); + } + free(tmp); +} +// }}} + +/** + * Heimdal add1 function // {{{ + */ +static inline void add1(unsigned char *a, unsigned char *b, size_t len) { + int i, x; + int carry = 0; + for(i = len - 1; i >= 0; i--){ + x = a[i] + b[i] + carry; + carry = x > 0xff; + a[i] = x & 0xff; + } + for(i = len - 1; carry && i >= 0; i--){ + x = a[i] + carry; + carry = x > 0xff; + a[i] = x & 0xff; + } +} +// }}} + +/** + * Heimdal _krb5_n_fold function // {{{ + */ +static inline void _krb5_n_fold(const void *str, int len, void *key, int size) { + + int maxlen = 2 * max(size, len), l = 0; + unsigned char *tmp = (unsigned char *) malloc(maxlen); + unsigned char *buf = (unsigned char *) malloc(len); + + memcpy(buf, str, len); + memset(key, 0, size); + do { + memcpy(tmp + l, buf, len); + l += len; + rr13(buf, len * 8); + while(l >= size) { + add1(key, tmp, size); + l -= size; + if(l == 0) + break; + memmove(tmp, tmp + size, l); + } + } while(l != 0); + sfree(buf, len); + sfree(tmp, maxlen); +} +// }}} + +/** + * Heimdal DES3_postproc function // {{{ + */ +static inline void DES3_postproc(unsigned char *k, int len, krb5_key *krb5key) { + unsigned char x[24]; + int i, j; + unsigned char foo; + unsigned char b; + + memset(x, 0, sizeof(x)); + for (i = 0; i < 3; ++i) { + for (j = 0; j < 7; ++j) { + b = k[7 * i + j]; + x[8 * i + j] = b; + } + foo = 0; + for (j = 6; j >= 0; --j) { + foo |= k[7 * i + j] & 1; + foo <<= 1; + } + x[8 * i + 7] = foo; + } + k = krb5key->key; + memcpy(k, x, 24); + DES_set_odd_parity((DES_cblock*)k); + DES_set_odd_parity((DES_cblock*)(k + 8)); + DES_set_odd_parity((DES_cblock*)(k + 16)); + + memset(x, 0, sizeof(x)); +} +// }}} + +/** + * Heimdal based derive_key function // {{{ + */ +static inline void derive_key(const void *constant, int len, krb5_key *krb5key) { + + unsigned char *k; + unsigned int nblocks = 0, i; + DES_cblock *bk; + DES_key_schedule *s; + + // set the des schedule + bk = (DES_cblock*) krb5key->key; + s = (DES_key_schedule *) krb5key->schedule; + DES_set_key(&bk[0], &s[0]); + DES_set_key(&bk[1], &s[1]); + DES_set_key(&bk[2], &s[2]); + + if(DES3_BLOCK_SIZE * 8 < DES3_KEY_BITS || len != DES3_BLOCK_SIZE) { + nblocks = (DES3_KEY_BITS + DES3_BLOCK_SIZE * 8 - 1) / (DES3_BLOCK_SIZE * 8); + k = (unsigned char *) malloc(nblocks * DES3_BLOCK_SIZE); + if(k == NULL) { + printf("malloc: out of memory"); + exit(1); + } + _krb5_n_fold(constant, len, k, DES3_BLOCK_SIZE); + for(i = 0; i < nblocks; i++) { + if(i > 0) + memcpy(k + i * DES3_BLOCK_SIZE, k + (i - 1) * DES3_BLOCK_SIZE, DES3_BLOCK_SIZE); + + memset(ivec, 0x00, sizeof(ivec)); + DES_ede3_cbc_encrypt((void *) k + i * DES3_BLOCK_SIZE, (void *) k + i * DES3_BLOCK_SIZE, + DES3_BLOCK_SIZE, &s[0], &s[1], &s[2], (DES_cblock *) ivec, 1); + } + } else { + printf("Error, should never get here\n"); + exit(1); + } + + // keytype dependent post-processing + DES3_postproc(k, nblocks * DES3_BLOCK_SIZE, krb5key); + + sfree(k, nblocks * DES3_BLOCK_SIZE); +} +// }}} + +/** + * Heimdal based string_to_key_derived function // {{{ + */ +static inline void string_to_key_derived(const void *passwd, int len, krb5_key *krb5key) { + + unsigned char *tmp; + + tmp = (char *) malloc(DES3_KEY_BITS_BYTES); + if(tmp == NULL) { + printf("malloc: out of memory"); + // FIXME make it real return value if sometime this is needed + exit(1); + } + _krb5_n_fold(passwd, len, tmp, DES3_KEY_BITS_BYTES); + + DES3_postproc(tmp, DES3_KEY_BITS_BYTES, krb5key); + derive_key("kerberos", strlen("kerberos"), krb5key); + + sfree(tmp, DES3_KEY_BITS_BYTES); +} +// }}} + +/** + * des3_decrypt // {{{ + */ +void des3_decrypt(krb5_key *key, char *cipher, char *plain, int len) { + + DES_cblock *k; + DES_key_schedule *s; + + memset(&ivec, 0x00, sizeof(ivec)); + + k = (DES_cblock *) key->key; + s = (DES_key_schedule *) key->schedule; + + DES_set_key(&k[0], &s[0]); + DES_set_key(&k[1], &s[1]); + DES_set_key(&k[2], &s[2]); + + DES_ede3_cbc_encrypt((const unsigned char*) cipher, (unsigned char*) plain, len, &s[0], &s[1], &s[2], &ivec, 0); + +} +// }}} + +/** + * str2key // {{{ + */ +void str2key(char *user, char *realm, char *passwd, krb5_key *krb5key) { + int offset = 0; + char *text; + + text = (char*) malloc(strlen(user) + strlen(realm) + strlen(passwd)); + if (text == NULL) { + return; + } + + memset(krb5key->key, 0x00, DES3_KEY_SIZE); + memset(krb5key->schedule, 0x00, DES3_KEY_SCHED_SIZE); + + // make the string from the passwd, realm, username + offset = 0; + memcpy(text + offset, passwd, strlen(passwd)); + offset += strlen(passwd); + memcpy(text + offset, realm, strlen(realm)); + offset += strlen(realm); + memcpy(text + offset, user, strlen(user)); + offset += strlen(user); + + string_to_key_derived(text, offset, krb5key); + + // derive key from key + derive_key(derive_const, sizeof(derive_const), krb5key); + +} +// }}} + diff -ruN src/KRB5_std.h src-patched/KRB5_std.h --- src/KRB5_std.h 1969-12-31 19:00:00.000000000 -0500 +++ src-patched/KRB5_std.h 2006-02-18 17:35:35.000000000 -0500 @@ -0,0 +1,56 @@ +/* + * KRB5_std.h + * + * Kerberos 5 module for John the Ripper by Solar Designer, based on the + * KRB4 module by Dug Soug. + * + * Author: Nasko Oskov + * + * Licensing: + * + * The module contains code derived or copied from the Heimdal project. + * + * Copyright (c) 1997-2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Which is distribution of Kerberos based on M.I.T. implementation. + * + * Copyright (C) 1990 by the Massachusetts Institute of Technology + * + */ + +#ifndef _KRB5_STD_H_ +#define _KRB5_STD_H_ + +#include + +#define DES3_BLOCK_SIZE 8 +#define DES3_KEY_SIZE 24 +#define DES3_KEY_BITS 168 +#define DES3_KEY_BITS_BYTES DES3_KEY_BITS/8 +#define DES3_KEY_SCHED_SIZE 384 + +#ifndef sfree +#define sfree(x, len) if (x) { memset(x, 0x00, len); free(x); } +#endif + +#ifndef min +#define min(A, B) ((A) < (B) ? (A): (B)) +#endif + +#ifndef max +#define max(A, B) ((A) > (B) ? (A): (B)) +#endif + +typedef struct _krb5_key { + char *key; + char *schedule; +} krb5_key; + +void des3_decrypt(krb5_key *key, char *cipher, char *plain, int len); + +void str2key(char *user, char *realm, char *passwd, krb5_key *krb5key); + +#endif // _KRB5_STD_H_ + diff -ruN src/MD5_apache_fmt.c src-patched/MD5_apache_fmt.c --- src/MD5_apache_fmt.c 1969-12-31 19:00:00.000000000 -0500 +++ src-patched/MD5_apache_fmt.c 2006-02-18 17:25:21.000000000 -0500 @@ -0,0 +1,201 @@ +/* + Modified by Sun-Zero + 2004. 07. 26. + + Now, its work with md5 hash of apache. + The original john patch came from + http://lists.jammed.com/pen-test/2001/11/0134.html by + Kostas Evangelinos (kos@bastard.net) +*/ + +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-2001 by Solar Designer + */ + +#include + +#include "arch.h" +#include "misc.h" +#include "MD5_std.h" +#include "common.h" +#include "formats.h" + +#define FORMAT_LABEL "md5a" +#define FORMAT_NAME "Apache MD5" + +#define BENCHMARK_COMMENT "" +#define BENCHMARK_LENGTH -1 + +#define PLAINTEXT_LENGTH 15 +#define CIPHERTEXT_LENGTH 22 + +#define BINARY_SIZE 4 +#define SALT_SIZE 8 + +#define MIN_KEYS_PER_CRYPT MD5_N +#define MAX_KEYS_PER_CRYPT MD5_N + + +static struct fmt_tests tests[] = { + {"$apr1$Q6ZYh...$RV6ft2bZ8j.NGrxLYaJt9.", "test"}, + {"$apr1$rBXqc...$NlXxN9myBOk95T0AyLAsJ0", "john"}, + {"$apr1$Grpld/..$qp5GyjwM2dnA5Cdej9b411", "the"}, + {"$apr1$GBx.D/..$yfVeeYFCIiEXInfRhBRpy/", "ripper"}, + {NULL} +}; + +static char saved_key[MD5_N][PLAINTEXT_LENGTH + 1]; + +static int valid(char *ciphertext) +{ + char *pos, *start; + + if (strncmp(ciphertext, "$apr1$", 6)) return 0; + + /* magic string */ + start = &ciphertext[1]; + for (pos = start; *pos && *pos != '$'; pos++); + if (!*pos || pos < start+1 || pos > start+MD5_MAGIC_LENGTH+1) + return 0; + + /* salt */ + start = ++pos; + for (pos = start; *pos && *pos != '$'; pos++); + if (!*pos || pos < start || pos > start+8) + return 0; + + + start = ++pos; + while (atoi64[ARCH_INDEX(*pos)] != 0x7F) pos++; + if (*pos || pos - start != CIPHERTEXT_LENGTH) return 0; + + if (atoi64[ARCH_INDEX(*(pos - 1))] & 0x3C) return 0; + + return 1; +} + +static int binary_hash_0(void *binary) +{ + return *(MD5_word *)binary & 0xF; +} + +static int binary_hash_1(void *binary) +{ + return *(MD5_word *)binary & 0xFF; +} + +static int binary_hash_2(void *binary) +{ + return *(MD5_word *)binary & 0xFFF; +} + +static int get_hash_0(int index) +{ + return MD5_out[index][0] & 0xF; +} + +static int get_hash_1(int index) +{ + return MD5_out[index][0] & 0xFF; +} + +static int get_hash_2(int index) +{ + return MD5_out[index][0] & 0xFFF; +} + +static int salt_hash(void *salt) +{ + return + ((int)atoi64[ARCH_INDEX(((char *)salt)[0])] | + ((int)atoi64[ARCH_INDEX(((char *)salt)[1])] << 6)) & 0x3FF; +} + +static void set_key(char *key, int index) +{ + MD5_std_set_key(key, index); + + strnfcpy(saved_key[index], key, PLAINTEXT_LENGTH); +} + +static char *get_key(int index) +{ + saved_key[index][PLAINTEXT_LENGTH] = 0; + + return saved_key[index]; +} + +static int cmp_all(void *binary, int index) +{ + +#if MD5_X2 + return *(MD5_word *)binary == MD5_out[0][0] || + *(MD5_word *)binary == MD5_out[1][0]; +#else + return *(MD5_word *)binary == MD5_out[0][0]; +#endif +} + + +static int cmp_exact(char *source, int index) +{ + return !memcmp(MD5_std_get_binary(source, MD5_TYPE_APACHE), MD5_out[index], + sizeof(MD5_binary)); +} + + +static void crypt_all(int count) { + MD5_std_crypt(MD5_TYPE_APACHE); +} + +static void *get_salt(char *ciphertext) { + return MD5_std_get_salt(ciphertext, MD5_TYPE_APACHE); +} + +static void *get_binary(char *ciphertext) { + return MD5_std_get_binary(ciphertext, MD5_TYPE_APACHE); +} + + +struct fmt_main fmt_MD5_apache = { + { + FORMAT_LABEL, + FORMAT_NAME, + MD5_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 + }, { + MD5_std_init, + valid, + fmt_default_split, + get_binary, //(void *(*)(char *))MD5_std_get_binary, + get_salt, //(void *(*)(char *))MD5_std_get_salt, + { + binary_hash_0, + binary_hash_1, + binary_hash_2 + }, + salt_hash, + (void (*)(void *))MD5_std_set_salt, + set_key, + get_key, + fmt_default_clear_keys, + crypt_all, //(void (*)(int))MD5_std_crypt, + { + get_hash_0, + get_hash_1, + get_hash_2 + }, + cmp_all, + cmp_all, + cmp_exact + } +}; diff -ruN src/MD5_fmt.c src-patched/MD5_fmt.c --- src/MD5_fmt.c 2003-08-21 00:04:45.000000000 -0400 +++ src-patched/MD5_fmt.c 2006-02-18 17:25:21.000000000 -0500 @@ -1,4 +1,11 @@ /* + Modified by Sun-Zero + 2004. 07. 26. + + Now, its work with md5 hash of apache. +*/ + +/* * This file is part of John the Ripper password cracker, * Copyright (c) 1996-2001 by Solar Designer */ @@ -117,10 +124,22 @@ static int cmp_exact(char *source, int index) { - return !memcmp(MD5_std_get_binary(source), MD5_out[index], + return !memcmp(MD5_std_get_binary(source, MD5_TYPE_STD), MD5_out[index], sizeof(MD5_binary)); } +static void crypt_all(int count) { + MD5_std_crypt(MD5_TYPE_STD); +} + +static void *get_salt(char *ciphertext) { + return MD5_std_get_salt(ciphertext, MD5_TYPE_STD); +} + +static void *get_binary(char *ciphertext) { + return MD5_std_get_binary(ciphertext, MD5_TYPE_STD); +} + struct fmt_main fmt_MD5 = { { FORMAT_LABEL, @@ -139,8 +158,8 @@ MD5_std_init, valid, fmt_default_split, - (void *(*)(char *))MD5_std_get_binary, - (void *(*)(char *))MD5_std_get_salt, + get_binary, //(void *(*)(char *))MD5_std_get_binary, + get_salt, //(void *(*)(char *))MD5_std_get_salt, { binary_hash_0, binary_hash_1, @@ -151,7 +170,7 @@ set_key, get_key, fmt_default_clear_keys, - (void (*)(int))MD5_std_crypt, + crypt_all, // (void (*)(int))MD5_std_crypt, { get_hash_0, get_hash_1, diff -ruN src/MD5_std.c src-patched/MD5_std.c --- src/MD5_std.c 2005-01-05 19:10:18.000000000 -0500 +++ src-patched/MD5_std.c 2006-02-18 17:25:21.000000000 -0500 @@ -1,4 +1,14 @@ /* + Modified by Sun-Zero + 2004. 07. 26. + + Now, its work with md5 hash of apache. + The original john patch came from + http://lists.jammed.com/pen-test/2001/11/0134.html by + Kostas Evangelinos (kos@bastard.net) +*/ + +/* * This file is part of John the Ripper password cracker, * Copyright (c) 1996-2001,2003 by Solar Designer * @@ -400,7 +410,7 @@ order[19][index].length = current->l.pp; } -void MD5_std_crypt(void) +void MD5_std_crypt(int md5_type) { int length, index, mask; MD5_pattern *line; @@ -482,12 +492,21 @@ #if MD5_X2 for (index = 0, key = pool; index < MD5_N; index++, key++) { #endif + memcpy(&block[index], key->o.p.b, key->l.p); + if (md5_type == MD5_TYPE_APACHE) { + memcpy(&block[index].b[key->l.p], "$apr1$", 6); + memcpy(&block[index].b[key->l.p + 6], key->s, key->l.s); + memcpy(&block[index].b[key->l.ps + 6], + MD5_out[index], key->l.p); + length = key->l.psp + 6; + } else { memcpy(&block[index].b[key->l.p], "$1$", 3); memcpy(&block[index].b[key->l.p + 3], key->s, key->l.s); memcpy(&block[index].b[key->l.ps + 3], MD5_out[index], key->l.p); length = key->l.psp + 3; + } if ((mask = key->l.p)) do { block[index].b[length++] = @@ -853,13 +872,26 @@ #endif -char *MD5_std_get_salt(char *ciphertext) +char *MD5_std_get_salt(char *ciphertext, int md5_type) { static char out[9]; int length; + char *pos; + char *start; - for (length = 0; length < 8; length++) - if ((out[length] = ciphertext[3 + length]) == '$') break; + start = &ciphertext[1]; + if (md5_type == MD5_TYPE_APACHE) { + for (pos = start; *pos && *pos != '$'; pos++); + start = ++pos; + } + + for (length = 0; length < 8; length++) { + if (md5_type == MD5_TYPE_APACHE) { + if ((out[length] = start[length]) == '$') break; + } else { + if ((out[length] = ciphertext[3 + length]) == '$') break; + } + } out[length] = 0; return out; @@ -876,7 +908,7 @@ out.b[b2] = value >> 8; \ out.b[b3] = value; -MD5_word *MD5_std_get_binary(char *ciphertext) +MD5_word *MD5_std_get_binary(char *ciphertext, int md5_type) { static union { MD5_binary w; @@ -885,7 +917,16 @@ char *pos; MD5_word value; + char *start; + if (md5_type == MD5_TYPE_APACHE) { + start = &ciphertext[1]; + for (pos = start; *pos && *pos != '$'; pos++); + if (!*pos || pos < start+1 || pos > start+MD5_MAGIC_LENGTH+1) return 0; + pos++; + while (*pos++ != '$'); + } else { pos = ciphertext + 3; while (*pos++ != '$'); + } TO_BINARY(0, 6, 12); TO_BINARY(1, 7, 13); diff -ruN src/MD5_std.h src-patched/MD5_std.h --- src/MD5_std.h 2003-12-03 05:16:02.000000000 -0500 +++ src-patched/MD5_std.h 2006-02-18 17:25:21.000000000 -0500 @@ -13,6 +13,9 @@ #include "arch.h" #include "common.h" +#define MD5_TYPE_STD 0 +#define MD5_TYPE_APACHE 1 + typedef ARCH_WORD_32 MD5_word; /* @@ -88,6 +91,8 @@ #define MD5_ALGORITHM_NAME "32/" ARCH_BITS_STR #endif +#define MD5_MAGIC_LENGTH 10 + /* * Initializes the internal structures. */ @@ -107,16 +112,16 @@ /* * Main encryption routine, sets MD5_out. */ -extern void MD5_std_crypt(void); +extern void MD5_std_crypt(int md5_type); /* * Returns the salt for MD5_std_set_salt(). */ -extern char *MD5_std_get_salt(char *ciphertext); +extern char *MD5_std_get_salt(char *ciphertext, int md5_type); /* * Converts an ASCII ciphertext to binary. */ -extern MD5_word *MD5_std_get_binary(char *ciphertext); +extern MD5_word *MD5_std_get_binary(char *ciphertext, int md5_type); #endif diff -ruN src/MYSQL_fmt.c src-patched/MYSQL_fmt.c --- src/MYSQL_fmt.c 1969-12-31 19:00:00.000000000 -0500 +++ src-patched/MYSQL_fmt.c 2006-02-18 17:25:21.000000000 -0500 @@ -0,0 +1,241 @@ +//////////////////////////////////////////////////////////////// +// MySQL password cracker - v1.0 - 16.1.2003 +// +// by Andrew Hintz drew@overt.org +// +// This production has been brought to you by +// 4tphi and violating +// +// This file is an add-on to John the Ripper +// +// Part of this code is based on the MySQL brute password cracker +// mysqlpassword.c by Chris Given +// This program executes about 75% faster than mysqlpassword.c +// John the ripper also performs sophisticated password guessing. +// +// John the Ripper will expect the MySQL password file to be +// in the following format (without the leading // ): +// dumb_user:5d2e19393cc5ef67 +// another_luser:28ff8d49159ffbaf + +#include +#include +#include +#include + +// johntr includes +#include "arch.h" +#include "misc.h" +#include "formats.h" +#include "common.h" + +//johntr defines +#define FORMAT_LABEL "mysql" +#define FORMAT_NAME "MYSQL" +#define ALGORITHM_NAME "mysql" + +#define BENCHMARK_COMMENT "" +#define BENCHMARK_LENGTH -1 + +// Increase the PLAINTEXT_LENGTH value for longer passwords. +// You can also set it to 8 when using MySQL systems that truncate +// the password to only 8 characters. +#define PLAINTEXT_LENGTH 32 + +#define CIPHERTEXT_LENGTH 16 + +#define BINARY_SIZE 16 +#define SALT_SIZE 0 + +#define MIN_KEYS_PER_CRYPT 1 +#define MAX_KEYS_PER_CRYPT 1 + + +//used for mysql scramble function +struct rand_struct { + unsigned long seed1,seed2,max_value; + double max_value_dbl; +}; + + +void make_scrambled_password(char *,const char *); +char *scramble(char *,const char *,const char *, int); + +//test cases +static struct fmt_tests mysql_tests[] = { + {"30f098972cc8924d", "http://guh.nu"}, + {"3fc56f6037218993", "Andrew Hintz"}, + {"697a7de87c5390b2", "drew"}, + {"1eb71cf460712b3e", "http://4tphi.net"}, + {"28ff8d49159ffbaf", "http://violating.us"}, + {"5d2e19393cc5ef67", "password"}, + {NULL} +}; + + +//stores the ciphertext for value currently being tested +static char crypt_key[BINARY_SIZE+1]; + +//used by set_key +static char saved_key[PLAINTEXT_LENGTH + 1]; + +static int mysql_valid(char *ciphertext) { //returns 0 for invalid ciphertexts + + int i; //used as counter in loop + + //ciphertext is 16 characters + if (strlen(ciphertext) != 16) return 0; + + //ciphertext is ASCII representation of hex digits + for (i = 0; i < 16; i++){ + if (!( ((48 <= ciphertext[i])&&(ciphertext[i] <= 57)) || + ((97 <= ciphertext[i])&&(ciphertext[i] <= 102)) )) + return 0; + } + + return 1; +} + +static void mysql_set_salt(void *salt) { } + +static void mysql_set_key(char *key, int index) { + strnzcpy(saved_key, key, PLAINTEXT_LENGTH+1); +} + +static char *mysql_get_key(int index) { + return saved_key; +} + +static int mysql_cmp_all(void *binary, int index) { //also is mysql_cmp_one + return !memcmp(binary, crypt_key, BINARY_SIZE); +} + +static int mysql_cmp_exact(char *source, int count){ + return (1); // mysql_cmp_all fallthrough? +} + +static void mysql_crypt_all(int count) { + // get plaintext input in saved_key put it into ciphertext crypt_key + make_scrambled_password(crypt_key,saved_key); +} + +//////////////////////////////////////////////////////////////// +//begin mysql code +// This code was copied from mysqlpassword.c by Chris Given +// He probably copied it from password.c in the MySQL source +// The code is GPLed + +void randominit(struct rand_struct *rand_st,unsigned long seed1, unsigned long seed2) { + rand_st->max_value= 0x3FFFFFFFL; + rand_st->max_value_dbl=(double) rand_st->max_value; + rand_st->seed1=seed1%rand_st->max_value ; + rand_st->seed2=seed2%rand_st->max_value; +} +static void old_randominit(struct rand_struct *rand_st,unsigned long seed1) { + rand_st->max_value= 0x01FFFFFFL; + rand_st->max_value_dbl=(double) rand_st->max_value; + seed1%=rand_st->max_value; + rand_st->seed1=seed1 ; rand_st->seed2=seed1/2; +} +double rnd(struct rand_struct *rand_st) { + rand_st->seed1=(rand_st->seed1*3+rand_st->seed2) % + rand_st->max_value; + rand_st->seed2=(rand_st->seed1+rand_st->seed2+33) % + rand_st->max_value; + return(((double) rand_st->seed1)/rand_st->max_value_dbl); +} +void hash_password(unsigned long *result, const char *password) { + register unsigned long nr=1345345333L, add=7, nr2=0x12345671L; + unsigned long tmp; + for (; *password ; password++) { + if (*password == ' ' || *password == '\t') + continue; + tmp= (unsigned long) (unsigned char) *password; + nr^= (((nr & 63)+add)*tmp)+ (nr << 8); + nr2+=(nr2 << 8) ^ nr; + add+=tmp; + } + result[0]=nr & (((unsigned long) 1L << 31) -1L); /* Don't use sign bit + (str2int) */; + result[1]=nr2 & (((unsigned long) 1L << 31) -1L); + return; +} +void make_scrambled_password(char *to,const char *password) { + unsigned long hash_res[2]; + hash_password(hash_res,password); + sprintf(to,"%08lx%08lx",hash_res[0],hash_res[1]); +} +static inline unsigned int char_val(char X) { + return (unsigned int) (X >= '0' && X <= '9' ? X-'0' : X >= 'A' && X <= 'Z' ? + X-'A'+10 : X-'a'+10); +} +char *scramble(char *to,const char *message,const char *password, int + old_ver) { + struct rand_struct rand_st; + unsigned long hash_pass[2],hash_message[2]; + if(password && password[0]) { + char *to_start=to; + hash_password(hash_pass,password); + hash_password(hash_message,message); + if (old_ver) + old_randominit(&rand_st,hash_pass[0] ^ + hash_message[0]); + else + randominit(&rand_st,hash_pass[0] ^ hash_message[0], + hash_pass[1] ^ hash_message[1]); + while (*message++) + *to++= (char) (floor(rnd(&rand_st)*31)+64); + if (!old_ver) { + char extra=(char) (floor(rnd(&rand_st)*31)); + while(to_start != to) + *(to_start++)^=extra; + } + } + *to=0; + return to; +} + +//end mysql code +//////////////////////////////////////////////////////////////// + +struct fmt_main fmt_MYSQL = { + { + FORMAT_LABEL, + FORMAT_NAME, + 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, + mysql_tests + }, { + fmt_default_init, + mysql_valid, + fmt_default_split, + fmt_default_binary, + fmt_default_salt, + { + fmt_default_binary_hash, + fmt_default_binary_hash, + fmt_default_binary_hash + }, + fmt_default_salt_hash, + mysql_set_salt, + mysql_set_key, + mysql_get_key, + fmt_default_clear_keys, + mysql_crypt_all, + { + fmt_default_get_hash, + fmt_default_get_hash, + fmt_default_get_hash + }, + mysql_cmp_all, + mysql_cmp_all, //should it be the same as cmp_all or same as cmp_exact? + mysql_cmp_exact //fallthrough + } +}; diff -ruN src/Makefile src-patched/Makefile --- src/Makefile 2006-01-11 21:30:50.000000000 -0500 +++ src-patched/Makefile 2006-02-18 17:38:25.000000000 -0500 @@ -14,26 +14,44 @@ SED = sed PERL = perl NULL = /dev/null -CPPFLAGS = -E -CFLAGS = -c -Wall -O2 -fomit-frame-pointer + +CFLAGS = -c -Wall -O2 -fomit-frame-pointer -I/usr/local/include -L/usr/local/lib ASFLAGS = -c LDFLAGS = -s OPT_NORMAL = -funroll-loops OPT_INLINE = -finline-functions +LIBS = -lcrypto -lssl JOHN_OBJS_MINIMAL = \ DES_fmt.o DES_std.o DES_bs.o \ BSDI_fmt.o \ MD5_fmt.o MD5_std.o \ + MD5_apache_fmt.o \ + BFEgg_fmt.o \ BF_fmt.o BF_std.o \ AFS_fmt.o \ LM_fmt.o \ + DOMINOSEC_fmt.o \ + lotus5_fmt.o \ + MYSQL_fmt.o \ + KRB5_fmt.o KRB5_std.o \ + md5_go.o \ + rawMD5go_fmt.o \ + PO_fmt.o \ + md5.o \ + IPB2_fmt.o \ + rawSHA1_fmt.o \ + NSLDAP_fmt.o sha1.o base64.o \ + NT_fmt.o \ + md4.o smbencrypt.o \ + mscash_fmt.o \ batch.o bench.o charset.o common.o compiler.o config.o cracker.o \ crc32.o external.o formats.o getopt.o idle.o inc.o john.o list.o \ loader.o logger.o math.o memory.o misc.o options.o params.o path.o \ recovery.o rpp.o rules.o signals.o single.o status.o tty.o wordlist.o \ unshadow.o \ unafs.o \ + undrop.o \ unique.o JOHN_OBJS_ORIG = \ @@ -66,11 +84,11 @@ bench.o best.o common.o config.o formats.o math.o memory.o miscnl.o \ params.o path.o signals.o tty.o -PROJ = ../run/john ../run/unshadow ../run/unafs ../run/unique +PROJ = ../run/john ../run/unshadow ../run/unafs ../run/unique ../run/undrop PROJ_DOS = ../run/john.bin ../run/john.com \ - ../run/unshadow.com ../run/unafs.com ../run/unique.com + ../run/unshadow.com ../run/unafs.com ../run/unique.com ../run/undrop.com PROJ_WIN32 = ../run/john.exe \ - ../run/unshadow.exe ../run/unafs.exe ../run/unique.exe + ../run/unshadow.exe ../run/unafs.exe ../run/unique.exe ../run/undrop.exe default: @echo "To build John the Ripper, type:" @@ -460,9 +478,9 @@ $(LN) ppc32.h arch.h $(MAKE) $(PROJ) \ CPP=cc CC=cc AS=cc LD=cc \ - CFLAGS="-c -traditional-cpp" \ - OPT_NORMAL="-O2" \ - OPT_INLINE="-O3" + CFLAGS="-c -Wall -fomit-frame-pointer" \ + OPT_NORMAL="-fast -mcpu=750" \ + OPT_INLINE="-fast -mcpu=750 -finline-limit=4000" # This is slightly slower than macosx-ppc32-altivec for most hash types. macosx-ppc64-altivec: @@ -595,7 +613,7 @@ $(LD) $(LDFLAGS) $(BENCH_OBJS) -o bench ../run/john: $(JOHN_OBJS) - $(LD) $(LDFLAGS) $(JOHN_OBJS) -o ../run/john + $(LD) $(LDFLAGS) $(JOHN_OBJS) -o ../run/john $(LIBS) ../run/unshadow: ../run/john $(RM) ../run/unshadow @@ -605,6 +623,10 @@ $(RM) ../run/unafs ln -s john ../run/unafs +../run/undrop: ../run/john + $(RM) ../run/undrop + ln -s john ../run/undrop + ../run/unique: ../run/john $(RM) ../run/unique ln -s john ../run/unique @@ -623,6 +645,9 @@ ../run/unafs.com: john.com copy john.com ..\run\unafs.com +../run/undrop.com: john.com + copy john.com ..\run\undrop.com + ../run/unique.com: john.com copy john.com ..\run\unique.com @@ -641,6 +666,10 @@ $(CC) symlink.c -o ../run/unafs.exe strip ../run/unafs.exe +../run/undrop.exe: symlink.c + $(CC) symlink.c -o ../run/undrop.exe + strip ../run/undrop.exe + ../run/unique.exe: symlink.c $(CC) symlink.c -o ../run/unique.exe strip ../run/unique.exe diff -ruN src/NSLDAP_fmt.c src-patched/NSLDAP_fmt.c --- src/NSLDAP_fmt.c 1969-12-31 19:00:00.000000000 -0500 +++ src-patched/NSLDAP_fmt.c 2006-02-18 17:25:21.000000000 -0500 @@ -0,0 +1,167 @@ +// Fix for john the ripper 1.6.37 by Sun-Zero, 2004. 07. 26. +/* + * This file is part of John the Ripper password cracker, + * Copyright (c) 1996-98 by Solar Designer + */ + +#include + +#include "misc.h" +#include "formats.h" +#include "common.h" + +#include "sha.h" +#include "base64.h" + +#define FORMAT_LABEL "nsldap" +#define FORMAT_NAME "Netscape LDAP SHA" +#define SHA_TYPE "sha1" + +#define BENCHMARK_COMMENT "" +#define BENCHMARK_LENGTH -1 + +#define PLAINTEXT_LENGTH 72 +#define CIPHERTEXT_LENGTH 33 + +#define BINARY_SIZE 20 +#define SALT_SIZE 0 + +#define MIN_KEYS_PER_CRYPT 1 +#define MAX_KEYS_PER_CRYPT 1 + +#define NSLDAP_MAGIC "{sha}" +#define NSLDAP_MAGIC_LENGTH 5 + +static struct fmt_tests tests[] = { + {"{SHA}cMiB1KJphN3OeV9vcYF8nPRIDnk=", "aaaa"}, + {"{SHA}iu0TIuVFC62weOH7YKgXod8loso=", "bbbb"}, + {"{SHA}0ijZPTcJXMa+t2XnEbEwSOkvQu0=", "ccccccccc"}, + {"{SHA}vNR9eUfJfcKmdkLDqNoKagho+qU=", "dddddddddd"}, + {NULL} +}; + +static char crypt_key[BINARY_SIZE]; +static char saved_key[PLAINTEXT_LENGTH + 1]; + +static void * +binary(char *ciphertext) { + static char realcipher[BINARY_SIZE]; + + base64_decode(NSLDAP_MAGIC_LENGTH+ciphertext, CIPHERTEXT_LENGTH, realcipher); + return (void *)realcipher; +} + +static int +valid(char *ciphertext) +{ + if(ciphertext && strlen(ciphertext) == CIPHERTEXT_LENGTH) + return !strncasecmp(ciphertext, NSLDAP_MAGIC, NSLDAP_MAGIC_LENGTH); + return 0; +} + +static int binary_hash_0(void *binary) +{ + return ((int *)binary)[0] & 0xF; +} + +static int binary_hash_1(void *binary) +{ + return ((int *)binary)[0] & 0xFF; +} + +static int binary_hash_2(void *binary) +{ + return ((int *)binary)[0] & 0xFFF; +} + +static int get_hash_0(int index) +{ + return ((int *)crypt_key)[0] & 0xF; +} + +static int get_hash_1(int index) +{ + return ((int *)crypt_key)[0] & 0xFF; +} + +static int get_hash_2(int index) +{ + return ((int *)crypt_key)[0] & 0xFFF; +} + +static void set_key(char *key, int index) +{ + strnzcpy(saved_key, key, PLAINTEXT_LENGTH+1); +} + +static char *get_key(int index) +{ + return saved_key; +} + +static int +cmp_all(void *binary, int index) +{ + return !memcmp(binary, crypt_key, BINARY_SIZE); +} + +static int +cmp_exact(char *source, int index) +{ + return 1; +} + +static void set_salt(void *salt) { +} + +static void +crypt_all(int count) { + static SHA_CTX ctx; + + SHA1_Init(&ctx); + SHA1_Update(&ctx, saved_key, strlen(saved_key)); + SHA1_Final(crypt_key, &ctx); +} + +struct fmt_main fmt_NSLDAP = { + { + FORMAT_LABEL, + FORMAT_NAME, + SHA_TYPE, + BENCHMARK_COMMENT, + BENCHMARK_LENGTH, + PLAINTEXT_LENGTH, + BINARY_SIZE, + SALT_SIZE, + MIN_KEYS_PER_CRYPT, + MAX_KEYS_PER_CRYPT, + FMT_CASE | FMT_8_BIT, + tests + }, { + fmt_default_init, + valid, + fmt_default_split, + binary, + fmt_default_salt, + { + binary_hash_0, + binary_hash_1, + binary_hash_2 + }, + fmt_default_salt_hash, + set_salt, + set_key, + get_key, + fmt_default_clear_keys, + crypt_all, + { + get_hash_0, + get_hash_1, + get_hash_2 + }, + cmp_all, + cmp_all, + cmp_exact + } +}; + diff -ruN src/NT_fmt.c src-patched/NT_fmt.c --- src/NT_fmt.c 1969-12-31 19:00:00.000000000 -0500 +++ src-patched/NT_fmt.c 2006-02-18 17:25:21.000000000 -0500 @@ -0,0 +1,187 @@ +/* + * NTLM patch for john version 0.3 + * + * (C) 2001 Olle Segerdahl + * + * license: GPL + * + * This file is based on code from John the Ripper, + * Copyright (c) 1996-99 by Solar Designer + * + */ + +#include + +#include "arch.h" +#include "memory.h" +#include "common.h" +#include "formats.h" + +#ifndef uchar +#define uchar unsigned char +#endif + +#define FORMAT_LABEL "nt" +#define FORMAT_NAME "NT MD4" + +#define BENCHMARK_COMMENT "" +#define BENCHMARK_LENGTH -1 + +#define PLAINTEXT_LENGTH 54 +#define CIPHERTEXT_LENGTH 36 + + +static struct fmt_tests tests[] = { + {"$NT$b7e4b9022cd45f275334bbdb83bb5be5", "John the Ripper"}, + {"$NT$8846f7eaee8fb117ad06bdd830b7586c", "password"}, + {"$NT$0cb6948805f797bf2a82807973b89537", "test"}, + {"$NT$31d6cfe0d16ae931b73c59d7e0c089c0", ""}, + {NULL} +}; + +#define ALGORITHM_NAME "TridgeMD4" + +#define BINARY_SIZE 16 +#define SALT_SIZE 0 + +#define MIN_KEYS_PER_CRYPT 1 +#define MAX_KEYS_PER_CRYPT 1 + +uchar saved_plain[PLAINTEXT_LENGTH + 1]; +uchar output[BINARY_SIZE + 1]; + +extern void E_md4hash(uchar *passwd, uchar *p16); + + +static int valid(char *ciphertext) +{ + char *pos; + + if (strncmp(ciphertext, "$NT$", 4)!=0) return 0; + + for (pos = &ciphertext[4]; atoi16[ARCH_INDEX(*pos)] != 0x7F; pos++); + + if (!*pos && pos - ciphertext == CIPHERTEXT_LENGTH) + return 1; + else + return 0; + +} + +static void *get_binary(char *ciphertext) +{ + static uchar binary[BINARY_SIZE]; + int i; + + ciphertext+=4; + for (i=0; i + */ + +#include +#include + +#include "arch.h" +#include "misc.h" +#include "common.h" +#include "formats.h" +#include "md5_go.h" + +typedef ARCH_WORD_32 MD5_word; +typedef MD5_word MD5_binary[4]; +#if !ARCH_LITTLE_ENDIAN +#define MD5_out MD5_bitswapped_out +#endif +extern MD5_binary MD5_out; + +#define FORMAT_LABEL "po" +#define FORMAT_NAME "Post.Office MD5" + +#define BENCHMARK_COMMENT "" +#define BENCHMARK_LENGTH -1 + +#define PLAINTEXT_LENGTH 64 +#define CIPHERTEXT_LENGTH 64 + +#define BINARY_SIZE 4 +#define SALT_SIZE 32 + +#define MIN_KEYS_PER_CRYPT 1 +#define MAX_KEYS_PER_CRYPT 1 + +static struct fmt_tests tests[] = { + {"550c41c11bab48f9dbd8203ed313eef0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "abc123"}, + {"0c78bdef7d5448105cfbbc9aaa490a44550c41c11bab48f9dbd8203ed313eef0", "abc123"}, + {"9be296cf73d2f548dae3cccafaff1dd982916963c701200625cba2acd40d6569", "FRED"}, + {"a0e2078f0354846ec5bc4c7d7be08a4682916963c701200625cba2acd40d6569", ""}, + {NULL} +}; + +static char saved_key[PLAINTEXT_LENGTH + 1]; +static int saved_key_len; +static char po_buf[SALT_SIZE * 2 + 2 + PLAINTEXT_LENGTH + 128 /* MD5 scratch space */]; + +static void po_init(void) { + /* Do nothing */ +} + +static int valid(char *ciphertext) +{ + if (strlen(ciphertext) == 64 && + strspn(ciphertext, "0123456789abcdef") == 64) { + return 1; + } + return 0; +} + +static int binary_hash_0(void *binary) +{ + return *(MD5_word *)binary & 0xF; +} + +static int binary_hash_1(void *binary) +{ + return *(MD5_word *)binary & 0xFF; +} + +static int binary_hash_2(void *binary) +{ + return *(MD5_word *)binary & 0xFFF; +} + +static int get_hash_0(int index) +{ + return MD5_out[0] & 0xF; +} + +static int get_hash_1(int index) +{ + return MD5_out[0] & 0xFF; +} + +static int get_hash_2(int index) +{ + return MD5_out[0] & 0xFFF; +} + +static int salt_hash(void *salt) +{ + return + ((int)atoi64[ARCH_INDEX(((char *)salt)[0])] | + ((int)atoi64[ARCH_INDEX(((char *)salt)[1])] << 6)) & 0x3FF; +} + +static void set_key(char *key, int index) +{ + strnfcpy(saved_key, key, PLAINTEXT_LENGTH); + saved_key_len = strlen(saved_key); +} + +static char *get_key(int index) +{ + saved_key[PLAINTEXT_LENGTH] = 0; + return saved_key; +} + +static int cmp_all(void *binary, int index) +{ + /* also used for cmp_one */ + return *(MD5_word *)binary == MD5_out[0]; +} + +static int cmp_exact(char *source, int index) +{ + static char fullmd5[16]; + int i; + + for(i=0;i<16;i++) + { + fullmd5[i] = atoi16[ARCH_INDEX(source[i*2])]*16 + atoi16[ARCH_INDEX(source[i*2+1])]; + } + return !memcmp(fullmd5, MD5_out, sizeof(MD5_binary)); +} + +static void *get_binary(char *ciphertext) +{ + static char binarycipher[BINARY_SIZE]; + int i; + + for(i=0;i +#include +#include +#include + +void base64_unmap(char *in_block) { + int i; + unsigned char *c; + + for(i=0; i<4; i++) { + c = in_block + i; + + if(*c>='A' && *c<='Z') { + *c -= 'A'; + continue; + } + + if(*c>='a' && *c<='z') { + *c -= 'a'; + *c += 26; + continue; + } + + if(*c == '+') { + *c = 62; + continue; + } + + if(*c == '/') { + *c = 63; + continue; + } + + if(*c == '=') { + *c = 0; + } + + *c -= '0'; + *c += 52; + } +} + +int base64_decode(char *in, int inlen, char *out) { + int i; + char *in_block; + char *out_block; + char temp[4]; + + out_block = out; + in_block = in; + + for(i=0; i + * 2002-04-16 +*/ + +#include + +#include "blowfish.h" +#include "bf_tab.h" /* P-box P-array, S-box */ + +/* #define S(x,i) (bf_S[i][x.w.byte##i]) */ +#define S0(x) (bf_S[0][x.w.byte0]) +#define S1(x) (bf_S[1][x.w.byte1]) +#define S2(x) (bf_S[2][x.w.byte2]) +#define S3(x) (bf_S[3][x.w.byte3]) +#define bf_F(x) (((S0(x) + S1(x)) ^ S2(x)) + S3(x)) +#define ROUND(a,b,n) (a.word ^= bf_F(b) ^ bf_P[n]) + +#include + +/* keep a set of rotating P & S boxes */ +static struct box_t { + UWORD_32bits *P; + UWORD_32bits **S; + char key[81]; + char keybytes; +} box; + +//static UWORD_32bits bf_P[bf_N+2]; +//static UWORD_32bits bf_S[4][256]; +static UWORD_32bits *bf_P; +static UWORD_32bits **bf_S; + + +void blowfish_first_init(void) { + box.P = NULL; + box.S = NULL; + box.key[0] = 0; +} + +static void blowfish_encipher(UWORD_32bits * xl, UWORD_32bits * xr) +{ + union aword Xl; + union aword Xr; + + Xl.word = *xl; + Xr.word = *xr; + + Xl.word ^= bf_P[0]; + ROUND(Xr, Xl, 1); + ROUND(Xl, Xr, 2); + ROUND(Xr, Xl, 3); + ROUND(Xl, Xr, 4); + ROUND(Xr, Xl, 5); + ROUND(Xl, Xr, 6); + ROUND(Xr, Xl, 7); + ROUND(Xl, Xr, 8); + ROUND(Xr, Xl, 9); + ROUND(Xl, Xr, 10); + ROUND(Xr, Xl, 11); + ROUND(Xl, Xr, 12); + ROUND(Xr, Xl, 13); + ROUND(Xl, Xr, 14); + ROUND(Xr, Xl, 15); + ROUND(Xl, Xr, 16); + Xr.word ^= bf_P[17]; + + *xr = Xl.word; + *xl = Xr.word; +} + +static void blowfish_init(UBYTE_08bits * key, short keybytes) +{ + int i, j; + UWORD_32bits data; + UWORD_32bits datal; + UWORD_32bits datar; + union aword temp; + + /* is buffer already allocated for this? */ + if (box.P != NULL) { + if ((box.keybytes == keybytes) && + (!strncmp((char *) (box.key), (char *) key, keybytes))) { + /* match! */ + bf_P = box.P; + bf_S = box.S; + return; + } + free(box.P); + for (i = 0; i < 4; i++) + free(box.S[i]); + free(box.S); + } + /* initialize new buffer */ + /* uh... this is over 4k */ + box.P = (UWORD_32bits *) malloc((bf_N + 2) * sizeof(UWORD_32bits)); + box.S = (UWORD_32bits **) malloc(4 * sizeof(UWORD_32bits *)); + for (i = 0; i < 4; i++) + box.S[i] = (UWORD_32bits *) malloc(256 * sizeof(UWORD_32bits)); + bf_P = box.P; + bf_S = box.S; + box.keybytes = keybytes; + strncpy(box.key, key, keybytes); + /* robey: reset blowfish boxes to initial state */ + /* (i guess normally it just keeps scrambling them, but here it's + * important to get the same encrypted result each time) */ + for (i = 0; i < bf_N + 2; i++) + bf_P[i] = initbf_P[i]; + for (i = 0; i < 4; i++) + for (j = 0; j < 256; j++) + bf_S[i][j] = initbf_S[i][j]; + + j = 0; + for (i = 0; i < bf_N + 2; ++i) { + temp.word = 0; + temp.w.byte0 = key[j]; + temp.w.byte1 = key[(j + 1) % keybytes]; + temp.w.byte2 = key[(j + 2) % keybytes]; + temp.w.byte3 = key[(j + 3) % keybytes]; + data = temp.word; + bf_P[i] = bf_P[i] ^ data; + j = (j + 4) % keybytes; + } + datal = 0x00000000; + datar = 0x00000000; + for (i = 0; i < bf_N + 2; i += 2) { + blowfish_encipher(&datal, &datar); + bf_P[i] = datal; + bf_P[i + 1] = datar; + } + for (i = 0; i < 4; ++i) { + for (j = 0; j < 256; j += 2) { + blowfish_encipher(&datal, &datar); + bf_S[i][j] = datal; + bf_S[i][j + 1] = datar; + } + } +} + +/* stuff below this line was written by robey for eggdrop use */ + +/* of course, if you change either of these, then your userfile will + * no longer be able to be shared. :) */ +#define SALT1 0xdeadd061 +#define SALT2 0x23f6b095 + +/* convert 64-bit encrypted password to text for userfile */ +static char *base64 = "./0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + +static void blowfish_encrypt_pass(char *text, char *new) +{ + UWORD_32bits left, right; + int n; + char *p; + + blowfish_init(text, strlen(text)); + left = SALT1; + right = SALT2; + blowfish_encipher(&left, &right); + p = new; + *p++ = '+'; /* + means encrypted pass */ + n = 32; + while (n > 0) { + *p++ = base64[right & 0x3f]; + right = (right >> 6); + n -= 6; + } + n = 32; + while (n > 0) { + *p++ = base64[left & 0x3f]; + left = (left >> 6); + n -= 6; + } + *p = 0; +} \ No newline at end of file diff -ruN src/blowfish.h src-patched/blowfish.h --- src/blowfish.h 1969-12-31 19:00:00.000000000 -0500 +++ src-patched/blowfish.h 2006-02-18 17:25:21.000000000 -0500 @@ -0,0 +1,55 @@ +/* modified 19jul1996 by robey -- uses autoconf values now */ +#ifndef _H_BLOWFISH +#define _H_BLOWFISH + +#include "arch.h" + +#define bf_N 16 +#define noErr 0 +#define DATAERROR -1 + +#define UBYTE_08bits unsigned char +#define UWORD_16bits unsigned short + +#define SIZEOF_INT 4 + +#if SIZEOF_INT==4 +#define UWORD_32bits unsigned int +#else +#if SIZEOF_LONG==4 +#define UWORD_32bits unsigned long +#endif +#endif + +/* choose a byte order for your hardware */ + +#if !ARCH_LITTLE_ENDIAN +/* ABCD - big endian - motorola */ +union aword { + UWORD_32bits word; + UBYTE_08bits byte[4]; + struct { + unsigned int byte0:8; + unsigned int byte1:8; + unsigned int byte2:8; + unsigned int byte3:8; + } w; +}; +#endif /* !ARCH_LITTLE_ENDIAN */ + +#if ARCH_LITTLE_ENDIAN +/* DCBA - little endian - intel */ +union aword { + UWORD_32bits word; + UBYTE_08bits byte[4]; + struct { + unsigned int byte3:8; + unsigned int byte2:8; + unsigned int byte1:8; + unsigned int byte0:8; + } w; +}; + +#endif /* ARCH_LITTLE_ENDIAN */ + +#endif diff -ruN src/byteorder.h src-patched/byteorder.h --- src/byteorder.h 1969-12-31 19:00:00.000000000 -0500 +++ src-patched/byteorder.h 2006-02-18 17:25:21.000000000 -0500 @@ -0,0 +1,274 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + SMB Byte handling + Copyright (C) Andrew Tridgell 1992-1998 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _BYTEORDER_H +#define _BYTEORDER_H + +/* + This file implements macros for machine independent short and + int manipulation + +Here is a description of this file that I emailed to the samba list once: + +> I am confused about the way that byteorder.h works in Samba. I have +> looked at it, and I would have thought that you might make a distinction +> between LE and BE machines, but you only seem to distinguish between 386 +> and all other architectures. +> +> Can you give me a clue? + +sure. + +The distinction between 386 and other architectures is only there as +an optimisation. You can take it out completely and it will make no +difference. The routines (macros) in byteorder.h are totally byteorder +independent. The 386 optimsation just takes advantage of the fact that +the x86 processors don't care about alignment, so we don't have to +align ints on int boundaries etc. If there are other processors out +there that aren't alignment sensitive then you could also define +CAREFUL_ALIGNMENT=0 on those processors as well. + +Ok, now to the macros themselves. I'll take a simple example, say we +want to extract a 2 byte integer from a SMB packet and put it into a +type called uint16 that is in the local machines byte order, and you +want to do it with only the assumption that uint16 is _at_least_ 16 +bits long (this last condition is very important for architectures +that don't have any int types that are 2 bytes long) + +You do this: + +#define CVAL(buf,pos) (((unsigned char *)(buf))[pos]) +#define PVAL(buf,pos) ((unsigned)CVAL(buf,pos)) +#define SVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+1)<<8) + +then to extract a uint16 value at offset 25 in a buffer you do this: + +char *buffer = foo_bar(); +uint16 xx = SVAL(buffer,25); + +We are using the byteoder independence of the ANSI C bitshifts to do +the work. A good optimising compiler should turn this into efficient +code, especially if it happens to have the right byteorder :-) + +I know these macros can be made a bit tidier by removing some of the +casts, but you need to look at byteorder.h as a whole to see the +reasoning behind them. byteorder.h defines the following macros: + +SVAL(buf,pos) - extract a 2 byte SMB value +IVAL(buf,pos) - extract a 4 byte SMB value +SVALS(buf,pos) signed version of SVAL() +IVALS(buf,pos) signed version of IVAL() + +SSVAL(buf,pos,val) - put a 2 byte SMB value into a buffer +SIVAL(buf,pos,val) - put a 4 byte SMB value into a buffer +SSVALS(buf,pos,val) - signed version of SSVAL() +SIVALS(buf,pos,val) - signed version of SIVAL() + +RSVAL(buf,pos) - like SVAL() but for NMB byte ordering +RSVALS(buf,pos) - like SVALS() but for NMB byte ordering +RIVAL(buf,pos) - like IVAL() but for NMB byte ordering +RIVALS(buf,pos) - like IVALS() but for NMB byte ordering +RSSVAL(buf,pos,val) - like SSVAL() but for NMB ordering +RSIVAL(buf,pos,val) - like SIVAL() but for NMB ordering +RSIVALS(buf,pos,val) - like SIVALS() but for NMB ordering + +it also defines lots of intermediate macros, just ignore those :-) + +*/ + +/* some switch macros that do both store and read to and from SMB buffers */ + +#define RW_PCVAL(read,inbuf,outbuf,len) \ + { if (read) { PCVAL (inbuf,0,outbuf,len); } \ + else { PSCVAL(inbuf,0,outbuf,len); } } + +#define RW_PIVAL(read,big_endian,inbuf,outbuf,len) \ + { if (read) { if (big_endian) { RPIVAL(inbuf,0,outbuf,len); } else { PIVAL(inbuf,0,outbuf,len); } } \ + else { if (big_endian) { RPSIVAL(inbuf,0,outbuf,len); } else { PSIVAL(inbuf,0,outbuf,len); } } } + +#define RW_PSVAL(read,big_endian,inbuf,outbuf,len) \ + { if (read) { if (big_endian) { RPSVAL(inbuf,0,outbuf,len); } else { PSVAL(inbuf,0,outbuf,len); } } \ + else { if (big_endian) { RPSSVAL(inbuf,0,outbuf,len); } else { PSSVAL(inbuf,0,outbuf,len); } } } + +#define RW_CVAL(read, inbuf, outbuf, offset) \ + { if (read) { (outbuf) = CVAL (inbuf,offset); } \ + else { SCVAL(inbuf,offset,outbuf); } } + +#define RW_IVAL(read, big_endian, inbuf, outbuf, offset) \ + { if (read) { (outbuf) = ((big_endian) ? RIVAL(inbuf,offset) : IVAL (inbuf,offset)); } \ + else { if (big_endian) { RSIVAL(inbuf,offset,outbuf); } else { SIVAL(inbuf,offset,outbuf); } } } + +#define RW_SVAL(read, big_endian, inbuf, outbuf, offset) \ + { if (read) { (outbuf) = ((big_endian) ? RSVAL(inbuf,offset) : SVAL (inbuf,offset)); } \ + else { if (big_endian) { RSSVAL(inbuf,offset,outbuf); } else { SSVAL(inbuf,offset,outbuf); } } } + +#undef CAREFUL_ALIGNMENT + +/* we know that the 386 can handle misalignment and has the "right" + byteorder */ +#ifdef __i386__ +#define CAREFUL_ALIGNMENT 0 +#endif + +#ifndef CAREFUL_ALIGNMENT +#define CAREFUL_ALIGNMENT 1 +#endif + +#define CVAL(buf,pos) (((unsigned char *)(buf))[pos]) +#define PVAL(buf,pos) ((unsigned)CVAL(buf,pos)) +#define SCVAL(buf,pos,val) (CVAL(buf,pos) = (val)) + + +#if CAREFUL_ALIGNMENT + +#define SVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+1)<<8) +#define IVAL(buf,pos) (SVAL(buf,pos)|SVAL(buf,(pos)+2)<<16) +#define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8) +#define SIVALX(buf,pos,val) (SSVALX(buf,pos,val&0xFFFF),SSVALX(buf,pos+2,val>>16)) +#define SVALS(buf,pos) ((int16)SVAL(buf,pos)) +#define IVALS(buf,pos) ((int32)IVAL(buf,pos)) +#define SSVAL(buf,pos,val) SSVALX((buf),(pos),((uint16)(val))) +#define SIVAL(buf,pos,val) SIVALX((buf),(pos),((uint32)(val))) +#define SSVALS(buf,pos,val) SSVALX((buf),(pos),((int16)(val))) +#define SIVALS(buf,pos,val) SIVALX((buf),(pos),((int32)(val))) + +#else /* CAREFUL_ALIGNMENT */ + +/* this handles things for architectures like the 386 that can handle + alignment errors */ +/* + WARNING: This section is dependent on the length of int16 and int32 + being correct +*/ + +/* get single value from an SMB buffer */ +#define SVAL(buf,pos) (*(const uint16 *)((const char *)(buf) + (pos))) +#define IVAL(buf,pos) (*(const uint32 *)((const char *)(buf) + (pos))) +#define SVALS(buf,pos) (*(const int16 *)((const char *)(buf) + (pos))) +#define IVALS(buf,pos) (*(const int32 *)((const char *)(buf) + (pos))) + +/* store single value in an SMB buffer */ +#define SVALMOD(buf,pos) (*(uint16 *)((char *)(buf) + (pos))) +#define IVALMOD(buf,pos) (*(uint32 *)((char *)(buf) + (pos))) +#define SVALSMOD(buf,pos) (*(int16 *)((char *)(buf) + (pos))) +#define IVALSMOD(buf,pos) (*(int32 *)((char *)(buf) + (pos))) + +#define SSVAL(buf,pos,val) SVALMOD(buf,pos)=((uint16)(val)) +#define SIVAL(buf,pos,val) IVALMOD(buf,pos)=((uint32)(val)) +#define SSVALS(buf,pos,val) SVALSMOD(buf,pos)=((int16)(val)) +#define SIVALS(buf,pos,val) IVALSMOD(buf,pos)=((int32)(val)) + +#endif /* CAREFUL_ALIGNMENT */ + +/* macros for reading / writing arrays */ + +#define SMBMACRO(macro,buf,pos,val,len,size) \ +{ uint32 l; for (l = 0; l < (uint32)(len); l++) (val)[l] = macro((buf), (pos) + (size)*l); } + +#define SSMBMACRO(macro,buf,pos,val,len,size) \ +{ uint32 l; for (l = 0; l < (uint32)(len); l++) macro((buf), (pos) + (size)*l, (val)[l]); } + +/* reads multiple data from an SMB buffer */ +#define PCVAL(buf,pos,val,len) SMBMACRO(CVAL,buf,pos,val,len,1) +#define PSVAL(buf,pos,val,len) SMBMACRO(SVAL,buf,pos,val,len,2) +#define PIVAL(buf,pos,val,len) SMBMACRO(IVAL,buf,pos,val,len,4) +#define PCVALS(buf,pos,val,len) SMBMACRO(CVALS,buf,pos,val,len,1) +#define PSVALS(buf,pos,val,len) SMBMACRO(SVALS,buf,pos,val,len,2) +#define PIVALS(buf,pos,val,len) SMBMACRO(IVALS,buf,pos,val,len,4) + +/* stores multiple data in an SMB buffer */ +#define PSCVAL(buf,pos,val,len) SSMBMACRO(SCVAL,buf,pos,val,len,1) +#define PSSVAL(buf,pos,val,len) SSMBMACRO(SSVAL,buf,pos,val,len,2) +#define PSIVAL(buf,pos,val,len) SSMBMACRO(SIVAL,buf,pos,val,len,4) +#define PSCVALS(buf,pos,val,len) SSMBMACRO(SCVALS,buf,pos,val,len,1) +#define PSSVALS(buf,pos,val,len) SSMBMACRO(SSVALS,buf,pos,val,len,2) +#define PSIVALS(buf,pos,val,len) SSMBMACRO(SIVALS,buf,pos,val,len,4) + + +/* now the reverse routines - these are used in nmb packets (mostly) */ +#define SREV(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF)) +#define IREV(x) ((SREV(x)<<16) | (SREV((x)>>16))) + +#define RSVAL(buf,pos) SREV(SVAL(buf,pos)) +#define RSVALS(buf,pos) SREV(SVALS(buf,pos)) +#define RIVAL(buf,pos) IREV(IVAL(buf,pos)) +#define RIVALS(buf,pos) IREV(IVALS(buf,pos)) +#define RSSVAL(buf,pos,val) SSVAL(buf,pos,SREV(val)) +#define RSSVALS(buf,pos,val) SSVALS(buf,pos,SREV(val)) +#define RSIVAL(buf,pos,val) SIVAL(buf,pos,IREV(val)) +#define RSIVALS(buf,pos,val) SIVALS(buf,pos,IREV(val)) + +/* reads multiple data from an SMB buffer (big-endian) */ +#define RPSVAL(buf,pos,val,len) SMBMACRO(RSVAL,buf,pos,val,len,2) +#define RPIVAL(buf,pos,val,len) SMBMACRO(RIVAL,buf,pos,val,len,4) +#define RPSVALS(buf,pos,val,len) SMBMACRO(RSVALS,buf,pos,val,len,2) +#define RPIVALS(buf,pos,val,len) SMBMACRO(RIVALS,buf,pos,val,len,4) + +/* stores multiple data in an SMB buffer (big-endian) */ +#define RPSSVAL(buf,pos,val,len) SSMBMACRO(RSSVAL,buf,pos,val,len,2) +#define RPSIVAL(buf,pos,val,len) SSMBMACRO(RSIVAL,buf,pos,val,len,4) +#define RPSSVALS(buf,pos,val,len) SSMBMACRO(RSSVALS,buf,pos,val,len,2) +#define RPSIVALS(buf,pos,val,len) SSMBMACRO(RSIVALS,buf,pos,val,len,4) + +#define DBG_RW_PCVAL(charmode,string,depth,base,read,inbuf,outbuf,len) \ + { RW_PCVAL(read,inbuf,outbuf,len) \ + DEBUG(5,("%s%04x %s: ", \ + tab_depth(depth), base,string)); \ + if (charmode) print_asc(5, (unsigned char*)(outbuf), (len)); else \ + { uint32 idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%02x ", (outbuf)[idx])); } } \ + DEBUG(5,("\n")); } + +#define DBG_RW_PSVAL(charmode,string,depth,base,read,big_endian,inbuf,outbuf,len) \ + { RW_PSVAL(read,big_endian,inbuf,outbuf,len) \ + DEBUG(5,("%s%04x %s: ", \ + tab_depth(depth), base,string)); \ + if (charmode) print_asc(5, (unsigned char*)(outbuf), 2*(len)); else \ + { uint32 idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%04x ", (outbuf)[idx])); } } \ + DEBUG(5,("\n")); } + +#define DBG_RW_PIVAL(charmode,string,depth,base,read,big_endian,inbuf,outbuf,len) \ + { RW_PIVAL(read,big_endian,inbuf,outbuf,len) \ + DEBUG(5,("%s%04x %s: ", \ + tab_depth(depth), base,string)); \ + if (charmode) print_asc(5, (unsigned char*)(outbuf), 4*(len)); else \ + { uint32 idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%08x ", (outbuf)[idx])); } } \ + DEBUG(5,("\n")); } + +#define DBG_RW_CVAL(string,depth,base,read,inbuf,outbuf) \ + { RW_CVAL(read,inbuf,outbuf,0) \ + DEBUG(5,("%s%04x %s: %02x\n", \ + tab_depth(depth), base, string, outbuf)); } + +#define DBG_RW_SVAL(string,depth,base,read,big_endian,inbuf,outbuf) \ + { RW_SVAL(read,big_endian,inbuf,outbuf,0) \ + DEBUG(5,("%s%04x %s: %04x\n", \ + tab_depth(depth), base, string, outbuf)); } + +#define DBG_RW_IVAL(string,depth,base,read,big_endian,inbuf,outbuf) \ + { RW_IVAL(read,big_endian,inbuf,outbuf,0) \ + DEBUG(5,("%s%04x %s: %08x\n", \ + tab_depth(depth), base, string, outbuf)); } + +/* Alignment macros. */ +#define ALIGN4(p,base) ((p) + ((4 - (PTR_DIFF((p), (base)) & 3)) & 3)) +#define ALIGN2(p,base) ((p) + ((2 - (PTR_DIFF((p), (base)) & 1)) & 1)) + +#endif /* _BYTEORDER_H */ diff -ruN src/john.c src-patched/john.c --- src/john.c 2006-01-09 09:13:15.000000000 -0500 +++ src-patched/john.c 2006-02-18 17:25:21.000000000 -0500 @@ -37,10 +37,21 @@ #endif extern struct fmt_main fmt_DES, fmt_BSDI, fmt_MD5, fmt_BF; -extern struct fmt_main fmt_AFS, fmt_LM; +extern struct fmt_main fmt_AFS, fmt_LM, fmt_NT, fmt_PO, fmt_rawMD5go; +extern struct fmt_main fmt_IPB2; +extern struct fmt_main fmt_MD5_apache; +extern struct fmt_main fmt_BFEgg; +extern struct fmt_main fmt_KRB5; +extern struct fmt_main fmt_MYSQL; +extern struct fmt_main fmt_NSLDAP; +extern struct fmt_main fmt_mscash; +extern struct fmt_main fmt_rawSHA1; +extern struct fmt_main fmt_lotus5; +extern struct fmt_main fmt_DOMINOSEC; extern int unshadow(int argc, char **argv); extern int unafs(int argc, char **argv); +extern int undrop(int argc, char **argv); extern int unique(int argc, char **argv); static struct db_main database; @@ -48,7 +59,7 @@ static void john_register_one(struct fmt_main *format) { - if (options.format) + if (options.format) if (strcmp(options.format, format->params.label)) return; fmt_register(format); @@ -59,11 +70,24 @@ if (options.format) strlwr(options.format); john_register_one(&fmt_DES); + john_register_one(&fmt_LM); + john_register_one(&fmt_NT); + john_register_one(&fmt_mscash); john_register_one(&fmt_BSDI); john_register_one(&fmt_MD5); + john_register_one(&fmt_MD5_apache); + john_register_one(&fmt_PO); + john_register_one(&fmt_rawMD5go); + john_register_one(&fmt_IPB2); + john_register_one(&fmt_rawSHA1); + john_register_one(&fmt_KRB5); + john_register_one(&fmt_NSLDAP); john_register_one(&fmt_BF); + john_register_one(&fmt_BFEgg); john_register_one(&fmt_AFS); - john_register_one(&fmt_LM); + john_register_one(&fmt_MYSQL); + john_register_one(&fmt_lotus5); + john_register_one(&fmt_DOMINOSEC); if (!fmt_list) { fprintf(stderr, "Unknown ciphertext format name requested\n"); @@ -341,6 +365,9 @@ if (!strcmp(name, "unique")) return unique(argc, argv); + if (!strcmp(name, "undrop")) + return undrop(argc, argv); + john_init(name, argc, argv); john_run(); john_done(); diff -ruN src/loader.c src-patched/loader.c --- src/loader.c 2005-11-08 08:03:20.000000000 -0500 +++ src-patched/loader.c 2006-02-18 17:25:21.000000000 -0500 @@ -18,6 +18,7 @@ #include "signals.h" #include "formats.h" #include "loader.h" +#include "options.h" /* * Flags for read_file(). @@ -183,7 +184,7 @@ static int ldr_split_line(char **login, char **ciphertext, char **gecos, char **home, char *source, struct fmt_main **format, - struct db_options *options, char *line) + struct db_options *db_options, char *line) { char *uid = NULL, *gid = NULL, *shell = NULL; char *tmp; @@ -206,10 +207,27 @@ if (!strncmp(*ciphertext, "NO PASSWORD", 11)) *ciphertext = ""; + /* NT loader hack starts here ! */ + + if (options.format && (strncmp(options.format, "nt", 2)==0)) { + + tmp = ldr_get_field(&line); + *ciphertext = tmp; + + if (!strncmp(*ciphertext, "NO PASSWORD", 11)) + *ciphertext = ""; + else { + *ciphertext -= 4; + strncpy(*ciphertext,"$NT$",4); + } + } + + /* NT loader hack ends here ! */ + if (source) sprintf(source, "%s:%s", uid, line); } - if (options->flags & DB_WORDS || options->shells->head) { + if (db_options->flags & DB_WORDS || db_options->shells->head) { gid = ldr_get_field(&line); do { *gecos = ldr_get_field(&line); @@ -218,13 +236,13 @@ } while (!**gecos && !strcmp(*home, "0") && !strcmp(shell, "0")); } else - if (options->groups->head) { + if (db_options->groups->head) { gid = ldr_get_field(&line); } - if (ldr_check_list(options->users, *login, uid)) return 0; - if (ldr_check_list(options->groups, gid, gid)) return 0; - if (ldr_check_shells(options->shells, shell)) return 0; + if (ldr_check_list(db_options->users, *login, uid)) return 0; + if (ldr_check_list(db_options->groups, gid, gid)) return 0; + if (ldr_check_shells(db_options->shells, shell)) return 0; if (*format) return (*format)->methods.valid(*ciphertext); @@ -286,7 +304,8 @@ struct db_password *current_pw, *last_pw; struct list_main *words; size_t pw_size, salt_size; - + extern struct fmt_main fmt_mscash; + count = ldr_split_line(&login, &ciphertext, &gecos, &home, NULL, &db->format, db->options, line); if (count <= 0) return; @@ -311,7 +330,13 @@ } for (index = 0; index < count; index++) { - piece = format->methods.split(ciphertext, index); + if (db->format == &fmt_mscash) + { + piece = (char *) mem_alloc(strlen(login) + strlen(ciphertext) + 4); + sprintf(piece, "M$%s#%s", login, ciphertext); + } + else + piece = format->methods.split(ciphertext, index); binary = format->methods.binary(piece); pw_hash = LDR_HASH_FUNC(binary); @@ -643,6 +668,7 @@ int pass, found, chars; int hash; struct db_cracked *current; + extern struct fmt_main fmt_mscash; format = NULL; count = ldr_split_line(&login, &ciphertext, &gecos, &home, @@ -654,6 +680,13 @@ if (format) { split = format->methods.split; unify = format->params.flags & FMT_SPLIT_UNIFIES_CASE; + if(format == &fmt_mscash) + { + char * ciphertext2 = (char *) mem_alloc(strlen(login) + strlen(ciphertext) + 4); + sprintf(ciphertext2, "M$%s#%s", login, ciphertext); + ciphertext = ciphertext2; + } + } else { split = fmt_default_split; count = 1; diff -ruN src/lotus5_fmt.c src-patched/lotus5_fmt.c --- src/lotus5_fmt.c 1969-12-31 19:00:00.000000000 -0500 +++ src-patched/lotus5_fmt.c 2006-02-18 17:25:21.000000000 -0500 @@ -0,0 +1,247 @@ +//original work by Jeff Fay +//some optimisations by bartavelle@bandecon.com + +#include +#include +#include "misc.h" +#include "formats.h" +#include "common.h" + +/*preprocessor constants that John The Ripper likes*/ +#define FORMAT_LABEL "lotus5" +#define FORMAT_NAME "Lotus5" +#define ALGORITHM_NAME "Lotus v5 Proprietary" +#define BENCHMARK_COMMENT "" +#define BENCHMARK_LENGTH -1 +#define PLAINTEXT_LENGTH 16 +#define CIPHERTEXT_LENGTH 32 +#define BINARY_SIZE 16 +#define SALT_SIZE 0 +#define MIN_KEYS_PER_CRYPT 1 +#define MAX_KEYS_PER_CRYPT 1 + +/*A struct used for JTR's benchmarks*/ +static struct fmt_tests tests[] = { + {"06E0A50B579AD2CD5FFDC48564627EE7", "secret"}, + {"355E98E7C7B59BD810ED845AD0FD2FC4", "password"}, + {"CD2D90E8E00D8A2A63A81F531EA8A9A3", "lotus"}, + {"69D90B46B1AC0912E5CCF858094BBBFC", "dirtydog"}, + {NULL} +}; + +static const char lotus_magic_table[256] = { + 0xbd, 0x56, 0xea, 0xf2, 0xa2, 0xf1, 0xac, 0x2a, + 0xb0, 0x93, 0xd1, 0x9c, 0x1b, 0x33, 0xfd, 0xd0, + 0x30, 0x04, 0xb6, 0xdc, 0x7d, 0xdf, 0x32, 0x4b, + 0xf7, 0xcb, 0x45, 0x9b, 0x31, 0xbb, 0x21, 0x5a, + 0x41, 0x9f, 0xe1, 0xd9, 0x4a, 0x4d, 0x9e, 0xda, + 0xa0, 0x68, 0x2c, 0xc3, 0x27, 0x5f, 0x80, 0x36, + 0x3e, 0xee, 0xfb, 0x95, 0x1a, 0xfe, 0xce, 0xa8, + 0x34, 0xa9, 0x13, 0xf0, 0xa6, 0x3f, 0xd8, 0x0c, + 0x78, 0x24, 0xaf, 0x23, 0x52, 0xc1, 0x67, 0x17, + 0xf5, 0x66, 0x90, 0xe7, 0xe8, 0x07, 0xb8, 0x60, + 0x48, 0xe6, 0x1e, 0x53, 0xf3, 0x92, 0xa4, 0x72, + 0x8c, 0x08, 0x15, 0x6e, 0x86, 0x00, 0x84, 0xfa, + 0xf4, 0x7f, 0x8a, 0x42, 0x19, 0xf6, 0xdb, 0xcd, + 0x14, 0x8d, 0x50, 0x12, 0xba, 0x3c, 0x06, 0x4e, + 0xec, 0xb3, 0x35, 0x11, 0xa1, 0x88, 0x8e, 0x2b, + 0x94, 0x99, 0xb7, 0x71, 0x74, 0xd3, 0xe4, 0xbf, + 0x3a, 0xde, 0x96, 0x0e, 0xbc, 0x0a, 0xed, 0x77, + 0xfc, 0x37, 0x6b, 0x03, 0x79, 0x89, 0x62, 0xc6, + 0xd7, 0xc0, 0xd2, 0x7c, 0x6a, 0x8b, 0x22, 0xa3, + 0x5b, 0x05, 0x5d, 0x02, 0x75, 0xd5, 0x61, 0xe3, + 0x18, 0x8f, 0x55, 0x51, 0xad, 0x1f, 0x0b, 0x5e, + 0x85, 0xe5, 0xc2, 0x57, 0x63, 0xca, 0x3d, 0x6c, + 0xb4, 0xc5, 0xcc, 0x70, 0xb2, 0x91, 0x59, 0x0d, + 0x47, 0x20, 0xc8, 0x4f, 0x58, 0xe0, 0x01, 0xe2, + 0x16, 0x38, 0xc4, 0x6f, 0x3b, 0x0f, 0x65, 0x46, + 0xbe, 0x7e, 0x2d, 0x7b, 0x82, 0xf9, 0x40, 0xb5, + 0x1d, 0x73, 0xf8, 0xeb, 0x26, 0xc7, 0x87, 0x97, + 0x25, 0x54, 0xb1, 0x28, 0xaa, 0x98, 0x9d, 0xa5, + 0x64, 0x6d, 0x7a, 0xd4, 0x10, 0x81, 0x44, 0xef, + 0x49, 0xd6, 0xae, 0x2e, 0xdd, 0x76, 0x5c, 0x2f, + 0xa7, 0x1c, 0xc9, 0x09, 0x69, 0x9a, 0x83, 0xcf, + 0x29, 0x39, 0xb9, 0xe9, 0x4c, 0xff, 0x43, 0xab, +}; + +/*Some more JTR variables*/ +static char crypt_key[BINARY_SIZE+1]; +static char saved_key[PLAINTEXT_LENGTH + 1]; + +/*Utility function to convert hex to bin */ +static void * binary (char *ciphertext) +{ + static char realcipher[BINARY_SIZE]; + int i; + for (i = 0; i < BINARY_SIZE; i++) + realcipher[i] = atoi16[ARCH_INDEX(ciphertext[i*2])]*16 + atoi16[ARCH_INDEX(ciphertext[i*2+1])]; + return ((void *) realcipher); +} + +/*Another function required by JTR: decides whether we have a valid + * ciphertext */ +static int +valid (char *ciphertext) +{ + int i; + + for (i = 0; i < CIPHERTEXT_LENGTH; i++) + if (!(((ciphertext[i] >= '0') && (ciphertext[i] <= '9')) + || ((ciphertext[i] >= 'a') && (ciphertext[i] <= 'f')) + || ((ciphertext[i] >= 'A') && (ciphertext[i] <= 'F')))) + { + return 0; + } + return 1; +} + +/*sets the value of saved_key so we can play with it*/ +static void set_key (char *key, int index) +{ + strnzcpy (saved_key, key, PLAINTEXT_LENGTH + 1); +} + +/*retrieves the saved key; used by JTR*/ +static char * get_key (int index) +{ + return saved_key; +} +static int +cmp_all (void *binary, int index) +{ + int i = 0; + while(i 0; i--) + { + temp = lotus_matrix; + for (j = 48; j > 0; j--) + { + *temp = *temp ^ lotus_magic_table[ARCH_INDEX((j + prevbyte) & 0xff)]; + prevbyte = *temp; + temp++; + } + } +} + + +/*the last public function; generates ciphertext*/ +static void crypt_all (int count) +{ + unsigned char password[PLAINTEXT_LENGTH]; + unsigned char lotus_matrix[64], *lotus_matrix1, *lotus_matrix2, *lotus_matrix3, *lotus_matrix4; + int i; + int password_length; + + password_length = strlen (saved_key); + memset (password, (PLAINTEXT_LENGTH - password_length), PLAINTEXT_LENGTH); + lotus_matrix1 = lotus_matrix; + lotus_matrix2 = lotus_matrix1 + 16; + lotus_matrix3 = lotus_matrix2 + 16; + lotus_matrix4 = lotus_matrix3 + 16; + memcpy (password, saved_key, password_length); + + memset (lotus_matrix1, 0, 16); + memcpy (lotus_matrix2, password, 16); + memcpy (lotus_matrix3, password, 16); + lotus_transform_password (lotus_matrix2, lotus_matrix4); + lotus_mix (lotus_matrix); + memcpy (lotus_matrix2, lotus_matrix4, 16); + for (i = 0; i < 16; i++) + { + lotus_matrix3[i] = lotus_matrix1[i] ^ lotus_matrix2[i]; + } + lotus_mix (lotus_matrix); + memcpy (crypt_key, lotus_matrix1, BINARY_SIZE); +} + +static int get_hash1(int index) { return (((unsigned int *)crypt_key)[0] & 0xf); } +static int get_hash2(int index) { return (((unsigned int *)crypt_key)[0] & 0xff); } +static int get_hash3(int index) { return (((unsigned int *)crypt_key)[0] & 0xfff); } +static int binary_hash1(void * binary) { return (((unsigned int *)binary)[0] & 0xf); } +static int binary_hash2(void * binary) { return (((unsigned int *)binary)[0] & 0xff); } +static int binary_hash3(void * binary) { return (((unsigned int *)binary)[0] & 0xfff); } + +/* C's version of a class specifier */ +struct fmt_main fmt_lotus5 = { + { + FORMAT_LABEL, + FORMAT_NAME, + 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 + }, { + fmt_default_init, + valid, + fmt_default_split, + binary, + fmt_default_salt, + { + binary_hash1, + binary_hash2, + binary_hash3 + }, + fmt_default_salt_hash, + set_salt, + set_key, + get_key, + fmt_default_clear_keys, + crypt_all, + { + get_hash1, + get_hash2, + get_hash3 + }, + cmp_all, + cmp_all, + cmp_exact} +}; diff -ruN src/md4.c src-patched/md4.c --- src/md4.c 1969-12-31 19:00:00.000000000 -0500 +++ src-patched/md4.c 2006-02-18 17:25:21.000000000 -0500 @@ -0,0 +1,262 @@ +/* + * This is an OpenSSL-compatible implementation of the RSA Data Security, + * Inc. MD4 Message-Digest Algorithm (RFC 1320). + * + * Written by Solar Designer in 2005, 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 "md4.h" + +/* + * The basic MD4 functions. + * + * F and G are optimized compared to their RFC 1320 definitions, with the + * optimization for F borrowed from Colin Plumb's MD5 implementation. + */ +#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) +#define G(x, y, z) (((x) & ((y) | (z))) | ((y) & (z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) + +/* + * The MD4 transformation for all three rounds. + */ +#define STEP(f, a, b, c, d, x, s) \ + (a) += f((b), (c), (d)) + (x); \ + (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); + +/* + * 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 which tolerate unaligned + * memory accesses is just an optimization. Nothing will break if it + * doesn't work. + */ +#if defined(__i386__) || defined(__vax__) +#define SET(n) \ + (*(MD4_u32plus *)&ptr[(n) * 4]) +#define GET(n) \ + SET(n) +#else +#define SET(n) \ + (ctx->block[(n)] = \ + (MD4_u32plus)ptr[(n) * 4] | \ + ((MD4_u32plus)ptr[(n) * 4 + 1] << 8) | \ + ((MD4_u32plus)ptr[(n) * 4 + 2] << 16) | \ + ((MD4_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're no alignment requirements. + */ +static void *body(MD4_CTX *ctx, void *data, unsigned long size) +{ + unsigned char *ptr; + MD4_u32plus a, b, c, d; + MD4_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), 3) + STEP(F, d, a, b, c, SET(1), 7) + STEP(F, c, d, a, b, SET(2), 11) + STEP(F, b, c, d, a, SET(3), 19) + STEP(F, a, b, c, d, SET(4), 3) + STEP(F, d, a, b, c, SET(5), 7) + STEP(F, c, d, a, b, SET(6), 11) + STEP(F, b, c, d, a, SET(7), 19) + STEP(F, a, b, c, d, SET(8), 3) + STEP(F, d, a, b, c, SET(9), 7) + STEP(F, c, d, a, b, SET(10), 11) + STEP(F, b, c, d, a, SET(11), 19) + STEP(F, a, b, c, d, SET(12), 3) + STEP(F, d, a, b, c, SET(13), 7) + STEP(F, c, d, a, b, SET(14), 11) + STEP(F, b, c, d, a, SET(15), 19) + +/* Round 2 */ + STEP(G, a, b, c, d, GET(0) + 0x5a827999, 3) + STEP(G, d, a, b, c, GET(4) + 0x5a827999, 5) + STEP(G, c, d, a, b, GET(8) + 0x5a827999, 9) + STEP(G, b, c, d, a, GET(12) + 0x5a827999, 13) + STEP(G, a, b, c, d, GET(1) + 0x5a827999, 3) + STEP(G, d, a, b, c, GET(5) + 0x5a827999, 5) + STEP(G, c, d, a, b, GET(9) + 0x5a827999, 9) + STEP(G, b, c, d, a, GET(13) + 0x5a827999, 13) + STEP(G, a, b, c, d, GET(2) + 0x5a827999, 3) + STEP(G, d, a, b, c, GET(6) + 0x5a827999, 5) + STEP(G, c, d, a, b, GET(10) + 0x5a827999, 9) + STEP(G, b, c, d, a, GET(14) + 0x5a827999, 13) + STEP(G, a, b, c, d, GET(3) + 0x5a827999, 3) + STEP(G, d, a, b, c, GET(7) + 0x5a827999, 5) + STEP(G, c, d, a, b, GET(11) + 0x5a827999, 9) + STEP(G, b, c, d, a, GET(15) + 0x5a827999, 13) + +/* Round 3 */ + STEP(H, a, b, c, d, GET(0) + 0x6ed9eba1, 3) + STEP(H, d, a, b, c, GET(8) + 0x6ed9eba1, 9) + STEP(H, c, d, a, b, GET(4) + 0x6ed9eba1, 11) + STEP(H, b, c, d, a, GET(12) + 0x6ed9eba1, 15) + STEP(H, a, b, c, d, GET(2) + 0x6ed9eba1, 3) + STEP(H, d, a, b, c, GET(10) + 0x6ed9eba1, 9) + STEP(H, c, d, a, b, GET(6) + 0x6ed9eba1, 11) + STEP(H, b, c, d, a, GET(14) + 0x6ed9eba1, 15) + STEP(H, a, b, c, d, GET(1) + 0x6ed9eba1, 3) + STEP(H, d, a, b, c, GET(9) + 0x6ed9eba1, 9) + STEP(H, c, d, a, b, GET(5) + 0x6ed9eba1, 11) + STEP(H, b, c, d, a, GET(13) + 0x6ed9eba1, 15) + STEP(H, a, b, c, d, GET(3) + 0x6ed9eba1, 3) + STEP(H, d, a, b, c, GET(11) + 0x6ed9eba1, 9) + STEP(H, c, d, a, b, GET(7) + 0x6ed9eba1, 11) + STEP(H, b, c, d, a, GET(15) + 0x6ed9eba1, 15) + + 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 MD4_Init(MD4_CTX *ctx) +{ + ctx->a = 0x67452301; + ctx->b = 0xefcdab89; + ctx->c = 0x98badcfe; + ctx->d = 0x10325476; + + ctx->lo = 0; + ctx->hi = 0; +} + +void MD4_Update(MD4_CTX *ctx, void *data, unsigned long size) +{ + MD4_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 MD4_Final(unsigned char *result, MD4_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)); +} + +void mdfour(unsigned char *out, unsigned char *in, int n) +{ + MD4_CTX ctx; + MD4_Init(&ctx); + MD4_Update(&ctx, in, n); + MD4_Final(out, &ctx); +} + +#endif diff -ruN src/md4.h src-patched/md4.h --- src/md4.h 1969-12-31 19:00:00.000000000 -0500 +++ src-patched/md4.h 2006-02-18 17:25:21.000000000 -0500 @@ -0,0 +1,29 @@ +/* + * This is an OpenSSL-compatible implementation of the RSA Data Security, + * Inc. MD4 Message-Digest Algorithm (RFC 1320). + * + * Written by Solar Designer in 2005, and placed + * in the public domain. See md4.c for more information. + */ + +#ifdef HAVE_OPENSSL +#include +#elif !defined(_MD4_H) +#define _MD4_H + +/* Any 32-bit or wider unsigned integer data type will do */ +typedef unsigned long MD4_u32plus; + +typedef struct { + MD4_u32plus lo, hi; + MD4_u32plus a, b, c, d; + unsigned char buffer[64]; + MD4_u32plus block[16]; +} MD4_CTX; + +extern void MD4_Init(MD4_CTX *ctx); +extern void MD4_Update(MD4_CTX *ctx, void *data, unsigned long size); +extern void MD4_Final(unsigned char *result, MD4_CTX *ctx); + +extern void mdfour(unsigned char *out, unsigned char *in, int n); +#endif diff -ruN src/md5.c src-patched/md5.c --- src/md5.c 1969-12-31 19:00:00.000000000 -0500 +++ src-patched/md5.c 2006-02-18 17:25:21.000000000 -0500 @@ -0,0 +1,274 @@ +/* + * This is an OpenSSL-compatible implementation of the RSA Data Security, + * Inc. MD5 Message-Digest Algorithm. + * + * 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 is optimized compared to its RFC 1321 definition 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 which tolerate unaligned + * memory accesses is just an optimization. Nothing will break if it + * doesn't work. + */ +#if defined(__i386__) || 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're 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 diff -ruN src/md5.h src-patched/md5.h --- src/md5.h 1969-12-31 19:00:00.000000000 -0500 +++ src-patched/md5.h 2006-02-18 17:25:21.000000000 -0500 @@ -0,0 +1,28 @@ +/* + * This is an OpenSSL-compatible implementation of the RSA Data Security, + * Inc. MD5 Message-Digest Algorithm. + * + * Written by Solar Designer in 2001, and placed in + * the public domain. 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 long 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 -ruN src/md5_go.c src-patched/md5_go.c --- src/md5_go.c 1969-12-31 19:00:00.000000000 -0500 +++ src-patched/md5_go.c 2006-02-18 17:25:21.000000000 -0500 @@ -0,0 +1,224 @@ +/* + * This is an OpenSSL-compatible implementation of the RSA Data Security, + * Inc. MD5 Message-Digest Algorithm. + * + * 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. + * + * This file has been modifed by David Luyer to introduce + * some performance improvements, at the cost of its general-purpose use. + * See the caveats documented above the MD5_Go() routine. + */ + +#include + +#include "common.h" +#include "md5_go.h" + +/* Output words */ +ARCH_WORD_32 MD5_out[4]; + +#if !ARCH_LITTLE_ENDIAN +/* Bit-swapped output words */ +ARCH_WORD_32 MD5_bitswapped_out[4]; +#endif + +/* + * The basic MD5 functions. + * + * F is optimized compared to its RFC 1321 definition 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 which tolerate unaligned + * memory accesses is just an optimization. Nothing will break if it + * doesn't work. + */ +#if defined(__i386__) || defined(__vax__) +#define SET(n) \ + (*(MD5_u32plus *)&ptr[(n) * 4]) +#define GET(n) \ + SET(n) +#else +static MD5_u32plus work[16]; +#define SET(n) \ + (work[(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) \ + (work[(n)]) +#endif + +/* + * This processes one or more 64-byte data blocks, but does NOT update + * the bit counters. There're no alignment requirements. + */ +static void body(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 = 0x67452301; + b = 0xefcdab89; + c = 0x98badcfe; + d = 0x10325476; + + 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); + + MD5_out[0] = a; + MD5_out[1] = b; + MD5_out[2] = c; + MD5_out[3] = d; +} + +/* Single-pass MD5 of a string of up to 2^11 bytes + * + * Caveats: + * - String length limited to 2^11 bytes (can be easily increased + * by adding data[process-6] = len >> 13 etc). + * - Requires scratch space at the end of the string (up to 73 bytes). + * - String will need re-terminating after calling this rountine. + */ +void MD5_Go(unsigned char *data, unsigned int len) +{ + int process = (len + 73) & ~0x3f; + + data[len] = 0x80; + memset(&data[len+1], 0, process - len - 1); + data[process-8] = len << 3; + data[process-7] = len >> 5; + body(data, process); + +#if !ARCH_LITTLE_ENDIAN + MD5_bitswapped_out[0] = (MD5_out[0] << 24) | + (MD5_out[0] >> 24) | + ((MD5_out[0] << 8) & 0x00ff0000) | + ((MD5_out[0] >> 8) & 0x0000ff00); + MD5_bitswapped_out[1] = (MD5_out[1] << 24) | + (MD5_out[1] >> 24) | + ((MD5_out[1] << 8) & 0x00ff0000) | + ((MD5_out[1] >> 8) & 0x0000ff00); + MD5_bitswapped_out[2] = (MD5_out[2] << 24) | + (MD5_out[2] >> 24) | + ((MD5_out[2] << 8) & 0x00ff0000) | + ((MD5_out[2] >> 8) & 0x0000ff00); + MD5_bitswapped_out[3] = (MD5_out[3] << 24) | + (MD5_out[3] >> 24) | + ((MD5_out[3] << 8) & 0x00ff0000) | + ((MD5_out[3] >> 8) & 0x0000ff00); +#endif +} diff -ruN src/md5_go.h src-patched/md5_go.h --- src/md5_go.h 1969-12-31 19:00:00.000000000 -0500 +++ src-patched/md5_go.h 2006-02-18 17:25:21.000000000 -0500 @@ -0,0 +1,16 @@ +/* + * This is an OpenSSL-compatible implementation of the RSA Data Security, + * Inc. MD5 Message-Digest Algorithm. + * + * Written by Solar Designer in 2001, and placed in + * the public domain. See md5.c for more information. + */ + +#if !defined(_MD5_GO_H) +#define _MD5_GO_H + +/* Any 32-bit or wider unsigned integer data type will do */ +typedef unsigned long MD5_u32plus; +extern void MD5_Go(unsigned char *data, unsigned int len/*, unsigned char *result*/); + +#endif diff -ruN src/mscash_fmt.c src-patched/mscash_fmt.c --- src/mscash_fmt.c 1969-12-31 19:00:00.000000000 -0500 +++ src-patched/mscash_fmt.c 2006-02-18 17:25:21.000000000 -0500 @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2004 Simon Marechal + * bartavelle@bandecon.com + * + * This is a plugin that adds Microsoft credential's cache hashing algorithm, + * MS Cache Hash, a.k.a. MS Cash. This patch is invasive because john doesn't + * support the use of the username easily within the current framework. + * In order to get those hashes, use the CacheDump utility : + * + * http://www.cr0.net:8040/misc/cachedump.html + * + * It uses + * - smbencrypt.c Copyright (C) Andrew Tridgell 1997-1998 + * - md4.c, md4.h Copyright (C) Solar Designer + * + */ + +#include + +#include "arch.h" +#include "misc.h" +#include "common.h" +#include "formats.h" +#include "md4.h" + +#define FORMAT_LABEL "mscash" +#define FORMAT_NAME "M$ Cache Hash" +#define ALGORITHM_NAME "mscash" + +#define BENCHMARK_COMMENT "" +#define BENCHMARK_LENGTH -1 + +#define PLAINTEXT_LENGTH 32 + +#define BINARY_SIZE 16 +//max username size is 64, double for unicode "optimization" +#define SALT_SIZE (64*2) +#define CIPHERTEXT_LENGTH (BINARY_SIZE*2 + SALT_SIZE) + +#define MIN_KEYS_PER_CRYPT 1 +#define MAX_KEYS_PER_CRYPT 1 + +static struct fmt_tests mscash_tests[] = { + {"M$test1#64cd29e36a8431a2b111378564a10631", "test1" }, + {"M$test2#ab60bdb4493822b175486810ac2abe63", "test2" }, + {"M$test3#14dd041848e12fc48c0aa7a416a4a00c", "test3" }, + {"M$test4#b945d24866af4b01a6d89b9d932a153c", "test4" }, + {NULL} +}; + +static char saved_key[PLAINTEXT_LENGTH + 1]; +//stores the ciphertext for value currently being tested +static char crypt_key[BINARY_SIZE+1]; + +static int salt_length; //the length of the current username +static unsigned short cur_salt[SALT_SIZE/2]; //current salt + +extern void E_md4hash(unsigned char *passwd, unsigned char *p16); + +static int valid(char *ciphertext) +{ + int i; + int l; + + /* + * 2 cases + * 1 - it comes from the disk, and does not have M$ + salt + * 2 - it comes from memory, and has got M$ + salt + # + blah + */ + + if (!memcmp(ciphertext, "M$", 2)) + { + l = strlen(ciphertext) - PLAINTEXT_LENGTH; + if(ciphertext[l-1]!='#') + return 0; + } + else + { + if(strlen(ciphertext)!=PLAINTEXT_LENGTH) + return 0; + l = 0; + } + for (i = l; i < l + PLAINTEXT_LENGTH; i++){ + if (!( (('0' <= ciphertext[i])&&(ciphertext[i] <= '9')) || + (('a' <= ciphertext[i])&&(ciphertext[i] <= 'f')) + || (('A' <= ciphertext[i])&&(ciphertext[i] <= 'F')))) + return 0; + } + + return 1; +} + +//salt is unicode, so let's say it's unsigned short +static void mscash_set_salt(void *salt) { + salt_length = 0; + while( ((unsigned char *)salt)[salt_length]!='#' ) + { +#if ARCH_LITTLE_ENDIAN + cur_salt[salt_length] = ((unsigned char *)salt)[salt_length]; +#else + cur_salt[salt_length] = ((unsigned char *)salt)[salt_length] << 8; +#endif + salt_length ++; + } + cur_salt[salt_length] = 0; +} + +static void mscash_set_key(char *key, int index) { + strnzcpy(saved_key, key, PLAINTEXT_LENGTH+1); +} + +static char *mscash_get_key(int index) { + return saved_key; +} + +static int mscash_cmp_all(void *binary, int index) { + int i=0; + while(i to + * use a modified (faster) version of Solar Designer's + * md5 implementation. + */ + +#include + +#include "arch.h" +#include "misc.h" +#include "common.h" +#include "formats.h" +#include "md5_go.h" + +#if !ARCH_LITTLE_ENDIAN +#define MD5_out MD5_bitswapped_out +#endif + +extern ARCH_WORD_32 MD5_out[4]; + +#define FORMAT_LABEL "raw-md5" +#define FORMAT_NAME "Raw MD5" +#define ALGORITHM_NAME "raw-md5" + +#define BENCHMARK_COMMENT "" +#define BENCHMARK_LENGTH -1 + +#define PLAINTEXT_LENGTH 32 +#define CIPHERTEXT_LENGTH 32 + +#define BINARY_SIZE 16 +#define SALT_SIZE 0 + +#define MIN_KEYS_PER_CRYPT 1 +#define MAX_KEYS_PER_CRYPT 1 + +static struct fmt_tests rawmd5_tests[] = { + {"5a105e8b9d40e1329780d62ea2265d8a", "test1"}, + {"ad0234829205b9033196ba818f7a872b", "test2"}, + {"8ad8757baa8564dc136c1e07507f4a98", "test3"}, + {"86985e105f79b95d6bc918fb45ec7727", "test4"}, + {NULL} +}; + +static char saved_key[PLAINTEXT_LENGTH + 1 + 128 /* MD5 scratch space */]; +int saved_key_len; + +static int valid(char *ciphertext) +{ + int i; + + if (strlen(ciphertext) != CIPHERTEXT_LENGTH) return 0; + for (i = 0; i < CIPHERTEXT_LENGTH; i++){ + if (!( (('0' <= ciphertext[i])&&(ciphertext[i] <= '9')) || + (('a' <= ciphertext[i])&&(ciphertext[i] <= 'f')) )) + return 0; + } + return 1; +} + +static void rawmd5_set_salt(void *salt) { } + +static void rawmd5_set_key(char *key, int index) { + strnzcpy(saved_key, key, PLAINTEXT_LENGTH+1); + saved_key_len = strlen(saved_key); +} + +static char *rawmd5_get_key(int index) { + saved_key[saved_key_len] = '\0'; + return saved_key; +} + +static int rawmd5_cmp_all(void *binary, int index) { + /* used for cmp_all and cmp_one */ + return !memcmp(binary, MD5_out, BINARY_SIZE); +} + +static int rawmd5_cmp_exact(char *source, int count){ + /* only used if cmp_all matches */ + return (1); +} + +static void rawmd5_crypt_all(int count) { + /* get plaintext input in saved_key put it into ciphertext MD5_out */ + MD5_Go( (unsigned char *)saved_key, saved_key_len ); +} + +static void * rawmd5_binary(char *ciphertext) +{ + static char realcipher[BINARY_SIZE]; + int i; + + for(i=0;i + +#include "arch.h" +#include "misc.h" +#include "common.h" +#include "formats.h" +#include "sha.h" + +#define FORMAT_LABEL "raw-sha1" +#define FORMAT_NAME "Raw SHA1" +#ifdef MMX_COEF +#if (MMX_COEF == 2) +#define ALGORITHM_NAME "raw-sha1 MMX" +#else +#define ALGORITHM_NAME "raw-sha1 SSE2" +#endif +#else +#define ALGORITHM_NAME "raw-sha1" +#endif + +#ifdef MMX_TYPE +#define BENCHMARK_COMMENT MMX_TYPE +#else +#define BENCHMARK_COMMENT "" +#endif +#define BENCHMARK_LENGTH -1 + +#define PLAINTEXT_LENGTH 32 +#define CIPHERTEXT_LENGTH 40 + +#define BINARY_SIZE 20 +#define SALT_SIZE 0 + +#ifdef MMX_COEF +#define MIN_KEYS_PER_CRYPT MMX_COEF +#define MAX_KEYS_PER_CRYPT MMX_COEF +//#define GETPOS(i, index) ( (index)*4 + (i& (0xffffffff-3) )*MMX_COEF + ((i)&3) ) //std getpos +#define GETPOS(i, index) ( (index)*4 + (i& (0xffffffff-3) )*MMX_COEF + (3-((i)&3)) ) //for endianity conversion +#else +#define MIN_KEYS_PER_CRYPT 1 +#define MAX_KEYS_PER_CRYPT 1 +#endif + +static struct fmt_tests rawsha1_tests[] = { + {"A9993E364706816ABA3E25717850C26C9CD0D89D", "abc"}, + {"2fbf0eba37de1d1d633bc1ed943b907f9b360d4c", "azertyuiop1"}, + {"f879f8090e92232ed07092ebed6dc6170457a21d", "azertyuiop2"}, + {"1813c12f25e64931f3833b26e999e26e81f9ad24", "azertyuiop3"}, + {NULL} +}; + +#ifdef MMX_COEF +static char saved_key[PLAINTEXT_LENGTH*MMX_COEF*2 + 1] __attribute__ ((aligned(16))); +static char crypt_key[80*4*MMX_COEF+1] __attribute__ ((aligned(16))); +unsigned long total_len; +unsigned char out[PLAINTEXT_LENGTH]; +#else +static char saved_key[PLAINTEXT_LENGTH + 1]; +static char crypt_key[BINARY_SIZE+1]; +static SHA_CTX ctx; +#endif + +static int valid(char *ciphertext) +{ + int i; + + if (strlen(ciphertext) != CIPHERTEXT_LENGTH) return 0; + for (i = 0; i < CIPHERTEXT_LENGTH; i++){ + if (!( (('0' <= ciphertext[i])&&(ciphertext[i] <= '9')) || + (('a' <= ciphertext[i])&&(ciphertext[i] <= 'f')) + || (('A' <= ciphertext[i])&&(ciphertext[i] <= 'F')))) + return 0; + } + return 1; +} + +static void rawsha1_set_salt(void *salt) { } + +static void rawsha1_init(void) +{ +#ifdef MMX_COEF + memset(saved_key, 0, PLAINTEXT_LENGTH*MMX_COEF*2 + 1); +#endif +} + +static void rawsha1_set_key(char *key, int index) { +#ifdef MMX_COEF + int len; + int i; + + if(index==0) + { + total_len = 0; + memset(saved_key, 0, PLAINTEXT_LENGTH*MMX_COEF); + } + len = strlen(key); + if(len>PLAINTEXT_LENGTH) + len = PLAINTEXT_LENGTH; + + total_len += len << ( ( (32/MMX_COEF) * index ) ); + for(i=0;i> (((32/MMX_COEF)*(index)))) & 0xff; + for(i=0;i 3) + && ( ((unsigned long *)binary)[i] != ((unsigned long *)crypt_key)[i*MMX_COEF+2]) + && ( ((unsigned long *)binary)[i] != ((unsigned long *)crypt_key)[i*MMX_COEF+3]) +#endif + ) + return 0; + i++; + } +#else + while(i +#include +#undef SHA_0 +#define SHA_1 +#include "sha.h" +#include "sha_locl.h" + +char *SHA1_version="SHA1 part of SSLeay 0.8.2b 08-Jan-1998"; + +/* Implemented from SHA-1 document - The Secure Hash Algorithm + */ + +#define INIT_DATA_h0 (unsigned long)0x67452301L +#define INIT_DATA_h1 (unsigned long)0xefcdab89L +#define INIT_DATA_h2 (unsigned long)0x98badcfeL +#define INIT_DATA_h3 (unsigned long)0x10325476L +#define INIT_DATA_h4 (unsigned long)0xc3d2e1f0L + +#define K_00_19 0x5a827999L +#define K_20_39 0x6ed9eba1L +#define K_40_59 0x8f1bbcdcL +#define K_60_79 0xca62c1d6L + +#ifndef NOPROTO +# ifdef SHA1_ASM + void sha1_block_x86(SHA_CTX *c, register unsigned long *p, int num); +# define sha1_block sha1_block_x86 +# else + void sha1_block(SHA_CTX *c, register unsigned long *p, int num); +# endif +#else +# ifdef SHA1_ASM + void sha1_block_x86(); +# define sha1_block sha1_block_x86 +# else + void sha1_block(); +# endif +#endif + +#if defined(L_ENDIAN) && defined(SHA1_ASM) +# define M_c2nl c2l +# define M_p_c2nl p_c2l +# define M_c2nl_p c2l_p +# define M_p_c2nl_p p_c2l_p +# define M_nl2c l2c +#else +# define M_c2nl c2nl +# define M_p_c2nl p_c2nl +# define M_c2nl_p c2nl_p +# define M_p_c2nl_p p_c2nl_p +# define M_nl2c nl2c +#endif + +void SHA1_Init(c) +SHA_CTX *c; + { + c->h0=INIT_DATA_h0; + c->h1=INIT_DATA_h1; + c->h2=INIT_DATA_h2; + c->h3=INIT_DATA_h3; + c->h4=INIT_DATA_h4; + c->Nl=0; + c->Nh=0; + c->num=0; + } + +void SHA1_Update(c, data, len) +SHA_CTX *c; +register unsigned char *data; +unsigned long len; + { + register ULONG *p; + int ew,ec,sw,sc; + ULONG l; + + if (len == 0) return; + + l=(c->Nl+(len<<3))&0xffffffffL; + if (l < c->Nl) /* overflow */ + c->Nh++; + c->Nh+=(len>>29); + c->Nl=l; + + if (c->num != 0) + { + p=c->data; + sw=c->num>>2; + sc=c->num&0x03; + + if ((c->num+len) >= SHA_CBLOCK) + { + l= p[sw]; + M_p_c2nl(data,l,sc); + p[sw++]=l; + for (; swnum); + + sha1_block(c,p,64); + c->num=0; + /* drop through and do the rest */ + } + else + { + c->num+=(int)len; + if ((sc+len) < 4) /* ugly, add char's to a word */ + { + l= p[sw]; + M_p_c2nl_p(data,l,sc,len); + p[sw]=l; + } + else + { + ew=(c->num>>2); + ec=(c->num&0x03); + l= p[sw]; + M_p_c2nl(data,l,sc); + p[sw++]=l; + for (; sw < ew; sw++) + { M_c2nl(data,l); p[sw]=l; } + if (ec) + { + M_c2nl_p(data,l,ec); + p[sw]=l; + } + } + return; + } + } + /* We can only do the following code for assember, the reason + * being that the sha1_block 'C' version changes the values + * in the 'data' array. The assember code avoids this and + * copies it to a local array. I should be able to do this for + * the C version as well.... + */ +#if 1 +#if defined(B_ENDIAN) || defined(SHA1_ASM) + if ((((unsigned int)data)%sizeof(ULONG)) == 0) + { + sw=len/SHA_CBLOCK; + if (sw) + { + sw*=SHA_CBLOCK; + sha1_block(c,(ULONG *)data,sw); + data+=sw; + len-=sw; + } + } +#endif +#endif + /* we now can process the input data in blocks of SHA_CBLOCK + * chars and save the leftovers to c->data. */ + p=c->data; + while (len >= SHA_CBLOCK) + { +#if defined(B_ENDIAN) || defined(L_ENDIAN) + if (p != (unsigned long *)data) + memcpy(p,data,SHA_CBLOCK); + data+=SHA_CBLOCK; +# ifdef L_ENDIAN +# ifndef SHA1_ASM /* Will not happen */ + for (sw=(SHA_LBLOCK/4); sw; sw--) + { + Endian_Reverse32(p[0]); + Endian_Reverse32(p[1]); + Endian_Reverse32(p[2]); + Endian_Reverse32(p[3]); + p+=4; + } + p=c->data; +# endif +# endif +#else + for (sw=(SHA_BLOCK/4); sw; sw--) + { + M_c2nl(data,l); *(p++)=l; + M_c2nl(data,l); *(p++)=l; + M_c2nl(data,l); *(p++)=l; + M_c2nl(data,l); *(p++)=l; + } + p=c->data; +#endif + sha1_block(c,p,64); + len-=SHA_CBLOCK; + } + ec=(int)len; + c->num=ec; + ew=(ec>>2); + ec&=0x03; + + for (sw=0; sw < ew; sw++) + { M_c2nl(data,l); p[sw]=l; } + M_c2nl_p(data,l,ec); + p[sw]=l; + } + +void SHA1_Transform(c,b) +SHA_CTX *c; +unsigned char *b; + { + ULONG p[16]; +#ifndef B_ENDIAN + ULONG *q; + int i; +#endif + +#if defined(B_ENDIAN) || defined(L_ENDIAN) + memcpy(p,b,64); +#ifdef L_ENDIAN + q=p; + for (i=(SHA_LBLOCK/4); i; i--) + { + Endian_Reverse32(q[0]); + Endian_Reverse32(q[1]); + Endian_Reverse32(q[2]); + Endian_Reverse32(q[3]); + q+=4; + } +#endif +#else + q=p; + for (i=(SHA_LBLOCK/4); i; i--) + { + ULONG l; + c2nl(b,l); *(q++)=l; + c2nl(b,l); *(q++)=l; + c2nl(b,l); *(q++)=l; + c2nl(b,l); *(q++)=l; + } +#endif + sha1_block(c,p,64); + } + +#ifndef SHA1_ASM + +void sha1_block(c, W, num) +SHA_CTX *c; +register unsigned long *W; +int num; + { + register ULONG A,B,C,D,E,T; + ULONG X[16]; + + A=c->h0; + B=c->h1; + C=c->h2; + D=c->h3; + E=c->h4; + + for (;;) + { + BODY_00_15( 0,A,B,C,D,E,T,W); + BODY_00_15( 1,T,A,B,C,D,E,W); + BODY_00_15( 2,E,T,A,B,C,D,W); + BODY_00_15( 3,D,E,T,A,B,C,W); + BODY_00_15( 4,C,D,E,T,A,B,W); + BODY_00_15( 5,B,C,D,E,T,A,W); + BODY_00_15( 6,A,B,C,D,E,T,W); + BODY_00_15( 7,T,A,B,C,D,E,W); + BODY_00_15( 8,E,T,A,B,C,D,W); + BODY_00_15( 9,D,E,T,A,B,C,W); + BODY_00_15(10,C,D,E,T,A,B,W); + BODY_00_15(11,B,C,D,E,T,A,W); + BODY_00_15(12,A,B,C,D,E,T,W); + BODY_00_15(13,T,A,B,C,D,E,W); + BODY_00_15(14,E,T,A,B,C,D,W); + BODY_00_15(15,D,E,T,A,B,C,W); + BODY_16_19(16,C,D,E,T,A,B,W,W,W,W); + BODY_16_19(17,B,C,D,E,T,A,W,W,W,W); + BODY_16_19(18,A,B,C,D,E,T,W,W,W,W); + BODY_16_19(19,T,A,B,C,D,E,W,W,W,X); + + BODY_20_31(20,E,T,A,B,C,D,W,W,W,X); + BODY_20_31(21,D,E,T,A,B,C,W,W,W,X); + BODY_20_31(22,C,D,E,T,A,B,W,W,W,X); + BODY_20_31(23,B,C,D,E,T,A,W,W,W,X); + BODY_20_31(24,A,B,C,D,E,T,W,W,X,X); + BODY_20_31(25,T,A,B,C,D,E,W,W,X,X); + BODY_20_31(26,E,T,A,B,C,D,W,W,X,X); + BODY_20_31(27,D,E,T,A,B,C,W,W,X,X); + BODY_20_31(28,C,D,E,T,A,B,W,W,X,X); + BODY_20_31(29,B,C,D,E,T,A,W,W,X,X); + BODY_20_31(30,A,B,C,D,E,T,W,X,X,X); + BODY_20_31(31,T,A,B,C,D,E,W,X,X,X); + BODY_32_39(32,E,T,A,B,C,D,X); + BODY_32_39(33,D,E,T,A,B,C,X); + BODY_32_39(34,C,D,E,T,A,B,X); + BODY_32_39(35,B,C,D,E,T,A,X); + BODY_32_39(36,A,B,C,D,E,T,X); + BODY_32_39(37,T,A,B,C,D,E,X); + BODY_32_39(38,E,T,A,B,C,D,X); + BODY_32_39(39,D,E,T,A,B,C,X); + + BODY_40_59(40,C,D,E,T,A,B,X); + BODY_40_59(41,B,C,D,E,T,A,X); + BODY_40_59(42,A,B,C,D,E,T,X); + BODY_40_59(43,T,A,B,C,D,E,X); + BODY_40_59(44,E,T,A,B,C,D,X); + BODY_40_59(45,D,E,T,A,B,C,X); + BODY_40_59(46,C,D,E,T,A,B,X); + BODY_40_59(47,B,C,D,E,T,A,X); + BODY_40_59(48,A,B,C,D,E,T,X); + BODY_40_59(49,T,A,B,C,D,E,X); + BODY_40_59(50,E,T,A,B,C,D,X); + BODY_40_59(51,D,E,T,A,B,C,X); + BODY_40_59(52,C,D,E,T,A,B,X); + BODY_40_59(53,B,C,D,E,T,A,X); + BODY_40_59(54,A,B,C,D,E,T,X); + BODY_40_59(55,T,A,B,C,D,E,X); + BODY_40_59(56,E,T,A,B,C,D,X); + BODY_40_59(57,D,E,T,A,B,C,X); + BODY_40_59(58,C,D,E,T,A,B,X); + BODY_40_59(59,B,C,D,E,T,A,X); + + BODY_60_79(60,A,B,C,D,E,T,X); + BODY_60_79(61,T,A,B,C,D,E,X); + BODY_60_79(62,E,T,A,B,C,D,X); + BODY_60_79(63,D,E,T,A,B,C,X); + BODY_60_79(64,C,D,E,T,A,B,X); + BODY_60_79(65,B,C,D,E,T,A,X); + BODY_60_79(66,A,B,C,D,E,T,X); + BODY_60_79(67,T,A,B,C,D,E,X); + BODY_60_79(68,E,T,A,B,C,D,X); + BODY_60_79(69,D,E,T,A,B,C,X); + BODY_60_79(70,C,D,E,T,A,B,X); + BODY_60_79(71,B,C,D,E,T,A,X); + BODY_60_79(72,A,B,C,D,E,T,X); + BODY_60_79(73,T,A,B,C,D,E,X); + BODY_60_79(74,E,T,A,B,C,D,X); + BODY_60_79(75,D,E,T,A,B,C,X); + BODY_60_79(76,C,D,E,T,A,B,X); + BODY_60_79(77,B,C,D,E,T,A,X); + BODY_60_79(78,A,B,C,D,E,T,X); + BODY_60_79(79,T,A,B,C,D,E,X); + + c->h0=(c->h0+E)&0xffffffffL; + c->h1=(c->h1+T)&0xffffffffL; + c->h2=(c->h2+A)&0xffffffffL; + c->h3=(c->h3+B)&0xffffffffL; + c->h4=(c->h4+C)&0xffffffffL; + + num-=64; + if (num <= 0) break; + + A=c->h0; + B=c->h1; + C=c->h2; + D=c->h3; + E=c->h4; + + W+=16; + } + } +#endif + +void SHA1_Final(md, c) +unsigned char *md; +SHA_CTX *c; + { + register int i,j; + register ULONG l; + register ULONG *p; + static unsigned char end[4]={0x80,0x00,0x00,0x00}; + unsigned char *cp=end; + + /* c->num should definitly have room for at least one more byte. */ + p=c->data; + j=c->num; + i=j>>2; +#ifdef PURIFY + if ((j&0x03) == 0) p[i]=0; +#endif + l=p[i]; + M_p_c2nl(cp,l,j&0x03); + p[i]=l; + i++; + /* i is the next 'undefined word' */ + if (c->num >= SHA_LAST_BLOCK) + { + for (; iNh; + p[SHA_LBLOCK-1]=c->Nl; +#if defined(L_ENDIAN) && defined(SHA1_ASM) + Endian_Reverse32(p[SHA_LBLOCK-2]); + Endian_Reverse32(p[SHA_LBLOCK-1]); +#endif + sha1_block(c,p,64); + cp=md; + l=c->h0; nl2c(l,cp); + l=c->h1; nl2c(l,cp); + l=c->h2; nl2c(l,cp); + l=c->h3; nl2c(l,cp); + l=c->h4; nl2c(l,cp); + + /* clear stuff, sha1_block may be leaving some stuff on the stack + * but I'm not worried :-) */ + c->num=0; +/* memset((char *)&c,0,sizeof(c));*/ + } + diff -ruN src/sha_locl.h src-patched/sha_locl.h --- src/sha_locl.h 1969-12-31 19:00:00.000000000 -0500 +++ src-patched/sha_locl.h 2006-02-18 17:25:21.000000000 -0500 @@ -0,0 +1,246 @@ +/* crypto/sha/sha_locl.h */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include + +#ifdef undef +/* one or the other needs to be defined */ +#ifndef SHA_1 /* FIPE 180-1 */ +#define SHA_0 /* FIPS 180 */ +#endif +#endif + +#define ULONG unsigned long +#define UCHAR unsigned char +#define UINT unsigned int + +#ifdef NOCONST +#define const +#endif + +#undef c2nl +#define c2nl(c,l) (l =(((unsigned long)(*((c)++)))<<24), \ + l|=(((unsigned long)(*((c)++)))<<16), \ + l|=(((unsigned long)(*((c)++)))<< 8), \ + l|=(((unsigned long)(*((c)++))) )) + +#undef p_c2nl +#define p_c2nl(c,l,n) { \ + switch (n) { \ + case 0: l =((unsigned long)(*((c)++)))<<24; \ + case 1: l|=((unsigned long)(*((c)++)))<<16; \ + case 2: l|=((unsigned long)(*((c)++)))<< 8; \ + case 3: l|=((unsigned long)(*((c)++))); \ + } \ + } + +#undef c2nl_p +/* NOTE the pointer is not incremented at the end of this */ +#define c2nl_p(c,l,n) { \ + l=0; \ + (c)+=n; \ + switch (n) { \ + case 3: l =((unsigned long)(*(--(c))))<< 8; \ + case 2: l|=((unsigned long)(*(--(c))))<<16; \ + case 1: l|=((unsigned long)(*(--(c))))<<24; \ + } \ + } + +#undef p_c2nl_p +#define p_c2nl_p(c,l,sc,len) { \ + switch (sc) \ + { \ + case 0: l =((unsigned long)(*((c)++)))<<24; \ + if (--len == 0) break; \ + case 1: l|=((unsigned long)(*((c)++)))<<16; \ + if (--len == 0) break; \ + case 2: l|=((unsigned long)(*((c)++)))<< 8; \ + } \ + } + +#undef nl2c +#define nl2c(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff)) + +#undef c2l +#define c2l(c,l) (l =(((unsigned long)(*((c)++))) ), \ + l|=(((unsigned long)(*((c)++)))<< 8), \ + l|=(((unsigned long)(*((c)++)))<<16), \ + l|=(((unsigned long)(*((c)++)))<<24)) + +#undef p_c2l +#define p_c2l(c,l,n) { \ + switch (n) { \ + case 0: l =((unsigned long)(*((c)++))); \ + case 1: l|=((unsigned long)(*((c)++)))<< 8; \ + case 2: l|=((unsigned long)(*((c)++)))<<16; \ + case 3: l|=((unsigned long)(*((c)++)))<<24; \ + } \ + } + +#undef c2l_p +/* NOTE the pointer is not incremented at the end of this */ +#define c2l_p(c,l,n) { \ + l=0; \ + (c)+=n; \ + switch (n) { \ + case 3: l =((unsigned long)(*(--(c))))<<16; \ + case 2: l|=((unsigned long)(*(--(c))))<< 8; \ + case 1: l|=((unsigned long)(*(--(c)))); \ + } \ + } + +#undef p_c2l_p +#define p_c2l_p(c,l,sc,len) { \ + switch (sc) \ + { \ + case 0: l =((unsigned long)(*((c)++))); \ + if (--len == 0) break; \ + case 1: l|=((unsigned long)(*((c)++)))<< 8; \ + if (--len == 0) break; \ + case 2: l|=((unsigned long)(*((c)++)))<<16; \ + } \ + } + +#undef l2c +#define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>>24)&0xff)) + +#undef ROTATE +#if defined(WIN32) +#define ROTATE(a,n) _lrotl(a,n) +#else +#define ROTATE(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n)))) +#endif + +/* A nice byte order reversal from Wei Dai */ +#if defined(WIN32) +/* 5 instructions with rotate instruction, else 9 */ +#define Endian_Reverse32(a) \ + { \ + unsigned long l=(a); \ + (a)=((ROTATE(l,8)&0x00FF00FF)|(ROTATE(l,24)&0xFF00FF00)); \ + } +#else +/* 6 instructions with rotate instruction, else 8 */ +#define Endian_Reverse32(a) \ + { \ + unsigned long l=(a); \ + l=(((l&0xFF00FF00)>>8L)|((l&0x00FF00FF)<<8L)); \ + (a)=ROTATE(l,16L); \ + } +#endif + +/* As pointed out by Wei Dai , F() below can be + * simplified to the code in F_00_19. Wei attributes these optimisations + * to Peter Gutmann's SHS code, and he attributes it to Rich Schroeppel. + * #define F(x,y,z) (((x) & (y)) | ((~(x)) & (z))) + * I've just become aware of another tweak to be made, again from Wei Dai, + * in F_40_59, (x&a)|(y&a) -> (x|y)&a + */ +#define F_00_19(b,c,d) ((((c) ^ (d)) & (b)) ^ (d)) +#define F_20_39(b,c,d) ((b) ^ (c) ^ (d)) +#define F_40_59(b,c,d) (((b) & (c)) | (((b)|(c)) & (d))) +#define F_60_79(b,c,d) F_20_39(b,c,d) + +#ifdef SHA_0 +#undef Xupdate +#define Xupdate(a,i,ia,ib,ic,id) X[(i)&0x0f]=(a)=\ + (ia[(i)&0x0f]^ib[((i)+2)&0x0f]^ic[((i)+8)&0x0f]^id[((i)+13)&0x0f]); +#endif +#ifdef SHA_1 +#undef Xupdate +#define Xupdate(a,i,ia,ib,ic,id) (a)=\ + (ia[(i)&0x0f]^ib[((i)+2)&0x0f]^ic[((i)+8)&0x0f]^id[((i)+13)&0x0f]);\ + X[(i)&0x0f]=(a)=ROTATE((a),1); +#endif + +#define BODY_00_15(i,a,b,c,d,e,f,xa) \ + (f)=xa[i]+(e)+K_00_19+ROTATE((a),5)+F_00_19((b),(c),(d)); \ + (b)=ROTATE((b),30); + +#define BODY_16_19(i,a,b,c,d,e,f,xa,xb,xc,xd) \ + Xupdate(f,i,xa,xb,xc,xd); \ + (f)+=(e)+K_00_19+ROTATE((a),5)+F_00_19((b),(c),(d)); \ + (b)=ROTATE((b),30); + +#define BODY_20_31(i,a,b,c,d,e,f,xa,xb,xc,xd) \ + Xupdate(f,i,xa,xb,xc,xd); \ + (f)+=(e)+K_20_39+ROTATE((a),5)+F_20_39((b),(c),(d)); \ + (b)=ROTATE((b),30); + +#define BODY_32_39(i,a,b,c,d,e,f,xa) \ + Xupdate(f,i,xa,xa,xa,xa); \ + (f)+=(e)+K_20_39+ROTATE((a),5)+F_20_39((b),(c),(d)); \ + (b)=ROTATE((b),30); + +#define BODY_40_59(i,a,b,c,d,e,f,xa) \ + Xupdate(f,i,xa,xa,xa,xa); \ + (f)+=(e)+K_40_59+ROTATE((a),5)+F_40_59((b),(c),(d)); \ + (b)=ROTATE((b),30); + +#define BODY_60_79(i,a,b,c,d,e,f,xa) \ + Xupdate(f,i,xa,xa,xa,xa); \ + (f)=X[(i)&0x0f]+(e)+K_60_79+ROTATE((a),5)+F_60_79((b),(c),(d)); \ + (b)=ROTATE((b),30); + diff -ruN src/smbencrypt.c src-patched/smbencrypt.c --- src/smbencrypt.c 1969-12-31 19:00:00.000000000 -0500 +++ src-patched/smbencrypt.c 2006-02-18 17:25:21.000000000 -0500 @@ -0,0 +1,106 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + SMB parameters and setup + Copyright (C) Andrew Tridgell 1992-1998 + Modified by Jeremy Allison 1995. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +#include +#include + + +#ifndef uchar +#define uchar unsigned char +#endif + +#if !defined(uint16) && !defined(HAVE_UINT16_FROM_RPC_RPC_H) +#if (SIZEOF_SHORT == 4) +#define uint16 __ERROR___CANNOT_DETERMINE_TYPE_FOR_INT16; +#else /* SIZEOF_SHORT != 4 */ +#define uint16 unsigned short +#endif /* SIZEOF_SHORT != 4 */ +#endif + +#if !defined(int16) && !defined(HAVE_INT16_FROM_RPC_RPC_H) +#if (SIZEOF_SHORT == 4) +#define int16 __ERROR___CANNOT_DETERMINE_TYPE_FOR_INT16; +#else /* SIZEOF_SHORT != 4 */ +#define int16 short +#endif /* SIZEOF_SHORT != 4 */ +#endif + +#include "byteorder.h" + +extern void mdfour(unsigned char *out, unsigned char *in, int n); + + +/* Routines for Windows NT MD4 Hash functions. */ +static int _my_wcslen(int16 *str) +{ + int len = 0; + while(*str++ != 0) + len++; + return len; +} + +/* + * Convert a string into an NT UNICODE string. + * Note that regardless of processor type + * this must be in intel (little-endian) + * format. + */ + +int _my_mbstowcs(int16 *dst, uchar *src, int len) +{ + int i; + int16 val; + + for(i = 0; i < len; i++) { + val = *src; + SSVAL(dst,0,val); + dst++; + src++; + if(val == 0) + break; + } + return i; +} + +/* + * Creates the MD4 Hash of the users password in NT UNICODE. + */ + +void E_md4hash(uchar *passwd, uchar *p16) +{ + int len; + int16 wpwd[129]; + + /* Password cannot be longer than 128 characters */ + len = strlen((char *)passwd); + if(len > 128) + len = 128; + /* Password must be converted to NT unicode */ + _my_mbstowcs(wpwd, passwd, len); + wpwd[len] = 0; /* Ensure string is null terminated */ + /* Calculate length in bytes */ + len = _my_wcslen(wpwd) * sizeof(int16); + + mdfour(p16, (unsigned char *)wpwd, len); +} + diff -ruN src/undrop.c src-patched/undrop.c --- src/undrop.c 1969-12-31 19:00:00.000000000 -0500 +++ src-patched/undrop.c 2006-02-18 17:25:21.000000000 -0500 @@ -0,0 +1,73 @@ +/* + * Eggdrop userfile converter + * Copyright (c) 2002 by Sun-Zero + * This is a free software distributable under terms of the GNU GPL. + * See the file COPYING for details. + * + * 2003-04-21 +*/ + +#include +#include +#include + + +#define USERFILE_HEADER "#4v:" +#define USERNAME_LENGTH 11 +#define PASSWORD_LENGTH 13 +#define MAX_FLAGS_LENGTH 32 +#define BUFSIZE 512 + +int undrop(int argc, char *argv[]) { + + FILE *userfile; + char username[USERNAME_LENGTH]; + char password[PASSWORD_LENGTH]; + char flags[MAX_FLAGS_LENGTH]; + char t_username[BUFSIZE]; + char t_flags[BUFSIZE]; + char t_line[BUFSIZE]; + + if (argc != 2) { + userfile = stdin; + printf("# userfile reading from stdin\n"); + } else { + if ((userfile = fopen(argv[1], "rt")) == NULL) { + fprintf(stderr, "opening userfile\n"); + userfile = stdin; + } + } + + + if (fgets(t_line, sizeof(t_line) - 1, userfile) == NULL) + return 1; + + if (strncmp(t_line, USERFILE_HEADER, strlen(USERFILE_HEADER)) != 0) { + fprintf(stderr, "usefile format is wrong\n"); + return 1; + } else { + printf("# userfile format OK\n\n"); + } + + while (fgets(t_line, sizeof(t_line) - 1, userfile) != NULL) { + if (sscanf(t_line, "%10s - %24s\n", t_username, t_flags) == 2) { + if (strncmp(t_username, "! ", 2) != 0 && + strncmp(t_username, "--", 2) != 0 && + strncmp(t_username, "&&", 2) != 0 && + strncmp(t_username, "::", 2) != 0 && + strncmp(t_username, "$$", 2) != 0 + ) { + strncpy(username, t_username, USERNAME_LENGTH); + strncpy(flags, t_flags, MAX_FLAGS_LENGTH); + } + } + + if (strncmp(t_line, "--PASS +", 8) == 0) { + sscanf(t_line, "--PASS %s", password); + printf("%s:%s:::%s:\n", username, password, flags); + } + fflush(stdout); + } + fclose(userfile); + return 0; +}