mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 02:37:10 +00:00 
			
		
		
		
	res_pjsip: mediasec: Add Security-Client headers after 401
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:
		| @@ -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