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

Side by Side Diff: webrtc/base/schanneladapter.cc

Issue 1383253002: Get rid of SCHANNEL code. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Rebase Created 5 years, 2 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
« no previous file with comments | « webrtc/base/schanneladapter.h ('k') | webrtc/base/ssladapter.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "webrtc/base/win32.h"
12 #define SECURITY_WIN32
13 #include <security.h>
14 #include <schannel.h>
15
16 #include <algorithm>
17 #include <iomanip>
18 #include <vector>
19
20 #include "webrtc/base/common.h"
21 #include "webrtc/base/logging.h"
22 #include "webrtc/base/schanneladapter.h"
23 #include "webrtc/base/sec_buffer.h"
24 #include "webrtc/base/thread.h"
25
26 namespace rtc {
27
28 /////////////////////////////////////////////////////////////////////////////
29 // SChannelAdapter
30 /////////////////////////////////////////////////////////////////////////////
31
32 extern const ConstantLabel SECURITY_ERRORS[];
33
34 const ConstantLabel SCHANNEL_BUFFER_TYPES[] = {
35 KLABEL(SECBUFFER_EMPTY), // 0
36 KLABEL(SECBUFFER_DATA), // 1
37 KLABEL(SECBUFFER_TOKEN), // 2
38 KLABEL(SECBUFFER_PKG_PARAMS), // 3
39 KLABEL(SECBUFFER_MISSING), // 4
40 KLABEL(SECBUFFER_EXTRA), // 5
41 KLABEL(SECBUFFER_STREAM_TRAILER), // 6
42 KLABEL(SECBUFFER_STREAM_HEADER), // 7
43 KLABEL(SECBUFFER_MECHLIST), // 11
44 KLABEL(SECBUFFER_MECHLIST_SIGNATURE), // 12
45 KLABEL(SECBUFFER_TARGET), // 13
46 KLABEL(SECBUFFER_CHANNEL_BINDINGS), // 14
47 LASTLABEL
48 };
49
50 void DescribeBuffer(LoggingSeverity severity, const char* prefix,
51 const SecBuffer& sb) {
52 LOG_V(severity)
53 << prefix
54 << "(" << sb.cbBuffer
55 << ", " << FindLabel(sb.BufferType & ~SECBUFFER_ATTRMASK,
56 SCHANNEL_BUFFER_TYPES)
57 << ", " << sb.pvBuffer << ")";
58 }
59
60 void DescribeBuffers(LoggingSeverity severity, const char* prefix,
61 const SecBufferDesc* sbd) {
62 if (!LOG_CHECK_LEVEL_V(severity))
63 return;
64 LOG_V(severity) << prefix << "(";
65 for (size_t i=0; i<sbd->cBuffers; ++i) {
66 DescribeBuffer(severity, " ", sbd->pBuffers[i]);
67 }
68 LOG_V(severity) << ")";
69 }
70
71 const ULONG SSL_FLAGS_DEFAULT = ISC_REQ_ALLOCATE_MEMORY
72 | ISC_REQ_CONFIDENTIALITY
73 | ISC_REQ_EXTENDED_ERROR
74 | ISC_REQ_INTEGRITY
75 | ISC_REQ_REPLAY_DETECT
76 | ISC_REQ_SEQUENCE_DETECT
77 | ISC_REQ_STREAM;
78 //| ISC_REQ_USE_SUPPLIED_CREDS;
79
80 typedef std::vector<char> SChannelBuffer;
81
82 struct SChannelAdapter::SSLImpl {
83 CredHandle cred;
84 CtxtHandle ctx;
85 bool cred_init, ctx_init;
86 SChannelBuffer inbuf, outbuf, readable;
87 SecPkgContext_StreamSizes sizes;
88
89 SSLImpl() : cred_init(false), ctx_init(false) { }
90 };
91
92 SChannelAdapter::SChannelAdapter(AsyncSocket* socket)
93 : SSLAdapter(socket), state_(SSL_NONE), mode_(SSL_MODE_TLS),
94 restartable_(false), signal_close_(false), message_pending_(false),
95 impl_(new SSLImpl) {
96 }
97
98 SChannelAdapter::~SChannelAdapter() {
99 Cleanup();
100 }
101
102 void
103 SChannelAdapter::SetMode(SSLMode mode) {
104 // SSL_MODE_DTLS isn't supported.
105 ASSERT(mode == SSL_MODE_TLS);
106 mode_ = mode;
107 }
108
109 int
110 SChannelAdapter::StartSSL(const char* hostname, bool restartable) {
111 if (state_ != SSL_NONE)
112 return -1;
113
114 if (mode_ != SSL_MODE_TLS)
115 return -1;
116
117 ssl_host_name_ = hostname;
118 restartable_ = restartable;
119
120 if (socket_->GetState() != Socket::CS_CONNECTED) {
121 state_ = SSL_WAIT;
122 return 0;
123 }
124
125 state_ = SSL_CONNECTING;
126 if (int err = BeginSSL()) {
127 Error("BeginSSL", err, false);
128 return err;
129 }
130
131 return 0;
132 }
133
134 int
135 SChannelAdapter::BeginSSL() {
136 LOG(LS_VERBOSE) << "BeginSSL: " << ssl_host_name_;
137 ASSERT(state_ == SSL_CONNECTING);
138
139 SECURITY_STATUS ret;
140
141 SCHANNEL_CRED sc_cred = { 0 };
142 sc_cred.dwVersion = SCHANNEL_CRED_VERSION;
143 //sc_cred.dwMinimumCipherStrength = 128; // Note: use system default
144 sc_cred.dwFlags = SCH_CRED_NO_DEFAULT_CREDS | SCH_CRED_AUTO_CRED_VALIDATION;
145
146 ret = AcquireCredentialsHandle(NULL, const_cast<LPTSTR>(UNISP_NAME),
147 SECPKG_CRED_OUTBOUND, NULL, &sc_cred, NULL,
148 NULL, &impl_->cred, NULL);
149 if (ret != SEC_E_OK) {
150 LOG(LS_ERROR) << "AcquireCredentialsHandle error: "
151 << ErrorName(ret, SECURITY_ERRORS);
152 return ret;
153 }
154 impl_->cred_init = true;
155
156 if (LOG_CHECK_LEVEL(LS_VERBOSE)) {
157 SecPkgCred_CipherStrengths cipher_strengths = { 0 };
158 ret = QueryCredentialsAttributes(&impl_->cred,
159 SECPKG_ATTR_CIPHER_STRENGTHS,
160 &cipher_strengths);
161 if (SUCCEEDED(ret)) {
162 LOG(LS_VERBOSE) << "SChannel cipher strength: "
163 << cipher_strengths.dwMinimumCipherStrength << " - "
164 << cipher_strengths.dwMaximumCipherStrength;
165 }
166
167 SecPkgCred_SupportedAlgs supported_algs = { 0 };
168 ret = QueryCredentialsAttributes(&impl_->cred,
169 SECPKG_ATTR_SUPPORTED_ALGS,
170 &supported_algs);
171 if (SUCCEEDED(ret)) {
172 LOG(LS_VERBOSE) << "SChannel supported algorithms:";
173 for (DWORD i=0; i<supported_algs.cSupportedAlgs; ++i) {
174 ALG_ID alg_id = supported_algs.palgSupportedAlgs[i];
175 PCCRYPT_OID_INFO oinfo = CryptFindOIDInfo(CRYPT_OID_INFO_ALGID_KEY,
176 &alg_id, 0);
177 LPCWSTR alg_name = (NULL != oinfo) ? oinfo->pwszName : L"Unknown";
178 LOG(LS_VERBOSE) << " " << ToUtf8(alg_name) << " (" << alg_id << ")";
179 }
180 CSecBufferBase::FreeSSPI(supported_algs.palgSupportedAlgs);
181 }
182 }
183
184 ULONG flags = SSL_FLAGS_DEFAULT, ret_flags = 0;
185 if (ignore_bad_cert())
186 flags |= ISC_REQ_MANUAL_CRED_VALIDATION;
187
188 CSecBufferBundle<2, CSecBufferBase::FreeSSPI> sb_out;
189 ret = InitializeSecurityContextA(&impl_->cred, NULL,
190 const_cast<char*>(ssl_host_name_.c_str()),
191 flags, 0, 0, NULL, 0,
192 &impl_->ctx, sb_out.desc(),
193 &ret_flags, NULL);
194 if (SUCCEEDED(ret))
195 impl_->ctx_init = true;
196 return ProcessContext(ret, NULL, sb_out.desc());
197 }
198
199 int
200 SChannelAdapter::ContinueSSL() {
201 LOG(LS_VERBOSE) << "ContinueSSL";
202 ASSERT(state_ == SSL_CONNECTING);
203
204 SECURITY_STATUS ret;
205
206 CSecBufferBundle<2> sb_in;
207 sb_in[0].BufferType = SECBUFFER_TOKEN;
208 sb_in[0].cbBuffer = static_cast<unsigned long>(impl_->inbuf.size());
209 sb_in[0].pvBuffer = &impl_->inbuf[0];
210 //DescribeBuffers(LS_VERBOSE, "Input Buffer ", sb_in.desc());
211
212 ULONG flags = SSL_FLAGS_DEFAULT, ret_flags = 0;
213 if (ignore_bad_cert())
214 flags |= ISC_REQ_MANUAL_CRED_VALIDATION;
215
216 CSecBufferBundle<2, CSecBufferBase::FreeSSPI> sb_out;
217 ret = InitializeSecurityContextA(&impl_->cred, &impl_->ctx,
218 const_cast<char*>(ssl_host_name_.c_str()),
219 flags, 0, 0, sb_in.desc(), 0,
220 NULL, sb_out.desc(),
221 &ret_flags, NULL);
222 return ProcessContext(ret, sb_in.desc(), sb_out.desc());
223 }
224
225 int
226 SChannelAdapter::ProcessContext(long int status, _SecBufferDesc* sbd_in,
227 _SecBufferDesc* sbd_out) {
228 if (status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED &&
229 status != SEC_E_INCOMPLETE_MESSAGE) {
230 LOG(LS_ERROR)
231 << "InitializeSecurityContext error: "
232 << ErrorName(status, SECURITY_ERRORS);
233 }
234 //if (sbd_in)
235 // DescribeBuffers(LS_VERBOSE, "Input Buffer ", sbd_in);
236 //if (sbd_out)
237 // DescribeBuffers(LS_VERBOSE, "Output Buffer ", sbd_out);
238
239 if (status == SEC_E_INCOMPLETE_MESSAGE) {
240 // Wait for more input from server.
241 return Flush();
242 }
243
244 if (FAILED(status)) {
245 // We can't continue. Common errors:
246 // SEC_E_CERT_EXPIRED - Typically, this means the computer clock is wrong.
247 return status;
248 }
249
250 // Note: we check both input and output buffers for SECBUFFER_EXTRA.
251 // Experience shows it appearing in the input, but the documentation claims
252 // it should appear in the output.
253 size_t extra = 0;
254 if (sbd_in) {
255 for (size_t i=0; i<sbd_in->cBuffers; ++i) {
256 SecBuffer& buffer = sbd_in->pBuffers[i];
257 if (buffer.BufferType == SECBUFFER_EXTRA) {
258 extra += buffer.cbBuffer;
259 }
260 }
261 }
262 if (sbd_out) {
263 for (size_t i=0; i<sbd_out->cBuffers; ++i) {
264 SecBuffer& buffer = sbd_out->pBuffers[i];
265 if (buffer.BufferType == SECBUFFER_EXTRA) {
266 extra += buffer.cbBuffer;
267 } else if (buffer.BufferType == SECBUFFER_TOKEN) {
268 impl_->outbuf.insert(impl_->outbuf.end(),
269 reinterpret_cast<char*>(buffer.pvBuffer),
270 reinterpret_cast<char*>(buffer.pvBuffer) + buffer.cbBuffer);
271 }
272 }
273 }
274
275 if (extra) {
276 ASSERT(extra <= impl_->inbuf.size());
277 size_t consumed = impl_->inbuf.size() - extra;
278 memmove(&impl_->inbuf[0], &impl_->inbuf[consumed], extra);
279 impl_->inbuf.resize(extra);
280 } else {
281 impl_->inbuf.clear();
282 }
283
284 if (SEC_I_CONTINUE_NEEDED == status) {
285 // Send data to server and wait for response.
286 // Note: ContinueSSL will result in a Flush, anyway.
287 return impl_->inbuf.empty() ? Flush() : ContinueSSL();
288 }
289
290 if (SEC_E_OK == status) {
291 LOG(LS_VERBOSE) << "QueryContextAttributes";
292 status = QueryContextAttributes(&impl_->ctx, SECPKG_ATTR_STREAM_SIZES,
293 &impl_->sizes);
294 if (FAILED(status)) {
295 LOG(LS_ERROR) << "QueryContextAttributes error: "
296 << ErrorName(status, SECURITY_ERRORS);
297 return status;
298 }
299
300 state_ = SSL_CONNECTED;
301
302 if (int err = DecryptData()) {
303 return err;
304 } else if (int err = Flush()) {
305 return err;
306 } else {
307 // If we decrypted any data, queue up a notification here
308 PostEvent();
309 // Signal our connectedness
310 AsyncSocketAdapter::OnConnectEvent(this);
311 }
312 return 0;
313 }
314
315 if (SEC_I_INCOMPLETE_CREDENTIALS == status) {
316 // We don't support client authentication in schannel.
317 return status;
318 }
319
320 // We don't expect any other codes
321 ASSERT(false);
322 return status;
323 }
324
325 int
326 SChannelAdapter::DecryptData() {
327 SChannelBuffer& inbuf = impl_->inbuf;
328 SChannelBuffer& readable = impl_->readable;
329
330 while (!inbuf.empty()) {
331 CSecBufferBundle<4> in_buf;
332 in_buf[0].BufferType = SECBUFFER_DATA;
333 in_buf[0].cbBuffer = static_cast<unsigned long>(inbuf.size());
334 in_buf[0].pvBuffer = &inbuf[0];
335
336 //DescribeBuffers(LS_VERBOSE, "Decrypt In ", in_buf.desc());
337 SECURITY_STATUS status = DecryptMessage(&impl_->ctx, in_buf.desc(), 0, 0);
338 //DescribeBuffers(LS_VERBOSE, "Decrypt Out ", in_buf.desc());
339
340 // Note: We are explicitly treating SEC_E_OK, SEC_I_CONTEXT_EXPIRED, and
341 // any other successful results as continue.
342 if (SUCCEEDED(status)) {
343 size_t data_len = 0, extra_len = 0;
344 for (size_t i=0; i<in_buf.desc()->cBuffers; ++i) {
345 if (in_buf[i].BufferType == SECBUFFER_DATA) {
346 data_len += in_buf[i].cbBuffer;
347 readable.insert(readable.end(),
348 reinterpret_cast<char*>(in_buf[i].pvBuffer),
349 reinterpret_cast<char*>(in_buf[i].pvBuffer) + in_buf[i].cbBuffer);
350 } else if (in_buf[i].BufferType == SECBUFFER_EXTRA) {
351 extra_len += in_buf[i].cbBuffer;
352 }
353 }
354 // There is a bug on Win2K where SEC_I_CONTEXT_EXPIRED is misclassified.
355 if ((data_len == 0) && (inbuf[0] == 0x15)) {
356 status = SEC_I_CONTEXT_EXPIRED;
357 }
358 if (extra_len) {
359 size_t consumed = inbuf.size() - extra_len;
360 memmove(&inbuf[0], &inbuf[consumed], extra_len);
361 inbuf.resize(extra_len);
362 } else {
363 inbuf.clear();
364 }
365 // TODO: Handle SEC_I_CONTEXT_EXPIRED to do clean shutdown
366 if (status != SEC_E_OK) {
367 LOG(LS_INFO) << "DecryptMessage returned continuation code: "
368 << ErrorName(status, SECURITY_ERRORS);
369 }
370 continue;
371 }
372
373 if (status == SEC_E_INCOMPLETE_MESSAGE) {
374 break;
375 } else {
376 return status;
377 }
378 }
379
380 return 0;
381 }
382
383 void
384 SChannelAdapter::Cleanup() {
385 if (impl_->ctx_init)
386 DeleteSecurityContext(&impl_->ctx);
387 if (impl_->cred_init)
388 FreeCredentialsHandle(&impl_->cred);
389 delete impl_;
390 }
391
392 void
393 SChannelAdapter::PostEvent() {
394 // Check if there's anything notable to signal
395 if (impl_->readable.empty() && !signal_close_)
396 return;
397
398 // Only one post in the queue at a time
399 if (message_pending_)
400 return;
401
402 if (Thread* thread = Thread::Current()) {
403 message_pending_ = true;
404 thread->Post(this);
405 } else {
406 LOG(LS_ERROR) << "No thread context available for SChannelAdapter";
407 ASSERT(false);
408 }
409 }
410
411 void
412 SChannelAdapter::Error(const char* context, int err, bool signal) {
413 LOG(LS_WARNING) << "SChannelAdapter::Error("
414 << context << ", "
415 << ErrorName(err, SECURITY_ERRORS) << ")";
416 state_ = SSL_ERROR;
417 SetError(err);
418 if (signal)
419 AsyncSocketAdapter::OnCloseEvent(this, err);
420 }
421
422 int
423 SChannelAdapter::Read() {
424 char buffer[4096];
425 SChannelBuffer& inbuf = impl_->inbuf;
426 while (true) {
427 int ret = AsyncSocketAdapter::Recv(buffer, sizeof(buffer));
428 if (ret > 0) {
429 inbuf.insert(inbuf.end(), buffer, buffer + ret);
430 } else if (GetError() == EWOULDBLOCK) {
431 return 0; // Blocking
432 } else {
433 return GetError();
434 }
435 }
436 }
437
438 int
439 SChannelAdapter::Flush() {
440 int result = 0;
441 size_t pos = 0;
442 SChannelBuffer& outbuf = impl_->outbuf;
443 while (pos < outbuf.size()) {
444 int sent = AsyncSocketAdapter::Send(&outbuf[pos], outbuf.size() - pos);
445 if (sent > 0) {
446 pos += sent;
447 } else if (GetError() == EWOULDBLOCK) {
448 break; // Blocking
449 } else {
450 result = GetError();
451 break;
452 }
453 }
454 if (int remainder = static_cast<int>(outbuf.size() - pos)) {
455 memmove(&outbuf[0], &outbuf[pos], remainder);
456 outbuf.resize(remainder);
457 } else {
458 outbuf.clear();
459 }
460 return result;
461 }
462
463 //
464 // AsyncSocket Implementation
465 //
466
467 int
468 SChannelAdapter::Send(const void* pv, size_t cb) {
469 switch (state_) {
470 case SSL_NONE:
471 return AsyncSocketAdapter::Send(pv, cb);
472
473 case SSL_WAIT:
474 case SSL_CONNECTING:
475 SetError(EWOULDBLOCK);
476 return SOCKET_ERROR;
477
478 case SSL_CONNECTED:
479 break;
480
481 case SSL_ERROR:
482 default:
483 return SOCKET_ERROR;
484 }
485
486 size_t written = 0;
487 SChannelBuffer& outbuf = impl_->outbuf;
488 while (written < cb) {
489 const size_t encrypt_len = std::min<size_t>(cb - written,
490 impl_->sizes.cbMaximumMessage);
491
492 CSecBufferBundle<4> out_buf;
493 out_buf[0].BufferType = SECBUFFER_STREAM_HEADER;
494 out_buf[0].cbBuffer = impl_->sizes.cbHeader;
495 out_buf[1].BufferType = SECBUFFER_DATA;
496 out_buf[1].cbBuffer = static_cast<unsigned long>(encrypt_len);
497 out_buf[2].BufferType = SECBUFFER_STREAM_TRAILER;
498 out_buf[2].cbBuffer = impl_->sizes.cbTrailer;
499
500 size_t packet_len = out_buf[0].cbBuffer
501 + out_buf[1].cbBuffer
502 + out_buf[2].cbBuffer;
503
504 SChannelBuffer message;
505 message.resize(packet_len);
506 out_buf[0].pvBuffer = &message[0];
507 out_buf[1].pvBuffer = &message[out_buf[0].cbBuffer];
508 out_buf[2].pvBuffer = &message[out_buf[0].cbBuffer + out_buf[1].cbBuffer];
509
510 memcpy(out_buf[1].pvBuffer,
511 static_cast<const char*>(pv) + written,
512 encrypt_len);
513
514 //DescribeBuffers(LS_VERBOSE, "Encrypt In ", out_buf.desc());
515 SECURITY_STATUS res = EncryptMessage(&impl_->ctx, 0, out_buf.desc(), 0);
516 //DescribeBuffers(LS_VERBOSE, "Encrypt Out ", out_buf.desc());
517
518 if (FAILED(res)) {
519 Error("EncryptMessage", res, false);
520 return SOCKET_ERROR;
521 }
522
523 // We assume that the header and data segments do not change length,
524 // or else encrypting the concatenated packet in-place is wrong.
525 ASSERT(out_buf[0].cbBuffer == impl_->sizes.cbHeader);
526 ASSERT(out_buf[1].cbBuffer == static_cast<unsigned long>(encrypt_len));
527
528 // However, the length of the trailer may change due to padding.
529 ASSERT(out_buf[2].cbBuffer <= impl_->sizes.cbTrailer);
530
531 packet_len = out_buf[0].cbBuffer
532 + out_buf[1].cbBuffer
533 + out_buf[2].cbBuffer;
534
535 written += encrypt_len;
536 outbuf.insert(outbuf.end(), &message[0], &message[packet_len-1]+1);
537 }
538
539 if (int err = Flush()) {
540 state_ = SSL_ERROR;
541 SetError(err);
542 return SOCKET_ERROR;
543 }
544
545 return static_cast<int>(written);
546 }
547
548 int
549 SChannelAdapter::Recv(void* pv, size_t cb) {
550 switch (state_) {
551 case SSL_NONE:
552 return AsyncSocketAdapter::Recv(pv, cb);
553
554 case SSL_WAIT:
555 case SSL_CONNECTING:
556 SetError(EWOULDBLOCK);
557 return SOCKET_ERROR;
558
559 case SSL_CONNECTED:
560 break;
561
562 case SSL_ERROR:
563 default:
564 return SOCKET_ERROR;
565 }
566
567 SChannelBuffer& readable = impl_->readable;
568 if (readable.empty()) {
569 SetError(EWOULDBLOCK);
570 return SOCKET_ERROR;
571 }
572 size_t read = std::min(cb, readable.size());
573 memcpy(pv, &readable[0], read);
574 if (size_t remaining = readable.size() - read) {
575 memmove(&readable[0], &readable[read], remaining);
576 readable.resize(remaining);
577 } else {
578 readable.clear();
579 }
580
581 PostEvent();
582 return static_cast<int>(read);
583 }
584
585 int
586 SChannelAdapter::Close() {
587 if (!impl_->readable.empty()) {
588 LOG(WARNING) << "SChannelAdapter::Close with readable data";
589 // Note: this isn't strictly an error, but we're using it temporarily to
590 // track bugs.
591 //ASSERT(false);
592 }
593 if (state_ == SSL_CONNECTED) {
594 DWORD token = SCHANNEL_SHUTDOWN;
595 CSecBufferBundle<1> sb_in;
596 sb_in[0].BufferType = SECBUFFER_TOKEN;
597 sb_in[0].cbBuffer = sizeof(token);
598 sb_in[0].pvBuffer = &token;
599 ApplyControlToken(&impl_->ctx, sb_in.desc());
600 // TODO: In theory, to do a nice shutdown, we need to begin shutdown
601 // negotiation with more calls to InitializeSecurityContext. Since the
602 // socket api doesn't support nice shutdown at this point, we don't bother.
603 }
604 Cleanup();
605 impl_ = new SSLImpl;
606 state_ = restartable_ ? SSL_WAIT : SSL_NONE;
607 signal_close_ = false;
608 message_pending_ = false;
609 return AsyncSocketAdapter::Close();
610 }
611
612 Socket::ConnState
613 SChannelAdapter::GetState() const {
614 if (signal_close_)
615 return CS_CONNECTED;
616 ConnState state = socket_->GetState();
617 if ((state == CS_CONNECTED)
618 && ((state_ == SSL_WAIT) || (state_ == SSL_CONNECTING)))
619 state = CS_CONNECTING;
620 return state;
621 }
622
623 void
624 SChannelAdapter::OnConnectEvent(AsyncSocket* socket) {
625 LOG(LS_VERBOSE) << "SChannelAdapter::OnConnectEvent";
626 if (state_ != SSL_WAIT) {
627 ASSERT(state_ == SSL_NONE);
628 AsyncSocketAdapter::OnConnectEvent(socket);
629 return;
630 }
631
632 state_ = SSL_CONNECTING;
633 if (int err = BeginSSL()) {
634 Error("BeginSSL", err);
635 }
636 }
637
638 void
639 SChannelAdapter::OnReadEvent(AsyncSocket* socket) {
640 if (state_ == SSL_NONE) {
641 AsyncSocketAdapter::OnReadEvent(socket);
642 return;
643 }
644
645 if (int err = Read()) {
646 Error("Read", err);
647 return;
648 }
649
650 if (impl_->inbuf.empty())
651 return;
652
653 if (state_ == SSL_CONNECTED) {
654 if (int err = DecryptData()) {
655 Error("DecryptData", err);
656 } else if (!impl_->readable.empty()) {
657 AsyncSocketAdapter::OnReadEvent(this);
658 }
659 } else if (state_ == SSL_CONNECTING) {
660 if (int err = ContinueSSL()) {
661 Error("ContinueSSL", err);
662 }
663 }
664 }
665
666 void
667 SChannelAdapter::OnWriteEvent(AsyncSocket* socket) {
668 if (state_ == SSL_NONE) {
669 AsyncSocketAdapter::OnWriteEvent(socket);
670 return;
671 }
672
673 if (int err = Flush()) {
674 Error("Flush", err);
675 return;
676 }
677
678 // See if we have more data to write
679 if (!impl_->outbuf.empty())
680 return;
681
682 // Buffer is empty, submit notification
683 if (state_ == SSL_CONNECTED) {
684 AsyncSocketAdapter::OnWriteEvent(socket);
685 }
686 }
687
688 void
689 SChannelAdapter::OnCloseEvent(AsyncSocket* socket, int err) {
690 if ((state_ == SSL_NONE) || impl_->readable.empty()) {
691 AsyncSocketAdapter::OnCloseEvent(socket, err);
692 return;
693 }
694
695 // If readable is non-empty, then we have a pending Message
696 // that will allow us to signal close (eventually).
697 signal_close_ = true;
698 }
699
700 void
701 SChannelAdapter::OnMessage(Message* pmsg) {
702 if (!message_pending_)
703 return; // This occurs when socket is closed
704
705 message_pending_ = false;
706 if (!impl_->readable.empty()) {
707 AsyncSocketAdapter::OnReadEvent(this);
708 } else if (signal_close_) {
709 signal_close_ = false;
710 AsyncSocketAdapter::OnCloseEvent(this, 0); // TODO: cache this error?
711 }
712 }
713
714 } // namespace rtc
OLDNEW
« no previous file with comments | « webrtc/base/schanneladapter.h ('k') | webrtc/base/ssladapter.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698