signon
8.58
|
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