summaryrefslogtreecommitdiff
path: root/regress/unittests/test_helper/fuzz.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2014-10-07 13:33:15 +0100
committerColin Watson <cjwatson@debian.org>2014-10-07 14:27:30 +0100
commitf0b009aea83e9ff3a50be30f51012099a5143c16 (patch)
tree3825e6f7e3b7ea4481d06ed89aba9a7a95150df5 /regress/unittests/test_helper/fuzz.c
parent47f0bad4330b16ec3bad870fcf9839c196e42c12 (diff)
parent762c062828f5a8f6ed189ed6e44ad38fd92f8b36 (diff)
Merge 6.7p1.
* New upstream release (http://www.openssh.com/txt/release-6.7): - sshd(8): The default set of ciphers and MACs has been altered to remove unsafe algorithms. In particular, CBC ciphers and arcfour* are disabled by default. The full set of algorithms remains available if configured explicitly via the Ciphers and MACs sshd_config options. - ssh(1), sshd(8): Add support for Unix domain socket forwarding. A remote TCP port may be forwarded to a local Unix domain socket and vice versa or both ends may be a Unix domain socket (closes: #236718). - ssh(1), ssh-keygen(1): Add support for SSHFP DNS records for ED25519 key types. - sftp(1): Allow resumption of interrupted uploads. - ssh(1): When rekeying, skip file/DNS lookups of the hostkey if it is the same as the one sent during initial key exchange. - sshd(8): Allow explicit ::1 and 127.0.0.1 forwarding bind addresses when GatewayPorts=no; allows client to choose address family. - sshd(8): Add a sshd_config PermitUserRC option to control whether ~/.ssh/rc is executed, mirroring the no-user-rc authorized_keys option. - ssh(1): Add a %C escape sequence for LocalCommand and ControlPath that expands to a unique identifer based on a hash of the tuple of (local host, remote user, hostname, port). Helps avoid exceeding miserly pathname limits for Unix domain sockets in multiplexing control paths. - sshd(8): Make the "Too many authentication failures" message include the user, source address, port and protocol in a format similar to the authentication success / failure messages. - Use CLOCK_BOOTTIME in preference to CLOCK_MONOTONIC when it is available. It considers time spent suspended, thereby ensuring timeouts (e.g. for expiring agent keys) fire correctly (closes: #734553). - Use prctl() to prevent sftp-server from accessing /proc/self/{mem,maps}. * Restore TCP wrappers support, removed upstream in 6.7. It is true that dropping this reduces preauth attack surface in sshd. On the other hand, this support seems to be quite widely used, and abruptly dropping it (from the perspective of users who don't read openssh-unix-dev) could easily cause more serious problems in practice. It's not entirely clear what the right long-term answer for Debian is, but it at least probably doesn't involve dropping this feature shortly before a freeze. * Replace patch to disable OpenSSL version check with an updated version of Kurt Roeckx's patch from #732940 to just avoid checking the status field.
Diffstat (limited to 'regress/unittests/test_helper/fuzz.c')
-rw-r--r--regress/unittests/test_helper/fuzz.c378
1 files changed, 378 insertions, 0 deletions
diff --git a/regress/unittests/test_helper/fuzz.c b/regress/unittests/test_helper/fuzz.c
new file mode 100644
index 000000000..77c6e7cad
--- /dev/null
+++ b/regress/unittests/test_helper/fuzz.c
@@ -0,0 +1,378 @@
1/* $OpenBSD: fuzz.c,v 1.3 2014/05/02 09:41:32 andre Exp $ */
2/*
3 * Copyright (c) 2011 Damien Miller <djm@mindrot.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18/* Utility functions/framework for fuzz tests */
19
20#include "includes.h"
21
22#include <sys/types.h>
23
24#include <assert.h>
25#include <ctype.h>
26#include <stdio.h>
27#ifdef HAVE_STDINT_H
28# include <stdint.h>
29#endif
30#include <stdlib.h>
31#include <string.h>
32#include <assert.h>
33
34#include "test_helper.h"
35
36/* #define FUZZ_DEBUG */
37
38#ifdef FUZZ_DEBUG
39# define FUZZ_DBG(x) do { \
40 printf("%s:%d %s: ", __FILE__, __LINE__, __func__); \
41 printf x; \
42 printf("\n"); \
43 fflush(stdout); \
44 } while (0)
45#else
46# define FUZZ_DBG(x)
47#endif
48
49/* For brevity later */
50typedef unsigned long long fuzz_ullong;
51
52/* For base-64 fuzzing */
53static const char fuzz_b64chars[] =
54 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
55
56struct fuzz {
57 /* Fuzz method currently in use */
58 int strategy;
59
60 /* Fuzz methods remaining */
61 int strategies;
62
63 /* Original seed data blob */
64 void *seed;
65 size_t slen;
66
67 /* Current working copy of seed with fuzz mutations applied */
68 u_char *fuzzed;
69
70 /* Used by fuzz methods */
71 size_t o1, o2;
72};
73
74static const char *
75fuzz_ntop(u_int n)
76{
77 switch (n) {
78 case 0:
79 return "NONE";
80 case FUZZ_1_BIT_FLIP:
81 return "FUZZ_1_BIT_FLIP";
82 case FUZZ_2_BIT_FLIP:
83 return "FUZZ_2_BIT_FLIP";
84 case FUZZ_1_BYTE_FLIP:
85 return "FUZZ_1_BYTE_FLIP";
86 case FUZZ_2_BYTE_FLIP:
87 return "FUZZ_2_BYTE_FLIP";
88 case FUZZ_TRUNCATE_START:
89 return "FUZZ_TRUNCATE_START";
90 case FUZZ_TRUNCATE_END:
91 return "FUZZ_TRUNCATE_END";
92 case FUZZ_BASE64:
93 return "FUZZ_BASE64";
94 default:
95 abort();
96 }
97}
98
99void
100fuzz_dump(struct fuzz *fuzz)
101{
102 u_char *p = fuzz_ptr(fuzz);
103 size_t i, j, len = fuzz_len(fuzz);
104
105 switch (fuzz->strategy) {
106 case FUZZ_1_BIT_FLIP:
107 fprintf(stderr, "%s case %zu of %zu (bit: %zu)\n",
108 fuzz_ntop(fuzz->strategy),
109 fuzz->o1, fuzz->slen * 8, fuzz->o1);
110 break;
111 case FUZZ_2_BIT_FLIP:
112 fprintf(stderr, "%s case %llu of %llu (bits: %zu, %zu)\n",
113 fuzz_ntop(fuzz->strategy),
114 (((fuzz_ullong)fuzz->o2) * fuzz->slen * 8) + fuzz->o1,
115 ((fuzz_ullong)fuzz->slen * 8) * fuzz->slen * 8,
116 fuzz->o1, fuzz->o2);
117 break;
118 case FUZZ_1_BYTE_FLIP:
119 fprintf(stderr, "%s case %zu of %zu (byte: %zu)\n",
120 fuzz_ntop(fuzz->strategy),
121 fuzz->o1, fuzz->slen, fuzz->o1);
122 break;
123 case FUZZ_2_BYTE_FLIP:
124 fprintf(stderr, "%s case %llu of %llu (bytes: %zu, %zu)\n",
125 fuzz_ntop(fuzz->strategy),
126 (((fuzz_ullong)fuzz->o2) * fuzz->slen) + fuzz->o1,
127 ((fuzz_ullong)fuzz->slen) * fuzz->slen,
128 fuzz->o1, fuzz->o2);
129 break;
130 case FUZZ_TRUNCATE_START:
131 fprintf(stderr, "%s case %zu of %zu (offset: %zu)\n",
132 fuzz_ntop(fuzz->strategy),
133 fuzz->o1, fuzz->slen, fuzz->o1);
134 break;
135 case FUZZ_TRUNCATE_END:
136 fprintf(stderr, "%s case %zu of %zu (offset: %zu)\n",
137 fuzz_ntop(fuzz->strategy),
138 fuzz->o1, fuzz->slen, fuzz->o1);
139 break;
140 case FUZZ_BASE64:
141 assert(fuzz->o2 < sizeof(fuzz_b64chars) - 1);
142 fprintf(stderr, "%s case %llu of %llu (offset: %zu char: %c)\n",
143 fuzz_ntop(fuzz->strategy),
144 (fuzz->o1 * (fuzz_ullong)64) + fuzz->o2,
145 fuzz->slen * (fuzz_ullong)64, fuzz->o1,
146 fuzz_b64chars[fuzz->o2]);
147 break;
148 default:
149 abort();
150 }
151
152 fprintf(stderr, "fuzz context %p len = %zu\n", fuzz, len);
153 for (i = 0; i < len; i += 16) {
154 fprintf(stderr, "%.4zd: ", i);
155 for (j = i; j < i + 16; j++) {
156 if (j < len)
157 fprintf(stderr, "%02x ", p[j]);
158 else
159 fprintf(stderr, " ");
160 }
161 fprintf(stderr, " ");
162 for (j = i; j < i + 16; j++) {
163 if (j < len) {
164 if (isascii(p[j]) && isprint(p[j]))
165 fprintf(stderr, "%c", p[j]);
166 else
167 fprintf(stderr, ".");
168 }
169 }
170 fprintf(stderr, "\n");
171 }
172}
173
174struct fuzz *
175fuzz_begin(u_int strategies, const void *p, size_t l)
176{
177 struct fuzz *ret = calloc(sizeof(*ret), 1);
178
179 assert(p != NULL);
180 assert(ret != NULL);
181 ret->seed = malloc(l);
182 assert(ret->seed != NULL);
183 memcpy(ret->seed, p, l);
184 ret->slen = l;
185 ret->strategies = strategies;
186
187 assert(ret->slen < SIZE_MAX / 8);
188 assert(ret->strategies <= (FUZZ_MAX|(FUZZ_MAX-1)));
189
190 FUZZ_DBG(("begin, ret = %p", ret));
191
192 fuzz_next(ret);
193 return ret;
194}
195
196void
197fuzz_cleanup(struct fuzz *fuzz)
198{
199 FUZZ_DBG(("cleanup, fuzz = %p", fuzz));
200 assert(fuzz != NULL);
201 assert(fuzz->seed != NULL);
202 assert(fuzz->fuzzed != NULL);
203 free(fuzz->seed);
204 free(fuzz->fuzzed);
205 free(fuzz);
206}
207
208static int
209fuzz_strategy_done(struct fuzz *fuzz)
210{
211 FUZZ_DBG(("fuzz = %p, strategy = %s, o1 = %zu, o2 = %zu, slen = %zu",
212 fuzz, fuzz_ntop(fuzz->strategy), fuzz->o1, fuzz->o2, fuzz->slen));
213
214 switch (fuzz->strategy) {
215 case FUZZ_1_BIT_FLIP:
216 return fuzz->o1 >= fuzz->slen * 8;
217 case FUZZ_2_BIT_FLIP:
218 return fuzz->o2 >= fuzz->slen * 8;
219 case FUZZ_2_BYTE_FLIP:
220 return fuzz->o2 >= fuzz->slen;
221 case FUZZ_1_BYTE_FLIP:
222 case FUZZ_TRUNCATE_START:
223 case FUZZ_TRUNCATE_END:
224 case FUZZ_BASE64:
225 return fuzz->o1 >= fuzz->slen;
226 default:
227 abort();
228 }
229}
230
231void
232fuzz_next(struct fuzz *fuzz)
233{
234 u_int i;
235
236 FUZZ_DBG(("start, fuzz = %p, strategy = %s, strategies = 0x%lx, "
237 "o1 = %zu, o2 = %zu, slen = %zu", fuzz, fuzz_ntop(fuzz->strategy),
238 (u_long)fuzz->strategies, fuzz->o1, fuzz->o2, fuzz->slen));
239
240 if (fuzz->strategy == 0 || fuzz_strategy_done(fuzz)) {
241 /* If we are just starting out, we need to allocate too */
242 if (fuzz->fuzzed == NULL) {
243 FUZZ_DBG(("alloc"));
244 fuzz->fuzzed = calloc(fuzz->slen, 1);
245 }
246 /* Pick next strategy */
247 FUZZ_DBG(("advance"));
248 for (i = 1; i <= FUZZ_MAX; i <<= 1) {
249 if ((fuzz->strategies & i) != 0) {
250 fuzz->strategy = i;
251 break;
252 }
253 }
254 FUZZ_DBG(("selected = %u", fuzz->strategy));
255 if (fuzz->strategy == 0) {
256 FUZZ_DBG(("done, no more strategies"));
257 return;
258 }
259 fuzz->strategies &= ~(fuzz->strategy);
260 fuzz->o1 = fuzz->o2 = 0;
261 }
262
263 assert(fuzz->fuzzed != NULL);
264
265 switch (fuzz->strategy) {
266 case FUZZ_1_BIT_FLIP:
267 assert(fuzz->o1 / 8 < fuzz->slen);
268 memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen);
269 fuzz->fuzzed[fuzz->o1 / 8] ^= 1 << (fuzz->o1 % 8);
270 fuzz->o1++;
271 break;
272 case FUZZ_2_BIT_FLIP:
273 assert(fuzz->o1 / 8 < fuzz->slen);
274 assert(fuzz->o2 / 8 < fuzz->slen);
275 memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen);
276 fuzz->fuzzed[fuzz->o1 / 8] ^= 1 << (fuzz->o1 % 8);
277 fuzz->fuzzed[fuzz->o2 / 8] ^= 1 << (fuzz->o2 % 8);
278 fuzz->o1++;
279 if (fuzz->o1 >= fuzz->slen * 8) {
280 fuzz->o1 = 0;
281 fuzz->o2++;
282 }
283 break;
284 case FUZZ_1_BYTE_FLIP:
285 assert(fuzz->o1 < fuzz->slen);
286 memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen);
287 fuzz->fuzzed[fuzz->o1] ^= 0xff;
288 fuzz->o1++;
289 break;
290 case FUZZ_2_BYTE_FLIP:
291 assert(fuzz->o1 < fuzz->slen);
292 assert(fuzz->o2 < fuzz->slen);
293 memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen);
294 fuzz->fuzzed[fuzz->o1] ^= 0xff;
295 fuzz->fuzzed[fuzz->o2] ^= 0xff;
296 fuzz->o1++;
297 if (fuzz->o1 >= fuzz->slen) {
298 fuzz->o1 = 0;
299 fuzz->o2++;
300 }
301 break;
302 case FUZZ_TRUNCATE_START:
303 case FUZZ_TRUNCATE_END:
304 assert(fuzz->o1 < fuzz->slen);
305 memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen);
306 fuzz->o1++;
307 break;
308 case FUZZ_BASE64:
309 assert(fuzz->o1 < fuzz->slen);
310 assert(fuzz->o2 < sizeof(fuzz_b64chars) - 1);
311 memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen);
312 fuzz->fuzzed[fuzz->o1] = fuzz_b64chars[fuzz->o2];
313 fuzz->o2++;
314 if (fuzz->o2 >= sizeof(fuzz_b64chars) - 1) {
315 fuzz->o2 = 0;
316 fuzz->o1++;
317 }
318 break;
319 default:
320 abort();
321 }
322
323 FUZZ_DBG(("done, fuzz = %p, strategy = %s, strategies = 0x%lx, "
324 "o1 = %zu, o2 = %zu, slen = %zu", fuzz, fuzz_ntop(fuzz->strategy),
325 (u_long)fuzz->strategies, fuzz->o1, fuzz->o2, fuzz->slen));
326}
327
328int
329fuzz_done(struct fuzz *fuzz)
330{
331 FUZZ_DBG(("fuzz = %p, strategies = 0x%lx", fuzz,
332 (u_long)fuzz->strategies));
333
334 return fuzz_strategy_done(fuzz) && fuzz->strategies == 0;
335}
336
337size_t
338fuzz_len(struct fuzz *fuzz)
339{
340 assert(fuzz->fuzzed != NULL);
341 switch (fuzz->strategy) {
342 case FUZZ_1_BIT_FLIP:
343 case FUZZ_2_BIT_FLIP:
344 case FUZZ_1_BYTE_FLIP:
345 case FUZZ_2_BYTE_FLIP:
346 case FUZZ_BASE64:
347 return fuzz->slen;
348 case FUZZ_TRUNCATE_START:
349 case FUZZ_TRUNCATE_END:
350 assert(fuzz->o1 <= fuzz->slen);
351 return fuzz->slen - fuzz->o1;
352 default:
353 abort();
354 }
355}
356
357u_char *
358fuzz_ptr(struct fuzz *fuzz)
359{
360 assert(fuzz->fuzzed != NULL);
361 switch (fuzz->strategy) {
362 case FUZZ_1_BIT_FLIP:
363 case FUZZ_2_BIT_FLIP:
364 case FUZZ_1_BYTE_FLIP:
365 case FUZZ_2_BYTE_FLIP:
366 case FUZZ_BASE64:
367 return fuzz->fuzzed;
368 case FUZZ_TRUNCATE_START:
369 assert(fuzz->o1 <= fuzz->slen);
370 return fuzz->fuzzed + fuzz->o1;
371 case FUZZ_TRUNCATE_END:
372 assert(fuzz->o1 <= fuzz->slen);
373 return fuzz->fuzzed;
374 default:
375 abort();
376 }
377}
378