Added fingerprint check

This commit is contained in:
Paul-Louis Ageneau
2021-03-18 20:51:12 +01:00
parent 412f94dd96
commit 016aea7805
2 changed files with 67 additions and 43 deletions

View File

@ -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();

View File

@ -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");