Skip to content

Commit

Permalink
Fix setting an X-Line on a server with a matching user
Browse files Browse the repository at this point in the history
X-Lines use MatchItems, not AccessItems, and the match reporting was
using an AccessItem, thus accessing out of bounds memory.  Also
completely rip out map_to_conf, instead putting the
MatchItem/AccessItem/ClassItem/ResvChannel in an anonymous union in the
ClassItem.  map_to_conf was a horrible hack, and this at least gets us
some type checking, as long as you pick the right union member.

Fixes #43
  • Loading branch information
dwfreed committed Sep 8, 2023
1 parent 566f4da commit bdacbd4
Show file tree
Hide file tree
Showing 27 changed files with 236 additions and 240 deletions.
2 changes: 1 addition & 1 deletion contrib/m_classlist.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ mo_classlist(struct Client *client_p, struct Client *source_p,

if (match(parv[1], conf->name))
{
const struct ClassItem *aclass = map_to_conf(conf);
const struct ClassItem *aclass = &conf->aclass;
sendto_one(source_p, ":%s NOTICE %s :%s %d",
me.name, source_p->name, conf->name,
CurrUserCount(aclass));
Expand Down
32 changes: 21 additions & 11 deletions include/s_conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "client.h"
#include "hook.h"
#include "pcre.h"
#include "resv.h" /* ResvChannel */

struct Client;
struct DNSReply;
Expand Down Expand Up @@ -79,15 +80,6 @@ struct split_nuh_item
size_t hostsize;
};

struct ConfItem
{
char *name; /* Primary key */
pcre *regexpname;
dlink_node node; /* link into known ConfItems of this type */
unsigned int flags;
ConfType type;
};

/*
* MatchItem - used for XLINE and ULINE types
*/
Expand Down Expand Up @@ -156,6 +148,22 @@ struct ClassItem
char *reject_message;
};

struct ConfItem
{
char *name; /* Primary key */
pcre *regexpname;
dlink_node node; /* link into known ConfItems of this type */
unsigned int flags;
ConfType type;
union
{
struct AccessItem aconf;
struct MatchItem mconf;
struct ClassItem aclass;
struct ResvChannel cresv;
};
};

