ircd: support restarting ssld processes

Add REHASH SSLD (admins only) that starts new sslds and marks the
existing ones as inactive until all their clients disconnect.

Very useful whenever the SSL library has a vulnerability because
new connections can use a new version of the library without
disconnecting existing clients/servers.

Add STATS S (admins only) to list ssld processes, status, and client
count.
This commit is contained in:
Simon Arlott 2016-02-10 22:57:16 +00:00 committed by William Pitcock
parent dea27a087c
commit eb1b303d56
6 changed files with 88 additions and 5 deletions

View file

@ -11,6 +11,7 @@ ircd.conf file.
NICKDELAY - Clears delayed nicks NICKDELAY - Clears delayed nicks
OMOTD - Re-reads Oper MOTD file OMOTD - Re-reads Oper MOTD file
REJECTCACHE - Clears the reject cache REJECTCACHE - Clears the reject cache
SSLD - Restarts the ssld processes
TDLINES - Clears temporary D Lines TDLINES - Clears temporary D Lines
THROTTLES - Clears throttled IP addresses THROTTLES - Clears throttled IP addresses
TKLINES - Clears temporary K Lines TKLINES - Clears temporary K Lines

View file

@ -32,6 +32,7 @@ X f - Shows File Descriptors
* q - Shows temporary and global resv'd nicks and channels * q - Shows temporary and global resv'd nicks and channels
* Q - Shows resv'd nicks and channels * Q - Shows resv'd nicks and channels
* r - Shows resource usage by ircd * r - Shows resource usage by ircd
X S - Shows ssld processes
* t - Shows generic server stats * t - Shows generic server stats
* U - Shows shared blocks (Old U: lines) * U - Shows shared blocks (Old U: lines)
u - Shows server uptime u - Shows server uptime

View file

@ -27,7 +27,14 @@
struct _ssl_ctl; struct _ssl_ctl;
typedef struct _ssl_ctl ssl_ctl_t; typedef struct _ssl_ctl ssl_ctl_t;
enum ssld_status {
SSLD_ACTIVE,
SSLD_SHUTDOWN,
SSLD_DEAD,
};
void init_ssld(void); void init_ssld(void);
void restart_ssld(void);
int start_ssldaemon(int count, const char *ssl_cert, const char *ssl_private_key, const char *ssl_dh_params, const char *ssl_cipher_list); int start_ssldaemon(int count, const char *ssl_cert, const char *ssl_private_key, const char *ssl_dh_params, const char *ssl_cipher_list);
ssl_ctl_t *start_ssld_accept(rb_fde_t *sslF, rb_fde_t *plainF, uint32_t id); ssl_ctl_t *start_ssld_accept(rb_fde_t *sslF, rb_fde_t *plainF, uint32_t id);
ssl_ctl_t *start_ssld_connect(rb_fde_t *sslF, rb_fde_t *plainF, uint32_t id); ssl_ctl_t *start_ssld_connect(rb_fde_t *sslF, rb_fde_t *plainF, uint32_t id);
@ -35,6 +42,7 @@ void start_zlib_session(void *data);
void send_new_ssl_certs(const char *ssl_cert, const char *ssl_private_key, const char *ssl_dh_params, const char *ssl_cipher_list); void send_new_ssl_certs(const char *ssl_cert, const char *ssl_private_key, const char *ssl_dh_params, const char *ssl_cipher_list);
void ssld_decrement_clicount(ssl_ctl_t *ctl); void ssld_decrement_clicount(ssl_ctl_t *ctl);
int get_ssld_count(void); int get_ssld_count(void);
void ssld_foreach_info(void (*func)(void *data, pid_t pid, int cli_count, enum ssld_status status), void *data);
#endif #endif

View file

