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>
23 #include <afs/com_err.h>
24 #include <afs/cellconfig.h>
31 static char *whoami = "test_interim_ktc";
33 #define CELLSTOKEEP 50
34 static char cell[MAXKTCREALMLEN];
35 static char cellNameList[CELLSTOKEEP][MAXKTCREALMLEN];
36 static int nCells = 0;
37 static int unusedCell;
38 static char tester[MAXKTCNAMELEN];
39 static char testerPassword[32];
41 static char remoteTester[MAXKTCNAMELEN];
42 static char remoteTesterPassword[32];
43 static long remoteTesterId;
46 PrintPrincipal(stream, p)
48 struct ktc_principal *p;
52 fprintf(stream, "%s", p->name);
53 if (strlen(p->instance))
54 fprintf(stream, ".%s", p->instance);
55 if (strlen(p->cell) && (strcmp(p->cell, ka_LocalCell()) != 0))
56 fprintf(stream, "@%s", p->cell);
60 PrintAuthentication(stream, s, t, c)
62 struct ktc_principal *s, *c;
66 unsigned long now = time(0);
67 char bob[KA_TIMESTR_LEN];
69 lifetime = (unsigned long)t->endTime - (unsigned long)t->startTime;
71 fprintf(stream, "Ticket for '");
72 PrintPrincipal(stream, s);
73 fprintf(stream, "'\n");
74 ka_timestr(t->endTime, bob, KA_TIMESTR_LEN);
75 fprintf(stream, " good for %d seconds till %s", lifetime, bob);
77 /* Allow one second grace, so the even/odd lifetime doesn't appear as an
78 * error. If it is way off complain loudly. */
79 if (now + KTC_TIME_UNCERTAINTY < t->startTime)
80 fprintf(stream, " [FUTURE]\n");
81 else if (now + 1 < t->startTime)
82 fprintf(stream, " [ahead]\n");
83 else if (now >= t->endTime + KTC_TIME_UNCERTAINTY)
84 fprintf(stream, " [EXPIRED]\n");
85 else if (now >= t->endTime)
86 fprintf(stream, " [behind]\n");
88 fprintf(stream, "\n");
89 fprintf(stream, " for user '");
90 PrintPrincipal(stream, c);
91 fprintf(stream, "'\n");
92 fprintf(stream, " session key='");
93 ka_PrintBytes(&t->sessionKey, sizeof(t->sessionKey));
94 fprintf(stream, "'\n");
95 fprintf(stream, " kvno=%d, ticket is %d bytes long.\n", t->kvno,
98 fprintf(stream, "from %d to %d is %d seconds\n", t->startTime,
99 t->endTime, lifetime);
100 fprintf(stream, "Lifetime is odd\n");
105 CheckUnixUID(server, token, client)
106 struct ktc_principal *server;
107 struct ktc_token *token;
108 struct ktc_principal *client;
111 struct ktc_token ntoken;
112 struct ktc_principal nclient;
116 code = ktc_SetToken(server, token, client, 0);
118 afs_com_err(whoami, code, "using SetToken to set vice id");
121 sprintf(name_buf, "Unix UID %d", getuid());
123 code = ktc_GetToken(server, &ntoken, sizeof(ntoken), &nclient);
124 if (code || (strcmp(nclient.name, name_buf) != 0)
125 || strlen(nclient.instance)) {
126 fprintf(stderr, "GetToken returned bad client: '");
127 PrintPrincipal(stderr, &nclient);
128 fprintf(stderr, "'\n");
129 afs_com_err(whoami, code, "should have gotten '%s'", name_buf);
133 (unsigned long)ntoken.endTime - (unsigned long)ntoken.startTime;
134 if ((lifetime & 1) == 1) {
135 afs_com_err(whoami, code, "GetToken returned even lifetime (%d)",
143 CheckAFSId(server, token, client)
144 struct ktc_principal *server;
145 struct ktc_token *token;
146 struct ktc_principal *client;
149 struct ktc_token ntoken;
150 struct ktc_principal nclient;
155 viceId = atoi((client->name) + 7);
156 code = ktc_SetToken(server, token, client, 0);
158 afs_com_err(whoami, code, "using SetToken to set vice id to %d", viceId);
161 code = ktc_GetToken(server, &ntoken, sizeof(ntoken), &nclient);
162 if ((strncmp(nclient.name, "AFS ID ", 7) != 0)
163 || (strlen(nclient.name) < 8) || (atoi(nclient.name + 7) != viceId)
164 || strlen(nclient.instance)) {
165 fprintf(stderr, "GetToken returned bad client: '");
166 PrintPrincipal(stderr, &nclient);
167 fprintf(stderr, "' should have gotten '");
168 PrintPrincipal(stderr, client);
169 fprintf(stderr, "'\n");
170 afs_com_err(whoami, code, "didn't preserve AFS ID");
174 (unsigned long)ntoken.endTime - (unsigned long)ntoken.startTime;
175 if ((lifetime & 1) == 0) {
176 afs_com_err(whoami, code, "GetToken returned even lifetime (%d)",
183 #include <afs/venus.h>
185 /* Stolen from auth/comktc.c: U_CellSetLocalTokens */
186 /* Try various Auth2 style pioctl calls with kvno == 999 */
190 struct ktc_principal *server;
194 struct ViceIoctl buffer; /*pioctl() communication block */
195 struct ktc_principal client;
196 struct ktc_token token;
199 struct EncryptedSecretToken {
202 typedef struct EncryptedSecretToken EncryptedSecretToken;
206 struct ktc_encryptionKey HandShakeKey;
211 typedef struct ClearToken ClearToken;
213 /* venus buffer for using the new interface to set/get venus tokens */
215 int sTokenSize; /*Size in bytes of secret token */
216 EncryptedSecretToken stoken; /*Secret token */
217 int cTokenSize; /*Size in bytes of clear token */
218 ClearToken ctoken; /*Clear token */
219 int isPrimary; /*Is this the primary ID? */
220 char cellName[64]; /*Cell in which tokens are valid */
224 EncryptedSecretToken sToken;
228 cellID = server->cell;
231 /* First build a plausible clear token (code from old auth(2) server */
232 cToken.AuthHandle = -1; /* not in use right now */
233 for (i = 0; i < sizeof(struct ktc_encryptionKey); i++)
234 cToken.HandShakeKey.data[i] = random() & 0xff;
235 cToken.BeginTimestamp = 0;
236 cToken.EndTimestamp = time(0) + 60 * 60 * 25; /* valid for 25 hours */
239 /* Then invent secret token */
240 for (i = 0; i < sizeof(sToken); i++)
241 sToken.data[i] = random() & 0xff;
244 /*Copy in the sizes and bodies of the secret and clear tokens */
245 inbuff.sTokenSize = sizeof(EncryptedSecretToken);
246 memcpy((char *)&inbuff.stoken, &sToken, sizeof(EncryptedSecretToken));
247 inbuff.cTokenSize = sizeof(ClearToken);
248 memcpy((char *)&inbuff.ctoken, &cToken, sizeof(ClearToken));
250 /* Copy in the Primary ID flag and the cell name */
253 "U_CellSetLocalTokens: using isPrimary=%d, cellName='%s'\n",
254 primaryFlag, cellID);
255 #endif /* DB_CELLS */
256 inbuff.isPrimary = primaryFlag;
257 strcpy(inbuff.cellName, cellID);
259 /* Place our inbuff in the standard PIOCTL buffer and go for it. */
260 buffer.in = (char *)&inbuff;
262 buffer.in_size = sizeof(inbuff);
264 code = pioctl(0, _VICEIOCTL(3), &buffer, 1);
266 afs_com_err(whoami, errno, "setting old-style token");
270 /* now get it back and see if it's OK */
271 code = ktc_GetToken(server, &token, sizeof(token), &client);
272 if ((strcmp(client.name, "AFS ID 123") != 0) || strlen(client.instance)
273 || (strcmp(client.cell, cellID) != 0)) {
274 fprintf(stderr, "GetToken returned bad client: '");
275 PrintPrincipal(stderr, &client);
276 fprintf(stderr, "'\n");
279 if ((token.kvno != 999) || (token.startTime != 0)
280 || (token.endTime != cToken.EndTimestamp)
281 || (token.ticketLen != sizeof(sToken))
284 (&cToken.HandShakeKey, &token.sessionKey,
285 sizeof(struct ktc_encryptionKey)) != 0)
286 || (memcmp(&sToken, token.ticket, sizeof(sToken)) != 0)) {
287 fprintf(stdout, "Auth2 token was bad\n");
288 PrintAuthentication(stdout, server, &token, &client);
296 /* Stolen from the "fs" command. */
309 struct ViceIoctl blob;
311 for (i = 0; i < 1000; i++) {
313 blob.out_size = MAXSIZE;
314 blob.in_size = sizeof(long);
317 memcpy(space, &i, sizeof(long));
318 code = pioctl(0, VIOCGETCELL, &blob, 1);
321 break; /* done with the list */
323 afs_com_err(whoami, code, "getting cell list");
327 cellname = space + 8 * sizeof(long);
329 printf("Cell %s on hosts", cellname);
330 for (j = 0; j < 8; j++) {
331 memcpy(&clear, space + j * sizeof(long), sizeof(long));
335 tcp = hostutil_GetNameByINet(clear);
337 tcp = inet_ntoa(clear);
343 if (nCells < CELLSTOKEEP) {
344 strncpy(cellNameList[nCells++], cellname, MAXKTCREALMLEN);
350 /* Stolen from the fs command */
355 struct AclEntry *pluslist;
356 struct AclEntry *minuslist;
360 struct AclEntry *next;
369 static char mydata[MAXSIZE];
370 char tstring[MAXSIZE];
372 sprintf(mydata, "%d\n%d\n", acl->nplus, acl->nminus);
373 for (tp = acl->pluslist; tp; tp = tp->next) {
374 sprintf(tstring, "%s %d\n", tp->name, tp->rights);
375 strcat(mydata, tstring);
377 for (tp = acl->minuslist; tp; tp = tp->next) {
378 sprintf(tstring, "%s %d\n", tp->name, tp->rights);
379 strcat(mydata, tstring);
388 while (*astr != '\n')
398 int nplus, nminus, i, trights;
400 struct AclEntry *first, *last, *tl;
402 sscanf(astr, "%d", &nplus);
403 astr = SkipLine(astr);
404 sscanf(astr, "%d", &nminus);
405 astr = SkipLine(astr);
407 ta = (struct Acl *)malloc(sizeof(struct Acl));
413 for (i = 0; i < nplus; i++) {
414 sscanf(astr, "%100s %d", tname, &trights);
415 astr = SkipLine(astr);
416 tl = (struct AclEntry *)malloc(sizeof(struct AclEntry));
419 strcpy(tl->name, tname);
420 tl->rights = trights;
426 ta->pluslist = first;
430 for (i = 0; i < nminus; i++) {
431 sscanf(astr, "%100s %d", tname, &trights);
432 astr = SkipLine(astr);
433 tl = (struct AclEntry *)malloc(sizeof(struct AclEntry));
436 strcpy(tl->name, tname);
437 tl->rights = trights;
443 ta->minuslist = first;
449 struct AclEntry *alist;
451 register struct AclEntry *tp, *np;
452 for (tp = alist; tp; tp = np) {
460 struct AclEntry **ae;
462 struct AclEntry **lp;
463 struct AclEntry *te, *ne;
467 for (te = *ae; te; te = ne) {
468 if (te->rights == 0) {
486 struct ViceIoctl blob;
490 blob.out_size = MAXSIZE;
493 code = pioctl(pathname, VIOCGETAL, &blob, 1);
495 afs_com_err(whoami, errno, "getting acl for %s", pathname);
499 printf("old acl for %s is %s\n", pathname, space);
500 al = ParseAcl(space);
503 struct AclEntry *tlist;
505 /* clean acl up a bit */
506 ZapList(al->minuslist);
509 for (ae = al->pluslist; ae; ae = ae->next) {
510 if ((strcmp(ae->name, tester) == 0) ||
511 /* punt useless entries (like system:anyuser) */
513 rights & (PRSFS_INSERT | PRSFS_DELETE | PRSFS_WRITE |
514 PRSFS_LOCK | PRSFS_ADMINISTER)))
517 al->nplus -= PruneList(&al->pluslist);
519 tlist = (struct AclEntry *)malloc(sizeof(struct AclEntry));
521 strcpy(tlist->name, tester);
522 tlist->next = al->pluslist;
523 al->pluslist = tlist;
530 sprintf(tmp, "fs la %s", pathname);
534 blob.in = AclToString(al);
536 blob.in_size = 1 + strlen(blob.in);
537 code = pioctl(pathname, VIOCSETAL, &blob, 1);
539 afs_com_err(whoami, errno, "setting acl on %s to %s", pathname, blob.in);
545 sprintf(tmp, "fs la %s", pathname);
551 /* Free this cell for reuse */
555 struct ktc_principal client, server;
556 struct ktc_token token;
559 strcpy(server.name, "afs");
560 strcpy(server.instance, "");
561 strcpy(server.cell, cellNameList[unusedCell]);
563 token.ticketLen = MINKTCTICKETLEN;
565 code = ktc_SetToken(&server, &token, &client, 0);
567 afs_com_err(whoami, code, "freeing cell");
573 TryAuthenticating(name, password, viceId, cell)
581 struct ktc_principal server, client;
582 struct ktc_token token;
584 unsigned long now = time(0);
586 code = ka_UserAuthenticate(name, "", cell, password, 0, &reason);
588 fprintf(stderr, "unable to authenticate as %s because %s\n", name,
592 strcpy(server.name, "afs");
593 strcpy(server.instance, "");
594 strcpy(server.cell, cell);
595 code = ktc_GetToken(&server, &token, sizeof(token), &client);
597 afs_com_err(whoami, code, "so couldn't get %s's afs token in %s", name,
601 if (code = tkt_CheckTimes(token.startTime, token.endTime, now) != 2) {
602 fprintf(stdout, "Bad times on afs ticket\n");
603 PrintAuthentication(stdout, &server, &token, &client);
607 lifetime = token.endTime - token.startTime;
608 if ((lifetime & 1) == 0) {
609 fprintf(stderr, "*** Old style KTC (in cell %s) ***\n", cell);
612 sprintf(tmp, "AFS ID %d", viceId);
613 if ((strcmp(client.name, tmp) != 0) || strlen(client.instance)) {
614 fprintf(stderr, "GetToken returned bad client: '");
615 PrintPrincipal(stderr, &client);
616 fprintf(stderr, "' should have gotten AFS ID %d for %s@%s\n",
622 fprintf(stdout, "%s@%s using ", name, cell);
623 PrintAuthentication(stdout, &server, &token, &client);
632 struct ktc_principal client, server;
633 struct ktc_token token;
634 struct ktc_principal nclient;
635 struct ktc_token ntoken;
639 char *tdpath = "./tester_dir";
640 char *tfpath = "./tester_dir/touch";
642 unsigned long now = time(0);
644 strcpy(server.name, "afs");
645 strcpy(server.instance, "");
646 strcpy(server.cell, ka_LocalCell());
647 code = ktc_GetToken(&server, &token, sizeof(token), &client);
649 afs_com_err(whoami, code, "so couldn't get afs token");
653 code = mkdir(tdpath, 0777);
654 if (code && (errno != EEXIST)) {
655 afs_com_err(whoami, errno, "making test dir %s", tdpath);
658 fd = open(tfpath, O_WRONLY + O_CREAT + O_TRUNC, 0777);
660 afs_com_err(whoami, errno, "making test file %s", tfpath);
665 afs_com_err(whoami, errno, "failed to close %s after create", tfpath);
669 code = AddTester(tdpath);
675 if (TryAuthenticating(tester, testerPassword, testerId, server.cell))
677 code = ktc_GetToken(&server, &ntoken, sizeof(ntoken), &nclient);
679 afs_com_err(whoami, code, "getting new local afs token");
683 if (remoteTesterId) { /* make sure remote cells work also */
684 if (TryAuthenticating
685 (remoteTester, remoteTesterPassword, remoteTesterId, cell))
689 ktc_ForgetToken(&server); /* switch to unauthenticated */
691 /* check to see if remote ticket disappears also. */
693 struct ktc_principal remote;
694 strcpy(remote.name, "afs");
695 strcpy(remote.instance, "");
696 strcpy(remote.cell, cell);
697 code = ktc_GetToken(&remote, 0, 0, 0);
698 if (code == KTC_NOENT)
699 fprintf(stdout, "*** Using interim KTC ***\n");
701 fprintf(stdout, "Using kernel ticket cache\n");
704 code = open(tfpath, O_RDONLY, 0); /* check for read access */
705 if (!((code == -1) && ((errno == ENOENT) || (errno == EACCES)))) {
706 afs_com_err(whoami, errno, "didn't fail to open %s for read", tfpath);
710 /* as tester we should have read but not write */
711 code = ktc_SetToken(&server, &ntoken, &nclient, 0);
713 afs_com_err(whoami, code, "restoring new local afs token");
716 code = open(tfpath, O_RDWR + O_TRUNC, 0);
717 if ((code != -1) || (errno != EACCES)) {
718 afs_com_err(whoami, errno, "didn't fail to open %s for write", tfpath);
721 fd = open(tfpath, O_RDONLY, 0);
723 afs_com_err(whoami, errno, "failed to open %s for read", tfpath);
728 afs_com_err(whoami, errno, "failed to close %s after open", tfpath);
733 /* go back to original privileges */
734 code = ktc_SetToken(&server, &token, &client, 0);
736 afs_com_err(whoami, code, "so couldn't set afs token in new pag");
739 if (unlink(tfpath) || rmdir(tdpath)) {
740 afs_com_err(whoami, errno, "removing test dir %s", tdpath);
756 struct ktc_principal client, server;
757 struct ktc_token token;
758 struct ktc_principal nclient, nnclient;
759 struct ktc_token ntoken;
762 int printToken = 0; /* just print afs @ remoteCell */
766 /* Initialize afs_com_err error code hacking */
767 initialize_U_error_table();
768 initialize_KA_error_table();
769 initialize_RXK_error_table();
770 initialize_KTC_error_table();
771 initialize_ACFG_error_table();
775 strcpy(tester, "tester");
776 strcpy(testerPassword, "xxx");
778 remoteTesterId = 0; /* don't try this */
780 /* parse arguments */
783 int arglen = strlen(argv[i]);
785 lcstring(arg, argv[i], sizeof(arg));
786 #define IsArg(a) (strncmp (arg,a, arglen) == 0)
789 else if (IsArg("-verbose"))
791 else if (IsArg("-printtoken"))
793 else if (IsArg("-remotecell"))
794 strncpy(cell, argv[++i], sizeof(cell));
795 else if (IsArg("-testid"))
796 testerId = atoi(argv[++i]);
797 else if (IsArg("-tester"))
798 strncpy(tester, argv[++i], sizeof(tester));
799 else if (IsArg("-testpassword"))
800 strncpy(testerPassword, argv[++i], sizeof(testerPassword));
801 else if (IsArg("-remotetestid"))
802 remoteTesterId = atoi(argv[++i]);
803 else if (IsArg("-remotetester"))
804 strncpy(remoteTester, argv[++i], sizeof(tester));
805 else if (IsArg("-remotetestpassword"))
806 strncpy(remoteTesterPassword, argv[++i],
807 sizeof(remoteTesterPassword));
809 fprintf(stderr, "unexpected arg '%s'\n", arg);
812 "Usage is: '%s [-quiet] [-verbose] [-remotecell <cellname>] [-testid <AFS ID>] [-tester <name>] -testpassword <pass> [-remotetestid <AFS ID> -remotetester <name> -remotetestpassword <pass>]\n",
819 /* get list of cells */
822 /* expand requested cell name */
823 code = ka_CellConfig(AFSCONF_CLIENTNAME);
825 afs_com_err(whoami, code, "calling cell config");
826 code = ka_ExpandCell(cell, cell, 0);
828 afs_com_err(whoami, code, "expanding cell %s", cell);
832 strcpy(server.name, "afs");
833 strcpy(server.instance, "");
834 strcpy(server.cell, cell);
836 code = ktc_GetToken(&server, &token, sizeof(token), &client);
838 afs_com_err(whoami, code, "so couldn't get afs token");
841 PrintAuthentication(stdout, &server, &token, &client);
842 } else { /* dummy up a token */
843 token.startTime = time(0);
844 token.endTime = token.startTime + 3600;
846 token.ticketLen = 48;
849 /* find a cell w/o tokens */
850 for (i = 0; i < nCells; i++) {
851 strcpy(server.cell, cellNameList[i]);
852 code = ktc_GetToken(&server, &ntoken, sizeof(ntoken), &nclient);
853 if ((code == KTC_NOENT) || ((code == 0) && (ntoken.endTime == 0)))
854 goto unused_cell_found;
856 fprintf(stderr, "All cells have tokens\n");
860 printf("Using unused cell %s\n", cellNameList[unusedCell]);
862 /* First check for various pathological cases */
864 strcpy(server.cell, "foo.bar.baz");
865 memcpy(&ntoken, &token, sizeof(ntoken));
866 code = ktc_SetToken(&server, &ntoken, &client, 0);
867 if (code != KTC_NOCELL) {
868 afs_com_err(whoami, code,
869 "should have gotten bad pioctl error calling SetToken with bogus cell name");
872 strcpy(server.cell, cellNameList[unusedCell]);
874 ntoken.ticketLen = 0;
875 code = ktc_SetToken(&server, &ntoken, &client, 0);
876 if ((code != KTC_TOOBIG) && (code != KTC_PIOCTLFAIL)) {
877 afs_com_err(whoami, code,
878 "should have gotten error calling SetToken with zero ticket length");
881 ntoken.ticketLen = token.ticketLen;
883 code = ktc_SetToken(&server, &ntoken, &client, 0);
885 afs_com_err(whoami, code, "calling SetToken with zero expiration time");
888 strcpy(nclient.name, "foo");
889 strcpy(nclient.instance, "bar");
890 strcpy(nclient.cell, "foo.bar.baz");
891 code = ktc_SetToken(&server, &ntoken, &nclient, 0);
893 afs_com_err(whoami, code, "calling SetToken with bogus client cell");
896 memcpy(&ntoken, &token, sizeof(ntoken));
897 if (token.kvno == 999)
900 /* Now check out SetToken parsing of specially formed names */
902 strcpy(nclient.instance, "");
903 /* cell is uniformly ignored */
905 sprintf(nclient.name, "AFS ID %d", viceId);
906 if (CheckAFSId(&server, &ntoken, &nclient))
909 if (CheckAFSId(&server, &ntoken, &nclient))
911 sprintf(nclient.name, "AFS ID 0%d", viceId);
912 if (CheckAFSId(&server, &ntoken, &nclient))
915 sprintf(nclient.name, "AFS ID %d", -44444);
916 if (CheckAFSId(&server, &ntoken, &nclient))
919 sprintf(nclient.name, "AFS ID %d", 0x7fffffff);
920 if (CheckAFSId(&server, &ntoken, &nclient))
923 sprintf(nclient.name, "AFS ID ");
924 if (CheckUnixUID(&server, &ntoken, &nclient))
926 sprintf(nclient.name, "AFS ID 10x");
927 if (CheckUnixUID(&server, &ntoken, &nclient))
929 sprintf(nclient.name, "foobar");
930 if (CheckUnixUID(&server, &ntoken, &nclient))
933 if (CheckUnixUID(&server, &ntoken, &nclient))
936 /* make sure simulated auth2 tokens still does something reasonable */
937 if (CheckAuth2(&server))
942 code = CheckAFSTickets(); /* returns in new PAG */