]> jfr.im git - solanum.git/commitdiff
ircd/listener: return a fatal TLS alert for early rejected TLS clients
authorAaron Jones <redacted>
Thu, 15 Jun 2023 22:32:12 +0000 (22:32 +0000)
committerAaron Jones <redacted>
Tue, 7 Nov 2023 23:52:41 +0000 (23:52 +0000)
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
ircd/listener.c
ircd/reject.c

index 2ca378fe8f4f9361a8b434e882744ed845c8b7b3..5ed0234277f68e372a73dd27a83f245bf8802fbc 100644 (file)
@@ -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);
index 80947af85d9ce873775f848e8f39347b93b0f71e..02b6dabdc6809fe77b29c0b7e0f4c48230055406 100644 (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;
        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;
        }
index 801af5ffcec19b0d70675d1a5496356c142bd584..767dc08738f153da6a2782d15a783c80fb0a4f56 100644 (file)
@@ -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->aconf)
+               if (ddata->ssl)
                {
-                       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);
+                       rb_write(ddata->F, ssldeniederrcode, sizeof(ssldeniederrcode));
                }
-               else if (ddata->reason)
+               else
                {
-                       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));
+                       *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));
                }
 
-               rb_write(ddata->F, errbuf, strlen(errbuf));
+               if (ddata->aconf)
+                       deref_conf(ddata->aconf);
+
                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;
 }