[vhffs-dev] [1624] added permissions checking on vhffsfs without using fuse default_permission option |
[ Thread Index |
Date Index
| More vhffs.org/vhffs-dev Archives
]
Revision: 1624
Author: gradator
Date: 2010-09-07 01:16:04 +0200 (Tue, 07 Sep 2010)
Log Message:
-----------
added permissions checking on vhffsfs without using fuse default_permission option
Modified Paths:
--------------
trunk/vhffs-fs/vhffsfs.c
trunk/vhffs-fs/vhffsfs_run
Modified: trunk/vhffs-fs/vhffsfs.c
===================================================================
--- trunk/vhffs-fs/vhffsfs.c 2010-09-06 19:50:23 UTC (rev 1623)
+++ trunk/vhffs-fs/vhffsfs.c 2010-09-06 23:16:04 UTC (rev 1624)
@@ -18,6 +18,7 @@
*/
#define VHFFSFS_MAXCONNDB 5
+// TODO: use a randomised temporary directory
#define VHFFSFS_EMPTYDIR "/tmp/emptydir"
#define _GNU_SOURCE
@@ -55,6 +56,10 @@
#include <pthread.h>
#include <signal.h>
+#define CREATE_OK 1024
+#define REMOVE_OK 2048
+#define CHMOD_OK 4096
+
#if defined(WITH_CACHE) || defined(WITH_CHECKQUOTA_CACHE)
#include <glib.h>
#endif
@@ -630,22 +635,181 @@
}
+// path must be an absolute allocated path, without symlink
+// content of path is modified and is left modified if right checks fails
+int vhffsfs_checkperm_with_realpath(char *path, uid_t uid, gid_t gid, int mode) {
+
+ char *cur, *parent;
+ struct stat st;
+
+ if(!path || *path == '\0' || *path != '/') {
+ errno = ENOENT;
+ return -1;
+ }
+
+ for(parent=path, cur=path+1 ; *cur ; cur++ ) {
+ if(*cur == '/') {
+ *cur = '\0';
+
+ if( lstat(path, &st) ) {
+ // lstat() handles ENOENT and so on then set errno
+ return -1;
+ }
+
+ if(!S_ISDIR(st.st_mode)) {
+ errno = ENOTDIR;
+ return -1;
+ }
+
+ if(st.st_uid == uid) {
+ if(!(st.st_mode & S_IXUSR)) {
+ errno = EACCES;
+ return -1;
+ }
+ } else if(st.st_gid == gid) {
+ if(!(st.st_mode & S_IXGRP)) {
+ errno = EACCES;
+ return -1;
+ }
+ } else {
+ if(!(st.st_mode & S_IXOTH)) {
+ errno = EACCES;
+ return -1;
+ }
+ }
+ *cur = '/';
+ parent = cur;
+ }
+ }
+
+ if( mode & (CREATE_OK|REMOVE_OK) ) {
+ *parent = '\0';
+
+ if( lstat(path, &st) ) {
+ return -1;
+ }
+
+ if(st.st_uid == uid) {
+ if(!(st.st_mode & S_IWUSR)) {
+ errno = EACCES;
+ return -1;
+ }
+ } else if(st.st_gid == gid) {
+ if(!(st.st_mode & S_IWGRP)) {
+ errno = EACCES;
+ return -1;
+ }
+ } else {
+ if(!(st.st_mode & S_IWOTH)) {
+ errno = EACCES;
+ return -1;
+ }
+ }
+
+ *parent = '/';
+ return 0;
+ }
+
+ if( lstat(path, &st) ) {
+ return -1;
+ }
+
+ if(mode == F_OK) {
+ return 0;
+ }
+
+ if(mode & CHMOD_OK) {
+ if(st.st_uid != uid) {
+ errno = EACCES;
+ return -1;
+ }
+ return 0;
+ }
+
+ if(mode & R_OK) {
+ if(st.st_uid == uid) {
+ if(!(st.st_mode & S_IRUSR)) {
+ errno = EACCES;
+ return -1;
+ }
+ } else if(st.st_gid == gid) {
+ if(!(st.st_mode & S_IRGRP)) {
+ errno = EACCES;
+ return -1;
+ }
+ } else {
+ if(!(st.st_mode & S_IROTH)) {
+ errno = EACCES;
+ return -1;
+ }
+ }
+ }
+
+ if(mode & W_OK) {
+ if(st.st_uid == uid) {
+ if(!(st.st_mode & S_IWUSR)) {
+ errno = EACCES;
+ return -1;
+ }
+ } else if(st.st_gid == gid) {
+ if(!(st.st_mode & S_IWGRP)) {
+ errno = EACCES;
+ return -1;
+ }
+ } else {
+ if(!(st.st_mode & S_IWOTH)) {
+ errno = EACCES;
+ return -1;
+ }
+ }
+ }
+
+ if(mode & X_OK) {
+ if(st.st_uid == uid) {
+ if(!(st.st_mode & S_IXUSR)) {
+ errno = EACCES;
+ return -1;
+ }
+ } else if(st.st_gid == gid) {
+ if(!(st.st_mode & S_IXGRP)) {
+ errno = EACCES;
+ return -1;
+ }
+ } else {
+ if(!(st.st_mode & S_IXOTH)) {
+ errno = EACCES;
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+
// return the real path
-char *vhffsfs_realpath(const char *path, uid_t *uid, gid_t *gid) {
+char *vhffsfs_realpath(const char *path, uid_t *ruid, gid_t *rgid, int access) {
char *begin, *cur;
char *first=NULL;
char *homedir;
char *rpath=NULL;
+ uid_t uid;
+ gid_t gid;
//printf("======= PATH: %s\n", path);
//printf("======= UID: %d\n", fuse_get_context()->uid);
//printf("======= GID: %d\n", fuse_get_context()->gid);
// path empty
- if(*(path+0) == '\0') return NULL;
+ if(*(path+0) == '\0') {
+ errno = ENOENT;
+ return NULL;
+ }
// set uid and gid
- if(uid) *uid = fuse_get_context()->uid;
- if(gid) *gid = fuse_get_context()->gid;
+ uid = fuse_get_context()->uid;
+ if(ruid) *ruid = uid;
+ gid = fuse_get_context()->gid;
+ if(rgid) *rgid = gid;
// fetch homedir
homedir = vhffsfs_gethomedir();
if(!homedir) return strdup(VHFFSFS_EMPTYDIR);
@@ -682,7 +846,8 @@
char *second=NULL;
// set gid
- if(gid) *gid = vhffsfs_getgroupgid(groupname);
+ gid = vhffsfs_getgroupgid(groupname);
+ if(rgid) *rgid = gid;
// get second node
if(*cur++) {
@@ -743,6 +908,11 @@
}
free(homedir);
+ if( vhffsfs_checkperm_with_realpath(rpath, uid, gid, access) ) {
+ free(rpath);
+ return NULL;
+ }
+
//printf("======= RETURN: %s\n\n", rpath);
return rpath;
}
@@ -759,7 +929,7 @@
// get groupname
groupname = (char*)path+1;
- if(!groupname)
+ if(!*groupname)
return vhffsfs_getusergroups(fuse_get_context()->uid);
// don't do group lookup if the path is not a group directory
@@ -1185,8 +1355,8 @@
int res;
char *rpath;
- rpath = vhffsfs_realpath(path, NULL, NULL);
- if(!rpath) return -ENOENT;
+ rpath = vhffsfs_realpath(path, NULL, NULL, F_OK);
+ if(!rpath) return -errno;
res = lstat(rpath, stbuf);
free(rpath);
@@ -1201,8 +1371,11 @@
static int vhffsfs_fgetattr(const char *path, struct stat *stbuf, struct fuse_file_info *fi)
{
int res;
+ char *rpath;
- (void) path;
+ rpath = vhffsfs_realpath(path, NULL, NULL, F_OK);
+ if(!rpath) return -errno;
+ free(rpath);
res = fstat(fi->fh, stbuf);
@@ -1215,16 +1388,16 @@
static int vhffsfs_access(const char *path, int mask)
{
- int res;
+// int res;
char *rpath;
- rpath = vhffsfs_realpath(path, NULL, NULL);
- if(!rpath) return -ENOENT;
+ rpath = vhffsfs_realpath(path, NULL, NULL, mask);
+ if(!rpath) return -errno;
- res = access(rpath, mask);
+// res = access(rpath, mask);
free(rpath);
- if(res == -1) return -errno;
+// if(res == -1) return -errno;
return 0;
}
@@ -1234,8 +1407,8 @@
int res;
char *rpath;
- rpath = vhffsfs_realpath(path, NULL, NULL);
- if(!rpath) return -ENOENT;
+ rpath = vhffsfs_realpath(path, NULL, NULL, R_OK);
+ if(!rpath) return -errno;
res = readlink(rpath, buf, size - 1);
free(rpath);
@@ -1250,8 +1423,8 @@
{
char *rpath;
- rpath = vhffsfs_realpath(path, NULL, NULL);
- if(!rpath) return -ENOENT;
+ rpath = vhffsfs_realpath(path, NULL, NULL, R_OK);
+ if(!rpath) return -errno;
DIR *dp = opendir(rpath);
free(rpath);
@@ -1320,8 +1493,8 @@
int res;
char *rpath;
- rpath = vhffsfs_realpath(path, NULL, NULL);
- if(!rpath) return -ENOENT;
+ rpath = vhffsfs_realpath(path, NULL, NULL, W_OK);
+ if(!rpath) return -errno;
#ifdef WITH_CHECKQUOTA
res = vhffsfs_checkquota_gid_with_realpath(rpath, gid, 0, 1);
@@ -1350,8 +1523,8 @@
uid_t uid;
gid_t gid;
- rpath = vhffsfs_realpath(path, &uid, &gid);
- if(!rpath) return -ENOENT;
+ rpath = vhffsfs_realpath(path, &uid, &gid, CREATE_OK);
+ if(!rpath) return -errno;
#ifdef WITH_CHECKQUOTA
res = vhffsfs_checkquota_gid_with_realpath(rpath, gid, 0, 1);
@@ -1382,8 +1555,8 @@
int res;
char *rpath;
- rpath = vhffsfs_realpath(path, NULL, NULL);
- if(!rpath) return -ENOENT;
+ rpath = vhffsfs_realpath(path, NULL, NULL, REMOVE_OK);
+ if(!rpath) return -errno;
res = unlink(rpath);
free(rpath);
@@ -1398,8 +1571,8 @@
int res;
char *rpath;
- rpath = vhffsfs_realpath(path, NULL, NULL);
- if(!rpath) return -ENOENT;
+ rpath = vhffsfs_realpath(path, NULL, NULL, REMOVE_OK);
+ if(!rpath) return -errno;
res = rmdir(rpath);
free(rpath);
@@ -1416,8 +1589,8 @@
uid_t uid;
gid_t gid;
- rto = vhffsfs_realpath(to, &uid, &gid);
- if(!rto) return -ENOENT;
+ rto = vhffsfs_realpath(to, &uid, &gid, CREATE_OK);
+ if(!rto) return -errno;
#ifdef WITH_CHECKQUOTA
res = vhffsfs_checkquota_gid_with_realpath(rto, gid, 0, 1);
@@ -1441,13 +1614,13 @@
int res;
char *rfrom, *rto;
- rfrom = vhffsfs_realpath(from, NULL, NULL);
- if(!rfrom) return -ENOENT;
+ rfrom = vhffsfs_realpath(from, NULL, NULL, REMOVE_OK);
+ if(!rfrom) return -errno;
- rto = vhffsfs_realpath(to, NULL, NULL);
+ rto = vhffsfs_realpath(to, NULL, NULL, CREATE_OK);
if(!rto) {
free(rfrom);
- return -ENOENT;
+ return -errno;
}
res = rename(rfrom, rto);
@@ -1466,13 +1639,13 @@
uid_t uid;
gid_t gid;
- rfrom = vhffsfs_realpath(from, NULL, NULL);
- if(!rfrom) return -ENOENT;
+ rfrom = vhffsfs_realpath(from, NULL, NULL, F_OK);
+ if(!rfrom) return -errno;
- rto = vhffsfs_realpath(to, &uid, &gid);
+ rto = vhffsfs_realpath(to, &uid, &gid, CREATE_OK);
if(!rto) {
free(rfrom);
- return -ENOENT;
+ return -errno;
}
#ifdef WITH_CHECKQUOTA
@@ -1500,8 +1673,8 @@
char *rpath;
struct stat st;
- rpath = vhffsfs_realpath(path, NULL, NULL);
- if(!rpath) return -ENOENT;
+ rpath = vhffsfs_realpath(path, NULL, NULL, CHMOD_OK);
+ if(!rpath) return -errno;
stat(rpath, &st);
if( S_ISDIR(st.st_mode) ) {
@@ -1521,17 +1694,20 @@
static int vhffsfs_chown(const char *path, uid_t uid, gid_t gid)
{
- int res;
+// disabled for now, needs intensive group checking and is pretty useless as groups are correctly assigned
+// should we break unix way and allow chown of files owner to group members ?
+/* int res;
char *rpath;
- rpath = vhffsfs_realpath(path, NULL, NULL);
- if(!rpath) return -ENOENT;
+ rpath = vhffsfs_realpath(path, NULL, NULL, W_OK);
+ if(!rpath) return -errno;
res = lchown(rpath, uid, gid);
free(rpath);
if(res == -1) return -errno;
- return 0;
+ return 0; */
+ return -EACCES;
}
@@ -1540,8 +1716,8 @@
int res;
char *rpath;
- rpath = vhffsfs_realpath(path, NULL, NULL);
- if(!rpath) return -ENOENT;
+ rpath = vhffsfs_realpath(path, NULL, NULL, W_OK);
+ if(!rpath) return -errno;
res = truncate(rpath, size);
free(rpath);
@@ -1554,8 +1730,12 @@
static int vhffsfs_ftruncate(const char *path, off_t size, struct fuse_file_info *fi)
{
int res;
- (void) path;
+ char *rpath;
+ rpath = vhffsfs_realpath(path, NULL, NULL, W_OK);
+ if(!rpath) return -errno;
+ free(rpath);
+
res = ftruncate(fi->fh, size);
if(res == -1) return -errno;
@@ -1568,8 +1748,8 @@
int res;
char *rpath;
- rpath = vhffsfs_realpath(path, NULL, NULL);
- if(!rpath) return -ENOENT;
+ rpath = vhffsfs_realpath(path, NULL, NULL, W_OK);
+ if(!rpath) return -errno;
res = utime(rpath, buf);
free(rpath);
@@ -1587,8 +1767,8 @@
gid_t gid;
int res;
- rpath = vhffsfs_realpath(path, &uid, &gid);
- if(!rpath) return -ENOENT;
+ rpath = vhffsfs_realpath(path, &uid, &gid, CREATE_OK);
+ if(!rpath) return -errno;
#ifdef WITH_CHECKQUOTA
res = vhffsfs_checkquota_gid_with_realpath(rpath, gid, 0, 1);
@@ -1619,10 +1799,16 @@
{
int fd;
char *rpath;
+ int mode = R_OK|W_OK;
- rpath = vhffsfs_realpath(path, NULL, NULL);
- if(!rpath) return -ENOENT;
+ if(fi->flags & O_WRONLY)
+ mode = W_OK;
+ else if(fi->flags & O_RDONLY)
+ mode = R_OK;
+ rpath = vhffsfs_realpath(path, NULL, NULL, mode);
+ if(!rpath) return -errno;
+
fd = open(rpath, fi->flags);
free(rpath);
@@ -1653,8 +1839,8 @@
gid_t gid;
char *rpath;
- rpath = vhffsfs_realpath(path, &uid, &gid);
- if(!rpath) return -ENOENT;
+ rpath = vhffsfs_realpath(path, &uid, &gid, F_OK);
+ if(!rpath) return -errno;
res = vhffsfs_checkquota_gid_with_realpath(rpath, gid, size, 0);
free(rpath);
@@ -1674,8 +1860,8 @@
int res;
char *rpath;
- rpath = vhffsfs_realpath(path, NULL, NULL);
- if(!rpath) return -ENOENT;
+ rpath = vhffsfs_realpath(path, NULL, NULL, R_OK);
+ if(!rpath) return -errno;
res = statvfs(rpath, stbuf);
free(rpath);
@@ -1720,8 +1906,8 @@
int res;
char *rpath;
- rpath = vhffsfs_realpath(path, NULL, NULL);
- if(!rpath) return -ENOENT;
+ rpath = vhffsfs_realpath(path, NULL, NULL, W_OK);
+ if(!rpath) return -errno;
res = lsetxattr(rpath, name, value, size, flags);
free(rpath);
@@ -1736,8 +1922,8 @@
int res;
char *rpath;
- rpath = vhffsfs_realpath(path, NULL, NULL);
- if(!rpath) return -ENOENT;
+ rpath = vhffsfs_realpath(path, NULL, NULL, R_OK);
+ if(!rpath) return -errno;
res = lgetxattr(rpath, name, value, size);
free(rpath);
@@ -1752,8 +1938,8 @@
int res;
char *rpath;
- rpath = vhffsfs_realpath(path, NULL, NULL);
- if(!rpath) return -ENOENT;
+ rpath = vhffsfs_realpath(path, NULL, NULL, R_OK);
+ if(!rpath) return -errno;
res = llistxattr(rpath, list, size);
free(rpath);
@@ -1768,8 +1954,8 @@
int res;
char *rpath;
- rpath = vhffsfs_realpath(path, NULL, NULL);
- if(!rpath) return -ENOENT;
+ rpath = vhffsfs_realpath(path, NULL, NULL, W_OK);
+ if(!rpath) return -errno;
res = lremovexattr(rpath, name);
free(rpath);
Modified: trunk/vhffs-fs/vhffsfs_run
===================================================================
--- trunk/vhffs-fs/vhffsfs_run 2010-09-06 19:50:23 UTC (rev 1623)
+++ trunk/vhffs-fs/vhffsfs_run 2010-09-06 23:16:04 UTC (rev 1624)
@@ -1,2 +1,2 @@
#!/bin/sh
-./vhffsfs -o allow_other,default_permissions,kernel_cache /mnt/fuse/
+./vhffsfs -o allow_other,hard_remove,readdir_ino,use_ino,noauto_cache,entry_timeout=0,negative_timeout=0,attr_timeout=0,ac_attr_timeout=0,intr /mnt/fuse/