summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Jordan <mjordan@digium.com>2015-06-02 09:29:46 -0500
committerGerrit Code Review <gerrit2@gerrit.digium.api>2015-06-02 09:29:46 -0500
commitaf420ba4aed1c84b125d0785f6009d58d69f0e31 (patch)
tree9469bda845bc6e5da362bab5c78521cb751a8aba
parent255f695434359c11ff14b0008bf1707435d42a79 (diff)
parent5cdcae5240be4f284b108187bfbcdb0e42121341 (diff)
Merge "res_pjsip_session: Fix in-dialog authentication."
-rw-r--r--res/res_pjsip_session.c141
1 files changed, 125 insertions, 16 deletions
diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c
index 98450109a..ca89d76a9 100644
--- a/res/res_pjsip_session.c
+++ b/res/res_pjsip_session.c
@@ -1418,16 +1418,95 @@ void ast_sip_session_unsuspend(struct ast_sip_session *session)
ao2_ref(suspender, -1);
}
-static int session_outbound_auth(pjsip_dialog *dlg, pjsip_tx_data *tdata, void *user_data)
+/*!
+ * \internal
+ * \brief Handle initial INVITE challenge response message.
+ * \since 13.5.0
+ *
+ * \param rdata PJSIP receive response message data.
+ *
+ * \retval PJ_FALSE Did not handle message.
+ * \retval PJ_TRUE Handled message.
+ */
+static pj_bool_t outbound_invite_auth(pjsip_rx_data *rdata)
{
- pjsip_inv_session *inv = pjsip_dlg_get_inv_session(dlg);
- struct ast_sip_session *session = inv->mod_data[session_module.id];
+ pjsip_transaction *tsx;
+ pjsip_dialog *dlg;
+ pjsip_inv_session *inv;
+ pjsip_tx_data *tdata;
+ struct ast_sip_session *session;
+
+ 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;
+ }
+
+ tsx = pjsip_rdata_get_tsx(rdata);
+ dlg = pjsip_rdata_get_dlg(rdata);
+ if (!dlg || !tsx) {
+ return PJ_FALSE;
+ }
- if (inv->state < PJSIP_INV_STATE_CONFIRMED && tdata->msg->line.req.method.id == PJSIP_INVITE_METHOD) {
- pjsip_inv_uac_restart(inv, 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.
+ */
+ ast_debug(1, "A reINVITE is being challenged.\n");
+ return PJ_FALSE;
}
+ ast_debug(1, "Initial INVITE is being challenged.\n");
+
+ session = inv->mod_data[session_module.id];
+
+ if (ast_sip_create_request_with_auth(&session->endpoint->outbound_auths, rdata, tsx,
+ &tdata)) {
+ return PJ_FALSE;
+ }
+
+ /*
+ * Restart the outgoing initial INVITE transaction to deal
+ * with authentication.
+ */
+ pjsip_inv_uac_restart(inv, PJ_FALSE);
+
ast_sip_session_send_request(session, tdata);
- return 0;
+ return PJ_TRUE;
+}
+
+static pjsip_module outbound_invite_auth_module = {
+ .name = {"Outbound INVITE Auth", 20},
+ .priority = PJSIP_MOD_PRIORITY_DIALOG_USAGE,
+ .on_rx_response = outbound_invite_auth,
+};
+
+/*!
+ * \internal
+ * \brief Setup outbound initial INVITE authentication.
+ * \since 13.5.0
+ *
+ * \param dlg PJSIP dialog to attach outbound authentication.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+static int setup_outbound_invite_auth(pjsip_dialog *dlg)
+{
+ pj_status_t status;
+
+ ++dlg->sess_count;
+ status = pjsip_dlg_add_usage(dlg, &outbound_invite_auth_module, NULL);
+ --dlg->sess_count;
+
+ return status != PJ_SUCCESS ? -1 : 0;
}
struct ast_sip_session *ast_sip_session_create_outgoing(struct ast_sip_endpoint *endpoint,
@@ -1465,7 +1544,7 @@ struct ast_sip_session *ast_sip_session_create_outgoing(struct ast_sip_endpoint
return NULL;
}
- if (ast_sip_dialog_setup_outbound_authentication(dlg, endpoint, session_outbound_auth, NULL)) {
+ if (setup_outbound_invite_auth(dlg)) {
pjsip_dlg_terminate(dlg);
return NULL;
}
@@ -1505,7 +1584,7 @@ struct ast_sip_session *ast_sip_session_create_outgoing(struct ast_sip_endpoint
ao2_cleanup(joint_caps);
}
- if ((pjsip_dlg_add_usage(dlg, &session_module, NULL) != PJ_SUCCESS)) {
+ if (pjsip_dlg_add_usage(dlg, &session_module, NULL) != PJ_SUCCESS) {
pjsip_inv_terminate(inv_session, 500, PJ_FALSE);
/* Since we are not notifying ourselves that the INVITE session is being terminated
* we need to manually drop its reference to session
@@ -2254,6 +2333,7 @@ static void session_inv_on_tsx_state_changed(pjsip_inv_session *inv, pjsip_trans
{
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 +2363,23 @@ static void session_inv_on_tsx_state_changed(pjsip_inv_session *inv, pjsip_trans
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 +2390,30 @@ static void session_inv_on_tsx_state_changed(pjsip_inv_session *inv, pjsip_trans
* 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);
@@ -2640,6 +2747,7 @@ static int load_module(void)
return AST_MODULE_LOAD_DECLINE;
}
ast_sip_register_service(&session_reinvite_module);
+ ast_sip_register_service(&outbound_invite_auth_module);
ast_module_shutdown_ref(ast_module_info->self);
@@ -2648,6 +2756,7 @@ static int load_module(void)
static int unload_module(void)
{
+ ast_sip_unregister_service(&outbound_invite_auth_module);
ast_sip_unregister_service(&session_reinvite_module);
ast_sip_unregister_service(&session_module);
ast_sorcery_delete(ast_sip_get_sorcery(), nat_hook);