Skip to content
This repository was archived by the owner on May 24, 2022. It is now read-only.

Patch 1 #106

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ MANDIR = $(PREFIX)/share/man

CFLAGS = -O2 -g -std=c99 -fno-strict-aliasing -Wall -W -D_GNU_SOURCE -I/usr/local/include
LDFLAGS = -lssl -lcrypto -lev -L/usr/local/lib
OBJS = stud.o ringbuffer.o configuration.o
OBJS = stud.o ringbuffer.o configuration.o log.o

all: realall

Expand Down
170 changes: 128 additions & 42 deletions configuration.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <errno.h>
#include <stdarg.h>
#include <stdlib.h>
#include <libgen.h>
#include <ctype.h>
#include <unistd.h>
#include <getopt.h>
Expand All @@ -19,8 +20,10 @@
#include <sys/stat.h>
#include <syslog.h>

#include "stud.h"
#include "configuration.h"
#include "version.h"
#include "log.h"

#define ADDR_LEN 150
#define PORT_LEN 6
Expand All @@ -42,10 +45,15 @@
#define CFG_SYSLOG "syslog"
#define CFG_SYSLOG_FACILITY "syslog-facility"
#define CFG_PARAM_SYSLOG_FACILITY 11015
#define CFG_LOG_LEVEL "log-level"
#define CFG_PARAM_LOG_LEVEL 11016
#define CFG_PARAM_INSTANCE_NAME 11017
#define CFG_DAEMON "daemon"
#define CFG_WRITE_IP "write-ip"
#define CFG_WRITE_PROXY "write-proxy"
#define CFG_PEM_FILE "pem-file"
#define CFG_INSTANCE_NAME "instance-name"
#define CFG_PID_FILE "pid-file"

#ifdef USE_SHARED_CACHE
#define CFG_SHARED_CACHE "shared-cache"
Expand All @@ -69,6 +77,9 @@
#endif
// END: configuration parameters

#define PID_DIR "/var/run/stud"
#define PID_DIR_NONPRIVILEGED "/tmp"

static char var_buf[CONFIG_BUF_SIZE];
static char val_buf[CONFIG_BUF_SIZE];
static char error_buf[CONFIG_BUF_SIZE];
Expand All @@ -90,14 +101,28 @@ char * config_error_get (void) {
return error_buf;
}

void config_die (char *fmt, ...) {
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
fprintf(stderr, "\n");
char * pid_dir_get () {
if (getuid() == 0) {
return PID_DIR;
} else {
char *td = getenv("TMPDIR");
return (td == NULL || strlen(td) < 1) ?
PID_DIR_NONPRIVILEGED :
td;
}
}

exit(1);
int config_param_val_pid_file (char *str, char *dst) {
int len = (str == NULL) ? 0 : strlen(str);
memset(dst, '\0', PATH_MAX);
if (len < 1) {
char *name = stud_instance_name(NULL);
if (name == NULL || strlen(name) < 1) name = "stud";
snprintf(dst, PATH_MAX, "%s/%s.pid", pid_dir_get(), name);
} else {
strncat(dst, str, PATH_MAX);
}
return 1;
}

stud_config * config_new (void) {
Expand Down Expand Up @@ -138,13 +163,15 @@ stud_config * config_new (void) {
r->SHCUPD_MCASTTTL = NULL;
#endif

r->QUIET = 0;
r->SYSLOG = 0;
r->SYSLOG_FACILITY = LOG_DAEMON;
r->LOG_LEVEL = log_str2level(NULL);
r->TCP_KEEPALIVE_TIME = 3600;
r->DAEMONIZE = 0;
r->PREFER_SERVER_CIPHERS = 0;

config_param_val_pid_file(NULL, r->PID_FILE);

return r;
}

Expand Down Expand Up @@ -528,10 +555,10 @@ void config_param_validate (char *k, char *v, stud_config *cfg, char *file, int
struct stat st;

if (strcmp(k, "tls") == 0) {
//cfg->ENC_TLS = 1;
cfg->ETYPE = ENC_TLS;
}
else if (strcmp(k, "ssl") == 0) {
//cfg->ENC_TLS = 0;
cfg->ETYPE = ENC_SSL;
}
else if (strcmp(k, CFG_CIPHERS) == 0) {
if (v != NULL && strlen(v) > 0) {
Expand Down Expand Up @@ -619,7 +646,7 @@ void config_param_validate (char *k, char *v, stud_config *cfg, char *file, int
}
}
else if (strcmp(k, CFG_QUIET) == 0) {
r = config_param_val_bool(v, &cfg->QUIET);
cfg->LOG_LEVEL = LOG_ERR;
}
else if (strcmp(k, CFG_SYSLOG) == 0) {
r = config_param_val_bool(v, &cfg->SYSLOG);
Expand Down Expand Up @@ -665,6 +692,9 @@ void config_param_validate (char *k, char *v, stud_config *cfg, char *file, int
r = 0;
}
}
else if (strcmp(k, CFG_LOG_LEVEL) == 0) {
cfg->LOG_LEVEL = log_str2level(v);
}
else if (strcmp(k, CFG_DAEMON) == 0) {
r = config_param_val_bool(v, &cfg->DAEMONIZE);
}
Expand All @@ -687,6 +717,12 @@ void config_param_validate (char *k, char *v, stud_config *cfg, char *file, int
config_assign_str(&cfg->CERT_FILE, v);
}
}
else if (strcmp(k, CFG_INSTANCE_NAME) == 0) {
stud_instance_name(v);
}
else if (strcmp(k, CFG_PID_FILE) == 0) {
r = config_param_val_pid_file(v, cfg->PID_FILE);
}
else {
fprintf(
stderr,
Expand All @@ -696,17 +732,19 @@ void config_param_validate (char *k, char *v, stud_config *cfg, char *file, int
}

if (! r) {
if (file != NULL)
config_die("Error in configuration file '%s', line %d: %s\n", file, line, config_error_get());
else
config_die("Invalid parameter '%s': %s", k, config_error_get());
if (file != NULL) {
die("Error in configuration file '%s', line %d: %s\n", file, line, config_error_get());
} else {
die("Invalid parameter '%s': %s", k, config_error_get());
}
}
}

#ifndef NO_CONFIG_FILE
int config_file_parse (char *file, stud_config *cfg) {
if (cfg == NULL)
config_die("Undefined stud options; THIS IS A BUG!\n");
if (cfg == NULL) {
die("Undefined stud options; THIS IS A BUG!\n");
}

char line[CONFIG_BUF_SIZE];
FILE *fd = NULL;
Expand All @@ -717,8 +755,26 @@ int config_file_parse (char *file, stud_config *cfg) {
} else {
fd = fopen(file, "r");
}
if (fd == NULL)
config_die("Unable to open configuration file '%s': %s\n", file, strerror(errno));
if (fd == NULL) {
die("Unable to open configuration file '%s': %s\n", file, strerror(errno));
}

// assign stud instance name
char *bn = strdup(basename(file));
if (bn != NULL) {
char *ptr = bn + strlen(bn);
while (ptr > bn) {
if (*ptr == '.') {
*ptr = '\0';
break;
}
ptr--;
}
str_trim(bn);
stud_instance_name(bn);
config_param_val_pid_file(NULL, cfg->PID_FILE);
free(bn);
}

// read config
int i = 0;
Expand All @@ -737,8 +793,6 @@ int config_file_parse (char *file, stud_config *cfg) {
if (val == NULL) continue;
str_trim(val);

// printf("File '%s', line %d, key: '%s', value: '%s'\n", file, i, key, val);

// validate configuration key => value
config_param_validate(key, val, cfg, file, i);
}
Expand Down Expand Up @@ -894,9 +948,13 @@ void config_print_usage_fd (char *prog, stud_config *cfg, FILE *out) {
fprintf(out, " -q --quiet Be quiet; emit only error messages\n");
fprintf(out, " -s --syslog Send log message to syslog in addition to stderr/stdout\n");
fprintf(out, " --syslog-facility=FACILITY Syslog facility to use (Default: \"%s\")\n", config_disp_log_facility(cfg->SYSLOG_FACILITY));
fprintf(out, " --log-level=NAME Log level (Default: \"%s\")\n", config_disp_str(log_level2str(cfg->LOG_LEVEL)));
fprintf(out, " --instance-name Instance name (Default: \"%s\")\n", config_disp_str(stud_instance_name(NULL)));
fprintf(out, "\n");
fprintf(out, "OTHER OPTIONS:\n");
fprintf(out, " --daemon Fork into background and become a daemon (Default: %s)\n", config_disp_bool(cfg->DAEMONIZE));
fprintf(out, " -p --pid-file=FILE Save daemon's pid to specified file (Default: \"%s\")\n", config_disp_str(cfg->PID_FILE));
fprintf(out, "\n");
fprintf(out, " --write-ip Write 1 octet with the IP family followed by the IP\n");
fprintf(out, " address in 4 (IPv4) or 16 (IPv6) octets little-endian\n");
fprintf(out, " to backend before the actual data\n");
Expand Down Expand Up @@ -1044,12 +1102,6 @@ void config_print_default (FILE *fd, stud_config *cfg) {
fprintf(fd, FMT_QSTR, CFG_GROUP, config_disp_gid(cfg->GID));
fprintf(fd, "\n");

fprintf(fd, "# Quiet execution, report only error messages\n");
fprintf(fd, "#\n");
fprintf(fd, "# type: boolean\n");
fprintf(fd, FMT_STR, CFG_QUIET, config_disp_bool(cfg->QUIET));
fprintf(fd, "\n");

fprintf(fd, "# Use syslog for logging\n");
fprintf(fd, "#\n");
fprintf(fd, "# type: boolean\n");
Expand All @@ -1062,12 +1114,30 @@ void config_print_default (FILE *fd, stud_config *cfg) {
fprintf(fd, FMT_QSTR, CFG_SYSLOG_FACILITY, config_disp_log_facility(cfg->SYSLOG_FACILITY));
fprintf(fd, "\n");

fprintf(fd, "# Log level\n");
fprintf(fd, "# Available levels: fatal, error, warning, notice, info, debug\n");
fprintf(fd, "# type: string\n");
fprintf(fd, FMT_QSTR, CFG_LOG_LEVEL, config_disp_str(log_level2str(cfg->LOG_LEVEL)));
fprintf(fd, "\n");

fprintf(fd, "# Instance name (used for syslog ident)\n");
fprintf(fd, "# type: string\n");
fprintf(fd, FMT_QSTR, CFG_INSTANCE_NAME, config_disp_str(stud_instance_name(NULL)));
fprintf(fd, "\n");

fprintf(fd, "# Run as daemon\n");
fprintf(fd, "#\n");
fprintf(fd, "# type: boolean\n");
fprintf(fd, FMT_STR, CFG_DAEMON, config_disp_bool(cfg->DAEMONIZE));
fprintf(fd, "\n");

fprintf(fd, "# Pid file\n");
fprintf(fd, "# NOTE: Pid file is automatically computed from instance name.\n");
fprintf(fd, "#\n");
fprintf(fd, "# type: string\n");
fprintf(fd, "# %s = \"%s\"\n", CFG_PID_FILE, config_disp_str(cfg->PID_FILE));
fprintf(fd, "\n");

fprintf(fd, "# Report client address by writing IP before sending data\n");
fprintf(fd, "#\n");
fprintf(fd, "# NOTE: This option is mutually exclusive with option %s.\n", CFG_WRITE_PROXY);
Expand Down Expand Up @@ -1127,9 +1197,12 @@ void config_parse_cli(int argc, char **argv, stud_config *cfg) {
{ CFG_QUIET, 0, NULL, 'q' },
{ CFG_SYSLOG, 0, NULL, 's' },
{ CFG_SYSLOG_FACILITY, 1, NULL, CFG_PARAM_SYSLOG_FACILITY },
{ CFG_LOG_LEVEL, 1, NULL, CFG_PARAM_LOG_LEVEL },
{ CFG_INSTANCE_NAME, 1, NULL, CFG_PARAM_INSTANCE_NAME },
{ CFG_DAEMON, 0, &cfg->DAEMONIZE, 1 },
{ CFG_WRITE_IP, 0, &cfg->WRITE_IP_OCTET, 1 },
{ CFG_WRITE_PROXY, 0, &cfg->WRITE_PROXY_LINE, 1 },
{ CFG_PID_FILE, 1, NULL, 'p' },

{ "test", 0, NULL, 't' },
{ "version", 0, NULL, 'V' },
Expand All @@ -1141,7 +1214,7 @@ void config_parse_cli(int argc, char **argv, stud_config *cfg) {
int option_index = 0;
c = getopt_long(
argc, argv,
"c:e:Ob:f:n:B:C:U:P:M:k:r:u:g:qstVh",
"c:e:Ob:f:n:B:C:U:P:M:k:r:u:g:qsp:tVh",
long_options, &option_index
);

Expand All @@ -1153,8 +1226,9 @@ void config_parse_cli(int argc, char **argv, stud_config *cfg) {
break;
#ifndef NO_CONFIG_FILE
case CFG_PARAM_CFGFILE:
if (!config_file_parse(optarg, cfg))
config_die("%s", config_error_get());
if (!config_file_parse(optarg, cfg)) {
die("%s", config_error_get());
}
break;
case CFG_PARAM_DEFCFG:
config_print_default(stdout, cfg);
Expand All @@ -1164,6 +1238,9 @@ void config_parse_cli(int argc, char **argv, stud_config *cfg) {
case CFG_PARAM_SYSLOG_FACILITY:
config_param_validate(CFG_SYSLOG_FACILITY, optarg, cfg, NULL, 0);
break;
case CFG_PARAM_LOG_LEVEL:
config_param_validate(CFG_LOG_LEVEL, optarg, cfg, NULL, 0);
break;
case 'c':
config_param_validate(CFG_CIPHERS, optarg, cfg, NULL, 0);
break;
Expand Down Expand Up @@ -1212,11 +1289,17 @@ void config_parse_cli(int argc, char **argv, stud_config *cfg) {
config_param_validate(CFG_GROUP, optarg, cfg, NULL, 0);
break;
case 'q':
config_param_validate(CFG_QUIET, CFG_BOOL_ON, cfg, NULL, 0);
config_param_validate(CFG_LOG_LEVEL, LSTR_ERR, cfg, NULL, 0);
break;
case CFG_PARAM_INSTANCE_NAME:
config_param_validate(CFG_INSTANCE_NAME, optarg, cfg, NULL, 0);
break;
case 's':
config_param_validate(CFG_SYSLOG, CFG_BOOL_ON, cfg, NULL, 0);
break;
case 'p':
config_param_validate(CFG_PID_FILE, optarg, cfg, NULL, 0);
break;
case 't':
test_only = 1;
break;
Expand All @@ -1230,47 +1313,50 @@ void config_parse_cli(int argc, char **argv, stud_config *cfg) {
break;

default:
config_die("Invalid command line parameters. Run %s --help for instructions.", basename(argv[0]));
die("Invalid command line parameters. Run %s --help for instructions.", basename(argv[0]));
}
}

prog = argv[0];

if (tls && ssl)
config_die("Options --tls and --ssl are mutually exclusive.");
if (tls && ssl) {
die("Options --tls and --ssl are mutually exclusive.");
}
else {
if (ssl)
cfg->ETYPE = ENC_SSL;
else if (tls)
cfg->ETYPE = ENC_TLS;
}

if (cfg->WRITE_IP_OCTET && cfg->WRITE_PROXY_LINE)
config_die("Options --write-ip and --write-proxy are mutually exclusive.");
if (cfg->WRITE_IP_OCTET && cfg->WRITE_PROXY_LINE) {
die("Options --write-ip and --write-proxy are mutually exclusive.");
}

if (cfg->DAEMONIZE) {
cfg->SYSLOG = 1;
cfg->QUIET = 1;
}

#ifdef USE_SHARED_CACHE
if (cfg->SHCUPD_IP != NULL && ! cfg->SHARED_CACHE)
config_die("Shared cache update listener is defined, but shared cache is disabled.");
if (cfg->SHCUPD_IP != NULL && ! cfg->SHARED_CACHE) {
die("Shared cache update listener is defined, but shared cache is disabled.");
}
#endif

// argv leftovers, do we have pem file as an argument?
argc -= optind;
argv += optind;
if (argv != NULL && argv[0] != NULL)
config_param_validate(CFG_PEM_FILE, argv[0], cfg, NULL, 0);
else if (cfg->CERT_FILE == NULL || strlen(cfg->CERT_FILE) < 1)
config_die("No x509 certificate PEM file specified!");
else if (cfg->CERT_FILE == NULL || strlen(cfg->CERT_FILE) < 1) {
fail("No x509 certificate PEM file specified!");
}

// was this only a test?
if (test_only) {
fprintf(stderr, "Trying to initialize SSL context with certificate '%s'\n", cfg->CERT_FILE);
if (! init_openssl())
config_die("Error initializing OpenSSL.");
die("Error initializing OpenSSL.");
printf("%s configuration looks ok.\n", basename(prog));
exit(0);
}
Expand Down
Loading