diff --git a/common.c b/common.c index 2758c06..9274d19 100644 --- a/common.c +++ b/common.c @@ -15,6 +15,7 @@ #include "common.h" #include "probe.h" +#include "log.h" #include "sslh-conf.h" /* Added to make the code compilable under CYGWIN @@ -174,7 +175,7 @@ int start_listen_sockets(struct listen_endpoint *sockfd[]) *sockfd = NULL; - if (cfg.verbose) fprintf(stderr, "Listening to:\n"); + print_message(msg_config, "Listening to:\n"); for (i = 0; i < cfg.listen_len; i++) { keepalive = cfg.listen[i].keepalive; @@ -188,10 +189,9 @@ int start_listen_sockets(struct listen_endpoint *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) - fprintf(stderr, "%d:\t%s\t[%s] [%s]\n", (*sockfd)[num_addr-1].socketfd, sprintaddr(buf, sizeof(buf), addr), - cfg.listen[i].keepalive ? "keepalive" : "", - cfg.listen[i].is_udp ? "udp" : ""); + print_message(msg_config, "%d:\t%s\t[%s] [%s]\n", (*sockfd)[num_addr-1].socketfd, sprintaddr(buf, sizeof(buf), addr), + cfg.listen[i].keepalive ? "keepalive" : "", + cfg.listen[i].is_udp ? "udp" : ""); } freeaddrinfo(start_addr); } @@ -793,16 +793,14 @@ void drop_privileges(const char* user_name, const char* chroot_path) if (user_name) { pw = getpwnam(user_name); if (!pw) { - fprintf(stderr, "%s: not found\n", user_name); + print_message(msg_config_error, "%s: not found\n", user_name); exit(2); } - if (cfg.verbose) - fprintf(stderr, "turning into %s\n", user_name); + print_message(msg_config, "turning into %s\n", user_name); } if (chroot_path) { - if (cfg.verbose) - fprintf(stderr, "chrooting into %s\n", chroot_path); + print_message(msg_config, "chrooting into %s\n", chroot_path); res = chroot(chroot_path); CHECK_RES_DIE(res, "chroot"); diff --git a/echosrv-conf.c b/echosrv-conf.c index 38ddc3b..a5d1a71 100644 --- a/echosrv-conf.c +++ b/echosrv-conf.c @@ -1,5 +1,5 @@ /* Generated by conf2struct (https://www.rutschle.net/tech/conf2struct/README) - * on Fri Aug 13 18:03:20 2021. + * on Sat Sep 18 17:28:37 2021. # conf2struct: generate libconf parsers that read to structs # Copyright (C) 2018-2021 Yves Rutschle diff --git a/echosrv-conf.h b/echosrv-conf.h index 4f49e9e..0218d99 100644 --- a/echosrv-conf.h +++ b/echosrv-conf.h @@ -1,5 +1,5 @@ /* Generated by conf2struct (https://www.rutschle.net/tech/conf2struct/README) - * on Fri Aug 13 18:03:20 2021. + * on Sat Sep 18 17:28:37 2021. # conf2struct: generate libconf parsers that read to structs # Copyright (C) 2018-2021 Yves Rutschle diff --git a/example.cfg b/example.cfg index 4b70d48..974a3f9 100644 --- a/example.cfg +++ b/example.cfg @@ -3,7 +3,6 @@ # not be used as a starting point for a working # configuration. Instead use basic.cfg. -verbose: 0; foreground: true; inetd: false; numeric: false; @@ -13,6 +12,13 @@ user: "nobody"; pidfile: "/var/run/sslh.pid"; chroot: "/var/empty"; +verbose: 0; + +# Logging configuration +# Value: 1: stdout; 2: syslog; 3: both +verbose-config: 0; # config: print configuration at startup + + # Specify which syslog facility to use (names for your # system are usually defined in /usr/include/*/sys/syslog.h # or equivalent) diff --git a/log.c b/log.c index fea3d65..11aed81 100644 --- a/log.c +++ b/log.c @@ -29,6 +29,39 @@ #include "common.h" #include "log.h" +msg_info msg_config = { + LOG_INFO, + &cfg.verbose_config +}; + + +msg_info msg_config_error = { + LOG_ERR, + &cfg.verbose_config_error +}; + + +/* Bitmasks in verbose-* values */ +#define MSG_STDOUT 1 +#define MSG_SYSLOG 2 + +/* Prints a message to stderr and/or syslog if appropriate */ +void print_message(msg_info info, const char* str, ...) +{ + va_list ap; + + va_start(ap, str); + + if ((*info.verbose & MSG_STDOUT) && ! cfg.inetd) + vfprintf(stderr, str, ap); + + if (*info.verbose & MSG_SYSLOG) { + va_start(ap, str); + vsyslog(info.log_level, str, ap); + va_end(ap); + } +} + static int do_syslog = 1; /* Should we syslog? controled by syslog_facility = "none" */ /* Open syslog connection with appropriate banner; @@ -57,8 +90,6 @@ void setup_syslog(const char* bin_name) { openlog(name2, LOG_CONS, facilitynames[fn].c_val); free(name1); /* Don't free name2, as openlog(3) uses it (at least in glibc) */ - - log_message(LOG_INFO, "%s %s started\n", server_type, VERSION); } diff --git a/log.h b/log.h index 4bd85e1..70a76bc 100644 --- a/log.h +++ b/log.h @@ -7,4 +7,13 @@ void log_message(int type, const char* msg, ...); void log_connection(struct connection_desc* desc, const struct connection *cnx); +typedef struct s_msg_info{ + int log_level; + int *verbose; +} msg_info; + +void print_message(msg_info info, const char* str, ...); +extern msg_info msg_config; +extern msg_info msg_config_error; + #endif /* LOG_H */ diff --git a/sslh-conf.c b/sslh-conf.c index 9c52cc6..e16dde9 100644 --- a/sslh-conf.c +++ b/sslh-conf.c @@ -1,5 +1,5 @@ /* Generated by conf2struct (https://www.rutschle.net/tech/conf2struct/README) - * on Tue Aug 24 13:53:04 2021. + * on Sat Sep 18 22:17:39 2021. # conf2struct: generate libconf parsers that read to structs # Copyright (C) 2018-2021 Yves Rutschle @@ -443,6 +443,8 @@ struct compound_cl_arg { struct arg_file* sslhcfg_conffile; + struct arg_int* sslhcfg_verbose_config; + struct arg_int* sslhcfg_verbose_config_error; struct arg_int* sslhcfg_verbose; struct arg_lit* sslhcfg_version; struct arg_lit* sslhcfg_foreground; @@ -783,10 +785,42 @@ static struct config_desc table_sslhcfg_listen[] = { }, { 0 } }; - + static struct config_desc table_sslhcfg[] = { + { + /* name */ "verbose_config", + /* type */ CFG_INT, + /* sub_group*/ NULL, + /* arg_cl */ & sslhcfg_verbose_config, + /* base_addr */ NULL, + /* offset */ offsetof(struct sslhcfg_item, verbose_config), + /* offset_len */ 0, + /* offset_present */ 0, + /* size */ sizeof(int), + /* array_type */ -1, + /* mandatory */ 0, + /* optional */ 0, + /* default_val*/ .default_val.def_int = 0 + }, + + { + /* name */ "verbose_config_error", + /* type */ CFG_INT, + /* sub_group*/ NULL, + /* arg_cl */ & sslhcfg_verbose_config_error, + /* base_addr */ NULL, + /* offset */ offsetof(struct sslhcfg_item, verbose_config_error), + /* offset_len */ 0, + /* offset_present */ 0, + /* size */ sizeof(int), + /* array_type */ -1, + /* mandatory */ 0, + /* optional */ 0, + /* default_val*/ .default_val.def_int = 3 + }, + { /* name */ "verbose", /* type */ CFG_INT, @@ -798,7 +832,7 @@ static struct config_desc table_sslhcfg[] = { /* offset_present */ 0, /* size */ sizeof(int), /* array_type */ -1, - /* mandatory */ 0, + /* mandatory */ 1, /* optional */ 0, /* default_val*/ .default_val.def_int = 0 }, @@ -1123,7 +1157,7 @@ static struct compound_cl_arg compound_cl_args[] = { { /* arg: listen */ .regex = "(.+):(\\w+)", .arg_cl = & sslhcfg_listen, - .base_entry = & table_sslhcfg [13], + .base_entry = & table_sslhcfg [15], .targets = sslhcfg_listen_targets, @@ -1135,7 +1169,7 @@ static struct compound_cl_arg compound_cl_args[] = { { /* arg: ssh */ .regex = "(.+):(\\w+)", .arg_cl = & sslhcfg_ssh, - .base_entry = & table_sslhcfg [14], + .base_entry = & table_sslhcfg [16], .targets = sslhcfg_ssh_targets, @@ -1147,7 +1181,7 @@ static struct compound_cl_arg compound_cl_args[] = { { /* arg: tls */ .regex = "(.+):(\\w+)", .arg_cl = & sslhcfg_tls, - .base_entry = & table_sslhcfg [14], + .base_entry = & table_sslhcfg [16], .targets = sslhcfg_tls_targets, @@ -1159,7 +1193,7 @@ static struct compound_cl_arg compound_cl_args[] = { { /* arg: openvpn */ .regex = "(.+):(\\w+)", .arg_cl = & sslhcfg_openvpn, - .base_entry = & table_sslhcfg [14], + .base_entry = & table_sslhcfg [16], .targets = sslhcfg_openvpn_targets, @@ -1171,7 +1205,7 @@ static struct compound_cl_arg compound_cl_args[] = { { /* arg: tinc */ .regex = "(.+):(\\w+)", .arg_cl = & sslhcfg_tinc, - .base_entry = & table_sslhcfg [14], + .base_entry = & table_sslhcfg [16], .targets = sslhcfg_tinc_targets, @@ -1183,7 +1217,7 @@ static struct compound_cl_arg compound_cl_args[] = { { /* arg: xmpp */ .regex = "(.+):(\\w+)", .arg_cl = & sslhcfg_xmpp, - .base_entry = & table_sslhcfg [14], + .base_entry = & table_sslhcfg [16], .targets = sslhcfg_xmpp_targets, @@ -1195,7 +1229,7 @@ static struct compound_cl_arg compound_cl_args[] = { { /* arg: http */ .regex = "(.+):(\\w+)", .arg_cl = & sslhcfg_http, - .base_entry = & table_sslhcfg [14], + .base_entry = & table_sslhcfg [16], .targets = sslhcfg_http_targets, @@ -1207,7 +1241,7 @@ static struct compound_cl_arg compound_cl_args[] = { { /* arg: adb */ .regex = "(.+):(\\w+)", .arg_cl = & sslhcfg_adb, - .base_entry = & table_sslhcfg [14], + .base_entry = & table_sslhcfg [16], .targets = sslhcfg_adb_targets, @@ -1219,7 +1253,7 @@ static struct compound_cl_arg compound_cl_args[] = { { /* arg: socks5 */ .regex = "(.+):(\\w+)", .arg_cl = & sslhcfg_socks5, - .base_entry = & table_sslhcfg [14], + .base_entry = & table_sslhcfg [16], .targets = sslhcfg_socks5_targets, @@ -1231,7 +1265,7 @@ static struct compound_cl_arg compound_cl_args[] = { { /* arg: syslog */ .regex = "(.+):(\\w+)", .arg_cl = & sslhcfg_syslog, - .base_entry = & table_sslhcfg [14], + .base_entry = & table_sslhcfg [16], .targets = sslhcfg_syslog_targets, @@ -1243,7 +1277,7 @@ static struct compound_cl_arg compound_cl_args[] = { { /* arg: anyprot */ .regex = "(.+):(\\w+)", .arg_cl = & sslhcfg_anyprot, - .base_entry = & table_sslhcfg [14], + .base_entry = & table_sslhcfg [16], .targets = sslhcfg_anyprot_targets, @@ -1908,6 +1942,8 @@ int sslhcfg_cl_parse(int argc, char* argv[], struct sslhcfg_item* cfg) #ifdef LIBCONFIG sslhcfg_conffile = arg_filen("F", "config", "", 0, 1, "Specify configuration file"), #endif + sslhcfg_verbose_config = arg_intn(NULL, "verbose-config", "", 0, 1, ""), + sslhcfg_verbose_config_error = arg_intn(NULL, "verbose-config-error", "", 0, 1, ""), sslhcfg_verbose = arg_intn("v", "verbose", "", 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"), @@ -2076,6 +2112,12 @@ void sslhcfg_fprint( int depth) { int i; + indent(out, depth); + fprintf(out, "verbose_config: %d", sslhcfg->verbose_config); + fprintf(out, "\n"); + indent(out, depth); + fprintf(out, "verbose_config_error: %d", sslhcfg->verbose_config_error); + fprintf(out, "\n"); indent(out, depth); fprintf(out, "verbose: %d", sslhcfg->verbose); fprintf(out, "\n"); diff --git a/sslh-conf.h b/sslh-conf.h index 7e09ccc..1f900e1 100644 --- a/sslh-conf.h +++ b/sslh-conf.h @@ -1,5 +1,5 @@ /* Generated by conf2struct (https://www.rutschle.net/tech/conf2struct/README) - * on Tue Aug 24 13:53:04 2021. + * on Sat Sep 18 22:17:39 2021. # conf2struct: generate libconf parsers that read to structs # Copyright (C) 2018-2021 Yves Rutschle @@ -74,6 +74,8 @@ struct sslhcfg_protocols_item { }; struct sslhcfg_item { + int verbose_config; + int verbose_config_error; int verbose; int version; int foreground; diff --git a/sslh-main.c b/sslh-main.c index 1777c93..bb737f5 100644 --- a/sslh-main.c +++ b/sslh-main.c @@ -36,6 +36,7 @@ #include "common.h" #include "probe.h" +#include "log.h" /* Constants for options that have no one-character shorthand */ #define OPT_ONTIMEOUT 257 @@ -50,7 +51,7 @@ static void printcaps(void) { desc = cap_to_text(caps, &len); - fprintf(stderr, "capabilities: %s\n", desc); + print_message(msg_config, "capabilities: %s\n", desc); cap_free(caps); cap_free(desc); @@ -65,7 +66,7 @@ static void printsettings(void) for (i = 0; i < cfg.protocols_len; i++ ) { p = &cfg.protocols[i]; - fprintf(stderr, + print_message(msg_config, "%s addr: %s. libwrap service: %s log_level: %d family %d %d [%s] [%s] [%s]\n", p->name, sprintaddr(buf, sizeof(buf), p->saddr), @@ -78,7 +79,7 @@ static void printsettings(void) p->transparent ? "transparent" : "" ); } - fprintf(stderr, "timeout: %d\non-timeout: %s\n", cfg.timeout, + print_message(msg_config, "timeout: %d\non-timeout: %s\n", cfg.timeout, timeout_protocol()->name); } @@ -124,13 +125,13 @@ static void config_protocols() for (i = 0; i < cfg.protocols_len; i++) { struct sslhcfg_protocols_item* p = &(cfg.protocols[i]); if (resolve_split_name(&(p->saddr), p->host, p->port)) { - fprintf(stderr, "cannot resolve %s:%s\n", p->host, p->port); + print_message(msg_config_error, "cannot resolve %s:%s\n", p->host, p->port); exit(4); } p->probe = get_probe(p->name); if (!p->probe) { - fprintf(stderr, "%s: probe unknown\n", p->name); + print_message(msg_config_error, "%s: probe unknown\n", p->name); exit(1); } @@ -155,14 +156,14 @@ static void config_protocols() void config_sanity_check(struct sslhcfg_item* cfg) { if (!cfg->protocols_len) { - fprintf(stderr, "At least one target protocol must be specified.\n"); + print_message(msg_config_error, "At least one target protocol must be specified.\n"); exit(2); } /* If compiling with systemd socket support no need to require listen address */ #ifndef SYSTEMD if (!cfg->listen_len && !cfg->inetd) { - fprintf(stderr, "No listening address specified; use at least one -p option\n"); + print_message(msg_config_error, "No listening address specified; use at least one -p option\n"); exit(1); } #endif @@ -184,8 +185,6 @@ int main(int argc, char *argv[], char* envp[]) memset(&cfg, 0, sizeof(cfg)); res = sslhcfg_cl_parse(argc, argv, &cfg); if (res) exit(6); - if (cfg.verbose > 3) - sslhcfg_fprint(stderr, &cfg, 0); if (cfg.version) { printf("%s %s\n", server_type, VERSION); @@ -202,14 +201,13 @@ int main(int argc, char *argv[], char* envp[]) exit(0); } - if (cfg.verbose) - printsettings(); + printsettings(); num_addr_listen = start_listen_sockets(&listen_sockets); #ifdef SYSTEMD if (num_addr_listen < 1) { - fprintf(stderr, "No listening sockets found, restart sockets or specify addresses in config\n"); + print_message(msg_config_error, "No listening sockets found, restart sockets or specify addresses in config\n"); exit(1); } #endif @@ -235,8 +233,9 @@ int main(int argc, char *argv[], char* envp[]) if (cfg.user || cfg.chroot) drop_privileges(cfg.user, cfg.chroot); - if (cfg.verbose) - printcaps(); + printcaps(); + + print_message(msg_config, "%s %s started\n", server_type, VERSION); main_loop(listen_sockets, num_addr_listen); diff --git a/sslhconf.cfg b/sslhconf.cfg index ed5b588..bb4b830 100644 --- a/sslhconf.cfg +++ b/sslhconf.cfg @@ -25,7 +25,10 @@ config: { name : "sslhcfg", type: "list", items: ( - { name: "verbose"; type: "int"; default: 0; short: "v"; }, + { name: "verbose-config"; type: "int"; default: 0; }, + { name: "verbose-config-error"; type: "int"; default: 3; }, + + { name: "verbose"; type: "int"; short: "v" }, # to delete { name: "version"; type: "bool"; default: false; short: "V"; description: "Print version information and exit"; }, diff --git a/test.cfg b/test.cfg index 7dd66ea..08b37df 100644 --- a/test.cfg +++ b/test.cfg @@ -11,6 +11,10 @@ pidfile: "/tmp/sslh_test.pid"; syslog_facility: "auth"; +# Logging configuration +# Value: 1: stdout; 2: syslog; 3: both +#verbose-config: 3; # config: print configuration at startup +#verbose-config-error: 3; #config-error: print configuration errors # List of interfaces on which we should listen # Options: