From 8065903604b0b9820bd78385706a6c7678d50e0f Mon Sep 17 00:00:00 2001 From: Jan Vidar Krey Date: Sun, 7 Feb 2010 23:08:04 +0100 Subject: [PATCH] Fix bug #108: share limits can be avoided. This was due to updates to the share limit not being enforced after a succesful login. --- src/core/hub.c | 90 ++++++++++++++++++++++++++------------------- src/core/hub.h | 2 +- src/core/hubevent.c | 14 +++++++ src/core/hubevent.h | 1 + src/core/inf.c | 25 ++++++++----- src/core/user.c | 1 + src/core/user.h | 5 ++- 7 files changed, 88 insertions(+), 50 deletions(-) diff --git a/src/core/hub.c b/src/core/hub.c index 4da1094..c904909 100644 --- a/src/core/hub.c +++ b/src/core/hub.c @@ -825,63 +825,79 @@ void hub_send_status(struct hub_info* hub, struct hub_user* user, enum status_me { struct hub_config* cfg = hub->config; struct adc_message* cmd = adc_msg_construct(ADC_CMD_ISTA, 6); + struct adc_message* qui = adc_msg_construct(ADC_CMD_IQUI, 256); char code[4]; + char buf[250]; const char* text = 0; const char* flag = 0; char* escaped_text = 0; + int reconnect_time = 0; if (!cmd) return; - -#define STATUS(CODE, MSG, FLAG) case status_ ## MSG : set_status_code(level, CODE, code); text = cfg->MSG; flag = FLAG; break + +#define STATUS(CODE, MSG, FLAG, RCONTIME) case status_ ## MSG : set_status_code(level, CODE, code); text = cfg->MSG; flag = FLAG; reconnect_time = RCONTIME; break switch (msg) { - STATUS(11, msg_hub_full, 0); - STATUS(12, msg_hub_disabled, 0); - STATUS(26, msg_hub_registered_users_only, 0); - STATUS(43, msg_inf_error_nick_missing, 0); - STATUS(43, msg_inf_error_nick_multiple, 0); - STATUS(21, msg_inf_error_nick_invalid, 0); - STATUS(21, msg_inf_error_nick_long, 0); - STATUS(21, msg_inf_error_nick_short, 0); - STATUS(21, msg_inf_error_nick_spaces, 0); - STATUS(21, msg_inf_error_nick_bad_chars, 0); - STATUS(21, msg_inf_error_nick_not_utf8, 0); - STATUS(22, msg_inf_error_nick_taken, 0); - STATUS(21, msg_inf_error_nick_restricted, 0); - STATUS(43, msg_inf_error_cid_invalid, "FBID"); - STATUS(43, msg_inf_error_cid_missing, "FMID"); - STATUS(24, msg_inf_error_cid_taken, 0); - STATUS(43, msg_inf_error_pid_missing, "FMPD"); - STATUS(27, msg_inf_error_pid_invalid, "FBPD"); - STATUS(31, msg_ban_permanently, 0); - STATUS(32, msg_ban_temporarily, "TL600"); /* FIXME: Use a proper timeout */ - STATUS(23, msg_auth_invalid_password, 0); - STATUS(20, msg_auth_user_not_found, 0); - STATUS(30, msg_error_no_memory, 0); - STATUS(43, msg_user_share_size_low, "FB" ADC_INF_FLAG_SHARED_SIZE); - STATUS(43, msg_user_share_size_high, "FB" ADC_INF_FLAG_SHARED_SIZE); - STATUS(43, msg_user_slots_low, "FB" ADC_INF_FLAG_UPLOAD_SLOTS); - STATUS(43, msg_user_slots_high, "FB" ADC_INF_FLAG_UPLOAD_SLOTS); - STATUS(43, msg_user_hub_limit_low, 0); - STATUS(43, msg_user_hub_limit_high, 0); + STATUS(11, msg_hub_full, 0, 600); /* FIXME: Proper timeout? */ + STATUS(12, msg_hub_disabled, 0, -1); + STATUS(26, msg_hub_registered_users_only, 0, 0); + STATUS(43, msg_inf_error_nick_missing, 0, 0); + STATUS(43, msg_inf_error_nick_multiple, 0, 0); + STATUS(21, msg_inf_error_nick_invalid, 0, 0); + STATUS(21, msg_inf_error_nick_long, 0, 0); + STATUS(21, msg_inf_error_nick_short, 0, 0); + STATUS(21, msg_inf_error_nick_spaces, 0, 0); + STATUS(21, msg_inf_error_nick_bad_chars, 0, 0); + STATUS(21, msg_inf_error_nick_not_utf8, 0, 0); + STATUS(22, msg_inf_error_nick_taken, 0, 0); + STATUS(21, msg_inf_error_nick_restricted, 0, 0); + STATUS(43, msg_inf_error_cid_invalid, "FBID", 0); + STATUS(43, msg_inf_error_cid_missing, "FMID", 0); + STATUS(24, msg_inf_error_cid_taken, 0, 0); + STATUS(43, msg_inf_error_pid_missing, "FMPD", 0); + STATUS(27, msg_inf_error_pid_invalid, "FBPD", 0); + STATUS(31, msg_ban_permanently, 0, 0); + STATUS(32, msg_ban_temporarily, "TL600", 600); /* FIXME: Proper timeout? */ + STATUS(23, msg_auth_invalid_password, 0, 0); + STATUS(20, msg_auth_user_not_found, 0, 0); + STATUS(30, msg_error_no_memory, 0, 0); + STATUS(43, msg_user_share_size_low, "FB" ADC_INF_FLAG_SHARED_SIZE, 0); + STATUS(43, msg_user_share_size_high, "FB" ADC_INF_FLAG_SHARED_SIZE, 0); + STATUS(43, msg_user_slots_low, "FB" ADC_INF_FLAG_UPLOAD_SLOTS, 0); + STATUS(43, msg_user_slots_high, "FB" ADC_INF_FLAG_UPLOAD_SLOTS, 0); + STATUS(43, msg_user_hub_limit_low, 0, 0); + STATUS(43, msg_user_hub_limit_high, 0, 0); } #undef STATUS escaped_text = adc_msg_escape(text); - + adc_msg_add_argument(cmd, code); adc_msg_add_argument(cmd, escaped_text); - - hub_free(escaped_text); - + if (flag) { adc_msg_add_argument(cmd, flag); } - + route_to_user(hub, user, cmd); + + if (level >= status_level_fatal) + { + snprintf(buf, 230, "MS%s", escaped_text); + adc_msg_add_argument(cmd, buf); + + if (reconnect_time != 0) + { + snprintf(buf, 10, "TL%d", reconnect_time); + adc_msg_add_argument(cmd, buf); + } + route_to_user(hub, user, cmd); + } + + hub_free(escaped_text); adc_msg_free(cmd); - + adc_msg_free(qui); } const char* hub_get_status_message(struct hub_info* hub, enum status_message msg) diff --git a/src/core/hub.h b/src/core/hub.h index af6db67..3c8272f 100644 --- a/src/core/hub.h +++ b/src/core/hub.h @@ -45,7 +45,7 @@ enum status_message status_msg_auth_invalid_password = -21, /* Password is wrong */ status_msg_auth_user_not_found = -22, /* User not found in password database */ status_msg_error_no_memory = -23, /* Hub is out of memory */ - + status_msg_user_share_size_low = -40, /* User is not sharing enough. */ status_msg_user_share_size_high = -41, /* User is sharing too much. */ status_msg_user_slots_low = -42, /* User has too few slots open. */ diff --git a/src/core/hubevent.c b/src/core/hubevent.c index 4c5207c..72cd073 100644 --- a/src/core/hubevent.c +++ b/src/core/hubevent.c @@ -33,6 +33,13 @@ static void log_user_login_error(struct hub_user* u, enum status_message msg) LOG_USER("LoginError %s/%s %s \"%s\" (%s) \"%s\"", sid_to_string(u->id.sid), u->id.cid, addr, u->id.nick, message, u->user_agent); } +static void log_user_update_error(struct hub_user* u, enum status_message msg) +{ + const char* addr = user_get_address(u); + const char* message = hub_get_status_message_log(u->hub, msg); + LOG_USER("UpdateError %s/%s %s \"%s\" (%s) \"%s\"", sid_to_string(u->id.sid), u->id.cid, addr, u->id.nick, message, u->user_agent); +} + static void log_user_logout(struct hub_user* u, const char* message) { const char* addr = user_get_address(u); @@ -83,6 +90,13 @@ void on_login_failure(struct hub_info* hub, struct hub_user* u, enum status_mess hub_disconnect_user(hub, u, quit_logon_error); } +void on_update_failure(struct hub_info* hub, struct hub_user* u, enum status_message msg) +{ + log_user_update_error(u, msg); + hub_send_status(hub, u, msg, status_level_fatal); + hub_disconnect_user(hub, u, quit_update_error); +} + void on_nick_change(struct hub_info* hub, struct hub_user* u, const char* nick) { if (user_is_logged_in(u)) diff --git a/src/core/hubevent.h b/src/core/hubevent.h index e3af03e..1d25054 100644 --- a/src/core/hubevent.h +++ b/src/core/hubevent.h @@ -29,6 +29,7 @@ extern void on_login_success(struct hub_info* hub, struct hub_user* u); * This event is triggered whenever a user failed to log in to the hub. */ extern void on_login_failure(struct hub_info* hub, struct hub_user* u, enum status_message msg); +extern void on_update_failure(struct hub_info* hub, struct hub_user* u, enum status_message msg); /** * This event is triggered whenever a previously logged in user leaves the hub. diff --git a/src/core/inf.c b/src/core/inf.c index 8cfded0..5034057 100644 --- a/src/core/inf.c +++ b/src/core/inf.c @@ -187,7 +187,7 @@ static int check_required_login_flags(struct hub_info* hub, struct hub_user* use * remove any wrong address, and replace it with the correct one * as seen by the hub. */ -int check_network(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd) +static int check_network(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd) { const char* address = user_get_address(user); @@ -223,7 +223,7 @@ int check_network(struct hub_info* hub, struct hub_user* user, struct adc_messag return 0; } -void strip_network(struct hub_user* user, struct adc_message* cmd) +static void strip_network(struct hub_user* user, struct adc_message* cmd) { adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_ADDR); adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_UDP_PORT); @@ -526,7 +526,6 @@ static int check_limits(struct hub_info* hub, struct hub_user* user, struct adc_ return 0; } - /* * Set the expected credentials, and returns 1 if authentication is needed, * or 0 if not. @@ -648,7 +647,7 @@ static int hub_handle_info_low_bandwidth(struct hub_info* hub, struct hub_user* return ret; \ } while(0) -int hub_perform_login_checks(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd) +static int hub_perform_login_checks(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd) { /* Make syntax checks. */ INF_CHECK(check_required_login_flags, hub, user, cmd); @@ -666,7 +665,7 @@ int hub_perform_login_checks(struct hub_info* hub, struct hub_user* user, struct * * @return 0 if success, <0 if error, >0 if authentication needed. */ -int hub_handle_info_login(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd) +static int hub_handle_info_login(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd) { int code = 0; @@ -737,7 +736,7 @@ int hub_handle_info(struct hub_info* hub, struct hub_user* user, const struct ad adc_msg_free(cmd); return 0; } - + ret = hub_handle_info_login(hub, user, cmd); if (ret < 0) { @@ -763,7 +762,7 @@ int hub_handle_info(struct hub_info* hub, struct hub_user* user, const struct ad /* These must not be allowed updated, let's remove them! */ adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_PRIVATE_ID); adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_CLIENT_ID); - + /* * If the nick is not accepted, do not relay it. * Otherwise, the nickname will be updated. @@ -775,9 +774,15 @@ int hub_handle_info(struct hub_info* hub, struct hub_user* user, const struct ad #endif adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_NICK); } - - /* FIXME - What if limits are not met ? */ - check_limits(hub, user, cmd); + + ret = check_limits(hub, user, cmd); + if (ret < 0) + { + on_update_failure(hub, user, ret); + adc_msg_free(cmd); + return -1; + } + strip_network(user, cmd); hub_handle_info_low_bandwidth(hub, user, cmd); diff --git a/src/core/user.c b/src/core/user.c index 7e0c000..a251a50 100644 --- a/src/core/user.c +++ b/src/core/user.c @@ -336,6 +336,7 @@ const char* user_get_quit_reason_string(enum user_quit_reason reason) case quit_socket_error: return "socket error"; break; case quit_protocol_error: return "protocol error"; break; case quit_logon_error: return "login error"; break; + case quit_update_error: return "update error"; break; case quit_hub_disabled: return "hub disabled"; break; case quit_ghost_timeout: return "ghost"; break; } diff --git a/src/core/user.h b/src/core/user.h index b2f2f87..3d97670 100644 --- a/src/core/user.h +++ b/src/core/user.h @@ -68,8 +68,9 @@ enum user_quit_reason quit_socket_error = 7, /** A socket error occured */ quit_protocol_error = 8, /** Fatal protocol error */ quit_logon_error = 9, /** Unable to login (wrong password, CID/PID, etc) */ - quit_hub_disabled = 10, /** Hub is disabled. No new connections allowed */ - quit_ghost_timeout = 11, /** The user is a ghost, and trying to login from another connection */ + quit_update_error = 10, /** Update error. INF update changed share/slot info and no longer satisfies the hub limits. */ + quit_hub_disabled = 11, /** Hub is disabled. No new connections allowed */ + quit_ghost_timeout = 12, /** The user is a ghost, and trying to login from another connection */ }; /** Returns an apropriate string for the given quit reason */