2 The oSIP library implements the Session Initiation Protocol (SIP -rfc3261-)
3 Copyright (C) 2001,2002,2003 Aymeric MOIZARD jack@atosc.org
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.
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.
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
24 #include <osipparser2/osip_port.h>
25 #include <osipparser2/osip_message.h>
26 #include <osipparser2/osip_parser.h>
30 osip_www_authenticate_init (osip_www_authenticate_t ** dest)
33 (osip_www_authenticate_t *)
34 osip_malloc (sizeof (osip_www_authenticate_t));
37 (*dest)->auth_type = NULL;
38 (*dest)->realm = NULL;
39 (*dest)->domain = NULL; /* optionnal */
40 (*dest)->nonce = NULL;
41 (*dest)->opaque = NULL; /* optionnal */
42 (*dest)->stale = NULL; /* optionnal */
43 (*dest)->algorithm = NULL; /* optionnal */
44 (*dest)->qop_options = NULL; /* optionnal (contains a list of qop-value) */
45 (*dest)->auth_param = NULL;
49 /* fills the www-authenticate header of message. */
50 /* INPUT : char *hvalue | value of header. */
51 /* OUTPUT: osip_message_t *sip | structure to save results. */
52 /* returns -1 on error. */
54 osip_message_set_www_authenticate (osip_message_t * sip, const char *hvalue)
56 osip_www_authenticate_t *www_authenticate;
59 if (hvalue == NULL || hvalue[0] == '\0')
62 if (sip == NULL || sip->www_authenticates == NULL)
64 i = osip_www_authenticate_init (&www_authenticate);
67 i = osip_www_authenticate_parse (www_authenticate, hvalue);
70 osip_www_authenticate_free (www_authenticate);
73 sip->message_property = 2;
74 osip_list_add (sip->www_authenticates, www_authenticate, -1);
79 __osip_quoted_string_set (const char *name, const char *str,
80 char **result, const char **next)
84 return 0; /* already parsed */
86 while ((' ' == *str) || ('\t' == *str) || (',' == *str))
90 return -1; /* bad header format */
92 if (strlen (str) <= strlen (name))
93 return -1; /* bad header format... */
94 if (osip_strncasecmp (name, str, strlen (name)) == 0)
99 const char *hack = strchr (str, '=');
104 while (' ' == *(hack - 1)) /* get rid of extra spaces */
106 if ((size_t) (hack - str) != strlen (name))
112 quote1 = __osip_quote_find (str);
114 return -1; /* bad header format... */
115 quote2 = __osip_quote_find (quote1 + 1);
117 return -1; /* bad header format... */
118 if (quote2 - quote1 == 1)
120 /* this is a special case! The quote contains nothing! */
121 /* example: Digest opaque="",cnonce="" */
122 /* in this case, we just forget the parameter... this */
123 /* this should prevent from user manipulating empty */
125 tmp = quote2 + 1; /* next element start here */
126 for (; *tmp == ' ' || *tmp == '\t'; tmp++)
129 for (; *tmp == '\n' || *tmp == '\r'; tmp++)
133 if (*tmp == '\0') /* end of header detected */
135 if (*tmp != '\t' && *tmp != ' ')
139 { /* it is: skip it... */
140 for (; *tmp == ' ' || *tmp == '\t'; tmp++)
143 if (*tmp == '\0') /* end of header detected */
149 *result = (char *) osip_malloc (quote2 - quote1 + 3);
152 osip_strncpy (*result, quote1, quote2 - quote1 + 1);
153 tmp = quote2 + 1; /* next element start here */
154 for (; *tmp == ' ' || *tmp == '\t'; tmp++)
157 for (; *tmp == '\n' || *tmp == '\r'; tmp++)
161 if (*tmp == '\0') /* end of header detected */
163 if (*tmp != '\t' && *tmp != ' ')
167 { /* it is: skip it... */
168 for (; *tmp == ' ' || *tmp == '\t'; tmp++)
171 if (*tmp == '\0') /* end of header detected */
177 *next = str; /* wrong header asked! */
182 __osip_token_set (const char *name, const char *str, char **result,
190 return 0; /* already parsed */
193 beg = strchr (str, '=');
195 return -1; /* bad header format... */
197 if (strlen (str) < 6)
198 return 0; /* end of header... */
200 while ((' ' == *str) || ('\t' == *str) || (',' == *str))
204 return -1; /* bad header format */
206 if (osip_strncasecmp (name, str, strlen (name)) == 0)
210 end = strchr (str, ',');
212 end = str + strlen (str); /* This is the end of the header */
216 *result = (char *) osip_malloc (end - beg);
219 osip_strncpy (*result, beg + 1, end - beg - 1);
220 osip_clrspace (*result);
222 /* make sure the element does not contain more parameter */
223 tmp = (*end) ? (end + 1) : end;
224 for (; *tmp == ' ' || *tmp == '\t'; tmp++)
227 for (; *tmp == '\n' || *tmp == '\r'; tmp++)
231 if (*tmp == '\0') /* end of header detected */
233 if (*tmp != '\t' && *tmp != ' ')
237 { /* it is: skip it... */
238 for (; *tmp == ' ' || *tmp == '\t'; tmp++)
241 if (*tmp == '\0') /* end of header detected */
247 *next = str; /* next element start here */
251 /* fills the www-authenticate strucuture. */
252 /* INPUT : char *hvalue | value of header. */
253 /* OUTPUT: osip_message_t *sip | structure to save results. */
254 /* returns -1 on error. */
256 digest-challenge tken has no order preference??
257 verify many situations (extra SP....)
260 osip_www_authenticate_parse (osip_www_authenticate_t * wwwa,
264 const char *next = NULL;
266 space = strchr (hvalue, ' '); /* SEARCH FOR SPACE */
270 if (space - hvalue + 1 < 2)
272 wwwa->auth_type = (char *) osip_malloc (space - hvalue + 1);
273 if (wwwa->auth_type == NULL)
275 osip_strncpy (wwwa->auth_type, hvalue, space - hvalue);
281 if (__osip_quoted_string_set ("realm", space, &(wwwa->realm), &next))
284 return 0; /* end of header detected! */
285 else if (next != space)
290 if (__osip_quoted_string_set ("domain", space, &(wwwa->domain), &next))
293 return 0; /* end of header detected! */
294 else if (next != space)
299 if (__osip_quoted_string_set ("nonce", space, &(wwwa->nonce), &next))
302 return 0; /* end of header detected! */
303 else if (next != space)
308 if (__osip_quoted_string_set ("opaque", space, &(wwwa->opaque), &next))
311 return 0; /* end of header detected! */
312 else if (next != space)
317 if (__osip_token_set ("stale", space, &(wwwa->stale), &next))
320 return 0; /* end of header detected! */
321 else if (next != space)
326 if (__osip_token_set ("algorithm", space, &(wwwa->algorithm), &next))
329 return 0; /* end of header detected! */
330 else if (next != space)
335 if (__osip_quoted_string_set
336 ("qop", space, &(wwwa->qop_options), &next))
339 return 0; /* end of header detected! */
340 else if (next != space)
347 char *quote1, *quote2, *tmp;
350 /* parameter not understood!!! I'm too lazy to handle IT */
351 /* let's simply bypass it */
352 if (strlen (space) < 1)
354 tmp = strchr (space + 1, ',');
355 if (tmp == NULL) /* it was the last header */
357 quote1 = __osip_quote_find (space);
358 if ((quote1 != NULL) && (quote1 < tmp)) /* this may be a quoted string! */
360 quote2 = __osip_quote_find (quote1 + 1);
362 return -1; /* bad header format... */
363 if (tmp < quote2) /* the comma is inside the quotes! */
364 space = strchr (quote2, ',');
367 if (space == NULL) /* it was the last header */
372 /* continue parsing... */
378 /* returns the www_authenticate header. */
379 /* INPUT : osip_message_t *sip | sip message. */
380 /* returns null on error. */
382 osip_message_get_www_authenticate (const osip_message_t * sip, int pos,
383 osip_www_authenticate_t ** dest)
385 osip_www_authenticate_t *www_authenticate;
388 if (osip_list_size (sip->www_authenticates) <= pos)
389 return -1; /* does not exist */
392 (osip_www_authenticate_t *) osip_list_get (sip->www_authenticates, pos);
394 *dest = www_authenticate;
399 osip_www_authenticate_get_auth_type (osip_www_authenticate_t *
402 return www_authenticate->auth_type;
406 osip_www_authenticate_set_auth_type (osip_www_authenticate_t *
407 www_authenticate, char *auth_type)
409 www_authenticate->auth_type = (char *) auth_type;
413 osip_www_authenticate_get_realm (osip_www_authenticate_t * www_authenticate)
415 return www_authenticate->realm;
419 osip_www_authenticate_set_realm (osip_www_authenticate_t * www_authenticate,
422 www_authenticate->realm = (char *) realm;
426 osip_www_authenticate_get_domain (osip_www_authenticate_t * www_authenticate)
428 return www_authenticate->domain;
432 osip_www_authenticate_set_domain (osip_www_authenticate_t * www_authenticate,
435 www_authenticate->domain = (char *) domain;
439 osip_www_authenticate_get_nonce (osip_www_authenticate_t * www_authenticate)
441 return www_authenticate->nonce;
445 osip_www_authenticate_set_nonce (osip_www_authenticate_t * www_authenticate,
448 www_authenticate->nonce = (char *) nonce;
452 osip_www_authenticate_get_stale (osip_www_authenticate_t * www_authenticate)
454 return www_authenticate->stale;
458 osip_www_authenticate_set_stale (osip_www_authenticate_t * www_authenticate,
461 www_authenticate->stale = (char *) stale;
465 osip_www_authenticate_get_opaque (osip_www_authenticate_t * www_authenticate)
467 return www_authenticate->opaque;
471 osip_www_authenticate_set_opaque (osip_www_authenticate_t * www_authenticate,
474 www_authenticate->opaque = (char *) opaque;
478 osip_www_authenticate_get_algorithm (osip_www_authenticate_t *
481 return www_authenticate->algorithm;
485 osip_www_authenticate_set_algorithm (osip_www_authenticate_t *
486 www_authenticate, char *algorithm)
488 www_authenticate->algorithm = (char *) algorithm;
492 osip_www_authenticate_get_qop_options (osip_www_authenticate_t *
495 return www_authenticate->qop_options;
499 osip_www_authenticate_set_qop_options (osip_www_authenticate_t *
500 www_authenticate, char *qop_options)
502 www_authenticate->qop_options = (char *) qop_options;
507 /* returns the www_authenticate header as a string. */
508 /* INPUT : osip_www_authenticate_t *www_authenticate | www_authenticate header. */
509 /* returns null on error. */
511 osip_www_authenticate_to_str (const osip_www_authenticate_t * wwwa,
518 if ((wwwa == NULL) || (wwwa->auth_type == NULL) || (wwwa->realm == NULL)
519 || (wwwa->nonce == NULL))
522 len = strlen (wwwa->auth_type) + 1;
524 if (wwwa->realm != NULL)
525 len = len + strlen (wwwa->realm) + 7;
526 if (wwwa->nonce != NULL)
527 len = len + strlen (wwwa->nonce) + 8;
529 if (wwwa->domain != NULL)
530 len = len + strlen (wwwa->domain) + 9;
531 if (wwwa->opaque != NULL)
532 len = len + strlen (wwwa->opaque) + 9;
533 if (wwwa->stale != NULL)
534 len = len + strlen (wwwa->stale) + 8;
535 if (wwwa->algorithm != NULL)
536 len = len + strlen (wwwa->algorithm) + 12;
537 if (wwwa->qop_options != NULL)
538 len = len + strlen (wwwa->qop_options) + 6;
540 tmp = (char *) osip_malloc (len);
545 osip_strncpy (tmp, wwwa->auth_type, strlen (wwwa->auth_type));
546 tmp = tmp + strlen (tmp);
548 if (wwwa->realm != NULL)
550 osip_strncpy (tmp, " realm=", 7);
552 osip_strncpy (tmp, wwwa->realm, strlen (wwwa->realm));
553 tmp = tmp + strlen (tmp);
555 if (wwwa->domain != NULL)
557 osip_strncpy (tmp, ", domain=", 9);
559 osip_strncpy (tmp, wwwa->domain, strlen (wwwa->domain));
560 tmp = tmp + strlen (tmp);
562 if (wwwa->nonce != NULL)
564 osip_strncpy (tmp, ", nonce=", 8);
566 osip_strncpy (tmp, wwwa->nonce, strlen (wwwa->nonce));
567 tmp = tmp + strlen (tmp);
569 if (wwwa->opaque != NULL)
571 osip_strncpy (tmp, ", opaque=", 9);
573 osip_strncpy (tmp, wwwa->opaque, strlen (wwwa->opaque));
574 tmp = tmp + strlen (tmp);
576 if (wwwa->stale != NULL)
578 osip_strncpy (tmp, ", stale=", 8);
580 osip_strncpy (tmp, wwwa->stale, strlen (wwwa->stale));
581 tmp = tmp + strlen (tmp);
583 if (wwwa->algorithm != NULL)
585 osip_strncpy (tmp, ", algorithm=", 12);
587 osip_strncpy (tmp, wwwa->algorithm, strlen (wwwa->algorithm));
588 tmp = tmp + strlen (tmp);
590 if (wwwa->qop_options != NULL)
592 osip_strncpy (tmp, ", qop=", 6);
594 osip_strncpy (tmp, wwwa->qop_options, strlen (wwwa->qop_options));
595 tmp = tmp + strlen (tmp);
601 /* deallocates a osip_www_authenticate_t structure. */
602 /* INPUT : osip_www_authenticate_t *www_authenticate | www_authenticate. */
604 osip_www_authenticate_free (osip_www_authenticate_t * www_authenticate)
606 if (www_authenticate == NULL)
609 osip_free (www_authenticate->auth_type);
610 osip_free (www_authenticate->realm);
611 osip_free (www_authenticate->domain);
612 osip_free (www_authenticate->nonce);
613 osip_free (www_authenticate->opaque);
614 osip_free (www_authenticate->stale);
615 osip_free (www_authenticate->algorithm);
616 osip_free (www_authenticate->qop_options);
618 osip_free (www_authenticate);
622 osip_www_authenticate_clone (const osip_www_authenticate_t * wwwa,
623 osip_www_authenticate_t ** dest)
626 osip_www_authenticate_t *wa;
631 if (wwwa->auth_type == NULL)
633 if (wwwa->realm == NULL)
635 if (wwwa->nonce == NULL)
638 i = osip_www_authenticate_init (&wa);
639 if (i == -1) /* allocation failed */
641 wa->auth_type = osip_strdup (wwwa->auth_type);
642 wa->realm = osip_strdup (wwwa->realm);
643 if (wwwa->domain != NULL)
644 wa->domain = osip_strdup (wwwa->domain);
645 wa->nonce = osip_strdup (wwwa->nonce);
646 if (wwwa->opaque != NULL)
647 wa->opaque = osip_strdup (wwwa->opaque);
648 if (wwwa->stale != NULL)
649 wa->stale = osip_strdup (wwwa->stale);
650 if (wwwa->algorithm != NULL)
651 wa->algorithm = osip_strdup (wwwa->algorithm);
652 if (wwwa->qop_options != NULL)
653 wa->qop_options = osip_strdup (wwwa->qop_options);