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:
parent
c1b01bf5ec
commit
642c73dddb
3 changed files with 48 additions and 21 deletions
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue