diff --git a/appl/ftp/ftp/cmdtab.c b/appl/ftp/ftp/cmdtab.c index fbd6bebe2..8eb20ecf5 100644 --- a/appl/ftp/ftp/cmdtab.c +++ b/appl/ftp/ftp/cmdtab.c @@ -108,6 +108,8 @@ char verbosehelp[] = "toggle verbose mode"; char prothelp[] = "set protection level"; char kauthhelp[] = "get remote tokens"; +char klisthelp[] = "show remote tickets"; +char aklog[] = "obtain remote AFS tokens"; struct cmd cmdtab[] = { { "!", shellhelp, 0, 0, 0, shell }, @@ -185,6 +187,7 @@ struct cmd cmdtab[] = { { "prot", prothelp, 0, 1, 0, sec_prot }, { "kauth", kauthhelp, 0, 1, 0, kauth }, + { "klist", klisthelp, 0, 1, 0, klist }, { 0 }, }; diff --git a/appl/ftp/ftp/kauth.c b/appl/ftp/ftp/kauth.c index e1fd8bc7d..b03b3bab8 100644 --- a/appl/ftp/ftp/kauth.c +++ b/appl/ftp/ftp/kauth.c @@ -14,8 +14,8 @@ void kauth(int argc, char **argv) KTEXT_ST tkt; char *name; char *p; + int overbose; - if(argc > 2){ printf("usage: %s [principal]\n", argv[0]); code = -1; @@ -25,11 +25,16 @@ void kauth(int argc, char **argv) name = argv[1]; else name = username; + + overbose = verbose; + verbose = 0; + ret = command("SITE KAUTH %s", name); if(ret != CONTINUE){ code = -1; return; } + verbose = overbose; p = strstr(reply_string, "T="); if(!p){ printf("Bad reply from server.\n"); @@ -73,3 +78,16 @@ void kauth(int argc, char **argv) } code = 0; } + +void klist(int argc, char **argv) +{ + int ret; + if(argc != 1){ + printf("usage: %s\n", argv[0]); + code = -1; + return; + } + + ret = command("SITE KLIST"); + code = (ret == COMPLETE); +} diff --git a/appl/ftp/ftp/krb4.h b/appl/ftp/ftp/krb4.h index a0f3e35db..e532a57c4 100644 --- a/appl/ftp/ftp/krb4.h +++ b/appl/ftp/ftp/krb4.h @@ -8,6 +8,7 @@ void sec_status(void); void sec_prot(int, char**); void kauth(int, char **); +void klist(int, char **); void krb4_quit(void); diff --git a/appl/ftp/ftpd/ftpcmd.y b/appl/ftp/ftpd/ftpcmd.y index 2cf9799ed..03bd3f66a 100644 --- a/appl/ftp/ftpd/ftpcmd.y +++ b/appl/ftp/ftpd/ftpcmd.y @@ -138,7 +138,7 @@ static int yylex (void); AUTH ADAT PROT PBSZ CCC MIC CONF ENC - KAUTH + KAUTH KLIST LEXERR @@ -526,6 +526,10 @@ cmd kauth($5, NULL); free($5); } + | SITE SP KLIST CRLF + { + klist(); + } | STOU check_login SP pathname CRLF { if ($2 && $4 != NULL) @@ -900,6 +904,7 @@ struct tab sitetab[] = { { "HELP", HELP, OSTR, 1, "[ ]" }, { "KAUTH", KAUTH, STR1, 1, " principal [ ticket ]" }, + { "KLIST", KLIST, ARGS, 1, "(show ticket file)" }, { NULL, 0, 0, 0, 0 } }; diff --git a/appl/ftp/ftpd/kauth.c b/appl/ftp/ftpd/kauth.c index b1e148a47..4f7a46112 100644 --- a/appl/ftp/ftpd/kauth.c +++ b/appl/ftp/ftpd/kauth.c @@ -20,6 +20,7 @@ static KTEXT_ST cip; +static unsigned int lifetime; static time_t local_time; static char name[ANAME_SZ], inst[INST_SZ], realm[REALM_SZ]; @@ -41,7 +42,6 @@ store_ticket(KTEXT cip) char sname[SNAME_SZ]; char sinst[INST_SZ]; char srealm[REALM_SZ]; - unsigned char lifetime; unsigned char kvno; KTEXT_ST tkt; @@ -159,7 +159,7 @@ void kauth(char *principal, char *ticket) } if(k_hasafs()) k_afsklog(0, 0); - reply(200, "OK"); + reply(200, "Tickets will be destroyed on exit."); return; } @@ -174,3 +174,101 @@ void kauth(char *principal, char *ticket) free(p); memset(&cip, 0, sizeof(cip)); } + + +static char * +short_date(int32_t dp) +{ + char *cp; + time_t t = (time_t)dp; + + if (t == (time_t)(-1L)) return "*** Never *** "; + cp = ctime(&t) + 4; + cp[15] = '\0'; + return (cp); +} + +void klist(void) +{ + int err; + + char *file = tkt_string(); + + char name[ANAME_SZ]; + char inst[INST_SZ]; + char realm[REALM_SZ]; + + char buf1[128], buf2[128]; + int header = 1; + CREDENTIALS c; + + + + err = tf_init(file, R_TKT_FIL); + if(err != KSUCCESS){ + reply(500, "%s", krb_get_err_text(err)); + return; + } + tf_close(); + + /* + * We must find the realm of the ticket file here before calling + * tf_init because since the realm of the ticket file is not + * really stored in the principal section of the file, the + * routine we use must itself call tf_init and tf_close. + */ + err = krb_get_tf_realm(file, realm); + if(err != KSUCCESS){ + reply(500, "%s", krb_get_err_text(err)); + return; + } + + err = tf_init(file, R_TKT_FIL); + if(err != KSUCCESS){ + reply(500, "%s", krb_get_err_text(err)); + return; + } + + err = tf_get_pname(name); + if(err != KSUCCESS){ + reply(500, "%s", krb_get_err_text(err)); + return; + } + err = tf_get_pinst(inst); + if(err != KSUCCESS){ + reply(500, "%s", krb_get_err_text(err)); + return; + } + + /* + * You may think that this is the obvious place to get the + * realm of the ticket file, but it can't be done here as the + * routine to do this must open the ticket file. This is why + * it was done before tf_init. + */ + + if(inst[0]) + lreply(200, "Principal: %s.%s@%s", name, inst, realm); + else + lreply(200, "Principal: %s@%s", name, realm); + while ((err = tf_get_cred(&c)) == KSUCCESS) { + if (header) { + lreply(200, "%-15s %-15s %s", + " Issued", " Expires", " Principal (kvno)"); + header = 0; + } + strcpy(buf1, short_date(c.issue_date)); + c.issue_date = krb_life_to_time(c.issue_date, c.lifetime); + if (time(0) < (unsigned long) c.issue_date) + strcpy(buf2, short_date(c.issue_date)); + else + strcpy(buf2, ">>> Expired <<< "); + lreply(200, "%s %s %s%s%s%s%s (%d)", buf1, buf2, + c.service, (c.instance[0] ? "." : ""), c.instance, + (c.realm[0] ? "@" : ""), c.realm, c.kvno); + } + if (header && err == EOF) { + lreply(200, "No tickets in file."); + } + reply(200, ""); +}