void probe_destroy(struct hub_probe* probe) { LOG_TRACE("probe_destroy(): %p (connection=%p)", probe, probe->connection); if (probe->connection) { net_con_close(probe->connection); probe->connection = 0; } hub_free(probe); }
static int command_showtopic_handler(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_command* cmd) { struct cbuffer* buf = cbuf_create(128); char* topic = plugin->hub.get_description(plugin); cbuf_append_format(buf, "*** %s: Current topic is: \"%s\"", cmd->prefix, topic); plugin->hub.send_message(plugin, user, cbuf_get(buf)); cbuf_destroy(buf); hub_free(topic); return 0; }
static int apply_string(const char* key, const char* data, char** target, char* regexp) { (void) regexp; // FIXME: Add regexp checks for correct data if (*target) hub_free(*target); *target = hub_strdup(data); return 1; }
struct auth_info* acl_get_access_info(struct hub_info* hub, const char* name) { struct auth_info* info = 0; info = (struct auth_info*) hub_malloc(sizeof(struct auth_info)); if (plugin_auth_get_user(hub, name, info) != st_allow) { hub_free(info); return NULL; } return info; }
struct net_connect_handle* net_con_connect(const char* address, uint16_t port, net_connect_cb callback, void* ptr) { struct net_connect_handle* handle = hub_malloc_zero(sizeof(struct net_connect_handle)); handle->address = hub_strdup(address); handle->port = port; handle->ptr = ptr; handle->callback = callback; // FIXME: Check if DNS resolving is necessary ? handle->dns = net_dns_gethostbyname(address, AF_UNSPEC, net_con_connect_dns_callback, handle); if (!handle->dns) { LOG_TRACE("net_con_connect(): Unable to create DNS lookup job."); hub_free((char*) handle->address); hub_free(handle); return NULL; } return handle; }
static void hub_command_args_free(struct hub_command* cmd) { struct hub_command_arg_data* data = NULL; if (!cmd->args) return; LIST_FOREACH(struct hub_command_arg_data*, data, cmd->args, { switch (data->type) { case type_string: hub_free(data->data.string); break; case type_range: hub_free(data->data.range); break; default: break; } });
void net_notify_destroy(struct uhub_notify_handle* handle) { LOG_TRACE("net_notify_destroy()"); #ifndef WIN32 net_con_destroy(handle->con); close(handle->pipe_fd[0]); close(handle->pipe_fd[1]); handle->pipe_fd[0] = -1; handle->pipe_fd[0] = -1; #endif hub_free(handle); }
void ADC_client_destroy(struct ADC_client* client) { ADC_TRACE; ADC_client_disconnect(client); ioq_send_destroy(client->send_queue); ioq_recv_destroy(client->recv_queue); hub_free(client->timer); adc_msg_free(client->info); hub_free(client->nick); hub_free(client->desc); hub_free(client->address.hostname); hub_free(client); if (g_adc_client && g_adc_client->references > 0) { g_adc_client->references--; if (!g_adc_client->references) { #ifdef SSL_SUPPORT net_ssl_context_destroy(g_adc_client->ctx); g_adc_client->ctx = NULL; #endif hub_free(g_adc_client); g_adc_client = NULL; } } }
static void log_change_nick(struct plugin_handle* plugin, struct plugin_user* user, const char* new_nick) { struct log_data* ldata = (struct log_data*) plugin->ptr; const char* addr = ip_convert_to_string(&user->addr); char* nick = strdup(sql_escape_string(user->nick)); int rc = sql_execute(ldata, null_callback, NULL, "INSERT INTO userlog VALUES('', '%s', '%s', '', '', '%s (%s -> %s)', DATETIME('NOW', 'localtime', '%d hours'));", user->cid, addr, "NickChange", nick, new_nick, ldata->srvtdiff); if (rc < 0) fprintf(stderr, "[SQLITE LOG] Unable to log: NickChange %s/%s %s \"%s\" -> \"%s\"\n", sid_to_string(user->sid), user->cid, addr, user->nick, new_nick); hub_free(nick); }
/* * Set the expected credentials, and returns 1 if authentication is needed, * or 0 if not. * If the hub is configured to allow only registered users and the user * is not recognized this will return 1. */ static int set_credentials(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd) { int ret = 0; struct auth_info* info = acl_get_access_info(hub, user->id.nick); if (info) { user->credentials = info->credentials; ret = 1; } else { user->credentials = auth_cred_guest; } hub_free(info); switch (user->credentials) { case auth_cred_none: break; case auth_cred_bot: adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_BOT); break; case auth_cred_guest: /* Nothing to be added to the info message */ break; case auth_cred_user: adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_REGISTERED_USER); break; case auth_cred_operator: adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_OPERATOR); break; case auth_cred_super: adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_SUPER_USER); break; case auth_cred_admin: adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_ADMIN); break; case auth_cred_link: break; } return ret; }
int uman_shutdown(struct hub_info* hub) { if (!hub || !hub->users) return -1; if (net_backend_get_timeout_queue()) { timeout_queue_remove(net_backend_get_timeout_queue(), hub->users->timeout); hub_free(hub->users->timeout); } if (hub->users->list) { list_clear(hub->users->list, &clear_user_list_callback); list_destroy(hub->users->list); } sid_pool_destroy(hub->users->sids); hub_free(hub->users); hub->users = 0; return 0; }
void hub_shutdown_service(struct hub_info* hub) { LOG_DEBUG("hub_shutdown_service()"); #ifdef SSL_SUPPORT unload_ssl_certificates(hub); #endif event_queue_shutdown(hub->queue); net_con_close(hub->server); hub_free(hub->server); server_alt_port_stop(hub); uman_shutdown(hub); hub->status = hub_status_stopped; hub_free(hub->sendbuf); hub_free(hub->recvbuf); hub_chat_history_clear(hub); list_destroy(hub->chat_history); list_clear(hub->logout_info, &hub_free); list_destroy(hub->logout_info); hub_free(hub); hub = 0; g_hub = 0; }
static int command_releaseadd(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_command* cmd) { struct extras_data* extrasdata = (struct extras_data*) plugin->ptr; struct cbuffer* buf = cbuf_create(128); struct plugin_command_arg_data* arg1 = (struct plugin_command_arg_data*) list_get_first(cmd->args); struct plugin_command_arg_data* arg2 = (struct plugin_command_arg_data*) list_get_next(cmd->args); char* tth = strdup(sql_escape_string(arg1->data.string)); char* title = strdup(sql_escape_string(arg2->data.string)); int rc = sql_execute(extrasdata, null_callback, NULL, "INSERT INTO releases (id, title, tth) VALUES(NULL, '%s', '%s');", title, tth); if (rc > 0) cbuf_append_format(buf, "*** %s: Added \"%s\" to releases.", cmd->prefix, title); else cbuf_append_format(buf, "*** %s: Unable to add \"%s\" to releases.", cmd->prefix, title); plugin->hub.send_message(plugin, user, cbuf_get(buf)); cbuf_destroy(buf); hub_free(tth); hub_free(title); return 0; }
/** * Create a new SSL context. */ struct ssl_context_handle* net_ssl_context_create(const char* tls_version, const char* tls_ciphersuite) { struct net_context_openssl* ctx = (struct net_context_openssl*) hub_malloc_zero(sizeof(struct net_context_openssl)); const SSL_METHOD* ssl_method = get_ssl_method(tls_version); if (!ssl_method) { hub_free(ctx); return 0; } ctx->ssl = SSL_CTX_new(ssl_method); /* Disable SSLv2 */ SSL_CTX_set_options(ctx->ssl, SSL_OP_NO_SSLv2); // FIXME: Why did we need this again? SSL_CTX_set_quiet_shutdown(ctx->ssl, 1); #ifdef SSL_OP_NO_COMPRESSION /* Disable compression */ LOG_TRACE("Disabling SSL compression."); /* "CRIME" attack */ SSL_CTX_set_options(ctx->ssl, SSL_OP_NO_COMPRESSION); #endif /* Set preferred cipher suite */ if (SSL_CTX_set_cipher_list(ctx->ssl, tls_ciphersuite) != 1) { LOG_ERROR("Unable to set cipher suite."); SSL_CTX_free(ctx->ssl); hub_free(ctx); return 0; } return (struct ssl_context_handle*) ctx; }
static struct acl_data* parse_config(const char* line) { struct acl_data* data = (struct acl_data*) hub_malloc_zero(sizeof(struct acl_data)); struct cfg_tokens* tokens = cfg_tokenize(line); char* token = cfg_token_get_first(tokens); if (!data) return 0; // set defaults data->readonly = 1; data->exclusive = 0; data->users = list_create(); while (token) { char* split = strchr(token, '='); size_t len = strlen(token); size_t key = split ? (split - token) : len; if (key == 4 && strncmp(token, "file", 4) == 0) { if (data->file) hub_free(data->file); data->file = strdup(split + 1); } else if (key == 8 && strncmp(token, "readonly", 8) == 0) { if (!string_to_boolean(split + 1, &data->readonly)) data->readonly = 1; } else if (key == 9 && strncmp(token, "exclusive", 9) == 0) { if (!string_to_boolean(split + 1, &data->exclusive)) data->exclusive = 1; } else { cfg_tokens_free(tokens); free_acl(data); return 0; } token = cfg_token_get_next(tokens); } cfg_tokens_free(tokens); return data; }
struct plugin_handle* plugin_load(const char* filename, const char* config) { plugin_register_f register_f; plugin_unregister_f unregister_f; int ret; struct plugin_handle* handle = hub_malloc_zero(sizeof(struct plugin_handle)); struct uhub_plugin* plugin = plugin_open(filename); if (!plugin) return NULL; if (!handle) { plugin_close(plugin); return NULL; } handle->handle = plugin; register_f = plugin_lookup_symbol(plugin, "plugin_register"); unregister_f = plugin_lookup_symbol(plugin, "plugin_unregister"); if (register_f && unregister_f) { ret = register_f(handle, config); if (ret == 0) { if (handle->plugin_api_version == PLUGIN_API_VERSION && handle->plugin_funcs_size == sizeof(struct plugin_funcs)) { LOG_INFO("Loaded plugin: %s: %s, version %s.", filename, handle->name, handle->version); LOG_TRACE("Plugin API version: %d (func table size: " PRINTF_SIZE_T ")", handle->plugin_api_version, handle->plugin_funcs_size); plugin->unregister = unregister_f; return handle; } else { LOG_ERROR("Unable to load plugin: %s - API version mistmatch", filename); } } else { LOG_ERROR("Unable to load plugin: %s - Failed to initialize: %s", filename, handle->error_msg); } } plugin_close(plugin); hub_free(handle); return NULL; }
/** * Add a chat message to history. */ static void history_add(struct plugin_handle* plugin, struct plugin_user* from, const char* message, int flags) { size_t loglen = strlen(message) + strlen(from->nick) + 13; struct chat_history_data* data = (struct chat_history_data*) plugin->ptr; char* log = hub_malloc(loglen + 1); snprintf(log, loglen, "%s <%s> %s\n", get_timestamp(time(NULL)), from->nick, message); log[loglen] = '\0'; list_append(data->chat_history, log); while (list_size(data->chat_history) > data->history_max) { char* msg = list_get_first(data->chat_history); list_remove(data->chat_history, msg); hub_free(msg); } }
void hub_plugins_load(struct hub_info* hub) { if (!hub->config->file_plugins || !*hub->config->file_plugins) return; hub->plugins = hub_malloc_zero(sizeof(struct uhub_plugins)); if (!hub->plugins) return; if (plugin_initialize(hub->config, hub->plugins) < 0) { hub_free(hub->plugins); hub->plugins = 0; return; } }
void user_destroy(struct hub_user* user) { LOG_TRACE("user_destroy(), user=%p", user); ioq_recv_destroy(user->recv_queue); ioq_send_destroy(user->send_queue); if (user->connection) { LOG_TRACE("user_destory() -> net_con_close(%p)", user->connection); net_con_close(user->connection); } adc_msg_free(user->info); user_clear_feature_cast_support(user); hub_free(user); }
void hub_logout_log(struct hub_info* hub, struct hub_user* user) { struct hub_logout_info* loginfo = hub_malloc_zero(sizeof(struct hub_logout_info)); if (!loginfo) return; loginfo->time = time(NULL); strcpy(loginfo->cid, user->id.cid); strcpy(loginfo->nick, user->id.nick); memcpy(&loginfo->addr, &user->id.addr, sizeof(struct ip_addr_encap)); loginfo->reason = user->quit_reason; list_append(hub->logout_info, loginfo); while (list_size(hub->logout_info) > (size_t) hub->config->max_logout_log) { struct hub_logout_info* entry = list_get_first(hub->logout_info); list_remove(hub->logout_info, entry); hub_free(entry); } }
/** * The callback function for handling the !history command. */ static int command_history(struct plugin_handle* plugin, struct plugin_user* user, struct plugin_command* cmd) { struct chat_history_data* data = (struct chat_history_data*) plugin->ptr; struct cbuffer* buf = cbuf_create(MAX_HISTORY_SIZE); struct linked_list* found = (struct linked_list*) list_create(); struct plugin_command_arg_data* arg = plugin->hub.command_arg_next(plugin, cmd, plugin_cmd_arg_type_integer); int maxlines; if (arg) maxlines = arg->data.integer; else maxlines = data->history_default; sql_execute(data, get_messages_callback, found, "SELECT from_nick,message, datetime(time, 'localtime') as time FROM chat_history ORDER BY time DESC LIMIT 0,%d;", maxlines); size_t linecount = list_size(found); if (linecount > 0) { cbuf_append_format(buf, "*** %s: Chat History:\n\n", cmd->prefix); struct chat_history_line* history_line; history_line = (struct chat_history_line*) list_get_last(found); while (history_line) { cbuf_append_format(buf, "[%s] <%s> %s\n", history_line->time, history_line->from, history_line->message); list_remove(found, history_line); hub_free(history_line); history_line = (struct chat_history_line*) list_get_last(found); } } else { cbuf_append_format(buf, "*** %s: No messages found.", cmd->prefix); } plugin->hub.send_message(plugin, user, cbuf_get(buf)); cbuf_destroy(buf); list_clear(found, &hub_free); list_destroy(found); return 0; }
struct uhub_notify_handle* net_notify_create(net_notify_callback cb, void* ptr) { LOG_TRACE("net_notify_create()"); struct uhub_notify_handle* handle = (struct uhub_notify_handle*) hub_malloc(sizeof(struct uhub_notify_handle)); handle->callback = cb; handle->ptr = ptr; #ifndef WIN32 int ret = pipe(handle->pipe_fd); if (ret == -1) { LOG_ERROR("Unable to setup notification pipes."); hub_free(handle); return 0; } handle->con = net_con_create(); net_con_initialize(handle->con, handle->pipe_fd[0], notify_callback, handle, NET_EVENT_READ); #endif return handle; }
void hub_send_flood_warning(struct hub_info* hub, struct hub_user* u, const char* message) { struct adc_message* msg; char* tmp; if (user_flag_get(u, flag_flood)) return; msg = adc_msg_construct(ADC_CMD_ISTA, 128); if (msg) { tmp = adc_msg_escape(message); adc_msg_add_argument(msg, "110"); adc_msg_add_argument(msg, tmp); hub_free(tmp); route_to_user(hub, u, msg); user_flag_set(u, flag_flood); adc_msg_free(msg); } }
int hub_handle_password(struct hub_info* hub, struct hub_user* u, struct adc_message* cmd) { char* password = adc_msg_get_argument(cmd, 0); int ret = 0; if (u->state == state_verify) { if (acl_password_verify(hub, u, password)) { on_login_success(hub, u); } else { on_login_failure(hub, u, status_msg_auth_invalid_password); ret = -1; } } hub_free(password); return ret; }
int acl_password_verify(struct hub_info* hub, struct hub_user* user, const char* password) { char buf[1024]; struct auth_info* access; const char* challenge; char raw_challenge[64]; char password_calc[64]; uint64_t tiger_res[3]; size_t password_len; if (!password || !user || strlen(password) != MAX_CID_LEN) return 0; access = acl_get_access_info(hub, user->id.nick); if (!access) return 0; challenge = acl_password_generate_challenge(hub, user); base32_decode(challenge, (unsigned char*) raw_challenge, MAX_CID_LEN); password_len = strlen(access->password); memcpy(&buf[0], access->password, password_len); memcpy(&buf[password_len], raw_challenge, TIGERSIZE); tiger((uint64_t*) buf, TIGERSIZE+password_len, (uint64_t*) tiger_res); base32_encode((unsigned char*) tiger_res, TIGERSIZE, password_calc); password_calc[MAX_CID_LEN] = 0; #ifdef PLUGIN_SUPPORT hub_free(access); #endif if (strcasecmp(password, password_calc) == 0) { return 1; } return 0; }
struct sid_pool* sid_pool_create(sid_t max) { struct sid_pool* pool = hub_malloc(sizeof(struct sid_pool)); if (!pool) return 0; pool->min = 1; pool->max = max + 1; pool->count = 0; pool->map = hub_malloc_zero(sizeof(struct hub_user*) * pool->max); if (!pool->map) { hub_free(pool); return 0; } pool->map[0] = (struct hub_user*) pool; /* hack to reserve the first sid. */ #ifdef DEBUG_SID LOG_DUMP("SID_POOL: max=%d", (int) pool->max); #endif return pool; }
struct net_backend* net_backend_init_epoll(struct net_backend_handler* handler, struct net_backend_common* common) { struct net_backend_epoll* backend; if (getenv("EVENT_NOEPOLL")) return 0; backend = hub_malloc_zero(sizeof(struct net_backend_epoll)); backend->epfd = epoll_create(common->max); if (backend->epfd == -1) { LOG_WARN("Unable to create epoll socket."); hub_free(backend); return 0; } backend->conns = hub_malloc_zero(sizeof(struct net_connection_epoll*) * common->max); backend->common = common; net_backend_set_handlers(handler); return (struct net_backend*) backend; }
struct auth_info* acl_get_access_info(struct hub_info* hub, const char* name) { struct auth_info* info = 0; #ifdef PLUGIN_SUPPORT info = (struct auth_info*) hub_malloc(sizeof(struct auth_info)); if (plugin_auth_get_user(hub, name, info) != st_allow) { hub_free(info); return NULL; } return info; #else info = (struct auth_info*) list_get_first(hub->acl->users); while (info) { if (strcasecmp((char*)info->nickname, name) == 0) { return info; } info = (struct auth_info*) list_get_next(hub->acl->users); } return NULL; #endif }
struct uhub_plugin* plugin_open(const char* filename) { LOG_TRACE("plugin_open: \"%s\"", filename); #ifdef HAVE_DLOPEN struct uhub_plugin* plugin = (struct uhub_plugin*) hub_malloc_zero(sizeof(struct uhub_plugin)); if (!plugin) { return 0; } plugin->handle = dlopen(filename, RTLD_LAZY); if (!plugin->handle) { LOG_ERROR("Unable to open plugin %s: %s", filename, dlerror()); hub_free(plugin); return 0; } return plugin; #else return 0; #endif }
/* * FIXME: Only works for tiger hash. If a client doesnt support tiger we cannot let it in! */ static int check_cid(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd) { size_t pos; char* cid = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_CLIENT_ID); char* pid = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_PRIVATE_ID); if (!cid || !pid) { hub_free(cid); hub_free(pid); return status_msg_error_no_memory; } if (strlen(cid) != MAX_CID_LEN) { hub_free(cid); hub_free(pid); return status_msg_inf_error_cid_invalid; } if (strlen(pid) != MAX_CID_LEN) { hub_free(cid); hub_free(pid); return status_msg_inf_error_pid_invalid; } for (pos = 0; pos < MAX_CID_LEN; pos++) { if (!is_valid_base32_char(cid[pos])) { hub_free(cid); hub_free(pid); return status_msg_inf_error_cid_invalid; } if (!is_valid_base32_char(pid[pos])) { hub_free(cid); hub_free(pid); return status_msg_inf_error_pid_invalid; } } if (!check_hash_tiger(cid, pid)) { hub_free(cid); hub_free(pid); return status_msg_inf_error_cid_invalid; } /* Set the cid in the user object */ memcpy(user->id.cid, cid, MAX_CID_LEN); user->id.cid[MAX_CID_LEN] = 0; hub_free(cid); hub_free(pid); return 0; }