File: url_loader_network_service_observer.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 (237 lines) | stat: -rw-r--r-- 8,948 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
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "remoting/base/url_loader_network_service_observer.h"

#include "base/functional/bind.h"
#include "base/logging.h"
#include "base/memory/weak_ptr.h"
#include "base/task/single_thread_task_runner.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "net/base/net_errors.h"
#include "net/ssl/client_cert_store.h"
#include "net/ssl/ssl_cert_request_info.h"
#include "net/ssl/ssl_private_key.h"
#include "net/url_request/url_request.h"
#include "remoting/base/certificate_helpers.h"
#include "remoting/base/logging.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "services/network/public/mojom/shared_storage.mojom.h"
#include "url/gurl.h"

namespace remoting {

namespace {

constexpr char kCertIssuerWildCard[] = "*";

class SSLPrivateKeyWrapper : public network::mojom::SSLPrivateKey {
 public:
  explicit SSLPrivateKeyWrapper(
      scoped_refptr<net::SSLPrivateKey> ssl_private_key)
      : ssl_private_key_(std::move(ssl_private_key)) {}

  SSLPrivateKeyWrapper(const SSLPrivateKeyWrapper&) = delete;
  SSLPrivateKeyWrapper& operator=(const SSLPrivateKeyWrapper&) = delete;

  ~SSLPrivateKeyWrapper() override = default;

