1
0
Fork 0

Fixed a dead-lock issue in authinfo (#3764)

This commit is contained in:
Michael Hackstein 2017-11-22 10:33:39 +01:00 committed by GitHub
parent ce537af092
commit 7d95de46e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 50 additions and 5 deletions

View File

@ -211,14 +211,14 @@ void RestUsersHandler::generateDatabaseResult(AuthInfo* authInfo,
data.add(c->name(), VPackValue("undefined"));
}
});
lvl = authInfo->canUseCollection(user, vocbase->name(), "*");
lvl = authInfo->canUseCollectionNoLock(user, vocbase->name(), "*");
data.add("*", VPackValue(convertFromAuthLevel(lvl)));
} else if (lvl != AuthLevel::NONE) { // hide db's without access
data.add(vocbase->name(), VPackValue(str));
}
});
if (full) {
AuthLevel lvl = authInfo->canUseDatabase(user, "*");
AuthLevel lvl = authInfo->canUseDatabaseNoLock(user, "*");
data("*", VPackValue(VPackValueType::Object))(
"permission", VPackValue(convertFromAuthLevel(lvl)))();
}

View File

@ -208,8 +208,9 @@ static VPackBuilder QueryUser(aql::QueryRegistry* queryRegistry,
if (doc.isExternal()) {
doc = doc.resolveExternals();
}
return VPackBuilder(doc);
VPackBuilder result;
result.add(doc);
return result;
}
static void ConvertLegacyFormat(VPackSlice doc, VPackBuilder& result) {
@ -680,6 +681,7 @@ Result AuthInfo::removeAllUsers() {
Result res;
{
MUTEX_LOCKER(locker, _loadFromDBLock);
WRITE_LOCKER(guard, _authInfoLock);
for (auto const& pair : _authInfo) {
@ -698,7 +700,6 @@ Result AuthInfo::removeAllUsers() {
// do not get into race conditions with loadFromDB
{
MUTEX_LOCKER(locker, _loadFromDBLock);
_authInfo.clear();
_authBasicCache.clear();
_outdated = true;
@ -912,6 +913,17 @@ AuthLevel AuthInfo::canUseDatabase(std::string const& username,
return level;
}
AuthLevel AuthInfo::canUseDatabaseNoLock(std::string const& username,
std::string const& dbname) {
AuthLevel level = configuredDatabaseAuthLevelInternal(username, dbname, 0);
static_assert(AuthLevel::RO < AuthLevel::RW, "ro < rw");
if (level > AuthLevel::RO && !ServerState::writeOpsEnabled()) {
return AuthLevel::RO;
}
return level;
}
// internal method called by configuredCollectionAuthLevel
// asserts that collection name is non-empty and already translated
// from collection id to name
@ -986,6 +998,29 @@ AuthLevel AuthInfo::canUseCollection(std::string const& username,
return level;
}
AuthLevel AuthInfo::canUseCollectionNoLock(std::string const& username,
std::string const& dbname,
std::string const& coll) {
if (coll.empty()) {
// no collection name given
return AuthLevel::NONE;
}
AuthLevel level;
if (coll[0] >= '0' && coll[0] <= '9') {
std::string tmpColl = DatabaseFeature::DATABASE->translateCollectionName(dbname, coll);
level = configuredCollectionAuthLevelInternal(username, dbname, tmpColl, 0);
} else {
level = configuredCollectionAuthLevelInternal(username, dbname, coll, 0);
}
static_assert(AuthLevel::RO < AuthLevel::RW, "ro < rw");
if (level > AuthLevel::RO && !ServerState::writeOpsEnabled()) {
return AuthLevel::RO;
}
return level;
}
// public called from HttpCommTask.cpp and VstCommTask.cpp

View File

@ -126,6 +126,16 @@ class AuthInfo {
std::string const& dbname,
std::string const& coll);
// No Lock variants of the above to be used in callbacks
// Use with CARE! You need to make sure that the lock
// is held from outside.
AuthLevel canUseDatabaseNoLock(std::string const& username,
std::string const& dbname);
AuthLevel canUseCollectionNoLock(std::string const& username,
std::string const& dbname,
std::string const& coll);
void setJwtSecret(std::string const&);
std::string jwtSecret();
std::string generateJwt(VPackBuilder const&);