unrealircd- supernets unrealircd source & configuration |
git clone git://git.acid.vegas/unrealircd.git |
Log | Files | Refs | Archive | README | LICENSE |
tls_antidos.c (2811B)
1 /* 2 * TLS Anti DoS module 3 * This protects against TLS renegotiation attacks while still allowing us 4 * to leave renegotiation on with all it's security benefits. 5 * 6 * (C) Copyright 2015- Bram Matthys and the UnrealIRCd team. 7 * 8 * License: GPLv2 or later 9 */ 10 11 #include "unrealircd.h" 12 13 ModuleHeader MOD_HEADER 14 = { 15 "tls_antidos", 16 "5.0", 17 "TLS Renegotiation DoS protection", 18 "UnrealIRCd Team", 19 "unrealircd-6", 20 }; 21 22 #define HANDSHAKE_LIMIT_COUNT 3 23 #define HANDSHAKE_LIMIT_SECS 300 24 25 typedef struct SAD SAD; 26 struct SAD { 27 Client *client; /**< client */ 28 time_t ts; /**< time */ 29 int n; /**< number of times */ 30 }; 31 32 int tls_antidos_index = 0; /* slot# we acquire from OpenSSL. Hmm.. looks awfully similar to our moddata system ;) */ 33 34 /* Forward declaration */ 35 int tls_antidos_handshake(Client *client); 36 37 void tls_antidos_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp); 38 39 MOD_INIT() 40 { 41 HookAdd(modinfo->handle, HOOKTYPE_HANDSHAKE, 0, tls_antidos_handshake); 42 43 MARK_AS_OFFICIAL_MODULE(modinfo); 44 45 ModuleSetOptions(modinfo->handle, MOD_OPT_PERM, 1); 46 /* Note that we cannot be MOD_OPT_PERM_RELOADABLE as we use OpenSSL functions to register 47 * an index and callback function. 48 */ 49 50 tls_antidos_index = SSL_get_ex_new_index(0, "tls_antidos", NULL, NULL, tls_antidos_free); 51 52 return MOD_SUCCESS; 53 } 54 55 MOD_LOAD() 56 { 57 return MOD_SUCCESS; 58 } 59 60 MOD_UNLOAD() 61 { 62 return MOD_SUCCESS; 63 } 64 65 /** Called upon handshake (and other events) */ 66 void ssl_info_callback(const SSL *ssl, int where, int ret) 67 { 68 if (where & SSL_CB_HANDSHAKE_START) 69 { 70 SAD *e = SSL_get_ex_data(ssl, tls_antidos_index); 71 Client *client = e->client; 72 73 if (IsServer(client) || IsDeadSocket(client)) 74 return; /* if it's a server, or already pending to be killed off then we don't care */ 75 76 if (e->ts < TStime() - HANDSHAKE_LIMIT_SECS) 77 { 78 e->ts = TStime(); 79 e->n = 1; 80 } else { 81 e->n++; 82 if (e->n >= HANDSHAKE_LIMIT_COUNT) 83 { 84 unreal_log(ULOG_INFO, "flood", "TLS_HANDSHAKE_FLOOD", client, "TLS Handshake flood detected from $client.details -- killed"); 85 dead_socket(client, "TLS Handshake flood detected"); 86 } 87 } 88 } 89 } 90 91 /** Called when a client has just connected to us. 92 * This function is called quite quickly after accept(), 93 * in any case very likely before any data has been received. 94 */ 95 int tls_antidos_handshake(Client *client) 96 { 97 if (client->local->ssl) 98 { 99 SAD *sad = safe_alloc(sizeof(SAD)); 100 sad->client = client; 101 SSL_set_info_callback(client->local->ssl, ssl_info_callback); 102 SSL_set_ex_data(client->local->ssl, tls_antidos_index, sad); 103 } 104 return 0; 105 } 106 107 /** Called by OpenSSL when the SSL * structure is freed (so we can free up our custom struct too) */ 108 void tls_antidos_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp) 109 { 110 safe_free(ptr); 111 }