From a9536f755c048567c6e7ee91eca0c944851d3463 Mon Sep 17 00:00:00 2001 From: Ed Kellett Date: Tue, 31 Dec 2019 01:11:45 +0000 Subject: [PATCH] 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)) --- include/reject.h | 2 +- include/s_conf.h | 1 + ircd/reject.c | 76 ++++++++++++++++++++++++++++++++++++++++++++---- ircd/s_conf.c | 21 ++++++++++--- ircd/s_user.c | 8 ++--- 5 files changed, 94 insertions(+), 14 deletions(-) diff --git a/include/reject.h b/include/reject.h index 6fabb2cb..2ca378fe 100644 --- a/include/reject.h +++ b/include/reject.h @@ -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); diff --git a/include/s_conf.h b/include/s_conf.h index 88a41c3e..98c66d28 100644 --- a/include/s_conf.h +++ b/include/s_conf.h @@ -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 *); diff --git a/ircd/reject.c b/ircd/reject.c index 570552a7..efff4919 100644 --- a/ircd/reject.c +++ b/ircd/reject.c @@ -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++; } diff --git a/ircd/s_conf.c b/ircd/s_conf.c index 700b8f7d..2658bddc 100644 --- a/ircd/s_conf.c +++ b/ircd/s_conf.c @@ -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 * diff --git a/ircd/s_user.c b/ircd/s_user.c index 4ac4741e..daba26ec 100644 --- a/ircd/s_user.c +++ b/ircd/s_user.c @@ -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; }