Change allow block to use allow::mask instead of allow::ip / allow::hostname

We use 'mask' everywhere in the config except here, which is annoying
and also inflexible since mask has several nice options, see
https://www.unrealircd.org/docs/Mask_item

Users upgrading will receive a warning, and a reference to
https://www.unrealircd.org/docs/FAQ#allow-mask
but the IRCd will continue to boot (it is not an error).
This commit is contained in:
Bram Matthys 2021-06-19 10:15:09 +02:00
parent deead90ac3
commit b72ea1d945
No known key found for this signature in database
GPG key ID: BF8116B163EAAE98
7 changed files with 88 additions and 109 deletions

View file

@ -116,7 +116,7 @@ class servers
/* Allow everyone in, but only 3 connections per IP */
allow {
ip *@*;
mask *;
class clients;
maxperip 3;
}
@ -126,7 +126,7 @@ allow {
* is correct then it permits 20 connections on that IP.
*/
allow {
ip *@192.0.2.1;
mask 192.0.2.1;
class clients;
password "somesecretpasswd";
maxperip 20;

View file

@ -121,7 +121,7 @@ class servers
/* Accepter tout le monde, mais seulement 5 connexions par IP */
allow {
ip *@*;
mask *;
class clients;
maxperip 5;
}
@ -131,7 +131,7 @@ allow {
* S'il est correct, alors autoriser 20 connexions sur cette IP.
*/
allow {
ip *@192.0.2.1;
mask 192.0.2.1;
class clients;
password "unmotdepassesecret";
maxperip 20;

View file

@ -117,7 +117,7 @@ class servers
/* IP başına sadece 5 bağlantı izini verir */
allow {
ip *@*;
mask *;
class clients;
maxperip 3;
}
@ -127,7 +127,7 @@ allow {
* Şifre doğru ise o zaman bu IP 20 bağlantıya izin verecektir.
*/
allow {
ip *@192.0.2.1;
mask 192.0.2.1;
class clients;
password "somesecretpasswd";
maxperip 20;

View file

@ -1524,8 +1524,7 @@ struct ConfigFlag_allow {
struct ConfigItem_allow {
ConfigItem_allow *prev, *next;
ConfigFlag flag;
char *ip;
char *hostname;
ConfigItem_mask *mask;
char *server;
AuthConfig *auth;
int maxperip; /**< Maximum connections permitted per IP address (locally) */

View file

@ -2540,8 +2540,7 @@ void config_rehash()
for (allow_ptr = conf_allow; allow_ptr; allow_ptr = (ConfigItem_allow *) next)
{
next = (ListStruct *)allow_ptr->next;
safe_free(allow_ptr->ip);
safe_free(allow_ptr->hostname);
unreal_delete_masks(allow_ptr->mask);
Auth_FreeAuthConfig(allow_ptr->auth);
DelListItem(allow_ptr, conf_allow);
safe_free(allow_ptr);
@ -5439,12 +5438,10 @@ int _conf_allow(ConfigFile *conf, ConfigEntry *ce)
for (cep = ce->ce_entries; cep; cep = cep->ce_next)
{
if (!strcmp(cep->ce_varname, "ip"))
if (!strcmp(cep->ce_varname, "mask") || !strcmp(cep->ce_varname, "ip") || !strcmp(cep->ce_varname, "hostname"))
{
safe_strdup(allow->ip, cep->ce_vardata);
unreal_add_masks(&allow->mask, cep);
}
else if (!strcmp(cep->ce_varname, "hostname"))
safe_strdup(allow->hostname, cep->ce_vardata);
else if (!strcmp(cep->ce_varname, "password"))
allow->auth = AuthBlockToAuthConfig(cep);
else if (!strcmp(cep->ce_varname, "class"))
@ -5492,12 +5489,6 @@ int _conf_allow(ConfigFile *conf, ConfigEntry *ce)
}
}
if (!allow->hostname)
safe_strdup(allow->hostname, "*@NOMATCH");
if (!allow->ip)
safe_strdup(allow->ip, "*@NOMATCH");
/* Default: global-maxperip = maxperip+1 */
if (allow->global_maxperip == 0)
allow->global_maxperip = allow->maxperip+1;
@ -5515,7 +5506,8 @@ int _test_allow(ConfigFile *conf, ConfigEntry *ce)
ConfigEntry *cep, *cepp;
int errors = 0;
Hook *h;
char has_ip = 0, has_hostname = 0, has_maxperip = 0, has_global_maxperip = 0, has_password = 0, has_class = 0;
char has_ip = 0, has_hostname = 0, has_mask = 0;
char has_maxperip = 0, has_global_maxperip = 0, has_password = 0, has_class = 0;
char has_redirectserver = 0, has_redirectport = 0, has_options = 0;
int hostname_possible_silliness = 0;
@ -5563,7 +5555,9 @@ int _test_allow(ConfigFile *conf, ConfigEntry *ce)
for (cep = ce->ce_entries; cep; cep = cep->ce_next)
{
if (strcmp(cep->ce_varname, "options") && config_is_blankorempty(cep, "allow"))
if (strcmp(cep->ce_varname, "options") &&
strcmp(cep->ce_varname, "mask") &&
config_is_blankorempty(cep, "allow"))
{
errors++;
continue;
@ -5578,6 +5572,22 @@ int _test_allow(ConfigFile *conf, ConfigEntry *ce)
}
has_ip = 1;
}
else if (!strcmp(cep->ce_varname, "hostname"))
{
if (has_hostname)
{
config_warn_duplicate(cep->ce_fileptr->cf_filename,
cep->ce_varlinenum, "allow::hostname");
continue;
}
has_hostname = 1;
if (!strcmp(cep->ce_vardata, "*@*") || !strcmp(cep->ce_vardata, "*"))
hostname_possible_silliness = 1;
}
else if (!strcmp(cep->ce_varname, "mask"))
{
has_mask = 1;
}
else if (!strcmp(cep->ce_varname, "maxperip"))
{
int v = atoi(cep->ce_vardata);
@ -5636,18 +5646,6 @@ int _test_allow(ConfigFile *conf, ConfigEntry *ce)
cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
}
}
else if (!strcmp(cep->ce_varname, "hostname"))
{
if (has_hostname)
{
config_warn_duplicate(cep->ce_fileptr->cf_filename,
cep->ce_varlinenum, "allow::hostname");
continue;
}
has_hostname = 1;
if (!strcmp(cep->ce_vardata, "*@*") || !strcmp(cep->ce_vardata, "*"))
hostname_possible_silliness = 1;
}
else if (!strcmp(cep->ce_varname, "password"))
{
if (has_password)
@ -5736,25 +5734,45 @@ int _test_allow(ConfigFile *conf, ConfigEntry *ce)
}
}
if (!has_ip && !has_hostname)
if (has_mask && (has_ip || has_hostname))
{
config_error("%s:%d: allow block needs an allow::ip or allow::hostname",
config_error("%s:%d: The allow block uses allow::mask, but you also have an allow::ip and allow::hostname.",
ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
config_error("Please delete your allow::ip and allow::hostname entries and/or integrate them into allow::mask");
} else
if (has_ip)
{
config_warn("%s:%d: The allow block uses allow::mask nowadays. Rename your allow::ip item to allow::mask.",
ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
config_warn("See https://www.unrealircd.org/docs/FAQ#allow-mask for more information");
} else
if (has_hostname)
{
config_warn("%s:%d: The allow block uses allow::mask nowadays. Rename your allow::hostname item to allow::mask.",
ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
config_warn("See https://www.unrealircd.org/docs/FAQ#allow-mask for more information");
} else
if (!has_mask)
{
config_error("%s:%d: allow block needs an allow::mask",
ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
errors++;
}
if (has_ip && has_hostname)
{
config_warn("%s:%d: allow block has both allow::ip and allow::hostname which is no longer permitted.",
ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
config_error("%s:%d: allow block has both allow::ip and allow::hostname, this is no longer permitted.",
ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
config_error("Please integrate your allow::ip and allow::hostname items into a single allow::mask block");
need_34_upgrade = 1;
errors++;
} else
if (hostname_possible_silliness)
{
config_warn("%s:%d: allow block contains 'hostname *;'. This means means that users "
"without a valid hostname (unresolved IP's) will be unable to connect. "
"You most likely want to use 'ip *;' instead.",
ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
config_error("%s:%d: allow block contains 'hostname *;'. This means means that users "
"without a valid hostname (unresolved IP's) will be unable to connect. "
"You most likely want to use 'mask *;' instead.",
ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
}
if (!has_class)

View file

@ -1321,6 +1321,18 @@ int AllowClient(Client *client, char *username)
return 0;
hp = client->local->hostp;
if (hp && hp->h_name)
set_sockhost(client, hp->h_name);
else if (!strcmp(sockhost, "localhost"))
set_sockhost(client, "localhost"); /* yeah, special case :D */
/* SET HOSTNAME: We set client->user->realhost early here
* because we are going to run some checks.
* Note that later on this may be reversed from hostname to IP if
* allow::options::useip is set.
* Also, register_user() contains more stringent hostname checks later on.
*/
strlcpy(client->user->realhost, client->local->sockhost, sizeof(client->local->sockhost));
if (!IsSecure(client) && !IsLocalhost(client) && (iConf.plaintext_policy_user == POLICY_DENY))
{
@ -1340,62 +1352,9 @@ int AllowClient(Client *client, char *username)
if (aconf->flags.tls && !IsSecure(client))
continue;
if (hp && hp->h_name)
{
hname = hp->h_name;
strlcpy(fullname, hname, sizeof(fullname));
Debug((DEBUG_DNS, "a_il: %s->%s", sockhost, fullname));
if (strchr(aconf->hostname, '@'))
{
if (aconf->flags.noident)
strlcpy(uhost, username, sizeof(uhost));
else
strlcpy(uhost, client->ident, sizeof(uhost));
strlcat(uhost, "@", sizeof(uhost));
}
else
*uhost = '\0';
strlcat(uhost, fullname, sizeof(uhost));
if (match_simple(aconf->hostname, uhost))
goto attach;
}
if (!unreal_mask_match(client, aconf->mask))
continue;
if (strchr(aconf->ip, '@'))
{
if (aconf->flags.noident)
strlcpy(uhost, username, sizeof(uhost));
else
strlcpy(uhost, client->ident, sizeof(uhost));
strlcat(uhost, "@", sizeof(uhost));
}
else
*uhost = '\0';
strlcat(uhost, sockhost, sizeof(uhost));
/* Check the IP */
if (match_user(aconf->ip, client, MATCH_CHECK_IP))
goto attach;
/* Hmm, localhost is a special case, hp == NULL and sockhost contains
* 'localhost' instead of an ip... -- Syzop. */
if (!strcmp(sockhost, "localhost"))
{
if (strchr(aconf->hostname, '@'))
{
if (aconf->flags.noident)
strlcpy(uhost, username, sizeof(uhost));
else
strlcpy(uhost, client->ident, sizeof(uhost));
strlcat(uhost, "@localhost", sizeof(uhost));
}
else
strcpy(uhost, "localhost");
if (match_simple(aconf->hostname, uhost))
goto attach;
}
continue; /* No match */
attach:
/* Check authentication */
if (aconf->auth && !Auth_Check(client, aconf->auth, client->local->passwd))
{
@ -1411,11 +1370,9 @@ int AllowClient(Client *client, char *username)
if (!aconf->flags.noident)
SetUseIdent(client);
if (!aconf->flags.useip && hp)
strlcpy(uhost, fullname, sizeof(uhost));
else
strlcpy(uhost, sockhost, sizeof(uhost));
set_sockhost(client, uhost);
if (aconf->flags.useip)
set_sockhost(client, GetIP(client));
if (exceeds_maxperip(client, aconf))
{

View file

@ -493,15 +493,20 @@ int stats_except(Client *client, char *para)
int stats_allow(Client *client, char *para)
{
ConfigItem_allow *allows;
ConfigItem_mask *m;
for (allows = conf_allow; allows; allows = allows->next)
{
sendnumeric(client, RPL_STATSILINE,
allows->ip, allows->hostname,
allows->maxperip,
allows->global_maxperip,
allows->class->name,
allows->server ? allows->server : defserv,
allows->port ? allows->port : 6667);
for (m = allows->mask; m; m = m->next)
{
sendnumeric(client, RPL_STATSILINE,
m->mask, "-",
allows->maxperip,
allows->global_maxperip,
allows->class->name,
allows->server ? allows->server : defserv,
allows->port ? allows->port : 6667);
}
}
return 0;
}