mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-05 04:11:08 +00:00
res_pjsip_refer: Fix crash from a REFER and BYE collision.
Analyzing a one-off crash on a busy system showed that processing a REFER request had a NULL session channel pointer. The only way I can think of that could cause this is if an outgoing BYE transaction overlapped the incoming REFER transaction in a collision. Asterisk sends a BYE while the phone sends a REFER to complete an attended transfer. * Made check the session channel pointer before processing an incoming REFER request in res_pjsip_refer. * Fixed similar crash potential for res_pjsip supplement incoming request processing for res_pjsip_sdp_rtp INFO, res_pjsip_caller_id INVITE/UPDATE, res_pjsip_messaging MESSAGE, and res_pjsip_send_to_voicemail REFER messages. * Made res_pjsip_messaging respond to a message body too large with a 413 instead of ignoring it. ASTERISK-24700 #close Reported by: Zane Conkle Review: https://reviewboard.asterisk.org/r/4417/ ........ Merged revisions 431898 from http://svn.asterisk.org/svn/asterisk/branches/13 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@431899 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -361,7 +361,7 @@ static int caller_id_incoming_request(struct ast_sip_session *session, pjsip_rx_
|
||||
if (!session->endpoint->id.self.number.valid) {
|
||||
set_id_from_from(rdata, &session->id);
|
||||
}
|
||||
} else {
|
||||
} else if (session->channel) {
|
||||
/* Reinvite. Check for changes to the ID and queue a connected line
|
||||
* update if necessary
|
||||
*/
|
||||
|
@@ -681,10 +681,14 @@ static int incoming_in_dialog_request(struct ast_sip_session *session, struct pj
|
||||
char buf[MAX_BODY_SIZE];
|
||||
enum pjsip_status_code code;
|
||||
struct ast_frame f;
|
||||
|
||||
pjsip_dialog *dlg = session->inv_session->dlg;
|
||||
pjsip_transaction *tsx = pjsip_rdata_get_tsx(rdata);
|
||||
|
||||
if (!session->channel) {
|
||||
send_response(rdata, PJSIP_SC_NOT_FOUND, dlg, tsx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((code = check_content_type(rdata)) != PJSIP_SC_OK) {
|
||||
send_response(rdata, code, dlg, tsx);
|
||||
return 0;
|
||||
@@ -692,6 +696,7 @@ static int incoming_in_dialog_request(struct ast_sip_session *session, struct pj
|
||||
|
||||
if (print_body(rdata, buf, sizeof(buf)-1) < 1) {
|
||||
/* invalid body size */
|
||||
send_response(rdata, PJSIP_SC_REQUEST_ENTITY_TOO_LARGE, dlg, tsx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -418,7 +418,7 @@ static void refer_attended_destroy(void *obj)
|
||||
struct refer_attended *attended = obj;
|
||||
|
||||
ao2_cleanup(attended->transferer);
|
||||
ast_channel_unref(attended->transferer_chan);
|
||||
ast_channel_cleanup(attended->transferer_chan);
|
||||
ao2_cleanup(attended->transferer_second);
|
||||
ao2_cleanup(attended->progress);
|
||||
}
|
||||
@@ -674,7 +674,7 @@ static int refer_incoming_attended_request(struct ast_sip_session *session, pjsi
|
||||
|
||||
return 200;
|
||||
} else {
|
||||
const char *context = (session->channel ? pbx_builtin_getvar_helper(session->channel, "TRANSFER_CONTEXT") : "");
|
||||
const char *context = pbx_builtin_getvar_helper(session->channel, "TRANSFER_CONTEXT");
|
||||
struct refer_blind refer = { 0, };
|
||||
|
||||
if (ast_strlen_zero(context)) {
|
||||
@@ -718,10 +718,6 @@ static int refer_incoming_blind_request(struct ast_sip_session *session, pjsip_r
|
||||
char exten[AST_MAX_EXTENSION];
|
||||
struct refer_blind refer = { 0, };
|
||||
|
||||
if (!session->channel) {
|
||||
return 404;
|
||||
}
|
||||
|
||||
/* If no explicit transfer context has been provided use their configured context */
|
||||
context = pbx_builtin_getvar_helper(session->channel, "TRANSFER_CONTEXT");
|
||||
if (ast_strlen_zero(context)) {
|
||||
@@ -893,6 +889,14 @@ static int refer_incoming_refer_request(struct ast_sip_session *session, struct
|
||||
static const pj_str_t str_refer_to = { "Refer-To", 8 };
|
||||
static const pj_str_t str_replaces = { "Replaces", 8 };
|
||||
|
||||
if (!session->channel) {
|
||||
/* No channel to refer. Likely because the call was just hung up. */
|
||||
pjsip_dlg_respond(session->inv_session->dlg, rdata, 404, NULL, NULL, NULL);
|
||||
ast_debug(3, "Received a REFER on a session with no channel from endpoint '%s'.\n",
|
||||
ast_sorcery_object_get_id(session->endpoint));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!session->endpoint->allowtransfer) {
|
||||
pjsip_dlg_respond(session->inv_session->dlg, rdata, 603, NULL, NULL, NULL);
|
||||
ast_log(LOG_WARNING, "Endpoint %s transfer attempt blocked due to configuration\n",
|
||||
|
@@ -1269,15 +1269,18 @@ static struct ast_sip_session_sdp_handler video_sdp_handler = {
|
||||
|
||||
static int video_info_incoming_request(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
|
||||
{
|
||||
struct pjsip_transaction *tsx = pjsip_rdata_get_tsx(rdata);
|
||||
struct pjsip_transaction *tsx;
|
||||
pjsip_tx_data *tdata;
|
||||
|
||||
if (!ast_sip_is_content_type(&rdata->msg_info.msg->body->content_type,
|
||||
"application",
|
||||
"media_control+xml")) {
|
||||
if (!session->channel
|
||||
|| !ast_sip_is_content_type(&rdata->msg_info.msg->body->content_type,
|
||||
"application",
|
||||
"media_control+xml")) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
tsx = pjsip_rdata_get_tsx(rdata);
|
||||
|
||||
ast_queue_control(session->channel, AST_CONTROL_VIDUPDATE);
|
||||
|
||||
if (pjsip_dlg_create_response(session->inv_session->dlg, rdata, 200, NULL, &tdata) == PJ_SUCCESS) {
|
||||
|
@@ -119,13 +119,17 @@ static int has_call_feature(pjsip_rx_data *rdata)
|
||||
|
||||
static int handle_incoming_request(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
|
||||
{
|
||||
|
||||
struct ast_datastore *sip_session_datastore;
|
||||
struct ast_channel *other_party;
|
||||
int has_feature;
|
||||
int has_reason;
|
||||
|
||||
int has_feature = has_call_feature(rdata);
|
||||
int has_reason = has_diversion_reason(rdata);
|
||||
if (!session->channel) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
has_feature = has_call_feature(rdata);
|
||||
has_reason = has_diversion_reason(rdata);
|
||||
if (!has_feature && !has_reason) {
|
||||
/* If we don't have a call feature or diversion reason or if
|
||||
it's not a feature this module is related to then there
|
||||
|
Reference in New Issue
Block a user