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>
15 #include <sys/types.h>
18 #include <afs/cellconfig.h>
30 char name[MAXKTCNAMELEN] = "guest";
31 char inst[MAXKTCNAMELEN] = "";
33 char aname[] = "AuthServer";
34 char ainst[] = "Admin";
36 static print_entry (tentry, name, instance)
37 struct kaentryinfo *tentry;
41 char bob[KA_TIMESTR_LEN];
43 if (tentry->minor_version != KAMINORVERSION)
44 printf ("Minor version number mismatch: got %d, expected %d\n",
45 tentry->minor_version, KAMINORVERSION);
46 ka_PrintUserID ("User data for ", name, instance, "");
47 { char *prefix = " (";
49 if (tentry->flags & KAFADMIN) { printf ("%sADMIN", prefix); prefix = NEWPREFIX; }
50 if (tentry->flags & KAFNOTGS) { printf ("%sNOTGS", prefix); prefix = NEWPREFIX; }
51 if (tentry->flags & KAFNOCPW) { printf ("%sNOCPW", prefix); prefix = NEWPREFIX; }
52 if (tentry->flags & KAFNOSEAL) { printf ("%sNOSEAL", prefix); prefix = NEWPREFIX; }
53 if (tentry->user_expiration <= now) { printf ("%sexpired", prefix); prefix = NEWPREFIX; }
54 if (strcmp (prefix, NEWPREFIX) == 0) printf (")\n");
57 printf (" key (%d):", tentry->key_version);
58 ka_PrintBytes (&tentry->key, sizeof(tentry->key));
59 ka_timestr(tentry->change_password_time, bob, KA_TIMESTR_LEN);
60 printf (", last cpw: %s\n", bob);
61 ka_timestr(tentry->user_expiration,bob, KA_TIMESTR_LEN);
62 printf (" entry expires on %s. Max ticket lifetime %.2f hours.\n",
63 bob, tentry->max_ticket_lifetime / 3600.0);
64 ka_timestr(tentry->modification_time,bob, KA_TIMESTR_LEN);
65 printf (" last mod on %s by ", bob);
66 ka_PrintUserID ("", tentry->modification_user.name,
67 tentry->modification_user.instance, "\n");
77 void TestOldKeys (userkey)
78 struct ktc_encryptionKey *userkey;
81 #define MAXADMINTOKENS 30
82 #define MAXTGSTOKENS 10
83 int nAdminTokens, nTGSTokens;
84 struct ktc_token adminTokens[MAXADMINTOKENS];
85 struct ktc_token tgsTokens[MAXTGSTOKENS];
87 /* depends on 10 updates in 10 seconds to get AutoCPW to trigger,
88 also 90 seconds is the maximum password age,
89 also 11 old keys per block. */
91 static int OKTestVector[] = {
92 0, 1000, 3000, 1005, 1005, 1005, 1006, 1006, 1007, 1007, 1007, 1007, 1008,
93 1011, 3012, 3012, 1015, 3017, 3017, 3017,
94 1021, 2024, 4024, 13026, 1028, 1028, 1028, 1028, 1028, 1028, 1028, 1028,
95 1031, 1031, 13032, 13032, 13032, 13032, 13032, 13032, 2037, 4037,
96 13040, 13040, 13041, 13041, 13042, 13042, 2049, 4049,
97 13050, 13051, 13052, 54, 55, 56,
98 2061, 4061, 65, 65, 65, 65, 65, 65, 65, 65, 65,
99 2073, 4073, 13073, 13073, 13074, 13075, 77,
100 2085, 4085, 85, 85, 85, 85, 85, 85, 85,
102 2100, 1103 /* should change primary on aa */, 4105,
104 int nOKTestVector = sizeof(OKTestVector) / sizeof(int);
107 struct ktc_token tgt;
108 struct ktc_token atoken;
109 struct ubik_client *aconn; /* connection to authentication service */
110 struct ubik_client *tgsConn; /* connection to TGS */
111 struct ubik_client *adminConn; /* connection to maintenance service */
112 struct ktc_token ttoken;
113 struct kaentryinfo aentry;
114 struct ka_debugInfo info;
119 struct ktc_encryptionKey key;
120 char *aaname = "krbtgt";
121 char *aainst = "FAKECELL.EDU";
123 printf ("checking old keys\n");
126 if ((code = ka_AuthServerConn (localCell, KA_AUTHENTICATION_SERVICE, 0, &aconn)) ||
127 (code = ka_Authenticate (name, inst, localCell, aconn,
128 KA_TICKET_GRANTING_SERVICE,
129 userkey, now, now+3600, &tgt, 0 )) ||
130 (code = ka_Authenticate (name, inst, localCell, aconn,
131 KA_MAINTENANCE_SERVICE,
132 userkey, now, now+3600, &atoken, 0 )) ||
133 (code = ka_AuthServerConn (localCell, KA_TICKET_GRANTING_SERVICE, 0, &tgsConn)) ||
134 (code = ka_AuthServerConn (localCell, KA_MAINTENANCE_SERVICE, &atoken, &adminConn))
137 com_err (whoami, code, "testing old keys");
141 code = ubik_Call (KAM_GetRandomKey, adminConn, 0, &key);
142 if (code) goto abort;
143 code = ubik_Call (KAM_CreateUser, adminConn, 0, aaname, aainst, key);
144 if (code == KAEXIST) printf ("Alternate Admin User already exists\n");
145 else if (code) goto abort;
147 nAdminTokens = nTGSTokens = 0;
150 for (i=0; i<nOKTestVector; i++) {
151 int v = OKTestVector[i]; /* get test vector */
157 if ((now=time(0)) < start+sleep)
158 IOMGR_Sleep (start+sleep - now);
161 if (sleep >= notify) {
162 printf ("Now at %d seconds\n", sleep);
167 case 1: /* set krbtgt.FAKECELL.EDU password */
168 code = ubik_Call (KAM_GetRandomKey, adminConn, 0, &key);
169 if (code) goto abort_1;
170 code = ubik_Call (KAM_SetPassword, adminConn, 0, aaname, aainst, 0, key);
172 case 3: /* set AuthServer.Admin password */
173 case 13: /* and remember admin ticket */
174 code = ubik_Call (KAM_GetRandomKey, adminConn, 0, &key);
175 if (code) goto abort_1;
176 code = ubik_Call (KAM_SetPassword, adminConn, 0, aname, ainst, 0, key);
178 case 4: /* remeber Admin ticket and TGS ticket */
179 if (nAdminTokens >= MAXADMINTOKENS) printf ("Too many admin tokens\n");
180 else code = ka_Authenticate (name, inst, localCell, aconn, KA_MAINTENANCE_SERVICE,
181 userkey, now, now+3600,
182 &adminTokens[nAdminTokens++], 0);
183 if (code) goto abort_1;
185 if (nTGSTokens >= MAXTGSTOKENS) printf ("Too many tgs tokens\n");
186 else code = ka_Authenticate (name, inst, localCell, aconn, KA_TICKET_GRANTING_SERVICE,
187 userkey, now, now+3600,
188 &tgsTokens[nTGSTokens++], 0);
191 code = ubik_Call (KAM_Debug, adminConn, 0, KAMAJORVERSION, 0, &info);
192 if (code) goto abort_1;
194 printf ("Now at %d seconds (really %d): %d updates and %d seconds remaining\n",
195 sleep, (now-start), info.updatesRemaining, info.nextAutoCPW-now);
196 if (info.updatesRemaining > 1)
197 printf ("Too many updates needed at time %d\n", sleep);
198 while ((now=time(0))<info.nextAutoCPW) {
199 printf ("...waiting for next auto CPW\n");
200 if (info.nextAutoCPW-now > 1) IOMGR_Sleep (1);
203 code = ubik_Call (KAM_SetFields, adminConn, 0,
204 name, inst, 0, 0, 100*3600, 0, /* spares */ 0,0);
207 code = ubik_Call (KAM_GetEntry, adminConn, 0, aname, ainst, KAMAJORVERSION, &aentry);
212 com_err (whoami, code, "at %d seconds: calling server with v=%x", sleep, v);
217 printf ("Trying %d Admin tokens\n", nAdminTokens);
218 for (i=0; i<nAdminTokens; i++) {
220 struct ubik_client *conn;
222 for (j=i+1; j<nAdminTokens; j++)
223 if (adminTokens[i].kvno == adminTokens[j].kvno)
224 printf ("Two admin tokens with kvno %d: %d and %d\n",
225 (int)adminTokens[i].kvno, i, j);
227 code = ka_AuthServerConn (localCell, KA_MAINTENANCE_SERVICE, &adminTokens[i], &conn);
230 com_err (whoami, code, "Checking admin token #%d with kvno %d\n",
231 i, (int)adminTokens[i].kvno);
234 code = ubik_Call (KAM_GetEntry, conn, 0, aname, ainst, KAMAJORVERSION, &aentry);
235 if (code) goto abort_ta;
238 printf ("Trying %d TGS tokens\n", nTGSTokens);
239 for (i=0; i<nTGSTokens; i++) {
241 struct ktc_token token;
243 for (j=i+1; j<nTGSTokens; j++)
244 if (tgsTokens[i].kvno == tgsTokens[j].kvno)
245 printf ("Two tgs tokens with kvno %d: %d and %d\n",
246 (int)tgsTokens[i].kvno, i, j);
248 code = ka_GetToken (name, inst, localCell, name, inst, tgsConn, now, now+3600, &tgsTokens[i], "", &token);
250 com_err (whoami, code, "Checking tgs token #%d with kvno %d\n",
251 i, (int)tgsTokens[i].kvno);
256 code = ubik_Call (KAM_DeleteUser, adminConn, 0, aaname, aainst);
258 com_err (whoami, code, "Deleting alternate admin user");
264 int main (argc, argv)
269 long serverList[MAXSERVERS];
272 struct ktc_encryptionKey key;
273 struct ktc_token tgt;
274 struct ktc_token token;
275 struct ktc_token atoken;
276 struct ubik_client *aconn; /* connection to authentication service */
277 struct ubik_client *conn;
278 struct ubik_client *lpbkConn=0;
279 struct kaentryinfo tentry;
282 char password[BUFSIZ];
284 password needs to be at least 1000 chars long;
286 static char source[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0987654321";
287 static int truncate[] = {1000, 750, 562, 432, 316, 237, 178, 133, 100, 75, 56, 42, 32, 24, 18, 13, 10, 8, 6, 4, 3, 2, 1, 0};
288 static char answer[sizeof(truncate)/sizeof(int)][32] = {"\250y\3161\315\250\361\274", "\212\133\133\345\236\206\362\200", "\230b\354\334\302F\352\040", "\001\221T\016\265T\376\100", "X\002\224g\250\221\214\340", "\241p\304\032\135\0328\361", "\010\352\037\236sp\046\212", "\3522\352\325\247\313\023W", "\023\310\034\315\265\227L\203", "z\373RJ\233\304\046m", "\310\244\032\375\3704\045\323", "n\224\3022\034\376\013\247", "\217\343\302\364\177\277\052\214", "\357\337\010\054sv\332\057", "\373\373\316u\247\302\362g", "\214O\007m\320\221\301\174", "\002\057OQ\031p\370u", "k\224s\235\362\247\230\206", "\364\233\334\211\235\217k\205", "\352\203m\212s\337\211d", "k\354\256\364\222\352\265\323", "\205\135d\351\326\334\260\313", "\345\250\331\340\265hd\222", "\346\265\352\136\316\205\217\313"};
289 struct ktc_encryptionKey correct_key;
294 args[1] = "-servers";
297 gethostname(hostname,sizeof(hostname));
300 /* test string hacking */
301 if ((strcmp (lcstring (name, "AbcDe", 5), "abcd") != 0) ||
302 (strcmp (lcstring (name, "AbcDe", 6), "abcde") != 0) ||
303 (strcmp (ucstring (inst, "AbcDe", 4), "ABC") != 0) ||
304 (strcmp (ucstring (inst, "AbcDe", sizeof(inst)), "ABCDE") != 0)) {
305 printf ("uc/lc string problem\n");
308 #define tryscc(A,B,a,b) (sign(strcasecmp (A,B)) != sign (strcmp (a,b)))
309 if (tryscc ("Abc", "abc", "abc", "abc") ||
310 tryscc ("aB", "ABC", "ab", "abc") ||
311 tryscc ("ABC", "ab", "abc", "ab") ||
312 tryscc ("Abcd", "aBg", "abcd", "abg")) {
313 printf ("strcasecmp problem\n");
317 strcpy (password, "");
318 for (i=0; i<100; i++)
320 password[i*10+j] = source[i % (sizeof(source)-1)];
322 code = ka_CellConfig (AFSCONF_CLIENTNAME);
323 if (code) com_err (whoami, code, "calling cell config");
324 localCell = ka_LocalCell();
326 for (i=0; i<(sizeof(truncate)/sizeof(int)); i++) {
327 password[truncate[i]] = 0;
328 ka_StringToKey (password, "andy.edu", &key);
329 ka_ReadBytes (answer[i], &correct_key, sizeof(key));
330 if (memcmp (&key, &correct_key, sizeof(key)) != 0) {
331 printf ("String to key error converting '%s'; should be '%s' instead got '",
332 password, answer[i]);
333 ka_PrintBytes (&key, sizeof(key));
338 memset(password, 0, sizeof(password));
339 j=0; /* current password length */
340 for (i=(sizeof(truncate)/sizeof(int))-1; i>=0; i--) {
341 while (j<truncate[i]) {
342 password[j] = source[j/10 % (sizeof(source)-1)];
345 ka_StringToKey (password, "andy.edu", &key);
346 ka_ReadBytes (answer[i], &correct_key, sizeof(key));
347 if (memcmp (&key, &correct_key, sizeof(key)) != 0) {
348 printf ("String to key error converting '%s'; should be '%s' instead got '",
349 password, answer[i]);
350 ka_PrintBytes (&key, sizeof(key));
355 strcpy (name, "guest");
360 com_err (whoami, code, "rx_Init'ing");
363 if (code = ka_Init(0)) {
364 com_err (whoami, code, "ka_Init'ing");
367 if (code = ubik_ParseClientList(3, args, serverList)) {
368 com_err (whoami, code, "parsing Ubik server list");
371 ka_ExplicitCell (localCell, serverList);
373 { struct rx_connection *conns[2];
374 struct rx_securityClass *sc;
375 int si; /* security class index */
377 sc = rxnull_NewClientSecurityObject();
378 si = RX_SCINDEX_NULL;
379 conns[0] = rx_NewConnection (htonl(INADDR_LOOPBACK), htons(AFSCONF_KAUTHPORT),
380 KA_MAINTENANCE_SERVICE, sc, si);
382 code = ubik_ClientInit(conns, &lpbkConn);
385 com_err (whoami, code,
386 "getting %s's password via loopback connection to GetPassword", name);
389 code = ubik_Call (KAM_GetPassword, lpbkConn, 0, name, &key);
390 if (code == KANOAUTH) {
391 printf ("GetPassword disabled\n");
392 ka_StringToKey (name, localCell, &key);
394 else if (code) goto abort_4;
397 /* first just get TGS ticket */
398 code = ka_AuthServerConn (localCell, KA_AUTHENTICATION_SERVICE, 0, &aconn);
401 com_err (whoami, code, "connecting to authentication service");
404 end = now+100*3600+2;
405 code = ka_Authenticate (name, inst, localCell, aconn,
406 KA_TICKET_GRANTING_SERVICE,
407 &key, now, end, &tgt, 0);
408 if (code) goto abort;
409 if (tgt.endTime == end) {
410 fprintf (stderr, "*** AuthTicket expires too late: must be old style sever ***\n");
411 } else if (tgt.endTime != now+100*3600) {
412 fprintf (stderr, "Bogus expiration because lifetime (%d) wrong\n",
413 tgt.endTime - tgt.startTime);
417 /* try to get ticket w/ time jitter */
418 code = ka_Authenticate (name, inst, localCell, aconn,
419 KA_MAINTENANCE_SERVICE, &key,
420 now+KTC_TIME_UNCERTAINTY/2, now+3600, &token, 0);
423 com_err (whoami, code, "using admin ticket with time jitter");
427 code = ka_AuthServerConn (localCell, KA_MAINTENANCE_SERVICE, &token, &conn);
428 if (code) goto abort_1;
429 code = ubik_Call (KAM_GetEntry, conn, 0, name, inst, KAMAJORVERSION, &tentry);
430 if (code) goto abort_1;
431 print_entry (&tentry, name, inst);
433 { struct ktc_encryptionKey badkey;
435 memcpy(&badkey, &key, sizeof(badkey));
436 *(int *)&badkey ^= 1; /* toggle some bit */
437 code = ubik_Call (KAM_SetPassword, conn, 0, name, inst, 0, badkey);
438 if (code != KABADKEY) {
440 com_err (whoami, code, "Trying to set bad key");
443 memset(&badkey, 0, sizeof(badkey));
444 code = ubik_Call (KAM_SetPassword, conn, 0, name, inst, 0, badkey);
445 if (code != KABADKEY) goto abort_5;
446 code = ubik_Call (KAM_SetPassword, conn, 0, name, inst, 9999, key);
447 if (code != KABADARGUMENT) goto abort_5;
450 /* try using ticket with no expiration time */
451 { struct ktc_encryptionKey akey;
452 struct kaentryinfo aentry;
454 ka_StringToKey ("authserv", localCell, &akey);
456 code = ubik_Call (KAM_SetPassword, conn, 0, aname, ainst, 0, akey);
459 com_err (whoami, code, "Checking SetPassword");
462 code = ubik_Call (KAM_GetEntry, conn, 0, aname, ainst, KAMAJORVERSION, &aentry);
463 if (code) goto abort_6;
464 atoken.kvno = aentry.key_version;
465 for (i=0; i<sizeof(aentry.key); i++) if (((char *)&aentry.key)[i]) {
469 code = ubik_Call (KAM_GetRandomKey, conn, 0, &atoken.sessionKey);
470 if (code) goto abort_3;
471 printf ("Got random sessionKey: ");
472 ka_PrintBytes (&atoken.sessionKey, sizeof(key));
475 atoken.startTime = 0;
476 atoken.endTime = NEVERDATE;
477 code = tkt_MakeTicket (atoken.ticket, &atoken.ticketLen, &akey, name, inst, "",
478 atoken.startTime, atoken.endTime, &atoken.sessionKey,
482 com_err (whoami, code, "faking up AuthServer ticket");
485 { struct ktc_principal client;
486 struct ktc_encryptionKey sessionkey;
490 code = tkt_DecodeTicket (atoken.ticket, atoken.ticketLen, &akey,
491 client.name, client.instance, client.cell,
492 &sessionkey, &host, &start, &end);
493 if (code) goto abort_3;
494 if (code = tkt_CheckTimes (start, end, time(0)) <= 0) goto abort_3;
496 if (!des_check_key_parity (&sessionkey) ||
497 des_is_weak_key (&sessionkey))
498 { code = KABADKEY; goto abort_3;}
502 code = ka_AuthServerConn (localCell, KA_MAINTENANCE_SERVICE, &atoken, &conn);
503 if (code) goto abort_3;
504 { struct kaentryinfo entry;
506 code = ubik_Call (KAM_GetEntry, conn, 0, name, inst, KAMAJORVERSION, &entry);
507 if (code) goto abort_3;
508 if (memcmp (&tentry, &entry, sizeof(entry)) != 0) {
509 printf ("Entries obtained not the same!\n");
510 print_entry (&entry, name, inst);
514 /* try bashing a ticket to make sure it fails to work */
515 memset(atoken.ticket+10, 0, 1);
516 code = ka_AuthServerConn (localCell, KA_MAINTENANCE_SERVICE, &atoken, &conn);
518 com_err (whoami, code, "contacting admin server with bashed ticket");
519 exit (0); /* this is supposed to happen */
521 code = ubik_Call (KAM_GetEntry, conn, 0, name, inst, KAMAJORVERSION, &tentry);
522 if (code != RXKADBADTICKET) {
523 com_err(whoami, code, "GetEntry failed to fail even with damaged ticket!!!!\n");
529 printf ("All clear!\n");
532 if (code) com_err (whoami, code, "calling SetPAG");
533 else printf ("Calling SetPAG and exec'ing %s\n", argv[1]);
534 execve (argv[1], argv+1, 0);
535 perror ("execve returned");