Mercurial > dropbear
annotate fuzz.h @ 1788:1fc0012b9c38
Fix handling of replies to global requests (#112)
The current code assumes that all global requests want / need a reply.
This isn't always true and the request itself indicates if it wants a
reply or not.
It causes a specific problem with [email protected] messages.
These are sent by OpenSSH after authentication to inform the client of
potential other host keys for the host. This can be used to add a new
type of host key or to rotate host keys.
The initial information message from the server is sent as a global
request, but with want_reply set to false. This means that the server
doesn't expect an answer to this message. Instead the client needs to
send a prove request as a reply if it wants to receive proof of
ownership for the host keys.
The bug doesn't cause any current problems with due to how OpenSSH
treats receiving the failure message. It instead treats it as a
keepalive message and further ignores it.
Arguably this is a protocol violation though of Dropbear and it is only
accidental that it doesn't cause a problem with OpenSSH.
The bug was found when adding host keys support to libssh, which is more
strict protocol wise and treats the unexpected failure message an error,
also see https://gitlab.com/libssh/libssh-mirror/-/merge_requests/145
for more information.
The fix here is to honor the want_reply flag in the global request and
to only send a reply if the other side expects a reply.
author | Dirkjan Bussink <d.bussink@gmail.com> |
---|---|
date | Thu, 10 Dec 2020 16:13:13 +0100 |
parents | a3b39df57c8b |
children | 685b47d8faf7 |
rev | line source |
---|---|
1348 | 1 #ifndef DROPBEAR_FUZZ_H |
2 #define DROPBEAR_FUZZ_H | |
3 | |
1357 | 4 #include "config.h" |
1559
92c93b4a3646
Fix to be able to compile normal(ish) binaries with --enable-fuzz
Matt Johnston <matt@ucc.asn.au>
parents:
1558
diff
changeset
|
5 |
1558
2f64cb3d3007
- #if not #ifdef for DROPBEAR_FUZZ
Matt Johnston <matt@ucc.asn.au>
parents:
1456
diff
changeset
|
6 #if DROPBEAR_FUZZ |
1357 | 7 |
1348 | 8 #include "includes.h" |
9 #include "buffer.h" | |
1357 | 10 #include "algo.h" |
1778 | 11 #include "netio.h" |
1357 | 12 #include "fuzz-wrapfd.h" |
1348 | 13 |
1356
3677a510f545
add wrapfd. improve fuzzer in makefile
Matt Johnston <matt@ucc.asn.au>
parents:
1348
diff
changeset
|
14 // once per process |
1456
a90fdd2d2ed8
add fuzzer-preauth_nomaths
Matt Johnston <matt@ucc.asn.au>
parents:
1385
diff
changeset
|
15 void fuzz_common_setup(void); |
a90fdd2d2ed8
add fuzzer-preauth_nomaths
Matt Johnston <matt@ucc.asn.au>
parents:
1385
diff
changeset
|
16 void fuzz_svr_setup(void); |
1741
d1b279aa5ed1
Get client fuzzer building and starting (fails straight away)
Matt Johnston <matt@ucc.asn.au>
parents:
1740
diff
changeset
|
17 void fuzz_cli_setup(void); |
1348 | 18 |
1758
1365661f6be6
Disable stderr output for fuzzer by default
Matt Johnston <matt@ucc.asn.au>
parents:
1757
diff
changeset
|
19 // constructor attribute so it runs before main(), including |
1365661f6be6
Disable stderr output for fuzzer by default
Matt Johnston <matt@ucc.asn.au>
parents:
1757
diff
changeset
|
20 // in non-fuzzing mode. |
1365661f6be6
Disable stderr output for fuzzer by default
Matt Johnston <matt@ucc.asn.au>
parents:
1757
diff
changeset
|
21 void fuzz_early_setup(void) __attribute__((constructor)); |
1365661f6be6
Disable stderr output for fuzzer by default
Matt Johnston <matt@ucc.asn.au>
parents:
1757
diff
changeset
|
22 |
1377
d4cc85e6c569
rearrange, all fuzzers now call fuzzer_set_input()
Matt Johnston <matt@ucc.asn.au>
parents:
1369
diff
changeset
|
23 // must be called once per fuzz iteration. |
d4cc85e6c569
rearrange, all fuzzers now call fuzzer_set_input()
Matt Johnston <matt@ucc.asn.au>
parents:
1369
diff
changeset
|
24 // returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE |
1456
a90fdd2d2ed8
add fuzzer-preauth_nomaths
Matt Johnston <matt@ucc.asn.au>
parents:
1385
diff
changeset
|
25 int fuzz_set_input(const uint8_t *Data, size_t Size); |
a90fdd2d2ed8
add fuzzer-preauth_nomaths
Matt Johnston <matt@ucc.asn.au>
parents:
1385
diff
changeset
|
26 |
1782
a6da10ac64b5
fuzz: make postauth set authdone properly
Matt Johnston <matt@ucc.asn.au>
parents:
1779
diff
changeset
|
27 int fuzz_run_server(const uint8_t *Data, size_t Size, int skip_kexmaths, int postauth); |
1746 | 28 int fuzz_run_client(const uint8_t *Data, size_t Size, int skip_kexmaths); |
1589
35af85194268
Add kexdh and kexecdh fuzzers
Matt Johnston <matt@ucc.asn.au>
parents:
1561
diff
changeset
|
29 const void* fuzz_get_algo(const algo_type *algos, const char* name); |
1356
3677a510f545
add wrapfd. improve fuzzer in makefile
Matt Johnston <matt@ucc.asn.au>
parents:
1348
diff
changeset
|
30 |
1369 | 31 // fuzzer functions that intrude into general code |
1357 | 32 void fuzz_kex_fakealgos(void); |
1369 | 33 int fuzz_checkpubkey_line(buffer* line, int line_num, char* filename, |
34 const char* algo, unsigned int algolen, | |
35 const unsigned char* keyblob, unsigned int keybloblen); | |
36 extern const char * const * fuzz_signkey_names; | |
1757
517fb7b62438
Add some more variation to fuzzer random number generation
Matt Johnston <matt@ucc.asn.au>
parents:
1751
diff
changeset
|
37 void fuzz_seed(const unsigned char* dat, unsigned int len); |
1782
a6da10ac64b5
fuzz: make postauth set authdone properly
Matt Johnston <matt@ucc.asn.au>
parents:
1779
diff
changeset
|
38 void fuzz_svr_hook_preloop(void); |
1741
d1b279aa5ed1
Get client fuzzer building and starting (fails straight away)
Matt Johnston <matt@ucc.asn.au>
parents:
1740
diff
changeset
|
39 |
1778 | 40 typedef void(*connect_callback)(int result, int sock, void* data, const char* errstring); |
41 struct dropbear_progress_connection *fuzz_connect_remote(const char* remotehost, const char* remoteport, | |
42 connect_callback cb, void* cb_data, | |
43 const char* bind_address, const char* bind_port); | |
44 | |
1786
a3b39df57c8b
fuzz: add an always-failing dropbear_listen() replacement
Matt Johnston <matt@ucc.asn.au>
parents:
1782
diff
changeset
|
45 int fuzz_dropbear_listen(const char* address, const char* port, |
a3b39df57c8b
fuzz: add an always-failing dropbear_listen() replacement
Matt Johnston <matt@ucc.asn.au>
parents:
1782
diff
changeset
|
46 int *socks, unsigned int sockcount, char **errstring, int *maxfd); |
a3b39df57c8b
fuzz: add an always-failing dropbear_listen() replacement
Matt Johnston <matt@ucc.asn.au>
parents:
1782
diff
changeset
|
47 |
1741
d1b279aa5ed1
Get client fuzzer building and starting (fails straight away)
Matt Johnston <matt@ucc.asn.au>
parents:
1740
diff
changeset
|
48 // helpers |
1383
f03cfe9c76ac
Disable setnonblocking(), get_socket_address(), set_sock_priority()
Matt Johnston <matt@ucc.asn.au>
parents:
1377
diff
changeset
|
49 void fuzz_get_socket_address(int fd, char **local_host, char **local_port, |
f03cfe9c76ac
Disable setnonblocking(), get_socket_address(), set_sock_priority()
Matt Johnston <matt@ucc.asn.au>
parents:
1377
diff
changeset
|
50 char **remote_host, char **remote_port, int host_lookup); |
1456
a90fdd2d2ed8
add fuzzer-preauth_nomaths
Matt Johnston <matt@ucc.asn.au>
parents:
1385
diff
changeset
|
51 void fuzz_fake_send_kexdh_reply(void); |
1740
dfbe947bdf0d
Make wrapfd share a common buffer for all FDs
Matt Johnston <matt@ucc.asn.au>
parents:
1589
diff
changeset
|
52 int fuzz_spawn_command(int *ret_writefd, int *ret_readfd, int *ret_errfd, pid_t *ret_pid); |
1751
3b9b427925a0
Load password and key for client fuzzer.
Matt Johnston <matt@ucc.asn.au>
parents:
1746
diff
changeset
|
53 void fuzz_dump(const unsigned char* data, size_t len); |
1357 | 54 |
55 // fake IO wrappers | |
56 #ifndef FUZZ_SKIP_WRAP | |
57 #define select(nfds, readfds, writefds, exceptfds, timeout) \ | |
58 wrapfd_select(nfds, readfds, writefds, exceptfds, timeout) | |
59 #define write(fd, buf, count) wrapfd_write(fd, buf, count) | |
60 #define read(fd, buf, count) wrapfd_read(fd, buf, count) | |
1358
6b89eb92f872
glaring wrapfd problems fixed
Matt Johnston <matt@ucc.asn.au>
parents:
1357
diff
changeset
|
61 #define close(fd) wrapfd_close(fd) |
1357 | 62 #endif // FUZZ_SKIP_WRAP |
63 | |
1348 | 64 struct dropbear_fuzz_options { |
65 int fuzzing; | |
66 | |
67 // fuzzing input | |
1356
3677a510f545
add wrapfd. improve fuzzer in makefile
Matt Johnston <matt@ucc.asn.au>
parents:
1348
diff
changeset
|
68 buffer *input; |
1357 | 69 struct dropbear_cipher recv_cipher; |
70 struct dropbear_hash recv_mac; | |
71 int wrapfds; | |
1348 | 72 |
1456
a90fdd2d2ed8
add fuzzer-preauth_nomaths
Matt Johnston <matt@ucc.asn.au>
parents:
1385
diff
changeset
|
73 // whether to skip slow bignum maths |
a90fdd2d2ed8
add fuzzer-preauth_nomaths
Matt Johnston <matt@ucc.asn.au>
parents:
1385
diff
changeset
|
74 int skip_kexmaths; |
1782
a6da10ac64b5
fuzz: make postauth set authdone properly
Matt Johnston <matt@ucc.asn.au>
parents:
1779
diff
changeset
|
75 // whether is svr_postauth mode |
a6da10ac64b5
fuzz: make postauth set authdone properly
Matt Johnston <matt@ucc.asn.au>
parents:
1779
diff
changeset
|
76 int svr_postauth; |
1456
a90fdd2d2ed8
add fuzzer-preauth_nomaths
Matt Johnston <matt@ucc.asn.au>
parents:
1385
diff
changeset
|
77 |
1348 | 78 // dropbear_exit() jumps back |
1385
6c92e97553f1
Add a flag whether to longjmp, missed that last commit
Matt Johnston <matt@ucc.asn.au>
parents:
1383
diff
changeset
|
79 int do_jmp; |
1348 | 80 sigjmp_buf jmp; |
1751
3b9b427925a0
Load password and key for client fuzzer.
Matt Johnston <matt@ucc.asn.au>
parents:
1746
diff
changeset
|
81 |
3b9b427925a0
Load password and key for client fuzzer.
Matt Johnston <matt@ucc.asn.au>
parents:
1746
diff
changeset
|
82 // write out decrypted session data to this FD if it's set |
3b9b427925a0
Load password and key for client fuzzer.
Matt Johnston <matt@ucc.asn.au>
parents:
1746
diff
changeset
|
83 // flag - this needs to be set manually in cli-main.c etc |
3b9b427925a0
Load password and key for client fuzzer.
Matt Johnston <matt@ucc.asn.au>
parents:
1746
diff
changeset
|
84 int dumping; |
3b9b427925a0
Load password and key for client fuzzer.
Matt Johnston <matt@ucc.asn.au>
parents:
1746
diff
changeset
|
85 // the file descriptor |
3b9b427925a0
Load password and key for client fuzzer.
Matt Johnston <matt@ucc.asn.au>
parents:
1746
diff
changeset
|
86 int recv_dumpfd; |
1758
1365661f6be6
Disable stderr output for fuzzer by default
Matt Johnston <matt@ucc.asn.au>
parents:
1757
diff
changeset
|
87 |
1365661f6be6
Disable stderr output for fuzzer by default
Matt Johnston <matt@ucc.asn.au>
parents:
1757
diff
changeset
|
88 // avoid filling fuzzing logs, this points to /dev/null |
1768
096a66e45212
Fix fuzzing stderr override on os x
Matt Johnston <matt@ucc.asn.au>
parents:
1758
diff
changeset
|
89 FILE *fake_stderr; |
1348 | 90 }; |
91 | |
92 extern struct dropbear_fuzz_options fuzz; | |
93 | |
1768
096a66e45212
Fix fuzzing stderr override on os x
Matt Johnston <matt@ucc.asn.au>
parents:
1758
diff
changeset
|
94 /* guard for when fuzz.h is included by fuzz-common.c */ |
096a66e45212
Fix fuzzing stderr override on os x
Matt Johnston <matt@ucc.asn.au>
parents:
1758
diff
changeset
|
95 #ifndef FUZZ_NO_REPLACE_STDERR |
096a66e45212
Fix fuzzing stderr override on os x
Matt Johnston <matt@ucc.asn.au>
parents:
1758
diff
changeset
|
96 |
1758
1365661f6be6
Disable stderr output for fuzzer by default
Matt Johnston <matt@ucc.asn.au>
parents:
1757
diff
changeset
|
97 /* This is a bodge but seems to work. |
1365661f6be6
Disable stderr output for fuzzer by default
Matt Johnston <matt@ucc.asn.au>
parents:
1757
diff
changeset
|
98 glibc stdio.h has the comment |
1365661f6be6
Disable stderr output for fuzzer by default
Matt Johnston <matt@ucc.asn.au>
parents:
1757
diff
changeset
|
99 "C89/C99 say they're macros. Make them happy." */ |
1768
096a66e45212
Fix fuzzing stderr override on os x
Matt Johnston <matt@ucc.asn.au>
parents:
1758
diff
changeset
|
100 /* OS X has it as a macro */ |
1758
1365661f6be6
Disable stderr output for fuzzer by default
Matt Johnston <matt@ucc.asn.au>
parents:
1757
diff
changeset
|
101 #ifdef stderr |
1365661f6be6
Disable stderr output for fuzzer by default
Matt Johnston <matt@ucc.asn.au>
parents:
1757
diff
changeset
|
102 #undef stderr |
1365661f6be6
Disable stderr output for fuzzer by default
Matt Johnston <matt@ucc.asn.au>
parents:
1757
diff
changeset
|
103 #endif |
1768
096a66e45212
Fix fuzzing stderr override on os x
Matt Johnston <matt@ucc.asn.au>
parents:
1758
diff
changeset
|
104 #define stderr (fuzz.fake_stderr) |
096a66e45212
Fix fuzzing stderr override on os x
Matt Johnston <matt@ucc.asn.au>
parents:
1758
diff
changeset
|
105 |
096a66e45212
Fix fuzzing stderr override on os x
Matt Johnston <matt@ucc.asn.au>
parents:
1758
diff
changeset
|
106 #endif /* FUZZ_NO_REPLACE_STDERR */ |
1758
1365661f6be6
Disable stderr output for fuzzer by default
Matt Johnston <matt@ucc.asn.au>
parents:
1757
diff
changeset
|
107 |
1779
36d4c027cba7
fuzzing: add workaround getpwuid/getpwnam
Matt Johnston <matt@ucc.asn.au>
parents:
1778
diff
changeset
|
108 struct passwd* fuzz_getpwuid(uid_t uid); |
36d4c027cba7
fuzzing: add workaround getpwuid/getpwnam
Matt Johnston <matt@ucc.asn.au>
parents:
1778
diff
changeset
|
109 struct passwd* fuzz_getpwnam(const char *login); |
36d4c027cba7
fuzzing: add workaround getpwuid/getpwnam
Matt Johnston <matt@ucc.asn.au>
parents:
1778
diff
changeset
|
110 /* guard for when fuzz.h is included by fuzz-common.c */ |
36d4c027cba7
fuzzing: add workaround getpwuid/getpwnam
Matt Johnston <matt@ucc.asn.au>
parents:
1778
diff
changeset
|
111 #ifndef FUZZ_NO_REPLACE_GETPW |
36d4c027cba7
fuzzing: add workaround getpwuid/getpwnam
Matt Johnston <matt@ucc.asn.au>
parents:
1778
diff
changeset
|
112 #define getpwnam(x) fuzz_getpwnam(x) |
36d4c027cba7
fuzzing: add workaround getpwuid/getpwnam
Matt Johnston <matt@ucc.asn.au>
parents:
1778
diff
changeset
|
113 #define getpwuid(x) fuzz_getpwuid(x) |
36d4c027cba7
fuzzing: add workaround getpwuid/getpwnam
Matt Johnston <matt@ucc.asn.au>
parents:
1778
diff
changeset
|
114 #endif // FUZZ_NO_REPLACE_GETPW |
36d4c027cba7
fuzzing: add workaround getpwuid/getpwnam
Matt Johnston <matt@ucc.asn.au>
parents:
1778
diff
changeset
|
115 |
1357 | 116 #endif // DROPBEAR_FUZZ |
1348 | 117 |
118 #endif /* DROPBEAR_FUZZ_H */ |