From 058ab0df1d39595cba1dd5769ab6ff85a71951b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Fri, 18 Nov 2016 17:00:59 +0200 Subject: [PATCH] rtspsrc: Move to new helper function to parse authentication responses https://bugzilla.gnome.org/show_bug.cgi?id=774416 --- gst/rtsp/gstrtspsrc.c | 176 +++++++++--------------------------------- 1 file changed, 35 insertions(+), 141 deletions(-) diff --git a/gst/rtsp/gstrtspsrc.c b/gst/rtsp/gstrtspsrc.c index 2880ffc91f..e7df04ba74 100644 --- a/gst/rtsp/gstrtspsrc.c +++ b/gst/rtsp/gstrtspsrc.c @@ -5149,131 +5149,6 @@ gst_rtsp_auth_method_to_string (GstRTSPAuthMethod method) } #endif -static const gchar * -gst_rtspsrc_skip_lws (const gchar * s) -{ - while (g_ascii_isspace (*s)) - s++; - return s; -} - -static const gchar * -gst_rtspsrc_unskip_lws (const gchar * s, const gchar * start) -{ - while (s > start && g_ascii_isspace (*(s - 1))) - s--; - return s; -} - -static const gchar * -gst_rtspsrc_skip_commas (const gchar * s) -{ - /* The grammar allows for multiple commas */ - while (g_ascii_isspace (*s) || *s == ',') - s++; - return s; -} - -static const gchar * -gst_rtspsrc_skip_item (const gchar * s) -{ - gboolean quoted = FALSE; - const gchar *start = s; - - /* A list item ends at the last non-whitespace character - * before a comma which is not inside a quoted-string. Or at - * the end of the string. - */ - while (*s) { - if (*s == '"') - quoted = !quoted; - else if (quoted) { - if (*s == '\\' && *(s + 1)) - s++; - } else { - if (*s == ',') - break; - } - s++; - } - - return gst_rtspsrc_unskip_lws (s, start); -} - -static void -gst_rtsp_decode_quoted_string (gchar * quoted_string) -{ - gchar *src, *dst; - - src = quoted_string + 1; - dst = quoted_string; - while (*src && *src != '"') { - if (*src == '\\' && *(src + 1)) - src++; - *dst++ = *src++; - } - *dst = '\0'; -} - -/* Extract the authentication tokens that the server provided for each method - * into an array of structures and give those to the connection object. - */ -static void -gst_rtspsrc_parse_digest_challenge (GstRTSPConnection * conn, - const gchar * header, gboolean * stale) -{ - GSList *list = NULL, *iter; - const gchar *end; - gchar *item, *eq, *name_end, *value; - - g_return_if_fail (stale != NULL); - - gst_rtsp_connection_clear_auth_params (conn); - *stale = FALSE; - - /* Parse a header whose content is described by RFC2616 as - * "#something", where "something" does not itself contain commas, - * except as part of quoted-strings, into a list of allocated strings. - */ - header = gst_rtspsrc_skip_commas (header); - while (*header) { - end = gst_rtspsrc_skip_item (header); - list = g_slist_prepend (list, g_strndup (header, end - header)); - header = gst_rtspsrc_skip_commas (end); - } - if (!list) - return; - - list = g_slist_reverse (list); - for (iter = list; iter; iter = iter->next) { - item = iter->data; - - eq = strchr (item, '='); - if (eq) { - name_end = (gchar *) gst_rtspsrc_unskip_lws (eq, item); - if (name_end == item) { - /* That's no good... */ - g_free (item); - continue; - } - - *name_end = '\0'; - - value = (gchar *) gst_rtspsrc_skip_lws (eq + 1); - if (*value == '"') - gst_rtsp_decode_quoted_string (value); - } else - value = NULL; - - if (value && strcmp (item, "stale") == 0 && strcmp (value, "TRUE") == 0) - *stale = TRUE; - gst_rtsp_connection_set_auth_param (conn, item, value); - g_free (item); - } - - g_slist_free (list); -} - /* Parse a WWW-Authenticate Response header and determine the * available authentication methods * @@ -5283,24 +5158,47 @@ gst_rtspsrc_parse_digest_challenge (GstRTSPConnection * conn, * At the moment, for Basic auth, we just do a minimal check and don't * even parse out the realm */ static void -gst_rtspsrc_parse_auth_hdr (gchar * hdr, GstRTSPAuthMethod * methods, - GstRTSPConnection * conn, gboolean * stale) +gst_rtspsrc_parse_auth_hdr (GstRTSPMessage * response, + GstRTSPAuthMethod * methods, GstRTSPConnection * conn, gboolean * stale) { - gchar *start; + GstRTSPAuthCredential **credentials, **credential; - g_return_if_fail (hdr != NULL); + g_return_if_fail (response != NULL); g_return_if_fail (methods != NULL); g_return_if_fail (stale != NULL); - /* Skip whitespace at the start of the string */ - for (start = hdr; start[0] != '\0' && g_ascii_isspace (start[0]); start++); + credentials = + gst_rtsp_message_parse_auth_credentials (response, + GST_RTSP_HDR_WWW_AUTHENTICATE); + if (!credentials) + return; - if (g_ascii_strncasecmp (start, "basic", 5) == 0) - *methods |= GST_RTSP_AUTH_BASIC; - else if (g_ascii_strncasecmp (start, "digest ", 7) == 0) { - *methods |= GST_RTSP_AUTH_DIGEST; - gst_rtspsrc_parse_digest_challenge (conn, &start[7], stale); + credential = credentials; + while (*credential) { + if ((*credential)->scheme == GST_RTSP_AUTH_BASIC) { + *methods |= GST_RTSP_AUTH_BASIC; + } else if ((*credential)->scheme == GST_RTSP_AUTH_DIGEST) { + GstRTSPAuthParam **param = (*credential)->params; + + *methods |= GST_RTSP_AUTH_DIGEST; + + gst_rtsp_connection_clear_auth_params (conn); + *stale = FALSE; + + while (*param) { + if (strcmp ((*param)->name, "stale") == 0 + && g_ascii_strcasecmp ((*param)->value, "TRUE") == 0) + *stale = TRUE; + gst_rtsp_connection_set_auth_param (conn, (*param)->name, + (*param)->value); + param++; + } + } + + credential++; } + + gst_rtsp_auth_credentials_free (credentials); } /** @@ -5327,16 +5225,12 @@ gst_rtspsrc_setup_auth (GstRTSPSrc * src, GstRTSPMessage * response) GstRTSPResult auth_result; GstRTSPUrl *url; GstRTSPConnection *conn; - gchar *hdr; gboolean stale = FALSE; conn = src->conninfo.connection; /* Identify the available auth methods and see if any are supported */ - if (gst_rtsp_message_get_header (response, GST_RTSP_HDR_WWW_AUTHENTICATE, - &hdr, 0) == GST_RTSP_OK) { - gst_rtspsrc_parse_auth_hdr (hdr, &avail_methods, conn, &stale); - } + gst_rtspsrc_parse_auth_hdr (response, &avail_methods, conn, &stale); if (avail_methods == GST_RTSP_AUTH_NONE) goto no_auth_available;