Blame src/object/ntapi_tt_keyed_object_directory.c

dd89bb
/********************************************************/
dd89bb
/*  ntapi: Native API core library                      */
dde53a
/*  Copyright (C) 2013--2017  Z. Gilboa                 */
dd89bb
/*  Released under GPLv2 and GPLv3; see COPYING.NTAPI.  */
dd89bb
/********************************************************/
dd89bb
dd89bb
#include <psxtypes/psxtypes.h>
dd89bb
#include <ntapi/nt_object.h>
dd89bb
#include <ntapi/nt_guid.h>
dd89bb
#include <ntapi/nt_string.h>
b8eeed
#include <ntapi/nt_acl.h>
dd89bb
#include "ntapi_impl.h"
dd89bb
36da55
#define __SID_SYSTEM			{1,1,{{0,0,0,0,0,5}},{18}}
36da55
#define __SID_OWNER_RIGHTS		{1,1,{{0,0,0,0,0,3}},{4}}
36da55
#define __SID_AUTHENTICATED_USERS	{1,1,{{0,0,0,0,0,5}},{11}}
36da55
36da55
static const nt_sid    sid_system       = __SID_SYSTEM;
36da55
static const nt_sid    sid_owner_rights = __SID_OWNER_RIGHTS;
36da55
static const nt_sid    sid_auth_users   = __SID_AUTHENTICATED_USERS;
36da55
dd89bb
typedef ntapi_zw_open_directory_object objdir_open_fn;
dd89bb
d5e229
static void __tt_guid_to_hex_utf16(
d5e229
	__in	const nt_guid *	guid,
d5e229
	__out	wchar16_t * 	hex_str)
d5e229
{
d5e229
	uint16_t key;
d5e229
d5e229
	__ntapi_tt_uint32_to_hex_utf16(
d5e229
		guid->data1,&hex_str[0]);
d5e229
d5e229
	__ntapi_tt_uint16_to_hex_utf16(
d5e229
		guid->data2,&hex_str[9]);
d5e229
d5e229
	__ntapi_tt_uint16_to_hex_utf16(
d5e229
		guid->data3,&hex_str[14]);
d5e229
d5e229
	key = guid->data4[0] * 0x100 + guid->data4[1];
d5e229
d5e229
	__ntapi_tt_uint16_to_hex_utf16(
d5e229
		key,&hex_str[19]);
d5e229
d5e229
	key = guid->data4[2] * 0x100 + guid->data4[3];
d5e229
d5e229
	__ntapi_tt_uint16_to_hex_utf16(
d5e229
		key,&hex_str[24]);
d5e229
d5e229
	key = guid->data4[4] * 0x100 + guid->data4[5];
af6bd7
d5e229
	__ntapi_tt_uint16_to_hex_utf16(
d5e229
		key,&hex_str[28]);
d5e229
d5e229
	key = guid->data4[6] * 0x100 + guid->data4[7];
d5e229
d5e229
	__ntapi_tt_uint16_to_hex_utf16(
d5e229
		key,&hex_str[32]);
d5e229
d5e229
	hex_str[8]  = '-';
d5e229
	hex_str[13] = '-';
d5e229
	hex_str[18] = '-';
d5e229
	hex_str[23] = '-';
d5e229
}
661c27
b8eeed
static nt_access_allowed_ace * __ipc_ace_init(
b8eeed
	nt_access_allowed_ace * ace,
b8eeed
	uint32_t		mask,
b8eeed
	const nt_sid *		sid)
