blob: a1cb59d7c6b265fc46272da2ae986f83c979daeb [file] [log] [blame]
// 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 SERVICES_NETWORK_LOCAL_NETWORK_ACCESS_CHECKER_H_
#define SERVICES_NETWORK_LOCAL_NETWORK_ACCESS_CHECKER_H_
#include <stdint.h>
#include "base/component_export.h"
#include "base/memory/raw_ptr.h"
#include "net/base/ip_address.h"
#include "services/network/public/cpp/cors/cors_error_status.h"
#include "services/network/public/cpp/local_network_access_check_result.h"
#include "services/network/public/mojom/client_security_state.mojom.h"
#include "services/network/public/mojom/ip_address_space.mojom-forward.h"
#include "services/network/public/mojom/network_context.mojom-forward.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/origin.h"
class GURL;
namespace net {
struct TransportInfo;
} // namespace net
namespace network {
struct ResourceRequest;
// Applies Local Network Access checks to a single fetch / URL load.
//
// Manages state used for the "Local Network Access check" algorithm from
// the Local Network Access spec:
// https://wicg.github.io/local-network-access/#local-network-access-check
//
// Helper class for `URLLoader`. Should be instantiated once per `URLLoader`.
//
// Thread-compatible.
class COMPONENT_EXPORT(NETWORK_SERVICE) LocalNetworkAccessChecker {
public:
// `resource_request` and `url_load_options` correspond to `URLLoader`
// constructor arguments.
// `factory_client_security_state` should point to the client security
// state object coming from the factory that built the owner `URLLoader`. It
// can be nullptr when the factory doesn't use a client security state.
LocalNetworkAccessChecker(
const ResourceRequest& resource_request,
const mojom::ClientSecurityState* factory_client_security_state,
int32_t url_load_options);
// Instances of this class are neither copyable nor movable.
LocalNetworkAccessChecker(const LocalNetworkAccessChecker&) = delete;
LocalNetworkAccessChecker& operator=(const LocalNetworkAccessChecker&) =
delete;
~LocalNetworkAccessChecker();
// Checks whether the client should be allowed to use the given transport.
//
// Implements the following "Local Network Access check" algorithm:
// https://wicg.github.io/local-network-access/#local-network-access-check
LocalNetworkAccessCheckResult Check(const net::TransportInfo& transport_info);
// Returns the IP address space derived from the `transport_info` argument
// passed to the last call to `Check()`, if any.
//
// Spec:
// https://wicg.github.io/local-network-access/#response-ip-address-space
absl::optional<mojom::IPAddressSpace> ResponseAddressSpace() const {
return response_address_space_;
}
// The target IP address space applied to subsequent checks.
//
// Spec:
// https://wicg.github.io/local-network-access/#request-target-ip-address-space
mojom::IPAddressSpace TargetAddressSpace() const {
return target_address_space_;
}
// Clears state from all checks this instance has performed, and sets the
// request URL to `new_url`.
//
// This instance will behave as if newly constructed once more. In addition,
// resets this instance's target IP address space to `kUnknown`.
//
// This should be called upon following a redirect or after a cache result
// blocked without preflight because we'll try fetching from the network.
void ResetForRedirect(const GURL& new_url);
// Clears state from all checks this instance has performed.
//
// This instance will behave as if newly constructed once more. In addition,
// resets this instance's target IP address space to `kUnknown`.
//
// This should be called after a cache result was blocked without preflight,
// because we'll try fetching from the network again.
void ResetForRetry();
// Returns the client security state that applies to the current request.
// May return nullptr.
//
// Contains relevant state derived from the fetch client's policy container.
const mojom::ClientSecurityState* client_security_state() const {
return client_security_state_.get();
}
// Returns an owned clone of `client_security_state()`.
mojom::ClientSecurityStatePtr CloneClientSecurityState() const;
// Returns the IP address space in `client_security_state()`.
// Returns `kUnknown` if `client_security_state()` is nullptr.
mojom::IPAddressSpace ClientAddressSpace() const;
private:
// Returns whether this instance has a client security state containing a
// policy set to `kPreflightWarn`.
bool IsPolicyPreflightWarn() const;
// Helper for `Check()`.
LocalNetworkAccessCheckResult CheckInternal(
mojom::IPAddressSpace resource_address_space);
// Sets the current request URL (it may change after redirects).
void SetRequestUrl(const GURL& url);
// The client security state copied from the request's trusted params.
// May be nullptr.
//
// Should not be used directly. Use `client_security_state_` instead, which
// points to the same struct iff this client security state should be used.
const mojom::ClientSecurityStatePtr request_client_security_state_;
// The security state of the client of the fetch. May be nullptr.
const raw_ptr<const mojom::ClientSecurityState> client_security_state_;
// Whether to block all requests to non-public IP address spaces, regardless
// of other considerations. Set based on URL load options.
const bool should_block_local_request_;
// Whether the request URL's scheme is `http:`.
bool is_request_url_scheme_http_ = false;
// If the request URL's host is a local IP literal, then this stores the
// IP. Nullopt otherwise.
//
// For example:
//
// - request url = `http://192.168.1.1` -> `192.168.1.1`
// - request url = `http://[fe80::]:1234` -> `fe80::`
// - request url = `https://10.0.0.1` -> `10.0.0.1`
// - request url = `http://localhost` -> nullptr
//
// Used to compute metrics for https://crbug.com/1381471.
absl::optional<net::IPAddress> request_url_local_ip_;
// The target IP address space set on the request. Ignored if `kUnknown`.
//
// Copied from `ResourceRequest::target_ip_address_space`.
//
// Invariant: always `kUnknown` if `client_security_state_` is nullptr, or
// if `client_security_state_->local_network_request_policy` is `kAllow`.
//
// https://wicg.github.io/local-network-access/#request-target-ip-address-space
mojom::IPAddressSpace target_address_space_;
// The IP address space derived from the `transport_info` argument passed to
// the last call to `Check()`.
//
// Set by `Check()`, reset by `ResetForRedirect()`.
absl::optional<mojom::IPAddressSpace> response_address_space_;
// The request initiator origin.
absl::optional<url::Origin> request_initiator_;
// The request is from/to a potentially trustworthy and same origin.
bool is_potentially_trustworthy_same_origin_;
};
} // namespace network
#endif // SERVICES_NETWORK_LOCAL_NETWORK_ACCESS_CHECKER_H_