]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
AST-2014-016: Fix crash when receiving an in-dialog INVITE with Replaces in res_pjsip...
authorJoshua Colp <jcolp@digium.com>
Thu, 20 Nov 2014 14:54:19 +0000 (14:54 +0000)
committerJoshua Colp <jcolp@digium.com>
Thu, 20 Nov 2014 14:54:19 +0000 (14:54 +0000)
The implementation of INVITE with Replaces in res_pjsip_refer did not expect them to
occur in-dialog. As a result it would incorrectly attempt to hang up a channel it
thought was under its control. In reality the channel would be under the control of
another thread. When the other thread accessed the channel it would be accessing freed
memory and could crash.

This change makes res_pjsip_refer not act on an in-dialog INVITE with Replaces.

ASTERISK-24528 #close
Reported by: Joshua Colp

git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/12@428304 65c4cc65-6c06-0410-ace0-fbb531ad65f3

res/res_pjsip_refer.c

index e46879d86da7d70ff4984dbc9c04cefc56afc6a7..995276cb1bf5bff1682ac0a229e7ab2510a07871 100644 (file)
@@ -785,6 +785,12 @@ static int refer_incoming_invite_request(struct ast_sip_session *session, struct
        other_session = ast_sip_dialog_get_session(other_dlg);
        pjsip_dlg_dec_lock(other_dlg);
 
+       /* Don't accept an in-dialog INVITE with Replaces as it does not make much sense */
+       if (session->inv_session->dlg->state == PJSIP_DIALOG_STATE_ESTABLISHED) {
+               response = 488;
+               goto end;
+       }
+
        if (!other_session) {
                response = 481;
                ast_debug(3, "INVITE with Replaces received on channel '%s' from endpoint '%s', but requested session does not exist\n",
@@ -831,14 +837,20 @@ static int refer_incoming_invite_request(struct ast_sip_session *session, struct
 
 end:
        if (response) {
-               ast_debug(3, "INVITE with Replaces failed on channel '%s', sending response of '%d'\n",
-                       ast_channel_name(session->channel), response);
-               session->defer_terminate = 1;
-               ast_hangup(session->channel);
-               session->channel = NULL;
-
-               if (pjsip_inv_end_session(session->inv_session, response, NULL, &packet) == PJ_SUCCESS) {
-                       ast_sip_session_send_response(session, packet);
+               if (session->inv_session->dlg->state != PJSIP_DIALOG_STATE_ESTABLISHED) {
+                       ast_debug(3, "INVITE with Replaces failed on channel '%s', sending response of '%d'\n",
+                               ast_channel_name(session->channel), response);
+                       session->defer_terminate = 1;
+                       ast_hangup(session->channel);
+                       session->channel = NULL;
+
+                       if (pjsip_inv_end_session(session->inv_session, response, NULL, &packet) == PJ_SUCCESS) {
+                               ast_sip_session_send_response(session, packet);
+                       }
+               } else {
+                       ast_debug(3, "INVITE with Replaces in-dialog on channel '%s', hanging up\n",
+                               ast_channel_name(session->channel));
+                       ast_queue_hangup(session->channel);
                }
        }