1
0
mirror of https://github.com/unrealircd/unrealircd.git synced 2026-07-09 08:23:12 +02:00

Move all vhost { } block handling to vhost module.

* Convert to use module-based config handling
* Split part of VHOST command into do_vhost() for later
* Use AppendListItem instead of AddListItem so they are in config-order.
  This is not really important atm but will matter later if we go auto.
* No other code changes at this point
This commit is contained in:
Bram Matthys
2024-09-20 14:43:57 +02:00
parent 51c055d4f0
commit fe751fdc9d
5 changed files with 315 additions and 271 deletions
+2 -2
View File
@@ -26,8 +26,8 @@ in progress and may not always be a stable version.
* When retrieving cold or hot patches we now do proper GPG/PGP checks.
Just like we do on `./unrealircd upgrade`
* Update shipped libraries: c-ares to 1.33.1
* Move around 750 lines of code from core to modules (regarding
throttling, maxperip, exit_client).
* Move +/- 1000 lines of code from core to modules (regarding
throttling, maxperip, vhost, exit_client).
### Fixes:
* In some circumstances users could hang during the handshake when
-2
View File
@@ -100,7 +100,6 @@ extern MODVAR ConfigItem_tld *conf_tld;
extern MODVAR ConfigItem_oper *conf_oper;
extern MODVAR ConfigItem_listen *conf_listen;
extern MODVAR ConfigItem_allow *conf_allow;
extern MODVAR ConfigItem_vhost *conf_vhost;
extern MODVAR ConfigItem_link *conf_link;
extern MODVAR ConfigItem_sni *conf_sni;
extern MODVAR ConfigItem_ban *conf_ban;
@@ -150,7 +149,6 @@ extern ConfigItem_tld *find_tld(Client *cptr);
extern ConfigItem_link *find_link(const char *servername);
extern ConfigItem_ban *find_ban(Client *, const char *host, short type);
extern ConfigItem_ban *find_banEx(Client *,const char *host, short type, short type2);
extern ConfigItem_vhost *find_vhost(const char *name);
extern ConfigItem_deny_channel *find_channel_allowed(Client *cptr, const char *name);
extern ConfigItem_alias *find_alias(const char *name);
extern ConfigItem_help *find_Help(const char *command);
-221
View File
@@ -47,7 +47,6 @@ static int _conf_tld (ConfigFile *conf, ConfigEntry *ce);
static int _conf_listen (ConfigFile *conf, ConfigEntry *ce);
static int _conf_allow (ConfigFile *conf, ConfigEntry *ce);
static int _conf_except (ConfigFile *conf, ConfigEntry *ce);
static int _conf_vhost (ConfigFile *conf, ConfigEntry *ce);
static int _conf_link (ConfigFile *conf, ConfigEntry *ce);
static int _conf_ban (ConfigFile *conf, ConfigEntry *ce);
static int _conf_set (ConfigFile *conf, ConfigEntry *ce);
@@ -82,7 +81,6 @@ static int _test_tld (ConfigFile *conf, ConfigEntry *ce);
static int _test_listen (ConfigFile *conf, ConfigEntry *ce);
static int _test_allow (ConfigFile *conf, ConfigEntry *ce);
static int _test_except (ConfigFile *conf, ConfigEntry *ce);
static int _test_vhost (ConfigFile *conf, ConfigEntry *ce);
static int _test_link (ConfigFile *conf, ConfigEntry *ce);
static int _test_ban (ConfigFile *conf, ConfigEntry *ce);
static int _test_require (ConfigFile *conf, ConfigEntry *ce);
@@ -129,7 +127,6 @@ static ConfigCommand _ConfigCommands[] = {
{ "sni", _conf_sni, _test_sni },
{ "tld", _conf_tld, _test_tld },
{ "ulines", _conf_ulines, _test_ulines },
{ "vhost", _conf_vhost, _test_vhost },
{ "webirc", _conf_proxy, _test_proxy },
};
@@ -227,7 +224,6 @@ ConfigItem_operclass *conf_operclass = NULL;
ConfigItem_listen *conf_listen = NULL;
ConfigItem_sni *conf_sni = NULL;
ConfigItem_allow *conf_allow = NULL;
ConfigItem_vhost *conf_vhost = NULL;
ConfigItem_link *conf_link = NULL;
ConfigItem_ban *conf_ban = NULL;
ConfigItem_deny_channel *conf_deny_channel = NULL;
@@ -2454,7 +2450,6 @@ void config_rehash()
ConfigItem_link *link_ptr;
ConfigItem_listen *listen_ptr;
ConfigItem_tld *tld_ptr;
ConfigItem_vhost *vhost_ptr;
ConfigItem_deny_channel *deny_channel_ptr;
ConfigItem_allow_channel *allow_channel_ptr;
ConfigItem_admin *admin_ptr;
@@ -2584,27 +2579,6 @@ void config_rehash()
DelListItem(tld_ptr, conf_tld);
safe_free(tld_ptr);
}
for (vhost_ptr = conf_vhost; vhost_ptr; vhost_ptr = (ConfigItem_vhost *) next)
{
SWhois *s, *s_next;
next = (ListStruct *)vhost_ptr->next;
safe_free(vhost_ptr->login);
Auth_FreeAuthConfig(vhost_ptr->auth);
safe_free(vhost_ptr->virthost);
safe_free(vhost_ptr->virtuser);
free_security_group(vhost_ptr->match);
for (s = vhost_ptr->swhois; s; s = s_next)
{
s_next = s->next;
safe_free(s->line);
safe_free(s->setby);
safe_free(s);
}
DelListItem(vhost_ptr, conf_vhost);
safe_free(vhost_ptr);
}
remove_config_tkls(TKL_FLAG_CONFIG);
@@ -3326,20 +3300,6 @@ ConfigItem_ban *find_banEx(Client *client, const char *host, short type, short
return NULL;
}
ConfigItem_vhost *find_vhost(const char *name)
{
ConfigItem_vhost *vhost;
for (vhost = conf_vhost; vhost; vhost = vhost->next)
{
if (!strcmp(name, vhost->login))
return vhost;
}
return NULL;
}
/** returns NULL if allowed and struct if denied */
ConfigItem_deny_channel *find_channel_allowed(Client *client, const char *name)
{
@@ -6401,187 +6361,6 @@ int _test_except(ConfigFile *conf, ConfigEntry *ce)
return errors;
}
/*
* vhost {} block parser
*/
int _conf_vhost(ConfigFile *conf, ConfigEntry *ce)
{
ConfigItem_vhost *vhost;
ConfigEntry *cep, *cepp;
vhost = safe_alloc(sizeof(ConfigItem_vhost));
vhost->match = safe_alloc(sizeof(SecurityGroup));
for (cep = ce->items; cep; cep = cep->next)
{
if (!strcmp(cep->name, "vhost"))
{
char *user, *host;
user = strtok(cep->value, "@");
host = strtok(NULL, "");
if (!host)
safe_strdup(vhost->virthost, user);
else
{
safe_strdup(vhost->virtuser, user);
safe_strdup(vhost->virthost, host);
}
}
else if (!strcmp(cep->name, "login"))
safe_strdup(vhost->login, cep->value);
else if (!strcmp(cep->name, "password"))
vhost->auth = AuthBlockToAuthConfig(cep);
else if (!strcmp(cep->name, "match") || !strcmp(cep->name, "mask"))
{
conf_match_block(conf, cep, &vhost->match);
}
else if (!strcmp(cep->name, "swhois"))
{
SWhois *s;
if (cep->items)
{
for (cepp = cep->items; cepp; cepp = cepp->next)
{
s = safe_alloc(sizeof(SWhois));
safe_strdup(s->line, cepp->name);
safe_strdup(s->setby, "vhost");
AddListItem(s, vhost->swhois);
}
} else
if (cep->value)
{
s = safe_alloc(sizeof(SWhois));
safe_strdup(s->line, cep->value);
safe_strdup(s->setby, "vhost");
AddListItem(s, vhost->swhois);
}
}
}
AddListItem(vhost, conf_vhost);
return 1;
}
int _test_vhost(ConfigFile *conf, ConfigEntry *ce)
{
int errors = 0;
ConfigEntry *cep;
char has_vhost = 0, has_login = 0, has_password = 0, has_mask = 0, has_match = 0;
for (cep = ce->items; cep; cep = cep->next)
{
if (!strcmp(cep->name, "vhost"))
{
char *at, *tmp, *host;
if (has_vhost)
{
config_warn_duplicate(cep->file->filename,
cep->line_number, "vhost::vhost");
continue;
}
has_vhost = 1;
if (!cep->value)
{
config_error_empty(cep->file->filename,
cep->line_number, "vhost", "vhost");
errors++;
continue;
}
if (!valid_vhost(cep->value))
{
config_error("%s:%i: oper::vhost contains illegal characters or is too long: '%s'",
cep->file->filename, cep->line_number, cep->value);
errors++;
}
}
else if (!strcmp(cep->name, "login"))
{
if (has_login)
{
config_warn_duplicate(cep->file->filename,
cep->line_number, "vhost::login");
}
has_login = 1;
if (!cep->value)
{
config_error_empty(cep->file->filename,
cep->line_number, "vhost", "login");
errors++;
continue;
}
}
else if (!strcmp(cep->name, "password"))
{
if (has_password)
{
config_warn_duplicate(cep->file->filename,
cep->line_number, "vhost::password");
}
has_password = 1;
if (!cep->value)
{
config_error_empty(cep->file->filename,
cep->line_number, "vhost", "password");
errors++;
continue;
}
if (Auth_CheckError(cep, 0) < 0)
errors++;
}
else if (!strcmp(cep->name, "mask"))
{
has_mask = 1;
test_match_block(conf, cep, &errors);
}
else if (!strcmp(cep->name, "match"))
{
has_match = 1;
test_match_block(conf, cep, &errors);
}
else if (!strcmp(cep->name, "swhois"))
{
/* multiple is ok */
}
else
{
config_error_unknown(cep->file->filename, cep->line_number,
"vhost", cep->name);
errors++;
}
}
if (!has_vhost)
{
config_error_missing(ce->file->filename, ce->line_number,
"vhost::vhost");
errors++;
}
if (!has_login)
{
config_error_missing(ce->file->filename, ce->line_number,
"vhost::login");
errors++;
}
if (!has_password)
{
config_error_missing(ce->file->filename, ce->line_number,
"vhost::password");
errors++;
}
if (!has_mask && !has_match)
{
config_error_missing(ce->file->filename, ce->line_number,
"vhost::match");
errors++;
}
if (has_mask && has_match)
{
config_error("%s:%d: You cannot have both ::mask and ::match. "
"You should only use %s::match.",
ce->file->filename, ce->line_number, ce->name);
errors++;
}
return errors;
}
int _test_sni(ConfigFile *conf, ConfigEntry *ce)
{
int errors = 0;
-21
View File
@@ -65,7 +65,6 @@ int stats_port(Client *, const char *);
int stats_bannick(Client *, const char *);
int stats_traffic(Client *, const char *);
int stats_uline(Client *, const char *);
int stats_vhost(Client *, const char *);
int stats_kline(Client *, const char *);
int stats_banrealname(Client *, const char *);
int stats_sqline(Client *, const char *);
@@ -112,7 +111,6 @@ struct statstab StatsTable[] = {
{ 'S', "set", stats_set, 0 },
{ 'T', "traffic", stats_traffic, 0 },
{ 'U', "uline", stats_uline, 0 },
{ 'V', "vhost", stats_vhost, 0 },
{ 'W', "fdtable", stats_fdtable, 0 },
{ 'X', "notlink", stats_notlink, 0 },
{ 'Y', "class", stats_class, 0 },
@@ -648,25 +646,6 @@ int stats_uline(Client *client, const char *para)
sendnumeric(client, RPL_STATSULINE, ulines->servername);
return 0;
}
int stats_vhost(Client *client, const char *para)
{
ConfigItem_vhost *vhosts;
NameValuePrioList *m;
for (vhosts = conf_vhost; vhosts; vhosts = vhosts->next)
{
for (m = vhosts->match->printable_list; m; m = m->next)
{
sendtxtnumeric(client, "vhost %s%s%s %s %s",
vhosts->virtuser ? vhosts->virtuser : "",
vhosts->virtuser ? "@" : "",
vhosts->virthost,
vhosts->login,
namevalue_nospaces(m));
}
}
return 0;
}
int stats_kline(Client *client, const char *para)
{
+313 -25
View File
@@ -1,6 +1,6 @@
/*
* Unreal Internet Relay Chat Daemon, src/modules/vhost.c
* (C) 2000-2001 Carsten V. Munk and the UnrealIRCd Team
* (C) 2000-2024 Carsten V. Munk, Bram Matthys and the UnrealIRCd Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,11 +19,10 @@
#include "unrealircd.h"
CMD_FUNC(cmd_vhost);
/* Place includes here */
/* Defines */
#define MSG_VHOST "VHOST"
/* Structs */
ModuleHeader MOD_HEADER
= {
"vhost", /* Name of module */
@@ -33,25 +32,301 @@ ModuleHeader MOD_HEADER
"unrealircd-6",
};
/* This is called on module init, before Server Ready */
MOD_INIT()
/* Variables */
ConfigItem_vhost *conf_vhost = NULL;
/* Forward declarations */
void free_vhost_config(void);
int vhost_config_test(ConfigFile *conf, ConfigEntry *ce, int type, int *errs);
int vhost_config_run(ConfigFile *conf, ConfigEntry *ce, int type);
static int stats_vhost(Client *client, const char *flag);
ConfigItem_vhost *find_vhost(const char *name);
void do_vhost(Client *client, ConfigItem_vhost *vhost);
CMD_FUNC(cmd_vhost);
MOD_TEST()
{
CommandAdd(modinfo->handle, MSG_VHOST, cmd_vhost, MAXPARA, CMD_USER);
MARK_AS_OFFICIAL_MODULE(modinfo);
HookAdd(modinfo->handle, HOOKTYPE_CONFIGTEST, 0, vhost_config_test);
return MOD_SUCCESS;
}
MOD_INIT()
{
MARK_AS_OFFICIAL_MODULE(modinfo);
HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, vhost_config_run);
HookAdd(modinfo->handle, HOOKTYPE_STATS, 0, stats_vhost);
CommandAdd(modinfo->handle, MSG_VHOST, cmd_vhost, MAXPARA, CMD_USER);
return MOD_SUCCESS;
}
/* Is first run when server is 100% ready */
MOD_LOAD()
{
return MOD_SUCCESS;
}
/* Called when module is unloaded */
MOD_UNLOAD()
{
return MOD_SUCCESS;
free_vhost_config();
return MOD_SUCCESS;
}
void free_vhost_config(void)
{
ConfigItem_vhost *e, *e_next;
for (e = conf_vhost; e; e = e_next)
{
SWhois *s, *s_next;
e_next = e->next;
safe_free(e->login);
Auth_FreeAuthConfig(e->auth);
safe_free(e->virthost);
safe_free(e->virtuser);
free_security_group(e->match);
for (s = e->swhois; s; s = s_next)
{
s_next = s->next;
safe_free(s->line);
safe_free(s->setby);
safe_free(s);
}
DelListItem(e, conf_vhost);
safe_free(e);
}
conf_vhost = NULL;
}
/** Test a vhost { } block in the configuration file */
int vhost_config_test(ConfigFile *conf, ConfigEntry *ce, int type, int *errs)
{
ConfigEntry *cep;
char has_vhost = 0, has_login = 0, has_password = 0, has_mask = 0, has_match = 0;
int errors = 0;
/* We are only interested in vhost { } blocks */
if ((type != CONFIG_MAIN) || strcmp(ce->name, "vhost"))
return 0;
for (cep = ce->items; cep; cep = cep->next)
{
if (!strcmp(cep->name, "vhost"))
{
char *at, *tmp, *host;
if (has_vhost)
{
config_warn_duplicate(cep->file->filename,
cep->line_number, "vhost::vhost");
continue;
}
has_vhost = 1;
if (!cep->value)
{
config_error_empty(cep->file->filename,
cep->line_number, "vhost", "vhost");
errors++;
continue;
}
if (!valid_vhost(cep->value))
{
config_error("%s:%i: oper::vhost contains illegal characters or is too long: '%s'",
cep->file->filename, cep->line_number, cep->value);
errors++;
}
}
else if (!strcmp(cep->name, "login"))
{
if (has_login)
{
config_warn_duplicate(cep->file->filename,
cep->line_number, "vhost::login");
}
has_login = 1;
if (!cep->value)
{
config_error_empty(cep->file->filename,
cep->line_number, "vhost", "login");
errors++;
continue;
}
}
else if (!strcmp(cep->name, "password"))
{
if (has_password)
{
config_warn_duplicate(cep->file->filename,
cep->line_number, "vhost::password");
}
has_password = 1;
if (!cep->value)
{
config_error_empty(cep->file->filename,
cep->line_number, "vhost", "password");
errors++;
continue;
}
if (Auth_CheckError(cep, 0) < 0)
errors++;
}
else if (!strcmp(cep->name, "mask"))
{
has_mask = 1;
test_match_block(conf, cep, &errors);
}
else if (!strcmp(cep->name, "match"))
{
has_match = 1;
test_match_block(conf, cep, &errors);
}
else if (!strcmp(cep->name, "swhois"))
{
/* multiple is ok */
}
else
{
config_error_unknown(cep->file->filename, cep->line_number,
"vhost", cep->name);
errors++;
}
}
if (!has_vhost)
{
config_error_missing(ce->file->filename, ce->line_number,
"vhost::vhost");
errors++;
}
if (!has_login)
{
config_error_missing(ce->file->filename, ce->line_number,
"vhost::login");
errors++;
}
if (!has_password)
{
config_error_missing(ce->file->filename, ce->line_number,
"vhost::password");
errors++;
}
if (!has_mask && !has_match)
{
config_error_missing(ce->file->filename, ce->line_number,
"vhost::match");
errors++;
}
if (has_mask && has_match)
{
config_error("%s:%d: You cannot have both ::mask and ::match. "
"You should only use %s::match.",
ce->file->filename, ce->line_number, ce->name);
errors++;
}
*errs = errors;
return errors ? -1 : 1;
}
/** Process a vhost { } block in the configuration file */
int vhost_config_run(ConfigFile *conf, ConfigEntry *ce, int type)
{
ConfigEntry *cep, *cepp;
ConfigItem_vhost *vhost;
/* We are only interested in vhost { } blocks */
if ((type != CONFIG_MAIN) || strcmp(ce->name, "vhost"))
return 0;
vhost = safe_alloc(sizeof(ConfigItem_vhost));
vhost->match = safe_alloc(sizeof(SecurityGroup));
for (cep = ce->items; cep; cep = cep->next)
{
if (!strcmp(cep->name, "vhost"))
{
char *user, *host;
user = strtok(cep->value, "@");
host = strtok(NULL, "");
if (!host)
safe_strdup(vhost->virthost, user);
else
{
safe_strdup(vhost->virtuser, user);
safe_strdup(vhost->virthost, host);
}
}
else if (!strcmp(cep->name, "login"))
safe_strdup(vhost->login, cep->value);
else if (!strcmp(cep->name, "password"))
vhost->auth = AuthBlockToAuthConfig(cep);
else if (!strcmp(cep->name, "match") || !strcmp(cep->name, "mask"))
{
conf_match_block(conf, cep, &vhost->match);
}
else if (!strcmp(cep->name, "swhois"))
{
SWhois *s;
if (cep->items)
{
for (cepp = cep->items; cepp; cepp = cepp->next)
{
s = safe_alloc(sizeof(SWhois));
safe_strdup(s->line, cepp->name);
safe_strdup(s->setby, "vhost");
AddListItem(s, vhost->swhois);
}
} else
if (cep->value)
{
s = safe_alloc(sizeof(SWhois));
safe_strdup(s->line, cep->value);
safe_strdup(s->setby, "vhost");
AddListItem(s, vhost->swhois);
}
}
}
AppendListItem(vhost, conf_vhost);
return 1;
}
static int stats_vhost(Client *client, const char *flag)
{
ConfigItem_vhost *vhosts;
NameValuePrioList *m;
if (strcmp(flag, "S") && strcasecmp(flag, "vhost"))
return 0; /* Not for us */
for (vhosts = conf_vhost; vhosts; vhosts = vhosts->next)
{
for (m = vhosts->match->printable_list; m; m = m->next)
{
sendtxtnumeric(client, "vhost %s%s%s %s %s",
vhosts->virtuser ? vhosts->virtuser : "",
vhosts->virtuser ? "@" : "",
vhosts->virthost,
vhosts->login,
namevalue_nospaces(m));
}
}
return 1;
}
ConfigItem_vhost *find_vhost(const char *name)
{
ConfigItem_vhost *vhost;
for (vhost = conf_vhost; vhost; vhost = vhost->next)
{
if (!strcmp(name, vhost->login))
return vhost;
}
return NULL;
}
CMD_FUNC(cmd_vhost)
@@ -59,7 +334,6 @@ CMD_FUNC(cmd_vhost)
ConfigItem_vhost *vhost;
char login[HOSTLEN+1];
const char *password;
char olduser[USERLEN+1];
if (!MyUser(client))
return;
@@ -88,7 +362,7 @@ CMD_FUNC(cmd_vhost)
sendnotice(client, "*** [\2vhost\2] Login for %s failed - password incorrect", login);
return;
}
if (!user_allowed_by_security_group(client, vhost->match))
{
unreal_log(ULOG_WARNING, "vhost", "VHOST_FAILED", client,
@@ -111,6 +385,13 @@ CMD_FUNC(cmd_vhost)
return;
}
do_vhost(client, vhost);
}
void do_vhost(Client *client, ConfigItem_vhost *vhost)
{
char olduser[USERLEN+1];
/* Authentication passed, but.. there could still be other restrictions: */
switch (UHOST_ALLOWED)
{
@@ -162,20 +443,27 @@ CMD_FUNC(cmd_vhost)
vhost->virtuser ? "@" : "",
vhost->virthost);
if (vhost->virtuser)
/* Only notify on logins, not on auto logins (should we make that configurable?)
* (if you do want it for auto logins, note that vhost->login will be NULL
* in the unreal_log() call currently below).
*/
if (vhost->login)
{
/* virtuser@virthost */
unreal_log(ULOG_INFO, "vhost", "VHOST_SUCCESS", client,
"$client.details is now using vhost $virtuser@$virthost [vhost-block: $vhost_block]",
log_data_string("virtuser", vhost->virtuser),
log_data_string("virthost", vhost->virthost),
log_data_string("vhost_block", login));
} else {
/* just virthost */
unreal_log(ULOG_INFO, "vhost", "VHOST_SUCCESS", client,
"$client.details is now using vhost $virthost [vhost-block: $vhost_block]",
log_data_string("virthost", vhost->virthost),
log_data_string("vhost_block", login));
if (vhost->virtuser)
{
/* virtuser@virthost */
unreal_log(ULOG_INFO, "vhost", "VHOST_SUCCESS", client,
"$client.details is now using vhost $virtuser@$virthost [vhost-block: $vhost_block]",
log_data_string("virtuser", vhost->virtuser),
log_data_string("virthost", vhost->virthost),
log_data_string("vhost_block", vhost->login));
} else {
/* just virthost */
unreal_log(ULOG_INFO, "vhost", "VHOST_SUCCESS", client,
"$client.details is now using vhost $virthost [vhost-block: $vhost_block]",
log_data_string("virthost", vhost->virthost),
log_data_string("vhost_block", vhost->login));
}
}
userhost_changed(client);