[Asterisk-code-review] res pjsip session: Fix in-dialog authentication. (asterisk[13])

Richard Mudgett asteriskteam at digium.com
Tue May 26 16:18:09 CDT 2015


Richard Mudgett has uploaded a new change for review.

  https://gerrit.asterisk.org/535

Change subject: res_pjsip_session: Fix in-dialog authentication.
......................................................................

res_pjsip_session: Fix in-dialog authentication.

When the remote peer requires authentication for in-dialog requests then
re-INVITEs to the peer cause the call to be disconnected and other
in-dialog requests to the peer like MESSAGE just don't go through.

* Made session_inv_on_tsx_state_changed() handle in-dialog authentication
for re-INVITEs and other methods.  Initial INVITEs cannot be handled here
because the INVITE transaction must be restarted earlier.

* Changed res/res_pjsip/pjsip_outbound_auth.c:outbound_auth() to only
handle initial outbound INVITEs.  Re-INVITEs cannot be handled here.  The
re-INVITE transaction is still in progress and the PJSIP library cannot
handle the overlapping INVITE transactions.  Other method types should
not be handled here as this code is only setup for outgoing calls while we
need to handle incoming and outgoing calls.

ASTERISK-25131 #close
Reported by: Richard Mudgett

Change-Id: I12bdd7ddccc819b4ce4b091e826d1e26334601b0
---
M res/res_pjsip/pjsip_outbound_auth.c
M res/res_pjsip_session.c
2 files changed, 72 insertions(+), 18 deletions(-)


  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/35/535/1

diff --git a/res/res_pjsip/pjsip_outbound_auth.c b/res/res_pjsip/pjsip_outbound_auth.c
index 1f75422..5764b4e 100644
--- a/res/res_pjsip/pjsip_outbound_auth.c
+++ b/res/res_pjsip/pjsip_outbound_auth.c
@@ -17,9 +17,12 @@
  */
 
 #include "asterisk.h"
+
 #undef bzero
 #define bzero bzero
-#include "pjsip.h"
+#include <pjsip.h>
+#include <pjsip_ua.h>
+#include <pjlib.h>
 
 #include "asterisk/res_pjsip.h"
 #include "asterisk/module.h"
@@ -40,14 +43,15 @@
 
 static pj_bool_t outbound_auth(pjsip_rx_data *rdata)
 {
-	RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
+	struct ast_sip_endpoint *endpoint;
 	pjsip_transaction *tsx;
 	pjsip_dialog *dlg;
 	struct outbound_auth_cb_data *cb_data;
+	pjsip_inv_session *inv;
 	pjsip_tx_data *tdata;
 
-	if (rdata->msg_info.msg->line.status.code != 401 &&
-			rdata->msg_info.msg->line.status.code != 407) {
+	if (rdata->msg_info.msg->line.status.code != 401
+		&& rdata->msg_info.msg->line.status.code != 407) {
 		/* Doesn't pertain to us. Move on */
 		return PJ_FALSE;
 	}
@@ -58,22 +62,47 @@
 		return PJ_FALSE;
 	}
 
+	if (tsx->method.id != PJSIP_INVITE_METHOD) {
+		/* Not an INVITE that needs authentication */
+		return PJ_FALSE;
+	}
+
+	inv = pjsip_dlg_get_inv_session(dlg);
+	if (PJSIP_INV_STATE_CONFIRMED <= inv->state) {
+		/*
+		 * We cannot handle reINVITE authentication at this
+		 * time because the reINVITE transaction is still in
+		 * progress.  Authentication will get handled by the
+		 * session state change callback.
+		 */
+		ast_debug(1, "A reINVITE is being challenged.\n");
+		return PJ_FALSE;
+	}
+	ast_debug(1, "Initial INVITE is being challenged.\n");
+
 	endpoint = ast_sip_dialog_get_endpoint(dlg);
 	if (!endpoint) {
 		return PJ_FALSE;
 	}
 
 	if (ast_sip_create_request_with_auth(&endpoint->outbound_auths, rdata, tsx, &tdata)) {
+		ao2_ref(endpoint, -1);
 		return PJ_FALSE;
 	}
+
+	/*
+	 * Restart the outgoing initial INVITE transaction to deal
+	 * with authentication.
+	 */
+	pjsip_inv_uac_restart(inv, PJ_FALSE);
 
 	cb_data = dlg->mod_data[outbound_auth_mod.id];
 	if (cb_data) {
 		cb_data->cb(dlg, tdata, cb_data->user_data);
-		return PJ_TRUE;
+	} else {
+		pjsip_dlg_send_request(dlg, tdata, -1, NULL);
 	}
-
-	pjsip_dlg_send_request(dlg, tdata, -1, NULL);
+	ao2_ref(endpoint, -1);
 	return PJ_TRUE;
 }
 
diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c
index 87ce2b0..97e859a 100644
--- a/res/res_pjsip_session.c
+++ b/res/res_pjsip_session.c
@@ -1423,9 +1423,6 @@
 	pjsip_inv_session *inv = pjsip_dlg_get_inv_session(dlg);
 	struct ast_sip_session *session = inv->mod_data[session_module.id];
 
-	if (inv->state < PJSIP_INV_STATE_CONFIRMED && tdata->msg->line.req.method.id == PJSIP_INVITE_METHOD) {
-		pjsip_inv_uac_restart(inv, PJ_FALSE);
-	}
 	ast_sip_session_send_request(session, tdata);
 	return 0;
 }
@@ -2254,6 +2251,7 @@
 {
 	ast_sip_session_response_cb cb;
 	struct ast_sip_session *session = inv->mod_data[session_module.id];
+	pjsip_tx_data *tdata;
 
 	print_debug_details(inv, tsx, e);
 	if (!session) {
@@ -2283,12 +2281,23 @@
 					if (tsx->status_code == PJSIP_SC_REQUEST_PENDING) {
 						reschedule_reinvite(session, cb);
 						return;
-					} else if (inv->state == PJSIP_INV_STATE_CONFIRMED &&
-						   tsx->status_code != 488) {
-						/* Other reinvite failures (except 488) result in destroying the session. */
-						pjsip_tx_data *tdata;
-						if (pjsip_inv_end_session(inv, 500, NULL, &tdata) == PJ_SUCCESS) {
-							ast_sip_session_send_request(session, tdata);
+					}
+					if (inv->state == PJSIP_INV_STATE_CONFIRMED) {
+						ast_debug(1, "reINVITE received final response code %d\n",
+							tsx->status_code);
+						if ((tsx->status_code == 401 || tsx->status_code == 407)
+							&& !ast_sip_create_request_with_auth(
+								&session->endpoint->outbound_auths,
+								e->body.tsx_state.src.rdata, tsx, &tdata)) {
+							/* Send authed reINVITE */
+							ast_sip_session_send_request_with_cb(session, tdata, cb);
+							return;
+						}
+						if (tsx->status_code != 488) {
+							/* Other reinvite failures (except 488) result in destroying the session. */
+							if (pjsip_inv_end_session(inv, 500, NULL, &tdata) == PJ_SUCCESS) {
+								ast_sip_session_send_request(session, tdata);
+							}
 						}
 					}
 				} else if (tsx->state == PJSIP_TSX_STATE_TERMINATED) {
@@ -2299,14 +2308,30 @@
 						 * a cancelled call. Our role is to immediately send a BYE to end the
 						 * dialog.
 						 */
-						pjsip_tx_data *tdata;
-
 						if (pjsip_inv_end_session(inv, 500, NULL, &tdata) == PJ_SUCCESS) {
 							ast_sip_session_send_request(session, tdata);
 						}
 					}
 				}
 			}
+		} else {
+			/* All other methods */
+			if (tsx->role == PJSIP_ROLE_UAC) {
+				if (tsx->state == PJSIP_TSX_STATE_COMPLETED) {
+					/* This means we got a final response to our outgoing method */
+					ast_debug(1, "%.*s received final response code %d\n",
+						(int) pj_strlen(&tsx->method.name), pj_strbuf(&tsx->method.name),
+						tsx->status_code);
+					if ((tsx->status_code == 401 || tsx->status_code == 407)
+						&& !ast_sip_create_request_with_auth(
+							&session->endpoint->outbound_auths,
+							e->body.tsx_state.src.rdata, tsx, &tdata)) {
+						/* Send authed version of the method */
+						ast_sip_session_send_request_with_cb(session, tdata, cb);
+						return;
+					}
+				}
+			}
 		}
 		if (cb) {
 			cb(session, e->body.tsx_state.src.rdata);

-- 
To view, visit https://gerrit.asterisk.org/535
To unsubscribe, visit https://gerrit.asterisk.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I12bdd7ddccc819b4ce4b091e826d1e26334601b0
Gerrit-PatchSet: 1
Gerrit-Project: asterisk
Gerrit-Branch: 13
Gerrit-Owner: Richard Mudgett <rmudgett at digium.com>



More information about the asterisk-code-review mailing list