Merge branch 'master' of github.com:janvidar/uhub

This commit is contained in:
Jan Vidar Krey 2011-09-05 23:34:05 +02:00
commit 70f13158d3
15 changed files with 260 additions and 51 deletions

View File

@ -10,9 +10,8 @@ LD := $(CC)
MV := mv
RANLIB := ranlib
CFLAGS += -pipe -Wall
USE_SSL ?= NO
USE_SSL ?= YES
USE_BIGENDIAN ?= AUTO
USE_PLUGINS ?= YES
BITS ?= AUTO
SILENT ?= YES
TERSE ?= NO
@ -43,7 +42,6 @@ UHUB_PREFIX ?= c:/uhub/
CFLAGS += -mno-cygwin
LDFLAGS += -mno-cygwin
BIN_EXT ?= .exe
USE_PLUGINS := NO
else
DESTDIR ?= /
UHUB_CONF_DIR ?= $(DESTDIR)/etc/uhub
@ -121,11 +119,7 @@ CFLAGS += -DSSL_SUPPORT
LDLIBS += -lssl
endif
ifeq ($(USE_PLUGINS),YES)
CFLAGS += -DPLUGIN_SUPPORT
LDLIBS += -ldl
endif
GIT_VERSION=$(shell git describe --tags 2>/dev/null || echo "")
GIT_REVISION=$(shell git show --abbrev-commit 2>/dev/null | head -n 1 | cut -f 2 -d " " || echo "")
@ -243,7 +237,7 @@ endif
%.o: %.c version.h revision.h
$(MSG_CC) $(CC) -fPIC -c $(CFLAGS) -o $@ $<
all: $(uhub_BINARY)
all: $(uhub_BINARY) plugins
plugins: $(uhub_BINARY) $(all_plugins)

View File

@ -120,7 +120,6 @@ void sid_pool_destroy(struct sid_pool* pool)
sid_t sid_alloc(struct sid_pool* pool, struct hub_user* user)
{
sid_t n;
if (pool->count >= (pool->max - pool->min))
{
#ifdef DEBUG_SID
@ -129,8 +128,7 @@ sid_t sid_alloc(struct sid_pool* pool, struct hub_user* user)
return 0;
}
n = ++pool->count;
n = (++pool->count);
for (; (pool->map[n % pool->max]); n++) ;
#ifdef DEBUG_SID

View File

@ -25,7 +25,6 @@
struct sid_pool;
struct hub_user;
extern const char* BASE32_ALPHABET;
extern char* sid_to_string(sid_t sid_);
extern sid_t string_to_sid(const char* sid);

View File

@ -1,6 +1,6 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2010, Jan Vidar Krey
* Copyright (C) 2007-2011, Jan Vidar Krey
*
* 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
@ -732,15 +732,22 @@ static int command_register(struct hub_info* hub, struct hub_user* user, struct
data.password[MAX_PASS_LEN] = '\0';
data.credentials = auth_cred_user;
if (acl_register_user(hub, &data))
if (hub->config->register_self)
{
sprintf(tmp, "User \"%s\" registered.", user->id.nick);
return command_status(hub, user, cmd, tmp);
if (acl_register_user(hub, &data))
{
sprintf(tmp, "User \"%s\" registered.", user->id.nick);
return command_status(hub, user, cmd, tmp);
}
else
{
sprintf(tmp, "Unable to register user \"%s\".", user->id.nick);
return command_status(hub, user, cmd, tmp);
}
}
else
{
sprintf(tmp, "Unable to register user \"%s\".", user->id.nick);
return command_status(hub, user, cmd, tmp);
return command_status(hub, user, cmd, "You are not allowed to register.");
}
}

View File

@ -108,6 +108,15 @@
<since>0.1.1</since>
</option>
<option name="register_self" type="boolean" default="0">
<short>Allow users to register themselves on the hub.</short>
<description><![CDATA[
If this is enabled guests can register their nickname on the hub.
Otherwise only operators can register users.
]]></description>
<since>0.4.0</since>
</option>
<option name="obsolete_clients" type="boolean" default="0">
<short>Support obsolete clients using a ADC protocol prior to 1.0</short>
<description><![CDATA[
@ -417,6 +426,17 @@
<since>0.3.0</since>
</option>
<option name="tls_require_redirect_addr" type="string" default="">
<check regexp="(adc|adcs|dchub)://.*" />
<short>A redirect address in case a client connects using "adc://" when "adcs://" is required.</short>
<description><![CDATA[
This is the redirect address used when the hub wants to redirect a client for not using ADCS.
For instance a hub at adc://adc.example.com might redirect to adcs://adc.example.com
]]></description>
<since>0.3.3</since>
</option>
<option name="tls_certificate" type="file" default="">
<short>Certificate file</short>
<description><![CDATA[

View File

@ -11,6 +11,7 @@ void config_defaults(struct hub_config* config)
config->show_banner_sys_info = 1;
config->max_users = 500;
config->registered_users_only = 0;
config->register_self = 0;
config->obsolete_clients = 0;
config->chat_only = 0;
config->chat_is_privileged = 0;
@ -42,6 +43,7 @@ void config_defaults(struct hub_config* config)
config->flood_ctl_extras = 0;
config->tls_enable = 0;
config->tls_require = 0;
config->tls_require_redirect_addr = hub_strdup("");
config->tls_certificate = hub_strdup("");
config->tls_private_key = hub_strdup("");
config->file_motd = hub_strdup("");
@ -183,6 +185,16 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
return 0;
}
if (!strcmp(key, "register_self"))
{
if (!apply_boolean(key, data, &config->register_self))
{
LOG_ERROR("Configuration parse error on line %d", line_count);
return -1;
}
return 0;
}
if (!strcmp(key, "obsolete_clients"))
{
if (!apply_boolean(key, data, &config->obsolete_clients))
@ -496,6 +508,16 @@ static int apply_config(struct hub_config* config, char* key, char* data, int li
return 0;
}
if (!strcmp(key, "tls_require_redirect_addr"))
{
if (!apply_string(key, data, &config->tls_require_redirect_addr, (char*) ""))
{
LOG_ERROR("Configuration parse error on line %d", line_count);
return -1;
}
return 0;
}
if (!strcmp(key, "tls_certificate"))
{
if (!apply_string(key, data, &config->tls_certificate, (char*) ""))
@ -933,6 +955,8 @@ void free_config(struct hub_config* config)
hub_free(config->redirect_addr);
hub_free(config->tls_require_redirect_addr);
hub_free(config->tls_certificate);
hub_free(config->tls_private_key);
@ -1048,6 +1072,9 @@ void dump_config(struct hub_config* config, int ignore_defaults)
if (!ignore_defaults || config->registered_users_only != 0)
fprintf(stdout, "registered_users_only = %s\n", config->registered_users_only ? "yes" : "no");
if (!ignore_defaults || config->register_self != 0)
fprintf(stdout, "register_self = %s\n", config->register_self ? "yes" : "no");
if (!ignore_defaults || config->obsolete_clients != 0)
fprintf(stdout, "obsolete_clients = %s\n", config->obsolete_clients ? "yes" : "no");
@ -1141,6 +1168,9 @@ void dump_config(struct hub_config* config, int ignore_defaults)
if (!ignore_defaults || config->tls_require != 0)
fprintf(stdout, "tls_require = %s\n", config->tls_require ? "yes" : "no");
if (!ignore_defaults || strcmp(config->tls_require_redirect_addr, "") != 0)
fprintf(stdout, "tls_require_redirect_addr = \"%s\"\n", config->tls_require_redirect_addr);
if (!ignore_defaults || strcmp(config->tls_certificate, "") != 0)
fprintf(stdout, "tls_certificate = \"%s\"\n", config->tls_certificate);

View File

@ -11,6 +11,7 @@ struct hub_config
int show_banner_sys_info; /*<<< Show banner on connect (default: 1) */
int max_users; /*<<< Maximum number of users allowed on the hub (default: 500) */
int registered_users_only; /*<<< Allow registered users only (default: 0) */
int register_self; /*<<< Allow users to register themselves on the hub. (default: 0) */
int obsolete_clients; /*<<< Support obsolete clients using a ADC protocol prior to 1.0 (default: 0) */
int chat_only; /*<<< Allow chat only operation on hub (default: 0) */
int chat_is_privileged; /*<<< Allow chat for operators and above only (default: 0) */
@ -42,6 +43,7 @@ struct hub_config
int flood_ctl_extras; /*<<< Max extra messages allowed in time interval (default: 0) */
int tls_enable; /*<<< Enable SSL/TLS support (default: 0) */
int tls_require; /*<<< If SSL/TLS enabled, should it be required (default: 0) (default: 0) */
char* tls_require_redirect_addr; /*<<< A redirect address in case a client connects using "adc://" when "adcs://" is required. (default: ) */
char* tls_certificate; /*<<< Certificate file (default: ) */
char* tls_private_key; /*<<< Private key file (default: ) */
char* file_motd; /*<<< File containing the 'message of the day (default: ) */

View File

@ -695,6 +695,7 @@ static int load_ssl_certificates(struct hub_info* hub, struct hub_config* config
/* Disable SSLv2 */
SSL_CTX_set_options(hub->ssl_ctx, SSL_OP_NO_SSLv2);
SSL_CTX_set_quiet_shutdown(hub->ssl_ctx, 1);
if (SSL_CTX_use_certificate_file(hub->ssl_ctx, config->tls_certificate, SSL_FILETYPE_PEM) < 0)
{
@ -824,7 +825,6 @@ void hub_shutdown_service(struct hub_info* hub)
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;
@ -840,21 +840,22 @@ void hub_shutdown_service(struct hub_info* hub)
}
#ifdef PLUGIN_SUPPORT
void hub_plugins_load(struct hub_info* hub)
int hub_plugins_load(struct hub_info* hub)
{
if (!hub->config->file_plugins || !*hub->config->file_plugins)
return;
return 0;
hub->plugins = hub_malloc_zero(sizeof(struct uhub_plugins));
if (!hub->plugins)
return;
return -1;
if (plugin_initialize(hub->config, hub->plugins) < 0)
{
hub_free(hub->plugins);
hub->plugins = 0;
return;
return -1;
}
return 0;
}
void hub_plugins_unload(struct hub_info* hub)
@ -943,7 +944,11 @@ void hub_set_variables(struct hub_info* hub, struct acl_handle* acl)
}
#ifdef PLUGIN_SUPPORT
hub_plugins_load(hub);
if (hub_plugins_load(hub) < 0)
{
hub->status = hub_status_shutdown;
}
else
#endif
hub->status = (hub->config->hub_enabled ? hub_status_running : hub_status_disabled);

View File

@ -50,6 +50,17 @@ static void probe_net_event(struct net_connection* con, int events, void *arg)
if (probe->hub->config->tls_enable && probe->hub->config->tls_require)
{
LOG_TRACE("Not TLS connection - closing connection.");
if (*probe->hub->config->tls_require_redirect_addr)
{
char buf[512];
ssize_t len = snprintf(buf, sizeof(buf), "ISUP " ADC_PROTO_SUPPORT "\nISID AAAB\nIINF NIRedirecting...\nIQUI AAAB RD%s\n", probe->hub->config->tls_require_redirect_addr);
net_con_send(con, buf, (size_t) len);
LOG_TRACE("Not TLS connection - Redirecting to %s.", probe->hub->config->tls_require_redirect_addr);
}
else
{
LOG_TRACE("Not TLS connection - closing connection.");
}
}
else
#endif
@ -60,9 +71,8 @@ static void probe_net_event(struct net_connection* con, int events, void *arg)
probe_destroy(probe);
return;
}
#ifdef SSL_SUPPORT
if (bytes >= 11 &&
else if (bytes >= 11 &&
probe_recvbuf[0] == 22 &&
probe_recvbuf[1] == 3 && /* protocol major version */
probe_recvbuf[5] == 1 && /* message type */
@ -107,6 +117,8 @@ struct hub_probe* probe_create(struct hub_info* hub, int sd, struct ip_addr_enca
if (probe == NULL)
return NULL; /* OOM */
LOG_TRACE("probe_create(): %p", probe);
probe->hub = hub;
probe->connection = net_con_create();
net_con_initialize(probe->connection, sd, probe_net_event, probe, NET_EVENT_READ);
@ -118,6 +130,7 @@ struct hub_probe* probe_create(struct hub_info* hub, int sd, struct ip_addr_enca
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);

View File

@ -71,6 +71,12 @@ void user_destroy(struct hub_user* user)
hub_recvq_destroy(user->recv_queue);
hub_sendq_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);

View File

@ -179,6 +179,14 @@ void net_con_close(struct net_connection* con)
g_backend->handler.con_del(g_backend->data, con);
#ifdef SSL_SUPPORT
if (con->ssl)
{
SSL_shutdown(con->ssl);
SSL_clear(con->ssl);
}
#endif
net_close(con->sd);
con->sd = -1;
@ -196,6 +204,7 @@ struct net_cleanup_handler* net_cleanup_initialize(size_t max)
void net_cleanup_shutdown(struct net_cleanup_handler* handler)
{
net_cleanup_process(handler);
hub_free(handler->queue);
hub_free(handler);
}

View File

@ -161,7 +161,7 @@ ssize_t net_con_send(struct net_connection* con, const void* buf, size_t len)
LOG_PROTO("SSL_write(con=%p, buf=%p, len=" PRINTF_SIZE_T ") => %d", con, buf, len, ret);
if (ret <= 0)
{
return -handle_openssl_error(con, ret);
return handle_openssl_error(con, ret);
}
}
#endif
@ -201,7 +201,7 @@ ssize_t net_con_recv(struct net_connection* con, void* buf, size_t len)
}
else
{
return -handle_openssl_error(con, ret);
return handle_openssl_error(con, ret);
}
}
#endif
@ -251,6 +251,9 @@ void* net_con_get_ptr(struct net_connection* con)
void net_con_destroy(struct net_connection* con)
{
#ifdef SSL_SUPPORT
SSL_free(con->ssl);
#endif
hub_free(con);
}

View File

@ -62,7 +62,6 @@ int net_initialize()
LOG_TRACE("Initializing OpenSSL...");
SSL_library_init();
SSL_load_error_strings();
OpenSSL_add_all_algorithms();
#endif /* SSL_SUPPORT */
net_initialized = 1;
@ -101,7 +100,9 @@ int net_destroy()
net_backend_shutdown();
#ifdef SSL_SUPPORT
/* FIXME: Shutdown OpenSSL here. */
ERR_free_strings();
EVP_cleanup();
CRYPTO_cleanup_all_ex_data();
#endif
#ifdef WINSOCK

View File

@ -51,6 +51,10 @@ struct plugin_user
enum auth_credentials credentials;
};
struct plugin_hub_info
{
};
enum plugin_status
{
st_default = 0, /* Use default */
@ -100,6 +104,11 @@ typedef void (*on_user_nick_change_t)(struct plugin_handle*, struct plugin_user*
typedef void (*on_user_update_error_t)(struct plugin_handle*, struct plugin_user*, const char* reason);
typedef void (*on_user_chat_msg_t)(struct plugin_handle*, struct plugin_user*, const char* message, int flags);
typedef void (*on_hub_started_t)(struct plugin_handle*, struct plugin_hub_info*);
typedef void (*on_hub_reloaded_t)(struct plugin_handle*, struct plugin_hub_info*);
typedef void (*on_hub_shutdown_t)(struct plugin_handle*, struct plugin_hub_info*);
typedef void (*on_hub_error_t)(struct plugin_handle*, struct plugin_hub_info*, const char* message);
typedef plugin_st (*on_change_nick_t)(struct plugin_handle*, struct plugin_user*, const char* new_nick);
typedef plugin_st (*on_check_ip_early_t)(struct plugin_handle*, struct ip_addr_encap*);
@ -126,6 +135,12 @@ struct plugin_funcs
on_user_update_error_t on_user_update_error;/* A user has failed to update - nickname, etc. */
on_user_chat_msg_t on_user_chat_message;/* A user has sent a public chat message */
// Log hub events
on_hub_started_t on_hub_started; /* Triggered just after plugins are loaded and the hub is started. */
on_hub_reloaded_t on_hub_reloaded; /* Triggered immediately after hub configuration is reloaded. */
on_hub_shutdown_t on_hub_shutdown; /* Triggered just before the hub is being shut down and before plugins are unloaded. */
on_hub_error_t on_hub_error; /* Triggered for log-worthy error messages */
// Activity events (can be intercepted and refused/accepted by a plugin)
on_chat_msg_t on_chat_msg; /* A public chat message is about to be sent (can be intercepted) */
on_private_msg_t on_private_msg; /* A public chat message is about to be sent (can be intercepted) */

View File

@ -1,7 +1,7 @@
/**
* This is a minimal example plugin for uhub.
* A logging plugin for uhub.
* Logs to either file or syslog.
*/
#include "system.h"
#include "adc/adcconst.h"
#include "adc/sid.h"
@ -9,40 +9,138 @@
#include "util/ipcalc.h"
#include "plugin_api/handle.h"
#include "util/misc.h"
#include "util/config_token.h"
#include <syslog.h>
struct ip_addr_encap;
struct log_data
{
enum {
mode_file,
mode_syslog
} logmode;
char* logfile;
int fd;
};
static void reset(struct log_data* data)
{
/* set defaults */
data->logmode = mode_file;
data->logfile = NULL;
data->fd = -1;
}
static void set_error_message(struct plugin_handle* plugin, const char* msg)
{
plugin->error_msg = msg;
}
static int log_open_file(struct plugin_handle* plugin, struct log_data* data)
{
data->fd = open(data->logfile, O_CREAT | O_APPEND | O_NOATIME | O_LARGEFILE | O_WRONLY, 0664);
return (data->fd != -1);
}
static struct log_data* log_open(struct plugin_handle* plugin, const char* config)
static int log_open_syslog(struct plugin_handle* plugin)
{
openlog("uhub", 0, LOG_USER);
return 1;
}
static struct log_data* parse_config(const char* line, struct plugin_handle* plugin)
{
struct log_data* data = (struct log_data*) hub_malloc(sizeof(struct log_data));
data->logfile = strdup(config);
data->fd = open(data->logfile, O_CREAT | O_APPEND | O_NOATIME | O_LARGEFILE | O_WRONLY, 0664);
if (data->fd == -1)
struct cfg_tokens* tokens = cfg_tokenize(line);
char* token = cfg_token_get_first(tokens);
if (!data)
return 0;
reset(data);
while (token)
{
set_error_message(plugin, "Unable to open log file!");
hub_free(data->logfile);
hub_free(data);
return NULL;
struct cfg_settings* setting = cfg_settings_split(token);
if (!setting)
{
set_error_message(plugin, "Unable to parse startup parameters");
cfg_tokens_free(tokens);
hub_free(data);
return 0;
}
if (strcmp(cfg_settings_get_key(setting), "file") == 0)
{
data->logfile = strdup(cfg_settings_get_value(setting));
data->logmode = mode_file;
}
else if (strcmp(cfg_settings_get_key(setting), "syslog") == 0)
{
int use_syslog = 0;
if (!string_to_boolean(cfg_settings_get_value(setting), &use_syslog))
{
data->logmode = (use_syslog) ? mode_syslog : mode_file;
}
}
else
{
set_error_message(plugin, "Unknown startup parameters given");
cfg_tokens_free(tokens);
cfg_settings_free(setting);
hub_free(data);
return 0;
}
cfg_settings_free(setting);
token = cfg_token_get_next(tokens);
}
if (data->logmode == mode_file)
{
if ((data->logmode == mode_file && !data->logfile))
{
set_error_message(plugin, "No log file is given, use file=<path>");
hub_free(data);
return 0;
}
if (!log_open_file(plugin, data))
{
hub_free(data->logfile);
hub_free(data);
set_error_message(plugin, "Unable to open log file");
return 0;
}
}
else
{
if (!log_open_syslog(plugin))
{
hub_free(data->logfile);
hub_free(data);
set_error_message(plugin, "Unable to open syslog");
return 0;
}
}
return data;
}
static void log_close(struct log_data* data)
{
hub_free(data->logfile);
close(data->fd);
if (data->logmode == mode_file)
{
hub_free(data->logfile);
close(data->fd);
}
else
{
closelog();
}
hub_free(data);
}
@ -54,16 +152,25 @@ static void log_message(struct log_data* data, const char *format, ...)
va_list args;
ssize_t size = 0;
t = time(NULL);
tmp = localtime(&t);
strftime(logmsg, 32, "%Y-%m-%d %H:%M:%S ", tmp);
if (data->logmode == mode_file)
{
t = time(NULL);
tmp = localtime(&t);
strftime(logmsg, 32, "%Y-%m-%d %H:%M:%S ", tmp);
va_start(args, format);
size = vsnprintf(logmsg + 20, 1004, format, args);
va_end(args);
va_start(args, format);
size = vsnprintf(logmsg + 20, 1004, format, args);
va_end(args);
write(data->fd, logmsg, size + 20);
fdatasync(data->fd);
write(data->fd, logmsg, size + 20);
fdatasync(data->fd);
}
else
{
va_start(args, format);
vsyslog(LOG_INFO, format, args);
va_end(args);
}
}
static void log_user_login(struct plugin_handle* plugin, struct plugin_user* user)
@ -101,7 +208,7 @@ int plugin_register(struct plugin_handle* plugin, const char* config)
plugin->funcs.on_user_logout = log_user_logout;
plugin->funcs.on_user_nick_change = log_change_nick;
plugin->ptr = log_open(plugin, config);
plugin->ptr = parse_config(config, plugin);
if (!plugin->ptr)
return -1;
return 0;