From e03e935bd510283741971ac22cc8fc0995450a04 Mon Sep 17 00:00:00 2001 From: Maksym Ked Date: Thu, 6 Jun 2019 14:35:30 +0300 Subject: Added permission check of encryption required for PROP --- .../policy_regular/include/policy/policy_helper.h | 46 +++-- .../include/policy/policy_manager_impl.h | 26 ++- .../policy_regular/include/policy/policy_types.h | 25 ++- .../policy/policy_regular/src/policy_helper.cc | 185 ++++++++++++++++++--- .../policy_regular/src/policy_manager_impl.cc | 98 ++++++++++- 5 files changed, 340 insertions(+), 40 deletions(-) diff --git a/src/components/policy/policy_regular/include/policy/policy_helper.h b/src/components/policy/policy_regular/include/policy/policy_helper.h index 887493f415..dfd12e7874 100644 --- a/src/components/policy/policy_regular/include/policy/policy_helper.h +++ b/src/components/policy/policy_regular/include/policy/policy_helper.h @@ -83,22 +83,11 @@ bool operator!=(const policy_table::ApplicationParams& first, struct CheckAppPolicy { CheckAppPolicy(PolicyManagerImpl* pm, const std::shared_ptr update, - const std::shared_ptr snapshot); + const std::shared_ptr snapshot, + CheckAppPolicyResults& out_results); bool operator()(const AppPoliciesValueType& app_policy); private: - enum PermissionsCheckResult { - RESULT_NO_CHANGES, - RESULT_APP_REVOKED, - RESULT_NICKNAME_MISMATCH, - RESULT_PERMISSIONS_REVOKED, - RESULT_CONSENT_NEEDED, - RESULT_CONSENT_NOT_REQIURED, - RESULT_PERMISSIONS_REVOKED_AND_CONSENT_NEEDED, - RESULT_REQUEST_TYPE_CHANGED, - RESULT_REQUEST_SUBTYPE_CHANGED - }; - void SetPendingPermissions(const AppPoliciesValueType& app_policy, PermissionsCheckResult result) const; PermissionsCheckResult CheckPermissionsChanges( @@ -119,6 +108,16 @@ struct CheckAppPolicy { const policy_table::Strings& groups) const; bool IsAppRevoked(const AppPoliciesValueType& app_policy) const; bool NicknamesMatch(const AppPoliciesValueType& app_policy) const; + + /** + * @brief Check of current policy against incoming updated policy is + * performed. + * This function adds result code of this check to container. + * @param app_id Application id + * @param result Result value + */ + void AddResult(const std::string& app_id, PermissionsCheckResult result); + /** * @brief Allows to check if appropriate group requires any consent. * @param group_name the group for which consent will be checked. @@ -129,10 +128,31 @@ struct CheckAppPolicy { bool IsRequestTypeChanged(const AppPoliciesValueType& app_policy) const; bool IsRequestSubTypeChanged(const AppPoliciesValueType& app_policy) const; + bool IsEncryptionRequiredFlagChanged( + const AppPoliciesValueType& app_policy) const; + private: PolicyManagerImpl* pm_; const std::shared_ptr update_; const std::shared_ptr snapshot_; + CheckAppPolicyResults& out_results_; +}; + +/** + * @brief Helper struct for filling actions to be done for processed application + * using CheckAppPolicyResults data as a source + */ +struct FillActionsForAppPolicies { + FillActionsForAppPolicies( + ApplicationsPoliciesActions& actions, + const policy_table::ApplicationPolicies& app_policies) + : actions_(actions), app_policies_(app_policies) {} + + void operator()(const policy::CheckAppPolicyResults::value_type& value); + + private: + ApplicationsPoliciesActions& actions_; + const policy_table::ApplicationPolicies& app_policies_; }; /* diff --git a/src/components/policy/policy_regular/include/policy/policy_manager_impl.h b/src/components/policy/policy_regular/include/policy/policy_manager_impl.h index 93d0c45fcc..d83dd52008 100644 --- a/src/components/policy/policy_regular/include/policy/policy_manager_impl.h +++ b/src/components/policy/policy_regular/include/policy/policy_manager_impl.h @@ -132,6 +132,21 @@ class PolicyManagerImpl : public PolicyManager { bool LoadPT(const std::string& file, const BinaryMessage& pt_content) OVERRIDE; + typedef policy_table::ApplicationPolicies::value_type AppPoliciesValueType; + + /** + * @brief Notifies system by sending OnAppPermissionChanged notification + * @param app_policy Reference to application policy + */ + void NotifySystem(const AppPoliciesValueType& app_policy) const; + + /** + * @brief Sends OnPermissionChange notification to application if its + * currently registered + * @param app_policy Reference to application policy + */ + void SendPermissionsToApp(const AppPoliciesValueType& app_policy); + /** * @brief Resets Policy Table * @param file_name Path to preloaded PT file @@ -855,10 +870,19 @@ class PolicyManagerImpl : public PolicyManager { * @param snapshot Shared pointer to current copy of policy table * @return Collection per-application results */ - void CheckPermissionsChanges( + CheckAppPolicyResults CheckPermissionsChanges( const std::shared_ptr update, const std::shared_ptr snapshot); + void ProcessAppPolicyCheckResults( + const CheckAppPolicyResults& results, + const rpc::policy_table_interface_base::ApplicationPolicies& + app_policies); + + void ProcessActionsForAppPolicies( + const ApplicationsPoliciesActions& actions, + const policy_table::ApplicationPolicies& app_policies); + /** * @brief Fill structure to be sent with OnPermissionsChanged notification * diff --git a/src/components/policy/policy_regular/include/policy/policy_types.h b/src/components/policy/policy_regular/include/policy/policy_types.h index e08d6d503e..d2858f3c59 100644 --- a/src/components/policy/policy_regular/include/policy/policy_types.h +++ b/src/components/policy/policy_regular/include/policy/policy_types.h @@ -430,6 +430,28 @@ struct ExternalConsentStatusItemSorter { } }; +/** + * @brief The ApplicationPolicyActions struct contains actions which should be + * done for some application + */ +struct ApplicationPolicyActions { + ApplicationPolicyActions() + : is_notify_system(false) + , is_send_permissions_to_app(false) + , is_consent_needed(false) {} + + bool is_notify_system; + bool is_send_permissions_to_app; + bool is_consent_needed; +}; + +/** + * @brief ApplicationsPoliciesActions map of actions to be done for every + * application + */ +typedef std::map + ApplicationsPoliciesActions; + /** * @brief Customer connectivity settings status */ @@ -479,7 +501,8 @@ enum PermissionsCheckResult { RESULT_CONSENT_NOT_REQIURED, RESULT_PERMISSIONS_REVOKED_AND_CONSENT_NEEDED, RESULT_REQUEST_TYPE_CHANGED, - RESULT_REQUEST_SUBTYPE_CHANGED + RESULT_REQUEST_SUBTYPE_CHANGED, + RESULT_ENCRYPTION_REQUIRED_FLAG_CHANGED }; /** diff --git a/src/components/policy/policy_regular/src/policy_helper.cc b/src/components/policy/policy_regular/src/policy_helper.cc index d9954daf81..255664b2e9 100644 --- a/src/components/policy/policy_regular/src/policy_helper.cc +++ b/src/components/policy/policy_regular/src/policy_helper.cc @@ -122,8 +122,12 @@ bool operator!=(const policy_table::ApplicationParams& first, CheckAppPolicy::CheckAppPolicy( PolicyManagerImpl* pm, const std::shared_ptr update, - const std::shared_ptr snapshot) - : pm_(pm), update_(update), snapshot_(snapshot) {} + const std::shared_ptr snapshot, + CheckAppPolicyResults& out_results) + : pm_(pm) + , update_(update) + , snapshot_(snapshot) + , out_results_(out_results) {} bool policy::CheckAppPolicy::HasRevokedGroups( const policy::AppPoliciesValueType& app_policy, @@ -317,6 +321,13 @@ bool CheckAppPolicy::NicknamesMatch( return true; } +void CheckAppPolicy::AddResult(const std::string& app_id, + PermissionsCheckResult result) { + LOG4CXX_AUTO_TRACE(logger_); + const auto item = std::make_pair(app_id, result); + out_results_.insert(item); +} + bool CheckAppPolicy::operator()(const AppPoliciesValueType& app_policy) { const std::string app_id = app_policy.first; @@ -328,13 +339,13 @@ bool CheckAppPolicy::operator()(const AppPoliciesValueType& app_policy) { if (!IsPredefinedApp(app_policy) && IsAppRevoked(app_policy)) { SetPendingPermissions(app_policy, RESULT_APP_REVOKED); - NotifySystem(app_policy); + AddResult(app_id, RESULT_APP_REVOKED); return true; } if (!IsPredefinedApp(app_policy) && !NicknamesMatch(app_policy)) { SetPendingPermissions(app_policy, RESULT_NICKNAME_MISMATCH); - NotifySystem(app_policy); + AddResult(app_id, RESULT_NICKNAME_MISMATCH); return true; } @@ -345,48 +356,51 @@ bool CheckAppPolicy::operator()(const AppPoliciesValueType& app_policy) { if (is_request_type_changed) { SetPendingPermissions(app_policy, RESULT_REQUEST_TYPE_CHANGED); + AddResult(app_id, RESULT_REQUEST_TYPE_CHANGED); } if (is_request_subtype_changed) { SetPendingPermissions(app_policy, RESULT_REQUEST_SUBTYPE_CHANGED); - } - - if (is_request_type_changed || is_request_subtype_changed) { - NotifySystem(app_policy); + AddResult(app_id, RESULT_REQUEST_SUBTYPE_CHANGED); } } if (RESULT_NO_CHANGES == result) { - LOG4CXX_INFO( - logger_, - "Permissions for application:" << app_id << " wasn't changed."); + LOG4CXX_INFO(logger_, + "Permissions for application:" << app_id + << " wasn't changed."); + AddResult(app_id, RESULT_NO_CHANGES); return true; } - LOG4CXX_INFO( - logger_, - "Permissions for application:" << app_id << " have been changed."); + LOG4CXX_INFO(logger_, + "Permissions for application:" << app_id + << " have been changed."); if (IsPredefinedApp(app_policy)) { + LOG4CXX_DEBUG(logger_, "app id: " << app_id << " is predefined app"); for (const policy_table::ApplicationPolicies::value_type& app : snapshot_->policy_table.app_policies_section.apps) { if (app_policy.first == app.second.get_string()) { if (RESULT_CONSENT_NOT_REQIURED != result) { SetPendingPermissions(app, result); - NotifySystem(app); + AddResult(app_id, RESULT_CONSENT_NEEDED); } - SendPermissionsToApp(app.first, app_policy.second.groups); + LOG4CXX_DEBUG(logger_, "Sending permissions for app: " << app_id); } } return true; } if (!IsPredefinedApp(app_policy) && RESULT_CONSENT_NOT_REQIURED != result) { + LOG4CXX_DEBUG(logger_, "Sending permissions for app: " << app_id); SetPendingPermissions(app_policy, result); - NotifySystem(app_policy); + AddResult(app_id, RESULT_CONSENT_NEEDED); } // Don't sent notification for predefined apps (e.g. default, device etc.) if (!IsPredefinedApp(app_policy)) { - SendPermissionsToApp(app_policy.first, app_policy.second.groups); + LOG4CXX_DEBUG(logger_, "Sending permissions for app: " << app_id); + SetPendingPermissions(app_policy, result); + AddResult(app_id, result); } return true; } @@ -445,8 +459,7 @@ void policy::CheckAppPolicy::SetPendingPermissions( pm_->app_permissions_diff_lock_.Release(); } -policy::CheckAppPolicy::PermissionsCheckResult -policy::CheckAppPolicy::CheckPermissionsChanges( +policy::PermissionsCheckResult policy::CheckAppPolicy::CheckPermissionsChanges( const policy::AppPoliciesValueType& app_policy) const { bool has_revoked_groups = HasRevokedGroups(app_policy); @@ -454,6 +467,9 @@ policy::CheckAppPolicy::CheckPermissionsChanges( bool has_new_groups = HasNewGroups(app_policy); + const bool encryption_required_flag_changed = + IsEncryptionRequiredFlagChanged(app_policy); + if (has_revoked_groups && has_consent_needed_groups) { return RESULT_PERMISSIONS_REVOKED_AND_CONSENT_NEEDED; } else if (has_revoked_groups) { @@ -462,6 +478,8 @@ policy::CheckAppPolicy::CheckPermissionsChanges( return RESULT_CONSENT_NEEDED; } else if (has_new_groups) { return RESULT_CONSENT_NOT_REQIURED; + } else if (encryption_required_flag_changed) { + return RESULT_ENCRYPTION_REQUIRED_FLAG_CHANGED; } return RESULT_NO_CHANGES; @@ -530,6 +548,133 @@ bool CheckAppPolicy::IsRequestSubTypeChanged( return diff.size(); } +bool CheckAppPolicy::IsEncryptionRequiredFlagChanged( + const AppPoliciesValueType& app_policy) const { + auto get_app_encryption_needed = + [](const std::string& policy_app_id, + policy_table::ApplicationPolicies& policies) + -> rpc::Optional { + auto it = policies.find(policy_app_id); + if (policies.end() == it) { + LOG4CXX_WARN(logger_, + "App is not present in policies" << policy_app_id); + return rpc::Optional(false); + } + return it->second.encryption_required; + }; + + auto get_app_groups = + [](const std::string& policy_app_id, + policy_table::ApplicationPolicies& policies) -> policy_table::Strings { + policy_table::Strings result; + auto it = policies.find(policy_app_id); + if (policies.end() == it) { + LOG4CXX_WARN(logger_, + "App is not present in policies" << policy_app_id); + return result; + } + auto& groups = it->second.groups; + std::copy(groups.begin(), groups.end(), std::back_inserter(result)); + return result; + }; + + auto get_app_rpcs = + [](const std::string group_name, const FunctionalGroupings& groups) + -> rpc::Optional { + auto it = groups.find(group_name); + if (it == groups.end()) { + return rpc::Optional(); + } + return rpc::Optional(it->second); + }; + + const auto snapshot_groups = get_app_groups( + app_policy.first, snapshot_->policy_table.app_policies_section.apps); + const auto update_groups = get_app_groups( + app_policy.first, update_->policy_table.app_policies_section.apps); + + auto get_resulting_encryption_required_flag_for_app_groups = + [this, &get_app_rpcs]( + const rpc::policy_table_interface_base::Strings& app_groups, + const std::shared_ptr pt) { + + for (const auto& group : app_groups) { + const auto rpcs = + get_app_rpcs(group, pt->policy_table.functional_groupings); + if (*rpcs->encryption_required) { + return true; + } + } + + return false; + }; + + auto group_res_en_flag_changed = + [this, &get_resulting_encryption_required_flag_for_app_groups]( + const rpc::policy_table_interface_base::Strings& snapshot_groups, + const rpc::policy_table_interface_base::Strings& update_groups) { + return get_resulting_encryption_required_flag_for_app_groups( + snapshot_groups, snapshot_) != + get_resulting_encryption_required_flag_for_app_groups( + update_groups, update_); + }; + + const auto snapshot_app_encryption_needed = get_app_encryption_needed( + app_policy.first, snapshot_->policy_table.app_policies_section.apps); + const auto update_app_encryption_needed = get_app_encryption_needed( + app_policy.first, update_->policy_table.app_policies_section.apps); + + const bool app_encryption_needed_changed = + (snapshot_app_encryption_needed.is_initialized() != + update_app_encryption_needed.is_initialized()) || + (*snapshot_app_encryption_needed != *update_app_encryption_needed); + + if ((!update_app_encryption_needed.is_initialized() || + *update_app_encryption_needed) && + group_res_en_flag_changed(snapshot_groups, update_groups)) { + return true; + } + + return app_encryption_needed_changed; +} + +void FillActionsForAppPolicies::operator()( + const policy::CheckAppPolicyResults::value_type& value) { + const std::string app_id = value.first; + const auto app_policy = app_policies_.find(app_id); + + if (app_policies_.end() == app_policy) { + return; + } + + if (IsPredefinedApp(*app_policy)) { + return; + } + + switch (value.second) { + case RESULT_APP_REVOKED: + case RESULT_NICKNAME_MISMATCH: + actions_[app_id].is_notify_system = true; + return; + case RESULT_CONSENT_NEEDED: + case RESULT_PERMISSIONS_REVOKED_AND_CONSENT_NEEDED: + actions_[app_id].is_consent_needed = true; + break; + case RESULT_CONSENT_NOT_REQIURED: + case RESULT_PERMISSIONS_REVOKED: + case RESULT_REQUEST_TYPE_CHANGED: + case RESULT_REQUEST_SUBTYPE_CHANGED: + case RESULT_ENCRYPTION_REQUIRED_FLAG_CHANGED: + break; + case RESULT_NO_CHANGES: + default: + return; + } + + actions_[app_id].is_notify_system = true; + actions_[app_id].is_send_permissions_to_app = true; +} + FillNotificationData::FillNotificationData(Permissions& data, GroupConsent group_state, GroupConsent undefined_group_consent) diff --git a/src/components/policy/policy_regular/src/policy_manager_impl.cc b/src/components/policy/policy_regular/src/policy_manager_impl.cc index fee95a7b9f..5cc5ad33c7 100644 --- a/src/components/policy/policy_regular/src/policy_manager_impl.cc +++ b/src/components/policy/policy_regular/src/policy_manager_impl.cc @@ -346,7 +346,8 @@ bool PolicyManagerImpl::LoadPT(const std::string& file, // groups, which had been present before are absent in PTU and will be // removed after update. So in case of revoked groups system has to know // names and ids of revoked groups before they will be removed. - CheckPermissionsChanges(pt_update, policy_table_snapshot); + const auto results = + CheckPermissionsChanges(pt_update, policy_table_snapshot); // Replace current data with updated if (!cache_->ApplyUpdate(*pt_update)) { @@ -357,6 +358,9 @@ bool PolicyManagerImpl::LoadPT(const std::string& file, return false; } + ProcessAppPolicyCheckResults( + results, pt_update->policy_table.app_policies_section.apps); + listener_->OnCertificateUpdated( *(pt_update->policy_table.module_config.certificate)); @@ -387,18 +391,102 @@ bool PolicyManagerImpl::LoadPT(const std::string& file, return true; } -void PolicyManagerImpl::CheckPermissionsChanges( +void PolicyManagerImpl::ProcessAppPolicyCheckResults( + const CheckAppPolicyResults& results, + const rpc::policy_table_interface_base::ApplicationPolicies& app_policies) { + LOG4CXX_AUTO_TRACE(logger_); + + ApplicationsPoliciesActions actions_for_apps_policies; + FillActionsForAppPolicies filler(actions_for_apps_policies, app_policies); + + std::for_each(results.begin(), results.end(), filler); + + ProcessActionsForAppPolicies(actions_for_apps_policies, app_policies); +} + +void PolicyManagerImpl::ProcessActionsForAppPolicies( + const ApplicationsPoliciesActions& actions, + const policy_table::ApplicationPolicies& app_policies) { + ApplicationsPoliciesActions::const_iterator it_actions = actions.begin(); + for (; it_actions != actions.end(); ++it_actions) { + auto app_policy = app_policies.find(it_actions->first); + if (app_policies.end() == app_policy) { + continue; + } + + if (it_actions->second.is_consent_needed) { + // Post-check after ExternalConsent consent changes + const std::string& policy_app_id = app_policy->first; + if (!IsConsentNeeded(policy_app_id)) { + sync_primitives::AutoLock lock(app_permissions_diff_lock_); + + PendingPermissions::iterator app_id_diff = + app_permissions_diff_.find(policy_app_id); + + if (app_permissions_diff_.end() != app_id_diff) { + app_id_diff->second.appPermissionsConsentNeeded = false; + } + } + } + if (it_actions->second.is_notify_system) { + NotifySystem(*app_policy); + } + if (it_actions->second.is_send_permissions_to_app) { + SendPermissionsToApp(*app_policy); + } + } +} + +void PolicyManagerImpl::NotifySystem( + const PolicyManagerImpl::AppPoliciesValueType& app_policy) const { + listener()->OnPendingPermissionChange(app_policy.first); +} + +void PolicyManagerImpl::SendPermissionsToApp( + const PolicyManagerImpl::AppPoliciesValueType& app_policy) { + const std::string app_id = app_policy.first; + + const std::string device_id = GetCurrentDeviceId(app_id); + if (device_id.empty()) { + LOG4CXX_WARN(logger_, + "Couldn't find device info for application id: " << app_id); + return; + } + std::vector group_permissons; + GetPermissionsForApp(device_id, app_id, group_permissons); + + Permissions notification_data; + + // Need to get rid of this call + auto policy_table_snapshot = cache_->GenerateSnapshot(); + + PrepareNotificationData( + policy_table_snapshot->policy_table.functional_groupings, + app_policy.second.groups, + group_permissons, + notification_data); + + std::string default_hmi; + default_hmi = "NONE"; + listener()->OnPermissionsUpdated(app_id, notification_data, default_hmi); +} + +CheckAppPolicyResults PolicyManagerImpl::CheckPermissionsChanges( const std::shared_ptr pt_update, const std::shared_ptr snapshot) { - LOG4CXX_INFO(logger_, "Checking incoming permissions."); + LOG4CXX_AUTO_TRACE(logger_); // Replace predefined policies with its actual setting, e.g. "123":"default" // to actual values of default section UnwrapAppPolicies(pt_update->policy_table.app_policies_section.apps); + CheckAppPolicyResults out_results; + std::for_each(pt_update->policy_table.app_policies_section.apps.begin(), pt_update->policy_table.app_policies_section.apps.end(), - CheckAppPolicy(this, pt_update, snapshot)); + CheckAppPolicy(this, pt_update, snapshot, out_results)); + + return out_results; } void PolicyManagerImpl::PrepareNotificationData( @@ -406,7 +494,7 @@ void PolicyManagerImpl::PrepareNotificationData( const policy_table::Strings& group_names, const std::vector& group_permission, Permissions& notification_data) { - LOG4CXX_INFO(logger_, "Preparing data for notification."); + LOG4CXX_AUTO_TRACE(logger_); ProcessFunctionalGroup processor(groups, group_permission, notification_data); std::for_each(group_names.begin(), group_names.end(), processor); } -- cgit v1.2.1