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