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 #define MAX_FUZZ_BUF (1024 * 1024)
75 enum proxy_parser_states {
82 enum fuzzer_parser_states {
85 FZY_FP_INJECT_PREPARE = 2,
98 enum proxy_parser_states pp;
106 enum fuzzer_parser_states fp;
110 int twin; /* must be fixed up when arrays lose guys */
111 unsigned int outbound:1; /* from local -> remote */
112 unsigned int is_pending:1;
114 unsigned char buf[MAX_FUZZ_BUF];
115 unsigned int inject_len;
121 unsigned int swallow:1;
127 static const struct test tests[] = {
128 { { NULL, "\x0d\x0a\x0d\x0a",
129 "{ 0xd9, 0x87, 0xd2, 0x88, 0xd2, (248){ 0x89, 0xd2 }, 0x0d, 0x0a },"
131 { { NULL, "\x0d\x0a\x0d\x0a",
132 "{ 0xd9, 0x87, 0xd2, 0x88, 0xd2, (1373){ 0x89, 0xd2 }, 0x0d, 0x0a },"
134 { { NULL, "\x0d\x0a\x0d\x0a",
135 "{ 0xd9, 0x87, 0xd2, 0x88, 0xd2, (16967){ 0x89, 0xd2 }, (87){ 0xe2, 0x82, 0xac }, 0x0d, 0x0a },"
137 { { NULL, "\x0d\x0a\x0d\x0a",
138 "0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, "
139 "0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, "
140 "0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x3a, 0x20, 0x77, 0x65, "
141 "0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, "
142 "0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0d, 0x0a, 0x53, 0x65, "
143 "0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2d, 0x4b, 0x65, 0x79, 0x3a, "
144 "0x20, 0x64, 0x47, 0x68, 0x6c, 0x49, 0x48, 0x4e, 0x68, 0x62, 0x58, 0x42, 0x73, 0x5a, 0x53, 0x42, "
145 "0x75, 0x62, 0x32, 0x35, 0x6a, 0x5a, 0x51, 0x3d, 0x3d, 0x0d, 0x0a, 0x4f, 0x72, 0x69, 0x67, 0x69, "
146 "0x6e, 0x3a, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, "
147 "0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, "
148 "0x65, 0x74, 0x2d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x31, 0x33, 0x0d, 0x0a, "
149 "0xef, 0xbb, 0xbf, 0xc2, 0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x48, 0x54, "
150 "0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0x31, 0x32, "
151 "0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, "
152 "0x3a, 0x20, 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, "
153 "0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x0d, 0x0a, "
155 { { NULL, "\x0d\x0a\x0d\x0a",
156 "(20){0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, "
157 "0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, "
158 "0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x3a, 0x20, 0x77, 0x65, "
159 "0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, "
160 "0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0d, 0x0a, 0x53, 0x65, "
161 "0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2d, 0x4b, 0x65, 0x79, 0x3a, "
162 "0x20, 0x64, 0x47, 0x68, 0x6c, 0x49, 0x48, 0x4e, 0x68, 0x62, 0x58, 0x42, 0x73, 0x5a, 0x53, 0x42, "
163 "0x75, 0x62, 0x32, 0x35, 0x6a, 0x5a, 0x51, 0x3d, 0x3d, 0x0d, 0x0a, 0x4f, 0x72, 0x69, 0x67, 0x69, "
164 "0x6e, 0x3a, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, "
165 "0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, "
166 "0x65, 0x74, 0x2d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x31, 0x33, 0x0d, 0x0a, "
167 "0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, "
168 "0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, "
169 "0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x3a, 0x20, 0x77, 0x65, "
170 "0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, "
171 "0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0d, 0x0a, 0x53, 0x65, "
172 "0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2d, 0x4b, 0x65, 0x79, 0x3a, "
173 "0x20, 0x64, 0x47, 0x68, 0x6c, 0x49, 0x48, 0x4e, 0x68, 0x62, 0x58, 0x42, 0x73, 0x5a, 0x53, 0x42, "
174 "0x75, 0x62, 0x32, 0x35, 0x6a, 0x5a, 0x51, 0x3d, 0x3d, 0x0d, 0x0a, 0x4f, 0x72, 0x69, 0x67, 0x69, "
175 "0x6e, 0x3a, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, "
176 "0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, "
177 "0x65, 0x74, 0x2d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x31, 0x33, 0x0d, 0x0a, "
178 "0xc2, 0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x48, 0x54, 0x54, 0x50, 0x2f, "
179 "0x31, 0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0x31, 0x32, 0x37, 0x2e, 0x30, "
180 "0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x3a, 0x20, 0x77, "
181 "0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, "
182 "0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0d, 0x0a, 0x53, "
183 "0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2d, 0x4b, 0x65, 0x79, "
184 "0x3a, 0x20, 0x64, 0x47, 0x68, 0x6c, 0x49, 0x48, 0x4e, 0x68, 0x62, 0x58, 0x42, 0x73, 0x5a, 0x53, "
185 "0x42, 0x75, 0x62, 0x32, 0x35, 0x6a, 0x5a, 0x51, 0x3d, 0x3d, 0x0d, 0x0a, 0x4f, 0x72, 0x69, 0x67, "
186 "0x69, 0x6e, 0x3a, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x31, 0x32, 0x37, 0x2e, 0x30, "
187 "0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, "
188 "0x6b, 0x65, 0x74, 0x2d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x31, 0x33, 0x0d, "
189 "0x0a, 0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x48, 0x54, 0x54, 0x50, 0x2f, "
190 "0x31, 0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0x31, 0x32, 0x37, 0x2e, 0x30, "
191 "0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x3a, 0x20, 0x77, "
192 "0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, "
193 "0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0d, 0x0a, 0x53, "
194 "0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2d, 0x4b, 0x65, 0x79, "
195 "0x3a, 0x20, 0x64, 0x47, 0x68, 0x6c, 0x49, 0x48, 0x4e, 0x68, 0x62, 0x58, 0x42, 0x73, 0x5a, 0x53, "
196 "0x42, 0x75, 0x62, 0x32, 0x35, 0x6a, 0x5a, 0x51, 0x3d, 0x3d, 0x0d, 0x0a, 0x4f, 0x72, 0x69, 0x67, "
197 "0x69, 0x6e, 0x3a, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x31, 0x32, 0x37, 0x2e, 0x30, "
198 "0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, "
199 "0x6b, 0x65, 0x74, 0x2d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x31, 0x33, 0x0d, "
200 "0x0a, 0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x48, 0x54, 0x54, 0x50, 0x2f, "
201 "0x31, 0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0x31, 0x32, 0x37, 0x2e, 0x30, "
202 "0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x3a, 0x20, 0x77, "
203 "0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, "
204 "0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0d, 0x0a, 0x53, "
205 "0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2d, 0x4b, 0x65, 0x79, "
206 "0x3a, 0x20, 0x64, 0x47, 0x68, 0x6c, 0x49, 0x48, 0x4e, 0x68, 0x62, 0x58, 0x42, 0x73, 0x5a, 0x53, "
207 "0x42, 0x75, 0x62, 0x32, 0x35, 0x6a, 0x5a, 0x51, 0x3d, 0x3d, 0x0d, 0x0a, 0x4f, 0x72, 0x69, 0x67, "
208 "0x69, 0x6e, 0x3a, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x31, 0x32, 0x37, 0x2e, 0x30, "
209 "0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, "
210 "0x6b, 0x65, 0x74, 0x2d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x31, 0x33, 0x0d, "
211 "0x0a, 0xc0, 0x80, 0xef, 0xb7, 0x90, 0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, "
212 "0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, "
213 "0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, "
214 "0x64, 0x65, 0x3a, 0x20, 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, "
215 "0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x55, 0x70, 0x67, 0x72, 0x61, "
216 "0x64, 0x65, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, "
217 "0x74, 0x2d, 0x4b, 0x65, 0x79, 0x3a, 0x20, 0x64, 0x47, 0x68, 0x6c, 0x49, 0x48, 0x4e, 0x68, 0x62, "
218 "0x58, 0x42, 0x73, 0x5a, 0x53, 0x42, 0x75, 0x62, 0x32, 0x35, 0x6a, 0x5a, 0x51, 0x3d, 0x3d, 0x0d, "
219 "0x0a, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, "
220 "0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, "
221 "0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, "
222 "0x3a, 0x20, 0x31, 0x33, 0x0d, 0x0a, 0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, "
223 "0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, "
224 "0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, "
225 "0x64, 0x65, 0x3a, 0x20, 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, "
226 "0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x55, 0x70, 0x67, 0x72, 0x61, "
227 "0x64, 0x65, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, "
228 "0x74, 0x2d, 0x4b, 0x65, 0x79, 0x3a, 0x20, 0x64, 0x47, 0x68, 0x6c, 0x49, 0x48, 0x4e, 0x68, 0x62, "
229 "0x58, 0x42, 0x73, 0x5a, 0x53, 0x42, 0x75, 0x62, 0x32, 0x35, 0x6a, 0x5a, 0x51, 0x3d, 0x3d, 0x0d, "
230 "0x0a, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, "
231 "0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, "
232 "0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, "
233 "0x3a, 0x20, 0x31, 0x33, 0x0d, 0x0a, 0xc2, 0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, "
234 "0x20, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, "
235 "0x20, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, "
236 "0x61, 0x64, 0x0d, 0x0a, }"
238 { { NULL, "\x0d\x0a\x0d\x0a",
239 "0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, "
240 "0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, "
241 "0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x3a, 0x20, 0x77, 0x65, "
242 "0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, "
243 "0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0d, 0x0a, 0x53, 0x65, "
244 "0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2d, 0x4b, 0x65, 0x79, 0x3a, "
245 "0x20, 0x64, 0x47, 0x68, 0x6c, 0x49, 0x48, 0x4e, 0x68, 0x62, 0x58, 0x42, 0x73, 0x5a, 0x53, 0x42, "
246 "0x75, 0x62, 0x32, 0x35, 0x6a, 0x5a, 0x51, 0x3d, 0x3d, 0x0d, 0x0a, 0x4f, 0x72, 0x69, 0x67, 0x69, "
247 "0x6e, 0x3a, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, "
248 "0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, "
249 "0x65, 0x74, 0x2d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x31, 0x33, 0x0d, 0x0a, "
250 "0xef, 0xbb, 0xbf, 0xc2, 0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x48, 0x54, "
251 "0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0x31, 0x32, "
252 "0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, "
253 "0x3a, 0x20, 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, "
254 "0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x0d, 0x0a, (2048){ 0x0d, 0x0a}"
258 static const int ring_size(struct ring *r)
260 return sizeof(r->buf);
262 static const int ring_used(struct ring *r)
264 return (r->head - r->tail) & (ring_size(r) - 1);
266 static const int ring_free(struct ring *r)
268 return (ring_size(r) - 1) - ring_used(r);
270 static const int ring_get_one(struct ring *r)
272 int n = r->buf[r->tail] & 255;
274 if (r->tail == r->head)
278 if (r->tail == ring_size(r))
284 static int hex(char c)
286 if (c >= '0' && c <= '9')
288 if (c >= 'a' && c <= 'f')
290 if (c >='A' && c <= 'F')
297 fuzxy_tok(const char **src, unsigned char **buf, int *len)
299 unsigned char *start;
300 unsigned int count, rlen;
304 if (**src == ' ' || **src == ',' || **src == '\n') {
309 if ((*src)[0] == '}') {
314 if ((*src)[0] == '0' && (*src)[1] == 'x') {
316 lwsl_err("out of space\n");
320 ((*buf)++)[0] = (hex((*src)[2]) << 4) | hex((*src)[3]);
325 if (*src[0] == '(') {
328 count = atoi(*src) - 1;
329 lwsl_err("count %d\n", count);
330 while (**src && **src != ')')
333 lwsl_err("unexpected end in (\n");
340 lwsl_err("missing {\n");
345 if (fuzxy_tok(src, buf, len))
350 lwsl_err("out of space\n");
353 memcpy(*buf, start, rlen);
364 fuzxy_create_pattern(const char *src, unsigned char *buf, int len)
366 unsigned char *old = buf;
369 while (*src && (*src == '{' || *src == ' '))
375 n = fuzxy_tok(&src, &buf, &len);
382 void sighandler(int sig)
387 static struct option options[] = {
388 { "help", no_argument, NULL, 'h' },
389 { "debug", required_argument, NULL, 'd' },
390 { "port", required_argument, NULL, 'p' },
391 { "ssl", no_argument, NULL, 's' },
392 { "allow-non-ssl", no_argument, NULL, 'a' },
393 { "interface", required_argument, NULL, 'i' },
394 { "closetest", no_argument, NULL, 'c' },
395 { "libev", no_argument, NULL, 'e' },
396 #ifndef LWS_NO_DAEMONIZE
397 { "daemonize", no_argument, NULL, 'D' },
399 { "resource_path", required_argument, NULL, 'r' },
403 static struct pollfd pfd[128];
404 static struct state state[128];
407 static void close_and_remove_fd(int index)
411 lwsl_notice("%s: closing index %d\n", __func__, index);
412 close(pfd[index].fd);
415 n = state[index].twin;
417 assert(state[n].twin == index);
419 state[index].type = FZY_S_DEAD;
421 if (index == pfds - 1) {
422 if (state[index].twin)
423 state[state[index].twin].twin = 0;
424 state[index].twin = 0;
428 /* swap the end guy into the deleted guy and trim back one */
430 if (state[pfds - 1].twin) {
431 state[state[pfds - 1].twin].twin = index;
432 if (n && n == pfds - 1)
436 /* swap the last guy into dead guy's place and trim by one */
437 pfd[index] = pfd[pfds - 1];
438 state[index] = state[pfds - 1];
443 close_and_remove_fd(n);
451 static void construct_state(int n, enum types s, int flags)
453 memset(&state[n], 0, sizeof state[n]);
455 pfd[n].events = flags | POLLHUP;
459 fuzxy_listen(const char *interface_name, int port, int *sockfd)
461 struct sockaddr_in serv_addr4;
462 socklen_t len = sizeof(struct sockaddr);
463 struct sockaddr_in sin;
466 *sockfd = socket(AF_INET, SOCK_STREAM, 0);
469 lwsl_err("ERROR opening socket\n");
473 if (setsockopt(*sockfd, SOL_SOCKET, SO_REUSEADDR,
474 (const void *)&opt, sizeof(opt)) < 0) {
475 lwsl_err("unable to set listen socket options\n");
479 bzero((char *) &serv_addr4, sizeof(serv_addr4));
480 serv_addr4.sin_addr.s_addr = INADDR_ANY;
481 serv_addr4.sin_family = AF_INET;
483 if (interface_name[0] &&
484 lws_interface_to_sa(0, interface_name, (struct sockaddr_in *)
485 (struct sockaddr *)&serv_addr4,
486 sizeof(serv_addr4)) < 0) {
487 lwsl_err("Unable to find interface %s\n", interface_name);
491 serv_addr4.sin_port = htons(port);
493 n = bind(*sockfd, (struct sockaddr *)&serv_addr4,
496 lwsl_err("ERROR on binding to port %d (%d %d)\n",
501 if (getsockname(*sockfd, (struct sockaddr *)&sin, &len) == -1)
502 lwsl_warn("getsockname: %s\n", strerror(errno));
504 port = ntohs(sin.sin_port);
506 listen(*sockfd, SOMAXCONN);
516 static int fuzz(int n, char *out, int len)
518 struct state *s = &state[n];
519 const struct test *t = &tests[which];
526 if (t->s[0] == NULL) {
529 s->fp = FZY_FP_SEARCH2;
532 c = ring_get_one(&state[s->twin].in);
535 if (c == tests[which].s[0][s->fuzc++]) {
536 if (s->fuzc == t->len[0]) {
538 s->fp = FZY_FP_SEARCH2;
547 if (tests[which].s[1] == NULL) {
550 s->fp = FZY_FP_INJECT_PREPARE;
553 c = ring_get_one(&state[s->twin].in);
556 if (c == tests[which].s[1][s->fuzc++]) {
557 if (s->fuzc == tests[which].len[1]) {
558 lwsl_notice("+++++++fuzzer hit...\n");
560 s->fp = FZY_FP_INJECT_PREPARE;
561 s->is_pending = !t->swallow;
571 case FZY_FP_INJECT_PREPARE:
573 s->inject_len = fuzxy_create_pattern(t->s[2],
574 s->buf, sizeof(s->buf));
575 if (s->inject_len == (unsigned int) -1)
577 s->fp = FZY_FP_INJECT;
581 out[m++] = s->buf[s->fuzc++];
582 if (s->fuzc == s->inject_len)
583 s->fp = FZY_FP_PENDING;
588 out[m++] = s->pending;
589 s->fp = FZY_FP_SEARCH;
601 struct addrinfo ai, *res, *result;
602 struct sockaddr_in serv_addr4;
603 struct state *s = &state[n];
608 m = ring_get_one(&s->in);
614 if (m != "CONNECT "[s->ppc++]) {
615 lwsl_notice("failed CONNECT match\n");
619 s->pp = FZY_PP_ADDRESS;
625 s->address[s->ppc++] = '\0';
631 s->address[s->ppc++] = '\0';
632 s->pp = FZY_PP_CRLFS;
638 s->address[s->ppc++] = m;
639 if (s->ppc == sizeof(s->address)) {
640 lwsl_notice("Failed on address length\n");
646 s->pp = FZY_PP_CRLFS;
650 if (m >= '0' && m <= '9') {
658 if (m != "\x0d\x0a\x0d\x0a"[s->ppc++])
662 s->type = FZY_S_PROXIED;
664 memset (&ai, 0, sizeof ai);
665 ai.ai_family = PF_UNSPEC;
666 ai.ai_socktype = SOCK_STREAM;
667 ai.ai_flags = AI_CANONNAME;
669 if (getaddrinfo(s->address, NULL, &ai, &result)) {
670 lwsl_notice("failed to lookup %s\n",
677 switch (res->ai_family) {
679 p = &((struct sockaddr_in *)res->
688 lwsl_notice("Failed to get address result %s\n",
690 freeaddrinfo(result);
694 serv_addr4.sin_family = AF_INET;
695 serv_addr4.sin_addr = *((struct in_addr *)p);
696 serv_addr4.sin_port = htons(s->port);
697 bzero(&serv_addr4.sin_zero, 8);
698 freeaddrinfo(result);
700 lwsl_err("Conn %d req '%s' port %d\n", n,
701 s->address, s->port);
702 /* we need to open the associated onward connection */
703 sockfd = socket(AF_INET, SOCK_STREAM, 0);
705 lwsl_err("Could not get socket\n");
709 if (connect(sockfd, (struct sockaddr *)&serv_addr4,
710 sizeof(struct sockaddr)) == -1 ||
713 lwsl_err("proxied onward connection failed\n");
717 construct_state(pfds, FZY_S_ONWARD,
718 POLLOUT | POLLIN | POLLERR);
719 state[pfds].twin = n;
720 lwsl_notice("binding conns %d and %d\n", n, pfds);
721 state[pfds].outbound = s->outbound;
723 pfd[pfds++].fd = sockfd;
725 lwsl_notice("onward connection in progress\n");
726 if (ring_used(&s->in))
727 pfd[s->twin].events |= POLLOUT;
729 "HTTP/1.0 200 \x0d\x0a\x0d\x0a", 17) < 17)
737 static void sigpipe_handler(int x)
742 main(int argc, char **argv)
744 char interface_name[128] = "", interface_name_local[128] = "lo";
745 int port_local = 8880, accept_fd;
746 struct sockaddr_in cli_addr;
755 int syslog_options = LOG_PID | LOG_PERROR;
757 #ifndef LWS_NO_DAEMONIZE
760 signal(SIGPIPE, sigpipe_handler);
763 n = getopt_long(argc, argv, "eci:hsap:d:Dr:", options, NULL);
768 opts |= LWS_SERVER_OPTION_LIBEV;
770 #ifndef LWS_NO_DAEMONIZE
774 syslog_options &= ~LOG_PERROR;
779 debug_level = atoi(optarg);
782 port_local = atoi(optarg);
785 strncpy(interface_name, optarg, sizeof interface_name);
786 interface_name[(sizeof interface_name) - 1] = '\0';
789 fprintf(stderr, "Usage: libwebsockets-test-fuzxy "
790 "[--port=<p>] [--ssl] "
791 "[-d <log bitfield>] "
792 "[--resource_path <path>]\n");
797 #if !defined(LWS_NO_DAEMONIZE) && !defined(WIN32)
799 * normally lock path would be /var/lock/lwsts or similar, to
800 * simplify getting started without having to take care about
801 * permissions or running as root, set to /tmp/.lwsts-lock
803 if (daemonize && lws_daemonize("/tmp/.lwsts-lock")) {
804 fprintf(stderr, "Failed to daemonize\n");
809 signal(SIGINT, sighandler);
812 /* we will only try to log things according to our debug_level */
813 setlogmask(LOG_UPTO (LOG_DEBUG));
814 openlog("fuzxy", syslog_options, LOG_DAEMON);
817 /* tell the library what debug level to emit and to send it to syslog */
818 lws_set_log_level(debug_level, lwsl_emit_syslog);
820 lwsl_notice("libwebsockets fuzzing proxy - license LGPL2.1+SLE\n");
821 lwsl_notice("(C) Copyright 2016 Andy Green <andy@warmcat.com>\n");
823 /* listen on local side */
825 if (fuzxy_listen(interface_name, port_local, &pfd[pfds].fd)) {
826 lwsl_err("Failed to listen on local side\n");
829 construct_state(pfds, FZY_S_LISTENING, POLLIN | POLLERR);
832 lwsl_notice("Local side listening on %s:%u\n",
833 interface_name_local, port_local);
835 while (!force_exit) {
837 m = poll(pfd, pfds, 50);
840 for (n = 0; n < pfds; n++) {
842 if (s->type == FZY_S_LISTENING &&
843 (pfd[n].revents & POLLIN)) {
844 /* first do the accept entry */
846 clilen = sizeof(cli_addr);
847 accept_fd = accept(pfd[0].fd,
848 (struct sockaddr *)&cli_addr, &clilen);
850 if (errno == EAGAIN ||
851 errno == EWOULDBLOCK)
854 lwsl_warn("ERROR on accept: %s\n",
858 construct_state(pfds, FZY_S_ACCEPTED,
860 state[pfds].outbound = n == 0;
861 state[pfds].pp = FZY_PP_CONNECT;
863 pfd[pfds++].fd = accept_fd;
864 lwsl_notice("new connect accepted\n");
867 if (pfd[n].revents & POLLIN) {
868 assert(ring_free(&s->in));
869 m = (ring_size(&s->in) - 1) -
871 if (s->in.head == ring_size(&s->in) - 1 &&
874 m = read(pfd[n].fd, s->in.buf + s->in.head, m);
875 // lwsl_notice("read %d\n", m);
877 lwsl_err("Error on read\n");
881 if (s->in.head == ring_size(&s->in))
885 case FZY_S_ACCEPTED: /* parse proxy CONNECT */
886 if (handle_accept(n))
891 if (ring_used(&s->in))
892 pfd[s->twin].events |= POLLOUT;
898 if (s->in.head == s->in.tail) {
899 s->in.head = s->in.tail = 0;
900 pfd[n].events |= POLLIN;
902 if (!ring_free(&s->in))
903 pfd[n].events &= ~POLLIN;
905 if (pfd[n].revents & POLLOUT) {
910 * draw down enough of the partner's
911 * in ring to either exhaust it
912 * or fill an output buffer
914 m = fuzz(n, out, sizeof(out));
916 lwsl_err("Error on fuzz\n");
919 lwsl_notice("got block %d\n", m);
921 m = write(pfd[n].fd, out, m);
923 lwsl_err("Error on write\n");
926 pfd[s->twin].events &= ~POLLIN;
928 pfd[n].events &= ~POLLOUT;
930 if (ring_free(&state[s->twin].in))
931 pfd[s->twin].events |= POLLIN;
942 close_and_remove_fd(n);
943 n--; /* redo this slot */
948 lwsl_notice("%s exited cleanly\n", argv[0]);