static boolean_t smb_ace_isvalid(smb_ace_t *ace, int which_acl) { uint16_t min_len; min_len = sizeof (smb_acehdr_t); if (ace->se_hdr.se_bsize < min_len) return (B_FALSE); if (smb_ace_is_access(ace->se_hdr.se_type) && (which_acl != SMB_DACL_SECINFO)) return (B_FALSE); if (smb_ace_is_audit(ace->se_hdr.se_type) && (which_acl != SMB_SACL_SECINFO)) return (B_FALSE); if (smb_ace_is_generic(ace->se_hdr.se_type)) { if (!smb_sid_isvalid(ace->se_sid)) return (B_FALSE); min_len += sizeof (ace->se_mask); min_len += smb_sid_len(ace->se_sid); if (ace->se_hdr.se_bsize < min_len) return (B_FALSE); } /* * object-specific ACE validation will be added later. */ return (B_TRUE); }
/* * smb_sid_split * * Take a full sid and split it into a domain sid and a relative id (rid). * The domain SID is allocated and a pointer to it will be returned. The * RID value is passed back in 'rid' arg if it's not NULL. The allocated * memory for the domain SID must be freed by caller. */ smb_sid_t * smb_sid_split(smb_sid_t *sid, uint32_t *rid) { smb_sid_t *domsid; int size; if (!smb_sid_isvalid(sid) || (sid->sid_subauthcnt == 0)) return (NULL); /* * We will reduce sid_subauthcnt by one, because * the domain SID does not include the RID. */ size = smb_sid_len(sid) - sizeof (uint32_t); if ((domsid = smb_sid_alloc(size)) == NULL) return (NULL); bcopy(sid, domsid, size); domsid->sid_subauthcnt = sid->sid_subauthcnt - 1; if (rid) *rid = sid->sid_subauth[sid->sid_subauthcnt - 1]; return (domsid); }
/* * smb_sid_getrid * * Return the Relative Id (RID) of the specified SID. It is the * caller's responsibility to ensure that this is an appropriate SID. * All we do here is return the last sub-authority from the SID. */ int smb_sid_getrid(smb_sid_t *sid, uint32_t *rid) { if (!smb_sid_isvalid(sid) || (rid == NULL) || (sid->sid_subauthcnt == 0)) return (-1); *rid = sid->sid_subauth[sid->sid_subauthcnt - 1]; return (0); }
uint32_t lsa_lookup_sid(smb_sid_t *sid, smb_account_t *info) { uint32_t status; if (!smb_sid_isvalid(sid)) return (NT_STATUS_INVALID_SID); status = lsa_lookup_sid_builtin(sid, info); if (status == NT_STATUS_NOT_FOUND) { status = smb_sam_lookup_sid(sid, info); if (status == NT_STATUS_NOT_FOUND) status = lsa_lookup_sid_domain(sid, info); } return ((status == NT_STATUS_SUCCESS) ? status : NT_STATUS_NONE_MAPPED); }
/* * smb_sid_split * * Take a full sid and split it into a domain sid and a relative id (rid). * The domain SID is allocated and a pointer to it will be returned. The * RID value is passed back in 'rid' arg if it's not NULL. The allocated * memory for the domain SID must be freed by caller. */ smb_sid_t * smb_sid_split(smb_sid_t *sid, uint32_t *rid) { smb_sid_t *domsid; if (!smb_sid_isvalid(sid) || (sid->sid_subauthcnt == 0)) return (NULL); if ((domsid = smb_sid_dup(sid)) == NULL) return (NULL); --domsid->sid_subauthcnt; if (rid) *rid = domsid->sid_subauth[domsid->sid_subauthcnt]; return (domsid); }
/* * smb_sd_tofs * * Creates a filesystem security structure based on the given * Windows security descriptor. */ uint32_t smb_sd_tofs(smb_sd_t *sd, smb_fssd_t *fs_sd) { smb_sid_t *sid; uint32_t status = NT_STATUS_SUCCESS; uint16_t sd_control; idmap_stat idm_stat; int idtype; int flags = 0; sd_control = sd->sd_control; /* * ZFS only has one set of flags so for now only * Windows DACL flags are taken into account. */ if (sd_control & SE_DACL_DEFAULTED) flags |= ACL_DEFAULTED; if (sd_control & SE_DACL_AUTO_INHERITED) flags |= ACL_AUTO_INHERIT; if (sd_control & SE_DACL_PROTECTED) flags |= ACL_PROTECTED; if (fs_sd->sd_flags & SMB_FSSD_FLAGS_DIR) flags |= ACL_IS_DIR; /* Owner */ if (fs_sd->sd_secinfo & SMB_OWNER_SECINFO) { sid = sd->sd_owner; if (!smb_sid_isvalid(sid)) return (NT_STATUS_INVALID_SID); idtype = SMB_IDMAP_USER; idm_stat = smb_idmap_getid(sid, &fs_sd->sd_uid, &idtype); if (idm_stat != IDMAP_SUCCESS) { return (NT_STATUS_NONE_MAPPED); } } /* Group */ if (fs_sd->sd_secinfo & SMB_GROUP_SECINFO) { sid = sd->sd_group; if (!smb_sid_isvalid(sid)) return (NT_STATUS_INVALID_SID); idtype = SMB_IDMAP_GROUP; idm_stat = smb_idmap_getid(sid, &fs_sd->sd_gid, &idtype); if (idm_stat != IDMAP_SUCCESS) { return (NT_STATUS_NONE_MAPPED); } } /* DACL */ if (fs_sd->sd_secinfo & SMB_DACL_SECINFO) { if (sd->sd_control & SE_DACL_PRESENT) { status = smb_acl_to_zfs(sd->sd_dacl, flags, SMB_DACL_SECINFO, &fs_sd->sd_zdacl); if (status != NT_STATUS_SUCCESS) return (status); } else return (NT_STATUS_INVALID_ACL); } /* SACL */ if (fs_sd->sd_secinfo & SMB_SACL_SECINFO) { if (sd->sd_control & SE_SACL_PRESENT) { status = smb_acl_to_zfs(sd->sd_sacl, flags, SMB_SACL_SECINFO, &fs_sd->sd_zsacl); if (status != NT_STATUS_SUCCESS) { return (status); } } else { return (NT_STATUS_INVALID_ACL); } } return (status); }