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