reindent-20030715
[openafs.git] / src / kauth / test / test_interim_ktc.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /* Test ktc related calls as well as some file access stuff. */
11
12 #include <sys/types.h>
13 #include <errno.h>
14 #include <stdio.h>
15 #include <sys/file.h>
16 #include <arpa/inet.h>
17 #include <afs/prs_fs.h>
18 #include <afsconfig.h>
19 #include <afs/param.h>
20
21 RCSID
22     ("$Header$");
23
24 #include <afs/stds.h>
25 #include <afs/com_err.h>
26 #include <afs/cellconfig.h>
27 #include <afs/auth.h>
28 #include "kautils.h"
29
30
31 extern int errno;
32
33 static char *whoami = "test_interim_ktc";
34 static verbose = 1;
35 #define CELLSTOKEEP 50
36 static char cell[MAXKTCREALMLEN];
37 static char cellNameList[CELLSTOKEEP][MAXKTCREALMLEN];
38 static int nCells = 0;
39 static int unusedCell;
40 static char tester[MAXKTCNAMELEN];
41 static char testerPassword[32];
42 static long testerId;
43 static char remoteTester[MAXKTCNAMELEN];
44 static char remoteTesterPassword[32];
45 static long remoteTesterId;
46
47 static void
48 PrintPrincipal(stream, p)
49      FILE *stream;
50      struct ktc_principal *p;
51 {
52     if (!verbose)
53         return;
54     fprintf(stream, "%s", p->name);
55     if (strlen(p->instance))
56         fprintf(stream, ".%s", p->instance);
57     if (strlen(p->cell) && (strcmp(p->cell, ka_LocalCell()) != 0))
58         fprintf(stream, "@%s", p->cell);
59 }
60
61 static void
62 PrintAuthentication(stream, s, t, c)
63      FILE *stream;
64      struct ktc_principal *s, *c;
65      struct ktc_token *t;
66 {
67     long lifetime;
68     unsigned long now = time(0);
69     char bob[KA_TIMESTR_LEN];
70
71     lifetime = (unsigned long)t->endTime - (unsigned long)t->startTime;
72
73     fprintf(stream, "Ticket for '");
74     PrintPrincipal(stream, s);
75     fprintf(stream, "'\n");
76     ka_timestr(t->endTime, bob, KA_TIMESTR_LEN);
77     fprintf(stream, "  good for %d seconds till %s", lifetime, bob);
78
79     /* Allow one second grace, so the even/odd lifetime doesn't appear as an
80      * error.  If it is way off complain loudly. */
81     if (now + KTC_TIME_UNCERTAINTY < t->startTime)
82         fprintf(stream, " [FUTURE]\n");
83     else if (now + 1 < t->startTime)
84         fprintf(stream, " [ahead]\n");
85     else if (now >= t->endTime + KTC_TIME_UNCERTAINTY)
86         fprintf(stream, " [EXPIRED]\n");
87     else if (now >= t->endTime)
88         fprintf(stream, " [behind]\n");
89     else
90         fprintf(stream, "\n");
91     fprintf(stream, "  for user '");
92     PrintPrincipal(stream, c);
93     fprintf(stream, "'\n");
94     fprintf(stream, "  session key='");
95     ka_PrintBytes(&t->sessionKey, sizeof(t->sessionKey));
96     fprintf(stream, "'\n");
97     fprintf(stream, "  kvno=%d, ticket is %d bytes long.\n", t->kvno,
98             t->ticketLen);
99     if (lifetime & 1) {
100         fprintf(stream, "from %d to %d is %d seconds\n", t->startTime,
101                 t->endTime, lifetime);
102         fprintf(stream, "Lifetime is odd\n");
103     }
104 }
105
106 static int
107 CheckUnixUID(server, token, client)
108      struct ktc_principal *server;
109      struct ktc_token *token;
110      struct ktc_principal *client;
111 {
112     long code;
113     struct ktc_token ntoken;
114     struct ktc_principal nclient;
115     long lifetime;
116     char name_buf[24];
117
118     code = ktc_SetToken(server, token, client, 0);
119     if (code) {
120         com_err(whoami, code, "using SetToken to set vice id");
121         return 1;
122     }
123     sprintf(name_buf, "Unix UID %d", getuid());
124
125     code = ktc_GetToken(server, &ntoken, sizeof(ntoken), &nclient);
126     if (code || (strcmp(nclient.name, name_buf) != 0)
127         || strlen(nclient.instance)) {
128         fprintf(stderr, "GetToken returned bad client: '");
129         PrintPrincipal(stderr, &nclient);
130         fprintf(stderr, "'\n");
131         com_err(whoami, code, "should have gotten '%s'", name_buf);
132         return 1;
133     }
134     lifetime =
135         (unsigned long)ntoken.endTime - (unsigned long)ntoken.startTime;
136     if ((lifetime & 1) == 1) {
137         com_err(whoami, code, "GetToken returned even lifetime (%d)",
138                 lifetime);
139         return 1;
140     }
141     return 0;
142 }
143
144 static int
145 CheckAFSId(server, token, client)
146      struct ktc_principal *server;
147      struct ktc_token *token;
148      struct ktc_principal *client;
149 {
150     long code;
151     struct ktc_token ntoken;
152     struct ktc_principal nclient;
153     long lifetime;
154     char name_buf[24];
155     long viceId;
156
157     viceId = atoi((client->name) + 7);
158     code = ktc_SetToken(server, token, client, 0);
159     if (code) {
160         com_err(whoami, code, "using SetToken to set vice id to %d", viceId);
161         return 1;
162     }
163     code = ktc_GetToken(server, &ntoken, sizeof(ntoken), &nclient);
164     if ((strncmp(nclient.name, "AFS ID ", 7) != 0)
165         || (strlen(nclient.name) < 8) || (atoi(nclient.name + 7) != viceId)
166         || strlen(nclient.instance)) {
167         fprintf(stderr, "GetToken returned bad client: '");
168         PrintPrincipal(stderr, &nclient);
169         fprintf(stderr, "' should have gotten '");
170         PrintPrincipal(stderr, client);
171         fprintf(stderr, "'\n");
172         com_err(whoami, code, "didn't preserve AFS ID");
173         return 1;
174     }
175     lifetime =
176         (unsigned long)ntoken.endTime - (unsigned long)ntoken.startTime;
177     if ((lifetime & 1) == 0) {
178         com_err(whoami, code, "GetToken returned even lifetime (%d)",
179                 lifetime);
180         return 1;
181     }
182     return 0;
183 }
184
185 #include <afs/venus.h>
186
187 /* Stolen from auth/comktc.c: U_CellSetLocalTokens */
188 /* Try various Auth2 style pioctl calls with kvno == 999 */
189
190 static int
191 CheckAuth2(server)
192      struct ktc_principal *server;
193 {
194     long code;
195     int i;
196     struct ViceIoctl buffer;    /*pioctl() communication block */
197     struct ktc_principal client;
198     struct ktc_token token;
199     long lifetime;
200
201     struct EncryptedSecretToken {
202         char data[56];
203     };
204     typedef struct EncryptedSecretToken EncryptedSecretToken;
205
206     struct ClearToken {
207         long AuthHandle;
208         struct ktc_encryptionKey HandShakeKey;
209         long ViceId;
210         long BeginTimestamp;
211         long EndTimestamp;
212     };
213     typedef struct ClearToken ClearToken;
214
215     /* venus buffer for using the new interface to set/get venus tokens */
216     typedef struct {
217         int sTokenSize;         /*Size in bytes of secret token */
218         EncryptedSecretToken stoken;    /*Secret token */
219         int cTokenSize;         /*Size in bytes of clear token */
220         ClearToken ctoken;      /*Clear token */
221         int isPrimary;          /*Is this the primary ID? */
222         char cellName[64];      /*Cell in which tokens are valid */
223     } venusbuff;
224     venusbuff inbuff;
225     ClearToken cToken;
226     EncryptedSecretToken sToken;
227     char *cellID;
228     int primaryFlag;
229
230     cellID = server->cell;
231     primaryFlag = 0;
232
233     /* First build a plausible clear token (code from old auth(2) server */
234     cToken.AuthHandle = -1;     /* not in use right now */
235     for (i = 0; i < sizeof(struct ktc_encryptionKey); i++)
236         cToken.HandShakeKey.data[i] = random() & 0xff;
237     cToken.BeginTimestamp = 0;
238     cToken.EndTimestamp = time(0) + 60 * 60 * 25;       /* valid for 25 hours */
239     cToken.ViceId = 123;
240
241     /* Then invent secret token */
242     for (i = 0; i < sizeof(sToken); i++)
243         sToken.data[i] = random() & 0xff;
244
245
246     /*Copy in the sizes and bodies of the secret and clear tokens */
247     inbuff.sTokenSize = sizeof(EncryptedSecretToken);
248     memcpy((char *)&inbuff.stoken, &sToken, sizeof(EncryptedSecretToken));
249     inbuff.cTokenSize = sizeof(ClearToken);
250     memcpy((char *)&inbuff.ctoken, &cToken, sizeof(ClearToken));
251
252     /* Copy in the Primary ID flag and the cell name */
253 #if DB_CELLS
254     fprintf(stderr,
255             "U_CellSetLocalTokens: using isPrimary=%d, cellName='%s'\n",
256             primaryFlag, cellID);
257 #endif /* DB_CELLS */
258     inbuff.isPrimary = primaryFlag;
259     strcpy(inbuff.cellName, cellID);
260
261     /* Place our inbuff in the standard PIOCTL buffer and go for it. */
262     buffer.in = (char *)&inbuff;
263     buffer.out = 0;
264     buffer.in_size = sizeof(inbuff);
265     buffer.out_size = 0;
266     code = pioctl(0, _VICEIOCTL(3), &buffer, 1);
267     if (code) {
268         com_err(whoami, errno, "setting old-style token");
269         return 1;
270     }
271
272     /* now get it back and see if it's OK */
273     code = ktc_GetToken(server, &token, sizeof(token), &client);
274     if ((strcmp(client.name, "AFS ID 123") != 0) || strlen(client.instance)
275         || (strcmp(client.cell, cellID) != 0)) {
276         fprintf(stderr, "GetToken returned bad client: '");
277         PrintPrincipal(stderr, &client);
278         fprintf(stderr, "'\n");
279         return 1;
280     }
281     if ((token.kvno != 999) || (token.startTime != 0)
282         || (token.endTime != cToken.EndTimestamp)
283         || (token.ticketLen != sizeof(sToken))
284         ||
285         (memcmp
286          (&cToken.HandShakeKey, &token.sessionKey,
287           sizeof(struct ktc_encryptionKey)) != 0)
288         || (memcmp(&sToken, token.ticket, sizeof(sToken)) != 0)) {
289         fprintf(stdout, "Auth2 token was bad\n");
290         PrintAuthentication(stdout, server, &token, &client);
291         return 1;
292     }
293
294     return 0;
295
296 }
297
298 /* Stolen from the "fs" command. */
299
300 #define MAXNAME 100
301 #define MAXSIZE 2048
302
303 static void
304 ListCellsCmd()
305 {
306     register long code;
307     long i, j;
308     char *tcp;
309     long clear;
310     char space[MAXSIZE];
311     struct ViceIoctl blob;
312
313     for (i = 0; i < 1000; i++) {
314         char *cellname;
315         blob.out_size = MAXSIZE;
316         blob.in_size = sizeof(long);
317         blob.in = space;
318         blob.out = space;
319         memcpy(space, &i, sizeof(long));
320         code = pioctl(0, VIOCGETCELL, &blob, 1);
321         if (code < 0) {
322             if (errno == EDOM)
323                 break;          /* done with the list */
324             else {
325                 com_err(whoami, code, "getting cell list");
326                 exit(1);
327             }
328         }
329         cellname = space + 8 * sizeof(long);
330         if (verbose > 1) {
331             printf("Cell %s on hosts", cellname);
332             for (j = 0; j < 8; j++) {
333                 memcpy(&clear, space + j * sizeof(long), sizeof(long));
334                 if (clear == 0)
335                     break;
336 #if SLOW
337                 tcp = hostutil_GetNameByINet(clear);
338 #else
339                 tcp = inet_ntoa(clear);
340 #endif
341                 printf(" %s", tcp);
342             }
343             printf(".\n");
344         }
345         if (nCells < CELLSTOKEEP) {
346             strncpy(cellNameList[nCells++], cellname, MAXKTCREALMLEN);
347         }
348     }
349     return;
350 }
351
352 /* Stolen from the fs command */
353
354 struct Acl {
355     int nplus;
356     int nminus;
357     struct AclEntry *pluslist;
358     struct AclEntry *minuslist;
359 };
360
361 struct AclEntry {
362     struct AclEntry *next;
363     char name[MAXNAME];
364     long rights;
365 };
366
367 char *
368 AclToString(acl)
369      struct Acl *acl;
370 {
371     static char mydata[MAXSIZE];
372     char tstring[MAXSIZE];
373     struct AclEntry *tp;
374     sprintf(mydata, "%d\n%d\n", acl->nplus, acl->nminus);
375     for (tp = acl->pluslist; tp; tp = tp->next) {
376         sprintf(tstring, "%s %d\n", tp->name, tp->rights);
377         strcat(mydata, tstring);
378     }
379     for (tp = acl->minuslist; tp; tp = tp->next) {
380         sprintf(tstring, "%s %d\n", tp->name, tp->rights);
381         strcat(mydata, tstring);
382     }
383     return mydata;
384 }
385
386 char *
387 SkipLine(astr)
388      register char *astr;
389 {
390     while (*astr != '\n')
391         astr++;
392     astr++;
393     return astr;
394 }
395
396 struct Acl *
397 ParseAcl(astr)
398      char *astr;
399 {
400     int nplus, nminus, i, trights;
401     char tname[MAXNAME];
402     struct AclEntry *first, *last, *tl;
403     struct Acl *ta;
404     sscanf(astr, "%d", &nplus);
405     astr = SkipLine(astr);
406     sscanf(astr, "%d", &nminus);
407     astr = SkipLine(astr);
408
409     ta = (struct Acl *)malloc(sizeof(struct Acl));
410     ta->nplus = nplus;
411     ta->nminus = nminus;
412
413     last = 0;
414     first = 0;
415     for (i = 0; i < nplus; i++) {
416         sscanf(astr, "%100s %d", tname, &trights);
417         astr = SkipLine(astr);
418         tl = (struct AclEntry *)malloc(sizeof(struct AclEntry));
419         if (!first)
420             first = tl;
421         strcpy(tl->name, tname);
422         tl->rights = trights;
423         tl->next = 0;
424         if (last)
425             last->next = tl;
426         last = tl;
427     }
428     ta->pluslist = first;
429
430     last = 0;
431     first = 0;
432     for (i = 0; i < nminus; i++) {
433         sscanf(astr, "%100s %d", tname, &trights);
434         astr = SkipLine(astr);
435         tl = (struct AclEntry *)malloc(sizeof(struct AclEntry));
436         if (!first)
437             first = tl;
438         strcpy(tl->name, tname);
439         tl->rights = trights;
440         tl->next = 0;
441         if (last)
442             last->next = tl;
443         last = tl;
444     }
445     ta->minuslist = first;
446
447     return ta;
448 }
449
450 ZapList(alist)
451      struct AclEntry *alist;
452 {
453     register struct AclEntry *tp, *np;
454     for (tp = alist; tp; tp = np) {
455         np = tp->next;
456         free(tp);
457     }
458 }
459
460 int
461 PruneList(ae)
462      struct AclEntry **ae;
463 {
464     struct AclEntry **lp;
465     struct AclEntry *te, *ne;
466     long ctr;
467     ctr = 0;
468     lp = ae;
469     for (te = *ae; te; te = ne) {
470         if (te->rights == 0) {
471             *lp = te->next;
472             ne = te->next;
473             free(te);
474             ctr++;
475         } else {
476             ne = te->next;
477             lp = &te->next;
478         }
479     }
480     return ctr;
481 }
482
483 static int
484 AddTester(pathname)
485      char *pathname;
486 {
487     register long code;
488     struct ViceIoctl blob;
489     struct Acl *al;
490     char space[MAXSIZE];
491
492     blob.out_size = MAXSIZE;
493     blob.in_size = 0;
494     blob.out = space;
495     code = pioctl(pathname, VIOCGETAL, &blob, 1);
496     if (code) {
497         com_err(whoami, errno, "getting acl for %s", pathname);
498         return 1;
499     }
500     if (verbose > 1)
501         printf("old acl for %s is %s\n", pathname, space);
502     al = ParseAcl(space);
503
504     {
505         struct AclEntry *tlist;
506         struct AclEntry *ae;
507         /* clean acl up a bit */
508         ZapList(al->minuslist);
509         al->minuslist = 0;
510         al->nminus = 0;
511         for (ae = al->pluslist; ae; ae = ae->next) {
512             if ((strcmp(ae->name, tester) == 0) ||
513                 /* punt useless entries (like system:anyuser) */
514                 !(ae->
515                   rights & (PRSFS_INSERT | PRSFS_DELETE | PRSFS_WRITE |
516                             PRSFS_LOCK | PRSFS_ADMINISTER)))
517                 ae->rights = 0;
518         }
519         al->nplus -= PruneList(&al->pluslist);
520
521         tlist = (struct AclEntry *)malloc(sizeof(struct AclEntry));
522         tlist->rights = 9;
523         strcpy(tlist->name, tester);
524         tlist->next = al->pluslist;
525         al->pluslist = tlist;
526         al->nplus++;
527     }
528
529     if (verbose > 1) {
530         char tmp[100];
531         printf("before:\n");
532         sprintf(tmp, "fs la %s", pathname);
533         system(tmp);
534     }
535
536     blob.in = AclToString(al);
537     blob.out_size = 0;
538     blob.in_size = 1 + strlen(blob.in);
539     code = pioctl(pathname, VIOCSETAL, &blob, 1);
540     if (code) {
541         com_err(whoami, errno, "setting acl on %s to %s", pathname, blob.in);
542         return 1;
543     }
544     if (verbose > 1) {
545         char tmp[100];
546         printf("after:\n");
547         sprintf(tmp, "fs la %s", pathname);
548         system(tmp);
549     }
550     return 0;
551 }
552
553 /* Free this cell for reuse */
554 static void
555 FreeUnusedCell()
556 {
557     struct ktc_principal client, server;
558     struct ktc_token token;
559     long code;
560
561     strcpy(server.name, "afs");
562     strcpy(server.instance, "");
563     strcpy(server.cell, cellNameList[unusedCell]);
564
565     token.ticketLen = MINKTCTICKETLEN;
566     token.endTime = 0;
567     code = ktc_SetToken(&server, &token, &client, 0);
568     if (code) {
569         com_err(whoami, code, "freeing cell");
570         exit(1);
571     }
572 }
573
574 static int
575 TryAuthenticating(name, password, viceId, cell)
576      char *name;
577      char *password;
578      long viceId;
579      char *cell;
580 {
581     long code;
582     char *reason;
583     struct ktc_principal server, client;
584     struct ktc_token token;
585     long lifetime;
586     unsigned long now = time(0);
587
588     code = ka_UserAuthenticate(name, "", cell, password, 0, &reason);
589     if (code) {
590         fprintf(stderr, "unable to authenticate as %s because %s\n", name,
591                 reason);
592         return 1;
593     }
594     strcpy(server.name, "afs");
595     strcpy(server.instance, "");
596     strcpy(server.cell, cell);
597     code = ktc_GetToken(&server, &token, sizeof(token), &client);
598     if (code) {
599         com_err(whoami, code, "so couldn't get %s's afs token in %s", name,
600                 cell);
601         return code;
602     }
603     if (code = tkt_CheckTimes(token.startTime, token.endTime, now) != 2) {
604         fprintf(stdout, "Bad times on afs ticket\n");
605         PrintAuthentication(stdout, &server, &token, &client);
606         return code;
607     }
608
609     lifetime = token.endTime - token.startTime;
610     if ((lifetime & 1) == 0) {
611         fprintf(stderr, "*** Old style KTC (in cell %s) ***\n", cell);
612     } else {
613         char tmp[24];
614         sprintf(tmp, "AFS ID %d", viceId);
615         if ((strcmp(client.name, tmp) != 0) || strlen(client.instance)) {
616             fprintf(stderr, "GetToken returned bad client: '");
617             PrintPrincipal(stderr, &client);
618             fprintf(stderr, "' should have gotten AFS ID %d for %s@%s\n",
619                     viceId, name, cell);
620             return 1;
621         }
622     }
623     if (verbose) {
624         fprintf(stdout, "%s@%s using ", name, cell);
625         PrintAuthentication(stdout, &server, &token, &client);
626     }
627     return 0;
628 }
629
630 static long
631 CheckAFSTickets()
632 {
633     long code;
634     struct ktc_principal client, server;
635     struct ktc_token token;
636     struct ktc_principal nclient;
637     struct ktc_token ntoken;
638     long lifetime;
639     long exitCode = 0;
640     char *reason;
641     char *tdpath = "./tester_dir";
642     char *tfpath = "./tester_dir/touch";
643     int fd;
644     unsigned long now = time(0);
645
646     strcpy(server.name, "afs");
647     strcpy(server.instance, "");
648     strcpy(server.cell, ka_LocalCell());
649     code = ktc_GetToken(&server, &token, sizeof(token), &client);
650     if (code) {
651         com_err(whoami, code, "so couldn't get afs token");
652         return code;
653     }
654
655     code = mkdir(tdpath, 0777);
656     if (code && (errno != EEXIST)) {
657         com_err(whoami, errno, "making test dir %s", tdpath);
658         return code;
659     }
660     fd = open(tfpath, O_WRONLY + O_CREAT + O_TRUNC, 0777);
661     if (fd == -1) {
662         com_err(whoami, errno, "making test file %s", tfpath);
663         goto failed;
664     }
665     code = close(fd);
666     if (code) {
667         com_err(whoami, errno, "failed to close %s after create", tfpath);
668         goto failed;
669     }
670
671     code = AddTester(tdpath);
672     if (code)
673         goto failed;
674
675     setpag();
676
677     if (TryAuthenticating(tester, testerPassword, testerId, server.cell))
678         goto failed;
679     code = ktc_GetToken(&server, &ntoken, sizeof(ntoken), &nclient);
680     if (code) {
681         com_err(whoami, code, "getting new local afs token");
682         goto failed;
683     }
684
685     if (remoteTesterId) {       /* make sure remote cells work also */
686         if (TryAuthenticating
687             (remoteTester, remoteTesterPassword, remoteTesterId, cell))
688             goto failed;
689     }
690
691     ktc_ForgetToken(&server);   /* switch to unauthenticated */
692
693     /* check to see if remote ticket disappears also. */
694     {
695         struct ktc_principal remote;
696         strcpy(remote.name, "afs");
697         strcpy(remote.instance, "");
698         strcpy(remote.cell, cell);
699         code = ktc_GetToken(&remote, 0, 0, 0);
700         if (code == KTC_NOENT)
701             fprintf(stdout, "*** Using interim KTC ***\n");
702         else
703             fprintf(stdout, "Using kernel ticket cache\n");
704     }
705
706     code = open(tfpath, O_RDONLY, 0);   /* check for read access */
707     if (!((code == -1) && ((errno == ENOENT) || (errno == EACCES)))) {
708         com_err(whoami, errno, "didn't fail to open %s for read", tfpath);
709         goto failed;
710     }
711
712     /* as tester we should have read but not write */
713     code = ktc_SetToken(&server, &ntoken, &nclient, 0);
714     if (code) {
715         com_err(whoami, code, "restoring new local afs token");
716         goto failed;
717     }
718     code = open(tfpath, O_RDWR + O_TRUNC, 0);
719     if ((code != -1) || (errno != EACCES)) {
720         com_err(whoami, errno, "didn't fail to open %s for write", tfpath);
721         goto failed;
722     }
723     fd = open(tfpath, O_RDONLY, 0);
724     if (fd == -1) {
725         com_err(whoami, errno, "failed to open %s for read", tfpath);
726         goto failed;
727     }
728     code = close(fd);
729     if (code) {
730         com_err(whoami, errno, "failed to close %s after open", tfpath);
731         goto failed;
732     }
733
734   finish:
735     /* go back to original privileges */
736     code = ktc_SetToken(&server, &token, &client, 0);
737     if (code) {
738         com_err(whoami, code, "so couldn't set afs token in new pag");
739         exit(1);
740     }
741     if (unlink(tfpath) || rmdir(tdpath)) {
742         com_err(whoami, errno, "removing test dir %s", tdpath);
743         return 1;
744     }
745     return exitCode;
746
747   failed:
748     exitCode = 1;
749     goto finish;
750 }
751
752 main(argc, argv)
753      int argc;
754      char *argv[];
755 {
756     int i;
757     long code;
758     struct ktc_principal client, server;
759     struct ktc_token token;
760     struct ktc_principal nclient, nnclient;
761     struct ktc_token ntoken;
762     long lifetime;
763     long viceId;
764     int printToken = 0;         /* just print afs @ remoteCell */
765
766     srandom(1);
767
768     /* Initialize com_err error code hacking */
769     initialize_U_error_table();
770     initialize_KA_error_table();
771     initialize_RXK_error_table();
772     initialize_KTC_error_table();
773     initialize_ACFG_error_table();
774
775     /* set defaults */
776     strcpy(cell, "");
777     strcpy(tester, "tester");
778     strcpy(testerPassword, "xxx");
779     testerId = 1031;
780     remoteTesterId = 0;         /* don't try this */
781
782     /* parse arguments */
783     i = 1;
784     while (i < argc) {
785         int arglen = strlen(argv[i]);
786         char arg[256];
787         lcstring(arg, argv[i], sizeof(arg));
788 #define IsArg(a) (strncmp (arg,a, arglen) == 0)
789         if (IsArg("-quiet"))
790             verbose--;
791         else if (IsArg("-verbose"))
792             verbose++;
793         else if (IsArg("-printtoken"))
794             printToken++;
795         else if (IsArg("-remotecell"))
796             strncpy(cell, argv[++i], sizeof(cell));
797         else if (IsArg("-testid"))
798             testerId = atoi(argv[++i]);
799         else if (IsArg("-tester"))
800             strncpy(tester, argv[++i], sizeof(tester));
801         else if (IsArg("-testpassword"))
802             strncpy(testerPassword, argv[++i], sizeof(testerPassword));
803         else if (IsArg("-remotetestid"))
804             remoteTesterId = atoi(argv[++i]);
805         else if (IsArg("-remotetester"))
806             strncpy(remoteTester, argv[++i], sizeof(tester));
807         else if (IsArg("-remotetestpassword"))
808             strncpy(remoteTesterPassword, argv[++i],
809                     sizeof(remoteTesterPassword));
810         else {
811             fprintf(stderr, "unexpected arg '%s'\n", arg);
812           usage:
813             fprintf(stderr,
814                     "Usage is: '%s [-quiet] [-verbose] [-remotecell <cellname>] [-testid <AFS ID>] [-tester <name>] -testpassword <pass> [-remotetestid <AFS ID> -remotetester <name> -remotetestpassword <pass>]\n",
815                     whoami);
816             exit(1);
817         }
818         i++;
819     }
820
821     /* get list of cells */
822     ListCellsCmd();
823
824     /* expand requested cell name */
825     code = ka_CellConfig(AFSCONF_CLIENTNAME);
826     if (code)
827         com_err(whoami, code, "calling cell config");
828     code = ka_ExpandCell(cell, cell, 0);
829     if (code) {
830         com_err(whoami, code, "expanding cell %s", cell);
831         exit(1);
832     }
833
834     strcpy(server.name, "afs");
835     strcpy(server.instance, "");
836     strcpy(server.cell, cell);
837     if (printToken) {
838         code = ktc_GetToken(&server, &token, sizeof(token), &client);
839         if (code) {
840             com_err(whoami, code, "so couldn't get afs token");
841             exit(1);
842         }
843         PrintAuthentication(stdout, &server, &token, &client);
844     } else {                    /* dummy up a token */
845         token.startTime = time(0);
846         token.endTime = token.startTime + 3600;
847         token.kvno = 1;
848         token.ticketLen = 48;
849     }
850
851     /* find a cell w/o tokens */
852     for (i = 0; i < nCells; i++) {
853         strcpy(server.cell, cellNameList[i]);
854         code = ktc_GetToken(&server, &ntoken, sizeof(ntoken), &nclient);
855         if ((code == KTC_NOENT) || ((code == 0) && (ntoken.endTime == 0)))
856             goto unused_cell_found;
857     }
858     fprintf(stderr, "All cells have tokens\n");
859   unused_cell_found:
860     unusedCell = i;
861     if (verbose)
862         printf("Using unused cell %s\n", cellNameList[unusedCell]);
863
864     /* First check for various pathological cases */
865
866     strcpy(server.cell, "foo.bar.baz");
867     memcpy(&ntoken, &token, sizeof(ntoken));
868     code = ktc_SetToken(&server, &ntoken, &client, 0);
869     if (code != KTC_NOCELL) {
870         com_err(whoami, code,
871                 "should have gotten bad pioctl error calling SetToken with bogus cell name");
872         goto failed;
873     }
874     strcpy(server.cell, cellNameList[unusedCell]);
875
876     ntoken.ticketLen = 0;
877     code = ktc_SetToken(&server, &ntoken, &client, 0);
878     if ((code != KTC_TOOBIG) && (code != KTC_PIOCTLFAIL)) {
879         com_err(whoami, code,
880                 "should have gotten error calling SetToken with zero ticket length");
881         goto failed;
882     }
883     ntoken.ticketLen = token.ticketLen;
884     ntoken.endTime = 0;
885     code = ktc_SetToken(&server, &ntoken, &client, 0);
886     if (code) {
887         com_err(whoami, code, "calling SetToken with zero expiration time");
888         goto failed;
889     }
890     strcpy(nclient.name, "foo");
891     strcpy(nclient.instance, "bar");
892     strcpy(nclient.cell, "foo.bar.baz");
893     code = ktc_SetToken(&server, &ntoken, &nclient, 0);
894     if (code) {
895         com_err(whoami, code, "calling SetToken with bogus client cell");
896         goto failed;
897     }
898     memcpy(&ntoken, &token, sizeof(ntoken));
899     if (token.kvno == 999)
900         ntoken.kvno = 99;
901
902     /* Now check out SetToken parsing of specially formed names */
903
904     strcpy(nclient.instance, "");
905     /* cell is uniformly ignored */
906     viceId = 123;
907     sprintf(nclient.name, "AFS ID %d", viceId);
908     if (CheckAFSId(&server, &ntoken, &nclient))
909         goto failed;
910     ntoken.endTime--;
911     if (CheckAFSId(&server, &ntoken, &nclient))
912         goto failed;
913     sprintf(nclient.name, "AFS ID 0%d", viceId);
914     if (CheckAFSId(&server, &ntoken, &nclient))
915         goto failed;
916 #if 1
917     sprintf(nclient.name, "AFS ID %d", -44444);
918     if (CheckAFSId(&server, &ntoken, &nclient))
919         goto failed;
920 #endif
921     sprintf(nclient.name, "AFS ID %d", 0x7fffffff);
922     if (CheckAFSId(&server, &ntoken, &nclient))
923         goto failed;
924
925     sprintf(nclient.name, "AFS ID ");
926     if (CheckUnixUID(&server, &ntoken, &nclient))
927         goto failed;
928     sprintf(nclient.name, "AFS ID 10x");
929     if (CheckUnixUID(&server, &ntoken, &nclient))
930         goto failed;
931     sprintf(nclient.name, "foobar");
932     if (CheckUnixUID(&server, &ntoken, &nclient))
933         goto failed;
934     ntoken.endTime--;
935     if (CheckUnixUID(&server, &ntoken, &nclient))
936         goto failed;
937
938     /* make sure simulated auth2 tokens still does something reasonable */
939     if (CheckAuth2(&server))
940         goto failed;
941
942     FreeUnusedCell();
943
944     code = CheckAFSTickets();   /* returns in new PAG */
945     if (code)
946         exit(1);
947
948     rx_Finalize();
949
950     printf("All OK\n");
951     exit(0);
952
953   failed:
954     FreeUnusedCell();
955     exit(1);
956 }