147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org/* 247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * Copyright 2004 The WebRTC Project Authors. All rights reserved. 347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * 447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * Use of this source code is governed by a BSD-style license 547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * that can be found in the LICENSE file in the root of the source 647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * tree. An additional intellectual property rights grant can be found 747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * in the file PATENTS. All contributing project authors may 847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * be found in the AUTHORS file in the root of the source tree. 947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org */ 1047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 1147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/win32.h" 1247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#define SECURITY_WIN32 1347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <security.h> 1447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <schannel.h> 1547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 1647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <iomanip> 1747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <vector> 1847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 1947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/common.h" 2047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/logging.h" 2147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/schanneladapter.h" 2247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/sec_buffer.h" 2347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/thread.h" 2447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 2547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgnamespace rtc { 2647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 2747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org///////////////////////////////////////////////////////////////////////////// 2847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// SChannelAdapter 2947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org///////////////////////////////////////////////////////////////////////////// 3047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 3147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgextern const ConstantLabel SECURITY_ERRORS[]; 3247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 3347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgconst ConstantLabel SCHANNEL_BUFFER_TYPES[] = { 3447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org KLABEL(SECBUFFER_EMPTY), // 0 3547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org KLABEL(SECBUFFER_DATA), // 1 3647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org KLABEL(SECBUFFER_TOKEN), // 2 3747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org KLABEL(SECBUFFER_PKG_PARAMS), // 3 3847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org KLABEL(SECBUFFER_MISSING), // 4 3947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org KLABEL(SECBUFFER_EXTRA), // 5 4047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org KLABEL(SECBUFFER_STREAM_TRAILER), // 6 4147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org KLABEL(SECBUFFER_STREAM_HEADER), // 7 4247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org KLABEL(SECBUFFER_MECHLIST), // 11 4347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org KLABEL(SECBUFFER_MECHLIST_SIGNATURE), // 12 4447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org KLABEL(SECBUFFER_TARGET), // 13 4547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org KLABEL(SECBUFFER_CHANNEL_BINDINGS), // 14 4647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LASTLABEL 4747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}; 4847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 4947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid DescribeBuffer(LoggingSeverity severity, const char* prefix, 5047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org const SecBuffer& sb) { 5147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG_V(severity) 5247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org << prefix 5347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org << "(" << sb.cbBuffer 5447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org << ", " << FindLabel(sb.BufferType & ~SECBUFFER_ATTRMASK, 5547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SCHANNEL_BUFFER_TYPES) 5647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org << ", " << sb.pvBuffer << ")"; 5747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 5847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 5947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid DescribeBuffers(LoggingSeverity severity, const char* prefix, 6047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org const SecBufferDesc* sbd) { 6147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!LOG_CHECK_LEVEL_V(severity)) 6247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return; 6347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG_V(severity) << prefix << "("; 6447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org for (size_t i=0; i<sbd->cBuffers; ++i) { 6547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org DescribeBuffer(severity, " ", sbd->pBuffers[i]); 6647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 6747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG_V(severity) << ")"; 6847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 6947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 7047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgconst ULONG SSL_FLAGS_DEFAULT = ISC_REQ_ALLOCATE_MEMORY 7147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org | ISC_REQ_CONFIDENTIALITY 7247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org | ISC_REQ_EXTENDED_ERROR 7347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org | ISC_REQ_INTEGRITY 7447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org | ISC_REQ_REPLAY_DETECT 7547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org | ISC_REQ_SEQUENCE_DETECT 7647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org | ISC_REQ_STREAM; 7747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org //| ISC_REQ_USE_SUPPLIED_CREDS; 7847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 7947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgtypedef std::vector<char> SChannelBuffer; 8047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 8147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstruct SChannelAdapter::SSLImpl { 8247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org CredHandle cred; 8347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org CtxtHandle ctx; 8447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org bool cred_init, ctx_init; 8547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SChannelBuffer inbuf, outbuf, readable; 8647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SecPkgContext_StreamSizes sizes; 8747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 8847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SSLImpl() : cred_init(false), ctx_init(false) { } 8947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}; 9047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 9147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSChannelAdapter::SChannelAdapter(AsyncSocket* socket) 9247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org : SSLAdapter(socket), state_(SSL_NONE), 9347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org restartable_(false), signal_close_(false), message_pending_(false), 9447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org impl_(new SSLImpl) { 9547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 9647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 9747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSChannelAdapter::~SChannelAdapter() { 9847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Cleanup(); 9947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 10047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 10147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint 10247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSChannelAdapter::StartSSL(const char* hostname, bool restartable) { 10347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (state_ != SSL_NONE) 10447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return ERROR_ALREADY_INITIALIZED; 10547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 10647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ssl_host_name_ = hostname; 10747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org restartable_ = restartable; 10847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 10947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (socket_->GetState() != Socket::CS_CONNECTED) { 11047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org state_ = SSL_WAIT; 11147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return 0; 11247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 11347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 11447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org state_ = SSL_CONNECTING; 11547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (int err = BeginSSL()) { 11647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Error("BeginSSL", err, false); 11747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return err; 11847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 11947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 12047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return 0; 12147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 12247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 12347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint 12447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSChannelAdapter::BeginSSL() { 12547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_VERBOSE) << "BeginSSL: " << ssl_host_name_; 12647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(state_ == SSL_CONNECTING); 12747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 12847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SECURITY_STATUS ret; 12947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 13047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SCHANNEL_CRED sc_cred = { 0 }; 13147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org sc_cred.dwVersion = SCHANNEL_CRED_VERSION; 13247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org //sc_cred.dwMinimumCipherStrength = 128; // Note: use system default 13347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org sc_cred.dwFlags = SCH_CRED_NO_DEFAULT_CREDS | SCH_CRED_AUTO_CRED_VALIDATION; 13447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 135b957cd8adc24f22701221b5755a87a8dccfe0b71sergeyu@chromium.org ret = AcquireCredentialsHandle(NULL, const_cast<LPTSTR>(UNISP_NAME), 136b957cd8adc24f22701221b5755a87a8dccfe0b71sergeyu@chromium.org SECPKG_CRED_OUTBOUND, NULL, &sc_cred, NULL, 137b957cd8adc24f22701221b5755a87a8dccfe0b71sergeyu@chromium.org NULL, &impl_->cred, NULL); 13847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (ret != SEC_E_OK) { 13947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_ERROR) << "AcquireCredentialsHandle error: " 14047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org << ErrorName(ret, SECURITY_ERRORS); 14147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return ret; 14247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 14347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org impl_->cred_init = true; 14447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 14547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (LOG_CHECK_LEVEL(LS_VERBOSE)) { 14647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SecPkgCred_CipherStrengths cipher_strengths = { 0 }; 14747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ret = QueryCredentialsAttributes(&impl_->cred, 14847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SECPKG_ATTR_CIPHER_STRENGTHS, 14947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org &cipher_strengths); 15047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (SUCCEEDED(ret)) { 15147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_VERBOSE) << "SChannel cipher strength: " 15247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org << cipher_strengths.dwMinimumCipherStrength << " - " 15347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org << cipher_strengths.dwMaximumCipherStrength; 15447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 15547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 15647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SecPkgCred_SupportedAlgs supported_algs = { 0 }; 15747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ret = QueryCredentialsAttributes(&impl_->cred, 15847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SECPKG_ATTR_SUPPORTED_ALGS, 15947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org &supported_algs); 16047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (SUCCEEDED(ret)) { 16147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_VERBOSE) << "SChannel supported algorithms:"; 16247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org for (DWORD i=0; i<supported_algs.cSupportedAlgs; ++i) { 16347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ALG_ID alg_id = supported_algs.palgSupportedAlgs[i]; 16447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PCCRYPT_OID_INFO oinfo = CryptFindOIDInfo(CRYPT_OID_INFO_ALGID_KEY, 16547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org &alg_id, 0); 16647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LPCWSTR alg_name = (NULL != oinfo) ? oinfo->pwszName : L"Unknown"; 16747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_VERBOSE) << " " << ToUtf8(alg_name) << " (" << alg_id << ")"; 16847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 16947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org CSecBufferBase::FreeSSPI(supported_algs.palgSupportedAlgs); 17047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 17147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 17247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 17347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ULONG flags = SSL_FLAGS_DEFAULT, ret_flags = 0; 17447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (ignore_bad_cert()) 17547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org flags |= ISC_REQ_MANUAL_CRED_VALIDATION; 17647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 17747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org CSecBufferBundle<2, CSecBufferBase::FreeSSPI> sb_out; 17847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ret = InitializeSecurityContextA(&impl_->cred, NULL, 17947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org const_cast<char*>(ssl_host_name_.c_str()), 18047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org flags, 0, 0, NULL, 0, 18147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org &impl_->ctx, sb_out.desc(), 18247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org &ret_flags, NULL); 18347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (SUCCEEDED(ret)) 18447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org impl_->ctx_init = true; 18547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return ProcessContext(ret, NULL, sb_out.desc()); 18647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 18747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 18847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint 18947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSChannelAdapter::ContinueSSL() { 19047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_VERBOSE) << "ContinueSSL"; 19147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(state_ == SSL_CONNECTING); 19247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 19347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SECURITY_STATUS ret; 19447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 19547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org CSecBufferBundle<2> sb_in; 19647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org sb_in[0].BufferType = SECBUFFER_TOKEN; 19747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org sb_in[0].cbBuffer = static_cast<unsigned long>(impl_->inbuf.size()); 19847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org sb_in[0].pvBuffer = &impl_->inbuf[0]; 19947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org //DescribeBuffers(LS_VERBOSE, "Input Buffer ", sb_in.desc()); 20047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 20147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ULONG flags = SSL_FLAGS_DEFAULT, ret_flags = 0; 20247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (ignore_bad_cert()) 20347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org flags |= ISC_REQ_MANUAL_CRED_VALIDATION; 20447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 20547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org CSecBufferBundle<2, CSecBufferBase::FreeSSPI> sb_out; 20647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ret = InitializeSecurityContextA(&impl_->cred, &impl_->ctx, 20747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org const_cast<char*>(ssl_host_name_.c_str()), 20847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org flags, 0, 0, sb_in.desc(), 0, 20947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org NULL, sb_out.desc(), 21047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org &ret_flags, NULL); 21147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return ProcessContext(ret, sb_in.desc(), sb_out.desc()); 21247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 21347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 21447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint 21547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSChannelAdapter::ProcessContext(long int status, _SecBufferDesc* sbd_in, 21647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org _SecBufferDesc* sbd_out) { 21747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED && 21847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org status != SEC_E_INCOMPLETE_MESSAGE) { 21947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_ERROR) 22047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org << "InitializeSecurityContext error: " 22147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org << ErrorName(status, SECURITY_ERRORS); 22247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 22347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org //if (sbd_in) 22447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // DescribeBuffers(LS_VERBOSE, "Input Buffer ", sbd_in); 22547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org //if (sbd_out) 22647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // DescribeBuffers(LS_VERBOSE, "Output Buffer ", sbd_out); 22747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 22847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (status == SEC_E_INCOMPLETE_MESSAGE) { 22947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Wait for more input from server. 23047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return Flush(); 23147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 23247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 23347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (FAILED(status)) { 23447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // We can't continue. Common errors: 23547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // SEC_E_CERT_EXPIRED - Typically, this means the computer clock is wrong. 23647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return status; 23747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 23847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 23947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Note: we check both input and output buffers for SECBUFFER_EXTRA. 24047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Experience shows it appearing in the input, but the documentation claims 24147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // it should appear in the output. 24247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org size_t extra = 0; 24347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (sbd_in) { 24447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org for (size_t i=0; i<sbd_in->cBuffers; ++i) { 24547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SecBuffer& buffer = sbd_in->pBuffers[i]; 24647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (buffer.BufferType == SECBUFFER_EXTRA) { 24747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org extra += buffer.cbBuffer; 24847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 24947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 25047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 25147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (sbd_out) { 25247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org for (size_t i=0; i<sbd_out->cBuffers; ++i) { 25347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SecBuffer& buffer = sbd_out->pBuffers[i]; 25447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (buffer.BufferType == SECBUFFER_EXTRA) { 25547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org extra += buffer.cbBuffer; 25647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else if (buffer.BufferType == SECBUFFER_TOKEN) { 25747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org impl_->outbuf.insert(impl_->outbuf.end(), 25847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org reinterpret_cast<char*>(buffer.pvBuffer), 25947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org reinterpret_cast<char*>(buffer.pvBuffer) + buffer.cbBuffer); 26047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 26147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 26247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 26347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 26447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (extra) { 26547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(extra <= impl_->inbuf.size()); 26647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org size_t consumed = impl_->inbuf.size() - extra; 26747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org memmove(&impl_->inbuf[0], &impl_->inbuf[consumed], extra); 26847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org impl_->inbuf.resize(extra); 26947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 27047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org impl_->inbuf.clear(); 27147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 27247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 27347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (SEC_I_CONTINUE_NEEDED == status) { 27447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Send data to server and wait for response. 27547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Note: ContinueSSL will result in a Flush, anyway. 27647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return impl_->inbuf.empty() ? Flush() : ContinueSSL(); 27747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 27847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 27947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (SEC_E_OK == status) { 28047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_VERBOSE) << "QueryContextAttributes"; 28147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org status = QueryContextAttributes(&impl_->ctx, SECPKG_ATTR_STREAM_SIZES, 28247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org &impl_->sizes); 28347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (FAILED(status)) { 28447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_ERROR) << "QueryContextAttributes error: " 28547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org << ErrorName(status, SECURITY_ERRORS); 28647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return status; 28747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 28847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 28947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org state_ = SSL_CONNECTED; 29047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 29147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (int err = DecryptData()) { 29247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return err; 29347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else if (int err = Flush()) { 29447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return err; 29547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 29647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // If we decrypted any data, queue up a notification here 29747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PostEvent(); 29847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Signal our connectedness 29947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org AsyncSocketAdapter::OnConnectEvent(this); 30047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 30147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return 0; 30247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 30347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 30447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (SEC_I_INCOMPLETE_CREDENTIALS == status) { 30547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // We don't support client authentication in schannel. 30647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return status; 30747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 30847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 30947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // We don't expect any other codes 31047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(false); 31147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return status; 31247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 31347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 31447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint 31547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSChannelAdapter::DecryptData() { 31647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SChannelBuffer& inbuf = impl_->inbuf; 31747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SChannelBuffer& readable = impl_->readable; 31847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 31947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org while (!inbuf.empty()) { 32047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org CSecBufferBundle<4> in_buf; 32147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org in_buf[0].BufferType = SECBUFFER_DATA; 32247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org in_buf[0].cbBuffer = static_cast<unsigned long>(inbuf.size()); 32347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org in_buf[0].pvBuffer = &inbuf[0]; 32447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 32547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org //DescribeBuffers(LS_VERBOSE, "Decrypt In ", in_buf.desc()); 32647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SECURITY_STATUS status = DecryptMessage(&impl_->ctx, in_buf.desc(), 0, 0); 32747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org //DescribeBuffers(LS_VERBOSE, "Decrypt Out ", in_buf.desc()); 32847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 32947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Note: We are explicitly treating SEC_E_OK, SEC_I_CONTEXT_EXPIRED, and 33047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // any other successful results as continue. 33147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (SUCCEEDED(status)) { 33247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org size_t data_len = 0, extra_len = 0; 33347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org for (size_t i=0; i<in_buf.desc()->cBuffers; ++i) { 33447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (in_buf[i].BufferType == SECBUFFER_DATA) { 33547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org data_len += in_buf[i].cbBuffer; 33647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org readable.insert(readable.end(), 33747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org reinterpret_cast<char*>(in_buf[i].pvBuffer), 33847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org reinterpret_cast<char*>(in_buf[i].pvBuffer) + in_buf[i].cbBuffer); 33947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else if (in_buf[i].BufferType == SECBUFFER_EXTRA) { 34047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org extra_len += in_buf[i].cbBuffer; 34147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 34247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 34347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // There is a bug on Win2K where SEC_I_CONTEXT_EXPIRED is misclassified. 34447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if ((data_len == 0) && (inbuf[0] == 0x15)) { 34547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org status = SEC_I_CONTEXT_EXPIRED; 34647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 34747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (extra_len) { 34847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org size_t consumed = inbuf.size() - extra_len; 34947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org memmove(&inbuf[0], &inbuf[consumed], extra_len); 35047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org inbuf.resize(extra_len); 35147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 35247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org inbuf.clear(); 35347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 35447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // TODO: Handle SEC_I_CONTEXT_EXPIRED to do clean shutdown 35547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (status != SEC_E_OK) { 35647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_INFO) << "DecryptMessage returned continuation code: " 35747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org << ErrorName(status, SECURITY_ERRORS); 35847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 35947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org continue; 36047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 36147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 36247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (status == SEC_E_INCOMPLETE_MESSAGE) { 36347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org break; 36447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 36547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return status; 36647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 36747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 36847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 36947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return 0; 37047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 37147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 37247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid 37347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSChannelAdapter::Cleanup() { 37447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (impl_->ctx_init) 37547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org DeleteSecurityContext(&impl_->ctx); 37647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (impl_->cred_init) 37747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org FreeCredentialsHandle(&impl_->cred); 37847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org delete impl_; 37947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 38047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 38147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid 38247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSChannelAdapter::PostEvent() { 38347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Check if there's anything notable to signal 38447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (impl_->readable.empty() && !signal_close_) 38547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return; 38647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 38747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Only one post in the queue at a time 38847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (message_pending_) 38947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return; 39047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 39147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (Thread* thread = Thread::Current()) { 39247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org message_pending_ = true; 39347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org thread->Post(this); 39447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 39547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_ERROR) << "No thread context available for SChannelAdapter"; 39647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(false); 39747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 39847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 39947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 40047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid 40147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSChannelAdapter::Error(const char* context, int err, bool signal) { 40247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_WARNING) << "SChannelAdapter::Error(" 40347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org << context << ", " 40447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org << ErrorName(err, SECURITY_ERRORS) << ")"; 40547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org state_ = SSL_ERROR; 40647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SetError(err); 40747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (signal) 40847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org AsyncSocketAdapter::OnCloseEvent(this, err); 40947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 41047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 41147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint 41247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSChannelAdapter::Read() { 41347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org char buffer[4096]; 41447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SChannelBuffer& inbuf = impl_->inbuf; 41547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org while (true) { 41647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int ret = AsyncSocketAdapter::Recv(buffer, sizeof(buffer)); 41747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (ret > 0) { 41847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org inbuf.insert(inbuf.end(), buffer, buffer + ret); 41947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else if (GetError() == EWOULDBLOCK) { 42047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return 0; // Blocking 42147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 42247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return GetError(); 42347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 42447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 42547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 42647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 42747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint 42847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSChannelAdapter::Flush() { 42947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int result = 0; 43047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org size_t pos = 0; 43147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SChannelBuffer& outbuf = impl_->outbuf; 43247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org while (pos < outbuf.size()) { 43347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int sent = AsyncSocketAdapter::Send(&outbuf[pos], outbuf.size() - pos); 43447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (sent > 0) { 43547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org pos += sent; 43647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else if (GetError() == EWOULDBLOCK) { 43747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org break; // Blocking 43847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 43947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org result = GetError(); 44047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org break; 44147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 44247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 44347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (int remainder = static_cast<int>(outbuf.size() - pos)) { 44447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org memmove(&outbuf[0], &outbuf[pos], remainder); 44547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org outbuf.resize(remainder); 44647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 44747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org outbuf.clear(); 44847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 44947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return result; 45047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 45147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 45247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// 45347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// AsyncSocket Implementation 45447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// 45547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 45647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint 45747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSChannelAdapter::Send(const void* pv, size_t cb) { 45847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org switch (state_) { 45947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case SSL_NONE: 46047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return AsyncSocketAdapter::Send(pv, cb); 46147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 46247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case SSL_WAIT: 46347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case SSL_CONNECTING: 46447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SetError(EWOULDBLOCK); 46547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return SOCKET_ERROR; 46647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 46747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case SSL_CONNECTED: 46847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org break; 46947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 47047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case SSL_ERROR: 47147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org default: 47247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return SOCKET_ERROR; 47347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 47447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 47547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org size_t written = 0; 47647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SChannelBuffer& outbuf = impl_->outbuf; 47747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org while (written < cb) { 47847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org const size_t encrypt_len = std::min<size_t>(cb - written, 47947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org impl_->sizes.cbMaximumMessage); 48047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 48147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org CSecBufferBundle<4> out_buf; 48247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org out_buf[0].BufferType = SECBUFFER_STREAM_HEADER; 48347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org out_buf[0].cbBuffer = impl_->sizes.cbHeader; 48447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org out_buf[1].BufferType = SECBUFFER_DATA; 48547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org out_buf[1].cbBuffer = static_cast<unsigned long>(encrypt_len); 48647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org out_buf[2].BufferType = SECBUFFER_STREAM_TRAILER; 48747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org out_buf[2].cbBuffer = impl_->sizes.cbTrailer; 48847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 48947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org size_t packet_len = out_buf[0].cbBuffer 49047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org + out_buf[1].cbBuffer 49147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org + out_buf[2].cbBuffer; 49247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 49347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SChannelBuffer message; 49447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org message.resize(packet_len); 49547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org out_buf[0].pvBuffer = &message[0]; 49647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org out_buf[1].pvBuffer = &message[out_buf[0].cbBuffer]; 49747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org out_buf[2].pvBuffer = &message[out_buf[0].cbBuffer + out_buf[1].cbBuffer]; 49847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 49947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org memcpy(out_buf[1].pvBuffer, 50047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org static_cast<const char*>(pv) + written, 50147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org encrypt_len); 50247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 50347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org //DescribeBuffers(LS_VERBOSE, "Encrypt In ", out_buf.desc()); 50447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SECURITY_STATUS res = EncryptMessage(&impl_->ctx, 0, out_buf.desc(), 0); 50547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org //DescribeBuffers(LS_VERBOSE, "Encrypt Out ", out_buf.desc()); 50647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 50747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (FAILED(res)) { 50847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Error("EncryptMessage", res, false); 50947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return SOCKET_ERROR; 51047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 51147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 51247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // We assume that the header and data segments do not change length, 51347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // or else encrypting the concatenated packet in-place is wrong. 51447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(out_buf[0].cbBuffer == impl_->sizes.cbHeader); 51547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(out_buf[1].cbBuffer == static_cast<unsigned long>(encrypt_len)); 51647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 51747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // However, the length of the trailer may change due to padding. 51847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(out_buf[2].cbBuffer <= impl_->sizes.cbTrailer); 51947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 52047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org packet_len = out_buf[0].cbBuffer 52147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org + out_buf[1].cbBuffer 52247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org + out_buf[2].cbBuffer; 52347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 52447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org written += encrypt_len; 52547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org outbuf.insert(outbuf.end(), &message[0], &message[packet_len-1]+1); 52647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 52747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 52847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (int err = Flush()) { 52947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org state_ = SSL_ERROR; 53047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SetError(err); 53147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return SOCKET_ERROR; 53247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 53347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 53447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return static_cast<int>(written); 53547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 53647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 53747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint 53847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSChannelAdapter::Recv(void* pv, size_t cb) { 53947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org switch (state_) { 54047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case SSL_NONE: 54147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return AsyncSocketAdapter::Recv(pv, cb); 54247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 54347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case SSL_WAIT: 54447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case SSL_CONNECTING: 54547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SetError(EWOULDBLOCK); 54647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return SOCKET_ERROR; 54747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 54847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case SSL_CONNECTED: 54947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org break; 55047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 55147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org case SSL_ERROR: 55247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org default: 55347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return SOCKET_ERROR; 55447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 55547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 55647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SChannelBuffer& readable = impl_->readable; 55747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (readable.empty()) { 55847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SetError(EWOULDBLOCK); 55947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return SOCKET_ERROR; 56047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 56147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org size_t read = _min(cb, readable.size()); 56247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org memcpy(pv, &readable[0], read); 56347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (size_t remaining = readable.size() - read) { 56447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org memmove(&readable[0], &readable[read], remaining); 56547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org readable.resize(remaining); 56647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 56747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org readable.clear(); 56847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 56947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 57047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org PostEvent(); 57147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return static_cast<int>(read); 57247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 57347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 57447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint 57547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSChannelAdapter::Close() { 57647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!impl_->readable.empty()) { 57747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(WARNING) << "SChannelAdapter::Close with readable data"; 57847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Note: this isn't strictly an error, but we're using it temporarily to 57947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // track bugs. 58047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org //ASSERT(false); 58147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 58247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (state_ == SSL_CONNECTED) { 58347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org DWORD token = SCHANNEL_SHUTDOWN; 58447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org CSecBufferBundle<1> sb_in; 58547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org sb_in[0].BufferType = SECBUFFER_TOKEN; 58647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org sb_in[0].cbBuffer = sizeof(token); 58747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org sb_in[0].pvBuffer = &token; 58847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ApplyControlToken(&impl_->ctx, sb_in.desc()); 58947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // TODO: In theory, to do a nice shutdown, we need to begin shutdown 59047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // negotiation with more calls to InitializeSecurityContext. Since the 59147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // socket api doesn't support nice shutdown at this point, we don't bother. 59247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 59347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Cleanup(); 59447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org impl_ = new SSLImpl; 59547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org state_ = restartable_ ? SSL_WAIT : SSL_NONE; 59647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org signal_close_ = false; 59747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org message_pending_ = false; 59847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return AsyncSocketAdapter::Close(); 59947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 60047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 60147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSocket::ConnState 60247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSChannelAdapter::GetState() const { 60347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (signal_close_) 60447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return CS_CONNECTED; 60547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ConnState state = socket_->GetState(); 60647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if ((state == CS_CONNECTED) 60747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org && ((state_ == SSL_WAIT) || (state_ == SSL_CONNECTING))) 60847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org state = CS_CONNECTING; 60947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return state; 61047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 61147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 61247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid 61347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSChannelAdapter::OnConnectEvent(AsyncSocket* socket) { 61447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LOG(LS_VERBOSE) << "SChannelAdapter::OnConnectEvent"; 61547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (state_ != SSL_WAIT) { 61647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(state_ == SSL_NONE); 61747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org AsyncSocketAdapter::OnConnectEvent(socket); 61847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return; 61947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 62047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 62147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org state_ = SSL_CONNECTING; 62247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (int err = BeginSSL()) { 62347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Error("BeginSSL", err); 62447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 62547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 62647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 62747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid 62847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSChannelAdapter::OnReadEvent(AsyncSocket* socket) { 62947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (state_ == SSL_NONE) { 63047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org AsyncSocketAdapter::OnReadEvent(socket); 63147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return; 63247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 63347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 63447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (int err = Read()) { 63547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Error("Read", err); 63647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return; 63747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 63847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 63947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (impl_->inbuf.empty()) 64047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return; 64147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 64247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (state_ == SSL_CONNECTED) { 64347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (int err = DecryptData()) { 64447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Error("DecryptData", err); 64547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else if (!impl_->readable.empty()) { 64647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org AsyncSocketAdapter::OnReadEvent(this); 64747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 64847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else if (state_ == SSL_CONNECTING) { 64947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (int err = ContinueSSL()) { 65047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Error("ContinueSSL", err); 65147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 65247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 65347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 65447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 65547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid 65647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSChannelAdapter::OnWriteEvent(AsyncSocket* socket) { 65747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (state_ == SSL_NONE) { 65847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org AsyncSocketAdapter::OnWriteEvent(socket); 65947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return; 66047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 66147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 66247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (int err = Flush()) { 66347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Error("Flush", err); 66447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return; 66547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 66647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 66747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // See if we have more data to write 66847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!impl_->outbuf.empty()) 66947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return; 67047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 67147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Buffer is empty, submit notification 67247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (state_ == SSL_CONNECTED) { 67347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org AsyncSocketAdapter::OnWriteEvent(socket); 67447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 67547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 67647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 67747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid 67847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSChannelAdapter::OnCloseEvent(AsyncSocket* socket, int err) { 67947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if ((state_ == SSL_NONE) || impl_->readable.empty()) { 68047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org AsyncSocketAdapter::OnCloseEvent(socket, err); 68147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return; 68247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 68347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 68447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // If readable is non-empty, then we have a pending Message 68547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // that will allow us to signal close (eventually). 68647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org signal_close_ = true; 68747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 68847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 68947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid 69047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSChannelAdapter::OnMessage(Message* pmsg) { 69147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!message_pending_) 69247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return; // This occurs when socket is closed 69347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 69447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org message_pending_ = false; 69547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (!impl_->readable.empty()) { 69647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org AsyncSocketAdapter::OnReadEvent(this); 69747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else if (signal_close_) { 69847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org signal_close_ = false; 69947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org AsyncSocketAdapter::OnCloseEvent(this, 0); // TODO: cache this error? 70047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 70147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 70247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 70347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} // namespace rtc 704