]> jfr.im git - solanum.git/blobdiff - ircd/s_conf.c
Update NUMERIC_STR_435 to be more human-readable and mention quiets
[solanum.git] / ircd / s_conf.c
index 7a914ed4832edbc5f6ba5b4741acce6673fcd9fb..b692430058409470be752ef1799997153d0cbe31 100644 (file)
@@ -25,6 +25,7 @@
 #include "stdinc.h"
 #include "ircd_defs.h"
 #include "s_conf.h"
+#include "s_user.h"
 #include "s_newconf.h"
 #include "newconf.h"
 #include "s_serv.h"
 #include "chmode.h"
 #include "hook.h"
 #include "s_assert.h"
-#include "authd.h"
+#include "authproc.h"
+#include "supported.h"
 
 struct config_server_hide ConfigServerHide;
 
 extern int yyparse(void);              /* defined in y.tab.c */
-extern char linebuf[];
-
-#ifndef INADDR_NONE
-#define INADDR_NONE ((unsigned int) 0xffffffff)
-#endif
+extern char yy_linebuf[16384];         /* defined in ircd_lexer.l */
 
 static rb_bh *confitem_heap = NULL;
 
-rb_dlink_list prop_bans;
-
 rb_dlink_list temp_klines[LAST_TEMP_TYPE];
 rb_dlink_list temp_dlines[LAST_TEMP_TYPE];
 rb_dlink_list service_list;
 
+rb_dictionary *prop_bans_dict;
+
 /* internally defined functions */
 static void set_default_conf(void);
 static void validate_conf(void);
 static void read_conf(void);
 static void clear_out_old_conf(void);
 
-static void expire_prop_bans(void *list);
+static void expire_prop_bans(void *);
 static void expire_temp_kd(void *list);
 static void reorganise_temp_kd(void *list);
 
+static int cmp_prop_ban(const void *, const void *);
+
 FILE *conf_fbfile_in;
 extern char yytext[];
 
