summaryrefslogtreecommitdiff
path: root/chromium/net/test/spawned_test_server/base_test_server.h
blob: c279b6cf21df6b439ad7c0c45aff5704e46f39a5 (plain)
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
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
// Copyright 2013 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.

#ifndef NET_TEST_SPAWNED_TEST_SERVER_BASE_TEST_SERVER_H_
#define NET_TEST_SPAWNED_TEST_SERVER_BASE_TEST_SERVER_H_

#include <stdint.h>

#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "base/compiler_specific.h"
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "net/base/host_port_pair.h"
#include "net/ssl/ssl_client_cert_type.h"

class GURL;

namespace base {
class DictionaryValue;
}

namespace net {

class AddressList;
class ScopedPortException;
class X509Certificate;

// The base class of Test server implementation.
class BaseTestServer {
 public:
  typedef std::pair<std::string, std::string> StringPair;

  // Following types represent protocol schemes. See also
  // http://www.iana.org/assignments/uri-schemes.html
  enum Type {
    TYPE_BASIC_AUTH_PROXY,
    TYPE_FTP,
    TYPE_HTTP,
    TYPE_HTTPS,
    TYPE_WS,
    TYPE_WSS,
    TYPE_TCP_ECHO,
    TYPE_UDP_ECHO,
  };

  // Container for various options to control how the HTTPS or WSS server is
  // initialized.
  struct SSLOptions {
    enum ServerCertificate {
      CERT_OK,

      // CERT_AUTO causes the testserver to generate a test certificate issued
      // by "Testing CA" (see net/data/ssl/certificates/ocsp-test-root.pem).
      CERT_AUTO,
      // Generate an intermediate cert issued by "Testing CA", and generate a
      // test certificate issued by that intermediate with an AIA record for
      // retrieving the intermediate.
      CERT_AUTO_AIA_INTERMEDIATE,

      CERT_MISMATCHED_NAME,
      CERT_EXPIRED,
      // 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.
      CERT_CHAIN_WRONG_ROOT,

      // Causes the testserver to use a hostname that is a domain
      // instead of an IP.
      CERT_COMMON_NAME_IS_DOMAIN,

      // A certificate with invalid notBefore and notAfter times. Windows'
      // certificate library will not parse this certificate.
      CERT_BAD_VALIDITY,
    };

    // OCSPStatus enumerates the types of OCSP response that the testserver
    // can produce.
    enum OCSPStatus {
      OCSP_OK,
      OCSP_REVOKED,
      OCSP_INVALID_RESPONSE,
      OCSP_UNAUTHORIZED,
      OCSP_UNKNOWN,
      OCSP_INVALID_RESPONSE_DATA,
      OCSP_TRY_LATER,
      OCSP_MISMATCHED_SERIAL,
    };

    // OCSPDate enumerates the date ranges for OCSP responses that the
    // testserver can produce.
    enum OCSPDate {
      OCSP_DATE_VALID,
      OCSP_DATE_OLD,
      OCSP_DATE_EARLY,
      OCSP_DATE_LONG,
    };

    // OCSPSingleResponse is used when specifying multiple stapled responses,
    // each
    // with their own CertStatus and date validity.
    struct OCSPSingleResponse {
      OCSPStatus status;
      OCSPDate date;
    };

    // OCSPProduced enumerates the validity of the producedAt field in OCSP
    // responses produced by the testserver.
    enum OCSPProduced {
      OCSP_PRODUCED_VALID,
      OCSP_PRODUCED_BEFORE_CERT,
      OCSP_PRODUCED_AFTER_CERT,
    };

    // Bitmask of key exchange algorithms that the test server supports and that
    // can be selectively enabled or disabled.
    enum KeyExchange {
      // Special value used to indicate that any algorithm the server supports
      // is acceptable. Preferred over explicitly OR-ing all key exchange
      // algorithms.
      KEY_EXCHANGE_ANY = 0,

      KEY_EXCHANGE_RSA = (1 << 0),
      KEY_EXCHANGE_DHE_RSA = (1 << 1),
      KEY_EXCHANGE_ECDHE_RSA = (1 << 2),
    };

    // Bitmask of bulk encryption algorithms that the test server supports
    // and that can be selectively enabled or disabled.
    enum BulkCipher {
      // Special value used to indicate that any algorithm the server supports
      // is acceptable. Preferred over explicitly OR-ing all ciphers.
      BULK_CIPHER_ANY = 0,

