blob: 43b7c6ed38be8c94d80729999177b6a45c034e4a [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_PRIVATE_NETWORK_ACCESS_CHECKER_H_
#define SERVICES_NETWORK_PRIVATE_NETWORK_ACCESS_CHECKER_H_
#include <stdint.h>
#include <optional>
#include "base/component_export.h"
#include "base/memory/raw_ptr.h"
#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
#include "services/network/public/cpp/cors/cors_error_status.h"
#include "services/network/public/cpp/private_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 "url/origin.h"
class GURL;
namespace net {
struct TransportInfo;
} // namespace net
namespace network {
struct ResourceRequest;
// Applies Private Network Access checks to a single fetch / URL load.
//
// Manages state used for the "Private Network Access check" algorithm from
// the Private Network Access spec:
// https://wicg.github.io/private-network-access/#private-network-access-check
//
// Helper class for `URLLoader`. Should be instantiated once per `URLLoader`.
//
// Thread-compatible.
class COMPONENT_EXPORT(NETWORK_SERVICE) PrivateNetworkAccessChecker {
public:
// `resource_request` and `url_load_options` correspond to `URLLoader`
// constructor arguments.
//
// `client_security_state` should point to the client security to use for the
// request, and must outlive the PrivateNetworkAccessChecker, if non-null. It
// can be nullptr when the factory doesn't use a client security state.
// `resource_request's` ClientSecurityState, if it has one, is ignored.
PrivateNetworkAccessChecker(
const ResourceRequest& resource_request,
const mojom::ClientSecurityState* client_security_state,
int32_t url_load_options);
PrivateNetworkAccessChecker(
const GURL& url,
mojom::IPAddressSpace target_ip_address_space,
const std::optional<url::Origin>& request_initiator,
mojom::IPAddressSpace required_ip_address_space,
const mojom::ClientSecurityState* client_security_state,
int32_t url_load_options);
// Instances of this class are neither copyable nor movable.
PrivateNetworkAccessChecker(const PrivateNetworkAccessChecker&) = delete;
PrivateNetworkAccessChecker& operator=(const PrivateNetworkAccessChecker&) =
delete;
~PrivateNetworkAccessChecker();
// Checks whether the client should be allowed to use the given transport.
//
// Implements the following "Private Network Access check" algorithm:
//
// https://wicg.github.io/local-network-access/#fetching
PrivateNetworkAccessCheckResult Check(
const net::TransportInfo& transport_info);
// Same as above, but on an IP EndPoint. Skips proxying checks that the
// net::TransportInfo version does.
PrivateNetworkAccessCheckResult Check(const net::IPEndPoint& server_address);
// 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/private-network-access/#response-ip-address-space
std::optional<mojom::IPAddressSpace> ResponseAddressSpace() const {
return response_address_space_;
}
// The target IP address space applied to subsequent checks.
//
// Spec:
// https://wicg.github.io/private-network-access/#request-target-ip-address-space
mojom::IPAddressSpace TargetAddressSpace() const {
return target_address_space_;
}
mojom::IPAddressSpace RequiredAddressSpace() const {
return required_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:
// Helper for `Check()`.
PrivateNetworkAccessCheckResult CheckInternal(
mojom::IPAddressSpace resource_address_space);
// Sets the current request URL (it may change after redirects).
void SetRequestUrl(const GURL& url);
// 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 private 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.
std::optional<net::IPAddress> request_url_private_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_->private_network_request_policy` is `kAllow`.
//
// https://wicg.github.io/private-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()`.
std::optional<mojom::IPAddressSpace> response_address_space_;
// The request initiator origin.
std::optional<url::Origin> request_initiator_;
// The request is from/to a potentially trustworthy and same origin.
bool is_potentially_trustworthy_same_origin_;
// IP address space required for permission prompt.
mojom::IPAddressSpace required_address_space_;
};
} // namespace network
#endif // SERVICES_NETWORK_PRIVATE_NETWORK_ACCESS_CHECKER_H_