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 test_auth_digest.c
26 *
27 * @brief Test authentication functions for "Digest" scheme.
28 *
29 * @author Pekka Pessi <Pekka.Pessi@nokia.com>
30 *
31 * @date Created: Thu Feb 22 12:10:37 2001 ppessi
32 */
33
34 #include "config.h"
35
36 #include <stddef.h>
37 #include <stdlib.h>
38 #include <stdio.h>
39 #include <string.h>
40
41 #if HAVE_SOFIA_SIP
42 #define PROTOCOL "SIP/2.0"
43 #include <sofia-sip/sip.h>
44 #include <sofia-sip/sip_header.h>
45 #include <sofia-sip/sip_hclasses.h>
46 #else
47 #define PROTOCOL "HTTP/1.1"
48 #include <sofia-sip/http.h>
49 #include <sofia-sip/http_header.h>
50 #define sip_authentication_info_class http_authentication_info_class
51 #define sip_authorization http_authorization
52 #define sip_authorization_class http_authorization_class
53 #define sip_authorization_make http_authorization_make
54 #define sip_authorization_t http_authorization_t
55 #define sip_default_mclass http_default_mclass
56 #define sip_object http_object
57 #define sip_payload http_payload
58 #define sip_proxy_authenticate_make http_proxy_authenticate_make
59 #define sip_proxy_authenticate_t http_proxy_authenticate_t
60 #define sip_proxy_authorization_make http_proxy_authorization_make
61 #define sip_proxy_authorization_t http_proxy_authorization_t
62 #define sip_request http_request
63 #define sip_request_t http_request_t
64 #define sip_t http_t
65 #define sip_www_authenticate http_www_authenticate
66 #define sip_www_authenticate_class http_www_authenticate_class
67 #define sip_www_authenticate http_www_authenticate
68 #define sip_www_authenticate_make http_www_authenticate_make
69 #define sip_www_authenticate_t http_www_authenticate_t
70 #endif
71
72 #include <sofia-sip/auth_digest.h>
73 #include <sofia-sip/auth_client.h>
74 #include <sofia-sip/msg_header.h>
75 #include <sofia-sip/su_wait.h>
76 #include <sofia-sip/su_string.h>
77
78 int tstflags;
79 char *argv0;
80
81 #define TSTFLAGS tstflags
82
83 #include <sofia-sip/tstdef.h>
84
85 #if defined(_WIN32)
86 #include <fcntl.h>
87 #endif
88
89 char const name[] = "test_auth_digest";
90
91 /* Fake su_time() implementation */
92 #include <time.h>
93
94 unsigned offset;
95
offset_time(su_time_t * tv)96 void offset_time(su_time_t *tv)
97 {
98 tv->tv_sec += offset;
99 }
100
test_digest(void)101 int test_digest(void)
102 {
103 char challenge[] = "Digest "
104 "realm=\"garage.sr.ntc.nokia.com\", "
105 "nonce=\"MjAwMS0wMS0yMSAxNTowODo1OA==\", "
106 "algorithm=MD5, "
107 "qop=\"auth\"";
108
109 char response[] =
110 "DIGEST USERNAME=\"digest\", "
111 "REALM=\"garage.sr.ntc.nokia.com\", "
112 "NONCE=\"MjAwMS0wMS0yMSAxNTowODo1OA==\", "
113 "RESPONSE=\"d9d7f1ae99a013cb05f319f0f678251d\", "
114 "URI=\"sip:garage.sr.ntc.nokia.com\"";
115
116 char rfc2617[] =
117 "Digest username=\"Mufasa\", "
118 "realm=\"testrealm@host.com\", "
119 "nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\", "
120 "cnonce=\"0a4f113b\", "
121 "nc=\"00000001\", "
122 "qop=\"auth\", "
123 "algorithm=\"md5\", "
124 "uri=\"/dir/index.html\"";
125
126 char indigo[] =
127 "Digest username=\"user1\", "
128 "realm=\"nokia-proxy\", "
129 "nonce=\"0YXwH29PCT4lEz8+YJipQg==\", "
130 "uri=\"sip:nokia@62.254.248.33\", "
131 "response=\"dd22a698b1a9510c4237c52e0e2cbfac\", "
132 "algorithm=MD5, "
133 "cnonce=\"V2VkIEF1ZyAxNSAxNzozNDowNyBHTVQrMDE6MDAgMjAwMVtCQDI0YmZhYQ==\", "
134 "opaque=\"WiMlvw==\", "
135 "qop=auth, "
136 "nc=000000002";
137
138 char proxy_authenticate[] =
139 "Digest realm=\"IndigoSw\", "
140 "domain=\"indigosw.com aol.com\", "
141 "nonce=\"V2VkIEF1ZyAxNSAxNzoxNzozNyBCU1QgMjAwMVtCQDE3OWU4Yg==\", "
142 "opaque=\"Nzg5MWU3YjZiNDQ0YzI2Zg==\", "
143 "stale=false, "
144 "algorithm=md5, "
145 "qop=\"auth, auth-int\"";
146
147 sip_www_authenticate_t *wa;
148 sip_authorization_t *au;
149 sip_proxy_authenticate_t *pa;
150 sip_proxy_authorization_t *pz;
151
152 auth_challenge_t ac[1] = {{ sizeof(ac) }};
153 auth_response_t ar[1] = {{ sizeof(ar) }};
154 su_home_t home[1] = {{ sizeof(home) }};
155
156 auth_hexmd5_t sessionkey, hresponse;
157
158 BEGIN();
159
160 TEST0(wa = sip_www_authenticate_make(home, challenge));
161 TEST_SIZE(auth_digest_challenge_get(home, ac, wa->au_params), 6);
162 TEST_S(ac->ac_realm, "garage.sr.ntc.nokia.com");
163 TEST_S(ac->ac_nonce, "MjAwMS0wMS0yMSAxNTowODo1OA==");
164 TEST_S(ac->ac_algorithm, "MD5");
165 TEST_1(ac->ac_md5); TEST_1(!ac->ac_md5sess); TEST_1(!ac->ac_sha1);
166 TEST_S(ac->ac_qop, "auth");
167 TEST_1(ac->ac_auth); TEST_1(!ac->ac_auth_int);
168
169 TEST0(au = sip_authorization_make(home, response));
170 TEST_SIZE(auth_digest_response_get(home, ar, au->au_params), 5);
171
172 TEST0(au = sip_authorization_make(home, rfc2617));
173 TEST_SIZE(auth_digest_response_get(home, ar, au->au_params), 10);
174
175 TEST0(auth_digest_sessionkey(ar, sessionkey, "Circle Of Life") == 0);
176 if (tstflags & tst_verbatim)
177 printf("%s: sessionkey=\"%s\"\n", name, sessionkey);
178 TEST0(strcmp(sessionkey, "939e7578ed9e3c518a452acee763bce9") == 0);
179
180 TEST0(auth_digest_response(ar, hresponse, sessionkey, "GET", NULL, 0) == 0);
181 if (tstflags & tst_verbatim)
182 printf("%s: hresponse=\"%s\"\n", name, hresponse);
183 TEST0(strcmp(hresponse, "6629fae49393a05397450978507c4ef1") == 0);
184
185 TEST0(au = sip_authorization_make(home, indigo));
186 TEST_SIZE(auth_digest_response_get(home, ar, au->au_params), 12);
187 TEST0(auth_digest_sessionkey(ar, sessionkey, "secret") == 0);
188 TEST0(auth_digest_response(ar, hresponse, sessionkey, "BYE", NULL, 0) == 0);
189 TEST0(strcmp(hresponse, "dd22a698b1a9510c4237c52e0e2cbfac") == 0);
190
191 TEST0(pa = sip_proxy_authenticate_make(home, proxy_authenticate));
192 TEST_SIZE(auth_digest_challenge_get(home, ac, pa->au_params), 9);
193
194 TEST_S(ac->ac_realm, "IndigoSw");
195 TEST_1(ac->ac_auth);
196 TEST_1(ac->ac_auth_int);
197
198 {
199 char challenge[] =
200 "Digest realm=\"opera.ntc.nokia.com\", "
201 "nonce=\"InyiWI+qIdvDKkO2jFK7mg==\"";
202
203 char credentials[] =
204 "Digest username=\"samuel.privat.saturday@opera.ntc.nokia.com\", "
205 "realm=\"opera.ntc.nokia.com\", nonce=\"InyiWI+qIdvDKkO2jFK7mg==\", "
206 "algorithm=MD5, uri=\"sip:opera.ntc.nokia.com\", "
207 "response=\"4b4edab897dafce8d9af4b37abcdc086\"";
208
209 memset(ac, 0, sizeof(ac)); ac->ac_size = sizeof(ac);
210 memset(ar, 0, sizeof(ar)); ar->ar_size = sizeof(ar);
211
212 TEST0(pa = sip_www_authenticate_make(home, challenge));
213 TEST_SIZE(auth_digest_challenge_get(home, ac, pa->au_params), 2);
214
215 TEST0(pz = sip_proxy_authorization_make(home, credentials));
216 TEST_SIZE(auth_digest_response_get(home, ar, pz->au_params), 7);
217
218 ar->ar_md5 = ac->ac_md5 || ac->ac_algorithm == NULL;
219
220 TEST0(!auth_digest_sessionkey(ar, sessionkey, "1123456789ABCDEF"));
221 TEST0(!auth_digest_response(ar, hresponse, sessionkey, "REGISTER", NULL, 0));
222 TEST_S(hresponse, "4b4edab897dafce8d9af4b37abcdc086");
223 }
224
225 if (0) {
226 /*
227 RFC 2069:
228 that the username for this document is "Mufasa", and the password is
229 "CircleOfLife".
230
231 The first time the client requests the document, no Authorization
232 header is sent, so the server responds with:
233
234 HTTP/1.1 401 Unauthorized
235 WWW-Authenticate: Digest realm="testrealm@host.com",
236 nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
237 opaque="5ccc069c403ebaf9f0171e9517f40e41"
238
239 The client may prompt the user for the username and password, after
240 which it will respond with a new request, including the following
241 Authorization header:
242
243 Authorization: Digest username="Mufasa",
244 realm="testrealm@host.com",
245 nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
246 uri="/dir/index.html",
247 response="e966c932a9242554e42c8ee200cec7f6",
248 opaque="5ccc069c403ebaf9f0171e9517f40e41"
249 */
250
251 char challenge[] =
252 "Digest realm=\"testrealm@host.com\", "
253 "nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\", "
254 "opaque=\"5ccc069c403ebaf9f0171e9517f40e41\"";
255
256 char rfc2069_cred[] =
257 "Digest username=\"Mufasa\", "
258 "realm=\"testrealm@host.com\", "
259 "nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\", "
260 "uri=\"/dir/index.html\", "
261 "response=\"e966c932a9242554e42c8ee200cec7f6\", "
262 "opaque=\"5ccc069c403ebaf9f0171e9517f40e41\"";
263
264 memset(ac, 0, sizeof(ac)); ac->ac_size = sizeof(ac);
265 memset(ar, 0, sizeof(ar)); ar->ar_size = sizeof(ar);
266
267 TEST0(pa = sip_www_authenticate_make(home, challenge));
268 TEST_SIZE(auth_digest_challenge_get(home, ac, pa->au_params), 3);
269
270 TEST0(pz = sip_proxy_authorization_make(home, rfc2069_cred));
271 TEST_SIZE(auth_digest_response_get(home, ar, pz->au_params), 6);
272
273 ar->ar_md5 = ac->ac_md5 || ac->ac_algorithm == NULL;
274
275 TEST_S(ar->ar_username, "Mufasa");
276 TEST0(!auth_digest_sessionkey(ar, sessionkey, "CircleOfLife"));
277 TEST0(!auth_digest_response(ar, hresponse, sessionkey, "GET", NULL, 0));
278 TEST_S(hresponse, "e966c932a9242554e42c8ee200cec7f6");
279 }
280
281 {
282 char worldcom_chal[] =
283 "Digest realm=\"WCOM\", nonce=\"ce2292f3f748fbe239bda9e852e8b986\"";
284
285 char worldcom_cred[] =
286 "Digest realm=\"WCOM\", username=\"jari\", "
287 "nonce=\"ce2292f3f748fbe239bda9e852e8b986\", "
288 "response=\"ea692d202019d41a75c70df4b2401e2f\", "
289 "uri=\"sip:1234@209.132.126.82\"";
290
291 memset(ac, 0, sizeof(ac)); ac->ac_size = sizeof(ac);
292 memset(ar, 0, sizeof(ar)); ar->ar_size = sizeof(ar);
293
294 TEST0(pa = sip_proxy_authenticate_make(home, worldcom_chal));
295 TEST_SIZE(auth_digest_challenge_get(home, ac, pa->au_params), 2);
296
297 TEST0(pz = sip_proxy_authorization_make(home, worldcom_cred));
298 TEST_SIZE(auth_digest_response_get(home, ar, pz->au_params), 5);
299
300 ar->ar_md5 = ac->ac_md5 || ac->ac_algorithm == NULL;
301
302 TEST0(!auth_digest_sessionkey(ar, sessionkey, "pass"));
303 TEST0(!auth_digest_response(ar, hresponse, sessionkey, "REGISTER", NULL, 0));
304 TEST_S(hresponse, "ea692d202019d41a75c70df4b2401e2f");
305 }
306
307 {
308 char etri_chal[] =
309 "Digest realm=\"nokia-proxy\", domain=\"sip:194.2.188.133\", "
310 "nonce=\"wB7JBwIb/XhtgfGp1VuPoQ==\", opaque=\"wkJxwA==\", "
311 ", algorithm=MD5, qop=\"auth\"";
312
313 char etri_cred[] =
314 "Digest username=\"myhuh\", realm=\"nokia-proxy\", "
315 "nonce=\"wB7JBwIb/XhtgfGp1VuPoQ==\", uri=\"sip:194.2.188.133\", "
316 "response=\"32960a62bdc202171ca5a294dc229a6d\", "
317 "opaque=\"wkJxwA==\"" /* , qop=\"auth\"" */;
318
319 memset(ac, 0, sizeof(ac)); ac->ac_size = sizeof(ac);
320 memset(ar, 0, sizeof(ar)); ar->ar_size = sizeof(ar);
321
322 TEST0(pa = sip_proxy_authenticate_make(home, etri_chal));
323 TEST_SIZE(auth_digest_challenge_get(home, ac, pa->au_params), 8);
324
325 TEST0(pz = sip_proxy_authorization_make(home, etri_cred));
326 TEST_SIZE(auth_digest_response_get(home, ar, pz->au_params), 6 /* 8 */);
327
328 ar->ar_md5 = ac->ac_md5 || ac->ac_algorithm == NULL;
329
330 TEST(auth_digest_sessionkey(ar, sessionkey, "myhuh"), 0);
331 TEST(auth_digest_response(ar, hresponse, sessionkey, "REGISTER", NULL, 0), 0);
332 TEST_S(hresponse, "32960a62bdc202171ca5a294dc229a6d");
333 }
334
335 {
336 char chal[] =
337 "Digest realm=\"nokia-proxy\", domain=\"sip:10.21.32.63\", "
338 "nonce=\"GjbLsrozHC6Lx95C57vGlw==\", opaque=\"HN22wQ==\", algorithm=MD5";
339
340 char cred[] =
341 "digest username=\"test1\",realm=\"nokia-proxy\","
342 "nonce=\"GjbLsrozHC6Lx95C57vGlw==\",opaque=\"HN22wQ==\","
343 "uri=\"sip:10.21.32.63\",response=\"e86db25d96713482e35378504caaba6b\","
344 "algorithm=\"MD5\"";
345
346 memset(ac, 0, sizeof(ac)); ac->ac_size = sizeof(ac);
347 memset(ar, 0, sizeof(ar)); ar->ar_size = sizeof(ar);
348
349 TEST0(pa = sip_proxy_authenticate_make(home, chal));
350 TEST_SIZE(auth_digest_challenge_get(home, ac, pa->au_params), 6);
351
352 TEST0(pz = sip_proxy_authorization_make(home, cred));
353
354 {
355 size_t n = auth_digest_response_get(home, ar, pz->au_params);
356 TEST_SIZE(n, 8);
357 }
358 ar->ar_md5 = ac->ac_md5 || ac->ac_algorithm == NULL;
359
360 TEST(auth_digest_sessionkey(ar, sessionkey, "test1"), 0);
361 TEST(auth_digest_response(ar, hresponse, sessionkey, "REGISTER", NULL, 0), 0);
362 TEST_S(hresponse, "db41913e8964dde69a1519739f35a302");
363 }
364
365 {
366 char challenge[] =
367 "Digest realm=\"nokia-proxy\", domain=\"sip:194.2.188.133\", "
368 "nonce=\"3wWGOvaWn3n+hFv8PK2ABQ==\", opaque=\"+GNywA==\", "
369 "algorithm=MD5, qop=\"auth-int\"";
370 char credentials[] =
371 "Digest username=\"test\", realm=\"nokia-proxy\", "
372 "nonce=\"3wWGOvaWn3n+hFv8PK2ABQ==\", "
373 "cnonce=\"11RkhFg9EdaIRD36w0EMVA==\", opaque=\"+GNywA==\", "
374 "uri=\"sip:3000@194.2.188.133\", algorithm=MD5, "
375 "response=\"26e8b9aaacfca2d68770fab1ec04e2c7\", "
376 "qop=auth-int, nc=00000001";
377 char data[] =
378 "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n"
379 "<presence>\n"
380 "<presentity uri=\"sip:3000@194.2.188.133\"/>\n"
381 "<atom atomid=\"BQpTalFpkMyF9hOlR8olWQ==\">\n"
382 "<address uri=\"sip:3000@194.2.188.133\" priority=\" 0\">\n"
383 "<status status=\"open\"/>\n"
384 "<class class=\"business\"/>\n"
385 "<duplex duplex=\"full\"/>\n"
386 "<feature feature=\"voicemail\"/>\n"
387 "<mobility mobility=\"fixed\"/>\n"
388 "<note>\n"
389 "</note>\n"
390 "</address>\n"
391 "</atom>\n"
392 "</presence>\n";
393
394 memset(ac, 0, sizeof(ac)); ac->ac_size = sizeof(ac);
395 memset(ar, 0, sizeof(ar)); ar->ar_size = sizeof(ar);
396
397 TEST0(pa = sip_proxy_authenticate_make(home, challenge));
398 TEST_SIZE(auth_digest_challenge_get(home, ac, pa->au_params), 8);
399
400 TEST0(pz = sip_proxy_authorization_make(home, credentials));
401 TEST_SIZE(auth_digest_response_get(home, ar, pz->au_params), 12);
402
403 ar->ar_md5 = ac->ac_md5 || ac->ac_algorithm == NULL;
404
405 TEST0(!auth_digest_sessionkey(ar, sessionkey, "test"));
406 TEST0(!auth_digest_response(ar, hresponse, sessionkey, "REGISTER",
407 data, strlen(data)));
408 TEST_S(hresponse, "26e8b9aaacfca2d68770fab1ec04e2c7");
409 }
410
411 su_home_deinit(home);
412
413 END();
414 }
415
416 #include <sofia-sip/msg_addr.h>
417
read_message(int flags,char const buffer[])418 msg_t *read_message(int flags, char const buffer[])
419 {
420 int n, m;
421 msg_t *msg;
422 msg_iovec_t iovec[2];
423
424 n = strlen(buffer);
425 if (n == 0)
426 return NULL;
427
428 msg = msg_create(sip_default_mclass(), flags);
429 if (msg_recv_iovec(msg, iovec, 2, n, 1) < 0) {
430 perror("msg_recv_iovec");
431 }
432 memcpy(iovec->mv_base, buffer, n);
433 msg_recv_commit(msg, n, 1);
434
435 m = msg_extract(msg);
436 if (m < 0) {
437 fprintf(stderr, "test_auth_digest: parsing error\n");
438 return NULL;
439 }
440
441 return msg;
442 }
443
444 #define AUTH_MAGIC_T su_root_t
445
446 #include <sofia-sip/auth_module.h>
447
448 static
test_callback(su_root_t * root,auth_status_t * as)449 void test_callback(su_root_t *root, auth_status_t *as)
450 {
451 su_root_break(root);
452 }
453
454 static
init_as(auth_status_t * as)455 void init_as(auth_status_t *as)
456 {
457 memset(as, 0, sizeof *as);
458 as->as_home->suh_size = (sizeof *as);
459 su_home_init(as->as_home);
460 as->as_method = "REGISTER";
461 as->as_status = 500;
462 as->as_phrase = "Infernal Error";
463 }
464
465 static
deinit_as(auth_status_t * as)466 void deinit_as(auth_status_t *as)
467 {
468 su_home_deinit(as->as_home);
469 memset(as, 0, sizeof *as);
470 }
471
472 static
reinit_as(auth_status_t * as)473 void reinit_as(auth_status_t *as)
474 {
475 deinit_as(as); init_as(as);
476 }
477
478 /* Test digest authentication client and server */
test_digest_client(void)479 int test_digest_client(void)
480 {
481 BEGIN();
482
483 {
484 char challenge[] =
485 PROTOCOL " 401 Unauthorized\r\n"
486 "Call-ID:0e3dc2b2-dcc6-1226-26ac-258b5ce429ab\r\n"
487 "CSeq:32439043 REGISTER\r\n"
488 "From:surf3.ims3.so.noklab.net <sip:surf3@ims3.so.noklab.net>;tag=I8hFdg0H3OK\r\n"
489 "To:<sip:surf3@ims3.so.noklab.net>\r\n"
490 "Via:SIP/2.0/UDP 10.21.36.70:23800;branch=z9hG4bKJjKGu9vIHqf;received=10.21.36.70;rport\r\n"
491 "WWW-Authenticate:DIGEST algorithm=MD5,nonce=\"h7wIpP+atU+/+Zau5UwLMA==\",realm=\"ims3.so.noklab.net\"\r\n"
492 "Content-Length:0\r\n"
493 "Security-Server:digest\r\n"
494 "r\n";
495
496 char request[] =
497 "REGISTER sip:ims3.so.noklab.net " PROTOCOL "\r\n"
498 "Via: SIP/2.0/UDP 10.21.36.70:23800;rport;branch=z9hG4bKRE18GFwa3AS\r\n"
499 "Max-Forwards: 80\r\n"
500 "From: surf3.ims3.so.noklab.net <sip:surf3@ims3.so.noklab.net>;tag=I8hFdg0H3OK\r\n"
501 "To: <sip:surf3@ims3.so.noklab.net>\r\n"
502 "Call-ID: 0e3dc2b2-dcc6-1226-26ac-258b5ce429ab\r\n"
503 "CSeq: 32439044 REGISTER\r\n"
504 "Contact: <sip:10.21.36.70:23800>\r\n"
505 "Expires: 3600\r\n"
506 "Supported: timer, 100rel\r\n"
507 "Security-Client: digest\r\n"
508 "Security-Verify: digest;d-ver=\"1234\"\r\n"
509 "Content-Length: 0\r\n"
510 "r\n";
511
512 msg_t *m1, *m2;
513 sip_t *sip;
514 auth_client_t *aucs = NULL;
515 sip_request_t *rq;
516 su_home_t *home;
517 su_root_t *root;
518 char *srcdir, *s, *testpasswd;
519 auth_mod_t *am;
520 auth_status_t as[1];
521 sip_www_authenticate_t *au;
522 auth_challenger_t ach[1] =
523 {{ 401, "Authorization required",
524 sip_www_authenticate_class,
525 sip_authentication_info_class
526 }};
527 auth_challenger_t pach[1] =
528 {{ 407, "Proxy Authorization required",
529 sip_proxy_authenticate_class,
530 sip_proxy_authentication_info_class
531 }};
532
533 TEST_1(home = su_home_new(sizeof(*home)));
534
535 TEST_1(m1 = read_message(MSG_DO_EXTRACT_COPY, challenge));
536 TEST_1(sip = sip_object(m1));
537
538 TEST_1(aucs == NULL);
539 TEST(auc_challenge(&aucs, home, sip->sip_www_authenticate,
540 sip_authorization_class), 1);
541 TEST_1(aucs != NULL);
542 msg_destroy(m1);
543
544 TEST(auc_all_credentials(&aucs, "DIGEST", "\"ims3.so.noklab.net\"",
545 "surf3.private@ims3.so.noklab.net", "1234"), 1);
546
547 TEST_1(m2 = read_message(MSG_DO_EXTRACT_COPY, request));
548 TEST_1(sip = sip_object(m2));
549 TEST_P(sip->sip_authorization, NULL);
550 TEST_1(rq = sip->sip_request);
551 TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name,
552 rq->rq_url, sip->sip_payload), 1);
553 TEST_1(sip->sip_authorization);
554 TEST_S(msg_params_find(sip->sip_authorization->au_params,
555 "response="),
556 "\"860f5ecc9990772e16937750ced9594d\"");
557
558 TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name,
559 (url_t *)"sip:surf3@ims3.so.noklab.net",
560 sip->sip_payload), 1);
561 TEST_1(sip->sip_authorization);
562 TEST_S(msg_params_find(sip->sip_authorization->au_params,
563 "response="),
564 "\"9ce0d6a5869b4e09832d5b705453cbfc\"");
565
566 srcdir = getenv("srcdir");
567 if (srcdir == NULL) {
568 srcdir = su_strdup(home, argv0);
569 if ((s = strrchr(srcdir, '/')))
570 *s = '\0';
571 else
572 srcdir = ".";
573 }
574 TEST_1(testpasswd = su_sprintf(home, "%s/testpasswd", srcdir));
575
576 TEST_1(root = su_root_create(NULL));
577
578 TEST_1(am = auth_mod_create(NULL,
579 AUTHTAG_METHOD("Digest"),
580 AUTHTAG_REALM("ims3.so.noklab.net"),
581 AUTHTAG_DB(testpasswd),
582 AUTHTAG_OPAQUE("+GNywA=="),
583 TAG_END()));
584
585 init_as(as);
586 auth_mod_check_client(am, as, sip->sip_authorization, ach);
587 TEST(as->as_status, 401);
588
589 TEST_1(au = sip_authorization_make(home,
590 "Digest username=\"user1\", "
591 "nonce=\"3wWGOvaWn3n+hFv8PK2ABQ==\", "
592 "opaque=\"+GNywA==\", "
593 "uri=\"sip:3000@194.2.188.133\", "
594 "response=\"26e8b9aaacfca2d6"
595 "8770fab1ec04e2c7\", "
596 "realm=\"ims3.so.noklab.net\""));
597
598 reinit_as(as);
599 auth_mod_check_client(am, as, au, ach);
600 TEST(as->as_status, 401);
601
602 {
603 char const *username = au->au_params[0];
604 char const *nonce = au->au_params[1];
605 char const *opaque = au->au_params[2];
606 char const *uri = au->au_params[3];
607 char const *response = au->au_params[4];
608 char const *realm = au->au_params[5];
609
610 TEST_S(username, "username=\"user1\"");
611 TEST_S(nonce, "nonce=\"3wWGOvaWn3n+hFv8PK2ABQ==\"");
612 TEST_S(opaque, "opaque=\"+GNywA==\"");
613 TEST_S(uri, "uri=\"sip:3000@194.2.188.133\"");
614 TEST_S(response, "response=\"26e8b9aaacfca2d68770fab1ec04e2c7\"");
615
616 TEST(msg_params_remove((msg_param_t *)au->au_params, "username"), 1);
617 reinit_as(as);
618 auth_mod_check_client(am, as, au, ach);
619 TEST(as->as_status, 400);
620 msg_params_add(home, (msg_param_t **)&au->au_params, username);
621
622 TEST(msg_params_remove((msg_param_t *)au->au_params, "nonce"), 1);
623 reinit_as(as);
624 auth_mod_check_client(am, as, au, ach);
625 TEST(as->as_status, 400);
626 msg_params_add(home, (msg_param_t **) &au->au_params, nonce);
627
628 TEST(msg_params_remove((msg_param_t *)au->au_params, "opaque"), 1);
629 reinit_as(as);
630 auth_mod_check_client(am, as, au, ach);
631 TEST(as->as_status, 401); /* We use opaque to match authorization */
632 msg_params_add(home, (msg_param_t **) &au->au_params, opaque);
633
634 TEST(msg_params_remove((msg_param_t *)au->au_params, "uri"), 1);
635 reinit_as(as);
636 auth_mod_check_client(am, as, au, ach);
637 TEST(as->as_status, 400);
638 msg_params_add(home, (msg_param_t **) &au->au_params, uri);
639
640 TEST(msg_params_remove((msg_param_t *)au->au_params, "response"), 1);
641 reinit_as(as);
642 auth_mod_check_client(am, as, au, ach);
643 TEST(as->as_status, 400);
644 msg_params_add(home, (msg_param_t **)&au->au_params, response);
645
646 TEST(msg_params_remove((msg_param_t *)au->au_params, "realm"), 1);
647 reinit_as(as);
648 auth_mod_check_client(am, as, au, ach);
649 TEST(as->as_status, 401); /* au is ignored by auth_module */
650 msg_params_add(home, (msg_param_t **)&au->au_params, realm);
651
652 reinit_as(as);
653 auth_mod_check_client(am, as, au, ach);
654 TEST(as->as_status, 401);
655 }
656
657 as->as_response = (msg_header_t *)
658 sip_www_authenticate_make(as->as_home, "Unknown realm=\"huu haa\"");
659 TEST_1(as->as_response);
660 TEST(auc_challenge(&aucs, home, (msg_auth_t *)as->as_response,
661 sip_authorization_class), 1);
662 aucs = NULL;
663
664 reinit_as(as);
665 auth_mod_check_client(am, as, NULL, ach);
666 TEST(as->as_status, 401);
667 TEST(auc_challenge(&aucs, home, (msg_auth_t *)as->as_response,
668 sip_authorization_class), 1);
669 reinit_as(as);
670
671 TEST(auc_all_credentials(&aucs, "Digest", "\"ims3.so.noklab.net\"",
672 "user1", "secret"), 1);
673
674 msg_header_remove(m2, (void *)sip, (void *)sip->sip_authorization);
675
676 TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name,
677 (url_t *)"sip:surf3@ims3.so.noklab.net",
678 sip->sip_payload), 1);
679 TEST_1(sip->sip_authorization);
680
681 TEST_1(msg_params_find(sip->sip_authorization->au_params, "cnonce=") == 0);
682 TEST_1(msg_params_find(sip->sip_authorization->au_params, "nc=") == 0);
683
684 auth_mod_check_client(am, as, sip->sip_authorization, ach);
685 TEST(as->as_status, 0);
686 TEST_1(as->as_info); /* challenge for next round */
687 auth_mod_destroy(am);
688 aucs = NULL;
689
690 TEST_1(am = auth_mod_create(NULL,
691 AUTHTAG_METHOD("Digest"),
692 AUTHTAG_REALM("ims3.so.noklab.net"),
693 AUTHTAG_DB(testpasswd),
694 AUTHTAG_ALGORITHM("MD5-sess"),
695 AUTHTAG_QOP("auth"),
696 AUTHTAG_OPAQUE("opaque=="),
697 TAG_END()));
698
699 reinit_as(as);
700 auth_mod_check_client(am, as, NULL, ach); TEST(as->as_status, 401);
701
702 {
703 msg_auth_t *au = (msg_auth_t *)as->as_response;
704 int i;
705 char *equal;
706
707 if (au->au_params)
708 for (i = 0; au->au_params[i]; i++) {
709 if (su_casenmatch(au->au_params[i], "realm=", 6))
710 continue;
711 equal = strchr(au->au_params[i], '=');
712 if (equal)
713 msg_unquote(equal + 1, equal + 1);
714 }
715
716 TEST(auc_challenge(&aucs, home, au, sip_authorization_class), 1);
717 reinit_as(as);
718 }
719
720 TEST(auc_all_credentials(&aucs, "Digest", "\"ims3.so.noklab.net\"",
721 "user1", "secret"), 1);
722 msg_header_remove(m2, (void *)sip, (void *)sip->sip_authorization);
723 TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name,
724 (url_t *)"sip:surf3@ims3.so.noklab.net",
725 sip->sip_payload), 1);
726 TEST_1(sip->sip_authorization);
727
728 auth_mod_check_client(am, as, sip->sip_authorization, ach);
729 TEST(as->as_status, 0);
730 TEST_1(as->as_info == NULL); /* No challenge for next round */
731
732 /* Test with changed payload */
733
734 reinit_as(as);
735 as->as_body = "foo"; as->as_bodylen = 3;
736 auth_mod_check_client(am, as, sip->sip_authorization, ach);
737 TEST(as->as_status, 0);
738
739 reinit_as(as); aucs = NULL;
740
741 /* Test without opaque */
742 {
743 msg_auth_t *au;
744 char const *opaque;
745
746 auth_mod_check_client(am, as, NULL, ach); TEST(as->as_status, 401);
747
748 au = (void *)msg_header_dup(home, as->as_response); TEST_1(au);
749
750 TEST_1(msg_params_find_slot((msg_param_t *)au->au_params, "opaque"));
751
752 opaque = *msg_params_find_slot((msg_param_t *)au->au_params, "opaque");
753
754 TEST(msg_params_remove((msg_param_t *)au->au_params, "opaque"), 1);
755
756 TEST(auc_challenge(&aucs, home, au, sip_authorization_class), 1);
757 TEST(auc_all_credentials(&aucs, "Digest", "\"ims3.so.noklab.net\"",
758 "user1", "secret"), 1);
759 msg_header_remove(m2, (void *)sip, (void *)sip->sip_authorization);
760
761 TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name,
762 (url_t *)"sip:surf3@ims3.so.noklab.net",
763 sip->sip_payload), 1);
764
765 TEST_1(sip->sip_authorization);
766 msg_params_add(home,
767 (msg_param_t **)&sip->sip_authorization->au_params,
768 opaque);
769
770 reinit_as(as);
771 auth_mod_check_client(am, as, sip->sip_authorization, ach);
772 TEST(as->as_status, 0);
773 }
774
775 reinit_as(as); auth_mod_destroy(am); aucs = NULL;
776
777 /* Test without realm */
778 {
779 msg_auth_t *au;
780
781 TEST_1(am = auth_mod_create(NULL,
782 AUTHTAG_METHOD("Digest"),
783 AUTHTAG_DB(testpasswd),
784 AUTHTAG_ALGORITHM("MD5-sess"),
785 AUTHTAG_QOP("auth"),
786 AUTHTAG_OPAQUE("opaque=="),
787 TAG_END()));
788 as->as_realm = NULL;
789 auth_mod_check_client(am, as, NULL, ach); TEST(as->as_status, 500);
790
791 as->as_realm = "ims3.so.noklab.net";
792 auth_mod_check_client(am, as, NULL, ach); TEST(as->as_status, 401);
793
794 au = (void *)msg_header_dup(home, as->as_response); TEST_1(au);
795
796 TEST(auc_challenge(&aucs, home, au, sip_authorization_class), 1);
797 TEST(auc_all_credentials(&aucs, "Digest", "\"ims3.so.noklab.net\"",
798 "user1", "secret"), 1);
799 msg_header_remove(m2, (void *)sip, (void *)sip->sip_authorization);
800
801 TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name,
802 (url_t *)"sip:surf3@ims3.so.noklab.net",
803 sip->sip_payload), 1);
804
805 TEST_1(sip->sip_authorization);
806 reinit_as(as);
807
808 as->as_realm = "ims3.so.noklab.net";
809 auth_mod_check_client(am, as, sip->sip_authorization, ach);
810 TEST(as->as_status, 0);
811 }
812
813 reinit_as(as); auth_mod_destroy(am); aucs = NULL;
814
815 /* Test nextnonce */
816 {
817 char const *nonce1, *nextnonce, *nonce2;
818
819 TEST_1(am = auth_mod_create(NULL,
820 AUTHTAG_METHOD("Digest"),
821 AUTHTAG_REALM("ims3.so.noklab.net"),
822 AUTHTAG_DB(testpasswd),
823 AUTHTAG_ALGORITHM("MD5"),
824 AUTHTAG_QOP("auth-int"),
825 AUTHTAG_EXPIRES(90),
826 /* Generate nextnonce
827 if NEXT_EXPIRES in nonzero */
828 AUTHTAG_NEXT_EXPIRES(900),
829 TAG_END()));
830
831 reinit_as(as);
832 auth_mod_check_client(am, as, NULL, ach); TEST(as->as_status, 401);
833
834 TEST(auc_challenge(&aucs, home, (msg_auth_t *)as->as_response,
835 sip_authorization_class), 1);
836 TEST(auc_all_credentials(&aucs, "Digest", "\"ims3.so.noklab.net\"",
837 "user1", "secret"), 1);
838 msg_header_remove(m2, (void *)sip, (void *)sip->sip_authorization);
839 TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name,
840 (url_t *)"sip:surf3@ims3.so.noklab.net",
841 sip->sip_payload), 1);
842 TEST_1(sip->sip_authorization);
843 TEST_1(nonce1 = msg_header_find_param(sip->sip_authorization->au_common, "nonce"));
844
845 reinit_as(as);
846 auth_mod_check_client(am, as, sip->sip_authorization, ach);
847 TEST(as->as_status, 0);
848 /* We got authentication-info */
849 TEST_1(as->as_info);
850 /* It contains nextnonce */
851 TEST_1(nextnonce = msg_header_find_param(as->as_info->sh_common, "nextnonce"));
852
853 /* Store it in authenticator */
854 TEST(auc_info(&aucs, (msg_auth_info_t const *)as->as_info, sip_authorization_class), 1);
855
856 msg_header_remove(m2, (void *)sip, (void *)sip->sip_authorization);
857 TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name,
858 (url_t *)"sip:surf3@ims3.so.noklab.net",
859 sip->sip_payload), 1);
860 TEST_1(sip->sip_authorization);
861 TEST_1(nonce2 = msg_header_find_param(sip->sip_authorization->au_common, "nonce"));
862
863 /*
864 * Make sure that server-side sends nextnonce in Authentication-info
865 * header, nextnonce differs from nonce sent in Challenge
866 */
867 TEST_1(strcmp(nonce1, nextnonce));
868 /* And client-side uses it */
869 TEST_S(nonce2, nextnonce);
870
871 auth_mod_destroy(am); aucs = NULL;
872 }
873
874 TEST_1(am = auth_mod_create(NULL,
875 AUTHTAG_METHOD("Digest"),
876 AUTHTAG_REALM("ims3.so.noklab.net"),
877 AUTHTAG_DB(testpasswd),
878 AUTHTAG_ALGORITHM("MD5-sess"),
879 AUTHTAG_QOP("auth-int"),
880 TAG_END()));
881
882 reinit_as(as);
883 auth_mod_check_client(am, as, NULL, ach); TEST(as->as_status, 401);
884
885 TEST(auc_challenge(&aucs, home, (msg_auth_t *)as->as_response,
886 sip_authorization_class), 1);
887 TEST(auc_all_credentials(&aucs, "Digest", "\"ims3.so.noklab.net\"",
888 "user1", "secret"), 1);
889 msg_header_remove(m2, (void *)sip, (void *)sip->sip_authorization);
890 TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name,
891 (url_t *)"sip:surf3@ims3.so.noklab.net",
892 sip->sip_payload), 1);
893 TEST_1(sip->sip_authorization);
894
895 reinit_as(as);
896 auth_mod_check_client(am, as, sip->sip_authorization, ach);
897 TEST(as->as_status, 0);
898 auth_mod_destroy(am); aucs = NULL;
899
900 TEST_1(am = auth_mod_create(NULL,
901 AUTHTAG_METHOD("Digest"),
902 AUTHTAG_REALM("ims3.so.noklab.net"),
903 AUTHTAG_DB(testpasswd),
904 AUTHTAG_ALGORITHM("MD5-sess"),
905 AUTHTAG_QOP("auth,auth-int"),
906 AUTHTAG_FORBIDDEN(1),
907 AUTHTAG_ANONYMOUS(1),
908 AUTHTAG_MAX_NCOUNT(1),
909 TAG_END()));
910
911 reinit_as(as);
912 auth_mod_check_client(am, as, NULL, ach); TEST(as->as_status, 401);
913
914 TEST(auc_challenge(&aucs, home, (msg_auth_t *)as->as_response,
915 sip_authorization_class), 1);
916 TEST(auc_all_credentials(&aucs, "Digest", "\"ims3.so.noklab.net\"",
917 "user1", "secret"), 1);
918 msg_header_remove(m2, (void *)sip, (void *)sip->sip_authorization);
919 TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name,
920 (url_t *)"sip:surf3@ims3.so.noklab.net",
921 sip->sip_payload), 1);
922 TEST_1(sip->sip_authorization);
923
924 reinit_as(as);
925 auth_mod_check_client(am, as, sip->sip_authorization, ach);
926 TEST(as->as_status, 0);
927
928 au = (void*)msg_header_copy(msg_home(m2), (void*)sip->sip_authorization);
929
930 /* Test with invalid qop (bug #2329) */
931 msg_params_replace(msg_home(m2), (void *)&au->au_params,
932 "qop=\"auth,auth-int\"");
933 reinit_as(as);
934 auth_mod_check_client(am, as, au, ach);
935 TEST(as->as_status, 400);
936
937 reinit_as(as);
938 as->as_body = "foo"; as->as_bodylen = 3;
939 auth_mod_check_client(am, as, sip->sip_authorization, ach);
940 TEST(as->as_status, 403);
941
942 reinit_as(as);
943 as->as_body = ""; as->as_bodylen = 0;
944 as->as_method = "OPTIONS";
945 auth_mod_check_client(am, as, sip->sip_authorization, ach);
946 TEST(as->as_status, 403);
947
948 /* Test staleness check */
949 offset = 2 * 3600;
950 reinit_as(as);
951 auth_mod_check_client(am, as, sip->sip_authorization, ach);
952 TEST(as->as_status, 401);
953 TEST_1(au = (void *)as->as_response); TEST_1(au->au_params);
954 TEST_S(msg_params_find(au->au_params, "stale="), "true");
955
956 TEST(auc_challenge(&aucs, home, (msg_auth_t *)as->as_response,
957 sip_authorization_class), 1);
958 msg_header_remove(m2, (void *)sip, (void *)sip->sip_authorization);
959 TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name,
960 (url_t *)"sip:surf3@ims3.so.noklab.net",
961 sip->sip_payload), 1);
962 TEST_1(sip->sip_authorization);
963 TEST_S(msg_header_find_param(sip->sip_authorization->au_common, "nc="),
964 "00000001");
965
966 reinit_as(as);
967 auth_mod_check_client(am, as, sip->sip_authorization, ach);
968 TEST(as->as_status, 0);
969
970 /* Test nonce count check */
971 msg_header_remove(m2, (void *)sip, (void *)sip->sip_authorization);
972 TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name,
973 (url_t *)"sip:surf3@ims3.so.noklab.net",
974 sip->sip_payload), 1);
975 TEST_1(sip->sip_authorization);
976 TEST_S(msg_header_find_param(sip->sip_authorization->au_common, "nc="),
977 "00000002");
978
979 reinit_as(as);
980 auth_mod_check_client(am, as, sip->sip_authorization, ach);
981 TEST(as->as_status, 401);
982 TEST_1(au = (void *)as->as_response); TEST_1(au->au_params);
983 TEST_S(msg_params_find(au->au_params, "stale="), "true");
984
985 aucs = NULL;
986
987 /* Test anonymous operation */
988 reinit_as(as);
989 auth_mod_check_client(am, as, NULL, ach); TEST(as->as_status, 401);
990 TEST(auc_challenge(&aucs, home, (msg_auth_t *)as->as_response,
991 sip_authorization_class), 1);
992 reinit_as(as);
993
994 TEST(auc_all_credentials(&aucs, "Digest", "\"ims3.so.noklab.net\"",
995 "anonymous", ""), 1);
996 msg_header_remove(m2, (void *)sip, (void *)sip->sip_authorization);
997 TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name,
998 (url_t *)"sip:surf3@ims3.so.noklab.net",
999 sip->sip_payload), 1);
1000 TEST_1(sip->sip_authorization);
1001
1002 auth_mod_check_client(am, as, sip->sip_authorization, ach);
1003 TEST(as->as_status, 0);
1004 auth_mod_destroy(am); aucs = NULL;
1005
1006 /* Test empty realm */
1007 TEST_1(am = auth_mod_create(root,
1008 AUTHTAG_METHOD("Digest"),
1009 AUTHTAG_REALM(""),
1010 AUTHTAG_DB(testpasswd),
1011 TAG_END()));
1012 reinit_as(as);
1013 auth_mod_check_client(am, as, NULL, ach); TEST(as->as_status, 401);
1014 TEST(auc_challenge(&aucs, home, (msg_auth_t *)as->as_response,
1015 sip_authorization_class), 1);
1016 reinit_as(as);
1017
1018 TEST(auc_all_credentials(&aucs, "Digest", "\"\"", "user1", "secret"), 1);
1019 msg_header_remove(m2, (void *)sip, (void *)sip->sip_authorization);
1020 TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name,
1021 (url_t *)"sip:surf3@ims3.so.noklab.net",
1022 sip->sip_payload), 1);
1023 TEST_1(sip->sip_authorization);
1024
1025 auth_mod_check_client(am, as, sip->sip_authorization, ach);
1026 TEST(as->as_status, 0);
1027 aucs = NULL;
1028 reinit_as(as);
1029 auth_mod_check_client(am, as, NULL, pach); TEST(as->as_status, 407);
1030 TEST(auc_challenge(&aucs, home, (msg_auth_t *)as->as_response,
1031 sip_proxy_authorization_class), 1);
1032 reinit_as(as);
1033
1034 TEST(auc_credentials(&aucs, as->as_home, "Digest:\"\":user1:secret"), 1);
1035 msg_header_remove(m2, (void *)sip, (void *)sip->sip_proxy_authorization);
1036 TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name,
1037 (url_t *)"sip:surf3@ims3.so.noklab.net",
1038 sip->sip_payload), 1);
1039 TEST_1(sip->sip_proxy_authorization);
1040
1041 auth_mod_check_client(am, as, sip->sip_proxy_authorization, pach);
1042 TEST(as->as_status, 0);
1043
1044 auth_mod_destroy(am); aucs = NULL;
1045
1046 /* Test Basic authentication scheme */
1047 TEST_1(am = auth_mod_create(root,
1048 AUTHTAG_METHOD("Basic"),
1049 AUTHTAG_REALM("ims3.so.noklab.net"),
1050 AUTHTAG_DB(testpasswd),
1051 TAG_END()));
1052
1053 reinit_as(as);
1054 auth_mod_check_client(am, as, NULL, ach);
1055 TEST(as->as_status, 401);
1056
1057 TEST(auc_challenge(&aucs, home, (msg_auth_t *)as->as_response,
1058 sip_authorization_class), 1);
1059 reinit_as(as);
1060
1061 TEST(auc_all_credentials(&aucs, "Basic", "\"ims3.so.noklab.net\"",
1062 "user1", "secret"), 1);
1063 msg_header_remove(m2, (void *)sip, (void *)sip->sip_authorization);
1064 TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name,
1065 (url_t *)"sip:surf3@ims3.so.noklab.net",
1066 sip->sip_payload), 1);
1067 TEST_1(sip->sip_authorization);
1068
1069 auth_mod_check_client(am, as, sip->sip_authorization, ach);
1070 TEST(as->as_status, 0);
1071
1072 aucs = NULL;
1073
1074 reinit_as(as);
1075 auth_mod_check_client(am, as, NULL, ach);
1076 TEST(as->as_status, 401);
1077
1078 TEST(auc_challenge(&aucs, home, (msg_auth_t *)as->as_response,
1079 sip_authorization_class), 1);
1080 reinit_as(as);
1081
1082 TEST(auc_all_credentials(&aucs, "Basic", "\"ims3.so.noklab.net\"",
1083 "very-long-user-name-that-surely-exceeds-the-static-buffer",
1084 "at-least-when-used-with-the-even-longer-password"), 1);
1085 msg_header_remove(m2, (void *)sip, (void *)sip->sip_authorization);
1086 TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name,
1087 (url_t *)"sip:surf3@ims3.so.noklab.net",
1088 sip->sip_payload), 1);
1089 TEST_1(sip->sip_authorization);
1090
1091 auth_mod_check_client(am, as, sip->sip_authorization, ach);
1092 TEST(as->as_status, 0);
1093
1094 auth_mod_destroy(am); deinit_as(as); aucs = NULL;
1095
1096 /* Test client with two challenges */
1097 au = sip_www_authenticate_make(
1098 NULL,
1099 "Digest realm=\"test-realm\", "
1100 "nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\", "
1101 "opaque=\"5ccc069c403ebaf9f0171e9517f40e41\"");
1102 au->au_next = sip_www_authenticate_make(
1103 NULL,
1104 "Not-Digest realm=\"test-realm\", "
1105 "zip=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\", "
1106 "zap=\"5ccc069c403ebaf9f0171e9517f40e41\"");
1107
1108 TEST_1(auc_challenge(&aucs, home, (msg_auth_t *)au,
1109 sip_authorization_class) >= 1);
1110 TEST_1(auc_all_credentials(&aucs, "Digest", "\"test-realm\"",
1111 "user", "pass"));
1112 msg_header_remove(m2, (void *)sip, (void *)sip->sip_authorization);
1113 TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name,
1114 (url_t *)"sip:surf3@ims3.so.noklab.net",
1115 sip->sip_payload), 1);
1116 TEST_1(sip->sip_authorization);
1117 aucs = NULL;
1118
1119 /* Test asynchronous operation */
1120 aucs = NULL;
1121 TEST_1(am = auth_mod_create(root,
1122 AUTHTAG_METHOD("Delayed+Digest"),
1123 AUTHTAG_REALM("ims3.so.noklab.net"),
1124 AUTHTAG_DB(testpasswd),
1125 AUTHTAG_ALGORITHM("MD5-sess"),
1126 AUTHTAG_QOP("auth-int"),
1127 AUTHTAG_REMOTE((void *)"http://localhost:9"),
1128 TAG_END()));
1129
1130 reinit_as(as);
1131 as->as_callback = test_callback;
1132 as->as_magic = root;
1133 auth_mod_check_client(am, as, NULL, ach);
1134 TEST(as->as_status, 100);
1135 su_root_run(root);
1136 TEST(as->as_status, 401);
1137
1138 TEST(auc_challenge(&aucs, home, (msg_auth_t *)as->as_response,
1139 sip_authorization_class), 1);
1140
1141 reinit_as(as);
1142 as->as_callback = test_callback;
1143 as->as_magic = root;
1144
1145 TEST(auc_all_credentials(&aucs, "Digest", "\"ims3.so.noklab.net\"",
1146 "user1", "secret"), 1);
1147 msg_header_remove(m2, (void *)sip, (void *)sip->sip_authorization);
1148 TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name,
1149 (url_t *)"sip:surf3@ims3.so.noklab.net",
1150 sip->sip_payload), 1);
1151 TEST_1(sip->sip_authorization);
1152
1153 auth_mod_check_client(am, as, sip->sip_authorization, ach);
1154 TEST(as->as_status, 100);
1155 su_root_run(root);
1156 TEST(as->as_status, 0);
1157
1158 auth_mod_destroy(am); aucs = NULL;
1159
1160 deinit_as(as);
1161 msg_destroy(m2);
1162
1163 su_root_destroy(root);
1164
1165 su_home_unref(home);
1166 }
1167
1168 END();
1169 }
1170
1171 int
test_auth_client(void)1172 test_auth_client(void)
1173 {
1174 BEGIN();
1175
1176 {
1177 char challenge[] =
1178 PROTOCOL " 401 Unauthorized\r\n"
1179 "Call-ID:0e3dc2b2-dcc6-1226-26ac-258b5ce429ab\r\n"
1180 "CSeq:32439043 REGISTER\r\n"
1181 "From:surf3.ims3.so.noklab.net <sip:surf3@ims3.so.noklab.net>;tag=I8hFdg0H3OK\r\n"
1182 "To:<sip:surf3@ims3.so.noklab.net>\r\n"
1183 "Via:SIP/2.0/UDP 10.21.36.70:23800;branch=z9hG4bKJjKGu9vIHqf;received=10.21.36.70;rport\r\n"
1184 "WWW-Authenticate:DIGEST algorithm=MD5,nonce=\"h7wIpP+atU+/+Zau5UwLMA==\",realm=\"[::1]\"\r\n"
1185 "Proxy-Authenticate:DIGEST algorithm=MD5,nonce=\"h7wIpP+atU+/+Zau5UwLMA==\",realm=\"\\\"realm\\\"\"\r\n"
1186 "Content-Length:0\r\n"
1187 "Security-Server:digest\r\n"
1188 "r\n";
1189
1190 su_home_t *home;
1191 msg_t *msg;
1192 sip_t *sip;
1193 auth_client_t *aucs = NULL;
1194
1195 TEST_1(home = su_home_new(sizeof(*home)));
1196
1197 TEST_1(msg = read_message(MSG_DO_EXTRACT_COPY, challenge));
1198 TEST_1(sip = sip_object(msg));
1199
1200 TEST_1(aucs == NULL);
1201 TEST(auc_challenge(&aucs, home, sip->sip_www_authenticate,
1202 sip_authorization_class), 1);
1203 TEST_1(aucs != NULL);
1204
1205 TEST(auc_credentials(&aucs, home, "Digest:\"[::1]\":user:pass"), 1);
1206
1207 TEST(auc_challenge(&aucs, home, sip->sip_proxy_authenticate,
1208 sip_proxy_authorization_class), 1);
1209
1210 TEST(auc_credentials(&aucs, home, "Digest:\"\\\"realm\\\"\":user:pass"), 1);
1211
1212 msg_destroy(msg);
1213 su_home_unref(home);
1214 }
1215
1216 END();
1217 }
1218
1219 #if HAVE_FLOCK
1220 #include <sys/file.h>
1221 #endif
1222
1223 #include <sofia-sip/auth_plugin.h>
1224
1225 char tmppasswd[] = "/tmp/test_auth_digest.XXXXXX";
1226
1227 #include <unistd.h>
1228
rmtmp(void)1229 static void rmtmp(void)
1230 {
1231 if (tmppasswd[0])
1232 unlink(tmppasswd);
1233 }
1234
1235 char const passwd[] =
1236 "# Comment\n"
1237 "malformed line\n"
1238 "user1:secret:\n"
1239 /* user2 has password "secret", too */
1240 "user2:realm:4cbc2aff0b5b2b33675c0731c0db1c14\n"
1241 /* duplicate user. fun */
1242 "user1:secret:realm\n"
1243 /* empty line */
1244 "\n";
1245
1246 /* Test digest authentication client and server */
test_module_io(void)1247 int test_module_io(void)
1248 {
1249 auth_mod_t *am, am0[1];
1250 auth_passwd_t *apw, *apw2;
1251 int tmpfd;
1252
1253 BEGIN();
1254
1255 #ifndef _WIN32
1256 tmpfd = mkstemp(tmppasswd); TEST_1(tmpfd != -1);
1257 #else
1258 tmpfd = open(tmppasswd, O_WRONLY); TEST_1(tmpfd != -1);
1259 #endif
1260 atexit(rmtmp); /* Make sure temp file is unlinked */
1261
1262 TEST_SIZE(write(tmpfd, passwd, strlen(passwd)), strlen(passwd));
1263 TEST(close(tmpfd), 0);
1264
1265 /* Test file reading operation */
1266 am = auth_mod_create(NULL,
1267 AUTHTAG_METHOD("Digest"),
1268 AUTHTAG_REALM("realm"),
1269 AUTHTAG_DB(tmppasswd),
1270 AUTHTAG_ALGORITHM("MD5-sess"),
1271 AUTHTAG_QOP("auth-int"),
1272 TAG_END()); TEST_1(am);
1273
1274 apw = auth_mod_getpass(am, "user1", NULL); TEST_1(apw);
1275 TEST_S(apw->apw_realm, "realm");
1276
1277 apw = auth_mod_getpass(am, "user2", NULL); TEST_1(apw);
1278 TEST_S(apw->apw_hash, "4cbc2aff0b5b2b33675c0731c0db1c14");
1279
1280 apw2 = apw;
1281
1282 *am0 = *am;
1283
1284 TEST_1(auth_readdb_if_needed(am) == 0);
1285
1286 apw = auth_mod_getpass(am, "user2", NULL); TEST_1(apw);
1287 TEST_P(apw, apw2);
1288
1289 apw = auth_mod_addpass(am, "user3", "realm"); TEST_1(apw);
1290 /* user3 with password fisu */
1291 apw->apw_hash = "056595147630692bb29d1855089bc95b";
1292
1293 {
1294 char const user3[] = "user3:realm:7df96b4718bd933af4883c8b73c96318\n";
1295 tmpfd = open(tmppasswd, O_WRONLY|O_APPEND, 0); TEST_1(tmpfd != -1);
1296 /* user3 with password fish */
1297 TEST_SIZE(write(tmpfd, user3, strlen(user3)), strlen(user3));
1298 TEST_1(close(tmpfd) == 0);
1299 }
1300
1301 #if HAVE_FLOCK
1302 /* Test flock(). */
1303 tmpfd = open(tmppasswd, O_RDONLY);
1304
1305 TEST_1(flock(tmpfd, LOCK_EX) != -1);
1306
1307 TEST_1(auth_readdb_if_needed(am) == 0);
1308
1309 /* there should be no changes in user table */
1310 apw = auth_mod_getpass(am, "user2", NULL); TEST_1(apw);
1311 TEST_P(apw, apw2);
1312
1313 TEST_1(flock(tmpfd, LOCK_UN) != -1);
1314 #endif
1315
1316 TEST_1(auth_readdb_if_needed(am) == 0);
1317
1318 apw = auth_mod_getpass(am, "user2", "realm"); TEST_1(apw);
1319 TEST_1(apw != apw2);
1320
1321 /* Local user3 overrides non-local */
1322 apw = auth_mod_getpass(am, "user3", "realm"); TEST_1(apw);
1323 TEST_S(apw->apw_hash, "7df96b4718bd933af4883c8b73c96318");
1324
1325 /* Test truncating */
1326 {
1327 char const user1[] = "user1:secret:\n";
1328 tmpfd = open(tmppasswd, O_WRONLY|O_TRUNC, 0); TEST_1(tmpfd != -1);
1329 TEST_SIZE(write(tmpfd, user1, strlen(user1)), strlen(user1));
1330 TEST_1(close(tmpfd) == 0);
1331 }
1332
1333 TEST_1(auth_readdb_if_needed(am) == 0);
1334
1335 apw = auth_mod_getpass(am, "user2", "realm"); TEST_1(apw == NULL);
1336
1337 /* Non-local user3 is kept in database */
1338 apw = auth_mod_getpass(am, "user3", "realm"); TEST_1(apw);
1339 TEST_S(apw->apw_hash, "056595147630692bb29d1855089bc95b");
1340
1341 auth_mod_destroy(am);
1342
1343 if (unlink(tmppasswd) == 0)
1344 tmppasswd[0] = '\0';
1345
1346 END();
1347 }
1348
1349 #include <sofia-sip/su_log.h>
1350
1351 extern su_log_t iptsec_log[];
1352
1353 static
usage(int exitcode)1354 void usage(int exitcode)
1355 {
1356 fprintf(stderr, "usage: %s [-v] [-a] [-l n]\n", name);
1357 exit(exitcode);
1358 }
1359
main(int argc,char * argv[])1360 int main(int argc, char *argv[])
1361 {
1362 int retval = 0;
1363 int i;
1364 extern void (*_su_time)(su_time_t *tv);
1365
1366 _su_time = offset_time;
1367
1368 argv0 = argv[0];
1369
1370 su_init();
1371
1372 for (i = 1; argv[i]; i++) {
1373 if (strcmp(argv[i], "-v") == 0)
1374 tstflags |= tst_verbatim;
1375 else if (strcmp(argv[i], "-a") == 0)
1376 tstflags |= tst_abort;
1377 else if (strncmp(argv[i], "-l", 2) == 0) {
1378 int level = 3;
1379 char *rest = NULL;
1380
1381 if (argv[i][2])
1382 level = strtol(argv[i] + 2, &rest, 10);
1383 else if (argv[i + 1])
1384 level = strtol(argv[i + 1], &rest, 10), i++;
1385 else
1386 level = 3, rest = "";
1387
1388 if (rest == NULL || *rest)
1389 usage(1);
1390
1391 su_log_set_level(iptsec_log, level);
1392 } else {
1393 usage(1);
1394 }
1395 }
1396
1397 if ((TSTFLAGS & tst_verbatim))
1398 su_log_soft_set_level(iptsec_log, 9);
1399 else
1400 su_log_soft_set_level(iptsec_log, 0);
1401
1402 retval |= test_digest();
1403 retval |= test_digest_client();
1404 retval |= test_auth_client();
1405 retval |= test_module_io();
1406
1407 su_deinit();
1408
1409 return retval;
1410 }
1411