@@ -91,8 +91,9 @@ void
 init_s_conf(void)
 {
        confitem_heap = rb_bh_create(sizeof(struct ConfItem), CONFITEM_HEAP_SIZE, "confitem_heap");
+       prop_bans_dict = rb_dictionary_create("prop_bans", cmp_prop_ban);
 
-       rb_event_addish("expire_prop_bans", expire_prop_bans, &prop_bans, 60);
+       rb_event_addish("expire_prop_bans", expire_prop_bans, NULL, 60);
 
        rb_event_addish("expire_temp_klines", expire_temp_kd, &temp_klines[TEMP_MIN], 60);
        rb_event_addish("expire_temp_dlines", expire_temp_kd, &temp_dlines[TEMP_MIN], 60);
@@ -259,7 +260,7 @@ check_client(struct Client *client_p, struct Client *source_p, const char *usern
        case NOT_AUTHORISED:
                {
                        int port = -1;
-                       port = ntohs(GET_SS_PORT(&source_p->localClient->listener->addr));
+                       port = ntohs(GET_SS_PORT(&source_p->localClient->listener->addr[0]));
 
                        ServerStats.is_ref++;
                        /* jdc - lists server name & port connections are on */
@@ -269,7 +270,7 @@ check_client(struct Client *client_p, struct Client *source_p, const char *usern
                        static char ipaddr[HOSTIPLEN];
                        rb_inet_ntop_sock(&source_p->localClient->ip, ipaddr, sizeof(ipaddr));
 #endif
-                       sendto_realops_snomask(SNO_UNAUTH, L_ALL,
+                       sendto_realops_snomask(SNO_UNAUTH, L_NETWIDE,
                                        "Unauthorised client connection from "
                                        "%s!%s%s@%s [%s] on [%s/%u].",
                                        source_p->name, IsGotId(source_p) ? "" : "~",
@@ -282,9 +283,8 @@ check_client(struct Client *client_p, struct Client *source_p, const char *usern
                                source_p->name, IsGotId(source_p) ? "" : "~",
                                source_p->username, source_p->sockhost,
                                source_p->localClient->listener->name, port);
-                       add_reject(client_p, NULL, NULL);
-                       exit_client(client_p, source_p, &me,
-                                   "You are not authorised to use this server");
+                       add_reject(client_p, NULL, NULL, NULL, "You are not authorised to use this server.");
+                       exit_client(client_p, source_p, &me, "You are not authorised to use this server.");
                        break;
                }
        case BANNED_CLIENT:
@@ -335,7 +335,7 @@ verify_access(struct Client *client_p, const char *username)
 
                        if(IsConfSpoofNotice(aconf))
                        {
-                               sendto_realops_snomask(SNO_GENERAL, L_ALL,
+                               sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
                                                "%s spoofing: %s as %s",
                                                client_p->name,
                                                show_ip(NULL, client_p) ? client_p->host : aconf->info.name,
@@ -366,7 +366,7 @@ verify_access(struct Client *client_p, const char *username)
                                        form_str(ERR_YOUREBANNEDCREEP),
                                        me.name, client_p->name,
                                        get_user_ban_reason(aconf));
-               add_reject(client_p, aconf->user, aconf->host);
+               add_reject(client_p, aconf->user, aconf->host, aconf, NULL);
                return (BANNED_CLIENT);
        }
 
@@ -533,6 +533,20 @@ attach_iline(struct Client *client_p, struct ConfItem *aconf)
        return (attach_conf(client_p, aconf));
 }
 
+/*
+ * deref_conf
+ *
+ * inputs      - ConfItem that is referenced by something other than a client
+ * side effects        - Decrement and free ConfItem if appropriate
+ */
+void
+deref_conf(struct ConfItem *aconf)
+{
+       aconf->clients--;
+       if(!aconf->clients && IsIllegal(aconf) && !lookup_prop_ban(aconf))
+               free_conf(aconf);
+}
+
 /*
  * detach_conf
  *
@@ -593,11 +607,11 @@ attach_conf(struct Client *client_p, struct ConfItem *aconf)
        if(IsIllegal(aconf))
                return (NOT_AUTHORISED);
 
-       if(ClassPtr(aconf))
-       {
-               if(!add_ip_limit(client_p, aconf))
-                       return (TOO_MANY_LOCAL);
-       }
+       if(s_assert(ClassPtr(aconf)))
+               return (NOT_AUTHORISED);
+
+       if(!add_ip_limit(client_p, aconf))
+               return (TOO_MANY_LOCAL);
 
        if((aconf->status & CONF_CLIENT) &&
           ConfCurrUsers(aconf) >= ConfMaxUsers(aconf) && ConfMaxUsers(aconf) > 0)
@@ -633,13 +647,18 @@ attach_conf(struct Client *client_p, struct ConfItem *aconf)
 bool
 rehash(bool sig)
 {
+       rb_dlink_node *n;
+
+       hook_data_rehash hdata = { sig };
+
        if(sig)
-       {
-               sendto_realops_snomask(SNO_GENERAL, L_ALL,
+               sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
                                     "Got signal SIGHUP, reloading ircd conf. file");
-       }
 
        rehash_authd();
+
+       privilegeset_prepare_rehash();
+
        /* don't close listeners until we know we can go ahead with the rehash */
        read_conf_files(false);
 
@@ -649,6 +668,17 @@ rehash(bool sig)
                rb_strlcpy(me.info, "unknown", sizeof(me.info));
 
        open_logfiles();
+
+       RB_DLINK_FOREACH(n, local_oper_list.head)
+       {
+               struct Client *oper = n->data;
+               struct PrivilegeSet *privset = oper->user->privset;
+               report_priv_change(oper, privset ? privset->shadow : NULL, privset);
+       }
+
+       privilegeset_cleanup_rehash();
+
+       call_hook(h_rehash, &hdata);
        return false;
 }
 
@@ -677,12 +707,10 @@ set_default_conf(void)
        ServerInfo.description = NULL;
        ServerInfo.network_name = NULL;
 
-       memset(&ServerInfo.ip, 0, sizeof(ServerInfo.ip));
-       ServerInfo.specific_ipv4_vhost = 0;
-#ifdef RB_IPV6
-       memset(&ServerInfo.ip6, 0, sizeof(ServerInfo.ip6));
-       ServerInfo.specific_ipv6_vhost = 0;
-#endif
+       memset(&ServerInfo.bind4, 0, sizeof(ServerInfo.bind4));
+       SET_SS_FAMILY(&ServerInfo.bind4, AF_UNSPEC);
+       memset(&ServerInfo.bind6, 0, sizeof(ServerInfo.bind6));
+       SET_SS_FAMILY(&ServerInfo.bind6, AF_UNSPEC);
 
        AdminInfo.name = NULL;
        AdminInfo.email = NULL;
@@ -709,17 +737,16 @@ set_default_conf(void)
        ConfigFileEntry.client_exit = true;
        ConfigFileEntry.dline_with_reason = true;
        ConfigFileEntry.kline_with_reason = true;
-       ConfigFileEntry.kline_delay = 0;
        ConfigFileEntry.warn_no_nline = true;
        ConfigFileEntry.non_redundant_klines = true;
        ConfigFileEntry.stats_e_disabled = false;
        ConfigFileEntry.stats_o_oper_only = false;
        ConfigFileEntry.stats_k_oper_only = 1;  /* masked */
+       ConfigFileEntry.stats_l_oper_only = 1;  /* self */
        ConfigFileEntry.stats_i_oper_only = 1;  /* masked */
        ConfigFileEntry.stats_P_oper_only = false;
        ConfigFileEntry.stats_c_oper_only = false;
        ConfigFileEntry.stats_y_oper_only = false;
-       ConfigFileEntry.stats_h_oper_only = false;
        ConfigFileEntry.map_oper_only = true;
        ConfigFileEntry.operspy_admin_only = false;
        ConfigFileEntry.pace_wait = 10;
@@ -749,10 +776,8 @@ set_default_conf(void)
        ConfigFileEntry.use_propagated_bans = true;
        ConfigFileEntry.max_ratelimit_tokens = 30;
        ConfigFileEntry.away_interval = 30;
-
-#ifdef HAVE_LIBZ
-       ConfigFileEntry.compression_level = 4;
-#endif
+       ConfigFileEntry.tls_ciphers_oper_only = false;
+       ConfigFileEntry.oper_secure_only = false;
 
        ConfigFileEntry.oper_umodes = UMODE_LOCOPS | UMODE_SERVNOTICE |
                UMODE_OPERWALL | UMODE_WALLOP;
@@ -781,6 +806,8 @@ set_default_conf(void)
        ConfigChannel.channel_target_change = true;
        ConfigChannel.disable_local_channels = false;
        ConfigChannel.displayed_usercount = 3;
+       ConfigChannel.opmod_send_statusmsg = false;
+       ConfigChannel.ip_bans_through_vhost= true;
 
        ConfigChannel.autochanmodes = MODE_TOPICLIMIT | MODE_NOPRIVMSGS;
 
@@ -810,11 +837,12 @@ set_default_conf(void)
        ServerInfo.default_max_clients = MAXCONNECTIONS;
 
        ConfigFileEntry.nicklen = NICKLEN;
-       ConfigFileEntry.certfp_method = RB_SSL_CERTFP_METH_SHA1;
+       ConfigFileEntry.certfp_method = RB_SSL_CERTFP_METH_CERT_SHA1;
        ConfigFileEntry.hide_opers_in_whois = 0;
+       ConfigFileEntry.hide_opers = 0;
 
        if (!alias_dict)
-               alias_dict = rb_dictionary_create("alias", strcasecmp);
+               alias_dict = rb_dictionary_create("alias", rb_strcasecmp);
 }
 
 /*
@@ -835,7 +863,6 @@ read_conf(void)
        validate_conf();        /* Check to make sure some values are still okay. */
        /* Some global values are also loaded here. */
        check_class();          /* Make sure classes are valid */
-       privilegeset_delete_all_illegal();
        construct_cflags_strings();
 }
 
@@ -866,19 +893,19 @@ validate_conf(void)
                ircd_ssl_ok = false;
        } else {
                ircd_ssl_ok = true;
-               send_new_ssl_certs(ServerInfo.ssl_cert, ServerInfo.ssl_private_key, ServerInfo.ssl_dh_params, ServerInfo.ssl_cipher_list);
+               ssld_update_config();
        }
 
        if(ServerInfo.ssld_count > get_ssld_count())
        {
                int start = ServerInfo.ssld_count - get_ssld_count();
                /* start up additional ssld if needed */
-               start_ssldaemon(start, ServerInfo.ssl_cert, ServerInfo.ssl_private_key, ServerInfo.ssl_dh_params, ServerInfo.ssl_cipher_list);
+               start_ssldaemon(start);
        }
 
        if(ServerInfo.wsockd_count > get_wsockd_count())
        {
-               int start = ServerInfo.wsockd_count - get_ssld_count();
+               int start = ServerInfo.wsockd_count - get_wsockd_count();
                start_wsockd(start);
        }
 
