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.
34 #define MAX_LINE_LENGTH BUFSIZ
39 #define UTF8_a "\xC2\xAA"
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"},
66 {"Kw==", "TlRMTVNTUAABAAAAB7IAAAYABgAgAAAAAAAAACYAAABhdXRoaWQ=",
67 "TlRMTVNTUAAAAAAAAAAAAAAAAAAAAGFiY2RlZmdoMDEyMzQ1Njc4ODY2NDQwMTIz",
68 "TlRMTVNTUAADAAAAGAAYAFgAAAAYABgAcAAAAAAAAABAAAAADAAMAEAAAAAMAAwATAAAA"
69 "AAAAACIAAAAAABhYmEAdQB0AGgAaQBkAGEAdQB0AGgAaQBkABeBBp9xJad9eYo3oh1k55"
70 "GNFDIui8H8Qz4CfWYVVToBhVzFFbzyzqAZN5Wl59K/Fg==",
71 NULL
, NULL
}, "password", "authzid", "authid"},
73 {"", "YXV0aHppZABhdXRoaWQAcGFzc3dvcmQ=", NULL
, NULL
}, "password",
76 {"", "YQBhAGE=", NULL
, NULL
}, "a", "a", "a"},
78 {"", "wqoAwqoAwqo=", NULL
, NULL
}, UTF8_a
, UTF8_a
, UTF8_a
},
80 {"YXV0aHppZABhdXRoaWQAcGFzc3dvcmQ=", NULL
, NULL
}, "password", "authzid",
83 {"", "", "YXV0aHppZABhdXRoaWQAcGFzc3dvcmQ=", NULL
, NULL
}, "password",
86 {"VXNlciBOYW1l", "YXV0aGlk", "UGFzc3dvcmQ=", "cGFzc3dvcmQ=", NULL
,
87 NULL
}, "password", NULL
, "authid"},
89 {"VXNlciBOYW1l", "YXV0aGlk", "UGFzc3dvcmQ=", "YQ==", NULL
, NULL
}, "a",
93 {"VXNlciBOYW1l", "YXV0aGlk", "UGFzc3dvcmQ=", "wqo=", NULL
, NULL
}, UTF8_a
,
96 {"", "VXNlciBOYW1l", "YXV0aGlk", "UGFzc3dvcmQ=", "cGFzc3dvcmQ=",
97 NULL
, NULL
}, "password", NULL
, "authid"},
99 {"PGNiNmQ5YTQ5ZDA3ZjEwY2MubGliZ3Nhc2xAbG9jYWxob3N0Pg==",
100 "YXV0aGlkIGZkNjRmMjYxZWYxYjBjYjg0ZmZjNGVmYzgwZDk3NjFj", NULL
, NULL
},
101 "password", "authzid", "authid"},
103 {"", "YXV0aHppZABhdXRoaWQANDcxMQA=", NULL
, NULL
}, NULL
, "authzid",
104 "authid", NULL
, NULL
, NULL
, NULL
, "4711"},
106 {"", "YXV0aHppZABhdXRoaWQANDcxMQA=", "cGFzc2NvZGU=",
107 "YXV0aHppZABhdXRoaWQANDcxMQA=", NULL
, NULL
}, NULL
, "authzid", "authid",
108 NULL
, NULL
, NULL
, NULL
, "4711"},
110 {"", "YXV0aHppZABhdXRoaWQANDcxMQA=", "cGlu",
111 "YXV0aHppZABhdXRoaWQANDcxMQA0MgA=", NULL
, NULL
}, NULL
, "authzid",
112 "authid", NULL
, NULL
, NULL
, NULL
, "4711", NULL
, "42"},
114 {"", "YXV0aHppZABhdXRoaWQANDcxMQA=", "cGluMjM=",
115 "YXV0aHppZABhdXRoaWQANDcxMQA0MgA=", NULL
, NULL
}, NULL
, "authzid",
116 "authid", NULL
, NULL
, NULL
, NULL
, "4711", "23", "42"},
118 {"", "YXV0aHppZABhdXRoaWQANDcxMQA=", "cGluMjM=",
119 "YXV0aHppZABhdXRoaWQANDcxMQA0MgA=", "cGFzc2NvZGU=",
120 "YXV0aHppZABhdXRoaWQANDcxMQA=", NULL
, NULL
}, NULL
, "authzid", "authid",
121 NULL
, NULL
, NULL
, NULL
, "4711", "23", "42"},
123 {"YXV0aHppZABhdXRoaWQANDcxMQA=", "", NULL
, NULL
}, NULL
, "authzid",
124 "authid", NULL
, NULL
, NULL
, NULL
, "4711"},
126 {"YXV0aHppZABhdXRoaWQANDcxMQA=", "", NULL
, NULL
}, NULL
, "authzid",
127 "authid", NULL
, NULL
, NULL
, NULL
, "4711"},
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
},
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
},
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
}
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
;
157 if (out
&& sasltv
[i
].authzid
)
158 memcpy (out
, sasltv
[i
].authzid
, needlen
);
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
;
176 memcpy (out
, sasltv
[i
].authid
, needlen
);
182 client_callback_password (Gsasl_session_ctx
* xctx
, char *out
,
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
;
194 memcpy (out
, sasltv
[i
].password
, needlen
);
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
;
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
);
240 memcpy (key
, sasltv
[i
].password
, needlen
);
246 client_callback_service (Gsasl_session_ctx
* ctx
,
250 size_t * hostlen
, char *srvname
, size_t * srvnamelen
)
263 client_callback_anonymous (Gsasl_session_ctx
* xctx
, char *out
,
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
;
275 memcpy (out
, sasltv
[i
].anonymous
, strlen (sasltv
[i
].anonymous
));
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
;
291 server_callback_external (Gsasl_session_ctx
* xctx
)
297 client_callback_passcode (Gsasl_session_ctx
* xctx
, char *out
,
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
;
309 memcpy (out
, sasltv
[i
].passcode
, needlen
);
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
;
335 memcpy (out
, sasltv
[i
].pin
, needlen
);
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
);
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
)
362 *suggestpinlen
= strlen (sasltv
[i
].suggestpin
);
364 memcpy (suggestpin
, sasltv
[i
].suggestpin
,
365 strlen (sasltv
[i
].suggestpin
));
367 else if (*suggestpinlen
)
370 else if (sasltv
[i
].securidrc
==
371 GSASL_SECURID_SERVER_NEED_ADDITIONAL_PASSCODE
)
373 res
= sasltv
[i
].securidrc
;
374 sasltv
[i
].securidrc
= GSASL_OK
;
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
;
397 Gsasl_ctx
*ctx
= NULL
;
398 Gsasl_session_ctx
*xctx
= NULL
;
399 char output
[MAX_LINE_LENGTH
];
404 res
= gsasl_init (&ctx
);
407 fail ("gsasl_init() failed (%d):\n%s\n", res
, gsasl_strerror (res
));
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
);
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
);
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
);
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
);
449 res
= gsasl_server_support_p (ctx
, sasltv
[i
].mech
);
453 if (sasltv
[i
].clientp
)
454 res
= gsasl_client_start (ctx
, sasltv
[i
].mech
, &xctx
);
456 res
= gsasl_server_start (ctx
, sasltv
[i
].mech
, &xctx
);
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
));
465 for (j
= 0; sasltv
[i
].step
[j
]; j
+= 2)
467 if (sasltv
[i
].clientp
)
468 gsasl_client_application_data_set (xctx
, &j
);
470 gsasl_server_application_data_set (xctx
, &j
);
473 printf ("Input : %s\n",
474 sasltv
[i
].step
[j
] ? sasltv
[i
].step
[j
] : "");
477 outputlen
= sizeof (output
);
478 if (sasltv
[i
].clientp
)
479 res
= gsasl_client_step_base64 (xctx
, sasltv
[i
].step
[j
],
482 res
= gsasl_server_step_base64 (xctx
, sasltv
[i
].step
[j
],
486 printf ("Output: %s\n", output
);
488 if (res
!= GSASL_OK
&& res
!= GSASL_NEEDS_MORE
)
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] : "");
497 ("SASL entry %d mechanism %s client step %d length error\n",
498 i
, sasltv
[i
].mech
, j
);
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
);
514 if (strcmp (sasltv
[i
].mech
, "SECURID") != 0 && res
== GSASL_OK
)
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
));
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
);
534 gsasl_server_finish (xctx
);