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.
This commit is contained in:
Elizabeth Myers 2016-04-12 09:33:51 -05:00
parent 5eb8ce0679
commit 5e9a3f8674
No known key found for this signature in database
GPG key ID: 1A10EF78D83E317B
6 changed files with 175 additions and 21 deletions

View file

@ -98,11 +98,15 @@ static bool create_listener(const char *ip, uint16_t port);
static int opm_timeout = OPM_TIMEOUT_DEFAULT; static int opm_timeout = OPM_TIMEOUT_DEFAULT;
static bool opm_enable = false; static bool opm_enable = false;
#define LISTEN_IPV4 0 enum
#define LISTEN_IPV6 1 {
LISTEN_IPV4,
LISTEN_IPV6,
LISTEN_LAST,
};
/* IPv4 and IPv6 */ /* IPv4 and IPv6 */
static struct opm_listener listeners[2]; static struct opm_listener listeners[LISTEN_LAST];
static inline protocol_t static inline protocol_t
get_protocol_from_string(const char *str) 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; 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[] = struct auth_opts_handler opm_options[] =
{ {
{ "opm_timeout", 1, add_conf_opm_timeout }, { "opm_timeout", 1, add_conf_opm_timeout },
{ "opm_enabled", 1, set_opm_enabled }, { "opm_enabled", 1, set_opm_enabled },
{ "opm_listener", 2, set_opm_listener }, { "opm_listener", 2, set_opm_listener },
{ "opm_listener_del_all", 0, delete_opm_listener_all },
{ "opm_scanner", 2, create_opm_scanner }, { "opm_scanner", 2, create_opm_scanner },
{ "opm_scanner_del", 2, delete_opm_scanner }, { "opm_scanner_del", 2, delete_opm_scanner },
{ "opm_scanner_del_all", 0, delete_opm_scanner_all }, { "opm_scanner_del_all", 0, delete_opm_scanner_all },

View file

@ -30,15 +30,38 @@
#include "rb_dictionary.h" #include "rb_dictionary.h"
#include "client.h" #include "client.h"
struct blacklist_stats struct BlacklistStats
{ {
uint8_t iptype; uint8_t iptype;
unsigned int hits; 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_helper *authd_helper;
extern rb_dictionary *bl_stats; extern rb_dictionary *bl_stats;
extern rb_dlink_list opm_list;
extern struct OPMListener opm_listeners[LISTEN_LAST];
void init_authd(void); void init_authd(void);
void configure_authd(void); void configure_authd(void);
@ -58,10 +81,13 @@ void del_blacklist_all(void);
bool set_authd_timeout(const char *key, int timeout); bool set_authd_timeout(const char *key, int timeout);
void ident_check_enable(bool enabled); 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 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 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(const char *type, uint16_t port);
void delete_opm_proxy_scanner_all(void); void delete_opm_proxy_scanner_all(void);
void delete_opm_listener_all(void);
void opm_check_enable(bool enabled);
#endif #endif

View file

@ -69,6 +69,9 @@ static struct ev_entry *timeout_ev;
rb_dictionary *bl_stats; rb_dictionary *bl_stats;
rb_dlink_list opm_list;
struct OPMListener opm_listeners[LISTEN_LAST];
static struct authd_cb authd_cmd_tab[256] = static struct authd_cb authd_cmd_tab[256] =
{ {
['A'] = { cmd_accept_client, 4 }, ['A'] = { cmd_accept_client, 4 },
@ -316,11 +319,41 @@ init_authd(void)
void void
configure_authd(void) configure_authd(void)
{ {
/* These will do for now */ /* Timeouts */
set_authd_timeout("ident_timeout", GlobalSetOptions.ident_timeout); set_authd_timeout("ident_timeout", GlobalSetOptions.ident_timeout);
set_authd_timeout("rdns_timeout", ConfigFileEntry.connect_timeout); set_authd_timeout("rdns_timeout", ConfigFileEntry.connect_timeout);
set_authd_timeout("rbl_timeout", ConfigFileEntry.connect_timeout); set_authd_timeout("rbl_timeout", ConfigFileEntry.connect_timeout);
ident_check_enable(!ConfigFileEntry.disable_auth); 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 static void
@ -346,7 +379,6 @@ restart_authd_cb(rb_helper * helper)
start_authd(); start_authd();
configure_authd(); configure_authd();
rehash(false); /* FIXME - needed to reload authd configuration */
} }
void void
@ -507,7 +539,7 @@ void
add_blacklist(const char *host, const char *reason, uint8_t iptype, rb_dlink_list *filters) add_blacklist(const char *host, const char *reason, uint8_t iptype, rb_dlink_list *filters)
{ {
rb_dlink_node *ptr; 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] = "*"; char filterbuf[BUFSIZE] = "*";
size_t s = 0; size_t s = 0;
@ -541,7 +573,12 @@ add_blacklist(const char *host, const char *reason, uint8_t iptype, rb_dlink_lis
void void
del_blacklist(const char *host) 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); rb_helper_write(authd_helper, "O rbl_del %s", host);
} }
@ -550,7 +587,7 @@ del_blacklist(const char *host)
void void
del_blacklist_all(void) del_blacklist_all(void)
{ {
struct blacklist_stats *stats; struct BlacklistStats *stats;
rb_dictionary_iter iter; rb_dictionary_iter iter;
RB_DICTIONARY_FOREACH(stats, &iter, bl_stats) 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); 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 void
create_opm_listener(const char *ip, uint16_t port) conf_create_opm_listener(const char *ip, uint16_t port)
{ {
char ipbuf[HOSTIPLEN]; char ipbuf[HOSTIPLEN];
struct OPMListener *listener;
rb_strlcpy(ipbuf, ip, sizeof(ipbuf)); rb_strlcpy(ipbuf, ip, sizeof(ipbuf));
if(ipbuf[0] == ':') if(ipbuf[0] == ':')
{ {
@ -592,7 +634,34 @@ create_opm_listener(const char *ip, uint16_t port)
ipbuf[0] = '0'; 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 */ /* 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); 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 void
create_opm_proxy_scanner(const char *type, uint16_t port) 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); rb_helper_write(authd_helper, "O opm_scanner %s %hu", type, port);
} }
void void
delete_opm_proxy_scanner(const char *type, uint16_t port) 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); rb_helper_write(authd_helper, "O opm_scanner_del %s %hu", type, port);
} }
void void
delete_opm_proxy_scanner_all(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"); rb_helper_write(authd_helper, "O opm_scanner_del_all");
} }

View file

@ -2043,6 +2043,7 @@ conf_begin_opm(struct TopConf *tc)
yy_opm_address_ipv4 = yy_opm_address_ipv6 = NULL; yy_opm_address_ipv4 = yy_opm_address_ipv6 = NULL;
yy_opm_port_ipv4 = yy_opm_port_ipv6 = yy_opm_timeout = 0; yy_opm_port_ipv4 = yy_opm_port_ipv6 = yy_opm_timeout = 0;
delete_opm_proxy_scanner_all(); delete_opm_proxy_scanner_all();
delete_opm_listener_all();
return 0; return 0;
} }
@ -2062,28 +2063,28 @@ conf_end_opm(struct TopConf *tc)
if(yy_opm_port_ipv4 > 0) if(yy_opm_port_ipv4 > 0)
{ {
if(yy_opm_address_ipv4 != NULL) 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 else
{ {
char ip[HOSTIPLEN]; char ip[HOSTIPLEN];
if(!rb_inet_ntop_sock((struct sockaddr *)&ServerInfo.ip, ip, sizeof(ip))) 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"); conf_report_error("No opm::listen_ipv4 nor serverinfo::vhost directive; cannot listen on IPv4");
else 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_port_ipv6 > 0)
{ {
if(yy_opm_address_ipv6 != NULL) 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 else
{ {
char ip[HOSTIPLEN]; char ip[HOSTIPLEN];
if(!rb_inet_ntop_sock((struct sockaddr *)&ServerInfo.ip6, ip, sizeof(ip))) 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"); conf_report_error("No opm::listen_ipv6 nor serverinfo::vhost directive; cannot listen on IPv6");
else 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); conf_report_error("%s argument is not an integer -- ignoring.", node);
continue; continue;
} }
if(args->v.number > 65535 || args->v.number <= 0) if(args->v.number > 65535 || args->v.number <= 0)
{ {
conf_report_error("%s argument is not an integer between 1 and 65535 -- ignoring.", node); conf_report_error("%s argument is not an integer between 1 and 65535 -- ignoring.", node);

View file

@ -215,7 +215,7 @@ authd_check(struct Client *client_p, struct Client *source_p)
{ {
case 'B': /* Blacklists */ case 'B': /* Blacklists */
{ {
struct blacklist_stats *stats; struct BlacklistStats *stats;
char *blacklist = source_p->preClient->auth.data; char *blacklist = source_p->preClient->auth.data;
if((stats = rb_dictionary_retrieve(bl_stats, blacklist)) != NULL) if((stats = rb_dictionary_retrieve(bl_stats, blacklist)) != NULL)

View file

@ -753,7 +753,7 @@ static void
stats_dnsbl(struct Client *source_p) stats_dnsbl(struct Client *source_p)
{ {
rb_dictionary_iter iter; rb_dictionary_iter iter;
struct blacklist_stats *stats; struct BlacklistStats *stats;
RB_DICTIONARY_FOREACH(stats, &iter, bl_stats) RB_DICTIONARY_FOREACH(stats, &iter, bl_stats)
{ {