mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 10:11:08 +00:00
rtspconnection: add Content-Length limit
Add the possible to limit the Content-Length Define an appropriate request size limit and reject requests exceeding the limit (413 Request Entity Too Large)
This commit is contained in:
parent
c70c6c085e
commit
1dea6d52ce
3 changed files with 115 additions and 6 deletions
|
@ -198,6 +198,8 @@ struct _GstRTSPConnection
|
|||
gchar *passwd;
|
||||
GHashTable *auth_params;
|
||||
|
||||
guint content_length_limit;
|
||||
|
||||
/* TLS */
|
||||
GTlsDatabase *tls_database;
|
||||
GTlsInteraction *tls_interaction;
|
||||
|
@ -240,7 +242,7 @@ typedef struct
|
|||
|
||||
guint line;
|
||||
guint8 *body_data;
|
||||
glong body_len;
|
||||
guint body_len;
|
||||
} GstRTSPBuilder;
|
||||
|
||||
/* function prototypes */
|
||||
|
@ -370,6 +372,8 @@ gst_rtsp_connection_create (const GstRTSPUrl * url, GstRTSPConnection ** conn)
|
|||
newconn->auth_params = NULL;
|
||||
newconn->version = 0;
|
||||
|
||||
newconn->content_length_limit = G_MAXUINT;
|
||||
|
||||
*conn = newconn;
|
||||
|
||||
return GST_RTSP_OK;
|
||||
|
@ -2417,6 +2421,7 @@ build_next (GstRTSPBuilder * builder, GstRTSPMessage * message,
|
|||
/* we have a regular response */
|
||||
if (builder->buffer[0] == '\0') {
|
||||
gchar *hdrval;
|
||||
gint64 content_length_parsed = 0;
|
||||
|
||||
/* empty line, end of message header */
|
||||
/* see if there is a Content-Length header, but ignore it if this
|
||||
|
@ -2428,13 +2433,23 @@ build_next (GstRTSPBuilder * builder, GstRTSPMessage * message,
|
|||
gst_rtsp_message_get_header (message,
|
||||
GST_RTSP_HDR_X_SESSIONCOOKIE, NULL, 0) != GST_RTSP_OK)) {
|
||||
/* there is, prepare to read the body */
|
||||
builder->body_len = atol (hdrval);
|
||||
errno = 0;
|
||||
content_length_parsed = g_ascii_strtoll (hdrval, NULL, 10);
|
||||
if (errno != 0 || content_length_parsed < 0) {
|
||||
res = GST_RTSP_EPARSE;
|
||||
goto invalid_body_len;
|
||||
} else if (content_length_parsed > conn->content_length_limit) {
|
||||
res = GST_RTSP_ENOMEM;
|
||||
goto invalid_body_len;
|
||||
}
|
||||
builder->body_len = content_length_parsed;
|
||||
builder->body_data = g_try_malloc (builder->body_len + 1);
|
||||
/* we can't do much here, we need the length to know how many bytes
|
||||
* we need to read next and when allocation fails, something is
|
||||
* probably wrong with the length. */
|
||||
if (builder->body_data == NULL)
|
||||
* we need to read next and when allocation fails, we can't read the payload. */
|
||||
if (builder->body_data == NULL) {
|
||||
res = GST_RTSP_ENOMEM;
|
||||
goto invalid_body_len;
|
||||
}
|
||||
|
||||
builder->body_data[builder->body_len] = '\0';
|
||||
builder->offset = 0;
|
||||
|
@ -2549,7 +2564,7 @@ invalid_body_len:
|
|||
{
|
||||
conn->may_cancel = TRUE;
|
||||
GST_DEBUG ("could not allocate body");
|
||||
return GST_RTSP_ERROR;
|
||||
return res;
|
||||
}
|
||||
invalid_format:
|
||||
{
|
||||
|
@ -3237,6 +3252,25 @@ gst_rtsp_connection_set_qos_dscp (GstRTSPConnection * conn, guint qos_dscp)
|
|||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_rtsp_connection_set_content_length_limit:
|
||||
* @conn: a #GstRTSPConnection
|
||||
* @limit: Content-Length limit
|
||||
*
|
||||
* Configure @conn to use the specified Content-Length limit.
|
||||
* Both requests and responses are validated. If content-length is
|
||||
* exceeded, ENOMEM error will be returned.
|
||||
*
|
||||
* Since: 1.18
|
||||
*/
|
||||
void
|
||||
gst_rtsp_connection_set_content_length_limit (GstRTSPConnection * conn,
|
||||
guint limit)
|
||||
{
|
||||
g_return_if_fail (conn != NULL);
|
||||
|
||||
conn->content_length_limit = limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_rtsp_connection_get_url:
|
||||
|
|
|
@ -189,6 +189,11 @@ GST_RTSP_API
|
|||
GstRTSPResult gst_rtsp_connection_set_qos_dscp (GstRTSPConnection *conn,
|
||||
guint qos_dscp);
|
||||
|
||||
/* Content-Length limit */
|
||||
GST_RTSP_API
|
||||
void gst_rtsp_connection_set_content_length_limit (GstRTSPConnection *conn,
|
||||
guint limit);
|
||||
|
||||
/* accessors */
|
||||
|
||||
GST_RTSP_API
|
||||
|
|
|
@ -859,6 +859,75 @@ GST_START_TEST (test_rtspconnection_ip)
|
|||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_rtspconnection_send_receive_content_length)
|
||||
{
|
||||
GSocketConnection *input_conn = NULL;
|
||||
GSocketConnection *output_conn = NULL;
|
||||
GSocket *input_sock;
|
||||
GSocket *output_sock;
|
||||
GstRTSPConnection *rtsp_output_conn;
|
||||
GstRTSPConnection *rtsp_input_conn;
|
||||
GstRTSPMessage *msg;
|
||||
|
||||
create_connection (&input_conn, &output_conn);
|
||||
input_sock = g_socket_connection_get_socket (input_conn);
|
||||
fail_unless (input_sock != NULL);
|
||||
output_sock = g_socket_connection_get_socket (output_conn);
|
||||
fail_unless (output_sock != NULL);
|
||||
|
||||
fail_unless (gst_rtsp_connection_create_from_socket (input_sock, "127.0.0.1",
|
||||
4444, NULL, &rtsp_input_conn) == GST_RTSP_OK);
|
||||
fail_unless (rtsp_input_conn != NULL);
|
||||
|
||||
fail_unless (gst_rtsp_connection_create_from_socket (output_sock, "127.0.0.1",
|
||||
4444, NULL, &rtsp_output_conn) == GST_RTSP_OK);
|
||||
fail_unless (rtsp_output_conn != NULL);
|
||||
|
||||
/* send request message with to big payload */
|
||||
fail_unless (gst_rtsp_message_new_request (&msg, GST_RTSP_SETUP,
|
||||
"rtsp://example.com/") == GST_RTSP_OK);
|
||||
fail_unless (gst_rtsp_message_add_header (msg, GST_RTSP_HDR_CONTENT_LENGTH,
|
||||
"2000") == GST_RTSP_OK);
|
||||
fail_unless (gst_rtsp_connection_send (rtsp_output_conn, msg,
|
||||
NULL) == GST_RTSP_OK);
|
||||
fail_unless (gst_rtsp_message_free (msg) == GST_RTSP_OK);
|
||||
msg = NULL;
|
||||
|
||||
/* receive request message, expect ENOMEM */
|
||||
gst_rtsp_connection_set_content_length_limit (rtsp_input_conn, 1000);
|
||||
fail_unless (gst_rtsp_message_new (&msg) == GST_RTSP_OK);
|
||||
fail_unless (gst_rtsp_connection_receive (rtsp_input_conn, msg, NULL) ==
|
||||
GST_RTSP_ENOMEM);
|
||||
fail_unless (gst_rtsp_message_free (msg) == GST_RTSP_OK);
|
||||
msg = NULL;
|
||||
|
||||
/* send request message with negative payload */
|
||||
fail_unless (gst_rtsp_message_new_request (&msg, GST_RTSP_SETUP,
|
||||
"rtsp://example.com/") == GST_RTSP_OK);
|
||||
fail_unless (gst_rtsp_message_add_header (msg, GST_RTSP_HDR_CONTENT_LENGTH,
|
||||
"-2000") == GST_RTSP_OK);
|
||||
fail_unless (gst_rtsp_connection_send (rtsp_output_conn, msg,
|
||||
NULL) == GST_RTSP_OK);
|
||||
fail_unless (gst_rtsp_message_free (msg) == GST_RTSP_OK);
|
||||
msg = NULL;
|
||||
|
||||
/* receive request message, expect EPARSE */
|
||||
fail_unless (gst_rtsp_message_new (&msg) == GST_RTSP_OK);
|
||||
fail_unless (gst_rtsp_connection_receive (rtsp_input_conn, msg, NULL) ==
|
||||
GST_RTSP_EPARSE);
|
||||
fail_unless (gst_rtsp_message_free (msg) == GST_RTSP_OK);
|
||||
msg = NULL;
|
||||
|
||||
fail_unless (gst_rtsp_connection_close (rtsp_input_conn) == GST_RTSP_OK);
|
||||
fail_unless (gst_rtsp_connection_free (rtsp_input_conn) == GST_RTSP_OK);
|
||||
fail_unless (gst_rtsp_connection_close (rtsp_output_conn) == GST_RTSP_OK);
|
||||
fail_unless (gst_rtsp_connection_free (rtsp_output_conn) == GST_RTSP_OK);
|
||||
|
||||
g_object_unref (input_conn);
|
||||
g_object_unref (output_conn);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static Suite *
|
||||
rtspconnection_suite (void)
|
||||
|
@ -875,6 +944,7 @@ rtspconnection_suite (void)
|
|||
tcase_add_test (tc_chain, test_rtspconnection_poll);
|
||||
tcase_add_test (tc_chain, test_rtspconnection_backlog);
|
||||
tcase_add_test (tc_chain, test_rtspconnection_ip);
|
||||
tcase_add_test (tc_chain, test_rtspconnection_send_receive_content_length);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue