2 * fuzzing proxy - network-level fuzzing injection proxy
4 * Copyright (C) 2016 Andy Green <andy@warmcat.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation:
9 * version 2.1 of the License.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22 * fuzxy is designed to go on the client path
24 * [ client <-> fuzxy ] <-> server
26 * you can arrange that with, eg,
28 * http_proxy=localhost:8880
30 * env var before starting the client.
32 * Even though he is on the client side, he is able to see and change traffic
33 * in both directions, and so fuzz both the client and the server.
36 #if defined(_WIN32) && defined(EXTERNAL_POLL)
38 #define _WIN32_WINNT 0x0600
39 #define poll(fdArray, fds, timeout) WSAPoll((LPWSAPOLLFD)(fdArray), (ULONG)(fds), (INT)(timeout))
42 #include "lws_config.h"
53 #include "../lib/libwebsockets.h"
57 #include "gettimeofday.h"
62 #include <sys/socket.h>
65 #if defined(__NetBSD__)
66 #include <netinet/in.h>
69 #define MAX_FUZZ_BUF (1024 * 1024)
79 enum proxy_parser_states {
86 enum fuzzer_parser_states {
89 FZY_FP_INJECT_PREPARE = 2,
102 enum proxy_parser_states pp;
110 enum fuzzer_parser_states fp;
114 int twin; /* must be fixed up when arrays lose guys */
115 unsigned int outbound:1; /* from local -> remote */
116 unsigned int is_pending:1;
118 unsigned char buf[MAX_FUZZ_BUF];
119 unsigned int inject_len;
125 unsigned int swallow:1;
131 static const struct test tests[] = {
132 { { NULL, "\x0d\x0a\x0d\x0a",
133 "{ 0xd9, 0x87, 0xd2, 0x88, 0xd2, (248){ 0x89, 0xd2 }, 0x0d, 0x0a },"
135 { { NULL, "\x0d\x0a\x0d\x0a",
136 "{ 0xd9, 0x87, 0xd2, 0x88, 0xd2, (1373){ 0x89, 0xd2 }, 0x0d, 0x0a },"
138 { { NULL, "\x0d\x0a\x0d\x0a",
139 "{ 0xd9, 0x87, 0xd2, 0x88, 0xd2, (16967){ 0x89, 0xd2 }, (87){ 0xe2, 0x82, 0xac }, 0x0d, 0x0a },"
141 { { NULL, "\x0d\x0a\x0d\x0a",
142 "0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, "
143 "0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, "
144 "0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x3a, 0x20, 0x77, 0x65, "
145 "0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, "
146 "0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0d, 0x0a, 0x53, 0x65, "
147 "0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2d, 0x4b, 0x65, 0x79, 0x3a, "
148 "0x20, 0x64, 0x47, 0x68, 0x6c, 0x49, 0x48, 0x4e, 0x68, 0x62, 0x58, 0x42, 0x73, 0x5a, 0x53, 0x42, "
149 "0x75, 0x62, 0x32, 0x35, 0x6a, 0x5a, 0x51, 0x3d, 0x3d, 0x0d, 0x0a, 0x4f, 0x72, 0x69, 0x67, 0x69, "
150 "0x6e, 0x3a, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, "
151 "0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, "
152 "0x65, 0x74, 0x2d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x31, 0x33, 0x0d, 0x0a, "
153 "0xef, 0xbb, 0xbf, 0xc2, 0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x48, 0x54, "
154 "0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0x31, 0x32, "
155 "0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, "
156 "0x3a, 0x20, 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, "
157 "0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x0d, 0x0a, "
159 { { NULL, "\x0d\x0a\x0d\x0a",
160 "(20){0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, "
161 "0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, "
162 "0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x3a, 0x20, 0x77, 0x65, "
163 "0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, "
164 "0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0d, 0x0a, 0x53, 0x65, "
165 "0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2d, 0x4b, 0x65, 0x79, 0x3a, "
166 "0x20, 0x64, 0x47, 0x68, 0x6c, 0x49, 0x48, 0x4e, 0x68, 0x62, 0x58, 0x42, 0x73, 0x5a, 0x53, 0x42, "
167 "0x75, 0x62, 0x32, 0x35, 0x6a, 0x5a, 0x51, 0x3d, 0x3d, 0x0d, 0x0a, 0x4f, 0x72, 0x69, 0x67, 0x69, "
168 "0x6e, 0x3a, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, "
169 "0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, "
170 "0x65, 0x74, 0x2d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x31, 0x33, 0x0d, 0x0a, "
171 "0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, "
172 "0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, "
173 "0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x3a, 0x20, 0x77, 0x65, "
174 "0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, "
175 "0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0d, 0x0a, 0x53, 0x65, "
176 "0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2d, 0x4b, 0x65, 0x79, 0x3a, "
177 "0x20, 0x64, 0x47, 0x68, 0x6c, 0x49, 0x48, 0x4e, 0x68, 0x62, 0x58, 0x42, 0x73, 0x5a, 0x53, 0x42, "
178 "0x75, 0x62, 0x32, 0x35, 0x6a, 0x5a, 0x51, 0x3d, 0x3d, 0x0d, 0x0a, 0x4f, 0x72, 0x69, 0x67, 0x69, "
179 "0x6e, 0x3a, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, "
180 "0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, "
181 "0x65, 0x74, 0x2d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x31, 0x33, 0x0d, 0x0a, "
182 "0xc2, 0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x48, 0x54, 0x54, 0x50, 0x2f, "
183 "0x31, 0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0x31, 0x32, 0x37, 0x2e, 0x30, "
184 "0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x3a, 0x20, 0x77, "
185 "0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, "
186 "0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0d, 0x0a, 0x53, "
187 "0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2d, 0x4b, 0x65, 0x79, "
188 "0x3a, 0x20, 0x64, 0x47, 0x68, 0x6c, 0x49, 0x48, 0x4e, 0x68, 0x62, 0x58, 0x42, 0x73, 0x5a, 0x53, "
189 "0x42, 0x75, 0x62, 0x32, 0x35, 0x6a, 0x5a, 0x51, 0x3d, 0x3d, 0x0d, 0x0a, 0x4f, 0x72, 0x69, 0x67, "
190 "0x69, 0x6e, 0x3a, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x31, 0x32, 0x37, 0x2e, 0x30, "
191 "0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, "
192 "0x6b, 0x65, 0x74, 0x2d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x31, 0x33, 0x0d, "
193 "0x0a, 0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x48, 0x54, 0x54, 0x50, 0x2f, "
194 "0x31, 0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0x31, 0x32, 0x37, 0x2e, 0x30, "
195 "0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x3a, 0x20, 0x77, "
196 "0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, "
197 "0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0d, 0x0a, 0x53, "
198 "0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2d, 0x4b, 0x65, 0x79, "
199 "0x3a, 0x20, 0x64, 0x47, 0x68, 0x6c, 0x49, 0x48, 0x4e, 0x68, 0x62, 0x58, 0x42, 0x73, 0x5a, 0x53, "
200 "0x42, 0x75, 0x62, 0x32, 0x35, 0x6a, 0x5a, 0x51, 0x3d, 0x3d, 0x0d, 0x0a, 0x4f, 0x72, 0x69, 0x67, "
201 "0x69, 0x6e, 0x3a, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x31, 0x32, 0x37, 0x2e, 0x30, "
202 "0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, "
203 "0x6b, 0x65, 0x74, 0x2d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x31, 0x33, 0x0d, "
204 "0x0a, 0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x48, 0x54, 0x54, 0x50, 0x2f, "
205 "0x31, 0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0x31, 0x32, 0x37, 0x2e, 0x30, "
206 "0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x3a, 0x20, 0x77, "
207 "0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, "
208 "0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0d, 0x0a, 0x53, "
209 "0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2d, 0x4b, 0x65, 0x79, "
210 "0x3a, 0x20, 0x64, 0x47, 0x68, 0x6c, 0x49, 0x48, 0x4e, 0x68, 0x62, 0x58, 0x42, 0x73, 0x5a, 0x53, "
211 "0x42, 0x75, 0x62, 0x32, 0x35, 0x6a, 0x5a, 0x51, 0x3d, 0x3d, 0x0d, 0x0a, 0x4f, 0x72, 0x69, 0x67, "
212 "0x69, 0x6e, 0x3a, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x31, 0x32, 0x37, 0x2e, 0x30, "
213 "0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, "
214 "0x6b, 0x65, 0x74, 0x2d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x31, 0x33, 0x0d, "
215 "0x0a, 0xc0, 0x80, 0xef, 0xb7, 0x90, 0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, "
216 "0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, "
217 "0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, "
218 "0x64, 0x65, 0x3a, 0x20, 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, "
219 "0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x55, 0x70, 0x67, 0x72, 0x61, "
220 "0x64, 0x65, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, "
221 "0x74, 0x2d, 0x4b, 0x65, 0x79, 0x3a, 0x20, 0x64, 0x47, 0x68, 0x6c, 0x49, 0x48, 0x4e, 0x68, 0x62, "
222 "0x58, 0x42, 0x73, 0x5a, 0x53, 0x42, 0x75, 0x62, 0x32, 0x35, 0x6a, 0x5a, 0x51, 0x3d, 0x3d, 0x0d, "
223 "0x0a, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, "
224 "0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, "
225 "0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, "
226 "0x3a, 0x20, 0x31, 0x33, 0x0d, 0x0a, 0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, "
227 "0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, "
228 "0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, "
229 "0x64, 0x65, 0x3a, 0x20, 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, "
230 "0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x55, 0x70, 0x67, 0x72, 0x61, "
231 "0x64, 0x65, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, "
232 "0x74, 0x2d, 0x4b, 0x65, 0x79, 0x3a, 0x20, 0x64, 0x47, 0x68, 0x6c, 0x49, 0x48, 0x4e, 0x68, 0x62, "
233 "0x58, 0x42, 0x73, 0x5a, 0x53, 0x42, 0x75, 0x62, 0x32, 0x35, 0x6a, 0x5a, 0x51, 0x3d, 0x3d, 0x0d, "
234 "0x0a, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, "
235 "0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, "
236 "0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, "
237 "0x3a, 0x20, 0x31, 0x33, 0x0d, 0x0a, 0xc2, 0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, "
238 "0x20, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, "
239 "0x20, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, "
240 "0x61, 0x64, 0x0d, 0x0a, }"
242 { { NULL, "\x0d\x0a\x0d\x0a",
243 "0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, "
244 "0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, "
245 "0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x3a, 0x20, 0x77, 0x65, "
246 "0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, "
247 "0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0d, 0x0a, 0x53, 0x65, "
248 "0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2d, 0x4b, 0x65, 0x79, 0x3a, "
249 "0x20, 0x64, 0x47, 0x68, 0x6c, 0x49, 0x48, 0x4e, 0x68, 0x62, 0x58, 0x42, 0x73, 0x5a, 0x53, 0x42, "
250 "0x75, 0x62, 0x32, 0x35, 0x6a, 0x5a, 0x51, 0x3d, 0x3d, 0x0d, 0x0a, 0x4f, 0x72, 0x69, 0x67, 0x69, "
251 "0x6e, 0x3a, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, "
252 "0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, "
253 "0x65, 0x74, 0x2d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x31, 0x33, 0x0d, 0x0a, "
254 "0xef, 0xbb, 0xbf, 0xc2, 0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x48, 0x54, "
255 "0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0x31, 0x32, "
256 "0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, "
257 "0x3a, 0x20, 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, "
258 "0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x0d, 0x0a, (2048){ 0x0d, 0x0a}"
262 static const int ring_size(struct ring *r)
264 return sizeof(r->buf);
266 static const int ring_used(struct ring *r)
268 return (r->head - r->tail) & (ring_size(r) - 1);
270 static const int ring_free(struct ring *r)
272 return (ring_size(r) - 1) - ring_used(r);
274 static const int ring_get_one(struct ring *r)
276 int n = r->buf[r->tail] & 255;
278 if (r->tail == r->head)
282 if (r->tail == ring_size(r))
288 static int hex(char c)
290 if (c >= '0' && c <= '9')
292 if (c >= 'a' && c <= 'f')
294 if (c >='A' && c <= 'F')
301 fuzxy_tok(const char **src, unsigned char **buf, int *len)
303 unsigned char *start;
304 unsigned int count, rlen;
308 if (**src == ' ' || **src == ',' || **src == '\n') {
313 if ((*src)[0] == '}') {
318 if ((*src)[0] == '0' && (*src)[1] == 'x') {
320 lwsl_err("out of space\n");
324 ((*buf)++)[0] = (hex((*src)[2]) << 4) | hex((*src)[3]);
329 if (*src[0] == '(') {
332 count = atoi(*src) - 1;
333 lwsl_err("count %d\n", count);
334 while (**src && **src != ')')
337 lwsl_err("unexpected end in (\n");
344 lwsl_err("missing {\n");
349 if (fuzxy_tok(src, buf, len))
354 lwsl_err("out of space\n");
357 memcpy(*buf, start, rlen);
368 fuzxy_create_pattern(const char *src, unsigned char *buf, int len)
370 unsigned char *old = buf;
373 while (*src && (*src == '{' || *src == ' '))
379 n = fuzxy_tok(&src, &buf, &len);
386 void sighandler(int sig)
391 static struct option options[] = {
392 { "help", no_argument, NULL, 'h' },
393 { "debug", required_argument, NULL, 'd' },
394 { "port", required_argument, NULL, 'p' },
395 { "ssl", no_argument, NULL, 's' },
396 { "allow-non-ssl", no_argument, NULL, 'a' },
397 { "interface", required_argument, NULL, 'i' },
398 { "closetest", no_argument, NULL, 'c' },
399 { "libev", no_argument, NULL, 'e' },
400 #ifndef LWS_NO_DAEMONIZE
401 { "daemonize", no_argument, NULL, 'D' },
403 { "resource_path", required_argument, NULL, 'r' },
407 static struct pollfd pfd[128];
408 static struct state state[128];
411 static void close_and_remove_fd(int index)
415 lwsl_notice("%s: closing index %d\n", __func__, index);
416 close(pfd[index].fd);
419 n = state[index].twin;
421 assert(state[n].twin == index);
423 state[index].type = FZY_S_DEAD;
425 if (index == pfds - 1) {
426 if (state[index].twin)
427 state[state[index].twin].twin = 0;
428 state[index].twin = 0;
432 /* swap the end guy into the deleted guy and trim back one */
434 if (state[pfds - 1].twin) {
435 state[state[pfds - 1].twin].twin = index;
436 if (n && n == pfds - 1)
440 /* swap the last guy into dead guy's place and trim by one */
441 pfd[index] = pfd[pfds - 1];
442 state[index] = state[pfds - 1];
447 close_and_remove_fd(n);
455 static void construct_state(int n, enum types s, int flags)
457 memset(&state[n], 0, sizeof state[n]);
459 pfd[n].events = flags | POLLHUP;
463 fuzxy_listen(const char *interface_name, int port, int *sockfd)
465 struct sockaddr_in serv_addr4;
466 socklen_t len = sizeof(struct sockaddr);
467 struct sockaddr_in sin;
470 *sockfd = socket(AF_INET, SOCK_STREAM, 0);
473 lwsl_err("ERROR opening socket\n");
477 if (setsockopt(*sockfd, SOL_SOCKET, SO_REUSEADDR,
478 (const void *)&opt, sizeof(opt)) < 0) {
479 lwsl_err("unable to set listen socket options\n");
483 bzero((char *) &serv_addr4, sizeof(serv_addr4));
484 serv_addr4.sin_addr.s_addr = INADDR_ANY;
485 serv_addr4.sin_family = AF_INET;
487 if (interface_name[0] &&
488 lws_interface_to_sa(0, interface_name, (struct sockaddr_in *)
489 (struct sockaddr *)&serv_addr4,
490 sizeof(serv_addr4)) < 0) {
491 lwsl_err("Unable to find interface %s\n", interface_name);
495 serv_addr4.sin_port = htons(port);
497 n = bind(*sockfd, (struct sockaddr *)&serv_addr4,
500 lwsl_err("ERROR on binding to port %d (%d %d)\n",
505 if (getsockname(*sockfd, (struct sockaddr *)&sin, &len) == -1)
506 lwsl_warn("getsockname: %s\n", strerror(errno));
508 port = ntohs(sin.sin_port);
510 listen(*sockfd, SOMAXCONN);
520 static int fuzz(int n, char *out, int len)
522 struct state *s = &state[n];
523 const struct test *t = &tests[which];
530 if (t->s[0] == NULL) {
533 s->fp = FZY_FP_SEARCH2;
536 c = ring_get_one(&state[s->twin].in);
539 if (c == tests[which].s[0][s->fuzc++]) {
540 if (s->fuzc == t->len[0]) {
542 s->fp = FZY_FP_SEARCH2;
551 if (tests[which].s[1] == NULL) {
554 s->fp = FZY_FP_INJECT_PREPARE;
557 c = ring_get_one(&state[s->twin].in);
560 if (c == tests[which].s[1][s->fuzc++]) {
561 if (s->fuzc == tests[which].len[1]) {
562 lwsl_notice("+++++++fuzzer hit...\n");
564 s->fp = FZY_FP_INJECT_PREPARE;
565 s->is_pending = !t->swallow;
575 case FZY_FP_INJECT_PREPARE:
577 s->inject_len = fuzxy_create_pattern(t->s[2],
578 s->buf, sizeof(s->buf));
579 if (s->inject_len == (unsigned int) -1)
581 s->fp = FZY_FP_INJECT;
585 out[m++] = s->buf[s->fuzc++];
586 if (s->fuzc == s->inject_len)
587 s->fp = FZY_FP_PENDING;
592 out[m++] = s->pending;
593 s->fp = FZY_FP_SEARCH;
605 struct addrinfo ai, *res, *result;
606 struct sockaddr_in serv_addr4;
607 struct state *s = &state[n];
612 m = ring_get_one(&s->in);
618 if (m != "CONNECT "[s->ppc++]) {
619 lwsl_notice("failed CONNECT match\n");
623 s->pp = FZY_PP_ADDRESS;
629 s->address[s->ppc++] = '\0';
635 s->address[s->ppc++] = '\0';
636 s->pp = FZY_PP_CRLFS;
642 s->address[s->ppc++] = m;
643 if (s->ppc == sizeof(s->address)) {
644 lwsl_notice("Failed on address length\n");
650 s->pp = FZY_PP_CRLFS;
654 if (m >= '0' && m <= '9') {
662 if (m != "\x0d\x0a\x0d\x0a"[s->ppc++])
666 s->type = FZY_S_PROXIED;
668 memset (&ai, 0, sizeof ai);
669 ai.ai_family = PF_UNSPEC;
670 ai.ai_socktype = SOCK_STREAM;
671 ai.ai_flags = AI_CANONNAME;
673 if (getaddrinfo(s->address, NULL, &ai, &result)) {
674 lwsl_notice("failed to lookup %s\n",
681 switch (res->ai_family) {
683 p = &((struct sockaddr_in *)res->
692 lwsl_notice("Failed to get address result %s\n",
694 freeaddrinfo(result);
698 serv_addr4.sin_family = AF_INET;
699 serv_addr4.sin_addr = *((struct in_addr *)p);
700 serv_addr4.sin_port = htons(s->port);
701 bzero(&serv_addr4.sin_zero, 8);
702 freeaddrinfo(result);
704 lwsl_err("Conn %d req '%s' port %d\n", n,
705 s->address, s->port);
706 /* we need to open the associated onward connection */
707 sockfd = socket(AF_INET, SOCK_STREAM, 0);
709 lwsl_err("Could not get socket\n");
713 if (connect(sockfd, (struct sockaddr *)&serv_addr4,
714 sizeof(struct sockaddr)) == -1 ||
717 lwsl_err("proxied onward connection failed\n");
721 construct_state(pfds, FZY_S_ONWARD,
722 POLLOUT | POLLIN | POLLERR);
723 state[pfds].twin = n;
724 lwsl_notice("binding conns %d and %d\n", n, pfds);
725 state[pfds].outbound = s->outbound;
727 pfd[pfds++].fd = sockfd;
729 lwsl_notice("onward connection in progress\n");
730 if (ring_used(&s->in))
731 pfd[s->twin].events |= POLLOUT;
733 "HTTP/1.0 200 \x0d\x0a\x0d\x0a", 17) < 17)
741 static void sigpipe_handler(int x)
746 main(int argc, char **argv)
748 char interface_name[128] = "", interface_name_local[128] = "lo";
749 int port_local = 8880, accept_fd;
750 struct sockaddr_in cli_addr;
759 int syslog_options = LOG_PID | LOG_PERROR;
761 #ifndef LWS_NO_DAEMONIZE
764 signal(SIGPIPE, sigpipe_handler);
767 n = getopt_long(argc, argv, "eci:hsap:d:Dr:", options, NULL);
772 opts |= LWS_SERVER_OPTION_LIBEV;
774 #ifndef LWS_NO_DAEMONIZE
778 syslog_options &= ~LOG_PERROR;
783 debug_level = atoi(optarg);
786 port_local = atoi(optarg);
789 strncpy(interface_name, optarg, sizeof interface_name);
790 interface_name[(sizeof interface_name) - 1] = '\0';
793 fprintf(stderr, "Usage: libwebsockets-test-fuzxy "
794 "[--port=<p>] [--ssl] "
795 "[-d <log bitfield>] "
796 "[--resource_path <path>]\n");
801 #if !defined(LWS_NO_DAEMONIZE) && !defined(WIN32)
803 * normally lock path would be /var/lock/lwsts or similar, to
804 * simplify getting started without having to take care about
805 * permissions or running as root, set to /tmp/.lwsts-lock
807 if (daemonize && lws_daemonize("/tmp/.lwsts-lock")) {
808 fprintf(stderr, "Failed to daemonize\n");
813 signal(SIGINT, sighandler);
816 /* we will only try to log things according to our debug_level */
817 setlogmask(LOG_UPTO (LOG_DEBUG));
818 openlog("fuzxy", syslog_options, LOG_DAEMON);
821 /* tell the library what debug level to emit and to send it to syslog */
822 lws_set_log_level(debug_level, lwsl_emit_syslog);
824 lwsl_notice("libwebsockets fuzzing proxy - license LGPL2.1+SLE\n");
825 lwsl_notice("(C) Copyright 2016 Andy Green <andy@warmcat.com>\n");
827 /* listen on local side */
829 if (fuzxy_listen(interface_name, port_local, &pfd[pfds].fd)) {
830 lwsl_err("Failed to listen on local side\n");
833 construct_state(pfds, FZY_S_LISTENING, POLLIN | POLLERR);
836 lwsl_notice("Local side listening on %s:%u\n",
837 interface_name_local, port_local);
839 while (!force_exit) {
841 m = poll(pfd, pfds, 50);
844 for (n = 0; n < pfds; n++) {
846 if (s->type == FZY_S_LISTENING &&
847 (pfd[n].revents & POLLIN)) {
848 /* first do the accept entry */
850 clilen = sizeof(cli_addr);
851 accept_fd = accept(pfd[0].fd,
852 (struct sockaddr *)&cli_addr, &clilen);
854 if (errno == EAGAIN ||
855 errno == EWOULDBLOCK)
858 lwsl_warn("ERROR on accept: %s\n",
862 construct_state(pfds, FZY_S_ACCEPTED,
864 state[pfds].outbound = n == 0;
865 state[pfds].pp = FZY_PP_CONNECT;
867 pfd[pfds++].fd = accept_fd;
868 lwsl_notice("new connect accepted\n");
871 if (pfd[n].revents & POLLIN) {
872 assert(ring_free(&s->in));
873 m = (ring_size(&s->in) - 1) -
875 if (s->in.head == ring_size(&s->in) - 1 &&
878 m = read(pfd[n].fd, s->in.buf + s->in.head, m);
879 // lwsl_notice("read %d\n", m);
881 lwsl_err("Error on read\n");
885 if (s->in.head == ring_size(&s->in))
889 case FZY_S_ACCEPTED: /* parse proxy CONNECT */
890 if (handle_accept(n))
895 if (ring_used(&s->in))
896 pfd[s->twin].events |= POLLOUT;
902 if (s->in.head == s->in.tail) {
903 s->in.head = s->in.tail = 0;
904 pfd[n].events |= POLLIN;
906 if (!ring_free(&s->in))
907 pfd[n].events &= ~POLLIN;
909 if (pfd[n].revents & POLLOUT) {
914 * draw down enough of the partner's
915 * in ring to either exhaust it
916 * or fill an output buffer
918 m = fuzz(n, out, sizeof(out));
920 lwsl_err("Error on fuzz\n");
923 lwsl_notice("got block %d\n", m);
925 m = write(pfd[n].fd, out, m);
927 lwsl_err("Error on write\n");
930 pfd[s->twin].events &= ~POLLIN;
932 pfd[n].events &= ~POLLOUT;
934 if (ring_free(&state[s->twin].in))
935 pfd[s->twin].events |= POLLIN;
946 close_and_remove_fd(n);
947 n--; /* redo this slot */
952 lwsl_notice("%s exited cleanly\n", argv[0]);