diff --git a/include/ircd/authproc.h b/include/ircd/authproc.h deleted file mode 100644 index 892209e44..000000000 --- a/include/ircd/authproc.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * charybdis - * authproc.h: A header with the authd functions. - * - * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center - * Copyright (C) 1996-2002 Hybrid Development Team - * Copyright (C) 2002-2012 ircd-ratbox development team - * Copyright (C) 2016 William Pitcock - * - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -#pragma once -#define HAVE_CHARYBDIS_AUTHPROC_H - -#ifdef __cplusplus -namespace ircd { - -struct BlacklistStats -{ - char *host; - 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); -void restart_authd(void); -void rehash_authd(void); -void check_authd(void); - -void authd_initiate_client(client::client *, bool defer); -void authd_deferred_client(client::client *); -void authd_accept_client(client::client *client_p, const char *ident, const char *host); -void authd_reject_client(client::client *client_p, const char *ident, const char *host, char cause, const char *data, const char *reason); -void authd_abort_client(client::client *); - -void add_blacklist(const char *host, const char *reason, uint8_t iptype, rb_dlink_list *filters); -void del_blacklist(const char *host); -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 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); - -} // namespace ircd -#endif // __cplusplus diff --git a/include/ircd/bandbi.h b/include/ircd/bandbi.h deleted file mode 100644 index b77ca388d..000000000 --- a/include/ircd/bandbi.h +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Copyright (C) 2016 Charybdis Development Team - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice is present in all copies. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#pragma once -#define HAVE_BANDBI_H - -#ifdef __cplusplus -namespace ircd { - -void init_bandb(void); - -typedef enum -{ - BANDB_KLINE, - BANDB_DLINE, - BANDB_XLINE, - BANDB_RESV, - LAST_BANDB_TYPE -} bandb_type; - -void bandb_add(bandb_type, client::client *source_p, const char *mask1, - const char *mask2, const char *reason, const char *oper_reason, int perm); -void bandb_del(bandb_type, const char *mask1, const char *mask2); -void bandb_rehash_bans(void); - -} // namespace ircd -#endif // __cplusplus diff --git a/include/ircd/sslproc.h b/include/ircd/sslproc.h deleted file mode 100644 index c3a922681..000000000 --- a/include/ircd/sslproc.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * sslproc.h: An interface to the ratbox ssld helper daemon - * Copyright (C) 2007 Aaron Sethman - * Copyright (C) 2007 ircd-ratbox development team - * - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -#pragma once -#define HAVE_IRCD_SSLPROC_H - -#ifdef __cplusplus -namespace ircd { - -struct _ssl_ctl; -typedef struct _ssl_ctl ssl_ctl_t; - -enum ssld_status { - SSLD_ACTIVE, - SSLD_SHUTDOWN, - SSLD_DEAD, -}; - -void init_ssld(void); -void restart_ssld(void); -int start_ssldaemon(int count); -ssl_ctl_t *start_ssld_accept(rb_fde_t *sslF, rb_fde_t *plainF, uint32_t id); -ssl_ctl_t *start_ssld_connect(rb_fde_t *sslF, rb_fde_t *plainF, uint32_t id); -void start_zlib_session(void *data); -void ssld_update_config(void); -void ssld_decrement_clicount(ssl_ctl_t *ctl); -int get_ssld_count(void); -void ssld_foreach_info(void (*func)(void *data, pid_t pid, int cli_count, enum ssld_status status, const char *version), void *data); - -} // namespace ircd -#endif // __cplusplus diff --git a/include/ircd/stdinc.h b/include/ircd/stdinc.h index 9133f4303..6e05b5ddb 100644 --- a/include/ircd/stdinc.h +++ b/include/ircd/stdinc.h @@ -66,9 +66,6 @@ namespace ircd struct ConfItem; struct Blacklist; struct PrivilegeSet; - struct _ssl_ctl; - struct ev_ctl; - struct ws_ctl; struct server_conf; } @@ -118,8 +115,6 @@ namespace ircd #include "chmode.h" #include "channel.h" -#include "authproc.h" -#include "bandbi.h" #include "capability.h" #include "certfp.h" #include "class.h" @@ -135,10 +130,8 @@ namespace ircd #include "send.h" #include "s_newconf.h" #include "s_serv.h" -#include "sslproc.h" #include "s_stats.h" #include "substitution.h" #include "supported.h" #include "s_user.h" -#include "wsproc.h" */ diff --git a/include/ircd/wsproc.h b/include/ircd/wsproc.h deleted file mode 100644 index 681cfbf1e..000000000 --- a/include/ircd/wsproc.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * wsproc.h: An interface to the charybdis websocket helper daemon - * Copyright (C) 2007 Aaron Sethman - * Copyright (C) 2007 ircd-ratbox development team - * Copyright (C) 2016 William Pitcock - * - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -#pragma once -#define HAVE_IRCD_WSPROC_H - -#ifdef __cplusplus -namespace ircd { - -struct ws_ctl; -typedef struct ws_ctl ws_ctl_t; - -enum wsockd_status { - WSOCKD_ACTIVE, - WSOCKD_SHUTDOWN, - WSOCKD_DEAD, -}; - -void init_wsockd(void); -void restart_wsockd(void); -int start_wsockd(int count); -ws_ctl_t *start_wsockd_accept(rb_fde_t *wsF, rb_fde_t *plainF, uint32_t id); -void wsockd_decrement_clicount(ws_ctl_t *ctl); -int get_wsockd_count(void); -void wsockd_foreach_info(void (*func)(void *data, pid_t pid, int cli_count, enum wsockd_status status), void *data); - -} // namespace ircd -#endif // __cplusplus diff --git a/ircd/authproc.cc b/ircd/authproc.cc deleted file mode 100644 index c9a40ef1f..000000000 --- a/ircd/authproc.cc +++ /dev/null @@ -1,781 +0,0 @@ -/* - * authd.c: An interface to authd. - * (based somewhat on ircd-ratbox dns.c) - * - * Copyright (C) 2005 Aaron Sethman - * Copyright (C) 2005-2012 ircd-ratbox development team - * Copyright (C) 2016 William Pitcock - * - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -namespace ircd { - -typedef void (*authd_cb_t)(int, char **); - -struct authd_cb -{ - authd_cb_t fn; - int min_parc; -}; - -static int start_authd(void); -static void parse_authd_reply(rb_helper * helper); -static void restart_authd_cb(rb_helper * helper); -static EVH timeout_dead_authd_clients; - -static void cmd_accept_client(int parc, char **parv); -static void cmd_reject_client(int parc, char **parv); -static void cmd_dns_result(int parc, char **parv); -static void cmd_notice_client(int parc, char **parv); -static void cmd_oper_warn(int parc, char **parv); -static void cmd_stats_results(int parc, char **parv); - -rb_helper *authd_helper; -static char *authd_path; - -uint32_t cid; -static rb_dictionary *cid_clients; -static struct ev_entry *timeout_ev; - -rb_dictionary *bl_stats; - -rb_dlink_list opm_list; -struct OPMListener opm_listeners[LISTEN_LAST]; - -std::array authd_cmd_tab = -[]{ - std::array ret {0}; - ret['A'] = { cmd_accept_client, 4 }; - ret['E'] = { cmd_dns_result, 5 }; - ret['N'] = { cmd_notice_client, 3 }; - ret['R'] = { cmd_reject_client, 7 }; - ret['W'] = { cmd_oper_warn, 3 }; - ret['X'] = { cmd_stats_results, 3 }; - ret['Y'] = { cmd_stats_results, 3 }; - ret['Z'] = { cmd_stats_results, 3 }; - return ret; -}(); - -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", path::get(path::LIBEXEC), RB_PATH_SEPARATOR, suffix); - - if(access(fullpath, X_OK) == -1) - { - snprintf(fullpath, sizeof(fullpath), "%s%cbin%cauthd%s", - ConfigFileEntry.dpath, RB_PATH_SEPARATOR, RB_PATH_SEPARATOR, suffix); - if(access(fullpath, X_OK) == -1) - { - // TODO: double dipping - ierror("Unable to execute authd in %s or %s/bin", - path::get(path::LIBEXEC), - ConfigFileEntry.dpath); - - // TODO: double dipping - sendto_realops_snomask(sno::GENERAL, L_ALL, - "Unable to execute authd in %s or %s/bin", - path::get(path::LIBEXEC), - ConfigFileEntry.dpath); - return 1; - } - - } - - authd_path = rb_strdup(fullpath); - } - - if(cid_clients == NULL) - cid_clients = rb_dictionary_create("authd cid to uid mapping", rb_uint32cmp); - - if(timeout_ev == NULL) - timeout_ev = rb_event_addish("timeout_dead_authd_clients", timeout_dead_authd_clients, NULL, 1); - - authd_helper = rb_helper_start("authd", authd_path, parse_authd_reply, restart_authd_cb); - - 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)); - return 1; - } - - ilog(L_MAIN, "authd helper started"); - sendto_realops_snomask(sno::GENERAL, L_ALL, "authd helper started"); - rb_helper_run(authd_helper); - return 0; -} - -static inline uint32_t -str_to_cid(const char *str) -{ - long lcid = strtol(str, NULL, 16); - - if(lcid > UINT32_MAX || lcid <= 0) - { - iwarn("authd sent us back a bad client ID: %lx", lcid); - restart_authd(); - return 0; - } - - return (uint32_t)lcid; -} - -static inline client::client * -cid_to_client(uint32_t ncid, bool del) -{ - client::client *client_p; - - if(del) - client_p = (client::client *)rb_dictionary_delete(cid_clients, RB_UINT_TO_POINTER(ncid)); - else - client_p = (client::client *)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 */ - - return client_p; -} - -static inline client::client * -str_cid_to_client(const char *str, bool del) -{ - uint32_t ncid = str_to_cid(str); - - if(ncid == 0) - return NULL; - - return cid_to_client(ncid, del); -} - -static void -cmd_accept_client(int parc, char **parv) -{ - client::client *client_p; - - /* cid to uid (retrieve and delete) */ - if((client_p = str_cid_to_client(parv[1], true)) == NULL) - return; - - authd_accept_client(client_p, parv[2], parv[3]); -} - -static void -cmd_dns_result(int parc, char **parv) -{ - dns_results_callback(parv[1], parv[2], parv[3], parv[4]); -} - -static void -cmd_notice_client(int parc, char **parv) -{ - client::client *client_p; - - if((client_p = str_cid_to_client(parv[1], false)) == NULL) - return; - - sendto_one_notice(client_p, ":%s", parv[2]); -} - -static void -cmd_reject_client(int parc, char **parv) -{ - client::client *client_p; - - /* cid to uid (retrieve and delete) */ - if((client_p = str_cid_to_client(parv[1], true)) == NULL) - return; - - authd_reject_client(client_p, parv[3], parv[4], toupper(*parv[2]), parv[5], parv[6]); -} - -static void -cmd_oper_warn(int parc, char **parv) -{ - switch(*parv[1]) - { - case 'D': /* Debug */ - sendto_realops_snomask(sno::DEBUG, L_ALL, "authd debug: %s", parv[2]); - idebug("authd: %s", parv[2]); - break; - case 'I': /* Info */ - sendto_realops_snomask(sno::GENERAL, L_ALL, "authd info: %s", parv[2]); - inotice("authd: %s", parv[2]); - break; - case 'W': /* Warning */ - sendto_realops_snomask(sno::GENERAL, L_ALL, "authd WARNING: %s", parv[2]); - iwarn("authd: %s", parv[2]); - break; - case 'C': /* Critical (error) */ - sendto_realops_snomask(sno::GENERAL, L_ALL, "authd CRITICAL: %s", parv[2]); - ierror("authd: %s", parv[2]); - break; - default: /* idk */ - sendto_realops_snomask(sno::GENERAL, L_ALL, "authd sent us an unknown oper notice type (%s): %s", parv[1], parv[2]); - ilog(L_MAIN, "authd unknown oper notice type (%s): %s", parv[1], parv[2]); - break; - } -} - -static void -cmd_stats_results(int parc, char **parv) -{ - /* Select by type */ - switch(*parv[2]) - { - case 'D': - /* parv[0] conveys status */ - if(parc < 4) - { - iwarn("authd sent a result with wrong number of arguments: got %d", parc); - restart_authd(); - return; - } - dns_stats_results_callback(parv[1], parv[0], parc - 3, (const char **)&parv[3]); - break; - default: - break; - } -} - -static void -parse_authd_reply(rb_helper * helper) -{ - ssize_t len; - int parc; - char buf[READBUF_SIZE]; - char *parv[MAXPARA + 1]; - - while((len = rb_helper_read(helper, buf, sizeof(buf))) > 0) - { - struct authd_cb *cmd; - - parc = rb_string_to_array(buf, parv, MAXPARA+1); - cmd = &authd_cmd_tab[(unsigned char)*parv[0]]; - if(cmd->fn != NULL) - { - if(cmd->min_parc > parc) - { - iwarn("authd sent a result with wrong number of arguments: expected %d, got %d", - cmd->min_parc, parc); - restart_authd(); - continue; - } - - cmd->fn(parc, parv); - } - else - { - iwarn("authd sent us a bad command type: %c", *parv[0]); - restart_authd(); - continue; - } - } -} - -void -init_authd(void) -{ - if(start_authd()) - { - ierror("Unable to start authd helper: %s", strerror(errno)); - exit(0); - } -} - -void -configure_authd(void) -{ - /* 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 = (OPMScanner *)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 -authd_free_client(client::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) -{ - client::client *client_p = (client::client *)delem->data; - authd_free_client(client_p); -} - -void -authd_abort_client(client::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) -{ - rb_dictionary_iter iter; - client::client *client_p; - - iwarn("authd: restart_authd_cb called, authd died?"); - sendto_realops_snomask(sno::GENERAL, L_ALL, "authd: restart_authd_cb called, authd died?"); - - if(helper != NULL) - { - rb_helper_close(helper); - authd_helper = NULL; - } - - rb_dictionary_destroy(cid_clients, authd_free_client_cb, NULL); - cid_clients = NULL; - - start_authd(); - configure_authd(); -} - -void -restart_authd(void) -{ - ierror("authd restarting..."); - restart_authd_cb(authd_helper); -} - -void -rehash_authd(void) -{ - rb_helper_write(authd_helper, "R"); -} - -void -check_authd(void) -{ - if(authd_helper == NULL) - restart_authd(); -} - -static inline uint32_t -generate_cid(void) -{ - if(++cid == 0) - cid = 1; - - return cid; -} - -/* Basically when this is called we begin handing off the client to authd for - * processing. authd "owns" the client until processing is finished, or we - * timeout from authd. authd will make a decision whether or not to accept the - * client, but it's up to other parts of the code (for now) to decide if we're - * gonna accept the client and ignore authd's suggestion. - * - * --Elizafox - * - * If this is an SSL connection we must defer handing off the client for - * reading until it is open and we have the certificate fingerprint, otherwise - * it's possible for the client to immediately send data before authd completes - * and before the status of the connection is communicated via ssld. This data - * could then be processed too early by read_packet(). - */ -void -authd_initiate_client(client::client *client_p, bool defer) -{ - char client_ipaddr[HOSTIPLEN+1]; - char listen_ipaddr[HOSTIPLEN+1]; - uint16_t client_port, listen_port; - uint32_t authd_cid; - - if(client_p->preClient == NULL || client_p->preClient->auth.cid != 0) - return; - - authd_cid = client_p->preClient->auth.cid = generate_cid(); - - /* Collisions are extremely unlikely, so disregard the possibility */ - rb_dictionary_add(cid_clients, RB_UINT_TO_POINTER(authd_cid), client_p); - - /* Retrieve listener and client IP's */ - rb_inet_ntop_sock((struct sockaddr *)&client_p->preClient->lip, listen_ipaddr, sizeof(listen_ipaddr)); - rb_inet_ntop_sock((struct sockaddr *)&client_p->localClient->ip, client_ipaddr, sizeof(client_ipaddr)); - - /* Retrieve listener and client ports */ - listen_port = ntohs(GET_SS_PORT(&client_p->preClient->lip)); - client_port = ntohs(GET_SS_PORT(&client_p->localClient->ip)); - - if(defer) - client_p->preClient->auth.flags |= AUTHC_F_DEFERRED; - - /* 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); -} - -static inline void -authd_read_client(client::client *client_p) -{ - /* - * When a client has auth'ed, we want to start reading what it sends - * us. This is what read_packet() does. - * -- adrian - * - * Above comment was originally in s_auth.c, but moved here with below code. - * --Elizafox - */ - rb_dlinkAddTail(client_p, &client_p->node, &global_client_list); - read_packet(client_p->localClient->F, client_p); -} - -/* When this is called we have a decision on client acceptance. - * - * After this point authd no longer "owns" the client, but if - * it's flagged as deferred then we're still waiting for a call - * to authd_deferred_client(). - */ -static inline void -authd_decide_client(client::client *client_p, const char *ident, const char *host, bool accept, char cause, const char *data, const char *reason) -{ - if(client_p->preClient == NULL || client_p->preClient->auth.cid == 0) - return; - - if(*ident != '*') - { - rb_strlcpy(client_p->username, ident, sizeof(client_p->username)); - set_got_id(*client_p); - ServerStats.is_asuc++; - } - else - ServerStats.is_abad++; /* s_auth used to do this, stay compatible */ - - if(*host != '*') - rb_strlcpy(client_p->host, host, sizeof(client_p->host)); - - rb_dictionary_delete(cid_clients, RB_UINT_TO_POINTER(client_p->preClient->auth.cid)); - - client_p->preClient->auth.accepted = accept; - client_p->preClient->auth.cause = cause; - client_p->preClient->auth.data = (data == NULL ? NULL : rb_strdup(data)); - client_p->preClient->auth.reason = (reason == NULL ? NULL : rb_strdup(reason)); - client_p->preClient->auth.cid = 0; - - client_p->preClient->auth.flags |= AUTHC_F_COMPLETE; - if((client_p->preClient->auth.flags & AUTHC_F_DEFERRED) == 0) - authd_read_client(client_p); -} - -void -authd_deferred_client(client::client *client_p) -{ - client_p->preClient->auth.flags &= ~AUTHC_F_DEFERRED; - if(client_p->preClient->auth.flags & AUTHC_F_COMPLETE) - authd_read_client(client_p); -} - -/* Convenience function to accept client */ -void -authd_accept_client(client::client *client_p, const char *ident, const char *host) -{ - authd_decide_client(client_p, ident, host, true, '\0', NULL, NULL); -} - -/* Convenience function to reject client */ -void -authd_reject_client(client::client *client_p, const char *ident, const char *host, char cause, const char *data, const char *reason) -{ - authd_decide_client(client_p, ident, host, false, cause, data, reason); -} - -static void -timeout_dead_authd_clients(void *notused) -{ - rb_dictionary_iter iter; - client::client *client_p; - rb_dlink_list freelist = { NULL, NULL, 0 }; - rb_dlink_node *ptr, *nptr; - - void *elem; - RB_DICTIONARY_FOREACH(elem, &iter, cid_clients) - { - client_p = (client::client *)elem; - if(client_p->preClient->auth.timeout < rb_current_time()) - { - 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 = (client::client *)ptr->data; - rb_dictionary_delete(cid_clients, RB_UINT_TO_POINTER(client_p->preClient->auth.cid)); - } -} - -/* Send a new blacklist to authd */ -void -add_blacklist(const char *host, const char *reason, uint8_t iptype, rb_dlink_list *filters) -{ - rb_dlink_node *ptr; - struct BlacklistStats *stats = (BlacklistStats *)rb_malloc(sizeof(struct BlacklistStats)); - char filterbuf[BUFSIZE] = "*"; - size_t s = 0; - - if(bl_stats == NULL) - bl_stats = rb_dictionary_create("blacklist statistics", reinterpret_cast(rb_strcasecmp)); - - /* Build a list of comma-separated values for authd. - * We don't check for validity - do it elsewhere. - */ - RB_DLINK_FOREACH(ptr, filters->head) - { - char *filter = (char *)ptr->data; - size_t filterlen = strlen(filter) + 1; - - if(s + filterlen > sizeof(filterbuf)) - break; - - snprintf(&filterbuf[s], sizeof(filterbuf) - s, "%s,", filter); - - s += filterlen; - } - - if(s) - filterbuf[s - 1] = '\0'; - - stats->host = rb_strdup(host); - stats->iptype = iptype; - stats->hits = 0; - rb_dictionary_add(bl_stats, stats->host, stats); - - rb_helper_write(authd_helper, "O rbl %s %hhu %s :%s", host, iptype, filterbuf, reason); -} - -/* Delete a blacklist */ -void -del_blacklist(const char *host) -{ - struct BlacklistStats *stats = (BlacklistStats *)rb_dictionary_retrieve(bl_stats, host); - if(stats != NULL) - { - rb_dictionary_delete(bl_stats, host); - rb_free(stats->host); - rb_free(stats); - } - - rb_helper_write(authd_helper, "O rbl_del %s", host); -} - -static void -blacklist_delete(rb_dictionary_element *delem, void *unused) -{ - struct BlacklistStats *stats = (BlacklistStats *)delem->data; - - rb_free(stats->host); - rb_free(stats); -} - -/* Delete all the blacklists */ -void -del_blacklist_all(void) -{ - if(bl_stats != NULL) - rb_dictionary_destroy(bl_stats, blacklist_delete, NULL); - bl_stats = NULL; - - rb_helper_write(authd_helper, "O rbl_del_all"); -} - -/* Adjust an authd timeout value */ -bool -set_authd_timeout(const char *key, int timeout) -{ - if(timeout <= 0) - return false; - - rb_helper_write(authd_helper, "O %s %d", key, timeout); - return true; -} - -/* Enable identd checks */ -void -ident_check_enable(bool enabled) -{ - rb_helper_write(authd_helper, "O ident_enabled %d", enabled ? 1 : 0); -} - -/* Create an OPM listener - * XXX - This is a big nasty hack, but it avoids resending duplicate data when - * configure_authd() is called. - */ -void -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] == ':') - { - memmove(ipbuf + 1, ipbuf, sizeof(ipbuf) - 1); - ipbuf[0] = '0'; - } - - /* 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", ipbuf, 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 */ -void -opm_check_enable(bool enabled) -{ - rb_helper_write(authd_helper, "O opm_enabled %d", enabled ? 1 : 0); -} - -/* 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 = (OPMScanner *)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 = (OPMScanner *)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 = (OPMScanner *)ptr->data; - - rb_dlinkDelete(ptr, &opm_list); - rb_free(scanner); - } - - rb_helper_write(authd_helper, "O opm_scanner_del_all"); -} - -} // namespace ircd diff --git a/ircd/bandbi.cc b/ircd/bandbi.cc deleted file mode 100644 index 092a37b78..000000000 --- a/ircd/bandbi.cc +++ /dev/null @@ -1,437 +0,0 @@ -/* src/bandbi.c - * An interface to the ban db. - * - * Copyright (C) 2006 Lee Hardy - * Copyright (C) 2006 ircd-ratbox development team - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1.Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2.Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3.The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -namespace ircd { - -static void -bandb_handle_failure(rb_helper *helper, char **parv, int parc) __attribute__((noreturn)); - -static char bandb_add_letter[LAST_BANDB_TYPE] = { - 'K', 'D', 'X', 'R' -}; - -rb_dlink_list bandb_pending; - -static rb_helper *bandb_helper; -static int start_bandb(void); - -static void bandb_parse(rb_helper *); -static void bandb_restart_cb(rb_helper *); -static char *bandb_path; - -void -init_bandb(void) -{ - if(start_bandb()) - { - ilog(L_MAIN, "Unable to start bandb helper: %s", strerror(errno)); - exit(0); - } -} - - -static int -start_bandb(void) -{ - char fullpath[PATH_MAX + 1]; -#ifdef _WIN32 - const char *suffix = ".exe"; -#else - const char *suffix = ""; -#endif - - rb_setenv("BANDB_DBPATH", path::get(path::BANDB), 1); - if(bandb_path == NULL) - { - snprintf(fullpath, sizeof(fullpath), "%s%cbandb%s", path::get(path::LIBEXEC), RB_PATH_SEPARATOR, suffix); - - if(access(fullpath, X_OK) == -1) - { - snprintf(fullpath, sizeof(fullpath), "%s%cbin%cbandb%s", - ConfigFileEntry.dpath, RB_PATH_SEPARATOR, RB_PATH_SEPARATOR, suffix); - - if(access(fullpath, X_OK) == -1) - { - ilog(L_MAIN, - "Unable to execute bandb%s in %s or %s/bin", - suffix, path::get(path::LIBEXEC), ConfigFileEntry.dpath); - return 0; - } - } - bandb_path = rb_strdup(fullpath); - } - - - bandb_helper = rb_helper_start("bandb", bandb_path, bandb_parse, bandb_restart_cb); - - if(bandb_helper == NULL) - { - ilog(L_MAIN, "Unable to start bandb: %s", strerror(errno)); - sendto_realops_snomask(sno::GENERAL, L_ALL, "Unable to start bandb: %s", - strerror(errno)); - return 1; - } - - rb_helper_run(bandb_helper); - return 0; -} - -void -bandb_add(bandb_type type, client::client *source_p, const char *mask1, - const char *mask2, const char *reason, const char *oper_reason, int perm) -{ - if(bandb_helper == NULL) - return; - - static char buf[BUFSIZE]; - - snprintf(buf, sizeof(buf), "%c %s ", bandb_add_letter[type], mask1); - - if(!EmptyString(mask2)) - rb_snprintf_append(buf, sizeof(buf), "%s ", mask2); - - rb_snprintf_append(buf, sizeof(buf), "%s %ld %d :%s", - get_oper_name(source_p), (long int)rb_current_time(), perm, reason); - - if(!EmptyString(oper_reason)) - rb_snprintf_append(buf, sizeof(buf), "|%s", oper_reason); - - rb_helper_write(bandb_helper, "%s", buf); -} - -static char bandb_del_letter[LAST_BANDB_TYPE] = { - 'k', 'd', 'x', 'r' -}; - -void -bandb_del(bandb_type type, const char *mask1, const char *mask2) -{ - if(bandb_helper == NULL) - return; - - static char buf[BUFSIZE]; - - buf[0] = '\0'; - - rb_snprintf_append(buf, sizeof(buf), "%c %s", bandb_del_letter[type], mask1); - - if(!EmptyString(mask2)) - rb_snprintf_append(buf, sizeof(buf), " %s", mask2); - - rb_helper_write(bandb_helper, "%s", buf); -} - -static void -bandb_handle_ban(char *parv[], int parc) -{ - struct ConfItem *aconf; - char *p; - int para = 1; - - aconf = make_conf(); - aconf->port = 0; - - if(parv[0][0] == 'K') - aconf->user = rb_strdup(parv[para++]); - - aconf->host = rb_strdup(parv[para++]); - aconf->info.oper = operhash_add(parv[para++]); - - switch (parv[0][0]) - { - case 'K': - aconf->status = CONF_KILL; - break; - - case 'D': - aconf->status = CONF_DLINE; - break; - - case 'X': - aconf->status = CONF_XLINE; - break; - - case 'R': - if(chan::has_prefix(aconf->host)) - aconf->status = CONF_RESV_CHANNEL; - else - aconf->status = CONF_RESV_NICK; - - break; - } - - if((p = strchr(parv[para], '|'))) - { - *p++ = '\0'; - aconf->spasswd = rb_strdup(p); - } - - aconf->passwd = rb_strdup(parv[para]); - - rb_dlinkAddAlloc(aconf, &bandb_pending); -} - -static int -bandb_check_kline(struct ConfItem *aconf) -{ - struct rb_sockaddr_storage daddr; - struct ConfItem *kconf = NULL; - int aftype; - const char *p; - - aftype = parse_netmask(aconf->host, &daddr, NULL); - - if(aftype != HM_HOST) - { -#ifdef RB_IPV6 - if(aftype == HM_IPV6) - aftype = AF_INET6; - else -#endif - aftype = AF_INET; - - kconf = find_conf_by_address(aconf->host, NULL, NULL, (struct sockaddr *)&daddr, - CONF_KILL, aftype, aconf->user, NULL); - } - else - kconf = find_conf_by_address(aconf->host, NULL, NULL, NULL, CONF_KILL, 0, aconf->user, NULL); - - if(kconf && ((kconf->flags & CONF_FLAGS_TEMPORARY) == 0)) - return 0; - - for(p = aconf->user; *p; p++) - if(!rfc1459::is_user(*p) && !rfc1459::is_kwild(*p)) - return 0; - - for(p = aconf->host; *p; p++) - if(!rfc1459::is_host(*p) && !rfc1459::is_kwild(*p)) - return 0; - - return 1; -} - -static int -bandb_check_dline(struct ConfItem *aconf) -{ - struct rb_sockaddr_storage daddr; - int bits; - - if(!parse_netmask(aconf->host, &daddr, &bits)) - return 0; - - return 1; -} - -static int -bandb_check_xline(struct ConfItem *aconf) -{ - struct ConfItem *xconf; - /* XXX perhaps convert spaces to \s? -- jilles */ - - xconf = find_xline_mask(aconf->host); - if(xconf != NULL && !(xconf->flags & CONF_FLAGS_TEMPORARY)) - return 0; - - return 1; -} - -static int -bandb_check_resv_channel(struct ConfItem *aconf) -{ - const char *p; - - if(hash_find_resv(aconf->host) || strlen(aconf->host) > CHANNELLEN) - return 0; - - for(p = aconf->host; *p; p++) - if(!rfc1459::is_chan(*p)) - return 0; - - return 1; -} - -static int -bandb_check_resv_nick(struct ConfItem *aconf) -{ - if(!clean_resv_nick(aconf->host)) - return 0; - - if(find_nick_resv(aconf->host)) - return 0; - - return 1; -} - -static void -bandb_handle_clear(void) -{ - rb_dlink_node *ptr, *next_ptr; - - RB_DLINK_FOREACH_SAFE(ptr, next_ptr, bandb_pending.head) - { - free_conf((ConfItem *)ptr->data); - rb_dlinkDestroy(ptr, &bandb_pending); - } -} - -static void -bandb_handle_finish(void) -{ - struct ConfItem *aconf; - rb_dlink_node *ptr, *next_ptr; - - clear_out_address_conf_bans(); - clear_s_newconf_bans(); - - RB_DLINK_FOREACH_SAFE(ptr, next_ptr, bandb_pending.head) - { - aconf = (ConfItem *)ptr->data; - - rb_dlinkDestroy(ptr, &bandb_pending); - - switch (aconf->status) - { - case CONF_KILL: - if(bandb_check_kline(aconf)) - add_conf_by_address(aconf->host, CONF_KILL, aconf->user, NULL, aconf); - else - free_conf(aconf); - - break; - - case CONF_DLINE: - if(bandb_check_dline(aconf)) - add_conf_by_address(aconf->host, CONF_DLINE, aconf->user, NULL, aconf); - else - free_conf(aconf); - - break; - - case CONF_XLINE: - if(bandb_check_xline(aconf)) - rb_dlinkAddAlloc(aconf, &xline_conf_list); - else - free_conf(aconf); - - break; - - case CONF_RESV_CHANNEL: - if(bandb_check_resv_channel(aconf)) - add_to_resv_hash(aconf->host, aconf); - else - free_conf(aconf); - - break; - - case CONF_RESV_NICK: - if(bandb_check_resv_nick(aconf)) - rb_dlinkAddAlloc(aconf, &resv_conf_list); - else - free_conf(aconf); - - break; - } - } - - client::check_banned_lines(); -} - -static void -bandb_handle_failure(rb_helper *helper, char **parv, int parc) -{ - if(server_state_foreground) - fprintf(stderr, "bandb - bandb failure: %s\n", parv[1]); - - ilog(L_MAIN, "bandb - bandb failure: %s", parv[1]); - sendto_realops_snomask(sno::GENERAL, L_ALL, "bandb - bandb failure: %s", parv[1]); - exit(1); -} - -static void -bandb_parse(rb_helper *helper) -{ - static char buf[READBUF_SIZE]; - char *parv[MAXPARA + 1]; - int len, parc; - - while((len = rb_helper_read(helper, buf, sizeof(buf)))) - { - parc = rb_string_to_array(buf, parv, MAXPARA); - - if(parc < 1) - continue; - - switch (parv[0][0]) - { - case '!': - bandb_handle_failure(helper, parv, parc); - break; - case 'K': - case 'D': - case 'X': - case 'R': - bandb_handle_ban(parv, parc); - break; - - case 'C': - bandb_handle_clear(); - break; - case 'F': - bandb_handle_finish(); - break; - } - } -} - -void -bandb_rehash_bans(void) -{ - if(bandb_helper != NULL) - rb_helper_write(bandb_helper, "L"); -} - -static void -bandb_restart_cb(rb_helper *helper) -{ - ilog(L_MAIN, "bandb - bandb_restart_cb called, bandb helper died?"); - sendto_realops_snomask(sno::GENERAL, L_ALL, - "bandb - bandb_restart_cb called, bandb helper died?"); - if(helper != NULL) - { - rb_helper_close(helper); - bandb_helper = NULL; - } - start_bandb(); - return; -} - - -} // namespace ircd diff --git a/ircd/sslproc.cc b/ircd/sslproc.cc deleted file mode 100644 index 2519408c5..000000000 --- a/ircd/sslproc.cc +++ /dev/null @@ -1,1002 +0,0 @@ -/* - * sslproc.c: An interface to ssld - * Copyright (C) 2007 Aaron Sethman - * Copyright (C) 2007 ircd-ratbox development team - * - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -namespace ircd { - -#define ZIPSTATS_TIME 60 - -static void collect_zipstats(void *unused); -static void ssl_read_ctl(rb_fde_t * F, void *data); -static int ssld_count; - -static char tmpbuf[READBUF_SIZE]; -static char nul = '\0'; - -#define MAXPASSFD 4 -#define READSIZE 1024 -typedef struct _ssl_ctl_buf -{ - rb_dlink_node node; - char *buf; - size_t buflen; - rb_fde_t *F[MAXPASSFD]; - int nfds; -} ssl_ctl_buf_t; - - -struct _ssl_ctl -{ - rb_dlink_node node; - int cli_count; - rb_fde_t *F; - rb_fde_t *P; - pid_t pid; - rb_dlink_list readq; - rb_dlink_list writeq; - uint8_t shutdown; - uint8_t dead; - char version[256]; -}; - -static void ssld_update_config_one(ssl_ctl_t *ctl); -static void send_new_ssl_certs_one(ssl_ctl_t * ctl); -static void send_certfp_method(ssl_ctl_t *ctl); - - -static rb_dlink_list ssl_daemons; - -static inline uint32_t -buf_to_uint32(char *buf) -{ - uint32_t x; - memcpy(&x, buf, sizeof(x)); - return x; -} - -static inline void -uint32_to_buf(char *buf, uint32_t x) -{ - memcpy(buf, &x, sizeof(x)); - return; -} - -static ssl_ctl_t * -allocate_ssl_daemon(rb_fde_t * F, rb_fde_t * P, int pid) -{ - ssl_ctl_t *ctl; - - if(F == NULL || pid < 0) - return NULL; - ctl = (ssl_ctl_t *)rb_malloc(sizeof(ssl_ctl_t)); - ctl->F = F; - ctl->P = P; - ctl->pid = pid; - ssld_count++; - rb_dlinkAdd(ctl, &ctl->node, &ssl_daemons); - return ctl; -} - -static void -free_ssl_daemon(ssl_ctl_t * ctl) -{ - rb_dlink_node *ptr; - ssl_ctl_buf_t *ctl_buf; - int x; - if(ctl->cli_count) - return; - - RB_DLINK_FOREACH(ptr, ctl->readq.head) - { - ctl_buf = (ssl_ctl_buf_t *)ptr->data; - for(x = 0; x < ctl_buf->nfds; x++) - rb_close(ctl_buf->F[x]); - - rb_free(ctl_buf->buf); - rb_free(ctl_buf); - } - - RB_DLINK_FOREACH(ptr, ctl->writeq.head) - { - ctl_buf = (ssl_ctl_buf_t *)ptr->data; - for(x = 0; x < ctl_buf->nfds; x++) - rb_close(ctl_buf->F[x]); - - rb_free(ctl_buf->buf); - rb_free(ctl_buf); - } - rb_close(ctl->F); - rb_close(ctl->P); - rb_dlinkDelete(&ctl->node, &ssl_daemons); - rb_free(ctl); -} - -static char *ssld_path; - -static int ssld_spin_count = 0; -static time_t last_spin; -static int ssld_wait = 0; - - -void -restart_ssld(void) -{ - rb_dlink_node *ptr, *next; - ssl_ctl_t *ctl; - - RB_DLINK_FOREACH_SAFE(ptr, next, ssl_daemons.head) - { - ctl = (ssl_ctl_t *)ptr->data; - if(ctl->dead) - continue; - if(ctl->shutdown) - continue; - ctl->shutdown = 1; - ssld_count--; - if(!ctl->cli_count) - { - rb_kill(ctl->pid, SIGKILL); - free_ssl_daemon(ctl); - } - } - - ssld_spin_count = 0; - last_spin = 0; - ssld_wait = 0; - start_ssldaemon(ServerInfo.ssld_count); -} - -static void -ssl_killall(void) -{ - rb_dlink_node *ptr, *next; - ssl_ctl_t *ctl; - RB_DLINK_FOREACH_SAFE(ptr, next, ssl_daemons.head) - { - ctl = (ssl_ctl_t *)ptr->data; - if(ctl->dead) - continue; - ctl->dead = 1; - if(!ctl->shutdown) - ssld_count--; - rb_kill(ctl->pid, SIGKILL); - if(!ctl->cli_count) - free_ssl_daemon(ctl); - } -} - -static void -ssl_dead(ssl_ctl_t * ctl) -{ - if(ctl->dead) - return; - - ctl->dead = 1; - rb_kill(ctl->pid, SIGKILL); /* make sure the process is really gone */ - - if(!ctl->shutdown) - { - ssld_count--; - ilog(L_MAIN, "ssld helper died - attempting to restart"); - sendto_realops_snomask(sno::GENERAL, L_ALL, "ssld helper died - attempting to restart"); - start_ssldaemon(1); - } -} - -static void -ssl_do_pipe(rb_fde_t * F, void *data) -{ - int retlen; - ssl_ctl_t *ctl = (ssl_ctl_t *)data; - retlen = rb_write(F, "0", 1); - if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno))) - { - ssl_dead(ctl); - return; - } - rb_setselect(F, RB_SELECT_READ, ssl_do_pipe, data); -} - -static void -restart_ssld_event(void *unused) -{ - ssld_spin_count = 0; - last_spin = 0; - ssld_wait = 0; - if(ServerInfo.ssld_count > get_ssld_count()) - { - int start = ServerInfo.ssld_count - get_ssld_count(); - ilog(L_MAIN, "Attempting to restart ssld processes"); - sendto_realops_snomask(sno::GENERAL, L_ALL, "Attempt to restart ssld processes"); - start_ssldaemon(start); - } -} - -int -start_ssldaemon(int count) -{ - rb_fde_t *F1, *F2; - rb_fde_t *P1, *P2; -#ifdef _WIN32 - const char *suffix = ".exe"; -#else - const char *suffix = ""; -#endif - - char fullpath[PATH_MAX + 1]; - char fdarg[6]; - const char *parv[2]; - char buf[128]; - char s_pid[10]; - pid_t pid; - int started = 0, i; - - if(ssld_wait) - return 0; - - if(ssld_spin_count > 20 && (rb_current_time() - last_spin < 5)) - { - ilog(L_MAIN, "ssld helper is spinning - will attempt to restart in 1 minute"); - sendto_realops_snomask(sno::GENERAL, L_ALL, - "ssld helper is spinning - will attempt to restart in 1 minute"); - rb_event_add("restart_ssld_event", restart_ssld_event, NULL, 60); - ssld_wait = 1; - return 0; - } - - ssld_spin_count++; - last_spin = rb_current_time(); - - if(ssld_path == NULL) - { - snprintf(fullpath, sizeof(fullpath), "%s%cssld%s", path::get(path::LIBEXEC), RB_PATH_SEPARATOR, suffix); - - if(access(fullpath, X_OK) == -1) - { - snprintf(fullpath, sizeof(fullpath), "%s%cbin%cssld%s", - ConfigFileEntry.dpath, RB_PATH_SEPARATOR, RB_PATH_SEPARATOR, suffix); - if(access(fullpath, X_OK) == -1) - { - ilog(L_MAIN, - "Unable to execute ssld%s in %s or %s/bin", - suffix, path::get(path::LIBEXEC), ConfigFileEntry.dpath); - return 0; - } - } - ssld_path = rb_strdup(fullpath); - } - rb_strlcpy(buf, "-ircd ssld daemon", sizeof(buf)); - parv[0] = buf; - parv[1] = NULL; - - for(i = 0; i < count; i++) - { - ssl_ctl_t *ctl; - if(rb_socketpair(AF_UNIX, SOCK_DGRAM, 0, &F1, &F2, "SSL/TLS handle passing socket") == -1) - { - ilog(L_MAIN, "Unable to create ssld - rb_socketpair failed: %s", strerror(errno)); - return started; - } - - rb_set_buffers(F1, READBUF_SIZE); - rb_set_buffers(F2, READBUF_SIZE); - snprintf(fdarg, sizeof(fdarg), "%d", rb_get_fd(F2)); - rb_setenv("CTL_FD", fdarg, 1); - if(rb_pipe(&P1, &P2, "SSL/TLS pipe") == -1) - { - ilog(L_MAIN, "Unable to create ssld - rb_pipe failed: %s", strerror(errno)); - return started; - } - snprintf(fdarg, sizeof(fdarg), "%d", rb_get_fd(P1)); - rb_setenv("CTL_PIPE", fdarg, 1); - snprintf(s_pid, sizeof(s_pid), "%d", (int)getpid()); - rb_setenv("CTL_PPID", s_pid, 1); -#ifdef _WIN32 - SetHandleInformation((HANDLE) rb_get_fd(F2), HANDLE_FLAG_INHERIT, 1); - SetHandleInformation((HANDLE) rb_get_fd(P1), HANDLE_FLAG_INHERIT, 1); -#endif - - pid = rb_spawn_process(ssld_path, (const char **) parv); - if(pid == -1) - { - ilog(L_MAIN, "Unable to create ssld: %s\n", strerror(errno)); - rb_close(F1); - rb_close(F2); - rb_close(P1); - rb_close(P2); - return started; - } - started++; - rb_close(F2); - rb_close(P1); - ctl = allocate_ssl_daemon(F1, P2, pid); - if(ircd_ssl_ok) - ssld_update_config_one(ctl); - ssl_read_ctl(ctl->F, ctl); - ssl_do_pipe(P2, ctl); - - } - return started; -} - -static void -ssl_process_zipstats(ssl_ctl_t * ctl, ssl_ctl_buf_t * ctl_buf) -{ - client::client *server; - struct ZipStats *zips; - char *parv[7]; - (void) rb_string_to_array(ctl_buf->buf, parv, 6); - server = find_server(NULL, parv[1]); - if(server == NULL || server->localClient == NULL || !IsCapable(server, CAP_ZIP)) - return; - if(server->localClient->zipstats == NULL) - server->localClient->zipstats = (ZipStats *)rb_malloc(sizeof(struct ZipStats)); - - zips = server->localClient->zipstats; - - zips->in += strtoull(parv[2], NULL, 10); - zips->in_wire += strtoull(parv[3], NULL, 10); - zips->out += strtoull(parv[4], NULL, 10); - zips->out_wire += strtoull(parv[5], NULL, 10); - - if(zips->in > 0) - zips->in_ratio = ((double) (zips->in - zips->in_wire) / (double) zips->in) * 100.00; - else - zips->in_ratio = 0; - - if(zips->out > 0) - zips->out_ratio = ((double) (zips->out - zips->out_wire) / (double) zips->out) * 100.00; - else - zips->out_ratio = 0; -} - -static void -ssl_process_open_fd(ssl_ctl_t * ctl, ssl_ctl_buf_t * ctl_buf) -{ - client::client *client_p; - uint32_t fd; - - if(ctl_buf->buflen < 5) - return; /* bogus message..drop it.. XXX should warn here */ - - fd = buf_to_uint32(&ctl_buf->buf[1]); - client_p = find_cli_connid_hash(fd); - if(client_p == NULL || client_p->localClient == NULL) - return; - - if(client_p->localClient->ssl_callback) - { - client::SSL_OPEN_CB *hdl = client_p->localClient->ssl_callback; - - client_p->localClient->ssl_callback = NULL; - - hdl(client_p, RB_OK); - } -} - -static void -ssl_process_dead_fd(ssl_ctl_t * ctl, ssl_ctl_buf_t * ctl_buf) -{ - client::client *client_p; - char reason[256]; - uint32_t fd; - - if(ctl_buf->buflen < 6) - return; /* bogus message..drop it.. XXX should warn here */ - - fd = buf_to_uint32(&ctl_buf->buf[1]); - rb_strlcpy(reason, &ctl_buf->buf[5], sizeof(reason)); - client_p = find_cli_connid_hash(fd); - if(client_p == NULL || client_p->localClient == NULL) - return; - - if(is_any_server(*client_p)) - { - sendto_realops_snomask(sno::GENERAL, is_remote_connect(client_p) && !is_server(*client_p) ? L_NETWIDE : L_ALL, "ssld error for %s: %s", client_p->name, reason); - ilog(L_SERVER, "ssld error for %s: %s", log_client_name(client_p, SHOW_IP), reason); - } - - /* if there is still a pending callback, call it now */ - if(client_p->localClient->ssl_callback) - { - client::SSL_OPEN_CB *hdl = client_p->localClient->ssl_callback; - - client_p->localClient->ssl_callback = NULL; - - if (hdl(client_p, RB_ERROR_SSL)) - { - /* the callback has exited the client */ - return; - } - } - - if(is_any_server(*client_p) || is_registered(*client_p)) - { - /* read any last moment ERROR, QUIT or the like -- jilles */ - if (!strcmp(reason, "Remote host closed the connection")) - read_packet(client_p->localClient->F, client_p); - if (is_any_dead(*client_p)) - return; - } - exit_client(client_p, client_p, &me, reason); -} - - -static void -ssl_process_cipher_string(ssl_ctl_t *ctl, ssl_ctl_buf_t *ctl_buf) -{ - client::client *client_p; - const char *cstring; - uint32_t fd; - - if(ctl_buf->buflen < 6) - return; /* bogus message..drop it.. XXX should warn here */ - - fd = buf_to_uint32(&ctl_buf->buf[1]); - cstring = (const char *)&ctl_buf->buf[5]; - - if(EmptyString(cstring)) - return; - - client_p = find_cli_connid_hash(fd); - if(client_p != NULL && client_p->localClient != NULL) - { - rb_free(client_p->localClient->cipher_string); - client_p->localClient->cipher_string = rb_strdup(cstring); - } -} - - -static void -ssl_process_certfp(ssl_ctl_t * ctl, ssl_ctl_buf_t * ctl_buf) -{ - client::client *client_p; - uint32_t fd; - uint32_t certfp_method; - uint32_t len; - uint8_t *certfp; - char *certfp_string; - const char *method_string; - int method_len; - - if(ctl_buf->buflen > 13 + RB_SSL_CERTFP_LEN) - return; /* bogus message..drop it.. XXX should warn here */ - - fd = buf_to_uint32(&ctl_buf->buf[1]); - certfp_method = buf_to_uint32(&ctl_buf->buf[5]); - len = buf_to_uint32(&ctl_buf->buf[9]); - certfp = (uint8_t *)&ctl_buf->buf[13]; - client_p = find_cli_connid_hash(fd); - if(client_p == NULL) - return; - - switch (certfp_method) { - case RB_SSL_CERTFP_METH_CERT_SHA1: - method_string = CERTFP_PREFIX_CERT_SHA1; - break; - case RB_SSL_CERTFP_METH_CERT_SHA256: - method_string = CERTFP_PREFIX_CERT_SHA256; - break; - case RB_SSL_CERTFP_METH_CERT_SHA512: - method_string = CERTFP_PREFIX_CERT_SHA512; - break; - case RB_SSL_CERTFP_METH_SPKI_SHA256: - method_string = CERTFP_PREFIX_SPKI_SHA256; - break; - case RB_SSL_CERTFP_METH_SPKI_SHA512: - method_string = CERTFP_PREFIX_SPKI_SHA512; - break; - default: - return; - } - method_len = strlen(method_string); - - rb_free(client_p->certfp); - certfp_string = (char *)rb_malloc(method_len + len * 2 + 1); - rb_strlcpy(certfp_string, method_string, method_len + len * 2 + 1); - for(uint32_t i = 0; i < len; i++) - snprintf(certfp_string + method_len + 2 * i, 3, "%02x", - certfp[i]); - client_p->certfp = certfp_string; -} - -static void -ssl_process_cmd_recv(ssl_ctl_t * ctl) -{ - static const char *cannot_setup_ssl = "ssld cannot setup ssl, check your certificates and private key"; - static const char *no_ssl_or_zlib = "ssld has neither SSL/TLS or zlib support killing all sslds"; - rb_dlink_node *ptr, *next; - ssl_ctl_buf_t *ctl_buf; - unsigned long len; - - if(ctl->dead) - return; - - RB_DLINK_FOREACH_SAFE(ptr, next, ctl->readq.head) - { - ctl_buf = (ssl_ctl_buf_t *)ptr->data; - switch (*ctl_buf->buf) - { - case 'N': - ircd_ssl_ok = false; /* ssld says it can't do ssl/tls */ - break; - case 'O': - ssl_process_open_fd(ctl, ctl_buf); - break; - case 'D': - ssl_process_dead_fd(ctl, ctl_buf); - break; - case 'C': - ssl_process_cipher_string(ctl, ctl_buf); - break; - case 'F': - ssl_process_certfp(ctl, ctl_buf); - break; - case 'S': - ssl_process_zipstats(ctl, ctl_buf); - break; - case 'I': - ircd_ssl_ok = false; - ilog(L_MAIN, "%s", cannot_setup_ssl); - sendto_realops_snomask(sno::GENERAL, L_ALL, "%s", cannot_setup_ssl); - break; - case 'U': - ircd_zlib_ok = 0; - ircd_ssl_ok = false; - ilog(L_MAIN, "%s", no_ssl_or_zlib); - sendto_realops_snomask(sno::GENERAL, L_ALL, "%s", no_ssl_or_zlib); - ssl_killall(); - return; - case 'V': - len = ctl_buf->buflen - 1; - if (len > sizeof(ctl->version) - 1) - len = sizeof(ctl->version) - 1; - strncpy(ctl->version, &ctl_buf->buf[1], len); - case 'z': - ircd_zlib_ok = 0; - break; - default: - ilog(L_MAIN, "Received invalid command from ssld: %s", ctl_buf->buf); - sendto_realops_snomask(sno::GENERAL, L_ALL, "Received invalid command from ssld"); - break; - } - rb_dlinkDelete(ptr, &ctl->readq); - rb_free(ctl_buf->buf); - rb_free(ctl_buf); - } - -} - - -static void -ssl_read_ctl(rb_fde_t * F, void *data) -{ - ssl_ctl_buf_t *ctl_buf; - ssl_ctl_t *ctl = (ssl_ctl_t *)data; - int retlen; - - if(ctl->dead) - return; - do - { - ctl_buf = (ssl_ctl_buf_t *)rb_malloc(sizeof(ssl_ctl_buf_t)); - ctl_buf->buf = (char *)rb_malloc(READSIZE); - retlen = rb_recv_fd_buf(ctl->F, ctl_buf->buf, READSIZE, ctl_buf->F, 4); - ctl_buf->buflen = retlen; - if(retlen <= 0) - { - rb_free(ctl_buf->buf); - rb_free(ctl_buf); - } - else - rb_dlinkAddTail(ctl_buf, &ctl_buf->node, &ctl->readq); - } - while(retlen > 0); - - if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno))) - { - ssl_dead(ctl); - return; - } - ssl_process_cmd_recv(ctl); - rb_setselect(ctl->F, RB_SELECT_READ, ssl_read_ctl, ctl); -} - -static ssl_ctl_t * -which_ssld(void) -{ - ssl_ctl_t *ctl, *lowest = NULL; - rb_dlink_node *ptr; - - RB_DLINK_FOREACH(ptr, ssl_daemons.head) - { - ctl = (ssl_ctl_t *)ptr->data; - if(ctl->dead) - continue; - if(ctl->shutdown) - continue; - if(lowest == NULL) - { - lowest = ctl; - continue; - } - if(ctl->cli_count < lowest->cli_count) - lowest = ctl; - } - return (lowest); -} - -static void -ssl_write_ctl(rb_fde_t * F, void *data) -{ - ssl_ctl_t *ctl = (ssl_ctl_t *)data; - ssl_ctl_buf_t *ctl_buf; - rb_dlink_node *ptr, *next; - int retlen, x; - - if(ctl->dead) - return; - - RB_DLINK_FOREACH_SAFE(ptr, next, ctl->writeq.head) - { - ctl_buf = (ssl_ctl_buf_t *)ptr->data; - /* in theory unix sock_dgram shouldn't ever short write this.. */ - retlen = rb_send_fd_buf(ctl->F, ctl_buf->F, ctl_buf->nfds, ctl_buf->buf, ctl_buf->buflen, ctl->pid); - if(retlen > 0) - { - rb_dlinkDelete(ptr, &ctl->writeq); - for(x = 0; x < ctl_buf->nfds; x++) - rb_close(ctl_buf->F[x]); - rb_free(ctl_buf->buf); - rb_free(ctl_buf); - - } - if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno))) - { - ssl_dead(ctl); - return; - } - else - { - rb_setselect(ctl->F, RB_SELECT_WRITE, ssl_write_ctl, ctl); - } - } -} - -static void -ssl_cmd_write_queue(ssl_ctl_t * ctl, rb_fde_t ** F, int count, const void *buf, size_t buflen) -{ - ssl_ctl_buf_t *ctl_buf; - int x; - - /* don't bother */ - if(ctl->dead) - return; - - ctl_buf = (ssl_ctl_buf_t *)rb_malloc(sizeof(ssl_ctl_buf_t)); - ctl_buf->buf = (char *)rb_malloc(buflen); - memcpy(ctl_buf->buf, buf, buflen); - ctl_buf->buflen = buflen; - - for(x = 0; x < count && x < MAXPASSFD; x++) - { - ctl_buf->F[x] = F[x]; - } - ctl_buf->nfds = count; - rb_dlinkAddTail(ctl_buf, &ctl_buf->node, &ctl->writeq); - ssl_write_ctl(ctl->F, ctl); -} - - -static void -send_new_ssl_certs_one(ssl_ctl_t * ctl) -{ - size_t len = 5; - - if(ServerInfo.ssl_cert) - len += strlen(ServerInfo.ssl_cert); - else - return; - - if(ServerInfo.ssl_private_key) - len += strlen(ServerInfo.ssl_private_key); - - if(ServerInfo.ssl_dh_params) - len += strlen(ServerInfo.ssl_dh_params); - - if(ServerInfo.ssl_cipher_list) - len += strlen(ServerInfo.ssl_cipher_list); - - if(len > sizeof(tmpbuf)) - { - sendto_realops_snomask(sno::GENERAL, L_ALL, - "Parameters for send_new_ssl_certs_one too long (%zu > %zu) to pass to ssld, not sending...", - len, sizeof(tmpbuf)); - ilog(L_MAIN, - "Parameters for send_new_ssl_certs_one too long (%zu > %zu) to pass to ssld, not sending...", - len, sizeof(tmpbuf)); - return; - } - - int ret = snprintf(tmpbuf, sizeof(tmpbuf), "K%c%s%c%s%c%s%c%s%c", nul, - ServerInfo.ssl_cert, nul, - ServerInfo.ssl_private_key != NULL ? ServerInfo.ssl_private_key : "", nul, - ServerInfo.ssl_dh_params != NULL ? ServerInfo.ssl_dh_params : "", nul, - ServerInfo.ssl_cipher_list != NULL ? ServerInfo.ssl_cipher_list : "", nul); - - if(ret > 5) - ssl_cmd_write_queue(ctl, NULL, 0, tmpbuf, (size_t) ret); -} - -static void -send_certfp_method(ssl_ctl_t *ctl) -{ - char buf[5]; - - buf[0] = 'F'; - uint32_to_buf(&buf[1], ConfigFileEntry.certfp_method); - ssl_cmd_write_queue(ctl, NULL, 0, buf, sizeof(buf)); -} - -static void -ssld_update_config_one(ssl_ctl_t *ctl) -{ - send_certfp_method(ctl); - send_new_ssl_certs_one(ctl); -} - -void -ssld_update_config(void) -{ - rb_dlink_node *ptr; - - RB_DLINK_FOREACH(ptr, ssl_daemons.head) - { - ssl_ctl_t *ctl = (ssl_ctl_t *)ptr->data; - - if (ctl->dead || ctl->shutdown) - continue; - - ssld_update_config_one(ctl); - } -} - -ssl_ctl_t * -start_ssld_accept(rb_fde_t * sslF, rb_fde_t * plainF, uint32_t id) -{ - rb_fde_t *F[2]; - ssl_ctl_t *ctl; - char buf[5]; - F[0] = sslF; - F[1] = plainF; - - buf[0] = 'A'; - uint32_to_buf(&buf[1], id); - ctl = which_ssld(); - if(!ctl) - return NULL; - ctl->cli_count++; - ssl_cmd_write_queue(ctl, F, 2, buf, sizeof(buf)); - return ctl; -} - -ssl_ctl_t * -start_ssld_connect(rb_fde_t * sslF, rb_fde_t * plainF, uint32_t id) -{ - rb_fde_t *F[2]; - ssl_ctl_t *ctl; - char buf[5]; - F[0] = sslF; - F[1] = plainF; - - buf[0] = 'C'; - uint32_to_buf(&buf[1], id); - - ctl = which_ssld(); - if(!ctl) - return NULL; - ctl->cli_count++; - ssl_cmd_write_queue(ctl, F, 2, buf, sizeof(buf)); - return ctl; -} - -void -ssld_decrement_clicount(ssl_ctl_t * ctl) -{ - if(ctl == NULL) - return; - - ctl->cli_count--; - if(ctl->shutdown && !ctl->cli_count) - { - ctl->dead = 1; - rb_kill(ctl->pid, SIGKILL); - } - if(ctl->dead && !ctl->cli_count) - { - free_ssl_daemon(ctl); - } -} - -/* - * what we end up sending to the ssld process for ziplinks is the following - * Z[ourfd][level][RECVQ] - * Z = ziplinks command = buf[0] - * ourfd = Our end of the socketpair = buf[1..4] - * level = zip level buf[5] - * recvqlen = our recvq len = buf[6-7] - * recvq = any data we read prior to starting ziplinks - */ -void -start_zlib_session(void *data) -{ - client::client *server = (client::client *) data; - uint16_t recvqlen; - uint8_t level; - void *xbuf; - - rb_fde_t *F[2]; - rb_fde_t *xF1, *xF2; - char *buf; - void *recvq_start; - - size_t hdr = (sizeof(uint8_t) * 2) + sizeof(uint32_t); - size_t len; - int cpylen, left; - - server->localClient->event = NULL; - - recvqlen = rb_linebuf_len(&server->localClient->buf_recvq); - - len = recvqlen + hdr; - - if(len > READBUF_SIZE) - { - sendto_realops_snomask(sno::GENERAL, L_ALL, - "ssld - attempted to pass message of %zd len, max len %d, giving up", - len, READBUF_SIZE); - ilog(L_MAIN, "ssld - attempted to pass message of %zd len, max len %d, giving up", len, READBUF_SIZE); - exit_client(server, server, server, "ssld readbuf exceeded"); - return; - } - - buf = (char *)rb_malloc(len); - level = ConfigFileEntry.compression_level; - - uint32_to_buf(&buf[1], rb_get_fd(server->localClient->F)); - buf[5] = (char) level; - - recvq_start = &buf[6]; - server->localClient->zipstats = (ZipStats *)rb_malloc(sizeof(struct ZipStats)); - - xbuf = recvq_start; - left = recvqlen; - - do - { - cpylen = rb_linebuf_get(&server->localClient->buf_recvq, (char *)xbuf, left, LINEBUF_PARTIAL, LINEBUF_RAW); - left -= cpylen; - xbuf = (void *) (((uintptr_t) xbuf) + cpylen); - } - while(cpylen > 0); - - /* Pass the socket to ssld. */ - *buf = 'Z'; - if(rb_socketpair(AF_UNIX, SOCK_STREAM, 0, &xF1, &xF2, "Initial zlib socketpairs") == -1) - { - sendto_realops_snomask(sno::GENERAL, L_ALL, "Error creating zlib socketpair - %s", strerror(errno)); - ilog(L_MAIN, "Error creating zlib socketpairs - %s", strerror(errno)); - exit_client(server, server, server, "Error creating zlib socketpair"); - rb_free(buf); - return; - } - - F[0] = server->localClient->F; - F[1] = xF1; - server->localClient->F = xF2; - /* need to redo as what we did before isn't valid now */ - uint32_to_buf(&buf[1], connid_get(server)); - - server->localClient->z_ctl = which_ssld(); - if(!server->localClient->z_ctl) - { - exit_client(server, server, server, "Error finding available ssld"); - rb_free(buf); - return; - } - server->localClient->z_ctl->cli_count++; - ssl_cmd_write_queue(server->localClient->z_ctl, F, 2, buf, len); - rb_free(buf); -} - -static void -collect_zipstats(void *unused) -{ - rb_dlink_node *ptr; - client::client *target_p; - char buf[sizeof(uint8_t) + sizeof(uint32_t) + HOSTLEN]; - void *odata; - size_t len; - uint32_t id; - - buf[0] = 'S'; - odata = buf + sizeof(uint8_t) + sizeof(uint32_t); - - RB_DLINK_FOREACH(ptr, serv_list.head) - { - target_p = (client::client *)ptr->data; - if(IsCapable(target_p, CAP_ZIP)) - { - len = sizeof(uint8_t) + sizeof(uint32_t); - - id = rb_get_fd(target_p->localClient->F); - uint32_to_buf(&buf[1], id); - rb_strlcpy((char *)odata, target_p->name, (sizeof(buf) - len)); - len += strlen((const char *)odata) + 1; /* Get the \0 as well */ - ssl_cmd_write_queue(target_p->localClient->z_ctl, NULL, 0, buf, len); - } - } -} - -static void -cleanup_dead_ssl(void *unused) -{ - rb_dlink_node *ptr, *next; - ssl_ctl_t *ctl; - RB_DLINK_FOREACH_SAFE(ptr, next, ssl_daemons.head) - { - ctl = (ssl_ctl_t *)ptr->data; - if(ctl->dead && !ctl->cli_count) - { - free_ssl_daemon(ctl); - } - } -} - -int -get_ssld_count(void) -{ - return ssld_count; -} - -void -ssld_foreach_info(void (*func)(void *data, pid_t pid, int cli_count, enum ssld_status status, const char *version), void *data) -{ - rb_dlink_node *ptr, *next; - ssl_ctl_t *ctl; - RB_DLINK_FOREACH_SAFE(ptr, next, ssl_daemons.head) - { - ctl = (ssl_ctl_t *)ptr->data; - func(data, ctl->pid, ctl->cli_count, - ctl->dead ? SSLD_DEAD : - (ctl->shutdown ? SSLD_SHUTDOWN : SSLD_ACTIVE), - ctl->version); - } -} - -void -init_ssld(void) -{ - rb_event_addish("collect_zipstats", collect_zipstats, NULL, ZIPSTATS_TIME); - rb_event_addish("cleanup_dead_ssld", cleanup_dead_ssl, NULL, 60); -} - -} - diff --git a/ircd/wsproc.cc b/ircd/wsproc.cc deleted file mode 100644 index 0ce81f5e8..000000000 --- a/ircd/wsproc.cc +++ /dev/null @@ -1,583 +0,0 @@ -/* - * sslproc.c: An interface to wsockd - * Copyright (C) 2007 Aaron Sethman - * Copyright (C) 2007 ircd-ratbox development team - * - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -namespace ircd { - -static void ws_read_ctl(rb_fde_t * F, void *data); -static int wsockd_count; - -static char tmpbuf[READBUF_SIZE]; -static char nul = '\0'; - -#define MAXPASSFD 4 -#define READSIZE 1024 -typedef struct _ws_ctl_buf -{ - rb_dlink_node node; - char *buf; - size_t buflen; - rb_fde_t *F[MAXPASSFD]; - int nfds; -} ws_ctl_buf_t; - - -struct ws_ctl -{ - rb_dlink_node node; - int cli_count; - rb_fde_t *F; - rb_fde_t *P; - pid_t pid; - rb_dlink_list readq; - rb_dlink_list writeq; - uint8_t shutdown; - uint8_t dead; -}; - -static rb_dlink_list wsock_daemons; - -static inline uint32_t -buf_to_uint32(char *buf) -{ - uint32_t x; - memcpy(&x, buf, sizeof(x)); - return x; -} - -static inline void -uint32_to_buf(char *buf, uint32_t x) -{ - memcpy(buf, &x, sizeof(x)); - return; -} - -static ws_ctl_t * -allocate_ws_daemon(rb_fde_t * F, rb_fde_t * P, int pid) -{ - ws_ctl_t *ctl; - - if(F == NULL || pid < 0) - return NULL; - ctl = (ws_ctl_t *)rb_malloc(sizeof(ws_ctl_t)); - ctl->F = F; - ctl->P = P; - ctl->pid = pid; - wsockd_count++; - rb_dlinkAdd(ctl, &ctl->node, &wsock_daemons); - return ctl; -} - -static void -free_ws_daemon(ws_ctl_t * ctl) -{ - rb_dlink_node *ptr; - ws_ctl_buf_t *ctl_buf; - int x; - if(ctl->cli_count) - return; - - RB_DLINK_FOREACH(ptr, ctl->readq.head) - { - ctl_buf = (ws_ctl_buf_t *)ptr->data; - for(x = 0; x < ctl_buf->nfds; x++) - rb_close(ctl_buf->F[x]); - - rb_free(ctl_buf->buf); - rb_free(ctl_buf); - } - - RB_DLINK_FOREACH(ptr, ctl->writeq.head) - { - ctl_buf = (ws_ctl_buf_t *)ptr->data; - for(x = 0; x < ctl_buf->nfds; x++) - rb_close(ctl_buf->F[x]); - - rb_free(ctl_buf->buf); - rb_free(ctl_buf); - } - rb_close(ctl->F); - rb_close(ctl->P); - rb_dlinkDelete(&ctl->node, &wsock_daemons); - rb_free(ctl); -} - -static char *wsockd_path; - -static int wsockd_spin_count = 0; -static time_t last_spin; -static int wsockd_wait = 0; - -void -restart_wsockd(void) -{ - rb_dlink_node *ptr, *next; - ws_ctl_t *ctl; - - RB_DLINK_FOREACH_SAFE(ptr, next, wsock_daemons.head) - { - ctl = (ws_ctl_t *)ptr->data; - if(ctl->dead) - continue; - if(ctl->shutdown) - continue; - ctl->shutdown = 1; - wsockd_count--; - if(!ctl->cli_count) - { - rb_kill(ctl->pid, SIGKILL); - free_ws_daemon(ctl); - } - } - - start_wsockd(ServerInfo.wsockd_count); -} - -#if 0 -static void -ws_killall(void) -{ - rb_dlink_node *ptr, *next; - ws_ctl_t *ctl; - RB_DLINK_FOREACH_SAFE(ptr, next, wsock_daemons.head) - { - ctl = ptr->data; - if(ctl->dead) - continue; - ctl->dead = 1; - if(!ctl->shutdown) - wsockd_count--; - rb_kill(ctl->pid, SIGKILL); - if(!ctl->cli_count) - free_ws_daemon(ctl); - } -} -#endif - -static void -ws_dead(ws_ctl_t * ctl) -{ - if(ctl->dead) - return; - - ctl->dead = 1; - rb_kill(ctl->pid, SIGKILL); /* make sure the process is really gone */ - - if(!ctl->shutdown) - { - wsockd_count--; - ilog(L_MAIN, "wsockd helper died - attempting to restart"); - sendto_realops_snomask(sno::GENERAL, L_ALL, "wsockd helper died - attempting to restart"); - start_wsockd(1); - } -} - -static void -ws_do_pipe(rb_fde_t * F, void *data) -{ - int retlen; - ws_ctl_t *ctl = (ws_ctl_t *)data; - retlen = rb_write(F, "0", 1); - if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno))) - { - ws_dead(ctl); - return; - } - rb_setselect(F, RB_SELECT_READ, ws_do_pipe, data); -} - -static void -restart_wsockd_event(void *unused) -{ - wsockd_spin_count = 0; - last_spin = 0; - wsockd_wait = 0; - if(ServerInfo.wsockd_count > get_wsockd_count()) - { - int start = ServerInfo.wsockd_count - get_wsockd_count(); - ilog(L_MAIN, "Attempting to restart wsockd processes"); - sendto_realops_snomask(sno::GENERAL, L_ALL, "Attempting to restart wsockd processes"); - start_wsockd(start); - } -} - -int -start_wsockd(int count) -{ - rb_fde_t *F1, *F2; - rb_fde_t *P1, *P2; -#ifdef _WIN32 - const char *suffix = ".exe"; -#else - const char *suffix = ""; -#endif - - char fullpath[PATH_MAX + 1]; - char fdarg[6]; - const char *parv[2]; - char buf[128]; - char s_pid[10]; - pid_t pid; - int started = 0, i; - - if(wsockd_wait) - return 0; - - if(wsockd_spin_count > 20 && (rb_current_time() - last_spin < 5)) - { - ilog(L_MAIN, "wsockd helper is spinning - will attempt to restart in 1 minute"); - sendto_realops_snomask(sno::GENERAL, L_ALL, - "wsockd helper is spinning - will attempt to restart in 1 minute"); - rb_event_add("restart_wsockd_event", restart_wsockd_event, NULL, 60); - wsockd_wait = 1; - return 0; - } - - wsockd_spin_count++; - last_spin = rb_current_time(); - - if(wsockd_path == NULL) - { - snprintf(fullpath, sizeof(fullpath), "%s%cwsockd%s", path::get(path::LIBEXEC), RB_PATH_SEPARATOR, suffix); - - if(access(fullpath, X_OK) == -1) - { - snprintf(fullpath, sizeof(fullpath), "%s%cbin%cwsockd%s", - ConfigFileEntry.dpath, RB_PATH_SEPARATOR, RB_PATH_SEPARATOR, suffix); - if(access(fullpath, X_OK) == -1) - { - ilog(L_MAIN, - "Unable to execute wsockd%s in %s or %s/bin", - suffix, path::get(path::LIBEXEC), ConfigFileEntry.dpath); - return 0; - } - } - wsockd_path = rb_strdup(fullpath); - } - rb_strlcpy(buf, "-ircd wsockd daemon", sizeof(buf)); - parv[0] = buf; - parv[1] = NULL; - - for(i = 0; i < count; i++) - { - ws_ctl_t *ctl; - if(rb_socketpair(AF_UNIX, SOCK_DGRAM, 0, &F1, &F2, "wsockd handle passing socket") == -1) - { - ilog(L_MAIN, "Unable to create wsockd - rb_socketpair failed: %s", strerror(errno)); - return started; - } - - rb_set_buffers(F1, READBUF_SIZE); - rb_set_buffers(F2, READBUF_SIZE); - snprintf(fdarg, sizeof(fdarg), "%d", rb_get_fd(F2)); - rb_setenv("CTL_FD", fdarg, 1); - if(rb_pipe(&P1, &P2, "wsockd pipe") == -1) - { - ilog(L_MAIN, "Unable to create wsockd - rb_pipe failed: %s", strerror(errno)); - return started; - } - snprintf(fdarg, sizeof(fdarg), "%d", rb_get_fd(P1)); - rb_setenv("CTL_PIPE", fdarg, 1); - snprintf(s_pid, sizeof(s_pid), "%d", (int)getpid()); - rb_setenv("CTL_PPID", s_pid, 1); - -#ifdef _WIN32 - SetHandleInformation((HANDLE) rb_get_fd(F2), HANDLE_FLAG_INHERIT, 1); - SetHandleInformation((HANDLE) rb_get_fd(P1), HANDLE_FLAG_INHERIT, 1); -#endif - - pid = rb_spawn_process(wsockd_path, (const char **) parv); - if(pid == -1) - { - ilog(L_MAIN, "Unable to create wsockd: %s\n", strerror(errno)); - rb_close(F1); - rb_close(F2); - rb_close(P1); - rb_close(P2); - return started; - } - started++; - rb_close(F2); - rb_close(P1); - ctl = allocate_ws_daemon(F1, P2, pid); - ws_read_ctl(ctl->F, ctl); - ws_do_pipe(P2, ctl); - - } - return started; -} - -static void -ws_process_dead_fd(ws_ctl_t * ctl, ws_ctl_buf_t * ctl_buf) -{ - client::client *client_p; - char reason[256]; - uint32_t fd; - - if(ctl_buf->buflen < 6) - return; /* bogus message..drop it.. XXX should warn here */ - - fd = buf_to_uint32(&ctl_buf->buf[1]); - rb_strlcpy(reason, &ctl_buf->buf[5], sizeof(reason)); - client_p = find_cli_connid_hash(fd); - if(client_p == NULL) - return; - if(is_any_server(*client_p) || is_registered(*client_p)) - { - /* read any last moment ERROR, QUIT or the like -- jilles */ - if (!strcmp(reason, "Remote host closed the connection")) - read_packet(client_p->localClient->F, client_p); - if (is_any_dead(*client_p)) - return; - } - exit_client(client_p, client_p, &me, reason); -} - - -static void -ws_process_cmd_recv(ws_ctl_t * ctl) -{ - rb_dlink_node *ptr, *next; - ws_ctl_buf_t *ctl_buf; - unsigned long len; - - if(ctl->dead) - return; - - RB_DLINK_FOREACH_SAFE(ptr, next, ctl->readq.head) - { - ctl_buf = (ws_ctl_buf_t *)ptr->data; - switch (*ctl_buf->buf) - { - case 'D': - ws_process_dead_fd(ctl, ctl_buf); - break; - default: - ilog(L_MAIN, "Received invalid command from wsockd: %s", ctl_buf->buf); - sendto_realops_snomask(sno::GENERAL, L_ALL, "Received invalid command from wsockd"); - break; - } - rb_dlinkDelete(ptr, &ctl->readq); - rb_free(ctl_buf->buf); - rb_free(ctl_buf); - } - -} - - -static void -ws_read_ctl(rb_fde_t * F, void *data) -{ - ws_ctl_buf_t *ctl_buf; - ws_ctl_t *ctl = (ws_ctl_t *)data; - int retlen; - - if(ctl->dead) - return; - do - { - ctl_buf = (ws_ctl_buf_t *)rb_malloc(sizeof(ws_ctl_buf_t)); - ctl_buf->buf = (char *)rb_malloc(READSIZE); - retlen = rb_recv_fd_buf(ctl->F, ctl_buf->buf, READSIZE, ctl_buf->F, 4); - ctl_buf->buflen = retlen; - if(retlen <= 0) - { - rb_free(ctl_buf->buf); - rb_free(ctl_buf); - } - else - rb_dlinkAddTail(ctl_buf, &ctl_buf->node, &ctl->readq); - } - while(retlen > 0); - - if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno))) - { - ws_dead(ctl); - return; - } - ws_process_cmd_recv(ctl); - rb_setselect(ctl->F, RB_SELECT_READ, ws_read_ctl, ctl); -} - -static ws_ctl_t * -which_wsockd(void) -{ - ws_ctl_t *ctl, *lowest = NULL; - rb_dlink_node *ptr; - - RB_DLINK_FOREACH(ptr, wsock_daemons.head) - { - ctl = (ws_ctl_t *)ptr->data; - if(ctl->dead) - continue; - if(ctl->shutdown) - continue; - if(lowest == NULL) - { - lowest = ctl; - continue; - } - if(ctl->cli_count < lowest->cli_count) - lowest = ctl; - } - - return (lowest); -} - -static void -ws_write_ctl(rb_fde_t * F, void *data) -{ - ws_ctl_t *ctl = (ws_ctl_t *)data; - ws_ctl_buf_t *ctl_buf; - rb_dlink_node *ptr, *next; - int retlen, x; - - if(ctl->dead) - return; - - RB_DLINK_FOREACH_SAFE(ptr, next, ctl->writeq.head) - { - ctl_buf = (ws_ctl_buf_t *)ptr->data; - /* in theory unix sock_dgram shouldn't ever short write this.. */ - retlen = rb_send_fd_buf(ctl->F, ctl_buf->F, ctl_buf->nfds, ctl_buf->buf, ctl_buf->buflen, ctl->pid); - if(retlen > 0) - { - rb_dlinkDelete(ptr, &ctl->writeq); - for(x = 0; x < ctl_buf->nfds; x++) - rb_close(ctl_buf->F[x]); - rb_free(ctl_buf->buf); - rb_free(ctl_buf); - - } - if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno))) - { - ws_dead(ctl); - return; - } - else - { - rb_setselect(ctl->F, RB_SELECT_WRITE, ws_write_ctl, ctl); - } - } -} - -static void -ws_cmd_write_queue(ws_ctl_t * ctl, rb_fde_t ** F, int count, const void *buf, size_t buflen) -{ - ws_ctl_buf_t *ctl_buf; - int x; - - /* don't bother */ - if(ctl->dead) - return; - - ctl_buf = (ws_ctl_buf_t *)rb_malloc(sizeof(ws_ctl_buf_t)); - ctl_buf->buf = (char *)rb_malloc(buflen); - memcpy(ctl_buf->buf, buf, buflen); - ctl_buf->buflen = buflen; - - for(x = 0; x < count && x < MAXPASSFD; x++) - { - ctl_buf->F[x] = F[x]; - } - ctl_buf->nfds = count; - rb_dlinkAddTail(ctl_buf, &ctl_buf->node, &ctl->writeq); - ws_write_ctl(ctl->F, ctl); -} - -ws_ctl_t * -start_wsockd_accept(rb_fde_t * sslF, rb_fde_t * plainF, uint32_t id) -{ - rb_fde_t *F[2]; - ws_ctl_t *ctl; - char buf[5]; - F[0] = sslF; - F[1] = plainF; - - buf[0] = 'A'; - uint32_to_buf(&buf[1], id); - ctl = which_wsockd(); - if(!ctl) - return NULL; - ctl->cli_count++; - ws_cmd_write_queue(ctl, F, 2, buf, sizeof(buf)); - return ctl; -} - -void -wsockd_decrement_clicount(ws_ctl_t * ctl) -{ - if(ctl == NULL) - return; - - ctl->cli_count--; - if(ctl->shutdown && !ctl->cli_count) - { - ctl->dead = 1; - rb_kill(ctl->pid, SIGKILL); - } - if(ctl->dead && !ctl->cli_count) - { - free_ws_daemon(ctl); - } -} - -static void -cleanup_dead_ws(void *unused) -{ - rb_dlink_node *ptr, *next; - ws_ctl_t *ctl; - RB_DLINK_FOREACH_SAFE(ptr, next, wsock_daemons.head) - { - ctl = (ws_ctl_t *)ptr->data; - if(ctl->dead && !ctl->cli_count) - { - free_ws_daemon(ctl); - } - } -} - -int -get_wsockd_count(void) -{ - return wsockd_count; -} - -void -wsockd_foreach_info(void (*func)(void *data, pid_t pid, int cli_count, enum wsockd_status status), void *data) -{ - rb_dlink_node *ptr, *next; - ws_ctl_t *ctl; - RB_DLINK_FOREACH_SAFE(ptr, next, wsock_daemons.head) - { - ctl = (ws_ctl_t *)ptr->data; - func(data, ctl->pid, ctl->cli_count, - ctl->dead ? WSOCKD_DEAD : - (ctl->shutdown ? WSOCKD_SHUTDOWN : WSOCKD_ACTIVE)); - } -} - -void -init_wsockd(void) -{ - rb_event_addish("cleanup_dead_ws", cleanup_dead_ws, NULL, 60); -} - -}