X-Git-Url: https://jfr.im/git/solanum.git/blobdiff_plain/762468f85d2f99c3b51ffc9800ae55b945c798e6..2ef034d1111fe65fc4e5175896624c30b8aee9dd:/ircd/authproc.c diff --git a/ircd/authproc.c b/ircd/authproc.c index 7aa93dd7..602601b0 100644 --- a/ircd/authproc.c +++ b/ircd/authproc.c @@ -4,7 +4,7 @@ * * Copyright (C) 2005 Aaron Sethman * Copyright (C) 2005-2012 ircd-ratbox development team - * Copyright (C) 2016 William Pitcock + * Copyright (C) 2016 Ariadne Conill * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -67,7 +67,7 @@ uint32_t cid; static rb_dictionary *cid_clients; static struct ev_entry *timeout_ev; -rb_dictionary *bl_stats; +rb_dictionary *dnsbl_stats; rb_dlink_list opm_list; struct OPMListener opm_listeners[LISTEN_LAST]; @@ -88,24 +88,19 @@ static int start_authd(void) { char fullpath[PATH_MAX + 1]; -#ifdef _WIN32 - const char *suffix = ".exe"; -#else - const char *suffix = ""; -#endif + if(authd_path == NULL) { - snprintf(fullpath, sizeof(fullpath), "%s%cauthd%s", ircd_paths[IRCD_PATH_LIBEXEC], RB_PATH_SEPARATOR, suffix); + snprintf(fullpath, sizeof(fullpath), "%s/authd", ircd_paths[IRCD_PATH_LIBEXEC]); if(access(fullpath, X_OK) == -1) { - snprintf(fullpath, sizeof(fullpath), "%s%cbin%cauthd%s", - ConfigFileEntry.dpath, RB_PATH_SEPARATOR, RB_PATH_SEPARATOR, suffix); + snprintf(fullpath, sizeof(fullpath), "%s/bin/authd", ConfigFileEntry.dpath); if(access(fullpath, X_OK) == -1) { ierror("Unable to execute authd in %s or %s/bin", ircd_paths[IRCD_PATH_LIBEXEC], ConfigFileEntry.dpath); - sendto_realops_snomask(SNO_GENERAL, L_ALL, + sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "Unable to execute authd in %s or %s/bin", ircd_paths[IRCD_PATH_LIBEXEC], ConfigFileEntry.dpath); return 1; @@ -119,9 +114,6 @@ start_authd(void) if(cid_clients == NULL) cid_clients = rb_dictionary_create("authd cid to uid mapping", rb_uint32cmp); - if(bl_stats == NULL) - bl_stats = rb_dictionary_create("blacklist statistics", rb_strcasecmp); - if(timeout_ev == NULL) timeout_ev = rb_event_addish("timeout_dead_authd_clients", timeout_dead_authd_clients, NULL, 1); @@ -130,11 +122,12 @@ start_authd(void) if(authd_helper == NULL) { ierror("Unable to start authd helper: %s", strerror(errno)); - sendto_realops_snomask(SNO_GENERAL, L_ALL, "Unable to start authd helper: %s", strerror(errno)); + sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "Unable to start authd helper: %s", strerror(errno)); return 1; } + ilog(L_MAIN, "authd helper started"); - sendto_realops_snomask(SNO_GENERAL, L_ALL, "authd helper started"); + sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "authd helper started"); rb_helper_run(authd_helper); return 0; } @@ -155,14 +148,14 @@ str_to_cid(const char *str) } static inline struct Client * -cid_to_client(uint32_t cid, bool delete) +cid_to_client(uint32_t ncid, bool del) { struct Client *client_p; - if(delete) - client_p = rb_dictionary_delete(cid_clients, RB_UINT_TO_POINTER(cid)); + if(del) + client_p = rb_dictionary_delete(cid_clients, RB_UINT_TO_POINTER(ncid)); else - client_p = rb_dictionary_retrieve(cid_clients, RB_UINT_TO_POINTER(cid)); + client_p = rb_dictionary_retrieve(cid_clients, RB_UINT_TO_POINTER(ncid)); /* If the client's not found, that's okay, it may have already gone away. * --Elizafox */ @@ -171,14 +164,14 @@ cid_to_client(uint32_t cid, bool delete) } static inline struct Client * -str_cid_to_client(const char *str, bool delete) +str_cid_to_client(const char *str, bool del) { - uint32_t cid = str_to_cid(str); + uint32_t ncid = str_to_cid(str); - if(cid == 0) + if(ncid == 0) return NULL; - return cid_to_client(cid, delete); + return cid_to_client(ncid, del); } static void @@ -204,7 +197,10 @@ cmd_notice_client(int parc, char **parv) { struct Client *client_p; - if((client_p = str_cid_to_client(parv[1], false)) == NULL) + if ((client_p = str_cid_to_client(parv[1], false)) == NULL) + return; + + if (IsAnyDead(client_p)) return; sendto_one_notice(client_p, ":%s", parv[2]); @@ -277,13 +273,13 @@ parse_authd_reply(rb_helper * helper) ssize_t len; int parc; char buf[READBUF_SIZE]; - char *parv[MAXPARA + 1]; + char *parv[MAXPARA]; while((len = rb_helper_read(helper, buf, sizeof(buf))) > 0) { struct authd_cb *cmd; - parc = rb_string_to_array(buf, parv, MAXPARA+1); + parc = rb_string_to_array(buf, parv, sizeof(parv)); cmd = &authd_cmd_tab[(unsigned char)*parv[0]]; if(cmd->fn != NULL) { @@ -337,11 +333,9 @@ configure_authd(void) 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) { @@ -357,11 +351,38 @@ configure_authd(void) } static void -restart_authd_cb(rb_helper * helper) +authd_free_client(struct Client *client_p) { - rb_dictionary_iter iter; - struct Client *client_p; + if(client_p == NULL || client_p->preClient == NULL) + return; + + if(client_p->preClient->auth.cid == 0) + return; + if(authd_helper != NULL) + rb_helper_write(authd_helper, "E %x", client_p->preClient->auth.cid); + + client_p->preClient->auth.accepted = true; + client_p->preClient->auth.cid = 0; +} + +static void +authd_free_client_cb(rb_dictionary_element *delem, void *unused) +{ + struct Client *client_p = delem->data; + authd_free_client(client_p); +} + +void +authd_abort_client(struct Client *client_p) +{ + rb_dictionary_delete(cid_clients, RB_UINT_TO_POINTER(client_p->preClient->auth.cid)); + authd_free_client(client_p); +} + +static void +restart_authd_cb(rb_helper * helper) +{ iwarn("authd: restart_authd_cb called, authd died?"); sendto_realops_snomask(SNO_GENERAL, L_ALL, "authd: restart_authd_cb called, authd died?"); @@ -371,11 +392,8 @@ restart_authd_cb(rb_helper * helper) authd_helper = NULL; } - RB_DICTIONARY_FOREACH(client_p, &iter, cid_clients) - { - /* Abort any existing clients */ - authd_abort_client(client_p); - } + rb_dictionary_destroy(cid_clients, authd_free_client_cb, NULL); + cid_clients = NULL; start_authd(); configure_authd(); @@ -454,7 +472,12 @@ authd_initiate_client(struct Client *client_p, bool defer) /* Add a bit of a fudge factor... */ client_p->preClient->auth.timeout = rb_current_time() + ConfigFileEntry.connect_timeout + 10; - rb_helper_write(authd_helper, "C %x %s %hu %s %hu", authd_cid, listen_ipaddr, listen_port, client_ipaddr, client_port); + rb_helper_write(authd_helper, "C %x %s %hu %s %hu %x", authd_cid, listen_ipaddr, listen_port, client_ipaddr, client_port, +#ifdef HAVE_LIBSCTP + IsSCTP(client_p) ? IPPROTO_SCTP : IPPROTO_TCP); +#else + IPPROTO_TCP); +#endif } static inline void @@ -531,46 +554,43 @@ authd_reject_client(struct Client *client_p, const char *ident, const char *host authd_decide_client(client_p, ident, host, false, cause, data, reason); } -void -authd_abort_client(struct Client *client_p) -{ - if(client_p == NULL || client_p->preClient == NULL) - return; - - if(client_p->preClient->auth.cid == 0) - return; - - rb_dictionary_delete(cid_clients, RB_UINT_TO_POINTER(client_p->preClient->auth.cid)); - - if(authd_helper != NULL) - rb_helper_write(authd_helper, "E %x", client_p->preClient->auth.cid); - - client_p->preClient->auth.accepted = true; - client_p->preClient->auth.cid = 0; -} - static void timeout_dead_authd_clients(void *notused __unused) { rb_dictionary_iter iter; struct Client *client_p; + rb_dlink_list freelist = { NULL, NULL, 0 }; + rb_dlink_node *ptr, *nptr; RB_DICTIONARY_FOREACH(client_p, &iter, cid_clients) { if(client_p->preClient->auth.timeout < rb_current_time()) - authd_abort_client(client_p); + { + authd_free_client(client_p); + rb_dlinkAddAlloc(client_p, &freelist); + } + } + + /* RB_DICTIONARY_FOREACH is not safe for deletion, so we do this crap */ + RB_DLINK_FOREACH_SAFE(ptr, nptr, freelist.head) + { + client_p = ptr->data; + rb_dictionary_delete(cid_clients, RB_UINT_TO_POINTER(client_p->preClient->auth.cid)); } } -/* Send a new blacklist to authd */ +/* Send a new DNSBL entry to authd */ void -add_blacklist(const char *host, const char *reason, uint8_t iptype, rb_dlink_list *filters) +add_dnsbl_entry(const char *host, const char *reason, uint8_t iptype, rb_dlink_list *filters) { rb_dlink_node *ptr; - struct BlacklistStats *stats = rb_malloc(sizeof(struct BlacklistStats)); + struct DNSBLEntryStats *stats = rb_malloc(sizeof(*stats)); char filterbuf[BUFSIZE] = "*"; size_t s = 0; + if(dnsbl_stats == NULL) + dnsbl_stats = rb_dictionary_create("dnsbl statistics", rb_strcasecmp); + /* Build a list of comma-separated values for authd. * We don't check for validity - do it elsewhere. */ @@ -593,19 +613,19 @@ add_blacklist(const char *host, const char *reason, uint8_t iptype, rb_dlink_lis stats->host = rb_strdup(host); stats->iptype = iptype; stats->hits = 0; - rb_dictionary_add(bl_stats, host, stats); + rb_dictionary_add(dnsbl_stats, stats->host, stats); rb_helper_write(authd_helper, "O rbl %s %hhu %s :%s", host, iptype, filterbuf, reason); } -/* Delete a blacklist */ +/* Delete a DNSBL entry. */ void -del_blacklist(const char *host) +del_dnsbl_entry(const char *host) { - struct BlacklistStats *stats = rb_dictionary_retrieve(bl_stats, host); + struct DNSBLEntryStats *stats = rb_dictionary_retrieve(dnsbl_stats, host); if(stats != NULL) { - rb_dictionary_delete(bl_stats, host); + rb_dictionary_delete(dnsbl_stats, host); rb_free(stats->host); rb_free(stats); } @@ -613,19 +633,22 @@ del_blacklist(const char *host) rb_helper_write(authd_helper, "O rbl_del %s", host); } -/* Delete all the blacklists */ -void -del_blacklist_all(void) +static void +dnsbl_delete_elem(rb_dictionary_element *delem, void *unused) { - struct BlacklistStats *stats; - rb_dictionary_iter iter; + struct DNSBLEntryStats *stats = delem->data; - RB_DICTIONARY_FOREACH(stats, &iter, bl_stats) - { - rb_dictionary_delete(bl_stats, stats->host); - rb_free(stats->host); - rb_free(stats); - } + rb_free(stats->host); + rb_free(stats); +} + +/* Delete all the DNSBL entries. */ +void +del_dnsbl_entry_all(void) +{ + if(dnsbl_stats != NULL) + rb_dictionary_destroy(dnsbl_stats, dnsbl_delete_elem, NULL); + dnsbl_stats = NULL; rb_helper_write(authd_helper, "O rbl_del_all"); }