Blob Blame History Raw
/********************************************************/
/*  ntapi: Native API core library                      */
/*  Copyright (C) 2013--2017  Z. Gilboa                 */
/*  Released under GPLv2 and GPLv3; see COPYING.NTAPI.  */
/********************************************************/

#include <psxtypes/psxtypes.h>
#include <ntapi/nt_object.h>
#include <ntapi/nt_guid.h>
#include <ntapi/nt_string.h>
#include <ntapi/nt_acl.h>
#include "ntapi_impl.h"

typedef ntapi_zw_open_directory_object objdir_open_fn;

static  nt_keyed_objdir_name __template_name = {__NT_BASED_NAMED_OBJECTS,
						0,
						{0,0,0,0,0,0},
						{0,{0},0},
						{0}};


static nt_access_allowed_ace * __ipc_ace_init(
	nt_access_allowed_ace * ace,
	uint32_t		mask,
	const nt_sid *		sid)
{
	ace->mask             = mask;
	ace->header.ace_type  = NT_ACE_TYPE_ACCESS_ALLOWED;
	ace->header.ace_flags = 0;
	ace->header.ace_size  = sizeof(uint32_t) * sid->sub_authority_count
	                        + __offsetof(nt_access_allowed_ace,sid_start)
	                        + __offsetof(nt_sid,sub_authority);

	__ntapi->tt_sid_copy(
		(nt_sid *)&ace->sid_start,
		sid);

	return (nt_access_allowed_ace *)((size_t)ace + ace->header.ace_size);
}

static void __ipc_sd_init(nt_sd_common_buffer * sd, int fdir)
{
	nt_access_allowed_ace * ace;
	uint32_t		mask_system;
	uint32_t		mask_owner;
	uint32_t		mask_other;

	/* access mask */
	if (fdir) {
		mask_system = NT_SEC_READ_CONTROL
				| NT_DIRECTORY_QUERY
				| NT_DIRECTORY_TRAVERSE
				| NT_DIRECTORY_CREATE_OBJECT
				| NT_DIRECTORY_CREATE_SUBDIRECTORY;

		mask_owner  = NT_DIRECTORY_ALL_ACCESS;
		mask_other  = mask_system;
	} else {
		mask_system = NT_SYMBOLIC_LINK_ALL_ACCESS;
		mask_owner  = NT_SYMBOLIC_LINK_ALL_ACCESS;
		mask_other  = NT_SYMBOLIC_LINK_QUERY;
	}

	/* sd header */
	sd->sd.revision         = 1;
	sd->sd.sbz_1st          = 0;
	sd->sd.control          = NT_SE_SELF_RELATIVE | NT_SE_DACL_PRESENT;
	sd->sd.offset_owner     = __offsetof(nt_sd_common_buffer,owner);
	sd->sd.offset_group     = 0;
	sd->sd.offset_dacl      = __offsetof(nt_sd_common_buffer,dacl);
	sd->sd.offset_sacl      = 0;

	/* owner sid */
	__ntapi->tt_sid_copy(
		(nt_sid *)&sd->owner,
		__ntapi_internals()->user);


	/* ace's for LOCAL_SYSTEM, AUTHENTICATED_USERS, and process token user */
	ace = (nt_access_allowed_ace *)&sd->buffer;
	ace = __ipc_ace_init(ace,mask_system,&(nt_sid){1,1,{{0,0,0,0,0,5}},{18}});
	ace = __ipc_ace_init(ace,mask_other,&(nt_sid){1,1,{{0,0,0,0,0,5}},{11}});
	ace = __ipc_ace_init(ace,mask_owner,(nt_sid *)&sd->owner);

	sd->dacl.acl_revision   = 0x02;
	sd->dacl.sbz_1st        = 0;
	sd->dacl.acl_size       = (uint16_t)((char *)ace - (char *)&sd->dacl);
	sd->dacl.ace_count      = 3;
	sd->dacl.sbz_2nd        = 0;

}

