/**
* @file ApiInterfaceImpl.cpp
* @author Piotr Sawicki <p.sawicki2@partner.samsung.com>
+ * @author Zofia Grzelewska <z.abramowska@samsung.com>
* @brief The definition of ApiInterfaceImpl.
*/
#include <log/alog.h>
#include <policy/Policy.h>
+#include <policy/PrivilegePolicy.h>
#include <client-channel.h>
#include <common-types.h>
askuser_check_result ApiInterfaceImpl::checkPrivilege(const std::string &privilege)
{
std::string appId = getOwnAppId();
+ PrivilegePolicy privPolicy(appId, privilege);
+ auto policyLevel = privPolicy.calculatePolicy();
- auto policyLevel = getPrivilegeMappedPolicy(appId, privilege);
-
- if (policyLevel.empty()) {
- ALOGD("Privilege " << privilege << " is not a privacy privilege for app " << appId);
- return ASKUSER_CHECK_RESULT_DENY;
- }
if (policyLevel == "Allow") {
return ASKUSER_CHECK_RESULT_ALLOW;
}
-# Copyright (c) 2014-2017 Samsung Electronics Co., Ltd All Rights Reserved
+# Copyright (c) 2014-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.
REQUIRED
security-manager
pkgmgr-info
+ security-privilege-manager
)
SET(ASKUSER_COMMON_VERSION_MAJOR 0)
${COMMON_PATH}/log/alog.cpp
${COMMON_PATH}/policy/Policy.cpp
${COMMON_PATH}/policy/PrivilegeInfo.cpp
+ ${COMMON_PATH}/policy/PrivilegePolicy.cpp
${COMMON_PATH}/types/AgentErrorMsg.cpp
${COMMON_PATH}/util/SafeFunction.cpp
${COMMON_PATH}/config/Limits.cpp
/*
- * Copyright (c) 2016-2017 Samsung Electronics Co.
+ * Copyright (c) 2016-2018 Samsung Electronics Co.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*/
/**
* @file src/agent/main/Policy.cpp
- * @author Zofia Abramowska <z.abramowska@samsung.com>
+ * @author Zofia Grzelewska <z.abramowska@samsung.com>
* @brief Implementation of Policy wrappers
*/
m_level = level;
}
-Policy getMinimumPolicy(const std::vector<Policy> &policies) {
- if (policies.empty())
- return "";
-
- Policy minimumPolicy = "Allow";
-
- for (auto &policy : policies) {
- if (policy == "Deny") {
- minimumPolicy = "Deny";
- break;
- } else if (policy != minimumPolicy && policy == "Ask user") {
- minimumPolicy = "Ask user";
- }
+std::set<Privilege> getManifestPrivs(const std::string &appId)
+{
+ char **privsRaw;
+ size_t privsCount;
+
+ int ret = security_manager_get_app_manifest_policy(appId.c_str(), geteuid(),
+ &privsRaw, &privsCount);
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ ALOGE("Failed to fetch manifest privileges for app " << appId << " : " << ret);
+ return {};
}
- return minimumPolicy;
-}
-
-Policy calculatePolicyForPrivacy(const std::string &appId, const Privacy &privacy) {
- ALOGD("Calculating privacy " << privacy);
- std::vector<Policy> privsPolicies;
- auto privileges = PrivilegeInfo::getPrivacyPrivileges(privacy);
- for (const auto &privilege : privileges) {
- ALOGD("Calculating policy for privilege " << privilege);
-
- std::string policyLevel = getPrivilegePolicy(appId, privilege);
-
- if (policyLevel.empty()) {
- ALOGE("Couldn't get policy level, skipping");
- continue;
- }
-
- ALOGD("Fetched policy level : " << policyLevel);
- privsPolicies.push_back(std::move(policyLevel));
+ auto privsFree = [privsCount](char ** privs) {
+ security_manager_privileges_free(privs, privsCount);
+ };
+ std::unique_ptr<char *, decltype(privsFree)> privsPtr(privsRaw, privsFree);
+ std::set<Privilege> privileges;
+
+ for (size_t i = 0; i < privsCount; i++) {
+ privileges.insert(privsRaw[i]);
}
- return getMinimumPolicy(privsPolicies);
+ return privileges;
}
Policy getPrivilegePolicy(const std::string &appId, const Privilege &privilege) {
return policies[0].getLevel();
}
-Policy getPrivaciesPolicy(const std::string &appId, const std::vector<Privacy> &privacies) {
- std::vector<Policy> policies;
- for (auto &privacy : privacies) {
- Policy privacyPolicy = calculatePolicyForPrivacy(appId, privacy);
- if (privacyPolicy.empty())
- continue;
- policies.push_back(privacyPolicy);
- }
- return getMinimumPolicy(policies);
+std::vector<PolicyEntryCopy> getAppPolicy(const std::string &appId) {
+ PolicyEntry filter;
+ filter.setApp(appId);
+ filter.setUser(std::to_string(geteuid()));
+ filter.setPrivilege(SECURITY_MANAGER_ANY);
+
+ PolicyFetchRequest fetch(std::move(filter));
+ return fetch.fetchPolicy();
}
void identifyApp(const std::string &client, std::string &appId, std::string &pkgLabel)
pkgLabel = pkgInfo.pkgLabel();
}
-Policy getPrivilegeMappedPolicy(const std::string &appId, const std::string &privilege) {
- std::vector<Privacy> privacies = PrivilegeInfo::getPrivilegePrivaciesMapping(appId, privilege);
- if (privacies.empty()) {
- ALOGE("Privilege doesn't map to any privacy");
- return "";
- }
-
- return getPrivaciesPolicy(appId, privacies);
-}
-
std::string getOwnAppId()
{
char *pkgName = nullptr;
/*
- * Copyright (c) 2016-2017 Samsung Electronics Co.
+ * Copyright (c) 2016-2018 Samsung Electronics Co.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*/
/**
* @file src/agent/main/Policy.h
- * @author Zofia Abramowska <z.abramowska@samsung.com>
+ * @author Zofia Grzelewska <z.abramowska@samsung.com>
* @brief Definition of Policy wrappers
*/
#pragma once
+#include <set>
#include <string>
#include <vector>
namespace AskUser {
+class PolicyEntryCopy;
+
std::string getOwnAppId();
void identifyApp(const std::string &client, std::string &appId, std::string &pkgLabel);
-Policy calculatePolicyForPrivacy(const std::string &appId, const Privacy &privacy);
-Policy getMinimumPolicy(const std::vector<Policy> &policies);
-Policy getPrivilegeMappedPolicy(const std::string &appId, const Privilege &privilege);
-Policy getPrivaciesPolicy(const std::string &appId, const std::vector<Privacy> &privacies);
+std::set<Privilege> getManifestPrivs(const std::string &appId);
Policy getPrivilegePolicy(const std::string &appId, const Privilege &corePrivilege);
+std::vector<PolicyEntryCopy> getAppPolicy(const std::string &appId);
class PolicyEntry {
public:
/*
- * Copyright (c) 2016 Samsung Electronics Co.
+ * Copyright (c) 2016-2018 Samsung Electronics Co.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*/
/**
* @file src/agent/notification-daemon/Privilege.cpp
- * @author Zofia Abramowska <z.abramowska@samsung.com>
+ * @author Zofia Grzelewska <z.abramowska@samsung.com>
* @brief Implementation of Privilege Info wrappers
*/
#include <memory>
#include <set>
+#include "Policy.h"
#include "PrivilegeInfo.h"
#include <exception/Exception.h>
#include <privilegemgr/privilege_info.h>
#include <privilegemgr/privilege_db_manager.h>
-#include <pkgmgr-info.h>
#include <glib.h>
-
namespace AskUser {
namespace PrivilegeInfo {
GList *m_head;
};
+Privacy getPrivacyName(const Privilege &privilege) {
+ char* privacyName = nullptr;
+ int ret = privilege_info_get_privacy_by_privilege(privilege.c_str(), &privacyName);
+ if (ret != PRVMGR_ERR_NONE || !privacyName) {
+ ALOGE("Unable to get privacy group for privilege: <" << privilege << ">, err: <" << ret << ">");
+ return privilege;
+ }
+
+ std::unique_ptr<char, decltype(free) *> privacyNamePtr(privacyName, free);
+ return std::string(privacyName);
+}
+
+} //namespace anonymous
+
std::vector<Privacy> getPrivilegesPrivacies(const std::vector<std::string> &corePrivileges) {
std::set<Privacy> privaciesSet;
for (auto &privilege : corePrivileges) {
return privMappedVector;
}
-
-} //namespace anonymous
-
bool isPrivacy(const Privilege &privilege) {
return privilege_info_is_privacy(privilege.c_str()) == 1;
}
return std::string(displayName);
}
-Privacy getPrivacyName(const Privilege &privilege) {
- char* privacyName = nullptr;
- int ret = privilege_info_get_privacy_by_privilege(privilege.c_str(), &privacyName);
- if (ret != PRVMGR_ERR_NONE || !privacyName) {
- ALOGE("Unable to get privacy group for privilege: <" << privilege << ">, err: <" << ret << ">");
- return privilege;
- }
-
- std::unique_ptr<char, decltype(free) *> privacyNamePtr(privacyName, free);
- return std::string(privacyName);
-}
-
std::vector<Privilege> getPrivacyPrivileges(const Privacy &privacy) {
GList *privilegeList = nullptr;
return privVector;
}
-
-std::vector<Privacy> getPrivilegePrivaciesMapping(const std::string &appId, const std::string &privilege) {
- std::vector<std::string> corePrivileges = PrivilegeInfo::getPrivilegeMapping(appId, privilege);
- if (corePrivileges.empty()) {
- ALOGE("Cannot fetch mapping for application " << appId << " and privilege " << privilege << ", aborting");
- return {};
- }
-
- return getPrivilegesPrivacies(corePrivileges);
-}
-
}
} /* namespace AskUser */
/*
- * Copyright (c) 2016 Samsung Electronics Co.
+ * Copyright (c) 2016-2018 Samsung Electronics Co.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* limitations under the License
*/
/**
- * @file src/agent/notification-daemon/Privilege.h
- * @author Zofia Abramowska <z.abramowska@samsung.com>
- * @brief Definition of Privilege Info wrappers
+ * @file PrivilegeInfo.h
+ * @author Zofia Grzelewska <z.abramowska@samsung.com>
+ * @brief Definition of Privilege Info wrappers.
*/
#pragma once
namespace AskUser {
namespace PrivilegeInfo {
- std::vector<Privacy> getPrivilegePrivaciesMapping(const std::string &appId, const std::string &privilege);
+ std::vector<Privilege> getPrivilegeMapping(const std::string &appId,
+ const Privilege &privilege);
+ std::vector<Privacy> getPrivilegesPrivacies(const std::vector<std::string> &corePrivileges);
bool isPrivacy(const Privilege &privilege);
- Privacy getPrivacyName(const Privacy &privilege);
+
std::string getPrivacyDisplayName(const Privacy &privacy);
std::vector<Privilege> getPrivacyPrivileges(const Privacy &privacy);
--- /dev/null
+/*
+ * Copyright (c) 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.
+ * 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 PrivilegePolicy.cpp
+ * @author Zofia Grzelewska <z.abramowska@samsung.com>
+ * @brief The implementation of PrivilegePolicy class.
+ */
+
+
+#include <glib.h>
+#include <memory>
+#include <set>
+
+#include <log/alog.h>
+#include <policy/AppInfo.h>
+#include <policy/Policy.h>
+#include <policy/PrivilegeInfo.h>
+
+#include "PrivilegePolicy.h"
+
+namespace AskUser {
+
+namespace {
+bool updateMinimal(const Policy ¤t, Policy &minimal) {
+ if (current == "Deny") {
+ minimal = "Deny";
+ return false;
+ } else if (current != minimal && current == "Ask user") {
+ minimal = "Ask user";
+ }
+ return true;
+}
+
+Policy calculatePrivsPolicy(const std::vector<Privilege> &privs,
+ const std::unordered_map<Privilege, Policy> &policyMap) {
+ Policy minimalPolicy = "Allow";
+ bool policyExists = false;
+
+ for (auto & priv : privs) {
+ auto it = policyMap.find(priv);
+ if (it == policyMap.end()) {
+ ALOGD("Application has no privacy policy for privilege " << priv);
+ continue;
+ }
+ policyExists = true;
+ if (!updateMinimal(it->second, minimalPolicy))
+ break;
+ }
+
+ if (!policyExists)
+ return "";
+
+ return minimalPolicy;
+}
+
+} // anonymous namespace
+
+PrivilegePolicy::PrivilegePolicy(const std::string &appId, const Privilege &privilege)
+ : m_appId(appId),
+ m_privilege(privilege)
+{}
+
+Policy PrivilegePolicy::calculatePolicy() {
+ std::vector<Privilege> corePrivileges =
+ PrivilegeInfo::getPrivilegeMapping(m_appId, m_privilege);
+ if (corePrivileges.empty()) {
+ ALOGE("Privilege " << m_privilege << " doesn't map to any core privilege");
+ return "Deny";
+ }
+
+ // Check if application requested core privileges in manifest
+ std::set<Privilege> manifestPrivs = getManifestPrivs(m_appId);
+ for (auto &corePriv : corePrivileges) {
+ if (manifestPrivs.find(corePriv) == manifestPrivs.end()) {
+ ALOGE("Application " << m_appId << " didn't request privilege "
+ << corePriv << " in its manifest");
+ return "Deny";
+ }
+ }
+ std::vector<Privacy> privacies = PrivilegeInfo::getPrivilegesPrivacies(corePrivileges);
+ if (privacies.empty()) {
+ ALOGE("Privilege doesn't map to any privacy");
+ return "Allow";
+ }
+
+ return calculatePrivaciesPolicy(privacies);
+}
+
+
+Policy PrivilegePolicy::calculatePrivaciesPolicy(const std::vector<Privacy> &privacies) {
+ std::unordered_map<Privacy, std::vector<Privilege>> privacyPrivileges;
+ std::unordered_map<Privilege, Policy> privilegePolicy;
+
+ for (auto &privacy : privacies) {
+ auto privileges = PrivilegeInfo::getPrivacyPrivileges(privacy);
+ privacyPrivileges[privacy] = privileges;
+ }
+
+ auto policies = getAppPolicy(m_appId);
+
+ for (auto &policy : policies) {
+ privilegePolicy[policy.getPrivilege()] = policy.getLevel();
+ }
+
+ m_askablePrivacies.clear();
+ Policy totalPolicy = "Allow";
+ for (auto &privacy : privacies) {
+ Policy policy = calculatePrivsPolicy(privacyPrivileges[privacy], privilegePolicy);
+ if (policy.empty()) {
+ ALOGD("Privacy group " << privacy << " is not privacy for application " << m_appId);
+ policy = "Allow";
+ }
+ if (policy == "Ask user") {
+ m_askablePrivacies.push_back(privacy);
+ }
+ if (!updateMinimal(policy, totalPolicy))
+ break;
+ }
+
+ if (totalPolicy == "Deny")
+ m_askablePrivacies.clear();
+
+ return totalPolicy;
+}
+
+}
--- /dev/null
+/*
+ * Copyright (c) 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.
+ * 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 PrivilegePolicy.h
+ * @author Zofia Grzelewska <z.abramowska@samsung.com>
+ * @brief The definition of PrivilegePolicy class.
+ */
+
+#include <unordered_map>
+#include <string>
+#include <vector>
+
+#include <types/PolicyTypes.h>
+
+namespace AskUser {
+
+class PrivilegePolicy {
+public:
+ PrivilegePolicy(const std::string &appId, const Privilege &privilege);
+ Policy calculatePolicy();
+ std::vector<Privacy> getAskablePrivacies() const {
+ return m_askablePrivacies;
+ }
+private:
+ Policy calculatePrivaciesPolicy(const std::vector<Privacy> &privacies);
+ std::string m_appId;
+ Privilege m_privilege;
+
+ std::vector<Privacy> m_askablePrivacies;
+};
+
+}
glib-2.0
capi-ui-efl-util
capi-system-info
- security-privilege-manager
)
INCLUDE_DIRECTORIES(SYSTEM
* limitations under the License
*/
/**
- * @file src/agent/notification-daemon/Service.cpp
- * @author Zofia Abramowska <z.abramowska@samsung.com>
- * @brief Declaration of Popupper class
+ * @file Logic.cpp
+ * @author Zofia Grzelewska <z.abramowska@samsung.com>
+ * @brief Declaration of Logic class
*/
#include "Logic.h"
#include <exception/Exception.h>
#include <exception/ErrnoException.h>
#include <policy/Policy.h>
+#include <policy/PrivilegePolicy.h>
+
#include "PolicyUpdater.h"
#include "ServerCallbacks.h"
-#include "policy/PrivilegeInfo.h"
-
namespace AskUser {
}
ConnectionInfo &conn = it->second;
- std::vector<Privacy> privacies = PrivilegeInfo::getPrivilegePrivaciesMapping(conn.appId, privilege);
- if (privacies.empty()) {
- ALOGE("Privilege " << privilege << " doesn't map to any privacy");
- m_serverChannel->popupResponse(fd, id, ASKUSER_DENY_ONCE);
- return;
- }
-
- std::vector<Policy> policies;
-
- std::string removePrivacy = "removeme";
- for (auto &privacy : privacies) {
- std::string policy = calculatePolicyForPrivacy(conn.appId, privacy);
- if (policy == "Allow") {
- // Remove privacies which are already allowed - we don't need to spam user more with popups
- privacy = removePrivacy;
- }
- if (policy.empty()) {
- ALOGD("Application doesn't use privacy " << privacy);
- continue;
- }
- policies.push_back(policy);
- }
-
- if (policies.empty()) {
- ALOGD("Privilege " << privilege << " is not privacy for app : " << conn.appId);
- m_serverChannel->popupResponse(fd, id, ASKUSER_DENY_FOREVER);
- return;
- }
- std::string policyLevel = getMinimumPolicy(policies);
+ PrivilegePolicy privPolicy(conn.appId, privilege);
+ auto policyLevel = privPolicy.calculatePolicy();
ALOGD("Privilege policy level calculated to : " << policyLevel);
if (policyLevel == "Allow") {
return;
}
- auto removeIt = std::remove_if(privacies.begin(), privacies.end(), [&](const Privacy &privacy) {return privacy == removePrivacy;});
- privacies.erase(removeIt, privacies.end());
+ auto privacies = privPolicy.getAskablePrivacies();
+ if (privacies.empty()) {
+ ALOGE("All privacies for privilege " << privilege
+ << " are already allowed");
+ m_serverChannel->popupResponse(fd, id, ASKUSER_ALLOW_FOREVER);
+ return;
+ }
addEvent(fd, id, privacies);
processEvents();