debdiff for asterisk in Wheezy CVE-2014-6610 CVE-2014-4046 CVE-2014-2286 CVE-2014-4047 CVE-2014-8412 CVE-2014-8418 CVE-2015-3008

Thorsten Alteholz alteholz at debian.org
Sun Apr 24 20:17:59 UTC 2016


Ok, this time even with the attachement ...

On Sun, 24 Apr 2016, Thorsten Alteholz wrote:

> Hi everybody,
>
> attached is the debdiff to fix CVE-2014-6610 CVE-2014-4046 CVE-2014-2286 
> CVE-2014-4047 CVE-2014-8412 CVE-2014-8418 CVE-2015-3008 in the Wheezy version 
> of asterisk[1].
> As I am not able to test all those issues, I sent an email to debian-lts and 
> asked for testing. The packages are available at[2].
>
> @VoIP Team: how do you test such issues normally?
>
>
>  Thorsten
>
> [1] https://security-tracker.debian.org/tracker/source-package/asterisk
> [2] https://people.debian.org/~alteholz/packages/wheezy-lts/asterisk/
>
>
-------------- next part --------------
diff -Nru asterisk-1.8.13.1~dfsg1/debian/changelog asterisk-1.8.13.1~dfsg1/debian/changelog
--- asterisk-1.8.13.1~dfsg1/debian/changelog	2014-01-04 01:59:53.000000000 +0100
+++ asterisk-1.8.13.1~dfsg1/debian/changelog	2016-04-24 16:58:48.000000000 +0200
@@ -1,3 +1,57 @@
+asterisk (1:1.8.13.1~dfsg1-3+deb7u4) wheezy-security; urgency=high
+
+  * Non-maintainer upload by the Wheezy LTS Team. 
+  * CVE-2014-6610 (in AST-2014-010-11.diff) (Closes: #762164)
+    Asterisk Open Source 11.x before 11.12.1 and 12.x before 12.5.1 
+    and Certified Asterisk 11.6 before 11.6-cert6, when using the 
+    res_fax_spandsp module, allows remote authenticated users to 
+    cause a denial of service (crash) via an out of call message, 
+    which is not properly handled in the ReceiveFax dialplan 
+    application.
+  * CVE-2014-4046 (in AST-2014-006-11.6.diff)
+    Asterisk Open Source 11.x before 11.10.1 and 12.x before 12.3.1 
+    and Certified Asterisk 11.6 before 11.6-cert3 allows remote 
+    authenticated Manager users to execute arbitrary shell commands 
+    via a MixMonitor action.
+  * CVE-2014-2286 (in AST-2014-001-1.8.15.diff) (Closes: #741313)
+    main/http.c in Asterisk Open Source 1.8.x before 1.8.26.1, 11.8.x 
+    before 11.8.1, and 12.1.x before 12.1.1, and Certified Asterisk 
+    1.8.x before 1.8.15-cert5 and 11.6 before 11.6-cert2, allows remote 
+    attackers to cause a denial of service (stack consumption) and 
+    possibly execute arbitrary code via an HTTP request with a large 
+    number of Cookie headers.
+  * CVE-2014-4047 (in AST-2014-007-1.8.15.diff)
+    Asterisk Open Source 1.8.x before 1.8.28.1, 11.x before 11.10.1, 
+    and 12.x before 12.3.1 and Certified Asterisk 1.8.15 before 
+    1.8.15-cert6 and 11.6 before 11.6-cert3 allows remote attackers 
+    to cause a denial of service (connection consumption) via a large 
+    number of (1) inactive or (2) incomplete HTTP connections.
+  * CVE-2014-8412 (in AST-2014-012-1.8.diff) (Closes: #771463)
+    The (1) VoIP channel drivers, (2) DUNDi, and (3) Asterisk Manager 
+    Interface (AMI) in Asterisk Open Source 1.8.x before 1.8.32.1, 
+    11.x before 11.14.1, 12.x before 12.7.1, and 13.x before 13.0.1 
+    and Certified Asterisk 1.8.28 before 1.8.28-cert3 and 11.6 before 
+    11.6-cert8 allows remote attackers to bypass the ACL restrictions 
+    via a packet with a source IP that does not share the address family 
+    as the first ACL entry.
+  * CVE-2014-8418 (in AST-2014-018-1.8.diff) (Closes: #771463)
+    The DB dialplan function in Asterisk Open Source 1.8.x before 1.8.32, 
+    11.x before 11.1.4.1, 12.x before 12.7.1, and 13.x before 13.0.1 and 
+    Certified Asterisk 1.8 before 1.8.28-cert8 and 11.6 before 11.6-cert8 
+    allows remote authenticated users to gain privileges via a call from
+    an external protocol, as demonstrated by the AMI protocol.
+  * CVE-2015-3008 (in AST-2015-003-1.8.diff) (Closes: #782411)
+    Asterisk Open Source 1.8 before 1.8.32.3, 11.x before 11.17.1, 12.x 
+    before 12.8.2, and 13.x before 13.3.2 and Certified Asterisk 1.8.28 
+    before 1.8.28-cert5, 11.6 before 11.6-cert11, and 13.1 before 
+    13.1-cert2, when registering a SIP TLS device, does not properly 
+    handle a null byte in a domain name in the subject's Common Name (CN) 
+    field of an X.509 certificate, which allows man-in-the-middle attackers 
+    to spoof arbitrary SSL servers via a crafted certificate issued by a 
+    legitimate Certification Authority.
+ 
+ -- Thorsten Alteholz <debian at alteholz.de>  Sun, 24 Apr 2016 16:03:02 +0200
+
 asterisk (1:1.8.13.1~dfsg1-3+deb7u3) stable-security; urgency=high
 
   * Bumped repackages tarball number: security and main had different copies
diff -Nru asterisk-1.8.13.1~dfsg1/debian/patches/AST-2014-001-1.8.15.diff asterisk-1.8.13.1~dfsg1/debian/patches/AST-2014-001-1.8.15.diff
--- asterisk-1.8.13.1~dfsg1/debian/patches/AST-2014-001-1.8.15.diff	1970-01-01 01:00:00.000000000 +0100
+++ asterisk-1.8.13.1~dfsg1/debian/patches/AST-2014-001-1.8.15.diff	2016-04-21 15:17:36.000000000 +0200
@@ -0,0 +1,135 @@
+Index: asterisk-1.8.13.1~dfsg1/main/http.c
+===================================================================
+--- asterisk-1.8.13.1~dfsg1.orig/main/http.c	2016-04-21 15:17:30.000000000 +0200
++++ asterisk-1.8.13.1~dfsg1/main/http.c	2016-04-21 15:17:30.000000000 +0200
+@@ -187,9 +187,7 @@
+ 			break;
+ 		}
+ 	}
+-	if (cookies) {
+-		ast_variables_destroy(cookies);
+-	}
++	ast_variables_destroy(cookies);
+ 	return mngid;
+ }
+ 
+@@ -683,7 +681,7 @@
+ 			prev = v;
+ 		}
+ 	}
+-	
++
+ done:
+ 	ast_free(buf);
+ 	return post_vars;
+@@ -822,12 +820,13 @@
+ }*/
+ #endif	/* DO_SSL */
+ 
+-static struct ast_variable *parse_cookies(char *cookies)
++static struct ast_variable *parse_cookies(const char *cookies)
+ {
++	char *parse = ast_strdupa(cookies);
+ 	char *cur;
+ 	struct ast_variable *vars = NULL, *var;
+ 
+-	while ((cur = strsep(&cookies, ";"))) {
++	while ((cur = strsep(&parse, ";"))) {
+ 		char *name, *val;
+ 
+ 		name = val = cur;
+@@ -857,21 +856,19 @@
+ /* get cookie from Request headers */
+ struct ast_variable *ast_http_get_cookies(struct ast_variable *headers)
+ {
+-	struct ast_variable *v, *cookies=NULL;
++	struct ast_variable *v, *cookies = NULL;
+ 
+ 	for (v = headers; v; v = v->next) {
+-		if (!strncasecmp(v->name, "Cookie", 6)) {
+-			char *tmp = ast_strdupa(v->value);
+-			if (cookies) {
+-				ast_variables_destroy(cookies);
+-			}
+-
+-			cookies = parse_cookies(tmp);
++		if (!strcasecmp(v->name, "Cookie")) {
++			ast_variables_destroy(cookies);
++			cookies = parse_cookies(v->value);
+ 		}
+ 	}
+ 	return cookies;
+ }
+ 
++/*! Limit the number of request headers in case the sender is being ridiculous. */
++#define MAX_HTTP_REQUEST_HEADERS	100
+ 
+ static void *httpd_helper_thread(void *data)
+ {
+@@ -882,6 +879,7 @@
+ 	struct ast_variable *tail = headers;
+ 	char *uri, *method;
+ 	enum ast_http_method http_method = AST_HTTP_UNKNOWN;
++	int remaining_headers;
+ 
+ 	if (ast_atomic_fetchadd_int(&session_count, +1) >= session_limit) {
+ 		goto done;
+@@ -916,9 +914,13 @@
+ 		if (*c) {
+ 			*c = '\0';
+ 		}
++	} else {
++		ast_http_error(ser, 400, "Bad Request", "Invalid Request");
++		goto done;
+ 	}
+ 
+ 	/* process "Request Headers" lines */
++	remaining_headers = MAX_HTTP_REQUEST_HEADERS;
+ 	while (fgets(header_line, sizeof(header_line), ser->f)) {
+ 		char *name, *value;
+ 
+@@ -941,6 +943,11 @@
+ 
+ 		ast_trim_blanks(name);
+ 
++		if (!remaining_headers--) {
++			/* Too many headers. */
++			ast_http_error(ser, 413, "Request Entity Too Large", "Too many headers");
++			goto done;
++		}
+ 		if (!headers) {
+ 			headers = ast_variable_new(name, value, __FILE__);
+ 			tail = headers;
+@@ -948,11 +955,17 @@
+ 			tail->next = ast_variable_new(name, value, __FILE__);
+ 			tail = tail->next;
+ 		}
+-	}
++		if (!tail) {
++			/*
++			 * Variable allocation failure.
++			 * Try to make some room.
++			 */
++			ast_variables_destroy(headers);
++			headers = NULL;
+ 
+-	if (!*uri) {
+-		ast_http_error(ser, 400, "Bad Request", "Invalid Request");
+-		goto done;
++			ast_http_error(ser, 500, "Server Error", "Out of memory");
++			goto done;
++		}
+ 	}
+ 
+ 	handle_uri(ser, uri, http_method, headers);
+@@ -961,9 +974,7 @@
+ 	ast_atomic_fetchadd_int(&session_count, -1);
+ 
+ 	/* clean up all the header information */
+-	if (headers) {
+-		ast_variables_destroy(headers);
+-	}
++	ast_variables_destroy(headers);
+ 
+ 	if (ser->f) {
+ 		fclose(ser->f);
diff -Nru asterisk-1.8.13.1~dfsg1/debian/patches/AST-2014-002-1.8.diff asterisk-1.8.13.1~dfsg1/debian/patches/AST-2014-002-1.8.diff
--- asterisk-1.8.13.1~dfsg1/debian/patches/AST-2014-002-1.8.diff	1970-01-01 01:00:00.000000000 +0100
+++ asterisk-1.8.13.1~dfsg1/debian/patches/AST-2014-002-1.8.diff	2016-04-23 22:22:46.000000000 +0200
@@ -0,0 +1,346 @@
+Index: channels/chan_sip.c
+===================================================================
+--- a/channels/chan_sip.c	(revision 409702)
++++ /bchannels/chan_sip.c	(working copy)
+@@ -23032,6 +23032,145 @@
+ 	return 0;
+ }
+ 
++/*
++ * \internal \brief Check Session Timers for an INVITE request
++ *
++ * \retval 0 ok
++ * \retval -1 failure
++ */
++static int handle_request_invite_st(struct sip_pvt *p, struct sip_request *req,
++		const char *required, int reinvite)
++{
++	const char *p_uac_se_hdr;       /* UAC's Session-Expires header string                      */
++	const char *p_uac_min_se;       /* UAC's requested Min-SE interval (char string)            */
++	int uac_max_se = -1;            /* UAC's Session-Expires in integer format                  */
++	int uac_min_se = -1;            /* UAC's Min-SE in integer format                           */
++	int st_active = FALSE;          /* Session-Timer on/off boolean                             */
++	int st_interval = 0;            /* Session-Timer negotiated refresh interval                */
++	enum st_refresher tmp_st_ref = SESSION_TIMER_REFRESHER_AUTO; /* Session-Timer refresher     */
++	int dlg_min_se = -1;
++	int dlg_max_se = global_max_se;
++	int rtn;
++
++	/* Session-Timers */
++	if ((p->sipoptions & SIP_OPT_TIMER)) {
++		enum st_refresher_param st_ref_param = SESSION_TIMER_REFRESHER_PARAM_UNKNOWN;
++
++		/* The UAC has requested session-timers for this session. Negotiate
++		the session refresh interval and who will be the refresher */
++		ast_debug(2, "Incoming INVITE with 'timer' option supported\n");
++
++		/* Allocate Session-Timers struct w/in the dialog */
++		if (!p->stimer) {
++			sip_st_alloc(p);
++		}
++
++		/* Parse the Session-Expires header */
++		p_uac_se_hdr = get_header(req, "Session-Expires");
++		if (!ast_strlen_zero(p_uac_se_hdr)) {
++			ast_debug(2, "INVITE also has \"Session-Expires\" header.\n");
++			rtn = parse_session_expires(p_uac_se_hdr, &uac_max_se, &st_ref_param);
++			tmp_st_ref = (st_ref_param == SESSION_TIMER_REFRESHER_PARAM_UAC) ? SESSION_TIMER_REFRESHER_THEM : SESSION_TIMER_REFRESHER_US;
++			if (rtn != 0) {
++				transmit_response_reliable(p, "400 Session-Expires Invalid Syntax", req);
++				return -1;
++			}
++		}
++
++		/* Parse the Min-SE header */
++		p_uac_min_se = get_header(req, "Min-SE");
++		if (!ast_strlen_zero(p_uac_min_se)) {
++			ast_debug(2, "INVITE also has \"Min-SE\" header.\n");
++			rtn = parse_minse(p_uac_min_se, &uac_min_se);
++			if (rtn != 0) {
++				transmit_response_reliable(p, "400 Min-SE Invalid Syntax", req);
++				return -1;
++			}
++		}
++
++		dlg_min_se = st_get_se(p, FALSE);
++		switch (st_get_mode(p, 1)) {
++		case SESSION_TIMER_MODE_ACCEPT:
++		case SESSION_TIMER_MODE_ORIGINATE:
++			if (uac_max_se > 0 && uac_max_se < dlg_min_se) {
++				transmit_response_with_minse(p, "422 Session Interval Too Small", req, dlg_min_se);
++				return -1;
++			}
++
++			p->stimer->st_active_peer_ua = TRUE;
++			st_active = TRUE;
++			if (st_ref_param == SESSION_TIMER_REFRESHER_PARAM_UNKNOWN) {
++				tmp_st_ref = st_get_refresher(p);
++			}
++
++			dlg_max_se = st_get_se(p, TRUE);
++			if (uac_max_se > 0) {
++				if (dlg_max_se >= uac_min_se) {
++					st_interval = (uac_max_se < dlg_max_se) ? uac_max_se : dlg_max_se;
++				} else {
++					st_interval = uac_max_se;
++				}
++			} else if (uac_min_se > 0) {
++				st_interval = MAX(dlg_max_se, uac_min_se);
++			} else {
++				st_interval = dlg_max_se;
++			}
++			break;
++
++		case SESSION_TIMER_MODE_REFUSE:
++			if (p->reqsipoptions & SIP_OPT_TIMER) {
++				transmit_response_with_unsupported(p, "420 Option Disabled", req, required);
++				ast_log(LOG_WARNING, "Received SIP INVITE with supported but disabled option: %s\n", required);
++				return -1;
++			}
++			break;
++
++		default:
++			ast_log(LOG_ERROR, "Internal Error %d at %s:%d\n", st_get_mode(p, 1), __FILE__, __LINE__);
++			break;
++		}
++	} else {
++		/* The UAC did not request session-timers.  Asterisk (UAS), will now decide
++		(based on session-timer-mode in sip.conf) whether to run session-timers for
++		this session or not. */
++		switch (st_get_mode(p, 1)) {
++		case SESSION_TIMER_MODE_ORIGINATE:
++			st_active = TRUE;
++			st_interval = st_get_se(p, TRUE);
++			tmp_st_ref = SESSION_TIMER_REFRESHER_US;
++			p->stimer->st_active_peer_ua = (p->sipoptions & SIP_OPT_TIMER) ? TRUE : FALSE;
++			break;
++
++		default:
++			break;
++		}
++	}
++
++	if (reinvite == 0) {
++		/* Session-Timers: Start session refresh timer based on negotiation/config */
++		if (st_active == TRUE) {
++			p->stimer->st_active = TRUE;
++			p->stimer->st_interval = st_interval;
++			p->stimer->st_ref = tmp_st_ref;
++		}
++	} else {
++		if (p->stimer->st_active == TRUE) {
++			/* Session-Timers:  A re-invite request sent within a dialog will serve as
++			a refresh request, no matter whether the re-invite was sent for refreshing
++			the session or modifying it.*/
++			ast_debug (2, "Restarting session-timers on a refresh - %s\n", p->callid);
++
++			/* The UAC may be adjusting the session-timers mid-session */
++			if (st_interval > 0) {
++				p->stimer->st_interval = st_interval;
++				p->stimer->st_ref      = tmp_st_ref;
++			}
++		}
++	}
++
++	return 0;
++}
++
+ /*!
+  * \brief Handle incoming INVITE request
+  * \note If the INVITE has a Replaces header, it is part of an
+@@ -23051,19 +23190,9 @@
+ 	struct ast_channel *c = NULL;		/* New channel */
+ 	struct sip_peer *authpeer = NULL;	/* Matching Peer */
+ 	int reinvite = 0;
+-	int rtn;
+ 	struct ast_party_redirecting redirecting;
+ 	struct ast_set_party_redirecting update_redirecting;
+ 
+-	const char *p_uac_se_hdr;       /* UAC's Session-Expires header string                      */
+-	const char *p_uac_min_se;       /* UAC's requested Min-SE interval (char string)            */
+-	int uac_max_se = -1;            /* UAC's Session-Expires in integer format                  */
+-	int uac_min_se = -1;            /* UAC's Min-SE in integer format                           */
+-	int st_active = FALSE;          /* Session-Timer on/off boolean                             */
+-	int st_interval = 0;            /* Session-Timer negotiated refresh interval                */
+-	enum st_refresher tmp_st_ref = SESSION_TIMER_REFRESHER_AUTO; /* Session-Timer refresher     */
+-	int dlg_min_se = -1;
+-	int dlg_max_se = global_max_se;
+ 	struct {
+ 		char exten[AST_MAX_EXTENSION];
+ 		char context[AST_MAX_CONTEXT];
+@@ -23543,6 +23672,14 @@
+ 			/* Initialize our tag */
+ 
+ 			make_our_tag(p);
++
++			if (handle_request_invite_st(p, req, required, reinvite)) {
++				p->invitestate = INV_COMPLETED;
++				sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
++				res = -1;
++				goto request_invite_cleanup;
++			}
++
+ 			/* First invitation - create the channel.  Allocation
+ 			 * failures are handled below. */
+ 			c = sip_new(p, AST_STATE_DOWN, S_OR(p->peername, NULL), NULL);
+@@ -23575,6 +23712,16 @@
+ 		}
+ 		if (!req->ignore)
+ 			reinvite = 1;
++
++		if (handle_request_invite_st(p, req, required, reinvite)) {
++			p->invitestate = INV_COMPLETED;
++			if (!p->lastinvite) {
++				sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
++			}
++			res = -1;
++			goto request_invite_cleanup;
++		}
++
+ 		c = p->owner;
+ 		change_redirecting_information(p, req, &redirecting, &update_redirecting, FALSE); /*Will return immediately if no Diversion header is present */
+ 		if (c) {
+@@ -23583,140 +23730,10 @@
+ 		ast_party_redirecting_free(&redirecting);
+ 	}
+ 
+-	/* Session-Timers */
+-	if ((p->sipoptions & SIP_OPT_TIMER)) {
+-		enum st_refresher_param st_ref_param = SESSION_TIMER_REFRESHER_PARAM_UNKNOWN;
+-
+-		/* The UAC has requested session-timers for this session. Negotiate
+-		the session refresh interval and who will be the refresher */
+-		ast_debug(2, "Incoming INVITE with 'timer' option supported\n");
+-
+-		/* Allocate Session-Timers struct w/in the dialog */
+-		if (!p->stimer)
+-			sip_st_alloc(p);
+-
+-		/* Parse the Session-Expires header */
+-		p_uac_se_hdr = get_header(req, "Session-Expires");
+-		if (!ast_strlen_zero(p_uac_se_hdr)) {
+-			ast_debug(2, "INVITE also has \"Session-Expires\" header.\n");
+-			rtn = parse_session_expires(p_uac_se_hdr, &uac_max_se, &st_ref_param);
+-			tmp_st_ref = (st_ref_param == SESSION_TIMER_REFRESHER_PARAM_UAC) ? SESSION_TIMER_REFRESHER_THEM : SESSION_TIMER_REFRESHER_US;
+-			if (rtn != 0) {
+-				transmit_response_reliable(p, "400 Session-Expires Invalid Syntax", req);
+-				p->invitestate = INV_COMPLETED;
+-				if (!p->lastinvite) {
+-					sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
+-				}
+-				res = -1;
+-				goto request_invite_cleanup;
+-			}
+-		}
+-
+-		/* Parse the Min-SE header */
+-		p_uac_min_se = get_header(req, "Min-SE");
+-		if (!ast_strlen_zero(p_uac_min_se)) {
+-			ast_debug(2, "INVITE also has \"Min-SE\" header.\n");
+-			rtn = parse_minse(p_uac_min_se, &uac_min_se);
+-			if (rtn != 0) {
+-				transmit_response_reliable(p, "400 Min-SE Invalid Syntax", req);
+-				p->invitestate = INV_COMPLETED;
+-				if (!p->lastinvite) {
+-					sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
+-				}
+-				res = -1;
+-				goto request_invite_cleanup;
+-			}
+-		}
+-
+-		dlg_min_se = st_get_se(p, FALSE);
+-		switch (st_get_mode(p, 1)) {
+-		case SESSION_TIMER_MODE_ACCEPT:
+-		case SESSION_TIMER_MODE_ORIGINATE:
+-			if (uac_max_se > 0 && uac_max_se < dlg_min_se) {
+-				transmit_response_with_minse(p, "422 Session Interval Too Small", req, dlg_min_se);
+-				p->invitestate = INV_COMPLETED;
+-				if (!p->lastinvite) {
+-					sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
+-				}
+-				res = -1;
+-				goto request_invite_cleanup;
+-			}
+-
+-			p->stimer->st_active_peer_ua = TRUE;
+-			st_active = TRUE;
+-			if (st_ref_param == SESSION_TIMER_REFRESHER_PARAM_UNKNOWN) {
+-				tmp_st_ref = st_get_refresher(p);
+-			}
+-
+-			dlg_max_se = st_get_se(p, TRUE);
+-			if (uac_max_se > 0) {
+-				if (dlg_max_se >= uac_min_se) {
+-					st_interval = (uac_max_se < dlg_max_se) ? uac_max_se : dlg_max_se;
+-				} else {
+-					st_interval = uac_max_se;
+-				}
+-			} else if (uac_min_se > 0) {
+-				st_interval = MAX(dlg_max_se, uac_min_se);
+-			} else {
+-				st_interval = dlg_max_se;
+-			}
+-			break;
+-
+-		case SESSION_TIMER_MODE_REFUSE:
+-			if (p->reqsipoptions & SIP_OPT_TIMER) {
+-				transmit_response_with_unsupported(p, "420 Option Disabled", req, required);
+-				ast_log(LOG_WARNING, "Received SIP INVITE with supported but disabled option: %s\n", required);
+-				p->invitestate = INV_COMPLETED;
+-				if (!p->lastinvite) {
+-					sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
+-				}
+-				res = -1;
+-				goto request_invite_cleanup;
+-			}
+-			break;
+-
+-		default:
+-			ast_log(LOG_ERROR, "Internal Error %d at %s:%d\n", st_get_mode(p, 1), __FILE__, __LINE__);
+-			break;
+-		}
+-	} else {
+-		/* The UAC did not request session-timers.  Asterisk (UAS), will now decide
+-		(based on session-timer-mode in sip.conf) whether to run session-timers for
+-		this session or not. */
+-		switch (st_get_mode(p, 1)) {
+-		case SESSION_TIMER_MODE_ORIGINATE:
+-			st_active = TRUE;
+-			st_interval = st_get_se(p, TRUE);
+-			tmp_st_ref = SESSION_TIMER_REFRESHER_US;
+-			p->stimer->st_active_peer_ua = (p->sipoptions & SIP_OPT_TIMER) ? TRUE : FALSE;
+-			break;
+-
+-		default:
+-			break;
+-		}
+-	}
+-
+-	if (reinvite == 0) {
+-		/* Session-Timers: Start session refresh timer based on negotiation/config */
+-		if (st_active == TRUE) {
+-			p->stimer->st_active = TRUE;
+-			p->stimer->st_interval = st_interval;
+-			p->stimer->st_ref = tmp_st_ref;
++	if (p->stimer->st_active == TRUE) {
++		if (reinvite == 0) {
+ 			start_session_timer(p);
+-		}
+-	} else {
+-		if (p->stimer->st_active == TRUE) {
+-			/* Session-Timers:  A re-invite request sent within a dialog will serve as
+-			a refresh request, no matter whether the re-invite was sent for refreshing
+-			the session or modifying it.*/
+-			ast_debug (2, "Restarting session-timers on a refresh - %s\n", p->callid);
+-
+-			/* The UAC may be adjusting the session-timers mid-session */
+-			if (st_interval > 0) {
+-				p->stimer->st_interval = st_interval;
+-				p->stimer->st_ref      = tmp_st_ref;
+-			}
+-
++		} else {
+ 			restart_session_timer(p);
+ 		}
+ 	}
diff -Nru asterisk-1.8.13.1~dfsg1/debian/patches/AST-2014-006-11.6.diff asterisk-1.8.13.1~dfsg1/debian/patches/AST-2014-006-11.6.diff
--- asterisk-1.8.13.1~dfsg1/debian/patches/AST-2014-006-11.6.diff	1970-01-01 01:00:00.000000000 +0100
+++ asterisk-1.8.13.1~dfsg1/debian/patches/AST-2014-006-11.6.diff	2016-04-20 16:20:49.000000000 +0200
@@ -0,0 +1,13 @@
+Index: asterisk-1.8.13.1~dfsg1/apps/app_mixmonitor.c
+===================================================================
+--- asterisk-1.8.13.1~dfsg1.orig/apps/app_mixmonitor.c	2016-04-20 16:20:11.000000000 +0200
++++ asterisk-1.8.13.1~dfsg1/apps/app_mixmonitor.c	2016-04-20 16:20:43.000000000 +0200
+@@ -725,7 +725,7 @@
+ 	ast_cli_register_multiple(cli_mixmonitor, ARRAY_LEN(cli_mixmonitor));
+ 	res = ast_register_application_xml(app, mixmonitor_exec);
+ 	res |= ast_register_application_xml(stop_app, stop_mixmonitor_exec);
+-	res |= ast_manager_register_xml("MixMonitorMute", 0, manager_mute_mixmonitor);
++	res |= ast_manager_register_xml("MixMonitorMute", EVENT_FLAG_SYSTEM | EVENT_FLAG_CALL, manager_mute_mixmonitor);
+ 
+ 	return res;
+ }
diff -Nru asterisk-1.8.13.1~dfsg1/debian/patches/AST-2014-007-1.8.15.diff asterisk-1.8.13.1~dfsg1/debian/patches/AST-2014-007-1.8.15.diff
--- asterisk-1.8.13.1~dfsg1/debian/patches/AST-2014-007-1.8.15.diff	1970-01-01 01:00:00.000000000 +0100
+++ asterisk-1.8.13.1~dfsg1/debian/patches/AST-2014-007-1.8.15.diff	2016-04-23 19:42:25.000000000 +0200
@@ -0,0 +1,1172 @@
+Index: asterisk-1.8.13.1~dfsg1/channels/chan_sip.c
+===================================================================
+--- asterisk-1.8.13.1~dfsg1.orig/channels/chan_sip.c	2016-04-23 19:30:01.000000000 +0200
++++ asterisk-1.8.13.1~dfsg1/channels/chan_sip.c	2016-04-23 19:30:01.000000000 +0200
+@@ -2585,11 +2585,15 @@
+ 		goto cleanup;
+ 	}
+ 
++	ast_tcptls_stream_set_timeout_sequence(tcptls_session->stream_cookie, ast_tvnow(),
++		tcptls_session->client ? -1 : (authtimeout * 1000));
++
+ 	for (;;) {
+ 		struct ast_str *str_save;
+ 
+ 		if (!tcptls_session->client && req.authenticated && !authenticated) {
+ 			authenticated = 1;
++			ast_tcptls_stream_set_timeout_disable(tcptls_session->stream_cookie);
+ 			ast_atomic_fetchadd_int(&unauth_sessions, -1);
+ 		}
+ 
+Index: asterisk-1.8.13.1~dfsg1/include/asterisk/time.h
+===================================================================
+--- asterisk-1.8.13.1~dfsg1.orig/include/asterisk/time.h	2016-04-23 19:30:01.000000000 +0200
++++ asterisk-1.8.13.1~dfsg1/include/asterisk/time.h	2016-04-23 19:30:01.000000000 +0200
+@@ -152,6 +152,20 @@
+ struct timeval ast_tvsub(struct timeval a, struct timeval b);
+ 
+ /*!
++ * \brief Calculate remaining milliseconds given a starting timestamp
++ * and upper bound
++ *
++ * If the upper bound is negative, then this indicates that there is no
++ * upper bound on the amount of time to wait. This will result in a
++ * negative return.
++ *
++ * \param start When timing started being calculated
++ * \param max_ms The maximum number of milliseconds to wait from start. May be negative.
++ * \return The number of milliseconds left to wait for. May be negative.
++ */
++int ast_remaining_ms(struct timeval start, int max_ms);
++
++/*!
+  * \brief Returns a timeval from sec, usec
+  */
+ AST_INLINE_API(
+Index: asterisk-1.8.13.1~dfsg1/include/asterisk/utils.h
+===================================================================
+--- asterisk-1.8.13.1~dfsg1.orig/include/asterisk/utils.h	2016-04-23 19:30:01.000000000 +0200
++++ asterisk-1.8.13.1~dfsg1/include/asterisk/utils.h	2016-04-23 19:30:01.000000000 +0200
+@@ -337,6 +337,7 @@
+ 
+ int ast_utils_init(void);
+ int ast_wait_for_input(int fd, int ms);
++int ast_wait_for_output(int fd, int ms);
+ 
+ /*!
+ 	\brief Try to write string, but wait no more than ms milliseconds
+Index: asterisk-1.8.13.1~dfsg1/include/asterisk/tcptls.h
+===================================================================
+--- asterisk-1.8.13.1~dfsg1.orig/include/asterisk/tcptls.h	2016-04-23 19:30:01.000000000 +0200
++++ asterisk-1.8.13.1~dfsg1/include/asterisk/tcptls.h	2016-04-23 19:30:01.000000000 +0200
+@@ -136,6 +136,51 @@
+ 	const char *name;
+ };
+ 
++struct ast_tcptls_stream;
++
++/*!
++ * \brief Disable the TCP/TLS stream timeout timer.
++ *
++ * \param stream TCP/TLS stream control data.
++ *
++ * \return Nothing
++ */
++void ast_tcptls_stream_set_timeout_disable(struct ast_tcptls_stream *stream);
++
++/*!
++ * \brief Set the TCP/TLS stream inactivity timeout timer.
++ *
++ * \param stream TCP/TLS stream control data.
++ * \param timeout Number of milliseconds to wait for data transfer with the peer.
++ *
++ * \details This is basically how much time we are willing to spend
++ * in an I/O call before we declare the peer unresponsive.
++ *
++ * \note Setting timeout to -1 disables the timeout.
++ * \note Setting this timeout replaces the I/O sequence timeout timer.
++ *
++ * \return Nothing
++ */
++void ast_tcptls_stream_set_timeout_inactivity(struct ast_tcptls_stream *stream, int timeout);
++
++/*!
++ * \brief Set the TCP/TLS stream I/O sequence timeout timer.
++ *
++ * \param stream TCP/TLS stream control data.
++ * \param start Time the I/O sequence timer starts.
++ * \param timeout Number of milliseconds from the start time before timeout.
++ *
++ * \details This is how much time are we willing to allow the peer
++ * to complete an operation that can take several I/O calls.  The
++ * main use is as an authentication timer with us.
++ *
++ * \note Setting timeout to -1 disables the timeout.
++ * \note Setting this timeout replaces the inactivity timeout timer.
++ *
++ * \return Nothing
++ */
++void ast_tcptls_stream_set_timeout_sequence(struct ast_tcptls_stream *stream, struct timeval start, int timeout);
++
+ /*
+  * describes a server instance
+  */
+@@ -149,6 +194,8 @@
+ 	struct ast_tcptls_session_args *parent;
+ 	/*! XXX Why do we still use this lock when this struct is allocated as an ao2 object which has its own lock? */
+ 	ast_mutex_t lock;
++	/*! ao2 FILE stream cookie object associated with f. */
++	struct ast_tcptls_stream *stream_cookie;
+ };
+ 
+ #if defined(HAVE_FUNOPEN)
+Index: asterisk-1.8.13.1~dfsg1/main/utils.c
+===================================================================
+--- asterisk-1.8.13.1~dfsg1.orig/main/utils.c	2016-04-23 19:30:01.000000000 +0200
++++ asterisk-1.8.13.1~dfsg1/main/utils.c	2016-04-23 19:30:01.000000000 +0200
+@@ -792,7 +792,7 @@
+ 	ast_mutex_t *lock;
+ 	struct ast_lock_track *lt;
+ 	
+-	ast_str_append(str, 0, "=== ---> %sLock #%d (%s): %s %d %s %s %p (%d)\n", 
++	ast_str_append(str, 0, "=== ---> %sLock #%d (%s): %s %d %s %s %p (%d)\n",
+ 				   lock_info->locks[i].pending > 0 ? "Waiting for " : 
+ 				   lock_info->locks[i].pending < 0 ? "Tried and failed to get " : "", i,
+ 				   lock_info->locks[i].file, 
+@@ -1087,13 +1087,24 @@
+ int ast_wait_for_input(int fd, int ms)
+ {
+ 	struct pollfd pfd[1];
++
++	memset(pfd, 0, sizeof(pfd));
++	pfd[0].fd = fd;
++	pfd[0].events = POLLIN | POLLPRI;
++	return ast_poll(pfd, 1, ms);
++}
++
++int ast_wait_for_output(int fd, int ms)
++{
++	struct pollfd pfd[1];
++
+ 	memset(pfd, 0, sizeof(pfd));
+ 	pfd[0].fd = fd;
+-	pfd[0].events = POLLIN|POLLPRI;
++	pfd[0].events = POLLOUT;
+ 	return ast_poll(pfd, 1, ms);
+ }
+ 
+-static int ast_wait_for_output(int fd, int timeoutms)
++static int wait_for_output(int fd, int timeoutms)
+ {
+ 	struct pollfd pfd = {
+ 		.fd = fd,
+@@ -1153,7 +1164,7 @@
+ 	int elapsed = 0;
+ 
+ 	while (len) {
+-		if (ast_wait_for_output(fd, timeoutms - elapsed)) {
++		if (wait_for_output(fd, timeoutms - elapsed)) {
+ 			return -1;
+ 		}
+ 
+@@ -1194,7 +1205,7 @@
+ 	int elapsed = 0;
+ 
+ 	while (len) {
+-		if (ast_wait_for_output(fd, timeoutms - elapsed)) {
++		if (wait_for_output(fd, timeoutms - elapsed)) {
+ 			/* poll returned a fatal error, so bail out immediately. */
+ 			return -1;
+ 		}
+@@ -1425,6 +1436,23 @@
+ 	}
+ 	return a;
+ }
++
++int ast_remaining_ms(struct timeval start, int max_ms)
++{
++	int ms;
++
++	if (max_ms < 0) {
++		ms = max_ms;
++	} else {
++		ms = max_ms - ast_tvdiff_ms(ast_tvnow(), start);
++		if (ms < 0) {
++			ms = 0;
++		}
++	}
++
++	return ms;
++}
++
+ #undef ONE_MILLION
+ 
+ /*! \brief glibc puts a lock inside random(3), so that the results are thread-safe.
+Index: asterisk-1.8.13.1~dfsg1/main/manager.c
+===================================================================
+--- asterisk-1.8.13.1~dfsg1.orig/main/manager.c	2016-04-23 19:30:01.000000000 +0200
++++ asterisk-1.8.13.1~dfsg1/main/manager.c	2016-04-23 19:30:01.000000000 +0200
+@@ -878,7 +878,6 @@
+ 
+ static const int DEFAULT_ENABLED			= 0;	/*!< Default setting for manager to be enabled */
+ static const int DEFAULT_WEBENABLED			= 0;	/*!< Default setting for the web interface to be enabled */
+-static const int DEFAULT_BLOCKSOCKETS		= 0;	/*!< Default setting for block-sockets */
+ static const int DEFAULT_DISPLAYCONNECTS	= 1;	/*!< Default setting for displaying manager connections */
+ static const int DEFAULT_TIMESTAMPEVENTS	= 0;	/*!< Default setting for timestampevents */	
+ static const int DEFAULT_HTTPTIMEOUT 		= 60;	/*!< Default manager http timeout */
+@@ -902,7 +901,6 @@
+ #define DEFAULT_REALM		"asterisk"
+ static char global_realm[MAXHOSTNAMELEN];	/*!< Default realm */
+ 
+-static int block_sockets;
+ static int unauth_sessions = 0;
+ 
+ 
+@@ -1316,6 +1314,7 @@
+ 	}
+ 
+ 	if (session->f != NULL) {
++		fflush(session->f);
+ 		fclose(session->f);
+ 	}
+ 	if (eqe) {
+@@ -4956,12 +4955,9 @@
+ 		ast_log(LOG_WARNING, "Failed to set manager tcp connection to TCP_NODELAY, getprotobyname(\"tcp\") failed\nSome manager actions may be slow to respond.\n");
+ 	}
+ 
++	/* make sure socket is non-blocking */
+ 	flags = fcntl(ser->fd, F_GETFL);
+-	if (!block_sockets) { /* make sure socket is non-blocking */
+-		flags |= O_NONBLOCK;
+-	} else {
+-		flags &= ~O_NONBLOCK;
+-	}
++	flags |= O_NONBLOCK;
+ 	fcntl(ser->fd, F_SETFL, flags);
+ 
+ 	ao2_lock(session);
+@@ -4987,11 +4983,17 @@
+ 	}
+ 	ao2_unlock(session);
+ 
++	ast_tcptls_stream_set_timeout_sequence(ser->stream_cookie,
++		ast_tvnow(), authtimeout * 1000);
++
+ 	astman_append(&s, "Asterisk Call Manager/%s\r\n", AMI_VERSION);	/* welcome prompt */
+ 	for (;;) {
+ 		if ((res = do_message(&s)) < 0 || s.write_error) {
+ 			break;
+ 		}
++		if (session->authenticated) {
++			ast_tcptls_stream_set_timeout_disable(ser->stream_cookie);
++		}
+ 	}
+ 	/* session is over, explain why and terminate */
+ 	if (session->authenticated) {
+@@ -5746,6 +5748,30 @@
+ 	}
+ }
+ 
++static void close_mansession_file(struct mansession *s)
++{
++	if (s->f) {
++		if (fclose(s->f)) {
++			ast_log(LOG_ERROR, "fclose() failed: %s\n", strerror(errno));
++		}
++		s->f = NULL;
++		s->fd = -1;
++	} else if (s->fd != -1) {
++		/*
++		 * Issuing shutdown() is necessary here to avoid a race
++		 * condition where the last data written may not appear
++		 * in the TCP stream.  See ASTERISK-23548
++		 */
++		shutdown(s->fd, SHUT_RDWR);
++		if (close(s->fd)) {
++			ast_log(LOG_ERROR, "close() failed: %s\n", strerror(errno));
++		}
++		s->fd = -1;
++	} else {
++		ast_log(LOG_ERROR, "Attempted to close file/file descriptor on mansession without a valid file or file descriptor.\n");
++	}
++}
++
+ static void process_output(struct mansession *s, struct ast_str **out, struct ast_variable *params, enum output_format format)
+ {
+ 	char *buf;
+@@ -5773,20 +5799,7 @@
+ 		xml_translate(out, "", params, format);
+ 	}
+ 
+-	if (s->f) {
+-		if (fclose(s->f)) {
+-			ast_log(LOG_ERROR, "fclose() failed: %s\n", strerror(errno));
+-		}
+-		s->f = NULL;
+-		s->fd = -1;
+-	} else if (s->fd != -1) {
+-		if (close(s->fd)) {
+-			ast_log(LOG_ERROR, "close() failed: %s\n", strerror(errno));
+-		}
+-		s->fd = -1;
+-	} else {
+-		ast_log(LOG_ERROR, "process output attempted to close file/file descriptor on mansession without a valid file or file descriptor.\n");
+-	}
++	close_mansession_file(s);
+ }
+ 
+ static int generic_http_callback(struct ast_tcptls_session_instance *ser,
+@@ -6504,7 +6517,6 @@
+ 	ast_cli(a->fd, FORMAT, "Timestamp events:", AST_CLI_YESNO(timestampevents));
+ 	ast_cli(a->fd, FORMAT, "Channel vars:", S_OR(manager_channelvars, ""));
+ 	ast_cli(a->fd, FORMAT, "Debug:", AST_CLI_YESNO(manager_debug));
+-	ast_cli(a->fd, FORMAT, "Block sockets:", AST_CLI_YESNO(block_sockets));
+ #undef FORMAT
+ #undef FORMAT2
+ 
+@@ -6626,7 +6638,6 @@
+ 	manager_debug = DEFAULT_MANAGERDEBUG;
+ 	displayconnects = DEFAULT_DISPLAYCONNECTS;
+ 	broken_events_action = DEFAULT_BROKENEVENTSACTION;
+-	block_sockets = DEFAULT_BLOCKSOCKETS;
+ 	timestampevents = DEFAULT_TIMESTAMPEVENTS;
+ 	httptimeout = DEFAULT_HTTPTIMEOUT;
+ 	authtimeout = DEFAULT_AUTHTIMEOUT;
+@@ -6674,8 +6685,6 @@
+ 
+ 		if (!strcasecmp(var->name, "enabled")) {
+ 			manager_enabled = ast_true(val);
+-		} else if (!strcasecmp(var->name, "block-sockets")) {
+-			block_sockets = ast_true(val);
+ 		} else if (!strcasecmp(var->name, "webenabled")) {
+ 			webmanager_enabled = ast_true(val);
+ 		} else if (!strcasecmp(var->name, "port")) {
+Index: asterisk-1.8.13.1~dfsg1/main/http.c
+===================================================================
+--- asterisk-1.8.13.1~dfsg1.orig/main/http.c	2016-04-23 19:30:01.000000000 +0200
++++ asterisk-1.8.13.1~dfsg1/main/http.c	2016-04-23 19:30:01.000000000 +0200
+@@ -60,6 +60,7 @@
+ 
+ #define MAX_PREFIX 80
+ #define DEFAULT_SESSION_LIMIT 100
++#define DEFAULT_SESSION_INACTIVITY 30000	/* (ms) Idle time waiting for data. */
+ 
+ #define DEFAULT_HTTP_PORT 8088
+ #define DEFAULT_HTTPS_PORT 8089
+@@ -70,6 +71,7 @@
+ #endif
+ 
+ static int session_limit = DEFAULT_SESSION_LIMIT;
++static int session_inactivity = DEFAULT_SESSION_INACTIVITY;
+ static int session_count = 0;
+ 
+ static struct ast_tls_config http_tls_cfg;
+@@ -260,12 +262,12 @@
+ 		goto out404;
+ 	}
+ 
+-	fd = open(path, O_RDONLY);
+-	if (fd < 0) {
++	if (strstr(path, "/private/") && !astman_is_authed(ast_http_manid_from_vars(headers))) {
+ 		goto out403;
+ 	}
+ 
+-	if (strstr(path, "/private/") && !astman_is_authed(ast_http_manid_from_vars(headers))) {
++	fd = open(path, O_RDONLY);
++	if (fd < 0) {
+ 		goto out403;
+ 	}
+ 
+@@ -288,6 +290,7 @@
+ 	}
+ 
+ 	if ( (http_header = ast_str_create(255)) == NULL) {
++		close(fd);
+ 		return -1;
+ 	}
+ 
+@@ -404,7 +407,7 @@
+ 
+ 	/* calc content length */
+ 	if (out) {
+-		content_length += strlen(ast_str_buffer(out));
++		content_length += ast_str_strlen(out);
+ 	}
+ 
+ 	if (fd) {
+@@ -431,8 +434,10 @@
+ 
+ 	/* send content */
+ 	if (method != AST_HTTP_HEAD || status_code >= 400) {
+-		if (out) {
+-			fprintf(ser->f, "%s", ast_str_buffer(out));
++		if (out && ast_str_strlen(out)) {
++			if (fwrite(ast_str_buffer(out), ast_str_strlen(out), 1, ser->f) != 1) {
++				ast_log(LOG_ERROR, "fwrite() failed: %s\n", strerror(errno));
++			}
+ 		}
+ 
+ 		if (fd) {
+@@ -454,8 +459,7 @@
+ 		ast_free(out);
+ 	}
+ 
+-	fclose(ser->f);
+-	ser->f = 0;
++	ast_tcptls_close_session_file(ser);
+ 	return;
+ }
+ 
+@@ -880,12 +884,20 @@
+ 	char *uri, *method;
+ 	enum ast_http_method http_method = AST_HTTP_UNKNOWN;
+ 	int remaining_headers;
++	int flags;
+ 
+ 	if (ast_atomic_fetchadd_int(&session_count, +1) >= session_limit) {
+ 		goto done;
+ 	}
+ 
+-	if (!fgets(buf, sizeof(buf), ser->f)) {
++	/* make sure socket is non-blocking */
++	flags = fcntl(ser->fd, F_GETFL);
++	flags |= O_NONBLOCK;
++	fcntl(ser->fd, F_SETFL, flags);
++
++	ast_tcptls_stream_set_timeout_inactivity(ser->stream_cookie, session_inactivity);
++
++	if (!fgets(buf, sizeof(buf), ser->f) || feof(ser->f)) {
+ 		goto done;
+ 	}
+ 
+@@ -921,12 +933,19 @@
+ 
+ 	/* process "Request Headers" lines */
+ 	remaining_headers = MAX_HTTP_REQUEST_HEADERS;
+-	while (fgets(header_line, sizeof(header_line), ser->f)) {
+-		char *name, *value;
++	for (;;) {
++		char *name;
++		char *value;
++
++		if (!fgets(header_line, sizeof(header_line), ser->f) || feof(ser->f)) {
++			ast_http_error(ser, 400, "Bad Request", "Timeout");
++			goto done;
++		}
+ 
+ 		/* Trim trailing characters */
+ 		ast_trim_blanks(header_line);
+ 		if (ast_strlen_zero(header_line)) {
++			/* A blank line ends the request header section. */
+ 			break;
+ 		}
+ 
+@@ -977,7 +996,7 @@
+ 	ast_variables_destroy(headers);
+ 
+ 	if (ser->f) {
+-		fclose(ser->f);
++		ast_tcptls_close_session_file(ser);
+ 	}
+ 	ao2_ref(ser, -1);
+ 	ser = NULL;
+@@ -1092,6 +1111,9 @@
+ 
+ 	ast_sockaddr_setnull(&https_desc.local_address);
+ 
++	session_limit = DEFAULT_SESSION_LIMIT;
++	session_inactivity = DEFAULT_SESSION_INACTIVITY;
++
+ 	if (cfg) {
+ 		v = ast_variable_browse(cfg, "general");
+ 		for (; v; v = v->next) {
+@@ -1133,6 +1155,12 @@
+ 					ast_log(LOG_WARNING, "Invalid %s '%s' at line %d of http.conf\n",
+ 							v->name, v->value, v->lineno);
+ 				}
++			} else if (!strcasecmp(v->name, "session_inactivity")) {
++				if (ast_parse_arg(v->value, PARSE_INT32 |PARSE_DEFAULT | PARSE_IN_RANGE,
++					&session_inactivity, DEFAULT_SESSION_INACTIVITY, 1, INT_MAX)) {
++					ast_log(LOG_WARNING, "Invalid %s '%s' at line %d of http.conf\n",
++						v->name, v->value, v->lineno);
++				}
+ 			} else {
+ 				ast_log(LOG_WARNING, "Ignoring unknown option '%s' in http.conf\n", v->name);
+ 			}
+Index: asterisk-1.8.13.1~dfsg1/main/tcptls.c
+===================================================================
+--- asterisk-1.8.13.1~dfsg1.orig/main/tcptls.c	2016-04-23 19:30:01.000000000 +0200
++++ asterisk-1.8.13.1~dfsg1/main/tcptls.c	2016-04-23 19:42:22.000000000 +0200
+@@ -46,92 +46,483 @@
+ #include "asterisk/astobj2.h"
+ #include "asterisk/pbx.h"
+ 
+-/*! \brief
+- * replacement read/write functions for SSL support.
+- * We use wrappers rather than SSL_read/SSL_write directly so
+- * we can put in some debugging.
+- */
++/*! ao2 object used for the FILE stream fopencookie()/funopen() cookie. */
++struct ast_tcptls_stream {
++	/*! SSL state if not NULL */
++	SSL *ssl;
++	/*!
++	 * \brief Start time from when an I/O sequence must complete
++	 * by struct ast_tcptls_stream.timeout.
++	 *
++	 * \note If struct ast_tcptls_stream.start.tv_sec is zero then
++	 * start time is the current I/O request.
++	 */
++	struct timeval start;
++	/*!
++	 * \brief The socket returned by accept().
++	 *
++	 * \note Set to -1 if the stream is closed.
++	 */
++	int fd;
++	/*!
++	 * \brief Timeout in ms relative to struct ast_tcptls_stream.start
++	 * to wait for an event on struct ast_tcptls_stream.fd.
++	 *
++	 * \note Set to -1 to disable timeout.
++	 * \note The socket needs to be set to non-blocking for the timeout
++	 * feature to work correctly.
++	 */
++	int timeout;
++};
+ 
+-#ifdef DO_SSL
+-static HOOK_T ssl_read(void *cookie, char *buf, LEN_T len)
++void ast_tcptls_stream_set_timeout_disable(struct ast_tcptls_stream *stream)
+ {
+-	int i = SSL_read(cookie, buf, len-1);
+-#if 0
+-	if (i >= 0)
+-		buf[i] = '\0';
+-	ast_verb(0, "ssl read size %d returns %d <%s>\n", (int)len, i, buf);
+-#endif
+-	return i;
++	ast_assert(stream != NULL);
++
++	stream->timeout = -1;
+ }
+ 
+-static HOOK_T ssl_write(void *cookie, const char *buf, LEN_T len)
++void ast_tcptls_stream_set_timeout_inactivity(struct ast_tcptls_stream *stream, int timeout)
+ {
+-#if 0
+-	char *s = alloca(len+1);
+-	strncpy(s, buf, len);
+-	s[len] = '\0';
+-	ast_verb(0, "ssl write size %d <%s>\n", (int)len, s);
+-#endif
+-	return SSL_write(cookie, buf, len);
++	ast_assert(stream != NULL);
++
++	stream->start.tv_sec = 0;
++	stream->timeout = timeout;
+ }
+ 
+-static int ssl_close(void *cookie)
++void ast_tcptls_stream_set_timeout_sequence(struct ast_tcptls_stream *stream, struct timeval start, int timeout)
+ {
+-	int cookie_fd = SSL_get_fd(cookie);
+-	int ret;
+-	if (cookie_fd > -1) {
+-		/*
+-		 * According to the TLS standard, it is acceptable for an application to only send its shutdown
+-		 * alert and then close the underlying connection without waiting for the peer's response (this
+-		 * way resources can be saved, as the process can already terminate or serve another connection).
+-		 */
+-		if ((ret = SSL_shutdown(cookie)) < 0) {
+-			ast_log(LOG_ERROR, "SSL_shutdown() failed: %d\n", SSL_get_error(cookie, ret));
+-		}
+-		SSL_free(cookie);
+-		/* adding shutdown(2) here has no added benefit */
+-		if (close(cookie_fd)) {
+-			ast_log(LOG_ERROR, "close() failed: %s\n", strerror(errno));
++	ast_assert(stream != NULL);
++
++	stream->start = start;
++	stream->timeout = timeout;
++}
++
++/*!
++ * \internal
++ * \brief fopencookie()/funopen() stream read function.
++ *
++ * \param cookie Stream control data.
++ * \param buf Where to put read data.
++ * \param size Size of the buffer.
++ *
++ * \retval number of bytes put into buf.
++ * \retval 0 on end of file.
++ * \retval -1 on error.
++ */
++static HOOK_T tcptls_stream_read(void *cookie, char *buf, LEN_T size)
++{
++	struct ast_tcptls_stream *stream = cookie;
++	struct timeval start;
++	int ms;
++	int res;
++
++	if (!size) {
++		/* You asked for no data you got no data. */
++		return 0;
++	}
++
++	if (!stream || stream->fd == -1) {
++		errno = EBADF;
++		return -1;
++	}
++
++	if (stream->start.tv_sec) {
++		start = stream->start;
++	} else {
++		start = ast_tvnow();
++	}
++
++#if defined(DO_SSL)
++	if (stream->ssl) {
++		for (;;) {
++			res = SSL_read(stream->ssl, buf, size);
++			if (0 < res) {
++				/* We read some payload data. */
++				return res;
++			}
++			switch (SSL_get_error(stream->ssl, res)) {
++			case SSL_ERROR_ZERO_RETURN:
++				/* Report EOF for a shutdown */
++				ast_debug(1, "TLS clean shutdown alert reading data\n");
++				return 0;
++			case SSL_ERROR_WANT_READ:
++				while ((ms = ast_remaining_ms(start, stream->timeout))) {
++					res = ast_wait_for_input(stream->fd, ms);
++					if (0 < res) {
++						/* Socket is ready to be read. */
++						break;
++					}
++					if (res < 0) {
++						if (errno == EINTR || errno == EAGAIN) {
++							/* Try again. */
++							continue;
++						}
++						ast_debug(1, "TLS socket error waiting for read data: %s\n",
++							strerror(errno));
++						return -1;
++					}
++				}
++				break;
++			case SSL_ERROR_WANT_WRITE:
++				while ((ms = ast_remaining_ms(start, stream->timeout))) {
++					res = ast_wait_for_output(stream->fd, ms);
++					if (0 < res) {
++						/* Socket is ready to be written. */
++						break;
++					}
++					if (res < 0) {
++						if (errno == EINTR || errno == EAGAIN) {
++							/* Try again. */
++							continue;
++						}
++						ast_debug(1, "TLS socket error waiting for write space: %s\n",
++							strerror(errno));
++						return -1;
++					}
++				}
++				break;
++			default:
++				/* Report EOF for an undecoded SSL or transport error. */
++				ast_debug(1, "TLS transport or SSL error reading data\n");
++				return 0;
++			}
++			if (!ms) {
++				/* Report EOF for a timeout */
++				ast_debug(1, "TLS timeout reading data\n");
++				return 0;
++			}
++ 		}
++	}
++#endif	/* defined(DO_SSL) */
++
++	for (;;) {
++		res = read(stream->fd, buf, size);
++		if (0 <= res) {
++			return res;
++ 		}
++		if (errno != EINTR && errno != EAGAIN) {
++			/* Not a retryable error. */
++			ast_debug(1, "TCP socket error reading data: %s\n",
++				strerror(errno));
++			return -1;
+ 		}
++		ms = ast_remaining_ms(start, stream->timeout);
++		if (!ms) {
++			/* Report EOF for a timeout */
++			ast_debug(1, "TCP timeout reading data\n");
++			return 0;
++		}
++		ast_wait_for_input(stream->fd, ms);
+ 	}
+-	return 0;
+ }
+-#endif	/* DO_SSL */
+ 
+-HOOK_T ast_tcptls_server_read(struct ast_tcptls_session_instance *tcptls_session, void *buf, size_t count)
++/*!
++ * \internal
++ * \brief fopencookie()/funopen() stream write function.
++ *
++ * \param cookie Stream control data.
++ * \param buf Where to get data to write.
++ * \param size Size of the buffer.
++ *
++ * \retval number of bytes written from buf.
++ * \retval -1 on error.
++ */
++static HOOK_T tcptls_stream_write(void *cookie, const char *buf, LEN_T size)
+ {
+-	if (tcptls_session->fd == -1) {
+-		ast_log(LOG_ERROR, "server_read called with an fd of -1\n");
+-		errno = EIO;
++	struct ast_tcptls_stream *stream = cookie;
++	struct timeval start;
++	int ms;
++	int res;
++	int written;
++	int remaining;
++
++	if (!size) {
++		/* You asked to write no data you wrote no data. */
++		return 0;
++	}
++
++	if (!stream || stream->fd == -1) {
++		errno = EBADF;
+ 		return -1;
+ 	}
+ 
+-#ifdef DO_SSL
+-	if (tcptls_session->ssl)
+-		return ssl_read(tcptls_session->ssl, buf, count);
+-#endif
+-	return read(tcptls_session->fd, buf, count);
++	if (stream->start.tv_sec) {
++		start = stream->start;
++	} else {
++		start = ast_tvnow();
++	}
++
++#if defined(DO_SSL)
++	if (stream->ssl) {
++		written = 0;
++		remaining = size;
++		for (;;) {
++			res = SSL_write(stream->ssl, buf + written, remaining);
++			if (res == remaining) {
++				/* Everything was written. */
++				return size;
++			}
++			if (0 < res) {
++				/* Successfully wrote part of the buffer.  Try to write the rest. */
++				written += res;
++				remaining -= res;
++				continue;
++			}
++			switch (SSL_get_error(stream->ssl, res)) {
++			case SSL_ERROR_ZERO_RETURN:
++				ast_debug(1, "TLS clean shutdown alert writing data\n");
++				if (written) {
++					/* Report partial write. */
++					return written;
++				}
++				errno = EBADF;
++				return -1;
++			case SSL_ERROR_WANT_READ:
++				ms = ast_remaining_ms(start, stream->timeout);
++				if (!ms) {
++					/* Report partial write. */
++					ast_debug(1, "TLS timeout writing data (want read)\n");
++					return written;
++				}
++				ast_wait_for_input(stream->fd, ms);
++				break;
++			case SSL_ERROR_WANT_WRITE:
++				ms = ast_remaining_ms(start, stream->timeout);
++				if (!ms) {
++					/* Report partial write. */
++					ast_debug(1, "TLS timeout writing data (want write)\n");
++					return written;
++				}
++				ast_wait_for_output(stream->fd, ms);
++				break;
++			default:
++				/* Undecoded SSL or transport error. */
++				ast_debug(1, "TLS transport or SSL error writing data\n");
++				if (written) {
++					/* Report partial write. */
++					return written;
++				}
++				errno = EBADF;
++				return -1;
++			}
++		}
++	}
++#endif	/* defined(DO_SSL) */
++
++	written = 0;
++	remaining = size;
++	for (;;) {
++		res = write(stream->fd, buf + written, remaining);
++		if (res == remaining) {
++			/* Yay everything was written. */
++			return size;
++		}
++		if (0 < res) {
++			/* Successfully wrote part of the buffer.  Try to write the rest. */
++			written += res;
++			remaining -= res;
++			continue;
++		}
++		if (errno != EINTR && errno != EAGAIN) {
++			/* Not a retryable error. */
++			ast_debug(1, "TCP socket error writing: %s\n", strerror(errno));
++			if (written) {
++				return written;
++			}
++			return -1;
++		}
++		ms = ast_remaining_ms(start, stream->timeout);
++		if (!ms) {
++			/* Report partial write. */
++			ast_debug(1, "TCP timeout writing data\n");
++			return written;
++		}
++		ast_wait_for_output(stream->fd, ms);
++	}
+ }
+ 
+-HOOK_T ast_tcptls_server_write(struct ast_tcptls_session_instance *tcptls_session, const void *buf, size_t count)
++/*!
++ * \internal
++ * \brief fopencookie()/funopen() stream close function.
++ *
++ * \param cookie Stream control data.
++ *
++ * \retval 0 on success.
++ * \retval -1 on error.
++ */
++static int tcptls_stream_close(void *cookie)
+ {
+-	if (tcptls_session->fd == -1) {
+-		ast_log(LOG_ERROR, "server_write called with an fd of -1\n");
+-		errno = EIO;
++	struct ast_tcptls_stream *stream = cookie;
++
++	if (!stream) {
++		errno = EBADF;
+ 		return -1;
+ 	}
+ 
+-#ifdef DO_SSL
+-	if (tcptls_session->ssl)
+-		return ssl_write(tcptls_session->ssl, buf, count);
++	if (stream->fd != -1) {
++#if defined(DO_SSL)
++		if (stream->ssl) {
++			int res;
++
++			/*
++			 * According to the TLS standard, it is acceptable for an
++			 * application to only send its shutdown alert and then
++			 * close the underlying connection without waiting for
++			 * the peer's response (this way resources can be saved,
++			 * as the process can already terminate or serve another
++			 * connection).
++			 */
++			res = SSL_shutdown(stream->ssl);
++			if (res < 0) {
++				ast_log(LOG_ERROR, "SSL_shutdown() failed: %d\n",
++					SSL_get_error(stream->ssl, res));
++			}
++
++			if (!stream->ssl->server) {
++				/* For client threads, ensure that the error stack is cleared */
++				ERR_remove_state(0);
++			}
++
++			SSL_free(stream->ssl);
++			stream->ssl = NULL;
++		}
++#endif	/* defined(DO_SSL) */
++
++		/*
++		 * Issuing shutdown() is necessary here to avoid a race
++		 * condition where the last data written may not appear
++		 * in the TCP stream.  See ASTERISK-23548
++		 */
++		shutdown(stream->fd, SHUT_RDWR);
++		if (close(stream->fd)) {
++ 			ast_log(LOG_ERROR, "close() failed: %s\n", strerror(errno));
++ 		}
++		stream->fd = -1;
++ 	}
++	ao2_t_ref(stream, -1, "Closed tcptls stream cookie");
++
++ 	return 0;
++ }
++
++/*!
++ * \internal
++ * \brief fopencookie()/funopen() stream destructor function.
++ *
++ * \param cookie Stream control data.
++ *
++ * \return Nothing
++ */
++static void tcptls_stream_dtor(void *cookie)
++{
++	struct ast_tcptls_stream *stream = cookie;
++
++	ast_assert(stream->fd == -1);
++}
++
++/*!
++ * \internal
++ * \brief fopencookie()/funopen() stream allocation function.
++ *
++ * \retval stream_cookie on success.
++ * \retval NULL on error.
++ */
++static struct ast_tcptls_stream *tcptls_stream_alloc(void)
++{
++	struct ast_tcptls_stream *stream;
++
++	stream = ao2_alloc(sizeof(*stream), tcptls_stream_dtor);
++	if (stream) {
++		stream->fd = -1;
++		stream->timeout = -1;
++	}
++	return stream;
++}
++
++/*!
++ * \internal
++ * \brief Open a custom FILE stream for tcptls.
++ *
++ * \param stream Stream cookie control data.
++ * \param ssl SSL state if not NULL.
++ * \param fd Socket file descriptor.
++ * \param timeout ms to wait for an event on fd. -1 if timeout disabled.
++ *
++ * \retval fp on success.
++ * \retval NULL on error.
++ */
++static FILE *tcptls_stream_fopen(struct ast_tcptls_stream *stream, SSL *ssl, int fd, int timeout)
++{
++	FILE *fp;
++
++#if defined(HAVE_FOPENCOOKIE)	/* the glibc/linux interface */
++	static const cookie_io_functions_t cookie_funcs = {
++		tcptls_stream_read,
++		tcptls_stream_write,
++		NULL,
++		tcptls_stream_close
++	};
++#endif	/* defined(HAVE_FOPENCOOKIE) */
++
++	if (fd == -1) {
++		/* Socket not open. */
++		return NULL;
++	}
++
++	stream->ssl = ssl;
++	stream->fd = fd;
++	stream->timeout = timeout;
++	ao2_t_ref(stream, +1, "Opening tcptls stream cookie");
++
++#if defined(HAVE_FUNOPEN)	/* the BSD interface */
++	fp = funopen(stream, tcptls_stream_read, tcptls_stream_write, NULL,
++		tcptls_stream_close);
++#elif defined(HAVE_FOPENCOOKIE)	/* the glibc/linux interface */
++	fp = fopencookie(stream, "w+", cookie_funcs);
++#else
++	/* could add other methods here */
++	ast_debug(2, "No stream FILE methods attempted!\n");
++	fp = NULL;
+ #endif
+-	return write(tcptls_session->fd, buf, count);
++
++	if (!fp) {
++		stream->fd = -1;
++		ao2_t_ref(stream, -1, "Failed to open tcptls stream cookie");
++	}
++	return fp;
++}
++
++HOOK_T ast_tcptls_server_read(struct ast_tcptls_session_instance *tcptls_session, void *buf, size_t count)
++{
++	if (!tcptls_session->stream_cookie || tcptls_session->stream_cookie->fd == -1) {
++		ast_log(LOG_ERROR, "TCP/TLS read called on invalid stream.\n");
++ 		errno = EIO;
++ 		return -1;
++ 	}
++
++	return tcptls_stream_read(tcptls_session->stream_cookie, buf, count);
++}
++
++HOOK_T ast_tcptls_server_write(struct ast_tcptls_session_instance *tcptls_session, const void *buf, size_t count)
++{
++	if (!tcptls_session->stream_cookie || tcptls_session->stream_cookie->fd == -1) {
++		ast_log(LOG_ERROR, "TCP/TLS write called on invalid stream.\n");
++ 		errno = EIO;
++ 		return -1;
++ 	}
++
++	return tcptls_stream_write(tcptls_session->stream_cookie, buf, count);
+ }
+ 
+ static void session_instance_destructor(void *obj)
+ {
+-	struct ast_tcptls_session_instance *i = obj;
+-	ast_mutex_destroy(&i->lock);
++ 	struct ast_tcptls_session_instance *i = obj;
++
++	if (i->stream_cookie) {
++		ao2_t_ref(i->stream_cookie, -1, "Destroying tcptls session instance");
++		i->stream_cookie = NULL;
++	}
++ 	ast_mutex_destroy(&i->lock);
+ }
+ 
+ /*! \brief
+@@ -157,6 +548,15 @@
+ 	 */
+ 	if (ast_thread_inhibit_escalations()) {
+ 		ast_log(LOG_ERROR, "Failed to inhibit privilege escalations; killing connection\n");
++		ast_tcptls_close_session_file(tcptls_session);
++		ao2_ref(tcptls_session, -1);
++		return NULL;
++	}
++
++	tcptls_session->stream_cookie = tcptls_stream_alloc();
++	if (!tcptls_session->stream_cookie) {
++		ast_tcptls_close_session_file(tcptls_session);
++		ao2_ref(tcptls_session, -1);
+ 		return NULL;
+ 	}
+ 
+@@ -164,8 +564,10 @@
+ 	* open a FILE * as appropriate.
+ 	*/
+ 	if (!tcptls_session->parent->tls_cfg) {
+-		if ((tcptls_session->f = fdopen(tcptls_session->fd, "w+"))) {
+-			if(setvbuf(tcptls_session->f, NULL, _IONBF, 0)) {
++		tcptls_session->f = tcptls_stream_fopen(tcptls_session->stream_cookie, NULL,
++			tcptls_session->fd, -1);
++		if (tcptls_session->f) {
++			if (setvbuf(tcptls_session->f, NULL, _IONBF, 0)) {
+ 				ast_tcptls_close_session_file(tcptls_session);
+ 			}
+ 		}
+@@ -175,29 +577,28 @@
+ 		SSL_set_fd(tcptls_session->ssl, tcptls_session->fd);
+ 		if ((ret = ssl_setup(tcptls_session->ssl)) <= 0) {
+ 			ast_verb(2, "Problem setting up ssl connection: %s\n", ERR_error_string(ERR_get_error(), err));
+-		} else {
+-#if defined(HAVE_FUNOPEN)	/* the BSD interface */
+-			tcptls_session->f = funopen(tcptls_session->ssl, ssl_read, ssl_write, NULL, ssl_close);
+-
+-#elif defined(HAVE_FOPENCOOKIE)	/* the glibc/linux interface */
+-			static const cookie_io_functions_t cookie_funcs = {
+-				ssl_read, ssl_write, NULL, ssl_close
+-			};
+-			tcptls_session->f = fopencookie(tcptls_session->ssl, "w+", cookie_funcs);
+-#else
+-			/* could add other methods here */
+-			ast_debug(2, "no tcptls_session->f methods attempted!\n");
+-#endif
++		} else if ((tcptls_session->f = tcptls_stream_fopen(tcptls_session->stream_cookie,
++			tcptls_session->ssl, tcptls_session->fd, -1))) {
+ 			if ((tcptls_session->client && !ast_test_flag(&tcptls_session->parent->tls_cfg->flags, AST_SSL_DONT_VERIFY_SERVER))
+ 				|| (!tcptls_session->client && ast_test_flag(&tcptls_session->parent->tls_cfg->flags, AST_SSL_VERIFY_CLIENT))) {
+ 				X509 *peer;
+ 				long res;
+ 				peer = SSL_get_peer_certificate(tcptls_session->ssl);
+-				if (!peer)
+-					ast_log(LOG_WARNING, "No peer SSL certificate\n");
++				if (!peer) {
++					ast_log(LOG_ERROR, "No peer SSL certificate to verify\n");
++					ast_tcptls_close_session_file(tcptls_session);
++					ao2_ref(tcptls_session, -1);
++					return NULL;
++				}
++
+ 				res = SSL_get_verify_result(tcptls_session->ssl);
+-				if (res != X509_V_OK)
++				if (res != X509_V_OK) {
+ 					ast_log(LOG_ERROR, "Certificate did not verify: %s\n", X509_verify_cert_error_string(res));
++					X509_free(peer);
++					ast_tcptls_close_session_file(tcptls_session);
++					ao2_ref(tcptls_session, -1);
++					return NULL;
++				}
+ 				if (!ast_test_flag(&tcptls_session->parent->tls_cfg->flags, AST_SSL_IGNORE_COMMON_NAME)) {
+ 					ASN1_STRING *str;
+ 					unsigned char *str2;
+@@ -231,16 +632,13 @@
+ 					}
+ 					if (!found) {
+ 						ast_log(LOG_ERROR, "Certificate common name did not match (%s)\n", tcptls_session->parent->hostname);
+-						if (peer) {
+-							X509_free(peer);
+-						}
++						X509_free(peer);
+ 						ast_tcptls_close_session_file(tcptls_session);
+ 						ao2_ref(tcptls_session, -1);
+ 						return NULL;
+ 					}
+ 				}
+-				if (peer)
+-					X509_free(peer);
++				X509_free(peer);
+ 			}
+ 		}
+ 		if (!tcptls_session->f)	/* no success opening descriptor stacking */
+@@ -572,12 +970,19 @@
+ void ast_tcptls_close_session_file(struct ast_tcptls_session_instance *tcptls_session)
+ {
+ 	if (tcptls_session->f) {
++		fflush(tcptls_session->f);
+ 		if (fclose(tcptls_session->f)) {
+ 			ast_log(LOG_ERROR, "fclose() failed: %s\n", strerror(errno));
+ 		}
+ 		tcptls_session->f = NULL;
+ 		tcptls_session->fd = -1;
+ 	} else if (tcptls_session->fd != -1) {
++		/*
++		 * Issuing shutdown() is necessary here to avoid a race
++		 * condition where the last data written may not appear
++		 * in the TCP stream.  See ASTERISK-23548
++		 */
++		shutdown(tcptls_session->fd, SHUT_RDWR);
+ 		if (close(tcptls_session->fd)) {
+ 			ast_log(LOG_ERROR, "close() failed: %s\n", strerror(errno));
+ 		}
+Index: asterisk-1.8.13.1~dfsg1/configs/http.conf.sample
+===================================================================
+--- asterisk-1.8.13.1~dfsg1.orig/configs/http.conf.sample	2016-04-23 19:30:01.000000000 +0200
++++ asterisk-1.8.13.1~dfsg1/configs/http.conf.sample	2016-04-23 19:30:01.000000000 +0200
+@@ -37,6 +37,12 @@
+ ;
+ ;sessionlimit=100
+ ;
++; session_inactivity specifies the number of milliseconds to wait for
++; more data over the HTTP connection before closing it.
++;
++; Default: 30000
++;session_inactivity=30000
++;
+ ; Whether Asterisk should serve static content from http-static
+ ; Default is no.
+ ;
diff -Nru asterisk-1.8.13.1~dfsg1/debian/patches/AST-2014-010-11.diff asterisk-1.8.13.1~dfsg1/debian/patches/AST-2014-010-11.diff
--- asterisk-1.8.13.1~dfsg1/debian/patches/AST-2014-010-11.diff	1970-01-01 01:00:00.000000000 +0100
+++ asterisk-1.8.13.1~dfsg1/debian/patches/AST-2014-010-11.diff	2016-04-20 16:09:39.000000000 +0200
@@ -0,0 +1,31 @@
+Index: asterisk-1.8.13.1~dfsg1/res/res_fax_spandsp.c
+===================================================================
+--- asterisk-1.8.13.1~dfsg1.orig/res/res_fax_spandsp.c	2016-04-20 16:09:34.000000000 +0200
++++ asterisk-1.8.13.1~dfsg1/res/res_fax_spandsp.c	2016-04-20 16:09:34.000000000 +0200
+@@ -141,8 +141,25 @@
+ static void session_destroy(struct spandsp_pvt *p)
+ {
+ 	struct ast_frame *f;
++	t30_state_t *t30_to_terminate;
+ 
+-	t30_terminate(p->t30_state);
++	if (p->t30_state) {
++		t30_to_terminate = p->t30_state;
++	} else if (p->ist38) {
++#if SPANDSP_RELEASE_DATE >= 20080725
++		t30_to_terminate = &p->t38_state.t30;
++#else
++		t30_to_terminate = &p->t38_state.t30_state;
++#endif
++	} else {
++#if SPANDSP_RELEASE_DATE >= 20080725
++		t30_to_terminate = &p->fax_state.t30;
++#else
++		t30_to_terminate = &p->fax_state.t30_state;
++#endif
++	}
++
++	t30_terminate(t30_to_terminate);
+ 	p->isdone = 1;
+ 
+ 	ast_timer_close(p->timer);
diff -Nru asterisk-1.8.13.1~dfsg1/debian/patches/AST-2014-012-1.8.diff asterisk-1.8.13.1~dfsg1/debian/patches/AST-2014-012-1.8.diff
--- asterisk-1.8.13.1~dfsg1/debian/patches/AST-2014-012-1.8.diff	1970-01-01 01:00:00.000000000 +0100
+++ asterisk-1.8.13.1~dfsg1/debian/patches/AST-2014-012-1.8.diff	2016-04-23 11:15:42.000000000 +0200
@@ -0,0 +1,13 @@
+Index: asterisk-1.8.13.1~dfsg1/main/acl.c
+===================================================================
+--- asterisk-1.8.13.1~dfsg1.orig/main/acl.c	2016-04-23 11:14:33.000000000 +0200
++++ asterisk-1.8.13.1~dfsg1/main/acl.c	2016-04-23 11:14:33.000000000 +0200
+@@ -529,7 +529,7 @@
+ 		ast_copy_string(iabuf2, ast_inet_ntoa(ha->netaddr), sizeof(iabuf2));
+ 		ast_debug(1, "##### Testing %s with %s\n", iabuf, iabuf2);
+ #endif
+-		if (ast_sockaddr_is_ipv4(&ha->addr)) {
++		if (ast_sockaddr_is_ipv4(&current_ha->addr)) {
+ 			if (ast_sockaddr_is_ipv6(addr)) {
+ 				if (ast_sockaddr_is_ipv4_mapped(addr)) {
+ 					/* IPv4 ACLs apply to IPv4-mapped addresses */
diff -Nru asterisk-1.8.13.1~dfsg1/debian/patches/AST-2014-018-1.8.diff asterisk-1.8.13.1~dfsg1/debian/patches/AST-2014-018-1.8.diff
--- asterisk-1.8.13.1~dfsg1/debian/patches/AST-2014-018-1.8.diff	1970-01-01 01:00:00.000000000 +0100
+++ asterisk-1.8.13.1~dfsg1/debian/patches/AST-2014-018-1.8.diff	2016-04-23 12:25:18.000000000 +0200
@@ -0,0 +1,13 @@
+Index: asterisk-1.8.13.1~dfsg1/funcs/func_db.c
+===================================================================
+--- asterisk-1.8.13.1~dfsg1.orig/funcs/func_db.c	2016-04-23 12:25:13.000000000 +0200
++++ asterisk-1.8.13.1~dfsg1/funcs/func_db.c	2016-04-23 12:25:13.000000000 +0200
+@@ -282,7 +282,7 @@
+ {
+ 	int res = 0;
+ 
+-	res |= ast_custom_function_register(&db_function);
++	res |= ast_custom_function_register_escalating(&db_function, AST_CFE_BOTH);
+ 	res |= ast_custom_function_register(&db_exists_function);
+ 	res |= ast_custom_function_register_escalating(&db_delete_function, AST_CFE_READ);
+ 
diff -Nru asterisk-1.8.13.1~dfsg1/debian/patches/AST-2015-003-1.8.diff asterisk-1.8.13.1~dfsg1/debian/patches/AST-2015-003-1.8.diff
--- asterisk-1.8.13.1~dfsg1/debian/patches/AST-2015-003-1.8.diff	1970-01-01 01:00:00.000000000 +0100
+++ asterisk-1.8.13.1~dfsg1/debian/patches/AST-2015-003-1.8.diff	2016-04-23 12:27:55.000000000 +0200
@@ -0,0 +1,24 @@
+Index: asterisk-1.8.13.1~dfsg1/main/tcptls.c
+===================================================================
+--- asterisk-1.8.13.1~dfsg1.orig/main/tcptls.c	2016-04-23 12:27:50.000000000 +0200
++++ asterisk-1.8.13.1~dfsg1/main/tcptls.c	2016-04-23 12:27:50.000000000 +0200
+@@ -212,10 +212,17 @@
+ 						if (pos < 0)
+ 							break;
+ 						str = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, pos));
+-						ASN1_STRING_to_UTF8(&str2, str);
++						ret = ASN1_STRING_to_UTF8(&str2, str);
++						if (ret < 0) {
++							continue;
++						}
++
+ 						if (str2) {
+-							if (!strcasecmp(tcptls_session->parent->hostname, (char *) str2))
++							if (strlen((char *) str2) != ret) {
++								ast_log(LOG_WARNING, "Invalid certificate common name length (contains NULL bytes?)\n");
++							} else if (!strcasecmp(tcptls_session->parent->hostname, (char *) str2)) {
+ 								found = 1;
++							}
+ 							ast_debug(3, "SSL Common Name compare s1='%s' s2='%s'\n", tcptls_session->parent->hostname, str2);
+ 							OPENSSL_free(str2);
+ 						}
diff -Nru asterisk-1.8.13.1~dfsg1/debian/patches/series asterisk-1.8.13.1~dfsg1/debian/patches/series
--- asterisk-1.8.13.1~dfsg1/debian/patches/series	2014-01-04 01:22:48.000000000 +0100
+++ asterisk-1.8.13.1~dfsg1/debian/patches/series	2016-04-24 16:50:35.000000000 +0200
@@ -39,3 +39,13 @@
 AST-2013-006
 ASTERISK-20658
 AST-2013-007
+
+#
+# first Wheezy LTS upload
+AST-2014-010-11.diff
+AST-2014-006-11.6.diff
+AST-2014-001-1.8.15.diff
+AST-2014-012-1.8.diff
+AST-2014-018-1.8.diff
+AST-2015-003-1.8.diff
+AST-2014-007-1.8.15.diff


More information about the Pkg-voip-maintainers mailing list