Feat: Protect db against pw/token tests

This commit is contained in:
brindosch 2019-08-30 18:51:07 +02:00
parent 5553199cc4
commit 4595ae8e2d
2 changed files with 96 additions and 4 deletions

View File

@ -110,6 +110,18 @@ public:
/// ///
bool isUserTokenAuthorized(const QString& usr, const QString& token); bool isUserTokenAuthorized(const QString& usr, const QString& token);
///
/// @brief Check if user auth is temporary blocked due to failed attempts
/// @return True on blocked and no further Auth requests will be accepted
///
bool isUserAuthBlocked(){ return (_userAuthAttempts.length() >= 10); };
///
/// @brief Check if token auth is temporary blocked due to failed attempts
/// @return True on blocked and no further Auth requests will be accepted
///
bool isTokenAuthBlocked(){ return (_tokenAuthAttempts.length() >= 25); };
/// ///
/// @brief Change password of user /// @brief Change password of user
/// @param user The username /// @param user The username
@ -186,6 +198,12 @@ signals:
void tokenResponse(const bool& success, QObject* caller, const QString& token, const QString& comment, const QString& id); void tokenResponse(const bool& success, QObject* caller, const QString& token, const QString& comment, const QString& id);
private: private:
///
/// @brief Increment counter for token/user auth
/// @param user If true we increment USER auth instead of token
///
void setAuthBlock(const bool& user = false);
/// Database interface for auth table /// Database interface for auth table
AuthTable* _authTable; AuthTable* _authTable;
@ -210,9 +228,23 @@ private:
/// Timer for counting against pendingRequest timeouts /// Timer for counting against pendingRequest timeouts
QTimer* _timer; QTimer* _timer;
// Timer which cleans up the block counter
QTimer* _authBlockTimer;
// Contains timestamps of failed user login attempts
QVector<uint64_t> _userAuthAttempts;
// Contains timestamps of failed token login attempts
QVector<uint64_t> _tokenAuthAttempts;
private slots: private slots:
/// ///
/// @brief Check timeout of pending requests /// @brief Check timeout of pending requests
/// ///
void checkTimeout(); void checkTimeout();
///
/// @brief Check if there are timeouts for failed login attempts
///
void checkAuthBlockTimeout();
}; };

View File

@ -17,9 +17,11 @@ AuthManager::AuthManager(QObject* parent)
, _pendingRequests() , _pendingRequests()
, _authRequired(true) , _authRequired(true)
, _timer(new QTimer(this)) , _timer(new QTimer(this))
, _authBlockTimer(new QTimer(this))
{ {
AuthManager::manager = this; AuthManager::manager = this;
// get uuid // get uuid
_uuid = _metaTable->getUUID(); _uuid = _metaTable->getUUID();
@ -27,6 +29,10 @@ AuthManager::AuthManager(QObject* parent)
_timer->setInterval(1000); _timer->setInterval(1000);
connect(_timer, &QTimer::timeout, this, &AuthManager::checkTimeout); connect(_timer, &QTimer::timeout, this, &AuthManager::checkTimeout);
// setup authBlockTimer
_authBlockTimer->setInterval(60000);
connect(_authBlockTimer, &QTimer::timeout, this, &AuthManager::checkAuthBlockTimeout);
// init with default user and password // init with default user and password
if(!_authTable->userExist("Hyperion")) if(!_authTable->userExist("Hyperion"))
{ {
@ -72,22 +78,54 @@ const QVector<AuthManager::AuthDefinition> AuthManager::getTokenList()
const QString AuthManager::getUserToken(const QString & usr) const QString AuthManager::getUserToken(const QString & usr)
{ {
return QString(_authTable->getUserToken("Hyperion")); return QString(_authTable->getUserToken(usr));
}
void AuthManager::setAuthBlock(const bool& user)
{
// current timestamp +10 minutes
if(user)
_userAuthAttempts.append(QDateTime::currentMSecsSinceEpoch()+600000);
else
_tokenAuthAttempts.append(QDateTime::currentMSecsSinceEpoch()+600000);
QMetaObject::invokeMethod(_authBlockTimer, "start", Qt::QueuedConnection);
} }
bool AuthManager::isUserAuthorized(const QString& user, const QString& pw) bool AuthManager::isUserAuthorized(const QString& user, const QString& pw)
{ {
return _authTable->isUserAuthorized(user, pw); if(isUserAuthBlocked())
return false;
if(!_authTable->isUserAuthorized(user, pw)){
setAuthBlock(true);
return false;
}
return true;
} }
bool AuthManager::isTokenAuthorized(const QString& token) bool AuthManager::isTokenAuthorized(const QString& token)
{ {
return _authTable->tokenExist(token); if(isTokenAuthBlocked())
return false;
if(!_authTable->tokenExist(token)){
setAuthBlock();
return false;
}
return true;
} }
bool AuthManager::isUserTokenAuthorized(const QString& usr, const QString& token) bool AuthManager::isUserTokenAuthorized(const QString& usr, const QString& token)
{ {
return _authTable->isUserTokenAuthorized(usr, token); if(isUserAuthBlocked())
return false;
if(!_authTable->isUserTokenAuthorized(usr, token)){
setAuthBlock(true);
return false;
}
return true;
} }
bool AuthManager::updateUserPassword(const QString& user, const QString& pw, const QString& newPw) bool AuthManager::updateUserPassword(const QString& user, const QString& pw, const QString& newPw)
@ -184,3 +222,25 @@ void AuthManager::checkTimeout()
if(_pendingRequests.isEmpty()) if(_pendingRequests.isEmpty())
_timer->stop(); _timer->stop();
} }
void AuthManager::checkAuthBlockTimeout(){
// handle user auth block
for (auto it = _userAuthAttempts.begin(); it != _userAuthAttempts.end(); it++) {
// after 10 minutes, we remove the entry
if (*it < (uint64_t)QDateTime::currentMSecsSinceEpoch()) {
_userAuthAttempts.erase(it--);
}
}
// handle token auth block
for (auto it = _tokenAuthAttempts.begin(); it != _tokenAuthAttempts.end(); it++) {
// after 10 minutes, we remove the entry
if (*it < (uint64_t)QDateTime::currentMSecsSinceEpoch()) {
_tokenAuthAttempts.erase(it--);
}
}
// if the lists are empty we stop
if(_userAuthAttempts.empty() && _tokenAuthAttempts.empty())
_authBlockTimer->stop();
}