Blob Blame History Raw
/***********************************************************/
/*  ntux: native translation und extension                 */
/*  Copyright (C) 2016--2022  SysDeer Technologies, LLC    */
/*  Released under GPLv2 and GPLv3; see COPYING.NTUX.      */
/***********************************************************/

#include <psxabi/sys_sysapi.h>
#include <psxabi/sys_stat.h>
#include <psxabi/sys_errno.h>

#include <psxxfi/xfi_base.h>
#include <psxxfi/xfi_acl.h>
#include <psxxfi/xfi_fs.h>
#include <psxxfi/xfi_ofd.h>
#include <psxxfi/xfi_unicode.h>

#include <ntapi/nt_object.h>
#include <ntapi/nt_acl.h>
#include <ntapi/nt_file.h>

#include <ntux/ntux.h>
#include "ntux_driver_impl.h"
#include "ntux_nolibc_impl.h"
#include "ntux_errinfo_impl.h"


struct ntux_ace_any {
        nt_ace_header   header;
        uint32_t        mask;
        uint32_t        sid_start;
};


struct ntux_sid_any {
        unsigned char                   revision;
        unsigned char                   sub_authority_count;
        nt_sid_identifier_authority     identifier_authority;
        uint32_t                        sub_authority[];
};


static int ntux_cmd_aceit_ret(int fd, struct __ofd * ofd, void * hasync, int ret)
{
	if (hasync)
		__xfi_close_handle(hasync);

	if (ofd)
		__xfi_ofd_ref_dec(ofd);

	if (fd >= 0)
		__sys_close(fd);

	return ret;
}


static int ntux_cmd_aceit_dump_acl(nt_acl * acl, const char * acldesc, int fdout)
{
	int                     idx;
	int                     saidx;
	size_t                  addr;
	struct ntux_sid_any *   sid;
	struct ntux_ace_any *   ace;
	char                    comma[2];

	ntux_dprintf(
		fdout,
		"  ::sd::%s = {\n"
		"    .revision = 0x%x,\n"
		"    .sbz_1st = 0x%x,\n"
		"    .acl_size = 0x%x,\n"
		"    .ace_count = 0x%x,\n"
		"    .sbz_2nd = 0x%x\n",
		acldesc,
		acl->acl_revision,
		acl->sbz_1st,
		acl->acl_size,
		acl->ace_count,
		acl->sbz_2nd);

	addr  = (size_t)acl;
	addr += sizeof(*acl);

	for (idx=0; idx<acl->ace_count; idx++) {
		ace = (struct ntux_ace_any *)addr;

		ntux_dprintf(
			fdout,
			"    ::sd::%s::ace[%d] = {\n"
			"      .ace_type = 0x%x,\n"
			"      .ace_flags = 0x%x,\n"
			"      .ace_size = 0x%x,\n"
			"      .mask = 0x%x,\n",
			acldesc,idx,
			ace->header.ace_type,
			ace->header.ace_flags,
			ace->header.ace_size,
			ace->mask);

		sid = (struct ntux_sid_any *)&ace->sid_start;

		ntux_dprintf(fdout,
		"      .sid = {\n"
		"        .revision = 0x%x,\n"
		"        .sub_authority_count = 0x%x,\n"
		"        .identifier_authority = {%u,%u,%u,%u,%u,%u}\n"
		"        .sub_authority = {",
		sid->revision,
		sid->sub_authority_count,
		sid->identifier_authority.value[0],
		sid->identifier_authority.value[1],
		sid->identifier_authority.value[2],
		sid->identifier_authority.value[3],
		sid->identifier_authority.value[4],
		sid->identifier_authority.value[5]);

		comma[0] = '\0';
		comma[1] = 0;

		for (saidx=0; saidx<sid->sub_authority_count; saidx++) {
			ntux_dprintf(fdout,"%s%u",comma,sid->sub_authority[saidx]);
			comma[0] = ',';
		}

		ntux_dprintf(fdout,"}\n");
		ntux_dprintf(fdout,"      }\n");
		ntux_dprintf(fdout,"    }\n");

		addr += ace->header.ace_size;
	}

	ntux_dprintf(fdout,"  }\n");

(void)saidx;
	return 0;
}


