1 /*
2 The oSIP library implements the Session Initiation Protocol (SIP -rfc3261-)
3 Copyright (C) 2001-2020 Aymeric MOIZARD amoizard@antisip.com
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20 #include <osipparser2/internal.h>
21
22 #include <osipparser2/osip_port.h>
23 #include <osipparser2/osip_message.h>
24 #include <osipparser2/osip_parser.h>
25 #include "parser.h"
26
27 #ifndef MINISIZE
28
osip_authentication_info_init(osip_authentication_info_t ** dest)29 int osip_authentication_info_init(osip_authentication_info_t **dest) {
30 *dest = (osip_authentication_info_t *) osip_malloc(sizeof(osip_authentication_info_t));
31
32 if (*dest == NULL)
33 return OSIP_NOMEM;
34
35 memset(*dest, 0, sizeof(osip_authentication_info_t));
36 return OSIP_SUCCESS;
37 }
38
39 /* fills the www-authenticate header of message. */
40 /* INPUT : char *hvalue | value of header. */
41 /* OUTPUT: osip_message_t *sip | structure to save results. */
42 /* returns -1 on error. */
osip_message_set_authentication_info(osip_message_t * sip,const char * hvalue)43 int osip_message_set_authentication_info(osip_message_t *sip, const char *hvalue) {
44 osip_authentication_info_t *authentication_info;
45 int i;
46
47 if (hvalue == NULL || hvalue[0] == '\0')
48 return OSIP_SUCCESS;
49
50 if (sip == NULL)
51 return OSIP_BADPARAMETER;
52
53 i = osip_authentication_info_init(&authentication_info);
54
55 if (i != 0)
56 return i;
57
58 i = osip_authentication_info_parse(authentication_info, hvalue);
59
60 if (i != 0) {
61 osip_authentication_info_free(authentication_info);
62 return i;
63 }
64
65 sip->message_property = 2;
66
67 osip_list_add(&sip->authentication_infos, authentication_info, -1);
68 return OSIP_SUCCESS;
69 }
70
71 /* fills the authentication_info strucuture. */
72 /* INPUT : char *hvalue | value of header. */
73 /* OUTPUT: osip_message_t *sip | structure to save results. */
74 /* returns -1 on error. */
75 /* TODO:
76 digest-challenge tken has no order preference??
77 verify many situations (extra SP....)
78 */
osip_authentication_info_parse(osip_authentication_info_t * ainfo,const char * hvalue)79 int osip_authentication_info_parse(osip_authentication_info_t *ainfo, const char *hvalue) {
80 const char *space, *hack;
81 const char *next = NULL;
82 int i;
83
84 space = strchr(hvalue, ' ');
85 hack = strchr(hvalue, '=');
86
87 if (space && hack && hack > space) {
88 ainfo->auth_type = (char *) osip_malloc(space - hvalue + 1);
89
90 if (ainfo->auth_type == NULL)
91 return OSIP_NOMEM;
92
93 osip_strncpy(ainfo->auth_type, hvalue, space - hvalue);
94
95 } else
96 space = hvalue;
97
98 for (;;) {
99 int parse_ok = 0;
100
101 i = __osip_quoted_string_set("nextnonce", space, &(ainfo->nextnonce), &next);
102
103 if (i != 0)
104 return i;
105
106 if (next == NULL)
107 return OSIP_SUCCESS; /* end of header detected! */
108 else if (next != space) {
109 space = next;
110 parse_ok++;
111 }
112
113 i = __osip_quoted_string_set("cnonce", space, &(ainfo->cnonce), &next);
114
115 if (i != 0)
116 return i;
117
118 if (next == NULL)
119 return OSIP_SUCCESS; /* end of header detected! */
120 else if (next != space) {
121 space = next;
122 parse_ok++;
123 }
124
125 i = __osip_quoted_string_set("rspauth", space, &(ainfo->rspauth), &next);
126
127 if (i != 0)
128 return i;
129
130 if (next == NULL)
131 return OSIP_SUCCESS; /* end of header detected! */
132 else if (next != space) {
133 space = next;
134 parse_ok++;
135 }
136
137 i = __osip_token_set("nc", space, &(ainfo->nonce_count), &next);
138
139 if (i != 0)
140 return i;
141
142 if (next == NULL)
143 return OSIP_SUCCESS; /* end of header detected! */
144 else if (next != space) {
145 space = next;
146 parse_ok++;
147 }
148
149 i = __osip_token_set("qop", space, &(ainfo->qop_options), &next);
150
151 if (i != 0)
152 return i;
153
154 if (next == NULL)
155 return OSIP_SUCCESS; /* end of header detected! */
156 else if (next != space) {
157 space = next;
158 parse_ok++;
159 }
160
161 i = __osip_quoted_string_set("snum", space, &(ainfo->snum), &next);
162
163 if (i != 0)
164 return i;
165
166 if (next == NULL)
167 return OSIP_SUCCESS; /* end of header detected! */
168 else if (next != space) {
169 space = next;
170 parse_ok++;
171 }
172
173 i = __osip_quoted_string_set("srand", space, &(ainfo->srand), &next);
174
175 if (i != 0)
176 return i;
177
178 if (next == NULL)
179 return OSIP_SUCCESS; /* end of header detected! */
180 else if (next != space) {
181 space = next;
182 parse_ok++;
183 }
184
185 i = __osip_quoted_string_set("targetname", space, &(ainfo->targetname), &next);
186
187 if (i != 0)
188 return i;
189
190 if (next == NULL)
191 return OSIP_SUCCESS; /* end of header detected! */
192 else if (next != space) {
193 space = next;
194 parse_ok++;
195 }
196
197 i = __osip_quoted_string_set("realm", space, &(ainfo->realm), &next);
198
199 if (i != 0)
200 return i;
201
202 if (next == NULL)
203 return OSIP_SUCCESS; /* end of header detected! */
204 else if (next != space) {
205 space = next;
206 parse_ok++;
207 }
208
209 i = __osip_quoted_string_set("opaque", space, &(ainfo->opaque), &next);
210
211 if (i != 0)
212 return i;
213
214 if (next == NULL)
215 return OSIP_SUCCESS; /* end of header detected! */
216 else if (next != space) {
217 space = next;
218 parse_ok++;
219 }
220
221 if (0 == parse_ok) {
222 const char *quote1, *quote2, *tmp;
223
224 /* CAUTION */
225 /* parameter not understood!!! I'm too lazy to handle IT */
226 /* let's simply bypass it */
227 if (strlen(space) < 1)
228 return OSIP_SUCCESS;
229
230 tmp = strchr(space + 1, ',');
231
232 if (tmp == NULL) /* it was the last header */
233 return OSIP_SUCCESS;
234
235 quote1 = __osip_quote_find(space);
236
237 if ((quote1 != NULL) && (quote1 < tmp)) { /* this may be a quoted string! */
238 quote2 = __osip_quote_find(quote1 + 1);
239
240 if (quote2 == NULL)
241 return OSIP_SYNTAXERROR; /* bad header format... */
242
243 if (tmp < quote2) /* the comma is inside the quotes! */
244 space = strchr(quote2, ',');
245
246 else
247 space = tmp;
248
249 if (space == NULL) /* it was the last header */
250 return OSIP_SUCCESS;
251
252 } else
253 space = tmp;
254
255 /* continue parsing... */
256 }
257 }
258
259 return OSIP_SUCCESS; /* ok */
260 }
261
262 /* returns the authentication_info header. */
263 /* INPUT : osip_message_t *sip | sip message. */
264 /* returns null on error. */
osip_message_get_authentication_info(const osip_message_t * sip,int pos,osip_authentication_info_t ** dest)265 int osip_message_get_authentication_info(const osip_message_t *sip, int pos, osip_authentication_info_t **dest) {
266 osip_authentication_info_t *authentication_info;
267
268 *dest = NULL;
269
270 if (osip_list_size(&sip->authentication_infos) <= pos)
271 return OSIP_UNDEFINED_ERROR; /* does not exist */
272
273 authentication_info = (osip_authentication_info_t *) osip_list_get(&sip->authentication_infos, pos);
274
275 *dest = authentication_info;
276 return pos;
277 }
278
osip_authentication_info_get_auth_type(osip_authentication_info_t * authentication_info)279 char *osip_authentication_info_get_auth_type(osip_authentication_info_t *authentication_info) {
280 return authentication_info->auth_type;
281 }
282
osip_authentication_info_set_auth_type(osip_authentication_info_t * authentication_info,char * auth_type)283 void osip_authentication_info_set_auth_type(osip_authentication_info_t *authentication_info, char *auth_type) {
284 authentication_info->auth_type = (char *) auth_type;
285 }
286
osip_authentication_info_get_nextnonce(osip_authentication_info_t * authentication_info)287 char *osip_authentication_info_get_nextnonce(osip_authentication_info_t *authentication_info) {
288 return authentication_info->nextnonce;
289 }
290
osip_authentication_info_set_nextnonce(osip_authentication_info_t * authentication_info,char * nextnonce)291 void osip_authentication_info_set_nextnonce(osip_authentication_info_t *authentication_info, char *nextnonce) {
292 authentication_info->nextnonce = (char *) nextnonce;
293 }
294
osip_authentication_info_get_cnonce(osip_authentication_info_t * authentication_info)295 char *osip_authentication_info_get_cnonce(osip_authentication_info_t *authentication_info) {
296 return authentication_info->cnonce;
297 }
298
osip_authentication_info_set_cnonce(osip_authentication_info_t * authentication_info,char * cnonce)299 void osip_authentication_info_set_cnonce(osip_authentication_info_t *authentication_info, char *cnonce) {
300 authentication_info->cnonce = (char *) cnonce;
301 }
302
osip_authentication_info_get_rspauth(osip_authentication_info_t * authentication_info)303 char *osip_authentication_info_get_rspauth(osip_authentication_info_t *authentication_info) {
304 return authentication_info->rspauth;
305 }
306
osip_authentication_info_set_rspauth(osip_authentication_info_t * authentication_info,char * rspauth)307 void osip_authentication_info_set_rspauth(osip_authentication_info_t *authentication_info, char *rspauth) {
308 authentication_info->rspauth = (char *) rspauth;
309 }
310
osip_authentication_info_get_nonce_count(osip_authentication_info_t * authentication_info)311 char *osip_authentication_info_get_nonce_count(osip_authentication_info_t *authentication_info) {
312 return authentication_info->nonce_count;
313 }
314
osip_authentication_info_set_nonce_count(osip_authentication_info_t * authentication_info,char * nonce_count)315 void osip_authentication_info_set_nonce_count(osip_authentication_info_t *authentication_info, char *nonce_count) {
316 authentication_info->nonce_count = (char *) nonce_count;
317 }
318
osip_authentication_info_get_qop_options(osip_authentication_info_t * authentication_info)319 char *osip_authentication_info_get_qop_options(osip_authentication_info_t *authentication_info) {
320 return authentication_info->qop_options;
321 }
322
osip_authentication_info_set_qop_options(osip_authentication_info_t * authentication_info,char * qop_options)323 void osip_authentication_info_set_qop_options(osip_authentication_info_t *authentication_info, char *qop_options) {
324 authentication_info->qop_options = (char *) qop_options;
325 }
326
osip_authentication_info_get_snum(osip_authentication_info_t * authentication_info)327 char *osip_authentication_info_get_snum(osip_authentication_info_t *authentication_info) {
328 return authentication_info->snum;
329 }
330
osip_authentication_info_set_snum(osip_authentication_info_t * authentication_info,char * snum)331 void osip_authentication_info_set_snum(osip_authentication_info_t *authentication_info, char *snum) {
332 authentication_info->snum = (char *) snum;
333 }
334
osip_authentication_info_get_srand(osip_authentication_info_t * authentication_info)335 char *osip_authentication_info_get_srand(osip_authentication_info_t *authentication_info) {
336 return authentication_info->srand;
337 }
338
osip_authentication_info_set_srand(osip_authentication_info_t * authentication_info,char * srand)339 void osip_authentication_info_set_srand(osip_authentication_info_t *authentication_info, char *srand) {
340 authentication_info->srand = (char *) srand;
341 }
342
osip_authentication_info_get_targetname(osip_authentication_info_t * authentication_info)343 char *osip_authentication_info_get_targetname(osip_authentication_info_t *authentication_info) {
344 return authentication_info->targetname;
345 }
346
osip_authentication_info_set_targetname(osip_authentication_info_t * authentication_info,char * targetname)347 void osip_authentication_info_set_targetname(osip_authentication_info_t *authentication_info, char *targetname) {
348 authentication_info->targetname = (char *) targetname;
349 }
350
osip_authentication_info_get_realm(osip_authentication_info_t * authentication_info)351 char *osip_authentication_info_get_realm(osip_authentication_info_t *authentication_info) {
352 return authentication_info->realm;
353 }
354
osip_authentication_info_set_realm(osip_authentication_info_t * authentication_info,char * realm)355 void osip_authentication_info_set_realm(osip_authentication_info_t *authentication_info, char *realm) {
356 authentication_info->realm = (char *) realm;
357 }
358
osip_authentication_info_get_opaque(osip_authentication_info_t * authentication_info)359 char *osip_authentication_info_get_opaque(osip_authentication_info_t *authentication_info) {
360 return authentication_info->opaque;
361 }
362
osip_authentication_info_set_opaque(osip_authentication_info_t * authentication_info,char * opaque)363 void osip_authentication_info_set_opaque(osip_authentication_info_t *authentication_info, char *opaque) {
364 authentication_info->opaque = (char *) opaque;
365 }
366
367 /* returns the authentication_info header as a string. */
368 /* INPUT : osip_authentication_info_t *authentication_info | authentication_info header. */
369 /* returns null on error. */
osip_authentication_info_to_str(const osip_authentication_info_t * ainfo,char ** dest)370 int osip_authentication_info_to_str(const osip_authentication_info_t *ainfo, char **dest) {
371 size_t len;
372 char *tmp, *start;
373
374 *dest = NULL;
375
376 if (ainfo == NULL)
377 return OSIP_BADPARAMETER;
378
379 len = 0;
380
381 if (ainfo->auth_type != NULL)
382 len = len + strlen(ainfo->auth_type) + 1;
383
384 if (ainfo->nextnonce != NULL)
385 len = len + strlen(ainfo->nextnonce) + 12; /* fixed Jan 10,2020: missing one byte */
386
387 if (ainfo->rspauth != NULL)
388 len = len + strlen(ainfo->rspauth) + 10;
389
390 if (ainfo->cnonce != NULL)
391 len = len + strlen(ainfo->cnonce) + 9;
392
393 if (ainfo->nonce_count != NULL)
394 len = len + strlen(ainfo->nonce_count) + 5;
395
396 if (ainfo->qop_options != NULL)
397 len = len + strlen(ainfo->qop_options) + 6;
398
399 if (ainfo->snum != NULL)
400 len = len + strlen(ainfo->snum) + 7;
401
402 if (ainfo->srand != NULL)
403 len = len + strlen(ainfo->srand) + 8;
404
405 if (ainfo->targetname != NULL)
406 len = len + strlen(ainfo->targetname) + 13;
407
408 if (ainfo->realm != NULL)
409 len = len + strlen(ainfo->realm) + 8;
410
411 if (ainfo->opaque != NULL)
412 len = len + strlen(ainfo->opaque) + 9; /* fixed Jan 10,2020: missing one byte */
413
414 if (len == 0)
415 return OSIP_BADPARAMETER;
416
417 len++; /* fixed Jan 10,2020: missing one byte for the final \0 added by osip_str_append */
418 tmp = (char *) osip_malloc(len);
419
420 if (tmp == NULL)
421 return OSIP_NOMEM;
422
423 *dest = tmp;
424
425 start = tmp;
426
427 if (ainfo->auth_type != NULL) {
428 tmp = osip_str_append(tmp, ainfo->auth_type);
429 tmp = osip_str_append(tmp, " ");
430 start = tmp;
431 }
432
433 if (ainfo->qop_options != NULL) {
434 if (tmp != start) {
435 tmp = osip_strn_append(tmp, ", ", 2);
436 }
437
438 tmp = osip_strn_append(tmp, "qop=", 4);
439 tmp = osip_str_append(tmp, ainfo->qop_options);
440 }
441
442 if (ainfo->nextnonce != NULL) {
443 if (tmp != start) {
444 tmp = osip_strn_append(tmp, ", ", 2);
445 }
446
447 tmp = osip_strn_append(tmp, "nextnonce=", 10);
448 tmp = osip_str_append(tmp, ainfo->nextnonce);
449 }
450
451 if (ainfo->rspauth != NULL) {
452 if (tmp != start) {
453 tmp = osip_strn_append(tmp, ", ", 2);
454 }
455
456 tmp = osip_strn_append(tmp, "rspauth=", 8);
457 tmp = osip_str_append(tmp, ainfo->rspauth);
458 }
459
460 if (ainfo->cnonce != NULL) {
461 if (tmp != start) {
462 tmp = osip_strn_append(tmp, ", ", 2);
463 }
464
465 tmp = osip_strn_append(tmp, "cnonce=", 7);
466 tmp = osip_str_append(tmp, ainfo->cnonce);
467 }
468
469 if (ainfo->nonce_count != NULL) {
470 if (tmp != start) {
471 tmp = osip_strn_append(tmp, ", ", 2);
472 }
473
474 tmp = osip_strn_append(tmp, "nc=", 3);
475 tmp = osip_str_append(tmp, ainfo->nonce_count);
476 }
477
478 if (ainfo->snum != NULL) {
479 if (tmp != start) {
480 tmp = osip_strn_append(tmp, ", ", 2);
481 }
482
483 tmp = osip_strn_append(tmp, "snum=", 5);
484 tmp = osip_str_append(tmp, ainfo->snum);
485 }
486
487 if (ainfo->srand != NULL) {
488 if (tmp != start) {
489 tmp = osip_strn_append(tmp, ", ", 2);
490 }
491
492 tmp = osip_strn_append(tmp, "srand=", 6);
493 tmp = osip_str_append(tmp, ainfo->srand);
494 }
495
496 if (ainfo->targetname != NULL) {
497 if (tmp != start) {
498 tmp = osip_strn_append(tmp, ", ", 2);
499 }
500
501 tmp = osip_strn_append(tmp, "targetname=", 11);
502 tmp = osip_str_append(tmp, ainfo->targetname);
503 }
504
505 if (ainfo->realm != NULL) {
506 if (tmp != start) {
507 tmp = osip_strn_append(tmp, ", ", 2);
508 }
509
510 tmp = osip_strn_append(tmp, "realm=", 6);
511 tmp = osip_str_append(tmp, ainfo->realm);
512 }
513
514 if (ainfo->opaque != NULL) {
515 if (tmp != start) {
516 tmp = osip_strn_append(tmp, ", ", 2);
517 }
518
519 tmp = osip_strn_append(tmp, "opaque=", 7);
520 tmp = osip_str_append(tmp, ainfo->opaque);
521 }
522
523 return OSIP_SUCCESS;
524 }
525
526 /* deallocates a osip_authentication_info_t structure. */
527 /* INPUT : osip_authentication_info_t *authentication_info | authentication_info. */
osip_authentication_info_free(osip_authentication_info_t * authentication_info)528 void osip_authentication_info_free(osip_authentication_info_t *authentication_info) {
529 if (authentication_info == NULL)
530 return;
531
532 osip_free(authentication_info->auth_type);
533 osip_free(authentication_info->nextnonce);
534 osip_free(authentication_info->rspauth);
535 osip_free(authentication_info->cnonce);
536 osip_free(authentication_info->nonce_count);
537 osip_free(authentication_info->qop_options);
538 osip_free(authentication_info->snum);
539 osip_free(authentication_info->srand);
540 osip_free(authentication_info->targetname);
541 osip_free(authentication_info->realm);
542 osip_free(authentication_info->opaque);
543 osip_free(authentication_info);
544 }
545
osip_authentication_info_clone(const osip_authentication_info_t * ainfo,osip_authentication_info_t ** dest)546 int osip_authentication_info_clone(const osip_authentication_info_t *ainfo, osip_authentication_info_t **dest) {
547 int i;
548 osip_authentication_info_t *wa;
549
550 *dest = NULL;
551
552 if (ainfo == NULL)
553 return OSIP_BADPARAMETER;
554
555 i = osip_authentication_info_init(&wa);
556
557 if (i != 0) /* allocation failed */
558 return i;
559
560 if (ainfo->auth_type != NULL)
561 wa->auth_type = osip_strdup(ainfo->auth_type);
562
563 if (ainfo->nextnonce != NULL)
564 wa->nextnonce = osip_strdup(ainfo->nextnonce);
565
566 if (ainfo->cnonce != NULL)
567 wa->cnonce = osip_strdup(ainfo->cnonce);
568
569 if (ainfo->rspauth != NULL)
570 wa->rspauth = osip_strdup(ainfo->rspauth);
571
572 if (ainfo->nonce_count != NULL)
573 wa->nonce_count = osip_strdup(ainfo->nonce_count);
574
575 if (ainfo->qop_options != NULL)
576 wa->qop_options = osip_strdup(ainfo->qop_options);
577
578 if (ainfo->snum != NULL)
579 wa->snum = osip_strdup(ainfo->snum);
580
581 if (ainfo->srand != NULL)
582 wa->srand = osip_strdup(ainfo->srand);
583
584 if (ainfo->targetname != NULL)
585 wa->targetname = osip_strdup(ainfo->targetname);
586
587 if (ainfo->realm != NULL)
588 wa->realm = osip_strdup(ainfo->realm);
589
590 if (ainfo->opaque != NULL)
591 wa->opaque = osip_strdup(ainfo->opaque);
592
593 *dest = wa;
594 return OSIP_SUCCESS;
595 }
596
597 #endif
598