2 * Bittorrent Client using Qt and libtorrent.
3 * Copyright (C) 2018 Vladimir Golovnev <glassez@yandex.ru>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 * In addition, as a special exception, the copyright holders give permission to
20 * link this program with the OpenSSL project's "OpenSSL" library (or with
21 * modified versions of it that use the same license as the "OpenSSL" library),
22 * and distribute the linked executables. You must obey the GNU General Public
23 * License in all respects for all of the code used other than "OpenSSL". If you
24 * modify file(s), you may extend this exception to your version of the file(s),
25 * but you are not obligated to do so. If you do not wish to do so, delete this
26 * exception statement from your version.
29 #include "authcontroller.h"
33 #include "base/global.h"
34 #include "base/logger.h"
35 #include "base/preferences.h"
36 #include "base/utils/password.h"
38 #include "isessionmanager.h"
40 AuthController::AuthController(ISessionManager
*sessionManager
, IApplication
*app
, QObject
*parent
)
41 : APIController(app
, parent
)
42 , m_sessionManager
{sessionManager
}
46 void AuthController::setUsername(const QString
&username
)
48 m_username
= username
;
51 void AuthController::setPasswordHash(const QByteArray
&passwordHash
)
53 m_passwordHash
= passwordHash
;
56 void AuthController::loginAction()
58 if (m_sessionManager
->session())
64 const QString clientAddr
= m_sessionManager
->clientId();
65 const QString usernameFromWeb
= params()[u
"username"_s
];
66 const QString passwordFromWeb
= params()[u
"password"_s
];
70 LogMsg(tr("WebAPI login failure. Reason: IP has been banned, IP: %1, username: %2")
71 .arg(clientAddr
, usernameFromWeb
)
73 throw APIError(APIErrorType::AccessDenied
74 , tr("Your IP address has been banned after too many failed authentication attempts."));
77 const bool usernameEqual
= Utils::Password::slowEquals(usernameFromWeb
.toUtf8(), m_username
.toUtf8());
78 const bool passwordEqual
= Utils::Password::PBKDF2::verify(m_passwordHash
, passwordFromWeb
);
80 if (usernameEqual
&& passwordEqual
)
82 m_clientFailedLogins
.remove(clientAddr
);
84 m_sessionManager
->sessionStart();
86 LogMsg(tr("WebAPI login success. IP: %1").arg(clientAddr
));
90 if (Preferences::instance()->getWebUIMaxAuthFailCount() > 0)
91 increaseFailedAttempts();
92 setResult(u
"Fails."_s
);
93 LogMsg(tr("WebAPI login failure. Reason: invalid credentials, attempt count: %1, IP: %2, username: %3")
94 .arg(QString::number(failedAttemptsCount()), clientAddr
, usernameFromWeb
)
99 void AuthController::logoutAction() const
101 m_sessionManager
->sessionEnd();
104 bool AuthController::isBanned() const
106 const auto failedLoginIter
= m_clientFailedLogins
.find(m_sessionManager
->clientId());
107 if (failedLoginIter
== m_clientFailedLogins
.end())
110 bool isBanned
= (failedLoginIter
->banTimer
.remainingTime() >= 0);
111 if (isBanned
&& failedLoginIter
->banTimer
.hasExpired())
113 m_clientFailedLogins
.erase(failedLoginIter
);
120 int AuthController::failedAttemptsCount() const
122 return m_clientFailedLogins
.value(m_sessionManager
->clientId()).failedAttemptsCount
;
125 void AuthController::increaseFailedAttempts()
127 Q_ASSERT(Preferences::instance()->getWebUIMaxAuthFailCount() > 0);
129 FailedLogin
&failedLogin
= m_clientFailedLogins
[m_sessionManager
->clientId()];
130 ++failedLogin
.failedAttemptsCount
;
132 if (failedLogin
.failedAttemptsCount
>= Preferences::instance()->getWebUIMaxAuthFailCount())
134 // Max number of failed attempts reached
136 failedLogin
.banTimer
.setRemainingTime(Preferences::instance()->getWebUIBanDuration());