mirror of
https://github.com/unrealircd/unrealircd.git
synced 2026-07-10 08:23:13 +02:00
Add protection against SSL Renegotiation attacks (#4046). Reported by seraph.
Also expose dead_link() to modules, IOTW: make it non-static.
This commit is contained in:
@@ -750,3 +750,4 @@ extern void send_moddata_channel(aClient *srv, aChannel *chptr);
|
||||
extern void send_moddata_members(aClient *srv);
|
||||
extern int ssl_used_in_config_but_unavail(void);
|
||||
extern void config_report_ssl_error(void);
|
||||
extern int dead_link(aClient *to, char *notice);
|
||||
|
||||
@@ -107,6 +107,7 @@ loadmodule "modules/m_nopost";
|
||||
loadmodule "modules/m_cap";
|
||||
loadmodule "modules/m_sasl";
|
||||
loadmodule "modules/m_md";
|
||||
loadmodule "modules/ssl_antidos";
|
||||
loadmodule "modules/certfp";
|
||||
loadmodule "modules/cap_invitenotify";
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ R_MODULES= \
|
||||
m_mode.so m_watch.so m_part.so m_join.so m_motd.so m_opermotd.so \
|
||||
m_botmotd.so m_lusers.so m_names.so m_svsnolag.so m_addmotd.so \
|
||||
m_svslusers.so m_starttls.so m_nopost.so m_cap.so \
|
||||
m_sasl.so cap_invitenotify.so m_md.so certfp.so
|
||||
m_sasl.so cap_invitenotify.so m_md.so certfp.so ssl_antidos.so
|
||||
|
||||
MODULES=cloak.so $(R_MODULES)
|
||||
MODULEFLAGS=@MODULEFLAGS@
|
||||
@@ -496,6 +496,10 @@ certfp.so: certfp.c $(INCLUDES)
|
||||
$(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
|
||||
-o certfp.so certfp.c
|
||||
|
||||
ssl_antidos.so: ssl_antidos.c $(INCLUDES)
|
||||
$(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \
|
||||
-o ssl_antidos.so ssl_antidos.c
|
||||
|
||||
#############################################################################
|
||||
# capabilities
|
||||
#############################################################################
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* SSL Anti DoS module
|
||||
* This protects against SSL renegotiation attacks while still allowing us
|
||||
* to leave renegotiation on with all it's security benefits.
|
||||
*
|
||||
* (C) Copyright 2015 The UnrealIRCd team (Syzop and others)
|
||||
*
|
||||
* License: GPLv2
|
||||
*/
|
||||
|
||||
#include "unrealircd.h"
|
||||
|
||||
ModuleHeader MOD_HEADER(ssl_antidos)
|
||||
= {
|
||||
"ssl_antidos",
|
||||
"$Id$",
|
||||
"SSL Renegotiation DoS protection",
|
||||
"3.2-b8-1",
|
||||
NULL
|
||||
};
|
||||
|
||||
#define HANDSHAKE_LIMIT_COUNT 3
|
||||
#define HANDSHAKE_LIMIT_SECS 300
|
||||
|
||||
typedef struct _sad SAD;
|
||||
struct _sad {
|
||||
aClient *acptr; /**< client */
|
||||
time_t ts; /**< time */
|
||||
int n; /**< number of times */
|
||||
};
|
||||
|
||||
int ssl_antidos_index = 0; /* slot# we acquire from OpenSSL. Hmm.. looks awfully similar to our moddata system ;) */
|
||||
|
||||
/* Forward declaration */
|
||||
int ssl_antidos_handshake(aClient *acptr);
|
||||
|
||||
void ssl_antidos_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp);
|
||||
|
||||
DLLFUNC int MOD_INIT(ssl_antidos)(ModuleInfo *modinfo)
|
||||
{
|
||||
HookAddEx(modinfo->handle, HOOKTYPE_HANDSHAKE, ssl_antidos_handshake);
|
||||
|
||||
ModuleSetOptions(modinfo->handle, MOD_OPT_PERM, 1);
|
||||
|
||||
ssl_antidos_index = SSL_get_ex_new_index(0, "ssl_antidos", NULL, NULL, ssl_antidos_free);
|
||||
|
||||
return MOD_SUCCESS;
|
||||
}
|
||||
|
||||
DLLFUNC int MOD_LOAD(ssl_antidos)(int module_load)
|
||||
{
|
||||
return MOD_SUCCESS;
|
||||
}
|
||||
|
||||
DLLFUNC int MOD_UNLOAD(ssl_antidos)(int module_unload)
|
||||
{
|
||||
return MOD_SUCCESS;
|
||||
}
|
||||
|
||||
/** Called upon handshake (and other events) */
|
||||
void ssl_info_callback(const SSL *ssl, int where, int ret)
|
||||
{
|
||||
if (where & SSL_CB_HANDSHAKE_START)
|
||||
{
|
||||
SAD *e = SSL_get_ex_data(ssl, ssl_antidos_index);
|
||||
aClient *acptr = e->acptr;
|
||||
|
||||
if (IsServer(acptr) || IsDead(acptr))
|
||||
return; /* if it's a server, or already pending to be killed off then we don't care */
|
||||
|
||||
if (e->ts < TStime() - HANDSHAKE_LIMIT_SECS)
|
||||
{
|
||||
e->ts = TStime();
|
||||
e->n = 1;
|
||||
} else {
|
||||
e->n++;
|
||||
if (e->n >= HANDSHAKE_LIMIT_COUNT)
|
||||
{
|
||||
ircd_log(LOG_ERROR, "SSL Handshake flood detected from %s -- killed", get_client_name(acptr, TRUE));
|
||||
sendto_realops("SSL Handshake flood detected from %s -- killed", get_client_name(acptr, TRUE));
|
||||
dead_link(acptr, "SSL Handshake flood detected");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Called when a client has just connected to us.
|
||||
* This function is called quite quickly after accept(),
|
||||
* in any case very likely before any data has been received.
|
||||
*/
|
||||
int ssl_antidos_handshake(aClient *acptr)
|
||||
{
|
||||
if (acptr->ssl)
|
||||
{
|
||||
SAD *sad = MyMallocEx(sizeof(SAD));
|
||||
sad->acptr = acptr;
|
||||
SSL_set_info_callback(acptr->ssl, ssl_info_callback);
|
||||
SSL_set_ex_data(acptr->ssl, ssl_antidos_index, sad);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Called by OpenSSL when the SSL structure is freed (so we can free up our custom struct too) */
|
||||
void ssl_antidos_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
|
||||
{
|
||||
MyFree(ptr);
|
||||
}
|
||||
+1
-1
@@ -69,7 +69,7 @@ MODVAR int sendanyways = 0;
|
||||
** notice will be the quit message. notice will also be
|
||||
** sent to failops in case 'to' is a server.
|
||||
*/
|
||||
static int dead_link(aClient *to, char *notice)
|
||||
int dead_link(aClient *to, char *notice)
|
||||
{
|
||||
|
||||
to->flags |= FLAGS_DEADSOCKET;
|
||||
|
||||
Reference in New Issue
Block a user