signon  8.58
signondaemonadaptor.cpp
Go to the documentation of this file.
00001 /*
00002  * This file is part of signon
00003  *
00004  * Copyright (C) 2009-2010 Nokia Corporation.
00005  * Copyright (C) 2011 Intel Corporation.
00006  * Copyright (C) 2013 Canonical Ltd.
00007  *
00008  * Contact: Aurel Popirtac <ext-aurel.popirtac@nokia.com>
00009  * Contact: Alberto Mardegan <alberto.mardegan@canonical.com>
00010  * Contact: Jussi Laako <jussi.laako@linux.intel.com>
00011  *
00012  * This library is free software; you can redistribute it and/or
00013  * modify it under the terms of the GNU Lesser General Public License
00014  * version 2.1 as published by the Free Software Foundation.
00015  *
00016  * This library is distributed in the hope that it will be useful, but
00017  * WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00019  * Lesser General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU Lesser General Public
00022  * License along with this library; if not, write to the Free Software
00023  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
00024  * 02110-1301 USA
00025  */
00026 
00027 #include "signondaemonadaptor.h"
00028 #include "signondisposable.h"
00029 #include "accesscontrolmanagerhelper.h"
00030 
00031 namespace SignonDaemonNS {
00032 
00033 SignonDaemonAdaptor::SignonDaemonAdaptor(SignonDaemon *parent):
00034     QDBusAbstractAdaptor(parent),
00035     m_parent(parent)
00036 {
00037     setAutoRelaySignals(false);
00038 }
00039 
00040 SignonDaemonAdaptor::~SignonDaemonAdaptor()
00041 {
00042 }
00043 
00044 void SignonDaemonAdaptor::registerNewIdentity(QDBusObjectPath &objectPath)
00045 {
00046     QObject *identity = m_parent->registerNewIdentity();
00047     objectPath = registerObject(parentDBusContext().connection(), identity);
00048 
00049     SignonDisposable::destroyUnused();
00050 }
00051 
00052 void SignonDaemonAdaptor::securityErrorReply()
00053 {
00054     securityErrorReply(parentDBusContext().connection(),
00055                        parentDBusContext().message());
00056 }
00057 
00058 void SignonDaemonAdaptor::securityErrorReply(const QDBusConnection &conn,
00059                                              const QDBusMessage &msg)
00060 {
00061     QString errMsg;
00062     QTextStream(&errMsg) << SIGNOND_PERMISSION_DENIED_ERR_STR
00063                          << "Method:"
00064                          << msg.member();
00065 
00066     msg.setDelayedReply(true);
00067     QDBusMessage errReply =
00068                 msg.createErrorReply(SIGNOND_PERMISSION_DENIED_ERR_NAME,
00069                                      errMsg);
00070     conn.send(errReply);
00071     TRACE() << "Method FAILED Access Control check:" << msg.member();
00072 }
00073 
00074 bool SignonDaemonAdaptor::handleLastError(const QDBusConnection &conn,
00075                                           const QDBusMessage &msg)
00076 {
00077     if (!m_parent->lastErrorIsValid()) return false;
00078 
00079     msg.setDelayedReply(true);
00080     QDBusMessage errReply =
00081                 msg.createErrorReply(m_parent->lastErrorName(),
00082                                      m_parent->lastErrorMessage());
00083     conn.send(errReply);
00084     return true;
00085 }
00086 
00087 QDBusObjectPath
00088 SignonDaemonAdaptor::registerObject(const QDBusConnection &connection,
00089                                     QObject *object)
00090 {
00091     QString path = object->objectName();
00092 
00093     if (connection.objectRegisteredAt(path) != object) {
00094         QDBusConnection conn(connection);
00095         if (!conn.registerObject(path, object,
00096                                  QDBusConnection::ExportAdaptors)) {
00097             BLAME() << "Object registration failed:" << object <<
00098                 conn.lastError();
00099         }
00100     }
00101     return QDBusObjectPath(path);
00102 }
00103 
00104 void SignonDaemonAdaptor::getIdentity(const quint32 id,
00105                                       QDBusObjectPath &objectPath,
00106                                       QVariantMap &identityData)
00107 {
00108     AccessControlManagerHelper *acm = AccessControlManagerHelper::instance();
00109     QDBusMessage msg = parentDBusContext().message();
00110     QDBusConnection conn = parentDBusContext().connection();
00111     if (!acm->isPeerAllowedToUseIdentity(conn, msg, id)) {
00112         SignOn::AccessReply *reply =
00113             acm->requestAccessToIdentity(conn, msg, id);
00114         QObject::connect(reply, SIGNAL(finished()),
00115                          this, SLOT(onIdentityAccessReplyFinished()));
00116         msg.setDelayedReply(true);
00117         return;
00118     }
00119 
00120     QObject *identity = m_parent->getIdentity(id, identityData);
00121     if (handleLastError(conn, msg)) return;
00122 
00123     objectPath = registerObject(conn, identity);
00124 
00125     SignonDisposable::destroyUnused();
00126 }
00127 
00128 void SignonDaemonAdaptor::onIdentityAccessReplyFinished()
00129 {
00130     SignOn::AccessReply *reply = qobject_cast<SignOn::AccessReply*>(sender());
00131     Q_ASSERT(reply != 0);
00132 
00133     reply->deleteLater();
00134     QDBusConnection connection = reply->request().peerConnection();
00135     QDBusMessage message = reply->request().peerMessage();
00136     quint32 id = reply->request().identity();
00137     AccessControlManagerHelper *acm = AccessControlManagerHelper::instance();
00138 
00139     if (!reply->isAccepted() ||
00140         !acm->isPeerAllowedToUseIdentity(connection, message, id)) {
00141         securityErrorReply(connection, message);
00142         return;
00143     }
00144 
00145     QVariantMap identityData;
00146     QObject *identity = m_parent->getIdentity(id, identityData);
00147     if (handleLastError(connection, message)) return;
00148 
00149     QDBusObjectPath objectPath = registerObject(connection, identity);
00150 
00151     QVariantList args;
00152     args << QVariant::fromValue(objectPath);
00153     args << identityData;
00154     connection.send(message.createReply(args));
00155 
00156     SignonDisposable::destroyUnused();
00157 }
00158 
00159 QStringList SignonDaemonAdaptor::queryMethods()
00160 {
00161     return m_parent->queryMethods();
00162 }
00163 
00164 QString SignonDaemonAdaptor::getAuthSessionObjectPath(const quint32 id,
00165                                                       const QString &type)
00166 {
00167     SignonDisposable::destroyUnused();
00168 
00169     AccessControlManagerHelper *acm = AccessControlManagerHelper::instance();
00170     QDBusMessage msg = parentDBusContext().message();
00171     QDBusConnection conn = parentDBusContext().connection();
00172 
00173     /* Access Control */
00174     if (id != SIGNOND_NEW_IDENTITY) {
00175         if (!acm->isPeerAllowedToUseIdentity(conn, msg, id)) {
00176             SignOn::AccessReply *reply =
00177                 acm->requestAccessToIdentity(conn, msg, id);
00178             /* If the request is accepted, we'll need the method name ("type")
00179              * in order to proceed with the creation of the authsession. */
00180             reply->setProperty("type", type);
00181             QObject::connect(reply, SIGNAL(finished()),
00182                              this, SLOT(onAuthSessionAccessReplyFinished()));
00183             msg.setDelayedReply(true);
00184             return QString();
00185         }
00186     }
00187 
00188     TRACE() << "ACM passed, creating AuthSession object";
00189     pid_t ownerPid = acm->pidOfPeer(conn, msg);
00190     QObject *authSession = m_parent->getAuthSession(id, type, ownerPid);
00191     if (handleLastError(conn, msg)) return QString();
00192 
00193     QDBusObjectPath objectPath = registerObject(conn, authSession);
00194     return objectPath.path();
00195 }
00196 
00197 void SignonDaemonAdaptor::onAuthSessionAccessReplyFinished()
00198 {
00199     SignOn::AccessReply *reply = qobject_cast<SignOn::AccessReply*>(sender());
00200     Q_ASSERT(reply != 0);
00201 
00202     reply->deleteLater();
00203     QDBusConnection connection = reply->request().peerConnection();
00204     QDBusMessage message = reply->request().peerMessage();
00205     quint32 id = reply->request().identity();
00206     QString type = reply->property("type").toString();
00207     AccessControlManagerHelper *acm = AccessControlManagerHelper::instance();
00208 
00209     if (!reply->isAccepted() ||
00210         !acm->isPeerAllowedToUseIdentity(connection, message, id)) {
00211         securityErrorReply(connection, message);
00212         TRACE() << "still not allowed";
00213         return;
00214     }
00215 
00216     pid_t ownerPid = acm->pidOfPeer(connection, message);
00217     QObject *authSession = m_parent->getAuthSession(id, type, ownerPid);
00218     if (handleLastError(connection, message)) return;
00219     QDBusObjectPath objectPath = registerObject(connection, authSession);
00220 
00221     QVariantList args;
00222     args << QVariant::fromValue(objectPath);
00223     connection.send(message.createReply(args));
00224 
00225     SignonDisposable::destroyUnused();
00226 }
00227 
00228 QStringList SignonDaemonAdaptor::queryMechanisms(const QString &method)
00229 {
00230     QStringList mechanisms = m_parent->queryMechanisms(method);
00231     if (handleLastError(parentDBusContext().connection(),
00232                         parentDBusContext().message())) {
00233         return QStringList();
00234     }
00235 
00236     return mechanisms;
00237 }
00238 
00239 void SignonDaemonAdaptor::queryIdentities(const QVariantMap &filter)
00240 {
00241     /* Access Control */
00242     QDBusMessage msg = parentDBusContext().message();
00243     QDBusConnection conn = parentDBusContext().connection();
00244     if (!AccessControlManagerHelper::instance()->isPeerKeychainWidget(conn,
00245                                                                       msg)) {
00246         securityErrorReply();
00247         return;
00248     }
00249 
00250     msg.setDelayedReply(true);
00251     MapList identities = m_parent->queryIdentities(filter);
00252     if (handleLastError(conn, msg)) return;
00253 
00254     QDBusMessage reply = msg.createReply(QVariant::fromValue(identities));
00255     conn.send(reply);
00256 }
00257 
00258 bool SignonDaemonAdaptor::clear()
00259 {
00260     /* Access Control */
00261     QDBusMessage msg = parentDBusContext().message();
00262     QDBusConnection conn = parentDBusContext().connection();
00263     if (!AccessControlManagerHelper::instance()->isPeerKeychainWidget(conn,
00264                                                                       msg)) {
00265         securityErrorReply();
00266         return false;
00267     }
00268 
00269     bool ok = m_parent->clear();
00270     if (handleLastError(conn, msg)) return false;
00271 
00272     return ok;
00273 }
00274 
00275 } //namespace SignonDaemonNS