Expose DtlsTransport::remote_ssl_certificates

Bug: chromium:907849
Change-Id: If990d541099edb9a327230e1d78a03b406269885
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/131951
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Commit-Queue: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27558}
diff --git a/api/BUILD.gn b/api/BUILD.gn
index 84b0c0e..31dd898 100644
--- a/api/BUILD.gn
+++ b/api/BUILD.gn
@@ -93,6 +93,7 @@
     "crypto_params.h",
     "data_channel_interface.cc",
     "data_channel_interface.h",
+    "dtls_transport_interface.cc",
     "dtls_transport_interface.h",
     "dtmf_sender_interface.h",
     "ice_transport_interface.h",
diff --git a/api/DEPS b/api/DEPS
index 6afa3d7..34bdfe0 100644
--- a/api/DEPS
+++ b/api/DEPS
@@ -75,6 +75,7 @@
 
   "dtls_transport_interface\.h": [
     "+rtc_base/ref_count.h",
+    "+rtc_base/ssl_certificate.h",
   ],
 
   "dtmf_sender_interface\.h": [
diff --git a/api/dtls_transport_interface.cc b/api/dtls_transport_interface.cc
new file mode 100644
index 0000000..2bb5049
--- /dev/null
+++ b/api/dtls_transport_interface.cc
@@ -0,0 +1,43 @@
+/*
+ *  Copyright 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "api/dtls_transport_interface.h"
+
+namespace webrtc {
+
+DtlsTransportInformation::DtlsTransportInformation()
+    : state_(DtlsTransportState::kNew) {}
+
+DtlsTransportInformation::DtlsTransportInformation(DtlsTransportState state)
+    : state_(state) {}
+
+DtlsTransportInformation::DtlsTransportInformation(
+    DtlsTransportState state,
+    std::unique_ptr<rtc::SSLCertChain> remote_ssl_certificates)
+    : state_(state),
+      remote_ssl_certificates_(std::move(remote_ssl_certificates)) {}
+
+DtlsTransportInformation::DtlsTransportInformation(
+    const DtlsTransportInformation& c)
+    : state_(c.state()),
+      remote_ssl_certificates_(c.remote_ssl_certificates()
+                                   ? c.remote_ssl_certificates()->Clone()
+                                   : nullptr) {}
+
+DtlsTransportInformation& DtlsTransportInformation::operator=(
+    const DtlsTransportInformation& c) {
+  state_ = c.state();
+  remote_ssl_certificates_ = c.remote_ssl_certificates()
+                                 ? c.remote_ssl_certificates()->Clone()
+                                 : nullptr;
+  return *this;
+}
+
+}  // namespace webrtc
diff --git a/api/dtls_transport_interface.h b/api/dtls_transport_interface.h
index 7f35a23..0270043 100644
--- a/api/dtls_transport_interface.h
+++ b/api/dtls_transport_interface.h
@@ -11,10 +11,14 @@
 #ifndef API_DTLS_TRANSPORT_INTERFACE_H_
 #define API_DTLS_TRANSPORT_INTERFACE_H_
 
+#include <memory>
+#include <utility>
+
 #include "api/ice_transport_interface.h"
 #include "api/rtc_error.h"
 #include "api/scoped_refptr.h"
 #include "rtc_base/ref_count.h"
+#include "rtc_base/ssl_certificate.h"
 
 namespace webrtc {
 
@@ -34,11 +38,28 @@
 // DTLSTransport.
 class DtlsTransportInformation {
  public:
-  explicit DtlsTransportInformation(DtlsTransportState state) : state_(state) {}
+  DtlsTransportInformation();
+  explicit DtlsTransportInformation(DtlsTransportState state);
+  DtlsTransportInformation(
+      DtlsTransportState state,
+      std::unique_ptr<rtc::SSLCertChain> remote_ssl_certificates);
+  // Copy and assign
+  DtlsTransportInformation(const DtlsTransportInformation& c);
+  DtlsTransportInformation& operator=(const DtlsTransportInformation& c);
+  // Move
+  DtlsTransportInformation(DtlsTransportInformation&& other) = default;
+  DtlsTransportInformation& operator=(DtlsTransportInformation&& other) =
+      default;
+
   DtlsTransportState state() const { return state_; }
-  // TODO(hta): Add remote certificate access
+  // The accessor returns a temporary pointer, it does not release ownership.
+  const rtc::SSLCertChain* remote_ssl_certificates() const {
+    return remote_ssl_certificates_.get();
+  }
+
  private:
   DtlsTransportState state_;
+  std::unique_ptr<rtc::SSLCertChain> remote_ssl_certificates_;
 };
 
 class DtlsTransportObserverInterface {
diff --git a/pc/dtls_transport.cc b/pc/dtls_transport.cc
index 38cef1e..9ce72a3 100644
--- a/pc/dtls_transport.cc
+++ b/pc/dtls_transport.cc
@@ -116,8 +116,15 @@
   RTC_DCHECK_RUN_ON(owner_thread_);
   rtc::CritScope scope(&lock_);
   if (internal_dtls_transport_) {
-    info_ = DtlsTransportInformation(
-        TranslateState(internal_dtls_transport_->dtls_state()));
+    if (internal_dtls_transport_->dtls_state() ==
+        cricket::DTLS_TRANSPORT_CONNECTED) {
+      info_ = DtlsTransportInformation(
+          TranslateState(internal_dtls_transport_->dtls_state()),
+          internal_dtls_transport_->GetRemoteSSLCertChain());
+    } else {
+      info_ = DtlsTransportInformation(
+          TranslateState(internal_dtls_transport_->dtls_state()));
+    }
   } else {
     info_ = DtlsTransportInformation(DtlsTransportState::kClosed);
   }
diff --git a/pc/dtls_transport_unittest.cc b/pc/dtls_transport_unittest.cc
index 0c27c1b..05f5440 100644
--- a/pc/dtls_transport_unittest.cc
+++ b/pc/dtls_transport_unittest.cc
@@ -31,6 +31,7 @@
   void OnStateChange(DtlsTransportInformation info) override {
     state_change_called_ = true;
     states_.push_back(info.state());
+    info_ = info;
   }
 
   void OnError(RTCError error) override {}
@@ -44,6 +45,7 @@
   }
 
   bool state_change_called_ = false;
+  DtlsTransportInformation info_;
   std::vector<DtlsTransportState> states_;
 };
 
@@ -52,9 +54,12 @@
   DtlsTransport* transport() { return transport_.get(); }
   DtlsTransportObserverInterface* observer() { return &observer_; }
 
-  void CreateTransport() {
+  void CreateTransport(rtc::FakeSSLCertificate* certificate = nullptr) {
     auto cricket_transport = absl::make_unique<FakeDtlsTransport>(
         "audio", cricket::ICE_CANDIDATE_COMPONENT_RTP);
+    if (certificate) {
+      cricket_transport->SetRemoteSSLCertificate(certificate);
+    }
     transport_ =
         new rtc::RefCountedObject<DtlsTransport>(std::move(cricket_transport));
   }
@@ -113,4 +118,28 @@
                    kDefaultTimeout);
 }
 
+TEST_F(DtlsTransportTest, CertificateAppearsOnConnect) {
+  rtc::FakeSSLCertificate fake_certificate("fake data");
+  CreateTransport(&fake_certificate);
+  transport()->RegisterObserver(observer());
+  CompleteDtlsHandshake();
+  ASSERT_TRUE_WAIT(observer_.state() == DtlsTransportState::kConnected,
+                   kDefaultTimeout);
+  EXPECT_TRUE(observer_.info_.remote_ssl_certificates() != nullptr);
+}
+
+TEST_F(DtlsTransportTest, CertificateDisappearsOnClose) {
+  rtc::FakeSSLCertificate fake_certificate("fake data");
+  CreateTransport(&fake_certificate);
+  transport()->RegisterObserver(observer());
+  CompleteDtlsHandshake();
+  ASSERT_TRUE_WAIT(observer_.state() == DtlsTransportState::kConnected,
+                   kDefaultTimeout);
+  EXPECT_TRUE(observer_.info_.remote_ssl_certificates() != nullptr);
+  transport()->Clear();
+  ASSERT_TRUE_WAIT(observer_.state() == DtlsTransportState::kClosed,
+                   kDefaultTimeout);
+  EXPECT_FALSE(observer_.info_.remote_ssl_certificates());
+}
+
 }  // namespace webrtc