Revert "Revert "and added files""
[bcm963xx.git] / userapps / opensource / libosip2 / src / osipparser2 / osip_authorization.c
1 /*
2   The oSIP library implements the Session Initiation Protocol (SIP -rfc3261-)
3   Copyright (C) 2001,2002,2003  Aymeric MOIZARD jack@atosc.org
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
21 #include <stdlib.h>
22 #include <stdio.h>
23
24 #include <osipparser2/osip_port.h>
25 #include <osipparser2/osip_message.h>
26 #include <osipparser2/osip_parser.h>
27 #include "parser.h"
28
29 int
30 osip_authorization_init (osip_authorization_t ** dest)
31 {
32   *dest =
33     (osip_authorization_t *) osip_malloc (sizeof (osip_authorization_t));
34   if (*dest == NULL)
35     return -1;
36   (*dest)->auth_type = NULL;
37   (*dest)->username = NULL;
38   (*dest)->realm = NULL;
39   (*dest)->nonce = NULL;
40   (*dest)->uri = NULL;
41   (*dest)->response = NULL;
42   (*dest)->digest = NULL;       /* DO NOT USE IT IN AUTHORIZATION_T HEADER?? */
43   (*dest)->algorithm = NULL;    /* optionnal, default is "md5" */
44   (*dest)->cnonce = NULL;       /* optionnal */
45   (*dest)->opaque = NULL;       /* optionnal */
46   (*dest)->message_qop = NULL;  /* optionnal */
47   (*dest)->nonce_count = NULL;  /* optionnal */
48   (*dest)->auth_param = NULL;   /* for other headers --NOT IMPLEMENTED-- */
49   return 0;
50 }
51
52 /* fills the www-authenticate header of message.               */
53 /* INPUT :  char *hvalue | value of header.   */
54 /* OUTPUT: osip_message_t *sip | structure to save results. */
55 /* returns -1 on error. */
56 int
57 osip_message_set_authorization (osip_message_t * sip, const char *hvalue)
58 {
59   osip_authorization_t *authorization;
60   int i;
61
62   if (hvalue == NULL || hvalue[0] == '\0')
63     return 0;
64
65   if (sip == NULL || sip->authorizations == NULL)
66     return -1;
67   i = osip_authorization_init (&authorization);
68   if (i != 0)
69     return -1;
70   i = osip_authorization_parse (authorization, hvalue);
71   if (i != 0)
72     {
73       osip_authorization_free (authorization);
74       return -1;
75     }
76   sip->message_property = 2;
77   osip_list_add (sip->authorizations, authorization, -1);
78   return 0;
79 }
80
81 /* fills the www-authenticate structure.           */
82 /* INPUT : char *hvalue | value of header.         */
83 /* OUTPUT: osip_message_t *sip | structure to save results. */
84 /* returns -1 on error. */
85 /* TODO:
86    digest-challenge tken has no order preference??
87    verify many situations (extra SP....)
88 */
89 int
90 osip_authorization_parse (osip_authorization_t * auth, const char *hvalue)
91 {
92   const char *space;
93   const char *next = NULL;
94
95   space = strchr (hvalue, ' '); /* SEARCH FOR SPACE */
96   if (space == NULL)
97     return -1;
98
99   if (space - hvalue < 1)
100     return -1;
101   auth->auth_type = (char *) osip_malloc (space - hvalue + 1);
102   osip_strncpy (auth->auth_type, hvalue, space - hvalue);
103
104   for (;;)
105     {
106       int parse_ok = 0;
107
108       if (__osip_quoted_string_set
109           ("username", space, &(auth->username), &next))
110         return -1;
111       if (next == NULL)
112         return 0;               /* end of header detected! */
113       else if (next != space)
114         {
115           space = next;
116           parse_ok++;
117         }
118       if (__osip_quoted_string_set ("realm", space, &(auth->realm), &next))
119         return -1;
120       if (next == NULL)
121         return 0;
122       else if (next != space)
123         {
124           space = next;
125           parse_ok++;
126         }
127       if (__osip_quoted_string_set ("nonce", space, &(auth->nonce), &next))
128         return -1;
129       if (next == NULL)
130         return 0;               /* end of header detected! */
131       else if (next != space)
132         {
133           space = next;
134           parse_ok++;
135         }
136       if (__osip_quoted_string_set ("uri", space, &(auth->uri), &next))
137         return -1;
138       if (next == NULL)
139         return 0;               /* end of header detected! */
140       else if (next != space)
141         {
142           space = next;
143           parse_ok++;
144         }
145       if (__osip_quoted_string_set
146           ("response", space, &(auth->response), &next))
147         return -1;
148       if (next == NULL)
149         return 0;               /* end of header detected! */
150       else if (next != space)
151         {
152           space = next;
153           parse_ok++;
154         }
155       if (__osip_quoted_string_set ("digest", space, &(auth->digest), &next))
156         return -1;
157       if (next == NULL)
158         return 0;               /* end of header detected! */
159       else if (next != space)
160         {
161           space = next;
162           parse_ok++;
163         }
164       if (__osip_token_set ("algorithm", space, &(auth->algorithm), &next))
165         return -1;
166       if (next == NULL)
167         return 0;               /* end of header detected! */
168       else if (next != space)
169         {
170           space = next;
171           parse_ok++;
172         }
173       if (__osip_quoted_string_set ("cnonce", space, &(auth->cnonce), &next))
174         return -1;
175       if (next == NULL)
176         return 0;               /* end of header detected! */
177       else if (next != space)
178         {
179           space = next;
180           parse_ok++;
181         }
182       if (__osip_quoted_string_set ("opaque", space, &(auth->opaque), &next))
183         return -1;
184       if (next == NULL)
185         return 0;               /* end of header detected! */
186       else if (next != space)
187         {
188           space = next;
189           parse_ok++;
190         }
191       if (__osip_token_set ("qop", space, &(auth->message_qop), &next))
192         return -1;
193       if (next == NULL)
194         return 0;               /* end of header detected! */
195       else if (next != space)
196         {
197           space = next;
198           parse_ok++;
199         }
200       if (__osip_token_set ("nc", space, &(auth->nonce_count), &next))
201         return -1;
202       if (next == NULL)
203         return 0;               /* end of header detected! */
204       else if (next != space)
205         {
206           space = next;
207           parse_ok++;
208         }
209       /* nothing was recognized:
210          here, we should handle a list of unknown tokens where:
211          token1 = ( token2 | quoted_text ) */
212       /* TODO */
213
214       if (0 == parse_ok)
215         {
216           const char *quote1, *quote2, *tmp;
217
218           /* CAUTION */
219           /* parameter not understood!!! I'm too lazy to handle IT */
220           /* let's simply bypass it */
221           if (strlen (space) < 1)
222             return 0;
223           tmp = strchr (space + 1, ',');
224           if (tmp == NULL)      /* it was the last header */
225             return 0;
226           quote1 = __osip_quote_find (space);
227           if ((quote1 != NULL) && (quote1 < tmp))       /* this may be a quoted string! */
228             {
229               quote2 = __osip_quote_find (quote1 + 1);
230               if (quote2 == NULL)
231                 return -1;      /* bad header format... */
232               if (tmp < quote2) /* the comma is inside the quotes! */
233                 space = strchr (quote2, ',');
234               else
235                 space = tmp;
236               if (space == NULL)        /* it was the last header */
237                 return 0;
238             }
239           else
240             space = tmp;
241           /* continue parsing... */
242         }
243     }
244   return 0;                     /* ok */
245 }
246
247 /* returns the authorization header.   */
248 /* INPUT : osip_message_t *sip | sip message.   */
249 /* returns null on error. */
250 int
251 osip_message_get_authorization (const osip_message_t * sip, int pos,
252                                 osip_authorization_t ** dest)
253 {
254   osip_authorization_t *authorization;
255
256   *dest = NULL;
257   if (osip_list_size (sip->authorizations) <= pos)
258     return -1;                  /* does not exist */
259   authorization =
260     (osip_authorization_t *) osip_list_get (sip->authorizations, pos);
261   *dest = authorization;
262   return pos;
263 }
264
265 char *
266 osip_authorization_get_auth_type (const osip_authorization_t * authorization)
267 {
268   return authorization->auth_type;
269 }
270
271 void
272 osip_authorization_set_auth_type (osip_authorization_t * authorization,
273                                   char *auth_type)
274 {
275   authorization->auth_type = (char *) auth_type;
276 }
277
278 char *
279 osip_authorization_get_username (osip_authorization_t * authorization)
280 {
281   return authorization->username;
282 }
283
284 void
285 osip_authorization_set_username (osip_authorization_t * authorization,
286                                  char *username)
287 {
288   authorization->username = (char *) username;
289 }
290
291 char *
292 osip_authorization_get_realm (osip_authorization_t * authorization)
293 {
294   return authorization->realm;
295 }
296
297 void
298 osip_authorization_set_realm (osip_authorization_t * authorization,
299                               char *realm)
300 {
301   authorization->realm = (char *) realm;
302 }
303
304 char *
305 osip_authorization_get_nonce (osip_authorization_t * authorization)
306 {
307   return authorization->nonce;
308 }
309
310 void
311 osip_authorization_set_nonce (osip_authorization_t * authorization,
312                               char *nonce)
313 {
314   authorization->nonce = (char *) nonce;
315 }
316
317 char *
318 osip_authorization_get_uri (osip_authorization_t * authorization)
319 {
320   return authorization->uri;
321 }
322
323 void
324 osip_authorization_set_uri (osip_authorization_t * authorization, char *uri)
325 {
326   authorization->uri = (char *) uri;
327 }
328
329 char *
330 osip_authorization_get_response (osip_authorization_t * authorization)
331 {
332   return authorization->response;
333 }
334
335 void
336 osip_authorization_set_response (osip_authorization_t * authorization,
337                                  char *response)
338 {
339   authorization->response = (char *) response;
340 }
341
342 char *
343 osip_authorization_get_digest (osip_authorization_t * authorization)
344 {
345   return authorization->digest;
346 }
347
348 void
349 osip_authorization_set_digest (osip_authorization_t * authorization,
350                                char *digest)
351 {
352   authorization->digest = (char *) digest;
353 }
354
355 char *
356 osip_authorization_get_algorithm (osip_authorization_t * authorization)
357 {
358   return authorization->algorithm;
359 }
360
361 void
362 osip_authorization_set_algorithm (osip_authorization_t * authorization,
363                                   char *algorithm)
364 {
365   authorization->algorithm = (char *) algorithm;
366 }
367
368 char *
369 osip_authorization_get_cnonce (osip_authorization_t * authorization)
370 {
371   return authorization->cnonce;
372 }
373
374 void
375 osip_authorization_set_cnonce (osip_authorization_t * authorization,
376                                char *cnonce)
377 {
378   authorization->cnonce = (char *) cnonce;
379 }
380
381 char *
382 osip_authorization_get_opaque (osip_authorization_t * authorization)
383 {
384   return authorization->opaque;
385 }
386
387 void
388 osip_authorization_set_opaque (osip_authorization_t * authorization,
389                                char *opaque)
390 {
391   authorization->opaque = (char *) opaque;
392 }
393
394 char *
395 osip_authorization_get_message_qop (osip_authorization_t * authorization)
396 {
397   return authorization->message_qop;
398 }
399
400 void
401 osip_authorization_set_message_qop (osip_authorization_t * authorization,
402                                     char *message_qop)
403 {
404   authorization->message_qop = (char *) message_qop;
405 }
406
407 char *
408 osip_authorization_get_nonce_count (osip_authorization_t * authorization)
409 {
410   return authorization->nonce_count;
411 }
412
413 void
414 osip_authorization_set_nonce_count (osip_authorization_t * authorization,
415                                     char *nonce_count)
416 {
417   authorization->nonce_count = (char *) nonce_count;
418 }
419
420
421 /* returns the authorization header as a string.          */
422 /* INPUT : osip_authorization_t *authorization | authorization header.  */
423 /* returns null on error. */
424 int
425 osip_authorization_to_str (const osip_authorization_t * auth, char **dest)
426 {
427   size_t len;
428   char *tmp;
429
430   *dest = NULL;
431   /* DO NOT REALLY KNOW THE LIST OF MANDATORY PARAMETER: Please HELP! */
432   if ((auth == NULL) || (auth->auth_type == NULL) || (auth->realm == NULL)
433       || (auth->nonce == NULL))
434     return -1;
435
436   len = strlen (auth->auth_type) + 1;
437   if (auth->username != NULL)
438     len = len + 10 + strlen (auth->username);
439   if (auth->realm != NULL)
440     len = len + 8 + strlen (auth->realm);
441   if (auth->nonce != NULL)
442     len = len + 8 + strlen (auth->nonce);
443   if (auth->uri != NULL)
444     len = len + 6 + strlen (auth->uri);
445   if (auth->response != NULL)
446     len = len + 11 + strlen (auth->response);
447   len = len + 2;
448   if (auth->digest != NULL)
449     len = len + strlen (auth->digest) + 9;
450   if (auth->algorithm != NULL)
451     len = len + strlen (auth->algorithm) + 12;
452   if (auth->cnonce != NULL)
453     len = len + strlen (auth->cnonce) + 9;
454   if (auth->opaque != NULL)
455     len = len + 9 + strlen (auth->opaque);
456   if (auth->nonce_count != NULL)
457     len = len + strlen (auth->nonce_count) + 5;
458   if (auth->message_qop != NULL)
459     len = len + strlen (auth->message_qop) + 6;
460
461   tmp = (char *) osip_malloc (len);
462   if (tmp == NULL)
463     return -1;
464   *dest = tmp;
465
466   osip_strncpy (tmp, auth->auth_type, strlen (auth->auth_type));
467   tmp = tmp + strlen (tmp);
468
469   if (auth->username != NULL)
470     {
471       osip_strncpy (tmp, " username=", 10);
472       tmp = tmp + 10;
473       /* !! username-value must be a quoted string !! */
474       osip_strncpy (tmp, auth->username, strlen (auth->username));
475       tmp = tmp + strlen (tmp);
476     }
477
478   if (auth->realm != NULL)
479     {
480       osip_strncpy (tmp, ", realm=", 8);
481       tmp = tmp + 8;
482       /* !! realm-value must be a quoted string !! */
483       osip_strncpy (tmp, auth->realm, strlen (auth->realm));
484       tmp = tmp + strlen (tmp);
485     }
486   if (auth->nonce != NULL)
487     {
488       osip_strncpy (tmp, ", nonce=", 8);
489       tmp = tmp + 8;
490       /* !! nonce-value must be a quoted string !! */
491       osip_strncpy (tmp, auth->nonce, strlen (auth->nonce));
492       tmp = tmp + strlen (tmp);
493     }
494
495   if (auth->uri != NULL)
496     {
497       osip_strncpy (tmp, ", uri=", 6);
498       tmp = tmp + 6;
499       /* !! domain-value must be a list of URI in a quoted string !! */
500       osip_strncpy (tmp, auth->uri, strlen (auth->uri));
501       tmp = tmp + strlen (tmp);
502     }
503   if (auth->response != NULL)
504     {
505       osip_strncpy (tmp, ", response=", 11);
506       tmp = tmp + 11;
507       /* !! domain-value must be a list of URI in a quoted string !! */
508       osip_strncpy (tmp, auth->response, strlen (auth->response));
509       tmp = tmp + strlen (tmp);
510     }
511
512   if (auth->digest != NULL)
513     {
514       osip_strncpy (tmp, ", digest=", 9);
515       tmp = tmp + 9;
516       /* !! domain-value must be a list of URI in a quoted string !! */
517       osip_strncpy (tmp, auth->digest, strlen (auth->digest));
518       tmp = tmp + strlen (tmp);
519     }
520   if (auth->algorithm != NULL)
521     {
522       osip_strncpy (tmp, ", algorithm=", 12);
523       tmp = tmp + 12;
524       osip_strncpy (tmp, auth->algorithm, strlen (auth->algorithm));
525       tmp = tmp + strlen (tmp);
526     }
527   if (auth->cnonce != NULL)
528     {
529       osip_strncpy (tmp, ", cnonce=", 9);
530       tmp = tmp + 9;
531       osip_strncpy (tmp, auth->cnonce, strlen (auth->cnonce));
532       tmp = tmp + strlen (tmp);
533     }
534   if (auth->opaque != NULL)
535     {
536       osip_strncpy (tmp, ", opaque=", 9);
537       tmp = tmp + 9;
538       osip_strncpy (tmp, auth->opaque, strlen (auth->opaque));
539       tmp = tmp + strlen (tmp);
540     }
541   if (auth->message_qop != NULL)
542     {
543       osip_strncpy (tmp, ", qop=", 6);
544       tmp = tmp + 6;
545       osip_strncpy (tmp, auth->message_qop, strlen (auth->message_qop));
546       tmp = tmp + strlen (tmp);
547     }
548   if (auth->nonce_count != NULL)
549     {
550       osip_strncpy (tmp, ", nc=", 5);
551       tmp = tmp + 5;
552       osip_strncpy (tmp, auth->nonce_count, strlen (auth->nonce_count));
553       tmp = tmp + strlen (tmp);
554     }
555   return 0;
556 }
557
558 /* deallocates a osip_authorization_t structure.  */
559 /* INPUT : osip_authorization_t *authorization | authorization. */
560 void
561 osip_authorization_free (osip_authorization_t * authorization)
562 {
563   if (authorization == NULL)
564     return;
565   osip_free (authorization->auth_type);
566   osip_free (authorization->username);
567   osip_free (authorization->realm);
568   osip_free (authorization->nonce);
569   osip_free (authorization->uri);
570   osip_free (authorization->response);
571   osip_free (authorization->digest);
572   osip_free (authorization->algorithm);
573   osip_free (authorization->cnonce);
574   osip_free (authorization->opaque);
575   osip_free (authorization->message_qop);
576   osip_free (authorization->nonce_count);
577   osip_free (authorization);
578 }
579
580 int
581 osip_authorization_clone (const osip_authorization_t * auth,
582                           osip_authorization_t ** dest)
583 {
584   int i;
585   osip_authorization_t *au;
586
587   *dest = NULL;
588   if (auth == NULL)
589     return -1;
590   /* to be removed?
591      if (auth->auth_type==NULL) return -1;
592      if (auth->username==NULL) return -1;
593      if (auth->realm==NULL) return -1;
594      if (auth->nonce==NULL) return -1;
595      if (auth->uri==NULL) return -1;
596      if (auth->response==NULL) return -1;
597      if (auth->opaque==NULL) return -1;
598    */
599
600   i = osip_authorization_init (&au);
601   if (i == -1)                  /* allocation failed */
602     return -1;
603   if (auth->auth_type != NULL)
604     {
605       au->auth_type = osip_strdup (auth->auth_type);
606       if (au->auth_type == NULL)
607         goto ac_error;
608     }
609   if (auth->username != NULL)
610     {
611       au->username = osip_strdup (auth->username);
612       if (au->username == NULL)
613         goto ac_error;
614     }
615   if (auth->realm != NULL)
616     {
617       au->realm = osip_strdup (auth->realm);
618       if (auth->realm == NULL)
619         goto ac_error;
620     }
621   if (auth->nonce != NULL)
622     {
623       au->nonce = osip_strdup (auth->nonce);
624       if (auth->nonce == NULL)
625         goto ac_error;
626     }
627   if (auth->uri != NULL)
628     {
629       au->uri = osip_strdup (auth->uri);
630       if (au->uri == NULL)
631         goto ac_error;
632     }
633   if (auth->response != NULL)
634     {
635       au->response = osip_strdup (auth->response);
636       if (auth->response == NULL)
637         goto ac_error;
638     }
639   if (auth->digest != NULL)
640     {
641       au->digest = osip_strdup (auth->digest);
642       if (au->digest == NULL)
643         goto ac_error;
644     }
645   if (auth->algorithm != NULL)
646     {
647       au->algorithm = osip_strdup (auth->algorithm);
648       if (auth->algorithm == NULL)
649         goto ac_error;
650     }
651   if (auth->cnonce != NULL)
652     {
653       au->cnonce = osip_strdup (auth->cnonce);
654       if (au->cnonce == NULL)
655         goto ac_error;
656     }
657   if (auth->opaque != NULL)
658     {
659       au->opaque = osip_strdup (auth->opaque);
660       if (auth->opaque == NULL)
661         goto ac_error;
662     }
663   if (auth->message_qop != NULL)
664     {
665       au->message_qop = osip_strdup (auth->message_qop);
666       if (auth->message_qop == NULL)
667         goto ac_error;
668     }
669   if (auth->nonce_count != NULL)
670     {
671       au->nonce_count = osip_strdup (auth->nonce_count);
672       if (auth->nonce_count == NULL)
673         goto ac_error;
674     }
675
676   *dest = au;
677   return 0;
678
679 ac_error:
680   osip_authorization_free (au);
681   osip_free (au);
682   return -1;
683 }