mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 12:11:13 +00:00
rtspsrc: handle stale digest authentication session data
In particular, handle Unauthorized server response when trying to convey keep-alive. Fixes #635532.
This commit is contained in:
parent
e7b1655069
commit
b6b0de0c49
1 changed files with 28 additions and 5 deletions
|
@ -230,6 +230,9 @@ static GstStateChangeReturn gst_rtspsrc_change_state (GstElement * element,
|
||||||
static gboolean gst_rtspsrc_send_event (GstElement * element, GstEvent * event);
|
static gboolean gst_rtspsrc_send_event (GstElement * element, GstEvent * event);
|
||||||
static void gst_rtspsrc_handle_message (GstBin * bin, GstMessage * message);
|
static void gst_rtspsrc_handle_message (GstBin * bin, GstMessage * message);
|
||||||
|
|
||||||
|
static gboolean gst_rtspsrc_setup_auth (GstRTSPSrc * src,
|
||||||
|
GstRTSPMessage * response);
|
||||||
|
|
||||||
static void gst_rtspsrc_loop_send_cmd (GstRTSPSrc * src, gint cmd,
|
static void gst_rtspsrc_loop_send_cmd (GstRTSPSrc * src, gint cmd,
|
||||||
gboolean flush);
|
gboolean flush);
|
||||||
static GstRTSPResult gst_rtspsrc_send_cb (GstRTSPExtension * ext,
|
static GstRTSPResult gst_rtspsrc_send_cb (GstRTSPExtension * ext,
|
||||||
|
@ -3651,6 +3654,7 @@ gst_rtspsrc_loop_udp (GstRTSPSrc * src)
|
||||||
gboolean restart = FALSE;
|
gboolean restart = FALSE;
|
||||||
GstRTSPResult res;
|
GstRTSPResult res;
|
||||||
GstRTSPMessage message = { 0 };
|
GstRTSPMessage message = { 0 };
|
||||||
|
gint retry = 0;
|
||||||
|
|
||||||
GST_OBJECT_LOCK (src);
|
GST_OBJECT_LOCK (src);
|
||||||
if (src->loop_cmd == CMD_STOP)
|
if (src->loop_cmd == CMD_STOP)
|
||||||
|
@ -3668,6 +3672,7 @@ gst_rtspsrc_loop_udp (GstRTSPSrc * src)
|
||||||
GST_DEBUG_OBJECT (src, "doing receive with timeout %d seconds",
|
GST_DEBUG_OBJECT (src, "doing receive with timeout %d seconds",
|
||||||
(gint) tv_timeout.tv_sec);
|
(gint) tv_timeout.tv_sec);
|
||||||
|
|
||||||
|
gst_rtsp_message_unset (&message);
|
||||||
/* we should continue reading the TCP socket because the server might
|
/* we should continue reading the TCP socket because the server might
|
||||||
* send us requests. When the session timeout expires, we need to send a
|
* send us requests. When the session timeout expires, we need to send a
|
||||||
* keep-alive request to keep the session open. */
|
* keep-alive request to keep the session open. */
|
||||||
|
@ -3719,6 +3724,15 @@ gst_rtspsrc_loop_udp (GstRTSPSrc * src)
|
||||||
GST_DEBUG_OBJECT (src, "ignoring response message");
|
GST_DEBUG_OBJECT (src, "ignoring response message");
|
||||||
if (src->debug)
|
if (src->debug)
|
||||||
gst_rtsp_message_dump (&message);
|
gst_rtsp_message_dump (&message);
|
||||||
|
if (message.type_data.response.code == GST_RTSP_STS_UNAUTHORIZED) {
|
||||||
|
GST_DEBUG_OBJECT (src, "but is Unauthorized response ...");
|
||||||
|
if (gst_rtspsrc_setup_auth (src, &message) && !(retry++)) {
|
||||||
|
GST_DEBUG_OBJECT (src, "so retrying keep-alive");
|
||||||
|
gst_rtspsrc_send_keep_alive (src);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
retry = 0;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case GST_RTSP_MESSAGE_DATA:
|
case GST_RTSP_MESSAGE_DATA:
|
||||||
/* we ignore response and data messages */
|
/* we ignore response and data messages */
|
||||||
|
@ -4013,13 +4027,16 @@ gst_rtsp_decode_quoted_string (gchar * quoted_string)
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
gst_rtspsrc_parse_digest_challenge (GstRTSPConnection * conn,
|
gst_rtspsrc_parse_digest_challenge (GstRTSPConnection * conn,
|
||||||
const gchar * header)
|
const gchar * header, gboolean * stale)
|
||||||
{
|
{
|
||||||
GSList *list = NULL, *iter;
|
GSList *list = NULL, *iter;
|
||||||
const gchar *end;
|
const gchar *end;
|
||||||
gchar *item, *eq, *name_end, *value;
|
gchar *item, *eq, *name_end, *value;
|
||||||
|
|
||||||
|
g_return_if_fail (stale != NULL);
|
||||||
|
|
||||||
gst_rtsp_connection_clear_auth_params (conn);
|
gst_rtsp_connection_clear_auth_params (conn);
|
||||||
|
*stale = FALSE;
|
||||||
|
|
||||||
/* Parse a header whose content is described by RFC2616 as
|
/* Parse a header whose content is described by RFC2616 as
|
||||||
* "#something", where "something" does not itself contain commas,
|
* "#something", where "something" does not itself contain commas,
|
||||||
|
@ -4055,6 +4072,8 @@ gst_rtspsrc_parse_digest_challenge (GstRTSPConnection * conn,
|
||||||
} else
|
} else
|
||||||
value = NULL;
|
value = NULL;
|
||||||
|
|
||||||
|
if ((strcmp (item, "stale") == 0) && (strcmp (value, "TRUE") == 0))
|
||||||
|
*stale = TRUE;
|
||||||
gst_rtsp_connection_set_auth_param (conn, item, value);
|
gst_rtsp_connection_set_auth_param (conn, item, value);
|
||||||
g_free (item);
|
g_free (item);
|
||||||
}
|
}
|
||||||
|
@ -4072,12 +4091,13 @@ gst_rtspsrc_parse_digest_challenge (GstRTSPConnection * conn,
|
||||||
* even parse out the realm */
|
* even parse out the realm */
|
||||||
static void
|
static void
|
||||||
gst_rtspsrc_parse_auth_hdr (gchar * hdr, GstRTSPAuthMethod * methods,
|
gst_rtspsrc_parse_auth_hdr (gchar * hdr, GstRTSPAuthMethod * methods,
|
||||||
GstRTSPConnection * conn)
|
GstRTSPConnection * conn, gboolean * stale)
|
||||||
{
|
{
|
||||||
gchar *start;
|
gchar *start;
|
||||||
|
|
||||||
g_return_if_fail (hdr != NULL);
|
g_return_if_fail (hdr != NULL);
|
||||||
g_return_if_fail (methods != NULL);
|
g_return_if_fail (methods != NULL);
|
||||||
|
g_return_if_fail (stale != NULL);
|
||||||
|
|
||||||
/* Skip whitespace at the start of the string */
|
/* Skip whitespace at the start of the string */
|
||||||
for (start = hdr; start[0] != '\0' && g_ascii_isspace (start[0]); start++);
|
for (start = hdr; start[0] != '\0' && g_ascii_isspace (start[0]); start++);
|
||||||
|
@ -4086,7 +4106,7 @@ gst_rtspsrc_parse_auth_hdr (gchar * hdr, GstRTSPAuthMethod * methods,
|
||||||
*methods |= GST_RTSP_AUTH_BASIC;
|
*methods |= GST_RTSP_AUTH_BASIC;
|
||||||
else if (g_ascii_strncasecmp (start, "digest ", 7) == 0) {
|
else if (g_ascii_strncasecmp (start, "digest ", 7) == 0) {
|
||||||
*methods |= GST_RTSP_AUTH_DIGEST;
|
*methods |= GST_RTSP_AUTH_DIGEST;
|
||||||
gst_rtspsrc_parse_digest_challenge (conn, &start[7]);
|
gst_rtspsrc_parse_digest_challenge (conn, &start[7], stale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4115,21 +4135,24 @@ gst_rtspsrc_setup_auth (GstRTSPSrc * src, GstRTSPMessage * response)
|
||||||
GstRTSPUrl *url;
|
GstRTSPUrl *url;
|
||||||
GstRTSPConnection *conn;
|
GstRTSPConnection *conn;
|
||||||
gchar *hdr;
|
gchar *hdr;
|
||||||
|
gboolean stale = FALSE;
|
||||||
|
|
||||||
conn = src->conninfo.connection;
|
conn = src->conninfo.connection;
|
||||||
|
|
||||||
/* Identify the available auth methods and see if any are supported */
|
/* Identify the available auth methods and see if any are supported */
|
||||||
if (gst_rtsp_message_get_header (response, GST_RTSP_HDR_WWW_AUTHENTICATE,
|
if (gst_rtsp_message_get_header (response, GST_RTSP_HDR_WWW_AUTHENTICATE,
|
||||||
&hdr, 0) == GST_RTSP_OK) {
|
&hdr, 0) == GST_RTSP_OK) {
|
||||||
gst_rtspsrc_parse_auth_hdr (hdr, &avail_methods, conn);
|
gst_rtspsrc_parse_auth_hdr (hdr, &avail_methods, conn, &stale);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (avail_methods == GST_RTSP_AUTH_NONE)
|
if (avail_methods == GST_RTSP_AUTH_NONE)
|
||||||
goto no_auth_available;
|
goto no_auth_available;
|
||||||
|
|
||||||
/* FIXME: For digest auth, if the response indicates that the session
|
/* For digest auth, if the response indicates that the session
|
||||||
* data are stale, we just update them in the connection object and
|
* data are stale, we just update them in the connection object and
|
||||||
* return TRUE to retry the request */
|
* return TRUE to retry the request */
|
||||||
|
if (stale)
|
||||||
|
src->tried_url_auth = FALSE;
|
||||||
|
|
||||||
url = gst_rtsp_connection_get_url (conn);
|
url = gst_rtsp_connection_get_url (conn);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue