- Store Web UI password as md5

This commit is contained in:
Christophe Dumez 2009-12-10 19:19:19 +00:00
parent d1a549a6cc
commit d3687fd863
5 changed files with 115 additions and 75 deletions

View file

@ -45,6 +45,7 @@
- WEB UI: Added internationalization support - WEB UI: Added internationalization support
- WEB UI: Reduced computation in Javascript (do this one server side instead) - WEB UI: Reduced computation in Javascript (do this one server side instead)
- WEB UI: Fixed Transfer list flickering - WEB UI: Fixed Transfer list flickering
- WEB UI: Password is now stored as md5
- I18N: Added Serbian translation (By Anaximandar Milet) - I18N: Added Serbian translation (By Anaximandar Milet)
- COSMETIC: Merged download / upload lists - COSMETIC: Merged download / upload lists
- COSMETIC: Torrents can be filtered based on their status - COSMETIC: Torrents can be filtered based on their status

View file

@ -33,95 +33,103 @@
#include "httpconnection.h" #include "httpconnection.h"
#include "eventmanager.h" #include "eventmanager.h"
#include "bittorrent.h" #include "bittorrent.h"
#include "preferences.h"
#include <QTimer> #include <QTimer>
#include <QCryptographicHash>
HttpServer::HttpServer(Bittorrent *_BTSession, int msec, QObject* parent) : QTcpServer(parent) HttpServer::HttpServer(Bittorrent *_BTSession, int msec, QObject* parent) : QTcpServer(parent) {
{ username = Preferences::getWebUiUsername().toLocal8Bit();
base64 = QByteArray(":").toBase64(); password_md5 = Preferences::getWebUiPassword().toLocal8Bit();
connect(this, SIGNAL(newConnection()), this, SLOT(newHttpConnection())); connect(this, SIGNAL(newConnection()), this, SLOT(newHttpConnection()));
BTSession = _BTSession; BTSession = _BTSession;
manager = new EventManager(this, BTSession); manager = new EventManager(this, BTSession);
//add torrents //add torrents
std::vector<torrent_handle> torrents = BTSession->getTorrents(); std::vector<torrent_handle> torrents = BTSession->getTorrents();
std::vector<torrent_handle>::iterator torrentIT; std::vector<torrent_handle>::iterator torrentIT;
for(torrentIT = torrents.begin(); torrentIT != torrents.end(); torrentIT++) { for(torrentIT = torrents.begin(); torrentIT != torrents.end(); torrentIT++) {
QTorrentHandle h = QTorrentHandle(*torrentIT); QTorrentHandle h = QTorrentHandle(*torrentIT);
if(h.is_valid()) if(h.is_valid())
manager->addedTorrent(h); manager->addedTorrent(h);
} }
//connect BTSession to manager //connect BTSession to manager
connect(BTSession, SIGNAL(addedTorrent(QTorrentHandle&)), manager, SLOT(addedTorrent(QTorrentHandle&))); connect(BTSession, SIGNAL(addedTorrent(QTorrentHandle&)), manager, SLOT(addedTorrent(QTorrentHandle&)));
connect(BTSession, SIGNAL(deletedTorrent(QString)), manager, SLOT(deletedTorrent(QString))); connect(BTSession, SIGNAL(deletedTorrent(QString)), manager, SLOT(deletedTorrent(QString)));
//set timer //set timer
timer = new QTimer(this); timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(onTimer())); connect(timer, SIGNAL(timeout()), this, SLOT(onTimer()));
timer->start(msec); timer->start(msec);
// Additional translations for Web UI // Additional translations for Web UI
QString a = tr("File"); QString a = tr("File");
a = tr("Edit"); a = tr("Edit");
a = tr("Help"); a = tr("Help");
a = tr("Delete from HD"); a = tr("Delete from HD");
a = tr("Download Torrents from their URL or Magnet link"); a = tr("Download Torrents from their URL or Magnet link");
a = tr("Only one link per line"); a = tr("Only one link per line");
a = tr("Download local torrent"); a = tr("Download local torrent");
a = tr("Torrent files were correctly added to download list."); a = tr("Torrent files were correctly added to download list.");
a = tr("Point to torrent file"); a = tr("Point to torrent file");
a = tr("Download"); a = tr("Download");
a = tr("Are you sure you want to delete the selected torrents from the transfer list and hard disk?"); a = tr("Are you sure you want to delete the selected torrents from the transfer list and hard disk?");
a = tr("Download rate limit must be greater than 0 or disabled."); a = tr("Download rate limit must be greater than 0 or disabled.");
a = tr("Upload rate limit must be greater than 0 or disabled."); a = tr("Upload rate limit must be greater than 0 or disabled.");
a = tr("Maximum number of connections limit must be greater than 0 or disabled."); a = tr("Maximum number of connections limit must be greater than 0 or disabled.");
a = tr("Maximum number of connections per torrent limit must be greater than 0 or disabled."); a = tr("Maximum number of connections per torrent limit must be greater than 0 or disabled.");
a = tr("Maximum number of upload slots per torrent limit must be greater than 0 or disabled."); a = tr("Maximum number of upload slots per torrent limit must be greater than 0 or disabled.");
a = tr("Unable to save program preferences, qBittorrent is probably unreachable."); a = tr("Unable to save program preferences, qBittorrent is probably unreachable.");
} }
HttpServer::~HttpServer() HttpServer::~HttpServer()
{ {
delete timer; delete timer;
delete manager; delete manager;
} }
void HttpServer::newHttpConnection() void HttpServer::newHttpConnection()
{ {
QTcpSocket *socket; QTcpSocket *socket;
while((socket = nextPendingConnection())) while((socket = nextPendingConnection()))
{ {
HttpConnection *connection = new HttpConnection(socket, BTSession, this); HttpConnection *connection = new HttpConnection(socket, BTSession, this);
//connect connection to BTSession //connect connection to BTSession
connect(connection, SIGNAL(UrlReadyToBeDownloaded(QString)), BTSession, SLOT(downloadUrlAndSkipDialog(QString))); connect(connection, SIGNAL(UrlReadyToBeDownloaded(QString)), BTSession, SLOT(downloadUrlAndSkipDialog(QString)));
connect(connection, SIGNAL(MagnetReadyToBeDownloaded(QString)), BTSession, SLOT(addMagnetSkipAddDlg(QString))); connect(connection, SIGNAL(MagnetReadyToBeDownloaded(QString)), BTSession, SLOT(addMagnetSkipAddDlg(QString)));
connect(connection, SIGNAL(torrentReadyToBeDownloaded(QString, bool, QString, bool)), BTSession, SLOT(addTorrent(QString, bool, QString, bool))); connect(connection, SIGNAL(torrentReadyToBeDownloaded(QString, bool, QString, bool)), BTSession, SLOT(addTorrent(QString, bool, QString, bool)));
connect(connection, SIGNAL(deleteTorrent(QString, bool)), BTSession, SLOT(deleteTorrent(QString, bool))); connect(connection, SIGNAL(deleteTorrent(QString, bool)), BTSession, SLOT(deleteTorrent(QString, bool)));
connect(connection, SIGNAL(pauseTorrent(QString)), BTSession, SLOT(pauseTorrent(QString))); connect(connection, SIGNAL(pauseTorrent(QString)), BTSession, SLOT(pauseTorrent(QString)));
connect(connection, SIGNAL(resumeTorrent(QString)), BTSession, SLOT(resumeTorrent(QString))); connect(connection, SIGNAL(resumeTorrent(QString)), BTSession, SLOT(resumeTorrent(QString)));
connect(connection, SIGNAL(pauseAllTorrents()), BTSession, SLOT(pauseAllTorrents())); connect(connection, SIGNAL(pauseAllTorrents()), BTSession, SLOT(pauseAllTorrents()));
connect(connection, SIGNAL(resumeAllTorrents()), BTSession, SLOT(resumeAllTorrents())); connect(connection, SIGNAL(resumeAllTorrents()), BTSession, SLOT(resumeAllTorrents()));
} }
} }
void HttpServer::onTimer() { void HttpServer::onTimer() {
std::vector<torrent_handle> torrents = BTSession->getTorrents(); std::vector<torrent_handle> torrents = BTSession->getTorrents();
std::vector<torrent_handle>::iterator torrentIT; std::vector<torrent_handle>::iterator torrentIT;
for(torrentIT = torrents.begin(); torrentIT != torrents.end(); torrentIT++) { for(torrentIT = torrents.begin(); torrentIT != torrents.end(); torrentIT++) {
QTorrentHandle h = QTorrentHandle(*torrentIT); QTorrentHandle h = QTorrentHandle(*torrentIT);
if(h.is_valid()) if(h.is_valid())
manager->modifiedTorrent(h); manager->modifiedTorrent(h);
} }
} }
void HttpServer::setAuthorization(QString username, QString password) void HttpServer::setAuthorization(QString _username, QString _password_md5) {
{ username = _username.toLocal8Bit();
QString cat = username + ":" + password; password_md5 = _password_md5.toLocal8Bit();
base64 = QByteArray(cat.toLocal8Bit()).toBase64();
} }
bool HttpServer::isAuthorized(QByteArray auth) const bool HttpServer::isAuthorized(QByteArray auth) const {
{ // Decode Auth
return (auth == base64); QByteArray decoded = QByteArray::fromBase64(auth);
QList<QByteArray> creds = decoded.split(':');
if(creds.size() != 2) return false;
QByteArray prop_username = creds.first();
if(prop_username != username) return false;
QCryptographicHash md5(QCryptographicHash::Md5);
md5.addData(creds.last());
return (password_md5 == md5.result().toHex());
} }
EventManager* HttpServer::eventManager() const EventManager* HttpServer::eventManager() const
{ {
return manager; return manager;
} }