b8eeed
{
b8eeed
	ace->mask             = mask;
b8eeed
	ace->header.ace_type  = NT_ACE_TYPE_ACCESS_ALLOWED;
b8eeed
	ace->header.ace_flags = 0;
b8eeed
	ace->header.ace_size  = sizeof(uint32_t) * sid->sub_authority_count
b8eeed
	                        + __offsetof(nt_access_allowed_ace,sid_start)
b8eeed
	                        + __offsetof(nt_sid,sub_authority);
b8eeed
b8eeed
	__ntapi->tt_sid_copy(
b8eeed
		(nt_sid *)&ace->sid_start,
b8eeed
		sid);
b8eeed
b8eeed
	return (nt_access_allowed_ace *)((size_t)ace + ace->header.ace_size);
b8eeed
}
b8eeed
b8eeed
static void __ipc_sd_init(nt_sd_common_buffer * sd, int fdir)
b8eeed
{
b8eeed
	nt_access_allowed_ace * ace;
b8eeed
	uint32_t		mask_system;
b8eeed
	uint32_t		mask_owner;
b8eeed
	uint32_t		mask_other;
b8eeed
b8eeed
	/* access mask */
b8eeed
	if (fdir) {
b8eeed
		mask_system = NT_SEC_READ_CONTROL
b8eeed
				| NT_DIRECTORY_QUERY
b8eeed
				| NT_DIRECTORY_TRAVERSE
b8eeed
				| NT_DIRECTORY_CREATE_OBJECT
b8eeed
				| NT_DIRECTORY_CREATE_SUBDIRECTORY;
b8eeed
b8eeed
		mask_owner  = NT_DIRECTORY_ALL_ACCESS;
b8eeed
		mask_other  = mask_system;
b8eeed
	} else {
b8eeed
		mask_system = NT_SYMBOLIC_LINK_ALL_ACCESS;
b8eeed
		mask_owner  = NT_SYMBOLIC_LINK_ALL_ACCESS;
e1cbd3
		mask_other  = NT_SYMBOLIC_LINK_ALL_ACCESS;
b8eeed
	}
b8eeed
b8eeed
	/* sd header */
b8eeed
	sd->sd.revision         = 1;
b8eeed
	sd->sd.sbz_1st          = 0;
b8eeed
	sd->sd.control          = NT_SE_SELF_RELATIVE | NT_SE_DACL_PRESENT;
b8eeed
	sd->sd.offset_owner     = __offsetof(nt_sd_common_buffer,owner);
b8eeed
	sd->sd.offset_group     = 0;
b8eeed
	sd->sd.offset_dacl      = __offsetof(nt_sd_common_buffer,dacl);
b8eeed
	sd->sd.offset_sacl      = 0;
b8eeed
b8eeed
	/* owner sid */
b8eeed
	__ntapi->tt_sid_copy(
b8eeed
		(nt_sid *)&sd->owner,
0a8487
		__ntapi_internals()->user);
b8eeed
b8eeed
b8eeed
	/* ace's for LOCAL_SYSTEM, AUTHENTICATED_USERS, and process token user */
b8eeed
	ace = (nt_access_allowed_ace *)&sd->buffer;
36da55
	ace = __ipc_ace_init(ace,mask_system,&sid_system);
36da55
	ace = __ipc_ace_init(ace,mask_other,&sid_auth_users);
36da55
	ace = __ipc_ace_init(ace,mask_owner,&sid_owner_rights);
b8eeed
	ace = __ipc_ace_init(ace,mask_owner,(nt_sid *)&sd->owner);
b8eeed
b8eeed
	sd->dacl.acl_revision   = 0x02;
b8eeed
	sd->dacl.sbz_1st        = 0;
b8eeed
	sd->dacl.acl_size       = (uint16_t)((char *)ace - (char *)&sd->dacl);
b8eeed
	sd->dacl.ace_count      = 3;
b8eeed
	sd->dacl.sbz_2nd        = 0;
b8eeed
b8eeed
}
b8eeed
661c27
static int32_t __stdcall __tt_create_ipc_object_directory(
661c27
	__out	void **			hdir,
661c27
	__in	uint32_t		desired_access,
661c27
	__in	const wchar16_t		prefix[6],
ae515f
	__in	const nt_guid *		guid)
