[Pkg-voip-commits] [asterisk] 01/02: Upstream fixes for CVE-2017-14099 / AST-2017-005 and CVE-2017-14100 / AST-2017-006

Bernhard Schmidt berni at moszumanska.debian.org
Sat Sep 2 21:32:35 UTC 2017


This is an automated email from the git hooks/post-receive script.

berni pushed a commit to branch stretch
in repository asterisk.

commit 60eb631bfdf0917804c81b94e4aafd4001a20f56
Author: Bernhard Schmidt <berni at debian.org>
Date:   Sat Sep 2 23:17:59 2017 +0200

    Upstream fixes for CVE-2017-14099 / AST-2017-005 and CVE-2017-14100 / AST-2017-006
    
    For AST-2016-005 We actually use the 13.13-cert patch which applies cleanly
    to 13.14.1.
    
    Closes: #873907, #873908
---
 debian/patches/AST-2017-005-13.13.diff | 202 ++++++++++++++++
 debian/patches/AST-2017-006-13.diff    | 407 +++++++++++++++++++++++++++++++++
 debian/patches/series                  |   2 +
 3 files changed, 611 insertions(+)

diff --git a/debian/patches/AST-2017-005-13.13.diff b/debian/patches/AST-2017-005-13.13.diff
new file mode 100644
index 0000000..ea5d291
--- /dev/null
+++ b/debian/patches/AST-2017-005-13.13.diff
@@ -0,0 +1,202 @@
+From ae26ddb9f5cb10e565dc756c14df1da36eeff930 Mon Sep 17 00:00:00 2001
+From: Joshua Colp <jcolp at digium.com>
+Date: Mon, 22 May 2017 15:36:38 +0000
+Subject: [PATCH] res_rtp_asterisk: Only learn a new source in learn state.
+
+This change moves the logic which learns a new source address
+for RTP so it only occurs in the learning state. The learning
+state is entered on initial allocation of RTP or if we are
+told that the remote address for the media has changed. While
+in the learning state if we continue to receive media from
+the original source we restart the learning process. It is
+only once we receive a sufficient number of RTP packets from
+the new source that we will switch to it. Once this is done
+the closed state is entered where all packets that do not
+originate from the expected source are dropped.
+
+The learning process has also been improved to take into
+account the time between received packets so a flood of them
+while in the learning state does not cause media to be switched.
+
+Finally RTCP now drops packets which are not for the learned
+SSRC if strict RTP is enabled.
+
+ASTERISK-27013
+
+Change-Id: I56a96e993700906355e79bc880ad9d4ad3ab129c
+---
+
+diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c
+index e6ac793..18646a5 100644
+--- a/res/res_rtp_asterisk.c
++++ b/res/res_rtp_asterisk.c
+@@ -213,8 +213,9 @@
+ 
+ /*! \brief RTP learning mode tracking information */
+ struct rtp_learning_info {
+-	int max_seq;	/*!< The highest sequence number received */
+-	int packets;	/*!< The number of remaining packets before the source is accepted */
++	int max_seq;	 /*!< The highest sequence number received */
++	int packets;	 /*!< The number of remaining packets before the source is accepted */
++	struct timeval received; /*!< The time of the last received packet */
+ };
+ 
+ #ifdef HAVE_OPENSSL_SRTP
+@@ -299,7 +300,6 @@
+ 	 * but these are in place to keep learning mode sequence values sealed from their normal counterparts.
+ 	 */
+ 	struct rtp_learning_info rtp_source_learn;	/* Learning mode track for the expected RTP source */
+-	struct rtp_learning_info alt_source_learn;	/* Learning mode tracking for a new RTP source after one has been chosen */
+ 
+ 	struct rtp_red *red;
+ 
+@@ -2424,6 +2424,7 @@
+ {
+ 	info->max_seq = seq - 1;
+ 	info->packets = learning_min_sequential;
++	memset(&info->received, 0, sizeof(info->received));
+ }
+ 
+ /*!
+@@ -2438,6 +2439,13 @@
+  */
+ static int rtp_learning_rtp_seq_update(struct rtp_learning_info *info, uint16_t seq)
+ {
++	if (!ast_tvzero(info->received) && ast_tvdiff_ms(ast_tvnow(), info->received) < 5) {
++		/* During the probation period the minimum amount of media we'll accept is
++		 * 10ms so give a reasonable 5ms buffer just in case we get it sporadically.
++		 */
++		return 1;
++	}
++
+ 	if (seq == info->max_seq + 1) {
+ 		/* packet is in sequence */
+ 		info->packets--;
+@@ -2446,6 +2454,7 @@
+ 		info->packets = learning_min_sequential - 1;
+ 	}
+ 	info->max_seq = seq;
++	info->received = ast_tvnow();
+ 
+ 	return (info->packets == 0);
+ }
+@@ -2652,10 +2661,9 @@
+ 	/* Set default parameters on the newly created RTP structure */
+ 	rtp->ssrc = ast_random();
+ 	rtp->seqno = ast_random() & 0x7fff;
+-	rtp->strict_rtp_state = (strictrtp ? STRICT_RTP_LEARN : STRICT_RTP_OPEN);
++	rtp->strict_rtp_state = (strictrtp ? STRICT_RTP_CLOSED : STRICT_RTP_OPEN);
+ 	if (strictrtp) {
+ 		rtp_learning_seq_init(&rtp->rtp_source_learn, (uint16_t)rtp->seqno);
+-		rtp_learning_seq_init(&rtp->alt_source_learn, (uint16_t)rtp->seqno);
+ 	}
+ 
+ 	/* Create a new socket for us to listen on and use */
+@@ -4154,17 +4162,6 @@
+ 
+ 	packetwords = res / 4;
+ 
+-	if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_NAT)) {
+-		/* Send to whoever sent to us */
+-		if (ast_sockaddr_cmp(&rtp->rtcp->them, &addr)) {
+-			ast_sockaddr_copy(&rtp->rtcp->them, &addr);
+-			if (rtpdebug) {
+-				ast_debug(0, "RTCP NAT: Got RTCP from other end. Now sending to address %s\n",
+-					  ast_sockaddr_stringify(&rtp->rtcp->them));
+-			}
+-		}
+-	}
+-
+ 	ast_debug(1, "Got RTCP report of %d bytes\n", res);
+ 
+ 	while (position < packetwords) {
+@@ -4191,6 +4188,25 @@
+ 				ast_debug(1, "RTCP Read too short\n");
+ 			}
+ 			return &ast_null_frame;
++		}
++
++		if ((rtp->strict_rtp_state != STRICT_RTP_OPEN) && (rtcp_report->ssrc != rtp->themssrc)) {
++			/* Skip over this RTCP record as it does not contain the correct SSRC */
++			position += (length + 1);
++			ast_debug(1, "%p -- Received RTCP report from %s, dropping due to strict RTP protection. Received SSRC '%u' but expected '%u'\n",
++				rtp, ast_sockaddr_stringify(&addr), rtcp_report->ssrc, rtp->themssrc);
++			continue;
++		}
++
++		if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_NAT)) {
++			/* Send to whoever sent to us */
++			if (ast_sockaddr_cmp(&rtp->rtcp->them, &addr)) {
++				ast_sockaddr_copy(&rtp->rtcp->them, &addr);
++				if (rtpdebug) {
++					ast_debug(0, "RTCP NAT: Got RTCP from other end. Now sending to address %s\n",
++						ast_sockaddr_stringify(&rtp->rtcp->them));
++				}
++			}
+ 		}
+ 
+ 		if (rtcp_debug_test_addr(&addr)) {
+@@ -4517,37 +4533,30 @@
+ 
+ 	/* If strict RTP protection is enabled see if we need to learn the remote address or if we need to drop the packet */
+ 	if (rtp->strict_rtp_state == STRICT_RTP_LEARN) {
+-		ast_debug(1, "%p -- Probation learning mode pass with source address %s\n", rtp, ast_sockaddr_stringify(&addr));
+-		/* For now, we always copy the address. */
+-		ast_sockaddr_copy(&rtp->strict_rtp_address, &addr);
+-
+-		/* Send the rtp and the seqno from header to rtp_learning_rtp_seq_update to see whether we can exit or not*/
+-		if (rtp_learning_rtp_seq_update(&rtp->rtp_source_learn, seqno)) {
+-			ast_debug(1, "%p -- Probation at seq %d with %d to go; discarding frame\n",
+-				rtp, rtp->rtp_source_learn.max_seq, rtp->rtp_source_learn.packets);
+-			return &ast_null_frame;
+-		}
+-
+-		ast_verb(4, "%p -- Probation passed - setting RTP source address to %s\n", rtp, ast_sockaddr_stringify(&addr));
+-		rtp->strict_rtp_state = STRICT_RTP_CLOSED;
+-	}
+-	if (rtp->strict_rtp_state == STRICT_RTP_CLOSED) {
+ 		if (!ast_sockaddr_cmp(&rtp->strict_rtp_address, &addr)) {
+-			/* Always reset the alternate learning source */
+-			rtp_learning_seq_init(&rtp->alt_source_learn, seqno);
++			/* We are learning a new address but have received traffic from the existing address,
++			 * accept it but reset the current learning for the new source so it only takes over
++			 * once sufficient traffic has been received. */
++			rtp_learning_seq_init(&rtp->rtp_source_learn, seqno);
+ 		} else {
+ 			/* Start trying to learn from the new address. If we pass a probationary period with
+ 			 * it, that means we've stopped getting RTP from the original source and we should
+ 			 * switch to it.
+ 			 */
+-			if (rtp_learning_rtp_seq_update(&rtp->alt_source_learn, seqno)) {
++			if (rtp_learning_rtp_seq_update(&rtp->rtp_source_learn, seqno)) {
+ 				ast_debug(1, "%p -- Received RTP packet from %s, dropping due to strict RTP protection. Will switch to it in %d packets\n",
+-						rtp, ast_sockaddr_stringify(&addr), rtp->alt_source_learn.packets);
++					rtp, ast_sockaddr_stringify(&addr), rtp->rtp_source_learn.packets);
+ 				return &ast_null_frame;
+ 			}
+-			ast_verb(4, "%p -- Switching RTP source address to %s\n", rtp, ast_sockaddr_stringify(&addr));
+ 			ast_sockaddr_copy(&rtp->strict_rtp_address, &addr);
++
++			ast_verb(4, "%p -- Probation passed - setting RTP source address to %s\n", rtp, ast_sockaddr_stringify(&addr));
++			rtp->strict_rtp_state = STRICT_RTP_CLOSED;
+ 		}
++	} else if (rtp->strict_rtp_state == STRICT_RTP_CLOSED && ast_sockaddr_cmp(&rtp->strict_rtp_address, &addr)) {
++		ast_debug(1, "%p -- Received RTP packet from %s, dropping due to strict RTP protection.\n",
++			rtp, ast_sockaddr_stringify(&addr));
++		return &ast_null_frame;
+ 	}
+ 
+ 	/* If symmetric RTP is enabled see if the remote side is not what we expected and change where we are sending audio */
+@@ -5005,7 +5014,11 @@
+ 
+ 	rtp->rxseqno = 0;
+ 
+-	if (strictrtp && rtp->strict_rtp_state != STRICT_RTP_OPEN) {
++	if (strictrtp && rtp->strict_rtp_state != STRICT_RTP_OPEN && !ast_sockaddr_isnull(addr) &&
++		ast_sockaddr_cmp(addr, &rtp->strict_rtp_address)) {
++		/* We only need to learn a new strict source address if we've been told the source is
++		 * changing to something different.
++		 */
+ 		rtp->strict_rtp_state = STRICT_RTP_LEARN;
+ 		rtp_learning_seq_init(&rtp->rtp_source_learn, rtp->seqno);
+ 	}
diff --git a/debian/patches/AST-2017-006-13.diff b/debian/patches/AST-2017-006-13.diff
new file mode 100644
index 0000000..5083867
--- /dev/null
+++ b/debian/patches/AST-2017-006-13.diff
@@ -0,0 +1,407 @@
+From 8b7eaea2ac2c84d0946c4ac232597eb03c6cb8d2 Mon Sep 17 00:00:00 2001
+From: Corey Farrell <git at cfware.com>
+Date: Sat, 01 Jul 2017 20:24:27 -0400
+Subject: [PATCH] AST-2017-006: Fix app_minivm application MinivmNotify command injection
+
+An admin can configure app_minivm with an externnotify program to be run
+when a voicemail is received.  The app_minivm application MinivmNotify
+uses ast_safe_system() for this purpose which is vulnerable to command
+injection since the Caller-ID name and number values given to externnotify
+can come from an external untrusted source.
+
+* Add ast_safe_execvp() function.  This gives modules the ability to run
+external commands with greater safety compared to ast_safe_system().
+Specifically when some parameters are filled by untrusted sources the new
+function does not allow malicious input to break argument encoding.  This
+may be of particular concern where CALLERID(name) or CALLERID(num) may be
+used as a parameter to a script run by ast_safe_system() which could
+potentially allow arbitrary command execution.
+
+* Changed app_minivm.c:run_externnotify() to use the new ast_safe_execvp()
+instead of ast_safe_system() to avoid command injection.
+
+* Document code injection potential from untrusted data sources for other
+shell commands that are under user control.
+
+ASTERISK-27103
+
+Change-Id: I7552472247a84cde24e1358aaf64af160107aef1
+---
+
+diff --git a/README-SERIOUSLY.bestpractices.txt b/README-SERIOUSLY.bestpractices.txt
+index 108adce..b170d29 100644
+--- a/README-SERIOUSLY.bestpractices.txt
++++ b/README-SERIOUSLY.bestpractices.txt
+@@ -94,6 +94,13 @@
+ ways in which you can mitigate this impact: stricter pattern matching, or using
+ the FILTER() dialplan function.
+ 
++The CALLERID(num) and CALLERID(name) values are other commonly used values that
++are sources of data potentially supplied by outside sources.  If you use these
++values as parameters to the System(), MixMonitor(), or Monitor() applications
++or the SHELL() dialplan function, you can allow injection of arbitrary operating
++system command execution.  The FILTER() dialplan function is available to remove
++dangerous characters from untrusted strings to block the command injection.
++
+ Strict Pattern Matching
+ -----------------------
+ 
+diff --git a/apps/app_minivm.c b/apps/app_minivm.c
+index 1bfcfbb..37974c7 100644
+--- a/apps/app_minivm.c
++++ b/apps/app_minivm.c
+@@ -1757,21 +1757,35 @@
+ /*! \brief Run external notification for voicemail message */
+ static void run_externnotify(struct ast_channel *chan, struct minivm_account *vmu)
+ {
+-	char arguments[BUFSIZ];
++	char fquser[AST_MAX_CONTEXT * 2];
++	char *argv[5] = { NULL };
++	struct ast_party_caller *caller;
++	char *cid;
++	int idx;
+ 
+-	if (ast_strlen_zero(vmu->externnotify) && ast_strlen_zero(global_externnotify))
++	if (ast_strlen_zero(vmu->externnotify) && ast_strlen_zero(global_externnotify)) {
+ 		return;
++	}
+ 
+-	snprintf(arguments, sizeof(arguments), "%s %s@%s %s %s&", 
+-		ast_strlen_zero(vmu->externnotify) ? global_externnotify : vmu->externnotify, 
+-		vmu->username, vmu->domain,
+-		(ast_channel_caller(chan)->id.name.valid && ast_channel_caller(chan)->id.name.str)
+-			? ast_channel_caller(chan)->id.name.str : "",
+-		(ast_channel_caller(chan)->id.number.valid && ast_channel_caller(chan)->id.number.str)
+-			? ast_channel_caller(chan)->id.number.str : "");
++	snprintf(fquser, sizeof(fquser), "%s@%s", vmu->username, vmu->domain);
+ 
+-	ast_debug(1, "Executing: %s\n", arguments);
+-	ast_safe_system(arguments);
++	caller = ast_channel_caller(chan);
++	idx = 0;
++	argv[idx++] = ast_strlen_zero(vmu->externnotify) ? global_externnotify : vmu->externnotify;
++	argv[idx++] = fquser;
++	cid = S_COR(caller->id.name.valid, caller->id.name.str, NULL);
++	if (cid) {
++		argv[idx++] = cid;
++	}
++	cid = S_COR(caller->id.number.valid, caller->id.number.str, NULL);
++	if (cid) {
++		argv[idx++] = cid;
++	}
++	argv[idx] = NULL;
++
++	ast_debug(1, "Executing: %s %s %s %s\n",
++		argv[0], argv[1], argv[2] ?: "", argv[3] ?: "");
++	ast_safe_execvp(1, argv[0], argv);
+ }
+ 
+ /*!\internal
+diff --git a/apps/app_mixmonitor.c b/apps/app_mixmonitor.c
+index 979bf2d..24ce3b6 100644
+--- a/apps/app_mixmonitor.c
++++ b/apps/app_mixmonitor.c
+@@ -138,6 +138,11 @@
+ 				<para>Will be executed when the recording is over.</para>
+ 				<para>Any strings matching <literal>^{X}</literal> will be unescaped to <variable>X</variable>.</para>
+ 				<para>All variables will be evaluated at the time MixMonitor is called.</para>
++				<warning><para>Do not use untrusted strings such as <variable>CALLERID(num)</variable>
++				or <variable>CALLERID(name)</variable> as part of the command parameters.  You
++				risk a command injection attack executing arbitrary commands if the untrusted
++				strings aren't filtered to remove dangerous characters.  See function
++				<variable>FILTER()</variable>.</para></warning>
+ 			</parameter>
+ 		</syntax>
+ 		<description>
+@@ -150,6 +155,11 @@
+ 					<para>Will contain the filename used to record.</para>
+ 				</variable>
+ 			</variablelist>
++			<warning><para>Do not use untrusted strings such as <variable>CALLERID(num)</variable>
++			or <variable>CALLERID(name)</variable> as part of ANY of the application's
++			parameters.  You risk a command injection attack executing arbitrary commands
++			if the untrusted strings aren't filtered to remove dangerous characters.  See
++			function <variable>FILTER()</variable>.</para></warning>
+ 		</description>
+ 		<see-also>
+ 			<ref type="application">Monitor</ref>
+@@ -224,6 +234,11 @@
+ 				<para>Will be executed when the recording is over.
+ 				Any strings matching <literal>^{X}</literal> will be unescaped to <variable>X</variable>.
+ 				All variables will be evaluated at the time MixMonitor is called.</para>
++				<warning><para>Do not use untrusted strings such as <variable>CALLERID(num)</variable>
++				or <variable>CALLERID(name)</variable> as part of the command parameters.  You
++				risk a command injection attack executing arbitrary commands if the untrusted
++				strings aren't filtered to remove dangerous characters.  See function
++				<variable>FILTER()</variable>.</para></warning>
+ 			</parameter>
+ 		</syntax>
+ 		<description>
+diff --git a/apps/app_system.c b/apps/app_system.c
+index 7fe453d..e868a07 100644
+--- a/apps/app_system.c
++++ b/apps/app_system.c
+@@ -48,6 +48,11 @@
+ 		<syntax>
+ 			<parameter name="command" required="true">
+ 				<para>Command to execute</para>
++				<warning><para>Do not use untrusted strings such as <variable>CALLERID(num)</variable>
++				or <variable>CALLERID(name)</variable> as part of the command parameters.  You
++				risk a command injection attack executing arbitrary commands if the untrusted
++				strings aren't filtered to remove dangerous characters.  See function
++				<variable>FILTER()</variable>.</para></warning>
+ 			</parameter>
+ 		</syntax>
+ 		<description>
+@@ -73,6 +78,11 @@
+ 		<syntax>
+ 			<parameter name="command" required="true">
+ 				<para>Command to execute</para>
++				<warning><para>Do not use untrusted strings such as <variable>CALLERID(num)</variable>
++				or <variable>CALLERID(name)</variable> as part of the command parameters.  You
++				risk a command injection attack executing arbitrary commands if the untrusted
++				strings aren't filtered to remove dangerous characters.  See function
++				<variable>FILTER()</variable>.</para></warning>
+ 			</parameter>
+ 		</syntax>
+ 		<description>
+diff --git a/configs/samples/minivm.conf.sample b/configs/samples/minivm.conf.sample
+index 2df3449..79fdbb0 100644
+--- a/configs/samples/minivm.conf.sample
++++ b/configs/samples/minivm.conf.sample
+@@ -51,7 +51,7 @@
+ ; If you need to have an external program, i.e. /usr/bin/myapp called when a
+ ; voicemail is received by the server. The arguments are
+ ;
+-; 	<app> <username at domain> <callerid-number> <callerid-name>
++; 	<app> <username at domain> <callerid-name> <callerid-number>
+ ;
+ ;externnotify=/usr/bin/myapp
+ ; The character set for voicemail messages can be specified here
+diff --git a/funcs/func_shell.c b/funcs/func_shell.c
+index e403efc..79b7f99 100644
+--- a/funcs/func_shell.c
++++ b/funcs/func_shell.c
+@@ -84,6 +84,11 @@
+ 		<syntax>
+ 			<parameter name="command" required="true">
+ 				<para>The command that the shell should execute.</para>
++				<warning><para>Do not use untrusted strings such as <variable>CALLERID(num)</variable>
++				or <variable>CALLERID(name)</variable> as part of the command parameters.  You
++				risk a command injection attack executing arbitrary commands if the untrusted
++				strings aren't filtered to remove dangerous characters.  See function
++				<variable>FILTER()</variable>.</para></warning>
+ 			</parameter>
+ 		</syntax>
+ 		<description>
+diff --git a/include/asterisk/app.h b/include/asterisk/app.h
+index 86336e3..5b10b1c 100644
+--- a/include/asterisk/app.h
++++ b/include/asterisk/app.h
+@@ -871,9 +871,34 @@
+ int ast_vm_test_create_user(const char *context, const char *mailbox);
+ #endif
+ 
+-/*! \brief Safely spawn an external program while closing file descriptors
+-	\note This replaces the \b system call in all Asterisk modules
+-*/
++/*!
++ * \brief Safely spawn an external program while closing file descriptors
++ *
++ * \note This replaces the \b execvp call in all Asterisk modules
++ *
++ * \param dualfork Non-zero to simulate running the program in the
++ * background by forking twice.  The option provides similar
++ * functionality to the '&' in the OS shell command "cmd &".  The
++ * option allows Asterisk to run a reaper loop to watch the first fork
++ * which immediately exits after spaning the second fork.  The actual
++ * program is run in the second fork.
++ * \param file execvp(file, argv) file parameter
++ * \param argv execvp(file, argv) argv parameter
++ */
++int ast_safe_execvp(int dualfork, const char *file, char *const argv[]);
++
++/*!
++ * \brief Safely spawn an OS shell command while closing file descriptors
++ *
++ * \note This replaces the \b system call in all Asterisk modules
++ *
++ * \param s - OS shell command string to execute.
++ *
++ * \warning Command injection can happen using this call if the passed
++ * in string is created using untrusted data from an external source.
++ * It is best not to use untrusted data.  However, the caller could
++ * filter out dangerous characters to avoid command injection.
++ */
+ int ast_safe_system(const char *s);
+ 
+ /*!
+diff --git a/main/asterisk.c b/main/asterisk.c
+index ac078dd..cc55564 100644
+--- a/main/asterisk.c
++++ b/main/asterisk.c
+@@ -1283,11 +1283,10 @@
+ 	ast_mutex_unlock(&safe_system_lock);
+ }
+ 
+-int ast_safe_system(const char *s)
++/*! \brief fork and perform other preparations for spawning applications */
++static pid_t safe_exec_prep(int dualfork)
+ {
+ 	pid_t pid;
+-	int res;
+-	int status;
+ 
+ #if defined(HAVE_WORKING_FORK) || defined(HAVE_WORKING_VFORK)
+ 	ast_replace_sigchld();
+@@ -1309,35 +1308,101 @@
+ 		cap_free(cap);
+ #endif
+ #ifdef HAVE_WORKING_FORK
+-		if (ast_opt_high_priority)
++		if (ast_opt_high_priority) {
+ 			ast_set_priority(0);
++		}
+ 		/* Close file descriptors and launch system command */
+ 		ast_close_fds_above_n(STDERR_FILENO);
+ #endif
+-		execl("/bin/sh", "/bin/sh", "-c", s, (char *) NULL);
+-		_exit(1);
+-	} else if (pid > 0) {
++		if (dualfork) {
++#ifdef HAVE_WORKING_FORK
++			pid = fork();
++#else
++			pid = vfork();
++#endif
++			if (pid < 0) {
++				/* Second fork failed. */
++				/* No logger available. */
++				_exit(1);
++			}
++
++			if (pid > 0) {
++				/* This is the first fork, exit so the reaper finishes right away. */
++				_exit(0);
++			}
++
++			/* This is the second fork.  The first fork will exit immediately so
++			 * Asterisk doesn't have to wait for completion.
++			 * ast_safe_system("cmd &") would run in the background, but the '&'
++			 * cannot be added with ast_safe_execvp, so we have to double fork.
++			 */
++		}
++	}
++
++	if (pid < 0) {
++		ast_log(LOG_WARNING, "Fork failed: %s\n", strerror(errno));
++	}
++#else
++	ast_log(LOG_WARNING, "Fork failed: %s\n", strerror(ENOTSUP));
++	pid = -1;
++#endif
++
++	return pid;
++}
++
++/*! \brief wait for spawned application to complete and unreplace sigchld */
++static int safe_exec_wait(pid_t pid)
++{
++	int res = -1;
++
++#if defined(HAVE_WORKING_FORK) || defined(HAVE_WORKING_VFORK)
++	if (pid > 0) {
+ 		for (;;) {
++			int status;
++
+ 			res = waitpid(pid, &status, 0);
+ 			if (res > -1) {
+ 				res = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
+ 				break;
+-			} else if (errno != EINTR)
++			}
++			if (errno != EINTR) {
+ 				break;
++			}
+ 		}
+-	} else {
+-		ast_log(LOG_WARNING, "Fork failed: %s\n", strerror(errno));
+-		res = -1;
+ 	}
+ 
+ 	ast_unreplace_sigchld();
+-#else /* !defined(HAVE_WORKING_FORK) && !defined(HAVE_WORKING_VFORK) */
+-	res = -1;
+ #endif
+ 
+ 	return res;
+ }
+ 
++int ast_safe_execvp(int dualfork, const char *file, char *const argv[])
++{
++	pid_t pid = safe_exec_prep(dualfork);
++
++	if (pid == 0) {
++		execvp(file, argv);
++		_exit(1);
++		/* noreturn from _exit */
++	}
++
++	return safe_exec_wait(pid);
++}
++
++int ast_safe_system(const char *s)
++{
++	pid_t pid = safe_exec_prep(0);
++
++	if (pid == 0) {
++		execl("/bin/sh", "/bin/sh", "-c", s, (char *) NULL);
++		_exit(1);
++		/* noreturn from _exit */
++	}
++
++	return safe_exec_wait(pid);
++}
++
+ /*!
+  * \brief enable or disable a logging level to a specified console
+  */
+diff --git a/res/res_monitor.c b/res/res_monitor.c
+index ebf9843..0058592 100644
+--- a/res/res_monitor.c
++++ b/res/res_monitor.c
+@@ -62,17 +62,17 @@
+ 		<syntax>
+ 			<parameter name="file_format" argsep=":">
+ 				<argument name="file_format" required="true">
+-					<para>optional, if not set, defaults to <literal>wav</literal></para>
++					<para>Optional.  If not set, defaults to <literal>wav</literal></para>
+ 				</argument>
+ 				<argument name="urlbase" />
+ 			</parameter>
+ 			<parameter name="fname_base">
+-				<para>if set, changes the filename used to the one specified.</para>
++				<para>If set, changes the filename used to the one specified.</para>
+ 			</parameter>
+ 			<parameter name="options">
+ 				<optionlist>
+ 					<option name="m">
+-						<para>when the recording ends mix the two leg files into one and
++						<para>When the recording ends mix the two leg files into one and
+ 						delete the two leg files. If the variable <variable>MONITOR_EXEC</variable>
+ 						is set, the application referenced in it will be executed instead of
+ 						soxmix/sox and the raw leg files will NOT be deleted automatically.
+@@ -83,6 +83,13 @@
+ 						will be passed on as additional arguments to <variable>MONITOR_EXEC</variable>.
+ 						Both <variable>MONITOR_EXEC</variable> and the Mix flag can be set from the
+ 						administrator interface.</para>
++						<warning><para>Do not use untrusted strings such as
++						<variable>CALLERID(num)</variable> or <variable>CALLERID(name)</variable>
++						as part of <variable>MONITOR_EXEC</variable> or
++						<variable>MONITOR_EXEC_ARGS</variable>.  You risk a command injection
++						attack executing arbitrary commands if the untrusted strings aren't
++						filtered to remove dangerous characters.  See function
++						<variable>FILTER()</variable>.</para></warning>
+ 					</option>
+ 					<option name="b">
+ 						<para>Don't begin recording unless a call is bridged to another channel.</para>
diff --git a/debian/patches/series b/debian/patches/series
index 96fa174..ea6b3bc 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -44,3 +44,5 @@ pjsip_unresolved_symbol.patch
 859911-pjsip-set-rtp-source-address-part2.patch
 
 AST-2017-004.patch
+AST-2017-005-13.13.diff
+AST-2017-006-13.diff

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-voip/asterisk.git



More information about the Pkg-voip-commits mailing list