From 642c73dddb3ce7c9ae4824fa95ea9ebad41eb848 Mon Sep 17 00:00:00 2001 From: Aaron Jones Date: Thu, 15 Jun 2023 22:32:12 +0000 Subject: [PATCH] ircd/listener: return a fatal TLS alert for early rejected TLS clients This is in furtherance of commit 3fdf26aa19628d5e12a3 which added functionality to reply with a TLS record layer alert for D-Lined TLS clients. It turns out that there are other plaintext error messages in this same function that should receive the same treatment. Also move another error string to a variable and use a compile-time optimised-out strlen for it too, to use the same approach as an existing error string. Finally, use a different alert (internal_error) for the case where IRCd is simply unable to accept more connections. --- include/reject.h | 2 +- ircd/listener.c | 24 +++++++++++++++++++----- ircd/reject.c | 43 ++++++++++++++++++++++++++++--------------- 3 files changed, 48 insertions(+), 21 deletions(-) diff --git a/include/reject.h b/include/reject.h index 2ca378fe..5ed02342 100644 --- a/include/reject.h +++ b/include/reject.h @@ -28,7 +28,7 @@ #define DELAYED_EXIT_TIME 10 void init_reject(void); -int check_reject(rb_fde_t *F, struct sockaddr *addr); +int check_reject(rb_fde_t *F, struct sockaddr *addr, bool ssl); 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); diff --git a/ircd/listener.c b/ircd/listener.c index 80947af8..02b6dabd 100644 --- a/ircd/listener.c +++ b/ircd/listener.c @@ -581,13 +581,19 @@ accept_precallback(rb_fde_t *F, struct sockaddr *addr, rb_socklen_t addrlen, voi static time_t last_oper_notice = 0; int len; + static const char *allinuse = "ERROR :All connections in use\r\n"; static const char *toofast = "ERROR :Reconnecting too fast, throttled.\r\n"; - static const unsigned char sslerrcode[] = { + static const unsigned char ssldeniederrcode[] = { // SSLv3.0 Fatal Alert: Access Denied 0x15, 0x03, 0x00, 0x00, 0x02, 0x02, 0x31 }; + static const unsigned char sslinternalerrcode[] = { + // SSLv3.0 Fatal Alert: Internal Error + 0x15, 0x03, 0x00, 0x00, 0x02, 0x02, 0x50 + }; + if(listener->ssl && (!ircd_ssl_ok || !get_ssld_count())) { rb_close(F); @@ -608,7 +614,11 @@ accept_precallback(rb_fde_t *F, struct sockaddr *addr, rb_socklen_t addrlen, voi last_oper_notice = rb_current_time(); } - rb_write(F, "ERROR :All connections in use\r\n", 31); + if(listener->ssl) + rb_write(F, sslinternalerrcode, sizeof(sslinternalerrcode)); + else + rb_write(F, allinuse, strlen(allinuse)); + rb_close(F); return 0; } @@ -625,7 +635,7 @@ accept_precallback(rb_fde_t *F, struct sockaddr *addr, rb_socklen_t addrlen, voi if(listener->ssl) { - rb_write(F, sslerrcode, sizeof(sslerrcode)); + rb_write(F, ssldeniederrcode, sizeof(ssldeniederrcode)); } else if(ConfigFileEntry.dline_with_reason) { @@ -648,7 +658,7 @@ accept_precallback(rb_fde_t *F, struct sockaddr *addr, rb_socklen_t addrlen, voi return 0; } - if(check_reject(F, addr)) { + if(check_reject(F, addr, listener->ssl)) { /* Reject the connection without closing the socket * because it is now on the delay_exit list. */ return 0; @@ -656,7 +666,11 @@ accept_precallback(rb_fde_t *F, struct sockaddr *addr, rb_socklen_t addrlen, voi if(throttle_add(addr)) { - rb_write(F, toofast, strlen(toofast)); + if(listener->ssl) + rb_write(F, ssldeniederrcode, sizeof(ssldeniederrcode)); + else + rb_write(F, toofast, strlen(toofast)); + rb_close(F); return 0; } diff --git a/ircd/reject.c b/ircd/reject.c index 801af5ff..767dc087 100644 --- a/ircd/reject.c +++ b/ircd/reject.c @@ -58,6 +58,7 @@ typedef struct _delay_data rb_fde_t *F; struct ConfItem *aconf; const char *reason; + bool ssl; } delay_t; typedef struct _throttle @@ -92,28 +93,39 @@ reject_exit(void *unused) delay_t *ddata; static const char *errbuf = "ERROR :Closing Link: (*** Banned (cache))\r\n"; + static const unsigned char ssldeniederrcode[] = { + // SSLv3.0 Fatal Alert: Access Denied + 0x15, 0x03, 0x00, 0x00, 0x02, 0x02, 0x31 + }; + RB_DLINK_FOREACH_SAFE(ptr, ptr_next, delay_exit.head) { ddata = ptr->data; - *dynamic_reason = '\0'; + if (ddata->ssl) + { + rb_write(ddata->F, ssldeniederrcode, sizeof(ssldeniederrcode)); + } + else + { + *dynamic_reason = '\0'; + + if (ddata->aconf) + snprintf(dynamic_reason, sizeof dynamic_reason, form_str(ERR_YOUREBANNEDCREEP) "\r\n", + me.name, "*", get_user_ban_reason(ddata->aconf)); + else if (ddata->reason) + snprintf(dynamic_reason, sizeof dynamic_reason, ":%s 465 %s :%s\r\n", + me.name, "*", ddata->reason); + + if (*dynamic_reason) + rb_write(ddata->F, dynamic_reason, strlen(dynamic_reason)); + + rb_write(ddata->F, errbuf, strlen(errbuf)); + } if (ddata->aconf) - { - snprintf(dynamic_reason, sizeof dynamic_reason, 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, sizeof dynamic_reason, ":%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); } @@ -228,7 +240,7 @@ add_reject(struct Client *client_p, const char *mask1, const char *mask2, struct } int -check_reject(rb_fde_t *F, struct sockaddr *addr) +check_reject(rb_fde_t *F, struct sockaddr *addr, bool ssl) { rb_patricia_node_t *pnode; reject_t *rdata; @@ -276,6 +288,7 @@ check_reject(rb_fde_t *F, struct sockaddr *addr) ddata->reason = NULL; } ddata->F = F; + ddata->ssl = ssl; rb_dlinkAdd(ddata, &ddata->node, &delay_exit); return 1; }