X-Git-Url: https://jfr.im/git/solanum.git/blobdiff_plain/c46a4ecd97293e284031a09f3aefea83cb858ead..d513218a9e3feb262b7966fbca2a0ff9da5f6aa8:/src/newconf.c diff --git a/src/newconf.c b/src/newconf.c index afa06e33..717cfcf4 100644 --- a/src/newconf.c +++ b/src/newconf.c @@ -29,13 +29,14 @@ #include "blacklist.h" #include "sslproc.h" #include "privilege.h" +#include "chmode.h" #define CF_TYPE(x) ((x) & CF_MTYPE) static int yy_defer_accept = 1; struct TopConf *conf_cur_block; -static char *conf_cur_block_name; +static char *conf_cur_block_name = NULL; static rb_dlink_list conf_items; @@ -58,13 +59,14 @@ static char *yy_blacklist_host = NULL; static char *yy_blacklist_reason = NULL; static int yy_blacklist_ipv4 = 1; static int yy_blacklist_ipv6 = 0; +static rb_dlink_list yy_blacklist_filters; static char *yy_privset_extends = NULL; static const char * conf_strtype(int type) { - switch (type & CF_MTYPE) + switch (CF_TYPE(type)) { case CF_INT: return "integer value"; @@ -82,7 +84,7 @@ conf_strtype(int type) } int -add_top_conf(const char *name, int (*sfunc) (struct TopConf *), +add_top_conf(const char *name, int (*sfunc) (struct TopConf *), int (*efunc) (struct TopConf *), struct ConfEntry *items) { struct TopConf *tc; @@ -276,7 +278,7 @@ conf_set_serverinfo_nicklen(void *data) else if (ConfigFileEntry.nicklen < 9 + 1) { conf_report_error("Warning -- serverinfo::nicklen is too low (%u) -- forcing 9", - ConfigFileEntry.nicklen); + ConfigFileEntry.nicklen - 1); ConfigFileEntry.nicklen = 9 + 1; } } @@ -289,10 +291,8 @@ conf_set_modules_module(void *data) m_bn = rb_basename((char *) data); - if(findmodule_byname(m_bn) != -1) - return; - - load_one_module((char *) data, 0); + if(findmodule_byname(m_bn) == -1) + load_one_module((char *) data, 0); rb_free(m_bn); #else @@ -425,7 +425,7 @@ set_modes_from_table(int *modes, const char *whatis, struct mode_table *tab, con int dir = 1; int mode; - if((args->type & CF_MTYPE) != CF_STRING) + if(CF_TYPE(args->type) != CF_STRING) { conf_report_error("Warning -- %s is not a string; ignoring.", whatis); continue; @@ -604,7 +604,7 @@ conf_end_oper(struct TopConf *tc) yy_tmpoper->name); return 0; } - + yy_tmpoper->rsa_pubkey = (RSA *) PEM_read_bio_RSA_PUBKEY(file, NULL, 0, NULL); @@ -858,7 +858,7 @@ conf_set_listen_port_both(void *data, int ssl) conf_parm_t *args = data; for (; args; args = args->next) { - if((args->type & CF_MTYPE) != CF_INT) + if(CF_TYPE(args->type) != CF_INT) { conf_report_error ("listener::port argument is not an integer " "-- ignoring."); @@ -866,9 +866,9 @@ conf_set_listen_port_both(void *data, int ssl) } if(listener_address == NULL) { - add_listener(args->v.number, listener_address, AF_INET, ssl, yy_defer_accept); + add_listener(args->v.number, listener_address, AF_INET, ssl, ssl || yy_defer_accept); #ifdef RB_IPV6 - add_listener(args->v.number, listener_address, AF_INET6, ssl, yy_defer_accept); + add_listener(args->v.number, listener_address, AF_INET6, ssl, ssl || yy_defer_accept); #endif } else @@ -877,12 +877,12 @@ conf_set_listen_port_both(void *data, int ssl) #ifdef RB_IPV6 if(strchr(listener_address, ':') != NULL) family = AF_INET6; - else + else #endif family = AF_INET; - - add_listener(args->v.number, listener_address, family, ssl, yy_defer_accept); - + + add_listener(args->v.number, listener_address, family, ssl, ssl || yy_defer_accept); + } } @@ -968,7 +968,7 @@ conf_end_auth(struct TopConf *tc) if(yy_aconf->spasswd) yy_tmp->spasswd = rb_strdup(yy_aconf->spasswd); - + /* this will always exist.. */ yy_tmp->info.name = rb_strdup(yy_aconf->info.name); @@ -983,9 +983,11 @@ conf_end_auth(struct TopConf *tc) conf_add_class_to_conf(yy_tmp); - if (find_exact_conf_by_address("*", CONF_CLIENT, "*")) + if ((found_conf = find_exact_conf_by_address("*", CONF_CLIENT, "*")) && found_conf->spasswd == NULL) conf_report_error("Ignoring redundant auth block (after *@*)"); - else if (find_exact_conf_by_address(yy_tmp->host, CONF_CLIENT, yy_tmp->user)) + else if ((found_conf = find_exact_conf_by_address(yy_tmp->host, CONF_CLIENT, yy_tmp->user)) && + (!found_conf->spasswd || (yy_tmp->spasswd && + 0 == irccmp(found_conf->spasswd, yy_tmp->spasswd)))) conf_report_error("Ignoring duplicate auth block for %s@%s", yy_tmp->user, yy_tmp->host); else @@ -1178,7 +1180,7 @@ conf_set_shared_oper(void *data) if(args->next != NULL) { - if((args->type & CF_MTYPE) != CF_QSTRING) + if(CF_TYPE(args->type) != CF_QSTRING) { conf_report_error("Ignoring shared::oper -- server is not a qstring"); return; @@ -1190,7 +1192,7 @@ conf_set_shared_oper(void *data) else yy_shared->server = rb_strdup("*"); - if((args->type & CF_MTYPE) != CF_QSTRING) + if(CF_TYPE(args->type) != CF_QSTRING) { conf_report_error("Ignoring shared::oper -- oper is not a qstring"); return; @@ -1634,7 +1636,7 @@ conf_set_general_default_umodes(void *data) } break; } - } + } } static void @@ -1643,6 +1645,24 @@ conf_set_general_oper_umodes(void *data) set_modes_from_table(&ConfigFileEntry.oper_umodes, "umode", umode_table, data); } +static void +conf_set_general_certfp_method(void *data) +{ + char *method = data; + + if (!strcasecmp(method, "sha1")) + ConfigFileEntry.certfp_method = RB_SSL_CERTFP_METH_SHA1; + else if (!strcasecmp(method, "sha256")) + ConfigFileEntry.certfp_method = RB_SSL_CERTFP_METH_SHA256; + else if (!strcasecmp(method, "sha512")) + ConfigFileEntry.certfp_method = RB_SSL_CERTFP_METH_SHA512; + else + { + ConfigFileEntry.certfp_method = RB_SSL_CERTFP_METH_SHA1; + conf_report_error("Ignoring general::certfp_method -- bogus certfp method %s", method); + } +} + static void conf_set_general_oper_only_umodes(void *data) { @@ -1691,7 +1711,6 @@ conf_set_serverhide_links_delay(void *data) static void conf_set_service_name(void *data) { - struct Client *target_p; const char *s; char *tmp; int dots = 0; @@ -1779,9 +1798,60 @@ conf_set_alias_target(void *data) yy_alias->target = rb_strdup(data); } +static void +conf_set_channel_autochanmodes(void *data) +{ + char *pm; + int what = MODE_ADD; + + ConfigChannel.autochanmodes = 0; + for (pm = (char *) data; *pm; pm++) + { + switch (*pm) + { + case '+': + what = MODE_ADD; + break; + case '-': + what = MODE_DEL; + break; + + default: + if (chmode_table[(unsigned char) *pm].set_func == chm_simple) + { + if (what == MODE_ADD) + ConfigChannel.autochanmodes |= chmode_table[(unsigned char) *pm].mode_type; + else + ConfigChannel.autochanmodes &= ~chmode_table[(unsigned char) *pm].mode_type; + } + else + { + conf_report_error("channel::autochanmodes -- Invalid channel mode %c", *pm); + continue; + } + break; + } + } +} + +/* XXX for below */ +static void conf_set_blacklist_reason(void *data); + static void conf_set_blacklist_host(void *data) { + if (yy_blacklist_host) + { + conf_report_error("blacklist::host %s overlaps existing host %s", + (char *)data, yy_blacklist_host); + + /* Cleanup */ + conf_set_blacklist_reason(NULL); + return; + } + + yy_blacklist_ipv4 = 1; + yy_blacklist_ipv6 = 0; yy_blacklist_host = rb_strdup(data); } @@ -1813,13 +1883,93 @@ conf_set_blacklist_type(void *data) } } +static void +conf_set_blacklist_matches(void *data) +{ + conf_parm_t *args = data; + + for (; args; args = args->next) + { + struct BlacklistFilter *filter; + char *str = args->v.string; + char *p; + int type = BLACKLIST_FILTER_LAST; + + if (CF_TYPE(args->type) != CF_QSTRING) + { + conf_report_error("blacklist::matches -- must be quoted string"); + continue; + } + + if (str == NULL) + { + conf_report_error("blacklist::matches -- invalid entry"); + continue; + } + + if (strlen(str) > HOSTIPLEN) + { + conf_report_error("blacklist::matches has an entry too long: %s", + str); + continue; + } + + for (p = str; *p != '\0'; p++) + { + /* Check for validity */ + if (*p == '.') + type = BLACKLIST_FILTER_ALL; + else if (!isalnum((unsigned char)*p)) + { + conf_report_error("blacklist::matches has invalid IP match entry %s", + str); + type = 0; + break; + } + } + + if (type == BLACKLIST_FILTER_ALL) + { + /* Basic IP sanity check */ + struct rb_sockaddr_storage tmp; + if (rb_inet_pton(AF_INET, str, &tmp) <= 0) + { + conf_report_error("blacklist::matches has invalid IP match entry %s", + str); + continue; + } + } + else if (type == BLACKLIST_FILTER_LAST) + { + /* Verify it's the correct length */ + if (strlen(str) > 3) + { + conf_report_error("blacklist::matches has invalid octet match entry %s", + str); + continue; + } + } + else + { + continue; /* Invalid entry */ + } + + filter = rb_malloc(sizeof(struct BlacklistFilter)); + filter->type = type; + rb_strlcpy(filter->filterstr, str, sizeof(filter->filterstr)); + + rb_dlinkAdd(filter, &filter->node, &yy_blacklist_filters); + } +} + static void conf_set_blacklist_reason(void *data) { - yy_blacklist_reason = rb_strdup(data); + rb_dlink_node *ptr, *nptr; - if (yy_blacklist_host && yy_blacklist_reason) + if (yy_blacklist_host && data) { + yy_blacklist_reason = rb_strdup(data); if (yy_blacklist_ipv6) { /* Make sure things fit (64 = alnum count + dots) */ @@ -1842,16 +1992,30 @@ conf_set_blacklist_reason(void *data) } } - new_blacklist(yy_blacklist_host, yy_blacklist_reason, yy_blacklist_ipv4, yy_blacklist_ipv6); + new_blacklist(yy_blacklist_host, yy_blacklist_reason, yy_blacklist_ipv4, yy_blacklist_ipv6, + &yy_blacklist_filters); + } cleanup_bl: - rb_free(yy_blacklist_host); - rb_free(yy_blacklist_reason); - yy_blacklist_host = NULL; - yy_blacklist_reason = NULL; - yy_blacklist_ipv4 = 1; - yy_blacklist_ipv6 = 0; + if (data == NULL) + { + RB_DLINK_FOREACH_SAFE(ptr, nptr, yy_blacklist_filters.head) + { + rb_dlinkDelete(ptr, &yy_blacklist_filters); + rb_free(ptr); + } } + else + { + yy_blacklist_filters = (rb_dlink_list){ NULL, NULL, 0 }; + } + + rb_free(yy_blacklist_host); + rb_free(yy_blacklist_reason); + yy_blacklist_host = NULL; + yy_blacklist_reason = NULL; + yy_blacklist_ipv4 = 1; + yy_blacklist_ipv6 = 0; } /* public functions */ @@ -1901,11 +2065,13 @@ conf_start_block(char *block, char *name) int conf_end_block(struct TopConf *tc) { + int ret = 0; if(tc->tc_efunc) - return tc->tc_efunc(tc); + ret = tc->tc_efunc(tc); rb_free(conf_cur_block_name); - return 0; + conf_cur_block_name = NULL; + return ret; } static void @@ -1928,7 +2094,7 @@ conf_set_generic_string(void *data, int len, void *location) } int -conf_call_set(struct TopConf *tc, char *item, conf_parm_t * value, int type) +conf_call_set(struct TopConf *tc, char *item, conf_parm_t * value) { struct ConfEntry *cf; conf_parm_t *cp; @@ -1957,7 +2123,7 @@ conf_call_set(struct TopConf *tc, char *item, conf_parm_t * value, int type) if(CF_TYPE(value->v.list->type) != CF_TYPE(cf->cf_type)) { - /* if it expects a string value, but we got a yesno, + /* if it expects a string value, but we got a yesno, * convert it back */ if((CF_TYPE(value->v.list->type) == CF_YESNO) && @@ -2033,7 +2199,7 @@ add_conf_item(const char *topconf, const char *name, int type, void (*func) (voi if((tc = find_top_conf(topconf)) == NULL) return -1; - if((cf = find_conf_item(tc, name)) != NULL) + if(find_conf_item(tc, name) != NULL) return -1; cf = rb_malloc(sizeof(struct ConfEntry)); @@ -2074,7 +2240,6 @@ remove_conf_item(const char *topconf, const char *name) static struct ConfEntry conf_serverinfo_table[] = { { "description", CF_QSTRING, NULL, 0, &ServerInfo.description }, - { "network_desc", CF_QSTRING, NULL, 0, &ServerInfo.network_desc }, { "hub", CF_YESNO, NULL, 0, &ServerInfo.hub }, { "network_name", CF_QSTRING, conf_set_serverinfo_network_name, 0, NULL }, @@ -2085,8 +2250,9 @@ static struct ConfEntry conf_serverinfo_table[] = { "ssl_private_key", CF_QSTRING, NULL, 0, &ServerInfo.ssl_private_key }, { "ssl_ca_cert", CF_QSTRING, NULL, 0, &ServerInfo.ssl_ca_cert }, - { "ssl_cert", CF_QSTRING, NULL, 0, &ServerInfo.ssl_cert }, + { "ssl_cert", CF_QSTRING, NULL, 0, &ServerInfo.ssl_cert }, { "ssl_dh_params", CF_QSTRING, NULL, 0, &ServerInfo.ssl_dh_params }, + { "ssl_cipher_list", CF_QSTRING, NULL, 0, &ServerInfo.ssl_cipher_list }, { "ssld_count", CF_INT, NULL, 0, &ServerInfo.ssld_count }, { "default_max_clients",CF_INT, NULL, 0, &ServerInfo.default_max_clients }, @@ -2200,10 +2366,10 @@ static struct ConfEntry conf_general_table[] = { "default_operstring", CF_QSTRING, NULL, REALLEN, &ConfigFileEntry.default_operstring }, { "default_adminstring",CF_QSTRING, NULL, REALLEN, &ConfigFileEntry.default_adminstring }, { "servicestring", CF_QSTRING, NULL, REALLEN, &ConfigFileEntry.servicestring }, - { "egdpool_path", CF_QSTRING, NULL, PATH_MAX, &ConfigFileEntry.egdpool_path }, { "kline_reason", CF_QSTRING, NULL, REALLEN, &ConfigFileEntry.kline_reason }, { "identify_service", CF_QSTRING, NULL, REALLEN, &ConfigFileEntry.identifyservice }, { "identify_command", CF_QSTRING, NULL, REALLEN, &ConfigFileEntry.identifycommand }, + { "sasl_service", CF_QSTRING, NULL, REALLEN, &ConfigFileEntry.sasl_service }, { "anti_spam_exit_message_time", CF_TIME, NULL, 0, &ConfigFileEntry.anti_spam_exit_message_time }, { "disable_fake_channels", CF_YESNO, NULL, 0, &ConfigFileEntry.disable_fake_channels }, @@ -2255,7 +2421,6 @@ static struct ConfEntry conf_general_table[] = { "stats_y_oper_only", CF_YESNO, NULL, 0, &ConfigFileEntry.stats_y_oper_only }, { "target_change", CF_YESNO, NULL, 0, &ConfigFileEntry.target_change }, { "ts_max_delta", CF_TIME, NULL, 0, &ConfigFileEntry.ts_max_delta }, - { "use_egd", CF_YESNO, NULL, 0, &ConfigFileEntry.use_egd }, { "ts_warn_delta", CF_TIME, NULL, 0, &ConfigFileEntry.ts_warn_delta }, { "use_whois_actually", CF_YESNO, NULL, 0, &ConfigFileEntry.use_whois_actually }, { "warn_no_nline", CF_YESNO, NULL, 0, &ConfigFileEntry.warn_no_nline }, @@ -2267,6 +2432,7 @@ static struct ConfEntry conf_general_table[] = { "client_flood_message_time", CF_INT, NULL, 0, &ConfigFileEntry.client_flood_message_time }, { "max_ratelimit_tokens", CF_INT, NULL, 0, &ConfigFileEntry.max_ratelimit_tokens }, { "away_interval", CF_INT, NULL, 0, &ConfigFileEntry.away_interval }, + { "certfp_method", CF_STRING, conf_set_general_certfp_method, 0, NULL }, { "\0", 0, NULL, 0, NULL } }; @@ -2291,6 +2457,8 @@ static struct ConfEntry conf_channel_table[] = { "resv_forcepart", CF_YESNO, NULL, 0, &ConfigChannel.resv_forcepart }, { "channel_target_change", CF_YESNO, NULL, 0, &ConfigChannel.channel_target_change }, { "disable_local_channels", CF_YESNO, NULL, 0, &ConfigChannel.disable_local_channels }, + { "autochanmodes", CF_QSTRING, conf_set_channel_autochanmodes, 0, NULL }, + { "displayed_usercount", CF_INT, NULL, 0, &ConfigChannel.displayed_usercount }, { "\0", 0, NULL, 0, NULL } }; @@ -2328,7 +2496,7 @@ newconf_init() add_top_conf("auth", conf_begin_auth, conf_end_auth, conf_auth_table); add_top_conf("shared", conf_cleanup_shared, conf_cleanup_shared, NULL); - add_conf_item("shared", "oper", CF_QSTRING|CF_FLIST, conf_set_shared_oper); + add_conf_item("shared", "oper", CF_QSTRING | CF_FLIST, conf_set_shared_oper); add_conf_item("shared", "flags", CF_STRING | CF_FLIST, conf_set_shared_flags); add_top_conf("connect", conf_begin_connect, conf_end_connect, conf_connect_table); @@ -2354,5 +2522,6 @@ newconf_init() add_top_conf("blacklist", NULL, NULL, NULL); add_conf_item("blacklist", "host", CF_QSTRING, conf_set_blacklist_host); add_conf_item("blacklist", "type", CF_STRING | CF_FLIST, conf_set_blacklist_type); + add_conf_item("blacklist", "matches", CF_QSTRING | CF_FLIST, conf_set_blacklist_matches); add_conf_item("blacklist", "reject_reason", CF_QSTRING, conf_set_blacklist_reason); }