reject: Remember and send reasons for rejections

rejectcache entries can now use either a K-line aconf or a static
string as a reason. This will be sent in a 465 numeric before the usual
ERROR. In the case of K-lines, it resembles the 465 you would have been
sent without being rejected:

; nc -s 127.6.6.6 127.0.0.1 5000
:staberinde.local 465 * :You are banned from this server- Temporary
    K-line 4320 min. - abc123 (2019/12/31 01.07)
ERROR :Closing Link: (*** Banned (cache))
; nc -s 127.128.0.0 127.0.0.1 5000
:staberinde.local 465 * :You are not authorised to use this server.
ERROR :Closing Link: (*** Banned (cache))
This commit is contained in:
Ed Kellett 2019-12-31 01:11:45 +00:00
parent 7b8e4c0967
commit a9536f755c
No known key found for this signature in database
GPG key ID: CB9986DEF342FABC
5 changed files with 94 additions and 14 deletions

View file

@ -29,7 +29,7 @@
void init_reject(void);
int check_reject(rb_fde_t *F, struct sockaddr *addr);
void add_reject(struct Client *, const char *mask1, const char *mask2);
void add_reject(struct Client *, const char *mask1, const char *mask2, struct ConfItem *aconf, const char *reason);
int is_reject_ip(struct sockaddr *addr);
void flush_reject(void);
int remove_reject_ip(const char *ip);

View file

@ -350,6 +350,7 @@ extern void read_conf_files(bool cold);
extern int attach_conf(struct Client *, struct ConfItem *);
extern int check_client(struct Client *client_p, struct Client *source_p, const char *);
extern void deref_conf(struct ConfItem *);
extern int detach_conf(struct Client *);
extern struct ConfItem *find_tkline(const char *, const char *, struct sockaddr *);

View file

@ -45,6 +45,8 @@ static void throttle_expires(void *unused);
typedef struct _reject_data
{
rb_dlink_node rnode;
struct ConfItem *aconf;
const char *reason;
time_t time;
unsigned int count;
uint32_t mask_hashv;
@ -54,6 +56,8 @@ typedef struct _delay_data
{
rb_dlink_node node;
rb_fde_t *F;
struct ConfItem *aconf;
const char *reason;
} delay_t;
typedef struct _throttle
@ -69,9 +73,21 @@ delay_exit_length(void)
return rb_dlink_list_length(&delay_exit);
}
static void
reject_free(reject_t *rdata)
{
struct ConfItem *aconf = rdata->aconf;
if (aconf)
deref_conf(aconf);
rb_free(rdata);
}
static void
reject_exit(void *unused)
{
static char dynamic_reason[BUFSIZE];
rb_dlink_node *ptr, *ptr_next;
delay_t *ddata;
static const char *errbuf = "ERROR :Closing Link: (*** Banned (cache))\r\n";
@ -80,6 +96,23 @@ reject_exit(void *unused)
{
ddata = ptr->data;
*dynamic_reason = '\0';
if (ddata->aconf)
{
snprintf(dynamic_reason, BUFSIZE, form_str(ERR_YOUREBANNEDCREEP) "\r\n",
me.name, "*", get_user_ban_reason(ddata->aconf));
rb_write(ddata->F, dynamic_reason, strlen(dynamic_reason));
deref_conf(ddata->aconf);
}
else if (ddata->reason)
{
snprintf(dynamic_reason, BUFSIZE, ":%s 465 %s :%s\r\n",
me.name, "*", ddata->reason);
rb_write(ddata->F, dynamic_reason, strlen(dynamic_reason));
}
rb_write(ddata->F, errbuf, strlen(errbuf));
rb_close(ddata->F);
rb_free(ddata);
@ -105,7 +138,7 @@ reject_expires(void *unused)
continue;
rb_dlinkDelete(ptr, &reject_list);
rb_free(rdata);
reject_free(rdata);
rb_patricia_remove(reject_tree, pnode);
}
}
@ -141,7 +174,7 @@ throttle_size(void)
}
void
add_reject(struct Client *client_p, const char *mask1, const char *mask2)
add_reject(struct Client *client_p, const char *mask1, const char *mask2, struct ConfItem *aconf, const char *reason)
{
rb_patricia_node_t *pnode;
reject_t *rdata;
@ -173,8 +206,25 @@ add_reject(struct Client *client_p, const char *mask1, const char *mask2)
rb_dlinkAddTail(pnode, &rdata->rnode, &reject_list);
rdata->time = rb_current_time();
rdata->count = 1;
rdata->aconf = NULL;
rdata->reason = NULL;
}
rdata->mask_hashv = hashv;
if (aconf != NULL && aconf != rdata->aconf && (aconf->status & CONF_KILL) && aconf->passwd)
{
if (rdata->aconf != NULL)
deref_conf(rdata->aconf);
aconf->clients++;
rdata->aconf = aconf;
}
else if (reason != NULL)
{
if (rdata->aconf != NULL)
deref_conf(rdata->aconf);
rdata->aconf = NULL;
rdata->reason = reason;
}
}
int
@ -198,6 +248,22 @@ check_reject(rb_fde_t *F, struct sockaddr *addr)
ddata = rb_malloc(sizeof(delay_t));
ServerStats.is_rej++;
rb_setselect(F, RB_SELECT_WRITE | RB_SELECT_READ, NULL, NULL);
if(rdata->aconf)
{
ddata->aconf = rdata->aconf;
ddata->aconf->clients++;
ddata->reason = NULL;
}
else if(rdata->reason)
{
ddata->reason = rdata->reason;
ddata->aconf = NULL;
}
else
{
ddata->aconf = NULL;
ddata->reason = NULL;
}
ddata->F = F;
rb_dlinkAdd(ddata, &ddata->node, &delay_exit);
return 1;
@ -244,7 +310,7 @@ flush_reject(void)
pnode = ptr->data;
rdata = pnode->data;
rb_dlinkDelete(ptr, &reject_list);
rb_free(rdata);
reject_free(rdata);
rb_patricia_remove(reject_tree, pnode);
}
}
@ -262,7 +328,7 @@ remove_reject_ip(const char *ip)
{
reject_t *rdata = pnode->data;
rb_dlinkDelete(&rdata->rnode, &reject_list);
rb_free(rdata);
reject_free(rdata);
rb_patricia_remove(reject_tree, pnode);
return 1;
}
@ -290,7 +356,7 @@ remove_reject_mask(const char *mask1, const char *mask2)
if (rdata->mask_hashv == hashv)
{
rb_dlinkDelete(ptr, &reject_list);
rb_free(rdata);
reject_free(rdata);
rb_patricia_remove(reject_tree, pnode);
n++;
}

