Skip to content

Commit

Permalink
feat: add remoteFingerprints method to PeerConnection
Browse files Browse the repository at this point in the history
Returns a vector that contains the certificate fingerprints used
by the connection to the remote peer.

Closes paullouisageneau#1203
Refs paullouisageneau#1166
  • Loading branch information
achingbrain committed Jun 11, 2024
1 parent 541d646 commit 9d03db6
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 7 deletions.
6 changes: 6 additions & 0 deletions include/rtc/peerconnection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<impl::PeerConnection> {
public:
enum class State : int {
Expand Down Expand Up @@ -113,6 +118,7 @@ class RTC_CPP_EXPORT PeerConnection final : CheshireCat<impl::PeerConnection> {
void onSignalingStateChange(std::function<void(SignalingState state)> callback);

void resetCallbacks();
std::vector<struct RemoteFingerprint> remoteFingerprints();

// Stats
void clearStats();
Expand Down
31 changes: 25 additions & 6 deletions src/impl/peerconnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ shared_ptr<DtlsTransport> 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();
Expand Down Expand Up @@ -439,24 +439,36 @@ 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;
}

PLOG_ERROR << "Invalid fingerprint \"" << fingerprint << "\", expected \"" << expectedFingerprint << "\"";
return false;
}

void PeerConnection::storeRemoteFingerprint(const std::string &value, const CertificateFingerprint::Algorithm &algorithm) {
auto iter = std::find_if(rFingerprints.begin(), rFingerprints.end(), [&](const RemoteFingerprint& existing){return existing.value == value;});
bool seenPreviously = iter != rFingerprints.end();

if (seenPreviously) {
return;
}

rFingerprints.push_back({
value,
algorithm
});
}

void PeerConnection::forwardMessage(message_ptr message) {
if (!message) {
remoteCloseDataChannels();
Expand Down Expand Up @@ -1301,6 +1313,13 @@ void PeerConnection::resetCallbacks() {
trackCallback = nullptr;
}

std::vector<struct RemoteFingerprint> PeerConnection::remoteFingerprints() {
std::vector<struct RemoteFingerprint> ret;
ret = rFingerprints;

return ret;
}

void PeerConnection::updateTrackSsrcCache(const Description &description) {
std::unique_lock lock(mTracksMutex); // for safely writing to mTracksBySsrc

Expand Down
6 changes: 5 additions & 1 deletion src/impl/peerconnection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ struct PeerConnection : std::enable_shared_from_this<PeerConnection> {

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);
Expand Down Expand Up @@ -98,6 +98,7 @@ struct PeerConnection : std::enable_shared_from_this<PeerConnection> {
bool changeSignalingState(SignalingState newState);

void resetCallbacks();
std::vector<struct RemoteFingerprint> remoteFingerprints();

// Helper method for asynchronous callback invocation
template <typename... Args> void trigger(synchronized_callback<Args...> *cb, Args... args) {
Expand Down Expand Up @@ -129,6 +130,7 @@ struct PeerConnection : std::enable_shared_from_this<PeerConnection> {
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;
Expand Down Expand Up @@ -157,6 +159,8 @@ struct PeerConnection : std::enable_shared_from_this<PeerConnection> {

Queue<shared_ptr<DataChannel>> mPendingDataChannels;
Queue<shared_ptr<Track>> mPendingTracks;

std::vector<struct RemoteFingerprint> rFingerprints;
};

} // namespace rtc::impl
Expand Down
4 changes: 4 additions & 0 deletions src/peerconnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,10 @@ optional<std::chrono::milliseconds> PeerConnection::rtt() {
return sctpTransport ? sctpTransport->rtt() : nullopt;
}

std::vector<struct RemoteFingerprint> PeerConnection::remoteFingerprints() {
return impl()->remoteFingerprints();
}

std::ostream &operator<<(std::ostream &out, PeerConnection::State state) {
using State = PeerConnection::State;
const char *str;
Expand Down

0 comments on commit 9d03db6

Please sign in to comment.