Skip to content
This repository was archived by the owner on May 24, 2022. It is now read-only.
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
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,9 @@ Detail about the entire set of options can be found by invoking `stud -h`:
-n --workers=NUM Number of worker processes (Default: 1)
-B --backlog=NUM Set listen backlog size (Default: 100)
-k --keepalive=SECS TCP keepalive on client socket (Default: 3600)

--tcp-user-timeout=MSECS Milliseconds to wait for ACK packets. Only available
in Linux since 2.6.37. Disabled = 0 (Default: 0)

SECURITY:

-r --chroot=DIR Sets chroot directory (Default: "")
Expand Down
135 changes: 126 additions & 9 deletions configuration.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
#include <grp.h>
#include <sys/stat.h>
#include <syslog.h>
#ifdef __linux__
#include <sys/utsname.h>
#endif

#include "configuration.h"
#include "version.h"
Expand All @@ -30,11 +33,15 @@
#define CFG_CIPHERS "ciphers"
#define CFG_SSL_ENGINE "ssl-engine"
#define CFG_PREFER_SERVER_CIPHERS "prefer-server-ciphers"
#define CFG_NAMED_CURVE "named-curve"
#define CFG_SESSION_TIMEOUT "session-timeout"
#define CFG_SSL_CACHE_SIZE "openssl-cache-size"
#define CFG_BACKEND "backend"
#define CFG_FRONTEND "frontend"
#define CFG_WORKERS "workers"
#define CFG_BACKLOG "backlog"
#define CFG_KEEPALIVE "keepalive"
#define CFG_TCP_USER_TIMEOUT "tcp-user-timeout"
#define CFG_CHROOT "chroot"
#define CFG_USER "user"
#define CFG_GROUP "group"
Expand Down Expand Up @@ -121,13 +128,17 @@ stud_config * config_new (void) {
r->GID = 0;
r->FRONT_IP = NULL;
r->FRONT_PORT = strdup("8443");
r->BACK_IP = strdup("127.0.0.1");
r->BACK_PORT = strdup("8000");
r->BACKENDS_COUNT = 0;
r->BACKENDS[0].BACK_IP = strdup("127.0.0.1");
r->BACKENDS[0].BACK_PORT = strdup("8000");
r->NCORES = 1;
r->CERT_FILES = NULL;
r->CIPHER_SUITE = NULL;
r->NAMED_CURVE = NULL;
r->ENGINE = NULL;
r->BACKLOG = 100;
r->SESSION_TIMEOUT = -1;
r->SSL_CACHE_SIZE = -1;

#ifdef USE_SHARED_CACHE
r->SHARED_CACHE = 0;
Expand All @@ -145,6 +156,7 @@ stud_config * config_new (void) {
r->SYSLOG = 0;
r->SYSLOG_FACILITY = LOG_DAEMON;
r->TCP_KEEPALIVE_TIME = 3600;
r->TCP_USER_TIMEOUT_MS= 0;
r->DAEMONIZE = 0;
r->PREFER_SERVER_CIPHERS = 0;

Expand All @@ -159,8 +171,10 @@ void config_destroy (stud_config *cfg) {
if (cfg->CHROOT != NULL) free(cfg->CHROOT);
if (cfg->FRONT_IP != NULL) free(cfg->FRONT_IP);
if (cfg->FRONT_PORT != NULL) free(cfg->FRONT_PORT);
if (cfg->BACK_IP != NULL) free(cfg->BACK_IP);
if (cfg->BACK_PORT != NULL) free(cfg->BACK_PORT);
for (int i = 0; i < cfg->BACKENDS_COUNT; i++) {
if (cfg->BACKENDS[i].BACK_IP != NULL) free(cfg->BACKENDS[i].BACK_IP);
if (cfg->BACKENDS[i].BACK_PORT != NULL) free(cfg->BACKENDS[i].BACK_PORT);
}
if (cfg->CERT_FILES != NULL) {
struct cert_files *curr = cfg->CERT_FILES, *next;
while (cfg->CERT_FILES != NULL) {
Expand All @@ -170,6 +184,7 @@ void config_destroy (stud_config *cfg) {
}
}
if (cfg->CIPHER_SUITE != NULL) free(cfg->CIPHER_SUITE);
if (cfg->NAMED_CURVE != NULL) free(cfg->NAMED_CURVE);
if (cfg->ENGINE != NULL) free(cfg->ENGINE);

#ifdef USE_SHARED_CACHE
Expand Down Expand Up @@ -548,19 +563,32 @@ void config_param_validate (char *k, char *v, stud_config *cfg, char *file, int
config_assign_str(&cfg->CIPHER_SUITE, v);
}
}
else if (strcmp(k, CFG_SSL_ENGINE) == 0) {
else if (strcmp(k, CFG_NAMED_CURVE) == 0) {
if (v != NULL && strlen(v) > 0) {
config_assign_str(&cfg->NAMED_CURVE, v);
}
} else if (strcmp(k, CFG_SSL_ENGINE) == 0) {
if (v != NULL && strlen(v) > 0) {
config_assign_str(&cfg->ENGINE, v);
}
}
else if (strcmp(k, CFG_PREFER_SERVER_CIPHERS) == 0) {
r = config_param_val_bool(v, &cfg->PREFER_SERVER_CIPHERS);
}
else if (strcmp(k, CFG_SESSION_TIMEOUT) == 0) {
r = config_param_val_intl(v, &cfg->SESSION_TIMEOUT);
if (r && cfg->SESSION_TIMEOUT < -1) cfg->SESSION_TIMEOUT = -1;
}
else if (strcmp(k, CFG_SSL_CACHE_SIZE) == 0) {
r = config_param_val_int(v, &cfg->SSL_CACHE_SIZE);
if (r && cfg->SSL_CACHE_SIZE < -1) cfg->SSL_CACHE_SIZE = -1;
}
else if (strcmp(k, CFG_FRONTEND) == 0) {
r = config_param_host_port_wildcard(v, &cfg->FRONT_IP, &cfg->FRONT_PORT, 1);
}
else if (strcmp(k, CFG_BACKEND) == 0) {
r = config_param_host_port(v, &cfg->BACK_IP, &cfg->BACK_PORT);
r = config_param_host_port(v, &cfg->BACKENDS[cfg->BACKENDS_COUNT].BACK_IP, &cfg->BACKENDS[cfg->BACKENDS_COUNT].BACK_PORT);
cfg->BACKENDS_COUNT++;
}
else if (strcmp(k, CFG_WORKERS) == 0) {
r = config_param_val_intl_pos(v, &cfg->NCORES);
Expand All @@ -572,6 +600,56 @@ void config_param_validate (char *k, char *v, stud_config *cfg, char *file, int
else if (strcmp(k, CFG_KEEPALIVE) == 0) {
r = config_param_val_int_pos(v, &cfg->TCP_KEEPALIVE_TIME);
}
else if (strcmp(k, CFG_TCP_USER_TIMEOUT) == 0) {
#ifdef __linux__
int can_use_option = 0;
struct utsname info;

/* This option is supported in Linux since 2.6.37 */
if (uname(&info) == 0) {
int major, minor, patch;
if (sscanf(info.release, "%d.%d.%d", &major, &minor, &patch) == 3) {
if (major > 2) {
can_use_option = 1;
}
else if (major == 2) {
if (minor > 6) {
can_use_option = 1;
}
else if (minor == 6) {
if (patch >= 37) {
can_use_option = 1;
}
}
}
}
}

r = config_param_val_int(v, &cfg->TCP_USER_TIMEOUT_MS);

if (cfg->TCP_USER_TIMEOUT_MS < 0) {
config_error_set("The option TCP_USER_TIMEOUT must be positive");
r = 0;
}
else if (r && !can_use_option && cfg->TCP_USER_TIMEOUT_MS != 0) {
/* As this is only a warning, not an error, it won't be shown using config_error_set, so we print it to stderr directly */
fprintf(stderr, "TCP_USER_TIMEOUT option can only be used in Linux since 2.6.37, your version is %s. Option disabled.\n", info.release);
cfg->TCP_USER_TIMEOUT_MS = 0;
}
#else
r = config_param_val_int(v, &cfg->TCP_USER_TIMEOUT_MS);

if (cfg->TCP_USER_TIMEOUT_MS < 0) {
config_error_set("The option TCP_USER_TIMEOUT must be positive");
r = 0;
}
else if (r && cfg->TCP_USER_TIMEOUT_MS != 0) {
/* As this is only a warning, not an error, it won't be shown using config_error_set, so we print it to stderr directly */
fprintf(stderr, "TCP_USER_TIMEOUT option can only be used in Linux since 2.6.37. Option disabled.\n");
cfg->TCP_USER_TIMEOUT_MS = 0;
}
#endif
}
#ifdef USE_SHARED_CACHE
else if (strcmp(k, CFG_SHARED_CACHE) == 0) {
r = config_param_val_int(v, &cfg->SHARED_CACHE);
Expand Down Expand Up @@ -870,11 +948,14 @@ void config_print_usage_fd (char *prog, stud_config *cfg, FILE *out) {
fprintf(out, " -c --ciphers=SUITE Sets allowed ciphers (Default: \"%s\")\n", config_disp_str(cfg->CIPHER_SUITE));
fprintf(out, " -e --ssl-engine=NAME Sets OpenSSL engine (Default: \"%s\")\n", config_disp_str(cfg->ENGINE));
fprintf(out, " -O --prefer-server-ciphers Prefer server list order\n");
fprintf(out, " -N --named-curve=NAME Named curve for ECDH (Default: prime256v1, see openssl ecparams -list_curves)\n");
fprintf(out, " -x --session-timeout=SECONDS Session timeout in seconds\n");
fprintf(out, " -y --openssl-cache-size Sets OpenSSL library cache size (0 to disable it)\n");
fprintf(out, "\n");
fprintf(out, "SOCKET:\n");
fprintf(out, "\n");
fprintf(out, " --client Enable client proxy mode\n");
fprintf(out, " -b --backend=HOST,PORT Backend [connect] (default is \"%s\")\n", config_disp_hostport(cfg->BACK_IP, cfg->BACK_PORT));
fprintf(out, " -b --backend=HOST,PORT Backend [connect] (can be given multiple times) (default is \"%s\")\n", config_disp_hostport(cfg->BACKENDS[0].BACK_IP, cfg->BACKENDS[0].BACK_PORT));
fprintf(out, " -f --frontend=HOST,PORT Frontend [bind] (default is \"%s\")\n", config_disp_hostport(cfg->FRONT_IP, cfg->FRONT_PORT));

#ifdef USE_SHARED_CACHE
Expand All @@ -895,6 +976,8 @@ void config_print_usage_fd (char *prog, stud_config *cfg, FILE *out) {
fprintf(out, " -n --workers=NUM Number of worker processes (Default: %ld)\n", cfg->NCORES);
fprintf(out, " -B --backlog=NUM Set listen backlog size (Default: %d)\n", cfg->BACKLOG);
fprintf(out, " -k --keepalive=SECS TCP keepalive on client socket (Default: %d)\n", cfg->TCP_KEEPALIVE_TIME);
fprintf(out, " --tcp-user-timeout=MSECS Milliseconds to wait for ACK packets. Only available\n");
fprintf(out, " in Linux since 2.6.37. Disabled = 0 (Default: %d)\n", cfg->TCP_USER_TIMEOUT_MS);

#ifdef USE_SHARED_CACHE
fprintf(out, " -C --session-cache=NUM Enable and set SSL session cache to specified number\n");
Expand Down Expand Up @@ -953,7 +1036,12 @@ void config_print_default (FILE *fd, stud_config *cfg) {
fprintf(fd, "#\n");
fprintf(fd, "# type: string\n");
fprintf(fd, "# syntax: [HOST]:PORT.\n");
fprintf(fd, FMT_QSTR, CFG_BACKEND, config_disp_hostport(cfg->BACK_IP, cfg->BACK_PORT));
if (cfg->BACKENDS_COUNT == 0) {
fprintf(fd, FMT_QSTR, CFG_BACKEND, config_disp_hostport(cfg->BACKENDS[0].BACK_IP, cfg->BACKENDS[0].BACK_PORT));
} else {
for (int i = 0; i < cfg->BACKENDS_COUNT; i++)
fprintf(fd, FMT_QSTR, CFG_BACKEND, config_disp_hostport(cfg->BACKENDS[i].BACK_IP, cfg->BACKENDS[i].BACK_PORT));
}
fprintf(fd, "\n");

fprintf(fd, "# SSL x509 certificate file. REQUIRED.\n");
Expand Down Expand Up @@ -1006,6 +1094,15 @@ void config_print_default (FILE *fd, stud_config *cfg) {
fprintf(fd, "# type: integer\n");
fprintf(fd, FMT_ISTR, CFG_KEEPALIVE, cfg->TCP_KEEPALIVE_TIME);
fprintf(fd, "\n");

#ifdef __linux__
fprintf(fd, "# TCP socket TCP_USER_TIMEOUT option in milliseconds\n");
fprintf(fd, "#\n");
fprintf(fd, "# type: integer\n");
fprintf(fd, "# Value 0 means disabled\n");
fprintf(fd, FMT_ISTR, CFG_TCP_USER_TIMEOUT, cfg->TCP_USER_TIMEOUT_MS);
fprintf(fd, "\n");
#endif

#ifdef USE_SHARED_CACHE
fprintf(fd, "# SSL session cache size\n");
Expand Down Expand Up @@ -1143,7 +1240,10 @@ void config_parse_cli(int argc, char **argv, stud_config *cfg) {
{ "client", 0, &client, 1},
{ CFG_CIPHERS, 1, NULL, 'c' },
{ CFG_PREFER_SERVER_CIPHERS, 0, NULL, 'O' },
{ CFG_NAMED_CURVE, 1, NULL, 'N' },
{ CFG_BACKEND, 1, NULL, 'b' },
{ CFG_SESSION_TIMEOUT, required_argument, NULL, 'x'},
{ CFG_SSL_CACHE_SIZE, required_argument, NULL, 'y'},
{ CFG_FRONTEND, 1, NULL, 'f' },
{ CFG_WORKERS, 1, NULL, 'n' },
{ CFG_BACKLOG, 1, NULL, 'B' },
Expand All @@ -1154,6 +1254,7 @@ void config_parse_cli(int argc, char **argv, stud_config *cfg) {
{ CFG_SHARED_CACHE_MCASTIF, 1, NULL, 'M' },
#endif
{ CFG_KEEPALIVE, 1, NULL, 'k' },
{ CFG_TCP_USER_TIMEOUT, 1, NULL, 'T'},
{ CFG_CHROOT, 1, NULL, 'r' },
{ CFG_USER, 1, NULL, 'u' },
{ CFG_GROUP, 1, NULL, 'g' },
Expand All @@ -1175,7 +1276,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:N:e:Ob:f:n:B:C:U:P:M:k:r:u:g:x:y:qstVh",
long_options, &option_index
);

Expand All @@ -1201,12 +1302,21 @@ void config_parse_cli(int argc, char **argv, stud_config *cfg) {
case 'c':
config_param_validate(CFG_CIPHERS, optarg, cfg, NULL, 0);
break;
case 'N':
config_param_validate(CFG_NAMED_CURVE, optarg, cfg, NULL, 0);
break;
case 'e':
config_param_validate(CFG_SSL_ENGINE, optarg, cfg, NULL, 0);
break;
case 'O':
config_param_validate(CFG_PREFER_SERVER_CIPHERS, CFG_BOOL_ON, cfg, NULL, 0);
break;
case 'x':
config_param_validate(CFG_SESSION_TIMEOUT, optarg, cfg, NULL, 0);
break;
case 'y':
config_param_validate(CFG_SSL_CACHE_SIZE, optarg, cfg, NULL, 0);
break;
case 'b':
config_param_validate(CFG_BACKEND, optarg, cfg, NULL, 0);
break;
Expand Down Expand Up @@ -1236,6 +1346,9 @@ void config_parse_cli(int argc, char **argv, stud_config *cfg) {
case 'k':
config_param_validate(CFG_KEEPALIVE, optarg, cfg, NULL, 0);
break;
case 'T':
config_param_validate(CFG_TCP_USER_TIMEOUT, optarg, cfg, NULL, 0);
break;
case 'r':
config_param_validate(CFG_CHROOT, optarg, cfg, NULL, 0);
break;
Expand Down Expand Up @@ -1321,4 +1434,8 @@ void config_parse_cli(int argc, char **argv, stud_config *cfg) {
printf("%s configuration looks ok.\n", basename(prog));
exit(0);
}

// if no backend option given, use default
if (cfg->BACKENDS_COUNT == 0)
cfg->BACKENDS_COUNT = 1;
}
17 changes: 15 additions & 2 deletions configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ typedef struct shcupd_peer_opt {

#endif

#define BACKENDS_MAX 32

typedef enum {
ENC_TLS,
ENC_SSL
Expand All @@ -36,6 +38,13 @@ struct cert_files {
struct cert_files *NEXT;
};

struct __stud_backend {
char *BACK_IP;
char *BACK_PORT;
};

typedef struct __stud_backend stud_backend;

/* configuration structure */
struct __stud_config {
ENC_TYPE ETYPE;
Expand All @@ -48,13 +57,16 @@ struct __stud_config {
gid_t GID;
char *FRONT_IP;
char *FRONT_PORT;
char *BACK_IP;
char *BACK_PORT;
int BACKENDS_COUNT;
stud_backend BACKENDS[BACKENDS_MAX];
long NCORES;
struct cert_files *CERT_FILES;
char *CIPHER_SUITE;
char *NAMED_CURVE;
char *ENGINE;
int BACKLOG;
long SESSION_TIMEOUT;
int SSL_CACHE_SIZE;
#ifdef USE_SHARED_CACHE
int SHARED_CACHE;
char *SHCUPD_IP;
Expand All @@ -67,6 +79,7 @@ struct __stud_config {
int SYSLOG;
int SYSLOG_FACILITY;
int TCP_KEEPALIVE_TIME;
int TCP_USER_TIMEOUT_MS;
int DAEMONIZE;
int PREFER_SERVER_CIPHERS;
};
Expand Down
Loading