@ -66,6 +66,7 @@ struct _ssl_ctl
pid_t pid; pid_t pid;
rb_dlink_list readq; rb_dlink_list readq;
rb_dlink_list writeq; rb_dlink_list writeq;
uint8_t shutdown;
uint8_t dead; uint8_t dead;
}; };
@ -150,6 +151,31 @@ static time_t last_spin;
static int ssld_wait = 0; static int ssld_wait = 0;
void
restart_ssld(void)
{
rb_dlink_node *ptr, *next;
ssl_ctl_t *ctl;
RB_DLINK_FOREACH_SAFE(ptr, next, ssl_daemons.head)
{
ctl = ptr->data;
if(ctl->dead)
continue;
if(ctl->shutdown)
continue;
ctl->shutdown = 1;
ssld_count--;
if(!ctl->cli_count)
{
rb_kill(ctl->pid, SIGKILL);
free_ssl_daemon(ctl);
}
}
start_ssldaemon(ServerInfo.ssld_count, ServerInfo.ssl_cert, ServerInfo.ssl_private_key, ServerInfo.ssl_dh_params, ServerInfo.ssl_cipher_list);
}
static void static void
ssl_killall(void) ssl_killall(void)
{ {
@ -161,8 +187,11 @@ ssl_killall(void)
if(ctl->dead) if(ctl->dead)
continue; continue;
ctl->dead = 1; ctl->dead = 1;
if(!ctl->shutdown)
ssld_count--; ssld_count--;
rb_kill(ctl->pid, SIGKILL); rb_kill(ctl->pid, SIGKILL);
if(!ctl->cli_count)
free_ssl_daemon(ctl);
} }
} }
@ -173,11 +202,15 @@ ssl_dead(ssl_ctl_t * ctl)
return; return;
ctl->dead = 1; ctl->dead = 1;
ssld_count--;
rb_kill(ctl->pid, SIGKILL); /* make sure the process is really gone */ rb_kill(ctl->pid, SIGKILL); /* make sure the process is really gone */
if(!ctl->shutdown)
{
ssld_count--;
ilog(L_MAIN, "ssld helper died - attempting to restart"); ilog(L_MAIN, "ssld helper died - attempting to restart");
sendto_realops_snomask(SNO_GENERAL, L_ALL, "ssld helper died - attempting to restart"); sendto_realops_snomask(SNO_GENERAL, L_ALL, "ssld helper died - attempting to restart");
start_ssldaemon(1, ServerInfo.ssl_cert, ServerInfo.ssl_private_key, ServerInfo.ssl_dh_params, ServerInfo.ssl_cipher_list); start_ssldaemon(1, ServerInfo.ssl_cert, ServerInfo.ssl_private_key, ServerInfo.ssl_dh_params, ServerInfo.ssl_cipher_list);
}
} }
static void static void
@ -541,6 +574,8 @@ which_ssld(void)
ctl = ptr->data; ctl = ptr->data;
if(ctl->dead) if(ctl->dead)
continue; continue;
if(ctl->shutdown)
continue;
if(lowest == NULL) if(lowest == NULL)
{ {
lowest = ctl; lowest = ctl;
@ -737,6 +772,11 @@ ssld_decrement_clicount(ssl_ctl_t * ctl)
return; return;
ctl->cli_count--; ctl->cli_count--;
if(ctl->shutdown && !ctl->cli_count)
{
ctl->dead = 1;
rb_kill(ctl->pid, SIGKILL);
}
if(ctl->dead && !ctl->cli_count) if(ctl->dead && !ctl->cli_count)
{ {
free_ssl_daemon(ctl); free_ssl_daemon(ctl);

View file

@ -44,6 +44,7 @@
#include "hash.h" #include "hash.h"
#include "cache.h" #include "cache.h"
#include "irc_radixtree.h" #include "irc_radixtree.h"
#include "sslproc.h"
static int mo_rehash(struct Client *, struct Client *, int, const char **); static int mo_rehash(struct Client *, struct Client *, int, const char **);
static int me_rehash(struct Client *, struct Client *, int, const char **); static int me_rehash(struct Client *, struct Client *, int, const char **);
@ -85,6 +86,15 @@ rehash_dns(struct Client *source_p)
restart_authd(); restart_authd();
} }
static void
rehash_ssld(struct Client *source_p)
{
sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s is restarting ssld",
get_oper_name(source_p));
restart_ssld();
}
static void static void
rehash_motd(struct Client *source_p) rehash_motd(struct Client *source_p)
{ {
@ -276,6 +286,7 @@ static struct hash_commands rehash_commands[] =
{ {
{"BANS", rehash_bans_loc }, {"BANS", rehash_bans_loc },
{"DNS", rehash_dns }, {"DNS", rehash_dns },
{"SSLD", rehash_ssld },
{"MOTD", rehash_motd }, {"MOTD", rehash_motd },
{"OMOTD", rehash_omotd }, {"OMOTD", rehash_omotd },
{"TKLINES", rehash_tklines }, {"TKLINES", rehash_tklines },

View file

@ -49,6 +49,7 @@
#include "reject.h" #include "reject.h"
#include "whowas.h" #include "whowas.h"
#include "irc_radixtree.h" #include "irc_radixtree.h"
#include "sslproc.h"
static int m_stats (struct Client *, struct Client *, int, const char **); static int m_stats (struct Client *, struct Client *, int, const char **);
@ -109,6 +110,7 @@ static void stats_operedup(struct Client *);
static void stats_ports(struct Client *); static void stats_ports(struct Client *);
static void stats_tresv(struct Client *); static void stats_tresv(struct Client *);
static void stats_resv(struct Client *); static void stats_resv(struct Client *);
static void stats_ssld(struct Client *);
static void stats_usage(struct Client *); static void stats_usage(struct Client *);
static void stats_tstats(struct Client *); static void stats_tstats(struct Client *);
static void stats_uptime(struct Client *); static void stats_uptime(struct Client *);
@ -162,6 +164,8 @@ static struct StatsStruct stats_cmd_table[] = {
{'Q', stats_resv, 1, 0, }, {'Q', stats_resv, 1, 0, },
{'r', stats_usage, 1, 0, }, {'r', stats_usage, 1, 0, },
{'R', stats_usage, 1, 0, }, {'R', stats_usage, 1, 0, },
{'s', stats_ssld, 1, 1, },
{'S', stats_ssld, 1, 1, },
{'t', stats_tstats, 1, 0, }, {'t', stats_tstats, 1, 0, },
{'T', stats_tstats, 1, 0, }, {'T', stats_tstats, 1, 0, },
{'u', stats_uptime, 0, 0, }, {'u', stats_uptime, 0, 0, },
@ -884,6 +888,24 @@ stats_resv(struct Client *source_p)
} }
} }
static void
stats_ssld_foreach(void *data, pid_t pid, int cli_count, enum ssld_status status)
{
struct Client *source_p = data;
sendto_one_numeric(source_p, RPL_STATSDEBUG,
"S :%u %c %u",
pid,
status == SSLD_DEAD ? 'D' : (status == SSLD_SHUTDOWN ? 'S' : 'A'),
cli_count);
}
static void
stats_ssld(struct Client *source_p)
{
ssld_foreach_info(stats_ssld_foreach, source_p);
}
static void static void
stats_usage (struct Client *source_p) stats_usage (struct Client *source_p)
{ {