static int ntux_cmd_aceit_dump(const char * dunit, nt_sd * sd, int fdout)
{
	int             ret;
	size_t          addr;
	nt_acl *        sacl;
	nt_acl *        dacl;

	ntux_dprintf(
		fdout,
		"%s::sd = {\n"
		"  .revision = 0x%x,\n"
		"  .sbz_1st = 0x%x,\n"
		"  .control = 0x%x,\n"
		"  .offset_owner = 0x%x,\n"
		"  .offset_group = 0x%x,\n"
		"  .offset_sacl = 0x%x,\n"
		"  .offset_dacl = 0x%x\n",
		dunit,
		sd->revision,
		sd->sbz_1st,
		sd->control,
		sd->offset_owner,
		sd->offset_group,
		sd->offset_sacl,
		sd->offset_dacl);

	if (sd->offset_sacl) {
		addr  = (size_t)sd;
		addr += sd->offset_sacl;
		sacl  = (nt_acl *)addr;

		if ((ret = ntux_cmd_aceit_dump_acl(sacl,"sacl",fdout)))
			return ret;
	}

	if (sd->offset_dacl) {
		addr  = (size_t)sd;
		addr += sd->offset_dacl;
		dacl  = (nt_acl *)addr;

		if ((ret = ntux_cmd_aceit_dump_acl(dacl,"dacl",fdout)))
			return ret;
	}

	ntux_dprintf(fdout,"}\n");

	return 0;
}


int ntux_cmd_aceit(const struct ntux_driver_ctx * dctx, const char * dunit)
{
	intptr_t		ret;
	int32_t			status;
	int			fdout;
	int			fdcwd;
	const unsigned char *	unit;
	nt_sd *			srcsd;
	size_t			size;
	int			fd      = -1;
	struct __ofd *		ofd     = 0;
	void *			hasync  = 0;
	uint32_t		buf[0x300];

	/* init */
	ntux_driver_set_ectx(
		dctx,0,dunit);

	unit = (const unsigned char *)dunit;

	/* fdctx */
	fdout = ntux_driver_fdout(dctx);
	fdcwd = ntux_driver_fdcwd(dctx);

	/* fd */
	if ((ret = __sys_openat(fdcwd,unit,0,0)) < 0)
		if (ntux_errno_set(dctx,ret))
			return ntux_cmd_aceit_ret(
				0,0,0,
				NTUX_SYSTEM_ERROR(dctx));

	fd = ret;

	/* ofd */
	if (!(ofd = __xfi_ofd_ref_inc(fd)))
		return ntux_cmd_aceit_ret(
			fd,0,0,
			NTUX_CUSTOM_ERROR(
				dctx,
				NTUX_ERR_FLOW_ERROR));

	/* hasync */
	if ((status = __xfi_fs_open_async(
			&hasync,
			ofd->info.hfile,0,
			NT_SEC_READ_CONTROL,
			NT_FILE_SHARE_READ
				| NT_FILE_SHARE_WRITE
				| NT_FILE_SHARE_DELETE)))
		if (ntux_errno_set(dctx,EACCES))
			return ntux_cmd_aceit_ret(
				fd,ofd,0,
				NTUX_SYSTEM_ERROR(dctx));

	/* srcsd */
	srcsd = (nt_sd *)buf;

	if ((status = __xfi_query_security_object(
			hasync,
			NT_OWNER_SECURITY_INFORMATION
				| NT_GROUP_SECURITY_INFORMATION
				| NT_DACL_SECURITY_INFORMATION,
			srcsd,sizeof(buf),&size)))
		if (ntux_errno_set(dctx,ENXIO))
			return ntux_cmd_aceit_ret(
				fd,ofd,hasync,
				NTUX_SYSTEM_ERROR(dctx));

	/* dump */
	if (dctx->cctx->drvflags & NTUX_DRIVER_DUMP)
		if ((ntux_cmd_aceit_dump(dunit,srcsd,fdout)))
			return ntux_cmd_aceit_ret(
				fd,ofd,hasync,
				NTUX_SYSTEM_ERROR(dctx));

	/* all done */
	return ntux_cmd_aceit_ret(fd,ofd,hasync,0);
}