File: dm_response_validator.h

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (164 lines) | stat: -rw-r--r-- 6,164 bytes parent folder | download | duplicates (3)
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_UPDATER_DEVICE_MANAGEMENT_DM_RESPONSE_VALIDATOR_H_
#define CHROME_UPDATER_DEVICE_MANAGEMENT_DM_RESPONSE_VALIDATOR_H_

#include <algorithm>
#include <string>
#include <vector>

#include "chrome/enterprise_companion/device_management_storage/dm_storage.h"

namespace enterprise_management {

class PolicyData;
class PolicyFetchResponse;

}  // namespace enterprise_management

namespace updater {

struct PolicyValueValidationIssue {
  enum class Severity { kWarning, kError };

  PolicyValueValidationIssue(const std::string& policy_name,
                             Severity severity,
                             const std::string& message);
  ~PolicyValueValidationIssue();

  bool operator==(const PolicyValueValidationIssue& other) const {
    return policy_name == other.policy_name && severity == other.severity &&
           message == other.message;
  }

  std::string policy_name;
  Severity severity = Severity::kWarning;
  std::string message;
};

struct PolicyValidationResult {
  enum class Status {
    // Indicates successful validation.
    kValidationOK,
    // Bad signature on the initial key.
    kValidationBadInitialSignature,
    // Bad signature.
    kValidationBadSignature,
    // Policy blob contains error code.
    kValidationErrorCodePresent,
    // Policy payload failed to decode.
    kValidationPayloadParseError,
    // Unexpected policy type.
    kValidationWrongPolicyType,
    // Unexpected settings entity id.
    kValidationWrongSettingsEntityID,
    // Timestamp is missing or is older than expected.
    kValidationBadTimestamp,
    // DM token is empty or doesn't match.
    kValidationBadDMToken,
    // Device id is empty or doesn't match.
    kValidationBadDeviceID,
    // User id doesn't match.
    kValidationBadUser,
    // Policy payload protobuf parse error.
    kValidationPolicyParseError,
    // Policy key signature could not be verified using the hard-coded
    // verification key.
    kValidationBadKeyVerificationSignature,
    // Policy value validation raised warning(s).
    kValidationValueWarning,
    // Policy value validation failed with error(s).
    kValidationValueError,
  };

  PolicyValidationResult();
  PolicyValidationResult(const PolicyValidationResult& other);
  ~PolicyValidationResult();

  bool HasErrorIssue() const {
    return std::ranges::any_of(issues, [](const auto& issue) {
      return issue.severity == PolicyValueValidationIssue::Severity::kError;
    });
  }

  bool operator==(const PolicyValidationResult& other) const {
    return policy_type == other.policy_type &&
           policy_token == other.policy_token && status == other.status &&
           issues == other.issues;
  }

  std::string policy_type;
  std::string policy_token;

  Status status = Status::kValidationOK;
  std::vector<PolicyValueValidationIssue> issues;
};

class DMResponseValidator {
 public:
  DMResponseValidator(
      const device_management_storage::CachedPolicyInfo& policy_info,
      const std::string& expected_dm_token,
      const std::string& expected_device_id);
  ~DMResponseValidator();

  // Validates a single policy fetch response.
  // The validation steps are sorted in the order of descending severity
  // of the error, that means the most severe check will determine the
  // validation status.
  bool ValidatePolicyResponse(
      const enterprise_management::PolicyFetchResponse& policy_response,
      PolicyValidationResult& validation_result) const;

  // Validates that the policy response data is properly signed.
  bool ValidatePolicyData(
      const enterprise_management::PolicyFetchResponse& policy_response) const;

 private:
  // Extracts and validates the public key for for subsequent policy
  // verification. The public key is either the new key that signed the
  // response, or the existing public key if key is not rotated.
  // Possible scenarios:
  // 1) Client sends the first policy fetch request. In this case, there's no
  //    existing public key on the client side. The server must attach a new
  //    public key in the response and the new key must be signed by the pinned
  //    key.
  // 2) Client sends a policy fetch request with an existing public key, and
  //    server decides to NOT rotate the key. In this case, the response doesn't
  //    have a new key. The signing key will continue to be the existing key.
  // 3) Client sends a policy fetch request with an existing public key, and
  //    server decides to rotate the key. In this case, the server attaches a
  //    new public key in the response. The new key must be signed by the pinned
  //    key AND the existing key.
  //
  // `signature_key` will be the new public key when it is available, otherwise
  // it will be the existing public key from cached policy info.
  bool ValidateNewPublicKey(
      const enterprise_management::PolicyFetchResponse& fetch_response,
      std::string& signature_key,
      PolicyValidationResult& validation_result) const;

  bool ValidateSignature(
      const enterprise_management::PolicyFetchResponse& fetch_response,
      const std::string& signature_key,
      PolicyValidationResult& validation_result) const;
  bool ValidateDMToken(const enterprise_management::PolicyData& policy_data,
                       PolicyValidationResult& validation_result) const;
  bool ValidateDeviceId(const enterprise_management::PolicyData& policy_data,
                        PolicyValidationResult& validation_result) const;
  bool ValidateTimestamp(const enterprise_management::PolicyData& policy_data,
                         PolicyValidationResult& validation_result) const;
  bool ValidatePayloadPolicy(
      const enterprise_management::PolicyData& policy_data,
      PolicyValidationResult& validation_result) const;

  const device_management_storage::CachedPolicyInfo policy_info_;
  const std::string expected_dm_token_;
  const std::string expected_device_id_;
};

}  // namespace updater

#endif  // CHROME_UPDATER_DEVICE_MANAGEMENT_DM_RESPONSE_VALIDATOR_H_