-/*
- * Do sanity checks on security descriptors read from storage
- * basically, we make sure that every field holds within
- * allocated storage
- * Should not be called with a NULL argument
- * returns TRUE if considered safe
- * if not, error should be logged by caller
- */
-static BOOL _ntfs_valid_descr(const char *securattr, unsigned int attrsz)
-{
- const SECURITY_DESCRIPTOR_RELATIVE *phead;
- const ACL *pdacl;
- const ACL *psacl;
- unsigned int offdacl;
- unsigned int offsacl;
- unsigned int offowner;
- unsigned int offgroup;
- BOOL ok;
-
- ok = TRUE;
-
- /*
- * first check overall size if within allocation range
- * and a DACL is present
- * and owner and group SID are valid
- */
-
- phead = (const SECURITY_DESCRIPTOR_RELATIVE*)securattr;
- offdacl = le32_to_cpu(phead->dacl);
- offsacl = le32_to_cpu(phead->sacl);
- offowner = le32_to_cpu(phead->owner);
- offgroup = le32_to_cpu(phead->group);
- pdacl = (const ACL*)&securattr[offdacl];
- psacl = (const ACL*)&securattr[offsacl];
-
- /*
- * size check occurs before the above pointers are used
- *
- * "DR Watson" standard directory on WinXP has an
- * old revision and no DACL though SE_DACL_PRESENT is set
- */
- if ((attrsz >= sizeof(SECURITY_DESCRIPTOR_RELATIVE))
- && (phead->revision == SECURITY_DESCRIPTOR_REVISION)
- && (offowner >= sizeof(SECURITY_DESCRIPTOR_RELATIVE))
- && ((offowner + 2) < attrsz)
- && (offgroup >= sizeof(SECURITY_DESCRIPTOR_RELATIVE))
- && ((offgroup + 2) < attrsz)
- && (!offdacl
- || ((offdacl >= sizeof(SECURITY_DESCRIPTOR_RELATIVE))
- && (offdacl+sizeof(ACL) <= attrsz)))
- && (!offsacl
- || ((offsacl >= sizeof(SECURITY_DESCRIPTOR_RELATIVE))
- && (offsacl+sizeof(ACL) <= attrsz)))
- && !(phead->owner & const_cpu_to_le32(3))
- && !(phead->group & const_cpu_to_le32(3))
- && !(phead->dacl & const_cpu_to_le32(3))
- && !(phead->sacl & const_cpu_to_le32(3))
- && (ntfs_attr_size(securattr) <= attrsz)
- && ntfs_valid_sid((const SID*)&securattr[offowner])
- && ntfs_valid_sid((const SID*)&securattr[offgroup])
- /*
- * if there is an ACL, as indicated by offdacl,
- * require SE_DACL_PRESENT
- * but "Dr Watson" has SE_DACL_PRESENT though no DACL
- */
- && (!offdacl
- || ((phead->control & SE_DACL_PRESENT)
- && ((pdacl->revision == ACL_REVISION)
- || (pdacl->revision == ACL_REVISION_DS))))
- /* same for SACL */
- && (!offsacl
- || ((phead->control & SE_SACL_PRESENT)
- && ((psacl->revision == ACL_REVISION)
- || (psacl->revision == ACL_REVISION_DS))))) {
- /*
- * Check the DACL and SACL if present
- */
- if ((offdacl && !valid_acl(pdacl,attrsz - offdacl))
- || (offsacl && !valid_acl(psacl,attrsz - offsacl)))
- ok = FALSE;
- } else {
- ok = FALSE;
- }
- return (ok);
-}
-
-/*
- * Set security data on a NTFS file given an inode
- *
- * Returns nonzero on success
- */
-int _ntfs_set_file_security(ntfs_inode *ni, u32 selection,
- const char *attr)
-{
- const SECURITY_DESCRIPTOR_RELATIVE *phead;
- int attrsz;
- BOOL missing;
- char *oldattr;
- int res;
-
- res = 0; /* default return */
- phead = (const SECURITY_DESCRIPTOR_RELATIVE*)attr;
- attrsz = ntfs_attr_size(attr);
- /* if selected, owner and group must be present or defaulted */
- missing = ((selection & OWNER_SECURITY_INFORMATION)
- && !phead->owner
- && !(phead->control & SE_OWNER_DEFAULTED))
- || ((selection & GROUP_SECURITY_INFORMATION)
- && !phead->group
- && !(phead->control & SE_GROUP_DEFAULTED));
- if (!missing
- && (phead->control & SE_SELF_RELATIVE)
- && _ntfs_valid_descr(attr, attrsz)) {
- oldattr = getsecurityattr(ni->vol, ni);
- if (oldattr) {
- if (mergesecurityattr(
- ni->vol,
- oldattr, attr,
- selection, ni)) {
- if (test_nino_flag(ni,
- v3_Extensions))
- res = le32_to_cpu(
- ni->security_id);
- else
- res = -1;
- }
- free(oldattr);
- }
- } else
- errno = EINVAL;
- return (res);
-}
-
-
-#if 0