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