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