View file

@ -280,9 +280,8 @@ check_client(struct Client *client_p, struct Client *source_p, const char *usern
source_p->name, IsGotId(source_p) ? "" : "~",
source_p->username, source_p->sockhost,
source_p->localClient->listener->name, port);
add_reject(client_p, NULL, NULL);
exit_client(client_p, source_p, &me,
"You are not authorised to use this server");
add_reject(client_p, NULL, NULL, NULL, "You are not authorised to use this server.");
exit_client(client_p, source_p, &me, "You are not authorised to use this server.");
break;
}
case BANNED_CLIENT:
@ -364,7 +363,7 @@ verify_access(struct Client *client_p, const char *username)
form_str(ERR_YOUREBANNEDCREEP),
me.name, client_p->name,
get_user_ban_reason(aconf));
add_reject(client_p, aconf->user, aconf->host);
add_reject(client_p, aconf->user, aconf->host, aconf, NULL);
return (BANNED_CLIENT);
}
@ -531,6 +530,20 @@ attach_iline(struct Client *client_p, struct ConfItem *aconf)
return (attach_conf(client_p, aconf));
}
/*
* deref_conf
*
* inputs - ConfItem that is referenced by something other than a client
* side effects - Decrement and free ConfItem if appropriate
*/
void
deref_conf(struct ConfItem *aconf)
{
aconf->clients--;
if(!aconf->clients && IsIllegal(aconf))
free_conf(aconf);
}
/*
* detach_conf
*

View file

@ -240,7 +240,7 @@ authd_check(struct Client *client_p, struct Client *source_p)
sendto_one_notice(source_p, ":*** Your IP address %s is listed in %s",
source_p->sockhost, blacklist);
add_reject(source_p, NULL, NULL);
add_reject(source_p, NULL, NULL, NULL, "Banned (DNS blacklist)");
exit_client(client_p, source_p, &me, "Banned (DNS blacklist)");
reject = true;
}
@ -283,7 +283,7 @@ authd_check(struct Client *client_p, struct Client *source_p)
sendto_one_notice(source_p,
":*** Your IP address %s has been detected as an open proxy (type %s, port %s)",
source_p->sockhost, proxy, port);
add_reject(source_p, NULL, NULL);
add_reject(source_p, NULL, NULL, NULL, "Banned (Open proxy)");
exit_client(client_p, source_p, &me, "Banned (Open proxy)");
reject = true;
}
@ -307,7 +307,7 @@ authd_check(struct Client *client_p, struct Client *source_p)
sendto_one_notice(source_p, ":*** Rejected by authentication system: %s",
reason);
add_reject(source_p, NULL, NULL);
add_reject(source_p, NULL, NULL, NULL, "Banned (authentication system)");
exit_client(client_p, source_p, &me, "Banned (authentication system)");
reject = true;
break;
@ -553,7 +553,7 @@ register_local_user(struct Client *client_p, struct Client *source_p)
(xconf = find_xline(source_p->info, 1)) != NULL)
{
ServerStats.is_ref++;
add_reject(source_p, xconf->host, NULL);
add_reject(source_p, xconf->host, NULL, NULL, NULL);
exit_client(client_p, source_p, &me, "Bad user info");
return CLIENT_EXITED;
}