From eb01bad83e70424dc8196bdbbd969d815dcee035 Mon Sep 17 00:00:00 2001 From: Rafal Krypa Date: Mon, 14 Jul 2014 00:21:26 +0200 Subject: [PATCH] Set Cynara policies during application installation and uninstallation Applied policies will have a wildcard in "user" field. Security-manager will handle app installation per user soon, so this will also be changed. Change-Id: I41606fb94b7385426debbcf47a57ba1593dbfc5a Signed-off-by: Rafal Krypa Signed-off-by: Jan Cybulski --- src/server/db/include/privilege_db.h | 2 +- src/server/service/cynara.cpp | 68 +++++++++++++++++++++++++++++++++++- src/server/service/include/cynara.h | 22 ++++++++++++ src/server/service/installer.cpp | 25 +++++++++++-- 4 files changed, 113 insertions(+), 4 deletions(-) diff --git a/src/server/db/include/privilege_db.h b/src/server/db/include/privilege_db.h index 7890022..b508576 100644 --- a/src/server/db/include/privilege_db.h +++ b/src/server/db/include/privilege_db.h @@ -61,7 +61,7 @@ class PrivilegeDb { private: SecurityManager::DB::SqlConnection *mSqlConnection; const std::map Queries = { - { QueryType::EGetPkgPrivileges, "SELECT privilege_name FROM app_privilege_view WHERE pkg_name=? AND uid=?"}, + { QueryType::EGetPkgPrivileges, "SELECT DISTINCT privilege_name FROM app_privilege_view WHERE pkg_name=? AND uid=? ORDER BY privilege_name"}, { QueryType::EAddApplication, "INSERT INTO app_pkg_view (app_name, pkg_name, uid) VALUES (?, ?, ?)" }, { QueryType::ERemoveApplication, "DELETE FROM app_pkg_view WHERE app_name=? AND uid=?" }, { QueryType::EAddAppPrivileges, "INSERT INTO app_privilege_view (app_name, uid, privilege_name) VALUES (?, ?, ?)" }, diff --git a/src/server/service/cynara.cpp b/src/server/service/cynara.cpp index 4925984..ab9dbf3 100644 --- a/src/server/service/cynara.cpp +++ b/src/server/service/cynara.cpp @@ -26,6 +26,8 @@ #include #include "cynara.h" +#include + namespace SecurityManager { @@ -133,8 +135,17 @@ void CynaraAdmin::SetPolicies(const std::vector &policies) { std::vector pp_policies(policies.size() + 1); - for (std::size_t i = 0; i < policies.size(); ++i) + LogDebug("Sending " << policies.size() << " policies to Cynara"); + for (std::size_t i = 0; i < policies.size(); ++i) { pp_policies[i] = static_cast(&policies[i]); + LogDebug("policies[" << i << "] = {" << + ".bucket = " << pp_policies[i]->bucket << ", " << + ".client = " << pp_policies[i]->client << ", " << + ".user = " << pp_policies[i]->user << ", " << + ".privilege = " << pp_policies[i]->privilege << ", " << + ".result = " << pp_policies[i]->result << ", " << + ".result_extra = " << pp_policies[i]->result_extra << "}"); + } pp_policies[policies.size()] = nullptr; @@ -143,4 +154,59 @@ void CynaraAdmin::SetPolicies(const std::vector &policies) "Error while updating Cynara policy."); } +void CynaraAdmin::UpdatePackagePolicy( + const std::string &pkg, + const std::string &user, + const std::vector &oldPrivileges, + const std::vector &newPrivileges) +{ + CynaraAdmin cynaraAdmin; + std::vector policies; + + // Perform sort-merge join on oldPrivileges and newPrivileges. + // Assume that they are already sorted and without duplicates. + auto oldIter = oldPrivileges.begin(); + auto newIter = newPrivileges.begin(); + + while (oldIter != oldPrivileges.end() && newIter != newPrivileges.end()) { + int compare = oldIter->compare(*newIter); + if (compare == 0) { + LogDebug("(user = " << user << " pkg = " << pkg << ") " << + "keeping privilege " << *newIter); + ++oldIter; + ++newIter; + continue; + } else if (compare < 0) { + LogDebug("(user = " << user << " pkg = " << pkg << ") " << + "removing privilege " << *oldIter); + policies.push_back(CynaraAdminPolicy(pkg, user, *oldIter, + CynaraAdminPolicy::Operation::Delete)); + ++oldIter; + } else { + LogDebug("(user = " << user << " pkg = " << pkg << ") " << + "adding privilege " << *newIter); + policies.push_back(CynaraAdminPolicy(pkg, user, *newIter, + CynaraAdminPolicy::Operation::Allow)); + ++newIter; + } + } + + for (; oldIter != oldPrivileges.end(); ++oldIter) { + LogDebug("(user = " << user << " pkg = " << pkg << ") " << + "removing privilege " << *oldIter); + policies.push_back(CynaraAdminPolicy(pkg, user, *oldIter, + CynaraAdminPolicy::Operation::Delete)); + } + + for (; newIter != newPrivileges.end(); ++newIter) { + LogDebug("(user = " << user << " pkg = " << pkg << ") " << + "adding privilege " << *newIter); + policies.push_back(CynaraAdminPolicy(pkg, user, *newIter, + CynaraAdminPolicy::Operation::Allow)); + } + + cynaraAdmin.SetPolicies(policies); +} + + } // namespace SecurityManager diff --git a/src/server/service/include/cynara.h b/src/server/service/include/cynara.h index df28fdc..0daa1e5 100644 --- a/src/server/service/include/cynara.h +++ b/src/server/service/include/cynara.h @@ -80,6 +80,28 @@ public: */ void SetPolicies(const std::vector &policies); + /** + * Update Cynara policies for the package and the user, using two vectors + * of privileges: privileges set before (and already enabled in Cynara) + * and new privileges, to be set in Cynara. + * Difference will be calculated, removing old unneeded privileges and + * adding new, previously not enabled privileges. + * Caller must have permission to access Cynara administrative socket. + * + * @param pkg package identifier + * @param user user identifier + * @param oldPrivileges previously enabled privileges for the package. + * Must be sorted and without duplicates. + * @param newPrivileges currently enabled privileges for the package. + * Must be sorted and without duplicates. + * + * TODO: drop oldPrivileges argument and get them directly from Cynara. + * Appropriate Cynara interface is needed first. + */ + static void UpdatePackagePolicy(const std::string &pkg, const std::string &user, + const std::vector &oldPrivileges, + const std::vector &newPrivileges); + private: struct cynara_admin *m_CynaraAdmin; }; diff --git a/src/server/service/installer.cpp b/src/server/service/installer.cpp index 286fce6..0e5ec01 100644 --- a/src/server/service/installer.cpp +++ b/src/server/service/installer.cpp @@ -40,6 +40,7 @@ #include "smack-rules.h" #include "smack-labels.h" #include "privilege_db.h" +#include "cynara.h" namespace SecurityManager { @@ -286,13 +287,23 @@ bool InstallerService::processAppInstall(MessageBuffer &buffer, MessageBuffer &s m_privilegeDb.AddApplication(req.appId, req.pkgId, uid, pkgIdIsNew); m_privilegeDb.UpdateAppPrivileges(req.appId, uid, req.privileges); m_privilegeDb.GetPkgPrivileges(req.pkgId, uid, newPkgPrivileges); - // TODO: configure Cynara rules based on oldPkgPrivileges and newPkgPrivileges + CynaraAdmin::UpdatePackagePolicy(req.pkgId, + CYNARA_ADMIN_WILDCARD, /* TODO: pass proper user identifier */ + oldPkgPrivileges, newPkgPrivileges); m_privilegeDb.CommitTransaction(); LogDebug("Application installation commited to database"); } catch (const PrivilegeDb::Exception::InternalError &e) { m_privilegeDb.RollbackTransaction(); LogError("Error while saving application info to database: " << e.DumpToString()); goto error_label; + } catch (const CynaraException::Base &e) { + m_privilegeDb.RollbackTransaction(); + LogError("Error while setting Cynara rules for application: " << e.DumpToString()); + goto error_label; + } catch (const std::bad_alloc &e) { + m_privilegeDb.RollbackTransaction(); + LogError("Memory allocation while setting Cynara rules for application: " << e.what()); + goto error_label; } // register paths @@ -382,7 +393,9 @@ bool InstallerService::processAppUninstall(MessageBuffer &buffer, MessageBuffer m_privilegeDb.UpdateAppPrivileges(appId, uid, std::vector()); m_privilegeDb.RemoveApplication(appId, uid, removePkg); m_privilegeDb.GetPkgPrivileges(pkgId, uid, newPkgPrivileges); - // TODO: configure Cynara rules based on oldPkgPrivileges and newPkgPrivileges + CynaraAdmin::UpdatePackagePolicy(pkgId, + CYNARA_ADMIN_WILDCARD, /* TODO: pass proper user identifier */ + oldPkgPrivileges, newPkgPrivileges); m_privilegeDb.CommitTransaction(); LogDebug("Application uninstallation commited to database"); } @@ -390,6 +403,14 @@ bool InstallerService::processAppUninstall(MessageBuffer &buffer, MessageBuffer m_privilegeDb.RollbackTransaction(); LogError("Error while removing application info from database: " << e.DumpToString()); goto error_label; + } catch (const CynaraException::Base &e) { + m_privilegeDb.RollbackTransaction(); + LogError("Error while setting Cynara rules for application: " << e.DumpToString()); + goto error_label; + } catch (const std::bad_alloc &e) { + m_privilegeDb.RollbackTransaction(); + LogError("Memory allocation while setting Cynara rules for application: " << e.what()); + goto error_label; } if (appExists) { -- 2.7.4