From 5ac59f1ee793d7dcc8ef074b653f06ba1a9ae6b1 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Franti=C5=A1ek=20Dvo=C5=99=C3=A1k?= Date: Thu, 17 Oct 2013 19:47:55 +0200 Subject: [PATCH] AllowWrite and DenyWrite config options. --- src/Vfs.cpp | 8 ++++- src/Vfs.h | 2 +- src/VfsNs.cpp | 102 ++++++++++++++++++++++++++++++++++++++-------------------- src/VfsNs.h | 8 +++-- 4 files changed, 80 insertions(+), 40 deletions(-) diff --git a/src/Vfs.cpp b/src/Vfs.cpp index ad943d7..f79d753 100644 --- a/src/Vfs.cpp +++ b/src/Vfs.cpp @@ -70,6 +70,12 @@ void VfsFactory::configure(const std::string& key, const std::string& value) thr else if (key == "Deny") { this->deny_ = value; } + else if (key == "AllowWrite") { + this->allowWrite_ = value; + } + else if (key == "DenyWrite") { + this->denyWrite_ = value; + } else if (key == "NSPrefix") { this->nsPrefix_ = value; } @@ -86,7 +92,7 @@ void VfsFactory::configure(const std::string& key, const std::string& value) thr Catalog* VfsFactory::createCatalog(PluginManager*) throw (DmException) { syslog(LOG_DEBUG, "%s", __func__); - return new VfsCatalog(this->hostName_, this->nsPrefix_, this->allow_, this->deny_); + return new VfsCatalog(this->hostName_, this->nsPrefix_, this->allow_, this->deny_, this->allowWrite_, this->denyWrite_); } diff --git a/src/Vfs.h b/src/Vfs.h index f43d56f..1f938b2 100644 --- a/src/Vfs.h +++ b/src/Vfs.h @@ -61,7 +61,7 @@ namespace dmlite { std::string tokenPasswd_; bool tokenUseIp_; unsigned tokenLife_; - std::string allow_, deny_; + std::string allow_, deny_, allowWrite_, denyWrite_; private: std::string getImplId(void) const throw (); diff --git a/src/VfsNs.cpp b/src/VfsNs.cpp index 855f043..26793dd 100644 --- a/src/VfsNs.cpp +++ b/src/VfsNs.cpp @@ -32,29 +32,14 @@ static gid_t getGid(const SecurityContext* ctx) { } -VfsCatalog::VfsCatalog(const std::string& host, const std::string& prefix, const std::string &allow, const std::string &deny) throw (DmException): Catalog(), + +VfsCatalog::VfsCatalog(const std::string& host, const std::string& prefix, const std::string &allow, const std::string &deny, const std::string allowWrite, const std::string denyWrite) throw (DmException): Catalog(), hostName_(host), prefix_(prefix) { - regex_t regex; - int ret; - char buf[256]; - - this->allowRegex = 0; - if (!allow.empty()) { -//fprintf(stderr, "allow regex: '%s'\n", allow.c_str()); - if ((ret = regcomp(®ex, allow.c_str(), REG_EXTENDED | REG_NOSUB)) != 0) { - regerror(ret, ®ex, buf, sizeof buf); - vfsThrow(EINVAL, "invalid regular expresion for 'Allow': %s", buf); - } - this->allowRegex = new regex_t(regex); - } - this->denyRegex = 0; - if (!deny.empty()) { -//fprintf(stderr, "deny regex: '%s'\n", deny.c_str()); - if ((ret = regcomp(®ex, deny.c_str(), REG_EXTENDED | REG_NOSUB)) != 0) - vfsThrow(EINVAL, "invalid regular expresion for 'Deny': %s", buf); - this->denyRegex = new regex_t(regex); - } + this->allowRegex = vfsCompileRegex("Allow", allow); + this->denyRegex = vfsCompileRegex("Deny", deny); + this->allowWriteRegex = vfsCompileRegex("AllowWrite", allowWrite); + this->denyWriteRegex = vfsCompileRegex("DenyWrite", denyWrite); if (prefix.empty()) this->prefix_ = ""; } @@ -71,6 +56,14 @@ VfsCatalog::~VfsCatalog() regfree(this->denyRegex); delete this->denyRegex; } + if (this->allowWriteRegex) { + regfree(this->allowWriteRegex); + delete this->allowWriteRegex; + } + if (this->denyWriteRegex) { + regfree(this->denyWriteRegex); + delete this->denyWriteRegex; + } } @@ -93,20 +86,11 @@ void VfsCatalog::setSecurityContext(const SecurityContext* ctx) throw (DmExcepti { std::string subj = ctx->credentials.clientName; secCtx_ = ctx; - int ret; this->clientName = subj; - this->allowCurrent = false; - if (this->allowRegex) { - if ((ret = regexec(this->allowRegex, subj.c_str(), 0, NULL, 0)) == 0) - this->allowCurrent = true; -//fprintf(stderr, "'%s' %s allow regexp\n", subj.c_str(), ((ret == 0) ? "matches" : "not matches")); - } - if (this->allowCurrent && this->denyRegex) { - if ((ret = regexec(this->denyRegex, subj.c_str(), 0, NULL, 0)) == 0) - this->allowCurrent = false; -//fprintf(stderr, "'%s' %s deny regexp\n", subj.c_str(), (ret == 0) ? "matches" : "not matches"); - } + + this->allowCurrent = vfsEvalRegex(this->allowRegex, this->denyRegex, subj.c_str()); + this->allowWriteCurrent = vfsEvalRegex(this->allowWriteRegex, this->denyWriteRegex, subj.c_str()); } @@ -438,7 +422,12 @@ mode_t VfsCatalog::umask(mode_t mask) throw () void VfsCatalog::setMode(const std::string& path, mode_t mode) throw (DmException) { - ExtendedStat meta = this->extendedStat(path); + ExtendedStat meta; + + if (!this->allowWriteCurrent) + vfsThrow(EACCES, "not enough permissions for '%s' to setting mode", clientName.c_str()); + + meta = this->extendedStat(path); // User has to be the owner, or root if (getUid(this->secCtx_) != meta.stat.st_uid && @@ -845,7 +834,12 @@ 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); - return this->allowCurrent ? 0 : 1; + if (this->allowCurrent) { + if ((mode & S_IWRITE) != 0) return this->allowWriteCurrent ? 0 : 1; + else return 0; + } else { + return 1; + } } @@ -878,3 +872,41 @@ Extensible VfsCatalog::vfsGetXattrs(const std::string& path, const std::string& return xattrs; } + + + +regex_t *VfsCatalog::vfsCompileRegex(const char *name, const std::string value) throw (DmException) { + regex_t regex; + int ret; + char buf[256]; + + if (value.empty()) return 0; + + //syslog(LOG_DEBUG, "%s: %s regex: '%s'\n", __func__, name, value.c_str()); + if ((ret = regcomp(®ex, value.c_str(), REG_EXTENDED | REG_NOSUB)) != 0) { + regerror(ret, ®ex, buf, sizeof buf); + vfsThrow(EINVAL, "invalid regular expresion for '%s': %s", name, buf); + } + + return new regex_t(regex); +} + + + +bool VfsCatalog::vfsEvalRegex(regex_t *allowRegex, regex_t *denyRegex, const char *subj) { + bool allow = false; + int ret; + + if (allowRegex) { + if ((ret = regexec(allowRegex, subj, 0, NULL, 0)) == 0) + allow = true; + //fprintf(stderr, "'%s' %s allow regexp\n", subj.c_str(), ((ret == 0) ? "matches" : "not matches")); + } + if (allow && denyRegex) { + if ((ret = regexec(denyRegex, subj, 0, NULL, 0)) == 0) + allow = false; + //fprintf(stderr, "'%s' %s deny regexp\n", subj.c_str(), (ret == 0) ? "matches" : "not matches"); + } + + return allow; +} diff --git a/src/VfsNs.h b/src/VfsNs.h index 9015757..20c2477 100644 --- a/src/VfsNs.h +++ b/src/VfsNs.h @@ -28,7 +28,7 @@ namespace dmlite { public: /// Constructor /// @param retryLimit Limit of retrials. - VfsCatalog(const std::string& host, const std::string& prefix, const std::string& allow, const std::string& deny) throw (DmException); + VfsCatalog(const std::string& host, const std::string& prefix, const std::string& allow, const std::string& deny, const std::string allowWrite, const std::string denyWrite) throw (DmException); /// Destructor ~VfsCatalog(); @@ -108,6 +108,8 @@ namespace dmlite { ExtendedStat vfsExtendedStat(const std::string& name, const std::string& path, bool follow) throw (DmException); PrivateDir* vfsOpenDir(const std::string& lpath, const std::string& path) throw (DmException); Extensible vfsGetXattrs(const std::string& path, const std::string& lpath, bool follow) throw (DmException); + regex_t *vfsCompileRegex(const char *name, const std::string value) throw (DmException); + bool vfsEvalRegex(regex_t *allowRegex, regex_t *denyRegex, const char *subj); StackInstance* si_; const SecurityContext* secCtx_; @@ -117,8 +119,8 @@ namespace dmlite { private: int checkPermissions(const SecurityContext *context, const Acl &acl, const struct stat &stat, mode_t mode); - regex_t *allowRegex, *denyRegex; - bool allowCurrent; + regex_t *allowRegex, *denyRegex, *allowWriteRegex, *denyWriteRegex; + bool allowCurrent, allowWriteCurrent; std::string clientName; char xattrBuffer[1024], xattrValue[1024]; -- 1.8.2.3