OLD | NEW |
---|---|
(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 // OpenSSL binding for SSLClientSocket. The class layout and general principle | |
6 // of operation is derived from SSLClientSocketNSS. | |
7 | |
8 #include "net/socket/ssl_client_socket_openssl.h" | |
9 | |
10 #include <openssl/ssl.h> | |
11 #include <openssl/err.h> | |
12 | |
13 #include "net/base/net_errors.h" | |
14 #include "net/base/ssl_connection_status_flags.h" | |
15 #include "net/base/ssl_info.h" | |
16 #include "net/base/test_certificate_data.h" // TODO(joth): Remove!! | |
17 | |
18 namespace net { | |
19 | |
20 namespace { | |
21 | |
22 // Enable this to see logging for state machine state transitions. | |
wtc
2010/09/28 18:08:35
Nit: this comment says "Enable this", but the ifde
joth
2010/09/29 11:58:54
Done. (It was left as was for consistency with NSS
| |
23 #if 1 | |
24 #define GotoState(s) next_handshake_state_ = s | |
25 #else | |
26 #define GotoState(s) do { LOG(INFO) << (void *)this << " " << __FUNCTION__ << \ | |
27 " jump to state " << s; \ | |
28 next_handshake_state_ = s; } while (0) | |
29 #endif | |
30 | |
31 const size_t kMaxRecvBufferSize = 4096; | |
32 | |
33 void MaybeLogSSLError() { | |
34 int error_num; | |
35 while ((error_num = ERR_get_error()) != 0) { | |
36 char buf[128]; // this buffer must be at least 120 chars long. | |
37 ERR_error_string_n(error_num, buf, arraysize(buf)); | |
38 LOG(INFO) << "SSL error " << error_num << ": " << buf; | |
39 } | |
40 } | |
41 | |
42 int MapOpenSSLError(int err) { | |
43 switch (err) { | |
44 case SSL_ERROR_WANT_READ: | |
45 case SSL_ERROR_WANT_WRITE: | |
46 return ERR_IO_PENDING; | |
47 default: | |
48 MaybeLogSSLError(); | |
49 // TODO(joth): Implement full mapping. | |
50 return err < 0 ? ERR_SSL_PROTOCOL_ERROR : err; | |
wtc
2010/09/28 18:08:35
BUG:
This error-mapping function should never re
joth
2010/09/29 11:58:54
Done.
| |
51 } | |
52 } | |
53 | |
54 } // namespace | |
55 | |
56 SSL_CTX* SSLClientSocketOpenSSL::g_ctx = NULL; | |
wtc
2010/09/28 18:08:35
Nit: we usually add a comment
// static
before s
joth
2010/09/29 11:58:54
Done.
| |
57 | |
58 SSLClientSocketOpenSSL::SSLClientSocketOpenSSL( | |
59 ClientSocketHandle* transport_socket, | |
60 const std::string& hostname, | |
61 const SSLConfig& ssl_config) | |
62 : ALLOW_THIS_IN_INITIALIZER_LIST(buffer_send_callback_( | |
63 this, &SSLClientSocketOpenSSL::BufferSendComplete)), | |
64 ALLOW_THIS_IN_INITIALIZER_LIST(buffer_recv_callback_( | |
65 this, &SSLClientSocketOpenSSL::BufferRecvComplete)), | |
66 transport_send_busy_(false), | |
67 transport_recv_busy_(false), | |
68 user_connect_callback_(NULL), | |
69 user_read_callback_(NULL), | |
70 user_write_callback_(NULL), | |
71 client_auth_cert_needed_(false), | |
72 ssl_(NULL), | |
73 transport_bio_(NULL), | |
74 transport_(transport_socket), | |
75 hostname_(hostname), | |
76 ssl_config_(ssl_config), | |
77 completed_handshake_(false), | |
78 net_log_(transport_socket->socket()->NetLog()) { | |
79 } | |
80 | |
81 SSLClientSocketOpenSSL::~SSLClientSocketOpenSSL() { | |
82 Disconnect(); | |
83 } | |
84 | |
85 bool SSLClientSocketOpenSSL::InitOpenSSL() { | |
86 if (g_ctx) { | |
wtc
2010/09/28 18:08:35
Nit: in the net module we usually omit curly brace
joth
2010/09/29 11:58:54
Done.
| |
87 return true; | |
88 } | |
89 | |
90 SSL_load_error_strings(); | |
91 MaybeLogSSLError(); | |
92 SSL_library_init(); | |
93 MaybeLogSSLError(); | |
94 | |
95 g_ctx = SSL_CTX_new(TLSv1_client_method()); | |
96 | |
97 if (!g_ctx) { | |
98 MaybeLogSSLError(); | |
99 return false; | |
100 } | |
101 | |
102 SSL_CTX_set_verify(g_ctx, SSL_VERIFY_NONE, NULL /*callback*/); | |
103 | |
104 return true; | |
105 } | |
106 | |
107 bool SSLClientSocketOpenSSL::Init() { | |
108 DCHECK(g_ctx); | |
109 ssl_ = SSL_new(g_ctx); | |
110 if (!ssl_) { | |
111 MaybeLogSSLError(); | |
112 return false; | |
113 } | |
114 | |
115 if (!SSL_set_tlsext_host_name(ssl_, hostname_.c_str())) { | |
116 MaybeLogSSLError(); | |
117 return false; | |
118 } | |
119 | |
120 BIO* ssl_bio = NULL; | |
121 // TODO(joth): Provide explicit write buffer sizes, rather than use defaults? | |
122 if (!BIO_new_bio_pair(&ssl_bio, 0, &transport_bio_, 0)) { | |
123 MaybeLogSSLError(); | |
124 return false; | |
125 } | |
126 DCHECK(ssl_bio); | |
127 DCHECK(transport_bio_); | |
128 | |
129 SSL_set_bio(ssl_, ssl_bio, ssl_bio); | |
130 | |
131 return true; | |
132 } | |
133 | |
134 // SSLClientSocket methods | |
135 | |
136 void SSLClientSocketOpenSSL::GetSSLInfo(SSLInfo* ssl_info) { | |
137 // Chrome DCHECKs that https pages provide a valid cert. For now (whilst in | |
138 // early dev) we just create a spoof cert. | |
139 // TODO(joth): implement X509Certificate for OpenSSL and remove this hack. | |
140 LOG(WARNING) << "Filling in certificate with bogus content"; | |
141 ssl_info->Reset(); | |
142 ssl_info->cert = X509Certificate::CreateFromBytes( | |
wtc
2010/09/28 18:08:35
There is a better way to construct a fake certific
joth
2010/09/29 11:58:54
Hmmm couldn't find any reference to X509 in gears
wtc
2010/09/29 18:21:05
I should have said more about how to find those fi
| |
143 reinterpret_cast<const char*>(google_der), sizeof(google_der)); | |
144 DCHECK(ssl_info->cert); | |
145 ssl_info->cert_status = 0; | |
146 ssl_info->security_bits = 128; | |
147 | |
148 ssl_info->connection_status = | |
149 ((TLS1_CK_RSA_EXPORT1024_WITH_DES_CBC_SHA) & | |
wtc
2010/09/28 18:08:35
Nit: this fake cipher suite is inconsistent with t
joth
2010/09/29 11:58:54
Done. (although, I kind of like that this bogus in
| |
150 SSL_CONNECTION_CIPHERSUITE_MASK) << SSL_CONNECTION_CIPHERSUITE_SHIFT; | |
151 | |
152 // Silence compiler about unused vars. | |
153 (void)google_der; | |
154 (void)webkit_der; | |
155 (void)thawte_der; | |
156 (void)paypal_null_der; | |
157 } | |
158 | |
159 void SSLClientSocketOpenSSL::GetSSLCertRequestInfo( | |
160 SSLCertRequestInfo* cert_request_info) { | |
161 NOTREACHED(); | |
162 } | |
163 | |
164 SSLClientSocket::NextProtoStatus SSLClientSocketOpenSSL::GetNextProto( | |
165 std::string* proto) { | |
166 proto->clear(); | |
167 return kNextProtoUnsupported; | |
168 } | |
169 | |
170 void SSLClientSocketOpenSSL::DoReadCallback(int rv) { | |
171 // Since Run may result in Read being called, clear |user_read_callback_| | |
172 // up front. | |
173 CompletionCallback* c = user_read_callback_; | |
174 user_read_callback_ = NULL; | |
175 user_read_buf_ = NULL; | |
176 user_read_buf_len_ = 0; | |
177 c->Run(rv); | |
178 } | |
179 | |
180 void SSLClientSocketOpenSSL::DoWriteCallback(int rv) { | |
181 // Since Run may result in Write being called, clear |user_write_callback_| | |
182 // up front. | |
183 CompletionCallback* c = user_write_callback_; | |
184 user_write_callback_ = NULL; | |
185 user_write_buf_ = NULL; | |
186 user_write_buf_len_ = 0; | |
187 c->Run(rv); | |
188 } | |
189 | |
190 // ClientSocket methods | |
191 | |
192 // Should make a proper return error | |
193 // and call the callback with more info | |
wtc
2010/09/28 18:08:35
Nit: my C++ readability review told me to use
prop
joth
2010/09/29 11:58:54
Removed obsolete comment.
| |
194 int SSLClientSocketOpenSSL::Connect(CompletionCallback* callback) { | |
195 net_log_.BeginEvent(NetLog::TYPE_SSL_CONNECT, NULL); | |
196 | |
197 if (!InitOpenSSL()) { | |
198 net_log_.EndEvent(NetLog::TYPE_SSL_CONNECT, NULL); | |
199 return ERR_UNEXPECTED; | |
200 } | |
201 | |
202 // Set up new ssl object | |
203 if (!Init()) { | |
204 net_log_.EndEvent(NetLog::TYPE_SSL_CONNECT, NULL); | |
205 return ERR_UNEXPECTED; | |
206 } | |
207 | |
208 // Set SSL to client mode. Handshake happens in the loop below. | |
209 SSL_set_connect_state(ssl_); | |
210 | |
211 GotoState(STATE_HANDSHAKE); | |
212 int rv = DoHandshakeLoop(net::OK); | |
213 if (rv == ERR_IO_PENDING) { | |
214 user_connect_callback_ = callback; | |
215 } else { | |
216 net_log_.EndEvent(NetLog::TYPE_SSL_CONNECT, NULL); | |
217 } | |
218 | |
219 // (Optional) Tell loadlog we are starting and store a ref | |
wtc
2010/09/28 18:08:35
I have no idea what this comment means ...
joth
2010/09/29 11:58:54
Removed obsolete comment.
| |
220 return rv > OK ? OK : rv; | |
221 } | |
222 | |
223 void SSLClientSocketOpenSSL::Disconnect() { | |
224 // Null all callbacks | |
225 // Delete all buffers | |
226 transport_send_busy_ = false; | |
227 send_buffer_ = NULL; | |
228 transport_recv_busy_ = false; | |
229 recv_buffer_ = NULL; | |
230 | |
231 user_connect_callback_ = NULL; | |
232 user_read_callback_ = NULL; | |
233 user_write_callback_ = NULL; | |
234 user_read_buf_ = NULL; | |
235 user_read_buf_len_ = 0; | |
236 user_write_buf_ = NULL; | |
237 user_write_buf_len_ = 0; | |
238 | |
239 client_certs_.clear(); | |
240 client_auth_cert_needed_ = false; | |
241 | |
242 if (ssl_) { | |
243 SSL_free(ssl_); | |
244 ssl_ = NULL; | |
245 } | |
246 if (transport_bio_) { | |
247 BIO_free(transport_bio_); | |
248 transport_bio_ = NULL; | |
249 } | |
250 | |
251 completed_handshake_ = false; | |
252 transport_->socket()->Disconnect(); | |
253 } | |
254 | |
255 int SSLClientSocketOpenSSL::DoHandshakeLoop(int last_io_result) { | |
256 bool network_moved; | |
257 int rv = last_io_result; | |
258 do { | |
259 // Default to STATE_NONE for next state. | |
260 // (This is a quirk carried over from the windows | |
261 // implementation. It makes reading the logs a bit harder.) | |
262 // State handlers can and often do call GotoState just | |
263 // to stay in the current state. | |
264 State state = next_handshake_state_; | |
265 GotoState(STATE_NONE); | |
266 switch (state) { | |
267 case STATE_NONE: | |
268 // we're just pumping data between the buffer and the network | |
269 break; | |
270 case STATE_HANDSHAKE: | |
271 rv = DoHandshake(); | |
272 break; | |
273 #if 0 // TODO(joth): Implement cert verification. | |
274 case STATE_VERIFY_CERT: | |
275 DCHECK(rv == OK); | |
276 rv = DoVerifyCert(rv); | |
277 break; | |
278 case STATE_VERIFY_CERT_COMPLETE: | |
279 rv = DoVerifyCertComplete(rv); | |
280 break; | |
281 #endif | |
282 default: | |
283 rv = ERR_UNEXPECTED; | |
284 NOTREACHED() << "unexpected state" << state; | |
285 break; | |
286 } | |
287 | |
288 // To avoid getting an ERR_IO_PENDING here after handshake complete. | |
289 if (next_handshake_state_ == STATE_NONE) | |
290 break; | |
291 | |
292 // Do the actual network I/O | |
293 network_moved = DoTransportIO(); | |
294 } while ((rv != ERR_IO_PENDING || network_moved) && | |
295 next_handshake_state_ != STATE_NONE); | |
296 return rv; | |
297 } | |
298 | |
299 int SSLClientSocketOpenSSL::DoHandshake() { | |
300 int net_error = net::OK; | |
301 int rv = SSL_do_handshake(ssl_); | |
302 | |
303 if (rv == 1) { | |
304 // SSL handshake is completed. Let's verify the certificate. | |
305 // For now we are done, certificates not implemented yet | |
306 // TODO(joth): Implement certificates | |
307 GotoState(STATE_NONE); | |
308 completed_handshake_ = true; | |
309 } else { | |
310 int ssl_error = SSL_get_error(ssl_, rv); | |
311 | |
312 // If not done, stay in this state | |
313 GotoState(STATE_HANDSHAKE); | |
314 net_error = MapOpenSSLError(ssl_error); | |
315 } | |
316 | |
317 return net_error; | |
318 } | |
319 | |
320 bool SSLClientSocketOpenSSL::DoTransportIO() { | |
321 bool network_moved = false; | |
322 int nsent = BufferSend(); | |
323 int nreceived = BufferRecv(); | |
324 network_moved = (nsent > 0 || nreceived >= 0); | |
325 return network_moved; | |
326 } | |
327 | |
328 int SSLClientSocketOpenSSL::BufferSend(void) { | |
329 if (transport_send_busy_) | |
330 return ERR_IO_PENDING; | |
331 | |
332 if (!send_buffer_) { | |
333 // Get a fresh send buffer out of the send BIO. | |
334 size_t max_read = BIO_ctrl_pending(transport_bio_); | |
335 if (max_read > 0) { | |
336 send_buffer_ = new DrainableIOBuffer(new IOBuffer(max_read), max_read); | |
337 int read_bytes = BIO_read(transport_bio_, send_buffer_->data(), max_read); | |
338 DCHECK_GT(read_bytes, 0); | |
339 CHECK_EQ(static_cast<int>(max_read), read_bytes); | |
340 } | |
341 } | |
342 | |
343 int rv = 0; | |
344 while (send_buffer_) { | |
345 rv = transport_->socket()->Write(send_buffer_, | |
346 send_buffer_->BytesRemaining(), | |
347 &buffer_send_callback_); | |
348 if (rv == ERR_IO_PENDING) { | |
349 transport_send_busy_ = true; | |
350 return rv; | |
351 } | |
352 TransportWriteComplete(rv); | |
353 } | |
354 return rv; | |
355 } | |
356 | |
357 void SSLClientSocketOpenSSL::BufferSendComplete(int result) { | |
358 transport_send_busy_ = false; | |
359 TransportWriteComplete(result); | |
360 OnSendComplete(result); | |
361 } | |
362 | |
363 void SSLClientSocketOpenSSL::TransportWriteComplete(int result) { | |
364 if (result < 0) { | |
365 // Got a socket write error; close the BIO to indicate this upward. | |
366 (void)BIO_shutdown_wr(transport_bio_); | |
367 send_buffer_ = NULL; | |
368 } else { | |
369 DCHECK(send_buffer_); | |
370 send_buffer_->DidConsume(result); | |
371 DCHECK_GE(send_buffer_->BytesRemaining(), 0); | |
372 if (send_buffer_->BytesRemaining() <= 0) | |
373 send_buffer_ = NULL; | |
374 } | |
375 } | |
376 | |
377 int SSLClientSocketOpenSSL::BufferRecv(void) { | |
378 if (transport_recv_busy_) | |
379 return ERR_IO_PENDING; | |
380 | |
381 size_t max_write = BIO_ctrl_get_write_guarantee(transport_bio_); | |
382 if (max_write > kMaxRecvBufferSize) | |
383 max_write = kMaxRecvBufferSize; | |
384 | |
385 if (!max_write) { | |
386 return ERR_IO_PENDING; | |
387 } | |
388 recv_buffer_ = new IOBuffer(max_write); | |
389 int rv = transport_->socket()->Read(recv_buffer_, max_write, | |
390 &buffer_recv_callback_); | |
391 if (rv == ERR_IO_PENDING) { | |
392 transport_recv_busy_ = true; | |
393 } else { | |
394 TransportReadComplete(rv); | |
395 } | |
396 return rv; | |
397 } | |
398 | |
399 void SSLClientSocketOpenSSL::BufferRecvComplete(int result) { | |
400 TransportReadComplete(result); | |
401 OnRecvComplete(result); | |
402 } | |
403 | |
404 void SSLClientSocketOpenSSL::TransportReadComplete(int result) { | |
405 if (result > 0) { | |
406 int ret = BIO_write(transport_bio_, recv_buffer_->data(), result); | |
407 // A write into a memory BIO should always succeed. | |
408 CHECK_EQ(result, ret); | |
409 } else { | |
410 // Received end of file: bubble it up to the SSL layer via the BIO. | |
411 BIO_set_mem_eof_return(transport_bio_, 0); | |
412 (void)BIO_shutdown_wr(transport_bio_); | |
413 } | |
414 recv_buffer_ = NULL; | |
415 transport_recv_busy_ = false; | |
416 } | |
417 | |
418 void SSLClientSocketOpenSSL::DoConnectCallback(int rv) { | |
419 CompletionCallback* c = user_connect_callback_; | |
420 user_connect_callback_ = NULL; | |
421 c->Run(rv > OK ? OK : rv); | |
422 } | |
423 | |
424 void SSLClientSocketOpenSSL::OnHandshakeIOComplete(int result) { | |
425 int rv = DoHandshakeLoop(result); | |
426 if (rv != ERR_IO_PENDING) { | |
427 net_log_.EndEvent(NetLog::TYPE_SSL_CONNECT, NULL); | |
428 DoConnectCallback(rv); | |
429 } | |
430 } | |
431 | |
432 void SSLClientSocketOpenSSL::OnSendComplete(int result) { | |
433 if (next_handshake_state_ != STATE_NONE) { | |
434 // In handshake phase. | |
435 OnHandshakeIOComplete(result); | |
436 return; | |
437 } | |
438 | |
439 // OnSendComplete may need to call DoPayloadRead while the renegotiation | |
440 // handshake is in progress. | |
441 int rv_read = ERR_IO_PENDING; | |
442 int rv_write = ERR_IO_PENDING; | |
443 bool network_moved; | |
444 do { | |
445 if (user_read_buf_) | |
446 rv_read = DoPayloadRead(); | |
447 if (user_write_buf_) | |
448 rv_write = DoPayloadWrite(); | |
449 network_moved = DoTransportIO(); | |
450 } while (rv_read == ERR_IO_PENDING && | |
451 rv_write == ERR_IO_PENDING && | |
452 network_moved); | |
453 | |
454 if (user_read_buf_ && rv_read != ERR_IO_PENDING) | |
455 DoReadCallback(rv_read); | |
456 if (user_write_buf_ && rv_write != ERR_IO_PENDING) | |
457 DoWriteCallback(rv_write); | |
458 } | |
459 | |
460 void SSLClientSocketOpenSSL::OnRecvComplete(int result) { | |
461 if (next_handshake_state_ != STATE_NONE) { | |
462 // In handshake phase. | |
463 OnHandshakeIOComplete(result); | |
464 return; | |
465 } | |
466 | |
467 // Network layer received some data, check if client requested to read | |
468 // decrypted data. | |
469 if (!user_read_buf_) { | |
470 return; | |
471 } | |
472 | |
473 int rv = DoReadLoop(result); | |
474 if (rv != ERR_IO_PENDING) | |
475 DoReadCallback(rv); | |
476 } | |
477 | |
478 bool SSLClientSocketOpenSSL::IsConnected() const { | |
479 bool ret = completed_handshake_ && transport_->socket()->IsConnected(); | |
480 return ret; | |
481 } | |
482 | |
483 bool SSLClientSocketOpenSSL::IsConnectedAndIdle() const { | |
484 bool ret = completed_handshake_ && transport_->socket()->IsConnectedAndIdle(); | |
485 return ret; | |
486 } | |
487 | |
488 int SSLClientSocketOpenSSL::GetPeerAddress(AddressList* addressList) const { | |
489 return transport_->socket()->GetPeerAddress(addressList); | |
490 } | |
491 | |
492 const BoundNetLog& SSLClientSocketOpenSSL::NetLog() const { | |
493 return net_log_; | |
494 } | |
495 | |
496 void SSLClientSocketOpenSSL::SetSubresourceSpeculation() { | |
497 if (transport_.get() && transport_->socket()) { | |
498 transport_->socket()->SetSubresourceSpeculation(); | |
499 } else { | |
500 NOTREACHED(); | |
501 } | |
502 } | |
503 | |
504 void SSLClientSocketOpenSSL::SetOmniboxSpeculation() { | |
505 if (transport_.get() && transport_->socket()) { | |
506 transport_->socket()->SetOmniboxSpeculation(); | |
507 } else { | |
508 NOTREACHED(); | |
509 } | |
510 } | |
511 | |
512 bool SSLClientSocketOpenSSL::WasEverUsed() const { | |
513 if (transport_.get() && transport_->socket()) { | |
514 return transport_->socket()->WasEverUsed(); | |
515 } | |
516 NOTREACHED(); | |
517 return false; | |
518 } | |
519 | |
520 // Socket methods | |
521 | |
522 int SSLClientSocketOpenSSL::Read(IOBuffer* buf, | |
523 int buf_len, | |
524 CompletionCallback* callback) { | |
525 user_read_buf_ = buf; | |
526 user_read_buf_len_ = buf_len; | |
527 | |
528 int rv = DoReadLoop(OK); | |
529 | |
530 if (rv == ERR_IO_PENDING) { | |
531 user_read_callback_ = callback; | |
532 } else { | |
533 user_read_buf_ = NULL; | |
534 user_read_buf_len_ = 0; | |
535 } | |
536 | |
537 return rv; | |
538 } | |
539 | |
540 int SSLClientSocketOpenSSL::DoReadLoop(int result) { | |
541 if (result < 0) | |
542 return result; | |
543 | |
544 bool network_moved; | |
545 int rv; | |
546 do { | |
547 rv = DoPayloadRead(); | |
548 network_moved = DoTransportIO(); | |
549 } while (rv == ERR_IO_PENDING && network_moved); | |
550 | |
551 return rv; | |
552 } | |
553 | |
554 int SSLClientSocketOpenSSL::Write(IOBuffer* buf, | |
555 int buf_len, | |
556 CompletionCallback* callback) { | |
557 user_write_buf_ = buf; | |
558 user_write_buf_len_ = buf_len; | |
559 | |
560 int rv = DoWriteLoop(OK); | |
561 | |
562 if (rv == ERR_IO_PENDING) { | |
563 user_write_callback_ = callback; | |
564 } else { | |
565 user_write_buf_ = NULL; | |
566 user_write_buf_len_ = 0; | |
567 } | |
568 | |
569 return rv; | |
570 } | |
571 | |
572 int SSLClientSocketOpenSSL::DoWriteLoop(int result) { | |
573 if (result < 0) | |
574 return result; | |
575 | |
576 bool network_moved; | |
577 int rv; | |
578 do { | |
579 rv = DoPayloadWrite(); | |
580 network_moved = DoTransportIO(); | |
581 } while (rv == ERR_IO_PENDING && network_moved); | |
582 | |
583 return rv; | |
584 } | |
585 | |
586 bool SSLClientSocketOpenSSL::SetReceiveBufferSize(int32 size) { | |
587 return transport_->socket()->SetReceiveBufferSize(size); | |
588 } | |
589 | |
590 bool SSLClientSocketOpenSSL::SetSendBufferSize(int32 size) { | |
591 return transport_->socket()->SetSendBufferSize(size); | |
592 } | |
593 | |
594 int SSLClientSocketOpenSSL::DoPayloadRead() { | |
595 int rv = SSL_read(ssl_, user_read_buf_->data(), user_read_buf_len_); | |
596 if (client_auth_cert_needed_) { | |
597 // We don't need to invalidate the non-client-authenticated SSL session | |
598 // because the server will renegotiate anyway. | |
599 return ERR_SSL_CLIENT_AUTH_CERT_NEEDED; | |
600 } | |
601 | |
602 if (rv >= 0) { | |
603 return rv; | |
604 } | |
605 | |
606 int err = SSL_get_error(ssl_, rv); | |
607 return MapOpenSSLError(err); | |
608 } | |
609 | |
610 int SSLClientSocketOpenSSL::DoPayloadWrite() { | |
611 int rv = SSL_write(ssl_, user_write_buf_->data(), user_write_buf_len_); | |
612 | |
613 if (rv >= 0) { | |
614 return rv; | |
615 } | |
616 | |
617 int err = SSL_get_error(ssl_, rv); | |
618 return MapOpenSSLError(err); | |
619 } | |
620 | |
621 } // namespace net | |
OLD | NEW |