Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(47)

Side by Side Diff: net/base/ssl_test_util.cc

Issue 16207: Make ssl_client_socket_unittest use a local server (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/base/ssl_test_util.h ('k') | net/base/tcp_pinger.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 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 <string> 5 #include <string>
6 #include <algorithm> 6 #include <algorithm>
7 7
8 #include "net/base/ssl_test_util.h"
9
8 #include "build/build_config.h" 10 #include "build/build_config.h"
9 11
10 #if defined(OS_WIN) 12 #if defined(OS_WIN)
11 #include <windows.h> 13 #include <windows.h>
12 #include <wincrypt.h> 14 #include <wincrypt.h>
13 #elif defined(OS_LINUX) 15 #elif defined(OS_LINUX)
14 #include <nspr.h> 16 #include <nspr.h>
15 #include <nss.h> 17 #include <nss.h>
16 #include <secerr.h> 18 #include <secerr.h>
17 // Work around https://bugzilla.mozilla.org/show_bug.cgi?id=455424 19 // Work around https://bugzilla.mozilla.org/show_bug.cgi?id=455424
18 // until NSS 3.12.2 comes out and we update to it. 20 // until NSS 3.12.2 comes out and we update to it.
19 #define Lock FOO_NSS_Lock 21 #define Lock FOO_NSS_Lock
20 #include <ssl.h> 22 #include <ssl.h>
21 #include <sslerr.h> 23 #include <sslerr.h>
22 #include <pk11pub.h> 24 #include <pk11pub.h>
23 #undef Lock 25 #undef Lock
24 #include "base/nss_init.h" 26 #include "base/nss_init.h"
25 #endif 27 #endif
26 28
27 #include "base/file_util.h" 29 #include "base/file_util.h"
28 #include "base/logging.h" 30 #include "base/logging.h"
29 #include "base/path_service.h" 31 #include "base/path_service.h"
32 #include "base/platform_thread.h"
33 #include "base/string_util.h"
34 #include "net/base/tcp_pinger.h"
35 #include "net/base/host_resolver.h"
36 #include "net/base/tcp_client_socket.h"
37 #include "net/base/test_completion_callback.h"
38 #include "testing/platform_test.h"
30 39
31 #include "net/base/ssl_test_util.h" 40 namespace {
32
33 // static
34 const char SSLTestUtil::kHostName[] = "127.0.0.1";
35 const int SSLTestUtil::kOKHTTPSPort = 9443;
36 const int SSLTestUtil::kBadHTTPSPort = 9666;
37
38 // The issuer name of the cert that should be trusted for the test to work.
39 const wchar_t SSLTestUtil::kCertIssuerName[] = L"Test CA";
40 41
41 #if defined(OS_LINUX) 42 #if defined(OS_LINUX)
42 static CERTCertificate* LoadTemporaryCert(const FilePath& filename) { 43 static CERTCertificate* LoadTemporaryCert(const FilePath& filename) {
43 base::EnsureNSSInit(); 44 base::EnsureNSSInit();
44 45
45 std::string rawcert; 46 std::string rawcert;
46 if (!file_util::ReadFileToString(filename.ToWStringHack(), &rawcert)) { 47 if (!file_util::ReadFileToString(filename.ToWStringHack(), &rawcert)) {
47 LOG(ERROR) << "Can't load certificate " << filename.ToWStringHack(); 48 LOG(ERROR) << "Can't load certificate " << filename.ToWStringHack();
48 return NULL; 49 return NULL;
49 } 50 }
(...skipping 10 matching lines...) Expand all
60 CERTCertTrust trust; 61 CERTCertTrust trust;
61 int rv = CERT_DecodeTrustString(&trust, const_cast<char *>("TCu,Cu,Tu")); 62 int rv = CERT_DecodeTrustString(&trust, const_cast<char *>("TCu,Cu,Tu"));
62 if (rv != SECSuccess) { 63 if (rv != SECSuccess) {
63 LOG(ERROR) << "Can't decode trust string"; 64 LOG(ERROR) << "Can't decode trust string";
64 CERT_DestroyCertificate(cert); 65 CERT_DestroyCertificate(cert);
65 return NULL; 66 return NULL;
66 } 67 }
67 68
68 rv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), cert, &trust); 69 rv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), cert, &trust);
69 if (rv != SECSuccess) { 70 if (rv != SECSuccess) {
70 LOG(ERROR) << "Can't change trust for certificate " 71 LOG(ERROR) << "Can't change trust for certificate "
71 << filename.ToWStringHack(); 72 << filename.ToWStringHack();
72 CERT_DestroyCertificate(cert); 73 CERT_DestroyCertificate(cert);
73 return NULL; 74 return NULL;
74 } 75 }
75 76
76 LOG(INFO) << "Loaded temporary certificate " << filename.ToWStringHack(); 77 // TODO(dkegel): figure out how to get this to only happen once?
77 return cert; 78 return cert;
78 } 79 }
79 #endif 80 #endif
80 81
81 SSLTestUtil::SSLTestUtil() { 82 } // namespace
82 PathService::Get(base::DIR_SOURCE_ROOT, &cert_dir_); 83
83 cert_dir_ = cert_dir_.AppendASCII("net"); 84 namespace net {
84 cert_dir_ = cert_dir_.AppendASCII("data"); 85
85 cert_dir_ = cert_dir_.AppendASCII("ssl"); 86 // static
86 cert_dir_ = cert_dir_.AppendASCII("certificates"); 87 const char TestServerLauncher::kHostName[] = "127.0.0.1";
87 88 const char TestServerLauncher::kMismatchedHostName[] = "localhost";
89 const int TestServerLauncher::kOKHTTPSPort = 9443;
90 const int TestServerLauncher::kBadHTTPSPort = 9666;
91
92 // The issuer name of the cert that should be trusted for the test to work.
93 const wchar_t TestServerLauncher::kCertIssuerName[] = L"Test CA";
94
95 TestServerLauncher::TestServerLauncher() : process_handle_(NULL)
88 #if defined(OS_LINUX) 96 #if defined(OS_LINUX)
89 cert_ = reinterpret_cast<PrivateCERTCertificate*>( 97 , cert_(NULL)
98 #endif
99 {
100 PathService::Get(base::DIR_SOURCE_ROOT, &data_dir_);
101 data_dir_ = data_dir_.Append(FILE_PATH_LITERAL("net"))
102 .Append(FILE_PATH_LITERAL("data"))
103 .Append(FILE_PATH_LITERAL("ssl"));
104 cert_dir_ = data_dir_.Append(FILE_PATH_LITERAL("certificates"));
105 }
106
107 namespace {
108
109 void AppendToPythonPath(FilePath dir) {
110 // Do nothing if dir already on path.
111
112 #if defined(OS_WIN)
113 const wchar_t kPythonPath[] = L"PYTHONPATH";
114 // FIXME(dkegel): handle longer PYTHONPATH variables
115 wchar_t oldpath[4096];
116 if (GetEnvironmentVariable(kPythonPath, oldpath, sizeof(oldpath)) == 0) {
117 SetEnvironmentVariableW(kPythonPath, dir.value().c_str());
118 } else if (!wcsstr(oldpath, dir.value().c_str())) {
119 std::wstring newpath(oldpath);
120 newpath.append(L":");
121 newpath.append(dir.value());
122 SetEnvironmentVariableW(kPythonPath, newpath.c_str());
123 }
124 #elif defined(OS_POSIX)
125 const char kPythonPath[] = "PYTHONPATH";
126 const char* oldpath = getenv(kPythonPath);
127 if (!oldpath) {
128 setenv(kPythonPath, dir.value().c_str(), 1);
129 } else if (!strstr(oldpath, dir.value().c_str())) {
130 std::string newpath(oldpath);
131 newpath.append(":");
132 newpath.append(dir.value());
133 setenv(kPythonPath, newpath.c_str(), 1);
134 }
135 #endif
136 }
137
138 } // end namespace
139
140 void TestServerLauncher::SetPythonPath() {
141 FilePath third_party_dir;
142 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &third_party_dir));
143 third_party_dir = third_party_dir.Append(FILE_PATH_LITERAL("third_party"));
144
145 AppendToPythonPath(third_party_dir.Append(FILE_PATH_LITERAL("tlslite")));
146 AppendToPythonPath(third_party_dir.Append(FILE_PATH_LITERAL("pyftpdlib")));
147 }
148
149 bool TestServerLauncher::Start(Protocol protocol,
150 const std::string& host_name, int port,
151 const FilePath& document_root,
152 const FilePath& cert_path) {
153 if (!TestServerLauncher::CheckCATrusted())
154 return false;
155
156 std::string port_str = IntToString(port);
157
158 // Get path to python server script
159 FilePath testserver_path;
160 if (!PathService::Get(base::DIR_SOURCE_ROOT, &testserver_path))
161 return false;
162 testserver_path = testserver_path
163 .Append(FILE_PATH_LITERAL("net"))
164 .Append(FILE_PATH_LITERAL("tools"))
165 .Append(FILE_PATH_LITERAL("testserver"))
166 .Append(FILE_PATH_LITERAL("testserver.py"));
167
168 FilePath test_data_directory;
169 PathService::Get(base::DIR_SOURCE_ROOT, &test_data_directory);
170 test_data_directory = test_data_directory.Append(document_root);
171
172 #if defined(OS_LINUX)
173 if (!cert_ && !cert_path.value().empty()) {
174 cert_ = reinterpret_cast<PrivateCERTCertificate*>(
90 LoadTemporaryCert(GetRootCertPath())); 175 LoadTemporaryCert(GetRootCertPath()));
91 DCHECK(cert_); 176 DCHECK(cert_);
92 #endif 177 }
93 } 178 #endif
94 179
95 SSLTestUtil::~SSLTestUtil() { 180 SetPythonPath();
181
182 #if defined(OS_WIN)
183 // Get path to python interpreter
184 if (!PathService::Get(base::DIR_SOURCE_ROOT, &python_runtime_))
185 return false;
186 python_runtime_ = python_runtime_
187 .Append(FILE_PATH_LITERAL("third_party"))
188 .Append(FILE_PATH_LITERAL("python_24"))
189 .Append(FILE_PATH_LITERAL("python.exe"));
190
191 std::wstring command_line =
192 L"\"" + python_runtime_.ToWStringHack() + L"\" " +
193 L"\"" + testserver_path.ToWStringHack() +
194 L"\" --port=" + UTF8ToWide(port_str) +
195 L" --data-dir=\"" + test_data_directory.ToWStringHack() + L"\"";
196 if (protocol == ProtoFTP)
197 command_line.append(L" -f");
198 if (!cert_path.value().empty()) {
199 command_line.append(L" --https=\"");
200 command_line.append(cert_path.ToWStringHack());
201 command_line.append(L"\"");
202 }
203
204 if (!base::LaunchApp(command_line, false, true, &process_handle_)) {
205 LOG(ERROR) << "Failed to launch " << command_line;
206 return false;
207 }
208 #elif defined(OS_POSIX)
209 std::vector<std::string> command_line;
210 command_line.push_back("python");
211 command_line.push_back(WideToUTF8(testserver_path.ToWStringHack()));
212 command_line.push_back("--port=" + port_str);
213 command_line.push_back("--data-dir=" +
214 WideToUTF8(test_data_directory.ToWStringHack()));
215 if (protocol == ProtoFTP)
216 command_line.push_back("-f");
217 if (!cert_path.value().empty())
218 command_line.push_back("--https=" + WideToUTF8(cert_path.ToWStringHack()));
219
220 base::file_handle_mapping_vector no_mappings;
221 LOG(INFO) << "Trying to launch " << command_line[0] << " ...";
222 if (!base::LaunchApp(command_line, no_mappings, false, &process_handle_)) {
223 LOG(ERROR) << "Failed to launch " << command_line[0] << " ...";
224 return false;
225 }
226 #endif
227
228 // Let the server start, then verify that it's up.
229 // Our server is Python, and takes about 500ms to start
230 // up the first time, and about 200ms after that.
231 if (!Wait(host_name, port)) {
232 LOG(ERROR) << "Failed to connect to server";
233 Stop();
234 return false;
235 }
236
237 LOG(INFO) << "Started on port " << port_str;
238 return true;
239 }
240
241 bool TestServerLauncher::Wait(const std::string& host_name, int port) {
242 // Verify that the webserver is actually started.
243 // Otherwise tests can fail if they run faster than Python can start.
244 net::AddressList addr;
245 net::HostResolver resolver;
246 int rv = resolver.Resolve(host_name, port, &addr, NULL);
247 if (rv != net::OK)
248 return false;
249
250 net::TCPPinger pinger(addr);
251 rv = pinger.Ping();
252 return rv == net::OK;
253 }
254
255 void TestServerLauncher::Stop() {
256 if (!process_handle_)
257 return;
258
259 base::KillProcess(process_handle_, 1, true);
260
261 #if defined(OS_WIN)
262 CloseHandle(process_handle_);
263 #endif
264
265 process_handle_ = NULL;
266 LOG(INFO) << "Stopped.";
267 }
268
269 TestServerLauncher::~TestServerLauncher() {
96 #if defined(OS_LINUX) 270 #if defined(OS_LINUX)
97 if (cert_) 271 if (cert_)
98 CERT_DestroyCertificate(reinterpret_cast<CERTCertificate*>(cert_)); 272 CERT_DestroyCertificate(reinterpret_cast<CERTCertificate*>(cert_));
99 #endif 273 #endif
100 } 274 Stop();
101 275 }
102 FilePath SSLTestUtil::GetRootCertPath() { 276
277 FilePath TestServerLauncher::GetRootCertPath() {
103 FilePath path(cert_dir_); 278 FilePath path(cert_dir_);
104 path = path.AppendASCII("root_ca_cert.crt"); 279 path = path.AppendASCII("root_ca_cert.crt");
105 return path; 280 return path;
106 } 281 }
107 282
108 FilePath SSLTestUtil::GetOKCertPath() { 283 FilePath TestServerLauncher::GetOKCertPath() {
109 FilePath path(cert_dir_); 284 FilePath path(cert_dir_);
110 path = path.AppendASCII("ok_cert.pem"); 285 path = path.AppendASCII("ok_cert.pem");
111 return path; 286 return path;
112 } 287 }
113 288
114 FilePath SSLTestUtil::GetExpiredCertPath() { 289 FilePath TestServerLauncher::GetExpiredCertPath() {
115 FilePath path(cert_dir_); 290 FilePath path(cert_dir_);
116 path = path.AppendASCII("expired_cert.pem"); 291 path = path.AppendASCII("expired_cert.pem");
117 return path; 292 return path;
118 } 293 }
119 294
120 bool SSLTestUtil::CheckCATrusted() { 295 bool TestServerLauncher::CheckCATrusted() {
121 // TODO(port): Port either this or LoadTemporaryCert to MacOSX. 296 // TODO(port): Port either this or LoadTemporaryCert to MacOSX.
122 #if defined(OS_WIN) 297 #if defined(OS_WIN)
123 HCERTSTORE cert_store = CertOpenSystemStore(NULL, L"ROOT"); 298 HCERTSTORE cert_store = CertOpenSystemStore(NULL, L"ROOT");
124 if (!cert_store) { 299 if (!cert_store) {
125 LOG(ERROR) << " could not open trusted root CA store"; 300 LOG(ERROR) << " could not open trusted root CA store";
126 return false; 301 return false;
127 } 302 }
128 PCCERT_CONTEXT cert = 303 PCCERT_CONTEXT cert =
129 CertFindCertificateInStore(cert_store, 304 CertFindCertificateInStore(cert_store,
130 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 305 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
131 0, 306 0,
132 CERT_FIND_ISSUER_STR, 307 CERT_FIND_ISSUER_STR,
133 kCertIssuerName, 308 kCertIssuerName,
134 NULL); 309 NULL);
135 if (cert) 310 if (cert)
136 CertFreeCertificateContext(cert); 311 CertFreeCertificateContext(cert);
137 CertCloseStore(cert_store, 0); 312 CertCloseStore(cert_store, 0);
138 313
139 if (!cert) { 314 if (!cert) {
140 LOG(ERROR) << " TEST CONFIGURATION ERROR: you need to import the test ca " 315 LOG(ERROR) << " TEST CONFIGURATION ERROR: you need to import the test ca "
141 "certificate to your trusted roots for this test to work. " 316 "certificate to your trusted roots for this test to work. "
142 "For more info visit:\n" 317 "For more info visit:\n"
143 "http://dev.chromium.org/developers/testing\n"; 318 "http://dev.chromium.org/developers/testing\n";
144 return false; 319 return false;
145 } 320 }
146 #endif 321 #endif
147 return true; 322 return true;
148 } 323 }
324
325 } // namespace net
326
OLDNEW
« no previous file with comments | « net/base/ssl_test_util.h ('k') | net/base/tcp_pinger.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698