struct CidrItem
{
struct irc_ssaddr mask;
Expand Down Expand Up @@ -565,8 +573,10 @@ extern void parse_csv_file(FBFILE *, ConfType);

extern char *get_oper_name(const struct Client *);

extern void *map_to_conf(struct ConfItem *);
extern struct ConfItem *unmap_conf_item(void *);
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type, member) );})
#define unmap_conf_item(ptr, member) container_of(ptr, struct ConfItem, member)
/* XXX should the parse_aline stuff go into another file ?? */
#define AWILD 0x1 /* check wild cards */
#define NOUSERLOOKUP 0x2 /* Don't lookup the user@host on /rkline nick */
Expand Down
8 changes: 4 additions & 4 deletions modules/core/m_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ ms_server(struct Client *client_p, struct Client *source_p,

if (match(conf->name, client_p->name))
{
match_item = (struct MatchItem *)map_to_conf(conf);
match_item = &conf->mconf;
if (match(match_item->host, name))
llined++;
}
Expand All @@ -376,7 +376,7 @@ ms_server(struct Client *client_p, struct Client *source_p,

if (match(conf->name, client_p->name))
{
match_item = (struct MatchItem *)map_to_conf(conf);
match_item = &conf->mconf;

if (match(match_item->host, name))
hlined++;
Expand Down Expand Up @@ -608,7 +608,7 @@ ms_sid(struct Client *client_p, struct Client *source_p,

if (match(conf->name, client_p->name))
{
match_item = (struct MatchItem *)map_to_conf(conf);
match_item = &conf->mconf;
if (match(match_item->host, SID_NAME))
llined++;
}
Expand All @@ -620,7 +620,7 @@ ms_sid(struct Client *client_p, struct Client *source_p,

if (match(conf->name, client_p->name))
{
match_item = (struct MatchItem *)map_to_conf(conf);
match_item = &conf->mconf;

if (match(match_item->host, SID_NAME))
hlined++;
Expand Down
4 changes: 2 additions & 2 deletions modules/m_challenge.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,13 +148,13 @@ m_challenge(struct Client *client_p, struct Client *source_p,
parv[1], source_p->username, source_p->host
)) != NULL)
{
aconf = (struct AccessItem *)map_to_conf(conf);
aconf = &conf->aconf;
}
else if ((conf = find_conf_exact(OPER_TYPE,
parv[1], source_p->username,
source_p->sockhost)) != NULL)
{
aconf = (struct AccessItem *)map_to_conf(conf);
aconf = &conf->aconf;
}

if(aconf == NULL)
Expand Down
8 changes: 4 additions & 4 deletions modules/m_connect.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,10 @@ mo_connect(struct Client* client_p, struct Client* source_p,
*/
if ((conf = find_matching_name_conf(SERVER_TYPE,
parv[1], NULL, NULL, 0)) != NULL)
aconf = (struct AccessItem *)map_to_conf(conf);
aconf = &conf->aconf;
else if ((conf = find_matching_name_conf(SERVER_TYPE,
NULL, NULL, parv[1], 0)) != NULL)
aconf = (struct AccessItem *)map_to_conf(conf);
aconf = &conf->aconf;

if (conf == NULL)
{
Expand Down Expand Up @@ -236,10 +236,10 @@ ms_connect(struct Client *client_p, struct Client *source_p,
*/
if ((conf = find_matching_name_conf(SERVER_TYPE,
parv[1], NULL, NULL, 0)) != NULL)
aconf = (struct AccessItem *)map_to_conf(conf);
aconf = &conf->aconf;
else if ((conf = find_matching_name_conf(SERVER_TYPE,
NULL, NULL, parv[1], 0)) != NULL)
aconf = (struct AccessItem *)map_to_conf(conf);
aconf = &conf->aconf;

if (aconf == NULL)
{
Expand Down
4 changes: 2 additions & 2 deletions modules/m_cryptlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ cryptlink_auth(struct Client *client_p, struct Client *source_p,
return;
}

aconf = (struct AccessItem *)map_to_conf(conf);
aconf = &conf->aconf;

if (!(client_p->localClient->out_cipher ||
(client_p->localClient->out_cipher = check_cipher(client_p, aconf))))
Expand Down Expand Up @@ -419,7 +419,7 @@ cryptlink_serv(struct Client *client_p, struct Client *source_p,
strlcpy(client_p->info, p, sizeof(client_p->info));
client_p->hopcount = 0;

aconf = (struct AccessItem *)map_to_conf(conf);
aconf = &conf->aconf;

if (!(client_p->localClient->out_cipher ||
(client_p->localClient->out_cipher = check_cipher(client_p, aconf))))
Expand Down
8 changes: 5 additions & 3 deletions modules/m_gline.c
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ do_sgline(struct Client *client_p, struct Client *source_p,
DLINK_FOREACH(ptr, gdeny_items.head)
{
conf = ptr->data;
aconf = (struct AccessItem *)map_to_conf(conf);
aconf = &conf->aconf;

if (match(conf->name, source_p->servptr->name) &&
match(aconf->user, source_p->username) &&
Expand Down Expand Up @@ -413,7 +413,7 @@ set_local_gline(const struct Client *source_p, const char *user,

current_date = smalldate(cur_time);
conf = make_conf_item(GLINE_TYPE);
aconf = (struct AccessItem *)map_to_conf(conf);
aconf = &conf->aconf;

ircsprintf(buffer, "%s (%s)", reason, current_date);
DupString(aconf->reason, buffer);
Expand Down Expand Up @@ -566,6 +566,7 @@ check_majority_gline(const struct Client *source_p,
static int
remove_gline_match(const char *user, const char *host)
{
struct ConfItem *conf;
struct AccessItem *aconf;
dlink_node *ptr = NULL;
struct irc_ssaddr addr, caddr;
Expand All @@ -575,7 +576,8 @@ remove_gline_match(const char *user, const char *host)

DLINK_FOREACH(ptr, temporary_glines.head)
{
aconf = map_to_conf(ptr->data);
conf = (struct ConfItem *)ptr->data;
aconf = &conf->aconf;
cnm_t = parse_netmask(aconf->host, &caddr, &cbits);

if (cnm_t != nm_t || irccmp(user, aconf->user))
Expand Down
16 changes: 10 additions & 6 deletions modules/m_kline.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ mo_kline(struct Client *client_p, struct Client *source_p,
cur_time = CurrentTime;
current_date = smalldate(cur_time);
conf = make_conf_item(KLINE_TYPE);
aconf = map_to_conf(conf);
aconf = &conf->aconf;

DupString(aconf->host, host);
DupString(aconf->user, user);
Expand Down Expand Up @@ -255,7 +255,7 @@ me_kline(struct Client *client_p, struct Client *source_p,
return;

conf = make_conf_item(KLINE_TYPE);
aconf = map_to_conf(conf);
aconf = &conf->aconf;
DupString(aconf->host, khost);
DupString(aconf->user, kuser);

Expand Down Expand Up @@ -298,7 +298,7 @@ apply_kline(struct Client *source_p, struct ConfItem *conf,
{
struct AccessItem *aconf;

aconf = (struct AccessItem *)map_to_conf(conf);
aconf = &conf->aconf;
if(tkline_time > 0)
{
aconf->hold = CurrentTime + tkline_time;
Expand Down Expand Up @@ -421,7 +421,7 @@ mo_dline(struct Client *client_p, struct Client *source_p,
return;

conf = make_conf_item(DLINE_TYPE);
aconf = map_to_conf(conf);
aconf = &conf->aconf;
DupString(aconf->host, dlhost);

if (tkline_time != 0)
Expand Down Expand Up @@ -653,6 +653,7 @@ ms_unkline(struct Client *client_p, struct Client *source_p,
static int
remove_tkline_match(const char *host, const char *user)
{
struct ConfItem *conf;
struct AccessItem *tk_c;
dlink_node *tk_n;
struct irc_ssaddr addr, caddr;
Expand All @@ -661,7 +662,8 @@ remove_tkline_match(const char *host, const char *user)

DLINK_FOREACH(tk_n, temporary_klines.head)
{
tk_c = map_to_conf(tk_n->data);
conf = (struct ConfItem *)tk_n->data;
tk_c = &conf->aconf;
cnm_t = parse_netmask(tk_c->host, &caddr, &cbits);
if (cnm_t != nm_t || irccmp(user, tk_c->user))
continue;
Expand Down Expand Up @@ -689,6 +691,7 @@ remove_tkline_match(const char *host, const char *user)
static int
remove_tdline_match(const char *cidr)
{
struct ConfItem *conf;
struct AccessItem *td_conf;
dlink_node *td_node;
struct irc_ssaddr addr, caddr;
Expand All @@ -697,7 +700,8 @@ remove_tdline_match(const char *cidr)

DLINK_FOREACH(td_node, temporary_dlines.head)
{
td_conf = map_to_conf(td_node->data);
conf = (struct ConfItem *)td_node->data;
td_conf = &conf->aconf;
cnm_t = parse_netmask(td_conf->host, &caddr, &cbits);

if (cnm_t != nm_t)
Expand Down
2 changes: 1 addition & 1 deletion modules/m_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ mo_map(struct Client *client_p, struct Client *source_p,
DLINK_FOREACH(ptr, server_items.head)
{
conf = ptr->data;
aconf = (struct AccessItem *)map_to_conf(conf);
aconf = &conf->aconf;
if (aconf->status != CONF_SERVER)
continue;
if (strcmp(conf->name, me.name) == 0)
Expand Down
2 changes: 1 addition & 1 deletion modules/m_oper.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ m_oper(struct Client *client_p, struct Client *source_p,
return;
}

aconf = (struct AccessItem *)map_to_conf(conf);
aconf = &conf->aconf;

if (match_conf_password(password, aconf))
{
Expand Down
6 changes: 3 additions & 3 deletions modules/m_resv.c
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ parse_resv(struct Client *source_p, char *name, int tkline_time, char *reason)
return;
}

resv_p = map_to_conf(conf);
resv_p = &conf->cresv;

if (tkline_time != 0)
{
Expand Down Expand Up @@ -328,7 +328,7 @@ parse_resv(struct Client *source_p, char *name, int tkline_time, char *reason)
return;
}

resv_p = map_to_conf(conf);
resv_p = &conf->mconf;

if (tkline_time != 0)
{
Expand Down Expand Up @@ -416,7 +416,7 @@ remove_resv(struct Client *source_p, const char *name)
return;
}

resv_p = map_to_conf(conf);
resv_p = &conf->mconf;

if (resv_p->action)
{
Expand Down
11 changes: 6 additions & 5 deletions modules/m_rkline.c
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ mo_rkline(struct Client *client_p, struct Client *source_p,
cur_time = CurrentTime;
current_date = smalldate(cur_time);
conf = make_conf_item(RKLINE_TYPE);
aconf = map_to_conf(conf);
aconf = &conf->aconf;

DupString(aconf->host, host);
DupString(aconf->user, user);
Expand Down Expand Up @@ -241,7 +241,7 @@ me_rkline(struct Client *client_p, struct Client *source_p,
}

conf = make_conf_item(RKLINE_TYPE);
aconf = map_to_conf(conf);
aconf = &conf->aconf;
DupString(aconf->host, khost);
DupString(aconf->user, kuser);

Expand Down Expand Up @@ -284,7 +284,7 @@ static void
apply_rkline(struct Client *source_p, struct ConfItem *conf,
const char *current_date, time_t cur_time, time_t tkline_time)
{
struct AccessItem *aconf = map_to_conf(conf);
struct AccessItem *aconf = &conf->aconf;

if(tkline_time != 0)
{
Expand All @@ -307,7 +307,8 @@ already_placed_rkline(struct Client *source_p, const char *user, const char *hos

DLINK_FOREACH(ptr, rkconf_items.head)
{
struct AccessItem *aptr = map_to_conf(ptr->data);
struct ConfItem *conf = (struct ConfItem *)ptr->data;
struct AccessItem *aptr = &conf->aconf;

if (!strcmp(user, aptr->user) &&
!strcmp(aptr->host, host))
Expand Down Expand Up @@ -487,7 +488,7 @@ remove_trkline_match(const char *const host,
DLINK_FOREACH(ptr, temporary_rklines.head)
{
struct ConfItem *conf = ptr->data;
struct AccessItem *aptr = map_to_conf(ptr->data);
struct AccessItem *aptr = &conf->aconf;

if (!strcmp(user, aptr->user) &&
!strcmp(aptr->host, host))
Expand Down
4 changes: 2 additions & 2 deletions modules/m_rxline.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ already_placed_rxline(struct Client *source_p, const char *gecos)
DLINK_FOREACH(ptr, rxconf_items.head)
{
struct ConfItem *aptr = ptr->data;
const struct MatchItem *match_item = map_to_conf(aptr);
const struct MatchItem *match_item = &aptr->mconf;

if (!strcmp(gecos, aptr->name))
{
Expand Down Expand Up @@ -329,7 +329,7 @@ write_rxline(struct Client *source_p, const char *gecos, char *reason,
conf = make_conf_item(RXLINE_TYPE);
conf->regexpname = exp_gecos;

match_item = map_to_conf(conf);
match_item = &conf->mconf;

DupString(conf->name, gecos);
DupString(match_item->reason, reason);
Expand Down
2 changes: 1 addition & 1 deletion modules/m_stats.c
Original file line number Diff line number Diff line change
Expand Up @@ -695,7 +695,7 @@ dump_counters(struct Client *source_p)
DLINK_FOREACH(ptr, class_items.head)
{
conf = ptr->data;
classitem = map_to_conf(conf);
classitem = &conf->aclass;
DLINK_FOREACH(ptr2, classitem->list_ipv4.head)
{
cidr = ptr2->data;
Expand Down
Loading

0 comments on commit bdacbd4

Please sign in to comment.