File indexing completed on 2024-04-28 13:31:52

0001 /*  This file is part of the KDE project
0002     SPDX-FileCopyrightText: 2009 Jaroslav Reznik <jreznik@redhat.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include <QDBusConnection>
0008 #include <QDebug>
0009 
0010 #include <KWindowSystem>
0011 
0012 #include <PolkitQt1/Agent/Session>
0013 #include <PolkitQt1/Details>
0014 #include <PolkitQt1/Identity>
0015 #include <PolkitQt1/Subject>
0016 
0017 #include "AuthDialog.h"
0018 #include "policykitlistener.h"
0019 #include "polkit1authagentadaptor.h"
0020 
0021 PolicyKitListener::PolicyKitListener(QObject *parent)
0022     : Listener(parent)
0023     , m_inProgress(false)
0024     , m_selectedUser(nullptr)
0025 {
0026     (void)new Polkit1AuthAgentAdaptor(this);
0027 
0028     if (!QDBusConnection::sessionBus().registerObject("/org/kde/Polkit1AuthAgent",
0029                                                       this,
0030                                                       QDBusConnection::ExportScriptableSlots | QDBusConnection::ExportScriptableProperties
0031                                                           | QDBusConnection::ExportAdaptors)) {
0032         qWarning() << "Could not initiate DBus helper!";
0033     }
0034 
0035     qDebug() << "Listener online";
0036 }
0037 
0038 PolicyKitListener::~PolicyKitListener()
0039 {
0040 }
0041 
0042 void PolicyKitListener::setWIdForAction(const QString &action, qulonglong wID)
0043 {
0044     qDebug() << "On to the handshake";
0045     m_actionsToWID[action] = wID;
0046 }
0047 
0048 void PolicyKitListener::initiateAuthentication(const QString &actionId,
0049                                                const QString &message,
0050                                                const QString &iconName,
0051                                                const PolkitQt1::Details &details,
0052                                                const QString &cookie,
0053                                                const PolkitQt1::Identity::List &identities,
0054                                                PolkitQt1::Agent::AsyncResult *result)
0055 {
0056     qDebug() << "Initiating authentication";
0057 
0058     if (m_inProgress) {
0059         result->setError(i18n("Another client is already authenticating, please try again later."));
0060         result->setCompleted();
0061         qDebug() << "Another client is already authenticating, please try again later.";
0062         return;
0063     }
0064 
0065     m_identities = identities;
0066     m_cookie = cookie;
0067     m_result = result;
0068     m_session.clear();
0069 
0070     m_inProgress = true;
0071 
0072     const WId parentId = m_actionsToWID.value(actionId, 0);
0073 
0074     m_dialog = new AuthDialog(actionId, message, iconName, details, identities, parentId);
0075     connect(m_dialog.data(), SIGNAL(okClicked()), SLOT(dialogAccepted()));
0076     connect(m_dialog.data(), SIGNAL(rejected()), SLOT(dialogCanceled()));
0077     connect(m_dialog.data(), SIGNAL(adminUserSelected(PolkitQt1::Identity)), SLOT(userSelected(PolkitQt1::Identity)));
0078 
0079     qDebug() << "WinId of the dialog is " << m_dialog.data()->winId() << m_dialog.data()->effectiveWinId();
0080     m_dialog.data()->setOptions();
0081     m_dialog.data()->show();
0082     KWindowSystem::forceActiveWindow(m_dialog.data()->winId());
0083     qDebug() << "WinId of the shown dialog is " << m_dialog.data()->winId() << m_dialog.data()->effectiveWinId();
0084 
0085     if (identities.length() == 1) {
0086         m_selectedUser = identities[0];
0087     } else {
0088         m_selectedUser = m_dialog.data()->adminUserSelected();
0089     }
0090 
0091     m_numTries = 0;
0092     tryAgain();
0093 }
0094 
0095 void PolicyKitListener::tryAgain()
0096 {
0097     qDebug() << "Trying again";
0098     m_wasCancelled = false;
0099 
0100     // We will create new session only when some user is selected
0101     if (m_selectedUser.isValid()) {
0102         m_session = new Session(m_selectedUser, m_cookie, m_result);
0103         // clang-format off
0104         connect(m_session.data(), SIGNAL(request(QString,bool)), this, SLOT(request(QString,bool)));
0105         connect(m_session.data(), SIGNAL(completed(bool)), this, SLOT(completed(bool)));
0106         connect(m_session.data(), SIGNAL(showError(QString)), this, SLOT(showError(QString)));
0107         connect(m_session.data(), SIGNAL(showInfo(QString)), this, SLOT(showInfo(QString)));
0108         // clang-format on
0109 
0110         m_session.data()->initiate();
0111     }
0112 }
0113 
0114 void PolicyKitListener::finishObtainPrivilege()
0115 {
0116     qDebug() << "Finishing obtaining privileges";
0117 
0118     // Number of tries increase only when some user is selected
0119     if (m_selectedUser.isValid()) {
0120         m_numTries++;
0121     }
0122 
0123     if (!m_gainedAuthorization && !m_wasCancelled && !m_dialog.isNull()) {
0124         m_dialog.data()->authenticationFailure();
0125 
0126         if (m_numTries < 3) {
0127             m_session.data()->deleteLater();
0128 
0129             tryAgain();
0130             return;
0131         }
0132     }
0133 
0134     if (!m_session.isNull()) {
0135         m_session.data()->result()->setCompleted();
0136     } else {
0137         m_result->setCompleted();
0138     }
0139     m_session.data()->deleteLater();
0140 
0141     if (!m_dialog.isNull()) {
0142         m_dialog.data()->hide();
0143         m_dialog.data()->deleteLater();
0144     }
0145 
0146     m_inProgress = false;
0147 
0148     qDebug() << "Finish obtain authorization:" << m_gainedAuthorization;
0149 }
0150 
0151 bool PolicyKitListener::initiateAuthenticationFinish()
0152 {
0153     qDebug() << "Finishing authentication";
0154     return true;
0155 }
0156 
0157 void PolicyKitListener::cancelAuthentication()
0158 {
0159     qDebug() << "Cancelling authentication";
0160 
0161     m_wasCancelled = true;
0162     finishObtainPrivilege();
0163 }
0164 
0165 void PolicyKitListener::request(const QString &request, bool echo)
0166 {
0167     Q_UNUSED(echo);
0168     qDebug() << "Request: " << request;
0169 
0170     if (!m_dialog.isNull()) {
0171         m_dialog.data()->setRequest(request, m_selectedUser.isValid() && m_selectedUser.toString() == "unix-user:root");
0172     }
0173 }
0174 
0175 void PolicyKitListener::completed(bool gainedAuthorization)
0176 {
0177     qDebug() << "Completed: " << gainedAuthorization;
0178 
0179     m_gainedAuthorization = gainedAuthorization;
0180 
0181     finishObtainPrivilege();
0182 }
0183 
0184 void PolicyKitListener::showError(const QString &text)
0185 {
0186     qDebug() << "Error: " << text;
0187     if (!m_dialog.isNull()) {
0188         m_dialog.data()->showError(text);
0189     }
0190 }
0191 
0192 void PolicyKitListener::showInfo(const QString &text)
0193 {
0194     qDebug() << "Info: " << text;
0195     if (!m_dialog.isNull()) {
0196         m_dialog.data()->showInfo(text);
0197     }
0198 }
0199 
0200 void PolicyKitListener::dialogAccepted()
0201 {
0202     qDebug() << "Dialog accepted";
0203 
0204     if (!m_dialog.isNull()) {
0205         m_session.data()->setResponse(m_dialog.data()->password());
0206     }
0207 }
0208 
0209 void PolicyKitListener::dialogCanceled()
0210 {
0211     qDebug() << "Dialog cancelled";
0212 
0213     m_wasCancelled = true;
0214     if (!m_session.isNull()) {
0215         m_session.data()->cancel();
0216     }
0217 
0218     finishObtainPrivilege();
0219 }
0220 
0221 void PolicyKitListener::userSelected(const PolkitQt1::Identity &identity)
0222 {
0223     m_selectedUser = identity;
0224     // If some user is selected we must destroy existing session
0225     if (!m_session.isNull()) {
0226         m_session.data()->deleteLater();
0227     }
0228     tryAgain();
0229 }