signon  8.58
signondaemonadaptor.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of signon
3  *
4  * Copyright (C) 2009-2010 Nokia Corporation.
5  * Copyright (C) 2011 Intel Corporation.
6  * Copyright (C) 2013 Canonical Ltd.
7  *
8  * Contact: Aurel Popirtac <ext-aurel.popirtac@nokia.com>
9  * Contact: Alberto Mardegan <alberto.mardegan@canonical.com>
10  * Contact: Jussi Laako <jussi.laako@linux.intel.com>
11  *
12  * This library is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Lesser General Public License
14  * version 2.1 as published by the Free Software Foundation.
15  *
16  * This library is distributed in the hope that it will be useful, but
17  * WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with this library; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
24  * 02110-1301 USA
25  */
26 
27 #include "signondaemonadaptor.h"
28 #include "signondisposable.h"
30 
31 namespace SignonDaemonNS {
32 
33 SignonDaemonAdaptor::SignonDaemonAdaptor(SignonDaemon *parent):
34  QDBusAbstractAdaptor(parent),
35  m_parent(parent)
36 {
37  setAutoRelaySignals(false);
38 }
39 
40 SignonDaemonAdaptor::~SignonDaemonAdaptor()
41 {
42 }
43 
44 void SignonDaemonAdaptor::registerNewIdentity(QDBusObjectPath &objectPath)
45 {
46  QObject *identity = m_parent->registerNewIdentity();
47  objectPath = registerObject(parentDBusContext().connection(), identity);
48 
50 }
51 
52 void SignonDaemonAdaptor::securityErrorReply()
53 {
54  securityErrorReply(parentDBusContext().connection(),
55  parentDBusContext().message());
56 }
57 
58 void SignonDaemonAdaptor::securityErrorReply(const QDBusConnection &conn,
59  const QDBusMessage &msg)
60 {
61  QString errMsg;
62  QTextStream(&errMsg) << SIGNOND_PERMISSION_DENIED_ERR_STR
63  << "Method:"
64  << msg.member();
65 
66  msg.setDelayedReply(true);
67  QDBusMessage errReply =
68  msg.createErrorReply(SIGNOND_PERMISSION_DENIED_ERR_NAME,
69  errMsg);
70  conn.send(errReply);
71  TRACE() << "Method FAILED Access Control check:" << msg.member();
72 }
73 
74 bool SignonDaemonAdaptor::handleLastError(const QDBusConnection &conn,
75  const QDBusMessage &msg)
76 {
77  if (!m_parent->lastErrorIsValid()) return false;
78 
79  msg.setDelayedReply(true);
80  QDBusMessage errReply =
81  msg.createErrorReply(m_parent->lastErrorName(),
82  m_parent->lastErrorMessage());
83  conn.send(errReply);
84  return true;
85 }
86 
87 QDBusObjectPath
88 SignonDaemonAdaptor::registerObject(const QDBusConnection &connection,
89  QObject *object)
90 {
91  QString path = object->objectName();
92 
93  if (connection.objectRegisteredAt(path) != object) {
94  QDBusConnection conn(connection);
95  if (!conn.registerObject(path, object,
96  QDBusConnection::ExportAdaptors)) {
97  BLAME() << "Object registration failed:" << object <<
98  conn.lastError();
99  }
100  }
101  return QDBusObjectPath(path);
102 }
103 
104 void SignonDaemonAdaptor::getIdentity(const quint32 id,
105  QDBusObjectPath &objectPath,
106  QVariantMap &identityData)
107 {
109  QDBusMessage msg = parentDBusContext().message();
110  QDBusConnection conn = parentDBusContext().connection();
111  if (!acm->isPeerAllowedToUseIdentity(conn, msg, id)) {
112  SignOn::AccessReply *reply =
113  acm->requestAccessToIdentity(conn, msg, id);
114  QObject::connect(reply, SIGNAL(finished()),
115  this, SLOT(onIdentityAccessReplyFinished()));
116  msg.setDelayedReply(true);
117  return;
118  }
119 
120  QObject *identity = m_parent->getIdentity(id, identityData);
121  if (handleLastError(conn, msg)) return;
122 
123  objectPath = registerObject(conn, identity);
124 
126 }
127 
128 void SignonDaemonAdaptor::onIdentityAccessReplyFinished()
129 {
130  SignOn::AccessReply *reply = qobject_cast<SignOn::AccessReply*>(sender());
131  Q_ASSERT(reply != 0);
132 
133  reply->deleteLater();
134  QDBusConnection connection = reply->request().peerConnection();
135  QDBusMessage message = reply->request().peerMessage();
136  quint32 id = reply->request().identity();
138 
139  if (!reply->isAccepted() ||
140  !acm->isPeerAllowedToUseIdentity(connection, message, id)) {
141  securityErrorReply(connection, message);
142  return;
143  }
144 
145  QVariantMap identityData;
146  QObject *identity = m_parent->getIdentity(id, identityData);
147  if (handleLastError(connection, message)) return;
148 
149  QDBusObjectPath objectPath = registerObject(connection, identity);
150 
151  QVariantList args;
152  args << QVariant::fromValue(objectPath);
153  args << identityData;
154  connection.send(message.createReply(args));
155 
157 }
158 
160 {
161  return m_parent->queryMethods();
162 }
163 
165  const QString &type)
166 {
168 
170  QDBusMessage msg = parentDBusContext().message();
171  QDBusConnection conn = parentDBusContext().connection();
172 
173  /* Access Control */
174  if (id != SIGNOND_NEW_IDENTITY) {
175  if (!acm->isPeerAllowedToUseIdentity(conn, msg, id)) {
176  SignOn::AccessReply *reply =
177  acm->requestAccessToIdentity(conn, msg, id);
178  /* If the request is accepted, we'll need the method name ("type")
179  * in order to proceed with the creation of the authsession. */
180  reply->setProperty("type", type);
181  QObject::connect(reply, SIGNAL(finished()),
182  this, SLOT(onAuthSessionAccessReplyFinished()));
183  msg.setDelayedReply(true);
184  return QString();
185  }
186  }
187 
188  TRACE() << "ACM passed, creating AuthSession object";
189  pid_t ownerPid = acm->pidOfPeer(conn, msg);
190  QObject *authSession = m_parent->getAuthSession(id, type, ownerPid);
191  if (handleLastError(conn, msg)) return QString();
192 
193  QDBusObjectPath objectPath = registerObject(conn, authSession);
194  return objectPath.path();
195 }
196 
197 void SignonDaemonAdaptor::onAuthSessionAccessReplyFinished()
198 {
199  SignOn::AccessReply *reply = qobject_cast<SignOn::AccessReply*>(sender());
200  Q_ASSERT(reply != 0);
201 
202  reply->deleteLater();
203  QDBusConnection connection = reply->request().peerConnection();
204  QDBusMessage message = reply->request().peerMessage();
205  quint32 id = reply->request().identity();
206  QString type = reply->property("type").toString();
208 
209  if (!reply->isAccepted() ||
210  !acm->isPeerAllowedToUseIdentity(connection, message, id)) {
211  securityErrorReply(connection, message);
212  TRACE() << "still not allowed";
213  return;
214  }
215 
216  pid_t ownerPid = acm->pidOfPeer(connection, message);
217  QObject *authSession = m_parent->getAuthSession(id, type, ownerPid);
218  if (handleLastError(connection, message)) return;
219  QDBusObjectPath objectPath = registerObject(connection, authSession);
220 
221  QVariantList args;
222  args << QVariant::fromValue(objectPath);
223  connection.send(message.createReply(args));
224 
226 }
227 
228 QStringList SignonDaemonAdaptor::queryMechanisms(const QString &method)
229 {
230  QStringList mechanisms = m_parent->queryMechanisms(method);
231  if (handleLastError(parentDBusContext().connection(),
232  parentDBusContext().message())) {
233  return QStringList();
234  }
235 
236  return mechanisms;
237 }
238 
239 void SignonDaemonAdaptor::queryIdentities(const QVariantMap &filter)
240 {
241  /* Access Control */
242  QDBusMessage msg = parentDBusContext().message();
243  QDBusConnection conn = parentDBusContext().connection();
244  if (!AccessControlManagerHelper::instance()->isPeerKeychainWidget(conn,
245  msg)) {
246  securityErrorReply();
247  return;
248  }
249 
250  msg.setDelayedReply(true);
251  MapList identities = m_parent->queryIdentities(filter);
252  if (handleLastError(conn, msg)) return;
253 
254  QDBusMessage reply = msg.createReply(QVariant::fromValue(identities));
255  conn.send(reply);
256 }
257 
259 {
260  /* Access Control */
261  QDBusMessage msg = parentDBusContext().message();
262  QDBusConnection conn = parentDBusContext().connection();
263  if (!AccessControlManagerHelper::instance()->isPeerKeychainWidget(conn,
264  msg)) {
265  securityErrorReply();
266  return false;
267  }
268 
269  bool ok = m_parent->clear();
270  if (handleLastError(conn, msg)) return false;
271 
272  return ok;
273 }
274 
275 } //namespace SignonDaemonNS
void registerNewIdentity(QDBusObjectPath &objectPath)
#define BLAME()
Definition: debug.h:32
static AccessControlManagerHelper * instance()
QStringList queryMechanisms(const QString &method)
void getIdentity(const quint32 id, QDBusObjectPath &objectPath, QVariantMap &identityData)
static void destroyUnused()
Deletes all disposable object for which the inactivity time has elapsed.
void queryIdentities(const QVariantMap &filter)
QString getAuthSessionObjectPath(const quint32 id, const QString &type)
SignOn::AccessReply * requestAccessToIdentity(const QDBusConnection &peerConnection, const QDBusMessage &peerMessage, quint32 id)
static pid_t pidOfPeer(const QDBusContext &peerContext)
#define TRACE()
Definition: debug.h:28
Helper class for access control-related functionality.
Contains helper functions related to Access Control.
bool isPeerAllowedToUseIdentity(const QDBusConnection &peerConnection, const QDBusMessage &peerMessage, const quint32 identityId)
Checks if a client process is allowed to use a specific SignonIdentity.