| 
									
										
										
										
											2022-07-26 14:01:04 +02:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Asterisk -- An open source telephony toolkit. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (C) 2022, Commend International | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Maximilian Fridrich <m.fridrich@commend.com> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * See http://www.asterisk.org for more information about
 | 
					
						
							|  |  |  |  * the Asterisk project. Please do not directly contact | 
					
						
							|  |  |  |  * any of the maintainers of this project for assistance; | 
					
						
							|  |  |  |  * the project provides a web site, mailing lists and IRC | 
					
						
							|  |  |  |  * channels for your use. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software, distributed under the terms of | 
					
						
							|  |  |  |  * the GNU General Public License Version 2. See the LICENSE file | 
					
						
							|  |  |  |  * at the top of the source tree. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * \file | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \brief Interact with security agreement negotiations and mechanisms | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \author Maximilian Fridrich <m.fridrich@commend.com> | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "asterisk.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <pjsip.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "asterisk/res_pjsip.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct ast_sip_security_mechanism *ast_sip_security_mechanisms_alloc(size_t n_params) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct ast_sip_security_mechanism *mech; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mech = ast_calloc(1, sizeof(struct ast_sip_security_mechanism)); | 
					
						
							|  |  |  | 	if (mech == NULL) { | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	mech->qvalue = 0.0; | 
					
						
							|  |  |  | 	if (AST_VECTOR_INIT(&mech->mechanism_parameters, n_params) != 0) { | 
					
						
							|  |  |  | 		ast_free(mech); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return mech; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct ast_sip_security_mechanism *ast_sip_security_mechanisms_copy( | 
					
						
							|  |  |  | 	const struct ast_sip_security_mechanism *src) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct ast_sip_security_mechanism *dst = NULL; | 
					
						
							|  |  |  | 	int i, n_params; | 
					
						
							|  |  |  | 	char *param; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	n_params = AST_VECTOR_SIZE(&src->mechanism_parameters); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	dst = ast_sip_security_mechanisms_alloc(n_params); | 
					
						
							|  |  |  | 	if (dst == NULL) { | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	dst->type = src->type; | 
					
						
							|  |  |  | 	dst->qvalue = src->qvalue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < n_params; i++) { | 
					
						
							|  |  |  | 		param = ast_strdup(AST_VECTOR_GET(&src->mechanism_parameters, i)); | 
					
						
							|  |  |  | 		AST_VECTOR_APPEND(&dst->mechanism_parameters, param); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return dst; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void ast_sip_security_mechanisms_destroy(struct ast_sip_security_mechanism *mech) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < AST_VECTOR_SIZE(&mech->mechanism_parameters); i++) { | 
					
						
							|  |  |  | 		ast_free(AST_VECTOR_GET(&mech->mechanism_parameters, i)); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	AST_VECTOR_FREE(&mech->mechanism_parameters); | 
					
						
							|  |  |  | 	ast_free(mech); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ast_sip_security_mechanisms_vector_copy(struct ast_sip_security_mechanism_vector *dst, | 
					
						
							|  |  |  | 	const struct ast_sip_security_mechanism_vector *src) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct ast_sip_security_mechanism *mech; | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_sip_security_mechanisms_vector_destroy(dst); | 
					
						
							|  |  |  | 	for (i = 0; i < AST_VECTOR_SIZE(src); i++) { | 
					
						
							|  |  |  | 		mech = AST_VECTOR_GET(src, i); | 
					
						
							|  |  |  | 		AST_VECTOR_APPEND(dst, ast_sip_security_mechanisms_copy(mech)); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ast_sip_security_mechanisms_vector_destroy(struct ast_sip_security_mechanism_vector *security_mechanisms) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct ast_sip_security_mechanism *mech; | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!security_mechanisms) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < AST_VECTOR_SIZE(security_mechanisms); i++) { | 
					
						
							|  |  |  | 		mech = AST_VECTOR_GET(security_mechanisms, i); | 
					
						
							|  |  |  | 		ast_sip_security_mechanisms_destroy(mech); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	AST_VECTOR_FREE(security_mechanisms); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int ast_sip_str_to_security_mechanism_type(const char *security_mechanism) { | 
					
						
							|  |  |  | 	int result = -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!strcasecmp(security_mechanism, "msrp-tls")) { | 
					
						
							|  |  |  | 		result = AST_SIP_SECURITY_MECH_MSRP_TLS; | 
					
						
							|  |  |  | 	} else if (!strcasecmp(security_mechanism, "sdes-srtp")) { | 
					
						
							|  |  |  | 		result = AST_SIP_SECURITY_MECH_SDES_SRTP; | 
					
						
							|  |  |  | 	} else if (!strcasecmp(security_mechanism, "dtls-srtp")) { | 
					
						
							|  |  |  | 		result = AST_SIP_SECURITY_MECH_DTLS_SRTP; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static char *ast_sip_security_mechanism_type_to_str(enum ast_sip_security_mechanism_type mech_type) { | 
					
						
							|  |  |  | 	if (mech_type == AST_SIP_SECURITY_MECH_MSRP_TLS) { | 
					
						
							|  |  |  | 		return "msrp-tls"; | 
					
						
							|  |  |  | 	} else if (mech_type == AST_SIP_SECURITY_MECH_SDES_SRTP) { | 
					
						
							|  |  |  | 		return "sdes-srtp"; | 
					
						
							|  |  |  | 	} else if (mech_type == AST_SIP_SECURITY_MECH_DTLS_SRTP) { | 
					
						
							|  |  |  | 		return "dtls-srtp"; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-02 17:18:42 +02:00
										 |  |  | static int security_mechanism_to_str(const struct ast_sip_security_mechanism *security_mechanism, int add_qvalue, char **buf) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2022-07-26 14:01:04 +02:00
										 |  |  | 	size_t size; | 
					
						
							|  |  |  | 	size_t buf_size = 128; | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 	char *ret = ast_calloc(buf_size, sizeof(char)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (ret == NULL) { | 
					
						
							|  |  |  | 		return ENOMEM; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (security_mechanism == NULL) { | 
					
						
							|  |  |  | 		ast_free(ret); | 
					
						
							|  |  |  | 		return EINVAL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-02 17:18:42 +02:00
										 |  |  |     snprintf(ret, buf_size - 1, "%s", ast_sip_security_mechanism_type_to_str(security_mechanism->type)); | 
					
						
							| 
									
										
										
										
											2022-07-26 14:01:04 +02:00
										 |  |  | 	if (add_qvalue) { | 
					
						
							| 
									
										
										
										
											2023-05-02 17:18:42 +02:00
										 |  |  | 		snprintf(ret + strlen(ret), buf_size - 1, ";q=%f.4", security_mechanism->qvalue); | 
					
						
							| 
									
										
										
										
											2022-07-26 14:01:04 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	size = AST_VECTOR_SIZE(&security_mechanism->mechanism_parameters); | 
					
						
							|  |  |  | 	for (i = 0; i < size; ++i) { | 
					
						
							| 
									
										
										
										
											2023-05-02 17:18:42 +02:00
										 |  |  | 		snprintf(ret + strlen(ret), buf_size - 1, ";%s", AST_VECTOR_GET(&security_mechanism->mechanism_parameters, i)); | 
					
						
							| 
									
										
										
										
											2022-07-26 14:01:04 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	*buf = ret; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-02 17:18:42 +02:00
										 |  |  | int ast_sip_security_mechanisms_to_str(const struct ast_sip_security_mechanism_vector *security_mechanisms, int add_qvalue, char **buf) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	size_t vec_size; | 
					
						
							|  |  |  | 	struct ast_sip_security_mechanism *mech; | 
					
						
							|  |  |  | 	char *tmp_buf; | 
					
						
							|  |  |  | 	char ret[512]; | 
					
						
							|  |  |  | 	size_t i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!security_mechanisms) { | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vec_size = AST_VECTOR_SIZE(security_mechanisms); | 
					
						
							|  |  |  | 	ret[0] = '\0'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < vec_size; ++i) { | 
					
						
							|  |  |  | 		mech = AST_VECTOR_GET(security_mechanisms, i); | 
					
						
							|  |  |  | 		if (security_mechanism_to_str(mech, add_qvalue, &tmp_buf)) { | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		snprintf(ret + strlen(ret), sizeof(ret) - 1, "%s%s", | 
					
						
							|  |  |  | 		   tmp_buf, i == vec_size - 1 ? "" : ", "); | 
					
						
							|  |  |  | 		ast_free(tmp_buf); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	*buf = ast_strdup(ret); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-26 14:01:04 +02:00
										 |  |  | void ast_sip_remove_headers_by_name_and_value(pjsip_msg *msg, const pj_str_t *hdr_name, const char* value) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct pjsip_generic_string_hdr *hdr = pjsip_msg_find_hdr_by_name(msg, hdr_name, NULL); | 
					
						
							|  |  |  | 	for (; hdr; hdr = pjsip_msg_find_hdr_by_name(msg, hdr_name, hdr->next)) { | 
					
						
							|  |  |  | 		if (value == NULL || !pj_strcmp2(&hdr->hvalue, value)) { | 
					
						
							|  |  |  | 			pj_list_erase(hdr); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (hdr->next == hdr) { | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*!
 | 
					
						
							|  |  |  |  * \internal | 
					
						
							|  |  |  |  * \brief Parses a string representing a q_value to a float. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Valid q values must be in the range from 0.0 to 1.0 inclusively. | 
					
						
							| 
									
										
										
										
											2023-05-02 17:18:42 +02:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2022-07-26 14:01:04 +02:00
										 |  |  |  * \param q_value | 
					
						
							|  |  |  |  * \retval The parsed qvalue or -1.0 on failure. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static float parse_qvalue(const char *q_value) { | 
					
						
							|  |  |  | 	char *end; | 
					
						
							|  |  |  | 	float ret = strtof(q_value, &end); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (end == q_value) { | 
					
						
							|  |  |  | 		/* Not a number. */ | 
					
						
							|  |  |  | 		return -1.0; | 
					
						
							|  |  |  | 	} else if ('\0' != *end) { | 
					
						
							|  |  |  | 		/* Extra character at end of input. */ | 
					
						
							|  |  |  | 		return -1.0; | 
					
						
							|  |  |  | 	} else if (ret > 1.0 || ret < 0.0) { | 
					
						
							|  |  |  | 		/* Out of valid range. */ | 
					
						
							|  |  |  | 		return -1.0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ast_sip_str_to_security_mechanism(struct ast_sip_security_mechanism **security_mechanism, const char *value) { | 
					
						
							|  |  |  | 	struct ast_sip_security_mechanism *mech; | 
					
						
							|  |  |  | 	char *param; | 
					
						
							|  |  |  | 	char *tmp; | 
					
						
							|  |  |  | 	char *mechanism = ast_strdupa(value); | 
					
						
							|  |  |  | 	int err = 0; | 
					
						
							|  |  |  | 	int type = -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mech = ast_sip_security_mechanisms_alloc(1); | 
					
						
							|  |  |  | 	if (!mech) { | 
					
						
							|  |  |  | 		err = ENOMEM; | 
					
						
							|  |  |  | 		goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tmp = ast_strsep(&mechanism, ';', AST_STRSEP_ALL); | 
					
						
							|  |  |  | 	type = ast_sip_str_to_security_mechanism_type(tmp); | 
					
						
							|  |  |  | 	if (type == -1) { | 
					
						
							|  |  |  | 		err = EINVAL; | 
					
						
							|  |  |  | 		goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mech->type = type; | 
					
						
							|  |  |  | 	while ((param = ast_strsep(&mechanism, ';', AST_STRSEP_ALL))) { | 
					
						
							|  |  |  | 		if (!param) { | 
					
						
							|  |  |  | 			err = EINVAL; | 
					
						
							|  |  |  | 			goto out; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2023-05-02 17:18:42 +02:00
										 |  |  | 		if (!strncmp(param, "q=", 2)) { | 
					
						
							| 
									
										
										
										
											2022-07-26 14:01:04 +02:00
										 |  |  | 			mech->qvalue = parse_qvalue(¶m[2]); | 
					
						
							|  |  |  | 			if (mech->qvalue < 0.0) { | 
					
						
							| 
									
										
										
										
											2023-05-02 17:18:42 +02:00
										 |  |  | 				err = EINVAL; | 
					
						
							| 
									
										
										
										
											2022-07-26 14:01:04 +02:00
										 |  |  | 				goto out; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		param = ast_strdup(param); | 
					
						
							|  |  |  | 		AST_VECTOR_APPEND(&mech->mechanism_parameters, param); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	*security_mechanism = mech; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | out: | 
					
						
							|  |  |  | 	if (err && (mech != NULL)) { | 
					
						
							|  |  |  | 		ast_sip_security_mechanisms_destroy(mech); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return err; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ast_sip_add_security_headers(struct ast_sip_security_mechanism_vector *security_mechanisms, | 
					
						
							|  |  |  | 		const char *header_name, int add_qval, pjsip_tx_data *tdata) { | 
					
						
							|  |  |  | 	struct ast_sip_security_mechanism *mech; | 
					
						
							|  |  |  | 	char *buf; | 
					
						
							|  |  |  | 	int mech_cnt; | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 	int add_qvalue = 1; | 
					
						
							| 
									
										
										
										
											2024-07-03 14:50:47 -06:00
										 |  |  | 	static const pj_str_t proxy_require = { "Proxy-Require", 13 }; | 
					
						
							|  |  |  | 	static const pj_str_t require = { "Require", 7 }; | 
					
						
							| 
									
										
										
										
											2022-07-26 14:01:04 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (!security_mechanisms || !tdata) { | 
					
						
							|  |  |  | 		return EINVAL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!strcmp(header_name, "Security-Client")) { | 
					
						
							|  |  |  | 		add_qvalue = 0; | 
					
						
							|  |  |  | 	} else if (strcmp(header_name, "Security-Server") && | 
					
						
							|  |  |  | 			strcmp(header_name, "Security-Verify")) { | 
					
						
							|  |  |  | 		return EINVAL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	/* If we're adding Security-Client headers, don't add q-value
 | 
					
						
							|  |  |  | 	 * even if the function caller requested it. */ | 
					
						
							|  |  |  | 	add_qvalue = add_qvalue && add_qval; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mech_cnt = AST_VECTOR_SIZE(security_mechanisms); | 
					
						
							|  |  |  | 	for (i = 0; i < mech_cnt; ++i) { | 
					
						
							|  |  |  | 		mech = AST_VECTOR_GET(security_mechanisms, i); | 
					
						
							| 
									
										
										
										
											2023-05-02 17:18:42 +02:00
										 |  |  | 		if (security_mechanism_to_str(mech, add_qvalue, &buf)) { | 
					
						
							| 
									
										
										
										
											2022-07-26 14:01:04 +02:00
										 |  |  | 			continue; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		ast_sip_add_header(tdata, header_name, buf); | 
					
						
							|  |  |  | 		ast_free(buf); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-07-03 14:50:47 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (pjsip_msg_find_hdr_by_name(tdata->msg, &require, NULL) == NULL) { | 
					
						
							|  |  |  | 		ast_sip_add_header(tdata, "Require", "mediasec"); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (pjsip_msg_find_hdr_by_name(tdata->msg, &proxy_require, NULL) == NULL) { | 
					
						
							|  |  |  | 		ast_sip_add_header(tdata, "Proxy-Require", "mediasec"); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-07-26 14:01:04 +02:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ast_sip_header_to_security_mechanism(const pjsip_generic_string_hdr *hdr, | 
					
						
							|  |  |  | 		struct ast_sip_security_mechanism_vector *security_mechanisms) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	struct ast_sip_security_mechanism *mech; | 
					
						
							|  |  |  | 	char buf[512]; | 
					
						
							|  |  |  | 	char *hdr_val; | 
					
						
							|  |  |  | 	char *mechanism; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!security_mechanisms || !hdr) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (pj_stricmp2(&hdr->name, "Security-Client") && pj_stricmp2(&hdr->name, "Security-Server") && | 
					
						
							|  |  |  | 			pj_stricmp2(&hdr->name, "Security-Verify")) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_copy_pj_str(buf, &hdr->hvalue, sizeof(buf)); | 
					
						
							|  |  |  | 	hdr_val = ast_skip_blanks(buf); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while ((mechanism = ast_strsep(&hdr_val, ',', AST_STRSEP_ALL))) { | 
					
						
							|  |  |  | 		if (!ast_sip_str_to_security_mechanism(&mech, mechanism)) { | 
					
						
							|  |  |  | 			AST_VECTOR_APPEND(security_mechanisms, mech); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ast_sip_security_mechanism_vector_init(struct ast_sip_security_mechanism_vector *security_mechanisms, const char *value) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	char *val = value ? ast_strdupa(value) : NULL; | 
					
						
							|  |  |  | 	struct ast_sip_security_mechanism *mech; | 
					
						
							|  |  |  | 	char *mechanism; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_sip_security_mechanisms_vector_destroy(security_mechanisms); | 
					
						
							|  |  |  | 	if (AST_VECTOR_INIT(security_mechanisms, 1)) { | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!val) { | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while ((mechanism = ast_strsep(&val, ',', AST_STRSEP_ALL))) { | 
					
						
							|  |  |  | 		if (!ast_sip_str_to_security_mechanism(&mech, mechanism)) { | 
					
						
							|  |  |  | 			AST_VECTOR_APPEND(security_mechanisms, mech); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } |