diff options
author | Paul Park <pjpark@mit.edu> | 1995-05-09 19:58:24 +0000 |
---|---|---|
committer | Paul Park <pjpark@mit.edu> | 1995-05-09 19:58:24 +0000 |
commit | 29559af8f52619d4c1431a891fee4e0c3a8f243d (patch) | |
tree | bc31d520112781128d1fc53ff5410b4ac1befbfa /src/kadmin/v5client | |
parent | 704ff3380764cc524d50bcf728822b530656354d (diff) | |
download | krb5-29559af8f52619d4c1431a891fee4e0c3a8f243d.tar.gz krb5-29559af8f52619d4c1431a891fee4e0c3a8f243d.tar.xz krb5-29559af8f52619d4c1431a891fee4e0c3a8f243d.zip |
Checkin new administrative client
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@5782 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/kadmin/v5client')
-rw-r--r-- | src/kadmin/v5client/.Sanitize | 43 | ||||
-rw-r--r-- | src/kadmin/v5client/.cvsignore | 1 | ||||
-rw-r--r-- | src/kadmin/v5client/ChangeLog | 4 | ||||
-rw-r--r-- | src/kadmin/v5client/Makefile.in | 53 | ||||
-rw-r--r-- | src/kadmin/v5client/configure.in | 16 | ||||
-rw-r--r-- | src/kadmin/v5client/convert.c | 623 | ||||
-rw-r--r-- | src/kadmin/v5client/kadmin5.M | 251 | ||||
-rw-r--r-- | src/kadmin/v5client/kadmin5.c | 1434 | ||||
-rw-r--r-- | src/kadmin/v5client/kadmin5.h | 97 | ||||
-rw-r--r-- | src/kadmin/v5client/kadmin5_ct.ct | 76 | ||||
-rw-r--r-- | src/kadmin/v5client/network.c | 321 | ||||
-rw-r--r-- | src/kadmin/v5client/ss_wrapper.c | 61 |
12 files changed, 2980 insertions, 0 deletions
diff --git a/src/kadmin/v5client/.Sanitize b/src/kadmin/v5client/.Sanitize new file mode 100644 index 0000000000..f85c410099 --- /dev/null +++ b/src/kadmin/v5client/.Sanitize @@ -0,0 +1,43 @@ +# Sanitize.in for Kerberos V5 + +# Each directory to survive it's way into a release will need a file +# like this one called "./.Sanitize". All keyword lines must exist, +# and must exist in the order specified by this file. Each directory +# in the tree will be processed, top down, in the following order. + +# Hash started lines like this one are comments and will be deleted +# before anything else is done. Blank lines will also be squashed +# out. + +# The lines between the "Do-first:" line and the "Things-to-keep:" +# line are executed as a /bin/sh shell script before anything else is +# done in this + +Do-first: + +# All files listed between the "Things-to-keep:" line and the +# "Files-to-sed:" line will be kept. All other files will be removed. +# Directories listed in this section will have their own Sanitize +# called. Directories not listed will be removed in their entirety +# with rm -rf. + +Things-to-keep: + +.cvsignore +ChangeLog +Makefile.in +configure +configure.in +convert.c +kadmin5.M +kadmin5.c +kadmin5.h +kadmin5_ct.ct +network.c +ss_wrapper.c + +Things-to-lose: + +Do-last: + +# End of file. diff --git a/src/kadmin/v5client/.cvsignore b/src/kadmin/v5client/.cvsignore new file mode 100644 index 0000000000..e8c05a6b13 --- /dev/null +++ b/src/kadmin/v5client/.cvsignore @@ -0,0 +1 @@ +configure diff --git a/src/kadmin/v5client/ChangeLog b/src/kadmin/v5client/ChangeLog new file mode 100644 index 0000000000..bafbabddd6 --- /dev/null +++ b/src/kadmin/v5client/ChangeLog @@ -0,0 +1,4 @@ + +Tue May 9 15:56:40 EDT 1995 Paul Park (pjpark@mit.edu) + First checkin of new administrative client. + diff --git a/src/kadmin/v5client/Makefile.in b/src/kadmin/v5client/Makefile.in new file mode 100644 index 0000000000..08db709705 --- /dev/null +++ b/src/kadmin/v5client/Makefile.in @@ -0,0 +1,53 @@ +CFLAGS = $(CCOPTS) $(DEFS) $(LOCALINCLUDE) +LDFLAGS = -g + +COMERRLIB=$(BUILDTOP)/util/et/libcom_err.a +SSLIB=$(BUILDTOP)/util/ss/libss.a +DBMLIB= +KDBLIB=$(TOPLIBD)/libkdb5.a +DEPKDBLIB=$(TOPLIBD)/libkdb5.a +KADMLIB=$(TOPLIBD)/libkadm.a +DEPKADMLIB=$(TOPLIBD)/libkadm.a + +all:: + +KLIB = $(TOPLIBD)/libkrb5.a $(KRB4_LIB) $(TOPLIBD)/libcrypto.a $(SSLIB) $(COMERRLIB) $(DBMLIB) +DEPKLIB = $(TOPLIBD)/libkrb5.a $(TOPLIBD)/libcrypto.a $(SSLIB) $(COMERRLIB) $(DBMLIB) + + +DEPLIBS = $(DEPKDBLIB) $(DEPKLIB) $(DEPKADMLIB) +LOCAL_LIBRARIES = $(KDBLIB) $(KADMLIB) $(KLIB) +LOCALINCLUDE= + +OBJS= kadmin5.o \ + kadmin5_ct.o \ + network.o \ + convert.o \ + ss_wrapper.o \ + $(LIBOBJS) + +SRCS= $(srcdir)/kadmin5.c \ + $(srcdir)/kadmin5_ct.c \ + $(srcdir)/ss_wrapper.c + +all:: kadmin5 + +kadmin5: kadmin5.o $(DEPLIBS) $(OBJS) + $(CC) $(CFLAGS) -o kadmin5 $(OBJS) $(LOCAL_LIBRARIES) $(LIBS) + +install:: + $(INSTALL_PROGRAM) kadmin5 ${DESTDIR}$(ADMIN_BINDIR)/kadmin5 + $(INSTALL_DATA) $(srcdir)/kadmin5.M ${DESTDIR}$(ADMIN_MANDIR)/kadmin5.8 + +# needed until we run makedepend +kadmin5_ct.c: kadmin5_ct.ct + +kadmin5_ct.o: kadmin5_ct.c + +clean:: + $(RM) kadmin5_ct.c + +depend:: kadmin5_ct.c + +clean:: + $(RM) kadmin5 diff --git a/src/kadmin/v5client/configure.in b/src/kadmin/v5client/configure.in new file mode 100644 index 0000000000..d870e25101 --- /dev/null +++ b/src/kadmin/v5client/configure.in @@ -0,0 +1,16 @@ +AC_INIT(kadmin5.c) +WITH_CCOPTS +CONFIG_RULES +AC_SET_BUILDTOP +AC_PROG_INSTALL +AC_PROG_YACC +AC_HAVE_HEADERS(pwd.h) +AC_HAVE_FUNCS(strptime re_comp regcomp getcwd) +AC_CONST +WITH_NETLIB +AC_CHECK_LIB(ndbm,main) +AC_CHECK_LIB(dbm,main) +SS_RULES +KRB_INCLUDE +WITH_KRB5ROOT +V5_AC_OUTPUT_MAKEFILE diff --git a/src/kadmin/v5client/convert.c b/src/kadmin/v5client/convert.c new file mode 100644 index 0000000000..dc9dceda1f --- /dev/null +++ b/src/kadmin/v5client/convert.c @@ -0,0 +1,623 @@ +/* + * kadmin/v5client/convert.c + * + * Copyright 1995 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ + +/* + * convert.c - Perform various conversions for kadmin5. + */ +#include "k5-int.h" +#include "adm.h" +#include "kadmin5.h" + +/* Size of static buffers for conversions */ +#define BUFFER_SIZE 512 + +/* Forward declarations */ +static krb5_boolean get_integer PROTOTYPE((char *, const char *, void *)); +static krb5_boolean get_datestring PROTOTYPE((char *, const char *, void *)); +static krb5_boolean get_saltstring PROTOTYPE((char *, const char *, void *)); +/* static krb5_boolean get_deltastring PROTOTYPE((char *, const char *, void *)); */ + +/* Local data structure for flag to string and option to flag operations */ +struct flagtable { + krb5_flags f_value; + const char *f_string; + const char *f_option; + krb5_boolean f_sense; +}; + +/* Local data structure for option parsing */ +struct opttable { + krb5_ui_4 o_value; + const char *o_option; + krb5_boolean (*o_dispatch) PROTOTYPE((char *, + const char *, + void *)); + void *o_arg; +}; + +/* + * Static strings. + */ +static const char *dt_output_fmt = "%d %s %d:%d:%d"; +static const char *dt_output_noday_fmt = "%d:%d:%d"; +static const char *dt_output_donly_fmt = "%d %s"; +static const char *dt_day_singular = "day"; +static const char *dt_day_plural = "days"; +static const char *dbflag_bit_fmt = "Bit-%d"; +static const char *salt_norm_name = "Normal"; +static const char *salt_v4_name = "Kerberos V4"; +static const char *salt_norealm_name = "NoRealm"; +static const char *salt_orealm_name = "OnlyRealm"; +static const char *salt_special_name = "Special"; +static const char *salt_ufo_fmt = "Unknown(%d)"; +static const char *salt_norm_spec = "v5"; +static const char *salt_v4_spec = "v4"; +static const char *salt_norealm_spec = "norealm"; +static const char *salt_orealm_spec = "onlyrealm"; +static const char *salt_special_spec = "special"; +static const char *o_not_int_fmt = "%s does not specify an integer value for %s"; +static const char *o_val_req_fmt = "value required for %s"; +static const char *o_not_time_fmt = "%s does not specify a valid time value for %s"; +static const char *o_not_salt_fmt = "%s does not specify a valid salt type for %s"; +static const char *o_opt_ufo_fmt = "%s is unrecognized"; +static const char *help_option_head = "%s: valid options are:\n"; +static const char *help_flag_head = "%s: additional principal flags are:\n"; + +static const char flg_out_pdate[] = "Not Postdateable"; +static const char flg_in_pdate[] = "postdateable"; +static const char flg_out_fwd[] = "Not Forwardable"; +static const char flg_in_fwd[] = "forwardable"; +static const char flg_out_tgs[] = "No TGT-based Requests"; +static const char flg_in_tgs[] = "tgt_req"; +static const char flg_out_renew[] = "Not Renewable"; +static const char flg_in_renew[] = "renewable"; +static const char flg_out_proxy[] = "Not Proxiable"; +static const char flg_in_proxy[] = "proxiable"; +static const char flg_out_dskey[] = "No DUP_SKEY Requests"; +static const char flg_in_dskey[] = "dup_skey"; +static const char flg_out_tix[] = "All Tickets Disallowed"; +static const char flg_in_tix[] = "allow_tickets"; +static const char flg_out_pauth[] = "Preauthorization Required"; +static const char flg_in_pauth[] = "preauth"; +static const char flg_out_hauth[] = "HW Authorization Required"; +static const char flg_in_hauth[] = "hwauth"; +static const char flg_out_pwchg[] = "Password Change Required"; +static const char flg_in_pwchg[] = "pwchange_req"; +static const char flg_out_svr[] = "Server Disallowed"; +static const char flg_in_svr[] = "server"; +static const char flg_out_pwsvc[] = "Password Changing Service"; +static const char flg_in_pwsvc[] = "pwservice"; +static const char flg_out_md5[] = "DES MD5 supported"; +static const char flg_in_md5[] = "md5"; + +static const char opt_kvno[] = "kvno"; +static const char opt_maxlife[] = "maxlife"; +static const char opt_maxrenewlife[] = "maxrenewlife"; +static const char opt_expiration[] = "expiration"; +static const char opt_pwexpiration[] = "pwexpiration"; +static const char opt_randomkey[] = "randomkey"; +static const char opt_salttype[] = "salttype"; + +/* + * Formatting buffers + */ +static char dt_outbuf[BUFFER_SIZE]; +static char abs_outbuf[BUFFER_SIZE]; +static char db_outbuf[BUFFER_SIZE]; +static char salt_outbuf[BUFFER_SIZE]; +static krb5_db_entry opt_dbent; + +/* Flag to string and option to flag table */ +static struct flagtable flagtable[] = { +/* flag output string input option sen */ +{ KRB5_KDB_DISALLOW_POSTDATED, flg_out_pdate, flg_in_pdate, 0 }, +{ KRB5_KDB_DISALLOW_FORWARDABLE, flg_out_fwd, flg_in_fwd, 0 }, +{ KRB5_KDB_DISALLOW_TGT_BASED, flg_out_tgs, flg_in_tgs, 0 }, +{ KRB5_KDB_DISALLOW_RENEWABLE, flg_out_renew, flg_in_renew, 0 }, +{ KRB5_KDB_DISALLOW_PROXIABLE, flg_out_proxy, flg_in_proxy, 0 }, +{ KRB5_KDB_DISALLOW_DUP_SKEY, flg_out_dskey, flg_in_dskey, 0 }, +{ KRB5_KDB_DISALLOW_ALL_TIX, flg_out_tix, flg_in_tix, 0 }, +{ KRB5_KDB_REQUIRES_PRE_AUTH, flg_out_pauth, flg_in_pauth, 1 }, +{ KRB5_KDB_REQUIRES_HW_AUTH, flg_out_hauth, flg_in_hauth, 1 }, +{ KRB5_KDB_REQUIRES_PWCHANGE, flg_out_pwchg, flg_in_pwchg, 1 }, +{ KRB5_KDB_DISALLOW_SVR, flg_out_svr, flg_in_svr, 0 }, +{ KRB5_KDB_PWCHANGE_SERVICE, flg_out_pwsvc, flg_in_pwsvc, 1 }, +{ KRB5_KDB_SUPPORT_DESMD5, flg_out_md5, flg_in_md5, 1 }, +}; + +/* Option string parse table */ +static struct opttable opttable[] = { +/* flag option dispatch routine + argument */ +{ KRB5_ADM_M_KVNO, opt_kvno, get_integer, + (void *) &opt_dbent.kvno }, +{ KRB5_ADM_M_MAXLIFE, opt_maxlife, get_integer, + (void *) &opt_dbent.max_life }, +{ KRB5_ADM_M_MAXRENEWLIFE, opt_maxrenewlife, get_integer, + (void *) &opt_dbent.max_renewable_life }, +{ KRB5_ADM_M_EXPIRATION, opt_expiration, get_datestring, + (void *) &opt_dbent.expiration }, +{ KRB5_ADM_M_PWEXPIRATION, opt_pwexpiration, get_datestring, + (void *) &opt_dbent.pw_expiration }, +{ KRB5_ADM_M_SALTTYPE, opt_salttype, get_saltstring, + (void *) &opt_dbent }, +}; + +/* strptime formats table to recognize absolute dates */ +/* + * Recognize character string times of the format. + * 1) yymmddhhmmss (doesn't work under OSF/1) + * 2) yy.mm.dd.hh.mm.ss + * 3) yymmddhhmm + * 4) hhmmss (relative to today) + * 5) hhmm (relative to today) + * 6) hh:mm:ss (relative to today) + * 7) hh:mm (relative to today) + * 8) locale-dependent short format (mm/dd/yy:hh:mm:ss in usa) + * 9) dd-text_month-yyyy:hh:mm:ss + * 10) dd-text_month-yyyy:hh:mm + */ +static char *absformats[] = +{ + "%y%m%d%H%M%S", /* yymmddhhmmss */ + "%y.%m.%d.%H.%M.%S", /* yy.mm.dd.hh.mm.ss */ + "%y%m%d%H%M", /* yymmddhhmm */ + "%H%M%S", /* hhmmss */ + "%H%M", /* hhmm */ + "%T", /* hh:mm:ss */ + "%R", /* hh:mm */ + "%x:%X", /* locale-dependent short format */ + "%d-%b-%Y:T", /* dd-month-yyyy:hh:mm:ss */ + "%d-%b-%Y:R" /* dd-month-yyyy:hh:mm */ +}; + +#if !HAVE_STRPTIME +/* + * Rudimentary version of strptime for systems which don't have it. + */ +static char * +strptime( char *buf, char *format, struct tm *tm ) +{ + int year, month, day, hour, minute, second; + char *bp; + + /* + * We only understand two formats: + * %y%m%d%H%M%S + * This is fixed length, 12 characters. + * %y.%m.%d.%H.%M.%S + * This is fixed length, 17 characters. + */ + bp = (char *) NULL; + if ((strcmp(format,"%y%m%d%H%M%S") == 0) && + (sscanf(buf, "%02d%02d%02d%02d%02d%02d", + &year, &month, &day, &hour, &minute, &second) == 6)) { + tm->tm_year = year; + tm->tm_mon = month - 1; + tm->tm_mday = day; + tm->tm_hour = hour; + tm->tm_min = minute; + tm->tm_sec = second; + bp = &buf[12]; + } + else { + if ((strcmp(format,"%y.%m.%d.%H.%M.%S") == 0) && + (sscanf(buf, "%02d.%02d.%02d.%02d.%02d.%02d", + &year, &month, &day, &hour, &minute, &second) == 6)) { + tm->tm_year = year; + tm->tm_mon = month - 1; + tm->tm_mday = day; + tm->tm_hour = hour; + tm->tm_min = minute; + tm->tm_sec = second; + bp = &buf[17]; + } + } + return(bp); +} +#endif /* HAVE_STRPTIME */ + +/* + * delta2string() - Convert delta time value to string. + * + * WARNING: the returned output buffer is static. + */ +char * +delta2string(dt) + krb5_deltat dt; +{ + int days, hours, minutes, seconds; + + days = dt / (24*3600); + dt %= 24 * 3600; + hours = dt / 3600; + dt %= 3600; + minutes = dt / 60; + dt %= 60; + seconds = dt; + + if (days) { + if (hours || minutes || seconds) + sprintf(dt_outbuf, dt_output_fmt, days, + ((days > 1) ? dt_day_plural : dt_day_singular), + hours, minutes, seconds); + else + sprintf(dt_outbuf, dt_output_donly_fmt, days, + ((days > 1) ? dt_day_plural : dt_day_singular)); + } + else + sprintf(dt_outbuf, dt_output_noday_fmt, hours, minutes, seconds); + return(dt_outbuf); +} + +/* + * abs2string() - Convert absolute Kerberos time to string. + * + * WARNING: the returned output buffer is static. + */ +char * +abs2string(t) + krb5_timestamp t; +{ + /* + * ctime returns <datestring>\n\0. + */ + strcpy(abs_outbuf, ctime((time_t *) &t)); + abs_outbuf[strlen(abs_outbuf)-1] = '\0'; + return(abs_outbuf); +} + +/* + * dbflags2string() - Convert database flags to string. + * + * WARNING: the returned output buffer is static. + */ +char * +dbflags2string(f) + krb5_flags f; +{ + int bit; + int i; + krb5_flags mask; + struct flagtable *fent; + + mask = 1; + db_outbuf[0] = '\0'; + for (bit=0; bit<(sizeof(krb5_flags)*8); bit++) { + if (f & mask) { + /* Bit is set, find it in the flag table */ + fent = (struct flagtable *) NULL; + for (i=0; i<(sizeof(flagtable)/sizeof(flagtable[0])); i++) { + if (mask == flagtable[i].f_value) { + fent = &flagtable[i]; + break; + } + } + + /* Either print out table value or unknown bit value. */ + if (fent) + strcat(db_outbuf, fent->f_string); + else + sprintf(&db_outbuf[strlen(db_outbuf)], + dbflag_bit_fmt, bit); + strcat(db_outbuf, ", "); + } + mask <<= 1; + } + /* + * Clean up our trailing comma-space if present. + */ + if (strlen(db_outbuf) > 2) + db_outbuf[strlen(db_outbuf)-2] = '\0'; + return(db_outbuf); +} + +/* + * salt2string() - Convert salt type to string. + * + * WARNING: the returned output buffer is static. + */ +char * +salt2string(stype) + krb5_int32 stype; +{ + switch (stype) { + case KRB5_KDB_SALTTYPE_NORMAL: + strcpy(salt_outbuf, salt_norm_name); + break; + case KRB5_KDB_SALTTYPE_V4: + strcpy(salt_outbuf, salt_v4_name); + break; + case KRB5_KDB_SALTTYPE_NOREALM: + strcpy(salt_outbuf, salt_norealm_name); + break; + case KRB5_KDB_SALTTYPE_ONLYREALM: + strcpy(salt_outbuf, salt_orealm_name); + break; + case KRB5_KDB_SALTTYPE_SPECIAL: + strcpy(salt_outbuf, salt_special_name); + break; + default: + sprintf(salt_outbuf, salt_ufo_fmt, stype); + break; + } + return(salt_outbuf); +} + +/* + * string2salt() - Convert string to salt type. + */ +static krb5_int32 +string2salt(sstring, goodp) + char *sstring; + krb5_boolean *goodp; +{ + if (!strcasecmp(sstring, salt_norm_spec)) { + *goodp = 1; + return(KRB5_KDB_SALTTYPE_NORMAL); + } + else if (!strcasecmp(sstring, salt_v4_spec)) { + *goodp = 1; + return(KRB5_KDB_SALTTYPE_V4); + } + else if (!strcasecmp(sstring, salt_norealm_spec)) { + *goodp = 1; + return(KRB5_KDB_SALTTYPE_NOREALM); + } + else if (!strcasecmp(sstring, salt_orealm_spec)) { + *goodp = 1; + return(KRB5_KDB_SALTTYPE_ONLYREALM); + } + else if (!strcasecmp(sstring, salt_special_spec)) { + *goodp = 1; + return(KRB5_KDB_SALTTYPE_SPECIAL); + } + else { + *goodp = 0; + return(-1); + } +} + +/* + * get_integer() - Test for an option and its integer value. + */ +static krb5_boolean +get_integer(arg, value, optp) + char *arg; + const char *value; + void *optp; +{ + int index; + krb5_boolean good; + krb5_int32 *intp; + + intp = (krb5_int32 *) optp; + good = 0; + /* Match the value */ + if (!strncasecmp(arg, value, strlen(value))) { + /* If we have a match, look for value=<value> */ + index = strlen(value); + if (arg[index] == '=') { + /* Match one integer argument */ + if (sscanf(&arg[index+1], "%d", intp) == 1) + good = 1; + else + com_err(requestname, 0, o_not_int_fmt, &arg[index+1], value); + } + else + com_err(requestname, 0, o_val_req_fmt, value); + } + return(good); +} + +/* + * get_datestring() - Test for an option and its date value + */ +static krb5_boolean +get_datestring(arg, value, optp) + char *arg; + const char *value; + void *optp; +{ + int index; + krb5_timestamp *tp; + krb5_boolean good, found; + char *retval; + int ti; + time_t now; + struct tm *tmp; + struct tm timebuf; + + tp = (krb5_timestamp *) optp; + good = 0; + found = 0; + /* Match the value */ + if (!strncasecmp(arg, value, strlen(value))) { + /* If we have a match, look for value=<value> */ + index = strlen(value); + if (arg[index] == '=') { + /* Prime with current time */ + now = time((time_t *) NULL); + tmp = localtime(&now); + memcpy(&timebuf, tmp, sizeof(struct tm)); + /* Match date argument */ + for (ti=0; ti<(sizeof(absformats)/sizeof(absformats[0])); ti++) { + if (strptime(&arg[index+1], absformats[ti], &timebuf)) { + found = 1; + break; + } + memcpy(&timebuf, tmp, sizeof(struct tm)); + } + if (found) { + *tp = (krb5_timestamp) mktime(&timebuf); + good = 1; + } + else + com_err(requestname, 0, o_not_time_fmt, &arg[index+1], value); + } + else + com_err(requestname, 0, o_val_req_fmt, value); + } + return(good); +} + +/* + * get_saltstring() - Test for an option and its salt type value + */ +static krb5_boolean +get_saltstring(arg, value, optp) + char *arg; + const char *value; + void *optp; +{ + int index; + krb5_db_entry *dbentp; + krb5_boolean good; + char *s1, *s2; + + dbentp = (krb5_db_entry *) optp; + good = 0; + /* Match the value */ + if (!strncasecmp(arg, value, strlen(value))) { + /* If we have a match, look for value=<value> */ + index = strlen(value); + if (arg[index] == '=') { + if (s2 = strchr(&arg[index+1], (int) ',')) { + *s2 = '\0'; + s2++; + } + s1 = &arg[index+1]; + dbentp->salt_type = string2salt(s1, &good); + if (good) { + if (s2) { + dbentp->alt_salt_type = string2salt(s2, &good); + if (!good) + com_err(requestname, 0, o_not_salt_fmt, s2, value); + } + else + dbentp->alt_salt_type = KRB5_KDB_SALTTYPE_NORMAL; + } + else + com_err(requestname, 0, o_not_salt_fmt, s1, value); + } + else + com_err(requestname, 0, o_val_req_fmt, value); + } + + return(good); +} + +/* + * parse_princ_options() - Parse an argument list for values. + * + * NOTE: The formatting buffer is static. + */ +krb5_boolean +parse_princ_options(argc, argv, vmaskp, dbentp) + int argc; + char *argv[]; + krb5_ui_4 *vmaskp; + krb5_db_entry *dbentp; +{ + int i, oindex; + krb5_boolean good; + krb5_boolean found; + + good = 1; + /* Copy in our values */ + memcpy(&opt_dbent, dbentp, sizeof(krb5_db_entry)); + for (i=0; i<argc; i++) { + found = 0; + /* + * First try the option table. + */ + for (oindex=0; oindex<(sizeof(opttable)/sizeof(opttable[0])); + oindex++) { + if ((*opttable[oindex].o_dispatch)(argv[i], + opttable[oindex].o_option, + opttable[oindex].o_arg)) { + *vmaskp |= opttable[oindex].o_value; + found = 1; + break; + } + } + + /* + * If we didn't find an option, try trapsing through the flag table. + */ + if (!found) { + int ti, rindex; + krb5_boolean sense; + + found = 0; + rindex = 0; + sense = 1; + if ((argv[i][0] == '-') || (argv[i][0] == '+')) { + if (argv[i][0] == '-') + sense = 0; + rindex = 1; + } + for (ti=0; ti<(sizeof(flagtable)/sizeof(flagtable[0])); ti++) { + if (!strncasecmp(&argv[i][rindex], flagtable[ti].f_option, + strlen(flagtable[ti].f_option))) { + found = 1; + if (sense == flagtable[ti].f_sense) + opt_dbent.attributes |= flagtable[ti].f_value; + else + opt_dbent.attributes &= ~flagtable[ti].f_value; + *vmaskp |= KRB5_ADM_M_FLAGS; + } + } + if (!found) { + com_err(requestname, 0, o_opt_ufo_fmt, argv[i]); + good = 0; + } + } + } + /* Copy out our values, if good */ + if (good) + memcpy(dbentp, &opt_dbent, sizeof(krb5_db_entry)); + return(good); +} + +/* + * help_princ_options() - Print out a list of settable principal options. + */ +void +help_princ_options() +{ + int index; + int ntable; + + fprintf(stderr, help_option_head, requestname); + ntable = (sizeof(opttable)/sizeof(opttable[0])); + for (index=0; index<ntable-1; index++) + fprintf(stderr, "%s, ", opttable[index].o_option); + fprintf(stderr,"%s\n", opttable[ntable-1].o_option); + fprintf(stderr, help_flag_head, requestname); + ntable = (sizeof(flagtable)/sizeof(flagtable[0])); + for (index=0; index<ntable-1; index++) + fprintf(stderr, "[+/-]%s, ", flagtable[index].f_option); + fprintf(stderr, "[+/-]%s\n", flagtable[ntable-1].f_option); +} diff --git a/src/kadmin/v5client/kadmin5.M b/src/kadmin/v5client/kadmin5.M new file mode 100644 index 0000000000..f925652060 --- /dev/null +++ b/src/kadmin/v5client/kadmin5.M @@ -0,0 +1,251 @@ +.\" $Source$ +.\" $Author$ +.\" $Id$ +.\" Copyright 1995 by the Massachusetts Institute of Technology. +.\" +.\" Export of this software from the United States of America may +.\" require a specific license from the United States Government. +.\" It is the responsibility of any person or organization contemplating +.\" export to obtain such a license before exporting. +.\" +.\" WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +.\" distribute this software and its documentation for any purpose and +.\" without fee is hereby granted, provided that the above copyright +.\" notice appear in all copies and that both that copyright notice and +.\" this permission notice appear in supporting documentation, and that +.\" the name of M.I.T. not be used in advertising or publicity pertaining +.\" to distribution of the software without specific, written prior +.\" permission. M.I.T. makes no representations about the suitability of +.\" this software for any purpose. It is provided "as is" without express +.\" or implied warranty. +.\" +.\" +.TH KADMIN5 8 "Kerberos Version 5.0" "MIT Project Athena" +.SH NAME +kadmin5 \- administer a Kerberos principal database over the network. +.SH SYNOPSIS +.B kadmin5 +[ +.B \-r +.I realm +] [ +.B \-p +.I principal +] [ +.B \-m +] +[ command ... ] +.br +.SH FLAGS +.PP +.IP \-r +.B realm +specifies the default realm. +.IP \-p +.B principal +specifies a principal name to use instead of the default +.I user +.B /kadmind5@realm. +.IP \-m +specifies that multiple operations will be permitted for only one entry of the +administrative principal's password. + +.SH DESCRIPTION +This utility provides a network administration interface to the Kerberos +master database. Kerberos administrators use kadmin5 to register new +users and services with the master database; to remove old users and services +from the master database; to modify information about existing database +entries; and to create service key tables from entries in the database. +.PP +The +.I kadmin5 +communicates over the network with the +.I kadmind5 +program, which runs on the system where the Kerberos master database resides. +.I kadmind5 +performs the database operations which +.I kadmin5 +specifies. +.PP +Principals who may perform administrative operations are controlled by the +.I kadmind5 +access control list. The default administrative principal is +.I user +.B /kadmind5@realm. +.PP +One command may be specified on the command line, or if no command is provided, +an interactive command loop is entered for the administrator to enter commands. +.PP +.SH AVAILABLE COMMANDS + +The following is a list of commands and their aliases that the system +administrator may use to manipulate the database: + +.IP show_principal,show +Show the Kerberos database entry for a principal. + +.IP add_new_key,ank +Add new entry to Kerberos database (prompting for new password). + +.IP change_pwd_key,cpw +Change key of an entry in the Kerberos database (prompting for new password). + +.IP add_rnd_key,ark +Add new entry to Kerberos database, using a random key. + +.IP change_rnd_key,crk +Change key of an entry in the Kerberos database (selecting a new random key). + +.IP delete_entry,delent,del +Delete an entry from the database. + +.IP extract_srvtab,xst,ex_st +Extract service key table entry/entries. + +.IP extract_v4_srvtab,xst4 +Extract service key table entry/entries in V4 format. + +.IP modify_entry,modent +Modify database entry. + +.IP rename_entry,renent +Rename database entry. + +.IP list_db,ldb +List database entries. + +.IP change_working_directory,cwd,cd +Change working directory. + +.IP print_working_directory,pwd +Print working directory. + +.IP list_requests,lr,? +List available requests. + +.IP quit,exit,q +Exit program. +.PP +.SH Principal Options +For the +.I add_new_key, add_rnd_key +and +.I modify_entry +commands, an optional list of principal options may be specified. The +following options may be specified: +.TP i +.I kvno=<integer> +Specifies the key version number for the principal. +.TP i +.I maxlife=<integer> +Specifies the maximum ticket life for the principal in seconds. +.TP i +.I maxrenewlife=<integer> +Specifies the maximum renewable ticket life for the principal in seconds. +.TP i +.I expiration=<date> +Specifies the expiration date and time of the principal. See below for the +format of +.I <date>. +.TP i +.I pwexpiration=<date> +Specifies the expiration date and time of the principal's password. See below for the format of +.I <date>. +.TP i +.I salttype=[v5|v4|norealm|onlyrealm|special] +Indicates the salt type. +.TP i +.I [+/-]postdateable +Specifies that tickets for this principal [are/are not] postdateable. +.TP i +.I [+/-]forwardable +Specifies that tickets for this principal [are/are not] forwardable. +.TP i +.I [+/-]tgt_req +Specifies that TGT-based requests for this principal [are/are not] allowed. +.TP i +.I [+/-]renewable +Specifies that tickets for this principal [are/are not] renewable. +.TP i +.I [+/-]proxiable +Specifies that tickets for this principal [are/are not] proxiable. +.TP i +.I [+/-]dup_skey +Specifies that tickets issued by this service [may/may not] be encrypted +using the session key instead of the private key. +.TP i +.I [+/-]allow_tickets +Specifies that tickets for this principal [are/are not] allowed. +.TP i +.I [+/-]preauth +Specifies that preauthorization [is/is not] required for this principal. +.TP i +.I [+/-]hwauth +Specifies that hardware preauthorization [is/is not] required for this +principal. +.TP i +.I [+/-]pwchange_req +Specifies that a password change [is/is not] required for this principal. +.TP i +.I [+/-]server +Specifies that this principal [is/is not] allowed to be a service. +.TP i +.I [+/-]pwservice +Specifies that this principal [is/is not] the password changing service. +.TP i +.I [+/-]md5 +Specifies that DES MD5 [is/is not] supported for this principal. + +.SH Date Format +The format of <date> +may be one of the following, where +.I yy +is the last two digits of the year; +.I mm +is the month number (with a leading zero if less than 10); +.I dd +is the day number in the month (with a leading zero if less than 10); +.I HH +is the hour number (24-hour clock); +.I MM +is the minute number; and +.I SS +is the second number: +.TP i +.I yy.mm.dd.HH.MM.SS +e.g. 95.09.01.00.00.00 for midnight on September 1, 1995. +.TP i +.I yymmddHHMMSS +e.g. 950901000000 for midnight on September 1, 1995. +.PP +If the +.B strptime(3) +function is available, then the following formats are also supported. +.PP +.TP i +.I yymmddHHMM +e.g. 9509010000 for midnight on September 1, 1995. +.TP i +.I HHMMSS +e.g. 200000 for 8pm tonight. +.TP i +.I HHMM +e.g. 2100 for 9pm tonight. +.TP i +.I HH:MM:SS +e.g. 20:00:00 for 8pm tonight. +.TP i +.I HH:MM +e.g. 21:00 for 9pm tonight. +.TP i +.I locale-dependent short format (mm/dd/yy:HH:MM:SS) in U.S. +.e.g 01/09/95:00:00:00 for midnight on September 1, 1995. +.TP i +.I dd-<text-month>-yyyy:HH:MM:SS +e.g. 01-Sep-1995:00:00:00 for midnight on September 1, 1995. +.TP i +.I dd-<text-month>-yyyy:HH:MM +e.g. 01-Sep-1995:00:00 for midnight on September 1, 1995. +.PP +.SH SEE ALSO +kadmind5(8), kpasswd(1), strptime(3) diff --git a/src/kadmin/v5client/kadmin5.c b/src/kadmin/v5client/kadmin5.c new file mode 100644 index 0000000000..0538c9ee0e --- /dev/null +++ b/src/kadmin/v5client/kadmin5.c @@ -0,0 +1,1434 @@ +/* + * kadmin/v5client/kadmin5.c + * + * Copyright 1995 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ + +/* + * kadmin5.c - Perform administrative functions using the new + * administrative protocol. + */ +#include "k5-int.h" +#include "com_err.h" +#include "adm.h" +#include "kadmin5.h" +#if HAVE_PWD_H +#include <pwd.h> +#endif /* HAVE_PWD_H */ +#if HAVE_RE_COMP || HAVE_REGCOMP +#include <regex.h> +#endif /* HAVE_RE_COMP || HAVE_REGCOMP */ + +/* + * Global storage. + */ +int exit_status = 0; +krb5_context kcontext; +char *programname = (char *) NULL; +char *requestname = (char *) NULL; +krb5_boolean multiple = 0; +char *principal_name = (char *) NULL; +char *password_prompt = (char *) NULL; + +extern krb5_kt_ops krb5_ktf_writable_ops; + +/* + * Own storage + */ +static char *realm_name = (char *) NULL; +#if !HAVE_RE_COMP && !HAVE_REGCOMP +static char *re_string = (char *) NULL; +#endif /* !HAVE_RE_COMP && !HAVE_REGCOMP */ + +/* + * Static strings. + */ +static const char *help_option = "-help"; +static const char *verbose_option = "-verbose"; +static const char *force_option = "-force"; +static const char *kadmin_instance = "kadmin5"; + +static const char *wr_ktab_type = "WRFILE"; + +static const char *gent_opterr_fmt = "- cannot decode protocol"; +static const char *db_print_header = "------------------------------------\n"; +static const char *db_print_1_fmt = "Principal: %s (key version %d)\n"; +static const char *db_print_2_fmt = "Maximum ticket lifetime: %s\n"; +static const char *db_print_2a_fmt = "Maximum renewable lifetime: %s\n"; +static const char *db_print_3_fmt = "Principal expiration: %s\n"; +static const char *db_print_3a_fmt = "Password expiration: %s\n"; +static const char *db_print_4_fmt = "Last password change: %s\n"; +static const char *db_print_5_fmt = "Last successful entry: %s\n"; +static const char *db_print_6_fmt = "Last unsuccessful entry: %s"; +static const char *db_print_6_opt_fmt = " - failed %d times"; +static const char *db_print_7_fmt = "Last modified by: %s (%s)\n\t[master version %d]\n"; +static const char *db_print_8_fmt = "Flags: %s\n"; +static const char *db_print_9_fmt = "Salt: %s"; +static const char *db_print_9a_fmt = ", %s"; +static const char *db_print_trailer = "------------------------------------\n"; + +static const char *db_indef_dt_msg = "indefinite"; +static const char *db_never_msg = "never"; +static const char *db_none_msg = "none"; + +static const char *sprinc_usage_fmt = "usage is %s principal [...]"; +static const char *add_usage_fmt = "usage is %s principal [attributes...]"; +static const char *add_prompt1_fmt = " Enter new password for %s : "; +static const char *add_prompt2_fmt = "Re-enter new password for %s : "; +static const char *add_succ_fmt = "principal %s added"; +static const char *add_protoerr_fmt = "- protocol encode error"; +static const char *add_noconf_fmt = "password not confirmed"; +static const char *add_synerr_fmt = "syntax error"; +static const char *cpw_usage_fmt = "usage is %s principal"; +static const char *cpw_prompt1_fmt = " Enter new password for %s: "; +static const char *cpw_prompt2_fmt = "Re-enter new password for %s: "; +static const char *cpw_succ_fmt = "password changed for %s"; +static const char *cpw_nochange_fmt = "password not changed for %s"; +static const char *dprinc_usage_fmt = "usage is %s [%s] principal [...]"; +static const char *del_conf_fmt = "Enter '%c' to delete principal %s: "; +static const char del_conf_char = 'y'; +static const char *del_princ_fmt = "principal %s deleted."; +static const char *del_noconf_fmt = "not confirmed - principal %s not deleted"; +static const char *xst_ktab_name_fmt = "%s:%s-new-srvtab"; +static const char *xst_k4tab_name_fmt = "%s-new-v4-srvtab"; +static const char *xst_dfl_ktname = "DEFAULT"; +static const char *xst_usage_fmt = "usage is %s instance principal [...]"; +static const char *xst_wr_reg_fmt = "(%s) cannot register writeable keytable"; +static const char *xst_inst2long_fmt = "'%s' is too long for a filename, using '%s' instead"; +static const char *xst_nokeytab_fmt = "cannot open key table %s"; +static const char *xst_nodeskey_fmt = "%s does not have a DES key"; +static const char *xst_adderr_fmt = "cannot add entry %s"; +static const char *xst_success_fmt = "extracted entry %s to key table %s"; +static const char *xst_proto_fmt = "cannot decode service key table entry from protocol"; +static const char *xst_kclose_fmt = "cannot close key table %s"; +static const char *mod_usage_fmt = "usage is %s principal [attributes...]"; +static const char *mod_succ_fmt = "principal %s modified."; +static const char *mod_protoerr_fmt = "protocol encode error"; +static const char *mod_synerr_fmt = "syntax error"; +static const char *rprinc_usage_fmt = "usage is %s [%s] principal principal"; +static const char *ren_conf_fmt = "Enter '%c' to rename principal %s to %s: "; +static const char ren_conf_char = 'y'; +static const char *ren_princ_fmt = "principal %s renamed to %s."; +static const char *ren_noconf_fmt = "not confirmed - principal %s not renamed to %s."; +#if HAVE_RE_COMP || HAVE_REGCOMP +static const char *lprinc_usage_fmt = "usage is %s [%s] <regexp>"; +#else /* HAVE_RE_COMP || HAVE_REGCOMP */ +static const char *lprinc_usage_fmt = "usage is %s [%s] princpal"; +#endif /* HAVE_RE_COMP || HAVE_REGCOMP */ +static const char *lprinc_all_regexp = ".*"; +static const char *lprinc_regexp_fmt = "%s - regular expression error: %s"; +static const char *lprinc_regsrch_fmt = "%s on %s - RE search error: %s"; +static const char *lprinc_first_msg = "first database entry"; +static const char *cant_get_fmt = "cannot get entry for %s"; +static const char *no_memory_fmt = "cannot get memory"; +static const char *lang_usage_fmt = "usage is %s language"; +static const char *cd_cannot_fmt = "cannot change directory to %s"; +static const char *cd_usage_fmt = "usage is %s directory"; +static const char *pwd_mess_fmt = "Current directory is %s\n"; +static const char *pwd_err_fmt = "cannot get current directory: %s"; +static const char *pwd_usage_fmt = "usage is %s"; +static const char *kadmin_usage_fmt = "usage is %s [-r realm] [-p principal] [-m] [command ...]"; +static const char *kadmin_defrealm_msg = ": cannot get default realm"; +static const char *kadmin_srealm_fmt = ": cannot set realm to \"%s\""; +static const char *kadmin_nopname_msg = ": cannot find a principal name"; +static const char *kadmin_unparse_msg = ": cannot flatten principal name"; +static const char *kadmin_nocomp_msg = ": no components in principal name"; +static const char *kadmin_noprompt_msg = ": cannot make password prompt"; + +static const char *kadmin_pprompt_fmt = "Enter password for %s: "; + +#if !HAVE_RE_COMP && !HAVE_REGCOMP +/* + * re_comp() - Compile a regular expression for subsequent usage by re_exec + * + * This routine is only a shell. Null expressions or expressions matching + * lprinc_all_regexp are taken to match everything, all others are + * interpreted as "string".*. + */ +static char * +re_comp(rstring) + char *rstring; +{ + if (strlen(rstring) && strcmp(rstring, lprinc_all_regexp)) { + re_string = rstring; + } + else { + re_string = (char *) NULL; + } + return((char *) NULL); +} + +/* + * re_exec() - Attempt to match a string to a regular expression previously + * specified to re_comp(). + * + * This routine is only a shell. + */ +static int +re_exec(sstring) + char *sstring; +{ + if (re_string) + return(strncmp(sstring, re_string, strlen(re_string)) ? 0 : 1); + else + return(1); +} +#endif /* !HAVE_RE_COMP && !HAVE_REGCOMP */ + +/* + * kadmin_get_entry() - Get a principal entry. + */ +static krb5_error_code +kadmin_get_entry(pname, validp, dbentp, nextp) + char *pname; + krb5_ui_4 *validp; + krb5_db_entry *dbentp; + char **nextp; +{ + krb5_error_code kret; + krb5_int32 proto_stat; + krb5_int32 ncomps; + krb5_data *complist; + char *pword; + + if (!(kret = net_do_proto(KRB5_ADM_INQ_PRINC_CMD, + pname, + (char *) NULL, + 0, + (krb5_data *) NULL, + &proto_stat, + &ncomps, + &complist))) { + if (proto_stat == KRB5_ADM_SUCCESS) { + *nextp = (char *) malloc((size_t) complist[0].length + 1); + if (*nextp) { + strncpy(*nextp, complist[0].data, (size_t) complist[0].length); + (*nextp)[complist[0].length] = '\0'; + } + if (!(kret = krb5_adm_proto_to_dbent(kcontext, + ncomps-1, + &complist[1], + validp, + dbentp, + &pword))) { + if (pword) + krb5_xfree(pword); + } + else { + com_err(requestname, kret, gent_opterr_fmt); + } + krb5_free_adm_data(kcontext, ncomps, complist); + } + else + kret = EIO; + } + return(kret); +} + +/* + * kadmin_princ_entry() - Print out a database entry. + */ +static void +kadmin_print_entry(name, valid, dbentp) + char *name; + krb5_ui_4 valid; + krb5_db_entry *dbentp; +{ + printf(db_print_header); + printf(db_print_1_fmt, name, + ((valid & KRB5_ADM_M_KVNO) ? dbentp->kvno : -1)); + printf(db_print_2_fmt, + ((valid & KRB5_ADM_M_MAXLIFE) ? + delta2string(dbentp->max_life) : db_indef_dt_msg)); + printf(db_print_2a_fmt, + ((valid & KRB5_ADM_M_MAXRENEWLIFE) ? + delta2string(dbentp->max_renewable_life) : db_indef_dt_msg)); + printf(db_print_3_fmt, + ((valid & KRB5_ADM_M_EXPIRATION) ? + abs2string(dbentp->expiration) : db_never_msg)); + printf(db_print_3a_fmt, + ((valid & KRB5_ADM_M_PWEXPIRATION) ? + abs2string(dbentp->pw_expiration) : db_never_msg)); + printf(db_print_4_fmt, + ((valid & KRB5_ADM_M_LASTPWCHANGE) ? + abs2string(dbentp->last_pwd_change) : db_never_msg)); + printf(db_print_5_fmt, + ((valid & KRB5_ADM_M_LASTSUCCESS) ? + abs2string(dbentp->last_success) : db_never_msg)); + if ((valid & KRB5_ADM_M_FAILCOUNT) && (dbentp->fail_auth_count > 0)) { + printf(db_print_6_fmt, + ((valid & KRB5_ADM_M_LASTFAILED) ? + abs2string(dbentp->last_failed) : db_never_msg)); + printf(db_print_6_opt_fmt, dbentp->fail_auth_count); + printf("\n"); + } + + if (valid & KRB5_ADM_M_MODNAME) { + char *mname; + if (!krb5_unparse_name(kcontext, dbentp->mod_name, &mname)) { + printf(db_print_7_fmt, mname, + ((valid & KRB5_ADM_M_MODDATE) ? + abs2string(dbentp->mod_date) : db_never_msg), + ((valid & KRB5_ADM_M_MKVNO) ? dbentp->mkvno : -1)); + krb5_xfree(mname); + } + } + printf(db_print_8_fmt, + ((valid & KRB5_ADM_M_FLAGS) ? + dbflags2string(dbentp->attributes) : "")); + if (valid & KRB5_ADM_M_SALTTYPE) { + printf(db_print_9_fmt, salt2string(dbentp->salt_type)); + if (dbentp->salt_type != dbentp->alt_salt_type) + printf(db_print_9a_fmt, salt2string(dbentp->alt_salt_type)); + printf("\n"); + } + printf(db_print_trailer); +} + +/* + * Dispatch procedures. + */ + +/* + * kadmin_show_principal() - Show a principal. + */ +void +kadmin_show_principal(argc, argv) + int argc; + char *argv[]; +{ + int i; + krb5_error_code kret; + char *xxx; + krb5_ui_4 valid; + krb5_db_entry *dbentry; + + requestname = argv[0]; + if (argc == 1) { + com_err(argv[0], 0, sprinc_usage_fmt, argv[0]); + return; + } + for (i=1; i<argc; i++) { + if (dbentry = (krb5_db_entry *) malloc(sizeof(krb5_db_entry))) { + memset((char *) dbentry, 0, sizeof(*dbentry)); + kret = kadmin_get_entry(argv[i], &valid, dbentry, &xxx); + if (kret) { + com_err(argv[0], 0, cant_get_fmt, argv[i]); + break; + } + if (xxx) + free(xxx); + kadmin_print_entry(argv[i], valid, dbentry); + krb5_db_free_principal(kcontext, dbentry, 1); + } + else { + com_err(argv[0], 0, no_memory_fmt); + } + } +} + +/* + * kadmin_add_new_key() - Add a new principal. + */ +void +kadmin_add_new_key(argc, argv) + int argc; + char *argv[]; +{ + krb5_error_code kret; + char *p1, *p2; + char *npass; + int nplen; + krb5_int32 proto_stat; + krb5_int32 nargs; + krb5_data *arglist; + krb5_int32 ncomps; + krb5_data *complist; + char *principal; + krb5_ui_4 valid; + krb5_db_entry *dbentp; + + requestname = argv[0]; + if (argc < 2) { + com_err(argv[0], 0, add_usage_fmt, argv[0]); + help_princ_options(); + return; + } + principal = argv[1]; + argc -= 2; + argv += 2; + + p1 = (char *) malloc(strlen(add_prompt1_fmt)+strlen(principal)+1); + p2 = (char *) malloc(strlen(add_prompt2_fmt)+strlen(principal)+1); + npass = (char *) malloc(KRB5_ADM_MAX_PASSWORD_LEN); + dbentp = (krb5_db_entry *) malloc(sizeof(krb5_db_entry)); + if (p1 && p2 && npass && dbentp) { + memset((char *) dbentp, 0, sizeof(krb5_db_entry)); + valid = 0; + if (parse_princ_options(argc, argv, &valid, dbentp)) { + valid |= KRB5_ADM_M_SET; /* We are setting options */ + sprintf(p1, add_prompt1_fmt, principal); + sprintf(p2, add_prompt2_fmt, principal); + nplen = KRB5_ADM_MAX_PASSWORD_LEN; + valid |= KRB5_ADM_M_PASSWORD; /* We have a password */ + if (!(kret = krb5_read_password(kcontext, + p1, p2, npass, &nplen))) { + npass[nplen] = '\0'; + nargs = ncomps = 0; + if (!(kret = krb5_adm_dbent_to_proto(kcontext, + valid, + dbentp, + npass, + &nargs, + &arglist)) && + !(kret = net_do_proto(KRB5_ADM_ADD_PRINC_CMD, + principal, + (char *) NULL, + nargs, + arglist, + &proto_stat, + &ncomps, + &complist))) { + if (proto_stat == KRB5_ADM_SUCCESS) { + com_err(programname, 0, add_succ_fmt, principal); + } + } + else { + com_err(requestname, kret, add_protoerr_fmt); + } + if (ncomps) + krb5_free_adm_data(kcontext, ncomps, complist); + if (nargs) + krb5_free_adm_data(kcontext, nargs, arglist); + memset(npass, 0, KRB5_ADM_MAX_PASSWORD_LEN); + } + else { + com_err(requestname, 0, add_noconf_fmt); + } + } + else { + com_err(requestname, 0, add_synerr_fmt); + help_princ_options(); + } + } + else { + com_err(requestname, 0, no_memory_fmt); + } + if (p1) + free(p1); + if (p2) + free(p2); + if (npass) + free(npass); + if (dbentp) + free(dbentp); +} + + +/* + * kadmin_change_pwd() - Change principal's password. + */ +void +kadmin_change_pwd(argc, argv) + int argc; + char *argv[]; +{ + krb5_error_code kret; + char *p1, *p2; + char *npass; + int nplen; + krb5_int32 proto_stat; + krb5_int32 ncomps; + krb5_data *complist; + + requestname = argv[0]; + if (argc != 2) { + com_err(argv[0], 0, cpw_usage_fmt, argv[0]); + return; + } + p1 = (char *) malloc(strlen(cpw_prompt1_fmt)+strlen(argv[1])+1); + p2 = (char *) malloc(strlen(cpw_prompt2_fmt)+strlen(argv[1])+1); + npass = (char *) malloc(KRB5_ADM_MAX_PASSWORD_LEN); + if (p1 && p2 && npass) { + sprintf(p1, cpw_prompt1_fmt, argv[1]); + sprintf(p2, cpw_prompt2_fmt, argv[1]); + + nplen = KRB5_ADM_MAX_PASSWORD_LEN; + if (!(kret = krb5_read_password(kcontext, p1, p2, npass, &nplen))) { + npass[nplen] = '\0'; + if (!(kret = net_do_proto(KRB5_ADM_CHG_OPW_CMD, + argv[1], + npass, + 0, + (krb5_data *) NULL, + &proto_stat, + &ncomps, + &complist))) { + if (proto_stat == KRB5_ADM_SUCCESS) { + com_err(programname, 0, cpw_succ_fmt, argv[1]); + krb5_free_adm_data(kcontext, ncomps, complist); + } + } + memset(npass, 0, KRB5_ADM_MAX_PASSWORD_LEN); + } + else { + com_err(argv[0], kret, cpw_nochange_fmt, argv[1]); + } + } + else { + com_err(requestname, 0, no_memory_fmt); + } + if (p1) + free(p1); + if (p2) + free(p2); + if (npass) + free(npass); +} + +/* + * kadmin_add_rnd_key() - Add principal with random key. + */ +void +kadmin_add_rnd_key(argc, argv) + int argc; + char *argv[]; +{ + krb5_error_code kret; + krb5_int32 proto_stat; + krb5_int32 nargs; + krb5_data *arglist; + krb5_int32 ncomps; + krb5_data *complist; + char *principal; + krb5_ui_4 valid; + krb5_db_entry *dbentp; + + requestname = argv[0]; + if (argc < 2) { + com_err(argv[0], 0, add_usage_fmt, argv[0]); + help_princ_options(); + return; + } + principal = argv[1]; + argc -= 2; + argv += 2; + + dbentp = (krb5_db_entry *) malloc(sizeof(krb5_db_entry)); + if (dbentp) { + memset((char *) dbentp, 0, sizeof(krb5_db_entry)); + valid = 0; + if (parse_princ_options(argc, argv, &valid, dbentp)) { + valid |= KRB5_ADM_M_SET; /* We are setting options */ + valid |= KRB5_ADM_M_RANDOMKEY; /* We have a random key */ + ncomps = nargs = 0; + if (!(kret = krb5_adm_dbent_to_proto(kcontext, + valid, + dbentp, + (char *) NULL, + &nargs, + &arglist)) && + !(kret = net_do_proto(KRB5_ADM_ADD_PRINC_CMD, + principal, + (char *) NULL, + nargs, + arglist, + &proto_stat, + &ncomps, + &complist))) { + if (proto_stat == KRB5_ADM_SUCCESS) { + com_err(programname, 0, add_succ_fmt, principal); + } + } + else { + com_err(requestname, kret, add_protoerr_fmt); + } + if (ncomps) + krb5_free_adm_data(kcontext, ncomps, complist); + if (nargs) + krb5_free_adm_data(kcontext, nargs, arglist); + } + else { + com_err(requestname, 0, add_synerr_fmt); + help_princ_options(); + } + } + else { + com_err(requestname, 0, no_memory_fmt); + } + if (dbentp) + free(dbentp); +} + +/* + * kadmin_change_rnd() - Change random key. + */ +void +kadmin_change_rnd(argc, argv) + int argc; + char *argv[]; +{ + krb5_error_code kret; + krb5_int32 proto_stat; + krb5_int32 ncomps; + krb5_data *complist; + + requestname = argv[0]; + if (argc != 2) { + com_err(argv[0], 0, cpw_usage_fmt, argv[0]); + return; + } + if (!(kret = net_do_proto(KRB5_ADM_CHG_ORPW_CMD, + argv[1], + (char *) NULL, + 0, + (krb5_data *) NULL, + &proto_stat, + &ncomps, + &complist))) { + if (proto_stat == KRB5_ADM_SUCCESS) { + com_err(programname, 0, cpw_succ_fmt, argv[1]); + krb5_free_adm_data(kcontext, ncomps, complist); + } + } +} + +/* + * kadmin_delete_entry() - Delete principal. + */ +void +kadmin_delete_entry(argc, argv) + int argc; + char *argv[]; +{ + int i; + krb5_error_code kret; + krb5_int32 proto_stat; + krb5_int32 ncomps; + krb5_data *complist; + krb5_boolean force, doit; + + requestname = argv[0]; + force = 0; + if (argc == 1) { + com_err(argv[0], 0, dprinc_usage_fmt, argv[0], force_option); + return; + + } + for (i=1; i<argc; i++) { + if (!strcmp(argv[i], force_option)) { + force = 1; + continue; + } + doit = 0; + if (force) { + doit = 1; + } + else { + int c; + printf(del_conf_fmt, del_conf_char, argv[i]); + if (getchar() == del_conf_char) + doit = 1; + while (((c = getchar()) != '\n') && (c != EOF)); + } + + if (doit) { + if (!(kret = net_do_proto(KRB5_ADM_DEL_PRINC_CMD, + argv[i], + (char *) NULL, + 0, + (krb5_data *) NULL, + &proto_stat, + &ncomps, + &complist))) { + if (proto_stat == KRB5_ADM_SUCCESS) { + com_err(programname, 0, del_princ_fmt, argv[i]); + krb5_free_adm_data(kcontext, ncomps, complist); + } + } + } + else { + com_err(programname, 0, del_noconf_fmt, argv[i]); + } + } +} + +/* + * kadmin_extract() - Extract srvtab entry. + */ +void +kadmin_extract(argc, argv) + int argc; + char *argv[]; +{ + int i; + krb5_error_code kret; + krb5_int32 proto_stat; + krb5_int32 ncomps; + krb5_data *complist; + char *instance; + krb5_boolean force, doit; + krb5_keytab_entry keytab_entry; + char keytab_name[MAXPATHLEN+sizeof(wr_ktab_type)+2]; + krb5_keytab keytab_id; + char *actname; + + requestname = argv[0]; + force = 0; + if (argc < 3) { + com_err(argv[0], 0, xst_usage_fmt, argv[0]); + return; + + } + instance = argv[1]; + argc -= 2; + argv += 2; + + /* + * First prepare us for writeable keytable operations. + */ + if (kret = krb5_kt_register(kcontext, &krb5_ktf_writable_ops)) { + if (kret != KRB5_KT_TYPE_EXISTS) { + com_err(programname, kret, xst_wr_reg_fmt, requestname); + return; + } + } + + /* + * Format new srvtab name. + */ + if (strlen(instance)+strlen(wr_ktab_type)+strlen(xst_ktab_name_fmt)-3 + >= sizeof(keytab_name)) { + com_err(requestname, 0, xst_inst2long_fmt, instance, xst_dfl_ktname); + sprintf(keytab_name, xst_ktab_name_fmt, wr_ktab_type, xst_dfl_ktname); + } + else + sprintf(keytab_name, xst_ktab_name_fmt, wr_ktab_type, instance); + actname = &keytab_name[strlen(wr_ktab_type)+1]; + + if (kret = krb5_kt_resolve(kcontext, keytab_name, &keytab_id)) { + com_err(requestname, kret, xst_nokeytab_fmt, actname); + return; + } + memset((char *) &keytab_entry, 0, sizeof(krb5_keytab_entry)); + for (i=0; i<argc; i++) { + if (!(kret = net_do_proto(KRB5_ADM_EXT_KEY_CMD, + instance, + argv[i], + 0, + (krb5_data *) NULL, + &proto_stat, + &ncomps, + &complist))) { + if (proto_stat == KRB5_ADM_SUCCESS) { + if (!(kret = krb5_adm_proto_to_ktent(kcontext, + ncomps, + complist, + &keytab_entry))) { + if (kret = krb5_kt_add_entry(kcontext, + keytab_id, + &keytab_entry)) { + com_err(requestname, kret, xst_adderr_fmt, + argv[i], actname); + break; + } + else + com_err(requestname, 0, xst_success_fmt, + argv[i], actname); + if (keytab_entry.key.contents) { + memset((char *) keytab_entry.key.contents, 0, + (size_t) keytab_entry.key.length); + krb5_xfree(keytab_entry.key.contents); + } + } + else { + com_err(requestname, kret, xst_proto_fmt); + } + memset((char *) &keytab_entry, 0, sizeof(krb5_keytab_entry)); + krb5_free_adm_data(kcontext, ncomps, complist); + } + } + } + if (kret = krb5_kt_close(kcontext, keytab_id)) { + com_err(requestname, kret, xst_kclose_fmt, keytab_name); + } +} + +/* + * kadmin_extract_v4() - Extract srvtab entry in V4 format. + */ +void +kadmin_extract_v4(argc, argv) + int argc; + char *argv[]; +{ + int i; + krb5_error_code kret; + krb5_int32 proto_stat; + krb5_int32 ncomps; + krb5_data *complist; + char *instance; + krb5_boolean force, doit; + krb5_keytab_entry keytab_entry; + char keytab_name[MAXPATHLEN+1]; + FILE *v4tab; + + requestname = argv[0]; + force = 0; + if (argc < 3) { + com_err(argv[0], 0, xst_usage_fmt, argv[0]); + return; + + } + instance = argv[1]; + argc -= 2; + argv += 2; + + /* + * Format new srvtab name. + */ + if (strlen(instance)+strlen(xst_k4tab_name_fmt)-3 >= sizeof(keytab_name)) { + com_err(requestname, 0, xst_inst2long_fmt, instance, xst_dfl_ktname); + sprintf(keytab_name, xst_k4tab_name_fmt, xst_dfl_ktname); + } + else + sprintf(keytab_name, xst_k4tab_name_fmt, instance); + + if ((v4tab = fopen(keytab_name, "w")) == NULL) { + com_err(requestname, errno, xst_nokeytab_fmt, keytab_name); + return; + } + memset((char *) &keytab_entry, 0, sizeof(krb5_keytab_entry)); + for (i=0; i<argc; i++) { + if (!(kret = net_do_proto(KRB5_ADM_EXT_KEY_CMD, + instance, + argv[i], + 0, + (krb5_data *) NULL, + &proto_stat, + &ncomps, + &complist))) { + if (proto_stat == KRB5_ADM_SUCCESS) { + if (!(kret = krb5_adm_proto_to_ktent(kcontext, + ncomps, + complist, + &keytab_entry))) { + if (keytab_entry.key.keytype != 1) { + com_err(requestname, 0, xst_nodeskey_fmt, argv[i]); + break; + } + if ((fwrite(argv[i], + strlen(argv[i])+1, + 1, + v4tab) != 1) || + (fwrite(instance, + strlen(instance)+1, + 1, + v4tab) != 1) || + (fwrite(realm_name, + strlen(realm_name)+1, + 1, + v4tab) != 1) || + (fwrite((char *) &keytab_entry.vno, + sizeof(keytab_entry.vno), + 1, + v4tab) != 1) || + (fwrite((char *) keytab_entry.key.contents, + keytab_entry.key.length, + 1, + v4tab) != 1)) { + com_err(requestname, kret, xst_adderr_fmt, + argv[i], keytab_name); + break; + } + else + com_err(requestname, 0, xst_success_fmt, + argv[i], keytab_name); + if (keytab_entry.key.contents) { + memset((char *) keytab_entry.key.contents, 0, + (size_t) keytab_entry.key.length); + krb5_xfree(keytab_entry.key.contents); + } + } + else { + com_err(requestname, kret, xst_proto_fmt); + } + memset((char *) &keytab_entry, 0, sizeof(krb5_keytab_entry)); + krb5_free_adm_data(kcontext, ncomps, complist); + } + } + } + fclose(v4tab); +} + +/* + * kadmin_modify() - Modify principal. + */ +void +kadmin_modify(argc, argv) + int argc; + char *argv[]; +{ + krb5_error_code kret; + krb5_int32 proto_stat; + krb5_int32 nargs; + krb5_data *arglist; + krb5_int32 ncomps; + krb5_data *complist; + char *principal; + krb5_ui_4 valid; + krb5_db_entry *dbentp; + + requestname = argv[0]; + if (argc < 2) { + com_err(argv[0], 0, mod_usage_fmt, argv[0]); + help_princ_options(); + return; + } + principal = argv[1]; + argc -= 2; + argv += 2; + + dbentp = (krb5_db_entry *) malloc(sizeof(krb5_db_entry)); + if (dbentp) { + memset((char *) dbentp, 0, sizeof(krb5_db_entry)); + valid = 0; + if (parse_princ_options(argc, argv, &valid, dbentp)) { + valid |= KRB5_ADM_M_SET; /* We are setting options */ + nargs = ncomps = 0; + if (!(kret = krb5_adm_dbent_to_proto(kcontext, + valid, + dbentp, + (char *) NULL, + &nargs, + &arglist)) && + !(kret = net_do_proto(KRB5_ADM_MOD_PRINC_CMD, + principal, + (char *) NULL, + nargs, + arglist, + &proto_stat, + &ncomps, + &complist))) { + if (proto_stat == KRB5_ADM_SUCCESS) { + com_err(programname, 0, mod_succ_fmt, principal); + } + } + else { + com_err(requestname, kret, mod_protoerr_fmt); + } + if (ncomps) + krb5_free_adm_data(kcontext, ncomps, complist); + if (nargs) + krb5_free_adm_data(kcontext, nargs, arglist); + } + else { + com_err(requestname, 0, mod_synerr_fmt); + help_princ_options(); + } + } + else { + com_err(requestname, 0, no_memory_fmt); + } + if (dbentp) + free(dbentp); +} + +/* + * kadmin_rename() - Rename principal. + */ +void +kadmin_rename(argc, argv) + int argc; + char *argv[]; +{ + int i; + krb5_error_code kret; + krb5_int32 proto_stat; + krb5_int32 ncomps; + krb5_data *complist; + krb5_boolean force, doit, uerr; + + requestname = argv[0]; + uerr = force = 0; + + argc--; argv++; + if (argc > 0) { + if (!strcmp(argv[0], force_option)) { + force = 1; + argc--; + argv++; + } + if (argc != 2) + uerr++; + } + else + uerr++; + if (uerr) { + com_err(requestname, 0, rprinc_usage_fmt, requestname, force_option); + return; + } + + doit = 0; + if (force) { + doit = 1; + } + else { + int c; + printf(ren_conf_fmt, ren_conf_char, argv[0], argv[1]); + if (getchar() == ren_conf_char) + doit = 1; + while (((c = getchar()) != '\n') && (c != EOF)); + } + + if (doit) { + if (!(kret = net_do_proto(KRB5_ADM_REN_PRINC_CMD, + argv[0], + argv[1], + 0, + (krb5_data *) NULL, + &proto_stat, + &ncomps, + &complist))) { + if (proto_stat == KRB5_ADM_SUCCESS) { + com_err(programname, 0, ren_princ_fmt, argv[0], argv[1]); + krb5_free_adm_data(kcontext, ncomps, complist); + } + } + } + else { + com_err(programname, 0, ren_noconf_fmt, argv[0], argv[1]); + } +} + +/* + * kadmin_list() - List principals. + */ +void +kadmin_list(argc, argv) + int argc; + char *argv[]; +{ + krb5_error_code kret; + int error; + int i; + krb5_boolean verbose; + char *re_result; +#if HAVE_REGCOMP + regex_t match_exp; + regmatch_t match_match; + int match_error; + char match_errmsg[BUFSIZ]; + size_t errmsg_size; +#endif /* HAVE_REGCOMP */ +#if HAVE_RE_COMP && !HAVE_REGCOMP + extern char *re_comp(); +#endif /* HAVE_RE_COMP && !HAVE_REGCOMP */ + + requestname = argv[0]; + error = 0; + verbose = 0; +#if HAVE_REGCOMP + if (match_error = regcomp(&match_exp, lprinc_all_regexp, REG_EXTENDED)) { + errmsg_size = regerror(match_error, + &match_exp, + match_errmsg, + sizeof(match_errmsg)); + com_err(requestname, 0, lprinc_regexp_fmt, lprinc_all_regexp, + match_errmsg); + return; + } +#else /* HAVE_REGCOMP */ + re_comp(".*"); /* Accept everything */ +#endif /* HAVE_REGCOMP */ + + for (i=1; i<argc; i++) { + if (!strcmp(argv[i], help_option)) { + com_err(argv[0], 0, lprinc_usage_fmt, argv[0], verbose_option); + error = 1; + break; + } + if (!strcmp(argv[i], verbose_option)) { + verbose = 1; + continue; + } +#if HAVE_REGCOMP + if (match_error = regcomp(&match_exp, argv[i], REG_EXTENDED)) { + errmsg_size = regerror(match_error, + &match_exp, + match_errmsg, + sizeof(match_errmsg)); + com_err(requestname, 0, lprinc_regexp_fmt, argv[i], match_errmsg); + error = 1; + } + else + continue; +#else /* HAVE_REGCOMP */ + if (!(re_result = re_comp(argv[i]))) { + continue; + } + else { + com_err(argv[0], 0, lprinc_regexp_fmt, re_result); + error = 1; + } +#endif /* HAVE_REGCOMP */ + } + if (!error) { + char *next; + char *nnext; + krb5_ui_4 valid; + krb5_db_entry *dbentry; + + if (dbentry = (krb5_db_entry *) malloc(sizeof(krb5_db_entry))) { + memset((char *) dbentry, 0, sizeof(*dbentry)); + kret = kadmin_get_entry("", &valid, dbentry, &next); + if (kret) { + com_err(argv[0], 0, cant_get_fmt, lprinc_first_msg); + next = (char *) NULL; + } + else { + krb5_db_free_principal(kcontext, dbentry, 1); + } + while (next && strlen(next)) { + if (dbentry = (krb5_db_entry *) + malloc(sizeof(krb5_db_entry))) { + memset((char *) dbentry, 0, sizeof(*dbentry)); + kret = kadmin_get_entry(next, &valid, dbentry, &nnext); + if (kret) { + com_err(argv[0], 0, cant_get_fmt, lprinc_first_msg); + break; + } +#if HAVE_REGCOMP + if (match_error = regexec(&match_exp, + next, + 1, + &match_match, + 0)) { + if (match_error != REG_NOMATCH) { + errmsg_size = regerror(match_error, + &match_exp, + match_errmsg, + sizeof(match_errmsg)); + com_err(requestname, 0, + lprinc_regsrch_fmt, + argv[i], + next, + match_errmsg); + error = 1; + } + } + else { + /* + * We have a match. See if it matches the whole + * name. + */ + if ((match_match.rm_so == 0) && + (match_match.rm_eo == strlen(next))) { + if (verbose) { + kadmin_print_entry(next, valid, dbentry); + } + else { + printf("%s\n", next); + } + } + } +#else /* HAVE_REGCOMP */ + if (re_exec(next)) { + if (verbose) { + kadmin_print_entry(next, valid, dbentry); + } + else { + printf("%s\n", next); + } + } +#endif /* HAVE_REGCOMP */ + free(next); + next = nnext; + krb5_db_free_principal(kcontext, dbentry, 1); + } + } + } + else { + com_err(argv[0], 0, no_memory_fmt); + } + } +} + +#ifdef LANGUAGES_SUPPORTED +/* + * kadmin_language() - Tell server to enable output in target language. + */ +void +kadmin_language(argc, argv) + int argc; + char *argv[]; +{ + krb5_error_code kret; + krb5_int32 proto_stat; + krb5_int32 ncomps; + krb5_data *complist; + + requestname = argv[0]; + if (argc == 2) { + if (!(kret = net_do_proto(KRB5_ADM_LANGUAGE_CMD, + argv[1], + (char *) NULL, + 0, + (krb5_data *) NULL, + &proto_stat, + &ncomps, + &complist))) { + if (proto_stat == KRB5_ADM_SUCCESS) { + krb5_free_adm_data(kcontext, ncomps, complist); + } + if (!(kret = net_do_proto(KRB5_ADM_MIME_CMD, + (char *) NULL, + (char *) NULL, + 0, + (krb5_data *) NULL, + &proto_stat, + &ncomps, + &complist))) { + if (proto_stat == KRB5_ADM_SUCCESS) { + krb5_free_adm_data(kcontext, ncomps, complist); + } + } + } + } + else + com_err(argv[0], 0, lang_usage_fmt, argv[0]); +} +#endif /* LANGUAGES_SUPPORTED */ + +/* + * kadmin_cd() - Change working directory. + */ +void +kadmin_cd(argc, argv) + int argc; + char *argv[]; +{ + requestname = argv[0]; + if (argc == 2) { + if (chdir(argv[1]) == -1) { + com_err(argv[0], errno, cd_cannot_fmt, argv[1]); + } + } + else { + com_err(argv[0], 0, cd_usage_fmt, argv[0]); + } +} + +/* + * kadmin_pwd() - Print working directory. + */ +void +kadmin_pwd(argc, argv) + int argc; + char *argv[]; +{ + char cwd[MAXPATHLEN]; + + requestname = argv[0]; + if (argc == 1) { + if ( +#if HAVE_GETCWD + getcwd(cwd, MAXPATHLEN) +#else /* HAVE_GETCWD */ + getwd(cwd) +#endif /* HAVE_GETCWD */ + ) + printf(pwd_mess_fmt, cwd); + else + com_err(argv[0], errno, pwd_err_fmt, cwd); + } + else + com_err(argv[0], 0, pwd_usage_fmt, argv[0]); +} + +/* + * Startup fuction + */ +char * +kadmin_startup(argc, argv) + int argc; + char *argv[]; +{ + krb5_error_code kret; + int option; + extern char *optarg; + extern int optind; + char *action = (char *) NULL; + + programname = argv[0]; + while ((option = getopt(argc, argv, "r:p:mt:")) != EOF) { + switch (option) { + case 'r': + realm_name = optarg; + break; + case 'p': + principal_name = optarg; + break; + case 'm': + multiple = 1; + break; + default: + com_err(argv[0], 0, kadmin_usage_fmt, argv[0]); + exit(1); + } + } + + /* Now we do some real work */ + krb5_init_context(&kcontext); + krb5_init_ets(kcontext); + + /* Get or verify current realm */ + if (!realm_name) { + kret = krb5_get_default_realm(kcontext, &realm_name); + if (kret) { + com_err(argv[0], kret, kadmin_defrealm_msg); + exit(2); + } + } + else { + kret = krb5_set_default_realm(kcontext, realm_name); + if (kret) { + com_err(argv[0], kret, kadmin_srealm_fmt, realm_name); + exit(3); + } + } + + /* If no principal name, formulate a reasonable response */ + if (!principal_name) { + krb5_principal me; + krb5_ccache ccache; + char *user; +#if HAVE_PWD_H + struct passwd *pw; +#endif /* HAVE_PWD_H */ + + me = (krb5_principal) NULL; + ccache = (krb5_ccache) NULL; + user = (char *) NULL; + + /* First try our default credentials cache */ + if (!(kret = krb5_cc_default(kcontext, &ccache)) && + !(kret = krb5_cc_get_principal(kcontext, ccache, &me))) { + + /* Use our first component, if it exists. */ + if (krb5_princ_size(kcontext, me) > 0) { + krb5_data *dp; + + dp = krb5_princ_component(kcontext, me, 0); + if (user = (char *) malloc((size_t) dp->length + 1)) { + strncpy(user, dp->data, (size_t) dp->length); + user[dp->length] = '\0'; + } + else { + kret = ENOMEM; + } + } + else { + com_err(argv[0], 0, kadmin_nocomp_msg); + exit(1); + } + } + else if (user = getenv("USER")) { + char *xxx; + + xxx = (char *) malloc(strlen(user)+1); + if (xxx) { + strcpy(xxx, user); + kret = 0; + } + user = xxx; + } +#if HAVE_PWD_H + else if (pw = getpwuid(getuid())) { + if (user = (char *) malloc(strlen(pw->pw_name)+1)) { + strcpy(user, pw->pw_name); + kret = 0; + } + else + kret = ENOMEM; + } +#endif /* HAVE_PWD_H */ + + if (user) { + if (principal_name = (char *) malloc(strlen(user)+1+ + strlen(kadmin_instance)+1+ + strlen(realm_name)+1)) { + sprintf(principal_name, "%s/%s@%s", + user, kadmin_instance, realm_name); + free(user); + } + else + kret = ENOMEM; + } + if (kret || !user) { + com_err(argv[0], kret, kadmin_nopname_msg); + exit(1); + } + if (ccache) + krb5_cc_close(kcontext, ccache); + if (me) + krb5_free_principal(kcontext, me); + } + + /* Formulate the password prompt while we're here */ + if (password_prompt = (char *) malloc(strlen(kadmin_pprompt_fmt)+ + strlen(principal_name)+1)) { + sprintf(password_prompt, kadmin_pprompt_fmt, principal_name); + } + else { + com_err(argv[0], ENOMEM, kadmin_noprompt_msg); + exit(1); + } + + /* See if something's left, e.g. a request */ + if (argc > optind) { + size_t n2alloc; + int i; + + n2alloc = 0; + for (i=optind; i<argc; i++) + n2alloc += strlen(argv[i]) + 1; + + if (action = (char *) malloc(n2alloc)) { + for (i=optind; i<argc; i++) { + strcat(action, argv[i]); + strcat(action, " "); + } + } + } + return(action); +} + +/* + * Cleanup function. + */ +int +kadmin_cleanup() +{ + if (password_prompt) + free(password_prompt); + net_disconnect(1); +} diff --git a/src/kadmin/v5client/kadmin5.h b/src/kadmin/v5client/kadmin5.h new file mode 100644 index 0000000000..85d6a6239c --- /dev/null +++ b/src/kadmin/v5client/kadmin5.h @@ -0,0 +1,97 @@ +/* + * kadmin/v5client/kadmin5.h + * + * Copyright 1995 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ + +/* + * kadmin5.h - Describe common interfaces between kadmin modules. + */ +#ifndef KADMIN5_H__ +#define KADMIN5_H__ + +/* + * Global data. + */ +extern int exit_status; +extern krb5_context kcontext; +extern char *programname; +extern char *requestname; +extern krb5_boolean multiple; +extern char *principal_name; +extern char *password_prompt; + +/* + * Function prototypes. + */ +/* network.c */ +void print_proto_sreply + PROTOTYPE((krb5_int32, krb5_data *)); +void print_proto_error + PROTOTYPE((char *, + krb5_int32, + krb5_int32, + krb5_data *)); +void net_disconnect + PROTOTYPE((krb5_boolean)); +krb5_error_code net_do_proto + PROTOTYPE((char *, + char *, + char *, + krb5_int32, + krb5_data *, + krb5_int32 *, + krb5_int32 *, + krb5_data **)); + +/* convert.c */ +char * delta2string PROTOTYPE((krb5_deltat)); +char * abs2string PROTOTYPE((krb5_timestamp)); +char * dbflags2string PROTOTYPE((krb5_flags)); +char * salt2string PROTOTYPE((krb5_int32)); +krb5_boolean parse_princ_options PROTOTYPE((int, + char **, + krb5_ui_4 *, + krb5_db_entry *)); +void help_princ_options(); + +/* kadmin5.c */ +void kadmin_show_principal PROTOTYPE((int, char **)); +void kadmin_add_new_key PROTOTYPE((int, char **)); +void kadmin_change_pwd PROTOTYPE((int, char **)); +void kadmin_add_rnd_key PROTOTYPE((int, char **)); +void kadmin_change_rnd PROTOTYPE((int, char **)); +void kadmin_add_v4_key PROTOTYPE((int, char **)); +void kadmin_change_v4_key PROTOTYPE((int, char **)); +void kadmin_delete_entry PROTOTYPE((int, char **)); +void kadmin_extract PROTOTYPE((int, char **)); +void kadmin_extract_v4 PROTOTYPE((int, char **)); +void kadmin_modify PROTOTYPE((int, char **)); +void kadmin_rename PROTOTYPE((int, char **)); +void kadmin_list PROTOTYPE((int, char **)); +void kadmin_language PROTOTYPE((int, char **)); +void kadmin_mime PROTOTYPE((int, char **)); +void kadmin_cd PROTOTYPE((int, char **)); +void kadmin_pwd PROTOTYPE((int, char **)); +char * kadmin_startup PROTOTYPE((int, char **)); +int kadmin_cleanup(); +#endif /* KADMIN5_H__ */ + diff --git a/src/kadmin/v5client/kadmin5_ct.ct b/src/kadmin/v5client/kadmin5_ct.ct new file mode 100644 index 0000000000..5defef69ed --- /dev/null +++ b/src/kadmin/v5client/kadmin5_ct.ct @@ -0,0 +1,76 @@ +# $Source$ +# $Author$ +# $Id$ +# +# Copyright 1995 by the Massachusetts Institute of Technology. +# All Rights Reserved. +# +# Export of this software from the United States of America may +# require a specific license from the United States Government. +# It is the responsibility of any person or organization contemplating +# export to obtain such a license before exporting. +# +# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +# distribute this software and its documentation for any purpose and +# without fee is hereby granted, provided that the above copyright +# notice appear in all copies and that both that copyright notice and +# this permission notice appear in supporting documentation, and that +# the name of M.I.T. not be used in advertising or publicity pertaining +# to distribution of the software without specific, written prior +# permission. M.I.T. makes no representations about the suitability of +# this software for any purpose. It is provided "as is" without express +# or implied warranty. +# +# +# Command table for Kerberos administration client +# + +command_table kadmin_cmds; + +request kadmin_show_principal, "Show the Kerberos database entry for a principal.", + show_principal, show; + +request kadmin_add_new_key, "Add new entry to Kerberos database (prompting for new password).", + add_new_key, ank; + +request kadmin_change_pwd, "Change key of an entry in the Kerberos database (prompting for new password).", + change_pwd_key, cpw; + +request kadmin_add_rnd_key, "Add new entry to Kerberos database, using a random key.", + add_rnd_key, ark; + +request kadmin_change_rnd, "Change key of an entry in the Kerberos database (selecting a new random key).", + change_rnd_key, crk; + +request kadmin_delete_entry, "Delete an entry from the database.", + delete_entry, delent, del; + +request kadmin_extract, "Extract service key table entry/entries.", + extract_srvtab, xst, ex_st; + +request kadmin_extract_v4, "Extract service key table entry/entries in V4 format.", + extract_v4_srvtab, xst4; + +request kadmin_modify, "Modify database entry.", + modify_entry, modent; + +request kadmin_rename, "Rename database entry.", + rename_entry, renent; + +request kadmin_list, "List database entries.", + list_db, ldb; + +request kadmin_cd, "Change working directory.", + change_working_directory, cwd, cd; + +request kadmin_pwd, "Print working directory.", + print_working_directory, pwd; + +# list_requests is generic -- unrelated to Kerberos +request ss_list_requests, "List available requests.", + list_requests, lr, "?"; + +request ss_quit, "Exit program.", + quit, exit, q; + +end; diff --git a/src/kadmin/v5client/network.c b/src/kadmin/v5client/network.c new file mode 100644 index 0000000000..2c8b5b844f --- /dev/null +++ b/src/kadmin/v5client/network.c @@ -0,0 +1,321 @@ +/* + * kadmin/v5client/network.c + * + * Copyright 1995 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ + +/* + * network.c - Handle network and protocol related functions for kadmin5. + */ +#include "k5-int.h" +#include "com_err.h" +#include "adm.h" +#include "adm_proto.h" +#include "kadmin5.h" + +/* + * Own storage. + */ +static int server_socket = -1; +static krb5_auth_context *server_auth_context = (krb5_auth_context *) NULL; +static krb5_ccache server_ccache = (krb5_ccache) NULL; +static krb5_boolean server_active = 0; +static krb5_error_code server_stat = 0; +static krb5_boolean server_op_in_prog = 0; + +/* + * Static strings. + */ +static const char *kadmin_server_name = "kadmin-server"; +static const char *proto_serv_supp_msg = "server response follows:"; +static const char *proto_serv_end_msg = "end of server response."; +static const char *proto_cmd_unsupp_fmt = "(%s) %s protocol command not supported by server"; +static const char *proto_pw_unacc_fmt = "(%s) password unacceptable to server"; +static const char *proto_bad_pw_fmt = "(%s) bad password entered"; +static const char *proto_in_tkt_fmt = "(%s) not an initial ticket"; +static const char *proto_cant_chg_fmt = "(%s) cannot change password"; +static const char *proto_lang_uns_fmt = "(%s) language not supported"; +static const char *proto_p_exists_fmt = "(%s) principal already exists"; +static const char *proto_p_notexist_fmt = "(%s) principal does not exist"; +static const char *proto_no_auth_fmt = "(%s) not authorized for this operation"; +static const char *proto_bad_opt_fmt = "(%s) option not recognized by server"; +static const char *proto_value_req_fmt = "(%s) value required for option"; +static const char *proto_system_err_fmt = "(%s) remote system error"; +static const char *proto_ufo_err_fmt = "- (%s) protocol command %s returned unexpected error %d"; +static const char *net_conn_err_fmt = "- %s: cannot connect to server"; + +/* + * print_proto_sreply() - Print server's error reply strings. + */ +void +print_proto_sreply(ncomps, complist) + krb5_int32 ncomps; + krb5_data *complist; +{ + int i; + + if (ncomps > 0) { + for (i=0; i<ncomps; i++) + com_err(kadmin_server_name, 0, complist[i].data); + } +} + +/* + * print_proto_error() - Print protocol error message if appropriate. + */ +void +print_proto_error(cmd, cstat, ncomps, complist) + char *cmd; + krb5_int32 cstat; + krb5_int32 ncomps; + krb5_data *complist; +{ + switch (cstat) { + case KRB5_ADM_SUCCESS: + break; + case KRB5_ADM_CMD_UNKNOWN: + com_err(programname, 0, proto_cmd_unsupp_fmt, requestname, cmd); + break; + case KRB5_ADM_PW_UNACCEPT: + com_err(programname, 0, proto_pw_unacc_fmt, requestname); + break; + case KRB5_ADM_BAD_PW: + com_err(programname, 0, proto_bad_pw_fmt, requestname); + break; + case KRB5_ADM_NOT_IN_TKT: + com_err(programname, 0, proto_in_tkt_fmt, requestname); + break; + case KRB5_ADM_CANT_CHANGE: + com_err(programname, 0, proto_cant_chg_fmt, requestname); + break; + case KRB5_ADM_LANG_NOT_SUPPORTED: + com_err(programname, 0, proto_lang_uns_fmt, requestname); + break; + case KRB5_ADM_P_ALREADY_EXISTS: + com_err(programname, 0, proto_p_exists_fmt, requestname); + break; + case KRB5_ADM_P_DOES_NOT_EXIST: + com_err(programname, 0, proto_p_notexist_fmt, requestname); + break; + case KRB5_ADM_NOT_AUTHORIZED: + com_err(programname, 0, proto_no_auth_fmt, requestname); + break; + case KRB5_ADM_BAD_OPTION: + com_err(programname, 0, proto_bad_opt_fmt, requestname); + break; + case KRB5_ADM_VALUE_REQUIRED: + com_err(programname, 0, proto_value_req_fmt, requestname); + break; + case KRB5_ADM_SYSTEM_ERROR: + com_err(programname, 0, proto_system_err_fmt, requestname); + break; + default: + com_err(programname, cstat, proto_ufo_err_fmt, requestname, + cmd, cstat); + break; + } + if (cstat != KRB5_ADM_SUCCESS) + print_proto_sreply(ncomps, complist); +} + +/* + * net_connect() - Connect to the administrative server if not already + * connected or a separate connection is required for + * each transaction. + */ +static krb5_error_code +net_connect() +{ + krb5_error_code kret = 0; + + /* + * Drop the connection if we were in the middle of something before. + */ + if (server_op_in_prog) + net_disconnect(1); + + if (!multiple || !server_active) { + char opassword[KRB5_ADM_MAX_PASSWORD_LEN]; + + if (!(kret = server_stat = krb5_adm_connect(kcontext, + principal_name, + password_prompt, + opassword, + &server_socket, + &server_auth_context, + &server_ccache))) { + server_active = 1; + memset(opassword, 0, KRB5_ADM_MAX_PASSWORD_LEN); + } + else + com_err(programname, kret, net_conn_err_fmt, requestname); + } + return(kret); +} + +/* + * kadmin_disconnect() - Disconnect from the server. If there has been + * a server error, just close the socket. Otherwise + * engage in the disconnection protocol. + */ +void +net_disconnect(force) + krb5_boolean force; +{ + /* + * Only need to do this if we think the connection is active. + */ + if (server_active) { + /* + * Disconnect if: + * 1) this is a one-time-only connection. + * 2) there was an error on the connection. + * 3) somebody's forcing the disconnection. + */ + if (!multiple || (server_stat != 0) || force) { + /* If the connection is still good, then send a QUIT command */ + if ((server_stat == 0) && !server_op_in_prog) { + krb5_data quit_data; + krb5_int32 quit_status; + krb5_int32 quit_ncomps; + krb5_data *quit_reply; + + quit_data.data = KRB5_ADM_QUIT_CMD; + quit_data.length = strlen(quit_data.data); + if (!(server_stat = krb5_send_adm_cmd(kcontext, + &server_socket, + server_auth_context, + 1, + &quit_data))) + server_stat = krb5_read_adm_reply(kcontext, + &server_socket, + server_auth_context, + &quit_status, + &quit_ncomps, + &quit_reply); + if (!server_stat) { + print_proto_error(KRB5_ADM_QUIT_CMD, + quit_status, + quit_ncomps, + quit_reply); + krb5_free_adm_data(kcontext, quit_ncomps, quit_reply); + } + } + /* Break down the connection */ + krb5_adm_disconnect(kcontext, + &server_socket, + server_auth_context, + server_ccache); + + /* Clean up our state. */ + server_socket = -1; + server_auth_context = (krb5_auth_context *) NULL; + server_ccache = (krb5_ccache) NULL; + server_active = 0; + server_op_in_prog = 0; + server_stat = EINVAL; + } + } +} + +/* + * net_do_proto() - Perform a protocol request and return the results. + */ +krb5_error_code +net_do_proto(cmd, arg1, arg2, nargs, argp, rstatp, ncompp, complistp) + char *cmd; + char *arg1; + char *arg2; + krb5_int32 nargs; + krb5_data *argp; + krb5_int32 *rstatp; + krb5_int32 *ncompp; + krb5_data **complistp; +{ + krb5_error_code kret; + krb5_int32 nprotoargs; + krb5_data *protoargs; + + /* Connect to the server, if necessary */ + if (!(kret = net_connect())) { + + /* Figure out how many things we need to prepend to the arguments */ + nprotoargs = nargs + 1; + if (arg1) + nprotoargs++; + if (arg2) + nprotoargs++; + + /* Get the space for the new argument list */ + if (protoargs = (krb5_data *) malloc((size_t) nprotoargs * + sizeof(krb5_data))) { + int index = 0; + + /* Copy in the command */ + protoargs[index].data = cmd; + protoargs[index].length = strlen(cmd); + index++; + + /* Copy in the optional arguments */ + if (arg1) { + protoargs[index].data = arg1; + protoargs[index].length = strlen(arg1); + index++; + } + if (arg2) { + protoargs[index].data = arg2; + protoargs[index].length = strlen(arg2); + index++; + } + + /* Copy in the argument list */ + memcpy(&protoargs[index], argp, + (size_t) (nargs*sizeof(krb5_data))); + + server_op_in_prog = 1; + /* + * Now send the command. + */ + if (!(kret = server_stat = krb5_send_adm_cmd(kcontext, + &server_socket, + server_auth_context, + nprotoargs, + protoargs))) { + /* + * If that was successful, then try to read the reply. + */ + kret = server_stat = krb5_read_adm_reply(kcontext, + &server_socket, + server_auth_context, + rstatp, + ncompp, + complistp); + print_proto_error(cmd, *rstatp, *ncompp, *complistp); + } + server_op_in_prog = 0; + free(protoargs); + } + else + kret = ENOMEM; + net_disconnect(0); + } + return(kret); +} diff --git a/src/kadmin/v5client/ss_wrapper.c b/src/kadmin/v5client/ss_wrapper.c new file mode 100644 index 0000000000..26ef6dc8ca --- /dev/null +++ b/src/kadmin/v5client/ss_wrapper.c @@ -0,0 +1,61 @@ +/* + * kadmin/v5client/ss_wrapper.c + * + * Copyright 1995 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * ss_wrapper.c - ss wrapper for kadmin client. + */ + +#include "krb5.h" +#include <ss/ss.h> +#include <stdio.h> + +extern ss_request_table kadmin_cmds; +extern int exit_status; +extern char *kadmin_startup(); + +int main(argc, argv) + int argc; + char *argv[]; +{ + char *request; + krb5_error_code retval; + int sci_idx, code = 0; + + request = kadmin_startup(argc, argv); + sci_idx = ss_create_invocation("kadmin5", "5.0", (char *) NULL, + &kadmin_cmds, &retval); + if (retval) { + ss_perror(sci_idx, retval, "creating invocation"); + exit(1); + } + if (request) { + (void) ss_execute_line(sci_idx, request, &code); + free(request); + if (code != 0) { + ss_perror(sci_idx, code, request); + exit_status++; + } + } else + ss_listen(sci_idx, &retval); + return kadmin_cleanup() ? 1 : exit_status; +} |