From af5909677a97f62b20d89229be42701762ae05c3 Mon Sep 17 00:00:00 2001 From: Bas Pape Date: Thu, 30 Aug 2012 13:58:24 +0200 Subject: [PATCH] Add support for SASL EXTERNAL This is a method to identify to nickserv during connection registration, like SASL PLAIN, but using the fingerprint of the certificate. Currently the method used is chosen based on the mere presence of a certificate. SASL PLAIN is not used as fallback (either this works or the certificate is used as normal, with the race condition). --- src/common/quassel.h | 3 +- src/core/coresessioneventprocessor.cpp | 36 ++++++++++---- .../settingspages/networkssettingspage.cpp | 48 +++++++++++++++++++ src/qtui/settingspages/networkssettingspage.h | 8 ++++ .../settingspages/networkssettingspage.ui | 12 ++++- 5 files changed, 96 insertions(+), 11 deletions(-) diff --git a/src/common/quassel.h b/src/common/quassel.h index de19313a..6089ac03 100644 --- a/src/common/quassel.h +++ b/src/common/quassel.h @@ -71,8 +71,9 @@ public: enum Feature { SynchronizedMarkerLine = 0x0001, SaslAuthentication = 0x0002, + SaslExternal = 0x0004, - NumFeatures = 0x0002 + NumFeatures = 0x0004 }; Q_DECLARE_FLAGS(Features, Feature); diff --git a/src/core/coresessioneventprocessor.cpp b/src/core/coresessioneventprocessor.cpp index 07362b60..e2edd083 100644 --- a/src/core/coresessioneventprocessor.cpp +++ b/src/core/coresessioneventprocessor.cpp @@ -112,14 +112,22 @@ void CoreSessionEventProcessor::processIrcEventAuthenticate(IrcEvent *e) CoreNetwork *net = coreNetwork(e); - QString construct = net->saslAccount(); - construct.append(QChar(QChar::Null)); - construct.append(net->saslAccount()); - construct.append(QChar(QChar::Null)); - construct.append(net->saslPassword()); - QByteArray saslData = QByteArray(construct.toAscii().toBase64()); - saslData.prepend("AUTHENTICATE "); - net->putRawLine(saslData); +#ifdef HAVE_SSL + if (net->identityPtr()->sslCert().isNull()) { +#endif + QString construct = net->saslAccount(); + construct.append(QChar(QChar::Null)); + construct.append(net->saslAccount()); + construct.append(QChar(QChar::Null)); + construct.append(net->saslPassword()); + QByteArray saslData = QByteArray(construct.toAscii().toBase64()); + saslData.prepend("AUTHENTICATE "); + net->putRawLine(saslData); +#ifdef HAVE_SSL + } else { + net->putRawLine("AUTHENTICATE +"); + } +#endif } @@ -131,7 +139,17 @@ void CoreSessionEventProcessor::processIrcEventCap(IrcEvent *e) if (e->params().count() == 3) { if (e->params().at(2).startsWith("sasl")) { // Freenode (at least) sends "sasl " with a trailing space for some reason! // FIXME use event - coreNetwork(e)->putRawLine(coreNetwork(e)->serverEncode("AUTHENTICATE PLAIN")); // Only working with PLAIN atm, blowfish later + // if the current identity has a cert set, use SASL EXTERNAL +#ifdef HAVE_SSL + if (!coreNetwork(e)->identityPtr()->sslCert().isNull()) { + coreNetwork(e)->putRawLine(coreNetwork(e)->serverEncode("AUTHENTICATE EXTERNAL")); + } else { +#endif + // Only working with PLAIN atm, blowfish later + coreNetwork(e)->putRawLine(coreNetwork(e)->serverEncode("AUTHENTICATE PLAIN")); +#ifdef HAVE_SSL + } +#endif } } } diff --git a/src/qtui/settingspages/networkssettingspage.cpp b/src/qtui/settingspages/networkssettingspage.cpp index bcaab22e..6ae5f515 100644 --- a/src/qtui/settingspages/networkssettingspage.cpp +++ b/src/qtui/settingspages/networkssettingspage.cpp @@ -35,12 +35,20 @@ NetworksSettingsPage::NetworksSettingsPage(QWidget *parent) : SettingsPage(tr("IRC"), tr("Networks"), parent) +#ifdef HAVE_SSL + , _cid(0) +#endif { ui.setupUi(this); // hide SASL options for older cores if (!(Client::coreFeatures() & Quassel::SaslAuthentication)) ui.sasl->hide(); + if (!(Client::coreFeatures() & Quassel::SaslExternal)) + ui.label_saslext->hide(); +#ifndef HAVE_SSL + ui.label_saslext->hide(); +#endif // set up icons ui.renameNetwork->setIcon(SmallIcon("edit-rename")); @@ -469,6 +477,20 @@ void NetworksSettingsPage::displayNetwork(NetworkId id) _ignoreWidgetChanges = true; if (id != 0) { NetworkInfo info = networkInfos[id]; + +#ifdef HAVE_SSL + // this is only needed when the core supports SASL EXTERNAL + if (Client::coreFeatures() & Quassel::SaslExternal) { + if (_cid) { + disconnect(_cid, SIGNAL(sslSettingsUpdated()), this, SLOT(sslUpdated())); + delete _cid; + } + _cid = new CertIdentity(*Client::identity(info.identity), this); + _cid->enableEditSsl(true); + connect(_cid, SIGNAL(sslSettingsUpdated()), this, SLOT(sslUpdated())); + } +#endif + ui.identityList->setCurrentIndex(ui.identityList->findData(info.identity.toInt())); ui.serverList->clear(); foreach(Network::Server server, info.serverList) { @@ -506,6 +528,12 @@ void NetworksSettingsPage::displayNetwork(NetworkId id) } else { // just clear widgets +#ifdef HAVE_SSL + if (_cid) { + disconnect(_cid, SIGNAL(sslSettingsUpdated()), this, SLOT(sslUpdated())); + delete _cid; + } +#endif ui.identityList->setCurrentIndex(-1); ui.serverList->clear(); ui.performEdit->clear(); @@ -549,6 +577,26 @@ void NetworksSettingsPage::saveToNetworkInfo(NetworkInfo &info) } +#ifdef HAVE_SSL +void NetworksSettingsPage::sslUpdated() +{ + if (_cid && !_cid->sslKey().isNull()) { + ui.saslAccount->setDisabled(true); + ui.label_10->setDisabled(true); + ui.saslPassword->setDisabled(true); + ui.label_11->setDisabled(true); + ui.label_saslext->setHidden(false); + } else { + ui.saslAccount->setDisabled(false); + ui.label_10->setDisabled(false); + ui.saslPassword->setDisabled(false); + ui.label_11->setDisabled(false); + ui.label_saslext->setHidden(true); + } +} +#endif + + /*** Network list ***/ void NetworksSettingsPage::on_networkList_itemSelectionChanged() diff --git a/src/qtui/settingspages/networkssettingspage.h b/src/qtui/settingspages/networkssettingspage.h index c337325f..ef9f8835 100644 --- a/src/qtui/settingspages/networkssettingspage.h +++ b/src/qtui/settingspages/networkssettingspage.h @@ -25,6 +25,7 @@ #include "network.h" #include "settingspage.h" +#include "clientidentity.h" #include "ui_networkssettingspage.h" #include "ui_networkadddlg.h" @@ -65,6 +66,10 @@ private slots: void clientIdentityRemoved(IdentityId); void clientIdentityUpdated(); +#ifdef HAVE_SSL + void sslUpdated(); +#endif + void on_networkList_itemSelectionChanged(); void on_addNetwork_clicked(); void on_deleteNetwork_clicked(); @@ -86,6 +91,9 @@ private: NetworkId currentId; QHash networkInfos; bool _ignoreWidgetChanges; +#ifdef HAVE_SSL + CertIdentity *_cid; +#endif QPixmap connectedIcon, connectingIcon, disconnectedIcon; diff --git a/src/qtui/settingspages/networkssettingspage.ui b/src/qtui/settingspages/networkssettingspage.ui index 7665e101..e2c106cd 100644 --- a/src/qtui/settingspages/networkssettingspage.ui +++ b/src/qtui/settingspages/networkssettingspage.ui @@ -180,7 +180,7 @@ - 0 + 3 @@ -629,6 +629,16 @@ Note that Quassel IRC automatically rejoins channels, so /join will rarely be ne + + + + <html><head/><body><p><span style=" font-weight:600;">Note:</span> because the identity has an ssl certificate set, SASL EXTERNAL will be used.</p></body></html> + + + true + + + -- 2.20.1