comerr-rename-20070410
[openafs.git] / src / kauth / test / test_badtix.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 #include <afsconfig.h>
11 #include <afs/param.h>
12
13 RCSID
14     ("$Header$");
15
16 #include <sys/types.h>
17 #include <des.h>
18 #include <afs/auth.h>
19 #include <afs/cellconfig.h>
20 #include <rx/xdr.h>
21 #include <rx/rx.h>
22 #include <rx/rxkad.h>
23 #include <lock.h>
24 #include <ubik.h>
25 #include <lwp.h>
26 #include "kauth.h"
27 #include "kautils.h"
28
29 char *whoami;
30 char *localCell;
31 char name[MAXKTCNAMELEN] = "guest";
32 char inst[MAXKTCNAMELEN] = "";
33
34 char aname[] = "AuthServer";
35 char ainst[] = "Admin";
36
37 static
38 print_entry(tentry, name, instance)
39      struct kaentryinfo *tentry;
40      char *name;
41      char *instance;
42 {
43     Date now = time(0);
44     char bob[KA_TIMESTR_LEN];
45
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, "");
50     {
51         char *prefix = " (";
52 #define NEWPREFIX "+"
53         if (tentry->flags & KAFADMIN) {
54             printf("%sADMIN", prefix);
55             prefix = NEWPREFIX;
56         }
57         if (tentry->flags & KAFNOTGS) {
58             printf("%sNOTGS", prefix);
59             prefix = NEWPREFIX;
60         }
61         if (tentry->flags & KAFNOCPW) {
62             printf("%sNOCPW", prefix);
63             prefix = NEWPREFIX;
64         }
65         if (tentry->flags & KAFNOSEAL) {
66             printf("%sNOSEAL", prefix);
67             prefix = NEWPREFIX;
68         }
69         if (tentry->user_expiration <= now) {
70             printf("%sexpired", prefix);
71             prefix = NEWPREFIX;
72         }
73         if (strcmp(prefix, NEWPREFIX) == 0)
74             printf(")\n");
75         else
76             printf("\n");
77     }
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");
89 }
90
91 int
92 sign(x)
93      int x;
94 {
95     if (x < 0)
96         return -1;
97     if (x > 0)
98         return 1;
99     return 0;
100 }
101
102 void
103 TestOldKeys(userkey)
104      struct ktc_encryptionKey *userkey;
105 {
106
107 #define MAXADMINTOKENS 30
108 #define MAXTGSTOKENS 10
109     int nAdminTokens, nTGSTokens;
110     struct ktc_token adminTokens[MAXADMINTOKENS];
111     struct ktc_token tgsTokens[MAXTGSTOKENS];
112
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. */
116
117     static int OKTestVector[] = {
118         0, 1000, 3000, 1005, 1005, 1005, 1006, 1006, 1007, 1007, 1007, 1007,
119         1008,
120         1011, 3012, 3012, 1015, 3017, 3017, 3017,
121         1021, 2024, 4024, 13026, 1028, 1028, 1028, 1028, 1028, 1028, 1028,
122         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,
129         13093,
130         2100, 1103 /* should change primary on aa */ , 4105,
131         13111
132     };
133     int nOKTestVector = sizeof(OKTestVector) / sizeof(int);
134
135     long code;
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;
144     Date now = time(0);
145     Date start;
146     int notify;
147     int i;
148     struct ktc_encryptionKey key;
149     char *aaname = "krbtgt";
150     char *aainst = "FAKECELL.EDU";
151
152     printf("checking old keys\n");
153
154     /* get tickets */
155     if ((code =
156          ka_AuthServerConn(localCell, KA_AUTHENTICATION_SERVICE, 0, &aconn))
157         || (code =
158             ka_Authenticate(name, inst, localCell, aconn,
159                             KA_TICKET_GRANTING_SERVICE, userkey, now,
160                             now + 3600, &tgt, 0))
161         || (code =
162             ka_Authenticate(name, inst, localCell, aconn,
163                             KA_MAINTENANCE_SERVICE, userkey, now, now + 3600,
164                             &atoken, 0))
165         || (code =
166             ka_AuthServerConn(localCell, KA_TICKET_GRANTING_SERVICE, 0,
167                               &tgsConn))
168         || (code =
169             ka_AuthServerConn(localCell, KA_MAINTENANCE_SERVICE, &atoken,
170                               &adminConn))
171         ) {
172       abort:
173         afs_com_err(whoami, code, "testing old keys");
174         exit(1);
175     }
176
177     code = ubik_Call(KAM_GetRandomKey, adminConn, 0, &key);
178     if (code)
179         goto abort;
180     code = ubik_Call(KAM_CreateUser, adminConn, 0, aaname, aainst, key);
181     if (code == KAEXIST)
182         printf("Alternate Admin User already exists\n");
183     else if (code)
184         goto abort;
185
186     nAdminTokens = nTGSTokens = 0;
187     start = time(0);
188     notify = 10;
189     for (i = 0; i < nOKTestVector; i++) {
190         int v = OKTestVector[i];        /* get test vector */
191         int sleep;
192
193         sleep = v % 1000;
194         v = v / 1000;
195
196         if ((now = time(0)) < start + sleep)
197             IOMGR_Sleep(start + sleep - now);
198         else
199             IOMGR_Poll();
200         now = time(0);
201         if (sleep >= notify) {
202             printf("Now at %d seconds\n", sleep);
203             notify = sleep + 10;
204         }
205
206         switch (v) {
207         case 1:         /* set krbtgt.FAKECELL.EDU password */
208             code = ubik_Call(KAM_GetRandomKey, adminConn, 0, &key);
209             if (code)
210                 goto abort_1;
211             code =
212                 ubik_Call(KAM_SetPassword, adminConn, 0, aaname, aainst, 0,
213                           key);
214             break;
215         case 3:         /* set AuthServer.Admin password */
216         case 13:                /* and remember admin ticket */
217             code = ubik_Call(KAM_GetRandomKey, adminConn, 0, &key);
218             if (code)
219                 goto abort_1;
220             code =
221                 ubik_Call(KAM_SetPassword, adminConn, 0, aname, ainst, 0,
222                           key);
223             if (v == 3)
224                 break;
225         case 4:         /* remeber Admin ticket and TGS ticket */
226             if (nAdminTokens >= MAXADMINTOKENS)
227                 printf("Too many admin tokens\n");
228             else
229                 code =
230                     ka_Authenticate(name, inst, localCell, aconn,
231                                     KA_MAINTENANCE_SERVICE, userkey, now,
232                                     now + 3600, &adminTokens[nAdminTokens++],
233                                     0);
234             if (code)
235                 goto abort_1;
236             if (v != 4)
237                 break;
238             if (nTGSTokens >= MAXTGSTOKENS)
239                 printf("Too many tgs tokens\n");
240             else
241                 code =
242                     ka_Authenticate(name, inst, localCell, aconn,
243                                     KA_TICKET_GRANTING_SERVICE, userkey, now,
244                                     now + 3600, &tgsTokens[nTGSTokens++], 0);
245             break;
246         case 2:
247             code =
248                 ubik_Call(KAM_Debug, adminConn, 0, KAMAJORVERSION, 0, &info);
249             if (code)
250                 goto abort_1;
251             now = time(0);
252             printf
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)
261                     IOMGR_Sleep(1);
262                 else
263                     IOMGR_Poll();
264             }
265             code =
266                 ubik_Call(KAM_SetFields, adminConn, 0, name, inst, 0, 0,
267                           100 * 3600, 0, /* spares */ 0,
268                           0);
269             break;
270         case 0:
271             code =
272                 ubik_Call(KAM_GetEntry, adminConn, 0, aname, ainst,
273                           KAMAJORVERSION, &aentry);
274             break;
275         }
276         if (code) {
277           abort_1:
278             afs_com_err(whoami, code, "at %d seconds: calling server with v=%x",
279                     sleep, v);
280             exit(2);
281         }
282     }
283
284     printf("Trying %d Admin tokens\n", nAdminTokens);
285     for (i = 0; i < nAdminTokens; i++) {
286         int j;
287         struct ubik_client *conn;
288
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);
293
294         code =
295             ka_AuthServerConn(localCell, KA_MAINTENANCE_SERVICE,
296                               &adminTokens[i], &conn);
297         if (code) {
298           abort_ta:
299             afs_com_err(whoami, code, "Checking admin token #%d with kvno %d\n",
300                     i, (int)adminTokens[i].kvno);
301             exit(5);
302         }
303         code =
304             ubik_Call(KAM_GetEntry, conn, 0, aname, ainst, KAMAJORVERSION,
305                       &aentry);
306         if (code)
307             goto abort_ta;
308     }
309
310     printf("Trying %d TGS tokens\n", nTGSTokens);
311     for (i = 0; i < nTGSTokens; i++) {
312         int j;
313         struct ktc_token token;
314
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);
319
320         code =
321             ka_GetToken(name, inst, localCell, name, inst, tgsConn, now,
322                         now + 3600, &tgsTokens[i], "", &token);
323         if (code) {
324             afs_com_err(whoami, code, "Checking tgs token #%d with kvno %d\n", i,
325                     (int)tgsTokens[i].kvno);
326             exit(6);
327         }
328     }
329
330     code = ubik_Call(KAM_DeleteUser, adminConn, 0, aaname, aainst);
331     if (code) {
332         afs_com_err(whoami, code, "Deleting alternate admin user");
333         exit(3);
334     }
335     return;
336 }
337
338 int
339 main(argc, argv)
340      int argc;
341      char *argv[];
342 {
343     int i, j;
344     long serverList[MAXSERVERS];
345     int code;
346     char *args[3];
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;
355     Date now = time(0);
356     Date end;
357     char password[BUFSIZ];
358 #if (BUFSIZ<=1000)
359     password needs to be at least 1000 chars long;
360 #endif
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
366     };
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"
382     };
383     struct ktc_encryptionKey correct_key;
384     char hostname[64];
385
386     whoami = argv[0];
387     args[0] = "";
388     args[1] = "-servers";
389
390     /* get this host */
391     gethostname(hostname, sizeof(hostname));
392     args[2] = hostname;
393
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");
400         exit(1);
401     }
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");
407         exit(1);
408     }
409
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)];
414
415     code = ka_CellConfig(AFSCONF_CLIENTNAME);
416     if (code)
417         afs_com_err(whoami, code, "calling cell config");
418     localCell = ka_LocalCell();
419
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) {
425             printf
426                 ("String to key error converting '%s'; should be '%s' instead got '",
427                  password, answer[i]);
428             ka_PrintBytes(&key, sizeof(key));
429             printf("'\n");
430             exit(1);
431         }
432     }
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)];
438             j++;
439         }
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) {
443             printf
444                 ("String to key error converting '%s'; should be '%s' instead got '",
445                  password, answer[i]);
446             ka_PrintBytes(&key, sizeof(key));
447             printf("'\n");
448         }
449     }
450
451     strcpy(name, "guest");
452     strcpy(inst, "");
453
454     code = rx_Init(0);
455     if (code) {
456         afs_com_err(whoami, code, "rx_Init'ing");
457         exit(1);
458     }
459     if (code = ka_Init(0)) {
460         afs_com_err(whoami, code, "ka_Init'ing");
461         exit(1);
462     }
463     if (code = ubik_ParseClientList(3, args, serverList)) {
464         afs_com_err(whoami, code, "parsing Ubik server list");
465         exit(1);
466     }
467     ka_ExplicitCell(localCell, serverList);
468
469     {
470         struct rx_connection *conns[2];
471         struct rx_securityClass *sc;
472         int si;                 /* security class index */
473
474         sc = rxnull_NewClientSecurityObject();
475         si = RX_SCINDEX_NULL;
476         conns[0] =
477             rx_NewConnection(htonl(INADDR_LOOPBACK), htons(AFSCONF_KAUTHPORT),
478                              KA_MAINTENANCE_SERVICE, sc, si);
479         conns[1] = 0;
480         code = ubik_ClientInit(conns, &lpbkConn);
481         if (code) {
482           abort_4:
483             afs_com_err(whoami, code,
484                     "getting %s's password via loopback connection to GetPassword",
485                     name);
486             exit(1);
487         }
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);
492         } else if (code)
493             goto abort_4;
494     }
495
496     /* first just get TGS ticket */
497     code = ka_AuthServerConn(localCell, KA_AUTHENTICATION_SERVICE, 0, &aconn);
498     if (code) {
499       abort:
500         afs_com_err(whoami, code, "connecting to authentication service");
501         exit(1);
502     }
503     end = now + 100 * 3600 + 2;
504     code =
505         ka_Authenticate(name, inst, localCell, aconn,
506                         KA_TICKET_GRANTING_SERVICE, &key, now, end, &tgt, 0);
507     if (code)
508         goto abort;
509     if (tgt.endTime == end) {
510         fprintf(stderr,
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);
515         exit(1);
516     }
517
518     /* try to get ticket w/ time jitter */
519     code =
520         ka_Authenticate(name, inst, localCell, aconn, KA_MAINTENANCE_SERVICE,
521                         &key, now + KTC_TIME_UNCERTAINTY / 2, now + 3600,
522                         &token, 0);
523     if (code) {
524       abort_1:
525         afs_com_err(whoami, code, "using admin ticket with time jitter");
526         exit(1);
527     }
528
529     code =
530         ka_AuthServerConn(localCell, KA_MAINTENANCE_SERVICE, &token, &conn);
531     if (code)
532         goto abort_1;
533     code =
534         ubik_Call(KAM_GetEntry, conn, 0, name, inst, KAMAJORVERSION, &tentry);
535     if (code)
536         goto abort_1;
537     print_entry(&tentry, name, inst);
538
539     {
540         struct ktc_encryptionKey badkey;
541
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) {
546           abort_5:
547             afs_com_err(whoami, code, "Trying to set bad key");
548             exit(1);
549         }
550         memset(&badkey, 0, sizeof(badkey));
551         code = ubik_Call(KAM_SetPassword, conn, 0, name, inst, 0, badkey);
552         if (code != KABADKEY)
553             goto abort_5;
554         code = ubik_Call(KAM_SetPassword, conn, 0, name, inst, 9999, key);
555         if (code != KABADARGUMENT)
556             goto abort_5;
557     }
558
559     /* try using ticket with no expiration time */
560     {
561         struct ktc_encryptionKey akey;
562         struct kaentryinfo aentry;
563
564         ka_StringToKey("authserv", localCell, &akey);
565
566         code = ubik_Call(KAM_SetPassword, conn, 0, aname, ainst, 0, akey);
567         if (code) {
568           abort_6:
569             afs_com_err(whoami, code, "Checking SetPassword");
570             exit(2);
571         }
572         code =
573             ubik_Call(KAM_GetEntry, conn, 0, aname, ainst, KAMAJORVERSION,
574                       &aentry);
575         if (code)
576             goto abort_6;
577         atoken.kvno = aentry.key_version;
578         for (i = 0; i < sizeof(aentry.key); i++)
579             if (((char *)&aentry.key)[i]) {
580                 code = KABADKEY;
581                 goto abort_6;
582             }
583         code = ubik_Call(KAM_GetRandomKey, conn, 0, &atoken.sessionKey);
584         if (code)
585             goto abort_3;
586         printf("Got random sessionKey: ");
587         ka_PrintBytes(&atoken.sessionKey, sizeof(key));
588         printf("\n");
589
590         atoken.startTime = 0;
591         atoken.endTime = NEVERDATE;
592         code =
593             tkt_MakeTicket(atoken.ticket, &atoken.ticketLen, &akey, name,
594                            inst, "", atoken.startTime, atoken.endTime,
595                            &atoken.sessionKey, 0, aname, ainst);
596         if (code) {
597           abort_3:
598             afs_com_err(whoami, code, "faking up AuthServer ticket");
599             exit(1);
600         }
601         {
602             struct ktc_principal client;
603             struct ktc_encryptionKey sessionkey;
604             Date start, end;
605             long host;
606
607             code =
608                 tkt_DecodeTicket(atoken.ticket, atoken.ticketLen, &akey,
609                                  client.name, client.instance, client.cell,
610                                  &sessionkey, &host, &start, &end);
611             if (code)
612                 goto abort_3;
613             if (code = tkt_CheckTimes(start, end, time(0)) <= 0)
614                 goto abort_3;
615
616             if (!des_check_key_parity(&sessionkey)
617                 || des_is_weak_key(&sessionkey)) {
618                 code = KABADKEY;
619                 goto abort_3;
620             }
621         }
622     }
623
624     code =
625         ka_AuthServerConn(localCell, KA_MAINTENANCE_SERVICE, &atoken, &conn);
626     if (code)
627         goto abort_3;
628     {
629         struct kaentryinfo entry;
630
631         code =
632             ubik_Call(KAM_GetEntry, conn, 0, name, inst, KAMAJORVERSION,
633                       &entry);
634         if (code)
635             goto abort_3;
636         if (memcmp(&tentry, &entry, sizeof(entry)) != 0) {
637             printf("Entries obtained not the same!\n");
638             print_entry(&entry, name, inst);
639         }
640     }
641
642     /* try bashing a ticket to make sure it fails to work */
643     memset(atoken.ticket + 10, 0, 1);
644     code =
645         ka_AuthServerConn(localCell, KA_MAINTENANCE_SERVICE, &atoken, &conn);
646     if (code) {
647         afs_com_err(whoami, code, "contacting admin server with bashed ticket");
648         exit(0);                /* this is supposed to happen */
649     }
650     code =
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");
655         exit(1);
656     }
657
658     TestOldKeys(&key);
659
660     printf("All clear!\n");
661     if (argc == 2) {
662         code = setpag();
663         if (code)
664             afs_com_err(whoami, code, "calling SetPAG");
665         else
666             printf("Calling SetPAG and exec'ing %s\n", argv[1]);
667         execve(argv[1], argv + 1, 0);
668         perror("execve returned");
669     }
670     exit(0);
671 }