From f4bd0adddb06b472320143cf8744ba889c02e3d7 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Franti=C5=A1ek=20Dvo=C5=99=C3=A1k?= Date: Thu, 17 Oct 2013 21:25:07 +0200 Subject: [PATCH] Basic authn check (based only on the user name and catalog path). --- src/VfsNs.cpp | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- src/VfsNs.h | 1 + 2 files changed, 88 insertions(+), 13 deletions(-) diff --git a/src/VfsNs.cpp b/src/VfsNs.cpp index b78650e..538567d 100644 --- a/src/VfsNs.cpp +++ b/src/VfsNs.cpp @@ -100,6 +100,9 @@ void VfsCatalog::changeDir(const std::string& path) throw (DmException) ExtendedStat meta; std::string lpath; + if (vfsCheckPermissions(path, S_IEXEC | S_IREAD)) + vfsThrow(EACCES, "not enough permissions for '%s'", clientName.c_str()); + meta = this->extendedStat(path); if (checkPermissions(this->secCtx_, meta.acl, meta.stat, S_IEXEC | S_IREAD) != 0) vfsThrow(EACCES, "not enough permissions for '%s' on '%s'", clientName.c_str(), meta.name.c_str()); @@ -116,6 +119,9 @@ std::string VfsCatalog::getWorkingDir(void) throw (DmException) char buffer[1024]; size_t len; + if (vfsCheckPermissions("", S_IREAD)) + vfsThrow(EACCES, "not enough permissions for '%s'", clientName.c_str()); + wrapCall(getcwd(buffer, sizeof(buffer))); len = strlen(buffer); @@ -198,6 +204,9 @@ ExtendedStat VfsCatalog::extendedStat(const std::string& path, bool follow) thro ExtendedStat meta; Extensible xattrs; + if (vfsCheckPermissions(path, S_IREAD)) + vfsThrow(EACCES, "not enough permissions for '%s'", clientName.c_str()); + meta = vfsExtendedStat(path, follow); // not require working xattrs @@ -240,6 +249,9 @@ bool VfsCatalog::access(const std::string& path, int mode) throw (DmException) ExtendedStat meta; mode_t perm; + if (vfsCheckPermissions(path, S_IREAD)) + vfsThrow(EACCES, "not enough permissions for '%s'", clientName.c_str()); + try { meta = this->extendedStat(path); @@ -294,8 +306,12 @@ void VfsCatalog::deleteReplica(const Replica& replica) throw (DmException) std::vector VfsCatalog::getReplicas(const std::string& path) throw (DmException) { Replica replica; - ExtendedStat xStat = this->extendedStat(path, true); + ExtendedStat xStat; + if (vfsCheckPermissions(path, S_IREAD)) + vfsThrow(EACCES, "not enough permissions for '%s'", clientName.c_str()); + + xStat = this->extendedStat(path, true); if (checkPermissions(this->secCtx_, xStat.acl, xStat.stat, S_IREAD) != 0) vfsThrow(EACCES, "not enough permissions for '%s' to read '%s'", clientName.c_str(), path.c_str()); @@ -327,9 +343,13 @@ std::vector VfsCatalog::getReplicas(const std::string& path) throw (DmE void VfsCatalog::symlink(const std::string& oldPath, const std::string& newPath) throw (DmException) { std::string parentPath, symName; + ExtendedStat parent; - ExtendedStat parent = this->getParent(newPath, &parentPath, &symName); + if (vfsCheckPermissions(oldPath, S_IWRITE) || + vfsCheckPermissions(newPath, S_IWRITE)) + vfsThrow(EACCES, "not enough permissions for '%s'", clientName.c_str()); + parent = this->getParent(newPath, &parentPath, &symName); if (checkPermissions(this->secCtx_, parent.acl, parent.stat, S_IWRITE | S_IEXEC) != 0) vfsThrow(EACCES, "not enough permissions for '%s' on '%s'", clientName.c_str(), parentPath.c_str()); @@ -340,9 +360,13 @@ void VfsCatalog::symlink(const std::string& oldPath, const std::string& newPath) std::string VfsCatalog::readLink(const std::string& path) throw (DmException) { - ExtendedStat meta = this->extendedStat(path, false); + ExtendedStat meta; char *buf; + if (vfsCheckPermissions(path, S_IREAD)) + vfsThrow(EACCES, "not enough permissions for '%s'", clientName.c_str()); + + meta = this->vfsExtendedStat(path, false); if (checkPermissions(this->secCtx_, meta.acl, meta.stat, S_IREAD) != 0) vfsThrow(EACCES, "not enough permissions for '%s' on '%s'", clientName.c_str(), path.c_str()); @@ -362,6 +386,9 @@ void VfsCatalog::unlink(const std::string& path) throw (DmException) { std::string parentPath, name; + if (vfsCheckPermissions(path, S_IWRITE)) + vfsThrow(EACCES, "not enough permissions for '%s'", clientName.c_str()); + ExtendedStat parent = this->getParent(path, &parentPath, &name); if (checkPermissions(this->secCtx_, parent.acl, parent.stat, S_IEXEC) != 0) @@ -390,6 +417,9 @@ void VfsCatalog::create(const std::string& path, mode_t mode) throw (DmException int code = DMLITE_SUCCESS; ExtendedStat file; + if (vfsCheckPermissions(path, S_IWRITE)) + vfsThrow(EACCES, "not enough permissions for '%s'", clientName.c_str()); + ExtendedStat parent = this->getParent(path, &parentPath, &name); if (checkPermissions(this->secCtx_, parent.acl, parent.stat, S_IEXEC) != 0) @@ -442,6 +472,9 @@ void VfsCatalog::create(const std::string& path, mode_t mode) throw (DmException mode_t VfsCatalog::umask(mode_t mask) throw () { + if (vfsCheckPermissions("", S_IREAD)) + vfsThrow(EACCES, "not enough permissions for '%s'", clientName.c_str()); + return ::umask(mask); } @@ -451,10 +484,10 @@ void VfsCatalog::setMode(const std::string& path, mode_t mode) throw (DmExceptio { ExtendedStat meta; - if (!this->allowWriteCurrent) - vfsThrow(EACCES, "not enough permissions for '%s' to setting mode", clientName.c_str()); + if (vfsCheckPermissions(path, S_IWRITE)) + vfsThrow(EACCES, "not enough permissions for '%s'", clientName.c_str()); - meta = this->extendedStat(path); + meta = this->vfsExtendedStat(path, true); // User has to be the owner, or root if (getUid(this->secCtx_) != meta.stat.st_uid && @@ -482,8 +515,12 @@ void VfsCatalog::setOwner(const std::string& path, uid_t newUid, gid_t newGid, b void VfsCatalog::setSize(const std::string& path, size_t newSize) throw (DmException) { - ExtendedStat file = this->extendedStat(path); + ExtendedStat file; + if (vfsCheckPermissions(path, S_IWRITE)) + vfsThrow(EACCES, "not enough permissions for '%s'", clientName.c_str()); + + file = this->extendedStat(path); if (S_ISDIR(file.stat.st_mode)) vfsThrow(EISDIR, "'%s' is directory, can not truncate", path.c_str()); if (getUid(this->secCtx_) != file.stat.st_uid && @@ -513,8 +550,12 @@ void VfsCatalog::setAcl(const std::string& path, const Acl& acl) throw (DmExcept void VfsCatalog::utime(const std::string& path, const struct utimbuf* buf) throw (DmException) { - ExtendedStat meta = this->extendedStat(path); + ExtendedStat meta; + if (vfsCheckPermissions(path, S_IWRITE)) + vfsThrow(EACCES, "not enough permissions for '%s'", clientName.c_str()); + + meta = this->extendedStat(path); if (getUid(this->secCtx_) != meta.stat.st_uid && checkPermissions(this->secCtx_, meta.acl, meta.stat, S_IWRITE) != 0) { vfsThrow(EACCES, "not enough permissions for '%s' to modify the time of '%s'", clientName.c_str(), path.c_str()); @@ -558,6 +599,9 @@ void VfsCatalog::updateExtendedAttributes(const std::string& path, std::string key, value, oldvalue; std::string lpath; + if (vfsCheckPermissions(path, S_IWRITE)) + vfsThrow(EACCES, "not enough permissions for '%s'", clientName.c_str()); + meta = this->extendedStat(path, true); if (checkPermissions(this->secCtx_, meta.acl, meta.stat, S_IWRITE) != 0) vfsThrow(EACCES, "not enough permissions for '%s' to change attributes on '%s'", clientName.c_str(), path.c_str()); @@ -623,6 +667,9 @@ Directory* VfsCatalog::openDir(const std::string& path) throw (DmException) ExtendedStat meta; std::string lpath; + if (vfsCheckPermissions(path, S_IREAD)) + vfsThrow(EACCES, "not enough permissions for '%s'", clientName.c_str()); + meta = this->extendedStat(path); if (checkPermissions(this->secCtx_, meta.acl, meta.stat, S_IREAD) != 0) vfsThrow(EACCES, "not enough permissions for '%s' to read '%s'", clientName.c_str(), path.c_str()); @@ -702,6 +749,9 @@ void VfsCatalog::makeDir(const std::string& path, mode_t mode) throw (DmExceptio { std::string parentPath, name; + if (vfsCheckPermissions(path, S_IWRITE)) + vfsThrow(EACCES, "not enough permissions for '%s'", clientName.c_str()); + if (path.empty()) vfsThrow(EINVAL, "empty directory name"); @@ -725,6 +775,10 @@ void VfsCatalog::rename(const std::string& oldPath, const std::string& newPath) { std::string oldParentPath, newParentPath, oldName, newName; + if (vfsCheckPermissions(oldPath, S_IWRITE) || + vfsCheckPermissions(newPath, S_IWRITE)) + vfsThrow(EACCES, "not enough permissions for '%s'", clientName.c_str()); + if (oldPath == "/" || newPath == "/") vfsThrow(EINVAL, "not the source, neither the destination, can be '/'"); @@ -761,6 +815,9 @@ void VfsCatalog::removeDir(const std::string& path) throw (DmException) char *cwd = NULL, *rmd = NULL; std::string parentPath, name; + if (vfsCheckPermissions(path, S_IWRITE)) + vfsThrow(EACCES, "not enough permissions for '%s'", clientName.c_str()); + if (path == "/") vfsThrow(EINVAL, "can not remove '/'"); @@ -807,6 +864,9 @@ Replica VfsCatalog::getReplicaByRFN(const std::string& rfn) throw (DmException) Replica replica; struct stat fstat; + if (vfsCheckPermissions(rfn, S_IREAD)) + vfsThrow(EACCES, "not enough permissions for '%s'", clientName.c_str()); + wrapCall(stat(getLocalPath(rfn).c_str(), &fstat)); replica.atime = fstat.st_atime; @@ -870,17 +930,31 @@ const std::string VfsCatalog::getLocalPath(const std::string &path) { -int VfsCatalog::checkPermissions(const SecurityContext *context, const Acl &acl, const struct stat &stat, mode_t mode) { -//fprintf(stderr, "VfsCatalog::checkPermissions(inode %lu, %04o)\n", stat.st_ino, mode); +/// +/// Basic permissions check, to be called before stat(). +/// +int VfsCatalog::vfsCheckPermissions(const std::string& path, mode_t mode) { + int ret = 1; + if (this->allowCurrent) { - if ((mode & S_IWRITE) != 0) return this->allowWriteCurrent ? 0 : 1; + if ((mode & S_IWRITE) != 0) ret = this->allowWriteCurrent ? 0 : 1; else return 0; - } else { - return 1; } + + return ret; } + +/// +/// override all permission checks - no file-level permissions in zero version +/// +int VfsCatalog::checkPermissions(const SecurityContext *context, const Acl &acl, const struct stat &stat, mode_t mode) { + return 0; +} + + + Extensible VfsCatalog::vfsGetXattrs(const std::string& path, const std::string& lpath, bool follow) throw (DmException) { int len; std::string attrValue; diff --git a/src/VfsNs.h b/src/VfsNs.h index c0f4a9a..7dcf6db 100644 --- a/src/VfsNs.h +++ b/src/VfsNs.h @@ -107,6 +107,7 @@ namespace dmlite { void vfsSetXattr(const std::string& path, const std::string& lpath, const std::string key, const std::string value, int flags); regex_t *vfsCompileRegex(const char *name, const std::string value) throw (DmException); bool vfsEvalRegex(regex_t *allowRegex, regex_t *denyRegex, const char *subj); + int vfsCheckPermissions(const std::string& path, mode_t mode); StackInstance* si_; const SecurityContext* secCtx_; -- 1.8.2.3