View file

@ -44,7 +44,8 @@ class HttpServer : public QTcpServer {
Q_OBJECT Q_OBJECT
private: private:
QByteArray base64; QByteArray username;
QByteArray password_md5;
Bittorrent *BTSession; Bittorrent *BTSession;
EventManager *manager; EventManager *manager;
QTimer *timer; QTimer *timer;
@ -52,7 +53,7 @@ class HttpServer : public QTcpServer {
public: public:
HttpServer(Bittorrent *BTSession, int msec, QObject* parent = 0); HttpServer(Bittorrent *BTSession, int msec, QObject* parent = 0);
~HttpServer(); ~HttpServer();
void setAuthorization(QString username, QString password); void setAuthorization(QString username, QString password_md5);
bool isAuthorized(QByteArray auth) const; bool isAuthorized(QByteArray auth) const;
EventManager *eventManager() const; EventManager *eventManager() const;

View file

@ -465,7 +465,8 @@ void options_imp::saveOptions(){
{ {
settings.setValue("Port", webUiPort()); settings.setValue("Port", webUiPort());
settings.setValue("Username", webUiUsername()); settings.setValue("Username", webUiUsername());
settings.setValue("Password", webUiPassword()); // FIXME: Check that the password is valid (not empty at least)
Preferences::setWebUiPassword(webUiPassword());
} }
// End Web UI // End Web UI
settings.endGroup(); settings.endGroup();

View file

@ -32,6 +32,7 @@
#define PREFERENCES_H #define PREFERENCES_H
#include <QSettings> #include <QSettings>
#include <QCryptographicHash>
#include <QPair> #include <QPair>
#include <QDir> #include <QDir>
@ -456,12 +457,40 @@ public:
static QString getWebUiUsername() { static QString getWebUiUsername() {
QSettings settings("qBittorrent", "qBittorrent"); QSettings settings("qBittorrent", "qBittorrent");
return settings.value("Preferences/WebUI/Username", "user").toString(); return settings.value("Preferences/WebUI/Username", "admin").toString();
}
static void setWebUiPassword(QString new_password) {
// Get current password md5
QString current_pass_md5 = getWebUiPassword();
// Check if password did not change
if(current_pass_md5 == new_password) return;
// Encode to md5 and save
QCryptographicHash md5(QCryptographicHash::Md5);
md5.addData(new_password.toLocal8Bit());
QSettings settings("qBittorrent", "qBittorrent");
settings.setValue("Preferences/WebUI/Password_md5", md5.result().toHex());
} }
static QString getWebUiPassword() { static QString getWebUiPassword() {
QSettings settings("qBittorrent", "qBittorrent"); QSettings settings("qBittorrent", "qBittorrent");
return settings.value("Preferences/WebUI/Password", "").toString(); // Here for backward compatiblity
if(settings.contains("Preferences/WebUI/Password")) {
QString clear_pass = settings.value("Preferences/WebUI/Password", "adminadmin").toString();
settings.remove("Preferences/WebUI/Password");
QCryptographicHash md5(QCryptographicHash::Md5);
md5.addData(clear_pass.toLocal8Bit());
QString pass_md5(md5.result().toHex());
settings.setValue("Preferences/WebUI/Password_md5", pass_md5);
return pass_md5;
}
QString pass_md5 = settings.value("Preferences/WebUI/Password_md5", "").toString();
if(pass_md5.isEmpty()) {
QCryptographicHash md5(QCryptographicHash::Md5);
md5.addData("adminadmin");
pass_md5 = md5.result().toHex();
}
return pass_md5;
} }
}; };