}
void Logic::addEvent(Protocol::ConnectionFd fd, Protocol::RequestId id,
- const std::map<Privilege, std::vector<Privacy>> &privsToAskablePrivacies,
- const std::map<Privilege, Policy> &privsToPolicy,
- const std::vector<Privilege> &privs,
- const std::vector<Privacy> &privacies) {
+ const std::vector<Privacy> &privacies,
+ const std::vector<PrivilegeStruct> &privilegesStructure) {
EventId eventId{fd, id};
auto &ev = m_eventInfo[eventId];
- PrivaciesSequence &seq = ev.privaciesSeq;
- seq.setPrivacies(privacies);
- ev.privilegesAskablePrivacies = privsToAskablePrivacies;
- ev.privilegesPolicy = privsToPolicy;
- ev.privileges = privs;
+ ev.uniquePrivacies = privacies;
+ ev.privilegesStructure = privilegesStructure;
ev.privacyResponses.clear();
ConnectionInfo &conn = m_connToInfo[fd];
- Privacy currentPrivacy;
- seq.getNextPrivacy(currentPrivacy);
-
- FdEvent fdEvent{eventId, std::unique_ptr<IUIEvent>(new EventPopupCheck(&m_popupper, conn.pkgId, currentPrivacy))};
+ FdEvent fdEvent{eventId, std::unique_ptr<IUIEvent>(new EventPopupCheck(&m_popupper, conn.pkgId, privacies))};
m_pendingEvents.emplace_back(std::move(fdEvent));
}
}
ConnectionInfo &conn = it->second;
PkgMgrAppInfo appInfo;
- std::map<Privilege, std::vector<Privacy>> privsToAskablePrivacies;
- std::map<Privilege, Policy> privsToPolicy;
std::set<Privacy> uniquePrivacies;
+ std::vector<PrivilegeStruct> privilegesStructure;
for (auto &privilege : privileges) {
+ PrivilegeStruct privStruct;
+ privStruct.privilege = privilege;
PrivilegePolicy privPolicy(conn.appId, privilege);
- privsToPolicy[privilege] = privPolicy.calculatePolicy(appInfo);
- ALOGD("Privilege " << privilege << " policy level calculated to : " << privsToPolicy[privilege]);
- if (privsToPolicy[privilege] == "Ask user") {
- privsToAskablePrivacies[privilege] = privPolicy.calculateAskablePrivacies(appInfo);
- if (privsToAskablePrivacies[privilege].empty()) {
+ privStruct.policy = privPolicy.calculatePolicy(appInfo);
+ ALOGD("Privilege " << privilege << " policy level calculated to : " << privStruct.policy);
+ if (privStruct.policy == "Ask user") {
+ privStruct.askablePrivacies = privPolicy.calculateAskablePrivacies(appInfo);
+ if (privStruct.askablePrivacies.empty()) {
ALOGE("All privacies for privilege " << privilege << " are already allowed");
- privsToPolicy[privilege] = "Allow";
+ privStruct.policy = "Allow";
} else {
- for (auto &privacy : privsToAskablePrivacies[privilege])
+ for (auto &privacy : privStruct.askablePrivacies)
uniquePrivacies.insert(privacy);
}
}
+ privilegesStructure.push_back(std::move(privStruct));
}
if (uniquePrivacies.empty()) {
std::vector<int> responses;
responses.resize(privileges.size());
for (size_t i = 0; i < privileges.size(); ++i) {
- if (privsToPolicy[privileges[i]] == "Allow") {
+ if (privilegesStructure[i].policy == "Allow") {
responses[i] = ASKUSER_ALLOW_FOREVER;
- } else if (privsToPolicy[privileges[i]] == "Deny") {
+ } else if (privilegesStructure[i].policy == "Deny") {
responses[i] = ASKUSER_DENY_FOREVER;
} else {
- ALOGE("Unknown policy set : " << privsToPolicy[privileges[i]] << " for (" << conn.appId << ", " << conn.user
+ ALOGE("Unknown policy set : " << privilegesStructure[i].policy << " for (" << conn.appId << ", " << conn.user
<< ", " << privileges[i] << ")");
responses[i] = ASKUSER_DENY_ONCE;
}
// we do have privacies to ask about, we need to generate event
std::vector<Privacy> privacies(uniquePrivacies.begin(), uniquePrivacies.end());
- addEvent(fd, id, privsToAskablePrivacies, privsToPolicy, privileges, privacies);
+ addEvent(fd, id, privacies, privilegesStructure);
processEvents();
} catch (const std::exception &e) {
init_agent_log();
m_popupper.initialize();
Po::setLocale();
- m_popupper.registerPopupResponseHandler([&](NResponseType response) { popupResponse(response);});
+ m_popupper.registerPopupResponseHandler([&](std::vector<NResponseType> responses) { popupResponses(responses);});
registerSignalFd();
bool Logic::setPolicy(const ConnectionInfo &conn) {
ALOGD("Setting policy for app " << conn.appId);
- for (auto &pr : m_eventInfo[m_currentEvent].privacyResponses) {
- const auto &level = clientResponseToPolicy(pr.second);
- if (!PolicyUpdater::update(conn.appId, pr.first, level)) {
- ALOGE("Couldn't set policy for " << conn.appId << " privacy : " << pr.first << " level : " << level);
- return false;
- }
+ auto ¤tEvent = m_eventInfo[m_currentEvent];
+ std::vector<std::string> levels(currentEvent.uniquePrivacies.size());
+
+ for (size_t i = 0; i < levels.size(); ++i) {
+ const auto &privacy = currentEvent.uniquePrivacies[i];
+ levels[i] = clientResponseToPolicy(currentEvent.privacyResponses[privacy]);
}
+
+ if (!PolicyUpdater::update(conn.appId, currentEvent.uniquePrivacies, levels)) {
+ ALOGE("Couldn't set policy for " << conn.appId);
+ return false;
+ }
+
return true;
}
void Logic::processResponse(const ConnectionInfo &conn) {
auto ¤tEvent = m_eventInfo[m_currentEvent];
- std::vector<int> responses(currentEvent.privileges.size(), ASKUSER_UNKNOWN_ERROR);
+ std::vector<int> responses(currentEvent.privilegesStructure.size(), ASKUSER_UNKNOWN_ERROR);
if (setPolicy(conn)) {
for (size_t i = 0; i < responses.size(); ++i) {
- const auto &privilege = currentEvent.privileges[i];
- const auto &policy = currentEvent.privilegesPolicy[privilege];
+ const auto &privilegeStruct = currentEvent.privilegesStructure[i];
+ const auto &policy = privilegeStruct.policy;
if (policy == "Allow") {
responses[i] = ASKUSER_ALLOW_FOREVER;
} else if (policy == "Deny") {
// Ask user policy - need to calcualte from existing responses to privacies
// but only privacies askable for this privilege should be used!
responses[i] = ASKUSER_ALLOW_FOREVER;
- bool hasAnswer = false;
- for (auto &privacy : currentEvent.privilegesAskablePrivacies[privilege]) {
- const auto &privResponses = currentEvent.privacyResponses;
- const auto privResponseIt = privResponses.find(privacy);
- if (privResponseIt != privResponses.end()) {
+ for (auto &privacy : privilegeStruct.askablePrivacies) {
+ const auto &privResponseIt = currentEvent.privacyResponses.find(privacy);
+ if (privResponseIt != currentEvent.privacyResponses.end()) {
responses[i] = std::min(privResponseIt->second, responses[i]);
- hasAnswer = true;
+ }
+ else {
+ ALOGE("Unable to response for askable privacy: " << privacy);
+ responses[i] = ASKUSER_DENY_ONCE;
+ break;
}
}
- if (!hasAnswer)
- responses[i] = ASKUSER_DENY_ONCE;
}
}
}
m_serverChannel->popupResponses(m_currentEvent.fd, m_currentEvent.id, std::move(responses));
}
-void Logic::popupResponse(NResponseType response) {
+void Logic::popupResponses(const std::vector<NResponseType> &responses) {
auto it = m_connToInfo.find(m_currentEvent.fd);
+
if (it == m_connToInfo.end()) {
ALOGE("Got response from inactive fd " << m_currentEvent.fd);
return;
}
+
ConnectionInfo &conn = it->second;
- PrivaciesSequence &seq = m_eventInfo[m_currentEvent].privaciesSeq;
- int clientResponse = uiResponseToClientResponse(response);
+ auto ¤tEvent = m_eventInfo[m_currentEvent];
- std::string justAnsweredPrivacy;
- if (!seq.getCurrentPrivacy(justAnsweredPrivacy)) {
- ALOGE("Received response for unknown privacy - this should not happen");
+ if (responses.size() != currentEvent.uniquePrivacies.size()) {
+ ALOGE("Got invalid number of responses: " << responses.size() << " but expected: "
+ << currentEvent.uniquePrivacies.size());
finishCurrentRequest();
processEvents();
return;
}
- m_eventInfo[m_currentEvent].privacyResponses[justAnsweredPrivacy] = clientResponse;
- if (clientResponse != ASKUSER_ALLOW_FOREVER && m_eventInfo[m_currentEvent].privileges.size() == 1) {
- // request for only 1 privilege is being processed and at least 1 privacy is not allowed
- // stop iteration over privacies, its pointless as the privilege is alraedy dissallowed
- processResponse(conn);
- finishCurrentRequest();
- } else {
- // request for many privileges is being processed or one privilege but still needs to be processed
- Privacy nextPrivacy;
- if (seq.getNextPrivacy(nextPrivacy)) {
- // More privacies to process - replace existing event with new privacy
- FdEvent fdEvent{m_currentEvent, std::unique_ptr<IUIEvent>(new EventPopupCheck(&m_popupper, conn.pkgId, nextPrivacy))};
- m_pendingEvents[0] = std::move(fdEvent);
- // don't call finishCurrentRequest here, because it will pop event, which we replaced
- m_currentEvent = EventId();
- } else {
- // No more privacies, request is ready for response
- processResponse(conn);
- finishCurrentRequest();
- }
+
+ for (size_t i = 0; i < responses.size(); ++i) {
+ int clientResponse = uiResponseToClientResponse(responses[i]);
+ const auto &privacy = currentEvent.uniquePrivacies[i];
+ ALOGD("Client response for privacy " << privacy << " is " << clientResponse);
+ currentEvent.privacyResponses[privacy] = clientResponse;
}
+
+ // No more privacies, since all are answered by one popup - request is ready for response
+ processResponse(conn);
+ finishCurrentRequest();
processEvents();
}
#include <Elementary.h>
#include "event/Event.h"
-#include "PrivaciesSequence.h"
namespace AskUser {
std::string user;
};
+ struct PrivilegeStruct {
+ Privilege privilege;
+ Policy policy;
+ std::vector<Privacy> askablePrivacies;
+ };
+
//Initialization
void registerSignalFd();
void prepareChannel();
//static Eina_Bool signalHandler(void *data, int type, void *event);
void addEvent(Protocol::ConnectionFd fd, Protocol::RequestId id,
- const std::map<Privilege, std::vector<Privacy>> &privsToAskablePrivacies,
- const std::map<Privilege, Policy> &privsToPolicy,
- const std::vector<Privilege> &privs,
- const std::vector<Privacy> &privacies);
+ const std::vector<Privacy> &privacies,
+ const std::vector<PrivilegeStruct> &privilegesStructure);
Eina_Bool processChannel(int fd, int mask);
bool identifyClient(const std::string &label, std::string &appId, std::string &pkgId);
void startTimer();
void stopTimer();
- void popupResponse(NResponseType response);
+ void popupResponses(const std::vector<NResponseType> &response);
bool processError(EventId id, int error);
bool setPolicy(const ConnectionInfo &conn);
std::map<Protocol::ConnectionFd, ConnectionInfo> m_connToInfo;
struct EventInfo {
- PrivaciesSequence privaciesSeq;
- std::vector<Privilege> privileges;
- std::map<Privilege, std::vector<Privacy>> privilegesAskablePrivacies;
- std::map<Privilege, Policy> privilegesPolicy;
+ std::vector<Privacy> uniquePrivacies; // privacies placement order is important,
+ // UI will only send back responses, so then Logic has to map responses to privacies
+ std::vector<PrivilegeStruct> privilegesStructure;
std::map<Privacy, int> privacyResponses;
};
/*
- * Copyright (c) 2016-2017 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2016-2018 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
/**
* @file PolicyUpdater.cpp
* @author Zofia Abramowska <z.abramowska@samsung.com>
+ * @author Tomasz Swierczek <t.swierczek@samsung.com>
* @brief This file implements class of policy updater
*/
namespace Notification {
-bool PolicyUpdater::update(const std::string &appId,
- const std::string &privacy, const std::string &level)
+bool PolicyUpdater::update(const std::string &appId, const std::vector<std::string> &privacies,
+ const std::vector<std::string> &levels)
{
try {
- ALOGD("Generating policy update for: app: " << appId << ", privacy: " << privacy
- << ", user:" << geteuid() << ", level: " << level);
+ ALOGD("Generating policy update for: app: " << appId << ", user:" << geteuid()
+ << ", privacies num: " << privacies.size());
+
+ if (privacies.size() != levels.size() || levels.size() == 0) {
+ ALOGE("Policy update for invalid parameres");
+ return false;
+ }
static const std::string user = std::to_string(geteuid());
PolicyRequest req;
- auto privacyPrivs = PrivilegeInfo::getPrivacyPrivileges(privacy);
- if (privacyPrivs.empty()) {
- ALOGE("Unable to get privacy privileges for privacy " << privacy);
- throw Exception("Unable to get privacy privileges for privacy " + privacy);
- }
+ for (size_t i = 0; i < privacies.size(); ++i) {
+ const auto &privacy = privacies[i];
+ const auto &level = levels[i];
+
+ ALOGD("Generating policy update for: app: " << appId << ", user:" << geteuid()
+ << ", privacy " << privacy << ", level: " << level);
+
+ auto privacyPrivs = PrivilegeInfo::getPrivacyPrivileges(privacy);
+ if (privacyPrivs.empty()) {
+ ALOGE("Unable to get privacy privileges for privacy " << privacy);
+ throw Exception("Unable to get privacy privileges for privacy " + privacy);
+ }
- for (auto &priv : privacyPrivs) {
- std::string currentPolicy = getPrivilegePolicy(appId, priv);
- if (currentPolicy.empty()) {
- ALOGD("Application didn't request privilege " << priv << ", skipping");
- continue;
+ for (auto &priv : privacyPrivs) {
+ std::string currentPolicy = getPrivilegePolicy(appId, priv);
+ if (currentPolicy.empty()) {
+ ALOGD("Application didn't request privilege " << priv << ", skipping");
+ continue;
+ }
+ ALOGD("Adding policy entries for : app: " << appId << ", priv: "
+ << priv << ", user:" << user << ", level: "
+ << level);
+ PolicyEntry entry;
+ entry.setApp(appId);
+ entry.setUser(user);
+ entry.setPrivilege(priv);
+ entry.setLevel(level);
+ req.addEntry(std::move(entry));
}
- ALOGD("Adding policy entries for : app: " << appId << ", priv: "
- << priv << ", user:" << user << ", level: "
- << level);
- PolicyEntry entry;
- entry.setApp(appId);
- entry.setUser(user);
- entry.setPrivilege(priv);
- entry.setLevel(level);
- req.addEntry(std::move(entry));
}
req.updatePolicy();