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