mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-16 15:20:42 +01:00
Implement certificate chain stats.
There was an implementation, but it relied on SSLCertificate::GetChain, which was never implemented. Except in the fake certificate classes used by the stats collector tests, hence the tests were passing. Instead of implementing GetChain, we decided (in https://webrtc-review.googlesource.com/c/src/+/6500) to add methods that return a SSLCertChain directly, since it results in a somewhat cleaner object model. So this CL switches everything to use the "chain" methods, and gets rid of the obsolete methods and member variables. Bug: webrtc:8920 Change-Id: Ie9d7d53654ba859535462521b54c788adec7badf Reviewed-on: https://webrtc-review.googlesource.com/56961 Commit-Queue: Taylor Brandstetter <deadbeef@webrtc.org> Reviewed-by: Zhi Huang <zhihuang@webrtc.org> Cr-Commit-Position: refs/heads/master@{#22177}
This commit is contained in:
parent
29ef9f066c
commit
c392866d86
34 changed files with 241 additions and 314 deletions
|
@ -309,15 +309,6 @@ bool DtlsTransport::SetRemoteFingerprint(const std::string& digest_alg,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<rtc::SSLCertificate> DtlsTransport::GetRemoteSSLCertificate()
|
|
||||||
const {
|
|
||||||
if (!dtls_) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return dtls_->GetPeerCertificate();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<rtc::SSLCertChain> DtlsTransport::GetRemoteSSLCertChain()
|
std::unique_ptr<rtc::SSLCertChain> DtlsTransport::GetRemoteSSLCertChain()
|
||||||
const {
|
const {
|
||||||
if (!dtls_) {
|
if (!dtls_) {
|
||||||
|
|
|
@ -143,14 +143,9 @@ class DtlsTransport : public DtlsTransportInternal {
|
||||||
// Find out which DTLS cipher was negotiated
|
// Find out which DTLS cipher was negotiated
|
||||||
bool GetSslCipherSuite(int* cipher) override;
|
bool GetSslCipherSuite(int* cipher) override;
|
||||||
|
|
||||||
// Once DTLS has been established, this method retrieves the certificate in
|
// Once DTLS has been established, this method retrieves the certificate
|
||||||
// use by the remote peer, for use in external identity verification.
|
// chain in use by the remote peer, for use in external identity
|
||||||
// TODO(zhihuang): Remove all the SSLCertificate versions of these methods,
|
// verification.
|
||||||
// and replace them with the SSLCertChain versions. Implement the
|
|
||||||
// PeerConnection::GetRemoteSSLCertificate using the SSLCertChain version.
|
|
||||||
std::unique_ptr<rtc::SSLCertificate> GetRemoteSSLCertificate() const override;
|
|
||||||
|
|
||||||
// Version of the above method that returns the full certificate chain.
|
|
||||||
std::unique_ptr<rtc::SSLCertChain> GetRemoteSSLCertChain() const override;
|
std::unique_ptr<rtc::SSLCertChain> GetRemoteSSLCertChain() const override;
|
||||||
|
|
||||||
// Once DTLS has established (i.e., this ice_transport is writable), this
|
// Once DTLS has established (i.e., this ice_transport is writable), this
|
||||||
|
|
|
@ -515,8 +515,8 @@ TEST_F(DtlsTransportTest, TestCertificatesBeforeConnect) {
|
||||||
auto certificate2 = client2_.dtls_transport()->GetLocalCertificate();
|
auto certificate2 = client2_.dtls_transport()->GetLocalCertificate();
|
||||||
ASSERT_NE(certificate1->ssl_certificate().ToPEMString(),
|
ASSERT_NE(certificate1->ssl_certificate().ToPEMString(),
|
||||||
certificate2->ssl_certificate().ToPEMString());
|
certificate2->ssl_certificate().ToPEMString());
|
||||||
ASSERT_FALSE(client1_.dtls_transport()->GetRemoteSSLCertificate());
|
ASSERT_FALSE(client1_.dtls_transport()->GetRemoteSSLCertChain());
|
||||||
ASSERT_FALSE(client2_.dtls_transport()->GetRemoteSSLCertificate());
|
ASSERT_FALSE(client2_.dtls_transport()->GetRemoteSSLCertChain());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test Certificates state after connection.
|
// Test Certificates state after connection.
|
||||||
|
@ -531,15 +531,17 @@ TEST_F(DtlsTransportTest, TestCertificatesAfterConnect) {
|
||||||
certificate2->ssl_certificate().ToPEMString());
|
certificate2->ssl_certificate().ToPEMString());
|
||||||
|
|
||||||
// Each side's remote certificate is the other side's local certificate.
|
// Each side's remote certificate is the other side's local certificate.
|
||||||
std::unique_ptr<rtc::SSLCertificate> remote_cert1 =
|
std::unique_ptr<rtc::SSLCertChain> remote_cert1 =
|
||||||
client1_.dtls_transport()->GetRemoteSSLCertificate();
|
client1_.dtls_transport()->GetRemoteSSLCertChain();
|
||||||
ASSERT_TRUE(remote_cert1);
|
ASSERT_TRUE(remote_cert1);
|
||||||
ASSERT_EQ(remote_cert1->ToPEMString(),
|
ASSERT_EQ(1u, remote_cert1->GetSize());
|
||||||
|
ASSERT_EQ(remote_cert1->Get(0).ToPEMString(),
|
||||||
certificate2->ssl_certificate().ToPEMString());
|
certificate2->ssl_certificate().ToPEMString());
|
||||||
std::unique_ptr<rtc::SSLCertificate> remote_cert2 =
|
std::unique_ptr<rtc::SSLCertChain> remote_cert2 =
|
||||||
client2_.dtls_transport()->GetRemoteSSLCertificate();
|
client2_.dtls_transport()->GetRemoteSSLCertChain();
|
||||||
ASSERT_TRUE(remote_cert2);
|
ASSERT_TRUE(remote_cert2);
|
||||||
ASSERT_EQ(remote_cert2->ToPEMString(),
|
ASSERT_EQ(1u, remote_cert2->GetSize());
|
||||||
|
ASSERT_EQ(remote_cert2->Get(0).ToPEMString(),
|
||||||
certificate1->ssl_certificate().ToPEMString());
|
certificate1->ssl_certificate().ToPEMString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,10 +78,6 @@ class DtlsTransportInternal : public rtc::PacketTransportInternal {
|
||||||
virtual bool SetLocalCertificate(
|
virtual bool SetLocalCertificate(
|
||||||
const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) = 0;
|
const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) = 0;
|
||||||
|
|
||||||
// Gets a copy of the remote side's SSL certificate.
|
|
||||||
virtual std::unique_ptr<rtc::SSLCertificate> GetRemoteSSLCertificate()
|
|
||||||
const = 0;
|
|
||||||
|
|
||||||
// Gets a copy of the remote side's SSL certificate chain.
|
// Gets a copy of the remote side's SSL certificate chain.
|
||||||
virtual std::unique_ptr<rtc::SSLCertChain> GetRemoteSSLCertChain() const = 0;
|
virtual std::unique_ptr<rtc::SSLCertChain> GetRemoteSSLCertChain() const = 0;
|
||||||
|
|
||||||
|
|
|
@ -178,14 +178,9 @@ class FakeDtlsTransport : public DtlsTransportInternal {
|
||||||
rtc::scoped_refptr<rtc::RTCCertificate> GetLocalCertificate() const override {
|
rtc::scoped_refptr<rtc::RTCCertificate> GetLocalCertificate() const override {
|
||||||
return local_cert_;
|
return local_cert_;
|
||||||
}
|
}
|
||||||
std::unique_ptr<rtc::SSLCertificate> GetRemoteSSLCertificate()
|
|
||||||
const override {
|
|
||||||
return remote_cert_ ? std::unique_ptr<rtc::SSLCertificate>(
|
|
||||||
remote_cert_->GetReference())
|
|
||||||
: nullptr;
|
|
||||||
}
|
|
||||||
std::unique_ptr<rtc::SSLCertChain> GetRemoteSSLCertChain() const override {
|
std::unique_ptr<rtc::SSLCertChain> GetRemoteSSLCertChain() const override {
|
||||||
return nullptr;
|
return remote_cert_ ? rtc::MakeUnique<rtc::SSLCertChain>(remote_cert_)
|
||||||
|
: nullptr;
|
||||||
}
|
}
|
||||||
bool ExportKeyingMaterial(const std::string& label,
|
bool ExportKeyingMaterial(const std::string& label,
|
||||||
const uint8_t* context,
|
const uint8_t* context,
|
||||||
|
|
|
@ -243,12 +243,12 @@ JsepTransportController::GetLocalCertificate(
|
||||||
return t->GetLocalCertificate();
|
return t->GetLocalCertificate();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<rtc::SSLCertificate>
|
std::unique_ptr<rtc::SSLCertChain>
|
||||||
JsepTransportController::GetRemoteSSLCertificate(
|
JsepTransportController::GetRemoteSSLCertChain(
|
||||||
const std::string& transport_name) const {
|
const std::string& transport_name) const {
|
||||||
if (!network_thread_->IsCurrent()) {
|
if (!network_thread_->IsCurrent()) {
|
||||||
return network_thread_->Invoke<std::unique_ptr<rtc::SSLCertificate>>(
|
return network_thread_->Invoke<std::unique_ptr<rtc::SSLCertChain>>(
|
||||||
RTC_FROM_HERE, [&] { return GetRemoteSSLCertificate(transport_name); });
|
RTC_FROM_HERE, [&] { return GetRemoteSSLCertChain(transport_name); });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the certificate from the RTP channel's DTLS handshake. Should be
|
// Get the certificate from the RTP channel's DTLS handshake. Should be
|
||||||
|
@ -259,7 +259,7 @@ JsepTransportController::GetRemoteSSLCertificate(
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return dtls->GetRemoteSSLCertificate();
|
return dtls->GetRemoteSSLCertChain();
|
||||||
}
|
}
|
||||||
|
|
||||||
void JsepTransportController::MaybeStartGathering() {
|
void JsepTransportController::MaybeStartGathering() {
|
||||||
|
|
|
@ -122,9 +122,9 @@ class JsepTransportController : public sigslot::has_slots<>,
|
||||||
const rtc::scoped_refptr<rtc::RTCCertificate>& certificate);
|
const rtc::scoped_refptr<rtc::RTCCertificate>& certificate);
|
||||||
rtc::scoped_refptr<rtc::RTCCertificate> GetLocalCertificate(
|
rtc::scoped_refptr<rtc::RTCCertificate> GetLocalCertificate(
|
||||||
const std::string& mid) const;
|
const std::string& mid) const;
|
||||||
// Caller owns returned certificate. This method mainly exists for stats
|
// Caller owns returned certificate chain. This method mainly exists for
|
||||||
// reporting.
|
// stats reporting.
|
||||||
std::unique_ptr<rtc::SSLCertificate> GetRemoteSSLCertificate(
|
std::unique_ptr<rtc::SSLCertChain> GetRemoteSSLCertChain(
|
||||||
const std::string& mid) const;
|
const std::string& mid) const;
|
||||||
// Get negotiated role, if one has been negotiated.
|
// Get negotiated role, if one has been negotiated.
|
||||||
rtc::Optional<rtc::SSLRole> GetDtlsRole(const std::string& mid) const;
|
rtc::Optional<rtc::SSLRole> GetDtlsRole(const std::string& mid) const;
|
||||||
|
|
|
@ -462,7 +462,7 @@ TEST_F(JsepTransportControllerTest, SetAndGetLocalCertificate) {
|
||||||
EXPECT_FALSE(transport_controller_->SetLocalCertificate(certificate2));
|
EXPECT_FALSE(transport_controller_->SetLocalCertificate(certificate2));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(JsepTransportControllerTest, GetRemoteSSLCertificate) {
|
TEST_F(JsepTransportControllerTest, GetRemoteSSLCertChain) {
|
||||||
CreateJsepTransportController(JsepTransportController::Config());
|
CreateJsepTransportController(JsepTransportController::Config());
|
||||||
auto description = CreateSessionDescriptionWithBundleGroup();
|
auto description = CreateSessionDescriptionWithBundleGroup();
|
||||||
EXPECT_TRUE(transport_controller_
|
EXPECT_TRUE(transport_controller_
|
||||||
|
@ -473,14 +473,15 @@ TEST_F(JsepTransportControllerTest, GetRemoteSSLCertificate) {
|
||||||
auto fake_audio_dtls = static_cast<FakeDtlsTransport*>(
|
auto fake_audio_dtls = static_cast<FakeDtlsTransport*>(
|
||||||
transport_controller_->GetDtlsTransport(kAudioMid1));
|
transport_controller_->GetDtlsTransport(kAudioMid1));
|
||||||
fake_audio_dtls->SetRemoteSSLCertificate(&fake_certificate);
|
fake_audio_dtls->SetRemoteSSLCertificate(&fake_certificate);
|
||||||
std::unique_ptr<rtc::SSLCertificate> returned_certificate =
|
std::unique_ptr<rtc::SSLCertChain> returned_cert_chain =
|
||||||
transport_controller_->GetRemoteSSLCertificate(kAudioMid1);
|
transport_controller_->GetRemoteSSLCertChain(kAudioMid1);
|
||||||
EXPECT_TRUE(returned_certificate);
|
ASSERT_TRUE(returned_cert_chain);
|
||||||
|
ASSERT_EQ(1u, returned_cert_chain->GetSize());
|
||||||
EXPECT_EQ(fake_certificate.ToPEMString(),
|
EXPECT_EQ(fake_certificate.ToPEMString(),
|
||||||
returned_certificate->ToPEMString());
|
returned_cert_chain->Get(0).ToPEMString());
|
||||||
|
|
||||||
// Should fail if called for a nonexistant transport.
|
// Should fail if called for a nonexistant transport.
|
||||||
EXPECT_FALSE(transport_controller_->GetRemoteSSLCertificate(kAudioMid2));
|
EXPECT_FALSE(transport_controller_->GetRemoteSSLCertChain(kAudioMid2));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(JsepTransportControllerTest, GetDtlsRole) {
|
TEST_F(JsepTransportControllerTest, GetDtlsRole) {
|
||||||
|
|
|
@ -2945,12 +2945,11 @@ void PeerConnection::SetAudioRecording(bool recording) {
|
||||||
|
|
||||||
std::unique_ptr<rtc::SSLCertificate>
|
std::unique_ptr<rtc::SSLCertificate>
|
||||||
PeerConnection::GetRemoteAudioSSLCertificate() {
|
PeerConnection::GetRemoteAudioSSLCertificate() {
|
||||||
auto audio_transceiver = GetFirstAudioTransceiver();
|
std::unique_ptr<rtc::SSLCertChain> chain = GetRemoteAudioSSLCertChain();
|
||||||
if (!audio_transceiver || !audio_transceiver->internal()->channel()) {
|
if (!chain || !chain->GetSize()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return GetRemoteSSLCertificate(
|
return chain->Get(0).GetUniqueReference();
|
||||||
audio_transceiver->internal()->channel()->transport_name());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<rtc::SSLCertChain>
|
std::unique_ptr<rtc::SSLCertChain>
|
||||||
|
@ -5007,9 +5006,9 @@ bool PeerConnection::GetLocalCertificate(
|
||||||
certificate);
|
certificate);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<rtc::SSLCertificate> PeerConnection::GetRemoteSSLCertificate(
|
std::unique_ptr<rtc::SSLCertChain> PeerConnection::GetRemoteSSLCertChain(
|
||||||
const std::string& transport_name) {
|
const std::string& transport_name) {
|
||||||
return transport_controller_->GetRemoteSSLCertificate(transport_name);
|
return transport_controller_->GetRemoteSSLCertChain(transport_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
cricket::DataChannelType PeerConnection::data_channel_type() const {
|
cricket::DataChannelType PeerConnection::data_channel_type() const {
|
||||||
|
|
|
@ -242,7 +242,7 @@ class PeerConnection : public PeerConnectionInternal,
|
||||||
bool GetLocalCertificate(
|
bool GetLocalCertificate(
|
||||||
const std::string& transport_name,
|
const std::string& transport_name,
|
||||||
rtc::scoped_refptr<rtc::RTCCertificate>* certificate) override;
|
rtc::scoped_refptr<rtc::RTCCertificate>* certificate) override;
|
||||||
std::unique_ptr<rtc::SSLCertificate> GetRemoteSSLCertificate(
|
std::unique_ptr<rtc::SSLCertChain> GetRemoteSSLCertChain(
|
||||||
const std::string& transport_name) override;
|
const std::string& transport_name) override;
|
||||||
bool IceRestartPending(const std::string& content_name) const override;
|
bool IceRestartPending(const std::string& content_name) const override;
|
||||||
bool NeedsIceRestart(const std::string& content_name) const override;
|
bool NeedsIceRestart(const std::string& content_name) const override;
|
||||||
|
|
|
@ -71,7 +71,7 @@ class PeerConnectionInternal : public PeerConnectionInterface {
|
||||||
virtual bool GetLocalCertificate(
|
virtual bool GetLocalCertificate(
|
||||||
const std::string& transport_name,
|
const std::string& transport_name,
|
||||||
rtc::scoped_refptr<rtc::RTCCertificate>* certificate) = 0;
|
rtc::scoped_refptr<rtc::RTCCertificate>* certificate) = 0;
|
||||||
virtual std::unique_ptr<rtc::SSLCertificate> GetRemoteSSLCertificate(
|
virtual std::unique_ptr<rtc::SSLCertChain> GetRemoteSSLCertChain(
|
||||||
const std::string& transport_name) = 0;
|
const std::string& transport_name) = 0;
|
||||||
|
|
||||||
// Returns true if there was an ICE restart initiated by the remote offer.
|
// Returns true if there was an ICE restart initiated by the remote offer.
|
||||||
|
|
|
@ -1234,13 +1234,13 @@ RTCStatsCollector::PrepareTransportCertificateStats_n(
|
||||||
rtc::scoped_refptr<rtc::RTCCertificate> local_certificate;
|
rtc::scoped_refptr<rtc::RTCCertificate> local_certificate;
|
||||||
if (pc_->GetLocalCertificate(transport_name, &local_certificate)) {
|
if (pc_->GetLocalCertificate(transport_name, &local_certificate)) {
|
||||||
certificate_stats_pair.local =
|
certificate_stats_pair.local =
|
||||||
local_certificate->ssl_certificate().GetStats();
|
local_certificate->ssl_cert_chain().GetStats();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<rtc::SSLCertificate> remote_certificate =
|
std::unique_ptr<rtc::SSLCertChain> remote_cert_chain =
|
||||||
pc_->GetRemoteSSLCertificate(transport_name);
|
pc_->GetRemoteSSLCertChain(transport_name);
|
||||||
if (remote_certificate) {
|
if (remote_cert_chain) {
|
||||||
certificate_stats_pair.remote = remote_certificate->GetStats();
|
certificate_stats_pair.remote = remote_cert_chain->GetStats();
|
||||||
}
|
}
|
||||||
|
|
||||||
transport_cert_stats.insert(
|
transport_cert_stats.insert(
|
||||||
|
|
|
@ -133,7 +133,7 @@ std::unique_ptr<CertificateInfo> CreateFakeCertificateAndInfoFromDers(
|
||||||
}
|
}
|
||||||
info->certificate =
|
info->certificate =
|
||||||
rtc::RTCCertificate::Create(std::unique_ptr<rtc::FakeSSLIdentity>(
|
rtc::RTCCertificate::Create(std::unique_ptr<rtc::FakeSSLIdentity>(
|
||||||
new rtc::FakeSSLIdentity(rtc::FakeSSLCertificate(info->pems))));
|
new rtc::FakeSSLIdentity(info->pems)));
|
||||||
// Strip header/footer and newline characters of PEM strings.
|
// Strip header/footer and newline characters of PEM strings.
|
||||||
for (size_t i = 0; i < info->pems.size(); ++i) {
|
for (size_t i = 0; i < info->pems.size(); ++i) {
|
||||||
rtc::replace_substrs("-----BEGIN CERTIFICATE-----", 27,
|
rtc::replace_substrs("-----BEGIN CERTIFICATE-----", 27,
|
||||||
|
@ -143,21 +143,14 @@ std::unique_ptr<CertificateInfo> CreateFakeCertificateAndInfoFromDers(
|
||||||
rtc::replace_substrs("\n", 1,
|
rtc::replace_substrs("\n", 1,
|
||||||
"", 0, &info->pems[i]);
|
"", 0, &info->pems[i]);
|
||||||
}
|
}
|
||||||
// Fingerprint of leaf certificate.
|
// Fingerprints for the whole certificate chain, starting with leaf
|
||||||
std::unique_ptr<rtc::SSLFingerprint> fp(
|
// certificate.
|
||||||
rtc::SSLFingerprint::Create("sha-1",
|
const rtc::SSLCertChain& chain = info->certificate->ssl_cert_chain();
|
||||||
&info->certificate->ssl_certificate()));
|
std::unique_ptr<rtc::SSLFingerprint> fp;
|
||||||
EXPECT_TRUE(fp);
|
for (size_t i = 0; i < chain.GetSize(); i++) {
|
||||||
info->fingerprints.push_back(fp->GetRfc4572Fingerprint());
|
fp.reset(rtc::SSLFingerprint::Create("sha-1", &chain.Get(i)));
|
||||||
// Fingerprints of the rest of the chain.
|
EXPECT_TRUE(fp);
|
||||||
std::unique_ptr<rtc::SSLCertChain> chain =
|
info->fingerprints.push_back(fp->GetRfc4572Fingerprint());
|
||||||
info->certificate->ssl_certificate().GetChain();
|
|
||||||
if (chain) {
|
|
||||||
for (size_t i = 0; i < chain->GetSize(); i++) {
|
|
||||||
fp.reset(rtc::SSLFingerprint::Create("sha-1", &chain->Get(i)));
|
|
||||||
EXPECT_TRUE(fp);
|
|
||||||
info->fingerprints.push_back(fp->GetRfc4572Fingerprint());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
EXPECT_EQ(info->ders.size(), info->fingerprints.size());
|
EXPECT_EQ(info->ders.size(), info->fingerprints.size());
|
||||||
return info;
|
return info;
|
||||||
|
@ -579,9 +572,9 @@ TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsSingle) {
|
||||||
std::unique_ptr<CertificateInfo> remote_certinfo =
|
std::unique_ptr<CertificateInfo> remote_certinfo =
|
||||||
CreateFakeCertificateAndInfoFromDers(
|
CreateFakeCertificateAndInfoFromDers(
|
||||||
std::vector<std::string>({ "(remote) single certificate" }));
|
std::vector<std::string>({ "(remote) single certificate" }));
|
||||||
pc_->SetRemoteCertificate(
|
pc_->SetRemoteCertChain(
|
||||||
kTransportName,
|
kTransportName,
|
||||||
remote_certinfo->certificate->ssl_certificate().GetUniqueReference());
|
remote_certinfo->certificate->ssl_cert_chain().UniqueCopy());
|
||||||
|
|
||||||
rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
|
rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
|
||||||
|
|
||||||
|
@ -693,9 +686,9 @@ TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsMultiple) {
|
||||||
std::unique_ptr<CertificateInfo> audio_remote_certinfo =
|
std::unique_ptr<CertificateInfo> audio_remote_certinfo =
|
||||||
CreateFakeCertificateAndInfoFromDers(
|
CreateFakeCertificateAndInfoFromDers(
|
||||||
std::vector<std::string>({ "(remote) audio" }));
|
std::vector<std::string>({ "(remote) audio" }));
|
||||||
pc_->SetRemoteCertificate(
|
pc_->SetRemoteCertChain(
|
||||||
kAudioTransport, audio_remote_certinfo->certificate->ssl_certificate()
|
kAudioTransport,
|
||||||
.GetUniqueReference());
|
audio_remote_certinfo->certificate->ssl_cert_chain().UniqueCopy());
|
||||||
|
|
||||||
pc_->AddVideoChannel("video", kVideoTransport);
|
pc_->AddVideoChannel("video", kVideoTransport);
|
||||||
std::unique_ptr<CertificateInfo> video_local_certinfo =
|
std::unique_ptr<CertificateInfo> video_local_certinfo =
|
||||||
|
@ -705,9 +698,9 @@ TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsMultiple) {
|
||||||
std::unique_ptr<CertificateInfo> video_remote_certinfo =
|
std::unique_ptr<CertificateInfo> video_remote_certinfo =
|
||||||
CreateFakeCertificateAndInfoFromDers(
|
CreateFakeCertificateAndInfoFromDers(
|
||||||
std::vector<std::string>({ "(remote) video" }));
|
std::vector<std::string>({ "(remote) video" }));
|
||||||
pc_->SetRemoteCertificate(
|
pc_->SetRemoteCertChain(
|
||||||
kVideoTransport, video_remote_certinfo->certificate->ssl_certificate()
|
kVideoTransport,
|
||||||
.GetUniqueReference());
|
video_remote_certinfo->certificate->ssl_cert_chain().UniqueCopy());
|
||||||
|
|
||||||
rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
|
rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
|
||||||
ExpectReportContainsCertificateInfo(report, *audio_local_certinfo);
|
ExpectReportContainsCertificateInfo(report, *audio_local_certinfo);
|
||||||
|
@ -730,9 +723,9 @@ TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsChain) {
|
||||||
CreateFakeCertificateAndInfoFromDers({"(remote) this", "(remote) is",
|
CreateFakeCertificateAndInfoFromDers({"(remote) this", "(remote) is",
|
||||||
"(remote) another",
|
"(remote) another",
|
||||||
"(remote) chain"});
|
"(remote) chain"});
|
||||||
pc_->SetRemoteCertificate(
|
pc_->SetRemoteCertChain(
|
||||||
kTransportName,
|
kTransportName,
|
||||||
remote_certinfo->certificate->ssl_certificate().GetUniqueReference());
|
remote_certinfo->certificate->ssl_cert_chain().UniqueCopy());
|
||||||
|
|
||||||
rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
|
rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
|
||||||
ExpectReportContainsCertificateInfo(report, *local_certinfo);
|
ExpectReportContainsCertificateInfo(report, *local_certinfo);
|
||||||
|
@ -1805,9 +1798,9 @@ TEST_F(RTCStatsCollectorTest, CollectRTCTransportStats) {
|
||||||
std::unique_ptr<CertificateInfo> remote_certinfo =
|
std::unique_ptr<CertificateInfo> remote_certinfo =
|
||||||
CreateFakeCertificateAndInfoFromDers(
|
CreateFakeCertificateAndInfoFromDers(
|
||||||
{"(remote) local", "(remote) chain"});
|
{"(remote) local", "(remote) chain"});
|
||||||
pc_->SetRemoteCertificate(
|
pc_->SetRemoteCertChain(
|
||||||
kTransportName,
|
kTransportName,
|
||||||
remote_certinfo->certificate->ssl_certificate().GetUniqueReference());
|
remote_certinfo->certificate->ssl_cert_chain().UniqueCopy());
|
||||||
|
|
||||||
report = stats_->GetFreshStatsReport();
|
report = stats_->GetFreshStatsReport();
|
||||||
|
|
||||||
|
|
|
@ -623,14 +623,12 @@ bool StatsCollector::IsValidTrack(const std::string& track_id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
StatsReport* StatsCollector::AddCertificateReports(
|
StatsReport* StatsCollector::AddCertificateReports(
|
||||||
const rtc::SSLCertificate* cert) {
|
std::unique_ptr<rtc::SSLCertificateStats> cert_stats) {
|
||||||
RTC_DCHECK(pc_->signaling_thread()->IsCurrent());
|
RTC_DCHECK(pc_->signaling_thread()->IsCurrent());
|
||||||
RTC_DCHECK(cert != NULL);
|
|
||||||
|
|
||||||
std::unique_ptr<rtc::SSLCertificateStats> first_stats = cert->GetStats();
|
|
||||||
StatsReport* first_report = nullptr;
|
StatsReport* first_report = nullptr;
|
||||||
StatsReport* prev_report = nullptr;
|
StatsReport* prev_report = nullptr;
|
||||||
for (rtc::SSLCertificateStats* stats = first_stats.get(); stats;
|
for (rtc::SSLCertificateStats* stats = cert_stats.get(); stats;
|
||||||
stats = stats->issuer.get()) {
|
stats = stats->issuer.get()) {
|
||||||
StatsReport::Id id(StatsReport::NewTypedId(
|
StatsReport::Id id(StatsReport::NewTypedId(
|
||||||
StatsReport::kStatsReportTypeCertificate, stats->fingerprint));
|
StatsReport::kStatsReportTypeCertificate, stats->fingerprint));
|
||||||
|
@ -786,15 +784,16 @@ void StatsCollector::ExtractSessionInfo() {
|
||||||
StatsReport::Id local_cert_report_id, remote_cert_report_id;
|
StatsReport::Id local_cert_report_id, remote_cert_report_id;
|
||||||
rtc::scoped_refptr<rtc::RTCCertificate> certificate;
|
rtc::scoped_refptr<rtc::RTCCertificate> certificate;
|
||||||
if (pc_->GetLocalCertificate(transport_name, &certificate)) {
|
if (pc_->GetLocalCertificate(transport_name, &certificate)) {
|
||||||
StatsReport* r = AddCertificateReports(&(certificate->ssl_certificate()));
|
StatsReport* r =
|
||||||
|
AddCertificateReports(certificate->ssl_cert_chain().GetStats());
|
||||||
if (r)
|
if (r)
|
||||||
local_cert_report_id = r->id();
|
local_cert_report_id = r->id();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<rtc::SSLCertificate> cert =
|
std::unique_ptr<rtc::SSLCertChain> remote_cert_chain =
|
||||||
pc_->GetRemoteSSLCertificate(transport_name);
|
pc_->GetRemoteSSLCertChain(transport_name);
|
||||||
if (cert) {
|
if (remote_cert_chain) {
|
||||||
StatsReport* r = AddCertificateReports(cert.get());
|
StatsReport* r = AddCertificateReports(remote_cert_chain->GetStats());
|
||||||
if (r)
|
if (r)
|
||||||
remote_cert_report_id = r->id();
|
remote_cert_report_id = r->id();
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#define PC_STATSCOLLECTOR_H_
|
#define PC_STATSCOLLECTOR_H_
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -101,8 +102,9 @@ class StatsCollector {
|
||||||
bool local);
|
bool local);
|
||||||
|
|
||||||
// Adds a report for this certificate and every certificate in its chain, and
|
// Adds a report for this certificate and every certificate in its chain, and
|
||||||
// returns the leaf certificate's report (|cert|'s report).
|
// returns the leaf certificate's report (|cert_stats|'s report).
|
||||||
StatsReport* AddCertificateReports(const rtc::SSLCertificate* cert);
|
StatsReport* AddCertificateReports(
|
||||||
|
std::unique_ptr<rtc::SSLCertificateStats> cert_stats);
|
||||||
|
|
||||||
StatsReport* AddConnectionInfoReport(const std::string& content_name,
|
StatsReport* AddConnectionInfoReport(const std::string& content_name,
|
||||||
int component, int connection_id,
|
int component, int connection_id,
|
||||||
|
|
|
@ -636,11 +636,10 @@ class StatsCollectorTest : public testing::Test {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestCertificateReports(
|
void TestCertificateReports(const rtc::FakeSSLIdentity& local_identity,
|
||||||
const rtc::FakeSSLCertificate& local_cert,
|
const std::vector<std::string>& local_ders,
|
||||||
const std::vector<std::string>& local_ders,
|
const rtc::FakeSSLIdentity& remote_identity,
|
||||||
std::unique_ptr<rtc::FakeSSLCertificate> remote_cert,
|
const std::vector<std::string>& remote_ders) {
|
||||||
const std::vector<std::string>& remote_ders) {
|
|
||||||
const std::string kTransportName = "transport";
|
const std::string kTransportName = "transport";
|
||||||
|
|
||||||
auto pc = CreatePeerConnection();
|
auto pc = CreatePeerConnection();
|
||||||
|
@ -656,12 +655,13 @@ class StatsCollectorTest : public testing::Test {
|
||||||
internal::TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA;
|
internal::TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA;
|
||||||
pc->SetTransportStats(kTransportName, channel_stats);
|
pc->SetTransportStats(kTransportName, channel_stats);
|
||||||
|
|
||||||
// Fake certificate to report
|
// Fake certificate to report.
|
||||||
rtc::scoped_refptr<rtc::RTCCertificate> local_certificate(
|
rtc::scoped_refptr<rtc::RTCCertificate> local_certificate(
|
||||||
rtc::RTCCertificate::Create(
|
rtc::RTCCertificate::Create(
|
||||||
rtc::MakeUnique<rtc::FakeSSLIdentity>(local_cert)));
|
std::unique_ptr<rtc::SSLIdentity>(local_identity.GetReference())));
|
||||||
pc->SetLocalCertificate(kTransportName, local_certificate);
|
pc->SetLocalCertificate(kTransportName, local_certificate);
|
||||||
pc->SetRemoteCertificate(kTransportName, std::move(remote_cert));
|
pc->SetRemoteCertChain(kTransportName,
|
||||||
|
remote_identity.cert_chain().UniqueCopy());
|
||||||
|
|
||||||
stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
|
stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
|
||||||
|
|
||||||
|
@ -1329,7 +1329,7 @@ TEST_F(StatsCollectorTest, ChainedCertificateReportsCreated) {
|
||||||
local_ders[2] = "some";
|
local_ders[2] = "some";
|
||||||
local_ders[3] = "der";
|
local_ders[3] = "der";
|
||||||
local_ders[4] = "values";
|
local_ders[4] = "values";
|
||||||
rtc::FakeSSLCertificate local_cert(DersToPems(local_ders));
|
rtc::FakeSSLIdentity local_identity(DersToPems(local_ders));
|
||||||
|
|
||||||
// Build remote certificate chain
|
// Build remote certificate chain
|
||||||
std::vector<std::string> remote_ders(4);
|
std::vector<std::string> remote_ders(4);
|
||||||
|
@ -1337,10 +1337,9 @@ TEST_F(StatsCollectorTest, ChainedCertificateReportsCreated) {
|
||||||
remote_ders[1] = "non-";
|
remote_ders[1] = "non-";
|
||||||
remote_ders[2] = "intersecting";
|
remote_ders[2] = "intersecting";
|
||||||
remote_ders[3] = "set";
|
remote_ders[3] = "set";
|
||||||
std::unique_ptr<rtc::FakeSSLCertificate> remote_cert(
|
rtc::FakeSSLIdentity remote_identity(DersToPems(remote_ders));
|
||||||
new rtc::FakeSSLCertificate(DersToPems(remote_ders)));
|
|
||||||
|
|
||||||
TestCertificateReports(local_cert, local_ders, std::move(remote_cert),
|
TestCertificateReports(local_identity, local_ders, remote_identity,
|
||||||
remote_ders);
|
remote_ders);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1349,15 +1348,14 @@ TEST_F(StatsCollectorTest, ChainedCertificateReportsCreated) {
|
||||||
TEST_F(StatsCollectorTest, ChainlessCertificateReportsCreated) {
|
TEST_F(StatsCollectorTest, ChainlessCertificateReportsCreated) {
|
||||||
// Build local certificate.
|
// Build local certificate.
|
||||||
std::string local_der = "This is the local der.";
|
std::string local_der = "This is the local der.";
|
||||||
rtc::FakeSSLCertificate local_cert(DerToPem(local_der));
|
rtc::FakeSSLIdentity local_identity(DerToPem(local_der));
|
||||||
|
|
||||||
// Build remote certificate.
|
// Build remote certificate.
|
||||||
std::string remote_der = "This is somebody else's der.";
|
std::string remote_der = "This is somebody else's der.";
|
||||||
std::unique_ptr<rtc::FakeSSLCertificate> remote_cert(
|
rtc::FakeSSLIdentity remote_identity(DerToPem(remote_der));
|
||||||
new rtc::FakeSSLCertificate(DerToPem(remote_der)));
|
|
||||||
|
|
||||||
TestCertificateReports(local_cert, std::vector<std::string>(1, local_der),
|
TestCertificateReports(local_identity, std::vector<std::string>(1, local_der),
|
||||||
std::move(remote_cert),
|
remote_identity,
|
||||||
std::vector<std::string>(1, remote_der));
|
std::vector<std::string>(1, remote_der));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1405,16 +1403,16 @@ TEST_F(StatsCollectorTest, NoTransport) {
|
||||||
TEST_F(StatsCollectorTest, UnsupportedDigestIgnored) {
|
TEST_F(StatsCollectorTest, UnsupportedDigestIgnored) {
|
||||||
// Build a local certificate.
|
// Build a local certificate.
|
||||||
std::string local_der = "This is the local der.";
|
std::string local_der = "This is the local der.";
|
||||||
rtc::FakeSSLCertificate local_cert(DerToPem(local_der));
|
rtc::FakeSSLIdentity local_identity(DerToPem(local_der));
|
||||||
|
|
||||||
// Build a remote certificate with an unsupported digest algorithm.
|
// Build a remote certificate with an unsupported digest algorithm.
|
||||||
std::string remote_der = "This is somebody else's der.";
|
std::string remote_der = "This is somebody else's der.";
|
||||||
std::unique_ptr<rtc::FakeSSLCertificate> remote_cert(
|
rtc::FakeSSLCertificate remote_cert(DerToPem(remote_der));
|
||||||
new rtc::FakeSSLCertificate(DerToPem(remote_der)));
|
remote_cert.set_digest_algorithm("foobar");
|
||||||
remote_cert->set_digest_algorithm("foobar");
|
rtc::FakeSSLIdentity remote_identity(remote_cert);
|
||||||
|
|
||||||
TestCertificateReports(local_cert, std::vector<std::string>(1, local_der),
|
TestCertificateReports(local_identity, std::vector<std::string>(1, local_der),
|
||||||
std::move(remote_cert), std::vector<std::string>());
|
remote_identity, std::vector<std::string>());
|
||||||
}
|
}
|
||||||
|
|
||||||
// This test verifies that the audio/video related stats which are -1 initially
|
// This test verifies that the audio/video related stats which are -1 initially
|
||||||
|
|
|
@ -292,7 +292,7 @@ class FakePeerConnectionBase : public PeerConnectionInternal {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<rtc::SSLCertificate> GetRemoteSSLCertificate(
|
std::unique_ptr<rtc::SSLCertChain> GetRemoteSSLCertChain(
|
||||||
const std::string& transport_name) override {
|
const std::string& transport_name) override {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -196,9 +196,9 @@ class FakePeerConnectionForStats : public FakePeerConnectionBase {
|
||||||
local_certificates_by_transport_[transport_name] = certificate;
|
local_certificates_by_transport_[transport_name] = certificate;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetRemoteCertificate(const std::string& transport_name,
|
void SetRemoteCertChain(const std::string& transport_name,
|
||||||
std::unique_ptr<rtc::SSLCertificate> certificate) {
|
std::unique_ptr<rtc::SSLCertChain> chain) {
|
||||||
remote_certificates_by_transport_[transport_name] = std::move(certificate);
|
remote_cert_chains_by_transport_[transport_name] = std::move(chain);
|
||||||
}
|
}
|
||||||
|
|
||||||
// PeerConnectionInterface overrides.
|
// PeerConnectionInterface overrides.
|
||||||
|
@ -313,11 +313,11 @@ class FakePeerConnectionForStats : public FakePeerConnectionBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<rtc::SSLCertificate> GetRemoteSSLCertificate(
|
std::unique_ptr<rtc::SSLCertChain> GetRemoteSSLCertChain(
|
||||||
const std::string& transport_name) override {
|
const std::string& transport_name) override {
|
||||||
auto it = remote_certificates_by_transport_.find(transport_name);
|
auto it = remote_cert_chains_by_transport_.find(transport_name);
|
||||||
if (it != remote_certificates_by_transport_.end()) {
|
if (it != remote_cert_chains_by_transport_.end()) {
|
||||||
return it->second->GetUniqueReference();
|
return it->second->UniqueCopy();
|
||||||
} else {
|
} else {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -379,8 +379,8 @@ class FakePeerConnectionForStats : public FakePeerConnectionBase {
|
||||||
|
|
||||||
std::map<std::string, rtc::scoped_refptr<rtc::RTCCertificate>>
|
std::map<std::string, rtc::scoped_refptr<rtc::RTCCertificate>>
|
||||||
local_certificates_by_transport_;
|
local_certificates_by_transport_;
|
||||||
std::map<std::string, std::unique_ptr<rtc::SSLCertificate>>
|
std::map<std::string, std::unique_ptr<rtc::SSLCertChain>>
|
||||||
remote_certificates_by_transport_;
|
remote_cert_chains_by_transport_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|
|
@ -191,17 +191,6 @@ bool TransportController::GetLocalCertificate(
|
||||||
this, transport_name, certificate));
|
this, transport_name, certificate));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<rtc::SSLCertificate>
|
|
||||||
TransportController::GetRemoteSSLCertificate(
|
|
||||||
const std::string& transport_name) const {
|
|
||||||
if (network_thread_->IsCurrent()) {
|
|
||||||
return GetRemoteSSLCertificate_n(transport_name);
|
|
||||||
}
|
|
||||||
return network_thread_->Invoke<std::unique_ptr<rtc::SSLCertificate>>(
|
|
||||||
RTC_FROM_HERE, rtc::Bind(&TransportController::GetRemoteSSLCertificate_n,
|
|
||||||
this, transport_name));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<rtc::SSLCertChain> TransportController::GetRemoteSSLCertChain(
|
std::unique_ptr<rtc::SSLCertChain> TransportController::GetRemoteSSLCertChain(
|
||||||
const std::string& transport_name) const {
|
const std::string& transport_name) const {
|
||||||
if (!network_thread_->IsCurrent()) {
|
if (!network_thread_->IsCurrent()) {
|
||||||
|
@ -209,6 +198,9 @@ std::unique_ptr<rtc::SSLCertChain> TransportController::GetRemoteSSLCertChain(
|
||||||
RTC_FROM_HERE, [&] { return GetRemoteSSLCertChain(transport_name); });
|
RTC_FROM_HERE, [&] { return GetRemoteSSLCertChain(transport_name); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the certificate from the RTP channel's DTLS handshake. Should be
|
||||||
|
// identical to the RTCP channel's, since they were given the same remote
|
||||||
|
// fingerprint.
|
||||||
const RefCountedChannel* ch =
|
const RefCountedChannel* ch =
|
||||||
GetChannel_n(transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
|
GetChannel_n(transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
|
||||||
if (!ch) {
|
if (!ch) {
|
||||||
|
@ -762,21 +754,6 @@ bool TransportController::GetLocalCertificate_n(
|
||||||
return t->GetLocalCertificate(certificate);
|
return t->GetLocalCertificate(certificate);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<rtc::SSLCertificate>
|
|
||||||
TransportController::GetRemoteSSLCertificate_n(
|
|
||||||
const std::string& transport_name) const {
|
|
||||||
RTC_DCHECK(network_thread_->IsCurrent());
|
|
||||||
|
|
||||||
// Get the certificate from the RTP channel's DTLS handshake. Should be
|
|
||||||
// identical to the RTCP channel's, since they were given the same remote
|
|
||||||
// fingerprint.
|
|
||||||
const RefCountedChannel* ch = GetChannel_n(transport_name, 1);
|
|
||||||
if (!ch) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return ch->dtls()->GetRemoteSSLCertificate();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TransportController::SetLocalTransportDescription_n(
|
bool TransportController::SetLocalTransportDescription_n(
|
||||||
const std::string& transport_name,
|
const std::string& transport_name,
|
||||||
const TransportDescription& tdesc,
|
const TransportDescription& tdesc,
|
||||||
|
|
|
@ -91,10 +91,8 @@ class TransportController : public sigslot::has_slots<>,
|
||||||
bool GetLocalCertificate(
|
bool GetLocalCertificate(
|
||||||
const std::string& transport_name,
|
const std::string& transport_name,
|
||||||
rtc::scoped_refptr<rtc::RTCCertificate>* certificate) const;
|
rtc::scoped_refptr<rtc::RTCCertificate>* certificate) const;
|
||||||
// Caller owns returned certificate. This method mainly exists for stats
|
// Caller owns returned certificate chain. This method mainly exists for
|
||||||
// reporting.
|
// stats reporting.
|
||||||
std::unique_ptr<rtc::SSLCertificate> GetRemoteSSLCertificate(
|
|
||||||
const std::string& transport_name) const;
|
|
||||||
std::unique_ptr<rtc::SSLCertChain> GetRemoteSSLCertChain(
|
std::unique_ptr<rtc::SSLCertChain> GetRemoteSSLCertChain(
|
||||||
const std::string& transport_name) const;
|
const std::string& transport_name) const;
|
||||||
|
|
||||||
|
@ -249,8 +247,6 @@ class TransportController : public sigslot::has_slots<>,
|
||||||
bool GetLocalCertificate_n(
|
bool GetLocalCertificate_n(
|
||||||
const std::string& transport_name,
|
const std::string& transport_name,
|
||||||
rtc::scoped_refptr<rtc::RTCCertificate>* certificate) const;
|
rtc::scoped_refptr<rtc::RTCCertificate>* certificate) const;
|
||||||
std::unique_ptr<rtc::SSLCertificate> GetRemoteSSLCertificate_n(
|
|
||||||
const std::string& transport_name) const;
|
|
||||||
bool SetLocalTransportDescription_n(const std::string& transport_name,
|
bool SetLocalTransportDescription_n(const std::string& transport_name,
|
||||||
const TransportDescription& tdesc,
|
const TransportDescription& tdesc,
|
||||||
webrtc::SdpType type,
|
webrtc::SdpType type,
|
||||||
|
|
|
@ -348,21 +348,21 @@ TEST_F(TransportControllerTest, TestSetAndGetLocalCertificate) {
|
||||||
EXPECT_FALSE(transport_controller_->SetLocalCertificate(certificate2));
|
EXPECT_FALSE(transport_controller_->SetLocalCertificate(certificate2));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TransportControllerTest, TestGetRemoteSSLCertificate) {
|
TEST_F(TransportControllerTest, TestGetRemoteSSLCertChain) {
|
||||||
rtc::FakeSSLCertificate fake_certificate("fake_data");
|
rtc::FakeSSLCertificate fake_certificate("fake_data");
|
||||||
|
|
||||||
FakeDtlsTransport* transport = CreateFakeDtlsTransport("audio", 1);
|
FakeDtlsTransport* transport = CreateFakeDtlsTransport("audio", 1);
|
||||||
ASSERT_NE(nullptr, transport);
|
ASSERT_NE(nullptr, transport);
|
||||||
|
|
||||||
transport->SetRemoteSSLCertificate(&fake_certificate);
|
transport->SetRemoteSSLCertificate(&fake_certificate);
|
||||||
std::unique_ptr<rtc::SSLCertificate> returned_certificate =
|
std::unique_ptr<rtc::SSLCertChain> returned_cert_chain =
|
||||||
transport_controller_->GetRemoteSSLCertificate("audio");
|
transport_controller_->GetRemoteSSLCertChain("audio");
|
||||||
EXPECT_TRUE(returned_certificate);
|
EXPECT_TRUE(returned_cert_chain);
|
||||||
EXPECT_EQ(fake_certificate.ToPEMString(),
|
EXPECT_EQ(fake_certificate.ToPEMString(),
|
||||||
returned_certificate->ToPEMString());
|
returned_cert_chain->Get(0).ToPEMString());
|
||||||
|
|
||||||
// Should fail if called for a nonexistant transport.
|
// Should fail if called for a nonexistant transport.
|
||||||
EXPECT_FALSE(transport_controller_->GetRemoteSSLCertificate("video"));
|
EXPECT_FALSE(transport_controller_->GetRemoteSSLCertChain("video"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TransportControllerTest, TestSetLocalTransportDescription) {
|
TEST_F(TransportControllerTest, TestSetLocalTransportDescription) {
|
||||||
|
|
|
@ -20,19 +20,10 @@
|
||||||
|
|
||||||
namespace rtc {
|
namespace rtc {
|
||||||
|
|
||||||
FakeSSLCertificate::FakeSSLCertificate(const std::string& data)
|
FakeSSLCertificate::FakeSSLCertificate(const std::string& pem_string)
|
||||||
: data_(data), digest_algorithm_(DIGEST_SHA_1), expiration_time_(-1) {}
|
: pem_string_(pem_string),
|
||||||
|
|
||||||
FakeSSLCertificate::FakeSSLCertificate(const std::vector<std::string>& certs)
|
|
||||||
: data_(certs.front()),
|
|
||||||
digest_algorithm_(DIGEST_SHA_1),
|
digest_algorithm_(DIGEST_SHA_1),
|
||||||
expiration_time_(-1) {
|
expiration_time_(-1) {}
|
||||||
std::vector<std::string>::const_iterator it;
|
|
||||||
// Skip certs[0].
|
|
||||||
for (it = certs.begin() + 1; it != certs.end(); ++it) {
|
|
||||||
certs_.push_back(FakeSSLCertificate(*it));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FakeSSLCertificate::FakeSSLCertificate(const FakeSSLCertificate&) = default;
|
FakeSSLCertificate::FakeSSLCertificate(const FakeSSLCertificate&) = default;
|
||||||
|
|
||||||
|
@ -43,12 +34,13 @@ FakeSSLCertificate* FakeSSLCertificate::GetReference() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string FakeSSLCertificate::ToPEMString() const {
|
std::string FakeSSLCertificate::ToPEMString() const {
|
||||||
return data_;
|
return pem_string_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FakeSSLCertificate::ToDER(Buffer* der_buffer) const {
|
void FakeSSLCertificate::ToDER(Buffer* der_buffer) const {
|
||||||
std::string der_string;
|
std::string der_string;
|
||||||
RTC_CHECK(SSLIdentity::PemToDer(kPemTypeCertificate, data_, &der_string));
|
RTC_CHECK(
|
||||||
|
SSLIdentity::PemToDer(kPemTypeCertificate, pem_string_, &der_string));
|
||||||
der_buffer->SetData(der_string.c_str(), der_string.size());
|
der_buffer->SetData(der_string.c_str(), der_string.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,30 +66,40 @@ bool FakeSSLCertificate::ComputeDigest(const std::string& algorithm,
|
||||||
unsigned char* digest,
|
unsigned char* digest,
|
||||||
size_t size,
|
size_t size,
|
||||||
size_t* length) const {
|
size_t* length) const {
|
||||||
*length =
|
*length = rtc::ComputeDigest(algorithm, pem_string_.c_str(),
|
||||||
rtc::ComputeDigest(algorithm, data_.c_str(), data_.size(), digest, size);
|
pem_string_.size(), digest, size);
|
||||||
return (*length != 0);
|
return (*length != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<SSLCertChain> FakeSSLCertificate::GetChain() const {
|
FakeSSLIdentity::FakeSSLIdentity(const std::string& pem_string)
|
||||||
if (certs_.empty())
|
: FakeSSLIdentity(FakeSSLCertificate(pem_string)) {}
|
||||||
return nullptr;
|
|
||||||
std::vector<std::unique_ptr<SSLCertificate>> new_certs(certs_.size());
|
FakeSSLIdentity::FakeSSLIdentity(const std::vector<std::string>& pem_strings) {
|
||||||
std::transform(certs_.begin(), certs_.end(), new_certs.begin(), DupCert);
|
std::vector<std::unique_ptr<SSLCertificate>> certs;
|
||||||
return MakeUnique<SSLCertChain>(std::move(new_certs));
|
for (const std::string& pem_string : pem_strings) {
|
||||||
|
certs.push_back(MakeUnique<FakeSSLCertificate>(pem_string));
|
||||||
|
}
|
||||||
|
cert_chain_ = MakeUnique<SSLCertChain>(std::move(certs));
|
||||||
}
|
}
|
||||||
|
|
||||||
FakeSSLIdentity::FakeSSLIdentity(const std::string& data) : cert_(data) {}
|
|
||||||
|
|
||||||
FakeSSLIdentity::FakeSSLIdentity(const FakeSSLCertificate& cert)
|
FakeSSLIdentity::FakeSSLIdentity(const FakeSSLCertificate& cert)
|
||||||
: cert_(cert) {}
|
: cert_chain_(MakeUnique<SSLCertChain>(&cert)) {}
|
||||||
|
|
||||||
|
FakeSSLIdentity::FakeSSLIdentity(const FakeSSLIdentity& o)
|
||||||
|
: cert_chain_(o.cert_chain_->UniqueCopy()) {}
|
||||||
|
|
||||||
|
FakeSSLIdentity::~FakeSSLIdentity() = default;
|
||||||
|
|
||||||
FakeSSLIdentity* FakeSSLIdentity::GetReference() const {
|
FakeSSLIdentity* FakeSSLIdentity::GetReference() const {
|
||||||
return new FakeSSLIdentity(*this);
|
return new FakeSSLIdentity(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
const FakeSSLCertificate& FakeSSLIdentity::certificate() const {
|
const SSLCertificate& FakeSSLIdentity::certificate() const {
|
||||||
return cert_;
|
return cert_chain_->Get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const SSLCertChain& FakeSSLIdentity::cert_chain() const {
|
||||||
|
return *cert_chain_.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string FakeSSLIdentity::PrivateKeyToPEMString() const {
|
std::string FakeSSLIdentity::PrivateKeyToPEMString() const {
|
||||||
|
|
|
@ -18,13 +18,11 @@
|
||||||
|
|
||||||
namespace rtc {
|
namespace rtc {
|
||||||
|
|
||||||
class FakeSSLCertificate : public rtc::SSLCertificate {
|
class FakeSSLCertificate : public SSLCertificate {
|
||||||
public:
|
public:
|
||||||
// SHA-1 is the default digest algorithm because it is available in all build
|
// SHA-1 is the default digest algorithm because it is available in all build
|
||||||
// configurations used for unit testing.
|
// configurations used for unit testing.
|
||||||
explicit FakeSSLCertificate(const std::string& data);
|
explicit FakeSSLCertificate(const std::string& pem_string);
|
||||||
|
|
||||||
explicit FakeSSLCertificate(const std::vector<std::string>& certs);
|
|
||||||
|
|
||||||
FakeSSLCertificate(const FakeSSLCertificate&);
|
FakeSSLCertificate(const FakeSSLCertificate&);
|
||||||
~FakeSSLCertificate() override;
|
~FakeSSLCertificate() override;
|
||||||
|
@ -39,32 +37,33 @@ class FakeSSLCertificate : public rtc::SSLCertificate {
|
||||||
unsigned char* digest,
|
unsigned char* digest,
|
||||||
size_t size,
|
size_t size,
|
||||||
size_t* length) const override;
|
size_t* length) const override;
|
||||||
std::unique_ptr<SSLCertChain> GetChain() const override;
|
|
||||||
|
|
||||||
void SetCertificateExpirationTime(int64_t expiration_time);
|
void SetCertificateExpirationTime(int64_t expiration_time);
|
||||||
|
|
||||||
void set_digest_algorithm(const std::string& algorithm);
|
void set_digest_algorithm(const std::string& algorithm);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static std::unique_ptr<SSLCertificate> DupCert(FakeSSLCertificate cert) {
|
std::string pem_string_;
|
||||||
return cert.GetUniqueReference();
|
|
||||||
}
|
|
||||||
static void DeleteCert(SSLCertificate* cert) { delete cert; }
|
|
||||||
std::string data_;
|
|
||||||
std::vector<FakeSSLCertificate> certs_;
|
|
||||||
std::string digest_algorithm_;
|
std::string digest_algorithm_;
|
||||||
// Expiration time in seconds relative to epoch, 1970-01-01T00:00:00Z (UTC).
|
// Expiration time in seconds relative to epoch, 1970-01-01T00:00:00Z (UTC).
|
||||||
int64_t expiration_time_;
|
int64_t expiration_time_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FakeSSLIdentity : public rtc::SSLIdentity {
|
class FakeSSLIdentity : public SSLIdentity {
|
||||||
public:
|
public:
|
||||||
explicit FakeSSLIdentity(const std::string& data);
|
explicit FakeSSLIdentity(const std::string& pem_string);
|
||||||
|
// For a certificate chain.
|
||||||
|
explicit FakeSSLIdentity(const std::vector<std::string>& pem_strings);
|
||||||
explicit FakeSSLIdentity(const FakeSSLCertificate& cert);
|
explicit FakeSSLIdentity(const FakeSSLCertificate& cert);
|
||||||
|
|
||||||
|
explicit FakeSSLIdentity(const FakeSSLIdentity& o);
|
||||||
|
|
||||||
|
~FakeSSLIdentity() override;
|
||||||
|
|
||||||
// SSLIdentity implementation.
|
// SSLIdentity implementation.
|
||||||
FakeSSLIdentity* GetReference() const override;
|
FakeSSLIdentity* GetReference() const override;
|
||||||
const FakeSSLCertificate& certificate() const override;
|
const SSLCertificate& certificate() const override;
|
||||||
|
const SSLCertChain& cert_chain() const override;
|
||||||
// Not implemented.
|
// Not implemented.
|
||||||
std::string PrivateKeyToPEMString() const override;
|
std::string PrivateKeyToPEMString() const override;
|
||||||
// Not implemented.
|
// Not implemented.
|
||||||
|
@ -73,7 +72,7 @@ class FakeSSLIdentity : public rtc::SSLIdentity {
|
||||||
virtual bool operator==(const SSLIdentity& other) const;
|
virtual bool operator==(const SSLIdentity& other) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FakeSSLCertificate cert_;
|
std::unique_ptr<SSLCertChain> cert_chain_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace rtc
|
} // namespace rtc
|
||||||
|
|
|
@ -366,10 +366,6 @@ bool OpenSSLCertificate::GetSignatureDigestAlgorithm(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<SSLCertChain> OpenSSLCertificate::GetChain() const {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OpenSSLCertificate::ComputeDigest(const std::string& algorithm,
|
bool OpenSSLCertificate::ComputeDigest(const std::string& algorithm,
|
||||||
unsigned char* digest,
|
unsigned char* digest,
|
||||||
size_t size,
|
size_t size,
|
||||||
|
@ -590,6 +586,10 @@ const OpenSSLCertificate& OpenSSLIdentity::certificate() const {
|
||||||
return *static_cast<const OpenSSLCertificate*>(&cert_chain_->Get(0));
|
return *static_cast<const OpenSSLCertificate*>(&cert_chain_->Get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SSLCertChain& OpenSSLIdentity::cert_chain() const {
|
||||||
|
return *cert_chain_.get();
|
||||||
|
}
|
||||||
|
|
||||||
OpenSSLIdentity* OpenSSLIdentity::GetReference() const {
|
OpenSSLIdentity* OpenSSLIdentity::GetReference() const {
|
||||||
return new OpenSSLIdentity(WrapUnique(key_pair_->GetReference()),
|
return new OpenSSLIdentity(WrapUnique(key_pair_->GetReference()),
|
||||||
WrapUnique(cert_chain_->Copy()));
|
WrapUnique(cert_chain_->Copy()));
|
||||||
|
|
|
@ -92,7 +92,6 @@ class OpenSSLCertificate : public SSLCertificate {
|
||||||
size_t* length);
|
size_t* length);
|
||||||
|
|
||||||
bool GetSignatureDigestAlgorithm(std::string* algorithm) const override;
|
bool GetSignatureDigestAlgorithm(std::string* algorithm) const override;
|
||||||
std::unique_ptr<SSLCertChain> GetChain() const override;
|
|
||||||
|
|
||||||
int64_t CertificateExpirationTime() const override;
|
int64_t CertificateExpirationTime() const override;
|
||||||
|
|
||||||
|
@ -118,6 +117,7 @@ class OpenSSLIdentity : public SSLIdentity {
|
||||||
~OpenSSLIdentity() override;
|
~OpenSSLIdentity() override;
|
||||||
|
|
||||||
const OpenSSLCertificate& certificate() const override;
|
const OpenSSLCertificate& certificate() const override;
|
||||||
|
const SSLCertChain& cert_chain() const override;
|
||||||
OpenSSLIdentity* GetReference() const override;
|
OpenSSLIdentity* GetReference() const override;
|
||||||
|
|
||||||
// Configure an SSL context object to use our key and certificate.
|
// Configure an SSL context object to use our key and certificate.
|
||||||
|
|
|
@ -288,13 +288,6 @@ void OpenSSLStreamAdapter::SetServerRole(SSLRole role) {
|
||||||
role_ = role;
|
role_ = role;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<SSLCertificate> OpenSSLStreamAdapter::GetPeerCertificate()
|
|
||||||
const {
|
|
||||||
return peer_certificate_ ? std::unique_ptr<SSLCertificate>(
|
|
||||||
peer_certificate_->GetReference())
|
|
||||||
: nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OpenSSLStreamAdapter::SetPeerCertificateDigest(
|
bool OpenSSLStreamAdapter::SetPeerCertificateDigest(
|
||||||
const std::string& digest_alg,
|
const std::string& digest_alg,
|
||||||
const unsigned char* digest_val,
|
const unsigned char* digest_val,
|
||||||
|
@ -324,7 +317,7 @@ bool OpenSSLStreamAdapter::SetPeerCertificateDigest(
|
||||||
peer_certificate_digest_value_.SetData(digest_val, digest_len);
|
peer_certificate_digest_value_.SetData(digest_val, digest_len);
|
||||||
peer_certificate_digest_algorithm_ = digest_alg;
|
peer_certificate_digest_algorithm_ = digest_alg;
|
||||||
|
|
||||||
if (!peer_certificate_) {
|
if (!peer_cert_chain_) {
|
||||||
// Normal case, where the digest is set before we obtain the certificate
|
// Normal case, where the digest is set before we obtain the certificate
|
||||||
// from the handshake.
|
// from the handshake.
|
||||||
return true;
|
return true;
|
||||||
|
@ -831,7 +824,7 @@ int OpenSSLStreamAdapter::ContinueSSL() {
|
||||||
RTC_LOG(LS_VERBOSE) << " -- success";
|
RTC_LOG(LS_VERBOSE) << " -- success";
|
||||||
// By this point, OpenSSL should have given us a certificate, or errored
|
// By this point, OpenSSL should have given us a certificate, or errored
|
||||||
// out if one was missing.
|
// out if one was missing.
|
||||||
RTC_DCHECK(peer_certificate_ || !client_auth_enabled());
|
RTC_DCHECK(peer_cert_chain_ || !client_auth_enabled());
|
||||||
|
|
||||||
state_ = SSL_CONNECTED;
|
state_ = SSL_CONNECTED;
|
||||||
if (!waiting_to_verify_peer_certificate()) {
|
if (!waiting_to_verify_peer_certificate()) {
|
||||||
|
@ -928,7 +921,7 @@ void OpenSSLStreamAdapter::Cleanup(uint8_t alert) {
|
||||||
ssl_ctx_ = nullptr;
|
ssl_ctx_ = nullptr;
|
||||||
}
|
}
|
||||||
identity_.reset();
|
identity_.reset();
|
||||||
peer_certificate_.reset();
|
peer_cert_chain_.reset();
|
||||||
|
|
||||||
// Clear the DTLS timer
|
// Clear the DTLS timer
|
||||||
Thread::Current()->Clear(this, MSG_TIMEOUT);
|
Thread::Current()->Clear(this, MSG_TIMEOUT);
|
||||||
|
@ -1062,15 +1055,18 @@ SSL_CTX* OpenSSLStreamAdapter::SetupSSLContext() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenSSLStreamAdapter::VerifyPeerCertificate() {
|
bool OpenSSLStreamAdapter::VerifyPeerCertificate() {
|
||||||
if (!has_peer_certificate_digest() || !peer_certificate_) {
|
if (!has_peer_certificate_digest() || !peer_cert_chain_ ||
|
||||||
|
!peer_cert_chain_->GetSize()) {
|
||||||
RTC_LOG(LS_WARNING) << "Missing digest or peer certificate.";
|
RTC_LOG(LS_WARNING) << "Missing digest or peer certificate.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
const OpenSSLCertificate* leaf_cert =
|
||||||
|
static_cast<const OpenSSLCertificate*>(&peer_cert_chain_->Get(0));
|
||||||
|
|
||||||
unsigned char digest[EVP_MAX_MD_SIZE];
|
unsigned char digest[EVP_MAX_MD_SIZE];
|
||||||
size_t digest_length;
|
size_t digest_length;
|
||||||
if (!OpenSSLCertificate::ComputeDigest(
|
if (!OpenSSLCertificate::ComputeDigest(
|
||||||
peer_certificate_->x509(), peer_certificate_digest_algorithm_, digest,
|
leaf_cert->x509(), peer_certificate_digest_algorithm_, digest,
|
||||||
sizeof(digest), &digest_length)) {
|
sizeof(digest), &digest_length)) {
|
||||||
RTC_LOG(LS_WARNING) << "Failed to compute peer cert digest.";
|
RTC_LOG(LS_WARNING) << "Failed to compute peer cert digest.";
|
||||||
return false;
|
return false;
|
||||||
|
@ -1092,7 +1088,7 @@ bool OpenSSLStreamAdapter::VerifyPeerCertificate() {
|
||||||
|
|
||||||
std::unique_ptr<SSLCertChain> OpenSSLStreamAdapter::GetPeerSSLCertChain()
|
std::unique_ptr<SSLCertChain> OpenSSLStreamAdapter::GetPeerSSLCertChain()
|
||||||
const {
|
const {
|
||||||
return std::unique_ptr<SSLCertChain>(peer_cert_chain_->Copy());
|
return peer_cert_chain_ ? peer_cert_chain_->UniqueCopy() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
int OpenSSLStreamAdapter::SSLVerifyCallback(X509_STORE_CTX* store, void* arg) {
|
int OpenSSLStreamAdapter::SSLVerifyCallback(X509_STORE_CTX* store, void* arg) {
|
||||||
|
@ -1104,9 +1100,6 @@ int OpenSSLStreamAdapter::SSLVerifyCallback(X509_STORE_CTX* store, void* arg) {
|
||||||
|
|
||||||
#if defined(OPENSSL_IS_BORINGSSL)
|
#if defined(OPENSSL_IS_BORINGSSL)
|
||||||
STACK_OF(X509)* chain = SSL_get_peer_full_cert_chain(ssl);
|
STACK_OF(X509)* chain = SSL_get_peer_full_cert_chain(ssl);
|
||||||
// Creates certificate.
|
|
||||||
stream->peer_certificate_.reset(
|
|
||||||
new OpenSSLCertificate(sk_X509_value(chain, 0)));
|
|
||||||
// Creates certificate chain.
|
// Creates certificate chain.
|
||||||
std::vector<std::unique_ptr<SSLCertificate>> cert_chain;
|
std::vector<std::unique_ptr<SSLCertificate>> cert_chain;
|
||||||
for (X509* cert : chain) {
|
for (X509* cert : chain) {
|
||||||
|
@ -1116,7 +1109,8 @@ int OpenSSLStreamAdapter::SSLVerifyCallback(X509_STORE_CTX* store, void* arg) {
|
||||||
#else
|
#else
|
||||||
// Record the peer's certificate.
|
// Record the peer's certificate.
|
||||||
X509* cert = SSL_get_peer_certificate(ssl);
|
X509* cert = SSL_get_peer_certificate(ssl);
|
||||||
stream->peer_certificate_.reset(new OpenSSLCertificate(cert));
|
stream->peer_cert_chain_.reset(
|
||||||
|
new SSLCertChain(new OpenSSLCertificate(cert)));
|
||||||
X509_free(cert);
|
X509_free(cert);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -69,8 +69,6 @@ class OpenSSLStreamAdapter : public SSLStreamAdapter {
|
||||||
size_t digest_len,
|
size_t digest_len,
|
||||||
SSLPeerCertificateDigestError* error = nullptr) override;
|
SSLPeerCertificateDigestError* error = nullptr) override;
|
||||||
|
|
||||||
std::unique_ptr<SSLCertificate> GetPeerCertificate() const override;
|
|
||||||
|
|
||||||
std::unique_ptr<SSLCertChain> GetPeerSSLCertChain() const override;
|
std::unique_ptr<SSLCertChain> GetPeerSSLCertChain() const override;
|
||||||
|
|
||||||
// Goes from state SSL_NONE to either SSL_CONNECTING or SSL_WAIT, depending
|
// Goes from state SSL_NONE to either SSL_CONNECTING or SSL_WAIT, depending
|
||||||
|
@ -197,9 +195,8 @@ class OpenSSLStreamAdapter : public SSLStreamAdapter {
|
||||||
|
|
||||||
// Our key and certificate.
|
// Our key and certificate.
|
||||||
std::unique_ptr<OpenSSLIdentity> identity_;
|
std::unique_ptr<OpenSSLIdentity> identity_;
|
||||||
// The certificate that the peer presented. Initially null, until the
|
// The certificate chain that the peer presented. Initially null, until the
|
||||||
// connection is established.
|
// connection is established.
|
||||||
std::unique_ptr<OpenSSLCertificate> peer_certificate_;
|
|
||||||
std::unique_ptr<SSLCertChain> peer_cert_chain_;
|
std::unique_ptr<SSLCertChain> peer_cert_chain_;
|
||||||
bool peer_certificate_verified_ = false;
|
bool peer_certificate_verified_ = false;
|
||||||
// The digest of the certificate that the peer must present.
|
// The digest of the certificate that the peer must present.
|
||||||
|
|
|
@ -46,6 +46,10 @@ const SSLCertificate& RTCCertificate::ssl_certificate() const {
|
||||||
return identity_->certificate();
|
return identity_->certificate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SSLCertChain& RTCCertificate::ssl_cert_chain() const {
|
||||||
|
return identity_->cert_chain();
|
||||||
|
}
|
||||||
|
|
||||||
RTCCertificatePEM RTCCertificate::ToPEM() const {
|
RTCCertificatePEM RTCCertificate::ToPEM() const {
|
||||||
return RTCCertificatePEM(identity_->PrivateKeyToPEMString(),
|
return RTCCertificatePEM(identity_->PrivateKeyToPEMString(),
|
||||||
ssl_certificate().ToPEMString());
|
ssl_certificate().ToPEMString());
|
||||||
|
|
|
@ -58,6 +58,7 @@ class RTCCertificate : public RefCountInterface {
|
||||||
// relative to epoch, 1970-01-01T00:00:00Z.
|
// relative to epoch, 1970-01-01T00:00:00Z.
|
||||||
bool HasExpired(uint64_t now) const;
|
bool HasExpired(uint64_t now) const;
|
||||||
const SSLCertificate& ssl_certificate() const;
|
const SSLCertificate& ssl_certificate() const;
|
||||||
|
const SSLCertChain& ssl_cert_chain() const;
|
||||||
|
|
||||||
// TODO(hbos): If possible, remove once RTCCertificate and its
|
// TODO(hbos): If possible, remove once RTCCertificate and its
|
||||||
// ssl_certificate() is used in all relevant places. Should not pass around
|
// ssl_certificate() is used in all relevant places. Should not pass around
|
||||||
|
|
|
@ -43,30 +43,6 @@ SSLCertificateStats::~SSLCertificateStats() {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<SSLCertificateStats> SSLCertificate::GetStats() const {
|
std::unique_ptr<SSLCertificateStats> SSLCertificate::GetStats() const {
|
||||||
// We have a certificate and optionally a chain of certificates. This forms a
|
|
||||||
// linked list, starting with |this|, then the first element of |chain| and
|
|
||||||
// ending with the last element of |chain|. The "issuer" of a certificate is
|
|
||||||
// the next certificate in the chain. Stats are produced for each certificate
|
|
||||||
// in the list. Here, the "issuer" is the issuer's stats.
|
|
||||||
std::unique_ptr<SSLCertChain> chain = GetChain();
|
|
||||||
std::unique_ptr<SSLCertificateStats> issuer;
|
|
||||||
if (chain) {
|
|
||||||
// The loop runs in reverse so that the |issuer| is known before the
|
|
||||||
// |cert|'s stats.
|
|
||||||
for (ptrdiff_t i = chain->GetSize() - 1; i >= 0; --i) {
|
|
||||||
const SSLCertificate* cert = &chain->Get(i);
|
|
||||||
issuer = cert->GetStats(std::move(issuer));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return GetStats(std::move(issuer));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<SSLCertificate> SSLCertificate::GetUniqueReference() const {
|
|
||||||
return WrapUnique(GetReference());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<SSLCertificateStats> SSLCertificate::GetStats(
|
|
||||||
std::unique_ptr<SSLCertificateStats> issuer) const {
|
|
||||||
// TODO(bemasc): Move this computation to a helper class that caches these
|
// TODO(bemasc): Move this computation to a helper class that caches these
|
||||||
// values to reduce CPU use in |StatsCollector::GetStats|. This will require
|
// values to reduce CPU use in |StatsCollector::GetStats|. This will require
|
||||||
// adding a fast |SSLCertificate::Equals| to detect certificate changes.
|
// adding a fast |SSLCertificate::Equals| to detect certificate changes.
|
||||||
|
@ -89,11 +65,13 @@ std::unique_ptr<SSLCertificateStats> SSLCertificate::GetStats(
|
||||||
std::string der_base64;
|
std::string der_base64;
|
||||||
Base64::EncodeFromArray(der_buffer.data(), der_buffer.size(), &der_base64);
|
Base64::EncodeFromArray(der_buffer.data(), der_buffer.size(), &der_base64);
|
||||||
|
|
||||||
return std::unique_ptr<SSLCertificateStats>(new SSLCertificateStats(
|
return rtc::MakeUnique<SSLCertificateStats>(std::move(fingerprint),
|
||||||
std::move(fingerprint),
|
std::move(digest_algorithm),
|
||||||
std::move(digest_algorithm),
|
std::move(der_base64), nullptr);
|
||||||
std::move(der_base64),
|
}
|
||||||
std::move(issuer)));
|
|
||||||
|
std::unique_ptr<SSLCertificate> SSLCertificate::GetUniqueReference() const {
|
||||||
|
return WrapUnique(GetReference());
|
||||||
}
|
}
|
||||||
|
|
||||||
KeyParams::KeyParams(KeyType key_type) {
|
KeyParams::KeyParams(KeyType key_type) {
|
||||||
|
@ -228,6 +206,28 @@ SSLCertChain* SSLCertChain::Copy() const {
|
||||||
return new SSLCertChain(std::move(new_certs));
|
return new SSLCertChain(std::move(new_certs));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<SSLCertChain> SSLCertChain::UniqueCopy() const {
|
||||||
|
return WrapUnique(Copy());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<SSLCertificateStats> SSLCertChain::GetStats() const {
|
||||||
|
// We have a linked list of certificates, starting with the first element of
|
||||||
|
// |certs_| and ending with the last element of |certs_|. The "issuer" of a
|
||||||
|
// certificate is the next certificate in the chain. Stats are produced for
|
||||||
|
// each certificate in the list. Here, the "issuer" is the issuer's stats.
|
||||||
|
std::unique_ptr<SSLCertificateStats> issuer;
|
||||||
|
// The loop runs in reverse so that the |issuer| is known before the
|
||||||
|
// certificate issued by |issuer|.
|
||||||
|
for (ptrdiff_t i = certs_.size() - 1; i >= 0; --i) {
|
||||||
|
std::unique_ptr<SSLCertificateStats> new_stats = certs_[i]->GetStats();
|
||||||
|
if (new_stats) {
|
||||||
|
new_stats->issuer = std::move(issuer);
|
||||||
|
}
|
||||||
|
issuer = std::move(new_stats);
|
||||||
|
}
|
||||||
|
return issuer;
|
||||||
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
SSLCertificate* SSLCertificate::FromPEMString(const std::string& pem_string) {
|
SSLCertificate* SSLCertificate::FromPEMString(const std::string& pem_string) {
|
||||||
return OpenSSLCertificate::FromPEMString(pem_string);
|
return OpenSSLCertificate::FromPEMString(pem_string);
|
||||||
|
|
|
@ -67,10 +67,6 @@ class SSLCertificate {
|
||||||
|
|
||||||
std::unique_ptr<SSLCertificate> GetUniqueReference() const;
|
std::unique_ptr<SSLCertificate> GetUniqueReference() const;
|
||||||
|
|
||||||
// Returns null. This is deprecated. Please use
|
|
||||||
// SSLStreamAdapter::GetPeerSSLCertChain
|
|
||||||
virtual std::unique_ptr<SSLCertChain> GetChain() const = 0;
|
|
||||||
|
|
||||||
// Returns a PEM encoded string representation of the certificate.
|
// Returns a PEM encoded string representation of the certificate.
|
||||||
virtual std::string ToPEMString() const = 0;
|
virtual std::string ToPEMString() const = 0;
|
||||||
|
|
||||||
|
@ -91,14 +87,10 @@ class SSLCertificate {
|
||||||
// or -1 if an expiration time could not be retrieved.
|
// or -1 if an expiration time could not be retrieved.
|
||||||
virtual int64_t CertificateExpirationTime() const = 0;
|
virtual int64_t CertificateExpirationTime() const = 0;
|
||||||
|
|
||||||
// Gets information (fingerprint, etc.) about this certificate and its chain
|
// Gets information (fingerprint, etc.) about this certificate. This is used
|
||||||
// (if it has a certificate chain). This is used for certificate stats, see
|
// for certificate stats, see
|
||||||
// https://w3c.github.io/webrtc-stats/#certificatestats-dict*.
|
// https://w3c.github.io/webrtc-stats/#certificatestats-dict*.
|
||||||
std::unique_ptr<SSLCertificateStats> GetStats() const;
|
std::unique_ptr<SSLCertificateStats> GetStats() const;
|
||||||
|
|
||||||
private:
|
|
||||||
std::unique_ptr<SSLCertificateStats> GetStats(
|
|
||||||
std::unique_ptr<SSLCertificateStats> issuer) const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// SSLCertChain is a simple wrapper for a vector of SSLCertificates. It serves
|
// SSLCertChain is a simple wrapper for a vector of SSLCertificates. It serves
|
||||||
|
@ -122,6 +114,13 @@ class SSLCertChain {
|
||||||
// Returns a new SSLCertChain object instance wrapping the same underlying
|
// Returns a new SSLCertChain object instance wrapping the same underlying
|
||||||
// certificate chain. Caller is responsible for freeing the returned object.
|
// certificate chain. Caller is responsible for freeing the returned object.
|
||||||
SSLCertChain* Copy() const;
|
SSLCertChain* Copy() const;
|
||||||
|
// Same as above, but returning a unique_ptr for convenience.
|
||||||
|
std::unique_ptr<SSLCertChain> UniqueCopy() const;
|
||||||
|
|
||||||
|
// Gets information (fingerprint, etc.) about this certificate chain. This is
|
||||||
|
// used for certificate stats, see
|
||||||
|
// https://w3c.github.io/webrtc-stats/#certificatestats-dict*.
|
||||||
|
std::unique_ptr<SSLCertificateStats> GetStats() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<std::unique_ptr<SSLCertificate>> certs_;
|
std::vector<std::unique_ptr<SSLCertificate>> certs_;
|
||||||
|
@ -241,8 +240,10 @@ class SSLIdentity {
|
||||||
// TODO(hbos,torbjorng): Rename to a less confusing name.
|
// TODO(hbos,torbjorng): Rename to a less confusing name.
|
||||||
virtual SSLIdentity* GetReference() const = 0;
|
virtual SSLIdentity* GetReference() const = 0;
|
||||||
|
|
||||||
// Returns a temporary reference to the certificate.
|
// Returns a temporary reference to the end-entity (leaf) certificate.
|
||||||
virtual const SSLCertificate& certificate() const = 0;
|
virtual const SSLCertificate& certificate() const = 0;
|
||||||
|
// Returns a temporary reference to the entire certificate chain.
|
||||||
|
virtual const SSLCertChain& cert_chain() const = 0;
|
||||||
virtual std::string PrivateKeyToPEMString() const = 0;
|
virtual std::string PrivateKeyToPEMString() const = 0;
|
||||||
virtual std::string PublicKeyToPEMString() const = 0;
|
virtual std::string PublicKeyToPEMString() const = 0;
|
||||||
|
|
||||||
|
|
|
@ -175,8 +175,7 @@ IdentityAndInfo CreateFakeIdentityAndInfoFromDers(
|
||||||
reinterpret_cast<const unsigned char*>(der.c_str()),
|
reinterpret_cast<const unsigned char*>(der.c_str()),
|
||||||
der.length()));
|
der.length()));
|
||||||
}
|
}
|
||||||
info.identity.reset(
|
info.identity.reset(new rtc::FakeSSLIdentity(info.pems));
|
||||||
new rtc::FakeSSLIdentity(rtc::FakeSSLCertificate(info.pems)));
|
|
||||||
// Strip header/footer and newline characters of PEM strings.
|
// Strip header/footer and newline characters of PEM strings.
|
||||||
for (size_t i = 0; i < info.pems.size(); ++i) {
|
for (size_t i = 0; i < info.pems.size(); ++i) {
|
||||||
rtc::replace_substrs("-----BEGIN CERTIFICATE-----", 27,
|
rtc::replace_substrs("-----BEGIN CERTIFICATE-----", 27,
|
||||||
|
@ -186,20 +185,14 @@ IdentityAndInfo CreateFakeIdentityAndInfoFromDers(
|
||||||
rtc::replace_substrs("\n", 1,
|
rtc::replace_substrs("\n", 1,
|
||||||
"", 0, &info.pems[i]);
|
"", 0, &info.pems[i]);
|
||||||
}
|
}
|
||||||
// Fingerprint of leaf certificate.
|
// Fingerprints for the whole certificate chain, starting with leaf
|
||||||
std::unique_ptr<rtc::SSLFingerprint> fp(
|
// certificate.
|
||||||
rtc::SSLFingerprint::Create("sha-1", &info.identity->certificate()));
|
const rtc::SSLCertChain& chain = info.identity->cert_chain();
|
||||||
EXPECT_TRUE(fp);
|
std::unique_ptr<rtc::SSLFingerprint> fp;
|
||||||
info.fingerprints.push_back(fp->GetRfc4572Fingerprint());
|
for (size_t i = 0; i < chain.GetSize(); i++) {
|
||||||
// Fingerprints of the rest of the chain.
|
fp.reset(rtc::SSLFingerprint::Create("sha-1", &chain.Get(i)));
|
||||||
std::unique_ptr<rtc::SSLCertChain> chain =
|
EXPECT_TRUE(fp);
|
||||||
info.identity->certificate().GetChain();
|
info.fingerprints.push_back(fp->GetRfc4572Fingerprint());
|
||||||
if (chain) {
|
|
||||||
for (size_t i = 0; i < chain->GetSize(); i++) {
|
|
||||||
fp.reset(rtc::SSLFingerprint::Create("sha-1", &chain->Get(i)));
|
|
||||||
EXPECT_TRUE(fp);
|
|
||||||
info.fingerprints.push_back(fp->GetRfc4572Fingerprint());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
EXPECT_EQ(info.ders.size(), info.fingerprints.size());
|
EXPECT_EQ(info.ders.size(), info.fingerprints.size());
|
||||||
return info;
|
return info;
|
||||||
|
@ -477,7 +470,7 @@ TEST_F(SSLIdentityTest, SSLCertificateGetStatsWithChain) {
|
||||||
EXPECT_EQ(info.fingerprints.size(), info.ders.size());
|
EXPECT_EQ(info.fingerprints.size(), info.ders.size());
|
||||||
|
|
||||||
std::unique_ptr<rtc::SSLCertificateStats> first_stats =
|
std::unique_ptr<rtc::SSLCertificateStats> first_stats =
|
||||||
info.identity->certificate().GetStats();
|
info.identity->cert_chain().GetStats();
|
||||||
rtc::SSLCertificateStats* cert_stats = first_stats.get();
|
rtc::SSLCertificateStats* cert_stats = first_stats.get();
|
||||||
for (size_t i = 0; i < info.ders.size(); ++i) {
|
for (size_t i = 0; i < info.ders.size(); ++i) {
|
||||||
EXPECT_EQ(cert_stats->fingerprint, info.fingerprints[i]);
|
EXPECT_EQ(cert_stats->fingerprint, info.fingerprints[i]);
|
||||||
|
|
|
@ -201,11 +201,7 @@ class SSLStreamAdapter : public StreamAdapterInterface {
|
||||||
size_t digest_len,
|
size_t digest_len,
|
||||||
SSLPeerCertificateDigestError* error = nullptr) = 0;
|
SSLPeerCertificateDigestError* error = nullptr) = 0;
|
||||||
|
|
||||||
// Retrieves the peer's X.509 certificate, if a connection has been
|
// Retrieves the peer's certificate chain including leaf certificate, if a
|
||||||
// established.
|
|
||||||
virtual std::unique_ptr<SSLCertificate> GetPeerCertificate() const = 0;
|
|
||||||
|
|
||||||
// Retrieves the peer's certificate chain including leaf, if a
|
|
||||||
// connection has been established.
|
// connection has been established.
|
||||||
virtual std::unique_ptr<SSLCertChain> GetPeerSSLCertChain() const = 0;
|
virtual std::unique_ptr<SSLCertChain> GetPeerSSLCertChain() const = 0;
|
||||||
|
|
||||||
|
|
|
@ -597,10 +597,13 @@ class SSLStreamAdapterTestBase : public testing::Test,
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<rtc::SSLCertificate> GetPeerCertificate(bool client) {
|
std::unique_ptr<rtc::SSLCertificate> GetPeerCertificate(bool client) {
|
||||||
|
std::unique_ptr<rtc::SSLCertChain> chain;
|
||||||
if (client)
|
if (client)
|
||||||
return client_ssl_->GetPeerCertificate();
|
chain = client_ssl_->GetPeerSSLCertChain();
|
||||||
else
|
else
|
||||||
return server_ssl_->GetPeerCertificate();
|
chain = server_ssl_->GetPeerSSLCertChain();
|
||||||
|
return (chain && chain->GetSize()) ? chain->Get(0).GetUniqueReference()
|
||||||
|
: nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GetSslCipherSuite(bool client, int* retval) {
|
bool GetSslCipherSuite(bool client, int* retval) {
|
||||||
|
@ -971,11 +974,10 @@ TEST_P(SSLStreamAdapterTestTLS, GetPeerCertChainWithOneCertificate) {
|
||||||
TestHandshake();
|
TestHandshake();
|
||||||
std::unique_ptr<rtc::SSLCertChain> cert_chain =
|
std::unique_ptr<rtc::SSLCertChain> cert_chain =
|
||||||
client_ssl_->GetPeerSSLCertChain();
|
client_ssl_->GetPeerSSLCertChain();
|
||||||
std::unique_ptr<rtc::SSLCertificate> certificate =
|
|
||||||
client_ssl_->GetPeerCertificate();
|
|
||||||
ASSERT_NE(nullptr, cert_chain);
|
ASSERT_NE(nullptr, cert_chain);
|
||||||
EXPECT_EQ(1u, cert_chain->GetSize());
|
EXPECT_EQ(1u, cert_chain->GetSize());
|
||||||
EXPECT_EQ(cert_chain->Get(0).ToPEMString(), certificate->ToPEMString());
|
EXPECT_EQ(cert_chain->Get(0).ToPEMString(),
|
||||||
|
server_identity_->certificate().ToPEMString());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SSLStreamAdapterTestDTLSCertChain, TwoCertHandshake) {
|
TEST_F(SSLStreamAdapterTestDTLSCertChain, TwoCertHandshake) {
|
||||||
|
@ -1388,9 +1390,6 @@ TEST_F(SSLStreamAdapterTestDTLSFromPEMStrings, TestDTLSGetPeerCertificate) {
|
||||||
std::string client_peer_string = client_peer_cert->ToPEMString();
|
std::string client_peer_string = client_peer_cert->ToPEMString();
|
||||||
ASSERT_NE(kCERT_PEM, client_peer_string);
|
ASSERT_NE(kCERT_PEM, client_peer_string);
|
||||||
|
|
||||||
// It must not have a chain, because the test certs are self-signed.
|
|
||||||
ASSERT_FALSE(client_peer_cert->GetChain());
|
|
||||||
|
|
||||||
// The server should have a peer certificate after the handshake.
|
// The server should have a peer certificate after the handshake.
|
||||||
std::unique_ptr<rtc::SSLCertificate> server_peer_cert =
|
std::unique_ptr<rtc::SSLCertificate> server_peer_cert =
|
||||||
GetPeerCertificate(false);
|
GetPeerCertificate(false);
|
||||||
|
@ -1398,9 +1397,6 @@ TEST_F(SSLStreamAdapterTestDTLSFromPEMStrings, TestDTLSGetPeerCertificate) {
|
||||||
|
|
||||||
// It's kCERT_PEM
|
// It's kCERT_PEM
|
||||||
ASSERT_EQ(kCERT_PEM, server_peer_cert->ToPEMString());
|
ASSERT_EQ(kCERT_PEM, server_peer_cert->ToPEMString());
|
||||||
|
|
||||||
// It must not have a chain, because the test certs are self-signed.
|
|
||||||
ASSERT_FALSE(server_peer_cert->GetChain());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test getting the used DTLS ciphers.
|
// Test getting the used DTLS ciphers.
|
||||||
|
|
Loading…
Reference in a new issue