Compare commits

..
7 Commits
14 changed files with 129 additions and 54 deletions

No files matched your search

+14
View File
@@ -1,3 +1,17 @@
v1.23.x:
Obsolete. Please use v2.0 or above. This is a branch
where no new features will be introduced, only
bugfixes to versions below 1.22.
v1.23.1:
Check accept() for failure in sslh-fork. Aborted
connections otherwise result in crashes.
v1.23.0:
Reintroduce --ssl as alias to --tls.
v1.22: 17AUG2021
sslh-select now supports UDP protocols.
Probes specified in the `protocols`
+4 -3
View File
@@ -30,8 +30,9 @@ struct cnx_collection {
gap_array* fd2cnx; /* Array indexed by file descriptor to things in cnx[] */
};
/* Allocates and initialises a new collection of connections. */
cnx_collection* collection_init(void)
/* Allocates and initialises a new collection of connections with at least
* `len` elements. */
cnx_collection* collection_init(int len)
{
cnx_collection* collection;
@@ -40,7 +41,7 @@ cnx_collection* collection_init(void)
memset(collection, 0, sizeof(*collection));
collection->fd2cnx = gap_init();
collection->fd2cnx = gap_init(len);
return collection;
}
+1 -1
View File
@@ -4,7 +4,7 @@
typedef struct cnx_collection cnx_collection;
cnx_collection* collection_init(void);
cnx_collection* collection_init(int len);
void collection_destroy(cnx_collection* collection);
struct connection* collection_alloc_cnx_from_fd(cnx_collection* collection, int fd);
+1 -1
View File
@@ -188,7 +188,7 @@ int start_listen_sockets(struct listen_endpoint *sockfd[])
for (addr = start_addr; addr; addr = addr->ai_next) {
num_addr++;
*sockfd = realloc(*sockfd, num_addr * sizeof(*sockfd));
*sockfd = realloc(*sockfd, num_addr * sizeof(*sockfd[0]));
(*sockfd)[num_addr-1].socketfd = listen_single_addr(addr, keepalive, udp);
(*sockfd)[num_addr-1].type = udp ? SOCK_DGRAM : SOCK_STREAM;
if (cfg.verbose)
-1
View File
@@ -171,7 +171,6 @@ int flush_deferred(struct queue *q);
extern struct sslhcfg_item cfg;
extern struct addrinfo *addr_listen;
extern const char* USAGE_STRING;
extern const char* server_type;
/* sslh-fork.c */
+4 -3
View File
@@ -42,8 +42,8 @@ static int gap_len_alloc(int elem_size)
return getpagesize() / elem_size;
}
/* Creates a new gap, all pointers are initialised at NULL */
gap_array* gap_init(void)
/* Creates a new gap at least `len` big, all pointers are initialised at NULL */
gap_array* gap_init(int len)
{
gap_array* gap = malloc(sizeof(*gap));
if (!gap) return NULL;
@@ -51,6 +51,7 @@ gap_array* gap_init(void)
int elem_size = sizeof(gap->array[0]);
gap->len = gap_len_alloc(elem_size);
if (gap->len < len) gap->len = len;
gap->array = malloc(gap->len * elem_size);
if (!gap->array) return NULL;
@@ -85,7 +86,7 @@ static int gap_extend(gap_array* gap)
int gap_set(gap_array* gap, int index, void* ptr)
{
if (index >= gap->len) {
while (index >= gap->len) {
int res = gap_extend(gap);
if (res == -1) return -1;
}
+1 -1
View File
@@ -3,7 +3,7 @@
typedef struct gap_array gap_array;
gap_array* gap_init();
gap_array* gap_init(int len);
void* gap_get(gap_array* gap, int index);
int gap_set(gap_array* gap, int index, void* ptr);
void gap_destroy(gap_array* gap);
+57 -13
View File
@@ -1,5 +1,5 @@
/* Generated by conf2struct (https://www.rutschle.net/tech/conf2struct/README)
* on Fri Aug 13 18:03:18 2021.
* on Tue Jan 2 21:42:30 2024.
# conf2struct: generate libconf parsers that read to structs
# Copyright (C) 2018-2021 Yves Rutschle
@@ -444,6 +444,7 @@ struct compound_cl_arg {
struct arg_file* sslhcfg_conffile;
struct arg_int* sslhcfg_verbose;
struct arg_lit* sslhcfg_version;
struct arg_lit* sslhcfg_foreground;
struct arg_lit* sslhcfg_inetd;
struct arg_lit* sslhcfg_numeric;
@@ -458,6 +459,7 @@ struct arg_file* sslhcfg_conffile;
struct arg_str* sslhcfg_listen;
struct arg_str* sslhcfg_ssh;
struct arg_str* sslhcfg_tls;
struct arg_str* sslhcfg_ssl;
struct arg_str* sslhcfg_openvpn;
struct arg_str* sslhcfg_tinc;
struct arg_str* sslhcfg_xmpp;
@@ -782,7 +784,7 @@ static struct config_desc table_sslhcfg_listen[] = {
},
{ 0 }
};
static struct config_desc table_sslhcfg[] = {
@@ -802,6 +804,22 @@ static struct config_desc table_sslhcfg[] = {
/* default_val*/ .default_val.def_int = 0
},
{
/* name */ "version",
/* type */ CFG_BOOL,
/* sub_group*/ NULL,
/* arg_cl */ & sslhcfg_version,
/* base_addr */ NULL,
/* offset */ offsetof(struct sslhcfg_item, version),
/* offset_len */ 0,
/* offset_present */ 0,
/* size */ sizeof(int),
/* array_type */ -1,
/* mandatory */ 0,
/* optional */ 0,
/* default_val*/ .default_val.def_bool = 0
},
{
/* name */ "foreground",
/* type */ CFG_BOOL,
@@ -1077,6 +1095,15 @@ static struct compound_cl_target sslhcfg_openvpn_targets [] = {
{ 0 }
};
static struct compound_cl_target sslhcfg_ssl_targets [] = {
{ & table_sslhcfg_protocols[0], 0, .value.def_string = "tls" },
{ & table_sslhcfg_protocols[1], 1, .value.def_string = "0" },
{ & table_sslhcfg_protocols[2], 2, .value.def_string = "0" },
{ & table_sslhcfg_protocols[9], 0, .value.def_int = 1 },
{ & table_sslhcfg_protocols[7], 0, .value.def_bool = 1 },
{ 0 }
};
static struct compound_cl_target sslhcfg_tls_targets [] = {
{ & table_sslhcfg_protocols[0], 0, .value.def_string = "tls" },
{ & table_sslhcfg_protocols[1], 1, .value.def_string = "0" },
@@ -1106,7 +1133,7 @@ static struct compound_cl_arg compound_cl_args[] = {
{ /* arg: listen */
.regex = "(.+):(\\w+)",
.arg_cl = & sslhcfg_listen,
.base_entry = & table_sslhcfg [12],
.base_entry = & table_sslhcfg [13],
.targets = sslhcfg_listen_targets,
@@ -1118,7 +1145,7 @@ static struct compound_cl_arg compound_cl_args[] = {
{ /* arg: ssh */
.regex = "(.+):(\\w+)",
.arg_cl = & sslhcfg_ssh,
.base_entry = & table_sslhcfg [13],
.base_entry = & table_sslhcfg [14],
.targets = sslhcfg_ssh_targets,
@@ -1130,7 +1157,7 @@ static struct compound_cl_arg compound_cl_args[] = {
{ /* arg: tls */
.regex = "(.+):(\\w+)",
.arg_cl = & sslhcfg_tls,
.base_entry = & table_sslhcfg [13],
.base_entry = & table_sslhcfg [14],
.targets = sslhcfg_tls_targets,
@@ -1139,10 +1166,22 @@ static struct compound_cl_arg compound_cl_args[] = {
.override_const = "tls",
},
{ /* arg: ssl */
.regex = "(.+):(\\w+)",
.arg_cl = & sslhcfg_ssl,
.base_entry = & table_sslhcfg [14],
.targets = sslhcfg_ssl_targets,
.override_desc = & table_sslhcfg_protocols [0],
.override_matchindex = 0,
.override_const = "tls",
},
{ /* arg: openvpn */
.regex = "(.+):(\\w+)",
.arg_cl = & sslhcfg_openvpn,
.base_entry = & table_sslhcfg [13],
.base_entry = & table_sslhcfg [14],
.targets = sslhcfg_openvpn_targets,
@@ -1154,7 +1193,7 @@ static struct compound_cl_arg compound_cl_args[] = {
{ /* arg: tinc */
.regex = "(.+):(\\w+)",
.arg_cl = & sslhcfg_tinc,
.base_entry = & table_sslhcfg [13],
.base_entry = & table_sslhcfg [14],
.targets = sslhcfg_tinc_targets,
@@ -1166,7 +1205,7 @@ static struct compound_cl_arg compound_cl_args[] = {
{ /* arg: xmpp */
.regex = "(.+):(\\w+)",
.arg_cl = & sslhcfg_xmpp,
.base_entry = & table_sslhcfg [13],
.base_entry = & table_sslhcfg [14],
.targets = sslhcfg_xmpp_targets,
@@ -1178,7 +1217,7 @@ static struct compound_cl_arg compound_cl_args[] = {
{ /* arg: http */
.regex = "(.+):(\\w+)",
.arg_cl = & sslhcfg_http,
.base_entry = & table_sslhcfg [13],
.base_entry = & table_sslhcfg [14],
.targets = sslhcfg_http_targets,
@@ -1190,7 +1229,7 @@ static struct compound_cl_arg compound_cl_args[] = {
{ /* arg: adb */
.regex = "(.+):(\\w+)",
.arg_cl = & sslhcfg_adb,
.base_entry = & table_sslhcfg [13],
.base_entry = & table_sslhcfg [14],
.targets = sslhcfg_adb_targets,
@@ -1202,7 +1241,7 @@ static struct compound_cl_arg compound_cl_args[] = {
{ /* arg: socks5 */
.regex = "(.+):(\\w+)",
.arg_cl = & sslhcfg_socks5,
.base_entry = & table_sslhcfg [13],
.base_entry = & table_sslhcfg [14],
.targets = sslhcfg_socks5_targets,
@@ -1214,7 +1253,7 @@ static struct compound_cl_arg compound_cl_args[] = {
{ /* arg: syslog */
.regex = "(.+):(\\w+)",
.arg_cl = & sslhcfg_syslog,
.base_entry = & table_sslhcfg [13],
.base_entry = & table_sslhcfg [14],
.targets = sslhcfg_syslog_targets,
@@ -1226,7 +1265,7 @@ static struct compound_cl_arg compound_cl_args[] = {
{ /* arg: anyprot */
.regex = "(.+):(\\w+)",
.arg_cl = & sslhcfg_anyprot,
.base_entry = & table_sslhcfg [13],
.base_entry = & table_sslhcfg [14],
.targets = sslhcfg_anyprot_targets,
@@ -1892,6 +1931,7 @@ int sslhcfg_cl_parse(int argc, char* argv[], struct sslhcfg_item* cfg)
sslhcfg_conffile = arg_filen("F", "config", "<file>", 0, 1, "Specify configuration file"),
#endif
sslhcfg_verbose = arg_intn("v", "verbose", "<n>", 0, 1, ""),
sslhcfg_version = arg_litn("V", "version", 0, 1, "Print version information and exit"),
sslhcfg_foreground = arg_litn("f", "foreground", 0, 1, "Run in foreground instead of as a daemon"),
sslhcfg_inetd = arg_litn("i", "inetd", 0, 1, "Run in inetd mode: use stdin/stdout instead of network listen"),
sslhcfg_numeric = arg_litn("n", "numeric", 0, 1, "Print IP addresses and ports as numbers"),
@@ -1906,6 +1946,7 @@ int sslhcfg_cl_parse(int argc, char* argv[], struct sslhcfg_item* cfg)
sslhcfg_listen = arg_strn("p", "listen", "<host:port>", 0, 10, "Listen on host:port"),
sslhcfg_ssh = arg_strn(NULL, "ssh", "<host:port>", 0, 10, "Set up ssh target"),
sslhcfg_tls = arg_strn(NULL, "tls", "<host:port>", 0, 10, "Set up TLS/SSL target"),
sslhcfg_ssl = arg_strn(NULL, "ssl", "<host:port>", 0, 10, "Set up TLS/SSL target"),
sslhcfg_openvpn = arg_strn(NULL, "openvpn", "<host:port>", 0, 10, "Set up OpenVPN target"),
sslhcfg_tinc = arg_strn(NULL, "tinc", "<host:port>", 0, 10, "Set up tinc target"),
sslhcfg_xmpp = arg_strn(NULL, "xmpp", "<host:port>", 0, 10, "Set up XMPP target"),
@@ -2062,6 +2103,9 @@ void sslhcfg_fprint(
fprintf(out, "verbose: %d", sslhcfg->verbose);
fprintf(out, "\n");
indent(out, depth);
fprintf(out, "version: %d", sslhcfg->version);
fprintf(out, "\n");
indent(out, depth);
fprintf(out, "foreground: %d", sslhcfg->foreground);
fprintf(out, "\n");
indent(out, depth);
+2 -1
View File
@@ -1,5 +1,5 @@
/* Generated by conf2struct (https://www.rutschle.net/tech/conf2struct/README)
* on Fri Aug 13 18:03:18 2021.
* on Tue Jan 2 21:42:30 2024.
# conf2struct: generate libconf parsers that read to structs
# Copyright (C) 2018-2021 Yves Rutschle
@@ -75,6 +75,7 @@ struct sslhcfg_protocols_item {
struct sslhcfg_item {
int verbose;
int version;
int foreground;
int inetd;
int numeric;
+1
View File
@@ -179,6 +179,7 @@ void tcp_listener(struct listen_endpoint* endpoint, int num_endpoints, int activ
while (1) {
in_socket = accept(endpoint[active_endpoint].socketfd, 0, 0);
if (in_socket == -1) continue;
if (cfg.verbose) fprintf(stderr, "accepted fd %d\n", in_socket);
switch(fork()) {
+6 -23
View File
@@ -37,29 +37,6 @@
#include "common.h"
#include "probe.h"
const char* USAGE_STRING =
"sslh " VERSION "\n" \
"usage:\n" \
"\tsslh [-v] [-i] [-V] [-f] [-n] [--transparent] [-F<file>]\n"
"\t[-t <timeout>] [-P <pidfile>] [-u <username>] [-C <chroot>] -p <addr> [-p <addr> ...] \n" \
"%s\n\n" /* Dynamically built list of builtin protocols */ \
"\t[--on-timeout <addr>]\n" \
"-v: verbose\n" \
"-V: version\n" \
"-f: foreground\n" \
"-n: numeric output\n" \
"-u: specify under which user to run\n" \
"-C: specify under which chroot path to run\n" \
"--transparent: behave as a transparent proxy\n" \
"-F: use configuration file (warning: no space between -F and file name!)\n" \
"--on-timeout: connect to specified address upon timeout (default: ssh address)\n" \
"-t: seconds to wait before connecting to --on-timeout address.\n" \
"-p: address and port to listen on.\n Can be used several times to bind to several addresses.\n" \
"--[ssh,ssl,...]: where to connect connections from corresponding protocol.\n" \
"-P: PID file.\n" \
"-i: Run as a inetd service.\n" \
"";
/* Constants for options that have no one-character shorthand */
#define OPT_ONTIMEOUT 257
@@ -209,6 +186,12 @@ int main(int argc, char *argv[], char* envp[])
if (res) exit(6);
if (cfg.verbose > 3)
sslhcfg_fprint(stderr, &cfg, 0);
if (cfg.version) {
printf("%s %s\n", server_type, VERSION);
exit(0);
}
config_protocols();
config_sanity_check(&cfg);
+8 -7
View File
@@ -475,15 +475,16 @@ static void udp_timeouts(struct select_info* fd_info)
if (now < fd_info->next_timeout) return;
for (int i = 0; i < fd_info->max_fd; i++) {
time_t next_timeout = INT_MAX;
time_t next_timeout = INT_MAX;
for (int i = 0; i < fd_info->max_fd; i++) {
/* if it's either in read or write set, there is a connection
* behind that file descriptor */
if (FD_ISSET(i, &fd_info->fds_r) || FD_ISSET(i, &fd_info->fds_w)) {
struct connection* cnx = collection_get_cnx_from_fd(fd_info->collection, i);
if (cnx) {
time_t timeout = udp_timeout(cnx);
if (!timeout) continue; /* Not a UDP connection */
if (cnx && (timeout <= now)) {
if (cfg.verbose > 3)
fprintf(stderr, "timed out UDP %d\n", cnx->target_sock);
@@ -496,10 +497,10 @@ static void udp_timeouts(struct select_info* fd_info)
}
}
}
if (next_timeout != INT_MAX)
fd_info->next_timeout = next_timeout;
}
if (next_timeout != INT_MAX)
fd_info->next_timeout = next_timeout;
}
/* Main loop: the idea is as follow:
@@ -526,7 +527,7 @@ void main_loop(struct listen_endpoint listen_sockets[], int num_addr_listen)
fd_info.num_probing = 0;
FD_ZERO(&fd_info.fds_r);
FD_ZERO(&fd_info.fds_w);
fd_info.probing_list = gap_init();
fd_info.probing_list = gap_init(0);
for (i = 0; i < num_addr_listen; i++) {
FD_SET(listen_sockets[i].socketfd, &fd_info.fds_r);
@@ -534,7 +535,7 @@ void main_loop(struct listen_endpoint listen_sockets[], int num_addr_listen)
}
fd_info.max_fd = listen_sockets[num_addr_listen-1].socketfd + 1;
fd_info.collection = collection_init();
fd_info.collection = collection_init(fd_info.max_fd);
while (1)
{
+16
View File
@@ -26,6 +26,9 @@ config: {
type: "list",
items: (
{ name: "verbose"; type: "int"; default: 0; short: "v"; },
{ name: "version"; type: "bool"; default: false;
short: "V";
description: "Print version information and exit"; },
{ name: "foreground"; type: "bool"; default: false;
short: "f";
description: "Run in foreground instead of as a daemon"; },
@@ -152,6 +155,19 @@ cl_groups: (
{ path: "tfo_ok"; value: 1 }
);
},
# Redundant with the --tls setting before, for backwards compatibility
{ name: "ssl"; pattern: "(.+):(\w+)"; description: "Set up TLS/SSL target";
list: "protocols";
override: "name";
argdesc: "<host:port>";
targets: (
{ path: "name"; value: "tls" },
{ path: "host"; value: "$1" },
{ path: "port"; value: "$2" },
{ path: "log_level"; value: 1 },
{ path: "tfo_ok"; value: 1 }
);
},
{ name: "openvpn"; pattern: "(.+):(\w+)"; description: "Set up OpenVPN target";
list: "protocols";
override: "name";
+14
View File
@@ -26,6 +26,7 @@ my $PROBES_NOFRAG = 1;
my $PROBES_AGAIN = 1;
my $SSL_MIX_SSH = 1;
my $SSH_MIX_SSL = 1;
my $DROP_CNX = 1;
# Robustness tests. These are mostly to achieve full test
# coverage, but do not necessarily result in an actual test
@@ -285,6 +286,19 @@ for my $binary (@binaries) {
}
}
# Test: Drop connection without writing anything
if ($DROP_CNX) {
print "***Test: Connect but don't write anything\n";
my $cnx_h = new IO::Socket::INET(PeerHost => "localhost:$sslh_port");
warn "$!\n" unless $cnx_h;
if ($cnx_h) {
close $cnx_h;
my_is(1, "$binary: Connect and write nothing");
# The goal of the test is to check sslh doesn't
# crash
}
}
if ($PROBES_NOFRAG) {
test_probes(no_frag => 1, binary => $binary);