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 #include <afsconfig.h>
11 #include <afs/param.h>
16 #include <sys/types.h>
19 #include <afs/cellconfig.h>
31 char name[MAXKTCNAMELEN] = "guest";
32 char inst[MAXKTCNAMELEN] = "";
34 char aname[] = "AuthServer";
35 char ainst[] = "Admin";
38 print_entry(tentry, name, instance)
39 struct kaentryinfo *tentry;
44 char bob[KA_TIMESTR_LEN];
46 if (tentry->minor_version != KAMINORVERSION)
47 printf("Minor version number mismatch: got %d, expected %d\n",
48 tentry->minor_version, KAMINORVERSION);
49 ka_PrintUserID("User data for ", name, instance, "");
53 if (tentry->flags & KAFADMIN) {
54 printf("%sADMIN", prefix);
57 if (tentry->flags & KAFNOTGS) {
58 printf("%sNOTGS", prefix);
61 if (tentry->flags & KAFNOCPW) {
62 printf("%sNOCPW", prefix);
65 if (tentry->flags & KAFNOSEAL) {
66 printf("%sNOSEAL", prefix);
69 if (tentry->user_expiration <= now) {
70 printf("%sexpired", prefix);
73 if (strcmp(prefix, NEWPREFIX) == 0)
78 printf(" key (%d):", tentry->key_version);
79 ka_PrintBytes(&tentry->key, sizeof(tentry->key));
80 ka_timestr(tentry->change_password_time, bob, KA_TIMESTR_LEN);
81 printf(", last cpw: %s\n", bob);
82 ka_timestr(tentry->user_expiration, bob, KA_TIMESTR_LEN);
83 printf(" entry expires on %s. Max ticket lifetime %.2f hours.\n", bob,
84 tentry->max_ticket_lifetime / 3600.0);
85 ka_timestr(tentry->modification_time, bob, KA_TIMESTR_LEN);
86 printf(" last mod on %s by ", bob);
87 ka_PrintUserID("", tentry->modification_user.name,
88 tentry->modification_user.instance, "\n");
104 struct ktc_encryptionKey *userkey;
107 #define MAXADMINTOKENS 30
108 #define MAXTGSTOKENS 10
109 int nAdminTokens, nTGSTokens;
110 struct ktc_token adminTokens[MAXADMINTOKENS];
111 struct ktc_token tgsTokens[MAXTGSTOKENS];
113 /* depends on 10 updates in 10 seconds to get AutoCPW to trigger,
114 * also 90 seconds is the maximum password age,
115 * also 11 old keys per block. */
117 static int OKTestVector[] = {
118 0, 1000, 3000, 1005, 1005, 1005, 1006, 1006, 1007, 1007, 1007, 1007,
120 1011, 3012, 3012, 1015, 3017, 3017, 3017,
121 1021, 2024, 4024, 13026, 1028, 1028, 1028, 1028, 1028, 1028, 1028,
123 1031, 1031, 13032, 13032, 13032, 13032, 13032, 13032, 2037, 4037,
124 13040, 13040, 13041, 13041, 13042, 13042, 2049, 4049,
125 13050, 13051, 13052, 54, 55, 56,
126 2061, 4061, 65, 65, 65, 65, 65, 65, 65, 65, 65,
127 2073, 4073, 13073, 13073, 13074, 13075, 77,
128 2085, 4085, 85, 85, 85, 85, 85, 85, 85,
130 2100, 1103 /* should change primary on aa */ , 4105,
133 int nOKTestVector = sizeof(OKTestVector) / sizeof(int);
136 struct ktc_token tgt;
137 struct ktc_token atoken;
138 struct ubik_client *aconn; /* connection to authentication service */
139 struct ubik_client *tgsConn; /* connection to TGS */
140 struct ubik_client *adminConn; /* connection to maintenance service */
141 struct ktc_token ttoken;
142 struct kaentryinfo aentry;
143 struct ka_debugInfo info;
148 struct ktc_encryptionKey key;
149 char *aaname = "krbtgt";
150 char *aainst = "FAKECELL.EDU";
152 printf("checking old keys\n");
156 ka_AuthServerConn(localCell, KA_AUTHENTICATION_SERVICE, 0, &aconn))
158 ka_Authenticate(name, inst, localCell, aconn,
159 KA_TICKET_GRANTING_SERVICE, userkey, now,
160 now + 3600, &tgt, 0))
162 ka_Authenticate(name, inst, localCell, aconn,
163 KA_MAINTENANCE_SERVICE, userkey, now, now + 3600,
166 ka_AuthServerConn(localCell, KA_TICKET_GRANTING_SERVICE, 0,
169 ka_AuthServerConn(localCell, KA_MAINTENANCE_SERVICE, &atoken,
173 afs_com_err(whoami, code, "testing old keys");
177 code = ubik_Call(KAM_GetRandomKey, adminConn, 0, &key);
180 code = ubik_Call(KAM_CreateUser, adminConn, 0, aaname, aainst, key);
182 printf("Alternate Admin User already exists\n");
186 nAdminTokens = nTGSTokens = 0;
189 for (i = 0; i < nOKTestVector; i++) {
190 int v = OKTestVector[i]; /* get test vector */
196 if ((now = time(0)) < start + sleep)
197 IOMGR_Sleep(start + sleep - now);
201 if (sleep >= notify) {
202 printf("Now at %d seconds\n", sleep);
207 case 1: /* set krbtgt.FAKECELL.EDU password */
208 code = ubik_Call(KAM_GetRandomKey, adminConn, 0, &key);
212 ubik_Call(KAM_SetPassword, adminConn, 0, aaname, aainst, 0,
215 case 3: /* set AuthServer.Admin password */
216 case 13: /* and remember admin ticket */
217 code = ubik_Call(KAM_GetRandomKey, adminConn, 0, &key);
221 ubik_Call(KAM_SetPassword, adminConn, 0, aname, ainst, 0,
225 case 4: /* remeber Admin ticket and TGS ticket */
226 if (nAdminTokens >= MAXADMINTOKENS)
227 printf("Too many admin tokens\n");
230 ka_Authenticate(name, inst, localCell, aconn,
231 KA_MAINTENANCE_SERVICE, userkey, now,
232 now + 3600, &adminTokens[nAdminTokens++],
238 if (nTGSTokens >= MAXTGSTOKENS)
239 printf("Too many tgs tokens\n");
242 ka_Authenticate(name, inst, localCell, aconn,
243 KA_TICKET_GRANTING_SERVICE, userkey, now,
244 now + 3600, &tgsTokens[nTGSTokens++], 0);
248 ubik_Call(KAM_Debug, adminConn, 0, KAMAJORVERSION, 0, &info);
253 ("Now at %d seconds (really %d): %d updates and %d seconds remaining\n",
254 sleep, (now - start), info.updatesRemaining,
255 info.nextAutoCPW - now);
256 if (info.updatesRemaining > 1)
257 printf("Too many updates needed at time %d\n", sleep);
258 while ((now = time(0)) < info.nextAutoCPW) {
259 printf("...waiting for next auto CPW\n");
260 if (info.nextAutoCPW - now > 1)
266 ubik_Call(KAM_SetFields, adminConn, 0, name, inst, 0, 0,
267 100 * 3600, 0, /* spares */ 0,
272 ubik_Call(KAM_GetEntry, adminConn, 0, aname, ainst,
273 KAMAJORVERSION, &aentry);
278 afs_com_err(whoami, code, "at %d seconds: calling server with v=%x",
284 printf("Trying %d Admin tokens\n", nAdminTokens);
285 for (i = 0; i < nAdminTokens; i++) {
287 struct ubik_client *conn;
289 for (j = i + 1; j < nAdminTokens; j++)
290 if (adminTokens[i].kvno == adminTokens[j].kvno)
291 printf("Two admin tokens with kvno %d: %d and %d\n",
292 (int)adminTokens[i].kvno, i, j);
295 ka_AuthServerConn(localCell, KA_MAINTENANCE_SERVICE,
296 &adminTokens[i], &conn);
299 afs_com_err(whoami, code, "Checking admin token #%d with kvno %d\n",
300 i, (int)adminTokens[i].kvno);
304 ubik_Call(KAM_GetEntry, conn, 0, aname, ainst, KAMAJORVERSION,
310 printf("Trying %d TGS tokens\n", nTGSTokens);
311 for (i = 0; i < nTGSTokens; i++) {
313 struct ktc_token token;
315 for (j = i + 1; j < nTGSTokens; j++)
316 if (tgsTokens[i].kvno == tgsTokens[j].kvno)
317 printf("Two tgs tokens with kvno %d: %d and %d\n",
318 (int)tgsTokens[i].kvno, i, j);
321 ka_GetToken(name, inst, localCell, name, inst, tgsConn, now,
322 now + 3600, &tgsTokens[i], "", &token);
324 afs_com_err(whoami, code, "Checking tgs token #%d with kvno %d\n", i,
325 (int)tgsTokens[i].kvno);
330 code = ubik_Call(KAM_DeleteUser, adminConn, 0, aaname, aainst);
332 afs_com_err(whoami, code, "Deleting alternate admin user");
344 long serverList[MAXSERVERS];
347 struct ktc_encryptionKey key;
348 struct ktc_token tgt;
349 struct ktc_token token;
350 struct ktc_token atoken;
351 struct ubik_client *aconn; /* connection to authentication service */
352 struct ubik_client *conn;
353 struct ubik_client *lpbkConn = 0;
354 struct kaentryinfo tentry;
357 char password[BUFSIZ];
359 password needs to be at least 1000 chars long;
361 static char source[] =
362 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0987654321";
363 static int truncate[] =
364 { 1000, 750, 562, 432, 316, 237, 178, 133, 100, 75, 56, 42, 32, 24,
365 18, 13, 10, 8, 6, 4, 3, 2, 1, 0
367 static char answer[sizeof(truncate) / sizeof(int)][32] =
368 { "\250y\3161\315\250\361\274", "\212\133\133\345\236\206\362\200",
369 "\230b\354\334\302F\352\040", "\001\221T\016\265T\376\100",
370 "X\002\224g\250\221\214\340", "\241p\304\032\135\0328\361",
371 "\010\352\037\236sp\046\212", "\3522\352\325\247\313\023W",
372 "\023\310\034\315\265\227L\203", "z\373RJ\233\304\046m",
373 "\310\244\032\375\3704\045\323", "n\224\3022\034\376\013\247",
374 "\217\343\302\364\177\277\052\214",
375 "\357\337\010\054sv\332\057", "\373\373\316u\247\302\362g",
376 "\214O\007m\320\221\301\174", "\002\057OQ\031p\370u",
377 "k\224s\235\362\247\230\206", "\364\233\334\211\235\217k\205",
378 "\352\203m\212s\337\211d",
379 "k\354\256\364\222\352\265\323", "\205\135d\351\326\334\260\313",
380 "\345\250\331\340\265hd\222",
381 "\346\265\352\136\316\205\217\313"
383 struct ktc_encryptionKey correct_key;
388 args[1] = "-servers";
391 gethostname(hostname, sizeof(hostname));
394 /* test string hacking */
395 if ((strcmp(lcstring(name, "AbcDe", 5), "abcd") != 0)
396 || (strcmp(lcstring(name, "AbcDe", 6), "abcde") != 0)
397 || (strcmp(ucstring(inst, "AbcDe", 4), "ABC") != 0)
398 || (strcmp(ucstring(inst, "AbcDe", sizeof(inst)), "ABCDE") != 0)) {
399 printf("uc/lc string problem\n");
402 #define tryscc(A,B,a,b) (sign(strcasecmp (A,B)) != sign (strcmp (a,b)))
403 if (tryscc("Abc", "abc", "abc", "abc") || tryscc("aB", "ABC", "ab", "abc")
404 || tryscc("ABC", "ab", "abc", "ab")
405 || tryscc("Abcd", "aBg", "abcd", "abg")) {
406 printf("strcasecmp problem\n");
410 strcpy(password, "");
411 for (i = 0; i < 100; i++)
412 for (j = 0; j < 10; j++)
413 password[i * 10 + j] = source[i % (sizeof(source) - 1)];
415 code = ka_CellConfig(AFSCONF_CLIENTNAME);
417 afs_com_err(whoami, code, "calling cell config");
418 localCell = ka_LocalCell();
420 for (i = 0; i < (sizeof(truncate) / sizeof(int)); i++) {
421 password[truncate[i]] = 0;
422 ka_StringToKey(password, "andy.edu", &key);
423 ka_ReadBytes(answer[i], &correct_key, sizeof(key));
424 if (memcmp(&key, &correct_key, sizeof(key)) != 0) {
426 ("String to key error converting '%s'; should be '%s' instead got '",
427 password, answer[i]);
428 ka_PrintBytes(&key, sizeof(key));
433 memset(password, 0, sizeof(password));
434 j = 0; /* current password length */
435 for (i = (sizeof(truncate) / sizeof(int)) - 1; i >= 0; i--) {
436 while (j < truncate[i]) {
437 password[j] = source[j / 10 % (sizeof(source) - 1)];
440 ka_StringToKey(password, "andy.edu", &key);
441 ka_ReadBytes(answer[i], &correct_key, sizeof(key));
442 if (memcmp(&key, &correct_key, sizeof(key)) != 0) {
444 ("String to key error converting '%s'; should be '%s' instead got '",
445 password, answer[i]);
446 ka_PrintBytes(&key, sizeof(key));
451 strcpy(name, "guest");
456 afs_com_err(whoami, code, "rx_Init'ing");
459 if (code = ka_Init(0)) {
460 afs_com_err(whoami, code, "ka_Init'ing");
463 if (code = ubik_ParseClientList(3, args, serverList)) {
464 afs_com_err(whoami, code, "parsing Ubik server list");
467 ka_ExplicitCell(localCell, serverList);
470 struct rx_connection *conns[2];
471 struct rx_securityClass *sc;
472 int si; /* security class index */
474 sc = rxnull_NewClientSecurityObject();
475 si = RX_SCINDEX_NULL;
477 rx_NewConnection(htonl(INADDR_LOOPBACK), htons(AFSCONF_KAUTHPORT),
478 KA_MAINTENANCE_SERVICE, sc, si);
480 code = ubik_ClientInit(conns, &lpbkConn);
483 afs_com_err(whoami, code,
484 "getting %s's password via loopback connection to GetPassword",
488 code = ubik_Call(KAM_GetPassword, lpbkConn, 0, name, &key);
489 if (code == KANOAUTH) {
490 printf("GetPassword disabled\n");
491 ka_StringToKey(name, localCell, &key);
496 /* first just get TGS ticket */
497 code = ka_AuthServerConn(localCell, KA_AUTHENTICATION_SERVICE, 0, &aconn);
500 afs_com_err(whoami, code, "connecting to authentication service");
503 end = now + 100 * 3600 + 2;
505 ka_Authenticate(name, inst, localCell, aconn,
506 KA_TICKET_GRANTING_SERVICE, &key, now, end, &tgt, 0);
509 if (tgt.endTime == end) {
511 "*** AuthTicket expires too late: must be old style sever ***\n");
512 } else if (tgt.endTime != now + 100 * 3600) {
513 fprintf(stderr, "Bogus expiration because lifetime (%d) wrong\n",
514 tgt.endTime - tgt.startTime);
518 /* try to get ticket w/ time jitter */
520 ka_Authenticate(name, inst, localCell, aconn, KA_MAINTENANCE_SERVICE,
521 &key, now + KTC_TIME_UNCERTAINTY / 2, now + 3600,
525 afs_com_err(whoami, code, "using admin ticket with time jitter");
530 ka_AuthServerConn(localCell, KA_MAINTENANCE_SERVICE, &token, &conn);
534 ubik_Call(KAM_GetEntry, conn, 0, name, inst, KAMAJORVERSION, &tentry);
537 print_entry(&tentry, name, inst);
540 struct ktc_encryptionKey badkey;
542 memcpy(&badkey, &key, sizeof(badkey));
543 *(int *)&badkey ^= 1; /* toggle some bit */
544 code = ubik_Call(KAM_SetPassword, conn, 0, name, inst, 0, badkey);
545 if (code != KABADKEY) {
547 afs_com_err(whoami, code, "Trying to set bad key");
550 memset(&badkey, 0, sizeof(badkey));
551 code = ubik_Call(KAM_SetPassword, conn, 0, name, inst, 0, badkey);
552 if (code != KABADKEY)
554 code = ubik_Call(KAM_SetPassword, conn, 0, name, inst, 9999, key);
555 if (code != KABADARGUMENT)
559 /* try using ticket with no expiration time */
561 struct ktc_encryptionKey akey;
562 struct kaentryinfo aentry;
564 ka_StringToKey("authserv", localCell, &akey);
566 code = ubik_Call(KAM_SetPassword, conn, 0, aname, ainst, 0, akey);
569 afs_com_err(whoami, code, "Checking SetPassword");
573 ubik_Call(KAM_GetEntry, conn, 0, aname, ainst, KAMAJORVERSION,
577 atoken.kvno = aentry.key_version;
578 for (i = 0; i < sizeof(aentry.key); i++)
579 if (((char *)&aentry.key)[i]) {
583 code = ubik_Call(KAM_GetRandomKey, conn, 0, &atoken.sessionKey);
586 printf("Got random sessionKey: ");
587 ka_PrintBytes(&atoken.sessionKey, sizeof(key));
590 atoken.startTime = 0;
591 atoken.endTime = NEVERDATE;
593 tkt_MakeTicket(atoken.ticket, &atoken.ticketLen, &akey, name,
594 inst, "", atoken.startTime, atoken.endTime,
595 &atoken.sessionKey, 0, aname, ainst);
598 afs_com_err(whoami, code, "faking up AuthServer ticket");
602 struct ktc_principal client;
603 struct ktc_encryptionKey sessionkey;
608 tkt_DecodeTicket(atoken.ticket, atoken.ticketLen, &akey,
609 client.name, client.instance, client.cell,
610 &sessionkey, &host, &start, &end);
613 if (code = tkt_CheckTimes(start, end, time(0)) <= 0)
616 if (!des_check_key_parity(&sessionkey)
617 || des_is_weak_key(&sessionkey)) {
625 ka_AuthServerConn(localCell, KA_MAINTENANCE_SERVICE, &atoken, &conn);
629 struct kaentryinfo entry;
632 ubik_Call(KAM_GetEntry, conn, 0, name, inst, KAMAJORVERSION,
636 if (memcmp(&tentry, &entry, sizeof(entry)) != 0) {
637 printf("Entries obtained not the same!\n");
638 print_entry(&entry, name, inst);
642 /* try bashing a ticket to make sure it fails to work */
643 memset(atoken.ticket + 10, 0, 1);
645 ka_AuthServerConn(localCell, KA_MAINTENANCE_SERVICE, &atoken, &conn);
647 afs_com_err(whoami, code, "contacting admin server with bashed ticket");
648 exit(0); /* this is supposed to happen */
651 ubik_Call(KAM_GetEntry, conn, 0, name, inst, KAMAJORVERSION, &tentry);
652 if (code != RXKADBADTICKET) {
653 afs_com_err(whoami, code,
654 "GetEntry failed to fail even with damaged ticket!!!!\n");
660 printf("All clear!\n");
664 afs_com_err(whoami, code, "calling SetPAG");
666 printf("Calling SetPAG and exec'ing %s\n", argv[1]);
667 execve(argv[1], argv + 1, 0);
668 perror("execve returned");