File: auto_launch_protocols_policy_handler.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (141 lines) | stat: -rw-r--r-- 5,138 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/external_protocol/auto_launch_protocols_policy_handler.h"

#include <memory>
#include <string>
#include <string_view>
#include <utility>

#include "base/strings/string_util.h"
#include "base/values.h"
#include "chrome/browser/external_protocol/constants.h"
#include "chrome/common/pref_names.h"
#include "components/policy/core/browser/policy_error_map.h"
#include "components/policy/core/common/policy_map.h"
#include "components/policy/core/common/policy_pref_names.h"
#include "components/policy/core/common/schema.h"
#include "components/policy/policy_constants.h"
#include "components/prefs/pref_value_map.h"
#include "components/strings/grit/components_strings.h"
#include "url/gurl.h"

namespace policy {

namespace {
const char kValidProtocolChars[] =
    "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+-.";

bool IsValidProtocol(std::string_view protocol) {
  // RFC3986: ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
  if (protocol.empty())
    return false;
  if (!base::IsAsciiAlpha(protocol.front()))
    return false;
  if (protocol.length() > 1 &&
      !base::ContainsOnlyChars(protocol, kValidProtocolChars)) {
    return false;
  }
  return true;
}

// Catches obvious errors like including a [/path] or [@query] element in the
// pattern.
bool IsValidOriginMatchingPattern(std::string_view origin_pattern) {
  GURL gurl(origin_pattern);
  if (gurl.has_path() && gurl.path_piece() != "/")
    return false;
  if (gurl.has_query())
    return false;
  return true;
}

}  // namespace

AutoLaunchProtocolsPolicyHandler::AutoLaunchProtocolsPolicyHandler(
    const policy::Schema& chrome_schema)
    : SchemaValidatingPolicyHandler(
          policy::key::kAutoLaunchProtocolsFromOrigins,
          chrome_schema.GetKnownProperty(
              policy::key::kAutoLaunchProtocolsFromOrigins),
          policy::SCHEMA_ALLOW_UNKNOWN) {}

AutoLaunchProtocolsPolicyHandler::~AutoLaunchProtocolsPolicyHandler() = default;

bool AutoLaunchProtocolsPolicyHandler::CheckPolicySettings(
    const PolicyMap& policies,
    PolicyErrorMap* errors) {
  std::unique_ptr<base::Value> policy_value;
  if (!CheckAndGetValue(policies, nullptr, &policy_value) || !policy_value)
    return false;

  base::Value::List& policy_list = policy_value->GetList();
  for (size_t i = 0; i < policy_list.size(); ++i) {
    const base::Value::Dict& protocol_origins_map = policy_list[i].GetDict();

    // If the protocol is invalid mark it as an error.
    const std::string* protocol = protocol_origins_map.FindString(
        policy::external_protocol::kProtocolNameKey);
    DCHECK(protocol);
    if (!IsValidProtocol(*protocol)) {
      errors->AddError(policy::key::kAutoLaunchProtocolsFromOrigins,
                       IDS_POLICY_INVALID_PROTOCOL_ERROR, PolicyErrorPath{i});
    }

    const base::Value::List* origins_list = protocol_origins_map.FindList(
        policy::external_protocol::kOriginListKey);
    for (const auto& entry : *origins_list) {
      const std::string pattern = entry.GetString();
      // If it's not a valid origin pattern mark it as an error.
      if (!IsValidOriginMatchingPattern(pattern)) {
        errors->AddError(policy::key::kAutoLaunchProtocolsFromOrigins,
                         IDS_POLICY_INVALID_ORIGIN_ERROR, PolicyErrorPath{i});
      }
    }
    // If the origin list is empty mark it as an error.
    if (origins_list->empty()) {
      errors->AddError(policy::key::kAutoLaunchProtocolsFromOrigins,
                       IDS_POLICY_EMPTY_ORIGIN_LIST_ERROR, PolicyErrorPath{i});
    }
  }

  // Always continue to ApplyPolicySettings which can remove invalid values and
  // apply the valid ones.
  return true;
}

void AutoLaunchProtocolsPolicyHandler::ApplyPolicySettings(
    const PolicyMap& policies,
    PrefValueMap* prefs) {
  std::unique_ptr<base::Value> policy_value;
  CheckAndGetValue(policies, nullptr, &policy_value);

  base::Value::List validated_pref_values;
  for (auto& protocol_origins_map : policy_value->GetList()) {
    // If the protocol is invalid skip the entry.
    base::Value::Dict& protocol_origins_dict = protocol_origins_map.GetDict();
    const std::string* protocol = protocol_origins_dict.FindString(
        policy::external_protocol::kProtocolNameKey);
    DCHECK(protocol);
    if (!IsValidProtocol(*protocol))
      continue;

    // Remove invalid patterns from the list.
    base::Value::List* origin_patterns_list = protocol_origins_dict.FindList(
        policy::external_protocol::kOriginListKey);
    origin_patterns_list->EraseIf([](const base::Value& pattern) {
      return !IsValidOriginMatchingPattern(pattern.GetString());
    });
    // If the origin list is empty skip the entry.
    if (origin_patterns_list->size() == 0)
      continue;

    validated_pref_values.Append(protocol_origins_dict.Clone());
  }
  prefs->SetValue(prefs::kAutoLaunchProtocolsFromOrigins,
                  base::Value(std::move(validated_pref_values)));
}

}  // namespace policy