From be5a4d963d0757e60b2c79e43573f234c458114b Mon Sep 17 00:00:00 2001 From: achingbrain Date: Sun, 9 Jun 2024 10:27:35 +0100 Subject: [PATCH] feat: add remoteFingerprints method to PeerConnection Returns a vector that contains the certificate fingerprints used by the connection to the remote peer. Closes #1203 Refs #1166 --- include/rtc/peerconnection.hpp | 6 ++++++ src/impl/peerconnection.cpp | 31 +++++++++++++++++++++++++------ src/impl/peerconnection.hpp | 6 +++++- src/peerconnection.cpp | 4 ++++ 4 files changed, 40 insertions(+), 7 deletions(-) diff --git a/include/rtc/peerconnection.hpp b/include/rtc/peerconnection.hpp index 9e49f80e1..e07ad4461 100644 --- a/include/rtc/peerconnection.hpp +++ b/include/rtc/peerconnection.hpp @@ -35,6 +35,11 @@ struct RTC_CPP_EXPORT DataChannelInit { string protocol = ""; }; +struct RTC_CPP_EXPORT RemoteFingerprint { + string value; + CertificateFingerprint::Algorithm algorithm; +}; + class RTC_CPP_EXPORT PeerConnection final : CheshireCat { public: enum class State : int { @@ -113,6 +118,7 @@ class RTC_CPP_EXPORT PeerConnection final : CheshireCat { void onSignalingStateChange(std::function callback); void resetCallbacks(); + std::vector remoteFingerprints(); // Stats void clearStats(); diff --git a/src/impl/peerconnection.cpp b/src/impl/peerconnection.cpp index 1d3611b2b..a334eee54 100644 --- a/src/impl/peerconnection.cpp +++ b/src/impl/peerconnection.cpp @@ -239,7 +239,7 @@ shared_ptr PeerConnection::initDtlsTransport() { throw std::logic_error("No underlying ICE transport for DTLS transport"); auto certificate = mCertificate.get(); - auto verifierCallback = weak_bind(&PeerConnection::checkFingerprint, this, _1); + auto verifierCallback = weak_bind(&PeerConnection::checkFingerprint, this, _1, fingerprintAlgorithm); auto dtlsStateChangeCallback = [this, weak_this = weak_from_this()](DtlsTransport::State transportState) { auto shared_this = weak_this.lock(); @@ -439,17 +439,15 @@ void PeerConnection::rollbackLocalDescription() { } } -bool PeerConnection::checkFingerprint(const std::string &fingerprint) const { +bool PeerConnection::checkFingerprint(const std::string &fingerprint, const CertificateFingerprint::Algorithm &algorithm) { std::lock_guard lock(mRemoteDescriptionMutex); if (!mRemoteDescription || !mRemoteDescription->fingerprint()) return false; - if (config.disableFingerprintVerification) - return true; - auto expectedFingerprint = mRemoteDescription->fingerprint()->value; - if (expectedFingerprint == fingerprint) { + if (config.disableFingerprintVerification || expectedFingerprint == fingerprint) { PLOG_VERBOSE << "Valid fingerprint \"" << fingerprint << "\""; + storeRemoteFingerprint(fingerprint, algorithm); return true; } @@ -457,6 +455,20 @@ bool PeerConnection::checkFingerprint(const std::string &fingerprint) const { return false; } +void PeerConnection::storeRemoteFingerprint(const std::string &fingerprint, const CertificateFingerprint::Algorithm &algorithm) { + auto iter = std::find_if(rFingerprints.begin(), rFingerprints.end(), [&](const RemoteFingerprint& existing){return existing.value == fingerprint;}); + bool seenPreviously = iter != rFingerprints.end(); + + if (seenPreviously) { + return; + } + + rFingerprints.push_back({ + .value = fingerprint, + algorithm + }); +} + void PeerConnection::forwardMessage(message_ptr message) { if (!message) { remoteCloseDataChannels(); @@ -1301,6 +1313,13 @@ void PeerConnection::resetCallbacks() { trackCallback = nullptr; } +std::vector PeerConnection::remoteFingerprints() { + std::vector ret; + ret = rFingerprints; + + return ret; +} + void PeerConnection::updateTrackSsrcCache(const Description &description) { std::unique_lock lock(mTracksMutex); // for safely writing to mTracksBySsrc diff --git a/src/impl/peerconnection.hpp b/src/impl/peerconnection.hpp index 33dba4408..4fd611939 100644 --- a/src/impl/peerconnection.hpp +++ b/src/impl/peerconnection.hpp @@ -53,7 +53,7 @@ struct PeerConnection : std::enable_shared_from_this { void endLocalCandidates(); void rollbackLocalDescription(); - bool checkFingerprint(const std::string &fingerprint) const; + bool checkFingerprint(const std::string &fingerprint, const CertificateFingerprint::Algorithm &algorithm); void forwardMessage(message_ptr message); void forwardMedia(message_ptr message); void forwardBufferedAmount(uint16_t stream, size_t amount); @@ -98,6 +98,7 @@ struct PeerConnection : std::enable_shared_from_this { bool changeSignalingState(SignalingState newState); void resetCallbacks(); + std::vector remoteFingerprints(); // Helper method for asynchronous callback invocation template void trigger(synchronized_callback *cb, Args... args) { @@ -129,6 +130,7 @@ struct PeerConnection : std::enable_shared_from_this { private: void dispatchMedia(message_ptr message); void updateTrackSsrcCache(const Description &description); + void storeRemoteFingerprint(const std::string &fingerprint, const CertificateFingerprint::Algorithm &algorithm); const init_token mInitToken = Init::Instance().token(); future_certificate_ptr mCertificate; @@ -157,6 +159,8 @@ struct PeerConnection : std::enable_shared_from_this { Queue> mPendingDataChannels; Queue> mPendingTracks; + + std::vector rFingerprints; }; } // namespace rtc::impl diff --git a/src/peerconnection.cpp b/src/peerconnection.cpp index 0e146834b..caaef24bb 100644 --- a/src/peerconnection.cpp +++ b/src/peerconnection.cpp @@ -367,6 +367,10 @@ optional PeerConnection::rtt() { return sctpTransport ? sctpTransport->rtt() : nullopt; } +std::vector PeerConnection::remoteFingerprints() { + return impl()->remoteFingerprints(); +} + std::ostream &operator<<(std::ostream &out, PeerConnection::State state) { using State = PeerConnection::State; const char *str;