예제 #1
0
static void login_connection_authreply_input(struct login_connection *conn)
{
	const char *line;

	while ((line = i_stream_read_next_line(conn->input)) != NULL) T_BEGIN {
		if (!conn->handshaked) {
			if (!version_string_verify(line, "director-authreply-client",
						   AUTHREPLY_PROTOCOL_MAJOR_VERSION)) {
				i_error("authreply client sent invalid handshake: %s", line);
				login_connection_deinit(&conn);
				return;
			}
			conn->handshaked = TRUE;
		} else {
			auth_input_line(line, conn);
		}
	} T_END;
	if (conn->input->eof) {
		if (conn->input->stream_errno != 0 &&
		    conn->input->stream_errno != ECONNRESET) {
			i_error("read(authreply connection) failed: %s",
				i_stream_get_error(conn->input));
		}
		login_connection_deinit(&conn);
	}
}
예제 #2
0
void login_connections_deinit(void)
{
	while (login_connections != NULL) {
		struct login_connection *conn = login_connections;

		login_connection_deinit(&conn);
	}
}
예제 #3
0
static void login_connection_input(struct login_connection *conn)
{
	unsigned char buf[4096];
	ssize_t ret;

	ret = read(conn->fd, buf, sizeof(buf));
	if (ret <= 0) {
		if (ret < 0) {
			if (errno == EAGAIN)
				return;
			if (errno != ECONNRESET)
				i_error("read(login connection) failed: %m");
		}
		login_connection_deinit(&conn);
		return;
	}
	auth_connection_send(conn->auth, buf, ret);
}
예제 #4
0
static void auth_input_line(const char *line, void *context)
{
	struct login_connection *conn = context;
	struct login_host_request *request, temp_request;
	const char *const *args, *line_params, *username = NULL, *tag = "";
	bool proxy = FALSE, host = FALSE;

	if (line == NULL) {
		/* auth connection died -> kill also this login connection */
		login_connection_deinit(&conn);
		return;
	}
	if (conn->type != LOGIN_CONNECTION_TYPE_USERDB &&
	    strncmp(line, "OK\t", 3) == 0)
		line_params = line + 3;
	else if (conn->type == LOGIN_CONNECTION_TYPE_USERDB &&
		 strncmp(line, "PASS\t", 5) == 0)
		line_params = line + 5;
	else {
		login_connection_send_line(conn, line);
		return;
	}

	/* OK <id> [<parameters>] */
	args = t_strsplit_tab(line_params);
	if (*args != NULL) {
		/* we should always get here, but in case we don't just
		   forward as-is and let login process handle the error. */
		args++;
	}

	memset(&temp_request, 0, sizeof(temp_request));
	for (; *args != NULL; args++) {
		if (strncmp(*args, "proxy", 5) == 0 &&
		    ((*args)[5] == '=' || (*args)[5] == '\0'))
			proxy = TRUE;
		else if (strncmp(*args, "host=", 5) == 0)
			host = TRUE;
		else if (strncmp(*args, "lip=", 4) == 0) {
			if (net_addr2ip((*args) + 4, &temp_request.local_ip) < 0)
				i_error("auth sent invalid lip field: %s", (*args) + 6);
		} else if (strncmp(*args, "lport=", 6) == 0) {
			if (str_to_uint((*args) + 6, &temp_request.local_port) < 0)
				i_error("auth sent invalid lport field: %s", (*args) + 6);
		} else if (strncmp(*args, "port=", 5) == 0) {
			if (str_to_uint((*args) + 5, &temp_request.dest_port) < 0)
				i_error("auth sent invalid port field: %s", (*args) + 6);
		} else if (strncmp(*args, "destuser="******"director_tag=", 13) == 0)
			tag = *args + 13;
		else if (strncmp(*args, "director_proxy_maybe", 20) == 0 &&
			 ((*args)[20] == '=' || (*args)[20] == '\0'))
			temp_request.director_proxy_maybe = TRUE;
		else if (strncmp(*args, "user=", 5) == 0) {
			if (username == NULL)
				username = *args + 5;
		}
	}
	if ((!proxy && !temp_request.director_proxy_maybe) ||
	    host || username == NULL) {
		login_connection_send_line(conn, line);
		return;
	}
	if (*conn->dir->set->master_user_separator != '\0') {
		/* with master user logins we still want to use only the
		   login username */
		username = t_strcut(username,
				    *conn->dir->set->master_user_separator);
	}

	/* we need to add the host. the lookup might be asynchronous */
	request = i_new(struct login_host_request, 1);
	*request = temp_request;
	request->conn = conn;
	request->line = i_strdup(line);
	request->username = i_strdup(username);

	conn->refcount++;
	director_request(conn->dir, username, tag, login_host_callback, request);
}
예제 #5
0
static void auth_input_line(const char *line, void *context)
{
	struct login_connection *conn = context;
	struct login_host_request *request;
	const char *const *args, *line_params, *username = NULL;
	bool proxy = FALSE, host = FALSE;

	if (line == NULL) {
		/* auth connection died -> kill also this login connection */
		login_connection_deinit(&conn);
		return;
	}
	if (!conn->userdb && strncmp(line, "OK\t", 3) == 0)
		line_params = line + 3;
	else if (conn->userdb && strncmp(line, "PASS\t", 5) == 0)
		line_params = line + 5;
	else {
		login_connection_send_line(conn, line);
		return;
	}

	/* OK <id> [<parameters>] */
	args = t_strsplit_tab(line_params);
	if (*args != NULL) {
		/* we should always get here, but in case we don't just
		   forward as-is and let login process handle the error. */
		args++;
	}

	for (; *args != NULL; args++) {
		if (strncmp(*args, "proxy", 5) == 0 &&
		    ((*args)[5] == '=' || (*args)[5] == '\0'))
			proxy = TRUE;
		else if (strncmp(*args, "host=", 5) == 0)
			host = TRUE;
		else if (strncmp(*args, "destuser="******"user=", 5) == 0) {
			if (username == NULL)
				username = *args + 5;
		}
	}
	if (!proxy || host || username == NULL) {
		login_connection_send_line(conn, line);
		return;
	}
	if (*conn->dir->set->master_user_separator != '\0') {
		/* with master user logins we still want to use only the
		   login username */
		username = t_strcut(username,
				    *conn->dir->set->master_user_separator);
	}

	/* we need to add the host. the lookup might be asynchronous */
	request = i_new(struct login_host_request, 1);
	request->conn = conn;
	request->line = i_strdup(line);
	request->username = i_strdup(username);

	conn->refcount++;
	director_request(conn->dir, username, login_host_callback, request);
}