mirror of
https://github.com/qbittorrent/qBittorrent
synced 2025-07-16 02:03:07 -07:00
- Protect Web UI authentication against brute forcing (IP are banned after 3 failed attempts)
This commit is contained in:
parent
2bf8e2d2d7
commit
9c4c5e2d1a
2 changed files with 17 additions and 4 deletions
|
@ -128,17 +128,28 @@ QString HttpConnection::translateDocument(QString data) {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpConnection::respond()
|
void HttpConnection::respond() {
|
||||||
{
|
|
||||||
//qDebug("Respond called");
|
//qDebug("Respond called");
|
||||||
|
int nb_fail = parent->client_failed_attempts.value(socket->peerAddress().toString(), 0);
|
||||||
|
if(nb_fail > 2) {
|
||||||
|
generator.setStatusLine(403, "Forbidden");
|
||||||
|
generator.setMessage(tr("Your IP address has been banned after too many failed authentication attempts."));
|
||||||
|
write();
|
||||||
|
return;
|
||||||
|
}
|
||||||
QStringList auth = parser.value("Authorization").split(" ", QString::SkipEmptyParts);
|
QStringList auth = parser.value("Authorization").split(" ", QString::SkipEmptyParts);
|
||||||
if (auth.size() != 2 || QString::compare(auth[0], "Basic", Qt::CaseInsensitive) != 0 || !parent->isAuthorized(auth[1].toLocal8Bit()))
|
if (auth.size() != 2 || QString::compare(auth[0], "Basic", Qt::CaseInsensitive) != 0 || !parent->isAuthorized(auth[1].toLocal8Bit())) {
|
||||||
{
|
// Update failed attempt counter
|
||||||
|
parent->client_failed_attempts.insert(socket->peerAddress().toString(), nb_fail+1);
|
||||||
|
qDebug("client IP: %s (%d failed attempts)", socket->peerAddress().toString().toLocal8Bit().data(), nb_fail);
|
||||||
|
// Return unauthorized header
|
||||||
generator.setStatusLine(401, "Unauthorized");
|
generator.setStatusLine(401, "Unauthorized");
|
||||||
generator.setValue("WWW-Authenticate", "Basic realm=\"you know what\"");
|
generator.setValue("WWW-Authenticate", "Basic realm=\"you know what\"");
|
||||||
write();
|
write();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// Client sucessfuly authenticated, reset number of failed attempts
|
||||||
|
parent->client_failed_attempts.remove(socket->peerAddress().toString());
|
||||||
QString url = parser.url();
|
QString url = parser.url();
|
||||||
// Favicon
|
// Favicon
|
||||||
if(url.endsWith("favicon.ico")) {
|
if(url.endsWith("favicon.ico")) {
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include <QPair>
|
#include <QPair>
|
||||||
#include <QTcpServer>
|
#include <QTcpServer>
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
|
#include <QHash>
|
||||||
|
|
||||||
class Bittorrent;
|
class Bittorrent;
|
||||||
class QTimer;
|
class QTimer;
|
||||||
|
@ -56,6 +57,7 @@ class HttpServer : public QTcpServer {
|
||||||
void setAuthorization(QString username, QString password_md5);
|
void setAuthorization(QString username, QString password_md5);
|
||||||
bool isAuthorized(QByteArray auth) const;
|
bool isAuthorized(QByteArray auth) const;
|
||||||
EventManager *eventManager() const;
|
EventManager *eventManager() const;
|
||||||
|
QHash<QString, int> client_failed_attempts;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void newHttpConnection();
|
void newHttpConnection();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue