Rename settingspages.inc to settingspages.cmake
[quassel.git] / src / core / coreauthhandler.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005-2013 by the Quassel Project                        *
3  *   devel@quassel-irc.org                                                 *
4  *                                                                         *
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.                                           *
9  *                                                                         *
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.                          *
14  *                                                                         *
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  ***************************************************************************/
20
21 #include "coreauthhandler.h"
22
23 #ifdef HAVE_SSL
24 #  include <QSslSocket>
25 #endif
26
27 #include "core.h"
28 #include "logger.h"
29
30 #include "protocols/legacy/legacypeer.h"
31
32 using namespace Protocol;
33
34 CoreAuthHandler::CoreAuthHandler(QTcpSocket *socket, QObject *parent)
35     : AuthHandler(parent)
36     , _peer(0)
37     , _clientRegistered(false)
38 {
39     setSocket(socket);
40
41     // TODO: protocol detection
42
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)));
48 }
49
50
51 // only in compat mode
52 void CoreAuthHandler::onProtocolVersionMismatch(int actual, int expected)
53 {
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));
59     _peer->close();
60 }
61
62
63 void CoreAuthHandler::startSsl()
64 {
65 #ifdef HAVE_SSL
66     QSslSocket *sslSocket = qobject_cast<QSslSocket *>(socket());
67     Q_ASSERT(sslSocket);
68
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();
73 #endif
74 }
75
76
77 #ifdef HAVE_SSL
78 void CoreAuthHandler::onSslErrors()
79 {
80     QSslSocket *sslSocket = qobject_cast<QSslSocket *>(socket());
81     Q_ASSERT(sslSocket);
82     sslSocket->ignoreSslErrors();
83 }
84 #endif
85
86
87 bool CoreAuthHandler::checkClientRegistered()
88 {
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.")));
92         _peer->close();
93         return false;
94     }
95     return true;
96 }
97
98
99 void CoreAuthHandler::handle(const RegisterClient &msg)
100 {
101     // TODO: only in compat mode
102     bool useSsl = false;
103 #ifdef HAVE_SSL
104     if (Core::sslSupported() && msg.sslSupported)
105         useSsl = true;
106 #endif
107     QVariantList backends;
108     bool configured = Core::isConfigured();
109     if (!configured)
110         backends = Core::backendInfo();
111
112     _peer->dispatch(ClientRegistered(Quassel::features(), configured, backends, useSsl, Core::instance()->startTime()));
113     // TODO: only in compat mode
114     if (useSsl)
115         startSsl();
116
117     _clientRegistered = true;
118 }
119
120
121 void CoreAuthHandler::handle(const SetupData &msg)
122 {
123     if (!checkClientRegistered())
124         return;
125
126     QString result = Core::setup(msg.adminUser, msg.adminPassword, msg.backend, msg.setupData);
127     if (!result.isEmpty())
128         _peer->dispatch(SetupFailed(result));
129     else
130         _peer->dispatch(SetupDone());
131 }
132
133
134 void CoreAuthHandler::handle(const Login &msg)
135 {
136     if (!checkClientRegistered())
137         return;
138
139     UserId uid = Core::validateUser(msg.user, msg.password);
140     if (uid == 0) {
141         _peer->dispatch(LoginFailed(tr("<b>Invalid username or password!</b><br>The username/password combination you supplied could not be found in the database.")));
142         return;
143     }
144     _peer->dispatch(LoginSuccess());
145
146     quInfo() << qPrintable(tr("Client %1 initialized and authenticated successfully as \"%2\" (UserId: %3).").arg(socket()->peerAddress().toString(), msg.user, QString::number(uid.toInt())));
147
148     disconnect(socket(), 0, this, 0);
149     disconnect(_peer, 0, this, 0);
150     _peer->setParent(0); // Core needs to take care of this one now!
151
152     socket()->flush(); // Make sure all data is sent before handing over the peer (and socket) to the session thread (bug 682)
153     emit handshakeComplete(_peer, uid);
154 }