aboutsummaryrefslogtreecommitdiffstats
path: root/kdc
diff options
context:
space:
mode:
Diffstat (limited to 'kdc')
-rw-r--r--kdc/Makefile.am49
-rw-r--r--kdc/Makefile.in690
-rw-r--r--kdc/NTMakefile35
-rw-r--r--kdc/config.c70
-rw-r--r--kdc/connect.c476
-rw-r--r--kdc/default_config.c12
-rw-r--r--kdc/digest-service.c4
-rw-r--r--kdc/digest.c71
-rw-r--r--kdc/fast.c560
-rw-r--r--kdc/headers.h5
-rw-r--r--kdc/hprop.c3
-rw-r--r--kdc/hprop.h2
-rw-r--r--kdc/hpropd.c78
-rw-r--r--kdc/kdc-private.h73
-rw-r--r--kdc/kdc-protos.h8
-rw-r--r--kdc/kdc-replay.c6
-rw-r--r--kdc/kdc-tester.c508
-rw-r--r--kdc/kdc.813
-rw-r--r--kdc/kdc.cat820
-rw-r--r--kdc/kdc.h3
-rw-r--r--kdc/kdc_locl.h58
-rw-r--r--kdc/kerberos5.c1810
-rw-r--r--kdc/krb5tgs.c411
-rw-r--r--kdc/kstash.c29
-rw-r--r--kdc/kx509.c171
-rw-r--r--kdc/log.c2
-rw-r--r--kdc/main.c42
-rw-r--r--kdc/misc.c139
-rw-r--r--kdc/mit_dump.c402
-rw-r--r--kdc/pkinit-ec.c318
-rw-r--r--kdc/pkinit.c304
-rw-r--r--kdc/process.c21
-rw-r--r--kdc/string2key.c15
-rw-r--r--kdc/windc.c171
-rw-r--r--kdc/windc_plugin.h6
35 files changed, 4620 insertions, 1965 deletions
diff --git a/kdc/Makefile.am b/kdc/Makefile.am
index 5ef3cbec5d98..842b5a888227 100644
--- a/kdc/Makefile.am
+++ b/kdc/Makefile.am
@@ -2,7 +2,7 @@
include $(top_srcdir)/Makefile.am.common
-AM_CPPFLAGS += $(INCLUDE_libintl) $(INCLUDE_krb4) $(INCLUDE_hcrypto) -I$(srcdir)/../lib/krb5
+AM_CPPFLAGS += $(INCLUDE_libintl) $(INCLUDE_openssl_crypto) -I$(srcdir)/../lib/krb5
lib_LTLIBRARIES = libkdc.la
@@ -12,7 +12,7 @@ sbin_PROGRAMS = kstash
libexec_PROGRAMS = hprop hpropd kdc digest-service
-noinst_PROGRAMS = kdc-replay
+noinst_PROGRAMS = kdc-replay kdc-tester
man_MANS = kdc.8 kstash.8 hprop.8 hpropd.8 string2key.8
@@ -31,16 +31,20 @@ kdc_SOURCES = connect.c \
announce.c \
main.c
+kdc_tester_SOURCES = \
+ config.c \
+ kdc-tester.c
+
libkdc_la_SOURCES = \
- kdc-private.h \
- kdc-protos.h \
default_config.c \
set_dbinfo.c \
digest.c \
+ fast.c \
kdc_locl.h \
kerberos5.c \
krb5tgs.c \
pkinit.c \
+ pkinit-ec.c \
log.c \
misc.c \
kx509.c \
@@ -48,8 +52,19 @@ libkdc_la_SOURCES = \
windc.c \
rx.h
+KDC_PROTOS = $(srcdir)/kdc-protos.h $(srcdir)/kdc-private.h
+
+ALL_OBJECTS = $(kdc_OBJECTS)
+ALL_OBJECTS += $(kdc_replay_OBJECTS)
+ALL_OBJECTS += $(kdc_tester_OBJECTS)
+ALL_OBJECTS += $(libkdc_la_OBJECTS)
+ALL_OBJECTS += $(string2key_OBJECTS)
+ALL_OBJECTS += $(kstash_OBJECTS)
+ALL_OBJECTS += $(hprop_OBJECTS)
+ALL_OBJECTS += $(hpropd_OBJECTS)
+ALL_OBJECTS += $(digest_service_OBJECTS)
-$(libkdc_la_OBJECTS): $(srcdir)/kdc-protos.h $(srcdir)/kdc-private.h
+$(ALL_OBJECTS): $(KDC_PROTOS)
libkdc_la_LDFLAGS = -version-info 2:0:0
@@ -58,30 +73,30 @@ libkdc_la_LDFLAGS += $(LDFLAGS_VERSION_SCRIPT)$(srcdir)/version-script.map
endif
$(libkdc_la_OBJECTS): $(srcdir)/version-script.map
-$(srcdir)/kdc-protos.h:
+$(srcdir)/kdc-protos.h: $(libkdc_la_SOURCES)
cd $(srcdir) && perl ../cf/make-proto.pl -q -P comment -o kdc-protos.h $(libkdc_la_SOURCES) || rm -f kdc-protos.h
-$(srcdir)/kdc-private.h:
+$(srcdir)/kdc-private.h: $(libkdc_la_SOURCES)
cd $(srcdir) && perl ../cf/make-proto.pl -q -P comment -p kdc-private.h $(libkdc_la_SOURCES) || rm -f kdc-private.h
hprop_LDADD = \
$(top_builddir)/lib/hdb/libhdb.la \
$(top_builddir)/lib/krb5/libkrb5.la \
- $(LIB_kdb) $(LIB_krb4) \
+ $(LIB_kdb) \
$(LIB_hcrypto) \
$(top_builddir)/lib/asn1/libasn1.la \
$(LIB_roken) \
- $(DBLIB)
+ $(DB3LIB) $(DB1LIB) $(LMDBLIB) $(NDBMLIB)
hpropd_LDADD = \
$(top_builddir)/lib/hdb/libhdb.la \
$(top_builddir)/lib/krb5/libkrb5.la \
- $(LIB_kdb) $(LIB_krb4) \
+ $(LIB_kdb) \
$(LIB_hcrypto) \
$(top_builddir)/lib/asn1/libasn1.la \
$(LIB_roken) \
- $(DBLIB)
+ $(DB3LIB) $(DB1LIB) $(LMDBLIB) $(NDBMLIB)
if PKINIT
LIB_pkinit = $(top_builddir)/lib/hx509/libhx509.la
@@ -91,20 +106,20 @@ libkdc_la_LIBADD = \
$(LIB_pkinit) \
$(top_builddir)/lib/hdb/libhdb.la \
$(top_builddir)/lib/krb5/libkrb5.la \
- $(LIB_kdb) $(LIB_krb4) \
+ $(LIB_kdb) \
$(top_builddir)/lib/ntlm/libheimntlm.la \
$(LIB_hcrypto) \
+ $(LIB_openssl_crypto) \
$(top_builddir)/lib/asn1/libasn1.la \
$(LIB_roken) \
- $(DBLIB)
+ $(DB3LIB) $(DB1LIB) $(LMDBLIB) $(NDBMLIB)
LDADD = $(top_builddir)/lib/hdb/libhdb.la \
$(top_builddir)/lib/krb5/libkrb5.la \
- $(LIB_krb4) \
$(LIB_hcrypto) \
$(top_builddir)/lib/asn1/libasn1.la \
$(LIB_roken) \
- $(DBLIB)
+ $(DB3LIB) $(DB1LIB) $(LMDBLIB) $(NDBMLIB)
kdc_LDADD = libkdc.la $(LDADD) $(LIB_pidfile) $(CAPNG_LIBS)
@@ -119,9 +134,11 @@ digest_service_LDADD = \
$(top_builddir)/lib/ipc/libheim-ipcs.la \
$(LDADD) $(LIB_pidfile)
kdc_replay_LDADD = libkdc.la $(LDADD) $(LIB_pidfile)
+kdc_tester_LDADD = libkdc.la $(LDADD) $(LIB_pidfile) $(LIB_heimbase)
-include_HEADERS = kdc.h kdc-protos.h
+include_HEADERS = kdc.h $(srcdir)/kdc-protos.h
+noinst_HEADERS = $(srcdir)/kdc-private.h
krb5dir = $(includedir)/krb5
krb5_HEADERS = windc_plugin.h
diff --git a/kdc/Makefile.in b/kdc/Makefile.in
index 57259cf151dd..92359c5de10b 100644
--- a/kdc/Makefile.in
+++ b/kdc/Makefile.in
@@ -1,9 +1,8 @@
-# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# Makefile.in generated by automake 1.15.1 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
-# Inc.
+# Copyright (C) 1994-2017 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.
@@ -24,6 +23,61 @@
VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
@@ -42,14 +96,11 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
-DIST_COMMON = $(include_HEADERS) $(krb5_HEADERS) $(srcdir)/Makefile.am \
- $(srcdir)/Makefile.in $(top_srcdir)/Makefile.am.common \
- $(top_srcdir)/cf/Makefile.am.common
bin_PROGRAMS = string2key$(EXEEXT)
sbin_PROGRAMS = kstash$(EXEEXT)
libexec_PROGRAMS = hprop$(EXEEXT) hpropd$(EXEEXT) kdc$(EXEEXT) \
digest-service$(EXEEXT)
-noinst_PROGRAMS = kdc-replay$(EXEEXT)
+noinst_PROGRAMS = kdc-replay$(EXEEXT) kdc-tester$(EXEEXT)
@versionscript_TRUE@am__append_1 = $(LDFLAGS_VERSION_SCRIPT)$(srcdir)/version-script.map
subdir = kdc
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -66,8 +117,7 @@ am__aclocal_m4_deps = $(top_srcdir)/cf/aix.m4 \
$(top_srcdir)/cf/check-man.m4 \
$(top_srcdir)/cf/check-netinet-ip-and-tcp.m4 \
$(top_srcdir)/cf/check-type-extra.m4 \
- $(top_srcdir)/cf/check-var.m4 $(top_srcdir)/cf/check-x.m4 \
- $(top_srcdir)/cf/check-xau.m4 $(top_srcdir)/cf/crypto.m4 \
+ $(top_srcdir)/cf/check-var.m4 $(top_srcdir)/cf/crypto.m4 \
$(top_srcdir)/cf/db.m4 $(top_srcdir)/cf/destdirs.m4 \
$(top_srcdir)/cf/dispatch.m4 $(top_srcdir)/cf/dlopen.m4 \
$(top_srcdir)/cf/find-func-no-libs.m4 \
@@ -80,6 +130,7 @@ am__aclocal_m4_deps = $(top_srcdir)/cf/aix.m4 \
$(top_srcdir)/cf/krb-bigendian.m4 \
$(top_srcdir)/cf/krb-func-getlogin.m4 \
$(top_srcdir)/cf/krb-ipv6.m4 $(top_srcdir)/cf/krb-prog-ln-s.m4 \
+ $(top_srcdir)/cf/krb-prog-perl.m4 \
$(top_srcdir)/cf/krb-readline.m4 \
$(top_srcdir)/cf/krb-struct-spwd.m4 \
$(top_srcdir)/cf/krb-struct-winsize.m4 \
@@ -99,6 +150,8 @@ am__aclocal_m4_deps = $(top_srcdir)/cf/aix.m4 \
$(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(include_HEADERS) $(krb5_HEADERS) \
+ $(noinst_HEADERS) $(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/include/config.h
CONFIG_CLEAN_FILES =
@@ -124,6 +177,12 @@ am__nobase_list = $(am__nobase_strip_setup); \
am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \
"$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(sbindir)" \
"$(DESTDIR)$(man8dir)" "$(DESTDIR)$(includedir)" \
@@ -133,14 +192,20 @@ am__DEPENDENCIES_1 =
libkdc_la_DEPENDENCIES = $(LIB_pkinit) \
$(top_builddir)/lib/hdb/libhdb.la \
$(top_builddir)/lib/krb5/libkrb5.la $(am__DEPENDENCIES_1) \
- $(am__DEPENDENCIES_1) $(top_builddir)/lib/ntlm/libheimntlm.la \
+ $(top_builddir)/lib/ntlm/libheimntlm.la $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(top_builddir)/lib/asn1/libasn1.la \
- $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
am_libkdc_la_OBJECTS = default_config.lo set_dbinfo.lo digest.lo \
- kerberos5.lo krb5tgs.lo pkinit.lo log.lo misc.lo kx509.lo \
- process.lo windc.lo
+ fast.lo kerberos5.lo krb5tgs.lo pkinit.lo pkinit-ec.lo log.lo \
+ misc.lo kx509.lo process.lo windc.lo
libkdc_la_OBJECTS = $(am_libkdc_la_OBJECTS)
-libkdc_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+libkdc_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libkdc_la_LDFLAGS) $(LDFLAGS) -o $@
PROGRAMS = $(bin_PROGRAMS) $(libexec_PROGRAMS) $(noinst_PROGRAMS) \
@@ -149,7 +214,8 @@ am_digest_service_OBJECTS = digest-service.$(OBJEXT)
digest_service_OBJECTS = $(am_digest_service_OBJECTS)
am__DEPENDENCIES_2 = $(top_builddir)/lib/hdb/libhdb.la \
$(top_builddir)/lib/krb5/libkrb5.la $(am__DEPENDENCIES_1) \
- $(am__DEPENDENCIES_1) $(top_builddir)/lib/asn1/libasn1.la \
+ $(top_builddir)/lib/asn1/libasn1.la $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
digest_service_DEPENDENCIES = libkdc.la \
$(top_builddir)/lib/ntlm/libheimntlm.la \
@@ -159,70 +225,126 @@ am_hprop_OBJECTS = hprop.$(OBJEXT) mit_dump.$(OBJEXT)
hprop_OBJECTS = $(am_hprop_OBJECTS)
hprop_DEPENDENCIES = $(top_builddir)/lib/hdb/libhdb.la \
$(top_builddir)/lib/krb5/libkrb5.la $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(top_builddir)/lib/asn1/libasn1.la \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
- $(top_builddir)/lib/asn1/libasn1.la $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1)
am_hpropd_OBJECTS = hpropd.$(OBJEXT)
hpropd_OBJECTS = $(am_hpropd_OBJECTS)
hpropd_DEPENDENCIES = $(top_builddir)/lib/hdb/libhdb.la \
$(top_builddir)/lib/krb5/libkrb5.la $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(top_builddir)/lib/asn1/libasn1.la \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
- $(top_builddir)/lib/asn1/libasn1.la $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1)
am_kdc_OBJECTS = kdc-connect.$(OBJEXT) kdc-config.$(OBJEXT) \
kdc-announce.$(OBJEXT) kdc-main.$(OBJEXT)
kdc_OBJECTS = $(am_kdc_OBJECTS)
kdc_DEPENDENCIES = libkdc.la $(am__DEPENDENCIES_2) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
-kdc_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
- --mode=link $(CCLD) $(kdc_CFLAGS) $(CFLAGS) $(kdc_LDFLAGS) \
- $(LDFLAGS) -o $@
+kdc_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(kdc_CFLAGS) $(CFLAGS) \
+ $(kdc_LDFLAGS) $(LDFLAGS) -o $@
kdc_replay_SOURCES = kdc-replay.c
kdc_replay_OBJECTS = kdc-replay.$(OBJEXT)
kdc_replay_DEPENDENCIES = libkdc.la $(am__DEPENDENCIES_2) \
$(am__DEPENDENCIES_1)
+am_kdc_tester_OBJECTS = config.$(OBJEXT) kdc-tester.$(OBJEXT)
+kdc_tester_OBJECTS = $(am_kdc_tester_OBJECTS)
+kdc_tester_DEPENDENCIES = libkdc.la $(am__DEPENDENCIES_2) \
+ $(am__DEPENDENCIES_1) $(LIB_heimbase)
am_kstash_OBJECTS = kstash.$(OBJEXT)
kstash_OBJECTS = $(am_kstash_OBJECTS)
kstash_LDADD = $(LDADD)
kstash_DEPENDENCIES = $(top_builddir)/lib/hdb/libhdb.la \
$(top_builddir)/lib/krb5/libkrb5.la $(am__DEPENDENCIES_1) \
- $(am__DEPENDENCIES_1) $(top_builddir)/lib/asn1/libasn1.la \
+ $(top_builddir)/lib/asn1/libasn1.la $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
am_string2key_OBJECTS = string2key.$(OBJEXT)
string2key_OBJECTS = $(am_string2key_OBJECTS)
string2key_LDADD = $(LDADD)
string2key_DEPENDENCIES = $(top_builddir)/lib/hdb/libhdb.la \
$(top_builddir)/lib/krb5/libkrb5.la $(am__DEPENDENCIES_1) \
- $(am__DEPENDENCIES_1) $(top_builddir)/lib/asn1/libasn1.la \
+ $(top_builddir)/lib/asn1/libasn1.la $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
- --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
- $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
CCLD = $(CC)
-LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
- --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
- $(LDFLAGS) -o $@
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
SOURCES = $(libkdc_la_SOURCES) $(digest_service_SOURCES) \
$(hprop_SOURCES) $(hpropd_SOURCES) $(kdc_SOURCES) kdc-replay.c \
- $(kstash_SOURCES) $(string2key_SOURCES)
+ $(kdc_tester_SOURCES) $(kstash_SOURCES) $(string2key_SOURCES)
DIST_SOURCES = $(libkdc_la_SOURCES) $(digest_service_SOURCES) \
$(hprop_SOURCES) $(hpropd_SOURCES) $(kdc_SOURCES) kdc-replay.c \
- $(kstash_SOURCES) $(string2key_SOURCES)
+ $(kdc_tester_SOURCES) $(kstash_SOURCES) $(string2key_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
man8dir = $(mandir)/man8
MANS = $(man_MANS)
-HEADERS = $(include_HEADERS) $(krb5_HEADERS)
+HEADERS = $(include_HEADERS) $(krb5_HEADERS) $(noinst_HEADERS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
+am__DIST_COMMON = $(srcdir)/Makefile.in \
+ $(top_srcdir)/Makefile.am.common \
+ $(top_srcdir)/cf/Makefile.am.common $(top_srcdir)/depcomp
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AIX_EXTRA_KAFS = @AIX_EXTRA_KAFS@
AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AR = @AR@
+AS = @AS@
ASN1_COMPILE = @ASN1_COMPILE@
ASN1_COMPILE_DEP = @ASN1_COMPILE_DEP@
AUTOCONF = @AUTOCONF@
@@ -241,12 +363,12 @@ COMPILE_ET = @COMPILE_ET@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
+DB1LIB = @DB1LIB@
+DB3LIB = @DB3LIB@
DBHEADER = @DBHEADER@
-DBLIB = @DBLIB@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DIR_com_err = @DIR_com_err@
-DIR_hcrypto = @DIR_hcrypto@
DIR_hdbdir = @DIR_hdbdir@
DIR_roken = @DIR_roken@
DLLTOOL = @DLLTOOL@
@@ -256,17 +378,17 @@ ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
+ENABLE_AFS_STRING_TO_KEY = @ENABLE_AFS_STRING_TO_KEY@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+GCD_MIG = @GCD_MIG@
GREP = @GREP@
GROFF = @GROFF@
INCLUDES_roken = @INCLUDES_roken@
-INCLUDE_hcrypto = @INCLUDE_hcrypto@
-INCLUDE_hesiod = @INCLUDE_hesiod@
-INCLUDE_krb4 = @INCLUDE_krb4@
INCLUDE_libedit = @INCLUDE_libedit@
INCLUDE_libintl = @INCLUDE_libintl@
INCLUDE_openldap = @INCLUDE_openldap@
+INCLUDE_openssl_crypto = @INCLUDE_openssl_crypto@
INCLUDE_readline = @INCLUDE_readline@
INCLUDE_sqlite3 = @INCLUDE_sqlite3@
INSTALL = @INSTALL@
@@ -285,12 +407,9 @@ LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIB_AUTH_SUBDIRS = @LIB_AUTH_SUBDIRS@
-LIB_NDBM = @LIB_NDBM@
-LIB_XauFileName = @LIB_XauFileName@
-LIB_XauReadAuth = @LIB_XauReadAuth@
-LIB_XauWriteAuth = @LIB_XauWriteAuth@
LIB_bswap16 = @LIB_bswap16@
LIB_bswap32 = @LIB_bswap32@
+LIB_bswap64 = @LIB_bswap64@
LIB_com_err = @LIB_com_err@
LIB_com_err_a = @LIB_com_err_a@
LIB_com_err_so = @LIB_com_err_so@
@@ -299,6 +418,7 @@ LIB_db_create = @LIB_db_create@
LIB_dbm_firstkey = @LIB_dbm_firstkey@
LIB_dbopen = @LIB_dbopen@
LIB_dispatch_async_f = @LIB_dispatch_async_f@
+LIB_dladdr = @LIB_dladdr@
LIB_dlopen = @LIB_dlopen@
LIB_dn_expand = @LIB_dn_expand@
LIB_dns_search = @LIB_dns_search@
@@ -315,10 +435,8 @@ LIB_hcrypto = @LIB_hcrypto@
LIB_hcrypto_a = @LIB_hcrypto_a@
LIB_hcrypto_appl = @LIB_hcrypto_appl@
LIB_hcrypto_so = @LIB_hcrypto_so@
-LIB_hesiod = @LIB_hesiod@
LIB_hstrerror = @LIB_hstrerror@
LIB_kdb = @LIB_kdb@
-LIB_krb4 = @LIB_krb4@
LIB_libedit = @LIB_libedit@
LIB_libintl = @LIB_libintl@
LIB_loadquery = @LIB_loadquery@
@@ -326,6 +444,7 @@ LIB_logout = @LIB_logout@
LIB_logwtmp = @LIB_logwtmp@
LIB_openldap = @LIB_openldap@
LIB_openpty = @LIB_openpty@
+LIB_openssl_crypto = @LIB_openssl_crypto@
LIB_otp = @LIB_otp@
LIB_pidfile = @LIB_pidfile@
LIB_readline = @LIB_readline@
@@ -340,12 +459,15 @@ LIB_sqlite3 = @LIB_sqlite3@
LIB_syslog = @LIB_syslog@
LIB_tgetent = @LIB_tgetent@
LIPO = @LIPO@
+LMDBLIB = @LMDBLIB@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
+NDBMLIB = @NDBMLIB@
NM = @NM@
NMEDIT = @NMEDIT@
NO_AFS = @NO_AFS@
@@ -362,6 +484,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
PTHREAD_LDADD = @PTHREAD_LDADD@
@@ -376,13 +499,7 @@ STRIP = @STRIP@
VERSION = @VERSION@
VERSIONING = @VERSIONING@
WFLAGS = @WFLAGS@
-WFLAGS_NOIMPLICITINT = @WFLAGS_NOIMPLICITINT@
-WFLAGS_NOUNUSED = @WFLAGS_NOUNUSED@
-XMKMF = @XMKMF@
-X_CFLAGS = @X_CFLAGS@
-X_EXTRA_LIBS = @X_EXTRA_LIBS@
-X_LIBS = @X_LIBS@
-X_PRE_LIBS = @X_PRE_LIBS@
+WFLAGS_LITE = @WFLAGS_LITE@
YACC = @YACC@
YFLAGS = @YFLAGS@
abs_builddir = @abs_builddir@
@@ -406,6 +523,8 @@ build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
+db_type = @db_type@
+db_type_preference = @db_type_preference@
docdir = @docdir@
dpagaix_cflags = @dpagaix_cflags@
dpagaix_ldadd = @dpagaix_ldadd@
@@ -441,30 +560,38 @@ target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
-SUFFIXES = .et .h .x .z .hx .1 .3 .5 .8 .cat1 .cat3 .cat5 .cat8
+SUFFIXES = .et .h .pc.in .pc .x .z .hx .1 .3 .5 .7 .8 .cat1 .cat3 \
+ .cat5 .cat7 .cat8
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/include -I$(top_srcdir)/include
-AM_CPPFLAGS = $(INCLUDES_roken) $(INCLUDE_libintl) $(INCLUDE_krb4) \
- $(INCLUDE_hcrypto) -I$(srcdir)/../lib/krb5
+AM_CPPFLAGS = $(INCLUDES_roken) $(INCLUDE_libintl) \
+ $(INCLUDE_openssl_crypto) -I$(srcdir)/../lib/krb5
@do_roken_rename_TRUE@ROKEN_RENAME = -DROKEN_RENAME
AM_CFLAGS = $(WFLAGS)
CP = cp
buildinclude = $(top_builddir)/include
+LIB_XauReadAuth = @LIB_XauReadAuth@
LIB_el_init = @LIB_el_init@
LIB_getattr = @LIB_getattr@
LIB_getpwent_r = @LIB_getpwent_r@
LIB_odm_initialize = @LIB_odm_initialize@
LIB_setpcred = @LIB_setpcred@
-HESIODLIB = @HESIODLIB@
-HESIODINCLUDE = @HESIODINCLUDE@
+INCLUDE_krb4 = @INCLUDE_krb4@
+LIB_krb4 = @LIB_krb4@
libexec_heimdaldir = $(libexecdir)/heimdal
NROFF_MAN = groff -mandoc -Tascii
-LIB_kafs = $(top_builddir)/lib/kafs/libkafs.la $(AIX_EXTRA_KAFS)
+@NO_AFS_FALSE@LIB_kafs = $(top_builddir)/lib/kafs/libkafs.la $(AIX_EXTRA_KAFS)
+@NO_AFS_TRUE@LIB_kafs =
@KRB5_TRUE@LIB_krb5 = $(top_builddir)/lib/krb5/libkrb5.la \
@KRB5_TRUE@ $(top_builddir)/lib/asn1/libasn1.la
@KRB5_TRUE@LIB_gssapi = $(top_builddir)/lib/gssapi/libgssapi.la
-LIB_heimbase = $(top_builddir)/base/libheimbase.la
+LIB_heimbase = $(top_builddir)/lib/base/libheimbase.la
@DCE_TRUE@LIB_kdfs = $(top_builddir)/lib/kdfs/libkdfs.la
+
+#silent-rules
+heim_verbose = $(heim_verbose_$(V))
+heim_verbose_ = $(heim_verbose_$(AM_DEFAULT_VERBOSITY))
+heim_verbose_0 = @echo " GEN "$@;
lib_LTLIBRARIES = libkdc.la
man_MANS = kdc.8 kstash.8 hprop.8 hpropd.8 string2key.8
hprop_SOURCES = hprop.c mit_dump.c hprop.h
@@ -479,16 +606,20 @@ kdc_SOURCES = connect.c \
announce.c \
main.c
+kdc_tester_SOURCES = \
+ config.c \
+ kdc-tester.c
+
libkdc_la_SOURCES = \
- kdc-private.h \
- kdc-protos.h \
default_config.c \
set_dbinfo.c \
digest.c \
+ fast.c \
kdc_locl.h \
kerberos5.c \
krb5tgs.c \
pkinit.c \
+ pkinit-ec.c \
log.c \
misc.c \
kx509.c \
@@ -496,44 +627,49 @@ libkdc_la_SOURCES = \
windc.c \
rx.h
+KDC_PROTOS = $(srcdir)/kdc-protos.h $(srcdir)/kdc-private.h
+ALL_OBJECTS = $(kdc_OBJECTS) $(kdc_replay_OBJECTS) \
+ $(kdc_tester_OBJECTS) $(libkdc_la_OBJECTS) \
+ $(string2key_OBJECTS) $(kstash_OBJECTS) $(hprop_OBJECTS) \
+ $(hpropd_OBJECTS) $(digest_service_OBJECTS)
libkdc_la_LDFLAGS = -version-info 2:0:0 $(am__append_1)
hprop_LDADD = \
$(top_builddir)/lib/hdb/libhdb.la \
$(top_builddir)/lib/krb5/libkrb5.la \
- $(LIB_kdb) $(LIB_krb4) \
+ $(LIB_kdb) \
$(LIB_hcrypto) \
$(top_builddir)/lib/asn1/libasn1.la \
$(LIB_roken) \
- $(DBLIB)
+ $(DB3LIB) $(DB1LIB) $(LMDBLIB) $(NDBMLIB)
hpropd_LDADD = \
$(top_builddir)/lib/hdb/libhdb.la \
$(top_builddir)/lib/krb5/libkrb5.la \
- $(LIB_kdb) $(LIB_krb4) \
+ $(LIB_kdb) \
$(LIB_hcrypto) \
$(top_builddir)/lib/asn1/libasn1.la \
$(LIB_roken) \
- $(DBLIB)
+ $(DB3LIB) $(DB1LIB) $(LMDBLIB) $(NDBMLIB)
@PKINIT_TRUE@LIB_pkinit = $(top_builddir)/lib/hx509/libhx509.la
libkdc_la_LIBADD = \
$(LIB_pkinit) \
$(top_builddir)/lib/hdb/libhdb.la \
$(top_builddir)/lib/krb5/libkrb5.la \
- $(LIB_kdb) $(LIB_krb4) \
+ $(LIB_kdb) \
$(top_builddir)/lib/ntlm/libheimntlm.la \
$(LIB_hcrypto) \
+ $(LIB_openssl_crypto) \
$(top_builddir)/lib/asn1/libasn1.la \
$(LIB_roken) \
- $(DBLIB)
+ $(DB3LIB) $(DB1LIB) $(LMDBLIB) $(NDBMLIB)
LDADD = $(top_builddir)/lib/hdb/libhdb.la \
$(top_builddir)/lib/krb5/libkrb5.la \
- $(LIB_krb4) \
$(LIB_hcrypto) \
$(top_builddir)/lib/asn1/libasn1.la \
$(LIB_roken) \
- $(DBLIB)
+ $(DB3LIB) $(DB1LIB) $(LMDBLIB) $(NDBMLIB)
kdc_LDADD = libkdc.la $(LDADD) $(LIB_pidfile) $(CAPNG_LIBS)
@FRAMEWORK_SECURITY_TRUE@kdc_LDFLAGS = -framework SystemConfiguration -framework CoreFoundation
@@ -545,7 +681,9 @@ digest_service_LDADD = \
$(LDADD) $(LIB_pidfile)
kdc_replay_LDADD = libkdc.la $(LDADD) $(LIB_pidfile)
-include_HEADERS = kdc.h kdc-protos.h
+kdc_tester_LDADD = libkdc.la $(LDADD) $(LIB_pidfile) $(LIB_heimbase)
+include_HEADERS = kdc.h $(srcdir)/kdc-protos.h
+noinst_HEADERS = $(srcdir)/kdc-private.h
krb5dir = $(includedir)/krb5
krb5_HEADERS = windc_plugin.h
build_HEADERZ = $(krb5_HEADERS) # XXX
@@ -562,7 +700,7 @@ EXTRA_DIST = \
all: all-am
.SUFFIXES:
-.SUFFIXES: .et .h .x .z .hx .1 .3 .5 .8 .cat1 .cat3 .cat5 .cat8 .c .lo .o .obj
+.SUFFIXES: .et .h .pc.in .pc .x .z .hx .1 .3 .5 .7 .8 .cat1 .cat3 .cat5 .cat7 .cat8 .c .lo .o .obj
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.am.common $(top_srcdir)/cf/Makefile.am.common $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
@@ -575,7 +713,6 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign kdc/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --foreign kdc/Makefile
-.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
@@ -584,6 +721,7 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
+$(top_srcdir)/Makefile.am.common $(top_srcdir)/cf/Makefile.am.common $(am__empty):
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
@@ -593,9 +731,9 @@ $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
+
install-libLTLIBRARIES: $(lib_LTLIBRARIES)
@$(NORMAL_INSTALL)
- test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
list2=; for p in $$list; do \
if test -f $$p; then \
@@ -603,6 +741,8 @@ install-libLTLIBRARIES: $(lib_LTLIBRARIES)
else :; fi; \
done; \
test -z "$$list2" || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
}
@@ -618,24 +758,32 @@ uninstall-libLTLIBRARIES:
clean-libLTLIBRARIES:
-test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
- @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
- dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
- test "$$dir" != "$$p" || dir=.; \
- echo "rm -f \"$${dir}/so_locations\""; \
- rm -f "$${dir}/so_locations"; \
- done
-libkdc.la: $(libkdc_la_OBJECTS) $(libkdc_la_DEPENDENCIES)
- $(libkdc_la_LINK) -rpath $(libdir) $(libkdc_la_OBJECTS) $(libkdc_la_LIBADD) $(LIBS)
+ @list='$(lib_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+libkdc.la: $(libkdc_la_OBJECTS) $(libkdc_la_DEPENDENCIES) $(EXTRA_libkdc_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libkdc_la_LINK) -rpath $(libdir) $(libkdc_la_OBJECTS) $(libkdc_la_LIBADD) $(LIBS)
install-binPROGRAMS: $(bin_PROGRAMS)
@$(NORMAL_INSTALL)
- test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
+ fi; \
for p in $$list; do echo "$$p $$p"; done | \
sed 's/$(EXEEXT)$$//' | \
- while read p p1; do if test -f $$p || test -f $$p1; \
- then echo "$$p"; echo "$$p"; else :; fi; \
+ while read p p1; do if test -f $$p \
+ || test -f $$p1 \
+ ; then echo "$$p"; echo "$$p"; else :; fi; \
done | \
- sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
+ sed -e 'p;s,.*/,,;n;h' \
+ -e 's|.*|.|' \
-e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
sed 'N;N;N;s,\n, ,g' | \
$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
@@ -656,7 +804,8 @@ uninstall-binPROGRAMS:
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
files=`for p in $$list; do echo "$$p"; done | \
sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
- -e 's/$$/$(EXEEXT)/' `; \
+ -e 's/$$/$(EXEEXT)/' \
+ `; \
test -n "$$list" || exit 0; \
echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(bindir)" && rm -f $$files
@@ -671,14 +820,19 @@ clean-binPROGRAMS:
rm -f $$list
install-libexecPROGRAMS: $(libexec_PROGRAMS)
@$(NORMAL_INSTALL)
- test -z "$(libexecdir)" || $(MKDIR_P) "$(DESTDIR)$(libexecdir)"
@list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \
+ fi; \
for p in $$list; do echo "$$p $$p"; done | \
sed 's/$(EXEEXT)$$//' | \
- while read p p1; do if test -f $$p || test -f $$p1; \
- then echo "$$p"; echo "$$p"; else :; fi; \
+ while read p p1; do if test -f $$p \
+ || test -f $$p1 \
+ ; then echo "$$p"; echo "$$p"; else :; fi; \
done | \
- sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
+ sed -e 'p;s,.*/,,;n;h' \
+ -e 's|.*|.|' \
-e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
sed 'N;N;N;s,\n, ,g' | \
$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
@@ -699,7 +853,8 @@ uninstall-libexecPROGRAMS:
@list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \
files=`for p in $$list; do echo "$$p"; done | \
sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
- -e 's/$$/$(EXEEXT)/' `; \
+ -e 's/$$/$(EXEEXT)/' \
+ `; \
test -n "$$list" || exit 0; \
echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(libexecdir)" && rm -f $$files
@@ -723,14 +878,19 @@ clean-noinstPROGRAMS:
rm -f $$list
install-sbinPROGRAMS: $(sbin_PROGRAMS)
@$(NORMAL_INSTALL)
- test -z "$(sbindir)" || $(MKDIR_P) "$(DESTDIR)$(sbindir)"
@list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \
+ fi; \
for p in $$list; do echo "$$p $$p"; done | \
sed 's/$(EXEEXT)$$//' | \
- while read p p1; do if test -f $$p || test -f $$p1; \
- then echo "$$p"; echo "$$p"; else :; fi; \
+ while read p p1; do if test -f $$p \
+ || test -f $$p1 \
+ ; then echo "$$p"; echo "$$p"; else :; fi; \
done | \
- sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
+ sed -e 'p;s,.*/,,;n;h' \
+ -e 's|.*|.|' \
-e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
sed 'N;N;N;s,\n, ,g' | \
$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
@@ -751,7 +911,8 @@ uninstall-sbinPROGRAMS:
@list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
files=`for p in $$list; do echo "$$p"; done | \
sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
- -e 's/$$/$(EXEEXT)/' `; \
+ -e 's/$$/$(EXEEXT)/' \
+ `; \
test -n "$$list" || exit 0; \
echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(sbindir)" && rm -f $$files
@@ -764,27 +925,38 @@ clean-sbinPROGRAMS:
list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
echo " rm -f" $$list; \
rm -f $$list
-digest-service$(EXEEXT): $(digest_service_OBJECTS) $(digest_service_DEPENDENCIES)
+
+digest-service$(EXEEXT): $(digest_service_OBJECTS) $(digest_service_DEPENDENCIES) $(EXTRA_digest_service_DEPENDENCIES)
@rm -f digest-service$(EXEEXT)
- $(LINK) $(digest_service_OBJECTS) $(digest_service_LDADD) $(LIBS)
-hprop$(EXEEXT): $(hprop_OBJECTS) $(hprop_DEPENDENCIES)
+ $(AM_V_CCLD)$(LINK) $(digest_service_OBJECTS) $(digest_service_LDADD) $(LIBS)
+
+hprop$(EXEEXT): $(hprop_OBJECTS) $(hprop_DEPENDENCIES) $(EXTRA_hprop_DEPENDENCIES)
@rm -f hprop$(EXEEXT)
- $(LINK) $(hprop_OBJECTS) $(hprop_LDADD) $(LIBS)
-hpropd$(EXEEXT): $(hpropd_OBJECTS) $(hpropd_DEPENDENCIES)
+ $(AM_V_CCLD)$(LINK) $(hprop_OBJECTS) $(hprop_LDADD) $(LIBS)
+
+hpropd$(EXEEXT): $(hpropd_OBJECTS) $(hpropd_DEPENDENCIES) $(EXTRA_hpropd_DEPENDENCIES)
@rm -f hpropd$(EXEEXT)
- $(LINK) $(hpropd_OBJECTS) $(hpropd_LDADD) $(LIBS)
-kdc$(EXEEXT): $(kdc_OBJECTS) $(kdc_DEPENDENCIES)
+ $(AM_V_CCLD)$(LINK) $(hpropd_OBJECTS) $(hpropd_LDADD) $(LIBS)
+
+kdc$(EXEEXT): $(kdc_OBJECTS) $(kdc_DEPENDENCIES) $(EXTRA_kdc_DEPENDENCIES)
@rm -f kdc$(EXEEXT)
- $(kdc_LINK) $(kdc_OBJECTS) $(kdc_LDADD) $(LIBS)
-kdc-replay$(EXEEXT): $(kdc_replay_OBJECTS) $(kdc_replay_DEPENDENCIES)
+ $(AM_V_CCLD)$(kdc_LINK) $(kdc_OBJECTS) $(kdc_LDADD) $(LIBS)
+
+kdc-replay$(EXEEXT): $(kdc_replay_OBJECTS) $(kdc_replay_DEPENDENCIES) $(EXTRA_kdc_replay_DEPENDENCIES)
@rm -f kdc-replay$(EXEEXT)
- $(LINK) $(kdc_replay_OBJECTS) $(kdc_replay_LDADD) $(LIBS)
-kstash$(EXEEXT): $(kstash_OBJECTS) $(kstash_DEPENDENCIES)
+ $(AM_V_CCLD)$(LINK) $(kdc_replay_OBJECTS) $(kdc_replay_LDADD) $(LIBS)
+
+kdc-tester$(EXEEXT): $(kdc_tester_OBJECTS) $(kdc_tester_DEPENDENCIES) $(EXTRA_kdc_tester_DEPENDENCIES)
+ @rm -f kdc-tester$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(kdc_tester_OBJECTS) $(kdc_tester_LDADD) $(LIBS)
+
+kstash$(EXEEXT): $(kstash_OBJECTS) $(kstash_DEPENDENCIES) $(EXTRA_kstash_DEPENDENCIES)
@rm -f kstash$(EXEEXT)
- $(LINK) $(kstash_OBJECTS) $(kstash_LDADD) $(LIBS)
-string2key$(EXEEXT): $(string2key_OBJECTS) $(string2key_DEPENDENCIES)
+ $(AM_V_CCLD)$(LINK) $(kstash_OBJECTS) $(kstash_LDADD) $(LIBS)
+
+string2key$(EXEEXT): $(string2key_OBJECTS) $(string2key_DEPENDENCIES) $(EXTRA_string2key_DEPENDENCIES)
@rm -f string2key$(EXEEXT)
- $(LINK) $(string2key_OBJECTS) $(string2key_LDADD) $(LIBS)
+ $(AM_V_CCLD)$(LINK) $(string2key_OBJECTS) $(string2key_LDADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -792,9 +964,11 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/config.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/default_config.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/digest-service.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/digest.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fast.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hprop.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hpropd.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kdc-announce.Po@am__quote@
@@ -802,6 +976,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kdc-connect.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kdc-main.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kdc-replay.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kdc-tester.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kerberos5.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/krb5tgs.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kstash.Po@am__quote@
@@ -809,6 +984,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mit_dump.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pkinit-ec.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pkinit.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/process.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/set_dbinfo.Plo@am__quote@
@@ -816,81 +992,81 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/windc.Plo@am__quote@
.c.o:
-@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
.c.obj:
-@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
.c.lo:
-@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
kdc-connect.o: connect.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kdc_CFLAGS) $(CFLAGS) -MT kdc-connect.o -MD -MP -MF $(DEPDIR)/kdc-connect.Tpo -c -o kdc-connect.o `test -f 'connect.c' || echo '$(srcdir)/'`connect.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/kdc-connect.Tpo $(DEPDIR)/kdc-connect.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='connect.c' object='kdc-connect.o' libtool=no @AMDEPBACKSLASH@
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kdc_CFLAGS) $(CFLAGS) -MT kdc-connect.o -MD -MP -MF $(DEPDIR)/kdc-connect.Tpo -c -o kdc-connect.o `test -f 'connect.c' || echo '$(srcdir)/'`connect.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/kdc-connect.Tpo $(DEPDIR)/kdc-connect.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='connect.c' object='kdc-connect.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kdc_CFLAGS) $(CFLAGS) -c -o kdc-connect.o `test -f 'connect.c' || echo '$(srcdir)/'`connect.c
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kdc_CFLAGS) $(CFLAGS) -c -o kdc-connect.o `test -f 'connect.c' || echo '$(srcdir)/'`connect.c
kdc-connect.obj: connect.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kdc_CFLAGS) $(CFLAGS) -MT kdc-connect.obj -MD -MP -MF $(DEPDIR)/kdc-connect.Tpo -c -o kdc-connect.obj `if test -f 'connect.c'; then $(CYGPATH_W) 'connect.c'; else $(CYGPATH_W) '$(srcdir)/connect.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/kdc-connect.Tpo $(DEPDIR)/kdc-connect.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='connect.c' object='kdc-connect.obj' libtool=no @AMDEPBACKSLASH@
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kdc_CFLAGS) $(CFLAGS) -MT kdc-connect.obj -MD -MP -MF $(DEPDIR)/kdc-connect.Tpo -c -o kdc-connect.obj `if test -f 'connect.c'; then $(CYGPATH_W) 'connect.c'; else $(CYGPATH_W) '$(srcdir)/connect.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/kdc-connect.Tpo $(DEPDIR)/kdc-connect.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='connect.c' object='kdc-connect.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kdc_CFLAGS) $(CFLAGS) -c -o kdc-connect.obj `if test -f 'connect.c'; then $(CYGPATH_W) 'connect.c'; else $(CYGPATH_W) '$(srcdir)/connect.c'; fi`
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kdc_CFLAGS) $(CFLAGS) -c -o kdc-connect.obj `if test -f 'connect.c'; then $(CYGPATH_W) 'connect.c'; else $(CYGPATH_W) '$(srcdir)/connect.c'; fi`
kdc-config.o: config.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kdc_CFLAGS) $(CFLAGS) -MT kdc-config.o -MD -MP -MF $(DEPDIR)/kdc-config.Tpo -c -o kdc-config.o `test -f 'config.c' || echo '$(srcdir)/'`config.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/kdc-config.Tpo $(DEPDIR)/kdc-config.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config.c' object='kdc-config.o' libtool=no @AMDEPBACKSLASH@
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kdc_CFLAGS) $(CFLAGS) -MT kdc-config.o -MD -MP -MF $(DEPDIR)/kdc-config.Tpo -c -o kdc-config.o `test -f 'config.c' || echo '$(srcdir)/'`config.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/kdc-config.Tpo $(DEPDIR)/kdc-config.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='config.c' object='kdc-config.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kdc_CFLAGS) $(CFLAGS) -c -o kdc-config.o `test -f 'config.c' || echo '$(srcdir)/'`config.c
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kdc_CFLAGS) $(CFLAGS) -c -o kdc-config.o `test -f 'config.c' || echo '$(srcdir)/'`config.c
kdc-config.obj: config.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kdc_CFLAGS) $(CFLAGS) -MT kdc-config.obj -MD -MP -MF $(DEPDIR)/kdc-config.Tpo -c -o kdc-config.obj `if test -f 'config.c'; then $(CYGPATH_W) 'config.c'; else $(CYGPATH_W) '$(srcdir)/config.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/kdc-config.Tpo $(DEPDIR)/kdc-config.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config.c' object='kdc-config.obj' libtool=no @AMDEPBACKSLASH@
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kdc_CFLAGS) $(CFLAGS) -MT kdc-config.obj -MD -MP -MF $(DEPDIR)/kdc-config.Tpo -c -o kdc-config.obj `if test -f 'config.c'; then $(CYGPATH_W) 'config.c'; else $(CYGPATH_W) '$(srcdir)/config.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/kdc-config.Tpo $(DEPDIR)/kdc-config.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='config.c' object='kdc-config.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kdc_CFLAGS) $(CFLAGS) -c -o kdc-config.obj `if test -f 'config.c'; then $(CYGPATH_W) 'config.c'; else $(CYGPATH_W) '$(srcdir)/config.c'; fi`
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kdc_CFLAGS) $(CFLAGS) -c -o kdc-config.obj `if test -f 'config.c'; then $(CYGPATH_W) 'config.c'; else $(CYGPATH_W) '$(srcdir)/config.c'; fi`
kdc-announce.o: announce.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kdc_CFLAGS) $(CFLAGS) -MT kdc-announce.o -MD -MP -MF $(DEPDIR)/kdc-announce.Tpo -c -o kdc-announce.o `test -f 'announce.c' || echo '$(srcdir)/'`announce.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/kdc-announce.Tpo $(DEPDIR)/kdc-announce.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='announce.c' object='kdc-announce.o' libtool=no @AMDEPBACKSLASH@
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kdc_CFLAGS) $(CFLAGS) -MT kdc-announce.o -MD -MP -MF $(DEPDIR)/kdc-announce.Tpo -c -o kdc-announce.o `test -f 'announce.c' || echo '$(srcdir)/'`announce.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/kdc-announce.Tpo $(DEPDIR)/kdc-announce.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='announce.c' object='kdc-announce.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kdc_CFLAGS) $(CFLAGS) -c -o kdc-announce.o `test -f 'announce.c' || echo '$(srcdir)/'`announce.c
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kdc_CFLAGS) $(CFLAGS) -c -o kdc-announce.o `test -f 'announce.c' || echo '$(srcdir)/'`announce.c
kdc-announce.obj: announce.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kdc_CFLAGS) $(CFLAGS) -MT kdc-announce.obj -MD -MP -MF $(DEPDIR)/kdc-announce.Tpo -c -o kdc-announce.obj `if test -f 'announce.c'; then $(CYGPATH_W) 'announce.c'; else $(CYGPATH_W) '$(srcdir)/announce.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/kdc-announce.Tpo $(DEPDIR)/kdc-announce.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='announce.c' object='kdc-announce.obj' libtool=no @AMDEPBACKSLASH@
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kdc_CFLAGS) $(CFLAGS) -MT kdc-announce.obj -MD -MP -MF $(DEPDIR)/kdc-announce.Tpo -c -o kdc-announce.obj `if test -f 'announce.c'; then $(CYGPATH_W) 'announce.c'; else $(CYGPATH_W) '$(srcdir)/announce.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/kdc-announce.Tpo $(DEPDIR)/kdc-announce.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='announce.c' object='kdc-announce.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kdc_CFLAGS) $(CFLAGS) -c -o kdc-announce.obj `if test -f 'announce.c'; then $(CYGPATH_W) 'announce.c'; else $(CYGPATH_W) '$(srcdir)/announce.c'; fi`
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kdc_CFLAGS) $(CFLAGS) -c -o kdc-announce.obj `if test -f 'announce.c'; then $(CYGPATH_W) 'announce.c'; else $(CYGPATH_W) '$(srcdir)/announce.c'; fi`
kdc-main.o: main.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kdc_CFLAGS) $(CFLAGS) -MT kdc-main.o -MD -MP -MF $(DEPDIR)/kdc-main.Tpo -c -o kdc-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/kdc-main.Tpo $(DEPDIR)/kdc-main.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='main.c' object='kdc-main.o' libtool=no @AMDEPBACKSLASH@
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kdc_CFLAGS) $(CFLAGS) -MT kdc-main.o -MD -MP -MF $(DEPDIR)/kdc-main.Tpo -c -o kdc-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/kdc-main.Tpo $(DEPDIR)/kdc-main.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='main.c' object='kdc-main.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kdc_CFLAGS) $(CFLAGS) -c -o kdc-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kdc_CFLAGS) $(CFLAGS) -c -o kdc-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c
kdc-main.obj: main.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kdc_CFLAGS) $(CFLAGS) -MT kdc-main.obj -MD -MP -MF $(DEPDIR)/kdc-main.Tpo -c -o kdc-main.obj `if test -f 'main.c'; then $(CYGPATH_W) 'main.c'; else $(CYGPATH_W) '$(srcdir)/main.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/kdc-main.Tpo $(DEPDIR)/kdc-main.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='main.c' object='kdc-main.obj' libtool=no @AMDEPBACKSLASH@
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kdc_CFLAGS) $(CFLAGS) -MT kdc-main.obj -MD -MP -MF $(DEPDIR)/kdc-main.Tpo -c -o kdc-main.obj `if test -f 'main.c'; then $(CYGPATH_W) 'main.c'; else $(CYGPATH_W) '$(srcdir)/main.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/kdc-main.Tpo $(DEPDIR)/kdc-main.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='main.c' object='kdc-main.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kdc_CFLAGS) $(CFLAGS) -c -o kdc-main.obj `if test -f 'main.c'; then $(CYGPATH_W) 'main.c'; else $(CYGPATH_W) '$(srcdir)/main.c'; fi`
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(kdc_CFLAGS) $(CFLAGS) -c -o kdc-main.obj `if test -f 'main.c'; then $(CYGPATH_W) 'main.c'; else $(CYGPATH_W) '$(srcdir)/main.c'; fi`
mostlyclean-libtool:
-rm -f *.lo
@@ -899,11 +1075,18 @@ clean-libtool:
-rm -rf .libs _libs
install-man8: $(man_MANS)
@$(NORMAL_INSTALL)
- test -z "$(man8dir)" || $(MKDIR_P) "$(DESTDIR)$(man8dir)"
- @list=''; test -n "$(man8dir)" || exit 0; \
- { for i in $$list; do echo "$$i"; done; \
- l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \
- sed -n '/\.8[a-z]*$$/p'; \
+ @list1=''; \
+ list2='$(man_MANS)'; \
+ test -n "$(man8dir)" \
+ && test -n "`echo $$list1$$list2`" \
+ || exit 0; \
+ echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \
+ { for i in $$list1; do echo "$$i"; done; \
+ if test -n "$$list2"; then \
+ for i in $$list2; do echo "$$i"; done \
+ | sed -n '/\.8[a-z]*$$/p'; \
+ fi; \
} | while read p; do \
if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; echo "$$p"; \
@@ -932,13 +1115,14 @@ uninstall-man8:
sed -n '/\.8[a-z]*$$/p'; \
} | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
- test -z "$$files" || { \
- echo " ( cd '$(DESTDIR)$(man8dir)' && rm -f" $$files ")"; \
- cd "$(DESTDIR)$(man8dir)" && rm -f $$files; }
+ dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir)
install-includeHEADERS: $(include_HEADERS)
@$(NORMAL_INSTALL)
- test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)"
@list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \
+ fi; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; \
@@ -952,13 +1136,14 @@ uninstall-includeHEADERS:
@$(NORMAL_UNINSTALL)
@list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
- test -n "$$files" || exit 0; \
- echo " ( cd '$(DESTDIR)$(includedir)' && rm -f" $$files ")"; \
- cd "$(DESTDIR)$(includedir)" && rm -f $$files
+ dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir)
install-krb5HEADERS: $(krb5_HEADERS)
@$(NORMAL_INSTALL)
- test -z "$(krb5dir)" || $(MKDIR_P) "$(DESTDIR)$(krb5dir)"
@list='$(krb5_HEADERS)'; test -n "$(krb5dir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(krb5dir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(krb5dir)" || exit 1; \
+ fi; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; \
@@ -972,30 +1157,17 @@ uninstall-krb5HEADERS:
@$(NORMAL_UNINSTALL)
@list='$(krb5_HEADERS)'; test -n "$(krb5dir)" || list=; \
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
- test -n "$$files" || exit 0; \
- echo " ( cd '$(DESTDIR)$(krb5dir)' && rm -f" $$files ")"; \
- cd "$(DESTDIR)$(krb5dir)" && rm -f $$files
-
-ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | \
- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
- END { if (nonempty) { for (i in files) print i; }; }'`; \
- mkid -fID $$unique
-tags: TAGS
-
-TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
- $(TAGS_FILES) $(LISP)
+ dir='$(DESTDIR)$(krb5dir)'; $(am__uninstall_files_from_dir)
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
set x; \
here=`pwd`; \
- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | \
- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
- END { if (nonempty) { for (i in files) print i; }; }'`; \
+ $(am__define_uniq_tagged_files); \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
@@ -1007,15 +1179,11 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$$unique; \
fi; \
fi
-ctags: CTAGS
-CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
- $(TAGS_FILES) $(LISP)
- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | \
- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
- END { if (nonempty) { for (i in files) print i; }; }'`; \
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
@@ -1024,24 +1192,26 @@ GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
- @list='$(MANS)'; if test -n "$$list"; then \
- list=`for p in $$list; do \
- if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
- if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \
- if test -n "$$list" && \
- grep 'ab help2man is required to generate this page' $$list >/dev/null; then \
- echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \
- grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \
- echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \
- echo " typically \`make maintainer-clean' will remove them" >&2; \
- exit 1; \
- else :; fi; \
- else :; fi
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
@@ -1095,10 +1265,15 @@ install-am: all-am
installcheck: installcheck-am
install-strip:
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
- `test -z '$(STRIP)' || \
- echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
mostlyclean-generic:
clean-generic:
@@ -1142,10 +1317,10 @@ install-dvi: install-dvi-am
install-dvi-am:
-install-exec-am: install-binPROGRAMS install-libLTLIBRARIES \
- install-libexecPROGRAMS install-sbinPROGRAMS
- @$(NORMAL_INSTALL)
- $(MAKE) $(AM_MAKEFLAGS) install-exec-hook
+install-exec-am: install-binPROGRAMS install-exec-local \
+ install-libLTLIBRARIES install-libexecPROGRAMS \
+ install-sbinPROGRAMS
+
install-html: install-html-am
install-html-am:
@@ -1191,46 +1366,60 @@ uninstall-am: uninstall-binPROGRAMS uninstall-includeHEADERS \
$(MAKE) $(AM_MAKEFLAGS) uninstall-hook
uninstall-man: uninstall-man8
-.MAKE: check-am install-am install-data-am install-exec-am \
- install-strip uninstall-am
+.MAKE: check-am install-am install-data-am install-strip uninstall-am
-.PHONY: CTAGS GTAGS all all-am all-local check check-am check-local \
- clean clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \
- clean-libexecPROGRAMS clean-libtool clean-noinstPROGRAMS \
- clean-sbinPROGRAMS ctags dist-hook distclean distclean-compile \
+.PHONY: CTAGS GTAGS TAGS all all-am all-local check check-am \
+ check-local clean clean-binPROGRAMS clean-generic \
+ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \
+ clean-noinstPROGRAMS clean-sbinPROGRAMS cscopelist-am ctags \
+ ctags-am dist-hook distclean distclean-compile \
distclean-generic distclean-libtool distclean-tags distdir dvi \
dvi-am html html-am info info-am install install-am \
install-binPROGRAMS install-data install-data-am \
install-data-hook install-dvi install-dvi-am install-exec \
- install-exec-am install-exec-hook install-html install-html-am \
- install-includeHEADERS install-info install-info-am \
- install-krb5HEADERS install-libLTLIBRARIES \
+ install-exec-am install-exec-local install-html \
+ install-html-am install-includeHEADERS install-info \
+ install-info-am install-krb5HEADERS install-libLTLIBRARIES \
install-libexecPROGRAMS install-man install-man8 install-pdf \
install-pdf-am install-ps install-ps-am install-sbinPROGRAMS \
install-strip installcheck installcheck-am installdirs \
maintainer-clean maintainer-clean-generic mostlyclean \
mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
- pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \
uninstall-binPROGRAMS uninstall-hook uninstall-includeHEADERS \
uninstall-krb5HEADERS uninstall-libLTLIBRARIES \
uninstall-libexecPROGRAMS uninstall-man uninstall-man8 \
uninstall-sbinPROGRAMS
+.PRECIOUS: Makefile
+
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 \
- echo "*"; \
- echo "* Failed to install $$x setuid root"; \
- echo "*"; \
- fi; done
+ x=$(DESTDIR)$(bindir)/$$file; \
+ if chown 0:0 $$x && chmod u+s $$x; then :; else \
+ echo "*"; \
+ echo "* Failed to install $$x setuid root"; \
+ echo "*"; \
+ fi; \
+ done
-install-exec-hook: install-suid-programs
+install-exec-local: install-suid-programs
-install-build-headers:: $(include_HEADERS) $(dist_include_HEADERS) $(nodist_include_HEADERS) $(build_HEADERZ) $(nobase_include_HEADERS)
- @foo='$(include_HEADERS) $(dist_include_HEADERS) $(nodist_include_HEADERS) $(build_HEADERZ)'; \
+codesign-all:
+ @if [ X"$$CODE_SIGN_IDENTITY" != X ] ; then \
+ foo='$(bin_PROGRAMS) $(sbin_PROGRAMS) $(libexec_PROGRAMS)' ; \
+ for file in $$foo ; do \
+ echo "CODESIGN $$file" ; \
+ codesign -f -s "$$CODE_SIGN_IDENTITY" $$file || exit 1 ; \
+ done ; \
+ fi
+
+all-local: codesign-all
+
+install-build-headers:: $(include_HEADERS) $(dist_include_HEADERS) $(nodist_include_HEADERS) $(build_HEADERZ) $(nobase_include_HEADERS) $(noinst_HEADERS)
+ @foo='$(include_HEADERS) $(dist_include_HEADERS) $(nodist_include_HEADERS) $(build_HEADERZ) $(noinst_HEADERS)'; \
for f in $$foo; do \
f=`basename $$f`; \
if test -f "$(srcdir)/$$f"; then file="$(srcdir)/$$f"; \
@@ -1238,7 +1427,7 @@ install-build-headers:: $(include_HEADERS) $(dist_include_HEADERS) $(nodist_incl
if cmp -s $$file $(buildinclude)/$$f 2> /dev/null ; then \
: ; else \
echo " $(CP) $$file $(buildinclude)/$$f"; \
- $(CP) $$file $(buildinclude)/$$f; \
+ $(CP) $$file $(buildinclude)/$$f || true; \
fi ; \
done ; \
foo='$(nobase_include_HEADERS)'; \
@@ -1295,6 +1484,8 @@ check-local::
$(NROFF_MAN) $< > $@
.5.cat5:
$(NROFF_MAN) $< > $@
+.7.cat7:
+ $(NROFF_MAN) $< > $@
.8.cat8:
$(NROFF_MAN) $< > $@
@@ -1337,6 +1528,19 @@ dist-cat5-mans:
$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \
done
+dist-cat7-mans:
+ @foo='$(man7_MANS)'; \
+ bar='$(man_MANS)'; \
+ for i in $$bar; do \
+ case $$i in \
+ *.7) foo="$$foo $$i";; \
+ esac; done ;\
+ for i in $$foo; do \
+ x=`echo $$i | sed 's/\.[^.]*$$/.cat7/'`; \
+ echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \
+ $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \
+ done
+
dist-cat8-mans:
@foo='$(man8_MANS)'; \
bar='$(man_MANS)'; \
@@ -1350,13 +1554,13 @@ dist-cat8-mans:
$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \
done
-dist-hook: dist-cat1-mans dist-cat3-mans dist-cat5-mans dist-cat8-mans
+dist-hook: dist-cat1-mans dist-cat3-mans dist-cat5-mans dist-cat7-mans dist-cat8-mans
install-cat-mans:
- $(SHELL) $(top_srcdir)/cf/install-catman.sh install "$(INSTALL_DATA)" "$(mkinstalldirs)" "$(srcdir)" "$(DESTDIR)$(mandir)" '$(CATMANEXT)' $(man_MANS) $(man1_MANS) $(man3_MANS) $(man5_MANS) $(man8_MANS)
+ $(SHELL) $(top_srcdir)/cf/install-catman.sh install "$(INSTALL_DATA)" "$(mkinstalldirs)" "$(srcdir)" "$(DESTDIR)$(mandir)" '$(CATMANEXT)' $(man_MANS) $(man1_MANS) $(man3_MANS) $(man5_MANS) $(man7_MANS) $(man8_MANS)
uninstall-cat-mans:
- $(SHELL) $(top_srcdir)/cf/install-catman.sh uninstall "$(INSTALL_DATA)" "$(mkinstalldirs)" "$(srcdir)" "$(DESTDIR)$(mandir)" '$(CATMANEXT)' $(man_MANS) $(man1_MANS) $(man3_MANS) $(man5_MANS) $(man8_MANS)
+ $(SHELL) $(top_srcdir)/cf/install-catman.sh uninstall "$(INSTALL_DATA)" "$(mkinstalldirs)" "$(srcdir)" "$(DESTDIR)$(mandir)" '$(CATMANEXT)' $(man_MANS) $(man1_MANS) $(man3_MANS) $(man5_MANS) $(man7_MANS) $(man8_MANS)
install-data-hook: install-cat-mans
uninstall-hook: uninstall-cat-mans
@@ -1387,13 +1591,13 @@ distdir-in-tree: $(DISTFILES) $(INFO_DEPS)
fi ; \
done
-$(libkdc_la_OBJECTS): $(srcdir)/kdc-protos.h $(srcdir)/kdc-private.h
+$(ALL_OBJECTS): $(KDC_PROTOS)
$(libkdc_la_OBJECTS): $(srcdir)/version-script.map
-$(srcdir)/kdc-protos.h:
+$(srcdir)/kdc-protos.h: $(libkdc_la_SOURCES)
cd $(srcdir) && perl ../cf/make-proto.pl -q -P comment -o kdc-protos.h $(libkdc_la_SOURCES) || rm -f kdc-protos.h
-$(srcdir)/kdc-private.h:
+$(srcdir)/kdc-private.h: $(libkdc_la_SOURCES)
cd $(srcdir) && perl ../cf/make-proto.pl -q -P comment -p kdc-private.h $(libkdc_la_SOURCES) || rm -f kdc-private.h
# Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/kdc/NTMakefile b/kdc/NTMakefile
index bb5b51069a1d..c4bc69ab1cd0 100644
--- a/kdc/NTMakefile
+++ b/kdc/NTMakefile
@@ -1,6 +1,6 @@
########################################################################
#
-# Copyright (c) 2009, Secure Endpoints Inc.
+# Copyright (c) 2009-2016, Secure Endpoints Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -67,11 +67,6 @@ $(LIBEXECDIR)\hprop.exe: $(OBJ)\hprop.obj $(OBJ)\mit_dump.obj $(BIN_LIBS) $(OBJ)
$(EXECONLINK)
$(EXEPREP)
-!ifdef KRB4
-$(LIBEXECDIR)\hprop.exe: $(OBJ)\v4_dump.obj
-!endif
-
-
$(LIBEXECDIR)\hpropd.exe: $(OBJ)\hpropd.obj $(BIN_LIBS) $(OBJ)\hpropd-version.res
$(EXECONLINK)
$(EXEPREP)
@@ -91,7 +86,7 @@ $(BINDIR)\digest-service.exe: $(OBJ)\digest-service.obj $(BIN_LIBS)
$(LIBEXECDIR)\kdc.exe: \
$(OBJ)\connect.obj $(OBJ)\config.obj $(OBJ)\announce.obj \
$(OBJ)\main.obj $(OBJ)\kdc-version.res \
- $(LIBKDC) $(BIN_LIBS)
+ $(LIBKDC) $(BIN_LIBS) $(LIB_openssl_crypto)
$(EXECONLINK)
$(EXEPREP)
@@ -99,32 +94,30 @@ LIBKDC_OBJS=\
$(OBJ)\default_config.obj \
$(OBJ)\set_dbinfo.obj \
$(OBJ)\digest.obj \
+ $(OBJ)\fast.obj \
$(OBJ)\kerberos5.obj \
$(OBJ)\krb5tgs.obj \
$(OBJ)\pkinit.obj \
+ $(OBJ)\pkinit-ec.obj \
$(OBJ)\log.obj \
$(OBJ)\misc.obj \
$(OBJ)\kx509.obj \
$(OBJ)\process.obj \
$(OBJ)\windc.obj
-!ifdef KRB4
-LIBKDC_OBJS=$(LIBKDC_OBJS) \
- $(OBJ)\524.obj \
- $(OBJ)\kerberos4.obj
-!endif
-
LIBKDC_LIBS=\
- $(LIBHDB) \
- $(LIBHEIMDAL) \
- $(LIBHEIMNTLM) \
+ $(LIBHDB) \
+ $(LIBHEIMBASE) \
+ $(LIBHEIMDAL) \
+ $(LIBHEIMNTLM) \
+ $(LIB_openssl_crypto) \
$(LIBROKEN)
LIBKDCRES=$(OBJ)\libkdc-version.res
$(LIBEXECDIR)\libkdc.dll: $(LIBKDC_OBJS) $(LIBKDC_LIBS) $(LIBKDCRES)
$(DLLGUILINK) -implib:$(LIBKDC) -def:libkdc-exports.def
- $(DLLPREP)
+ $(DLLPREP_NODIST)
$(LIBKDC): $(LIBEXECDIR)\libkdc.dll
@@ -135,10 +128,12 @@ libkdc_la_SOURCES = \
default_config.c \
set_dbinfo.c \
digest.c \
+ fast.c \
kdc_locl.h \
kerberos5.c \
krb5tgs.c \
pkinit.c \
+ pkinit-ec.c \
log.c \
misc.c \
kx509.c \
@@ -146,12 +141,6 @@ libkdc_la_SOURCES = \
windc.c \
rx.h
-!ifdef KRB4
-libkdc_la_SOURCES=$(libkdc_la_SOURCES) \
- 524.c \
- kerberos4.c
-!endif
-
$(OBJ)\kdc-protos.h: $(libkdc_la_SOURCES)
$(PERL) ..\cf\make-proto.pl -q -P remove -o $@ $(libkdc_la_SOURCES) \
|| $(RM) $@
diff --git a/kdc/config.c b/kdc/config.c
index a437bbd121b2..e8e0ee4a535c 100644
--- a/kdc/config.c
+++ b/kdc/config.c
@@ -52,9 +52,25 @@ static char *max_request_str; /* `max_request' as a string */
static int disable_des = -1;
static int builtin_hdb_flag;
+int testing_flag;
static int help_flag;
static int version_flag;
+/* Should we enable the HTTP hack? */
+int enable_http = -1;
+
+/* Log over requests to the KDC */
+const char *request_log;
+
+/* A string describing on what ports to listen */
+const char *port_str;
+
+krb5_addresses explicit_addresses;
+
+size_t max_request_udp;
+size_t max_request_tcp;
+
+
static struct getarg_strings addresses_str; /* addresses to listen on */
char *runas_string;
@@ -79,18 +95,19 @@ static struct getargs args[] = {
{ "ports", 'P', arg_string, rk_UNCONST(&port_str),
"ports to listen to", "portspec"
},
-#ifdef SUPPORT_DETACH
-#if DETACH_IS_DEFAULT
- {
- "detach", 'D', arg_negative_flag, &detach_from_console,
- "don't detach from console", NULL
- },
-#else
{
"detach", 0 , arg_flag, &detach_from_console,
"detach from console", NULL
},
-#endif
+ {
+ "daemon-child", 0 , arg_flag, &daemon_child,
+ "private argument, do not use", NULL
+ },
+#ifdef __APPLE__
+ {
+ "bonjour", 0 , arg_flag, &do_bonjour,
+ "private argument, do not use", NULL
+ },
#endif
{ "addresses", 0, arg_strings, &addresses_str,
"addresses to listen on", "list of addresses" },
@@ -104,6 +121,7 @@ static struct getargs args[] = {
{ "chroot", 0, arg_string, &chroot_string,
"chroot directory to run in", NULL
},
+ { "testing", 0, arg_flag, &testing_flag, NULL, NULL },
{ "help", 'h', arg_flag, &help_flag, NULL, NULL },
{ "version", 'v', arg_flag, &version_flag, NULL, NULL }
};
@@ -134,17 +152,19 @@ add_one_address (krb5_context context, const char *str, int first)
}
krb5_kdc_configuration *
-configure(krb5_context context, int argc, char **argv)
+configure(krb5_context context, int argc, char **argv, int *optidx)
{
krb5_kdc_configuration *config;
krb5_error_code ret;
- int optidx = 0;
+
const char *p;
- while(getarg(args, num_args, argc, argv, &optidx))
- warnx("error at argument `%s'", argv[optidx]);
+ *optidx = 0;
+
+ while (getarg(args, num_args, argc, argv, optidx))
+ warnx("error at argument `%s'", argv[*optidx]);
- if(help_flag)
+ if (help_flag)
usage (0);
if (version_flag) {
@@ -162,18 +182,22 @@ configure(krb5_context context, int argc, char **argv)
exit(0);
}
- argc -= optidx;
- argv += optidx;
+ if(detach_from_console == -1)
+ detach_from_console = krb5_config_get_bool_default(context, NULL,
+ FALSE,
+ "kdc",
+ "detach", NULL);
- if (argc != 0)
- usage(1);
+ if (detach_from_console && daemon_child == -1)
+ roken_detach_prep(argc, argv, "--daemon-child");
{
char **files;
+ int aret;
if (config_file == NULL) {
- asprintf(&config_file, "%s/kdc.conf", hdb_db_dir(context));
- if (config_file == NULL)
+ aret = asprintf(&config_file, "%s/kdc.conf", hdb_db_dir(context));
+ if (aret == -1 || config_file == NULL)
errx(1, "out of memory");
}
@@ -253,14 +277,6 @@ configure(krb5_context context, int argc, char **argv)
krb5_errx(context, 1, "enforce-transited-policy deprecated, "
"use [kdc]transited-policy instead");
-#ifdef SUPPORT_DETACH
- if(detach_from_console == -1)
- detach_from_console = krb5_config_get_bool_default(context, NULL,
- DETACH_IS_DEFAULT,
- "kdc",
- "detach", NULL);
-#endif /* SUPPORT_DETACH */
-
if(max_request_tcp == 0)
max_request_tcp = 64 * 1024;
if(max_request_udp == 0)
diff --git a/kdc/connect.c b/kdc/connect.c
index 8ecf375b8d21..7b45103f6b7a 100644
--- a/kdc/connect.c
+++ b/kdc/connect.c
@@ -33,20 +33,6 @@
#include "kdc_locl.h"
-/* Should we enable the HTTP hack? */
-int enable_http = -1;
-
-/* Log over requests to the KDC */
-const char *request_log;
-
-/* A string describing on what ports to listen */
-const char *port_str;
-
-krb5_addresses explicit_addresses;
-
-size_t max_request_udp;
-size_t max_request_tcp;
-
/*
* a tuple describing on what to listen
*/
@@ -61,6 +47,7 @@ struct port_desc{
static struct port_desc *ports;
static size_t num_ports;
+static pid_t bonjour_pid = -1;
/*
* add `family, port, protocol' to the list with duplicate suppresion.
@@ -272,6 +259,7 @@ init_socket(krb5_context context,
d->s = rk_INVALID_SOCKET;
return;
}
+ rk_cloexec(d->s);
#if defined(HAVE_SETSOCKOPT) && defined(SOL_SOCKET) && defined(SO_REUSEADDR)
{
int one = 1;
@@ -281,6 +269,8 @@ init_socket(krb5_context context,
d->type = type;
d->port = port;
+ socket_set_nonblocking(d->s, 1);
+
if(rk_IS_SOCKET_ERROR(bind(d->s, sa, sa_size))){
char a_str[256];
size_t len;
@@ -471,16 +461,18 @@ handle_udp(krb5_context context,
ssize_t n;
buf = malloc(max_request_udp);
- if(buf == NULL){
- kdc_log(context, config, 0, "Failed to allocate %lu bytes", (unsigned long)max_request_udp);
+ if (buf == NULL){
+ kdc_log(context, config, 0, "Failed to allocate %lu bytes",
+ (unsigned long)max_request_udp);
return;
}
d->sock_len = sizeof(d->__ss);
n = recvfrom(d->s, buf, max_request_udp, 0, d->sa, &d->sock_len);
- if(rk_IS_SOCKET_ERROR(n))
- krb5_warn(context, rk_SOCK_ERRNO, "recvfrom");
- else {
+ if (rk_IS_SOCKET_ERROR(n)) {
+ if (rk_SOCK_ERRNO != EAGAIN && rk_SOCK_ERRNO != EINTR)
+ krb5_warn(context, rk_SOCK_ERRNO, "recvfrom");
+ } else {
addr_to_string (context, d->sa, d->sock_len,
d->addr_string, sizeof(d->addr_string));
if ((size_t)n == max_request_udp) {
@@ -523,15 +515,21 @@ static int
de_http(char *buf)
{
unsigned char *p, *q;
- for(p = q = (unsigned char *)buf; *p; p++, q++) {
- if(*p == '%' && isxdigit(p[1]) && isxdigit(p[2])) {
- unsigned int x;
- if(sscanf((char *)p + 1, "%2x", &x) != 1)
+ unsigned int x;
+
+ for (p = q = (unsigned char *)buf; *p; p++, q++) {
+ if (*p == '%') {
+ if (!(isxdigit(p[1]) && isxdigit(p[2])))
+ return -1;
+
+ if (sscanf((char *)p + 1, "%2x", &x) != 1)
return -1;
+
*q = x;
p += 2;
- } else
+ } else {
*q = *p;
+ }
}
*q = '\0';
return 0;
@@ -556,7 +554,8 @@ add_new_tcp (krb5_context context,
d[child].sock_len = sizeof(d[child].__ss);
s = accept(d[parent].s, d[child].sa, &d[child].sock_len);
if(rk_IS_BAD_SOCKET(s)) {
- krb5_warn(context, rk_SOCK_ERRNO, "accept");
+ if (rk_SOCK_ERRNO != EAGAIN && rk_SOCK_ERRNO != EINTR)
+ krb5_warn(context, rk_SOCK_ERRNO, "accept");
return;
}
@@ -695,7 +694,7 @@ handle_http_tcp (krb5_context context,
free(data);
return -1;
}
- len = base64_decode(t, data);
+ len = rk_base64_decode(t, data);
if(len <= 0){
const char *msg =
" 404 Not found\r\n"
@@ -838,18 +837,67 @@ handle_tcp(krb5_context context,
}
}
-void
-loop(krb5_context context,
- krb5_kdc_configuration *config)
+#ifdef HAVE_FORK
+static void
+handle_islive(int fd)
{
- struct descr *d;
- unsigned int ndescr;
+ char buf;
+ int ret;
- ndescr = init_sockets(context, config, &d);
- if(ndescr <= 0)
- krb5_errx(context, 1, "No sockets!");
- kdc_log(context, config, 0, "KDC started");
- while(exit_flag == 0){
+ ret = read(fd, &buf, 1);
+ if (ret != 1)
+ exit_flag = -1;
+}
+#endif
+
+krb5_boolean
+realloc_descrs(struct descr **d, unsigned int *ndescr)
+{
+ struct descr *tmp;
+ size_t i;
+
+ tmp = realloc(*d, (*ndescr + 4) * sizeof(**d));
+ if(tmp == NULL)
+ return FALSE;
+
+ *d = tmp;
+ reinit_descrs (*d, *ndescr);
+ memset(*d + *ndescr, 0, 4 * sizeof(**d));
+ for(i = *ndescr; i < *ndescr + 4; i++)
+ init_descr (*d + i);
+
+ *ndescr += 4;
+
+ return TRUE;
+}
+
+int
+next_min_free(krb5_context context, struct descr **d, unsigned int *ndescr)
+{
+ size_t i;
+ int min_free;
+
+ for(i = 0; i < *ndescr; i++) {
+ int s = (*d + i)->s;
+ if(rk_IS_BAD_SOCKET(s))
+ return i;
+ }
+
+ min_free = *ndescr;
+ if(!realloc_descrs(d, ndescr)) {
+ min_free = -1;
+ krb5_warnx(context, "No memory");
+ }
+
+ return min_free;
+}
+
+static void
+loop(krb5_context context, krb5_kdc_configuration *config,
+ struct descr *d, unsigned int ndescr, int islive)
+{
+
+ while (exit_flag == 0) {
struct timeval tmout;
fd_set fds;
int min_free = -1;
@@ -857,9 +905,13 @@ loop(krb5_context context,
size_t i;
FD_ZERO(&fds);
- for(i = 0; i < ndescr; i++) {
- if(!rk_IS_BAD_SOCKET(d[i].s)){
- if(d[i].type == SOCK_STREAM &&
+ if (islive > -1) {
+ FD_SET(islive, &fds);
+ max_fd = islive;
+ }
+ for (i = 0; i < ndescr; i++) {
+ if (!rk_IS_BAD_SOCKET(d[i].s)) {
+ if (d[i].type == SOCK_STREAM &&
d[i].timeout && d[i].timeout < time(NULL)) {
kdc_log(context, config, 1,
"TCP-connection from %s expired after %lu bytes",
@@ -868,7 +920,7 @@ loop(krb5_context context,
continue;
}
#ifndef NO_LIMIT_FD_SETSIZE
- if(max_fd < d[i].s)
+ if (max_fd < d[i].s)
max_fd = d[i].s;
#ifdef FD_SETSIZE
if (max_fd >= FD_SETSIZE)
@@ -876,22 +928,6 @@ loop(krb5_context context,
#endif
#endif
FD_SET(d[i].s, &fds);
- } else if(min_free < 0 || i < (size_t)min_free)
- min_free = i;
- }
- if(min_free == -1){
- struct descr *tmp;
- tmp = realloc(d, (ndescr + 4) * sizeof(*d));
- if(tmp == NULL)
- krb5_warnx(context, "No memory");
- else {
- d = tmp;
- reinit_descrs (d, ndescr);
- memset(d + ndescr, 0, 4 * sizeof(*d));
- for(i = ndescr; i < ndescr + 4; i++)
- init_descr (&d[i]);
- min_free = ndescr;
- ndescr += 4;
}
}
@@ -905,23 +941,333 @@ loop(krb5_context context,
krb5_warn(context, rk_SOCK_ERRNO, "select");
break;
default:
- for(i = 0; i < ndescr; i++)
- if(!rk_IS_BAD_SOCKET(d[i].s) && FD_ISSET(d[i].s, &fds)) {
- if(d[i].type == SOCK_DGRAM)
+#ifdef HAVE_FORK
+ if (islive > -1 && FD_ISSET(islive, &fds))
+ handle_islive(islive);
+#endif
+ for (i = 0; i < ndescr; i++)
+ if (!rk_IS_BAD_SOCKET(d[i].s) && FD_ISSET(d[i].s, &fds)) {
+ min_free = next_min_free(context, &d, &ndescr);
+
+ if (d[i].type == SOCK_DGRAM)
handle_udp(context, config, &d[i]);
- else if(d[i].type == SOCK_STREAM)
+ else if (d[i].type == SOCK_STREAM)
handle_tcp(context, config, d, i, min_free);
}
}
}
- if (0);
+
+ switch (exit_flag) {
+ case -1:
+ kdc_log(context, config, 0,
+ "KDC worker process exiting because KDC master exited.");
+ break;
#ifdef SIGXCPU
- else if(exit_flag == SIGXCPU)
+ case SIGXCPU:
kdc_log(context, config, 0, "CPU time limit exceeded");
+ break;
#endif
- else if(exit_flag == SIGINT || exit_flag == SIGTERM)
+ case SIGINT:
+ case SIGTERM:
kdc_log(context, config, 0, "Terminated");
- else
+ break;
+ default:
kdc_log(context, config, 0, "Unexpected exit reason: %d", exit_flag);
- free (d);
+ break;
+ }
+}
+
+#ifdef __APPLE__
+static void
+bonjour_kid(krb5_context context, krb5_kdc_configuration *config, const char *argv0, int *islive)
+{
+ char buf;
+
+ if (do_bonjour > 0) {
+ bonjour_announce(context, config);
+
+ while (read(0, &buf, 1) == 1)
+ continue;
+ _exit(0);
+ }
+
+ if ((bonjour_pid = fork()) != 0)
+ return;
+
+ close(islive[0]);
+ if (dup2(islive[1], 0) == -1)
+ err(1, "failed to announce with bonjour (dup)");
+ if (islive[1] != 0)
+ close(islive[1]);
+ execlp(argv0, "kdc", "--bonjour", NULL);
+ err(1, "failed to announce with bonjour (exec)");
+}
+#endif
+
+#ifdef HAVE_FORK
+static void
+kill_kids(pid_t *pids, int max_kids, int sig)
+{
+ int i;
+
+ for (i=0; i < max_kids; i++)
+ if (pids[i] > 0)
+ kill(sig, pids[i]);
+ if (bonjour_pid > 0)
+ kill(sig, bonjour_pid);
+}
+
+static int
+reap_kid(krb5_context context, krb5_kdc_configuration *config,
+ pid_t *pids, int max_kids, int options)
+{
+ pid_t pid;
+ char *what;
+ int status;
+ int i = 0; /* quiet warnings */
+
+ pid = waitpid(-1, &status, options);
+ if (pid < 1)
+ return 0;
+
+ if (pid != bonjour_pid) {
+ for (i=0; i < max_kids; i++) {
+ if (pids[i] == pid)
+ break;
+ }
+
+ if (i == max_kids) {
+ /* XXXrcd: this should not happen, have to do something, though */
+ return 0;
+ }
+ }
+
+ if (pid == bonjour_pid)
+ what = "bonjour";
+ else
+ what = "worker";
+ if (WIFEXITED(status))
+ kdc_log(context, config, 0, "KDC reaped %s process: %d, exit status: %d",
+ what, (int)pid, WEXITSTATUS(status));
+ else if (WIFSIGNALED(status))
+ kdc_log(context, config, 0, "KDC reaped %s process: %d, term signal %d%s",
+ what, (int)pid, WTERMSIG(status),
+ WCOREDUMP(status) ? " (core dumped)" : "");
+ else
+ kdc_log(context, config, 0, "KDC reaped %s process: %d",
+ what, (int)pid);
+ if (pid == bonjour_pid) {
+ bonjour_pid = (pid_t)-1;
+ return 0;
+ } else {
+ pids[i] = (pid_t)0;
+ return 1;
+ }
+}
+
+static int
+reap_kids(krb5_context context, krb5_kdc_configuration *config,
+ pid_t *pids, int max_kids)
+{
+ int reaped = 0;
+
+ for (;;) {
+ if (reap_kid(context, config, pids, max_kids, WNOHANG) == 0)
+ break;
+ reaped++;
+ }
+
+ return reaped;
+}
+
+static void
+select_sleep(int microseconds)
+{
+ struct timeval tv;
+
+ tv.tv_sec = microseconds / 1000000;
+ tv.tv_usec = microseconds % 1000000;
+ select(0, NULL, NULL, NULL, &tv);
+}
+#endif
+
+void
+start_kdc(krb5_context context,
+ krb5_kdc_configuration *config, const char *argv0)
+{
+ struct timeval tv1;
+ struct timeval tv2;
+ struct descr *d;
+ unsigned int ndescr;
+ pid_t pid = -1;
+#ifdef HAVE_FORK
+ pid_t *pids;
+ int max_kdcs = config->num_kdc_processes;
+ int num_kdcs = 0;
+ int i;
+ int islive[2];
+#endif
+
+#ifdef __APPLE__
+ if (do_bonjour > 0)
+ bonjour_kid(context, config, argv0, NULL);
+#endif
+
+#ifdef HAVE_FORK
+#ifdef _SC_NPROCESSORS_ONLN
+ if (max_kdcs < 1)
+ max_kdcs = sysconf(_SC_NPROCESSORS_ONLN);
+#endif
+
+ if (max_kdcs < 1)
+ max_kdcs = 1;
+
+ pids = calloc(max_kdcs, sizeof(*pids));
+ if (!pids)
+ krb5_err(context, 1, errno, "malloc");
+
+ /*
+ * We open a socketpair of which we hand one end to each of our kids.
+ * When we exit, for whatever reason, the children will notice an EOF
+ * on their end and be able to cleanly exit.
+ */
+
+ if (socketpair(PF_LOCAL, SOCK_STREAM, 0, islive) == -1)
+ krb5_errx(context, 1, "socketpair");
+ socket_set_nonblocking(islive[1], 1);
+#endif
+
+ ndescr = init_sockets(context, config, &d);
+ if(ndescr <= 0)
+ krb5_errx(context, 1, "No sockets!");
+
+#ifdef HAVE_FORK
+
+# ifdef __APPLE__
+ if (do_bonjour < 0)
+ bonjour_kid(context, config, argv0, islive);
+# endif
+
+ kdc_log(context, config, 0, "KDC started master process pid=%d", getpid());
+#else
+ kdc_log(context, config, 0, "KDC started pid=%d", getpid());
+#endif
+
+ roken_detach_finish(NULL, daemon_child);
+
+ tv1.tv_sec = 0;
+ tv1.tv_usec = 0;
+
+#ifdef HAVE_FORK
+ if (!testing_flag) {
+ /* Note that we might never execute the body of this loop */
+ while (exit_flag == 0) {
+
+ /* Slow down the creation of KDCs... */
+
+ gettimeofday(&tv2, NULL);
+ if (tv1.tv_sec == tv2.tv_sec && tv2.tv_usec - tv1.tv_usec < 25000) {
+#if 0 /* XXXrcd: should print a message... */
+ kdc_log(context, config, 0, "Spawning KDCs too quickly, "
+ "pausing for 50ms");
+#endif
+ select_sleep(12500);
+ continue;
+ }
+
+ if (num_kdcs >= max_kdcs) {
+ num_kdcs -= reap_kid(context, config, pids, max_kdcs, 0);
+ continue;
+ }
+
+ if (num_kdcs > 0)
+ num_kdcs -= reap_kids(context, config, pids, max_kdcs);
+
+ pid = fork();
+ switch (pid) {
+ case 0:
+ close(islive[0]);
+ loop(context, config, d, ndescr, islive[1]);
+ exit(0);
+ case -1:
+ /* XXXrcd: hmmm, do something useful?? */
+ kdc_log(context, config, 0,
+ "KDC master process could not fork worker process");
+ sleep(10);
+ break;
+ default:
+ for (i=0; i < max_kdcs; i++) {
+ if (pids[i] == 0) {
+ pids[i] = pid;
+ break;
+ }
+ }
+ kdc_log(context, config, 0, "KDC worker process started: %d",
+ pid);
+ num_kdcs++;
+ gettimeofday(&tv1, NULL);
+ break;
+ }
+ }
+
+ /* Closing these sockets should cause the kids to die... */
+
+ close(islive[0]);
+ close(islive[1]);
+
+ /* Close our listener sockets before terminating workers */
+ for (i = 0; i < ndescr; ++i)
+ clear_descr(&d[i]);
+
+ gettimeofday(&tv1, NULL);
+ tv2 = tv1;
+
+ /* Reap every 10ms, terminate stragglers once a second, give up after 10 */
+ for (;;) {
+ struct timeval tv3;
+ num_kdcs -= reap_kids(context, config, pids, max_kdcs);
+ if (num_kdcs == 0 && bonjour_pid <= 0)
+ goto end;
+ /*
+ * Using select to sleep will fail with EINTR if we receive a
+ * SIGCHLD. This is desirable.
+ */
+ select_sleep(10000);
+ gettimeofday(&tv3, NULL);
+ if (tv3.tv_sec - tv1.tv_sec > 10 ||
+ (tv3.tv_sec - tv1.tv_sec == 10 && tv3.tv_usec >= tv1.tv_usec))
+ break;
+ if (tv3.tv_sec - tv2.tv_sec > 1 ||
+ (tv3.tv_sec - tv2.tv_sec == 1 && tv3.tv_usec >= tv2.tv_usec)) {
+ kill_kids(pids, max_kdcs, SIGTERM);
+ tv2 = tv3;
+ }
+ }
+
+ /* Kill stragglers and reap every 200ms, give up after 15s */
+ for (;;) {
+ kill_kids(pids, max_kdcs, SIGKILL);
+ num_kdcs -= reap_kids(context, config, pids, max_kdcs);
+ if (num_kdcs == 0 && bonjour_pid <= 0)
+ break;
+ select_sleep(200000);
+ gettimeofday(&tv2, NULL);
+ if (tv2.tv_sec - tv1.tv_sec > 15 ||
+ (tv2.tv_sec - tv1.tv_sec == 15 && tv2.tv_usec >= tv1.tv_usec))
+ break;
+ }
+
+ end:
+ kdc_log(context, config, 0, "KDC master process exiting", pid);
+ free(pids);
+ } else {
+ loop(context, config, d, ndescr, -1);
+ kdc_log(context, config, 0, "KDC exiting", pid);
+ }
+#else
+ loop(context, config, d, ndescr, -1);
+ kdc_log(context, config, 0, "KDC exiting", pid);
+#endif
+
+ free(d);
}
diff --git a/kdc/default_config.c b/kdc/default_config.c
index 9a33a7f270c0..63b4681f0ea2 100644
--- a/kdc/default_config.c
+++ b/kdc/default_config.c
@@ -48,6 +48,7 @@ krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config)
return ENOMEM;
}
+ c->num_kdc_processes = -1;
c->require_preauth = TRUE;
c->kdc_warn_pwexpire = 0;
c->encode_as_rep_as_tgs_rep = FALSE;
@@ -58,6 +59,7 @@ krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config)
c->check_ticket_addresses = TRUE;
c->allow_null_ticket_addresses = TRUE;
c->allow_anonymous = FALSE;
+ c->strict_nametypes = FALSE;
c->trpolicy = TRPOLICY_ALWAYS_CHECK;
c->enable_pkinit = FALSE;
c->pkinit_princ_in_cert = TRUE;
@@ -66,6 +68,10 @@ krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config)
c->num_db = 0;
c->logf = NULL;
+ c->num_kdc_processes =
+ krb5_config_get_int_default(context, NULL, c->num_kdc_processes,
+ "kdc", "num-kdc-processes", NULL);
+
c->require_preauth =
krb5_config_get_bool_default(context, NULL,
c->require_preauth,
@@ -158,6 +164,12 @@ krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config)
"kdc",
"allow-anonymous", NULL);
+ c->strict_nametypes =
+ krb5_config_get_bool_default(context, NULL,
+ c->strict_nametypes,
+ "kdc",
+ "strict-nametypes", NULL);
+
c->max_datagram_reply_length =
krb5_config_get_int_default(context,
NULL,
diff --git a/kdc/digest-service.c b/kdc/digest-service.c
index 4d339a2ddd35..0115866503d0 100644
--- a/kdc/digest-service.c
+++ b/kdc/digest-service.c
@@ -44,6 +44,8 @@
typedef struct pk_client_params pk_client_params;
struct DigestREQ;
struct Kx509Request;
+typedef struct kdc_request_desc *kdc_request_t;
+
#include <kdc-private.h>
krb5_kdc_configuration *config;
@@ -116,7 +118,7 @@ ntlm_service(void *ctx, const heim_idata *req,
if (ret)
goto failed;
- ret = hdb_enctype2key(context, &user->entry,
+ ret = hdb_enctype2key(context, &user->entry, NULL,
ETYPE_ARCFOUR_HMAC_MD5, &key);
if (ret) {
krb5_set_error_message(context, ret, "NTLM missing arcfour key");
diff --git a/kdc/digest.c b/kdc/digest.c
index 5f0d27441a23..295189c66f2b 100644
--- a/kdc/digest.c
+++ b/kdc/digest.c
@@ -238,7 +238,7 @@ _kdc_do_digest(krb5_context context,
kdc_log(context, config, 0, "Digest request from %s", from);
- ret = krb5_kt_resolve(context, "HDB:", &id);
+ ret = krb5_kt_resolve(context, "HDBGET:", &id);
if (ret) {
kdc_log(context, config, 0, "Can't open database for digest");
goto out;
@@ -406,11 +406,12 @@ _kdc_do_digest(krb5_context context,
if (ireq.u.init.channel) {
char *s;
+ int aret;
- asprintf(&s, "%s-%s:%s", r.u.initReply.nonce,
- ireq.u.init.channel->cb_type,
- ireq.u.init.channel->cb_binding);
- if (s == NULL) {
+ aret = asprintf(&s, "%s-%s:%s", r.u.initReply.nonce,
+ ireq.u.init.channel->cb_type,
+ ireq.u.init.channel->cb_binding);
+ if (aret == -1 || s == NULL) {
ret = ENOMEM;
krb5_set_error_message(context, ret,
"Failed to allocate channel binding");
@@ -427,6 +428,8 @@ _kdc_do_digest(krb5_context context,
}
if (strcasecmp(ireq.u.init.type, "CHAP") == 0) {
+ int aret;
+
r.u.initReply.identifier =
malloc(sizeof(*r.u.initReply.identifier));
if (r.u.initReply.identifier == NULL) {
@@ -435,8 +438,8 @@ _kdc_do_digest(krb5_context context,
goto out;
}
- asprintf(r.u.initReply.identifier, "%02X", identifier & 0xff);
- if (*r.u.initReply.identifier == NULL) {
+ aret = asprintf(r.u.initReply.identifier, "%02X", identifier&0xff);
+ if (aret == -1 || *r.u.initReply.identifier == NULL) {
ret = ENOMEM;
krb5_set_error_message(context, ret, "malloc: out of memory");
goto out;
@@ -605,7 +608,7 @@ _kdc_do_digest(krb5_context context,
}
t = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
- if (abs((kdc_time & 0xffffffff) - t) > context->max_skew) {
+ if (labs((kdc_time & 0xffffffff) - t) > context->max_skew) {
ret = EINVAL;
krb5_set_error_message(context, ret, "time screw in server nonce ");
goto out;
@@ -798,7 +801,7 @@ _kdc_do_digest(krb5_context context,
}
} else if (strcasecmp(ireq.u.digestRequest.type, "MS-CHAP-V2") == 0) {
- unsigned char md[SHA_DIGEST_LENGTH], challange[SHA_DIGEST_LENGTH];
+ unsigned char md[SHA_DIGEST_LENGTH], challenge[SHA_DIGEST_LENGTH];
krb5_principal clientprincipal = NULL;
char *mdx;
const char *username;
@@ -833,7 +836,7 @@ _kdc_do_digest(krb5_context context,
ctp = EVP_MD_CTX_create();
- /* ChallangeHash */
+ /* ChallengeHash */
EVP_DigestInit_ex(ctp, EVP_sha1(), NULL);
{
ssize_t ssize;
@@ -864,7 +867,7 @@ _kdc_do_digest(krb5_context context,
EVP_DigestUpdate(ctp, serverNonce.data, serverNonce.length);
EVP_DigestUpdate(ctp, username, strlen(username));
- EVP_DigestFinal_ex(ctp, challange, NULL);
+ EVP_DigestFinal_ex(ctp, challenge, NULL);
EVP_MD_CTX_destroy(ctp);
@@ -883,7 +886,7 @@ _kdc_do_digest(krb5_context context,
goto failed;
}
- ret = hdb_enctype2key(context, &user->entry,
+ ret = hdb_enctype2key(context, &user->entry, NULL,
ETYPE_ARCFOUR_HMAC_MD5, &key);
if (ret) {
krb5_set_error_message(context, ret,
@@ -895,7 +898,7 @@ _kdc_do_digest(krb5_context context,
/* ChallengeResponse */
ret = heim_ntlm_calculate_ntlm1(key->key.keyvalue.data,
key->key.keyvalue.length,
- challange, &answer);
+ challenge, &answer);
if (ret) {
krb5_set_error_message(context, ret, "NTLM missing arcfour key");
goto failed;
@@ -946,7 +949,7 @@ _kdc_do_digest(krb5_context context,
EVP_DigestInit_ex(ctxp, EVP_sha1(), NULL);
EVP_DigestUpdate(ctxp, md, sizeof(md));
- EVP_DigestUpdate(ctxp, challange, 8);
+ EVP_DigestUpdate(ctxp, challenge, 8);
EVP_DigestUpdate(ctxp, ms_chap_v2_magic2,
sizeof(ms_chap_v2_magic2));
EVP_DigestFinal_ex(ctxp, md, NULL);
@@ -997,10 +1000,12 @@ _kdc_do_digest(krb5_context context,
}
} else {
+ int aret;
+
r.element = choice_DigestRepInner_error;
- asprintf(&r.u.error.reason, "Unsupported digest type %s",
- ireq.u.digestRequest.type);
- if (r.u.error.reason == NULL) {
+ aret = asprintf(&r.u.error.reason, "Unsupported digest type %s",
+ ireq.u.digestRequest.type);
+ if (aret == -1 || r.u.error.reason == NULL) {
ret = ENOMEM;
krb5_set_error_message(context, ret, "malloc: out of memory");
goto out;
@@ -1059,15 +1064,15 @@ _kdc_do_digest(krb5_context context,
krb5_set_error_message(context, ret, "malloc: out of memory");
goto out;
}
- r.u.ntlmInitReply.challange.data = malloc(8);
- if (r.u.ntlmInitReply.challange.data == NULL) {
+ r.u.ntlmInitReply.challenge.data = malloc(8);
+ if (r.u.ntlmInitReply.challenge.data == NULL) {
ret = ENOMEM;
krb5_set_error_message(context, ret, "malloc: out of memory");
goto out;
}
- r.u.ntlmInitReply.challange.length = 8;
- if (RAND_bytes(r.u.ntlmInitReply.challange.data,
- r.u.ntlmInitReply.challange.length) != 1)
+ r.u.ntlmInitReply.challenge.length = 8;
+ if (RAND_bytes(r.u.ntlmInitReply.challenge.data,
+ r.u.ntlmInitReply.challenge.length) != 1)
{
ret = ENOMEM;
krb5_set_error_message(context, ret, "out of random error");
@@ -1102,10 +1107,10 @@ _kdc_do_digest(krb5_context context,
goto out;
}
- ret = krb5_storage_write(sp, r.u.ntlmInitReply.challange.data, 8);
+ ret = krb5_storage_write(sp, r.u.ntlmInitReply.challenge.data, 8);
if (ret != 8) {
ret = ENOMEM;
- krb5_set_error_message(context, ret, "storage write challange");
+ krb5_set_error_message(context, ret, "storage write challenge");
goto out;
}
ret = krb5_store_uint32(sp, r.u.ntlmInitReply.flags);
@@ -1139,7 +1144,7 @@ _kdc_do_digest(krb5_context context,
case choice_DigestReqInner_ntlmRequest: {
krb5_principal clientprincipal;
unsigned char sessionkey[16];
- unsigned char challange[8];
+ unsigned char challenge[8];
uint32_t flags;
Key *key = NULL;
int version;
@@ -1188,10 +1193,10 @@ _kdc_do_digest(krb5_context context,
goto out;
}
- ret = krb5_storage_read(sp, challange, sizeof(challange));
- if (ret != sizeof(challange)) {
+ ret = krb5_storage_read(sp, challenge, sizeof(challenge));
+ if (ret != sizeof(challenge)) {
ret = ENOMEM;
- krb5_set_error_message(context, ret, "NTLM storage read challange");
+ krb5_set_error_message(context, ret, "NTLM storage read challenge");
goto out;
}
ret = krb5_ret_uint32(sp, &flags);
@@ -1209,7 +1214,7 @@ _kdc_do_digest(krb5_context context,
goto out;
}
- ret = hdb_enctype2key(context, &user->entry,
+ ret = hdb_enctype2key(context, &user->entry, NULL,
ETYPE_ARCFOUR_HMAC_MD5, &key);
if (ret) {
krb5_set_error_message(context, ret, "NTLM missing arcfour key");
@@ -1243,7 +1248,7 @@ _kdc_do_digest(krb5_context context,
ireq.u.ntlmRequest.username,
targetname,
0,
- challange,
+ challenge,
&answer,
&infotarget,
sessionkey);
@@ -1284,10 +1289,10 @@ _kdc_do_digest(krb5_context context,
EVP_DigestInit_ex(ctx, EVP_md5(), NULL);
- EVP_DigestUpdate(ctx, challange, sizeof(challange));
+ EVP_DigestUpdate(ctx, challenge, sizeof(challenge));
EVP_DigestUpdate(ctx, ireq.u.ntlmRequest.lm.data, 8);
EVP_DigestFinal_ex(ctx, sessionhash, NULL);
- memcpy(challange, sessionhash, sizeof(challange));
+ memcpy(challenge, sessionhash, sizeof(challenge));
EVP_MD_CTX_destroy(ctx);
@@ -1300,7 +1305,7 @@ _kdc_do_digest(krb5_context context,
ret = heim_ntlm_calculate_ntlm1(key->key.keyvalue.data,
key->key.keyvalue.length,
- challange, &answer);
+ challenge, &answer);
if (ret) {
krb5_set_error_message(context, ret, "NTLM missing arcfour key");
goto failed;
diff --git a/kdc/fast.c b/kdc/fast.c
new file mode 100644
index 000000000000..3b3621037abd
--- /dev/null
+++ b/kdc/fast.c
@@ -0,0 +1,560 @@
+/*
+ * Copyright (c) 1997-2011 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Portions Copyright (c) 2010 - 2011 Apple Inc. 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 "kdc_locl.h"
+
+static krb5_error_code
+get_fastuser_crypto(kdc_request_t r, krb5_enctype enctype, krb5_crypto *crypto)
+{
+ krb5_principal fast_princ;
+ hdb_entry_ex *fast_user = NULL;
+ Key *cookie_key = NULL;
+ krb5_error_code ret;
+
+ *crypto = NULL;
+
+ ret = krb5_make_principal(r->context, &fast_princ,
+ KRB5_WELLKNOWN_ORG_H5L_REALM,
+ KRB5_WELLKNOWN_NAME, "org.h5l.fast-cookie", NULL);
+ if (ret)
+ goto out;
+
+ ret = _kdc_db_fetch(r->context, r->config, fast_princ,
+ HDB_F_GET_CLIENT, NULL, NULL, &fast_user);
+ krb5_free_principal(r->context, fast_princ);
+ if (ret)
+ goto out;
+
+ if (enctype == KRB5_ENCTYPE_NULL)
+ ret = _kdc_get_preferred_key(r->context, r->config, fast_user,
+ "fast-cookie", &enctype, &cookie_key);
+ else
+ ret = hdb_enctype2key(r->context, &fast_user->entry, NULL,
+ enctype, &cookie_key);
+ if (ret)
+ goto out;
+
+ ret = krb5_crypto_init(r->context, &cookie_key->key, 0, crypto);
+ if (ret)
+ goto out;
+
+ out:
+ if (fast_user)
+ _kdc_free_ent(r->context, fast_user);
+
+ return ret;
+}
+
+
+static krb5_error_code
+fast_parse_cookie(kdc_request_t r, const PA_DATA *pa)
+{
+ krb5_crypto crypto = NULL;
+ krb5_error_code ret;
+ KDCFastCookie data;
+ krb5_data d1;
+ size_t len;
+
+ ret = decode_KDCFastCookie(pa->padata_value.data,
+ pa->padata_value.length,
+ &data, &len);
+ if (ret)
+ return ret;
+
+ if (len != pa->padata_value.length || strcmp("H5L1", data.version) != 0) {
+ free_KDCFastCookie(&data);
+ return KRB5KDC_ERR_POLICY;
+ }
+
+ ret = get_fastuser_crypto(r, data.cookie.etype, &crypto);
+ if (ret)
+ goto out;
+
+ ret = krb5_decrypt_EncryptedData(r->context, crypto,
+ KRB5_KU_H5L_COOKIE,
+ &data.cookie, &d1);
+ krb5_crypto_destroy(r->context, crypto);
+ if (ret)
+ goto out;
+
+ ret = decode_KDCFastState(d1.data, d1.length, &r->fast, &len);
+ krb5_data_free(&d1);
+ if (ret)
+ goto out;
+
+ if (r->fast.expiration < kdc_time) {
+ kdc_log(r->context, r->config, 0, "fast cookie expired");
+ ret = KRB5KDC_ERR_POLICY;
+ goto out;
+ }
+
+ out:
+ free_KDCFastCookie(&data);
+
+ return ret;
+}
+
+static krb5_error_code
+fast_add_cookie(kdc_request_t r, METHOD_DATA *method_data)
+{
+ krb5_crypto crypto = NULL;
+ KDCFastCookie shell;
+ krb5_error_code ret;
+ krb5_data data;
+ size_t size;
+
+ memset(&shell, 0, sizeof(shell));
+
+ r->fast.expiration = kdc_time + FAST_EXPIRATION_TIME;
+
+ ASN1_MALLOC_ENCODE(KDCFastState, data.data, data.length,
+ &r->fast, &size, ret);
+ if (ret)
+ return ret;
+ heim_assert(size == data.length, "internal asn1 encoder error");
+
+ ret = get_fastuser_crypto(r, KRB5_ENCTYPE_NULL, &crypto);
+ if (ret)
+ goto out;
+
+ ret = krb5_encrypt_EncryptedData(r->context, crypto,
+ KRB5_KU_H5L_COOKIE,
+ data.data, data.length, 0,
+ &shell.cookie);
+ krb5_crypto_destroy(r->context, crypto);
+ if (ret)
+ goto out;
+
+ free(data.data);
+
+ shell.version = "H5L1";
+
+ ASN1_MALLOC_ENCODE(KDCFastCookie, data.data, data.length,
+ &shell, &size, ret);
+ free_EncryptedData(&shell.cookie);
+ if (ret)
+ goto out;
+ heim_assert(size == data.length, "internal asn1 encoder error");
+
+ ret = krb5_padata_add(r->context, method_data,
+ KRB5_PADATA_FX_COOKIE,
+ data.data, data.length);
+ out:
+ if (ret)
+ free(data.data);
+ return ret;
+}
+
+krb5_error_code
+_kdc_fast_mk_response(krb5_context context,
+ krb5_crypto armor_crypto,
+ METHOD_DATA *pa_data,
+ krb5_keyblock *strengthen_key,
+ KrbFastFinished *finished,
+ krb5uint32 nonce,
+ krb5_data *data)
+{
+ PA_FX_FAST_REPLY fxfastrep;
+ KrbFastResponse fastrep;
+ krb5_error_code ret;
+ krb5_data buf;
+ size_t size;
+
+ memset(&fxfastrep, 0, sizeof(fxfastrep));
+ memset(&fastrep, 0, sizeof(fastrep));
+ krb5_data_zero(data);
+
+ if (pa_data) {
+ fastrep.padata.val = pa_data->val;
+ fastrep.padata.len = pa_data->len;
+ }
+ fastrep.strengthen_key = strengthen_key;
+ fastrep.finished = finished;
+ fastrep.nonce = nonce;
+
+ ASN1_MALLOC_ENCODE(KrbFastResponse, buf.data, buf.length,
+ &fastrep, &size, ret);
+ if (ret)
+ return ret;
+ if (buf.length != size)
+ krb5_abortx(context, "internal asn.1 error");
+
+ fxfastrep.element = choice_PA_FX_FAST_REPLY_armored_data;
+
+ ret = krb5_encrypt_EncryptedData(context,
+ armor_crypto,
+ KRB5_KU_FAST_REP,
+ buf.data,
+ buf.length,
+ 0,
+ &fxfastrep.u.armored_data.enc_fast_rep);
+ krb5_data_free(&buf);
+ if (ret)
+ return ret;
+
+ ASN1_MALLOC_ENCODE(PA_FX_FAST_REPLY, data->data, data->length,
+ &fxfastrep, &size, ret);
+ free_PA_FX_FAST_REPLY(&fxfastrep);
+ if (ret)
+ return ret;
+ if (data->length != size)
+ krb5_abortx(context, "internal asn.1 error");
+
+ return 0;
+}
+
+
+krb5_error_code
+_kdc_fast_mk_error(krb5_context context,
+ kdc_request_t r,
+ METHOD_DATA *error_method,
+ krb5_crypto armor_crypto,
+ const KDC_REQ_BODY *req_body,
+ krb5_error_code outer_error,
+ const char *e_text,
+ krb5_principal error_server,
+ const PrincipalName *error_client_name,
+ const Realm *error_client_realm,
+ time_t *csec, int *cusec,
+ krb5_data *error_msg)
+{
+ krb5_error_code ret;
+ krb5_data e_data;
+ size_t size;
+
+ krb5_data_zero(&e_data);
+
+ if (armor_crypto) {
+ PA_FX_FAST_REPLY fxfastrep;
+ KrbFastResponse fastrep;
+
+ memset(&fxfastrep, 0, sizeof(fxfastrep));
+ memset(&fastrep, 0, sizeof(fastrep));
+
+ /* first add the KRB-ERROR to the fast errors */
+
+ ret = krb5_mk_error_ext(context,
+ outer_error,
+ e_text,
+ NULL,
+ error_server,
+ error_client_name,
+ error_client_realm,
+ NULL,
+ NULL,
+ &e_data);
+ if (ret)
+ return ret;
+
+ ret = krb5_padata_add(context, error_method,
+ KRB5_PADATA_FX_ERROR,
+ e_data.data, e_data.length);
+ if (ret) {
+ krb5_data_free(&e_data);
+ return ret;
+ }
+
+ if (/* hide_principal */ 0) {
+ error_client_name = NULL;
+ error_client_realm = NULL;
+ error_server = NULL;
+ e_text = NULL;
+ }
+
+ if (r)
+ ret = fast_add_cookie(r, error_method);
+ else
+ ret = krb5_padata_add(context, error_method,
+ KRB5_PADATA_FX_COOKIE,
+ NULL, 0);
+ if (ret) {
+ kdc_log(r->context, r->config, 0, "failed to add fast cookie with: %d", ret);
+ free_METHOD_DATA(error_method);
+ return ret;
+ }
+
+ ret = _kdc_fast_mk_response(context, armor_crypto,
+ error_method, NULL, NULL,
+ req_body->nonce, &e_data);
+ free_METHOD_DATA(error_method);
+ if (ret)
+ return ret;
+
+ ret = krb5_padata_add(context, error_method,
+ KRB5_PADATA_FX_FAST,
+ e_data.data, e_data.length);
+ if (ret)
+ return ret;
+ }
+
+ if (error_method && error_method->len) {
+ ASN1_MALLOC_ENCODE(METHOD_DATA, e_data.data, e_data.length,
+ error_method, &size, ret);
+ if (ret)
+ return ret;
+ if (e_data.length != size)
+ krb5_abortx(context, "internal asn.1 error");
+ }
+
+ ret = krb5_mk_error_ext(context,
+ outer_error,
+ e_text,
+ (e_data.length ? &e_data : NULL),
+ error_server,
+ error_client_name,
+ error_client_realm,
+ csec,
+ cusec,
+ error_msg);
+ krb5_data_free(&e_data);
+
+ return ret;
+}
+
+krb5_error_code
+_kdc_fast_unwrap_request(kdc_request_t r)
+{
+ krb5_principal armor_server = NULL;
+ hdb_entry_ex *armor_user = NULL;
+ PA_FX_FAST_REQUEST fxreq;
+ krb5_auth_context ac = NULL;
+ krb5_ticket *ticket = NULL;
+ krb5_flags ap_req_options;
+ Key *armor_key = NULL;
+ krb5_keyblock armorkey;
+ krb5_error_code ret;
+ krb5_ap_req ap_req;
+ unsigned char *buf = NULL;
+ KrbFastReq fastreq;
+ size_t len, size;
+ krb5_data data;
+ const PA_DATA *pa;
+ int i = 0;
+
+ /*
+ * First look for FX_COOKIE and and process it
+ */
+ pa = _kdc_find_padata(&r->req, &i, KRB5_PADATA_FX_COOKIE);
+ if (pa) {
+ ret = fast_parse_cookie(r, pa);
+ if (ret)
+ goto out;
+ }
+
+ i = 0;
+ pa = _kdc_find_padata(&r->req, &i, KRB5_PADATA_FX_FAST);
+ if (pa == NULL)
+ return 0;
+
+ ret = decode_PA_FX_FAST_REQUEST(pa->padata_value.data,
+ pa->padata_value.length,
+ &fxreq,
+ &len);
+ if (ret)
+ goto out;
+ if (len != pa->padata_value.length) {
+ ret = KRB5KDC_ERR_PREAUTH_FAILED;
+ goto out;
+ }
+
+ if (fxreq.element != choice_PA_FX_FAST_REQUEST_armored_data) {
+ kdc_log(r->context, r->config, 0,
+ "AS-REQ FAST contain unknown type: %d", (int)fxreq.element);
+ ret = KRB5KDC_ERR_PREAUTH_FAILED;
+ goto out;
+ }
+
+ /* pull out armor key */
+ if (fxreq.u.armored_data.armor == NULL) {
+ kdc_log(r->context, r->config, 0,
+ "AS-REQ armor missing");
+ ret = KRB5KDC_ERR_PREAUTH_FAILED;
+ goto out;
+ }
+
+ if (fxreq.u.armored_data.armor->armor_type != 1) {
+ kdc_log(r->context, r->config, 0,
+ "AS-REQ armor type not ap-req");
+ ret = KRB5KDC_ERR_PREAUTH_FAILED;
+ goto out;
+ }
+
+ ret = krb5_decode_ap_req(r->context,
+ &fxreq.u.armored_data.armor->armor_value,
+ &ap_req);
+ if(ret) {
+ kdc_log(r->context, r->config, 0, "AP-REQ decode failed");
+ goto out;
+ }
+
+ /* Save that principal that was in the request */
+ ret = _krb5_principalname2krb5_principal(r->context,
+ &armor_server,
+ ap_req.ticket.sname,
+ ap_req.ticket.realm);
+ if (ret) {
+ free_AP_REQ(&ap_req);
+ goto out;
+ }
+
+ ret = _kdc_db_fetch(r->context, r->config, armor_server,
+ HDB_F_GET_SERVER, NULL, NULL, &armor_user);
+ if(ret == HDB_ERR_NOT_FOUND_HERE) {
+ kdc_log(r->context, r->config, 5,
+ "armor key does not have secrets at this KDC, "
+ "need to proxy");
+ goto out;
+ } else if (ret) {
+ free_AP_REQ(&ap_req);
+ ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
+ goto out;
+ }
+
+ ret = hdb_enctype2key(r->context, &armor_user->entry, NULL,
+ ap_req.ticket.enc_part.etype,
+ &armor_key);
+ if (ret) {
+ free_AP_REQ(&ap_req);
+ goto out;
+ }
+
+ ret = krb5_verify_ap_req2(r->context, &ac,
+ &ap_req,
+ armor_server,
+ &armor_key->key,
+ 0,
+ &ap_req_options,
+ &ticket,
+ KRB5_KU_AP_REQ_AUTH);
+ free_AP_REQ(&ap_req);
+ if (ret)
+ goto out;
+
+ if (ac->remote_subkey == NULL) {
+ krb5_auth_con_free(r->context, ac);
+ kdc_log(r->context, r->config, 0,
+ "FAST AP-REQ remote subkey missing");
+ ret = KRB5KDC_ERR_PREAUTH_FAILED;
+ goto out;
+ }
+
+ ret = _krb5_fast_armor_key(r->context,
+ ac->remote_subkey,
+ &ticket->ticket.key,
+ &armorkey,
+ &r->armor_crypto);
+ krb5_auth_con_free(r->context, ac);
+ krb5_free_ticket(r->context, ticket);
+ if (ret)
+ goto out;
+
+ krb5_free_keyblock_contents(r->context, &armorkey);
+
+ /* verify req-checksum of the outer body */
+
+ ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, len, &r->req.req_body, &size, ret);
+ if (ret)
+ goto out;
+ if (size != len) {
+ ret = KRB5KDC_ERR_PREAUTH_FAILED;
+ goto out;
+ }
+
+ ret = krb5_verify_checksum(r->context, r->armor_crypto,
+ KRB5_KU_FAST_REQ_CHKSUM,
+ buf, len,
+ &fxreq.u.armored_data.req_checksum);
+ if (ret) {
+ kdc_log(r->context, r->config, 0,
+ "FAST request have a bad checksum");
+ goto out;
+ }
+
+ ret = krb5_decrypt_EncryptedData(r->context, r->armor_crypto,
+ KRB5_KU_FAST_ENC,
+ &fxreq.u.armored_data.enc_fast_req,
+ &data);
+ if (ret) {
+ kdc_log(r->context, r->config, 0,
+ "Failed to decrypt FAST request");
+ goto out;
+ }
+
+ ret = decode_KrbFastReq(data.data, data.length, &fastreq, &size);
+ if (ret) {
+ krb5_data_free(&data);
+ goto out;
+ }
+ if (data.length != size) {
+ krb5_data_free(&data);
+ ret = KRB5KDC_ERR_PREAUTH_FAILED;
+ goto out;
+ }
+ krb5_data_free(&data);
+
+ free_KDC_REQ_BODY(&r->req.req_body);
+ ret = copy_KDC_REQ_BODY(&fastreq.req_body, &r->req.req_body);
+ if (ret)
+ goto out;
+
+ /* check for unsupported mandatory options */
+ if (FastOptions2int(fastreq.fast_options) & 0xfffc) {
+ kdc_log(r->context, r->config, 0,
+ "FAST unsupported mandatory option set");
+ ret = KRB5KDC_ERR_PREAUTH_FAILED;
+ goto out;
+ }
+
+ /* KDC MUST ignore outer pa data preauth-14 - 6.5.5 */
+ if (r->req.padata)
+ free_METHOD_DATA(r->req.padata);
+ else
+ ALLOC(r->req.padata);
+
+ ret = copy_METHOD_DATA(&fastreq.padata, r->req.padata);
+ if (ret)
+ goto out;
+
+ free_KrbFastReq(&fastreq);
+ free_PA_FX_FAST_REQUEST(&fxreq);
+
+ out:
+ if (armor_server)
+ krb5_free_principal(r->context, armor_server);
+ if(armor_user)
+ _kdc_free_ent(r->context, armor_user);
+
+ return ret;
+}
diff --git a/kdc/headers.h b/kdc/headers.h
index aced5ce61707..d4185a8c6fe2 100644
--- a/kdc/headers.h
+++ b/kdc/headers.h
@@ -47,6 +47,9 @@
#include <errno.h>
#include <signal.h>
#include <stdarg.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
@@ -106,6 +109,8 @@
#include <kdc.h>
#include <windc_plugin.h>
+#include <heimbase.h>
+
#undef ALLOC
#define ALLOC(X) ((X) = calloc(1, sizeof(*(X))))
#undef ALLOC_SEQ
diff --git a/kdc/hprop.c b/kdc/hprop.c
index b68f159ef234..880a6f746406 100644
--- a/kdc/hprop.c
+++ b/kdc/hprop.c
@@ -161,7 +161,7 @@ get_creds(krb5_context context, krb5_ccache *cache)
krb5_preauthtype preauth = KRB5_PADATA_ENC_TIMESTAMP;
krb5_creds creds;
- ret = krb5_kt_register(context, &hdb_kt_ops);
+ ret = krb5_kt_register(context, &hdb_get_kt_ops);
if(ret) krb5_err(context, 1, ret, "krb5_kt_register");
ret = krb5_kt_resolve(context, ktname, &keytab);
@@ -341,7 +341,6 @@ propagate_database (krb5_context context, int type,
if(ret) {
failed++;
krb5_warn(context, ret, "krb5_sendauth (%s)", host);
- close(fd);
goto next_host;
}
diff --git a/kdc/hprop.h b/kdc/hprop.h
index 59fe8bc16934..426bf6ed7fd5 100644
--- a/kdc/hprop.h
+++ b/kdc/hprop.h
@@ -46,7 +46,7 @@ struct prop_data{
#define HPROP_VERSION "hprop-0.0"
#define HPROP_NAME "hprop"
-#define HPROP_KEYTAB "HDB:"
+#define HPROP_KEYTAB "HDBGET:"
#define HPROP_PORT 754
#ifndef NEVERDATE
diff --git a/kdc/hpropd.c b/kdc/hpropd.c
index 75b26a15f501..a931d7f6893a 100644
--- a/kdc/hpropd.c
+++ b/kdc/hpropd.c
@@ -85,23 +85,23 @@ main(int argc, char **argv)
setprogname(argv[0]);
ret = krb5_init_context(&context);
- if(ret)
+ if (ret)
exit(1);
ret = krb5_openlog(context, "hpropd", &fac);
- if(ret)
+ if (ret)
errx(1, "krb5_openlog");
krb5_set_warn_dest(context, fac);
- if(getarg(args, num_args, argc, argv, &optidx))
+ if (getarg(args, num_args, argc, argv, &optidx))
usage(1);
- if(local_realm != NULL)
+ if (local_realm != NULL)
krb5_set_default_realm(context, local_realm);
- if(help_flag)
+ if (help_flag)
usage(0);
- if(version_flag) {
+ if (version_flag) {
print_version(NULL);
exit(0);
}
@@ -115,7 +115,7 @@ main(int argc, char **argv)
if (database == NULL)
database = hdb_default_db(context);
- if(from_stdin) {
+ if (from_stdin) {
sock = STDIN_FILENO;
} else {
struct sockaddr_storage ss;
@@ -142,10 +142,10 @@ main(int argc, char **argv)
HPROP_PORT), &sock);
}
sin_len = sizeof(ss);
- if(getpeername(sock, sa, &sin_len) < 0)
+ if (getpeername(sock, sa, &sin_len) < 0)
krb5_err(context, 1, errno, "getpeername");
- if (inet_ntop(sa->sa_family,
+ if (inet_ntop(ss.ss_family,
socket_get_address (sa),
addr_name,
sizeof(addr_name)) == NULL)
@@ -154,8 +154,8 @@ main(int argc, char **argv)
krb5_log(context, fac, 0, "Connection from %s", addr_name);
- ret = krb5_kt_register(context, &hdb_kt_ops);
- if(ret)
+ ret = krb5_kt_register(context, &hdb_get_kt_ops);
+ if (ret)
krb5_err(context, 1, ret, "krb5_kt_register");
if (ktname != NULL) {
@@ -170,7 +170,7 @@ main(int argc, char **argv)
ret = krb5_recvauth(context, &ac, &sock, HPROP_VERSION, NULL,
0, keytab, &ticket);
- if(ret)
+ if (ret)
krb5_err(context, 1, ret, "krb5_recvauth");
ret = krb5_unparse_name(context, ticket->server, &server);
@@ -183,15 +183,15 @@ main(int argc, char **argv)
krb5_free_ticket (context, ticket);
ret = krb5_auth_con_getauthenticator(context, ac, &authent);
- if(ret)
+ if (ret)
krb5_err(context, 1, ret, "krb5_auth_con_getauthenticator");
ret = krb5_make_principal(context, &c1, NULL, "kadmin", "hprop", NULL);
- if(ret)
+ if (ret)
krb5_err(context, 1, ret, "krb5_make_principal");
_krb5_principalname2krb5_principal(context, &c2,
authent->cname, authent->crealm);
- if(!krb5_principal_compare(context, c1, c2)) {
+ if (!krb5_principal_compare(context, c1, c2)) {
char *s;
ret = krb5_unparse_name(context, c2, &s);
if (ret)
@@ -202,48 +202,52 @@ main(int argc, char **argv)
krb5_free_principal(context, c2);
ret = krb5_kt_close(context, keytab);
- if(ret)
+ if (ret)
krb5_err(context, 1, ret, "krb5_kt_close");
}
- if(!print_dump) {
- asprintf(&tmp_db, "%s~", database);
+ if (!print_dump) {
+ int aret;
+
+ aret = asprintf(&tmp_db, "%s~", database);
+ if (aret == -1)
+ krb5_errx(context, 1, "hdb_create: out of memory");
ret = hdb_create(context, &db, tmp_db);
- if(ret)
+ if (ret)
krb5_err(context, 1, ret, "hdb_create(%s)", tmp_db);
ret = db->hdb_open(context, db, O_RDWR | O_CREAT | O_TRUNC, 0600);
- if(ret)
+ if (ret)
krb5_err(context, 1, ret, "hdb_open(%s)", tmp_db);
}
nprincs = 0;
- while(1){
+ while (1){
krb5_data data;
hdb_entry_ex entry;
- if(from_stdin) {
+ if (from_stdin) {
ret = krb5_read_message(context, &sock, &data);
- if(ret != 0 && ret != HEIM_ERR_EOF)
+ if (ret != 0 && ret != HEIM_ERR_EOF)
krb5_err(context, 1, ret, "krb5_read_message");
} else {
ret = krb5_read_priv_message(context, ac, &sock, &data);
- if(ret)
+ if (ret)
krb5_err(context, 1, ret, "krb5_read_priv_message");
}
- if(ret == HEIM_ERR_EOF || data.length == 0) {
- if(!from_stdin) {
+ if (ret == HEIM_ERR_EOF || data.length == 0) {
+ if (!from_stdin) {
data.data = NULL;
data.length = 0;
krb5_write_priv_message(context, ac, &sock, &data);
}
- if(!print_dump) {
+ if (!print_dump) {
ret = db->hdb_close(context, db);
- if(ret)
+ if (ret)
krb5_err(context, 1, ret, "db_close");
ret = db->hdb_rename(context, db, database);
- if(ret)
+ if (ret)
krb5_err(context, 1, ret, "db_rename");
}
break;
@@ -251,20 +255,24 @@ main(int argc, char **argv)
memset(&entry, 0, sizeof(entry));
ret = hdb_value2entry(context, &data, &entry.entry);
krb5_data_free(&data);
- if(ret)
+ if (ret)
krb5_err(context, 1, ret, "hdb_value2entry");
- if(print_dump)
- hdb_print_entry(context, db, &entry, stdout);
- else {
+ if (print_dump) {
+ struct hdb_print_entry_arg parg;
+
+ parg.out = stdout;
+ parg.fmt = HDB_DUMP_HEIMDAL;
+ hdb_print_entry(context, db, &entry, &parg);
+ } else {
ret = db->hdb_store(context, db, 0, &entry);
- if(ret == HDB_ERR_EXISTS) {
+ if (ret == HDB_ERR_EXISTS) {
char *s;
ret = krb5_unparse_name(context, entry.entry.principal, &s);
if (ret)
s = strdup(unparseable_name);
krb5_warnx(context, "Entry exists: %s", s);
free(s);
- } else if(ret)
+ } else if (ret)
krb5_err(context, 1, ret, "db_store");
else
nprincs++;
diff --git a/kdc/kdc-private.h b/kdc/kdc-private.h
index aef929b26972..c64940492a2a 100644
--- a/kdc/kdc-private.h
+++ b/kdc/kdc-private.h
@@ -24,10 +24,7 @@ _kdc_add_inital_verified_cas (
krb5_error_code
_kdc_as_rep (
- krb5_context /*context*/,
- krb5_kdc_configuration */*config*/,
- KDC_REQ */*req*/,
- const krb5_data */*req_buffer*/,
+ kdc_request_t /*r*/,
krb5_data */*reply*/,
const char */*from*/,
struct sockaddr */*from_addr*/,
@@ -42,7 +39,7 @@ _kdc_check_access (
hdb_entry_ex */*server_ex*/,
const char */*server_name*/,
KDC_REQ */*req*/,
- krb5_data */*e_data*/);
+ METHOD_DATA */*method_data*/);
krb5_boolean
_kdc_check_addresses (
@@ -83,8 +80,10 @@ krb5_error_code
_kdc_encode_reply (
krb5_context /*context*/,
krb5_kdc_configuration */*config*/,
+ krb5_crypto /*armor_crypto*/,
+ uint32_t /*nonce*/,
KDC_REP */*rep*/,
- const EncTicketPart */*et*/,
+ EncTicketPart */*et*/,
EncKDCRepPart */*ek*/,
krb5_enctype /*etype*/,
int /*skvno*/,
@@ -96,6 +95,35 @@ _kdc_encode_reply (
krb5_data */*reply*/);
krb5_error_code
+_kdc_fast_mk_error (
+ krb5_context /*context*/,
+ kdc_request_t /*r*/,
+ METHOD_DATA */*error_method*/,
+ krb5_crypto /*armor_crypto*/,
+ const KDC_REQ_BODY */*req_body*/,
+ krb5_error_code /*outer_error*/,
+ const char */*e_text*/,
+ krb5_principal /*error_server*/,
+ const PrincipalName */*error_client_name*/,
+ const Realm */*error_client_realm*/,
+ time_t */*csec*/,
+ int */*cusec*/,
+ krb5_data */*error_msg*/);
+
+krb5_error_code
+_kdc_fast_mk_response (
+ krb5_context /*context*/,
+ krb5_crypto /*armor_crypto*/,
+ METHOD_DATA */*pa_data*/,
+ krb5_keyblock */*strengthen_key*/,
+ KrbFastFinished */*finished*/,
+ krb5uint32 /*nonce*/,
+ krb5_data */*data*/);
+
+krb5_error_code
+_kdc_fast_unwrap_request (kdc_request_t /*r*/);
+
+krb5_error_code
_kdc_find_etype (
krb5_context /*context*/,
krb5_boolean /*use_strongest_session_key*/,
@@ -121,6 +149,21 @@ _kdc_free_ent (
hdb_entry_ex */*ent*/);
krb5_error_code
+_kdc_generate_ecdh_keyblock (
+ krb5_context /*context*/,
+ void */*ec_key_pk*/,
+ void **/*ec_key_key*/,
+ unsigned char **/*dh_gen_key*/,
+ size_t */*dh_gen_keylen*/);
+
+krb5_error_code
+_kdc_get_ecdh_param (
+ krb5_context /*context*/,
+ krb5_kdc_configuration */*config*/,
+ SubjectPublicKeyInfo */*dh_key_info*/,
+ void **/*out*/);
+
+krb5_error_code
_kdc_get_preferred_key (
krb5_context /*context*/,
krb5_kdc_configuration */*config*/,
@@ -130,6 +173,9 @@ _kdc_get_preferred_key (
Key **/*key*/);
krb5_boolean
+_kdc_is_anon_request (const KDC_REQ_BODY */*b*/);
+
+krb5_boolean
_kdc_is_anonymous (
krb5_context /*context*/,
krb5_principal /*principal*/);
@@ -179,6 +225,12 @@ _kdc_pk_check_client (
char **/*subject_name*/);
void
+_kdc_pk_free_client_ec_param (
+ krb5_context /*context*/,
+ void */*ec_key_pk*/,
+ void */*ec_key_key*/);
+
+void
_kdc_pk_free_client_param (
krb5_context /*context*/,
pk_client_params */*cp*/);
@@ -192,7 +244,7 @@ _kdc_pk_mk_pa_reply (
krb5_enctype /*sessionetype*/,
const KDC_REQ */*req*/,
const krb5_data */*req_buffer*/,
- krb5_keyblock **/*reply_key*/,
+ krb5_keyblock */*reply_key*/,
krb5_keyblock */*sessionkey*/,
METHOD_DATA */*md*/);
@@ -206,6 +258,13 @@ _kdc_pk_rd_padata (
pk_client_params **/*ret_params*/);
krb5_error_code
+_kdc_serialize_ecdh_key (
+ krb5_context /*context*/,
+ void */*key*/,
+ unsigned char **/*out*/,
+ size_t */*out_len*/);
+
+krb5_error_code
_kdc_tgs_rep (
krb5_context /*context*/,
krb5_kdc_configuration */*config*/,
diff --git a/kdc/kdc-protos.h b/kdc/kdc-protos.h
index a46993b6790e..71eb4293e085 100644
--- a/kdc/kdc-protos.h
+++ b/kdc/kdc-protos.h
@@ -1,6 +1,7 @@
/* This is a generated file */
#ifndef __kdc_protos_h__
#define __kdc_protos_h__
+#ifndef DOXY
#include <stdarg.h>
@@ -18,6 +19,12 @@ kdc_check_flags (
const char */*server_name*/,
krb5_boolean /*is_as_req*/);
+krb5_error_code
+kdc_kx509_verify_service_principal (
+ krb5_context /*context*/,
+ const char */*cname*/,
+ krb5_principal /*sprincipal*/);
+
void
kdc_log (
krb5_context /*context*/,
@@ -114,4 +121,5 @@ krb5_kdc_windc_init (krb5_context /*context*/);
}
#endif
+#endif /* DOXY */
#endif /* __kdc_protos_h__ */
diff --git a/kdc/kdc-replay.c b/kdc/kdc-replay.c
index b0510f408924..af4e55c356d9 100644
--- a/kdc/kdc-replay.c
+++ b/kdc/kdc-replay.c
@@ -37,11 +37,11 @@ static int version_flag;
static int help_flag;
struct getargs args[] = {
- { "version", 0, arg_flag, &version_flag },
- { "help", 'h', arg_flag, &help_flag }
+ { "version", 0, arg_flag, &version_flag, NULL, NULL },
+ { "help", 'h', arg_flag, &help_flag, NULL, NULL }
};
-const static int num_args = sizeof(args) / sizeof(args[0]);
+static const int num_args = sizeof(args) / sizeof(args[0]);
static void
usage(int ret)
diff --git a/kdc/kdc-tester.c b/kdc/kdc-tester.c
new file mode 100644
index 000000000000..cbe4b1c00326
--- /dev/null
+++ b/kdc/kdc-tester.c
@@ -0,0 +1,508 @@
+/*
+ * Copyright (c) 1997-2005 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Portions Copyright (c) 2009 Apple Inc. 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 "kdc_locl.h"
+#include "send_to_kdc_plugin.h"
+
+struct perf {
+ unsigned long as_req;
+ unsigned long tgs_req;
+ struct timeval start;
+ struct timeval stop;
+ struct perf *next;
+} *ptop;
+
+int detach_from_console = -1;
+int daemon_child = -1;
+int do_bonjour = -1;
+
+static krb5_kdc_configuration *kdc_config;
+static krb5_context kdc_context;
+
+static struct sockaddr_storage sa;
+static const char *astr = "0.0.0.0";
+
+static void eval_object(heim_object_t);
+
+
+/*
+ *
+ */
+
+static krb5_error_code
+plugin_init(krb5_context context, void **pctx)
+{
+ *pctx = NULL;
+ return 0;
+}
+
+static void
+plugin_fini(void *ctx)
+{
+}
+
+static krb5_error_code
+plugin_send_to_kdc(krb5_context context,
+ void *ctx,
+ krb5_krbhst_info *ho,
+ time_t timeout,
+ const krb5_data *in,
+ krb5_data *out)
+{
+ return KRB5_PLUGIN_NO_HANDLE;
+}
+
+static krb5_error_code
+plugin_send_to_realm(krb5_context context,
+ void *ctx,
+ krb5_const_realm realm,
+ time_t timeout,
+ const krb5_data *in,
+ krb5_data *out)
+{
+ int ret;
+
+ krb5_kdc_update_time(NULL);
+
+ ret = krb5_kdc_process_request(kdc_context, kdc_config,
+ in->data, in->length,
+ out, NULL, astr,
+ (struct sockaddr *)&sa, 0);
+ if (ret)
+ krb5_err(kdc_context, 1, ret, "krb5_kdc_process_request");
+
+ return 0;
+}
+
+static krb5plugin_send_to_kdc_ftable send_to_kdc = {
+ KRB5_PLUGIN_SEND_TO_KDC_VERSION_2,
+ plugin_init,
+ plugin_fini,
+ plugin_send_to_kdc,
+ plugin_send_to_realm
+};
+
+static void
+perf_start(struct perf *perf)
+{
+ memset(perf, 0, sizeof(*perf));
+
+ gettimeofday(&perf->start, NULL);
+ perf->next = ptop;
+ ptop = perf;
+}
+
+static void
+perf_stop(struct perf *perf)
+{
+ gettimeofday(&perf->stop, NULL);
+ ptop = perf->next;
+
+ if (ptop) {
+ ptop->as_req += perf->as_req;
+ ptop->tgs_req += perf->tgs_req;
+ }
+
+ timevalsub(&perf->stop, &perf->start);
+ printf("time: %lu.%06lu\n",
+ (unsigned long)perf->stop.tv_sec,
+ (unsigned long)perf->stop.tv_usec);
+
+#define USEC_PER_SEC 1000000
+
+ if (perf->as_req) {
+ double as_ps = 0.0;
+ as_ps = (perf->as_req * USEC_PER_SEC) / (double)((perf->stop.tv_sec * USEC_PER_SEC) + perf->stop.tv_usec);
+ printf("as-req/s %.2lf (total %lu requests)\n", as_ps, perf->as_req);
+ }
+
+ if (perf->tgs_req) {
+ double tgs_ps = 0.0;
+ tgs_ps = (perf->tgs_req * USEC_PER_SEC) / (double)((perf->stop.tv_sec * USEC_PER_SEC) + perf->stop.tv_usec);
+ printf("tgs-req/s %.2lf (total %lu requests)\n", tgs_ps, perf->tgs_req);
+ }
+}
+
+/*
+ *
+ */
+
+static void
+eval_repeat(heim_dict_t o)
+{
+ heim_object_t or = heim_dict_get_value(o, HSTR("value"));
+ heim_number_t n = heim_dict_get_value(o, HSTR("num"));
+ int i, num;
+ struct perf perf;
+
+ perf_start(&perf);
+
+ heim_assert(or != NULL, "value missing");
+ heim_assert(n != NULL, "num missing");
+
+ num = heim_number_get_int(n);
+ heim_assert(num >= 0, "num >= 0");
+
+ for (i = 0; i < num; i++)
+ eval_object(or);
+
+ perf_stop(&perf);
+}
+
+/*
+ *
+ */
+
+static krb5_error_code
+copy_keytab(krb5_context context, krb5_keytab from, krb5_keytab to)
+{
+ krb5_keytab_entry entry;
+ krb5_kt_cursor cursor;
+ krb5_error_code ret;
+
+ ret = krb5_kt_start_seq_get(context, from, &cursor);
+ if (ret)
+ return ret;
+ while((ret = krb5_kt_next_entry(context, from, &entry, &cursor)) == 0){
+ krb5_kt_add_entry(context, to, &entry);
+ krb5_kt_free_entry(context, &entry);
+ }
+ return krb5_kt_end_seq_get(context, from, &cursor);
+}
+
+/*
+ *
+ */
+
+static void
+eval_kinit(heim_dict_t o)
+{
+ heim_string_t user, password, keytab, fast_armor_cc, pk_user_id, ccache;
+ krb5_get_init_creds_opt *opt;
+ krb5_init_creds_context ctx;
+ krb5_principal client;
+ krb5_keytab ktmem = NULL;
+ krb5_ccache fast_cc = NULL;
+ krb5_error_code ret;
+
+ if (ptop)
+ ptop->as_req++;
+
+ user = heim_dict_get_value(o, HSTR("client"));
+ if (user == NULL)
+ krb5_errx(kdc_context, 1, "no client");
+
+ password = heim_dict_get_value(o, HSTR("password"));
+ keytab = heim_dict_get_value(o, HSTR("keytab"));
+ pk_user_id = heim_dict_get_value(o, HSTR("pkinit-user-cert-id"));
+ if (password == NULL && keytab == NULL && pk_user_id == NULL)
+ krb5_errx(kdc_context, 1, "password, keytab, nor PKINIT user cert ID");
+
+ ccache = heim_dict_get_value(o, HSTR("ccache"));
+
+ ret = krb5_parse_name(kdc_context, heim_string_get_utf8(user), &client);
+ if (ret)
+ krb5_err(kdc_context, 1, ret, "krb5_unparse_name");
+
+ /* PKINIT parts */
+ ret = krb5_get_init_creds_opt_alloc (kdc_context, &opt);
+ if (ret)
+ krb5_err(kdc_context, 1, ret, "krb5_get_init_creds_opt_alloc");
+
+ if (pk_user_id) {
+ heim_bool_t rsaobj = heim_dict_get_value(o, HSTR("pkinit-use-rsa"));
+ int use_rsa = rsaobj ? heim_bool_val(rsaobj) : 0;
+
+ ret = krb5_get_init_creds_opt_set_pkinit(kdc_context, opt,
+ client,
+ heim_string_get_utf8(pk_user_id),
+ NULL, NULL, NULL,
+ use_rsa ? 2 : 0,
+ NULL, NULL, NULL);
+ if (ret)
+ krb5_err(kdc_context, 1, ret, "krb5_get_init_creds_opt_set_pkinit");
+ }
+
+ ret = krb5_init_creds_init(kdc_context, client, NULL, NULL, 0, opt, &ctx);
+ if (ret)
+ krb5_err(kdc_context, 1, ret, "krb5_init_creds_init");
+
+ fast_armor_cc = heim_dict_get_value(o, HSTR("fast-armor-cc"));
+ if (fast_armor_cc) {
+
+ ret = krb5_cc_resolve(kdc_context, heim_string_get_utf8(fast_armor_cc), &fast_cc);
+ if (ret)
+ krb5_err(kdc_context, 1, ret, "krb5_cc_resolve");
+
+ ret = krb5_init_creds_set_fast_ccache(kdc_context, ctx, fast_cc);
+ if (ret)
+ krb5_err(kdc_context, 1, ret, "krb5_init_creds_set_fast_ccache");
+ }
+
+ if (password) {
+ ret = krb5_init_creds_set_password(kdc_context, ctx,
+ heim_string_get_utf8(password));
+ if (ret)
+ krb5_err(kdc_context, 1, ret, "krb5_init_creds_set_password");
+ }
+ if (keytab) {
+ krb5_keytab kt = NULL;
+
+ ret = krb5_kt_resolve(kdc_context, heim_string_get_utf8(keytab), &kt);
+ if (ret)
+ krb5_err(kdc_context, 1, ret, "krb5_kt_resolve");
+
+ ret = krb5_kt_resolve(kdc_context, "MEMORY:keytab", &ktmem);
+ if (ret)
+ krb5_err(kdc_context, 1, ret, "krb5_kt_resolve(MEMORY)");
+
+ ret = copy_keytab(kdc_context, kt, ktmem);
+ if (ret)
+ krb5_err(kdc_context, 1, ret, "copy_keytab");
+
+ krb5_kt_close(kdc_context, kt);
+
+ ret = krb5_init_creds_set_keytab(kdc_context, ctx, ktmem);
+ if (ret)
+ krb5_err(kdc_context, 1, ret, "krb5_init_creds_set_keytab");
+ }
+
+ ret = krb5_init_creds_get(kdc_context, ctx);
+ if (ret)
+ krb5_err(kdc_context, 1, ret, "krb5_init_creds_get");
+
+ if (ccache) {
+ const char *name = heim_string_get_utf8(ccache);
+ krb5_creds cred;
+ krb5_ccache cc;
+
+ ret = krb5_init_creds_get_creds(kdc_context, ctx, &cred);
+ if (ret)
+ krb5_err(kdc_context, 1, ret, "krb5_init_creds_get_creds");
+
+ ret = krb5_cc_resolve(kdc_context, name, &cc);
+ if (ret)
+ krb5_err(kdc_context, 1, ret, "krb5_cc_resolve");
+
+ krb5_init_creds_store(kdc_context, ctx, cc);
+
+ ret = krb5_cc_close(kdc_context, cc);
+ if (ret)
+ krb5_err(kdc_context, 1, ret, "krb5_cc_close");
+
+ krb5_free_cred_contents(kdc_context, &cred);
+ }
+
+ krb5_init_creds_free(kdc_context, ctx);
+
+ if (ktmem)
+ krb5_kt_close(kdc_context, ktmem);
+ if (fast_cc)
+ krb5_cc_close(kdc_context, fast_cc);
+}
+
+/*
+ *
+ */
+
+static void
+eval_kgetcred(heim_dict_t o)
+{
+ heim_string_t server, ccache;
+ krb5_get_creds_opt opt;
+ heim_bool_t nostore;
+ krb5_error_code ret;
+ krb5_ccache cc = NULL;
+ krb5_principal s;
+ krb5_creds *out = NULL;
+
+ if (ptop)
+ ptop->tgs_req++;
+
+ server = heim_dict_get_value(o, HSTR("server"));
+ if (server == NULL)
+ krb5_errx(kdc_context, 1, "no server");
+
+ ccache = heim_dict_get_value(o, HSTR("ccache"));
+ if (ccache == NULL)
+ krb5_errx(kdc_context, 1, "no ccache");
+
+ nostore = heim_dict_get_value(o, HSTR("nostore"));
+ if (nostore == NULL)
+ nostore = heim_bool_create(1);
+
+ ret = krb5_cc_resolve(kdc_context, heim_string_get_utf8(ccache), &cc);
+ if (ret)
+ krb5_err(kdc_context, 1, ret, "krb5_cc_resolve");
+
+ ret = krb5_parse_name(kdc_context, heim_string_get_utf8(server), &s);
+ if (ret)
+ krb5_err(kdc_context, 1, ret, "krb5_parse_name");
+
+ ret = krb5_get_creds_opt_alloc(kdc_context, &opt);
+ if (ret)
+ krb5_err(kdc_context, 1, ret, "krb5_get_creds_opt_alloc");
+
+ if (heim_bool_val(nostore))
+ krb5_get_creds_opt_add_options(kdc_context, opt, KRB5_GC_NO_STORE);
+
+ ret = krb5_get_creds(kdc_context, opt, cc, s, &out);
+ if (ret)
+ krb5_err(kdc_context, 1, ret, "krb5_get_creds");
+
+ krb5_free_creds(kdc_context, out);
+ krb5_free_principal(kdc_context, s);
+ krb5_get_creds_opt_free(kdc_context, opt);
+ krb5_cc_close(kdc_context, cc);
+}
+
+
+/*
+ *
+ */
+
+static void
+eval_kdestroy(heim_dict_t o)
+{
+ heim_string_t ccache = heim_dict_get_value(o, HSTR("ccache"));;
+ krb5_error_code ret;
+ const char *name;
+ krb5_ccache cc;
+
+ heim_assert(ccache != NULL, "ccache_missing");
+
+ name = heim_string_get_utf8(ccache);
+
+ ret = krb5_cc_resolve(kdc_context, name, &cc);
+ if (ret)
+ krb5_err(kdc_context, 1, ret, "krb5_cc_resolve");
+
+ krb5_cc_destroy(kdc_context, cc);
+}
+
+
+/*
+ *
+ */
+
+static void
+eval_array_element(heim_object_t o, void *ptr, int *stop)
+{
+ eval_object(o);
+}
+
+static void
+eval_object(heim_object_t o)
+{
+ heim_tid_t t = heim_get_tid(o);
+
+ if (t == heim_array_get_type_id()) {
+ heim_array_iterate_f(o, NULL, eval_array_element);
+ } else if (t == heim_dict_get_type_id()) {
+ const char *op = heim_dict_get_value(o, HSTR("op"));
+
+ heim_assert(op != NULL, "op missing");
+
+ if (strcmp(op, "repeat") == 0) {
+ eval_repeat(o);
+ } else if (strcmp(op, "kinit") == 0) {
+ eval_kinit(o);
+ } else if (strcmp(op, "kgetcred") == 0) {
+ eval_kgetcred(o);
+ } else if (strcmp(op, "kdestroy") == 0) {
+ eval_kdestroy(o);
+ } else {
+ errx(1, "unsupported ops %s", op);
+ }
+
+ } else
+ errx(1, "unsupported");
+}
+
+
+int
+main(int argc, char **argv)
+{
+ krb5_error_code ret;
+ int optidx = 0;
+
+ setprogname(argv[0]);
+
+ ret = krb5_init_context(&kdc_context);
+ if (ret == KRB5_CONFIG_BADFORMAT)
+ errx (1, "krb5_init_context failed to parse configuration file");
+ else if (ret)
+ errx (1, "krb5_init_context failed: %d", ret);
+
+ ret = krb5_kt_register(kdc_context, &hdb_get_kt_ops);
+ if (ret)
+ errx (1, "krb5_kt_register(HDB) failed: %d", ret);
+
+ kdc_config = configure(kdc_context, argc, argv, &optidx);
+
+ argc -= optidx;
+ argv += optidx;
+
+ if (argc == 0)
+ errx(1, "missing operations");
+
+ krb5_plugin_register(kdc_context, PLUGIN_TYPE_DATA,
+ KRB5_PLUGIN_SEND_TO_KDC, &send_to_kdc);
+
+ {
+ void *buf;
+ size_t size;
+ heim_object_t o;
+
+ if (rk_undumpdata(argv[0], &buf, &size))
+ errx(1, "undumpdata: %s", argv[0]);
+
+ o = heim_json_create_with_bytes(buf, size, 10, 0, NULL);
+ free(buf);
+ if (o == NULL)
+ errx(1, "heim_json");
+
+ /*
+ * do the work here
+ */
+
+ eval_object(o);
+
+ heim_release(o);
+ }
+
+ krb5_free_context(kdc_context);
+ return 0;
+}
diff --git a/kdc/kdc.8 b/kdc/kdc.8
index 171c426a0c52..70c4cafe3bcd 100644
--- a/kdc/kdc.8
+++ b/kdc/kdc.8
@@ -47,9 +47,6 @@
.Op Fl p | Fl Fl no-require-preauth
.Op Fl Fl max-request= Ns Ar size
.Op Fl H | Fl Fl enable-http
-.Op Fl Fl no-524
-.Op Fl Fl kerberos4
-.Op Fl Fl kerberos4-cross-realm
.Oo Fl r Ar string \*(Ba Xo
.Fl Fl v4-realm= Ns Ar string
.Xc
@@ -93,14 +90,6 @@ Gives an upper limit on the size of the requests that the kdc is
willing to handle.
.It Fl H , Fl Fl enable-http
Makes the kdc listen on port 80 and handle requests encapsulated in HTTP.
-.It Fl Fl no-524
-don't respond to 524 requests
-.It Fl Fl kerberos4
-respond to Kerberos 4 requests
-.It Fl Fl kerberos4-cross-realm
-respond to Kerberos 4 requests from foreign realms.
-This is a known security hole and should not be enabled unless you
-understand the consequences and are willing to live with them.
.It Fl r Ar string , Fl Fl v4-realm= Ns Ar string
What realm this server should act as when dealing with version 4
requests.
@@ -124,7 +113,7 @@ option might be used.
.It Fl Fl detach
detach from pty and run as a daemon.
.It Fl Fl disable-des
-disable add des encryption types, makes the kdc not use them.
+disable all des encryption types, makes the kdc not use them.
.El
.Pp
All activities are logged to one or more destinations, see
diff --git a/kdc/kdc.cat8 b/kdc/kdc.cat8
index 98f10d6f01b8..00ebf56be662 100644
--- a/kdc/kdc.cat8
+++ b/kdc/kdc.cat8
@@ -6,10 +6,9 @@ NNAAMMEE
SSYYNNOOPPSSIISS
kkddcc [--cc _f_i_l_e | ----ccoonnffiigg--ffiillee==_f_i_l_e] [--pp | ----nnoo--rreeqquuiirree--pprreeaauutthh]
- [----mmaaxx--rreeqquueesstt==_s_i_z_e] [--HH | ----eennaabbllee--hhttttpp] [----nnoo--552244] [----kkeerrbbeerrooss44]
- [----kkeerrbbeerrooss44--ccrroossss--rreeaallmm] [--rr _s_t_r_i_n_g | ----vv44--rreeaallmm==_s_t_r_i_n_g] [--PP
- _p_o_r_t_s_p_e_c | ----ppoorrttss==_p_o_r_t_s_p_e_c] [----ddeettaacchh] [----ddiissaabbllee--ddeess]
- [----aaddddrreesssseess==_l_i_s_t _o_f _a_d_d_r_e_s_s_e_s]
+ [----mmaaxx--rreeqquueesstt==_s_i_z_e] [--HH | ----eennaabbllee--hhttttpp] [--rr _s_t_r_i_n_g |
+ ----vv44--rreeaallmm==_s_t_r_i_n_g] [--PP _p_o_r_t_s_p_e_c | ----ppoorrttss==_p_o_r_t_s_p_e_c] [----ddeettaacchh]
+ [----ddiissaabbllee--ddeess] [----aaddddrreesssseess==_l_i_s_t _o_f _a_d_d_r_e_s_s_e_s]
DDEESSCCRRIIPPTTIIOONN
kkddcc serves requests for tickets. When it starts, it first checks the
@@ -42,17 +41,6 @@ DDEESSCCRRIIPPTTIIOONN
Makes the kdc listen on port 80 and handle requests encapsulated
in HTTP.
- ----nnoo--552244
- don't respond to 524 requests
-
- ----kkeerrbbeerrooss44
- respond to Kerberos 4 requests
-
- ----kkeerrbbeerrooss44--ccrroossss--rreeaallmm
- respond to Kerberos 4 requests from foreign realms. This is a
- known security hole and should not be enabled unless you under-
- stand the consequences and are willing to live with them.
-
--rr _s_t_r_i_n_g, ----vv44--rreeaallmm==_s_t_r_i_n_g
What realm this server should act as when dealing with version 4
requests. The database can contain any number of realms, but
@@ -75,7 +63,7 @@ DDEESSCCRRIIPPTTIIOONN
detach from pty and run as a daemon.
----ddiissaabbllee--ddeess
- disable add des encryption types, makes the kdc not use them.
+ disable all des encryption types, makes the kdc not use them.
All activities are logged to one or more destinations, see krb5.conf(5),
and krb5_openlog(3). The entity used for logging is kkddcc.
diff --git a/kdc/kdc.h b/kdc/kdc.h
index ab643ec20071..2a1671aa81e4 100644
--- a/kdc/kdc.h
+++ b/kdc/kdc.h
@@ -57,6 +57,8 @@ typedef struct krb5_kdc_configuration {
struct HDB **db;
int num_db;
+ int num_kdc_processes;
+
krb5_boolean encode_as_rep_as_tgs_rep; /* bug compatibility */
krb5_boolean tgt_use_strongest_session_key;
@@ -67,6 +69,7 @@ typedef struct krb5_kdc_configuration {
krb5_boolean check_ticket_addresses;
krb5_boolean allow_null_ticket_addresses;
krb5_boolean allow_anonymous;
+ krb5_boolean strict_nametypes;
enum krb5_kdc_trpolicy trpolicy;
krb5_boolean enable_pkinit;
diff --git a/kdc/kdc_locl.h b/kdc/kdc_locl.h
index 36d694dae5f9..adbb94765fcf 100644
--- a/kdc/kdc_locl.h
+++ b/kdc/kdc_locl.h
@@ -43,8 +43,53 @@
typedef struct pk_client_params pk_client_params;
struct DigestREQ;
struct Kx509Request;
+typedef struct kdc_request_desc *kdc_request_t;
+
#include <kdc-private.h>
+#define FAST_EXPIRATION_TIME (3 * 60)
+
+struct kdc_request_desc {
+ krb5_context context;
+ krb5_kdc_configuration *config;
+
+ /* */
+
+ krb5_data request;
+ KDC_REQ req;
+ METHOD_DATA *padata;
+
+ /* out */
+
+ METHOD_DATA outpadata;
+
+ KDC_REP rep;
+ EncTicketPart et;
+ EncKDCRepPart ek;
+
+ /* PA methods can affect both the reply key and the session key (pkinit) */
+ krb5_enctype sessionetype;
+ krb5_keyblock reply_key;
+ krb5_keyblock session_key;
+
+ const char *e_text;
+
+ /* state */
+ krb5_principal client_princ;
+ char *client_name;
+ hdb_entry_ex *client;
+ HDB *clientdb;
+
+ krb5_principal server_princ;
+ char *server_name;
+ hdb_entry_ex *server;
+
+ krb5_crypto armor_crypto;
+
+ KDCFastState fast;
+};
+
+
extern sig_atomic_t exit_flag;
extern size_t max_request_udp;
extern size_t max_request_tcp;
@@ -54,12 +99,11 @@ extern krb5_addresses explicit_addresses;
extern int enable_http;
-#ifdef SUPPORT_DETACH
-
-#define DETACH_IS_DEFAULT FALSE
-
extern int detach_from_console;
-#endif
+extern int daemon_child;
+extern int do_bonjour;
+
+extern int testing_flag;
extern const struct units _kdc_digestunits[];
@@ -72,10 +116,10 @@ extern char *runas_string;
extern char *chroot_string;
void
-loop(krb5_context context, krb5_kdc_configuration *config);
+start_kdc(krb5_context context, krb5_kdc_configuration *config, const char *argv0);
krb5_kdc_configuration *
-configure(krb5_context context, int argc, char **argv);
+configure(krb5_context context, int argc, char **argv, int *optidx);
#ifdef __APPLE__
void bonjour_announce(krb5_context, krb5_kdc_configuration *);
diff --git a/kdc/kerberos5.c b/kdc/kerberos5.c
index ee6baf0edc9c..675b406b8277 100644
--- a/kdc/kerberos5.c
+++ b/kdc/kerberos5.c
@@ -92,9 +92,9 @@ _kdc_is_weak_exception(krb5_principal principal, krb5_enctype etype)
{
if (principal->name.name_string.len > 0 &&
strcmp(principal->name.name_string.val[0], "afs") == 0 &&
- (etype == ETYPE_DES_CBC_CRC
- || etype == ETYPE_DES_CBC_MD4
- || etype == ETYPE_DES_CBC_MD5))
+ (etype == (krb5_enctype)ETYPE_DES_CBC_CRC
+ || etype == (krb5_enctype)ETYPE_DES_CBC_MD4
+ || etype == (krb5_enctype)ETYPE_DES_CBC_MD5))
return TRUE;
return FALSE;
}
@@ -119,7 +119,7 @@ is_default_salt_p(const krb5_salt *default_salt, const Key *key)
/*
* return the first appropriate key of `princ' in `ret_key'. Look for
* all the etypes in (`etypes', `len'), stopping as soon as we find
- * one, but preferring one that has default salt
+ * one, but preferring one that has default salt.
*/
krb5_error_code
@@ -130,9 +130,10 @@ _kdc_find_etype(krb5_context context, krb5_boolean use_strongest_session_key,
{
krb5_error_code ret;
krb5_salt def_salt;
- krb5_enctype enctype = ETYPE_NULL;
- Key *key;
- int i;
+ krb5_enctype enctype = (krb5_enctype)ETYPE_NULL;
+ const krb5_enctype *p;
+ Key *key = NULL;
+ int i, k;
/* We'll want to avoid keys with v4 salted keys in the pre-auth case... */
ret = krb5_get_pw_salt(context, princ->entry.principal, &def_salt);
@@ -142,9 +143,6 @@ _kdc_find_etype(krb5_context context, krb5_boolean use_strongest_session_key,
ret = KRB5KDC_ERR_ETYPE_NOSUPP;
if (use_strongest_session_key) {
- const krb5_enctype *p;
- krb5_enctype clientbest = ETYPE_NULL;
- int j;
/*
* Pick the strongest key that the KDC, target service, and
@@ -159,34 +157,35 @@ _kdc_find_etype(krb5_context context, krb5_boolean use_strongest_session_key,
/* drive the search with local supported enctypes list */
p = krb5_kerberos_enctypes(context);
- for (i = 0; p[i] != ETYPE_NULL && enctype == ETYPE_NULL; i++) {
- if (krb5_enctype_valid(context, p[i]) != 0)
+ for (i = 0;
+ p[i] != (krb5_enctype)ETYPE_NULL && enctype == (krb5_enctype)ETYPE_NULL;
+ i++) {
+ if (krb5_enctype_valid(context, p[i]) != 0 &&
+ !_kdc_is_weak_exception(princ->entry.principal, p[i]))
continue;
/* check that the client supports it too */
- for (j = 0; j < len && enctype == ETYPE_NULL; j++) {
- if (p[i] != etypes[j])
- continue;
- /* save best of union of { client, crypto system } */
- if (clientbest == ETYPE_NULL)
- clientbest = p[i];
- /* check target princ support */
- ret = hdb_enctype2key(context, &princ->entry, p[i], &key);
- if (ret)
- continue;
- if (is_preauth && !is_default_salt_p(&def_salt, key))
+ for (k = 0; k < len && enctype == (krb5_enctype)ETYPE_NULL; k++) {
+
+ if (p[i] != etypes[k])
continue;
- enctype = p[i];
+
+ /* check target princ support */
+ key = NULL;
+ while (hdb_next_enctype2key(context, &princ->entry, NULL,
+ p[i], &key) == 0) {
+ if (key->key.keyvalue.length == 0) {
+ ret = KRB5KDC_ERR_NULL_KEY;
+ continue;
+ }
+ enctype = p[i];
+ ret = 0;
+ if (is_preauth && ret_key != NULL &&
+ !is_default_salt_p(&def_salt, key))
+ continue;
+ }
}
}
- if (clientbest != ETYPE_NULL && enctype == ETYPE_NULL)
- enctype = clientbest;
- else if (enctype == ETYPE_NULL)
- ret = KRB5KDC_ERR_ETYPE_NOSUPP;
- if (ret == 0 && ret_enctype != NULL)
- *ret_enctype = enctype;
- if (ret == 0 && ret_key != NULL)
- *ret_key = key;
} else {
/*
* Pick the first key from the client's enctype list that is
@@ -197,29 +196,51 @@ _kdc_find_etype(krb5_context context, krb5_boolean use_strongest_session_key,
* weak enctypes in krb5.conf and selects this key selection
* algorithm, then we get exactly what RFC4120 says.
*/
- for(key = NULL, i = 0; ret != 0 && i < len; i++, key = NULL) {
+ for(i = 0; ret != 0 && i < len; i++) {
if (krb5_enctype_valid(context, etypes[i]) != 0 &&
!_kdc_is_weak_exception(princ->entry.principal, etypes[i]))
continue;
- while (hdb_next_enctype2key(context, &princ->entry, etypes[i], &key) == 0) {
+ key = NULL;
+ while (ret != 0 &&
+ hdb_next_enctype2key(context, &princ->entry, NULL,
+ etypes[i], &key) == 0) {
if (key->key.keyvalue.length == 0) {
ret = KRB5KDC_ERR_NULL_KEY;
continue;
}
- if (ret_key != NULL)
- *ret_key = key;
- if (ret_enctype != NULL)
- *ret_enctype = etypes[i];
+ enctype = etypes[i];
ret = 0;
- if (is_preauth && is_default_salt_p(&def_salt, key))
- goto out;
+ if (is_preauth && ret_key != NULL &&
+ !is_default_salt_p(&def_salt, key))
+ continue;
}
}
}
-out:
+ if (enctype == (krb5_enctype)ETYPE_NULL) {
+ /*
+ * if the service principal is one for which there is a known 1DES
+ * exception and no other enctype matches both the client request and
+ * the service key list, provide a DES-CBC-CRC key.
+ */
+ if (ret_key == NULL &&
+ _kdc_is_weak_exception(princ->entry.principal, ETYPE_DES_CBC_CRC)) {
+ ret = 0;
+ enctype = ETYPE_DES_CBC_CRC;
+ } else {
+ ret = KRB5KDC_ERR_ETYPE_NOSUPP;
+ }
+ }
+
+ if (ret == 0) {
+ if (ret_enctype != NULL)
+ *ret_enctype = enctype;
+ if (ret_key != NULL)
+ *ret_key = key;
+ }
+
krb5_free_salt (context, def_salt);
return ret;
}
@@ -241,6 +262,24 @@ _kdc_make_anonymous_principalname (PrincipalName *pn)
return 0;
}
+static void
+_kdc_r_log(kdc_request_t r, int level, const char *fmt, ...)
+{
+ va_list ap;
+ char *s;
+ va_start(ap, fmt);
+ s = kdc_log_msg_va(r->context, r->config, level, fmt, ap);
+ if(s) free(s);
+ va_end(ap);
+}
+
+static void
+_kdc_set_e_text(kdc_request_t r, const char *e_text)
+{
+ r->e_text = e_text;
+ kdc_log(r->context, r->config, 0, "%s", e_text);
+}
+
void
_kdc_log_timestamp(krb5_context context,
krb5_kdc_configuration *config,
@@ -271,6 +310,466 @@ _kdc_log_timestamp(krb5_context context,
type, authtime_str, starttime_str, endtime_str, renewtime_str);
}
+/*
+ *
+ */
+
+#ifdef PKINIT
+
+static krb5_error_code
+pa_pkinit_validate(kdc_request_t r, const PA_DATA *pa)
+{
+ pk_client_params *pkp = NULL;
+ char *client_cert = NULL;
+ krb5_error_code ret;
+
+ ret = _kdc_pk_rd_padata(r->context, r->config, &r->req, pa, r->client, &pkp);
+ if (ret || pkp == NULL) {
+ ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+ _kdc_r_log(r, 5, "Failed to decode PKINIT PA-DATA -- %s",
+ r->client_name);
+ goto out;
+ }
+
+ ret = _kdc_pk_check_client(r->context,
+ r->config,
+ r->clientdb,
+ r->client,
+ pkp,
+ &client_cert);
+ if (ret) {
+ _kdc_set_e_text(r, "PKINIT certificate not allowed to "
+ "impersonate principal");
+ goto out;
+ }
+
+ _kdc_r_log(r, 0, "PKINIT pre-authentication succeeded -- %s using %s",
+ r->client_name, client_cert);
+ free(client_cert);
+
+ ret = _kdc_pk_mk_pa_reply(r->context, r->config, pkp, r->client,
+ r->sessionetype, &r->req, &r->request,
+ &r->reply_key, &r->session_key, &r->outpadata);
+ if (ret) {
+ _kdc_set_e_text(r, "Failed to build PK-INIT reply");
+ goto out;
+ }
+#if 0
+ ret = _kdc_add_inital_verified_cas(r->context, r->config,
+ pkp, &r->et);
+#endif
+ out:
+ if (pkp)
+ _kdc_pk_free_client_param(r->context, pkp);
+
+ return ret;
+}
+
+#endif /* PKINIT */
+
+/*
+ *
+ */
+
+static krb5_error_code
+make_pa_enc_challange(krb5_context context, METHOD_DATA *md,
+ krb5_crypto crypto)
+{
+ PA_ENC_TS_ENC p;
+ unsigned char *buf;
+ size_t buf_size;
+ size_t len;
+ EncryptedData encdata;
+ krb5_error_code ret;
+ int32_t usec;
+ int usec2;
+
+ krb5_us_timeofday (context, &p.patimestamp, &usec);
+ usec2 = usec;
+ p.pausec = &usec2;
+
+ ASN1_MALLOC_ENCODE(PA_ENC_TS_ENC, buf, buf_size, &p, &len, ret);
+ if (ret)
+ return ret;
+ if(buf_size != len)
+ krb5_abortx(context, "internal error in ASN.1 encoder");
+
+ ret = krb5_encrypt_EncryptedData(context,
+ crypto,
+ KRB5_KU_ENC_CHALLENGE_KDC,
+ buf,
+ len,
+ 0,
+ &encdata);
+ free(buf);
+ if (ret)
+ return ret;
+
+ ASN1_MALLOC_ENCODE(EncryptedData, buf, buf_size, &encdata, &len, ret);
+ free_EncryptedData(&encdata);
+ if (ret)
+ return ret;
+ if(buf_size != len)
+ krb5_abortx(context, "internal error in ASN.1 encoder");
+
+ ret = krb5_padata_add(context, md, KRB5_PADATA_ENCRYPTED_CHALLENGE, buf, len);
+ if (ret)
+ free(buf);
+ return ret;
+}
+
+static krb5_error_code
+pa_enc_chal_validate(kdc_request_t r, const PA_DATA *pa)
+{
+ krb5_data pepper1, pepper2, ts_data;
+ KDC_REQ_BODY *b = &r->req.req_body;
+ int invalidPassword = 0;
+ EncryptedData enc_data;
+ krb5_enctype aenctype;
+ krb5_error_code ret;
+ struct Key *k;
+ size_t size;
+ int i;
+
+ heim_assert(r->armor_crypto != NULL, "ENC-CHAL called for non FAST");
+
+ if (_kdc_is_anon_request(b)) {
+ ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+ kdc_log(r->context, r->config, 0, "ENC-CHALL doesn't support anon");
+ return ret;
+ }
+
+ ret = decode_EncryptedData(pa->padata_value.data,
+ pa->padata_value.length,
+ &enc_data,
+ &size);
+ if (ret) {
+ ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+ _kdc_r_log(r, 5, "Failed to decode PA-DATA -- %s",
+ r->client_name);
+ return ret;
+ }
+
+ pepper1.data = "clientchallengearmor";
+ pepper1.length = strlen(pepper1.data);
+ pepper2.data = "challengelongterm";
+ pepper2.length = strlen(pepper2.data);
+
+ krb5_crypto_getenctype(r->context, r->armor_crypto, &aenctype);
+
+ for (i = 0; i < r->client->entry.keys.len; i++) {
+ krb5_crypto challangecrypto, longtermcrypto;
+ krb5_keyblock challangekey;
+ PA_ENC_TS_ENC p;
+
+ k = &r->client->entry.keys.val[i];
+
+ ret = krb5_crypto_init(r->context, &k->key, 0, &longtermcrypto);
+ if (ret)
+ continue;
+
+ ret = krb5_crypto_fx_cf2(r->context, r->armor_crypto, longtermcrypto,
+ &pepper1, &pepper2, aenctype,
+ &challangekey);
+ krb5_crypto_destroy(r->context, longtermcrypto);
+ if (ret)
+ continue;
+
+ ret = krb5_crypto_init(r->context, &challangekey, 0,
+ &challangecrypto);
+ if (ret)
+ continue;
+
+ ret = krb5_decrypt_EncryptedData(r->context, challangecrypto,
+ KRB5_KU_ENC_CHALLENGE_CLIENT,
+ &enc_data,
+ &ts_data);
+ if (ret) {
+ const char *msg = krb5_get_error_message(r->context, ret);
+ krb5_error_code ret2;
+ char *str = NULL;
+
+ invalidPassword = 1;
+
+ ret2 = krb5_enctype_to_string(r->context, k->key.keytype, &str);
+ if (ret2)
+ str = NULL;
+ _kdc_r_log(r, 5, "Failed to decrypt ENC-CHAL -- %s "
+ "(enctype %s) error %s",
+ r->client_name, str ? str : "unknown enctype", msg);
+ krb5_free_error_message(r->context, msg);
+ free(str);
+
+ continue;
+ }
+
+ ret = decode_PA_ENC_TS_ENC(ts_data.data,
+ ts_data.length,
+ &p,
+ &size);
+ krb5_data_free(&ts_data);
+ if(ret){
+ krb5_crypto_destroy(r->context, challangecrypto);
+ ret = KRB5KDC_ERR_PREAUTH_FAILED;
+ _kdc_r_log(r, 5, "Failed to decode PA-ENC-TS_ENC -- %s",
+ r->client_name);
+ continue;
+ }
+
+ if (labs(kdc_time - p.patimestamp) > r->context->max_skew) {
+ char client_time[100];
+
+ krb5_crypto_destroy(r->context, challangecrypto);
+
+ krb5_format_time(r->context, p.patimestamp,
+ client_time, sizeof(client_time), TRUE);
+
+ ret = KRB5KRB_AP_ERR_SKEW;
+ _kdc_r_log(r, 0, "Too large time skew, "
+ "client time %s is out by %u > %u seconds -- %s",
+ client_time,
+ (unsigned)labs(kdc_time - p.patimestamp),
+ r->context->max_skew,
+ r->client_name);
+
+ free_PA_ENC_TS_ENC(&p);
+ goto out;
+ }
+
+ free_PA_ENC_TS_ENC(&p);
+
+ ret = make_pa_enc_challange(r->context, &r->outpadata,
+ challangecrypto);
+ krb5_crypto_destroy(r->context, challangecrypto);
+ if (ret)
+ goto out;
+
+ set_salt_padata(&r->outpadata, k->salt);
+ krb5_free_keyblock_contents(r->context, &r->reply_key);
+ ret = krb5_copy_keyblock_contents(r->context, &k->key, &r->reply_key);
+ if (ret)
+ goto out;
+
+ /*
+ * Success
+ */
+ if (r->clientdb->hdb_auth_status)
+ r->clientdb->hdb_auth_status(r->context, r->clientdb, r->client,
+ HDB_AUTH_SUCCESS);
+ goto out;
+ }
+
+ if (invalidPassword && r->clientdb->hdb_auth_status) {
+ r->clientdb->hdb_auth_status(r->context, r->clientdb, r->client,
+ HDB_AUTH_WRONG_PASSWORD);
+ ret = KRB5KDC_ERR_PREAUTH_FAILED;
+ }
+ out:
+ free_EncryptedData(&enc_data);
+
+ return ret;
+}
+
+static krb5_error_code
+pa_enc_ts_validate(kdc_request_t r, const PA_DATA *pa)
+{
+ EncryptedData enc_data;
+ krb5_error_code ret;
+ krb5_crypto crypto;
+ krb5_data ts_data;
+ PA_ENC_TS_ENC p;
+ size_t len;
+ Key *pa_key;
+ char *str;
+
+ if (_kdc_is_anon_request(&r->req.req_body)) {
+ ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+ _kdc_set_e_text(r, "ENC-TS doesn't support anon");
+ goto out;
+ }
+
+ ret = decode_EncryptedData(pa->padata_value.data,
+ pa->padata_value.length,
+ &enc_data,
+ &len);
+ if (ret) {
+ ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+ _kdc_r_log(r, 5, "Failed to decode PA-DATA -- %s",
+ r->client_name);
+ goto out;
+ }
+
+ ret = hdb_enctype2key(r->context, &r->client->entry, NULL,
+ enc_data.etype, &pa_key);
+ if(ret){
+ char *estr;
+ _kdc_set_e_text(r, "No key matching entype");
+ ret = KRB5KDC_ERR_ETYPE_NOSUPP;
+ if(krb5_enctype_to_string(r->context, enc_data.etype, &estr))
+ estr = NULL;
+ if(estr == NULL)
+ _kdc_r_log(r, 5,
+ "No client key matching pa-data (%d) -- %s",
+ enc_data.etype, r->client_name);
+ else
+ _kdc_r_log(r, 5,
+ "No client key matching pa-data (%s) -- %s",
+ estr, r->client_name);
+ free(estr);
+ free_EncryptedData(&enc_data);
+ goto out;
+ }
+
+ try_next_key:
+ ret = krb5_crypto_init(r->context, &pa_key->key, 0, &crypto);
+ if (ret) {
+ const char *msg = krb5_get_error_message(r->context, ret);
+ _kdc_r_log(r, 0, "krb5_crypto_init failed: %s", msg);
+ krb5_free_error_message(r->context, msg);
+ free_EncryptedData(&enc_data);
+ goto out;
+ }
+
+ ret = krb5_decrypt_EncryptedData (r->context,
+ crypto,
+ KRB5_KU_PA_ENC_TIMESTAMP,
+ &enc_data,
+ &ts_data);
+ krb5_crypto_destroy(r->context, crypto);
+ /*
+ * Since the user might have several keys with the same
+ * enctype but with diffrent salting, we need to try all
+ * the keys with the same enctype.
+ */
+ if(ret){
+ krb5_error_code ret2;
+ const char *msg = krb5_get_error_message(r->context, ret);
+
+ ret2 = krb5_enctype_to_string(r->context,
+ pa_key->key.keytype, &str);
+ if (ret2)
+ str = NULL;
+ _kdc_r_log(r, 5, "Failed to decrypt PA-DATA -- %s "
+ "(enctype %s) error %s",
+ r->client_name, str ? str : "unknown enctype", msg);
+ krb5_free_error_message(r->context, msg);
+ free(str);
+
+ if(hdb_next_enctype2key(r->context, &r->client->entry, NULL,
+ enc_data.etype, &pa_key) == 0)
+ goto try_next_key;
+
+ free_EncryptedData(&enc_data);
+
+ if (r->clientdb->hdb_auth_status)
+ r->clientdb->hdb_auth_status(r->context, r->clientdb, r->client,
+ HDB_AUTH_WRONG_PASSWORD);
+
+ ret = KRB5KDC_ERR_PREAUTH_FAILED;
+ goto out;
+ }
+ free_EncryptedData(&enc_data);
+ ret = decode_PA_ENC_TS_ENC(ts_data.data,
+ ts_data.length,
+ &p,
+ &len);
+ krb5_data_free(&ts_data);
+ if(ret){
+ ret = KRB5KDC_ERR_PREAUTH_FAILED;
+ _kdc_r_log(r, 5, "Failed to decode PA-ENC-TS_ENC -- %s",
+ r->client_name);
+ goto out;
+ }
+ if (labs(kdc_time - p.patimestamp) > r->context->max_skew) {
+ char client_time[100];
+
+ krb5_format_time(r->context, p.patimestamp,
+ client_time, sizeof(client_time), TRUE);
+
+ ret = KRB5KRB_AP_ERR_SKEW;
+ _kdc_r_log(r, 0, "Too large time skew, "
+ "client time %s is out by %u > %u seconds -- %s",
+ client_time,
+ (unsigned)labs(kdc_time - p.patimestamp),
+ r->context->max_skew,
+ r->client_name);
+
+ /*
+ * The following is needed to make windows clients to
+ * retry using the timestamp in the error message, if
+ * there is a e_text, they become unhappy.
+ */
+ r->e_text = NULL;
+ free_PA_ENC_TS_ENC(&p);
+ goto out;
+ }
+ free_PA_ENC_TS_ENC(&p);
+
+ set_salt_padata(&r->outpadata, pa_key->salt);
+
+ ret = krb5_copy_keyblock_contents(r->context, &pa_key->key, &r->reply_key);
+ if (ret)
+ return ret;
+
+ ret = krb5_enctype_to_string(r->context, pa_key->key.keytype, &str);
+ if (ret)
+ str = NULL;
+ _kdc_r_log(r, 2, "ENC-TS Pre-authentication succeeded -- %s using %s",
+ r->client_name, str ? str : "unknown enctype");
+ free(str);
+
+ ret = 0;
+
+ out:
+
+ return ret;
+}
+
+struct kdc_patypes {
+ int type;
+ char *name;
+ unsigned int flags;
+#define PA_ANNOUNCE 1
+#define PA_REQ_FAST 2 /* only use inside fast */
+ krb5_error_code (*validate)(kdc_request_t, const PA_DATA *pa);
+};
+
+static const struct kdc_patypes pat[] = {
+#ifdef PKINIT
+ {
+ KRB5_PADATA_PK_AS_REQ, "PK-INIT(ietf)", PA_ANNOUNCE,
+ pa_pkinit_validate
+ },
+ {
+ KRB5_PADATA_PK_AS_REQ_WIN, "PK-INIT(win2k)", PA_ANNOUNCE,
+ pa_pkinit_validate
+ },
+ {
+ KRB5_PADATA_PKINIT_KX, "Anonymous PK-INIT", PA_ANNOUNCE,
+ NULL
+ },
+#else
+ { KRB5_PADATA_PK_AS_REQ, "PK-INIT(ietf)", 0, NULL },
+ { KRB5_PADATA_PK_AS_REQ_WIN, "PK-INIT(win2k)", 0, NULL },
+ { KRB5_PADATA_PKINIT_KX, "Anonymous PK-INIT", 0, NULL },
+#endif
+ { KRB5_PADATA_PA_PK_OCSP_RESPONSE , "OCSP", 0, NULL },
+ {
+ KRB5_PADATA_ENC_TIMESTAMP , "ENC-TS",
+ PA_ANNOUNCE,
+ pa_enc_ts_validate
+ },
+ {
+ KRB5_PADATA_ENCRYPTED_CHALLENGE , "ENC-CHAL",
+ PA_ANNOUNCE | PA_REQ_FAST,
+ pa_enc_chal_validate
+ },
+ { KRB5_PADATA_REQ_ENC_PA_REP , "REQ-ENC-PA-REP", 0, NULL },
+ { KRB5_PADATA_FX_FAST, "FX-FAST", PA_ANNOUNCE, NULL },
+ { KRB5_PADATA_FX_ERROR, "FX-ERROR", 0, NULL },
+ { KRB5_PADATA_FX_COOKIE, "FX-COOKIE", 0, NULL }
+};
+
static void
log_patypes(krb5_context context,
krb5_kdc_configuration *config,
@@ -278,27 +777,18 @@ log_patypes(krb5_context context,
{
struct rk_strpool *p = NULL;
char *str;
- size_t i;
-
- for (i = 0; i < padata->len; i++) {
- switch(padata->val[i].padata_type) {
- case KRB5_PADATA_PK_AS_REQ:
- p = rk_strpoolprintf(p, "PK-INIT(ietf)");
- break;
- case KRB5_PADATA_PK_AS_REQ_WIN:
- p = rk_strpoolprintf(p, "PK-INIT(win2k)");
- break;
- case KRB5_PADATA_PA_PK_OCSP_RESPONSE:
- p = rk_strpoolprintf(p, "OCSP");
- break;
- case KRB5_PADATA_ENC_TIMESTAMP:
- p = rk_strpoolprintf(p, "encrypted-timestamp");
- break;
- default:
- p = rk_strpoolprintf(p, "%d", padata->val[i].padata_type);
- break;
+ size_t n, m;
+
+ for (n = 0; n < padata->len; n++) {
+ for (m = 0; m < sizeof(pat) / sizeof(pat[0]); m++) {
+ if (padata->val[n].padata_type == pat[m].type) {
+ p = rk_strpoolprintf(p, "%s", pat[m].name);
+ break;
+ }
}
- if (p && i + 1 < padata->len)
+ if (m == sizeof(pat) / sizeof(pat[0]))
+ p = rk_strpoolprintf(p, "%d", padata->val[n].padata_type);
+ if (p && n + 1 < padata->len)
p = rk_strpoolprintf(p, ", ");
if (p == NULL) {
kdc_log(context, config, 0, "out of memory");
@@ -317,11 +807,11 @@ log_patypes(krb5_context context,
*
*/
-
krb5_error_code
_kdc_encode_reply(krb5_context context,
krb5_kdc_configuration *config,
- KDC_REP *rep, const EncTicketPart *et, EncKDCRepPart *ek,
+ krb5_crypto armor_crypto, uint32_t nonce,
+ KDC_REP *rep, EncTicketPart *et, EncKDCRepPart *ek,
krb5_enctype etype,
int skvno, const EncryptionKey *skey,
int ckvno, const EncryptionKey *reply_key,
@@ -342,20 +832,15 @@ _kdc_encode_reply(krb5_context context,
krb5_free_error_message(context, msg);
return ret;
}
- if(buf_size != len) {
- free(buf);
- kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
- *e_text = "KDC internal error";
- return KRB5KRB_ERR_GENERIC;
- }
+ if(buf_size != len)
+ krb5_abortx(context, "Internal error in ASN.1 encoder");
ret = krb5_crypto_init(context, skey, etype, &crypto);
if (ret) {
- const char *msg;
- free(buf);
- msg = krb5_get_error_message(context, ret);
+ const char *msg = krb5_get_error_message(context, ret);
kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
krb5_free_error_message(context, msg);
+ free(buf);
return ret;
}
@@ -375,6 +860,69 @@ _kdc_encode_reply(krb5_context context,
return ret;
}
+ if (armor_crypto) {
+ krb5_data data;
+ krb5_keyblock *strengthen_key = NULL;
+ KrbFastFinished finished;
+
+ kdc_log(context, config, 0, "FAST armor protection");
+
+ memset(&finished, 0, sizeof(finished));
+ krb5_data_zero(&data);
+
+ finished.timestamp = kdc_time;
+ finished.usec = 0;
+ finished.crealm = et->crealm;
+ finished.cname = et->cname;
+
+ ASN1_MALLOC_ENCODE(Ticket, data.data, data.length,
+ &rep->ticket, &len, ret);
+ if (ret)
+ return ret;
+ if (data.length != len)
+ krb5_abortx(context, "internal asn.1 error");
+
+ ret = krb5_create_checksum(context, armor_crypto,
+ KRB5_KU_FAST_FINISHED, 0,
+ data.data, data.length,
+ &finished.ticket_checksum);
+ krb5_data_free(&data);
+ if (ret)
+ return ret;
+
+ ret = _kdc_fast_mk_response(context, armor_crypto,
+ rep->padata, strengthen_key, &finished,
+ nonce, &data);
+ free_Checksum(&finished.ticket_checksum);
+ if (ret)
+ return ret;
+
+ if (rep->padata) {
+ free_METHOD_DATA(rep->padata);
+ } else {
+ rep->padata = calloc(1, sizeof(*(rep->padata)));
+ if (rep->padata == NULL) {
+ krb5_data_free(&data);
+ return ENOMEM;
+ }
+ }
+
+ ret = krb5_padata_add(context, rep->padata,
+ KRB5_PADATA_FX_FAST,
+ data.data, data.length);
+ if (ret)
+ return ret;
+
+ /*
+ * Hide client name of privacy reasons
+ */
+ if (1 /* r->fast_options.hide_client_names */) {
+ rep->crealm[0] = '\0';
+ free_PrincipalName(&rep->cname);
+ rep->cname.name_type = 0;
+ }
+ }
+
if(rep->msg_type == krb_as_rep && !config->encode_as_rep_as_tgs_rep)
ASN1_MALLOC_ENCODE(EncASRepPart, buf, buf_size, ek, &len, ret);
else
@@ -559,11 +1107,33 @@ get_pa_etype_info(krb5_context context,
*
*/
-extern int _krb5_AES_string_to_default_iterator;
+extern int _krb5_AES_SHA1_string_to_default_iterator;
+extern int _krb5_AES_SHA2_string_to_default_iterator;
+
+static krb5_error_code
+make_s2kparams(int value, size_t len, krb5_data **ps2kparams)
+{
+ krb5_data *s2kparams;
+ krb5_error_code ret;
+
+ ALLOC(s2kparams);
+ if (s2kparams == NULL)
+ return ENOMEM;
+ ret = krb5_data_alloc(s2kparams, len);
+ if (ret) {
+ free(s2kparams);
+ return ret;
+ }
+ _krb5_put_int(s2kparams->data, value, len);
+ *ps2kparams = s2kparams;
+ return 0;
+}
static krb5_error_code
make_etype_info2_entry(ETYPE_INFO2_ENTRY *ent, Key *key)
{
+ krb5_error_code ret;
+
ent->etype = key->key.keytype;
if(key->salt) {
ALLOC(ent->salt);
@@ -585,44 +1155,28 @@ make_etype_info2_entry(ETYPE_INFO2_ENTRY *ent, Key *key)
switch (key->key.keytype) {
case ETYPE_AES128_CTS_HMAC_SHA1_96:
case ETYPE_AES256_CTS_HMAC_SHA1_96:
- ALLOC(ent->s2kparams);
- if (ent->s2kparams == NULL)
- return ENOMEM;
- ent->s2kparams->length = 4;
- ent->s2kparams->data = malloc(ent->s2kparams->length);
- if (ent->s2kparams->data == NULL) {
- free(ent->s2kparams);
- ent->s2kparams = NULL;
- return ENOMEM;
- }
- _krb5_put_int(ent->s2kparams->data,
- _krb5_AES_string_to_default_iterator,
- ent->s2kparams->length);
+ ret = make_s2kparams(_krb5_AES_SHA1_string_to_default_iterator,
+ 4, &ent->s2kparams);
+ break;
+ case KRB5_ENCTYPE_AES128_CTS_HMAC_SHA256_128:
+ case KRB5_ENCTYPE_AES256_CTS_HMAC_SHA384_192:
+ ret = make_s2kparams(_krb5_AES_SHA2_string_to_default_iterator,
+ 4, &ent->s2kparams);
break;
case ETYPE_DES_CBC_CRC:
case ETYPE_DES_CBC_MD4:
case ETYPE_DES_CBC_MD5:
/* Check if this was a AFS3 salted key */
- if(key->salt && key->salt->type == hdb_afs3_salt){
- ALLOC(ent->s2kparams);
- if (ent->s2kparams == NULL)
- return ENOMEM;
- ent->s2kparams->length = 1;
- ent->s2kparams->data = malloc(ent->s2kparams->length);
- if (ent->s2kparams->data == NULL) {
- free(ent->s2kparams);
- ent->s2kparams = NULL;
- return ENOMEM;
- }
- _krb5_put_int(ent->s2kparams->data,
- 1,
- ent->s2kparams->length);
- }
+ if(key->salt && key->salt->type == hdb_afs3_salt)
+ ret = make_s2kparams(1, 1, &ent->s2kparams);
+ else
+ ret = 0;
break;
default:
+ ret = 0;
break;
}
- return 0;
+ return ret;
}
/*
@@ -788,6 +1342,13 @@ kdc_check_flags(krb5_context context,
return KRB5KDC_ERR_NAME_EXP;
}
+ if (client->flags.require_pwchange &&
+ (server_ex == NULL || !server_ex->entry.flags.change_pw)) {
+ kdc_log(context, config, 0,
+ "Client's key must be changed -- %s", client_name);
+ return KRB5KDC_ERR_KEY_EXPIRED;
+ }
+
if (client->pw_end && *client->pw_end < kdc_time
&& (server_ex == NULL || !server_ex->entry.flags.change_pw)) {
char pwend_str[100];
@@ -937,10 +1498,55 @@ send_pac_p(krb5_context context, KDC_REQ *req)
return TRUE;
}
+/*
+ *
+ */
+
+static krb5_error_code
+generate_pac(kdc_request_t r, Key *skey)
+{
+ krb5_error_code ret;
+ krb5_pac p = NULL;
+ krb5_data data;
+
+ ret = _kdc_pac_generate(r->context, r->client, &p);
+ if (ret) {
+ _kdc_r_log(r, 0, "PAC generation failed for -- %s",
+ r->client_name);
+ return ret;
+ }
+ if (p == NULL)
+ return 0;
+
+ ret = _krb5_pac_sign(r->context, p, r->et.authtime,
+ r->client->entry.principal,
+ &skey->key, /* Server key */
+ &skey->key, /* FIXME: should be krbtgt key */
+ &data);
+ krb5_pac_free(r->context, p);
+ if (ret) {
+ _kdc_r_log(r, 0, "PAC signing failed for -- %s",
+ r->client_name);
+ return ret;
+ }
+
+ ret = _kdc_tkt_add_if_relevant_ad(r->context, &r->et,
+ KRB5_AUTHDATA_WIN2K_PAC,
+ &data);
+ krb5_data_free(&data);
+
+ return ret;
+}
+
+/*
+ *
+ */
+
krb5_boolean
_kdc_is_anonymous(krb5_context context, krb5_principal principal)
{
- if (principal->name.name_type != KRB5_NT_WELLKNOWN ||
+ if ((principal->name.name_type != KRB5_NT_WELLKNOWN &&
+ principal->name.name_type != KRB5_NT_UNKNOWN) ||
principal->name.name_string.len != 2 ||
strcmp(principal->name.name_string.val[0], KRB5_WELLKNOWN_NAME) != 0 ||
strcmp(principal->name.name_string.val[1], KRB5_ANON_NAME) != 0)
@@ -948,62 +1554,115 @@ _kdc_is_anonymous(krb5_context context, krb5_principal principal)
return 1;
}
+static int
+require_preauth_p(kdc_request_t r)
+{
+ return r->config->require_preauth
+ || r->client->entry.flags.require_preauth
+ || r->server->entry.flags.require_preauth;
+}
+
+
+/*
+ *
+ */
+
+static krb5_error_code
+add_enc_pa_rep(kdc_request_t r)
+{
+ krb5_error_code ret;
+ krb5_crypto crypto;
+ Checksum checksum;
+ krb5_data cdata;
+ size_t len;
+
+ ret = krb5_crypto_init(r->context, &r->reply_key, 0, &crypto);
+ if (ret)
+ return ret;
+
+ ret = krb5_create_checksum(r->context, crypto,
+ KRB5_KU_AS_REQ, 0,
+ r->request.data, r->request.length,
+ &checksum);
+ krb5_crypto_destroy(r->context, crypto);
+ if (ret)
+ return ret;
+
+ ASN1_MALLOC_ENCODE(Checksum, cdata.data, cdata.length,
+ &checksum, &len, ret);
+ free_Checksum(&checksum);
+ if (ret)
+ return ret;
+ heim_assert(cdata.length == len, "ASN.1 internal error");
+
+ if (r->ek.encrypted_pa_data == NULL) {
+ ALLOC(r->ek.encrypted_pa_data);
+ if (r->ek.encrypted_pa_data == NULL)
+ return ENOMEM;
+ }
+ ret = krb5_padata_add(r->context, r->ek.encrypted_pa_data,
+ KRB5_PADATA_REQ_ENC_PA_REP, cdata.data, cdata.length);
+ if (ret)
+ return ret;
+
+ return krb5_padata_add(r->context, r->ek.encrypted_pa_data,
+ KRB5_PADATA_FX_FAST, NULL, 0);
+}
+
/*
*
*/
krb5_error_code
-_kdc_as_rep(krb5_context context,
- krb5_kdc_configuration *config,
- KDC_REQ *req,
- const krb5_data *req_buffer,
+_kdc_as_rep(kdc_request_t r,
krb5_data *reply,
const char *from,
struct sockaddr *from_addr,
int datagram_reply)
{
- KDC_REQ_BODY *b = &req->req_body;
+ krb5_context context = r->context;
+ krb5_kdc_configuration *config = r->config;
+ KDC_REQ *req = &r->req;
+ KDC_REQ_BODY *b = NULL;
AS_REP rep;
- KDCOptions f = b->kdc_options;
- hdb_entry_ex *client = NULL, *server = NULL;
- HDB *clientdb;
- krb5_enctype setype, sessionetype;
- krb5_data e_data;
- EncTicketPart et;
- EncKDCRepPart ek;
- krb5_principal client_princ = NULL, server_princ = NULL;
- char *client_name = NULL, *server_name = NULL;
+ KDCOptions f;
+ krb5_enctype setype;
krb5_error_code ret = 0;
- const char *e_text = NULL;
- krb5_crypto crypto;
- Key *ckey, *skey;
- EncryptionKey *reply_key = NULL, session_key;
- int flags = HDB_F_FOR_AS_REQ;
-#ifdef PKINIT
- pk_client_params *pkp = NULL;
-#endif
+ Key *skey;
+ int found_pa = 0;
+ int i, flags = HDB_F_FOR_AS_REQ;
+ METHOD_DATA error_method;
+ const PA_DATA *pa;
memset(&rep, 0, sizeof(rep));
- memset(&session_key, 0, sizeof(session_key));
- krb5_data_zero(&e_data);
+ error_method.len = 0;
+ error_method.val = NULL;
+
+ /*
+ * Look for FAST armor and unwrap
+ */
+ ret = _kdc_fast_unwrap_request(r);
+ if (ret) {
+ _kdc_r_log(r, 0, "FAST unwrap request from %s failed: %d", from, ret);
+ goto out;
+ }
- ALLOC(rep.padata);
- rep.padata->len = 0;
- rep.padata->val = NULL;
+ b = &req->req_body;
+ f = b->kdc_options;
if (f.canonicalize)
flags |= HDB_F_CANON;
if(b->sname == NULL){
ret = KRB5KRB_ERR_GENERIC;
- e_text = "No server in request";
+ _kdc_set_e_text(r, "No server in request");
} else{
ret = _krb5_principalname2krb5_principal (context,
- &server_princ,
+ &r->server_princ,
*(b->sname),
b->realm);
if (ret == 0)
- ret = krb5_unparse_name(context, server_princ, &server_name);
+ ret = krb5_unparse_name(context, r->server_princ, &r->server_name);
}
if (ret) {
kdc_log(context, config, 0,
@@ -1012,16 +1671,16 @@ _kdc_as_rep(krb5_context context,
}
if(b->cname == NULL){
ret = KRB5KRB_ERR_GENERIC;
- e_text = "No client in request";
+ _kdc_set_e_text(r, "No client in request");
} else {
ret = _krb5_principalname2krb5_principal (context,
- &client_princ,
+ &r->client_princ,
*(b->cname),
b->realm);
if (ret)
goto out;
- ret = krb5_unparse_name(context, client_princ, &client_name);
+ ret = krb5_unparse_name(context, r->client_princ, &r->client_name);
}
if (ret) {
kdc_log(context, config, 0,
@@ -1030,22 +1689,22 @@ _kdc_as_rep(krb5_context context,
}
kdc_log(context, config, 0, "AS-REQ %s from %s for %s",
- client_name, from, server_name);
+ r->client_name, from, r->server_name);
/*
*
*/
- if (_kdc_is_anonymous(context, client_princ)) {
- if (!b->kdc_options.request_anonymous) {
+ if (_kdc_is_anonymous(context, r->client_princ)) {
+ if (!_kdc_is_anon_request(b)) {
kdc_log(context, config, 0, "Anonymous ticket w/o anonymous flag");
ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
goto out;
}
- } else if (b->kdc_options.request_anonymous) {
+ } else if (_kdc_is_anon_request(b)) {
kdc_log(context, config, 0,
"Request for a anonymous ticket with non "
- "anonymous client name: %s", client_name);
+ "anonymous client name: %s", r->client_name);
ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
goto out;
}
@@ -1054,36 +1713,60 @@ _kdc_as_rep(krb5_context context,
*
*/
- ret = _kdc_db_fetch(context, config, client_princ,
+ ret = _kdc_db_fetch(context, config, r->client_princ,
HDB_F_GET_CLIENT | flags, NULL,
- &clientdb, &client);
+ &r->clientdb, &r->client);
if(ret == HDB_ERR_NOT_FOUND_HERE) {
- kdc_log(context, config, 5, "client %s does not have secrets at this KDC, need to proxy", client_name);
+ kdc_log(context, config, 5, "client %s does not have secrets at this KDC, need to proxy",
+ r->client_name);
+ goto out;
+ } else if (ret == HDB_ERR_WRONG_REALM) {
+ char *fixed_client_name = NULL;
+
+ ret = krb5_unparse_name(context, r->client->entry.principal,
+ &fixed_client_name);
+ if (ret) {
+ goto out;
+ }
+
+ kdc_log(context, config, 0, "WRONG_REALM - %s -> %s",
+ r->client_name, fixed_client_name);
+ free(fixed_client_name);
+
+ ret = _kdc_fast_mk_error(context, r,
+ &error_method,
+ r->armor_crypto,
+ &req->req_body,
+ KRB5_KDC_ERR_WRONG_REALM,
+ NULL,
+ r->server_princ,
+ NULL,
+ &r->client->entry.principal->realm,
+ NULL, NULL,
+ reply);
goto out;
} else if(ret){
const char *msg = krb5_get_error_message(context, ret);
- kdc_log(context, config, 0, "UNKNOWN -- %s: %s", client_name, msg);
+ kdc_log(context, config, 0, "UNKNOWN -- %s: %s", r->client_name, msg);
krb5_free_error_message(context, msg);
ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
goto out;
}
- ret = _kdc_db_fetch(context, config, server_princ,
+ ret = _kdc_db_fetch(context, config, r->server_princ,
HDB_F_GET_SERVER|HDB_F_GET_KRBTGT | flags,
- NULL, NULL, &server);
+ NULL, NULL, &r->server);
if(ret == HDB_ERR_NOT_FOUND_HERE) {
- kdc_log(context, config, 5, "target %s does not have secrets at this KDC, need to proxy", server_name);
+ kdc_log(context, config, 5, "target %s does not have secrets at this KDC, need to proxy",
+ r->server_name);
goto out;
} else if(ret){
const char *msg = krb5_get_error_message(context, ret);
- kdc_log(context, config, 0, "UNKNOWN -- %s: %s", server_name, msg);
+ kdc_log(context, config, 0, "UNKNOWN -- %s: %s", r->server_name, msg);
krb5_free_error_message(context, msg);
ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
goto out;
}
- memset(&et, 0, sizeof(et));
- memset(&ek, 0, sizeof(ek));
-
/*
* Select a session enctype from the list of the crypto system
* supported enctypes that is supported by the client and is one of
@@ -1094,310 +1777,75 @@ _kdc_as_rep(krb5_context context,
* enctype that an older version of a KDC in the same realm can't
* decrypt.
*/
+
ret = _kdc_find_etype(context,
- krb5_principal_is_krbtgt(context, server_princ) ?
+ krb5_principal_is_krbtgt(context, r->server_princ) ?
config->tgt_use_strongest_session_key :
config->svc_use_strongest_session_key, FALSE,
- client, b->etype.val, b->etype.len, &sessionetype,
+ r->client, b->etype.val, b->etype.len, &r->sessionetype,
NULL);
if (ret) {
kdc_log(context, config, 0,
"Client (%s) from %s has no common enctypes with KDC "
"to use for the session key",
- client_name, from);
+ r->client_name, from);
goto out;
}
- /*
- * But if the KDC admin is paranoid and doesn't want to have "not
- * the best" enctypes on the krbtgt, lets save the best pick from
- * the client list and hope that that will work for any other
- * KDCs.
- */
/*
* Pre-auth processing
*/
if(req->padata){
- int i;
- const PA_DATA *pa;
- int found_pa = 0;
+ unsigned int n;
log_patypes(context, config, req->padata);
-#ifdef PKINIT
- kdc_log(context, config, 5,
- "Looking for PKINIT pa-data -- %s", client_name);
+ /* Check if preauth matching */
- e_text = "No PKINIT PA found";
+ for (n = 0; !found_pa && n < sizeof(pat) / sizeof(pat[0]); n++) {
+ if (pat[n].validate == NULL)
+ continue;
+ if (r->armor_crypto == NULL && (pat[n].flags & PA_REQ_FAST))
+ continue;
- i = 0;
- pa = _kdc_find_padata(req, &i, KRB5_PADATA_PK_AS_REQ);
- if (pa == NULL) {
+ kdc_log(context, config, 5,
+ "Looking for %s pa-data -- %s", pat[n].name, r->client_name);
i = 0;
- pa = _kdc_find_padata(req, &i, KRB5_PADATA_PK_AS_REQ_WIN);
- }
- if (pa) {
- char *client_cert = NULL;
-
- ret = _kdc_pk_rd_padata(context, config, req, pa, client, &pkp);
- if (ret) {
- ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
- kdc_log(context, config, 5,
- "Failed to decode PKINIT PA-DATA -- %s",
- client_name);
- goto ts_enc;
- }
- if (ret == 0 && pkp == NULL)
- goto ts_enc;
-
- ret = _kdc_pk_check_client(context,
- config,
- clientdb,
- client,
- pkp,
- &client_cert);
- if (ret) {
- e_text = "PKINIT certificate not allowed to "
- "impersonate principal";
- _kdc_pk_free_client_param(context, pkp);
-
- kdc_log(context, config, 0, "%s", e_text);
- pkp = NULL;
- goto out;
+ pa = _kdc_find_padata(req, &i, pat[n].type);
+ if (pa) {
+ ret = pat[n].validate(r, pa);
+ if (ret != 0) {
+ goto out;
+ }
+ kdc_log(context, config, 0,
+ "%s pre-authentication succeeded -- %s",
+ pat[n].name, r->client_name);
+ found_pa = 1;
+ r->et.flags.pre_authent = 1;
}
-
- found_pa = 1;
- et.flags.pre_authent = 1;
- kdc_log(context, config, 0,
- "PKINIT pre-authentication succeeded -- %s using %s",
- client_name, client_cert);
- free(client_cert);
- if (pkp)
- goto preauth_done;
}
- ts_enc:
-#endif
- kdc_log(context, config, 5, "Looking for ENC-TS pa-data -- %s",
- client_name);
-
- i = 0;
- e_text = "No ENC-TS found";
- while((pa = _kdc_find_padata(req, &i, KRB5_PADATA_ENC_TIMESTAMP))){
- krb5_data ts_data;
- PA_ENC_TS_ENC p;
- size_t len;
- EncryptedData enc_data;
- Key *pa_key;
- char *str;
-
- found_pa = 1;
-
- if (b->kdc_options.request_anonymous) {
- ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
- kdc_log(context, config, 0, "ENC-TS doesn't support anon");
- goto out;
- }
-
- ret = decode_EncryptedData(pa->padata_value.data,
- pa->padata_value.length,
- &enc_data,
- &len);
- if (ret) {
- ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
- kdc_log(context, config, 5, "Failed to decode PA-DATA -- %s",
- client_name);
- goto out;
- }
-
- ret = hdb_enctype2key(context, &client->entry,
- enc_data.etype, &pa_key);
- if(ret){
- char *estr;
- e_text = "No key matches pa-data";
- ret = KRB5KDC_ERR_ETYPE_NOSUPP;
- if(krb5_enctype_to_string(context, enc_data.etype, &estr))
- estr = NULL;
- if(estr == NULL)
- kdc_log(context, config, 5,
- "No client key matching pa-data (%d) -- %s",
- enc_data.etype, client_name);
- else
- kdc_log(context, config, 5,
- "No client key matching pa-data (%s) -- %s",
- estr, client_name);
- free(estr);
- free_EncryptedData(&enc_data);
-
- continue;
- }
+ }
- try_next_key:
- ret = krb5_crypto_init(context, &pa_key->key, 0, &crypto);
- if (ret) {
- const char *msg = krb5_get_error_message(context, ret);
- kdc_log(context, config, 0, "krb5_crypto_init failed: %s", msg);
- krb5_free_error_message(context, msg);
- free_EncryptedData(&enc_data);
- continue;
- }
+ if (found_pa == 0) {
+ Key *ckey = NULL;
+ size_t n;
- ret = krb5_decrypt_EncryptedData (context,
- crypto,
- KRB5_KU_PA_ENC_TIMESTAMP,
- &enc_data,
- &ts_data);
- krb5_crypto_destroy(context, crypto);
- /*
- * Since the user might have several keys with the same
- * enctype but with diffrent salting, we need to try all
- * the keys with the same enctype.
- */
- if(ret){
- krb5_error_code ret2;
- const char *msg = krb5_get_error_message(context, ret);
-
- ret2 = krb5_enctype_to_string(context,
- pa_key->key.keytype, &str);
- if (ret2)
- str = NULL;
- kdc_log(context, config, 5,
- "Failed to decrypt PA-DATA -- %s "
- "(enctype %s) error %s",
- client_name, str ? str : "unknown enctype", msg);
- krb5_free_error_message(context, msg);
- free(str);
-
- if(hdb_next_enctype2key(context, &client->entry,
- enc_data.etype, &pa_key) == 0)
- goto try_next_key;
- e_text = "Failed to decrypt PA-DATA";
-
- free_EncryptedData(&enc_data);
-
- if (clientdb->hdb_auth_status)
- (clientdb->hdb_auth_status)(context, clientdb, client, HDB_AUTH_WRONG_PASSWORD);
-
- ret = KRB5KDC_ERR_PREAUTH_FAILED;
+ for (n = 0; n < sizeof(pat) / sizeof(pat[0]); n++) {
+ if ((pat[n].flags & PA_ANNOUNCE) == 0)
continue;
- }
- free_EncryptedData(&enc_data);
- ret = decode_PA_ENC_TS_ENC(ts_data.data,
- ts_data.length,
- &p,
- &len);
- krb5_data_free(&ts_data);
- if(ret){
- e_text = "Failed to decode PA-ENC-TS-ENC";
- ret = KRB5KDC_ERR_PREAUTH_FAILED;
- kdc_log(context, config,
- 5, "Failed to decode PA-ENC-TS_ENC -- %s",
- client_name);
- continue;
- }
- free_PA_ENC_TS_ENC(&p);
- if (abs(kdc_time - p.patimestamp) > context->max_skew) {
- char client_time[100];
-
- krb5_format_time(context, p.patimestamp,
- client_time, sizeof(client_time), TRUE);
-
- ret = KRB5KRB_AP_ERR_SKEW;
- kdc_log(context, config, 0,
- "Too large time skew, "
- "client time %s is out by %u > %u seconds -- %s",
- client_time,
- (unsigned)abs(kdc_time - p.patimestamp),
- context->max_skew,
- client_name);
-
- /*
- * The following is needed to make windows clients to
- * retry using the timestamp in the error message, if
- * there is a e_text, they become unhappy.
- */
- e_text = NULL;
- goto out;
- }
- et.flags.pre_authent = 1;
-
- set_salt_padata(rep.padata, pa_key->salt);
-
- reply_key = &pa_key->key;
-
- ret = krb5_enctype_to_string(context, pa_key->key.keytype, &str);
+ ret = krb5_padata_add(context, &error_method,
+ pat[n].type, NULL, 0);
if (ret)
- str = NULL;
-
- kdc_log(context, config, 2,
- "ENC-TS Pre-authentication succeeded -- %s using %s",
- client_name, str ? str : "unknown enctype");
- free(str);
- break;
- }
-#ifdef PKINIT
- preauth_done:
-#endif
- if(found_pa == 0 && config->require_preauth)
- goto use_pa;
- /* We come here if we found a pa-enc-timestamp, but if there
- was some problem with it, other than too large skew */
- if(found_pa && et.flags.pre_authent == 0){
- kdc_log(context, config, 0, "%s -- %s", e_text, client_name);
- e_text = NULL;
- goto out;
- }
- }else if (config->require_preauth
- || b->kdc_options.request_anonymous /* hack to force anon */
- || client->entry.flags.require_preauth
- || server->entry.flags.require_preauth) {
- METHOD_DATA method_data;
- PA_DATA *pa;
- unsigned char *buf;
- size_t len;
-
- use_pa:
- method_data.len = 0;
- method_data.val = NULL;
-
- ret = realloc_method_data(&method_data);
- if (ret) {
- free_METHOD_DATA(&method_data);
- goto out;
- }
- pa = &method_data.val[method_data.len-1];
- pa->padata_type = KRB5_PADATA_ENC_TIMESTAMP;
- pa->padata_value.length = 0;
- pa->padata_value.data = NULL;
-
-#ifdef PKINIT
- ret = realloc_method_data(&method_data);
- if (ret) {
- free_METHOD_DATA(&method_data);
- goto out;
- }
- pa = &method_data.val[method_data.len-1];
- pa->padata_type = KRB5_PADATA_PK_AS_REQ;
- pa->padata_value.length = 0;
- pa->padata_value.data = NULL;
-
- ret = realloc_method_data(&method_data);
- if (ret) {
- free_METHOD_DATA(&method_data);
- goto out;
+ goto out;
}
- pa = &method_data.val[method_data.len-1];
- pa->padata_type = KRB5_PADATA_PK_AS_REQ_WIN;
- pa->padata_value.length = 0;
- pa->padata_value.data = NULL;
-#endif
/*
* If there is a client key, send ETYPE_INFO{,2}
*/
ret = _kdc_find_etype(context,
config->preauth_use_strongest_session_key, TRUE,
- client, b->etype.val, b->etype.len, NULL, &ckey);
+ r->client, b->etype.val, b->etype.len, NULL, &ckey);
if (ret == 0) {
/*
@@ -1414,83 +1862,93 @@ _kdc_as_rep(krb5_context context,
if (older_enctype(ckey->key.keytype)) {
ret = get_pa_etype_info(context, config,
- &method_data, ckey);
- if (ret) {
- free_METHOD_DATA(&method_data);
+ &error_method, ckey);
+ if (ret)
goto out;
- }
}
ret = get_pa_etype_info2(context, config,
- &method_data, ckey);
- if (ret) {
- free_METHOD_DATA(&method_data);
+ &error_method, ckey);
+ if (ret)
goto out;
- }
}
- ASN1_MALLOC_ENCODE(METHOD_DATA, buf, len, &method_data, &len, ret);
- free_METHOD_DATA(&method_data);
-
- e_data.data = buf;
- e_data.length = len;
- e_text ="Need to use PA-ENC-TIMESTAMP/PA-PK-AS-REQ",
-
- ret = KRB5KDC_ERR_PREAUTH_REQUIRED;
+ /*
+ * send requre preauth is its required or anon is requested,
+ * anon is today only allowed via preauth mechanisms.
+ */
+ if (require_preauth_p(r) || _kdc_is_anon_request(b)) {
+ ret = KRB5KDC_ERR_PREAUTH_REQUIRED;
+ _kdc_set_e_text(r, "Need to use PA-ENC-TIMESTAMP/PA-PK-AS-REQ");
+ goto out;
+ }
- kdc_log(context, config, 0,
- "No preauth found, returning PREAUTH-REQUIRED -- %s",
- client_name);
- goto out;
+ if (ckey == NULL) {
+ ret = KRB5KDC_ERR_CLIENT_NOTYET;
+ _kdc_set_e_text(r, "Doesn't have a client key available");
+ goto out;
+ }
+ krb5_free_keyblock_contents(r->context, &r->reply_key);
+ ret = krb5_copy_keyblock_contents(r->context, &ckey->key, &r->reply_key);
+ if (ret)
+ goto out;
}
- if (clientdb->hdb_auth_status)
- (clientdb->hdb_auth_status)(context, clientdb, client,
- HDB_AUTH_SUCCESS);
+ if (r->clientdb->hdb_auth_status) {
+ r->clientdb->hdb_auth_status(context, r->clientdb, r->client,
+ HDB_AUTH_SUCCESS);
+ }
/*
* Verify flags after the user been required to prove its identity
* with in a preauth mech.
*/
- ret = _kdc_check_access(context, config, client, client_name,
- server, server_name,
- req, &e_data);
+ ret = _kdc_check_access(context, config, r->client, r->client_name,
+ r->server, r->server_name,
+ req, &error_method);
if(ret)
goto out;
/*
- * Selelct the best encryption type for the KDC with out regard to
+ * Select the best encryption type for the KDC with out regard to
* the client since the client never needs to read that data.
*/
ret = _kdc_get_preferred_key(context, config,
- server, server_name,
+ r->server, r->server_name,
&setype, &skey);
if(ret)
goto out;
if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey
- || (f.request_anonymous && !config->allow_anonymous)) {
+ || (_kdc_is_anon_request(b) && !config->allow_anonymous)) {
ret = KRB5KDC_ERR_BADOPTION;
- e_text = "Bad KDC options";
- kdc_log(context, config, 0, "Bad KDC options -- %s", client_name);
+ _kdc_set_e_text(r, "Bad KDC options");
goto out;
}
+ /*
+ * Build reply
+ */
+
rep.pvno = 5;
rep.msg_type = krb_as_rep;
- ret = copy_Realm(&client->entry.principal->realm, &rep.crealm);
+ if (_kdc_is_anonymous(context, r->client_princ)) {
+ Realm anon_realm=KRB5_ANON_REALM;
+ ret = copy_Realm(&anon_realm, &rep.crealm);
+ } else
+ ret = copy_Realm(&r->client->entry.principal->realm, &rep.crealm);
if (ret)
goto out;
- ret = _krb5_principal2principalname(&rep.cname, client->entry.principal);
+ ret = _krb5_principal2principalname(&rep.cname, r->client->entry.principal);
if (ret)
goto out;
rep.ticket.tkt_vno = 5;
- copy_Realm(&server->entry.principal->realm, &rep.ticket.realm);
+ copy_Realm(&r->server->entry.principal->realm, &rep.ticket.realm);
_krb5_principal2principalname(&rep.ticket.sname,
- server->entry.principal);
+ r->server->entry.principal);
/* java 1.6 expects the name to be the same type, lets allow that
* uncomplicated name-types. */
#define CNT(sp,t) (((sp)->sname->name_type) == KRB5_NT_##t)
@@ -1498,77 +1956,69 @@ _kdc_as_rep(krb5_context context,
rep.ticket.sname.name_type = b->sname->name_type;
#undef CNT
- et.flags.initial = 1;
- if(client->entry.flags.forwardable && server->entry.flags.forwardable)
- et.flags.forwardable = f.forwardable;
+ r->et.flags.initial = 1;
+ if(r->client->entry.flags.forwardable && r->server->entry.flags.forwardable)
+ r->et.flags.forwardable = f.forwardable;
else if (f.forwardable) {
- e_text = "Ticket may not be forwardable";
+ _kdc_set_e_text(r, "Ticket may not be forwardable");
ret = KRB5KDC_ERR_POLICY;
- kdc_log(context, config, 0,
- "Ticket may not be forwardable -- %s", client_name);
goto out;
}
- if(client->entry.flags.proxiable && server->entry.flags.proxiable)
- et.flags.proxiable = f.proxiable;
+ if(r->client->entry.flags.proxiable && r->server->entry.flags.proxiable)
+ r->et.flags.proxiable = f.proxiable;
else if (f.proxiable) {
- e_text = "Ticket may not be proxiable";
+ _kdc_set_e_text(r, "Ticket may not be proxiable");
ret = KRB5KDC_ERR_POLICY;
- kdc_log(context, config, 0,
- "Ticket may not be proxiable -- %s", client_name);
goto out;
}
- if(client->entry.flags.postdate && server->entry.flags.postdate)
- et.flags.may_postdate = f.allow_postdate;
+ if(r->client->entry.flags.postdate && r->server->entry.flags.postdate)
+ r->et.flags.may_postdate = f.allow_postdate;
else if (f.allow_postdate){
- e_text = "Ticket may not be postdate";
+ _kdc_set_e_text(r, "Ticket may not be postdate");
ret = KRB5KDC_ERR_POLICY;
- kdc_log(context, config, 0,
- "Ticket may not be postdatable -- %s", client_name);
goto out;
}
/* check for valid set of addresses */
if(!_kdc_check_addresses(context, config, b->addresses, from_addr)) {
- e_text = "Bad address list in requested";
+ _kdc_set_e_text(r, "Bad address list in requested");
ret = KRB5KRB_AP_ERR_BADADDR;
- kdc_log(context, config, 0,
- "Bad address list requested -- %s", client_name);
goto out;
}
- ret = copy_PrincipalName(&rep.cname, &et.cname);
+ ret = copy_PrincipalName(&rep.cname, &r->et.cname);
if (ret)
goto out;
- ret = copy_Realm(&rep.crealm, &et.crealm);
+ ret = copy_Realm(&rep.crealm, &r->et.crealm);
if (ret)
goto out;
{
time_t start;
time_t t;
-
- start = et.authtime = kdc_time;
+
+ start = r->et.authtime = kdc_time;
if(f.postdated && req->req_body.from){
- ALLOC(et.starttime);
- start = *et.starttime = *req->req_body.from;
- et.flags.invalid = 1;
- et.flags.postdated = 1; /* XXX ??? */
+ ALLOC(r->et.starttime);
+ start = *r->et.starttime = *req->req_body.from;
+ r->et.flags.invalid = 1;
+ r->et.flags.postdated = 1; /* XXX ??? */
}
_kdc_fix_time(&b->till);
t = *b->till;
/* be careful not overflowing */
- if(client->entry.max_life)
- t = start + min(t - start, *client->entry.max_life);
- if(server->entry.max_life)
- t = start + min(t - start, *server->entry.max_life);
+ if(r->client->entry.max_life)
+ t = start + min(t - start, *r->client->entry.max_life);
+ if(r->server->entry.max_life)
+ t = start + min(t - start, *r->server->entry.max_life);
#if 0
t = min(t, start + realm->max_life);
#endif
- et.endtime = t;
- if(f.renewable_ok && et.endtime < *b->till){
+ r->et.endtime = t;
+ if(f.renewable_ok && r->et.endtime < *b->till){
f.renewable = 1;
if(b->rtime == NULL){
ALLOC(b->rtime);
@@ -1581,29 +2031,29 @@ _kdc_as_rep(krb5_context context,
t = *b->rtime;
if(t == 0)
t = MAX_TIME;
- if(client->entry.max_renew)
- t = start + min(t - start, *client->entry.max_renew);
- if(server->entry.max_renew)
- t = start + min(t - start, *server->entry.max_renew);
+ if(r->client->entry.max_renew)
+ t = start + min(t - start, *r->client->entry.max_renew);
+ if(r->server->entry.max_renew)
+ t = start + min(t - start, *r->server->entry.max_renew);
#if 0
t = min(t, start + realm->max_renew);
#endif
- ALLOC(et.renew_till);
- *et.renew_till = t;
- et.flags.renewable = 1;
+ ALLOC(r->et.renew_till);
+ *r->et.renew_till = t;
+ r->et.flags.renewable = 1;
}
}
- if (f.request_anonymous)
- et.flags.anonymous = 1;
+ if (_kdc_is_anon_request(b))
+ r->et.flags.anonymous = 1;
if(b->addresses){
- ALLOC(et.caddr);
- copy_HostAddresses(b->addresses, et.caddr);
+ ALLOC(r->et.caddr);
+ copy_HostAddresses(b->addresses, r->et.caddr);
}
- et.transited.tr_type = DOMAIN_X500_COMPRESS;
- krb5_data_zero(&et.transited.contents);
+ r->et.transited.tr_type = DOMAIN_X500_COMPRESS;
+ krb5_data_zero(&r->et.transited.contents);
/* The MIT ASN.1 library (obviously) doesn't tell lengths encoded
* as 0 and as 0x80 (meaning indefinite length) apart, and is thus
@@ -1614,246 +2064,219 @@ _kdc_as_rep(krb5_context context,
* If there's a pw_end or valid_end we will use that,
* otherwise just a dummy lr.
*/
- ek.last_req.val = malloc(2 * sizeof(*ek.last_req.val));
- if (ek.last_req.val == NULL) {
+ r->ek.last_req.val = malloc(2 * sizeof(*r->ek.last_req.val));
+ if (r->ek.last_req.val == NULL) {
ret = ENOMEM;
goto out;
}
- ek.last_req.len = 0;
- if (client->entry.pw_end
+ r->ek.last_req.len = 0;
+ if (r->client->entry.pw_end
&& (config->kdc_warn_pwexpire == 0
- || kdc_time + config->kdc_warn_pwexpire >= *client->entry.pw_end)) {
- ek.last_req.val[ek.last_req.len].lr_type = LR_PW_EXPTIME;
- ek.last_req.val[ek.last_req.len].lr_value = *client->entry.pw_end;
- ++ek.last_req.len;
- }
- if (client->entry.valid_end) {
- ek.last_req.val[ek.last_req.len].lr_type = LR_ACCT_EXPTIME;
- ek.last_req.val[ek.last_req.len].lr_value = *client->entry.valid_end;
- ++ek.last_req.len;
- }
- if (ek.last_req.len == 0) {
- ek.last_req.val[ek.last_req.len].lr_type = LR_NONE;
- ek.last_req.val[ek.last_req.len].lr_value = 0;
- ++ek.last_req.len;
- }
- ek.nonce = b->nonce;
- if (client->entry.valid_end || client->entry.pw_end) {
- ALLOC(ek.key_expiration);
- if (client->entry.valid_end) {
- if (client->entry.pw_end)
- *ek.key_expiration = min(*client->entry.valid_end,
- *client->entry.pw_end);
+ || kdc_time + config->kdc_warn_pwexpire >= *r->client->entry.pw_end)) {
+ r->ek.last_req.val[r->ek.last_req.len].lr_type = LR_PW_EXPTIME;
+ r->ek.last_req.val[r->ek.last_req.len].lr_value = *r->client->entry.pw_end;
+ ++r->ek.last_req.len;
+ }
+ if (r->client->entry.valid_end) {
+ r->ek.last_req.val[r->ek.last_req.len].lr_type = LR_ACCT_EXPTIME;
+ r->ek.last_req.val[r->ek.last_req.len].lr_value = *r->client->entry.valid_end;
+ ++r->ek.last_req.len;
+ }
+ if (r->ek.last_req.len == 0) {
+ r->ek.last_req.val[r->ek.last_req.len].lr_type = LR_NONE;
+ r->ek.last_req.val[r->ek.last_req.len].lr_value = 0;
+ ++r->ek.last_req.len;
+ }
+ r->ek.nonce = b->nonce;
+ if (r->client->entry.valid_end || r->client->entry.pw_end) {
+ ALLOC(r->ek.key_expiration);
+ if (r->client->entry.valid_end) {
+ if (r->client->entry.pw_end)
+ *r->ek.key_expiration = min(*r->client->entry.valid_end,
+ *r->client->entry.pw_end);
else
- *ek.key_expiration = *client->entry.valid_end;
+ *r->ek.key_expiration = *r->client->entry.valid_end;
} else
- *ek.key_expiration = *client->entry.pw_end;
+ *r->ek.key_expiration = *r->client->entry.pw_end;
} else
- ek.key_expiration = NULL;
- ek.flags = et.flags;
- ek.authtime = et.authtime;
- if (et.starttime) {
- ALLOC(ek.starttime);
- *ek.starttime = *et.starttime;
- }
- ek.endtime = et.endtime;
- if (et.renew_till) {
- ALLOC(ek.renew_till);
- *ek.renew_till = *et.renew_till;
- }
- copy_Realm(&rep.ticket.realm, &ek.srealm);
- copy_PrincipalName(&rep.ticket.sname, &ek.sname);
- if(et.caddr){
- ALLOC(ek.caddr);
- copy_HostAddresses(et.caddr, ek.caddr);
- }
-
-#if PKINIT
- if (pkp) {
- e_text = "Failed to build PK-INIT reply";
- ret = _kdc_pk_mk_pa_reply(context, config, pkp, client,
- sessionetype, req, req_buffer,
- &reply_key, &et.key, rep.padata);
- if (ret)
- goto out;
- ret = _kdc_add_inital_verified_cas(context,
- config,
- pkp,
- &et);
- if (ret)
- goto out;
+ r->ek.key_expiration = NULL;
+ r->ek.flags = r->et.flags;
+ r->ek.authtime = r->et.authtime;
+ if (r->et.starttime) {
+ ALLOC(r->ek.starttime);
+ *r->ek.starttime = *r->et.starttime;
+ }
+ r->ek.endtime = r->et.endtime;
+ if (r->et.renew_till) {
+ ALLOC(r->ek.renew_till);
+ *r->ek.renew_till = *r->et.renew_till;
+ }
+ copy_Realm(&rep.ticket.realm, &r->ek.srealm);
+ copy_PrincipalName(&rep.ticket.sname, &r->ek.sname);
+ if(r->et.caddr){
+ ALLOC(r->ek.caddr);
+ copy_HostAddresses(r->et.caddr, r->ek.caddr);
+ }
- } else
-#endif
- {
- ret = krb5_generate_random_keyblock(context, sessionetype, &et.key);
+ /*
+ * Check and session and reply keys
+ */
+
+ if (r->session_key.keytype == ETYPE_NULL) {
+ ret = krb5_generate_random_keyblock(context, r->sessionetype, &r->session_key);
if (ret)
goto out;
}
- if (reply_key == NULL) {
- e_text = "Client have no reply key";
+ if (r->reply_key.keytype == ETYPE_NULL) {
+ _kdc_set_e_text(r, "Client have no reply key");
ret = KRB5KDC_ERR_CLIENT_NOTYET;
goto out;
}
- ret = copy_EncryptionKey(&et.key, &ek.key);
+ ret = copy_EncryptionKey(&r->session_key, &r->et.key);
if (ret)
goto out;
- /* Add signing of alias referral */
- if (f.canonicalize) {
- PA_ClientCanonicalized canon;
- krb5_data data;
- PA_DATA pa;
- krb5_crypto cryptox;
- size_t len = 0;
-
- memset(&canon, 0, sizeof(canon));
+ ret = copy_EncryptionKey(&r->session_key, &r->ek.key);
+ if (ret)
+ goto out;
- canon.names.requested_name = *b->cname;
- canon.names.mapped_name = client->entry.principal->name;
+ if (r->outpadata.len) {
- ASN1_MALLOC_ENCODE(PA_ClientCanonicalizedNames, data.data, data.length,
- &canon.names, &len, ret);
- if (ret)
- goto out;
- if (data.length != len)
- krb5_abortx(context, "internal asn.1 error");
-
- /* sign using "returned session key" */
- ret = krb5_crypto_init(context, &et.key, 0, &cryptox);
- if (ret) {
- free(data.data);
+ ALLOC(rep.padata);
+ if (rep.padata == NULL) {
+ ret = ENOMEM;
goto out;
}
-
- ret = krb5_create_checksum(context, cryptox,
- KRB5_KU_CANONICALIZED_NAMES, 0,
- data.data, data.length,
- &canon.canon_checksum);
- free(data.data);
- krb5_crypto_destroy(context, cryptox);
- if (ret)
- goto out;
-
- ASN1_MALLOC_ENCODE(PA_ClientCanonicalized, data.data, data.length,
- &canon, &len, ret);
- free_Checksum(&canon.canon_checksum);
+ ret = copy_METHOD_DATA(&r->outpadata, rep.padata);
if (ret)
goto out;
- if (data.length != len)
- krb5_abortx(context, "internal asn.1 error");
-
- pa.padata_type = KRB5_PADATA_CLIENT_CANONICALIZED;
- pa.padata_value = data;
- ret = add_METHOD_DATA(rep.padata, &pa);
- free(data.data);
- if (ret)
- goto out;
- }
-
- if (rep.padata->len == 0) {
- free(rep.padata);
- rep.padata = NULL;
}
/* Add the PAC */
if (send_pac_p(context, req)) {
- krb5_pac p = NULL;
- krb5_data data;
-
- ret = _kdc_pac_generate(context, client, &p);
- if (ret) {
- kdc_log(context, config, 0, "PAC generation failed for -- %s",
- client_name);
- goto out;
- }
- if (p != NULL) {
- ret = _krb5_pac_sign(context, p, et.authtime,
- client->entry.principal,
- &skey->key, /* Server key */
- &skey->key, /* FIXME: should be krbtgt key */
- &data);
- krb5_pac_free(context, p);
- if (ret) {
- kdc_log(context, config, 0, "PAC signing failed for -- %s",
- client_name);
- goto out;
- }
-
- ret = _kdc_tkt_add_if_relevant_ad(context, &et,
- KRB5_AUTHDATA_WIN2K_PAC,
- &data);
- krb5_data_free(&data);
- if (ret)
- goto out;
- }
+ generate_pac(r, skey);
}
- _kdc_log_timestamp(context, config, "AS-REQ", et.authtime, et.starttime,
- et.endtime, et.renew_till);
+ _kdc_log_timestamp(context, config, "AS-REQ", r->et.authtime, r->et.starttime,
+ r->et.endtime, r->et.renew_till);
/* do this as the last thing since this signs the EncTicketPart */
ret = _kdc_add_KRB5SignedPath(context,
config,
- server,
+ r->server,
setype,
- client->entry.principal,
+ r->client->entry.principal,
NULL,
NULL,
- &et);
+ &r->et);
if (ret)
goto out;
- log_as_req(context, config, reply_key->keytype, setype, b);
+ log_as_req(context, config, r->reply_key.keytype, setype, b);
+
+ /*
+ * We always say we support FAST/enc-pa-rep
+ */
+
+ r->et.flags.enc_pa_rep = r->ek.flags.enc_pa_rep = 1;
+
+ /*
+ * Add REQ_ENC_PA_REP if client supports it
+ */
+
+ i = 0;
+ pa = _kdc_find_padata(req, &i, KRB5_PADATA_REQ_ENC_PA_REP);
+ if (pa) {
+
+ ret = add_enc_pa_rep(r);
+ if (ret) {
+ const char *msg = krb5_get_error_message(r->context, ret);
+ _kdc_r_log(r, 0, "add_enc_pa_rep failed: %s: %d", msg, ret);
+ krb5_free_error_message(r->context, msg);
+ goto out;
+ }
+ }
+
+ /*
+ *
+ */
ret = _kdc_encode_reply(context, config,
- &rep, &et, &ek, setype, server->entry.kvno,
- &skey->key, client->entry.kvno,
- reply_key, 0, &e_text, reply);
- free_EncTicketPart(&et);
- free_EncKDCRepPart(&ek);
+ r->armor_crypto, req->req_body.nonce,
+ &rep, &r->et, &r->ek, setype, r->server->entry.kvno,
+ &skey->key, r->client->entry.kvno,
+ &r->reply_key, 0, &r->e_text, reply);
if (ret)
goto out;
- /* */
+ /*
+ * Check if message too large
+ */
if (datagram_reply && reply->length > config->max_datagram_reply_length) {
krb5_data_free(reply);
ret = KRB5KRB_ERR_RESPONSE_TOO_BIG;
- e_text = "Reply packet too large";
+ _kdc_set_e_text(r, "Reply packet too large");
}
out:
free_AS_REP(&rep);
- if(ret != 0 && ret != HDB_ERR_NOT_FOUND_HERE){
- krb5_mk_error(context,
- ret,
- e_text,
- (e_data.data ? &e_data : NULL),
- client_princ,
- server_princ,
- NULL,
- NULL,
- reply);
- ret = 0;
+
+ /*
+ * In case of a non proxy error, build an error message.
+ */
+ if (ret != 0 && ret != HDB_ERR_NOT_FOUND_HERE && reply->length == 0) {
+ ret = _kdc_fast_mk_error(context, r,
+ &error_method,
+ r->armor_crypto,
+ &req->req_body,
+ ret, r->e_text,
+ r->server_princ,
+ r->client_princ ?
+ &r->client_princ->name : NULL,
+ r->client_princ ?
+ &r->client_princ->realm : NULL,
+ NULL, NULL,
+ reply);
+ if (ret)
+ goto out2;
}
-#ifdef PKINIT
- if (pkp)
- _kdc_pk_free_client_param(context, pkp);
-#endif
- if (e_data.data)
- free(e_data.data);
- if (client_princ)
- krb5_free_principal(context, client_princ);
- free(client_name);
- if (server_princ)
- krb5_free_principal(context, server_princ);
- free(server_name);
- if(client)
- _kdc_free_ent(context, client);
- if(server)
- _kdc_free_ent(context, server);
+out2:
+ free_EncTicketPart(&r->et);
+ free_EncKDCRepPart(&r->ek);
+ free_KDCFastState(&r->fast);
+
+ if (error_method.len)
+ free_METHOD_DATA(&error_method);
+ if (r->outpadata.len)
+ free_METHOD_DATA(&r->outpadata);
+ if (r->client_princ) {
+ krb5_free_principal(context, r->client_princ);
+ r->client_princ = NULL;
+ }
+ if (r->client_name) {
+ free(r->client_name);
+ r->client_name = NULL;
+ }
+ if (r->server_princ){
+ krb5_free_principal(context, r->server_princ);
+ r->server_princ = NULL;
+ }
+ if (r->server_name) {
+ free(r->server_name);
+ r->server_name = NULL;
+ }
+ if (r->client)
+ _kdc_free_ent(context, r->client);
+ if (r->server)
+ _kdc_free_ent(context, r->server);
+ if (r->armor_crypto) {
+ krb5_crypto_destroy(r->context, r->armor_crypto);
+ r->armor_crypto = NULL;
+ }
+ krb5_free_keyblock_contents(r->context, &r->reply_key);
+ krb5_free_keyblock_contents(r->context, &r->session_key);
return ret;
}
@@ -1917,3 +2340,14 @@ _kdc_tkt_add_if_relevant_ad(krb5_context context,
return 0;
}
+
+krb5_boolean
+_kdc_is_anon_request(const KDC_REQ_BODY *b)
+{
+ /* some versions of heimdal use bit 14 instead of 16 for
+ request_anonymous, as indicated in the anonymous draft prior to
+ version 11. Bit 14 is assigned to S4U2Proxy, but all S4U2Proxy
+ requests will have a second ticket; don't consider those anonymous */
+ return (b->kdc_options.request_anonymous ||
+ (b->kdc_options.constrained_delegation && !b->additional_tickets));
+}
diff --git a/kdc/krb5tgs.c b/kdc/krb5tgs.c
index 87e33930be15..b6ccb68ed3b0 100644
--- a/kdc/krb5tgs.c
+++ b/kdc/krb5tgs.c
@@ -139,7 +139,7 @@ _kdc_add_KRB5SignedPath(krb5_context context,
{
Key *key;
- ret = hdb_enctype2key(context, &krbtgt->entry, enctype, &key);
+ ret = hdb_enctype2key(context, &krbtgt->entry, NULL, enctype, &key);
if (ret == 0)
ret = krb5_crypto_init(context, &key->key, 0, &crypto);
if (ret) {
@@ -226,7 +226,8 @@ check_KRB5SignedPath(krb5_context context,
{
Key *key;
- ret = hdb_enctype2key(context, &krbtgt->entry, sp.etype, &key);
+ ret = hdb_enctype2key(context, &krbtgt->entry, NULL, /* XXX use correct kvno! */
+ sp.etype, &key);
if (ret == 0)
ret = krb5_crypto_init(context, &key->key, 0, &crypto);
if (ret) {
@@ -284,7 +285,6 @@ check_PAC(krb5_context context,
hdb_entry_ex *server,
hdb_entry_ex *krbtgt,
const EncryptionKey *server_check_key,
- const EncryptionKey *krbtgt_check_key,
const EncryptionKey *server_sign_key,
const EncryptionKey *krbtgt_sign_key,
EncTicketPart *tkt,
@@ -330,7 +330,7 @@ check_PAC(krb5_context context,
ret = krb5_pac_verify(context, pac, tkt->authtime,
client_principal,
- server_check_key, krbtgt_check_key);
+ server_check_key, NULL);
if (ret) {
krb5_pac_free(context, pac);
return ret;
@@ -655,8 +655,12 @@ fix_transited_encoding(krb5_context context,
"Decoding transited encoding");
return ret;
}
+
+ /*
+ * If the realm of the presented tgt is neither the client nor the server
+ * realm, it is a transit realm and must be added to transited set.
+ */
if(strcmp(client_realm, tgt_realm) && strcmp(server_realm, tgt_realm)) {
- /* not us, so add the previous realm to transited set */
if (num_realms + 1 > UINT_MAX/sizeof(*realms)) {
ret = ERANGE;
goto free_realms;
@@ -737,6 +741,7 @@ tgs_make_reply(krb5_context context,
const char *server_name,
hdb_entry_ex *client,
krb5_principal client_principal,
+ const char *tgt_realm,
hdb_entry_ex *krbtgt,
krb5_enctype krbtgt_etype,
krb5_principals spp,
@@ -798,7 +803,7 @@ tgs_make_reply(krb5_context context,
&tgt->transited, &et,
krb5_principal_get_realm(context, client_principal),
krb5_principal_get_realm(context, server->entry.principal),
- krb5_principal_get_realm(context, krbtgt->entry.principal));
+ tgt_realm);
if(ret)
goto out;
@@ -814,8 +819,6 @@ tgs_make_reply(krb5_context context,
rep.ticket.tkt_vno = 5;
ek.caddr = et.caddr;
- if(et.caddr == NULL)
- et.caddr = tgt->caddr;
{
time_t life;
@@ -836,12 +839,12 @@ tgs_make_reply(krb5_context context,
}
if(et.renew_till){
time_t renew;
- renew = *et.renew_till - et.authtime;
+ renew = *et.renew_till - *et.starttime;
if(client && client->entry.max_renew)
renew = min(renew, *client->entry.max_renew);
if(server->entry.max_renew)
renew = min(renew, *server->entry.max_renew);
- *et.renew_till = et.authtime + renew;
+ *et.renew_till = *et.starttime + renew;
}
if(et.renew_till){
@@ -922,12 +925,12 @@ tgs_make_reply(krb5_context context,
ek.key = et.key;
/* MIT must have at least one last_req */
- ek.last_req.len = 1;
ek.last_req.val = calloc(1, sizeof(*ek.last_req.val));
if (ek.last_req.val == NULL) {
ret = ENOMEM;
goto out;
}
+ ek.last_req.len = 1; /* set after alloc to avoid null deref on cleanup */
ek.nonce = b->nonce;
ek.flags = et.flags;
ek.authtime = et.authtime;
@@ -969,10 +972,10 @@ tgs_make_reply(krb5_context context,
goto out;
}
- if (krb5_enctype_valid(context, et.key.keytype) != 0
- && _kdc_is_weak_exception(server->entry.principal, et.key.keytype))
+ if (krb5_enctype_valid(context, serverkey->keytype) != 0
+ && _kdc_is_weak_exception(server->entry.principal, serverkey->keytype))
{
- krb5_enctype_enable(context, et.key.keytype);
+ krb5_enctype_enable(context, serverkey->keytype);
is_weak = 1;
}
@@ -987,13 +990,13 @@ tgs_make_reply(krb5_context context,
CAST session key. Should the DES3 etype be added to the
etype list, even if we don't want a session key with
DES3? */
- ret = _kdc_encode_reply(context, config,
- &rep, &et, &ek, et.key.keytype,
+ ret = _kdc_encode_reply(context, config, NULL, 0,
+ &rep, &et, &ek, serverkey->keytype,
kvno,
serverkey, 0, replykey, rk_is_subkey,
e_text, reply);
if (is_weak)
- krb5_enctype_disable(context, et.key.keytype);
+ krb5_enctype_disable(context, serverkey->keytype);
out:
free_TGS_REP(&rep);
@@ -1092,23 +1095,6 @@ out:
return ret;
}
-/*
- *
- */
-
-static const char *
-find_rpath(krb5_context context, Realm crealm, Realm srealm)
-{
- const char *new_realm = krb5_config_get_string(context,
- NULL,
- "capaths",
- crealm,
- srealm,
- NULL);
- return new_realm;
-}
-
-
static krb5_boolean
need_referral(krb5_context context, krb5_kdc_configuration *config,
const KDCOptions * const options, krb5_principal server,
@@ -1121,7 +1107,23 @@ need_referral(krb5_context context, krb5_kdc_configuration *config,
if (server->name.name_string.len == 1)
name = server->name.name_string.val[0];
- else if (server->name.name_string.len > 1)
+ else if (server->name.name_string.len == 3) {
+ /*
+ This is used to give referrals for the
+ E3514235-4B06-11D1-AB04-00C04FC2DCD2/NTDSGUID/DNSDOMAIN
+ SPN form, which is used for inter-domain communication in AD
+ */
+ name = server->name.name_string.val[2];
+ kdc_log(context, config, 0, "Giving 3 part referral for %s", name);
+ *realms = malloc(sizeof(char *)*2);
+ if (*realms == NULL) {
+ krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
+ return FALSE;
+ }
+ (*realms)[0] = strdup(name);
+ (*realms)[1] = NULL;
+ return TRUE;
+ } else if (server->name.name_string.len > 1)
name = server->name.name_string.val[1];
else
return FALSE;
@@ -1156,6 +1158,10 @@ tgs_parse_request(krb5_context context,
krb5_flags ap_req_options;
krb5_flags verify_ap_req_flags;
krb5_crypto crypto;
+ krb5uint32 krbtgt_kvno; /* kvno used for the PA-TGS-REQ AP-REQ Ticket */
+ krb5uint32 krbtgt_kvno_try;
+ int kvno_search_tries = 4; /* number of kvnos to try when tkt_vno == 0 */
+ const Keys *krbtgt_keys;/* keyset for TGT tkt_vno */
Key *tkey;
krb5_keyblock *subkey = NULL;
unsigned usage;
@@ -1186,59 +1192,78 @@ tgs_parse_request(krb5_context context,
ap_req.ticket.sname,
ap_req.ticket.realm);
- ret = _kdc_db_fetch(context, config, princ, HDB_F_GET_KRBTGT, ap_req.ticket.enc_part.kvno, NULL, krbtgt);
+ krbtgt_kvno = ap_req.ticket.enc_part.kvno ? *ap_req.ticket.enc_part.kvno : 0;
+ ret = _kdc_db_fetch(context, config, princ, HDB_F_GET_KRBTGT,
+ &krbtgt_kvno, NULL, krbtgt);
- if(ret == HDB_ERR_NOT_FOUND_HERE) {
+ if (ret == HDB_ERR_NOT_FOUND_HERE) {
+ /* XXX Factor out this unparsing of the same princ all over */
char *p;
ret = krb5_unparse_name(context, princ, &p);
if (ret != 0)
p = failed;
krb5_free_principal(context, princ);
- kdc_log(context, config, 5, "Ticket-granting ticket account %s does not have secrets at this KDC, need to proxy", p);
+ kdc_log(context, config, 5,
+ "Ticket-granting ticket account %s does not have secrets at "
+ "this KDC, need to proxy", p);
if (ret == 0)
free(p);
ret = HDB_ERR_NOT_FOUND_HERE;
goto out;
- } else if(ret){
- const char *msg = krb5_get_error_message(context, ret);
+ } else if (ret == HDB_ERR_KVNO_NOT_FOUND) {
char *p;
ret = krb5_unparse_name(context, princ, &p);
if (ret != 0)
p = failed;
krb5_free_principal(context, princ);
- kdc_log(context, config, 0,
- "Ticket-granting ticket not found in database: %s", msg);
- krb5_free_error_message(context, msg);
+ kdc_log(context, config, 5,
+ "Ticket-granting ticket account %s does not have keys for "
+ "kvno %d at this KDC", p, krbtgt_kvno);
if (ret == 0)
free(p);
- ret = KRB5KRB_AP_ERR_NOT_US;
+ ret = HDB_ERR_KVNO_NOT_FOUND;
goto out;
- }
-
- if(ap_req.ticket.enc_part.kvno &&
- *ap_req.ticket.enc_part.kvno != (*krbtgt)->entry.kvno){
+ } else if (ret == HDB_ERR_NO_MKEY) {
char *p;
-
- ret = krb5_unparse_name (context, princ, &p);
+ ret = krb5_unparse_name(context, princ, &p);
+ if (ret != 0)
+ p = failed;
krb5_free_principal(context, princ);
+ kdc_log(context, config, 5,
+ "Missing master key for decrypting keys for ticket-granting "
+ "ticket account %s with kvno %d at this KDC", p, krbtgt_kvno);
+ if (ret == 0)
+ free(p);
+ ret = HDB_ERR_KVNO_NOT_FOUND;
+ goto out;
+ } else if (ret) {
+ const char *msg = krb5_get_error_message(context, ret);
+ char *p;
+ ret = krb5_unparse_name(context, princ, &p);
if (ret != 0)
p = failed;
+ krb5_free_principal(context, princ);
kdc_log(context, config, 0,
- "Ticket kvno = %d, DB kvno = %d (%s)",
- *ap_req.ticket.enc_part.kvno,
- (*krbtgt)->entry.kvno,
- p);
+ "Ticket-granting ticket not found in database: %s", msg);
+ krb5_free_error_message(context, msg);
if (ret == 0)
- free (p);
- ret = KRB5KRB_AP_ERR_BADKEYVER;
+ free(p);
+ ret = KRB5KRB_AP_ERR_NOT_US;
goto out;
}
+ krbtgt_kvno_try = krbtgt_kvno ? krbtgt_kvno : (*krbtgt)->entry.kvno;
*krbtgt_etype = ap_req.ticket.enc_part.etype;
- ret = hdb_enctype2key(context, &(*krbtgt)->entry,
+next_kvno:
+ krbtgt_keys = hdb_kvno2keys(context, &(*krbtgt)->entry, krbtgt_kvno_try);
+ ret = hdb_enctype2key(context, &(*krbtgt)->entry, krbtgt_keys,
ap_req.ticket.enc_part.etype, &tkey);
- if(ret){
+ if (ret && krbtgt_kvno == 0 && kvno_search_tries > 0) {
+ kvno_search_tries--;
+ krbtgt_kvno_try--;
+ goto next_kvno;
+ } else if (ret) {
char *str = NULL, *p = NULL;
krb5_enctype_to_string(context, ap_req.ticket.enc_part.etype, &str);
@@ -1267,6 +1292,11 @@ tgs_parse_request(krb5_context context,
&ap_req_options,
ticket,
KRB5_KU_TGS_REQ_AUTH);
+ if (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY && kvno_search_tries > 0) {
+ kvno_search_tries--;
+ krbtgt_kvno_try--;
+ goto next_kvno;
+ }
krb5_free_principal(context, princ);
if(ret) {
@@ -1481,10 +1511,10 @@ tgs_build_reply(krb5_context context,
AuthorizationData **auth_data,
const struct sockaddr *from_addr)
{
- krb5_error_code ret;
+ krb5_error_code ret, ret2;
krb5_principal cp = NULL, sp = NULL, rsp = NULL, tp = NULL, dp = NULL;
- krb5_principal krbtgt_principal = NULL;
- char *spn = NULL, *cpn = NULL, *tpn = NULL, *dpn = NULL;
+ krb5_principal krbtgt_out_principal = NULL;
+ char *spn = NULL, *cpn = NULL, *tpn = NULL, *dpn = NULL, *krbtgt_out_n = NULL;
hdb_entry_ex *server = NULL, *client = NULL, *s4u2self_impersonated_client = NULL;
HDB *clientdb, *s4u2self_impersonated_clientdb;
krb5_realm ref_realm = NULL;
@@ -1494,6 +1524,12 @@ tgs_build_reply(krb5_context context,
krb5_keyblock sessionkey;
krb5_kvno kvno;
krb5_data rspac;
+ const char *tgt_realm = /* Realm of TGT issuer */
+ krb5_principal_get_realm(context, krbtgt->entry.principal);
+ const char *our_realm = /* Realm of this KDC */
+ krb5_principal_get_comp_string(context, krbtgt->entry.principal, 1);
+ char **capath = NULL;
+ size_t num_capath = 0;
hdb_entry_ex *krbtgt_out = NULL;
@@ -1501,7 +1537,6 @@ tgs_build_reply(krb5_context context,
PrincipalName *s;
Realm r;
- int nloop = 0;
EncTicketPart adtkt;
char opt_str[128];
int signedpath = 0;
@@ -1528,6 +1563,8 @@ tgs_build_reply(krb5_context context,
hdb_entry_ex *uu;
krb5_principal p;
Key *uukey;
+ krb5uint32 second_kvno = 0;
+ krb5uint32 *kvno_ptr = NULL;
if(b->additional_tickets == NULL ||
b->additional_tickets->len == 0){
@@ -1544,8 +1581,12 @@ tgs_build_reply(krb5_context context,
goto out;
}
_krb5_principalname2krb5_principal(context, &p, t->sname, t->realm);
+ if(t->enc_part.kvno){
+ second_kvno = *t->enc_part.kvno;
+ kvno_ptr = &second_kvno;
+ }
ret = _kdc_db_fetch(context, config, p,
- HDB_F_GET_KRBTGT, t->enc_part.kvno,
+ HDB_F_GET_KRBTGT, kvno_ptr,
NULL, &uu);
krb5_free_principal(context, p);
if(ret){
@@ -1553,7 +1594,7 @@ tgs_build_reply(krb5_context context,
ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
goto out;
}
- ret = hdb_enctype2key(context, &uu->entry,
+ ret = hdb_enctype2key(context, &uu->entry, NULL,
t->enc_part.etype, &uukey);
if(ret){
_kdc_free_ent(context, uu);
@@ -1600,51 +1641,92 @@ server_lookup:
ret = _kdc_db_fetch(context, config, sp, HDB_F_GET_SERVER | flags,
NULL, NULL, &server);
- if(ret == HDB_ERR_NOT_FOUND_HERE) {
+ if (ret == HDB_ERR_NOT_FOUND_HERE) {
kdc_log(context, config, 5, "target %s does not have secrets at this KDC, need to proxy", sp);
goto out;
- } else if(ret){
+ } else if (ret == HDB_ERR_WRONG_REALM) {
+ free(ref_realm);
+ ref_realm = strdup(server->entry.principal->realm);
+ if (ref_realm == NULL) {
+ ret = krb5_enomem(context);
+ goto out;
+ }
+
+ kdc_log(context, config, 5,
+ "Returning a referral to realm %s for "
+ "server %s.",
+ ref_realm, spn);
+ krb5_free_principal(context, sp);
+ sp = NULL;
+ ret = krb5_make_principal(context, &sp, r, KRB5_TGS_NAME,
+ ref_realm, NULL);
+ if (ret)
+ goto out;
+ free(spn);
+ spn = NULL;
+ ret = krb5_unparse_name(context, sp, &spn);
+ if (ret)
+ goto out;
+
+ goto server_lookup;
+ } else if (ret) {
const char *new_rlm, *msg;
Realm req_rlm;
krb5_realm *realms;
if ((req_rlm = get_krbtgt_realm(&sp->name)) != NULL) {
- if(nloop++ < 2) {
- new_rlm = find_rpath(context, tgt->crealm, req_rlm);
- if(new_rlm) {
- kdc_log(context, config, 5, "krbtgt for realm %s "
- "not found, trying %s",
- req_rlm, new_rlm);
- krb5_free_principal(context, sp);
- free(spn);
- krb5_make_principal(context, &sp, r,
- KRB5_TGS_NAME, new_rlm, NULL);
- ret = krb5_unparse_name(context, sp, &spn);
- if (ret)
- goto out;
-
- if (ref_realm)
- free(ref_realm);
- ref_realm = strdup(new_rlm);
- goto server_lookup;
- }
- }
- } else if(need_referral(context, config, &b->kdc_options, sp, &realms)) {
+ if (capath == NULL) {
+ /* With referalls, hierarchical capaths are always enabled */
+ ret2 = _krb5_find_capath(context, tgt->crealm, our_realm,
+ req_rlm, TRUE, &capath, &num_capath);
+ if (ret2) {
+ ret = ret2;
+ goto out;
+ }
+ }
+ new_rlm = num_capath > 0 ? capath[--num_capath] : NULL;
+ if (new_rlm) {
+ kdc_log(context, config, 5, "krbtgt from %s via %s for "
+ "realm %s not found, trying %s", tgt->crealm,
+ our_realm, req_rlm, new_rlm);
+
+ free(ref_realm);
+ ref_realm = strdup(new_rlm);
+ if (ref_realm == NULL) {
+ ret = krb5_enomem(context);
+ goto out;
+ }
+
+ krb5_free_principal(context, sp);
+ sp = NULL;
+ krb5_make_principal(context, &sp, r,
+ KRB5_TGS_NAME, ref_realm, NULL);
+ free(spn);
+ spn = NULL;
+ ret = krb5_unparse_name(context, sp, &spn);
+ if (ret)
+ goto out;
+ goto server_lookup;
+ }
+ } else if (need_referral(context, config, &b->kdc_options, sp, &realms)) {
if (strcmp(realms[0], sp->realm) != 0) {
kdc_log(context, config, 5,
"Returning a referral to realm %s for "
"server %s that was not found",
realms[0], spn);
krb5_free_principal(context, sp);
- free(spn);
+ sp = NULL;
krb5_make_principal(context, &sp, r, KRB5_TGS_NAME,
realms[0], NULL);
+ free(spn);
+ spn = NULL;
ret = krb5_unparse_name(context, sp, &spn);
- if (ret)
+ if (ret) {
+ krb5_free_host_realm(context, realms);
goto out;
+ }
- if (ref_realm)
- free(ref_realm);
+ free(ref_realm);
ref_realm = strdup(realms[0]);
krb5_free_host_realm(context, realms);
@@ -1702,15 +1784,21 @@ server_lookup:
krb5_principal_is_krbtgt(context, sp) ?
config->tgt_use_strongest_session_key :
config->svc_use_strongest_session_key, FALSE,
- server, b->etype.val, b->etype.len, NULL,
- &skey);
+ server, b->etype.val, b->etype.len, &etype,
+ NULL);
if(ret) {
kdc_log(context, config, 0,
"Server (%s) has no support for etypes", spn);
goto out;
}
+ ret = _kdc_get_preferred_key(context, config, server, spn,
+ NULL, &skey);
+ if(ret) {
+ kdc_log(context, config, 0,
+ "Server (%s) has no supported etypes", spn);
+ goto out;
+ }
ekey = &skey->key;
- etype = skey->key.keytype;
kvno = server->entry.kvno;
}
@@ -1729,7 +1817,7 @@ server_lookup:
* Validate authoriation data
*/
- ret = hdb_enctype2key(context, &krbtgt->entry,
+ ret = hdb_enctype2key(context, &krbtgt->entry, NULL, /* XXX use the right kvno! */
krbtgt_etype, &tkey_check);
if(ret) {
kdc_log(context, config, 0,
@@ -1737,46 +1825,53 @@ server_lookup:
goto out;
}
- /* Now refetch the primary krbtgt, and get the current kvno (the
+ /*
+ * Now refetch the primary krbtgt, and get the current kvno (the
* sign check may have been on an old kvno, and the server may
- * have been an incoming trust) */
- ret = krb5_make_principal(context, &krbtgt_principal,
- krb5_principal_get_comp_string(context,
- krbtgt->entry.principal,
- 1),
- KRB5_TGS_NAME,
- krb5_principal_get_comp_string(context,
- krbtgt->entry.principal,
- 1), NULL);
- if(ret) {
- kdc_log(context, config, 0,
- "Failed to generate krbtgt principal");
- goto out;
+ * have been an incoming trust)
+ */
+
+ ret = krb5_make_principal(context,
+ &krbtgt_out_principal,
+ our_realm,
+ KRB5_TGS_NAME,
+ our_realm,
+ NULL);
+ if (ret) {
+ kdc_log(context, config, 0,
+ "Failed to make krbtgt principal name object for "
+ "authz-data signatures");
+ goto out;
+ }
+ ret = krb5_unparse_name(context, krbtgt_out_principal, &krbtgt_out_n);
+ if (ret) {
+ kdc_log(context, config, 0,
+ "Failed to make krbtgt principal name object for "
+ "authz-data signatures");
+ goto out;
}
- ret = _kdc_db_fetch(context, config, krbtgt_principal, HDB_F_GET_KRBTGT, NULL, NULL, &krbtgt_out);
- krb5_free_principal(context, krbtgt_principal);
+ ret = _kdc_db_fetch(context, config, krbtgt_out_principal,
+ HDB_F_GET_KRBTGT, NULL, NULL, &krbtgt_out);
if (ret) {
- krb5_error_code ret2;
- char *ktpn, *ktpn2;
+ char *ktpn = NULL;
ret = krb5_unparse_name(context, krbtgt->entry.principal, &ktpn);
- ret2 = krb5_unparse_name(context, krbtgt_principal, &ktpn2);
kdc_log(context, config, 0,
- "Request with wrong krbtgt: %s, %s not found in our database",
- (ret == 0) ? ktpn : "<unknown>", (ret2 == 0) ? ktpn2 : "<unknown>");
- if(ret == 0)
- free(ktpn);
- if(ret2 == 0)
- free(ktpn2);
+ "No such principal %s (needed for authz-data signature keys) "
+ "while processing TGS-REQ for service %s with krbtg %s",
+ krbtgt_out_n, spn, (ret == 0) ? ktpn : "<unknown>");
+ free(ktpn);
ret = KRB5KRB_AP_ERR_NOT_US;
goto out;
}
- /* The first realm is the realm of the service, the second is
+ /*
+ * The first realm is the realm of the service, the second is
* krbtgt/<this>/@REALM component of the krbtgt DN the request was
* encrypted to. The redirection via the krbtgt_out entry allows
* the DB to possibly correct the case of the realm (Samba4 does
- * this) before the strcmp() */
+ * this) before the strcmp()
+ */
if (strcmp(krb5_principal_get_realm(context, server->entry.principal),
krb5_principal_get_realm(context, krbtgt_out->entry.principal)) != 0) {
char *ktpn;
@@ -1787,10 +1882,18 @@ server_lookup:
if(ret == 0)
free(ktpn);
ret = KRB5KRB_AP_ERR_NOT_US;
+ goto out;
}
- ret = hdb_enctype2key(context, &krbtgt_out->entry,
- krbtgt_etype, &tkey_sign);
+ ret = _kdc_get_preferred_key(context, config, krbtgt_out, krbtgt_out_n,
+ NULL, &tkey_sign);
+ if (ret) {
+ kdc_log(context, config, 0,
+ "Failed to find key for krbtgt PAC signature");
+ goto out;
+ }
+ ret = hdb_enctype2key(context, &krbtgt_out->entry, NULL,
+ tkey_sign->key.keytype, &tkey_sign);
if(ret) {
kdc_log(context, config, 0,
"Failed to find key for krbtgt PAC signature");
@@ -1829,7 +1932,7 @@ server_lookup:
ret = check_PAC(context, config, cp, NULL,
client, server, krbtgt,
- &tkey_check->key, &tkey_check->key,
+ &tkey_check->key,
ekey, &tkey_sign->key,
tgt, &rspac, &signedpath);
if (ret) {
@@ -2029,6 +2132,8 @@ server_lookup:
t = &b->additional_tickets->val[0];
ret = hdb_enctype2key(context, &client->entry,
+ hdb_kvno2keys(context, &client->entry,
+ t->enc_part.kvno ? * t->enc_part.kvno : 0),
t->enc_part.etype, &clientkey);
if(ret){
ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */
@@ -2099,7 +2204,7 @@ server_lookup:
*/
ret = check_PAC(context, config, tp, dp,
client, server, krbtgt,
- &clientkey->key, &tkey_check->key,
+ &clientkey->key,
ekey, &tkey_sign->key,
&adtkt, &rspac, &ad_signedpath);
if (ret) {
@@ -2228,8 +2333,9 @@ server_lookup:
spn,
client,
cp,
+ tgt_realm,
krbtgt_out,
- krbtgt_etype,
+ tkey_sign->key.keytype,
spp,
&rspac,
&enc_pa_data,
@@ -2241,8 +2347,9 @@ out:
free(tpn);
free(spn);
free(cpn);
- if (dpn)
- free(dpn);
+ free(dpn);
+ free(krbtgt_out_n);
+ _krb5_free_capath(context, capath);
krb5_data_free(&rspac);
krb5_free_keyblock_contents(context, &sessionkey);
@@ -2257,14 +2364,11 @@ out:
if (tp && tp != cp)
krb5_free_principal(context, tp);
- if (cp)
- krb5_free_principal(context, cp);
- if (dp)
- krb5_free_principal(context, dp);
- if (sp)
- krb5_free_principal(context, sp);
- if (ref_realm)
- free(ref_realm);
+ krb5_free_principal(context, cp);
+ krb5_free_principal(context, dp);
+ krb5_free_principal(context, sp);
+ krb5_free_principal(context, krbtgt_out_principal);
+ free(ref_realm);
free_METHOD_DATA(&enc_pa_data);
free_EncTicketPart(&adtkt);
@@ -2337,6 +2441,13 @@ _kdc_tgs_rep(krb5_context context,
goto out;
}
+ {
+ const PA_DATA *pa = _kdc_find_padata(req, &i, KRB5_PADATA_FX_FAST);
+ if (pa)
+ kdc_log(context, config, 10, "Got TGS FAST request");
+ }
+
+
ret = tgs_build_reply(context,
config,
req,
@@ -2367,17 +2478,23 @@ _kdc_tgs_rep(krb5_context context,
out:
if (replykey)
krb5_free_keyblock(context, replykey);
+
if(ret && ret != HDB_ERR_NOT_FOUND_HERE && data->data == NULL){
- krb5_mk_error(context,
- ret,
- NULL,
- NULL,
- NULL,
- NULL,
- csec,
- cusec,
- data);
- ret = 0;
+ /* XXX add fast wrapping on the error */
+ METHOD_DATA error_method = { 0, NULL };
+
+
+ kdc_log(context, config, 10, "tgs-req: sending error: %d to client", ret);
+ ret = _kdc_fast_mk_error(context, NULL,
+ &error_method,
+ NULL,
+ NULL,
+ ret, NULL,
+ NULL,
+ NULL, NULL,
+ csec, cusec,
+ data);
+ free_METHOD_DATA(&error_method);
}
free(csec);
free(cusec);
diff --git a/kdc/kstash.c b/kdc/kstash.c
index 0b75fb8d84a1..54d6628388e3 100644
--- a/kdc/kstash.c
+++ b/kdc/kstash.c
@@ -64,8 +64,9 @@ int num_args = sizeof(args) / sizeof(args[0]);
int
main(int argc, char **argv)
{
- char buf[1024];
+ char buf[1024+1];
krb5_error_code ret;
+ int aret;
krb5_enctype enctype;
@@ -84,8 +85,11 @@ main(int argc, char **argv)
krb5_errx(context, 1, "random-key and master-key-fd "
"is mutual exclusive");
- if (keyfile == NULL)
- asprintf(&keyfile, "%s/m-key", hdb_db_dir(context));
+ if (keyfile == NULL) {
+ aret = asprintf(&keyfile, "%s/m-key", hdb_db_dir(context));
+ if (aret == -1)
+ krb5_errx(context, 1, "out of memory");
+ }
ret = krb5_string_to_enctype(context, enctype_str, &enctype);
if(ret)
@@ -113,7 +117,7 @@ main(int argc, char **argv)
} else {
if(master_key_fd != -1) {
ssize_t n;
- n = read(master_key_fd, buf, sizeof(buf));
+ n = read(master_key_fd, buf, sizeof(buf)-1);
if(n <= 0)
krb5_err(context, 1, errno, "failed to read passphrase");
buf[n] = '\0';
@@ -132,9 +136,20 @@ main(int argc, char **argv)
}
{
- char *new, *old;
- asprintf(&old, "%s.old", keyfile);
- asprintf(&new, "%s.new", keyfile);
+ char *new = NULL, *old = NULL;
+
+ aret = asprintf(&old, "%s.old", keyfile);
+ if (aret == -1) {
+ old = NULL;
+ ret = ENOMEM;
+ goto out;
+ }
+ aret = asprintf(&new, "%s.new", keyfile);
+ if (aret == -1) {
+ new = NULL;
+ ret = ENOMEM;
+ goto out;
+ }
if(unlink(new) < 0 && errno != ENOENT) {
ret = errno;
goto out;
diff --git a/kdc/kx509.c b/kdc/kx509.c
index 8d683d50a375..6f61a8ea322c 100644
--- a/kdc/kx509.c
+++ b/kdc/kx509.c
@@ -143,22 +143,54 @@ build_certificate(krb5_context context,
krb5_principal principal,
krb5_data *certificate)
{
+ char *name = NULL;
+ const char *kx509_ca;
hx509_ca_tbs tbs = NULL;
hx509_env env = NULL;
hx509_cert cert = NULL;
hx509_cert signer = NULL;
+ krb5_boolean def_bool;
int ret;
- if (krb5_principal_get_comp_string(context, principal, 1) != NULL) {
- kdc_log(context, config, 0, "Principal is not a user");
- return EINVAL;
- }
+ ret = krb5_unparse_name_flags(context, principal,
+ KRB5_PRINCIPAL_UNPARSE_NO_REALM,
+ &name);
+ if (ret)
+ goto out;
+
+ ret = hx509_env_add(context->hx509ctx, &env, "principal-name-without-realm",
+ name);
+ krb5_xfree(name);
+ name = NULL;
+ if (ret)
+ goto out;
+
+ /*
+ * Include the realm in the principal-name env var; the template
+ * might not use $principal-name-realm after all.
+ */
+ ret = krb5_unparse_name(context, principal, &name);
+ if (ret)
+ goto out;
ret = hx509_env_add(context->hx509ctx, &env, "principal-name",
- krb5_principal_get_comp_string(context, principal, 0));
+ name);
+ if (ret)
+ goto out;
+
+ ret = hx509_env_add(context->hx509ctx, &env, "principal-name-realm",
+ krb5_principal_get_realm(context, principal));
if (ret)
goto out;
+ /* Pick an issuer based on the crealm if we can */
+ kx509_ca = krb5_config_get_string(context, NULL, "kdc",
+ krb5_principal_get_realm(context,
+ principal),
+ "kx509_ca", NULL);
+ if (kx509_ca == NULL)
+ kx509_ca = config->kx509_ca;
+
{
hx509_certs certs;
hx509_query *q;
@@ -243,6 +275,19 @@ build_certificate(krb5_context context,
goto out;
}
+ def_bool = krb5_config_get_bool_default(context, NULL, TRUE, "kdc",
+ "kx509_include_pkinit_san",
+ NULL);
+ if (krb5_config_get_bool_default(context, NULL, def_bool, "kdc",
+ krb5_principal_get_realm(context,
+ principal),
+ "kx509_include_pkinit_san",
+ NULL)) {
+ ret = hx509_ca_tbs_add_san_pkinit(context->hx509ctx, tbs, name);
+ if (ret)
+ goto out;
+ }
+
hx509_ca_tbs_set_notAfter(context->hx509ctx, tbs, endtime);
hx509_ca_tbs_subject_expand(context->hx509ctx, tbs, env);
@@ -260,8 +305,13 @@ build_certificate(krb5_context context,
if (ret)
goto out;
+ /* cleanup on success */
+ krb5_xfree(name);
+
return 0;
out:
+ if (name)
+ krb5_xfree(name);
if (env)
hx509_env_free(&env);
if (tbs)
@@ -272,6 +322,53 @@ out:
return ret;
}
+krb5_error_code
+kdc_kx509_verify_service_principal(krb5_context context,
+ const char *cname,
+ krb5_principal sprincipal)
+{
+ krb5_error_code ret, aret;
+ krb5_boolean bret;
+ krb5_principal principal = NULL;
+ char *expected = NULL;
+ char localhost[MAXHOSTNAMELEN];
+
+ ret = gethostname(localhost, sizeof(localhost) - 1);
+ if (ret != 0) {
+ ret = errno;
+ krb5_set_error_message(context, ret,
+ N_("Failed to get local hostname", ""));
+ return ret;
+ }
+ localhost[sizeof(localhost) - 1] = '\0';
+
+ ret = krb5_make_principal(context, &principal, "", "kca_service",
+ localhost, NULL);
+ if (ret)
+ goto out;
+
+ bret = krb5_principal_compare_any_realm(context, sprincipal, principal);
+ if (bret == TRUE)
+ goto out; /* found a match */
+
+ ret = KRB5KDC_ERR_SERVER_NOMATCH;
+
+ aret = krb5_unparse_name(context, sprincipal, &expected);
+ if (aret)
+ goto out;
+
+ krb5_set_error_message(context, ret,
+ "User %s used wrong Kx509 service "
+ "principal, expected: %s",
+ cname, expected);
+
+ out:
+ krb5_xfree(expected);
+ krb5_free_principal(context, principal);
+
+ return ret;
+}
+
/*
*
*/
@@ -292,6 +389,7 @@ _kdc_do_kx509(krb5_context context,
Kx509Response rep;
size_t size;
krb5_keyblock *key = NULL;
+ krb5_boolean def_bool;
krb5_data_zero(reply);
memset(&rep, 0, sizeof(rep));
@@ -304,7 +402,7 @@ _kdc_do_kx509(krb5_context context,
kdc_log(context, config, 0, "Kx509 request from %s", from);
- ret = krb5_kt_resolve(context, "HDB:", &id);
+ ret = krb5_kt_resolve(context, "HDBGET:", &id);
if (ret) {
kdc_log(context, config, 0, "Can't open database for digest");
goto out;
@@ -324,48 +422,29 @@ _kdc_do_kx509(krb5_context context,
if (ret)
goto out;
+ def_bool = krb5_config_get_bool_default(context, NULL, TRUE, "kdc",
+ "require_initial_kca_tickets",
+ NULL);
+ if (!ticket->ticket.flags.initial &&
+ krb5_config_get_bool_default(context, NULL, def_bool, "kdc",
+ krb5_principal_get_realm(context,
+ cprincipal),
+ "require_initial_kca_tickets", NULL)) {
+ ret = KRB5KDC_ERR_POLICY;
+ goto out;
+ }
+
ret = krb5_unparse_name(context, cprincipal, &cname);
if (ret)
goto out;
- /* verify server principal */
-
- ret = krb5_sname_to_principal(context, NULL, "kca_service",
- KRB5_NT_UNKNOWN, &sprincipal);
+ ret = krb5_ticket_get_server(context, ticket, &sprincipal);
if (ret)
goto out;
- {
- krb5_principal principal = NULL;
-
- ret = krb5_ticket_get_server(context, ticket, &principal);
- if (ret)
- goto out;
-
- ret = krb5_principal_compare(context, sprincipal, principal);
- krb5_free_principal(context, principal);
- if (ret != TRUE) {
- char *expected, *used;
-
- ret = krb5_unparse_name(context, sprincipal, &expected);
- if (ret)
- goto out;
- ret = krb5_unparse_name(context, principal, &used);
- if (ret) {
- krb5_xfree(expected);
- goto out;
- }
-
- ret = KRB5KDC_ERR_SERVER_NOMATCH;
- krb5_set_error_message(context, ret,
- "User %s used wrong Kx509 service "
- "principal, expected: %s, used %s",
- cname, expected, used);
- krb5_xfree(expected);
- krb5_xfree(used);
- goto out;
- }
- }
+ ret = kdc_kx509_verify_service_principal(context, cname, sprincipal);
+ if (ret)
+ goto out;
ret = krb5_auth_con_getkey(context, ac, &key);
if (ret == 0 && key == NULL)
@@ -381,15 +460,15 @@ _kdc_do_kx509(krb5_context context,
/* Verify that the key is encoded RSA key */
{
- RSAPublicKey key;
- size_t size;
+ RSAPublicKey rsapkey;
+ size_t rsapkeysize;
ret = decode_RSAPublicKey(req->pk_key.data, req->pk_key.length,
- &key, &size);
+ &rsapkey, &rsapkeysize);
if (ret)
goto out;
- free_RSAPublicKey(&key);
- if (size != req->pk_key.length) {
+ free_RSAPublicKey(&rsapkey);
+ if (rsapkeysize != req->pk_key.length) {
ret = ASN1_EXTRA_DATA;
goto out;
}
diff --git a/kdc/log.c b/kdc/log.c
index 6d85729f514c..6850bedd9cf3 100644
--- a/kdc/log.c
+++ b/kdc/log.c
@@ -53,7 +53,7 @@ kdc_openlog(krb5_context context,
char *ss;
if (asprintf(&ss, "0-1/FILE:%s/%s", hdb_db_dir(context),
KDC_LOG_FILE) < 0)
- err(1, NULL);
+ err(1, "out of memory");
krb5_addlog_dest(context, config->logf, ss);
free(ss);
}
diff --git a/kdc/main.c b/kdc/main.c
index fc42e9dcdebf..f5355ed5babe 100644
--- a/kdc/main.c
+++ b/kdc/main.c
@@ -44,9 +44,14 @@
sig_atomic_t exit_flag = 0;
-#ifdef SUPPORT_DETACH
int detach_from_console = -1;
-#endif
+int daemon_child = -1;
+int do_bonjour = -1;
+
+static RETSIGTYPE
+sigchld(int sig)
+{
+}
static RETSIGTYPE
sigterm(int sig)
@@ -68,8 +73,12 @@ switch_environment(void)
if ((runas_string || chroot_string) && geteuid() != 0)
errx(1, "no running as root, can't switch user/chroot");
- if (chroot_string && chroot(chroot_string) != 0)
- errx(1, "chroot(%s)", "chroot_string failed");
+ if (chroot_string) {
+ if (chroot(chroot_string))
+ err(1, "chroot(%s) failed", chroot_string);
+ if (chdir("/"))
+ err(1, "chdir(/) after chroot failed");
+ }
if (runas_string) {
struct passwd *pw;
@@ -101,13 +110,13 @@ switch_environment(void)
#endif
}
-
int
main(int argc, char **argv)
{
krb5_error_code ret;
krb5_context context;
krb5_kdc_configuration *config;
+ int optidx = 0;
setprogname(argv[0]);
@@ -117,11 +126,11 @@ main(int argc, char **argv)
else if (ret)
errx (1, "krb5_init_context failed: %d", ret);
- ret = krb5_kt_register(context, &hdb_kt_ops);
+ ret = krb5_kt_register(context, &hdb_get_kt_ops);
if (ret)
errx (1, "krb5_kt_register(HDB) failed: %d", ret);
- config = configure(context, argc, argv);
+ config = configure(context, argc, argv, &optidx);
#ifdef HAVE_SIGACTION
{
@@ -137,6 +146,11 @@ main(int argc, char **argv)
sigaction(SIGXCPU, &sa, NULL);
#endif
+#ifdef SIGCHLD
+ sa.sa_handler = sigchld;
+ sigaction(SIGCHLD, &sa, NULL);
+#endif
+
sa.sa_handler = SIG_IGN;
#ifdef SIGPIPE
sigaction(SIGPIPE, &sa, NULL);
@@ -145,6 +159,9 @@ main(int argc, char **argv)
#else
signal(SIGINT, sigterm);
signal(SIGTERM, sigterm);
+#ifdef SIGCHLD
+ signal(SIGCHLD, sigchld);
+#endif
#ifdef SIGXCPU
signal(SIGXCPU, sigterm);
#endif
@@ -152,18 +169,11 @@ main(int argc, char **argv)
signal(SIGPIPE, SIG_IGN);
#endif
#endif
-#ifdef SUPPORT_DETACH
- if (detach_from_console)
- daemon(0, 0);
-#endif
-#ifdef __APPLE__
- bonjour_announce(context, config);
-#endif
- pidfile(NULL);
+ rk_pidfile(NULL);
switch_environment();
- loop(context, config);
+ start_kdc(context, config, argv[0]);
krb5_free_context(context);
return 0;
}
diff --git a/kdc/misc.c b/kdc/misc.c
index 1b2c44000598..15fae0f3a3b2 100644
--- a/kdc/misc.c
+++ b/kdc/misc.c
@@ -33,6 +33,22 @@
#include "kdc_locl.h"
+static int
+name_type_ok(krb5_context context,
+ krb5_kdc_configuration *config,
+ krb5_const_principal principal)
+{
+ int nt = krb5_principal_get_type(context, principal);
+
+ if (!krb5_principal_is_krbtgt(context, principal))
+ return 1;
+ if (nt == KRB5_NT_SRV_INST || nt == KRB5_NT_UNKNOWN)
+ return 1;
+ if (config->strict_nametypes == 0)
+ return 1;
+ return 0;
+}
+
struct timeval _kdc_now;
krb5_error_code
@@ -44,45 +60,45 @@ _kdc_db_fetch(krb5_context context,
HDB **db,
hdb_entry_ex **h)
{
- hdb_entry_ex *ent;
+ hdb_entry_ex *ent = NULL;
krb5_error_code ret = HDB_ERR_NOENTRY;
int i;
unsigned kvno = 0;
+ krb5_principal enterprise_principal = NULL;
+ krb5_const_principal princ;
- if (kvno_ptr) {
- kvno = *kvno_ptr;
- flags |= HDB_F_KVNO_SPECIFIED;
- }
+ *h = NULL;
+
+ if (!name_type_ok(context, config, principal))
+ goto out2;
- ent = calloc (1, sizeof (*ent));
- if (ent == NULL) {
- krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
- return ENOMEM;
+ if (kvno_ptr != NULL && *kvno_ptr != 0) {
+ kvno = *kvno_ptr;
+ flags |= HDB_F_KVNO_SPECIFIED;
+ } else {
+ flags |= HDB_F_ALL_KVNOS;
}
- for(i = 0; i < config->num_db; i++) {
- krb5_principal enterprise_principal = NULL;
- if (!(config->db[i]->hdb_capability_flags & HDB_CAP_F_HANDLE_ENTERPRISE_PRINCIPAL)
- && principal->name.name_type == KRB5_NT_ENTERPRISE_PRINCIPAL) {
- if (principal->name.name_string.len != 1) {
- ret = KRB5_PARSE_MALFORMED;
- krb5_set_error_message(context, ret,
- "malformed request: "
- "enterprise name with %d name components",
- principal->name.name_string.len);
- free(ent);
- return ret;
- }
- ret = krb5_parse_name(context, principal->name.name_string.val[0],
- &enterprise_principal);
- if (ret) {
- free(ent);
- return ret;
- }
-
- principal = enterprise_principal;
- }
+ ent = calloc(1, sizeof (*ent));
+ if (ent == NULL)
+ return krb5_enomem(context);
+
+ if (principal->name.name_type == KRB5_NT_ENTERPRISE_PRINCIPAL) {
+ if (principal->name.name_string.len != 1) {
+ ret = KRB5_PARSE_MALFORMED;
+ krb5_set_error_message(context, ret,
+ "malformed request: "
+ "enterprise name with %d name components",
+ principal->name.name_string.len);
+ goto out;
+ }
+ ret = krb5_parse_name(context, principal->name.name_string.val[0],
+ &enterprise_principal);
+ if (ret)
+ goto out;
+ }
+ for (i = 0; i < config->num_db; i++) {
ret = config->db[i]->hdb_open(context, config->db[i], O_RDONLY, 0);
if (ret) {
const char *msg = krb5_get_error_message(context, ret);
@@ -91,26 +107,56 @@ _kdc_db_fetch(krb5_context context,
continue;
}
+ princ = principal;
+ if (!(config->db[i]->hdb_capability_flags & HDB_CAP_F_HANDLE_ENTERPRISE_PRINCIPAL) && enterprise_principal)
+ princ = enterprise_principal;
+
ret = config->db[i]->hdb_fetch_kvno(context,
config->db[i],
- principal,
+ princ,
flags | HDB_F_DECRYPT,
kvno,
ent);
-
- krb5_free_principal(context, enterprise_principal);
-
config->db[i]->hdb_close(context, config->db[i]);
- if(ret == 0) {
+
+ switch (ret) {
+ case HDB_ERR_WRONG_REALM:
+ /*
+ * the ent->entry.principal just contains hints for the client
+ * to retry. This is important for enterprise principal routing
+ * between trusts.
+ */
+ /* fall through */
+ case 0:
if (db)
*db = config->db[i];
*h = ent;
- return 0;
+ ent = NULL;
+ goto out;
+
+ case HDB_ERR_NOENTRY:
+ /* Check the other databases */
+ continue;
+
+ default:
+ /*
+ * This is really important, because errors like
+ * HDB_ERR_NOT_FOUND_HERE (used to indicate to Samba that
+ * the RODC on which this code is running does not have
+ * the key we need, and so a proxy to the KDC is required)
+ * have specific meaning, and need to be propogated up.
+ */
+ goto out;
}
}
+
+out2:
+ if (ret == HDB_ERR_NOENTRY) {
+ krb5_set_error_message(context, ret, "no such entry found in hdb");
+ }
+out:
+ krb5_free_principal(context, enterprise_principal);
free(ent);
- krb5_set_error_message(context, ret,
- "no such entry found in hdb");
return ret;
}
@@ -140,10 +186,11 @@ _kdc_get_preferred_key(krb5_context context,
if (config->use_strongest_server_key) {
const krb5_enctype *p = krb5_kerberos_enctypes(context);
- for (i = 0; p[i] != ETYPE_NULL; i++) {
- if (krb5_enctype_valid(context, p[i]) != 0)
+ for (i = 0; p[i] != (krb5_enctype)ETYPE_NULL; i++) {
+ if (krb5_enctype_valid(context, p[i]) != 0 &&
+ !_kdc_is_weak_exception(h->entry.principal, p[i]))
continue;
- ret = hdb_enctype2key(context, &h->entry, p[i], key);
+ ret = hdb_enctype2key(context, &h->entry, NULL, p[i], key);
if (ret != 0)
continue;
if (enctype != NULL)
@@ -154,11 +201,11 @@ _kdc_get_preferred_key(krb5_context context,
*key = NULL;
for (i = 0; i < h->entry.keys.len; i++) {
- if (krb5_enctype_valid(context, h->entry.keys.val[i].key.keytype)
- != 0)
+ if (krb5_enctype_valid(context, h->entry.keys.val[i].key.keytype) != 0 &&
+ !_kdc_is_weak_exception(h->entry.principal, h->entry.keys.val[i].key.keytype))
continue;
- ret = hdb_enctype2key(context, &h->entry,
- h->entry.keys.val[i].key.keytype, key);
+ ret = hdb_enctype2key(context, &h->entry, NULL,
+ h->entry.keys.val[i].key.keytype, key);
if (ret != 0)
continue;
if (enctype != NULL)
diff --git a/kdc/mit_dump.c b/kdc/mit_dump.c
index f28e932b15b4..bb6b4d481c32 100644
--- a/kdc/mit_dump.c
+++ b/kdc/mit_dump.c
@@ -33,6 +33,17 @@
#include "hprop.h"
+extern krb5_error_code _hdb_mdb_value2entry(krb5_context context,
+ krb5_data *data,
+ krb5_kvno target_kvno,
+ hdb_entry *entry);
+
+extern int _hdb_mit_dump2mitdb_entry(krb5_context context,
+ char *line,
+ krb5_storage *sp);
+
+
+
/*
can have any number of princ stanzas.
format is as follows (only \n indicates newlines)
@@ -74,19 +85,6 @@ unless no extra data
*/
-static int
-hex_to_octet_string(const char *ptr, krb5_data *data)
-{
- size_t i;
- unsigned int v;
- for(i = 0; i < data->length; i++) {
- if(sscanf(ptr + 2 * i, "%02x", &v) != 1)
- return -1;
- ((unsigned char*)data->data)[i] = v;
- }
- return 2 * i;
-}
-
static char *
nexttoken(char **p)
{
@@ -97,321 +95,133 @@ nexttoken(char **p)
return q;
}
-static size_t
-getdata(char **p, unsigned char *buf, size_t len)
-{
- size_t i;
- int v;
- char *q = nexttoken(p);
- i = 0;
- while(*q && i < len) {
- if(sscanf(q, "%02x", &v) != 1)
- break;
- buf[i++] = v;
- q += 2;
- }
- return i;
-}
-
-static int
-getint(char **p)
-{
- int val;
- char *q = nexttoken(p);
- sscanf(q, "%d", &val);
- return val;
-}
-
#include <kadm5/admin.h>
-static void
-attr_to_flags(unsigned attr, HDBFlags *flags)
-{
- flags->postdate = !(attr & KRB5_KDB_DISALLOW_POSTDATED);
- flags->forwardable = !(attr & KRB5_KDB_DISALLOW_FORWARDABLE);
- flags->initial = !!(attr & KRB5_KDB_DISALLOW_TGT_BASED);
- flags->renewable = !(attr & KRB5_KDB_DISALLOW_RENEWABLE);
- flags->proxiable = !(attr & KRB5_KDB_DISALLOW_PROXIABLE);
- /* DUP_SKEY */
- flags->invalid = !!(attr & KRB5_KDB_DISALLOW_ALL_TIX);
- flags->require_preauth = !!(attr & KRB5_KDB_REQUIRES_PRE_AUTH);
- flags->require_hwauth = !!(attr & KRB5_KDB_REQUIRES_HW_AUTH);
- flags->server = !(attr & KRB5_KDB_DISALLOW_SVR);
- flags->change_pw = !!(attr & KRB5_KDB_PWCHANGE_SERVICE);
- flags->client = 1; /* XXX */
-}
-
-#define KRB5_KDB_SALTTYPE_NORMAL 0
-#define KRB5_KDB_SALTTYPE_V4 1
-#define KRB5_KDB_SALTTYPE_NOREALM 2
-#define KRB5_KDB_SALTTYPE_ONLYREALM 3
-#define KRB5_KDB_SALTTYPE_SPECIAL 4
-#define KRB5_KDB_SALTTYPE_AFS3 5
-
-static krb5_error_code
-fix_salt(krb5_context context, hdb_entry *ent, int key_num)
+/* XXX: Principal names with '\n' cannot be dumped or loaded */
+static int
+my_fgetln(FILE *f, char **bufp, size_t *szp, size_t *lenp)
{
- krb5_error_code ret;
- Salt *salt = ent->keys.val[key_num].salt;
- /* fix salt type */
- switch((int)salt->type) {
- case KRB5_KDB_SALTTYPE_NORMAL:
- salt->type = KRB5_PADATA_PW_SALT;
- break;
- case KRB5_KDB_SALTTYPE_V4:
- krb5_data_free(&salt->salt);
- salt->type = KRB5_PADATA_PW_SALT;
- break;
- case KRB5_KDB_SALTTYPE_NOREALM:
- {
- size_t len;
- size_t i;
- char *p;
-
- len = 0;
- for (i = 0; i < ent->principal->name.name_string.len; ++i)
- len += strlen(ent->principal->name.name_string.val[i]);
- ret = krb5_data_alloc (&salt->salt, len);
- if (ret)
- return ret;
- p = salt->salt.data;
- for (i = 0; i < ent->principal->name.name_string.len; ++i) {
- memcpy (p,
- ent->principal->name.name_string.val[i],
- strlen(ent->principal->name.name_string.val[i]));
- p += strlen(ent->principal->name.name_string.val[i]);
- }
-
- salt->type = KRB5_PADATA_PW_SALT;
- break;
+ size_t len;
+ size_t sz = *szp;
+ char *buf = *bufp;
+ char *p, *n;
+
+ if (!buf) {
+ buf = malloc(sz ? sz : 8192);
+ if (!buf)
+ return ENOMEM;
+ if (!sz)
+ sz = 8192;
}
- case KRB5_KDB_SALTTYPE_ONLYREALM:
- krb5_data_free(&salt->salt);
- ret = krb5_data_copy(&salt->salt,
- ent->principal->realm,
- strlen(ent->principal->realm));
- if(ret)
- return ret;
- salt->type = KRB5_PADATA_PW_SALT;
- break;
- case KRB5_KDB_SALTTYPE_SPECIAL:
- salt->type = KRB5_PADATA_PW_SALT;
- break;
- case KRB5_KDB_SALTTYPE_AFS3:
- krb5_data_free(&salt->salt);
- ret = krb5_data_copy(&salt->salt,
- ent->principal->realm,
- strlen(ent->principal->realm));
- if(ret)
- return ret;
- salt->type = KRB5_PADATA_AFS3_SALT;
- break;
- default:
- abort();
+
+ len = 0;
+ while ((p = fgets(&buf[len], sz-len, f)) != NULL) {
+ len += strlen(&buf[len]);
+ if (buf[len-1] == '\n')
+ break;
+ if (feof(f))
+ break;
+ if (sz > SIZE_MAX/2 ||
+ (n = realloc(buf, sz += 1 + (sz >> 1))) == NULL) {
+ free(buf);
+ *bufp = NULL;
+ *szp = 0;
+ *lenp = 0;
+ return ENOMEM;
+ }
+ buf = n;
}
- return 0;
+ *bufp = buf;
+ *szp = sz;
+ *lenp = len;
+ return 0; /* *len == 0 || no EOL -> EOF */
}
int
mit_prop_dump(void *arg, const char *file)
{
krb5_error_code ret;
- char line [2048];
- FILE *f;
+ size_t line_bufsz = 0;
+ size_t line_len = 0;
+ char *line = NULL;
int lineno = 0;
+ FILE *f;
struct hdb_entry_ex ent;
-
struct prop_data *pd = arg;
+ krb5_storage *sp = NULL;
+ krb5_data kdb_ent;
+ memset(&ent, 0, sizeof (ent));
f = fopen(file, "r");
- if(f == NULL)
+ if (f == NULL)
return errno;
- while(fgets(line, sizeof(line), f)) {
- char *p = line, *q;
-
- int i;
-
- int num_tl_data;
- int num_key_data;
- int high_kvno;
- int attributes;
-
- int tmp;
-
- lineno++;
-
- memset(&ent, 0, sizeof(ent));
-
- q = nexttoken(&p);
- if(strcmp(q, "kdb5_util") == 0) {
+ ret = ENOMEM;
+ sp = krb5_storage_emem();
+ if (!sp)
+ goto out;
+ while ((ret = my_fgetln(f, &line, &line_bufsz, &line_len)) == 0 &&
+ line_len > 0) {
+ char *p = line;
+ char *q;
+
+ lineno++;
+ if(strncmp(line, "kdb5_util", strlen("kdb5_util")) == 0) {
int major;
+ q = nexttoken(&p);
+ if (strcmp(q, "kdb5_util"))
+ errx(1, "line %d: unknown version", lineno);
q = nexttoken(&p); /* load_dump */
- if(strcmp(q, "load_dump"))
+ if (strcmp(q, "load_dump"))
errx(1, "line %d: unknown version", lineno);
q = nexttoken(&p); /* load_dump */
- if(strcmp(q, "version"))
+ if (strcmp(q, "version"))
errx(1, "line %d: unknown version", lineno);
q = nexttoken(&p); /* x.0 */
- if(sscanf(q, "%d", &major) != 1)
+ if (sscanf(q, "%d", &major) != 1)
errx(1, "line %d: unknown version", lineno);
- if(major != 4 && major != 5 && major != 6)
+ if (major != 4 && major != 5 && major != 6)
errx(1, "unknown dump file format, got %d, expected 4-6",
major);
continue;
- } else if(strcmp(q, "policy") == 0) {
+ } else if(strncmp(p, "policy", strlen("policy")) == 0) {
+ warnx("line: %d: ignoring policy (not supported)", lineno);
continue;
- } else if(strcmp(q, "princ") != 0) {
+ } else if(strncmp(p, "princ", strlen("princ")) != 0) {
warnx("line %d: not a principal", lineno);
continue;
}
- tmp = getint(&p);
- if(tmp != 38) {
- warnx("line %d: bad base length %d != 38", lineno, tmp);
- continue;
- }
- nexttoken(&p); /* length of principal */
- num_tl_data = getint(&p); /* number of tl-data */
- num_key_data = getint(&p); /* number of key-data */
- getint(&p); /* length of extra data */
- q = nexttoken(&p); /* principal name */
- krb5_parse_name(pd->context, q, &ent.entry.principal);
- attributes = getint(&p); /* attributes */
- attr_to_flags(attributes, &ent.entry.flags);
- tmp = getint(&p); /* max life */
- if(tmp != 0) {
- ALLOC(ent.entry.max_life);
- *ent.entry.max_life = tmp;
- }
- tmp = getint(&p); /* max renewable life */
- if(tmp != 0) {
- ALLOC(ent.entry.max_renew);
- *ent.entry.max_renew = tmp;
- }
- tmp = getint(&p); /* expiration */
- if(tmp != 0 && tmp != 2145830400) {
- ALLOC(ent.entry.valid_end);
- *ent.entry.valid_end = tmp;
- }
- tmp = getint(&p); /* pw expiration */
- if(tmp != 0) {
- ALLOC(ent.entry.pw_end);
- *ent.entry.pw_end = tmp;
- }
- nexttoken(&p); /* last auth */
- nexttoken(&p); /* last failed auth */
- nexttoken(&p); /* fail auth count */
- for(i = 0; i < num_tl_data; i++) {
- unsigned long val;
- int tl_type, tl_length;
- unsigned char *buf;
- krb5_principal princ;
-
- tl_type = getint(&p); /* data type */
- tl_length = getint(&p); /* data length */
-
-#define mit_KRB5_TL_LAST_PWD_CHANGE 1
-#define mit_KRB5_TL_MOD_PRINC 2
- switch(tl_type) {
- case mit_KRB5_TL_LAST_PWD_CHANGE:
- buf = malloc(tl_length);
- if (buf == NULL)
- errx(ENOMEM, "malloc");
- getdata(&p, buf, tl_length); /* data itself */
- val = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
- free(buf);
- ALLOC(ent.entry.extensions);
- ALLOC_SEQ(ent.entry.extensions, 1);
- ent.entry.extensions->val[0].mandatory = 0;
- ent.entry.extensions->val[0].data.element
- = choice_HDB_extension_data_last_pw_change;
- ent.entry.extensions->val[0].data.u.last_pw_change = val;
- break;
- case mit_KRB5_TL_MOD_PRINC:
- buf = malloc(tl_length);
- if (buf == NULL)
- errx(ENOMEM, "malloc");
- getdata(&p, buf, tl_length); /* data itself */
- val = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
- ret = krb5_parse_name(pd->context, (char *)buf + 4, &princ);
- if (ret)
- krb5_err(pd->context, 1, ret,
- "parse_name: %s", (char *)buf + 4);
- free(buf);
- ALLOC(ent.entry.modified_by);
- ent.entry.modified_by->time = val;
- ent.entry.modified_by->principal = princ;
- break;
- default:
- nexttoken(&p);
- break;
- }
- }
- ALLOC_SEQ(&ent.entry.keys, num_key_data);
- high_kvno = -1;
- for(i = 0; i < num_key_data; i++) {
- int key_versions;
- int kvno;
- key_versions = getint(&p); /* key data version */
- kvno = getint(&p);
-
- /*
- * An MIT dump file may contain multiple sets of keys with
- * different kvnos. Since the Heimdal database can only represent
- * one kvno per principal, we only want the highest set. Assume
- * that set will be given first, and discard all keys with lower
- * kvnos.
- */
- if (kvno > high_kvno && high_kvno != -1)
- errx(1, "line %d: high kvno keys given after low kvno keys",
- lineno);
- else if (kvno < high_kvno) {
- nexttoken(&p); /* key type */
- nexttoken(&p); /* key length */
- nexttoken(&p); /* key */
- if (key_versions > 1) {
- nexttoken(&p); /* salt type */
- nexttoken(&p); /* salt length */
- nexttoken(&p); /* salt */
- }
- ent.entry.keys.len--;
- continue;
- }
- ent.entry.kvno = kvno;
- high_kvno = kvno;
- ALLOC(ent.entry.keys.val[i].mkvno);
- *ent.entry.keys.val[i].mkvno = 1;
-
- /* key version 0 -- actual key */
- ent.entry.keys.val[i].key.keytype = getint(&p); /* key type */
- tmp = getint(&p); /* key length */
- /* the first two bytes of the key is the key length --
- skip it */
- krb5_data_alloc(&ent.entry.keys.val[i].key.keyvalue, tmp - 2);
- q = nexttoken(&p); /* key itself */
- hex_to_octet_string(q + 4, &ent.entry.keys.val[i].key.keyvalue);
-
- if(key_versions > 1) {
- /* key version 1 -- optional salt */
- ALLOC(ent.entry.keys.val[i].salt);
- ent.entry.keys.val[i].salt->type = getint(&p); /* salt type */
- tmp = getint(&p); /* salt length */
- if(tmp > 0) {
- krb5_data_alloc(&ent.entry.keys.val[i].salt->salt, tmp - 2);
- q = nexttoken(&p); /* salt itself */
- hex_to_octet_string(q + 4,
- &ent.entry.keys.val[i].salt->salt);
- } else {
- ent.entry.keys.val[i].salt->salt.length = 0;
- ent.entry.keys.val[i].salt->salt.data = NULL;
- getint(&p); /* -1, if no data. */
- }
- fix_salt(pd->context, &ent.entry, i);
- }
- }
- nexttoken(&p); /* extra data */
- v5_prop(pd->context, NULL, &ent, arg);
+ krb5_storage_truncate(sp, 0);
+ ret = _hdb_mit_dump2mitdb_entry(pd->context, line, sp);
+ if (ret) {
+ if (ret > 0)
+ warn("line: %d: failed to parse; ignoring", lineno);
+ else
+ warnx("line: %d: failed to parse; ignoring", lineno);
+ continue;
+ }
+ ret = krb5_storage_to_data(sp, &kdb_ent);
+ if (ret) break;
+ ret = _hdb_mdb_value2entry(pd->context, &kdb_ent, 0, &ent.entry);
+ krb5_data_free(&kdb_ent);
+ if (ret) {
+ warnx("line: %d: failed to store; ignoring", lineno);
+ continue;
+ }
+ ret = v5_prop(pd->context, NULL, &ent, arg);
+ hdb_free_entry(pd->context, &ent);
+ if (ret) break;
}
+
+out:
fclose(f);
- return 0;
+ free(line);
+ if (sp)
+ krb5_storage_free(sp);
+ if (ret && ret == ENOMEM)
+ errx(1, "out of memory");
+ if (ret)
+ errx(1, "line %d: problem parsing dump line", lineno);
+ return ret;
}
+
diff --git a/kdc/pkinit-ec.c b/kdc/pkinit-ec.c
new file mode 100644
index 000000000000..c718aa79962b
--- /dev/null
+++ b/kdc/pkinit-ec.c
@@ -0,0 +1,318 @@
+/*
+ * Copyright (c) 2016 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Portions Copyright (c) 2009 Apple Inc. 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 <config.h>
+#include <roken.h>
+
+#ifdef PKINIT
+
+/*
+ * As with the other *-ec.c files in Heimdal, this is a bit of a hack.
+ *
+ * The idea is to use OpenSSL for EC because hcrypto doesn't have the
+ * required functionality at this time. To do this we segregate
+ * EC-using code into separate source files and then we arrange for them
+ * to get the OpenSSL headers and not the conflicting hcrypto ones.
+ *
+ * Because of auto-generated *-private.h headers, we end up needing to
+ * make sure various types are defined before we include them, thus the
+ * strange header include order here.
+ */
+
+#ifdef HAVE_HCRYPTO_W_OPENSSL
+#include <openssl/ec.h>
+#include <openssl/ecdh.h>
+#include <openssl/evp.h>
+#include <openssl/bn.h>
+#define HEIM_NO_CRYPTO_HDRS
+#endif /* HAVE_HCRYPTO_W_OPENSSL */
+
+#define NO_HCRYPTO_POLLUTION
+
+#include "kdc_locl.h"
+#include <hcrypto/des.h>
+#include <heim_asn1.h>
+#include <rfc2459_asn1.h>
+#include <cms_asn1.h>
+#include <pkinit_asn1.h>
+
+#include <hx509.h>
+
+#ifdef HAVE_HCRYPTO_W_OPENSSL
+static void
+free_client_ec_param(krb5_context context,
+ EC_KEY *ec_key_pk,
+ EC_KEY *ec_key_key)
+{
+ if (ec_key_pk != NULL)
+ EC_KEY_free(ec_key_pk);
+ if (ec_key_key != NULL)
+ EC_KEY_free(ec_key_key);
+}
+#endif
+
+void
+_kdc_pk_free_client_ec_param(krb5_context context,
+ void *ec_key_pk,
+ void *ec_key_key)
+{
+#ifdef HAVE_HCRYPTO_W_OPENSSL
+ free_client_ec_param(context, ec_key_pk, ec_key_key);
+#endif
+}
+
+#ifdef HAVE_HCRYPTO_W_OPENSSL
+static krb5_error_code
+generate_ecdh_keyblock(krb5_context context,
+ EC_KEY *ec_key_pk, /* the client's public key */
+ EC_KEY **ec_key_key, /* the KDC's ephemeral private */
+ unsigned char **dh_gen_key, /* shared secret */
+ size_t *dh_gen_keylen)
+{
+ const EC_GROUP *group;
+ EC_KEY *ephemeral;
+ krb5_keyblock key;
+ krb5_error_code ret;
+ unsigned char *p;
+ size_t size;
+ int len;
+
+ *dh_gen_key = NULL;
+ *dh_gen_keylen = 0;
+ *ec_key_key = NULL;
+
+ memset(&key, 0, sizeof(key));
+
+ if (ec_key_pk == NULL) {
+ ret = KRB5KRB_ERR_GENERIC;
+ krb5_set_error_message(context, ret, "public_key");
+ return ret;
+ }
+
+ group = EC_KEY_get0_group(ec_key_pk);
+ if (group == NULL) {
+ ret = KRB5KRB_ERR_GENERIC;
+ krb5_set_error_message(context, ret, "failed to get the group of "
+ "the client's public key");
+ return ret;
+ }
+
+ ephemeral = EC_KEY_new();
+ if (ephemeral == NULL)
+ return krb5_enomem(context);
+
+ EC_KEY_set_group(ephemeral, group);
+
+ if (EC_KEY_generate_key(ephemeral) != 1) {
+ EC_KEY_free(ephemeral);
+ return krb5_enomem(context);
+ }
+
+ size = (EC_GROUP_get_degree(group) + 7) / 8;
+ p = malloc(size);
+ if (p == NULL) {
+ EC_KEY_free(ephemeral);
+ return krb5_enomem(context);
+ }
+
+ len = ECDH_compute_key(p, size,
+ EC_KEY_get0_public_key(ec_key_pk),
+ ephemeral, NULL);
+ if (len <= 0) {
+ free(p);
+ EC_KEY_free(ephemeral);
+ ret = KRB5KRB_ERR_GENERIC;
+ krb5_set_error_message(context, ret, "Failed to compute ECDH "
+ "public shared secret");
+ return ret;
+ }
+
+ *ec_key_key = ephemeral;
+ *dh_gen_key = p;
+ *dh_gen_keylen = len;
+
+ return 0;
+}
+#endif /* HAVE_HCRYPTO_W_OPENSSL */
+
+krb5_error_code
+_kdc_generate_ecdh_keyblock(krb5_context context,
+ void *ec_key_pk, /* the client's public key */
+ void **ec_key_key, /* the KDC's ephemeral private */
+ unsigned char **dh_gen_key, /* shared secret */
+ size_t *dh_gen_keylen)
+{
+#ifdef HAVE_HCRYPTO_W_OPENSSL
+ return generate_ecdh_keyblock(context, ec_key_pk,
+ (EC_KEY **)ec_key_key,
+ dh_gen_key, dh_gen_keylen);
+#else
+ return ENOTSUP;
+#endif /* HAVE_HCRYPTO_W_OPENSSL */
+}
+
+#ifdef HAVE_HCRYPTO_W_OPENSSL
+static krb5_error_code
+get_ecdh_param(krb5_context context,
+ krb5_kdc_configuration *config,
+ SubjectPublicKeyInfo *dh_key_info,
+ EC_KEY **out)
+{
+ ECParameters ecp;
+ EC_KEY *public = NULL;
+ krb5_error_code ret;
+ const unsigned char *p;
+ size_t len;
+ int nid;
+
+ if (dh_key_info->algorithm.parameters == NULL) {
+ krb5_set_error_message(context, KRB5_BADMSGTYPE,
+ "PKINIT missing algorithm parameter "
+ "in clientPublicValue");
+ return KRB5_BADMSGTYPE;
+ }
+
+ memset(&ecp, 0, sizeof(ecp));
+
+ ret = decode_ECParameters(dh_key_info->algorithm.parameters->data,
+ dh_key_info->algorithm.parameters->length, &ecp, &len);
+ if (ret)
+ goto out;
+
+ if (ecp.element != choice_ECParameters_namedCurve) {
+ ret = KRB5_BADMSGTYPE;
+ goto out;
+ }
+
+ if (der_heim_oid_cmp(&ecp.u.namedCurve, &asn1_oid_id_ec_group_secp256r1) == 0)
+ nid = NID_X9_62_prime256v1;
+ else {
+ ret = KRB5_BADMSGTYPE;
+ goto out;
+ }
+
+ /* XXX verify group is ok */
+
+ public = EC_KEY_new_by_curve_name(nid);
+
+ p = dh_key_info->subjectPublicKey.data;
+ len = dh_key_info->subjectPublicKey.length / 8;
+ if (o2i_ECPublicKey(&public, &p, len) == NULL) {
+ ret = KRB5_BADMSGTYPE;
+ krb5_set_error_message(context, ret,
+ "PKINIT failed to decode ECDH key");
+ goto out;
+ }
+ *out = public;
+ public = NULL;
+
+ out:
+ if (public)
+ EC_KEY_free(public);
+ free_ECParameters(&ecp);
+ return ret;
+}
+#endif /* HAVE_HCRYPTO_W_OPENSSL */
+
+krb5_error_code
+_kdc_get_ecdh_param(krb5_context context,
+ krb5_kdc_configuration *config,
+ SubjectPublicKeyInfo *dh_key_info,
+ void **out)
+{
+#ifdef HAVE_HCRYPTO_W_OPENSSL
+ return get_ecdh_param(context, config, dh_key_info, (EC_KEY **)out);
+#else
+ return ENOTSUP;
+#endif /* HAVE_HCRYPTO_W_OPENSSL */
+}
+
+
+/*
+ *
+ */
+
+#ifdef HAVE_HCRYPTO_W_OPENSSL
+static krb5_error_code
+serialize_ecdh_key(krb5_context context,
+ EC_KEY *key,
+ unsigned char **out,
+ size_t *out_len)
+{
+ krb5_error_code ret = 0;
+ unsigned char *p;
+ int len;
+
+ *out = NULL;
+ *out_len = 0;
+
+ len = i2o_ECPublicKey(key, NULL);
+ if (len <= 0)
+ return EOVERFLOW;
+
+ *out = malloc(len);
+ if (*out == NULL)
+ return krb5_enomem(context);
+
+ p = *out;
+ len = i2o_ECPublicKey(key, &p);
+ if (len <= 0) {
+ free(*out);
+ *out = NULL;
+ ret = EINVAL; /* XXX Better error please */
+ krb5_set_error_message(context, ret,
+ "PKINIT failed to encode ECDH key");
+ return ret;
+ }
+
+ *out_len = len * 8;
+ return ret;
+}
+#endif
+
+krb5_error_code
+_kdc_serialize_ecdh_key(krb5_context context,
+ void *key,
+ unsigned char **out,
+ size_t *out_len)
+{
+#ifdef HAVE_HCRYPTO_W_OPENSSL
+ return serialize_ecdh_key(context, key, out, out_len);
+#else
+ return ENOTSUP;
+#endif
+}
+
+#endif
diff --git a/kdc/pkinit.c b/kdc/pkinit.c
index d85b15650073..28333fc565b4 100644
--- a/kdc/pkinit.c
+++ b/kdc/pkinit.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003 - 2008 Kungliga Tekniska Högskolan
+ * Copyright (c) 2003 - 2016 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -47,18 +47,16 @@
struct pk_client_params {
enum krb5_pk_type type;
- enum { USE_RSA, USE_DH, USE_ECDH } keyex;
+ enum keyex_enum keyex;
union {
struct {
BIGNUM *public_key;
DH *key;
} dh;
-#ifdef HAVE_OPENSSL
struct {
- EC_KEY *public_key;
- EC_KEY *key;
+ void *public_key;
+ void *key;
} ecdh;
-#endif
} u;
hx509_cert cert;
unsigned nonce;
@@ -101,7 +99,7 @@ pk_check_pkauthenticator_win2k(krb5_context context,
krb5_timeofday (context, &now);
/* XXX cusec */
- if (a->ctime == 0 || abs(a->ctime - now) > context->max_skew) {
+ if (a->ctime == 0 || labs(a->ctime - now) > context->max_skew) {
krb5_clear_error_message(context);
return KRB5KRB_AP_ERR_SKEW;
}
@@ -123,7 +121,7 @@ pk_check_pkauthenticator(krb5_context context,
krb5_timeofday (context, &now);
/* XXX cusec */
- if (a->ctime == 0 || abs(a->ctime - now) > context->max_skew) {
+ if (a->ctime == 0 || labs(a->ctime - now) > context->max_skew) {
krb5_clear_error_message(context);
return KRB5KRB_AP_ERR_SKEW;
}
@@ -181,14 +179,9 @@ _kdc_pk_free_client_param(krb5_context context, pk_client_params *cp)
if (cp->u.dh.public_key)
BN_free(cp->u.dh.public_key);
}
-#ifdef HAVE_OPENSSL
- if (cp->keyex == USE_ECDH) {
- if (cp->u.ecdh.key)
- EC_KEY_free(cp->u.ecdh.key);
- if (cp->u.ecdh.public_key)
- EC_KEY_free(cp->u.ecdh.public_key);
- }
-#endif
+ if (cp->keyex == USE_ECDH)
+ _kdc_pk_free_client_ec_param(context, cp->u.ecdh.key,
+ cp->u.ecdh.public_key);
krb5_free_keyblock_contents(context, &cp->reply_key);
if (cp->dh_group_name)
free(cp->dh_group_name);
@@ -216,7 +209,7 @@ generate_dh_keyblock(krb5_context context,
if (client_params->u.dh.public_key == NULL) {
ret = KRB5KRB_ERR_GENERIC;
- krb5_set_error_message(context, ret, "public_key");
+ krb5_set_error_message(context, ret, "missing DH public_key");
goto out;
}
@@ -250,42 +243,18 @@ generate_dh_keyblock(krb5_context context,
}
ret = 0;
-#ifdef HAVE_OPENSSL
} else if (client_params->keyex == USE_ECDH) {
-
if (client_params->u.ecdh.public_key == NULL) {
ret = KRB5KRB_ERR_GENERIC;
- krb5_set_error_message(context, ret, "public_key");
- goto out;
- }
-
- client_params->u.ecdh.key = EC_KEY_new();
- if (client_params->u.ecdh.key == NULL) {
- ret = ENOMEM;
- goto out;
- }
- EC_KEY_set_group(client_params->u.ecdh.key,
- EC_KEY_get0_group(client_params->u.ecdh.public_key));
-
- if (EC_KEY_generate_key(client_params->u.ecdh.key) != 1) {
- ret = ENOMEM;
+ krb5_set_error_message(context, ret, "missing ECDH public_key");
goto out;
}
-
- size = (EC_GROUP_get_degree(EC_KEY_get0_group(client_params->u.ecdh.key)) + 7) / 8;
- dh_gen_key = malloc(size);
- if (dh_gen_key == NULL) {
- ret = ENOMEM;
- krb5_set_error_message(context, ret,
- N_("malloc: out of memory", ""));
- goto out;
- }
-
- dh_gen_keylen = ECDH_compute_key(dh_gen_key, size,
- EC_KEY_get0_public_key(client_params->u.ecdh.public_key),
- client_params->u.ecdh.key, NULL);
-
-#endif /* HAVE_OPENSSL */
+ ret = _kdc_generate_ecdh_keyblock(context,
+ client_params->u.ecdh.public_key,
+ &client_params->u.ecdh.key,
+ &dh_gen_key, &dh_gen_keylen);
+ if (ret)
+ goto out;
} else {
ret = KRB5KRB_ERR_GENERIC;
krb5_set_error_message(context, ret,
@@ -361,7 +330,7 @@ get_dh_param(krb5_context context,
}
ret = _krb5_dh_group_ok(context, config->pkinit_dh_min_bits,
- &dhparam.p, &dhparam.g, &dhparam.q, moduli,
+ &dhparam.p, &dhparam.g, dhparam.q, moduli,
&client_params->dh_group_name);
if (ret) {
/* XXX send back proposal of better group */
@@ -381,9 +350,12 @@ get_dh_param(krb5_context context,
dh->g = integer_to_BN(context, "DH base", &dhparam.g);
if (dh->g == NULL)
goto out;
- dh->q = integer_to_BN(context, "DH p-1 factor", &dhparam.q);
- if (dh->g == NULL)
- goto out;
+
+ if (dhparam.q) {
+ dh->q = integer_to_BN(context, "DH p-1 factor", dhparam.q);
+ if (dh->g == NULL)
+ goto out;
+ }
{
heim_integer glue;
@@ -419,71 +391,6 @@ get_dh_param(krb5_context context,
return ret;
}
-#ifdef HAVE_OPENSSL
-
-static krb5_error_code
-get_ecdh_param(krb5_context context,
- krb5_kdc_configuration *config,
- SubjectPublicKeyInfo *dh_key_info,
- pk_client_params *client_params)
-{
- ECParameters ecp;
- EC_KEY *public = NULL;
- krb5_error_code ret;
- const unsigned char *p;
- size_t len;
- int nid;
-
- if (dh_key_info->algorithm.parameters == NULL) {
- krb5_set_error_message(context, KRB5_BADMSGTYPE,
- "PKINIT missing algorithm parameter "
- "in clientPublicValue");
- return KRB5_BADMSGTYPE;
- }
-
- memset(&ecp, 0, sizeof(ecp));
-
- ret = decode_ECParameters(dh_key_info->algorithm.parameters->data,
- dh_key_info->algorithm.parameters->length, &ecp, &len);
- if (ret)
- goto out;
-
- if (ecp.element != choice_ECParameters_namedCurve) {
- ret = KRB5_BADMSGTYPE;
- goto out;
- }
-
- if (der_heim_oid_cmp(&ecp.u.namedCurve, &asn1_oid_id_ec_group_secp256r1) == 0)
- nid = NID_X9_62_prime256v1;
- else {
- ret = KRB5_BADMSGTYPE;
- goto out;
- }
-
- /* XXX verify group is ok */
-
- public = EC_KEY_new_by_curve_name(nid);
-
- p = dh_key_info->subjectPublicKey.data;
- len = dh_key_info->subjectPublicKey.length / 8;
- if (o2i_ECPublicKey(&public, &p, len) == NULL) {
- ret = KRB5_BADMSGTYPE;
- krb5_set_error_message(context, ret,
- "PKINIT failed to decode ECDH key");
- goto out;
- }
- client_params->u.ecdh.public_key = public;
- public = NULL;
-
- out:
- if (public)
- EC_KEY_free(public);
- free_ECParameters(&ecp);
- return ret;
-}
-
-#endif /* HAVE_OPENSSL */
-
krb5_error_code
_kdc_pk_rd_padata(krb5_context context,
krb5_kdc_configuration *config,
@@ -540,11 +447,11 @@ _kdc_pk_rd_padata(krb5_context context,
unsigned int i;
for (i = 0; i < pc->len; i++) {
- ret = hx509_cert_init_data(context->hx509ctx,
- pc->val[i].cert.data,
- pc->val[i].cert.length,
- &cert);
- if (ret)
+ cert = hx509_cert_init_data(context->hx509ctx,
+ pc->val[i].cert.data,
+ pc->val[i].cert.length,
+ NULL);
+ if (cert == NULL)
continue;
hx509_certs_add(context->hx509ctx, trust_anchors, cert);
hx509_cert_free(cert);
@@ -570,7 +477,7 @@ _kdc_pk_rd_padata(krb5_context context,
type = "PK-INIT-Win2k";
- if (req->req_body.kdc_options.request_anonymous) {
+ if (_kdc_is_anon_request(&req->req_body)) {
ret = KRB5_KDC_ERR_PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED;
krb5_set_error_message(context, ret,
"Anon not supported in RSA mode");
@@ -716,7 +623,7 @@ _kdc_pk_rd_padata(krb5_context context,
hx509_certs signer_certs;
int flags = HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH; /* BTMM */
- if (req->req_body.kdc_options.request_anonymous)
+ if (_kdc_is_anon_request(&req->req_body))
flags |= HX509_CMS_VS_ALLOW_ZERO_SIGNER;
ret = hx509_cms_verify_signed(context->hx509ctx,
@@ -801,7 +708,7 @@ _kdc_pk_rd_padata(krb5_context context,
goto out;
}
- if (req->req_body.kdc_options.request_anonymous &&
+ if (_kdc_is_anon_request(&req->req_body) &&
ap.clientPublicValue == NULL) {
free_AuthPack(&ap);
ret = KRB5_KDC_ERR_PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED;
@@ -826,12 +733,11 @@ _kdc_pk_rd_padata(krb5_context context,
cp->keyex = USE_DH;
ret = get_dh_param(context, config,
ap.clientPublicValue, cp);
-#ifdef HAVE_OPENSSL
} else if (der_heim_oid_cmp(&ap.clientPublicValue->algorithm.algorithm, &asn1_oid_id_ecPublicKey) == 0) {
cp->keyex = USE_ECDH;
- ret = get_ecdh_param(context, config,
- ap.clientPublicValue, cp);
-#endif /* HAVE_OPENSSL */
+ ret = _kdc_get_ecdh_param(context, config,
+ ap.clientPublicValue,
+ &cp->u.ecdh.public_key);
} else {
ret = KRB5_BADMSGTYPE;
krb5_set_error_message(context, ret, "PKINIT unknown DH mechanism");
@@ -1131,26 +1037,13 @@ pk_mk_pa_reply_dh(krb5_context context,
dh_info.subjectPublicKey.length = buf.length * 8;
dh_info.subjectPublicKey.data = buf.data;
krb5_data_zero(&buf);
-#ifdef HAVE_OPENSSL
} else if (cp->keyex == USE_ECDH) {
- unsigned char *p;
- int len;
-
- len = i2o_ECPublicKey(cp->u.ecdh.key, NULL);
- if (len <= 0)
- abort();
-
- p = malloc(len);
- if (p == NULL)
- abort();
-
- dh_info.subjectPublicKey.length = len * 8;
- dh_info.subjectPublicKey.data = p;
-
- len = i2o_ECPublicKey(cp->u.ecdh.key, &p);
- if (len <= 0)
- abort();
-#endif
+ unsigned char *p;
+ ret = _kdc_serialize_ecdh_key(context, cp->u.ecdh.key, &p,
+ &dh_info.subjectPublicKey.length);
+ dh_info.subjectPublicKey.data = p;
+ if (ret)
+ goto out;
} else
krb5_abortx(context, "no keyex selected ?");
@@ -1237,7 +1130,7 @@ _kdc_pk_mk_pa_reply(krb5_context context,
krb5_enctype sessionetype,
const KDC_REQ *req,
const krb5_data *req_buffer,
- krb5_keyblock **reply_key,
+ krb5_keyblock *reply_key,
krb5_keyblock *sessionkey,
METHOD_DATA *md)
{
@@ -1326,9 +1219,7 @@ _kdc_pk_mk_pa_reply(krb5_context context,
switch (cp->keyex) {
case USE_DH: type = "dh"; break;
-#ifdef HAVE_OPENSSL
case USE_ECDH: type = "ecdh"; break;
-#endif
default: krb5_abortx(context, "unknown keyex"); break;
}
@@ -1367,16 +1258,86 @@ _kdc_pk_mk_pa_reply(krb5_context context,
if (rep.u.encKeyPack.length != size)
krb5_abortx(context, "Internal ASN.1 encoder error");
- /* XXX KRB-FX-CF2 */
- ret = krb5_generate_random_keyblock(context, sessionetype,
- sessionkey);
- if (ret) {
- free_PA_PK_AS_REP(&rep);
- goto out;
+ /* generate the session key using the method from RFC6112 */
+ {
+ krb5_keyblock kdc_contribution_key;
+ krb5_crypto reply_crypto;
+ krb5_crypto kdccont_crypto;
+ krb5_data p1 = { strlen("PKINIT"), "PKINIT"};
+ krb5_data p2 = { strlen("KEYEXCHANGE"), "KEYEXCHANGE"};
+ void *kckdata;
+ size_t kcklen;
+ EncryptedData kx;
+ void *kxdata;
+ size_t kxlen;
+
+ ret = krb5_generate_random_keyblock(context, sessionetype,
+ &kdc_contribution_key);
+ if (ret) {
+ free_PA_PK_AS_REP(&rep);
+ goto out;
+ }
+ ret = krb5_crypto_init(context, &cp->reply_key, enctype, &reply_crypto);
+ if (ret) {
+ krb5_free_keyblock_contents(context, &kdc_contribution_key);
+ free_PA_PK_AS_REP(&rep);
+ goto out;
+ }
+ ret = krb5_crypto_init(context, &kdc_contribution_key, sessionetype, &kdccont_crypto);
+ if (ret) {
+ krb5_crypto_destroy(context, reply_crypto);
+ krb5_free_keyblock_contents(context, &kdc_contribution_key);
+ free_PA_PK_AS_REP(&rep);
+ goto out;
+ }
+ /* KRB-FX-CF2 */
+ ret = krb5_crypto_fx_cf2(context, kdccont_crypto, reply_crypto,
+ &p1, &p2, sessionetype, sessionkey);
+ krb5_crypto_destroy(context, kdccont_crypto);
+ if (ret) {
+ krb5_crypto_destroy(context, reply_crypto);
+ krb5_free_keyblock_contents(context, &kdc_contribution_key);
+ free_PA_PK_AS_REP(&rep);
+ goto out;
+ }
+ ASN1_MALLOC_ENCODE(EncryptionKey, kckdata, kcklen,
+ &kdc_contribution_key, &size, ret);
+ krb5_free_keyblock_contents(context, &kdc_contribution_key);
+ if (ret) {
+ krb5_set_error_message(context, ret, "encoding of PKINIT-KX Key failed %d", ret);
+ krb5_crypto_destroy(context, reply_crypto);
+ free_PA_PK_AS_REP(&rep);
+ goto out;
+ }
+ if (kcklen != size)
+ krb5_abortx(context, "Internal ASN.1 encoder error");
+ ret = krb5_encrypt_EncryptedData(context, reply_crypto, KRB5_KU_PA_PKINIT_KX,
+ kckdata, kcklen, 0, &kx);
+ krb5_crypto_destroy(context, reply_crypto);
+ free(kckdata);
+ if (ret) {
+ free_PA_PK_AS_REP(&rep);
+ goto out;
+ }
+ ASN1_MALLOC_ENCODE(EncryptedData, kxdata, kxlen,
+ &kx, &size, ret);
+ free_EncryptedData(&kx);
+ if (ret) {
+ krb5_set_error_message(context, ret, "encoding of PKINIT-KX failed %d", ret);
+ free_PA_PK_AS_REP(&rep);
+ goto out;
+ }
+ if (kxlen != size)
+ krb5_abortx(context, "Internal ASN.1 encoder error");
+ /* Add PA-PKINIT-KX */
+ ret = krb5_padata_add(context, md, KRB5_PADATA_PKINIT_KX, kxdata, kxlen);
+ if (ret) {
+ krb5_set_error_message(context, ret,
+ "Failed adding PKINIT-KX %d", ret);
+ free(buf);
+ goto out;
+ }
}
-
- /* XXX Add PA-PKINIT-KX */
-
}
#define use_btmm_with_enckey 0
@@ -1563,7 +1524,7 @@ out:
hx509_cert_free(kdc_cert);
if (ret == 0)
- *reply_key = &cp->reply_key;
+ ret = krb5_copy_keyblock_contents(context, &cp->reply_key, reply_key);
return ret;
}
@@ -1608,6 +1569,7 @@ match_rfc_san(krb5_context context,
return KRB5_KDC_ERR_CLIENT_NAME_MISMATCH;
}
+ memset(&principal, 0, sizeof (principal));
principal.name = kn.principalName;
principal.realm = kn.realm;
@@ -1653,6 +1615,7 @@ match_ms_upn_san(krb5_context context,
if (list.len != 1) {
kdc_log(context, config, 0,
"More then one PK-INIT MS UPN SAN");
+ ret = KRB5_KDC_ERR_CLIENT_NAME_MISMATCH;
goto out;
}
@@ -1741,11 +1704,11 @@ _kdc_pk_check_client(krb5_context context,
size_t j;
for (j = 0; j < pc->len; j++) {
- ret = hx509_cert_init_data(context->hx509ctx,
- pc->val[j].cert.data,
- pc->val[j].cert.length,
- &cert);
- if (ret)
+ cert = hx509_cert_init_data(context->hx509ctx,
+ pc->val[j].cert.data,
+ pc->val[j].cert.length,
+ NULL);
+ if (cert == NULL)
continue;
ret = hx509_cert_cmp(cert, cp->cert);
hx509_cert_free(cert);
@@ -2034,7 +1997,14 @@ krb5_kdc_pk_initialize(krb5_context context,
"pkinit_mappings_file",
NULL);
if (file == NULL) {
- asprintf(&fn, "%s/pki-mapping", hdb_db_dir(context));
+ int aret;
+
+ aret = asprintf(&fn, "%s/pki-mapping", hdb_db_dir(context));
+ if (aret == -1) {
+ krb5_warnx(context, "PKINIT: out of memory");
+ return ENOMEM;
+ }
+
file = fn;
}
diff --git a/kdc/process.c b/kdc/process.c
index 6f36915800bb..f91d4174ae3e 100644
--- a/kdc/process.c
+++ b/kdc/process.c
@@ -57,19 +57,25 @@ kdc_as_req(krb5_context context,
int datagram_reply,
int *claim)
{
+ struct kdc_request_desc r;
krb5_error_code ret;
- KDC_REQ req;
size_t len;
- ret = decode_AS_REQ(req_buffer->data, req_buffer->length, &req, &len);
+ memset(&r, 0, sizeof(r));
+
+ ret = decode_AS_REQ(req_buffer->data, req_buffer->length, &r.req, &len);
if (ret)
return ret;
+ r.context = context;
+ r.config = config;
+ r.request.data = req_buffer->data;
+ r.request.length = req_buffer->length;
+
*claim = 1;
- ret = _kdc_as_rep(context, config, &req, req_buffer,
- reply, from, addr, datagram_reply);
- free_AS_REQ(&req);
+ ret = _kdc_as_rep(&r, reply, from, addr, datagram_reply);
+ free_AS_REQ(&r.req);
return ret;
}
@@ -193,6 +199,7 @@ krb5_kdc_process_request(krb5_context context,
unsigned int i;
krb5_data req_buffer;
int claim = 0;
+ heim_auto_release_t pool = heim_auto_release_create();
req_buffer.data = buf;
req_buffer.length = len;
@@ -204,10 +211,14 @@ krb5_kdc_process_request(krb5_context context,
if (claim) {
if (services[i].flags & KS_NO_LENGTH)
*prependlength = 0;
+
+ heim_release(pool);
return ret;
}
}
+ heim_release(pool);
+
return -1;
}
diff --git a/kdc/string2key.c b/kdc/string2key.c
index 6f24c27a29a0..1b603dece58d 100644
--- a/kdc/string2key.c
+++ b/kdc/string2key.c
@@ -128,9 +128,9 @@ main(int argc, char **argv)
if(ret)
krb5_err(context, 1, ret, "krb5_string_to_enctype");
- if((etype != ETYPE_DES_CBC_CRC &&
- etype != ETYPE_DES_CBC_MD4 &&
- etype != ETYPE_DES_CBC_MD5) &&
+ if((etype != (krb5_enctype)ETYPE_DES_CBC_CRC &&
+ etype != (krb5_enctype)ETYPE_DES_CBC_MD4 &&
+ etype != (krb5_enctype)ETYPE_DES_CBC_MD5) &&
(afs || version4)) {
if(!version5) {
etype = ETYPE_DES_CBC_CRC;
@@ -163,8 +163,13 @@ main(int argc, char **argv)
}
if(version5){
- krb5_parse_name(context, principal, &princ);
- krb5_get_pw_salt(context, princ, &salt);
+ ret = krb5_parse_name(context, principal, &princ);
+ if (ret)
+ krb5_err(context, 1, ret, "failed to unparse name: %s", principal);
+ ret = krb5_get_pw_salt(context, princ, &salt);
+ if (ret)
+ krb5_err(context, 1, ret, "failed to get salt for %s", principal);
+
tokey(context, etype, password, salt, "Kerberos 5 (%s)");
krb5_free_salt(context, salt);
}
diff --git a/kdc/windc.c b/kdc/windc.c
index ba87abb7cc0b..4048f6ca841c 100644
--- a/kdc/windc.c
+++ b/kdc/windc.c
@@ -33,40 +33,41 @@
#include "kdc_locl.h"
-static krb5plugin_windc_ftable *windcft;
-static void *windcctx;
+static int have_plugin = 0;
/*
* Pick the first WINDC module that we find.
*/
+static krb5_error_code KRB5_LIB_CALL
+load(krb5_context context, const void *plug, void *plugctx, void *userctx)
+{
+ have_plugin = 1;
+ return KRB5_PLUGIN_NO_HANDLE;
+}
+
krb5_error_code
krb5_kdc_windc_init(krb5_context context)
{
- struct krb5_plugin *list = NULL, *e;
- krb5_error_code ret;
-
- ret = _krb5_plugin_find(context, PLUGIN_TYPE_DATA, "windc", &list);
- if(ret != 0 || list == NULL)
- return 0;
-
- for (e = list; e != NULL; e = _krb5_plugin_get_next(e)) {
+ (void)_krb5_plugin_run_f(context, "krb5", "windc",
+ KRB5_WINDC_PLUGIN_MINOR, 0, NULL, load);
+ return 0;
+}
- windcft = _krb5_plugin_get_symbol(e);
- if (windcft->minor_version < KRB5_WINDC_PLUGIN_MINOR)
- continue;
+struct generate_uc {
+ hdb_entry_ex *client;
+ krb5_pac *pac;
+};
- (*windcft->init)(context, &windcctx);
- break;
- }
- _krb5_plugin_free(list);
- if (e == NULL) {
- krb5_set_error_message(context, ENOENT, "Did not find any WINDC plugin");
- windcft = NULL;
- return ENOENT;
- }
+static krb5_error_code KRB5_LIB_CALL
+generate(krb5_context context, const void *plug, void *plugctx, void *userctx)
+{
+ krb5plugin_windc_ftable *ft = (krb5plugin_windc_ftable *)plug;
+ struct generate_uc *uc = (struct generate_uc *)userctx;
- return 0;
+ if (ft->pac_generate == NULL)
+ return KRB5_PLUGIN_NO_HANDLE;
+ return ft->pac_generate((void *)plug, context, uc->client, uc->pac);
}
@@ -75,10 +76,46 @@ _kdc_pac_generate(krb5_context context,
hdb_entry_ex *client,
krb5_pac *pac)
{
- *pac = NULL;
- if (windcft == NULL)
+ struct generate_uc uc;
+
+ if (!have_plugin)
return 0;
- return (windcft->pac_generate)(windcctx, context, client, pac);
+
+ uc.client = client;
+ uc.pac = pac;
+
+ (void)_krb5_plugin_run_f(context, "krb5", "windc",
+ KRB5_WINDC_PLUGIN_MINOR, 0, &uc, generate);
+ return 0;
+}
+
+struct verify_uc {
+ krb5_principal client_principal;
+ krb5_principal delegated_proxy_principal;
+ hdb_entry_ex *client;
+ hdb_entry_ex *server;
+ hdb_entry_ex *krbtgt;
+ krb5_pac *pac;
+ int *verified;
+};
+
+static krb5_error_code KRB5_LIB_CALL
+verify(krb5_context context, const void *plug, void *plugctx, void *userctx)
+{
+ krb5plugin_windc_ftable *ft = (krb5plugin_windc_ftable *)plug;
+ struct verify_uc *uc = (struct verify_uc *)userctx;
+ krb5_error_code ret;
+
+ if (ft->pac_verify == NULL)
+ return KRB5_PLUGIN_NO_HANDLE;
+ ret = ft->pac_verify((void *)plug, context,
+ uc->client_principal,
+ uc->delegated_proxy_principal,
+ uc->client, uc->server, uc->krbtgt, uc->pac);
+ if (ret == 0)
+ (*uc->verified) = 1;
+
+ return 0;
}
krb5_error_code
@@ -91,37 +128,77 @@ _kdc_pac_verify(krb5_context context,
krb5_pac *pac,
int *verified)
{
- krb5_error_code ret;
+ struct verify_uc uc;
- if (windcft == NULL)
+ if (!have_plugin)
return 0;
- ret = windcft->pac_verify(windcctx, context,
- client_principal,
- delegated_proxy_principal,
- client, server, krbtgt, pac);
- if (ret == 0)
- *verified = 1;
- return ret;
+ uc.client_principal = client_principal;
+ uc.delegated_proxy_principal = delegated_proxy_principal;
+ uc.client = client;
+ uc.server = server;
+ uc.krbtgt = krbtgt;
+ uc.pac = pac;
+ uc.verified = verified;
+
+ (void)_krb5_plugin_run_f(context, "krb5", "windc",
+ KRB5_WINDC_PLUGIN_MINOR, 0, &uc, verify);
+ return 0;
+}
+
+struct check_uc {
+ krb5_kdc_configuration *config;
+ hdb_entry_ex *client_ex;
+ const char *client_name;
+ hdb_entry_ex *server_ex;
+ const char *server_name;
+ KDC_REQ *req;
+ METHOD_DATA *method_data;
+};
+
+static krb5_error_code KRB5_LIB_CALL
+check(krb5_context context, const void *plug, void *plugctx, void *userctx)
+{
+ krb5plugin_windc_ftable *ft = (krb5plugin_windc_ftable *)plug;
+ struct check_uc *uc = (struct check_uc *)userctx;
+
+ if (ft->client_access == NULL)
+ return KRB5_PLUGIN_NO_HANDLE;
+ return ft->client_access((void *)plug, context, uc->config,
+ uc->client_ex, uc->client_name,
+ uc->server_ex, uc->server_name,
+ uc->req, uc->method_data);
}
+
krb5_error_code
_kdc_check_access(krb5_context context,
krb5_kdc_configuration *config,
hdb_entry_ex *client_ex, const char *client_name,
hdb_entry_ex *server_ex, const char *server_name,
KDC_REQ *req,
- krb5_data *e_data)
+ METHOD_DATA *method_data)
{
- if (windcft == NULL)
- return kdc_check_flags(context, config,
- client_ex, client_name,
- server_ex, server_name,
- req->msg_type == krb_as_req);
-
- return (windcft->client_access)(windcctx,
- context, config,
- client_ex, client_name,
- server_ex, server_name,
- req, e_data);
+ krb5_error_code ret = KRB5_PLUGIN_NO_HANDLE;
+ struct check_uc uc;
+
+ if (have_plugin) {
+ uc.config = config;
+ uc.client_ex = client_ex;
+ uc.client_name = client_name;
+ uc.server_ex = server_ex;
+ uc.server_name = server_name;
+ uc.req = req;
+ uc.method_data = method_data;
+
+ ret = _krb5_plugin_run_f(context, "krb5", "windc",
+ KRB5_WINDC_PLUGIN_MINOR, 0, &uc, check);
+ }
+
+ if (ret == KRB5_PLUGIN_NO_HANDLE)
+ return kdc_check_flags(context, config,
+ client_ex, client_name,
+ server_ex, server_name,
+ req->msg_type == krb_as_req);
+ return ret;
}
diff --git a/kdc/windc_plugin.h b/kdc/windc_plugin.h
index fa4ba434f3ed..4401500e6563 100644
--- a/kdc/windc_plugin.h
+++ b/kdc/windc_plugin.h
@@ -68,9 +68,9 @@ typedef krb5_error_code
(*krb5plugin_windc_client_access)(
void *, krb5_context,
krb5_kdc_configuration *config,
- hdb_entry_ex *, const char *,
- hdb_entry_ex *, const char *,
- KDC_REQ *, krb5_data *);
+ hdb_entry_ex *, const char *,
+ hdb_entry_ex *, const char *,
+ KDC_REQ *, METHOD_DATA *);
#define KRB5_WINDC_PLUGIN_MINOR 6