sdp: reject RTP payload types in the 64-95 range w/rtcp-mux

which is forbidden by
  https://tools.ietf.org/html/rfc5761#section-4

BUG=webrtc:12197

Change-Id: I6227f01e7dcbca3f5871a2e4a8cea3c4db0b16cf
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/319120
Reviewed-by: Florent Castelli <orphis@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Commit-Queue: Philipp Hancke <phancke@microsoft.com>
Cr-Commit-Position: refs/heads/main@{#40752}
This commit is contained in:
Philipp Hancke 2023-09-14 16:23:31 +02:00 committed by WebRTC LUCI CQ
parent e0083d4804
commit b64615a194
2 changed files with 80 additions and 0 deletions

View File

@ -120,6 +120,12 @@ const char kDefaultStreamId[] = "default";
static const char kDefaultAudioSenderId[] = "defaulta0";
static const char kDefaultVideoSenderId[] = "defaultv0";
// NOTE: Duplicated from pc/used_ids.h
static const int kLastDynamicPayloadTypeLowerRange = 63;
static const int kFirstDynamicPayloadTypeUpperRange = 96;
static const int kLastDynamicPayloadTypeUpperRange = 127;
void NoteAddIceCandidateResult(int result) {
RTC_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.AddIceCandidate", result,
kAddIceCandidateMax);
@ -562,6 +568,53 @@ RTCError ValidateSsrcGroups(const cricket::SessionDescription& description) {
return RTCError::OK();
}
RTCError ValidatePayloadTypes(const cricket::SessionDescription& description) {
for (const ContentInfo& content : description.contents()) {
if (content.type != MediaProtocolType::kRtp) {
continue;
}
const auto media_description = content.media_description();
RTC_DCHECK(media_description);
if (content.rejected || !media_description ||
!media_description->has_codecs()) {
continue;
}
const auto type = media_description->type();
if (type == cricket::MEDIA_TYPE_AUDIO) {
RTC_DCHECK(media_description->as_audio());
for (const auto& codec : media_description->as_audio()->codecs()) {
if (codec.id < 0 || codec.id > kLastDynamicPayloadTypeUpperRange ||
(media_description->rtcp_mux() &&
(codec.id > kLastDynamicPayloadTypeLowerRange &&
codec.id < kFirstDynamicPayloadTypeUpperRange))) {
LOG_AND_RETURN_ERROR(
RTCErrorType::INVALID_PARAMETER,
"The media section with MID='" + content.mid() +
"' used an invalid payload type " + rtc::ToString(codec.id) +
" for codec '" + codec.name + ", rtcp-mux:" +
(media_description->rtcp_mux() ? "enabled" : "disabled"));
}
}
} else if (type == cricket::MEDIA_TYPE_VIDEO) {
RTC_DCHECK(media_description->as_video());
for (const auto& codec : media_description->as_video()->codecs()) {
if (codec.id < 0 || codec.id > kLastDynamicPayloadTypeUpperRange ||
(media_description->rtcp_mux() &&
(codec.id > kLastDynamicPayloadTypeLowerRange &&
codec.id < kFirstDynamicPayloadTypeUpperRange))) {
LOG_AND_RETURN_ERROR(
RTCErrorType::INVALID_PARAMETER,
"The media section with MID='" + content.mid() +
"' used an invalid payload type " + rtc::ToString(codec.id) +
" for codec '" + codec.name + ", rtcp-mux:" +
(media_description->rtcp_mux() ? "enabled" : "disabled"));
}
}
}
}
return RTCError::OK();
}
bool IsValidOfferToReceiveMedia(int value) {
typedef PeerConnectionInterface::RTCOfferAnswerOptions Options;
return (value >= Options::kUndefined) &&
@ -3587,6 +3640,11 @@ RTCError SdpOfferAnswerHandler::ValidateSessionDescription(
kBundleWithoutRtcpMux);
}
error = ValidatePayloadTypes(*sdesc->description());
if (!error.ok()) {
return error;
}
// TODO(skvlad): When the local rtcp-mux policy is Require, reject any
// m-lines that do not rtcp-mux enabled.

View File

@ -993,4 +993,26 @@ TEST_F(SdpOfferAnswerTest, RejectsAnswerWithInvalidTransport) {
EXPECT_EQ(error.type(), RTCErrorType::INVALID_PARAMETER);
}
TEST_F(SdpOfferAnswerTest, SdpMungingWithInvalidPayloadTypeIsRejected) {
auto pc = CreatePeerConnection();
pc->AddAudioTrack("audio_track", {});
auto offer = pc->CreateOffer();
ASSERT_EQ(offer->description()->contents().size(), 1u);
auto* audio =
offer->description()->contents()[0].media_description()->as_audio();
ASSERT_GT(audio->codecs().size(), 0u);
EXPECT_TRUE(audio->rtcp_mux());
auto codecs = audio->codecs();
for (int invalid_payload_type = 64; invalid_payload_type < 96;
invalid_payload_type++) {
codecs[0].id =
invalid_payload_type; // The range [64-95] is disallowed with rtcp_mux.
audio->set_codecs(codecs);
// ASSERT to avoid getting into a bad state.
ASSERT_FALSE(pc->SetLocalDescription(offer->Clone()));
ASSERT_FALSE(pc->SetRemoteDescription(offer->Clone()));
}
}
} // namespace webrtc