[Pkg-voip-commits] r9892 - in /asterisk: branches/squeeze/debian/ branches/squeeze/debian/patches/ trunk/debian/ trunk/debian/patches/

maniac-guest at alioth.debian.org maniac-guest at alioth.debian.org
Fri Jul 6 07:57:37 UTC 2012


Author: maniac-guest
Date: Fri Jul  6 07:57:36 2012
New Revision: 9892

URL: http://svn.debian.org/wsvn/pkg-voip/?sc=1&rev=9892
Log:
Initial work on AST-2012-010 and AST-2012-011

Added:
    asterisk/branches/squeeze/debian/patches/AST-2012-010
    asterisk/trunk/debian/patches/AST-2012-010
    asterisk/trunk/debian/patches/AST-2012-011
Modified:
    asterisk/branches/squeeze/debian/changelog
    asterisk/branches/squeeze/debian/patches/series
    asterisk/trunk/debian/changelog
    asterisk/trunk/debian/patches/series

Modified: asterisk/branches/squeeze/debian/changelog
URL: http://svn.debian.org/wsvn/pkg-voip/asterisk/branches/squeeze/debian/changelog?rev=9892&op=diff
==============================================================================
--- asterisk/branches/squeeze/debian/changelog (original)
+++ asterisk/branches/squeeze/debian/changelog Fri Jul  6 07:57:36 2012
@@ -1,8 +1,13 @@
 asterisk (1:1.6.2.9-2+squeeze7) UNRELEASED; urgency=low
 
+  [ Tzafrir Cohen ]
   * NOT RELEASED YET
 
- -- Tzafrir Cohen <tzafrir at debian.org>  Wed, 13 Jun 2012 01:09:05 +0300
+  [ Victor Seva ]
+  * Patch AST-2012-010 : Possible resource leak on uncompleted
+    re-invite transactions.
+
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Fri, 06 Jul 2012 09:10:35 +0200
 
 asterisk (1:1.6.2.9-2+squeeze6) stable-security; urgency=high
 

Added: asterisk/branches/squeeze/debian/patches/AST-2012-010
URL: http://svn.debian.org/wsvn/pkg-voip/asterisk/branches/squeeze/debian/patches/AST-2012-010?rev=9892&op=file
==============================================================================
--- asterisk/branches/squeeze/debian/patches/AST-2012-010 (added)
+++ asterisk/branches/squeeze/debian/patches/AST-2012-010 Fri Jul  6 07:57:36 2012
@@ -1,0 +1,139 @@
+Description: Possible resource leak on uncompleted re-invite transactions
+Origin: http://downloads.asterisk.org/pub/security/AST-2012-010-1.8.diff
+Bug-Debian: http://bugs.debian.org/680470
+
+If Asterisk sends a re-invite and an endpoint responds to the re-invite
+with a provisional response but never sends a final response, then the
+SIP dialog structure is never freed and the RTP ports for the call are
+never released. If an attacker has the ability to place a call, they
+could create a denial of service by using all available RTP ports.
+
+--- a/channels/chan_sip.c
++++ b/channels/chan_sip.c
+@@ -1662,6 +1662,7 @@
+ 	struct sip_auth *peerauth;		/*!< Realm authentication */
+ 	int noncecount;				/*!< Nonce-count */
+ 	unsigned int stalenonce:1;	/*!< Marks the current nonce as responded too */
++	unsigned int ongoing_reinvite:1;    /*!< There is a reinvite in progress that might need to be cleaned up */
+ 	char lastmsg[256];			/*!< Last Message sent/received */
+ 	int amaflags;				/*!< AMA Flags */
+ 	int pendinginvite;			/*!< Any pending INVITE or state NOTIFY (in subscribe pvt's) ? (seqno of this) */
+@@ -1674,6 +1675,7 @@
+ 
+ 	int initid;				/*!< Auto-congest ID if appropriate (scheduler) */
+ 	int waitid;				/*!< Wait ID for scheduler after 491 or other delays */
++	int reinviteid;                     /*!< Reinvite in case of provisional, but no final response */
+ 	int autokillid;				/*!< Auto-kill ID (scheduler) */
+ 	int t38id;                              /*!< T.38 Response ID */
+ 	enum transfermodes allowtransfer;	/*!< REFER: restriction scheme */
+@@ -4081,7 +4083,7 @@
+ 			ast_debug(3, "Re-scheduled destruction of SIP call %s\n", p->callid ? p->callid : "<unknown>");
+ 			append_history(p, "ReliableXmit", "timeout");
+ 			if (sscanf(p->lastmsg, "Tx: %30s", method_str) == 1 || sscanf(p->lastmsg, "Rx: %30s", method_str) == 1) {
+-				if (method_match(SIP_CANCEL, method_str) || method_match(SIP_BYE, method_str)) {
++				if (p->ongoing_reinvite || method_match(SIP_CANCEL, method_str) || method_match(SIP_BYE, method_str)) {
+ 					pvt_set_needdestroy(p, "autodestruct");
+ 				}
+ 			}
+@@ -6092,6 +6094,20 @@
+ 	return 0;
+ }
+ 
++static int reinvite_timeout(const void *data)
++{
++	struct sip_pvt *dialog = (struct sip_pvt *) data;
++	struct ast_channel *owner = sip_pvt_lock_full(dialog);
++	dialog->reinviteid = -1;
++	check_pendings(dialog);
++	if (owner) {
++		ast_channel_unlock(owner);
++		ast_channel_unref(owner);
++	}
++	ao2_unlock(dialog);
++	dialog_unref(dialog, "unref for reinvite timeout");
++	return 0;
++}
+ 
+ /*! \brief  sip_hangup: Hangup SIP call
+  * Part of PBX interface, called from ast_hangup */
+@@ -6289,8 +6305,16 @@
+ 				ast_set_flag(&p->flags[0], SIP_PENDINGBYE);	
+ 				ast_clear_flag(&p->flags[0], SIP_NEEDREINVITE);	
+ 				AST_SCHED_DEL_UNREF(sched, p->waitid, dialog_unref(p, "when you delete the waitid sched, you should dec the refcount for the stored dialog ptr"));
+-				if (sip_cancel_destroy(p))
++				if (sip_cancel_destroy(p)) {
+ 					ast_log(LOG_WARNING, "Unable to cancel SIP destruction.  Expect bad things.\n");
++				}
++				/* If we have an ongoing reinvite, there is a chance that we have gotten a provisional
++				 * response, but something weird has happened and we will never receive a final response.
++				 * So, just in case, check for pending actions after a bit of time to trigger the pending
++				 * bye that we are setting above */
++				if (p->ongoing_reinvite && p->reinviteid < 0) {
++					p->reinviteid = ast_sched_add(sched, 32 * p->timer_t1, reinvite_timeout, dialog_ref(p, "ref for reinvite_timeout"));
++				}
+ 			}
+ 		}
+ 	}
+@@ -7338,6 +7362,7 @@
+ 	p->method = intended_method;
+ 	p->initid = -1;
+ 	p->waitid = -1;
++	p->reinviteid = -1;
+ 	p->autokillid = -1;
+ 	p->request_queue_sched_id = -1;
+ 	p->provisional_keepalive_sched_id = -1;
+@@ -10715,7 +10740,7 @@
+ 	initialize_initreq(p, &req);
+ 	p->lastinvite = p->ocseq;
+ 	ast_set_flag(&p->flags[0], SIP_OUTGOING);       /* Change direction of this dialog */
+-
++	p->ongoing_reinvite = 1;
+ 	return send_request(p, &req, XMIT_CRITICAL, p->ocseq);
+ }
+ 
+@@ -17736,17 +17761,20 @@
+ static void check_pendings(struct sip_pvt *p)
+ {
+ 	if (ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) {
+-		/* if we can't BYE, then this is really a pending CANCEL */
+-		if (p->invitestate == INV_PROCEEDING || p->invitestate == INV_EARLY_MEDIA)
++                if (p->reinviteid > -1) {
++                        /* Outstanding p->reinviteid timeout, so wait... */
++                        return;
++                } else if (p->invitestate == INV_PROCEEDING || p->invitestate == INV_EARLY_MEDIA) {
++                        /* if we can't BYE, then this is really a pending CANCEL */
+ 			transmit_request(p, SIP_CANCEL, p->lastinvite, XMIT_RELIABLE, FALSE);
+ 			/* Actually don't destroy us yet, wait for the 487 on our original 
+ 			   INVITE, but do set an autodestruct just in case we never get it. */
+-		else {
++		} else {
+ 			/* We have a pending outbound invite, don't send something
+-				new in-transaction */
+-			if (p->pendinginvite)
++			 * new in-transaction, unless it is a pending reinvite, then
++			 * by the time we are called here, we should probably just hang up. */
++			if (p->pendinginvite && !p->ongoing_reinvite)
+ 				return;
+-
+ 			/* Perhaps there is an SD change INVITE outstanding */
+ 			transmit_request_with_auth(p, SIP_BYE, 0, XMIT_RELIABLE, TRUE);
+ 		}
+@@ -17821,9 +17849,17 @@
+  	if (resp >= 300 && (p->invitestate == INV_CALLING || p->invitestate == INV_PROCEEDING || p->invitestate == INV_EARLY_MEDIA ))
+  		p->invitestate = INV_COMPLETED;
+  	
++	if ((resp >= 200 && reinvite)) {
++		p->ongoing_reinvite = 0;
++		if (p->reinviteid > -1) {
++			AST_SCHED_DEL_UNREF(sched, p->reinviteid, dialog_unref(p, "unref dialog for reinvite timeout because of a final response"));
++		}
++	}
++
+ 	/* Final response, clear out pending invite */
+-	if ((resp == 200 || resp >= 300) && p->pendinginvite && seqno == p->pendinginvite)
++	if ((resp == 200 || resp >= 300) && p->pendinginvite && seqno == p->pendinginvite) {
+ 		p->pendinginvite = 0;
++	}
+ 
+ 	switch (resp) {
+ 	case 100:	/* Trying */

Modified: asterisk/branches/squeeze/debian/patches/series
URL: http://svn.debian.org/wsvn/pkg-voip/asterisk/branches/squeeze/debian/patches/series?rev=9892&op=diff
==============================================================================
--- asterisk/branches/squeeze/debian/patches/series (original)
+++ asterisk/branches/squeeze/debian/patches/series Fri Jul  6 07:57:36 2012
@@ -53,3 +53,4 @@
 AST-2012-007
 skinny_fix_16040
 AST-2012-008
+AST-2012-010

Modified: asterisk/trunk/debian/changelog
URL: http://svn.debian.org/wsvn/pkg-voip/asterisk/trunk/debian/changelog?rev=9892&op=diff
==============================================================================
--- asterisk/trunk/debian/changelog (original)
+++ asterisk/trunk/debian/changelog Fri Jul  6 07:57:36 2012
@@ -1,8 +1,15 @@
 asterisk (1:1.8.13.0~dfsg-2) UNRELEASED; urgency=low
 
+  [ Tzafrir Cohen ]
   * NOT RELEASED YET
 
- -- Tzafrir Cohen <tzafrir at debian.org>  Tue, 05 Jun 2012 11:11:24 +0300
+  [ Victor Seva ]
+  * Patch AST-2012-010 : Possible resource leak on uncompleted
+    re-invite transactions.
+  * Patch AST-2012-011 (CVE-2012-3812): Remote crash
+    vulnerability in voice mail application (Closes: #680470).
+
+ -- Victor Seva <linuxmaniac at torreviejawireless.org>  Fri, 06 Jul 2012 09:43:40 +0200
 
 asterisk (1:1.8.13.0~dfsg-1) unstable; urgency=high
 

Added: asterisk/trunk/debian/patches/AST-2012-010
URL: http://svn.debian.org/wsvn/pkg-voip/asterisk/trunk/debian/patches/AST-2012-010?rev=9892&op=file
==============================================================================
--- asterisk/trunk/debian/patches/AST-2012-010 (added)
+++ asterisk/trunk/debian/patches/AST-2012-010 Fri Jul  6 07:57:36 2012
@@ -1,0 +1,141 @@
+Description: Possible resource leak on uncompleted re-invite transactions
+Origin: http://downloads.asterisk.org/pub/security/AST-2012-010-1.8.diff
+Bug-Debian: http://bugs.debian.org/680470
+
+If Asterisk sends a re-invite and an endpoint responds to the re-invite
+with a provisional response but never sends a final response, then the
+SIP dialog structure is never freed and the RTP ports for the call are
+never released. If an attacker has the ability to place a call, they
+could create a denial of service by using all available RTP ports.
+
+--- a/channels/chan_sip.c
++++ b/channels/chan_sip.c
+@@ -3850,7 +3850,7 @@
+ 			ast_debug(3, "Re-scheduled destruction of SIP call %s\n", p->callid ? p->callid : "<unknown>");
+ 			append_history(p, "ReliableXmit", "timeout");
+ 			if (sscanf(p->lastmsg, "Tx: %30s", method_str) == 1 || sscanf(p->lastmsg, "Rx: %30s", method_str) == 1) {
+-				if (method_match(SIP_CANCEL, method_str) || method_match(SIP_BYE, method_str)) {
++				if (p->ongoing_reinvite || method_match(SIP_CANCEL, method_str) || method_match(SIP_BYE, method_str)) {
+ 					pvt_set_needdestroy(p, "autodestruct");
+ 				}
+ 			}
+@@ -6224,6 +6224,21 @@
+ 	return 0;
+ }
+ 
++static int reinvite_timeout(const void *data)
++{
++	struct sip_pvt *dialog = (struct sip_pvt *) data;
++	struct ast_channel *owner = sip_pvt_lock_full(dialog);
++	dialog->reinviteid = -1;
++	check_pendings(dialog);
++	if (owner) {
++		ast_channel_unlock(owner);
++		ast_channel_unref(owner);
++	}
++	ao2_unlock(dialog);
++	dialog_unref(dialog, "unref for reinvite timeout");
++	return 0;
++}
++
+ /*! \brief  sip_hangup: Hangup SIP call
+  * Part of PBX interface, called from ast_hangup */
+ static int sip_hangup(struct ast_channel *ast)
+@@ -6423,8 +6438,16 @@
+ 				ast_set_flag(&p->flags[0], SIP_PENDINGBYE);	
+ 				ast_clear_flag(&p->flags[0], SIP_NEEDREINVITE);	
+ 				AST_SCHED_DEL_UNREF(sched, p->waitid, dialog_unref(p, "when you delete the waitid sched, you should dec the refcount for the stored dialog ptr"));
+-				if (sip_cancel_destroy(p))
++				if (sip_cancel_destroy(p)) {
+ 					ast_log(LOG_WARNING, "Unable to cancel SIP destruction.  Expect bad things.\n");
++				}
++				/* If we have an ongoing reinvite, there is a chance that we have gotten a provisional
++				 * response, but something weird has happened and we will never receive a final response.
++				 * So, just in case, check for pending actions after a bit of time to trigger the pending
++				 * bye that we are setting above */
++				if (p->ongoing_reinvite && p->reinviteid < 0) {
++					p->reinviteid = ast_sched_add(sched, 32 * p->timer_t1, reinvite_timeout, dialog_ref(p, "ref for reinvite_timeout"));
++				}
+ 			}
+ 		}
+ 	}
+@@ -7693,6 +7716,7 @@
+ 	p->method = intended_method;
+ 	p->initid = -1;
+ 	p->waitid = -1;
++	p->reinviteid = -1;
+ 	p->autokillid = -1;
+ 	p->request_queue_sched_id = -1;
+ 	p->provisional_keepalive_sched_id = -1;
+@@ -11860,7 +11884,7 @@
+ 	initialize_initreq(p, &req);
+ 	p->lastinvite = p->ocseq;
+ 	ast_set_flag(&p->flags[0], SIP_OUTGOING);       /* Change direction of this dialog */
+-
++	p->ongoing_reinvite = 1;
+ 	return send_request(p, &req, XMIT_CRITICAL, p->ocseq);
+ }
+ 
+@@ -19762,8 +19786,11 @@
+ static void check_pendings(struct sip_pvt *p)
+ {
+ 	if (ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) {
+-		/* if we can't BYE, then this is really a pending CANCEL */
+-		if (p->invitestate == INV_PROCEEDING || p->invitestate == INV_EARLY_MEDIA) {
++                if (p->reinviteid > -1) {
++                        /* Outstanding p->reinviteid timeout, so wait... */
++                        return;
++                } else if (p->invitestate == INV_PROCEEDING || p->invitestate == INV_EARLY_MEDIA) {
++                        /* if we can't BYE, then this is really a pending CANCEL */
+ 			p->invitestate = INV_CANCELLED;
+ 			transmit_request(p, SIP_CANCEL, p->lastinvite, XMIT_RELIABLE, FALSE);
+ 			/* If the cancel occurred on an initial invite, cancel the pending BYE */
+@@ -19774,8 +19801,9 @@
+ 			   INVITE, but do set an autodestruct just in case we never get it. */
+ 		} else {
+ 			/* We have a pending outbound invite, don't send something
+-				new in-transaction */
+-			if (p->pendinginvite)
++			 * new in-transaction, unless it is a pending reinvite, then
++			 * by the time we are called here, we should probably just hang up. */
++			if (p->pendinginvite && !p->ongoing_reinvite)
+ 				return;
+ 
+ 			if (p->owner) {
+@@ -19980,9 +20008,17 @@
+  	if (resp >= 300 && (p->invitestate == INV_CALLING || p->invitestate == INV_PROCEEDING || p->invitestate == INV_EARLY_MEDIA ))
+  		p->invitestate = INV_COMPLETED;
+  	
++	if ((resp >= 200 && reinvite)) {
++		p->ongoing_reinvite = 0;
++		if (p->reinviteid > -1) {
++			AST_SCHED_DEL_UNREF(sched, p->reinviteid, dialog_unref(p, "unref dialog for reinvite timeout because of a final response"));
++		}
++	}
++
+ 	/* Final response, clear out pending invite */
+-	if ((resp == 200 || resp >= 300) && p->pendinginvite && seqno == p->pendinginvite)
++	if ((resp == 200 || resp >= 300) && p->pendinginvite && seqno == p->pendinginvite) {
+ 		p->pendinginvite = 0;
++	}
+ 
+ 	/* If this is a response to our initial INVITE, we need to set what we can use
+ 	 * for this peer.
+--- a/channels/sip/include/sip.h
++++ b/channels/sip/include/sip.h
+@@ -1056,6 +1056,7 @@
+ 	struct sip_auth_container *peerauth;/*!< Realm authentication credentials */
+ 	int noncecount;                     /*!< Nonce-count */
+ 	unsigned int stalenonce:1;          /*!< Marks the current nonce as responded too */
++	unsigned int ongoing_reinvite:1;    /*!< There is a reinvite in progress that might need to be cleaned up */
+ 	char lastmsg[256];                  /*!< Last Message sent/received */
+ 	int amaflags;                       /*!< AMA Flags */
+ 	uint32_t pendinginvite; /*!< Any pending INVITE or state NOTIFY (in subscribe pvt's) ? (seqno of this) */
+@@ -1068,6 +1069,7 @@
+ 
+ 	int initid;                         /*!< Auto-congest ID if appropriate (scheduler) */
+ 	int waitid;                         /*!< Wait ID for scheduler after 491 or other delays */
++	int reinviteid;                     /*!< Reinvite in case of provisional, but no final response */
+ 	int autokillid;                     /*!< Auto-kill ID (scheduler) */
+ 	int t38id;                          /*!< T.38 Response ID */
+ 	struct sip_refer *refer;            /*!< REFER: SIP transfer data structure */

Added: asterisk/trunk/debian/patches/AST-2012-011
URL: http://svn.debian.org/wsvn/pkg-voip/asterisk/trunk/debian/patches/AST-2012-011?rev=9892&op=file
==============================================================================
--- asterisk/trunk/debian/patches/AST-2012-011 (added)
+++ asterisk/trunk/debian/patches/AST-2012-011 Fri Jul  6 07:57:36 2012
@@ -1,0 +1,166 @@
+Description: Remote crash vulnerability in voice mail application
+Origin: http://downloads.asterisk.org/pub/security/AST-2012-011-1.8.diff
+Bug-Debian: http://bugs.debian.org/680470
+
+If a single voicemail account is manipulated by two parties simultaneously,
+a condition can occur where memory is freed twice causing a crash.
+
+--- a/apps/app_voicemail.c
++++ b/apps/app_voicemail.c
+@@ -1758,25 +1758,28 @@
+ static int vm_allocate_dh(struct vm_state *vms, struct ast_vm_user *vmu, int count_msg) {
+ 
+ 	int arraysize = (vmu->maxmsg > count_msg ? vmu->maxmsg : count_msg);
+-	if (!vms->dh_arraysize) {
+-		/* initial allocation */
++
++	/* remove old allocation */
++	if (vms->deleted) {
++		ast_free(vms->deleted);
++		vms->deleted = NULL;
++	}
++	if (vms->heard) {
++		ast_free(vms->heard);
++		vms->heard = NULL;
++	}
++	vms->dh_arraysize = 0;
++
++	if (arraysize > 0) {
+ 		if (!(vms->deleted = ast_calloc(arraysize, sizeof(int)))) {
+ 			return -1;
+ 		}
+ 		if (!(vms->heard = ast_calloc(arraysize, sizeof(int)))) {
++			ast_free(vms->deleted);
++			vms->deleted = NULL;
+ 			return -1;
+ 		}
+ 		vms->dh_arraysize = arraysize;
+-	} else if (vms->dh_arraysize < arraysize) {
+-		if (!(vms->deleted = ast_realloc(vms->deleted, arraysize * sizeof(int)))) {
+-			return -1;
+-		}
+-		if (!(vms->heard = ast_realloc(vms->heard, arraysize * sizeof(int)))) {
+-			return -1;
+-		}
+-		memset(vms->deleted, 0, arraysize * sizeof(int));
+-		memset(vms->heard, 0, arraysize * sizeof(int));
+-		vms->dh_arraysize = arraysize;
+ 	}
+ 
+ 	return 0;
+@@ -6565,9 +6568,15 @@
+ 		name = "Unknown Caller";
+ 
+ 	/* If deleted, show "undeleted" */
+-
+-	if (vms->deleted[vms->curmsg])
+-		keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
++#ifdef IMAP_STORAGE
++	ast_mutex_lock(&vms->lock);
++#endif
++	if (vms->deleted[vms->curmsg]) {
++ 		keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
++	}
++#ifdef IMAP_STORAGE
++	ast_mutex_unlock(&vms->lock);
++#endif
+ 
+ 	/* Except "Exit" */
+ 	keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
+@@ -6620,8 +6629,15 @@
+ 	}
+ 
+ 	/* If deleted, show "undeleted" */
+-	if (vms->deleted[vms->curmsg]) 
++#ifdef IMAP_STORAGE
++	ast_mutex_lock(&vms->lock);
++#endif
++	if (vms->deleted[vms->curmsg]) {
+ 		keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
++	}
++#ifdef IMAP_STORAGE
++	ast_mutex_unlock(&vms->lock);
++#endif
+ 
+ 	/* Except "Exit" */
+ 	keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
+@@ -7800,8 +7816,12 @@
+ 
+ 	if (!res) {
+ 		make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
++#ifdef IMAP_STORAGE
++		ast_mutex_lock(&vms->lock);
++#endif
+ 		vms->heard[vms->curmsg] = 1;
+ #ifdef IMAP_STORAGE
++		ast_mutex_unlock(&vms->lock);
+ 		/*IMAP storage stores any prepended message from a forward
+ 		 * as a separate file from the rest of the message
+ 		 */
+@@ -8016,6 +8036,7 @@
+ 	}
+ 	ast_unlock_path(vms->curdir);
+ #else /* defined(IMAP_STORAGE) */
++	ast_mutex_lock(&vms->lock);
+ 	if (vms->deleted) {
+ 		/* Since we now expunge after each delete, deleting in reverse order
+ 		 * ensures that no reordering occurs between each step. */
+@@ -8030,12 +8051,18 @@
+ #endif
+ 
+ done:
+-	if (vms->deleted && last_msg_idx) {
++	if (vms->deleted) {
+ 		ast_free(vms->deleted);
++		vms->deleted = NULL;
+ 	}
+-	if (vms->heard && last_msg_idx) {
++	if (vms->heard) {
+ 		ast_free(vms->heard);
++		vms->heard = NULL;
+ 	}
++	vms->dh_arraysize = 0;
++#ifdef IMAP_STORAGE
++	ast_mutex_unlock(&vms->lock);
++#endif
+ 
+ 	return 0;
+ }
+@@ -9130,14 +9157,25 @@
+ 				res = ast_play_and_wait(chan, "vm-next");
+ 			}
+ 			if (!res) {
+-				if (!vms->deleted[vms->curmsg])
++				int curmsg_deleted;
++#ifdef IMAP_STORAGE
++				ast_mutex_lock(&vms->lock);
++#endif
++				curmsg_deleted = vms->deleted[vms->curmsg];
++#ifdef IMAP_STORAGE
++				ast_mutex_unlock(&vms->lock);
++#endif
++				if (!curmsg_deleted) {
+ 					res = ast_play_and_wait(chan, "vm-delete");
+-				else
++				} else {
+ 					res = ast_play_and_wait(chan, "vm-undelete");
+-				if (!res)
++				}
++				if (!res) {
+ 					res = ast_play_and_wait(chan, "vm-toforward");
+-				if (!res)
++				}
++				if (!res) {
+ 					res = ast_play_and_wait(chan, "vm-savemessage");
++				}
+ 			}
+ 		}
+ 		if (!res) {
+@@ -10171,6 +10209,7 @@
+ 			}
+ 
+ 			vms.starting = 1;
++			vms.curmsg = 0;
+ 			break;
+ 		case '3': /* Advanced options */
+ 			ast_test_suite_event_notify("ADVOPTIONS", "Message: entering advanced options menu");

Modified: asterisk/trunk/debian/patches/series
URL: http://svn.debian.org/wsvn/pkg-voip/asterisk/trunk/debian/patches/series?rev=9892&op=diff
==============================================================================
--- asterisk/trunk/debian/patches/series (original)
+++ asterisk/trunk/debian/patches/series Fri Jul  6 07:57:36 2012
@@ -25,3 +25,6 @@
 menuselect_cflags
 ilbc_disable
 httpd_port
+
+AST-2012-010
+AST-2012-011




More information about the Pkg-voip-commits mailing list