1 /***************************************************************************
2 * Copyright (C) 2005-2013 by the Quassel Project *
3 * devel@quassel-irc.org *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) version 3. *
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 *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
19 ***************************************************************************/
21 #include "coreauthhandler.h"
24 # include <QSslSocket>
30 #include "protocols/legacy/legacypeer.h"
32 using namespace Protocol;
34 CoreAuthHandler::CoreAuthHandler(QTcpSocket *socket, QObject *parent)
37 , _clientRegistered(false)
41 // TODO: protocol detection
43 // FIXME: make sure _peer gets deleted
44 // TODO: socket ownership goes to the peer! (-> use shared ptr later...)
45 _peer = new LegacyPeer(this, socket, this);
46 // only in compat mode
47 connect(_peer, SIGNAL(protocolVersionMismatch(int,int)), SLOT(onProtocolVersionMismatch(int,int)));
51 // only in compat mode
52 void CoreAuthHandler::onProtocolVersionMismatch(int actual, int expected)
54 qWarning() << qPrintable(tr("Client")) << _peer->description() << qPrintable(tr("too old, rejecting."));
55 QString errorString = tr("<b>Your Quassel Client is too old!</b><br>"
56 "This core needs at least client/core protocol version %1 (got: %2).<br>"
57 "Please consider upgrading your client.").arg(expected, actual);
58 _peer->dispatch(ClientDenied(errorString));
63 void CoreAuthHandler::startSsl()
66 QSslSocket *sslSocket = qobject_cast<QSslSocket *>(socket());
69 qDebug() << qPrintable(tr("Starting encryption for Client:")) << _peer->description();
70 connect(sslSocket, SIGNAL(sslErrors(const QList<QSslError> &)), SLOT(onSslErrors()));
71 sslSocket->flush(); // ensure that the write cache is flushed before we switch to ssl (bug 682)
72 sslSocket->startServerEncryption();
78 void CoreAuthHandler::onSslErrors()
80 QSslSocket *sslSocket = qobject_cast<QSslSocket *>(socket());
82 sslSocket->ignoreSslErrors();
87 bool CoreAuthHandler::checkClientRegistered()
89 if (!_clientRegistered) {
90 qWarning() << qPrintable(tr("Client")) << qPrintable(socket()->peerAddress().toString()) << qPrintable(tr("did not send an init message before trying to login, rejecting."));
91 _peer->dispatch(ClientDenied(tr("<b>Client not initialized!</b><br>You need to send an init message before trying to login.")));
99 void CoreAuthHandler::handle(const RegisterClient &msg)
101 // TODO: only in compat mode
104 if (Quassel::isOptionSet("require-ssl") && !msg.sslSupported) {
105 _peer->dispatch(ClientDenied(tr("<b>SSL is required!</b><br>You need to use SSL in order to connect to this core.")));
109 if (Core::sslSupported() && msg.sslSupported)
112 QVariantList backends;
113 bool configured = Core::isConfigured();
115 backends = Core::backendInfo();
117 _peer->dispatch(ClientRegistered(Quassel::features(), configured, backends, useSsl, Core::instance()->startTime()));
118 // TODO: only in compat mode
122 _clientRegistered = true;
126 void CoreAuthHandler::handle(const SetupData &msg)
128 if (!checkClientRegistered())
131 QString result = Core::setup(msg.adminUser, msg.adminPassword, msg.backend, msg.setupData);
132 if (!result.isEmpty())
133 _peer->dispatch(SetupFailed(result));
135 _peer->dispatch(SetupDone());
139 void CoreAuthHandler::handle(const Login &msg)
141 if (!checkClientRegistered())
144 UserId uid = Core::validateUser(msg.user, msg.password);
146 _peer->dispatch(LoginFailed(tr("<b>Invalid username or password!</b><br>The username/password combination you supplied could not be found in the database.")));
149 _peer->dispatch(LoginSuccess());
151 quInfo() << qPrintable(tr("Client %1 initialized and authenticated successfully as \"%2\" (UserId: %3).").arg(socket()->peerAddress().toString(), msg.user, QString::number(uid.toInt())));
153 disconnect(socket(), 0, this, 0);
154 disconnect(_peer, 0, this, 0);
155 _peer->setParent(0); // Core needs to take care of this one now!
157 socket()->flush(); // Make sure all data is sent before handing over the peer (and socket) to the session thread (bug 682)
158 emit handshakeComplete(_peer, uid);