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>
70 #include <strings.h> /* bzero */
73 #define MAX_FUZZ_BUF (1024 * 1024)
83 enum proxy_parser_states {
90 enum fuzzer_parser_states {
93 FZY_FP_INJECT_PREPARE = 2,
106 enum proxy_parser_states pp;
114 enum fuzzer_parser_states fp;
118 int twin; /* must be fixed up when arrays lose guys */
119 unsigned int outbound:1; /* from local -> remote */
120 unsigned int is_pending:1;
122 unsigned char buf[MAX_FUZZ_BUF];
123 unsigned int inject_len;
129 unsigned int swallow:1;
135 static const struct test tests[] = {
136 { { NULL, "\x0d\x0a\x0d\x0a",
137 "{ 0xd9, 0x87, 0xd2, 0x88, 0xd2, (248){ 0x89, 0xd2 }, 0x0d, 0x0a },"
139 { { NULL, "\x0d\x0a\x0d\x0a",
140 "{ 0xd9, 0x87, 0xd2, 0x88, 0xd2, (1373){ 0x89, 0xd2 }, 0x0d, 0x0a },"
142 { { NULL, "\x0d\x0a\x0d\x0a",
143 "{ 0xd9, 0x87, 0xd2, 0x88, 0xd2, (16967){ 0x89, 0xd2 }, (87){ 0xe2, 0x82, 0xac }, 0x0d, 0x0a },"
145 { { NULL, "\x0d\x0a\x0d\x0a",
146 "0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, "
147 "0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, "
148 "0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x3a, 0x20, 0x77, 0x65, "
149 "0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, "
150 "0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0d, 0x0a, 0x53, 0x65, "
151 "0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2d, 0x4b, 0x65, 0x79, 0x3a, "
152 "0x20, 0x64, 0x47, 0x68, 0x6c, 0x49, 0x48, 0x4e, 0x68, 0x62, 0x58, 0x42, 0x73, 0x5a, 0x53, 0x42, "
153 "0x75, 0x62, 0x32, 0x35, 0x6a, 0x5a, 0x51, 0x3d, 0x3d, 0x0d, 0x0a, 0x4f, 0x72, 0x69, 0x67, 0x69, "
154 "0x6e, 0x3a, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, "
155 "0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, "
156 "0x65, 0x74, 0x2d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x31, 0x33, 0x0d, 0x0a, "
157 "0xef, 0xbb, 0xbf, 0xc2, 0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x48, 0x54, "
158 "0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0x31, 0x32, "
159 "0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, "
160 "0x3a, 0x20, 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, "
161 "0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x0d, 0x0a, "
163 { { NULL, "\x0d\x0a\x0d\x0a",
164 "(20){0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, "
165 "0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, "
166 "0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x3a, 0x20, 0x77, 0x65, "
167 "0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, "
168 "0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0d, 0x0a, 0x53, 0x65, "
169 "0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2d, 0x4b, 0x65, 0x79, 0x3a, "
170 "0x20, 0x64, 0x47, 0x68, 0x6c, 0x49, 0x48, 0x4e, 0x68, 0x62, 0x58, 0x42, 0x73, 0x5a, 0x53, 0x42, "
171 "0x75, 0x62, 0x32, 0x35, 0x6a, 0x5a, 0x51, 0x3d, 0x3d, 0x0d, 0x0a, 0x4f, 0x72, 0x69, 0x67, 0x69, "
172 "0x6e, 0x3a, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, "
173 "0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, "
174 "0x65, 0x74, 0x2d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x31, 0x33, 0x0d, 0x0a, "
175 "0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, "
176 "0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, "
177 "0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x3a, 0x20, 0x77, 0x65, "
178 "0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, "
179 "0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0d, 0x0a, 0x53, 0x65, "
180 "0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2d, 0x4b, 0x65, 0x79, 0x3a, "
181 "0x20, 0x64, 0x47, 0x68, 0x6c, 0x49, 0x48, 0x4e, 0x68, 0x62, 0x58, 0x42, 0x73, 0x5a, 0x53, 0x42, "
182 "0x75, 0x62, 0x32, 0x35, 0x6a, 0x5a, 0x51, 0x3d, 0x3d, 0x0d, 0x0a, 0x4f, 0x72, 0x69, 0x67, 0x69, "
183 "0x6e, 0x3a, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, "
184 "0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, "
185 "0x65, 0x74, 0x2d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x31, 0x33, 0x0d, 0x0a, "
186 "0xc2, 0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x48, 0x54, 0x54, 0x50, 0x2f, "
187 "0x31, 0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0x31, 0x32, 0x37, 0x2e, 0x30, "
188 "0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x3a, 0x20, 0x77, "
189 "0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, "
190 "0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0d, 0x0a, 0x53, "
191 "0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2d, 0x4b, 0x65, 0x79, "
192 "0x3a, 0x20, 0x64, 0x47, 0x68, 0x6c, 0x49, 0x48, 0x4e, 0x68, 0x62, 0x58, 0x42, 0x73, 0x5a, 0x53, "
193 "0x42, 0x75, 0x62, 0x32, 0x35, 0x6a, 0x5a, 0x51, 0x3d, 0x3d, 0x0d, 0x0a, 0x4f, 0x72, 0x69, 0x67, "
194 "0x69, 0x6e, 0x3a, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x31, 0x32, 0x37, 0x2e, 0x30, "
195 "0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, "
196 "0x6b, 0x65, 0x74, 0x2d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x31, 0x33, 0x0d, "
197 "0x0a, 0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x48, 0x54, 0x54, 0x50, 0x2f, "
198 "0x31, 0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0x31, 0x32, 0x37, 0x2e, 0x30, "
199 "0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x3a, 0x20, 0x77, "
200 "0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, "
201 "0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0d, 0x0a, 0x53, "
202 "0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2d, 0x4b, 0x65, 0x79, "
203 "0x3a, 0x20, 0x64, 0x47, 0x68, 0x6c, 0x49, 0x48, 0x4e, 0x68, 0x62, 0x58, 0x42, 0x73, 0x5a, 0x53, "
204 "0x42, 0x75, 0x62, 0x32, 0x35, 0x6a, 0x5a, 0x51, 0x3d, 0x3d, 0x0d, 0x0a, 0x4f, 0x72, 0x69, 0x67, "
205 "0x69, 0x6e, 0x3a, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x31, 0x32, 0x37, 0x2e, 0x30, "
206 "0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, "
207 "0x6b, 0x65, 0x74, 0x2d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x31, 0x33, 0x0d, "
208 "0x0a, 0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x48, 0x54, 0x54, 0x50, 0x2f, "
209 "0x31, 0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0x31, 0x32, 0x37, 0x2e, 0x30, "
210 "0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x3a, 0x20, 0x77, "
211 "0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, "
212 "0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0d, 0x0a, 0x53, "
213 "0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2d, 0x4b, 0x65, 0x79, "
214 "0x3a, 0x20, 0x64, 0x47, 0x68, 0x6c, 0x49, 0x48, 0x4e, 0x68, 0x62, 0x58, 0x42, 0x73, 0x5a, 0x53, "
215 "0x42, 0x75, 0x62, 0x32, 0x35, 0x6a, 0x5a, 0x51, 0x3d, 0x3d, 0x0d, 0x0a, 0x4f, 0x72, 0x69, 0x67, "
216 "0x69, 0x6e, 0x3a, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x31, 0x32, 0x37, 0x2e, 0x30, "
217 "0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, "
218 "0x6b, 0x65, 0x74, 0x2d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x31, 0x33, 0x0d, "
219 "0x0a, 0xc0, 0x80, 0xef, 0xb7, 0x90, 0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, "
220 "0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, "
221 "0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, "
222 "0x64, 0x65, 0x3a, 0x20, 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, "
223 "0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x55, 0x70, 0x67, 0x72, 0x61, "
224 "0x64, 0x65, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, "
225 "0x74, 0x2d, 0x4b, 0x65, 0x79, 0x3a, 0x20, 0x64, 0x47, 0x68, 0x6c, 0x49, 0x48, 0x4e, 0x68, 0x62, "
226 "0x58, 0x42, 0x73, 0x5a, 0x53, 0x42, 0x75, 0x62, 0x32, 0x35, 0x6a, 0x5a, 0x51, 0x3d, 0x3d, 0x0d, "
227 "0x0a, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, "
228 "0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, "
229 "0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, "
230 "0x3a, 0x20, 0x31, 0x33, 0x0d, 0x0a, 0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, "
231 "0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, "
232 "0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, "
233 "0x64, 0x65, 0x3a, 0x20, 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, "
234 "0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x55, 0x70, 0x67, 0x72, 0x61, "
235 "0x64, 0x65, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, "
236 "0x74, 0x2d, 0x4b, 0x65, 0x79, 0x3a, 0x20, 0x64, 0x47, 0x68, 0x6c, 0x49, 0x48, 0x4e, 0x68, 0x62, "
237 "0x58, 0x42, 0x73, 0x5a, 0x53, 0x42, 0x75, 0x62, 0x32, 0x35, 0x6a, 0x5a, 0x51, 0x3d, 0x3d, 0x0d, "
238 "0x0a, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, "
239 "0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, "
240 "0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, "
241 "0x3a, 0x20, 0x31, 0x33, 0x0d, 0x0a, 0xc2, 0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, "
242 "0x20, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, "
243 "0x20, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, "
244 "0x61, 0x64, 0x0d, 0x0a, }"
246 { { NULL, "\x0d\x0a\x0d\x0a",
247 "0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, "
248 "0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, "
249 "0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x3a, 0x20, 0x77, 0x65, "
250 "0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, "
251 "0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0d, 0x0a, 0x53, 0x65, "
252 "0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2d, 0x4b, 0x65, 0x79, 0x3a, "
253 "0x20, 0x64, 0x47, 0x68, 0x6c, 0x49, 0x48, 0x4e, 0x68, 0x62, 0x58, 0x42, 0x73, 0x5a, 0x53, 0x42, "
254 "0x75, 0x62, 0x32, 0x35, 0x6a, 0x5a, 0x51, 0x3d, 0x3d, 0x0d, 0x0a, 0x4f, 0x72, 0x69, 0x67, 0x69, "
255 "0x6e, 0x3a, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, "
256 "0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, "
257 "0x65, 0x74, 0x2d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x31, 0x33, 0x0d, 0x0a, "
258 "0xef, 0xbb, 0xbf, 0xc2, 0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x48, 0x54, "
259 "0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0x31, 0x32, "
260 "0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, "
261 "0x3a, 0x20, 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, "
262 "0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x0d, 0x0a, (2048){ 0x0d, 0x0a}"
266 static int ring_size(struct ring *r)
268 return sizeof(r->buf);
270 static int ring_used(struct ring *r)
272 return (r->head - r->tail) & (ring_size(r) - 1);
274 static int ring_free(struct ring *r)
276 return (ring_size(r) - 1) - ring_used(r);
278 static int ring_get_one(struct ring *r)
280 int n = r->buf[r->tail] & 255;
282 if (r->tail == r->head)
286 if (r->tail == ring_size(r))
292 static int hex(char c)
294 if (c >= '0' && c <= '9')
296 if (c >= 'a' && c <= 'f')
298 if (c >='A' && c <= 'F')
305 fuzxy_tok(const char **src, unsigned char **buf, int *len)
307 unsigned char *start;
308 unsigned int count, rlen;
312 if (**src == ' ' || **src == ',' || **src == '\n') {
317 if ((*src)[0] == '}') {
322 if ((*src)[0] == '0' && (*src)[1] == 'x') {
324 lwsl_err("out of space\n");
328 ((*buf)++)[0] = (hex((*src)[2]) << 4) | hex((*src)[3]);
333 if (*src[0] == '(') {
336 count = atoi(*src) - 1;
337 lwsl_err("count %d\n", count);
338 while (**src && **src != ')')
341 lwsl_err("unexpected end in (\n");
348 lwsl_err("missing {\n");
353 if (fuzxy_tok(src, buf, len))
358 lwsl_err("out of space\n");
361 memcpy(*buf, start, rlen);
372 fuzxy_create_pattern(const char *src, unsigned char *buf, int len)
374 unsigned char *old = buf;
377 while (*src && (*src == '{' || *src == ' '))
383 n = fuzxy_tok(&src, &buf, &len);
390 void sighandler(int sig)
395 static struct option options[] = {
396 { "help", no_argument, NULL, 'h' },
397 { "debug", required_argument, NULL, 'd' },
398 { "port", required_argument, NULL, 'p' },
399 { "ssl", no_argument, NULL, 's' },
400 { "allow-non-ssl", no_argument, NULL, 'a' },
401 { "interface", required_argument, NULL, 'i' },
402 { "closetest", no_argument, NULL, 'c' },
403 { "libev", no_argument, NULL, 'e' },
404 #ifndef LWS_NO_DAEMONIZE
405 { "daemonize", no_argument, NULL, 'D' },
407 { "resource_path", required_argument, NULL, 'r' },
411 static struct pollfd pfd[128];
412 static struct state state[128];
415 static void close_and_remove_fd(int index)
419 lwsl_notice("%s: closing index %d\n", __func__, index);
420 close(pfd[index].fd);
423 n = state[index].twin;
425 assert(state[n].twin == index);
427 state[index].type = FZY_S_DEAD;
429 if (index == pfds - 1) {
430 if (state[index].twin)
431 state[state[index].twin].twin = 0;
432 state[index].twin = 0;
436 /* swap the end guy into the deleted guy and trim back one */
438 if (state[pfds - 1].twin) {
439 state[state[pfds - 1].twin].twin = index;
440 if (n && n == pfds - 1)
444 /* swap the last guy into dead guy's place and trim by one */
445 pfd[index] = pfd[pfds - 1];
446 state[index] = state[pfds - 1];
451 close_and_remove_fd(n);
459 static void construct_state(int n, enum types s, int flags)
461 memset(&state[n], 0, sizeof state[n]);
463 pfd[n].events = flags | POLLHUP;
467 fuzxy_listen(const char *interface_name, int port, int *sockfd)
469 struct sockaddr_in serv_addr4;
470 socklen_t len = sizeof(struct sockaddr);
471 struct sockaddr_in sin;
474 *sockfd = socket(AF_INET, SOCK_STREAM, 0);
477 lwsl_err("ERROR opening socket\n");
481 if (setsockopt(*sockfd, SOL_SOCKET, SO_REUSEADDR,
482 (const void *)&opt, sizeof(opt)) < 0) {
483 lwsl_err("unable to set listen socket options\n");
487 bzero((char *) &serv_addr4, sizeof(serv_addr4));
488 serv_addr4.sin_addr.s_addr = INADDR_ANY;
489 serv_addr4.sin_family = AF_INET;
491 if (interface_name[0] &&
492 lws_interface_to_sa(0, interface_name, (struct sockaddr_in *)
493 (struct sockaddr *)&serv_addr4,
494 sizeof(serv_addr4)) < 0) {
495 lwsl_err("Unable to find interface %s\n", interface_name);
499 serv_addr4.sin_port = htons(port);
501 n = bind(*sockfd, (struct sockaddr *)&serv_addr4,
504 lwsl_err("ERROR on binding to port %d (%d %d)\n",
509 if (getsockname(*sockfd, (struct sockaddr *)&sin, &len) == -1)
510 lwsl_warn("getsockname: %s\n", strerror(errno));
512 port = ntohs(sin.sin_port);
514 listen(*sockfd, SOMAXCONN);
524 static int fuzz(int n, char *out, int len)
526 struct state *s = &state[n];
527 const struct test *t = &tests[which];
534 if (t->s[0] == NULL) {
537 s->fp = FZY_FP_SEARCH2;
540 c = ring_get_one(&state[s->twin].in);
543 if (c == tests[which].s[0][s->fuzc++]) {
544 if (s->fuzc == t->len[0]) {
546 s->fp = FZY_FP_SEARCH2;
555 if (tests[which].s[1] == NULL) {
558 s->fp = FZY_FP_INJECT_PREPARE;
561 c = ring_get_one(&state[s->twin].in);
564 if (c == tests[which].s[1][s->fuzc++]) {
565 if (s->fuzc == tests[which].len[1]) {
566 lwsl_notice("+++++++fuzzer hit...\n");
568 s->fp = FZY_FP_INJECT_PREPARE;
569 s->is_pending = !t->swallow;
579 case FZY_FP_INJECT_PREPARE:
581 s->inject_len = fuzxy_create_pattern(t->s[2],
582 s->buf, sizeof(s->buf));
583 if (s->inject_len == (unsigned int) -1)
585 s->fp = FZY_FP_INJECT;
589 out[m++] = s->buf[s->fuzc++];
590 if (s->fuzc == s->inject_len)
591 s->fp = FZY_FP_PENDING;
596 out[m++] = s->pending;
597 s->fp = FZY_FP_SEARCH;
609 struct addrinfo ai, *res, *result;
610 struct sockaddr_in serv_addr4;
611 struct state *s = &state[n];
616 m = ring_get_one(&s->in);
622 if (m != "CONNECT "[s->ppc++]) {
623 lwsl_notice("failed CONNECT match\n");
627 s->pp = FZY_PP_ADDRESS;
633 s->address[s->ppc++] = '\0';
639 s->address[s->ppc++] = '\0';
640 s->pp = FZY_PP_CRLFS;
646 s->address[s->ppc++] = m;
647 if (s->ppc == sizeof(s->address)) {
648 lwsl_notice("Failed on address length\n");
654 s->pp = FZY_PP_CRLFS;
658 if (m >= '0' && m <= '9') {
666 if (m != "\x0d\x0a\x0d\x0a"[s->ppc++])
670 s->type = FZY_S_PROXIED;
672 memset (&ai, 0, sizeof ai);
673 ai.ai_family = PF_UNSPEC;
674 ai.ai_socktype = SOCK_STREAM;
675 ai.ai_flags = AI_CANONNAME;
677 if (getaddrinfo(s->address, NULL, &ai, &result)) {
678 lwsl_notice("failed to lookup %s\n",
685 switch (res->ai_family) {
687 p = &((struct sockaddr_in *)res->
696 lwsl_notice("Failed to get address result %s\n",
698 freeaddrinfo(result);
702 serv_addr4.sin_family = AF_INET;
703 serv_addr4.sin_addr = *((struct in_addr *)p);
704 serv_addr4.sin_port = htons(s->port);
705 bzero(&serv_addr4.sin_zero, 8);
706 freeaddrinfo(result);
708 lwsl_err("Conn %d req '%s' port %d\n", n,
709 s->address, s->port);
710 /* we need to open the associated onward connection */
711 sockfd = socket(AF_INET, SOCK_STREAM, 0);
713 lwsl_err("Could not get socket\n");
717 if (connect(sockfd, (struct sockaddr *)&serv_addr4,
718 sizeof(struct sockaddr)) == -1 ||
721 lwsl_err("proxied onward connection failed\n");
725 construct_state(pfds, FZY_S_ONWARD,
726 POLLOUT | POLLIN | POLLERR);
727 state[pfds].twin = n;
728 lwsl_notice("binding conns %d and %d\n", n, pfds);
729 state[pfds].outbound = s->outbound;
731 pfd[pfds++].fd = sockfd;
733 lwsl_notice("onward connection in progress\n");
734 if (ring_used(&s->in))
735 pfd[s->twin].events |= POLLOUT;
737 "HTTP/1.0 200 \x0d\x0a\x0d\x0a", 17) < 17)
745 static void sigpipe_handler(int x)
750 main(int argc, char **argv)
752 char interface_name[128] = "", interface_name_local[128] = "lo";
753 int port_local = 8880, accept_fd;
754 struct sockaddr_in cli_addr;
763 /* LOG_PERROR is not POSIX standard, and may not be portable */
765 int syslog_options = LOG_PID;
767 int syslog_options = LOG_PID | LOG_PERROR;
770 #ifndef LWS_NO_DAEMONIZE
773 signal(SIGPIPE, sigpipe_handler);
776 n = getopt_long(argc, argv, "eci:hsap:d:Dr:", options, NULL);
781 opts |= LWS_SERVER_OPTION_LIBEV;
783 #ifndef LWS_NO_DAEMONIZE
786 #if !defined(_WIN32) && !defined(__sun)
787 syslog_options &= ~LOG_PERROR;
792 debug_level = atoi(optarg);
795 port_local = atoi(optarg);
798 strncpy(interface_name, optarg, sizeof interface_name);
799 interface_name[(sizeof interface_name) - 1] = '\0';
802 fprintf(stderr, "Usage: libwebsockets-test-fuzxy "
803 "[--port=<p>] [--ssl] "
804 "[-d <log bitfield>] "
805 "[--resource_path <path>]\n");
810 #if !defined(LWS_NO_DAEMONIZE) && !defined(WIN32)
812 * normally lock path would be /var/lock/lwsts or similar, to
813 * simplify getting started without having to take care about
814 * permissions or running as root, set to /tmp/.lwsts-lock
816 if (daemonize && lws_daemonize("/tmp/.lwsts-lock")) {
817 fprintf(stderr, "Failed to daemonize\n");
822 signal(SIGINT, sighandler);
825 /* we will only try to log things according to our debug_level */
826 setlogmask(LOG_UPTO (LOG_DEBUG));
827 openlog("fuzxy", syslog_options, LOG_DAEMON);
830 /* tell the library what debug level to emit and to send it to syslog */
831 lws_set_log_level(debug_level, lwsl_emit_syslog);
833 lwsl_notice("libwebsockets fuzzing proxy - license LGPL2.1+SLE\n");
834 lwsl_notice("(C) Copyright 2016 Andy Green <andy@warmcat.com>\n");
836 /* listen on local side */
838 if (fuzxy_listen(interface_name, port_local, &pfd[pfds].fd)) {
839 lwsl_err("Failed to listen on local side\n");
842 construct_state(pfds, FZY_S_LISTENING, POLLIN | POLLERR);
845 (void)interface_name_local;
846 lwsl_notice("Local side listening on %s:%u\n",
847 interface_name_local, port_local);
849 while (!force_exit) {
851 m = poll(pfd, pfds, 50);
854 for (n = 0; n < pfds; n++) {
856 if (s->type == FZY_S_LISTENING &&
857 (pfd[n].revents & POLLIN)) {
858 /* first do the accept entry */
860 clilen = sizeof(cli_addr);
861 accept_fd = accept(pfd[0].fd,
862 (struct sockaddr *)&cli_addr, &clilen);
864 if (errno == EAGAIN ||
865 errno == EWOULDBLOCK)
868 lwsl_warn("ERROR on accept: %s\n",
872 construct_state(pfds, FZY_S_ACCEPTED,
874 state[pfds].outbound = n == 0;
875 state[pfds].pp = FZY_PP_CONNECT;
877 pfd[pfds++].fd = accept_fd;
878 lwsl_notice("new connect accepted\n");
881 if (pfd[n].revents & POLLIN) {
882 assert(ring_free(&s->in));
883 m = (ring_size(&s->in) - 1) -
885 if (s->in.head == ring_size(&s->in) - 1 &&
888 m = read(pfd[n].fd, s->in.buf + s->in.head, m);
889 // lwsl_notice("read %d\n", m);
891 lwsl_err("Error on read\n");
895 if (s->in.head == ring_size(&s->in))
899 case FZY_S_ACCEPTED: /* parse proxy CONNECT */
900 if (handle_accept(n))
905 if (ring_used(&s->in))
906 pfd[s->twin].events |= POLLOUT;
912 if (s->in.head == s->in.tail) {
913 s->in.head = s->in.tail = 0;
914 pfd[n].events |= POLLIN;
916 if (!ring_free(&s->in))
917 pfd[n].events &= ~POLLIN;
919 if (pfd[n].revents & POLLOUT) {
924 * draw down enough of the partner's
925 * in ring to either exhaust it
926 * or fill an output buffer
928 m = fuzz(n, out, sizeof(out));
930 lwsl_err("Error on fuzz\n");
933 lwsl_notice("got block %d\n", m);
935 m = write(pfd[n].fd, out, m);
937 lwsl_err("Error on write\n");
940 pfd[s->twin].events &= ~POLLIN;
942 pfd[n].events &= ~POLLOUT;
944 if (ring_free(&state[s->twin].in))
945 pfd[s->twin].events |= POLLIN;
956 close_and_remove_fd(n);
957 n--; /* redo this slot */
962 lwsl_notice("%s exited cleanly\n", argv[0]);