Branch data Line data Source code
1 : : /* scram.c --- Test the SCRAM mechanism.
2 : : * Copyright (C) 2009-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 : : #include <stdbool.h>
30 : :
31 : : #include "utils.h"
32 : :
33 : : #define PASSWORD "Open, Sesame"
34 : :
35 : : #define N_AUTHID 4
36 : : static const char *AUTHID[N_AUTHID] = {
37 : : "Ali Baba", "BAB,ABA", ",=,=", "="
38 : : /* "Ali " "\xC2\xAD" "Bab" "\xC2\xAA" */
39 : : /* "Al\xC2\xAA""dd\xC2\xAD""in\xC2\xAE" */
40 : : };
41 : :
42 : : #define N_AUTHZID 4
43 : : static const char *AUTHZID[N_AUTHZID] = {
44 : : "jas", "BAB,ABA", ",=,=", "="
45 : : };
46 : :
47 : : int i;
48 : :
49 : : static int
50 : 193 : callback (Gsasl * ctx, Gsasl_session * sctx, Gsasl_property prop)
51 : : {
52 : 193 : int rc = GSASL_NO_CALLBACK;
53 : :
54 : : /* Get user info from user. */
55 : :
56 [ + + + + : 193 : switch (prop)
+ + + - ]
57 : : {
58 : : case GSASL_PASSWORD:
59 : 39 : gsasl_property_set (sctx, prop, PASSWORD);
60 : 39 : rc = GSASL_OK;
61 : 39 : break;
62 : :
63 : : case GSASL_AUTHID:
64 : 22 : gsasl_property_set (sctx, prop, AUTHID[i % N_AUTHID]);
65 : 22 : rc = GSASL_OK;
66 : 22 : break;
67 : :
68 : : case GSASL_AUTHZID:
69 [ + + ]: 22 : if (i & 0x01)
70 : : {
71 : 11 : gsasl_property_set (sctx, prop, AUTHZID[i % N_AUTHZID]);
72 : 11 : rc = GSASL_OK;
73 : : }
74 : 22 : break;
75 : :
76 : : case GSASL_SCRAM_ITER:
77 [ - + ]: 22 : if (strcmp (gsasl_property_fast (sctx, GSASL_AUTHID),
78 : 22 : AUTHID[i % N_AUTHID]) != 0)
79 : 0 : fail ("Username mismatch: %s",
80 : : gsasl_property_fast (sctx, GSASL_AUTHID));
81 [ + + ]: 22 : if (i & 0x02)
82 : : {
83 : 10 : gsasl_property_set (sctx, prop, "1234");
84 : 10 : rc = GSASL_OK;
85 : : }
86 : 22 : break;
87 : :
88 : : case GSASL_SCRAM_SALT:
89 [ + + ]: 22 : if (i & 0x04)
90 : : {
91 : 10 : gsasl_property_set (sctx, prop, "c2FsdA==");
92 : 10 : rc = GSASL_OK;
93 : : }
94 : 22 : break;
95 : :
96 : : case GSASL_SCRAM_SALTED_PASSWORD:
97 [ + + ][ + + ]: 22 : if (i & 0x04 && i & 0x08) /* Only works with fixed salt. */
98 : : {
99 : 4 : const char *str[] = {
100 : : "06bfd2d70a0fa425c20473722a93700df39f3cbd",
101 : : "f1e6c0e5a207367176ac42c7799b67ae3e097d7e",
102 : : };
103 : : /* >>1 to mask out authzid. */
104 : 4 : size_t pos = (i & ~0x04 & ~0x08) >> 1;
105 : 4 : gsasl_property_set (sctx, prop, str[pos]);
106 : 4 : rc = GSASL_OK;
107 : : }
108 : 22 : break;
109 : :
110 : : case GSASL_CB_TLS_UNIQUE:
111 : 44 : break;
112 : :
113 : : default:
114 : 0 : fail ("Unknown callback property %d\n", prop);
115 : 0 : break;
116 : : }
117 : :
118 : 193 : return rc;
119 : : }
120 : :
121 : : void
122 : 1 : doit (void)
123 : : {
124 : 1 : Gsasl *ctx = NULL;
125 : 1 : Gsasl_session *server = NULL, *client = NULL;
126 : : char *s1, *s2;
127 : : size_t s1len, s2len;
128 : : int res;
129 : :
130 : 1 : res = gsasl_init (&ctx);
131 [ - + ]: 1 : if (res != GSASL_OK)
132 : : {
133 : 0 : fail ("gsasl_init() failed (%d):\n%s\n", res, gsasl_strerror (res));
134 : 0 : return;
135 : : }
136 : :
137 [ + - ]: 1 : if (!gsasl_client_support_p (ctx, "SCRAM-SHA-1")
138 [ - + ]: 1 : || !gsasl_server_support_p (ctx, "SCRAM-SHA-1"))
139 : : {
140 : 0 : gsasl_done (ctx);
141 : 0 : fail ("No support for SCRAM-SHA-1.\n");
142 : 0 : exit (77);
143 : : }
144 : :
145 : 1 : gsasl_callback_set (ctx, callback);
146 : :
147 [ + + ]: 23 : for (i = 0; i <= 21; i++)
148 : : {
149 : 22 : bool server_first = (i % 2) == 0;
150 : :
151 [ + - ]: 22 : if (debug)
152 : 22 : printf ("Iteration %d ...\n", i);
153 : :
154 : 22 : res = gsasl_server_start (ctx, "SCRAM-SHA-1", &server);
155 [ - + ]: 22 : if (res != GSASL_OK)
156 : : {
157 : 0 : fail ("gsasl_server_start() failed (%d):\n%s\n",
158 : : res, gsasl_strerror (res));
159 : 0 : return;
160 : : }
161 : 22 : res = gsasl_client_start (ctx, "SCRAM-SHA-1", &client);
162 [ - + ]: 22 : if (res != GSASL_OK)
163 : : {
164 : 0 : fail ("gsasl_client_start() failed (%d):\n%s\n",
165 : : res, gsasl_strerror (res));
166 : 0 : return;
167 : : }
168 : :
169 [ + + ]: 22 : if (server_first)
170 : : {
171 : 11 : res = gsasl_step (server, NULL, 0, &s1, &s1len);
172 [ - + ]: 11 : if (res != GSASL_NEEDS_MORE)
173 : : {
174 : 0 : fail ("gsasl_step[%d](0) failed (%d):\n%s\n", i, res,
175 : : gsasl_strerror (res));
176 : 0 : return;
177 : : }
178 : :
179 [ - + ]: 11 : if (s1len != 0)
180 : 0 : fail ("dummy initial server step produced output?!\n");
181 : :
182 [ + - ]: 11 : if (debug)
183 [ - + ]: 11 : printf ("S: %.*s [%c]\n", (int) s1len,
184 : : s1, res == GSASL_OK ? 'O' : 'N');
185 : : }
186 : : else
187 : : {
188 : 11 : s1 = NULL;
189 : 11 : s1len = 0;
190 : : }
191 : :
192 : : /* Client first... */
193 : :
194 : 22 : res = gsasl_step (client, s1, s1len, &s1, &s1len);
195 [ - + ]: 22 : if (res != GSASL_NEEDS_MORE)
196 : : {
197 : 0 : fail ("gsasl_step[%d](1) failed (%d):\n%s\n", i, res,
198 : : gsasl_strerror (res));
199 : 0 : return;
200 : : }
201 : :
202 [ + + ][ + + ]: 22 : if (i == 16 || i == 17)
203 : 2 : s1[0] = 'y';
204 : :
205 [ + + ]: 22 : if (i == 18)
206 : : {
207 : : char *s;
208 : : int l;
209 : :
210 : 1 : l = asprintf (&s, "%s,a=b", s1);
211 [ - + ]: 1 : if (l < 0)
212 : : {
213 : 0 : fail ("malloc");
214 : 0 : return;
215 : : }
216 : 1 : gsasl_free (s1);
217 : 1 : s1 = s;
218 : 1 : s1len = strlen (s);
219 : : }
220 : :
221 [ + + ]: 22 : if (i == 20)
222 : : {
223 : : char *s;
224 : : int l;
225 : :
226 : 1 : l = asprintf (&s, "%s,a=b,b=c,c=d", s1);
227 [ - + ]: 1 : if (l < 0)
228 : : {
229 : 0 : fail ("malloc");
230 : 0 : return;
231 : : }
232 : 1 : gsasl_free (s1);
233 : 1 : s1 = s;
234 : 1 : s1len = strlen (s);
235 : : }
236 : :
237 [ + - ]: 22 : if (debug)
238 [ - + ]: 22 : printf ("C: %.*s [%c]\n", (int) s1len,
239 : : s1, res == GSASL_OK ? 'O' : 'N');
240 : :
241 : : /* Server first... */
242 : :
243 : 22 : res = gsasl_step (server, s1, s1len, &s2, &s2len);
244 : 22 : gsasl_free (s1);
245 [ - + ]: 22 : if (res != GSASL_NEEDS_MORE)
246 : : {
247 : 0 : fail ("gsasl_step[%d](2) failed (%d):\n%s\n", i, res,
248 : : gsasl_strerror (res));
249 : 0 : return;
250 : : }
251 : :
252 [ + - ]: 22 : if (debug)
253 [ - + ]: 22 : printf ("S: %.*s [%c]\n", (int) s2len,
254 : : s2, res == GSASL_OK ? 'O' : 'N');
255 : :
256 : : /* Client final... */
257 : :
258 : 22 : res = gsasl_step (client, s2, s2len, &s1, &s1len);
259 : 22 : gsasl_free (s2);
260 [ - + ]: 22 : if (res != GSASL_NEEDS_MORE)
261 : : {
262 : 0 : fail ("gsasl_step[%d](3) failed (%d):\n%s\n", i, res,
263 : : gsasl_strerror (res));
264 : 0 : return;
265 : : }
266 : :
267 [ + + ]: 22 : if (i == 17)
268 : 1 : memcpy (s1 + 2, "eS", 2);
269 : :
270 [ + + ][ + - ]: 22 : if (i == 19 && s1len > 31)
271 : : {
272 : : char *s;
273 : : int l;
274 : :
275 : 1 : l = asprintf (&s, "%.*s,a=b,%s", (int) (s1len - 31),
276 : 1 : s1, s1 + s1len - 31 + 1);
277 [ - + ]: 1 : if (l < 0)
278 : : {
279 : 0 : fail ("malloc");
280 : 0 : return;
281 : : }
282 : 1 : gsasl_free (s1);
283 : 1 : s1 = s;
284 : 1 : s1len = strlen (s);
285 : : }
286 : :
287 [ + + ][ + - ]: 22 : if (i == 21 && s1len > 31)
288 : : {
289 : : char *s;
290 : : int l;
291 : :
292 : 1 : l = asprintf (&s, "%.*s,a=b,b=c,c=d,%s", (int) (s1len - 31),
293 : 1 : s1, s1 + s1len - 31 + 1);
294 [ - + ]: 1 : if (l < 0)
295 : : {
296 : 0 : fail ("malloc");
297 : 0 : return;
298 : : }
299 : 1 : gsasl_free (s1);
300 : 1 : s1 = s;
301 : 1 : s1len = strlen (s);
302 : : }
303 : :
304 [ + - ]: 22 : if (debug)
305 [ - + ]: 22 : printf ("C: %.*s [%c]\n", (int) s1len,
306 : : s1, res == GSASL_OK ? 'O' : 'N');
307 : :
308 : : /* Server final... */
309 : :
310 : 22 : res = gsasl_step (server, s1, s1len, &s2, &s2len);
311 : 22 : gsasl_free (s1);
312 [ + + ][ + - ]: 22 : if (i >= 16 && i <= 21)
313 : : {
314 [ + - ]: 6 : if (res == GSASL_AUTHENTICATION_ERROR)
315 : : {
316 [ + - ]: 6 : if (debug)
317 : 6 : success ("Authentication failed expectedly\n");
318 : 6 : goto done;
319 : : }
320 : : else
321 : 0 : res = GSASL_AUTHENTICATION_ERROR;
322 : : }
323 [ - + ]: 16 : if (res != GSASL_OK)
324 : : {
325 : 0 : fail ("gsasl_step[%d](4) failed (%d):\n%s\n", i, res,
326 : : gsasl_strerror (res));
327 : 0 : return;
328 : : }
329 : :
330 [ + - ]: 16 : if (debug)
331 [ + - ]: 16 : printf ("S: %.*s [%c]\n", (int) s2len,
332 : : s2, res == GSASL_OK ? 'O' : 'N');
333 : :
334 : : /* Let client parse server final... */
335 : :
336 : 16 : res = gsasl_step (client, s2, s2len, &s1, &s1len);
337 : 16 : gsasl_free (s2);
338 [ - + ]: 16 : if (res != GSASL_OK)
339 : : {
340 : 0 : fail ("gsasl_step[%d](5) failed (%d):\n%s\n", i, res,
341 : : gsasl_strerror (res));
342 : 0 : return;
343 : : }
344 : :
345 [ - + ]: 16 : if (s1len != 0)
346 : 0 : fail ("dummy final client step produced output?!\n");
347 : :
348 : : {
349 : 16 : const char *p = gsasl_property_fast (server, GSASL_AUTHID);
350 [ + - ][ - + ]: 16 : if (p && strcmp (p, AUTHID[i % N_AUTHID]) != 0)
351 : 0 : fail ("Bad authid? %s != %s\n", p, AUTHID[i % N_AUTHID]);
352 [ + + ][ - + ]: 16 : if (i & 0x01 && !p)
353 : 0 : fail ("Expected authid? %d/%s\n", i, AUTHID[i % N_AUTHID]);
354 : : }
355 : :
356 : : {
357 : 16 : const char *p = gsasl_property_fast (server, GSASL_AUTHZID);
358 [ + + ][ - + ]: 16 : if (p && strcmp (p, AUTHZID[i % N_AUTHZID]) != 0)
359 : 0 : fail ("Bad authzid? %s != %s\n", p, AUTHZID[i % N_AUTHZID]);
360 [ + + ][ - + ]: 16 : if (i & 0x01 && !p)
361 : 0 : fail ("Expected authzid? %d/%s\n", i, AUTHZID[i % N_AUTHZID]);
362 : : }
363 : :
364 : : done:
365 [ + - ]: 22 : if (debug)
366 : 22 : printf ("\n");
367 : :
368 : 22 : gsasl_finish (client);
369 : 22 : gsasl_finish (server);
370 : : }
371 : :
372 : 1 : gsasl_done (ctx);
373 : : }
|