Blame src/acl/ntapi_acl_helper.c

60ddd3
/********************************************************/
60ddd3
/*  ntapi: Native API core library                      */
60ddd3
/*  Copyright (C) 2013--2017  Z. Gilboa                 */
60ddd3
/*  Released under GPLv2 and GPLv3; see COPYING.NTAPI.  */
60ddd3
/********************************************************/
60ddd3
60ddd3
#include <psxtypes/psxtypes.h>
60ddd3
#include <ntapi/nt_status.h>
60ddd3
#include <ntapi/nt_object.h>
60ddd3
#include <ntapi/nt_acl.h>
60ddd3
#include "ntapi_impl.h"
60ddd3
60ddd3
#define __SID_SYSTEM			{1,1,{{0,0,0,0,0,5}},{18}}
60ddd3
#define __SID_OWNER_RIGHTS		{1,1,{{0,0,0,0,0,3}},{4}}
60ddd3
#define __SID_AUTHENTICATED_USERS	{1,1,{{0,0,0,0,0,5}},{11}}
17fbe4
#define __SID_ADMINISTRATORS		{1,2,{{0,0,0,0,0,5}},{32,544}}
17fbe4
17fbe4
static const nt_sid    sid_system       = __SID_SYSTEM;
17fbe4
static const nt_sid    sid_owner_rights = __SID_OWNER_RIGHTS;
17fbe4
static const nt_sid    sid_auth_users   = __SID_AUTHENTICATED_USERS;
17fbe4
static const nt_sid_os sid_admins       = __SID_ADMINISTRATORS;
60ddd3
60ddd3
static nt_access_allowed_ace * __acl_ace_init(
60ddd3
	nt_access_allowed_ace * ace,
60ddd3
	uint32_t		mask,
60ddd3
	const nt_sid *		sid,
60ddd3
	uint16_t *		aces)
60ddd3
{
60ddd3
	if (mask == 0)
60ddd3
		return ace;
60ddd3
60ddd3
	ace->mask             = mask;
60ddd3
	ace->header.ace_type  = NT_ACE_TYPE_ACCESS_ALLOWED;
60ddd3
	ace->header.ace_flags = 0;
60ddd3
	ace->header.ace_size  = sizeof(uint32_t) * sid->sub_authority_count
60ddd3
	                        + __offsetof(nt_access_allowed_ace,sid_start)
60ddd3
	                        + __offsetof(nt_sid,sub_authority);
60ddd3
60ddd3
	__ntapi->tt_sid_copy(
60ddd3
		(nt_sid *)&ace->sid_start,
60ddd3
		sid);
60ddd3
60ddd3
	(*aces)++;
60ddd3
60ddd3
	return (nt_access_allowed_ace *)((size_t)ace + ace->header.ace_size);
60ddd3
}
60ddd3
60ddd3
void __stdcall __ntapi_acl_init_common_descriptor(
60ddd3
	__out	nt_sd_common_buffer *	sd,
60ddd3
	__in	const nt_sid *		owner,
60ddd3
	__in	const nt_sid *		group,
60ddd3
	__in	const nt_sid *		other,
17fbe4
	__in	const nt_sid *		admin,
60ddd3
	__in	uint32_t		owner_access,
60ddd3
	__in	uint32_t		group_access,
60ddd3
	__in	uint32_t		other_access,
17fbe4
	__in	uint32_t		admin_access,
60ddd3
	__in	uint32_t		system_access)
60ddd3
{
60ddd3
	nt_access_allowed_ace * ace;
60ddd3
	uint16_t                ace_count        = 0;
60ddd3
60ddd3
	/* sd header */
60ddd3
	sd->sd.revision         = 1;
60ddd3
	sd->sd.sbz_1st          = 0;
5c3887
	sd->sd.control          = NT_SE_SELF_RELATIVE | NT_SE_DACL_PRESENT | NT_SE_DACL_PROTECTED;
60ddd3
	sd->sd.offset_owner     = __offsetof(nt_sd_common_buffer,owner);
60ddd3
	sd->sd.offset_group     = 0;
60ddd3
	sd->sd.offset_dacl      = __offsetof(nt_sd_common_buffer,dacl);
60ddd3
	sd->sd.offset_sacl      = 0;
60ddd3
60ddd3
	/* owner, group, other: default sid's */
0a8487
	owner = owner ? owner : __ntapi_internals()->user;
808392
	group = group ? group : owner;
60ddd3
	other = other ? other : &sid_auth_users;
60ddd3
60ddd3
	/* owner sid */
60ddd3
	__ntapi->tt_sid_copy(
60ddd3
		(nt_sid *)&sd->owner,
60ddd3
		owner);
60ddd3
83fba2
	/* is the local system account both the owner and the group? */
83fba2
	if (!__ntapi->tt_sid_compare(owner,&sid_system))
83fba2
		if (!__ntapi->tt_sid_compare(group,&sid_system))
83fba2
				if (system_access == owner_access)
83fba2
					system_access = 0;
83fba2
60ddd3
	/* ace's */
60ddd3
	ace = (nt_access_allowed_ace *)&sd->buffer;
60ddd3
	ace = __acl_ace_init(ace,system_access,&sid_system,&ace_count);
808392
	ace = __acl_ace_init(ace,owner_access,&sid_owner_rights,&ace_count);
60ddd3
	ace = __acl_ace_init(ace,group_access,group,&ace_count);
60ddd3
	ace = __acl_ace_init(ace,other_access,other,&ace_count);
60ddd3
17fbe4
	if (admin_access) {
17fbe4
		admin = admin ? admin : (nt_sid *)&sid_admins;
17fbe4
		ace   = __acl_ace_init(ace,admin_access,admin,&ace_count);
17fbe4
	}
17fbe4
60ddd3
	/* dacl */
60ddd3
	sd->dacl.acl_revision   = 0x02;
60ddd3
	sd->dacl.sbz_1st        = 0;
60ddd3
	sd->dacl.acl_size       = (uint16_t)((char *)ace - (char *)&sd->dacl);
60ddd3
	sd->dacl.ace_count      = ace_count;
60ddd3
	sd->dacl.sbz_2nd        = 0;
60ddd3
}
32ec33
32ec33
static int32_t __acl_init_common_meta_impl(
32ec33
	__out	nt_sd_common_meta *	meta,
32ec33
	__in	nt_sd *			sd)
