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 Keith Buck
parent e386d7f362
commit d4b074a771
6 changed files with 88 additions and 5 deletions

View file

@ -11,6 +11,7 @@ ircd.conf file.
NICKDELAY - Clears delayed nicks
OMOTD - Re-reads Oper MOTD file
REJECTCACHE - Clears the reject cache
SSLD - Restarts the ssld processes
TDLINES - Clears temporary D Lines
THROTTLES - Clears throttled IP addresses
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 resv'd nicks and channels
* r - Shows resource usage by ircd
X S - Shows ssld processes
* t - Shows generic server stats
* U - Shows shared blocks (Old U: lines)
u - Shows server uptime

View file

@ -27,7 +27,14 @@
struct _ssl_ctl;
typedef struct _ssl_ctl ssl_ctl_t;
enum ssld_status {
SSLD_ACTIVE,
SSLD_SHUTDOWN,
SSLD_DEAD,
};
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);
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);
@ -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, const int method);
void ssld_decrement_clicount(ssl_ctl_t *ctl);
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

View file

@ -44,6 +44,7 @@
#include "reject.h"
#include "hash.h"
#include "cache.h"
#include "sslproc.h"
static int mo_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_resolver();
}
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
rehash_motd(struct Client *source_p)
{
@ -278,6 +288,7 @@ static struct hash_commands rehash_commands[] =
{
{"BANS", rehash_bans_loc },
{"DNS", rehash_dns },
{"SSLD", rehash_ssld },
{"MOTD", rehash_motd },
{"OMOTD", rehash_omotd },
{"TKLINES", rehash_tklines },

View file

@ -48,6 +48,7 @@
#include "hash.h"
#include "reject.h"
#include "whowas.h"
#include "sslproc.h"
static int m_stats (struct Client *, struct Client *, int, const char **);
@ -108,6 +109,7 @@ static void stats_operedup(struct Client *);
static void stats_ports(struct Client *);
static void stats_tresv(struct Client *);
static void stats_resv(struct Client *);
static void stats_ssld(struct Client *);
static void stats_usage(struct Client *);
static void stats_tstats(struct Client *);
static void stats_uptime(struct Client *);
@ -161,6 +163,8 @@ static struct StatsStruct stats_cmd_table[] = {
{'Q', stats_resv, 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, },
{'u', stats_uptime, 0, 0, },
@ -869,6 +873,24 @@ stats_resv(struct Client *source_p)
HASH_WALK_END
}
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
stats_usage (struct Client *source_p)
{

View file

@ -64,6 +64,7 @@ struct _ssl_ctl
pid_t pid;
rb_dlink_list readq;
rb_dlink_list writeq;
uint8_t shutdown;
uint8_t dead;
};
@ -146,6 +147,31 @@ static int ssld_spin_count = 0;
static time_t last_spin;
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
ssl_killall(void)
{
@ -157,8 +183,11 @@ ssl_killall(void)
if(ctl->dead)
continue;
ctl->dead = 1;
ssld_count--;
if(!ctl->shutdown)
ssld_count--;
rb_kill(ctl->pid, SIGKILL);
if(!ctl->cli_count)
free_ssl_daemon(ctl);
}
}
@ -169,11 +198,15 @@ ssl_dead(ssl_ctl_t * ctl)
return;
ctl->dead = 1;
ssld_count--;
rb_kill(ctl->pid, SIGKILL); /* make sure the process is really gone */
ilog(L_MAIN, "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);
if(!ctl->shutdown)
{
ssld_count--;
ilog(L_MAIN, "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);
}
}
static void
@ -558,6 +591,8 @@ which_ssld(void)
ctl = ptr->data;
if(ctl->dead)
continue;
if(ctl->shutdown)
continue;
if(lowest == NULL)
{
lowest = ctl;
@ -758,6 +793,11 @@ ssld_decrement_clicount(ssl_ctl_t * ctl)
return;
ctl->cli_count--;
if(ctl->shutdown && !ctl->cli_count)
{
ctl->dead = 1;
rb_kill(ctl->pid, SIGKILL);
}
if(ctl->dead && !ctl->cli_count)
{
free_ssl_daemon(ctl);