mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-02-10 00:37:00 +08:00
Added reference counting to configuration values.
That is, to allow referencing to these values from proc_st without fearing of them being invalidated on a config reload. We perform a cleanup of these values on the server periodic check.
This commit is contained in:
committed by
Nikos Mavrogiannopoulos
parent
2e68ba1158
commit
9252e22298
139
src/config.c
139
src/config.c
@@ -61,6 +61,8 @@
|
||||
static char pid_file[_POSIX_PATH_MAX] = "";
|
||||
static char cfg_file[_POSIX_PATH_MAX] = DEFAULT_CFG_FILE;
|
||||
|
||||
static void archive_cfg(struct perm_cfg_st* perm_config);
|
||||
|
||||
struct cfg_options {
|
||||
const char* name;
|
||||
unsigned type;
|
||||
@@ -740,6 +742,21 @@ size_t urlfw_size = 0;
|
||||
perm_config->occtl_socket_file = talloc_strdup(perm_config, OCCTL_UNIX_SOCKET);
|
||||
|
||||
PREAD_STRING(perm_config, "chroot-dir", perm_config->chroot_dir);
|
||||
|
||||
list_head_init(&perm_config->attic);
|
||||
}
|
||||
|
||||
perm_config->config = talloc_zero(perm_config, struct cfg_st);
|
||||
if (perm_config->config == NULL)
|
||||
exit(1);
|
||||
|
||||
config = perm_config->config;
|
||||
pool = config;
|
||||
|
||||
config->usage_count = talloc_zero(config, int);
|
||||
if (config->usage_count == NULL) {
|
||||
fprintf(stderr, "memory error\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* When adding allocated data, remember to modify
|
||||
@@ -1145,21 +1162,17 @@ int cmd_parser (void *pool, int argc, char **argv, struct perm_cfg_st** config)
|
||||
if (*config == NULL)
|
||||
exit(1);
|
||||
|
||||
(*config)->config = talloc_zero(*config, struct cfg_st);
|
||||
if ((*config)->config == NULL)
|
||||
exit(1);
|
||||
|
||||
optionProcess( &ocservOptions, argc, argv);
|
||||
|
||||
if (HAVE_OPT(FOREGROUND))
|
||||
(*config)->config->foreground = 1;
|
||||
(*config)->foreground = 1;
|
||||
|
||||
if (HAVE_OPT(PID_FILE)) {
|
||||
strlcpy(pid_file, OPT_ARG(PID_FILE), sizeof(pid_file));
|
||||
}
|
||||
|
||||
if (HAVE_OPT(DEBUG))
|
||||
(*config)->config->debug = OPT_VALUE_DEBUG;
|
||||
(*config)->debug = OPT_VALUE_DEBUG;
|
||||
|
||||
if (HAVE_OPT(CONFIG)) {
|
||||
strlcpy(cfg_file, OPT_ARG(CONFIG), sizeof(cfg_file));
|
||||
@@ -1176,70 +1189,40 @@ int cmd_parser (void *pool, int argc, char **argv, struct perm_cfg_st** config)
|
||||
|
||||
}
|
||||
|
||||
#define DEL(x) {talloc_free(x);x=NULL;}
|
||||
static void archive_cfg(struct perm_cfg_st* perm_config)
|
||||
{
|
||||
attic_entry_st *e;
|
||||
|
||||
/* we don't clear anything as it may be referenced by some
|
||||
* client (proc_st). We move everything to attic and
|
||||
* once nothing is in use we clear that */
|
||||
|
||||
e = talloc(perm_config, attic_entry_st);
|
||||
if (e == NULL) {
|
||||
/* we leak, but better than crashing */
|
||||
return;
|
||||
}
|
||||
|
||||
e->usage_count = perm_config->config->usage_count;
|
||||
|
||||
/* we rely on talloc doing that recursively */
|
||||
talloc_steal(e, perm_config->config);
|
||||
perm_config->config = NULL;
|
||||
|
||||
if (e->usage_count == NULL || *e->usage_count == 0) {
|
||||
talloc_free(e);
|
||||
} else {
|
||||
list_add(&perm_config->attic, &e->list);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void clear_cfg(struct perm_cfg_st* perm_config)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
#ifdef ANYCONNECT_CLIENT_COMPAT
|
||||
DEL(perm_config->config->xml_config_file);
|
||||
DEL(perm_config->config->xml_config_hash);
|
||||
#endif
|
||||
DEL(perm_config->config->cgroup);
|
||||
DEL(perm_config->config->route_add_cmd);
|
||||
DEL(perm_config->config->route_del_cmd);
|
||||
DEL(perm_config->config->per_user_dir);
|
||||
DEL(perm_config->config->per_group_dir);
|
||||
DEL(perm_config->config->default_domain);
|
||||
|
||||
DEL(perm_config->config->ocsp_response);
|
||||
DEL(perm_config->config->banner);
|
||||
DEL(perm_config->config->crl);
|
||||
DEL(perm_config->config->cert_user_oid);
|
||||
DEL(perm_config->config->cert_group_oid);
|
||||
DEL(perm_config->config->priorities);
|
||||
DEL(perm_config->config->connect_script);
|
||||
DEL(perm_config->config->disconnect_script);
|
||||
DEL(perm_config->config->proxy_url);
|
||||
|
||||
#ifdef HAVE_GSSAPI
|
||||
for (i=0;i<perm_config->config->kkdcp_size;i++) {
|
||||
unsigned j;
|
||||
DEL(perm_config->config->kkdcp[i].url);
|
||||
for (j=0;j<perm_config->config->kkdcp[i].realms_size;j++) {
|
||||
DEL(perm_config->config->kkdcp[i].realms[j].realm);
|
||||
}
|
||||
}
|
||||
DEL(perm_config->config->kkdcp);
|
||||
#endif
|
||||
|
||||
DEL(perm_config->config->network.ipv4);
|
||||
DEL(perm_config->config->network.ipv4_netmask);
|
||||
DEL(perm_config->config->network.ipv6);
|
||||
for (i=0;i<perm_config->config->network.routes_size;i++)
|
||||
DEL(perm_config->config->network.routes[i]);
|
||||
DEL(perm_config->config->network.routes);
|
||||
for (i=0;i<perm_config->config->network.dns_size;i++)
|
||||
DEL(perm_config->config->network.dns[i]);
|
||||
DEL(perm_config->config->network.dns);
|
||||
for (i=0;i<perm_config->config->network.nbns_size;i++)
|
||||
DEL(perm_config->config->network.nbns[i]);
|
||||
DEL(perm_config->config->network.nbns);
|
||||
for (i=0;i<perm_config->config->custom_header_size;i++)
|
||||
DEL(perm_config->config->custom_header[i]);
|
||||
DEL(perm_config->config->custom_header);
|
||||
for (i=0;i<perm_config->config->split_dns_size;i++)
|
||||
DEL(perm_config->config->split_dns[i]);
|
||||
DEL(perm_config->config->split_dns);
|
||||
for (i=0;i<perm_config->config->group_list_size;i++)
|
||||
DEL(perm_config->config->group_list[i]);
|
||||
DEL(perm_config->config->group_list);
|
||||
DEL(perm_config->config->default_select_group);
|
||||
#ifdef HAVE_LIBTALLOC
|
||||
/* our included talloc don't include that */
|
||||
talloc_free_children(perm_config->config);
|
||||
#endif
|
||||
memset(perm_config->config, 0, sizeof(*perm_config->config));
|
||||
/* we rely on talloc doing that recursively */
|
||||
talloc_free(perm_config->config);
|
||||
perm_config->config = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1287,9 +1270,12 @@ void print_version(tOptions *opts, tOptDesc *desc)
|
||||
}
|
||||
|
||||
|
||||
void reload_cfg_file(void *pool, struct perm_cfg_st* perm_config)
|
||||
void reload_cfg_file(void *pool, struct perm_cfg_st* perm_config, unsigned archive)
|
||||
{
|
||||
clear_cfg(perm_config);
|
||||
if (archive)
|
||||
archive_cfg(perm_config);
|
||||
else
|
||||
clear_cfg(perm_config);
|
||||
|
||||
parse_cfg_file(pool, cfg_file, perm_config, 1);
|
||||
|
||||
@@ -1355,3 +1341,16 @@ int add_multi_line_val(void *pool, const char *name, char ***s_name, size_t *num
|
||||
(*s_name)[*num] = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void clear_old_configs(struct perm_cfg_st* config)
|
||||
{
|
||||
attic_entry_st *e, *pos;
|
||||
|
||||
/* go through the attic and clear old configurations if unused */
|
||||
list_for_each_safe(&config->attic, e, pos, list) {
|
||||
if (*e->usage_count == 0) {
|
||||
list_del(&e->list);
|
||||
talloc_free(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
18
src/log.c
18
src/log.c
@@ -99,16 +99,16 @@ void __attribute__ ((format(printf, 3, 4)))
|
||||
const char* ip;
|
||||
va_list args;
|
||||
|
||||
if (priority == LOG_DEBUG && ws->config->debug < 3)
|
||||
if (priority == LOG_DEBUG && ws->perm_config->debug < 3)
|
||||
return;
|
||||
|
||||
if (priority == LOG_HTTP_DEBUG) {
|
||||
if (ws->config->debug < DEBUG_HTTP)
|
||||
if (ws->perm_config->debug < DEBUG_HTTP)
|
||||
return;
|
||||
else
|
||||
priority = LOG_INFO;
|
||||
} else if (priority == LOG_TRANSFER_DEBUG) {
|
||||
if (ws->config->debug < DEBUG_TRANSFERRED)
|
||||
if (ws->perm_config->debug < DEBUG_TRANSFERRED)
|
||||
return;
|
||||
else
|
||||
priority = LOG_DEBUG;
|
||||
@@ -142,16 +142,16 @@ void __attribute__ ((format(printf, 4, 5)))
|
||||
const char* ip = NULL;
|
||||
va_list args;
|
||||
|
||||
if (priority == LOG_DEBUG && s->config->debug < 3)
|
||||
if (priority == LOG_DEBUG && s->perm_config->debug < 3)
|
||||
return;
|
||||
|
||||
if (priority == LOG_HTTP_DEBUG) {
|
||||
if (s->config->debug < DEBUG_HTTP)
|
||||
if (s->perm_config->debug < DEBUG_HTTP)
|
||||
return;
|
||||
else
|
||||
priority = LOG_DEBUG;
|
||||
} else if (priority == LOG_TRANSFER_DEBUG) {
|
||||
if (s->config->debug < DEBUG_TRANSFERRED)
|
||||
if (s->perm_config->debug < DEBUG_TRANSFERRED)
|
||||
return;
|
||||
else
|
||||
priority = LOG_DEBUG;
|
||||
@@ -186,7 +186,7 @@ void mslog_hex(const main_server_st * s, const struct proc_st* proc,
|
||||
size_t buf_size;
|
||||
gnutls_datum_t data = {bin, bin_size};
|
||||
|
||||
if (priority == LOG_DEBUG && s->config->debug == 0)
|
||||
if (priority == LOG_DEBUG && s->perm_config->debug == 0)
|
||||
return;
|
||||
|
||||
if (b64) {
|
||||
@@ -211,7 +211,7 @@ void oclog_hex(const worker_st* ws, int priority,
|
||||
size_t buf_size;
|
||||
gnutls_datum_t data = {bin, bin_size};
|
||||
|
||||
if (priority == LOG_DEBUG && ws->config->debug == 0)
|
||||
if (priority == LOG_DEBUG && ws->perm_config->debug == 0)
|
||||
return;
|
||||
|
||||
if (b64) {
|
||||
@@ -236,7 +236,7 @@ void seclog_hex(const struct sec_mod_st* sec, int priority,
|
||||
size_t buf_size;
|
||||
gnutls_datum_t data = {bin, bin_size};
|
||||
|
||||
if (priority == LOG_DEBUG && sec->config->debug == 0)
|
||||
if (priority == LOG_DEBUG && sec->perm_config->debug == 0)
|
||||
return;
|
||||
|
||||
if (b64) {
|
||||
|
||||
@@ -371,7 +371,6 @@ static int append_user_info(method_ctx *ctx,
|
||||
rep->dpd = ctmp->config->dpd;
|
||||
|
||||
rep->keepalive = ctmp->config->keepalive;
|
||||
|
||||
rep->domains = ctx->s->config->split_dns;
|
||||
rep->n_domains = ctx->s->config->split_dns_size;
|
||||
|
||||
@@ -721,7 +720,7 @@ static void ctl_handle_commands(main_server_st * s)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = check_upeer_id("ctl", s->config->debug, cfd, 0, 0, NULL, NULL);
|
||||
ret = check_upeer_id("ctl", s->perm_config->debug, cfd, 0, 0, NULL, NULL);
|
||||
if (ret < 0) {
|
||||
mslog(s, NULL, LOG_ERR, "ctl: unauthorized connection");
|
||||
goto cleanup;
|
||||
|
||||
@@ -211,6 +211,9 @@ void remove_proc(main_server_st * s, struct proc_st *proc, unsigned flags)
|
||||
|
||||
close_tun(s, proc);
|
||||
proc_table_del(s, proc);
|
||||
if (proc->config_usage_count && *proc->config_usage_count > 0) {
|
||||
(*proc->config_usage_count)--;
|
||||
}
|
||||
|
||||
talloc_free(proc);
|
||||
}
|
||||
|
||||
@@ -412,6 +412,10 @@ void apply_default_config(main_server_st *s, proc_st *proc, GroupCfgSt *gc)
|
||||
gc->n_fw_ports = s->config->n_fw_ports;
|
||||
gc->fw_ports = s->config->fw_ports;
|
||||
}
|
||||
|
||||
/* since we keep pointers on s->config, increase its usage count */
|
||||
proc->config_usage_count = s->config->usage_count;
|
||||
(*proc->config_usage_count)++;
|
||||
}
|
||||
|
||||
int session_open(main_server_st * s, struct proc_st *proc, const uint8_t *cookie, unsigned cookie_size)
|
||||
|
||||
14
src/main.c
14
src/main.c
@@ -176,7 +176,7 @@ int _listen_ports(void *pool, struct perm_cfg_st* config,
|
||||
else
|
||||
continue;
|
||||
|
||||
if (config->config->foreground != 0)
|
||||
if (config->foreground != 0)
|
||||
fprintf(stderr, "listening (%s) on %s...\n",
|
||||
type, human_addr(ptr->ai_addr, ptr->ai_addrlen,
|
||||
buf, sizeof(buf)));
|
||||
@@ -249,7 +249,7 @@ int _listen_unix_ports(void *pool, struct perm_cfg_st* config,
|
||||
strlcpy(sa.sun_path, config->unix_conn_file, sizeof(sa.sun_path));
|
||||
remove(sa.sun_path);
|
||||
|
||||
if (config->config->foreground != 0)
|
||||
if (config->foreground != 0)
|
||||
fprintf(stderr, "listening (UNIX) on %s...\n",
|
||||
sa.sun_path);
|
||||
|
||||
@@ -608,7 +608,7 @@ static void drop_privileges(main_server_st* s)
|
||||
}
|
||||
|
||||
#define MAX_WORKER_MEM (16*1024*1024)
|
||||
if (s->config->debug == 0) {
|
||||
if (s->perm_config->debug == 0) {
|
||||
rl.rlim_cur = MAX_WORKER_MEM;
|
||||
rl.rlim_max = MAX_WORKER_MEM;
|
||||
ret = setrlimit(RLIMIT_AS, &rl);
|
||||
@@ -850,7 +850,8 @@ unsigned total = 10;
|
||||
|
||||
if (reload_conf != 0) {
|
||||
mslog(s, NULL, LOG_INFO, "reloading configuration");
|
||||
reload_cfg_file(s->main_pool, s->perm_config);
|
||||
reload_cfg_file(s->main_pool, s->perm_config, 1);
|
||||
s->config = s->perm_config->config;
|
||||
tls_reload_crl(s, s->creds, 1);
|
||||
reload_conf = 0;
|
||||
kill(s->sec_mod_pid, SIGHUP);
|
||||
@@ -897,6 +898,7 @@ unsigned total = 10;
|
||||
tls_reload_crl(s, s->creds, 0);
|
||||
expire_tls_sessions(s);
|
||||
cleanup_banned_entries(s);
|
||||
clear_old_configs(s->perm_config);
|
||||
alarm(MAINTAINANCE_TIME(s));
|
||||
}
|
||||
}
|
||||
@@ -1024,7 +1026,7 @@ int main(int argc, char** argv)
|
||||
|
||||
flags = LOG_PID|LOG_NDELAY;
|
||||
#ifdef LOG_PERROR
|
||||
if (s->config->debug != 0)
|
||||
if (s->perm_config->debug != 0)
|
||||
flags |= LOG_PERROR;
|
||||
#endif
|
||||
openlog("ocserv", flags, LOG_DAEMON);
|
||||
@@ -1034,7 +1036,7 @@ int main(int argc, char** argv)
|
||||
deny_severity = LOG_DAEMON|LOG_WARNING;
|
||||
#endif
|
||||
|
||||
if (s->config->foreground == 0) {
|
||||
if (s->perm_config->foreground == 0) {
|
||||
if (daemon(0, 0) == -1) {
|
||||
e = errno;
|
||||
fprintf(stderr, "daemon failed: %s\n", strerror(e));
|
||||
|
||||
@@ -44,7 +44,8 @@ extern char **saved_argv;
|
||||
|
||||
extern sigset_t sig_default_set;
|
||||
int cmd_parser (void *pool, int argc, char **argv, struct perm_cfg_st** config);
|
||||
void reload_cfg_file(void *pool, struct perm_cfg_st* config);
|
||||
void reload_cfg_file(void *pool, struct perm_cfg_st* config, unsigned archive);
|
||||
void clear_old_configs(struct perm_cfg_st* config);
|
||||
void clear_cfg(struct perm_cfg_st* config);
|
||||
void write_pid_file(void);
|
||||
void remove_pid_file(void);
|
||||
@@ -147,6 +148,7 @@ typedef struct proc_st {
|
||||
|
||||
/* The following we rely on talloc for deallocation */
|
||||
GroupCfgSt *config; /* custom user/group config */
|
||||
int *config_usage_count; /* points to s->config->usage_count */
|
||||
} proc_st;
|
||||
|
||||
struct ip_lease_db_st {
|
||||
|
||||
@@ -435,7 +435,8 @@ static void check_other_work(sec_mod_st *sec)
|
||||
|
||||
if (need_reload) {
|
||||
seclog(sec, LOG_DEBUG, "reloading configuration");
|
||||
reload_cfg_file(sec, sec->perm_config);
|
||||
reload_cfg_file(sec, sec->perm_config, 0);
|
||||
sec->config = sec->perm_config->config;
|
||||
need_reload = 0;
|
||||
}
|
||||
|
||||
@@ -836,7 +837,7 @@ void sec_mod_server(void *main_pool, struct perm_cfg_st *perm_config, const char
|
||||
|
||||
/* do not allow unauthorized processes to issue commands
|
||||
*/
|
||||
ret = check_upeer_id("sec-mod", sec->config->debug, cfd, perm_config->uid, perm_config->gid, &uid, &pid);
|
||||
ret = check_upeer_id("sec-mod", sec->perm_config->debug, cfd, perm_config->uid, perm_config->gid, &uid, &pid);
|
||||
if (ret < 0) {
|
||||
seclog(sec, LOG_INFO, "rejected unauthorized connection");
|
||||
} else {
|
||||
|
||||
@@ -112,7 +112,7 @@ void cleanup_client_entries(sec_mod_st *sec);
|
||||
|
||||
#ifdef __GNUC__
|
||||
# define seclog(sec, prio, fmt, ...) \
|
||||
if (prio != LOG_DEBUG || sec->config->debug >= 3) { \
|
||||
if (prio != LOG_DEBUG || sec->perm_config->debug >= 3) { \
|
||||
syslog(prio, "sec-mod: "fmt, ##__VA_ARGS__); \
|
||||
}
|
||||
#else
|
||||
|
||||
@@ -682,7 +682,7 @@ void tls_load_certs(main_server_st *s, tls_st *creds)
|
||||
int ret;
|
||||
const char* perr;
|
||||
|
||||
if (s->config->debug >= DEBUG_TLS) {
|
||||
if (s->perm_config->debug >= DEBUG_TLS) {
|
||||
gnutls_global_set_log_function(tls_log_func);
|
||||
gnutls_global_set_log_level(9);
|
||||
}
|
||||
|
||||
18
src/vpn.h
18
src/vpn.h
@@ -25,6 +25,7 @@
|
||||
#include <gnutls/gnutls.h>
|
||||
#include <http_parser.h>
|
||||
#include <ccan/htable/htable.h>
|
||||
#include <ccan/list/list.h>
|
||||
#include <syslog.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
@@ -314,8 +315,6 @@ struct cfg_st {
|
||||
unsigned keepalive;
|
||||
unsigned dpd;
|
||||
unsigned mobile_dpd;
|
||||
unsigned foreground;
|
||||
unsigned debug;
|
||||
unsigned max_clients;
|
||||
unsigned max_same_clients;
|
||||
unsigned use_utmp;
|
||||
@@ -372,6 +371,9 @@ struct cfg_st {
|
||||
|
||||
/* the tun network */
|
||||
struct vpn_st network;
|
||||
|
||||
/* holds a usage count of holders of pointers in this struct */
|
||||
int *usage_count;
|
||||
};
|
||||
|
||||
struct perm_cfg_st {
|
||||
@@ -404,6 +406,9 @@ struct perm_cfg_st {
|
||||
char *cert_hash;
|
||||
#endif
|
||||
|
||||
unsigned foreground;
|
||||
unsigned debug;
|
||||
|
||||
char *ca;
|
||||
char *dh_params_file;
|
||||
|
||||
@@ -411,8 +416,17 @@ struct perm_cfg_st {
|
||||
char* unix_conn_file;
|
||||
unsigned int port;
|
||||
unsigned int udp_port;
|
||||
|
||||
/* attic, where old config allocated values are stored */
|
||||
struct list_head attic;
|
||||
};
|
||||
|
||||
typedef struct attic_entry_st {
|
||||
struct list_node list;
|
||||
int *usage_count;
|
||||
} attic_entry_st;
|
||||
|
||||
|
||||
/* generic thing to stop complaints */
|
||||
struct worker_st;
|
||||
struct main_server_st;
|
||||
|
||||
@@ -408,7 +408,7 @@ void vpn_server(struct worker_st *ws)
|
||||
|
||||
/* do not allow this process to be traced. That
|
||||
* prevents worker processes tracing each other. */
|
||||
if (ws->config->debug == 0)
|
||||
if (ws->perm_config->debug == 0)
|
||||
pr_set_undumpable("worker");
|
||||
if (ws->config->isolate != 0) {
|
||||
ret = disable_system_calls(ws);
|
||||
|
||||
Reference in New Issue
Block a user