From: Tomasz Swierczek Date: Wed, 1 Jun 2016 13:44:47 +0000 (+0200) Subject: Add proper policy setup for privacy-related privileges X-Git-Tag: accepted/tizen/common/20160620.163323~10 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=2896b9700d2f7480bf4bf3a9aceb399df5e93963;p=platform%2Fcore%2Fsecurity%2Fsecurity-manager.git Add proper policy setup for privacy-related privileges Thanks to privielge-checker module API we can setup "ASK-USER"/popup Cynara policy for privacy-related privileges. Test with https://review.tizen.org/gerrit/#/c/72604/ Change-Id: I6bb8bc1dffc1e607c09b7722c6fac33b29620b4e --- diff --git a/packaging/security-manager.spec b/packaging/security-manager.spec index 7ac305c..20a84bd 100644 --- a/packaging/security-manager.spec +++ b/packaging/security-manager.spec @@ -25,6 +25,7 @@ BuildRequires: pkgconfig(sqlite3) BuildRequires: pkgconfig(db-util) BuildRequires: pkgconfig(cynara-admin) BuildRequires: pkgconfig(cynara-client-async) +BuildRequires: pkgconfig(security-privilege-manager) BuildRequires: boost-devel %{?systemd_requires} diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index fcfb46b..7c10f7b 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -9,6 +9,7 @@ PKG_CHECK_MODULES(COMMON_DEP cynara-admin cynara-client-async libtzplatform-config + security-privilege-manager ) IF(DPL_WITH_DLOG) diff --git a/src/common/config.cpp b/src/common/config.cpp index 6b1887d..8c8dd9e 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -45,6 +45,8 @@ const std::string PRIVILEGE_APPSHARING_ADMIN = "http://tizen.org/privilege/notex const std::string APPS_NAME_FILE = "apps-names"; const std::string SKEL_DIR = "/etc/skel"; + +const std::string PRIVACY_POLICY_DESC = "Ask user"; }; } /* namespace SecurityManager */ diff --git a/src/common/cynara.cpp b/src/common/cynara.cpp index d08f7d4..d2c26d2 100644 --- a/src/common/cynara.cpp +++ b/src/common/cynara.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2014-2016 Samsung Electronics Co., Ltd All Rights Reserved * * Contact: Rafal Krypa * @@ -27,6 +27,7 @@ #include #include +#include namespace SecurityManager { @@ -113,7 +114,6 @@ CynaraAdmin::BucketsMap CynaraAdmin::Buckets = { Bucket::MANIFESTS, std::string("MANIFESTS")}, }; - CynaraAdminPolicy::CynaraAdminPolicy(const std::string &client, const std::string &user, const std::string &privilege, int operation, const std::string &bucket) @@ -288,37 +288,74 @@ void CynaraAdmin::SetPolicies(const std::vector &policies) void CynaraAdmin::UpdateAppPolicy( const std::string &label, const std::string &user, - const std::vector &privileges) -{ - std::unordered_set privilegesSet(privileges.begin(), privileges.end()); - - std::vector policies; - CynaraAdmin::getInstance().ListPolicies( - CynaraAdmin::Buckets.at(Bucket::MANIFESTS), - label, user, CYNARA_ADMIN_ANY, policies); + const std::vector &privileges, + std::function isPrivacy) +{ + auto calcPolicies = [&label]( + const std::string &user, + const std::vector &privileges, + const std::string &bucket, + int policyToSet, + std::vector &policies) + { + std::vector oldPolicies; + std::unordered_set privilegesSet(privileges.begin(), + privileges.end()); + CynaraAdmin::getInstance().ListPolicies(bucket, label, user, + CYNARA_ADMIN_ANY, oldPolicies); + + // Compare previous policies with set of new requested privileges + for (auto &policy : oldPolicies) { + if (privilegesSet.erase(policy.privilege)) { + // privilege was found and removed from the set, keeping policy + LogDebug("(user = " << user << " label = " << label << ") " << + "keeping privilege " << policy.privilege); + } else { + // privilege was not found in the set, deleting policy + policy.result = static_cast(CynaraAdminPolicy::Operation::Delete); + LogDebug("(user = " << user << " label = " << label << ") " << + "removing privilege " << policy.privilege); + } + policies.push_back(std::move(policy)); + } - // Compare previous policies with set of new requested privileges - for (auto &policy : policies) { - if (privilegesSet.erase(policy.privilege)) { - // privilege was found and removed from the set, keeping policy - LogDebug("(user = " << user << " label = " << label << ") " << - "keeping privilege " << policy.privilege); - } else { - // privilege was not found in the set, deleting policy - policy.result = static_cast(CynaraAdminPolicy::Operation::Delete); + // Add policies for privileges that weren't previously enabled + // Those that were previously enabled are now removed from privilegesSet + for (const auto &privilege : privilegesSet) { LogDebug("(user = " << user << " label = " << label << ") " << - "removing privilege " << policy.privilege); + "adding privilege " << privilege); + policies.push_back(CynaraAdminPolicy(label, user, privilege, policyToSet, bucket)); } - } + }; - // Add policies for privileges that weren't previously enabled - // Those that were previously enabled are now removed from privilegesSet - for (const auto &privilege : privilegesSet) { - LogDebug("(user = " << user << " label = " << label << ") " << - "adding privilege " << privilege); - policies.push_back(CynaraAdminPolicy(label, user, privilege, - static_cast(CynaraAdminPolicy::Operation::Allow), - Buckets.at(Bucket::MANIFESTS))); + std::vector policies; + + // 1st, performing operation on MANIFESTS bucket + calcPolicies(user, privileges, Buckets.at(Bucket::MANIFESTS), + static_cast(CynaraAdminPolicy::Operation::Allow), + policies); + + int askUserPolicy = convertToPolicyType(Config::PRIVACY_POLICY_DESC); + + std::vector privacyPrivileges; + for (auto &p : privileges) + if (isPrivacy(p)) + privacyPrivileges.push_back(p); + + // 2nd, performing operation on PRIVACY_MANAGER bucket for all affected users + if (user == CYNARA_ADMIN_WILDCARD) { + // perform bucket setting for all users in the system, app is installed for everyone + std::vector users; + ListUsers(users); + for (uid_t id : users) { + calcPolicies(std::to_string(id), privacyPrivileges, + Buckets.at(Bucket::PRIVACY_MANAGER), + askUserPolicy, policies); + } + } else { + // local single user installation, do it only for that particular user + calcPolicies(user, privacyPrivileges, Buckets.at(Bucket::PRIVACY_MANAGER), + askUserPolicy, policies); } SetPolicies(policies); @@ -339,10 +376,12 @@ void CynaraAdmin::GetAppPolicy(const std::string &label, const std::string &user } } -void CynaraAdmin::UserInit(uid_t uid, security_manager_user_type userType) +void CynaraAdmin::UserInit(uid_t uid, security_manager_user_type userType, + std::function isPrivacy) { Bucket bucket; std::vector policies; + std::string userStr = std::to_string(uid); switch (userType) { case SM_USER_TYPE_SYSTEM: @@ -365,11 +404,28 @@ void CynaraAdmin::UserInit(uid_t uid, security_manager_user_type userType) } policies.push_back(CynaraAdminPolicy(CYNARA_ADMIN_WILDCARD, - std::to_string(static_cast(uid)), + userStr, CYNARA_ADMIN_WILDCARD, Buckets.at(bucket), Buckets.at(Bucket::MAIN))); + // for each global app: retrieve its privacy-related privileges and set + // their policy in PRIVACY_MANAGER bucket to "Ask user" + int askUserPolicy = convertToPolicyType(Config::PRIVACY_POLICY_DESC); + + std::vector appPolicies; + CynaraAdmin::getInstance().ListPolicies(CynaraAdmin::Buckets.at(Bucket::MANIFESTS), + CYNARA_ADMIN_ANY, CYNARA_ADMIN_WILDCARD, + CYNARA_ADMIN_ANY, appPolicies); + + for (CynaraAdminPolicy &policy : appPolicies) + if (isPrivacy(policy.privilege)) + policies.push_back(CynaraAdminPolicy(policy.client, + userStr, + policy.privilege, + askUserPolicy, + Buckets.at(Bucket::PRIVACY_MANAGER))); + CynaraAdmin::getInstance().SetPolicies(policies); } diff --git a/src/common/include/config.h b/src/common/include/config.h index 9f4c466..01d0f79 100644 --- a/src/common/include/config.h +++ b/src/common/include/config.h @@ -41,10 +41,13 @@ extern const std::string PRIVILEGE_POLICY_USER; extern const std::string PRIVILEGE_POLICY_ADMIN; extern const std::string PRIVILEGE_APPSHARING_ADMIN; -/* Files used in permitted label managment*/ +/* Files used in permitted label managment */ extern const std::string APPS_NAME_FILE; extern const std::string SKEL_DIR; + +/* Ask-user policy description */ +extern const std::string PRIVACY_POLICY_DESC; }; } /* namespace SecurityManager */ diff --git a/src/common/include/cynara.h b/src/common/include/cynara.h index 219667d..1d267d4 100644 --- a/src/common/include/cynara.h +++ b/src/common/include/cynara.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2014-2016 Samsung Electronics Co., Ltd All Rights Reserved * * Contact: Rafal Krypa * @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -126,10 +127,11 @@ public: * @param label application Smack label * @param user user identifier * @param privileges currently enabled privileges - * + * @param isPrivacy a function that checks if privilege is privacy-related */ void UpdateAppPolicy(const std::string &label, const std::string &user, - const std::vector &privileges); + const std::vector &privileges, + std::function isPrivacy); /** * Fetch Cynara policies for the application and the user. @@ -150,8 +152,10 @@ public: * * @param uid new user uid * @param userType type as enumerated in security-manager.h + * @param isPrivacy a function that checks if privilege is privacy-related */ - void UserInit(uid_t uid, security_manager_user_type userType); + void UserInit(uid_t uid, security_manager_user_type userType, + std::function isPrivacy); /** * List all users registered in Cynara diff --git a/src/common/include/service_impl.h b/src/common/include/service_impl.h index fbe6c5b..652244a 100644 --- a/src/common/include/service_impl.h +++ b/src/common/include/service_impl.h @@ -72,6 +72,8 @@ private: static void getTizen2XApps(SmackRules::PkgsApps &pkgsApps); + static bool isPrivilegePrivacy(const std::string &privilege); + int dropOnePrivateSharing(const std::string &ownerAppName, const std::string &ownerPkgName, const std::vector &ownerPkgContents, diff --git a/src/common/service_impl.cpp b/src/common/service_impl.cpp index b8ffc8a..583d23f 100644 --- a/src/common/service_impl.cpp +++ b/src/common/service_impl.cpp @@ -35,6 +35,8 @@ #include #include +#include + #include #include "protocols.h" #include "privilege_db.h" @@ -398,6 +400,19 @@ void ServiceImpl::getTizen2XApps(SmackRules::PkgsApps &pkgsApps) } } +bool ServiceImpl::isPrivilegePrivacy(const std::string &privilege) +{ + int ret = privilege_info_is_privacy(privilege.c_str()); + if (ret == 1) + return true; + if (ret != 0) + LogError("privilege_info_is_privacy called with " << privilege << " returned error: " << ret); + // FIXME: we should probably disallow such installation where privilege is not known + // However, currently privielge-checker seems to return -1 with so many real privileges + // that it would make ask-user testing impossible. + return false; +} + int ServiceImpl::appInstall(const Credentials &creds, app_inst_req &&req) { std::vector addedPermissions; @@ -442,8 +457,7 @@ int ServiceImpl::appInstall(const Credentials &creds, app_inst_req &&req) /* Get all application ids in the package to generate rules withing the package */ PrivilegeDb::getInstance().GetPkgApps(req.pkgName, pkgContents); PrivilegeDb::getInstance().GetPkgAuthorId(req.pkgName, authorId); - CynaraAdmin::getInstance().UpdateAppPolicy(appLabel, cynaraUserStr, req.privileges); - + CynaraAdmin::getInstance().UpdateAppPolicy(appLabel, cynaraUserStr, req.privileges, isPrivilegePrivacy); // if app is targetted to Tizen 2.X, give other 2.X apps RO rules to it's shared dir if (isTizen2XVersion(req.tizenVersion)) getTizen2XApps(tizen2XpkgsApps); @@ -563,7 +577,8 @@ int ServiceImpl::appUninstall(const Credentials &creds, app_inst_req &&req) if (isTizen2XVersion(req.tizenVersion)) getTizen2XApps(tizen2XpkgsApps); - CynaraAdmin::getInstance().UpdateAppPolicy(smackLabel, cynaraUserStr, std::vector()); + CynaraAdmin::getInstance().UpdateAppPolicy(smackLabel, cynaraUserStr, std::vector(), isPrivilegePrivacy); + PrivilegeDb::getInstance().CommitTransaction(); LogDebug("Application uninstallation commited to database"); PermissibleSet::updatePermissibleFile(req.uid, req.installationType); @@ -713,7 +728,8 @@ int ServiceImpl::userAdd(const Credentials &creds, uid_t uidAdded, int userType) } try { - CynaraAdmin::getInstance().UserInit(uidAdded, static_cast(userType)); + CynaraAdmin::getInstance().UserInit(uidAdded, static_cast(userType), isPrivilegePrivacy); + } catch (CynaraException::InvalidParam &e) { return SECURITY_MANAGER_ERROR_INPUT_PARAM; }