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>
14 #include <sys/types.h>
17 #include <afs/cellconfig.h>
29 char name
[MAXKTCNAMELEN
] = "guest";
30 char inst
[MAXKTCNAMELEN
] = "";
32 char aname
[] = "AuthServer";
33 char ainst
[] = "Admin";
36 print_entry(tentry
, name
, instance
)
37 struct kaentryinfo
*tentry
;
42 char bob
[KA_TIMESTR_LEN
];
44 if (tentry
->minor_version
!= KAMINORVERSION
)
45 printf("Minor version number mismatch: got %d, expected %d\n",
46 tentry
->minor_version
, KAMINORVERSION
);
47 ka_PrintUserID("User data for ", name
, instance
, "");
51 if (tentry
->flags
& KAFADMIN
) {
52 printf("%sADMIN", prefix
);
55 if (tentry
->flags
& KAFNOTGS
) {
56 printf("%sNOTGS", prefix
);
59 if (tentry
->flags
& KAFNOCPW
) {
60 printf("%sNOCPW", prefix
);
63 if (tentry
->flags
& KAFNOSEAL
) {
64 printf("%sNOSEAL", prefix
);
67 if (tentry
->user_expiration
<= now
) {
68 printf("%sexpired", prefix
);
71 if (strcmp(prefix
, NEWPREFIX
) == 0)
76 printf(" key (%d):", tentry
->key_version
);
77 ka_PrintBytes(&tentry
->key
, sizeof(tentry
->key
));
78 ka_timestr(tentry
->change_password_time
, bob
, KA_TIMESTR_LEN
);
79 printf(", last cpw: %s\n", bob
);
80 ka_timestr(tentry
->user_expiration
, bob
, KA_TIMESTR_LEN
);
81 printf(" entry expires on %s. Max ticket lifetime %.2f hours.\n", bob
,
82 tentry
->max_ticket_lifetime
/ 3600.0);
83 ka_timestr(tentry
->modification_time
, bob
, KA_TIMESTR_LEN
);
84 printf(" last mod on %s by ", bob
);
85 ka_PrintUserID("", tentry
->modification_user
.name
,
86 tentry
->modification_user
.instance
, "\n");
102 struct ktc_encryptionKey
*userkey
;
105 #define MAXADMINTOKENS 30
106 #define MAXTGSTOKENS 10
107 int nAdminTokens
, nTGSTokens
;
108 struct ktc_token adminTokens
[MAXADMINTOKENS
];
109 struct ktc_token tgsTokens
[MAXTGSTOKENS
];
111 /* depends on 10 updates in 10 seconds to get AutoCPW to trigger,
112 * also 90 seconds is the maximum password age,
113 * also 11 old keys per block. */
115 static int OKTestVector
[] = {
116 0, 1000, 3000, 1005, 1005, 1005, 1006, 1006, 1007, 1007, 1007, 1007,
118 1011, 3012, 3012, 1015, 3017, 3017, 3017,
119 1021, 2024, 4024, 13026, 1028, 1028, 1028, 1028, 1028, 1028, 1028,
121 1031, 1031, 13032, 13032, 13032, 13032, 13032, 13032, 2037, 4037,
122 13040, 13040, 13041, 13041, 13042, 13042, 2049, 4049,
123 13050, 13051, 13052, 54, 55, 56,
124 2061, 4061, 65, 65, 65, 65, 65, 65, 65, 65, 65,
125 2073, 4073, 13073, 13073, 13074, 13075, 77,
126 2085, 4085, 85, 85, 85, 85, 85, 85, 85,
128 2100, 1103 /* should change primary on aa */ , 4105,
131 int nOKTestVector
= sizeof(OKTestVector
) / sizeof(int);
134 struct ktc_token tgt
;
135 struct ktc_token atoken
;
136 struct ubik_client
*aconn
; /* connection to authentication service */
137 struct ubik_client
*tgsConn
; /* connection to TGS */
138 struct ubik_client
*adminConn
; /* connection to maintenance service */
139 struct ktc_token ttoken
;
140 struct kaentryinfo aentry
;
141 struct ka_debugInfo info
;
146 struct ktc_encryptionKey key
;
147 char *aaname
= "krbtgt";
148 char *aainst
= "FAKECELL.EDU";
150 printf("checking old keys\n");
154 ka_AuthServerConn(localCell
, KA_AUTHENTICATION_SERVICE
, 0, &aconn
))
156 ka_Authenticate(name
, inst
, localCell
, aconn
,
157 KA_TICKET_GRANTING_SERVICE
, userkey
, now
,
158 now
+ 3600, &tgt
, 0))
160 ka_Authenticate(name
, inst
, localCell
, aconn
,
161 KA_MAINTENANCE_SERVICE
, userkey
, now
, now
+ 3600,
164 ka_AuthServerConn(localCell
, KA_TICKET_GRANTING_SERVICE
, 0,
167 ka_AuthServerConn(localCell
, KA_MAINTENANCE_SERVICE
, &atoken
,
171 afs_com_err(whoami
, code
, "testing old keys");
175 code
= ubik_Call(KAM_GetRandomKey
, adminConn
, 0, &key
);
178 code
= ubik_Call(KAM_CreateUser
, adminConn
, 0, aaname
, aainst
, key
);
180 printf("Alternate Admin User already exists\n");
184 nAdminTokens
= nTGSTokens
= 0;
187 for (i
= 0; i
< nOKTestVector
; i
++) {
188 int v
= OKTestVector
[i
]; /* get test vector */
194 if ((now
= time(0)) < start
+ sleep
)
195 IOMGR_Sleep(start
+ sleep
- now
);
199 if (sleep
>= notify
) {
200 printf("Now at %d seconds\n", sleep
);
205 case 1: /* set krbtgt.FAKECELL.EDU password */
206 code
= ubik_Call(KAM_GetRandomKey
, adminConn
, 0, &key
);
210 ubik_Call(KAM_SetPassword
, adminConn
, 0, aaname
, aainst
, 0,
213 case 3: /* set AuthServer.Admin password */
214 case 13: /* and remember admin ticket */
215 code
= ubik_Call(KAM_GetRandomKey
, adminConn
, 0, &key
);
219 ubik_Call(KAM_SetPassword
, adminConn
, 0, aname
, ainst
, 0,
223 case 4: /* remeber Admin ticket and TGS ticket */
224 if (nAdminTokens
>= MAXADMINTOKENS
)
225 printf("Too many admin tokens\n");
228 ka_Authenticate(name
, inst
, localCell
, aconn
,
229 KA_MAINTENANCE_SERVICE
, userkey
, now
,
230 now
+ 3600, &adminTokens
[nAdminTokens
++],
236 if (nTGSTokens
>= MAXTGSTOKENS
)
237 printf("Too many tgs tokens\n");
240 ka_Authenticate(name
, inst
, localCell
, aconn
,
241 KA_TICKET_GRANTING_SERVICE
, userkey
, now
,
242 now
+ 3600, &tgsTokens
[nTGSTokens
++], 0);
246 ubik_Call(KAM_Debug
, adminConn
, 0, KAMAJORVERSION
, 0, &info
);
251 ("Now at %d seconds (really %d): %d updates and %d seconds remaining\n",
252 sleep
, (now
- start
), info
.updatesRemaining
,
253 info
.nextAutoCPW
- now
);
254 if (info
.updatesRemaining
> 1)
255 printf("Too many updates needed at time %d\n", sleep
);
256 while ((now
= time(0)) < info
.nextAutoCPW
) {
257 printf("...waiting for next auto CPW\n");
258 if (info
.nextAutoCPW
- now
> 1)
264 ubik_Call(KAM_SetFields
, adminConn
, 0, name
, inst
, 0, 0,
265 100 * 3600, 0, /* spares */ 0,
270 ubik_Call(KAM_GetEntry
, adminConn
, 0, aname
, ainst
,
271 KAMAJORVERSION
, &aentry
);
276 afs_com_err(whoami
, code
, "at %d seconds: calling server with v=%x",
282 printf("Trying %d Admin tokens\n", nAdminTokens
);
283 for (i
= 0; i
< nAdminTokens
; i
++) {
285 struct ubik_client
*conn
;
287 for (j
= i
+ 1; j
< nAdminTokens
; j
++)
288 if (adminTokens
[i
].kvno
== adminTokens
[j
].kvno
)
289 printf("Two admin tokens with kvno %d: %d and %d\n",
290 (int)adminTokens
[i
].kvno
, i
, j
);
293 ka_AuthServerConn(localCell
, KA_MAINTENANCE_SERVICE
,
294 &adminTokens
[i
], &conn
);
297 afs_com_err(whoami
, code
, "Checking admin token #%d with kvno %d\n",
298 i
, (int)adminTokens
[i
].kvno
);
302 ubik_Call(KAM_GetEntry
, conn
, 0, aname
, ainst
, KAMAJORVERSION
,
308 printf("Trying %d TGS tokens\n", nTGSTokens
);
309 for (i
= 0; i
< nTGSTokens
; i
++) {
311 struct ktc_token token
;
313 for (j
= i
+ 1; j
< nTGSTokens
; j
++)
314 if (tgsTokens
[i
].kvno
== tgsTokens
[j
].kvno
)
315 printf("Two tgs tokens with kvno %d: %d and %d\n",
316 (int)tgsTokens
[i
].kvno
, i
, j
);
319 ka_GetToken(name
, inst
, localCell
, name
, inst
, tgsConn
, now
,
320 now
+ 3600, &tgsTokens
[i
], "", &token
);
322 afs_com_err(whoami
, code
, "Checking tgs token #%d with kvno %d\n", i
,
323 (int)tgsTokens
[i
].kvno
);
328 code
= ubik_Call(KAM_DeleteUser
, adminConn
, 0, aaname
, aainst
);
330 afs_com_err(whoami
, code
, "Deleting alternate admin user");
342 long serverList
[MAXSERVERS
];
345 struct ktc_encryptionKey key
;
346 struct ktc_token tgt
;
347 struct ktc_token token
;
348 struct ktc_token atoken
;
349 struct ubik_client
*aconn
; /* connection to authentication service */
350 struct ubik_client
*conn
;
351 struct ubik_client
*lpbkConn
= 0;
352 struct kaentryinfo tentry
;
355 char password
[BUFSIZ
];
357 password needs to be at least
1000 chars
long;
359 static char source
[] =
360 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0987654321";
361 static int truncate
[] =
362 { 1000, 750, 562, 432, 316, 237, 178, 133, 100, 75, 56, 42, 32, 24,
363 18, 13, 10, 8, 6, 4, 3, 2, 1, 0
365 static char answer
[sizeof(truncate
) / sizeof(int)][32] =
366 { "\250y\3161\315\250\361\274", "\212\133\133\345\236\206\362\200",
367 "\230b\354\334\302F\352\040", "\001\221T\016\265T\376\100",
368 "X\002\224g\250\221\214\340", "\241p\304\032\135\0328\361",
369 "\010\352\037\236sp\046\212", "\3522\352\325\247\313\023W",
370 "\023\310\034\315\265\227L\203", "z\373RJ\233\304\046m",
371 "\310\244\032\375\3704\045\323", "n\224\3022\034\376\013\247",
372 "\217\343\302\364\177\277\052\214",
373 "\357\337\010\054sv\332\057", "\373\373\316u\247\302\362g",
374 "\214O\007m\320\221\301\174", "\002\057OQ\031p\370u",
375 "k\224s\235\362\247\230\206", "\364\233\334\211\235\217k\205",
376 "\352\203m\212s\337\211d",
377 "k\354\256\364\222\352\265\323", "\205\135d\351\326\334\260\313",
378 "\345\250\331\340\265hd\222",
379 "\346\265\352\136\316\205\217\313"
381 struct ktc_encryptionKey correct_key
;
386 args
[1] = "-servers";
389 gethostname(hostname
, sizeof(hostname
));
392 /* test string hacking */
393 if ((strcmp(lcstring(name
, "AbcDe", 5), "abcd") != 0)
394 || (strcmp(lcstring(name
, "AbcDe", 6), "abcde") != 0)
395 || (strcmp(ucstring(inst
, "AbcDe", 4), "ABC") != 0)
396 || (strcmp(ucstring(inst
, "AbcDe", sizeof(inst
)), "ABCDE") != 0)) {
397 printf("uc/lc string problem\n");
400 #define tryscc(A,B,a,b) (sign(strcasecmp (A,B)) != sign (strcmp (a,b)))
401 if (tryscc("Abc", "abc", "abc", "abc") || tryscc("aB", "ABC", "ab", "abc")
402 || tryscc("ABC", "ab", "abc", "ab")
403 || tryscc("Abcd", "aBg", "abcd", "abg")) {
404 printf("strcasecmp problem\n");
408 strcpy(password
, "");
409 for (i
= 0; i
< 100; i
++)
410 for (j
= 0; j
< 10; j
++)
411 password
[i
* 10 + j
] = source
[i
% (sizeof(source
) - 1)];
413 code
= ka_CellConfig(AFSCONF_CLIENTNAME
);
415 afs_com_err(whoami
, code
, "calling cell config");
416 localCell
= ka_LocalCell();
418 for (i
= 0; i
< (sizeof(truncate
) / sizeof(int)); i
++) {
419 password
[truncate
[i
]] = 0;
420 ka_StringToKey(password
, "andy.edu", &key
);
421 ka_ReadBytes(answer
[i
], &correct_key
, sizeof(key
));
422 if (memcmp(&key
, &correct_key
, sizeof(key
)) != 0) {
424 ("String to key error converting '%s'; should be '%s' instead got '",
425 password
, answer
[i
]);
426 ka_PrintBytes(&key
, sizeof(key
));
431 memset(password
, 0, sizeof(password
));
432 j
= 0; /* current password length */
433 for (i
= (sizeof(truncate
) / sizeof(int)) - 1; i
>= 0; i
--) {
434 while (j
< truncate
[i
]) {
435 password
[j
] = source
[j
/ 10 % (sizeof(source
) - 1)];
438 ka_StringToKey(password
, "andy.edu", &key
);
439 ka_ReadBytes(answer
[i
], &correct_key
, sizeof(key
));
440 if (memcmp(&key
, &correct_key
, sizeof(key
)) != 0) {
442 ("String to key error converting '%s'; should be '%s' instead got '",
443 password
, answer
[i
]);
444 ka_PrintBytes(&key
, sizeof(key
));
449 strcpy(name
, "guest");
454 afs_com_err(whoami
, code
, "rx_Init'ing");
457 if (code
= ka_Init(0)) {
458 afs_com_err(whoami
, code
, "ka_Init'ing");
461 if (code
= ubik_ParseClientList(3, args
, serverList
)) {
462 afs_com_err(whoami
, code
, "parsing Ubik server list");
465 ka_ExplicitCell(localCell
, serverList
);
468 struct rx_connection
*conns
[2];
469 struct rx_securityClass
*sc
;
470 int si
; /* security class index */
472 sc
= rxnull_NewClientSecurityObject();
475 rx_NewConnection(htonl(INADDR_LOOPBACK
), htons(AFSCONF_KAUTHPORT
),
476 KA_MAINTENANCE_SERVICE
, sc
, si
);
478 code
= ubik_ClientInit(conns
, &lpbkConn
);
481 afs_com_err(whoami
, code
,
482 "getting %s's password via loopback connection to GetPassword",
486 code
= ubik_Call(KAM_GetPassword
, lpbkConn
, 0, name
, &key
);
487 if (code
== KANOAUTH
) {
488 printf("GetPassword disabled\n");
489 ka_StringToKey(name
, localCell
, &key
);
494 /* first just get TGS ticket */
495 code
= ka_AuthServerConn(localCell
, KA_AUTHENTICATION_SERVICE
, 0, &aconn
);
498 afs_com_err(whoami
, code
, "connecting to authentication service");
501 end
= now
+ 100 * 3600 + 2;
503 ka_Authenticate(name
, inst
, localCell
, aconn
,
504 KA_TICKET_GRANTING_SERVICE
, &key
, now
, end
, &tgt
, 0);
507 if (tgt
.endTime
== end
) {
509 "*** AuthTicket expires too late: must be old style sever ***\n");
510 } else if (tgt
.endTime
!= now
+ 100 * 3600) {
511 fprintf(stderr
, "Bogus expiration because lifetime (%d) wrong\n",
512 tgt
.endTime
- tgt
.startTime
);
516 /* try to get ticket w/ time jitter */
518 ka_Authenticate(name
, inst
, localCell
, aconn
, KA_MAINTENANCE_SERVICE
,
519 &key
, now
+ KTC_TIME_UNCERTAINTY
/ 2, now
+ 3600,
523 afs_com_err(whoami
, code
, "using admin ticket with time jitter");
528 ka_AuthServerConn(localCell
, KA_MAINTENANCE_SERVICE
, &token
, &conn
);
532 ubik_Call(KAM_GetEntry
, conn
, 0, name
, inst
, KAMAJORVERSION
, &tentry
);
535 print_entry(&tentry
, name
, inst
);
538 struct ktc_encryptionKey badkey
;
540 memcpy(&badkey
, &key
, sizeof(badkey
));
541 *(int *)&badkey
^= 1; /* toggle some bit */
542 code
= ubik_Call(KAM_SetPassword
, conn
, 0, name
, inst
, 0, badkey
);
543 if (code
!= KABADKEY
) {
545 afs_com_err(whoami
, code
, "Trying to set bad key");
548 memset(&badkey
, 0, sizeof(badkey
));
549 code
= ubik_Call(KAM_SetPassword
, conn
, 0, name
, inst
, 0, badkey
);
550 if (code
!= KABADKEY
)
552 code
= ubik_Call(KAM_SetPassword
, conn
, 0, name
, inst
, 9999, key
);
553 if (code
!= KABADARGUMENT
)
557 /* try using ticket with no expiration time */
559 struct ktc_encryptionKey akey
;
560 struct kaentryinfo aentry
;
562 ka_StringToKey("authserv", localCell
, &akey
);
564 code
= ubik_Call(KAM_SetPassword
, conn
, 0, aname
, ainst
, 0, akey
);
567 afs_com_err(whoami
, code
, "Checking SetPassword");
571 ubik_Call(KAM_GetEntry
, conn
, 0, aname
, ainst
, KAMAJORVERSION
,
575 atoken
.kvno
= aentry
.key_version
;
576 for (i
= 0; i
< sizeof(aentry
.key
); i
++)
577 if (((char *)&aentry
.key
)[i
]) {
581 code
= ubik_Call(KAM_GetRandomKey
, conn
, 0, &atoken
.sessionKey
);
584 printf("Got random sessionKey: ");
585 ka_PrintBytes(&atoken
.sessionKey
, sizeof(key
));
588 atoken
.startTime
= 0;
589 atoken
.endTime
= NEVERDATE
;
591 tkt_MakeTicket(atoken
.ticket
, &atoken
.ticketLen
, &akey
, name
,
592 inst
, "", atoken
.startTime
, atoken
.endTime
,
593 &atoken
.sessionKey
, 0, aname
, ainst
);
596 afs_com_err(whoami
, code
, "faking up AuthServer ticket");
600 struct ktc_principal client
;
601 struct ktc_encryptionKey sessionkey
;
606 tkt_DecodeTicket(atoken
.ticket
, atoken
.ticketLen
, &akey
,
607 client
.name
, client
.instance
, client
.cell
,
608 &sessionkey
, &host
, &start
, &end
);
611 if (code
= tkt_CheckTimes(start
, end
, time(0)) <= 0)
614 if (!des_check_key_parity(&sessionkey
)
615 || des_is_weak_key(&sessionkey
)) {
623 ka_AuthServerConn(localCell
, KA_MAINTENANCE_SERVICE
, &atoken
, &conn
);
627 struct kaentryinfo entry
;
630 ubik_Call(KAM_GetEntry
, conn
, 0, name
, inst
, KAMAJORVERSION
,
634 if (memcmp(&tentry
, &entry
, sizeof(entry
)) != 0) {
635 printf("Entries obtained not the same!\n");
636 print_entry(&entry
, name
, inst
);
640 /* try bashing a ticket to make sure it fails to work */
641 memset(atoken
.ticket
+ 10, 0, 1);
643 ka_AuthServerConn(localCell
, KA_MAINTENANCE_SERVICE
, &atoken
, &conn
);
645 afs_com_err(whoami
, code
, "contacting admin server with bashed ticket");
646 exit(0); /* this is supposed to happen */
649 ubik_Call(KAM_GetEntry
, conn
, 0, name
, inst
, KAMAJORVERSION
, &tentry
);
650 if (code
!= RXKADBADTICKET
) {
651 afs_com_err(whoami
, code
,
652 "GetEntry failed to fail even with damaged ticket!!!!\n");
658 printf("All clear!\n");
662 afs_com_err(whoami
, code
, "calling SetPAG");
664 printf("Calling SetPAG and exec'ing %s\n", argv
[1]);
665 execve(argv
[1], argv
+ 1, 0);
666 perror("execve returned");