      BULK_CIPHER_RC4 = (1 << 0),
      BULK_CIPHER_AES128 = (1 << 1),
      BULK_CIPHER_AES256 = (1 << 2),

      // NOTE: 3DES support in the Python test server has external
      // dependencies and not be available on all machines. Clients may not
      // be able to connect if only 3DES is specified.
      BULK_CIPHER_3DES = (1 << 3),

      BULK_CIPHER_AES128GCM = (1 << 4),
    };

    // NOTE: the values of these enumerators are passed to the the Python test
    // server. Do not change them.
    enum TLSIntolerantLevel {
      TLS_INTOLERANT_NONE = 0,
      TLS_INTOLERANT_ALL = 1,     // Intolerant of all TLS versions.
      TLS_INTOLERANT_TLS1_1 = 2,  // Intolerant of TLS 1.1 or higher.
      TLS_INTOLERANT_TLS1_2 = 3,  // Intolerant of TLS 1.2 or higher.
      TLS_INTOLERANT_TLS1_3 = 4,  // Intolerant of TLS 1.3 or higher.
    };

    // Values which control how the server reacts in response to a ClientHello
    // it is intolerant of.
    enum TLSIntoleranceType {
      TLS_INTOLERANCE_ALERT = 0,  // Send a handshake_failure alert.
      TLS_INTOLERANCE_CLOSE = 1,  // Close the connection.
      TLS_INTOLERANCE_RESET = 2,  // Send a TCP reset.
    };

    // Initialize a new SSLOptions using CERT_OK as the certificate.
    SSLOptions();

    // Initialize a new SSLOptions that will use the specified certificate.
    explicit SSLOptions(ServerCertificate cert);
    SSLOptions(const SSLOptions& other);
    ~SSLOptions();

    // Returns the relative filename of the file that contains the
    // |server_certificate|.
    base::FilePath GetCertificateFile() const;

    // GetOCSPArgument returns the value of any OCSP argument to testserver or
    // the empty string if there is none.
    std::string GetOCSPArgument() const;

    // GetOCSPDateArgument returns the value of the OCSP date argument to
    // testserver or the empty string if there is none.
    std::string GetOCSPDateArgument() const;

    // GetOCSPProducedArgument returns the value of the OCSP produced argument
    // to testserver or the empty string if there is none.
    std::string GetOCSPProducedArgument() const;

    // The certificate to use when serving requests.
    ServerCertificate server_certificate = CERT_OK;

    // If |server_certificate==CERT_AUTO| then this determines the type of OCSP
    // response returned. Ignored if |ocsp_responses| is non-empty.
    OCSPStatus ocsp_status = OCSP_OK;

    // If |server_certificate==CERT_AUTO| then this determines the date range
    // set on the OCSP response returned. Ignore if |ocsp_responses| is
    // non-empty.
    OCSPDate ocsp_date = OCSP_DATE_VALID;

    // If |server_certificate==CERT_AUTO|, contains the status and validity for
    // multiple stapled responeses. Overrides |ocsp_status| and |ocsp_date| when
    // non-empty.
    std::vector<OCSPSingleResponse> ocsp_responses;

    // If |server_certificate==CERT_AUTO| then this determines the validity of
    // the producedAt field on the returned OCSP response.
    OCSPProduced ocsp_produced = OCSP_PRODUCED_VALID;

    // If not zero, |cert_serial| will be the serial number of the
    // auto-generated leaf certificate when |server_certificate==CERT_AUTO|.
    uint64_t cert_serial = 0;

    // If not empty, |cert_common_name| will be the common name of the
    // auto-generated leaf certificate when |server_certificate==CERT_AUTO|.
    std::string cert_common_name;

    // True if a CertificateRequest should be sent to the client during
    // handshaking.
    bool request_client_certificate = false;

    // If |request_client_certificate| is true, an optional list of files,
    // each containing a single, PEM-encoded X.509 certificates. The subject
    // from each certificate will be added to the certificate_authorities
    // field of the CertificateRequest.
    std::vector<base::FilePath> client_authorities;

    // If |request_client_certificate| is true, an optional list of
    // SSLClientCertType values to populate the certificate_types field of the
    // CertificateRequest.
    std::vector<SSLClientCertType> client_cert_types;

