/** * This will check the ip address of the user, and * remove any wrong address, and replace it with the correct one * as seen by the hub. */ static int check_network(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd) { const char* address = user_get_address(user); /* Check for NAT override address */ if (acl_is_ip_nat_override(hub->acl, address)) { char* client_given_ip = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR); if (client_given_ip && strcmp(client_given_ip, "0.0.0.0") != 0) { user_set_nat_override(user); adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_ADDR); adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_UDP_PORT); hub_free(client_given_ip); return 0; } hub_free(client_given_ip); } if (strchr(address, '.')) { adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_ADDR); adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_UDP_PORT); adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR); adc_msg_add_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR, address); } else if (strchr(address, ':')) { adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR); adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV4_UDP_PORT); adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_ADDR); adc_msg_add_named_argument(cmd, ADC_INF_FLAG_IPV6_ADDR, address); } return 0; }
/** * Perform additional INF checks used at time of login. * * @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) { int code = 0; INF_CHECK(hub_perform_login_checks, hub, user, cmd); /* Private ID must never be broadcasted - drop it! */ adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_PRIVATE_ID); code = set_credentials(hub, user, cmd); /* Note: this must be done *after* set_credentials. */ if (check_is_hub_full(hub, user)) { return status_msg_hub_full; } if (check_registered_users_only(hub, user)) { return status_msg_hub_registered_users_only; } INF_CHECK(check_limits, hub, user, cmd); /* strip off stuff if low_bandwidth_mode is enabled */ hub_handle_info_low_bandwidth(hub, user, cmd); /* Set initial user info */ user_set_info(user, cmd); return code; }
int route_info_message(struct hub_info* hub, struct hub_user* u) { if (!user_is_nat_override(u)) { return route_to_all(hub, u->info); } else { struct adc_message* cmd = adc_msg_copy(u->info); const char* address = user_get_address(u); struct hub_user* user = 0; adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR); adc_msg_add_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR, address); user = (struct hub_user*) list_get_first(hub->users->list); while (user) { if (user_is_nat_override(user)) route_to_user(hub, user, cmd); else route_to_user(hub, user, u->info); user = (struct hub_user*) list_get_next(hub->users->list); } adc_msg_free(cmd); } return 0; }
/* * These flags can only be set by the hub. * Make sure we don't allow clients to specify these themselves. * * NOTE: Some of them are legacy ADC flags and no longer used, these * should be removed at some point in the future when functionality no * longer depend on them. */ static void remove_server_restricted_flags(struct adc_message* cmd) { adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE); /* Client type flag (CT, obsoletes BO, RG, OP, HU) */ adc_msg_remove_named_argument(cmd, "BO"); /* Obsolete: bot flag (CT) */ adc_msg_remove_named_argument(cmd, "RG"); /* Obsolete: registered user flag (CT) */ adc_msg_remove_named_argument(cmd, "OP"); /* Obsolete: operator flag (CT) */ adc_msg_remove_named_argument(cmd, "HU"); /* Obsolete: hub flag (CT) */ adc_msg_remove_named_argument(cmd, "HI"); /* Obsolete: hidden user flag */ adc_msg_remove_named_argument(cmd, "TO"); /* Client to client token - should not be seen here */ adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_REFERER); }
/* * If user is in the connecting state, we need to do fairly * strict checking of all arguments. * This means we disconnect users when they provide invalid data * during the login sequence. * When users are merely updating their data after successful login * we can just ignore any invalid data and not broadcast it. * * The data we need to check is: * - nick name (valid, not taken, etc) * - CID/PID (valid, not taken, etc). * - IP addresses (IPv4 and IPv6) */ int hub_handle_info(struct hub_info* hub, struct hub_user* user, const struct adc_message* cmd_unmodified) { int ret; struct adc_message* cmd = adc_msg_copy(cmd_unmodified); if (!cmd) return -1; /* OOM */ cmd->priority = 1; hub_handle_info_common(user, cmd); /* If user is logging in, perform more checks, otherwise only a few things need to be checked. */ if (user_is_connecting(user)) { /* * Don't allow the user to send multiple INF messages in this stage! * Since that can have serious side-effects. */ if (user->info) { adc_msg_free(cmd); return 0; } ret = hub_handle_info_login(hub, user, cmd); if (ret < 0) { on_login_failure(hub, user, ret); adc_msg_free(cmd); return -1; } else { /* Post a message, the user has joined */ struct event_data post; memset(&post, 0, sizeof(post)); post.id = UHUB_EVENT_USER_JOIN; post.ptr = user; post.flags = ret; /* 0 - all OK, 1 - need authentication */ event_queue_post(hub->queue, &post); adc_msg_free(cmd); return 0; } } else { /* 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. */ if (adc_msg_has_named_argument(cmd, ADC_INF_FLAG_NICK)) { #ifdef ALLOW_CHANGE_NICK if (!check_nick(hub, user, cmd)) #endif adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_NICK); } 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); user_update_info(user, cmd); if (!adc_msg_is_empty(cmd)) { route_message(hub, user, cmd); } adc_msg_free(cmd); } return 0; }
static int hub_handle_info_low_bandwidth(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd) { if (hub->config->low_bandwidth_mode) { adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_USER_AGENT); adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_SHARED_FILES); adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_COUNT_HUB_NORMAL); adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_COUNT_HUB_REGISTER); adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_COUNT_HUB_OPERATOR); adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_UPLOAD_SPEED); adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_DOWNLOAD_SPEED); adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_AUTO_SLOTS); adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_AUTO_SLOTS_MAX); adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_AWAY); adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_DESCRIPTION); adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_EMAIL); } return 0; }
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_IPV4_ADDR); }