KAuth

Polkit1Backend.cpp
1 /*
2  SPDX-FileCopyrightText: 2008 Nicola Gigante <[email protected]>
3  SPDX-FileCopyrightText: 2009 Radek Novacek <[email protected]>
4  SPDX-FileCopyrightText: 2009-2010 Dario Freddi <[email protected]>
5  SPDX-FileCopyrightText: 2020 David Edmundson <[email protected]>
6 
7  SPDX-License-Identifier: LGPL-2.1-or-later
8 */
9 
10 #include "Polkit1Backend.h"
11 #include "kauthdebug.h"
12 
13 #include <QCoreApplication>
14 #include <QTimer>
15 #include <qplugin.h>
16 
17 #include <QApplication>
18 #include <QWidget>
19 
20 #include <QDBusConnection>
21 #include <QDBusConnectionInterface>
22 
23 #include <PolkitQt1/Subject>
24 #include <polkitqt1-version.h>
25 
26 namespace KAuth
27 {
28 Polkit1Backend::Polkit1Backend()
29  : AuthBackend()
30 {
31  setCapabilities(AuthorizeFromHelperCapability | CheckActionExistenceCapability | PreAuthActionCapability);
32 
33  // Setup useful signals
34  connect(PolkitQt1::Authority::instance(), &PolkitQt1::Authority::configChanged, this, &KAuth::Polkit1Backend::checkForResultChanged);
35  connect(PolkitQt1::Authority::instance(), &PolkitQt1::Authority::consoleKitDBChanged, this, &KAuth::Polkit1Backend::checkForResultChanged);
36 }
37 
38 Polkit1Backend::~Polkit1Backend()
39 {
40 }
41 
42 void Polkit1Backend::preAuthAction(const QString &action, QWidget *parent)
43 {
44  // If a parent was not specified, skip this
45  if (!parent) {
46  qCDebug(KAUTH) << "Parent widget does not exist, skipping";
47  return;
48  }
49 
50  // Are we running our KDE auth agent?
51  if (QDBusConnection::sessionBus().interface()->isServiceRegistered(QLatin1String("org.kde.polkit-kde-authentication-agent-1"))) {
52  // Check if we actually are entitled to use GUI capabilities
53  if (qApp == nullptr || !qobject_cast<QApplication *>(qApp)) {
54  qCDebug(KAUTH) << "Not streaming parent as we are on a TTY application";
55  }
56 
57  // Retrieve the dialog root window Id
58  qulonglong wId = parent->effectiveWinId();
59 
60  // Send it over the bus to our agent
61  QDBusMessage methodCall = QDBusMessage::createMethodCall(QLatin1String("org.kde.polkit-kde-authentication-agent-1"),
62  QLatin1String("/org/kde/Polkit1AuthAgent"),
63  QLatin1String("org.kde.Polkit1AuthAgent"),
64  QLatin1String("setWIdForAction"));
65 
66  methodCall << action;
67  methodCall << wId;
68 
70  call.waitForFinished();
71 
72  if (call.isError()) {
73  qCWarning(KAUTH) << "ERROR while streaming the parent!!" << call.error();
74  }
75  } else {
76  qCDebug(KAUTH) << "KDE polkit agent appears too old or not registered on the bus";
77  }
78 }
79 
80 Action::AuthStatus Polkit1Backend::authorizeAction(const QString &action)
81 {
82  Q_UNUSED(action)
83  // Always return Yes here, we'll authorize inside isCallerAuthorized
85 }
86 
87 void Polkit1Backend::setupAction(const QString &action)
88 {
89  m_cachedResults[action] = actionStatus(action);
90 }
91 
92 Action::AuthStatus Polkit1Backend::actionStatus(const QString &action)
93 {
95  auto authority = PolkitQt1::Authority::instance();
96  PolkitQt1::Authority::Result r = authority->checkAuthorizationSync(action, subject, PolkitQt1::Authority::None);
97 
98  if (authority->hasError()) {
99  qCDebug(KAUTH) << "Encountered error while checking action status, error code:" << authority->lastError() << authority->errorDetails();
100  authority->clearError();
101  return Action::InvalidStatus;
102  }
103 
104  switch (r) {
109  return Action::DeniedStatus;
110  default:
112  }
113 }
114 
115 QByteArray Polkit1Backend::callerID() const
116 {
118 }
119 
120 AuthBackend::ExtraCallerIDVerificationMethod Polkit1Backend::extraCallerIDVerificationMethod() const
121 {
122  return VerifyAgainstDBusServiceName;
123 }
124 
125 bool Polkit1Backend::isCallerAuthorized(const QString &action, const QByteArray &callerID, const QVariantMap &details)
126 {
129  QMap<QString, QString> polkit1Details;
130  for (auto it = details.cbegin(); it != details.cend(); ++it) {
131  polkit1Details.insert(it.key(), it.value().toString());
132  }
133 
135  QEventLoop e;
136  connect(authority, &PolkitQt1::Authority::checkAuthorizationFinished, &e, [&result, &e](PolkitQt1::Authority::Result _result) {
137  result = _result;
138  e.quit();
139  });
140 
141 #if POLKITQT1_IS_VERSION(0, 113, 0)
142  authority->checkAuthorizationWithDetails(action, subject, PolkitQt1::Authority::AllowUserInteraction, polkit1Details);
143 #else
145 #endif
146  e.exec();
147 
148  if (authority->hasError()) {
149  qCDebug(KAUTH) << "Encountered error while checking authorization, error code:" << authority->lastError() << authority->errorDetails();
150  authority->clearError();
151  }
152 
153  switch (result) {
155  return true;
156  default:
157  return false;
158  }
159 }
160 
161 void Polkit1Backend::checkForResultChanged()
162 {
163  for (auto it = m_cachedResults.begin(); it != m_cachedResults.end(); ++it) {
164  const QString action = it.key();
165  if (it.value() != actionStatus(action)) {
166  *it = actionStatus(action);
167  Q_EMIT actionStatusChanged(action, *it);
168  }
169  }
170 }
171 
172 bool Polkit1Backend::actionExists(const QString &action)
173 {
174  return m_cachedResults.value(action) != Action::InvalidStatus;
175 }
176 
177 QVariantMap Polkit1Backend::backendDetails(const DetailsMap &details)
178 {
179  QVariantMap backendDetails;
180  for (auto it = details.cbegin(); it != details.cend(); ++it) {
181  switch (it.key()) {
183  backendDetails.insert(QStringLiteral("polkit.message"), it.value());
184  break;
185  case Action::AuthDetail::DetailOther:
186  default:
187  backendDetails.insert(QStringLiteral("other_details"), it.value());
188  break;
189  }
190  }
191  return backendDetails;
192 }
193 
194 } // namespace Auth
bool hasError() const
QString fromUtf8(const char *str, int size)
@ AuthorizedStatus
The authorization has been granted by the authorization backend.
Definition: action.h:86
AuthStatus
The three values set by authorization methods.
Definition: action.h:82
int exec(QEventLoop::ProcessEventsFlags flags)
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QString baseService() const const
QMap::iterator insert(const Key &key, const T &value)
QDBusConnection sessionBus()
void quit()
void checkAuthorizationFinished(PolkitQt1::Authority::Result)
QByteArray toUtf8() const const
void checkAuthorization(const QString &actionId, const Subject &subject, AuthorizationFlags flags)
QDBusMessage createMethodCall(const QString &service, const QString &path, const QString &interface, const QString &method)
static Authority * instance(PolkitAuthority *authority=nullptr)
Definition: action.cpp:18
const QString errorDetails() const
@ InvalidStatus
An invalid action cannot be authorized.
Definition: action.h:85
QDBusConnection systemBus()
WId effectiveWinId() const const
@ DeniedStatus
The authorization has been denied by the authorization backend.
Definition: action.h:83
ErrorCode lastError() const
@ AuthRequiredStatus
The user could obtain the authorization after authentication.
Definition: action.h:87
@ DetailMessage
The message to show in authentication dialog.
void checkAuthorizationWithDetails(const QString &actionId, const Subject &subject, AuthorizationFlags flags, const DetailsMap &details)
QDBusPendingCall asyncCall(const QDBusMessage &message, int timeout) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Sun Feb 5 2023 04:14:58 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.