diff options
author | markm <markm@FreeBSD.org> | 2000-01-09 20:58:00 +0000 |
---|---|---|
committer | markm <markm@FreeBSD.org> | 2000-01-09 20:58:00 +0000 |
commit | 4ecbd6db44d79348bc815f31096e53104f50838b (patch) | |
tree | 36fa73706fa0587a390c45a3fbf17c9523cb0e35 /crypto/heimdal/kadmin | |
download | FreeBSD-src-4ecbd6db44d79348bc815f31096e53104f50838b.zip FreeBSD-src-4ecbd6db44d79348bc815f31096e53104f50838b.tar.gz |
Import KTH Heimdal, which will be the core of our Kerberos5.
Userland to follow.
Diffstat (limited to 'crypto/heimdal/kadmin')
-rw-r--r-- | crypto/heimdal/kadmin/ChangeLog | 212 | ||||
-rw-r--r-- | crypto/heimdal/kadmin/Makefile.am | 55 | ||||
-rw-r--r-- | crypto/heimdal/kadmin/Makefile.in | 702 | ||||
-rw-r--r-- | crypto/heimdal/kadmin/ank.c | 266 | ||||
-rw-r--r-- | crypto/heimdal/kadmin/cpw.c | 177 | ||||
-rw-r--r-- | crypto/heimdal/kadmin/del.c | 53 | ||||
-rw-r--r-- | crypto/heimdal/kadmin/del_enctype.c | 132 | ||||
-rw-r--r-- | crypto/heimdal/kadmin/dump.c | 80 | ||||
-rw-r--r-- | crypto/heimdal/kadmin/ext.c | 116 | ||||
-rw-r--r-- | crypto/heimdal/kadmin/get.c | 250 | ||||
-rw-r--r-- | crypto/heimdal/kadmin/init.c | 210 | ||||
-rw-r--r-- | crypto/heimdal/kadmin/kadmin.c | 281 | ||||
-rw-r--r-- | crypto/heimdal/kadmin/kadmin_locl.h | 161 | ||||
-rw-r--r-- | crypto/heimdal/kadmin/kadmind.c | 151 | ||||
-rw-r--r-- | crypto/heimdal/kadmin/load.c | 335 | ||||
-rw-r--r-- | crypto/heimdal/kadmin/mod.c | 143 | ||||
-rw-r--r-- | crypto/heimdal/kadmin/random_password.c | 156 | ||||
-rw-r--r-- | crypto/heimdal/kadmin/rename.c | 66 | ||||
-rw-r--r-- | crypto/heimdal/kadmin/server.c | 506 | ||||
-rw-r--r-- | crypto/heimdal/kadmin/util.c | 520 | ||||
-rw-r--r-- | crypto/heimdal/kadmin/version4.c | 985 |
21 files changed, 5557 insertions, 0 deletions
diff --git a/crypto/heimdal/kadmin/ChangeLog b/crypto/heimdal/kadmin/ChangeLog new file mode 100644 index 0000000..542667e --- /dev/null +++ b/crypto/heimdal/kadmin/ChangeLog @@ -0,0 +1,212 @@ +2000-01-02 Assar Westerlund <assar@sics.se> + + * server.c: check initial flag in ticket and allow users to change + their own password if it's set + * ext.c (do_ext_keytab): set timestamp + +1999-12-14 Assar Westerlund <assar@sics.se> + + * del_enctype.c (usage): don't use arg_printusage + +1999-11-25 Assar Westerlund <assar@sics.se> + + * del_enctype.c (del_enctype): try not to leak memory + + * version4.c (kadm_ser_mod): use kadm5_s_modify_principal (no + _with_key) + + * kadmin.c: add `del_enctype' + + * del_enctype.c (del_enctype): new function for deleting enctypes + from a principal + + * Makefile.am (kadmin_SOURCES): add del_enctype.c + +1999-11-09 Johan Danielsson <joda@pdc.kth.se> + + * server.c: cope with old clients + + * kadmin_locl.h: remove version string + +1999-10-17 Assar Westerlund <assar@sics.se> + + * Makefile.am (kadmin_LDADD): add LIB_dlopen + +1999-10-01 Assar Westerlund <assar@sics.se> + + * ank.c (add_one_principal): `password' can cactually be NULL in + the overwrite code, check for it. + +1999-09-20 Assar Westerlund <assar@sics.se> + + * mod.c (mod_entry): print the correct principal name in error + messages. From Love <lha@e.kth.se> + +1999-09-10 Assar Westerlund <assar@sics.se> + + * init.c (init): also create `changepw/kerberos' + + * version4.c: only create you loose packets when we fail decoding + and not when an operation is not performed for some reason + (decode_packet): read the service key from the hdb + (dispatch, decode_packet): return proper error messages + + * version4.c (kadm_ser_cpw): add password quality functions + +1999-08-27 Johan Danielsson <joda@pdc.kth.se> + + * server.c (handle_v5): give more informative message if + KRB5_KT_NOTFOUND + +1999-08-26 Johan Danielsson <joda@pdc.kth.se> + + * kadmind.c: use HDB keytabs + +1999-08-25 Assar Westerlund <assar@sics.se> + + * cpw.c (set_password): use correct variable. From Love + <lha@e.kth.se> + + * server.c (v5_loop): use correct error code + + * ank.c (add_one_principal): initialize `default_ent' + +1999-08-21 Assar Westerlund <assar@sics.se> + + * random_password.c: new file, stolen from krb4 + + * kadmin_locl.h: add prototype for random_password + + * cpw.c: add support for --random-password + + * ank.c: add support for --random-password + + * Makefile.am (kadmin_SOURCES): add random_password.c + +1999-08-19 Assar Westerlund <assar@sics.se> + + * util.c (edit_timet): break when we manage to parse the time not + the inverse. + + * mod.c: add parsing of lots of options. From Love + <lha@stacken.kth.se> + + * ank.c: add setting of expiration and password expiration + + * kadmin_locl.h: update util.c prototypes + + * util.c: move-around. clean-up, rename, make consistent (and + some other weird stuff). based on patches from Love + <lha@stacken.kth.se> + + * version4.c (kadm_ser_cpw): initialize password + (handle_v4): remove unused variable `ret' + +1999-08-16 Assar Westerlund <assar@sics.se> + + * version4.c (handle_v4): more error checking and more correct + error messages + + * server.c (v5_loop, kadmind_loop): more error checking and more + correct error messages + +1999-07-24 Assar Westerlund <assar@sics.se> + + * util.c (str2timeval, edit_time): functions for parsing and + editing times. Based on patches from Love <lha@stacken.kth.se>. + (edit_entry): call new functions + + * mod.c (mod_entry): allow modifying expiration times + + * kadmin_locl.h (str2timeval): add prototype + + * ank.c (add_one_principal): allow setting expiration times + +1999-07-03 Assar Westerlund <assar@sics.se> + + * server.c (v5_loop): handle data allocation with krb5_data_alloc + and check return value + +1999-06-23 Assar Westerlund <assar@sics.se> + + * version4.c (kadm_ser_cpw): read the key in the strange order + it's sent + + * util.c (edit_entry): look at default + (edit_time): always set mask even if value == 0 + + * kadmin_locl.h (edit_entry): update + + * ank.c: make ank use the values of the default principal for + prompting + + * version4.c (values_to_ent): convert key data correctly + +1999-05-23 Assar Westerlund <assar@sics.se> + + * init.c (create_random_entry): more correct setting of mask + +1999-05-21 Assar Westerlund <assar@sics.se> + + * server.c (handle_v5): read sendauth version correctly. + +1999-05-14 Assar Westerlund <assar@sics.se> + + * version4.c (error_code): try to handle really old krb4 + distributions + +1999-05-11 Assar Westerlund <assar@sics.se> + + * init.c (init): initialize realm_max_life and realm_max_rlife + +1999-05-07 Assar Westerlund <assar@sics.se> + + * ank.c (add_new_key): initialize more variables + +1999-05-04 Assar Westerlund <assar@sics.se> + + * version4.c (kadm_ser_cpw): always allow a user to change her + password + (kadm_ser_*): make logging work + clean-up and restructure + + * kadmin_locl.h (set_entry): add prototype + + * kadmin.c (usage): update usage string + + * init.c (init): new arguments realm-max-ticket-life and + realm-max-renewable-life + + * util.c (edit_time, edit_attributes): don't do anything if it's + already set + (set_entry): new function + + * ank.c (add_new_key): new options for setting max-ticket-life, + max-renewable-life, and attributes + + * server.c (v5_loop): remove unused variable + + * kadmin_locl.h: add prototypes + + * version4.c: re-insert krb_err.h and other miss + + * server.c (kadmind_loop): break-up and restructure + + * version4.c: add ACL checks more error code checks restructure + +1999-05-03 Johan Danielsson <joda@pdc.kth.se> + + * load.c: check for (un-)encrypted keys + + * dump.c: use hdb_print_entry + + * version4.c: version 4 support + + * Makefile.am: link with krb4 + + * kadmin_locl.h: include <sys/un.h> + + * server.c: move from lib/kadm5, and add basic support for krb4 + kadmin protocol + + * kadmind.c: move recvauth to kadmind_loop() diff --git a/crypto/heimdal/kadmin/Makefile.am b/crypto/heimdal/kadmin/Makefile.am new file mode 100644 index 0000000..2bafb55 --- /dev/null +++ b/crypto/heimdal/kadmin/Makefile.am @@ -0,0 +1,55 @@ +# $Id: Makefile.am,v 1.25 2000/01/06 08:04:13 assar Exp $ + +include $(top_srcdir)/Makefile.am.common + +INCLUDES += $(INCLUDE_readline) $(INCLUDE_krb4) + +sbin_PROGRAMS = kadmin + +libexec_PROGRAMS = kadmind + +kadmin_SOURCES = \ + ank.c \ + cpw.c \ + del.c \ + del_enctype.c \ + dump.c \ + ext.c \ + get.c \ + init.c \ + kadmin.c \ + load.c \ + mod.c \ + rename.c \ + util.c \ + random_password.c \ + kadmin_locl.h + +if KRB4 +KRB4LIB = $(LIB_krb4) +version4_c = version4.c +endif + +kadmind_SOURCES = kadmind.c server.c kadmin_locl.h $(version4_c) + +EXTRA_kadmind_SOURCES = version4.c + +COMMON_LDADD = \ + $(top_builddir)/lib/hdb/libhdb.la \ + $(top_builddir)/lib/krb5/libkrb5.la \ + $(top_builddir)/lib/des/libdes.la \ + $(top_builddir)/lib/asn1/libasn1.la \ + $(LIB_roken) \ + $(DBLIB) + +kadmind_LDADD = $(KRB4LIB) $(top_builddir)/lib/kadm5/libkadm5srv.la \ + $(COMMON_LDADD) \ + $(LIB_dlopen) + +kadmin_LDADD = \ + $(top_builddir)/lib/kadm5/libkadm5clnt.la \ + $(top_builddir)/lib/kadm5/libkadm5srv.la \ + $(top_builddir)/lib/sl/libsl.la \ + $(LIB_readline) \ + $(COMMON_LDADD) \ + $(LIB_dlopen) diff --git a/crypto/heimdal/kadmin/Makefile.in b/crypto/heimdal/kadmin/Makefile.in new file mode 100644 index 0000000..b7fa775 --- /dev/null +++ b/crypto/heimdal/kadmin/Makefile.in @@ -0,0 +1,702 @@ +# Makefile.in generated automatically by automake 1.4 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +# $Id: Makefile.am,v 1.25 2000/01/06 08:04:13 assar Exp $ + + +# $Id: Makefile.am.common,v 1.3 1999/04/01 14:58:43 joda Exp $ + + +# $Id: Makefile.am.common,v 1.13 1999/11/01 03:19:58 assar Exp $ + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ +AFS_EXTRA_LD = @AFS_EXTRA_LD@ +AIX_EXTRA_KAFS = @AIX_EXTRA_KAFS@ +AWK = @AWK@ +CANONICAL_HOST = @CANONICAL_HOST@ +CATMAN = @CATMAN@ +CATMANEXT = @CATMANEXT@ +CC = @CC@ +DBLIB = @DBLIB@ +EXEEXT = @EXEEXT@ +EXTRA_LIB45 = @EXTRA_LIB45@ +GROFF = @GROFF@ +INCLUDE_ = @INCLUDE_@ +LD = @LD@ +LEX = @LEX@ +LIBOBJS = @LIBOBJS@ +LIBTOOL = @LIBTOOL@ +LIB_ = @LIB_@ +LIB_AUTH_SUBDIRS = @LIB_AUTH_SUBDIRS@ +LIB_kdb = @LIB_kdb@ +LIB_otp = @LIB_otp@ +LIB_roken = @LIB_roken@ +LIB_security = @LIB_security@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MAKE_X_PROGS_BIN_PROGS = @MAKE_X_PROGS_BIN_PROGS@ +MAKE_X_PROGS_BIN_SCRPTS = @MAKE_X_PROGS_BIN_SCRPTS@ +MAKE_X_PROGS_LIBEXEC_PROGS = @MAKE_X_PROGS_LIBEXEC_PROGS@ +NEED_WRITEAUTH_FALSE = @NEED_WRITEAUTH_FALSE@ +NEED_WRITEAUTH_TRUE = @NEED_WRITEAUTH_TRUE@ +NM = @NM@ +NROFF = @NROFF@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +VERSION = @VERSION@ +VOID_RETSIGTYPE = @VOID_RETSIGTYPE@ +WFLAGS = @WFLAGS@ +WFLAGS_NOIMPLICITINT = @WFLAGS_NOIMPLICITINT@ +WFLAGS_NOUNUSED = @WFLAGS_NOUNUSED@ +YACC = @YACC@ + +AUTOMAKE_OPTIONS = foreign no-dependencies + +SUFFIXES = .et .h .1 .3 .5 .8 .cat1 .cat3 .cat5 .cat8 .x + +INCLUDES = -I$(top_builddir)/include $(INCLUDE_readline) $(INCLUDE_krb4) + +AM_CFLAGS = $(WFLAGS) + +COMPILE_ET = $(top_builddir)/lib/com_err/compile_et + +buildinclude = $(top_builddir)/include + +LIB_XauReadAuth = @LIB_XauReadAuth@ +LIB_crypt = @LIB_crypt@ +LIB_dbm_firstkey = @LIB_dbm_firstkey@ +LIB_dbopen = @LIB_dbopen@ +LIB_dlopen = @LIB_dlopen@ +LIB_dn_expand = @LIB_dn_expand@ +LIB_el_init = @LIB_el_init@ +LIB_getattr = @LIB_getattr@ +LIB_gethostbyname = @LIB_gethostbyname@ +LIB_getpwent_r = @LIB_getpwent_r@ +LIB_getpwnam_r = @LIB_getpwnam_r@ +LIB_getsockopt = @LIB_getsockopt@ +LIB_logout = @LIB_logout@ +LIB_logwtmp = @LIB_logwtmp@ +LIB_odm_initialize = @LIB_odm_initialize@ +LIB_readline = @LIB_readline@ +LIB_res_search = @LIB_res_search@ +LIB_setpcred = @LIB_setpcred@ +LIB_setsockopt = @LIB_setsockopt@ +LIB_socket = @LIB_socket@ +LIB_syslog = @LIB_syslog@ +LIB_tgetent = @LIB_tgetent@ + +HESIODLIB = @HESIODLIB@ +HESIODINCLUDE = @HESIODINCLUDE@ +INCLUDE_hesiod = @INCLUDE_hesiod@ +LIB_hesiod = @LIB_hesiod@ + +INCLUDE_krb4 = @INCLUDE_krb4@ +LIB_krb4 = @LIB_krb4@ + +INCLUDE_readline = @INCLUDE_readline@ + +LEXLIB = @LEXLIB@ + +cat1dir = $(mandir)/cat1 +cat3dir = $(mandir)/cat3 +cat5dir = $(mandir)/cat5 +cat8dir = $(mandir)/cat8 + +MANRX = \(.*\)\.\([0-9]\) +CATSUFFIX = @CATSUFFIX@ + +NROFF_MAN = groff -mandoc -Tascii + +@KRB4_TRUE@LIB_kafs = $(top_builddir)/lib/kafs/libkafs.la $(AIX_EXTRA_KAFS) + +@KRB5_TRUE@LIB_krb5 = $(top_builddir)/lib/krb5/libkrb5.la $(top_builddir)/lib/asn1/libasn1.la +@KRB5_TRUE@LIB_gssapi = $(top_builddir)/lib/gssapi/libgssapi.la + +CHECK_LOCAL = $(PROGRAMS) + +sbin_PROGRAMS = kadmin + +libexec_PROGRAMS = kadmind + +kadmin_SOURCES = ank.c cpw.c del.c del_enctype.c dump.c ext.c get.c init.c kadmin.c load.c mod.c rename.c util.c random_password.c kadmin_locl.h + + +@KRB4_TRUE@KRB4LIB = $(LIB_krb4) +@KRB4_TRUE@version4_c = version4.c + +kadmind_SOURCES = kadmind.c server.c kadmin_locl.h $(version4_c) + +EXTRA_kadmind_SOURCES = version4.c + +COMMON_LDADD = $(top_builddir)/lib/hdb/libhdb.la $(top_builddir)/lib/krb5/libkrb5.la $(top_builddir)/lib/des/libdes.la $(top_builddir)/lib/asn1/libasn1.la $(LIB_roken) $(DBLIB) + + +kadmind_LDADD = $(KRB4LIB) $(top_builddir)/lib/kadm5/libkadm5srv.la $(COMMON_LDADD) $(LIB_dlopen) + + +kadmin_LDADD = $(top_builddir)/lib/kadm5/libkadm5clnt.la $(top_builddir)/lib/kadm5/libkadm5srv.la $(top_builddir)/lib/sl/libsl.la $(LIB_readline) $(COMMON_LDADD) $(LIB_dlopen) + +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../include/config.h +CONFIG_CLEAN_FILES = +libexec_PROGRAMS = kadmind$(EXEEXT) +sbin_PROGRAMS = kadmin$(EXEEXT) +PROGRAMS = $(libexec_PROGRAMS) $(sbin_PROGRAMS) + + +DEFS = @DEFS@ -I. -I$(srcdir) -I../include +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +X_CFLAGS = @X_CFLAGS@ +X_LIBS = @X_LIBS@ +X_EXTRA_LIBS = @X_EXTRA_LIBS@ +X_PRE_LIBS = @X_PRE_LIBS@ +@KRB4_TRUE@kadmind_OBJECTS = kadmind.$(OBJEXT) server.$(OBJEXT) \ +@KRB4_TRUE@version4.$(OBJEXT) +@KRB4_FALSE@kadmind_OBJECTS = kadmind.$(OBJEXT) server.$(OBJEXT) +@KRB4_TRUE@kadmind_DEPENDENCIES = \ +@KRB4_TRUE@$(top_builddir)/lib/kadm5/libkadm5srv.la \ +@KRB4_TRUE@$(top_builddir)/lib/hdb/libhdb.la \ +@KRB4_TRUE@$(top_builddir)/lib/krb5/libkrb5.la \ +@KRB4_TRUE@$(top_builddir)/lib/des/libdes.la \ +@KRB4_TRUE@$(top_builddir)/lib/asn1/libasn1.la +@KRB4_FALSE@kadmind_DEPENDENCIES = \ +@KRB4_FALSE@$(top_builddir)/lib/kadm5/libkadm5srv.la \ +@KRB4_FALSE@$(top_builddir)/lib/hdb/libhdb.la \ +@KRB4_FALSE@$(top_builddir)/lib/krb5/libkrb5.la \ +@KRB4_FALSE@$(top_builddir)/lib/des/libdes.la \ +@KRB4_FALSE@$(top_builddir)/lib/asn1/libasn1.la +kadmind_LDFLAGS = +kadmin_OBJECTS = ank.$(OBJEXT) cpw.$(OBJEXT) del.$(OBJEXT) \ +del_enctype.$(OBJEXT) dump.$(OBJEXT) ext.$(OBJEXT) get.$(OBJEXT) \ +init.$(OBJEXT) kadmin.$(OBJEXT) load.$(OBJEXT) mod.$(OBJEXT) \ +rename.$(OBJEXT) util.$(OBJEXT) random_password.$(OBJEXT) +kadmin_DEPENDENCIES = $(top_builddir)/lib/kadm5/libkadm5clnt.la \ +$(top_builddir)/lib/kadm5/libkadm5srv.la \ +$(top_builddir)/lib/sl/libsl.la $(top_builddir)/lib/hdb/libhdb.la \ +$(top_builddir)/lib/krb5/libkrb5.la $(top_builddir)/lib/des/libdes.la \ +$(top_builddir)/lib/asn1/libasn1.la +kadmin_LDFLAGS = +CFLAGS = @CFLAGS@ +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ +DIST_COMMON = ChangeLog Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP_ENV = --best +SOURCES = $(kadmind_SOURCES) $(EXTRA_kadmind_SOURCES) $(kadmin_SOURCES) +OBJECTS = $(kadmind_OBJECTS) $(kadmin_OBJECTS) + +all: all-redirect +.SUFFIXES: +.SUFFIXES: .1 .3 .5 .8 .S .c .cat1 .cat3 .cat5 .cat8 .et .h .lo .o .obj .s .x +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) $(top_srcdir)/Makefile.am.common $(top_srcdir)/cf/Makefile.am.common + cd $(top_srcdir) && $(AUTOMAKE) --foreign kadmin/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + + +mostlyclean-libexecPROGRAMS: + +clean-libexecPROGRAMS: + -test -z "$(libexec_PROGRAMS)" || rm -f $(libexec_PROGRAMS) + +distclean-libexecPROGRAMS: + +maintainer-clean-libexecPROGRAMS: + +install-libexecPROGRAMS: $(libexec_PROGRAMS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(libexecdir) + @list='$(libexec_PROGRAMS)'; for p in $$list; do \ + if test -f $$p; then \ + echo " $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(libexecdir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \ + $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(libexecdir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ + else :; fi; \ + done + +uninstall-libexecPROGRAMS: + @$(NORMAL_UNINSTALL) + list='$(libexec_PROGRAMS)'; for p in $$list; do \ + rm -f $(DESTDIR)$(libexecdir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ + done + +mostlyclean-sbinPROGRAMS: + +clean-sbinPROGRAMS: + -test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS) + +distclean-sbinPROGRAMS: + +maintainer-clean-sbinPROGRAMS: + +install-sbinPROGRAMS: $(sbin_PROGRAMS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(sbindir) + @list='$(sbin_PROGRAMS)'; for p in $$list; do \ + if test -f $$p; then \ + echo " $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(sbindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \ + $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(sbindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ + else :; fi; \ + done + +uninstall-sbinPROGRAMS: + @$(NORMAL_UNINSTALL) + list='$(sbin_PROGRAMS)'; for p in $$list; do \ + rm -f $(DESTDIR)$(sbindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ + done + +.c.o: + $(COMPILE) -c $< + +# FIXME: We should only use cygpath when building on Windows, +# and only if it is available. +.c.obj: + $(COMPILE) -c `cygpath -w $<` + +.s.o: + $(COMPILE) -c $< + +.S.o: + $(COMPILE) -c $< + +mostlyclean-compile: + -rm -f *.o core *.core + -rm -f *.$(OBJEXT) + +clean-compile: + +distclean-compile: + -rm -f *.tab.c + +maintainer-clean-compile: + +.c.lo: + $(LIBTOOL) --mode=compile $(COMPILE) -c $< + +.s.lo: + $(LIBTOOL) --mode=compile $(COMPILE) -c $< + +.S.lo: + $(LIBTOOL) --mode=compile $(COMPILE) -c $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + +maintainer-clean-libtool: + +kadmind$(EXEEXT): $(kadmind_OBJECTS) $(kadmind_DEPENDENCIES) + @rm -f kadmind$(EXEEXT) + $(LINK) $(kadmind_LDFLAGS) $(kadmind_OBJECTS) $(kadmind_LDADD) $(LIBS) + +kadmin$(EXEEXT): $(kadmin_OBJECTS) $(kadmin_DEPENDENCIES) + @rm -f kadmin$(EXEEXT) + $(LINK) $(kadmin_LDFLAGS) $(kadmin_OBJECTS) $(kadmin_LDADD) $(LIBS) + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = kadmin + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done + $(MAKE) $(AM_MAKEFLAGS) top_distdir="$(top_distdir)" distdir="$(distdir)" dist-hook +info-am: +info: info-am +dvi-am: +dvi: dvi-am +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) check-local +check: check-am +installcheck-am: +installcheck: installcheck-am +install-exec-am: install-libexecPROGRAMS install-sbinPROGRAMS + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-exec-hook +install-exec: install-exec-am + +install-data-am: install-data-local +install-data: install-data-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-am +uninstall-am: uninstall-libexecPROGRAMS uninstall-sbinPROGRAMS +uninstall: uninstall-am +all-am: Makefile $(PROGRAMS) all-local +all-redirect: all-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: + $(mkinstalldirs) $(DESTDIR)$(libexecdir) $(DESTDIR)$(sbindir) + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-libexecPROGRAMS mostlyclean-sbinPROGRAMS \ + mostlyclean-compile mostlyclean-libtool \ + mostlyclean-tags mostlyclean-generic + +mostlyclean: mostlyclean-am + +clean-am: clean-libexecPROGRAMS clean-sbinPROGRAMS clean-compile \ + clean-libtool clean-tags clean-generic mostlyclean-am + +clean: clean-am + +distclean-am: distclean-libexecPROGRAMS distclean-sbinPROGRAMS \ + distclean-compile distclean-libtool distclean-tags \ + distclean-generic clean-am + -rm -f libtool + +distclean: distclean-am + +maintainer-clean-am: maintainer-clean-libexecPROGRAMS \ + maintainer-clean-sbinPROGRAMS maintainer-clean-compile \ + maintainer-clean-libtool maintainer-clean-tags \ + maintainer-clean-generic distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-am + +.PHONY: mostlyclean-libexecPROGRAMS distclean-libexecPROGRAMS \ +clean-libexecPROGRAMS maintainer-clean-libexecPROGRAMS \ +uninstall-libexecPROGRAMS install-libexecPROGRAMS \ +mostlyclean-sbinPROGRAMS distclean-sbinPROGRAMS clean-sbinPROGRAMS \ +maintainer-clean-sbinPROGRAMS uninstall-sbinPROGRAMS \ +install-sbinPROGRAMS mostlyclean-compile distclean-compile \ +clean-compile maintainer-clean-compile mostlyclean-libtool \ +distclean-libtool clean-libtool maintainer-clean-libtool tags \ +mostlyclean-tags distclean-tags clean-tags maintainer-clean-tags \ +distdir info-am info dvi-am dvi check-local check check-am \ +installcheck-am installcheck install-exec-am install-exec \ +install-data-local install-data-am install-data install-am install \ +uninstall-am uninstall all-local all-redirect all-am all installdirs \ +mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + + +install-suid-programs: + @foo='$(bin_SUIDS)'; \ + for file in $$foo; do \ + x=$(DESTDIR)$(bindir)/$$file; \ + if chown 0:0 $$x && chmod u+s $$x; then :; else \ + chmod 0 $$x; fi; done + +install-exec-hook: install-suid-programs + +install-build-headers:: $(include_HEADERS) $(build_HEADERZ) + @foo='$(include_HEADERS) $(build_HEADERZ)'; \ + for f in $$foo; do \ + f=`basename $$f`; \ + if test -f "$(srcdir)/$$f"; then file="$(srcdir)/$$f"; \ + else file="$$f"; fi; \ + if cmp -s $$file $(buildinclude)/$$f 2> /dev/null ; then \ + : ; else \ + echo " cp $$file $(buildinclude)/$$f"; \ + cp $$file $(buildinclude)/$$f; \ + fi ; \ + done + +all-local: install-build-headers +#NROFF_MAN = nroff -man +.1.cat1: + $(NROFF_MAN) $< > $@ +.3.cat3: + $(NROFF_MAN) $< > $@ +.5.cat5: + $(NROFF_MAN) $< > $@ +.8.cat8: + $(NROFF_MAN) $< > $@ + +dist-cat1-mans: + @foo='$(man1_MANS)'; \ + bar='$(man_MANS)'; \ + for i in $$bar; do \ + case $$i in \ + *.1) foo="$$foo $$i";; \ + esac; done ;\ + for i in $$foo; do \ + x=`echo $$i | sed 's/\.[^.]*$$/.cat1/'`; \ + echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \ + $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \ + done + +dist-cat3-mans: + @foo='$(man3_MANS)'; \ + bar='$(man_MANS)'; \ + for i in $$bar; do \ + case $$i in \ + *.3) foo="$$foo $$i";; \ + esac; done ;\ + for i in $$foo; do \ + x=`echo $$i | sed 's/\.[^.]*$$/.cat3/'`; \ + echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \ + $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \ + done + +dist-cat5-mans: + @foo='$(man5_MANS)'; \ + bar='$(man_MANS)'; \ + for i in $$bar; do \ + case $$i in \ + *.5) foo="$$foo $$i";; \ + esac; done ;\ + for i in $$foo; do \ + x=`echo $$i | sed 's/\.[^.]*$$/.cat5/'`; \ + echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \ + $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \ + done + +dist-cat8-mans: + @foo='$(man8_MANS)'; \ + bar='$(man_MANS)'; \ + for i in $$bar; do \ + case $$i in \ + *.8) foo="$$foo $$i";; \ + esac; done ;\ + for i in $$foo; do \ + x=`echo $$i | sed 's/\.[^.]*$$/.cat8/'`; \ + echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \ + $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \ + done + +dist-hook: dist-cat1-mans dist-cat3-mans dist-cat5-mans dist-cat8-mans + +install-cat1-mans: + @ext=1;\ + foo='$(man1_MANS)'; \ + bar='$(man_MANS)'; \ + for i in $$bar; do \ + case $$i in \ + *.1) foo="$$foo $$i";; \ + esac; done; \ + if test "$$foo"; then \ + $(mkinstalldirs) $(DESTDIR)$(cat1dir); \ + for x in $$foo; do \ + f=`echo $$x | sed 's/\.[^.]*$$/.cat1/'`; \ + if test -f "$(srcdir)/$$f"; then \ + b=`echo $$x | sed 's!$(MANRX)!\1!'`; \ + echo "$(INSTALL_DATA) $(srcdir)/$$f $(DESTDIR)$(cat1dir)/$$b.$(CATSUFFIX)";\ + $(INSTALL_DATA) $(srcdir)/$$g $(DESTDIR)$(cat1dir)/$$b.$(CATSUFFIX);\ + fi; \ + done ;\ + fi + +install-cat3-mans: + @ext=3;\ + foo='$(man3_MANS)'; \ + bar='$(man_MANS)'; \ + for i in $$bar; do \ + case $$i in \ + *.3) foo="$$foo $$i";; \ + esac; done; \ + if test "$$foo"; then \ + $(mkinstalldirs) $(DESTDIR)$(cat3dir); \ + for x in $$foo; do \ + f=`echo $$x | sed 's/\.[^.]*$$/.cat3/'`; \ + if test -f "$(srcdir)/$$f"; then \ + b=`echo $$x | sed 's!$(MANRX)!\1!'`; \ + echo "$(INSTALL_DATA) $(srcdir)/$$f $(DESTDIR)$(cat3dir)/$$b.$(CATSUFFIX)";\ + $(INSTALL_DATA) $(srcdir)/$$g $(DESTDIR)$(cat3dir)/$$b.$(CATSUFFIX);\ + fi; \ + done ;\ + fi + +install-cat5-mans: + @ext=5;\ + foo='$(man5_MANS)'; \ + bar='$(man_MANS)'; \ + for i in $$bar; do \ + case $$i in \ + *.5) foo="$$foo $$i";; \ + esac; done; \ + if test "$$foo"; then \ + $(mkinstalldirs) $(DESTDIR)$(cat5dir); \ + for x in $$foo; do \ + f=`echo $$x | sed 's/\.[^.]*$$/.cat5/'`; \ + if test -f "$(srcdir)/$$f"; then \ + b=`echo $$x | sed 's!$(MANRX)!\1!'`; \ + echo "$(INSTALL_DATA) $(srcdir)/$$f $(DESTDIR)$(cat5dir)/$$b.$(CATSUFFIX)";\ + $(INSTALL_DATA) $(srcdir)/$$g $(DESTDIR)$(cat5dir)/$$b.$(CATSUFFIX);\ + fi; \ + done ;\ + fi + +install-cat8-mans: + @ext=8;\ + foo='$(man8_MANS)'; \ + bar='$(man_MANS)'; \ + for i in $$bar; do \ + case $$i in \ + *.8) foo="$$foo $$i";; \ + esac; done; \ + if test "$$foo"; then \ + $(mkinstalldirs) $(DESTDIR)$(cat8dir); \ + for x in $$foo; do \ + f=`echo $$x | sed 's/\.[^.]*$$/.cat8/'`; \ + if test -f "$(srcdir)/$$f"; then \ + b=`echo $$x | sed 's!$(MANRX)!\1!'`; \ + echo "$(INSTALL_DATA) $(srcdir)/$$f $(DESTDIR)$(cat8dir)/$$b.$(CATSUFFIX)";\ + $(INSTALL_DATA) $(srcdir)/$$g $(DESTDIR)$(cat8dir)/$$b.$(CATSUFFIX);\ + fi; \ + done ;\ + fi + +install-cat-mans: install-cat1-mans install-cat3-mans install-cat5-mans install-cat8-mans + +install-data-local: install-cat-mans + +.et.h: + $(COMPILE_ET) $< +.et.c: + $(COMPILE_ET) $< + +.x.c: + @cmp -s $< $@ 2> /dev/null || cp $< $@ + +check-local:: + @foo='$(CHECK_LOCAL)'; \ + if test "$$foo"; then \ + failed=0; all=0; \ + for i in $$foo; do \ + all=`expr $$all + 1`; \ + if ./$$i --version > /dev/null 2>&1; then \ + echo "PASS: $$i"; \ + else \ + echo "FAIL: $$i"; \ + failed=`expr $$failed + 1`; \ + fi; \ + done; \ + if test "$$failed" -eq 0; then \ + banner="All $$all tests passed"; \ + else \ + banner="$$failed of $$all tests failed"; \ + fi; \ + dashes=`echo "$$banner" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + echo "$$dashes"; \ + test "$$failed" -eq 0; \ + fi + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/crypto/heimdal/kadmin/ank.c b/crypto/heimdal/kadmin/ank.c new file mode 100644 index 0000000..7068912 --- /dev/null +++ b/crypto/heimdal/kadmin/ank.c @@ -0,0 +1,266 @@ +/* + * Copyright (c) 1997 - 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "kadmin_locl.h" + +RCSID("$Id: ank.c,v 1.19 1999/12/02 17:04:57 joda Exp $"); + +/* + * fetch the default principal corresponding to `princ' + */ + +static krb5_error_code +get_default (kadm5_server_context *context, + krb5_principal princ, + kadm5_principal_ent_t default_ent) +{ + krb5_error_code ret; + krb5_principal def_principal; + krb5_realm *realm = krb5_princ_realm(context->context, princ); + + ret = krb5_make_principal (context->context, &def_principal, + *realm, "default", NULL); + if (ret) + return ret; + ret = kadm5_get_principal (context, def_principal, default_ent, + KADM5_PRINCIPAL_NORMAL_MASK); + krb5_free_principal (context->context, def_principal); + return ret; +} + +/* + * Add the principal `name' to the database. + * Prompt for all data not given by the input parameters. + */ + +static krb5_error_code +add_one_principal (const char *name, + int rand_key, + int rand_password, + char *password, + const char *max_ticket_life, + const char *max_renewable_life, + const char *attributes, + const char *expiration, + const char *pw_expiration) +{ + krb5_error_code ret; + kadm5_principal_ent_rec princ, defrec; + kadm5_principal_ent_rec *default_ent = NULL; + krb5_principal princ_ent = NULL; + int mask = 0; + int default_mask = 0; + char pwbuf[1024]; + + memset(&princ, 0, sizeof(princ)); + ret = krb5_parse_name(context, name, &princ_ent); + if (ret) { + krb5_warn(context, ret, "krb5_parse_name"); + return ret; + } + princ.principal = princ_ent; + mask |= KADM5_PRINCIPAL; + + ret = set_entry(context, &princ, &mask, + max_ticket_life, max_renewable_life, + expiration, pw_expiration, attributes); + if (ret) + goto out; + + default_ent = &defrec; + ret = get_default (kadm_handle, princ_ent, default_ent); + if (ret) { + default_ent = NULL; + default_mask = 0; + } else { + default_mask = KADM5_ATTRIBUTES | KADM5_MAX_LIFE | KADM5_MAX_RLIFE | + KADM5_PRINC_EXPIRE_TIME | KADM5_PW_EXPIRATION; + } + + edit_entry(&princ, &mask, default_ent, default_mask); + if(rand_key) { + princ.attributes |= KRB5_KDB_DISALLOW_ALL_TIX; + mask |= KADM5_ATTRIBUTES; + strlcpy (pwbuf, "hemlig", sizeof(pwbuf)); + password = pwbuf; + } else if (rand_password) { + random_password (pwbuf, sizeof(pwbuf)); + password = pwbuf; + } else if(password == NULL) { + char *princ_name; + char *prompt; + + krb5_unparse_name(context, princ_ent, &princ_name); + asprintf (&prompt, "%s's Password: ", princ_name); + free (princ_name); + ret = des_read_pw_string (pwbuf, sizeof(pwbuf), prompt, 1); + free (prompt); + if (ret) + goto out; + password = pwbuf; + } + + ret = kadm5_create_principal(kadm_handle, &princ, mask, password); + if(ret) + krb5_warn(context, ret, "kadm5_create_principal"); + if(rand_key) { + krb5_keyblock *new_keys; + int n_keys, i; + ret = kadm5_randkey_principal(kadm_handle, princ_ent, + &new_keys, &n_keys); + if(ret){ + krb5_warn(context, ret, "kadm5_randkey_principal"); + n_keys = 0; + } + for(i = 0; i < n_keys; i++) + krb5_free_keyblock_contents(context, &new_keys[i]); + free(new_keys); + kadm5_get_principal(kadm_handle, princ_ent, &princ, + KADM5_PRINCIPAL | KADM5_KVNO | KADM5_ATTRIBUTES); + princ.attributes &= (~KRB5_KDB_DISALLOW_ALL_TIX); + princ.kvno = 1; + kadm5_modify_principal(kadm_handle, &princ, + KADM5_ATTRIBUTES | KADM5_KVNO); + kadm5_free_principal_ent(kadm_handle, &princ); + } else if (rand_password) { + char *princ_name; + + krb5_unparse_name(context, princ_ent, &princ_name); + printf ("added %s with password `%s'\n", princ_name, password); + free (princ_name); + } +out: + if (princ_ent) + krb5_free_principal (context, princ_ent); + if(default_ent) + kadm5_free_principal_ent (context, default_ent); + if (password != NULL) + memset (password, 0, strlen(password)); + return ret; +} + +/* + * the ank command + */ + +static struct getargs args[] = { + { "random-key", 'r', arg_flag, NULL, "set random key" }, + { "random-password", 0, arg_flag, NULL, "set random password" }, + { "password", 'p', arg_string, NULL, "princial's password" }, + { "max-ticket-life", 0, arg_string, NULL, "max ticket lifetime", + "lifetime"}, + { "max-renewable-life", 0, arg_string, NULL, + "max renewable lifetime", "lifetime" }, + { "attributes", 0, arg_string, NULL, "principal attributes", + "attributes"}, + { "expiration-time",0, arg_string, NULL, "Expiration time", + "time"}, + { "pw-expiration-time", 0, arg_string, NULL, + "Password expiration time", "time"} +}; + +static int num_args = sizeof(args) / sizeof(args[0]); + +static void +usage(void) +{ + arg_printusage (args, num_args, "ank", "principal"); +} + +/* + * Parse arguments and add all the principals. + */ + +int +add_new_key(int argc, char **argv) +{ + char *password = NULL; + int random_key = 0; + int random_password = 0; + int optind = 0; + krb5_error_code ret; + char *max_ticket_life = NULL; + char *max_renewable_life = NULL; + char *attributes = NULL; + char *expiration = NULL; + char *pw_expiration = NULL; + int i; + int num; + + args[0].value = &random_key; + args[1].value = &random_password; + args[2].value = &password; + args[3].value = &max_ticket_life; + args[4].value = &max_renewable_life; + args[5].value = &attributes; + args[6].value = &expiration; + args[7].value = &pw_expiration; + + if(getarg(args, num_args, argc, argv, &optind)) { + usage (); + return 0; + } + if(optind == argc) { + usage (); + return 0; + } + + num = 0; + if (random_key) + ++num; + if (random_password) + ++num; + if (password) + ++num; + + if (num > 1) { + printf ("give only one of " + "--random-key, --random-password, --password\n"); + return 0; + } + + for (i = optind; i < argc; ++i) { + ret = add_one_principal (argv[i], random_key, random_password, + password, + max_ticket_life, + max_renewable_life, + attributes, + expiration, + pw_expiration); + if (ret) { + krb5_warn (context, ret, "adding %s", argv[i]); + break; + } + } + return 0; +} diff --git a/crypto/heimdal/kadmin/cpw.c b/crypto/heimdal/kadmin/cpw.c new file mode 100644 index 0000000..2bd71a7 --- /dev/null +++ b/crypto/heimdal/kadmin/cpw.c @@ -0,0 +1,177 @@ +/* + * Copyright (c) 1997, 1998, 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "kadmin_locl.h" + +RCSID("$Id: cpw.c,v 1.9 1999/12/02 17:04:57 joda Exp $"); + +struct cpw_entry_data { + int random_key; + int random_password; + char *password; +}; + +static struct getargs args[] = { + { "random-key", 'r', arg_flag, NULL, "set random key" }, + { "random-password", 0, arg_flag, NULL, "set random password" }, + { "password", 'p', arg_string, NULL, "princial's password" }, +}; + +static int num_args = sizeof(args) / sizeof(args[0]); + +static void +usage(void) +{ + arg_printusage(args, num_args, "cpw", "principal..."); +} + +static int +set_random_key (krb5_principal principal) +{ + krb5_error_code ret; + int i; + krb5_keyblock *keys; + int num_keys; + + ret = kadm5_randkey_principal(kadm_handle, principal, &keys, &num_keys); + if(ret) + return ret; + for(i = 0; i < num_keys; i++) + krb5_free_keyblock_contents(context, &keys[i]); + free(keys); + return 0; +} + +static int +set_random_password (krb5_principal principal) +{ + krb5_error_code ret; + char pw[128]; + + random_password (pw, sizeof(pw)); + ret = kadm5_chpass_principal(kadm_handle, principal, pw); + if (ret == 0) { + char *princ_name; + + krb5_unparse_name(context, principal, &princ_name); + + printf ("%s's password set to `%s'\n", princ_name, pw); + free (princ_name); + } + memset (pw, 0, sizeof(pw)); + return ret; +} + +static int +set_password (krb5_principal principal, char *password) +{ + krb5_error_code ret = 0; + char pwbuf[128]; + + if(password == NULL) { + char *princ_name; + char *prompt; + + krb5_unparse_name(context, principal, &princ_name); + asprintf(&prompt, "%s's Password: ", princ_name); + free (princ_name); + ret = des_read_pw_string(pwbuf, sizeof(pwbuf), prompt, 1); + free (prompt); + if(ret){ + return 0; /* XXX error code? */ + } + password = pwbuf; + } + if(ret == 0) + ret = kadm5_chpass_principal(kadm_handle, principal, password); + memset(pwbuf, 0, sizeof(pwbuf)); + return ret; +} + +static int +do_cpw_entry(krb5_principal principal, void *data) +{ + struct cpw_entry_data *e = data; + + if (e->random_key) + return set_random_key (principal); + else if (e->random_password) + return set_random_password (principal); + else + return set_password (principal, e->password); +} + +int +cpw_entry(int argc, char **argv) +{ + krb5_error_code ret; + int i; + int optind = 0; + struct cpw_entry_data data; + int num; + + data.random_key = 0; + data.random_password = 0; + data.password = NULL; + + args[0].value = &data.random_key; + args[1].value = &data.random_password; + args[2].value = &data.password; + if(getarg(args, num_args, argc, argv, &optind)){ + usage(); + return 0; + } + + num = 0; + if (data.random_key) + ++num; + if (data.random_password) + ++num; + if (data.password) + ++num; + + if (num > 1) { + printf ("give only one of " + "--random-key, --random-password, --password\n"); + return 0; + } + + argc -= optind; + argv += optind; + + for(i = 0; i < argc; i++) + ret = foreach_principal(argv[i], do_cpw_entry, &data); + + return 0; +} + diff --git a/crypto/heimdal/kadmin/del.c b/crypto/heimdal/kadmin/del.c new file mode 100644 index 0000000..39ee24e --- /dev/null +++ b/crypto/heimdal/kadmin/del.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 1997, 1998 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "kadmin_locl.h" + +RCSID("$Id: del.c,v 1.4 1999/12/02 17:04:58 joda Exp $"); + +static int +do_del_entry(krb5_principal principal, void *data) +{ + return kadm5_delete_principal(kadm_handle, principal); +} + +int +del_entry(int argc, char **argv) +{ + int i; + krb5_error_code ret; + + for(i = 1; i < argc; i++) + ret = foreach_principal(argv[i], do_del_entry, NULL); + return 0; +} diff --git a/crypto/heimdal/kadmin/del_enctype.c b/crypto/heimdal/kadmin/del_enctype.c new file mode 100644 index 0000000..d772b65 --- /dev/null +++ b/crypto/heimdal/kadmin/del_enctype.c @@ -0,0 +1,132 @@ +/* + * Copyright (c) 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "kadmin_locl.h" + +RCSID("$Id: del_enctype.c,v 1.4 1999/12/14 02:37:49 assar Exp $"); + +static void +usage(void) +{ + fprintf (stderr, "Usage: del_enctype principal enctypes...\n"); +} + +/* + * del_enctype principal enctypes... + */ + +int +del_enctype(int argc, char **argv) +{ + kadm5_principal_ent_rec princ; + krb5_principal princ_ent = NULL; + krb5_error_code ret; + const char *princ_name; + int i, j, k; + krb5_key_data *new_key_data; + int n_etypes; + krb5_enctype *etypes; + + if (argc < 3) { + usage (); + return 0; + } + + memset (&princ, 0, sizeof(princ)); + princ_name = argv[1]; + n_etypes = argc - 2; + etypes = malloc (n_etypes * sizeof(*etypes)); + if (etypes == NULL) { + krb5_warnx (context, "out of memory"); + return 0; + } + for (i = 0; i < n_etypes; ++i) { + ret = krb5_string_to_enctype (context, argv[i + 2], &etypes[i]); + if (ret) { + krb5_warnx (context, "bad enctype `%s'", argv[i + 2]); + goto out2; + } + } + + ret = krb5_parse_name(context, princ_name, &princ_ent); + if (ret) { + krb5_warn (context, ret, "krb5_parse_name %s", princ_name); + goto out2; + } + + ret = kadm5_get_principal(kadm_handle, princ_ent, &princ, + KADM5_PRINCIPAL | KADM5_KEY_DATA); + if (ret) { + krb5_free_principal (context, princ_ent); + krb5_warnx (context, "no such principal: %s", princ_name); + goto out2; + } + + new_key_data = malloc(princ.n_key_data * sizeof(*new_key_data)); + if (new_key_data == NULL) { + krb5_warnx (context, "out of memory"); + goto out; + } + + for (i = 0, j = 0; i < princ.n_key_data; ++i) { + krb5_key_data *key = &princ.key_data[i]; + int docopy = 1; + + for (k = 0; k < n_etypes; ++k) + if (etypes[k] == key->key_data_type[0]) { + docopy = 0; + break; + } + if (docopy) { + new_key_data[j++] = *key; + } else { + int16_t ignore; + + kadm5_free_key_data (kadm_handle, &ignore, key); + } + } + + free (princ.key_data); + princ.n_key_data = j; + princ.key_data = new_key_data; + + ret = kadm5_modify_principal (kadm_handle, &princ, KADM5_KEY_DATA); + if (ret) + krb5_warn(context, ret, "kadm5_modify_principal"); +out: + krb5_free_principal (context, princ_ent); + kadm5_free_principal_ent(kadm_handle, &princ); +out2: + free (etypes); + return 0; +} diff --git a/crypto/heimdal/kadmin/dump.c b/crypto/heimdal/kadmin/dump.c new file mode 100644 index 0000000..a57309c --- /dev/null +++ b/crypto/heimdal/kadmin/dump.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 1997, 1998, 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "kadmin_locl.h" +#include <kadm5/private.h> + +RCSID("$Id: dump.c,v 1.26 1999/12/02 17:04:58 joda Exp $"); + +int +dump(int argc, char **argv) +{ + krb5_error_code ret; + FILE *f; + HDB *db = _kadm5_s_get_db(kadm_handle); + int decrypt = 0; + int optind = 0; + + struct getargs args[] = { + { "decrypt", 'd', arg_flag, NULL, "decrypt keys" } + }; + args[0].value = &decrypt; + + if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optind)) { + arg_printusage(args, sizeof(args) / sizeof(args[0]), "kadmin dump", + "[dump-file]"); + return 0; + } + + argc -= optind; + argv += optind; + if(argc < 1) + f = stdout; + else + f = fopen(argv[0], "w"); + + ret = db->open(context, db, O_RDONLY, 0600); + if(ret){ + krb5_warn(context, ret, "hdb_open"); + if(f != stdout) + fclose(f); + return 0; + } + + hdb_foreach(context, db, decrypt ? HDB_F_DECRYPT : 0, hdb_print_entry, f); + + if(f != stdout) + fclose(f); + db->close(context, db); + return 0; +} diff --git a/crypto/heimdal/kadmin/ext.c b/crypto/heimdal/kadmin/ext.c new file mode 100644 index 0000000..9d2be17 --- /dev/null +++ b/crypto/heimdal/kadmin/ext.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 1997 - 2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "kadmin_locl.h" + +RCSID("$Id: ext.c,v 1.5 2000/01/02 03:58:02 assar Exp $"); + +struct ext_keytab_data { + krb5_keytab keytab; +}; + +static struct getargs args[] = { + { "keytab", 'k', arg_string, NULL, "keytab to use" }, +}; + +static int num_args = sizeof(args) / sizeof(args[0]); + +static void +usage(void) +{ + arg_printusage(args, num_args, "ext", "principal..."); +} + +static int +do_ext_keytab(krb5_principal principal, void *data) +{ + krb5_error_code ret; + int i; + kadm5_principal_ent_rec princ; + struct ext_keytab_data *e = data; + + ret = kadm5_get_principal(kadm_handle, principal, &princ, + KADM5_PRINCIPAL|KADM5_KVNO|KADM5_KEY_DATA); + if(ret) + return ret; + for(i = 0; i < princ.n_key_data; i++){ + krb5_keytab_entry key; + krb5_key_data *k = &princ.key_data[i]; + key.principal = princ.principal; + key.vno = k->key_data_kvno; + key.keyblock.keytype = k->key_data_type[0]; + key.keyblock.keyvalue.length = k->key_data_length[0]; + key.keyblock.keyvalue.data = k->key_data_contents[0]; + key.timestamp = time(NULL); + ret = krb5_kt_add_entry(context, e->keytab, &key); + if(ret) + krb5_warn(context, ret, "krb5_kt_add_entry"); + } + kadm5_free_principal_ent(kadm_handle, &princ); + return 0; +} + +int +ext_keytab(int argc, char **argv) +{ + krb5_error_code ret; + int i; + int optind = 0; + char *keytab = NULL; + struct ext_keytab_data data; + + args[0].value = &keytab; + if(getarg(args, num_args, argc, argv, &optind)){ + usage(); + return 0; + } + if(keytab) + ret = krb5_kt_resolve(context, keytab, &data.keytab); + else + ret = krb5_kt_default(context, &data.keytab); + if(ret){ + krb5_warn(context, ret, "krb5_kt_resolve"); + return 0; + } + + argc -= optind; + argv += optind; + + for(i = 0; i < argc; i++) + foreach_principal(argv[i], do_ext_keytab, &data); + + krb5_kt_close(context, data.keytab); + + return 0; +} + diff --git a/crypto/heimdal/kadmin/get.c b/crypto/heimdal/kadmin/get.c new file mode 100644 index 0000000..1492ca9 --- /dev/null +++ b/crypto/heimdal/kadmin/get.c @@ -0,0 +1,250 @@ +/* + * Copyright (c) 1997, 1998, 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "kadmin_locl.h" +#include <parse_units.h> + +RCSID("$Id: get.c,v 1.8 1999/12/02 17:04:58 joda Exp $"); + +struct get_entry_data { + void (*header)(void); + void (*format)(kadm5_principal_ent_t); +}; + +static void +print_entry_terse(kadm5_principal_ent_t princ) +{ + char *p; + krb5_unparse_name(context, princ->principal, &p); + printf(" %s\n", p); + free(p); +} + +static void +print_header_short(void) +{ + printf("%-20s ", "Principal"); + + printf("%-10s ", "Expires"); + + printf("%-10s ", "PW-exp"); + + printf("%-10s ", "PW-change"); + + printf("%-9s ", "Max life"); + + printf("%-9s ", "Max renew"); + + printf("\n"); +} + +static void +print_entry_short(kadm5_principal_ent_t princ) +{ + char buf[1024]; + + krb5_unparse_name_fixed_short(context, princ->principal, buf, sizeof(buf)); + printf("%-20s ", buf); + + time_t2str(princ->princ_expire_time, buf, sizeof(buf), 0); + printf("%-10s ", buf); + + time_t2str(princ->pw_expiration, buf, sizeof(buf), 0); + printf("%-10s ", buf); + + time_t2str(princ->last_pwd_change, buf, sizeof(buf), 0); + printf("%-10s ", buf); + + deltat2str(princ->max_life, buf, sizeof(buf)); + printf("%-9s ", buf); + + deltat2str(princ->max_renewable_life, buf, sizeof(buf)); + printf("%-9s ", buf); + +#if 0 + time_t2str(princ->mod_date, buf, sizeof(buf), 0); + printf("%-10s ", buf); + + krb5_unparse_name_fixed(context, princ->mod_name, buf, sizeof(buf)); + printf("%-24s", buf); +#endif + + printf("\n"); +} + +static void +print_entry_long(kadm5_principal_ent_t princ) +{ + char buf[1024]; + int i; + + krb5_unparse_name_fixed(context, princ->principal, buf, sizeof(buf)); + printf("%24s: %s\n", "Principal", buf); + time_t2str(princ->princ_expire_time, buf, sizeof(buf), 1); + printf("%24s: %s\n", "Principal expires", buf); + + time_t2str(princ->pw_expiration, buf, sizeof(buf), 1); + printf("%24s: %s\n", "Password expires", buf); + + time_t2str(princ->last_pwd_change, buf, sizeof(buf), 1); + printf("%24s: %s\n", "Last password change", buf); + + deltat2str(princ->max_life, buf, sizeof(buf)); + printf("%24s: %s\n", "Max ticket life", buf); + + deltat2str(princ->max_renewable_life, buf, sizeof(buf)); + printf("%24s: %s\n", "Max renewable life", buf); + printf("%24s: %d\n", "Kvno", princ->kvno); + printf("%24s: %d\n", "Mkvno", princ->mkvno); + printf("%24s: %s\n", "Policy", princ->policy ? princ->policy : "none"); + time_t2str(princ->last_success, buf, sizeof(buf), 1); + printf("%24s: %s\n", "Last successful login", buf); + time_t2str(princ->last_failed, buf, sizeof(buf), 1); + printf("%24s: %s\n", "Last failed login", buf); + printf("%24s: %d\n", "Failed login count", princ->fail_auth_count); + time_t2str(princ->mod_date, buf, sizeof(buf), 1); + printf("%24s: %s\n", "Last modified", buf); + krb5_unparse_name_fixed(context, princ->mod_name, buf, sizeof(buf)); + printf("%24s: %s\n", "Modifier", buf); + attributes2str (princ->attributes, buf, sizeof(buf)); + printf("%24s: %s\n", "Attributes", buf); + + printf("%24s: ", "Keytypes(salts)"); + + for (i = 0; i < princ->n_key_data; ++i) { + krb5_key_data *k = &princ->key_data[i]; + krb5_error_code ret; + char *e_string, *s_string; + + ret = krb5_enctype_to_string (context, + k->key_data_type[0], + &e_string); + if (ret) + asprintf (&e_string, "unknown(%d)", k->key_data_type[0]); + + ret = krb5_salttype_to_string (context, + k->key_data_type[0], + k->key_data_type[1], + &s_string); + if (ret) + asprintf (&s_string, "unknown(%d)", k->key_data_type[1]); + + printf ("%s%s(%s)", (i != 0) ? ", " : "", e_string, s_string); + free (e_string); + free (s_string); + } + printf("\n\n"); +} + +static int +do_get_entry(krb5_principal principal, void *data) +{ + kadm5_principal_ent_rec princ; + krb5_error_code ret; + struct get_entry_data *e = data; + + memset(&princ, 0, sizeof(princ)); + ret = kadm5_get_principal(kadm_handle, principal, + &princ, + KADM5_PRINCIPAL_NORMAL_MASK|KADM5_KEY_DATA); + if(ret) + return ret; + else { + if(e->header) { + (*e->header)(); + e->header = NULL; /* XXX only once */ + } + (e->format)(&princ); + kadm5_free_principal_ent(kadm_handle, &princ); + } + return 0; +} + +int +get_entry(int argc, char **argv) +{ + int i; + krb5_error_code ret; + struct get_entry_data data; + struct getargs args[] = { + { "long", 'l', arg_flag, NULL, "long format" }, + { "terse", 't', arg_flag, NULL, "terse format" }, + }; + int num_args = sizeof(args) / sizeof(args[0]); + int optind = 0; + int long_flag = 0; + int terse_flag = 0; + + args[0].value = &long_flag; + args[1].value = &terse_flag; + if(getarg(args, num_args, argc, argv, &optind)) + goto usage; + if(optind == argc) + goto usage; + + if(long_flag) { + data.format = print_entry_long; + data.header = NULL; + } else if(terse_flag) { + data.format = print_entry_terse; + data.header = NULL; + } else { + data.format = print_entry_short; + data.header = print_header_short; + } + + argc -= optind; + argv += optind; + + for(i = 0; i < argc; i++) + ret = foreach_principal(argv[i], do_get_entry, &data); + return 0; +usage: + arg_printusage (args, num_args, "get", "principal..."); + return 0; +} + +int +list_princs(int argc, char **argv) +{ + int i; + krb5_error_code ret; + struct get_entry_data data; + + data.format = print_entry_terse; + data.header = NULL; + + for(i = 1; i < argc; i++) + ret = foreach_principal(argv[i], do_get_entry, &data); + return 0; +} diff --git a/crypto/heimdal/kadmin/init.c b/crypto/heimdal/kadmin/init.c new file mode 100644 index 0000000..b889131 --- /dev/null +++ b/crypto/heimdal/kadmin/init.c @@ -0,0 +1,210 @@ +/* + * Copyright (c) 1997, 1998, 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "kadmin_locl.h" +#include <kadm5/private.h> + +RCSID("$Id: init.c,v 1.23 1999/12/02 17:04:58 joda Exp $"); + +static kadm5_ret_t +create_random_entry(krb5_principal princ, + unsigned max_life, + unsigned max_rlife, + u_int32_t attributes) +{ + kadm5_principal_ent_rec ent; + kadm5_ret_t ret; + int mask = 0; + krb5_keyblock *keys; + int n_keys, i; + + memset(&ent, 0, sizeof(ent)); + ent.principal = princ; + mask |= KADM5_PRINCIPAL; + if (max_life) { + ent.max_life = max_life; + mask |= KADM5_MAX_LIFE; + } + if (max_rlife) { + ent.max_renewable_life = max_rlife; + mask |= KADM5_MAX_RLIFE; + } + ent.attributes |= attributes | KRB5_KDB_DISALLOW_ALL_TIX; + mask |= KADM5_ATTRIBUTES; + + ret = kadm5_create_principal(kadm_handle, &ent, mask, "hemlig"); + if(ret) + return ret; + ret = kadm5_randkey_principal(kadm_handle, princ, &keys, &n_keys); + if(ret) + return ret; + for(i = 0; i < n_keys; i++) + krb5_free_keyblock_contents(context, &keys[i]); + free(keys); + ret = kadm5_get_principal(kadm_handle, princ, &ent, + KADM5_PRINCIPAL | KADM5_ATTRIBUTES); + if(ret) + return ret; + ent.attributes &= (~KRB5_KDB_DISALLOW_ALL_TIX); + ent.kvno = 1; + ret = kadm5_modify_principal(kadm_handle, &ent, + KADM5_ATTRIBUTES|KADM5_KVNO); + kadm5_free_principal_ent (kadm_handle, &ent); + if(ret) + return ret; + return 0; +} + +static struct getargs args[] = { + { "realm-max-ticket-life", 0, arg_string, NULL, + "realm max ticket lifetime" }, + { "realm-max-renewable-life", 0, arg_string, NULL, + "realm max renewable lifetime" }, +}; + +static int num_args = sizeof(args) / sizeof(args[0]); + +static void +usage(void) +{ + arg_printusage (args, num_args, "ank", "principal"); +} + +int +init(int argc, char **argv) +{ + kadm5_ret_t ret; + int i; + char *realm_max_life = NULL; + char *realm_max_rlife = NULL; + HDB *db; + int optind = 0; + krb5_deltat max_life, max_rlife; + + args[0].value = &realm_max_life; + args[1].value = &realm_max_rlife; + + if(getarg(args, num_args, argc, argv, &optind)) { + usage(); + return 0; + } + + if (realm_max_life) { + if (str2deltat (realm_max_life, &max_life) != 0) { + krb5_warnx (context, "unable to parse `%s'", realm_max_life); + return 0; + } + } + if (realm_max_rlife) { + if (str2deltat (realm_max_rlife, &max_rlife) != 0) { + krb5_warnx (context, "unable to parse `%s'", realm_max_rlife); + return 0; + } + } + + db = _kadm5_s_get_db(kadm_handle); + + ret = db->open(context, db, O_RDWR | O_CREAT, 0600); + if(ret){ + krb5_warn(context, ret, "hdb_open"); + return 0; + } + db->close(context, db); + for(i = optind; i < argc; i++){ + krb5_principal princ; + const char *realm = argv[i]; + + /* Create `krbtgt/REALM' */ + krb5_make_principal(context, &princ, realm, "krbtgt", realm, NULL); + if (realm_max_life == NULL) { + max_life = 0; + edit_deltat ("Realm max ticket life", &max_life, NULL, 0); + } + if (realm_max_rlife == NULL) { + max_rlife = 0; + edit_deltat("Realm max renewable ticket life", &max_rlife, + NULL, 0); + } + create_random_entry(princ, max_life, max_rlife, 0); + krb5_free_principal(context, princ); + + /* Create `kadmin/changepw' */ + krb5_make_principal(context, &princ, realm, + "kadmin", "changepw", NULL); + create_random_entry(princ, 5*60, 5*60, + KRB5_KDB_DISALLOW_TGT_BASED| + KRB5_KDB_PWCHANGE_SERVICE| + KRB5_KDB_DISALLOW_POSTDATED| + KRB5_KDB_DISALLOW_FORWARDABLE| + KRB5_KDB_DISALLOW_RENEWABLE| + KRB5_KDB_DISALLOW_PROXIABLE| + KRB5_KDB_REQUIRES_PRE_AUTH); + krb5_free_principal(context, princ); + + /* Create `kadmin/admin' */ + krb5_make_principal(context, &princ, realm, + "kadmin", "admin", NULL); + create_random_entry(princ, 60*60, 60*60, KRB5_KDB_REQUIRES_PRE_AUTH); + krb5_free_principal(context, princ); + + /* Create `changepw/kerberos' (for v4 compat) */ + krb5_make_principal(context, &princ, realm, + "changepw", "kerberos", NULL); + create_random_entry(princ, 60*60, 60*60, 0); + krb5_free_principal(context, princ); + + /* Create `default' */ + { + kadm5_principal_ent_rec ent; + int mask = 0; + + memset (&ent, 0, sizeof(ent)); + mask |= KADM5_PRINCIPAL; + krb5_make_principal(context, &ent.principal, realm, + "default", NULL); + mask |= KADM5_MAX_LIFE; + ent.max_life = 24 * 60 * 60; + mask |= KADM5_MAX_RLIFE; + ent.max_renewable_life = 7 * ent.max_life; + ent.attributes = KRB5_KDB_DISALLOW_ALL_TIX; + mask |= KADM5_ATTRIBUTES; + + ret = kadm5_create_principal(kadm_handle, &ent, mask, ""); + if (ret) + krb5_err (context, 1, ret, "kadm5_create_principal"); + + krb5_free_principal(context, ent.principal); + } + } + return 0; +} diff --git a/crypto/heimdal/kadmin/kadmin.c b/crypto/heimdal/kadmin/kadmin.c new file mode 100644 index 0000000..9172d6e --- /dev/null +++ b/crypto/heimdal/kadmin/kadmin.c @@ -0,0 +1,281 @@ +/* + * Copyright (c) 1997, 1998, 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "kadmin_locl.h" +#include <sl.h> + +RCSID("$Id: kadmin.c,v 1.26 1999/12/02 17:04:58 joda Exp $"); + +static char *config_file; +static char *keyfile; +static int local_flag; +static int help_flag; +static int version_flag; +static char *realm; +static char *admin_server; +static int server_port = 0; +static char *client_name; + +static struct getargs args[] = { + { "principal", 'p', arg_string, &client_name, + "principal to authenticate as" }, + { + "config-file", 'c', arg_string, &config_file, + "location of config file", "file" + }, + { + "key-file", 'k', arg_string, &keyfile, + "location of master key file", "file" + }, + { + "realm", 'r', arg_string, &realm, + "realm to use", "realm" + }, + { + "admin-server", 'a', arg_string, &admin_server, + "server to contact", "host" + }, + { + "server-port", 's', arg_integer, &server_port, + "server to contact", "port number" + }, + { "local", 'l', arg_flag, &local_flag, "local admin mode" }, + { "help", 'h', arg_flag, &help_flag }, + { "version", 'v', arg_flag, &version_flag } +}; + +static int num_args = sizeof(args) / sizeof(args[0]); + +static SL_cmd commands[] = { + /* commands that are only available with `-l' */ + { + "dump", dump, "dump [file]", + "Dumps the database in a human readable format to the\n" + "specified file, or the standard out." + }, + { + "load", load, "load file", + "Loads a previously dumped file." + }, + { + "merge", merge, "merge file" , + "Merges the contents of a dump file into the database." + }, + { + "init", init, "init realm...", + "Initializes the default principals for a realm.\n" + "Creates the database if necessary." + }, + /* common commands */ + { + "add", add_new_key, "add principal" , + "Adds a principal to the database." + }, + { "add_new_key"}, + { "ank"}, + { + "passwd", cpw_entry, "passwd expression..." , + "Changes the password of one or more principals\n" + "matching the expressions." + }, + { "change_password"}, + { "cpw"}, + { + "delete", del_entry, "delete expression...", + "Deletes all principals matching the expressions." + }, + { "del_entry" }, + { + "del_enctype", del_enctype, "del_enctype principal enctype...", + "Delete all the mentioned enctypes for principal." + }, + { + "ext_keytab", ext_keytab, "ext_keytab expression...", + "Extracts the keys of all principals matching the expressions,\n" + "and stores them in a keytab." + }, + { + "get", get_entry, "get expression...", + "Shows information about principals matching the expressions." + }, + { "get_entry" }, + { + "rename", rename_entry, "rename source target", + "Renames `source' to `target'." + }, + { + "modify", mod_entry, "modify principal", + "Modifies some attributes of the specified principal." + }, + { + "privileges", get_privs, "privileges", + "Shows which kinds of operations you are allowed to perform." + }, + { + "list", list_princs, "list expression...", + "Lists principals in a terse format. The same as `get -t'." + }, + { "help", help, "help"}, + { "?"}, + { "exit", exit_kadmin, "exit"}, + { NULL} +}; + +krb5_context context; +void *kadm_handle; + +int +help(int argc, char **argv) +{ + sl_help(commands, argc, argv); + return 0; +} + +int +exit_kadmin (int argc, char **argv) +{ + return 1; +} + +static void +usage(int ret) +{ + arg_printusage (args, num_args, NULL, "[command]"); + exit (ret); +} + +int +get_privs(int argc, char **argv) +{ + u_int32_t privs; + char str[128]; + kadm5_ret_t ret; + + ret = kadm5_get_privs(kadm_handle, &privs); + if(ret) + krb5_warn(context, ret, "kadm5_get_privs"); + else{ + ret =_kadm5_privs_to_string(privs, str, sizeof(str)); + printf("%s\n", str); + } + return 0; +} + +int +main(int argc, char **argv) +{ + krb5_error_code ret; + krb5_config_section *cf = NULL; + kadm5_config_params conf; + int optind = 0; + int e; + SL_cmd *cmd; + + set_progname(argv[0]); + + krb5_init_context(&context); + + while((e = getarg(args, num_args, argc, argv, &optind))) + warnx("error at argument `%s'", argv[optind]); + + if (help_flag) + usage (0); + + if (version_flag) { + print_version(NULL); + exit(0); + } + + argc -= optind; + argv += optind; + + if (config_file == NULL) + config_file = HDB_DB_DIR "/kdc.conf"; + + if(krb5_config_parse_file(config_file, &cf) == 0) { + const char *p = krb5_config_get_string (context, cf, + "kdc", "key-file", NULL); + if (p) + keyfile = strdup(p); + } + + memset(&conf, 0, sizeof(conf)); + if(realm) { + krb5_set_default_realm(context, realm); /* XXX should be fixed + some other way */ + conf.realm = realm; + conf.mask |= KADM5_CONFIG_REALM; + } + + if (admin_server) { + conf.admin_server = admin_server; + conf.mask |= KADM5_CONFIG_ADMIN_SERVER; + } + + if (server_port) { + conf.kadmind_port = htons(server_port); + conf.mask |= KADM5_CONFIG_KADMIND_PORT; + } + + if(local_flag){ + ret = kadm5_s_init_with_password_ctx(context, + KADM5_ADMIN_SERVICE, + NULL, + KADM5_ADMIN_SERVICE, + &conf, 0, 0, + &kadm_handle); + cmd = commands; + } else { + ret = kadm5_c_init_with_password_ctx(context, + client_name, + NULL, + KADM5_ADMIN_SERVICE, + &conf, 0, 0, + &kadm_handle); + cmd = commands + 4; /* XXX */ + } + + if(ret) + krb5_err(context, 1, ret, "kadm5_init_with_password"); + if (argc != 0) { + ret = sl_command (cmd, argc, argv); + if(ret == -1) + krb5_warnx (context, "unrecognized command: %s", argv[0]); + } else + ret = sl_loop (cmd, "kadmin> ") != 0; + + kadm5_destroy(kadm_handle); + krb5_config_file_free (context, cf); + krb5_free_context(context); + return ret; +} diff --git a/crypto/heimdal/kadmin/kadmin_locl.h b/crypto/heimdal/kadmin/kadmin_locl.h new file mode 100644 index 0000000..240ca2c --- /dev/null +++ b/crypto/heimdal/kadmin/kadmin_locl.h @@ -0,0 +1,161 @@ +/* + * Copyright (c) 1997-1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: kadmin_locl.h,v 1.24 1999/12/02 17:04:58 joda Exp $ + */ + +#ifndef __ADMIN_LOCL_H__ +#define __ADMIN_LOCL_H__ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <errno.h> +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif +#ifdef HAVE_NETINET_IN6_H +#include <netinet/in6.h> +#endif +#ifdef HAVE_NETINET6_IN6_H +#include <netinet6/in6.h> +#endif + +#ifdef HAVE_NETDB_H +#include <netdb.h> +#endif +#ifdef HAVE_SYS_UN_H +#include <sys/un.h> +#endif +#include <err.h> +#include <roken.h> +#include <krb5.h> +#include <hdb.h> +#include <hdb_err.h> +#include <kadm5/admin.h> +#include <kadm5/private.h> +#include <kadm5/kadm5_err.h> +#include <parse_time.h> +#include <getarg.h> + + +extern krb5_context context; +extern void * kadm_handle; + +#define DECL(X) int X(int, char **) + +DECL(add_new_key); +DECL(cpw_entry); +DECL(del_entry); +DECL(del_enctype); +DECL(exit_kadmin); +DECL(ext_keytab); +DECL(get_entry); +DECL(get_privs); +DECL(help); +DECL(list_princs); +DECL(mod_entry); +DECL(rename_entry); +DECL(init); +DECL(dump); +DECL(load); +DECL(merge); + +#define ALLOC(X) ((X) = malloc(sizeof(*(X)))) + +/* util.c */ + +void attributes2str(krb5_flags attributes, char *str, size_t len); +int str2attributes(const char *str, krb5_flags *flags); +int parse_attributes (const char *resp, krb5_flags *attr, int *mask, int bit); +int edit_attributes (const char *prompt, krb5_flags *attr, int *mask, + int bit); + +void time_t2str(time_t t, char *str, size_t len, int include_time); +int str2time_t (const char *str, time_t *time); +int parse_timet (const char *resp, krb5_timestamp *value, int *mask, int bit); +int edit_timet (const char *prompt, krb5_timestamp *value, int *mask, + int bit); + +void deltat2str(unsigned t, char *str, size_t len); +int str2deltat(const char *str, krb5_deltat *delta); +int parse_deltat (const char *resp, krb5_deltat *value, int *mask, int bit); +int edit_deltat (const char *prompt, krb5_deltat *value, int *mask, int bit); + +int edit_entry(kadm5_principal_ent_t ent, int *mask, + kadm5_principal_ent_t default_ent, int default_mask); +int set_entry(krb5_context context, + kadm5_principal_ent_t ent, + int *mask, + const char *max_ticket_life, + const char *max_renewable_life, + const char *expiration, + const char *pw_expiration, + const char *attributes); +int +foreach_principal(const char *exp, + int (*func)(krb5_principal, void*), + void *data); + +void get_response(const char *prompt, const char *def, char *buf, size_t len); + +/* server.c */ + +krb5_error_code +kadmind_loop (krb5_context, krb5_auth_context, krb5_keytab, int); + +/* version4.c */ + +void +handle_v4(krb5_context context, int len, int fd); + +/* random_password.c */ + +void +random_password(char *pw, size_t len); + +#endif /* __ADMIN_LOCL_H__ */ diff --git a/crypto/heimdal/kadmin/kadmind.c b/crypto/heimdal/kadmin/kadmind.c new file mode 100644 index 0000000..4b4fb0d --- /dev/null +++ b/crypto/heimdal/kadmin/kadmind.c @@ -0,0 +1,151 @@ +/* + * Copyright (c) 1997, 1998, 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "kadmin_locl.h" + +RCSID("$Id: kadmind.c,v 1.16 1999/12/02 17:04:58 joda Exp $"); + +static char *config_file; +static char *keyfile; +static char *keytab_str = "HDB:"; +static int help_flag; +static int version_flag; +static int debug_flag; +static int debug_port; +char *realm; + +static struct getargs args[] = { + { + "config-file", 'c', arg_string, &config_file, + "location of config file", "file" + }, + { + "key-file", 'k', arg_string, &keyfile, + "location of master key file", "file" + }, + { + "keytab", 0, arg_string, &keytab_str, + "what keytab to use", "keytab" + }, + { "realm", 'r', arg_string, &realm, + "realm to use", "realm" + }, + { "debug", 'd', arg_flag, &debug_flag, + "enable debugging" + }, + { "debug-port", 'p', arg_integer,&debug_port, + "port to use with debug", "port" }, + { "help", 'h', arg_flag, &help_flag }, + { "version", 'v', arg_flag, &version_flag } +}; + +static int num_args = sizeof(args) / sizeof(args[0]); + +krb5_context context; + +static void +usage(int ret) +{ + arg_printusage (args, num_args, NULL, ""); + exit (ret); +} + +krb5_error_code +kadmind_loop (krb5_context, krb5_auth_context, krb5_keytab, int); + +int +main(int argc, char **argv) +{ + krb5_error_code ret; + krb5_config_section *cf; + int optind = 0; + int e; + krb5_log_facility *logf; + krb5_keytab keytab; + + set_progname(argv[0]); + + krb5_init_context(&context); + + ret = krb5_openlog(context, "kadmind", &logf); + ret = krb5_set_warn_dest(context, logf); + + while((e = getarg(args, num_args, argc, argv, &optind))) + warnx("error at argument `%s'", argv[optind]); + + if (help_flag) + usage (0); + + if (version_flag) { + print_version(NULL); + exit(0); + } + + argc -= optind; + argv += optind; + + ret = krb5_kt_register(context, &hdb_kt_ops); + if(ret) + krb5_err(context, 1, ret, "krb5_kt_register"); + + if (config_file == NULL) + config_file = HDB_DB_DIR "/kdc.conf"; + + if(krb5_config_parse_file(config_file, &cf) == 0) { + const char *p = krb5_config_get_string (context, cf, + "kdc", "key-file", NULL); + if (p) + keyfile = strdup(p); + } + + ret = krb5_kt_resolve(context, keytab_str, &keytab); + if(ret) + krb5_err(context, 1, ret, "krb5_kt_resolve"); + + { + int fd = 0; + krb5_auth_context ac = NULL; + if(debug_flag){ + if(debug_port == 0) + debug_port = krb5_getportbyname (context, "kerberos-adm", + "tcp", 749); + else + debug_port = htons(debug_port); + mini_inetd(debug_port); + } + if(realm) + krb5_set_default_realm(context, realm); /* XXX */ + kadmind_loop(context, ac, keytab, fd); + } + return 0; +} diff --git a/crypto/heimdal/kadmin/load.c b/crypto/heimdal/kadmin/load.c new file mode 100644 index 0000000..5f9f2b7 --- /dev/null +++ b/crypto/heimdal/kadmin/load.c @@ -0,0 +1,335 @@ +/* + * Copyright (c) 1997, 1998, 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "kadmin_locl.h" +#include <kadm5/private.h> + +RCSID("$Id: load.c,v 1.34 1999/12/02 17:04:58 joda Exp $"); + +struct entry{ + char *principal; + char *key; + char *max_life; + char *max_renew; + char *created; + char *modified; + char *valid_start; + char *valid_end; + char *pw_end; + char *flags; + char *etypes; +}; + +static char * +skip_next(char *p) +{ + while(*p && !isspace((unsigned char)*p)) + p++; + *p++ = 0; + while(*p && isspace((unsigned char)*p)) p++; + return p; +} + +static time_t* +parse_time_string(time_t *t, char *s) +{ + int year, month, date, hour, minute, second; + struct tm tm; + if(strcmp(s, "-") == 0) + return NULL; + if(t == NULL) + t = malloc(sizeof(*t)); + sscanf(s, "%04d%02d%02d%02d%02d%02d", + &year, &month, &date, &hour, &minute, &second); + tm.tm_year = year - 1900; + tm.tm_mon = month - 1; + tm.tm_mday = date; + tm.tm_hour = hour; + tm.tm_min = minute; + tm.tm_sec = second; + tm.tm_isdst = 0; + *t = timegm(&tm); + return t; +} + +static unsigned* +parse_integer(unsigned *u, char *s) +{ + if(strcmp(s, "-") == 0) + return NULL; + if(u == NULL) + u = malloc(sizeof(*u)); + sscanf(s, "%u", u); + return u; +} + +static void +parse_keys(hdb_entry *ent, char *str) +{ + int tmp; + char *p; + int i; + + p = strsep(&str, ":"); + sscanf(p, "%d", &tmp); + ent->kvno = tmp; + p = strsep(&str, ":"); + while(p){ + Key *key; + key = realloc(ent->keys.val, + (ent->keys.len + 1) * sizeof(*ent->keys.val)); + if(key == NULL) + abort(); + ent->keys.val = key; + key = ent->keys.val + ent->keys.len; + ent->keys.len++; + memset(key, 0, sizeof(*key)); + if(sscanf(p, "%d", &tmp) == 1) { + key->mkvno = malloc(sizeof(*key->mkvno)); + *key->mkvno = tmp; + } else + key->mkvno = NULL; + p = strsep(&str, ":"); + sscanf(p, "%d", &tmp); + key->key.keytype = tmp; + p = strsep(&str, ":"); + krb5_data_alloc(&key->key.keyvalue, (strlen(p) - 1) / 2 + 1); + for(i = 0; i < strlen(p); i += 2){ + sscanf(p + i, "%02x", &tmp); + ((u_char*)key->key.keyvalue.data)[i / 2] = tmp; + } + p = strsep(&str, ":"); + if(strcmp(p, "-") != 0){ + unsigned type; + size_t p_len; + if(sscanf(p, "%u/", &type) != 1){ + abort (); + } + p = strchr(p, '/'); + if(p == NULL) + abort (); + p++; + p_len = strlen(p); + + key->salt = malloc(sizeof(*key->salt)); + key->salt->type = type; + + if (p_len) { + if(*p == '\"'){ + krb5_data_copy(&key->salt->salt, p + 1, p_len - 2); + }else{ + krb5_data_alloc(&key->salt->salt, (p_len - 1) / 2 + 1); + for(i = 0; i < p_len; i += 2){ + sscanf(p + i, "%02x", &tmp); + ((u_char*)key->salt->salt.data)[i / 2] = tmp; + } + } + } else + krb5_data_zero (&key->salt->salt); + } + p = strsep(&str, ":"); + } +} + +static Event* +parse_event(Event *ev, char *str) +{ + char *p; + if(strcmp(str, "-") == 0) + return NULL; + if(ev == NULL) + ev = malloc(sizeof(*ev)); + memset(ev, 0, sizeof(*ev)); + p = strsep(&str, ":"); + parse_time_string(&ev->time, p); + p = strsep(&str, ":"); + krb5_parse_name(context, p, &ev->principal); + return ev; +} + +static HDBFlags +parse_hdbflags2int(char *str) +{ + unsigned i; + parse_integer(&i, str); + + return int2HDBFlags(i); +} + +#if 0 +static void +parse_etypes(char *str, unsigned **val, unsigned *len) +{ + unsigned v; + + *val = NULL; + *len = 0; + while(sscanf(str, "%u", &v) == 1) { + *val = realloc(*val, (*len+1) * sizeof(**val)); + (*val)[(*len)++] = v; + str = strchr(str, ':'); + if(str == NULL) + break; + str++; + } +} +#endif + +static void +doit(char *filename, int merge) +{ + krb5_error_code ret; + FILE *f; + char s[1024]; + char *p; + int line; + int flags = O_RDWR; + struct entry e; + hdb_entry ent; + HDB *db = _kadm5_s_get_db(kadm_handle); + + f = fopen(filename, "r"); + if(f == NULL){ + krb5_warn(context, errno, "fopen(%s)", filename); + return; + } + if(!merge) + flags |= O_CREAT | O_TRUNC; + ret = db->open(context, db, flags, 0600); + if(ret){ + krb5_warn(context, ret, "hdb_open"); + fclose(f); + return; + } + line = 0; + while(fgets(s, sizeof(s), f)){ + line++; + e.principal = s; + for(p = s; *p; p++){ + if(*p == '\\') + p++; + else if(isspace((unsigned char)*p)) { + *p = 0; + break; + } + } + p = skip_next(p); + + e.key = p; + p = skip_next(p); + + e.created = p; + p = skip_next(p); + + e.modified = p; + p = skip_next(p); + + e.valid_start = p; + p = skip_next(p); + + e.valid_end = p; + p = skip_next(p); + + e.pw_end = p; + p = skip_next(p); + + e.max_life = p; + p = skip_next(p); + + e.max_renew = p; + p = skip_next(p); + + e.flags = p; + p = skip_next(p); + + e.etypes = p; + p = skip_next(p); + + memset(&ent, 0, sizeof(ent)); + ret = krb5_parse_name(context, e.principal, &ent.principal); + if(ret){ + fprintf(stderr, "%s:%d:%s (%s)\n", + filename, + line, + krb5_get_err_text(context, ret), + e.principal); + continue; + } + + parse_keys(&ent, e.key); + + parse_event(&ent.created_by, e.created); + ent.modified_by = parse_event(NULL, e.modified); + ent.valid_start = parse_time_string(NULL, e.valid_start); + ent.valid_end = parse_time_string(NULL, e.valid_end); + ent.pw_end = parse_time_string(NULL, e.pw_end); + ent.max_life = parse_integer(NULL, e.max_life); + ent.max_renew = parse_integer(NULL, e.max_renew); + ent.flags = parse_hdbflags2int(e.flags); +#if 0 + ALLOC(ent.etypes); + parse_etypes(e.etypes, &ent.etypes->val, &ent.etypes->len); + if(ent.etypes->len == 0) { + free(ent.etypes); + ent.etypes = NULL; + } +#endif + + db->store(context, db, HDB_F_REPLACE, &ent); + hdb_free_entry (context, &ent); + } + db->close(context, db); + fclose(f); +} + +int +load(int argc, char **argv) +{ + if(argc < 2){ + krb5_warnx(context, "Usage: load filename"); + return 0; + } + doit(argv[1], 0); + return 0; +} + +int +merge(int argc, char **argv) +{ + if(argc < 2){ + krb5_warnx(context, "Usage: merge filename"); + return 0; + } + doit(argv[1], 1); + return 0; +} diff --git a/crypto/heimdal/kadmin/mod.c b/crypto/heimdal/kadmin/mod.c new file mode 100644 index 0000000..48d00a6 --- /dev/null +++ b/crypto/heimdal/kadmin/mod.c @@ -0,0 +1,143 @@ +/* + * Copyright (c) 1997, 1998, 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "kadmin_locl.h" + +RCSID("$Id: mod.c,v 1.7 1999/12/02 17:04:58 joda Exp $"); + +static int parse_args (krb5_context context, kadm5_principal_ent_t ent, + int argc, char **argv, int *optind, char *name, + int *mask); + +static int +parse_args(krb5_context context, kadm5_principal_ent_t ent, + int argc, char **argv, int *optind, char *name, + int *mask) +{ + char *attr_str = NULL; + char *max_life_str = NULL; + char *max_rlife_str = NULL; + char *expiration_str = NULL; + char *pw_expiration_str = NULL; + int ret, i; + + struct getargs args[] = { + {"attributes", 'a', arg_string, NULL, "Attributies", + "attributes"}, + {"max-ticket-life", 0, arg_string, NULL, "max ticket lifetime", + "lifetime"}, + {"max-renewable-life", 0, arg_string, NULL, + "max renewable lifetime", "lifetime" }, + {"expiration-time", 0, arg_string, + NULL, "Expiration time", "time"}, + {"pw-expiration-time", 0, arg_string, + NULL, "Password expiration time", "time"}, + }; + + i = 0; + args[i++].value = &attr_str; + args[i++].value = &max_life_str; + args[i++].value = &max_rlife_str; + args[i++].value = &expiration_str; + args[i++].value = &pw_expiration_str; + + *optind = 0; /* XXX */ + + if(getarg(args, sizeof(args) / sizeof(args[0]), + argc, argv, optind)){ + arg_printusage(args, + sizeof(args) / sizeof(args[0]), + name ? name : "", + "principal"); + return -1; + } + + ret = set_entry(context, ent, mask, max_life_str, max_rlife_str, + expiration_str, pw_expiration_str, attr_str); + if (ret) + return ret; + return 0; +} + +int +mod_entry(int argc, char **argv) +{ + kadm5_principal_ent_rec princ; + int mask = 0; + krb5_error_code ret; + krb5_principal princ_ent = NULL; + int optind; + + memset (&princ, 0, sizeof(princ)); + + ret = parse_args (context, &princ, argc, argv, + &optind, "mod", &mask); + if (ret) + return 0; + + argc -= optind; + argv += optind; + + if (argc != 1) { + printf ("Usage: mod [options] principal\n"); + return 0; + } + + krb5_parse_name(context, argv[0], &princ_ent); + + if (mask == 0) { + memset(&princ, 0, sizeof(princ)); + ret = kadm5_get_principal(kadm_handle, princ_ent, &princ, + KADM5_PRINCIPAL | KADM5_ATTRIBUTES | + KADM5_MAX_LIFE | KADM5_MAX_RLIFE | + KADM5_PRINC_EXPIRE_TIME | + KADM5_PW_EXPIRATION); + if (ret) { + printf ("no such principal: %s\n", argv[0]); + krb5_free_principal (context, princ_ent); + return 0; + } + edit_entry(&princ, &mask, NULL, 0); + + } else { + princ.principal = princ_ent; + } + + ret = kadm5_modify_principal(kadm_handle, &princ, mask); + if(ret) + krb5_warn(context, ret, "kadm5_modify_principal"); + if(princ_ent) + krb5_free_principal(context, princ_ent); + kadm5_free_principal_ent(kadm_handle, &princ); + return 0; +} diff --git a/crypto/heimdal/kadmin/random_password.c b/crypto/heimdal/kadmin/random_password.c new file mode 100644 index 0000000..aabe08c --- /dev/null +++ b/crypto/heimdal/kadmin/random_password.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 1998, 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "kadmin_locl.h" + +RCSID("$Id: random_password.c,v 1.3 1999/12/02 17:04:58 joda Exp $"); + +/* This file defines some a function that generates a random password, + that can be used when creating a large amount of principals (such + as for a batch of students). Since this is a political matter, you + should think about how secure generated passwords has to be. + + Both methods defined here will give you at least 55 bits of + entropy. + */ + +/* If you want OTP-style passwords, define OTP_STYLE */ + +#ifdef OTP_STYLE +#include <otp.h> +#else +static void generate_password(char **pw, int num_classes, ...); +#endif + +void +random_password(char *pw, size_t len) +{ +#ifdef OTP_STYLE + { + des_cblock newkey; + + des_new_random_key(&newkey); + otp_print_stddict (newkey, pw, len); + strlwr(pw); + } +#else + char *pass; + generate_password(&pass, 3, + "abcdefghijklmnopqrstuvwxyz", 7, + "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 2, + "@$%&*()-+=:,/<>1234567890", 1); + strlcpy(pw, pass, len); + memset(pass, 0, strlen(pass)); + free(pass); +#endif +} + +/* some helper functions */ + +#ifndef OTP_STYLE +/* return a random value in range 0-127 */ +static int +RND(des_cblock *key, int *left) +{ + if(*left == 0){ + des_new_random_key(key); + *left = 8; + } + (*left)--; + return ((unsigned char*)key)[*left]; +} + +/* This a helper function that generates a random password with a + number of characters from a set of character classes. + + If there are n classes, and the size of each class is Pi, and the + number of characters from each class is Ni, the number of possible + passwords are (given that the character classes are disjoint): + + n n + ----- / ---- \ + | | Ni | \ | + | | Pi | \ Ni| ! + | | ---- * | / | + | | Ni! | /___ | + i=1 \ i=1 / + + Since it uses the RND function above, neither the size of each + class, nor the total length of the generated password should be + larger than 127 (without fixing RND). + + */ +static void +generate_password(char **pw, int num_classes, ...) +{ + struct { + const char *str; + int len; + int freq; + } *classes; + va_list ap; + int len, i; + des_cblock rbuf; /* random buffer */ + int rleft = 0; + + classes = malloc(num_classes * sizeof(*classes)); + va_start(ap, num_classes); + len = 0; + for(i = 0; i < num_classes; i++){ + classes[i].str = va_arg(ap, const char*); + classes[i].len = strlen(classes[i].str); + classes[i].freq = va_arg(ap, int); + len += classes[i].freq; + } + va_end(ap); + *pw = malloc(len + 1); + if(*pw == NULL) + return; + for(i = 0; i < len; i++) { + int j; + int x = RND(&rbuf, &rleft) % (len - i); + int t = 0; + for(j = 0; j < num_classes; j++) { + if(x < t + classes[j].freq) { + (*pw)[i] = classes[j].str[RND(&rbuf, &rleft) % classes[j].len]; + classes[j].freq--; + break; + } + t += classes[j].freq; + } + } + (*pw)[len] = '\0'; + memset(rbuf, 0, sizeof(rbuf)); + free(classes); +} +#endif diff --git a/crypto/heimdal/kadmin/rename.c b/crypto/heimdal/kadmin/rename.c new file mode 100644 index 0000000..4d8a48e --- /dev/null +++ b/crypto/heimdal/kadmin/rename.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 1997 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "kadmin_locl.h" + +RCSID("$Id: rename.c,v 1.2 1999/12/02 17:04:58 joda Exp $"); + +int +rename_entry(int argc, char **argv) +{ + krb5_error_code ret; + krb5_principal princ1, princ2; + + if(argc != 3){ + krb5_warnx(context, "rename source target"); + return 0; + } + ret = krb5_parse_name(context, argv[1], &princ1); + if(ret){ + krb5_warn(context, ret, "krb5_parse_name(%s)", argv[1]); + return 0; + } + ret = krb5_parse_name(context, argv[2], &princ2); + if(ret){ + krb5_free_principal(context, princ2); + krb5_warn(context, ret, "krb5_parse_name(%s)", argv[2]); + return 0; + } + ret = kadm5_rename_principal(kadm_handle, princ1, princ2); + if(ret) + krb5_warn(context, ret, "rename"); + krb5_free_principal(context, princ1); + krb5_free_principal(context, princ2); + return 0; +} + diff --git a/crypto/heimdal/kadmin/server.c b/crypto/heimdal/kadmin/server.c new file mode 100644 index 0000000..d491e46 --- /dev/null +++ b/crypto/heimdal/kadmin/server.c @@ -0,0 +1,506 @@ +/* + * Copyright (c) 1997 - 2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "kadmin_locl.h" +#include <krb5-private.h> + +RCSID("$Id: server.c,v 1.24 2000/01/02 03:58:45 assar Exp $"); + +static kadm5_ret_t +kadmind_dispatch(void *kadm_handle, krb5_boolean initial, + krb5_data *in, krb5_data *out) +{ + kadm5_ret_t ret; + int32_t cmd, mask, tmp; + kadm5_server_context *context = kadm_handle; + char client[128], name[128], name2[128]; + char *op = ""; + krb5_principal princ, princ2; + kadm5_principal_ent_rec ent; + char *password, *exp; + krb5_keyblock *new_keys; + int n_keys; + char **princs; + int n_princs; + krb5_storage *sp; + + krb5_unparse_name_fixed(context->context, context->caller, + client, sizeof(client)); + + sp = krb5_storage_from_data(in); + + krb5_ret_int32(sp, &cmd); + switch(cmd){ + case kadm_get:{ + op = "GET"; + ret = krb5_ret_principal(sp, &princ); + if(ret) + goto fail; + ret = krb5_ret_int32(sp, &mask); + if(ret){ + krb5_free_principal(context->context, princ); + goto fail; + } + krb5_unparse_name_fixed(context->context, princ, name, sizeof(name)); + krb5_warnx(context->context, "%s: %s %s", client, op, name); + ret = _kadm5_acl_check_permission(context, KADM5_PRIV_GET); + if(ret){ + krb5_free_principal(context->context, princ); + goto fail; + } + ret = kadm5_get_principal(kadm_handle, princ, &ent, mask); + krb5_storage_free(sp); + sp = krb5_storage_emem(); + krb5_store_int32(sp, ret); + if(ret == 0){ + kadm5_store_principal_ent(sp, &ent); + kadm5_free_principal_ent(kadm_handle, &ent); + } + krb5_free_principal(context->context, princ); + break; + } + case kadm_delete:{ + op = "DELETE"; + ret = krb5_ret_principal(sp, &princ); + if(ret) + goto fail; + krb5_unparse_name_fixed(context->context, princ, name, sizeof(name)); + krb5_warnx(context->context, "%s: %s %s", client, op, name); + ret = _kadm5_acl_check_permission(context, KADM5_PRIV_DELETE); + if(ret){ + krb5_free_principal(context->context, princ); + goto fail; + } + ret = kadm5_delete_principal(kadm_handle, princ); + krb5_free_principal(context->context, princ); + krb5_storage_free(sp); + sp = krb5_storage_emem(); + krb5_store_int32(sp, ret); + break; + } + case kadm_create:{ + op = "CREATE"; + ret = kadm5_ret_principal_ent(sp, &ent); + if(ret) + goto fail; + ret = krb5_ret_int32(sp, &mask); + if(ret){ + kadm5_free_principal_ent(context->context, &ent); + goto fail; + } + ret = krb5_ret_string(sp, &password); + if(ret){ + kadm5_free_principal_ent(context->context, &ent); + goto fail; + } + krb5_unparse_name_fixed(context->context, ent.principal, + name, sizeof(name)); + krb5_warnx(context->context, "%s: %s %s", client, op, name); + ret = _kadm5_acl_check_permission(context, KADM5_PRIV_ADD); + if(ret){ + kadm5_free_principal_ent(context->context, &ent); + memset(password, 0, strlen(password)); + free(password); + goto fail; + } + ret = kadm5_create_principal(kadm_handle, &ent, + mask, password); + kadm5_free_principal_ent(kadm_handle, &ent); + memset(password, 0, strlen(password)); + free(password); + krb5_storage_free(sp); + sp = krb5_storage_emem(); + krb5_store_int32(sp, ret); + break; + } + case kadm_modify:{ + op = "MODIFY"; + ret = kadm5_ret_principal_ent(sp, &ent); + if(ret) + goto fail; + ret = krb5_ret_int32(sp, &mask); + if(ret){ + kadm5_free_principal_ent(context, &ent); + goto fail; + } + krb5_unparse_name_fixed(context->context, ent.principal, + name, sizeof(name)); + krb5_warnx(context->context, "%s: %s %s", client, op, name); + ret = _kadm5_acl_check_permission(context, KADM5_PRIV_MODIFY); + if(ret){ + kadm5_free_principal_ent(context, &ent); + goto fail; + } + ret = kadm5_modify_principal(kadm_handle, &ent, mask); + kadm5_free_principal_ent(kadm_handle, &ent); + krb5_storage_free(sp); + sp = krb5_storage_emem(); + krb5_store_int32(sp, ret); + break; + } + case kadm_rename:{ + op = "RENAME"; + ret = krb5_ret_principal(sp, &princ); + if(ret) + goto fail; + ret = krb5_ret_principal(sp, &princ2); + if(ret){ + krb5_free_principal(context->context, princ); + goto fail; + } + krb5_unparse_name_fixed(context->context, princ, name, sizeof(name)); + krb5_unparse_name_fixed(context->context, princ2, name2, sizeof(name2)); + krb5_warnx(context->context, "%s: %s %s -> %s", + client, op, name, name2); + ret = _kadm5_acl_check_permission(context, + KADM5_PRIV_ADD|KADM5_PRIV_DELETE); + if(ret){ + krb5_free_principal(context->context, princ); + goto fail; + } + ret = kadm5_rename_principal(kadm_handle, princ, princ2); + krb5_free_principal(context->context, princ); + krb5_free_principal(context->context, princ2); + krb5_storage_free(sp); + sp = krb5_storage_emem(); + krb5_store_int32(sp, ret); + break; + } + case kadm_chpass:{ + op = "CHPASS"; + ret = krb5_ret_principal(sp, &princ); + if(ret) + goto fail; + ret = krb5_ret_string(sp, &password); + if(ret){ + krb5_free_principal(context->context, princ); + goto fail; + } + krb5_unparse_name_fixed(context->context, princ, name, sizeof(name)); + krb5_warnx(context->context, "%s: %s %s", client, op, name); + + /* + * The change is allowed if at least one of: + * a) it's for the principal him/herself and this was an initial ticket + * b) the user is on the CPW ACL. + */ + + if (initial + && krb5_principal_compare (context->context, context->caller, + princ)) + ret = 0; + else + ret = _kadm5_acl_check_permission(context, KADM5_PRIV_CPW); + + if(ret) { + krb5_free_principal(context->context, princ); + goto fail; + } + ret = kadm5_chpass_principal(kadm_handle, princ, password); + krb5_free_principal(context->context, princ); + memset(password, 0, strlen(password)); + free(password); + krb5_storage_free(sp); + sp = krb5_storage_emem(); + krb5_store_int32(sp, ret); + break; + } + case kadm_randkey:{ + op = "RANDKEY"; + ret = krb5_ret_principal(sp, &princ); + if(ret) + goto fail; + krb5_unparse_name_fixed(context->context, princ, name, sizeof(name)); + krb5_warnx(context->context, "%s: %s %s", client, op, name); + /* + * The change is allowed if at least one of: + * a) it's for the principal him/herself and this was an initial ticket + * b) the user is on the CPW ACL. + */ + + if (initial + && krb5_principal_compare (context->context, context->caller, + princ)) + ret = 0; + else + ret = _kadm5_acl_check_permission(context, KADM5_PRIV_CPW); + + if(ret) { + krb5_free_principal(context->context, princ); + goto fail; + } + ret = kadm5_randkey_principal(kadm_handle, princ, + &new_keys, &n_keys); + krb5_free_principal(context->context, princ); + krb5_storage_free(sp); + sp = krb5_storage_emem(); + krb5_store_int32(sp, ret); + if(ret == 0){ + int i; + krb5_store_int32(sp, n_keys); + for(i = 0; i < n_keys; i++){ + krb5_store_keyblock(sp, new_keys[i]); + krb5_free_keyblock_contents(context->context, &new_keys[i]); + } + } + break; + } + case kadm_get_privs:{ + ret = kadm5_get_privs(kadm_handle, &mask); + krb5_storage_free(sp); + sp = krb5_storage_emem(); + krb5_store_int32(sp, ret); + if(ret == 0) + krb5_store_int32(sp, mask); + break; + } + case kadm_get_princs:{ + op = "LIST"; + ret = krb5_ret_int32(sp, &tmp); + if(ret) + goto fail; + if(tmp){ + ret = krb5_ret_string(sp, &exp); + if(ret) + goto fail; + }else + exp = NULL; + krb5_warnx(context->context, "%s: %s %s", client, op, exp ? exp : "*"); + ret = _kadm5_acl_check_permission(context, KADM5_PRIV_LIST); + if(ret){ + free(exp); + goto fail; + } + ret = kadm5_get_principals(kadm_handle, exp, &princs, &n_princs); + free(exp); + krb5_storage_free(sp); + sp = krb5_storage_emem(); + krb5_store_int32(sp, ret); + if(ret == 0){ + int i; + krb5_store_int32(sp, n_princs); + for(i = 0; i < n_princs; i++) + krb5_store_string(sp, princs[i]); + kadm5_free_name_list(kadm_handle, princs, &n_princs); + } + break; + } + default: + krb5_warnx(context->context, "%s: UNKNOWN OP %d", client, cmd); + krb5_storage_free(sp); + sp = krb5_storage_emem(); + krb5_store_int32(sp, KADM5_FAILURE); + break; + } + krb5_storage_to_data(sp, out); + krb5_storage_free(sp); + return 0; +fail: + krb5_warn(context->context, ret, "%s", op); + sp->seek(sp, 0, SEEK_SET); + krb5_store_int32(sp, ret); + krb5_storage_to_data(sp, out); + krb5_storage_free(sp); + return 0; +} + +static void +v5_loop (krb5_context context, + krb5_auth_context ac, + krb5_boolean initial, + void *kadm_handle, + int fd) +{ + krb5_error_code ret; + ssize_t n; + unsigned long len; + u_char tmp[4]; + struct iovec iov[2]; + krb5_data in, out, msg, reply; + + for (;;) { + n = krb5_net_read(context, &fd, tmp, 4); + if (n < 0) + krb5_err (context, 1, errno, "krb5_net_read"); + if (n == 0) + exit (0); + _krb5_get_int (tmp, &len, 4); + + ret = krb5_data_alloc(&in, len); + if (ret) + krb5_err (context, 1, ret, "krb5_data_alloc"); + + n = krb5_net_read(context, &fd, in.data, in.length); + if (n == 0) + exit (0); + if(n < 0) + krb5_errx(context, 1, "read error: %d", errno); + ret = krb5_rd_priv(context, ac, &in, &out, NULL); + if (ret) + krb5_err(context, 1, ret, "krb5_rd_priv"); + krb5_data_free(&in); + kadmind_dispatch(kadm_handle, initial, &out, &msg); + krb5_data_free(&out); + ret = krb5_mk_priv(context, ac, &msg, &reply, NULL); + krb5_data_free(&msg); + if(ret) + krb5_err(context, 1, ret, "krb5_mk_priv"); + + _krb5_put_int(tmp, reply.length, 4); + + iov[0].iov_base = tmp; + iov[0].iov_len = 4; + iov[1].iov_base = reply.data; + iov[1].iov_len = reply.length; + n = writev(fd, iov, 2); + krb5_data_free(&reply); + if(n < 0) + krb5_err(context, 1, errno, "writev"); + if(n < iov[0].iov_len + iov[1].iov_len) + krb5_errx(context, 1, "short write"); + } +} + +static krb5_boolean +match_appl_version(void *data, const char *appl_version) +{ + unsigned minor; + if(sscanf(appl_version, "KADM0.%u", &minor) != 1) + return 0; + *(unsigned*)data = minor; + return 1; +} + +static void +handle_v5(krb5_context context, + krb5_auth_context ac, + krb5_keytab keytab, + int len, + int fd) +{ + krb5_error_code ret; + u_char version[sizeof(KRB5_SENDAUTH_VERSION)]; + krb5_ticket *ticket; + krb5_principal server; + char *client; + void *kadm_handle; + ssize_t n; + krb5_boolean initial; + + unsigned kadm_version; + kadm5_config_params realm_params; + + if (len != sizeof(KRB5_SENDAUTH_VERSION)) + krb5_errx(context, 1, "bad sendauth len %d", len); + n = krb5_net_read(context, &fd, version, len); + if (n < 0) + krb5_err (context, 1, errno, "reading sendauth version"); + if (n == 0) + krb5_errx (context, 1, "EOF reading sendauth version"); + if(memcmp(version, KRB5_SENDAUTH_VERSION, len) != 0) + krb5_errx(context, 1, "bad sendauth version %.8s", version); + + ret = krb5_parse_name(context, KADM5_ADMIN_SERVICE, &server); + if (ret) + krb5_err (context, 1, ret, "krb5_parse_name %s", KADM5_ADMIN_SERVICE); + ret = krb5_recvauth_match_version(context, &ac, &fd, + match_appl_version, &kadm_version, + server, KRB5_RECVAUTH_IGNORE_VERSION, + keytab, &ticket); + if(ret == KRB5_KT_NOTFOUND) { + char *name; + krb5_unparse_name(context, server, &name); + krb5_errx(context, 1, "krb5_recvauth: %s (%s)", + krb5_get_err_text(context, ret), + name); + } + krb5_free_principal(context, server); + + if(ret) + krb5_err(context, 1, ret, "krb5_recvauth"); + + memset(&realm_params, 0, sizeof(realm_params)); + + if(kadm_version == 1) { + krb5_data enc_data, params; + ret = krb5_read_message(context, &fd, &enc_data); + ret = krb5_rd_priv(context, ac, &enc_data, ¶ms, NULL); + krb5_data_free(&enc_data); + _kadm5_unmarshal_params(context, ¶ms, &realm_params); + } + + initial = ticket->ticket.flags.initial; + ret = krb5_unparse_name(context, ticket->client, &client); + if (ret) + krb5_err (context, 1, ret, "krb5_unparse_name"); + krb5_free_ticket (context, ticket); + ret = kadm5_init_with_password_ctx(context, + client, + NULL, + KADM5_ADMIN_SERVICE, + &realm_params, + 0, 0, + &kadm_handle); + if(ret) + krb5_err (context, 1, ret, "kadm5_init_with_password_ctx"); + v5_loop (context, ac, initial, kadm_handle, fd); +} + +krb5_error_code +kadmind_loop(krb5_context context, + krb5_auth_context ac, + krb5_keytab keytab, + int fd) +{ + unsigned char tmp[4]; + ssize_t n; + unsigned long len; + + n = krb5_net_read(context, &fd, tmp, 4); + if(n == 0) + exit(0); + if(n < 0) + krb5_errx(context, 1, "read error: %d", errno); + _krb5_get_int(tmp, &len, 4); + if(len > 0xffff && (len & 0xffff) == ('K' << 8) + 'A') { + len >>= 16; +#ifdef KRB4 + handle_v4(context, len, fd); +#else + krb5_errx(context, 1, "packet appears to be version 4"); +#endif + } else { + handle_v5(context, ac, keytab, len, fd); + } + return 0; +} diff --git a/crypto/heimdal/kadmin/util.c b/crypto/heimdal/kadmin/util.c new file mode 100644 index 0000000..f30c8c5 --- /dev/null +++ b/crypto/heimdal/kadmin/util.c @@ -0,0 +1,520 @@ +/* + * Copyright (c) 1997, 1998, 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "kadmin_locl.h" +#include <parse_units.h> + +RCSID("$Id: util.c,v 1.23 1999/12/02 17:04:58 joda Exp $"); + +/* + * util.c - functions for parsing, unparsing, and editing different + * types of data used in kadmin. + */ + +/* + * attributes + */ + +struct units kdb_attrs[] = { + { "new-princ", KRB5_KDB_NEW_PRINC }, + { "support-desmd5", KRB5_KDB_SUPPORT_DESMD5 }, + { "pwchange-service", KRB5_KDB_PWCHANGE_SERVICE }, + { "disallow-svr", KRB5_KDB_DISALLOW_SVR }, + { "requires-pw-change", KRB5_KDB_REQUIRES_PWCHANGE }, + { "requires-hw-auth", KRB5_KDB_REQUIRES_HW_AUTH }, + { "requires-pre-auth", KRB5_KDB_REQUIRES_PRE_AUTH }, + { "disallow-all-tix", KRB5_KDB_DISALLOW_ALL_TIX }, + { "disallow-dup-skey", KRB5_KDB_DISALLOW_DUP_SKEY }, + { "disallow-proxiable", KRB5_KDB_DISALLOW_PROXIABLE }, + { "disallow-renewable", KRB5_KDB_DISALLOW_RENEWABLE }, + { "disallow-tgt-based", KRB5_KDB_DISALLOW_TGT_BASED }, + { "disallow-forwardable", KRB5_KDB_DISALLOW_FORWARDABLE }, + { "disallow-postdated", KRB5_KDB_DISALLOW_POSTDATED }, + { NULL } +}; + +/* + * convert the attributes in `attributes' into a printable string + * in `str, len' + */ + +void +attributes2str(krb5_flags attributes, char *str, size_t len) +{ + unparse_flags (attributes, kdb_attrs, str, len); +} + +/* + * convert the string in `str' into attributes in `flags' + * return 0 if parsed ok, else -1. + */ + +int +str2attributes(const char *str, krb5_flags *flags) +{ + int res; + + res = parse_flags (str, kdb_attrs, *flags); + if (res < 0) + return res; + else { + *flags = res; + return 0; + } +} + +/* + * try to parse the string `resp' into attributes in `attr', also + * setting the `bit' in `mask' if attributes are given and valid. + */ + +int +parse_attributes (const char *resp, krb5_flags *attr, int *mask, int bit) +{ + krb5_flags tmp = *attr; + + if (resp[0] == '\0') + return 0; + else if (str2attributes(resp, &tmp) == 0) { + *attr = tmp; + if (mask) + *mask |= bit; + return 0; + } else if(*resp == '?') { + print_flags_table (kdb_attrs, stderr); + } else { + fprintf (stderr, "Unable to parse '%s'\n", resp); + } + return -1; +} + +/* + * allow the user to edit the attributes in `attr', prompting with `prompt' + */ + +int +edit_attributes (const char *prompt, krb5_flags *attr, int *mask, int bit) +{ + char buf[1024], resp[1024]; + + if (mask && (*mask & bit)) + return 0; + + attributes2str(*attr, buf, sizeof(buf)); + for (;;) { + get_response("Attributes", buf, resp, sizeof(resp)); + if (parse_attributes (resp, attr, mask, bit) == 0) + break; + } + return 0; +} + +/* + * time_t + * the special value 0 means ``never'' + */ + +/* + * Convert the time `t' to a string representation in `str' (of max + * size `len'). If include_time also include time, otherwise just + * date. + */ + +void +time_t2str(time_t t, char *str, size_t len, int include_time) +{ + if(t) { + if(include_time) + strftime(str, len, "%Y-%m-%d %H:%M:%S UTC", gmtime(&t)); + else + strftime(str, len, "%Y-%m-%d", gmtime(&t)); + } else + snprintf(str, len, "never"); +} + +/* + * Convert the time representation in `str' to a time in `time'. + * Return 0 if succesful, else -1. + */ + +int +str2time_t (const char *str, time_t *time) +{ + const char *p; + struct tm tm; + + memset (&tm, 0, sizeof (tm)); + + if(strcasecmp(str, "never") == 0) { + *time = 0; + return 0; + } + + p = strptime (str, "%Y-%m-%d", &tm); + + if (p == NULL) + return -1; + + /* Do it on the end of the day */ + tm.tm_hour = 23; + tm.tm_min = 59; + tm.tm_sec = 59; + + strptime (p, "%H:%M:%S", &tm); + + *time = tm2time (tm, 0); + return 0; +} + +/* + * try to parse the time in `resp' storing it in `value' + */ + +int +parse_timet (const char *resp, krb5_timestamp *value, int *mask, int bit) +{ + time_t tmp; + + if (str2time_t(resp, &tmp) == 0) { + *value = tmp; + if(mask) + *mask |= bit; + return 0; + } else if(*resp == '?') { + printf ("Print date on format YYYY-mm-dd [hh:mm:ss]\n"); + } else { + fprintf (stderr, "Unable to parse time '%s'\n", resp); + } + return -1; +} + +/* + * allow the user to edit the time in `value' + */ + +int +edit_timet (const char *prompt, krb5_timestamp *value, int *mask, int bit) +{ + char buf[1024], resp[1024]; + + if (mask && (*mask & bit)) + return 0; + + time_t2str (*value, buf, sizeof (buf), 0); + + for (;;) { + get_response(prompt, buf, resp, sizeof(resp)); + if (parse_timet (resp, value, mask, bit) == 0) + break; + } + return 0; +} + +/* + * deltat + * the special value 0 means ``unlimited'' + */ + +/* + * convert the delta_t value in `t' into a printable form in `str, len' + */ + +void +deltat2str(unsigned t, char *str, size_t len) +{ + if(t) + unparse_time(t, str, len); + else + snprintf(str, len, "unlimited"); +} + +/* + * parse the delta value in `str', storing result in `*delta' + * return 0 if ok, else -1 + */ + +int +str2deltat(const char *str, krb5_deltat *delta) +{ + int res; + + if(strcasecmp(str, "unlimited") == 0) { + *delta = 0; + return 0; + } + res = parse_time(str, "day"); + if (res < 0) + return res; + else { + *delta = res; + return 0; + } +} + +/* + * try to parse the string in `resp' into a deltad in `value' + * `mask' will get the bit `bit' set if a value was given. + */ + +int +parse_deltat (const char *resp, krb5_deltat *value, int *mask, int bit) +{ + krb5_deltat tmp; + + if (str2deltat(resp, &tmp) == 0) { + *value = tmp; + if (mask) + *mask |= bit; + return 0; + } else if(*resp == '?') { + print_time_table (stderr); + } else { + fprintf (stderr, "Unable to parse time '%s'\n", resp); + } + return -1; +} + +/* + * allow the user to edit the deltat in `value' + */ + +int +edit_deltat (const char *prompt, krb5_deltat *value, int *mask, int bit) +{ + char buf[1024], resp[1024]; + + if (mask && (*mask & bit)) + return 0; + + deltat2str(*value, buf, sizeof(buf)); + for (;;) { + get_response(prompt, buf, resp, sizeof(resp)); + if (parse_deltat (resp, value, mask, bit) == 0) + break; + } + return 0; +} + +/* + * allow the user to edit `ent' + */ + +int +edit_entry(kadm5_principal_ent_t ent, int *mask, + kadm5_principal_ent_t default_ent, int default_mask) +{ + if (default_ent && (default_mask & KADM5_MAX_LIFE)) + ent->max_life = default_ent->max_life; + edit_deltat ("Max ticket life", &ent->max_life, mask, + KADM5_MAX_LIFE); + + if (default_ent && (default_mask & KADM5_MAX_RLIFE)) + ent->max_renewable_life = default_ent->max_renewable_life; + edit_deltat ("Max renewable life", &ent->max_renewable_life, mask, + KADM5_MAX_RLIFE); + + if (default_ent && (default_mask & KADM5_PRINC_EXPIRE_TIME)) + ent->princ_expire_time = default_ent->princ_expire_time; + edit_timet ("Principal expiration time", &ent->princ_expire_time, mask, + KADM5_PRINC_EXPIRE_TIME); + + if (default_ent && (default_mask & KADM5_PW_EXPIRATION)) + ent->pw_expiration = default_ent->pw_expiration; + edit_timet ("Password expiration time", &ent->pw_expiration, mask, + KADM5_PW_EXPIRATION); + + if (default_ent && (default_mask & KADM5_ATTRIBUTES)) + ent->attributes = default_ent->attributes & ~KRB5_KDB_DISALLOW_ALL_TIX; + edit_attributes ("Attributes", &ent->attributes, mask, + KADM5_ATTRIBUTES); + return 0; +} + +/* + * Parse the arguments, set the fields in `ent' and the `mask' for the + * entries having been set. + * Return 1 on failure and 0 on success. + */ + +int +set_entry(krb5_context context, + kadm5_principal_ent_t ent, + int *mask, + const char *max_ticket_life, + const char *max_renewable_life, + const char *expiration, + const char *pw_expiration, + const char *attributes) +{ + if (max_ticket_life != NULL) { + if (parse_deltat (max_ticket_life, &ent->max_life, + mask, KADM5_MAX_LIFE)) { + krb5_warnx (context, "unable to parse `%s'", max_ticket_life); + return 1; + } + } + if (max_renewable_life != NULL) { + if (parse_deltat (max_renewable_life, &ent->max_renewable_life, + mask, KADM5_MAX_RLIFE)) { + krb5_warnx (context, "unable to parse `%s'", max_renewable_life); + return 1; + } + } + + if (expiration) { + if (parse_timet (expiration, &ent->princ_expire_time, + mask, KADM5_PRINC_EXPIRE_TIME)) { + krb5_warnx (context, "unable to parse `%s'", expiration); + return 1; + } + } + if (pw_expiration) { + if (parse_timet (pw_expiration, &ent->pw_expiration, + mask, KADM5_PW_EXPIRATION)) { + krb5_warnx (context, "unable to parse `%s'", pw_expiration); + return 1; + } + } + if (attributes != NULL) { + if (parse_attributes (attributes, &ent->attributes, + mask, KADM5_ATTRIBUTES)) { + krb5_warnx (context, "unable to parse `%s'", attributes); + return 1; + } + } + return 0; +} + +/* + * Does `string' contain any globing characters? + */ + +static int +is_expression(const char *string) +{ + const char *p; + int quote = 0; + + for(p = string; *p; p++) { + if(quote) { + quote = 0; + continue; + } + if(*p == '\\') + quote++; + else if(strchr("[]*?", *p) != NULL) + return 1; + } + return 0; +} + +/* loop over all principals matching exp */ +int +foreach_principal(const char *exp, + int (*func)(krb5_principal, void*), + void *data) +{ + char **princs; + int num_princs; + int i; + krb5_error_code ret; + krb5_principal princ_ent; + int is_expr; + + /* if this isn't an expression, there is no point in wading + through the whole database looking for matches */ + is_expr = is_expression(exp); + if(is_expr) + ret = kadm5_get_principals(kadm_handle, exp, &princs, &num_princs); + if(!is_expr || ret == KADM5_AUTH_LIST) { + /* we might be able to perform the requested opreration even + if we're not allowed to list principals */ + num_princs = 1; + princs = malloc(sizeof(*princs)); + if(princs == NULL) + return ENOMEM; + princs[0] = strdup(exp); + if(princs[0] == NULL){ + free(princs); + return ENOMEM; + } + } else if(ret) { + krb5_warn(context, ret, "kadm5_get_principals"); + return ret; + } + for(i = 0; i < num_princs; i++) { + ret = krb5_parse_name(context, princs[i], &princ_ent); + if(ret){ + krb5_warn(context, ret, "krb5_parse_name(%s)", princs[i]); + continue; + } + ret = (*func)(princ_ent, data); + if(ret) { + char *tmp; + krb5_error_code ret2; + + ret2 = krb5_unparse_name(context, princ_ent, &tmp); + if(ret2) { + krb5_warn(context, ret2, "krb5_unparse_name"); + krb5_warn(context, ret, "<unknown principal>"); + } else { + krb5_warn(context, ret, "%s", tmp); + free(tmp); + } + } + krb5_free_principal(context, princ_ent); + } + kadm5_free_name_list(kadm_handle, princs, &num_princs); + return 0; +} + +/* + * prompt with `prompt' and default value `def', and store the reply + * in `buf, len' + */ + +void +get_response(const char *prompt, const char *def, char *buf, size_t len) +{ + char *p; + + printf("%s [%s]:", prompt, def); + if(fgets(buf, len, stdin) == NULL) + *buf = '\0'; + p = strchr(buf, '\n'); + if(p) + *p = '\0'; + if(strcmp(buf, "") == 0) + strncpy(buf, def, len); + buf[len-1] = 0; +} diff --git a/crypto/heimdal/kadmin/version4.c b/crypto/heimdal/kadmin/version4.c new file mode 100644 index 0000000..77ac029 --- /dev/null +++ b/crypto/heimdal/kadmin/version4.c @@ -0,0 +1,985 @@ +/* + * Copyright (c) 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include "kadmin_locl.h" +#include <krb5-private.h> + +#define Principal krb4_Principal +#define kadm_get krb4_kadm_get +#undef ALLOC +#include <krb.h> +#include <kadm.h> +#include <krb_err.h> +#include <kadm_err.h> + +RCSID("$Id: version4.c,v 1.16 1999/11/25 22:32:47 assar Exp $"); + +#define KADM_NO_OPCODE -1 +#define KADM_NO_ENCRYPT -2 + +/* + * make an error packet if we fail encrypting + */ + +static void +make_you_loose_packet(int code, krb5_data *reply) +{ + krb5_data_alloc(reply, KADM_VERSIZE + 4); + memcpy(reply->data, KADM_ULOSE, KADM_VERSIZE); + _krb5_put_int((char*)reply->data + KADM_VERSIZE, code, 4); +} + +static int +ret_fields(krb5_storage *sp, char *fields) +{ + return sp->fetch(sp, fields, FLDSZ); +} + +static int +store_fields(krb5_storage *sp, char *fields) +{ + return sp->store(sp, fields, FLDSZ); +} + +static void +ret_vals(krb5_storage *sp, Kadm_vals *vals) +{ + int field; + char *tmp_string; + + memset(vals, 0, sizeof(*vals)); + + ret_fields(sp, vals->fields); + + for(field = 31; field >= 0; field--) { + if(IS_FIELD(field, vals->fields)) { + switch(field) { + case KADM_NAME: + krb5_ret_stringz(sp, &tmp_string); + strlcpy(vals->name, tmp_string, sizeof(vals->name)); + free(tmp_string); + break; + case KADM_INST: + krb5_ret_stringz(sp, &tmp_string); + strlcpy(vals->instance, tmp_string, + sizeof(vals->instance)); + free(tmp_string); + break; + case KADM_EXPDATE: + krb5_ret_int32(sp, &vals->exp_date); + break; + case KADM_ATTR: + krb5_ret_int16(sp, &vals->attributes); + break; + case KADM_MAXLIFE: + krb5_ret_int8(sp, &vals->max_life); + break; + case KADM_DESKEY: + krb5_ret_int32(sp, &vals->key_high); + krb5_ret_int32(sp, &vals->key_low); + break; +#ifdef EXTENDED_KADM + case KADM_MODDATE: + krb5_ret_int32(sp, &vals->mod_date); + break; + case KADM_MODNAME: + krb5_ret_stringz(sp, &tmp_string); + strlcpy(vals->mod_name, tmp_string, + sizeof(vals->mod_name)); + free(tmp_string); + break; + case KADM_MODINST: + krb5_ret_stringz(sp, &tmp_string); + strlcpy(vals->mod_instance, tmp_string, + sizeof(vals->mod_instance)); + free(tmp_string); + break; + case KADM_KVNO: + krb5_ret_int8(sp, &vals->key_version); + break; +#endif + default: + break; + } + } + } +} + +static void +store_vals(krb5_storage *sp, Kadm_vals *vals) +{ + int field; + + store_fields(sp, vals->fields); + + for(field = 31; field >= 0; field--) { + if(IS_FIELD(field, vals->fields)) { + switch(field) { + case KADM_NAME: + krb5_store_stringz(sp, vals->name); + break; + case KADM_INST: + krb5_store_stringz(sp, vals->instance); + break; + case KADM_EXPDATE: + krb5_store_int32(sp, vals->exp_date); + break; + case KADM_ATTR: + krb5_store_int16(sp, vals->attributes); + break; + case KADM_MAXLIFE: + krb5_store_int8(sp, vals->max_life); + break; + case KADM_DESKEY: + krb5_store_int32(sp, vals->key_high); + krb5_store_int32(sp, vals->key_low); + break; +#ifdef EXTENDED_KADM + case KADM_MODDATE: + krb5_store_int32(sp, vals->mod_date); + break; + case KADM_MODNAME: + krb5_store_stringz(sp, vals->mod_name); + break; + case KADM_MODINST: + krb5_store_stringz(sp, vals->mod_instance); + break; + case KADM_KVNO: + krb5_store_int8(sp, vals->key_version); + break; +#endif + default: + break; + } + } + } +} + +static int +flags_4_to_5(char *flags) +{ + int i; + int32_t mask = 0; + for(i = 31; i >= 0; i--) { + if(IS_FIELD(i, flags)) + switch(i) { + case KADM_NAME: + case KADM_INST: + mask |= KADM5_PRINCIPAL; + case KADM_EXPDATE: + mask |= KADM5_PW_EXPIRATION; + case KADM_MAXLIFE: + mask |= KADM5_MAX_LIFE; +#ifdef EXTENDED_KADM + case KADM_KVNO: + mask |= KADM5_KEY_DATA; + case KADM_MODDATE: + mask |= KADM5_MOD_TIME; + case KADM_MODNAME: + case KADM_MODINST: + mask |= KADM5_MOD_NAME; +#endif + } + } + return mask; +} + +static void +ent_to_values(krb5_context context, + kadm5_principal_ent_t ent, + int32_t mask, + Kadm_vals *vals) +{ + krb5_error_code ret; + char realm[REALM_SZ]; + + memset(vals, 0, sizeof(*vals)); + if(mask & KADM5_PRINCIPAL) { + ret = krb5_524_conv_principal(context, ent->principal, + vals->name, vals->instance, realm); + SET_FIELD(KADM_NAME, vals->fields); + SET_FIELD(KADM_INST, vals->fields); + } + if(mask & KADM5_PW_EXPIRATION) { + time_t exp = 0; + if(ent->princ_expire_time != 0) + exp = ent->princ_expire_time; + if(ent->pw_expiration != 0 && (exp == 0 || exp > ent->pw_expiration)) + exp = ent->pw_expiration; + if(exp) { + vals->exp_date = exp; + SET_FIELD(KADM_EXPDATE, vals->fields); + } + } + if(mask & KADM5_MAX_LIFE) { + if(ent->max_life == 0) + vals->max_life = 255; + else + vals->max_life = krb_time_to_life(0, ent->max_life); + SET_FIELD(KADM_MAXLIFE, vals->fields); + } + if(mask & KADM5_KEY_DATA) { + if(ent->n_key_data > 0) { +#ifdef EXTENDED_KADM + vals->key_version = ent->key_data[0].key_data_kvno; + SET_FIELD(KADM_KVNO, vals->fields); +#endif + } + /* XXX the key itself? */ + } +#ifdef EXTENDED_KADM + if(mask & KADM5_MOD_TIME) { + vals->mod_date = ent->mod_date; + SET_FIELD(KADM_MODDATE, vals->fields); + } + if(mask & KADM5_MOD_NAME) { + krb5_524_conv_principal(context, ent->mod_name, + vals->mod_name, vals->mod_instance, realm); + SET_FIELD(KADM_MODNAME, vals->fields); + SET_FIELD(KADM_MODINST, vals->fields); + } +#endif +} + +/* + * convert the kadm4 values in `vals' to `ent' (and `mask') + */ + +static krb5_error_code +values_to_ent(krb5_context context, + Kadm_vals *vals, + kadm5_principal_ent_t ent, + int32_t *mask) +{ + krb5_error_code ret; + *mask = 0; + memset(ent, 0, sizeof(*ent)); + + if(IS_FIELD(KADM_NAME, vals->fields)) { + char *inst = NULL; + if(IS_FIELD(KADM_INST, vals->fields)) + inst = vals->instance; + ret = krb5_425_conv_principal(context, + vals->name, + inst, + NULL, + &ent->principal); + if(ret) + return ret; + *mask |= KADM5_PRINCIPAL; + } + if(IS_FIELD(KADM_EXPDATE, vals->fields)) { + ent->pw_expiration = vals->exp_date; + *mask |= KADM5_PW_EXPIRATION; + } + if(IS_FIELD(KADM_MAXLIFE, vals->fields)) { + ent->max_life = krb_life_to_time(0, vals->max_life); + *mask |= KADM5_MAX_LIFE; + } + + if(IS_FIELD(KADM_DESKEY, vals->fields)) { + int i; + ent->key_data = calloc(3, sizeof(*ent->key_data)); + if(ent->key_data == NULL) + return ENOMEM; + for(i = 0; i < 3; i++) { + u_int32_t key_low, key_high; + + ent->key_data[i].key_data_ver = 2; +#ifdef EXTENDED_KADM + if(IS_FIELD(KADM_KVNO, vals->fields)) + ent->key_data[i].key_data_kvno = vals->key_version; +#endif + ent->key_data[i].key_data_type[0] = ETYPE_DES_CBC_MD5; + ent->key_data[i].key_data_length[0] = 8; + if((ent->key_data[i].key_data_contents[0] = malloc(8)) == NULL) + return ENOMEM; + + key_low = ntohl(vals->key_low); + key_high = ntohl(vals->key_high); + memcpy(ent->key_data[i].key_data_contents[0], + &key_low, 4); + memcpy((char*)ent->key_data[i].key_data_contents[0] + 4, + &key_high, 4); + ent->key_data[i].key_data_type[1] = KRB5_PW_SALT; + ent->key_data[i].key_data_length[1] = 0; + ent->key_data[i].key_data_contents[1] = NULL; + } + ent->key_data[1].key_data_type[0] = ETYPE_DES_CBC_MD4; + ent->key_data[2].key_data_type[0] = ETYPE_DES_CBC_CRC; + ent->n_key_data = 3; + *mask |= KADM5_KEY_DATA; + } + +#ifdef EXTENDED_KADM + if(IS_FIELD(KADM_MODDATE, vals->fields)) { + ent->mod_date = vals->mod_date; + *mask |= KADM5_MOD_TIME; + } + if(IS_FIELD(KADM_MODNAME, vals->fields)) { + char *inst = NULL; + if(IS_FIELD(KADM_MODINST, vals->fields)) + inst = vals->mod_instance; + ret = krb5_425_conv_principal(context, + vals->mod_name, + inst, + NULL, + &ent->mod_name); + if(ret) + return ret; + *mask |= KADM5_MOD_NAME; + } +#endif + return 0; +} + +/* + * Try to translate a KADM5 error code into a v4 kadmin one. + */ + +static int +error_code(int ret) +{ + switch (ret) { + case 0: + return 0; + case KADM5_FAILURE : + case KADM5_AUTH_GET : + case KADM5_AUTH_ADD : + case KADM5_AUTH_MODIFY : + case KADM5_AUTH_DELETE : + case KADM5_AUTH_INSUFFICIENT : + return KADM_UNAUTH; + case KADM5_BAD_DB : + return KADM_UK_RERROR; + case KADM5_DUP : + return KADM_INUSE; + case KADM5_RPC_ERROR : + case KADM5_NO_SRV : + return KADM_NO_SERV; + case KADM5_NOT_INIT : + return KADM_NO_CONN; + case KADM5_UNK_PRINC : + return KADM_NOENTRY; + case KADM5_PASS_Q_TOOSHORT : +#ifdef KADM_PASS_Q_TOOSHORT + return KADM_PASS_Q_TOOSHORT; +#else + return KADM_INSECURE_PW; +#endif + case KADM5_PASS_Q_CLASS : +#ifdef KADM_PASS_Q_CLASS + return KADM_PASS_Q_CLASS; +#else + return KADM_INSECURE_PW; +#endif + case KADM5_PASS_Q_DICT : +#ifdef KADM_PASS_Q_DICT + return KADM_PASS_Q_DICT; +#else + return KADM_INSECURE_PW; +#endif + case KADM5_PASS_REUSE : + case KADM5_PASS_TOOSOON : + case KADM5_BAD_PASSWORD : + return KADM_INSECURE_PW; + case KADM5_PROTECT_PRINCIPAL : + return KADM_IMMUTABLE; + case KADM5_POLICY_REF : + case KADM5_INIT : + case KADM5_BAD_HIST_KEY : + case KADM5_UNK_POLICY : + case KADM5_BAD_MASK : + case KADM5_BAD_CLASS : + case KADM5_BAD_LENGTH : + case KADM5_BAD_POLICY : + case KADM5_BAD_PRINCIPAL : + case KADM5_BAD_AUX_ATTR : + case KADM5_BAD_HISTORY : + case KADM5_BAD_MIN_PASS_LIFE : + case KADM5_BAD_SERVER_HANDLE : + case KADM5_BAD_STRUCT_VERSION : + case KADM5_OLD_STRUCT_VERSION : + case KADM5_NEW_STRUCT_VERSION : + case KADM5_BAD_API_VERSION : + case KADM5_OLD_LIB_API_VERSION : + case KADM5_OLD_SERVER_API_VERSION : + case KADM5_NEW_LIB_API_VERSION : + case KADM5_NEW_SERVER_API_VERSION : + case KADM5_SECURE_PRINC_MISSING : + case KADM5_NO_RENAME_SALT : + case KADM5_BAD_CLIENT_PARAMS : + case KADM5_BAD_SERVER_PARAMS : + case KADM5_AUTH_LIST : + case KADM5_AUTH_CHANGEPW : + case KADM5_BAD_TL_TYPE : + case KADM5_MISSING_CONF_PARAMS : + case KADM5_BAD_SERVER_NAME : + default : + return KADM_UNAUTH; /* XXX */ + } +} + +/* + * server functions + */ + +static int +kadm_ser_cpw(krb5_context context, + void *kadm_handle, + krb5_principal principal, + const char *principal_string, + krb5_storage *message, + krb5_storage *reply) +{ + char key[8]; + char *password = NULL; + krb5_error_code ret; + + krb5_warnx(context, "v4-compat %s: cpw %s", + principal_string, principal_string); + + ret = message->fetch(message, key + 4, 4); + ret = message->fetch(message, key, 4); + ret = krb5_ret_stringz(message, &password); + + if(password) { + krb5_data pwd_data; + const char *tmp; + + pwd_data.data = password; + pwd_data.length = strlen(password); + + tmp = kadm5_check_password_quality (context, principal, &pwd_data); + + if (tmp != NULL) { + krb5_store_stringz (reply, (char *)tmp); + ret = KADM5_PASS_Q_DICT; + goto fail; + } + ret = kadm5_chpass_principal(kadm_handle, principal, password); + } else { + krb5_key_data key_data[3]; + int i; + for(i = 0; i < 3; i++) { + key_data[i].key_data_ver = 2; + key_data[i].key_data_kvno = 0; + /* key */ + key_data[i].key_data_type[0] = ETYPE_DES_CBC_CRC; + key_data[i].key_data_length[0] = 8; + key_data[i].key_data_contents[0] = malloc(8); + memcpy(key_data[i].key_data_contents[0], &key, 8); + /* salt */ + key_data[i].key_data_type[1] = KRB5_PW_SALT; + key_data[i].key_data_length[1] = 0; + key_data[i].key_data_contents[1] = NULL; + } + key_data[0].key_data_type[0] = ETYPE_DES_CBC_MD5; + key_data[1].key_data_type[0] = ETYPE_DES_CBC_MD4; + ret = kadm5_s_chpass_principal_with_key(kadm_handle, + principal, 3, key_data); + } + + if(ret != 0) { + krb5_store_stringz(reply, (char*)krb5_get_err_text(context, ret)); + goto fail; + } + return 0; +fail: + krb5_warn(context, ret, "v4-compat cpw"); + return error_code(ret); +} + +static int +kadm_ser_add(krb5_context context, + void *kadm_handle, + krb5_principal principal, + const char *principal_string, + krb5_storage *message, + krb5_storage *reply) +{ + int32_t mask; + kadm5_principal_ent_rec ent, out; + Kadm_vals values; + krb5_error_code ret; + char name[128]; + + ret_vals(message, &values); + + ret = values_to_ent(context, &values, &ent, &mask); + if(ret) + goto fail; + + krb5_unparse_name_fixed(context, ent.principal, name, sizeof(name)); + krb5_warnx(context, "v4-compat %s: add %s", + principal_string, name); + + ret = _kadm5_acl_check_permission (kadm_handle, KADM5_PRIV_ADD); + if (ret) + goto fail; + + ret = kadm5_s_create_principal_with_key(kadm_handle, &ent, mask); + if(ret) { + kadm5_free_principal_ent(kadm_handle, &ent); + goto fail; + } + + mask = KADM5_PRINCIPAL | KADM5_PW_EXPIRATION | KADM5_MAX_LIFE | + KADM5_KEY_DATA | KADM5_MOD_TIME | KADM5_MOD_NAME; + + kadm5_get_principal(kadm_handle, ent.principal, &out, mask); + ent_to_values(context, &out, mask, &values); + kadm5_free_principal_ent(kadm_handle, &ent); + kadm5_free_principal_ent(kadm_handle, &out); + store_vals(reply, &values); + return 0; +fail: + krb5_warn(context, ret, "v4-compat add"); + return error_code(ret); +} + +static int +kadm_ser_get(krb5_context context, + void *kadm_handle, + krb5_principal principal, + const char *principal_string, + krb5_storage *message, + krb5_storage *reply) +{ + krb5_error_code ret; + Kadm_vals values; + kadm5_principal_ent_rec ent, out; + int32_t mask; + char flags[FLDSZ]; + char name[128]; + + ret_vals(message, &values); + /* XXX BRAIN DAMAGE! these flags are not stored in the same order + as in the header */ + krb5_ret_int8(message, &flags[3]); + krb5_ret_int8(message, &flags[2]); + krb5_ret_int8(message, &flags[1]); + krb5_ret_int8(message, &flags[0]); + ret = values_to_ent(context, &values, &ent, &mask); + if(ret) + goto fail; + + krb5_unparse_name_fixed(context, ent.principal, name, sizeof(name)); + krb5_warnx(context, "v4-compat %s: get %s", + principal_string, name); + + ret = _kadm5_acl_check_permission (kadm_handle, KADM5_PRIV_GET); + if (ret) + goto fail; + + mask = flags_4_to_5(flags); + + ret = kadm5_get_principal(kadm_handle, ent.principal, &out, mask); + kadm5_free_principal_ent(kadm_handle, &ent); + + if (ret) + goto fail; + + ent_to_values(context, &out, mask, &values); + + kadm5_free_principal_ent(kadm_handle, &out); + + store_vals(reply, &values); + return 0; +fail: + krb5_warn(context, ret, "v4-compat get"); + return error_code(ret); +} + +static int +kadm_ser_mod(krb5_context context, + void *kadm_handle, + krb5_principal principal, + const char *principal_string, + krb5_storage *message, + krb5_storage *reply) +{ + Kadm_vals values1, values2; + kadm5_principal_ent_rec ent, out; + int32_t mask; + krb5_error_code ret; + char name[128]; + + ret_vals(message, &values1); + /* why are the old values sent? is the mask the same in the old and + the new entry? */ + ret_vals(message, &values2); + + ret = values_to_ent(context, &values2, &ent, &mask); + if(ret) + goto fail; + + krb5_unparse_name_fixed(context, ent.principal, name, sizeof(name)); + krb5_warnx(context, "v4-compat %s: mod %s", + principal_string, name); + + ret = _kadm5_acl_check_permission (kadm_handle, KADM5_PRIV_MODIFY); + if (ret) + goto fail; + + ret = kadm5_s_modify_principal(kadm_handle, &ent, mask); + if(ret) { + kadm5_free_principal_ent(kadm_handle, &ent); + krb5_warn(context, ret, "kadm5_s_modify_principal"); + goto fail; + } + + ret = kadm5_get_principal(kadm_handle, ent.principal, &out, mask); + if(ret) { + kadm5_free_principal_ent(kadm_handle, &ent); + krb5_warn(context, ret, "kadm5_s_modify_principal"); + goto fail; + } + + ent_to_values(context, &out, mask, &values1); + + kadm5_free_principal_ent(kadm_handle, &ent); + kadm5_free_principal_ent(kadm_handle, &out); + + store_vals(reply, &values1); + return 0; +fail: + krb5_warn(context, ret, "v4-compat mod"); + return error_code(ret); +} + +static int +kadm_ser_del(krb5_context context, + void *kadm_handle, + krb5_principal principal, + const char *principal_string, + krb5_storage *message, + krb5_storage *reply) +{ + Kadm_vals values; + kadm5_principal_ent_rec ent; + int32_t mask; + krb5_error_code ret; + char name[128]; + + ret_vals(message, &values); + + ret = values_to_ent(context, &values, &ent, &mask); + if(ret) + goto fail; + + krb5_unparse_name_fixed(context, ent.principal, name, sizeof(name)); + krb5_warnx(context, "v4-compat %s: del %s", + principal_string, name); + + ret = _kadm5_acl_check_permission (kadm_handle, KADM5_PRIV_DELETE); + if (ret) + goto fail; + + ret = kadm5_delete_principal(kadm_handle, ent.principal); + + kadm5_free_principal_ent(kadm_handle, &ent); + + if (ret) + goto fail; + + return 0; +fail: + krb5_warn(context, ret, "v4-compat add"); + return error_code(ret); +} + +static int +dispatch(krb5_context context, + void *kadm_handle, + krb5_principal principal, + const char *principal_string, + krb5_data msg, + krb5_data *reply) +{ + int retval; + int8_t command; + krb5_storage *sp_in, *sp_out; + + sp_in = krb5_storage_from_data(&msg); + krb5_ret_int8(sp_in, &command); + + sp_out = krb5_storage_emem(); + sp_out->store(sp_out, KADM_VERSTR, KADM_VERSIZE); + krb5_store_int32(sp_out, 0); + + switch(command) { + case CHANGE_PW: + retval = kadm_ser_cpw(context, kadm_handle, principal, + principal_string, + sp_in, sp_out); + break; + case ADD_ENT: + retval = kadm_ser_add(context, kadm_handle, principal, + principal_string, + sp_in, sp_out); + break; + case GET_ENT: + retval = kadm_ser_get(context, kadm_handle, principal, + principal_string, + sp_in, sp_out); + break; + case MOD_ENT: + retval = kadm_ser_mod(context, kadm_handle, principal, + principal_string, + sp_in, sp_out); + break; + case DEL_ENT: + retval = kadm_ser_del(context, kadm_handle, principal, + principal_string, + sp_in, sp_out); + break; + default: + krb5_warnx(context, "v4-compat %s: unknown opcode: %d", + principal_string, command); + retval = KADM_NO_OPCODE; + break; + } + krb5_storage_free(sp_in); + if(retval) { + sp_out->seek(sp_out, KADM_VERSIZE, SEEK_SET); + krb5_store_int32(sp_out, retval); + } + krb5_storage_to_data(sp_out, reply); + krb5_storage_free(sp_out); + return retval; +} + +/* + * Decode a v4 kadmin packet in `message' and create a reply in `reply' + */ + +static void +decode_packet(krb5_context context, + struct sockaddr_in *admin_addr, + struct sockaddr_in *client_addr, + krb5_data message, + krb5_data *reply) +{ + int ret; + KTEXT_ST authent; + AUTH_DAT ad; + MSG_DAT msg_dat; + off_t off = 0; + unsigned long rlen; + char sname[] = "changepw", sinst[] = "kerberos"; + unsigned long checksum; + des_key_schedule schedule; + char *msg = message.data; + void *kadm_handle; + krb5_principal client; + char *client_str; + + if(message.length < KADM_VERSIZE + || strncmp(msg, KADM_VERSTR, KADM_VERSIZE) != 0) { + make_you_loose_packet (KADM_BAD_VER, reply); + return; + } + + off = KADM_VERSIZE; + off += _krb5_get_int(msg + off, &rlen, 4); + memset(&authent, 0, sizeof(authent)); + authent.length = message.length - rlen - KADM_VERSIZE - 4; + memcpy(authent.dat, (char*)msg + off, authent.length); + off += authent.length; + + { + krb5_principal principal; + krb5_keyblock *key; + + ret = krb5_make_principal(context, &principal, NULL, + "changepw", "kerberos", NULL); + if (ret) { + krb5_warn (context, ret, "krb5_make_principal"); + make_you_loose_packet (KADM_NOMEM, reply); + return; + } + ret = krb5_kt_read_service_key(context, + "HDB:", + principal, + 0, +/* ETYPE_DES_CBC_CRC,*/ + ETYPE_DES_CBC_MD5, + &key); + krb5_free_principal(context, principal); + if(ret) { + if(ret == KRB5_KT_NOTFOUND) + make_you_loose_packet(KADM_NO_AUTH, reply); + else + /* XXX */ + make_you_loose_packet(KADM_NO_AUTH, reply); + krb5_warn(context, ret, "krb5_kt_read_service_key"); + return; + } + + if(key->keyvalue.length != 8) + krb5_abortx(context, "key has wrong length (%lu)", + (unsigned long)key->keyvalue.length); + krb_set_key(key->keyvalue.data, 0); + krb5_free_keyblock(context, key); + } + + ret = krb_rd_req(&authent, sname, sinst, + client_addr->sin_addr.s_addr, &ad, NULL); + + if(ret) { + make_you_loose_packet(krb_err_base + ret, reply); + krb5_warnx(context, "krb_rd_req: %d", ret); + return; + } + + krb5_425_conv_principal(context, ad.pname, ad.pinst, ad.prealm, + &client); + krb5_unparse_name(context, client, &client_str); + + ret = kadm5_init_with_password_ctx(context, + client_str, + NULL, + KADM5_ADMIN_SERVICE, + NULL, 0, 0, + &kadm_handle); + if (ret) { + krb5_warn (context, ret, "kadm5_init_with_password_ctx"); + make_you_loose_packet (KADM_NOMEM, reply); + goto out; + } + + checksum = des_quad_cksum((des_cblock*)(msg + off), NULL, rlen, + 0, &ad.session); + if(checksum != ad.checksum) { + krb5_warnx(context, "decode_packet: bad checksum"); + make_you_loose_packet (KADM_BAD_CHK, reply); + goto out; + } + des_set_key(&ad.session, schedule); + ret = krb_rd_priv(msg + off, rlen, schedule, &ad.session, + client_addr, admin_addr, &msg_dat); + if (ret) { + make_you_loose_packet (krb_err_base + ret, reply); + krb5_warnx(context, "krb_rd_priv: %d", ret); + goto out; + } + + { + krb5_data d, r; + int retval; + + d.data = msg_dat.app_data; + d.length = msg_dat.app_length; + + retval = dispatch(context, kadm_handle, + client, client_str, d, &r); + krb5_data_alloc(reply, r.length + 26); + reply->length = krb_mk_priv(r.data, reply->data, r.length, + schedule, &ad.session, + admin_addr, client_addr); + if((ssize_t)reply->length < 0) { + make_you_loose_packet(KADM_NO_ENCRYPT, reply); + goto out; + } + } +out: + krb5_free_principal(context, client); + free(client_str); +} + +void +handle_v4(krb5_context context, + int len, + int fd) +{ + int first = 1; + struct sockaddr_in admin_addr, client_addr; + int addr_len; + krb5_data message, reply; + ssize_t n; + + addr_len = sizeof(client_addr); + if (getsockname(fd, (struct sockaddr*)&admin_addr, &addr_len) < 0) + krb5_errx (context, 1, "getsockname"); + addr_len = sizeof(client_addr); + if (getpeername(fd, (struct sockaddr*)&client_addr, &addr_len) < 0) + krb5_errx (context, 1, "getpeername"); + + while(1) { + if(first) { + /* first time around, we have already read len, and two + bytes of the version string */ + krb5_data_alloc(&message, len); + memcpy(message.data, "KA", 2); + n = krb5_net_read(context, &fd, (char*)message.data + 2, + len - 2); + if (n == 0) + exit (0); + if (n < 0) + krb5_err (context, 1, errno, "krb5_net_read"); + first = 0; + } else { + char buf[2]; + unsigned long tmp; + ssize_t n; + + n = krb5_net_read(context, &fd, buf, sizeof(2)); + if (n == 0) + exit (0); + if (n < 0) + krb5_err (context, 1, errno, "krb5_net_read"); + _krb5_get_int(buf, &tmp, 2); + krb5_data_alloc(&message, tmp); + n = krb5_net_read(context, &fd, message.data, message.length); + if (n == 0) + krb5_errx (context, 1, "EOF in krb5_net_read"); + if (n < 0) + krb5_err (context, 1, errno, "krb5_net_read"); + } + decode_packet(context, &admin_addr, &client_addr, + message, &reply); + krb5_data_free(&message); + { + char buf[2]; + + _krb5_put_int(buf, reply.length, sizeof(buf)); + n = krb5_net_write(context, &fd, buf, sizeof(buf)); + if (n < 0) + krb5_err (context, 1, errno, "krb5_net_write"); + n = krb5_net_write(context, &fd, reply.data, reply.length); + if (n < 0) + krb5_err (context, 1, errno, "krb5_net_write"); + krb5_data_free(&reply); + } + } +} |