@@ -919,6 +946,12 @@ validate_conf(void)
                splitmode = 0;
                splitchecking = 0;
        }
+
+       CharAttrs['&'] |= CHANPFX_C;
+       if (ConfigChannel.disable_local_channels)
+               CharAttrs['&'] &= ~CHANPFX_C;
+
+       chantypes_update();
 }
 
 /* add_temp_kline()
@@ -1046,31 +1079,52 @@ valid_wild_card(const char *luser, const char *lhost)
        return 0;
 }
 
-rb_dlink_node *
-find_prop_ban(unsigned int status, const char *user, const char *host)
+
+int cmp_prop_ban(const void *a_, const void *b_)
 {
-       rb_dlink_node *ptr;
-       struct ConfItem *aconf;
+       const struct ConfItem *a = a_, *b = b_;
+       int r;
 
-       RB_DLINK_FOREACH(ptr, prop_bans.head)
-       {
-               aconf = ptr->data;
+       if ((a->status & ~CONF_ILLEGAL) > (int)(b->status & ~CONF_ILLEGAL)) return 1;
+       if ((a->status & ~CONF_ILLEGAL) < (int)(b->status & ~CONF_ILLEGAL)) return -1;
 
-               if((aconf->status & ~CONF_ILLEGAL) == status &&
-                               (!user || !aconf->user ||
-                                !irccmp(aconf->user, user)) &&
-                               !irccmp(aconf->host, host))
-                       return ptr;
-       }
-       return NULL;
+       r = irccmp(a->host, b->host);
+       if (r) return r;
+
+       if (a->user && b->user)
+               return irccmp(a->user, b->user);
+
+       return 0;
 }
 
 void
-deactivate_conf(struct ConfItem *aconf, rb_dlink_node *ptr, time_t now)
+add_prop_ban(struct ConfItem *aconf)
 {
-       int i;
+       rb_dictionary_add(prop_bans_dict, aconf, aconf);
+}
+
+struct ConfItem *
+find_prop_ban(unsigned status, const char *user, const char *host)
+{
+       struct ConfItem key = {.status = status, .user = (char *)user, .host = (char *)host};
+       return rb_dictionary_retrieve(prop_bans_dict, &key);
+}
+
+void
+remove_prop_ban(struct ConfItem *aconf)
+{
+       rb_dictionary_delete(prop_bans_dict, aconf);
+}
+
+bool lookup_prop_ban(struct ConfItem *aconf)
+{
+       return rb_dictionary_retrieve(prop_bans_dict, aconf) == aconf;
+}
 
-       s_assert(ptr->data == aconf);
+void
+deactivate_conf(struct ConfItem *aconf, time_t now)
+{
+       int i;
 
        switch (aconf->status)
        {
@@ -1106,12 +1160,17 @@ deactivate_conf(struct ConfItem *aconf, rb_dlink_node *ptr, time_t now)
                        break;
        }
        if (aconf->lifetime != 0 && now < aconf->lifetime)
+       {
                aconf->status |= CONF_ILLEGAL;
+       }
        else
        {
                if (aconf->lifetime != 0)
-                       rb_dlinkDestroy(ptr, &prop_bans);
-               free_conf(aconf);
+                       remove_prop_ban(aconf);
+               if (aconf->clients == 0)
+                       free_conf(aconf);
+               else
+                       aconf->status |= CONF_ILLEGAL;
        }
 }
 
@@ -1121,13 +1180,11 @@ deactivate_conf(struct ConfItem *aconf, rb_dlink_node *ptr, time_t now)
 void
 replace_old_ban(struct ConfItem *aconf)
 {
-       rb_dlink_node *ptr;
        struct ConfItem *oldconf;
 
-       ptr = find_prop_ban(aconf->status, aconf->user, aconf->host);
-       if(ptr != NULL)
+       oldconf = find_prop_ban(aconf->status, aconf->user, aconf->host);
+       if (oldconf != NULL)
        {
-               oldconf = ptr->data;
                /* Remember at least as long as the old one. */
                if(oldconf->lifetime > aconf->lifetime)
                        aconf->lifetime = oldconf->lifetime;
