]> jfr.im git - solanum.git/blobdiff - ircd/reject.c
ircd/listener: return a fatal TLS alert for early rejected TLS clients
[solanum.git] / ircd / reject.c
index efff49190c088d1ff566eaca20fcffe135b260a6..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, 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);
+                       rb_write(ddata->F, ssldeniederrcode, sizeof(ssldeniederrcode));
                }
-               else if (ddata->reason)
+               else
                {
-                       snprintf(dynamic_reason, BUFSIZE, ":%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,49 +240,57 @@ 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;
        delay_t *ddata;
+
        /* Reject is disabled */
-       if(ConfigFileEntry.reject_after_count == 0 || ConfigFileEntry.reject_duration == 0)
+       if (ConfigFileEntry.reject_after_count == 0 || ConfigFileEntry.reject_duration == 0)
                return 0;
 
        pnode = rb_match_ip(reject_tree, addr);
-       if(pnode != NULL)
+       if (pnode == NULL)
+               return 0;
+
+       rdata = pnode->data;
+       rdata->time = rb_current_time();
+
+       if (rdata->count <= (unsigned long)ConfigFileEntry.reject_after_count)
+               return 0;
+
+       if (rdata->aconf != NULL && rdata->aconf->status & CONF_ILLEGAL)
        {
-               rdata = pnode->data;
+               rb_dlinkDelete(&rdata->rnode, &reject_list);
+               reject_free(rdata);
+               rb_patricia_remove(reject_tree, pnode);
+               return 0;
+       }
 
-               rdata->time = rb_current_time();
-               if(rdata->count > (unsigned long)ConfigFileEntry.reject_after_count)
-               {
-                       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;
-               }
+       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;
        }
-       /* Caller does what it wants */
-       return 0;
+       else if (rdata->reason)
+       {
+               ddata->reason = rdata->reason;
+               ddata->aconf = NULL;
+       }
+       else
+       {
+               ddata->aconf = NULL;
+               ddata->reason = NULL;
+       }
+       ddata->F = F;
+       ddata->ssl = ssl;
+       rb_dlinkAdd(ddata, &ddata->node, &delay_exit);
+       return 1;
 }
 
 int