-#endif
-
-int ntfs_inode_get_security(ntfs_inode *ni, u32 selection, char *buf,
- u32 buflen, u32 *psize)
-{
- char *attr;
- int res = 0;
-
- attr = getsecurityattr(ni->vol, ni);
- if (attr) {
- if (feedsecurityattr(attr,selection,
- buf,buflen,psize)) {
- if (test_nino_flag(ni, v3_Extensions)
- && ni->security_id)
- res = le32_to_cpu(
- ni->security_id);
- else
- res = -1;
- }
- free(attr);
- }
- return (res);
-}
-/*
- * Check the validity of the ACEs in a DACL or SACL
- */
-
-static BOOL valid_acl(const ACL *pacl, unsigned int end)
-{
- const ACCESS_ALLOWED_ACE *pace;
- unsigned int offace;
- unsigned int acecnt;
- unsigned int acesz;
- unsigned int nace;
- BOOL ok;
-
- ok = TRUE;
- acecnt = le16_to_cpu(pacl->ace_count);
- offace = sizeof(ACL);
- for (nace = 0; (nace < acecnt) && ok; nace++) {
- /* be sure the beginning is within range */
- if ((offace + sizeof(ACCESS_ALLOWED_ACE)) > end)
- ok = FALSE;
- else {
- pace = (const ACCESS_ALLOWED_ACE*)
- &((const char*)pacl)[offace];
- acesz = le16_to_cpu(pace->size);
- if (((offace + acesz) > end)
- || !ntfs_valid_sid(&pace->sid)
- || ((ntfs_sid_size(&pace->sid) + 8) != (int)acesz))
- ok = FALSE;
- offace += acesz;
- }
- }
- return (ok);
-}
-
-/*
- * 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_inode_set_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);
-}