1 /*
2  * This file is part of the Sofia-SIP package
3  *
4  * Copyright (C) 2005 Nokia Corporation.
5  *
6  * Contact: Pekka Pessi <pekka.pessi@nokia.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation; either version 2.1 of
11  * the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21  * 02110-1301 USA
22  *
23  */
24 
25 /**@CFILE sip_security.c
26  *
27  * Security-related SIP header handling.
28  *
29  * This file contains implementation of headers related to HTTP authentication
30  * (@RFC2617):
31  * @ref sip_authorization "Authorization",
32  * @ref sip_authentication_info "Authentication-Info",
33  * @ref sip_proxy_authenticate "Proxy-Authenticate",
34  * @ref sip_proxy_authentication_info "Proxy-Authentication-Info",
35  * @ref sip_proxy_authorization "Proxy-Authorization", and
36  * @ref sip_www_authenticate "WWW-Authenticate".
37  *
38  * There is also implementation of headers related to security agreement
39  * (@RFC3329):
40  * @ref sip_security_client "Security-Client",
41  * @ref sip_security_server "Security-Server", and
42  * @ref sip_security_verify "Security-Verify" headers.
43  *
44  * The implementation of @ref sip_privacy "Privacy" header (@RFC3323) is
45  * also here.
46  *
47  * @author Pekka Pessi <Pekka.Pessi@nokia.com>.
48  *
49  * @date Created: Tue Jun 13 02:57:51 2000 ppessi
50  */
51 
52 #include "config.h"
53 
54 /* Avoid casting sip_t to msg_pub_t and sip_header_t to msg_header_t */
55 #define MSG_PUB_T       struct sip_s
56 #define MSG_HDR_T       union sip_header_u
57 
58 #include "sofia-sip/sip_parser.h"
59 
60 #include <stdio.h>
61 #include <stddef.h>
62 #include <stdlib.h>
63 #include <string.h>
64 #include <limits.h>
65 #include <assert.h>
66 
67 /* ====================================================================== */
68 
69 /**@SIP_HEADER sip_authorization Authorization Header
70  *
71  * The Authorization header consists of credentials containing the
72  * authentication information of the user agent for the realm of the
73  * resource being requested. Its syntax is defined in @RFC2617 and @RFC3261
74  * as follows:
75  *
76  * @code
77  *    Authorization     =  "Authorization" HCOLON credentials
78  *    credentials       =  ("Digest" LWS digest-response)
79  *                         / other-response
80  *    digest-response   =  dig-resp *(COMMA dig-resp)
81  *    dig-resp          =  username / realm / nonce / digest-uri
82  *                          / dresponse / algorithm / cnonce
83  *                          / opaque / message-qop
84  *                          / nonce-count / auth-param
85  *    username          =  "username" EQUAL username-value
86  *    username-value    =  quoted-string
87  *    digest-uri        =  "uri" EQUAL LDQUOT digest-uri-value RDQUOT
88  *    digest-uri-value  =  rquest-uri ; Equal to request-uri as specified
89  *                         by HTTP/1.1
90  *    message-qop       =  "qop" EQUAL qop-value
91  *    cnonce            =  "cnonce" EQUAL cnonce-value
92  *    cnonce-value      =  nonce-value
93  *    nonce-count       =  "nc" EQUAL nc-value
94  *    nc-value          =  8LHEX
95  *    dresponse         =  "response" EQUAL request-digest
96  *    request-digest    =  LDQUOT 32LHEX RDQUOT
97  *    auth-param        =  auth-param-name EQUAL
98  *                         ( token / quoted-string )
99  *    auth-param-name   =  token
100  *    other-response    =  auth-scheme LWS auth-param
101  *                         *(COMMA auth-param)
102  *    auth-scheme       =  token
103  * @endcode
104  *
105  * The parsed Authorization header
106  * is stored in #sip_authorization_t structure.
107  *
108  * @sa @RFC2617, auth_mod_verify(), auth_mod_check(), auth_get_params(),
109  * auth_digest_response_get().
110  */
111 
112 /**@ingroup sip_authorization
113  * @typedef typedef struct sip_authorization_s sip_authorization_t;
114  *
115  * The structure #sip_authorization_t contains representation of SIP
116  * @Authorization header.
117  *
118  * The #sip_authorization_t is defined as follows:
119  * @code
120  * typedef struct msg_auth_s {
121  *   msg_common_t       au_common[1];  // Common fragment info
122  *   msg_auth_t        *au_next;       // Link to next header
123  *   char const        *au_scheme;     // Auth-scheme like "Basic" or "Digest"
124  *   msg_param_t const *au_params;     // Comma-separated parameters
125  * } sip_authorization_t;
126  * @endcode
127  *
128  */
129 
130 msg_hclass_t sip_authorization_class[] =
131 SIP_HEADER_CLASS_AUTH(authorization, "Authorization", append);
132 
sip_authorization_d(su_home_t * home,sip_header_t * h,char * s,isize_t slen)133 issize_t sip_authorization_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
134 {
135   return msg_auth_d(home, h, s, slen);
136 }
137 
sip_authorization_e(char b[],isize_t bsiz,sip_header_t const * h,int f)138 issize_t sip_authorization_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
139 {
140   assert(sip_is_authorization(h));
141   return msg_auth_e(b, bsiz, h, f);
142 }
143 
144 /* ====================================================================== */
145 
146 /**@SIP_HEADER sip_proxy_authenticate Proxy-Authenticate Header
147  *
148  * The Proxy-Authenticate header consists of a challenge that indicates the
149  * authentication scheme and parameters applicable to the proxy.  Its syntax
150  * is defined in [H14.33, S10.31] as follows:
151  *
152  * @code
153  *    Proxy-Authenticate  =  "Proxy-Authenticate" HCOLON challenge
154  *    challenge           =  ("Digest" LWS digest-cln *(COMMA digest-cln))
155  *                           / other-challenge
156  *    other-challenge     =  auth-scheme LWS auth-param
157  *                           *(COMMA auth-param)
158  *    digest-cln          =  realm / domain / nonce
159  *                            / opaque / stale / algorithm
160  *                            / qop-options / auth-param
161  *    realm               =  "realm" EQUAL realm-value
162  *    realm-value         =  quoted-string
163  *    domain              =  "domain" EQUAL LDQUOT URI
164  *                           *( 1*SP URI ) RDQUOT
165  *    URI                 =  absoluteURI / abs-path
166  *    nonce               =  "nonce" EQUAL nonce-value
167  *    nonce-value         =  quoted-string
168  *    opaque              =  "opaque" EQUAL quoted-string
169  *    stale               =  "stale" EQUAL ( "true" / "false" )
170  *    algorithm           =  "algorithm" EQUAL ( "MD5" / "MD5-sess"
171  *                           / token )
172  *    qop-options         =  "qop" EQUAL LDQUOT qop-value
173  *                           *("," qop-value) RDQUOT
174  *    qop-value           =  "auth" / "auth-int" / token
175  * @endcode
176  *
177  *
178  * The parsed Proxy-Authenticate header
179  * is stored in #sip_proxy_authenticate_t structure.
180  */
181 
182 /**@ingroup sip_proxy_authenticate
183  * @typedef typedef struct sip_proxy_authenticate_s sip_proxy_authenticate_t;
184  *
185  * The structure #sip_proxy_authenticate_t contains representation of SIP
186  * @ProxyAuthenticate header.
187  *
188  * The #sip_proxy_authenticate_t is defined as follows:
189  * @code
190  * typedef struct msg_auth_s {
191  *   msg_common_t       au_common[1];  // Common fragment info
192  *   msg_auth_t        *au_next;       // Link to next header
193  *   char const        *au_scheme;     // Auth-scheme like "Basic" or "Digest"
194  *   msg_param_t const *au_params;     // Comma-separated parameters
195  * } sip_proxy_authenticate_t;
196  * @endcode
197  *
198  */
199 
200 msg_hclass_t sip_proxy_authenticate_class[] =
201 SIP_HEADER_CLASS_AUTH(proxy_authenticate, "Proxy-Authenticate", append);
202 
sip_proxy_authenticate_d(su_home_t * home,sip_header_t * h,char * s,isize_t slen)203 issize_t sip_proxy_authenticate_d(su_home_t *home, sip_header_t *h,
204 				  char *s, isize_t slen)
205 {
206   return msg_auth_d(home, h, s, slen);
207 }
208 
sip_proxy_authenticate_e(char b[],isize_t bsiz,sip_header_t const * h,int f)209 issize_t sip_proxy_authenticate_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
210 {
211   assert(sip_is_proxy_authenticate(h));
212   return msg_auth_e(b, bsiz, h, f);
213 }
214 
215 
216 /* ====================================================================== */
217 
218 /**@SIP_HEADER sip_proxy_authorization Proxy-Authorization Header
219  *
220  * The Proxy-Authorization header consists of credentials containing the
221  * authentication information of the user agent for the proxy and/or realm
222  * of the resource being requested.  Its syntax is defined in @RFC3261
223  * as follows:
224  *
225  * @code
226  *    Proxy-Authorization  = "Proxy-Authorization" ":" credentials
227  *    credentials          =  ("Digest" LWS digest-response)
228  *                            / other-response
229  * @endcode
230  *
231  * @sa auth_mod_verify(), auth_mod_check(), auth_get_params(),
232  * auth_digest_response_get().
233  *
234  * The parsed Proxy-Authorization header
235  * is stored in #sip_proxy_authorization_t structure.
236  */
237 
238 /**@ingroup sip_proxy_authorization
239  * @typedef typedef struct sip_proxy_authorization_s sip_proxy_authorization_t;
240  *
241  * The structure #sip_proxy_authorization_t contains representation of SIP
242  * @ProxyAuthorization header.
243  *
244  * The #sip_proxy_authorization_t is defined as follows:
245  * @code
246  * typedef struct msg_auth_s {
247  *   msg_common_t       au_common[1];  // Common fragment info
248  *   msg_auth_t        *au_next;       // Link to next header
249  *   char const        *au_scheme;     // Auth-scheme like "Basic" or "Digest"
250  *   msg_param_t const *au_params;     // Comma-separated parameters
251  * } sip_proxy_authorization_t;
252  * @endcode
253  *
254  */
255 
256 msg_hclass_t sip_proxy_authorization_class[] =
257 SIP_HEADER_CLASS_AUTH(proxy_authorization, "Proxy-Authorization", append);
258 
sip_proxy_authorization_d(su_home_t * home,sip_header_t * h,char * s,isize_t slen)259 issize_t sip_proxy_authorization_d(su_home_t *home, sip_header_t *h,
260 				   char *s, isize_t slen)
261 {
262   return msg_auth_d(home, h, s, slen);
263 }
264 
sip_proxy_authorization_e(char b[],isize_t bsiz,sip_header_t const * h,int f)265 issize_t sip_proxy_authorization_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
266 {
267   assert(sip_is_proxy_authorization(h));
268   return msg_auth_e(b, bsiz, h, f);
269 }
270 
271 /* ====================================================================== */
272 
273 /**@SIP_HEADER sip_www_authenticate WWW-Authenticate Header
274  *
275  * The WWW-Authenticate header consists of at least one challenge that
276  * indicates the authentication scheme(s) and parameters applicable to the
277  * Request-URI.  Its syntax is defined in @RFC3261 as
278  * follows:
279  *
280  * @code
281  *    WWW-Authenticate  = "WWW-Authenticate" HCOLON challenge
282  *    challenge         =  ("Digest" LWS digest-cln *(COMMA digest-cln))
283  *                      / other-challenge
284  *    other-challenge   =  auth-scheme LWS auth-param *(COMMA auth-param)
285  * @endcode
286  *
287  * See @ProxyAuthenticate for the definition of \<digest-cln\>.
288  *
289  * The parsed WWW-Authenticate header
290  * is stored in #sip_www_authenticate_t structure.
291  */
292 
293 /**@ingroup sip_www_authenticate
294  * @typedef typedef struct sip_www_authenticate_s sip_www_authenticate_t;
295  *
296  * The structure #sip_www_authenticate_t contains representation of SIP
297  * @WWWAuthenticate header.
298  *
299  * The #sip_www_authenticate_t is defined as follows:
300  * @code
301  * typedef struct msg_auth_s {
302  *   msg_common_t       au_common[1];  // Common fragment info
303  *   msg_auth_t        *au_next;       // Link to next header
304  *   char const        *au_scheme;     // Auth-scheme like "Basic" or "Digest"
305  *   msg_param_t const *au_params;     // Comma-separated parameters
306  * } sip_www_authenticate_t;
307  * @endcode
308  *
309  */
310 
311 msg_hclass_t sip_www_authenticate_class[] =
312 SIP_HEADER_CLASS_AUTH(www_authenticate, "WWW-Authenticate", append);
313 
sip_www_authenticate_d(su_home_t * home,sip_header_t * h,char * s,isize_t slen)314 issize_t sip_www_authenticate_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
315 {
316   return msg_auth_d(home, h, s, slen);
317 }
318 
sip_www_authenticate_e(char b[],isize_t bsiz,sip_header_t const * h,int f)319 issize_t sip_www_authenticate_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
320 {
321   assert(sip_is_www_authenticate(h));
322   return msg_auth_e(b, bsiz, h, f);
323 }
324 
325 /**@SIP_HEADER sip_authentication_info Authentication-Info Header
326  *
327  * The @b Authentication-Info header contains either a next-nonce used by
328  * next request and/or authentication from server used in mutual
329  * authentication. The syntax of @b Authentication-Info header is defined in
330  * @RFC2617 and @RFC3261 as follows:
331  *
332  * @code
333  *   Authentication-Info  = "Authentication-Info" HCOLON ainfo
334  *                           *(COMMA ainfo)
335  *   ainfo                =  nextnonce / message-qop
336  *                            / response-auth / cnonce
337  *                            / nonce-count
338  *   nextnonce            =  "nextnonce" EQUAL nonce-value
339  *   response-auth        =  "rspauth" EQUAL response-digest
340  *   response-digest      =  LDQUOT *LHEX RDQUOT
341  * @endcode
342  *
343  * The parsed Authentication-Info header
344  * is stored in #sip_authentication_info_t structure.
345  */
346 
347 /**@ingroup sip_authentication_info
348  * @typedef typedef struct sip_authentication_info_s sip_authentication_info_t;
349  *
350  * The structure #sip_authentication_info_t contains representation of SIP
351  * @AuthenticationInfo header.
352  *
353  * The #sip_authentication_info_t is defined as follows:
354  * @code
355  * typedef struct msg_auth_info_s
356  * {
357  *   msg_common_t       ai_common[1];  // Common fragment info
358  *   msg_error_t       *ai_next;       // Dummy link to next header
359  *   msg_param_t       *ai_items;      // List of ainfo
360  * } sip_authentication_info_t;
361  * @endcode
362  */
363 
364 #define sip_authentication_info_dup_xtra msg_list_dup_xtra
365 #define sip_authentication_info_dup_one msg_list_dup_one
366 #define sip_authentication_info_update NULL
367 
368 msg_hclass_t sip_authentication_info_class[] =
369   SIP_HEADER_CLASS(authentication_info, "Authentication-Info", "",
370 		   ai_params, append, authentication_info);
371 
sip_authentication_info_d(su_home_t * home,sip_header_t * h,char * s,isize_t slen)372 issize_t sip_authentication_info_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
373 {
374   return msg_list_d(home, (msg_header_t *)h, s, slen);
375 }
376 
377 
sip_authentication_info_e(char b[],isize_t bsiz,sip_header_t const * h,int f)378 issize_t sip_authentication_info_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
379 {
380   assert(sip_is_authentication_info(h));
381   return msg_list_e(b, bsiz, h, f);
382 }
383 
384 
385 /* ====================================================================== */
386 
387 /**@SIP_HEADER sip_proxy_authentication_info Proxy-Authentication-Info Header
388  *
389  * The @b Proxy-Authentication-Info header contains either a next-nonce used
390  * by next request and/or authentication from proxy used in mutual
391  * authentication. The syntax of @b Proxy-Authentication-Info header is defined
392  * in @RFC2617 as follows:
393  *
394  * @code
395  *   Proxy-Authentication-Info  = "Proxy-Authentication-Info" HCOLON ainfo
396  *                           *(COMMA ainfo)
397  *   ainfo                =  nextnonce / message-qop
398  *                            / response-auth / cnonce
399  *                            / nonce-count
400  *   nextnonce            =  "nextnonce" EQUAL nonce-value
401  *   response-auth        =  "rspauth" EQUAL response-digest
402  *   response-digest      =  LDQUOT *LHEX RDQUOT
403  * @endcode
404  *
405  * @note @b Proxy-Authentication-Info is not specified @RFC3261 and it is
406  * mentioned by @RFC2617 but in passage.
407  *
408  * The parsed Proxy-Authentication-Info header
409  * is stored in #sip_proxy_authentication_info_t structure.
410  */
411 
412 /**@ingroup sip_proxy_authentication_info
413  * @typedef typedef struct msg_authentication_info_s sip_proxy_authentication_info_t;
414  *
415  * The structure #sip_proxy_authentication_info_t contains representation of SIP
416  * @ProxyAuthenticationInfo header.
417  *
418  * The #sip_proxy_authentication_info_t is defined as follows:
419  * @code
420  * typedef struct msg_auth_info_s
421  * {
422  *   msg_common_t       ai_common[1];  // Common fragment info
423  *   msg_error_t       *ai_next;       // Dummy link to next header
424  *   msg_param_t       *ai_items;      // List of ainfo
425  * } sip_proxy_authentication_info_t;
426  * @endcode
427  *
428  */
429 
430 #define sip_proxy_authentication_info_dup_xtra msg_list_dup_xtra
431 #define sip_proxy_authentication_info_dup_one msg_list_dup_one
432 #define sip_proxy_authentication_info_update NULL
433 
434 msg_hclass_t sip_proxy_authentication_info_class[] =
435   SIP_HEADER_CLASS(proxy_authentication_info, "Proxy-Authentication-Info", "",
436 		   ai_params, append, proxy_authentication_info);
437 
sip_proxy_authentication_info_d(su_home_t * home,sip_header_t * h,char * s,isize_t slen)438 issize_t sip_proxy_authentication_info_d(su_home_t *home, sip_header_t *h,
439 					 char *s, isize_t slen)
440 {
441   return msg_list_d(home, (msg_header_t *)h, s, slen);
442 }
443 
sip_proxy_authentication_info_e(char b[],isize_t bsiz,sip_header_t const * h,int f)444 issize_t sip_proxy_authentication_info_e(char b[], isize_t bsiz,
445 					 sip_header_t const *h, int f)
446 {
447   assert(sip_is_proxy_authentication_info(h)); /* This is soo popular */
448   return msg_list_e(b, bsiz, h, f);
449 }
450 
451 /* ====================================================================== */
452 
453 /* Functions parsing @RFC3329 SIP Security Agreement headers */
454 
455 typedef struct sip_security_agree_s sip_security_agree_t;
456 #define sh_security_agree sh_security_client
457 
458 static
sip_security_agree_d(su_home_t * home,sip_header_t * h,char * s,isize_t slen)459 issize_t sip_security_agree_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
460 {
461 
462 	for (;;) {
463 		sip_security_agree_t *sa = (sip_security_agree_t *)h;
464 
465 		isize_t n;
466 
467 		while (*s == ',')   /* Ignore empty entries (comma-whitespace) */
468 			*s = '\0', s += span_lws(s + 1) + 1;
469 
470 		if ((n = span_token(s)) == 0)
471 			return -1;
472 		sa->sa_mec = s; s += n; while (IS_LWS(*s)) *s++ = '\0';
473 		if (*s == ';' && msg_params_d(home, &s, &sa->sa_params) < 0)
474 			return -1;
475 
476 		msg_parse_next_field_without_recursion();
477 	}
478 
479 }
480 
481 static
sip_security_agree_e(char b[],isize_t bsiz,sip_header_t const * h,int f)482 issize_t sip_security_agree_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
483 {
484   char *end = b + bsiz, *b0 = b;
485   sip_security_agree_t const *sa = (sip_security_agree_t const *)h;
486 
487   MSG_STRING_E(b, end, sa->sa_mec);
488   MSG_PARAMS_E(b, end, sa->sa_params, flags);
489 
490   return b - b0;
491 }
492 
493 static
sip_security_agree_dup_xtra(sip_header_t const * h,isize_t offset)494 isize_t sip_security_agree_dup_xtra(sip_header_t const *h, isize_t offset)
495 {
496   sip_security_agree_t const *sa = h->sh_security_agree;
497 
498   MSG_PARAMS_SIZE(offset, sa->sa_params);
499   offset += MSG_STRING_SIZE(sa->sa_mec);
500 
501   return offset;
502 }
503 
504 /** Duplicate one sip_security_agree_t object */
505 static
sip_security_agree_dup_one(sip_header_t * dst,sip_header_t const * src,char * b,isize_t xtra)506 char *sip_security_agree_dup_one(sip_header_t *dst, sip_header_t const *src,
507 				 char *b, isize_t xtra)
508 {
509   sip_security_agree_t *sa_dst = dst->sh_security_agree;
510   sip_security_agree_t const *sa_src = src->sh_security_agree;
511 
512   char *end = b + xtra;
513   b = msg_params_dup(&sa_dst->sa_params, sa_src->sa_params, b, xtra);
514   MSG_STRING_DUP(b, sa_dst->sa_mec, sa_src->sa_mec);
515   assert(b <= end); (void)end;
516 
517   return b;
518 }
519 
sip_security_agree_update(msg_common_t * h,char const * name,isize_t namelen,char const * value)520 static int sip_security_agree_update(msg_common_t *h,
521 				     char const *name, isize_t namelen,
522 				     char const *value)
523 {
524   sip_security_agree_t *sa = (sip_security_agree_t *)h;
525 
526   if (name == NULL) {
527     sa->sa_q = NULL;
528     sa->sa_d_alg = NULL;
529     sa->sa_d_qop = NULL;
530     sa->sa_d_ver = NULL;
531   }
532 #define MATCH(s) (namelen == strlen(#s) && su_casenmatch(name, #s, strlen(#s)))
533 
534   else if (MATCH(q)) {
535     sa->sa_q = value;
536   }
537   else if (MATCH(d-alg)) {
538     sa->sa_d_alg = value;
539   }
540   else if (MATCH(d-qop)) {
541     sa->sa_d_qop = value;
542   }
543   else if (MATCH(d-ver)) {
544     sa->sa_d_ver = value;
545   }
546 
547 #undef MATCH
548 
549   return 0;
550 }
551 
552 
553 /**@SIP_HEADER sip_security_client Security-Client Header
554  *
555  * The Security-Client header is defined by @RFC3329, "Security Mechanism
556  * Agreement for the Session Initiation Protocol (SIP)".
557  *
558  * @code
559  *    security-client  = "Security-Client" HCOLON
560  *                       sec-mechanism *(COMMA sec-mechanism)
561  *    security-server  = "Security-Server" HCOLON
562  *                       sec-mechanism *(COMMA sec-mechanism)
563  *    security-verify  = "Security-Verify" HCOLON
564  *                       sec-mechanism *(COMMA sec-mechanism)
565  *    sec-mechanism    = mechanism-name *(SEMI mech-parameters)
566  *    mechanism-name   = ( "digest" / "tls" / "ipsec-ike" /
567  *                        "ipsec-man" / token )
568  *    mech-parameters  = ( preference / digest-algorithm /
569  *                         digest-qop / digest-verify / extension )
570  *    preference       = "q" EQUAL qvalue
571  *    qvalue           = ( "0" [ "." 0*3DIGIT ] )
572  *                        / ( "1" [ "." 0*3("0") ] )
573  *    digest-algorithm = "d-alg" EQUAL token
574  *    digest-qop       = "d-qop" EQUAL token
575  *    digest-verify    = "d-ver" EQUAL LDQUOT 32LHEX RDQUOT
576  *    extension        = generic-param
577  * @endcode
578  *
579  * @sa @SecurityServer, @SecurityVerify, sip_security_verify_compare(),
580  * sip_security_client_select(), @RFC3329
581  *
582  * The parsed Security-Client header
583  * is stored in #sip_security_client_t structure.
584  */
585 
586 /**@ingroup sip_security_client
587  * @typedef typedef struct sip_security_client_s sip_security_client_t;
588  *
589  * The structure #sip_security_client_t contains representation of SIP
590  * @SecurityClient header.
591  *
592  * The #sip_security_client_t is defined as follows:
593  * @code
594  * typedef struct sip_security_agree_s
595  * {
596  *   sip_common_t        sa_common[1]; // Common fragment info
597  *   sip_security_client_t *sa_next;   // Link to next mechanism
598  *   char const         *sa_mec;       // Security mechanism
599  *   msg_param_t const  *sa_params;    // List of mechanism parameters
600  *   char const         *sa_q;         // Value of q (preference) parameter
601  *   char const         *sa_d_alg;     // Value of d-alg parameter
602  *   char const         *sa_d_qop;     // Value of d-qop parameter
603  *   char const         *sa_d_ver;     // Value of d-ver parameter
604  * } sip_security_client_t;
605  * @endcode
606  */
607 
608 msg_hclass_t sip_security_client_class[] =
609 SIP_HEADER_CLASS(security_client, "Security-Client", "",
610 		 sa_params, append, security_agree);
611 
sip_security_client_d(su_home_t * home,sip_header_t * h,char * s,isize_t slen)612 issize_t sip_security_client_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
613 {
614   return sip_security_agree_d(home, h, s, slen);
615 }
616 
sip_security_client_e(char b[],isize_t bsiz,sip_header_t const * h,int f)617 issize_t sip_security_client_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
618 {
619   return sip_security_agree_e(b, bsiz, h, f);
620 }
621 
622 
623 /**@SIP_HEADER sip_security_server Security-Server Header
624  *
625  * The Security-Server header is defined by @RFC3329, "Security Mechanism
626  * Agreement for the Session Initiation Protocol (SIP)".
627  *
628  * @sa @SecurityClient, @SecurityVerify, sip_security_verify_compare(),
629  * sip_security_client_select(), @RFC3329.
630  *
631  * The parsed Security-Server header
632  * is stored in #sip_security_server_t structure.
633  */
634 
635 /**@ingroup sip_security_server
636  * @typedef typedef struct sip_security_server_s sip_security_server_t;
637  *
638  * The structure #sip_security_server_t contains representation of SIP
639  * @SecurityServer header.
640  *
641  * The #sip_security_server_t is defined as follows:
642  * @code
643  * typedef struct sip_security_agree_s
644  * {
645  *   sip_common_t        sa_common[1]; // Common fragment info
646  *   sip_security_server_t *sa_next;   // Link to next mechanism
647  *   char const         *sa_mec;       // Security mechanism
648  *   msg_param_t const  *sa_params;    // List of mechanism parameters
649  *   char const         *sa_q;         // Value of q (preference) parameter
650  *   char const         *sa_d_alg;     // Value of d-alg parameter
651  *   char const         *sa_d_qop;     // Value of d-qop parameter
652  *   char const         *sa_d_ver;     // Value of d-ver parameter
653  * } sip_security_server_t;
654  * @endcode
655  */
656 
657 msg_hclass_t sip_security_server_class[] =
658 SIP_HEADER_CLASS(security_server, "Security-Server", "",
659 		 sa_params, append, security_agree);
660 
sip_security_server_d(su_home_t * home,sip_header_t * h,char * s,isize_t slen)661 issize_t sip_security_server_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
662 {
663   return sip_security_agree_d(home, h, s, slen);
664 }
665 
sip_security_server_e(char b[],isize_t bsiz,sip_header_t const * h,int f)666 issize_t sip_security_server_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
667 {
668   return sip_security_agree_e(b, bsiz, h, f);
669 }
670 
671 
672 /**@SIP_HEADER sip_security_verify Security-Verify Header
673  *
674  * The Security-Verify header is defined by @RFC3329, "Security Mechanism
675  * Agreement for the Session Initiation Protocol (SIP)".
676  *
677  * @sa @SecurityClient, @SecurityServer, sip_security_verify_compare(),
678  * sip_security_client_select(), @RFC3329.
679  *
680  * The parsed Security-Verify header
681  * is stored in #sip_security_verify_t structure.
682  */
683 
684 /**@ingroup sip_security_verify
685  * @typedef typedef struct sip_security_verify_s sip_security_verify_t;
686  *
687  * The structure #sip_security_verify_t contains representation of SIP
688  * @SecurityVerify header.
689  *
690  * The #sip_security_verify_t is defined as follows:
691  * @code
692  * typedef struct sip_security_agree_s
693  * {
694  *   sip_common_t        sa_common[1]; // Common fragment info
695  *   sip_security_verify_t *sa_next;   // Link to next mechanism
696  *   char const         *sa_mec;       // Security mechanism
697  *   msg_param_t const  *sa_params;    // List of mechanism parameters
698  *   char const         *sa_q;         // Value of q (preference) parameter
699  *   char const         *sa_d_alg;     // Value of d-alg parameter
700  *   char const         *sa_d_qop;     // Value of d-qop parameter
701  *   char const         *sa_d_ver;     // Value of d-ver parameter
702  * } sip_security_verify_t;
703  * @endcode
704  */
705 
706 
707 msg_hclass_t sip_security_verify_class[] =
708 SIP_HEADER_CLASS(security_verify, "Security-Verify", "",
709 		 sa_params, append, security_agree);
710 
sip_security_verify_d(su_home_t * home,sip_header_t * h,char * s,isize_t slen)711 issize_t sip_security_verify_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
712 {
713   return sip_security_agree_d(home, h, s, slen);
714 }
715 
sip_security_verify_e(char b[],isize_t bsiz,sip_header_t const * h,int f)716 issize_t sip_security_verify_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
717 {
718   return sip_security_agree_e(b, bsiz, h, f);
719 }
720 
721 /* ====================================================================== */
722 /* RFC 3323 */
723 
724 /**@SIP_HEADER sip_privacy Privacy Header
725  *
726  * The Privacy header is used by User-Agent to request privacy services from
727  * the network. Its syntax is defined in @RFC3323 as follows:
728  *
729  * @code
730  *    Privacy-hdr  =  "Privacy" HCOLON priv-value *(";" priv-value)
731  *    priv-value   =   "header" / "session" / "user" / "none" / "critical"
732  *                     / token
733  * @endcode
734  *
735  * The parsed Privacy header is stored in #sip_privacy_t structure.
736  */
737 
738 /**@ingroup sip_privacy
739  * @typedef typedef struct sip_privacy_s sip_privacy_t;
740  *
741  * The structure #sip_privacy_t contains representation of a SIP @Privacy
742  * header.
743  *
744  * The #sip_privacy_t is defined as follows:
745  * @code
746  * typedef struct sip_privacy_s {
747  *   sip_common_t       priv_common[1];	// Common fragment info
748  *   sip_error_t       *priv_next;     	// Dummy link
749  *   msg_param_t const *priv_values;   	// List of privacy values
750  * } sip_privacy_t;
751  * @endcode
752  */
753 
754 msg_xtra_f sip_privacy_dup_xtra;
755 msg_dup_f sip_privacy_dup_one;
756 
757 #define sip_privacy_update NULL
758 
759 msg_hclass_t sip_privacy_class[] =
760 SIP_HEADER_CLASS(privacy, "Privacy", "", priv_values, single, privacy);
761 
762 static
sip_privacy_token_scan(char * start)763 issize_t sip_privacy_token_scan(char *start)
764 {
765   char *s = start;
766   skip_token(&s);
767 
768   if (s == start)
769     return -1;
770 
771   if (IS_LWS(*s))
772     *s++ = '\0';
773   skip_lws(&s);
774 
775   return s - start;
776 }
777 
sip_privacy_d(su_home_t * home,sip_header_t * h,char * s,isize_t slen)778 issize_t sip_privacy_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
779 {
780   sip_privacy_t *priv = (sip_privacy_t *)h;
781 
782   while (*s == ';' || *s == ',') {
783     s++;
784     skip_lws(&s);
785   }
786 
787   for (;;) {
788     if (msg_any_list_d(home, &s, (msg_param_t **)&priv->priv_values,
789 		       sip_privacy_token_scan, ';') < 0)
790       return -1;
791 
792     if (*s == '\0')
793       return 0;			/* Success! */
794 
795     if (*s == ',')
796       *s++ = '\0';		/* We accept comma-separated list, too */
797     else if (IS_TOKEN(*s))
798       ;				/* LWS separated list...  */
799     else
800       return -1;
801   }
802 }
803 
sip_privacy_e(char b[],isize_t bsiz,sip_header_t const * h,int f)804 issize_t sip_privacy_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
805 {
806   sip_privacy_t const *priv = h->sh_privacy;
807   char *b0 = b, *end = b + bsiz;
808   size_t i;
809 
810   if (priv->priv_values) {
811     for (i = 0; priv->priv_values[i]; i++) {
812       if (i > 0) MSG_CHAR_E(b, end, ';');
813       MSG_STRING_E(b, end, priv->priv_values[i]);
814     }
815   }
816 
817   MSG_TERM_E(b, end);
818 
819   return b - b0;
820 }
821 
sip_privacy_dup_xtra(sip_header_t const * h,isize_t offset)822 isize_t sip_privacy_dup_xtra(sip_header_t const *h, isize_t offset)
823 {
824   sip_privacy_t const *priv = h->sh_privacy;
825 
826   MSG_PARAMS_SIZE(offset, priv->priv_values);
827 
828   return offset;
829 }
830 
sip_privacy_dup_one(sip_header_t * dst,sip_header_t const * src,char * b,isize_t xtra)831 char *sip_privacy_dup_one(sip_header_t *dst,
832 			  sip_header_t const *src,
833 			  char *b,
834 			  isize_t xtra)
835 {
836   sip_privacy_t *priv = dst->sh_privacy;
837   sip_privacy_t const *o = src->sh_privacy;
838   char *end = b + xtra;
839 
840   b = msg_params_dup(&priv->priv_values, o->priv_values, b, xtra);
841 
842   assert(b <= end); (void)end;
843 
844   return b;
845 }
846 
847