From a576faf82a692c9422dcdc3278394ed25e6ee4f7 Mon Sep 17 00:00:00 2001 From: "jiayl@webrtc.org" Date: Wed, 29 Jan 2014 17:45:53 +0000 Subject: [PATCH] Enable SCTP and use OPENSSL on Anroid and NSS on other platforms. It includes unit test fixes to properly initialize SSL if DTLS or SSL random number generator is used in the tests. The private key and certificate constant strings used in some tests are updated to be compatible with NSS. A few potentially overflow type conversions caused compiling warning on Windows and they are fixed by importing and using Chromium's checked_cast, which aborts the program if overflow occurs. It also fixes a leak in nssstreamadapter.cc by releasing the PRFileDesc* in StreamClose. BUG=2253 R=fischman@webrtc.org, juberti@google.com, wu@webrtc.org Review URL: https://webrtc-codereview.appspot.com/4679005 git-svn-id: http://webrtc.googlecode.com/svn/trunk@5459 4adac7df-926f-26a2-2b94-8c16560cd09d --- DEPS | 22 +- .../webrtc/jsepsessiondescription_unittest.cc | 9 + .../webrtc/objctests/RTCPeerConnectionTest.mm | 7 +- talk/app/webrtc/peerconnection_unittest.cc | 14 +- .../peerconnectioninterface_unittest.cc | 14 +- .../app/webrtc/test/fakedtlsidentityservice.h | 45 ++-- talk/base/common.h | 10 +- talk/base/helpers_unittest.cc | 22 +- talk/base/nssidentity.cc | 10 +- talk/base/nssstreamadapter.cc | 36 +-- talk/base/safe_conversions.h | 96 ++++++++ talk/base/safe_conversions_impl.h | 205 ++++++++++++++++++ talk/base/sslidentity_unittest.cc | 45 ++-- talk/base/sslstreamadapter_unittest.cc | 50 +++-- talk/build/common.gypi | 39 +++- talk/libjingle.gyp | 35 ++- talk/libjingle_tests.gyp | 8 + talk/media/base/rtpdataengine_unittest.cc | 9 + talk/media/sctp/sctpdataengine.cc | 10 +- talk/media/sctp/sctpdataengine_unittest.cc | 11 + 20 files changed, 557 insertions(+), 140 deletions(-) create mode 100644 talk/base/safe_conversions.h create mode 100644 talk/base/safe_conversions_impl.h diff --git a/DEPS b/DEPS index 9813c616b5..dded4ac495 100644 --- a/DEPS +++ b/DEPS @@ -119,6 +119,15 @@ deps = { # Needed by build/common.gypi. "tools/win/supalink": Var("chromium_trunk") + "/src/tools/win/supalink@" + Var("chromium_revision"), + + "net/third_party/nss": + Var("chromium_trunk") + "/src/net/third_party/nss@" + Var("chromium_revision"), + + "third_party/usrsctp/": + Var("chromium_trunk") + "/src/third_party/usrsctp@" + Var("chromium_revision"), + + "third_party/usrsctp/usrsctplib": + (Var("googlecode_url") % "sctp-refimpl") + "/trunk/KERN/usrsctp/usrsctplib@8723", } deps_os = { @@ -147,12 +156,6 @@ deps_os = { # NSS, for SSLClientSocketNSS. "third_party/nss": From("chromium_deps", "src/third_party/nss"), - - # TODO(fischman): delete this in favor of the copy in "ios" below, once the - # webrtc iOS bots are fixed to target_os=['ios'] in their .gclient - # https://code.google.com/p/webrtc/issues/detail?id=2152 - "net/third_party/nss": - Var("chromium_trunk") + "/src/net/third_party/nss@" + Var("chromium_revision"), }, "ios": { @@ -160,9 +163,6 @@ deps_os = { "third_party/nss": From("chromium_deps", "src/third_party/nss"), - "net/third_party/nss": - Var("chromium_trunk") + "/src/net/third_party/nss@" + Var("chromium_revision"), - # class-dump utility to generate header files for undocumented SDKs. "testing/iossim/third_party/class-dump": From("chromium_deps", "src/testing/iossim/third_party/class-dump"), @@ -175,10 +175,8 @@ deps_os = { "unix": { "third_party/gold": From("chromium_deps", "src/third_party/gold"), - - "third_party/openssl": - From("chromium_deps", "src/third_party/openssl"), }, + "android": { # Precompiled tools needed for Android test execution. Needed since we can't # compile them from source in WebRTC since they depend on Chromium's base. diff --git a/talk/app/webrtc/jsepsessiondescription_unittest.cc b/talk/app/webrtc/jsepsessiondescription_unittest.cc index e2b59fba20..671df36d96 100644 --- a/talk/app/webrtc/jsepsessiondescription_unittest.cc +++ b/talk/app/webrtc/jsepsessiondescription_unittest.cc @@ -32,6 +32,7 @@ #include "talk/base/gunit.h" #include "talk/base/helpers.h" #include "talk/base/scoped_ptr.h" +#include "talk/base/ssladapter.h" #include "talk/base/stringencode.h" #include "talk/p2p/base/candidate.h" #include "talk/p2p/base/constants.h" @@ -96,6 +97,14 @@ static cricket::SessionDescription* CreateCricketSessionDescription() { class JsepSessionDescriptionTest : public testing::Test { protected: + static void SetUpTestCase() { + talk_base::InitializeSSL(); + } + + static void TearDownTestCase() { + talk_base::CleanupSSL(); + } + virtual void SetUp() { int port = 1234; talk_base::SocketAddress address("127.0.0.1", port++); diff --git a/talk/app/webrtc/objctests/RTCPeerConnectionTest.mm b/talk/app/webrtc/objctests/RTCPeerConnectionTest.mm index 0ce8822fd1..55e738839a 100644 --- a/talk/app/webrtc/objctests/RTCPeerConnectionTest.mm +++ b/talk/app/webrtc/objctests/RTCPeerConnectionTest.mm @@ -39,6 +39,7 @@ #import "RTCVideoTrack.h" #include "talk/base/gunit.h" +#include "talk/base/ssladapter.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -229,8 +230,12 @@ @end - +// TODO(fischman): move {Initialize,Cleanup}SSL into alloc/dealloc of +// RTCPeerConnectionTest and avoid the appearance of RTCPeerConnectionTest being +// a TestBase since it's not. TEST(RTCPeerConnectionTest, SessionTest) { + talk_base::InitializeSSL(); RTCPeerConnectionTest *pcTest = [[RTCPeerConnectionTest alloc] init]; [pcTest testCompleteSession]; + talk_base::CleanupSSL(); } diff --git a/talk/app/webrtc/peerconnection_unittest.cc b/talk/app/webrtc/peerconnection_unittest.cc index 76d9cd73cf..edf79f5a75 100644 --- a/talk/app/webrtc/peerconnection_unittest.cc +++ b/talk/app/webrtc/peerconnection_unittest.cc @@ -40,6 +40,7 @@ #include "talk/app/webrtc/peerconnectioninterface.h" #include "talk/app/webrtc/test/fakeaudiocapturemodule.h" #include "talk/app/webrtc/test/fakeconstraints.h" +#include "talk/app/webrtc/test/fakedtlsidentityservice.h" #include "talk/app/webrtc/test/fakevideotrackrenderer.h" #include "talk/app/webrtc/test/fakeperiodicvideocapturer.h" #include "talk/app/webrtc/test/mockpeerconnectionobservers.h" @@ -719,8 +720,19 @@ class JsepTestClient webrtc::PeerConnectionInterface::IceServer ice_server; ice_server.uri = "stun:stun.l.google.com:19302"; ice_servers.push_back(ice_server); + + // TODO(jiayl): we should always pass a FakeIdentityService so that DTLS + // is enabled by default like in Chrome (issue 2838). + FakeIdentityService* dtls_service = NULL; + bool dtls; + if (FindConstraint(constraints, + MediaConstraintsInterface::kEnableDtlsSrtp, + &dtls, + NULL) && dtls) { + dtls_service = new FakeIdentityService(); + } return peer_connection_factory()->CreatePeerConnection( - ice_servers, constraints, factory, NULL, this); + ice_servers, constraints, factory, dtls_service, this); } void HandleIncomingOffer(const std::string& msg) { diff --git a/talk/app/webrtc/peerconnectioninterface_unittest.cc b/talk/app/webrtc/peerconnectioninterface_unittest.cc index e47e5b17f8..f9d5e2eee8 100644 --- a/talk/app/webrtc/peerconnectioninterface_unittest.cc +++ b/talk/app/webrtc/peerconnectioninterface_unittest.cc @@ -32,6 +32,7 @@ #include "talk/app/webrtc/mediastreaminterface.h" #include "talk/app/webrtc/peerconnectioninterface.h" #include "talk/app/webrtc/test/fakeconstraints.h" +#include "talk/app/webrtc/test/fakedtlsidentityservice.h" #include "talk/app/webrtc/test/mockpeerconnectionobservers.h" #include "talk/app/webrtc/test/testsdpstrings.h" #include "talk/app/webrtc/videosource.h" @@ -258,9 +259,20 @@ class PeerConnectionInterfaceTest : public testing::Test { servers.push_back(server); port_allocator_factory_ = FakePortAllocatorFactory::Create(); + + // TODO(jiayl): we should always pass a FakeIdentityService so that DTLS + // is enabled by default like in Chrome (issue 2838). + FakeIdentityService* dtls_service = NULL; + bool dtls; + if (FindConstraint(constraints, + webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, + &dtls, + NULL) && dtls) { + dtls_service = new FakeIdentityService(); + } pc_ = pc_factory_->CreatePeerConnection(servers, constraints, port_allocator_factory_.get(), - NULL, + dtls_service, &observer_); ASSERT_TRUE(pc_.get() != NULL); observer_.SetPeerConnectionInterface(pc_.get()); diff --git a/talk/app/webrtc/test/fakedtlsidentityservice.h b/talk/app/webrtc/test/fakedtlsidentityservice.h index c70e0edb66..0c1a2a0c7c 100644 --- a/talk/app/webrtc/test/fakedtlsidentityservice.h +++ b/talk/app/webrtc/test/fakedtlsidentityservice.h @@ -33,32 +33,33 @@ static const char kRSA_PRIVATE_KEY_PEM[] = "-----BEGIN RSA PRIVATE KEY-----\n" - "MIICXQIBAAKBgQDCueE4a9hDMZ3sbVZdlXOz9ZA+cvzie3zJ9gXnT/BCt9P4b9HE\n" - "vD/tr73YBqD3Wr5ZWScmyGYF9EMn0r3rzBxv6oooLU5TdUvOm4rzUjkCLQaQML8o\n" - "NxXq+qW/j3zUKGikLhaaAl/amaX2zSWUsRQ1CpngQ3+tmDNH4/25TncNmQIDAQAB\n" - "AoGAUcuU0Id0k10fMjYHZk4mCPzot2LD2Tr4Aznl5vFMQipHzv7hhZtx2xzMSRcX\n" - "vG+Qr6VkbcUWHgApyWubvZXCh3+N7Vo2aYdMAQ8XqmFpBdIrL5CVdVfqFfEMlgEy\n" - "LSZNG5klnrIfl3c7zQVovLr4eMqyl2oGfAqPQz75+fecv1UCQQD6wNHch9NbAG1q\n" - "yuFEhMARB6gDXb+5SdzFjjtTWW5uJfm4DcZLoYyaIZm0uxOwsUKd0Rsma+oGitS1\n" - "CXmuqfpPAkEAxszyN3vIdpD44SREEtyKZBMNOk5pEIIGdbeMJC5/XHvpxww9xkoC\n" - "+39NbvUZYd54uT+rafbx4QZKc0h9xA/HlwJBAL37lYVWy4XpPv1olWCKi9LbUCqs\n" - "vvQtyD1N1BkEayy9TQRsO09WKOcmigRqsTJwOx7DLaTgokEuspYvhagWVPUCQE/y\n" - "0+YkTbYBD1Xbs9SyBKXCU6uDJRWSdO6aZi2W1XloC9gUwDMiSJjD1Wwt/YsyYPJ+\n" - "/Hyc5yFL2l0KZimW/vkCQQCjuZ/lPcH46EuzhdbRfumDOG5N3ld7UhGI1TIRy17W\n" - "dGF90cG33/L6BfS8Ll+fkkW/2AMRk8FDvF4CZi2nfW4L\n" + "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMYRkbhmI7kVA/rM\n" + "czsZ+6JDhDvnkF+vn6yCAGuRPV03zuRqZtDy4N4to7PZu9PjqrRl7nDMXrG3YG9y\n" + "rlIAZ72KjcKKFAJxQyAKLCIdawKRyp8RdK3LEySWEZb0AV58IadqPZDTNHHRX8dz\n" + "5aTSMsbbkZ+C/OzTnbiMqLL/vg6jAgMBAAECgYAvgOs4FJcgvp+TuREx7YtiYVsH\n" + "mwQPTum2z/8VzWGwR8BBHBvIpVe1MbD/Y4seyI2aco/7UaisatSgJhsU46/9Y4fq\n" + "2TwXH9QANf4at4d9n/R6rzwpAJOpgwZgKvdQjkfrKTtgLV+/dawvpxUYkRH4JZM1\n" + "CVGukMfKNrSVH4Ap4QJBAOJmGV1ASPnB4r4nc99at7JuIJmd7fmuVUwUgYi4XgaR\n" + "WhScBsgYwZ/JoywdyZJgnbcrTDuVcWG56B3vXbhdpMsCQQDf9zeJrjnPZ3Cqm79y\n" + "kdqANep0uwZciiNiWxsQrCHztywOvbFhdp8iYVFG9EK8DMY41Y5TxUwsHD+67zao\n" + "ZNqJAkEA1suLUP/GvL8IwuRneQd2tWDqqRQ/Td3qq03hP7e77XtF/buya3Ghclo5\n" + "54czUR89QyVfJEC6278nzA7n2h1uVQJAcG6mztNL6ja/dKZjYZye2CY44QjSlLo0\n" + "MTgTSjdfg/28fFn2Jjtqf9Pi/X+50LWI/RcYMC2no606wRk9kyOuIQJBAK6VSAim\n" + "1pOEjsYQn0X5KEIrz1G3bfCbB848Ime3U2/FWlCHMr6ch8kCZ5d1WUeJD3LbwMNG\n" + "UCXiYxSsu20QNVw=\n" "-----END RSA PRIVATE KEY-----\n"; static const char kCERT_PEM[] = "-----BEGIN CERTIFICATE-----\n" - "MIIBmTCCAQICCQCPNJORW/M13DANBgkqhkiG9w0BAQUFADARMQ8wDQYDVQQDDAZ3\n" - "ZWJydGMwHhcNMTMwNjE0MjIzMDAxWhcNMTQwNjE0MjIzMDAxWjARMQ8wDQYDVQQD\n" - "DAZ3ZWJydGMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMK54Thr2EMxnext\n" - "Vl2Vc7P1kD5y/OJ7fMn2BedP8EK30/hv0cS8P+2vvdgGoPdavllZJybIZgX0QyfS\n" - "vevMHG/qiigtTlN1S86bivNSOQItBpAwvyg3Fer6pb+PfNQoaKQuFpoCX9qZpfbN\n" - "JZSxFDUKmeBDf62YM0fj/blOdw2ZAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAECMt\n" - "UZb35H8TnjGx4XPzco/kbnurMLFFWcuve/DwTsuf10Ia9N4md8LY0UtgIgtyNqWc\n" - "ZwyRMwxONF6ty3wcaIiPbGqiAa55T3YRuPibkRmck9CjrmM9JAtyvqHnpHd2TsBD\n" - "qCV42aXS3onOXDQ1ibuWq0fr0//aj0wo4KV474c=\n" + "MIIBmTCCAQKgAwIBAgIEbzBSAjANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDEwZX\n" + "ZWJSVEMwHhcNMTQwMTAyMTgyNDQ3WhcNMTQwMjAxMTgyNDQ3WjARMQ8wDQYDVQQD\n" + "EwZXZWJSVEMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMYRkbhmI7kVA/rM\n" + "czsZ+6JDhDvnkF+vn6yCAGuRPV03zuRqZtDy4N4to7PZu9PjqrRl7nDMXrG3YG9y\n" + "rlIAZ72KjcKKFAJxQyAKLCIdawKRyp8RdK3LEySWEZb0AV58IadqPZDTNHHRX8dz\n" + "5aTSMsbbkZ+C/OzTnbiMqLL/vg6jAgMBAAEwDQYJKoZIhvcNAQELBQADgYEAUflI\n" + "VUe5Krqf5RVa5C3u/UTAOAUJBiDS3VANTCLBxjuMsvqOG0WvaYWP3HYPgrz0jXK2\n" + "LJE/mGw3MyFHEqi81jh95J+ypl6xKW6Rm8jKLR87gUvCaVYn/Z4/P3AqcQTB7wOv\n" + "UD0A8qfhfDM+LK6rPAnCsVN0NRDY3jvd6rzix9M=\n" "-----END CERTIFICATE-----\n"; using webrtc::DTLSIdentityRequestObserver; diff --git a/talk/base/common.h b/talk/base/common.h index e8e89dac19..381b6b5ac4 100644 --- a/talk/base/common.h +++ b/talk/base/common.h @@ -93,6 +93,11 @@ inline void Unused(const void*) {} namespace talk_base { + +// If a debugger is attached, triggers a debugger breakpoint. If a debugger is +// not attached, forces program termination. +void Break(); + // LogAssert writes information about an assertion to the log. It's called by // Assert (and from the ASSERT macro in debug mode) before any other action // is taken (e.g. breaking the debugger, abort()ing, etc.). @@ -113,15 +118,10 @@ void SetCustomAssertLogger(AssertLogger logger); } // namespace talk_base - #if ENABLE_DEBUG namespace talk_base { -// If a debugger is attached, triggers a debugger breakpoint. If a debugger is -// not attached, forces program termination. -void Break(); - inline bool Assert(bool result, const char* function, const char* file, int line, const char* expression) { if (!result) { diff --git a/talk/base/helpers_unittest.cc b/talk/base/helpers_unittest.cc index 0fe1d5b36e..c2cfdb193d 100644 --- a/talk/base/helpers_unittest.cc +++ b/talk/base/helpers_unittest.cc @@ -29,14 +29,26 @@ #include "talk/base/gunit.h" #include "talk/base/helpers.h" +#include "talk/base/ssladapter.h" namespace talk_base { -TEST(RandomTest, TestCreateRandomId) { +class RandomTest : public testing::Test { + public: + static void SetUpTestCase() { + talk_base::InitializeSSL(); + } + + static void TearDownTestCase() { + talk_base::CleanupSSL(); + } +}; + +TEST_F(RandomTest, TestCreateRandomId) { CreateRandomId(); } -TEST(RandomTest, TestCreateRandomDouble) { +TEST_F(RandomTest, TestCreateRandomDouble) { for (int i = 0; i < 100; ++i) { double r = CreateRandomDouble(); EXPECT_GE(r, 0.0); @@ -44,11 +56,11 @@ TEST(RandomTest, TestCreateRandomDouble) { } } -TEST(RandomTest, TestCreateNonZeroRandomId) { +TEST_F(RandomTest, TestCreateNonZeroRandomId) { EXPECT_NE(0U, CreateRandomNonZeroId()); } -TEST(RandomTest, TestCreateRandomString) { +TEST_F(RandomTest, TestCreateRandomString) { std::string random = CreateRandomString(256); EXPECT_EQ(256U, random.size()); std::string random2; @@ -57,7 +69,7 @@ TEST(RandomTest, TestCreateRandomString) { EXPECT_EQ(256U, random2.size()); } -TEST(RandomTest, TestCreateRandomForTest) { +TEST_F(RandomTest, TestCreateRandomForTest) { // Make sure we get the output we expect. SetRandomTestMode(true); EXPECT_EQ(2154761789U, CreateRandomId()); diff --git a/talk/base/nssidentity.cc b/talk/base/nssidentity.cc index 7bacb44461..05c82de8a6 100644 --- a/talk/base/nssidentity.cc +++ b/talk/base/nssidentity.cc @@ -48,6 +48,7 @@ #include "talk/base/logging.h" #include "talk/base/helpers.h" #include "talk/base/nssstreamadapter.h" +#include "talk/base/safe_conversions.h" namespace talk_base { @@ -143,7 +144,7 @@ NSSCertificate *NSSCertificate::FromPEMString(const std::string &pem_string) { SECItem der_cert; der_cert.data = reinterpret_cast(const_cast( der.data())); - der_cert.len = der.size(); + der_cert.len = checked_cast(der.size()); CERTCertificate *cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &der_cert, NULL, PR_FALSE, PR_TRUE); @@ -472,10 +473,9 @@ SSLIdentity* NSSIdentity::FromPEMStrings(const std::string& private_key, return NULL; SECItem private_key_item; - private_key_item.data = - reinterpret_cast( - const_cast(private_key_der.c_str())); - private_key_item.len = private_key_der.size(); + private_key_item.data = reinterpret_cast( + const_cast(private_key_der.c_str())); + private_key_item.len = checked_cast(private_key_der.size()); const unsigned int key_usage = KU_KEY_ENCIPHERMENT | KU_DATA_ENCIPHERMENT | KU_DIGITAL_SIGNATURE; diff --git a/talk/base/nssstreamadapter.cc b/talk/base/nssstreamadapter.cc index acddb672b4..8965a6830f 100644 --- a/talk/base/nssstreamadapter.cc +++ b/talk/base/nssstreamadapter.cc @@ -53,6 +53,7 @@ #endif #include "talk/base/nssidentity.h" +#include "talk/base/safe_conversions.h" #include "talk/base/thread.h" namespace talk_base { @@ -86,7 +87,8 @@ static const SrtpCipherMapEntry kSrtpCipherMap[] = { // Implementation of NSPR methods static PRStatus StreamClose(PRFileDesc *socket) { - // Noop + ASSERT(!socket->lower); + socket->dtor(socket); return PR_SUCCESS; } @@ -96,7 +98,7 @@ static PRInt32 StreamRead(PRFileDesc *socket, void *buf, PRInt32 length) { int error; StreamResult result = stream->Read(buf, length, &read, &error); if (result == SR_SUCCESS) { - return read; + return checked_cast(read); } if (result == SR_EOS) { @@ -119,7 +121,7 @@ static PRInt32 StreamWrite(PRFileDesc *socket, const void *buf, int error; StreamResult result = stream->Write(buf, length, &written, &error); if (result == SR_SUCCESS) { - return written; + return checked_cast(written); } if (result == SR_BLOCK) { @@ -437,7 +439,7 @@ bool NSSStreamAdapter::Init() { LOG(LS_ERROR) << "Error disabling false start"; return false; } - + ssl_fd_ = ssl_fd; return true; @@ -515,7 +517,7 @@ int NSSStreamAdapter::BeginSSL() { SSL_LIBRARY_VERSION_TLS_1_1 : SSL_LIBRARY_VERSION_TLS_1_0; vrange.max = SSL_LIBRARY_VERSION_TLS_1_1; - + rv = SSL_VersionRangeSet(ssl_fd_, &vrange); if (rv != SECSuccess) { Error("BeginSSL", -1, false); @@ -525,7 +527,9 @@ int NSSStreamAdapter::BeginSSL() { // SRTP #ifdef HAVE_DTLS_SRTP if (!srtp_ciphers_.empty()) { - rv = SSL_SetSRTPCiphers(ssl_fd_, &srtp_ciphers_[0], srtp_ciphers_.size()); + rv = SSL_SetSRTPCiphers( + ssl_fd_, &srtp_ciphers_[0], + checked_cast(srtp_ciphers_.size())); if (rv != SECSuccess) { Error("BeginSSL", -1, false); return -1; @@ -644,7 +648,7 @@ StreamResult NSSStreamAdapter::Read(void* data, size_t data_len, return SR_ERROR; } - PRInt32 rv = PR_Read(ssl_fd_, data, data_len); + PRInt32 rv = PR_Read(ssl_fd_, data, checked_cast(data_len)); if (rv == 0) { return SR_EOS; @@ -681,7 +685,7 @@ StreamResult NSSStreamAdapter::Write(const void* data, size_t data_len, case SSL_CONNECTED: break; - + case SSL_ERROR: case SSL_CLOSED: default: @@ -690,7 +694,7 @@ StreamResult NSSStreamAdapter::Write(const void* data, size_t data_len, return SR_ERROR; } - PRInt32 rv = PR_Write(ssl_fd_, data, data_len); + PRInt32 rv = PR_Write(ssl_fd_, data, checked_cast(data_len)); // Error if (rv < 0) { @@ -879,11 +883,15 @@ bool NSSStreamAdapter::ExportKeyingMaterial(const std::string& label, bool use_context, uint8* result, size_t result_len) { - SECStatus rv = SSL_ExportKeyingMaterial(ssl_fd_, - label.c_str(), label.size(), - use_context, - context, context_len, - result, result_len); + SECStatus rv = SSL_ExportKeyingMaterial( + ssl_fd_, + label.c_str(), + checked_cast(label.size()), + use_context, + context, + checked_cast(context_len), + result, + checked_cast(result_len)); return rv == SECSuccess; } diff --git a/talk/base/safe_conversions.h b/talk/base/safe_conversions.h new file mode 100644 index 0000000000..d246d4ffce --- /dev/null +++ b/talk/base/safe_conversions.h @@ -0,0 +1,96 @@ +/* + * libjingle + * Copyright 2014, Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Borrowed from Chromium's src/base/numerics/safe_conversions.h. + +#ifndef TALK_BASE_SAFE_CONVERSIONS_H_ +#define TALK_BASE_SAFE_CONVERSIONS_H_ + +#include + +#include "talk/base/common.h" +#include "talk/base/logging.h" +#include "talk/base/safe_conversions_impl.h" + +namespace talk_base { + +inline void Check(bool condition) { + if (!condition) { + LOG(LS_ERROR) << "CHECK failed."; + Break(); + // The program should have crashed at this point. + } +} + +// Convenience function that returns true if the supplied value is in range +// for the destination type. +template +inline bool IsValueInRangeForNumericType(Src value) { + return internal::RangeCheck(value) == internal::TYPE_VALID; +} + +// checked_cast<> is analogous to static_cast<> for numeric types, +// except that it CHECKs that the specified numeric conversion will not +// overflow or underflow. NaN source will always trigger a CHECK. +template +inline Dst checked_cast(Src value) { + Check(IsValueInRangeForNumericType(value)); + return static_cast(value); +} + +// saturated_cast<> is analogous to static_cast<> for numeric types, except +// that the specified numeric conversion will saturate rather than overflow or +// underflow. NaN assignment to an integral will trigger a CHECK condition. +template +inline Dst saturated_cast(Src value) { + // Optimization for floating point values, which already saturate. + if (std::numeric_limits::is_iec559) + return static_cast(value); + + switch (internal::RangeCheck(value)) { + case internal::TYPE_VALID: + return static_cast(value); + + case internal::TYPE_UNDERFLOW: + return std::numeric_limits::min(); + + case internal::TYPE_OVERFLOW: + return std::numeric_limits::max(); + + // Should fail only on attempting to assign NaN to a saturated integer. + case internal::TYPE_INVALID: + Check(false); + return std::numeric_limits::max(); + } + + Check(false); // NOTREACHED(); + return static_cast(value); +} + +} // namespace talk_base + +#endif // TALK_BASE_SAFE_CONVERSIONS_H_ diff --git a/talk/base/safe_conversions_impl.h b/talk/base/safe_conversions_impl.h new file mode 100644 index 0000000000..391e5966b9 --- /dev/null +++ b/talk/base/safe_conversions_impl.h @@ -0,0 +1,205 @@ +/* + * libjingle + * Copyright 2014, Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Borrowed from Chromium's src/base/numerics/safe_conversions_impl.h. + +#ifndef TALK_BASE_SAFE_CONVERSIONS_IMPL_H_ +#define TALK_BASE_SAFE_CONVERSIONS_IMPL_H_ + +#include + +namespace talk_base { +namespace internal { + +enum DstSign { + DST_UNSIGNED, + DST_SIGNED +}; + +enum SrcSign { + SRC_UNSIGNED, + SRC_SIGNED +}; + +enum DstRange { + OVERLAPS_RANGE, + CONTAINS_RANGE +}; + +// Helper templates to statically determine if our destination type can contain +// all values represented by the source type. + +template ::is_signed ? + DST_SIGNED : DST_UNSIGNED, + SrcSign IsSrcSigned = std::numeric_limits::is_signed ? + SRC_SIGNED : SRC_UNSIGNED> +struct StaticRangeCheck {}; + +template +struct StaticRangeCheck { + typedef std::numeric_limits DstLimits; + typedef std::numeric_limits SrcLimits; + // Compare based on max_exponent, which we must compute for integrals. + static const size_t kDstMaxExponent = DstLimits::is_iec559 ? + DstLimits::max_exponent : + (sizeof(Dst) * 8 - 1); + static const size_t kSrcMaxExponent = SrcLimits::is_iec559 ? + SrcLimits::max_exponent : + (sizeof(Src) * 8 - 1); + static const DstRange value = kDstMaxExponent >= kSrcMaxExponent ? + CONTAINS_RANGE : OVERLAPS_RANGE; +}; + +template +struct StaticRangeCheck { + static const DstRange value = sizeof(Dst) >= sizeof(Src) ? + CONTAINS_RANGE : OVERLAPS_RANGE; +}; + +template +struct StaticRangeCheck { + typedef std::numeric_limits DstLimits; + typedef std::numeric_limits SrcLimits; + // Compare based on max_exponent, which we must compute for integrals. + static const size_t kDstMaxExponent = DstLimits::is_iec559 ? + DstLimits::max_exponent : + (sizeof(Dst) * 8 - 1); + static const size_t kSrcMaxExponent = sizeof(Src) * 8; + static const DstRange value = kDstMaxExponent >= kSrcMaxExponent ? + CONTAINS_RANGE : OVERLAPS_RANGE; +}; + +template +struct StaticRangeCheck { + static const DstRange value = OVERLAPS_RANGE; +}; + + +enum RangeCheckResult { + TYPE_VALID = 0, // Value can be represented by the destination type. + TYPE_UNDERFLOW = 1, // Value would overflow. + TYPE_OVERFLOW = 2, // Value would underflow. + TYPE_INVALID = 3 // Source value is invalid (i.e. NaN). +}; + +// This macro creates a RangeCheckResult from an upper and lower bound +// check by taking advantage of the fact that only NaN can be out of range in +// both directions at once. +#define BASE_NUMERIC_RANGE_CHECK_RESULT(is_in_upper_bound, is_in_lower_bound) \ + RangeCheckResult(((is_in_upper_bound) ? 0 : TYPE_OVERFLOW) | \ + ((is_in_lower_bound) ? 0 : TYPE_UNDERFLOW)) + +template ::is_signed ? + DST_SIGNED : DST_UNSIGNED, + SrcSign IsSrcSigned = std::numeric_limits::is_signed ? + SRC_SIGNED : SRC_UNSIGNED, + DstRange IsSrcRangeContained = StaticRangeCheck::value> +struct RangeCheckImpl {}; + +// The following templates are for ranges that must be verified at runtime. We +// split it into checks based on signedness to avoid confusing casts and +// compiler warnings on signed an unsigned comparisons. + +// Dst range always contains the result: nothing to check. +template +struct RangeCheckImpl { + static RangeCheckResult Check(Src value) { + return TYPE_VALID; + } +}; + +// Signed to signed narrowing. +template +struct RangeCheckImpl { + static RangeCheckResult Check(Src value) { + typedef std::numeric_limits DstLimits; + return DstLimits::is_iec559 ? + BASE_NUMERIC_RANGE_CHECK_RESULT( + value <= static_cast(DstLimits::max()), + value >= static_cast(DstLimits::max() * -1)) : + BASE_NUMERIC_RANGE_CHECK_RESULT( + value <= static_cast(DstLimits::max()), + value >= static_cast(DstLimits::min())); + } +}; + +// Unsigned to unsigned narrowing. +template +struct RangeCheckImpl { + static RangeCheckResult Check(Src value) { + typedef std::numeric_limits DstLimits; + return BASE_NUMERIC_RANGE_CHECK_RESULT( + value <= static_cast(DstLimits::max()), true); + } +}; + +// Unsigned to signed. +template +struct RangeCheckImpl { + static RangeCheckResult Check(Src value) { + typedef std::numeric_limits DstLimits; + return sizeof(Dst) > sizeof(Src) ? TYPE_VALID : + BASE_NUMERIC_RANGE_CHECK_RESULT( + value <= static_cast(DstLimits::max()), true); + } +}; + +// Signed to unsigned. +template +struct RangeCheckImpl { + static RangeCheckResult Check(Src value) { + typedef std::numeric_limits DstLimits; + typedef std::numeric_limits SrcLimits; + // Compare based on max_exponent, which we must compute for integrals. + static const size_t kDstMaxExponent = sizeof(Dst) * 8; + static const size_t kSrcMaxExponent = SrcLimits::is_iec559 ? + SrcLimits::max_exponent : + (sizeof(Src) * 8 - 1); + return (kDstMaxExponent >= kSrcMaxExponent) ? + BASE_NUMERIC_RANGE_CHECK_RESULT(true, value >= static_cast(0)) : + BASE_NUMERIC_RANGE_CHECK_RESULT( + value <= static_cast(DstLimits::max()), + value >= static_cast(0)); + } +}; + +template +inline RangeCheckResult RangeCheck(Src value) { + COMPILE_ASSERT(std::numeric_limits::is_specialized, + argument_must_be_numeric); + COMPILE_ASSERT(std::numeric_limits::is_specialized, + result_must_be_numeric); + return RangeCheckImpl::Check(value); +} + +} // namespace internal +} // namespace talk_base + +#endif // TALK_BASE_SAFE_CONVERSIONS_IMPL_H_ diff --git a/talk/base/sslidentity_unittest.cc b/talk/base/sslidentity_unittest.cc index b63b8b9d43..fdb165c9f6 100644 --- a/talk/base/sslidentity_unittest.cc +++ b/talk/base/sslidentity_unittest.cc @@ -177,32 +177,33 @@ TEST_F(SSLIdentityTest, DigestSHA512) { TEST_F(SSLIdentityTest, FromPEMStrings) { static const char kRSA_PRIVATE_KEY_PEM[] = "-----BEGIN RSA PRIVATE KEY-----\n" - "MIICXQIBAAKBgQDCueE4a9hDMZ3sbVZdlXOz9ZA+cvzie3zJ9gXnT/BCt9P4b9HE\n" - "vD/tr73YBqD3Wr5ZWScmyGYF9EMn0r3rzBxv6oooLU5TdUvOm4rzUjkCLQaQML8o\n" - "NxXq+qW/j3zUKGikLhaaAl/amaX2zSWUsRQ1CpngQ3+tmDNH4/25TncNmQIDAQAB\n" - "AoGAUcuU0Id0k10fMjYHZk4mCPzot2LD2Tr4Aznl5vFMQipHzv7hhZtx2xzMSRcX\n" - "vG+Qr6VkbcUWHgApyWubvZXCh3+N7Vo2aYdMAQ8XqmFpBdIrL5CVdVfqFfEMlgEy\n" - "LSZNG5klnrIfl3c7zQVovLr4eMqyl2oGfAqPQz75+fecv1UCQQD6wNHch9NbAG1q\n" - "yuFEhMARB6gDXb+5SdzFjjtTWW5uJfm4DcZLoYyaIZm0uxOwsUKd0Rsma+oGitS1\n" - "CXmuqfpPAkEAxszyN3vIdpD44SREEtyKZBMNOk5pEIIGdbeMJC5/XHvpxww9xkoC\n" - "+39NbvUZYd54uT+rafbx4QZKc0h9xA/HlwJBAL37lYVWy4XpPv1olWCKi9LbUCqs\n" - "vvQtyD1N1BkEayy9TQRsO09WKOcmigRqsTJwOx7DLaTgokEuspYvhagWVPUCQE/y\n" - "0+YkTbYBD1Xbs9SyBKXCU6uDJRWSdO6aZi2W1XloC9gUwDMiSJjD1Wwt/YsyYPJ+\n" - "/Hyc5yFL2l0KZimW/vkCQQCjuZ/lPcH46EuzhdbRfumDOG5N3ld7UhGI1TIRy17W\n" - "dGF90cG33/L6BfS8Ll+fkkW/2AMRk8FDvF4CZi2nfW4L\n" + "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMYRkbhmI7kVA/rM\n" + "czsZ+6JDhDvnkF+vn6yCAGuRPV03zuRqZtDy4N4to7PZu9PjqrRl7nDMXrG3YG9y\n" + "rlIAZ72KjcKKFAJxQyAKLCIdawKRyp8RdK3LEySWEZb0AV58IadqPZDTNHHRX8dz\n" + "5aTSMsbbkZ+C/OzTnbiMqLL/vg6jAgMBAAECgYAvgOs4FJcgvp+TuREx7YtiYVsH\n" + "mwQPTum2z/8VzWGwR8BBHBvIpVe1MbD/Y4seyI2aco/7UaisatSgJhsU46/9Y4fq\n" + "2TwXH9QANf4at4d9n/R6rzwpAJOpgwZgKvdQjkfrKTtgLV+/dawvpxUYkRH4JZM1\n" + "CVGukMfKNrSVH4Ap4QJBAOJmGV1ASPnB4r4nc99at7JuIJmd7fmuVUwUgYi4XgaR\n" + "WhScBsgYwZ/JoywdyZJgnbcrTDuVcWG56B3vXbhdpMsCQQDf9zeJrjnPZ3Cqm79y\n" + "kdqANep0uwZciiNiWxsQrCHztywOvbFhdp8iYVFG9EK8DMY41Y5TxUwsHD+67zao\n" + "ZNqJAkEA1suLUP/GvL8IwuRneQd2tWDqqRQ/Td3qq03hP7e77XtF/buya3Ghclo5\n" + "54czUR89QyVfJEC6278nzA7n2h1uVQJAcG6mztNL6ja/dKZjYZye2CY44QjSlLo0\n" + "MTgTSjdfg/28fFn2Jjtqf9Pi/X+50LWI/RcYMC2no606wRk9kyOuIQJBAK6VSAim\n" + "1pOEjsYQn0X5KEIrz1G3bfCbB848Ime3U2/FWlCHMr6ch8kCZ5d1WUeJD3LbwMNG\n" + "UCXiYxSsu20QNVw=\n" "-----END RSA PRIVATE KEY-----\n"; static const char kCERT_PEM[] = "-----BEGIN CERTIFICATE-----\n" - "MIIBmTCCAQICCQCPNJORW/M13DANBgkqhkiG9w0BAQUFADARMQ8wDQYDVQQDDAZ3\n" - "ZWJydGMwHhcNMTMwNjE0MjIzMDAxWhcNMTQwNjE0MjIzMDAxWjARMQ8wDQYDVQQD\n" - "DAZ3ZWJydGMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMK54Thr2EMxnext\n" - "Vl2Vc7P1kD5y/OJ7fMn2BedP8EK30/hv0cS8P+2vvdgGoPdavllZJybIZgX0QyfS\n" - "vevMHG/qiigtTlN1S86bivNSOQItBpAwvyg3Fer6pb+PfNQoaKQuFpoCX9qZpfbN\n" - "JZSxFDUKmeBDf62YM0fj/blOdw2ZAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAECMt\n" - "UZb35H8TnjGx4XPzco/kbnurMLFFWcuve/DwTsuf10Ia9N4md8LY0UtgIgtyNqWc\n" - "ZwyRMwxONF6ty3wcaIiPbGqiAa55T3YRuPibkRmck9CjrmM9JAtyvqHnpHd2TsBD\n" - "qCV42aXS3onOXDQ1ibuWq0fr0//aj0wo4KV474c=\n" + "MIIBmTCCAQKgAwIBAgIEbzBSAjANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDEwZX\n" + "ZWJSVEMwHhcNMTQwMTAyMTgyNDQ3WhcNMTQwMjAxMTgyNDQ3WjARMQ8wDQYDVQQD\n" + "EwZXZWJSVEMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMYRkbhmI7kVA/rM\n" + "czsZ+6JDhDvnkF+vn6yCAGuRPV03zuRqZtDy4N4to7PZu9PjqrRl7nDMXrG3YG9y\n" + "rlIAZ72KjcKKFAJxQyAKLCIdawKRyp8RdK3LEySWEZb0AV58IadqPZDTNHHRX8dz\n" + "5aTSMsbbkZ+C/OzTnbiMqLL/vg6jAgMBAAEwDQYJKoZIhvcNAQELBQADgYEAUflI\n" + "VUe5Krqf5RVa5C3u/UTAOAUJBiDS3VANTCLBxjuMsvqOG0WvaYWP3HYPgrz0jXK2\n" + "LJE/mGw3MyFHEqi81jh95J+ypl6xKW6Rm8jKLR87gUvCaVYn/Z4/P3AqcQTB7wOv\n" + "UD0A8qfhfDM+LK6rPAnCsVN0NRDY3jvd6rzix9M=\n" "-----END CERTIFICATE-----\n"; talk_base::scoped_ptr identity( diff --git a/talk/base/sslstreamadapter_unittest.cc b/talk/base/sslstreamadapter_unittest.cc index 5cc4bfda73..d489221954 100644 --- a/talk/base/sslstreamadapter_unittest.cc +++ b/talk/base/sslstreamadapter_unittest.cc @@ -49,32 +49,33 @@ static int kExporterContextLen = sizeof(kExporterContext); static const char kRSA_PRIVATE_KEY_PEM[] = "-----BEGIN RSA PRIVATE KEY-----\n" - "MIICXQIBAAKBgQDCueE4a9hDMZ3sbVZdlXOz9ZA+cvzie3zJ9gXnT/BCt9P4b9HE\n" - "vD/tr73YBqD3Wr5ZWScmyGYF9EMn0r3rzBxv6oooLU5TdUvOm4rzUjkCLQaQML8o\n" - "NxXq+qW/j3zUKGikLhaaAl/amaX2zSWUsRQ1CpngQ3+tmDNH4/25TncNmQIDAQAB\n" - "AoGAUcuU0Id0k10fMjYHZk4mCPzot2LD2Tr4Aznl5vFMQipHzv7hhZtx2xzMSRcX\n" - "vG+Qr6VkbcUWHgApyWubvZXCh3+N7Vo2aYdMAQ8XqmFpBdIrL5CVdVfqFfEMlgEy\n" - "LSZNG5klnrIfl3c7zQVovLr4eMqyl2oGfAqPQz75+fecv1UCQQD6wNHch9NbAG1q\n" - "yuFEhMARB6gDXb+5SdzFjjtTWW5uJfm4DcZLoYyaIZm0uxOwsUKd0Rsma+oGitS1\n" - "CXmuqfpPAkEAxszyN3vIdpD44SREEtyKZBMNOk5pEIIGdbeMJC5/XHvpxww9xkoC\n" - "+39NbvUZYd54uT+rafbx4QZKc0h9xA/HlwJBAL37lYVWy4XpPv1olWCKi9LbUCqs\n" - "vvQtyD1N1BkEayy9TQRsO09WKOcmigRqsTJwOx7DLaTgokEuspYvhagWVPUCQE/y\n" - "0+YkTbYBD1Xbs9SyBKXCU6uDJRWSdO6aZi2W1XloC9gUwDMiSJjD1Wwt/YsyYPJ+\n" - "/Hyc5yFL2l0KZimW/vkCQQCjuZ/lPcH46EuzhdbRfumDOG5N3ld7UhGI1TIRy17W\n" - "dGF90cG33/L6BfS8Ll+fkkW/2AMRk8FDvF4CZi2nfW4L\n" + "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMYRkbhmI7kVA/rM\n" + "czsZ+6JDhDvnkF+vn6yCAGuRPV03zuRqZtDy4N4to7PZu9PjqrRl7nDMXrG3YG9y\n" + "rlIAZ72KjcKKFAJxQyAKLCIdawKRyp8RdK3LEySWEZb0AV58IadqPZDTNHHRX8dz\n" + "5aTSMsbbkZ+C/OzTnbiMqLL/vg6jAgMBAAECgYAvgOs4FJcgvp+TuREx7YtiYVsH\n" + "mwQPTum2z/8VzWGwR8BBHBvIpVe1MbD/Y4seyI2aco/7UaisatSgJhsU46/9Y4fq\n" + "2TwXH9QANf4at4d9n/R6rzwpAJOpgwZgKvdQjkfrKTtgLV+/dawvpxUYkRH4JZM1\n" + "CVGukMfKNrSVH4Ap4QJBAOJmGV1ASPnB4r4nc99at7JuIJmd7fmuVUwUgYi4XgaR\n" + "WhScBsgYwZ/JoywdyZJgnbcrTDuVcWG56B3vXbhdpMsCQQDf9zeJrjnPZ3Cqm79y\n" + "kdqANep0uwZciiNiWxsQrCHztywOvbFhdp8iYVFG9EK8DMY41Y5TxUwsHD+67zao\n" + "ZNqJAkEA1suLUP/GvL8IwuRneQd2tWDqqRQ/Td3qq03hP7e77XtF/buya3Ghclo5\n" + "54czUR89QyVfJEC6278nzA7n2h1uVQJAcG6mztNL6ja/dKZjYZye2CY44QjSlLo0\n" + "MTgTSjdfg/28fFn2Jjtqf9Pi/X+50LWI/RcYMC2no606wRk9kyOuIQJBAK6VSAim\n" + "1pOEjsYQn0X5KEIrz1G3bfCbB848Ime3U2/FWlCHMr6ch8kCZ5d1WUeJD3LbwMNG\n" + "UCXiYxSsu20QNVw=\n" "-----END RSA PRIVATE KEY-----\n"; static const char kCERT_PEM[] = "-----BEGIN CERTIFICATE-----\n" - "MIIBmTCCAQICCQCPNJORW/M13DANBgkqhkiG9w0BAQUFADARMQ8wDQYDVQQDDAZ3\n" - "ZWJydGMwHhcNMTMwNjE0MjIzMDAxWhcNMTQwNjE0MjIzMDAxWjARMQ8wDQYDVQQD\n" - "DAZ3ZWJydGMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMK54Thr2EMxnext\n" - "Vl2Vc7P1kD5y/OJ7fMn2BedP8EK30/hv0cS8P+2vvdgGoPdavllZJybIZgX0QyfS\n" - "vevMHG/qiigtTlN1S86bivNSOQItBpAwvyg3Fer6pb+PfNQoaKQuFpoCX9qZpfbN\n" - "JZSxFDUKmeBDf62YM0fj/blOdw2ZAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAECMt\n" - "UZb35H8TnjGx4XPzco/kbnurMLFFWcuve/DwTsuf10Ia9N4md8LY0UtgIgtyNqWc\n" - "ZwyRMwxONF6ty3wcaIiPbGqiAa55T3YRuPibkRmck9CjrmM9JAtyvqHnpHd2TsBD\n" - "qCV42aXS3onOXDQ1ibuWq0fr0//aj0wo4KV474c=\n" + "MIIBmTCCAQKgAwIBAgIEbzBSAjANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDEwZX\n" + "ZWJSVEMwHhcNMTQwMTAyMTgyNDQ3WhcNMTQwMjAxMTgyNDQ3WjARMQ8wDQYDVQQD\n" + "EwZXZWJSVEMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMYRkbhmI7kVA/rM\n" + "czsZ+6JDhDvnkF+vn6yCAGuRPV03zuRqZtDy4N4to7PZu9PjqrRl7nDMXrG3YG9y\n" + "rlIAZ72KjcKKFAJxQyAKLCIdawKRyp8RdK3LEySWEZb0AV58IadqPZDTNHHRX8dz\n" + "5aTSMsbbkZ+C/OzTnbiMqLL/vg6jAgMBAAEwDQYJKoZIhvcNAQELBQADgYEAUflI\n" + "VUe5Krqf5RVa5C3u/UTAOAUJBiDS3VANTCLBxjuMsvqOG0WvaYWP3HYPgrz0jXK2\n" + "LJE/mGw3MyFHEqi81jh95J+ypl6xKW6Rm8jKLR87gUvCaVYn/Z4/P3AqcQTB7wOv\n" + "UD0A8qfhfDM+LK6rPAnCsVN0NRDY3jvd6rzix9M=\n" "-----END CERTIFICATE-----\n"; #define MAYBE_SKIP_TEST(feature) \ @@ -208,13 +209,16 @@ class SSLStreamAdapterTestBase : public testing::Test, ~SSLStreamAdapterTestBase() { // Put it back for the next test. talk_base::SetRandomTestMode(false); - talk_base::CleanupSSL(); } static void SetUpTestCase() { talk_base::InitializeSSL(); } + static void TearDownTestCase() { + talk_base::CleanupSSL(); + } + // Recreate the client/server identities with the specified validity period. // |not_before| and |not_after| are offsets from the current time in number // of seconds. diff --git a/talk/build/common.gypi b/talk/build/common.gypi index 50acb39ea9..4c762d1ddf 100644 --- a/talk/build/common.gypi +++ b/talk/build/common.gypi @@ -101,11 +101,10 @@ ['OS=="ios"', { 'defines': [ 'IOS', - 'HAVE_NSS_SSL_H=1', - 'SSL_USE_NSS_RNG', ], - 'defines!': [ - 'HAVE_OPENSSL_SSL_H=1', + }, { + 'defines': [ + 'HAVE_SCTP', ], }], ['OS=="ios" or (OS=="mac" and target_arch!="ia32")', { @@ -118,11 +117,41 @@ 'HASH_NAMESPACE=__gnu_cxx', 'POSIX', 'DISABLE_DYNAMIC_CAST', - 'HAVE_OPENSSL_SSL_H=1', # The POSIX standard says we have to define this. '_REENTRANT', ], }], + # TODO(jiayl): collapse the following 5 defines into 2, one for NSS and + # one for OPENSSL, and update the relevant code. + ['use_openssl==1', { + 'defines': [ + 'SSL_USE_OPENSSL', + 'HAVE_OPENSSL_SSL_H', + ], + 'dependencies': [ + '<(DEPTH)/third_party/openssl/openssl.gyp:openssl', + ], + }, { + 'defines': [ + 'SSL_USE_NSS', + 'HAVE_NSS_SSL_H', + 'SSL_USE_NSS_RNG', + ], + 'conditions': [ + ['os_posix == 1 and OS != "mac" and OS != "ios" and OS != "android"', { + 'dependencies': [ + '<(DEPTH)/build/linux/system.gyp:ssl', + ], + }], + ['OS == "mac" or OS == "ios" or OS == "win"', { + 'dependencies': [ + '<(DEPTH)/net/third_party/nss/ssl.gyp:libssl', + '<(DEPTH)/third_party/nss/nss.gyp:nspr', + '<(DEPTH)/third_party/nss/nss.gyp:nss', + ], + }], + ], + }], ], }, # target_defaults } diff --git a/talk/libjingle.gyp b/talk/libjingle.gyp index 38a165be80..f5632b1658 100755 --- a/talk/libjingle.gyp +++ b/talk/libjingle.gyp @@ -27,7 +27,6 @@ { 'includes': ['build/common.gypi'], - 'conditions': [ ['os_posix == 1 and OS != "mac" and OS != "ios"', { 'conditions': [ @@ -546,13 +545,6 @@ 'xmpp/xmppthread.h', ], 'conditions': [ - ['OS=="mac" or OS=="ios" or OS=="win"', { - 'dependencies': [ - # The chromium copy of nss should NOT be used on platforms that - # have NSS as system libraries, such as linux. - '<(DEPTH)/third_party/nss/nss.gyp:nss', - ], - }], ['OS=="android"', { 'sources': [ 'base/ifaddrs-android.cc', @@ -713,11 +705,6 @@ 'base/unixfilesystem.h', ], 'conditions': [ - ['OS=="linux" or OS=="android"', { - 'dependencies': [ - '<(DEPTH)/third_party/openssl/openssl.gyp:openssl', - ], - }], ['OS!="ios"', { 'sources': [ 'base/openssladapter.cc', @@ -779,8 +766,14 @@ { 'target_name': 'libjingle_media', 'type': 'static_library', + 'include_dirs': [ + # TODO(jiayl): move this into the direct_dependent_settings of + # usrsctp.gyp. + '<(DEPTH)/third_party/usrsctp', + ], 'dependencies': [ '<(DEPTH)/third_party/libyuv/libyuv.gyp:libyuv', + '<(DEPTH)/third_party/usrsctp/usrsctp.gyp:usrsctplib', '<(webrtc_root)/modules/modules.gyp:video_capture_module', '<(webrtc_root)/modules/modules.gyp:video_render_module', '<(webrtc_root)/video_engine/video_engine.gyp:video_engine_core', @@ -847,9 +840,8 @@ 'media/devices/filevideocapturer.h', 'media/devices/videorendererfactory.h', 'media/other/linphonemediaengine.h', - # TODO(ronghuawu): Enable when SCTP is ready. - # 'media/sctp/sctpdataengine.cc', - # 'media/sctp/sctpdataengine.h', + 'media/sctp/sctpdataengine.cc', + 'media/sctp/sctpdataengine.h', 'media/webrtc/webrtccommon.h', 'media/webrtc/webrtcexport.h', 'media/webrtc/webrtcmediaengine.h', @@ -965,6 +957,13 @@ # libjpeg which pulls in libyuv which currently disabled. '../third_party/libyuv/include', ], + 'dependencies!': [ + '<(DEPTH)/third_party/usrsctp/usrsctp.gyp:usrsctplib', + ], + 'sources!': [ + 'media/sctp/sctpdataengine.cc', + 'media/sctp/sctpdataengine.h', + ], }], ['OS=="android"', { 'sources': [ @@ -989,10 +988,6 @@ '<(DEPTH)/testing/gtest/include', ], }, - 'defines': [ - # TODO(ronghuawu): enable SCTP when it's ready. - # 'HAVE_SCTP', - ], 'sources': [ 'p2p/base/asyncstuntcpsocket.cc', 'p2p/base/asyncstuntcpsocket.h', diff --git a/talk/libjingle_tests.gyp b/talk/libjingle_tests.gyp index 201052af13..9987ed8a49 100755 --- a/talk/libjingle_tests.gyp +++ b/talk/libjingle_tests.gyp @@ -279,6 +279,9 @@ 'media/base/videoengine_unittest.h', 'media/devices/dummydevicemanager_unittest.cc', 'media/devices/filevideocapturer_unittest.cc', + # TODO(jiayl): Enable the SCTP test once the memcheck and tsan bots + # failures are fixed (issue 2846). + #'media/sctp/sctpdataengine_unittest.cc', 'media/webrtc/webrtcpassthroughrender_unittest.cc', 'media/webrtc/webrtcvideocapturer_unittest.cc', # Omitted because depends on non-open-source testdata files. @@ -304,6 +307,11 @@ }, }, }], + ['OS=="ios"', { + 'sources!': [ + 'media/sctp/sctpdataengine_unittest.cc', + ], + }], ], }, # target libjingle_media_unittest { diff --git a/talk/media/base/rtpdataengine_unittest.cc b/talk/media/base/rtpdataengine_unittest.cc index 3c8318493b..640c18dbfc 100644 --- a/talk/media/base/rtpdataengine_unittest.cc +++ b/talk/media/base/rtpdataengine_unittest.cc @@ -31,6 +31,7 @@ #include "talk/base/gunit.h" #include "talk/base/helpers.h" #include "talk/base/scoped_ptr.h" +#include "talk/base/ssladapter.h" #include "talk/base/timing.h" #include "talk/media/base/constants.h" #include "talk/media/base/fakenetworkinterface.h" @@ -82,6 +83,14 @@ class FakeDataReceiver : public sigslot::has_slots<> { class RtpDataMediaChannelTest : public testing::Test { protected: + static void SetUpTestCase() { + talk_base::InitializeSSL(); + } + + static void TearDownTestCase() { + talk_base::CleanupSSL(); + } + virtual void SetUp() { // Seed needed for each test to satisfy expectations. iface_.reset(new cricket::FakeNetworkInterface()); diff --git a/talk/media/sctp/sctpdataengine.cc b/talk/media/sctp/sctpdataengine.cc index 03bbdcaa1f..37b17d3a51 100644 --- a/talk/media/sctp/sctpdataengine.cc +++ b/talk/media/sctp/sctpdataengine.cc @@ -35,6 +35,7 @@ #include "talk/base/buffer.h" #include "talk/base/helpers.h" #include "talk/base/logging.h" +#include "talk/base/safe_conversions.h" #include "talk/media/base/codec.h" #include "talk/media/base/constants.h" #include "talk/media/base/streamparams.h" @@ -560,7 +561,7 @@ bool SctpDataMediaChannel::SendData( send_res = usrsctp_sendv(sock_, payload.data(), static_cast(payload.length()), NULL, 0, &spa, - static_cast(sizeof(spa)), + talk_base::checked_cast(sizeof(spa)), SCTP_SENDV_SPA, 0); if (send_res < 0) { if (errno == EWOULDBLOCK) { @@ -919,15 +920,16 @@ bool SctpDataMediaChannel::SendQueuedStreamResets() { &reset_stream_buf[0]); resetp->srs_assoc_id = SCTP_ALL_ASSOC; resetp->srs_flags = SCTP_STREAM_RESET_INCOMING | SCTP_STREAM_RESET_OUTGOING; - resetp->srs_number_streams = num_streams; + resetp->srs_number_streams = talk_base::checked_cast(num_streams); int result_idx = 0; for (StreamSet::iterator it = queued_reset_streams_.begin(); it != queued_reset_streams_.end(); ++it) { resetp->srs_stream_list[result_idx++] = *it; } - int ret = usrsctp_setsockopt(sock_, IPPROTO_SCTP, SCTP_RESET_STREAMS, resetp, - reset_stream_buf.size()); + int ret = usrsctp_setsockopt( + sock_, IPPROTO_SCTP, SCTP_RESET_STREAMS, resetp, + talk_base::checked_cast(reset_stream_buf.size())); if (ret < 0) { LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to send a stream reset for " << num_streams << " streams"; diff --git a/talk/media/sctp/sctpdataengine_unittest.cc b/talk/media/sctp/sctpdataengine_unittest.cc index 6371300b53..650c785cb1 100644 --- a/talk/media/sctp/sctpdataengine_unittest.cc +++ b/talk/media/sctp/sctpdataengine_unittest.cc @@ -39,6 +39,7 @@ #include "talk/base/messagehandler.h" #include "talk/base/messagequeue.h" #include "talk/base/scoped_ptr.h" +#include "talk/base/ssladapter.h" #include "talk/base/thread.h" #include "talk/media/base/constants.h" #include "talk/media/base/mediachannel.h" @@ -215,6 +216,16 @@ class SignalChannelClosedReopener : public sigslot::has_slots<> { class SctpDataMediaChannelTest : public testing::Test, public sigslot::has_slots<> { protected: + // usrsctp uses the NSS random number generator on non-Android platforms, + // so we need to initialize SSL. + static void SetUpTestCase() { + talk_base::InitializeSSL(); + } + + static void TearDownTestCase() { + talk_base::CleanupSSL(); + } + virtual void SetUp() { engine_.reset(new cricket::SctpDataEngine()); }