Blame src/daemon/toks_daemon_acquire.c

44e933
/*********************************************************/
44e933
/*  toksvc: a framework-native token broker service      */
44e933
/*  Copyright (C) 2020  Z. Gilboa                        */
44e933
/*  Released under GPLv2 and GPLv3; see COPYING.TOKSVC.  */
44e933
/*********************************************************/
44e933
44e933
#include <psxtypes/psxtypes.h>
44e933
#include <ntapi/ntapi.h>
44e933
44e933
#include <toksvc/toksvc.h>
44e933
#include "toksvc_daemon_impl.h"
44e933
#include "toksvc_driver_impl.h"
44e933
c78a06
static void toks_daemon_token_release(struct toks_token * token)
c78a06
{
c78a06
	void *			hport;
c78a06
	struct _nt_tty_ipc_msg	msg;
c78a06
	uint32_t *		keys;
c78a06
c78a06
	hport = token->client.hdaemon;
c78a06
	keys  = token->keys.key;
c78a06
c78a06
	ntapi->tt_aligned_block_memset(
c78a06
		&msg,0,sizeof(msg));
c78a06
c78a06
	msg.header.msg_type	= NT_LPC_NEW_MESSAGE;
c78a06
	msg.header.data_size	= sizeof(msg.data);
c78a06
	msg.header.msg_size	= sizeof(msg);
c78a06
	msg.data.ttyinfo.opcode	= TOKS_DAEMON_RELEASE;
c78a06
c78a06
	msg.data.ipcinfo.ipckeys[0] = keys[0];
c78a06
	msg.data.ipcinfo.ipckeys[1] = keys[1];
c78a06
	msg.data.ipcinfo.ipckeys[2] = keys[2];
c78a06
	msg.data.ipcinfo.ipckeys[3] = keys[3];
c78a06
	msg.data.ipcinfo.ipckeys[4] = keys[4];
c78a06
	msg.data.ipcinfo.ipckeys[5] = keys[5];
c78a06
c78a06
	ntapi->zw_request_wait_reply_port(
c78a06
		hport,&msg,&msg;;
c78a06
}
c78a06
44e933
static int32_t toks_daemon_client_wait(void * rapunzel)
44e933
{
44e933
	struct toks_token *      token;
44e933
	struct toks_client_ctx * client;
44e933
	void *                   hduo[2];
44e933
44e933
	token  = (struct toks_token *)rapunzel;
44e933
	client = &token->client;
44e933
44e933
	ntapi->zw_set_event(client->hswap,0);
44e933
44e933
	hduo[0] = client->hprocess;
44e933
	hduo[1] = client->halert;
44e933
44e933
	ntapi->zw_wait_for_multiple_objects(
44e933
		2,hduo,
44e933
		NT_WAIT_ANY,
44e933
		NT_SYNC_NON_ALERTABLE,
44e933
		0);
44e933
44e933
	ntapi->zw_close(client->hprocess);
44e933
	ntapi->zw_close(client->hport);
44e933
	ntapi->zw_close(client->halert);
44e933
c78a06
	toks_daemon_token_release(token);
c78a06
44e933
	return ntapi->zw_terminate_thread(
44e933
		NT_CURRENT_THREAD_HANDLE,
44e933
		NT_STATUS_SUCCESS);
44e933
}
44e933
44e933
static void toks_daemon_token_reset(struct toks_token * token)
44e933
{
44e933
	token->self        = 0;
44e933
	token->keys.key[0] = 0;
44e933
	token->keys.key[1] = 0;
44e933
	token->keys.key[2] = 0;
44e933
	token->keys.key[3] = 0;
44e933
	token->keys.key[4] = 0;
44e933
	token->keys.key[5] = 0;
44e933
}
44e933
44e933
static int32_t toks_daemon_token_instance(
44e933
	struct toks_token *         token,
44e933
	struct toks_client_ctx *    client)
44e933
{
44e933
	int32_t			status;
44e933
	nt_thread_params	params;
44e933
44e933
	if ((status = ntapi->tt_create_private_event(
44e933
			&client->hswap,
44e933
			NT_NOTIFICATION_EVENT,
44e933
			NT_EVENT_NOT_SIGNALED)))
44e933
		return status;
44e933
44e933
	status = ntapi->tt_create_private_event(
44e933
		&client->halert,
44e933
		NT_NOTIFICATION_EVENT,
44e933
		NT_EVENT_NOT_SIGNALED);
44e933
44e933
	if (status) {
44e933
		ntapi->zw_close(client->hswap);
44e933
		return status;
44e933
	}
44e933
44e933
	token->self                     = token;
44e933
	token->client.hprocess          = client->hprocess;
44e933
	token->client.hswap             = client->hswap;
44e933
	token->client.halert            = client->halert;
c78a06
	token->client.hdaemon           = client->hdaemon;
44e933
	token->client.cid.process_id    = client->cid.process_id;
44e933
	token->client.cid.thread_id     = client->cid.thread_id;
44e933
44e933
	ntapi->tt_aligned_block_memset(
44e933
		&params,0,sizeof(params));
44e933
44e933
	params.hprocess		  = NT_CURRENT_PROCESS_HANDLE;
44e933
	params.start		  = toks_daemon_client_wait;
44e933
	params.ext_ctx            = token;
44e933
	params.ext_ctx_size       = sizeof(*token);
44e933
	params.stack_size_commit  = 4 * 1024;
44e933
	params.stack_size_reserve = 4 * 1024;
44e933
	params.creation_flags	  = NT_CREATE_LOCAL_THREAD;
44e933
44e933
	if ((status = ntapi->tt_create_thread(&params))) {
44e933
		toks_daemon_token_reset(token);
44e933
		ntapi->zw_close(client->hswap);
44e933
		ntapi->zw_close(client->halert);
44e933
		return status;
44e933
	}
44e933
44e933
	status = ntapi->zw_wait_for_single_object(
44e933
		client->hswap,
44e933
		NT_SYNC_NON_ALERTABLE,
44e933
		0);
44e933
c11340
	ntapi->zw_close(client->hswap);
c11340
44e933
	if (status) {
44e933
		toks_daemon_token_reset(token);
44e933
		ntapi->zw_close(client->halert);
44e933
		return status;
44e933
	}
44e933
44e933
	token->client.hinstance = params.hthread;
44e933
44e933
	return NT_STATUS_SUCCESS;
44e933
}
44e933
658181
static int32_t toks_daemon_queue(struct toks_daemon_ctx * dctx, void * hcaller, void * hprocess)
d73408
{
d73408
	int                         nwaiters;
d73408
	struct toks_waiter *        waiter;
d73408
	nt_tty_port_msg *           msg;
658181
	void *                      hevent;
658181
	int32_t                     status;
d73408
d73408
	msg      = &dctx->reply;
d73408
	nwaiters = toks_get_driver_nwaiters(dctx->driver_ctx);
d73408
d73408
	if (nwaiters == TOKS_MAX_WAITERS)
d73408
		return NT_STATUS_TIMEOUT;
d73408
658181
658181
	status = ntapi->zw_duplicate_object(
658181
		hcaller,
658181
		msg->ipcinfo.hevent,
658181
		NT_CURRENT_PROCESS_HANDLE,
658181
		&hevent,
658181
		NT_EVENT_QUERY_STATE|NT_EVENT_MODIFY_STATE,
658181
		0,0);
658181
658181
	ntapi->zw_close(hcaller);
658181
658181
	if (status) {
658181
		ntapi->zw_close(hprocess);
658181
		return status;
658181
	}
658181
658181
	if ((status = ntapi->zw_reset_event(hevent,&(int){0}))) {
658181
		ntapi->zw_close(hprocess);
658181
		ntapi->zw_close(hevent);
658181
		return status;
658181
	}
658181
658181
681a45
	waiter = dctx->waiter_next;
d73408
658181
	waiter->client.hprocess = hprocess;
658181
	waiter->client.hevent   = hevent;
658181
d73408
	toks_set_driver_nwaiters(
d73408
		dctx->driver_ctx,
d73408
		++nwaiters);
d73408
681a45
	dctx->waiter_next++;
681a45
681a45
	if (dctx->waiter_next == dctx->waiter_cap)
681a45
		dctx->waiter_next = dctx->waiter_base;
681a45
d73408
	ntapi->tt_generic_memcpy(
d73408
		&waiter->msg,msg,
d73408
		sizeof(*msg));
d73408
658181
	return NT_STATUS_PENDING;
d73408
}
d73408
44e933
int32_t __stdcall toks_daemon_acquire(struct toks_daemon_ctx * dctx)
44e933
{
44e933
	int32_t                     status;
44e933
	nt_tty_port_msg *           msg;
658181
	void *                      hcaller;
44e933
	struct toks_client_ctx      client;
44e933
	nt_oa                       oa;
44e933
	struct toks_token *         token;
44e933
	struct toks_token *         tocap;
44e933
	nt_filetime                 pcnt;
44e933
44e933
	msg                   = &dctx->reply;
44e933
44e933
	client.hport          = 0;
44e933
	client.hprocess       = 0;
44e933
	client.hswap          = 0;
c78a06
	client.hdaemon        = dctx->hport_internal_client;
44e933
	client.cid.process_id = msg->header.client_id.process_id;
44e933
	client.cid.thread_id  = 0;
44e933
44e933
	oa.len      = sizeof(oa);
44e933
	oa.root_dir = 0;
44e933
	oa.obj_name = 0;
44e933
	oa.obj_attr = 0;
44e933
	oa.sec_desc = 0;
44e933
	oa.sec_qos  = 0;
44e933
658181
	if (dctx->opcode == TOKS_DAEMON_ACQUIRE) {
658181
		if (msg->ipcinfo.ctrlsvc.keys.key[0]) {
658181
			if ((status = toks_daemon_pidopen(dctx)))
658181
				return status;
44e933
658181
			client.cid.process_id = msg->ipcinfo.ctrlsvc.keys.key[1];
658181
		}
500bc3
658181
		if ((status = ntapi->zw_open_process(
658181
				&client.hprocess,
658181
				NT_PROCESS_SYNCHRONIZE
658181
					| NT_PROCESS_DUP_HANDLE
658181
					| NT_PROCESS_QUERY_INFORMATION,
658181
				&oa,&client.cid)))
658181
			return status;
500bc3
	}
500bc3
44e933
	token = toks_get_driver_tokens(dctx->driver_ctx);
44e933
	tocap = &token[toks_get_driver_ntokens(dctx->driver_ctx)];
44e933
44e933
	for (; token->self && (token
44e933
		token++;
44e933
658181
	if ((token == tocap) && !msg->ipcinfo.hevent) {
44e933
		ntapi->zw_close(client.hprocess);
44e933
		return NT_STATUS_TIMEOUT;
44e933
	}
44e933
658181
	toks_query_performance_counters(dctx->driver_ctx,&pcnt);
658181
44e933
	if (token == tocap) {
658181
		status = ntapi->zw_open_process(
658181
			&hcaller,
658181
			NT_PROCESS_SYNCHRONIZE
658181
				| NT_PROCESS_DUP_HANDLE
658181
				| NT_PROCESS_QUERY_INFORMATION,
658181
			&oa,&msg->header.client_id);
658181
658181
		if (status) {
658181
			ntapi->zw_close(client.hprocess);
658181
			return status;
658181
		}
44e933
658181
		msg->ipcinfo.ipckeys[0] = ntapi->tt_buffer_crc32(
658181
			msg->header.msg_id,
658181
			&pcnt,sizeof(pcnt));
44e933
658181
		msg->ipcinfo.ipckeys[1] = ntapi->tt_buffer_crc32(
658181
			msg->header.msg_id,
658181
			&msg->header,sizeof(msg->header));
658181
658181
		msg->ipcinfo.ipckeys[2] = ntapi->tt_buffer_crc32(
658181
			msg->header.msg_id,
658181
			&msg->ipcinfo,sizeof(msg->ipcinfo));
658181
658181
		msg->ipcinfo.ipckeys[3] = ntapi->tt_buffer_crc32(
658181
			msg->header.msg_id,
658181
			&client,sizeof(client));
658181
658181
		msg->ipcinfo.ipckeys[4] = ntapi->tt_buffer_crc32(
658181
			msg->header.msg_id,
658181
			toks_get_driver_tokens(dctx->driver_ctx),
658181
			toks_get_driver_ntokens(dctx->driver_ctx)
658181
			* sizeof(struct toks_token));
658181
658181
		msg->ipcinfo.ipckeys[5] = ntapi->tt_buffer_crc32(
658181
			msg->header.msg_id,
658181
			&token->keys,sizeof(token->keys));
658181
658181
		return toks_daemon_queue(
658181
			dctx,hcaller,
658181
			client.hprocess);
658181
	}
658181
658181
	if (dctx->opcode == TOKS_DAEMON_RELEASE) {
658181
		client.hprocess    = msg->ttyinfo.exarg;
658181
658181
		token->keys.key[0] = msg->ipcinfo.ipckeys[0];
658181
		token->keys.key[1] = msg->ipcinfo.ipckeys[1];
658181
		token->keys.key[2] = msg->ipcinfo.ipckeys[2];
658181
		token->keys.key[3] = msg->ipcinfo.ipckeys[3];
658181
		token->keys.key[4] = msg->ipcinfo.ipckeys[4];
658181
		token->keys.key[5] = msg->ipcinfo.ipckeys[5];
658181
	} else {
658181
		token->keys.key[0] = ntapi->tt_buffer_crc32(
658181
			msg->header.msg_id,
658181
			&pcnt,sizeof(pcnt));
658181
658181
		token->keys.key[1] = ntapi->tt_buffer_crc32(
658181
			msg->header.msg_id,
658181
			&msg->header,sizeof(msg->header));
658181
658181
		token->keys.key[2] = ntapi->tt_buffer_crc32(
658181
			msg->header.msg_id,
658181
			&msg->ipcinfo,sizeof(msg->ipcinfo));
658181
658181
		token->keys.key[3] = ntapi->tt_buffer_crc32(
658181
			msg->header.msg_id,
658181
			&client,sizeof(client));
658181
658181
		token->keys.key[4] = ntapi->tt_buffer_crc32(
658181
			msg->header.msg_id,
658181
			toks_get_driver_tokens(dctx->driver_ctx),
658181
			toks_get_driver_ntokens(dctx->driver_ctx)
658181
			* sizeof(struct toks_token));
658181
658181
		token->keys.key[5] = ntapi->tt_buffer_crc32(
658181
			msg->header.msg_id,
658181
			&token->keys,sizeof(token->keys));
658181
658181
		msg->ipcinfo.ipckeys[0] = token->keys.key[0];
658181
		msg->ipcinfo.ipckeys[1] = token->keys.key[1];
658181
		msg->ipcinfo.ipckeys[2] = token->keys.key[2];
658181
		msg->ipcinfo.ipckeys[3] = token->keys.key[3];
658181
		msg->ipcinfo.ipckeys[4] = token->keys.key[4];
658181
		msg->ipcinfo.ipckeys[5] = token->keys.key[5];
658181
	}
44e933
44e933
	if ((status = toks_daemon_token_instance(token,&client))) {
44e933
		toks_daemon_token_reset(token);
44e933
		ntapi->zw_close(client.hprocess);
44e933
		return status;
44e933
	}
44e933
44e933
	return NT_STATUS_SUCCESS;
44e933
}