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

Side by Side Diff: net/socket/ssl_server_socket_nss.cc

Issue 5746003: Defines SSLServerSocket and implements SSLServerSocketNSS (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: address comments Created 10 years 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
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "net/socket/ssl_server_socket_nss.h"
6
7 #if defined(USE_SYSTEM_SSL)
8 #include <dlfcn.h>
9 #endif
10 #if defined(OS_MACOSX)
11 #include <Security/Security.h>
12 #endif
13 #include <certdb.h>
14 #include <cryptohi.h>
15 #include <hasht.h>
16 #include <keyhi.h>
17 #include <nspr.h>
18 #include <nss.h>
19 #include <pk11pub.h>
20 #include <secerr.h>
21 #include <sechash.h>
22 #include <ssl.h>
23 #include <sslerr.h>
24 #include <sslproto.h>
25
26 #include <limits>
27
28 #include "base/crypto/rsa_private_key.h"
29 #include "base/ref_counted.h"
30 #include "net/base/io_buffer.h"
31 #include "net/base/net_errors.h"
32 #include "net/base/net_log.h"
33 #include "net/ocsp/nss_ocsp.h"
34 #include "net/socket/nss_ssl_util.h"
35 #include "net/socket/ssl_error_params.h"
36
37 static const int kRecvBufferSize = 4096;
38
39 #define GotoState(s) next_handshake_state_ = s
40
41 namespace net {
42
43 SSLServerSocket* CreateSSLServerSocket(
44 Socket* socket, X509Certificate* cert, base::RSAPrivateKey* key) {
45 // SSLConfig is currently not used in SSLServerSocketNSS so pass in the
agl 2010/12/17 18:30:50 s/so/so we/
46 // default object.
wtc 2010/12/17 18:08:04 API DESIGN: it's better to change CreateSSLServerS
Alpha Left Google 2010/12/17 20:31:12 Done.
47 return new SSLServerSocketNSS(socket, SSLConfig(), cert, key);
48 }
49
50 SSLServerSocketNSS::SSLServerSocketNSS(
51 Socket* socket,
wtc 2010/12/17 18:08:04 Nit: socket => transport_socket
Alpha Left Google 2010/12/17 20:31:12 Done.
52 const SSLConfig& ssl_config,
wtc 2010/12/17 18:08:04 Nit: list ssl_config after cert and key.
Alpha Left Google 2010/12/17 20:31:12 Done.
Alpha Left Google 2010/12/17 20:31:12 Done.
53 scoped_refptr<X509Certificate> cert,
54 base::RSAPrivateKey* key)
55 : ALLOW_THIS_IN_INITIALIZER_LIST(buffer_send_callback_(
56 this, &SSLServerSocketNSS::BufferSendComplete)),
57 ALLOW_THIS_IN_INITIALIZER_LIST(buffer_recv_callback_(
58 this, &SSLServerSocketNSS::BufferRecvComplete)),
59 transport_send_busy_(false),
60 transport_recv_busy_(false),
61 user_accept_callback_(NULL),
62 user_read_callback_(NULL),
63 user_write_callback_(NULL),
64 nss_fd_(NULL),
65 nss_bufs_(NULL),
66 transport_socket_(socket),
67 ssl_config_(ssl_config),
68 cert_(cert),
69 next_handshake_state_(STATE_NONE),
70 completed_handshake_(false) {
71 ssl_config_.false_start_enabled = false;
72 ssl_config_.ssl3_enabled = true;
73 ssl_config_.tls1_enabled = true;
74
75 // TODO(hclam): Need a better way to clone a key.
76 std::vector<uint8> key_bytes;
77 CHECK(key->ExportPrivateKey(&key_bytes));
78 key_.reset(base::RSAPrivateKey::CreateFromPrivateKeyInfo(key_bytes));
79 CHECK(key_.get());
80 }
81
82 int SSLServerSocketNSS::Init() {
83 // Initialize the NSS SSL library in a threadsafe way. This also
84 // initializes the NSS base library.
85 EnsureNSSSSLInit();
86 if (!NSS_IsInitialized())
87 return ERR_UNEXPECTED;
88 #if !defined(OS_MACOSX) && !defined(OS_WIN)
89 // We must call EnsureOCSPInit() here, on the IO thread, to get the IO loop
90 // by MessageLoopForIO::current().
91 // X509Certificate::Verify() runs on a worker thread of CertVerifier.
92 EnsureOCSPInit();
93 #endif
94
95 return OK;
96 }
97
98 int SSLServerSocketNSS::Accept(CompletionCallback* callback) {
99 net_log_.BeginEvent(NetLog::TYPE_SSL_ACCEPT, NULL);
100
101 int rv = Init();
102 if (rv != OK) {
103 LOG(ERROR) << "Failed to initialize NSS";
104 net_log_.EndEvent(NetLog::TYPE_SSL_ACCEPT, NULL);
105 return rv;
106 }
107
108 rv = InitializeSSLOptions();
109 if (rv != OK) {
110 LOG(ERROR) << "Failed to initialize SSL options";
111 net_log_.EndEvent(NetLog::TYPE_SSL_ACCEPT, NULL);
112 return rv;
113 }
114
115 // Set peer address. TODO(hclam): This should be in a separate method.
116 PRNetAddr peername;
117 memset(&peername, 0, sizeof(peername));
118 peername.raw.family = AF_INET;
119 memio_SetPeerName(nss_fd_, &peername);
120
121 GotoState(STATE_HANDSHAKE);
122 rv = DoHandshakeLoop(net::OK);
123 if (rv == ERR_IO_PENDING) {
124 user_accept_callback_ = callback;
125 } else {
126 net_log_.EndEvent(NetLog::TYPE_SSL_ACCEPT, NULL);
127 }
128
129 return rv > OK ? OK : rv;
130 }
131
132 int SSLServerSocketNSS::Read(IOBuffer* buf, int buf_len,
133 CompletionCallback* callback) {
134 DCHECK(!user_read_callback_);
135 DCHECK(!user_accept_callback_);
136 DCHECK(!user_read_buf_);
137 DCHECK(nss_bufs_);
138
139 user_read_buf_ = buf;
140 user_read_buf_len_ = buf_len;
141
142 DCHECK(completed_handshake_);
143
144 int rv = DoReadLoop(OK);
145
146 if (rv == ERR_IO_PENDING) {
147 user_read_callback_ = callback;
148 } else {
149 user_read_buf_ = NULL;
150 user_read_buf_len_ = 0;
151 }
152 return rv;
153 }
154
155 int SSLServerSocketNSS::Write(IOBuffer* buf, int buf_len,
156 CompletionCallback* callback) {
157 DCHECK(!user_write_callback_);
158 DCHECK(!user_write_buf_);
159 DCHECK(nss_bufs_);
160
161 user_write_buf_ = buf;
162 user_write_buf_len_ = buf_len;
163
164 int rv = DoWriteLoop(OK);
165
166 if (rv == ERR_IO_PENDING) {
167 user_write_callback_ = callback;
168 } else {
169 user_write_buf_ = NULL;
170 user_write_buf_len_ = 0;
171 }
172 return rv;
173 }
174
175 // static
176 // NSS calls this if an incoming certificate needs to be verified.
177 // Do nothing but return SECSuccess.
178 // This is called only in full handshake mode.
179 // Peer certificate is retrieved in HandshakeCallback() later, which is called
180 // in full handshake mode or in resumption handshake mode.
181 SECStatus SSLServerSocketNSS::OwnAuthCertHandler(void* arg,
182 PRFileDesc* socket,
183 PRBool checksig,
184 PRBool is_server) {
185 // TODO(hclam): Implement.
186 // Tell NSS to not verify the certificate.
187 return SECSuccess;
188 }
189
190 // static
191 // NSS calls this when handshake is completed.
192 // After the SSL handshake is finished we need to verify the certificate.
193 void SSLServerSocketNSS::HandshakeCallback(PRFileDesc* socket,
194 void* arg) {
195 // TODO(hclam): Implement.
196 }
197
198 int SSLServerSocketNSS::InitializeSSLOptions() {
199 // Transport connected, now hook it up to nss
200 // TODO(port): specify rx and tx buffer sizes separately
201 nss_fd_ = memio_CreateIOLayer(kRecvBufferSize);
202 if (nss_fd_ == NULL) {
203 return ERR_OUT_OF_MEMORY; // TODO(port): map NSPR error code.
204 }
205
206 // Grab pointer to buffers
207 nss_bufs_ = memio_GetSecret(nss_fd_);
208
209 /* Create SSL state machine */
210 /* Push SSL onto our fake I/O socket */
211 nss_fd_ = SSL_ImportFD(NULL, nss_fd_);
212 if (nss_fd_ == NULL) {
213 LogFailedNSSFunction(net_log_, "SSL_ImportFD", "");
214 return ERR_OUT_OF_MEMORY; // TODO(port): map NSPR/NSS error code.
215 }
216 // TODO(port): set more ssl options! Check errors!
217
218 int rv;
219
220 rv = SSL_OptionSet(nss_fd_, SSL_SECURITY, PR_TRUE);
221 if (rv != SECSuccess) {
222 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_SECURITY");
223 return ERR_UNEXPECTED;
224 }
225
226 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL2, PR_FALSE);
227 if (rv != SECSuccess) {
228 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_SSL2");
229 return ERR_UNEXPECTED;
230 }
231
232 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL3, PR_TRUE);
233 if (rv != SECSuccess) {
234 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_SSL3");
235 return ERR_UNEXPECTED;
236 }
237
238 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_TLS, ssl_config_.tls1_enabled);
239 if (rv != SECSuccess) {
240 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_TLS");
241 return ERR_UNEXPECTED;
242 }
243
244 for (std::vector<uint16>::const_iterator it =
245 ssl_config_.disabled_cipher_suites.begin();
246 it != ssl_config_.disabled_cipher_suites.end(); ++it) {
247 // This will fail if the specified cipher is not implemented by NSS, but
248 // the failure is harmless.
249 SSL_CipherPrefSet(nss_fd_, *it, PR_FALSE);
250 }
251
252 // Server socket doesn't need session tickets.
253 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SESSION_TICKETS, PR_FALSE);
254 if (rv != SECSuccess) {
255 LogFailedNSSFunction(
256 net_log_, "SSL_OptionSet", "SSL_ENABLE_SESSION_TICKETS");
257 }
258
259 // Doing this will force PR_Accept perform handshake as server.
260 rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_CLIENT, PR_FALSE);
261 if (rv != SECSuccess) {
262 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_CLIENT");
263 return ERR_UNEXPECTED;
264 }
265
266 rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_SERVER, PR_TRUE);
267 if (rv != SECSuccess) {
268 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_SERVER");
269 return ERR_UNEXPECTED;
270 }
271
272 rv = SSL_OptionSet(nss_fd_, SSL_REQUEST_CERTIFICATE, PR_FALSE);
273 if (rv != SECSuccess) {
274 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_REQUEST_CERTIFICATE");
275 return ERR_UNEXPECTED;
276 }
277
278 rv = SSL_OptionSet(nss_fd_, SSL_REQUIRE_CERTIFICATE, PR_FALSE);
279 if (rv != SECSuccess) {
280 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_REQUIRE_CERTIFICATE");
281 return ERR_UNEXPECTED;
282 }
283
284 rv = SSL_OptionSet(nss_fd_, SSL_NO_CACHE, PR_TRUE);
285 if (rv != SECSuccess) {
286 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_NO_CACHE");
287 return ERR_UNEXPECTED;
288 }
289
290 rv = SSL_AuthCertificateHook(nss_fd_, OwnAuthCertHandler, this);
291 if (rv != SECSuccess) {
292 LogFailedNSSFunction(net_log_, "SSL_AuthCertificateHook", "");
293 return ERR_UNEXPECTED;
294 }
295
296 rv = SSL_HandshakeCallback(nss_fd_, HandshakeCallback, this);
297 if (rv != SECSuccess) {
298 LogFailedNSSFunction(net_log_, "SSL_HandshakeCallback", "");
299 return ERR_UNEXPECTED;
300 }
301
302 // Assign server certificate and private key.
303 SSLKEAType cert_kea = NSS_FindCertKEAType(cert_->os_cert_handle());
304 rv = SSL_ConfigSecureServer(nss_fd_, cert_->os_cert_handle(),
305 key_->key(), cert_kea);
306 if (rv != SECSuccess) {
307 PRErrorCode prerr = PR_GetError();
308 LOG(ERROR) << "Failed to config SSL server: " << prerr;
309 LogFailedNSSFunction(net_log_, "SSL_ConfigureSecureServer", "");
310 return ERR_UNEXPECTED;
311 }
312
313 // Tell SSL we're a server; needed if not letting NSPR do socket I/O
314 rv = SSL_ResetHandshake(nss_fd_, PR_TRUE);
315 if (rv != SECSuccess) {
316 LogFailedNSSFunction(net_log_, "SSL_ResetHandshake", "");
317 return ERR_UNEXPECTED;
318 }
319
320 return OK;
321 }
322
323 // Return 0 for EOF,
324 // > 0 for bytes transferred immediately,
325 // < 0 for error (or the non-error ERR_IO_PENDING).
326 int SSLServerSocketNSS::BufferSend(void) {
327 if (transport_send_busy_)
328 return ERR_IO_PENDING;
329
330 const char* buf1;
331 const char* buf2;
332 unsigned int len1, len2;
333 memio_GetWriteParams(nss_bufs_, &buf1, &len1, &buf2, &len2);
334 const unsigned int len = len1 + len2;
335
336 int rv = 0;
337 if (len) {
338 scoped_refptr<IOBuffer> send_buffer(new IOBuffer(len));
339 memcpy(send_buffer->data(), buf1, len1);
340 memcpy(send_buffer->data() + len1, buf2, len2);
341 rv = transport_socket_->Write(send_buffer, len,
342 &buffer_send_callback_);
343 if (rv == ERR_IO_PENDING) {
344 transport_send_busy_ = true;
345 } else {
346 memio_PutWriteResult(nss_bufs_, MapErrorToNSS(rv));
347 }
348 }
349
350 return rv;
351 }
352
353 void SSLServerSocketNSS::BufferSendComplete(int result) {
354 memio_PutWriteResult(nss_bufs_, MapErrorToNSS(result));
355 transport_send_busy_ = false;
356 OnSendComplete(result);
357 }
358
359 int SSLServerSocketNSS::BufferRecv(void) {
360 if (transport_recv_busy_) return ERR_IO_PENDING;
361
362 char *buf;
363 int nb = memio_GetReadParams(nss_bufs_, &buf);
364 int rv;
365 if (!nb) {
366 // buffer too full to read into, so no I/O possible at moment
367 rv = ERR_IO_PENDING;
368 } else {
369 recv_buffer_ = new IOBuffer(nb);
370 rv = transport_socket_->Read(recv_buffer_, nb, &buffer_recv_callback_);
371 if (rv == ERR_IO_PENDING) {
372 transport_recv_busy_ = true;
373 } else {
374 if (rv > 0)
375 memcpy(buf, recv_buffer_->data(), rv);
376 memio_PutReadResult(nss_bufs_, MapErrorToNSS(rv));
377 recv_buffer_ = NULL;
378 }
379 }
380 return rv;
381 }
382
383 void SSLServerSocketNSS::BufferRecvComplete(int result) {
384 if (result > 0) {
385 char *buf;
386 memio_GetReadParams(nss_bufs_, &buf);
387 memcpy(buf, recv_buffer_->data(), result);
388 }
389 recv_buffer_ = NULL;
390 memio_PutReadResult(nss_bufs_, MapErrorToNSS(result));
391 transport_recv_busy_ = false;
392 OnRecvComplete(result);
393 }
394
395 void SSLServerSocketNSS::OnSendComplete(int result) {
wtc 2010/12/17 18:08:04 IMPORTANT: I believe OnSendComplete can be written
Alpha Left Google 2010/12/17 20:31:12 Done.
396 if (next_handshake_state_ == STATE_HANDSHAKE) {
397 // In handshake phase.
398 OnHandshakeIOComplete(result);
399 return;
400 }
401
402 int rv_write = ERR_IO_PENDING;
403 bool network_moved;
404 do {
405 if (user_write_buf_)
406 rv_write = DoPayloadWrite();
407 network_moved = DoTransportIO();
408 } while (rv_write == ERR_IO_PENDING && network_moved);
409
410 if (user_write_buf_ && rv_write != ERR_IO_PENDING)
411 DoWriteCallback(rv_write);
412 }
413
414 void SSLServerSocketNSS::OnRecvComplete(int result) {
415 if (next_handshake_state_ == STATE_HANDSHAKE) {
416 // In handshake phase.
417 OnHandshakeIOComplete(result);
418 return;
419 }
420
421 // Network layer received some data, check if client requested to read
422 // decrypted data.
423 if (!user_read_buf_ || !completed_handshake_) {
424 return;
425 }
426
427 int rv = DoReadLoop(result);
428 if (rv != ERR_IO_PENDING)
429 DoReadCallback(rv);
430 }
431
432 void SSLServerSocketNSS::OnHandshakeIOComplete(int result) {
433 int rv = DoHandshakeLoop(result);
434 if (rv != ERR_IO_PENDING) {
435 net_log_.EndEvent(net::NetLog::TYPE_SSL_ACCEPT, NULL);
436 if (user_accept_callback_)
437 DoAcceptCallback(rv);
438 }
439 }
440
441 void SSLServerSocketNSS::DoAcceptCallback(int rv) {
442 DCHECK_NE(rv, ERR_IO_PENDING);
443
444 CompletionCallback* c = user_accept_callback_;
445 user_accept_callback_ = NULL;
446 c->Run(rv > OK ? OK : rv);
447 }
448
449 void SSLServerSocketNSS::DoReadCallback(int rv) {
450 DCHECK(rv != ERR_IO_PENDING);
451 DCHECK(user_read_callback_);
452
453 // Since Run may result in Read being called, clear |user_read_callback_|
454 // up front.
455 CompletionCallback* c = user_read_callback_;
456 user_read_callback_ = NULL;
457 user_read_buf_ = NULL;
458 user_read_buf_len_ = 0;
459 c->Run(rv);
460 }
461
462 void SSLServerSocketNSS::DoWriteCallback(int rv) {
463 DCHECK(rv != ERR_IO_PENDING);
464 DCHECK(user_write_callback_);
465
466 // Since Run may result in Write being called, clear |user_write_callback_|
467 // up front.
468 CompletionCallback* c = user_write_callback_;
469 user_write_callback_ = NULL;
470 user_write_buf_ = NULL;
471 user_write_buf_len_ = 0;
472 c->Run(rv);
473 }
474
475 // Do network I/O between the given buffer and the given socket.
476 // Return true if some I/O performed, false otherwise (error or ERR_IO_PENDING)
477 bool SSLServerSocketNSS::DoTransportIO() {
478 bool network_moved = false;
479 if (nss_bufs_ != NULL) {
480 int nsent = BufferSend();
481 int nreceived = BufferRecv();
482 network_moved = (nsent > 0 || nreceived >= 0);
483 }
484 return network_moved;
485 }
486
487 int SSLServerSocketNSS::DoPayloadRead() {
488 DCHECK(user_read_buf_);
489 DCHECK_GT(user_read_buf_len_, 0);
490 int rv = PR_Read(nss_fd_, user_read_buf_->data(), user_read_buf_len_);
491 if (rv >= 0)
492 return rv;
493 PRErrorCode prerr = PR_GetError();
494 if (prerr == PR_WOULD_BLOCK_ERROR) {
495 return ERR_IO_PENDING;
496 }
497 rv = MapNSSError(prerr);
498 net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR,
499 make_scoped_refptr(new SSLErrorParams(rv, prerr)));
500 return rv;
501 }
502
503 int SSLServerSocketNSS::DoPayloadWrite() {
504 DCHECK(user_write_buf_);
505 int rv = PR_Write(nss_fd_, user_write_buf_->data(), user_write_buf_len_);
506 if (rv >= 0)
507 return rv;
508 PRErrorCode prerr = PR_GetError();
509 if (prerr == PR_WOULD_BLOCK_ERROR) {
510 return ERR_IO_PENDING;
511 }
512 rv = MapNSSError(prerr);
513 net_log_.AddEvent(NetLog::TYPE_SSL_WRITE_ERROR,
514 make_scoped_refptr(new SSLErrorParams(rv, prerr)));
515 return rv;
516 }
517
518 int SSLServerSocketNSS::DoHandshakeLoop(int last_io_result) {
519 bool network_moved;
520 int rv = last_io_result;
521 do {
522 // Default to STATE_NONE for next state.
523 // (This is a quirk carried over from the windows
524 // implementation. It makes reading the logs a bit harder.)
525 // State handlers can and often do call GotoState just
526 // to stay in the current state.
527 State state = next_handshake_state_;
528 GotoState(STATE_NONE);
529 switch (state) {
530 case STATE_NONE:
531 // we're just pumping data between the buffer and the network
532 break;
533 case STATE_HANDSHAKE:
534 rv = DoHandshake();
535 break;
536 default:
537 rv = ERR_UNEXPECTED;
538 LOG(DFATAL) << "unexpected state " << state;
539 break;
540 }
541
542 // Do the actual network I/O
543 network_moved = DoTransportIO();
544 } while ((rv != ERR_IO_PENDING || network_moved) &&
545 next_handshake_state_ != STATE_NONE);
546 return rv;
547 }
548
549 int SSLServerSocketNSS::DoReadLoop(int result) {
550 DCHECK(completed_handshake_);
551 DCHECK(next_handshake_state_ == STATE_NONE);
552
553 if (result < 0)
554 return result;
555
556 if (!nss_bufs_) {
557 LOG(DFATAL) << "!nss_bufs_";
558 int rv = ERR_UNEXPECTED;
559 net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR,
560 make_scoped_refptr(new SSLErrorParams(rv, 0)));
561 return rv;
562 }
563
564 bool network_moved;
565 int rv;
566 do {
567 rv = DoPayloadRead();
568 network_moved = DoTransportIO();
569 } while (rv == ERR_IO_PENDING && network_moved);
570 return rv;
571 }
572
573 int SSLServerSocketNSS::DoWriteLoop(int result) {
574 DCHECK(completed_handshake_);
575 DCHECK(next_handshake_state_ == STATE_NONE);
576
577 if (result < 0)
578 return result;
579
580 if (!nss_bufs_) {
581 LOG(DFATAL) << "!nss_bufs_";
582 int rv = ERR_UNEXPECTED;
583 net_log_.AddEvent(NetLog::TYPE_SSL_WRITE_ERROR,
584 make_scoped_refptr(new SSLErrorParams(rv, 0)));
585 return rv;
586 }
587
588 bool network_moved;
589 int rv;
590 do {
591 rv = DoPayloadWrite();
592 network_moved = DoTransportIO();
593 } while (rv == ERR_IO_PENDING && network_moved);
594 return rv;
595 }
596
597 int SSLServerSocketNSS::DoHandshake() {
598 int net_error = net::OK;
599 SECStatus rv = SSL_ForceHandshake(nss_fd_);
600
601 if (rv == SECSuccess) {
602 completed_handshake_ = true;
603 } else {
604 PRErrorCode prerr = PR_GetError();
605 net_error = MapHandshakeError(prerr);
606
607 // If not done, stay in this state
608 if (net_error == ERR_IO_PENDING) {
609 GotoState(STATE_HANDSHAKE);
610 } else {
611 LOG(ERROR) << "handshake failed; NSS error code " << prerr
612 << ", net_error " << net_error;
613 net_log_.AddEvent(
614 NetLog::TYPE_SSL_HANDSHAKE_ERROR,
615 make_scoped_refptr(new SSLErrorParams(net_error, prerr)));
616 }
617 }
618 return net_error;
619 }
620
621 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698