cynara: handle additional error codes from Cynara API
[platform/core/security/security-manager.git] / src / common / cynara.cpp
index 39b7e05..14acb36 100644 (file)
@@ -175,6 +175,26 @@ CynaraAdminPolicy::CynaraAdminPolicy(CynaraAdminPolicy &&that)
     that.result_extra = nullptr;
 }
 
+CynaraAdminPolicy& CynaraAdminPolicy::operator=(CynaraAdminPolicy &&that)
+{
+    if (this != &that) {
+        bucket = that.bucket;
+        client = that.client;
+        user = that.user;
+        privilege = that.privilege;
+        result_extra = that.result_extra;
+        result = that.result;
+
+        that.bucket = nullptr;
+        that.client = nullptr;
+        that.user = nullptr;
+        that.privilege = nullptr;
+        that.result_extra = nullptr;
+    };
+
+    return *this;
+}
+
 CynaraAdminPolicy::~CynaraAdminPolicy()
 {
     free(this->bucket);
@@ -192,12 +212,20 @@ static bool checkCynaraError(int result, const std::string &msg)
             return true;
         case CYNARA_API_ACCESS_DENIED:
             return false;
+        case CYNARA_API_MAX_PENDING_REQUESTS:
+            ThrowMsg(CynaraException::MaxPendingRequests, msg);
         case CYNARA_API_OUT_OF_MEMORY:
             ThrowMsg(CynaraException::OutOfMemory, msg);
         case CYNARA_API_INVALID_PARAM:
             ThrowMsg(CynaraException::InvalidParam, msg);
         case CYNARA_API_SERVICE_NOT_AVAILABLE:
             ThrowMsg(CynaraException::ServiceNotAvailable, msg);
+        case CYNARA_API_METHOD_NOT_SUPPORTED:
+            ThrowMsg(CynaraException::MethodNotSupported, msg);
+        case CYNARA_API_OPERATION_NOT_ALLOWED:
+            ThrowMsg(CynaraException::OperationNotAllowed, msg);
+        case CYNARA_API_OPERATION_FAILED:
+            ThrowMsg(CynaraException::OperationFailed, msg);
         case CYNARA_API_BUCKET_NOT_FOUND:
             ThrowMsg(CynaraException::BucketNotFound, msg);
         default:
@@ -205,7 +233,11 @@ static bool checkCynaraError(int result, const std::string &msg)
     }
 }
 
+CynaraAdmin::TypeToDescriptionMap CynaraAdmin::TypeToDescription;
+CynaraAdmin::DescriptionToTypeMap CynaraAdmin::DescriptionToType;
+
 CynaraAdmin::CynaraAdmin()
