summaryrefslogtreecommitdiff
path: root/netfs/daemon
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2016-02-14 19:06:41 +0000
committerDan Goodliffe <dan@randomdan.homeip.net>2016-02-14 19:06:41 +0000
commita10dec76b856876039ce80ec0f26c9a5141bcab2 (patch)
tree148c4d737bca3b30a95f7bf75ee18b705a297004 /netfs/daemon
parentCreate test export in bin dir, not root dir (diff)
downloadnetfs-a10dec76b856876039ce80ec0f26c9a5141bcab2.tar.bz2
netfs-a10dec76b856876039ce80ec0f26c9a5141bcab2.tar.xz
netfs-a10dec76b856876039ce80ec0f26c9a5141bcab2.zip
Replace first level permission checks and path resolution/normalization
Diffstat (limited to 'netfs/daemon')
-rw-r--r--netfs/daemon/daemonVolume.cpp50
-rw-r--r--netfs/daemon/modeCheck.cpp19
-rw-r--r--netfs/daemon/modeCheck.h2
3 files changed, 55 insertions, 16 deletions
diff --git a/netfs/daemon/daemonVolume.cpp b/netfs/daemon/daemonVolume.cpp
index a84c2e1..2d67272 100644
--- a/netfs/daemon/daemonVolume.cpp
+++ b/netfs/daemon/daemonVolume.cpp
@@ -48,7 +48,7 @@ VolumeServer::access(const NetFS::ReqEnv & re, const std::string & path, Ice::In
// stat succeeded, file must exist
return 0;
}
- mc.AssertRead(p.parent_path());
+ mc.AssertReadParent(p);
if (mode & R_OK && !mc.ReadableBy(s, mc.myu, mc.myg)) {
return EACCES;
}
@@ -67,7 +67,7 @@ VolumeServer::getattr(const NetFS::ReqEnv & re, const std::string & path, const
ModeCheck mc(re, root, userLookup, groupLookup);
struct stat s;
boost::filesystem::path p(resolvePath(path));
- mc.AssertRead(p.parent_path());
+ mc.AssertReadParent(p);
if (::lstat(p.c_str(), &s) != 0) {
throw NetFS::SystemError(errno);
}
@@ -82,7 +82,7 @@ VolumeServer::mknod(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.parent_path());
+ mc.AssertWriteParent(p);
if (::mknod(p.c_str(), mode, dev) != 0) {
throw NetFS::SystemError(errno);
}
@@ -94,7 +94,7 @@ VolumeServer::symlink(const NetFS::ReqEnv & re, const std::string & path1, const
ModeCheck mc(re, root, userLookup, groupLookup);
errno = 0;
boost::filesystem::path p(resolvePath(path2));
- mc.AssertWrite(p.parent_path());
+ mc.AssertWriteParent(p);
if (::symlink(path1.c_str(), p.c_str()) != 0) {
throw NetFS::SystemError(errno);
}
@@ -127,13 +127,13 @@ VolumeServer::rename(const NetFS::ReqEnv & re, const std::string & from, const s
errno = 0;
boost::filesystem::path f(resolvePath(from));
boost::filesystem::path t(resolvePath(to));
- mc.AssertWrite(f.parent_path());
+ mc.AssertWriteParent(f);
mc.AssertWrite(f);
if (boost::filesystem::is_directory(t)) {
mc.AssertWrite(t);
}
else {
- mc.AssertWrite(t.parent_path());
+ mc.AssertWriteParent(t);
}
if (::rename(f.c_str(), t.c_str()) != 0) {
throw NetFS::SystemError(errno);
@@ -232,7 +232,7 @@ VolumeServer::unlink(const NetFS::ReqEnv & re, const std::string & path, const I
errno = 0;
boost::filesystem::path p(resolvePath(path));
mc.AssertWrite(p);
- mc.AssertWrite(p.parent_path());
+ mc.AssertWriteParent(p);
if (::unlink(p.c_str()) != 0) {
throw NetFS::SystemError(errno);
}
@@ -261,7 +261,7 @@ VolumeServer::create(const NetFS::ReqEnv & re, const std::string & path, Ice::In
ModeCheck mc(re, root, userLookup, groupLookup);
errno = 0;
boost::filesystem::path p(resolvePath(path));
- mc.AssertWrite(p.parent_path());
+ mc.AssertWriteParent(p);
int fd = ::open(p.c_str(), O_CREAT | flags, mode);
if (fd == -1) {
throw NetFS::SystemError(errno);
@@ -294,7 +294,7 @@ VolumeServer::mkdir(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.parent_path());
+ mc.AssertWriteParent(p);
if (::mkdir(p.c_str(), mode) != 0) {
throw NetFS::SystemError(errno);
}
@@ -311,20 +311,38 @@ VolumeServer::rmdir(const NetFS::ReqEnv & re, const std::string & path, const Ic
errno = 0;
boost::filesystem::path p(resolvePath(path));
mc.AssertWrite(p);
- mc.AssertWrite(p.parent_path());
+ mc.AssertWriteParent(p);
if (::rmdir(p.c_str()) != 0) {
throw NetFS::SystemError(errno);
}
}
boost::filesystem::path
-VolumeServer::resolvePath(const std::string & path) const
+normalizedAppend(boost::filesystem::path out, const boost::filesystem::path & in)
{
- Lock(lock);
- auto p((root / path).normalize());
- if (!boost::algorithm::starts_with(p.string(), root.string())) {
- throw NetFS::SystemError(EPERM);
+ unsigned int depth = 0;
+ for(auto e : in) {
+ if (e.empty() || e == "." || e == "/") {
+ continue;
+ }
+ else if (e == "..") {
+ if (depth == 0) {
+ throw NetFS::SystemError(EPERM);
+ }
+ out.remove_leaf();
+ depth -= 1;
+ }
+ else {
+ out /= e;
+ depth += 1;
+ }
}
- return p;
+ return out;
+}
+
+boost::filesystem::path
+VolumeServer::resolvePath(const std::string & path) const
+{
+ return normalizedAppend(root, path);
}
diff --git a/netfs/daemon/modeCheck.cpp b/netfs/daemon/modeCheck.cpp
index 8468f52..dd1464c 100644
--- a/netfs/daemon/modeCheck.cpp
+++ b/netfs/daemon/modeCheck.cpp
@@ -12,6 +12,14 @@ ModeCheck::ModeCheck(const NetFS::ReqEnv & re, const boost::filesystem::path & r
}
void
+ModeCheck::AssertReadParent(const boost::filesystem::path & p) const
+{
+ if (p != root) {
+ AssertRead(p.parent_path());
+ }
+}
+
+void
ModeCheck::AssertRead(const boost::filesystem::path & p) const
{
if (p != root) {
@@ -23,6 +31,17 @@ ModeCheck::AssertRead(const boost::filesystem::path & p) const
}
void
+ModeCheck::AssertWriteParent(const boost::filesystem::path & p) const
+{
+ if (p != root) {
+ AssertWrite(p.parent_path());
+ }
+ else {
+ throw NetFS::SystemError(EACCES);
+ }
+}
+
+void
ModeCheck::AssertWrite(const boost::filesystem::path & p) const
{
if (p != root) {
diff --git a/netfs/daemon/modeCheck.h b/netfs/daemon/modeCheck.h
index d43fa2f..6c3ee2c 100644
--- a/netfs/daemon/modeCheck.h
+++ b/netfs/daemon/modeCheck.h
@@ -10,7 +10,9 @@ class ModeCheck {
public:
ModeCheck(const NetFS::ReqEnv & re, const boost::filesystem::path &, const EntCache<User> &, const EntCache<Group> &);
+ void AssertReadParent(const boost::filesystem::path &) const;
void AssertRead(const boost::filesystem::path &) const;
+ void AssertWriteParent(const boost::filesystem::path &) const;
void AssertWrite(const boost::filesystem::path &) const;
const uid_t myu;