#include <sys/types.h>
#include <sys/acl.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <uuid/uuid.h>
#if 1
#include <string.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#endif
static int chmodx_syscall(void *obj, uid_t fsowner, gid_t fsgrp, int mode, kauth_filesec_t fsacl);
static int fchmodx_syscall(void *obj, uid_t fsowner, gid_t fsgrp, int mode, kauth_filesec_t fsacl);
static int chmodx1(void *obj,
int (* chmod_syscall)(void *obj, uid_t fsowner, gid_t fsgrp, int mode,
kauth_filesec_t fsacl),
filesec_t fsec);
int
chmodx_np(const char *path, filesec_t fsec)
{
return(chmodx1((void *)&path, chmodx_syscall, fsec));
}
int
fchmodx_np(int fd, filesec_t fsec)
{
return(chmodx1((void *)&fd, fchmodx_syscall, fsec));
}
extern int __chmod_extended(char *, uid_t, gid_t, int, kauth_filesec_t);
extern int __fchmod_extended(int, uid_t, gid_t, int, kauth_filesec_t);
static int
chmodx_syscall(void *obj, uid_t fsowner, gid_t fsgrp, int mode, kauth_filesec_t fsacl)
{
char *path = *(char **)obj;
return(__chmod_extended(path, fsowner, fsgrp, mode, fsacl));
}
static int
fchmodx_syscall(void *obj, uid_t fsowner, gid_t fsgrp, int mode, kauth_filesec_t fsacl)
{
int fd = *(int *)obj;
return(__fchmod_extended(fd, fsowner, fsgrp, mode, fsacl));
}
static int
chmodx1(void *obj,
int (chmod_syscall)(void *obj, uid_t fsowner, gid_t fsgrp, int mode, kauth_filesec_t fsacl),
filesec_t fsec)
{
uid_t fsowner = KAUTH_UID_NONE;
gid_t fsgrp = KAUTH_GID_NONE;
mode_t fsec_mode;
int fsmode = -1;
size_t size = 0;
int fsacl_used = 0;
int delete_acl = 0;
kauth_filesec_t fsacl = KAUTH_FILESEC_NONE;
struct kauth_filesec static_filesec;
if (fsec == NULL) {
errno = EINVAL;
return(-1);
}
if ((filesec_get_property(fsec, FILESEC_OWNER, &fsowner) != 0) && (errno != ENOENT))
return(-1);
if ((filesec_get_property(fsec, FILESEC_GROUP, &fsgrp) != 0) && (errno != ENOENT))
return(-1);
if ((filesec_get_property(fsec, FILESEC_MODE, &fsec_mode)) != 0) {
if (errno != ENOENT)
return(-1);
} else {
fsmode = fsec_mode;
}
if (((filesec_get_property(fsec, FILESEC_ACL_RAW, &fsacl) != 0) ||
(filesec_get_property(fsec, FILESEC_ACL_ALLOCSIZE, &size) != 0)) &&
(errno != ENOENT))
return(-1);
if (fsacl == _FILESEC_REMOVE_ACL) {
delete_acl = 1;
fsacl = 0;
}
if (fsacl == KAUTH_FILESEC_NONE) {
bzero(&static_filesec, sizeof(static_filesec));
fsacl = &static_filesec;
fsacl->fsec_magic = KAUTH_FILESEC_MAGIC;
fsacl->fsec_entrycount = KAUTH_FILESEC_NOACL;
} else {
fsacl_used = 1;
}
if (filesec_get_property(fsec, FILESEC_UUID, &fsacl->fsec_owner) != 0) {
if (errno != ENOENT)
return(-1);
bzero(&fsacl->fsec_owner, sizeof(fsacl->fsec_owner));
} else {
fsacl_used = 1;
}
if (filesec_get_property(fsec, FILESEC_GRPUUID, &fsacl->fsec_group) != 0) {
if (errno != ENOENT)
return(-1);
bzero(&fsacl->fsec_group, sizeof(fsacl->fsec_group));
} else {
fsacl_used = 1;
}
if (!fsacl_used) {
if (delete_acl) {
fsacl = _FILESEC_REMOVE_ACL;
} else {
fsacl = KAUTH_FILESEC_NONE;
}
}
return(chmod_syscall(obj, fsowner, fsgrp, fsmode, fsacl));
}