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(¤t_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