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

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

Powered by Google App Engine
This is Rietveld 408576698