Bug 1204099: RTP payload type validation. draft
authorPaul Ellenbogen <pe5@cs.princeton.edu>
Tue, 19 Jul 2016 13:56:29 -0700
changeset 390745 1663b5cf0c2005526eab34f465b9efe70a09fd52
parent 389773 1ebb6348564337c00d889bd858eedf3c922e68c0
child 526062 b2a6e111f60664c025f60de5030669d1d3e8b2a4
push id23739
push userpe5@cs.princeton.edu
push dateThu, 21 Jul 2016 17:27:12 +0000
bugs1204099
milestone50.0a1
Bug 1204099: RTP payload type validation. MozReview-Commit-ID: LYNcxKqKwiC
media/webrtc/signaling/src/jsep/JsepSessionImpl.cpp
media/webrtc/signaling/test/jsep_session_unittest.cpp
--- a/media/webrtc/signaling/src/jsep/JsepSessionImpl.cpp
+++ b/media/webrtc/signaling/src/jsep/JsepSessionImpl.cpp
@@ -2,16 +2,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "logging.h"
 
 #include "signaling/src/jsep/JsepSessionImpl.h"
 #include <string>
 #include <set>
+#include <bitset>
 #include <stdlib.h>
 
 #include "nspr.h"
 #include "nss.h"
 #include "pk11pub.h"
 #include "nsDebug.h"
 
 #include <mozilla/Move.h>
@@ -32,16 +33,27 @@ MOZ_MTLOG_MODULE("jsep")
 #define JSEP_SET_ERROR(error)                                                  \
   do {                                                                         \
     std::ostringstream os;                                                     \
     os << error;                                                               \
     mLastError = os.str();                                                     \
     MOZ_MTLOG(ML_ERROR, mLastError);                                           \
   } while (0);
 
+static std::bitset<128> GetForbiddenSdpPayloadTypes() {
+  std::bitset<128> forbidden(0);
+  forbidden[1] = true;
+  forbidden[2] = true;
+  forbidden[19] = true;
+  for (uint16_t i = 64; i < 96; ++i) {
+    forbidden[i] = true;
+  }
+  return forbidden;
+}
+
 nsresult
 JsepSessionImpl::Init()
 {
   mLastError.clear();
 
   MOZ_ASSERT(!mSessionId, "Init called more than once");
 
   nsresult rv = SetupIds();
@@ -1653,26 +1665,31 @@ JsepSessionImpl::ParseSdp(const std::str
       }
 
       trackIds.insert(trackId);
     } else if (rv != NS_ERROR_NOT_AVAILABLE) {
       // Error has already been set
       return rv;
     }
 
+    static const std::bitset<128> forbidden = GetForbiddenSdpPayloadTypes();
     if (msection.GetMediaType() == SdpMediaSection::kAudio ||
         msection.GetMediaType() == SdpMediaSection::kVideo) {
       // Sanity-check that payload type can work with RTP
       for (const std::string& fmt : msection.GetFormats()) {
         uint16_t payloadType;
         // TODO (bug 1204099): Make this check for reserved ranges.
         if (!SdpHelper::GetPtAsInt(fmt, &payloadType) || payloadType > 127) {
           JSEP_SET_ERROR("audio/video payload type is too large: " << fmt);
           return NS_ERROR_INVALID_ARG;
         }
+	if (forbidden.test(payloadType)) {
+	  JSEP_SET_ERROR("Illegal audio/video payload type: " << fmt);
+          return NS_ERROR_INVALID_ARG;
+	}
       }
     }
   }
 
   *parsedp = Move(parsed);
   return NS_OK;
 }
 
--- a/media/webrtc/signaling/test/jsep_session_unittest.cpp
+++ b/media/webrtc/signaling/test/jsep_session_unittest.cpp
@@ -2115,16 +2115,31 @@ TEST_P(JsepSessionTest, RenegotiationAns
   }
 
   ASSERT_NE(newOffererPairs[0].mRtpTransport.get(),
             offererPairs[0].mRtpTransport.get());
   ASSERT_NE(newAnswererPairs[0].mRtpTransport.get(),
             answererPairs[0].mRtpTransport.get());
 }
 
+TEST_P(JsepSessionTest, ParseRejectsBadMediaFormat)
+{
+  if (GetParam() == "datachannel") {
+    return;
+  }
+  AddTracks(mSessionOff);
+  std::string offer = CreateOffer();
+  UniquePtr<Sdp> munge(Parse(offer));
+  SdpMediaSection& mediaSection = munge->GetMediaSection(0);
+  mediaSection.AddCodec("75", "DummyFormatVal", 8000, 1);
+  std::string sdpString = munge->ToString();
+  nsresult rv = mSessionOff.SetLocalDescription(kJsepSdpOffer, sdpString);
+  ASSERT_EQ(NS_ERROR_INVALID_ARG, rv);
+}
+
 TEST_P(JsepSessionTest, FullCallWithCandidates)
 {
   AddTracks(mSessionOff);
   std::string offer = CreateOffer();
   SetLocalOffer(offer);
   mOffCandidates.Gather(mSessionOff, types);
 
   UniquePtr<Sdp> localOffer(Parse(mSessionOff.GetLocalDescription()));