    // A bitwise-OR of KeyExchnage that should be used by the
    // HTTPS server, or KEY_EXCHANGE_ANY to indicate that all implemented
    // key exchange algorithms are acceptable.
    int key_exchanges = KEY_EXCHANGE_ANY;

    // A bitwise-OR of BulkCipher that should be used by the
    // HTTPS server, or BULK_CIPHER_ANY to indicate that all implemented
    // ciphers are acceptable.
    int bulk_ciphers = BULK_CIPHER_ANY;

    // If true, pass the --https-record-resume argument to testserver.py which
    // causes it to log session cache actions and echo the log on
    // /ssl-session-cache.
    bool record_resume = false;

    // If not TLS_INTOLERANT_NONE, the server will abort any handshake that
    // negotiates an intolerant TLS version in order to test version fallback.
    TLSIntolerantLevel tls_intolerant = TLS_INTOLERANT_NONE;

    // If |tls_intolerant| is not TLS_INTOLERANT_NONE, how the server reacts to
    // an intolerant TLS version.
    TLSIntoleranceType tls_intolerance_type = TLS_INTOLERANCE_ALERT;

    // fallback_scsv_enabled, if true, causes the server to process the
    // TLS_FALLBACK_SCSV cipher suite. This cipher suite is sent by Chrome
    // when performing TLS version fallback in response to an SSL handshake
    // failure. If this option is enabled then the server will reject fallback
    // connections.
    bool fallback_scsv_enabled = false;

    // Temporary glue for testing: validation of SCTs is application-controlled
    // and can be appropriately mocked out, so sending fake data here does not
    // affect handshaking behaviour.
    // TODO(ekasper): replace with valid SCT files for test certs.
    // (Fake) SignedCertificateTimestampList (as a raw binary string) to send in
    // a TLS extension.
    std::string signed_cert_timestamps_tls_ext;

    // Whether to staple the OCSP response.
    bool staple_ocsp_response = false;

    // Whether to make the OCSP server unavailable. This does not affect the
    // stapled OCSP response.
    bool ocsp_server_unavailable = false;

    // List of protocols to advertise in NPN extension.  NPN is not supported if
    // list is empty.  Note that regardless of what protocol is negotiated, the
    // test server will continue to speak HTTP/1.1.
    std::vector<std::string> npn_protocols;

    // List of supported ALPN protocols.
    std::vector<std::string> alpn_protocols;

    // Whether to send a fatal alert immediately after completing the handshake.
    bool alert_after_handshake = false;

    // If true, disables channel ID on the server.
    bool disable_channel_id = false;

    // If true, disables extended master secret tls extension.
    bool disable_extended_master_secret = false;

    // List of token binding params that the server supports and will negotiate.
    std::vector<int> supported_token_binding_params;
  };

  // Initialize a TestServer.
  explicit BaseTestServer(Type type);

  // Initialize a TestServer with a specific set of SSLOptions for HTTPS or WSS.
  BaseTestServer(Type type, const SSLOptions& ssl_options);

  // Starts the server blocking until the server is ready.
  bool Start() WARN_UNUSED_RESULT;

  // Start the test server without blocking. Use this if you need multiple test
  // servers (such as WebSockets and HTTP, or HTTP and HTTPS). You must call
  // BlockUntilStarted on all servers your test requires before executing the
  // test. For example:
  //
  //   // Start the servers in parallel.
  //   ASSERT_TRUE(http_server.StartInBackground());
  //   ASSERT_TRUE(websocket_server.StartInBackground());
  //   // Wait for both servers to be ready.
  //   ASSERT_TRUE(http_server.BlockUntilStarted());
  //   ASSERT_TRUE(websocket_server.BlockUntilStarted());
  //   RunMyTest();
  //
  // Returns true on success.
  virtual bool StartInBackground() WARN_UNUSED_RESULT = 0;

  // Block until the test server is ready. Returns true on success. See
  // StartInBackground() documentation for more information.
  virtual bool BlockUntilStarted() WARN_UNUSED_RESULT = 0;

  // Returns the host port pair used by current Python based test server only
  // if the server is started.
  const HostPortPair& host_port_pair() const;

  const base::FilePath& document_root() const { return document_root_; }
  const base::DictionaryValue& server_data() const;
  std::string GetScheme() const;
  bool GetAddressList(AddressList* address_list) const WARN_UNUSED_RESULT;

  GURL GetURL(const std::string& path) const;

  GURL GetURLWithUser(const std::string& path,
                      const std::string& user) const;

  GURL GetURLWithUserAndPassword(const std::string& path,
                                 const std::string& user,
                                 const std::string& password) const;

  static bool GetFilePathWithReplacements(
      const std::string& original_path,
      const std::vector<StringPair>& text_to_replace,
      std::string* replacement_path);

  static bool UsingSSL(Type type) {
    return type == BaseTestServer::TYPE_HTTPS ||
           type == BaseTestServer::TYPE_WSS;
  }

  // Enable HTTP basic authentication. Currently this only works for TYPE_WS and
  // TYPE_WSS.
  void set_websocket_basic_auth(bool ws_basic_auth) {
    ws_basic_auth_ = ws_basic_auth;
  }

  // Disable creation of anonymous FTP user.
  void set_no_anonymous_ftp_user(bool no_anonymous_ftp_user) {
    no_anonymous_ftp_user_ = no_anonymous_ftp_user;
  }

  // Redirect proxied CONNECT requests to localhost.
  void set_redirect_connect_to_localhost(bool redirect_connect_to_localhost) {
    redirect_connect_to_localhost_ = redirect_connect_to_localhost;
  }

  // Marks the root certificate of an HTTPS test server as trusted for
  // the duration of tests.
  bool LoadTestRootCert() const WARN_UNUSED_RESULT;

  // Returns the certificate that the server is using.
  scoped_refptr<X509Certificate> GetCertificate() const;

 protected:
  virtual ~BaseTestServer();
  Type type() const { return type_; }
  const SSLOptions& ssl_options() const { return ssl_options_; }

  bool started() const { return started_; }

  // Gets port currently assigned to host_port_pair_ without checking
  // whether it's available (server started) or not.
  uint16_t GetPort();

  // Sets |port| as the actual port used by Python based test server.
  void SetPort(uint16_t port);

  // Set up internal status when the server is started.
  bool SetupWhenServerStarted() WARN_UNUSED_RESULT;

  // Clean up internal status when starting to stop server.
  void CleanUpWhenStoppingServer();

  // Set path of test resources.
  void SetResourcePath(const base::FilePath& document_root,
                       const base::FilePath& certificates_dir);

  // Parses the server data read from the test server and sets |server_data_|.
  // *port is set to the port number specified in server_data. The port may be
  // different from the local port set in |host_port_pair_|, specifically when
  // using RemoteTestServer (which proxies connections from 127.0.0.1 to a
  // different IP). Returns true on success.
  bool SetAndParseServerData(const std::string& server_data,
                             int* port) WARN_UNUSED_RESULT;

  // Generates a DictionaryValue with the arguments for launching the external
  // Python test server.
  bool GenerateArguments(base::DictionaryValue* arguments) const
    WARN_UNUSED_RESULT;

  // Subclasses can override this to add arguments that are specific to their
  // own test servers.
  virtual bool GenerateAdditionalArguments(
      base::DictionaryValue* arguments) const WARN_UNUSED_RESULT;

 private:
  void Init(const std::string& host);

  // Document root of the test server.
  base::FilePath document_root_;

  // Directory that contains the SSL certificates.
  base::FilePath certificates_dir_;

  // Address on which the tests should connect to the server. With
  // RemoteTestServer it may be different from the address on which the server
  // listens on.
  HostPortPair host_port_pair_;

  // Holds the data sent from the server (e.g., port number).
  std::unique_ptr<base::DictionaryValue> server_data_;

  // If |type_| is TYPE_HTTPS or TYPE_WSS, the TLS settings to use for the test
  // server.
  SSLOptions ssl_options_;

  Type type_;

  // Has the server been started?
  bool started_ = false;

  // Enables logging of the server to the console.
  bool log_to_console_ = false;

  // Is WebSocket basic HTTP authentication enabled?
  bool ws_basic_auth_ = false;

  // Disable creation of anonymous FTP user?
  bool no_anonymous_ftp_user_ = false;

  // Redirect proxied CONNECT requests to localhost?
  bool redirect_connect_to_localhost_ = false;

  std::unique_ptr<ScopedPortException> allowed_port_;

  DISALLOW_COPY_AND_ASSIGN(BaseTestServer);
};

}  // namespace net

#endif  // NET_TEST_SPAWNED_TEST_SERVER_BASE_TEST_SERVER_H_