ircd/listener: return a fatal TLS alert for early rejected TLS clients

This is in furtherance of commit 3fdf26aa19 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.
This commit is contained in:
Aaron Jones 2023-06-15 22:32:12 +00:00
parent c1b01bf5ec
commit 642c73dddb
3 changed files with 48 additions and 21 deletions

View file

@ -28,7 +28,7 @@
#define DELAYED_EXIT_TIME 10 #define DELAYED_EXIT_TIME 10
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, bool ssl);
void add_reject(struct Client *, const char *mask1, const char *mask2, struct ConfItem *aconf, const char *reason); 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);

View file

@ -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; static time_t last_oper_notice = 0;
int len; 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 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 // SSLv3.0 Fatal Alert: Access Denied
0x15, 0x03, 0x00, 0x00, 0x02, 0x02, 0x31 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())) if(listener->ssl && (!ircd_ssl_ok || !get_ssld_count()))
{ {
rb_close(F); 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(); 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); rb_close(F);
return 0; return 0;
} }
@ -625,7 +635,7 @@ accept_precallback(rb_fde_t *F, struct sockaddr *addr, rb_socklen_t addrlen, voi
if(listener->ssl) if(listener->ssl)
{ {
rb_write(F, sslerrcode, sizeof(sslerrcode)); rb_write(F, ssldeniederrcode, sizeof(ssldeniederrcode));
} }
else if(ConfigFileEntry.dline_with_reason) 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; return 0;
} }
if(check_reject(F, addr)) { if(check_reject(F, addr, listener->ssl)) {
/* Reject the connection without closing the socket /* Reject the connection without closing the socket
* because it is now on the delay_exit list. */ * because it is now on the delay_exit list. */
return 0; return 0;
@ -656,7 +666,11 @@ accept_precallback(rb_fde_t *F, struct sockaddr *addr, rb_socklen_t addrlen, voi
if(throttle_add(addr)) 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); rb_close(F);
return 0; return 0;
} }

View file

@ -58,6 +58,7 @@ typedef struct _delay_data
rb_fde_t *F; rb_fde_t *F;
struct ConfItem *aconf; struct ConfItem *aconf;
const char *reason; const char *reason;
bool ssl;
} delay_t; } delay_t;
typedef struct _throttle typedef struct _throttle
@ -92,28 +93,39 @@ reject_exit(void *unused)
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";
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) RB_DLINK_FOREACH_SAFE(ptr, ptr_next, delay_exit.head)
{ {
ddata = ptr->data; 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) 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); 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_close(ddata->F);
rb_free(ddata); rb_free(ddata);
} }
@ -228,7 +240,7 @@ add_reject(struct Client *client_p, const char *mask1, const char *mask2, struct
} }
int 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; rb_patricia_node_t *pnode;
reject_t *rdata; reject_t *rdata;
@ -276,6 +288,7 @@ check_reject(rb_fde_t *F, struct sockaddr *addr)
ddata->reason = NULL; ddata->reason = NULL;
} }
ddata->F = F; ddata->F = F;
ddata->ssl = ssl;
rb_dlinkAdd(ddata, &ddata->node, &delay_exit); rb_dlinkAdd(ddata, &ddata->node, &delay_exit);
return 1; return 1;
} }