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>
31 #define UBIK_LEGACY_CALLITER 1
37 #include <afs/cellconfig.h>
39 #include <afs/com_err.h>
40 #include <afs/afsutil.h>
46 #define CMD_PARSER_AMBIG_FIX 1 /* allow ambiguous aliases */
48 #define KA_SIXHOURS (6*3600)
50 static struct ubik_client *conn;
51 static char cell[MAXKTCREALMLEN] = "";
52 static char whoami[32];
53 static char passwd[BUFSIZ];
54 static char myName[510]; /* almost like whoami save with path and without : */
58 static char **zero_argv;
59 afs_uint32 ka_islocked();
68 code = ka_ExpandCell(0, cell, 0 /*local */ );
70 afs_com_err(whoami, code, "Can't expand cell name");
75 /* These are the command operation procedures. */
78 DumpUser(char *user, char *arock, int showadmin, int showkey, char *inst)
80 char name[MAXKTCNAMELEN];
81 char instance[MAXKTCNAMELEN];
84 char bob[KA_TIMESTR_LEN];
86 struct kaentryinfo tentry;
88 code = ka_ParseLoginName(user, name, instance, 0);
90 afs_com_err(whoami, code, "parsing user's name '%s'", user);
97 ubik_Call(KAM_GetEntry, conn, 0, name, inst, KAMAJORVERSION, &tentry);
99 afs_com_err(whoami, code, "getting information for %s.%s", name, inst);
102 if (tentry.minor_version != KAMINORVERSION)
103 printf("Minor version number mismatch: got %d, expected %d\n",
104 tentry.minor_version, KAMINORVERSION);
105 if (showadmin && !(tentry.flags & KAFADMIN))
107 ka_PrintUserID("\nUser data for ", name, inst, "");
110 #define NEWPREFIX "+"
111 if (tentry.flags & KAFADMIN) {
112 printf("%sADMIN", prefix);
115 if (tentry.flags & KAFNOTGS) {
116 printf("%sNOTGS", prefix);
119 if (tentry.flags & KAFNOCPW) {
120 printf("%sNOCPW", prefix);
123 if (tentry.flags & KAFNOSEAL) {
124 printf("%sNOSEAL", prefix);
127 if (tentry.flags & KAFNEWASSOC) {
128 printf("%sNEWASSOC", prefix);
131 if (tentry.flags & KAFASSOCROOT) {
132 printf("%sASSOCROOT", prefix);
135 if (tentry.flags & KAFASSOC) {
136 printf("%sASSOC", prefix);
139 if (tentry.user_expiration <= now) {
140 printf("%sexpired", prefix);
143 if (strcmp(prefix, NEWPREFIX) == 0)
148 if ((!ka_KeyIsZero((char *)&tentry.key, sizeof(tentry.key))) && (showkey)) {
149 printf(" key (%d):", tentry.key_version);
150 ka_PrintBytes((char *)&tentry.key, sizeof(tentry.key));
152 if (tentry.keyCheckSum == 0)
153 printf(" key version is %d", tentry.key_version);
155 printf(" key (%d) cksum is %u", tentry.key_version,
158 ka_timestr(tentry.change_password_time, bob, KA_TIMESTR_LEN);
159 printf(", last cpw: %s\n", bob);
160 if (!tentry.misc_auth_bytes) {
161 printf(" password will never expire.\n");
163 (" An unlimited number of unsuccessful authentications is permitted.\n");
165 unsigned char misc_stuff[4];
168 temp = tentry.misc_auth_bytes;
170 temp = ntohl(tentry.misc_auth_bytes);
172 unpack_long(temp, misc_stuff);
174 if (!misc_stuff[0]) {
175 printf(" password will never expire.\n");
177 ka_timestr((tentry.change_password_time +
178 misc_stuff[0] * 24 * 60 * 60), bob, KA_TIMESTR_LEN);
179 printf(" password will expire: %s\n", bob);
184 (" An unlimited number of unsuccessful authentications is permitted.\n");
187 (" %d consecutive unsuccessful authentications are permitted.\n",
191 printf(" The lock time for this user is not limited.\n");
193 printf(" The lock time for this user is %4.1f minutes.\n",
194 (float)((unsigned int)misc_stuff[3] << 9) / 60.0);
196 if (!(misc_stuff[1] & KA_ISLOCKED)
197 || !ka_islocked(name, instance, &temp))
198 printf(" User is not locked.\n");
199 else if (temp == (afs_uint32) (-1L))
200 printf(" User is locked forever.\n");
202 ka_timestr(temp, bob, KA_TIMESTR_LEN);
203 printf(" User is locked until %s\n", bob);
209 char exp[KA_TIMESTR_LEN];
210 ka_timestr(tentry.user_expiration, exp, KA_TIMESTR_LEN);
211 if (tentry.user_expiration < now)
212 printf(" DISABLED entry at %s.", exp);
213 else if (tentry.user_expiration == NEVERDATE)
214 printf(" entry never expires.");
216 printf(" entry expires on %s.", exp);
218 printf(" Max ticket lifetime %.2f hours.\n",
219 tentry.max_ticket_lifetime / 3600.0);
220 ka_timestr(tentry.modification_time, bob, KA_TIMESTR_LEN);
221 printf(" last mod on %s by ", bob);
222 ka_PrintUserID("", tentry.modification_user.name,
223 tentry.modification_user.instance, "\n");
224 if ((tentry.reserved3 & 0xffff0000) == 0x12340000) {
225 int short reused = (short)tentry.reserved3;
227 printf(" permit password reuse\n");
229 printf(" don't permit password reuse\n");
236 ListUsers(struct cmd_syndesc *as, void *arock)
241 afs_int32 next_index;
242 int code, all = 0, showa = 0;
243 int showkey = (as->parms[2].items != NULL);
245 if (as->parms[0].items)
247 if (as->parms[1].items) {
251 for (index = 0; 1; index = next_index) {
253 ubik_Call(KAM_ListEntry, conn, 0, index, &next_index, &count,
256 afs_com_err(whoami, code, "calling KAM_ListEntry");
262 printf("next_index (%d) is negative: ", next_index);
263 if (strlen(name.name) == 0)
264 printf("name is zero length: ");
266 DumpUser(name.name, NULL, showa, showkey, name.instance);
268 ka_PrintUserID("", name.name, name.instance, "\n");
275 ExamineUser(struct cmd_syndesc *as, void *arock)
277 int showkey = (as->parms[1].items != NULL);
278 return DumpUser(as->parms[0].items->data, arock, 0, showkey, NULL);
288 handle_errors(int code, /* error code to handle */
289 struct OKerrors OKlist[], /* list of errors & messages that should be ignored */
291 { /* set this if we should retry, clear otherwise */
294 for (i = 0; OKlist[i].code; i++) {
295 if (OKlist[i].code == code) {
296 printf("%s\n", OKlist[i].msg);
297 *persist = 0; /* we're done */
302 printf(" : [%s] %s", afs_error_table_name(code), afs_error_message(code));
305 printf(", wait one second\n");
309 case RX_CALL_TIMEOUT:
310 printf(" (retrying)\n");
315 *persist = 0; /* don't retry these errors */
320 CreateUser(struct cmd_syndesc *as, void *arock)
323 char name[MAXKTCNAMELEN];
324 char instance[MAXKTCNAMELEN];
325 struct ktc_encryptionKey key;
328 struct OKerrors OKlist[2];
331 code = ka_ParseLoginName(as->parms[0].items->data, name, instance, 0);
333 afs_com_err(whoami, code, "parsing user's name '%s'",
334 as->parms[0].items->data);
337 ka_StringToKey(as->parms[1].items->data, cell, &key);
340 code = ubik_Call(KAM_CreateUser, conn, 0, name, instance, key);
343 ka_PrintUserID("Creating user ", name, instance, " ");
344 code = handle_errors(code, OKlist, &persist);
350 DeleteUser(struct cmd_syndesc *as, void *arock)
353 char name[MAXKTCNAMELEN];
354 char instance[MAXKTCNAMELEN];
357 struct OKerrors OKlist[2];
359 code = ka_ParseLoginName(as->parms[0].items->data, name, instance, 0);
361 afs_com_err(whoami, code, "parsing user's name '%s'",
362 as->parms[0].items->data);
367 code = ubik_Call(KAM_DeleteUser, conn, 0, name, instance);
370 ka_PrintUserID("Deleting user ", name, instance, " ");
371 code = handle_errors(code, OKlist, &persist);
377 read_time_interval(char *str, afs_int32 * seconds)
383 str = strncpy(buf, str, sizeof(buf));
384 s = strchr(str, ':');
388 *s++ = '\0'; /* separate hours and minutes */
389 sec = atoi(str) * 3600 + atoi(s) * 60;
396 parse_flags(char *name, char *inst, char *str, afs_int32 * flags)
398 struct kaentryinfo tentry;
404 int addop; /* 1=add bit; 0=remove bit */
408 str = lcstring(bitspec, str, sizeof(bitspec));
410 if (strncmp(str, "0x", 2) == 0) /* 0x => hex */
411 sscanf(str, "0x%lx", &f);
412 else if (*str == '0') /* assume octal */
413 sscanf(str, "%lo", &f);
414 else /* just assume hex */
415 sscanf(str, "%lx", &f);
422 if (strchr("+-", *str))
423 addop = (*str++ == '+');
424 else if (*str == '_') {
430 ubik_Call(KAM_GetEntry, conn, 0, name, inst, KAMAJORVERSION,
433 afs_com_err(whoami, code,
434 "could get current flag value for %s.%s", name, inst);
451 if (strcmp(bit, "admin") == 0)
453 else if (strcmp(bit, "noadmin") == 0)
454 flag = KAFADMIN, addop = !addop;
455 else if (strcmp(bit, "notgs") == 0)
457 else if (strcmp(bit, "tgs") == 0)
458 flag = KAFNOTGS, addop = !addop;
459 else if (strcmp(bit, "noseal") == 0)
461 else if (strcmp(bit, "seal") == 0)
462 flag = KAFNOSEAL, addop = !addop;
463 else if (strcmp(bit, "nocpw") == 0)
465 else if (strcmp(bit, "cpw") == 0)
466 flag = KAFNOCPW, addop = !addop;
467 else if (strcmp(bit, "newassoc") == 0)
469 else if (strcmp(bit, "nonewassoc") == 0)
470 flag = KAFNEWASSOC, addop = !addop;
473 ("Illegal bit name: %s; choices are: [no]admin, [no]tgs, [no]seal, [no]cpw\n",
486 addop = 1; /* get next op */
487 else if ((*str == '-') || (*str == '_'))
490 printf("Illegal combination operator: %c\n", *str);
496 *flags = (f & KAF_SETTABLE_FLAGS) | KAFNORMAL;
500 #define seriouserror(code) ((code <0) || ((code != UNOSERVERS) && (code != UNOQUORUM) && code != UNOTSYNC))
502 /* return MAXLONG if locked forever */
504 ka_islocked(char *name, char *instance, afs_uint32 * when)
514 ubik_CallIter(KAM_LockStatus, conn, UPUBIKONLY, &count, (long) name,
515 (long) instance, (long) &tempwhen, 0, 0, 0,
516 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
518 if (seriouserror(code))
519 afs_com_err(whoami, code, "");
520 } else if (tempwhen) { /* user is locked */
521 if (!*when || tempwhen < *when) {
525 } else /* ! tempwhen ==> user is not locked */
528 } while (code != UNOSERVERS);
534 Unlock(struct cmd_syndesc *as, void *arock)
536 afs_int32 code, rcode = 0;
539 char name[MAXKTCNAMELEN];
540 char instance[MAXKTCNAMELEN];
542 code = ka_ParseLoginName(as->parms[0].items->data, name, instance, 0);
544 afs_com_err(whoami, code, "parsing user's name '%s'",
545 as->parms[0].items->data);
551 code = ubik_CallIter(KAM_Unlock, conn, 0, &count, (long) name, (long) instance,
552 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
553 if (code && (code != UNOSERVERS)) {
555 if (conn && conn->conns[count - 1]
556 && conn->conns[count - 1]->peer) {
557 server = conn->conns[count - 1]->peer->host;
559 afs_com_err(whoami, code,
560 "so %s.%s may still be locked (on server %d.%d.%d.%d)",
561 name, instance, ((server >> 24) & 0xFF),
562 ((server >> 16) & 0xFF), ((server >> 8) & 0xFF),
569 } while (code != UNOSERVERS);
575 SetFields(struct cmd_syndesc *as, void *arock)
578 char name[MAXKTCNAMELEN];
579 char instance[MAXKTCNAMELEN];
582 afs_int32 lifetime = 0;
583 afs_int32 maxAssociates = -1;
584 afs_int32 pwexpiry = 0;
585 afs_int32 was_spare = 0;
586 char misc_auth_bytes[4];
589 code = ka_ParseLoginName(as->parms[0].items->data, name, instance, 0);
591 afs_com_err(whoami, code, "parsing user's name '%s'",
592 as->parms[0].items->data);
596 if (as->parms[1].items) {
597 code = parse_flags(name, instance, as->parms[1].items->data, &flags);
600 ("Illegal flag specification: %s, should be of the form <'='|'+'|'-'|'_'>bitname{<'+'|'-'>bitname}*\n",
601 as->parms[1].items->data);
605 if (as->parms[2].items) {
607 char *s = strncpy(buf, as->parms[2].items->data, sizeof(buf));
608 code = ktime_DateToInt32(s, &expiration);
610 printf("Illegal time format %s: %s\n", as->parms[2].items->data,
611 ktime_GetDateUsage());
614 if (expiration == 0) {
615 fprintf(stderr, "Expiration time must be after (about) 1970.\n");
618 if (expiration < time(0)) {
620 "Warning: expiration being set into the past, account will be disabled.\n");
626 if (as->parms[3].items) {
627 code = read_time_interval(as->parms[3].items->data, &lifetime);
632 /* no point in doing this any sooner than necessary */
633 for (i = 0; i < 4; misc_auth_bytes[i++] = 0);
635 if (as->parms[4].items) {
636 if (util_isint(as->parms[4].items->data))
637 pwexpiry = atoi(as->parms[4].items->data);
640 "Password lifetime specified must be a non-negative decimal integer.\n");
643 if (pwexpiry < 0 || pwexpiry > 254) {
645 "Password lifetime range must be [0..254] days.\n");
646 fprintf(stderr, "Zero represents an unlimited lifetime.\n");
649 misc_auth_bytes[0] = pwexpiry + 1;
653 if (as->parms[5].items) {
655 reuse = (as->parms[5].items->data);
657 if (!strcmp(reuse, "yes")) {
658 misc_auth_bytes[1] = KA_REUSEPW;
659 } else if (strcmp(reuse, "no")) {
661 "must specify \"yes\" or \"no\": \"yes\" assumed\n");
662 misc_auth_bytes[1] = KA_REUSEPW;
664 misc_auth_bytes[1] = KA_NOREUSEPW;
668 if (as->parms[6].items) {
672 if (util_isint(as->parms[6].items->data)
673 && ((nfailures = atoi(as->parms[6].items->data)) < 255)) {
674 misc_auth_bytes[2] = nfailures + 1;
676 fprintf(stderr, "Failure limit must be in [0..254].\n");
677 fprintf(stderr, "Zero represents unlimited login attempts.\n");
682 if (as->parms[7].items) {
683 int locktime, hrs, mins;
687 s = as->parms[7].items->data;
689 sscanf(s, "%d:%d", &hrs, &mins);
691 sscanf(s, "%d", &mins);
693 locktime = hrs * 60 + mins;
694 if (hrs < 0 || hrs > 36 || mins < 0) {
696 "Lockout times must be either minutes or hh:mm.\n");
697 fprintf(stderr, "Lockout times must be less than 36 hours.\n");
699 } else if (locktime > 36 * 60) {
701 "Lockout times must be either minutes or hh:mm.\n");
702 fprintf(stderr, "Lockout times must be less than 36 hours.\n");
704 "Continuing with lock time of exactly 36 hours...\n");
707 locktime = (locktime * 60 + 511) >> 9; /* ceil(l*60/512) */
708 misc_auth_bytes[3] = locktime + 1; /* will be 1 if user said 0 */
711 if (as->parms[8].items) {
712 maxAssociates = atoi(as->parms[6].items->data);
713 if (maxAssociates < 0) {
714 printf("Illegal maximum number of associates\n");
719 was_spare = pack_long(misc_auth_bytes);
721 if (was_spare || flags || expiration || lifetime || (maxAssociates >= 0))
723 ubik_Call(KAM_SetFields, conn, 0, name, instance, flags,
724 expiration, lifetime, maxAssociates, was_spare,
727 printf("Must specify one of the optional parameters\n");
731 afs_com_err(whoami, code, "calling KAM_SetFields for %s.%s", name,
737 StringToKey(struct cmd_syndesc *as, void *arock)
740 char realm[MAXKTCREALMLEN];
741 struct ktc_encryptionKey key;
743 if (as->parms[1].items) {
744 code = ka_ExpandCell(as->parms[1].items->data, realm, 0 /*local */ );
746 afs_com_err(whoami, code,
747 "expanding %s as cell name, attempting to continue",
748 as->parms[1].items->data);
750 ucstring(realm, realm, sizeof(realm));
752 if (code = DefaultCell())
754 ucstring(realm, cell, sizeof(realm));
756 ka_StringToKey(as->parms[0].items->data, realm, &key);
758 printf("Converting %s in realm '%s' yields key='",
759 as->parms[0].items->data, realm);
760 ka_PrintBytes((char *)&key, sizeof(key));
763 des_string_to_key(as->parms[0].items->data, &key);
765 printf("Converting %s with the DES string to key yields key='",
766 as->parms[0].items->data);
767 ka_PrintBytes((char *)&key, sizeof(key));
774 SetPassword(struct cmd_syndesc *as, void *arock)
777 char name[MAXKTCNAMELEN];
778 char instance[MAXKTCNAMELEN];
779 char realm[MAXKTCREALMLEN];
780 struct ktc_encryptionKey key;
783 code = ka_ParseLoginName(as->parms[0].items->data, name, instance, realm);
785 afs_com_err(whoami, code, "parsing user's name '%s'",
786 as->parms[0].items->data);
790 if (strlen(realm) == 0)
791 ucstring(realm, cell, sizeof(realm));
793 if (as->parms[1].items && as->parms[2].items) {
794 printf("Can't specify both a password and a key\n");
796 } else if (as->parms[1].items) {
797 (void)init_child(myName);
798 (void)give_to_child(passwd); /* old password */
799 code = password_bad(as->parms[1].items->data);
800 (void)terminate_child();
803 ka_StringToKey(as->parms[1].items->data, realm, &key);
804 } else if (as->parms[2].items) {
805 if (ka_ReadBytes(as->parms[2].items->data, (char *)&key, sizeof(key))
807 printf("Key must be 8 bytes: '%s' was too long\n",
808 as->parms[2].items->data);
812 printf("Must specify new password or key\n");
817 if (as->parms[3].items)
818 sscanf(as->parms[3].items->data, "%d", &kvno);
820 #if defined(AFS_S390_LINUX20_ENV) && !defined(AFS_S390X_LINUX20_ENV)
821 code = ubik_Call(KAM_SetPassword, conn, 0, name, instance, kvno, 0, key);
823 code = ubik_Call(KAM_SetPassword, conn, 0, name, instance, kvno, key);
826 afs_com_err(whoami, code, "so can't set password for %s.%s", name,
831 #define PrintPrincipal(p,n,l) \
832 PrintName((p)->name, (p)->instance, (p)->cell, l, n)
835 PrintName(char *name, char *inst, char *acell, int buflen, char *buf)
838 int left; /* if ConvertBytes stops early */
847 left = ka_ConvertBytes(buf, buflen, name, strlen(name));
851 afs_com_err(whoami, code, "PrintName: principal name was '%s'.'%s'@'%s'",
858 if (nlen + len + 1 >= buflen)
861 left = ka_ConvertBytes(buf + nlen, buflen - nlen, inst, len);
869 char *lcell = ka_LocalCell();
872 if (strcmp(acell, lcell) != 0) {
873 /* only append cell if not the local cell */
874 if (nlen + len + 1 >= buflen)
877 left = ka_ConvertBytes(buf + nlen, buflen - nlen, acell, len);
886 #define PrintedPrincipal(p) PrintedName ((p)->name, (p)->instance, (p)->cell)
888 /* PrintedName - returned a pointer to a static string in which the formated
889 * name has been stored. */
892 PrintedName(char *name, char *inst, char *cell)
894 static char printedName[128];
896 code = PrintName(name, inst, cell, sizeof(printedName), printedName);
900 strncpy(printedName, name, sizeof(printedName));
901 printedName[sizeof(printedName) - 8] = 0;
902 strcat(printedName, "<error>");
908 ListTicket(struct ktc_principal *server, int verbose)
911 struct ktc_token token; /* the token we're printing */
912 struct ktc_principal client;
913 char UserName[sizeof(struct ktc_principal)];
914 char ServerName[sizeof(struct ktc_principal)];
915 afs_int32 now = time(0);
916 char bob[KA_TIMESTR_LEN];
918 /* get the ticket info itself */
919 code = ktc_GetToken(server, &token, sizeof(token), &client);
921 afs_com_err(whoami, code, "failed to get token info for server %s",
922 PrintedPrincipal(server));
925 code = PrintPrincipal(&client, UserName, sizeof(UserName));
928 /* spaces are printed as "\040" */
929 if (UserName[0] == 0)
931 else if (strncmp(UserName, "AFS\\040ID\\040", 13) == 0) {
932 printf("User's (AFS ID %s) tokens", UserName + 13);
933 } else if (strncmp(UserName, "Unix\\040UID\\040", 15) == 0) {
936 printf("User %s's tokens", UserName);
938 code = PrintPrincipal(server, ServerName, sizeof(ServerName));
941 printf(" for %s ", ServerName);
943 if (token.startTime > now) {
944 ka_timestr(token.startTime, bob, KA_TIMESTR_LEN);
945 printf("[>> POSTDATED 'till %s <<]", bob);
948 if (token.endTime <= now)
949 printf("[>> Expired <<]\n");
951 ka_timestr(token.endTime, bob, KA_TIMESTR_LEN);
952 printf("[Expires %s]\n", bob);
955 printf("SessionKey: ");
956 ka_PrintBytes((char *)&token.sessionKey, sizeof(token.sessionKey));
957 printf("\nTicket (kvno = %d, len = %d): ", token.kvno,
959 ka_PrintBytes((char *)token.ticket, token.ticketLen);
966 GetTicket(struct cmd_syndesc *as, void *arock)
969 struct ktc_principal server;
970 struct ktc_token token;
971 afs_int32 life = KA_SIXHOURS;
973 if (as->parms[1].items) {
974 code = read_time_interval(as->parms[1].items->data, &life);
979 ka_ParseLoginName(as->parms[0].items->data, server.name,
980 server.instance, server.cell);
982 afs_com_err(whoami, code, "parsing user's name '%s'",
983 as->parms[0].items->data);
986 if (server.cell[0] == 0) {
987 if (code = DefaultCell())
989 strcpy(server.cell, cell);
991 code = ka_ExpandCell(server.cell, server.cell, 0 /*local */ );
993 afs_com_err(whoami, code, "Can't expand cell name");
998 token.ticketLen = 0; /* in case there are no tokens */
1000 ka_GetServerToken(server.name, server.instance, server.cell, life,
1001 &token, /*new */ 1, /*dosetpag */ 0);
1003 afs_com_err(whoami, code, "getting ticket for %s",
1004 PrintedPrincipal(&server));
1006 code = ListTicket(&server, /*verbose */ 1);
1012 GetPassword(struct cmd_syndesc *as, void *arock)
1015 char name[MAXKTCNAMELEN];
1016 struct ktc_encryptionKey key;
1017 static struct ubik_client *lpbkConn = 0;
1019 /* no instance allowed */
1020 code = ka_ParseLoginName(as->parms[0].items->data, name, 0, 0);
1023 afs_com_err(whoami, code,
1024 "getting %s's password via loopback connection to GetPassword",
1026 /* if we got a timeout, print a clarification, too */
1029 "%s: please note that this command must be run locally on a database server machine.\n",
1034 if (lpbkConn == 0) {
1035 struct rx_connection *conns[2];
1036 struct rx_securityClass *sc;
1037 int si; /* security class index */
1042 sc = rxnull_NewClientSecurityObject();
1043 si = RX_SCINDEX_NULL;
1045 rx_NewConnection(htonl(INADDR_LOOPBACK), htons(AFSCONF_KAUTHPORT),
1046 KA_MAINTENANCE_SERVICE, sc, si);
1048 code = ubik_ClientInit(conns, &lpbkConn);
1052 code = ubik_Call(KAM_GetPassword, lpbkConn, 0, name, &key);
1053 /* Lets close down the ubik_Client connection now */
1054 ubik_ClientDestroy(lpbkConn);
1058 ka_PrintBytes((char *)&key, sizeof(key));
1064 GetRandomKey(struct cmd_syndesc *as, void *arock)
1067 struct ktc_encryptionKey key;
1069 code = ubik_Call(KAM_GetRandomKey, conn, 0, &key);
1071 afs_com_err(whoami, code, "so can't get random key");
1075 ka_PrintBytes((char *)&key, sizeof(key));
1077 for (i = 0; i < sizeof(key); i++) {
1078 printf("%0.2x", ((char *)&key)[i] & 0xff);
1090 Statistics(struct cmd_syndesc *as, void *arock)
1096 char bob[KA_TIMESTR_LEN];
1099 ubik_Call(KAM_GetStats, conn, 0, KAMAJORVERSION, &admins, &statics,
1102 printf("call to GetStats failed: %s\n", ka_ErrorString(code));
1105 if (statics.minor_version != KAMINORVERSION)
1106 printf("Minor version number mismatch: got %d, expected %d\n",
1107 statics.minor_version, KAMINORVERSION);
1108 printf("%d allocs, %d frees, %d password changes\n", statics.allocs,
1109 statics.frees, statics.cpws);
1110 printf("Hash table utilization = %f%%\n",
1111 (double)dynamics.hashTableUtilization / 100.0);
1112 ka_timestr(dynamics.start_time, bob, KA_TIMESTR_LEN);
1113 printf("From host %lx started at %s:\n",
1114 afs_cast_uint32(dynamics.host), bob);
1116 #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)
1117 print_stat(Authenticate);
1118 print_stat(ChangePassword);
1119 print_stat(GetTicket);
1120 print_stat(CreateUser);
1121 print_stat(SetPassword);
1122 print_stat(SetFields);
1123 print_stat(DeleteUser);
1124 print_stat(GetEntry);
1125 print_stat(ListEntry);
1126 print_stat(GetStats);
1127 print_stat(GetPassword);
1128 print_stat(GetRandomKey);
1130 print_stat(UAuthenticate);
1131 print_stat(UGetTicket);
1133 #if (KAMAJORVERSION>5)
1134 print cpu stats printf("%d string checks\n", dynamics.string_checks);
1136 printf("Used %.3f seconds of CPU time.\n",
1137 dynamics.string_checks / 1000.0);
1139 printf("%d admin accounts\n", admins);
1144 DebugInfo(struct cmd_syndesc *as, void *arock)
1147 struct ka_debugInfo info;
1151 char bob[KA_TIMESTR_LEN];
1154 if (as->parms[0].items) {
1155 struct ubik_client *iConn;
1157 ka_SingleServerConn(cell, as->parms[0].items->data,
1158 KA_MAINTENANCE_SERVICE, 0, &iConn);
1160 struct afsconf_cell cellinfo;
1162 afs_com_err(whoami, code, "couldn't find host %s in cell %s",
1163 as->parms[0].items->data, cell);
1164 code = ka_GetServers(cell, &cellinfo);
1166 afs_com_err(whoami, code, "getting servers in cell %s", cell);
1168 printf("Servers in cell %s, are:\n", cell);
1169 for (i = 0; i < cellinfo.numServers; i++)
1170 printf(" %s\n", cellinfo.hostName[i]);
1174 code = ubik_Call(KAM_Debug, iConn, 0, KAMAJORVERSION, 0, &info);
1175 ubik_ClientDestroy(iConn);
1177 code = ubik_Call(KAM_Debug, conn, 0, KAMAJORVERSION, 0, &info);
1180 afs_com_err(whoami, code, "call to Debug failed");
1185 if (info.minorVersion != KAMINORVERSION)
1186 printf("Minor version number mismatch: got %d, expected %d\n",
1187 info.minorVersion, KAMINORVERSION);
1190 #if (KAMAJORVERSION>5)
1197 timeOffset = -timeOffset;
1198 if (timeOffset > 60) {
1200 ("WARNING: Large server client clock skew: %d seconds. Call itself took %d seconds.\n",
1201 timeOffset, now - start);
1203 ka_timestr(info.startTime, bob, KA_TIMESTR_LEN);
1204 printf("From host %lx started %sat %s:\n",
1205 afs_cast_uint32(info.host),
1206 (info.noAuth ? "w/o authorization " : ""), bob);
1207 ka_timestr(info.lastTrans, bob, KA_TIMESTR_LEN);
1208 printf("Last trans was %s at %s\n", info.lastOperation, bob);
1209 ka_timestr(info.dbHeaderRead, bob, KA_TIMESTR_LEN);
1210 printf("Header last read %s.\n", bob);
1211 printf("db version=%d, keyVersion=%d, key cache version=%d\n",
1212 info.dbVersion, info.dbSpecialKeysVersion, info.kcVersion);
1213 printf("db ptrs: free %d, eof %d, kvno %d.\n", info.dbFreePtr,
1214 info.dbEofPtr, info.dbKvnoPtr);
1215 ka_timestr(info.nextAutoCPW, bob, KA_TIMESTR_LEN);
1216 printf("Next autoCPW at %s or in %d updates.\n", bob,
1217 info.updatesRemaining);
1218 if (info.cheader_lock || info.keycache_lock)
1219 printf("locks: cheader %08lx, keycache %08lx\n",
1220 afs_cast_uint32(info.cheader_lock),
1221 afs_cast_uint32(info.keycache_lock));
1222 printf("Last authentication for %s, last admin user was %s\n",
1223 info.lastAuth, info.lastAdmin);
1224 printf("Last TGS op was a %s ticket was for %s\n", info.lastTGSServer,
1226 printf("Last UDP TGS was a %s ticket for %s. UDP Authenticate for %s\n",
1227 info.lastUTGSServer, info.lastUTGS, info.lastUAuth);
1228 printf("key cache size %d, used %d.\n", info.kcSize, info.kcUsed);
1229 if (info.kcUsed > KADEBUGKCINFOSIZE) {
1230 printf("insufficient room to return all key cache entries!\n");
1231 info.kcUsed = KADEBUGKCINFOSIZE;
1233 for (i = 0; i < info.kcUsed; i++)
1234 ka_timestr(info.kcInfo[i].used, bob, KA_TIMESTR_LEN);
1235 printf("%32s %c %2x(%2x) used %s\n", info.kcInfo[i].principal,
1236 (info.kcInfo[i].primary ? '*' : ' '), info.kcInfo[i].kvno,
1237 info.kcInfo[i].keycksum, bob);
1242 Interactive(struct cmd_syndesc *as, void *arock)
1249 Quit(struct cmd_syndesc *as, void *arock)
1256 MyAfterProc(struct cmd_syndesc *as, void *arock)
1258 if (!strcmp(as->name, "help"))
1261 /* Determine if we need to destory the ubik connection.
1262 * Closing it avoids resends of packets.
1265 ubik_ClientDestroy(conn);
1272 int init = 0, noauth;
1273 char name[MAXKTCNAMELEN];
1274 char instance[MAXKTCNAMELEN];
1275 char newCell[MAXKTCREALMLEN];
1276 afs_int32 serverList[MAXSERVERS];
1279 NoAuth(struct cmd_syndesc *as, void *arock)
1286 MyBeforeProc(struct cmd_syndesc *as, void *arock)
1288 extern struct passwd *getpwuid();
1289 struct ktc_encryptionKey key;
1290 struct ktc_principal auth_server, auth_token, client;
1291 char realm[MAXKTCREALMLEN];
1293 struct ktc_token token, *pToken;
1294 int i, acode, code = 0;
1297 char *ws = strrchr(as->a0name, '/');
1299 ws++; /* skip everything before the "/" */
1302 if (strlen(ws) > 0) {
1303 strncpy(whoami, ws, sizeof(whoami));
1304 if (strlen(whoami) + 1 >= sizeof(whoami))
1305 strcpy(whoami, "kas:");
1307 strcat(whoami, ":");
1310 /* append sub-command name */
1311 strncat(whoami, as->name, sizeof(whoami) - strlen(whoami) - 1);
1314 if (as->parms[12].name == 0)
1317 assert(as->parms[13].name && as->parms[14].name && as->parms[15].name
1318 && as->parms[16].name);
1320 /* MyAfterProc() destroys the conn, but just to be sure */
1322 code = ubik_ClientDestroy(conn);
1326 if (!init || as->parms[12].items || as->parms[13].items
1327 || as->parms[14].items || as->parms[15].items
1328 || as->parms[16].items) {
1329 strcpy(instance, "");
1330 strcpy(newCell, "");
1332 if (as->parms[12].items) { /* -admin_username */
1334 ka_ParseLoginName(as->parms[12].items->data, name, instance,
1337 afs_com_err(whoami, code, "parsing user's name '%s'",
1338 as->parms[12].items->data);
1343 DWORD len = MAXKTCNAMELEN;
1344 if (!GetUserName((LPTSTR) name, &len)) {
1345 printf("Can't get user name \n");
1349 /* No explicit name provided: use Unix uid. */
1350 struct passwd *pw = getpwuid(getuid());
1352 printf("Can't figure out your name from your user id.\n");
1355 strncpy(name, pw->pw_name, sizeof(name));
1359 if (as->parms[14].items) { /* -cell */
1360 if (strlen(newCell) > 0) {
1361 printf("Duplicate cell specification not allowed\n");
1363 strncpy(newCell, as->parms[14].items->data, sizeof(newCell));
1366 code = ka_ExpandCell(newCell, newCell, 0 /*local */ );
1368 afs_com_err(whoami, code, "Can't expand cell name");
1371 strcpy(cell, newCell);
1373 if (as->parms[15].items) { /* -servers */
1374 struct cmd_item *ip;
1375 char *ap[MAXSERVERS + 2];
1379 for (ip = as->parms[15].items, i = 2; ip; ip = ip->next, i++)
1381 code = ubik_ParseClientList(i, ap, serverList);
1383 afs_com_err(whoami, code, "could not parse server list");
1386 ka_ExplicitCell(cell, serverList);
1389 noauth = (as->parms[16].items ? 1 : 0); /* -noauth */
1394 token.ticketLen = 0; /* in case there are no tokens */
1395 if (!noauth) { /* Will prompt for a password */
1396 /* first see if there's already an admin ticket */
1398 ka_GetAdminToken(0, 0, cell, 0, KA_SIXHOURS, &token,
1400 if (code) { /* if not then get key and try again */
1401 if (as->parms[13].items) { /* if password specified */
1402 strncpy(passwd, as->parms[13].items->data, sizeof(passwd));
1403 memset(as->parms[13].items->data, 0,
1404 strlen(as->parms[13].items->data));
1406 char msg[MAXKTCNAMELEN + 50];
1407 if (as->parms[12].items)
1408 sprintf(msg, "Administrator's (%s) Password: ", name);
1410 sprintf(msg, "Password for %s: ", name);
1411 code = read_pw_string(passwd, sizeof(passwd), msg, 0);
1414 else if (strlen(passwd) == 0)
1415 code = KANULLPASSWORD;
1417 afs_com_err(whoami, code, "reading password");
1421 ka_StringToKey(passwd, cell, &key);
1423 ka_GetAdminToken(name, instance, cell, &key, KA_SIXHOURS,
1424 &token, 0 /* !new */ );
1425 if (code == KABADREQUEST) {
1426 des_string_to_key(passwd, &key);
1428 ka_GetAdminToken(name, instance, cell, &key, KA_SIXHOURS,
1429 &token, 0 /* !new */ );
1431 if ((code == KABADREQUEST) && (strlen(passwd) > 8)) {
1432 /* try with only the first 8 characters incase they set
1433 * their password with an old style passwd program. */
1435 ka_StringToKey(passwd, cell, &key);
1437 ka_GetAdminToken(name, instance, cell, &key, KA_SIXHOURS,
1438 &token, 0 /* !new */ );
1441 "Warning: you have typed a password longer than 8 characters, but only the\n");
1443 "first 8 characters were actually significant. If you change your password\n");
1445 "again this warning message will go away.\n");
1452 reason = "password was incorrect";
1455 reason = "Authentication Server was unavailable";
1458 reason = (char *)afs_error_message(code);
1461 "%s: Auth. as %s to AuthServer failed: %s\nProceeding w/o authentication\n",
1462 whoami, PrintedName(name, instance, cell), reason);
1464 /* get an Authentication token while were at it. */
1465 if (ka_CellToRealm(cell, realm, 0) != 0)
1467 strcpy(auth_server.name, KA_TGS_NAME);
1468 strcpy(auth_server.instance, realm);
1469 strcpy(auth_server.cell, cell);
1471 (&auth_server, &auth_token, sizeof(struct ktc_token),
1474 ka_GetAuthToken(name, instance, cell, &key,
1475 MAXKTCTICKETLIFETIME, (afs_int32 *) 0
1476 /*Don't need pwd expiration info here */
1478 if (acode && (acode != code)) /* codes are usually the same */
1479 afs_com_err(whoami, code,
1480 "getting Authentication token for %s",
1481 PrintedName(name, instance, cell));
1483 memset(&key, 0, sizeof(key));
1487 pToken = ((token.ticketLen == 0) ? 0 : &token);
1488 code = ka_AuthServerConn(cell, KA_MAINTENANCE_SERVICE, pToken, &conn);
1489 if (code && pToken) {
1490 afs_com_err(whoami, code,
1491 "connecting to AuthServer: now trying w/o authentication");
1492 code = ka_AuthServerConn(cell, KA_MAINTENANCE_SERVICE, 0, &conn);
1494 afs_com_err(whoami, code,
1495 "making unauthenticated connection to AuthServer");
1498 afs_com_err(whoami, code,
1499 "Couldn't establish connection to Authentication Server");
1503 /* now default unspecified password by prompting from terminal */
1504 if (as->nParms >= 12)
1505 for (i = 0; i < 12; i++)
1506 if (as->parms[i].name && (as->parms[i].items == 0)) {
1507 char *p = as->parms[i].name; /* parameter name */
1508 int l = strlen(p); /* length of name */
1509 /* does parameter end in "password" */
1510 if (strcmp(p + (l - 8), "password") == 0) {
1512 char password[BUFSIZ];
1513 struct cmd_item *ip;
1517 code = read_pw_string(password, sizeof(password), msg, 1);
1520 else if (strlen(password) == 0)
1521 code = KANULLPASSWORD;
1523 afs_com_err(whoami, code, "prompting for %s", p + 1);
1526 ip = (struct cmd_item *)malloc(sizeof(struct cmd_item));
1527 ip->data = (char *)malloc(strlen(password) + 1);
1529 strcpy(ip->data, password);
1530 as->parms[i].items = ip;
1533 if (!conn) { /* if all else fails... */
1534 code = NoAuth(0, 0); /* get unauthenticated conn */
1541 /* These are some helpful command that deal with the cache managers tokens. */
1544 ForgetTicket(struct cmd_syndesc *as, void *arock)
1549 struct ktc_principal server;
1551 if (as->parms[0].items) {
1552 char *name = as->parms[0].items->data;
1554 ka_ParseLoginName(name, server.name, server.instance,
1557 afs_com_err(whoami, code, "couldn't interpret name '%s'", name);
1560 if (server.cell[0] == 0) {
1561 if (code = DefaultCell())
1563 strcpy(server.cell, cell);
1565 code = ka_ExpandCell(server.cell, server.cell, 0 /*local */ );
1567 afs_com_err(whoami, code, "Can't expand cell name");
1571 code = ktc_ForgetToken(&server);
1573 afs_com_err(whoami, code, "couldn't remove tokens for %s",
1574 PrintedPrincipal(&server));
1578 if (!as->parms[1].items) {
1579 fprintf(stderr, "Must specify server name or -all\n");
1582 code = ktc_ForgetAllTokens();
1584 afs_com_err(whoami, code, "couldn't delete all tokens");
1589 code = ktc_ForgetAllTokens();
1591 afs_com_err(whoami, code, "couldn't delete all tokens");
1598 ListTickets(struct cmd_syndesc *as, void *arock)
1601 int index, newIndex;
1602 struct ktc_principal server;
1605 if (as->parms[1].items)
1607 if (as->parms[0].items) {
1608 char *name = as->parms[0].items->data;
1610 ka_ParseLoginName(name, server.name, server.instance,
1613 afs_com_err(whoami, code, "couldn't interpret name '%s'", name);
1616 if (server.cell[0] == 0) {
1617 if (code = DefaultCell())
1619 strcpy(server.cell, cell);
1621 code = ka_ExpandCell(server.cell, server.cell, 0 /*local */ );
1623 afs_com_err(whoami, code, "Can't expand cell name");
1627 code = ListTicket(&server, verbose);
1629 for (index = 0;; index = newIndex) {
1630 code = ktc_ListTokens(index, &newIndex, &server);
1632 if (code == KTC_NOENT)
1633 code = 0; /* end of list */
1636 code = ListTicket(&server, verbose);
1642 add_std_args(register struct cmd_syndesc *ts)
1645 /* 12 */ cmd_AddParm(ts, "-admin_username", CMD_SINGLE, CMD_OPTIONAL,
1646 "admin principal to use for authentication");
1647 /* 13 */ cmd_AddParm(ts, "-password_for_admin", CMD_SINGLE, CMD_OPTIONAL,
1649 /* 14 */ cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cell name");
1650 /* 15 */ cmd_AddParm(ts, "-servers", CMD_LIST, CMD_OPTIONAL,
1651 "explicit list of authentication servers");
1652 /* 16 */ cmd_AddParm(ts, "-noauth", CMD_FLAG, CMD_OPTIONAL,
1653 "don't authenticate");
1657 ka_AdminInteractive(int cmd_argc, char *cmd_argv[])
1660 register struct cmd_syndesc *ts;
1666 strncpy(myName, *cmd_argv, 509);
1668 cmd_SetBeforeProc(MyBeforeProc, NULL);
1669 cmd_SetAfterProc(MyAfterProc, NULL);
1671 ts = cmd_CreateSyntax("interactive", Interactive, NULL,
1672 "enter interactive mode");
1675 ts = cmd_CreateSyntax("noauthentication", NoAuth, NULL,
1676 "connect to AuthServer w/o using token");
1678 ts = cmd_CreateSyntax("list", ListUsers, NULL,
1679 "list all users in database");
1680 cmd_AddParm(ts, "-long", CMD_FLAG, CMD_OPTIONAL,
1681 "show detailed info about each user");
1682 cmd_AddParm(ts, "-showadmin", CMD_FLAG, CMD_OPTIONAL,
1683 "show all cell administrators");
1684 cmd_AddParm(ts, "-showkey", CMD_FLAG, CMD_OPTIONAL,
1685 "show the user's actual key rather than the checksum");
1687 cmd_CreateAlias(ts, "ls");
1689 ts = cmd_CreateSyntax("examine", ExamineUser, NULL,
1690 "examine the entry for a user");
1691 cmd_AddParm(ts, "-name", CMD_SINGLE, 0, "name of user");
1692 cmd_AddParm(ts, "-showkey", CMD_FLAG, CMD_OPTIONAL,
1693 "show the user's actual key rather than the checksum");
1696 ts = cmd_CreateSyntax("create", CreateUser, NULL,
1697 "create an entry for a user");
1698 cmd_AddParm(ts, "-name", CMD_SINGLE, 0, "name of user");
1699 cmd_AddParm(ts, "-initial_password", CMD_SINGLE, CMD_OPTIONAL,
1700 "initial password");
1703 ts = cmd_CreateSyntax("delete", DeleteUser, NULL, "delete a user");
1704 cmd_AddParm(ts, "-name", CMD_SINGLE, 0, "name of user");
1706 cmd_CreateAlias(ts, "rm");
1708 ts = cmd_CreateSyntax("setfields", SetFields, NULL,
1709 "set various fields in a user's entry");
1710 cmd_AddParm(ts, "-name", CMD_SINGLE, 0, "name of user");
1711 cmd_AddParm(ts, "-flags", CMD_SINGLE, CMD_OPTIONAL,
1712 "hex flag value or flag name expression");
1713 cmd_AddParm(ts, "-expiration", CMD_SINGLE, CMD_OPTIONAL,
1714 "date of account expiration");
1715 cmd_AddParm(ts, "-lifetime", CMD_SINGLE, CMD_OPTIONAL,
1716 "maximum ticket lifetime");
1717 cmd_AddParm(ts, "-pwexpires", CMD_SINGLE, CMD_OPTIONAL,
1718 "number days password is valid ([0..254])");
1719 cmd_AddParm(ts, "-reuse", CMD_SINGLE, CMD_OPTIONAL,
1720 "permit password reuse (yes/no)");
1721 cmd_AddParm(ts, "-attempts", CMD_SINGLE, CMD_OPTIONAL,
1722 "maximum successive failed login tries ([0..254])");
1723 cmd_AddParm(ts, "-locktime", CMD_SINGLE, CMD_OPTIONAL,
1724 "failure penalty [hh:mm or minutes]");
1726 cmd_AddParm(ts, "-associates", CMD_SINGLE, CMD_OPTIONAL,
1727 "maximum associate instances");
1730 cmd_CreateAlias(ts, "sf");
1733 ts = cmd_CreateSyntax("unlock", Unlock, NULL,
1734 "Enable authentication ID after max failed attempts exceeded");
1735 cmd_AddParm(ts, "-name", CMD_SINGLE, 0, "authentication ID");
1739 ts = cmd_CreateSyntax("stringtokey", StringToKey, NULL,
1740 "convert a string to a key");
1741 cmd_AddParm(ts, "-string", CMD_SINGLE, 0, "password string");
1742 cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cell name");
1744 ts = cmd_CreateSyntax("setpassword", SetPassword, NULL,
1745 "set a user's password");
1746 cmd_AddParm(ts, "-name", CMD_SINGLE, 0, "name of user");
1747 cmd_AddParm(ts, "-new_password", CMD_SINGLE, CMD_OPTIONAL,
1750 cmd_AddParm(ts, "-kvno", CMD_SINGLE, CMD_OPTIONAL, "key version number");
1752 cmd_CreateAlias(ts, "sp");
1753 #ifdef CMD_PARSER_AMBIG_FIX
1754 cmd_CreateAlias(ts, "setpasswd");
1757 /* set a user's key */
1758 ts = cmd_CreateSyntax("setkey", SetPassword, NULL, (char *)CMD_HIDDEN);
1759 cmd_AddParm(ts, "-name", CMD_SINGLE, 0, "name of user");
1761 cmd_AddParm(ts, "-new_key", CMD_SINGLE, 0, "eight byte new key");
1763 cmd_AddParm(ts, "-kvno", CMD_SINGLE, CMD_OPTIONAL, "key version number");
1766 /* get a user's password */
1767 ts = cmd_CreateSyntax("getpassword", GetPassword, NULL, (char *)CMD_HIDDEN);
1768 cmd_AddParm(ts, "-name", CMD_SINGLE, 0, "name of user");
1769 /* don't take standard args */
1770 /* add_std_args (ts); */
1771 #ifdef CMD_PARSER_AMBIG_FIX
1772 cmd_CreateAlias(ts, "getpasswd");
1775 /* get a random key */
1776 ts = cmd_CreateSyntax("getrandomkey", GetRandomKey, NULL,
1777 (char *)CMD_HIDDEN);
1780 /* get a ticket for a specific server */
1781 ts = cmd_CreateSyntax("getticket", GetTicket, NULL, (char *)CMD_HIDDEN);
1782 cmd_AddParm(ts, "-name", CMD_SINGLE, 0, "name of server");
1783 cmd_AddParm(ts, "-lifetime", CMD_SINGLE, CMD_OPTIONAL, "ticket lifetime");
1786 ts = cmd_CreateSyntax("statistics", Statistics, NULL,
1787 "show statistics for AuthServer");
1790 /* show debugging info from AuthServer */
1791 ts = cmd_CreateSyntax("debuginfo", DebugInfo, NULL, (char *)CMD_HIDDEN);
1792 cmd_AddParm(ts, "-hostname", CMD_SINGLE, CMD_OPTIONAL,
1793 "authentication server host name");
1796 ts = cmd_CreateSyntax("forgetticket", ForgetTicket, NULL,
1797 "delete user's tickets");
1799 cmd_AddParm(ts, "-name", CMD_SINGLE, (CMD_OPTIONAL | CMD_HIDE),
1802 cmd_AddParm(ts, "-all", CMD_FLAG, CMD_OPTIONAL, "delete all tickets");
1804 ts = cmd_CreateSyntax("listtickets", ListTickets, NULL,
1805 "show all cache manager tickets");
1806 cmd_AddParm(ts, "-name", CMD_SINGLE, CMD_OPTIONAL, "name of server");
1807 cmd_AddParm(ts, "-long", CMD_FLAG, CMD_OPTIONAL,
1808 "show session key and ticket");
1810 ts = cmd_CreateSyntax("quit", Quit, NULL, "exit program");
1813 conn = 0; /* no connection yet */
1814 zero_argc = cmd_argc;
1815 zero_argv = cmd_argv;
1817 strcpy(whoami, "kas");
1819 if (code = cmd_Dispatch(cmd_argc, cmd_argv)) {
1828 s = fgets(line, sizeof(line), stdin);
1830 return 0; /* EOF on input */
1831 for (i = strlen(line) - 1; i >= 0 && isspace(line[i]); i--)
1834 continue; /* blank line */
1837 cmd_ParseLine(line, argv, &argc, sizeof(argv) / sizeof(argv[0]));
1839 afs_com_err(whoami, code, "parsing line: '%s'", line);
1842 code = cmd_Dispatch(argc, argv);