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