From a37ec13b8d9736d90b2ef38216c2a85156de838a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Franti=C5=A1ek=20Dvo=C5=99=C3=A1k?= Date: Tue, 15 Oct 2013 13:16:54 +0200 Subject: [PATCH] More verbose permission error messages. --- src/VfsNs.cpp | 45 +++++++++++++++++++++++---------------------- src/VfsNs.h | 1 + 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/src/VfsNs.cpp b/src/VfsNs.cpp index 08bc0a8..7308c8b 100644 --- a/src/VfsNs.cpp +++ b/src/VfsNs.cpp @@ -92,6 +92,7 @@ void VfsCatalog::setSecurityContext(const SecurityContext* ctx) throw (DmExcepti 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) @@ -101,7 +102,7 @@ void VfsCatalog::setSecurityContext(const SecurityContext* ctx) throw (DmExcepti 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"); +//fprintf(stderr, "'%s' %s deny regexp\n", subj.c_str(), (ret == 0) ? "matches" : "not matches"); } } @@ -167,7 +168,7 @@ ExtendedStat VfsCatalog::extendedStat(const std::string& path, bool follow) thro meta = vfsExtendedStat(components[i], dir, true); if (checkPermissions(this->secCtx_, meta.acl, meta.stat, S_IEXEC) != 0) - vfsThrow(EACCES, "not enough permissions to list '%s'", meta.name.c_str()); + vfsThrow(EACCES, "not enough permissions for '%s' to list '%s'", clientName.c_str(), meta.name.c_str()); } meta = vfsExtendedStat(components.back(), path, follow); @@ -258,7 +259,7 @@ std::vector VfsCatalog::getReplicas(const std::string& path) throw (DmE ExtendedStat xStat = this->extendedStat(path, true); if (checkPermissions(this->secCtx_, xStat.acl, xStat.stat, S_IREAD) != 0) - vfsThrow(EACCES, "not enough permissions to read '%s'", path.c_str()); + vfsThrow(EACCES, "not enough permissions for '%s' to read '%s'", clientName.c_str(), path.c_str()); if (S_ISDIR(xStat.stat.st_mode)) vfsThrow(EISDIR, "directories do not have replicas"); @@ -292,7 +293,7 @@ void VfsCatalog::symlink(const std::string& oldPath, const std::string& newPath) ExtendedStat parent = this->getParent(newPath, &parentPath, &symName); if (checkPermissions(this->secCtx_, parent.acl, parent.stat, S_IWRITE | S_IEXEC) != 0) - vfsThrow(EACCES, "not enough permissions on '%s'", parentPath.c_str()); + vfsThrow(EACCES, "not enough permissions for '%s' on '%s'", clientName.c_str(), parentPath.c_str()); wrapCall(::symlink(oldPath.c_str(), newPath.c_str())); } @@ -305,7 +306,7 @@ std::string VfsCatalog::readLink(const std::string& path) throw (DmException) ExtendedStat meta = this->extendedStat(path, false); if (checkPermissions(this->secCtx_, meta.acl, meta.stat, S_IREAD) != 0) - vfsThrow(EACCES, "not enough permissions on '%s'", path.c_str()); + vfsThrow(EACCES, "not enough permissions for '%s' on '%s'", clientName.c_str(), path.c_str()); memset(buf, 0, sizeof(buf)); wrapCall(readlink(path.c_str(), buf, sizeof(buf) - 1)); @@ -321,16 +322,16 @@ void VfsCatalog::unlink(const std::string& path) throw (DmException) ExtendedStat parent = this->getParent(path, &parentPath, &name); if (checkPermissions(this->secCtx_, parent.acl, parent.stat, S_IEXEC) != 0) - vfsThrow(EACCES, "not enough permissions on '%s' to list", parentPath.c_str()); + vfsThrow(EACCES, "not enough permissions for '%s' on '%s' to list", clientName.c_str(), parentPath.c_str()); if (checkPermissions(this->secCtx_, parent.acl, parent.stat, S_IWRITE) != 0) - vfsThrow(EACCES, "not enough permissions on '%s' to unlink '%s'", parentPath.c_str(), path.c_str()); + vfsThrow(EACCES, "not enough permissions for '%s' on '%s' to unlink '%s'", clientName.c_str(), parentPath.c_str(), path.c_str()); // Sticky bit set ==> only directory or file owner can delete if ((parent.stat.st_mode & S_ISVTX) == S_ISVTX) { ExtendedStat file = this->extendedStat(path); if (getUid(this->secCtx_) != file.stat.st_uid && getUid(this->secCtx_) != parent.stat.st_uid) { - vfsThrow(EACCES, "not enough permissions to unlink '%s' (sticky bit set)", path.c_str()); + vfsThrow(EACCES, "not enough permissions for '%s' to unlink '%s' (sticky bit set)", clientName.c_str(), path.c_str()); } } @@ -349,9 +350,9 @@ void VfsCatalog::create(const std::string& path, mode_t mode) throw (DmException ExtendedStat parent = this->getParent(path, &parentPath, &name); if (checkPermissions(this->secCtx_, parent.acl, parent.stat, S_IEXEC) != 0) - vfsThrow(EACCES, "not enough permissions on '%s' to list", parentPath.c_str()); + vfsThrow(EACCES, "not enough permissions for '%s' on '%s' to list", clientName.c_str(), parentPath.c_str()); if (checkPermissions(this->secCtx_, parent.acl, parent.stat, S_IWRITE) != 0) - vfsThrow(EACCES, "need write access on '%s' to create '%s'", parentPath.c_str(), path.c_str()); + vfsThrow(EACCES, "need write access for '%s' on '%s' to create '%s'", clientName.c_str(), parentPath.c_str(), path.c_str()); try { file = this->extendedStat(path); @@ -385,7 +386,7 @@ void VfsCatalog::create(const std::string& path, mode_t mode) throw (DmException vfsThrow(EISDIR, "'%s' is directory, can not truncate", path.c_str()); if (getUid(this->secCtx_) != file.stat.st_uid && checkPermissions(this->secCtx_, file.acl, file.stat, S_IWRITE) != 0) { - vfsThrow(EACCES, "not enough permissions to truncate '%s'", path.c_str()); + vfsThrow(EACCES, "not enough permissions for '%s' to truncate '%s'", clientName.c_str(), path.c_str()); } wrapCall(truncate(path.c_str(), 0)); } @@ -409,7 +410,7 @@ void VfsCatalog::setMode(const std::string& path, mode_t mode) throw (DmExceptio // User has to be the owner, or root if (getUid(this->secCtx_) != meta.stat.st_uid && getUid(this->secCtx_) != 0) { - vfsThrow(EACCES, "only the owner or root can set the mode of '%s'", path.c_str()); + vfsThrow(EACCES, "'%s' neither owner nor root, setting the mode of '%s' rejected", clientName.c_str(), path.c_str()); } // Clean up unwanted bits mode &= ~S_IFMT; @@ -438,7 +439,7 @@ void VfsCatalog::setSize(const std::string& path, size_t newSize) throw (DmExcep vfsThrow(EISDIR, "'%s' is directory, can not truncate", path.c_str()); if (getUid(this->secCtx_) != file.stat.st_uid && checkPermissions(this->secCtx_, file.acl, file.stat, S_IWRITE) != 0) { - vfsThrow(EACCES, "not enough permissions to truncate '%s'", path.c_str()); + vfsThrow(EACCES, "not enough permissions for '%s' to truncate '%s'", clientName.c_str(), path.c_str()); } wrapCall(truncate(path.c_str(), newSize)); } @@ -467,7 +468,7 @@ void VfsCatalog::utime(const std::string& path, const struct utimbuf* buf) throw if (getUid(this->secCtx_) != meta.stat.st_uid && checkPermissions(this->secCtx_, meta.acl, meta.stat, S_IWRITE) != 0) { - vfsThrow(EACCES, "not enough permissions to modify the time of '%s'", path.c_str()); + vfsThrow(EACCES, "not enough permissions for '%s' to modify the time of '%s'", clientName.c_str(), path.c_str()); } wrapCall(::utime(path.c_str(), buf)); @@ -517,7 +518,7 @@ Directory* VfsCatalog::openDir(const std::string& path) throw (DmException) try { meta = this->extendedStat(path); if (checkPermissions(this->secCtx_, meta.acl, meta.stat, S_IREAD) != 0) - vfsThrow(EACCES, "not enough permissions to read '%s'", path.c_str()); + vfsThrow(EACCES, "not enough permissions for '%s' to read '%s'", clientName.c_str(), path.c_str()); privateDir->path = path; privateDir->dir = opendir(path.c_str()); @@ -592,9 +593,9 @@ void VfsCatalog::makeDir(const std::string& path, mode_t mode) throw (DmExceptio ExtendedStat parent = this->getParent(path, &parentPath, &name); if (checkPermissions(this->secCtx_, parent.acl, parent.stat, S_IEXEC) != 0) - vfsThrow(EACCES, "not enough permissions on '%s' to list", parentPath.c_str()); + vfsThrow(EACCES, "not enough permissions for '%s' on '%s' to list", clientName.c_str(), parentPath.c_str()); if (checkPermissions(this->secCtx_, parent.acl, parent.stat, S_IWRITE) != 0) - vfsThrow(EACCES, "need write access on '%s' to create directory '%s'", parentPath.c_str(), name.c_str()); + vfsThrow(EACCES, "need write access for '%s' on '%s' to create directory '%s'", clientName.c_str(), parentPath.c_str(), name.c_str()); // Clean up unwanted bits mode &= ~S_IFMT; @@ -615,9 +616,9 @@ void VfsCatalog::rename(const std::string& oldPath, const std::string& newPath) ExtendedStat oldParent = this->getParent(oldPath, &oldParentPath, &oldName); ExtendedStat newParent = this->getParent(newPath, &oldParentPath, &newName); if (checkPermissions(this->secCtx_, oldParent.acl, oldParent.stat, S_IWRITE) != 0) - vfsThrow(EACCES, "Not enough permissions on origin '%s'", oldPath.c_str()); + vfsThrow(EACCES, "Not enough permissions for '%s' on origin '%s'", clientName.c_str(), oldPath.c_str()); if (checkPermissions(this->secCtx_, newParent.acl, newParent.stat, S_IWRITE) != 0) - vfsThrow(EACCES, "Not enough permissions on destination '%s'", newPath.c_str()); + vfsThrow(EACCES, "Not enough permissions for '%s' on destination '%s'", clientName.c_str(), newPath.c_str()); // Check sticky if (oldParent.stat.st_mode & S_ISVTX) { @@ -625,7 +626,7 @@ void VfsCatalog::rename(const std::string& oldPath, const std::string& newPath) if (getUid(this->secCtx_) != oldParent.stat.st_uid && getUid(this->secCtx_) != old.stat.st_uid && checkPermissions(this->secCtx_, old.acl, old.stat, S_IWRITE) != 0) - vfsThrow(EACCES, "not enough permissions (sticky bit set on parent '%s')", oldParentPath.c_str()); + vfsThrow(EACCES, "not enough permissions for '%s' (sticky bit set on parent '%s')", clientName.c_str(), oldParentPath.c_str()); } // XXX: test-rename should probably accept both ENOTEMPTY and EEXIST instead @@ -655,11 +656,11 @@ void VfsCatalog::removeDir(const std::string& path) throw (DmException) if (getUid(this->secCtx_) != entry.stat.st_uid && getUid(this->secCtx_) != parent.stat.st_uid && checkPermissions(this->secCtx_, entry.acl, entry.stat, S_IWRITE) != 0) - vfsThrow(EACCES, "not enough permissions to remove '%s' (sticky bit set)", path.c_str()); + vfsThrow(EACCES, "not enough permissions for '%s' to remove '%s' (sticky bit set)", clientName.c_str(), path.c_str()); } else { // No sticky bit if (checkPermissions(this->secCtx_, parent.acl, parent.stat, S_IWRITE) != 0) - vfsThrow(EACCES, "not enough permissions to remove '%s'", path.c_str()); + vfsThrow(EACCES, "not enough permissions for '%s' to remove '%s'", clientName.c_str(), path.c_str()); } // check if we are not removing current working directory diff --git a/src/VfsNs.h b/src/VfsNs.h index 2ab57d4..3d8c72b 100644 --- a/src/VfsNs.h +++ b/src/VfsNs.h @@ -112,6 +112,7 @@ namespace dmlite { regex_t *allowRegex, *denyRegex; bool allowCurrent; + std::string clientName; }; }; -- 1.8.2.3