diff options
Diffstat (limited to 'regress')
-rw-r--r-- | regress/Makefile | 9 | ||||
-rw-r--r-- | regress/integrity.sh | 58 | ||||
-rwxr-xr-x | regress/modpipe.c | 124 |
3 files changed, 188 insertions, 3 deletions
diff --git a/regress/Makefile b/regress/Makefile index c628fb5ff..2eb2e3181 100644 --- a/regress/Makefile +++ b/regress/Makefile | |||
@@ -1,4 +1,4 @@ | |||
1 | # $OpenBSD: Makefile,v 1.60 2012/12/02 20:47:48 djm Exp $ | 1 | # $OpenBSD: Makefile,v 1.61 2012/12/11 22:42:11 markus Exp $ |
2 | 2 | ||
3 | REGRESS_TARGETS= t1 t2 t3 t4 t5 t6 t7 t8 t9 t-exec | 3 | REGRESS_TARGETS= t1 t2 t3 t4 t5 t6 t7 t8 t9 t-exec |
4 | tests: $(REGRESS_TARGETS) | 4 | tests: $(REGRESS_TARGETS) |
@@ -59,7 +59,8 @@ LTESTS= connect \ | |||
59 | cert-userkey \ | 59 | cert-userkey \ |
60 | host-expand \ | 60 | host-expand \ |
61 | keys-command \ | 61 | keys-command \ |
62 | forward-control | 62 | forward-control \ |
63 | integrity | ||
63 | 64 | ||
64 | INTEROP_TESTS= putty-transfer putty-ciphers putty-kex conch-ciphers | 65 | INTEROP_TESTS= putty-transfer putty-ciphers putty-kex conch-ciphers |
65 | #INTEROP_TESTS+=ssh-com ssh-com-client ssh-com-keygen ssh-com-sftp | 66 | #INTEROP_TESTS+=ssh-com ssh-com-client ssh-com-keygen ssh-com-sftp |
@@ -142,7 +143,9 @@ t9: $(OBJ)/t9.out | |||
142 | test "${TEST_SSH_ECC}" != yes || \ | 143 | test "${TEST_SSH_ECC}" != yes || \ |
143 | ${TEST_SSH_SSHKEYGEN} -Bf $(OBJ)/t9.out > /dev/null | 144 | ${TEST_SSH_SSHKEYGEN} -Bf $(OBJ)/t9.out > /dev/null |
144 | 145 | ||
145 | t-exec: ${LTESTS:=.sh} | 146 | modpipe: modpipe.c |
147 | |||
148 | t-exec: modpipe ${LTESTS:=.sh} | ||
146 | @if [ "x$?" = "x" ]; then exit 0; fi; \ | 149 | @if [ "x$?" = "x" ]; then exit 0; fi; \ |
147 | for TEST in ""$?; do \ | 150 | for TEST in ""$?; do \ |
148 | echo "run test $${TEST}" ... 1>&2; \ | 151 | echo "run test $${TEST}" ... 1>&2; \ |
diff --git a/regress/integrity.sh b/regress/integrity.sh new file mode 100644 index 000000000..23135685c --- /dev/null +++ b/regress/integrity.sh | |||
@@ -0,0 +1,58 @@ | |||
1 | # $OpenBSD: integrity.sh,v 1.1 2012/12/11 22:42:11 markus Exp $ | ||
2 | # Placed in the Public Domain. | ||
3 | |||
4 | tid="integrity" | ||
5 | |||
6 | # start at byte 2300 (i.e. after kex) and corrupt at different offsets | ||
7 | # XXX the test hangs if we modify the low bytes of the packet length | ||
8 | # XXX and ssh tries to read... | ||
9 | tries=10 | ||
10 | startoffset=2300 | ||
11 | macs="hmac-sha1 hmac-md5 umac-64@openssh.com umac-128@openssh.com | ||
12 | hmac-sha1-96 hmac-md5-96 hmac-sha2-256 hmac-sha2-512 | ||
13 | hmac-sha1-etm@openssh.com hmac-md5-etm@openssh.com | ||
14 | umac-64-etm@openssh.com umac-128-etm@openssh.com | ||
15 | hmac-sha1-96-etm@openssh.com hmac-md5-96-etm@openssh.com | ||
16 | hmac-sha2-256-etm@openssh.com hmac-sha2-512-etm@openssh.com" | ||
17 | |||
18 | # sshd-command for proxy (see test-exec.sh) | ||
19 | cmd="sh ${SRC}/sshd-log-wrapper.sh ${SSHD} ${TEST_SSH_LOGFILE} -i -f $OBJ/sshd_proxy" | ||
20 | |||
21 | for m in $macs; do | ||
22 | trace "test $tid: mac $m" | ||
23 | elen=0 | ||
24 | epad=0 | ||
25 | emac=0 | ||
26 | ecnt=0 | ||
27 | skip=0 | ||
28 | for off in $(jot $tries $startoffset); do | ||
29 | if [ $((skip--)) -gt 0 ]; then | ||
30 | # avoid modifying the high bytes of the length | ||
31 | continue | ||
32 | fi | ||
33 | # modify output from sshd at offset $off | ||
34 | pxy="proxycommand=$cmd | $OBJ/modpipe -m xor:$off:1" | ||
35 | output=$(${SSH} -m $m -2F $OBJ/ssh_proxy -o "$pxy" \ | ||
36 | 999.999.999.999 true 2>&1) | ||
37 | if [ $? -eq 0 ]; then | ||
38 | fail "ssh -m $m succeeds with bit-flip at $off" | ||
39 | fi | ||
40 | ecnt=$((ecnt+1)) | ||
41 | output=$(echo $output | tr -s '\r\n' '.') | ||
42 | verbose "test $tid: $m @$off $output" | ||
43 | case "$output" in | ||
44 | Bad?packet*) elen=$((elen+1)); skip=2;; | ||
45 | Corrupted?MAC*) emac=$((emac+1)); skip=0;; | ||
46 | padding*) epad=$((epad+1)); skip=0;; | ||
47 | *) fail "unexpected error mac $m at $off";; | ||
48 | esac | ||
49 | done | ||
50 | verbose "test $tid: $ecnt errors: mac $emac padding $epad length $elen" | ||
51 | if [ $emac -eq 0 ]; then | ||
52 | fail "$m: no mac errors" | ||
53 | fi | ||
54 | expect=$((ecnt-epad-elen)) | ||
55 | if [ $emac -ne $expect ]; then | ||
56 | fail "$m: expected $expect mac errors, got $emac" | ||
57 | fi | ||
58 | done | ||
diff --git a/regress/modpipe.c b/regress/modpipe.c new file mode 100755 index 000000000..439be4c9d --- /dev/null +++ b/regress/modpipe.c | |||
@@ -0,0 +1,124 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Damien Miller <djm@mindrot.org> | ||
3 | * | ||
4 | * Permission to use, copy, modify, and distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | /* $Id: modpipe.c,v 1.1 2012/12/11 23:54:40 djm Exp $ */ | ||
18 | |||
19 | #include <sys/types.h> | ||
20 | #include <unistd.h> | ||
21 | #include <stdio.h> | ||
22 | #include <string.h> | ||
23 | #include <stdlib.h> | ||
24 | #include <err.h> | ||
25 | #include <errno.h> | ||
26 | |||
27 | static void | ||
28 | usage(void) | ||
29 | { | ||
30 | fprintf(stderr, "Usage: modpipe [-m modspec ...] < in > out\n"); | ||
31 | fprintf(stderr, "modspec is one of:\n"); | ||
32 | fprintf(stderr, " xor:offset:value - XOR \"value\" at \"offset\"\n"); | ||
33 | fprintf(stderr, " andor:offset:val1:val2 - AND \"val1\" then OR \"val2\" at \"offset\"\n"); | ||
34 | exit(1); | ||
35 | } | ||
36 | |||
37 | #define MAX_MODIFICATIONS 256 | ||
38 | struct modification { | ||
39 | enum { MOD_XOR, MOD_AND_OR } what; | ||
40 | u_int64_t offset; | ||
41 | u_int8_t m1, m2; | ||
42 | }; | ||
43 | |||
44 | static void | ||
45 | parse_modification(const char *s, struct modification *m) | ||
46 | { | ||
47 | char what[16+1]; | ||
48 | int n; | ||
49 | |||
50 | bzero(m, sizeof(*m)); | ||
51 | if ((n = sscanf(s, "%16[^:]%*[:]%lli%*[:]%hhi%*[:]%hhi", | ||
52 | what, &m->offset, &m->m1, &m->m2)) < 3) | ||
53 | errx(1, "Invalid modification spec \"%s\"", s); | ||
54 | if (strcasecmp(what, "xor") == 0) { | ||
55 | m->what = MOD_XOR; | ||
56 | if (n > 3) | ||
57 | errx(1, "Invalid modification spec \"%s\"", s); | ||
58 | } else if (strcasecmp(what, "andor") == 0) { | ||
59 | m->what = MOD_AND_OR; | ||
60 | if (n != 4) | ||
61 | errx(1, "Invalid modification spec \"%s\"", s); | ||
62 | } else | ||
63 | errx(1, "Invalid modification type \"%s\"", what); | ||
64 | } | ||
65 | |||
66 | int | ||
67 | main(int argc, char **argv) | ||
68 | { | ||
69 | int ch; | ||
70 | u_char buf[8192]; | ||
71 | size_t total; | ||
72 | ssize_t r, s, o; | ||
73 | struct modification mods[MAX_MODIFICATIONS]; | ||
74 | u_int i, num_mods = 0; | ||
75 | |||
76 | while ((ch = getopt(argc, argv, "m:")) != -1) { | ||
77 | switch (ch) { | ||
78 | case 'm': | ||
79 | if (num_mods >= MAX_MODIFICATIONS) | ||
80 | errx(1, "Too many modifications"); | ||
81 | parse_modification(optarg, &(mods[num_mods++])); | ||
82 | break; | ||
83 | default: | ||
84 | usage(); | ||
85 | /* NOTREACHED */ | ||
86 | } | ||
87 | } | ||
88 | for (total = 0;;) { | ||
89 | r = s = read(STDIN_FILENO, buf, sizeof(buf)); | ||
90 | if (r == 0) | ||
91 | return 0; | ||
92 | if (r < 0) { | ||
93 | if (errno == EAGAIN || errno == EINTR) | ||
94 | continue; | ||
95 | err(1, "read"); | ||
96 | } | ||
97 | for (i = 0; i < num_mods; i++) { | ||
98 | if (mods[i].offset < total || | ||
99 | mods[i].offset >= total + s) | ||
100 | continue; | ||
101 | switch (mods[i].what) { | ||
102 | case MOD_XOR: | ||
103 | buf[mods[i].offset - total] ^= mods[i].m1; | ||
104 | break; | ||
105 | case MOD_AND_OR: | ||
106 | buf[mods[i].offset - total] &= mods[i].m1; | ||
107 | buf[mods[i].offset - total] |= mods[i].m2; | ||
108 | break; | ||
109 | } | ||
110 | } | ||
111 | for (o = 0; o < s; o += r) { | ||
112 | r = write(STDOUT_FILENO, buf, s - o); | ||
113 | if (r == 0) | ||
114 | return 0; | ||
115 | if (r < 0) { | ||
116 | if (errno == EAGAIN || errno == EINTR) | ||
117 | continue; | ||
118 | err(1, "write"); | ||
119 | } | ||
120 | } | ||
121 | total += s; | ||
122 | } | ||
123 | return 0; | ||
124 | } | ||