Branch data Line data Source code
1 : : /* scramplus.c --- Test the SCRAM-SHA-1-PLUS 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 : 191 : callback (Gsasl * ctx, Gsasl_session * sctx, Gsasl_property prop)
51 : : {
52 : 191 : int rc = GSASL_NO_CALLBACK;
53 : :
54 : : /* Get user info from user. */
55 : :
56 [ + + + + : 191 : switch (prop)
+ + + - ]
57 : : {
58 : : case GSASL_PASSWORD:
59 : 37 : gsasl_property_set (sctx, prop, PASSWORD);
60 : 37 : rc = GSASL_OK;
61 : 37 : 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 : gsasl_property_set (sctx, prop, "Zm5vcmQ=");
112 : 44 : rc = GSASL_OK;
113 : 44 : break;
114 : :
115 : : default:
116 : 0 : fail ("Unknown callback property %d\n", prop);
117 : 0 : break;
118 : : }
119 : :
120 : 191 : return rc;
121 : : }
122 : :
123 : : void
124 : 1 : doit (void)
125 : : {
126 : 1 : Gsasl *ctx = NULL;
127 : 1 : Gsasl_session *server = NULL, *client = NULL;
128 : : char *s1, *s2;
129 : : size_t s1len, s2len;
130 : : int res;
131 : :
132 : 1 : res = gsasl_init (&ctx);
133 [ - + ]: 1 : if (res != GSASL_OK)
134 : : {
135 : 0 : fail ("gsasl_init() failed (%d):\n%s\n", res, gsasl_strerror (res));
136 : 0 : return;
137 : : }
138 : :
139 [ + - ]: 1 : if (!gsasl_client_support_p (ctx, "SCRAM-SHA-1-PLUS")
140 [ - + ]: 1 : || !gsasl_server_support_p (ctx, "SCRAM-SHA-1-PLUS"))
141 : : {
142 : 0 : gsasl_done (ctx);
143 : 0 : fail ("No support for SCRAM-SHA-1-PLUS.\n");
144 : 0 : exit (77);
145 : : }
146 : :
147 : 1 : gsasl_callback_set (ctx, callback);
148 : :
149 [ + + ]: 23 : for (i = 0; i <= 21; i++)
150 : : {
151 : 22 : bool server_first = (i % 2) == 0;
152 : :
153 [ + - ]: 22 : if (debug)
154 : 22 : printf ("Iteration %d ...\n", i);
155 : :
156 : 22 : res = gsasl_server_start (ctx, "SCRAM-SHA-1-PLUS", &server);
157 [ - + ]: 22 : if (res != GSASL_OK)
158 : : {
159 : 0 : fail ("gsasl_server_start() failed (%d):\n%s\n",
160 : : res, gsasl_strerror (res));
161 : 0 : return;
162 : : }
163 : 22 : res = gsasl_client_start (ctx, "SCRAM-SHA-1-PLUS", &client);
164 [ - + ]: 22 : if (res != GSASL_OK)
165 : : {
166 : 0 : fail ("gsasl_client_start() failed (%d):\n%s\n",
167 : : res, gsasl_strerror (res));
168 : 0 : return;
169 : : }
170 : :
171 [ + + ]: 22 : if (server_first)
172 : : {
173 : 11 : res = gsasl_step (server, NULL, 0, &s1, &s1len);
174 [ - + ]: 11 : if (res != GSASL_NEEDS_MORE)
175 : : {
176 : 0 : fail ("gsasl_step[%d](0) failed (%d):\n%s\n", i, res,
177 : : gsasl_strerror (res));
178 : 0 : return;
179 : : }
180 : :
181 [ - + ]: 11 : if (s1len != 0)
182 : 0 : fail ("dummy initial server step produced output?!\n");
183 : :
184 [ + - ]: 11 : if (debug)
185 [ - + ]: 11 : printf ("S: %.*s [%c]\n", (int) s1len,
186 : : s1, res == GSASL_OK ? 'O' : 'N');
187 : : }
188 : : else
189 : : {
190 : 11 : s1 = NULL;
191 : 11 : s1len = 0;
192 : : }
193 : :
194 : : /* Client first... */
195 : :
196 : 22 : res = gsasl_step (client, s1, s1len, &s1, &s1len);
197 [ - + ]: 22 : if (res != GSASL_NEEDS_MORE)
198 : : {
199 : 0 : fail ("gsasl_step[%d](1) failed (%d):\n%s\n", i, res,
200 : : gsasl_strerror (res));
201 : 0 : return;
202 : : }
203 : :
204 [ + - ]: 22 : if (debug)
205 [ - + ]: 22 : printf ("C: %.*s [%c]\n", (int) s1len,
206 : : s1, res == GSASL_OK ? 'O' : 'N');
207 : :
208 : : /* Server first... */
209 : :
210 : 22 : res = gsasl_step (server, s1, s1len, &s2, &s2len);
211 : 22 : gsasl_free (s1);
212 [ - + ]: 22 : if (res != GSASL_NEEDS_MORE)
213 : : {
214 : 0 : fail ("gsasl_step[%d](2) failed (%d):\n%s\n", i, res,
215 : : gsasl_strerror (res));
216 : 0 : return;
217 : : }
218 : :
219 [ + - ]: 22 : if (debug)
220 [ - + ]: 22 : printf ("S: %.*s [%c]\n", (int) s2len,
221 : : s2, res == GSASL_OK ? 'O' : 'N');
222 : :
223 : : /* Client final... */
224 : :
225 : 22 : res = gsasl_step (client, s2, s2len, &s1, &s1len);
226 : 22 : gsasl_free (s2);
227 [ - + ]: 22 : if (res != GSASL_NEEDS_MORE)
228 : : {
229 : 0 : fail ("gsasl_step[%d](3) failed (%d):\n%s\n", i, res,
230 : : gsasl_strerror (res));
231 : 0 : return;
232 : : }
233 : :
234 : : /* Shorten length of cbdata. */
235 [ + + ]: 22 : if (i == 17)
236 : 1 : s1[41] = '=';
237 : :
238 : : /* Increase length of cbdata. */
239 [ + + ]: 22 : if (i == 18)
240 : : {
241 : 1 : s1[28] = 'B';
242 : 1 : s1[29] = 'C';
243 : : }
244 : :
245 : : /* Modify cbdata. */
246 [ + + ]: 22 : if (i == 19)
247 : 1 : s1[30] = 'B';
248 : :
249 [ + - ]: 22 : if (debug)
250 [ - + ]: 22 : printf ("C: %.*s [%c]\n", (int) s1len,
251 : : s1, res == GSASL_OK ? 'O' : 'N');
252 : :
253 : : /* Server final... */
254 : :
255 : 22 : res = gsasl_step (server, s1, s1len, &s2, &s2len);
256 : 22 : gsasl_free (s1);
257 [ + + ][ + + ]: 22 : if (i >= 17 && i <= 19)
258 : : {
259 [ + - ]: 3 : if (res == GSASL_AUTHENTICATION_ERROR)
260 : : {
261 [ + - ]: 3 : if (debug)
262 : 3 : success ("Authentication failed expectedly\n");
263 : 3 : goto done;
264 : : }
265 : : else
266 : 0 : res = GSASL_AUTHENTICATION_ERROR;
267 : : }
268 [ - + ]: 19 : if (res != GSASL_OK)
269 : : {
270 : 0 : fail ("gsasl_step[%d](4) failed (%d):\n%s\n", i, res,
271 : : gsasl_strerror (res));
272 : 0 : return;
273 : : }
274 : :
275 [ + - ]: 19 : if (debug)
276 [ + - ]: 19 : printf ("S: %.*s [%c]\n", (int) s2len,
277 : : s2, res == GSASL_OK ? 'O' : 'N');
278 : :
279 : : /* Let client parse server final... */
280 : :
281 : 19 : res = gsasl_step (client, s2, s2len, &s1, &s1len);
282 : 19 : gsasl_free (s2);
283 [ - + ]: 19 : if (res != GSASL_OK)
284 : : {
285 : 0 : fail ("gsasl_step[%d](5) failed (%d):\n%s\n", i, res,
286 : : gsasl_strerror (res));
287 : 0 : return;
288 : : }
289 : :
290 [ - + ]: 19 : if (s1len != 0)
291 : 0 : fail ("dummy final client step produced output?!\n");
292 : :
293 : : {
294 : 19 : const char *p = gsasl_property_fast (server, GSASL_AUTHID);
295 [ + - ][ - + ]: 19 : if (p && strcmp (p, AUTHID[i % N_AUTHID]) != 0)
296 : 0 : fail ("Bad authid? %s != %s\n", p, AUTHID[i % N_AUTHID]);
297 [ + + ][ - + ]: 19 : if (i & 0x01 && !p)
298 : 0 : fail ("Expected authid? %d/%s\n", i, AUTHID[i % N_AUTHID]);
299 : : }
300 : :
301 : : {
302 : 19 : const char *p = gsasl_property_fast (server, GSASL_AUTHZID);
303 [ + + ][ - + ]: 19 : if (p && strcmp (p, AUTHZID[i % N_AUTHZID]) != 0)
304 : 0 : fail ("Bad authzid? %s != %s\n", p, AUTHZID[i % N_AUTHZID]);
305 [ + + ][ - + ]: 19 : if (i & 0x01 && !p)
306 : 0 : fail ("Expected authzid? %d/%s\n", i, AUTHZID[i % N_AUTHZID]);
307 : : }
308 : :
309 : : done:
310 [ + - ]: 22 : if (debug)
311 : 22 : printf ("\n");
312 : :
313 : 22 : gsasl_finish (client);
314 : 22 : gsasl_finish (server);
315 : : }
316 : :
317 : 1 : gsasl_done (ctx);
318 : : }
|