1
0
mirror of https://github.com/unrealircd/unrealircd.git synced 2026-07-06 04:33:13 +02:00

Added support for the "Server Name Indication" (SNI) SSL/TLS extension.

See https://www.unrealircd.org/docs/Sni_block
Requested in #4380 by Eman.
This commit is contained in:
Bram Matthys
2017-08-09 12:00:04 +02:00
parent 590e345b8d
commit b2129205f9
4 changed files with 125 additions and 0 deletions
+1
View File
@@ -107,6 +107,7 @@ extern ConfigItem_deny_dcc *Find_deny_dcc(char *name);
extern ConfigItem_oper *Find_oper(char *name);
extern ConfigItem_operclass *Find_operclass(char *name);
extern ConfigItem_listen *Find_listen(char *ipmask, int port, int ipv6);
extern ConfigItem_sni *Find_sni(char *name);
extern ConfigItem_ulines *Find_uline(char *host);
extern ConfigItem_except *Find_except(aClient *, short type);
extern ConfigItem_tld *Find_tld(aClient *cptr);
+10
View File
@@ -97,6 +97,7 @@ typedef struct _configitem_drpass ConfigItem_drpass;
typedef struct _configitem_ulines ConfigItem_ulines;
typedef struct _configitem_tld ConfigItem_tld;
typedef struct _configitem_listen ConfigItem_listen;
typedef struct _configitem_sni ConfigItem_sni;
typedef struct _configitem_allow ConfigItem_allow;
typedef struct _configflag_allow ConfigFlag_allow;
typedef struct _configitem_allow_channel ConfigItem_allow_channel;
@@ -1159,6 +1160,14 @@ struct _configitem_listen {
SSLOptions *ssl_options;
};
struct _configitem_sni {
ConfigItem_sni *prev, *next;
ConfigFlag flag;
char *name;
SSL_CTX *ssl_ctx;
SSLOptions *ssl_options;
};
struct _configitem_vhost {
ConfigItem *prev, *next;
ConfigFlag flag;
@@ -1339,6 +1348,7 @@ struct _configitem_offchans {
char *topic;
};
#define HM_HOST 1
#define HM_IPV4 2
#define HM_IPV6 3
+96
View File
@@ -100,6 +100,7 @@ static int _conf_alias (ConfigFile *conf, ConfigEntry *ce);
static int _conf_help (ConfigFile *conf, ConfigEntry *ce);
static int _conf_offchans (ConfigFile *conf, ConfigEntry *ce);
static int _conf_spamfilter (ConfigFile *conf, ConfigEntry *ce);
static int _conf_sni (ConfigFile *conf, ConfigEntry *ce);
/*
* Validation commands
@@ -131,6 +132,7 @@ static int _test_alias (ConfigFile *conf, ConfigEntry *ce);
static int _test_help (ConfigFile *conf, ConfigEntry *ce);
static int _test_offchans (ConfigFile *conf, ConfigEntry *ce);
static int _test_spamfilter (ConfigFile *conf, ConfigEntry *ce);
static int _test_sni (ConfigFile *conf, ConfigEntry *ce);
/* This MUST be alphabetized */
static ConfigCommand _ConfigCommands[] = {
@@ -154,6 +156,7 @@ static ConfigCommand _ConfigCommands[] = {
{ "oper", _conf_oper, _test_oper },
{ "operclass", _conf_operclass, _test_operclass },
{ "set", _conf_set, _test_set },
{ "sni", _conf_sni, _test_sni },
{ "spamfilter", _conf_spamfilter, _test_spamfilter },
{ "tld", _conf_tld, _test_tld },
{ "ulines", _conf_ulines, _test_ulines },
@@ -288,6 +291,7 @@ ConfigItem_tld *conf_tld = NULL;
ConfigItem_oper *conf_oper = NULL;
ConfigItem_operclass *conf_operclass = NULL;
ConfigItem_listen *conf_listen = NULL;
ConfigItem_sni *conf_sni = NULL;
ConfigItem_allow *conf_allow = NULL;
ConfigItem_except *conf_except = NULL;
ConfigItem_vhost *conf_vhost = NULL;
@@ -1920,6 +1924,7 @@ void config_rehash()
ConfigItem_alias *alias_ptr;
ConfigItem_help *help_ptr;
ConfigItem_offchans *of_ptr;
ConfigItem_sni *sni;
OperStat *os_ptr;
ListStruct *next, *next2;
aTKline *tk, *tk_next;
@@ -2214,6 +2219,17 @@ void config_rehash()
}
conf_offchans = NULL;
/* Free sni { } blocks */
for (sni = conf_sni; sni; sni = (ConfigItem_sni *)next)
{
next = (ListStruct *)sni->next;
SSL_CTX_free(sni->ssl_ctx);
free_ssl_options(sni->ssl_options);
safefree(sni->name);
MyFree(sni);
}
conf_sni = NULL;
for (i = 0; i < EXTCMODETABLESZ; i++)
{
if (iConf.modes_on_join.extparams[i])
@@ -2607,6 +2623,24 @@ ConfigItem_listen *Find_listen(char *ipmask, int port, int ipv6)
return NULL;
}
/** Find a SNI match.
* @param name The hostname to look for (eg: irc.xyz.com).
*/
ConfigItem_sni *Find_sni(char *name)
{
ConfigItem_sni *e;
if (!name)
return NULL;
for (e = conf_sni; e; e = e->next)
{
if (!match(name, e->name))
return e;
}
return NULL;
}
ConfigItem_ulines *Find_uline(char *host) {
ConfigItem_ulines *ulines;
@@ -6208,6 +6242,68 @@ int _test_spamfilter(ConfigFile *conf, ConfigEntry *ce)
return errors;
}
int _test_sni(ConfigFile *conf, ConfigEntry *ce)
{
int errors = 0;
ConfigEntry *cep, *sslconfig = NULL;
if (!ce->ce_vardata)
{
config_error("%s:%i: sni block needs a name, eg: sni irc.xyz.com {",
ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
errors++;
}
for (cep = ce->ce_entries; cep; cep = cep->ce_next)
{
if (!strcmp(cep->ce_varname, "ssl-options"))
{
test_sslblock(conf, cep, &errors);
} else
{
config_error_unknown(cep->ce_fileptr->cf_filename, cep->ce_varlinenum,
"sni", cep->ce_varname);
errors++;
continue;
}
}
return errors;
}
int _conf_sni(ConfigFile *conf, ConfigEntry *ce)
{
ConfigEntry *cep;
ConfigEntry *sslconfig = NULL;
char *name;
ConfigItem_sni *sni = NULL;
name = ce->ce_vardata;
if (!name)
return 0;
for (cep = ce->ce_entries; cep; cep = cep->ce_next)
{
if (!strcmp(cep->ce_varname, "ssl-options"))
{
sslconfig = cep;
}
}
if (!sslconfig)
return 0;
sni = MyMallocEx(sizeof(ConfigItem_listen));
sni->name = strdup(name);
sni->ssl_options = MyMallocEx(sizeof(SSLOptions));
conf_sslblock(conf, sslconfig, sni->ssl_options);
sni->ssl_ctx = init_ctx(sni->ssl_options, 1);
AddListItem(sni, conf_sni);
return 1;
}
int _conf_help(ConfigFile *conf, ConfigEntry *ce)
{
ConfigEntry *cep;
+18
View File
@@ -188,6 +188,19 @@ static int ssl_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
return 1;
}
static int ssl_hostname_callback(SSL *ssl, int *unk, void *arg)
{
char *name = (char *)SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
ConfigItem_sni *sni;
if (name && (sni = Find_sni(name)))
{
SSL_set_SSL_CTX(ssl, sni->ssl_ctx);
}
return SSL_TLSEXT_ERR_OK;
}
static void mylog(char *fmt, ...)
{
va_list vl;
@@ -353,6 +366,11 @@ SSL_CTX *init_ctx(SSLOptions *ssloptions, int server)
SSL_CTX_set_options(ctx, SSL_OP_SINGLE_ECDH_USE|SSL_OP_SINGLE_DH_USE);
}
if (server)
{
SSL_CTX_set_tlsext_servername_callback(ctx, ssl_hostname_callback);
}
return ctx;
fail:
SSL_CTX_free(ctx);