Asterisk - The Open Source Telephony Project GIT-master-7e7a603
security_agreements.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2022, Commend International
5 *
6 * Maximilian Fridrich <m.fridrich@commend.com>
7 *
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
13 *
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
17 */
18
19/*!
20 * \file
21 *
22 * \brief Interact with security agreement negotiations and mechanisms
23 *
24 * \author Maximilian Fridrich <m.fridrich@commend.com>
25 */
26
27#include "asterisk.h"
28
29#include <pjsip.h>
30
31#include "asterisk/res_pjsip.h"
32
34{
35 struct ast_sip_security_mechanism *mech;
36
37 mech = ast_calloc(1, sizeof(struct ast_sip_security_mechanism));
38 if (mech == NULL) {
39 return NULL;
40 }
41 mech->qvalue = 0.0;
42 if (AST_VECTOR_INIT(&mech->mechanism_parameters, n_params) != 0) {
43 ast_free(mech);
44 return NULL;
45 }
46
47 return mech;
48}
49
51 const struct ast_sip_security_mechanism *src)
52{
53 struct ast_sip_security_mechanism *dst = NULL;
54 int i, n_params;
55 char *param;
56
57 n_params = AST_VECTOR_SIZE(&src->mechanism_parameters);
58
60 if (dst == NULL) {
61 return NULL;
62 }
63 dst->type = src->type;
64 dst->qvalue = src->qvalue;
65
66 for (i = 0; i < n_params; i++) {
69 }
70
71 return dst;
72}
73
75{
76 int i;
77
78 for (i = 0; i < AST_VECTOR_SIZE(&mech->mechanism_parameters); i++) {
80 }
82 ast_free(mech);
83}
84
86 const struct ast_sip_security_mechanism_vector *src)
87{
88 struct ast_sip_security_mechanism *mech;
89 int i;
90
92 for (i = 0; i < AST_VECTOR_SIZE(src); i++) {
93 mech = AST_VECTOR_GET(src, i);
95 }
96};
97
99{
100 struct ast_sip_security_mechanism *mech;
101 int i;
102
103 if (!security_mechanisms) {
104 return;
105 }
106
107 for (i = 0; i < AST_VECTOR_SIZE(security_mechanisms); i++) {
108 mech = AST_VECTOR_GET(security_mechanisms, i);
110 }
111 AST_VECTOR_FREE(security_mechanisms);
112}
113
114static int ast_sip_str_to_security_mechanism_type(const char *security_mechanism) {
115 int result = -1;
116
117 if (!strcasecmp(security_mechanism, "msrp-tls")) {
119 } else if (!strcasecmp(security_mechanism, "sdes-srtp")) {
121 } else if (!strcasecmp(security_mechanism, "dtls-srtp")) {
123 }
124
125 return result;
126}
127
129 if (mech_type == AST_SIP_SECURITY_MECH_MSRP_TLS) {
130 return "msrp-tls";
131 } else if (mech_type == AST_SIP_SECURITY_MECH_SDES_SRTP) {
132 return "sdes-srtp";
133 } else if (mech_type == AST_SIP_SECURITY_MECH_DTLS_SRTP) {
134 return "dtls-srtp";
135 } else {
136 return NULL;
137 }
138}
139
140static int security_mechanism_to_str(const struct ast_sip_security_mechanism *security_mechanism, int add_qvalue, char **buf)
141{
142 size_t size;
143 size_t buf_size = 128;
144 int i;
145 char *ret = ast_calloc(buf_size, sizeof(char));
146
147 if (ret == NULL) {
148 return ENOMEM;
149 }
150 if (security_mechanism == NULL) {
151 ast_free(ret);
152 return EINVAL;
153 }
154
155 snprintf(ret, buf_size - 1, "%s", ast_sip_security_mechanism_type_to_str(security_mechanism->type));
156 if (add_qvalue) {
157 snprintf(ret + strlen(ret), buf_size - 1, ";q=%f.4", security_mechanism->qvalue);
158 }
159
160 size = AST_VECTOR_SIZE(&security_mechanism->mechanism_parameters);
161 for (i = 0; i < size; ++i) {
162 snprintf(ret + strlen(ret), buf_size - 1, ";%s", AST_VECTOR_GET(&security_mechanism->mechanism_parameters, i));
163 }
164
165 *buf = ret;
166 return 0;
167}
168
169int ast_sip_security_mechanisms_to_str(const struct ast_sip_security_mechanism_vector *security_mechanisms, int add_qvalue, char **buf)
170{
171 size_t vec_size;
172 struct ast_sip_security_mechanism *mech;
173 char *tmp_buf;
174 char ret[512];
175 size_t i;
176
177 if (!security_mechanisms) {
178 return -1;
179 }
180
181 vec_size = AST_VECTOR_SIZE(security_mechanisms);
182 ret[0] = '\0';
183
184 for (i = 0; i < vec_size; ++i) {
185 mech = AST_VECTOR_GET(security_mechanisms, i);
186 if (security_mechanism_to_str(mech, add_qvalue, &tmp_buf)) {
187 continue;
188 }
189 snprintf(ret + strlen(ret), sizeof(ret) - 1, "%s%s",
190 tmp_buf, i == vec_size - 1 ? "" : ", ");
192 }
193
194 *buf = ast_strdup(ret);
195
196 return 0;
197}
198
199void ast_sip_remove_headers_by_name_and_value(pjsip_msg *msg, const pj_str_t *hdr_name, const char* value)
200{
201 struct pjsip_generic_string_hdr *hdr = pjsip_msg_find_hdr_by_name(msg, hdr_name, NULL);
202 for (; hdr; hdr = pjsip_msg_find_hdr_by_name(msg, hdr_name, hdr->next)) {
203 if (value == NULL || !pj_strcmp2(&hdr->hvalue, value)) {
204 pj_list_erase(hdr);
205 }
206 if (hdr->next == hdr) {
207 break;
208 }
209 }
210}
211
212/*!
213 * \internal
214 * \brief Parses a string representing a q_value to a float.
215 *
216 * Valid q values must be in the range from 0.0 to 1.0 inclusively.
217 *
218 * \param q_value
219 * \retval The parsed qvalue or -1.0 on failure.
220 */
221static float parse_qvalue(const char *q_value) {
222 char *end;
223 float ret = strtof(q_value, &end);
224
225 if (end == q_value) {
226 /* Not a number. */
227 return -1.0;
228 } else if ('\0' != *end) {
229 /* Extra character at end of input. */
230 return -1.0;
231 } else if (ret > 1.0 || ret < 0.0) {
232 /* Out of valid range. */
233 return -1.0;
234 }
235 return ret;
236}
237
238int ast_sip_str_to_security_mechanism(struct ast_sip_security_mechanism **security_mechanism, const char *value) {
239 struct ast_sip_security_mechanism *mech;
240 char *param;
241 char *tmp;
242 char *mechanism = ast_strdupa(value);
243 int err = 0;
244 int type = -1;
245
247 if (!mech) {
248 err = ENOMEM;
249 goto out;
250 }
251
252 tmp = ast_strsep(&mechanism, ';', AST_STRSEP_ALL);
254 if (type == -1) {
255 err = EINVAL;
256 goto out;
257 }
258
259 mech->type = type;
260 while ((param = ast_strsep(&mechanism, ';', AST_STRSEP_ALL))) {
261 if (!param) {
262 err = EINVAL;
263 goto out;
264 }
265 if (!strncmp(param, "q=", 2)) {
266 mech->qvalue = parse_qvalue(&param[2]);
267 if (mech->qvalue < 0.0) {
268 err = EINVAL;
269 goto out;
270 }
271 continue;
272 }
273 param = ast_strdup(param);
275 }
276
277 *security_mechanism = mech;
278
279out:
280 if (err && (mech != NULL)) {
282 }
283 return err;
284}
285
287 const char *header_name, int add_qval, pjsip_tx_data *tdata) {
288 struct ast_sip_security_mechanism *mech;
289 char *buf;
290 int mech_cnt;
291 int i;
292 int add_qvalue = 1;
293
294 if (!security_mechanisms || !tdata) {
295 return EINVAL;
296 }
297
298 if (!strcmp(header_name, "Security-Client")) {
299 add_qvalue = 0;
300 } else if (strcmp(header_name, "Security-Server") &&
301 strcmp(header_name, "Security-Verify")) {
302 return EINVAL;
303 }
304 /* If we're adding Security-Client headers, don't add q-value
305 * even if the function caller requested it. */
306 add_qvalue = add_qvalue && add_qval;
307
308 mech_cnt = AST_VECTOR_SIZE(security_mechanisms);
309 for (i = 0; i < mech_cnt; ++i) {
310 mech = AST_VECTOR_GET(security_mechanisms, i);
311 if (security_mechanism_to_str(mech, add_qvalue, &buf)) {
312 continue;
313 }
314 ast_sip_add_header(tdata, header_name, buf);
315 ast_free(buf);
316 }
317 return 0;
318}
319
320void ast_sip_header_to_security_mechanism(const pjsip_generic_string_hdr *hdr,
321 struct ast_sip_security_mechanism_vector *security_mechanisms) {
322
323 struct ast_sip_security_mechanism *mech;
324 char buf[512];
325 char *hdr_val;
326 char *mechanism;
327
328 if (!security_mechanisms || !hdr) {
329 return;
330 }
331
332 if (pj_stricmp2(&hdr->name, "Security-Client") && pj_stricmp2(&hdr->name, "Security-Server") &&
333 pj_stricmp2(&hdr->name, "Security-Verify")) {
334 return;
335 }
336
337 ast_copy_pj_str(buf, &hdr->hvalue, sizeof(buf));
338 hdr_val = ast_skip_blanks(buf);
339
340 while ((mechanism = ast_strsep(&hdr_val, ',', AST_STRSEP_ALL))) {
341 if (!ast_sip_str_to_security_mechanism(&mech, mechanism)) {
342 AST_VECTOR_APPEND(security_mechanisms, mech);
343 }
344 }
345}
346
348{
349 char *val = value ? ast_strdupa(value) : NULL;
350 struct ast_sip_security_mechanism *mech;
351 char *mechanism;
352
354 if (AST_VECTOR_INIT(security_mechanisms, 1)) {
355 return -1;
356 }
357
358 if (!val) {
359 return 0;
360 }
361
362 while ((mechanism = ast_strsep(&val, ',', AST_STRSEP_ALL))) {
363 if (!ast_sip_str_to_security_mechanism(&mech, mechanism)) {
364 AST_VECTOR_APPEND(security_mechanisms, mech);
365 }
366 }
367
368 return 0;
369}
Asterisk main include file. File version handling, generic pbx functions.
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
static int tmp()
Definition: bt_open.c:389
static PGresult * result
Definition: cel_pgsql.c:84
static const char type[]
Definition: chan_ooh323.c:109
char * end
Definition: eagi_proxy.c:73
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static struct ast_threadstorage tmp_buf
Definition: func_strings.c:48
ast_sip_security_mechanism_type
The security mechanism type.
Definition: res_pjsip.h:364
@ AST_SIP_SECURITY_MECH_DTLS_SRTP
Definition: res_pjsip.h:371
@ AST_SIP_SECURITY_MECH_SDES_SRTP
Definition: res_pjsip.h:369
@ AST_SIP_SECURITY_MECH_MSRP_TLS
Definition: res_pjsip.h:367
void ast_copy_pj_str(char *dest, const pj_str_t *src, size_t size)
Copy a pj_str_t into a standard character buffer.
Definition: res_pjsip.c:2201
int ast_sip_add_header(pjsip_tx_data *tdata, const char *name, const char *value)
Add a header to an outbound SIP message.
Definition: res_pjsip.c:2008
#define NULL
Definition: resample.c:96
void ast_sip_header_to_security_mechanism(const pjsip_generic_string_hdr *hdr, struct ast_sip_security_mechanism_vector *security_mechanisms)
Append to security mechanism vector from SIP header.
void ast_sip_security_mechanisms_vector_copy(struct ast_sip_security_mechanism_vector *dst, const struct ast_sip_security_mechanism_vector *src)
Duplicate a security mechanism.
static struct ast_sip_security_mechanism * ast_sip_security_mechanisms_copy(const struct ast_sip_security_mechanism *src)
static char * ast_sip_security_mechanism_type_to_str(enum ast_sip_security_mechanism_type mech_type)
static struct ast_sip_security_mechanism * ast_sip_security_mechanisms_alloc(size_t n_params)
void ast_sip_security_mechanisms_vector_destroy(struct ast_sip_security_mechanism_vector *security_mechanisms)
Free contents of a security mechanism vector.
static int security_mechanism_to_str(const struct ast_sip_security_mechanism *security_mechanism, int add_qvalue, char **buf)
int ast_sip_security_mechanism_vector_init(struct ast_sip_security_mechanism_vector *security_mechanisms, const char *value)
Initialize security mechanism vector from string of security mechanisms.
int ast_sip_security_mechanisms_to_str(const struct ast_sip_security_mechanism_vector *security_mechanisms, int add_qvalue, char **buf)
Writes the security mechanisms of an endpoint into a buffer as a string and returns the buffer.
int ast_sip_str_to_security_mechanism(struct ast_sip_security_mechanism **security_mechanism, const char *value)
Allocate a security mechanism from a string.
static float parse_qvalue(const char *q_value)
void ast_sip_remove_headers_by_name_and_value(pjsip_msg *msg, const pj_str_t *hdr_name, const char *value)
Removes all headers of a specific name and value from a pjsip_msg.
static int ast_sip_str_to_security_mechanism_type(const char *security_mechanism)
static void ast_sip_security_mechanisms_destroy(struct ast_sip_security_mechanism *mech)
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)
Add security headers to transmission data.
@ AST_STRSEP_ALL
Definition: strings.h:258
char * ast_strsep(char **s, const char sep, uint32_t flags)
Act like strsep but ignore separators inside quotes.
Definition: utils.c:1835
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition: strings.h:161
Structure representing a security mechanism as defined in RFC 3329.
Definition: res_pjsip.h:378
struct ast_vector_string mechanism_parameters
Definition: res_pjsip.h:384
enum ast_sip_security_mechanism_type type
Definition: res_pjsip.h:380
Definition: ast_expr2.c:325
int value
Definition: syslog.c:37
FILE * out
Definition: utils/frame.c:33
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:609
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:680