Fix typo, reported by Thadeu Lima de Souza Cascardo
[gsasl.git] / tests / simple.c
blobc65966ad0b44c0256ce9ba9c748add44bb029278
1 /* simple.c --- Test the simple SASL mechanisms.
2 * Copyright (C) 2002, 2003, 2004, 2005 Simon Josefsson
4 * This file is part of GNU SASL.
6 * GNU SASL 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 2 of the License, or
9 * (at your option) any later version.
11 * GNU SASL 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.
16 * You should have received a copy of the GNU General Public License
17 * along with GNU SASL; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 #ifdef HAVE_CONFIG_H
23 # include "config.h"
24 #endif
26 #include <stdio.h>
27 #include <stdarg.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <gsasl.h>
32 #include "utils.h"
34 #define MAX_LINE_LENGTH BUFSIZ
36 #define MAXSTEP 50
37 #define CLIENT 1
38 #define SERVER 0
39 #define UTF8_a "\xC2\xAA"
41 struct sasltv
43 int clientp;
44 char *mech;
45 char *step[MAXSTEP];
46 char *password;
47 char *authzid;
48 char *authid;
49 char *service;
50 char *hostname;
51 char *servicename;
52 char *anonymous;
53 char *passcode;
54 char *suggestpin;
55 char *pin;
56 int securidrc;
58 static struct sasltv sasltv[] = {
59 {CLIENT, "EXTERNAL", {"", NULL}},
60 {SERVER, "EXTERNAL", {"", NULL}},
61 {CLIENT, "ANONYMOUS", {"", "Zm9vQGJhci5jb20=", NULL, NULL}, NULL, NULL,
62 NULL, NULL, NULL, NULL, "foo@bar.com"},
63 {SERVER, "ANONYMOUS", {"Zm9vQGJhci5jb20=", NULL, NULL}, NULL, NULL, NULL,
64 NULL, NULL, NULL, "foo@bar.com"},
65 {CLIENT, "NTLM",
66 {"Kw==", "TlRMTVNTUAABAAAAB7IAAAYABgAgAAAAAAAAACYAAABhdXRoaWQ=",
67 "TlRMTVNTUAAAAAAAAAAAAAAAAAAAAGFiY2RlZmdoMDEyMzQ1Njc4ODY2NDQwMTIz",
68 "TlRMTVNTUAADAAAAGAAYAFgAAAAYABgAcAAAAAAAAABAAAAADAAMAEAAAAAMAAwATAAAA"
69 "AAAAACIAAAAAABhYmEAdQB0AGgAaQBkAGEAdQB0AGgAaQBkABeBBp9xJad9eYo3oh1k55"
70 "GNFDIui8H8Qz4CfWYVVToBhVzFFbzyzqAZN5Wl59K/Fg==",
71 NULL, NULL}, "password", "authzid", "authid"},
72 {CLIENT, "PLAIN",
73 {"", "YXV0aHppZABhdXRoaWQAcGFzc3dvcmQ=", NULL, NULL}, "password",
74 "authzid", "authid"},
75 {CLIENT, "PLAIN",
76 {"", "YQBhAGE=", NULL, NULL}, "a", "a", "a"},
77 {CLIENT, "PLAIN",
78 {"", "wqoAwqoAwqo=", NULL, NULL}, UTF8_a, UTF8_a, UTF8_a},
79 {SERVER, "PLAIN",
80 {"YXV0aHppZABhdXRoaWQAcGFzc3dvcmQ=", NULL, NULL}, "password", "authzid",
81 "authid"},
82 {SERVER, "PLAIN",
83 {"", "", "YXV0aHppZABhdXRoaWQAcGFzc3dvcmQ=", NULL, NULL}, "password",
84 "authzid", "authid"},
85 {CLIENT, "LOGIN",
86 {"VXNlciBOYW1l", "YXV0aGlk", "UGFzc3dvcmQ=", "cGFzc3dvcmQ=", NULL,
87 NULL}, "password", NULL, "authid"},
88 {CLIENT, "LOGIN",
89 {"VXNlciBOYW1l", "YXV0aGlk", "UGFzc3dvcmQ=", "YQ==", NULL, NULL}, "a",
90 NULL,
91 "authid"},
92 {CLIENT, "LOGIN",
93 {"VXNlciBOYW1l", "YXV0aGlk", "UGFzc3dvcmQ=", "wqo=", NULL, NULL}, UTF8_a,
94 NULL, "authid"},
95 {SERVER, "LOGIN",
96 {"", "VXNlciBOYW1l", "YXV0aGlk", "UGFzc3dvcmQ=", "cGFzc3dvcmQ=",
97 NULL, NULL}, "password", NULL, "authid"},
98 {CLIENT, "CRAM-MD5",
99 {"PGNiNmQ5YTQ5ZDA3ZjEwY2MubGliZ3Nhc2xAbG9jYWxob3N0Pg==",
100 "YXV0aGlkIGZkNjRmMjYxZWYxYjBjYjg0ZmZjNGVmYzgwZDk3NjFj", NULL, NULL},
101 "password", "authzid", "authid"},
102 {CLIENT, "SECURID",
103 {"", "YXV0aHppZABhdXRoaWQANDcxMQA=", NULL, NULL}, NULL, "authzid",
104 "authid", NULL, NULL, NULL, NULL, "4711"},
105 {CLIENT, "SECURID",
106 {"", "YXV0aHppZABhdXRoaWQANDcxMQA=", "cGFzc2NvZGU=",
107 "YXV0aHppZABhdXRoaWQANDcxMQA=", NULL, NULL}, NULL, "authzid", "authid",
108 NULL, NULL, NULL, NULL, "4711"},
109 {CLIENT, "SECURID",
110 {"", "YXV0aHppZABhdXRoaWQANDcxMQA=", "cGlu",
111 "YXV0aHppZABhdXRoaWQANDcxMQA0MgA=", NULL, NULL}, NULL, "authzid",
112 "authid", NULL, NULL, NULL, NULL, "4711", NULL, "42"},
113 {CLIENT, "SECURID",
114 {"", "YXV0aHppZABhdXRoaWQANDcxMQA=", "cGluMjM=",
115 "YXV0aHppZABhdXRoaWQANDcxMQA0MgA=", NULL, NULL}, NULL, "authzid",
116 "authid", NULL, NULL, NULL, NULL, "4711", "23", "42"},
117 {CLIENT, "SECURID",
118 {"", "YXV0aHppZABhdXRoaWQANDcxMQA=", "cGluMjM=",
119 "YXV0aHppZABhdXRoaWQANDcxMQA0MgA=", "cGFzc2NvZGU=",
120 "YXV0aHppZABhdXRoaWQANDcxMQA=", NULL, NULL}, NULL, "authzid", "authid",
121 NULL, NULL, NULL, NULL, "4711", "23", "42"},
122 {SERVER, "SECURID",
123 {"YXV0aHppZABhdXRoaWQANDcxMQA=", "", NULL, NULL}, NULL, "authzid",
124 "authid", NULL, NULL, NULL, NULL, "4711"},
125 {SERVER, "SECURID",
126 {"YXV0aHppZABhdXRoaWQANDcxMQA=", "", NULL, NULL}, NULL, "authzid",
127 "authid", NULL, NULL, NULL, NULL, "4711"},
128 {SERVER, "SECURID",
129 {"YXV0aHppZABhdXRoaWQANDcxMQA=", "cGlu",
130 "YXV0aHppZABhdXRoaWQANDcxMQA0MgA=", "", NULL, NULL}, NULL, "authzid",
131 "authid", NULL, NULL, NULL, NULL, "4711", NULL, "42",
132 GSASL_SECURID_SERVER_NEED_NEW_PIN},
133 {SERVER, "SECURID",
134 {"YXV0aHppZABhdXRoaWQANDcxMQA=", "cGluMTc=",
135 "YXV0aHppZABhdXRoaWQANDcxMQAyMwA=", "", NULL, NULL}, NULL, "authzid",
136 "authid", NULL, NULL, NULL, NULL, "4711", "17", "23",
137 GSASL_SECURID_SERVER_NEED_NEW_PIN},
138 {SERVER, "SECURID",
139 {"YXV0aHppZABhdXRoaWQANDcxMQA=", "cGFzc2NvZGU=",
140 "YXV0aHppZABhdXRoaWQANDcxMQA=", NULL, NULL}, NULL, "authzid", "authid",
141 NULL, NULL, NULL, NULL, "4711", NULL, NULL,
142 GSASL_SECURID_SERVER_NEED_ADDITIONAL_PASSCODE}
145 static int
146 client_callback_authorization_id (Gsasl_session_ctx * xctx,
147 char *out, size_t * outlen)
149 Gsasl_ctx *ctx = gsasl_client_ctx_get (xctx);
150 int i = *(int *) gsasl_application_data_get (ctx);
151 size_t needlen = sasltv[i].authzid ? strlen (sasltv[i].authzid) : 0;
153 if (*outlen < needlen)
154 return GSASL_TOO_SMALL_BUFFER;
156 *outlen = needlen;
157 if (out && sasltv[i].authzid)
158 memcpy (out, sasltv[i].authzid, needlen);
160 return GSASL_OK;
163 static int
164 client_callback_authentication_id (Gsasl_session_ctx * xctx,
165 char *out, size_t * outlen)
167 Gsasl_ctx *ctx = gsasl_client_ctx_get (xctx);
168 int i = *(int *) gsasl_application_data_get (ctx);
169 size_t needlen = strlen (sasltv[i].authid);
171 if (*outlen < needlen)
172 return GSASL_TOO_SMALL_BUFFER;
174 *outlen = needlen;
175 if (out)
176 memcpy (out, sasltv[i].authid, needlen);
178 return GSASL_OK;
181 static int
182 client_callback_password (Gsasl_session_ctx * xctx, char *out,
183 size_t * outlen)
185 Gsasl_ctx *ctx = gsasl_client_ctx_get (xctx);
186 int i = *(int *) gsasl_application_data_get (ctx);
187 size_t needlen = strlen (sasltv[i].password);
189 if (*outlen < needlen)
190 return GSASL_TOO_SMALL_BUFFER;
192 *outlen = needlen;
193 if (out)
194 memcpy (out, sasltv[i].password, needlen);
196 return GSASL_OK;
199 static int
200 server_callback_validate (Gsasl_session_ctx * xctx,
201 const char *authorization_id,
202 const char *authentication_id, const char *password)
204 Gsasl_ctx *ctx = gsasl_server_ctx_get (xctx);
205 int i = *(int *) gsasl_application_data_get (ctx);
207 if (authorization_id && sasltv[i].authzid &&
208 strcmp (authorization_id, sasltv[i].authzid) != 0)
209 return GSASL_AUTHENTICATION_ERROR;
211 if ((authorization_id == NULL && sasltv[i].authzid != NULL) ||
212 (authorization_id != NULL && sasltv[i].authzid == NULL))
213 return GSASL_AUTHENTICATION_ERROR;
215 if (authentication_id && sasltv[i].authid &&
216 strcmp (authentication_id, sasltv[i].authid) != 0)
217 return GSASL_AUTHENTICATION_ERROR;
219 if (strcmp (password, sasltv[i].password) != 0)
220 return GSASL_AUTHENTICATION_ERROR;
222 return GSASL_OK;
225 static int
226 server_callback_retrieve (Gsasl_session_ctx * xctx,
227 const char *authentication_id,
228 const char *authorization_id,
229 const char *realm, char *key, size_t * keylen)
231 Gsasl_ctx *ctx = gsasl_server_ctx_get (xctx);
232 int i = *(int *) gsasl_application_data_get (ctx);
233 size_t needlen = strlen (sasltv[i].password);
235 if (*keylen < needlen)
236 return GSASL_TOO_SMALL_BUFFER;
238 *keylen = strlen (sasltv[i].password);
239 if (key)
240 memcpy (key, sasltv[i].password, needlen);
242 return GSASL_OK;
245 static int
246 client_callback_service (Gsasl_session_ctx * ctx,
247 char *srv,
248 size_t * srvlen,
249 char *host,
250 size_t * hostlen, char *srvname, size_t * srvnamelen)
252 if (srvlen)
253 *srvlen = 0;
254 if (hostlen)
255 *hostlen = 0;
256 if (srvnamelen)
257 *srvnamelen = 0;
259 return GSASL_OK;
262 static int
263 client_callback_anonymous (Gsasl_session_ctx * xctx, char *out,
264 size_t * outlen)
266 Gsasl_ctx *ctx = gsasl_client_ctx_get (xctx);
267 int i = *(int *) gsasl_application_data_get (ctx);
268 size_t needlen = strlen (sasltv[i].anonymous);
270 if (*outlen < needlen)
271 return GSASL_TOO_SMALL_BUFFER;
273 *outlen = needlen;
274 if (out)
275 memcpy (out, sasltv[i].anonymous, strlen (sasltv[i].anonymous));
277 return GSASL_OK;
280 static int
281 server_callback_anonymous (Gsasl_session_ctx * xctx, const char *token)
283 Gsasl_ctx *ctx = gsasl_client_ctx_get (xctx);
284 int i = *(int *) gsasl_application_data_get (ctx);
286 return strcmp (sasltv[i].anonymous, token) == 0 ? GSASL_OK :
287 GSASL_AUTHENTICATION_ERROR;
290 static int
291 server_callback_external (Gsasl_session_ctx * xctx)
293 return GSASL_OK;
296 static int
297 client_callback_passcode (Gsasl_session_ctx * xctx, char *out,
298 size_t * outlen)
300 Gsasl_ctx *ctx = gsasl_client_ctx_get (xctx);
301 int i = *(int *) gsasl_application_data_get (ctx);
302 size_t needlen = strlen (sasltv[i].passcode);
304 if (*outlen < needlen)
305 return GSASL_TOO_SMALL_BUFFER;
307 *outlen = needlen;
308 if (out)
309 memcpy (out, sasltv[i].passcode, needlen);
311 return GSASL_OK;
314 static int
315 client_callback_pin (Gsasl_session_ctx * xctx, char *suggestion,
316 char *out, size_t * outlen)
318 Gsasl_ctx *ctx = gsasl_client_ctx_get (xctx);
319 int i = *(int *) gsasl_application_data_get (ctx);
320 size_t needlen = strlen (sasltv[i].pin);
322 if (suggestion && sasltv[i].suggestpin &&
323 strcmp (suggestion, sasltv[i].suggestpin) != 0)
324 return GSASL_AUTHENTICATION_ERROR;
326 if ((suggestion == NULL && sasltv[i].suggestpin != NULL) ||
327 (suggestion != NULL && sasltv[i].suggestpin == NULL))
328 return GSASL_AUTHENTICATION_ERROR;
330 if (*outlen < needlen)
331 return GSASL_TOO_SMALL_BUFFER;
333 *outlen = needlen;
334 if (out)
335 memcpy (out, sasltv[i].pin, needlen);
337 return GSASL_OK;
340 static int
341 server_callback_securid (Gsasl_session_ctx * xctx,
342 const char *authentication_id,
343 const char *authorization_id,
344 const char *passcode,
345 char *pin, char *suggestpin, size_t * suggestpinlen)
347 Gsasl_ctx *ctx = gsasl_server_ctx_get (xctx);
348 int i = *(int *) gsasl_application_data_get (ctx);
349 int res;
351 if (strcmp (passcode, sasltv[i].passcode) != 0)
352 return GSASL_AUTHENTICATION_ERROR;
354 if (sasltv[i].securidrc == GSASL_SECURID_SERVER_NEED_NEW_PIN)
356 res = sasltv[i].securidrc;
357 sasltv[i].securidrc = GSASL_OK;
359 if (sasltv[i].suggestpin)
361 if (*suggestpinlen)
362 *suggestpinlen = strlen (sasltv[i].suggestpin);
363 if (suggestpin)
364 memcpy (suggestpin, sasltv[i].suggestpin,
365 strlen (sasltv[i].suggestpin));
367 else if (*suggestpinlen)
368 *suggestpinlen = 0;
370 else if (sasltv[i].securidrc ==
371 GSASL_SECURID_SERVER_NEED_ADDITIONAL_PASSCODE)
373 res = sasltv[i].securidrc;
374 sasltv[i].securidrc = GSASL_OK;
376 else
378 res = sasltv[i].securidrc;
380 if (pin && sasltv[i].pin && strcmp (pin, sasltv[i].pin) != 0)
381 return GSASL_AUTHENTICATION_ERROR;
383 if ((pin == NULL && sasltv[i].pin != NULL) ||
384 (pin != NULL && sasltv[i].pin == NULL))
385 return GSASL_AUTHENTICATION_ERROR;
387 if (*suggestpinlen)
388 *suggestpinlen = 0;
391 return res;
394 void
395 doit (void)
397 Gsasl_ctx *ctx = NULL;
398 Gsasl_session_ctx *xctx = NULL;
399 char output[MAX_LINE_LENGTH];
400 size_t outputlen;
401 size_t i, j;
402 int res;
404 res = gsasl_init (&ctx);
405 if (res != GSASL_OK)
407 fail ("gsasl_init() failed (%d):\n%s\n", res, gsasl_strerror (res));
408 return;
411 gsasl_client_callback_authentication_id_set
412 (ctx, client_callback_authentication_id);
413 gsasl_client_callback_authorization_id_set
414 (ctx, client_callback_authorization_id);
415 gsasl_client_callback_password_set (ctx, client_callback_password);
416 gsasl_server_callback_validate_set (ctx, server_callback_validate);
417 gsasl_server_callback_retrieve_set (ctx, server_callback_retrieve);
418 gsasl_client_callback_service_set (ctx, client_callback_service);
419 gsasl_client_callback_anonymous_set (ctx, client_callback_anonymous);
420 gsasl_server_callback_anonymous_set (ctx, server_callback_anonymous);
421 gsasl_server_callback_external_set (ctx, server_callback_external);
422 gsasl_client_callback_passcode_set (ctx, client_callback_passcode);
423 gsasl_client_callback_pin_set (ctx, client_callback_pin);
424 gsasl_server_callback_securid_set (ctx, server_callback_securid);
426 outputlen = sizeof (output);
427 res = gsasl_client_listmech (ctx, output, &outputlen);
428 if (res != GSASL_OK)
429 fail ("gsasl_client_listmech() failed (%d):\n%s\n",
430 res, gsasl_strerror (res));
432 outputlen = sizeof (output);
433 res = gsasl_server_listmech (ctx, output, &outputlen);
434 if (res != GSASL_OK)
435 fail ("gsasl_server_listmech() failed (%d):\n%s\n",
436 res, gsasl_strerror (res));
438 for (i = 0; i < sizeof (sasltv) / sizeof (sasltv[0]); i++)
440 gsasl_application_data_set (ctx, &i);
442 if (debug)
443 printf ("Entry %d %s mechanism %s:\n",
444 i, sasltv[i].clientp ? "client" : "server", sasltv[i].mech);
446 if (sasltv[i].clientp)
447 res = gsasl_client_support_p (ctx, sasltv[i].mech);
448 else
449 res = gsasl_server_support_p (ctx, sasltv[i].mech);
450 if (!res)
451 continue;
453 if (sasltv[i].clientp)
454 res = gsasl_client_start (ctx, sasltv[i].mech, &xctx);
455 else
456 res = gsasl_server_start (ctx, sasltv[i].mech, &xctx);
457 if (res != GSASL_OK)
459 fail ("SASL %s start for mechanism %s failed (%d):\n%s\n",
460 sasltv[i].clientp ? "client" : "server",
461 sasltv[i].mech, res, gsasl_strerror (res));
462 continue;
465 for (j = 0; sasltv[i].step[j]; j += 2)
467 if (sasltv[i].clientp)
468 gsasl_client_application_data_set (xctx, &j);
469 else
470 gsasl_server_application_data_set (xctx, &j);
472 if (debug)
473 printf ("Input : %s\n",
474 sasltv[i].step[j] ? sasltv[i].step[j] : "");
476 output[0] = '\0';
477 outputlen = sizeof (output);
478 if (sasltv[i].clientp)
479 res = gsasl_client_step_base64 (xctx, sasltv[i].step[j],
480 output, outputlen);
481 else
482 res = gsasl_server_step_base64 (xctx, sasltv[i].step[j],
483 output, outputlen);
485 if (debug)
486 printf ("Output: %s\n", output);
488 if (res != GSASL_OK && res != GSASL_NEEDS_MORE)
489 break;
491 if (strlen (output) !=
492 strlen (sasltv[i].step[j + 1] ? sasltv[i].step[j + 1] : ""))
494 printf ("Expected: %s\n", sasltv[i].step[j + 1] ?
495 sasltv[i].step[j + 1] : "");
496 fail
497 ("SASL entry %d mechanism %s client step %d length error\n",
498 i, sasltv[i].mech, j);
499 j = -1;
500 break;
503 if (strcmp (output, sasltv[i].step[j + 1] ?
504 sasltv[i].step[j + 1] : "") != 0)
506 printf ("Expected: %s\n", sasltv[i].step[j + 1] ?
507 sasltv[i].step[j + 1] : "");
508 fail ("SASL entry %d mechanism %s client step %d data error\n",
509 i, sasltv[i].mech, j);
510 j = -1;
511 break;
514 if (strcmp (sasltv[i].mech, "SECURID") != 0 && res == GSASL_OK)
515 break;
518 if ((int) j != -1 && res == GSASL_OK && sasltv[i].step[j + 2])
519 fail ("SASL entry %d mechanism %s step %d code ended prematurely\n",
520 i, sasltv[i].mech, j);
521 else if ((int) j != -1 && res == GSASL_NEEDS_MORE)
522 fail ("SASL entry %d mechanism %s step %d table ended prematurely\n",
523 i, sasltv[i].mech, j, res, gsasl_strerror (res));
524 else if ((int) j != -1 && res != GSASL_OK)
525 fail ("SASL entry %d mechanism %s step %d failed (%d):\n%s\n",
526 i, sasltv[i].mech, j, res, gsasl_strerror (res));
527 else
528 printf ("PASS: simple %s %s %d\n", sasltv[i].mech,
529 sasltv[i].clientp ? "client" : "server", i);
531 if (sasltv[i].clientp)
532 gsasl_client_finish (xctx);
533 else
534 gsasl_server_finish (xctx);
536 if (debug)
537 printf ("\n");
540 gsasl_done (ctx);