diff --git a/Makefile b/Makefile index 986cf1c..b8db122 100644 --- a/Makefile +++ b/Makefile @@ -95,7 +95,7 @@ systemd-sslh-generator: systemd-sslh-generator.o $(CC) $(CFLAGS) $(LDFLAGS) -o systemd-sslh-generator systemd-sslh-generator.o -lconfig echosrv: version.h $(OBJS) echosrv.o - $(CC) $(CFLAGS) $(LDFLAGS) -o echosrv echosrv.o probe.o common.o tls.o $(LIBS) + $(CC) $(CFLAGS) $(LDFLAGS) -o echosrv echosrv.o sslh-conf.o probe.o common.o tls.o argtable3.o $(LIBS) $(MAN): sslh.pod Makefile pod2man --section=8 --release=$(VERSION) --center=" " sslh.pod | gzip -9 - > $(MAN) @@ -124,7 +124,7 @@ uninstall: update-rc.d sslh remove distclean: clean - rm -f tags sslh-conf.c sslh-conf.h cscope.* + rm -f tags sslh-conf.[ch] echosrv-conf.[ch] cscope.* clean: rm -f sslh-fork sslh-select echosrv version.h $(MAN) systemd-sslh-generator *.o *.gcov *.gcno *.gcda *.png *.html *.css *.info diff --git a/echosrv.c b/echosrv.c index 66a9675..b02db9c 100644 --- a/echosrv.c +++ b/echosrv.c @@ -29,6 +29,7 @@ #include #include "common.h" +#include "sslh-conf.h" /* Added to make the code compilable under CYGWIN * */ @@ -36,74 +37,18 @@ #define SA_NOCLDWAIT 0 #endif -const char* USAGE_STRING = -"echosrv\n" \ -"usage:\n" \ -"\techosrv [-v] --listen [--prefix ]\n" -"-v: verbose\n" \ -"--listen: address to listen on. Can be specified multiple times.\n" \ -"--prefix: add specified prefix before every line echoed.\n" -""; - const char* server_type = "echsrv"; /* keep setup_syslog happy */ -/* - * Settings that depend on the command line. - */ -char* prefix = ""; -int port; - -int verbose, numeric; - -void parse_cmdline(int argc, char* argv[]) -{ - int c; - struct option options[] = { - { "verbose", no_argument, &verbose, 1 }, - { "numeric", no_argument, &numeric, 1 }, - { "listen", required_argument, 0, 'l' }, - { "prefix", required_argument, 0, 'p' }, - }; - struct addrinfo **a; - - while ((c = getopt_long_only(argc, argv, "l:p:", options, NULL)) != -1) { - if (c == 0) continue; - - switch (c) { - - case 'l': - /* find the end of the listen list */ - for (a = &addr_listen; *a; a = &((*a)->ai_next)); - /* append the specified addresses */ - resolve_name(a, optarg); - break; - - case 'p': - prefix = optarg; - break; - - default: - fprintf(stderr, "%s", USAGE_STRING); - exit(2); - } - } - - if (!addr_listen) { - fprintf(stderr, "No listening port specified\n"); - exit(1); - } -} - void start_echo(int fd) { int res; char buffer[1 << 20]; int ret, prefix_len; - prefix_len = strlen(prefix); + prefix_len = strlen(cfg.prefix); memset(buffer, 0, sizeof(buffer)); - strcpy(buffer, prefix); + strcpy(buffer, cfg.prefix); while (1) { ret = read(fd, buffer + prefix_len, sizeof(buffer) - prefix_len); @@ -128,7 +73,7 @@ void main_loop(int listen_sockets[], int num_addr_listen) while (1) { in_socket = accept(listen_sockets[i], 0, 0); - if (verbose) fprintf(stderr, "accepted fd %d\n", in_socket); + if (cfg.verbose) fprintf(stderr, "accepted fd %d\n", in_socket); if (!fork()) { @@ -143,6 +88,26 @@ void main_loop(int listen_sockets[], int num_addr_listen) wait(NULL); } +static int config_resolve_listen(struct addrinfo **listen) +{ + int i, res; + for (i = 0; i < cfg.listen_len; i++) { + res = resolve_split_name(listen, cfg.listen[i].host, cfg.listen[i].port); + if (res) return res; + + /* getaddrinfo returned a list of addresses corresponding to the + * specification; move the pointer to the end of that list before + * processing the next specification, while setting flags for + * start_listen_sockets() through ai_flags (which is not meant for + * that, but is only used as hint in getaddrinfo, so it's OK) */ + for (; *listen; listen = &((*listen)->ai_next)) { + if (cfg.listen[i].keepalive) + (*listen)->ai_flags = SO_KEEPALIVE; + } + } + return 0; +} + int main(int argc, char *argv[]) { @@ -152,8 +117,13 @@ int main(int argc, char *argv[]) int *listen_sockets; - parse_cmdline(argc, argv); + memset(&cfg, 0, sizeof(cfg)); + if (sslhcfg_cl_parse(argc, argv, &cfg)) + exit(1); + sslhcfg_fprint(stdout, &cfg, 0); + + config_resolve_listen(&addr_listen); num_addr_listen = start_listen_sockets(&listen_sockets, addr_listen); main_loop(listen_sockets, num_addr_listen); diff --git a/sslh-conf.c b/sslh-conf.c index fd4cc32..ab25702 100644 --- a/sslh-conf.c +++ b/sslh-conf.c @@ -1,5 +1,5 @@ /* Generated by conf2struct (https://www.rutschle.net/tech/conf2struct/README) - * on Sat Aug 29 18:12:55 2020. + * on Sat Nov 7 09:23:57 2020. # conf2struct: generate libconf parsers that read to structs # Copyright (C) 2018-2019 Yves Rutschle @@ -409,6 +409,7 @@ struct arg_file* sslhcfg_conffile; struct arg_str* sslhcfg_chroot; struct arg_str* sslhcfg_syslog_facility; struct arg_str* sslhcfg_on_timeout; + struct arg_str* sslhcfg_prefix; struct arg_str* sslhcfg_listen; struct arg_str* sslhcfg_ssh; struct arg_str* sslhcfg_tls; @@ -671,7 +672,7 @@ static struct config_desc table_sslhcfg_listen[] = { }, { 0 } }; - + static struct config_desc table_sslhcfg[] = { @@ -851,6 +852,22 @@ static struct config_desc table_sslhcfg[] = { /* default_val*/ .default_val.def_string = "ssh" }, + { + /* name */ "prefix", + /* type */ CFG_STRING, + /* sub_group*/ NULL, + /* arg_cl */ & sslhcfg_prefix, + /* base_addr */ NULL, + /* offset */ offsetof(struct sslhcfg_item, prefix), + /* offset_len */ 0, + /* offset_present */ 0, + /* size */ sizeof(char*), + /* array_type */ -1, + /* mandatory */ 1, + /* optional */ 0, + /* default_val*/ .default_val.def_string = NULL + }, + { /* name */ "listen", /* type */ CFG_LIST, @@ -971,7 +988,7 @@ static struct compound_cl_arg compound_cl_args[] = { { /* arg: listen */ .regex = "(.+):(\\w+)", .arg_cl = & sslhcfg_listen, - .base_entry = & table_sslhcfg [11], + .base_entry = & table_sslhcfg [12], .targets = sslhcfg_listen_targets, @@ -983,7 +1000,7 @@ static struct compound_cl_arg compound_cl_args[] = { { /* arg: ssh */ .regex = "(.+):(\\w+)", .arg_cl = & sslhcfg_ssh, - .base_entry = & table_sslhcfg [12], + .base_entry = & table_sslhcfg [13], .targets = sslhcfg_ssh_targets, @@ -995,7 +1012,7 @@ static struct compound_cl_arg compound_cl_args[] = { { /* arg: tls */ .regex = "(.+):(\\w+)", .arg_cl = & sslhcfg_tls, - .base_entry = & table_sslhcfg [12], + .base_entry = & table_sslhcfg [13], .targets = sslhcfg_tls_targets, @@ -1007,7 +1024,7 @@ static struct compound_cl_arg compound_cl_args[] = { { /* arg: openvpn */ .regex = "(.+):(\\w+)", .arg_cl = & sslhcfg_openvpn, - .base_entry = & table_sslhcfg [12], + .base_entry = & table_sslhcfg [13], .targets = sslhcfg_openvpn_targets, @@ -1019,7 +1036,7 @@ static struct compound_cl_arg compound_cl_args[] = { { /* arg: tinc */ .regex = "(.+):(\\w+)", .arg_cl = & sslhcfg_tinc, - .base_entry = & table_sslhcfg [12], + .base_entry = & table_sslhcfg [13], .targets = sslhcfg_tinc_targets, @@ -1031,7 +1048,7 @@ static struct compound_cl_arg compound_cl_args[] = { { /* arg: xmpp */ .regex = "(.+):(\\w+)", .arg_cl = & sslhcfg_xmpp, - .base_entry = & table_sslhcfg [12], + .base_entry = & table_sslhcfg [13], .targets = sslhcfg_xmpp_targets, @@ -1043,7 +1060,7 @@ static struct compound_cl_arg compound_cl_args[] = { { /* arg: http */ .regex = "(.+):(\\w+)", .arg_cl = & sslhcfg_http, - .base_entry = & table_sslhcfg [12], + .base_entry = & table_sslhcfg [13], .targets = sslhcfg_http_targets, @@ -1055,7 +1072,7 @@ static struct compound_cl_arg compound_cl_args[] = { { /* arg: adb */ .regex = "(.+):(\\w+)", .arg_cl = & sslhcfg_adb, - .base_entry = & table_sslhcfg [12], + .base_entry = & table_sslhcfg [13], .targets = sslhcfg_adb_targets, @@ -1067,7 +1084,7 @@ static struct compound_cl_arg compound_cl_args[] = { { /* arg: socks5 */ .regex = "(.+):(\\w+)", .arg_cl = & sslhcfg_socks5, - .base_entry = & table_sslhcfg [12], + .base_entry = & table_sslhcfg [13], .targets = sslhcfg_socks5_targets, @@ -1079,7 +1096,7 @@ static struct compound_cl_arg compound_cl_args[] = { { /* arg: anyprot */ .regex = "(.+):(\\w+)", .arg_cl = & sslhcfg_anyprot, - .base_entry = & table_sslhcfg [12], + .base_entry = & table_sslhcfg [13], .targets = sslhcfg_anyprot_targets, @@ -1694,6 +1711,7 @@ int sslhcfg_cl_parse(int argc, char* argv[], struct sslhcfg_item* cfg) sslhcfg_chroot = arg_strn("C", "chroot", "", 0, 1, "Root to change to after set-up"), sslhcfg_syslog_facility = arg_strn(NULL, "syslog-facility", "", 0, 1, "Facility to syslog to"), sslhcfg_on_timeout = arg_strn(NULL, "on-timeout", "", 0, 1, "Target to connect to when timing out"), + sslhcfg_prefix = arg_strn(NULL, "prefix", "", 0, 1, "Reserved for testing"), sslhcfg_listen = arg_strn("p", "listen", "", 0, 10, "Listen on host:port"), sslhcfg_ssh = arg_strn(NULL, "ssh", "", 0, 10, "Set up ssh target"), sslhcfg_tls = arg_strn(NULL, "tls", "", 0, 10, "Set up TLS/SSL target"), @@ -1875,6 +1893,9 @@ void sslhcfg_fprint( indent(out, depth); fprintf(out, "on_timeout: %s", sslhcfg->on_timeout); fprintf(out, "\n"); + indent(out, depth); + fprintf(out, "prefix: %s", sslhcfg->prefix); + fprintf(out, "\n"); indent(out, depth); fprintf(out, "listen [%zu]:\n", sslhcfg->listen_len); diff --git a/sslh-conf.h b/sslh-conf.h index 53f6361..df0b845 100644 --- a/sslh-conf.h +++ b/sslh-conf.h @@ -1,5 +1,5 @@ /* Generated by conf2struct (https://www.rutschle.net/tech/conf2struct/README) - * on Sat Aug 29 18:12:55 2020. + * on Sat Nov 7 09:23:57 2020. # conf2struct: generate libconf parsers that read to structs # Copyright (C) 2018-2019 Yves Rutschle @@ -84,6 +84,7 @@ struct sslhcfg_item { char* chroot; char* syslog_facility; char* on_timeout; + char* prefix; size_t listen_len; struct sslhcfg_listen_item* listen; size_t protocols_len; diff --git a/sslhconf.cfg b/sslhconf.cfg index 56826ed..76760fd 100644 --- a/sslhconf.cfg +++ b/sslhconf.cfg @@ -55,6 +55,8 @@ config: { { name: "on-timeout"; type: "string"; default: "ssh"; description: "Target to connect to when timing out"; }, + { name: "prefix"; type: "string"; description: "Reserved for testing" }, # For echosrv only, not sslh + { name: "listen", no_cl_accessors: true; # disable generation of individual cl options for each group element (we create a specific --listen option further below) type: "list",