blob: 7716d2be736a9c23b556d316cab2ab5f1e777684 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <stdint.h>
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "base/callback.h"
#include "base/files/file_path.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string_piece.h"
#include "base/threading/thread.h"
#include "base/threading/thread_checker.h"
#include "net/base/address_list.h"
#include "net/base/host_port_pair.h"
#include "net/base/ip_endpoint.h"
#include "net/cert/ocsp_revocation_status.h"
#include "net/cert/x509_certificate.h"
#include "net/socket/ssl_server_socket.h"
#include "net/socket/stream_socket.h"
#include "net/socket/tcp_server_socket.h"
#include "net/ssl/ssl_server_config.h"
#include "net/test/embedded_test_server/http_connection.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
#include "url/origin.h"
namespace net {
class StreamSocket;
class TCPServerSocket;
namespace test_server {
class EmbeddedTestServerConnectionListener;
class HttpConnection;
class HttpResponse;
class HttpResponseDelegate;
struct HttpRequest;
class EmbeddedTestServer;
// Returned by the Start[AcceptingConnections]WithHandle() APIs, to simplify
// correct shutdown ordering of the EmbeddedTestServer. Shutdown() is invoked
// on the associated test server when the handle goes out of scope. The handle
// must therefore be destroyed before the test server.
class EmbeddedTestServerHandle {
EmbeddedTestServerHandle() = default;
EmbeddedTestServerHandle(EmbeddedTestServerHandle&& other);
EmbeddedTestServerHandle& operator=(EmbeddedTestServerHandle&& other);
bool is_valid() const { return test_server_; }
explicit operator bool() const { return test_server_; }
friend class EmbeddedTestServer;
explicit EmbeddedTestServerHandle(EmbeddedTestServer* test_server);
EmbeddedTestServer* test_server_ = nullptr;
// Class providing an HTTP server for testing purpose. This is a basic server
// providing only an essential subset of HTTP/1.1 protocol. Especially,
// it assumes that the request syntax is correct. It *does not* support
// a Chunked Transfer Encoding.
// The common use case for unit tests is below:
// void SetUp() {
// test_server_ = std::make_unique<EmbeddedTestServer>();
// test_server_->RegisterRequestHandler(
// base::BindRepeating(&FooTest::HandleRequest, base::Unretained(this)));
// ASSERT_TRUE((test_server_handle_ = test_server_.StartAndReturnHandle()));
// }
// std::unique_ptr<HttpResponse> HandleRequest(const HttpRequest& request) {
// GURL absolute_url = test_server_->GetURL(request.relative_url);
// if (absolute_url.path() != "/test")
// return nullptr;
// auto http_response = std::make_unique<BasicHttpResponse>();
// http_response->set_code(net::HTTP_OK);
// http_response->set_content("hello");
// http_response->set_content_type("text/plain");
// return http_response;
// }
// For a test that spawns another process such as browser_tests, it is
// suggested to call Start in SetUpOnMainThread after the process is spawned.
// If you have to do it before the process spawns, you need to first setup the
// listen socket so that there is no no other threads running while spawning
// the process. To do so, please follow the following example:
// void SetUp() {
// ASSERT_TRUE(embedded_test_server()->InitializeAndListen());
// ...
// InProcessBrowserTest::SetUp();
// }
// void SetUpOnMainThread() {
// // Starts the accept IO thread.
// embedded_test_server()->StartAcceptingConnections();
// }
class EmbeddedTestServer {
enum Type {
// A Java counterpart will be generated for this enum.
enum ServerCertificate {
// Cross-signed certificate to test PKIX path building. Contains an
// intermediate cross-signed by an unknown root, while the client (via
// TestRootStore) is expected to have a self-signed version of the
// intermediate.
// Causes the testserver to use a hostname that is a domain
// instead of an IP.
// A certificate that only contains a commonName, rather than also
// including a subjectAltName extension.
// A certificate that is a leaf certificate signed with SHA-1.
// A certificate that is signed by an intermediate certificate.
// A certificate with invalid notBefore and notAfter times. Windows'
// certificate library will not parse this certificate.
// A certificate that covers a number of test names. See [test_names] in
// net/data/ssl/scripts/ee.cnf. More may be added by editing this list and
// and rerunning net/data/ssl/scripts/
// An RSA certificate with the keyUsage extension specifying that the key
// is only for encipherment.
// An RSA certificate with the keyUsage extension specifying that the key
// is only for digital signatures.
// A certificate will be generated at runtime. A ServerCertificateConfig
// passed to SetSSLConfig may be used to configure the details of the
// generated certificate.
enum class IntermediateType {
// Generated cert is issued directly by the CA.
// Generated cert is issued by a generated intermediate cert, which is
// included in the TLS handshake.
// Generated cert is issued by a generated intermediate, which is NOT
// included in the TLS handshake, but is available through the leaf's
// AIA caIssuers URL.
struct OCSPConfig {
// Enumerates the types of OCSP response that the testserver can produce.
enum class ResponseType {
// OCSP will not be enabled for the corresponding config.
// These correspond to the OCSPResponseStatus enumeration in RFC
// 6960.
// The response will not be valid OCSPResponse DER.
// OCSPResponse will be valid DER but the contained ResponseData will not.
// OCSPProduced describes the time of the producedAt field in the
// OCSP response relative to the certificate the response is for.
enum class Produced {
// producedAt is between certificate's notBefore and notAfter dates.
// producedAt is before certificate's notBefore date.
// producedAt is after certificate's notAfter date.
struct SingleResponse {
// Date describes the thisUpdate..nextUpdate ranges for OCSP
// singleResponses, relative to the current time.
enum class Date {
// The singleResponse is valid for 7 days, and includes the current
// time.
// The singleResponse is valid for 7 days, but nextUpdate is before the
// current time.
// The singleResponse is valid for 7 days, but thisUpdate is after the
// current time.
// The singleResponse is valid for 366 days, and includes the current
// time.
// The singleResponse is valid for 368 days, and includes the current
// time.
// Configures whether a generated OCSP singleResponse's serial field
// matches the serial number of the target certificate.
enum class Serial {
OCSPRevocationStatus cert_status = OCSPRevocationStatus::GOOD;
Date ocsp_date = Date::kValid;
Serial serial = Serial::kMatch;
// Configure OCSP response with |response_type|.
explicit OCSPConfig(ResponseType response_type);
// Configure a successful OCSP response with |single_responses|. |produced|
// specifies the response's producedAt value, relative to the validity
// period of the certificate the OCSPConfig is for.
explicit OCSPConfig(std::vector<SingleResponse> single_responses,
Produced produced = Produced::kValid);
OCSPConfig(const OCSPConfig&);
OCSPConfig& operator=(const OCSPConfig&);
OCSPConfig& operator=(OCSPConfig&&);
ResponseType response_type = ResponseType::kOff;
Produced produced = Produced::kValid;
std::vector<SingleResponse> single_responses;
// Configuration for generated server certificate.
struct ServerCertificateConfig {
ServerCertificateConfig(const ServerCertificateConfig&);
ServerCertificateConfig& operator=(const ServerCertificateConfig&);
ServerCertificateConfig& operator=(ServerCertificateConfig&&);
// Configure whether the generated certificate chain should include an
// intermediate, and if so, how it is delivered to the client.
IntermediateType intermediate = IntermediateType::kNone;
// Configure OCSP handling.
// Note: In the current implementation the AIA request handler does not
// actually parse the OCSP request (a different OCSP URL is used for each
// cert). So this is useful for testing the client's handling of the OCSP
// response, but not for testing that the client is sending a proper OCSP
// request.
// AIA OCSP for the leaf cert. If |kOff|, no AIA OCSP URL will be included
// in the leaf cert.
OCSPConfig ocsp_config;
// Stapled OCSP for the leaf cert. If |kOff|, OCSP Stapling will not be
// used.
OCSPConfig stapled_ocsp_config;
// AIA OCSP for the intermediate cert. If |kOff|, no AIA OCSP URL will be
// included in the intermediate cert. It is invalid to supply a
// configuration other than |kOff| if |intermediate| is |kNone|.
OCSPConfig intermediate_ocsp_config;
// Certificate policy OIDs, in text notation (e.g. ""). If
// non-empty, the policies will be added to the leaf cert and the
// intermediate cert (if an intermediate is configured).
std::vector<std::string> policy_oids;
// A list of DNS names to include in the leaf subjectAltName extension.
std::vector<std::string> dns_names;
// A list of IP addresses to include in the leaf subjectAltName extension.
std::vector<net::IPAddress> ip_addresses;
typedef base::RepeatingCallback<std::unique_ptr<HttpResponse>(
const HttpRequest& request)>
typedef base::RepeatingCallback<void(const HttpRequest& request)>
// Creates a http test server. StartAndReturnHandle() must be called to start
// the server.
// |type| indicates the protocol type of the server (HTTP/HTTPS).
// When a TYPE_HTTPS server is created, EmbeddedTestServer will call
// EmbeddedTestServer::RegisterTestCerts(), so that when the default
// CertVerifiers are run in-process, they will recognize the test server's
// certs. However, if the test server is running in a different process from
// the CertVerifiers, EmbeddedTestServer::RegisterTestCerts() must be called
// in any process where CertVerifiers are expected to accept the
// EmbeddedTestServer's certs.
explicit EmbeddedTestServer(
Type type,
HttpConnection::Protocol protocol = HttpConnection::Protocol::kHttp1);
// Send a request to the server to be handled. If a response is created,
// SendResponseBytes() should be called on the provided HttpConnection.
void HandleRequest(base::WeakPtr<HttpResponseDelegate> connection,
std::unique_ptr<HttpRequest> request);
// Notify the server that a connection is no longer usable and is safe to
// destroy. For H/1 connections, this means a single request/response
// interaction, as keep-alive connections are not supported. If the
// connection listener is present and the socket is still connected, the
// listener will be notified.
void RemoveConnection(
HttpConnection* connection,
EmbeddedTestServerConnectionListener* listener = nullptr);
// Registers the EmbeddedTestServer's certs for the current process. See
// constructor documentation for more information.
static void RegisterTestCerts();
// Sets a connection listener, that would be notified when various connection
// events happen. May only be called before the server is started. Caller
// maintains ownership of the listener.
void SetConnectionListener(EmbeddedTestServerConnectionListener* listener);
// Initializes and waits until the server is ready to accept requests.
// This is the equivalent of calling InitializeAndListen() followed by
// StartAcceptingConnectionsAndReturnHandle().
// Returns a "handle" which will ShutdownAndWaitUntilComplete() when
// destroyed, or null if the listening socket could not be created.
[[nodiscard]] EmbeddedTestServerHandle StartAndReturnHandle(int port = 0);
// Equivalent of StartAndReturnHandle(), but requires manual Shutdown() by
// the caller.
[[nodiscard]] bool Start(int port = 0);
// Starts listening for incoming connections but will not yet accept them.
// Returns whether a listening socket has been succesfully created.
[[nodiscard]] bool InitializeAndListen(int port = 0);
// Starts the Accept IO Thread and begins accepting connections.
[[nodiscard]] EmbeddedTestServerHandle
// Equivalent of StartAcceptingConnectionsAndReturnHandle(), but requires
// manual Shutdown() by the caller.
void StartAcceptingConnections();
// Shuts down the http server and waits until the shutdown is complete.
// Prefer to use the Start*AndReturnHandle() APIs to manage shutdown, if
// possible.
[[nodiscard]] bool ShutdownAndWaitUntilComplete();
// Checks if the server has started listening for incoming connections.
bool Started() const { return listen_socket_.get() != nullptr; }
static base::FilePath GetRootCertPemPath();
HostPortPair host_port_pair() const {
return HostPortPair::FromURL(base_url_);
// Returns the base URL to the server, which looks like
//<port>/, where <port> is the actual port number used by
// the server.
const GURL& base_url() const { return base_url_; }
// Returns a URL to the server based on the given relative URL, which
// should start with '/'. For example: GetURL("/path?query=foo") =>
GURL GetURL(base::StringPiece relative_url) const;
// Similar to the above method with the difference that it uses the supplied
// |hostname| for the URL instead of The hostname should be
// resolved to
GURL GetURL(base::StringPiece hostname, base::StringPiece relative_url) const;
// Convenience function equivalent to calling url::Origin::Create(base_url()).
// Will use the GetURL() variant that takes a hostname as the base URL, if
// `hostname` is non-null.
url::Origin GetOrigin(
const absl::optional<std::string>& hostname = absl::nullopt) const;
// Returns the address list needed to connect to the server.
[[nodiscard]] bool GetAddressList(AddressList* address_list) const;
// Returns the IP Address to connect to the server as a string.
std::string GetIPLiteralString() const;
// Returns the port number used by the server.
uint16_t port() const { return port_; }
// SetSSLConfig sets the SSL configuration for the server. It is invalid to
// call after the server is started. If called multiple times, the last call
// will have effect.
void SetSSLConfig(ServerCertificate cert, const SSLServerConfig& ssl_config);
void SetSSLConfig(ServerCertificate cert);
void SetSSLConfig(const ServerCertificateConfig& cert_config,
const SSLServerConfig& ssl_config);
void SetSSLConfig(const ServerCertificateConfig& cert_config);
// TODO(mattm): make this [[nodiscard]]
bool ResetSSLConfig(ServerCertificate cert,
const SSLServerConfig& ssl_config);
// Returns the certificate that the server is using.
// If using a generated ServerCertificate type, this must not be called before
// InitializeAndListen() has been called.
scoped_refptr<X509Certificate> GetCertificate();
// Registers request handler which serves files from |directory|.
// For instance, a request to "/foo.html" is served by "foo.html" under
// |directory|. Files under sub directories are also handled in the same way
// (i.e. "/foo/bar.html" is served by "foo/bar.html" under |directory|).
// TODO(svaldez): Merge ServeFilesFromDirectory and
// ServeFilesFromSourceDirectory.
void ServeFilesFromDirectory(const base::FilePath& directory);
// Serves files relative to DIR_SOURCE_ROOT.
void ServeFilesFromSourceDirectory(base::StringPiece relative);
void ServeFilesFromSourceDirectory(const base::FilePath& relative);
// Registers the default handlers and serve additional files from the
// |directory| directory, relative to DIR_SOURCE_ROOT.
void AddDefaultHandlers(const base::FilePath& directory);
// Returns the directory that files will be served from if |relative| is
// passed to ServeFilesFromSourceDirectory().
static base::FilePath GetFullPathFromSourceDirectory(
const base::FilePath& relative);
// Adds all default handlers except, without serving additional files from any
// directory.
void AddDefaultHandlers();
// Adds a request handler that can perform any general-purpose processing.
// |callback| will be invoked on the server's IO thread. Note that:
// 1. All handlers must be registered before the server is Start()ed.
// 2. The server should be Shutdown() before any variables referred to by
// |callback| (e.g. via base::Unretained(&local)) are deleted. Using the
// Start*WithHandle() API variants is recommended for this reason.
void RegisterRequestHandler(const HandleRequestCallback& callback);
// Adds a request monitor that will be called before any handlers. Monitors
// can be used to observe requests, but not to respond to them.
// See RegisterRequestHandler() for notes on usage.
void RegisterRequestMonitor(const MonitorRequestCallback& callback);
// Adds a default request handler, to be called if no user-specified handler
// handles the request.
// See RegisterRequestHandler() for notes on usage.
void RegisterDefaultHandler(const HandleRequestCallback& callback);
bool FlushAllSocketsAndConnectionsOnUIThread();
void FlushAllSocketsAndConnections();
// Adds an origin/accept_ch pair to add to an ACCEPT_CH HTTP/2 frame. If any
// pairs have been added, the ALPS TLS extension will be populated, which
// will act as though an ACCEPT_CH frame was sent by the server before the
// first frame is sent by a client. For more information, see
// draft-vvv-tls-alps-01 and section 4.1 (HTTP/2 ACCEPT_CH Frame) of
// draft-davidben-http-client-hint-reliability
// Only valid before Start() or ResetSSLServerConfig(). Only valid when
// constructed with PROTOCOL_HTTP2. For the default host, use an empty
// string.
void SetAlpsAcceptCH(std::string hostname, std::string accept_ch);
// Returns the file name of the certificate the server is using. The test
// certificates can be found in net/data/ssl/certificates/.
std::string GetCertificateName() const;
// Shuts down the server.
void ShutdownOnIOThread();
// Sets the SSL configuration for the server. It is invalid for |cert_config|
// to be non-null if |cert| is not CERT_AUTO.
void SetSSLConfigInternal(ServerCertificate cert,
const ServerCertificateConfig* cert_config,
const SSLServerConfig& ssl_config);
// Resets the SSLServerConfig on the IO thread.
bool ResetSSLConfigOnIOThread(ServerCertificate cert,
const SSLServerConfig& ssl_config);
// Upgrade the TCP connection to one over SSL.
std::unique_ptr<SSLServerSocket> DoSSLUpgrade(
std::unique_ptr<StreamSocket> connection);
// Handles async callback when the SSL handshake has been completed.
void OnHandshakeDone(HttpConnection* http_connection, int rv);
// Begins new connection if handshake resulted in a connection
void HandleHandshakeResults();
// Begins accepting new client connections.
void DoAcceptLoop();
// Handles async callback when there is a new client socket. |rv| is the
// return value of the socket Accept.
void OnAcceptCompleted(int rv);
// Adds the new |socket| to the list of clients and begins the reading
// data.
void HandleAcceptResult(std::unique_ptr<StreamSocket> socket_ptr);
// Create a connection with a socket, add it to the map, and return pointers
// to both.
HttpConnection* AddConnection(std::unique_ptr<StreamSocket> socket_ptr);
// Handles async callback when new data has been read from the |connection|.
void OnReadCompleted(HttpConnection* connection, int rv);
// Returns true if the current |cert_| configuration uses a static
// pre-generated cert loaded from the filesystem.
bool UsingStaticCert() const;
// Reads server certificate and private key from file. May only be called if
// |cert_| refers to a file-based cert & key.
[[nodiscard]] bool InitializeCertAndKeyFromFile();
// Generate server certificate and private key. May only be called if |cert_|
// refers to a generated cert & key.
[[nodiscard]] bool GenerateCertAndKey();
// Initializes the SSLServerContext so that SSLServerSocket connections may
// share the same cache
[[nodiscard]] bool InitializeSSLServerContext();
// Posts a task to the |io_thread_| and waits for a reply.
[[nodiscard]] bool PostTaskToIOThreadAndWait(base::OnceClosure closure);
// Posts a task that returns a true/false success/fail value to the
// |io_thread_| and waits for a reply.
[[nodiscard]] bool PostTaskToIOThreadAndWaitWithResult(
base::OnceCallback<bool()> task);
const bool is_using_ssl_;
const HttpConnection::Protocol protocol_;
std::unique_ptr<base::Thread> io_thread_;
std::unique_ptr<TCPServerSocket> listen_socket_;
std::unique_ptr<StreamSocket> accepted_socket_;
raw_ptr<EmbeddedTestServerConnectionListener, DanglingUntriaged>
connection_listener_ = nullptr;
uint16_t port_ = 0;
GURL base_url_;
IPEndPoint local_endpoint_;
std::map<const StreamSocket*, std::unique_ptr<HttpConnection>> connections_;
// Vector of registered and default request handlers and monitors.
std::vector<HandleRequestCallback> request_handlers_;
std::vector<MonitorRequestCallback> request_monitors_;
std::vector<HandleRequestCallback> default_request_handlers_;
base::ThreadChecker thread_checker_;
net::SSLServerConfig ssl_config_;
ServerCertificate cert_ = CERT_OK;
ServerCertificateConfig cert_config_;
scoped_refptr<X509Certificate> x509_cert_;
bssl::UniquePtr<EVP_PKEY> private_key_;
base::flat_map<std::string, std::string> alps_accept_ch_;
std::unique_ptr<SSLServerContext> context_;
// HTTP server that handles AIA URLs that are embedded in this test server's
// certificate when the server certificate is one of the CERT_AUTO variants.
std::unique_ptr<EmbeddedTestServer> aia_http_server_;
base::WeakPtrFactory<EmbeddedTestServer> weak_factory_{this};
} // namespace test_server
// TODO(svaldez): Refactor EmbeddedTestServer to be in the net namespace.
using test_server::EmbeddedTestServer;
} // namespace net