AllowWrite and DenyWrite config options.
authorFrantišek Dvořák <valtri@civ.zcu.cz>
Thu, 17 Oct 2013 17:47:55 +0000 (19:47 +0200)
committerFrantišek Dvořák <valtri@civ.zcu.cz>
Thu, 17 Oct 2013 17:47:55 +0000 (19:47 +0200)
src/Vfs.cpp
src/Vfs.h
src/VfsNs.cpp
src/VfsNs.h

index ad943d7..f79d753 100644 (file)
@@ -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_);
 }
 
 
index f43d56f..1f938b2 100644 (file)
--- 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 ();
index 855f043..26793dd 100644 (file)
@@ -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(&regex, allow.c_str(), REG_EXTENDED | REG_NOSUB)) != 0) {
-      regerror(ret, &regex, 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(&regex, 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(&regex, value.c_str(), REG_EXTENDED | REG_NOSUB)) != 0) {
+    regerror(ret, &regex, 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;
+}
index 9015757..20c2477 100644 (file)
@@ -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];