mirror of
https://github.com/mii443/libdatachannel.git
synced 2025-08-22 15:15:28 +00:00
Added fingerprint check
This commit is contained in:
@ -40,6 +40,11 @@ inline bool match_prefix(string_view str, string_view prefix) {
|
||||
std::mismatch(prefix.begin(), prefix.end(), str.begin()).first == prefix.end();
|
||||
}
|
||||
|
||||
inline void trim_begin(string &str) {
|
||||
str.erase(str.begin(),
|
||||
std::find_if(str.begin(), str.end(), [](char c) { return !std::isspace(c); }));
|
||||
}
|
||||
|
||||
inline void trim_end(string &str) {
|
||||
str.erase(
|
||||
std::find_if(str.rbegin(), str.rend(), [](char c) { return !std::isspace(c); }).base(),
|
||||
@ -61,12 +66,27 @@ template <typename T> T to_integer(string_view s) {
|
||||
const string str(s);
|
||||
try {
|
||||
return std::is_signed<T>::value ? T(std::stol(str)) : T(std::stoul(str));
|
||||
}
|
||||
catch(...) {
|
||||
} catch (...) {
|
||||
throw std::invalid_argument("Invalid integer \"" + str + "\" in description");
|
||||
}
|
||||
}
|
||||
|
||||
inline bool is_sha256_fingerprint(string_view f) {
|
||||
if (f.size() != 32 * 3 - 1)
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < f.size(); ++i) {
|
||||
if (i % 3 == 2) {
|
||||
if (f[i] != ':')
|
||||
return false;
|
||||
} else {
|
||||
if (!std::isxdigit(f[i]))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace rtc {
|
||||
@ -106,10 +126,9 @@ Description::Description(const string &sdp, Type type, Role role)
|
||||
|
||||
} else if (key == "fingerprint") {
|
||||
if (match_prefix(value, "sha-256 ")) {
|
||||
mFingerprint = value.substr(8);
|
||||
std::transform(mFingerprint->begin(), mFingerprint->end(),
|
||||
mFingerprint->begin(),
|
||||
[](char c) { return char(std::toupper(c)); });
|
||||
string fingerprint{value.substr(8)};
|
||||
trim_begin(fingerprint);
|
||||
setFingerprint(std::move(fingerprint));
|
||||
} else {
|
||||
PLOG_WARNING << "Unknown SDP fingerprint format: " << value;
|
||||
}
|
||||
@ -173,6 +192,11 @@ void Description::hintType(Type type) {
|
||||
}
|
||||
|
||||
void Description::setFingerprint(string fingerprint) {
|
||||
if (!is_sha256_fingerprint(fingerprint))
|
||||
throw std::invalid_argument("Invalid SHA256 fingerprint \"" + fingerprint + "\"");
|
||||
|
||||
std::transform(fingerprint.begin(), fingerprint.end(), fingerprint.begin(),
|
||||
[](char c) { return char(std::toupper(c)); });
|
||||
mFingerprint.emplace(std::move(fingerprint));
|
||||
}
|
||||
|
||||
@ -401,8 +425,7 @@ int Description::addAudio(string mid, Direction dir) {
|
||||
return addMedia(Audio(std::move(mid), dir));
|
||||
}
|
||||
|
||||
variant<Description::Media *, Description::Application *>
|
||||
Description::media(unsigned int index) {
|
||||
variant<Description::Media *, Description::Application *> Description::media(unsigned int index) {
|
||||
if (index >= mEntries.size())
|
||||
throw std::out_of_range("Media index out of range");
|
||||
|
||||
@ -523,21 +546,22 @@ Description::Entry::removeAttribute(std::vector<string>::iterator it) {
|
||||
return mAttributes.erase(it);
|
||||
}
|
||||
|
||||
void Description::Media::addSSRC(uint32_t ssrc, optional<string> name,
|
||||
optional<string> msid, optional<string> trackID) {
|
||||
void Description::Media::addSSRC(uint32_t ssrc, optional<string> name, optional<string> msid,
|
||||
optional<string> trackID) {
|
||||
if (name)
|
||||
mAttributes.emplace_back("ssrc:" + std::to_string(ssrc) + " cname:" + *name);
|
||||
else
|
||||
mAttributes.emplace_back("ssrc:" + std::to_string(ssrc));
|
||||
|
||||
if (msid)
|
||||
mAttributes.emplace_back("ssrc:" + std::to_string(ssrc) + " msid:" + *msid + " " + trackID.value_or(*msid));
|
||||
mAttributes.emplace_back("ssrc:" + std::to_string(ssrc) + " msid:" + *msid + " " +
|
||||
trackID.value_or(*msid));
|
||||
|
||||
mSsrcs.emplace_back(ssrc);
|
||||
}
|
||||
|
||||
void Description::Media::replaceSSRC(uint32_t oldSSRC, uint32_t ssrc, optional<string> name,
|
||||
optional<string> msid, optional<string> trackID) {
|
||||
optional<string> msid, optional<string> trackID) {
|
||||
auto it = mAttributes.begin();
|
||||
while (it != mAttributes.end()) {
|
||||
if (it->find("ssrc:" + std::to_string(oldSSRC)) == 0) {
|
||||
@ -708,8 +732,7 @@ void Description::Media::removeFormat(const string &fmt) {
|
||||
}
|
||||
}
|
||||
|
||||
void Description::Video::addVideoCodec(int payloadType, string codec,
|
||||
optional<string> profile) {
|
||||
void Description::Video::addVideoCodec(int payloadType, string codec, optional<string> profile) {
|
||||
RTPMap map(std::to_string(payloadType) + ' ' + codec + "/90000");
|
||||
map.addFB("nack");
|
||||
map.addFB("nack pli");
|
||||
@ -733,8 +756,7 @@ void Description::Video::addVideoCodec(int payloadType, string codec,
|
||||
// ";rtx-time=3000"); addRTPMap(rtx);
|
||||
}
|
||||
|
||||
void Description::Audio::addAudioCodec(int payloadType, string codec,
|
||||
optional<string> profile) {
|
||||
void Description::Audio::addAudioCodec(int payloadType, string codec, optional<string> profile) {
|
||||
// TODO This 48000/2 should be parameterized
|
||||
RTPMap map(std::to_string(payloadType) + ' ' + codec + "/48000/2");
|
||||
if (profile)
|
||||
@ -843,9 +865,7 @@ void Description::Media::addRTPMap(const Description::Media::RTPMap &map) {
|
||||
mRtpMap.emplace(map.pt, map);
|
||||
}
|
||||
|
||||
std::vector<uint32_t> Description::Media::getSSRCs() {
|
||||
return mSsrcs;
|
||||
}
|
||||
std::vector<uint32_t> Description::Media::getSSRCs() { return mSsrcs; }
|
||||
|
||||
std::map<int, Description::Media::RTPMap>::iterator Description::Media::beginMaps() {
|
||||
return mRtpMap.begin();
|
||||
|
@ -355,10 +355,14 @@ void PeerConnection::rollbackLocalDescription() {
|
||||
|
||||
bool PeerConnection::checkFingerprint(const std::string &fingerprint) const {
|
||||
std::lock_guard lock(mRemoteDescriptionMutex);
|
||||
if (auto expectedFingerprint =
|
||||
mRemoteDescription ? mRemoteDescription->fingerprint() : nullopt) {
|
||||
return *expectedFingerprint == fingerprint;
|
||||
auto expectedFingerprint = mRemoteDescription ? mRemoteDescription->fingerprint() : nullopt;
|
||||
if (expectedFingerprint && *expectedFingerprint == fingerprint) {
|
||||
PLOG_VERBOSE << "Valid fingerprint \"" << fingerprint << "\"";
|
||||
return true;
|
||||
}
|
||||
|
||||
PLOG_ERROR << "Invalid fingerprint \"" << fingerprint << "\", expected \""
|
||||
<< expectedFingerprint.value_or("[none]") << "\"";
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -482,16 +486,16 @@ optional<std::string> PeerConnection::getMidFromSsrc(uint32_t ssrc) {
|
||||
if (!mRemoteDescription)
|
||||
return nullopt;
|
||||
for (unsigned int i = 0; i < mRemoteDescription->mediaCount(); ++i) {
|
||||
if (auto found = std::visit(
|
||||
rtc::overloaded{[&](Description::Application *) -> optional<string> {
|
||||
return std::nullopt;
|
||||
},
|
||||
[&](Description::Media *media) -> optional<string> {
|
||||
return media->hasSSRC(ssrc)
|
||||
? std::make_optional(media->mid())
|
||||
: nullopt;
|
||||
}},
|
||||
mRemoteDescription->media(i))) {
|
||||
if (auto found =
|
||||
std::visit(rtc::overloaded{[&](Description::Application *) -> optional<string> {
|
||||
return std::nullopt;
|
||||
},
|
||||
[&](Description::Media *media) -> optional<string> {
|
||||
return media->hasSSRC(ssrc)
|
||||
? std::make_optional(media->mid())
|
||||
: nullopt;
|
||||
}},
|
||||
mRemoteDescription->media(i))) {
|
||||
|
||||
mMidFromSsrc.emplace(ssrc, *found);
|
||||
return *found;
|
||||
@ -503,16 +507,16 @@ optional<std::string> PeerConnection::getMidFromSsrc(uint32_t ssrc) {
|
||||
if (!mLocalDescription)
|
||||
return nullopt;
|
||||
for (unsigned int i = 0; i < mLocalDescription->mediaCount(); ++i) {
|
||||
if (auto found = std::visit(
|
||||
rtc::overloaded{[&](Description::Application *) -> optional<string> {
|
||||
return std::nullopt;
|
||||
},
|
||||
[&](Description::Media *media) -> optional<string> {
|
||||
return media->hasSSRC(ssrc)
|
||||
? std::make_optional(media->mid())
|
||||
: nullopt;
|
||||
}},
|
||||
mLocalDescription->media(i))) {
|
||||
if (auto found =
|
||||
std::visit(rtc::overloaded{[&](Description::Application *) -> optional<string> {
|
||||
return std::nullopt;
|
||||
},
|
||||
[&](Description::Media *media) -> optional<string> {
|
||||
return media->hasSSRC(ssrc)
|
||||
? std::make_optional(media->mid())
|
||||
: nullopt;
|
||||
}},
|
||||
mLocalDescription->media(i))) {
|
||||
|
||||
mMidFromSsrc.emplace(ssrc, *found);
|
||||
return *found;
|
||||
@ -680,7 +684,7 @@ void PeerConnection::validateRemoteDescription(const Description &description) {
|
||||
throw std::invalid_argument("Remote description has no ICE password");
|
||||
|
||||
if (!description.fingerprint())
|
||||
throw std::invalid_argument("Remote description has no fingerprint");
|
||||
throw std::invalid_argument("Remote description has no valid fingerprint");
|
||||
|
||||
if (description.mediaCount() == 0)
|
||||
throw std::invalid_argument("Remote description has no media line");
|
||||
|
Reference in New Issue
Block a user