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