/***********************************************************/ /* ntux: native translation und extension */ /* Copyright (C) 2016--2018 Z. Gilboa */ /* 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" #define __SID_SYSTEM {1,1,{{0,0,0,0,0,5}},{18}} #define __SID_ADMINISTRATORS {1,2,{{0,0,0,0,0,5}},{32,544}} static const nt_sid sid_system = __SID_SYSTEM; static const nt_sid_os sid_admins = __SID_ADMINISTRATORS; static int ntux_cmd_chmod_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 nt_sid * ntux_cmd_chmod_sid_from_name(const char * name) { if (!strcmp(name,"Administrators")) return (nt_sid *)&sid_admins; else if (!strcmp(name,"SYSTEM")) return (nt_sid *)&sid_system; else return 0; } int ntux_cmd_chmod(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; nt_sd_common_buffer dstsd; nt_sd_common_meta meta; nt_sid * owner; nt_sid * group; uint32_t access_owner; uint32_t access_group; uint32_t access_other; uint32_t access_admin; uint32_t ace_flags; uint32_t sec_mask; size_t size; int fd = -1; struct __ofd * ofd = 0; void * hasync = 0; uint32_t buf[0x300]; /* ACE propagation: +p, -p */ if (!dctx->cctx->strmode) ace_flags = 0; else if (!strcmp(dctx->cctx->strmode,"+p")) ace_flags = NT_ACE_CONTAINER_INHERIT | NT_ACE_OBJECT_INHERIT; else if (!strcmp(dctx->cctx->strmode,"-p")) ace_flags = 0; else return ntux_cmd_chmod_ret( 0,0,0, NTUX_CUSTOM_ERROR( dctx, NTUX_ERR_FLEE_ERROR)); /* initial --owner and --group support: Administrators, SYSTEM */ owner = 0; group = 0; if (dctx->cctx->owner) if (!(owner = ntux_cmd_chmod_sid_from_name(dctx->cctx->owner))) return ntux_cmd_chmod_ret( 0,0,0, NTUX_CUSTOM_ERROR( dctx, NTUX_ERR_NOT_IMPLEMENTED)); if (dctx->cctx->group) if (!(group = ntux_cmd_chmod_sid_from_name(dctx->cctx->group))) return ntux_cmd_chmod_ret( 0,0,0, NTUX_CUSTOM_ERROR( dctx, NTUX_ERR_NOT_IMPLEMENTED)); /* 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_chmod_ret( 0,0,0, NTUX_SYSTEM_ERROR(dctx)); fd = ret; /* ofd */ if (!(ofd = __xfi_ofd_ref_inc(fd))) return ntux_cmd_chmod_ret( fd,0,0, NTUX_CUSTOM_ERROR( dctx, NTUX_ERR_FLOW_ERROR)); /* hasync */ sec_mask = NT_SEC_READ_CONTROL; sec_mask |= NT_SEC_WRITE_DAC; sec_mask |= owner ? NT_SEC_WRITE_OWNER : 0; if ((status = __xfi_fs_open_async( &hasync, ofd->info.hfile,0, sec_mask, NT_FILE_SHARE_READ | NT_FILE_SHARE_WRITE | NT_FILE_SHARE_DELETE))) if (ntux_errno_set(dctx,EACCES)) return ntux_cmd_chmod_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_chmod_ret( fd,ofd,hasync, NTUX_SYSTEM_ERROR(dctx)); if ((status = __xfi_acl_init_common_descriptor_meta( &meta,srcsd, NT_ACL_INIT_COMMON_DESCRIPTION_META_STRICT_MODE))) if (ntux_errno_set(dctx,EBADF)) return ntux_cmd_chmod_ret( fd,ofd,hasync, NTUX_SYSTEM_ERROR(dctx)); /* source permissions */ access_owner = meta.owner_ace ? meta.owner_ace->mask : 0; access_group = meta.group_ace ? meta.group_ace->mask : 0; access_other = meta.other_ace ? meta.other_ace->mask : 0; access_admin = meta.admin_ace ? meta.admin_ace->mask : 0; /* initial --strmode support, retaining previous options as needed */ if (!dctx->cctx->strmode) { ace_flags |= meta.owner_ace ? meta.owner_ace->header.ace_flags : 0; ace_flags |= meta.group_ace ? meta.group_ace->header.ace_flags : 0; ace_flags |= meta.other_ace ? meta.other_ace->header.ace_flags : 0; ace_flags |= meta.admin_ace ? meta.admin_ace->header.ace_flags : 0; } /* updated dacl */ __xfi_acl_init_common_descriptor( &dstsd, owner ? owner : meta.owner, group ? group : meta.group, 0,0, access_owner,access_group,access_other, access_admin,meta.system_acc, ace_flags); sec_mask = NT_DACL_SECURITY_INFORMATION; sec_mask |= owner ? NT_OWNER_SECURITY_INFORMATION : 0; if ((status = __xfi_set_security_object( hasync,sec_mask,&dstsd.sd))) if (ntux_errno_set(dctx,EPERM)) return ntux_cmd_chmod_ret( fd,ofd,hasync, NTUX_SYSTEM_ERROR(dctx)); /* changes */ (void)fdout; /* all done */ return ntux_cmd_chmod_ret(fd,ofd,hasync,0); }