661c27
{
661c27
	int32_t			status;
661c27
	nt_ipc_objdir_name	objdir_name;
661c27
	nt_unicode_string	name;
b8eeed
	nt_sd_common_buffer	sd;
661c27
	nt_oa			oa;
661c27
	nt_sqos			sqos = {
661c27
					sizeof(sqos),
661c27
					NT_SECURITY_IMPERSONATION,
661c27
					NT_SECURITY_TRACKING_DYNAMIC,
661c27
					1};
661c27
b8eeed
	__ipc_sd_init(&sd,1);
b8eeed
661c27
	__ntapi->tt_generic_memcpy(
d5e229
		objdir_name.base_named_objects,
d5e229
		(wchar16_t[])__NT_BASED_NAMED_OBJECTS,
d5e229
		sizeof(objdir_name.base_named_objects));
661c27
661c27
	__ntapi->tt_memcpy_utf16(
661c27
		objdir_name.prefix,
661c27
		prefix,
661c27
		sizeof(objdir_name.prefix));
661c27
d5e229
	__tt_guid_to_hex_utf16(
d5e229
		guid,objdir_name.guid);
661c27
661c27
	objdir_name.backslash = '\\';
d5e229
	objdir_name.uscore    = '_';
661c27
661c27
	name.strlen	= sizeof(objdir_name);
661c27
	name.maxlen	= 0;
d5e229
	name.buffer	= objdir_name.base_named_objects;
661c27
661c27
	oa.len		= sizeof(oa);
661c27
	oa.root_dir	= 0;
661c27
	oa.obj_name	= &nam;;
661c27
	oa.obj_attr	= NT_OBJ_INHERIT
661c27
			  | NT_OBJ_OPENIF
661c27
			  | NT_OBJ_CASE_INSENSITIVE;
b8eeed
	oa.sec_desc	= &sd.sd;
661c27
	oa.sec_qos	= &sqo;;
661c27
661c27
	status = __ntapi->zw_create_directory_object(
661c27
		hdir,desired_access,&oa);
661c27
661c27
	return (status == NT_STATUS_OBJECT_NAME_EXISTS)
661c27
		? NT_STATUS_SUCCESS
661c27
		: status;
661c27
}
661c27
661c27
dd89bb
static int32_t __stdcall __tt_create_keyed_object_directory(
dd89bb
	__out	void **			hdir,
dd89bb
	__in	uint32_t		desired_access,
d5e229
	__in	void *			hparent,
dd89bb
	__in	uint32_t		key,
dd89bb
	__in	objdir_open_fn *	openfn)
dd89bb
{
d5e229
	wchar16_t		keystr[8];
dd89bb
	nt_unicode_string	name;
b8eeed
	nt_sd_common_buffer	sd;
dd89bb
	nt_oa			oa;
dd89bb
	nt_sqos			sqos = {
dd89bb
					sizeof(sqos),
dd89bb
					NT_SECURITY_IMPERSONATION,
dd89bb
					NT_SECURITY_TRACKING_DYNAMIC,
dd89bb
					1};
dd89bb
b8eeed
	__ipc_sd_init(&sd,1);
b8eeed
dd89bb
	__ntapi->tt_uint32_to_hex_utf16(
d5e229
		key,keystr);
dd89bb
d5e229
	name.strlen = sizeof(keystr);
d5e229
	name.maxlen = 0;
d5e229
	name.buffer = keystr;
dd89bb
dd89bb
	oa.len		= sizeof(oa);
d5e229
	oa.root_dir	= hparent;
dd89bb
	oa.obj_name	= &nam;;
dd89bb
	oa.obj_attr	= NT_OBJ_INHERIT;
b8eeed
	oa.sec_desc	= &sd.sd;
dd89bb
	oa.sec_qos	= &sqo;;
dd89bb
dd89bb
	return openfn(hdir,desired_access,&oa);
dd89bb
}
dd89bb
dd89bb
661c27
static int32_t __stdcall __tt_create_object_directory_entry(
dd89bb
	__out	void **			hentry,
dd89bb
	__in	uint32_t		desired_access,
dd89bb
	__in	void *			hdir,
dd89bb
	__in	void *			htarget,
dd89bb
	__in	nt_unicode_string *	target_name,
dd89bb
	__in	uint32_t		key)