32ec33
{
32ec33
	int			i;
32ec33
	nt_sid *		sid;
32ec33
	nt_acl *		acl;
32ec33
	nt_access_allowed_ace *	ace;
ca4b1f
	nt_access_allowed_ace *	sysace;
ca4b1f
	nt_sid *		syssid;
32ec33
	unsigned char *		value;
32ec33
	unsigned char		sacnt;
32ec33
	char *			mark = (char *)sd;
32ec33
32ec33
	meta->sd    = sd;
32ec33
	meta->owner = sd->offset_owner ? (nt_sid *)(mark + sd->offset_owner) : 0;
32ec33
	meta->group = 0;
32ec33
	meta->dacl  = sd->offset_dacl  ? (nt_acl *)(mark + sd->offset_dacl) : 0;
32ec33
32ec33
	meta->owner_ace  = 0;
32ec33
	meta->owner_sid  = 0;
32ec33
	meta->group_ace  = 0;
32ec33
	meta->group_sid  = 0;
32ec33
	meta->other_ace  = 0;
32ec33
	meta->other_sid  = 0;
32ec33
	meta->admin_ace  = 0;
32ec33
	meta->admin_sid  = 0;
32ec33
	meta->system_acc = 0;
32ec33
32ec33
	if (!meta->owner)
32ec33
		return NT_STATUS_INVALID_OWNER;
32ec33
32ec33
	if (!(acl = meta->dacl))
32ec33
		return NT_STATUS_SUCCESS;
32ec33
32ec33
	if (acl->ace_count == 0)
32ec33
		return NT_STATUS_SUCCESS;
32ec33
32ec33
	if (acl->ace_count > 5)
32ec33
		return NT_STATUS_NOT_SUPPORTED;
32ec33
32ec33
	ace = (nt_access_allowed_ace *)&acl[1];
32ec33
32ec33
	for (i=0; i<acl->ace_count; i++) {
32ec33
		if (ace->header.ace_type != NT_ACE_TYPE_ACCESS_ALLOWED)
32ec33
			return NT_STATUS_NOT_SUPPORTED;
32ec33
32ec33
		mark = (char *)ace + ace->header.ace_size;
32ec33
		ace  = (nt_access_allowed_ace *)mark;
32ec33
	}
32ec33
32ec33
	ace = (nt_access_allowed_ace *)&acl[1];
32ec33
32ec33
	for (i=0; i<acl->ace_count; i++) {
32ec33
		sid   = (nt_sid *)&ace->sid_start;
32ec33
		value = sid->identifier_authority.value;
32ec33
ca4b1f
		if (!(__ntapi->tt_sid_compare(sid,&sid_system))) {
32ec33
			meta->system_acc = ace->mask;
32ec33
ca4b1f
			sysace = ace;
ca4b1f
			syssid = sid;
ca4b1f
ca4b1f
		} else if (!(__ntapi->tt_sid_compare(sid,&sid_owner_rights))) {
32ec33
			if (meta->owner_ace)
32ec33
				return NT_STATUS_INVALID_ACL;
32ec33
32ec33
			meta->owner_ace = ace;
32ec33
			meta->owner_sid = sid;
32ec33
		}
32ec33
32ec33
		else if (!(__ntapi->tt_sid_compare(sid,&sid_auth_users))) {
32ec33
			if (meta->other_ace)
32ec33
				return NT_STATUS_INVALID_ACL;
32ec33
32ec33
			meta->other_ace = ace;
32ec33
			meta->other_sid = sid;
32ec33
		}
32ec33
32ec33
		else if (!(__ntapi->tt_sid_compare(sid,meta->owner))) {
32ec33
			if (meta->group_ace)
32ec33
				return NT_STATUS_INVALID_ACL;
32ec33
32ec33
			meta->group_ace = ace;
32ec33
			meta->group_sid = sid;
32ec33
		}
32ec33
32ec33
		else if (!(__ntapi->tt_sid_compare(sid,(nt_sid *)&sid_admins))) {
32ec33
			if (meta->admin_ace)
32ec33
				return NT_STATUS_INVALID_ACL;
32ec33
32ec33
			meta->admin_ace = ace;
32ec33
			meta->admin_sid = sid;
32ec33
		}
32ec33
32ec33
		else if ((value[0] == 0) && (value[1] == 0)
32ec33
				&& (value[2] == 0) && (value[3] == 0)
32ec33
				&& (value[4] == 0) && (value[5] == 5)
32ec33
				&& (sid->sub_authority[0] == 21)
32ec33
				&& ((sacnt = sid->sub_authority_count))
32ec33
				&& (sid->sub_authority[sacnt - 1] == 500)) {
32ec33
			if (meta->admin_ace)
32ec33
				return NT_STATUS_INVALID_ACL;
32ec33
32ec33
			meta->admin_ace = ace;
32ec33
			meta->admin_sid = sid;
32ec33
		}
32ec33
32ec33
		else {
32ec33
			if (meta->group_ace)
32ec33
				return NT_STATUS_INVALID_ACL;
32ec33
32ec33
			meta->group_ace = ace;
32ec33
			meta->group_sid = sid;
32ec33
			meta->group     = sid;
32ec33
		}
32ec33
32ec33
		mark = (char *)ace + ace->header.ace_size;
32ec33
		ace  = (nt_access_allowed_ace *)mark;
32ec33
	}
32ec33
ca4b1f
	if (!meta->group_ace && meta->owner_ace) {
ca4b1f
		if (meta->owner_ace->mask != meta->system_acc) {
ca4b1f
			if (!__ntapi->tt_sid_compare(meta->owner,&sid_system)) {
ca4b1f
				meta->group_ace  = sysace;
ca4b1f
				meta->group_sid  = syssid;
ca4b1f
				meta->group      = syssid;
ca4b1f
				meta->system_acc = meta->owner_ace->mask;
ca4b1f
			}
ca4b1f
		}
ca4b1f
	}
ca4b1f
32ec33
	return NT_STATUS_SUCCESS;
32ec33
}
32ec33
32ec33
static int32_t __acl_init_common_meta_strict(
32ec33
	__out	nt_sd_common_meta *	meta,
32ec33
	__in	nt_sd *			sd)
