Esempio n. 1
0
File: hub.c Progetto: imobilis/uhub
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;
}
Esempio n. 2
0
File: inf.c Progetto: leejb521/uhub
/*
 * 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;
}
Esempio n. 3
0
File: hub.c Progetto: imobilis/uhub
static void hub_event_dispatcher(void* callback_data, struct event_data* message)
{
	int status;
	struct hub_info* hub = (struct hub_info*) callback_data;
	struct hub_user* user = (struct hub_user*) message->ptr;
	uhub_assert(hub != NULL);

	switch (message->id)
	{
		case UHUB_EVENT_USER_JOIN:
		{
			if (user_is_disconnecting(user))
				break;

			if (message->flags)
			{
				hub_send_password_challenge(hub, user);
			}
			else
			{
				/* Race condition, we could have two messages for two logins queued up.
				   So make sure we don't let the second client in. */
				status = check_duplicate_logins_ok(hub, user);
				if (!status)
				{
					on_login_success(hub, user);
				}
				else
				{
					on_login_failure(hub, user, (enum status_message) status);
				}
			}
			break;
		}

		case UHUB_EVENT_USER_QUIT:
		{
			uman_remove(hub->users, user);
			uman_send_quit_message(hub, hub->users, user);
			on_logout_user(hub, user);
			hub_schedule_destroy_user(hub, user);
			break;
		}

		case UHUB_EVENT_USER_DESTROY:
		{
			user_destroy(user);
			break;
		}

		case UHUB_EVENT_HUB_SHUTDOWN:
		{
			struct hub_user* u = (struct hub_user*) list_get_first(hub->users->list);
			while (u)
			{
				uman_remove(hub->users, u);
				user_destroy(u);
				u = (struct hub_user*) list_get_first(hub->users->list);
			}
			break;
		}


		default:
			/* FIXME: ignored */
			break;
	}
}
Esempio n. 4
0
File: hub.c Progetto: imobilis/uhub
int hub_handle_support(struct hub_info* hub, struct hub_user* u, struct adc_message* cmd)
{
	int ret = 0;
	int index = 0;
	int ok = 1;
	char* arg = adc_msg_get_argument(cmd, index);

	if (hub->status == hub_status_disabled && u->state == state_protocol)
	{
		on_login_failure(hub, u, status_msg_hub_disabled);
		hub_free(arg);
		return -1;
	}

	while (arg)
	{
		if (strlen(arg) == 6)
		{
			fourcc_t fourcc = FOURCC(arg[2], arg[3], arg[4], arg[5]);
			if (strncmp(arg, ADC_SUP_FLAG_ADD, 2) == 0)
			{
				user_support_add(u, fourcc);
			}
			else if (strncmp(arg, ADC_SUP_FLAG_REMOVE, 2) == 0)
			{
				user_support_remove(u, fourcc);
			}
			else
			{
				ok = 0;
			}
		}
		else
		{
			ok = 0;
		}

		index++;
		hub_free(arg);
		arg = adc_msg_get_argument(cmd, index);
	}

	if (u->state == state_protocol)
	{
		if (index == 0) ok = 0; /* Need to support *SOMETHING*, at least BASE */
		if (!ok)
		{
			/* disconnect user. Do not send crap during initial handshake! */
			hub_disconnect_user(hub, u, quit_logon_error);
			return -1;
		}

		if (user_flag_get(u, feature_base))
		{
			/* User supports ADC/1.0 and a hash we know */
			if (user_flag_get(u, feature_tiger))
			{
				hub_send_handshake(hub, u);
				/* TODO: timeouts for mux users */
				if (u->connection)
					net_con_set_timeout(u->connection, TIMEOUT_HANDSHAKE);
			}
			else
			{
				// no common hash algorithm.
				hub_send_status(hub, u, status_msg_proto_no_common_hash, status_level_fatal);
				hub_disconnect_user(hub, u, quit_protocol_error);
			}
		}
		else if (user_flag_get(u, feature_bas0))
		{
			if (hub->config->obsolete_clients)
			{
				hub_send_handshake(hub, u);
				/* TODO: timeouts for mux users */
				if (u->connection)
					net_con_set_timeout(u->connection, TIMEOUT_HANDSHAKE);
			}
			else
			{
				/* disconnect user for using an obsolete client. */
				char* tmp = adc_msg_escape(hub->config->msg_proto_obsolete_adc0);
				struct adc_message* message = adc_msg_construct(ADC_CMD_IMSG, 6 + strlen(tmp));
				adc_msg_add_argument(message, tmp);
				hub_free(tmp);
				route_to_user(hub, u, message);
				adc_msg_free(message);
				hub_disconnect_user(hub, u, quit_protocol_error);
			}
		}
		else
		{
			/* Not speaking a compatible protocol - just disconnect. */
			hub_disconnect_user(hub, u, quit_logon_error);
		}
	}

	return ret;
}