dd89bb
{
dd89bb
	int32_t			status;
dd89bb
	nt_oa			oa;
dd89bb
	nt_unicode_string	name;
b8eeed
	nt_sd_common_buffer	sd;
dd89bb
	wchar16_t		keystr[8];
dd89bb
	uintptr_t		buffer[2048/sizeof(uintptr_t)];
dd89bb
	nt_sqos			sqos = {
dd89bb
					sizeof(sqos),
dd89bb
					NT_SECURITY_IMPERSONATION,
dd89bb
					NT_SECURITY_TRACKING_DYNAMIC,
dd89bb
					1};
dd89bb
dd89bb
	if (!target_name) {
dd89bb
		if ((status = __ntapi->zw_query_object(
dd89bb
				htarget,
dd89bb
				NT_OBJECT_NAME_INFORMATION,
dd89bb
				buffer,sizeof(buffer),0)))
dd89bb
			return status;
dd89bb
		target_name = (nt_unicode_string *)buffer;
dd89bb
	}
dd89bb
b8eeed
	__ipc_sd_init(&sd,0);
dd89bb
	__ntapi->tt_uint32_to_hex_utf16(key,keystr);
dd89bb
dd89bb
	name.strlen = sizeof(keystr);
dd89bb
	name.maxlen = 0;
dd89bb
	name.buffer = keystr;
dd89bb
dd89bb
	oa.len		= sizeof(oa);
dd89bb
	oa.root_dir	= hdir;
dd89bb
	oa.obj_name	= &nam;;
dd89bb
	oa.obj_attr	= 0;
b8eeed
	oa.sec_desc	= &sd.sd;
dd89bb
	oa.sec_qos	= &sqo;;
dd89bb
dd89bb
	return __ntapi->zw_create_symbolic_link_object(
dd89bb
		hentry,
dd89bb
		desired_access,
dd89bb
		&oa,target_name);
dd89bb
}
dd89bb
661c27
int32_t __stdcall __ntapi_tt_open_ipc_object_directory(
661c27
	__out	void **			hdir,
661c27
	__in	uint32_t		desired_access,
661c27
	__in	const wchar16_t		prefix[6],
ae515f
	__in	const nt_guid *		guid)
661c27
{
661c27
	return __tt_create_ipc_object_directory(
661c27
		hdir,desired_access,
661c27
		prefix,guid);
661c27
}
661c27
661c27
int32_t __stdcall __ntapi_tt_create_ipc_object_directory_entry(
661c27
	__out	void **			hentry,
661c27
	__in	uint32_t		desired_access,
661c27
	__in	void *			hdir,
661c27
	__in	void *			htarget,
661c27
	__in	nt_unicode_string *	target_name,
661c27
	__in	uint32_t		key)
661c27
{
661c27
	return __tt_create_object_directory_entry(
661c27
		hentry,desired_access,
661c27
		hdir,htarget,target_name,key);
661c27
}
661c27
6729c8
int32_t __stdcall __ntapi_tt_open_dev_object_directory(
6729c8
	__out	void **			hdir,
6729c8
	__in	uint32_t		desired_access,
6729c8
	__in	const wchar16_t		prefix[6],
6729c8
	__in	const nt_guid *		ipc_guid)
6729c8
{
6729c8
	return __tt_create_ipc_object_directory(
6729c8
		hdir,desired_access,
6729c8
		prefix,ipc_guid);
6729c8
}
6729c8
6729c8
int32_t __stdcall __ntapi_tt_create_dev_object_directory_entry(
6729c8
	__out	void **			hentry,
6729c8
	__in	uint32_t		desired_access,
6729c8
	__in	void *			hdir,
6729c8
	__in	void *			htarget,
6729c8
	__in	nt_unicode_string *	target_name,
6729c8
	__in	const nt_guid *		dev_guid)
