Branch data Line data Source code
1 : : /* digest-md5.c --- Test the DIGEST-MD5 mechanism.
2 : : * Copyright (C) 2002-2012 Simon Josefsson
3 : : *
4 : : * This file is part of GNU SASL.
5 : : *
6 : : * This program is free software: you can redistribute it and/or modify
7 : : * it under the terms of the GNU General Public License as published by
8 : : * the Free Software Foundation, either version 3 of the License, or
9 : : * (at your option) any later version.
10 : : *
11 : : * This program is distributed in the hope that it will be useful,
12 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : : * GNU General Public License for more details.
15 : : *
16 : : * You should have received a copy of the GNU General Public License
17 : : * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 : : *
19 : : */
20 : :
21 : : #ifdef HAVE_CONFIG_H
22 : : #include "config.h"
23 : : #endif
24 : :
25 : : #include <stdio.h>
26 : : #include <stdarg.h>
27 : : #include <stdlib.h>
28 : : #include <string.h>
29 : :
30 : : #include "utils.h"
31 : :
32 : : #define PASSWORD "Open, Ses\xC2\xAA""me"
33 : : #define USERNAME "Ali B\xC2\xAA""ba"
34 : : /* "Ali " "\xC2\xAD" "Bab" "\xC2\xAA" */
35 : : /* "Al\xC2\xAA""dd\xC2\xAD""in\xC2\xAE" */
36 : : #define AUTHZID "joe"
37 : : #define SERVICE "imap"
38 : : #define HOSTNAME "hostname"
39 : : #define REALM "realm"
40 : :
41 : : size_t i;
42 : :
43 : : static int
44 : 110 : callback (Gsasl * ctx, Gsasl_session * sctx, Gsasl_property prop)
45 : : {
46 : : static int flip = 0;
47 : : static int flip2 = 0;
48 : 110 : int rc = GSASL_NO_CALLBACK;
49 : :
50 : : /* Get user info from user. */
51 : :
52 [ + + + + : 110 : switch (prop)
+ + + + +
- ]
53 : : {
54 : : case GSASL_PASSWORD:
55 : 20 : gsasl_property_set (sctx, prop, PASSWORD);
56 : 20 : rc = GSASL_OK;
57 : 20 : break;
58 : :
59 : : case GSASL_AUTHID:
60 : 10 : gsasl_property_set (sctx, prop, USERNAME);
61 : 10 : rc = GSASL_OK;
62 : 10 : break;
63 : :
64 : : case GSASL_AUTHZID:
65 [ + + ]: 10 : if (flip)
66 : 5 : gsasl_property_set (sctx, prop, AUTHZID);
67 : : else
68 : 5 : gsasl_property_set (sctx, prop, NULL);
69 : 10 : flip = !flip;
70 : 10 : rc = GSASL_OK;
71 : 10 : break;
72 : :
73 : : case GSASL_SERVICE:
74 : 10 : gsasl_property_set (sctx, prop, SERVICE);
75 : 10 : rc = GSASL_OK;
76 : 10 : break;
77 : :
78 : : case GSASL_REALM:
79 [ + + ]: 20 : if (flip2)
80 : 13 : gsasl_property_set (sctx, prop, REALM);
81 : : else
82 : 7 : gsasl_property_set (sctx, prop, NULL);
83 : 20 : flip2++;
84 [ + + ]: 20 : if (flip2 == 3)
85 : 6 : flip2 = 0;
86 : 20 : rc = GSASL_OK;
87 : 20 : break;
88 : :
89 : : case GSASL_HOSTNAME:
90 : 10 : gsasl_property_set (sctx, prop, HOSTNAME);
91 : 10 : rc = GSASL_OK;
92 : 10 : break;
93 : :
94 : : case GSASL_DIGEST_MD5_HASHED_PASSWORD:
95 : 10 : rc = GSASL_NO_CALLBACK;
96 : 10 : break;
97 : :
98 : : case GSASL_QOPS:
99 : 10 : rc = GSASL_OK;
100 [ + + + + : 10 : switch (i)
+ - ]
101 : : {
102 : : case 0:
103 : 2 : gsasl_property_set (sctx, prop, "qop-auth");
104 : 2 : break;
105 : :
106 : : case 1:
107 : 2 : rc = GSASL_NO_CALLBACK;
108 : 2 : break;
109 : :
110 : : case 2:
111 : 2 : gsasl_property_set (sctx, prop, "qop-int");
112 : 2 : break;
113 : :
114 : : case 3:
115 : 2 : gsasl_property_set (sctx, prop, "qop-auth");
116 : 2 : break;
117 : :
118 : : case 4:
119 : 2 : rc = GSASL_NO_CALLBACK;
120 : 2 : break;
121 : :
122 : : default:
123 : 0 : break;
124 : : }
125 : 10 : break;
126 : :
127 : : case GSASL_QOP:
128 : 10 : rc = GSASL_OK;
129 [ + + + + : 10 : switch (i)
+ - ]
130 : : {
131 : : case 0:
132 : 2 : rc = GSASL_NO_CALLBACK;
133 : 2 : break;
134 : :
135 : : case 1:
136 : 2 : gsasl_property_set (sctx, prop, "qop-auth");
137 : 2 : break;
138 : :
139 : : case 2:
140 : 2 : gsasl_property_set (sctx, prop, "qop-int");
141 : 2 : break;
142 : :
143 : : case 3:
144 : 2 : gsasl_property_set (sctx, prop, "qop-auth");
145 : 2 : break;
146 : :
147 : : case 4:
148 : 2 : gsasl_property_set (sctx, prop, "qop-auth");
149 : 2 : break;
150 : :
151 : : default:
152 : 0 : break;
153 : : }
154 : 10 : break;
155 : :
156 : : default:
157 : 0 : fail ("Unknown callback property %d\n", prop);
158 : 0 : break;
159 : : }
160 : :
161 : 110 : return rc;
162 : : }
163 : :
164 : : void
165 : 1 : doit (void)
166 : : {
167 : 1 : Gsasl *ctx = NULL;
168 : 1 : Gsasl_session *server = NULL, *client = NULL;
169 : : char *s1, *s2;
170 : : size_t s1len, s2len;
171 : : int res;
172 : :
173 : 1 : res = gsasl_init (&ctx);
174 [ - + ]: 1 : if (res != GSASL_OK)
175 : : {
176 : 0 : fail ("gsasl_init() failed (%d):\n%s\n", res, gsasl_strerror (res));
177 : 0 : return;
178 : : }
179 : :
180 [ + - ]: 1 : if (!gsasl_client_support_p (ctx, "DIGEST-MD5")
181 [ - + ]: 1 : || !gsasl_server_support_p (ctx, "DIGEST-MD5"))
182 : : {
183 : 0 : gsasl_done (ctx);
184 : 0 : fail ("No support for DIGEST-MD5.\n");
185 : 0 : exit (77);
186 : : }
187 : :
188 : 1 : gsasl_callback_set (ctx, callback);
189 : :
190 [ + + ]: 6 : for (i = 0; i < 5; i++)
191 : : {
192 : 5 : res = gsasl_server_start (ctx, "DIGEST-MD5", &server);
193 [ - + ]: 5 : if (res != GSASL_OK)
194 : : {
195 : 0 : fail ("gsasl_server_start() failed (%d):\n%s\n",
196 : : res, gsasl_strerror (res));
197 : 0 : return;
198 : : }
199 : 5 : res = gsasl_client_start (ctx, "DIGEST-MD5", &client);
200 [ - + ]: 5 : if (res != GSASL_OK)
201 : : {
202 : 0 : fail ("gsasl_client_start() failed (%d):\n%s\n",
203 : : res, gsasl_strerror (res));
204 : 0 : return;
205 : : }
206 : :
207 : : /* Client sends empty token... */
208 : :
209 : 5 : res = gsasl_step (client, NULL, 0, &s1, &s1len);
210 [ - + ]: 5 : if (res != GSASL_NEEDS_MORE)
211 : : {
212 : 0 : fail ("gsasl_step(1) failed (%d):\n%s\n", res,
213 : : gsasl_strerror (res));
214 : 0 : return;
215 : : }
216 : :
217 [ + - ]: 5 : if (debug)
218 [ - + ]: 5 : printf ("C: %.*s [%c]\n", (int) s1len,
219 : : s1, res == GSASL_OK ? 'O' : 'N');
220 : :
221 : : /* Server starts... */
222 : :
223 : 5 : res = gsasl_step (server, s1, s1len, &s2, &s2len);
224 : 5 : gsasl_free (s1);
225 [ - + ]: 5 : if (res != GSASL_NEEDS_MORE)
226 : : {
227 : 0 : fail ("gsasl_step(2) failed (%d):\n%s\n", res,
228 : : gsasl_strerror (res));
229 : 0 : return;
230 : : }
231 : :
232 [ + - ]: 5 : if (debug)
233 [ - + ]: 5 : printf ("S: %.*s [%c]\n", (int) s2len,
234 : : s2, res == GSASL_OK ? 'O' : 'N');
235 : :
236 : : /* Client responds... */
237 : :
238 : 5 : res = gsasl_step (client, s2, s2len, &s1, &s1len);
239 : 5 : gsasl_free (s2);
240 [ - + ]: 5 : if (res != GSASL_NEEDS_MORE)
241 : : {
242 : 0 : fail ("gsasl_step(3) failed (%d):\n%s\n", res,
243 : : gsasl_strerror (res));
244 : 0 : return;
245 : : }
246 : :
247 [ + - ]: 5 : if (debug)
248 [ - + ]: 5 : printf ("C: %.*s [%c]\n", (int) s1len,
249 : : s1, res == GSASL_OK ? 'O' : 'N');
250 : :
251 : : /* Server finishes... */
252 : :
253 : 5 : res = gsasl_step (server, s1, s1len, &s2, &s2len);
254 : 5 : gsasl_free (s1);
255 [ - + ]: 5 : if (res != GSASL_OK)
256 : : {
257 : 0 : fail ("gsasl_step(4) failed (%d):\n%s\n", res,
258 : : gsasl_strerror (res));
259 : 0 : return;
260 : : }
261 : :
262 [ + - ]: 5 : if (debug)
263 [ + - ]: 5 : printf ("S: %.*s [%c]\n", (int) s2len,
264 : : s2, res == GSASL_OK ? 'O' : 'N');
265 : :
266 : : /* Client finishes. */
267 : :
268 : 5 : res = gsasl_step (client, s2, s2len, &s1, &s1len);
269 : 5 : gsasl_free (s2);
270 [ - + ]: 5 : if (res != GSASL_OK)
271 : : {
272 : 0 : fail ("gsasl_step(5) failed (%d):\n%s\n", res,
273 : : gsasl_strerror (res));
274 : 0 : return;
275 : : }
276 : :
277 [ - + ]: 5 : if (s1len != 0)
278 : : {
279 : 0 : fail ("gsasl_step() failed, additional length=%lu:\n",
280 : : (unsigned long) s1len);
281 : 0 : fail ("%s\n", s1);
282 : 0 : return;
283 : : }
284 : :
285 [ + - ]: 5 : if (debug)
286 [ + - ]: 5 : printf ("C: %.*s [%c]\n", (int) s1len,
287 : : s1, res == GSASL_OK ? 'O' : 'N');
288 : :
289 : : /* Server is done. */
290 : :
291 : 5 : res = gsasl_step (server, s1, s1len, &s2, &s2len);
292 [ - + ]: 5 : if (res != GSASL_MECHANISM_CALLED_TOO_MANY_TIMES)
293 : : {
294 : 0 : fail ("gsasl_step(6) failed (%d):\n%s\n", res,
295 : : gsasl_strerror (res));
296 : 0 : return;
297 : : }
298 : :
299 : : /* Client is done. */
300 : :
301 : 5 : res = gsasl_step (client, s1, s1len, &s2, &s2len);
302 [ - + ]: 5 : if (res != GSASL_MECHANISM_CALLED_TOO_MANY_TIMES)
303 : : {
304 : 0 : fail ("gsasl_step(7) failed (%d):\n%s\n", res,
305 : : gsasl_strerror (res));
306 : 0 : return;
307 : : }
308 : :
309 : 5 : gsasl_free (s1);
310 : :
311 [ + - ]: 5 : if (debug)
312 : 5 : printf ("\n");
313 : :
314 : 5 : gsasl_finish (client);
315 : 5 : gsasl_finish (server);
316 : : }
317 : :
318 [ + + ]: 6 : for (i = 0; i < 5; i++)
319 : : {
320 : 5 : res = gsasl_server_start (ctx, "DIGEST-MD5", &server);
321 [ - + ]: 5 : if (res != GSASL_OK)
322 : : {
323 : 0 : fail ("gsasl_init() failed (%d):\n%s\n", res, gsasl_strerror (res));
324 : 0 : return;
325 : : }
326 : 5 : res = gsasl_client_start (ctx, "DIGEST-MD5", &client);
327 [ - + ]: 5 : if (res != GSASL_OK)
328 : : {
329 : 0 : fail ("gsasl_init() failed (%d):\n%s\n", res, gsasl_strerror (res));
330 : 0 : return;
331 : : }
332 : :
333 : : /* Server begins... */
334 : :
335 : 5 : res = gsasl_step (server, NULL, 0, &s1, &s1len);
336 [ - + ]: 5 : if (res != GSASL_NEEDS_MORE)
337 : : {
338 : 0 : fail ("gsasl_step(8) failed (%d):\n%s\n", res,
339 : : gsasl_strerror (res));
340 : 0 : return;
341 : : }
342 : :
343 [ + - ]: 5 : if (debug)
344 [ - + ]: 5 : printf ("S: %.*s [%c]\n", (int) s1len,
345 : : s1, res == GSASL_OK ? 'O' : 'N');
346 : :
347 : : /* Client respond... */
348 : :
349 : 5 : res = gsasl_step (client, s1, s1len, &s2, &s2len);
350 : 5 : gsasl_free (s1);
351 [ - + ]: 5 : if (res != GSASL_NEEDS_MORE)
352 : : {
353 : 0 : fail ("gsasl_step(9) failed (%d):\n%s\n", res,
354 : : gsasl_strerror (res));
355 : 0 : return;
356 : : }
357 : :
358 [ + - ]: 5 : if (debug)
359 [ - + ]: 5 : printf ("C: %.*s [%c]\n", (int) s2len,
360 : : s2, res == GSASL_OK ? 'O' : 'N');
361 : :
362 : : /* Server finishes... */
363 : :
364 : 5 : res = gsasl_step (server, s2, s2len, &s1, &s1len);
365 : 5 : gsasl_free (s2);
366 [ - + ]: 5 : if (res != GSASL_OK)
367 : : {
368 : 0 : fail ("gsasl_step(10) failed (%d):\n%s\n", res,
369 : : gsasl_strerror (res));
370 : 0 : return;
371 : : }
372 : :
373 [ + - ]: 5 : if (debug)
374 [ + - ]: 5 : printf ("S: %.*s [%c]\n", (int) s1len,
375 : : s1, res == GSASL_OK ? 'O' : 'N');
376 : :
377 : : /* Client finishes... */
378 : :
379 : 5 : res = gsasl_step (client, s1, s1len, &s2, &s2len);
380 : 5 : gsasl_free (s1);
381 [ - + ]: 5 : if (res != GSASL_OK)
382 : : {
383 : 0 : fail ("gsasl_step(11) failed (%d):\n%s\n", res,
384 : : gsasl_strerror (res));
385 : 0 : return;
386 : : }
387 : :
388 [ + - ]: 5 : if (debug)
389 [ + - ]: 5 : printf ("C: %.*s [%c]\n", (int) s2len,
390 : : s2, res == GSASL_OK ? 'O' : 'N');
391 : :
392 : : /* Server is done. */
393 : :
394 : 5 : res = gsasl_step (server, s2, s2len, &s1, &s1len);
395 [ - + ]: 5 : if (res != GSASL_MECHANISM_CALLED_TOO_MANY_TIMES)
396 : : {
397 : 0 : fail ("gsasl_step(12) failed (%d):\n%s\n", res,
398 : : gsasl_strerror (res));
399 : 0 : return;
400 : : }
401 : :
402 : : /* Client is done. */
403 : :
404 : 5 : res = gsasl_step (client, s2, s2len, &s1, &s1len);
405 [ - + ]: 5 : if (res != GSASL_MECHANISM_CALLED_TOO_MANY_TIMES)
406 : : {
407 : 0 : fail ("gsasl_step(13) failed (%d):\n%s\n", res,
408 : : gsasl_strerror (res));
409 : 0 : return;
410 : : }
411 : :
412 : 5 : gsasl_free (s2);
413 : :
414 : : /* Encode data in client. */
415 : :
416 : 5 : res = gsasl_encode (client, "foo", 3, &s1, &s1len);
417 [ - + ]: 5 : if (res != GSASL_OK)
418 : : {
419 : 0 : fail ("gsasl_encode failed (%d):\n%s\n", res, gsasl_strerror (res));
420 : 0 : return;
421 : : }
422 : :
423 [ + - ]: 5 : if (debug)
424 : : {
425 [ + + ][ + - ]: 5 : if (s1len == 3 && memcmp (s1, "foo", 3) == 0)
426 : 4 : printf ("C: %.*s\n", (int) s1len, s1);
427 : : else
428 : : {
429 : : char *out;
430 : : size_t outlen;
431 : :
432 : 1 : res = gsasl_base64_to (s1, s1len, &out, &outlen);
433 [ - + ]: 1 : if (res != GSASL_OK)
434 : : {
435 : 0 : fail ("gsasl_base64_to failed (%d):\n%s\n", res,
436 : : gsasl_strerror (res));
437 : 0 : return;
438 : : }
439 : :
440 : 1 : printf ("C: %.*s\n", (int) outlen, out);
441 : 1 : free (out);
442 : : }
443 : : }
444 : :
445 : : /* Decode data in server. */
446 : :
447 : 5 : res = gsasl_decode (server, s1, s1len, &s2, &s2len);
448 : 5 : free (s1);
449 [ - + ]: 5 : if (res != GSASL_OK)
450 : : {
451 : 0 : fail ("gsasl_decode failed (%d):\n%s\n", res, gsasl_strerror (res));
452 : 0 : return;
453 : : }
454 : :
455 [ + - ]: 5 : if (debug)
456 : 5 : printf ("S: %.*s\n", (int) s2len, s2);
457 : :
458 : 5 : free (s2);
459 : :
460 : : /* Encode data in server. */
461 : :
462 : 5 : res = gsasl_encode (server, "bar", 3, &s1, &s1len);
463 [ - + ]: 5 : if (res != GSASL_OK)
464 : : {
465 : 0 : fail ("gsasl_encode(2) failed (%d):\n%s\n", res,
466 : : gsasl_strerror (res));
467 : 0 : return;
468 : : }
469 : :
470 [ + - ]: 5 : if (debug)
471 : : {
472 [ + + ][ + - ]: 5 : if (s1len == 3 && memcmp (s1, "bar", 3) == 0)
473 : 4 : printf ("S: %.*s\n", (int) s1len, s1);
474 : : else
475 : : {
476 : : char *out;
477 : : size_t outlen;
478 : :
479 : 1 : res = gsasl_base64_to (s1, s1len, &out, &outlen);
480 [ - + ]: 1 : if (res != GSASL_OK)
481 : : {
482 : 0 : fail ("gsasl_base64_to(2) failed (%d):\n%s\n", res,
483 : : gsasl_strerror (res));
484 : 0 : return;
485 : : }
486 : :
487 : 1 : printf ("S: %.*s\n", (int) outlen, out);
488 : 1 : free (out);
489 : : }
490 : : }
491 : :
492 : : /* Decode data in client. */
493 : :
494 : 5 : res = gsasl_decode (client, s1, s1len, &s2, &s2len);
495 : 5 : free (s1);
496 [ - + ]: 5 : if (res != GSASL_OK)
497 : : {
498 : 0 : fail ("gsasl_decode failed (%d):\n%s\n", res, gsasl_strerror (res));
499 : 0 : return;
500 : : }
501 : :
502 [ + - ]: 5 : if (debug)
503 : 5 : printf ("C: %.*s\n", (int) s2len, s2);
504 : :
505 : 5 : free (s2);
506 : :
507 [ + - ]: 5 : if (debug)
508 : 5 : printf ("\n");
509 : :
510 : 5 : gsasl_finish (client);
511 : 5 : gsasl_finish (server);
512 : : }
513 : :
514 : 1 : gsasl_done (ctx);
515 : : }
|