| // Copyright 2020 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl.h" |
| |
| #include <algorithm> |
| #include <iterator> |
| #include <memory> |
| #include <string> |
| #include <utility> |
| |
| #include "base/bind.h" |
| #include "base/containers/contains.h" |
| #include "base/containers/fixed_flat_map.h" |
| #include "base/feature_list.h" |
| #include "base/values.h" |
| #include "chrome/browser/browser_process.h" |
| #include "chrome/browser/chromeos/policy/dlp/data_transfer_dlp_controller.h" |
| #include "chrome/browser/chromeos/policy/dlp/dlp_histogram_helper.h" |
| #include "chrome/browser/chromeos/policy/dlp/dlp_policy_constants.h" |
| #include "chrome/browser/chromeos/policy/dlp/dlp_reporting_manager.h" |
| #include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h" |
| #include "chrome/browser/chromeos/policy/dlp/dlp_scoped_file_access_delegate.h" |
| #include "chrome/common/chrome_features.h" |
| #include "chromeos/dbus/dlp/dlp_client.h" |
| #include "chromeos/dbus/dlp/dlp_service.pb.h" |
| #include "components/policy/core/common/policy_pref_names.h" |
| #include "components/prefs/pref_registry_simple.h" |
| #include "components/prefs/pref_service.h" |
| #include "components/url_matcher/url_util.h" |
| #include "third_party/abseil-cpp/absl/types/optional.h" |
| #include "url/origin.h" |
| |
| namespace policy { |
| |
| namespace { |
| |
| using RuleId = DlpRulesManagerImpl::RuleId; |
| |
| using UrlConditionId = DlpRulesManagerImpl::UrlConditionId; |
| |
| using RulesConditionsMap = std::map<RuleId, UrlConditionId>; |
| |
| constexpr char kWildCardMatching[] = "*"; |
| |
| DlpRulesManager::Restriction GetClassMapping(const std::string& restriction) { |
| static constexpr auto kRestrictionsMap = |
| base::MakeFixedFlatMap<base::StringPiece, DlpRulesManager::Restriction>( |
| {{dlp::kClipboardRestriction, |
| DlpRulesManager::Restriction::kClipboard}, |
| {dlp::kScreenshotRestriction, |
| DlpRulesManager::Restriction::kScreenshot}, |
| {dlp::kPrintingRestriction, DlpRulesManager::Restriction::kPrinting}, |
| {dlp::kPrivacyScreenRestriction, |
| DlpRulesManager::Restriction::kPrivacyScreen}, |
| {dlp::kScreenShareRestriction, |
| DlpRulesManager::Restriction::kScreenShare}, |
| {dlp::kFilesRestriction, DlpRulesManager::Restriction::kFiles}}); |
| |
| auto* it = kRestrictionsMap.find(restriction); |
| return (it == kRestrictionsMap.end()) |
| ? DlpRulesManager::Restriction::kUnknownRestriction |
| : it->second; |
| } |
| |
| DlpRulesManager::Level GetLevelMapping(const std::string& level) { |
| static constexpr auto kLevelsMap = |
| base::MakeFixedFlatMap<base::StringPiece, DlpRulesManager::Level>( |
| {{dlp::kAllowLevel, DlpRulesManager::Level::kAllow}, |
| {dlp::kBlockLevel, DlpRulesManager::Level::kBlock}, |
| {dlp::kWarnLevel, DlpRulesManager::Level::kWarn}, |
| {dlp::kReportLevel, DlpRulesManager::Level::kReport}}); |
| auto* it = kLevelsMap.find(level); |
| return (it == kLevelsMap.end()) ? DlpRulesManager::Level::kNotSet |
| : it->second; |
| } |
| |
| DlpRulesManager::Component GetComponentMapping(const std::string& component) { |
| static constexpr auto kComponentsMap = |
| base::MakeFixedFlatMap<base::StringPiece, DlpRulesManager::Component>( |
| {{dlp::kArc, DlpRulesManager::Component::kArc}, |
| {dlp::kCrostini, DlpRulesManager::Component::kCrostini}, |
| {dlp::kPluginVm, DlpRulesManager::Component::kPluginVm}, |
| {dlp::kDrive, DlpRulesManager::Component::kDrive}, |
| {dlp::kUsb, DlpRulesManager::Component::kUsb}}); |
| |
| auto* it = kComponentsMap.find(component); |
| return (it == kComponentsMap.end()) |
| ? DlpRulesManager::Component::kUnknownComponent |
| : it->second; |
| } |
| |
| // Creates `urls` conditions, saves patterns strings mapping in |
| // `patterns_mapping`, and saves conditions ids to rules ids mapping in `map`. |
| void AddUrlConditions(url_matcher::URLMatcher* matcher, |
| UrlConditionId& condition_id, |
| const base::Value* urls, |
| url_matcher::URLMatcherConditionSet::Vector& conditions, |
| std::map<UrlConditionId, std::string>& patterns_mapping, |
| RuleId rule_id, |
| std::map<UrlConditionId, RuleId>& map) { |
| DCHECK(urls); |
| std::string scheme; |
| std::string host; |
| uint16_t port = 0; |
| std::string path; |
| std::string query; |
| bool match_subdomains = true; |
| for (const auto& list_entry : urls->GetListDeprecated()) { |
| std::string url = list_entry.GetString(); |
| if (!url_matcher::util::FilterToComponents( |
| url, &scheme, &host, &match_subdomains, &port, &path, &query)) { |
| LOG(ERROR) << "Invalid pattern " << url; |
| continue; |
| } |
| auto condition_set = url_matcher::util::CreateConditionSet( |
| matcher, ++condition_id, scheme, host, match_subdomains, port, path, |
| query, /*allow=*/true); |
| |
| conditions.push_back(std::move(condition_set)); |
| map[condition_id] = rule_id; |
| patterns_mapping[condition_id] = url; |
| } |
| } |
| |
| // Matches `url` against `url_matcher` patterns and returns the rules IDs |
| // configured with the matched patterns. |
| RulesConditionsMap MatchUrlAndGetRulesMapping( |
| const GURL& url, |
| const url_matcher::URLMatcher* url_matcher, |
| const std::map<UrlConditionId, RuleId>& rules_map) { |
| DCHECK(url_matcher); |
| const std::set<UrlConditionId> url_conditions_ids = |
| url_matcher->MatchURL(url); |
| |
| RulesConditionsMap rules_conditions_map; |
| for (const auto& id : url_conditions_ids) { |
| rules_conditions_map[rules_map.at(id)] = id; |
| } |
| return rules_conditions_map; |
| } |
| |
| // Returns the maximum level of the rules of given `restriction` joined with |
| // the `selected_rules`. |
| template <typename T> |
| std::pair<DlpRulesManager::Level, absl::optional<T>> GetMaxJoinRestrictionLevel( |
| const DlpRulesManager::Restriction restriction, |
| const std::map<RuleId, T>& selected_rules, |
| const std::map<DlpRulesManager::Restriction, |
| std::map<RuleId, DlpRulesManager::Level>>& restrictions_map, |
| const bool ignore_allow = false) { |
| auto restriction_it = restrictions_map.find(restriction); |
| if (restriction_it == restrictions_map.end()) |
| return std::make_pair(DlpRulesManager::Level::kAllow, absl::nullopt); |
| |
| const std::map<RuleId, DlpRulesManager::Level>& restriction_rules = |
| restriction_it->second; |
| |
| std::pair<DlpRulesManager::Level, absl::optional<T>> max_level = |
| std::make_pair(DlpRulesManager::Level::kNotSet, absl::nullopt); |
| |
| for (const auto& rule_pair : selected_rules) { |
| const auto& restriction_rule_itr = restriction_rules.find(rule_pair.first); |
| if (restriction_rule_itr == restriction_rules.end()) { |
| continue; |
| } |
| if (ignore_allow && |
| restriction_rule_itr->second == DlpRulesManager::Level::kAllow) { |
| continue; |
| } |
| if (restriction_rule_itr->second > max_level.first) { |
| max_level.first = restriction_rule_itr->second; |
| max_level.second = rule_pair.second; |
| } |
| } |
| |
| if (max_level.first == DlpRulesManager::Level::kNotSet) |
| return std::make_pair(DlpRulesManager::Level::kAllow, absl::nullopt); |
| |
| return max_level; |
| } |
| |
| void OnSetDlpFilesPolicy(const ::dlp::SetDlpFilesPolicyResponse response) { |
| if (response.has_error_message()) { |
| DlpScopedFileAccessDelegate::DeleteInstance(); |
| LOG(ERROR) << "Failed to set DLP Files policy and start DLP daemon, error: " |
| << response.error_message(); |
| return; |
| } |
| DCHECK(chromeos::DlpClient::Get()->IsAlive()); |
| DlpScopedFileAccessDelegate::Initialize(chromeos::DlpClient::Get()); |
| } |
| |
| ::dlp::DlpRuleLevel GetLevelProtoEnum(const DlpRulesManager::Level level) { |
| static constexpr auto kLevelsMap = |
| base::MakeFixedFlatMap<DlpRulesManager::Level, ::dlp::DlpRuleLevel>( |
| {{DlpRulesManager::Level::kNotSet, ::dlp::DlpRuleLevel::UNSPECIFIED}, |
| {DlpRulesManager::Level::kReport, ::dlp::DlpRuleLevel::UNSPECIFIED}, |
| {DlpRulesManager::Level::kWarn, ::dlp::DlpRuleLevel::UNSPECIFIED}, |
| {DlpRulesManager::Level::kBlock, ::dlp::DlpRuleLevel::BLOCK}, |
| {DlpRulesManager::Level::kAllow, ::dlp::DlpRuleLevel::ALLOW}}); |
| return kLevelsMap.at(level); |
| } |
| |
| } // namespace |
| |
| DlpRulesManagerImpl::~DlpRulesManagerImpl() { |
| DataTransferDlpController::DeleteInstance(); |
| DlpScopedFileAccessDelegate::DeleteInstance(); |
| } |
| |
| // static |
| void DlpRulesManagerImpl::RegisterPrefs(PrefRegistrySimple* registry) { |
| registry->RegisterBooleanPref(policy_prefs::kDlpReportingEnabled, false); |
| registry->RegisterListPref(policy_prefs::kDlpRulesList); |
| registry->RegisterIntegerPref(policy_prefs::kDlpClipboardCheckSizeLimit, 0); |
| } |
| |
| DlpRulesManager::Level DlpRulesManagerImpl::IsRestricted( |
| const GURL& source, |
| Restriction restriction) const { |
| DCHECK(src_url_matcher_); |
| DCHECK(restriction == Restriction::kPrinting || |
| restriction == Restriction::kPrivacyScreen || |
| restriction == Restriction::kScreenshot || |
| restriction == Restriction::kScreenShare); |
| |
| const RulesConditionsMap src_rules_map = MatchUrlAndGetRulesMapping( |
| source, src_url_matcher_.get(), src_url_rules_mapping_); |
| |
| return GetMaxJoinRestrictionLevel(restriction, src_rules_map, |
| restrictions_map_) |
| .first; |
| } |
| |
| DlpRulesManager::Level DlpRulesManagerImpl::IsRestrictedByAnyRule( |
| const GURL& source, |
| Restriction restriction) const { |
| DCHECK(src_url_matcher_); |
| |
| const RulesConditionsMap src_rules_map = MatchUrlAndGetRulesMapping( |
| source, src_url_matcher_.get(), src_url_rules_mapping_); |
| |
| return GetMaxJoinRestrictionLevel(restriction, src_rules_map, |
| restrictions_map_, /*ignore_allow=*/true) |
| .first; |
| } |
| |
| DlpRulesManager::Level DlpRulesManagerImpl::IsRestrictedDestination( |
| const GURL& source, |
| const GURL& destination, |
| Restriction restriction, |
| std::string* out_source_pattern, |
| std::string* out_destination_pattern) const { |
| DCHECK(src_url_matcher_); |
| DCHECK(dst_url_matcher_); |
| DCHECK(restriction == Restriction::kClipboard || |
| restriction == Restriction::kFiles); |
| |
| // Allow copy/paste within the same document. |
| if (url::IsSameOriginWith(source, destination)) |
| return Level::kAllow; |
| |
| const RulesConditionsMap src_rules_map = MatchUrlAndGetRulesMapping( |
| source, src_url_matcher_.get(), src_url_rules_mapping_); |
| |
| const RulesConditionsMap dst_rules_map = MatchUrlAndGetRulesMapping( |
| destination, dst_url_matcher_.get(), dst_url_rules_mapping_); |
| |
| std::map<DlpRulesManagerImpl::RuleId, |
| std::pair<DlpRulesManagerImpl::UrlConditionId, |
| DlpRulesManagerImpl::UrlConditionId>> |
| intersection_rules; |
| auto src_map_itr = src_rules_map.begin(); |
| auto dst_map_itr = dst_rules_map.begin(); |
| while (src_map_itr != src_rules_map.end() && |
| dst_map_itr != dst_rules_map.end()) { |
| if (src_map_itr->first < dst_map_itr->first) { |
| ++src_map_itr; |
| } else if (dst_map_itr->first < src_map_itr->first) { |
| ++dst_map_itr; |
| } else { |
| intersection_rules.insert(std::make_pair( |
| src_map_itr->first, |
| std::make_pair(src_map_itr->second, dst_map_itr->second))); |
| ++src_map_itr; |
| ++dst_map_itr; |
| } |
| } |
| |
| std::pair<Level, absl::optional<std::pair<UrlConditionId, UrlConditionId>>> |
| level_urls_pair = GetMaxJoinRestrictionLevel( |
| restriction, intersection_rules, restrictions_map_); |
| if (level_urls_pair.second.has_value() && out_source_pattern && |
| out_destination_pattern) { |
| UrlConditionId src_condition_id = level_urls_pair.second.value().first; |
| UrlConditionId dst_condition_id = level_urls_pair.second.value().second; |
| if (out_source_pattern) |
| *out_source_pattern = src_pattterns_mapping_.at(src_condition_id); |
| if (out_destination_pattern) |
| *out_destination_pattern = dst_pattterns_mapping_.at(dst_condition_id); |
| } |
| return level_urls_pair.first; |
| } |
| |
| DlpRulesManager::Level DlpRulesManagerImpl::IsRestrictedComponent( |
| const GURL& source, |
| const Component& destination, |
| Restriction restriction, |
| std::string* out_source_pattern) const { |
| DCHECK(src_url_matcher_); |
| DCHECK(restriction == Restriction::kClipboard || |
| restriction == Restriction::kFiles); |
| |
| const RulesConditionsMap src_rules_map = MatchUrlAndGetRulesMapping( |
| source, src_url_matcher_.get(), src_url_rules_mapping_); |
| |
| auto it = components_rules_.find(destination); |
| if (it == components_rules_.end()) |
| return Level::kAllow; |
| |
| const std::set<RuleId>& component_rules_ids = it->second; |
| |
| RulesConditionsMap intersection_rules; |
| auto src_map_itr = src_rules_map.begin(); |
| auto component_rules_itr = component_rules_ids.begin(); |
| while (src_map_itr != src_rules_map.end() && |
| component_rules_itr != component_rules_ids.end()) { |
| if (src_map_itr->first < *component_rules_itr) { |
| ++src_map_itr; |
| } else if (*component_rules_itr < src_map_itr->first) { |
| ++component_rules_itr; |
| } else { |
| intersection_rules.insert(*src_map_itr); |
| ++src_map_itr; |
| ++component_rules_itr; |
| } |
| } |
| |
| std::pair<Level, absl::optional<UrlConditionId>> level_url_pair = |
| GetMaxJoinRestrictionLevel(restriction, intersection_rules, |
| restrictions_map_); |
| if (level_url_pair.second.has_value() && out_source_pattern) { |
| UrlConditionId src_condition_id = level_url_pair.second.value(); |
| *out_source_pattern = src_pattterns_mapping_.at(src_condition_id); |
| } |
| return level_url_pair.first; |
| } |
| |
| DlpRulesManager::AggregatedDestinations |
| DlpRulesManagerImpl::GetAggregatedDestinations(const GURL& source, |
| Restriction restriction) const { |
| DCHECK(src_url_matcher_); |
| DCHECK(dst_url_matcher_); |
| DCHECK(restriction == Restriction::kClipboard || |
| restriction == Restriction::kFiles); |
| |
| auto restriction_it = restrictions_map_.find(restriction); |
| if (restriction_it == restrictions_map_.end()) { |
| return std::map<Level, std::set<std::string>>(); |
| } |
| const std::map<RuleId, DlpRulesManager::Level>& restriction_rules = |
| restriction_it->second; |
| |
| const RulesConditionsMap src_rules_map = MatchUrlAndGetRulesMapping( |
| source, src_url_matcher_.get(), src_url_rules_mapping_); |
| // We need to check all possible destinations for rules that apply to it and |
| // to the `source`. There can be many matching rules, but we want to keep only |
| // the highest enforced level for each destination. |
| std::map<std::string, Level> destination_level_map; |
| for (auto dst_map_itr : dst_url_rules_mapping_) { |
| auto src_map_itr = src_rules_map.find(dst_map_itr.second); |
| if (src_map_itr == src_rules_map.end()) { |
| continue; |
| } |
| const auto& restriction_rule_itr = |
| restriction_rules.find(src_map_itr->first); |
| if (restriction_rule_itr == restriction_rules.end()) { |
| continue; |
| } |
| UrlConditionId dst_condition_id = dst_map_itr.first; |
| std::string destination_pattern = |
| dst_pattterns_mapping_.at(dst_condition_id); |
| Level level = restriction_rule_itr->second; |
| auto it = destination_level_map.find(destination_pattern); |
| if (it == destination_level_map.end() || level > it->second) { |
| destination_level_map[destination_pattern] = restriction_rule_itr->second; |
| } |
| } |
| |
| std::map<Level, std::set<std::string>> result; |
| for (auto it : destination_level_map) { |
| if (it.first == kWildCardMatching) { |
| result[it.second] = {it.first}; |
| } else if (result[it.second].find(kWildCardMatching) == |
| result[it.second].end()) { |
| result[it.second].insert(it.first); |
| } |
| } |
| return result; |
| } |
| |
| DlpRulesManager::AggregatedComponents |
| DlpRulesManagerImpl::GetAggregatedComponents(const GURL& source, |
| Restriction restriction) const { |
| DCHECK(src_url_matcher_); |
| DCHECK(restriction == Restriction::kClipboard || |
| restriction == Restriction::kFiles); |
| |
| std::map<Level, std::set<Component>> result; |
| for (Component component : components) { |
| std::string out_source_pattern; |
| Level level = IsRestrictedComponent(source, component, restriction, |
| &out_source_pattern); |
| result[level].insert(component); |
| } |
| |
| return result; |
| } |
| |
| DlpRulesManagerImpl::DlpRulesManagerImpl(PrefService* local_state) { |
| pref_change_registrar_.Init(local_state); |
| pref_change_registrar_.Add( |
| policy_prefs::kDlpRulesList, |
| base::BindRepeating(&DlpRulesManagerImpl::OnPolicyUpdate, |
| base::Unretained(this))); |
| OnPolicyUpdate(); |
| |
| if (!IsReportingEnabled()) |
| return; |
| reporting_manager_ = std::make_unique<DlpReportingManager>(); |
| } |
| |
| bool DlpRulesManagerImpl::IsReportingEnabled() const { |
| return g_browser_process->local_state()->GetBoolean( |
| policy_prefs::kDlpReportingEnabled); |
| } |
| |
| DlpReportingManager* DlpRulesManagerImpl::GetReportingManager() const { |
| return reporting_manager_.get(); |
| } |
| |
| std::string DlpRulesManagerImpl::GetSourceUrlPattern(const GURL& source_url, |
| Restriction restriction, |
| Level level) const { |
| const std::set<UrlConditionId> url_conditions_ids = |
| src_url_matcher_->MatchURL(source_url); |
| |
| std::map<RuleId, UrlConditionId> rules_conditions_map; |
| for (const auto& condition_id : url_conditions_ids) { |
| rules_conditions_map.insert( |
| std::make_pair(src_url_rules_mapping_.at(condition_id), condition_id)); |
| } |
| auto restriction_itr = restrictions_map_.find(restriction); |
| if (restriction_itr == restrictions_map_.end()) |
| return std::string(); |
| |
| const auto rules_levels_map = restriction_itr->second; |
| for (const auto& rule_level_entry : rules_levels_map) { |
| auto rule_id = rule_level_entry.first; |
| auto lvl = rule_level_entry.second; |
| auto rule_condition_itr = rules_conditions_map.find(rule_id); |
| if (lvl == level && rule_condition_itr != rules_conditions_map.end()) { |
| auto condition_id = rule_condition_itr->second; |
| auto condition_pattern_itr = src_pattterns_mapping_.find(condition_id); |
| if (condition_pattern_itr != src_pattterns_mapping_.end()) |
| return condition_pattern_itr->second; |
| } |
| } |
| return std::string(); |
| } |
| |
| size_t DlpRulesManagerImpl::GetClipboardCheckSizeLimitInBytes() const { |
| return pref_change_registrar_.prefs()->GetInteger( |
| policy_prefs::kDlpClipboardCheckSizeLimit); |
| } |
| |
| bool DlpRulesManagerImpl::IsFilesPolicyEnabled() const { |
| return base::FeatureList::IsEnabled( |
| features::kDataLeakPreventionFilesRestriction) && |
| base::Contains(restrictions_map_, |
| DlpRulesManager::Restriction::kFiles) && |
| chromeos::DlpClient::Get() && chromeos::DlpClient::Get()->IsAlive(); |
| } |
| |
| void DlpRulesManagerImpl::OnPolicyUpdate() { |
| components_rules_.clear(); |
| restrictions_map_.clear(); |
| src_url_rules_mapping_.clear(); |
| dst_url_rules_mapping_.clear(); |
| src_url_matcher_ = std::make_unique<url_matcher::URLMatcher>(); |
| dst_url_matcher_ = std::make_unique<url_matcher::URLMatcher>(); |
| src_pattterns_mapping_.clear(); |
| dst_pattterns_mapping_.clear(); |
| src_conditions_.clear(); |
| dst_conditions_.clear(); |
| |
| if (!base::FeatureList::IsEnabled(features::kDataLeakPreventionPolicy)) { |
| return; |
| } |
| |
| const base::Value::List& rules_list = |
| g_browser_process->local_state()->GetValueList( |
| policy_prefs::kDlpRulesList); |
| |
| DlpBooleanHistogram(dlp::kDlpPolicyPresentUMA, !rules_list.empty()); |
| if (rules_list.empty()) { |
| DataTransferDlpController::DeleteInstance(); |
| return; |
| } |
| |
| RuleId rules_counter = 0; |
| UrlConditionId src_url_condition_id = 0; |
| UrlConditionId dst_url_condition_id = 0; |
| |
| // Constructing request to send the policy to DLP Files daemon. |
| ::dlp::SetDlpFilesPolicyRequest request_to_daemon; |
| |
| for (const base::Value& rule : rules_list) { |
| DCHECK(rule.is_dict()); |
| const auto* sources = rule.FindDictKey("sources"); |
| DCHECK(sources); |
| const auto* sources_urls = sources->FindListKey("urls"); |
| DCHECK(sources_urls); // This DCHECK should be removed when other types are |
| // supported as sources. |
| |
| AddUrlConditions(src_url_matcher_.get(), src_url_condition_id, sources_urls, |
| src_conditions_, src_pattterns_mapping_, rules_counter, |
| src_url_rules_mapping_); |
| |
| const auto* destinations = rule.FindDictKey("destinations"); |
| const auto* destinations_urls = |
| destinations ? destinations->FindListKey("urls") : nullptr; |
| if (destinations_urls) { |
| AddUrlConditions(dst_url_matcher_.get(), dst_url_condition_id, |
| destinations_urls, dst_conditions_, |
| dst_pattterns_mapping_, rules_counter, |
| dst_url_rules_mapping_); |
| } |
| const auto* destinations_components = |
| destinations ? destinations->FindListKey("components") : nullptr; |
| if (destinations_components) { |
| for (const auto& component : |
| destinations_components->GetListDeprecated()) { |
| DCHECK(component.is_string()); |
| components_rules_[GetComponentMapping(component.GetString())].insert( |
| rules_counter); |
| } |
| } |
| |
| const auto* restrictions = rule.FindListKey("restrictions"); |
| DCHECK(restrictions); |
| for (const auto& restriction : restrictions->GetListDeprecated()) { |
| const auto* rule_class_str = restriction.FindStringKey("class"); |
| DCHECK(rule_class_str); |
| const auto* rule_level_str = restriction.FindStringKey("level"); |
| DCHECK(rule_level_str); |
| |
| const Restriction rule_restriction = GetClassMapping(*rule_class_str); |
| if (rule_restriction == Restriction::kUnknownRestriction) |
| continue; |
| |
| Level rule_level = GetLevelMapping(*rule_level_str); |
| if (rule_level == Level::kNotSet) |
| continue; |
| |
| bool rule_has_destinations = |
| destinations_urls && !destinations_urls->GetList().empty(); |
| bool rule_has_components = destinations_components && |
| !destinations_components->GetList().empty(); |
| |
| // TODO(crbug.com/1172959): Implement Warn level for Files. |
| if (rule_restriction == Restriction::kFiles && |
| (rule_has_destinations || rule_has_components) && |
| rule_level != Level::kWarn) { |
| ::dlp::DlpFilesRule files_rule; |
| for (const auto& url : sources_urls->GetList()) { |
| DCHECK(url.is_string()); |
| files_rule.add_source_urls(url.GetString()); |
| } |
| for (const auto& url : destinations_urls->GetList()) { |
| DCHECK(url.is_string()); |
| files_rule.add_destination_urls(url.GetString()); |
| } |
| // TODO(crbug.com/1321088): Add components to SetDlpFilesPolicyRequest. |
| |
| files_rule.set_level(GetLevelProtoEnum(rule_level)); |
| request_to_daemon.mutable_rules()->Add(std::move(files_rule)); |
| } |
| |
| DlpRestrictionConfiguredHistogram(rule_restriction); |
| restrictions_map_[rule_restriction].emplace(rules_counter, rule_level); |
| } |
| ++rules_counter; |
| } |
| |
| src_url_matcher_->AddConditionSets(src_conditions_); |
| dst_url_matcher_->AddConditionSets(dst_conditions_); |
| |
| if (base::Contains(restrictions_map_, Restriction::kClipboard)) { |
| DataTransferDlpController::Init(*this); |
| } else { |
| DataTransferDlpController::DeleteInstance(); |
| } |
| |
| // TODO(crbug.com/1174501) Shutdown the daemon when restrictions are empty. |
| if (request_to_daemon.rules_size() > 0 && |
| base::FeatureList::IsEnabled( |
| features::kDataLeakPreventionFilesRestriction)) { |
| DlpBooleanHistogram(dlp::kFilesDaemonStartedUMA, true); |
| chromeos::DlpClient::Get()->SetDlpFilesPolicy( |
| request_to_daemon, base::BindOnce(&OnSetDlpFilesPolicy)); |
| } else { |
| DlpScopedFileAccessDelegate::DeleteInstance(); |
| } |
| } |
| |
| } // namespace policy |