Add support for ICE/STUN/TURN in res_rtp_asterisk and chan_sip.
[asterisk/asterisk.git] / res / pjproject / pjsip / src / pjsip / sip_auth_msg.c
1 /* $Id$ */
2 /* 
3  * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4  * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
19  */
20 #include <pjsip/sip_auth_msg.h>
21 #include <pjsip/sip_auth_parser.h>
22 #include <pjsip/sip_parser.h>
23 #include <pj/pool.h>
24 #include <pj/list.h>
25 #include <pj/string.h>
26 #include <pj/assert.h>
27 #include <pjsip/print_util.h>
28
29 ///////////////////////////////////////////////////////////////////////////////
30 /*
31  * Authorization and Proxy-Authorization header.
32  */
33 static pjsip_authorization_hdr* pjsip_authorization_hdr_clone( pj_pool_t *pool,
34                                                                const pjsip_authorization_hdr *hdr);
35 static pjsip_authorization_hdr* pjsip_authorization_hdr_shallow_clone( pj_pool_t *pool,
36                                                                        const pjsip_authorization_hdr *hdr);
37 static int pjsip_authorization_hdr_print( pjsip_authorization_hdr *hdr,
38                                           char *buf, pj_size_t size);
39
40 static pjsip_hdr_vptr authorization_hdr_vptr = 
41 {
42     (pjsip_hdr_clone_fptr) &pjsip_authorization_hdr_clone,
43     (pjsip_hdr_clone_fptr) &pjsip_authorization_hdr_shallow_clone,
44     (pjsip_hdr_print_fptr) &pjsip_authorization_hdr_print,
45 };
46
47
48 PJ_DEF(pjsip_authorization_hdr*) pjsip_authorization_hdr_create(pj_pool_t *pool)
49 {
50     pjsip_authorization_hdr *hdr;
51     hdr = PJ_POOL_ZALLOC_T(pool, pjsip_authorization_hdr);
52     init_hdr(hdr, PJSIP_H_AUTHORIZATION, &authorization_hdr_vptr);
53     pj_list_init(&hdr->credential.common.other_param);
54     return hdr;
55 }
56
57 PJ_DEF(pjsip_proxy_authorization_hdr*) pjsip_proxy_authorization_hdr_create(pj_pool_t *pool)
58 {
59     pjsip_proxy_authorization_hdr *hdr;
60     hdr = PJ_POOL_ZALLOC_T(pool, pjsip_proxy_authorization_hdr);
61     init_hdr(hdr, PJSIP_H_PROXY_AUTHORIZATION, &authorization_hdr_vptr);
62     pj_list_init(&hdr->credential.common.other_param);
63     return hdr;
64 }
65
66 static int print_digest_credential(pjsip_digest_credential *cred, char *buf, pj_size_t size)
67 {
68     int printed;
69     char *startbuf = buf;
70     char *endbuf = buf + size;
71     const pjsip_parser_const_t *pc = pjsip_parser_const();
72     
73     copy_advance_pair_quote_cond(buf, "username=", 9, cred->username, '"', '"');
74     copy_advance_pair_quote_cond(buf, ", realm=", 8, cred->realm, '"', '"');
75     copy_advance_pair_quote(buf, ", nonce=", 8, cred->nonce, '"', '"');
76     copy_advance_pair_quote_cond(buf, ", uri=", 6, cred->uri, '"', '"');
77     copy_advance_pair_quote(buf, ", response=", 11, cred->response, '"', '"');
78     copy_advance_pair(buf, ", algorithm=", 12, cred->algorithm);
79     copy_advance_pair_quote_cond(buf, ", cnonce=", 9, cred->cnonce, '"', '"');
80     copy_advance_pair_quote_cond(buf, ", opaque=", 9, cred->opaque, '"', '"');
81     //Note: there's no dbl-quote in qop in Authorization header 
82     // (unlike WWW-Authenticate)
83     //copy_advance_pair_quote_cond(buf, ", qop=", 6, cred->qop, '"', '"');
84     copy_advance_pair(buf, ", qop=", 6, cred->qop);
85     copy_advance_pair(buf, ", nc=", 5, cred->nc);
86     
87     printed = pjsip_param_print_on(&cred->other_param, buf, endbuf-buf, 
88                                    &pc->pjsip_TOKEN_SPEC, 
89                                    &pc->pjsip_TOKEN_SPEC, ',');
90     if (printed < 0)
91         return -1;
92     buf += printed;
93
94     return (int) (buf-startbuf);
95 }
96
97 static int print_pgp_credential(pjsip_pgp_credential *cred, char *buf, pj_size_t size)
98 {
99     PJ_UNUSED_ARG(cred);
100     PJ_UNUSED_ARG(buf);
101     PJ_UNUSED_ARG(size);
102     return -1;
103 }
104
105 static int pjsip_authorization_hdr_print( pjsip_authorization_hdr *hdr,
106                                           char *buf, pj_size_t size)
107 {
108     int printed;
109     char *startbuf = buf;
110     char *endbuf = buf + size;
111
112     copy_advance(buf, hdr->name);
113     *buf++ = ':';
114     *buf++ = ' ';
115
116     copy_advance(buf, hdr->scheme);
117     *buf++ = ' ';
118
119     if (pj_stricmp(&hdr->scheme, &pjsip_DIGEST_STR) == 0)
120     {
121         printed = print_digest_credential(&hdr->credential.digest, buf, endbuf - buf);
122     } 
123     else if (pj_stricmp(&hdr->scheme, &pjsip_PGP_STR) == 0)
124     {
125         printed = print_pgp_credential(&hdr->credential.pgp, buf, endbuf - buf);
126     } 
127     else {
128         pj_assert(0);
129         return -1;
130     }
131
132     if (printed == -1)
133         return -1;
134
135     buf += printed;
136     *buf = '\0';
137     return (int)(buf-startbuf);
138 }
139
140 static pjsip_authorization_hdr* pjsip_authorization_hdr_clone(  pj_pool_t *pool,
141                                                                 const pjsip_authorization_hdr *rhs)
142 {
143     /* This function also serves Proxy-Authorization header. */
144     pjsip_authorization_hdr *hdr;
145     if (rhs->type == PJSIP_H_AUTHORIZATION)
146         hdr = pjsip_authorization_hdr_create(pool);
147     else
148         hdr = pjsip_proxy_authorization_hdr_create(pool);
149
150     pj_strdup(pool, &hdr->scheme, &rhs->scheme);
151
152     if (pj_stricmp2(&hdr->scheme, "digest") == 0) {
153         pj_strdup(pool, &hdr->credential.digest.username, &rhs->credential.digest.username);
154         pj_strdup(pool, &hdr->credential.digest.realm, &rhs->credential.digest.realm);
155         pj_strdup(pool, &hdr->credential.digest.nonce, &rhs->credential.digest.nonce);
156         pj_strdup(pool, &hdr->credential.digest.uri, &rhs->credential.digest.uri);
157         pj_strdup(pool, &hdr->credential.digest.response, &rhs->credential.digest.response);
158         pj_strdup(pool, &hdr->credential.digest.algorithm, &rhs->credential.digest.algorithm);
159         pj_strdup(pool, &hdr->credential.digest.cnonce, &rhs->credential.digest.cnonce);
160         pj_strdup(pool, &hdr->credential.digest.opaque, &rhs->credential.digest.opaque);
161         pj_strdup(pool, &hdr->credential.digest.qop, &rhs->credential.digest.qop);
162         pj_strdup(pool, &hdr->credential.digest.nc, &rhs->credential.digest.nc);
163         pjsip_param_clone(pool, &hdr->credential.digest.other_param, &rhs->credential.digest.other_param);
164     } else if (pj_stricmp2(&hdr->scheme, "pgp") == 0) {
165         pj_assert(0);
166         return NULL;
167     } else {
168         pj_assert(0);
169         return NULL;
170     }
171
172     return hdr;
173 }
174
175 static pjsip_authorization_hdr* 
176 pjsip_authorization_hdr_shallow_clone(  pj_pool_t *pool,
177                                         const pjsip_authorization_hdr *rhs)
178 {
179     /* This function also serves Proxy-Authorization header. */
180     pjsip_authorization_hdr *hdr;
181     hdr = PJ_POOL_ALLOC_T(pool, pjsip_authorization_hdr);
182     pj_memcpy(hdr, rhs, sizeof(*hdr));
183     pjsip_param_shallow_clone(pool, &hdr->credential.common.other_param, 
184                               &rhs->credential.common.other_param);
185     return hdr;
186 }
187
188
189 ///////////////////////////////////////////////////////////////////////////////
190 /*
191  * Proxy-Authenticate and WWW-Authenticate header.
192  */
193 static int pjsip_www_authenticate_hdr_print( pjsip_www_authenticate_hdr *hdr,
194                                              char *buf, pj_size_t size);
195 static pjsip_www_authenticate_hdr* pjsip_www_authenticate_hdr_clone( pj_pool_t *pool,
196                                                                      const pjsip_www_authenticate_hdr *hdr);
197 static pjsip_www_authenticate_hdr* pjsip_www_authenticate_hdr_shallow_clone( pj_pool_t *pool,
198                                                                              const pjsip_www_authenticate_hdr *hdr);
199
200 static pjsip_hdr_vptr www_authenticate_hdr_vptr = 
201 {
202     (pjsip_hdr_clone_fptr) &pjsip_www_authenticate_hdr_clone,
203     (pjsip_hdr_clone_fptr) &pjsip_www_authenticate_hdr_shallow_clone,
204     (pjsip_hdr_print_fptr) &pjsip_www_authenticate_hdr_print,
205 };
206
207
208 PJ_DEF(pjsip_www_authenticate_hdr*) pjsip_www_authenticate_hdr_create(pj_pool_t *pool)
209 {
210     pjsip_www_authenticate_hdr *hdr;
211     hdr = PJ_POOL_ZALLOC_T(pool, pjsip_www_authenticate_hdr);
212     init_hdr(hdr, PJSIP_H_WWW_AUTHENTICATE, &www_authenticate_hdr_vptr);
213     pj_list_init(&hdr->challenge.common.other_param);
214     return hdr;
215 }
216
217
218 PJ_DEF(pjsip_proxy_authenticate_hdr*) pjsip_proxy_authenticate_hdr_create(pj_pool_t *pool)
219 {
220     pjsip_proxy_authenticate_hdr *hdr;
221     hdr = PJ_POOL_ZALLOC_T(pool, pjsip_proxy_authenticate_hdr);
222     init_hdr(hdr, PJSIP_H_PROXY_AUTHENTICATE, &www_authenticate_hdr_vptr);
223     pj_list_init(&hdr->challenge.common.other_param);
224     return hdr;
225 }
226
227 static int print_digest_challenge( pjsip_digest_challenge *chal,
228                                    char *buf, pj_size_t size)
229 {
230     int printed;
231     char *startbuf = buf;
232     char *endbuf = buf + size;
233     const pjsip_parser_const_t *pc = pjsip_parser_const();
234
235     /* Allow empty realm, see http://trac.pjsip.org/repos/ticket/1061 */
236     copy_advance_pair_quote(buf, " realm=", 7, chal->realm, '"', '"');
237     copy_advance_pair_quote_cond(buf, ",domain=", 8, chal->domain, '"', '"');
238     copy_advance_pair_quote_cond(buf, ",nonce=", 7, chal->nonce, '"', '"');
239     copy_advance_pair_quote_cond(buf, ",opaque=", 8, chal->opaque, '"', '"');
240     if (chal->stale) {
241         pj_str_t true_str = { "true", 4 };
242         copy_advance_pair(buf, ",stale=", 7, true_str);
243     }
244     copy_advance_pair(buf, ",algorithm=", 11, chal->algorithm);
245     copy_advance_pair_quote_cond(buf, ",qop=", 5, chal->qop, '"', '"');
246     
247     printed = pjsip_param_print_on(&chal->other_param, buf, endbuf-buf, 
248                                    &pc->pjsip_TOKEN_SPEC, 
249                                    &pc->pjsip_TOKEN_SPEC, ',');
250     if (printed < 0)
251         return -1;
252     buf += printed;
253
254     return (int)(buf-startbuf);
255 }
256
257 static int print_pgp_challenge( pjsip_pgp_challenge *chal,
258                                 char *buf, pj_size_t size)
259 {
260     PJ_UNUSED_ARG(chal);
261     PJ_UNUSED_ARG(buf);
262     PJ_UNUSED_ARG(size);
263     return -1;
264 }
265
266 static int pjsip_www_authenticate_hdr_print( pjsip_www_authenticate_hdr *hdr,
267                                              char *buf, pj_size_t size)
268 {
269     int printed;
270     char *startbuf = buf;
271     char *endbuf = buf + size;
272
273     copy_advance(buf, hdr->name);
274     *buf++ = ':';
275     *buf++ = ' ';
276
277     copy_advance(buf, hdr->scheme);
278     *buf++ = ' ';
279
280     if (pj_stricmp2(&hdr->scheme, "digest") == 0)
281         printed = print_digest_challenge(&hdr->challenge.digest, buf, endbuf - buf);
282     else if (pj_stricmp2(&hdr->scheme, "pgp") == 0)
283         printed = print_pgp_challenge(&hdr->challenge.pgp, buf, endbuf - buf);
284     else {
285         pj_assert(0);
286         return -1;
287     }
288
289     if (printed == -1)
290         return -1;
291
292     buf += printed;
293     *buf = '\0';
294     return (int)(buf-startbuf);
295 }
296
297 static pjsip_www_authenticate_hdr* pjsip_www_authenticate_hdr_clone( pj_pool_t *pool,
298                                                                      const pjsip_www_authenticate_hdr *rhs)
299 {
300     /* This function also serves Proxy-Authenticate header. */
301     pjsip_www_authenticate_hdr *hdr;
302     if (rhs->type == PJSIP_H_WWW_AUTHENTICATE)
303         hdr = pjsip_www_authenticate_hdr_create(pool);
304     else
305         hdr = pjsip_proxy_authenticate_hdr_create(pool);
306
307     pj_strdup(pool, &hdr->scheme, &rhs->scheme);
308
309     if (pj_stricmp2(&hdr->scheme, "digest") == 0) {
310         pj_strdup(pool, &hdr->challenge.digest.realm, &rhs->challenge.digest.realm);
311         pj_strdup(pool, &hdr->challenge.digest.domain, &rhs->challenge.digest.domain);
312         pj_strdup(pool, &hdr->challenge.digest.nonce, &rhs->challenge.digest.nonce);
313         pj_strdup(pool, &hdr->challenge.digest.opaque, &rhs->challenge.digest.opaque);
314         hdr->challenge.digest.stale = rhs->challenge.digest.stale;
315         pj_strdup(pool, &hdr->challenge.digest.algorithm, &rhs->challenge.digest.algorithm);
316         pj_strdup(pool, &hdr->challenge.digest.qop, &rhs->challenge.digest.qop);
317         pjsip_param_clone(pool, &hdr->challenge.digest.other_param, 
318                           &rhs->challenge.digest.other_param);
319     } else if (pj_stricmp2(&hdr->scheme, "pgp") == 0) {
320         pj_assert(0);
321         return NULL;
322     } else {
323         pj_assert(0);
324         return NULL;
325     }
326
327     return hdr;
328
329 }
330
331 static pjsip_www_authenticate_hdr* pjsip_www_authenticate_hdr_shallow_clone( pj_pool_t *pool,
332                                                                              const pjsip_www_authenticate_hdr *rhs)
333 {
334     /* This function also serves Proxy-Authenticate header. */
335     pjsip_www_authenticate_hdr *hdr;
336     hdr = PJ_POOL_ALLOC_T(pool, pjsip_www_authenticate_hdr);
337     pj_memcpy(hdr, rhs, sizeof(*hdr));
338     pjsip_param_shallow_clone(pool, &hdr->challenge.common.other_param, 
339                               &rhs->challenge.common.other_param);
340     return hdr;
341 }
342
343