@@ -1141,23 +1198,21 @@ replace_old_ban(struct ConfItem *aconf)
                        aconf->lifetime = aconf->hold;
                /* Tell deactivate_conf() to destroy it. */
                oldconf->lifetime = rb_current_time();
-               deactivate_conf(oldconf, ptr, oldconf->lifetime);
+               deactivate_conf(oldconf, oldconf->lifetime);
        }
 }
 
 static void
-expire_prop_bans(void *list)
+expire_prop_bans(void *unused)
 {
-       rb_dlink_node *ptr;
-       rb_dlink_node *next_ptr;
        struct ConfItem *aconf;
        time_t now;
+       rb_dictionary_iter state;
 
        now = rb_current_time();
-       RB_DLINK_FOREACH_SAFE(ptr, next_ptr, ((rb_dlink_list *) list)->head)
-       {
-               aconf = ptr->data;
 
+       RB_DICTIONARY_FOREACH(aconf, &state, prop_bans_dict)
+       {
                if(aconf->lifetime <= now ||
                                (aconf->hold <= now &&
                                 !(aconf->status & CONF_ILLEGAL)))
@@ -1173,7 +1228,7 @@ expire_prop_bans(void *list)
                                                     aconf->host ? aconf->host : "*");
 
                        /* will destroy or mark illegal */
-                       deactivate_conf(aconf, ptr, now);
+                       deactivate_conf(aconf, now);
                }
        }
 }
