2016-01-18 09:24:35 +08:00
|
|
|
/*
|
|
|
|
* fuzzing proxy - network-level fuzzing injection proxy
|
|
|
|
*
|
|
|
|
* Copyright (C) 2016 Andy Green <andy@warmcat.com>
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation:
|
|
|
|
* version 2.1 of the License.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
|
|
* MA 02110-1301 USA
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* fuzxy is designed to go on the client path
|
|
|
|
*
|
|
|
|
* [ client <-> fuzxy ] <-> server
|
|
|
|
*
|
|
|
|
* you can arrange that with, eg,
|
|
|
|
*
|
|
|
|
* http_proxy=localhost:8880
|
|
|
|
*
|
|
|
|
* env var before starting the client.
|
|
|
|
*
|
|
|
|
* Even though he is on the client side, he is able to see and change traffic
|
|
|
|
* in both directions, and so fuzz both the client and the server.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#if defined(_WIN32) && defined(EXTERNAL_POLL)
|
|
|
|
#define WINVER 0x0600
|
|
|
|
#define _WIN32_WINNT 0x0600
|
|
|
|
#define poll(fdArray, fds, timeout) WSAPoll((LPWSAPOLLFD)(fdArray), (ULONG)(fds), (INT)(timeout))
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "lws_config.h"
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <getopt.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <assert.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include "../lib/libwebsockets.h"
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
#include <io.h>
|
|
|
|
#include "gettimeofday.h"
|
|
|
|
#else
|
|
|
|
#include <syslog.h>
|
|
|
|
#include <sys/time.h>
|
|
|
|
#include <unistd.h>
|
2016-01-25 21:00:37 +08:00
|
|
|
#include <sys/socket.h>
|
2016-01-18 09:24:35 +08:00
|
|
|
#endif
|
|
|
|
|
2016-01-21 10:54:51 +08:00
|
|
|
#define MAX_FUZZ_BUF (1024 * 1024)
|
2016-01-18 09:24:35 +08:00
|
|
|
|
|
|
|
enum types {
|
|
|
|
FZY_S_DEAD = 0,
|
|
|
|
FZY_S_LISTENING = 1,
|
|
|
|
FZY_S_ACCEPTED = 2,
|
|
|
|
FZY_S_PROXIED = 3,
|
|
|
|
FZY_S_ONWARD = 4,
|
|
|
|
};
|
|
|
|
|
|
|
|
enum proxy_parser_states {
|
|
|
|
FZY_PP_CONNECT = 0,
|
|
|
|
FZY_PP_ADDRESS = 1,
|
|
|
|
FZY_PP_PORT = 2,
|
|
|
|
FZY_PP_CRLFS = 3,
|
|
|
|
};
|
|
|
|
|
|
|
|
enum fuzzer_parser_states {
|
|
|
|
FZY_FP_SEARCH = 0,
|
|
|
|
FZY_FP_SEARCH2 = 1,
|
2016-01-21 10:54:51 +08:00
|
|
|
FZY_FP_INJECT_PREPARE = 2,
|
|
|
|
FZY_FP_INJECT = 3,
|
|
|
|
FZY_FP_PENDING = 4,
|
2016-01-18 09:24:35 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
struct ring {
|
|
|
|
char buf[4096];
|
|
|
|
int head;
|
|
|
|
int tail;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct state {
|
|
|
|
enum types type;
|
|
|
|
enum proxy_parser_states pp;
|
|
|
|
int ppc;
|
|
|
|
|
|
|
|
struct ring in;
|
|
|
|
|
|
|
|
char address[256];
|
|
|
|
int port;
|
|
|
|
|
|
|
|
enum fuzzer_parser_states fp;
|
|
|
|
int fuzc;
|
|
|
|
int pending;
|
|
|
|
|
|
|
|
int twin; /* must be fixed up when arrays lose guys */
|
|
|
|
unsigned int outbound:1; /* from local -> remote */
|
2016-01-21 10:54:51 +08:00
|
|
|
unsigned int is_pending:1;
|
|
|
|
|
|
|
|
unsigned char buf[MAX_FUZZ_BUF];
|
|
|
|
unsigned int inject_len;
|
2016-01-18 09:24:35 +08:00
|
|
|
};
|
|
|
|
|
2016-01-21 10:54:51 +08:00
|
|
|
struct test {
|
|
|
|
const char *s[3];
|
|
|
|
int len[2];
|
|
|
|
unsigned int swallow:1;
|
|
|
|
};
|
2016-01-18 09:24:35 +08:00
|
|
|
|
|
|
|
int force_exit = 0;
|
2016-01-21 10:54:51 +08:00
|
|
|
int which = 5;
|
|
|
|
|
|
|
|
static const struct test tests[] = {
|
|
|
|
{ { NULL, "\x0d\x0a\x0d\x0a",
|
|
|
|
"{ 0xd9, 0x87, 0xd2, 0x88, 0xd2, (248){ 0x89, 0xd2 }, 0x0d, 0x0a },"
|
|
|
|
}, { 0, 4 }, 1 },
|
|
|
|
{ { NULL, "\x0d\x0a\x0d\x0a",
|
|
|
|
"{ 0xd9, 0x87, 0xd2, 0x88, 0xd2, (1373){ 0x89, 0xd2 }, 0x0d, 0x0a },"
|
|
|
|
}, { 0, 4 }, 1 },
|
|
|
|
{ { NULL, "\x0d\x0a\x0d\x0a",
|
|
|
|
"{ 0xd9, 0x87, 0xd2, 0x88, 0xd2, (16967){ 0x89, 0xd2 }, (87){ 0xe2, 0x82, 0xac }, 0x0d, 0x0a },"
|
|
|
|
}, { 0, 4 }, 1 },
|
|
|
|
{ { NULL, "\x0d\x0a\x0d\x0a",
|
|
|
|
"0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, "
|
|
|
|
"0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, "
|
|
|
|
"0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x3a, 0x20, 0x77, 0x65, "
|
|
|
|
"0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, "
|
|
|
|
"0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0d, 0x0a, 0x53, 0x65, "
|
|
|
|
"0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2d, 0x4b, 0x65, 0x79, 0x3a, "
|
|
|
|
"0x20, 0x64, 0x47, 0x68, 0x6c, 0x49, 0x48, 0x4e, 0x68, 0x62, 0x58, 0x42, 0x73, 0x5a, 0x53, 0x42, "
|
|
|
|
"0x75, 0x62, 0x32, 0x35, 0x6a, 0x5a, 0x51, 0x3d, 0x3d, 0x0d, 0x0a, 0x4f, 0x72, 0x69, 0x67, 0x69, "
|
|
|
|
"0x6e, 0x3a, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, "
|
|
|
|
"0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, "
|
|
|
|
"0x65, 0x74, 0x2d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x31, 0x33, 0x0d, 0x0a, "
|
|
|
|
"0xef, 0xbb, 0xbf, 0xc2, 0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x48, 0x54, "
|
|
|
|
"0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0x31, 0x32, "
|
|
|
|
"0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, "
|
|
|
|
"0x3a, 0x20, 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, "
|
|
|
|
"0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x0d, 0x0a, "
|
|
|
|
}, { 0, 4 }, 1 },
|
|
|
|
{ { NULL, "\x0d\x0a\x0d\x0a",
|
|
|
|
"(20){0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, "
|
|
|
|
"0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, "
|
|
|
|
"0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x3a, 0x20, 0x77, 0x65, "
|
|
|
|
"0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, "
|
|
|
|
"0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0d, 0x0a, 0x53, 0x65, "
|
|
|
|
"0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2d, 0x4b, 0x65, 0x79, 0x3a, "
|
|
|
|
"0x20, 0x64, 0x47, 0x68, 0x6c, 0x49, 0x48, 0x4e, 0x68, 0x62, 0x58, 0x42, 0x73, 0x5a, 0x53, 0x42, "
|
|
|
|
"0x75, 0x62, 0x32, 0x35, 0x6a, 0x5a, 0x51, 0x3d, 0x3d, 0x0d, 0x0a, 0x4f, 0x72, 0x69, 0x67, 0x69, "
|
|
|
|
"0x6e, 0x3a, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, "
|
|
|
|
"0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, "
|
|
|
|
"0x65, 0x74, 0x2d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x31, 0x33, 0x0d, 0x0a, "
|
|
|
|
"0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, "
|
|
|
|
"0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, "
|
|
|
|
"0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x3a, 0x20, 0x77, 0x65, "
|
|
|
|
"0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, "
|
|
|
|
"0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0d, 0x0a, 0x53, 0x65, "
|
|
|
|
"0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2d, 0x4b, 0x65, 0x79, 0x3a, "
|
|
|
|
"0x20, 0x64, 0x47, 0x68, 0x6c, 0x49, 0x48, 0x4e, 0x68, 0x62, 0x58, 0x42, 0x73, 0x5a, 0x53, 0x42, "
|
|
|
|
"0x75, 0x62, 0x32, 0x35, 0x6a, 0x5a, 0x51, 0x3d, 0x3d, 0x0d, 0x0a, 0x4f, 0x72, 0x69, 0x67, 0x69, "
|
|
|
|
"0x6e, 0x3a, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, "
|
|
|
|
"0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, "
|
|
|
|
"0x65, 0x74, 0x2d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x31, 0x33, 0x0d, 0x0a, "
|
|
|
|
"0xc2, 0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x48, 0x54, 0x54, 0x50, 0x2f, "
|
|
|
|
"0x31, 0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0x31, 0x32, 0x37, 0x2e, 0x30, "
|
|
|
|
"0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x3a, 0x20, 0x77, "
|
|
|
|
"0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, "
|
|
|
|
"0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0d, 0x0a, 0x53, "
|
|
|
|
"0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2d, 0x4b, 0x65, 0x79, "
|
|
|
|
"0x3a, 0x20, 0x64, 0x47, 0x68, 0x6c, 0x49, 0x48, 0x4e, 0x68, 0x62, 0x58, 0x42, 0x73, 0x5a, 0x53, "
|
|
|
|
"0x42, 0x75, 0x62, 0x32, 0x35, 0x6a, 0x5a, 0x51, 0x3d, 0x3d, 0x0d, 0x0a, 0x4f, 0x72, 0x69, 0x67, "
|
|
|
|
"0x69, 0x6e, 0x3a, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x31, 0x32, 0x37, 0x2e, 0x30, "
|
|
|
|
"0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, "
|
|
|
|
"0x6b, 0x65, 0x74, 0x2d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x31, 0x33, 0x0d, "
|
|
|
|
"0x0a, 0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x48, 0x54, 0x54, 0x50, 0x2f, "
|
|
|
|
"0x31, 0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0x31, 0x32, 0x37, 0x2e, 0x30, "
|
|
|
|
"0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x3a, 0x20, 0x77, "
|
|
|
|
"0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, "
|
|
|
|
"0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0d, 0x0a, 0x53, "
|
|
|
|
"0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2d, 0x4b, 0x65, 0x79, "
|
|
|
|
"0x3a, 0x20, 0x64, 0x47, 0x68, 0x6c, 0x49, 0x48, 0x4e, 0x68, 0x62, 0x58, 0x42, 0x73, 0x5a, 0x53, "
|
|
|
|
"0x42, 0x75, 0x62, 0x32, 0x35, 0x6a, 0x5a, 0x51, 0x3d, 0x3d, 0x0d, 0x0a, 0x4f, 0x72, 0x69, 0x67, "
|
|
|
|
"0x69, 0x6e, 0x3a, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x31, 0x32, 0x37, 0x2e, 0x30, "
|
|
|
|
"0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, "
|
|
|
|
"0x6b, 0x65, 0x74, 0x2d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x31, 0x33, 0x0d, "
|
|
|
|
"0x0a, 0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x48, 0x54, 0x54, 0x50, 0x2f, "
|
|
|
|
"0x31, 0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0x31, 0x32, 0x37, 0x2e, 0x30, "
|
|
|
|
"0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x3a, 0x20, 0x77, "
|
|
|
|
"0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, "
|
|
|
|
"0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0d, 0x0a, 0x53, "
|
|
|
|
"0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2d, 0x4b, 0x65, 0x79, "
|
|
|
|
"0x3a, 0x20, 0x64, 0x47, 0x68, 0x6c, 0x49, 0x48, 0x4e, 0x68, 0x62, 0x58, 0x42, 0x73, 0x5a, 0x53, "
|
|
|
|
"0x42, 0x75, 0x62, 0x32, 0x35, 0x6a, 0x5a, 0x51, 0x3d, 0x3d, 0x0d, 0x0a, 0x4f, 0x72, 0x69, 0x67, "
|
|
|
|
"0x69, 0x6e, 0x3a, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x31, 0x32, 0x37, 0x2e, 0x30, "
|
|
|
|
"0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, "
|
|
|
|
"0x6b, 0x65, 0x74, 0x2d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x31, 0x33, 0x0d, "
|
|
|
|
"0x0a, 0xc0, 0x80, 0xef, 0xb7, 0x90, 0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, "
|
|
|
|
"0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, "
|
|
|
|
"0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, "
|
|
|
|
"0x64, 0x65, 0x3a, 0x20, 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, "
|
|
|
|
"0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x55, 0x70, 0x67, 0x72, 0x61, "
|
|
|
|
"0x64, 0x65, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, "
|
|
|
|
"0x74, 0x2d, 0x4b, 0x65, 0x79, 0x3a, 0x20, 0x64, 0x47, 0x68, 0x6c, 0x49, 0x48, 0x4e, 0x68, 0x62, "
|
|
|
|
"0x58, 0x42, 0x73, 0x5a, 0x53, 0x42, 0x75, 0x62, 0x32, 0x35, 0x6a, 0x5a, 0x51, 0x3d, 0x3d, 0x0d, "
|
|
|
|
"0x0a, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, "
|
|
|
|
"0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, "
|
|
|
|
"0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, "
|
|
|
|
"0x3a, 0x20, 0x31, 0x33, 0x0d, 0x0a, 0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, "
|
|
|
|
"0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, "
|
|
|
|
"0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, "
|
|
|
|
"0x64, 0x65, 0x3a, 0x20, 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, "
|
|
|
|
"0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x55, 0x70, 0x67, 0x72, 0x61, "
|
|
|
|
"0x64, 0x65, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, "
|
|
|
|
"0x74, 0x2d, 0x4b, 0x65, 0x79, 0x3a, 0x20, 0x64, 0x47, 0x68, 0x6c, 0x49, 0x48, 0x4e, 0x68, 0x62, "
|
|
|
|
"0x58, 0x42, 0x73, 0x5a, 0x53, 0x42, 0x75, 0x62, 0x32, 0x35, 0x6a, 0x5a, 0x51, 0x3d, 0x3d, 0x0d, "
|
|
|
|
"0x0a, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, "
|
|
|
|
"0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, "
|
|
|
|
"0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, "
|
|
|
|
"0x3a, 0x20, 0x31, 0x33, 0x0d, 0x0a, 0xc2, 0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, "
|
|
|
|
"0x20, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, "
|
|
|
|
"0x20, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, "
|
|
|
|
"0x61, 0x64, 0x0d, 0x0a, }"
|
|
|
|
}, { 0, 4 }, 1 },
|
|
|
|
{ { NULL, "\x0d\x0a\x0d\x0a",
|
|
|
|
"0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, "
|
|
|
|
"0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, "
|
|
|
|
"0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x3a, 0x20, 0x77, 0x65, "
|
|
|
|
"0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, "
|
|
|
|
"0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0d, 0x0a, 0x53, 0x65, "
|
|
|
|
"0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x2d, 0x4b, 0x65, 0x79, 0x3a, "
|
|
|
|
"0x20, 0x64, 0x47, 0x68, 0x6c, 0x49, 0x48, 0x4e, 0x68, 0x62, 0x58, 0x42, 0x73, 0x5a, 0x53, 0x42, "
|
|
|
|
"0x75, 0x62, 0x32, 0x35, 0x6a, 0x5a, 0x51, 0x3d, 0x3d, 0x0d, 0x0a, 0x4f, 0x72, 0x69, 0x67, 0x69, "
|
|
|
|
"0x6e, 0x3a, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, "
|
|
|
|
"0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x53, 0x65, 0x63, 0x2d, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, "
|
|
|
|
"0x65, 0x74, 0x2d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x31, 0x33, 0x0d, 0x0a, "
|
|
|
|
"0xef, 0xbb, 0xbf, 0xc2, 0x47, 0x45, 0x54, 0x20, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x20, 0x48, 0x54, "
|
|
|
|
"0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0x31, 0x32, "
|
|
|
|
"0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x0d, 0x0a, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, "
|
|
|
|
"0x3a, 0x20, 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, "
|
|
|
|
"0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x0d, 0x0a, (2048){ 0x0d, 0x0a}"
|
|
|
|
}, { 0, 4 }, 1 },
|
|
|
|
};
|
2016-01-18 09:24:35 +08:00
|
|
|
|
|
|
|
static const int ring_size(struct ring *r)
|
|
|
|
{
|
|
|
|
return sizeof(r->buf);
|
|
|
|
}
|
|
|
|
static const int ring_used(struct ring *r)
|
|
|
|
{
|
|
|
|
return (r->head - r->tail) & (ring_size(r) - 1);
|
|
|
|
}
|
|
|
|
static const int ring_free(struct ring *r)
|
|
|
|
{
|
|
|
|
return (ring_size(r) - 1) - ring_used(r);
|
|
|
|
}
|
|
|
|
static const int ring_get_one(struct ring *r)
|
|
|
|
{
|
|
|
|
int n = r->buf[r->tail] & 255;
|
|
|
|
|
|
|
|
if (r->tail == r->head)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
r->tail++;
|
|
|
|
if (r->tail == ring_size(r))
|
|
|
|
r->tail = 0;
|
|
|
|
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
2016-01-21 10:54:51 +08:00
|
|
|
static int hex(char c)
|
|
|
|
{
|
|
|
|
if (c >= '0' && c <= '9')
|
|
|
|
return c -'0';
|
|
|
|
if (c >= 'a' && c <= 'f')
|
|
|
|
return c - 'a' + 10;
|
|
|
|
if (c >='A' && c <= 'F')
|
|
|
|
return c - 'A' + 10;
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
fuzxy_tok(const char **src, unsigned char **buf, int *len)
|
|
|
|
{
|
|
|
|
unsigned char *start;
|
|
|
|
unsigned int count, rlen;
|
|
|
|
|
|
|
|
while (**src) {
|
|
|
|
|
|
|
|
if (**src == ' ' || **src == ',' || **src == '\n') {
|
|
|
|
(*src)++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((*src)[0] == '}') {
|
|
|
|
(*src)++;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((*src)[0] == '0' && (*src)[1] == 'x') {
|
|
|
|
if (!len) {
|
|
|
|
lwsl_err("out of space\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
((*buf)++)[0] = (hex((*src)[2]) << 4) | hex((*src)[3]);
|
|
|
|
*src += 4;
|
|
|
|
(*len)--;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*src[0] == '(') {
|
|
|
|
start = *buf;
|
|
|
|
(*src)++;
|
|
|
|
count = atoi(*src) - 1;
|
|
|
|
lwsl_err("count %d\n", count);
|
|
|
|
while (**src && **src != ')')
|
|
|
|
(*src)++;
|
|
|
|
if (!(*src)[0]) {
|
|
|
|
lwsl_err("unexpected end in (\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
(*src)++;
|
|
|
|
while (**src == ' ')
|
|
|
|
(*src)++;
|
|
|
|
if (**src != '{') {
|
|
|
|
lwsl_err("missing {\n");
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
(*src)++;
|
|
|
|
if (fuzxy_tok(src, buf, len))
|
|
|
|
return -1;
|
|
|
|
rlen = *buf - start;
|
|
|
|
while (count--) {
|
|
|
|
if (*len < rlen) {
|
|
|
|
lwsl_err("out of space\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
memcpy(*buf, start, rlen);
|
|
|
|
*buf += rlen;
|
|
|
|
*len -= rlen;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
fuzxy_create_pattern(const char *src, unsigned char *buf, int len)
|
|
|
|
{
|
|
|
|
unsigned char *old = buf;
|
|
|
|
int n;
|
|
|
|
|
|
|
|
while (*src && (*src == '{' || *src == ' '))
|
|
|
|
src++;
|
|
|
|
|
|
|
|
if (!*src)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
n = fuzxy_tok(&src, &buf, &len);
|
|
|
|
if (n)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return buf - old;
|
|
|
|
}
|
|
|
|
|
2016-01-18 09:24:35 +08:00
|
|
|
void sighandler(int sig)
|
|
|
|
{
|
|
|
|
force_exit = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct option options[] = {
|
|
|
|
{ "help", no_argument, NULL, 'h' },
|
|
|
|
{ "debug", required_argument, NULL, 'd' },
|
|
|
|
{ "port", required_argument, NULL, 'p' },
|
|
|
|
{ "ssl", no_argument, NULL, 's' },
|
|
|
|
{ "allow-non-ssl", no_argument, NULL, 'a' },
|
|
|
|
{ "interface", required_argument, NULL, 'i' },
|
|
|
|
{ "closetest", no_argument, NULL, 'c' },
|
|
|
|
{ "libev", no_argument, NULL, 'e' },
|
|
|
|
#ifndef LWS_NO_DAEMONIZE
|
|
|
|
{ "daemonize", no_argument, NULL, 'D' },
|
|
|
|
#endif
|
|
|
|
{ "resource_path", required_argument, NULL, 'r' },
|
|
|
|
{ NULL, 0, 0, 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct pollfd pfd[128];
|
|
|
|
static struct state state[128];
|
|
|
|
static int pfds = 0;
|
|
|
|
|
|
|
|
static void close_and_remove_fd(int index)
|
|
|
|
{
|
|
|
|
int n;
|
|
|
|
|
|
|
|
lwsl_notice("%s: closing index %d\n", __func__, index);
|
|
|
|
close(pfd[index].fd);
|
|
|
|
pfd[index].fd = -1;
|
|
|
|
|
|
|
|
n = state[index].twin;
|
|
|
|
if (n) {
|
|
|
|
assert(state[n].twin == index);
|
|
|
|
}
|
|
|
|
state[index].type = FZY_S_DEAD;
|
|
|
|
|
|
|
|
if (index == pfds - 1) {
|
|
|
|
if (state[index].twin)
|
|
|
|
state[state[index].twin].twin = 0;
|
|
|
|
state[index].twin = 0;
|
|
|
|
goto bail;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* swap the end guy into the deleted guy and trim back one */
|
|
|
|
|
|
|
|
if (state[pfds - 1].twin) {
|
|
|
|
state[state[pfds - 1].twin].twin = index;
|
|
|
|
if (n && n == pfds - 1)
|
|
|
|
n = index;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* swap the last guy into dead guy's place and trim by one */
|
|
|
|
pfd[index] = pfd[pfds - 1];
|
|
|
|
state[index] = state[pfds - 1];
|
|
|
|
|
|
|
|
if (n) {
|
|
|
|
pfds--;
|
|
|
|
state[n].twin = 0;
|
|
|
|
close_and_remove_fd(n);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bail:
|
|
|
|
pfds--;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void construct_state(int n, enum types s, int flags)
|
|
|
|
{
|
|
|
|
memset(&state[n], 0, sizeof state[n]);
|
|
|
|
state[n].type = s;
|
|
|
|
pfd[n].events = flags | POLLHUP;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
fuzxy_listen(const char *interface_name, int port, int *sockfd)
|
|
|
|
{
|
|
|
|
struct sockaddr_in serv_addr4;
|
|
|
|
socklen_t len = sizeof(struct sockaddr);
|
|
|
|
struct sockaddr_in sin;
|
|
|
|
int n, opt = 1;
|
|
|
|
|
|
|
|
*sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
|
|
|
|
|
|
|
if (*sockfd == -1) {
|
|
|
|
lwsl_err("ERROR opening socket\n");
|
|
|
|
goto bail1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (setsockopt(*sockfd, SOL_SOCKET, SO_REUSEADDR,
|
|
|
|
(const void *)&opt, sizeof(opt)) < 0) {
|
|
|
|
lwsl_err("unable to set listen socket options\n");
|
|
|
|
goto bail2;
|
|
|
|
}
|
|
|
|
|
|
|
|
bzero((char *) &serv_addr4, sizeof(serv_addr4));
|
|
|
|
serv_addr4.sin_addr.s_addr = INADDR_ANY;
|
|
|
|
serv_addr4.sin_family = AF_INET;
|
|
|
|
|
|
|
|
if (interface_name[0] &&
|
|
|
|
lws_interface_to_sa(0, interface_name, (struct sockaddr_in *)
|
|
|
|
(struct sockaddr *)&serv_addr4,
|
|
|
|
sizeof(serv_addr4)) < 0) {
|
|
|
|
lwsl_err("Unable to find interface %s\n", interface_name);
|
|
|
|
goto bail2;
|
|
|
|
}
|
|
|
|
|
|
|
|
serv_addr4.sin_port = htons(port);
|
|
|
|
|
|
|
|
n = bind(*sockfd, (struct sockaddr *)&serv_addr4,
|
|
|
|
sizeof(serv_addr4));
|
|
|
|
if (n < 0) {
|
|
|
|
lwsl_err("ERROR on binding to port %d (%d %d)\n",
|
|
|
|
port, n, errno);
|
|
|
|
goto bail2;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (getsockname(*sockfd, (struct sockaddr *)&sin, &len) == -1)
|
|
|
|
lwsl_warn("getsockname: %s\n", strerror(errno));
|
|
|
|
else
|
|
|
|
port = ntohs(sin.sin_port);
|
|
|
|
|
|
|
|
listen(*sockfd, SOMAXCONN);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
bail2:
|
|
|
|
close(*sockfd);
|
|
|
|
bail1:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int fuzz(int n, char *out, int len)
|
|
|
|
{
|
|
|
|
struct state *s = &state[n];
|
2016-01-21 10:54:51 +08:00
|
|
|
const struct test *t = &tests[which];
|
2016-01-18 09:24:35 +08:00
|
|
|
int m = 0;
|
|
|
|
int c;
|
|
|
|
|
|
|
|
while (m < len) {
|
|
|
|
switch (s->fp) {
|
|
|
|
case FZY_FP_SEARCH:
|
2016-01-21 10:54:51 +08:00
|
|
|
if (t->s[0] == NULL) {
|
|
|
|
s->fuzc = 0;
|
|
|
|
s->is_pending = 0;
|
|
|
|
s->fp = FZY_FP_SEARCH2;
|
|
|
|
goto search2;
|
|
|
|
}
|
2016-01-18 09:24:35 +08:00
|
|
|
c = ring_get_one(&state[s->twin].in);
|
|
|
|
if (c < 0)
|
|
|
|
return m;
|
2016-01-21 10:54:51 +08:00
|
|
|
if (c == tests[which].s[0][s->fuzc++]) {
|
|
|
|
if (s->fuzc == t->len[0]) {
|
2016-01-18 09:24:35 +08:00
|
|
|
s->fuzc = 0;
|
|
|
|
s->fp = FZY_FP_SEARCH2;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
s->fuzc = 0;
|
|
|
|
out[m++] = c;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FZY_FP_SEARCH2:
|
2016-01-21 10:54:51 +08:00
|
|
|
search2:
|
|
|
|
if (tests[which].s[1] == NULL) {
|
|
|
|
s->fuzc = 0;
|
|
|
|
s->is_pending = 0;
|
|
|
|
s->fp = FZY_FP_INJECT_PREPARE;
|
|
|
|
goto inject;
|
|
|
|
}
|
2016-01-18 09:24:35 +08:00
|
|
|
c = ring_get_one(&state[s->twin].in);
|
|
|
|
if (c < 0)
|
|
|
|
return m;
|
2016-01-21 10:54:51 +08:00
|
|
|
if (c == tests[which].s[1][s->fuzc++]) {
|
|
|
|
if (s->fuzc == tests[which].len[1]) {
|
2016-01-18 09:24:35 +08:00
|
|
|
lwsl_notice("+++++++fuzzer hit...\n");
|
|
|
|
s->fuzc = 0;
|
2016-01-21 10:54:51 +08:00
|
|
|
s->fp = FZY_FP_INJECT_PREPARE;
|
|
|
|
s->is_pending = !t->swallow;
|
2016-01-18 09:24:35 +08:00
|
|
|
s->pending = c;
|
|
|
|
goto inject;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
s->fuzc = 0;
|
2016-01-21 10:54:51 +08:00
|
|
|
if (!t->swallow)
|
|
|
|
out[m++] = c;
|
2016-01-18 09:24:35 +08:00
|
|
|
break;
|
2016-01-21 10:54:51 +08:00
|
|
|
|
|
|
|
case FZY_FP_INJECT_PREPARE:
|
2016-01-18 09:24:35 +08:00
|
|
|
inject:
|
2016-01-21 10:54:51 +08:00
|
|
|
s->inject_len = fuzxy_create_pattern(t->s[2],
|
|
|
|
s->buf, sizeof(s->buf));
|
|
|
|
if (s->inject_len == (unsigned int) -1)
|
|
|
|
return -1;
|
|
|
|
s->fp = FZY_FP_INJECT;
|
|
|
|
/* fallthru */
|
|
|
|
|
|
|
|
case FZY_FP_INJECT:
|
|
|
|
out[m++] = s->buf[s->fuzc++];
|
|
|
|
if (s->fuzc == s->inject_len)
|
2016-01-18 09:24:35 +08:00
|
|
|
s->fp = FZY_FP_PENDING;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FZY_FP_PENDING:
|
2016-01-21 10:54:51 +08:00
|
|
|
if (s->is_pending)
|
|
|
|
out[m++] = s->pending;
|
2016-01-18 09:24:35 +08:00
|
|
|
s->fp = FZY_FP_SEARCH;
|
|
|
|
s->fuzc = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
handle_accept(int n)
|
|
|
|
{
|
|
|
|
struct addrinfo ai, *res, *result;
|
|
|
|
struct sockaddr_in serv_addr4;
|
|
|
|
struct state *s = &state[n];
|
|
|
|
void *p = NULL;
|
|
|
|
int m, sockfd;
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
m = ring_get_one(&s->in);
|
|
|
|
if (m < 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
switch (s->pp) {
|
|
|
|
case FZY_PP_CONNECT:
|
|
|
|
if (m != "CONNECT "[s->ppc++]) {
|
|
|
|
lwsl_notice("failed CONNECT match\n");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (s->ppc == 8) {
|
|
|
|
s->pp = FZY_PP_ADDRESS;
|
|
|
|
s->ppc = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case FZY_PP_ADDRESS:
|
|
|
|
if (m == ':') {
|
|
|
|
s->address[s->ppc++] = '\0';
|
|
|
|
s->pp = FZY_PP_PORT;
|
|
|
|
s->ppc = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (m == ' ') {
|
|
|
|
s->address[s->ppc++] = '\0';
|
|
|
|
s->pp = FZY_PP_CRLFS;
|
|
|
|
s->ppc = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
s->address[s->ppc++] = m;
|
|
|
|
if (s->ppc == sizeof(s->address)) {
|
|
|
|
lwsl_notice("Failed on address length\n");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case FZY_PP_PORT:
|
|
|
|
if (m == ' ') {
|
|
|
|
s->pp = FZY_PP_CRLFS;
|
|
|
|
s->ppc = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (m >= '0' && m <= '9') {
|
|
|
|
s->port *= 10;
|
|
|
|
s->port += m - '0';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
case FZY_PP_CRLFS:
|
|
|
|
if (m != "\x0d\x0a\x0d\x0a"[s->ppc++])
|
|
|
|
s->ppc = 0;
|
|
|
|
if (s->ppc != 4)
|
|
|
|
break;
|
|
|
|
s->type = FZY_S_PROXIED;
|
|
|
|
|
|
|
|
memset (&ai, 0, sizeof ai);
|
|
|
|
ai.ai_family = PF_UNSPEC;
|
|
|
|
ai.ai_socktype = SOCK_STREAM;
|
|
|
|
ai.ai_flags = AI_CANONNAME;
|
|
|
|
|
|
|
|
if (getaddrinfo(s->address, NULL, &ai, &result)) {
|
|
|
|
lwsl_notice("failed to lookup %s\n",
|
|
|
|
s->address);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
res = result;
|
|
|
|
while (!p && res) {
|
|
|
|
switch (res->ai_family) {
|
|
|
|
case AF_INET:
|
|
|
|
p = &((struct sockaddr_in *)res->
|
|
|
|
ai_addr)->sin_addr;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
res = res->ai_next;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!p) {
|
|
|
|
lwsl_notice("Failed to get address result %s\n",
|
|
|
|
s->address);
|
|
|
|
freeaddrinfo(result);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
serv_addr4.sin_family = AF_INET;
|
|
|
|
serv_addr4.sin_addr = *((struct in_addr *)p);
|
|
|
|
serv_addr4.sin_port = htons(s->port);
|
|
|
|
bzero(&serv_addr4.sin_zero, 8);
|
|
|
|
freeaddrinfo(result);
|
|
|
|
|
|
|
|
lwsl_err("Conn %d req '%s' port %d\n", n,
|
|
|
|
s->address, s->port);
|
|
|
|
/* we need to open the associated onward connection */
|
|
|
|
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
2016-01-19 21:40:41 +08:00
|
|
|
if (sockfd < 0) {
|
|
|
|
lwsl_err("Could not get socket\n");
|
|
|
|
return -1;
|
|
|
|
}
|
2016-01-18 09:24:35 +08:00
|
|
|
|
|
|
|
if (connect(sockfd, (struct sockaddr *)&serv_addr4,
|
|
|
|
sizeof(struct sockaddr)) == -1 ||
|
|
|
|
errno == EISCONN) {
|
2016-01-19 21:44:20 +08:00
|
|
|
close(sockfd);
|
2016-01-18 09:24:35 +08:00
|
|
|
lwsl_err("proxied onward connection failed\n");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
s->twin = pfds;
|
|
|
|
construct_state(pfds, FZY_S_ONWARD,
|
|
|
|
POLLOUT | POLLIN | POLLERR);
|
|
|
|
state[pfds].twin = n;
|
|
|
|
lwsl_notice("binding conns %d and %d\n", n, pfds);
|
|
|
|
state[pfds].outbound = s->outbound;
|
|
|
|
state[pfds].ppc = 0;
|
|
|
|
pfd[pfds++].fd = sockfd;
|
|
|
|
|
|
|
|
lwsl_notice("onward connection in progress\n");
|
|
|
|
if (ring_used(&s->in))
|
|
|
|
pfd[s->twin].events |= POLLOUT;
|
|
|
|
if (write(pfd[n].fd,
|
|
|
|
"HTTP/1.0 200 \x0d\x0a\x0d\x0a", 17) < 17)
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void sigpipe_handler(int x)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
main(int argc, char **argv)
|
|
|
|
{
|
|
|
|
char interface_name[128] = "", interface_name_local[128] = "lo";
|
|
|
|
int port_local = 8880, accept_fd;
|
|
|
|
struct sockaddr_in cli_addr;
|
|
|
|
int debug_level = 7;
|
|
|
|
socklen_t clilen;
|
|
|
|
struct state *s;
|
|
|
|
char out[4096];
|
|
|
|
int opts = 0;
|
|
|
|
int n = 0, m;
|
|
|
|
|
|
|
|
#ifndef _WIN32
|
|
|
|
int syslog_options = LOG_PID | LOG_PERROR;
|
|
|
|
#endif
|
|
|
|
#ifndef LWS_NO_DAEMONIZE
|
|
|
|
int daemonize = 0;
|
|
|
|
#endif
|
|
|
|
signal(SIGPIPE, sigpipe_handler);
|
|
|
|
|
|
|
|
while (n >= 0) {
|
|
|
|
n = getopt_long(argc, argv, "eci:hsap:d:Dr:", options, NULL);
|
|
|
|
if (n < 0)
|
|
|
|
continue;
|
|
|
|
switch (n) {
|
|
|
|
case 'e':
|
|
|
|
opts |= LWS_SERVER_OPTION_LIBEV;
|
|
|
|
break;
|
|
|
|
#ifndef LWS_NO_DAEMONIZE
|
|
|
|
case 'D':
|
|
|
|
daemonize = 1;
|
|
|
|
#ifndef _WIN32
|
|
|
|
syslog_options &= ~LOG_PERROR;
|
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
case 'd':
|
|
|
|
debug_level = atoi(optarg);
|
|
|
|
break;
|
|
|
|
case 'p':
|
|
|
|
port_local = atoi(optarg);
|
|
|
|
break;
|
|
|
|
case 'i':
|
|
|
|
strncpy(interface_name, optarg, sizeof interface_name);
|
|
|
|
interface_name[(sizeof interface_name) - 1] = '\0';
|
|
|
|
break;
|
|
|
|
case 'h':
|
|
|
|
fprintf(stderr, "Usage: libwebsockets-test-fuzxy "
|
|
|
|
"[--port=<p>] [--ssl] "
|
|
|
|
"[-d <log bitfield>] "
|
|
|
|
"[--resource_path <path>]\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#if !defined(LWS_NO_DAEMONIZE) && !defined(WIN32)
|
|
|
|
/*
|
|
|
|
* normally lock path would be /var/lock/lwsts or similar, to
|
|
|
|
* simplify getting started without having to take care about
|
|
|
|
* permissions or running as root, set to /tmp/.lwsts-lock
|
|
|
|
*/
|
|
|
|
if (daemonize && lws_daemonize("/tmp/.lwsts-lock")) {
|
|
|
|
fprintf(stderr, "Failed to daemonize\n");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
signal(SIGINT, sighandler);
|
|
|
|
|
|
|
|
#ifndef _WIN32
|
|
|
|
/* we will only try to log things according to our debug_level */
|
|
|
|
setlogmask(LOG_UPTO (LOG_DEBUG));
|
|
|
|
openlog("fuzxy", syslog_options, LOG_DAEMON);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* tell the library what debug level to emit and to send it to syslog */
|
|
|
|
lws_set_log_level(debug_level, lwsl_emit_syslog);
|
|
|
|
|
2016-01-29 21:18:54 +08:00
|
|
|
lwsl_notice("libwebsockets fuzzing proxy - license LGPL2.1+SLE\n");
|
|
|
|
lwsl_notice("(C) Copyright 2016 Andy Green <andy@warmcat.com>\n");
|
2016-01-18 09:24:35 +08:00
|
|
|
|
|
|
|
/* listen on local side */
|
|
|
|
|
|
|
|
if (fuzxy_listen(interface_name, port_local, &pfd[pfds].fd)) {
|
|
|
|
lwsl_err("Failed to listen on local side\n");
|
|
|
|
goto bail1;
|
|
|
|
}
|
|
|
|
construct_state(pfds, FZY_S_LISTENING, POLLIN | POLLERR);
|
|
|
|
pfds++;
|
|
|
|
|
|
|
|
lwsl_notice("Local side listening on %s:%u\n",
|
|
|
|
interface_name_local, port_local);
|
|
|
|
|
|
|
|
while (!force_exit) {
|
|
|
|
|
|
|
|
m = poll(pfd, pfds, 50);
|
|
|
|
if (m < 0)
|
|
|
|
continue;
|
|
|
|
for (n = 0; n < pfds; n++) {
|
|
|
|
s = &state[n];
|
|
|
|
if (s->type == FZY_S_LISTENING &&
|
|
|
|
(pfd[n].revents & POLLIN)) {
|
|
|
|
/* first do the accept entry */
|
|
|
|
|
|
|
|
clilen = sizeof(cli_addr);
|
|
|
|
accept_fd = accept(pfd[0].fd,
|
|
|
|
(struct sockaddr *)&cli_addr, &clilen);
|
|
|
|
if (accept_fd < 0) {
|
|
|
|
if (errno == EAGAIN ||
|
|
|
|
errno == EWOULDBLOCK)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
lwsl_warn("ERROR on accept: %s\n",
|
|
|
|
strerror(errno));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
construct_state(pfds, FZY_S_ACCEPTED,
|
|
|
|
POLLIN | POLLERR);
|
|
|
|
state[pfds].outbound = n == 0;
|
|
|
|
state[pfds].pp = FZY_PP_CONNECT;
|
|
|
|
state[pfds].ppc = 0;
|
|
|
|
pfd[pfds++].fd = accept_fd;
|
|
|
|
lwsl_notice("new connect accepted\n");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (pfd[n].revents & POLLIN) {
|
|
|
|
assert(ring_free(&s->in));
|
|
|
|
m = (ring_size(&s->in) - 1) -
|
|
|
|
s->in.head;
|
|
|
|
if (s->in.head == ring_size(&s->in) - 1 &&
|
|
|
|
s->in.tail)
|
|
|
|
m = 1;
|
|
|
|
m = read(pfd[n].fd, s->in.buf + s->in.head, m);
|
|
|
|
// lwsl_notice("read %d\n", m);
|
2016-01-21 10:54:51 +08:00
|
|
|
if (m <= 0) {
|
|
|
|
lwsl_err("Error on read\n");
|
2016-01-18 09:24:35 +08:00
|
|
|
goto drop;
|
2016-01-21 10:54:51 +08:00
|
|
|
}
|
2016-01-18 09:24:35 +08:00
|
|
|
s->in.head += m;
|
|
|
|
if (s->in.head == ring_size(&s->in))
|
|
|
|
s->in.head = 0;
|
|
|
|
|
|
|
|
switch (s->type) {
|
|
|
|
case FZY_S_ACCEPTED: /* parse proxy CONNECT */
|
|
|
|
if (handle_accept(n))
|
|
|
|
goto drop;
|
|
|
|
break;
|
|
|
|
case FZY_S_PROXIED:
|
|
|
|
case FZY_S_ONWARD:
|
|
|
|
if (ring_used(&s->in))
|
|
|
|
pfd[s->twin].events |= POLLOUT;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
assert(0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (s->in.head == s->in.tail) {
|
|
|
|
s->in.head = s->in.tail = 0;
|
|
|
|
pfd[n].events |= POLLIN;
|
|
|
|
}
|
|
|
|
if (!ring_free(&s->in))
|
|
|
|
pfd[n].events &= ~POLLIN;
|
|
|
|
}
|
|
|
|
if (pfd[n].revents & POLLOUT) {
|
|
|
|
switch (s->type) {
|
|
|
|
case FZY_S_PROXIED:
|
|
|
|
case FZY_S_ONWARD:
|
|
|
|
/*
|
|
|
|
* draw down enough of the partner's
|
|
|
|
* in ring to either exhaust it
|
|
|
|
* or fill an output buffer
|
|
|
|
*/
|
|
|
|
m = fuzz(n, out, sizeof(out));
|
2016-01-29 15:35:01 +08:00
|
|
|
if (m < 0) {
|
|
|
|
lwsl_err("Error on fuzz\n");
|
|
|
|
goto drop;
|
|
|
|
}
|
2016-01-21 10:54:51 +08:00
|
|
|
lwsl_notice("got block %d\n", m);
|
2016-01-18 09:24:35 +08:00
|
|
|
if (m) {
|
|
|
|
m = write(pfd[n].fd, out, m);
|
2016-01-21 10:54:51 +08:00
|
|
|
if (m <= 0) {
|
|
|
|
lwsl_err("Error on write\n");
|
2016-01-18 09:24:35 +08:00
|
|
|
goto drop;
|
2016-01-21 10:54:51 +08:00
|
|
|
} else
|
|
|
|
pfd[s->twin].events &= ~POLLIN;
|
|
|
|
} else {
|
2016-01-18 09:24:35 +08:00
|
|
|
pfd[n].events &= ~POLLOUT;
|
|
|
|
|
2016-01-21 10:54:51 +08:00
|
|
|
if (ring_free(&state[s->twin].in))
|
|
|
|
pfd[s->twin].events |= POLLIN;
|
|
|
|
}
|
2016-01-18 09:24:35 +08:00
|
|
|
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
continue;
|
|
|
|
drop:
|
|
|
|
close_and_remove_fd(n);
|
|
|
|
n--; /* redo this slot */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bail1:
|
|
|
|
lwsl_notice("%s exited cleanly\n", argv[0]);
|
|
|
|
|
|
|
|
#ifndef _WIN32
|
|
|
|
closelog();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|