diff --git a/pc/peerconnection.cc b/pc/peerconnection.cc index b232a26b81..77e8e024f1 100644 --- a/pc/peerconnection.cc +++ b/pc/peerconnection.cc @@ -1285,6 +1285,18 @@ RTCError PeerConnection::SetBitrate(const BitrateParameters& bitrate) { return RTCError::OK(); } +std::unique_ptr +PeerConnection::GetRemoteAudioSSLCertificate() { + if (!session_) { + return nullptr; + } + auto* voice_channel = session_->voice_channel(); + if (!voice_channel) { + return nullptr; + } + return GetRemoteSSLCertificate(voice_channel->transport_name()); +} + bool PeerConnection::StartRtcEventLog(rtc::PlatformFile file, int64_t max_size_bytes) { return worker_thread()->Invoke( diff --git a/pc/peerconnection.h b/pc/peerconnection.h index 1913e601e0..df5085bf17 100644 --- a/pc/peerconnection.h +++ b/pc/peerconnection.h @@ -70,6 +70,15 @@ class PeerConnection : public PeerConnectionInterface, // directly via this getter. virtual WebRtcSession* session() { return session_; } + // Gets the DTLS SSL certificate associated with the audio transport on the + // remote side. This will become populated once the DTLS connection with the + // peer has been completed, as indicated by the ICE connection state + // transitioning to kIceConnectionCompleted. + // Note that this will be removed once we implement RTCDtlsTransport which + // has standardized method for getting this information. + // See https://www.w3.org/TR/webrtc/#rtcdtlstransport-interface + std::unique_ptr GetRemoteAudioSSLCertificate(); + rtc::scoped_refptr CreateDtmfSender( AudioTrackInterface* track) override; diff --git a/pc/peerconnection_integrationtest.cc b/pc/peerconnection_integrationtest.cc index 5ebf0315fa..e01230101a 100644 --- a/pc/peerconnection_integrationtest.cc +++ b/pc/peerconnection_integrationtest.cc @@ -25,6 +25,7 @@ #include "api/fakemetricsobserver.h" #include "api/mediastreaminterface.h" #include "api/peerconnectioninterface.h" +#include "api/peerconnectionproxy.h" #include "api/test/fakeconstraints.h" #include "media/engine/fakewebrtcvideoengine.h" #include "p2p/base/p2pconstants.h" @@ -66,8 +67,10 @@ using webrtc::MockDataChannelObserver; using webrtc::MockSetSessionDescriptionObserver; using webrtc::MockStatsObserver; using webrtc::ObserverInterface; +using webrtc::PeerConnection; using webrtc::PeerConnectionInterface; using webrtc::PeerConnectionFactory; +using webrtc::PeerConnectionProxy; using webrtc::SessionDescriptionInterface; using webrtc::StreamCollectionInterface; @@ -1290,6 +1293,55 @@ TEST_F(PeerConnectionIntegrationTest, EndToEndCallWithSdes) { kMaxWaitForFramesMs); } +// Tests that the GetRemoteAudioSSLCertificate method returns the remote DTLS +// certificate once the DTLS handshake has finished. +TEST_F(PeerConnectionIntegrationTest, + GetRemoteAudioSSLCertificateReturnsExchangedCertificate) { + auto GetRemoteAudioSSLCertificate = [](PeerConnectionWrapper* wrapper) { + auto pci = reinterpret_cast(wrapper->pc()); + auto pc = reinterpret_cast(pci->internal()); + return pc->GetRemoteAudioSSLCertificate(); + }; + + auto caller_cert = rtc::RTCCertificate::FromPEM(kRsaPems[0]); + auto callee_cert = rtc::RTCCertificate::FromPEM(kRsaPems[1]); + + // Configure each side with a known certificate so they can be compared later. + PeerConnectionInterface::RTCConfiguration caller_config; + caller_config.enable_dtls_srtp.emplace(true); + caller_config.certificates.push_back(caller_cert); + PeerConnectionInterface::RTCConfiguration callee_config; + callee_config.enable_dtls_srtp.emplace(true); + callee_config.certificates.push_back(callee_cert); + ASSERT_TRUE( + CreatePeerConnectionWrappersWithConfig(caller_config, callee_config)); + ConnectFakeSignaling(); + + // When first initialized, there should not be a remote SSL certificate (and + // calling this method should not crash). + EXPECT_EQ(nullptr, GetRemoteAudioSSLCertificate(caller())); + EXPECT_EQ(nullptr, GetRemoteAudioSSLCertificate(callee())); + + caller()->AddAudioOnlyMediaStream(); + callee()->AddAudioOnlyMediaStream(); + caller()->CreateAndSetAndSignalOffer(); + ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); + ASSERT_TRUE_WAIT(DtlsConnected(), kDefaultTimeout); + + // Once DTLS has been connected, each side should return the other's SSL + // certificate when calling GetRemoteAudioSSLCertificate. + + auto caller_remote_cert = GetRemoteAudioSSLCertificate(caller()); + ASSERT_TRUE(caller_remote_cert); + EXPECT_EQ(callee_cert->ssl_certificate().ToPEMString(), + caller_remote_cert->ToPEMString()); + + auto callee_remote_cert = GetRemoteAudioSSLCertificate(callee()); + ASSERT_TRUE(callee_remote_cert); + EXPECT_EQ(caller_cert->ssl_certificate().ToPEMString(), + callee_remote_cert->ToPEMString()); +} + // This test sets up a call between two parties (using DTLS) and tests that we // can get a video aspect ratio of 16:9. TEST_F(PeerConnectionIntegrationTest, SendAndReceive16To9AspectRatio) {