6729c8
{
6729c8
	int32_t			status;
6729c8
	nt_oa			oa;
6729c8
	nt_unicode_string	name;
6729c8
	nt_sd_common_buffer	sd;
6729c8
	nt_guid_str_utf16	guidstr;
6729c8
	uintptr_t		buffer[2048/sizeof(uintptr_t)];
6729c8
	nt_sqos			sqos = {
6729c8
					sizeof(sqos),
6729c8
					NT_SECURITY_IMPERSONATION,
6729c8
					NT_SECURITY_TRACKING_DYNAMIC,
6729c8
					1};
6729c8
6729c8
	if (!target_name) {
6729c8
		if ((status = __ntapi->zw_query_object(
6729c8
				htarget,
6729c8
				NT_OBJECT_NAME_INFORMATION,
6729c8
				buffer,sizeof(buffer),0)))
6729c8
			return status;
6729c8
		target_name = (nt_unicode_string *)buffer;
6729c8
	}
6729c8
6729c8
	__ipc_sd_init(&sd,0);
6729c8
	__ntapi->tt_guid_to_string_utf16(dev_guid,&guidstr);
6729c8
6729c8
	name.strlen = sizeof(guidstr);
6729c8
	name.maxlen = 0;
6729c8
	name.buffer = &guidstr.lbrace;
6729c8
6729c8
	oa.len		= sizeof(oa);
6729c8
	oa.root_dir	= hdir;
6729c8
	oa.obj_name	= &nam;;
6729c8
	oa.obj_attr	= 0;
6729c8
	oa.sec_desc	= &sd.sd;
6729c8
	oa.sec_qos	= &sqo;;
6729c8
6729c8
	return __ntapi->zw_create_symbolic_link_object(
6729c8
		hentry,
6729c8
		desired_access,
6729c8
		&oa,target_name);
6729c8
}
6729c8
dd89bb
int32_t __stdcall __ntapi_tt_create_keyed_object_directory(
dd89bb
	__out	void **			hdir,
dd89bb
	__in	uint32_t		desired_access,
d5e229
	__in	void *			hparent,
dd89bb
	__in	uint32_t		key)
dd89bb
{
dd89bb
	return __tt_create_keyed_object_directory(
dd89bb
		hdir,desired_access,
d5e229
		hparent,key,
dd89bb
		__ntapi->zw_create_directory_object);
dd89bb
}
dd89bb
dd89bb
int32_t __stdcall __ntapi_tt_open_keyed_object_directory(
dd89bb
	__out	void **			hdir,
dd89bb
	__in	uint32_t		desired_access,
d5e229
	__in	void *			hparent,
dd89bb
	__in	uint32_t		key)
dd89bb
{
dd89bb
	return __tt_create_keyed_object_directory(
dd89bb
		hdir,desired_access,
d5e229
		hparent,key,
dd89bb
		__ntapi->zw_open_directory_object);
dd89bb
}
661c27
661c27
int32_t __stdcall __ntapi_tt_create_keyed_object_directory_entry(
661c27
	__out	void **			hentry,
661c27
	__in	uint32_t		desired_access,
661c27
	__in	void *			hdir,
661c27
	__in	void *			htarget,
661c27
	__in	nt_unicode_string *	target_name,
661c27
	__in	uint32_t		key)
661c27
{
661c27
	return __tt_create_object_directory_entry(
661c27
		hentry,desired_access,
661c27
		hdir,htarget,target_name,key);
661c27
}
8ca63f
8ca63f
int32_t __stdcall __ntapi_tt_keyed_object_to_key(
8ca63f
	__in	void *			hentry,
8ca63f
	__out	uint32_t *		key,
8ca63f
	__out	void *			buffer,
8ca63f
	__in	size_t			buflen)
8ca63f
{
8ca63f
	int32_t			status;
8ca63f
	wchar16_t *		pidname;
8ca63f
	nt_unicode_string *	dirname;
8ca63f
8ca63f
	if ((status = __ntapi->zw_query_object(
8ca63f
			hentry,
8ca63f
			NT_OBJECT_NAME_INFORMATION,
8ca63f
			buffer,buflen,
8ca63f
			&(uint32_t){0})))
8ca63f
		return status;
8ca63f
8ca63f
	dirname = (nt_unicode_string *)buffer;
8ca63f
	pidname = dirname->buffer;
8ca63f
8ca63f
	if (dirname->strlen <= 8 * sizeof(wchar16_t))
8ca63f
		return NT_STATUS_INTERNAL_ERROR;
8ca63f
8ca63f
	pidname += dirname->strlen / sizeof(wchar16_t);
8ca63f
	pidname -= 8;
8ca63f
8ca63f
	if (pidname[-1] != '\\')
8ca63f
		return NT_STATUS_INVALID_PARAMETER;
8ca63f
8ca63f
	return __ntapi->tt_hex_utf16_to_uint32(
8ca63f
		pidname,key);
8ca63f
}