Beispiel #1
0
int32_t
qb_ipcc_us_setup_connect(struct qb_ipcc_connection *c,
			 struct qb_ipc_connection_response *r)
{
	int32_t res;
	struct qb_ipc_connection_request request;
	struct ipc_auth_data *data;
#ifdef QB_LINUX
	int off = 0;
	int on = 1;
#endif

	res = qb_ipcc_stream_sock_connect(c->name, &c->setup.u.us.sock);
	if (res != 0) {
		return res;
	}
#ifdef QB_LINUX
	setsockopt(c->setup.u.us.sock, SOL_SOCKET, SO_PASSCRED, &on,
		   sizeof(on));
#endif

	memset(&request, 0, sizeof(request));
	request.hdr.id = QB_IPC_MSG_AUTHENTICATE;
	request.hdr.size = sizeof(request);
	request.max_msg_size = c->setup.max_msg_size;
	res = qb_ipc_us_send(&c->setup, &request, request.hdr.size);
	if (res < 0) {
		qb_ipcc_us_sock_close(c->setup.u.us.sock);
		return res;
	}

	data = init_ipc_auth_data(c->setup.u.us.sock, sizeof(struct qb_ipc_connection_response));
	if (data == NULL) {
		qb_ipcc_us_sock_close(c->setup.u.us.sock);
		return -ENOMEM;
	}

	qb_ipc_us_ready(&c->setup, NULL, -1, POLLIN);
	res = qb_ipc_us_recv_msghdr(data);

#ifdef QB_LINUX
	setsockopt(c->setup.u.us.sock, SOL_SOCKET, SO_PASSCRED, &off,
		   sizeof(off));
#endif

	if (res != data->len) {
		destroy_ipc_auth_data(data);
		return res;
	}

	memcpy(r, &data->msg.res, sizeof(struct qb_ipc_connection_response));

	qb_ipc_auth_creds(data);
	c->egid = data->ugp.gid;
	c->server_pid = data->ugp.pid;

	destroy_ipc_auth_data(data);
	return r->hdr.error;
}
Beispiel #2
0
static void
qb_ipcs_uc_recv_and_auth(int32_t sock, struct qb_ipcs_service *s)
{
	int res = 0;
	struct ipc_auth_data *data = NULL;
#ifdef SO_PASSCRED
	int on = 1;
#endif

	data = init_ipc_auth_data(sock, sizeof(struct qb_ipc_connection_request));
	if (data == NULL) {
		close(sock);
		/* -ENOMEM */
		return;
	}

	data->s = s;
	qb_ipcs_ref(data->s);

#ifdef SO_PASSCRED
	setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
#endif

	res = s->poll_fns.dispatch_add(QB_LOOP_MED,
					data->sock,
					POLLIN | POLLPRI | POLLNVAL,
					data, process_auth);
	if (res < 0) {
		qb_util_log(LOG_DEBUG, "Failed to process AUTH for fd (%d)", data->sock);
		close(sock);
		destroy_ipc_auth_data(data);
	}
}
Beispiel #3
0
static struct ipc_auth_data *
init_ipc_auth_data(int sock, size_t len)
{
	struct ipc_auth_data *data = calloc(1, sizeof(struct ipc_auth_data));

	if (data == NULL) {
		return NULL;
	}

	data->msg_recv.msg_iov = &data->iov_recv;
	data->msg_recv.msg_iovlen = 1;
	data->msg_recv.msg_name = 0;
	data->msg_recv.msg_namelen = 0;

#ifdef SO_PASSCRED
	data->cmsg_cred = calloc(1, CMSG_SPACE(sizeof(struct ucred)));
	if (data->cmsg_cred == NULL) {
		destroy_ipc_auth_data(data);
		return NULL;
	}
	data->msg_recv.msg_control = (void *)data->cmsg_cred;
	data->msg_recv.msg_controllen = CMSG_SPACE(sizeof(struct ucred));
#endif
#ifdef QB_SOLARIS
	data->msg_recv.msg_accrights = 0;
	data->msg_recv.msg_accrightslen = 0;
#else
	data->msg_recv.msg_flags = 0;
#endif /* QB_SOLARIS */

	data->len = len;
	data->iov_recv.iov_base = &data->msg;
	data->iov_recv.iov_len = data->len;
	data->sock = sock;

	return data;
}
Beispiel #4
0
static int32_t
process_auth(int32_t fd, int32_t revents, void *d)
{
	struct ipc_auth_data *data = (struct ipc_auth_data *) d;

	int32_t res = 0;
#ifdef SO_PASSCRED
	int off = 0;
#endif

	if (data->s->server_sock == -1) {
		qb_util_log(LOG_DEBUG, "Closing fd (%d) for server shutdown", fd);
		res = -ESHUTDOWN;
		goto cleanup_and_return;
	}

	if (revents & POLLNVAL) {
		qb_util_log(LOG_DEBUG, "NVAL conn fd (%d)", fd);
		res = -EINVAL;
		goto cleanup_and_return;
	}
	if (revents & POLLHUP) {
		qb_util_log(LOG_DEBUG, "HUP conn fd (%d)", fd);
		res = -ESHUTDOWN;
		goto cleanup_and_return;
	}
	if ((revents & POLLIN) == 0) {
		return 0;
	}

	res = qb_ipc_us_recv_msghdr(data);
	if (res == -EAGAIN) {
		/* yield to mainloop, Let mainloop call us again */
		return 0;
	}

	if (res != data->len) {
		res = -EIO;
		goto cleanup_and_return;
	}

	res = qb_ipc_auth_creds(data);

cleanup_and_return:
#ifdef SO_PASSCRED
	setsockopt(data->sock, SOL_SOCKET, SO_PASSCRED, &off, sizeof(off));
#endif

	(void)data->s->poll_fns.dispatch_del(data->sock);

	if (res < 0) {
		close(data->sock);
	} else if (data->msg.req.hdr.id == QB_IPC_MSG_AUTHENTICATE) {
		(void)handle_new_connection(data->s, res, data->sock, &data->msg, data->len, &data->ugp);
	} else {
		close(data->sock);
	}
	destroy_ipc_auth_data(data);

	return 1;
}