cynara-plugin
cynara-creds-socket
libsystemd
- security-privilege-manager
- glib-2.0
)
SET(ASKUSER_AGENT_PATH ${ASKUSER_PATH}/agent)
${ASKUSER_AGENT_PATH}/main/Agent.cpp
${ASKUSER_AGENT_PATH}/main/CynaraTalker.cpp
${ASKUSER_AGENT_PATH}/main/main.cpp
+ ${ASKUSER_AGENT_PATH}/main/PolicyUpdater.cpp
${ASKUSER_AGENT_PATH}/ui/NotificationBackend.cpp
${ASKUSER_AGENT_PATH}/ui/FdNotifyObject.cpp
)
#include <utility>
#include <attributes/attributes.h>
+#include <policy/Policy.h>
#include <translator/Translator.h>
#include <types/AgentErrorMsg.h>
#include <types/SupportedTypes.h>
}
void Agent::init() {
- // TODO: implement if needed
-
ALOGD("Agent daemon initialized");
}
void Agent::run() {
m_cynaraTalker.start();
+ m_policyUpdater.start();
while (!m_stopFlag) {
std::unique_lock<std::mutex> lock(m_mutex);
}
void Agent::finish() {
+ m_policyUpdater.stop();
if (!m_cynaraTalker.stop()) {
- ALOGE("Cynara talker thread could not be stopped. Calling quick_exit()");
+ ALOGE("Threads could not be stopped. Calling quick_exit()");
quick_exit(EXIT_SUCCESS);
}
AgentErrorMsg::NoError);
}
m_cynaraTalker.sendResponse(RT_Action, requestIt->second->id(), pluginData);
+ auto data = Translator::Agent::dataToRequest(requestIt->second->data());
+
+ std::string appId, pkgLabel;
+ identifyApp(data.client, data.user, appId, pkgLabel);
+
+ switch (response.type()) {
+ case URT_NO_LIFE:
+ m_policyUpdater.update(appId, data.user, data.privilege, "Deny");
+ break;
+ case URT_YES_LIFE:
+ m_policyUpdater.update(appId, data.user, data.privilege, "Allow");
+ break;
+ default:
+ break;
+ }
+
delete requestIt->second;
m_requests.erase(requestIt);
}
#pragma once
-#include <condition_variable>
#include <csignal>
#include <map>
#include <mutex>
#include <types/PolicyType.h>
#include <main/CynaraTalker.h>
+#include <main/PolicyUpdater.h>
#include <main/Request.h>
#include <main/Response.h>
private:
CynaraTalker m_cynaraTalker;
+ PolicyUpdater m_policyUpdater;
std::map<RequestId, Request *> m_requests;
std::queue<Request *> m_incomingRequests;
std::queue<Response> m_incomingResponses;
--- /dev/null
+/*
+ * Copyright (c) 2016 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @file PolicyUpdater.cpp
+ * @author Zofia Abramowska <z.abramowska@samsung.com>
+ * @brief This file implements class of policy updater
+ */
+
+#include <csignal>
+#include <unistd.h>
+
+#include <exception/Exception.h>
+#include <log/alog.h>
+#include <policy/Policy.h>
+#include <policy/PrivilegeInfo.h>
+
+#include "PolicyUpdater.h"
+
+namespace AskUser {
+
+namespace Agent {
+
+PolicyUpdater::PolicyUpdater() : m_running(false)
+{}
+
+void PolicyUpdater::start() {
+ m_thread = std::thread(&PolicyUpdater::run, this);
+ m_running = true;
+}
+
+void PolicyUpdater::stop() {
+ if (!m_running || !m_thread.joinable())
+ return;
+ m_running = false;
+
+ m_thread.join();
+ ALOGD("PolicyUpdater thread finished.");
+}
+
+void PolicyUpdater::run() {
+ int ret;
+ sigset_t mask;
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGTERM);
+ if ((ret = pthread_sigmask(SIG_BLOCK, &mask, nullptr)) < 0) {
+ ALOGE("sigprocmask failed [<<" << ret << "]");
+ }
+
+ while (m_running) {
+ try {
+ std::unique_lock<std::mutex> lock(m_mutex);
+ m_event.wait(lock, [&](){ return !m_events.empty() || !m_running;});
+
+ if (m_events.empty()) {
+ continue;
+ }
+
+ ALOGD("Got " << m_events.size() << " policies to update");
+ m_eventsInternal = std::move(m_events);
+ lock.unlock();
+
+ PolicyRequest req;
+ ALOGD("Updating " << m_eventsInternal.size() << " policies");
+ for (auto &policyInfo : m_eventsInternal) {
+ std::string privacyName = PrivilegeInfo::getPrivacyName(policyInfo.priv);
+ if (privacyName.empty()) {
+ ALOGE("Unable to get privacy name for privilege " << policyInfo.priv);
+ throw Exception("Unable to get privacy name for " + policyInfo.priv);
+ }
+ auto privacyPrivs = PrivilegeInfo::getPrivacyPrivileges(privacyName);
+ if (privacyPrivs.empty()) {
+ ALOGE("Unable to get privacy privileges for privacy " << privacyName);
+ throw Exception("Unable to get privacy privileges for privacy " + privacyName);
+ }
+ ALOGD("Adding policy entry for : app: " << policyInfo.appId << ", privilege: "
+ << policyInfo.priv << ", user:" << policyInfo.user << ", level: "
+ << policyInfo.level);
+ for (auto &priv : privacyPrivs) {
+ PolicyEntry entry;
+ entry.setApp(policyInfo.appId);
+ entry.setUser(policyInfo.user);
+ entry.setPrivilege(priv);
+ entry.setLevel(policyInfo.level);
+ req.addEntry(std::move(entry));
+ }
+ }
+ req.updatePolicy();
+ ALOGD("Policy update sent");
+
+ m_eventsInternal.clear();
+ } catch (const std::exception &e) {
+ ALOGC("Unexpected exception: <" << e.what() << ">");
+ } catch (...) {
+ ALOGE("Unexpected unknown exception caught!");
+ }
+ }
+}
+
+void PolicyUpdater::update(const std::string &appId, const std::string &user,
+ const std::string &privilege, const std::string &level)
+{
+ ALOGD("Queueing policy update for: app: " << appId << ", privilege: " << privilege
+ << ", user:" << user << ", level: " << level);
+ if (!m_running) {
+ ALOGE("PolicyUpdater not running, cannot update policy for " << appId << " " << user << " "
+ << privilege << " " << level);
+ return;
+ }
+ {
+ std::lock_guard<std::mutex> lock(m_mutex);
+ m_events.push_back({appId, user, privilege, level});
+ }
+ m_event.notify_one();
+}
+
+} // namespace Agent
+
+} // namespace AskUser
--- /dev/null
+/*
+ * Copyright (c) 2016 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @file PolicyUpdater.h
+ * @author Zofia Abramowska <z.abramowska@samsung.com>
+ * @brief This file declares class of policy updater
+ */
+
+#pragma once
+
+#include <atomic>
+#include <mutex>
+#include <string>
+#include <vector>
+#include <thread>
+#include <condition_variable>
+
+namespace AskUser {
+
+namespace Agent {
+
+class PolicyUpdater {
+public:
+ PolicyUpdater();
+ ~PolicyUpdater() { stop(); }
+
+ void start();
+ void stop();
+
+ void update(const std::string &appId, const std::string &user, const std::string &privilege,
+ const std::string &level);
+private:
+ struct PolicyInfo {
+ std::string appId;
+ std::string user;
+ std::string priv;
+ std::string level;
+ };
+ std::atomic<bool> m_running;
+ std::thread m_thread;
+
+ std::mutex m_mutex;
+ std::condition_variable m_event;
+ std::vector<PolicyInfo> m_events;
+ std::vector<PolicyInfo> m_eventsInternal;
+
+ void run();
+};
+
+} // namespace Agent
+
+} // namespace AskUser
#include <string>
#include <sys/signalfd.h>
-#include "Policy.h"
-#include "PrivilegeInfo.h"
-
+#include <policy/Policy.h>
+#include <policy/PrivilegeInfo.h>
#include <socket/Socket.h>
#include <socket/Poll.h>
#include <types/NotificationResponse.h>
#include <translator/Translator.h>
#include <config/Path.h>
-#include <security-manager.h>
-
#ifdef BUILD_WITH_SYSTEMD_DAEMON
#include <systemd/sd-daemon.h>
#endif
namespace {
-void setSecurityLevel(const std::string &app, const std::string &perm, const std::string &level)
-{
- try {
- if (level != "Allow" && level != "Deny")
- throw std::invalid_argument("Not allowed security level <" + level + ">");
-
- ALOGD("SecurityManager: Setting security level to " << level);
- std::string appName;
- std::string pkgLabel;
- identifyApp(app, appName, pkgLabel);
- if (appName.empty()) {
- ALOGE("Couldn't fetch appName from cynara client. Cannot set policy");
- return;
- }
-
- std::string privacyName = PrivilegeInfo::getPrivacyName(perm);
- if (privacyName.empty()) {
- ALOGE("Unablte to get privacy name for privilege " << perm);
- throw Exception("Unable to get privacy name for " + perm);
- }
-
- auto privacyPrivs = PrivilegeInfo::getPrivacyPrivileges(privacyName);
- if (privacyPrivs.empty()) {
- ALOGE("Unablte to get privacy privileges for privacy " << privacyName);
- throw Exception("Unablte to get privacy privileges for privacy " + privacyName);
- }
- PolicyRequest updateRequest;
-
- std::vector<PolicyEntry> entryVector(privacyPrivs.size());
- for (size_t i=0; i < privacyPrivs.size(); ++i) {
- entryVector[i].setApp(appName);
- entryVector[i].setPrivilege(privacyPrivs[i]);
- entryVector[i].setLevel(level);
- updateRequest.addEntry(entryVector[i]);
- }
- updateRequest.updatePolicy();
- ALOGD("SecurityManager: Setting level succeeded");
- } catch (std::exception &e) {
- ALOGE("SecurityManager: Failed <" << e.what() << ">");
- }
-}
-
} /* namespace */
void AskUserTalker::dissmissCb(int fd, void *data) {
switch (response.response) {
case NResponseType::Error:
ALOGE("Error in user interface : " << m_gui.getErrorMsg());
- break;
case NResponseType::AllowAlways:
- setSecurityLevel(request.data.client, request.data.privilege,
- "Allow");
- break;
case NResponseType::DenyAlways:
- setSecurityLevel(request.data.client, request.data.privilege,
- "Deny");
- break;
case NResponseType::Deny:
case NResponseType::None:
+ ALOGD("Sending response " << static_cast<int>(response.response));
break;
default:
ALOGW("Unknown response type returned");
break;
}
-
return;
}
elementary
cynara-agent
libsystemd
- security-manager
- security-privilege-manager
- pkgmgr-info
vconf
capi-ui-efl-util
)
${NOTIF_PATH}/main.cpp
${NOTIF_PATH}/GuiRunner.cpp
${NOTIF_PATH}/AskUserTalker.cpp
- ${NOTIF_PATH}/Policy.cpp
- ${NOTIF_PATH}/PrivilegeInfo.cpp
)
#include <exception/ErrnoException.h>
#include <exception/Exception.h>
+#include <policy/Policy.h>
#include <translator/Translator.h>
#include <libintl.h>
#include <vconf.h>
#include <efl_util.h>
-#include "Policy.h"
+
+#include <unistd.h>
namespace AskUser {
std::string appId;
std::string pkgLabel;
- identifyApp(app, appId, pkgLabel);
+ identifyApp(app, std::to_string(getuid()), appId, pkgLabel);
// create message
char *messageFormat = dgettext(PROJECT_NAME, "IDS_IDLE_POP_ALLOW_P1SS_TO_ACCESS_YOUR_P2SS_Q");
REQUIRED
cynara-plugin
cynara-agent
+ glib-2.0
libsystemd
+ pkgmgr-info
+ security-manager
+ security-privilege-manager
)
SET(ASKUSER_COMMON_VERSION_MAJOR 0)
SET(COMMON_SOURCES
${COMMON_PATH}/log/alog.cpp
+ ${COMMON_PATH}/policy/Policy.cpp
+ ${COMMON_PATH}/policy/PrivilegeInfo.cpp
${COMMON_PATH}/socket/Socket.cpp
${COMMON_PATH}/socket/Poll.cpp
${COMMON_PATH}/translator/Translator.cpp
#include <memory>
#include <pkgmgr-info.h>
+#include <security-manager.h>
+
#include <exception/Exception.h>
#include <log/alog.h>
throw AskUser::Exception(err + " : " + std::to_string(ret));
}
-char * toAppId(const char *pkgId) {
- int ret = 0;
- char *mainappid = 0;
- pkgmgrinfo_pkginfo_h handle = NULL;
- ret = pkgmgrinfo_pkginfo_get_pkginfo(pkgId, &handle);
- if (ret != PMINFO_R_OK)
- return NULL;
- ret = pkgmgrinfo_pkginfo_get_mainappid(handle, &mainappid);
- if (ret != PMINFO_R_OK) {
- pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
- return NULL;
+struct PkgInfo {
+ PkgInfo(const std::string &pkgId, uid_t uid) : m_handle(nullptr) {
+ int ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgId.c_str(), uid, &m_handle);
+ if (ret != PMINFO_R_OK) {
+ ALOGE("pkgmgrinfo_pkginfo_get_usr_pkginfo failed for " << pkgId << " with " << ret);
+ m_handle = nullptr;
+ }
}
- printf("main app id: %s\n", mainappid);
- char *result = strdup(mainappid);
- pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
- return result;
-}
-
-char * toPkgLabel(const char *pkgId) {
- int ret = 0;
- char *pkgLabel = 0;
- pkgmgrinfo_pkginfo_h handle = NULL;
- ret = pkgmgrinfo_pkginfo_get_pkginfo(pkgId, &handle);
- if (ret != PMINFO_R_OK)
- return NULL;
- ret = pkgmgrinfo_pkginfo_get_label(handle, &pkgLabel);
- if (ret != PMINFO_R_OK) {
- pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
- return NULL;
+ ~PkgInfo() {
+ if (m_handle)
+ pkgmgrinfo_pkginfo_destroy_pkginfo(m_handle);
}
- printf("pkg label: %s\n", pkgLabel);
- char *result = strdup(pkgLabel);
- pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
- return result;
-}
+ const std::string mainAppId(){
+ if (!m_handle) {
+ return "";
+ }
+ char *mainAppId;
+ int ret = pkgmgrinfo_pkginfo_get_mainappid(m_handle, &mainAppId);
+ if (ret != PMINFO_R_OK) {
+ ALOGE("pkgmgrinfo_pkginfo_get_mainappid failed with " << ret);
+ return "";
+ }
+ return mainAppId ? mainAppId : "";
+ }
+ const std::string pkgLabel() {
+ if (!m_handle) {
+ return "";
+ }
+ char *pkgLabel;
+ int ret = pkgmgrinfo_pkginfo_get_label(m_handle, &pkgLabel);
+ if (ret != PMINFO_R_OK) {
+ ALOGE("pkgmgrinfo_pkginfo_get_label failed with " << ret);
+ return "";
+ }
+ return pkgLabel ? pkgLabel : "";
+ }
+ pkgmgrinfo_pkginfo_h m_handle;
+};
}
namespace AskUser {
-void identifyApp(const std::string &client, std::string &appId, std::string &pkgLabel) {
- char *pkg_name = nullptr;
- char *app_name = nullptr;
- char *pkg_label = nullptr;
-
- int ret = security_manager_identify_app_from_cynara_client(client.c_str(), &pkg_name, &app_name);
- std::unique_ptr<char, decltype(free)*> pkg_name_p(pkg_name, free);
-
- // non-hybrid
- if (!app_name && pkg_name_p)
- app_name = toAppId(pkg_name_p.get());
-
- pkg_label = toPkgLabel(pkg_name_p.get());
+void identifyApp(const std::string &client, const std::string &user,
+ std::string &appId, std::string &pkgLabel)
+{
+ char *pkgName = nullptr;
+ char *appName = nullptr;
- std::unique_ptr<char, decltype(free)*> app_name_p(app_name, free);
+ int ret = security_manager_identify_app_from_cynara_client(client.c_str(), &pkgName, &appName);
+ std::unique_ptr<char, decltype(free)*> pkg_name_p(pkgName, free);
+ std::unique_ptr<char, decltype(free)*> app_name_p(appName, free);
throwOnSMError("security_manager_identify_app_from_cynara_client", ret);
- std::unique_ptr<char, decltype(free)*> pkg_label_p(pkg_label, free);
-
- if (!app_name) {
- ALOGW("Identifying of application failed!");
+ if (!pkgName) {
+ ALOGE("Couldn't identify clients package id");
return;
}
- if (!pkg_label) {
- ALOGW("Get pkg label failed!");
- return;
- }
+ uid_t uid = std::strtoul(user.c_str(), nullptr, 10);
+ PkgInfo pkgInfo(pkgName, uid);
+ if (!appName)
+ appId = pkgInfo.mainAppId();
- appId = app_name;
- pkgLabel = pkg_label;
+ pkgLabel = pkgInfo.pkgLabel();
}
PolicyEntry::PolicyEntry() {
security_manager_policy_entry_new(&m_entry));
}
+PolicyEntry::PolicyEntry(PolicyEntry &&other) : m_entry(std::move(other.m_entry)) {
+ other.m_entry = nullptr;
+}
+
PolicyEntry::~PolicyEntry() {
security_manager_policy_entry_free(m_entry);
}
security_manager_policy_entry_set_application(m_entry, appId.c_str()));
}
+void PolicyEntry::setUser(const std::string &user) {
+ throwOnSMError("security_manager_policy_entry_set_user",
+ security_manager_policy_entry_set_user(m_entry, user.c_str()));
+}
+
void PolicyEntry::setPrivilege(const std::string &privilege) {
throwOnSMError("security_manager_policy_entry_set_privilege",
security_manager_policy_entry_set_privilege(m_entry, privilege.c_str()));
}
PolicyRequest::~PolicyRequest() {
+ m_entries.clear();
security_manager_policy_update_req_free(m_req);
}
-void PolicyRequest::addEntry(const PolicyEntry &entry) {
+void PolicyRequest::addEntry(PolicyEntry &&entry) {
throwOnSMError("security_manager_policy_update_req_add_entry",
security_manager_policy_update_req_add_entry(m_req, entry.get()));
+ m_entries.emplace_back(std::move(entry));
}
void PolicyRequest::updatePolicy() {
#pragma once
-#include <security-manager.h>
-
#include <string>
+#include <vector>
+
+struct policy_entry;
+struct policy_update_req;
namespace AskUser {
-void identifyApp(const std::string &client, std::string &appId, std::string &pkgLabel);
+void identifyApp(const std::string &client, const std::string &user,
+ std::string &appId, std::string &pkgLabel);
class PolicyEntry {
public:
PolicyEntry();
+ PolicyEntry(PolicyEntry &&other);
~PolicyEntry();
void setApp(const std::string &appId);
+ void setUser(const std::string &user);
void setPrivilege(const std::string &privilege);
void setLevel(const std::string &level);
public:
PolicyRequest();
~PolicyRequest();
- void addEntry(const PolicyEntry &entry);
+ void addEntry(PolicyEntry &&entry);
void updatePolicy();
private:
policy_update_req *m_req;
+ std::vector<PolicyEntry> m_entries;
};
} /* namespace AskUser */
std::string getPrivacyDisplayName(const std::string &privilege) {
char *displayName = nullptr;
- char *privacy = nullptr;
- int res = privilege_info_get_privacy_by_privilege(privilege.c_str(), &privacy);
- if (res != PRVMGR_ERR_NONE || !privacy) {
- ALOGE("Unable to get privacy name for: <" << privilege << ">, err: <" << res << ">");
+ int ret = privilege_info_get_privacy_display(getPrivacyName(privilege).c_str(), &displayName);
+ if (ret != PRVMGR_ERR_NONE || !displayName) {
+ ALOGE("Unable to get privacy display name for <" << privilege << ">, err: <" << ret << ">");
return privilege;
}
- res = privilege_info_get_privacy_display(privacy, &displayName);
- if (res != PRVMGR_ERR_NONE || !displayName) {
- ALOGE("Unable to get privacy display name for <" << privacy << ">, err: <" << res << ">");
- return privilege;
- }
- free(privacy);
std::unique_ptr<char, decltype(free)*> displaNamePtr(displayName, free);
return displayName;
}