mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 12:11:13 +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;
|
gchar *passwd;
|
||||||
GHashTable *auth_params;
|
GHashTable *auth_params;
|
||||||
|
|
||||||
|
guint content_length_limit;
|
||||||
|
|
||||||
/* TLS */
|
/* TLS */
|
||||||
GTlsDatabase *tls_database;
|
GTlsDatabase *tls_database;
|
||||||
GTlsInteraction *tls_interaction;
|
GTlsInteraction *tls_interaction;
|
||||||
|
@ -240,7 +242,7 @@ typedef struct
|
||||||
|
|
||||||
guint line;
|
guint line;
|
||||||
guint8 *body_data;
|
guint8 *body_data;
|
||||||
glong body_len;
|
guint body_len;
|
||||||
} GstRTSPBuilder;
|
} GstRTSPBuilder;
|
||||||
|
|
||||||
/* function prototypes */
|
/* function prototypes */
|
||||||
|
@ -370,6 +372,8 @@ gst_rtsp_connection_create (const GstRTSPUrl * url, GstRTSPConnection ** conn)
|
||||||
newconn->auth_params = NULL;
|
newconn->auth_params = NULL;
|
||||||
newconn->version = 0;
|
newconn->version = 0;
|
||||||
|
|
||||||
|
newconn->content_length_limit = G_MAXUINT;
|
||||||
|
|
||||||
*conn = newconn;
|
*conn = newconn;
|
||||||
|
|
||||||
return GST_RTSP_OK;
|
return GST_RTSP_OK;
|
||||||
|
@ -2417,6 +2421,7 @@ build_next (GstRTSPBuilder * builder, GstRTSPMessage * message,
|
||||||
/* we have a regular response */
|
/* we have a regular response */
|
||||||
if (builder->buffer[0] == '\0') {
|
if (builder->buffer[0] == '\0') {
|
||||||
gchar *hdrval;
|
gchar *hdrval;
|
||||||
|
gint64 content_length_parsed = 0;
|
||||||
|
|
||||||
/* empty line, end of message header */
|
/* empty line, end of message header */
|
||||||
/* see if there is a Content-Length header, but ignore it if this
|
/* 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_message_get_header (message,
|
||||||
GST_RTSP_HDR_X_SESSIONCOOKIE, NULL, 0) != GST_RTSP_OK)) {
|
GST_RTSP_HDR_X_SESSIONCOOKIE, NULL, 0) != GST_RTSP_OK)) {
|
||||||
/* there is, prepare to read the body */
|
/* 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);
|
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 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
|
* we need to read next and when allocation fails, we can't read the payload. */
|
||||||
* probably wrong with the length. */
|
if (builder->body_data == NULL) {
|
||||||
if (builder->body_data == NULL)
|
res = GST_RTSP_ENOMEM;
|
||||||
goto invalid_body_len;
|
goto invalid_body_len;
|
||||||
|
}
|
||||||
|
|
||||||
builder->body_data[builder->body_len] = '\0';
|
builder->body_data[builder->body_len] = '\0';
|
||||||
builder->offset = 0;
|
builder->offset = 0;
|
||||||
|
@ -2549,7 +2564,7 @@ invalid_body_len:
|
||||||
{
|
{
|
||||||
conn->may_cancel = TRUE;
|
conn->may_cancel = TRUE;
|
||||||
GST_DEBUG ("could not allocate body");
|
GST_DEBUG ("could not allocate body");
|
||||||
return GST_RTSP_ERROR;
|
return res;
|
||||||
}
|
}
|
||||||
invalid_format:
|
invalid_format:
|
||||||
{
|
{
|
||||||
|
@ -3237,6 +3252,25 @@ gst_rtsp_connection_set_qos_dscp (GstRTSPConnection * conn, guint qos_dscp)
|
||||||
return res;
|
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:
|
* gst_rtsp_connection_get_url:
|
||||||
|
|
|
@ -189,6 +189,11 @@ GST_RTSP_API
|
||||||
GstRTSPResult gst_rtsp_connection_set_qos_dscp (GstRTSPConnection *conn,
|
GstRTSPResult gst_rtsp_connection_set_qos_dscp (GstRTSPConnection *conn,
|
||||||
guint qos_dscp);
|
guint qos_dscp);
|
||||||
|
|
||||||
|
/* Content-Length limit */
|
||||||
|
GST_RTSP_API
|
||||||
|
void gst_rtsp_connection_set_content_length_limit (GstRTSPConnection *conn,
|
||||||
|
guint limit);
|
||||||
|
|
||||||
/* accessors */
|
/* accessors */
|
||||||
|
|
||||||
GST_RTSP_API
|
GST_RTSP_API
|
||||||
|
|
|
@ -859,6 +859,75 @@ GST_START_TEST (test_rtspconnection_ip)
|
||||||
|
|
||||||
GST_END_TEST;
|
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 *
|
static Suite *
|
||||||
rtspconnection_suite (void)
|
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_poll);
|
||||||
tcase_add_test (tc_chain, test_rtspconnection_backlog);
|
tcase_add_test (tc_chain, test_rtspconnection_backlog);
|
||||||
tcase_add_test (tc_chain, test_rtspconnection_ip);
|
tcase_add_test (tc_chain, test_rtspconnection_ip);
|
||||||
|
tcase_add_test (tc_chain, test_rtspconnection_send_receive_content_length);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue