private:
SecurityManager::DB::SqlConnection *mSqlConnection;
const std::map<QueryType, const char * const > 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 (?, ?, ?)" },
#include <vector>
#include "cynara.h"
+#include <dpl/log/log.h>
+
namespace SecurityManager {
{
std::vector<const struct cynara_admin_policy *> 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<const struct cynara_admin_policy *>(&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;
"Error while updating Cynara policy.");
}
+void CynaraAdmin::UpdatePackagePolicy(
+ const std::string &pkg,
+ const std::string &user,
+ const std::vector<std::string> &oldPrivileges,
+ const std::vector<std::string> &newPrivileges)
+{
+ CynaraAdmin cynaraAdmin;
+ std::vector<CynaraAdminPolicy> 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
*/
void SetPolicies(const std::vector<CynaraAdminPolicy> &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<std::string> &oldPrivileges,
+ const std::vector<std::string> &newPrivileges);
+
private:
struct cynara_admin *m_CynaraAdmin;
};
#include "smack-rules.h"
#include "smack-labels.h"
#include "privilege_db.h"
+#include "cynara.h"
namespace SecurityManager {
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
m_privilegeDb.UpdateAppPrivileges(appId, uid, std::vector<std::string>());
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");
}
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) {