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 <afsconfig.h>
16 #include <afs/param.h>
20 #include <afs/debug.h>
24 /* These two needed for rxgen output to work */
25 #include <sys/types.h>
32 #define UBIK_LEGACY_CALLITER 1
38 #include <afs/cellconfig.h>
40 #include <afs/com_err.h>
41 #include <afs/afsutil.h>
43 #include <des_prototypes.h>
50 #define CMD_PARSER_AMBIG_FIX 1 /* allow ambiguous aliases */
52 #define KA_SIXHOURS (6*3600)
54 static struct ubik_client *conn;
55 static char cell[MAXKTCREALMLEN] = "";
56 static char whoami[32];
57 static char passwd[BUFSIZ];
58 static char myName[510]; /* almost like whoami save with path and without : */
62 static char **zero_argv;
63 afs_uint32 ka_islocked(char *, char *, afs_uint32 *);
72 code = ka_ExpandCell(0, cell, 0 /*local */ );
74 afs_com_err(whoami, code, "Can't expand cell name");
79 /* These are the command operation procedures. */
82 DumpUser(char *user, char *arock, int showadmin, int showkey, char *inst)
84 char name[MAXKTCNAMELEN];
85 char instance[MAXKTCNAMELEN];
88 char bob[KA_TIMESTR_LEN];
90 struct kaentryinfo tentry;
92 code = ka_ParseLoginName(user, name, instance, 0);
94 afs_com_err(whoami, code, "parsing user's name '%s'", user);
101 ubik_Call(KAM_GetEntry, conn, 0, name, inst, KAMAJORVERSION, &tentry);
103 afs_com_err(whoami, code, "getting information for %s.%s", name, inst);
106 if (tentry.minor_version != KAMINORVERSION)
107 printf("Minor version number mismatch: got %d, expected %d\n",
108 tentry.minor_version, KAMINORVERSION);
109 if (showadmin && !(tentry.flags & KAFADMIN))
111 ka_PrintUserID("\nUser data for ", name, inst, "");
114 #define NEWPREFIX "+"
115 if (tentry.flags & KAFADMIN) {
116 printf("%sADMIN", prefix);
119 if (tentry.flags & KAFNOTGS) {
120 printf("%sNOTGS", prefix);
123 if (tentry.flags & KAFNOCPW) {
124 printf("%sNOCPW", prefix);
127 if (tentry.flags & KAFNOSEAL) {
128 printf("%sNOSEAL", prefix);
131 if (tentry.flags & KAFNEWASSOC) {
132 printf("%sNEWASSOC", prefix);
135 if (tentry.flags & KAFASSOCROOT) {
136 printf("%sASSOCROOT", prefix);
139 if (tentry.flags & KAFASSOC) {
140 printf("%sASSOC", prefix);
143 if (tentry.user_expiration <= now) {
144 printf("%sexpired", prefix);
147 if (strcmp(prefix, NEWPREFIX) == 0)
152 if ((!ka_KeyIsZero((char *)&tentry.key, sizeof(tentry.key))) && (showkey)) {
153 printf(" key (%d):", tentry.key_version);
154 ka_PrintBytes((char *)&tentry.key, sizeof(tentry.key));
156 if (tentry.keyCheckSum == 0)
157 printf(" key version is %d", tentry.key_version);
159 printf(" key (%d) cksum is %u", tentry.key_version,
162 ka_timestr(tentry.change_password_time, bob, KA_TIMESTR_LEN);
163 printf(", last cpw: %s\n", bob);
164 if (!tentry.misc_auth_bytes) {
165 printf(" password will never expire.\n");
167 (" An unlimited number of unsuccessful authentications is permitted.\n");
169 unsigned char misc_stuff[4];
172 temp = tentry.misc_auth_bytes;
174 temp = ntohl(tentry.misc_auth_bytes);
176 unpack_long(temp, misc_stuff);
178 if (!misc_stuff[0]) {
179 printf(" password will never expire.\n");
181 ka_timestr((tentry.change_password_time +
182 misc_stuff[0] * 24 * 60 * 60), bob, KA_TIMESTR_LEN);
183 printf(" password will expire: %s\n", bob);
188 (" An unlimited number of unsuccessful authentications is permitted.\n");
191 (" %d consecutive unsuccessful authentications are permitted.\n",
195 printf(" The lock time for this user is not limited.\n");
197 printf(" The lock time for this user is %4.1f minutes.\n",
198 (float)((unsigned int)misc_stuff[3] << 9) / 60.0);
200 if (!(misc_stuff[1] & KA_ISLOCKED)
201 || !ka_islocked(name, instance, &temp))
202 printf(" User is not locked.\n");
203 else if (temp == (afs_uint32) (-1L))
204 printf(" User is locked forever.\n");
206 ka_timestr(temp, bob, KA_TIMESTR_LEN);
207 printf(" User is locked until %s\n", bob);
213 char exp[KA_TIMESTR_LEN];
214 ka_timestr(tentry.user_expiration, exp, KA_TIMESTR_LEN);
215 if (tentry.user_expiration < now)
216 printf(" DISABLED entry at %s.", exp);
217 else if (tentry.user_expiration == NEVERDATE)
218 printf(" entry never expires.");
220 printf(" entry expires on %s.", exp);
222 printf(" Max ticket lifetime %.2f hours.\n",
223 tentry.max_ticket_lifetime / 3600.0);
224 ka_timestr(tentry.modification_time, bob, KA_TIMESTR_LEN);
225 printf(" last mod on %s by ", bob);
226 ka_PrintUserID("", tentry.modification_user.name,
227 tentry.modification_user.instance, "\n");
228 if ((tentry.reserved3 & 0xffff0000) == 0x12340000) {
229 int short reused = (short)tentry.reserved3;
231 printf(" permit password reuse\n");
233 printf(" don't permit password reuse\n");
240 ListUsers(struct cmd_syndesc *as, void *arock)
245 afs_int32 next_index;
246 int code, all = 0, showa = 0;
247 int showkey = (as->parms[2].items != NULL);
249 if (as->parms[0].items)
251 if (as->parms[1].items) {
255 for (index = 0; 1; index = next_index) {
257 ubik_Call(KAM_ListEntry, conn, 0, index, &next_index, &count,
260 afs_com_err(whoami, code, "calling KAM_ListEntry");
266 printf("next_index (%d) is negative: ", next_index);
267 if (strlen(name.name) == 0)
268 printf("name is zero length: ");
270 DumpUser(name.name, NULL, showa, showkey, name.instance);
272 ka_PrintUserID("", name.name, name.instance, "\n");
279 ExamineUser(struct cmd_syndesc *as, void *arock)
281 int showkey = (as->parms[1].items != NULL);
282 return DumpUser(as->parms[0].items->data, arock, 0, showkey, NULL);
292 handle_errors(int code, /* error code to handle */
293 struct OKerrors OKlist[], /* list of errors & messages that should be ignored */
295 { /* set this if we should retry, clear otherwise */
298 for (i = 0; OKlist[i].code; i++) {
299 if (OKlist[i].code == code) {
300 printf("%s\n", OKlist[i].msg);
301 *persist = 0; /* we're done */
306 printf(" : [%s] %s", afs_error_table_name(code), afs_error_message(code));
309 printf(", wait one second\n");
313 case RX_CALL_TIMEOUT:
314 printf(" (retrying)\n");
319 *persist = 0; /* don't retry these errors */
324 CreateUser(struct cmd_syndesc *as, void *arock)
327 char name[MAXKTCNAMELEN];
328 char instance[MAXKTCNAMELEN];
329 struct ktc_encryptionKey key;
332 struct OKerrors OKlist[2];
335 code = ka_ParseLoginName(as->parms[0].items->data, name, instance, 0);
337 afs_com_err(whoami, code, "parsing user's name '%s'",
338 as->parms[0].items->data);
341 ka_StringToKey(as->parms[1].items->data, cell, &key);
344 code = ubik_Call(KAM_CreateUser, conn, 0, name, instance, key);
347 ka_PrintUserID("Creating user ", name, instance, " ");
348 code = handle_errors(code, OKlist, &persist);
354 DeleteUser(struct cmd_syndesc *as, void *arock)
357 char name[MAXKTCNAMELEN];
358 char instance[MAXKTCNAMELEN];
361 struct OKerrors OKlist[2];
363 code = ka_ParseLoginName(as->parms[0].items->data, name, instance, 0);
365 afs_com_err(whoami, code, "parsing user's name '%s'",
366 as->parms[0].items->data);
371 code = ubik_Call(KAM_DeleteUser, conn, 0, name, instance);
374 ka_PrintUserID("Deleting user ", name, instance, " ");
375 code = handle_errors(code, OKlist, &persist);
381 read_time_interval(char *str, afs_int32 * seconds)
387 str = strncpy(buf, str, sizeof(buf));
388 s = strchr(str, ':');
392 *s++ = '\0'; /* separate hours and minutes */
393 sec = atoi(str) * 3600 + atoi(s) * 60;
400 parse_flags(char *name, char *inst, char *str, afs_int32 * flags)
402 struct kaentryinfo tentry;
408 int addop; /* 1=add bit; 0=remove bit */
412 str = lcstring(bitspec, str, sizeof(bitspec));
414 if (strncmp(str, "0x", 2) == 0) /* 0x => hex */
415 sscanf(str, "0x%lx", (long unsigned int *) &f);
416 else if (*str == '0') /* assume octal */
417 sscanf(str, "%lo", (long unsigned int *) &f);
418 else /* just assume hex */
419 sscanf(str, "%lx", (long unsigned int *) &f);
426 if (strchr("+-", *str))
427 addop = (*str++ == '+');
428 else if (*str == '_') {
434 ubik_Call(KAM_GetEntry, conn, 0, name, inst, KAMAJORVERSION,
437 afs_com_err(whoami, code,
438 "could get current flag value for %s.%s", name, inst);
455 if (strcmp(bit, "admin") == 0)
457 else if (strcmp(bit, "noadmin") == 0)
458 flag = KAFADMIN, addop = !addop;
459 else if (strcmp(bit, "notgs") == 0)
461 else if (strcmp(bit, "tgs") == 0)
462 flag = KAFNOTGS, addop = !addop;
463 else if (strcmp(bit, "noseal") == 0)
465 else if (strcmp(bit, "seal") == 0)
466 flag = KAFNOSEAL, addop = !addop;
467 else if (strcmp(bit, "nocpw") == 0)
469 else if (strcmp(bit, "cpw") == 0)
470 flag = KAFNOCPW, addop = !addop;
471 else if (strcmp(bit, "newassoc") == 0)
473 else if (strcmp(bit, "nonewassoc") == 0)
474 flag = KAFNEWASSOC, addop = !addop;
477 ("Illegal bit name: %s; choices are: [no]admin, [no]tgs, [no]seal, [no]cpw\n",
490 addop = 1; /* get next op */
491 else if ((*str == '-') || (*str == '_'))
494 printf("Illegal combination operator: %c\n", *str);
500 *flags = (f & KAF_SETTABLE_FLAGS) | KAFNORMAL;
504 #define seriouserror(code) ((code <0) || ((code != UNOSERVERS) && (code != UNOQUORUM) && code != UNOTSYNC))
506 /* return MAXLONG if locked forever */
508 ka_islocked(char *name, char *instance, afs_uint32 * when)
518 ubik_CallIter(KAM_LockStatus, conn, UPUBIKONLY, &count, (long) name,
519 (long) instance, (long) &tempwhen, 0, 0, 0,
520 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
522 if (seriouserror(code))
523 afs_com_err(whoami, code, "");
524 } else if (tempwhen) { /* user is locked */
525 if (!*when || tempwhen < *when) {
529 } else /* ! tempwhen ==> user is not locked */
532 } while (code != UNOSERVERS);
538 Unlock(struct cmd_syndesc *as, void *arock)
540 afs_int32 code, rcode = 0;
543 char name[MAXKTCNAMELEN];
544 char instance[MAXKTCNAMELEN];
546 code = ka_ParseLoginName(as->parms[0].items->data, name, instance, 0);
548 afs_com_err(whoami, code, "parsing user's name '%s'",
549 as->parms[0].items->data);
555 code = ubik_CallIter(KAM_Unlock, conn, 0, &count, (long) name, (long) instance,
556 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
557 if (code && (code != UNOSERVERS)) {
559 if (conn && conn->conns[count - 1]
560 && conn->conns[count - 1]->peer) {
561 server = conn->conns[count - 1]->peer->host;
563 afs_com_err(whoami, code,
564 "so %s.%s may still be locked (on server %d.%d.%d.%d)",
565 name, instance, ((server >> 24) & 0xFF),
566 ((server >> 16) & 0xFF), ((server >> 8) & 0xFF),
573 } while (code != UNOSERVERS);
579 SetFields(struct cmd_syndesc *as, void *arock)
582 char name[MAXKTCNAMELEN];
583 char instance[MAXKTCNAMELEN];
586 afs_int32 lifetime = 0;
587 afs_int32 maxAssociates = -1;
588 afs_int32 pwexpiry = 0;
589 afs_int32 was_spare = 0;
590 char misc_auth_bytes[4];
593 code = ka_ParseLoginName(as->parms[0].items->data, name, instance, 0);
595 afs_com_err(whoami, code, "parsing user's name '%s'",
596 as->parms[0].items->data);
600 if (as->parms[1].items) {
601 code = parse_flags(name, instance, as->parms[1].items->data, &flags);
604 ("Illegal flag specification: %s, should be of the form <'='|'+'|'-'|'_'>bitname{<'+'|'-'>bitname}*\n",
605 as->parms[1].items->data);
609 if (as->parms[2].items) {
611 char *s = strncpy(buf, as->parms[2].items->data, sizeof(buf));
612 code = ktime_DateToInt32(s, &expiration);
614 printf("Illegal time format %s: %s\n", as->parms[2].items->data,
615 ktime_GetDateUsage());
618 if (expiration == 0) {
619 fprintf(stderr, "Expiration time must be after (about) 1970.\n");
622 if (expiration < time(0)) {
624 "Warning: expiration being set into the past, account will be disabled.\n");
630 if (as->parms[3].items) {
631 code = read_time_interval(as->parms[3].items->data, &lifetime);
636 /* no point in doing this any sooner than necessary */
637 for (i = 0; i < 4; misc_auth_bytes[i++] = 0);
639 if (as->parms[4].items) {
640 if (util_isint(as->parms[4].items->data))
641 pwexpiry = atoi(as->parms[4].items->data);
644 "Password lifetime specified must be a non-negative decimal integer.\n");
647 if (pwexpiry < 0 || pwexpiry > 254) {
649 "Password lifetime range must be [0..254] days.\n");
650 fprintf(stderr, "Zero represents an unlimited lifetime.\n");
653 misc_auth_bytes[0] = pwexpiry + 1;
657 if (as->parms[5].items) {
659 reuse = (as->parms[5].items->data);
661 if (!strcmp(reuse, "yes")) {
662 misc_auth_bytes[1] = KA_REUSEPW;
663 } else if (strcmp(reuse, "no")) {
665 "must specify \"yes\" or \"no\": \"yes\" assumed\n");
666 misc_auth_bytes[1] = KA_REUSEPW;
668 misc_auth_bytes[1] = KA_NOREUSEPW;
672 if (as->parms[6].items) {
676 if (util_isint(as->parms[6].items->data)
677 && ((nfailures = atoi(as->parms[6].items->data)) < 255)) {
678 misc_auth_bytes[2] = nfailures + 1;
680 fprintf(stderr, "Failure limit must be in [0..254].\n");
681 fprintf(stderr, "Zero represents unlimited login attempts.\n");
686 if (as->parms[7].items) {
687 int locktime, hrs, mins;
691 s = as->parms[7].items->data;
693 sscanf(s, "%d:%d", &hrs, &mins);
695 sscanf(s, "%d", &mins);
697 locktime = hrs * 60 + mins;
698 if (hrs < 0 || hrs > 36 || mins < 0) {
700 "Lockout times must be either minutes or hh:mm.\n");
701 fprintf(stderr, "Lockout times must be less than 36 hours.\n");
703 } else if (locktime > 36 * 60) {
705 "Lockout times must be either minutes or hh:mm.\n");
706 fprintf(stderr, "Lockout times must be less than 36 hours.\n");
708 "Continuing with lock time of exactly 36 hours...\n");
711 locktime = (locktime * 60 + 511) >> 9; /* ceil(l*60/512) */
712 misc_auth_bytes[3] = locktime + 1; /* will be 1 if user said 0 */
715 if (as->parms[8].items) {
716 maxAssociates = atoi(as->parms[6].items->data);
717 if (maxAssociates < 0) {
718 printf("Illegal maximum number of associates\n");
723 was_spare = pack_long(misc_auth_bytes);
725 if (was_spare || flags || expiration || lifetime || (maxAssociates >= 0))
727 ubik_Call(KAM_SetFields, conn, 0, name, instance, flags,
728 expiration, lifetime, maxAssociates, was_spare,
731 printf("Must specify one of the optional parameters\n");
735 afs_com_err(whoami, code, "calling KAM_SetFields for %s.%s", name,
741 StringToKey(struct cmd_syndesc *as, void *arock)
744 char realm[MAXKTCREALMLEN];
745 struct ktc_encryptionKey key;
747 if (as->parms[1].items) {
748 code = ka_ExpandCell(as->parms[1].items->data, realm, 0 /*local */ );
750 afs_com_err(whoami, code,
751 "expanding %s as cell name, attempting to continue",
752 as->parms[1].items->data);
754 ucstring(realm, realm, sizeof(realm));
756 if ((code = DefaultCell()))
758 ucstring(realm, cell, sizeof(realm));
760 ka_StringToKey(as->parms[0].items->data, realm, &key);
762 printf("Converting %s in realm '%s' yields key='",
763 as->parms[0].items->data, realm);
764 ka_PrintBytes((char *)&key, sizeof(key));
767 des_string_to_key(as->parms[0].items->data, ktc_to_cblockptr(&key));
769 printf("Converting %s with the DES string to key yields key='",
770 as->parms[0].items->data);
771 ka_PrintBytes((char *)&key, sizeof(key));
778 SetPassword(struct cmd_syndesc *as, void *arock)
781 char name[MAXKTCNAMELEN];
782 char instance[MAXKTCNAMELEN];
783 char realm[MAXKTCREALMLEN];
784 struct ktc_encryptionKey key;
787 code = ka_ParseLoginName(as->parms[0].items->data, name, instance, realm);
789 afs_com_err(whoami, code, "parsing user's name '%s'",
790 as->parms[0].items->data);
794 if (strlen(realm) == 0)
795 ucstring(realm, cell, sizeof(realm));
797 if (as->parms[1].items && as->parms[2].items) {
798 printf("Can't specify both a password and a key\n");
800 } else if (as->parms[1].items) {
801 (void)init_child(myName);
802 (void)give_to_child(passwd); /* old password */
803 code = password_bad(as->parms[1].items->data);
804 (void)terminate_child();
807 ka_StringToKey(as->parms[1].items->data, realm, &key);
808 } else if (as->parms[2].items) {
809 if (ka_ReadBytes(as->parms[2].items->data, (char *)&key, sizeof(key))
811 printf("Key must be 8 bytes: '%s' was too long\n",
812 as->parms[2].items->data);
816 printf("Must specify new password or key\n");
821 if (as->parms[3].items)
822 sscanf(as->parms[3].items->data, "%d", &kvno);
824 #if defined(AFS_S390_LINUX20_ENV) && !defined(AFS_S390X_LINUX20_ENV)
825 code = ubik_Call(KAM_SetPassword, conn, 0, name, instance, kvno, 0, key);
827 code = ubik_Call(KAM_SetPassword, conn, 0, name, instance, kvno, key);
830 afs_com_err(whoami, code, "so can't set password for %s.%s", name,
835 #define PrintPrincipal(p,n,l) \
836 PrintName((p)->name, (p)->instance, (p)->cell, l, n)
839 PrintName(char *name, char *inst, char *acell, int buflen, char *buf)
842 int left; /* if ConvertBytes stops early */
851 left = ka_ConvertBytes(buf, buflen, name, strlen(name));
855 afs_com_err(whoami, code, "PrintName: principal name was '%s'.'%s'@'%s'",
862 if (nlen + len + 1 >= buflen)
865 left = ka_ConvertBytes(buf + nlen, buflen - nlen, inst, len);
873 char *lcell = ka_LocalCell();
876 if (strcmp(acell, lcell) != 0) {
877 /* only append cell if not the local cell */
878 if (nlen + len + 1 >= buflen)
881 left = ka_ConvertBytes(buf + nlen, buflen - nlen, acell, len);
890 #define PrintedPrincipal(p) PrintedName ((p)->name, (p)->instance, (p)->cell)
892 /* PrintedName - returned a pointer to a static string in which the formated
893 * name has been stored. */
896 PrintedName(char *name, char *inst, char *cell)
898 static char printedName[128];
900 code = PrintName(name, inst, cell, sizeof(printedName), printedName);
904 strncpy(printedName, name, sizeof(printedName));
905 printedName[sizeof(printedName) - 8] = 0;
906 strcat(printedName, "<error>");
912 ListTicket(struct ktc_principal *server, int verbose)
915 struct ktc_token token; /* the token we're printing */
916 struct ktc_principal client;
917 char UserName[sizeof(struct ktc_principal)];
918 char ServerName[sizeof(struct ktc_principal)];
919 afs_int32 now = time(0);
920 char bob[KA_TIMESTR_LEN];
922 /* get the ticket info itself */
923 code = ktc_GetToken(server, &token, sizeof(token), &client);
925 afs_com_err(whoami, code, "failed to get token info for server %s",
926 PrintedPrincipal(server));
929 code = PrintPrincipal(&client, UserName, sizeof(UserName));
932 /* spaces are printed as "\040" */
933 if (UserName[0] == 0)
935 else if (strncmp(UserName, "AFS\\040ID\\040", 13) == 0) {
936 printf("User's (AFS ID %s) tokens", UserName + 13);
937 } else if (strncmp(UserName, "Unix\\040UID\\040", 15) == 0) {
940 printf("User %s's tokens", UserName);
942 code = PrintPrincipal(server, ServerName, sizeof(ServerName));
945 printf(" for %s ", ServerName);
947 if (token.startTime > now) {
948 ka_timestr(token.startTime, bob, KA_TIMESTR_LEN);
949 printf("[>> POSTDATED 'till %s <<]", bob);
952 if (token.endTime <= now)
953 printf("[>> Expired <<]\n");
955 ka_timestr(token.endTime, bob, KA_TIMESTR_LEN);
956 printf("[Expires %s]\n", bob);
959 printf("SessionKey: ");
960 ka_PrintBytes((char *)&token.sessionKey, sizeof(token.sessionKey));
961 printf("\nTicket (kvno = %d, len = %d): ", token.kvno,
963 ka_PrintBytes((char *)token.ticket, token.ticketLen);
970 GetTicket(struct cmd_syndesc *as, void *arock)
973 struct ktc_principal server;
974 struct ktc_token token;
975 afs_int32 life = KA_SIXHOURS;
977 if (as->parms[1].items) {
978 code = read_time_interval(as->parms[1].items->data, &life);
983 ka_ParseLoginName(as->parms[0].items->data, server.name,
984 server.instance, server.cell);
986 afs_com_err(whoami, code, "parsing user's name '%s'",
987 as->parms[0].items->data);
990 if (server.cell[0] == 0) {
991 if ((code = DefaultCell()))
993 strcpy(server.cell, cell);
995 code = ka_ExpandCell(server.cell, server.cell, 0 /*local */ );
997 afs_com_err(whoami, code, "Can't expand cell name");
1002 token.ticketLen = 0; /* in case there are no tokens */
1004 ka_GetServerToken(server.name, server.instance, server.cell, life,
1005 &token, /*new */ 1, /*dosetpag */ 0);
1007 afs_com_err(whoami, code, "getting ticket for %s",
1008 PrintedPrincipal(&server));
1010 code = ListTicket(&server, /*verbose */ 1);
1016 GetPassword(struct cmd_syndesc *as, void *arock)
1019 char name[MAXKTCNAMELEN];
1020 struct ktc_encryptionKey key;
1021 static struct ubik_client *lpbkConn = 0;
1023 /* no instance allowed */
1024 code = ka_ParseLoginName(as->parms[0].items->data, name, 0, 0);
1027 afs_com_err(whoami, code,
1028 "getting %s's password via loopback connection to GetPassword",
1030 /* if we got a timeout, print a clarification, too */
1033 "%s: please note that this command must be run locally on a database server machine.\n",
1038 if (lpbkConn == 0) {
1039 struct rx_connection *conns[2];
1040 struct rx_securityClass *sc;
1041 int si; /* security class index */
1046 sc = rxnull_NewClientSecurityObject();
1047 si = RX_SCINDEX_NULL;
1049 rx_NewConnection(htonl(INADDR_LOOPBACK), htons(AFSCONF_KAUTHPORT),
1050 KA_MAINTENANCE_SERVICE, sc, si);
1052 code = ubik_ClientInit(conns, &lpbkConn);
1056 code = ubik_Call(KAM_GetPassword, lpbkConn, 0, name, &key);
1057 /* Lets close down the ubik_Client connection now */
1058 ubik_ClientDestroy(lpbkConn);
1062 ka_PrintBytes((char *)&key, sizeof(key));
1068 GetRandomKey(struct cmd_syndesc *as, void *arock)
1071 struct ktc_encryptionKey key;
1073 code = ubik_Call(KAM_GetRandomKey, conn, 0, &key);
1075 afs_com_err(whoami, code, "so can't get random key");
1079 ka_PrintBytes((char *)&key, sizeof(key));
1081 for (i = 0; i < sizeof(key); i++) {
1082 printf("%.2x", ((char *)&key)[i] & 0xff);
1094 Statistics(struct cmd_syndesc *as, void *arock)
1100 char bob[KA_TIMESTR_LEN];
1103 ubik_Call(KAM_GetStats, conn, 0, KAMAJORVERSION, &admins, &statics,
1106 printf("call to GetStats failed: %s\n", ka_ErrorString(code));
1109 if (statics.minor_version != KAMINORVERSION)
1110 printf("Minor version number mismatch: got %d, expected %d\n",
1111 statics.minor_version, KAMINORVERSION);
1112 printf("%d allocs, %d frees, %d password changes\n", statics.allocs,
1113 statics.frees, statics.cpws);
1114 printf("Hash table utilization = %f%%\n",
1115 (double)dynamics.hashTableUtilization / 100.0);
1116 ka_timestr(dynamics.start_time, bob, KA_TIMESTR_LEN);
1117 printf("From host %lx started at %s:\n",
1118 afs_printable_uint32_lu(dynamics.host), bob);
1120 #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)
1121 print_stat(Authenticate);
1122 print_stat(ChangePassword);
1123 print_stat(GetTicket);
1124 print_stat(CreateUser);
1125 print_stat(SetPassword);
1126 print_stat(SetFields);
1127 print_stat(DeleteUser);
1128 print_stat(GetEntry);
1129 print_stat(ListEntry);
1130 print_stat(GetStats);
1131 print_stat(GetPassword);
1132 print_stat(GetRandomKey);
1134 print_stat(UAuthenticate);
1135 print_stat(UGetTicket);
1137 #if (KAMAJORVERSION>5)
1138 print cpu stats printf("%d string checks\n", dynamics.string_checks);
1140 printf("Used %.3f seconds of CPU time.\n",
1141 dynamics.string_checks / 1000.0);
1143 printf("%d admin accounts\n", admins);
1148 DebugInfo(struct cmd_syndesc *as, void *arock)
1151 struct ka_debugInfo info;
1155 char bob[KA_TIMESTR_LEN];
1158 if (as->parms[0].items) {
1159 struct ubik_client *iConn;
1161 ka_SingleServerConn(cell, as->parms[0].items->data,
1162 KA_MAINTENANCE_SERVICE, 0, &iConn);
1164 struct afsconf_cell cellinfo;
1166 afs_com_err(whoami, code, "couldn't find host %s in cell %s",
1167 as->parms[0].items->data, cell);
1168 code = ka_GetServers(cell, &cellinfo);
1170 afs_com_err(whoami, code, "getting servers in cell %s", cell);
1172 printf("Servers in cell %s, are:\n", cell);
1173 for (i = 0; i < cellinfo.numServers; i++)
1174 printf(" %s\n", cellinfo.hostName[i]);
1178 code = ubik_Call(KAM_Debug, iConn, 0, KAMAJORVERSION, 0, &info);
1179 ubik_ClientDestroy(iConn);
1181 code = ubik_Call(KAM_Debug, conn, 0, KAMAJORVERSION, 0, &info);
1184 afs_com_err(whoami, code, "call to Debug failed");
1189 if (info.minorVersion != KAMINORVERSION)
1190 printf("Minor version number mismatch: got %d, expected %d\n",
1191 info.minorVersion, KAMINORVERSION);
1194 #if (KAMAJORVERSION>5)
1201 timeOffset = -timeOffset;
1202 if (timeOffset > 60) {
1204 ("WARNING: Large server client clock skew: %d seconds. Call itself took %d seconds.\n",
1205 timeOffset, now - start);
1207 ka_timestr(info.startTime, bob, KA_TIMESTR_LEN);
1208 printf("From host %lx started %sat %s:\n",
1209 afs_printable_uint32_lu(info.host),
1210 (info.noAuth ? "w/o authorization " : ""), bob);
1211 ka_timestr(info.lastTrans, bob, KA_TIMESTR_LEN);
1212 printf("Last trans was %s at %s\n", info.lastOperation, bob);
1213 ka_timestr(info.dbHeaderRead, bob, KA_TIMESTR_LEN);
1214 printf("Header last read %s.\n", bob);
1215 printf("db version=%d, keyVersion=%d, key cache version=%d\n",
1216 info.dbVersion, info.dbSpecialKeysVersion, info.kcVersion);
1217 printf("db ptrs: free %d, eof %d, kvno %d.\n", info.dbFreePtr,
1218 info.dbEofPtr, info.dbKvnoPtr);
1219 ka_timestr(info.nextAutoCPW, bob, KA_TIMESTR_LEN);
1220 printf("Next autoCPW at %s or in %d updates.\n", bob,
1221 info.updatesRemaining);
1222 if (info.cheader_lock || info.keycache_lock)
1223 printf("locks: cheader %08lx, keycache %08lx\n",
1224 afs_printable_uint32_lu(info.cheader_lock),
1225 afs_printable_uint32_lu(info.keycache_lock));
1226 printf("Last authentication for %s, last admin user was %s\n",
1227 info.lastAuth, info.lastAdmin);
1228 printf("Last TGS op was a %s ticket was for %s\n", info.lastTGSServer,
1230 printf("Last UDP TGS was a %s ticket for %s. UDP Authenticate for %s\n",
1231 info.lastUTGSServer, info.lastUTGS, info.lastUAuth);
1232 printf("key cache size %d, used %d.\n", info.kcSize, info.kcUsed);
1233 if (info.kcUsed > KADEBUGKCINFOSIZE) {
1234 printf("insufficient room to return all key cache entries!\n");
1235 info.kcUsed = KADEBUGKCINFOSIZE;
1237 for (i = 0; i < info.kcUsed; i++)
1238 ka_timestr(info.kcInfo[i].used, bob, KA_TIMESTR_LEN);
1239 printf("%32s %c %2x(%2x) used %s\n", info.kcInfo[i].principal,
1240 (info.kcInfo[i].primary ? '*' : ' '), info.kcInfo[i].kvno,
1241 info.kcInfo[i].keycksum, bob);
1246 Interactive(struct cmd_syndesc *as, void *arock)
1253 Quit(struct cmd_syndesc *as, void *arock)
1260 MyAfterProc(struct cmd_syndesc *as, void *arock)
1262 if (!strcmp(as->name, "help"))
1265 /* Determine if we need to destory the ubik connection.
1266 * Closing it avoids resends of packets.
1269 ubik_ClientDestroy(conn);
1276 int init = 0, noauth;
1277 char name[MAXKTCNAMELEN];
1278 char instance[MAXKTCNAMELEN];
1279 char newCell[MAXKTCREALMLEN];
1280 afs_int32 serverList[MAXSERVERS];
1283 NoAuth(struct cmd_syndesc *as, void *arock)
1290 MyBeforeProc(struct cmd_syndesc *as, void *arock)
1292 struct ktc_encryptionKey key;
1293 struct ktc_principal auth_server, client;
1294 struct ktc_token auth_token;
1295 char realm[MAXKTCREALMLEN];
1297 struct ktc_token token, *pToken;
1298 int i, acode, code = 0;
1301 char *ws = strrchr(as->a0name, '/');
1303 ws++; /* skip everything before the "/" */
1306 if (strlen(ws) > 0) {
1307 strncpy(whoami, ws, sizeof(whoami));
1308 if (strlen(whoami) + 1 >= sizeof(whoami))
1309 strcpy(whoami, "kas:");
1311 strcat(whoami, ":");
1314 /* append sub-command name */
1315 strncat(whoami, as->name, sizeof(whoami) - strlen(whoami) - 1);
1318 if (as->parms[12].name == 0)
1321 assert(as->parms[13].name && as->parms[14].name && as->parms[15].name
1322 && as->parms[16].name);
1324 /* MyAfterProc() destroys the conn, but just to be sure */
1326 code = ubik_ClientDestroy(conn);
1330 if (!init || as->parms[12].items || as->parms[13].items
1331 || as->parms[14].items || as->parms[15].items
1332 || as->parms[16].items) {
1333 strcpy(instance, "");
1334 strcpy(newCell, "");
1336 if (as->parms[12].items) { /* -admin_username */
1338 ka_ParseLoginName(as->parms[12].items->data, name, instance,
1341 afs_com_err(whoami, code, "parsing user's name '%s'",
1342 as->parms[12].items->data);
1347 DWORD len = MAXKTCNAMELEN;
1348 if (!GetUserName((LPTSTR) name, &len)) {
1349 printf("Can't get user name \n");
1353 /* No explicit name provided: use Unix uid. */
1354 struct passwd *pw = getpwuid(getuid());
1356 printf("Can't figure out your name from your user id.\n");
1359 strncpy(name, pw->pw_name, sizeof(name));
1363 if (as->parms[14].items) { /* -cell */
1364 if (strlen(newCell) > 0) {
1365 printf("Duplicate cell specification not allowed\n");
1367 strncpy(newCell, as->parms[14].items->data, sizeof(newCell));
1370 code = ka_ExpandCell(newCell, newCell, 0 /*local */ );
1372 afs_com_err(whoami, code, "Can't expand cell name");
1375 strcpy(cell, newCell);
1377 if (as->parms[15].items) { /* -servers */
1378 struct cmd_item *ip;
1379 char *ap[MAXSERVERS + 2];
1383 for (ip = as->parms[15].items, i = 2; ip; ip = ip->next, i++)
1385 code = ubik_ParseClientList(i, ap, serverList);
1387 afs_com_err(whoami, code, "could not parse server list");
1390 ka_ExplicitCell(cell, serverList);
1393 noauth = (as->parms[16].items ? 1 : 0); /* -noauth */
1398 token.ticketLen = 0; /* in case there are no tokens */
1399 if (!noauth) { /* Will prompt for a password */
1400 /* first see if there's already an admin ticket */
1402 ka_GetAdminToken(0, 0, cell, 0, KA_SIXHOURS, &token,
1404 if (code) { /* if not then get key and try again */
1405 if (as->parms[13].items) { /* if password specified */
1406 strncpy(passwd, as->parms[13].items->data, sizeof(passwd));
1407 memset(as->parms[13].items->data, 0,
1408 strlen(as->parms[13].items->data));
1410 char msg[MAXKTCNAMELEN + 50];
1411 if (as->parms[12].items)
1412 sprintf(msg, "Administrator's (%s) Password: ", name);
1414 sprintf(msg, "Password for %s: ", name);
1415 code = read_pw_string(passwd, sizeof(passwd), msg, 0);
1418 else if (strlen(passwd) == 0)
1419 code = KANULLPASSWORD;
1421 afs_com_err(whoami, code, "reading password");
1425 ka_StringToKey(passwd, cell, &key);
1427 ka_GetAdminToken(name, instance, cell, &key, KA_SIXHOURS,
1428 &token, 0 /* !new */ );
1429 if (code == KABADREQUEST) {
1430 des_string_to_key(passwd, ktc_to_cblockptr(&key));
1432 ka_GetAdminToken(name, instance, cell, &key, KA_SIXHOURS,
1433 &token, 0 /* !new */ );
1435 if ((code == KABADREQUEST) && (strlen(passwd) > 8)) {
1436 /* try with only the first 8 characters incase they set
1437 * their password with an old style passwd program. */
1439 ka_StringToKey(passwd, cell, &key);
1441 ka_GetAdminToken(name, instance, cell, &key, KA_SIXHOURS,
1442 &token, 0 /* !new */ );
1445 "Warning: you have typed a password longer than 8 characters, but only the\n");
1447 "first 8 characters were actually significant. If you change your password\n");
1449 "again this warning message will go away.\n");
1456 reason = "password was incorrect";
1459 reason = "Authentication Server was unavailable";
1462 reason = (char *)afs_error_message(code);
1465 "%s: Auth. as %s to AuthServer failed: %s\nProceeding w/o authentication\n",
1466 whoami, PrintedName(name, instance, cell), reason);
1468 /* get an Authentication token while were at it. */
1469 if (ka_CellToRealm(cell, realm, 0) != 0)
1471 strcpy(auth_server.name, KA_TGS_NAME);
1472 strcpy(auth_server.instance, realm);
1473 strcpy(auth_server.cell, cell);
1475 (&auth_server, &auth_token, sizeof(struct ktc_token),
1478 ka_GetAuthToken(name, instance, cell, &key,
1479 MAXKTCTICKETLIFETIME, (afs_int32 *) 0
1480 /*Don't need pwd expiration info here */
1482 if (acode && (acode != code)) /* codes are usually the same */
1483 afs_com_err(whoami, code,
1484 "getting Authentication token for %s",
1485 PrintedName(name, instance, cell));
1487 memset(&key, 0, sizeof(key));
1491 pToken = ((token.ticketLen == 0) ? 0 : &token);
1492 code = ka_AuthServerConn(cell, KA_MAINTENANCE_SERVICE, pToken, &conn);
1493 if (code && pToken) {
1494 afs_com_err(whoami, code,
1495 "connecting to AuthServer: now trying w/o authentication");
1496 code = ka_AuthServerConn(cell, KA_MAINTENANCE_SERVICE, 0, &conn);
1498 afs_com_err(whoami, code,
1499 "making unauthenticated connection to AuthServer");
1502 afs_com_err(whoami, code,
1503 "Couldn't establish connection to Authentication Server");
1507 /* now default unspecified password by prompting from terminal */
1508 if (as->nParms >= 12)
1509 for (i = 0; i < 12; i++)
1510 if (as->parms[i].name && (as->parms[i].items == 0)) {
1511 char *p = as->parms[i].name; /* parameter name */
1512 int l = strlen(p); /* length of name */
1513 /* does parameter end in "password" */
1514 if (strcmp(p + (l - 8), "password") == 0) {
1516 char password[BUFSIZ];
1517 struct cmd_item *ip;
1521 code = read_pw_string(password, sizeof(password), msg, 1);
1524 else if (strlen(password) == 0)
1525 code = KANULLPASSWORD;
1527 afs_com_err(whoami, code, "prompting for %s", p + 1);
1530 ip = (struct cmd_item *)malloc(sizeof(struct cmd_item));
1531 ip->data = (char *)malloc(strlen(password) + 1);
1533 strcpy(ip->data, password);
1534 as->parms[i].items = ip;
1537 if (!conn) { /* if all else fails... */
1538 code = NoAuth(0, 0); /* get unauthenticated conn */
1545 /* These are some helpful command that deal with the cache managers tokens. */
1548 ForgetTicket(struct cmd_syndesc *as, void *arock)
1553 struct ktc_principal server;
1555 if (as->parms[0].items) {
1556 char *name = as->parms[0].items->data;
1558 ka_ParseLoginName(name, server.name, server.instance,
1561 afs_com_err(whoami, code, "couldn't interpret name '%s'", name);
1564 if (server.cell[0] == 0) {
1565 if (code = DefaultCell())
1567 strcpy(server.cell, cell);
1569 code = ka_ExpandCell(server.cell, server.cell, 0 /*local */ );
1571 afs_com_err(whoami, code, "Can't expand cell name");
1575 code = ktc_ForgetToken(&server);
1577 afs_com_err(whoami, code, "couldn't remove tokens for %s",
1578 PrintedPrincipal(&server));
1582 if (!as->parms[1].items) {
1583 fprintf(stderr, "Must specify server name or -all\n");
1586 code = ktc_ForgetAllTokens();
1588 afs_com_err(whoami, code, "couldn't delete all tokens");
1593 code = ktc_ForgetAllTokens();
1595 afs_com_err(whoami, code, "couldn't delete all tokens");
1602 ListTickets(struct cmd_syndesc *as, void *arock)
1605 int index, newIndex;
1606 struct ktc_principal server;
1609 if (as->parms[1].items)
1611 if (as->parms[0].items) {
1612 char *name = as->parms[0].items->data;
1614 ka_ParseLoginName(name, server.name, server.instance,
1617 afs_com_err(whoami, code, "couldn't interpret name '%s'", name);
1620 if (server.cell[0] == 0) {
1621 if ((code = DefaultCell()))
1623 strcpy(server.cell, cell);
1625 code = ka_ExpandCell(server.cell, server.cell, 0 /*local */ );
1627 afs_com_err(whoami, code, "Can't expand cell name");
1631 code = ListTicket(&server, verbose);
1633 for (index = 0;; index = newIndex) {
1634 code = ktc_ListTokens(index, &newIndex, &server);
1636 if (code == KTC_NOENT)
1637 code = 0; /* end of list */
1640 code = ListTicket(&server, verbose);
1646 add_std_args(register struct cmd_syndesc *ts)
1649 /* 12 */ cmd_AddParm(ts, "-admin_username", CMD_SINGLE, CMD_OPTIONAL,
1650 "admin principal to use for authentication");
1651 /* 13 */ cmd_AddParm(ts, "-password_for_admin", CMD_SINGLE, CMD_OPTIONAL,
1653 /* 14 */ cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cell name");
1654 /* 15 */ cmd_AddParm(ts, "-servers", CMD_LIST, CMD_OPTIONAL,
1655 "explicit list of authentication servers");
1656 /* 16 */ cmd_AddParm(ts, "-noauth", CMD_FLAG, CMD_OPTIONAL,
1657 "don't authenticate");
1661 ka_AdminInteractive(int cmd_argc, char *cmd_argv[])
1664 register struct cmd_syndesc *ts;
1670 strncpy(myName, *cmd_argv, 509);
1672 cmd_SetBeforeProc(MyBeforeProc, NULL);
1673 cmd_SetAfterProc(MyAfterProc, NULL);
1675 ts = cmd_CreateSyntax("interactive", Interactive, NULL,
1676 "enter interactive mode");
1679 ts = cmd_CreateSyntax("noauthentication", NoAuth, NULL,
1680 "connect to AuthServer w/o using token");
1682 ts = cmd_CreateSyntax("list", ListUsers, NULL,
1683 "list all users in database");
1684 cmd_AddParm(ts, "-long", CMD_FLAG, CMD_OPTIONAL,
1685 "show detailed info about each user");
1686 cmd_AddParm(ts, "-showadmin", CMD_FLAG, CMD_OPTIONAL,
1687 "show all cell administrators");
1688 cmd_AddParm(ts, "-showkey", CMD_FLAG, CMD_OPTIONAL,
1689 "show the user's actual key rather than the checksum");
1691 cmd_CreateAlias(ts, "ls");
1693 ts = cmd_CreateSyntax("examine", ExamineUser, NULL,
1694 "examine the entry for a user");
1695 cmd_AddParm(ts, "-name", CMD_SINGLE, 0, "name of user");
1696 cmd_AddParm(ts, "-showkey", CMD_FLAG, CMD_OPTIONAL,
1697 "show the user's actual key rather than the checksum");
1700 ts = cmd_CreateSyntax("create", CreateUser, NULL,
1701 "create an entry for a user");
1702 cmd_AddParm(ts, "-name", CMD_SINGLE, 0, "name of user");
1703 cmd_AddParm(ts, "-initial_password", CMD_SINGLE, CMD_OPTIONAL,
1704 "initial password");
1707 ts = cmd_CreateSyntax("delete", DeleteUser, NULL, "delete a user");
1708 cmd_AddParm(ts, "-name", CMD_SINGLE, 0, "name of user");
1710 cmd_CreateAlias(ts, "rm");
1712 ts = cmd_CreateSyntax("setfields", SetFields, NULL,
1713 "set various fields in a user's entry");
1714 cmd_AddParm(ts, "-name", CMD_SINGLE, 0, "name of user");
1715 cmd_AddParm(ts, "-flags", CMD_SINGLE, CMD_OPTIONAL,
1716 "hex flag value or flag name expression");
1717 cmd_AddParm(ts, "-expiration", CMD_SINGLE, CMD_OPTIONAL,
1718 "date of account expiration");
1719 cmd_AddParm(ts, "-lifetime", CMD_SINGLE, CMD_OPTIONAL,
1720 "maximum ticket lifetime");
1721 cmd_AddParm(ts, "-pwexpires", CMD_SINGLE, CMD_OPTIONAL,
1722 "number days password is valid ([0..254])");
1723 cmd_AddParm(ts, "-reuse", CMD_SINGLE, CMD_OPTIONAL,
1724 "permit password reuse (yes/no)");
1725 cmd_AddParm(ts, "-attempts", CMD_SINGLE, CMD_OPTIONAL,
1726 "maximum successive failed login tries ([0..254])");
1727 cmd_AddParm(ts, "-locktime", CMD_SINGLE, CMD_OPTIONAL,
1728 "failure penalty [hh:mm or minutes]");
1730 cmd_AddParm(ts, "-associates", CMD_SINGLE, CMD_OPTIONAL,
1731 "maximum associate instances");
1734 cmd_CreateAlias(ts, "sf");
1737 ts = cmd_CreateSyntax("unlock", Unlock, NULL,
1738 "Enable authentication ID after max failed attempts exceeded");
1739 cmd_AddParm(ts, "-name", CMD_SINGLE, 0, "authentication ID");
1743 ts = cmd_CreateSyntax("stringtokey", StringToKey, NULL,
1744 "convert a string to a key");
1745 cmd_AddParm(ts, "-string", CMD_SINGLE, 0, "password string");
1746 cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cell name");
1748 ts = cmd_CreateSyntax("setpassword", SetPassword, NULL,
1749 "set a user's password");
1750 cmd_AddParm(ts, "-name", CMD_SINGLE, 0, "name of user");
1751 cmd_AddParm(ts, "-new_password", CMD_SINGLE, CMD_OPTIONAL,
1754 cmd_AddParm(ts, "-kvno", CMD_SINGLE, CMD_OPTIONAL, "key version number");
1756 cmd_CreateAlias(ts, "sp");
1757 #ifdef CMD_PARSER_AMBIG_FIX
1758 cmd_CreateAlias(ts, "setpasswd");
1761 /* set a user's key */
1762 ts = cmd_CreateSyntax("setkey", SetPassword, NULL, (char *)CMD_HIDDEN);
1763 cmd_AddParm(ts, "-name", CMD_SINGLE, 0, "name of user");
1765 cmd_AddParm(ts, "-new_key", CMD_SINGLE, 0, "eight byte new key");
1767 cmd_AddParm(ts, "-kvno", CMD_SINGLE, CMD_OPTIONAL, "key version number");
1770 /* get a user's password */
1771 ts = cmd_CreateSyntax("getpassword", GetPassword, NULL, (char *)CMD_HIDDEN);
1772 cmd_AddParm(ts, "-name", CMD_SINGLE, 0, "name of user");
1773 /* don't take standard args */
1774 /* add_std_args (ts); */
1775 #ifdef CMD_PARSER_AMBIG_FIX
1776 cmd_CreateAlias(ts, "getpasswd");
1779 /* get a random key */
1780 ts = cmd_CreateSyntax("getrandomkey", GetRandomKey, NULL,
1781 (char *)CMD_HIDDEN);
1784 /* get a ticket for a specific server */
1785 ts = cmd_CreateSyntax("getticket", GetTicket, NULL, (char *)CMD_HIDDEN);
1786 cmd_AddParm(ts, "-name", CMD_SINGLE, 0, "name of server");
1787 cmd_AddParm(ts, "-lifetime", CMD_SINGLE, CMD_OPTIONAL, "ticket lifetime");
1790 ts = cmd_CreateSyntax("statistics", Statistics, NULL,
1791 "show statistics for AuthServer");
1794 /* show debugging info from AuthServer */
1795 ts = cmd_CreateSyntax("debuginfo", DebugInfo, NULL, (char *)CMD_HIDDEN);
1796 cmd_AddParm(ts, "-hostname", CMD_SINGLE, CMD_OPTIONAL,
1797 "authentication server host name");
1800 ts = cmd_CreateSyntax("forgetticket", ForgetTicket, NULL,
1801 "delete user's tickets");
1803 cmd_AddParm(ts, "-name", CMD_SINGLE, (CMD_OPTIONAL | CMD_HIDE),
1806 cmd_AddParm(ts, "-all", CMD_FLAG, CMD_OPTIONAL, "delete all tickets");
1808 ts = cmd_CreateSyntax("listtickets", ListTickets, NULL,
1809 "show all cache manager tickets");
1810 cmd_AddParm(ts, "-name", CMD_SINGLE, CMD_OPTIONAL, "name of server");
1811 cmd_AddParm(ts, "-long", CMD_FLAG, CMD_OPTIONAL,
1812 "show session key and ticket");
1814 ts = cmd_CreateSyntax("quit", Quit, NULL, "exit program");
1817 conn = 0; /* no connection yet */
1818 zero_argc = cmd_argc;
1819 zero_argv = cmd_argv;
1821 strcpy(whoami, "kas");
1823 if ((code = cmd_Dispatch(cmd_argc, cmd_argv))) {
1832 s = fgets(line, sizeof(line), stdin);
1834 return 0; /* EOF on input */
1835 for (i = strlen(line) - 1; i >= 0 && isspace(line[i]); i--)
1838 continue; /* blank line */
1841 cmd_ParseLine(line, argv, &argc, sizeof(argv) / sizeof(argv[0]));
1843 afs_com_err(whoami, code, "parsing line: '%s'", line);
1846 code = cmd_Dispatch(argc, argv);