Branch data Line data Source code
1 : : /* simple.c --- Test the simple SASL mechanisms.
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 : : #include <gsasl.h>
30 : :
31 : : #include "utils.h"
32 : :
33 : : #define MAXSTEP 50
34 : : #define CLIENT 1
35 : : #define SERVER 0
36 : : #define UTF8_a "\xC2\xAA"
37 : :
38 : : struct sasltv
39 : : {
40 : : int clientp;
41 : : const char *mech;
42 : : const char *step[MAXSTEP];
43 : : const char *password;
44 : : const char *authzid;
45 : : const char *authid;
46 : : const char *service;
47 : : const char *hostname;
48 : : const char *servicename;
49 : : const char *anonymous;
50 : : const char *passcode;
51 : : const char *suggestpin;
52 : : const char *pin;
53 : : int securidrc;
54 : : };
55 : : static struct sasltv sasltv[] = {
56 : : {CLIENT, "EXTERNAL", {"", NULL}},
57 : : {SERVER, "EXTERNAL", {"", NULL}},
58 : : {CLIENT, "ANONYMOUS", {"", "Zm9vQGJhci5jb20=", NULL, NULL}, NULL, NULL,
59 : : NULL, NULL, NULL, NULL, "foo@bar.com"},
60 : : {SERVER, "ANONYMOUS", {"Zm9vQGJhci5jb20=", NULL, NULL}, NULL, NULL, NULL,
61 : : NULL, NULL, NULL, "foo@bar.com"},
62 : : {CLIENT, "NTLM",
63 : : {"Kw==", "TlRMTVNTUAABAAAAB7IAAAYABgAgAAAAAAAAACYAAABhdXRoaWQ=",
64 : : "TlRMTVNTUAAAAAAAAAAAAAAAAAAAAGFiY2RlZmdoMDEyMzQ1Njc4ODY2NDQwMTIz",
65 : : "TlRMTVNTUAADAAAAGAAYAFgAAAAYABgAcAAAAAAAAABAAAAADAAMAEAAAAAMAAwATAAAA"
66 : : "AAAAACIAAAAAABhYmEAdQB0AGgAaQBkAGEAdQB0AGgAaQBkABeBBp9xJad9eYo3oh1k55"
67 : : "GNFDIui8H8Qz4CfWYVVToBhVzFFbzyzqAZN5Wl59K/Fg==",
68 : : NULL, NULL}, "password", "authzid", "authid"},
69 : : {CLIENT, "PLAIN",
70 : : {"", "YXV0aHppZABhdXRoaWQAcGFzc3dvcmQ=", NULL, NULL}, "password",
71 : : "authzid", "authid"},
72 : : {CLIENT, "PLAIN",
73 : : {"", "YQBhAGE=", NULL, NULL}, "a", "a", "a"},
74 : : {CLIENT, "PLAIN",
75 : : {"", "wqoAwqoAwqo=", NULL, NULL}, UTF8_a, UTF8_a, UTF8_a},
76 : : {SERVER, "PLAIN",
77 : : {"YXV0aHppZABhdXRoaWQAcGFzc3dvcmQ=", NULL, NULL}, "password", "authzid",
78 : : "authid"},
79 : : {SERVER, "PLAIN",
80 : : {"", "", "YXV0aHppZABhdXRoaWQAcGFzc3dvcmQ=", NULL, NULL}, "password",
81 : : "authzid", "authid"},
82 : : {CLIENT, "LOGIN",
83 : : {"VXNlciBOYW1l", "YXV0aGlk", "UGFzc3dvcmQ=", "cGFzc3dvcmQ=", NULL,
84 : : NULL}, "password", NULL, "authid"},
85 : : {CLIENT, "LOGIN",
86 : : {"VXNlciBOYW1l", "YXV0aGlk", "UGFzc3dvcmQ=", "YQ==", NULL, NULL}, "a",
87 : : NULL,
88 : : "authid"},
89 : : {CLIENT, "LOGIN",
90 : : {"VXNlciBOYW1l", "YXV0aGlk", "UGFzc3dvcmQ=", "wqo=", NULL, NULL}, UTF8_a,
91 : : NULL, "authid"},
92 : : {SERVER, "LOGIN",
93 : : {"", "VXNlciBOYW1l", "YXV0aGlk", "UGFzc3dvcmQ=", "cGFzc3dvcmQ=",
94 : : NULL, NULL}, "password", NULL, "authid"},
95 : : {CLIENT, "CRAM-MD5",
96 : : {"PGNiNmQ5YTQ5ZDA3ZjEwY2MubGliZ3Nhc2xAbG9jYWxob3N0Pg==",
97 : : "YXV0aGlkIGZkNjRmMjYxZWYxYjBjYjg0ZmZjNGVmYzgwZDk3NjFj", NULL, NULL},
98 : : "password", "authzid", "authid"},
99 : : {CLIENT, "SECURID",
100 : : {"", "YXV0aHppZABhdXRoaWQANDcxMQA=", NULL, NULL}, NULL, "authzid",
101 : : "authid", NULL, NULL, NULL, NULL, "4711"},
102 : : {CLIENT, "SECURID",
103 : : {"", "YXV0aHppZABhdXRoaWQANDcxMQA=", "cGFzc2NvZGU=",
104 : : "YXV0aHppZABhdXRoaWQANDcxMQA=", NULL, NULL}, NULL, "authzid", "authid",
105 : : NULL, NULL, NULL, NULL, "4711"},
106 : : {CLIENT, "SECURID",
107 : : {"", "YXV0aHppZABhdXRoaWQANDcxMQA=", "cGlu",
108 : : "YXV0aHppZABhdXRoaWQANDcxMQA0MgA=", NULL, NULL}, NULL, "authzid",
109 : : "authid", NULL, NULL, NULL, NULL, "4711", NULL, "42"},
110 : : {CLIENT, "SECURID",
111 : : {"", "YXV0aHppZABhdXRoaWQANDcxMQA=", "cGluMjM=",
112 : : "YXV0aHppZABhdXRoaWQANDcxMQA0MgA=", NULL, NULL}, NULL, "authzid",
113 : : "authid", NULL, NULL, NULL, NULL, "4711", "23", "42"},
114 : : {CLIENT, "SECURID",
115 : : {"", "YXV0aHppZABhdXRoaWQANDcxMQA=", "cGluMjM=",
116 : : "YXV0aHppZABhdXRoaWQANDcxMQA0MgA=", "cGFzc2NvZGU=",
117 : : "YXV0aHppZABhdXRoaWQANDcxMQA=", NULL, NULL}, NULL, "authzid", "authid",
118 : : NULL, NULL, NULL, NULL, "4711", "23", "42"},
119 : : {SERVER, "SECURID",
120 : : {"YXV0aHppZABhdXRoaWQANDcxMQA=", "", NULL, NULL}, NULL, "authzid",
121 : : "authid", NULL, NULL, NULL, NULL, "4711"},
122 : : {SERVER, "SECURID",
123 : : {"YXV0aHppZABhdXRoaWQANDcxMQA=", "", NULL, NULL}, NULL, "authzid",
124 : : "authid", NULL, NULL, NULL, NULL, "4711"},
125 : : #if 0
126 : : {SERVER, "SECURID",
127 : : {"YXV0aHppZABhdXRoaWQANDcxMQA=", "cGlu",
128 : : "YXV0aHppZABhdXRoaWQANDcxMQA0MgA=", "", NULL, NULL}, NULL, "authzid",
129 : : "authid", NULL, NULL, NULL, NULL, "4711", NULL, "42",
130 : : GSASL_SECURID_SERVER_NEED_NEW_PIN},
131 : : #endif
132 : : {SERVER, "SECURID",
133 : : {"YXV0aHppZABhdXRoaWQANDcxMQA=", "cGluMTc=",
134 : : "YXV0aHppZABhdXRoaWQANDcxMQAyMwA=", "", NULL, NULL}, NULL, "authzid",
135 : : "authid", NULL, NULL, NULL, NULL, "4711", "17", "23",
136 : : GSASL_SECURID_SERVER_NEED_NEW_PIN},
137 : : {SERVER, "SECURID",
138 : : {"YXV0aHppZABhdXRoaWQANDcxMQA=", "cGFzc2NvZGU=",
139 : : "YXV0aHppZABhdXRoaWQANDcxMQA=", NULL, NULL}, NULL, "authzid", "authid",
140 : : NULL, NULL, NULL, NULL, "4711", NULL, NULL,
141 : : GSASL_SECURID_SERVER_NEED_ADDITIONAL_PASSCODE}
142 : : };
143 : :
144 : : static int
145 : 55 : cb (Gsasl * ctx, Gsasl_session * sctx, Gsasl_property prop)
146 : : {
147 : 55 : int rc = GSASL_NO_CALLBACK;
148 : 55 : int i = 0, j = 0;
149 : :
150 [ + + ]: 55 : if (gsasl_callback_hook_get (ctx))
151 : 51 : i = *(int *) gsasl_callback_hook_get (ctx);
152 [ + + ]: 55 : if (gsasl_session_hook_get (sctx))
153 : 51 : j = *(int *) gsasl_session_hook_get (sctx);
154 : :
155 [ + - ][ - + ]: 55 : if (j < 0 || j > 5)
156 : 0 : fail ("j out of bounds: %d\n", j);
157 : :
158 [ + + + + : 55 : switch (prop)
- + + - +
+ + + ]
159 : : {
160 : : case GSASL_AUTHID:
161 : 12 : gsasl_property_set (sctx, prop, sasltv[i].authid);
162 : 12 : rc = GSASL_OK;
163 : 12 : break;
164 : :
165 : : case GSASL_AUTHZID:
166 : 9 : gsasl_property_set (sctx, prop, sasltv[i].authzid);
167 : 9 : rc = GSASL_OK;
168 : 9 : break;
169 : :
170 : : case GSASL_PASSWORD:
171 : 10 : gsasl_property_set (sctx, prop, sasltv[i].password);
172 : 10 : rc = GSASL_OK;
173 : 10 : break;
174 : :
175 : : case GSASL_ANONYMOUS_TOKEN:
176 : 1 : gsasl_property_set (sctx, prop, sasltv[i].anonymous);
177 : 1 : rc = GSASL_OK;
178 : 1 : break;
179 : :
180 : : case GSASL_SERVICE:
181 : 0 : rc = GSASL_OK;
182 : 0 : break;
183 : :
184 : : case GSASL_PASSCODE:
185 : 5 : gsasl_property_set (sctx, prop, sasltv[i].passcode);
186 : 5 : rc = GSASL_OK;
187 : 5 : break;
188 : :
189 : : case GSASL_SUGGESTED_PIN:
190 : : case GSASL_PIN:
191 : : {
192 : 3 : const char *suggestion =
193 : : gsasl_property_fast (sctx, GSASL_SUGGESTED_PIN);
194 [ + + ][ + - ]: 3 : if (suggestion && sasltv[i].suggestpin
195 [ - + ]: 2 : && strcmp (suggestion, sasltv[i].suggestpin) != 0)
196 : 0 : return GSASL_AUTHENTICATION_ERROR;
197 : :
198 [ + + ][ + - ]: 3 : if ((suggestion == NULL && sasltv[i].suggestpin != NULL) ||
[ + + ]
199 [ - + ]: 2 : (suggestion != NULL && sasltv[i].suggestpin == NULL))
200 : 0 : return GSASL_AUTHENTICATION_ERROR;
201 : :
202 : 3 : gsasl_property_set (sctx, prop, sasltv[i].pin);
203 : 3 : rc = GSASL_OK;
204 : : }
205 : :
206 : : case GSASL_REALM:
207 : 3 : break;
208 : :
209 : : case GSASL_VALIDATE_EXTERNAL:
210 : 1 : rc = GSASL_OK;
211 : 1 : break;
212 : :
213 : : case GSASL_VALIDATE_ANONYMOUS:
214 [ + - ]: 1 : if (strcmp (sasltv[i].anonymous,
215 : : gsasl_property_fast (sctx, GSASL_ANONYMOUS_TOKEN)) == 0)
216 : 1 : rc = GSASL_OK;
217 : : else
218 : 0 : rc = GSASL_AUTHENTICATION_ERROR;
219 : 1 : break;
220 : :
221 : : case GSASL_VALIDATE_SECURID:
222 : : {
223 : 6 : const char *passcode = gsasl_property_fast (sctx, GSASL_PASSCODE);
224 : 6 : const char *pin = gsasl_property_fast (sctx, GSASL_PIN);
225 : :
226 [ - + ]: 6 : if (strcmp (passcode, sasltv[i].passcode) != 0)
227 : 0 : return GSASL_AUTHENTICATION_ERROR;
228 : :
229 [ + + ]: 6 : if (sasltv[i].securidrc == GSASL_SECURID_SERVER_NEED_NEW_PIN)
230 : : {
231 : 1 : rc = sasltv[i].securidrc;
232 : 1 : sasltv[i].securidrc = GSASL_OK;
233 : :
234 [ + - ]: 1 : if (sasltv[i].suggestpin)
235 : : {
236 : 1 : gsasl_property_set (sctx, GSASL_SUGGESTED_PIN,
237 : : sasltv[i].suggestpin);
238 : : }
239 : : }
240 [ + + ]: 5 : else if (sasltv[i].securidrc ==
241 : : GSASL_SECURID_SERVER_NEED_ADDITIONAL_PASSCODE)
242 : : {
243 : 1 : rc = sasltv[i].securidrc;
244 : 1 : sasltv[i].securidrc = GSASL_OK;
245 : : }
246 : : else
247 : : {
248 : 4 : rc = sasltv[i].securidrc;
249 : :
250 [ + + ][ + - ]: 4 : if (pin && sasltv[i].pin && strcmp (pin, sasltv[i].pin) != 0)
[ - + ]
251 : 0 : return GSASL_AUTHENTICATION_ERROR;
252 : :
253 [ + + ][ + - ]: 4 : if ((pin == NULL && sasltv[i].pin != NULL) ||
[ + + ]
254 [ - + ]: 1 : (pin != NULL && sasltv[i].pin == NULL))
255 : 0 : return GSASL_AUTHENTICATION_ERROR;
256 : : }
257 : : }
258 : 6 : break;
259 : :
260 : : default:
261 : 7 : printf ("Unknown property %d\n", prop);
262 : 7 : break;
263 : : }
264 : :
265 : 55 : return rc;
266 : : }
267 : :
268 : : void
269 : 1 : doit (void)
270 : : {
271 : 1 : Gsasl *ctx = NULL;
272 : 1 : Gsasl_session *sctx = NULL;
273 : 1 : char *out = NULL;
274 : : int i, j;
275 : : int res;
276 : :
277 [ - + ]: 1 : if (!gsasl_check_version (GSASL_VERSION))
278 : 0 : fail ("gsasl_check_version failure");
279 : :
280 : 1 : success ("Header version %s library version %s\n",
281 : : GSASL_VERSION, gsasl_check_version (NULL));
282 : :
283 : 1 : res = gsasl_init (&ctx);
284 [ - + ]: 1 : if (res != GSASL_OK)
285 : : {
286 : 0 : fail ("gsasl_init() failed (%d):\n%s\n", res, gsasl_strerror (res));
287 : 1 : return;
288 : : }
289 : :
290 : 1 : gsasl_callback_set (ctx, cb);
291 : :
292 : 1 : res = gsasl_client_mechlist (ctx, &out);
293 [ - + ]: 1 : if (res != GSASL_OK)
294 : 0 : fail ("gsasl_client_mechlist() failed (%d):\n%s\n",
295 : : res, gsasl_strerror (res));
296 : 1 : success ("client_mechlist: %s\n", out);
297 : 1 : gsasl_free (out);
298 : 1 : out = NULL;
299 : :
300 : 1 : res = gsasl_server_mechlist (ctx, &out);
301 [ - + ]: 1 : if (res != GSASL_OK)
302 : 0 : fail ("gsasl_server_mechlist() failed (%d):\n%s\n",
303 : : res, gsasl_strerror (res));
304 : 1 : success ("server_mechlist: %s\n", out);
305 : 1 : gsasl_free (out);
306 : 1 : out = NULL;
307 : :
308 [ + + ]: 25 : for (i = 0; i < sizeof (sasltv) / sizeof (sasltv[0]); i++)
309 : : {
310 : 24 : gsasl_callback_hook_set (ctx, &i);
311 : :
312 [ + - ]: 24 : if (debug)
313 [ + + ]: 24 : printf ("Entry %d %s mechanism %s:\n",
314 : 24 : i, sasltv[i].clientp ? "client" : "server", sasltv[i].mech);
315 : :
316 [ + + ]: 24 : if (sasltv[i].clientp)
317 : 15 : res = gsasl_client_support_p (ctx, sasltv[i].mech);
318 : : else
319 : 9 : res = gsasl_server_support_p (ctx, sasltv[i].mech);
320 [ + + ]: 24 : if (!res)
321 : 1 : continue;
322 : :
323 [ + + ]: 23 : if (sasltv[i].clientp)
324 : 14 : res = gsasl_client_start (ctx, sasltv[i].mech, &sctx);
325 : : else
326 : 9 : res = gsasl_server_start (ctx, sasltv[i].mech, &sctx);
327 [ - + ]: 23 : if (res != GSASL_OK)
328 : : {
329 [ # # ]: 0 : fail ("SASL %s start for mechanism %s failed (%d):\n%s\n",
330 : 0 : sasltv[i].clientp ? "client" : "server",
331 : : sasltv[i].mech, res, gsasl_strerror (res));
332 : 0 : continue;
333 : : }
334 : :
335 [ + + ]: 45 : for (j = 0; sasltv[i].step[j]; j += 2)
336 : : {
337 : 36 : gsasl_session_hook_set (sctx, &j);
338 : :
339 [ + - ]: 36 : if (debug)
340 [ + - ]: 36 : printf ("Input : %s\n",
341 : 72 : sasltv[i].step[j] ? sasltv[i].step[j] : "");
342 : :
343 : 36 : res = gsasl_step64 (sctx, sasltv[i].step[j], &out);
344 : :
345 [ + - ]: 36 : if (debug)
346 [ + - ]: 36 : printf ("Output: %s\n", out ? out : "(null)");
347 : :
348 [ + + ][ - + ]: 36 : if (res != GSASL_OK && res != GSASL_NEEDS_MORE)
349 : : {
350 : 0 : fail ("gsasl_step64 failed (%d): %s", res,
351 : : gsasl_strerror (res));
352 : 0 : break;
353 : : }
354 : :
355 [ - + ]: 36 : if (strlen (out) !=
356 [ + + ]: 36 : strlen (sasltv[i].step[j + 1] ? sasltv[i].step[j + 1] : ""))
357 : : {
358 [ # # ]: 0 : printf ("Expected: %s\n", sasltv[i].step[j + 1] ?
359 : 0 : sasltv[i].step[j + 1] : "");
360 : : fail
361 : 0 : ("SASL entry %d mechanism %s client step %d length error\n",
362 : : i, sasltv[i].mech, j);
363 : 0 : j = -1;
364 : 0 : break;
365 : : }
366 : :
367 [ + + ][ - + ]: 36 : if (strcmp (out, sasltv[i].step[j + 1] ?
368 : 29 : sasltv[i].step[j + 1] : "") != 0)
369 : : {
370 [ # # ]: 0 : printf ("Expected: %s\n", sasltv[i].step[j + 1] ?
371 : 0 : sasltv[i].step[j + 1] : "");
372 : 0 : fail ("SASL entry %d mechanism %s client step %d data error\n",
373 : : i, sasltv[i].mech, j);
374 : 0 : j = -1;
375 : 0 : break;
376 : : }
377 : :
378 : 36 : gsasl_free (out);
379 : 36 : out = NULL;
380 : :
381 [ + + ][ + + ]: 36 : if (strcmp (sasltv[i].mech, "SECURID") != 0 && res == GSASL_OK)
382 : 14 : break;
383 : : }
384 : :
385 [ + - ][ + - ]: 23 : if (j != (size_t) - 1 && res == GSASL_OK && sasltv[i].step[j + 2])
[ - + ]
386 : 0 : fail ("SASL entry %d mechanism %s step %d code ended prematurely\n",
387 : : i, sasltv[i].mech, j);
388 [ + - ][ - + ]: 23 : else if (j != (size_t) - 1 && res == GSASL_NEEDS_MORE)
389 : 0 : fail ("SASL entry %d mechanism %s step %d table ended prematurely\n",
390 : : i, sasltv[i].mech, j);
391 [ + - ][ - + ]: 23 : else if (j != (size_t) - 1 && res != GSASL_OK)
392 : 0 : fail ("SASL entry %d mechanism %s step %d failed (%d):\n%s\n",
393 : : i, sasltv[i].mech, j, res, gsasl_strerror (res));
394 : : else
395 [ + + ]: 23 : printf ("PASS: simple %s %s %d\n", sasltv[i].mech,
396 : 23 : sasltv[i].clientp ? "client" : "server", i);
397 : :
398 : : {
399 : : size_t outlen;
400 : :
401 : 23 : res = gsasl_encode (sctx, "foo", 3, &out, &outlen);
402 [ - + ]: 23 : if (res != GSASL_OK)
403 : 0 : fail ("gsasl_encode %d: %s\n", res, gsasl_strerror (res));
404 [ - + ][ # # ]: 23 : if (outlen != 3 && memcmp (out, "foo", outlen) != 0)
405 : 0 : fail ("gsasl_encode memcmp: %.*s\n", (int) outlen, out);
406 : 23 : gsasl_free (out);
407 : 23 : out = NULL;
408 : :
409 : 23 : res = gsasl_decode (sctx, "foo", 3, &out, &outlen);
410 [ - + ]: 23 : if (res != GSASL_OK)
411 : 0 : fail ("gsasl_decode %d: %s\n", res, gsasl_strerror (res));
412 [ - + ][ # # ]: 23 : if (outlen != 3 && memcmp (out, "foo", outlen) != 0)
413 : 0 : fail ("gsasl_decode memcmp: %.*s\n", (int) outlen, out);
414 : 23 : gsasl_free (out);
415 : 23 : out = NULL;
416 : : }
417 : :
418 : 23 : gsasl_finish (sctx);
419 : :
420 [ + - ]: 23 : if (debug)
421 : 23 : printf ("\n");
422 : : }
423 : :
424 : 1 : gsasl_done (ctx);
425 : :
426 : : /* Sanity check interfaces. */
427 : 1 : gsasl_finish (NULL);
428 : 1 : gsasl_done (NULL);
429 : : }
|