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 
osip_authorization_init(osip_authorization_t ** dest)27 int osip_authorization_init(osip_authorization_t **dest) {
28   *dest = (osip_authorization_t *) osip_malloc(sizeof(osip_authorization_t));
29 
30   if (*dest == NULL)
31     return OSIP_NOMEM;
32 
33   memset(*dest, 0, sizeof(osip_authorization_t));
34   return OSIP_SUCCESS;
35 }
36 
37 /* fills the www-authenticate header of message.               */
38 /* INPUT :  char *hvalue | value of header.   */
39 /* OUTPUT: osip_message_t *sip | structure to save results. */
40 /* returns -1 on error. */
osip_message_set_authorization(osip_message_t * sip,const char * hvalue)41 int osip_message_set_authorization(osip_message_t *sip, const char *hvalue) {
42   osip_authorization_t *authorization;
43   int i;
44 
45   if (hvalue == NULL || hvalue[0] == '\0')
46     return OSIP_SUCCESS;
47 
48   if (sip == NULL)
49     return OSIP_BADPARAMETER;
50 
51   i = osip_authorization_init(&authorization);
52 
53   if (i != 0)
54     return i;
55 
56   i = osip_authorization_parse(authorization, hvalue);
57 
58   if (i != 0) {
59     osip_authorization_free(authorization);
60     return i;
61   }
62 
63   sip->message_property = 2;
64   osip_list_add(&sip->authorizations, authorization, -1);
65   return OSIP_SUCCESS;
66 }
67 
68 /* fills the www-authenticate structure.           */
69 /* INPUT : char *hvalue | value of header.         */
70 /* OUTPUT: osip_message_t *sip | structure to save results. */
71 /* returns -1 on error. */
72 /* TODO:
73    digest-challenge tken has no order preference??
74    verify many situations (extra SP....)
75 */
osip_authorization_parse(osip_authorization_t * auth,const char * hvalue)76 int osip_authorization_parse(osip_authorization_t *auth, const char *hvalue) {
77   const char *space;
78   const char *next = NULL;
79   int i;
80 
81   space = strchr(hvalue, ' '); /* SEARCH FOR SPACE */
82 
83   if (space == NULL)
84     return OSIP_SYNTAXERROR;
85 
86   if (space - hvalue < 1)
87     return OSIP_SYNTAXERROR;
88 
89   auth->auth_type = (char *) osip_malloc(space - hvalue + 1);
90 
91   if (auth->auth_type == NULL)
92     return OSIP_NOMEM;
93 
94   osip_strncpy(auth->auth_type, hvalue, space - hvalue);
95 
96   for (;;) {
97     int parse_ok = 0;
98 
99     i = __osip_quoted_string_set("username", space, &(auth->username), &next);
100 
101     if (i != 0)
102       return i;
103 
104     if (next == NULL)
105       return OSIP_SUCCESS; /* end of header detected! */
106     else if (next != space) {
107       space = next;
108       parse_ok++;
109     }
110 
111     i = __osip_quoted_string_set("realm", space, &(auth->realm), &next);
112 
113     if (i != 0)
114       return i;
115 
116     if (next == NULL)
117       return OSIP_SUCCESS;
118 
119     else if (next != space) {
120       space = next;
121       parse_ok++;
122     }
123 
124     i = __osip_quoted_string_set("nonce", space, &(auth->nonce), &next);
125 
126     if (i != 0)
127       return i;
128 
129     if (next == NULL)
130       return OSIP_SUCCESS; /* end of header detected! */
131     else if (next != space) {
132       space = next;
133       parse_ok++;
134     }
135 
136     i = __osip_quoted_string_set("uri", space, &(auth->uri), &next);
137 
138     if (i != 0)
139       return i;
140 
141     if (next == NULL)
142       return OSIP_SUCCESS; /* end of header detected! */
143     else if (next != space) {
144       space = next;
145       parse_ok++;
146     }
147 
148     i = __osip_quoted_string_set("response", space, &(auth->response), &next);
149 
150     if (i != 0)
151       return i;
152 
153     if (next == NULL)
154       return OSIP_SUCCESS; /* end of header detected! */
155     else if (next != space) {
156       space = next;
157       parse_ok++;
158     }
159 
160     i = __osip_quoted_string_set("digest", space, &(auth->digest), &next);
161 
162     if (i != 0)
163       return i;
164 
165     if (next == NULL)
166       return OSIP_SUCCESS; /* end of header detected! */
167     else if (next != space) {
168       space = next;
169       parse_ok++;
170     }
171 
172     i = __osip_token_set("algorithm", space, &(auth->algorithm), &next);
173 
174     if (i != 0)
175       return i;
176 
177     if (next == NULL)
178       return OSIP_SUCCESS; /* end of header detected! */
179     else if (next != space) {
180       space = next;
181       parse_ok++;
182     }
183 
184     i = __osip_quoted_string_set("cnonce", space, &(auth->cnonce), &next);
185 
186     if (i != 0)
187       return i;
188 
189     if (next == NULL)
190       return OSIP_SUCCESS; /* end of header detected! */
191     else if (next != space) {
192       space = next;
193       parse_ok++;
194     }
195 
196     i = __osip_quoted_string_set("opaque", space, &(auth->opaque), &next);
197 
198     if (i != 0)
199       return i;
200 
201     if (next == NULL)
202       return OSIP_SUCCESS; /* end of header detected! */
203     else if (next != space) {
204       space = next;
205       parse_ok++;
206     }
207 
208     i = __osip_token_set("qop", space, &(auth->message_qop), &next);
209 
210     if (i != 0)
211       return i;
212 
213     if (next == NULL)
214       return OSIP_SUCCESS; /* end of header detected! */
215     else if (next != space) {
216       space = next;
217       parse_ok++;
218     }
219 
220     i = __osip_token_set("nc", space, &(auth->nonce_count), &next);
221 
222     if (i != 0)
223       return i;
224 
225     if (next == NULL)
226       return OSIP_SUCCESS; /* end of header detected! */
227     else if (next != space) {
228       space = next;
229       parse_ok++;
230     }
231 
232     i = __osip_token_set("version", space, &(auth->version), &next);
233 
234     if (i != 0)
235       return i;
236 
237     if (next == NULL)
238       return OSIP_SUCCESS; /* end of header detected! */
239     else if (next != space) {
240       space = next;
241       parse_ok++;
242     }
243 
244     i = __osip_quoted_string_set("targetname", space, &(auth->targetname), &next);
245 
246     if (i != 0)
247       return i;
248 
249     if (next == NULL)
250       return OSIP_SUCCESS; /* end of header detected! */
251     else if (next != space) {
252       space = next;
253       parse_ok++;
254     }
255 
256     i = __osip_quoted_string_set("gssapi-data", space, &(auth->gssapi_data), &next);
257 
258     if (i != 0)
259       return i;
260 
261     if (next == NULL)
262       return OSIP_SUCCESS; /* end of header detected! */
263     else if (next != space) {
264       space = next;
265       parse_ok++;
266     }
267 
268     i = __osip_quoted_string_set("crand", space, &(auth->crand), &next);
269 
270     if (i != 0)
271       return i;
272 
273     if (next == NULL)
274       return OSIP_SUCCESS; /* end of header detected! */
275     else if (next != space) {
276       space = next;
277       parse_ok++;
278     }
279 
280     i = __osip_quoted_string_set("cnum", space, &(auth->cnum), &next);
281 
282     if (i != 0)
283       return i;
284 
285     if (next == NULL)
286       return OSIP_SUCCESS; /* end of header detected! */
287     else if (next != space) {
288       space = next;
289       parse_ok++;
290     }
291 
292     /* nothing was recognized:
293        here, we should handle a list of unknown tokens where:
294        token1 = ( token2 | quoted_text ) */
295     /* TODO */
296 
297     if (0 == parse_ok) {
298       const char *quote1, *quote2, *tmp;
299 
300       /* CAUTION */
301       /* parameter not understood!!! I'm too lazy to handle IT */
302       /* let's simply bypass it */
303       if (strlen(space) < 1)
304         return OSIP_SUCCESS;
305 
306       tmp = strchr(space + 1, ',');
307 
308       if (tmp == NULL) /* it was the last header */
309         return OSIP_SUCCESS;
310 
311       quote1 = __osip_quote_find(space);
312 
313       if ((quote1 != NULL) && (quote1 < tmp)) { /* this may be a quoted string! */
314         quote2 = __osip_quote_find(quote1 + 1);
315 
316         if (quote2 == NULL)
317           return OSIP_SYNTAXERROR; /* bad header format... */
318 
319         if (tmp < quote2) /* the comma is inside the quotes! */
320           space = strchr(quote2, ',');
321 
322         else
323           space = tmp;
324 
325         if (space == NULL) /* it was the last header */
326           return OSIP_SUCCESS;
327 
328       } else
329         space = tmp;
330 
331       /* continue parsing... */
332     }
333   }
334 
335   return OSIP_SUCCESS; /* ok */
336 }
337 
338 #ifndef MINISIZE
339 /* returns the authorization header.   */
340 /* INPUT : osip_message_t *sip | sip message.   */
341 /* returns null on error. */
osip_message_get_authorization(const osip_message_t * sip,int pos,osip_authorization_t ** dest)342 int osip_message_get_authorization(const osip_message_t *sip, int pos, osip_authorization_t **dest) {
343   osip_authorization_t *authorization;
344 
345   *dest = NULL;
346 
347   if (osip_list_size(&sip->authorizations) <= pos)
348     return OSIP_UNDEFINED_ERROR; /* does not exist */
349 
350   authorization = (osip_authorization_t *) osip_list_get(&sip->authorizations, pos);
351   *dest = authorization;
352   return pos;
353 }
354 #endif
355 
osip_authorization_get_auth_type(const osip_authorization_t * authorization)356 char *osip_authorization_get_auth_type(const osip_authorization_t *authorization) {
357   return authorization->auth_type;
358 }
359 
osip_authorization_set_auth_type(osip_authorization_t * authorization,char * auth_type)360 void osip_authorization_set_auth_type(osip_authorization_t *authorization, char *auth_type) {
361   authorization->auth_type = (char *) auth_type;
362 }
363 
osip_authorization_get_username(osip_authorization_t * authorization)364 char *osip_authorization_get_username(osip_authorization_t *authorization) {
365   return authorization->username;
366 }
367 
osip_authorization_set_username(osip_authorization_t * authorization,char * username)368 void osip_authorization_set_username(osip_authorization_t *authorization, char *username) {
369   authorization->username = (char *) username;
370 }
371 
osip_authorization_get_realm(osip_authorization_t * authorization)372 char *osip_authorization_get_realm(osip_authorization_t *authorization) {
373   return authorization->realm;
374 }
375 
osip_authorization_set_realm(osip_authorization_t * authorization,char * realm)376 void osip_authorization_set_realm(osip_authorization_t *authorization, char *realm) {
377   authorization->realm = (char *) realm;
378 }
379 
osip_authorization_get_nonce(osip_authorization_t * authorization)380 char *osip_authorization_get_nonce(osip_authorization_t *authorization) {
381   return authorization->nonce;
382 }
383 
osip_authorization_set_nonce(osip_authorization_t * authorization,char * nonce)384 void osip_authorization_set_nonce(osip_authorization_t *authorization, char *nonce) {
385   authorization->nonce = (char *) nonce;
386 }
387 
osip_authorization_get_uri(osip_authorization_t * authorization)388 char *osip_authorization_get_uri(osip_authorization_t *authorization) {
389   return authorization->uri;
390 }
391 
osip_authorization_set_uri(osip_authorization_t * authorization,char * uri)392 void osip_authorization_set_uri(osip_authorization_t *authorization, char *uri) {
393   authorization->uri = (char *) uri;
394 }
395 
osip_authorization_get_response(osip_authorization_t * authorization)396 char *osip_authorization_get_response(osip_authorization_t *authorization) {
397   return authorization->response;
398 }
399 
osip_authorization_set_response(osip_authorization_t * authorization,char * response)400 void osip_authorization_set_response(osip_authorization_t *authorization, char *response) {
401   authorization->response = (char *) response;
402 }
403 
osip_authorization_get_digest(osip_authorization_t * authorization)404 char *osip_authorization_get_digest(osip_authorization_t *authorization) {
405   return authorization->digest;
406 }
407 
osip_authorization_set_digest(osip_authorization_t * authorization,char * digest)408 void osip_authorization_set_digest(osip_authorization_t *authorization, char *digest) {
409   authorization->digest = (char *) digest;
410 }
411 
osip_authorization_get_algorithm(osip_authorization_t * authorization)412 char *osip_authorization_get_algorithm(osip_authorization_t *authorization) {
413   return authorization->algorithm;
414 }
415 
osip_authorization_set_algorithm(osip_authorization_t * authorization,char * algorithm)416 void osip_authorization_set_algorithm(osip_authorization_t *authorization, char *algorithm) {
417   authorization->algorithm = (char *) algorithm;
418 }
419 
osip_authorization_get_cnonce(osip_authorization_t * authorization)420 char *osip_authorization_get_cnonce(osip_authorization_t *authorization) {
421   return authorization->cnonce;
422 }
423 
osip_authorization_set_cnonce(osip_authorization_t * authorization,char * cnonce)424 void osip_authorization_set_cnonce(osip_authorization_t *authorization, char *cnonce) {
425   authorization->cnonce = (char *) cnonce;
426 }
427 
osip_authorization_get_opaque(osip_authorization_t * authorization)428 char *osip_authorization_get_opaque(osip_authorization_t *authorization) {
429   return authorization->opaque;
430 }
431 
osip_authorization_set_opaque(osip_authorization_t * authorization,char * opaque)432 void osip_authorization_set_opaque(osip_authorization_t *authorization, char *opaque) {
433   authorization->opaque = (char *) opaque;
434 }
435 
osip_authorization_get_message_qop(osip_authorization_t * authorization)436 char *osip_authorization_get_message_qop(osip_authorization_t *authorization) {
437   return authorization->message_qop;
438 }
439 
osip_authorization_set_message_qop(osip_authorization_t * authorization,char * message_qop)440 void osip_authorization_set_message_qop(osip_authorization_t *authorization, char *message_qop) {
441   authorization->message_qop = (char *) message_qop;
442 }
443 
osip_authorization_get_nonce_count(osip_authorization_t * authorization)444 char *osip_authorization_get_nonce_count(osip_authorization_t *authorization) {
445   return authorization->nonce_count;
446 }
447 
osip_authorization_set_nonce_count(osip_authorization_t * authorization,char * nonce_count)448 void osip_authorization_set_nonce_count(osip_authorization_t *authorization, char *nonce_count) {
449   authorization->nonce_count = (char *) nonce_count;
450 }
451 
osip_authorization_get_version(osip_authorization_t * authorization)452 char *osip_authorization_get_version(osip_authorization_t *authorization) {
453   return authorization->version;
454 }
455 
osip_authorization_set_version(osip_authorization_t * authorization,char * version)456 void osip_authorization_set_version(osip_authorization_t *authorization, char *version) {
457   authorization->version = (char *) version;
458 }
459 
osip_authorization_get_targetname(osip_authorization_t * authorization)460 char *osip_authorization_get_targetname(osip_authorization_t *authorization) {
461   return authorization->targetname;
462 }
463 
osip_authorization_set_targetname(osip_authorization_t * authorization,char * targetname)464 void osip_authorization_set_targetname(osip_authorization_t *authorization, char *targetname) {
465   authorization->targetname = (char *) targetname;
466 }
467 
osip_authorization_get_gssapi_data(osip_authorization_t * authorization)468 char *osip_authorization_get_gssapi_data(osip_authorization_t *authorization) {
469   return authorization->gssapi_data;
470 }
471 
osip_authorization_set_gssapi_data(osip_authorization_t * authorization,char * gssapi_data)472 void osip_authorization_set_gssapi_data(osip_authorization_t *authorization, char *gssapi_data) {
473   authorization->gssapi_data = (char *) gssapi_data;
474 }
475 
osip_authorization_get_crand(osip_authorization_t * authorization)476 char *osip_authorization_get_crand(osip_authorization_t *authorization) {
477   return authorization->crand;
478 }
479 
osip_authorization_set_crand(osip_authorization_t * authorization,char * crand)480 void osip_authorization_set_crand(osip_authorization_t *authorization, char *crand) {
481   authorization->crand = (char *) crand;
482 }
483 
osip_authorization_get_cnum(osip_authorization_t * authorization)484 char *osip_authorization_get_cnum(osip_authorization_t *authorization) {
485   return authorization->cnum;
486 }
487 
osip_authorization_set_cnum(osip_authorization_t * authorization,char * cnum)488 void osip_authorization_set_cnum(osip_authorization_t *authorization, char *cnum) {
489   authorization->cnum = (char *) cnum;
490 }
491 
492 /* returns the authorization header as a string.          */
493 /* INPUT : osip_authorization_t *authorization | authorization header.  */
494 /* returns null on error. */
osip_authorization_to_str(const osip_authorization_t * auth,char ** dest)495 int osip_authorization_to_str(const osip_authorization_t *auth, char **dest) {
496   size_t len;
497   char *tmp;
498   int first = 1;
499 
500   *dest = NULL;
501   /* DO NOT REALLY KNOW THE LIST OF MANDATORY PARAMETER: Please HELP! */
502 #if 0
503 
504   if ((auth == NULL) || (auth->auth_type == NULL) || (auth->realm == NULL)
505       || (auth->nonce == NULL))
506     return OSIP_BADPARAMETER;
507 
508 #else
509 
510   /* IMS requirement: send authorization like in:
511      Digest uri="sip:sip.antisip.com", username="joe", response=""
512    */
513   if ((auth == NULL) || (auth->auth_type == NULL))
514     return OSIP_BADPARAMETER;
515 
516 #endif
517 
518   len = strlen(auth->auth_type) + 1;
519 
520   if (auth->username != NULL)
521     len = len + 10 + strlen(auth->username);
522 
523   if (auth->realm != NULL)
524     len = len + 8 + strlen(auth->realm);
525 
526   if (auth->nonce != NULL)
527     len = len + 8 + strlen(auth->nonce);
528 
529   if (auth->uri != NULL)
530     len = len + 6 + strlen(auth->uri);
531 
532   if (auth->response != NULL)
533     len = len + 11 + strlen(auth->response);
534 
535   len = len + 2;
536 
537   if (auth->digest != NULL)
538     len = len + strlen(auth->digest) + 9;
539 
540   if (auth->algorithm != NULL)
541     len = len + strlen(auth->algorithm) + 12;
542 
543   if (auth->cnonce != NULL)
544     len = len + strlen(auth->cnonce) + 9;
545 
546   if (auth->opaque != NULL)
547     len = len + 9 + strlen(auth->opaque);
548 
549   if (auth->nonce_count != NULL)
550     len = len + strlen(auth->nonce_count) + 5;
551 
552   if (auth->message_qop != NULL)
553     len = len + strlen(auth->message_qop) + 6;
554 
555   if (auth->version != NULL)
556     len = len + strlen(auth->version) + 10;
557 
558   if (auth->targetname != NULL)
559     len = len + strlen(auth->targetname) + 13;
560 
561   if (auth->gssapi_data != NULL)
562     len = len + strlen(auth->gssapi_data) + 14;
563 
564   if (auth->crand != NULL)
565     len = len + strlen(auth->crand) + 8;
566 
567   if (auth->cnum != NULL)
568     len = len + strlen(auth->cnum) + 7;
569 
570   tmp = (char *) osip_malloc(len);
571 
572   if (tmp == NULL)
573     return OSIP_NOMEM;
574 
575   *dest = tmp;
576 
577   tmp = osip_str_append(tmp, auth->auth_type);
578 
579   if (auth->username != NULL) {
580     if (!first)
581       tmp = osip_strn_append(tmp, ",", 1);
582 
583     first = 0;
584     tmp = osip_strn_append(tmp, " username=", 10);
585     /* !! username-value must be a quoted string !! */
586     tmp = osip_str_append(tmp, auth->username);
587   }
588 
589   if (auth->realm != NULL) {
590     if (!first)
591       tmp = osip_strn_append(tmp, ",", 1);
592 
593     first = 0;
594     tmp = osip_strn_append(tmp, " realm=", 7);
595     /* !! realm-value must be a quoted string !! */
596     tmp = osip_str_append(tmp, auth->realm);
597   }
598 
599   if (auth->nonce != NULL) {
600     if (!first)
601       tmp = osip_strn_append(tmp, ",", 1);
602 
603     first = 0;
604     tmp = osip_strn_append(tmp, " nonce=", 7);
605     /* !! nonce-value must be a quoted string !! */
606     tmp = osip_str_append(tmp, auth->nonce);
607   }
608 
609   if (auth->uri != NULL) {
610     if (!first)
611       tmp = osip_strn_append(tmp, ",", 1);
612 
613     first = 0;
614     tmp = osip_strn_append(tmp, " uri=", 5);
615     /* !! domain-value must be a list of URI in a quoted string !! */
616     tmp = osip_str_append(tmp, auth->uri);
617   }
618 
619   if (auth->response != NULL) {
620     if (!first)
621       tmp = osip_strn_append(tmp, ",", 1);
622 
623     first = 0;
624     tmp = osip_strn_append(tmp, " response=", 10);
625     /* !! domain-value must be a list of URI in a quoted string !! */
626     tmp = osip_str_append(tmp, auth->response);
627   }
628 
629   if (auth->digest != NULL) {
630     if (!first)
631       tmp = osip_strn_append(tmp, ",", 1);
632 
633     first = 0;
634     tmp = osip_strn_append(tmp, " digest=", 8);
635     /* !! domain-value must be a list of URI in a quoted string !! */
636     tmp = osip_str_append(tmp, auth->digest);
637   }
638 
639   if (auth->algorithm != NULL) {
640     if (!first)
641       tmp = osip_strn_append(tmp, ",", 1);
642 
643     first = 0;
644     tmp = osip_strn_append(tmp, " algorithm=", 11);
645     tmp = osip_str_append(tmp, auth->algorithm);
646   }
647 
648   if (auth->cnonce != NULL) {
649     if (!first)
650       tmp = osip_strn_append(tmp, ",", 1);
651 
652     first = 0;
653     tmp = osip_strn_append(tmp, " cnonce=", 8);
654     tmp = osip_str_append(tmp, auth->cnonce);
655   }
656 
657   if (auth->opaque != NULL) {
658     if (!first)
659       tmp = osip_strn_append(tmp, ",", 1);
660 
661     first = 0;
662     tmp = osip_strn_append(tmp, " opaque=", 8);
663     tmp = osip_str_append(tmp, auth->opaque);
664   }
665 
666   if (auth->message_qop != NULL) {
667     if (!first)
668       tmp = osip_strn_append(tmp, ",", 1);
669 
670     first = 0;
671     tmp = osip_strn_append(tmp, " qop=", 5);
672     tmp = osip_str_append(tmp, auth->message_qop);
673   }
674 
675   if (auth->nonce_count != NULL) {
676     if (!first)
677       tmp = osip_strn_append(tmp, ",", 1);
678 
679     first = 0;
680     tmp = osip_strn_append(tmp, " nc=", 4);
681     tmp = osip_str_append(tmp, auth->nonce_count);
682   }
683 
684   if (auth->version != NULL) {
685     if (!first)
686       tmp = osip_strn_append(tmp, ",", 1);
687 
688     first = 0;
689     tmp = osip_strn_append(tmp, " version=", 9);
690     tmp = osip_str_append(tmp, auth->version);
691   }
692 
693   if (auth->targetname != NULL) {
694     if (!first)
695       tmp = osip_strn_append(tmp, ",", 1);
696 
697     first = 0;
698     tmp = osip_strn_append(tmp, " targetname=", 12);
699     tmp = osip_str_append(tmp, auth->targetname);
700   }
701 
702   if (auth->gssapi_data != NULL) {
703     if (!first)
704       tmp = osip_strn_append(tmp, ",", 1);
705 
706     first = 0;
707     tmp = osip_strn_append(tmp, " gssapi-data=", 13);
708     tmp = osip_str_append(tmp, auth->gssapi_data);
709   }
710 
711   if (auth->crand != NULL) {
712     if (!first)
713       tmp = osip_strn_append(tmp, ",", 1);
714 
715     first = 0;
716     tmp = osip_strn_append(tmp, " crand=", 7);
717     tmp = osip_str_append(tmp, auth->crand);
718   }
719 
720   if (auth->cnum != NULL) {
721     if (!first)
722       tmp = osip_strn_append(tmp, ",", 1);
723 
724     first = 0;
725     tmp = osip_strn_append(tmp, " cnum=", 6);
726     tmp = osip_str_append(tmp, auth->cnum);
727   }
728 
729   return OSIP_SUCCESS;
730 }
731 
732 /* deallocates a osip_authorization_t structure.  */
733 /* INPUT : osip_authorization_t *authorization | authorization. */
osip_authorization_free(osip_authorization_t * authorization)734 void osip_authorization_free(osip_authorization_t *authorization) {
735   if (authorization == NULL)
736     return;
737 
738   osip_free(authorization->auth_type);
739   osip_free(authorization->username);
740   osip_free(authorization->realm);
741   osip_free(authorization->nonce);
742   osip_free(authorization->uri);
743   osip_free(authorization->response);
744   osip_free(authorization->digest);
745   osip_free(authorization->algorithm);
746   osip_free(authorization->cnonce);
747   osip_free(authorization->opaque);
748   osip_free(authorization->message_qop);
749   osip_free(authorization->nonce_count);
750   osip_free(authorization->version);
751   osip_free(authorization->targetname);
752   osip_free(authorization->gssapi_data);
753   osip_free(authorization->crand);
754   osip_free(authorization->cnum);
755   osip_free(authorization);
756 }
757 
osip_authorization_clone(const osip_authorization_t * auth,osip_authorization_t ** dest)758 int osip_authorization_clone(const osip_authorization_t *auth, osip_authorization_t **dest) {
759   int i;
760   osip_authorization_t *au;
761 
762   *dest = NULL;
763 
764   if (auth == NULL)
765     return OSIP_BADPARAMETER;
766 
767   /* to be removed?
768      if (auth->auth_type==NULL) return -1;
769      if (auth->username==NULL) return -1;
770      if (auth->realm==NULL) return -1;
771      if (auth->nonce==NULL) return -1;
772      if (auth->uri==NULL) return -1;
773      if (auth->response==NULL) return -1;
774      if (auth->opaque==NULL) return -1;
775    */
776 
777   i = osip_authorization_init(&au);
778 
779   if (i != 0) /* allocation failed */
780     return i;
781 
782   if (auth->auth_type != NULL) {
783     au->auth_type = osip_strdup(auth->auth_type);
784 
785     if (au->auth_type == NULL) {
786       osip_authorization_free(au);
787       return OSIP_NOMEM;
788     }
789   }
790 
791   if (auth->username != NULL) {
792     au->username = osip_strdup(auth->username);
793 
794     if (au->username == NULL) {
795       osip_authorization_free(au);
796       return OSIP_NOMEM;
797     }
798   }
799 
800   if (auth->realm != NULL) {
801     au->realm = osip_strdup(auth->realm);
802 
803     if (auth->realm == NULL) {
804       osip_authorization_free(au);
805       return OSIP_NOMEM;
806     }
807   }
808 
809   if (auth->nonce != NULL) {
810     au->nonce = osip_strdup(auth->nonce);
811 
812     if (auth->nonce == NULL) {
813       osip_authorization_free(au);
814       return OSIP_NOMEM;
815     }
816   }
817 
818   if (auth->uri != NULL) {
819     au->uri = osip_strdup(auth->uri);
820 
821     if (au->uri == NULL) {
822       osip_authorization_free(au);
823       return OSIP_NOMEM;
824     }
825   }
826 
827   if (auth->response != NULL) {
828     au->response = osip_strdup(auth->response);
829 
830     if (auth->response == NULL) {
831       osip_authorization_free(au);
832       return OSIP_NOMEM;
833     }
834   }
835 
836   if (auth->digest != NULL) {
837     au->digest = osip_strdup(auth->digest);
838 
839     if (au->digest == NULL) {
840       osip_authorization_free(au);
841       return OSIP_NOMEM;
842     }
843   }
844 
845   if (auth->algorithm != NULL) {
846     au->algorithm = osip_strdup(auth->algorithm);
847 
848     if (auth->algorithm == NULL) {
849       osip_authorization_free(au);
850       return OSIP_NOMEM;
851     }
852   }
853 
854   if (auth->cnonce != NULL) {
855     au->cnonce = osip_strdup(auth->cnonce);
856 
857     if (au->cnonce == NULL) {
858       osip_authorization_free(au);
859       return OSIP_NOMEM;
860     }
861   }
862 
863   if (auth->opaque != NULL) {
864     au->opaque = osip_strdup(auth->opaque);
865 
866     if (auth->opaque == NULL) {
867       osip_authorization_free(au);
868       return OSIP_NOMEM;
869     }
870   }
871 
872   if (auth->message_qop != NULL) {
873     au->message_qop = osip_strdup(auth->message_qop);
874 
875     if (auth->message_qop == NULL) {
876       osip_authorization_free(au);
877       return OSIP_NOMEM;
878     }
879   }
880 
881   if (auth->nonce_count != NULL) {
882     au->nonce_count = osip_strdup(auth->nonce_count);
883 
884     if (auth->nonce_count == NULL) {
885       osip_authorization_free(au);
886       return OSIP_NOMEM;
887     }
888   }
889 
890   if (auth->version != NULL) {
891     au->version = osip_strdup(auth->version);
892 
893     if (auth->version == NULL) {
894       osip_authorization_free(au);
895       return OSIP_NOMEM;
896     }
897   }
898 
899   if (auth->targetname != NULL) {
900     au->targetname = osip_strdup(auth->targetname);
901 
902     if (auth->targetname == NULL) {
903       osip_authorization_free(au);
904       return OSIP_NOMEM;
905     }
906   }
907 
908   if (auth->gssapi_data != NULL) {
909     au->gssapi_data = osip_strdup(auth->gssapi_data);
910 
911     if (auth->gssapi_data == NULL) {
912       osip_authorization_free(au);
913       return OSIP_NOMEM;
914     }
915   }
916 
917   if (auth->crand != NULL) {
918     au->crand = osip_strdup(auth->crand);
919 
920     if (auth->crand == NULL) {
921       osip_authorization_free(au);
922       return OSIP_NOMEM;
923     }
924   }
925 
926   if (auth->cnum != NULL) {
927     au->cnum = osip_strdup(auth->cnum);
928 
929     if (auth->cnum == NULL) {
930       osip_authorization_free(au);
931       return OSIP_NOMEM;
932     }
933   }
934 
935   *dest = au;
936   return OSIP_SUCCESS;
937 }
938