/* # log: processing of all outgoing messages # # Copyright (C) 2007-2021 Yves Rutschle # # This program is free software; you can redistribute it # and/or modify it under the terms of the GNU General Public # License as published by the Free Software Foundation; either # version 2 of the License, or (at your option) any later # version. # # This program 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 General Public License for more # details. # # The full text for the General Public License is here: # http://www.gnu.org/licenses/gpl.html */ #define SYSLOG_NAMES #define _GNU_SOURCE #include #include #include #include "sslh-conf.h" #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 }; msg_info msg_fd = { LOG_DEBUG, &cfg.verbose_fd }; /* Internal errors: inconsistent states, impossible values, things that should never happen, and are therefore the sign of memory corruption: hence the LOG_CRIT */ msg_info msg_int_error = { LOG_CRIT, &cfg.verbose_system_error }; /* System errors: when the system around us fails us: memory allocation, fork, ... */ msg_info msg_system_error = { LOG_ERR, &cfg.verbose_system_error }; msg_info msg_packets = { LOG_INFO, &cfg.verbose_packets }; /* additional info when attempting outgoing connections */ msg_info msg_connections_try = { LOG_DEBUG, &cfg.verbose_connections_try }; /* Connection information and failures (e.g. forbidden by policy) */ msg_info msg_connections = { LOG_INFO, &cfg.verbose_connections }; /* Connection failures, e.g. target server not present */ msg_info msg_connections_error = { LOG_ERR, &cfg.verbose_connections_error }; /* comment the probing process */ msg_info msg_probe_info = { LOG_INFO, &cfg.verbose_probe_info }; /* probing errors, e.g. inconsistent data in connections */ msg_info msg_probe_error = { LOG_ERR, &cfg.verbose_probe_error }; /* Bitmasks in verbose-* values */ #define MSG_STDOUT 1 #define MSG_SYSLOG 2 #define MSG_FILE 4 static FILE* logfile_fp = NULL; /* Prints a message to stderr and/or syslog if appropriate */ void print_message(msg_info info, const char* str, ...) { va_list ap; if ((*info.verbose & MSG_STDOUT) && ! cfg.inetd) { va_start(ap, str); vfprintf(stderr, str, ap); va_end(ap); } if (*info.verbose & MSG_SYSLOG) { va_start(ap, str); vsyslog(info.log_level, str, ap); va_end(ap); } if (*info.verbose & MSG_FILE && logfile_fp != NULL) { va_start(ap, str); vfprintf(logfile_fp, str, ap); fflush(logfile_fp); va_end(ap); } } static int do_syslog = 1; /* Should we syslog? controled by syslog_facility = "none" */ /* Open syslog connection with appropriate banner; * banner is made up of basename(bin_name)+"[pid]" */ void setup_syslog(const char* bin_name) { char *name1, *name2; int res, fn; if (!strcmp(cfg.syslog_facility, "none")) { do_syslog = 0; return; } name1 = strdup(bin_name); res = asprintf(&name2, "%s[%d]", basename(name1), getpid()); CHECK_RES_DIE(res, "asprintf"); for (fn = 0; facilitynames[fn].c_val != -1; fn++) if (strcmp(facilitynames[fn].c_name, cfg.syslog_facility) == 0) break; if (facilitynames[fn].c_val == -1) { fprintf(stderr, "Unknown facility %s\n", cfg.syslog_facility); exit(1); } openlog(name2, LOG_CONS, facilitynames[fn].c_val); free(name1); /* Don't free name2, as openlog(3) uses it (at least in glibc) */ } void setup_logfile() { if (cfg.logfile == NULL) { return; } logfile_fp = fopen(cfg.logfile, "a"); if (logfile_fp == NULL) { fprintf(stderr, "Could not open logfile %s for writing: %s\n", cfg.logfile, strerror(errno)); exit(1); } } void close_logfile() { if (logfile_fp != NULL) { fclose(logfile_fp); logfile_fp = NULL; } } /* syslogs who connected to where * desc: string description of the connection. if NULL, log_connection will * manage on its own * cnx: connection descriptor * */ void log_connection(struct connection_desc* desc, const struct connection *cnx) { struct connection_desc d; if (cnx->proto->log_level < 1) return; if (!desc) { desc = &d; if (!get_connection_desc(desc, cnx)) { print_message(msg_connections, "%s: lost incoming connection\n", cnx->proto->name); return; } } print_message(msg_connections, "%s:connection from %s to %s forwarded from %s to %s\n", cnx->proto->name, desc->peer, desc->service, desc->local, desc->target); }