mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-25 22:18:07 +00:00
res_pjsip: mediasec: Add Security-Client headers after 401 (#49)
When using mediasec, requests sent after a 401 must still contain the Security-Client header according to draft-dawes-sipcore-mediasec-parameter. Resolves: #48
This commit is contained in:
committed by
GitHub
parent
65fa8d6009
commit
cacd98bb29
@@ -425,6 +425,8 @@ struct sip_outbound_registration_client_state {
|
||||
unsigned int destroy:1;
|
||||
/*! \brief Non-zero if we have attempted sending a REGISTER with authentication */
|
||||
unsigned int auth_attempted:1;
|
||||
/*! \brief Status code of last response if we have tried to register before */
|
||||
int last_status_code;
|
||||
/*! \brief The name of the transport to be used for the registration */
|
||||
char *transport_name;
|
||||
/*! \brief The name of the registration sorcery object */
|
||||
@@ -642,6 +644,9 @@ out:
|
||||
static void add_security_headers(struct sip_outbound_registration_client_state *client_state,
|
||||
pjsip_tx_data *tdata)
|
||||
{
|
||||
int add_require_header = 1;
|
||||
int add_proxy_require_header = 1;
|
||||
int add_sec_client_header = 0;
|
||||
struct sip_outbound_registration *reg = NULL;
|
||||
struct ast_sip_endpoint *endpt = NULL;
|
||||
struct ao2_container *contact_container;
|
||||
@@ -674,20 +679,33 @@ static void add_security_headers(struct sip_outbound_registration_client_state *
|
||||
if (!contact_status && AST_VECTOR_SIZE(&client_state->server_security_mechanisms)) {
|
||||
sec_mechs = &client_state->server_security_mechanisms;
|
||||
}
|
||||
if (client_state->status == SIP_REGISTRATION_REGISTERED || client_state->status == SIP_REGISTRATION_REJECTED_TEMPORARY
|
||||
|| client_state->auth_attempted) {
|
||||
if (client_state->status == SIP_REGISTRATION_REJECTED_TEMPORARY || client_state->auth_attempted) {
|
||||
if (sec_mechs != NULL && pjsip_msg_find_hdr_by_name(tdata->msg, &security_verify, NULL) == NULL) {
|
||||
ast_sip_add_security_headers(sec_mechs, "Security-Verify", 0, tdata);
|
||||
}
|
||||
ast_sip_remove_headers_by_name_and_value(tdata->msg, &security_client, NULL);
|
||||
ast_sip_remove_headers_by_name_and_value(tdata->msg, &proxy_require, "mediasec");
|
||||
ast_sip_remove_headers_by_name_and_value(tdata->msg, &require, "mediasec");
|
||||
if (client_state->last_status_code == 494) {
|
||||
ast_sip_remove_headers_by_name_and_value(tdata->msg, &security_client, NULL);
|
||||
} else {
|
||||
/* necessary if a retry occures */
|
||||
add_sec_client_header = (pjsip_msg_find_hdr_by_name(tdata->msg, &security_client, NULL) == NULL) ? 1 : 0;
|
||||
}
|
||||
add_require_header =
|
||||
(pjsip_msg_find_hdr_by_name(tdata->msg, &require, NULL) == NULL) ? 1 : 0;
|
||||
add_proxy_require_header =
|
||||
(pjsip_msg_find_hdr_by_name(tdata->msg, &proxy_require, NULL) == NULL) ? 1 : 0;
|
||||
} else {
|
||||
ast_sip_add_security_headers(&client_state->security_mechanisms, "Security-Client", 0, tdata);
|
||||
}
|
||||
|
||||
ast_sip_add_header(tdata, "Require", "mediasec");
|
||||
ast_sip_add_header(tdata, "Proxy-Require", "mediasec");
|
||||
if (add_require_header) {
|
||||
ast_sip_add_header(tdata, "Require", "mediasec");
|
||||
}
|
||||
if (add_proxy_require_header) {
|
||||
ast_sip_add_header(tdata, "Proxy-Require", "mediasec");
|
||||
}
|
||||
if (add_sec_client_header) {
|
||||
ast_sip_add_security_headers(&client_state->security_mechanisms, "Security-Client", 0, tdata);
|
||||
}
|
||||
|
||||
/* Cleanup */
|
||||
if (contact_status) {
|
||||
@@ -1216,6 +1234,7 @@ static int handle_registration_response(void *data)
|
||||
pjsip_regc_get_info(response->client_state->client, &info);
|
||||
ast_copy_pj_str(server_uri, &info.server_uri, sizeof(server_uri));
|
||||
ast_copy_pj_str(client_uri, &info.client_uri, sizeof(client_uri));
|
||||
response->client_state->last_status_code = response->code;
|
||||
|
||||
ast_debug(1, "Processing REGISTER response %d from server '%s' for client '%s'\n",
|
||||
response->code, server_uri, client_uri);
|
||||
@@ -2018,6 +2037,27 @@ static int sip_outbound_registration_apply(const struct ast_sorcery *sorcery, vo
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int security_mechanism_to_str(const void *obj, const intptr_t *args, char **buf)
|
||||
{
|
||||
const struct sip_outbound_registration *registration = obj;
|
||||
|
||||
return ast_sip_security_mechanisms_to_str(®istration->security_mechanisms, 0, buf);
|
||||
}
|
||||
|
||||
static const char *security_negotiation_map[] = {
|
||||
[AST_SIP_SECURITY_NEG_NONE] = "no",
|
||||
[AST_SIP_SECURITY_NEG_MEDIASEC] = "mediasec",
|
||||
};
|
||||
|
||||
static int security_negotiation_to_str(const void *obj, const intptr_t *args, char **buf)
|
||||
{
|
||||
const struct sip_outbound_registration *registration = obj;
|
||||
if (ARRAY_IN_BOUNDS(registration->security_negotiation, security_negotiation_map)) {
|
||||
*buf = ast_strdup(security_negotiation_map[registration->security_negotiation]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int security_mechanisms_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
|
||||
{
|
||||
struct sip_outbound_registration *registration = obj;
|
||||
@@ -2761,8 +2801,8 @@ static int load_module(void)
|
||||
ast_sorcery_object_field_register_custom(ast_sip_get_sorcery(), "registration", "outbound_auth", "", outbound_auth_handler, outbound_auths_to_str, outbound_auths_to_var_list, 0, 0);
|
||||
ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "support_path", "no", OPT_BOOL_T, 1, FLDSET(struct sip_outbound_registration, support_path));
|
||||
ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "support_outbound", "no", OPT_YESNO_T, 1, FLDSET(struct sip_outbound_registration, support_outbound));
|
||||
ast_sorcery_object_field_register_custom(ast_sip_get_sorcery(), "registration", "security_negotiation", "no", security_negotiation_handler, NULL, NULL, 0, 0);
|
||||
ast_sorcery_object_field_register_custom(ast_sip_get_sorcery(), "registration", "security_mechanisms", "", security_mechanisms_handler, NULL, NULL, 0, 0);
|
||||
ast_sorcery_object_field_register_custom(ast_sip_get_sorcery(), "registration", "security_negotiation", "no", security_negotiation_handler, security_negotiation_to_str, NULL, 0, 0);
|
||||
ast_sorcery_object_field_register_custom(ast_sip_get_sorcery(), "registration", "security_mechanisms", "", security_mechanisms_handler, security_mechanism_to_str, NULL, 0, 0);
|
||||
ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "line", "no", OPT_BOOL_T, 1, FLDSET(struct sip_outbound_registration, line));
|
||||
ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "endpoint", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, endpoint));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user