X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=src%2Fntfs-3g_security.c;h=7c8dec3c504db8dace198cadd1c1afc19bc36ed5;hp=83b92ed99a247ca762d4804e90adc56e972389c9;hb=c41828c58a5f6b8d9df56b0832c598767639f1cb;hpb=902a8bb8de242de08b29b995b69ae3e2a3495f6f diff --git a/src/ntfs-3g_security.c b/src/ntfs-3g_security.c index 83b92ed9..7c8dec3c 100644 --- a/src/ntfs-3g_security.c +++ b/src/ntfs-3g_security.c @@ -22,19 +22,19 @@ * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "util.h" - #ifdef HAVE_CONFIG_H #include "config.h" #endif +#ifdef ENABLE_XATTR +#define HAVE_SETXATTR +#endif + +#include + #include -#ifdef HAVE_STDLIB_H #include -#endif -#ifdef HAVE_STRING_H #include -#endif #include #include #ifdef HAVE_SETXATTR @@ -44,8 +44,6 @@ #include #endif -#include - #include #include #include @@ -4125,6 +4123,77 @@ int ntfs_get_ntfs_attrib(ntfs_inode *ni, char *value, size_t size) return (outsize ? (int)outsize : -errno); } +/* + * Get the ntfs attributes from an inode + * The attributes are returned according to cpu endianness + * + * Returns the attributes if successful (cannot be zero) + * 0 if failed (errno to tell why) + */ + +u32 ntfs_get_inode_attributes(ntfs_inode *ni) +{ + u32 attrib = -1; + + if (ni) { + attrib = le32_to_cpu(ni->flags); + if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) + attrib |= const_le32_to_cpu(FILE_ATTR_DIRECTORY); + else + attrib &= ~const_le32_to_cpu(FILE_ATTR_DIRECTORY); + if (!attrib) + attrib |= const_le32_to_cpu(FILE_ATTR_NORMAL); + } else + errno = EINVAL; + return (attrib); +} + +/* + * Set the ntfs attributes on an inode + * The attribute is expected according to cpu endianness + * + * Returns 0 if successful + * -1 if failed (errno to tell why) + */ + +int ntfs_set_inode_attributes(ntfs_inode *ni, u32 attrib) +{ + le32 settable; + ATTR_FLAGS dirflags; + int res; + + res = -1; + if (ni) { + settable = FILE_ATTR_SETTABLE; + res = 0; + if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) { + /* + * Accept changing compression for a directory + * and set index root accordingly + */ + settable |= FILE_ATTR_COMPRESSED; + if ((ni->flags ^ cpu_to_le32(attrib)) + & FILE_ATTR_COMPRESSED) { + if (ni->flags & FILE_ATTR_COMPRESSED) + dirflags = const_cpu_to_le16(0); + else + dirflags = ATTR_IS_COMPRESSED; + res = ntfs_attr_set_flags(ni, AT_INDEX_ROOT, + NTFS_INDEX_I30, 4, dirflags, + ATTR_COMPRESSION_MASK); + } + } + if (!res) { + ni->flags = (ni->flags & ~settable) + | (cpu_to_le32(attrib) & settable); + NInoFileNameSetDirty(ni); + NInoSetDirty(ni); + } + } else + errno = EINVAL; + return (res); +} + /* * Return the ntfs attribute into an extended attribute * The attribute is expected according to cpu endianness @@ -4136,8 +4205,6 @@ int ntfs_set_ntfs_attrib(ntfs_inode *ni, const char *value, size_t size, int flags) { u32 attrib; - le32 settable; - ATTR_FLAGS dirflags; int res; res = -1; @@ -4145,33 +4212,7 @@ int ntfs_set_ntfs_attrib(ntfs_inode *ni, if (!(flags & XATTR_CREATE)) { /* copy to avoid alignment problems */ memcpy(&attrib,value,sizeof(FILE_ATTR_FLAGS)); - settable = FILE_ATTR_SETTABLE; - res = 0; - if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) { - /* - * Accept changing compression for a directory - * and set index root accordingly - */ - settable |= FILE_ATTR_COMPRESSED; - if ((ni->flags ^ cpu_to_le32(attrib)) - & FILE_ATTR_COMPRESSED) { - if (ni->flags & FILE_ATTR_COMPRESSED) - dirflags = const_cpu_to_le16(0); - else - dirflags = ATTR_IS_COMPRESSED; - res = ntfs_attr_set_flags(ni, - AT_INDEX_ROOT, - NTFS_INDEX_I30, 4, - dirflags, - ATTR_COMPRESSION_MASK); - } - } - if (!res) { - ni->flags = (ni->flags & ~settable) - | (cpu_to_le32(attrib) & settable); - NInoFileNameSetDirty(ni); - NInoSetDirty(ni); - } + res = ntfs_set_inode_attributes(ni, attrib); } else errno = EEXIST; } else @@ -4554,7 +4595,69 @@ static BOOL mergesecurityattr(ntfs_volume *vol, const char *oldattr, return (ok); } -#if 0 +int ntfs_get_inode_security(ntfs_inode *ni, u32 selection, + char *buf, u32 buflen, u32 *psize) +{ + int res; + char *attr; + + res = 0; + if (ni) { + 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); + } + } else + errno = EINVAL; + return (res); +} + +int ntfs_set_inode_security(ntfs_inode *ni, u32 selection, const char *attr) +{ + const SECURITY_DESCRIPTOR_RELATIVE *phead; + int attrsz; + BOOL missing; + char *oldattr; + int res; + + res = -1; /* default return */ + if (ni) { + 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)) { + res = 0; + } + free(oldattr); + } + } else + errno = EINVAL; + } else + errno = EINVAL; + return (res); +} + /* * Return the security descriptor of a file * This is intended to be similar to GetFileSecurity() from Win32 @@ -4680,176 +4783,8 @@ int ntfs_set_file_security(struct SECURITY_API *scapi, errno = EINVAL; return (res); } -#endif -/* - * 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_set_file_security(ntfs_volume *vol, 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(vol, ni); - if (oldattr) { - if (mergesecurityattr( - 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 /* * Return the attributes of a file * This is intended to be similar to GetFileAttributes() from Win32 @@ -4873,14 +4808,7 @@ int ntfs_get_file_attributes(struct SECURITY_API *scapi, const char *path) if (scapi && (scapi->magic == MAGIC_API) && path) { ni = ntfs_pathname_to_inode(scapi->security.vol, NULL, path); if (ni) { - attrib = le32_to_cpu(ni->flags); - if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) - attrib |= const_le32_to_cpu(FILE_ATTR_DIRECTORY); - else - attrib &= ~const_le32_to_cpu(FILE_ATTR_DIRECTORY); - if (!attrib) - attrib |= const_le32_to_cpu(FILE_ATTR_NORMAL); - + attrib = ntfs_get_inode_attributes(ni); ntfs_inode_close(ni); } else errno = ENOENT; @@ -4912,91 +4840,24 @@ BOOL ntfs_set_file_attributes(struct SECURITY_API *scapi, const char *path, s32 attrib) { ntfs_inode *ni; - le32 settable; - ATTR_FLAGS dirflags; int res; res = 0; /* default return */ if (scapi && (scapi->magic == MAGIC_API) && path) { ni = ntfs_pathname_to_inode(scapi->security.vol, NULL, path); if (ni) { - settable = FILE_ATTR_SETTABLE; - if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) { - /* - * Accept changing compression for a directory - * and set index root accordingly - */ - settable |= FILE_ATTR_COMPRESSED; - if ((ni->flags ^ cpu_to_le32(attrib)) - & FILE_ATTR_COMPRESSED) { - if (ni->flags & FILE_ATTR_COMPRESSED) - dirflags = const_cpu_to_le16(0); - else - dirflags = ATTR_IS_COMPRESSED; - res = ntfs_attr_set_flags(ni, - AT_INDEX_ROOT, - NTFS_INDEX_I30, 4, - dirflags, - ATTR_COMPRESSION_MASK); - } - } - if (!res) { - ni->flags = (ni->flags & ~settable) - | (cpu_to_le32(attrib) & settable); - NInoSetDirty(ni); - NInoFileNameSetDirty(ni); - } - if (!ntfs_inode_close(ni)) + /* Win32 convention here : -1 means successful */ + if (!ntfs_set_inode_attributes(ni, attrib)) res = -1; + if (ntfs_inode_close(ni)) + res = 0; } else errno = ENOENT; } return (res); } -#endif - -/* - * Set attributes of a NTFS file given an inode - * - * Returns nonzero on success - */ -int _ntfs_set_file_attributes(ntfs_inode *ni, s32 attrib) -{ - le32 settable = FILE_ATTR_SETTABLE; - ATTR_FLAGS dirflags; - int ret = 0; - - if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) { - /* - * Accept changing compression for a directory - * and set index root accordingly - */ - settable |= FILE_ATTR_COMPRESSED; - if ((ni->flags ^ cpu_to_le32(attrib)) - & FILE_ATTR_COMPRESSED) { - if (ni->flags & FILE_ATTR_COMPRESSED) - dirflags = const_cpu_to_le16(0); - else - dirflags = ATTR_IS_COMPRESSED; - ret = ntfs_attr_set_flags(ni, - AT_INDEX_ROOT, - NTFS_INDEX_I30, 4, - dirflags, - ATTR_COMPRESSION_MASK); - } - } - if (ret == 0) { - ni->flags = (ni->flags & ~settable) - | (cpu_to_le32(attrib) & settable); - NInoSetDirty(ni); - NInoFileNameSetDirty(ni); - ret = -1; - } - return ret; -} -#if 0 BOOL ntfs_read_directory(struct SECURITY_API *scapi, const char *path, ntfs_filldir_t callback, void *context) { @@ -5300,4 +5161,3 @@ BOOL ntfs_leave_file_security(struct SECURITY_API *scapi) return (ok); } -#endif