+    : m_policyDescriptionsInitialized(false)
 {
     checkCynaraError(
         cynara_admin_initialize(&m_CynaraAdmin),
@@ -225,6 +257,11 @@ CynaraAdmin &CynaraAdmin::getInstance()
 
 void CynaraAdmin::SetPolicies(const std::vector<CynaraAdminPolicy> &policies)
 {
+    if (policies.empty()) {
+        LogDebug("no policies to set in Cynara.");
+        return;
+    }
+
     std::vector<const struct cynara_admin_policy *> pp_policies(policies.size() + 1);
 
     LogDebug("Sending " << policies.size() << " policies to Cynara");
@@ -337,6 +374,30 @@ void CynaraAdmin::UserInit(uid_t uid, security_manager_user_type userType)
     CynaraAdmin::getInstance().SetPolicies(policies);
 }
 
+void CynaraAdmin::ListUsers(std::vector<uid_t> &listOfUsers)
+{
+    std::vector<CynaraAdminPolicy> tmpListOfUsers;
+    CynaraAdmin::getInstance().ListPolicies(
+        CynaraAdmin::Buckets.at(Bucket::MAIN),
+        CYNARA_ADMIN_WILDCARD,
+        CYNARA_ADMIN_ANY,
+        CYNARA_ADMIN_WILDCARD,
+        tmpListOfUsers);
+
+    for (const auto &tmpUser : tmpListOfUsers) {
+        std::string user = tmpUser.user;
+        if (!user.compare(CYNARA_ADMIN_WILDCARD))
+            continue;
+        try {
+            listOfUsers.push_back(std::stoul(user));
+        } catch (std::invalid_argument &e) {
+            LogError("Invalid UID: " << e.what());
+            continue;
+        };
+    };
+    LogDebug("Found users: " << listOfUsers.size());
+};
+
 void CynaraAdmin::UserRemove(uid_t uid)
 {
     std::vector<CynaraAdminPolicy> policies;
@@ -380,6 +441,107 @@ void CynaraAdmin::EmptyBucket(const std::string &bucketName, bool recursive, con
             client + ", " + user + ", " + privilege);
 }
 
+void CynaraAdmin::FetchCynaraPolicyDescriptions(bool forceRefresh)
+{
+    struct cynara_admin_policy_descr **descriptions = nullptr;
+
+    if (!forceRefresh && m_policyDescriptionsInitialized)
+        return;
+
+    // fetch
+    checkCynaraError(
+        cynara_admin_list_policies_descriptions(m_CynaraAdmin, &descriptions),
+        "Error while getting list of policies descriptions from Cynara.");
+
+    if (descriptions[0] == nullptr) {
+        LogError("Fetching policies levels descriptions from Cynara returned empty list. "
+                "There should be at least 2 entries - Allow and Deny");
+        return;
+    }
+
+    // reset the state
+    m_policyDescriptionsInitialized = false;
+    DescriptionToType.clear();
+    TypeToDescription.clear();
+
+    // extract strings
+    for (int i = 0; descriptions[i] != nullptr; i++) {
+        std::string descriptionName(descriptions[i]->name);
+
+        DescriptionToType[descriptionName] = descriptions[i]->result;
+        TypeToDescription[descriptions[i]->result] = std::move(descriptionName);
+
+        free(descriptions[i]->name);
+        free(descriptions[i]);
+    }
+
+    free(descriptions);
+
+    m_policyDescriptionsInitialized = true;
+}
+
+void CynaraAdmin::ListPoliciesDescriptions(std::vector<std::string> &policiesDescriptions)
+{
+    FetchCynaraPolicyDescriptions(false);
+
+    for (const auto &it : TypeToDescription)
+        policiesDescriptions.push_back(it.second);
+}
+
+std::string CynaraAdmin::convertToPolicyDescription(const int policyType, bool forceRefresh)
+{
+    FetchCynaraPolicyDescriptions(forceRefresh);
+
+    return TypeToDescription.at(policyType);
+}
+
+int CynaraAdmin::convertToPolicyType(const std::string &policy, bool forceRefresh)
+{
+    FetchCynaraPolicyDescriptions(forceRefresh);
+
+    return DescriptionToType.at(policy);
+}
+void CynaraAdmin::Check(const std::string &label, const std::string &user, const std::string &privilege,
+    const std::string &bucket, int &result, std::string &resultExtra, const bool recursive)
+{
+    char *resultExtraCstr = nullptr;
+
+    checkCynaraError(
+        cynara_admin_check(m_CynaraAdmin, bucket.c_str(), recursive, label.c_str(),
+            user.c_str(), privilege.c_str(), &result, &resultExtraCstr),
+        "Error while asking cynara admin API for permission for app label: " + label + ", user: "
+            + user + " privilege: " + privilege + " bucket: " + bucket);
+
+    if (resultExtraCstr == nullptr)
+        resultExtra = "";
+    else {
+        resultExtra = std::string(resultExtraCstr);
+        free(resultExtraCstr);
+    }
+}
+
+int CynaraAdmin::GetPrivilegeManagerCurrLevel(const std::string &label, const std::string &user,
+        const std::string &privilege)
+{
+    int result;
+    std::string resultExtra;
+
+    Check(label, user, privilege, Buckets.at(Bucket::PRIVACY_MANAGER), result, resultExtra, true);
+
+    return result;
+}
+
+int CynaraAdmin::GetPrivilegeManagerMaxLevel(const std::string &label, const std::string &user,
+        const std::string &privilege)
+{
+    int result;
+    std::string resultExtra;
+
+    Check(label, user, privilege, Buckets.at(Bucket::MAIN), result, resultExtra, true);
+
+    return result;
+}
+
 Cynara::Cynara()
 {
     checkCynaraError(