afs: removing trailing semicolons
[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, "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 }