  // network::mojom::SSLPrivateKey implementation.
  void Sign(uint16_t algorithm,
            const std::vector<uint8_t>& input,
            network::mojom::SSLPrivateKey::SignCallback callback) override {
    base::span<const uint8_t> input_span(input);
    ssl_private_key_->Sign(
        algorithm, input_span,
        base::BindOnce(&SSLPrivateKeyWrapper::Callback,
                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
  }

 private:
  void Callback(network::mojom::SSLPrivateKey::SignCallback callback,
                net::Error net_error,
                const std::vector<uint8_t>& signature) {
    std::move(callback).Run(static_cast<int32_t>(net_error), signature);
  }

  scoped_refptr<net::SSLPrivateKey> ssl_private_key_;
  base::WeakPtrFactory<SSLPrivateKeyWrapper> weak_ptr_factory_{this};
};

void PrintCertificateDetails(const net::X509Certificate& cert) {
  // Formatted to make log output more readable.
  HOST_LOG << "\n  Client certificate details:\n"
           << "    issued by: " << GetPreferredIssuerFieldValue(cert) << "\n"
           << "    with start date: " << cert.valid_start() << "\n"
           << "    and expiry date: " << cert.valid_expiry();
}

}  // namespace

UrlLoaderNetworkServiceObserver::UrlLoaderNetworkServiceObserver(
    std::unique_ptr<net::ClientCertStore> client_cert_store)
    : client_cert_store_(std::move(client_cert_store)) {
  CHECK(client_cert_store_);
}

UrlLoaderNetworkServiceObserver::~UrlLoaderNetworkServiceObserver() = default;

mojo::PendingRemote<network::mojom::URLLoaderNetworkServiceObserver>
UrlLoaderNetworkServiceObserver::Bind() {
  mojo::PendingRemote<network::mojom::URLLoaderNetworkServiceObserver>
      pending_remote;
  receivers_.Add(this, pending_remote.InitWithNewPipeAndPassReceiver());
  return pending_remote;
}

void UrlLoaderNetworkServiceObserver::OnSSLCertificateError(
    const GURL& url,
    int net_error,
    const net::SSLInfo& ssl_info,
    bool fatal,
    OnSSLCertificateErrorCallback response) {
  std::move(response).Run(net_error);
}

void UrlLoaderNetworkServiceObserver::OnCertificateRequested(
    const std::optional<base::UnguessableToken>& window_id,
    const scoped_refptr<net::SSLCertRequestInfo>& cert_info,
    mojo::PendingRemote<network::mojom::ClientCertificateResponder>
        client_cert_responder) {
  // Note: |cert_info| is bound to the callback as it is the caller's
  // responsibility to keep them alive until the callback has been run by
  // ClientCertStore.
  client_cert_store_->GetClientCerts(
      cert_info,
      base::BindOnce(&UrlLoaderNetworkServiceObserver::OnCertificatesSelected,
                     weak_factory_.GetWeakPtr(),
                     std::move(client_cert_responder), cert_info));
}

void UrlLoaderNetworkServiceObserver::OnAuthRequired(
    const std::optional<base::UnguessableToken>& window_id,
    int32_t request_id,
    const GURL& url,
    bool first_auth_attempt,
    const net::AuthChallengeInfo& auth_info,
    const scoped_refptr<net::HttpResponseHeaders>& head_headers,
    mojo::PendingRemote<network::mojom::AuthChallengeResponder>
        auth_challenge_responder) {}

void UrlLoaderNetworkServiceObserver::OnPrivateNetworkAccessPermissionRequired(
    const GURL& url,
    const net::IPAddress& ip_address,
    const std::optional<std::string>& private_network_device_id,
    const std::optional<std::string>& private_network_device_name,
    OnPrivateNetworkAccessPermissionRequiredCallback callback) {}

void UrlLoaderNetworkServiceObserver::OnLocalNetworkAccessPermissionRequired(
    OnLocalNetworkAccessPermissionRequiredCallback callback) {}

void UrlLoaderNetworkServiceObserver::OnClearSiteData(
    const GURL& url,
    const std::string& header_value,
    int32_t load_flags,
    const std::optional<net::CookiePartitionKey>& cookie_partition_key,
    bool partitioned_state_allowed_only,
    OnClearSiteDataCallback callback) {
  std::move(callback).Run();
}

void UrlLoaderNetworkServiceObserver::OnLoadingStateUpdate(
    network::mojom::LoadInfoPtr info,
    OnLoadingStateUpdateCallback callback) {
  std::move(callback).Run();
}

void UrlLoaderNetworkServiceObserver::OnDataUseUpdate(
    int32_t network_traffic_annotation_id_hash,
    int64_t recv_bytes,
    int64_t sent_bytes) {}

void UrlLoaderNetworkServiceObserver::OnSharedStorageHeaderReceived(
    const url::Origin& request_origin,
    std::vector<network::mojom::SharedStorageModifierMethodWithOptionsPtr>
        methods_with_options,
    const std::optional<std::string>& with_lock,
    OnSharedStorageHeaderReceivedCallback callback) {
  std::move(callback).Run();
}

void UrlLoaderNetworkServiceObserver::OnAdAuctionEventRecordHeaderReceived(
    network::AdAuctionEventRecord event_record,
    const std::optional<url::Origin>& top_frame_origin) {}

void UrlLoaderNetworkServiceObserver::Clone(
    mojo::PendingReceiver<network::mojom::URLLoaderNetworkServiceObserver>
        observer) {
  receivers_.Add(this, std::move(observer));
}

void UrlLoaderNetworkServiceObserver::OnWebSocketConnectedToPrivateNetwork(
    network::mojom::IPAddressSpace ip_address_space) {}

void UrlLoaderNetworkServiceObserver::OnUrlLoaderConnectedToPrivateNetwork(
    const GURL& request_url,
    network::mojom::IPAddressSpace response_address_space,
    network::mojom::IPAddressSpace client_address_space,
    network::mojom::IPAddressSpace target_address_space) {}

void UrlLoaderNetworkServiceObserver::OnCertificatesSelected(
    mojo::PendingRemote<network::mojom::ClientCertificateResponder>
        client_cert_responder,
    const scoped_refptr<net::SSLCertRequestInfo>& cert_info,
    net::ClientCertIdentityList selected_certs) {
  base::Time now = base::Time::Now();
  auto best_match =
      GetBestMatchFromCertificateList(kCertIssuerWildCard, now, selected_certs);
  if (!best_match) {
    ContinueWithCertificate(std::move(client_cert_responder), nullptr, nullptr);
    return;
  }

  scoped_refptr<net::X509Certificate> cert = best_match->certificate();
  if (!IsCertificateValid(kCertIssuerWildCard, now, *cert.get())) {
    LOG(ERROR) << "Best client certificate match was not valid.";
    PrintCertificateDetails(*cert.get());
    ContinueWithCertificate(std::move(client_cert_responder), nullptr, nullptr);
    return;
  }

  net::ClientCertIdentity::SelfOwningAcquirePrivateKey(
      std::move(best_match),
      base::BindOnce(&UrlLoaderNetworkServiceObserver::ContinueWithCertificate,
                     weak_factory_.GetWeakPtr(),
                     std::move(client_cert_responder), std::move(cert)));
}

void UrlLoaderNetworkServiceObserver::ContinueWithCertificate(
    mojo::PendingRemote<network::mojom::ClientCertificateResponder>
        client_cert_responder,
    scoped_refptr<net::X509Certificate> client_cert,
    scoped_refptr<net::SSLPrivateKey> private_key) {
  if (client_cert) {
    PrintCertificateDetails(*client_cert);
  }

  mojo::Remote<network::mojom::ClientCertificateResponder> responder(
      std::move(client_cert_responder));

  if (!client_cert || !private_key) {
    responder->ContinueWithoutCertificate();
    return;
  }

  mojo::PendingRemote<network::mojom::SSLPrivateKey> ssl_private_key;
  mojo::MakeSelfOwnedReceiver(
      std::make_unique<SSLPrivateKeyWrapper>(private_key),
      ssl_private_key.InitWithNewPipeAndPassReceiver());

  responder->ContinueWithCertificate(
      client_cert, private_key->GetProviderName(),
      private_key->GetAlgorithmPreferences(), std::move(ssl_private_key));
}

}  // namespace remoting