1/* testsuite.c -- Stress the library a little
2 * Rob Siemborski
3 * Tim Martin
4 * $Id: testsuite.c,v 1.49 2011/11/09 15:49:47 murch Exp $
5 */
6/*
7 * Copyright (c) 1998-2003 Carnegie Mellon University.  All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in
18 *    the documentation and/or other materials provided with the
19 *    distribution.
20 *
21 * 3. The name "Carnegie Mellon University" must not be used to
22 *    endorse or promote products derived from this software without
23 *    prior written permission. For permission or any other legal
24 *    details, please contact
25 *      Office of Technology Transfer
26 *      Carnegie Mellon University
27 *      5000 Forbes Avenue
28 *      Pittsburgh, PA  15213-3890
29 *      (412) 268-4387, fax: (412) 268-7395
30 *      tech-transfer@andrew.cmu.edu
31 *
32 * 4. Redistributions of any form whatsoever must retain the following
33 *    acknowledgment:
34 *    "This product includes software developed by Computing Services
35 *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
36 *
37 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
38 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
39 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
40 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
41 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
42 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
43 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
44 */
45
46/*
47 * To create a krb5 srvtab file given a krb4 srvtab
48 *
49 * ~/> ktutil
50 * ktutil:  rst /etc/srvtab
51 * ktutil:  wkt /etc/krb5.keytab
52 * ktutil:  q
53 */
54
55/*
56 * TODO [FIXME]:
57 *  put in alloc() routines that fail occasionally.
58 */
59
60#include <config.h>
61
62#include <stdio.h>
63#include <stdlib.h>
64
65#include <sasl.h>
66#include <saslplug.h>
67#include <saslutil.h>
68#include <prop.h>
69
70#ifdef HAVE_UNISTD_H
71#include <unistd.h>
72#endif
73#include <time.h>
74#include <string.h>
75#include <ctype.h>
76#ifndef WIN32
77#include <netinet/in.h>
78#include <netdb.h>
79#include <sys/socket.h>
80#include <arpa/inet.h>
81#include <sys/file.h>
82#endif
83
84#ifdef WIN32
85__declspec(dllimport) char *optarg;
86__declspec(dllimport) int optind;
87__declspec(dllimport) int getsubopt(char **optionp, char * const *tokens, char **valuep);
88#endif
89
90char myhostname[1024+1];
91#define MAX_STEPS 7 /* maximum steps any mechanism takes */
92
93#define CLIENT_TO_SERVER "Hello. Here is some stuff"
94
95#define REALLY_LONG_LENGTH  32000
96#define REALLY_LONG_BACKOFF  2000
97
98const char *username = "ken";
99const char *nonexistant_username = "ABCDEFGHIJ";
100const char *authname = "ken";
101const char *proxyasname = "kenproxy";
102const char *password = "1234";
103sasl_secret_t * g_secret = NULL;
104const char *cu_plugin = "INTERNAL";
105char other_result[1024];
106
107int proxyflag = 0;
108
109static const char *gssapi_service = "host";
110
111/* our types of failures */
112typedef enum {
113    NOTHING = 0,
114    ONEBYTE_RANDOM,		/* replace one byte with something random */
115    ONEBYTE_NULL,		/* replace one byte with a null */
116    ONEBYTE_QUOTES,		/* replace one byte with a double quote
117				   (try to fuck with digest-md5) */
118    ONLY_ONE_BYTE,		/* send only one byte */
119    ADDSOME,			/* add some random bytes onto the end */
120    SHORTEN,			/* shorten the string some */
121    REASONABLE_RANDOM,		/* send same size but random */
122    REALLYBIG,			/* send something absurdly large all random */
123    NEGATIVE_LENGTH,		/* send negative length */
124    CORRUPT_SIZE		/* keep this one last */
125} corrupt_type_t;
126
127const char *corrupt_types[] = {
128    "NOTHING",
129    "ONEBYTE_RANDOM",
130    "ONEBYTE_NULL",
131    "ONEBYTE_QUOTES",
132    "ONLY_ONE_BYTE",
133    "ADDSOME",
134    "SHORTEN",
135    "REASONABLE_RANDOM",
136    "REALLYBIG",
137    "NEGATIVE_LENGTH",
138    "CORRUPT_SIZE"
139};
140
141void fatal(char *str)
142{
143    printf("Failed with: %s\n",str);
144    exit(3);
145}
146
147/* interactions we support */
148static sasl_callback_t client_interactions[] = {
149  {
150    SASL_CB_GETREALM, NULL, NULL
151  }, {
152    SASL_CB_USER, NULL, NULL
153  }, {
154    SASL_CB_AUTHNAME, NULL, NULL
155  }, {
156    SASL_CB_PASS, NULL, NULL
157  }, {
158    SASL_CB_LIST_END, NULL, NULL
159  }
160};
161
162int test_getrealm(void *context __attribute__((unused)), int id,
163		  const char **availrealms __attribute__((unused)),
164		  const char **result)
165{
166    if(id != SASL_CB_GETREALM) fatal("test_getrealm not looking for realm");
167    if(!result) return SASL_BADPARAM;
168    *result = myhostname;
169    return SASL_OK;
170}
171
172int test_getsecret(sasl_conn_t *conn __attribute__((unused)),
173		   void *context __attribute__((unused)), int id,
174		   sasl_secret_t **psecret)
175{
176    if(id != SASL_CB_PASS) fatal("test_getsecret not looking for pass");
177    if(!psecret) return SASL_BADPARAM;
178
179    *psecret = g_secret;
180
181    return SASL_OK;
182}
183
184int test_getsimple(void *context __attribute__((unused)), int id,
185		   const char **result, unsigned *len)
186{
187    if(!result) return SASL_BADPARAM;
188
189    if (id==SASL_CB_USER && proxyflag == 0) {
190	*result=(char *) username;
191    } else if (id==SASL_CB_USER && proxyflag == 1) {
192	*result=(char *) proxyasname;
193    } else if (id==SASL_CB_AUTHNAME) {
194	*result=(char *) authname;
195    } else {
196	printf("I want %d\n", id);
197	fatal("unknown callback in test_getsimple");
198    }
199
200    if (len) *len = (unsigned) strlen(*result);
201    return SASL_OK;
202}
203
204/* callbacks we support */
205static sasl_callback_t client_callbacks[] = {
206  {
207    SASL_CB_GETREALM, (sasl_callback_ft)test_getrealm, NULL
208  }, {
209    SASL_CB_USER, (sasl_callback_ft)test_getsimple, NULL
210  }, {
211    SASL_CB_AUTHNAME, (sasl_callback_ft)test_getsimple, NULL
212  }, {
213    SASL_CB_PASS, (sasl_callback_ft)test_getsecret, NULL
214  }, {
215    SASL_CB_LIST_END, NULL, NULL
216  }
217};
218
219typedef void *foreach_t(char *mech, void *rock);
220
221typedef struct tosend_s {
222    corrupt_type_t type; /* type of corruption to make */
223    int step; /* step it should send bogus data on */
224    sasl_callback_t *client_callbacks; /* which client callbacks to use */
225} tosend_t;
226
227typedef struct mem_info
228{
229    void *addr;
230    size_t size;
231    struct mem_info *next;
232} mem_info_t;
233
234int DETAILED_MEMORY_DEBUGGING = 0;
235
236mem_info_t *head = NULL;
237
238#ifndef WITH_DMALLOC
239
240void *test_malloc(size_t size)
241{
242    void *out;
243    mem_info_t *new_data;
244
245    out = malloc(size);
246
247    if(DETAILED_MEMORY_DEBUGGING)
248	fprintf(stderr, "  %p = malloc(%u)\n", out, (unsigned) size);
249
250    if(out) {
251	new_data = malloc(sizeof(mem_info_t));
252	if(!new_data) return out;
253
254	new_data->addr = out;
255	new_data->size = size;
256	new_data->next = head;
257	head = new_data;
258    }
259
260    return out;
261}
262
263void *test_realloc(void *ptr, size_t size)
264{
265    void *out;
266    mem_info_t **prev, *cur;
267
268    out = realloc(ptr, size);
269
270    if(DETAILED_MEMORY_DEBUGGING)
271	fprintf(stderr, "  %p = realloc(%p,%d)\n",
272		out, ptr, size);
273
274    prev = &head; cur = head;
275
276    while(cur) {
277	if(cur->addr == ptr) {
278	    cur->addr = out;
279	    cur->size = size;
280	    return out;
281	}
282
283	prev = &cur->next;
284	cur = cur->next;
285    }
286
287    if(DETAILED_MEMORY_DEBUGGING && cur == NULL) {
288	fprintf(stderr,
289		"  MEM WARNING: reallocing something we never allocated!\n");
290
291	cur = malloc(sizeof(mem_info_t));
292	if(!cur) return out;
293
294	cur->addr = out;
295	cur->size = size;
296	cur->next = head;
297	head = cur;
298    }
299
300    return out;
301}
302
303void *test_calloc(size_t nmemb, size_t size)
304{
305    void *out;
306    mem_info_t *new_data;
307
308    out = calloc(nmemb, size);
309
310    if(DETAILED_MEMORY_DEBUGGING)
311	fprintf(stderr, "  %p = calloc(%d, %d)\n",
312		out, nmemb, size);
313
314    if(out) {
315	new_data = malloc(sizeof(mem_info_t));
316	if(!new_data) return out;
317
318	new_data->addr = out;
319	new_data->size = size;
320	new_data->next = head;
321	head = new_data;
322    }
323
324    return out;
325}
326
327
328void test_free(void *ptr)
329{
330    mem_info_t **prev, *cur;
331
332    if(DETAILED_MEMORY_DEBUGGING)
333	fprintf(stderr, "  free(%p)\n",
334		ptr);
335
336    prev = &head; cur = head;
337
338    while(cur) {
339	if(cur->addr == ptr) {
340	    *prev = cur->next;
341	    free(cur);
342	    break;
343	}
344
345	prev = &cur->next;
346	cur = cur->next;
347    }
348
349    if(DETAILED_MEMORY_DEBUGGING && cur == NULL) {
350	fprintf(stderr,
351		"  MEM WARNING: Freeing something we never allocated!\n");
352    }
353
354    free(ptr);
355}
356
357#endif /* WITH_DMALLOC */
358
359int mem_stat()
360{
361#ifndef WITH_DMALLOC
362    mem_info_t *cur;
363    size_t n;
364    unsigned char *data;
365
366    if(!head) {
367	fprintf(stderr, "  All memory accounted for!\n");
368	return SASL_OK;
369    }
370
371    fprintf(stderr, "  Currently Still Allocated:\n");
372    for(cur = head; cur; cur = cur->next) {
373	fprintf(stderr, "    %p (%5d)\t", cur->addr, cur->size);
374	for(data = (unsigned char *) cur->addr,
375		n = 0; n < (cur->size > 12 ? 12 : cur->size); n++) {
376	    if (isprint((int) data[n]))
377		fprintf(stderr, "'%c' ", (char) data[n]);
378	    else
379		fprintf(stderr, "%02X  ", data[n] & 0xff);
380	}
381	if (n < cur->size)
382	    fprintf(stderr, "...");
383	fprintf(stderr, "\n");
384    }
385    return SASL_FAIL;
386#else
387    return SASL_OK;
388#endif /* WITH_DMALLOC */
389}
390
391
392/************* End Memory Allocation functions ******/
393
394/* my mutex functions */
395int g_mutex_cnt = 0;
396
397typedef struct my_mutex_s {
398
399    int num;
400    int val;
401
402} my_mutex_t;
403
404void *my_mutex_new(void)
405{
406    my_mutex_t *ret = (my_mutex_t *)malloc(sizeof(my_mutex_t));
407    ret->num = g_mutex_cnt;
408    g_mutex_cnt++;
409
410    ret->val = 0;
411
412    return ret;
413}
414
415int my_mutex_lock(my_mutex_t *m)
416{
417    if (m->val != 0)
418    {
419	fatal("Trying to lock a mutex already locked [single-threaded app]");
420    }
421
422    m->val = 1;
423    return SASL_OK;
424}
425
426int my_mutex_unlock(my_mutex_t *m)
427{
428    if (m->val != 1)
429    {
430	fatal("Unlocking mutex that isn't locked");
431    }
432
433    m->val = 0;
434
435    return SASL_OK;
436}
437
438void my_mutex_dispose(my_mutex_t *m)
439{
440    if (m==NULL) return;
441
442    free(m);
443
444    return;
445}
446
447int good_getopt(void *context __attribute__((unused)),
448		const char *plugin_name __attribute__((unused)),
449		const char *option,
450		const char **result,
451		unsigned *len)
452{
453    if (strcmp(option,"pwcheck_method")==0)
454    {
455	*result = "auxprop";
456	if (len)
457	    *len = (unsigned) strlen("auxprop");
458	return SASL_OK;
459    } else if (!strcmp(option, "auxprop_plugin")) {
460	*result = "sasldb";
461	if (len)
462	    *len = (unsigned) strlen("sasldb");
463	return SASL_OK;
464    } else if (!strcmp(option, "sasldb_path")) {
465	*result = "./sasldb";
466	if (len)
467	    *len = (unsigned) strlen("./sasldb");
468	return SASL_OK;
469    } else if (!strcmp(option, "canon_user_plugin")) {
470	*result = cu_plugin;
471	if (len)
472	    *len = (unsigned) strlen(*result);
473	return SASL_OK;
474    }
475
476    return SASL_FAIL;
477}
478
479static struct sasl_callback goodsasl_cb[] = {
480    { SASL_CB_GETOPT, (sasl_callback_ft)&good_getopt, NULL },
481    { SASL_CB_LIST_END, NULL, NULL }
482};
483
484int givebadpath(void * context __attribute__((unused)),
485		char ** path)
486{
487    int lup;
488    *path = malloc(10000);
489    strcpy(*path,"/tmp/is/not/valid/path/");
490
491    for (lup = 0;lup<1000;lup++)
492	strcat(*path,"a/");
493
494    return SASL_OK;
495}
496
497static struct sasl_callback withbadpathsasl_cb[] = {
498    { SASL_CB_GETPATH, (sasl_callback_ft)&givebadpath, NULL },
499    { SASL_CB_LIST_END, NULL, NULL }
500};
501
502int giveokpath(void * context __attribute__((unused)),
503		const char ** path)
504{
505    *path = "/tmp/";
506
507    return SASL_OK;
508}
509
510static struct sasl_callback withokpathsasl_cb[] = {
511    { SASL_CB_GETPATH, (sasl_callback_ft)&giveokpath, NULL },
512    { SASL_CB_LIST_END, NULL, NULL }
513};
514
515static struct sasl_callback emptysasl_cb[] = {
516    { SASL_CB_LIST_END, NULL, NULL }
517};
518
519static int proxy_authproc(sasl_conn_t *conn,
520			   void *context __attribute__((unused)),
521			   const char *requested_user,
522			   unsigned rlen __attribute__((unused)),
523			   const char *auth_identity,
524			   unsigned alen __attribute__((unused)),
525			   const char *def_realm __attribute__((unused)),
526			   unsigned urlen __attribute__((unused)),
527			   struct propctx *propctx __attribute__((unused)))
528{
529    if(!strcmp(auth_identity, authname)
530       && !strcmp(requested_user, proxyasname)) return SASL_OK;
531
532    if(!strcmp(auth_identity, requested_user)) {
533	printf("Warning: Authenticated name but DID NOT proxy (%s/%s)\n",
534	       requested_user, auth_identity);
535	return SASL_OK;
536    }
537
538    sasl_seterror(conn, SASL_NOLOG, "authorization failed: %s by %s",
539		  requested_user, auth_identity);
540    return SASL_BADAUTH;
541}
542
543static struct sasl_callback goodsaslproxy_cb[] = {
544    { SASL_CB_PROXY_POLICY, (sasl_callback_ft)&proxy_authproc, NULL },
545    { SASL_CB_GETOPT, (sasl_callback_ft)&good_getopt, NULL },
546    { SASL_CB_LIST_END, NULL, NULL }
547};
548
549char really_long_string[REALLY_LONG_LENGTH];
550
551/*
552 * Setup some things for test
553 */
554void init(unsigned int seed)
555{
556    int lup;
557    int result;
558
559    srand(seed);
560
561    for (lup=0;lup<REALLY_LONG_LENGTH;lup++)
562	really_long_string[lup] = '0' + (rand() % 10);
563
564    really_long_string[REALLY_LONG_LENGTH - rand() % REALLY_LONG_BACKOFF] = '\0';
565
566    result = gethostname(myhostname, sizeof(myhostname)-1);
567    if (result == -1) fatal("gethostname");
568
569    sasl_set_mutex((sasl_mutex_alloc_t *) &my_mutex_new,
570		   (sasl_mutex_lock_t *) &my_mutex_lock,
571		   (sasl_mutex_unlock_t *) &my_mutex_unlock,
572		   (sasl_mutex_free_t *) &my_mutex_dispose);
573
574#ifndef WITH_DMALLOC
575    sasl_set_alloc((sasl_malloc_t *)test_malloc,
576		   (sasl_calloc_t *)test_calloc,
577		   (sasl_realloc_t *)test_realloc,
578		   (sasl_free_t *)test_free);
579#endif
580
581}
582
583/*
584 * Tests for sasl_server_init
585 */
586
587void test_init(void)
588{
589    int result;
590
591    /* sasl_done() before anything */
592    sasl_done();
593    if(mem_stat() != SASL_OK) fatal("memory error after sasl_done test");
594
595    /* Try passing appname a really long string (just see if it crashes it)*/
596
597    result = sasl_server_init(NULL,really_long_string);
598    sasl_done();
599    if(mem_stat() != SASL_OK) fatal("memory error after long appname test");
600
601    /* this calls sasl_done when it wasn't inited */
602    sasl_done();
603    if(mem_stat() != SASL_OK) fatal("memory error after null appname test");
604
605    /* try giving it a different path for where the plugins are */
606    result = sasl_server_init(withokpathsasl_cb, "Tester");
607    if (result!=SASL_OK) fatal("Didn't deal with ok callback path very well");
608    sasl_done();
609    if(mem_stat() != SASL_OK) fatal("memory error after callback path test");
610
611    /* and the client */
612    result = sasl_client_init(withokpathsasl_cb);
613
614    if (result!=SASL_OK)
615	fatal("Client didn't deal with ok callback path very well");
616    sasl_done();
617    if(mem_stat() != SASL_OK) fatal("memory error after client test");
618
619#if defined(DO_DLOPEN) && (defined(PIC) || (!defined(PIC) && defined(TRY_DLOPEN_WHEN_STATIC)))
620    /* try giving it an invalid path for where the plugins are */
621    result = sasl_server_init(withbadpathsasl_cb, NULL);
622    if (result==SASL_OK) fatal("Allowed invalid path");
623    sasl_done();
624    if(mem_stat() != SASL_OK) fatal("memory error after bad path test");
625#endif
626
627    /* and the client - xxx is this necessary?*/
628#if 0
629    result = sasl_client_init(withbadpathsasl_cb);
630
631    if (result==SASL_OK)
632	fatal("Client allowed invalid path");
633    sasl_done();
634#endif
635
636    /* Now try to break all the sasl_server_* functions for not returning
637       SASL_NOTINIT */
638
639    if(sasl_global_listmech())
640	fatal("sasl_global_listmech did not return NULL with no library initialized");
641
642    if(sasl_server_new(NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL)
643       != SASL_NOTINIT)
644	fatal("sasl_server_new did not return SASL_NOTINIT");
645
646/* Can't check this validly without a server conn, so this would be
647   a hard one to tickle anyway */
648#if 0
649    if(sasl_listmech(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)
650       != SASL_NOTINIT)
651	fatal("sasl_listmech did not return SASL_NOTINIT");
652#endif
653
654    if(sasl_server_start(NULL, NULL, NULL, 0, NULL, NULL)
655       != SASL_NOTINIT)
656	fatal("sasl_server_start did not return SASL_NOTINIT");
657
658    if(sasl_server_step(NULL, NULL, 0, NULL, NULL)
659       != SASL_NOTINIT)
660	fatal("sasl_server_step did not return SASL_NOTINIT");
661
662#ifdef DO_SASL_CHECKAPOP
663    if(sasl_checkapop(NULL, NULL, 0, NULL, 0)
664       != SASL_NOTINIT)
665	fatal("sasl_checkapop did not return SASL_NOTINIT");
666#endif
667
668    if(sasl_checkpass(NULL, NULL, 0, NULL, 0)
669       != SASL_NOTINIT)
670	fatal("sasl_checkpass did not return SASL_NOTINIT");
671
672    if(sasl_user_exists(NULL, NULL, NULL, NULL)
673       != SASL_NOTINIT)
674	fatal("sasl_user_exists did not return SASL_NOTINIT");
675
676    if(sasl_setpass(NULL, NULL, NULL, 0, NULL, 0, 0)
677       != SASL_NOTINIT)
678	fatal("sasl_setpass did not return SASL_NOTINIT");
679
680    /* And sasl_client_*... */
681
682    if(sasl_client_new(NULL, NULL, NULL, NULL, NULL, 0, NULL)
683       != SASL_NOTINIT)
684	fatal("sasl_client_new did not return SASL_NOTINIT");
685
686    if(sasl_client_start(NULL, NULL, NULL, NULL, NULL, NULL)
687       != SASL_NOTINIT)
688	fatal("sasl_client_start did not return SASL_NOTINIT");
689
690    if(sasl_client_step(NULL, NULL, 0, NULL, NULL, NULL)
691       != SASL_NOTINIT)
692	fatal("sasl_client_step did not return SASL_NOTINIT");
693
694}
695
696
697/*
698 * Tests sasl_listmech command
699 */
700
701void test_listmech(void)
702{
703    sasl_conn_t *saslconn, *cconn;
704    int result;
705    const char *str = NULL;
706    unsigned plen;
707    unsigned lup, flag;
708    int pcount;
709    const char **list;
710
711    /* test without initializing library */
712    result = sasl_listmech(NULL, /* conn */
713			   NULL,
714			   "[",
715			   "-",
716			   "]",
717			   &str,
718			   NULL,
719			   NULL);
720
721    /*    printf("List mech without library initialized: %s\n",sasl_errstring(result,NULL,NULL));*/
722    if (result == SASL_OK) fatal("Failed sasl_listmech() with NULL saslconn");
723
724    if (sasl_server_init(emptysasl_cb,"TestSuite")!=SASL_OK)
725	fatal("can't sasl_server_init");
726    if (sasl_client_init(client_interactions)!=SASL_OK)
727	fatal("can't sasl_client_init");
728
729    if (sasl_server_new("rcmd", myhostname,
730			NULL, NULL, NULL, NULL, 0,
731			&saslconn) != SASL_OK)
732	fatal("can't sasl_server_new");
733
734    if (sasl_setprop(saslconn, SASL_AUTH_EXTERNAL, authname)!=SASL_OK)
735	fatal("sasl_setprop(SASL_AUTH_EXTERNAL) failed");
736
737    /* client new connection */
738    if (sasl_client_new("rcmd",
739			myhostname,
740			NULL, NULL, NULL,
741			0,
742			&cconn)!= SASL_OK)
743	fatal("sasl_client_new() failure");
744
745    if (sasl_setprop(cconn, SASL_AUTH_EXTERNAL, authname)!=SASL_OK)
746	fatal("sasl_setprop(SASL_AUTH_EXTERNAL) failed");
747
748    /* try both sides */
749    list = sasl_global_listmech();
750    if(!list) fatal("sasl_global_listmech failure");
751
752    printf(" [");
753    flag = 0;
754    for(lup = 0; list[lup]; lup++) {
755	if(flag) printf(",");
756	else flag++;
757	printf("%s",list[lup]);
758    }
759    printf("]\n");
760
761    /* try client side */
762    result = sasl_listmech(cconn,
763			   NULL,
764			   " [",
765			   ",",
766			   "]",
767			   &str,
768			   NULL,
769			   NULL);
770    if(result == SASL_OK) {
771	printf("Client mechlist:\n%s\n", str);
772    } else {
773	fatal("client side sasl_listmech failed");
774    }
775
776    /* Test with really long user */
777
778    result = sasl_listmech(saslconn,
779			   really_long_string,
780			   "[",
781			   "-",
782			   "]",
783			   &str,
784			   NULL,
785			   NULL);
786
787    if (result != SASL_OK) fatal("Failed sasl_listmech() with long user");
788
789    if (str[0]!='[') fatal("Failed sasl_listmech() with long user (didn't start with '['");
790
791    result = sasl_listmech(saslconn,
792			   really_long_string,
793			   "[",
794			   ",",
795			   "]",
796			   &str,
797			   NULL,
798			   NULL);
799
800    if (result != SASL_OK) fatal("Failed sasl_listmech() with different params");
801
802    printf("We have the following mechs:\n %s\n",str);
803
804    /* Test with really long prefix */
805
806    result = sasl_listmech(saslconn,
807			   NULL,
808			   really_long_string,
809			   "-",
810			   "]",
811			   &str,
812			   NULL,
813			   NULL);
814
815    if (result != SASL_OK) fatal("failed sasl_listmech() with long prefix");
816
817    if (str[0]!=really_long_string[0]) fatal("failed sasl_listmech() with long prefix (str is suspect)");
818
819    /* Test with really long suffix */
820
821    result = sasl_listmech(saslconn,
822			   NULL,
823			   "[",
824			   "-",
825			   really_long_string,
826			   &str,
827			   NULL,
828			   NULL);
829
830    if (result != SASL_OK) fatal("Failed sasl_listmech() with long suffix");
831
832    /* Test with really long seperator */
833
834    result = sasl_listmech(saslconn,
835			   NULL,
836			   "[",
837			   really_long_string,
838			   "]",
839			   &str,
840			   NULL,
841			   NULL);
842
843    if (result != SASL_OK) fatal("Failed sasl_listmech() with long seperator");
844
845    /* Test contents of output string is accurate */
846    result = sasl_listmech(saslconn,
847			   NULL,
848			   "",
849			   "%",
850			   "",
851			   &str,
852			   &plen,
853			   &pcount);
854
855    if (result != SASL_OK) fatal("Failed sasl_listmech()");
856
857    if (strlen(str)!=plen) fatal("Length of string doesn't match what we were told");
858
859    for (lup=0;lup<plen;lup++)
860	if (str[lup]=='%')
861	    pcount--;
862
863    pcount--;
864    if (pcount != 0)
865    {
866	printf("mechanism string = %s\n",str);
867	printf("Mechs left = %d\n",pcount);
868	fatal("Number of mechs received doesn't match what we were told");
869    }
870
871    /* Call sasl done then make sure listmech doesn't work anymore */
872    sasl_dispose(&saslconn);
873    sasl_dispose(&cconn);
874    sasl_done();
875
876    result = sasl_listmech(saslconn,
877			   NULL,
878			   "[",
879			   "-",
880			   "]",
881			   &str,
882			   NULL,
883			   NULL);
884
885    if (result == SASL_OK) fatal("Called sasl_done but listmech still works\n");
886
887}
888
889/*
890 * Perform tests on the random utilities
891 */
892
893void test_random(void)
894{
895    sasl_rand_t *rpool;
896    int lup;
897    char buf[4096];
898
899    /* make sure it works consistantly */
900
901    for (lup = 0;lup<10;lup++)
902    {
903	if (sasl_randcreate(&rpool) != SASL_OK) fatal("sasl_randcreate failed");
904	sasl_randfree(&rpool);
905    }
906
907    /* try seeding w/o calling rand_create first */
908    rpool = NULL;
909    sasl_randseed(rpool, "seed", 4);
910
911    /* try seeding with bad values */
912    sasl_randcreate(&rpool);
913    sasl_randseed(rpool, "seed", 0);
914    sasl_randseed(rpool, NULL, 0);
915    sasl_randseed(rpool, NULL, 4);
916    sasl_randfree(&rpool);
917
918    /* try churning with bad values */
919    sasl_randcreate(&rpool);
920    sasl_churn(rpool, "seed", 0);
921    sasl_churn(rpool, NULL, 0);
922    sasl_churn(rpool, NULL, 4);
923    sasl_randfree(&rpool);
924
925    /* try seeding with a lot of crap */
926    sasl_randcreate(&rpool);
927
928    for (lup=0;lup<(int) sizeof(buf);lup++)
929    {
930	buf[lup] = (char) (rand() % 256);
931    }
932    sasl_randseed(rpool, buf, sizeof(buf));
933    sasl_churn(rpool, buf, sizeof(buf));
934
935    sasl_randfree(&rpool);
936}
937
938/*
939 * Test SASL base64 conversion routines
940 */
941
942void test_64(void)
943{
944    char orig[4096];
945    char enc[8192];
946    unsigned encsize;
947    int lup;
948
949    /* make random crap and see if enc->dec produces same as original */
950    for (lup=0;lup<(int) sizeof(orig);lup++)
951	orig[lup] = (char) (rand() % 256);
952
953    if (sasl_encode64(orig, sizeof(orig), enc, sizeof(enc), &encsize)!=SASL_OK)
954	fatal("encode64 failed when we didn't expect it to");
955
956    if (sasl_decode64(enc, encsize, enc, 8192, &encsize)!=SASL_OK)
957	fatal("decode64 failed when we didn't expect it to");
958
959    if (encsize != sizeof(orig)) fatal("Now has different size");
960
961    for (lup=0;lup<(int) sizeof(orig);lup++)
962	if (enc[lup] != orig[lup])
963	    fatal("enc64->dec64 doesn't match");
964
965    /* try to get a SASL_BUFOVER */
966
967    if (sasl_encode64(orig, sizeof(orig)-1, enc, 10, &encsize)!=SASL_BUFOVER)
968	fatal("Expected SASL_BUFOVER");
969
970
971    /* pass some bad params */
972    if (sasl_encode64(NULL, 10, enc, sizeof(enc), &encsize)==SASL_OK)
973	fatal("Said ok to null data");
974
975    if (sasl_encode64(orig, sizeof(orig), enc, sizeof(enc), NULL)!=SASL_OK)
976	fatal("Didn't allow null return size");
977
978    /* New tests in 2.1.22 */
979    for (lup=0;lup<(int) sizeof(orig);lup++) {
980	enc[lup] = 'A';
981    }
982
983    if (sasl_decode64(enc, 3, orig, 8192, &encsize) != SASL_CONTINUE)
984	fatal("decode64 succeded on a 3 byte buffer when it shouldn't have");
985
986    enc[3] = '\r';
987    enc[4] = '\n';
988
989    if (sasl_decode64(enc, 4, orig, 8192, &encsize) == SASL_OK)
990	fatal("decode64 succeded on a 4 byte buffer with a bare CR");
991
992    if (sasl_decode64(enc, 5, orig, 8192, &encsize) == SASL_OK)
993	fatal("decode64 succeded on a 5 byte buffer with CRLF");
994
995    enc[2] = '=';
996    enc[3] = '=';
997    enc[4] = '=';
998
999    if (sasl_decode64(enc, 4, orig, 8192, &encsize) != SASL_OK)
1000	fatal("decode64 failed on a 4 byte buffer with a terminating =");
1001
1002    if (sasl_decode64(enc, 5, orig, 8192, &encsize) != SASL_BADPROT)
1003	fatal("decode64 did not return SASL_CONTINUE on a 5 byte buffer with a terminating =");
1004
1005    /* Test for invalid character after the terminating '=' */
1006    enc[3] = '*';
1007
1008    if (sasl_decode64(enc, 4, orig, 8192, &encsize) == SASL_OK)
1009	fatal("decode64 failed on a 4 byte buffer with invalid character a terminating =");
1010
1011    /* Test for '=' in the middle of an encoded string */
1012    enc[3] = 'B';
1013
1014    if (sasl_decode64(enc, 4, orig, 8192, &encsize) == SASL_OK)
1015	fatal("decode64 succeed on a 4 byte buffer with a data after a terminating =");
1016
1017    if (sasl_decode64(enc, 0, orig, 8192, &encsize) != SASL_OK)
1018	fatal("decode64 should have succeeded on an empty buffer");
1019}
1020
1021/* This isn't complete, but then, what in the testsuite is? */
1022void test_props(void)
1023{
1024    int result;
1025    struct propval foobar[3];
1026    struct propctx *ctx, *dupctx;
1027
1028    const char *requests[] = {
1029	"userPassword",
1030        "userName",
1031	"homeDirectory",
1032        "uidNumber",
1033        "gidNumber",
1034        NULL
1035    };
1036
1037    const char *more_requests[] = {
1038	"a",
1039	"b",
1040	"c",
1041	"defghijklmnop",
1042	NULL
1043    };
1044
1045    const char *short_requests[] = {
1046	"userPassword",
1047	"userName",
1048	"BAD",
1049	NULL
1050    };
1051
1052    ctx = prop_new(2);
1053    if(!ctx) {
1054	fatal("no new prop context");
1055    }
1056
1057    if(prop_request(NULL, requests) == SASL_OK)
1058	fatal("prop_request w/NULL context succeeded");
1059    if(prop_request(ctx, NULL) == SASL_OK)
1060	fatal("prop_request w/NULL request list succeeded");
1061
1062    result = prop_request(ctx, requests);
1063    if(result != SASL_OK)
1064	fatal("prop request failed");
1065
1066    /* set some values */
1067    prop_set(ctx, "uidNumber", really_long_string, 0);
1068    prop_set(ctx, "userPassword", "pw1", 0);
1069    prop_set(ctx, "userPassword", "pw2", 0);
1070    prop_set(ctx, "userName", "rjs3", 0);
1071    prop_set(ctx, NULL, "tmartin", 0);
1072
1073    /* and request some more (this resets values) */
1074    prop_request(ctx, more_requests);
1075
1076    /* and set some more... */
1077    prop_set(ctx, "c", really_long_string, 0);
1078    prop_set(ctx, "b", really_long_string, 0);
1079    prop_set(ctx, "userPassword", "pw1b", 0);
1080    prop_set(ctx, "userPassword", "pw2b", 0);
1081    prop_set(ctx, "userName", "rjs3b", 0);
1082    prop_set(ctx, NULL, "tmartinagain", 0);
1083
1084    if(prop_set(ctx, "gah", "ack", 0) == SASL_OK) {
1085	printf("setting bad property name succeeded\n");
1086	exit(1);
1087    }
1088
1089    result = prop_getnames(ctx, short_requests, foobar);
1090    if(result < 0)
1091	fatal("prop_getnames failed");
1092
1093    if(strcmp(foobar[0].name, short_requests[0]))
1094	fatal("prop_getnames item 0 wrong name");
1095    if(strcmp(foobar[1].name, short_requests[1]))
1096	fatal("prop_getnames item 1 wrong name");
1097    if(foobar[2].name)
1098	fatal("prop_getnames returned an item 2");
1099
1100    if(strcmp(foobar[0].values[0], "pw1b"))
1101	fatal("prop_getnames item 1a wrong value");
1102    if(strcmp(foobar[0].values[1], "pw2b"))
1103	fatal("prop_getnames item 1b wrong value");
1104    if(strcmp(foobar[1].values[0], "rjs3b"))
1105	fatal("prop_getnames item 2a wrong value");
1106    if(strcmp(foobar[1].values[1], "tmartinagain"))
1107	fatal("prop_getnames item 2b wrong value");
1108
1109    result = prop_dup(ctx, &dupctx);
1110    if(result != SASL_OK)
1111	fatal("could not duplicate");
1112
1113    prop_clear(ctx, 1);
1114
1115    result = prop_getnames(ctx, short_requests, foobar);
1116    if(result < 0)
1117	fatal("prop_getnames failed second time");
1118
1119    if(foobar[0].name)
1120	fatal("it appears that prop_clear failed");
1121
1122    result = prop_getnames(dupctx, short_requests, foobar);
1123    if(result < 0)
1124	fatal("prop_getnames failed second time");
1125
1126    if(!foobar[0].name)
1127	fatal("prop_clear appears to have affected dup'd context");
1128
1129    prop_clear(dupctx, 0);
1130
1131    result = prop_getnames(dupctx, short_requests, foobar);
1132    if(result < 0)
1133	fatal("prop_getnames failed second time");
1134
1135    if(!foobar[0].name || strcmp(foobar[0].name, short_requests[0]))
1136	fatal("prop_clear appears to have cleared too much");
1137
1138    prop_dispose(&ctx);
1139    prop_dispose(&dupctx);
1140    if(ctx != NULL)
1141	fatal("ctx not null after prop_dispose");
1142}
1143
1144void interaction (int id, const char *prompt,
1145		  const char **tresult, unsigned int *tlen)
1146{
1147    if (id==SASL_CB_PASS) {
1148	*tresult=(char *) password;
1149    } else if (id==SASL_CB_USER && proxyflag == 0) {
1150	*tresult=(char *) username;
1151    } else if (id==SASL_CB_USER && proxyflag == 1) {
1152	*tresult=(char *) proxyasname;
1153    } else if (id==SASL_CB_AUTHNAME) {
1154	*tresult=(char *) authname;
1155    } else if ((id==SASL_CB_GETREALM)) {
1156	*tresult=(char *) myhostname;
1157    } else {
1158	size_t c;
1159
1160	printf("%s: ",prompt);
1161	fgets(other_result, sizeof(other_result) - 1, stdin);
1162	c = strlen(other_result);
1163	other_result[c - 1] = '\0';
1164	*tresult=other_result;
1165    }
1166
1167    *tlen = (unsigned int) strlen(*tresult);
1168}
1169
1170void fillin_correctly(sasl_interact_t *tlist)
1171{
1172  while (tlist->id!=SASL_CB_LIST_END)
1173  {
1174    interaction(tlist->id, tlist->prompt,
1175		(void *) &(tlist->result),
1176		&(tlist->len));
1177    tlist++;
1178  }
1179
1180}
1181
1182const sasl_security_properties_t security_props = {
1183    0,
1184    256,
1185    8192,
1186    0,
1187    NULL,
1188    NULL
1189};
1190
1191void set_properties(sasl_conn_t *conn, const sasl_security_properties_t *props)
1192{
1193    if(!props) {
1194	if (sasl_setprop(conn, SASL_SEC_PROPS, &security_props) != SASL_OK)
1195	    fatal("sasl_setprop() failed - default properties");
1196    } else {
1197       	if (sasl_setprop(conn, SASL_SEC_PROPS, props) != SASL_OK)
1198	    fatal("sasl_setprop() failed");
1199    }
1200
1201    if (sasl_setprop(conn, SASL_AUTH_EXTERNAL, authname)!=SASL_OK)
1202	fatal("sasl_setprop(SASL_AUTH_EXTERNAL) failed");
1203}
1204
1205/*
1206 * This corrupts the string for us
1207 */
1208void corrupt(corrupt_type_t type, char *in, int inlen,
1209	     char **out, unsigned *outlen)
1210{
1211    unsigned lup;
1212
1213
1214    switch (type)
1215	{
1216	case NOTHING:
1217	    *out = in;
1218	    *outlen = inlen;
1219	    break;
1220	case ONEBYTE_RANDOM: /* corrupt one byte */
1221
1222	    if (inlen>0)
1223		in[ (rand() % inlen) ] = (char) (rand() % 256);
1224
1225	    *out = in;
1226	    *outlen = inlen;
1227
1228	    break;
1229	case ONEBYTE_NULL:
1230	    if (inlen>0)
1231		in[ (rand() % inlen) ] = '\0';
1232
1233	    *out = in;
1234	    *outlen = inlen;
1235	    break;
1236	case ONEBYTE_QUOTES:
1237	    if (inlen>0)
1238		in[ (rand() % inlen) ] = '"';
1239
1240	    *out = in;
1241	    *outlen = inlen;
1242	    break;
1243	case ONLY_ONE_BYTE:
1244	    *out = (char *) malloc(1);
1245	    (*out)[0] = (char) (rand() % 256);
1246	    *outlen = 1;
1247	    break;
1248
1249	case ADDSOME:
1250	    *outlen = inlen+ (rand() % 100);
1251	    *out = (char *) malloc(*outlen);
1252	    memcpy( *out, in, inlen);
1253
1254	    for (lup=inlen;lup<*outlen;lup++)
1255		(*out)[lup] = (char) (rand() %256);
1256
1257	    break;
1258
1259	case SHORTEN:
1260	    if (inlen > 0)
1261	    {
1262		*outlen = 0;
1263		while(*outlen == 0)
1264		    *outlen = (rand() % inlen);
1265		*out = (char *) malloc(*outlen);
1266		memcpy(*out, in, *outlen);
1267	    } else {
1268		*outlen = inlen;
1269		*out = in;
1270	    }
1271	    break;
1272	case REASONABLE_RANDOM:
1273	    *outlen = inlen;
1274	    if(*outlen != 0)
1275		*out = (char *) malloc(*outlen);
1276	    else
1277		*out = malloc(1);
1278
1279	    for (lup=0;lup<*outlen;lup++)
1280		(*out)[lup] = (char) (rand() % 256);
1281
1282	    break;
1283	case REALLYBIG:
1284	    *outlen = rand() % 50000;
1285	    *out = (char *) malloc( *outlen);
1286
1287	    for (lup=0;lup<*outlen;lup++)
1288		(*out)[lup] = (char) (rand() % 256);
1289
1290	    break;
1291	case NEGATIVE_LENGTH:
1292
1293	    *out = in;
1294	    if (inlen == 0) inlen = 10;
1295	    *outlen = -1 * (rand() % inlen);
1296
1297	    break;
1298	default:
1299	    fatal("Invalid corruption type");
1300	    break;
1301	}
1302}
1303
1304void sendbadsecond(char *mech, void *rock)
1305{
1306    int result, need_another_client = 0;
1307    sasl_conn_t *saslconn;
1308    sasl_conn_t *clientconn;
1309    const char *out, *dec, *out2;
1310    char *tmp;
1311    unsigned outlen, declen, outlen2;
1312    sasl_interact_t *client_interact=NULL;
1313    const char *mechusing;
1314    const char *service = "rcmd";
1315    int mystep = 0; /* what step in the authentication are we on */
1316    int mayfail = 0; /* we did some corruption earlier so it's likely to fail now */
1317
1318    tosend_t *send = (tosend_t *)rock;
1319
1320    struct sockaddr_in addr;
1321    struct hostent *hp;
1322    char buf[8192];
1323    int reauth = 1;
1324
1325    printf("%s --> start\n",mech);
1326
1327    if (strncmp(mech,"GSS",3)==0) service = gssapi_service;
1328
1329    if (sasl_client_init(client_interactions)!=SASL_OK) fatal("Unable to init client");
1330
1331    if (sasl_server_init(goodsasl_cb,"TestSuite")!=SASL_OK) fatal("unable to init server");
1332
1333    if ((hp = gethostbyname(myhostname)) == NULL) {
1334	perror("gethostbyname");
1335	fatal("can't gethostbyname");
1336    }
1337
1338    addr.sin_family = 0;
1339    memcpy(&addr.sin_addr, hp->h_addr, hp->h_length);
1340    addr.sin_port = htons(0);
1341
1342 reauth: /* loop back for reauth testing */
1343    sprintf(buf,"%s;%d", inet_ntoa(addr.sin_addr), 23);
1344
1345    /* client new connection */
1346    if (sasl_client_new(service,
1347			myhostname,
1348			buf, buf, NULL,
1349			0,
1350			&clientconn)!= SASL_OK) fatal("sasl_client_new() failure");
1351
1352    set_properties(clientconn, NULL);
1353
1354    if (sasl_server_new(service, myhostname, NULL,
1355			buf, buf, NULL, 0,
1356			&saslconn) != SASL_OK) {
1357	fatal("can't sasl_server_new");
1358    }
1359    set_properties(saslconn, NULL);
1360
1361    do {
1362	result = sasl_client_start(clientconn, mech,
1363				   &client_interact,
1364				   &out, &outlen,
1365				   &mechusing);
1366
1367	if (result == SASL_INTERACT) fillin_correctly(client_interact);
1368	else if(result == SASL_CONTINUE) need_another_client = 1;
1369	else if(result == SASL_OK) need_another_client = 0;
1370    } while (result == SASL_INTERACT);
1371
1372    if (result < 0)
1373    {
1374	printf("%s - \n",sasl_errdetail(clientconn));
1375	fatal("sasl_client_start() error");
1376    }
1377
1378    if (mystep == send->step && outlen)
1379    {
1380	memcpy(buf, out, outlen);
1381	corrupt(send->type, buf, outlen, &tmp, &outlen);
1382	out = tmp;
1383	mayfail = 1;
1384    }
1385
1386    result = sasl_server_start(saslconn,
1387			       mech,
1388			       out,
1389			       outlen,
1390			       &out,
1391			       &outlen);
1392
1393    if (mayfail)
1394    {
1395	if (result >= SASL_OK)
1396	    printf("WARNING: We did a corruption but it still worked\n");
1397	else {
1398	    goto done;
1399	}
1400    } else {
1401	if (result < 0)
1402	{
1403	    printf("%s\n",sasl_errstring(result,NULL,NULL));
1404	    fatal("sasl_server_start() error");
1405	}
1406    }
1407    mystep++;
1408
1409    while (result == SASL_CONTINUE) {
1410
1411	if (mystep == send->step)
1412	{
1413	    memcpy(buf,out,outlen);
1414	    corrupt(send->type, buf, outlen, &tmp, &outlen);
1415	    out = tmp;
1416	    mayfail = 1;
1417	}
1418
1419	do {
1420	    result = sasl_client_step(clientconn,
1421				      out, outlen,
1422				      &client_interact,
1423				      &out2, &outlen2);
1424
1425	    if (result == SASL_INTERACT)
1426		fillin_correctly(client_interact);
1427	    else if (result == SASL_CONTINUE)
1428		need_another_client = 1;
1429	    else if (result == SASL_OK)
1430		need_another_client = 0;
1431	} while (result == SASL_INTERACT);
1432
1433	if (mayfail == 1)
1434	{
1435	    if (result >= 0)
1436		printf("WARNING: We did a corruption but it still worked\n");
1437	    else {
1438		goto done;
1439	    }
1440	} else {
1441	    if (result < 0)
1442	    {
1443		printf("%s\n",sasl_errstring(result,NULL,NULL));
1444		fatal("sasl_client_step() error");
1445	    }
1446	}
1447	out=out2;
1448	outlen=outlen2;
1449	mystep++;
1450
1451	if (mystep == send->step)
1452	{
1453	    memcpy(buf, out, outlen);
1454	    corrupt(send->type, buf, outlen, &tmp, &outlen);
1455	    out = tmp;
1456	    mayfail = 1;
1457	}
1458
1459	result = sasl_server_step(saslconn,
1460				  out,
1461				  outlen,
1462				  &out,
1463				  &outlen);
1464
1465	if (mayfail == 1)
1466	{
1467	    if (result >= 0)
1468		printf("WARNING: We did a corruption but it still worked\n");
1469	    else {
1470		goto done;
1471	    }
1472	} else {
1473	    if (result < 0)
1474	    {
1475		printf("%s\n",sasl_errstring(result,NULL,NULL));
1476		fatal("sasl_server_step() error");
1477	    }
1478	}
1479	mystep++;
1480
1481    }
1482
1483    if(need_another_client) {
1484	result = sasl_client_step(clientconn,
1485				  out, outlen,
1486				  &client_interact,
1487				  &out2, &outlen2);
1488	if(result != SASL_OK)
1489	    fatal("client was not ok on last server step");
1490    }
1491
1492    if (reauth) {
1493 	sasl_dispose(&clientconn);
1494 	sasl_dispose(&saslconn);
1495
1496 	reauth = 0;
1497 	goto reauth;
1498    }
1499
1500    /* client to server */
1501    result = sasl_encode(clientconn, CLIENT_TO_SERVER,
1502			 (unsigned) strlen(CLIENT_TO_SERVER), &out, &outlen);
1503    if (result != SASL_OK) fatal("Error encoding");
1504
1505    if (mystep == send->step)
1506    {
1507	memcpy(buf, out, outlen);
1508	corrupt(send->type, buf, outlen, &tmp, &outlen);
1509	out = tmp;
1510	mayfail = 1;
1511    }
1512
1513    result = sasl_decode(saslconn, out, outlen, &dec, &declen);
1514
1515    if (mayfail == 1)
1516    {
1517	if (result >= 0)
1518	    printf("WARNING: We did a corruption but it still worked\n");
1519	else {
1520	    goto done;
1521	}
1522    } else {
1523	if (result < 0)
1524	{
1525	    printf("%s\n",sasl_errstring(result,NULL,NULL));
1526	    fatal("sasl_decode() failure");
1527	}
1528    }
1529    mystep++;
1530
1531    /* no need to do other direction since symetric */
1532
1533    /* Just verify oparams */
1534    if(sasl_getprop(saslconn, SASL_USERNAME, (const void **)&out)
1535       != SASL_OK) {
1536	fatal("couldn't get server username");
1537	goto done;
1538    }
1539    if(sasl_getprop(clientconn, SASL_USERNAME, (const void **)&out2)
1540       != SASL_OK) {
1541	fatal("couldn't get client username");
1542	goto done;
1543    }
1544    if(strcmp(out,out2)) {
1545	fatal("client username does not match server username");
1546	goto done;
1547    }
1548
1549    printf("%s --> %s (as %s)\n",mech,sasl_errstring(result,NULL,NULL),out);
1550
1551 done:
1552    sasl_dispose(&clientconn);
1553    sasl_dispose(&saslconn);
1554    sasl_done();
1555}
1556
1557/* Authenticate two sasl_conn_t's to eachother, validly.
1558 * used to test the security layer */
1559int doauth(char *mech, sasl_conn_t **server_conn, sasl_conn_t **client_conn,
1560           const sasl_security_properties_t *props,
1561	   sasl_callback_t *c_calls, int fail_ok)
1562{
1563    int result, need_another_client = 0;
1564    sasl_conn_t *saslconn;
1565    sasl_conn_t *clientconn;
1566    const char *out, *out2;
1567    unsigned outlen, outlen2;
1568    sasl_interact_t *client_interact=NULL;
1569    const char *mechusing;
1570    const char *service = "rcmd";
1571    struct sockaddr_in addr;
1572    struct hostent *hp;
1573    char buf[8192];
1574
1575    if(!server_conn || !client_conn) return SASL_BADPARAM;
1576
1577    if (strncmp(mech,"GSS",3)==0) service = gssapi_service;
1578
1579    result = sasl_client_init((c_calls ? c_calls : client_interactions));
1580    if (result!=SASL_OK) {
1581	if(!fail_ok) fatal("Unable to init client");
1582	else return result;
1583    }
1584
1585    if(proxyflag == 0) {
1586        result = sasl_server_init(goodsasl_cb,"TestSuite");
1587    } else {
1588        result = sasl_server_init(goodsaslproxy_cb,"TestSuite");
1589    }
1590    if(result != SASL_OK) {
1591       if(!fail_ok) fatal("unable to init server");
1592       else return result;
1593    }
1594
1595
1596    if ((hp = gethostbyname(myhostname)) == NULL) {
1597	perror("gethostbyname");
1598	if(!fail_ok) fatal("can't gethostbyname");
1599	else return SASL_FAIL;
1600    }
1601
1602    addr.sin_family = 0;
1603    memcpy(&addr.sin_addr, hp->h_addr, hp->h_length);
1604    addr.sin_port = htons(0);
1605
1606    sprintf(buf,"%s;%d", inet_ntoa(addr.sin_addr), 0);
1607
1608    /* client new connection */
1609    result = sasl_client_new(service,
1610			     myhostname,
1611			     buf, buf, NULL,
1612			     0,
1613			     &clientconn);
1614    if(result != SASL_OK) {
1615	if(!fail_ok) fatal("sasl_client_new() failure");
1616	else return result;
1617    }
1618
1619    /* Set the security properties */
1620    set_properties(clientconn, props);
1621
1622    result = sasl_server_new(service, myhostname, NULL,
1623			     buf, buf, NULL, 0,
1624			     &saslconn);
1625    if(result != SASL_OK) {
1626	if(!fail_ok) fatal("can't sasl_server_new");
1627	else return result;
1628    }
1629    set_properties(saslconn, props);
1630
1631    do {
1632	result = sasl_client_start(clientconn, mech,
1633				   &client_interact,
1634				   &out, &outlen,
1635				   &mechusing);
1636
1637	if (result == SASL_INTERACT) fillin_correctly(client_interact);
1638	else if(result == SASL_CONTINUE) need_another_client = 1;
1639	else if(result == SASL_OK) need_another_client = 0;
1640    } while (result == SASL_INTERACT);
1641
1642    if (result < 0)
1643    {
1644	if(!fail_ok) fatal("sasl_client_start() error");
1645	else return result;
1646    }
1647
1648    result = sasl_server_start(saslconn,
1649			       mech,
1650			       out,
1651			       outlen,
1652			       &out,
1653			       &outlen);
1654
1655    if (result < 0)
1656    {
1657	if(!fail_ok) fatal("sasl_server_start() error");
1658	else return result;
1659    }
1660
1661    while (result == SASL_CONTINUE) {
1662	do {
1663	    result = sasl_client_step(clientconn,
1664				      out, outlen,
1665				      &client_interact,
1666				      &out2, &outlen2);
1667
1668	    if (result == SASL_INTERACT)
1669		fillin_correctly(client_interact);
1670	    else if (result == SASL_CONTINUE)
1671		need_another_client = 1;
1672	    else if (result == SASL_OK)
1673		need_another_client = 0;
1674	} while (result == SASL_INTERACT);
1675
1676	if (result < 0)
1677	{
1678	    if(!fail_ok) fatal("sasl_client_step() error");
1679	    else return result;
1680	}
1681
1682	out=out2;
1683	outlen=outlen2;
1684
1685	result = sasl_server_step(saslconn,
1686				  out,
1687				  outlen,
1688				  &out,
1689				  &outlen);
1690
1691	if (result < 0)
1692	{
1693	    if(!fail_ok) fatal("sasl_server_step() error");
1694	    else return result;
1695	}
1696
1697    }
1698
1699    if(need_another_client) {
1700	if(!fail_ok) fatal("server-last not allowed, but need another client call");
1701	else return SASL_BADPROT;
1702    }
1703
1704    *server_conn = saslconn;
1705    *client_conn = clientconn;
1706
1707    return SASL_OK;
1708}
1709
1710/* Authenticate two sasl_conn_t's to eachother, validly.
1711 * without allowing client-send-first */
1712int doauth_noclientfirst(char *mech, sasl_conn_t **server_conn,
1713			 sasl_conn_t **client_conn,
1714			 const sasl_security_properties_t *props,
1715			 sasl_callback_t *c_calls)
1716{
1717    int result, need_another_client = 0;
1718    sasl_conn_t *saslconn;
1719    sasl_conn_t *clientconn;
1720    const char *out, *out2;
1721    unsigned outlen, outlen2;
1722    sasl_interact_t *client_interact=NULL;
1723    const char *mechusing;
1724    const char *service = "rcmd";
1725
1726    struct sockaddr_in addr;
1727    struct hostent *hp;
1728    char buf[8192];
1729
1730    if(!server_conn || !client_conn) return SASL_BADPARAM;
1731
1732    if (strncmp(mech,"GSS",3)==0) service = gssapi_service;
1733
1734
1735    if (sasl_client_init((c_calls ? c_calls : client_interactions))!=SASL_OK)
1736	fatal("Unable to init client");
1737
1738    if (sasl_server_init(goodsasl_cb,"TestSuite")!=SASL_OK)
1739        fatal("unable to init server");
1740
1741    if ((hp = gethostbyname(myhostname)) == NULL) {
1742	perror("gethostbyname");
1743	fatal("can't gethostbyname");
1744    }
1745
1746    addr.sin_family = 0;
1747    memcpy(&addr.sin_addr, hp->h_addr, hp->h_length);
1748    addr.sin_port = htons(0);
1749
1750    sprintf(buf,"%s;%d", inet_ntoa(addr.sin_addr), 0);
1751
1752    /* client new connection */
1753    if (sasl_client_new(service,
1754			myhostname,
1755			buf, buf, NULL,
1756			0,
1757			&clientconn)!= SASL_OK) fatal("sasl_client_new() failure");
1758
1759    /* Set the security properties */
1760    set_properties(clientconn, props);
1761
1762    if (sasl_server_new(service, myhostname, NULL,
1763			buf, buf, NULL, 0,
1764			&saslconn) != SASL_OK) {
1765	fatal("can't sasl_server_new");
1766    }
1767    set_properties(saslconn, props);
1768
1769    do {
1770	result = sasl_client_start(clientconn, mech,
1771				   &client_interact,
1772				   NULL, NULL,
1773				   &mechusing);
1774
1775	if (result == SASL_INTERACT) fillin_correctly(client_interact);
1776	else if(result == SASL_CONTINUE) need_another_client = 1;
1777	else if(result == SASL_OK) need_another_client = 0;
1778    } while (result == SASL_INTERACT);
1779
1780    if (result < 0)
1781    {
1782	fatal("sasl_client_start() error");
1783    }
1784
1785    result = sasl_server_start(saslconn,
1786			       mech,
1787			       NULL,
1788			       0,
1789			       &out,
1790			       &outlen);
1791
1792    if (result < 0)
1793    {
1794	fatal("sasl_server_start() error");
1795    }
1796
1797    while (result == SASL_CONTINUE) {
1798	do {
1799	    result = sasl_client_step(clientconn,
1800				      out, outlen,
1801				      &client_interact,
1802				      &out2, &outlen2);
1803
1804	    if (result == SASL_INTERACT)
1805		fillin_correctly(client_interact);
1806	    else if (result == SASL_CONTINUE)
1807		need_another_client = 1;
1808	    else if (result == SASL_OK)
1809		need_another_client = 0;
1810	} while (result == SASL_INTERACT);
1811
1812	if (result < 0)
1813	{
1814	    fatal("sasl_client_step() error");
1815	}
1816
1817	out=out2;
1818	outlen=outlen2;
1819
1820	result = sasl_server_step(saslconn,
1821				  out,
1822				  outlen,
1823				  &out,
1824				  &outlen);
1825
1826	if (result < 0)
1827	{
1828	    fatal("sasl_server_step() error");
1829	}
1830
1831    }
1832
1833    if(need_another_client) {
1834	fatal("server-last not allowed, but need another client call");
1835    }
1836
1837    *server_conn = saslconn;
1838    *client_conn = clientconn;
1839
1840    return SASL_OK;
1841}
1842
1843/* Authenticate two sasl_conn_t's to eachother, validly.
1844 * used to test the security layer */
1845int doauth_serverlast(char *mech, sasl_conn_t **server_conn,
1846		      sasl_conn_t **client_conn,
1847		      const sasl_security_properties_t *props,
1848		      sasl_callback_t *c_calls)
1849{
1850    int result, need_another_client = 0;
1851    sasl_conn_t *saslconn;
1852    sasl_conn_t *clientconn;
1853    const char *out, *out2;
1854    unsigned outlen, outlen2;
1855    sasl_interact_t *client_interact=NULL;
1856    const char *mechusing;
1857    const char *service = "rcmd";
1858
1859    struct sockaddr_in addr;
1860    struct hostent *hp;
1861    char buf[8192];
1862
1863    if(!server_conn || !client_conn) return SASL_BADPARAM;
1864
1865    if (strncmp(mech,"GSS",3)==0) service = gssapi_service;
1866
1867    if (sasl_client_init((c_calls ? c_calls : client_interactions))!=SASL_OK)
1868	fatal("unable to init client");
1869
1870    if (sasl_server_init(goodsasl_cb,"TestSuite")!=SASL_OK)
1871	fatal("unable to init server");
1872
1873    if ((hp = gethostbyname(myhostname)) == NULL) {
1874	perror("gethostbyname");
1875	fatal("can't gethostbyname");
1876    }
1877
1878    addr.sin_family = 0;
1879    memcpy(&addr.sin_addr, hp->h_addr, hp->h_length);
1880    addr.sin_port = htons(0);
1881
1882    sprintf(buf,"%s;%d", inet_ntoa(addr.sin_addr), 0);
1883
1884    /* client new connection */
1885    if (sasl_client_new(service,
1886			myhostname,
1887			buf, buf, NULL,
1888			SASL_SUCCESS_DATA,
1889			&clientconn)!= SASL_OK) fatal("sasl_client_new() failure");
1890
1891    /* Set the security properties */
1892    set_properties(clientconn, props);
1893
1894    if (sasl_server_new(service, myhostname, NULL,
1895			buf, buf, NULL, SASL_SUCCESS_DATA,
1896			&saslconn) != SASL_OK) {
1897	fatal("can't sasl_server_new");
1898    }
1899    set_properties(saslconn, props);
1900
1901    do {
1902	result = sasl_client_start(clientconn, mech,
1903				   &client_interact,
1904				   &out, &outlen,
1905				   &mechusing);
1906
1907	if (result == SASL_INTERACT) fillin_correctly(client_interact);
1908	else if(result == SASL_CONTINUE) need_another_client = 1;
1909	else if(result == SASL_OK) need_another_client = 0;
1910    } while (result == SASL_INTERACT);
1911
1912
1913    if (result < 0)
1914    {
1915	fatal("sasl_client_start() error");
1916    }
1917
1918    result = sasl_server_start(saslconn,
1919			       mech,
1920			       out,
1921			       outlen,
1922			       &out,
1923			       &outlen);
1924
1925    if (result < 0)
1926    {
1927	fatal("sasl_server_start() error");
1928    }
1929
1930    while (result == SASL_CONTINUE) {
1931	do {
1932	    result = sasl_client_step(clientconn,
1933				      out, outlen,
1934				      &client_interact,
1935				      &out2, &outlen2);
1936
1937	    if (result == SASL_INTERACT)
1938		fillin_correctly(client_interact);
1939	    else if (result == SASL_CONTINUE)
1940		need_another_client = 1;
1941	    else if (result == SASL_OK)
1942		need_another_client = 0;
1943	} while (result == SASL_INTERACT);
1944
1945	if (result < 0)
1946	{
1947	    fatal("sasl_client_step() error");
1948	}
1949
1950	out=out2;
1951	outlen=outlen2;
1952
1953	result = sasl_server_step(saslconn,
1954				  out,
1955				  outlen,
1956				  &out,
1957				  &outlen);
1958
1959	if (result < 0)
1960	{
1961	    fatal("sasl_server_step() error");
1962	}
1963
1964    }
1965
1966    if(need_another_client) {
1967	result = sasl_client_step(clientconn,
1968				  out, outlen,
1969				  &client_interact,
1970				  &out2, &outlen2);
1971	if(result != SASL_OK)
1972	    fatal("client was not ok on last server step");
1973    }
1974
1975    *server_conn = saslconn;
1976    *client_conn = clientconn;
1977
1978    return SASL_OK;
1979}
1980
1981/* Authenticate two sasl_conn_t's to eachother, validly.
1982 * without allowing client-send-first */
1983int doauth_noclientfirst_andserverlast(char *mech, sasl_conn_t **server_conn,
1984				       sasl_conn_t **client_conn,
1985				       const sasl_security_properties_t *props,
1986				       sasl_callback_t *c_calls)
1987{
1988    int result, need_another_client = 0;
1989    sasl_conn_t *saslconn;
1990    sasl_conn_t *clientconn;
1991    const char *out, *out2;
1992    unsigned outlen, outlen2;
1993    sasl_interact_t *client_interact=NULL;
1994    const char *mechusing;
1995    const char *service = "rcmd";
1996
1997    struct sockaddr_in addr;
1998    struct hostent *hp;
1999    char buf[8192];
2000
2001    if(!server_conn || !client_conn) return SASL_BADPARAM;
2002
2003    if (strncmp(mech,"GSS",3)==0) service = gssapi_service;
2004
2005    if (sasl_client_init((c_calls ? c_calls : client_interactions))!=SASL_OK)
2006	fatal("unable to init client");
2007
2008    if (sasl_server_init(goodsasl_cb,"TestSuite")!=SASL_OK)
2009	fatal("unable to init server");
2010
2011    if ((hp = gethostbyname(myhostname)) == NULL) {
2012	perror("gethostbyname");
2013	fatal("can't gethostbyname");
2014    }
2015
2016    addr.sin_family = 0;
2017    memcpy(&addr.sin_addr, hp->h_addr, hp->h_length);
2018    addr.sin_port = htons(0);
2019
2020    sprintf(buf,"%s;%d", inet_ntoa(addr.sin_addr), 0);
2021
2022    /* client new connection */
2023    if (sasl_client_new(service,
2024			myhostname,
2025			buf, buf, NULL,
2026			SASL_SUCCESS_DATA,
2027			&clientconn)!= SASL_OK) fatal("sasl_client_new() failure");
2028
2029    /* Set the security properties */
2030    set_properties(clientconn, props);
2031
2032    if (sasl_server_new(service, myhostname, NULL,
2033			buf, buf, NULL, SASL_SUCCESS_DATA,
2034			&saslconn) != SASL_OK) {
2035	fatal("can't sasl_server_new");
2036    }
2037    set_properties(saslconn, props);
2038
2039    do {
2040	result = sasl_client_start(clientconn, mech,
2041				   &client_interact,
2042				   NULL, NULL,
2043				   &mechusing);
2044
2045	if (result == SASL_INTERACT) fillin_correctly(client_interact);
2046	else if(result == SASL_CONTINUE) need_another_client = 1;
2047	else if(result == SASL_OK) need_another_client = 0;
2048    } while (result == SASL_INTERACT);
2049
2050    if (result < 0)
2051    {
2052	fatal("sasl_client_start() error");
2053    }
2054
2055    result = sasl_server_start(saslconn,
2056			       mech,
2057			       NULL,
2058			       0,
2059			       &out,
2060			       &outlen);
2061
2062    if (result < 0)
2063    {
2064	fatal("sasl_server_start() error");
2065    }
2066
2067    while (result == SASL_CONTINUE) {
2068	do {
2069	    result = sasl_client_step(clientconn,
2070				      out, outlen,
2071				      &client_interact,
2072				      &out2, &outlen2);
2073
2074	    if (result == SASL_INTERACT)
2075		fillin_correctly(client_interact);
2076	    else if (result == SASL_CONTINUE)
2077		need_another_client = 1;
2078	    else if (result == SASL_OK)
2079		need_another_client = 0;
2080	} while (result == SASL_INTERACT);
2081
2082	if (result < 0)
2083	{
2084	    fatal("sasl_client_step() error");
2085	}
2086
2087	out=out2;
2088	outlen=outlen2;
2089
2090	result = sasl_server_step(saslconn,
2091				  out,
2092				  outlen,
2093				  &out,
2094				  &outlen);
2095
2096	if (result < 0)
2097	{
2098	    fatal("sasl_server_step() error");
2099	}
2100
2101    }
2102
2103    if(need_another_client) {
2104	result = sasl_client_step(clientconn,
2105				  out, outlen,
2106				  &client_interact,
2107				  &out2, &outlen2);
2108	if(result != SASL_OK)
2109	    fatal("client was not ok on last server step");
2110    }
2111
2112    *server_conn = saslconn;
2113    *client_conn = clientconn;
2114
2115    return SASL_OK;
2116}
2117
2118void cleanup_auth(sasl_conn_t **client, sasl_conn_t **server)
2119{
2120    sasl_dispose(client);
2121    sasl_dispose(server);
2122    sasl_done();
2123}
2124
2125
2126const sasl_security_properties_t int_only = {
2127    0,
2128    1,
2129    8192,
2130    0,
2131    NULL,
2132    NULL
2133};
2134
2135const sasl_security_properties_t force_des = {
2136    0,
2137    55,
2138    8192,
2139    0,
2140    NULL,
2141    NULL
2142};
2143
2144const sasl_security_properties_t force_rc4_56 = {
2145    0,
2146    56,
2147    8192,
2148    0,
2149    NULL,
2150    NULL
2151};
2152
2153const sasl_security_properties_t force_3des = {
2154    0,
2155    112,
2156    8192,
2157    0,
2158    NULL,
2159    NULL
2160};
2161
2162
2163const sasl_security_properties_t no_int = {
2164    2,
2165    256,
2166    8192,
2167    0,
2168    NULL,
2169    NULL
2170};
2171
2172const sasl_security_properties_t disable_seclayer = {
2173    0,
2174    256,
2175    0,
2176    0,
2177    NULL,
2178    NULL
2179};
2180
2181void do_proxypolicy_test(char *mech, void *rock __attribute__((unused)))
2182{
2183    sasl_conn_t *sconn, *cconn;
2184    const char *username;
2185
2186    printf("%s --> start\n", mech);
2187    proxyflag = 1;
2188    if(doauth(mech, &sconn, &cconn, &security_props, NULL, 0) != SASL_OK) {
2189	fatal("doauth failed in do_proxypolicy_test");
2190    }
2191
2192    if(sasl_getprop(sconn, SASL_USERNAME, (const void **)&username) != SASL_OK)
2193    {
2194	fatal("getprop failed in do_proxypolicy_test");
2195    }
2196
2197    if(strcmp(username, proxyasname)) {
2198	printf("Warning: Server Authorization Name != proxyasuser\n");
2199    }
2200
2201    cleanup_auth(&cconn, &sconn);
2202    proxyflag = 0;
2203    printf("%s --> successful result\n",mech);
2204}
2205
2206void test_clientfirst(char *mech, void *rock)
2207{
2208    sasl_conn_t *sconn, *cconn;
2209    tosend_t *tosend = (tosend_t *)rock;
2210
2211    printf("%s --> start\n", mech);
2212
2213    /* Basic crash-tests (none should cause a crash): */
2214    if(doauth(mech, &sconn, &cconn, &security_props, tosend->client_callbacks,
2215	      0) != SASL_OK) {
2216	fatal("doauth failed in test_clientfirst");
2217    }
2218
2219    cleanup_auth(&cconn, &sconn);
2220
2221    printf("%s --> successful result\n", mech);
2222}
2223
2224void test_noclientfirst(char *mech, void *rock)
2225{
2226    sasl_conn_t *sconn, *cconn;
2227    tosend_t *tosend = (tosend_t *)rock;
2228
2229    printf("%s --> start\n", mech);
2230
2231    /* Basic crash-tests (none should cause a crash): */
2232    if(doauth_noclientfirst(mech, &sconn, &cconn, &security_props,
2233	tosend->client_callbacks) != SASL_OK) {
2234	fatal("doauth failed in test_noclientfirst");
2235    }
2236
2237    cleanup_auth(&cconn, &sconn);
2238
2239    printf("%s --> successful result\n", mech);
2240}
2241
2242void test_serverlast(char *mech, void *rock)
2243{
2244    sasl_conn_t *sconn, *cconn;
2245    tosend_t *tosend = (tosend_t *)rock;
2246
2247    printf("%s --> start\n", mech);
2248
2249    /* Basic crash-tests (none should cause a crash): */
2250    if(doauth_serverlast(mech, &sconn, &cconn, &security_props,
2251			 tosend->client_callbacks) != SASL_OK) {
2252	fatal("doauth failed in test_serverlast");
2253    }
2254
2255    cleanup_auth(&cconn, &sconn);
2256
2257    printf("%s --> successful result\n", mech);
2258}
2259
2260
2261void test_noclientfirst_andserverlast(char *mech, void *rock)
2262{
2263    sasl_conn_t *sconn, *cconn;
2264    tosend_t *tosend = (tosend_t *)rock;
2265
2266    printf("%s --> start\n", mech);
2267
2268    /* Basic crash-tests (none should cause a crash): */
2269    if(doauth_noclientfirst_andserverlast(mech, &sconn, &cconn,
2270					  &security_props,
2271					  tosend->client_callbacks)
2272       != SASL_OK) {
2273	fatal("doauth failed in test_noclientfirst_andserverlast");
2274    }
2275
2276    cleanup_auth(&cconn, &sconn);
2277
2278    printf("%s --> successful result\n", mech);
2279}
2280
2281void testseclayer(char *mech, void *rock __attribute__((unused)))
2282{
2283    sasl_conn_t *sconn, *cconn;
2284    int result;
2285    char buf[8192], buf2[8192];
2286    const char *txstring = "THIS IS A TEST";
2287    const char *out, *out2;
2288    char *tmp;
2289    const sasl_security_properties_t *test_props[7] =
2290                                          { &security_props,
2291					    &force_3des,
2292					    &force_rc4_56,
2293					    &force_des,
2294					    &int_only,
2295					    &no_int,
2296					    &disable_seclayer };
2297    const unsigned num_properties = 7;
2298    unsigned i;
2299    const sasl_ssf_t *this_ssf;
2300    unsigned outlen = 0, outlen2 = 0, totlen = 0;
2301
2302    printf("%s --> security layer start\n", mech);
2303
2304    for(i=0; i<num_properties; i++) {
2305
2306    /* Basic crash-tests (none should cause a crash): */
2307    result = doauth(mech, &sconn, &cconn, test_props[i], NULL, 1);
2308    if(result == SASL_NOMECH && test_props[i]->min_ssf > 0) {
2309	printf("  Testing SSF: SKIPPED (requested minimum > 0: %d)\n",
2310	       test_props[i]->min_ssf);
2311	cleanup_auth(&sconn, &cconn);
2312	continue;
2313    } else if(result != SASL_OK) {
2314	fatal("doauth failed in testseclayer");
2315    }
2316
2317    if(sasl_getprop(cconn, SASL_SSF, (const void **)&this_ssf) != SASL_OK) {
2318	fatal("sasl_getprop in testseclayer");
2319    }
2320
2321    if(*this_ssf != 0 && !test_props[i]->maxbufsize) {
2322	fatal("got nonzero SSF with zero maxbufsize");
2323    }
2324
2325    printf("  SUCCESS Testing SSF: %d (requested %d/%d with maxbufsize: %d)\n",
2326	   (unsigned)(*this_ssf),
2327	   test_props[i]->min_ssf, test_props[i]->max_ssf,
2328	   test_props[i]->maxbufsize);
2329
2330    if(!test_props[i]->maxbufsize) {
2331	result = sasl_encode(cconn, txstring, (unsigned) strlen(txstring),
2332			     &out, &outlen);
2333	if(result == SASL_OK) {
2334	    fatal("got OK when encoding with zero maxbufsize");
2335	}
2336	result = sasl_decode(sconn, "foo", 3, &out, &outlen);
2337	if(result == SASL_OK) {
2338	    fatal("got OK when decoding with zero maxbufsize");
2339	}
2340	cleanup_auth(&sconn, &cconn);
2341	continue;
2342    }
2343
2344    sasl_encode(NULL, txstring, (unsigned) strlen(txstring), &out, &outlen);
2345    sasl_encode(cconn, NULL, (unsigned) strlen(txstring), &out, &outlen);
2346    sasl_encode(cconn, txstring, 0, &out, &outlen);
2347    sasl_encode(cconn, txstring, (unsigned) strlen(txstring), NULL, &outlen);
2348    sasl_encode(cconn, txstring, (unsigned) strlen(txstring), &out, NULL);
2349
2350    sasl_decode(NULL, txstring, (unsigned) strlen(txstring), &out, &outlen);
2351    sasl_decode(cconn, NULL, (unsigned) strlen(txstring), &out, &outlen);
2352    sasl_decode(cconn, txstring, 0, &out, &outlen);
2353    sasl_decode(cconn, txstring, (unsigned)-1, &out, &outlen);
2354    sasl_decode(cconn, txstring, (unsigned) strlen(txstring), NULL, &outlen);
2355    sasl_decode(cconn, txstring, (unsigned) strlen(txstring), &out, NULL);
2356
2357    cleanup_auth(&sconn, &cconn);
2358
2359    /* Basic I/O Test */
2360    if(doauth(mech, &sconn, &cconn, test_props[i], NULL, 0) != SASL_OK) {
2361	fatal("doauth failed in testseclayer");
2362    }
2363
2364    result = sasl_encode(cconn, txstring, (unsigned) strlen(txstring),
2365			 &out, &outlen);
2366    if(result != SASL_OK) {
2367	fatal("basic sasl_encode failure");
2368    }
2369
2370    result = sasl_decode(sconn, out, outlen, &out, &outlen);
2371    if(result != SASL_OK) {
2372	fatal("basic sasl_decode failure");
2373    }
2374
2375    cleanup_auth(&sconn, &cconn);
2376
2377    /* Split one block and reassemble */
2378    if(doauth(mech, &sconn, &cconn, test_props[i], NULL, 0) != SASL_OK) {
2379	fatal("doauth failed in testseclayer");
2380    }
2381
2382    result = sasl_encode(cconn, txstring, (unsigned) strlen(txstring),
2383			 &out, &outlen);
2384    if(result != SASL_OK) {
2385	fatal("basic sasl_encode failure (2)");
2386    }
2387
2388    memcpy(buf, out, 5);
2389    buf[5] = '\0';
2390
2391    out += 5;
2392
2393    result = sasl_decode(sconn, buf, 5, &out2, &outlen2);
2394    if(result != SASL_OK) {
2395	printf("Failed with: %s\n", sasl_errstring(result, NULL, NULL));
2396	fatal("sasl_decode failure part 1/2");
2397    }
2398
2399    memset(buf2, 0, 8192);
2400    if(outlen2)
2401        memcpy(buf2, out2, outlen2);
2402
2403    result = sasl_decode(sconn, out, outlen - 5, &out, &outlen);
2404    if(result != SASL_OK) {
2405	fatal("sasl_decode failure part 2/2");
2406    }
2407
2408    strcat(buf2, out);
2409    if(strcmp(buf2, txstring)) {
2410	printf("Exptected '%s' but got '%s'\n", txstring, buf2);
2411	fatal("did not get correct string back after 2 sasl_decodes");
2412    }
2413
2414    cleanup_auth(&sconn, &cconn);
2415
2416    /* Combine 2 blocks */
2417    if(doauth(mech, &sconn, &cconn, test_props[i], NULL, 0) != SASL_OK) {
2418	fatal("doauth failed in testseclayer");
2419    }
2420
2421    result = sasl_encode(cconn, txstring, (unsigned) strlen(txstring),
2422			 &out, &outlen);
2423    if(result != SASL_OK) {
2424	fatal("basic sasl_encode failure (3)");
2425    }
2426
2427    memcpy(buf, out, outlen);
2428
2429    tmp = buf + outlen;
2430    totlen = outlen;
2431
2432    result = sasl_encode(cconn, txstring, (unsigned) strlen(txstring),
2433			 &out, &outlen);
2434    if(result != SASL_OK) {
2435	fatal("basic sasl_encode failure (4)");
2436    }
2437
2438    memcpy(tmp, out, outlen);
2439    totlen += outlen;
2440
2441    result = sasl_decode(sconn, buf, totlen, &out, &outlen);
2442    if(result != SASL_OK) {
2443	printf("Failed with: %s\n", sasl_errstring(result, NULL, NULL));
2444	fatal("sasl_decode failure (2 blocks)");
2445    }
2446
2447    sprintf(buf2, "%s%s", txstring, txstring);
2448
2449    if(strcmp(out, buf2)) {
2450	fatal("did not get correct string back (2 blocks)");
2451    }
2452
2453    cleanup_auth(&sconn, &cconn);
2454
2455    /* Combine 2 blocks with 1 split */
2456    if(doauth(mech, &sconn, &cconn, test_props[i], NULL, 0) != SASL_OK) {
2457	fatal("doauth failed in testseclayer");
2458    }
2459
2460    result = sasl_encode(cconn, txstring, (unsigned) strlen(txstring),
2461			 &out, &outlen);
2462    if(result != SASL_OK) {
2463	fatal("basic sasl_encode failure (3)");
2464    }
2465
2466    memcpy(buf, out, outlen);
2467
2468    tmp = buf + outlen;
2469
2470    result = sasl_encode(cconn, txstring, (unsigned) strlen(txstring),
2471			 &out2, &outlen2);
2472    if(result != SASL_OK) {
2473	fatal("basic sasl_encode failure (4)");
2474    }
2475
2476    memcpy(tmp, out2, 5);
2477    tmp[5] = '\0';
2478    outlen += 5;
2479
2480    outlen2 -= 5;
2481    out2 += 5;
2482
2483    result = sasl_decode(sconn, buf, outlen, &out, &outlen);
2484    if(result != SASL_OK) {
2485	printf("Failed with: %s\n", sasl_errstring(result, NULL, NULL));
2486	fatal("sasl_decode failure 1/2 (2 blocks, 1 split)");
2487    }
2488
2489    memset(buf2, 0, 8192);
2490    memcpy(buf2, out, outlen);
2491
2492    tmp = buf2 + outlen;
2493
2494    result = sasl_decode(sconn, out2, outlen2, &out, &outlen);
2495    if(result != SASL_OK) {
2496	printf("Failed with: %s\n", sasl_errstring(result, NULL, NULL));
2497	fatal("sasl_decode failure 2/2 (2 blocks, 1 split)");
2498    }
2499
2500    memcpy(tmp, out, outlen);
2501
2502    sprintf(buf, "%s%s", txstring, txstring);
2503    if(strcmp(buf, buf2)) {
2504	fatal("did not get correct string back (2 blocks, 1 split)");
2505    }
2506
2507    cleanup_auth(&sconn, &cconn);
2508
2509    } /* for each properties type we want to test */
2510
2511    printf("%s --> security layer OK\n", mech);
2512
2513}
2514
2515
2516/*
2517 * Apply the given function to each machanism
2518 */
2519
2520void foreach_mechanism(foreach_t *func, void *rock)
2521{
2522    const char *out;
2523    char *str, *start;
2524    sasl_conn_t *saslconn;
2525    int result;
2526    struct sockaddr_in addr;
2527    struct hostent *hp;
2528    unsigned len;
2529    char buf[8192];
2530
2531    /* Get the list of mechanisms */
2532    sasl_done();
2533
2534    if (sasl_server_init(emptysasl_cb,"TestSuite")!=SASL_OK)
2535	fatal("sasl_server_init failed in foreach_mechanism");
2536
2537    if ((hp = gethostbyname(myhostname)) == NULL) {
2538        perror("gethostbyname");
2539        fatal("can't gethostbyname");
2540    }
2541
2542    addr.sin_family = 0;
2543    memcpy(&addr.sin_addr, hp->h_addr, hp->h_length);
2544    addr.sin_port = htons(0);
2545
2546    sprintf(buf,"%s;%d", inet_ntoa(addr.sin_addr), 0);
2547
2548    if (sasl_server_new("rcmd", myhostname, NULL,
2549			buf, buf, NULL, 0,
2550			&saslconn) != SASL_OK) {
2551	fatal("sasl_server_new in foreach_mechanism");
2552    }
2553
2554    if (sasl_setprop(saslconn, SASL_AUTH_EXTERNAL, authname)!=SASL_OK)
2555	fatal("sasl_setprop(SASL_AUTH_EXTERNAL) failed");
2556
2557    result = sasl_listmech(saslconn,
2558			   NULL,
2559			   "",
2560			   "\n",
2561			   "",
2562			   &out,
2563			   &len,
2564			   NULL);
2565
2566    if(result != SASL_OK) {
2567	fatal("sasl_listmech in foreach_mechanism");
2568    }
2569
2570    memcpy(buf, out, len + 1);
2571
2572    sasl_dispose(&saslconn);
2573    sasl_done();
2574
2575    /* call the function for each mechanism */
2576    start = str = buf;
2577    while (*start != '\0')
2578    {
2579	while ((*str != '\n') && (*str != '\0'))
2580	    str++;
2581
2582	if (*str == '\n')
2583	{
2584	    *str = '\0';
2585	    str++;
2586	}
2587
2588	func(start, rock);
2589
2590	start = str;
2591    }
2592}
2593
2594void test_serverstart()
2595{
2596    int result;
2597    sasl_conn_t *saslconn;
2598    const char *out;
2599    unsigned outlen;
2600    struct sockaddr_in addr;
2601    struct hostent *hp;
2602    char buf[8192];
2603
2604    if (sasl_server_init(emptysasl_cb,"TestSuite")!=SASL_OK)
2605	fatal("can't sasl_server_init in test_serverstart");
2606
2607    if ((hp = gethostbyname(myhostname)) == NULL) {
2608        perror("gethostbyname");
2609        fatal("can't gethostbyname in test_serverstart");
2610    }
2611
2612    addr.sin_family = 0;
2613    memcpy(&addr.sin_addr, hp->h_addr, hp->h_length);
2614    addr.sin_port = htons(0);
2615
2616    sprintf(buf,"%s;%d", inet_ntoa(addr.sin_addr), 0);
2617
2618    if (sasl_server_new("rcmd", myhostname, NULL,
2619			buf, buf, NULL, 0,
2620			&saslconn) != SASL_OK) {
2621	fatal("can't sasl_server_new in test_serverstart");
2622    }
2623
2624
2625    /* Test null connection */
2626    result = sasl_server_start(NULL,
2627			       "foobar",
2628			       NULL,
2629			       0,
2630			       NULL,
2631			       NULL);
2632
2633    if (result == SASL_OK) fatal("Said ok to null sasl_conn_t in sasl_server_start()");
2634
2635    /* send plausible but invalid mechanism */
2636    result = sasl_server_start(saslconn,
2637			       "foobar",
2638			       NULL,
2639			       0,
2640			       &out,
2641			       &outlen);
2642
2643    if (result == SASL_OK) fatal("Said ok to invalid mechanism");
2644
2645    /* send really long and invalid mechanism */
2646    result = sasl_server_start(saslconn,
2647			       really_long_string,
2648			       NULL,
2649			       0,
2650			       &out,
2651			       &outlen);
2652
2653    if (result == SASL_OK) fatal("Said ok to invalid mechanism");
2654
2655    sasl_dispose(&saslconn);
2656    sasl_done();
2657}
2658
2659void test_rand_corrupt(unsigned steps)
2660{
2661    unsigned lup;
2662    tosend_t tosend;
2663
2664    for (lup=0;lup<steps;lup++)
2665    {
2666	tosend.type = rand() % CORRUPT_SIZE;
2667	tosend.step = lup % MAX_STEPS;
2668	tosend.client_callbacks = NULL;
2669
2670	printf("RANDOM TEST: (%s in step %d) (%d of %d)\n",corrupt_types[tosend.type],tosend.step,lup+1,steps);
2671	foreach_mechanism((foreach_t *) &sendbadsecond,&tosend);
2672    }
2673}
2674
2675void test_proxypolicy()
2676{
2677    foreach_mechanism((foreach_t *) &do_proxypolicy_test,NULL);
2678}
2679
2680void test_all_corrupt()
2681{
2682    tosend_t tosend;
2683    tosend.client_callbacks = NULL;
2684
2685    /* Start just beyond NOTHING */
2686    for(tosend.type=1; tosend.type<CORRUPT_SIZE; tosend.type++) {
2687	for(tosend.step=0; tosend.step<MAX_STEPS; tosend.step++) {
2688	    printf("TEST: %s in step %d:\n", corrupt_types[tosend.type],
2689		   tosend.step);
2690	    foreach_mechanism((foreach_t *) &sendbadsecond, &tosend);
2691	}
2692    }
2693}
2694
2695void test_seclayer()
2696{
2697    foreach_mechanism((foreach_t *) &testseclayer, NULL);
2698}
2699
2700void create_ids(void)
2701{
2702    sasl_conn_t *saslconn;
2703    int result;
2704    struct sockaddr_in addr;
2705    struct hostent *hp;
2706    char buf[8192];
2707#ifdef DO_SASL_CHECKAPOP
2708    int i;
2709    const char challenge[] = "<1896.697170952@cyrus.andrew.cmu.edu>";
2710    MD5_CTX ctx;
2711    unsigned char digest[16];
2712    char digeststr[32];
2713#endif
2714
2715    if (sasl_server_init(goodsasl_cb,"TestSuite")!=SASL_OK)
2716	fatal("can't sasl_server_init in create_ids");
2717
2718    if ((hp = gethostbyname(myhostname)) == NULL) {
2719        perror("gethostbyname");
2720        fatal("can't gethostbyname in create_ids");
2721    }
2722
2723    addr.sin_family = 0;
2724    memcpy(&addr.sin_addr, hp->h_addr, hp->h_length);
2725    addr.sin_port = htons(0);
2726
2727    sprintf(buf,"%s;%d", inet_ntoa(addr.sin_addr), 0);
2728
2729    if (sasl_server_new("rcmd", myhostname, NULL,
2730			buf, buf, NULL, 0,
2731			&saslconn) != SASL_OK)
2732	fatal("can't sasl_server_new in create_ids");
2733
2734    /* Try to set password then check it */
2735
2736    result = sasl_setpass(saslconn, username, password,
2737			  (unsigned) strlen(password),
2738			  NULL, 0, SASL_SET_CREATE);
2739    if (result != SASL_OK) {
2740	printf("error was %s (%d)\n",sasl_errstring(result,NULL,NULL),result);
2741	fatal("Error setting password. Do we have write access to sasldb?");
2742    }
2743
2744    result = sasl_checkpass(saslconn, username,
2745			    (unsigned) strlen(username),
2746			    password, (unsigned) strlen(password));
2747    if (result != SASL_OK) {
2748	fprintf(stderr, "%s\n", sasl_errdetail(saslconn));
2749	fatal("Unable to verify password we just set");
2750    }
2751    result = sasl_user_exists(saslconn, "imap", NULL, username);
2752    if(result != SASL_OK)
2753	fatal("sasl_user_exists did not find user");
2754
2755    result = sasl_user_exists(saslconn, "imap", NULL,
2756			      nonexistant_username);
2757    if(result == SASL_OK)
2758	fatal("sasl_user_exists found nonexistant username");
2759
2760    /* Test sasl_checkapop */
2761#ifdef DO_SASL_CHECKAPOP
2762    _sasl_MD5Init(&ctx);
2763    _sasl_MD5Update(&ctx,challenge,strlen(challenge));
2764    _sasl_MD5Update(&ctx,password,strlen(password));
2765    _sasl_MD5Final(digest, &ctx);
2766
2767    /* convert digest from binary to ASCII hex */
2768    for (i = 0; i < 16; i++)
2769      sprintf(digeststr + (i*2), "%02x", digest[i]);
2770
2771    sprintf(buf, "%s %s", username, digeststr);
2772
2773    result = sasl_checkapop(saslconn,
2774                            challenge, strlen(challenge),
2775                            buf, strlen(buf));
2776    if(result != SASL_OK)
2777        fatal("Unable to checkapop password we just set");
2778    /* End checkapop test */
2779#else /* Just check that checkapop is really turned off */
2780    if(sasl_checkapop(saslconn, NULL, 0, NULL, 0) == SASL_OK)
2781	fatal("sasl_checkapop seems to work but was disabled at compile time");
2782#endif
2783
2784    /* now delete user and make sure can't find him anymore */
2785    result = sasl_setpass(saslconn, username, password,
2786			  (unsigned) strlen(password),
2787			  NULL, 0, SASL_SET_DISABLE);
2788    if (result != SASL_OK)
2789	fatal("Error disabling password. Do we have write access to sasldb?");
2790
2791    result = sasl_checkpass(saslconn, username,
2792			    (unsigned) strlen(username),
2793			    password, (unsigned) strlen(password));
2794    if (result == SASL_OK) {
2795	printf("\n  WARNING: sasl_checkpass got SASL_OK after disableing\n");
2796	printf("           This is generally ok, just an artifact of sasldb\n");
2797	printf("           being an external verifier\n");
2798    }
2799
2800#ifdef DO_SASL_CHECKAPOP
2801    /* And checkapop... */
2802    result = sasl_checkapop(saslconn,
2803                            challenge, strlen(challenge),
2804                            buf, strlen(buf));
2805    if (result == SASL_OK) {
2806	printf("\n  WARNING: sasl_checkapop got SASL_OK after disableing\n");
2807	printf("           This is generally ok, just an artifact of sasldb\n");
2808	printf("           being an external verifier\n");
2809    }
2810#endif
2811
2812    /* try bad params */
2813    if (sasl_setpass(NULL,username, password,
2814		     (unsigned) strlen(password),
2815		     NULL, 0, SASL_SET_CREATE)==SASL_OK)
2816	fatal("Didn't specify saslconn");
2817    if (sasl_setpass(saslconn,username, password, 0, NULL, 0, SASL_SET_CREATE)==SASL_OK)
2818	fatal("Allowed password of zero length");
2819    if (sasl_setpass(saslconn,username, password,
2820		     (unsigned) strlen(password), NULL, 0, 43)==SASL_OK)
2821	fatal("Gave weird code");
2822
2823#ifndef SASL_NDBM
2824    if (sasl_setpass(saslconn,really_long_string,
2825		     password, (unsigned)strlen(password),
2826		     NULL, 0, SASL_SET_CREATE)!=SASL_OK)
2827	fatal("Didn't allow really long username");
2828#else
2829    printf("WARNING: skipping sasl_setpass() on really_long_string with NDBM\n");
2830#endif
2831
2832    if (sasl_setpass(saslconn,"bob",really_long_string,
2833		     (unsigned) strlen(really_long_string),NULL, 0,
2834		     SASL_SET_CREATE)!=SASL_OK)
2835	fatal("Didn't allow really long password");
2836
2837    result = sasl_setpass(saslconn,"frank",
2838			  password, (unsigned) strlen(password),
2839			  NULL, 0, SASL_SET_DISABLE);
2840
2841    if ((result!=SASL_NOUSER) && (result!=SASL_OK))
2842	{
2843	    printf("error = %d\n",result);
2844	    fatal("Disabling non-existant didn't return SASL_NOUSER");
2845	}
2846
2847    /* Now set the user again (we use for rest of program) */
2848    result = sasl_setpass(saslconn, username,
2849			  password, (unsigned) strlen(password),
2850			  NULL, 0, SASL_SET_CREATE);
2851    if (result != SASL_OK)
2852	fatal("Error setting password. Do we have write access to sasldb?");
2853
2854    /* cleanup */
2855    sasl_dispose(&saslconn);
2856    sasl_done();
2857}
2858
2859/*
2860 * Test the checkpass routine
2861 */
2862
2863void test_checkpass(void)
2864{
2865    sasl_conn_t *saslconn;
2866
2867    /* try without initializing anything */
2868    if(sasl_checkpass(NULL,
2869		      username,
2870		      (unsigned) strlen(username),
2871		      password,
2872		      (unsigned) strlen(password)) != SASL_NOTINIT) {
2873	fatal("sasl_checkpass() when library not initialized");
2874    }
2875
2876    if (sasl_server_init(goodsasl_cb,"TestSuite")!=SASL_OK)
2877	fatal("can't sasl_server_init in test_checkpass");
2878
2879    if (sasl_server_new("rcmd", myhostname,
2880			NULL, NULL, NULL, NULL, 0,
2881			&saslconn) != SASL_OK)
2882	fatal("can't sasl_server_new in test_checkpass");
2883
2884    /* make sure works for general case */
2885
2886    if (sasl_checkpass(saslconn, username, (unsigned) strlen(username),
2887		       password, (unsigned) strlen(password))!=SASL_OK)
2888	fatal("sasl_checkpass() failed on simple case");
2889
2890    /* NULL saslconn */
2891    if (sasl_checkpass(NULL, username, (unsigned) strlen(username),
2892		   password, (unsigned) strlen(password)) == SASL_OK)
2893	fatal("Suceeded with NULL saslconn");
2894
2895    /* NULL username -- should be OK if sasl_checkpass enabled */
2896    if (sasl_checkpass(saslconn, NULL, (unsigned) strlen(username),
2897		   password, (unsigned) strlen(password)) != SASL_OK)
2898	fatal("failed check if sasl_checkpass is enabled");
2899
2900    /* NULL password */
2901    if (sasl_checkpass(saslconn, username, (unsigned) strlen(username),
2902		   NULL, (unsigned) strlen(password)) == SASL_OK)
2903	fatal("Suceeded with NULL password");
2904
2905    sasl_dispose(&saslconn);
2906    sasl_done();
2907}
2908
2909
2910
2911void notes(void)
2912{
2913    printf("NOTE:\n");
2914    printf("-For KERBEROS_V4 must be able to read srvtab file (usually /etc/srvtab)\n");
2915    printf("-For GSSAPI must be able to read srvtab (/etc/krb5.keytab)\n");
2916    printf("-For both KERBEROS_V4 and GSSAPI you must have non-expired tickets\n");
2917    printf("-For OTP (w/OPIE) must be able to read/write opiekeys (/etc/opiekeys)\n");
2918    printf("-For OTP you must have a non-expired secret\n");
2919    printf("-Must be able to read sasldb, which needs to be setup with a\n");
2920    printf(" username and a password (see top of testsuite.c)\n");
2921    printf("\n\n");
2922}
2923
2924void usage(void)
2925{
2926    printf("Usage:\n" \
2927           " testsuite [-g name] [-s seed] [-r tests] -a -M\n" \
2928           "    g -- gssapi service name to use (default: host)\n" \
2929	   "    r -- # of random tests to do (default: 25)\n" \
2930	   "    a -- do all corruption tests (and ignores random ones unless -r specified)\n" \
2931	   "    n -- skip the initial \"do correctly\" tests\n"
2932	   "    h -- show this screen\n" \
2933           "    s -- random seed to use\n" \
2934	   "    M -- detailed memory debugging ON\n" \
2935           );
2936}
2937
2938int main(int argc, char **argv)
2939{
2940    char c;
2941    int random_tests = -1;
2942    int do_all = 0;
2943    int skip_do_correct = 0;
2944    unsigned int seed = (unsigned int) time(NULL);
2945#ifdef WIN32
2946  /* initialize winsock */
2947    int result;
2948    WSADATA wsaData;
2949
2950    result = WSAStartup( MAKEWORD(2, 0), &wsaData );
2951    if ( result != 0) {
2952	fatal("Windows sockets initialization failure");
2953    }
2954#endif
2955
2956    while ((c = getopt(argc, argv, "Ms:g:r:han")) != EOF)
2957	switch (c) {
2958	case 'M':
2959	    DETAILED_MEMORY_DEBUGGING = 1;
2960	    break;
2961	case 's':
2962	    seed = atoi(optarg);
2963	    break;
2964	case 'g':
2965	    gssapi_service = optarg;
2966	    break;
2967	case 'r':
2968	    random_tests = atoi(optarg);
2969	    break;
2970	case 'a':
2971	    random_tests = 0;
2972	    do_all = 1;
2973	    break;
2974	case 'n':
2975	    skip_do_correct = 1;
2976	    break;
2977	case 'h':
2978	    usage();
2979	    exit(0);
2980	    break;
2981	default:
2982	    usage();
2983	    fatal("Invalid parameter\n");
2984	    break;
2985    }
2986
2987    g_secret = malloc(sizeof(sasl_secret_t) + strlen(password));
2988    g_secret->len = (unsigned) strlen(password);
2989    strcpy(g_secret->data, password);
2990
2991    if(random_tests < 0) random_tests = 25;
2992
2993    notes();
2994
2995    init(seed);
2996
2997#if 0 /* Disabled because it is borked */
2998    printf("Creating id's in mechanisms (not in sasldb)...\n");
2999    create_ids();
3000    if(mem_stat() != SASL_OK) fatal("memory error");
3001    printf("Creating id's in mechanisms (not in sasldb)... ok\n");
3002#endif
3003
3004    printf("Checking plaintext passwords... ");
3005    test_checkpass();
3006    if(mem_stat() != SASL_OK) fatal("memory error");
3007    printf("ok\n");
3008
3009    printf("Random number functions... ");
3010    test_random();
3011    if(mem_stat() != SASL_OK) fatal("memory error");
3012    printf("ok\n");
3013
3014    printf("Testing base64 functions... ");
3015    test_64();
3016    if(mem_stat() != SASL_OK) fatal("memory error");
3017    printf("ok\n");
3018
3019    printf("Testing auxprop functions... ");
3020    test_props();
3021    if(mem_stat() != SASL_OK) fatal("memory error");
3022    printf("ok\n");
3023
3024    printf("Tests of sasl_{server|client}_init()... ");
3025    test_init();
3026    if(mem_stat() != SASL_OK) fatal("memory error");
3027    printf("ok\n");
3028
3029    printf("Testing sasl_listmech()... \n");
3030    test_listmech();
3031    if(mem_stat() != SASL_OK) fatal("memory error");
3032    printf("Testing sasl_listmech()... ok\n");
3033
3034    printf("Testing serverstart...");
3035    test_serverstart();
3036    if(mem_stat() != SASL_OK) fatal("memory error");
3037    printf("ok\n");
3038
3039    if(!skip_do_correct) {
3040	tosend_t tosend;
3041
3042	tosend.type = NOTHING;
3043	tosend.step = 500;
3044	tosend.client_callbacks = client_interactions;
3045
3046	printf("Testing client-first/no-server-last correctly...\n");
3047	foreach_mechanism((foreach_t *) &test_clientfirst,&tosend);
3048	if(mem_stat() != SASL_OK) fatal("memory error");
3049	printf("Test of client-first/no-server-last...ok\n");
3050
3051	printf("Testing no-client-first/no-server-last correctly...\n");
3052	foreach_mechanism((foreach_t *) &test_noclientfirst, &tosend);
3053	if(mem_stat() != SASL_OK) fatal("memory error");
3054	printf("Test of no-client-first/no-server-last...ok\n");
3055
3056	printf("Testing no-client-first/server-last correctly...\n");
3057	foreach_mechanism((foreach_t *) &test_noclientfirst_andserverlast,
3058			  &tosend);
3059	if(mem_stat() != SASL_OK) fatal("memory error");
3060	printf("Test of no-client-first/server-last...ok\n");
3061
3062	printf("Testing client-first/server-last correctly...\n");
3063	foreach_mechanism((foreach_t *) &test_serverlast, &tosend);
3064	if(mem_stat() != SASL_OK) fatal("memory error");
3065	printf("Test of client-first/server-last...ok\n");
3066
3067	tosend.client_callbacks = client_callbacks;
3068	printf("-=-=-=-=- And now using the callbacks interface -=-=-=-=-\n");
3069
3070	printf("Testing client-first/no-server-last correctly...\n");
3071	foreach_mechanism((foreach_t *) &test_clientfirst,&tosend);
3072	if(mem_stat() != SASL_OK) fatal("memory error");
3073	printf("Test of client-first/no-server-last...ok\n");
3074
3075	printf("Testing no-client-first/no-server-last correctly...\n");
3076	foreach_mechanism((foreach_t *) &test_noclientfirst, &tosend);
3077	if(mem_stat() != SASL_OK) fatal("memory error");
3078	printf("Test of no-client-first/no-server-last...ok\n");
3079
3080	printf("Testing no-client-first/server-last correctly...\n");
3081	foreach_mechanism((foreach_t *) &test_noclientfirst_andserverlast,
3082			  &tosend);
3083	if(mem_stat() != SASL_OK) fatal("memory error");
3084	printf("Test of no-client-first/server-last...ok\n");
3085
3086	printf("Testing client-first/server-last correctly...\n");
3087	foreach_mechanism((foreach_t *) &test_serverlast, &tosend);
3088	if(mem_stat() != SASL_OK) fatal("memory error");
3089	printf("Test of client-first/server-last...ok\n");
3090    } else {
3091	printf("Testing client-first/no-server-last correctly...skipped\n");
3092	printf("Testing no-client-first/no-server-last correctly...skipped\n");
3093	printf("Testing no-client-first/server-last correctly...skipped\n");
3094	printf("Testing client-first/server-last correctly...skipped\n");
3095	printf("Above tests with callbacks interface...skipped\n");
3096    }
3097
3098    /* FIXME: do memory tests below here on the things
3099     * that are MEANT to fail sometime. */
3100    if(do_all) {
3101	printf("All corruption tests...\n");
3102	test_all_corrupt();
3103	printf("All corruption tests... ok\n");
3104    }
3105
3106    if(random_tests) {
3107	printf("Random corruption tests...\n");
3108	test_rand_corrupt(random_tests);
3109	printf("Random tests... ok\n");
3110    } else {
3111	printf("Random tests... skipped\n");
3112    }
3113
3114    printf("Testing Proxy Policy...\n");
3115    test_proxypolicy();
3116    printf("Tests of Proxy Policy...ok\n");
3117
3118    printf("Testing security layer...\n");
3119    test_seclayer();
3120    printf("Tests of security layer... ok\n");
3121
3122    printf("All tests seemed to go ok (i.e. we didn't crash)\n");
3123
3124    free(g_secret);
3125
3126    exit(0);
3127}
3128