webrtc: sdp: Validate ICE SDP attributes
According to https://datatracker.ietf.org/doc/html/rfc5245#section-15.4, those attributes should contain only alpha-numerical (with / and + allowed), should be less than 256 characters, the ufrag should be at least 4 characters and the pwd should be at least 22 characters. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/9485>
This commit is contained in:
parent
80e663d560
commit
ea69849cd8
@ -214,6 +214,25 @@ _media_get_ice_ufrag (const GstSDPMessage * msg, guint media_idx)
|
||||
return ice_ufrag;
|
||||
}
|
||||
|
||||
/* https://datatracker.ietf.org/doc/html/rfc5245#section-15.4 */
|
||||
static gboolean
|
||||
_validate_ice_attr (const gchar * attr, guint min_length)
|
||||
{
|
||||
guint len = strlen (attr);
|
||||
|
||||
if (len < min_length)
|
||||
return FALSE;
|
||||
|
||||
if (len > 256)
|
||||
return FALSE;
|
||||
|
||||
for (guint i = 0; i < len; i++) {
|
||||
if (!g_ascii_isalnum (attr[i]) && attr[i] != '+' && attr[i] != '/')
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
const gchar *
|
||||
_media_get_ice_pwd (const GstSDPMessage * msg, guint media_idx)
|
||||
{
|
||||
@ -302,6 +321,8 @@ validate_sdp (GstWebRTCSignalingState state, SDPSource source,
|
||||
const GstSDPMedia *media = gst_sdp_message_get_media (sdp->sdp, i);
|
||||
const gchar *mid;
|
||||
gboolean media_in_bundle = FALSE;
|
||||
const gchar *ice_ufrag;
|
||||
const gchar *ice_pwd;
|
||||
|
||||
if (_media_has_mid (media, i)) {
|
||||
mid = gst_sdp_media_get_attribute_val (media, "mid");
|
||||
@ -309,17 +330,30 @@ validate_sdp (GstWebRTCSignalingState state, SDPSource source,
|
||||
is_bundle && g_strv_contains ((const gchar **) group_members, mid);
|
||||
}
|
||||
|
||||
if (!_media_get_ice_ufrag (sdp->sdp, i)) {
|
||||
ice_ufrag = _media_get_ice_ufrag (sdp->sdp, i);
|
||||
if (!ice_ufrag) {
|
||||
g_set_error (error, GST_WEBRTC_ERROR, GST_WEBRTC_ERROR_SDP_SYNTAX_ERROR,
|
||||
"media %u is missing or contains an empty \'ice-ufrag\' attribute",
|
||||
i);
|
||||
goto fail;
|
||||
}
|
||||
if (!_media_get_ice_pwd (sdp->sdp, i)) {
|
||||
if (!_validate_ice_attr (ice_ufrag, 4)) {
|
||||
g_set_error (error, GST_WEBRTC_ERROR, GST_WEBRTC_ERROR_SDP_SYNTAX_ERROR,
|
||||
"media %u has an invalid \'ice-ufrag\' attribute", i);
|
||||
goto fail;
|
||||
}
|
||||
ice_pwd = _media_get_ice_pwd (sdp->sdp, i);
|
||||
if (!ice_pwd) {
|
||||
g_set_error (error, GST_WEBRTC_ERROR, GST_WEBRTC_ERROR_SDP_SYNTAX_ERROR,
|
||||
"media %u is missing or contains an empty \'ice-pwd\' attribute", i);
|
||||
goto fail;
|
||||
}
|
||||
if (!_validate_ice_attr (ice_pwd, 22)) {
|
||||
g_set_error (error, GST_WEBRTC_ERROR, GST_WEBRTC_ERROR_SDP_SYNTAX_ERROR,
|
||||
"media %u has an invalid \'ice-pwd\' attribute", i);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!has_session_setup && !_media_has_setup (media, i, error))
|
||||
goto fail;
|
||||
/* Validate ICE ufrag and pwd attributes. According to RFC 8839 section 5.4:
|
||||
|
@ -6921,6 +6921,91 @@ a=rtcp-rsize\r\n";
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static void
|
||||
validate_ice_attr (struct test_webrtc *t, GstElement * element,
|
||||
const gchar * sdp_str, const gchar * expected_error_message)
|
||||
{
|
||||
GstPromise *promise;
|
||||
GstSDPMessage *sdp;
|
||||
const GstStructure *reply;
|
||||
GstWebRTCSessionDescription *desc;
|
||||
GError *error = NULL;
|
||||
|
||||
gst_sdp_message_new_from_text (sdp_str, &sdp);
|
||||
desc = gst_webrtc_session_description_new (GST_WEBRTC_SDP_TYPE_OFFER, sdp);
|
||||
promise = gst_promise_new ();
|
||||
g_signal_emit_by_name (t->webrtc1, "set-remote-description", desc, promise);
|
||||
gst_promise_wait (promise);
|
||||
reply = gst_promise_get_reply (promise);
|
||||
if (expected_error_message) {
|
||||
fail_unless (gst_structure_get (reply, "error", G_TYPE_ERROR, &error,
|
||||
NULL));
|
||||
fail_unless (g_error_matches (error, GST_WEBRTC_ERROR,
|
||||
GST_WEBRTC_ERROR_SDP_SYNTAX_ERROR));
|
||||
fail_unless_equals_string (error->message, expected_error_message);
|
||||
g_clear_error (&error);
|
||||
} else {
|
||||
fail_if (reply != NULL);
|
||||
}
|
||||
gst_promise_unref (promise);
|
||||
gst_webrtc_session_description_free (desc);
|
||||
}
|
||||
|
||||
GST_START_TEST (test_invalid_ice_attrs)
|
||||
{
|
||||
struct test_webrtc *t = test_webrtc_new ();
|
||||
const gchar *sdp_preamble = "v=0\r\n\
|
||||
o=- 0 3 IN IP4 127.0.0.1\r\n\
|
||||
s=-\r\n\
|
||||
t=0 0\r\n\
|
||||
a=fingerprint:sha-256 A7:24:72:CA:6E:02:55:39:BA:66:DF:6E:CC:4C:D8:B0:1A:BF:1A:56:65:7D:F4:03:AD:7E:77:43:2A:29:EC:93\r\n\
|
||||
m=video 1 RTP/SAVPF 100\r\n\
|
||||
c=IN IP4 0.0.0.0\r\n\
|
||||
a=rtcp-mux\r\n\
|
||||
a=sendonly\r\n\
|
||||
a=mid:video\r\n\
|
||||
a=rtpmap:100 VP8\r\n\
|
||||
a=setup:actpass\r\n";
|
||||
const gchar *valid_ufrag = "a=ice-ufrag:ETEn\r\n";
|
||||
const gchar *valid_pwd = "a=ice-pwd:OtSK0WpNtpUjkY4+86js7Z/l\r\n";
|
||||
const gchar *invalid_ufrag = "a=ice-ufrag:ETEn$\r\n";
|
||||
const gchar *invalid_pwd = "a=ice-pwd:OtSK0WpNtpUjk$Y4+86js7Z/l\r\n";
|
||||
const gchar *too_short_ufrag = "a=ice-ufrag:foo\r\n";
|
||||
const gchar *too_short_pwd = "a=ice-pwd:thisistooshort\r\n";
|
||||
const gchar *invalid_ufrag_error_message =
|
||||
"media 0 has an invalid \'ice-ufrag\' attribute";
|
||||
const gchar *invalid_pwd_error_message =
|
||||
"media 0 has an invalid \'ice-pwd\' attribute";
|
||||
gchar *sdp_str;
|
||||
|
||||
t->on_negotiation_needed = NULL;
|
||||
t->on_offer_created = NULL;
|
||||
t->on_answer_created = NULL;
|
||||
gst_element_set_state (t->webrtc1, GST_STATE_READY);
|
||||
|
||||
sdp_str = g_strconcat (sdp_preamble, invalid_ufrag, valid_pwd, NULL);
|
||||
validate_ice_attr (t, t->webrtc1, sdp_str, invalid_ufrag_error_message);
|
||||
g_free (sdp_str);
|
||||
|
||||
sdp_str = g_strconcat (sdp_preamble, valid_ufrag, invalid_pwd, NULL);
|
||||
validate_ice_attr (t, t->webrtc1, sdp_str, invalid_pwd_error_message);
|
||||
g_free (sdp_str);
|
||||
|
||||
sdp_str = g_strconcat (sdp_preamble, too_short_ufrag, valid_pwd, NULL);
|
||||
validate_ice_attr (t, t->webrtc1, sdp_str, invalid_ufrag_error_message);
|
||||
g_free (sdp_str);
|
||||
|
||||
sdp_str = g_strconcat (sdp_preamble, valid_ufrag, too_short_pwd, NULL);
|
||||
validate_ice_attr (t, t->webrtc1, sdp_str, invalid_pwd_error_message);
|
||||
g_free (sdp_str);
|
||||
|
||||
sdp_str = g_strconcat (sdp_preamble, valid_ufrag, valid_pwd, NULL);
|
||||
validate_ice_attr (t, t->webrtc1, sdp_str, NULL);
|
||||
g_free (sdp_str);
|
||||
|
||||
test_webrtc_free (t);
|
||||
} GST_END_TEST;
|
||||
|
||||
static Suite *
|
||||
webrtcbin_suite (void)
|
||||
{
|
||||
@ -7027,6 +7112,7 @@ webrtcbin_suite (void)
|
||||
tcase_add_test (tc, test_offer_rollback);
|
||||
tcase_add_test (tc, test_video_rtx_no_duplicate_payloads);
|
||||
tcase_add_test (tc, test_bundle_with_different_ice_credentials);
|
||||
tcase_add_test (tc, test_invalid_ice_attrs);
|
||||
} else {
|
||||
GST_WARNING ("Some required elements were not found. "
|
||||
"All media tests are disabled. nicesrc %p, nicesink %p, "
|
||||
|
Loading…
x
Reference in New Issue
Block a user