/* * smb_fsacl_from_vsa * * Converts given vsecattr_t structure to a acl_t structure. * * The allocated memory for retuned acl_t should be freed by * calling acl_free(). */ acl_t * smb_fsacl_from_vsa(vsecattr_t *vsecattr, acl_type_t acl_type) { int aclbsize = 0; /* size of acl list in bytes */ int dfaclbsize = 0; /* size of default acl list in bytes */ int numacls; acl_t *acl_info; ASSERT(vsecattr); acl_info = acl_alloc(acl_type); if (acl_info == NULL) return (NULL); acl_info->acl_flags = 0; switch (acl_type) { case ACLENT_T: numacls = vsecattr->vsa_aclcnt + vsecattr->vsa_dfaclcnt; aclbsize = vsecattr->vsa_aclcnt * sizeof (aclent_t); dfaclbsize = vsecattr->vsa_dfaclcnt * sizeof (aclent_t); acl_info->acl_cnt = numacls; acl_info->acl_aclp = kmem_alloc(aclbsize + dfaclbsize, KM_SLEEP); (void) memcpy(acl_info->acl_aclp, vsecattr->vsa_aclentp, aclbsize); (void) memcpy((char *)acl_info->acl_aclp + aclbsize, vsecattr->vsa_dfaclentp, dfaclbsize); if (acl_info->acl_cnt <= MIN_ACL_ENTRIES) acl_info->acl_flags |= ACL_IS_TRIVIAL; break; case ACE_T: aclbsize = vsecattr->vsa_aclcnt * sizeof (ace_t); acl_info->acl_cnt = vsecattr->vsa_aclcnt; acl_info->acl_flags = vsecattr->vsa_aclflags; acl_info->acl_aclp = kmem_alloc(aclbsize, KM_SLEEP); (void) memcpy(acl_info->acl_aclp, vsecattr->vsa_aclentp, aclbsize); if (ace_trivial(acl_info->acl_aclp, acl_info->acl_cnt) == 0) acl_info->acl_flags |= ACL_IS_TRIVIAL; break; default: acl_free(acl_info); return (NULL); } if (aclbsize && vsecattr->vsa_aclentp) kmem_free(vsecattr->vsa_aclentp, aclbsize); if (dfaclbsize && vsecattr->vsa_dfaclentp) kmem_free(vsecattr->vsa_dfaclentp, dfaclbsize); return (acl_info); }
/* * Determine whether a file has a trivial ACL * returns: 0 = trivial * 1 = nontrivial * <0 some other system failure, such as ENOENT or EPERM */ int acl_trivial(const char *filename) { int acl_flavor; int aclcnt; int cntcmd; int val = 0; ace_t *acep; acl_flavor = pathconf(filename, _PC_ACL_ENABLED); if (acl_flavor == _ACL_ACE_ENABLED) cntcmd = ACE_GETACLCNT; else cntcmd = GETACLCNT; aclcnt = acl(filename, cntcmd, 0, NULL); if (aclcnt > 0) { if (acl_flavor == _ACL_ACE_ENABLED) { acep = malloc(sizeof (ace_t) * aclcnt); if (acep == NULL) return (-1); if (acl(filename, ACE_GETACL, aclcnt, acep) < 0) { free(acep); return (-1); } val = ace_trivial(acep, aclcnt); free(acep); } else if (aclcnt > MIN_ACL_ENTRIES) val = 1; } return (val); }
static int cacl_get(acl_inp inp, int get_flag, int type, acl_t **aclp) { const char *fname; int fd; int ace_acl = 0; int error; int getcmd, cntcmd; acl_t *acl_info; int save_errno; int stat_error; struct stat64 statbuf; *aclp = NULL; if (type == ACL_PATH) { fname = inp.file; ace_acl = pathconf(fname, _PC_ACL_ENABLED); } else { fd = inp.fd; ace_acl = fpathconf(fd, _PC_ACL_ENABLED); } /* * if acl's aren't supported then * send it through the old GETACL interface */ if (ace_acl == 0 || ace_acl == -1) { ace_acl = _ACL_ACLENT_ENABLED; } if (ace_acl & _ACL_ACE_ENABLED) { cntcmd = ACE_GETACLCNT; getcmd = ACE_GETACL; acl_info = acl_alloc(ACE_T); } else { cntcmd = GETACLCNT; getcmd = GETACL; acl_info = acl_alloc(ACLENT_T); } if (acl_info == NULL) return (-1); if (type == ACL_PATH) { acl_info->acl_cnt = acl(fname, cntcmd, 0, NULL); } else { acl_info->acl_cnt = facl(fd, cntcmd, 0, NULL); } save_errno = errno; if (acl_info->acl_cnt < 0) { acl_free(acl_info); errno = save_errno; return (-1); } if (acl_info->acl_cnt == 0) { acl_free(acl_info); errno = save_errno; return (0); } acl_info->acl_aclp = malloc(acl_info->acl_cnt * acl_info->acl_entry_size); save_errno = errno; if (acl_info->acl_aclp == NULL) { acl_free(acl_info); errno = save_errno; return (-1); } if (type == ACL_PATH) { stat_error = stat64(fname, &statbuf); error = acl(fname, getcmd, acl_info->acl_cnt, acl_info->acl_aclp); } else { stat_error = fstat64(fd, &statbuf); error = facl(fd, getcmd, acl_info->acl_cnt, acl_info->acl_aclp); } save_errno = errno; if (error == -1) { acl_free(acl_info); errno = save_errno; return (-1); } if (stat_error == 0) { acl_info->acl_flags = (S_ISDIR(statbuf.st_mode) ? ACL_IS_DIR : 0); } else acl_info->acl_flags = 0; switch (acl_info->acl_type) { case ACLENT_T: if (acl_info->acl_cnt <= MIN_ACL_ENTRIES) acl_info->acl_flags |= ACL_IS_TRIVIAL; break; case ACE_T: if (ace_trivial(acl_info->acl_aclp, acl_info->acl_cnt) == 0) acl_info->acl_flags |= ACL_IS_TRIVIAL; break; default: errno = EINVAL; acl_free(acl_info); return (-1); } if ((acl_info->acl_flags & ACL_IS_TRIVIAL) && (get_flag & ACL_NO_TRIVIAL)) { acl_free(acl_info); errno = 0; return (0); } *aclp = acl_info; return (0); }