diff options
| -rw-r--r-- | netfs/daemon/daemonVolume.cpp | 2 | ||||
| -rw-r--r-- | netfs/daemon/modeCheck.cpp | 12 | ||||
| -rw-r--r-- | netfs/daemon/modeCheck.h | 1 | ||||
| -rw-r--r-- | netfs/unittests/testCore.cpp | 30 | 
4 files changed, 44 insertions, 1 deletions
diff --git a/netfs/daemon/daemonVolume.cpp b/netfs/daemon/daemonVolume.cpp index e4c65bd..5064b5b 100644 --- a/netfs/daemon/daemonVolume.cpp +++ b/netfs/daemon/daemonVolume.cpp @@ -161,7 +161,7 @@ VolumeServer::chmod(const NetFS::ReqEnv & re, const std::string & path, Ice::Int  	ModeCheck mc(re, root, userLookup, groupLookup);  	errno = 0;  	boost::filesystem::path p(resolvePath(path)); -	mc.AssertWrite(p); +	mc.AssertWritePerms(p);  	if (::chmod(p.c_str(), mode) != 0) {  		throw NetFS::SystemError(errno);  	} diff --git a/netfs/daemon/modeCheck.cpp b/netfs/daemon/modeCheck.cpp index dd1464c..df409bf 100644 --- a/netfs/daemon/modeCheck.cpp +++ b/netfs/daemon/modeCheck.cpp @@ -52,6 +52,18 @@ ModeCheck::AssertWrite(const boost::filesystem::path & p) const  	}  } +void +ModeCheck::AssertWritePerms(const boost::filesystem::path & p) const +{ +	if (p != root) { +		AssertRead(p.parent_path()); +	} +	auto s = lstat(p); +	if (s.st_uid != myu && !WritableBy(s, myu, myg)) { +		throw NetFS::SystemError(EACCES); +	} +} +  struct stat  ModeCheck::lstat(const boost::filesystem::path & p)  { diff --git a/netfs/daemon/modeCheck.h b/netfs/daemon/modeCheck.h index 6c3ee2c..54a82e2 100644 --- a/netfs/daemon/modeCheck.h +++ b/netfs/daemon/modeCheck.h @@ -14,6 +14,7 @@ class ModeCheck {  		void AssertRead(const boost::filesystem::path &) const;  		void AssertWriteParent(const boost::filesystem::path &) const;  		void AssertWrite(const boost::filesystem::path &) const; +		void AssertWritePerms(const boost::filesystem::path &) const;  		const uid_t myu;  		const gid_t myg; diff --git a/netfs/unittests/testCore.cpp b/netfs/unittests/testCore.cpp index 8a0d38b..fb41f65 100644 --- a/netfs/unittests/testCore.cpp +++ b/netfs/unittests/testCore.cpp @@ -251,6 +251,36 @@ BOOST_AUTO_TEST_CASE( symlinks )  	BOOST_REQUIRE_EQUAL(fuse->unlink("/test3"), -ENOENT);  } +BOOST_AUTO_TEST_CASE( access ) +{ +	struct stat st; +	memset(&st, 0, sizeof(st)); +	BOOST_REQUIRE_EQUAL(fuse->access("/", F_OK), 0); +	BOOST_REQUIRE_EQUAL(fuse->access("/missing", F_OK), -ENOENT); +	BOOST_REQUIRE_EQUAL(fuse->mkdir("/dir", 0700), 0); +	BOOST_REQUIRE_EQUAL(fuse->getattr("/dir", &st), 0); +	BOOST_REQUIRE_EQUAL(st.st_mode, 0700 | S_IFDIR); +	BOOST_REQUIRE_EQUAL(fuse->access("/dir", F_OK), 0); +	BOOST_REQUIRE_EQUAL(fuse->access("/dir", R_OK), 0); +	BOOST_REQUIRE_EQUAL(fuse->access("/dir", W_OK), 0); +	BOOST_REQUIRE_EQUAL(fuse->access("/dir", X_OK), 0); +	BOOST_REQUIRE_EQUAL(fuse->chmod("/dir", 0000), 0); +	BOOST_REQUIRE_EQUAL(fuse->getattr("/dir", &st), 0); +	BOOST_REQUIRE_EQUAL(st.st_mode, 0000 | S_IFDIR); +	BOOST_REQUIRE_EQUAL(fuse->access("/dir", F_OK), 0); +	BOOST_REQUIRE_EQUAL(fuse->access("/dir", R_OK), -EACCES); +	BOOST_REQUIRE_EQUAL(fuse->access("/dir", W_OK), -EACCES); +	BOOST_REQUIRE_EQUAL(fuse->access("/dir", X_OK), -EACCES); +	BOOST_REQUIRE_EQUAL(fuse->chmod("/dir", 0500), 0); +	BOOST_REQUIRE_EQUAL(fuse->getattr("/dir", &st), 0); +	BOOST_REQUIRE_EQUAL(st.st_mode, 0500 | S_IFDIR); +	BOOST_REQUIRE_EQUAL(fuse->rmdir("/dir"), -EACCES); +	BOOST_REQUIRE_EQUAL(fuse->chmod("/dir", 0700), 0); +	BOOST_REQUIRE_EQUAL(fuse->getattr("/dir", &st), 0); +	BOOST_REQUIRE_EQUAL(st.st_mode, 0700 | S_IFDIR); +	BOOST_REQUIRE_EQUAL(fuse->rmdir("/dir"), 0); +} +  BOOST_AUTO_TEST_SUITE_END();  BOOST_AUTO_TEST_CASE( testNoAuthNoPass )  | 
