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