@@ -1250,26 +1305,22 @@ reorganise_temp_kd(void *list)
 /* const char* get_oper_name(struct Client *client_p)
  * Input: A client to find the active oper{} name for.
  * Output: The nick!user@host{oper} of the oper.
- *         "oper" is server name for remote opers
+ *         "oper" is server name for unknown opers
  * Side effects: None.
  */
-char *
+const char *
 get_oper_name(struct Client *client_p)
 {
        /* +5 for !,@,{,} and null */
-       static char buffer[NICKLEN + USERLEN + HOSTLEN + HOSTLEN + 5];
+       static char buffer[NAMELEN + USERLEN + HOSTLEN + MAX(HOSTLEN, OPERNICKLEN) + 5];
 
-       if(MyOper(client_p))
-       {
-               snprintf(buffer, sizeof(buffer), "%s!%s@%s{%s}",
-                               client_p->name, client_p->username,
-                               client_p->host, client_p->localClient->opername);
-               return buffer;
-       }
+       const char *opername = EmptyString(client_p->user->opername)
+                       ? client_p->servptr->name
+                       : client_p->user->opername;
 
-       snprintf(buffer, sizeof(buffer), "%s!%s@%s{%s}",
-                  client_p->name, client_p->username,
-                  client_p->host, client_p->servptr->name);
+       snprintf(buffer, sizeof buffer, "%s!%s@%s{%s}",
+                       client_p->name, client_p->username,
+                       client_p->host, opername);
        return buffer;
 }
 
