[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/


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/