From 5e9a3f8674371a30dc1c94e6961ef86d09f846ee Mon Sep 17 00:00:00 2001 From: Elizabeth Myers Date: Tue, 12 Apr 2016 09:33:51 -0500 Subject: [PATCH] Change the way authd configures opm It's a bit of a hack, but better than before. Rather than rehashing (which could get us into an endless loop), we now segregate the configuration phase (creating entries ircd-side in case we restart authd later) and sending phases (when configure_authd() is called). Since we have to call configure_authd() no matter what (to send timeouts etc.) and we have to send this data to configure authd anyway, and sending duplicate data is bad, this is the only way I can think of for now. --- authd/providers/opm.c | 25 ++++++++- include/authproc.h | 30 +++++++++- ircd/authproc.c | 126 +++++++++++++++++++++++++++++++++++++++--- ircd/newconf.c | 11 ++-- ircd/s_user.c | 2 +- modules/m_stats.c | 2 +- 6 files changed, 175 insertions(+), 21 deletions(-) diff --git a/authd/providers/opm.c b/authd/providers/opm.c index 746604b5..3fbc53a6 100644 --- a/authd/providers/opm.c +++ b/authd/providers/opm.c @@ -98,11 +98,15 @@ static bool create_listener(const char *ip, uint16_t port); static int opm_timeout = OPM_TIMEOUT_DEFAULT; static bool opm_enable = false; -#define LISTEN_IPV4 0 -#define LISTEN_IPV6 1 +enum +{ + LISTEN_IPV4, + LISTEN_IPV6, + LISTEN_LAST, +}; /* IPv4 and IPv6 */ -static struct opm_listener listeners[2]; +static struct opm_listener listeners[LISTEN_LAST]; static inline protocol_t get_protocol_from_string(const char *str) @@ -891,12 +895,27 @@ delete_opm_scanner_all(const char *key __unused, int parc __unused, const char * opm_enable = false; } +static void +delete_opm_listener_all(const char *key __unused, int parc __unused, const char **parv __unused) +{ + if(listeners[LISTEN_IPV4].F != NULL) + rb_close(listeners[LISTEN_IPV4].F); + +#ifdef RB_IPV6 + if(listeners[LISTEN_IPV6].F != NULL) + rb_close(listeners[LISTEN_IPV6].F); +#endif + + memset(&listeners, 0, sizeof(listeners)); +} + struct auth_opts_handler opm_options[] = { { "opm_timeout", 1, add_conf_opm_timeout }, { "opm_enabled", 1, set_opm_enabled }, { "opm_listener", 2, set_opm_listener }, + { "opm_listener_del_all", 0, delete_opm_listener_all }, { "opm_scanner", 2, create_opm_scanner }, { "opm_scanner_del", 2, delete_opm_scanner }, { "opm_scanner_del_all", 0, delete_opm_scanner_all }, diff --git a/include/authproc.h b/include/authproc.h index 884983d1..00de574a 100644 --- a/include/authproc.h +++ b/include/authproc.h @@ -30,15 +30,38 @@ #include "rb_dictionary.h" #include "client.h" -struct blacklist_stats +struct BlacklistStats { uint8_t iptype; unsigned int hits; }; +struct OPMScanner +{ + char type[16]; /* Type of proxy */ + uint16_t port; /* Port */ + + rb_dlink_node node; +}; + +struct OPMListener +{ + char ipaddr[HOSTIPLEN]; /* Listener address */ + uint16_t port; /* Listener port */ +}; + +enum +{ + LISTEN_IPV4, + LISTEN_IPV6, + LISTEN_LAST, +}; + extern rb_helper *authd_helper; extern rb_dictionary *bl_stats; +extern rb_dlink_list opm_list; +extern struct OPMListener opm_listeners[LISTEN_LAST]; void init_authd(void); void configure_authd(void); @@ -58,10 +81,13 @@ void del_blacklist_all(void); bool set_authd_timeout(const char *key, int timeout); void ident_check_enable(bool enabled); +void conf_create_opm_listener(const char *ip, uint16_t port); void create_opm_listener(const char *ip, uint16_t port); -void opm_check_enable(bool enabled); +void conf_create_opm_proxy_scanner(const char *type, uint16_t port); void create_opm_proxy_scanner(const char *type, uint16_t port); void delete_opm_proxy_scanner(const char *type, uint16_t port); void delete_opm_proxy_scanner_all(void); +void delete_opm_listener_all(void); +void opm_check_enable(bool enabled); #endif diff --git a/ircd/authproc.c b/ircd/authproc.c index 2a0da431..a07db671 100644 --- a/ircd/authproc.c +++ b/ircd/authproc.c @@ -69,6 +69,9 @@ static struct ev_entry *timeout_ev; rb_dictionary *bl_stats; +rb_dlink_list opm_list; +struct OPMListener opm_listeners[LISTEN_LAST]; + static struct authd_cb authd_cmd_tab[256] = { ['A'] = { cmd_accept_client, 4 }, @@ -316,11 +319,41 @@ init_authd(void) void configure_authd(void) { - /* These will do for now */ + /* Timeouts */ set_authd_timeout("ident_timeout", GlobalSetOptions.ident_timeout); set_authd_timeout("rdns_timeout", ConfigFileEntry.connect_timeout); set_authd_timeout("rbl_timeout", ConfigFileEntry.connect_timeout); + ident_check_enable(!ConfigFileEntry.disable_auth); + + /* Configure OPM */ + if(rb_dlink_list_length(&opm_list) > 0 && + (opm_listeners[LISTEN_IPV4].ipaddr[0] != '\0' || + opm_listeners[LISTEN_IPV6].ipaddr[0] != '\0')) + { + rb_dlink_node *ptr; + + if(opm_listeners[LISTEN_IPV4].ipaddr[0] != '\0') + rb_helper_write(authd_helper, "O opm_listener %s %hu", + opm_listeners[LISTEN_IPV4].ipaddr, opm_listeners[LISTEN_IPV4].port); + +#ifdef RB_IPV6 + if(opm_listeners[LISTEN_IPV6].ipaddr[0] != '\0') + rb_helper_write(authd_helper, "O opm_listener %s %hu", + opm_listeners[LISTEN_IPV6].ipaddr, opm_listeners[LISTEN_IPV6].port); +#endif + + RB_DLINK_FOREACH(ptr, opm_list.head) + { + struct OPMScanner *scanner = ptr->data; + rb_helper_write(authd_helper, "O opm_scanner %s %hu", + scanner->type, scanner->port); + } + + opm_check_enable(true); + } + else + opm_check_enable(false); } static void @@ -346,7 +379,6 @@ restart_authd_cb(rb_helper * helper) start_authd(); configure_authd(); - rehash(false); /* FIXME - needed to reload authd configuration */ } void @@ -507,7 +539,7 @@ void add_blacklist(const char *host, const char *reason, uint8_t iptype, rb_dlink_list *filters) { rb_dlink_node *ptr; - struct blacklist_stats *stats = rb_malloc(sizeof(struct blacklist_stats)); + struct BlacklistStats *stats = rb_malloc(sizeof(struct BlacklistStats)); char filterbuf[BUFSIZE] = "*"; size_t s = 0; @@ -541,7 +573,12 @@ add_blacklist(const char *host, const char *reason, uint8_t iptype, rb_dlink_lis void del_blacklist(const char *host) { - rb_free(rb_dictionary_delete(bl_stats, host)); + struct BlacklistStats *stats = rb_dictionary_retrieve(bl_stats, host); + if(stats != NULL) + { + rb_dictionary_delete(bl_stats, host); + rb_free(stats); + } rb_helper_write(authd_helper, "O rbl_del %s", host); } @@ -550,7 +587,7 @@ del_blacklist(const char *host) void del_blacklist_all(void) { - struct blacklist_stats *stats; + struct BlacklistStats *stats; rb_dictionary_iter iter; RB_DICTIONARY_FOREACH(stats, &iter, bl_stats) @@ -580,11 +617,16 @@ ident_check_enable(bool enabled) rb_helper_write(authd_helper, "O ident_enabled %d", enabled ? 1 : 0); } -/* Create an OPM listener */ +/* Create an OPM listener + * XXX - This is a big nasty hack, but it avoids resending duplicate data when + * configure_authd() is called. + */ void -create_opm_listener(const char *ip, uint16_t port) +conf_create_opm_listener(const char *ip, uint16_t port) { char ipbuf[HOSTIPLEN]; + struct OPMListener *listener; + rb_strlcpy(ipbuf, ip, sizeof(ipbuf)); if(ipbuf[0] == ':') { @@ -592,7 +634,34 @@ create_opm_listener(const char *ip, uint16_t port) ipbuf[0] = '0'; } - rb_helper_write(authd_helper, "O opm_listener %s %hu", ipbuf, port); + /* I am much too lazy to use rb_inet_pton and GET_SS_FAMILY for now --Elizafox */ + listener = &opm_listeners[(strchr(ipbuf, ':') != NULL ? LISTEN_IPV6 : LISTEN_IPV4)]; + rb_strlcpy(listener->ipaddr, ipbuf, sizeof(listener->ipaddr)); + listener->port = port; +} + +void +create_opm_listener(const char *ip, uint16_t port) +{ + char ipbuf[HOSTIPLEN]; + + /* XXX duplicated in conf_create_opm_listener */ + rb_strlcpy(ipbuf, ip, sizeof(ipbuf)); + if(ipbuf[0] == ':') + { + memmove(ipbuf + 1, ipbuf, sizeof(ipbuf) - 1); + ipbuf[0] = '0'; + } + + conf_create_opm_listener(ip, port); + rb_helper_write(authd_helper, "O opm_listener %s %hu", ip, port); +} + +void +delete_opm_listener_all(void) +{ + memset(&opm_listeners, 0, sizeof(opm_listeners)); + rb_helper_write(authd_helper, "O opm_listener_del_all"); } /* Disable all OPM scans */ @@ -602,21 +671,60 @@ opm_check_enable(bool enabled) rb_helper_write(authd_helper, "O opm_enabled %d", enabled ? 1 : 0); } -/* Create an OPM proxy scanner */ +/* Create an OPM proxy scanner + * XXX - This is a big nasty hack, but it avoids resending duplicate data when + * configure_authd() is called. + */ +void +conf_create_opm_proxy_scanner(const char *type, uint16_t port) +{ + struct OPMScanner *scanner = rb_malloc(sizeof(struct OPMScanner)); + + rb_strlcpy(scanner->type, type, sizeof(scanner->type)); + scanner->port = port; + rb_dlinkAdd(scanner, &scanner->node, &opm_list); +} + void create_opm_proxy_scanner(const char *type, uint16_t port) { + conf_create_opm_proxy_scanner(type, port); rb_helper_write(authd_helper, "O opm_scanner %s %hu", type, port); } void delete_opm_proxy_scanner(const char *type, uint16_t port) { + rb_dlink_node *ptr, *nptr; + + RB_DLINK_FOREACH_SAFE(ptr, nptr, opm_list.head) + { + struct OPMScanner *scanner = ptr->data; + + if(rb_strncasecmp(scanner->type, type, sizeof(scanner->type)) == 0 && + scanner->port == port) + { + rb_dlinkDelete(ptr, &opm_list); + rb_free(scanner); + break; + } + } + rb_helper_write(authd_helper, "O opm_scanner_del %s %hu", type, port); } void delete_opm_proxy_scanner_all(void) { + rb_dlink_node *ptr, *nptr; + + RB_DLINK_FOREACH_SAFE(ptr, nptr, opm_list.head) + { + struct OPMScanner *scanner = ptr->data; + + rb_dlinkDelete(ptr, &opm_list); + rb_free(scanner); + } + rb_helper_write(authd_helper, "O opm_scanner_del_all"); } diff --git a/ircd/newconf.c b/ircd/newconf.c index 79c76bac..01af2eb7 100644 --- a/ircd/newconf.c +++ b/ircd/newconf.c @@ -2043,6 +2043,7 @@ conf_begin_opm(struct TopConf *tc) yy_opm_address_ipv4 = yy_opm_address_ipv6 = NULL; yy_opm_port_ipv4 = yy_opm_port_ipv6 = yy_opm_timeout = 0; delete_opm_proxy_scanner_all(); + delete_opm_listener_all(); return 0; } @@ -2062,28 +2063,28 @@ conf_end_opm(struct TopConf *tc) if(yy_opm_port_ipv4 > 0) { if(yy_opm_address_ipv4 != NULL) - create_opm_listener(yy_opm_address_ipv4, yy_opm_port_ipv4); + conf_create_opm_listener(yy_opm_address_ipv4, yy_opm_port_ipv4); else { char ip[HOSTIPLEN]; if(!rb_inet_ntop_sock((struct sockaddr *)&ServerInfo.ip, ip, sizeof(ip))) conf_report_error("No opm::listen_ipv4 nor serverinfo::vhost directive; cannot listen on IPv4"); else - create_opm_listener(ip, yy_opm_port_ipv4); + conf_create_opm_listener(ip, yy_opm_port_ipv4); } } if(yy_opm_port_ipv6 > 0) { if(yy_opm_address_ipv6 != NULL) - create_opm_listener(yy_opm_address_ipv6, yy_opm_port_ipv6); + conf_create_opm_listener(yy_opm_address_ipv6, yy_opm_port_ipv6); else { char ip[HOSTIPLEN]; if(!rb_inet_ntop_sock((struct sockaddr *)&ServerInfo.ip6, ip, sizeof(ip))) conf_report_error("No opm::listen_ipv6 nor serverinfo::vhost directive; cannot listen on IPv6"); else - create_opm_listener(ip, yy_opm_port_ipv6); + conf_create_opm_listener(ip, yy_opm_port_ipv6); } } @@ -2272,7 +2273,7 @@ conf_set_opm_scan_ports_all(void *data, const char *node, const char *type) conf_report_error("%s argument is not an integer -- ignoring.", node); continue; } - + if(args->v.number > 65535 || args->v.number <= 0) { conf_report_error("%s argument is not an integer between 1 and 65535 -- ignoring.", node); diff --git a/ircd/s_user.c b/ircd/s_user.c index bed46654..18104c6a 100644 --- a/ircd/s_user.c +++ b/ircd/s_user.c @@ -215,7 +215,7 @@ authd_check(struct Client *client_p, struct Client *source_p) { case 'B': /* Blacklists */ { - struct blacklist_stats *stats; + struct BlacklistStats *stats; char *blacklist = source_p->preClient->auth.data; if((stats = rb_dictionary_retrieve(bl_stats, blacklist)) != NULL) diff --git a/modules/m_stats.c b/modules/m_stats.c index 7d9ac86f..4e21ab4c 100644 --- a/modules/m_stats.c +++ b/modules/m_stats.c @@ -753,7 +753,7 @@ static void stats_dnsbl(struct Client *source_p) { rb_dictionary_iter iter; - struct blacklist_stats *stats; + struct BlacklistStats *stats; RB_DICTIONARY_FOREACH(stats, &iter, bl_stats) {