@@ -1309,7 +1360,8 @@ get_user_ban_reason(struct ConfItem *aconf)
 {
        static char reasonbuf[BUFSIZE];
 
-       if (aconf->flags & CONF_FLAGS_TEMPORARY &&
+       if (!ConfigFileEntry.hide_tkdline_duration &&
+                       aconf->flags & CONF_FLAGS_TEMPORARY &&
                        (aconf->status == CONF_KILL || aconf->status == CONF_DLINE))
                snprintf(reasonbuf, sizeof reasonbuf,
                                "Temporary %c-line %d min. - ",
@@ -1343,7 +1395,7 @@ get_printable_kline(struct Client *source_p, struct ConfItem *aconf,
        *user = EmptyString(aconf->user) ? null : aconf->user;
        *reason = get_user_ban_reason(aconf);
 
-       if(!IsOper(source_p))
+       if(!IsOperGeneral(source_p))
                *oper_reason = NULL;
        else
        {
@@ -1398,7 +1450,7 @@ read_conf_files(bool cold)
                }
                else
                {
-                       sendto_realops_snomask(SNO_GENERAL, L_ALL,
+                       sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
                                             "Can't open file '%s' - aborting rehash!", filename);
                        return;
                }
@@ -1453,7 +1505,7 @@ clear_out_old_conf(void)
                MaxUsers(cltmp) = -1;
        }
 
-       clear_out_address_conf();
+       clear_out_address_conf(AC_CONFIG);
        clear_s_newconf();
 
        /* clean out module paths */
@@ -1496,6 +1548,16 @@ clear_out_old_conf(void)
        ConfigFileEntry.kline_reason = NULL;
        rb_free(ConfigFileEntry.sasl_service);
        ConfigFileEntry.sasl_service = NULL;
+       rb_free(ConfigFileEntry.drain_reason);
+       ConfigFileEntry.drain_reason = NULL;
+
+       if (ConfigFileEntry.hidden_caps != NULL)
+       {
+               for (size_t i = 0; ConfigFileEntry.hidden_caps[i] != NULL; i++)
+                       rb_free(ConfigFileEntry.hidden_caps[i]);
+               rb_free(ConfigFileEntry.hidden_caps);
+       }
+       ConfigFileEntry.hidden_caps = NULL;
 
        /* clean out log */
        rb_free(ConfigFileEntry.fname_userlog);
@@ -1530,9 +1592,7 @@ clear_out_old_conf(void)
                alias_dict = NULL;
        }
 
-       del_blacklist_all();
-
-       privilegeset_mark_all_illegal();
+       del_dnsbl_entry_all();
 
        /* OK, that should be everything... */
 }
@@ -1609,15 +1669,15 @@ conf_add_d_conf(struct ConfItem *aconf)
        }
 }
 
-static char *
-strip_tabs(char *dest, const char *src, size_t len)
+static void
+strip_tabs(char *dest, const char *src, size_t size)
 {
        char *d = dest;
 
        if(dest == NULL || src == NULL)
-               return NULL;
+               return;
 
-       rb_strlcpy(dest, src, len);
+       rb_strlcpy(dest, src, size);
 
        while(*d)
        {
@@ -1625,7 +1685,6 @@ strip_tabs(char *dest, const char *src, size_t len)
                        *d = ' ';
                d++;
        }
-       return dest;
 }
 
 /*
@@ -1640,10 +1699,10 @@ yyerror(const char *msg)
 {
        char newlinebuf[BUFSIZE];
 
-       strip_tabs(newlinebuf, linebuf, strlen(linebuf));
+       strip_tabs(newlinebuf, yy_linebuf, sizeof(newlinebuf));
 
        ierror("\"%s\", line %d: %s at '%s'", conffilebuf, lineno + 1, msg, newlinebuf);
-       sendto_realops_snomask(SNO_GENERAL, L_ALL, "\"%s\", line %d: %s at '%s'",
+       sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "\"%s\", line %d: %s at '%s'",
                             conffilebuf, lineno + 1, msg, newlinebuf);
 
 }