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:
parent
7b8e4c0967
commit
a9536f755c
5 changed files with 94 additions and 14 deletions
|
@ -29,7 +29,7 @@
|
||||||
|
|
||||||
void init_reject(void);
|
void init_reject(void);
|
||||||
int check_reject(rb_fde_t *F, struct sockaddr *addr);
|
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);
|
int is_reject_ip(struct sockaddr *addr);
|
||||||
void flush_reject(void);
|
void flush_reject(void);
|
||||||
int remove_reject_ip(const char *ip);
|
int remove_reject_ip(const char *ip);
|
||||||
|
|
|
@ -350,6 +350,7 @@ extern void read_conf_files(bool cold);
|
||||||
extern int attach_conf(struct Client *, struct ConfItem *);
|
extern int attach_conf(struct Client *, struct ConfItem *);
|
||||||
extern int check_client(struct Client *client_p, struct Client *source_p, const char *);
|
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 int detach_conf(struct Client *);
|
||||||
|
|
||||||
extern struct ConfItem *find_tkline(const char *, const char *, struct sockaddr *);
|
extern struct ConfItem *find_tkline(const char *, const char *, struct sockaddr *);
|
||||||
|
|
|
@ -45,6 +45,8 @@ static void throttle_expires(void *unused);
|
||||||
typedef struct _reject_data
|
typedef struct _reject_data
|
||||||
{
|
{
|
||||||
rb_dlink_node rnode;
|
rb_dlink_node rnode;
|
||||||
|
struct ConfItem *aconf;
|
||||||
|
const char *reason;
|
||||||
time_t time;
|
time_t time;
|
||||||
unsigned int count;
|
unsigned int count;
|
||||||
uint32_t mask_hashv;
|
uint32_t mask_hashv;
|
||||||
|
@ -54,6 +56,8 @@ typedef struct _delay_data
|
||||||
{
|
{
|
||||||
rb_dlink_node node;
|
rb_dlink_node node;
|
||||||
rb_fde_t *F;
|
rb_fde_t *F;
|
||||||
|
struct ConfItem *aconf;
|
||||||
|
const char *reason;
|
||||||
} delay_t;
|
} delay_t;
|
||||||
|
|
||||||
typedef struct _throttle
|
typedef struct _throttle
|
||||||
|
@ -69,9 +73,21 @@ delay_exit_length(void)
|
||||||
return rb_dlink_list_length(&delay_exit);
|
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
|
static void
|
||||||
reject_exit(void *unused)
|
reject_exit(void *unused)
|
||||||
{
|
{
|
||||||
|
static char dynamic_reason[BUFSIZE];
|
||||||
rb_dlink_node *ptr, *ptr_next;
|
rb_dlink_node *ptr, *ptr_next;
|
||||||
delay_t *ddata;
|
delay_t *ddata;
|
||||||
static const char *errbuf = "ERROR :Closing Link: (*** Banned (cache))\r\n";
|
static const char *errbuf = "ERROR :Closing Link: (*** Banned (cache))\r\n";
|
||||||
|
@ -80,6 +96,23 @@ reject_exit(void *unused)
|
||||||
{
|
{
|
||||||
ddata = ptr->data;
|
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_write(ddata->F, errbuf, strlen(errbuf));
|
||||||
rb_close(ddata->F);
|
rb_close(ddata->F);
|
||||||
rb_free(ddata);
|
rb_free(ddata);
|
||||||
|
@ -105,7 +138,7 @@ reject_expires(void *unused)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
rb_dlinkDelete(ptr, &reject_list);
|
rb_dlinkDelete(ptr, &reject_list);
|
||||||
rb_free(rdata);
|
reject_free(rdata);
|
||||||
rb_patricia_remove(reject_tree, pnode);
|
rb_patricia_remove(reject_tree, pnode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -141,7 +174,7 @@ throttle_size(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
rb_patricia_node_t *pnode;
|
||||||
reject_t *rdata;
|
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);
|
rb_dlinkAddTail(pnode, &rdata->rnode, &reject_list);
|
||||||
rdata->time = rb_current_time();
|
rdata->time = rb_current_time();
|
||||||
rdata->count = 1;
|
rdata->count = 1;
|
||||||
|
rdata->aconf = NULL;
|
||||||
|
rdata->reason = NULL;
|
||||||
}
|
}
|
||||||
rdata->mask_hashv = hashv;
|
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
|
int
|
||||||
|
@ -198,6 +248,22 @@ check_reject(rb_fde_t *F, struct sockaddr *addr)
|
||||||
ddata = rb_malloc(sizeof(delay_t));
|
ddata = rb_malloc(sizeof(delay_t));
|
||||||
ServerStats.is_rej++;
|
ServerStats.is_rej++;
|
||||||
rb_setselect(F, RB_SELECT_WRITE | RB_SELECT_READ, NULL, NULL);
|
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;
|
ddata->F = F;
|
||||||
rb_dlinkAdd(ddata, &ddata->node, &delay_exit);
|
rb_dlinkAdd(ddata, &ddata->node, &delay_exit);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -244,7 +310,7 @@ flush_reject(void)
|
||||||
pnode = ptr->data;
|
pnode = ptr->data;
|
||||||
rdata = pnode->data;
|
rdata = pnode->data;
|
||||||
rb_dlinkDelete(ptr, &reject_list);
|
rb_dlinkDelete(ptr, &reject_list);
|
||||||
rb_free(rdata);
|
reject_free(rdata);
|
||||||
rb_patricia_remove(reject_tree, pnode);
|
rb_patricia_remove(reject_tree, pnode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -262,7 +328,7 @@ remove_reject_ip(const char *ip)
|
||||||
{
|
{
|
||||||
reject_t *rdata = pnode->data;
|
reject_t *rdata = pnode->data;
|
||||||
rb_dlinkDelete(&rdata->rnode, &reject_list);
|
rb_dlinkDelete(&rdata->rnode, &reject_list);
|
||||||
rb_free(rdata);
|
reject_free(rdata);
|
||||||
rb_patricia_remove(reject_tree, pnode);
|
rb_patricia_remove(reject_tree, pnode);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -290,7 +356,7 @@ remove_reject_mask(const char *mask1, const char *mask2)
|
||||||
if (rdata->mask_hashv == hashv)
|
if (rdata->mask_hashv == hashv)
|
||||||
{
|
{
|
||||||
rb_dlinkDelete(ptr, &reject_list);
|
rb_dlinkDelete(ptr, &reject_list);
|
||||||
rb_free(rdata);
|
reject_free(rdata);
|
||||||
rb_patricia_remove(reject_tree, pnode);
|
rb_patricia_remove(reject_tree, pnode);
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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->name, IsGotId(source_p) ? "" : "~",
|
||||||
source_p->username, source_p->sockhost,
|
source_p->username, source_p->sockhost,
|
||||||
source_p->localClient->listener->name, port);
|
source_p->localClient->listener->name, port);
|
||||||
add_reject(client_p, NULL, NULL);
|
add_reject(client_p, NULL, NULL, NULL, "You are not authorised to use this server.");
|
||||||
exit_client(client_p, source_p, &me,
|
exit_client(client_p, source_p, &me, "You are not authorised to use this server.");
|
||||||
"You are not authorised to use this server");
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BANNED_CLIENT:
|
case BANNED_CLIENT:
|
||||||
|
@ -364,7 +363,7 @@ verify_access(struct Client *client_p, const char *username)
|
||||||
form_str(ERR_YOUREBANNEDCREEP),
|
form_str(ERR_YOUREBANNEDCREEP),
|
||||||
me.name, client_p->name,
|
me.name, client_p->name,
|
||||||
get_user_ban_reason(aconf));
|
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);
|
return (BANNED_CLIENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -531,6 +530,20 @@ attach_iline(struct Client *client_p, struct ConfItem *aconf)
|
||||||
return (attach_conf(client_p, 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
|
* detach_conf
|
||||||
*
|
*
|
||||||
|
|
|
@ -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",
|
sendto_one_notice(source_p, ":*** Your IP address %s is listed in %s",
|
||||||
source_p->sockhost, blacklist);
|
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)");
|
exit_client(client_p, source_p, &me, "Banned (DNS blacklist)");
|
||||||
reject = true;
|
reject = true;
|
||||||
}
|
}
|
||||||
|
@ -283,7 +283,7 @@ authd_check(struct Client *client_p, struct Client *source_p)
|
||||||
sendto_one_notice(source_p,
|
sendto_one_notice(source_p,
|
||||||
":*** Your IP address %s has been detected as an open proxy (type %s, port %s)",
|
":*** Your IP address %s has been detected as an open proxy (type %s, port %s)",
|
||||||
source_p->sockhost, proxy, port);
|
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)");
|
exit_client(client_p, source_p, &me, "Banned (Open proxy)");
|
||||||
reject = true;
|
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",
|
sendto_one_notice(source_p, ":*** Rejected by authentication system: %s",
|
||||||
reason);
|
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)");
|
exit_client(client_p, source_p, &me, "Banned (authentication system)");
|
||||||
reject = true;
|
reject = true;
|
||||||
break;
|
break;
|
||||||
|
@ -553,7 +553,7 @@ register_local_user(struct Client *client_p, struct Client *source_p)
|
||||||
(xconf = find_xline(source_p->info, 1)) != NULL)
|
(xconf = find_xline(source_p->info, 1)) != NULL)
|
||||||
{
|
{
|
||||||
ServerStats.is_ref++;
|
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");
|
exit_client(client_p, source_p, &me, "Bad user info");
|
||||||
return CLIENT_EXITED;
|
return CLIENT_EXITED;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue