Design fixes: move the event handling back to the RfbClient and improve password handling.

svn path=/trunk/KDE/kdenetwork/krfb/; revision=1195291
This commit is contained in:
George Kiagiadakis
2010-11-10 18:57:29 +00:00
parent 62e5eacbe7
commit cda3a0b972
6 changed files with 98 additions and 106 deletions

View File

@@ -39,6 +39,7 @@ public:
: RfbClient(client, parent) {}
virtual rfbNewClientAction doHandle();
virtual bool checkPassword(const QByteArray & encryptedPassword);
};
rfbNewClientAction InvitationsRfbClient::doHandle()
@@ -54,27 +55,47 @@ rfbNewClientAction InvitationsRfbClient::doHandle()
return RfbClient::doHandle();
}
//***********
static bool doCheckPassword(const QString &p, unsigned char *ochallenge, const char *response, int len)
bool InvitationsRfbClient::checkPassword(const QByteArray & encryptedPassword)
{
if ((len == 0) && (p.length() == 0)) {
return true;
bool allowUninvited = KrfbConfig::allowUninvitedConnections();
QByteArray password = KrfbConfig::uninvitedConnectionPassword().toLocal8Bit();
bool authd = false;
kDebug() << "about to start autentication";
if (allowUninvited) {
authd = vncAuthCheckPassword(password, encryptedPassword);
}
char passwd[MAXPWLEN];
unsigned char challenge[CHALLENGESIZE];
if (!authd) {
QList<Invitation> invlist = InvitationManager::self()->invitations();
memcpy(challenge, ochallenge, CHALLENGESIZE);
bzero(passwd, MAXPWLEN);
foreach(const Invitation & it, invlist) {
kDebug() << "checking password";
if (!p.isNull()) {
strncpy(passwd, p.toLatin1(),
(MAXPWLEN <= p.length()) ? MAXPWLEN : p.length());
if (vncAuthCheckPassword(it.password().toLocal8Bit(), encryptedPassword)
&& it.isValid())
{
authd = true;
InvitationManager::self()->removeInvitation(it);
break;
}
}
}
rfbEncryptBytes(challenge, passwd);
return memcmp(challenge, response, len) == 0;
if (!authd) {
if (InvitationManager::self()->invitations().size() > 0) {
KNotification::event("InvalidPasswordInvitations",
i18n("Failed login attempt from %1: wrong password", name()));
} else {
KNotification::event("InvalidPassword",
i18n("Failed login attempt from %1: wrong password", name()));
}
return false;
}
return true;
}
//***********
@@ -95,52 +116,6 @@ RfbClient* InvitationsRfbServer::newClient(rfbClientPtr client)
return new InvitationsRfbClient(client, this);
}
bool InvitationsRfbServer::checkPassword(RfbClient* client, const char* encryptedPassword, int len)
{
bool allowUninvited = KrfbConfig::allowUninvitedConnections();
QString password = KrfbConfig::uninvitedConnectionPassword();
bool authd = false;
kDebug() << "about to start autentication";
if (allowUninvited) {
authd = doCheckPassword(password, client->rfbClient()->authChallenge, encryptedPassword, len);
}
if (!authd) {
QList<Invitation> invlist = InvitationManager::self()->invitations();
foreach(const Invitation & it, invlist) {
kDebug() << "checking password";
if (doCheckPassword(it.password(), client->rfbClient()->authChallenge,
encryptedPassword, len)
&& it.isValid())
{
authd = true;
InvitationManager::self()->removeInvitation(it);
break;
}
}
}
if (!authd) {
if (InvitationManager::self()->invitations().size() > 0) {
KNotification::event("InvalidPasswordInvitations",
i18n("Failed login attempt from %1: wrong password",
client->name()));
} else {
KNotification::event("InvalidPassword",
i18n("Failed login attempt from %1: wrong password",
client->name()));
}
return false;
}
return true;
}
void InvitationsRfbServer::startAndCheck()
{
if (!start()) {

View File

@@ -32,7 +32,6 @@ protected:
InvitationsRfbServer() : RfbServer(0) {}
virtual RfbClient* newClient(rfbClientPtr client);
virtual bool checkPassword(RfbClient* client, const char* encryptedPassword, int len);
private Q_SLOTS:
void startAndCheck();

View File

@@ -21,6 +21,7 @@
#include "connectiondialog.h"
#include "krfbconfig.h"
#include "sockethelpers.h"
#include "events.h"
#include <QtCore/QSocketNotifier>
#include <KDebug>
#include <KNotification>
@@ -78,11 +79,6 @@ void RfbClient::setControlEnabled(bool enabled)
}
}
rfbClientPtr RfbClient::rfbClient() const
{
return d->client;
}
void RfbClient::update()
{
rfbUpdateClient(d->client);
@@ -154,6 +150,48 @@ void RfbClient::setStatusConnected()
}
}
void RfbClient::handleKeyboardEvent(bool down, rfbKeySym keySym)
{
if (d->controlEnabled) {
EventHandler::handleKeyboard(down, keySym);
}
}
void RfbClient::handleMouseEvent(int buttonMask, int x, int y)
{
if (d->controlEnabled) {
EventHandler::handlePointer(buttonMask, x, y);
}
}
bool RfbClient::checkPassword(const QByteArray & encryptedPassword)
{
Q_UNUSED(encryptedPassword);
return d->client->screen->authPasswdData == (void*)0;
}
bool RfbClient::vncAuthCheckPassword(const QByteArray& password, const QByteArray& encryptedPassword) const
{
if (password.isEmpty() && encryptedPassword.isEmpty()) {
return true;
}
char passwd[MAXPWLEN];
unsigned char challenge[CHALLENGESIZE];
memcpy(challenge, d->client->authChallenge, CHALLENGESIZE);
bzero(passwd, MAXPWLEN);
if (!password.isEmpty()) {
strncpy(passwd, password,
(MAXPWLEN <= password.size()) ? MAXPWLEN : password.size());
}
rfbEncryptBytes(challenge, passwd);
return memcmp(challenge, encryptedPassword, encryptedPassword.size()) == 0;
}
void RfbClient::onSocketActivated()
{
//Process not only one, but all pending messages.

View File

@@ -38,9 +38,6 @@ public:
bool controlEnabled() const;
void setControlEnabled(bool enabled);
///returns the internal rfbClient
rfbClientPtr rfbClient() const;
public Q_SLOTS:
void setOnHold(bool onHold);
void closeConnection();
@@ -63,6 +60,23 @@ protected:
bool isConnected() const;
void setStatusConnected(); ///call to declare the client as connected
virtual void handleKeyboardEvent(bool down, rfbKeySym keySym);
virtual void handleMouseEvent(int buttonMask, int x, int y);
/** This method is supposed to check if the provided \a encryptedPassword
* matches the criteria for authenticating the client.
* The default implementation returns false if a password is required.
* Reimplement to do more useful stuff.
*/
virtual bool checkPassword(const QByteArray & encryptedPassword);
/** This method checks if the \a encryptedPassword that was sent from the remote
* user matches the \a password that you have specified localy to be the password
* for this connection. This assumes that the standard VNC authentication mechanism
* is used. Returns true if the password matches or false otherwise.
*/
bool vncAuthCheckPassword(const QByteArray & password, const QByteArray & encryptedPassword) const;
private Q_SLOTS:
void onSocketActivated();
void dialogAccepted();

View File

@@ -18,7 +18,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "rfbserver.h"
#include "events.h"
#include "rfbservermanager.h"
#include <QtCore/QSocketNotifier>
#include <KDebug>
@@ -55,32 +54,6 @@ RfbServer::~RfbServer()
RfbServerManager::instance()->unregisterServer(this);
}
void RfbServer::handleKeyboardEvent(RfbClient* client, rfbBool down, rfbKeySym keySym)
{
if (client->controlEnabled()) {
EventHandler::handleKeyboard(down, keySym);
}
}
void RfbServer::handleMouseEvent(RfbClient* client, int buttonMask, int x, int y)
{
if (client->controlEnabled()) {
EventHandler::handlePointer(buttonMask, x, y);
}
}
/** Default implementation returns false if a password is required.
* Reimplement to do more useful stuff
*/
bool RfbServer::checkPassword(RfbClient* client, const char* encryptedPassword, int len)
{
Q_UNUSED(client);
Q_UNUSED(encryptedPassword);
Q_UNUSED(len);
return !d->passwordRequired;
}
QByteArray RfbServer::listeningAddress() const
{
return d->listeningAddress;
@@ -259,25 +232,22 @@ void RfbServer::clientGoneHook(rfbClientPtr cl)
//static
rfbBool RfbServer::passwordCheck(rfbClientPtr cl, const char *encryptedPassword, int len)
{
RfbServer *server = static_cast<RfbServer*>(cl->screen->screenData);
RfbClient *client = static_cast<RfbClient*>(cl->clientData);
return server->checkPassword(client, encryptedPassword, len);
return client->checkPassword(QByteArray::fromRawData(encryptedPassword, len));
}
//static
void RfbServer::keyboardHook(rfbBool down, rfbKeySym keySym, rfbClientPtr cl)
{
RfbServer *server = static_cast<RfbServer*>(cl->screen->screenData);
RfbClient *client = static_cast<RfbClient*>(cl->clientData);
server->handleKeyboardEvent(client, down ? true : false, keySym);
client->handleKeyboardEvent(down ? true : false, keySym);
}
//static
void RfbServer::pointerHook(int bm, int x, int y, rfbClientPtr cl)
{
RfbServer *server = static_cast<RfbServer*>(cl->screen->screenData);
RfbClient *client = static_cast<RfbClient*>(cl->clientData);
server->handleMouseEvent(client, bm, x, y);
client->handleMouseEvent(bm, x, y);
}
//static

View File

@@ -52,10 +52,6 @@ private Q_SLOTS:
protected:
virtual RfbClient *newClient(rfbClientPtr client) = 0;
virtual void handleKeyboardEvent(RfbClient *client, rfbBool down, rfbKeySym keySym);
virtual void handleMouseEvent(RfbClient *client, int buttonMask, int x, int y);
virtual bool checkPassword(RfbClient *client, const char *encryptedPassword, int len);
private:
static rfbNewClientAction newClientHook(rfbClientPtr cl);
static void clientGoneHook(rfbClientPtr cl);