main/sec-mod: handle sec-mod reload via synchronous communication

This eliminates race-conditions related to signal handling and potential
main/sec-mod desynchronizations related to cert/key pairs.

Signed-off-by: Nikos Mavrogiannopoulos <nmav@gnutls.org>
This commit is contained in:
Nikos Mavrogiannopoulos
2018-04-15 09:13:54 +02:00
parent a40ac19c49
commit 03bccbcaef
6 changed files with 71 additions and 18 deletions

View File

@@ -146,6 +146,10 @@ const char *cmd_request_to_str(unsigned _cmd)
return "sm: ban IP";
case CMD_SECM_BAN_IP_REPLY:
return "sm: ban IP reply";
case CMD_SECM_RELOAD:
return "sm: reload";
case CMD_SECM_RELOAD_REPLY:
return "sm: reload reply";
case CMD_SECM_LIST_COOKIES:
return "sm: list cookies";
case CMD_SECM_LIST_COOKIES_REPLY:
@@ -682,7 +686,7 @@ int recv_socket_msg(void *pool, int fd, uint8_t cmd,
}
}
if (length > 0) {
if (length > 0 && msg) {
data = talloc_size(pool, length);
if (data == NULL) {
ret = ERR_MEM;

View File

@@ -96,6 +96,8 @@ typedef enum {
CMD_SECM_LIST_COOKIES,
CMD_SECM_LIST_COOKIES_REPLY,
CMD_SECM_STATS, /* sent periodically */
CMD_SECM_RELOAD,
CMD_SECM_RELOAD_REPLY,
MAX_SECM_CMD,
} cmd_request_t;

View File

@@ -668,6 +668,31 @@ int session_close(main_server_st * s, struct proc_st *proc)
return 0;
}
int secmod_reload(main_server_st * s)
{
int ret, e;
mslog(s, NULL, LOG_DEBUG, "sending msg %s to sec-mod", cmd_request_to_str(CMD_SECM_RELOAD));
ret = send_msg(s->main_pool, s->sec_mod_fd_sync, CMD_SECM_RELOAD,
NULL, NULL, NULL);
if (ret < 0) {
mslog(s, NULL, LOG_ERR,
"error sending message to sec-mod cmd socket");
return -1;
}
ret = recv_msg(s->main_pool, s->sec_mod_fd_sync, CMD_SECM_RELOAD_REPLY,
NULL, NULL, MAIN_SEC_MOD_TIMEOUT);
if (ret < 0) {
e = errno;
mslog(s, NULL, LOG_ERR, "error receiving reload reply message from sec-mod cmd socket: %s", strerror(e));
return ret;
}
return 0;
}
void secmod_socket_file_name(struct perm_cfg_st *perm_config, char *name, unsigned max_name_size)
{
/* make socket name and full socket name */

View File

@@ -1026,6 +1026,7 @@ static void term_sig_watcher_cb(struct ev_loop *loop, ev_signal *w, int revents)
static void reload_sig_watcher_cb(struct ev_loop *loop, ev_signal *w, int revents)
{
main_server_st *s = ev_userdata(loop);
int ret;
mslog(s, NULL, LOG_INFO, "reloading configuration");
kill(s->sec_mod_pid, SIGHUP);
@@ -1033,7 +1034,12 @@ static void reload_sig_watcher_cb(struct ev_loop *loop, ev_signal *w, int revent
/* Reload on main needs to happen later than sec-mod.
* That's because of a test that the certificate matches the
* used key. */
ms_sleep(1500);
ret = secmod_reload(s);
if (ret < 0) {
mslog(s, NULL, LOG_ERR, "could not reload sec-mod!\n");
ev_feed_signal_event (loop, SIGTERM);
}
reload_cfg_file(s->config_pool, s->vconfig, 0);
}

View File

@@ -346,6 +346,8 @@ int send_socket_msg_to_worker(main_server_st* s, struct proc_st* proc, uint8_t c
return send_socket_msg(proc, proc->fd, cmd, socketfd, msg, get_size, pack);
}
int secmod_reload(main_server_st * s);
void secmod_socket_file_name(struct perm_cfg_st *perm_config, char *name, unsigned max_name_size);
void clear_vhosts(struct list_head *head);

View File

@@ -55,6 +55,8 @@ static int need_maintainance = 0;
static int need_reload = 0;
static int need_exit = 0;
static void reload_server(sec_mod_st *sec);
static int load_keys(sec_mod_st *sec, unsigned force);
static
@@ -496,6 +498,16 @@ int process_packet_from_main(void *pool, int fd, sec_mod_st * sec, cmd_request_t
data.size = buffer_size;
switch (cmd) {
case CMD_SECM_RELOAD:
reload_server(sec);
ret = send_msg(pool, fd, CMD_SECM_RELOAD_REPLY, NULL,
NULL, NULL);
if (ret < 0) {
seclog(sec, LOG_ERR, "could not send reload reply to main!\n");
return ERR_BAD_COMMAND;
}
break;
case CMD_SECM_LIST_COOKIES:
handle_secm_list_cookies_reply(pool, fd, sec);
@@ -561,11 +573,6 @@ static void handle_alarm(int signo)
need_maintainance = 1;
}
static void handle_sighup(int signo)
{
need_reload = 1;
}
static void handle_sigterm(int signo)
{
need_exit = 1;
@@ -608,6 +615,22 @@ static void send_stats_to_main(sec_mod_st *sec)
return;
}
static void reload_server(sec_mod_st *sec)
{
vhost_cfg_st *vhost = NULL;
seclog(sec, LOG_DEBUG, "reloading configuration");
reload_cfg_file(sec, sec->vconfig, 1);
load_keys(sec, 0);
list_for_each(sec->vconfig, vhost, list) {
sec_auth_init(vhost);
}
sup_config_init(sec);
need_reload = 0;
}
static void check_other_work(sec_mod_st *sec)
{
vhost_cfg_st *vhost = NULL;
@@ -631,16 +654,7 @@ static void check_other_work(sec_mod_st *sec)
}
if (need_reload) {
seclog(sec, LOG_DEBUG, "reloading configuration");
reload_cfg_file(sec, sec->vconfig, 1);
load_keys(sec, 0);
list_for_each(sec->vconfig, vhost, list) {
sec_auth_init(vhost);
}
sup_config_init(sec);
need_reload = 0;
reload_server(sec);
}
if (need_maintainance) {
@@ -933,7 +947,7 @@ void sec_mod_server(void *main_pool, void *config_pool, struct list_head *vconfi
/* we no longer need the main pool after this point. */
talloc_free(main_pool);
ocsignal(SIGHUP, handle_sighup);
ocsignal(SIGHUP, SIG_IGN);
ocsignal(SIGINT, handle_sigterm);
ocsignal(SIGTERM, handle_sigterm);
ocsignal(SIGALRM, handle_alarm);