Skip to content
Snippets Groups Projects
Commit ef99089e authored by Abhijith PA's avatar Abhijith PA
Browse files

icecast2 patches

parents
Branches
No related merge requests found
diff -Nru icecast2-2.4.0/debian/changelog icecast2-2.4.0/debian/changelog
--- icecast2-2.4.0/debian/changelog 2015-04-29 12:03:18.000000000 +0200
+++ icecast2-2.4.0/debian/changelog 2018-11-04 14:48:01.000000000 +0100
@@ -1,3 +1,10 @@
+icecast2 (2.4.0-1.1+deb8u2) jessie-security; urgency=medium
+
+ * Non-maintainer upload by the Debian LTS Team.
+ * Fix CVE-2018-18820: buffer overflow in url-auth (Closes: #912611)
+
+ -- Abhijith PA <abhijith@disroot.org> Sun, 04 Nov 2018 19:18:01 +0530
+
icecast2 (2.4.0-1.1+deb8u1) jessie-security; urgency=high
* This fixes a crash (NULL reference) in case URL Auth is used
diff -Nru icecast2-2.4.0/debian/patches/CVE-2018-18820.patch icecast2-2.4.0/debian/patches/CVE-2018-18820.patch
--- icecast2-2.4.0/debian/patches/CVE-2018-18820.patch 1970-01-01 01:00:00.000000000 +0100
+++ icecast2-2.4.0/debian/patches/CVE-2018-18820.patch 2018-11-04 14:48:01.000000000 +0100
@@ -0,0 +1,263 @@
+Description: CVE-2018-18820
+ Attackers could craft HTTP headers that would overwrite the server's stack
+ contents, leading to remote code execution. Since Icecast is commonly used to
+ host internet radio stations, a motivated attacker could potentially take a
+ station off air.
+
+Author: Abhijith PA <abhijith@disroot.org>
+Bug-Debian: https://bugs.debian.org/912611
+Origin: https://gitlab.xiph.org/xiph/icecast-server/commit/b21a7283bd1598c5af0bbb250a041ba8198f98f2
+ https://gitlab.xiph.org/xiph/icecast-server/commit/03ea74c04a5966114c2fe66e4e6892d11a68181e
+Bug: https://gitlab.xiph.org/xiph/icecast-server/issues/2342
+Last-Update: 2018-11-04
+
+Index: icecast2-2.4.0/src/auth_url.c
+===================================================================
+--- icecast2-2.4.0.orig/src/auth_url.c
++++ icecast2-2.4.0/src/auth_url.c
+@@ -141,34 +141,48 @@ static int my_getpass(void *client, char
+ static size_t handle_returned_header (void *ptr, size_t size, size_t nmemb, void *stream)
+ {
+ auth_client *auth_user = stream;
+- unsigned bytes = size * nmemb;
++ unsigned len = size * nmemb;
+ client_t *client = auth_user->client;
+
+- if (client)
+- {
++ if (client) {
+ auth_t *auth = client->auth;
+ auth_url *url = auth->state;
+- if (strncasecmp (ptr, url->auth_header, url->auth_header_len) == 0)
++ if (url->auth_header && len >= url->auth_header_len && strncasecmp(ptr, url->auth_header, url->auth_header_len) == 0)
+ client->authenticated = 1;
+- if (strncasecmp (ptr, url->timelimit_header, url->timelimit_header_len) == 0)
+- {
++ if (url->timelimit_header && len > url->timelimit_header_len && strncasecmp(ptr, url->timelimit_header, url->timelimit_header_len) == 0) {
++ const char *input = ptr;
+ unsigned int limit = 0;
+- sscanf ((char *)ptr+url->timelimit_header_len, "%u\r\n", &limit);
+- client->con->discon_time = time(NULL) + limit;
++ if (len >= 2 && input[len - 2] == '\r' && input[len - 1] == '\n') {
++ input += url->timelimit_header_len;
++
++ if (sscanf(input, "%u\r\n", &limit) == 1) {
++ client->con->discon_time = time(NULL) + limit;
++ } else {
++ ICECAST_LOG_ERROR("Auth backend returned invalid timeline header: Can not parse limit");
++ }
++ } else {
++ ICECAST_LOG_ERROR("Auth backend returned invalid timelimit header.");
++ }
+ }
+- if (strncasecmp (ptr, "icecast-auth-message: ", 22) == 0)
+- {
+- char *eol;
+- snprintf (url->errormsg, sizeof (url->errormsg), "%s", (char*)ptr+22);
+- eol = strchr (url->errormsg, '\r');
+- if (eol == NULL)
+- eol = strchr (url->errormsg, '\n');
+- if (eol)
+- *eol = '\0';
++ if (len > 24 && strncasecmp(ptr, "icecast-auth-message: ", 22) == 0) {
++ const char *input = ptr;
++ size_t copy_len = len - 24 + 1; /* length of string plus \0-termination */
++
++ if (copy_len > sizeof(url->errormsg)) {
++ copy_len = sizeof(url->errormsg);
++ }
++
++ if (len >= 2 && input[len - 2] == '\r' && input[len - 1] == '\n') {
++ input += 22;
++ memcpy(url->errormsg, input, copy_len);
++ url->errormsg[copy_len-1] = 0;
++ } else {
++ ICECAST_LOG_ERROR("Auth backend returned invalid message header.");
++ }
+ }
+ }
+
+- return (int)bytes;
++ return (int)len;
+ }
+
+ /* capture returned data, but don't do anything with it */
+@@ -191,6 +205,7 @@ static auth_result url_remove_listener (
+ char *userpwd = NULL, post [4096];
+ const char *agent;
+ char *user_agent, *ipaddr;
++ int ret;
+
+ if (url->removeurl == NULL)
+ return AUTH_OK;
+@@ -223,11 +238,11 @@ static auth_result url_remove_listener (
+ mount = util_url_escape (mountreq);
+ ipaddr = util_url_escape (client->con->ip);
+
+- snprintf (post, sizeof (post),
+- "action=listener_remove&server=%s&port=%d&client=%lu&mount=%s"
+- "&user=%s&pass=%s&duration=%lu&ip=%s&agent=%s",
+- server, port, client->con->id, mount, username,
+- password, (long unsigned)duration, ipaddr, user_agent);
++ret = snprintf(post, sizeof(post),
++ "action=listener_remove&server=%s&port=%d&client=%lu&mount=%s"
++ "&user=%s&pass=%s&duration=%lu&ip=%s&agent=%s",
++ server, port, client->con->id, mount, username,
++ password, (long unsigned)duration, ipaddr, user_agent);
+ free (server);
+ free (mount);
+ free (username);
+@@ -235,6 +250,11 @@ static auth_result url_remove_listener (
+ free (ipaddr);
+ free (user_agent);
+
++ if (ret <= 0 || ret >= sizeof(post)) {
++ ICECAST_LOG_ERROR("POST body too long for buffer on mount point \"%H\" client %p.", auth_user->mount, client);
++ return AUTH_FAILED;
++ }
++
+ if (strchr (url->removeurl, '@') == NULL)
+ {
+ if (url->userpwd)
+@@ -331,6 +351,11 @@ static auth_result url_add_listener (aut
+ free (password);
+ free (ipaddr);
+
++ if (post_offset <= 0 || post_offset >= sizeof(post)) {
++ ICECAST_LOG_ERROR("POST body too long for buffer on mount point \"%H\" client %p.", auth_user->mount, client);
++ return AUTH_FAILED;
++ }
++
+ pass_headers = NULL;
+ if (url->pass_headers)
+ pass_headers = strdup (url->pass_headers);
+@@ -349,11 +374,20 @@ static auth_result url_add_listener (aut
+ header_val = httpp_getvar (client->parser, cur_header);
+ if (header_val)
+ {
++ size_t left = sizeof(post) - post_offset;
++ int ret;
+ header_valesc = util_url_escape (header_val);
+- post_offset += snprintf (post+post_offset, sizeof (post)-post_offset, "&%s%s=%s",
++ ret = snprintf (post+post_offset, left, "&%s%s=%s",
+ url->prefix_headers ? url->prefix_headers : "",
+ cur_header, header_valesc);
+ free (header_valesc);
++ if (ret <= 0 || ret >= left) {
++ ICECAST_LOG_ERROR("POST body too long for buffer on mount point \"%H\" client %p.", auth_user->mount, client);
++ free(pass_headers);
++ return AUTH_FAILED;
++ } else {
++ post_offset += ret;
++ }
+ }
+
+ cur_header = next_header;
+@@ -418,6 +452,7 @@ static void url_stream_start (auth_clien
+ char *stream_start_url;
+ int port;
+ char post [4096];
++ int ret;
+
+ if (url->stream_start == NULL)
+ {
+@@ -433,11 +468,17 @@ static void url_stream_start (auth_clien
+ config_release_config ();
+ mount = util_url_escape (auth_user->mount);
+
+- snprintf (post, sizeof (post),
+- "action=mount_add&mount=%s&server=%s&port=%d", mount, server, port);
++ ret = snprintf(post, sizeof(post), "action=mount_add&mount=%s&server=%s&port=%d", mount, server, port);
+ free (server);
+ free (mount);
+
++if (ret <= 0 || ret >= sizeof(post)) {
++ ICECAST_LOG_ERROR("POST body too long for buffer on mount point \"%H\".", auth_user->mount);
++ auth_release(auth);
++ free(stream_start_url);
++ return;
++ }
++
+ if (strchr (url->stream_start, '@') == NULL)
+ {
+ if (url->userpwd)
+@@ -470,7 +511,7 @@ static void url_stream_end (auth_client
+ char *stream_end_url;
+ int port;
+ char post [4096];
+-
++ int ret;
+ if (url->stream_end == NULL)
+ {
+ config_release_config ();
+@@ -485,11 +526,17 @@ static void url_stream_end (auth_client
+ config_release_config ();
+ mount = util_url_escape (auth_user->mount);
+
+- snprintf (post, sizeof (post),
+- "action=mount_remove&mount=%s&server=%s&port=%d", mount, server, port);
++ ret = snprintf(post, sizeof(post), "action=mount_remove&mount=%s&server=%s&port=%d", mount, server, port);
+ free (server);
+ free (mount);
+
++ if (ret <= 0 || ret >= sizeof(post)) {
++ ICECAST_LOG_ERROR("POST body too long for buffer on mount point \"%H\".", auth_user->mount);
++ auth_release(auth);
++ free(stream_end_url);
++ return;
++ }
++
+ if (strchr (url->stream_end, '@') == NULL)
+ {
+ if (url->userpwd)
+@@ -519,7 +566,7 @@ static void url_stream_auth (auth_client
+ auth_url *url = client->auth->state;
+ char *mount, *host, *user, *pass, *ipaddr, *admin="";
+ char post [4096];
+-
++ int ret;
+ if (strchr (url->stream_auth, '@') == NULL)
+ {
+ if (url->userpwd)
+@@ -553,9 +600,9 @@ static void url_stream_auth (auth_client
+ pass = strdup("");
+ }
+
+- snprintf (post, sizeof (post),
+- "action=stream_auth&mount=%s&ip=%s&server=%s&port=%d&user=%s&pass=%s%s",
+- mount, ipaddr, host, port, user, pass, admin);
++ ret = snprintf(post, sizeof(post),
++ "action=stream_auth&mount=%s&ip=%s&server=%s&port=%d&user=%s&pass=%s%s",
++ mount, ipaddr, host, port, user, pass, admin);
+ free (ipaddr);
+ free (user);
+ free (pass);
+@@ -563,6 +610,11 @@ static void url_stream_auth (auth_client
+ free (host);
+
+ client->authenticated = 0;
++if (ret <= 0 || ret >= sizeof(post)) {
++ ICECAST_LOG_ERROR("POST body too long for buffer on mount point \"%H\" client %p.", auth_user->mount, client);
++ return;
++ }
++
+ if (curl_easy_perform (url->handle))
+ WARN2 ("auth to server %s failed with %s", url->stream_auth, url->errormsg);
+ }
+Index: icecast2-2.4.0/src/logging.h
+===================================================================
+--- icecast2-2.4.0.orig/src/logging.h
++++ icecast2-2.4.0/src/logging.h
+@@ -34,6 +34,12 @@ extern int playlistlog;
+ #define __func__ strrchr (__FILE__, '\\') ? strrchr (__FILE__, '\\') + 1 : __FILE__
+ #endif
+
++/*
++** Macros for logging. ICECAST_LOG_ERROR backported from 2.4.2 to deal with CVE-2018-18820
++*/
++
++#define ICECAST_LOG_ERROR(...) log_write(errorlog, 1, CATMODULE "/", __func__, __VA_ARGS__)
++
+ #define ERROR0(y) log_write(errorlog, 1, CATMODULE "/", __func__, y)
+ #define ERROR1(y, a) log_write(errorlog, 1, CATMODULE "/", __func__, y, a)
+ #define ERROR2(y, a, b) log_write(errorlog, 1, CATMODULE "/", __func__, y, a, b)
diff -Nru icecast2-2.4.0/debian/patches/series icecast2-2.4.0/debian/patches/series
--- icecast2-2.4.0/debian/patches/series 2015-04-29 12:03:18.000000000 +0200
+++ icecast2-2.4.0/debian/patches/series 2018-11-04 14:48:01.000000000 +0100
@@ -1,2 +1,3 @@
0001-disconnects_stdio_of_on_dis_connect_scripts_from_random_filehandles
0002-crash-in-url-auth
+CVE-2018-18820.patch
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment