| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/test/test_server.h" | 5 #include "net/test/test_server.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <string> | 8 #include <string> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 #include "base/utf_string_conversions.h" | 23 #include "base/utf_string_conversions.h" |
| 24 #include "googleurl/src/gurl.h" | 24 #include "googleurl/src/gurl.h" |
| 25 #include "net/base/cert_test_util.h" | 25 #include "net/base/cert_test_util.h" |
| 26 #include "net/base/host_port_pair.h" | 26 #include "net/base/host_port_pair.h" |
| 27 #include "net/base/host_resolver.h" | 27 #include "net/base/host_resolver.h" |
| 28 #include "net/base/test_completion_callback.h" | 28 #include "net/base/test_completion_callback.h" |
| 29 #include "net/socket/tcp_client_socket.h" | 29 #include "net/socket/tcp_client_socket.h" |
| 30 #include "net/test/python_utils.h" | 30 #include "net/test/python_utils.h" |
| 31 #include "testing/platform_test.h" | 31 #include "testing/platform_test.h" |
| 32 | 32 |
| 33 namespace net { |
| 34 |
| 33 namespace { | 35 namespace { |
| 34 | 36 |
| 35 // Number of connection attempts for tests. | 37 // Number of connection attempts for tests. |
| 36 const int kServerConnectionAttempts = 10; | 38 const int kServerConnectionAttempts = 10; |
| 37 | 39 |
| 38 // Connection timeout in milliseconds for tests. | 40 // Connection timeout in milliseconds for tests. |
| 39 const int kServerConnectionTimeoutMs = 1000; | 41 const int kServerConnectionTimeoutMs = 1000; |
| 40 | 42 |
| 41 const char kTestServerShardFlag[] = "test-server-shard"; | 43 const char kTestServerShardFlag[] = "test-server-shard"; |
| 42 | 44 |
| 43 int GetPortBase(net::TestServer::Type type) { | 45 int GetHTTPSPortBase(const TestServer::HTTPSOptions& options) { |
| 44 switch (type) { | 46 if (options.request_client_certificate) |
| 45 case net::TestServer::TYPE_FTP: | 47 return 9543; |
| 46 return 3117; | 48 |
| 47 case net::TestServer::TYPE_HTTP: | 49 switch (options.server_certificate) { |
| 48 return 1337; | 50 case TestServer::HTTPSOptions::CERT_OK: |
| 49 case net::TestServer::TYPE_HTTPS: | |
| 50 return 9443; | 51 return 9443; |
| 51 case net::TestServer::TYPE_HTTPS_CLIENT_AUTH: | 52 case TestServer::HTTPSOptions::CERT_MISMATCHED_NAME: |
| 52 return 9543; | 53 return 9643; |
| 53 case net::TestServer::TYPE_HTTPS_EXPIRED_CERTIFICATE: | 54 case TestServer::HTTPSOptions::CERT_EXPIRED: |
| 54 // TODO(phajdan.jr): Some tests rely on this hardcoded value. | 55 // TODO(phajdan.jr): Some tests rely on this hardcoded value. |
| 55 // Some uses of this are actually in .html/.js files. | 56 // Some uses of this are actually in .html/.js files. |
| 56 return 9666; | 57 return 9666; |
| 57 case net::TestServer::TYPE_HTTPS_MISMATCHED_HOSTNAME: | |
| 58 return 9643; | |
| 59 default: | 58 default: |
| 60 NOTREACHED(); | 59 NOTREACHED(); |
| 61 } | 60 } |
| 62 return -1; | 61 return -1; |
| 63 } | 62 } |
| 64 | 63 |
| 65 int GetPort(net::TestServer::Type type) { | 64 int GetPortBase(TestServer::Type type, |
| 66 int port = GetPortBase(type); | 65 const TestServer::HTTPSOptions& options) { |
| 66 switch (type) { |
| 67 case TestServer::TYPE_FTP: |
| 68 return 3117; |
| 69 case TestServer::TYPE_HTTP: |
| 70 return 1337; |
| 71 case TestServer::TYPE_HTTPS: |
| 72 return GetHTTPSPortBase(options); |
| 73 default: |
| 74 NOTREACHED(); |
| 75 } |
| 76 return -1; |
| 77 } |
| 78 |
| 79 int GetPort(TestServer::Type type, |
| 80 const TestServer::HTTPSOptions& options) { |
| 81 int port = GetPortBase(type, options); |
| 67 if (CommandLine::ForCurrentProcess()->HasSwitch(kTestServerShardFlag)) { | 82 if (CommandLine::ForCurrentProcess()->HasSwitch(kTestServerShardFlag)) { |
| 68 std::string shard_str(CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | 83 std::string shard_str(CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
| 69 kTestServerShardFlag)); | 84 kTestServerShardFlag)); |
| 70 int shard = -1; | 85 int shard = -1; |
| 71 if (base::StringToInt(shard_str, &shard)) { | 86 if (base::StringToInt(shard_str, &shard)) { |
| 72 port += shard; | 87 port += shard; |
| 73 } else { | 88 } else { |
| 74 LOG(FATAL) << "Got invalid " << kTestServerShardFlag << " flag value. " | 89 LOG(FATAL) << "Got invalid " << kTestServerShardFlag << " flag value. " |
| 75 << "An integer is expected."; | 90 << "An integer is expected."; |
| 76 } | 91 } |
| 77 } | 92 } |
| 78 return port; | 93 return port; |
| 79 } | 94 } |
| 80 | 95 |
| 81 std::string GetHostname(net::TestServer::Type type) { | 96 std::string GetHostname(TestServer::Type type, |
| 82 if (type == net::TestServer::TYPE_HTTPS_MISMATCHED_HOSTNAME) { | 97 const TestServer::HTTPSOptions& options) { |
| 98 if (type == TestServer::TYPE_HTTPS && |
| 99 options.server_certificate == |
| 100 TestServer::HTTPSOptions::CERT_MISMATCHED_NAME) { |
| 83 // Return a different hostname string that resolves to the same hostname. | 101 // Return a different hostname string that resolves to the same hostname. |
| 84 return "localhost"; | 102 return "localhost"; |
| 85 } | 103 } |
| 86 | 104 |
| 87 return "127.0.0.1"; | 105 return "127.0.0.1"; |
| 88 } | 106 } |
| 89 | 107 |
| 90 } // namespace | 108 } // namespace |
| 91 | 109 |
| 92 namespace net { | |
| 93 | |
| 94 #if defined(OS_MACOSX) | 110 #if defined(OS_MACOSX) |
| 95 void SetMacTestCertificate(X509Certificate* cert); | 111 void SetMacTestCertificate(X509Certificate* cert); |
| 96 #endif | 112 #endif |
| 97 | 113 |
| 114 TestServer::HTTPSOptions::HTTPSOptions() |
| 115 : server_certificate(CERT_OK), |
| 116 request_client_certificate(false), |
| 117 bulk_ciphers(HTTPSOptions::BULK_CIPHER_ANY) {} |
| 118 |
| 119 TestServer::HTTPSOptions::HTTPSOptions( |
| 120 TestServer::HTTPSOptions::ServerCertificate cert) |
| 121 : server_certificate(cert), |
| 122 request_client_certificate(false), |
| 123 bulk_ciphers(HTTPSOptions::BULK_CIPHER_ANY) {} |
| 124 |
| 125 TestServer::HTTPSOptions::~HTTPSOptions() {} |
| 126 |
| 127 FilePath TestServer::HTTPSOptions::GetCertificateFile() const { |
| 128 switch (server_certificate) { |
| 129 case CERT_OK: |
| 130 case CERT_MISMATCHED_NAME: |
| 131 return FilePath(FILE_PATH_LITERAL("ok_cert.pem")); |
| 132 case CERT_EXPIRED: |
| 133 return FilePath(FILE_PATH_LITERAL("expired_cert.pem")); |
| 134 default: |
| 135 NOTREACHED(); |
| 136 } |
| 137 return FilePath(); |
| 138 } |
| 139 |
| 98 TestServer::TestServer(Type type, const FilePath& document_root) | 140 TestServer::TestServer(Type type, const FilePath& document_root) |
| 99 : host_port_pair_(GetHostname(type), GetPort(type)), | 141 : type_(type) { |
| 100 process_handle_(base::kNullProcessHandle), | 142 Init(document_root); |
| 101 type_(type) { | 143 } |
| 144 |
| 145 TestServer::TestServer(const HTTPSOptions& https_options, |
| 146 const FilePath& document_root) |
| 147 : https_options_(https_options), type_(TYPE_HTTPS) { |
| 148 Init(document_root); |
| 149 } |
| 150 |
| 151 TestServer::~TestServer() { |
| 152 #if defined(OS_MACOSX) |
| 153 SetMacTestCertificate(NULL); |
| 154 #endif |
| 155 Stop(); |
| 156 } |
| 157 |
| 158 void TestServer::Init(const FilePath& document_root) { |
| 159 host_port_pair_ = HostPortPair(GetHostname(type_, https_options_), |
| 160 GetPort(type_, https_options_)); |
| 161 process_handle_ = base::kNullProcessHandle; |
| 162 |
| 102 FilePath src_dir; | 163 FilePath src_dir; |
| 103 PathService::Get(base::DIR_SOURCE_ROOT, &src_dir); | 164 PathService::Get(base::DIR_SOURCE_ROOT, &src_dir); |
| 104 | 165 |
| 105 document_root_ = src_dir.Append(document_root); | 166 document_root_ = src_dir.Append(document_root); |
| 106 | 167 |
| 107 certificates_dir_ = src_dir.Append(FILE_PATH_LITERAL("net")) | 168 certificates_dir_ = src_dir.Append(FILE_PATH_LITERAL("net")) |
| 108 .Append(FILE_PATH_LITERAL("data")) | 169 .Append(FILE_PATH_LITERAL("data")) |
| 109 .Append(FILE_PATH_LITERAL("ssl")) | 170 .Append(FILE_PATH_LITERAL("ssl")) |
| 110 .Append(FILE_PATH_LITERAL("certificates")); | 171 .Append(FILE_PATH_LITERAL("certificates")); |
| 111 } | 172 } |
| 112 | 173 |
| 113 TestServer::~TestServer() { | |
| 114 #if defined(OS_MACOSX) | |
| 115 SetMacTestCertificate(NULL); | |
| 116 #endif | |
| 117 Stop(); | |
| 118 } | |
| 119 | |
| 120 bool TestServer::Start() { | 174 bool TestServer::Start() { |
| 121 if (GetScheme() == "https") { | 175 if (type_ == TYPE_HTTPS) { |
| 122 if (!LoadTestRootCert()) | 176 if (!LoadTestRootCert()) |
| 123 return false; | 177 return false; |
| 124 if (!CheckCATrusted()) | 178 if (!CheckCATrusted()) |
| 125 return false; | 179 return false; |
| 126 } | 180 } |
| 127 | 181 |
| 128 // Get path to python server script | 182 // Get path to python server script |
| 129 FilePath testserver_path; | 183 FilePath testserver_path; |
| 130 if (!PathService::Get(base::DIR_SOURCE_ROOT, &testserver_path)) { | 184 if (!PathService::Get(base::DIR_SOURCE_ROOT, &testserver_path)) { |
| 131 LOG(ERROR) << "Failed to get DIR_SOURCE_ROOT"; | 185 LOG(ERROR) << "Failed to get DIR_SOURCE_ROOT"; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 170 return ret; | 224 return ret; |
| 171 } | 225 } |
| 172 | 226 |
| 173 std::string TestServer::GetScheme() const { | 227 std::string TestServer::GetScheme() const { |
| 174 switch (type_) { | 228 switch (type_) { |
| 175 case TYPE_FTP: | 229 case TYPE_FTP: |
| 176 return "ftp"; | 230 return "ftp"; |
| 177 case TYPE_HTTP: | 231 case TYPE_HTTP: |
| 178 return "http"; | 232 return "http"; |
| 179 case TYPE_HTTPS: | 233 case TYPE_HTTPS: |
| 180 case TYPE_HTTPS_CLIENT_AUTH: | |
| 181 case TYPE_HTTPS_MISMATCHED_HOSTNAME: | |
| 182 case TYPE_HTTPS_EXPIRED_CERTIFICATE: | |
| 183 return "https"; | 234 return "https"; |
| 184 default: | 235 default: |
| 185 NOTREACHED(); | 236 NOTREACHED(); |
| 186 } | 237 } |
| 187 return std::string(); | 238 return std::string(); |
| 188 } | 239 } |
| 189 | 240 |
| 190 bool TestServer::GetAddressList(AddressList* address_list) const { | 241 bool TestServer::GetAddressList(AddressList* address_list) const { |
| 191 DCHECK(address_list); | 242 DCHECK(address_list); |
| 192 | 243 |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 285 X509Certificate* cert = LoadTemporaryRootCert(GetRootCertificatePath()); | 336 X509Certificate* cert = LoadTemporaryRootCert(GetRootCertificatePath()); |
| 286 if (!cert) | 337 if (!cert) |
| 287 return false; | 338 return false; |
| 288 SetMacTestCertificate(cert); | 339 SetMacTestCertificate(cert); |
| 289 return true; | 340 return true; |
| 290 #else | 341 #else |
| 291 return true; | 342 return true; |
| 292 #endif | 343 #endif |
| 293 } | 344 } |
| 294 | 345 |
| 295 FilePath TestServer::GetCertificatePath() { | 346 bool TestServer::AddCommandLineArguments(CommandLine* command_line) const { |
| 296 switch (type_) { | 347 command_line->AppendSwitchASCII("port", |
| 297 case TYPE_FTP: | 348 base::IntToString(host_port_pair_.port())); |
| 298 case TYPE_HTTP: | 349 command_line->AppendSwitchPath("data-dir", document_root_); |
| 299 return FilePath(); | 350 |
| 300 case TYPE_HTTPS: | 351 if (type_ == TYPE_FTP) { |
| 301 case TYPE_HTTPS_CLIENT_AUTH: | 352 command_line->AppendArg("-f"); |
| 302 case TYPE_HTTPS_MISMATCHED_HOSTNAME: | 353 } else if (type_ == TYPE_HTTPS) { |
| 303 return certificates_dir_.AppendASCII("ok_cert.pem"); | 354 FilePath certificate_path(certificates_dir_); |
| 304 case TYPE_HTTPS_EXPIRED_CERTIFICATE: | 355 certificate_path = certificate_path.Append( |
| 305 return certificates_dir_.AppendASCII("expired_cert.pem"); | 356 https_options_.GetCertificateFile()); |
| 306 default: | 357 if (!file_util::PathExists(certificate_path)) { |
| 307 NOTREACHED(); | 358 LOG(ERROR) << "Certificate path " << certificate_path.value() |
| 359 << " doesn't exist. Can't launch https server."; |
| 360 return false; |
| 361 } |
| 362 command_line->AppendSwitchPath("https", certificate_path); |
| 363 |
| 364 if (https_options_.request_client_certificate) |
| 365 command_line->AppendSwitch("ssl-client-auth"); |
| 366 |
| 367 for (std::vector<FilePath>::const_iterator it = |
| 368 https_options_.client_authorities.begin(); |
| 369 it != https_options_.client_authorities.end(); ++it) { |
| 370 if (!file_util::PathExists(*it)) { |
| 371 LOG(ERROR) << "Client authority path " << it->value() |
| 372 << " doesn't exist. Can't launch https server."; |
| 373 return false; |
| 374 } |
| 375 |
| 376 command_line->AppendSwitchPath("ssl-client-ca", *it); |
| 377 } |
| 378 |
| 379 const char kBulkCipherSwitch[] = "ssl-bulk-cipher"; |
| 380 if (https_options_.bulk_ciphers & HTTPSOptions::BULK_CIPHER_RC4) |
| 381 command_line->AppendSwitchASCII(kBulkCipherSwitch, "rc4"); |
| 382 if (https_options_.bulk_ciphers & HTTPSOptions::BULK_CIPHER_AES128) |
| 383 command_line->AppendSwitchASCII(kBulkCipherSwitch, "aes128"); |
| 384 if (https_options_.bulk_ciphers & HTTPSOptions::BULK_CIPHER_AES256) |
| 385 command_line->AppendSwitchASCII(kBulkCipherSwitch, "aes256"); |
| 386 if (https_options_.bulk_ciphers & HTTPSOptions::BULK_CIPHER_3DES) |
| 387 command_line->AppendSwitchASCII(kBulkCipherSwitch, "3des"); |
| 308 } | 388 } |
| 309 return FilePath(); | 389 |
| 390 return true; |
| 310 } | 391 } |
| 311 | 392 |
| 312 } // namespace net | 393 } // namespace net |
| OLD | NEW |