2 * Copyright 2000, International Business Machines Corporation and others.
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
10 /* Test ktc related calls as well as some file access stuff. */
12 #include <sys/types.h>
16 #include <arpa/inet.h>
17 #include <afs/prs_fs.h>
18 #include <afsconfig.h>
19 #include <afs/param.h>
25 #include <afs/com_err.h>
26 #include <afs/cellconfig.h>
33 static char *whoami = "test_interim_ktc";
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];
43 static char remoteTester[MAXKTCNAMELEN];
44 static char remoteTesterPassword[32];
45 static long remoteTesterId;
48 PrintPrincipal(stream, p)
50 struct ktc_principal *p;
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);
62 PrintAuthentication(stream, s, t, c)
64 struct ktc_principal *s, *c;
68 unsigned long now = time(0);
69 char bob[KA_TIMESTR_LEN];
71 lifetime = (unsigned long)t->endTime - (unsigned long)t->startTime;
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);
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");
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,
100 fprintf(stream, "from %d to %d is %d seconds\n", t->startTime,
101 t->endTime, lifetime);
102 fprintf(stream, "Lifetime is odd\n");
107 CheckUnixUID(server, token, client)
108 struct ktc_principal *server;
109 struct ktc_token *token;
110 struct ktc_principal *client;
113 struct ktc_token ntoken;
114 struct ktc_principal nclient;
118 code = ktc_SetToken(server, token, client, 0);
120 com_err(whoami, code, "using SetToken to set vice id");
123 sprintf(name_buf, "Unix UID %d", getuid());
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);
135 (unsigned long)ntoken.endTime - (unsigned long)ntoken.startTime;
136 if ((lifetime & 1) == 1) {
137 com_err(whoami, code, "GetToken returned even lifetime (%d)",
145 CheckAFSId(server, token, client)
146 struct ktc_principal *server;
147 struct ktc_token *token;
148 struct ktc_principal *client;
151 struct ktc_token ntoken;
152 struct ktc_principal nclient;
157 viceId = atoi((client->name) + 7);
158 code = ktc_SetToken(server, token, client, 0);
160 com_err(whoami, code, "using SetToken to set vice id to %d", viceId);
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");
176 (unsigned long)ntoken.endTime - (unsigned long)ntoken.startTime;
177 if ((lifetime & 1) == 0) {
178 com_err(whoami, code, "GetToken returned even lifetime (%d)",
185 #include <afs/venus.h>
187 /* Stolen from auth/comktc.c: U_CellSetLocalTokens */
188 /* Try various Auth2 style pioctl calls with kvno == 999 */
192 struct ktc_principal *server;
196 struct ViceIoctl buffer; /*pioctl() communication block */
197 struct ktc_principal client;
198 struct ktc_token token;
201 struct EncryptedSecretToken {
204 typedef struct EncryptedSecretToken EncryptedSecretToken;
208 struct ktc_encryptionKey HandShakeKey;
213 typedef struct ClearToken ClearToken;
215 /* venus buffer for using the new interface to set/get venus tokens */
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 */
226 EncryptedSecretToken sToken;
230 cellID = server->cell;
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 */
241 /* Then invent secret token */
242 for (i = 0; i < sizeof(sToken); i++)
243 sToken.data[i] = random() & 0xff;
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));
252 /* Copy in the Primary ID flag and the cell name */
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);
261 /* Place our inbuff in the standard PIOCTL buffer and go for it. */
262 buffer.in = (char *)&inbuff;
264 buffer.in_size = sizeof(inbuff);
266 code = pioctl(0, _VICEIOCTL(3), &buffer, 1);
268 com_err(whoami, errno, "setting old-style token");
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");
281 if ((token.kvno != 999) || (token.startTime != 0)
282 || (token.endTime != cToken.EndTimestamp)
283 || (token.ticketLen != sizeof(sToken))
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);
298 /* Stolen from the "fs" command. */
311 struct ViceIoctl blob;
313 for (i = 0; i < 1000; i++) {
315 blob.out_size = MAXSIZE;
316 blob.in_size = sizeof(long);
319 memcpy(space, &i, sizeof(long));
320 code = pioctl(0, VIOCGETCELL, &blob, 1);
323 break; /* done with the list */
325 com_err(whoami, code, "getting cell list");
329 cellname = space + 8 * sizeof(long);
331 printf("Cell %s on hosts", cellname);
332 for (j = 0; j < 8; j++) {
333 memcpy(&clear, space + j * sizeof(long), sizeof(long));
337 tcp = hostutil_GetNameByINet(clear);
339 tcp = inet_ntoa(clear);
345 if (nCells < CELLSTOKEEP) {
346 strncpy(cellNameList[nCells++], cellname, MAXKTCREALMLEN);
352 /* Stolen from the fs command */
357 struct AclEntry *pluslist;
358 struct AclEntry *minuslist;
362 struct AclEntry *next;
371 static char mydata[MAXSIZE];
372 char tstring[MAXSIZE];
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);
379 for (tp = acl->minuslist; tp; tp = tp->next) {
380 sprintf(tstring, "%s %d\n", tp->name, tp->rights);
381 strcat(mydata, tstring);
390 while (*astr != '\n')
400 int nplus, nminus, i, trights;
402 struct AclEntry *first, *last, *tl;
404 sscanf(astr, "%d", &nplus);
405 astr = SkipLine(astr);
406 sscanf(astr, "%d", &nminus);
407 astr = SkipLine(astr);
409 ta = (struct Acl *)malloc(sizeof(struct Acl));
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));
421 strcpy(tl->name, tname);
422 tl->rights = trights;
428 ta->pluslist = first;
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));
438 strcpy(tl->name, tname);
439 tl->rights = trights;
445 ta->minuslist = first;
451 struct AclEntry *alist;
453 register struct AclEntry *tp, *np;
454 for (tp = alist; tp; tp = np) {
462 struct AclEntry **ae;
464 struct AclEntry **lp;
465 struct AclEntry *te, *ne;
469 for (te = *ae; te; te = ne) {
470 if (te->rights == 0) {
488 struct ViceIoctl blob;
492 blob.out_size = MAXSIZE;
495 code = pioctl(pathname, VIOCGETAL, &blob, 1);
497 com_err(whoami, errno, "getting acl for %s", pathname);
501 printf("old acl for %s is %s\n", pathname, space);
502 al = ParseAcl(space);
505 struct AclEntry *tlist;
507 /* clean acl up a bit */
508 ZapList(al->minuslist);
511 for (ae = al->pluslist; ae; ae = ae->next) {
512 if ((strcmp(ae->name, tester) == 0) ||
513 /* punt useless entries (like system:anyuser) */
515 rights & (PRSFS_INSERT | PRSFS_DELETE | PRSFS_WRITE |
516 PRSFS_LOCK | PRSFS_ADMINISTER)))
519 al->nplus -= PruneList(&al->pluslist);
521 tlist = (struct AclEntry *)malloc(sizeof(struct AclEntry));
523 strcpy(tlist->name, tester);
524 tlist->next = al->pluslist;
525 al->pluslist = tlist;
532 sprintf(tmp, "fs la %s", pathname);
536 blob.in = AclToString(al);
538 blob.in_size = 1 + strlen(blob.in);
539 code = pioctl(pathname, VIOCSETAL, &blob, 1);
541 com_err(whoami, errno, "setting acl on %s to %s", pathname, blob.in);
547 sprintf(tmp, "fs la %s", pathname);
553 /* Free this cell for reuse */
557 struct ktc_principal client, server;
558 struct ktc_token token;
561 strcpy(server.name, "afs");
562 strcpy(server.instance, "");
563 strcpy(server.cell, cellNameList[unusedCell]);
565 token.ticketLen = MINKTCTICKETLEN;
567 code = ktc_SetToken(&server, &token, &client, 0);
569 com_err(whoami, code, "freeing cell");
575 TryAuthenticating(name, password, viceId, cell)
583 struct ktc_principal server, client;
584 struct ktc_token token;
586 unsigned long now = time(0);
588 code = ka_UserAuthenticate(name, "", cell, password, 0, &reason);
590 fprintf(stderr, "unable to authenticate as %s because %s\n", name,
594 strcpy(server.name, "afs");
595 strcpy(server.instance, "");
596 strcpy(server.cell, cell);
597 code = ktc_GetToken(&server, &token, sizeof(token), &client);
599 com_err(whoami, code, "so couldn't get %s's afs token in %s", name,
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);
609 lifetime = token.endTime - token.startTime;
610 if ((lifetime & 1) == 0) {
611 fprintf(stderr, "*** Old style KTC (in cell %s) ***\n", cell);
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",
624 fprintf(stdout, "%s@%s using ", name, cell);
625 PrintAuthentication(stdout, &server, &token, &client);
634 struct ktc_principal client, server;
635 struct ktc_token token;
636 struct ktc_principal nclient;
637 struct ktc_token ntoken;
641 char *tdpath = "./tester_dir";
642 char *tfpath = "./tester_dir/touch";
644 unsigned long now = time(0);
646 strcpy(server.name, "afs");
647 strcpy(server.instance, "");
648 strcpy(server.cell, ka_LocalCell());
649 code = ktc_GetToken(&server, &token, sizeof(token), &client);
651 com_err(whoami, code, "so couldn't get afs token");
655 code = mkdir(tdpath, 0777);
656 if (code && (errno != EEXIST)) {
657 com_err(whoami, errno, "making test dir %s", tdpath);
660 fd = open(tfpath, O_WRONLY + O_CREAT + O_TRUNC, 0777);
662 com_err(whoami, errno, "making test file %s", tfpath);
667 com_err(whoami, errno, "failed to close %s after create", tfpath);
671 code = AddTester(tdpath);
677 if (TryAuthenticating(tester, testerPassword, testerId, server.cell))
679 code = ktc_GetToken(&server, &ntoken, sizeof(ntoken), &nclient);
681 com_err(whoami, code, "getting new local afs token");
685 if (remoteTesterId) { /* make sure remote cells work also */
686 if (TryAuthenticating
687 (remoteTester, remoteTesterPassword, remoteTesterId, cell))
691 ktc_ForgetToken(&server); /* switch to unauthenticated */
693 /* check to see if remote ticket disappears also. */
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");
703 fprintf(stdout, "Using kernel ticket cache\n");
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);
712 /* as tester we should have read but not write */
713 code = ktc_SetToken(&server, &ntoken, &nclient, 0);
715 com_err(whoami, code, "restoring new local afs token");
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);
723 fd = open(tfpath, O_RDONLY, 0);
725 com_err(whoami, errno, "failed to open %s for read", tfpath);
730 com_err(whoami, errno, "failed to close %s after open", tfpath);
735 /* go back to original privileges */
736 code = ktc_SetToken(&server, &token, &client, 0);
738 com_err(whoami, code, "so couldn't set afs token in new pag");
741 if (unlink(tfpath) || rmdir(tdpath)) {
742 com_err(whoami, errno, "removing test dir %s", tdpath);
758 struct ktc_principal client, server;
759 struct ktc_token token;
760 struct ktc_principal nclient, nnclient;
761 struct ktc_token ntoken;
764 int printToken = 0; /* just print afs @ remoteCell */
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();
777 strcpy(tester, "tester");
778 strcpy(testerPassword, "xxx");
780 remoteTesterId = 0; /* don't try this */
782 /* parse arguments */
785 int arglen = strlen(argv[i]);
787 lcstring(arg, argv[i], sizeof(arg));
788 #define IsArg(a) (strncmp (arg,a, arglen) == 0)
791 else if (IsArg("-verbose"))
793 else if (IsArg("-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));
811 fprintf(stderr, "unexpected arg '%s'\n", arg);
814 "Usage is: '%s [-quiet] [-verbose] [-remotecell <cellname>] [-testid <AFS ID>] [-tester <name>] -testpassword <pass> [-remotetestid <AFS ID> -remotetester <name> -remotetestpassword <pass>]\n",
821 /* get list of cells */
824 /* expand requested cell name */
825 code = ka_CellConfig(AFSCONF_CLIENTNAME);
827 com_err(whoami, code, "calling cell config");
828 code = ka_ExpandCell(cell, cell, 0);
830 com_err(whoami, code, "expanding cell %s", cell);
834 strcpy(server.name, "afs");
835 strcpy(server.instance, "");
836 strcpy(server.cell, cell);
838 code = ktc_GetToken(&server, &token, sizeof(token), &client);
840 com_err(whoami, code, "so couldn't get afs token");
843 PrintAuthentication(stdout, &server, &token, &client);
844 } else { /* dummy up a token */
845 token.startTime = time(0);
846 token.endTime = token.startTime + 3600;
848 token.ticketLen = 48;
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;
858 fprintf(stderr, "All cells have tokens\n");
862 printf("Using unused cell %s\n", cellNameList[unusedCell]);
864 /* First check for various pathological cases */
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");
874 strcpy(server.cell, cellNameList[unusedCell]);
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");
883 ntoken.ticketLen = token.ticketLen;
885 code = ktc_SetToken(&server, &ntoken, &client, 0);
887 com_err(whoami, code, "calling SetToken with zero expiration time");
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);
895 com_err(whoami, code, "calling SetToken with bogus client cell");
898 memcpy(&ntoken, &token, sizeof(ntoken));
899 if (token.kvno == 999)
902 /* Now check out SetToken parsing of specially formed names */
904 strcpy(nclient.instance, "");
905 /* cell is uniformly ignored */
907 sprintf(nclient.name, "AFS ID %d", viceId);
908 if (CheckAFSId(&server, &ntoken, &nclient))
911 if (CheckAFSId(&server, &ntoken, &nclient))
913 sprintf(nclient.name, "AFS ID 0%d", viceId);
914 if (CheckAFSId(&server, &ntoken, &nclient))
917 sprintf(nclient.name, "AFS ID %d", -44444);
918 if (CheckAFSId(&server, &ntoken, &nclient))
921 sprintf(nclient.name, "AFS ID %d", 0x7fffffff);
922 if (CheckAFSId(&server, &ntoken, &nclient))
925 sprintf(nclient.name, "AFS ID ");
926 if (CheckUnixUID(&server, &ntoken, &nclient))
928 sprintf(nclient.name, "AFS ID 10x");
929 if (CheckUnixUID(&server, &ntoken, &nclient))
931 sprintf(nclient.name, "foobar");
932 if (CheckUnixUID(&server, &ntoken, &nclient))
935 if (CheckUnixUID(&server, &ntoken, &nclient))
938 /* make sure simulated auth2 tokens still does something reasonable */
939 if (CheckAuth2(&server))
944 code = CheckAFSTickets(); /* returns in new PAG */