From 3b44e8890a50c94010456a231dad54e09fe66dc7 Mon Sep 17 00:00:00 2001 From: jpandre Date: Thu, 21 Aug 2008 10:55:18 +0000 Subject: [PATCH] Made use of fuse checks when "default_permissions" option is used --- libntfs-3g/security.c | 191 ++++++++---------------------------------- src/ntfs-3g.c | 76 +++++++++++++---- 2 files changed, 97 insertions(+), 170 deletions(-) diff --git a/libntfs-3g/security.c b/libntfs-3g/security.c index 61287fc8..ad723148 100644 --- a/libntfs-3g/security.c +++ b/libntfs-3g/security.c @@ -1792,6 +1792,13 @@ static char *getsecurityattr(ntfs_volume *vol, #if POSIXACLS +/* + * Determine which access types to a file are allowed + * according to the relation of current process to the file + * + * Do not call if default_permissions is set + */ + static int access_check_posix(struct SECURITY_CONTEXT *scx, struct POSIX_SECURITY *pxdesc, mode_t request, uid_t uid, gid_t gid) @@ -1862,23 +1869,17 @@ static int access_check_posix(struct SECURITY_CONTEXT *scx, return (perms); } -#endif - /* * Get permissions to access a file * Takes into account the relation of user to file (owner, group, ...) * Do no use as mode of the file + * Do no call if default_permissions is set * * returns -1 if there is a problem */ -#if POSIXACLS static int ntfs_get_perm(struct SECURITY_CONTEXT *scx, const char *path, ntfs_inode * ni, mode_t request) -#else -static int ntfs_get_perm(struct SECURITY_CONTEXT *scx, - const char *path, ntfs_inode * ni) -#endif { const SECURITY_DESCRIPTOR_RELATIVE *phead; const struct CACHED_PERMISSIONS *cached; @@ -1888,9 +1889,7 @@ static int ntfs_get_perm(struct SECURITY_CONTEXT *scx, uid_t uid; gid_t gid; int perm; -#if POSIXACLS struct POSIX_SECURITY *pxdesc; -#endif if (!scx->mapping[MAPUSERS] || !scx->uid) perm = 07777; @@ -1898,15 +1897,9 @@ static int ntfs_get_perm(struct SECURITY_CONTEXT *scx, /* check whether available in cache */ cached = fetch_cache(scx,ni); if (cached) { -#if POSIXACLS uid = cached->uid; gid = cached->gid; perm = access_check_posix(scx,cached->pxdesc,request,uid,gid); -#else - perm = cached->mode; - uid = cached->uid; - gid = cached->gid; -#endif } else { perm = 0; /* default to no permission */ securattr = getsecurityattr(scx->vol, path, ni); @@ -1917,39 +1910,29 @@ static int ntfs_get_perm(struct SECURITY_CONTEXT *scx, securattr[le32_to_cpu(phead->group)]; gid = ntfs_find_group(scx->mapping[MAPGROUPS],gsid); #if OWNERFROMACL - usid = acl_owner(securattr); -#if POSIXACLS - pxdesc = build_permissions_posix(scx,securattr, + usid = ntfs_acl_owner(securattr); + pxdesc = ntfs_ntfs_build_permissions_posix(scx->mapping,securattr, usid, gsid, ni); if (pxdesc) perm = pxdesc->mode & 07777; else perm = -1; -#else - perm = build_permissions(securattr, - usid, gsid, ni); -#endif - uid = findowner(scx,usid); + uid = ntfs_find_user(scx->mapping[MAPUSERS],usid); #else usid = (const SID*)& securattr[le32_to_cpu(phead->owner)]; -#if POSIXACLS - pxdesc = build_permissions_posix(scx,securattr, + pxdesc = ntfs_ntfs_build_permissions_posix(scx,securattr, usid, gsid, ni); if (pxdesc) perm = pxdesc->mode & 07777; else perm = -1; -#else - perm = build_permissions(securattr, - usid, gsid, ni); -#endif - if (!perm && same_sid(usid, adminsid)) { + if (!perm && ntfs_same_sid(usid, adminsid)) { uid = find_tenant(scx, securattr); if (uid) perm = 0700; } else - uid = findowner(scx,usid); + uid = ntfs_find_user(scx->mapping[MAPUSERS],usid); #endif /* * Create a security id if there were none @@ -1968,45 +1951,23 @@ static int ntfs_get_perm(struct SECURITY_CONTEXT *scx, } if (test_nino_flag(ni, v3_Extensions) && (perm >= 0)) { -#if POSIXACLS enter_cache(scx, ni, uid, gid, pxdesc); -#else - enter_cache(scx, ni, uid, - gid, perm); -#endif } -#if POSIXACLS if (pxdesc) { perm = access_check_posix(scx,pxdesc,request,uid,gid); free(pxdesc); } -#endif free(securattr); } else { perm = -1; uid = gid = 0; } } -#if POSIXACLS -#else - if (perm >= 0) { - if (uid == scx->uid) - perm &= 07700; - else - if ((gid == scx->gid) - || groupmember(scx, scx->uid, gid)) - perm &= 07070; - else - perm &= 07007; - } -#endif } return (perm); } -#if POSIXACLS - /* * Get a Posix ACL * returns size or -errno if there is a problem @@ -2939,6 +2900,8 @@ int ntfs_sd_add_everyone(ntfs_inode *ni) return ret; } +#if POSIXACLS + /* * Check whether user can access a file in a specific way * @@ -2958,6 +2921,7 @@ int ntfs_allowed_access(struct SECURITY_CONTEXT *scx, int allow; struct stat stbuf; + if (scx->vol->secure_flags & (1 << SECURITY_DEFAULT)) return (1); /* * Always allow for root. From the user's point of view, * testing X_OK for a file with no x flag should return @@ -3037,6 +3001,7 @@ BOOL ntfs_allowed_dir_access(struct SECURITY_CONTEXT *scx, ntfs_inode *dir_ni; struct stat stbuf; + if (scx->vol->secure_flags & (1 << SECURITY_DEFAULT)) return (TRUE); allow = 0; dirpath = strdup(path); if (dirpath) { @@ -3070,6 +3035,8 @@ BOOL ntfs_allowed_dir_access(struct SECURITY_CONTEXT *scx, return (allow); /* errno is set if not allowed */ } +#endif + /* * Define a new owner/group to a file * @@ -3090,8 +3057,8 @@ int ntfs_set_owner(struct SECURITY_CONTEXT *scx, int perm; int res; #if POSIXACLS - struct POSIX_SECURITY *oldpxdesc; - struct POSIX_SECURITY *newpxdesc; + struct POSIX_SECURITY *pxdesc; + BOOL pxdescbuilt = FALSE; #endif res = 0; @@ -3103,22 +3070,14 @@ int ntfs_set_owner(struct SECURITY_CONTEXT *scx, filegid = cached->gid; mode = cached->mode; #if POSIXACLS - oldpxdesc = cached->pxdesc; - if (oldpxdesc) { - newpxdesc = merge_owner_posix(oldpxdesc, - uid, gid, fileuid, filegid); - if (!newpxdesc) - res = -1; - } else - newpxdesc = (struct POSIX_SECURITY*)NULL; + pxdesc = cached->pxdesc; + if (!pxdesc) + res = -1; #endif } else { fileuid = 0; filegid = 0; mode = 0; -#if POSIXACLS - newpxdesc = (struct POSIX_SECURITY*)NULL; -#endif oldattr = getsecurityattr(scx->vol, path, ni); if (oldattr) { phead = (const SECURITY_DESCRIPTOR_RELATIVE*) @@ -3132,17 +3091,13 @@ int ntfs_set_owner(struct SECURITY_CONTEXT *scx, &oldattr[le32_to_cpu(phead->owner)]; #endif #if POSIXACLS - oldpxdesc = build_permissions_posix(scx, oldattr, + pxdesc = ntfs_ntfs_build_permissions_posix(scx->mapping, oldattr, usid, gsid, ni); - if (oldpxdesc) { - fileuid = findowner(scx,usid); - filegid = findgroup(scx,gsid); - mode = perm = oldpxdesc->mode; - newpxdesc = merge_owner_posix(oldpxdesc, - uid, gid, fileuid, filegid); - free(oldpxdesc); - if (!newpxdesc) - res = -1; + if (pxdesc) { + pxdescbuilt = TRUE; + fileuid = ntfs_find_user(scx->mapping[MAPUSERS],usid); + filegid = ntfs_find_group(scx->mapping[MAPGROUPS],gsid); + mode = perm = pxdesc->mode; } else res = -1; #else @@ -3177,7 +3132,7 @@ int ntfs_set_owner(struct SECURITY_CONTEXT *scx, mode &= 01777; #if POSIXACLS res = ntfs_set_owner_mode(scx, ni, uid, gid, - mode, newpxdesc); + mode, pxdesc); #else res = ntfs_set_owner_mode(scx, ni, uid, gid, mode); #endif @@ -3186,7 +3141,8 @@ int ntfs_set_owner(struct SECURITY_CONTEXT *scx, errno = EPERM; } #if POSIXACLS - free(newpxdesc); + if (pxdescbuilt) + free(pxdesc); #endif } else { /* @@ -3200,81 +3156,6 @@ int ntfs_set_owner(struct SECURITY_CONTEXT *scx, return (res ? -1 : 0); } -/* - * Copy the inheritable parts of an ACL - * - * Returns the size of the new ACL - * or zero if nothing is inheritable - */ - -static int inherit_acl(const ACL *oldacl, ACL *newacl, - const SID *usid, const SID *gsid, BOOL fordir) -{ - unsigned int src; - unsigned int dst; - int oldcnt; - int newcnt; - unsigned int selection; - int nace; - int acesz; - int usidsz; - int gsidsz; - const ACCESS_ALLOWED_ACE *poldace; - ACCESS_ALLOWED_ACE *pnewace; - - usidsz = sid_size(usid); - gsidsz = sid_size(gsid); - - /* ACL header */ - - newacl->revision = ACL_REVISION; - newacl->alignment1 = 0; - newacl->alignment2 = cpu_to_le16(0); - src = dst = sizeof(ACL); - - selection = (fordir ? CONTAINER_INHERIT_ACE : OBJECT_INHERIT_ACE); - newcnt = 0; - oldcnt = le16_to_cpu(oldacl->ace_count); - for (nace = 0; nace < oldcnt; nace++) { - poldace = (const ACCESS_ALLOWED_ACE*)((const char*)oldacl + src); - acesz = le16_to_cpu(poldace->size); - if (poldace->flags & selection) { - pnewace = (ACCESS_ALLOWED_ACE*) - ((char*)newacl + dst); - memcpy(pnewace,poldace,acesz); - /* - * Replace generic creator-owner and - * creator-group by owner and group - */ - if (same_sid(&pnewace->sid, ownersid)) { - memcpy(&pnewace->sid, usid, usidsz); - acesz = usidsz + 8; - } - if (same_sid(&pnewace->sid, groupsid)) { - memcpy(&pnewace->sid, gsid, gsidsz); - acesz = gsidsz + 8; - } - /* remove inheritance flags if not a directory */ - if (!fordir) - pnewace->flags &= ~(OBJECT_INHERIT_ACE - | CONTAINER_INHERIT_ACE - | INHERIT_ONLY_ACE); - dst += acesz; - newcnt++; - } - src += acesz; - } - /* - * Adjust header if something was inherited - */ - if (dst > sizeof(ACL)) { - newacl->ace_count = cpu_to_le16(newcnt); - newacl->size = cpu_to_le16(dst); - } else - dst = 0; - return (dst); -} - /* * Build a security id for a descriptor inherited from * parent directory the Windows way @@ -3349,7 +3230,7 @@ static le32 build_inherited_id(struct SECURITY_CONTEXT *scx, offpacl = le32_to_cpu(pphead->dacl); ppacl = (const ACL*)&parentattr[offpacl]; pnacl = (ACL*)&newattr[pos]; - aclsz = inherit_acl(ppacl, pnacl, usid, gsid, fordir); + aclsz = ntfs_inherit_acl(ppacl, pnacl, usid, gsid, fordir); if (aclsz) { pnhead->dacl = cpu_to_le32(pos); pos += aclsz; @@ -3364,7 +3245,7 @@ static le32 build_inherited_id(struct SECURITY_CONTEXT *scx, offpacl = le32_to_cpu(pphead->sacl); ppacl = (const ACL*)&parentattr[offpacl]; pnacl = (ACL*)&newattr[pos]; - aclsz = inherit_acl(ppacl, pnacl, usid, gsid, fordir); + aclsz = ntfs_inherit_acl(ppacl, pnacl, usid, gsid, fordir); if (aclsz) { pnhead->sacl = cpu_to_le32(pos); pos += aclsz; diff --git a/src/ntfs-3g.c b/src/ntfs-3g.c index 1672d48a..a940ff61 100644 --- a/src/ntfs-3g.c +++ b/src/ntfs-3g.c @@ -707,14 +707,16 @@ static int ntfs_fuse_readdir(const char *path, void *buf, static int ntfs_fuse_open(const char *org_path, struct fuse_file_info *fi) { - ntfs_inode *ni; - ntfs_attr *na; + ntfs_inode *ni = NULL; + ntfs_attr *na = NULL; int res = 0; char *path = NULL; ntfschar *stream_name; int stream_name_len; +#if POSIXACLS int accesstype; struct SECURITY_CONTEXT security; +#endif stream_name_len = ntfs_fuse_parse_path(org_path, &path, &stream_name); if (stream_name_len < 0) @@ -723,7 +725,7 @@ static int ntfs_fuse_open(const char *org_path, if (ni) { na = ntfs_attr_open(ni, AT_DATA, stream_name, stream_name_len); if (na) { - +#if POSIXACLS if (ntfs_fuse_fill_security_context(&security)) { if (fi->flags & O_WRONLY) accesstype = S_IWRITE; @@ -742,16 +744,22 @@ static int ntfs_fuse_open(const char *org_path, if (NAttrEncrypted(na)) res = -EACCES; } - ntfs_attr_close(na); +#else + if (NAttrEncrypted(na)) + res = -EACCES; +#endif } else res = -errno; - if (ntfs_inode_close(ni)) - set_fuse_error(&res); } else res = -errno; free(path); if (stream_name_len) free(stream_name); + if (res) { + ntfs_attr_close(na); + ntfs_inode_close(ni); + } else + fi->fh = (uintptr_t)na; return res; } @@ -879,7 +887,9 @@ static int ntfs_fuse_trunc(const char *org_path, off_t size, BOOL chkwrite) char *path = NULL; ntfschar *stream_name; int stream_name_len; +#if POSIXACLS struct SECURITY_CONTEXT security; +#endif stream_name_len = ntfs_fuse_parse_path(org_path, &path, &stream_name); if (stream_name_len < 0) @@ -951,8 +961,10 @@ static int ntfs_fuse_chmod(const char *path, else res = -EOPNOTSUPP; } else { +#if POSIXACLS /* parent directory must be executable */ if (ntfs_allowed_dir_access(&security,path,S_IEXEC)) { +#endif ni = ntfs_pathname_to_inode(ctx->vol, NULL, path); if (!ni) res = -errno; @@ -970,8 +982,10 @@ static int ntfs_fuse_chmod(const char *path, if (ntfs_inode_close(ni)) set_fuse_error(&res); } +#if POSIXACLS } else res = -errno; +#endif } return res; } @@ -993,10 +1007,11 @@ static int ntfs_fuse_chown(const char *path, uid_t uid, gid_t gid) } else { res = 0; if (((int)uid != -1) || ((int)gid != -1)) { - +#if POSIXACLS /* parent directory must be executable */ if (ntfs_allowed_dir_access(&security,path,S_IEXEC)) { +#endif ni = ntfs_pathname_to_inode(ctx->vol, NULL, path); if (!ni) res = -errno; @@ -1009,13 +1024,17 @@ static int ntfs_fuse_chown(const char *path, uid_t uid, gid_t gid) if (ntfs_inode_close(ni)) set_fuse_error(&res); } +#if POSIXACLS } else res = -errno; +#endif } } return (res); } +#if POSIXACLS + static int ntfs_fuse_access(const char *path, int type) { int res = 0; @@ -1034,7 +1053,6 @@ static int ntfs_fuse_access(const char *path, int type) res = -EOPNOTSUPP; } else { /* parent directory must be readable */ - /* this is supposed to imply access to outer dirs */ if (ntfs_allowed_dir_access(&security,path,S_IREAD)) { ni = ntfs_pathname_to_inode(ctx->vol, NULL, path); if (!ni) { @@ -1058,6 +1076,8 @@ static int ntfs_fuse_access(const char *path, int type) return (res); } +#endif + static int ntfs_fuse_create(const char *org_path, dev_t typemode, dev_t dev, const char *target) { @@ -1099,10 +1119,12 @@ static int ntfs_fuse_create(const char *org_path, dev_t typemode, dev_t dev, res = -errno; goto exit; } +#if POSIXACLS /* JPA make sure parent directory is writeable and executable */ if (!ntfs_fuse_fill_security_context(&security) || ntfs_allowed_access(&security,dir_path, dir_ni,S_IWRITE + S_IEXEC)) { +#endif /* ! JPA ! did not find where to get umask from ! */ if (S_ISDIR(type)) perm = typemode & ~ctx->dmask & 0777; @@ -1184,9 +1206,10 @@ static int ntfs_fuse_create(const char *org_path, dev_t typemode, dev_t dev, ntfs_fuse_update_times(dir_ni, NTFS_UPDATE_MCTIME); } else res = -errno; - +#if POSIXACLS } else res = -errno; +#endif free(path); exit: @@ -1279,8 +1302,10 @@ static int ntfs_fuse_link(const char *old_path, const char *new_path) ntfschar *uname = NULL; ntfs_inode *dir_ni = NULL, *ni; char *path; - struct SECURITY_CONTEXT security; int res = 0, uname_len; +#if POSIXACLS + struct SECURITY_CONTEXT security; +#endif if (ntfs_fuse_is_named_data_stream(old_path)) return -EINVAL; /* n/a for named data streams. */ @@ -1312,12 +1337,15 @@ static int ntfs_fuse_link(const char *old_path, const char *new_path) goto exit; } +#if POSIXACLS /* JPA make sure the parent directories are writeable */ if (ntfs_fuse_fill_security_context(&security) && (!ntfs_allowed_dir_access(&security,old_path,S_IWRITE + S_IEXEC) || !ntfs_allowed_access(&security,path,dir_ni,S_IWRITE + S_IEXEC))) res = -EACCES; - else { + else +#endif + { if (ntfs_link(ni, dir_ni, uname, uname_len)) { res = -errno; goto exit; @@ -1346,8 +1374,10 @@ static int ntfs_fuse_rm(const char *org_path) ntfschar *uname = NULL; ntfs_inode *dir_ni = NULL, *ni; char *path; - struct SECURITY_CONTEXT security; int res = 0, uname_len; +#if POSIXACLS + struct SECURITY_CONTEXT security; +#endif path = strdup(org_path); if (!path) @@ -1373,18 +1403,22 @@ static int ntfs_fuse_rm(const char *org_path) res = -errno; goto exit; } + +#if POSIXACLS /* JPA deny unlinking if directory is not writable and executable */ if (!ntfs_fuse_fill_security_context(&security) || ntfs_allowed_dir_access(&security, org_path, S_IEXEC + S_IWRITE + S_ISVTX)) { - +#endif if (ntfs_delete(ctx->vol, org_path, ni, dir_ni, uname, uname_len)) res = -errno; /* ntfs_delete() always closes ni and dir_ni */ ni = dir_ni = NULL; +#if POSIXACLS } else res = -EACCES; +#endif exit: if (ntfs_inode_close(dir_ni)) set_fuse_error(&res); @@ -1418,8 +1452,10 @@ static int ntfs_fuse_unlink(const char *org_path) char *path = NULL; ntfschar *stream_name; int stream_name_len; - struct SECURITY_CONTEXT security; int res = 0; +#if POSIXACLS + struct SECURITY_CONTEXT security; +#endif stream_name_len = ntfs_fuse_parse_path(org_path, &path, &stream_name); if (stream_name_len < 0) @@ -1427,6 +1463,7 @@ static int ntfs_fuse_unlink(const char *org_path) if (!stream_name_len) res = ntfs_fuse_rm(path); else { +#if POSIXACLS /* * JPA deny unlinking stream if directory is not * writable and executable (debatable) @@ -1437,6 +1474,9 @@ static int ntfs_fuse_unlink(const char *org_path) res = ntfs_fuse_rm_stream(path, stream_name, stream_name_len); else res = -errno; +#else + res = ntfs_fuse_rm_stream(path, stream_name, stream_name_len); +#endif } free(path); if (stream_name_len) @@ -1496,8 +1536,10 @@ static int ntfs_fuse_rename_existing_dest(const char *old_path, const char *new_ { int ret, len; char *tmp; - struct SECURITY_CONTEXT security; const char *ext = ".ntfs-3g-"; +#if POSIXACLS + struct SECURITY_CONTEXT security; +#endif ntfs_log_trace("Entering\n"); @@ -1511,6 +1553,7 @@ static int ntfs_fuse_rename_existing_dest(const char *old_path, const char *new_ ntfs_log_error("snprintf failed: %d != %d\n", ret, len - 1); ret = -EOVERFLOW; } else { +#if POSIXACLS /* * Make sure existing dest can be removed. * This is only needed if parent directory is @@ -1524,6 +1567,9 @@ static int ntfs_fuse_rename_existing_dest(const char *old_path, const char *new_ ret = ntfs_fuse_safe_rename(old_path, new_path, tmp); else ret = -EACCES; +#else + ret = ntfs_fuse_safe_rename(old_path, new_path, tmp); +#endif } free(tmp); return ret;