File: deep_scanning_request.h

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 (306 lines) | stat: -rw-r--r-- 13,561 bytes parent folder | download | duplicates (5)
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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
// 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.

#ifndef CHROME_BROWSER_SAFE_BROWSING_DOWNLOAD_PROTECTION_DEEP_SCANNING_REQUEST_H_
#define CHROME_BROWSER_SAFE_BROWSING_DOWNLOAD_PROTECTION_DEEP_SCANNING_REQUEST_H_

#include <memory>

#include "base/callback_list.h"
#include "base/containers/flat_map.h"
#include "base/files/file_path.h"
#include "base/memory/raw_ptr.h"
#include "base/observer_list.h"
#include "base/time/time.h"
#include "base/types/optional_ref.h"
#include "chrome/browser/download/download_item_warning_data.h"
#include "chrome/browser/enterprise/connectors/analysis/content_analysis_info.h"
#include "chrome/browser/enterprise/connectors/common.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.h"
#include "chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_utils.h"
#include "chrome/browser/safe_browsing/cloud_content_scanning/file_analysis_request.h"
#include "chrome/browser/safe_browsing/cloud_content_scanning/file_opening_job.h"
#include "chrome/browser/safe_browsing/download_protection/deep_scanning_metadata.h"
#include "chrome/browser/safe_browsing/download_protection/download_protection_util.h"
#include "components/enterprise/common/proto/connectors.pb.h"
#include "components/enterprise/obfuscation/core/download_obfuscator.h"
#include "components/safe_browsing/core/common/proto/csd.pb.h"

namespace download {
class DownloadItem;
}

