-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathformats.c
293 lines (237 loc) · 6.58 KB
/
formats.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
/*
* This file is part of John the Ripper password cracker,
* Copyright (c) 1996-2001,2006,2008,2010-2013,2015 by Solar Designer
*/
#include <stdio.h>
#include <string.h>
#include "params.h"
#include "memory.h"
#include "formats.h"
char fmt_null_key[PLAINTEXT_BUFFER_SIZE];
struct fmt_main *fmt_list = NULL;
static struct fmt_main **fmt_tail = &fmt_list;
void fmt_register(struct fmt_main *format)
{
format->private.initialized = 0;
format->next = NULL;
*fmt_tail = format;
fmt_tail = &format->next;
}
void fmt_init(struct fmt_main *format)
{
if (!format->private.initialized) {
format->methods.init(format);
format->private.initialized = 1;
}
}
void fmt_done(struct fmt_main *format)
{
if (format->private.initialized) {
format->methods.done();
format->private.initialized = 0;
}
}
static int is_poweroftwo(size_t align)
{
return align != 0 && (align & (align - 1)) == 0;
}
static int is_aligned(void *p, size_t align)
{
return ((size_t)p & (align - 1)) == 0;
}
static char *fmt_self_test_body(struct fmt_main *format,
void *binary_copy, void *salt_copy)
{
static char s_size[32];
struct fmt_tests *current;
char *ciphertext, *plaintext;
int ntests, done, index, max, size;
void *binary, *salt;
int binary_align_warned = 0, salt_align_warned = 0;
/*
* Test each format just once unless we're debugging.
*/
#ifndef DEBUG
if (format->private.initialized == 2)
return NULL;
#endif
if (format->params.plaintext_length < 1 ||
format->params.plaintext_length > PLAINTEXT_BUFFER_SIZE - 3)
return "plaintext_length";
if (!is_poweroftwo(format->params.binary_align))
return "binary_align";
if (!is_poweroftwo(format->params.salt_align))
return "salt_align";
if (format->methods.valid("*", format))
return "valid";
fmt_init(format);
format->methods.reset(NULL);
if (!(current = format->params.tests)) return NULL;
ntests = 0;
while ((current++)->ciphertext)
ntests++;
current = format->params.tests;
done = 0;
index = 0; max = format->params.max_keys_per_crypt;
do {
if (!current->fields[1])
current->fields[1] = current->ciphertext;
ciphertext = format->methods.prepare(current->fields, format);
if (!ciphertext || strlen(ciphertext) < 7)
return "prepare";
if (format->methods.valid(ciphertext, format) != 1)
return "valid";
ciphertext = format->methods.split(ciphertext, 0, format);
plaintext = current->plaintext;
/*
* Make sure the declared binary_size and salt_size are sufficient to actually
* hold the binary ciphertexts and salts. We do this by copying the values
* returned by binary() and salt() only to the declared sizes.
*/
binary = format->methods.binary(ciphertext);
if (!is_aligned(binary, format->params.binary_align) &&
!binary_align_warned) {
puts("Warning: binary() returned misaligned pointer");
binary_align_warned = 1;
}
memcpy(binary_copy, binary, format->params.binary_size);
binary = binary_copy;
salt = format->methods.salt(ciphertext);
if (!is_aligned(salt, format->params.salt_align) &&
!salt_align_warned) {
puts("Warning: salt() returned misaligned pointer");
salt_align_warned = 1;
}
memcpy(salt_copy, salt, format->params.salt_size);
salt = salt_copy;
if (strcmp(ciphertext,
format->methods.source(ciphertext, binary)))
return "source";
if ((unsigned int)format->methods.salt_hash(salt) >=
SALT_HASH_SIZE)
return "salt_hash";
format->methods.set_salt(salt);
format->methods.set_key(current->plaintext, index);
{
int count = index + 1;
int match = format->methods.crypt_all(&count, NULL);
/* If salt is NULL, the return value must always match *count the way it is
* after the crypt_all() call. */
if (match != count)
return "crypt_all";
}
for (size = 0; size < PASSWORD_HASH_SIZES; size++)
if (format->methods.binary_hash[size] &&
format->methods.get_hash[size](index) !=
format->methods.binary_hash[size](binary)) {
sprintf(s_size, "get_hash[%d](%d)", size, index);
return s_size;
}
if (!format->methods.cmp_all(binary, index + 1))
return "cmp_all";
if (!format->methods.cmp_one(binary, index))
return "cmp_one";
if (!format->methods.cmp_exact(ciphertext, index))
return "cmp_exact";
if (strncmp(format->methods.get_key(index), plaintext,
format->params.plaintext_length))
return "get_key";
/* Remove some old keys to better test cmp_all() */
if (index & 1)
format->methods.set_key(fmt_null_key, index);
/* 0 1 2 3 4 6 9 13 19 28 42 63 94 141 211 316 474 711 1066 ... */
if (index >= 2 && max > ntests)
index += index >> 1;
else
index++;
if (index >= max) {
index = (max > 5 && max > ntests && done != 1) ? 5 : 0;
done |= 1;
}
if (!(++current)->ciphertext) {
current = format->params.tests;
done |= 2;
}
} while (done != 3);
format->private.initialized = 2;
return NULL;
}
/*
* Allocate memory for a copy of a binary ciphertext or salt with only the
* minimum guaranteed alignment. We do this to test that binary_hash*(),
* cmp_*(), and salt_hash() do accept such pointers.
*/
static void *alloc_binary(void **alloc, size_t size, size_t align)
{
size_t mask = align - 1;
char *p;
/* Ensure minimum required alignment and leave room for "align" bytes more */
p = *alloc = mem_alloc(size + mask + align);
p += mask;
p -= (size_t)p & mask;
/* If the alignment is too great, reduce it to the minimum */
if (!((size_t)p & align))
p += align;
return p;
}
char *fmt_self_test(struct fmt_main *format)
{
char *retval;
void *binary_alloc, *salt_alloc;
void *binary_copy, *salt_copy;
binary_copy = alloc_binary(&binary_alloc,
format->params.binary_size, format->params.binary_align);
salt_copy = alloc_binary(&salt_alloc,
format->params.salt_size, format->params.salt_align);
retval = fmt_self_test_body(format, binary_copy, salt_copy);
MEM_FREE(salt_alloc);
MEM_FREE(binary_alloc);
return retval;
}
void fmt_default_init(struct fmt_main *self)
{
}
void fmt_default_done(void)
{
}
void fmt_default_reset(struct db_main *db)
{
}
char *fmt_default_prepare(char *fields[10], struct fmt_main *self)
{
return fields[1];
}
char *fmt_default_split(char *ciphertext, int index, struct fmt_main *self)
{
return ciphertext;
}
void *fmt_default_binary(char *ciphertext)
{
return ciphertext;
}
void *fmt_default_salt(char *ciphertext)
{
return ciphertext;
}
char *fmt_default_source(char *source, void *binary)
{
return source;
}
int fmt_default_binary_hash(void *binary)
{
return 0;
}
int fmt_default_salt_hash(void *salt)
{
return 0;
}
void fmt_default_set_salt(void *salt)
{
}
void fmt_default_clear_keys(void)
{
}
int fmt_default_get_hash(int index)
{
return 0;
}