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