namespace safe_browsing {

class DownloadProtectionService;
class DownloadRequestMaker;

// This class encapsulates the process of uploading a file to Safe Browsing for
// deep scanning and reporting the result.
// Deep scanning is not supported on Android.
class DeepScanningRequest : public download::DownloadItem::Observer,
                            public enterprise_connectors::ContentAnalysisInfo {
 public:
  // Enum representing the type of constructor that initiated scanning.
  // These values are persisted to logs. Entries should not be renumbered and
  // numeric values should never be reused.
  enum class DeepScanType {
    // Scanning was initiated by a normal download from a web page.
    NORMAL = 0,

    // Scanning was initiated by a save package being saved on disk.
    SAVE_PACKAGE = 1,

    kMaxValue = SAVE_PACKAGE,
  };

  class Observer : public base::CheckedObserver {
   public:
    ~Observer() override = default;

    // Called when the DeepScanningRequest finishes.
    virtual void OnFinish(DeepScanningRequest* request) {}
  };

  // Checks the current policies to determine whether files must be uploaded by
  // policy. Returns the settings to apply to this analysis if it should happen
  // or std::nullopt if no analysis should happen.
  static std::optional<enterprise_connectors::AnalysisSettings>
  ShouldUploadBinary(const DeepScanningMetadata& metadata);

  // Scan the given `metadata item`, with the given `trigger`. The result of the
  // scanning will be provided through `callback`. Take a references to the
  // owning `download_service`.
  DeepScanningRequest(std::unique_ptr<DeepScanningMetadata> metadata,
                      DownloadItemWarningData::DeepScanTrigger trigger,
                      DownloadCheckResult pre_scan_download_check_result,
                      CheckDownloadRepeatingCallback callback,
                      DownloadProtectionService* download_service,
                      enterprise_connectors::AnalysisSettings settings,
                      base::optional_ref<const std::string> password);

  // Scan the given `metadata item` that corresponds to a save package, with
  // `save_package_page` mapping every currently on-disk file part of that
  // package to their final target path. The result of the scanning is provided
  // through `callback` once every file has been scanned, and the given result
  // is the highest severity one. Takes a reference to the owning
  // `download_service`.
  DeepScanningRequest(
      std::unique_ptr<DeepScanningMetadata> metadata,
      DownloadCheckResult pre_scan_download_check_result,
      CheckDownloadRepeatingCallback callback,
      DownloadProtectionService* download_service,
      enterprise_connectors::AnalysisSettings settings,
      base::flat_map<base::FilePath, base::FilePath> save_package_files);

  ~DeepScanningRequest() override;

  // Begin the deep scanning request. This must be called on the UI thread.
  void Start();

  void AddObserver(Observer* observer);
  void RemoveObserver(Observer* observer);

  // download::DownloadItem::Observer:
  void OnDownloadUpdated(download::DownloadItem* download) override;
  void OnDownloadDestroyed(download::DownloadItem* download) override;

  // enterprise_connectors::ContentAnalysisInfo:
  const enterprise_connectors::AnalysisSettings& settings() const override;
  signin::IdentityManager* identity_manager() const override;
  int user_action_requests_count() const override;
  std::string tab_title() const override;
  std::string user_action_id() const override;
  std::string email() const override;
  std::string url() const override;
  const GURL& tab_url() const override;
  enterprise_connectors::ContentAnalysisRequest::Reason reason() const override;
  google::protobuf::RepeatedPtrField<::safe_browsing::ReferrerChainEntry>
  referrer_chain() const override;
  google::protobuf::RepeatedPtrField<std::string> frame_url_chain()
      const override;

 private:
  // Starts the deep scanning request when there is a one-to-one mapping from
  // the download item to a file.
  void StartSingleFileScan();

  // Starts the deep scanning requests when there is a one-to-many mapping from
  // the download item to multiple files being scanned as a part of a save
  // package.
  void StartSavePackageScan();

  // Callback when the |download_request_maker_| is finished assembling the
  // download metadata request.
  void OnDownloadRequestReady(
      const base::FilePath& current_path,
      std::unique_ptr<FileAnalysisRequest> deep_scan_request,
      std::unique_ptr<ClientDownloadRequest> download_request);

  // Callbacks for when |binary_upload_service_| finishes uploading.
  void OnScanComplete(const base::FilePath& current_path,
                      BinaryUploadService::Result result,
                      enterprise_connectors::ContentAnalysisResponse response);
  void OnConsumerScanComplete(
      const base::FilePath& current_path,
      BinaryUploadService::Result result,
      enterprise_connectors::ContentAnalysisResponse response);
  void OnEnterpriseScanComplete(
      const base::FilePath& current_path,
      BinaryUploadService::Result result,
      enterprise_connectors::ContentAnalysisResponse response);

  // Called when a single file scanning request has completed. Calls
  // FinishRequest if it was the last required one.
  void MaybeFinishRequest(DownloadCheckResult result);

  // Finishes the request, providing the result through |callback_| and
  // notifying |download_service_|.
  void FinishRequest(DownloadCheckResult result);

  // Called to verify if `result` is considered as a failure and the scan should
  // end early.
  bool ShouldTerminateEarly(BinaryUploadService::Result result);

  // Called to open the download. This is triggered by the timeout modal dialog.
  void OpenDownload();

  // Populates a request's proto fields with the appropriate data.
  void PopulateRequest(FileAnalysisRequest* request,
                       Profile* profile,
                       const base::FilePath& path);

  // Creates a ClientDownloadRequest asynchronously to attach to
  // `deep_scan_request`. Once it is obtained, OnDownloadRequestReady is called
  // to upload the request for deep scanning.
  void PrepareClientDownloadRequest(
      const base::FilePath& current_path,
      std::unique_ptr<FileAnalysisRequest> deep_scan_request);

  // Callback invoked in `StartSingleFileScan` to check if `data` has been
  // successfully fetched and ready for deep scanning if needed.
  void OnGetFileRequestData(const base::FilePath& file_path,
                            std::unique_ptr<FileAnalysisRequest> request,
                            BinaryUploadService::Result result,
                            BinaryUploadService::Request::Data data);

  // Callback invoked in `StartSavePackageScan` to check if `data` of a file in
  // package has been successfully fetched and ready for deep scanning if
  // needed.
  void OnGetPackageFileRequestData(const base::FilePath& final_path,
                                   const base::FilePath& current_path,
                                   std::unique_ptr<FileAnalysisRequest> request,
                                   BinaryUploadService::Result result,
                                   BinaryUploadService::Request::Data data);

  // Helper function to simplify checking if the report-only feature is set in
  // conjunction with the corresponding policy value.
  bool ReportOnlyScan();

  // Acknowledge the request's handling to the service provider.
  void AcknowledgeRequest(enterprise_connectors::EventResult event_result);

  bool IsEnterpriseTriggered() const;
  bool IsConsumerTriggered() const;

  // Callback for when deobfuscation of the file is completed.
  void OnDeobfuscationComplete(
      DownloadCheckResult download_result,
      base::expected<void, enterprise_obfuscation::Error> result);

  // Provides scan result to `callback_` and clean up.
  void CallbackAndCleanup(DownloadCheckResult result);

  // Metadata for the item being scanned. This is owned by `DeepScanningRequest`
  // and provides an abstraction layer over different types of scan sources
  // (download items, file system access writes).
  std::unique_ptr<DeepScanningMetadata> metadata_;

  // ScopedObservation to manage `DownloadItem` observation lifetime. Must be
  // cleared before `metadata_` is.
  std::unique_ptr<DeepScanningMetadata::DownloadScopedObservation>
      download_observation_;

  // The reason for deep scanning.
  DownloadItemWarningData::DeepScanTrigger trigger_;

  // The callback to provide the scan result to.
  CheckDownloadRepeatingCallback callback_;

  // The download protection service that initiated this upload. The
  // |download_service_| owns this class.
  raw_ptr<DownloadProtectionService> download_service_;

  // The time when uploading starts. Keyed with the file's current path.
  base::flat_map<base::FilePath, base::TimeTicks> upload_start_times_;

  // The settings to apply to this scan.
  enterprise_connectors::AnalysisSettings analysis_settings_;

  // Used to assemble the download metadata.
  std::unique_ptr<DownloadRequestMaker> download_request_maker_;

  // This list of observers of this request.
  base::ObserverList<Observer> observers_;

  // Stores a mapping of temporary paths to final paths for save package files.
  // This is empty on non-page save scanning requests.
  base::flat_map<base::FilePath, base::FilePath> save_package_files_;

  // Stores a mapping of a file's current path to its metadata so it can be used
  // in reporting events. This is populated from opening the file for save
  // package scans, or populated from `item_` for single file scans.
  base::flat_map<base::FilePath, enterprise_connectors::FileMetadata>
      file_metadata_;

  // Owner of the FileOpeningJob used to safely open multiple files in parallel
  // for save package scans. Always nullptr for non-save package scans.
  std::unique_ptr<FileOpeningJob> file_opening_job_;

  // The total number of files beings scanned for which OnScanComplete hasn't
  // been called. Once this is 0, FinishRequest should be called and `this`
  // should be destroyed.
  size_t pending_scan_requests_;

  // The highest precedence DownloadCheckResult obtained from scanning verdicts.
  // This should be updated when a scan completes.
  DownloadCheckResult download_check_result_ =
      DownloadCheckResult::DEEP_SCANNED_SAFE;

  // Cached SB result for the download to be used if deep scanning fails.
  DownloadCheckResult pre_scan_download_check_result_;

  // Cached danger type for the download to be used by reporting in case
  // scanning is skipped for any reason.
  download::DownloadDangerType pre_scan_danger_type_;

  // Set to true when StartSingleFileScan or StartSavePackageScan is called and
  // that scanning has started. This is used so that calls to OnDownloadUpdated
  // only ever start the scanning process once.
  bool scanning_started_ = false;

  // Cached callbacks to report scanning results until the final `event_result_`
  // is known. The callbacks in this list should be called in FinishRequest.
  base::OnceCallbackList<void(enterprise_connectors::EventResult result)>
      report_callbacks_;

  // The request tokens of all the requests that make up the user action
  // represented by this ContentAnalysisDelegate instance.
  std::vector<std::string> request_tokens_;

  // Password for the file, if it's an archive.
  std::optional<std::string> password_;

  // Reason the scanning took place. Used to populate enterprise requests to
  // give more context on what user action lead to a scan.
  enterprise_connectors::ContentAnalysisRequest::Reason reason_ =
      enterprise_connectors::ContentAnalysisRequest::UNKNOWN;

  base::WeakPtrFactory<DeepScanningRequest> weak_ptr_factory_;
};

}  // namespace safe_browsing

#endif  // CHROME_BROWSER_SAFE_BROWSING_DOWNLOAD_PROTECTION_DEEP_SCANNING_REQUEST_H_