1 /*
2 * Post.Office MD5 cracker.
3 * Uses a modified version of Solar Designer's MD5 routine.
4 *
5 * This file adapted from other code in this project.
6 *
7 * To extract these crypts from Post.Office, use something
8 * along the lines of:
9 *
10 * /usr/local/post.office/cmdutils/listacct \
11 * -i POP-Address,Account-ID,Password,Name | \
12 * perl -ne 'chop;@a=split(/;/);print
13 * (($a[0]?$a[0]:$a[1]).":".$a[2].":0:0:".$a[3]."::\n");'
14 *
15 * Then find any passwords ending in UNIX-PASSWORD and tidy
16 * them up (and crack as plain DES crypts); this module will
17 * handle the others.
18 *
19 * This crypt format may also be found in LDAP directories of
20 * users migrated from Post.Office, for example the crypt format
21 * can be supported by OpenWave and qmail-ldap.
22 *
23 * Copyright (c) 2005 David Luyer <david at luyer.net>
24 */
25
26 #if FMT_EXTERNS_H
27 extern struct fmt_main fmt_PO;
28 #elif FMT_REGISTERS_H
29 john_register_one(&fmt_PO);
30 #else
31
32 #include <string.h>
33
34 #include "arch.h"
35 #include "misc.h"
36 #include "common.h"
37 #include "formats.h"
38 #include "md5.h"
39
40 #define FORMAT_LABEL "po"
41 #define FORMAT_NAME "Post.Office"
42 #define ALGORITHM_NAME "MD5 32/" ARCH_BITS_STR
43
44 #define BENCHMARK_COMMENT ""
45 #define BENCHMARK_LENGTH 7
46
47 #define PLAINTEXT_LENGTH 64
48 #define CIPHERTEXT_LENGTH 64
49
50 #define BINARY_SIZE 4
51 #define BINARY_ALIGN 4
52 #define SALT_SIZE 32
53 #define SALT_ALIGN 1
54
55 #define MIN_KEYS_PER_CRYPT 1
56 #define MAX_KEYS_PER_CRYPT 1
57
58 static struct fmt_tests tests[] = {
59 {"550c41c11bab48f9dbd8203ed313eef0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "abc123"},
60 {"0c78bdef7d5448105cfbbc9aaa490a44550c41c11bab48f9dbd8203ed313eef0", "abc123"},
61 {"9be296cf73d2f548dae3cccafaff1dd982916963c701200625cba2acd40d6569", "FRED"},
62 {"a0e2078f0354846ec5bc4c7d7be08a4682916963c701200625cba2acd40d6569", ""},
63 {NULL}
64 };
65
66 static char saved_key[PLAINTEXT_LENGTH + 1];
67 static int saved_key_len;
68 static unsigned char po_buf[SALT_SIZE * 2 + 2 + PLAINTEXT_LENGTH + 128 /* MD5 scratch space */];
69 static uint32_t MD5_out[4];
70
po_init(struct fmt_main * self)71 static void po_init(struct fmt_main *self) {
72 /* Do nothing */
73 }
74
valid(char * ciphertext,struct fmt_main * self)75 static int valid(char *ciphertext, struct fmt_main *self)
76 {
77 if (strlen(ciphertext) == 64 &&
78 strspn(ciphertext, HEXCHARS_lc) == 64) {
79 return 1;
80 }
81 return 0;
82 }
83
84 #define COMMON_GET_HASH_VAR MD5_out
85 #include "common-get-hash.h"
86
salt_hash(void * salt)87 static int salt_hash(void *salt)
88 {
89 return ((int)atoi16[ARCH_INDEX(((char *)salt)[0])] |
90 ((int)atoi16[ARCH_INDEX(((char *)salt)[1])] << 4) |
91 ((int)atoi16[ARCH_INDEX(((char *)salt)[2])] << 8)) & (SALT_HASH_SIZE - 1);
92 }
93
set_key(char * key,int index)94 static void set_key(char *key, int index)
95 {
96 saved_key_len = strnzcpyn(saved_key, key, sizeof(saved_key));
97 }
98
get_key(int index)99 static char *get_key(int index)
100 {
101 saved_key[PLAINTEXT_LENGTH] = 0;
102 return saved_key;
103 }
104
cmp_all(void * binary,int count)105 static int cmp_all(void *binary, int count)
106 {
107 return *(uint32_t *)binary == MD5_out[0];
108 }
109
cmp_one(void * binary,int index)110 static int cmp_one(void *binary, int index)
111 {
112 return 1;
113 }
114
cmp_exact(char * source,int index)115 static int cmp_exact(char *source, int index)
116 {
117 static char fullmd5[16];
118 int i;
119
120 for (i=0;i<16;i++)
121 {
122 fullmd5[i] = atoi16[ARCH_INDEX(source[i*2])]*16 + atoi16[ARCH_INDEX(source[i*2+1])];
123 }
124 return !memcmp(fullmd5, MD5_out, sizeof(fullmd5));
125 }
126
get_binary(char * ciphertext)127 static void *get_binary(char *ciphertext)
128 {
129 static char *binarycipher;
130 int i;
131
132 if (!binarycipher) binarycipher = mem_alloc_tiny(BINARY_SIZE, MEM_ALIGN_WORD);
133
134 for (i=0;i<BINARY_SIZE;i++)
135 {
136 binarycipher[i] = atoi16[ARCH_INDEX(ciphertext[i*2])]*16 + atoi16[ARCH_INDEX(ciphertext[i*2+1])];
137 }
138 return (void *)binarycipher;
139 }
140
get_salt(char * ciphertext)141 static char *get_salt(char *ciphertext)
142 {
143 static char out[SALT_SIZE];
144
145 memcpy(out, ciphertext + 32, SALT_SIZE);
146 return out;
147 }
148
set_salt(char * salt)149 static void set_salt(char *salt)
150 {
151 memcpy(po_buf, salt, 32);
152 }
153
crypt_all(int * pcount,struct db_salt * salt)154 static int crypt_all(int *pcount, struct db_salt *salt)
155 {
156 MD5_CTX ctx;
157
158 po_buf[32] = 'Y';
159 memcpy(po_buf + 33, saved_key, saved_key_len);
160 po_buf[saved_key_len + 33] = 247;
161 memcpy(po_buf + saved_key_len + 34, po_buf, 32);
162 MD5_Init(&ctx);
163 MD5_Update(&ctx, po_buf, saved_key_len+66);
164 MD5_Final((unsigned char*)MD5_out, &ctx);
165
166 return *pcount;
167 }
168
169 struct fmt_main fmt_PO = {
170 {
171 FORMAT_LABEL,
172 FORMAT_NAME,
173 ALGORITHM_NAME,
174 BENCHMARK_COMMENT,
175 BENCHMARK_LENGTH,
176 0,
177 PLAINTEXT_LENGTH,
178 BINARY_SIZE,
179 BINARY_ALIGN,
180 SALT_SIZE,
181 SALT_ALIGN,
182 MIN_KEYS_PER_CRYPT,
183 MAX_KEYS_PER_CRYPT,
184 FMT_CASE | FMT_8_BIT,
185 { NULL },
186 { NULL },
187 tests
188 }, {
189 po_init,
190 fmt_default_done,
191 fmt_default_reset,
192 fmt_default_prepare,
193 valid,
194 fmt_default_split,
195 get_binary,
196 (void *(*)(char *))get_salt,
197 { NULL },
198 fmt_default_source,
199 {
200 fmt_default_binary_hash_0,
201 fmt_default_binary_hash_1,
202 fmt_default_binary_hash_2,
203 fmt_default_binary_hash_3,
204 fmt_default_binary_hash_4,
205 fmt_default_binary_hash_5,
206 fmt_default_binary_hash_6
207 },
208 salt_hash,
209 NULL,
210 (void (*)(void *))set_salt,
211 set_key,
212 get_key,
213 fmt_default_clear_keys,
214 crypt_all,
215 {
216 #define COMMON_GET_HASH_LINK
217 #include "common-get-hash.h"
218 },
219 cmp_all,
220 cmp_one,
221 cmp_exact
222 }
223 };
224
225 #endif /* plugin stanza */
226