Blame src/daemon/toks_daemon_ioctl.c

e6c547
/*********************************************************/
e6c547
/*  toksvc: a framework-native token broker service      */
d91fa0
/*  Copyright (C) 2020  SysDeer Technologies, LLC        */
e6c547
/*  Released under GPLv2 and GPLv3; see COPYING.TOKSVC.  */
e6c547
/*********************************************************/
e6c547
e6c547
#include <psxtypes/psxtypes.h>
e6c547
#include <ntapi/ntapi.h>
e6c547
#include <ntapi/nt_termios.h>
e6c547
e6c547
#include "toksvc_daemon_impl.h"
e6c547
#include "toksvc_driver_impl.h"
ca08aa
#include "toksvc_log_impl.h"
e6c547
e6c547
static int32_t toks_daemon_ioctl_get_token_count(struct toks_daemon_ctx * dctx)
e6c547
{
e6c547
	nt_tty_port_msg * msg = &dctx->reply;
e6c547
	msg->ttyinfo.exarg = (void *)(intptr_t)toks_get_driver_ntokens(dctx->driver_ctx);
e6c547
	return NT_STATUS_SUCCESS;
e6c547
}
e6c547
8f6a66
static int32_t toks_daemon_ioctl_set_token_count(struct toks_daemon_ctx * dctx)
8f6a66
{
8f6a66
	nt_tty_port_msg * msg;
8f6a66
	int               ntokens;
8f6a66
8f6a66
	msg     = &dctx->reply;
8f6a66
	ntokens = (int)(intptr_t)msg->ttyinfo.exarg;
8f6a66
dc482a
	if (ntokens < 0)
dc482a
		return NT_STATUS_INVALID_PARAMETER;
dc482a
dc482a
	else if (ntokens > toks_get_driver_atokens(dctx->driver_ctx))
8f6a66
		return NT_STATUS_BUFFER_TOO_SMALL;
8f6a66
8f6a66
	toks_set_driver_ntokens(dctx->driver_ctx,ntokens);
8f6a66
971724
	dctx->ftokens = (dctx->utokens < ntokens)
971724
		? ntokens - dctx->utokens : 0;
971724
8f6a66
	return toks_daemon_release(dctx);
8f6a66
}
8f6a66
a644fe
static int32_t toks_daemon_ioctl_get_log_level(struct toks_daemon_ctx * dctx)
a644fe
{
a644fe
	nt_tty_port_msg * msg = &dctx->reply;
a644fe
	msg->ttyinfo.exarg = (void *)(intptr_t)dctx->driver_ctx->cctx->loglevel;
a644fe
	return NT_STATUS_SUCCESS;
a644fe
}
a644fe
a644fe
static int32_t toks_daemon_ioctl_set_log_level(struct toks_daemon_ctx * dctx)
a644fe
{
a644fe
	nt_tty_port_msg * msg;
a644fe
	int               loglevel;
a644fe
a644fe
	msg      = &dctx->reply;
a644fe
	loglevel = (int)(intptr_t)msg->ttyinfo.exarg;
a644fe
a644fe
	if ((loglevel < 0) || (loglevel > 9))
a644fe
		return NT_STATUS_INVALID_PARAMETER;
a644fe
a644fe
	toks_set_driver_log_level(dctx->driver_ctx,loglevel);
a644fe
a644fe
	toks_log_service_info(dctx);
a644fe
a644fe
	return NT_STATUS_SUCCESS;
a644fe
}
a644fe
ca08aa
static int32_t toks_daemon_ioctl_get_service_info(struct toks_daemon_ctx * dctx)
ca08aa
{
ca08aa
	nt_tty_port_msg * msg = &dctx->reply;
ca08aa
ca08aa
	/* uuid */
ca08aa
	msg->svcdata.meta[0]  = (dctx->driver_ctx->cctx->uuid->data1);
ca08aa
ca08aa
	msg->svcdata.meta[1]  = (dctx->driver_ctx->cctx->uuid->data2);
ca08aa
	msg->svcdata.meta[1] |= (dctx->driver_ctx->cctx->uuid->data3 << 16);
ca08aa
ca08aa
	msg->svcdata.meta[2]  = (dctx->driver_ctx->cctx->uuid->data4[0]);
ca08aa
	msg->svcdata.meta[2] |= (dctx->driver_ctx->cctx->uuid->data4[1] << 8);
ca08aa
	msg->svcdata.meta[2] |= (dctx->driver_ctx->cctx->uuid->data4[2] << 16);
ca08aa
	msg->svcdata.meta[2] |= (dctx->driver_ctx->cctx->uuid->data4[3] << 24);
ca08aa
ca08aa
	msg->svcdata.meta[3]  = (dctx->driver_ctx->cctx->uuid->data4[4]);
ca08aa
	msg->svcdata.meta[3] |= (dctx->driver_ctx->cctx->uuid->data4[5] << 8);
ca08aa
	msg->svcdata.meta[3] |= (dctx->driver_ctx->cctx->uuid->data4[6] << 16);
ca08aa
	msg->svcdata.meta[3] |= (dctx->driver_ctx->cctx->uuid->data4[7] << 24);
ca08aa
ca08aa
	/* syspid, systid */
ca08aa
	msg->svcdata.data[0]  = pe_get_current_process_id();
ca08aa
	msg->svcdata.data[1]  = pe_get_current_thread_id();
ca08aa
ca08aa
	/* ctrlpid, csyspid */
ca08aa
	msg->svcdata.data[2]  = dctx->ctrlpid;
ca08aa
	msg->svcdata.data[3]  = dctx->csyspid;
ca08aa
91a57a
	/* allocated, available, pending */
ca08aa
	msg->svcdata.data[4]  = toks_get_driver_atokens(dctx->driver_ctx);
ca08aa
	msg->svcdata.data[5]  = toks_get_driver_ntokens(dctx->driver_ctx);
91a57a
	msg->svcdata.data[6]  = toks_get_driver_nwaiters(dctx->driver_ctx);
ca08aa
ca08aa
	/* used, free */
91a57a
	msg->svcdata.data[7]  = dctx->utokens;
91a57a
	msg->svcdata.data[8]  = dctx->ftokens;
ca08aa
ca08aa
	return NT_STATUS_SUCCESS;
ca08aa
}
ca08aa
ca08aa
static int32_t toks_daemon_ioctl_log_service_info(struct toks_daemon_ctx * dctx)
ca08aa
{
ca08aa
	toks_log_service_info(dctx);
ca08aa
	return NT_STATUS_SUCCESS;
ca08aa
}
ca08aa
7c2549
static int32_t toks_daemon_ioctl_get_token_info(struct toks_daemon_ctx * dctx)
7c2549
{
7c2549
	int32_t                     status;
7c2549
	void *                      hprocess;
7c2549
	void *                      hfile;
7c2549
	void *                      hrfile;
7c2549
	void *                      addr;
7c2549
	char *                      mark;
7c2549
	size_t                      size;
7c2549
	int32_t                     idx;
7c2549
	nt_oa                       oa;
7c2549
	nt_sd_common_buffer         sd;
7c2549
	nt_iosb                     iosb;
7c2549
	nt_unicode_string           path;
7c2549
	nt_large_integer            asize;
7c2549
	struct toks_token *         token;
093128
	struct toks_waiter *        waiter;
7c2549
	struct toks_token_ctx *     tctx;
7c2549
	struct toks_token_info *    tinfo;
7c2549
	struct toks_token_sctx      stctx;
7c2549
	uint32_t                    access;
7c2549
	uint32_t                    access_owner;
7c2549
	uint32_t                    access_group;
7c2549
	uint32_t                    access_other;
7c2549
	uint32_t                    access_admin;
093128
	int32_t                     nwaiters;
7c2549
	uint32_t                    keys[4];
7c2549
	wchar16_t                   name[37];
7c2549
7c2549
	/* service info */
7c2549
	toks_daemon_ioctl_get_service_info(dctx);
7c2549
7c2549
	/* hprocess */
7c2549
	oa.len      = sizeof(nt_oa);
7c2549
	oa.root_dir = 0;
7c2549
	oa.obj_name = 0;
7c2549
	oa.obj_attr = 0;
7c2549
	oa.sec_desc = 0;
7c2549
	oa.sec_qos  = 0;
7c2549
7c2549
	if ((status = ntapi->zw_open_process(
7c2549
			&hprocess,
7c2549
			NT_PROCESS_SYNCHRONIZE
7c2549
				| NT_PROCESS_DUP_HANDLE
7c2549
				| NT_PROCESS_QUERY_INFORMATION,
7c2549
			&oa,&dctx->request.header.client_id)))
7c2549
		return status;
7c2549
7c2549
	/* sd */
7c2549
	access_owner  = NT_GENERIC_READ     | NT_GENERIC_WRITE;
7c2549
	access_group  = NT_SEC_READ_CONTROL | NT_FILE_READ_ATTRIBUTES;
7c2549
	access_other  = NT_SEC_READ_CONTROL | NT_FILE_READ_ATTRIBUTES;
7c2549
7c2549
	access_owner |= NT_SEC_STANDARD_RIGHTS_ALL;
7c2549
	access_admin  = access_owner;
7c2549
7c2549
	ntapi->acl_init_common_descriptor(
7c2549
		&sd,0,0,0,0,
7c2549
		access_owner,access_group,access_other,
7c2549
		access_admin,access_owner,
7c2549
		0);
7c2549
7c2549
	/* name */
7c2549
	toks_query_performance_counters(
7c2549
		dctx->driver_ctx,
7c2549
		&dctx->pcnt);
7c2549
7c2549
	keys[0] = ntapi->tt_buffer_crc32(
7c2549
		dctx->noise,
7c2549
		&dctx->pcnt,sizeof(dctx->pcnt));
7c2549
7c2549
	keys[1] = ntapi->tt_buffer_crc32(
7c2549
		keys[0],
7c2549
		&dctx->request.header,sizeof(dctx->request.header));
7c2549
7c2549
	keys[2] = ntapi->tt_buffer_crc32(
7c2549
		keys[1],
7c2549
		toks_get_driver_tokens(dctx->driver_ctx),
7c2549
		toks_get_driver_ntokens(dctx->driver_ctx)
7c2549
		* sizeof(struct toks_token));
7c2549
7c2549
	keys[3] = ntapi->tt_buffer_crc32(
7c2549
		keys[2],
7c2549
		dctx,sizeof(*dctx));
7c2549
7c2549
	name[0]  = '.';
7c2549
	name[9]  = '.';
7c2549
	name[18] = '.';
7c2549
	name[27] = '.';
7c2549
	name[36] = 0;
7c2549
7c2549
	ntapi->tt_uint32_to_hex_utf16(keys[0],&name[1]);
7c2549
	ntapi->tt_uint32_to_hex_utf16(keys[1],&name[10]);
7c2549
	ntapi->tt_uint32_to_hex_utf16(keys[2],&name[19]);
7c2549
	ntapi->tt_uint32_to_hex_utf16(keys[3],&name[28]);
7c2549
7c2549
	/* path */
7c2549
	path.strlen = 36 * sizeof(wchar16_t);
7c2549
	path.maxlen = 0;
7c2549
	path.buffer = name;
7c2549
7c2549
	/* oa */
7c2549
	oa.len      = sizeof(nt_oa);
7c2549
	oa.root_dir = toks_get_driver_tmpfs(dctx->driver_ctx);
7c2549
	oa.obj_name = &pat;;
7c2549
	oa.obj_attr = 0;
7c2549
	oa.sec_desc = &sd.sd;
7c2549
	oa.sec_qos  = 0;
7c2549
7c2549
	/* access */
7c2549
	access  = NT_SEC_SYNCHRONIZE | NT_SEC_DELETE;
7c2549
	access |= NT_FILE_READ_DATA  | NT_FILE_READ_ATTRIBUTES;
7c2549
	access |= NT_FILE_WRITE_DATA | NT_FILE_WRITE_ATTRIBUTES;
7c2549
7c2549
	/* alloc_size */
093128
	nwaiters    = toks_get_driver_nwaiters(dctx->driver_ctx);
093128
f90166
	asize.quad  = __offsetof(struct toks_token_ctx,tokens);
7c2549
	asize.quad += sizeof(struct toks_token_info) * dctx->utokens;
093128
	asize.quad += sizeof(struct toks_token_info) * nwaiters;
7c2549
7c2549
	/* create temporary file */
7c2549
	status =  ntapi->zw_create_file(
7c2549
		&hfile,
7c2549
		access,&oa,&iosb,&asize,
7c2549
		NT_FILE_ATTRIBUTE_NORMAL,
7c2549
		0,NT_FILE_CREATE,
7c2549
		NT_FILE_NON_DIRECTORY_FILE
7c2549
			| NT_FILE_SYNCHRONOUS_IO_ALERT
7c2549
			| NT_FILE_DELETE_ON_CLOSE,
7c2549
		0,0);
7c2549
7c2549
	if (status) {
7c2549
		ntapi->zw_close(hprocess);
7c2549
		return status;
7c2549
	}
7c2549
7c2549
	/* buffer */
093128
	if ((dctx->utokens + nwaiters) <= 512) {
7c2549
		tctx  = 0;
7c2549
		addr  = &stctx;
7c2549
		size  = asize.quad;
620f32
		tinfo = stctx.tokens;
7c2549
7c2549
		stctx.allocated = toks_get_driver_atokens(dctx->driver_ctx);
7c2549
		stctx.available = toks_get_driver_ntokens(dctx->driver_ctx);
093128
		stctx.pending   = nwaiters;
7c2549
		stctx.tused     = dctx->utokens;
7c2549
		stctx.tfree     = dctx->ftokens;
7c2549
	} else {
7c2549
		size = asize.quad;
7c2549
		addr = toks_calloc(1,size);
7c2549
7c2549
		if (!addr) {
7c2549
			ntapi->zw_close(hfile);
7c2549
			ntapi->zw_close(hprocess);
7c2549
			return NT_STATUS_MEMORY_NOT_ALLOCATED;
7c2549
		}
7c2549
7c2549
		tctx  = (struct toks_token_ctx *)addr;
f89256
		tinfo = tctx->tokens;
7c2549
7c2549
		tctx->allocated = toks_get_driver_atokens(dctx->driver_ctx);
7c2549
		tctx->available = toks_get_driver_ntokens(dctx->driver_ctx);
093128
		tctx->pending   = nwaiters;
7c2549
		tctx->tused     = dctx->utokens;
7c2549
		tctx->tfree     = dctx->ftokens;
7c2549
	}
7c2549
7c2549
	/* token info */
7c2549
	token = toks_get_driver_tokens(dctx->driver_ctx);
7c2549
7c2549
	for (idx=0; idx<dctx->utokens; token++) {
7c2549
		if (token->self) {
7c2549
			tinfo->tokpid  = token->client.tokpid;
7c2549
			tinfo->tsyspid = token->client.cid.process_id;
7c2549
			tinfo->pad     = 0;
7c2549
7c2549
			tinfo->keys[0] = token->keys.key[0];
7c2549
			tinfo->keys[1] = token->keys.key[1];
7c2549
			tinfo->keys[2] = token->keys.key[2];
7c2549
			tinfo->keys[3] = token->keys.key[3];
7c2549
			tinfo->keys[4] = token->keys.key[4];
7c2549
			tinfo->keys[5] = token->keys.key[5];
7c2549
7c2549
			tinfo->meta[0] = token->meta.key[0];
7c2549
			tinfo->meta[1] = token->meta.key[1];
7c2549
			tinfo->meta[2] = token->meta.key[2];
7c2549
			tinfo->meta[3] = token->meta.key[3];
7c2549
			tinfo->meta[4] = token->meta.key[4];
7c2549
			tinfo->meta[5] = token->meta.key[5];
7c2549
7c2549
			idx++;
7c2549
			tinfo++;
7c2549
		}
7c2549
	}
7c2549
093128
	/* waiter info */
093128
	idx    = 0;
093128
	waiter = dctx->waiter_first;
093128
093128
	for (; idx
093128
		if (waiter->msg.header.msg_id) {
093128
			tinfo->tokpid  = waiter->client.tokpid;
093128
			tinfo->tsyspid = waiter->client.cid.process_id;
093128
			tinfo->pad     = 0;
093128
093128
			tinfo->keys[0] = waiter->msg.syncinfo.ipckeys[0];
093128
			tinfo->keys[1] = waiter->msg.syncinfo.ipckeys[1];
093128
			tinfo->keys[2] = waiter->msg.syncinfo.ipckeys[2];
093128
			tinfo->keys[3] = waiter->msg.syncinfo.ipckeys[3];
093128
			tinfo->keys[4] = waiter->msg.syncinfo.ipckeys[4];
093128
			tinfo->keys[5] = waiter->msg.syncinfo.ipckeys[5];
093128
093128
			tinfo->meta[0] = waiter->msg.syncinfo.ipcsvc.keys.key[0];
093128
			tinfo->meta[1] = waiter->msg.syncinfo.ipcsvc.keys.key[1];
093128
			tinfo->meta[2] = waiter->msg.syncinfo.ipcsvc.keys.key[2];
093128
			tinfo->meta[3] = waiter->msg.syncinfo.ipcsvc.keys.key[3];
093128
			tinfo->meta[4] = waiter->msg.syncinfo.ipcsvc.keys.key[4];
093128
			tinfo->meta[5] = waiter->msg.syncinfo.ipcsvc.keys.key[5];
093128
093128
			idx++;
093128
			tinfo++;
093128
		}
093128
093128
		if (++waiter == dctx->waiter_cap)
093128
			waiter = dctx->waiter_base;
093128
	}
093128
7c2549
	/* write */
7c2549
	for (mark=addr; size; size-=iosb.info) {
7c2549
		status = ntapi->zw_write_file(
7c2549
			hfile,0,0,0,
7c2549
			&iosb,addr,size,
7c2549
			0,0);
7c2549
7c2549
		switch (status) {
7c2549
			case NT_STATUS_SUCCESS:
7c2549
				mark += iosb.info;
7c2549
				addr  = mark;
7c2549
				break;
7c2549
7c2549
			default:
7c2549
				ntapi->zw_close(hfile);
7c2549
				ntapi->zw_close(hprocess);
7c2549
7c2549
				if (tctx)
7c2549
					toks_free(tctx);
7c2549
7c2549
				return status;
7c2549
		}
7c2549
	}
7c2549
7c2549
	/* buffer */
7c2549
	if (tctx)
7c2549
		toks_free(tctx);
7c2549
7c2549
	/* remote handle */
7c2549
	status = ntapi->zw_duplicate_object(
7c2549
		NT_CURRENT_PROCESS_HANDLE,
7c2549
		hfile,
7c2549
		hprocess,
7c2549
		&hrfile,
7c2549
		0,0,
7c2549
		NT_DUPLICATE_SAME_ACCESS
7c2549
			| NT_DUPLICATE_SAME_ATTRIBUTES);
7c2549
7c2549
7c2549
	ntapi->zw_close(hfile);
7c2549
	ntapi->zw_close(hprocess);
7c2549
7c2549
	switch (status) {
7c2549
		case NT_STATUS_SUCCESS:
7c2549
			dctx->reply.ttyinfo.exarg = hrfile;
7c2549
			return NT_STATUS_SUCCESS;
7c2549
7c2549
		default:
7c2549
			dctx->reply.ttyinfo.exarg = 0;
7c2549
			return status;
7c2549
	}
7c2549
}
7c2549
8ae1fc
static int32_t toks_daemon_ioctl_log_token_info(struct toks_daemon_ctx * dctx)
8ae1fc
{
8ae1fc
	toks_log_token_info(dctx);
8ae1fc
	return NT_STATUS_SUCCESS;
8ae1fc
}
8ae1fc
e6c547
int32_t __stdcall toks_daemon_ioctl(struct toks_daemon_ctx * dctx)
e6c547
{
e6c547
	nt_tty_port_msg * msg;
e6c547
	uint32_t          ctlcode;
e6c547
e6c547
	msg     = &dctx->reply;
e6c547
	ctlcode = msg->ttyinfo.opdata;
e6c547
e6c547
	switch (ctlcode) {
e6c547
		case TOKS_IOCTL_GET_TOKEN_COUNT:
e6c547
			return toks_daemon_ioctl_get_token_count(dctx);
e6c547
8f6a66
		case TOKS_IOCTL_SET_TOKEN_COUNT:
8f6a66
			return toks_daemon_ioctl_set_token_count(dctx);
8f6a66
ca08aa
		case TOKS_IOCTL_GET_SERVICE_INFO:
ca08aa
			return toks_daemon_ioctl_get_service_info(dctx);
ca08aa
ca08aa
		case TOKS_IOCTL_LOG_SERVICE_INFO:
ca08aa
			return toks_daemon_ioctl_log_service_info(dctx);
ca08aa
7c2549
		case TOKS_IOCTL_GET_TOKEN_INFO:
7c2549
			return toks_daemon_ioctl_get_token_info(dctx);
7c2549
8ae1fc
		case TOKS_IOCTL_LOG_TOKEN_INFO:
8ae1fc
			return toks_daemon_ioctl_log_token_info(dctx);
8ae1fc
a644fe
		case TOKS_IOCTL_GET_LOG_LEVEL:
a644fe
			return toks_daemon_ioctl_get_log_level(dctx);
a644fe
a644fe
		case TOKS_IOCTL_SET_LOG_LEVEL:
a644fe
			return toks_daemon_ioctl_set_log_level(dctx);
a644fe
e6c547
		default:
e6c547
			return NT_STATUS_NOT_IMPLEMENTED;
e6c547
	}
e6c547
}