blob: 0f37fae22e9f2f65cbc589d1923c83f94a3eceff [file] [log] [blame]
Alexandre Lision8af73cb2013-12-10 14:11:20 -05001/* $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 */
33static pjsip_authorization_hdr* pjsip_authorization_hdr_clone( pj_pool_t *pool,
34 const pjsip_authorization_hdr *hdr);
35static pjsip_authorization_hdr* pjsip_authorization_hdr_shallow_clone( pj_pool_t *pool,
36 const pjsip_authorization_hdr *hdr);
37static int pjsip_authorization_hdr_print( pjsip_authorization_hdr *hdr,
38 char *buf, pj_size_t size);
39
40static 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
48PJ_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
57PJ_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
66static int print_digest_credential(pjsip_digest_credential *cred, char *buf, pj_size_t size)
67{
68 pj_ssize_t 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
97static 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
105static 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
140static 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
175static pjsip_authorization_hdr*
176pjsip_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 */
193static int pjsip_www_authenticate_hdr_print( pjsip_www_authenticate_hdr *hdr,
194 char *buf, pj_size_t size);
195static pjsip_www_authenticate_hdr* pjsip_www_authenticate_hdr_clone( pj_pool_t *pool,
196 const pjsip_www_authenticate_hdr *hdr);
197static pjsip_www_authenticate_hdr* pjsip_www_authenticate_hdr_shallow_clone( pj_pool_t *pool,
198 const pjsip_www_authenticate_hdr *hdr);
199
200static 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
208PJ_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
218PJ_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
227static int print_digest_challenge( pjsip_digest_challenge *chal,
228 char *buf, pj_size_t size)
229{
230 pj_ssize_t 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
257static 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
266static 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
297static 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
331static 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