This commit is contained in:
samuelbrian 2017-10-18 14:26:54 +00:00 committed by GitHub
commit 4266dfa88c
6 changed files with 535 additions and 57 deletions

1
other/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
websockify

View File

@ -3,11 +3,12 @@ CFLAGS += -fPIC
all: $(TARGETS)
websockify: websockify.o websocket.o
$(CC) $(LDFLAGS) $^ -lssl -lcrypto -lresolv -o $@
websockify: websockify.o websocket.o base64.o
$(CC) $(LDFLAGS) $^ -lssl -lcrypto -o $@
websocket.o: websocket.c websocket.h
websockify.o: websockify.c websocket.h
base64.o: base64.c
clean:
rm -f websockify *.o

313
other/base64.c Normal file
View File

@ -0,0 +1,313 @@
/*
* Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
/*
* Portions Copyright (c) 1995 by International Business Machines, Inc.
*
* International Business Machines, Inc. (hereinafter called IBM) grants
* permission under its copyrights to use, copy, modify, and distribute this
* Software with or without fee, provided that the above copyright notice and
* all paragraphs of this notice appear in all copies, and that the name of IBM
* not be used in connection with the marketing of any product incorporating
* the Software or modifications thereof, without specific, written prior
* permission.
*
* To the extent it has a right to do so, IBM grants an immunity from suit
* under its patents, if any, for the use, sale or manufacture of products to
* the extent that such products are used for performing Domain Name System
* dynamic updates in TCP/IP networks by means of the Software. No immunity is
* granted for any product per se or for any other function of any product.
*
* THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
* DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
* IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
*/
#if !defined(LINT) && !defined(CODECENTER)
static const char rcsid[] = "$BINDId: base64.c,v 8.7 1999/10/13 16:39:33 vixie Exp $";
#endif /* not lint */
#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <ctype.h>
#include <resolv.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define Assert(Cond) if (!(Cond)) abort()
static const char Base64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static const char Pad64 = '=';
/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
The following encoding technique is taken from RFC 1521 by Borenstein
and Freed. It is reproduced here in a slightly edited form for
convenience.
A 65-character subset of US-ASCII is used, enabling 6 bits to be
represented per printable character. (The extra 65th character, "=",
is used to signify a special processing function.)
The encoding process represents 24-bit groups of input bits as output
strings of 4 encoded characters. Proceeding from left to right, a
24-bit input group is formed by concatenating 3 8-bit input groups.
These 24 bits are then treated as 4 concatenated 6-bit groups, each
of which is translated into a single digit in the base64 alphabet.
Each 6-bit group is used as an index into an array of 64 printable
characters. The character referenced by the index is placed in the
output string.
Table 1: The Base64 Alphabet
Value Encoding Value Encoding Value Encoding Value Encoding
0 A 17 R 34 i 51 z
1 B 18 S 35 j 52 0
2 C 19 T 36 k 53 1
3 D 20 U 37 l 54 2
4 E 21 V 38 m 55 3
5 F 22 W 39 n 56 4
6 G 23 X 40 o 57 5
7 H 24 Y 41 p 58 6
8 I 25 Z 42 q 59 7
9 J 26 a 43 r 60 8
10 K 27 b 44 s 61 9
11 L 28 c 45 t 62 +
12 M 29 d 46 u 63 /
13 N 30 e 47 v
14 O 31 f 48 w (pad) =
15 P 32 g 49 x
16 Q 33 h 50 y
Special processing is performed if fewer than 24 bits are available
at the end of the data being encoded. A full encoding quantum is
always completed at the end of a quantity. When fewer than 24 input
bits are available in an input group, zero bits are added (on the
right) to form an integral number of 6-bit groups. Padding at the
end of the data is performed using the '=' character.
Since all base64 input is an integral number of octets, only the
-------------------------------------------------
following cases can arise:
(1) the final quantum of encoding input is an integral
multiple of 24 bits; here, the final unit of encoded
output will be an integral multiple of 4 characters
with no "=" padding,
(2) the final quantum of encoding input is exactly 8 bits;
here, the final unit of encoded output will be two
characters followed by two "=" padding characters, or
(3) the final quantum of encoding input is exactly 16 bits;
here, the final unit of encoded output will be three
characters followed by one "=" padding character.
*/
int
ws_b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize) {
size_t datalength = 0;
u_char input[3];
u_char output[4];
size_t i;
while (2 < srclength) {
input[0] = *src++;
input[1] = *src++;
input[2] = *src++;
srclength -= 3;
output[0] = input[0] >> 2;
output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
output[3] = input[2] & 0x3f;
Assert(output[0] < 64);
Assert(output[1] < 64);
Assert(output[2] < 64);
Assert(output[3] < 64);
if (datalength + 4 > targsize)
return (-1);
target[datalength++] = Base64[output[0]];
target[datalength++] = Base64[output[1]];
target[datalength++] = Base64[output[2]];
target[datalength++] = Base64[output[3]];
}
/* Now we worry about padding. */
if (0 != srclength) {
/* Get what's left. */
input[0] = input[1] = input[2] = '\0';
for (i = 0; i < srclength; i++)
input[i] = *src++;
output[0] = input[0] >> 2;
output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
Assert(output[0] < 64);
Assert(output[1] < 64);
Assert(output[2] < 64);
if (datalength + 4 > targsize)
return (-1);
target[datalength++] = Base64[output[0]];
target[datalength++] = Base64[output[1]];
if (srclength == 1)
target[datalength++] = Pad64;
else
target[datalength++] = Base64[output[2]];
target[datalength++] = Pad64;
}
if (datalength >= targsize)
return (-1);
target[datalength] = '\0'; /* Returned value doesn't count \0. */
return (datalength);
}
//libresolv_hidden_def (b64_ntop)
/* skips all whitespace anywhere.
converts characters, four at a time, starting at (or after)
src from base - 64 numbers into three 8 bit bytes in the target area.
it returns the number of data bytes stored at the target, or -1 on error.
*/
int
ws_b64_pton(char const *src, u_char *target, size_t targsize) {
int tarindex, state, ch;
char *pos;
state = 0;
tarindex = 0;
while ((ch = *src++) != '\0') {
if (isspace(ch)) /* Skip whitespace anywhere. */
continue;
if (ch == Pad64)
break;
pos = strchr(Base64, ch);
if (pos == 0) /* A non-base64 character. */
return (-1);
switch (state) {
case 0:
if (target) {
if ((size_t)tarindex >= targsize)
return (-1);
target[tarindex] = (pos - Base64) << 2;
}
state = 1;
break;
case 1:
if (target) {
if ((size_t)tarindex + 1 >= targsize)
return (-1);
target[tarindex] |= (pos - Base64) >> 4;
target[tarindex+1] = ((pos - Base64) & 0x0f)
<< 4 ;
}
tarindex++;
state = 2;
break;
case 2:
if (target) {
if ((size_t)tarindex + 1 >= targsize)
return (-1);
target[tarindex] |= (pos - Base64) >> 2;
target[tarindex+1] = ((pos - Base64) & 0x03)
<< 6;
}
tarindex++;
state = 3;
break;
case 3:
if (target) {
if ((size_t)tarindex >= targsize)
return (-1);
target[tarindex] |= (pos - Base64);
}
tarindex++;
state = 0;
break;
default:
abort();
}
}
/*
* We are done decoding Base-64 chars. Let's see if we ended
* on a byte boundary, and/or with erroneous trailing characters.
*/
if (ch == Pad64) { /* We got a pad char. */
ch = *src++; /* Skip it, get next. */
switch (state) {
case 0: /* Invalid = in first position */
case 1: /* Invalid = in second position */
return (-1);
case 2: /* Valid, means one byte of info */
/* Skip any number of spaces. */
for ((void)NULL; ch != '\0'; ch = *src++)
if (!isspace(ch))
break;
/* Make sure there is another trailing = sign. */
if (ch != Pad64)
return (-1);
ch = *src++; /* Skip the = */
/* Fall through to "single trailing =" case. */
/* FALLTHROUGH */
case 3: /* Valid, means two bytes of info */
/*
* We know this char is an =. Is there anything but
* whitespace after it?
*/
for ((void)NULL; ch != '\0'; ch = *src++)
if (!isspace(ch))
return (-1);
/*
* Now make sure for cases 2 and 3 that the "extra"
* bits that slopped past the last full byte were
* zeros. If we don't check them, they become a
* subliminal channel.
*/
if (target && target[tarindex] != 0)
return (-1);
}
} else {
/*
* We ended by seeing the end of the string. Make sure we
* have no partial bytes lying around.
*/
if (state != 0)
return (-1);
}
return (tarindex);
}

