Made use of fuse checks when "default_permissions" option is used

N2009_11_14_FIXES
jpandre 2008-08-21 10:55:18 +00:00
parent 713e6349c8
commit 3b44e8890a
2 changed files with 97 additions and 170 deletions

View File

@ -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;

View File

@ -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;