Blob Blame History Raw
/*********************************************************/
/*  toksvc: a framework-native token broker service      */
/*  Copyright (C) 2020  SysDeer Technologies, LLC        */
/*  Released under GPLv2 and GPLv3; see COPYING.TOKSVC.  */
/*********************************************************/

#include <psxtypes/psxtypes.h>
#include <ntapi/ntapi.h>

#include <toksvc/toksvc.h>
#include "toksvc_driver_impl.h"
#include "toksvc_daemon_impl.h"

int32_t toks_get_server_snapshot(
	struct toks_driver_ctx *        dctx,
	struct toks_server_snapshot **  snapshot)
{
	int32_t                         status;
	void *                          hport;
	void *                          hfile;
	void *                          hsection;
	void *                          addr;
	size_t                          size;
	nt_oa                           oa;
	nt_large_integer                ssize;
	nt_sd_common_buffer             sd;
	struct _nt_tty_port_msg         msg;
	struct toks_server_snapshot *   ctx;
	struct toks_service_info *      svcinfo;
	uint32_t                        access_owner;
	uint32_t                        access_group;
	uint32_t                        access_other;
	uint32_t                        access_admin;

	hport  = toks_get_driver_hservice(dctx);

	ntapi->tt_aligned_block_memset(
		&msg,0,sizeof(msg));

	msg.header.msg_type  = NT_LPC_NEW_MESSAGE;
	msg.header.data_size = sizeof(msg.ttyinfo) + sizeof(msg.svcdata);
	msg.header.msg_size  = sizeof(msg);
	msg.ttyinfo.opcode   = TOKS_DAEMON_IOCTL;
	msg.ttyinfo.opdata   = TOKS_IOCTL_GET_TOKEN_INFO;

	if ((status = ntapi->zw_request_wait_reply_port(hport,&msg,&msg)))
		return status;

	else if (msg.ttyinfo.status)
		return msg.ttyinfo.status;

	/* token info */
	hfile = msg.ttyinfo.exarg;

	/* snapshot context */
	if (!(addr = toks_calloc(1,sizeof(*ctx)))) {
		ntapi->zw_close(hfile);
		return NT_STATUS_MEMORY_NOT_ALLOCATED;
	}

	ctx     = (struct toks_server_snapshot *)addr;
	svcinfo = (struct toks_service_info *)addr;

	/* uuid */
	svcinfo->uuid.data1    = (msg.svcdata.meta[0]);

	svcinfo->uuid.data2    = (msg.svcdata.meta[1]  & 0xffff);
	svcinfo->uuid.data3    = (msg.svcdata.meta[1] >> 16);

	svcinfo->uuid.data4[0] = (msg.svcdata.meta[2] & 0xff);
	svcinfo->uuid.data4[1] = (msg.svcdata.meta[2] & 0xff00) >> 8;
	svcinfo->uuid.data4[2] = (msg.svcdata.meta[2] & 0xff0000) >> 16;
	svcinfo->uuid.data4[3] = (msg.svcdata.meta[2] & 0xff000000) >> 24;

	svcinfo->uuid.data4[4] = (msg.svcdata.meta[3] & 0xff);
	svcinfo->uuid.data4[5] = (msg.svcdata.meta[3] & 0xff00) >> 8;
	svcinfo->uuid.data4[6] = (msg.svcdata.meta[3] & 0xff0000) >> 16;
	svcinfo->uuid.data4[7] = (msg.svcdata.meta[3] & 0xff000000) >> 24;

	/* syspid, systid */
	svcinfo->syspid        = msg.svcdata.data[0];
	svcinfo->systid        = msg.svcdata.data[1];

	/* ctrlpid, csyspid */
	svcinfo->ctrlpid       = msg.svcdata.data[2];
	svcinfo->csyspid       = msg.svcdata.data[3];

	/* allocated, available, pending */
	svcinfo->allocated     = msg.svcdata.data[4];
	svcinfo->available     = msg.svcdata.data[5];
	svcinfo->pending       = msg.svcdata.data[6];

	/* used, free */
	svcinfo->tused         = msg.svcdata.data[7];
	svcinfo->tfree         = msg.svcdata.data[8];

	/* sd */
	access_owner  = NT_GENERIC_READ;
	access_group  = NT_SEC_READ_CONTROL | NT_FILE_READ_ATTRIBUTES;
	access_other  = NT_SEC_READ_CONTROL | NT_FILE_READ_ATTRIBUTES;

	access_owner |= NT_SEC_STANDARD_RIGHTS_ALL;
	access_admin  = access_owner;

	ntapi->acl_init_common_descriptor(
		&sd,0,0,0,0,
		access_owner,access_group,access_other,
		access_admin,access_owner,
		0);

	/* section */
	oa.len		= sizeof(oa);
	oa.root_dir	= 0;
	oa.obj_name	= 0;
	oa.obj_attr	= 0;
	oa.sec_desc	= &sd.sd;
	oa.sec_qos	= 0;

	addr		= 0;
	ssize.quad	= 0;

	size		= __offsetof(struct toks_token_ctx,tokens);
	size           += svcinfo->tused * sizeof(struct toks_token_info);

	status = ntapi->zw_create_section(
		&hsection,
		NT_SECTION_QUERY|NT_SECTION_MAP_READ,
		&oa,&ssize,
		NT_PAGE_READONLY,
		NT_SEC_COMMIT,
		hfile);

	if (status) {
		ntapi->zw_close(hfile);
		toks_free(ctx);
		return status;
	};

	/* section mapping */
	status = ntapi->zw_map_view_of_section(
		hsection,
		NT_CURRENT_PROCESS_HANDLE,
		&addr,0,0,0,
		&size,NT_VIEW_UNMAP,
		0,NT_PAGE_READONLY);

	ntapi->zw_close(hfile);
	ntapi->zw_close(hsection);

	if (status) {
		toks_free(ctx);
		return status;
	};

	/* all done */
	ctx->tokctx = addr;
	*snapshot   = ctx;

	return NT_STATUS_SUCCESS;
}

void toks_free_server_snapshot(struct toks_server_snapshot * snapshot)
{
	ntapi->zw_unmap_view_of_section(
		NT_CURRENT_PROCESS_HANDLE,
		(void *)snapshot->tokctx);

	toks_free(snapshot);
}