View File

@ -21,11 +21,13 @@
#include <fcntl.h> // daemonizing
#include <openssl/err.h>
#include <openssl/ssl.h>
#include <resolv.h> /* base64 encode/decode */
#include <openssl/md5.h> /* md5 hash */
#include <openssl/sha.h> /* sha1 hash */
#include "websocket.h"
int ws_b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize);
int ws_b64_pton(char const *src, u_char *target, size_t targsize);
/*
* Global state
*
@ -214,7 +216,7 @@ int encode_hixie(u_char const *src, size_t srclength,
char *target, size_t targsize) {
int sz = 0, len = 0;
target[sz++] = '\x00';
len = b64_ntop(src, srclength, target+sz, targsize-sz);
len = ws_b64_ntop(src, srclength, target+sz, targsize-sz);
if (len < 0) {
return len;
}
@ -249,7 +251,7 @@ int decode_hixie(char *src, size_t srclength,
/* We may have more than one frame */
end = (char *)memchr(start, '\xff', srclength);
*end = '\x00';
len = b64_pton(start, target+retlen, targsize-retlen);
len = ws_b64_pton(start, target+retlen, targsize-retlen);
if (len < 0) {
return len;
}
@ -270,21 +272,29 @@ int encode_hybi(u_char const *src, size_t srclength,
{
unsigned long long b64_sz, len_offset = 1, payload_offset = 2, len = 0;
if ((int)srclength <= 0)
{
return 0;
if (opcode != OPCODE_TEXT && opcode != OPCODE_BINARY) {
handler_emsg("Invalid opcode. Opcode must be 0x01 for text mode, or 0x02 for binary mode.\n");
return -1;
}
b64_sz = ((srclength - 1) / 3) * 4 + 4;
target[0] = (char)(opcode & 0x0F | 0x80);
if (b64_sz <= 125) {
target[1] = (char) b64_sz;
if ((int)srclength <= 0) {
return 0;
}
if (opcode & OPCODE_TEXT) {
len = ((srclength - 1) / 3) * 4 + 4;
} else {
len = srclength;
}
if (len <= 125) {
target[1] = (char) len;
payload_offset = 2;
} else if ((b64_sz > 125) && (b64_sz < 65536)) {
} else if ((len > 125) && (len < 65536)) {
target[1] = (char) 126;
*(u_short*)&(target[2]) = htons(b64_sz);
*(u_short*)&(target[2]) = htons(len);
payload_offset = 4;
} else {
handler_emsg("Sending frames larger than 65535 bytes not supported\n");
@ -294,7 +304,12 @@ int encode_hybi(u_char const *src, size_t srclength,
//payload_offset = 10;
}
len = b64_ntop(src, srclength, target+payload_offset, targsize-payload_offset);
if (opcode & OPCODE_TEXT) {
len = ws_b64_ntop(src, srclength, target+payload_offset, targsize-payload_offset);
} else {
memcpy(target+payload_offset, src, srclength);
len = srclength;
}
if (len < 0) {
return len;
@ -364,7 +379,7 @@ int decode_hybi(unsigned char *src, size_t srclength,
//printf(" payload_length: %u, raw remaining: %u\n", payload_length, remaining);
payload = frame + hdr_length + 4*masked;
if (*opcode != 1 && *opcode != 2) {
if (*opcode != OPCODE_TEXT && *opcode != OPCODE_BINARY) {
handler_msg("Ignoring non-data frame, opcode 0x%x\n", *opcode);
continue;
}
@ -389,8 +404,13 @@ int decode_hybi(unsigned char *src, size_t srclength,
payload[i] ^= mask[i%4];
}
if (*opcode & OPCODE_TEXT) {
// base64 decode the data
len = b64_pton((const char*)payload, target+target_offset, targsize);
len = ws_b64_pton((const char*)payload, target+target_offset, targsize);
} else {
memcpy(target+target_offset, payload, payload_length);
len = payload_length;
}
// Restore the first character of the next frame
payload[payload_length] = save_char;
@ -560,7 +580,7 @@ static void gen_sha1(headers_t *headers, char *target) {
SHA1_Update(&c, HYBI_GUID, 36);
SHA1_Final(hash, &c);
r = b64_ntop(hash, sizeof hash, target, HYBI10_ACCEPTHDRLEN);
r = ws_b64_ntop(hash, sizeof hash, target, HYBI10_ACCEPTHDRLEN);
//assert(r == HYBI10_ACCEPTHDRLEN - 1);
}
@ -571,6 +591,7 @@ ws_ctx_t *do_handshake(int sock) {
headers_t *headers;
int len, ret, i, offset;
ws_ctx_t * ws_ctx;
char *response_protocol;
// Peek, but don't read the data
len = recv(sock, handshake, 1024, MSG_PEEK);
@ -640,10 +661,23 @@ ws_ctx_t *do_handshake(int sock) {
}
headers = ws_ctx->headers;
if (strstr(headers->protocols, "binary")) {
ws_ctx->opcode = OPCODE_BINARY;
response_protocol = "binary";
} else if (strstr(headers->protocols, "base64")) {
ws_ctx->opcode = OPCODE_TEXT;
response_protocol = "base64";
} else {
handler_emsg("Invalid protocol '%s', expecting 'binary' or 'base64'\n",
headers->protocols);
return NULL;
}
if (ws_ctx->hybi > 0) {
handler_msg("using protocol HyBi/IETF 6455 %d\n", ws_ctx->hybi);
gen_sha1(headers, sha1);
sprintf(response, SERVER_HANDSHAKE_HYBI, sha1, "base64");
sprintf(response, SERVER_HANDSHAKE_HYBI, sha1, response_protocol);
} else {
if (ws_ctx->hixie == 76) {
handler_msg("using protocol Hixie 76\n");
@ -666,9 +700,16 @@ ws_ctx_t *do_handshake(int sock) {
void signal_handler(sig) {
switch (sig) {
case SIGHUP: break; // ignore for now
case SIGHUP:
if (settings.whitelist != NULL) {
load_whitelist();
}
break;
case SIGPIPE: pipe_error = 1; break; // handle inline
case SIGTERM: exit(0); break;
case SIGTERM:
remove(settings.pid);
exit(0);
break;
}
}
@ -687,7 +728,17 @@ void daemonize(int keepfd) {
setsid(); // Obtain new process group
pid = fork();
if (pid<0) { fatal("fork error"); }
if (pid>0) { exit(0); } // parent exits
if (pid>0) {
// parent exits
FILE *pidf = fopen(settings.pid, "w");
if (pidf) {
fprintf(pidf, "%d", pid);
fclose(pidf);
} else {
fprintf(stderr, "Could not write daemon PID file '%s': %s\n", settings.pid, strerror(errno));
}
exit(0);
}
/* Signal handling */
signal(SIGHUP, signal_handler); // catch HUP

View File

@ -26,6 +26,9 @@ Sec-WebSocket-Protocol: %s\r\n\
#define POLICY_RESPONSE "<cross-domain-policy><allow-access-from domain=\"*\" to-ports=\"*\" /></cross-domain-policy>\n"
#define OPCODE_TEXT 0x01
#define OPCODE_BINARY 0x02
typedef struct {
char path[1024+1];
char host[1024+1];
@ -44,6 +47,7 @@ typedef struct {
SSL *ssl;
int hixie;
int hybi;
int opcode;
headers_t *headers;
char *cin_buf;
char *cout_buf;
@ -62,6 +66,9 @@ typedef struct {
int ssl_only;
int daemon;
int run_once;
char *whitelist;
char *pattern;
char *pid;
} settings_t;

View File

@ -18,6 +18,7 @@
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <signal.h>
#include "websocket.h"
char traffic_legend[] = "\n\
@ -33,20 +34,27 @@ Traffic Legend:\n\
";
char USAGE[] = "Usage: [options] " \
"[source_addr:]source_port target_addr:target_port\n\n" \
"[source_addr:]source_port target_addr{:target_port}\n\n" \
" --verbose|-v verbose messages and per frame traffic\n" \
" --daemon|-D become a daemon (background process)\n" \
" --cert CERT SSL certificate file\n" \
" --key KEY SSL key file (if separate from cert)\n" \
" --ssl-only disallow non-encrypted connections";
" --ssl-only disallow non-encrypted connections\n" \
" --whitelist|-w LIST new-line separated target port whitelist file\n" \
" (target_port is not required only with this option)\n" \
" --pattern|-P target port request pattern. Default: '/%d'\n" \
" --pid|-p desired path of pid file. Default: '/var/run/websockify.pid'";
#define usage(fmt, args...) \
do { \
fprintf(stderr, "%s\n\n", USAGE); \
fprintf(stderr, fmt , ## args); \
exit(1);
exit(1); \
} while(0)
char target_host[256];
int target_port;
int *target_ports;
extern pipe_error;
extern settings_t settings;
@ -156,7 +164,7 @@ void do_proxy(ws_ctx_t *ws_ctx, int target) {
cout_start = 0;
if (ws_ctx->hybi) {
cout_end = encode_hybi(ws_ctx->cin_buf, bytes,
ws_ctx->cout_buf, BUFSIZE, 1);
ws_ctx->cout_buf, BUFSIZE, ws_ctx->opcode);
} else {
cout_end = encode_hixie(ws_ctx->cin_buf, bytes,
ws_ctx->cout_buf, BUFSIZE);
@ -203,7 +211,7 @@ void do_proxy(ws_ctx_t *ws_ctx, int target) {
}
if (opcode == 8) {
handler_emsg("client sent orderly close frame\n");
handler_msg("client sent orderly close frame\n");
break;
}
@ -237,6 +245,27 @@ void proxy_handler(ws_ctx_t *ws_ctx) {
int tsock = 0;
struct sockaddr_in taddr;
if (target_ports != NULL) {
if (sscanf(ws_ctx->headers->path, settings.pattern, &target_port) != 1) {
handler_emsg("Could not match pattern '%s' to request path '%s'\n",
settings.pattern, ws_ctx->headers->path);
return;
}
int *p;
int found = 0;
for (p = target_ports; *p; p++) {
if (*p == target_port) {
found = 1;
break;
}
}
if (!found) {
handler_emsg("Rejecting connection to non-whitelisted port: '%d'\n",
target_port);
return;
}
}
handler_msg("connecting to: %s:%d\n", target_host, target_port);
tsock = socket(AF_INET, SOCK_STREAM, 0);
@ -272,19 +301,77 @@ void proxy_handler(ws_ctx_t *ws_ctx) {
close(tsock);
}
int load_whitelist() {
printf("loading port whitelist '%s'\n", settings.whitelist);
FILE *whitelist = fopen(settings.whitelist, "r");
if (whitelist == NULL) {
fprintf(stderr, "Error opening whitelist file '%s':\n\t%s\n",
settings.whitelist, strerror(errno));
return -1;
}
const int tplen_grow = 512;
int tplen = tplen_grow, tpcount = 0;
target_ports = (int*)malloc(tplen*sizeof(int));
if (target_ports == NULL) {
fprintf(stderr, "Whitelist port malloc error");
return -2;
}
char *line = NULL;
ssize_t n = 0, nread = 0;
while ((nread = getline(&line, &n, whitelist)) > 0) {
if (line[0] == '\n') continue;
line[nread-1] = '\x00';
long int port = strtol(line, NULL, 10);
if (port < 1 || port > 65535) {
fprintf(stderr,
"Whitelist port '%s' is not between valid range 1 and 65535", line);
return -3;
}
tpcount++;
if (tpcount >= tplen) {
tplen += tplen_grow;
target_ports = (int*)realloc(target_ports, tplen*sizeof(int));
if (target_ports == NULL) {
fprintf(stderr, "Whitelist port realloc error");
return -2;
}
}
target_ports[tpcount-1] = port;
}
if (line != NULL) free(line);
if (tpcount == 0) {
fprintf(stderr, "0 ports read from whitelist file '%s'\n",
settings.whitelist);
return -4;
}
target_ports = (int*)realloc(target_ports, (tpcount + 1)*sizeof(int));
if (target_ports == NULL) {
fprintf(stderr, "Whitelist port realloc error");
return -2;
}
target_ports[tpcount] = 0;
return 0;
}
int main(int argc, char *argv[])
{
int fd, c, option_index = 0;
static int ssl_only = 0, daemon = 0, run_once = 0, verbose = 0;
char *found;
static struct option long_options[] = {
{"verbose", no_argument, &verbose, 'v'},
{"ssl-only", no_argument, &ssl_only, 1 },
{"daemon", no_argument, &daemon, 'D'},
{"verbose", no_argument, 0, 'v'},
{"ssl-only", no_argument, &settings.ssl_only, 1 },
{"daemon", no_argument, 0, 'D'},
/* ---- */
{"run-once", no_argument, 0, 'r'},
{"cert", required_argument, 0, 'c'},
{"key", required_argument, 0, 'k'},
{"whitelist", required_argument, 0, 'w'},
{"pattern", required_argument, 0, 'P'},
{"pid", required_argument, 0, 'p'},
{0, 0, 0, 0}
};
@ -294,13 +381,15 @@ int main(int argc, char *argv[])
settings.cert = "self.pem";
}
settings.key = "";
settings.pattern = "/%d";
settings.pid = "/var/run/websockify.pid";
while (1) {
c = getopt_long (argc, argv, "vDrc:k:",
c = getopt_long (argc, argv, "vDrc:k:w:p:P:",
long_options, &option_index);
/* Detect the end */
if (c == -1) { break; }
if (c == -1) break;
switch (c) {
case 0:
@ -308,13 +397,13 @@ int main(int argc, char *argv[])
case 1:
break; // ignore
case 'v':
verbose = 1;
settings.verbose = 1;
break;
case 'D':
daemon = 1;
settings.daemon = 1;
break;
case 'r':
run_once = 1;
settings.run_once = 1;
break;
case 'c':
settings.cert = realpath(optarg, NULL);
@ -328,14 +417,22 @@ int main(int argc, char *argv[])
usage("No key file at %s\n", optarg);
}
break;
case 'w':
settings.whitelist = realpath(optarg, NULL);
if (! settings.whitelist) {
usage("No whitelist file at %s\n", optarg);
}
break;
case 'P':
settings.pattern = optarg;
break;
case 'p':
settings.pid = optarg;
break;
default:
usage(" ");
}
}
settings.verbose = verbose;
settings.ssl_only = ssl_only;
settings.daemon = daemon;
settings.run_once = run_once;
if ((argc-optind) != 2) {
usage("Invalid number of arguments\n");
@ -355,17 +452,25 @@ int main(int argc, char *argv[])
}
found = strstr(argv[optind], ":");
if (found) {
if (found && settings.whitelist == NULL) {
memcpy(target_host, argv[optind], found-argv[optind]);
target_port = strtol(found+1, NULL, 10);
target_ports = NULL;
} else if (!found && settings.whitelist != NULL) {
if (load_whitelist()) {
usage("Whitelist error.");
}
memcpy(target_host, argv[optind], strlen(argv[optind]));
target_port = -1;
} else {
usage("Target argument must be host:port\n");
usage("Target argument must be host:port or provide host and a port whitelist\n");
}
if (target_port == 0) {
usage("Could not parse target port\n");
}
if (ssl_only) {
if (settings.ssl_only) {
if (access(settings.cert, R_OK) != 0) {
usage("SSL only and cert file '%s' not found\n", settings.cert);
}