rpms/qbittorrent/devel HTTP_digest_mode_Web_UI_authentication.patch, NONE, 1.1 qbittorrent.spec, 1.70, 1.71
Leigh Scott
leigh123linux at fedoraproject.org
Fri Jan 15 16:16:42 UTC 2010
- Previous message: rpms/samba/devel samba.spec,1.206,1.207
- Next message: rpms/perl-Fedora-Bugzilla/devel perl-Fedora-Bugzilla-0.13-no-CascadeClear.patch, NONE, 1.1 .cvsignore, 1.4, 1.5 perl-Fedora-Bugzilla.spec, 1.6, 1.7 sources, 1.4, 1.5
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Author: leigh123linux
Update of /cvs/pkgs/rpms/qbittorrent/devel
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv25286
Modified Files:
qbittorrent.spec
Added Files:
HTTP_digest_mode_Web_UI_authentication.patch
Log Message:
* Thu Jan 15 2010 Leigh Scott <leigh123linux at googlemail.com> - 2.1.0-0.12.rc7
- add patch to use HTTP digest mode for Web UI authentication
HTTP_digest_mode_Web_UI_authentication.patch:
Changelog | 2
src/httpconnection.cpp | 6 +-
src/httpserver.cpp | 118 +++++++++++++++++++++++++++++++++++++++++++------
src/httpserver.h | 8 ++-
src/preferences.h | 17 ++++---
5 files changed, 125 insertions(+), 26 deletions(-)
--- NEW FILE HTTP_digest_mode_Web_UI_authentication.patch ---
--- trunk/Changelog 2010/01/15 07:32:33 3385
+++ trunk/Changelog 2010/01/15 14:20:20 3386
@@ -19,6 +19,8 @@
- BUGFIX: Use XDG folders (.cache, .local) instead of .qbittorrent
- BUGFIX: Added legal notice on startup that the user must accept
- BUGFIX: Protect Web UI authentication against brute forcing
+ - BUGFIX: Use HTTP digest mode for Web UI authentication (instead of Basic)
+ - BUGFIX: Properly display torrents with one file in subfolder(s)
- COSMETIC: Use checkboxes to filter torrent content instead of comboboxes
- COSMETIC: Use alternating row colors in transfer list (set in program preferences)
- COSMETIC: Added a spin box to speed limiting dialog for manual input
--- trunk/src/httpconnection.cpp 2010/01/15 07:32:33 3385
+++ trunk/src/httpconnection.cpp 2010/01/15 14:20:20 3386
@@ -137,14 +137,14 @@
write();
return;
}
- 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())) {
+ QString auth = parser.value("Authorization");
+ if (QString::compare(auth.split(" ").first(), "Digest", Qt::CaseInsensitive) != 0 || !parent->isAuthorized(auth.toLocal8Bit(), parser.method())) {
// 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.setValue("WWW-Authenticate", "Basic realm=\"you know what\"");
+ generator.setValue("WWW-Authenticate", "Digest realm=\""+QString(QBT_REALM)+"\", nonce=\""+parent->generateNonce()+"\", algorithm=\"MD5\", qop=\"auth\"");
write();
return;
}
--- trunk/src/httpserver.cpp 2010/01/15 07:32:33 3385
+++ trunk/src/httpserver.cpp 2010/01/15 14:20:20 3386
@@ -33,13 +33,14 @@
#include "httpconnection.h"
#include "eventmanager.h"
#include "bittorrent.h"
-#include "preferences.h"
#include <QTimer>
#include <QCryptographicHash>
+#include <QTime>
+#include <QRegExp>
HttpServer::HttpServer(Bittorrent *_BTSession, int msec, QObject* parent) : QTcpServer(parent) {
username = Preferences::getWebUiUsername().toLocal8Bit();
- password_md5 = Preferences::getWebUiPassword().toLocal8Bit();
+ password_ha1 = Preferences::getWebUiPassword().toLocal8Bit();
connect(this, SIGNAL(newConnection()), this, SLOT(newHttpConnection()));
BTSession = _BTSession;
manager = new EventManager(this, BTSession);
@@ -118,21 +119,110 @@
}
}
-void HttpServer::setAuthorization(QString _username, QString _password_md5) {
+QString HttpServer::generateNonce() const {
+ QCryptographicHash md5(QCryptographicHash::Md5);
+ md5.addData(QTime::currentTime().toString("hhmmsszzz").toLocal8Bit());
+ md5.addData(":");
+ md5.addData(QBT_REALM);
+ return md5.result().toHex();
+}
+
+void HttpServer::setAuthorization(QString _username, QString _password_ha1) {
username = _username.toLocal8Bit();
- password_md5 = _password_md5.toLocal8Bit();
+ password_ha1 = _password_ha1.toLocal8Bit();
}
-bool HttpServer::isAuthorized(QByteArray auth) const {
- // Decode Auth
- 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());
+// AUTH string is: Digest username="chris",
+// realm="Web UI Access",
+// nonce="570d04de93444b7fd3eaeaecb00e635e",
+// uri="/", algorithm=MD5,
+// response="ba886766d19b45313c0e2195e4344264",
+// qop=auth, nc=00000001, cnonce="e8ac970779c17075"
+bool HttpServer::isAuthorized(QByteArray auth, QString method) const {
+ qDebug("AUTH string is %s", auth.data());
+ // Get user name
+ QRegExp regex_user(".*username=\"([^\"]+)\".*");
+ if(regex_user.indexIn(auth) < 0) return false;
+ QString prop_user = regex_user.cap(1);
+ qDebug("AUTH: Proposed username is %s, real username is %s", prop_user.toLocal8Bit().data(), username.data());
+ if(prop_user != username) {
+ // User name is invalid, we can reject already
+ qDebug("AUTH-PROB: Username is invalid");
+ return false;
+ }
+ // Get realm
+ QRegExp regex_realm(".*realm=\"([^\"]+)\".*");
+ if(regex_realm.indexIn(auth) < 0) {
+ qDebug("AUTH-PROB: Missing realm");
+ return false;
+ }
+ QByteArray prop_realm = regex_realm.cap(1).toLocal8Bit();
+ if(prop_realm != QBT_REALM) {
+ qDebug("AUTH-PROB: Wrong realm");
+ return false;
+ }
+ // get nonce
+ QRegExp regex_nonce(".*nonce=\"([^\"]+)\".*");
+ if(regex_nonce.indexIn(auth) < 0) {
+ qDebug("AUTH-PROB: missing nonce");
+ return false;
+ }
+ QByteArray prop_nonce = regex_nonce.cap(1).toLocal8Bit();
+ qDebug("prop nonce is: %s", prop_nonce.data());
+ // get uri
+ QRegExp regex_uri(".*uri=\"([^\"]+)\".*");
+ if(regex_uri.indexIn(auth) < 0) {
+ qDebug("AUTH-PROB: Missing uri");
+ return false;
+ }
+ QByteArray prop_uri = regex_uri.cap(1).toLocal8Bit();
+ qDebug("prop uri is: %s", prop_uri.data());
+ // get response
+ QRegExp regex_response(".*response=\"([^\"]+)\".*");
+ if(regex_response.indexIn(auth) < 0) {
+ qDebug("AUTH-PROB: Missing response");
+ return false;
+ }
+ QByteArray prop_response = regex_response.cap(1).toLocal8Bit();
+ qDebug("prop response is: %s", prop_response.data());
+ // Compute correct reponse
+ QCryptographicHash md5_ha2(QCryptographicHash::Md5);
+ md5_ha2.addData(method.toLocal8Bit() + ":" + prop_uri);
+ QByteArray ha2 = md5_ha2.result().toHex();
+ QByteArray response = "";
+ if(auth.contains("qop=")) {
+ QCryptographicHash md5_ha(QCryptographicHash::Md5);
+ // Get nc
+ QRegExp regex_nc(".*nc=(\\w+).*");
+ if(regex_nc.indexIn(auth) < 0) {
+ qDebug("AUTH-PROB: qop but missing nc");
+ return false;
+ }
+ QByteArray prop_nc = regex_nc.cap(1).toLocal8Bit();
+ qDebug("prop nc is: %s", prop_nc.data());
+ QRegExp regex_cnonce(".*cnonce=\"([^\"]+)\".*");
+ if(regex_cnonce.indexIn(auth) < 0) {
+ qDebug("AUTH-PROB: qop but missing cnonce");
+ return false;
+ }
+ QByteArray prop_cnonce = regex_cnonce.cap(1).toLocal8Bit();
+ qDebug("prop cnonce is: %s", prop_cnonce.data());
+ QRegExp regex_qop(".*qop=(\\w+).*");
+ if(regex_qop.indexIn(auth) < 0) {
+ qDebug("AUTH-PROB: missing qop");
+ return false;
+ }
+ QByteArray prop_qop = regex_qop.cap(1).toLocal8Bit();
+ qDebug("prop qop is: %s", prop_qop.data());
+ md5_ha.addData(password_ha1+":"+prop_nonce+":"+prop_nc+":"+prop_cnonce+":"+prop_qop+":"+ha2);
+ response = md5_ha.result().toHex();
+ } else {
+ QCryptographicHash md5_ha(QCryptographicHash::Md5);
+ md5_ha.addData(password_ha1+":"+prop_nonce+":"+ha2);
+ response = md5_ha.result().toHex();
+ }
+ qDebug("AUTH: comparing reponses");
+ return prop_response == response;
}
EventManager* HttpServer::eventManager() const
--- trunk/src/httpserver.h 2010/01/15 07:32:33 3385
+++ trunk/src/httpserver.h 2010/01/15 14:20:20 3386
@@ -36,6 +36,7 @@
#include <QTcpServer>
#include <QByteArray>
#include <QHash>
+#include "preferences.h"
class Bittorrent;
class QTimer;
@@ -46,7 +47,7 @@
private:
QByteArray username;
- QByteArray password_md5;
+ QByteArray password_ha1;
Bittorrent *BTSession;
EventManager *manager;
QTimer *timer;
@@ -54,9 +55,10 @@
public:
HttpServer(Bittorrent *BTSession, int msec, QObject* parent = 0);
~HttpServer();
- void setAuthorization(QString username, QString password_md5);
- bool isAuthorized(QByteArray auth) const;
+ void setAuthorization(QString username, QString password_ha1);
+ bool isAuthorized(QByteArray auth, QString method) const;
EventManager *eventManager() const;
+ QString generateNonce() const;
QHash<QString, int> client_failed_attempts;
private slots:
--- trunk/src/preferences.h 2010/01/15 07:32:33 3385
+++ trunk/src/preferences.h 2010/01/15 14:20:20 3386
@@ -36,6 +36,8 @@
#include <QPair>
#include <QDir>
+#define QBT_REALM "Web UI Access"
+
class Preferences {
public:
// General options
@@ -708,9 +710,10 @@
if(current_pass_md5 == new_password) return;
// Encode to md5 and save
QCryptographicHash md5(QCryptographicHash::Md5);
+ md5.addData(getWebUiUsername().toLocal8Bit()+":"+QBT_REALM+":");
md5.addData(new_password.toLocal8Bit());
QSettings settings("qBittorrent", "qBittorrent");
- settings.setValue("Preferences/WebUI/Password_md5", md5.result().toHex());
+ settings.setValue("Preferences/WebUI/Password_ha1", md5.result().toHex());
}
static QString getWebUiPassword() {
@@ -720,18 +723,20 @@
QString clear_pass = settings.value("Preferences/WebUI/Password", "adminadmin").toString();
settings.remove("Preferences/WebUI/Password");
QCryptographicHash md5(QCryptographicHash::Md5);
+ md5.addData(getWebUiUsername().toLocal8Bit()+":"+QBT_REALM+":");
md5.addData(clear_pass.toLocal8Bit());
QString pass_md5(md5.result().toHex());
- settings.setValue("Preferences/WebUI/Password_md5", pass_md5);
+ settings.setValue("Preferences/WebUI/Password_ha1", pass_md5);
return pass_md5;
}
- QString pass_md5 = settings.value("Preferences/WebUI/Password_md5", "").toString();
- if(pass_md5.isEmpty()) {
+ QString pass_ha1 = settings.value("Preferences/WebUI/Password_ha1", "").toString();
+ if(pass_ha1.isEmpty()) {
QCryptographicHash md5(QCryptographicHash::Md5);
+ md5.addData(getWebUiUsername().toLocal8Bit()+":"+QBT_REALM+":");
md5.addData("adminadmin");
- pass_md5 = md5.result().toHex();
+ pass_ha1 = md5.result().toHex();
}
- return pass_md5;
+ return pass_ha1;
}
};
Index: qbittorrent.spec
===================================================================
RCS file: /cvs/pkgs/rpms/qbittorrent/devel/qbittorrent.spec,v
retrieving revision 1.70
retrieving revision 1.71
diff -u -p -r1.70 -r1.71
--- qbittorrent.spec 14 Jan 2010 22:17:49 -0000 1.70
+++ qbittorrent.spec 15 Jan 2010 16:16:42 -0000 1.71
@@ -3,7 +3,7 @@
Name: qbittorrent
Summary: A Bittorrent Client
Version: 2.1.0
-Release: 0.11.rc7%{?dist}
+Release: 0.12.rc7%{?dist}
# The source for this package was pulled from upstream's vcs. Use the
# following commands to generate the tarball:
# svn checkout -r %{svn_rev} https://qbittorrent.svn.sourceforge.net/svnroot/qbittorrent/trunk qbittorrent
@@ -15,6 +15,12 @@ Source0: http://downloads.sf.net/qbittor
# https://bugzilla.redhat.com/show_bug.cgi?id=548491
Patch1: gcc.patch
+# Upstream patches
+
+# svn commit 3386
+# Use HTTP digest mode for Web UI authentication (instead of Basic)
+Patch2: HTTP_digest_mode_Web_UI_authentication.patch
+
URL: http://sourceforge.net/projects/qbittorrent
Group: Applications/Internet
BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
@@ -44,6 +50,7 @@ It aims to be as fast as possible and to
%prep
%setup -q -n %{name}-%{version}rc7
%patch1 -p1 -b .gcc
+%patch2 -p1 -b .HTTP_digest_mode_Web_UI_authentication
%build
# use ./configure instead of %%configure as it doesn't work
@@ -107,6 +114,9 @@ gtk-update-icon-cache %{_datadir}/icons/
%changelog
+* Thu Jan 15 2010 Leigh Scott <leigh123linux at googlemail.com> - 2.1.0-0.12.rc7
+- add patch to use HTTP digest mode for Web UI authentication
+
* Thu Jan 14 2010 Leigh Scott <leigh123linux at googlemail.com> - 2.1.0-0.11.rc7
- update to 2.1.0rc7
- Previous message: rpms/samba/devel samba.spec,1.206,1.207
- Next message: rpms/perl-Fedora-Bugzilla/devel perl-Fedora-Bugzilla-0.13-no-CascadeClear.patch, NONE, 1.1 .cvsignore, 1.4, 1.5 perl-Fedora-Bugzilla.spec, 1.6, 1.7 sources, 1.4, 1.5
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the scm-commits
mailing list