/* * It is possible to do user-agent checking here. * But this is not something we want to do, and is deprecated in the ADC specification. * One should rather look at capabilities/features. */ static int check_user_agent(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd) { char* ua_name_encoded = 0; char* ua_version_encoded = 0; char* str = 0; size_t offset = 0; /* Get client user agent version */ ua_name_encoded = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_USER_AGENT_PRODUCT); ua_version_encoded = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_USER_AGENT_VERSION); if (ua_name_encoded) { str = adc_msg_unescape(ua_name_encoded); if (str) { offset = strlen(str); memcpy(user->id.user_agent, str, MIN(offset, MAX_UA_LEN)); hub_free(str); } } if (ua_version_encoded) { str = adc_msg_unescape(ua_version_encoded); if (str) { memcpy(user->id.user_agent + offset, str, MIN(strlen(str), MAX_UA_LEN - offset)); hub_free(str); } } hub_free(ua_name_encoded); hub_free(ua_version_encoded); return 0; }
/* * 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; }
static int set_feature_cast_supports(struct hub_user* u, struct adc_message* cmd) { char *it, *tmp; if (adc_msg_has_named_argument(cmd, ADC_INF_FLAG_SUPPORT)) { tmp = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_SUPPORT); if (!tmp) return -1; // FIXME: OOM user_clear_feature_cast_support(u); it = tmp; while (strlen(it) > 4) { it[4] = 0; /* FIXME: Not really needed */ user_set_feature_cast_support(u, it); it = &it[5]; } if (*it) { user_set_feature_cast_support(u, it); } hub_free(tmp); } return 0; }
/** * 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; }
static int check_nick(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd) { char* nick; char* tmp; enum nick_status status; tmp = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_NICK); if (!tmp) return 0; nick = adc_msg_unescape(tmp); free(tmp); tmp = 0; if (!nick) return 0; status = nick_length_ok(nick); if (status != nick_ok) { hub_free(nick); if (status == nick_invalid_short) return status_msg_inf_error_nick_short; return status_msg_inf_error_nick_long; } status = nick_bad_characters(nick); if (status != nick_ok) { hub_free(nick); if (status == nick_invalid_spaces) return status_msg_inf_error_nick_spaces; return status_msg_inf_error_nick_bad_chars; } status = nick_is_utf8(nick); if (status != nick_ok) { hub_free(nick); return status_msg_inf_error_nick_not_utf8; } if (user_is_connecting(user)) { memcpy(user->id.nick, nick, strlen(nick)); user->id.nick[strlen(nick)] = 0; } hub_free(nick); return 0; }
/* * It is possible to do user-agent checking here. * But this is not something we want to do, and is deprecated in the ADC specification. * One should rather look at capabilities/features. */ static int check_user_agent(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd) { char* ua_encoded = 0; char* ua = 0; /* Get client user agent version */ ua_encoded = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_USER_AGENT); if (ua_encoded) { ua = adc_msg_unescape(ua_encoded); if (ua) { memcpy(user->id.user_agent, ua, MIN(strlen(ua), MAX_UA_LEN)); hub_free(ua); } } hub_free(ua_encoded); return 0; }
static int check_limits(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd) { char* arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_SHARED_SIZE); if (arg) { int64_t shared_size = atoll(arg); if (shared_size < 0) shared_size = 0; if (user_is_logged_in(user)) { hub->users->shared_size -= user->limits.shared_size; hub->users->shared_size += shared_size; } user->limits.shared_size = shared_size; hub_free(arg); arg = 0; } arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_SHARED_FILES); if (arg) { int shared_files = atoi(arg); if (shared_files < 0) shared_files = 0; if (user_is_logged_in(user)) { hub->users->shared_files -= user->limits.shared_files; hub->users->shared_files += shared_files; } user->limits.shared_files = shared_files; hub_free(arg); arg = 0; } arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_COUNT_HUB_NORMAL); if (arg) { int num = atoi(arg); if (num < 0) num = 0; user->limits.hub_count_user = num; hub_free(arg); arg = 0; } arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_COUNT_HUB_REGISTER); if (arg) { int num = atoi(arg); if (num < 0) num = 0; user->limits.hub_count_registered = num; hub_free(arg); arg = 0; } arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_COUNT_HUB_OPERATOR); if (arg) { int num = atoi(arg); if (num < 0) num = 0; user->limits.hub_count_operator = num; hub_free(arg); arg = 0; } arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_UPLOAD_SLOTS); if (arg) { int num = atoi(arg); if (num < 0) num = 0; user->limits.upload_slots = num; hub_free(arg); arg = 0; } /* summarize total slots */ user->limits.hub_count_total = user->limits.hub_count_user + user->limits.hub_count_registered + user->limits.hub_count_operator; if (!user_is_protected(user)) { if (user->limits.shared_size < hub_get_min_share(hub) && hub_get_min_share(hub)) { return status_msg_user_share_size_low; } if (user->limits.shared_size > hub_get_max_share(hub) && hub_get_max_share(hub)) { return status_msg_user_share_size_high; } if ((user->limits.hub_count_user > hub_get_max_hubs_user(hub) && hub_get_max_hubs_user(hub)) || (user->limits.hub_count_registered > hub_get_max_hubs_reg(hub) && hub_get_max_hubs_reg(hub)) || (user->limits.hub_count_operator > hub_get_max_hubs_op(hub) && hub_get_max_hubs_op(hub)) || (user->limits.hub_count_total > hub_get_max_hubs_total(hub) && hub_get_max_hubs_total(hub))) { return status_msg_user_hub_limit_high; } if ((user->limits.hub_count_user < hub_get_min_hubs_user(hub) && hub_get_min_hubs_user(hub)) || (user->limits.hub_count_registered < hub_get_min_hubs_reg(hub) && hub_get_min_hubs_reg(hub)) || (user->limits.hub_count_operator < hub_get_min_hubs_op(hub) && hub_get_min_hubs_op(hub))) { return status_msg_user_hub_limit_low; } if (user->limits.upload_slots < hub_get_min_slots(hub) && hub_get_min_slots(hub)) { return status_msg_user_slots_low; } if (user->limits.upload_slots > hub_get_max_slots(hub) && hub_get_max_slots(hub)) { return status_msg_user_slots_high; } } return 0; }