32ec33
{
32ec33
	int32_t			status;
32ec33
	nt_sd_common_meta	m;
32ec33
32ec33
	if ((status = __acl_init_common_meta_impl(&m,sd)))
32ec33
		return status;
32ec33
32ec33
	meta->sd    = m.sd;
32ec33
	meta->owner = m.owner;
32ec33
	meta->group = m.group;
32ec33
	meta->dacl  = m.dacl;
32ec33
32ec33
	meta->owner_ace  = m.owner_ace;
32ec33
	meta->owner_sid  = m.owner_sid;
32ec33
	meta->group_ace  = m.group_ace;
32ec33
	meta->group_sid  = m.group_sid;
32ec33
	meta->other_ace  = m.other_ace;
32ec33
	meta->other_sid  = m.other_sid;
32ec33
	meta->admin_ace  = m.admin_ace;
32ec33
	meta->admin_sid  = m.admin_sid;
a39985
	meta->system_acc = m.system_acc;
32ec33
32ec33
	return NT_STATUS_SUCCESS;
32ec33
}
32ec33
32ec33
static int32_t __acl_init_common_meta_query(
32ec33
	__out	nt_sd_common_meta *	meta,
32ec33
	__in	nt_sd *			sd)
32ec33
{
32ec33
	__acl_init_common_meta_impl(meta,sd);
32ec33
	return NT_STATUS_SUCCESS;
32ec33
}
32ec33
32ec33
int32_t __stdcall __ntapi_acl_init_common_descriptor_meta(
32ec33
	__out	nt_sd_common_meta *	meta,
32ec33
	__in	nt_sd *			sd,
32ec33
	__in	uint32_t		options)
32ec33
{
32ec33
	switch (options) {
32ec33
		case NT_ACL_INIT_COMMON_DESCRIPTION_META_QUERY_MODE:
32ec33
			return __acl_init_common_meta_query(meta,sd);
32ec33
32ec33
		case NT_ACL_INIT_COMMON_DESCRIPTION_META_STRICT_MODE:
32ec33
			return __acl_init_common_meta_strict(meta,sd);
32ec33
32ec33
		default:
32ec33
			return NT_STATUS_INVALID_PARAMETER;
32ec33
	}
32ec33
}