Basic authn check (based only on the user name and catalog path).
authorFrantišek Dvořák <valtri@civ.zcu.cz>
Thu, 17 Oct 2013 19:25:07 +0000 (21:25 +0200)
committerFrantišek Dvořák <valtri@civ.zcu.cz>
Thu, 17 Oct 2013 19:25:07 +0000 (21:25 +0200)
src/VfsNs.cpp
src/VfsNs.h

index b78650e..538567d 100644 (file)
@@ -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<Replica> 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<Replica> 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;
index c0f4a9a..7dcf6db 100644 (file)
@@ -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_;