From 516345750a7b38c8344c88691944d79c1d81b304 Mon Sep 17 00:00:00 2001 From: Garrett Wollman Date: Fri, 20 Jan 1995 02:47:50 +0000 Subject: [PATCH] The user side of the kadmin protocol. HOW-TO describes how to recreate this based just on the eBones distribution. --- eBones/kadmin/HOW-TO | 8 + eBones/kadmin/Makefile | 19 + eBones/kadmin/kadmin.c | 626 +++++++++++++++++++++++++++ eBones/kadmin/kadmin_cmds.ct | 41 ++ eBones/usr.bin/kadmin/Makefile | 19 + eBones/usr.bin/kadmin/kadmin.c | 626 +++++++++++++++++++++++++++ eBones/usr.bin/kadmin/kadmin_cmds.ct | 41 ++ 7 files changed, 1380 insertions(+) create mode 100644 eBones/kadmin/HOW-TO create mode 100644 eBones/kadmin/Makefile create mode 100644 eBones/kadmin/kadmin.c create mode 100644 eBones/kadmin/kadmin_cmds.ct create mode 100644 eBones/usr.bin/kadmin/Makefile create mode 100644 eBones/usr.bin/kadmin/kadmin.c create mode 100644 eBones/usr.bin/kadmin/kadmin_cmds.ct diff --git a/eBones/kadmin/HOW-TO b/eBones/kadmin/HOW-TO new file mode 100644 index 000000000000..bb5c3ca936f0 --- /dev/null +++ b/eBones/kadmin/HOW-TO @@ -0,0 +1,8 @@ +# $Id$ + +To re-create this directory from outside the US, take the Makefile +(provided), get the two source files from the original eBones distribution, +do a `perl -spi.bak -e 's/\$(Header[^\$])\$/$1/g' *.{c,ct}', and then +edit the #includes in kadmin.c to make things compile. + +Unfortunately, this program is not exportable. diff --git a/eBones/kadmin/Makefile b/eBones/kadmin/Makefile new file mode 100644 index 000000000000..71dd36c767d1 --- /dev/null +++ b/eBones/kadmin/Makefile @@ -0,0 +1,19 @@ +# $Id$ + +BINDIR= /usr/lib +PROG= kadmin +SRCS= kadmin.c kadmin_cmds.c +CLEANFILES+= kadmin_cmds.c +CFLAGS+= -DPOSIX -I${.CURDIR}/../include -I${KRBOBJDIR} +CFLAGS+= -I${.CURDIR}/../libkadm +LDADD+= -L${KADMOBJDIR} -lkadm -L${KRBOBJDIR} -lkrb -L${DESOBJDIR} -ldes +LDADD+= -lss -lcom_err +NOMAN= # man page is in ../man + +kadmin_cmds.c: kadmin_cmds.ct + test -e kadmin_cmds.ct || ln -s ${.CURDIR}/kadmin_cmds.ct . + mk_cmds kadmin_cmds.ct + +.include + + diff --git a/eBones/kadmin/kadmin.c b/eBones/kadmin/kadmin.c new file mode 100644 index 000000000000..3d939bc058d4 --- /dev/null +++ b/eBones/kadmin/kadmin.c @@ -0,0 +1,626 @@ +/* + * $Source: /afs/athena.mit.edu/astaff/project/kerberos/src/kadmin/RCS/kadmin.c,v $ + * $Author: qjb $ + * + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * Copyright.MIT. + * + * Kerberos database administrator's tool. + * + * The default behavior of kadmin is if the -m option is given + * on the commandline, multiple requests are allowed to be given + * with one entry of the admin password (until the tickets expire). + * If you do not want this to be an available option, compile with + * NO_MULTIPLE defined. + */ + +#ifndef lint +static char rcsid_kadmin_c[] = +"BonesHeader: /afs/athena.mit.edu/astaff/project/kerberos/src/kadmin/RCS/kadmin.c,v 4.5 89/09/26 14:17:54 qjb Exp "; +#endif lint + +#include +#include +#include +#include +#include "krb_err.h" +#include "kadm.h" + +#define BAD_PW 1 +#define GOOD_PW 0 +#define FUDGE_VALUE 15 /* for ticket expiration time */ +#define PE_NO 0 +#define PE_YES 1 +#define PE_UNSURE 2 + +/* for get_password, whether it should do the swapping...necessary for + using vals structure, unnecessary for change_pw requests */ +#define DONTSWAP 0 +#define SWAP 1 + +extern int kadm_init_link(); +extern char *error_message(); +extern void krb_set_tkt_string(); + +static void do_init(); +void clean_up(); + +extern ss_request_table admin_cmds; + +static char myname[ANAME_SZ]; +static char default_realm[REALM_SZ]; /* default kerberos realm */ +static char krbrlm[REALM_SZ]; /* current realm being administered */ +#ifndef NO_MULTIPLE +static int multiple = 0; /* Allow multiple requests per ticket */ +#endif + +main(argc, argv) + int argc; + char *argv[]; +{ + int sci_idx; + int code; + char tktstring[MAXPATHLEN]; + + void quit(); + + sci_idx = ss_create_invocation("admin", "2.0", (char *) NULL, + &admin_cmds, &code); + if (code) { + ss_perror(sci_idx, code, "creating invocation"); + exit(1); + } + (void) sprintf(tktstring, "/tmp/tkt_adm_%d",getpid()); + krb_set_tkt_string(tktstring); + + do_init(argc, argv); + + printf("Welcome to the Kerberos Administration Program, version 2\n"); + printf("Type \"help\" if you need it.\n"); + ss_listen(sci_idx, &code); + printf("\n"); + quit(); + exit(0); +} + +int +setvals(vals, string) + Kadm_vals *vals; + char *string; +{ + char realm[REALM_SZ]; + int status = KADM_SUCCESS; + + bzero(vals, sizeof(*vals)); + bzero(realm, sizeof(realm)); + + SET_FIELD(KADM_NAME,vals->fields); + SET_FIELD(KADM_INST,vals->fields); + if (status = kname_parse(vals->name, vals->instance, realm, string)) { + printf("kerberos error: %s\n", krb_err_txt[status]); + return status; + } + if (!realm[0]) + strcpy(realm, default_realm); + if (strcmp(realm, krbrlm)) { + strcpy(krbrlm, realm); + if ((status = kadm_init_link(PWSERV_NAME, KRB_MASTER, krbrlm)) + != KADM_SUCCESS) + printf("kadm error for realm %s: %s\n", + krbrlm, error_message(status)); + } + if (status) + return 1; + else + return KADM_SUCCESS; +} + +void +change_password(argc, argv) + int argc; + char *argv[]; +{ + Kadm_vals old, new; + int status; + char pw_prompt[BUFSIZ]; + + if (argc != 2) { + printf("Usage: change_password loginname\n"); + return; + } + + if (setvals(&old, argv[1]) != KADM_SUCCESS) + return; + + new = old; + + SET_FIELD(KADM_DESKEY,new.fields); + + if (princ_exists(old.name, old.instance, krbrlm) != PE_NO) { + /* get the admin's password */ + if (get_admin_password() != GOOD_PW) + return; + + /* get the new password */ + (void) sprintf(pw_prompt, "New password for %s:", argv[1]); + + if (get_password(&new.key_low, &new.key_high, + pw_prompt, SWAP) == GOOD_PW) { + status = kadm_mod(&old, &new); + if (status == KADM_SUCCESS) { + printf("Password changed for %s.\n", argv[1]); + } else { + printf("kadmin: %s\nwhile changing password for %s", + error_message(status), argv[1]); + } + } else + printf("Error reading password; password unchanged\n"); + bzero((char *)&new, sizeof(new)); +#ifndef NO_MULTIPLE + if (!multiple) + clean_up(); +#endif + } + else + printf("kadmin: Principal does not exist.\n"); + return; +} + +/*ARGSUSED*/ +void +change_admin_password(argc, argv) + int argc; + char *argv[]; +{ + des_cblock newkey; + unsigned long low, high; + int status; + char prompt_pw[BUFSIZ]; + + if (argc != 1) { + printf("Usage: change_admin_password\n"); + return; + } + /* get the admin's password */ + if (get_admin_password() != GOOD_PW) + return; + + (void) sprintf(prompt_pw, "New password for %s.admin:",myname); + if (get_password(&low, &high, prompt_pw, DONTSWAP) == GOOD_PW) { + bcopy((char *)&low,(char *) newkey,4); + bcopy((char *)&high, (char *)(((long *) newkey) + 1),4); + low = high = 0L; + if ((status = kadm_change_pw(newkey)) == KADM_SUCCESS) + printf("Admin password changed\n"); + else + printf("kadm error: %s\n",error_message(status)); + bzero((char *)newkey, sizeof(newkey)); + } else + printf("Error reading password; password unchanged\n"); +#ifndef NO_MULTIPLE + if (!multiple) + clean_up(); +#endif + return; +} + +void +add_new_key(argc, argv) + int argc; + char *argv[]; +{ + Kadm_vals new; + char pw_prompt[BUFSIZ]; + int status; + + if (argc != 2) { + printf("Usage: add_new_key user_name.\n"); + return; + } + if (setvals(&new, argv[1]) != KADM_SUCCESS) + return; + + SET_FIELD(KADM_DESKEY,new.fields); + + if (princ_exists(new.name, new.instance, krbrlm) != PE_YES) { + /* get the admin's password */ + if (get_admin_password() != GOOD_PW) + return; + + /* get the new password */ + (void) sprintf(pw_prompt, "Password for %s:", argv[1]); + + if (get_password(&new.key_low, &new.key_high, + pw_prompt, SWAP) == GOOD_PW) { + status = kadm_add(&new); + if (status == KADM_SUCCESS) { + printf("%s added to database.\n", argv[1]); + } else { + printf("kadm error: %s\n",error_message(status)); + } + } else + printf("Error reading password; %s not added\n",argv[1]); + bzero((char *)&new, sizeof(new)); +#ifndef NO_MULTIPLE + if (!multiple) + clean_up(); +#endif + } + else + printf("kadmin: Principal already exists.\n"); + return; +} + +void +get_entry(argc, argv) + int argc; + char *argv[]; +{ + int status; + u_char fields[4]; + Kadm_vals vals; + + if (argc != 2) { + printf("Usage: get_entry username\n"); + return; + } + + bzero(fields, sizeof(fields)); + + SET_FIELD(KADM_NAME,fields); + SET_FIELD(KADM_INST,fields); + SET_FIELD(KADM_EXPDATE,fields); + SET_FIELD(KADM_ATTR,fields); + SET_FIELD(KADM_MAXLIFE,fields); + + if (setvals(&vals, argv[1]) != KADM_SUCCESS) + return; + + + if (princ_exists(vals.name, vals.instance, krbrlm) != PE_NO) { + /* get the admin's password */ + if (get_admin_password() != GOOD_PW) + return; + + if ((status = kadm_get(&vals, fields)) == KADM_SUCCESS) + prin_vals(&vals); + else + printf("kadm error: %s\n",error_message(status)); + +#ifndef NO_MULTIPLE + if (!multiple) + clean_up(); +#endif + } + else + printf("kadmin: Principal does not exist.\n"); + return; +} + + +void +help(argc, argv) + int argc; + char *argv[]; +{ + if (argc == 1) { + printf("Welcome to the Kerberos administration program."); + printf("Type \"?\" to get\n"); + printf("a list of requests that are available. You can"); + printf(" get help on each of\n"); + printf("the commands by typing \"help command_name\"."); + printf(" Some functions of this\n"); + printf("program will require an \"admin\" password"); + printf(" from you. This is a password\n"); + printf("private to you, that is used to authenticate"); + printf(" requests from this\n"); + printf("program. You can change this password with"); + printf(" the \"change_admin_password\"\n"); + printf("(or short form \"cap\") command. Good Luck! \n"); + } else if (!strcmp(argv[1], "change_password") || + !strcmp(argv[1], "cpw")) { + printf("Usage: change_password user_name.\n"); + printf("\n"); + printf("user_name is the name of the user whose password"); + printf(" you wish to change. \n"); + printf("His/her password is changed in the kerberos database\n"); + printf("When this command is issued, first the \"Admin\""); + printf(" password will be prompted\n"); + printf("for and if correct the user's new password will"); + printf(" be prompted for (twice with\n"); + printf("appropriate comparison). Note: No minimum password"); + printf(" length restrictions apply, but\n"); + printf("longer passwords are more secure.\n"); + } else if (!strcmp(argv[1], "change_admin_password") || + !strcmp(argv[1], "cap")) { + printf("Usage: change_admin_password.\n"); + printf("\n"); + printf("This command takes no arguments and is used"); + printf(" to change your private\n"); + printf("\"Admin\" password. It will first prompt for"); + printf(" the (current) \"Admin\"\n"); + printf("password and then ask for the new password"); + printf(" by prompting:\n"); + printf("\n"); + printf("New password for .admin:\n"); + printf("\n"); + printf("Enter the new admin password that you desire"); + printf(" (it will be asked for\n"); + printf("twice to avoid errors).\n"); + } else if (!strcmp(argv[1], "add_new_key") || + !strcmp(argv[1], "ank")) { + printf("Usage: add_new_key user_name.\n"); + printf("\n"); + printf("user_name is the name of a new user to put"); + printf(" in the kerberos database. Your\n"); + printf("\"Admin\" password and the user's password"); + printf(" are prompted for. The user's\n"); + printf("password will be asked for"); + printf(" twice to avoid errors.\n"); + } else if (!strcmp(argv[1], "get_entry") || + !strcmp(argv[1], "get")) { + printf("Usage: get_entry user_name.\n"); + printf("\n"); + printf("user_name is the name of a user whose"); + printf(" entry you wish to review. Your\n"); + printf("\"Admin\" password is prompted for. "); + printf(" The key field is not filled in, for\n"); + printf("security reasons.\n"); + } else if (!strcmp(argv[1], "destroy_tickets") || + !strcmp(argv[1], "dest")) { + printf("Usage: destroy_tickets\n"); + printf("\n"); + printf("Destroy your admin tickets. This will"); + printf(" cause you to be prompted for your\n"); + printf("admin password on your next request.\n"); + } else if (!strcmp(argv[1], "list_requests") || + !strcmp(argv[1], "lr") || + !strcmp(argv[1], "?")) { + printf("Usage: list_requests\n"); + printf("\n"); + printf("This command lists what other commands are"); + printf(" currently available.\n"); + } else if (!strcmp(argv[1], "exit") || + !strcmp(argv[1], "quit") || + !strcmp(argv[1], "q")) { + printf("Usage: quit\n"); + printf("\n"); + printf("This command exits this program.\n"); + } else { + printf("Sorry there is no such command as %s."); + printf(" Type \"help\" for more information. \n", argv[1]); + } + return; +} + +go_home(str,x) +char *str; +int x; +{ + fprintf(stderr, "%s: %s\n", str, error_message(x)); + clean_up(); + exit(1); +} + +static int inited = 0; + +void usage() +{ + fprintf(stderr, "Usage: kadmin [-u admin_name] [-r default_realm]"); +#ifndef NO_MULTIPLE + fprintf(stderr, " [-m]"); +#endif + fprintf(stderr, "\n"); +#ifndef NO_MULTIPLE + fprintf(stderr, " -m allows multiple admin requests to be "); + fprintf(stderr, "serviced with one entry of admin\n"); + fprintf(stderr, " password.\n"); +#endif + exit(1); +} + +static void +do_init(argc, argv) + int argc; + char *argv[]; +{ + struct passwd *pw; + extern char *optarg; + extern int optind; + int c; +#ifndef NO_MULTIPLE +#define OPTION_STRING "u:r:m" +#else +#define OPTION_STRING "u:r:" +#endif + + bzero(myname, sizeof(myname)); + + if (!inited) { + /* + * This is only as a default/initial realm; we don't care + * about failure. + */ + if (krb_get_lrealm(default_realm, 1) != KSUCCESS) + strcpy(default_realm, KRB_REALM); + + /* + * If we can reach the local realm, initialize to it. Otherwise, + * don't initialize. + */ + if (kadm_init_link(PWSERV_NAME, KRB_MASTER, krbrlm) != KADM_SUCCESS) + bzero(krbrlm, sizeof(krbrlm)); + else + strcpy(krbrlm, default_realm); + + while ((c = getopt(argc, argv, OPTION_STRING)) != EOF) + switch (c) { + case 'u': + strncpy(myname, optarg, sizeof(myname) - 1); + break; + case 'r': + bzero(default_realm, sizeof(default_realm)); + strncpy(default_realm, optarg, sizeof(default_realm) - 1); + break; +#ifndef NO_MULTIPLE + case 'm': + multiple++; + break; +#endif + default: + usage(); + break; + } + if (optind < argc) + usage(); + if (!myname[0]) { + pw = getpwuid((int) getuid()); + if (!pw) { + fprintf(stderr, + "You aren't in the password file. Who are you?\n"); + exit(1); + } + (void) strcpy(myname, pw->pw_name); + } + inited = 1; + } +} + +#ifdef NOENCRYPTION +#define read_long_pw_string placebo_read_pw_string +#else +#define read_long_pw_string des_read_pw_string +#endif +extern int read_long_pw_string(); + +int +get_admin_password() +{ + int status; + char admin_passwd[MAX_KPW_LEN]; /* Admin's password */ + int ticket_life = 1; /* minimum ticket lifetime */ +#ifndef NO_MULTIPLE + CREDENTIALS c; + + if (multiple) { + /* If admin tickets exist and are valid, just exit. */ + bzero(&c, sizeof(c)); + if (krb_get_cred(PWSERV_NAME, KADM_SINST, krbrlm, &c) == KSUCCESS) + /* + * If time is less than lifetime - FUDGE_VALUE after issue date, + * tickets will probably last long enough for the next + * transaction. + */ + if (time(0) < (c.issue_date + (5 * 60 * c.lifetime) - FUDGE_VALUE)) + return(KADM_SUCCESS); + ticket_life = DEFAULT_TKT_LIFE; + } +#endif + + if (princ_exists(myname, "admin", krbrlm) != PE_NO) { + if (read_long_pw_string(admin_passwd, sizeof(admin_passwd)-1, + "Admin password:", 0)) { + fprintf(stderr, "Error reading admin password.\n"); + goto bad; + } + status = krb_get_pw_in_tkt(myname, "admin", krbrlm, PWSERV_NAME, + KADM_SINST, ticket_life, admin_passwd); + bzero(admin_passwd, sizeof(admin_passwd)); + } + else + status = KDC_PR_UNKNOWN; + + switch(status) { + case GT_PW_OK: + return(GOOD_PW); + case KDC_PR_UNKNOWN: + printf("Principal %s.admin@%s does not exist.\n", myname, krbrlm); + goto bad; + case GT_PW_BADPW: + printf("Incorrect admin password.\n"); + goto bad; + default: + com_err("kadmin", status+krb_err_base, + "while getting password tickets"); + goto bad; + } + + bad: + bzero(admin_passwd, sizeof(admin_passwd)); + (void) dest_tkt(); + return(BAD_PW); +} + +void +clean_up() +{ + (void) dest_tkt(); + return; +} + +void +quit() +{ + printf("Cleaning up and exiting.\n"); + clean_up(); + exit(0); +} + +int +princ_exists(name, instance, realm) + char *name; + char *instance; + char *realm; +{ + int status; + + status = krb_get_pw_in_tkt(name, instance, realm, "krbtgt", realm, 1, ""); + + if ((status == KSUCCESS) || (status == INTK_BADPW)) + return(PE_YES); + else if (status == KDC_PR_UNKNOWN) + return(PE_NO); + else + return(PE_UNSURE); +} + +int +get_password(low, high, prompt, byteswap) +unsigned long *low, *high; +char *prompt; +int byteswap; +{ + char new_passwd[MAX_KPW_LEN]; /* new password */ + des_cblock newkey; + + do { + if (read_long_pw_string(new_passwd, sizeof(new_passwd)-1, prompt, 1)) + return(BAD_PW); + if (strlen(new_passwd) == 0) + printf("Null passwords are not allowed; try again.\n"); + } while (strlen(new_passwd) == 0); + +#ifdef NOENCRYPTION + bzero((char *) newkey, sizeof(newkey)); +#else + des_string_to_key(new_passwd, newkey); +#endif + bzero(new_passwd, sizeof(new_passwd)); + + bcopy((char *) newkey,(char *)low,4); + bcopy((char *)(((long *) newkey) + 1), (char *)high,4); + + bzero((char *) newkey, sizeof(newkey)); + +#ifdef NOENCRYPTION + *low = 1; +#endif + + if (byteswap != DONTSWAP) { + *low = htonl(*low); + *high = htonl(*high); + } + return(GOOD_PW); +} diff --git a/eBones/kadmin/kadmin_cmds.ct b/eBones/kadmin/kadmin_cmds.ct new file mode 100644 index 000000000000..92d31fd207a1 --- /dev/null +++ b/eBones/kadmin/kadmin_cmds.ct @@ -0,0 +1,41 @@ +# $Source: /mit/kerberos/src/kadmin/RCS/kadmin_cmds.ct,v $ +# $Author: jtkohl $ +# $Header: /mit/kerberos/src/kadmin/RCS/kadmin_cmds.ct,v 4.1 89/07/25 17:02:28 jtkohl Exp $ +# +# Copyright 1988 by the Massachusetts Institute of Technology. +# +# For copying and distribution information, please see the file +# . +# +# Command table for Kerberos administration tool +# + command_table admin_cmds; + + request change_password, + "Change a user's password", + change_password, cpw; + + request change_admin_password, "Change your admin password", + change_admin_password, cap; + + request add_new_key, "Add new user to kerberos database", + add_new_key, ank; + + request get_entry, "Get entry from kerberos database", + get_entry, get; + + request clean_up, "Destroy admin tickets", + destroy_tickets, dest; + + request help,"Request help with this program", + help; + +# list_requests is generic -- unrelated to Kerberos + + request ss_list_requests, "List available requests.", + list_requests, lr, "?"; + + request quit, "Exit program.", + quit, exit, q; + + end; diff --git a/eBones/usr.bin/kadmin/Makefile b/eBones/usr.bin/kadmin/Makefile new file mode 100644 index 000000000000..71dd36c767d1 --- /dev/null +++ b/eBones/usr.bin/kadmin/Makefile @@ -0,0 +1,19 @@ +# $Id$ + +BINDIR= /usr/lib +PROG= kadmin +SRCS= kadmin.c kadmin_cmds.c +CLEANFILES+= kadmin_cmds.c +CFLAGS+= -DPOSIX -I${.CURDIR}/../include -I${KRBOBJDIR} +CFLAGS+= -I${.CURDIR}/../libkadm +LDADD+= -L${KADMOBJDIR} -lkadm -L${KRBOBJDIR} -lkrb -L${DESOBJDIR} -ldes +LDADD+= -lss -lcom_err +NOMAN= # man page is in ../man + +kadmin_cmds.c: kadmin_cmds.ct + test -e kadmin_cmds.ct || ln -s ${.CURDIR}/kadmin_cmds.ct . + mk_cmds kadmin_cmds.ct + +.include + + diff --git a/eBones/usr.bin/kadmin/kadmin.c b/eBones/usr.bin/kadmin/kadmin.c new file mode 100644 index 000000000000..3d939bc058d4 --- /dev/null +++ b/eBones/usr.bin/kadmin/kadmin.c @@ -0,0 +1,626 @@ +/* + * $Source: /afs/athena.mit.edu/astaff/project/kerberos/src/kadmin/RCS/kadmin.c,v $ + * $Author: qjb $ + * + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * Copyright.MIT. + * + * Kerberos database administrator's tool. + * + * The default behavior of kadmin is if the -m option is given + * on the commandline, multiple requests are allowed to be given + * with one entry of the admin password (until the tickets expire). + * If you do not want this to be an available option, compile with + * NO_MULTIPLE defined. + */ + +#ifndef lint +static char rcsid_kadmin_c[] = +"BonesHeader: /afs/athena.mit.edu/astaff/project/kerberos/src/kadmin/RCS/kadmin.c,v 4.5 89/09/26 14:17:54 qjb Exp "; +#endif lint + +#include +#include +#include +#include +#include "krb_err.h" +#include "kadm.h" + +#define BAD_PW 1 +#define GOOD_PW 0 +#define FUDGE_VALUE 15 /* for ticket expiration time */ +#define PE_NO 0 +#define PE_YES 1 +#define PE_UNSURE 2 + +/* for get_password, whether it should do the swapping...necessary for + using vals structure, unnecessary for change_pw requests */ +#define DONTSWAP 0 +#define SWAP 1 + +extern int kadm_init_link(); +extern char *error_message(); +extern void krb_set_tkt_string(); + +static void do_init(); +void clean_up(); + +extern ss_request_table admin_cmds; + +static char myname[ANAME_SZ]; +static char default_realm[REALM_SZ]; /* default kerberos realm */ +static char krbrlm[REALM_SZ]; /* current realm being administered */ +#ifndef NO_MULTIPLE +static int multiple = 0; /* Allow multiple requests per ticket */ +#endif + +main(argc, argv) + int argc; + char *argv[]; +{ + int sci_idx; + int code; + char tktstring[MAXPATHLEN]; + + void quit(); + + sci_idx = ss_create_invocation("admin", "2.0", (char *) NULL, + &admin_cmds, &code); + if (code) { + ss_perror(sci_idx, code, "creating invocation"); + exit(1); + } + (void) sprintf(tktstring, "/tmp/tkt_adm_%d",getpid()); + krb_set_tkt_string(tktstring); + + do_init(argc, argv); + + printf("Welcome to the Kerberos Administration Program, version 2\n"); + printf("Type \"help\" if you need it.\n"); + ss_listen(sci_idx, &code); + printf("\n"); + quit(); + exit(0); +} + +int +setvals(vals, string) + Kadm_vals *vals; + char *string; +{ + char realm[REALM_SZ]; + int status = KADM_SUCCESS; + + bzero(vals, sizeof(*vals)); + bzero(realm, sizeof(realm)); + + SET_FIELD(KADM_NAME,vals->fields); + SET_FIELD(KADM_INST,vals->fields); + if (status = kname_parse(vals->name, vals->instance, realm, string)) { + printf("kerberos error: %s\n", krb_err_txt[status]); + return status; + } + if (!realm[0]) + strcpy(realm, default_realm); + if (strcmp(realm, krbrlm)) { + strcpy(krbrlm, realm); + if ((status = kadm_init_link(PWSERV_NAME, KRB_MASTER, krbrlm)) + != KADM_SUCCESS) + printf("kadm error for realm %s: %s\n", + krbrlm, error_message(status)); + } + if (status) + return 1; + else + return KADM_SUCCESS; +} + +void +change_password(argc, argv) + int argc; + char *argv[]; +{ + Kadm_vals old, new; + int status; + char pw_prompt[BUFSIZ]; + + if (argc != 2) { + printf("Usage: change_password loginname\n"); + return; + } + + if (setvals(&old, argv[1]) != KADM_SUCCESS) + return; + + new = old; + + SET_FIELD(KADM_DESKEY,new.fields); + + if (princ_exists(old.name, old.instance, krbrlm) != PE_NO) { + /* get the admin's password */ + if (get_admin_password() != GOOD_PW) + return; + + /* get the new password */ + (void) sprintf(pw_prompt, "New password for %s:", argv[1]); + + if (get_password(&new.key_low, &new.key_high, + pw_prompt, SWAP) == GOOD_PW) { + status = kadm_mod(&old, &new); + if (status == KADM_SUCCESS) { + printf("Password changed for %s.\n", argv[1]); + } else { + printf("kadmin: %s\nwhile changing password for %s", + error_message(status), argv[1]); + } + } else + printf("Error reading password; password unchanged\n"); + bzero((char *)&new, sizeof(new)); +#ifndef NO_MULTIPLE + if (!multiple) + clean_up(); +#endif + } + else + printf("kadmin: Principal does not exist.\n"); + return; +} + +/*ARGSUSED*/ +void +change_admin_password(argc, argv) + int argc; + char *argv[]; +{ + des_cblock newkey; + unsigned long low, high; + int status; + char prompt_pw[BUFSIZ]; + + if (argc != 1) { + printf("Usage: change_admin_password\n"); + return; + } + /* get the admin's password */ + if (get_admin_password() != GOOD_PW) + return; + + (void) sprintf(prompt_pw, "New password for %s.admin:",myname); + if (get_password(&low, &high, prompt_pw, DONTSWAP) == GOOD_PW) { + bcopy((char *)&low,(char *) newkey,4); + bcopy((char *)&high, (char *)(((long *) newkey) + 1),4); + low = high = 0L; + if ((status = kadm_change_pw(newkey)) == KADM_SUCCESS) + printf("Admin password changed\n"); + else + printf("kadm error: %s\n",error_message(status)); + bzero((char *)newkey, sizeof(newkey)); + } else + printf("Error reading password; password unchanged\n"); +#ifndef NO_MULTIPLE + if (!multiple) + clean_up(); +#endif + return; +} + +void +add_new_key(argc, argv) + int argc; + char *argv[]; +{ + Kadm_vals new; + char pw_prompt[BUFSIZ]; + int status; + + if (argc != 2) { + printf("Usage: add_new_key user_name.\n"); + return; + } + if (setvals(&new, argv[1]) != KADM_SUCCESS) + return; + + SET_FIELD(KADM_DESKEY,new.fields); + + if (princ_exists(new.name, new.instance, krbrlm) != PE_YES) { + /* get the admin's password */ + if (get_admin_password() != GOOD_PW) + return; + + /* get the new password */ + (void) sprintf(pw_prompt, "Password for %s:", argv[1]); + + if (get_password(&new.key_low, &new.key_high, + pw_prompt, SWAP) == GOOD_PW) { + status = kadm_add(&new); + if (status == KADM_SUCCESS) { + printf("%s added to database.\n", argv[1]); + } else { + printf("kadm error: %s\n",error_message(status)); + } + } else + printf("Error reading password; %s not added\n",argv[1]); + bzero((char *)&new, sizeof(new)); +#ifndef NO_MULTIPLE + if (!multiple) + clean_up(); +#endif + } + else + printf("kadmin: Principal already exists.\n"); + return; +} + +void +get_entry(argc, argv) + int argc; + char *argv[]; +{ + int status; + u_char fields[4]; + Kadm_vals vals; + + if (argc != 2) { + printf("Usage: get_entry username\n"); + return; + } + + bzero(fields, sizeof(fields)); + + SET_FIELD(KADM_NAME,fields); + SET_FIELD(KADM_INST,fields); + SET_FIELD(KADM_EXPDATE,fields); + SET_FIELD(KADM_ATTR,fields); + SET_FIELD(KADM_MAXLIFE,fields); + + if (setvals(&vals, argv[1]) != KADM_SUCCESS) + return; + + + if (princ_exists(vals.name, vals.instance, krbrlm) != PE_NO) { + /* get the admin's password */ + if (get_admin_password() != GOOD_PW) + return; + + if ((status = kadm_get(&vals, fields)) == KADM_SUCCESS) + prin_vals(&vals); + else + printf("kadm error: %s\n",error_message(status)); + +#ifndef NO_MULTIPLE + if (!multiple) + clean_up(); +#endif + } + else + printf("kadmin: Principal does not exist.\n"); + return; +} + + +void +help(argc, argv) + int argc; + char *argv[]; +{ + if (argc == 1) { + printf("Welcome to the Kerberos administration program."); + printf("Type \"?\" to get\n"); + printf("a list of requests that are available. You can"); + printf(" get help on each of\n"); + printf("the commands by typing \"help command_name\"."); + printf(" Some functions of this\n"); + printf("program will require an \"admin\" password"); + printf(" from you. This is a password\n"); + printf("private to you, that is used to authenticate"); + printf(" requests from this\n"); + printf("program. You can change this password with"); + printf(" the \"change_admin_password\"\n"); + printf("(or short form \"cap\") command. Good Luck! \n"); + } else if (!strcmp(argv[1], "change_password") || + !strcmp(argv[1], "cpw")) { + printf("Usage: change_password user_name.\n"); + printf("\n"); + printf("user_name is the name of the user whose password"); + printf(" you wish to change. \n"); + printf("His/her password is changed in the kerberos database\n"); + printf("When this command is issued, first the \"Admin\""); + printf(" password will be prompted\n"); + printf("for and if correct the user's new password will"); + printf(" be prompted for (twice with\n"); + printf("appropriate comparison). Note: No minimum password"); + printf(" length restrictions apply, but\n"); + printf("longer passwords are more secure.\n"); + } else if (!strcmp(argv[1], "change_admin_password") || + !strcmp(argv[1], "cap")) { + printf("Usage: change_admin_password.\n"); + printf("\n"); + printf("This command takes no arguments and is used"); + printf(" to change your private\n"); + printf("\"Admin\" password. It will first prompt for"); + printf(" the (current) \"Admin\"\n"); + printf("password and then ask for the new password"); + printf(" by prompting:\n"); + printf("\n"); + printf("New password for .admin:\n"); + printf("\n"); + printf("Enter the new admin password that you desire"); + printf(" (it will be asked for\n"); + printf("twice to avoid errors).\n"); + } else if (!strcmp(argv[1], "add_new_key") || + !strcmp(argv[1], "ank")) { + printf("Usage: add_new_key user_name.\n"); + printf("\n"); + printf("user_name is the name of a new user to put"); + printf(" in the kerberos database. Your\n"); + printf("\"Admin\" password and the user's password"); + printf(" are prompted for. The user's\n"); + printf("password will be asked for"); + printf(" twice to avoid errors.\n"); + } else if (!strcmp(argv[1], "get_entry") || + !strcmp(argv[1], "get")) { + printf("Usage: get_entry user_name.\n"); + printf("\n"); + printf("user_name is the name of a user whose"); + printf(" entry you wish to review. Your\n"); + printf("\"Admin\" password is prompted for. "); + printf(" The key field is not filled in, for\n"); + printf("security reasons.\n"); + } else if (!strcmp(argv[1], "destroy_tickets") || + !strcmp(argv[1], "dest")) { + printf("Usage: destroy_tickets\n"); + printf("\n"); + printf("Destroy your admin tickets. This will"); + printf(" cause you to be prompted for your\n"); + printf("admin password on your next request.\n"); + } else if (!strcmp(argv[1], "list_requests") || + !strcmp(argv[1], "lr") || + !strcmp(argv[1], "?")) { + printf("Usage: list_requests\n"); + printf("\n"); + printf("This command lists what other commands are"); + printf(" currently available.\n"); + } else if (!strcmp(argv[1], "exit") || + !strcmp(argv[1], "quit") || + !strcmp(argv[1], "q")) { + printf("Usage: quit\n"); + printf("\n"); + printf("This command exits this program.\n"); + } else { + printf("Sorry there is no such command as %s."); + printf(" Type \"help\" for more information. \n", argv[1]); + } + return; +} + +go_home(str,x) +char *str; +int x; +{ + fprintf(stderr, "%s: %s\n", str, error_message(x)); + clean_up(); + exit(1); +} + +static int inited = 0; + +void usage() +{ + fprintf(stderr, "Usage: kadmin [-u admin_name] [-r default_realm]"); +#ifndef NO_MULTIPLE + fprintf(stderr, " [-m]"); +#endif + fprintf(stderr, "\n"); +#ifndef NO_MULTIPLE + fprintf(stderr, " -m allows multiple admin requests to be "); + fprintf(stderr, "serviced with one entry of admin\n"); + fprintf(stderr, " password.\n"); +#endif + exit(1); +} + +static void +do_init(argc, argv) + int argc; + char *argv[]; +{ + struct passwd *pw; + extern char *optarg; + extern int optind; + int c; +#ifndef NO_MULTIPLE +#define OPTION_STRING "u:r:m" +#else +#define OPTION_STRING "u:r:" +#endif + + bzero(myname, sizeof(myname)); + + if (!inited) { + /* + * This is only as a default/initial realm; we don't care + * about failure. + */ + if (krb_get_lrealm(default_realm, 1) != KSUCCESS) + strcpy(default_realm, KRB_REALM); + + /* + * If we can reach the local realm, initialize to it. Otherwise, + * don't initialize. + */ + if (kadm_init_link(PWSERV_NAME, KRB_MASTER, krbrlm) != KADM_SUCCESS) + bzero(krbrlm, sizeof(krbrlm)); + else + strcpy(krbrlm, default_realm); + + while ((c = getopt(argc, argv, OPTION_STRING)) != EOF) + switch (c) { + case 'u': + strncpy(myname, optarg, sizeof(myname) - 1); + break; + case 'r': + bzero(default_realm, sizeof(default_realm)); + strncpy(default_realm, optarg, sizeof(default_realm) - 1); + break; +#ifndef NO_MULTIPLE + case 'm': + multiple++; + break; +#endif + default: + usage(); + break; + } + if (optind < argc) + usage(); + if (!myname[0]) { + pw = getpwuid((int) getuid()); + if (!pw) { + fprintf(stderr, + "You aren't in the password file. Who are you?\n"); + exit(1); + } + (void) strcpy(myname, pw->pw_name); + } + inited = 1; + } +} + +#ifdef NOENCRYPTION +#define read_long_pw_string placebo_read_pw_string +#else +#define read_long_pw_string des_read_pw_string +#endif +extern int read_long_pw_string(); + +int +get_admin_password() +{ + int status; + char admin_passwd[MAX_KPW_LEN]; /* Admin's password */ + int ticket_life = 1; /* minimum ticket lifetime */ +#ifndef NO_MULTIPLE + CREDENTIALS c; + + if (multiple) { + /* If admin tickets exist and are valid, just exit. */ + bzero(&c, sizeof(c)); + if (krb_get_cred(PWSERV_NAME, KADM_SINST, krbrlm, &c) == KSUCCESS) + /* + * If time is less than lifetime - FUDGE_VALUE after issue date, + * tickets will probably last long enough for the next + * transaction. + */ + if (time(0) < (c.issue_date + (5 * 60 * c.lifetime) - FUDGE_VALUE)) + return(KADM_SUCCESS); + ticket_life = DEFAULT_TKT_LIFE; + } +#endif + + if (princ_exists(myname, "admin", krbrlm) != PE_NO) { + if (read_long_pw_string(admin_passwd, sizeof(admin_passwd)-1, + "Admin password:", 0)) { + fprintf(stderr, "Error reading admin password.\n"); + goto bad; + } + status = krb_get_pw_in_tkt(myname, "admin", krbrlm, PWSERV_NAME, + KADM_SINST, ticket_life, admin_passwd); + bzero(admin_passwd, sizeof(admin_passwd)); + } + else + status = KDC_PR_UNKNOWN; + + switch(status) { + case GT_PW_OK: + return(GOOD_PW); + case KDC_PR_UNKNOWN: + printf("Principal %s.admin@%s does not exist.\n", myname, krbrlm); + goto bad; + case GT_PW_BADPW: + printf("Incorrect admin password.\n"); + goto bad; + default: + com_err("kadmin", status+krb_err_base, + "while getting password tickets"); + goto bad; + } + + bad: + bzero(admin_passwd, sizeof(admin_passwd)); + (void) dest_tkt(); + return(BAD_PW); +} + +void +clean_up() +{ + (void) dest_tkt(); + return; +} + +void +quit() +{ + printf("Cleaning up and exiting.\n"); + clean_up(); + exit(0); +} + +int +princ_exists(name, instance, realm) + char *name; + char *instance; + char *realm; +{ + int status; + + status = krb_get_pw_in_tkt(name, instance, realm, "krbtgt", realm, 1, ""); + + if ((status == KSUCCESS) || (status == INTK_BADPW)) + return(PE_YES); + else if (status == KDC_PR_UNKNOWN) + return(PE_NO); + else + return(PE_UNSURE); +} + +int +get_password(low, high, prompt, byteswap) +unsigned long *low, *high; +char *prompt; +int byteswap; +{ + char new_passwd[MAX_KPW_LEN]; /* new password */ + des_cblock newkey; + + do { + if (read_long_pw_string(new_passwd, sizeof(new_passwd)-1, prompt, 1)) + return(BAD_PW); + if (strlen(new_passwd) == 0) + printf("Null passwords are not allowed; try again.\n"); + } while (strlen(new_passwd) == 0); + +#ifdef NOENCRYPTION + bzero((char *) newkey, sizeof(newkey)); +#else + des_string_to_key(new_passwd, newkey); +#endif + bzero(new_passwd, sizeof(new_passwd)); + + bcopy((char *) newkey,(char *)low,4); + bcopy((char *)(((long *) newkey) + 1), (char *)high,4); + + bzero((char *) newkey, sizeof(newkey)); + +#ifdef NOENCRYPTION + *low = 1; +#endif + + if (byteswap != DONTSWAP) { + *low = htonl(*low); + *high = htonl(*high); + } + return(GOOD_PW); +} diff --git a/eBones/usr.bin/kadmin/kadmin_cmds.ct b/eBones/usr.bin/kadmin/kadmin_cmds.ct new file mode 100644 index 000000000000..92d31fd207a1 --- /dev/null +++ b/eBones/usr.bin/kadmin/kadmin_cmds.ct @@ -0,0 +1,41 @@ +# $Source: /mit/kerberos/src/kadmin/RCS/kadmin_cmds.ct,v $ +# $Author: jtkohl $ +# $Header: /mit/kerberos/src/kadmin/RCS/kadmin_cmds.ct,v 4.1 89/07/25 17:02:28 jtkohl Exp $ +# +# Copyright 1988 by the Massachusetts Institute of Technology. +# +# For copying and distribution information, please see the file +# . +# +# Command table for Kerberos administration tool +# + command_table admin_cmds; + + request change_password, + "Change a user's password", + change_password, cpw; + + request change_admin_password, "Change your admin password", + change_admin_password, cap; + + request add_new_key, "Add new user to kerberos database", + add_new_key, ank; + + request get_entry, "Get entry from kerberos database", + get_entry, get; + + request clean_up, "Destroy admin tickets", + destroy_tickets, dest; + + request help,"Request help with this program", + help; + +# list_requests is generic -- unrelated to Kerberos + + request ss_list_requests, "List available requests.", + list_requests, lr, "?"; + + request quit, "Exit program.", + quit, exit, q; + + end;