File indexing completed on 2023-10-01 05:03:15

0001 /*
0002  * Copyright (C) 2011 Collabora Ltd. <http://www.collabora.co.uk/>
0003  *   @author Andre Moreira Magalhaes <andre.magalhaes@collabora.co.uk>
0004  * Copyright (C) 2011 David Edmundson <kde@davidedmundson.co.uk>
0005  *
0006  * This library is free software; you can redistribute it and/or
0007  * modify it under the terms of the GNU Lesser General Public
0008  * License as published by the Free Software Foundation; either
0009  * version 2.1 of the License, or (at your option) any later version.
0010  *
0011  * This library is distributed in the hope that it will be useful,
0012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0014  * Lesser General Public License for more details.
0015  *
0016  * You should have received a copy of the GNU Lesser General Public
0017  * License along with this library; if not, write to the Free Software
0018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
0019  */
0020 
0021 #include "sasl-auth-op.h"
0022 
0023 #include "x-telepathy-password-auth-operation.h"
0024 #include "x-telepathy-sso-google-operation.h"
0025 
0026 #include <QtCore/QScopedPointer>
0027 
0028 #include <TelepathyQt/PendingVariantMap>
0029 
0030 #include <QDebug>
0031 #include <KLocalizedString>
0032 
0033 SaslAuthOp::SaslAuthOp(const Tp::AccountPtr &account,
0034         const Tp::ChannelPtr &channel)
0035     : Tp::PendingOperation(channel),
0036       m_account(account),
0037       m_channel(channel),
0038       m_saslIface(channel->interface<Tp::Client::ChannelInterfaceSASLAuthenticationInterface>())
0039 {
0040     //Check if the account has any StorageIdentifier, in which case we will
0041     //prioritize those mechanism related with KDE Accounts integration
0042     QScopedPointer<Tp::Client::AccountInterfaceStorageInterface> accountStorageInterface(
0043         new Tp::Client::AccountInterfaceStorageInterface(m_account->busName(), m_account->objectPath()));
0044 
0045     Tp::PendingVariantMap *pendingMap = accountStorageInterface->requestAllProperties();
0046     connect(pendingMap, SIGNAL(finished(Tp::PendingOperation*)), SLOT(onGetAccountStorageFetched(Tp::PendingOperation*)));
0047 }
0048 
0049 SaslAuthOp::~SaslAuthOp()
0050 {
0051 }
0052 
0053 void SaslAuthOp::gotProperties(Tp::PendingOperation *op)
0054 {
0055     if (m_mechanisms.isEmpty()) {
0056         if (op->isError()) {
0057             qWarning() << "Unable to retrieve available SASL mechanisms";
0058             m_channel->requestClose();
0059             setFinishedWithError(op->errorName(), op->errorMessage());
0060             return;
0061         }
0062 
0063         Tp::PendingVariantMap *pvm = qobject_cast<Tp::PendingVariantMap*>(op);
0064         m_properties = qdbus_cast<QVariantMap>(pvm->result());
0065         m_mechanisms = qdbus_cast<QStringList>(m_properties.value(QLatin1String("AvailableMechanisms")));
0066         qDebug() << m_mechanisms;
0067     }
0068 
0069     uint status = qdbus_cast<uint>(m_properties.value(QLatin1String("SASLStatus")));
0070     QString error = qdbus_cast<QString>(m_properties.value(QLatin1String("SASLError")));
0071     QVariantMap errorDetails = qdbus_cast<QVariantMap>(m_properties.value(QLatin1String("SASLErrorDetails")));
0072 
0073     if (m_mechanisms.contains(QLatin1String("X-OAUTH2"))) {
0074         qDebug() << "Starting X-OAuth2 auth";
0075         m_mechanisms.removeAll(QStringLiteral("X-OAUTH2"));
0076         XTelepathySSOGoogleOperation *authop = new XTelepathySSOGoogleOperation(m_account, m_accountStorageId, m_saslIface);
0077         connect(authop,
0078                 SIGNAL(finished(Tp::PendingOperation*)),
0079                 SLOT(onAuthOperationFinished(Tp::PendingOperation*)));
0080 
0081         authop->onSASLStatusChanged(status, error, errorDetails);
0082     } else if (m_mechanisms.contains(QLatin1String("X-TELEPATHY-PASSWORD"))) {
0083         qDebug() << "Starting Password auth";
0084         m_mechanisms.removeAll(QStringLiteral("X-TELEPATHY-PASSWORD"));
0085         Q_EMIT ready(this);
0086         XTelepathyPasswordAuthOperation *authop = new XTelepathyPasswordAuthOperation(m_account, m_accountStorageId, m_saslIface, qdbus_cast<bool>(m_properties.value(QLatin1String("CanTryAgain"))));
0087         connect(authop,
0088                 SIGNAL(finished(Tp::PendingOperation*)),
0089                 SLOT(onAuthOperationFinished(Tp::PendingOperation*)));
0090 
0091         authop->onSASLStatusChanged(status, error, errorDetails);
0092     } else {
0093         qWarning() << "X-TELEPATHY-PASSWORD, X-OAUTH2 are the only supported SASL mechanism and are not available:" << m_mechanisms;
0094         m_channel->requestClose();
0095         setFinishedWithError(TP_QT_ERROR_NOT_IMPLEMENTED,
0096                 QLatin1String("X-TELEPATHY-PASSWORD, X-OAUTH2 are the only supported SASL mechanism and are not available:"));
0097         return;
0098     }
0099 }
0100 
0101 void SaslAuthOp::onAuthOperationFinished(Tp::PendingOperation *op)
0102 {
0103     if (op->isError()) {
0104         if (!m_mechanisms.isEmpty()) {
0105             // if we have other mechanisms left, try again with different one
0106             gotProperties(0);
0107         } else {
0108             setFinishedWithError(op->errorName(), op->errorMessage());
0109             m_channel->requestClose();
0110         }
0111     } else {
0112         setFinished();
0113         m_channel->requestClose();
0114     }
0115 }
0116 
0117 void SaslAuthOp::setReady()
0118 {
0119     connect(m_saslIface->requestAllProperties(),
0120             SIGNAL(finished(Tp::PendingOperation*)),
0121             SLOT(gotProperties(Tp::PendingOperation*)));
0122 }
0123 
0124 void SaslAuthOp::onGetAccountStorageFetched(Tp::PendingOperation* op)
0125 {
0126     Tp::PendingVariantMap *pendingMap = qobject_cast<Tp::PendingVariantMap*>(op);
0127 
0128     m_accountStorageId = pendingMap->result()["StorageIdentifier"].value<QDBusVariant>().variant().toInt();
0129     qDebug() << m_accountStorageId;
0130 
0131     setReady();
0132 }