diff --git a/include/ntux/ntux.h b/include/ntux/ntux.h index 817b5c8..3bd5d83 100644 --- a/include/ntux/ntux.h +++ b/include/ntux/ntux.h @@ -39,6 +39,8 @@ extern "C" { #define NTUX_DRIVER_ROOTED 0x0400 #define NTUX_DRIVER_ROOTLESS 0x0800 +#define NTUX_DRIVER_DUMP 0x1000 + #define NTUX_DRIVER_ANNOTATE_ALWAYS 0x10000000 #define NTUX_DRIVER_ANNOTATE_NEVER 0x20000000 #define NTUX_DRIVER_ANNOTATE_FULL 0x40000000 @@ -63,6 +65,7 @@ enum ntux_cmd { NTUX_CMD_SPAWN, NTUX_CMD_STRACE, NTUX_CMD_CHMOD, + NTUX_CMD_ACEIT, NTUX_CMD_CAP, }; @@ -138,6 +141,7 @@ ntux_api int ntux_get_driver_fdctx (const struct ntux_driver_ctx *, struct ntux_api int ntux_set_driver_fdctx (struct ntux_driver_ctx *, const struct ntux_fd_ctx *); /* cmd api */ +ntux_api int ntux_cmd_aceit (const struct ntux_driver_ctx *, const char *); ntux_api int ntux_cmd_chmod (const struct ntux_driver_ctx *, const char *); ntux_api int ntux_cmd_stat (const struct ntux_driver_ctx *, const char *); ntux_api int ntux_cmd_spawn (const struct ntux_driver_ctx *); diff --git a/project/common.mk b/project/common.mk index 651ec93..77a504a 100644 --- a/project/common.mk +++ b/project/common.mk @@ -6,6 +6,7 @@ INIT_SRCS = \ DRIVER_SRCS = \ src/driver/ntux_amain.c \ src/driver/ntux_driver_ctx.c \ + src/skin/ntux_skin_aceit.c \ src/skin/ntux_skin_chmod.c \ src/skin/ntux_skin_default.c \ src/skin/ntux_skin_spawn.c \ @@ -21,6 +22,7 @@ INTERNAL_SRCS = \ src/internal/ntux_strerr_impl.c \ CMD_SRCS = \ + src/cmds/ntux_cmd_aceit.c \ src/cmds/ntux_cmd_chmod.c \ src/cmds/ntux_cmd_spawn.c \ src/cmds/ntux_cmd_stat.c \ diff --git a/src/cmds/ntux_cmd_aceit.c b/src/cmds/ntux_cmd_aceit.c new file mode 100644 index 0000000..ed50e6e --- /dev/null +++ b/src/cmds/ntux_cmd_aceit.c @@ -0,0 +1,266 @@ +/***********************************************************/ +/* ntux: native translation und extension */ +/* Copyright (C) 2016--2022 SysDeer Technologies, LLC */ +/* Released under GPLv2 and GPLv3; see COPYING.NTUX. */ +/***********************************************************/ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#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; idxace_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; saidxsub_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); +} diff --git a/src/driver/ntux_amain.c b/src/driver/ntux_amain.c index 80489b3..dbf5039 100644 --- a/src/driver/ntux_amain.c +++ b/src/driver/ntux_amain.c @@ -60,6 +60,9 @@ static void ntux_perform_unit_actions( else if (dctx->cctx->cmd == NTUX_CMD_CHMOD) ntux_cmd_chmod(dctx,unit); + + else if (dctx->cctx->cmd == NTUX_CMD_ACEIT) + ntux_cmd_aceit(dctx,unit); } static int ntux_exit(struct ntux_driver_ctx * dctx, int ret) diff --git a/src/driver/ntux_driver_ctx.c b/src/driver/ntux_driver_ctx.c index c93852c..3edf1d2 100644 --- a/src/driver/ntux_driver_ctx.c +++ b/src/driver/ntux_driver_ctx.c @@ -34,6 +34,7 @@ static const char * const ntux_cmd_name[NTUX_CMD_CAP] = { [NTUX_CMD_SPAWN] = "spawn", [NTUX_CMD_STRACE] = "strace", [NTUX_CMD_CHMOD] = "chmod", + [NTUX_CMD_ACEIT] = "aceit", }; /* ntux command options */ @@ -43,6 +44,7 @@ static const struct argv_option * ntux_cmd_options[NTUX_CMD_CAP] = { [NTUX_CMD_SPAWN] = ntux_spawn_options, [NTUX_CMD_STRACE] = ntux_strace_options, [NTUX_CMD_CHMOD] = ntux_chmod_options, + [NTUX_CMD_ACEIT] = ntux_aceit_options, }; /* package info */ @@ -206,6 +208,9 @@ static int ntux_cctx_update( else if (!strcmp(entry->arg,"chmod")) cctx->cmd = NTUX_CMD_CHMOD; + else if (!strcmp(entry->arg,"aceit")) + cctx->cmd = NTUX_CMD_ACEIT; + break; case TAG_LOADER: @@ -249,6 +254,10 @@ static int ntux_cctx_update( cctx->drvflags &= ~(uint64_t)NTUX_DRIVER_ROOTED; cctx->drvflags |= NTUX_DRIVER_ROOTLESS; break; + + case TAG_DUMP: + cctx->drvflags |= NTUX_DRIVER_DUMP; + break; } } else { (*nunits)++; @@ -288,6 +297,8 @@ static int ntux_cmd_from_program(const char * program) return NTUX_CMD_STRACE; else if (!strcmp(mark,"chmod")) return NTUX_CMD_CHMOD; + else if (!strcmp(mark,"aceit")) + return NTUX_CMD_ACEIT; return NTUX_CMD_DEFAULT; } @@ -426,6 +437,9 @@ int ntux_get_driver_ctx( else if (cctx.cmd == NTUX_CMD_CHMOD) argv_optv_init(ntux_chmod_options,optv); + else if (cctx.cmd == NTUX_CMD_ACEIT) + argv_optv_init(ntux_aceit_options,optv); + /* spawn, strace */ if ((cctx.cmd == NTUX_CMD_SPAWN) || (cctx.cmd == NTUX_CMD_STRACE)) { argv_scan(argv,optv,&ctx,0); diff --git a/src/internal/ntux_driver_impl.h b/src/internal/ntux_driver_impl.h index 6a7e070..cdc8bd3 100644 --- a/src/internal/ntux_driver_impl.h +++ b/src/internal/ntux_driver_impl.h @@ -18,6 +18,7 @@ extern const struct argv_option ntux_default_options[]; extern const struct argv_option ntux_spawn_options[]; extern const struct argv_option ntux_strace_options[]; extern const struct argv_option ntux_chmod_options[]; +extern const struct argv_option ntux_aceit_options[]; enum app_tags { TAG_HELP, @@ -35,6 +36,7 @@ enum app_tags { TAG_GROUP, TAG_ROOTED, TAG_ROOTLESS, + TAG_DUMP, }; struct ntux_driver_ctx_impl { diff --git a/src/skin/ntux_skin_aceit.c b/src/skin/ntux_skin_aceit.c new file mode 100644 index 0000000..c156131 --- /dev/null +++ b/src/skin/ntux_skin_aceit.c @@ -0,0 +1,16 @@ +#include "ntux_driver_impl.h" +#include "argv/argv.h" + +const struct argv_option ntux_aceit_options[] = { + {"version", 'v',TAG_VERSION,ARGV_OPTARG_NONE,0,0,0, + "show version information"}, + + {"help", 'h',TAG_HELP,ARGV_OPTARG_OPTIONAL,0,"short|long",0, + "show usage information [listing %s options only]"}, + + {"dump", 'd',TAG_DUMP,ARGV_OPTARG_NONE,0,0,0, + "print all entries of the (virtual) file's " + "security descriptor"}, + + {0,0,0,0,0,0,0,0} +}; diff --git a/src/skin/ntux_skin_default.c b/src/skin/ntux_skin_default.c index f79f008..389321e 100644 --- a/src/skin/ntux_skin_default.c +++ b/src/skin/ntux_skin_default.c @@ -8,7 +8,8 @@ const struct argv_option ntux_default_options[] = { {"help", 'h',TAG_HELP,ARGV_OPTARG_OPTIONAL,0,"short|long",0, "show usage information [listing %s options only]"}, - {"cmd", 0,TAG_CMD,ARGV_OPTARG_REQUIRED,0,"stat|spawn|strace|chmod",0, + {"cmd", 0,TAG_CMD,ARGV_OPTARG_REQUIRED,0, + "stat|spawn|strace|chmod|aceit",0, "invoke one of the following ntux commands: %s"}, {0,0,0,0,0,0,0,0}