signon  8.58
accesscontrolmanagerhelper.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /*
00003  * This file is part of signon
00004  *
00005  * Copyright (C) 2009-2010 Nokia Corporation.
00006  * Copyright (C) 2011 Intel Corporation.
00007  * Copyright (C) 2013 Canonical Ltd.
00008  *
00009  * Contact: Aurel Popirtac <ext-aurel.popirtac@nokia.com>
00010  * Contact: Alberto Mardegan <alberto.mardegan@canonical.com>
00011  * Contact: Elena Reshetova <elena.reshetova@intel.com>
00012  *
00013  * This library is free software; you can redistribute it and/or
00014  * modify it under the terms of the GNU Lesser General Public License
00015  * version 2.1 as published by the Free Software Foundation.
00016  *
00017  * This library is distributed in the hope that it will be useful, but
00018  * WITHOUT ANY WARRANTY; without even the implied warranty of
00019  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00020  * Lesser General Public License for more details.
00021  *
00022  * You should have received a copy of the GNU Lesser General Public
00023  * License along with this library; if not, write to the Free Software
00024  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
00025  * 02110-1301 USA
00026  */
00027 
00028 #include <QBuffer>
00029 #include <QDBusConnection>
00030 #include <QDBusConnectionInterface>
00031 #ifdef ENABLE_P2P
00032 #include <dbus/dbus.h>
00033 #endif
00034 
00035 #include "accesscontrolmanagerhelper.h"
00036 #include "signond-common.h"
00037 #include "credentialsaccessmanager.h"
00038 #include "signonidentity.h"
00039 
00040 using namespace SignonDaemonNS;
00041 
00042 AccessControlManagerHelper *AccessControlManagerHelper::m_pInstance = NULL;
00043 
00044 AccessControlManagerHelper *AccessControlManagerHelper::instance()
00045 {
00046     return m_pInstance;
00047 }
00048 
00049 AccessControlManagerHelper::AccessControlManagerHelper(
00050                                 SignOn::AbstractAccessControlManager *acManager)
00051 {
00052     if (!m_pInstance) {
00053         m_pInstance = this;
00054         m_acManager = acManager;
00055     } else {
00056         BLAME() << "Creating a second instance of the CAM";
00057     }
00058 }
00059 
00060 AccessControlManagerHelper::~AccessControlManagerHelper()
00061 {
00062     m_acManager = NULL;
00063     m_pInstance = NULL;
00064 }
00065 
00066 
00067 bool AccessControlManagerHelper::isPeerAllowedToUseIdentity(
00068                                        const QDBusConnection &peerConnection,
00069                                        const QDBusMessage &peerMessage,
00070                                        const quint32 identityId)
00071 {
00072     // TODO - improve this, the error handling and more precise behaviour
00073 
00074     CredentialsDB *db = CredentialsAccessManager::instance()->credentialsDB();
00075     if (db == 0) {
00076         TRACE() << "NULL db pointer, secure storage might be unavailable,";
00077         return false;
00078     }
00079     QStringList acl = db->accessControlList(identityId);
00080 
00081     TRACE() << QString(QLatin1String("Access control list of identity: "
00082                                  "%1: [%2].Tokens count: %3\t"))
00083                                 .arg(identityId)
00084                                 .arg(acl.join(QLatin1String(", ")))
00085                                 .arg(acl.size());
00086 
00087     if (db->errorOccurred())
00088         return false;
00089 
00090     IdentityOwnership ownership =
00091         isPeerOwnerOfIdentity(peerConnection, peerMessage, identityId);
00092     if (ownership == ApplicationIsOwner)
00093         return true;
00094 
00095     if (acl.isEmpty())
00096         return false;
00097 
00098     if (acl.contains(QLatin1String("*")))
00099         return true;
00100 
00101     return peerHasOneOfAccesses(peerConnection, peerMessage, acl);
00102 }
00103 
00104 AccessControlManagerHelper::IdentityOwnership
00105 AccessControlManagerHelper::isPeerOwnerOfIdentity(
00106                                        const QDBusConnection &peerConnection,
00107                                        const QDBusMessage &peerMessage,
00108                                        const quint32 identityId)
00109 {
00110     CredentialsDB *db = CredentialsAccessManager::instance()->credentialsDB();
00111     if (db == 0) {
00112         TRACE() << "NULL db pointer, secure storage might be unavailable,";
00113         return ApplicationIsNotOwner;
00114     }
00115     QStringList ownerSecContexts = db->ownerList(identityId);
00116 
00117     if (db->errorOccurred())
00118         return ApplicationIsNotOwner;
00119 
00120     if (ownerSecContexts.isEmpty())
00121         return IdentityDoesNotHaveOwner;
00122 
00123     return peerHasOneOfAccesses(peerConnection, peerMessage, ownerSecContexts) ?
00124         ApplicationIsOwner : ApplicationIsNotOwner;
00125 }
00126 
00127 bool
00128 AccessControlManagerHelper::isPeerKeychainWidget(
00129                                        const QDBusConnection &peerConnection,
00130                                        const QDBusMessage &peerMessage)
00131 {
00132     static QString keychainWidgetAppId = m_acManager->keychainWidgetAppId();
00133     QString peerAppId = appIdOfPeer(peerConnection, peerMessage);
00134     return (peerAppId == keychainWidgetAppId);
00135 }
00136 
00137 QString AccessControlManagerHelper::appIdOfPeer(
00138                                        const QDBusConnection &peerConnection,
00139                                        const QDBusMessage &peerMessage)
00140 {
00141     TRACE() << m_acManager->appIdOfPeer(peerConnection, peerMessage);
00142     return m_acManager->appIdOfPeer(peerConnection, peerMessage);
00143 }
00144 
00145 bool
00146 AccessControlManagerHelper::peerHasOneOfAccesses(
00147                                        const QDBusConnection &peerConnection,
00148                                        const QDBusMessage &peerMessage,
00149                                        const QStringList secContexts)
00150 {
00151     foreach(QString securityContext, secContexts)
00152     {
00153         TRACE() << securityContext;
00154         if (isPeerAllowedToAccess(peerConnection, peerMessage, securityContext))
00155             return true;
00156     }
00157 
00158     BLAME() << "given peer does not have needed permissions";
00159     return false;
00160 }
00161 
00162 bool
00163 AccessControlManagerHelper::isPeerAllowedToAccess(
00164                                        const QDBusConnection &peerConnection,
00165                                        const QDBusMessage &peerMessage,
00166                                        const QString securityContext)
00167 {
00168     TRACE() << securityContext;
00169     return m_acManager->isPeerAllowedToAccess(peerConnection, peerMessage,
00170                                               securityContext);
00171 }
00172 
00173 pid_t AccessControlManagerHelper::pidOfPeer(const QDBusContext &peerContext)
00174 {
00175     return pidOfPeer(peerContext.connection(), peerContext.message());
00176 }
00177 
00178 pid_t AccessControlManagerHelper::pidOfPeer(
00179                                        const QDBusConnection &peerConnection,
00180                                        const QDBusMessage &peerMessage)
00181 {
00182     QString service = peerMessage.service();
00183     if (service.isEmpty()) {
00184 #ifdef ENABLE_P2P
00185         DBusConnection *connection =
00186             (DBusConnection *)peerConnection.internalPointer();
00187         unsigned long pid = 0;
00188         dbus_bool_t ok = dbus_connection_get_unix_process_id(connection,
00189                                                              &pid);
00190         if (Q_UNLIKELY(!ok)) {
00191             BLAME() << "Couldn't get PID of caller!";
00192             return 0;
00193         }
00194         return pid;
00195 #else
00196         BLAME() << "Empty caller name, and no P2P support enabled";
00197         return 0;
00198 #endif
00199     } else {
00200         return peerConnection.interface()->servicePid(service).value();
00201     }
00202 }
00203 
00204 SignOn::AccessReply *
00205 AccessControlManagerHelper::requestAccessToIdentity(
00206                                        const QDBusConnection &peerConnection,
00207                                        const QDBusMessage &peerMessage,
00208                                        quint32 id)
00209 {
00210     SignOn::AccessRequest request;
00211     request.setPeer(peerConnection, peerMessage);
00212     request.setIdentity(id);
00213     return m_acManager->handleRequest(request);
00214 }