diff options
-rw-r--r-- | include/asterisk/res_pjsip.h | 23 | ||||
-rw-r--r-- | res/res_pjsip.c | 10 | ||||
-rw-r--r-- | res/res_pjsip_outbound_authenticator_digest.c | 14 | ||||
-rw-r--r-- | res/res_pjsip_outbound_registration.c | 17 |
4 files changed, 55 insertions, 9 deletions
diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h index a15e967b8..cbae5955e 100644 --- a/include/asterisk/res_pjsip.h +++ b/include/asterisk/res_pjsip.h @@ -702,6 +702,18 @@ struct ast_sip_outbound_authenticator { */ int (*create_request_with_auth)(const struct ast_sip_auth_vector *auths, struct pjsip_rx_data *challenge, struct pjsip_transaction *tsx, struct pjsip_tx_data **new_request); + /*! + * \brief Create a new request with authentication credentials based on old request + * + * \param auths A vector of IDs of auth sorcery objects + * \param challenge The SIP response with authentication challenge(s) + * \param old_request The request that resulted in challenge(s) + * \param new_request The new SIP request with challenge response(s) + * \retval 0 Successfully created new request + * \retval -1 Failed to create a new request + */ + int (*create_request_with_auth_from_old)(const struct ast_sip_auth_vector *auths, struct pjsip_rx_data *challenge, + struct pjsip_tx_data *old_request, struct pjsip_tx_data **new_request); }; /*! @@ -1397,6 +1409,17 @@ int ast_sip_create_request_with_auth(const struct ast_sip_auth_vector *auths, pj pjsip_transaction *tsx, pjsip_tx_data **new_request); /*! + * \brief Create a response to an authentication challenge + * + * This will call into an outbound authenticator's create_request_with_auth callback + * to create a new request with authentication credentials. See the create_request_with_auth_from_old + * callback in the \ref ast_sip_outbound_authenticator structure for details about + * the parameters and return values. + */ +int ast_sip_create_request_with_auth_from_old(const struct ast_sip_auth_vector *auths, pjsip_rx_data *challenge, + pjsip_tx_data *old_request, pjsip_tx_data **new_request); + +/*! * \brief Determine the endpoint that has sent a SIP message * * This will call into each of the registered endpoint identifiers' diff --git a/res/res_pjsip.c b/res/res_pjsip.c index bde0de1ec..5f68c4440 100644 --- a/res/res_pjsip.c +++ b/res/res_pjsip.c @@ -2012,6 +2012,16 @@ int ast_sip_create_request_with_auth(const struct ast_sip_auth_vector *auths, pj return registered_outbound_authenticator->create_request_with_auth(auths, challenge, tsx, new_request); } +int ast_sip_create_request_with_auth_from_old(const struct ast_sip_auth_vector *auths, pjsip_rx_data *challenge, + pjsip_tx_data *old_request, pjsip_tx_data **new_request) +{ + if (!registered_outbound_authenticator) { + ast_log(LOG_WARNING, "No SIP outbound authenticator registered. Cannot respond to authentication challenge\n"); + return -1; + } + return registered_outbound_authenticator->create_request_with_auth_from_old(auths, challenge, old_request, new_request); +} + struct endpoint_identifier_list { const char *name; unsigned int priority; diff --git a/res/res_pjsip_outbound_authenticator_digest.c b/res/res_pjsip_outbound_authenticator_digest.c index 35e59f21a..aa35fbac0 100644 --- a/res/res_pjsip_outbound_authenticator_digest.c +++ b/res/res_pjsip_outbound_authenticator_digest.c @@ -101,14 +101,14 @@ cleanup: return res; } -static int digest_create_request_with_auth(const struct ast_sip_auth_vector *auths, pjsip_rx_data *challenge, - pjsip_transaction *tsx, pjsip_tx_data **new_request) +static int digest_create_request_with_auth_from_old(const struct ast_sip_auth_vector *auths, pjsip_rx_data *challenge, + pjsip_tx_data *old_request, pjsip_tx_data **new_request) { pjsip_auth_clt_sess auth_sess; pjsip_cseq_hdr *cseq; if (pjsip_auth_clt_init(&auth_sess, ast_sip_get_pjsip_endpoint(), - tsx->pool, 0) != PJ_SUCCESS) { + old_request->pool, 0) != PJ_SUCCESS) { ast_log(LOG_WARNING, "Failed to initialize client authentication session\n"); return -1; } @@ -119,7 +119,7 @@ static int digest_create_request_with_auth(const struct ast_sip_auth_vector *aut } switch (pjsip_auth_clt_reinit_req(&auth_sess, challenge, - tsx->last_tx, new_request)) { + old_request, new_request)) { case PJ_SUCCESS: /* PJSIP creates a new transaction for new_request (meaning it creates a new * branch). However, it recycles the Call-ID, from-tag, and CSeq from the @@ -150,6 +150,12 @@ static int digest_create_request_with_auth(const struct ast_sip_auth_vector *aut return -1; } +static int digest_create_request_with_auth(const struct ast_sip_auth_vector *auths, pjsip_rx_data *challenge, + pjsip_transaction *tsx, pjsip_tx_data **new_request) +{ + return digest_create_request_with_auth_from_old(auths, challenge, tsx->last_tx, new_request); +} + static struct ast_sip_outbound_authenticator digest_authenticator = { .create_request_with_auth = digest_create_request_with_auth, }; diff --git a/res/res_pjsip_outbound_registration.c b/res/res_pjsip_outbound_registration.c index b8f7112e4..1c00473fb 100644 --- a/res/res_pjsip_outbound_registration.c +++ b/res/res_pjsip_outbound_registration.c @@ -487,8 +487,8 @@ struct registration_response { struct sip_outbound_registration_client_state *client_state; /*! \brief The response message */ pjsip_rx_data *rdata; - /*! \brief The response transaction */ - pjsip_transaction *tsx; + /*! \brief Request for which the response was received */ + pjsip_tx_data *old_request; }; /*! \brief Registration response structure destructor */ @@ -500,6 +500,10 @@ static void registration_response_destroy(void *obj) pjsip_rx_data_free_cloned(response->rdata); } + if (response->old_request) { + pjsip_tx_data_dec_ref(response->old_request); + } + ao2_cleanup(response->client_state); } @@ -558,8 +562,8 @@ static int handle_registration_response(void *data) if (!response->client_state->auth_attempted && (response->code == 401 || response->code == 407)) { pjsip_tx_data *tdata; - if (!ast_sip_create_request_with_auth(&response->client_state->outbound_auths, - response->rdata, response->tsx, &tdata)) { + if (!ast_sip_create_request_with_auth_from_old(&response->client_state->outbound_auths, + response->rdata, response->old_request, &tdata)) { ao2_ref(response->client_state, +1); response->client_state->auth_attempted = 1; if (pjsip_regc_send(response->client_state->client, tdata) != PJ_SUCCESS) { @@ -650,9 +654,12 @@ static void sip_outbound_registration_response_cb(struct pjsip_regc_cbparam *par if (param->rdata) { struct pjsip_retry_after_hdr *retry_after = pjsip_msg_find_hdr(param->rdata->msg_info.msg, PJSIP_H_RETRY_AFTER, NULL); + pjsip_transaction *tsx; response->retry_after = retry_after ? retry_after->ivalue : 0; - response->tsx = pjsip_rdata_get_tsx(param->rdata); + tsx = pjsip_rdata_get_tsx(param->rdata); + response->old_request = tsx->last_tx; + pjsip_tx_data_add_ref(response->old_request); pjsip_rx_data_clone(param->rdata, 0, &response->rdata); } |