* @author Michal Witanowski <m.witanowski@samsung.com>
* @author Jacek Bukarewicz <j.bukarewicz@samsung.com>
* @author Rafal Krypa <r.krypa@samsung.com>
+ * @author Krzysztof Sasiak <k.sasiak@samsung.com>
* @brief Implementation of the service methods
*/
#include "cynara.h"
#include "smack-rules.h"
#include "smack-labels.h"
+#include "security-manager.h"
#include "service_impl.h"
namespace SecurityManager {
namespace ServiceImpl {
+static const std::string ADMIN_PRIVILEGE = "http://tizen.org/privilege/systemsettings.admin";
+static const std::string SELF_PRIVILEGE = "http://tizen.org/privilege/systemsettings";
+
+namespace {
+
+static inline int validatePolicy(policy_entry &policyEntry, std::string uidStr, bool &forAdmin, CynaraAdminPolicy &cyap)
+{
+ LogDebug("Authenticating and validating policy update request for user with id: " << uidStr);
+ LogDebug("[policy_entry] app: " << policyEntry.appId
+ << " user: " << policyEntry.user
+ << " privilege: " << policyEntry.privilege
+ << " current: " << policyEntry.currentLevel
+ << " max: " << policyEntry.maxLevel);
+ //automagically fill missing fields:
+ if (policyEntry.user.empty()) {
+ policyEntry.user = uidStr;
+ };
+
+ std::string client;
+ int level;
+
+ if (policyEntry.currentLevel.empty()) { //for admin
+ if (policyEntry.appId.empty()
+ || policyEntry.privilege.empty()) {
+ LogError("Bad admin update request");
+ return SECURITY_MANAGER_API_ERROR_BAD_REQUEST;
+ };
+
+ if (!policyEntry.maxLevel.compare(SECURITY_MANAGER_DELETE)) {
+ level = CYNARA_ADMIN_DELETE;
+ } else {
+ try {
+ level = CynaraAdmin::getInstance().convertToPolicyType(policyEntry.maxLevel);
+ } catch (const std::out_of_range& e) {
+ LogError("policy max level cannot be: " << policyEntry.maxLevel);
+ return SECURITY_MANAGER_API_ERROR_INPUT_PARAM;
+ };
+ };
+ forAdmin = true;
+
+ } else if (policyEntry.maxLevel.empty()) { //for self
+ if (policyEntry.user.compare(uidStr)
+ || !policyEntry.appId.compare(SECURITY_MANAGER_ANY)
+ || !policyEntry.privilege.compare(SECURITY_MANAGER_ANY)
+ || policyEntry.appId.empty()
+ || policyEntry.privilege.empty()) {
+ LogError("Bad privacy manager update request");
+ return SECURITY_MANAGER_API_ERROR_BAD_REQUEST;
+ };
+
+ if (!policyEntry.currentLevel.compare(SECURITY_MANAGER_DELETE)) {
+ level = CYNARA_ADMIN_DELETE;
+ } else {
+ try {
+ level = CynaraAdmin::getInstance().convertToPolicyType(policyEntry.currentLevel);
+ } catch (const std::out_of_range& e) {
+ LogError("policy current level cannot be: " << policyEntry.currentLevel);
+ return SECURITY_MANAGER_API_ERROR_INPUT_PARAM;
+ };
+ };
+ forAdmin = false;
+
+ } else { //neither => bad request
+ return SECURITY_MANAGER_API_ERROR_BAD_REQUEST;
+ };
+
+ if (!policyEntry.user.compare(SECURITY_MANAGER_ANY))
+ policyEntry.user = CYNARA_ADMIN_WILDCARD;
+ if (!policyEntry.privilege.compare(SECURITY_MANAGER_ANY))
+ policyEntry.privilege = CYNARA_ADMIN_WILDCARD;
+ if (policyEntry.appId.compare(SECURITY_MANAGER_ANY))
+ generateAppLabel(policyEntry.appId, client);
+ else
+ client = CYNARA_ADMIN_WILDCARD;
+
+ cyap = std::move(CynaraAdminPolicy(
+ client,
+ policyEntry.user,
+ policyEntry.privilege,
+ level,
+ (forAdmin)?CynaraAdmin::Buckets.at(Bucket::ADMIN):CynaraAdmin::Buckets.at(Bucket::PRIVACY_MANAGER)));
+
+ LogDebug("Policy update request authenticated and validated successfully");
+ return SECURITY_MANAGER_API_SUCCESS;
+}
+} // end of anonymous namespace
+
static uid_t getGlobalUserId(void)
{
static uid_t globaluid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
return ret;
}
+int policyUpdate(const std::vector<policy_entry> &policyEntries, uid_t uid, pid_t pid, const std::string &smackLabel)
+{
+ enum {
+ NOT_CHECKED,
+ IS_NOT_ADMIN,
+ IS_ADMIN
+ } isAdmin = NOT_CHECKED;
+
+ try {
+ std::string uidStr = std::to_string(uid);
+ std::string pidStr = std::to_string(pid);
+
+ if (policyEntries.size() == 0) {
+ LogError("Validation failed: policy update request is empty");
+ return SECURITY_MANAGER_API_ERROR_BAD_REQUEST;
+ };
+
+ if (!Cynara::getInstance().check(smackLabel, SELF_PRIVILEGE, uidStr, pidStr)) {
+ LogError("Not enough permission to call: " << __FUNCTION__);
+ return SECURITY_MANAGER_API_ERROR_ACCESS_DENIED;
+ };
+
+ std::vector<CynaraAdminPolicy> validatedPolicies;
+
+ for (auto &entry : const_cast<std::vector<policy_entry>&>(policyEntries)) {
+ bool forAdmin = false;
+ CynaraAdminPolicy cyap("", "", "", CYNARA_ADMIN_NONE, "");
+ int ret = validatePolicy(entry, uidStr, forAdmin, cyap);
+
+ if (forAdmin && (isAdmin == NOT_CHECKED)) {
+ isAdmin = Cynara::getInstance().check(smackLabel, ADMIN_PRIVILEGE, uidStr, pidStr)?IS_ADMIN:IS_NOT_ADMIN;
+ };
+
+ if (ret == SECURITY_MANAGER_API_SUCCESS) {
+ if (!forAdmin
+ || (forAdmin && (isAdmin == IS_ADMIN))) {
+ validatedPolicies.push_back(std::move(cyap));
+ } else {
+ LogError("Not enough privilege to enforce admin policy");
+ return SECURITY_MANAGER_API_ERROR_ACCESS_DENIED;
+ };
+
+ } else
+ return ret;
+ };
+
+ // Apply updates
+ CynaraAdmin::getInstance().SetPolicies(validatedPolicies);
+
+ } catch (const CynaraException::Base &e) {
+ LogError("Error while updating Cynara rules: " << e.DumpToString());
+ return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
+ } catch (const std::bad_alloc &e) {
+ LogError("Memory allocation error while updating Cynara rules: " << e.what());
+ return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
+ }
+
+ return SECURITY_MANAGER_API_SUCCESS;
+}
+
} /* namespace ServiceImpl */
} /* namespace SecurityManager */