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 /* These routines provide administrative tools for managing the AuthServer.
11 There is an interactive routine that can be used to examine the database and
12 make small changes as well as subroutines to permit specialized programs to
13 update the database, change the server passwords, etc. */
15 #include <afs/param.h>
17 #include <afs/debug.h>
21 /* These two needed for rxgen output to work */
22 #include <sys/types.h>
33 #include <afs/cellconfig.h>
35 #include <afs/com_err.h>
36 #include <afs/afsutil.h>
43 #define CMD_PARSER_AMBIG_FIX 1 /* allow ambiguous aliases */
45 extern char *ktime_GetDateUsage();
47 #define KA_SIXHOURS (6*3600)
49 static struct ubik_client *conn;
50 static char cell[MAXKTCREALMLEN] = "";
51 static char whoami[32];
52 static char passwd[BUFSIZ];
53 static char myName[510]; /* almost like whoami save with path and without : */
57 static char **zero_argv;
58 afs_uint32 ka_islocked();
60 afs_int32 DefaultCell (void)
64 if (cell[0] != 0) return 0;
65 code = ka_ExpandCell (0, cell, 0/*local*/);
67 com_err (whoami, code, "Can't expand cell name");
72 /* These are the command operation procedures. */
75 struct cmd_syndesc *as,
82 int code, all=0, showa = 0;
83 int showkey = (as->parms[2].items != NULL);
85 if (as->parms[0].items)
87 if (as->parms[1].items) {
91 for (index = 0; 1; index = next_index) {
92 code = ubik_Call (KAM_ListEntry, conn, 0,
93 index, &next_index, &count, &name);
95 com_err (whoami, code, "calling KAM_ListEntry");
98 if (!next_index) break;
100 printf ("next_index (%d) is negative: ", next_index);
101 if (strlen(name.name) == 0) printf ("name is zero length: ");
103 DumpUser(name.name, (char *)0, showa, showkey, name.instance);
105 ka_PrintUserID ("", name.name, name.instance, "\n");
112 struct cmd_syndesc *as,
115 int showkey = (as->parms[1].items != NULL);
116 return DumpUser(as->parms[0].items->data, arock, 0, showkey, (char *)0);
127 char name[MAXKTCNAMELEN];
128 char instance[MAXKTCNAMELEN];
131 char bob[KA_TIMESTR_LEN];
133 struct kaentryinfo tentry;
135 code = ka_ParseLoginName (user, name, instance, 0);
137 com_err (whoami, code, "parsing user's name '%s'", user);
143 code = ubik_Call (KAM_GetEntry, conn, 0, name, inst,
144 KAMAJORVERSION, &tentry);
146 com_err (whoami, code,
147 "getting information for %s.%s", name, inst);
150 if (tentry.minor_version != KAMINORVERSION)
151 printf ("Minor version number mismatch: got %d, expected %d\n",
152 tentry.minor_version, KAMINORVERSION);
153 if (showadmin && !(tentry.flags & KAFADMIN))
155 ka_PrintUserID ("\nUser data for ", name, inst, "");
156 { char *prefix = " (";
157 #define NEWPREFIX "+"
158 if (tentry.flags & KAFADMIN) { printf ("%sADMIN", prefix); prefix = NEWPREFIX; }
159 if (tentry.flags & KAFNOTGS) { printf ("%sNOTGS", prefix); prefix = NEWPREFIX; }
160 if (tentry.flags & KAFNOCPW) { printf ("%sNOCPW", prefix); prefix = NEWPREFIX; }
161 if (tentry.flags & KAFNOSEAL) { printf ("%sNOSEAL", prefix); prefix = NEWPREFIX; }
162 if (tentry.flags & KAFNEWASSOC) { printf ("%sNEWASSOC", prefix); prefix = NEWPREFIX; }
163 if (tentry.flags & KAFASSOCROOT) { printf ("%sASSOCROOT", prefix); prefix = NEWPREFIX; }
164 if (tentry.flags & KAFASSOC) { printf ("%sASSOC", prefix); prefix = NEWPREFIX; }
165 if (tentry.user_expiration <= now) { printf ("%sexpired", prefix); prefix = NEWPREFIX; }
166 if (strcmp (prefix, NEWPREFIX) == 0) printf (")\n");
169 if ((!ka_KeyIsZero((char *) &tentry.key, sizeof(tentry.key))) &&
171 printf (" key (%d):", tentry.key_version);
172 ka_PrintBytes ((char *)&tentry.key, sizeof(tentry.key));
175 if (tentry.keyCheckSum == 0)
176 printf (" key version is %d", tentry.key_version);
178 printf (" key (%d) cksum is %u",
179 tentry.key_version, tentry.keyCheckSum);
181 ka_timestr(tentry.change_password_time,bob,KA_TIMESTR_LEN);
182 printf (", last cpw: %s\n", bob);
183 if (!tentry.misc_auth_bytes) {
184 printf (" password will never expire.\n");
185 printf (" An unlimited number of unsuccessful authentications is permitted.\n");
188 unsigned char misc_stuff[4];
191 temp = tentry.misc_auth_bytes;
193 temp = ntohl(tentry.misc_auth_bytes);
195 unpack_long(temp, misc_stuff);
197 if (!misc_stuff[0]) {
198 printf (" password will never expire.\n");
201 ka_timestr((tentry.change_password_time + misc_stuff[0]*24*60*60), bob, KA_TIMESTR_LEN);
202 printf (" password will expire: %s\n", bob);
206 printf (" An unlimited number of unsuccessful authentications is permitted.\n");
208 printf (" %d consecutive unsuccessful authentications are permitted.\n", misc_stuff[2]);
211 printf (" The lock time for this user is not limited.\n");
213 printf (" The lock time for this user is %4.1f minutes.\n",
214 (float) ((unsigned int) misc_stuff[3] << 9) / 60.0);
216 if (!(misc_stuff[1] & KA_ISLOCKED) || !ka_islocked(name, instance, &temp))
217 printf (" User is not locked.\n");
218 else if (temp == (afs_uint32) (-1L))
219 printf (" User is locked forever.\n");
221 ka_timestr(temp,bob,KA_TIMESTR_LEN);
222 printf (" User is locked until %s\n",bob);
227 { char exp[KA_TIMESTR_LEN];
228 ka_timestr (tentry.user_expiration, exp, KA_TIMESTR_LEN);
229 if (tentry.user_expiration < now)
230 printf (" DISABLED entry at %s.", exp);
231 else if (tentry.user_expiration == NEVERDATE)
232 printf (" entry never expires.");
233 else printf (" entry expires on %s.", exp);
235 printf (" Max ticket lifetime %.2f hours.\n",
236 tentry.max_ticket_lifetime / 3600.0);
237 ka_timestr (tentry.modification_time,bob,KA_TIMESTR_LEN);
238 printf (" last mod on %s by ", bob);
239 ka_PrintUserID ("", tentry.modification_user.name,
240 tentry.modification_user.instance, "\n");
241 if ((tentry.reserved3 & 0xffff0000) == 0x12340000) {
242 int short reused = (short)tentry.reserved3;
244 printf(" permit password reuse\n");
246 printf(" don't permit password reuse\n");
258 int code, /* error code to handle */
259 struct OKerrors OKlist[], /* list of errors & messages that should be ignored */
260 int *persist) /* set this if we should retry, clear otherwise */
264 for (i=0; OKlist[i].code; i++) {
265 if (OKlist[i].code == code) {
266 printf ("%s\n", OKlist[i].msg);
267 *persist = 0; /* we're done */
272 printf (" : [%s] %s", error_table_name(code), error_message(code));
275 printf (", wait one second\n");
279 case RX_CALL_TIMEOUT:
280 printf (" (retrying)\n");
285 *persist = 0; /* don't retry these errors */
290 struct cmd_syndesc *as,
294 char name[MAXKTCNAMELEN];
295 char instance[MAXKTCNAMELEN];
296 struct ktc_encryptionKey key;
299 struct OKerrors OKlist[2];
302 code = ka_ParseLoginName (as->parms[0].items->data, name, instance, 0);
304 com_err (whoami, code, "parsing user's name '%s'",
305 as->parms[0].items->data);
308 ka_StringToKey (as->parms[1].items->data, cell, &key);
311 code = ubik_Call (KAM_CreateUser, conn, 0, name, instance, key);
313 ka_PrintUserID ("Creating user ", name, instance, " ");
314 code = handle_errors (code, OKlist, &persist);
320 struct cmd_syndesc *as,
324 char name[MAXKTCNAMELEN];
325 char instance[MAXKTCNAMELEN];
328 struct OKerrors OKlist[2];
330 code = ka_ParseLoginName (as->parms[0].items->data, name, instance, 0);
332 com_err (whoami, code, "parsing user's name '%s'",
333 as->parms[0].items->data);
338 code = ubik_Call (KAM_DeleteUser, conn, 0, name, instance);
340 ka_PrintUserID ("Deleting user ", name, instance, " ");
341 code = handle_errors (code, OKlist, &persist);
346 static int read_time_interval (
354 str = strncpy (buf, str, sizeof(buf));
355 s = strchr (str, ':');
356 if (s == 0) sec = atoi (str);
358 *s++ = '\0'; /* separate hours and minutes */
359 sec = atoi(str)*3600 + atoi(s)*60;
371 struct kaentryinfo tentry;
377 int addop; /* 1=add bit; 0=remove bit */
381 str = lcstring (bitspec, str, sizeof(bitspec));
383 if (strncmp(str, "0x", 2) == 0) /* 0x => hex */
384 sscanf (str, "0x%lx", &f);
385 else if (*str == '0') /* assume octal */
386 sscanf (str, "%lo", &f);
387 else /* just assume hex */
388 sscanf (str, "%lx", &f);
397 if (strchr ("+-", *str)) addop = (*str++ == '+');
398 else if (*str == '_') {addop = 0; str++;}
400 code = ubik_Call (KAM_GetEntry, conn, 0,
401 name, inst, KAMAJORVERSION, &tentry);
403 com_err (whoami, code,
404 "could get current flag value for %s.%s", name, inst);
413 if (isupper (c)) c = tolower(c);
414 if (!islower(c)) break;
419 if (strcmp (bit, "admin") == 0) flag = KAFADMIN;
420 else if (strcmp (bit, "noadmin") == 0) flag = KAFADMIN, addop = !addop;
421 else if (strcmp (bit, "notgs") == 0) flag = KAFNOTGS;
422 else if (strcmp (bit, "tgs") == 0) flag = KAFNOTGS, addop = !addop;
423 else if (strcmp (bit, "noseal") == 0) flag = KAFNOSEAL;
424 else if (strcmp (bit, "seal") == 0) flag = KAFNOSEAL, addop = !addop;
425 else if (strcmp (bit, "nocpw") == 0) flag = KAFNOCPW;
426 else if (strcmp (bit, "cpw") == 0) flag = KAFNOCPW, addop = !addop;
427 else if (strcmp (bit, "newassoc") == 0) flag = KAFNEWASSOC;
428 else if (strcmp (bit, "nonewassoc") == 0) flag = KAFNEWASSOC, addop = !addop;
430 printf ("Illegal bit name: %s; choices are: [no]admin, [no]tgs, [no]seal, [no]cpw\n", bit);
434 if (addop) f |= flag;
437 if (*str == 0) break;
438 if (*str == '+') addop = 1; /* get next op */
439 else if ((*str == '-') || (*str == '_')) addop = 0;
441 printf ("Illegal combination operator: %c\n", *str);
447 *flags = (f & KAF_SETTABLE_FLAGS) | KAFNORMAL;
450 #define seriouserror(code) ((code <0) || ((code != UNOSERVERS) && (code != UNOQUORUM) && code != UNOTSYNC))
452 /* return MAXLONG if locked forever */
453 afs_uint32 ka_islocked (
465 code = ubik_CallIter (KAM_LockStatus, conn, UPUBIKONLY, &count,
466 name, instance, &tempwhen, /*spares*/0,0,0,0);
468 if (seriouserror(code))
469 com_err (whoami, code, "");
471 else if (tempwhen) { /* user is locked */
472 if (!*when || tempwhen < *when) {
477 else /* ! tempwhen ==> user is not locked */
480 } while (code != UNOSERVERS);
486 struct cmd_syndesc *as,
489 afs_int32 code, rcode=0;
492 char name[MAXKTCNAMELEN];
493 char instance[MAXKTCNAMELEN];
495 code = ka_ParseLoginName (as->parms[0].items->data, name, instance, 0);
497 com_err (whoami, code, "parsing user's name '%s'", as->parms[0].items->data);
503 code = ubik_CallIter (KAM_Unlock, conn, 0, &count, name, instance,
505 if (code && (code != UNOSERVERS)) {
507 if (conn && conn->conns[count-1] && conn->conns[count-1]->peer) {
508 server = conn->conns[count-1]->peer->host;
510 com_err (whoami, code,
511 "so %s.%s may still be locked (on server %d.%d.%d.%d)",
512 name, instance, ((server>>24)&0xFF), ((server>>16)&0xFF),
513 ((server>>8)&0xFF), (server&0xFF));
519 } while (code != UNOSERVERS);
525 struct cmd_syndesc *as,
529 char name[MAXKTCNAMELEN];
530 char instance[MAXKTCNAMELEN];
533 afs_int32 lifetime = 0;
534 afs_int32 maxAssociates = -1;
535 afs_int32 pwexpiry = 0;
536 afs_int32 was_spare = 0;
537 char misc_auth_bytes[4];
540 code = ka_ParseLoginName (as->parms[0].items->data, name, instance, 0);
542 com_err (whoami, code, "parsing user's name '%s'",
543 as->parms[0].items->data);
547 if (as->parms[1].items) {
548 code = parse_flags (name, instance, as->parms[1].items->data, &flags);
550 printf ("Illegal flag specification: %s, should be of the form <'='|'+'|'-'|'_'>bitname{<'+'|'-'>bitname}*\n", as->parms[1].items->data);
554 if (as->parms[2].items) {
556 char *s = strncpy (buf, as->parms[2].items->data, sizeof(buf));
557 code = ktime_DateToInt32 (s, &expiration);
559 printf ("Illegal time format %s: %s\n",
560 as->parms[2].items->data, ktime_GetDateUsage());
563 if (expiration == 0) {
564 fprintf (stderr, "Expiration time must be after (about) 1970.\n");
567 if (expiration < time(0)) {
568 fprintf (stderr, "Warning: expiration being set into the past, account will be disabled.\n");
574 if (as->parms[3].items) {
575 code = read_time_interval (as->parms[3].items->data, &lifetime);
576 if (code) return KABADCMD;
579 /* no point in doing this any sooner than necessary */
580 for (i=0;i<4;misc_auth_bytes[i++] = 0);
582 if (as->parms[4].items) {
583 if (isint(as->parms[4].items->data))
584 pwexpiry = atoi (as->parms[4].items->data);
586 fprintf(stderr,"Password lifetime specified must be a non-negative decimal integer.\n");
589 if (pwexpiry <0 || pwexpiry >254) {
590 fprintf(stderr,"Password lifetime range must be [0..254] days.\n");
591 fprintf(stderr,"Zero represents an unlimited lifetime.\n");
595 misc_auth_bytes[0] = pwexpiry+1;
599 if (as->parms[5].items) {
601 reuse = (as->parms[5].items->data);
603 if (!strcmp(reuse, "yes")) {
604 misc_auth_bytes[1] = KA_REUSEPW;
606 else if (strcmp(reuse, "no")) {
607 fprintf(stderr,"must specify \"yes\" or \"no\": \"yes\" assumed\n");
608 misc_auth_bytes[1] = KA_REUSEPW;
611 misc_auth_bytes[1] = KA_NOREUSEPW;
615 if (as->parms[6].items) {
619 if (isint(as->parms[6].items->data) &&
620 ((nfailures = atoi(as->parms[6].items->data)) < 255)) {
621 misc_auth_bytes[2] = nfailures+1;
624 fprintf(stderr,"Failure limit must be in [0..254].\n");
625 fprintf(stderr,"Zero represents unlimited login attempts.\n");
630 if (as->parms[7].items) {
631 int locktime, hrs, mins;
635 s = as->parms[7].items->data;
637 sscanf(s, "%d:%d", &hrs, &mins);
639 sscanf(s, "%d", &mins);
641 locktime = hrs*60 + mins;
642 if (hrs < 0 || hrs > 36 || mins < 0) {
643 fprintf(stderr,"Lockout times must be either minutes or hh:mm.\n");
644 fprintf(stderr,"Lockout times must be less than 36 hours.\n");
647 else if (locktime > 36*60 ) {
648 fprintf(stderr,"Lockout times must be either minutes or hh:mm.\n");
649 fprintf(stderr,"Lockout times must be less than 36 hours.\n");
650 fprintf(stderr,"Continuing with lock time of exactly 36 hours...\n");
653 locktime = (locktime * 60 + 511) >> 9; /* ceil(l*60/512) */
654 misc_auth_bytes[3] = locktime +1; /* will be 1 if user said 0 */
658 if (as->parms[8].items) {
659 maxAssociates = atoi (as->parms[6].items->data);
660 if (maxAssociates < 0) {
661 printf ("Illegal maximum number of associates\n");
666 was_spare = pack_long(misc_auth_bytes);
668 if (was_spare || flags || expiration || lifetime || (maxAssociates >= 0))
670 (KAM_SetFields, conn, 0,
671 name, instance, flags, expiration, lifetime, maxAssociates,
672 was_spare, /* spare */ 0);
674 printf ("Must specify one of the optional parameters\n");
677 if (code) com_err (whoami, code,
678 "calling KAM_SetFields for %s.%s", name, instance);
683 struct cmd_syndesc *as,
687 char realm[MAXKTCREALMLEN];
688 struct ktc_encryptionKey key;
690 if (as->parms[1].items) {
691 code = ka_ExpandCell (as->parms[1].items->data, realm, 0/*local*/);
693 com_err (whoami, code,
694 "expanding %s as cell name, attempting to continue",
695 as->parms[1].items->data);
697 ucstring (realm, realm, sizeof(realm));
700 if (code = DefaultCell()) return code;
701 ucstring (realm, cell, sizeof(realm));
703 ka_StringToKey (as->parms[0].items->data, realm, &key);
705 printf ("Converting %s in realm '%s' yields key='",
706 as->parms[0].items->data, realm);
707 ka_PrintBytes ((char *)&key, sizeof(key));
710 des_string_to_key (as->parms[0].items->data, &key);
712 printf ("Converting %s with the DES string to key yields key='",
713 as->parms[0].items->data);
714 ka_PrintBytes (&key, sizeof(key));
721 struct cmd_syndesc *as,
725 char name[MAXKTCNAMELEN];
726 char instance[MAXKTCNAMELEN];
727 char realm[MAXKTCREALMLEN];
728 struct ktc_encryptionKey key;
731 code = ka_ParseLoginName (as->parms[0].items->data, name, instance, realm);
733 com_err (whoami, code, "parsing user's name '%s'",
734 as->parms[0].items->data);
738 if (strlen(realm) == 0)
739 ucstring (realm, cell, sizeof(realm));
741 if (as->parms[1].items && as->parms[2].items) {
742 printf ("Can't specify both a password and a key\n");
745 else if (as->parms[1].items) {
746 (void) init_child(myName);
747 (void) give_to_child(passwd); /* old password */
748 code = password_bad(as->parms[1].items->data);
749 (void) terminate_child();
752 ka_StringToKey (as->parms[1].items->data, realm, &key);
754 else if (as->parms[2].items) {
755 if (ka_ReadBytes (as->parms[2].items->data, (char *)&key, sizeof(key))
757 printf ("Key must be 8 bytes: '%s' was too long\n",
758 as->parms[2].items->data);
763 printf ("Must specify new password or key\n");
768 if (as->parms[3].items)
769 sscanf (as->parms[3].items->data, "%d", &kvno);
771 #ifdef AFS_S390_LINUX20_ENV
772 code = ubik_Call (KAM_SetPassword, conn, 0, name, instance, kvno, 0, key);
774 code = ubik_Call (KAM_SetPassword, conn, 0, name, instance, kvno, key);
776 if (code) com_err (whoami, code,
777 "so can't set password for %s.%s", name, instance);
781 #define PrintPrincipal(p,n,l) \
782 PrintName((p)->name, (p)->instance, (p)->cell, l, n)
784 static afs_int32 PrintName (
792 int left; /* if ConvertBytes stops early */
795 if (name == 0) name = "";
796 if (inst == 0) inst = "";
797 if (acell == 0) acell = "";
798 left = ka_ConvertBytes(buf, buflen, name, strlen(name));
802 com_err (whoami, code,
803 "PrintName: principal name was '%s'.'%s'@'%s'",
810 if (nlen + len + 1 >= buflen) goto bad_name;
812 left = ka_ConvertBytes(buf+nlen, buflen-nlen, inst, len);
813 if (left) goto bad_name;
819 char *lcell = ka_LocalCell();
820 if (lcell == 0) lcell = "";
821 if (strcmp (acell, lcell) != 0) {
822 /* only append cell if not the local cell */
823 if (nlen + len + 1 >= buflen) goto bad_name;
825 left = ka_ConvertBytes(buf+nlen, buflen-nlen, acell, len);
826 if (left) goto bad_name;
833 #define PrintedPrincipal(p) PrintedName ((p)->name, (p)->instance, (p)->cell)
835 /* PrintedName - returned a pointer to a static string in which the formated
836 * name has been stored. */
838 static char *PrintedName (
843 static char printedName[128];
845 code = PrintName (name, inst, cell, sizeof(printedName), printedName);
847 if (name == 0) name = "";
848 strncpy (printedName, name, sizeof(printedName));
849 printedName[sizeof(printedName)-8] = 0;
850 strcat (printedName, "<error>");
855 static afs_int32 ListTicket (
856 struct ktc_principal *server,
860 struct ktc_token token; /* the token we're printing */
861 struct ktc_principal client;
862 char UserName[sizeof(struct ktc_principal)];
863 char ServerName[sizeof(struct ktc_principal)];
864 afs_int32 now = time(0);
865 char bob[KA_TIMESTR_LEN];
867 /* get the ticket info itself */
868 code = ktc_GetToken (server, &token, sizeof(token), &client);
870 com_err (whoami, code, "failed to get token info for server %s",
871 PrintedPrincipal (server));
874 code = PrintPrincipal (&client, UserName, sizeof(UserName));
875 if (code) return code;
876 /* spaces are printed as "\040" */
877 if (UserName[0] == 0)
879 else if (strncmp(UserName, "AFS\\040ID\\040", 13) == 0) {
880 printf("User's (AFS ID %s) tokens", UserName+13);
882 else if (strncmp(UserName, "Unix\\040UID\\040", 15) == 0) {
886 printf("User %s's tokens", UserName);
888 code = PrintPrincipal (server, ServerName, sizeof(ServerName));
889 if (code) return code;
890 printf(" for %s ", ServerName);
892 if (token.startTime > now) {
893 ka_timestr(token.startTime,bob,KA_TIMESTR_LEN);
894 printf("[>> POSTDATED 'till %s <<]",bob);
897 if (token.endTime <= now)
898 printf("[>> Expired <<]\n");
900 ka_timestr(token.endTime,bob,KA_TIMESTR_LEN);
901 printf("[Expires %s]\n", bob);
904 printf ("SessionKey: ");
905 ka_PrintBytes ((char *)&token.sessionKey, sizeof(token.sessionKey));
906 printf ("\nTicket (kvno = %d, len = %d): ", token.kvno,
908 ka_PrintBytes ((char *)token.ticket, token.ticketLen);
915 struct cmd_syndesc *as,
919 struct ktc_principal server;
920 struct ktc_token token;
921 afs_int32 life = KA_SIXHOURS;
923 if (as->parms[1].items) {
924 code = read_time_interval (as->parms[1].items->data, &life);
925 if (code) return KABADCMD;
927 code = ka_ParseLoginName (as->parms[0].items->data,
928 server.name, server.instance, server.cell);
930 com_err (whoami, code, "parsing user's name '%s'",
931 as->parms[0].items->data);
934 if (server.cell[0] == 0) {
935 if (code = DefaultCell()) return code;
936 strcpy (server.cell, cell);
938 code = ka_ExpandCell (server.cell, server.cell, 0/*local*/);
940 com_err (whoami, code, "Can't expand cell name");
945 token.ticketLen = 0; /* in case there are no tokens */
946 code = ka_GetServerToken (server.name, server.instance, server.cell,
947 life, &token, /*new*/1, /*dosetpag*/0);
948 if (code) com_err (whoami, code,
949 "getting ticket for %s", PrintedPrincipal (&server));
951 code = ListTicket (&server, /*verbose*/1);
957 struct cmd_syndesc *as,
961 char name[MAXKTCNAMELEN];
962 struct ktc_encryptionKey key;
963 static struct ubik_client *lpbkConn = 0;
965 /* no instance allowed */
966 code = ka_ParseLoginName (as->parms[0].items->data, name, 0, 0);
969 com_err (whoami, code,
970 "getting %s's password via loopback connection to GetPassword", name);
971 /* if we got a timeout, print a clarification, too */
973 fprintf(stderr, "%s: please note that this command must be run locally on a database server machine.\n", whoami);
978 struct rx_connection *conns[2];
979 struct rx_securityClass *sc;
980 int si; /* security class index */
983 if (code) goto abort;
984 sc = (struct rx_securityClass *) rxnull_NewClientSecurityObject();
985 si = RX_SCINDEX_NULL;
986 conns[0] = rx_NewConnection (htonl(INADDR_LOOPBACK), htons(AFSCONF_KAUTHPORT),
987 KA_MAINTENANCE_SERVICE, sc, si);
989 code = ubik_ClientInit(conns, &lpbkConn);
990 if (code) goto abort;
992 code = ubik_Call (KAM_GetPassword, lpbkConn, 0, name, &key);
993 /* Lets close down the ubik_Client connection now */
994 ubik_ClientDestroy(lpbkConn);
995 if (code) goto abort;
997 ka_PrintBytes ((char *)&key, sizeof(key));
1003 struct cmd_syndesc *as,
1007 struct ktc_encryptionKey key;
1009 code = ubik_Call (KAM_GetRandomKey, conn, 0, &key);
1010 if (code) com_err(whoami, code, "so can't get random key");
1014 ka_PrintBytes ((char *)&key, sizeof(key));
1016 for (i=0; i<sizeof(key); i++) {
1017 printf ("%0.2x", ((char *)&key)[i] & 0xff);
1018 if (i==3) printf (" ");
1019 else if (i!=7) printf (".");
1027 struct cmd_syndesc *as,
1034 char bob[KA_TIMESTR_LEN];
1036 code = ubik_Call (KAM_GetStats, conn, 0,
1037 KAMAJORVERSION, &admins, &statics, &dynamics);
1039 printf ("call to GetStats failed: %s\n", ka_ErrorString(code));
1042 if (statics.minor_version != KAMINORVERSION)
1043 printf ("Minor version number mismatch: got %d, expected %d\n",
1044 statics.minor_version, KAMINORVERSION);
1045 printf ("%d allocs, %d frees, %d password changes\n",
1046 statics.allocs, statics.frees, statics.cpws);
1047 printf ("Hash table utilization = %f%%\n",
1048 (double)dynamics.hashTableUtilization / 100.0);
1049 ka_timestr(dynamics.start_time,bob,KA_TIMESTR_LEN);
1050 printf ("From host %lx started at %s:\n", dynamics.host, bob);
1052 #define print_stat(name) if (dynamics.name.requests) printf (" of %d requests for %s, %d were aborted.\n", dynamics.name.requests, # name, dynamics.name.aborts)
1053 print_stat (Authenticate);
1054 print_stat (ChangePassword);
1055 print_stat (GetTicket);
1056 print_stat (CreateUser);
1057 print_stat (SetPassword);
1058 print_stat (SetFields);
1059 print_stat (DeleteUser);
1060 print_stat (GetEntry);
1061 print_stat (ListEntry);
1062 print_stat (GetStats);
1063 print_stat (GetPassword);
1064 print_stat (GetRandomKey);
1066 print_stat (UAuthenticate);
1067 print_stat (UGetTicket);
1069 #if (KAMAJORVERSION>5)
1071 printf ("%d string checks\n", dynamics.string_checks);
1073 printf ("Used %.3f seconds of CPU time.\n", dynamics.string_checks/1000.0);
1075 printf ("%d admin accounts\n", admins);
1080 struct cmd_syndesc *as,
1084 struct ka_debugInfo info;
1088 char bob[KA_TIMESTR_LEN];
1091 if (as->parms[0].items) {
1092 struct ubik_client *iConn;
1093 code = ka_SingleServerConn (cell, as->parms[0].items->data, KA_MAINTENANCE_SERVICE, 0, &iConn);
1095 struct afsconf_cell cellinfo;
1097 com_err (whoami, code, "couldn't find host %s in cell %s",
1098 as->parms[0].items->data, cell);
1099 code = ka_GetServers (cell, &cellinfo);
1100 if (code) com_err (whoami, code, "getting servers in cell %s", cell);
1102 printf ("Servers in cell %s, are:\n", cell);
1103 for (i=0; i<cellinfo.numServers; i++)
1104 printf (" %s\n", cellinfo.hostName[i]);
1108 code = ubik_Call (KAM_Debug, iConn, 0, KAMAJORVERSION, 0, &info);
1109 ubik_ClientDestroy (iConn);
1111 else code = ubik_Call (KAM_Debug, conn, 0, KAMAJORVERSION, 0, &info);
1114 com_err (whoami, code, "call to Debug failed");
1119 if (info.minorVersion != KAMINORVERSION)
1120 printf ("Minor version number mismatch: got %d, expected %d\n",
1121 info.minorVersion, KAMINORVERSION);
1124 #if (KAMAJORVERSION>5)
1130 if (timeOffset < 0) timeOffset = -timeOffset;
1131 if (timeOffset > 60) {
1132 printf ("WARNING: Large server client clock skew: %d seconds. Call itself took %d seconds.\n", timeOffset, now-start);
1134 ka_timestr(info.startTime,bob,KA_TIMESTR_LEN);
1135 printf ("From host %lx started %sat %s:\n",
1136 info.host, (info.noAuth ? "w/o authorization " : ""),
1138 ka_timestr (info.lastTrans,bob,KA_TIMESTR_LEN);
1139 printf ("Last trans was %s at %s\n", info.lastOperation, bob);
1140 ka_timestr (info.dbHeaderRead,bob,KA_TIMESTR_LEN);
1141 printf ("Header last read %s.\n", bob);
1142 printf ("db version=%d, keyVersion=%d, key cache version=%d\n",
1143 info.dbVersion, info.dbSpecialKeysVersion, info.kcVersion);
1144 printf ("db ptrs: free %d, eof %d, kvno %d.\n",
1145 info.dbFreePtr, info.dbEofPtr, info.dbKvnoPtr);
1146 ka_timestr (info.nextAutoCPW,bob,KA_TIMESTR_LEN);
1147 printf ("Next autoCPW at %s or in %d updates.\n",
1148 bob, info.updatesRemaining);
1149 if (info.cheader_lock || info.keycache_lock)
1150 printf ("locks: cheader %08lx, keycache %08lx\n",
1151 info.cheader_lock, info.keycache_lock);
1152 printf ("Last authentication for %s, last admin user was %s\n",
1153 info.lastAuth, info.lastAdmin);
1154 printf ("Last TGS op was a %s ticket was for %s\n",
1155 info.lastTGSServer, info.lastTGS);
1156 printf ("Last UDP TGS was a %s ticket for %s. UDP Authenticate for %s\n",
1157 info.lastUTGSServer, info.lastUTGS, info.lastUAuth);
1158 printf ("key cache size %d, used %d.\n",
1159 info.kcSize, info.kcUsed);
1160 if (info.kcUsed > KADEBUGKCINFOSIZE) {
1161 printf("insufficient room to return all key cache entries!\n");
1162 info.kcUsed = KADEBUGKCINFOSIZE;
1164 for (i=0; i<info.kcUsed; i++)
1165 ka_timestr(info.kcInfo[i].used,bob,KA_TIMESTR_LEN);
1166 printf ("%32s %c %2x(%2x) used %s\n",
1167 info.kcInfo[i].principal, (info.kcInfo[i].primary?'*':' '),
1168 info.kcInfo[i].kvno, info.kcInfo[i].keycksum,
1174 struct cmd_syndesc *as,
1182 struct cmd_syndesc *as,
1190 struct cmd_syndesc *as)
1192 if (!strcmp(as->name,"help")) return;
1194 /* Determine if we need to destory the ubik connection.
1195 * Closing it avoids resends of packets.
1198 ubik_ClientDestroy(conn);
1205 int init = 0, noauth;
1206 char name[MAXKTCNAMELEN];
1207 char instance[MAXKTCNAMELEN];
1208 char newCell[MAXKTCREALMLEN];
1209 afs_int32 serverList[MAXSERVERS];
1212 struct cmd_syndesc *as,
1219 static int MyBeforeProc(
1220 struct cmd_syndesc *as,
1223 extern struct passwd *getpwuid();
1225 struct ktc_encryptionKey key;
1226 struct ktc_principal auth_server, auth_token, client;
1227 char realm[MAXKTCREALMLEN];
1229 struct ktc_token token, *pToken;
1230 int i, acode, code = 0;
1232 { char *ws = strrchr (as->a0name, '/');
1233 if (ws) ws++; /* skip everything before the "/" */
1234 else ws = as->a0name;
1235 if (strlen(ws) > 0) {
1236 strncpy (whoami, ws, sizeof(whoami));
1237 if (strlen (whoami)+1 >= sizeof(whoami)) strcpy (whoami, "kas:");
1238 else strcat (whoami, ":");
1239 } else whoami[0] = 0;
1240 /* append sub-command name */
1241 strncat (whoami, as->name, sizeof(whoami) - strlen(whoami) -1);
1244 if (as->parms[12].name == 0) return 0;
1246 assert (as->parms[13].name && as->parms[14].name &&
1247 as->parms[15].name && as->parms[16].name);
1249 /* MyAfterProc() destroys the conn, but just to be sure */
1251 code = ubik_ClientDestroy (conn);
1255 if (!init || as->parms[12].items || as->parms[13].items ||
1256 as->parms[14].items || as->parms[15].items ||
1257 as->parms[16].items) {
1258 strcpy (instance, "");
1259 strcpy (newCell, "");
1261 if (as->parms[12].items) { /* -admin_username */
1262 code = ka_ParseLoginName (as->parms[12].items->data, name, instance, newCell);
1264 com_err (whoami, code, "parsing user's name '%s'", as->parms[12].items->data);
1269 DWORD len = MAXKTCNAMELEN;
1270 if (!GetUserName((LPTSTR)name, &len)) {
1271 printf("Can't get user name \n");
1275 /* No explicit name provided: use Unix uid. */
1276 pw = getpwuid(getuid());
1278 printf ("Can't figure out your name from your user id.\n");
1281 strncpy (name, pw->pw_name, sizeof(name));
1285 if (as->parms[14].items) { /* -cell */
1286 if (strlen(newCell) > 0) {
1287 printf ("Duplicate cell specification not allowed\n");
1289 strncpy (newCell, as->parms[14].items->data, sizeof(newCell));
1292 code = ka_ExpandCell (newCell, newCell, 0/*local*/);
1294 com_err (whoami, code, "Can't expand cell name");
1297 strcpy (cell, newCell);
1299 if (as->parms[15].items) { /* -servers */
1300 struct cmd_item *ip;
1301 char *ap[MAXSERVERS+2];
1305 for (ip = as->parms[15].items, i=2; ip; ip=ip->next, i++)
1307 code = ubik_ParseClientList(i, ap, serverList);
1309 com_err (whoami, code, "could not parse server list");
1312 ka_ExplicitCell (cell, serverList);
1315 noauth = (as->parms[16].items ? 1 : 0); /* -noauth */
1320 token.ticketLen = 0; /* in case there are no tokens */
1321 if (!noauth) { /* Will prompt for a password */
1322 /* first see if there's already an admin ticket */
1323 code = ka_GetAdminToken (0, 0, cell, 0, KA_SIXHOURS, &token, 0/* !new */);
1324 if (code) { /* if not then get key and try again */
1325 if (as->parms[13].items) { /* if password specified */
1326 strncpy (passwd, as->parms[13].items->data, sizeof(passwd));
1327 bzero (as->parms[13].items->data, strlen (as->parms[13].items->data));
1329 char msg[MAXKTCNAMELEN+50];
1330 if (as->parms[12].items) sprintf (msg, "Administrator's (%s) Password: ", name);
1331 else sprintf (msg, "Password for %s: ", name);
1332 code = read_pw_string (passwd, sizeof(passwd), msg, 0);
1333 if (code) code = KAREADPW;
1334 else if (strlen(passwd) == 0) code = KANULLPASSWORD;
1336 com_err (whoami, code, "reading password");
1340 ka_StringToKey (passwd, cell, &key);
1341 code = ka_GetAdminToken (name, instance, cell, &key, KA_SIXHOURS,
1342 &token, 0/* !new */);
1343 if (code == KABADREQUEST) {
1344 des_string_to_key (passwd, &key);
1345 code = ka_GetAdminToken (name, instance, cell, &key, KA_SIXHOURS,
1346 &token, 0/* !new */);
1348 if ((code == KABADREQUEST) && (strlen(passwd) > 8)) {
1349 /* try with only the first 8 characters incase they set
1350 * their password with an old style passwd program. */
1352 ka_StringToKey (passwd, cell, &key);
1353 code = ka_GetAdminToken (name, instance, cell, &key,
1354 KA_SIXHOURS, &token, 0/* !new */);
1356 fprintf (stderr, "Warning: you have typed a password longer than 8 characters, but only the\n");
1357 fprintf (stderr, "first 8 characters were actually significant. If you change your password\n");
1358 fprintf (stderr, "again this warning message will go away.\n");
1365 reason = "password was incorrect";
1368 reason = "Authentication Server was unavailable";
1371 reason = (char *)error_message (code);
1373 fprintf (stderr, "%s: Auth. as %s to AuthServer failed: %s\nProceeding w/o authentication\n",
1374 whoami, PrintedName(name,instance,cell), reason);
1376 /* get an Authentication token while were at it. */
1377 if (ka_CellToRealm(cell, realm, 0) != 0) realm[0] = '\0';
1378 strcpy(auth_server.name, KA_TGS_NAME);
1379 strcpy(auth_server.instance, realm);
1380 strcpy(auth_server.cell, cell);
1381 if (ktc_GetToken(&auth_server, &auth_token, sizeof(struct ktc_token), &client) != 0) {
1382 acode = ka_GetAuthToken (name, instance, cell, &key,
1383 MAXKTCTICKETLIFETIME,
1384 (afs_int32 *)0 /*Don't need pwd expiration info here*/);
1385 if (acode && (acode != code)) /* codes are usually the same */
1386 com_err (whoami, code,
1387 "getting Authentication token for %s",
1388 PrintedName (name, instance, cell));
1390 bzero (&key, sizeof(key));
1394 pToken = ((token.ticketLen == 0) ? 0 : &token);
1395 code = ka_AuthServerConn (cell, KA_MAINTENANCE_SERVICE, pToken, &conn);
1396 if (code && pToken) {
1397 com_err (whoami, code,
1398 "connecting to AuthServer: now trying w/o authentication");
1399 code = ka_AuthServerConn (cell, KA_MAINTENANCE_SERVICE, 0, &conn);
1400 if (code) com_err (whoami, code, "making unauthenticated connection to AuthServer");
1403 com_err (whoami, code, "Couldn't establish connection to Authentication Server");
1407 /* now default unspecified password by prompting from terminal */
1408 if (as->nParms >= 12) for (i=0; i<12; i++)
1409 if (as->parms[i].name && (as->parms[i].items == 0)) {
1410 char *p = as->parms[i].name; /* parameter name */
1411 int l = strlen (p); /* length of name */
1412 /* does parameter end in "password" */
1413 if (strcmp (p+(l-8), "password") == 0) {
1415 char password[BUFSIZ];
1416 struct cmd_item *ip;
1420 code = read_pw_string (password, sizeof(password), msg, 1);
1421 if (code) code = KAREADPW;
1422 else if (strlen(password) == 0) code = KANULLPASSWORD;
1424 com_err (whoami, code, "prompting for %s", p+1);
1427 ip = (struct cmd_item *)malloc (sizeof(struct cmd_item));
1428 ip->data = (char *)malloc (strlen(password)+1);
1430 strcpy (ip->data, password);
1431 as->parms[i].items = ip;
1434 if (!conn) { /* if all else fails... */
1435 code = NoAuth (0,0); /* get unauthenticated conn */
1436 if (code) return code;
1441 /* These are some helpful command that deal with the cache managers tokens. */
1443 static ForgetTicket (
1444 struct cmd_syndesc *as,
1448 struct ktc_principal server;
1451 if (as->parms[0].items) {
1452 char *name = as->parms[0].items->data;
1453 code = ka_ParseLoginName
1454 (name, server.name, server.instance, server.cell);
1456 com_err (whoami, code, "couldn't interpret name '%s'", name);
1459 if (server.cell[0] == 0) {
1460 if (code = DefaultCell()) return code;
1461 strcpy (server.cell, cell);
1463 code = ka_ExpandCell (server.cell, server.cell, 0/*local*/);
1465 com_err (whoami, code, "Can't expand cell name");
1469 code = ktc_ForgetToken (&server);
1471 com_err (whoami, code, "couldn't remove tokens for %s",
1472 PrintedPrincipal (&server));
1477 if (!as->parms[1].items) {
1478 fprintf (stderr, "Must specify server name or -all\n");
1481 code = ktc_ForgetAllTokens();
1483 com_err (whoami, code, "couldn't delete all tokens");
1488 code = ktc_ForgetAllTokens();
1490 com_err (whoami, code, "couldn't delete all tokens");
1496 static ListTickets (
1497 struct cmd_syndesc *as,
1501 int index, newIndex;
1502 struct ktc_principal server;
1505 if (as->parms[1].items) verbose = 1;
1506 if (as->parms[0].items) {
1507 char *name = as->parms[0].items->data;
1508 code = ka_ParseLoginName
1509 (name, server.name, server.instance, server.cell);
1511 com_err (whoami, code, "couldn't interpret name '%s'", name);
1514 if (server.cell[0] == 0) {
1515 if (code = DefaultCell()) return code;
1516 strcpy (server.cell, cell);
1518 code = ka_ExpandCell (server.cell, server.cell, 0/*local*/);
1520 com_err (whoami, code, "Can't expand cell name");
1524 code = ListTicket (&server, verbose);
1526 else for (index = 0; ; index = newIndex) {
1527 code = ktc_ListTokens(index, &newIndex, &server);
1529 if (code == KTC_NOENT) code = 0; /* end of list */
1532 code = ListTicket(&server, verbose);
1537 static void add_std_args (register struct cmd_syndesc *ts)
1540 /* 12 */ cmd_AddParm (ts, "-admin_username", CMD_SINGLE, CMD_OPTIONAL,
1541 "admin principal to use for authentication");
1542 /* 13 */ cmd_AddParm (ts, "-password_for_admin", CMD_SINGLE, CMD_OPTIONAL,
1544 /* 14 */ cmd_AddParm (ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cell name");
1545 /* 15 */ cmd_AddParm (ts, "-servers", CMD_LIST, CMD_OPTIONAL,
1546 "explicit list of authentication servers");
1547 /* 16 */ cmd_AddParm (ts, "-noauth", CMD_FLAG, CMD_OPTIONAL,
1548 "don't authenticate");
1551 afs_int32 ka_AdminInteractive (
1556 register struct cmd_syndesc *ts;
1562 strncpy(myName, *cmd_argv, 509);
1564 cmd_SetBeforeProc(MyBeforeProc, (char *) 0);
1565 cmd_SetAfterProc(MyAfterProc, (char *) 0);
1567 ts = cmd_CreateSyntax ("interactive", Interactive, 0, "enter interactive mode");
1570 ts = cmd_CreateSyntax ("noauthentication", NoAuth, 0, "connect to AuthServer w/o using token");
1572 ts = cmd_CreateSyntax ("list", ListUsers, 0, "list all users in database");
1573 cmd_AddParm (ts, "-long", CMD_FLAG, CMD_OPTIONAL, "show detailed info about each user");
1574 cmd_AddParm (ts, "-showadmin", CMD_FLAG, CMD_OPTIONAL, "show all cell administrators");
1575 cmd_AddParm (ts, "-showkey", CMD_FLAG, CMD_OPTIONAL, "show the user's actual key rather than the checksum");
1577 cmd_CreateAlias (ts, "ls");
1579 ts = cmd_CreateSyntax ("examine", ExamineUser, 0, "examine the entry for a user");
1580 cmd_AddParm (ts, "-name", CMD_SINGLE, 0, "name of user");
1581 cmd_AddParm (ts, "-showkey", CMD_FLAG, CMD_OPTIONAL, "show the user's actual key rather than the checksum");
1584 ts = cmd_CreateSyntax ("create", CreateUser, 0, "create an entry for a user");
1585 cmd_AddParm (ts, "-name", CMD_SINGLE, 0, "name of user");
1586 cmd_AddParm (ts, "-initial_password", CMD_SINGLE, CMD_OPTIONAL, "initial password");
1589 ts = cmd_CreateSyntax ("delete", DeleteUser, 0, "delete a user");
1590 cmd_AddParm (ts, "-name", CMD_SINGLE, 0, "name of user");
1592 cmd_CreateAlias (ts, "rm");
1594 ts = cmd_CreateSyntax ("setfields", SetFields, 0, "set various fields in a user's entry");
1595 cmd_AddParm (ts, "-name", CMD_SINGLE, 0, "name of user");
1596 cmd_AddParm (ts, "-flags", CMD_SINGLE, CMD_OPTIONAL, "hex flag value or flag name expression");
1597 cmd_AddParm (ts, "-expiration", CMD_SINGLE, CMD_OPTIONAL, "date of account expiration");
1598 cmd_AddParm (ts, "-lifetime", CMD_SINGLE, CMD_OPTIONAL, "maximum ticket lifetime");
1599 cmd_AddParm (ts, "-pwexpires", CMD_SINGLE, CMD_OPTIONAL, "number days password is valid ([0..254])");
1600 cmd_AddParm (ts, "-reuse", CMD_SINGLE, CMD_OPTIONAL, "permit password reuse (yes/no)");
1601 cmd_AddParm (ts, "-attempts", CMD_SINGLE, CMD_OPTIONAL, "maximum successive failed login tries ([0..254])");
1602 cmd_AddParm (ts, "-locktime", CMD_SINGLE, CMD_OPTIONAL, "failure penalty [hh:mm or minutes]");
1604 cmd_AddParm (ts, "-associates", CMD_SINGLE, CMD_OPTIONAL, "maximum associate instances");
1607 cmd_CreateAlias (ts, "sf");
1610 ts = cmd_CreateSyntax ("unlock", Unlock, 0, "Enable authentication ID after max failed attempts exceeded");
1611 cmd_AddParm (ts, "-name", CMD_SINGLE, 0, "authentication ID");
1615 ts = cmd_CreateSyntax ("stringtokey", StringToKey, 0, "convert a string to a key");
1616 cmd_AddParm (ts, "-string", CMD_SINGLE, 0, "password string");
1617 cmd_AddParm (ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cell name");
1619 ts = cmd_CreateSyntax ("setpassword", SetPassword, 0, "set a user's password");
1620 cmd_AddParm (ts, "-name", CMD_SINGLE, 0, "name of user");
1621 cmd_AddParm (ts, "-new_password", CMD_SINGLE, CMD_OPTIONAL, "new password");
1623 cmd_AddParm (ts, "-kvno", CMD_SINGLE, CMD_OPTIONAL, "key version number");
1625 cmd_CreateAlias (ts, "sp");
1626 #ifdef CMD_PARSER_AMBIG_FIX
1627 cmd_CreateAlias (ts, "setpasswd");
1630 /* set a user's key */
1631 ts = cmd_CreateSyntax ("setkey", SetPassword, 0, (char *) CMD_HIDDEN);
1632 cmd_AddParm (ts, "-name", CMD_SINGLE, 0, "name of user");
1634 cmd_AddParm (ts, "-new_key", CMD_SINGLE, 0, "eight byte new key");
1636 cmd_AddParm (ts, "-kvno", CMD_SINGLE, CMD_OPTIONAL, "key version number");
1639 /* get a user's password */
1640 ts = cmd_CreateSyntax ("getpassword", GetPassword, 0, (char *) CMD_HIDDEN);
1641 cmd_AddParm (ts, "-name", CMD_SINGLE, 0, "name of user");
1642 /* don't take standard args */
1643 /* add_std_args (ts); */
1644 #ifdef CMD_PARSER_AMBIG_FIX
1645 cmd_CreateAlias (ts, "getpasswd");
1648 /* get a random key */
1649 ts = cmd_CreateSyntax ("getrandomkey", GetRandomKey, 0, (char *) CMD_HIDDEN);
1652 /* get a ticket for a specific server */
1653 ts = cmd_CreateSyntax ("getticket", GetTicket, 0, (char *) CMD_HIDDEN);
1654 cmd_AddParm (ts, "-name", CMD_SINGLE, 0, "name of server");
1655 cmd_AddParm (ts, "-lifetime", CMD_SINGLE, CMD_OPTIONAL, "ticket lifetime");
1658 ts = cmd_CreateSyntax ("statistics", Statistics, 0, "show statistics for AuthServer");
1661 /* show debugging info from AuthServer */
1662 ts = cmd_CreateSyntax ("debuginfo", DebugInfo, 0, (char *) CMD_HIDDEN);
1663 cmd_AddParm (ts, "-hostname", CMD_SINGLE, CMD_OPTIONAL, "authentication server host name");
1666 ts = cmd_CreateSyntax ("forgetticket", ForgetTicket, 0, "delete user's tickets");
1668 cmd_AddParm (ts, "-name", CMD_SINGLE, (CMD_OPTIONAL | CMD_HIDE), "name of server");
1670 cmd_AddParm (ts, "-all", CMD_FLAG, CMD_OPTIONAL, "delete all tickets");
1672 ts = cmd_CreateSyntax ("listtickets", ListTickets, 0, "show all cache manager tickets");
1673 cmd_AddParm (ts, "-name", CMD_SINGLE, CMD_OPTIONAL, "name of server");
1674 cmd_AddParm (ts, "-long", CMD_FLAG, CMD_OPTIONAL, "show session key and ticket");
1676 ts = cmd_CreateSyntax ("quit", Quit, 0, "exit program");
1679 conn = 0; /* no connection yet */
1680 zero_argc = cmd_argc;
1681 zero_argv = cmd_argv;
1683 strcpy (whoami, "kas");
1685 if (code = cmd_Dispatch(cmd_argc, cmd_argv)) {
1694 s = fgets (line, sizeof(line), stdin);
1695 if (s == NULL) return 0; /* EOF on input */
1696 for (i=strlen(line)-1; i>=0 && isspace(line[i]); i--) line[i]=0;
1697 if (i < 0) continue; /* blank line */
1699 code = cmd_ParseLine (line, argv, &argc, sizeof(argv)/sizeof(argv[0]));
1701 com_err (whoami, code, "parsing line: '%s'", line);
1704 code = cmd_Dispatch (argc, argv);
1705 cmd_FreeArgv (argv);