static int32_t __stdcall __tt_create_ipc_object_directory(
	__out	void **			hdir,
	__in	uint32_t		desired_access,
	__in	const wchar16_t		prefix[6],
	__in	const nt_guid *		guid)
{
	int32_t			status;
	nt_ipc_objdir_name	objdir_name;
	nt_unicode_string	name;
	nt_sd_common_buffer	sd;
	nt_oa			oa;
	nt_sqos			sqos = {
					sizeof(sqos),
					NT_SECURITY_IMPERSONATION,
					NT_SECURITY_TRACKING_DYNAMIC,
					1};

	__ipc_sd_init(&sd,1);

	__ntapi->tt_generic_memcpy(
		&objdir_name,
		&__template_name,
		sizeof(objdir_name));

	__ntapi->tt_memcpy_utf16(
		objdir_name.prefix,
		prefix,
		sizeof(objdir_name.prefix));

	__ntapi->tt_guid_to_string_utf16(
		guid,
		(nt_guid_str_utf16 *)&objdir_name.objdir_guid);

	objdir_name.backslash = '\\';
	objdir_name.objdir_guid.uscore_guid = '_';

	name.strlen	= sizeof(objdir_name);
	name.maxlen	= 0;
	name.buffer	= (uint16_t *)&objdir_name;

	oa.len		= sizeof(oa);
	oa.root_dir	= 0;
	oa.obj_name	= &name;
	oa.obj_attr	= NT_OBJ_INHERIT
			  | NT_OBJ_OPENIF
			  | NT_OBJ_CASE_INSENSITIVE;
	oa.sec_desc	= &sd.sd;
	oa.sec_qos	= &sqos;

	status = __ntapi->zw_create_directory_object(
		hdir,desired_access,&oa);

	return (status == NT_STATUS_OBJECT_NAME_EXISTS)
		? NT_STATUS_SUCCESS
		: status;
}


static int32_t __stdcall __tt_create_keyed_object_directory(
	__out	void **			hdir,
	__in	uint32_t		desired_access,
	__in	const wchar16_t		prefix[6],
	__in	const nt_guid *		guid,
	__in	uint32_t		key,
	__in	objdir_open_fn *	openfn)
{
	nt_keyed_objdir_name	objdir_name;
	nt_unicode_string	name;
	nt_sd_common_buffer	sd;
	nt_oa			oa;
	nt_sqos			sqos = {
					sizeof(sqos),
					NT_SECURITY_IMPERSONATION,
					NT_SECURITY_TRACKING_DYNAMIC,
					1};

	__ipc_sd_init(&sd,1);

	__ntapi->tt_generic_memcpy(
		&objdir_name,
		&__template_name,
		sizeof(__template_name));

	__ntapi->tt_memcpy_utf16(
		objdir_name.prefix,
		prefix,
		sizeof(objdir_name.prefix));

	__ntapi->tt_guid_to_string_utf16(
		guid,
		(nt_guid_str_utf16 *)&objdir_name.objdir_guid);

	__ntapi->tt_uint32_to_hex_utf16(
		key,objdir_name.key);

	objdir_name.backslash = '\\';
	objdir_name.objdir_guid.uscore_guid = '_';
	objdir_name.objdir_guid.uscore_key  = '_';

	name.strlen	= sizeof(objdir_name);
	name.maxlen	= 0;
	name.buffer	= (uint16_t *)&objdir_name;

	oa.len		= sizeof(oa);
	oa.root_dir	= 0;
	oa.obj_name	= &name;
	oa.obj_attr	= NT_OBJ_INHERIT;
	oa.sec_desc	= &sd.sd;
	oa.sec_qos	= &sqos;

	return openfn(hdir,desired_access,&oa);
}


static int32_t __stdcall __tt_create_object_directory_entry(
	__out	void **			hentry,
	__in	uint32_t		desired_access,
	__in	void *			hdir,
	__in	void *			htarget,
	__in	nt_unicode_string *	target_name,
	__in	uint32_t		key)
{
	int32_t			status;
	nt_oa			oa;
	nt_unicode_string	name;
	nt_sd_common_buffer	sd;
	wchar16_t		keystr[8];
	uintptr_t		buffer[2048/sizeof(uintptr_t)];
	nt_sqos			sqos = {
					sizeof(sqos),
					NT_SECURITY_IMPERSONATION,
					NT_SECURITY_TRACKING_DYNAMIC,
					1};

	if (!target_name) {
		if ((status = __ntapi->zw_query_object(
				htarget,
				NT_OBJECT_NAME_INFORMATION,
				buffer,sizeof(buffer),0)))
			return status;
		target_name = (nt_unicode_string *)buffer;
	}

	__ipc_sd_init(&sd,0);
	__ntapi->tt_uint32_to_hex_utf16(key,keystr);

	name.strlen = sizeof(keystr);
	name.maxlen = 0;
	name.buffer = keystr;

	oa.len		= sizeof(oa);
	oa.root_dir	= hdir;
	oa.obj_name	= &name;
	oa.obj_attr	= 0;
	oa.sec_desc	= &sd.sd;
	oa.sec_qos	= &sqos;

	return __ntapi->zw_create_symbolic_link_object(
		hentry,
		desired_access,
		&oa,target_name);
}

