Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / kauth / test / test_getticket.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
14 #include <afs/stds.h>
15 #include <sys/types.h>
16 #include <sys/time.h>
17 #include <sys/resource.h>
18 #include <stdio.h>
19 #include <netinet/in.h>
20 #include <netdb.h>
21 #include <rx/rx.h>
22 #include <ubik.h>
23 #include <pwd.h>
24 #include <afs/auth.h>
25 #include <afs/cellconfig.h>
26 #include <afs/cmd.h>
27 #include <afs/com_err.h>
28 #include <afs/debug.h>
29
30 #include "kauth.h"
31 #include "kautils.h"
32
33
34 static char *whoami = "test_rxkad_free";
35 static char realm[MAXKTCREALMLEN];
36 static char *cell;
37 static char *admin_user;
38
39 static struct ktc_principal afs;
40 static struct ktc_token oldAFSToken;
41 static struct ktc_principal oldClient;
42
43 static void
44 Crash(line)
45 IN int line;
46 {
47 long code;
48 if (oldAFSToken.endTime > 0) {
49 code = ktc_SetToken(&afs, &oldAFSToken, &oldClient, 0);
50 printf("%s original AFS token\n",
51 (code == 0 ? "Restoring" : "Failed to restore"));
52 }
53 if (line)
54 printf("Crashing at line %d\n", line);
55 exit(line);
56 }
57
58 #define CRASH() Crash (__LINE__)
59 #define EXIT() Crash (0)
60
61 static void
62 PrintRxkadStats()
63 {
64 printf("New Objects client %d, server %d. Destroyed objects %d.\n",
65 rxkad_stats.clientObjects, rxkad_stats.serverObjects,
66 rxkad_stats.destroyObject);
67 printf("client conns: %d %d %d, destroyed client %d.\n",
68 rxkad_stats.connections[0], rxkad_stats.connections[1],
69 rxkad_stats.connections[2], rxkad_stats.destroyClient);
70 printf("server challenges %d, responses %d %d %d\n",
71 rxkad_stats.challengesSent, rxkad_stats.responses[0],
72 rxkad_stats.responses[1], rxkad_stats.responses[2]);
73 printf("server conns %d %d %d unused %d, unauth %d\n",
74 rxkad_stats.destroyConn[0], rxkad_stats.destroyConn[1],
75 rxkad_stats.destroyConn[2], rxkad_stats.destroyUnused,
76 rxkad_stats.destroyUnauth);
77 }
78
79 static void
80 SetFields(conn, name, flags, expiration, lifetime)
81 IN struct ubik_client *conn;
82 IN char *name;
83 IN long flags;
84 IN Date expiration;
85 IN long lifetime;
86 {
87 long code;
88 char *instance;
89 char buf[32];
90 char *which;
91 char *what;
92
93 if (strcmp(name, KA_TGS_NAME) == 0)
94 instance = realm;
95 else
96 instance = "";
97 if (flags) {
98 which = "flags";
99 if (flags & KAFNOTGS)
100 if (flags & KAFNOSEAL)
101 what = "NOTGS+NOSEAL";
102 else
103 what = "NOTGS";
104 else if (flags & KAFNOSEAL)
105 what = "NOSEAL";
106 else
107 what = "normal";
108 flags |= KAFNORMAL;
109 if (strcmp(name, admin_user) == 0)
110 flags |= KAFADMIN;
111 } else if (expiration) {
112 which = "expiration";
113 sprintf(buf, "now + %.1f hours",
114 (double)(expiration - time(0)) / 3600.0);
115 what = buf;
116 } else if (lifetime) {
117 which = "lifetime";
118 sprintf(buf, "%.1f hours", (double)lifetime / 3600.0);
119 what = buf;
120 } else
121 CRASH();
122
123 printf("Setting %s of ", which);
124 ka_PrintUserID("", name, instance, "");
125 printf(" to %s\n", what);
126 code =
127 ubik_Call(KAM_SetFields, conn, 0, name, instance, flags, expiration,
128 lifetime, -1,
129 /* spares */ 0, 0);
130 if (code) {
131 afs_com_err(whoami, code, "calling set fields on %s", name);
132 CRASH();
133 }
134 }
135
136 #define SetLife(c,n,l) SetFields (c,n,0,0,l)
137 #define SetExp(c,n,e) SetFields (c,n,0,e,0)
138 #define SetFlags(c,n,f) SetFields (c,n,f,0,0)
139
140 #define EXACT 0x5b
141 #define KERBEROS 0x2a
142
143 static void
144 CheckLife(tokenEnd, start, expectedLife, match)
145 IN Date tokenEnd;
146 IN Date start;
147 {
148 Date expectedEnd;
149 char bob[KA_TIMESTR_LEN];
150 printf("Expecting %s match with lifetime of %.1f hours\n",
151 (match == EXACT ? "exact" : "kerberos"),
152 (double)expectedLife / 3600.0);
153 expectedEnd = expectedLife + start;
154 if (match == EXACT) {
155 if (abs(expectedEnd - tokenEnd) <= 2)
156 return;
157 }
158 if (match == KERBEROS) {
159 unsigned char kerberosV4Life;
160 Date kend;
161 kerberosV4Life = time_to_life(start, expectedEnd);
162 kend = life_to_time(start, kerberosV4Life);
163 if (abs(kend - tokenEnd) <= 1)
164 return;
165 kerberosV4Life = time_to_life(start, expectedEnd - 2);
166 kend = life_to_time(start, kerberosV4Life);
167 if (abs(kend - tokenEnd) <= 1)
168 return;
169 }
170 ka_timestr(tokenEnd, bob, KA_TIMESTR_LEN);
171 printf("End doesn't match: token was %s", bob);
172 ka_timestr(expectedEnd, bob, KA_TIMESTR_LEN);
173 printf(", but expected %s\n", bob);
174 CRASH();
175 }
176
177 static void
178 GetTokenLife(name, passwd, expectedLife, match)
179 IN char *name;
180 IN char *passwd;
181 IN long expectedLife;
182 IN long match; /* or expected error code */
183 {
184 char *reason;
185 long code;
186 struct ktc_token t;
187
188 code = ka_UserAuthenticateLife(0, name, "", cell, passwd, 0, &reason);
189 if (!((match == EXACT) || (match == KERBEROS))) { /* must be error code */
190 if (code == match) {
191 printf("Received expected error code\n");
192 return;
193 }
194 }
195 if (code) {
196 fprintf(stderr, "Unable to authenticate to AFS because %s.\n",
197 reason);
198 CRASH();
199 }
200 code = ktc_GetToken(&afs, &t, sizeof(t), 0);
201 if (code) {
202 afs_com_err(whoami, code, "getting afs token from ktc");
203 CRASH();
204 }
205 CheckLife(t.endTime, t.startTime, expectedLife, match);
206 }
207
208 static int
209 Main(struct cmd_syndesc *as, void *arock)
210 {
211 int code;
212 char name[MAXKTCNAMELEN];
213 char instance[MAXKTCNAMELEN];
214 char newCell[MAXKTCREALMLEN];
215
216 long serverList[MAXSERVERS];
217 extern struct passwd *getpwuid();
218
219 struct passwd *pw;
220 struct ktc_encryptionKey key;
221
222 char passwd[BUFSIZ];
223
224 int cellSpecified;
225 int i;
226
227 unsigned long startTime;
228 unsigned long deadTime;
229 unsigned long now;
230 unsigned long end;
231
232 int patient = (as->parms[0].items != 0);
233
234 whoami = as->a0name;
235 newCell[0] = 0;
236
237 if (as->parms[12].items) { /* if username specified */
238 code =
239 ka_ParseLoginName(as->parms[12].items->data, name, instance,
240 newCell);
241 if (code) {
242 afs_com_err(whoami, code, "parsing user's name '%s'",
243 as->parms[12].items->data);
244 return code;
245 }
246 if (strlen(newCell) > 0)
247 cellSpecified = 1;
248 } else {
249 /* No explicit name provided: use Unix uid. */
250 pw = getpwuid(getuid());
251 if (pw == 0) {
252 printf("Can't figure out your name from your user id.\n");
253 return KABADCMD;
254 }
255 strncpy(name, pw->pw_name, sizeof(name));
256 strcpy(instance, "");
257 strcpy(newCell, "");
258 }
259 admin_user = name; /* this guy should keep admin bit */
260
261 if (strcmp(as->parms[14].name, "-cell") == 0) {
262 if (as->parms[14].items) { /* if cell specified */
263 if (cellSpecified)
264 printf("Duplicate cell specification not allowed\n");
265 else
266 strncpy(newCell, as->parms[14].items->data, sizeof(newCell));
267 }
268 }
269
270 code = ka_ExpandCell(newCell, newCell, 0 /*local */ );
271 if (code) {
272 afs_com_err(whoami, code, "Can't expand cell name");
273 return code;
274 }
275 cell = newCell;
276 code = ka_CellToRealm(cell, realm, 0);
277 if (code) {
278 afs_com_err(whoami, code, "Can't get realm from cell name");
279 return code;
280 }
281
282 if (as->parms[13].items) { /* if password specified */
283 strncpy(passwd, as->parms[13].items->data, sizeof(passwd));
284 memset(as->parms[13].items->data, 0,
285 strlen(as->parms[13].items->data));
286 } else {
287 char msg[sizeof(name) + 15];
288 if (as->parms[12].items)
289 strcpy(msg, "Admin Password: ");
290 else
291 sprintf(msg, "Password for %s: ", name);
292 code = read_pw_string(passwd, sizeof(passwd), msg, 0);
293 if (code)
294 code = KAREADPW;
295 else if (strlen(passwd) == 0)
296 code = KANULLPASSWORD;
297 if (code) {
298 afs_com_err(whoami, code, "reading password");
299 return code;
300 }
301 }
302 if (as->parms[15].items) {
303 struct cmd_item *ip;
304 char *ap[MAXSERVERS + 2];
305
306 for (ip = as->parms[15].items, i = 2; ip; ip = ip->next, i++)
307 ap[i] = ip->data;
308 ap[0] = "";
309 ap[1] = "-servers";
310 code = ubik_ParseClientList(i, ap, serverList);
311 if (code) {
312 afs_com_err(whoami, code, "could not parse server list");
313 return code;
314 }
315 ka_ExplicitCell(cell, serverList);
316 }
317
318 ka_StringToKey(passwd, cell, &key);
319
320 strcpy(afs.name, AUTH_SUPERUSER);
321 strcpy(afs.instance, "");
322 strcpy(afs.cell, cell);
323 code = ktc_GetToken(&afs, &oldAFSToken, sizeof(oldAFSToken), &oldClient);
324 if (code) {
325 afs_com_err(whoami, code, "saving existing afs token");
326 return code;
327 }
328
329 startTime = time(0);
330 {
331 struct ktc_token token;
332 struct ktc_token *pToken;
333 struct ubik_client *ubikConn;
334 struct kaentryinfo tentry;
335 struct ktc_principal tgs_server;
336 struct ktc_token tgs_token;
337 struct ktc_principal tgs_client;
338 Date start;
339
340 code =
341 ka_GetAdminToken(name, instance, cell, &key, 3600, &token,
342 1 /*new */ );
343 if (code) {
344 afs_com_err(whoami, code, "getting admin token");
345 return code;
346 }
347 pToken = &token;
348 if (token.ticketLen == 0) {
349 fprintf("Can't get admin token\n");
350 return -1;
351 }
352
353 code =
354 ka_AuthServerConn(cell, KA_MAINTENANCE_SERVICE, pToken,
355 &ubikConn);
356 if (code) {
357 afs_com_err(whoami, code, "Getting AuthServer ubik conn");
358 return code;
359 }
360
361 SetFlags(ubikConn, AUTH_SUPERUSER, KAFNORMAL);
362 SetFlags(ubikConn, name, KAFNORMAL);
363 SetLife(ubikConn, KA_TGS_NAME, MAXKTCTICKETLIFETIME);
364 SetLife(ubikConn, AUTH_SUPERUSER, MAXKTCTICKETLIFETIME);
365 SetLife(ubikConn, name, 3600);
366 deadTime = startTime + 365 * 24 * 3600;
367 SetExp(ubikConn, KA_TGS_NAME, deadTime);
368 SetExp(ubikConn, AUTH_SUPERUSER, deadTime);
369 SetExp(ubikConn, name, deadTime);
370
371 GetTokenLife(name, passwd, 3600, EXACT);
372
373 /* get TGS ticket for proper realm */
374 strcpy(tgs_server.name, KA_TGS_NAME);
375 strcpy(tgs_server.instance, realm);
376 strcpy(tgs_server.cell, cell);
377 /* save this for future use */
378 code =
379 ktc_GetToken(&tgs_server, &tgs_token, sizeof(tgs_token),
380 &tgs_client);
381 if (code) {
382 afs_com_err(whoami, code, "saving tgs token");
383 return code;
384 }
385
386 SetLife(ubikConn, name, MAXKTCTICKETLIFETIME);
387 now = time(0);
388 GetTokenLife(name, passwd, MAXKTCTICKETLIFETIME, EXACT);
389
390 SetLife(ubikConn, AUTH_SUPERUSER, 4000);
391 now = time(0);
392 GetTokenLife(name, passwd, 4000, KERBEROS);
393 SetLife(ubikConn, AUTH_SUPERUSER, MAXKTCTICKETLIFETIME);
394
395 SetLife(ubikConn, KA_TGS_NAME, 5000);
396 now = time(0);
397 GetTokenLife(name, passwd, 5000, KERBEROS);
398 SetLife(ubikConn, KA_TGS_NAME, MAXKTCTICKETLIFETIME);
399
400 now = time(0);
401 SetExp(ubikConn, KA_TGS_NAME, now + 6000);
402 GetTokenLife(name, passwd, 6000, KERBEROS);
403 SetExp(ubikConn, KA_TGS_NAME, deadTime);
404
405 now = time(0);
406 SetExp(ubikConn, AUTH_SUPERUSER, now + 7000);
407 GetTokenLife(name, passwd, 7000, KERBEROS);
408 SetExp(ubikConn, AUTH_SUPERUSER, deadTime);
409
410 now = time(0);
411 SetExp(ubikConn, name, now + 8000);
412 GetTokenLife(name, passwd, 8000, KERBEROS);
413
414 /* since the rest should be errors, restore good AFS ticket */
415 code = ktc_SetToken(&afs, &oldAFSToken, &oldClient, 0);
416 if (code) {
417 afs_com_err(whoami, code, "restoring old afs token");
418 return code;
419 }
420
421 SetExp(ubikConn, name, now - 1000);
422 GetTokenLife(name, passwd, 8000, KABADUSER);
423 SetExp(ubikConn, name, deadTime);
424
425 SetExp(ubikConn, AUTH_SUPERUSER, now - 1000);
426 GetTokenLife(name, passwd, 8000, KABADSERVER);
427 SetExp(ubikConn, AUTH_SUPERUSER, deadTime);
428
429 SetFlags(ubikConn, AUTH_SUPERUSER, KAFNORMAL + KAFNOSEAL);
430 GetTokenLife(name, passwd, 8000, KABADSERVER);
431 SetFlags(ubikConn, AUTH_SUPERUSER, KAFNORMAL);
432
433 SetFlags(ubikConn, name, KAFNORMAL + KAFNOTGS);
434 GetTokenLife(name, passwd, 8000, KABADUSER);
435 /* restore old tgs, since GetTicket are prohibited too. */
436 code = ktc_SetToken(&tgs_server, &tgs_token, &tgs_client, 0);
437 if (code) {
438 afs_com_err(whoami, code, "restoring old tgs token");
439 return code;
440 }
441 printf("Restoring TGT obtained before NOTGS set\n");
442 code = ka_GetServerToken(AUTH_SUPERUSER, "", cell, 100, 0, 1);
443 if (code != KABADUSER) {
444 afs_com_err(whoami, code,
445 "expected BADUSER error, getting AFS token w/ old tgs token but with NOTGS set");
446 CRASH();
447 } else
448 printf("Received expected error code\n");
449 SetFlags(ubikConn, name, KAFNORMAL);
450
451 if (patient) { /* this requires waiting too long */
452 struct ktc_token afsToken;
453 code = ktc_SetToken(&afs, &oldAFSToken, &oldClient, 0);
454 if (code) {
455 afs_com_err(whoami, code, "restoring old afs token");
456 return code;
457 }
458 fprintf(stdout, "Waiting for TGS ticket to age (about 5 min)...");
459 fflush(stdout);
460 while (((now = time(0)) - tgs_token.startTime) < 5 * 60) {
461 if (((now - tgs_token.startTime) % 60) == 0) {
462 fprintf(stdout, "%d seconds to go...",
463 (now - tgs_token.startTime));
464 fflush(stdout);
465 }
466 IOMGR_Sleep(1); /* with afs token restored... */
467 }
468 /* restore old tgs */
469 code = ktc_SetToken(&tgs_server, &tgs_token, &tgs_client, 0);
470 if (code) {
471 afs_com_err(whoami, code, "restoring old tgs token");
472 return code;
473 }
474 code =
475 ka_GetServerToken(AUTH_SUPERUSER, "", cell,
476 MAXKTCTICKETLIFETIME, &afsToken, 1);
477 if (code) {
478 afs_com_err(whoami, code, "getting AFS token w/ old tgs token");
479 CRASH();
480 }
481 CheckLife(afsToken.endTime, afsToken.startTime, 3600 - (5 * 60),
482 EXACT);
483 }
484 ubik_ClientDestroy(ubikConn);
485 }
486
487 printf("calling finalize\n");
488 rx_Finalize();
489 PrintRxkadStats();
490 printf("All Okay\n");
491 return 0;
492 }
493
494 int
495 main(argc, argv)
496 IN int argc;
497 IN char *argv[];
498 {
499 struct cmd_syndesc *ts;
500 long code;
501
502 initialize_U_error_table();
503 initialize_CMD_error_table();
504 initialize_RXK_error_table();
505 initialize_KTC_error_table();
506 initialize_ACFG_error_table();
507 initialize_KA_error_table();
508
509 ts = cmd_CreateSyntax(NULL, Main, NULL, 0, "Main program");
510 /* 0 */ cmd_AddParm(ts, "-patient", CMD_FLAG, CMD_OPTIONAL,
511 "wait for TGS ticket to age");
512 cmd_Seek(ts, 12);
513 /* 12 */ cmd_AddParm(ts, "-admin_username", CMD_SINGLE, CMD_OPTIONAL,
514 "admin principal to use for authentication");
515 /* 13 */ cmd_AddParm(ts, "-password_for_admin", CMD_SINGLE, CMD_OPTIONAL,
516 "admin password");
517 /* 14 */ cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cell name");
518 /* 15 */ cmd_AddParm(ts, "-servers", CMD_LIST, CMD_OPTIONAL,
519 "explicit list of authentication servers");
520 code = cmd_Dispatch(argc, argv);
521 if (code)
522 CRASH();
523 EXIT();
524 }