int32_t __stdcall __ntapi_tt_open_ipc_object_directory(
	__out	void **			hdir,
	__in	uint32_t		desired_access,
	__in	const wchar16_t		prefix[6],
	__in	const nt_guid *		guid)
{
	return __tt_create_ipc_object_directory(
		hdir,desired_access,
		prefix,guid);
}

int32_t __stdcall __ntapi_tt_create_ipc_object_directory_entry(
	__out	void **			hentry,
	__in	uint32_t		desired_access,
	__in	void *			hdir,
	__in	void *			htarget,
	__in	nt_unicode_string *	target_name,
	__in	uint32_t		key)
{
	return __tt_create_object_directory_entry(
		hentry,desired_access,
		hdir,htarget,target_name,key);
}

int32_t __stdcall __ntapi_tt_open_dev_object_directory(
	__out	void **			hdir,
	__in	uint32_t		desired_access,
	__in	const wchar16_t		prefix[6],
	__in	const nt_guid *		ipc_guid)
{
	return __tt_create_ipc_object_directory(
		hdir,desired_access,
		prefix,ipc_guid);
}

int32_t __stdcall __ntapi_tt_create_dev_object_directory_entry(
	__out	void **			hentry,
	__in	uint32_t		desired_access,
	__in	void *			hdir,
	__in	void *			htarget,
	__in	nt_unicode_string *	target_name,
	__in	const nt_guid *		dev_guid)
{
	int32_t			status;
	nt_oa			oa;
	nt_unicode_string	name;
	nt_sd_common_buffer	sd;
	nt_guid_str_utf16	guidstr;
	uintptr_t		buffer[2048/sizeof(uintptr_t)];
	nt_sqos			sqos = {
					sizeof(sqos),
					NT_SECURITY_IMPERSONATION,
					NT_SECURITY_TRACKING_DYNAMIC,
					1};

	if (!target_name) {
		if ((status = __ntapi->zw_query_object(
				htarget,
				NT_OBJECT_NAME_INFORMATION,
				buffer,sizeof(buffer),0)))
			return status;
		target_name = (nt_unicode_string *)buffer;
	}

	__ipc_sd_init(&sd,0);
	__ntapi->tt_guid_to_string_utf16(dev_guid,&guidstr);

	name.strlen = sizeof(guidstr);
	name.maxlen = 0;
	name.buffer = &guidstr.lbrace;

	oa.len		= sizeof(oa);
	oa.root_dir	= hdir;
	oa.obj_name	= &name;
	oa.obj_attr	= 0;
	oa.sec_desc	= &sd.sd;
	oa.sec_qos	= &sqos;

	return __ntapi->zw_create_symbolic_link_object(
		hentry,
		desired_access,
		&oa,target_name);
}

int32_t __stdcall __ntapi_tt_create_keyed_object_directory(
	__out	void **			hdir,
	__in	uint32_t		desired_access,
	__in	const wchar16_t		prefix[6],
	__in	const nt_guid *		guid,
	__in	uint32_t		key)
{
	return __tt_create_keyed_object_directory(
		hdir,desired_access,
		prefix,guid,key,
		__ntapi->zw_create_directory_object);
}

int32_t __stdcall __ntapi_tt_open_keyed_object_directory(
	__out	void **			hdir,
	__in	uint32_t		desired_access,
	__in	const wchar16_t		prefix[6],
	__in	const nt_guid *		guid,
	__in	uint32_t		key)
{
	return __tt_create_keyed_object_directory(
		hdir,desired_access,
		prefix,guid,key,
		__ntapi->zw_open_directory_object);
}

int32_t __stdcall __ntapi_tt_create_keyed_object_directory_entry(
	__out	void **			hentry,
	__in	uint32_t		desired_access,
	__in	void *			hdir,
	__in	void *			htarget,
	__in	nt_unicode_string *	target_name,
	__in	uint32_t		key)
{
	return __tt_create_object_directory_entry(
		hentry,desired_access,
		hdir,htarget,target_name,key);
}