diff options
Diffstat (limited to 'lib/krb5')
215 files changed, 69373 insertions, 0 deletions
diff --git a/lib/krb5/Makefile.am b/lib/krb5/Makefile.am new file mode 100644 index 0000000..ced9616 --- /dev/null +++ b/lib/krb5/Makefile.am @@ -0,0 +1,298 @@ +# $Id: Makefile.am 22501 2008-01-21 15:43:21Z lha $ + +include $(top_srcdir)/Makefile.am.common + +AM_CPPFLAGS += $(INCLUDE_krb4) $(INCLUDE_hcrypto) -I../com_err -I$(srcdir)/../com_err + +bin_PROGRAMS = verify_krb5_conf + +noinst_PROGRAMS = \ + krbhst-test \ + test_alname \ + test_crypto \ + test_get_addrs \ + test_kuserok \ + test_renew \ + test_forward + +TESTS = \ + aes-test \ + derived-key-test \ + n-fold-test \ + name-45-test \ + parse-name-test \ + store-test \ + string-to-key-test \ + test_acl \ + test_addr \ + test_cc \ + test_config \ + test_prf \ + test_store \ + test_crypto_wrapping \ + test_keytab \ + test_mem \ + test_pac \ + test_plugin \ + test_princ \ + test_pkinit_dh2key \ + test_time + +check_PROGRAMS = $(TESTS) test_hostname + +LDADD = libkrb5.la \ + $(LIB_hcrypto) \ + $(top_builddir)/lib/asn1/libasn1.la \ + $(LIB_roken) + +if PKINIT +LIB_pkinit = ../hx509/libhx509.la +endif + +libkrb5_la_LIBADD = \ + $(LIB_pkinit) \ + $(LIB_com_err) \ + $(LIB_hcrypto) \ + $(top_builddir)/lib/asn1/libasn1.la \ + $(LIBADD_roken) \ + $(LIB_door_create) \ + $(LIB_dlopen) + +lib_LTLIBRARIES = libkrb5.la + +ERR_FILES = krb5_err.c krb_err.c heim_err.c k524_err.c + +libkrb5_la_CPPFLAGS = -DBUILD_KRB5_LIB $(AM_CPPFLAGS) + +dist_libkrb5_la_SOURCES = \ + acache.c \ + acl.c \ + add_et_list.c \ + addr_families.c \ + aname_to_localname.c \ + appdefault.c \ + asn1_glue.c \ + auth_context.c \ + build_ap_req.c \ + build_auth.c \ + cache.c \ + changepw.c \ + codec.c \ + config_file.c \ + config_file_netinfo.c \ + convert_creds.c \ + constants.c \ + context.c \ + copy_host_realm.c \ + crc.c \ + creds.c \ + crypto.c \ + doxygen.c \ + data.c \ + digest.c \ + eai_to_heim_errno.c \ + error_string.c \ + expand_hostname.c \ + fcache.c \ + free.c \ + free_host_realm.c \ + generate_seq_number.c \ + generate_subkey.c \ + get_addrs.c \ + get_cred.c \ + get_default_principal.c \ + get_default_realm.c \ + get_for_creds.c \ + get_host_realm.c \ + get_in_tkt.c \ + get_in_tkt_pw.c \ + get_in_tkt_with_keytab.c \ + get_in_tkt_with_skey.c \ + get_port.c \ + heim_threads.h \ + init_creds.c \ + init_creds_pw.c \ + kcm.c \ + kcm.h \ + keyblock.c \ + keytab.c \ + keytab_any.c \ + keytab_file.c \ + keytab_keyfile.c \ + keytab_krb4.c \ + keytab_memory.c \ + krb5_locl.h \ + krb5-v4compat.h \ + krbhst.c \ + kuserok.c \ + log.c \ + mcache.c \ + misc.c \ + mk_error.c \ + mk_priv.c \ + mk_rep.c \ + mk_req.c \ + mk_req_ext.c \ + mk_safe.c \ + mit_glue.c \ + net_read.c \ + net_write.c \ + n-fold.c \ + pac.c \ + padata.c \ + pkinit.c \ + principal.c \ + prog_setup.c \ + prompter_posix.c \ + rd_cred.c \ + rd_error.c \ + rd_priv.c \ + rd_rep.c \ + rd_req.c \ + rd_safe.c \ + read_message.c \ + recvauth.c \ + replay.c \ + send_to_kdc.c \ + sendauth.c \ + set_default_realm.c \ + sock_principal.c \ + store.c \ + store-int.h \ + store_emem.c \ + store_fd.c \ + store_mem.c \ + plugin.c \ + ticket.c \ + time.c \ + transited.c \ + v4_glue.c \ + verify_init.c \ + verify_user.c \ + version.c \ + warn.c \ + write_message.c + +nodist_libkrb5_la_SOURCES = \ + $(ERR_FILES) + +libkrb5_la_LDFLAGS = -version-info 24:0:0 + +if versionscript +libkrb5_la_LDFLAGS += $(LDFLAGS_VERSION_SCRIPT)$(srcdir)/version-script.map +endif + +$(libkrb5_la_OBJECTS) $(verify_krb5_conf_OBJECTS): $(srcdir)/krb5-protos.h $(srcdir)/krb5-private.h + +$(srcdir)/krb5-protos.h: + cd $(srcdir) && perl ../../cf/make-proto.pl -E KRB5_LIB_FUNCTION -q -P comment -o krb5-protos.h $(dist_libkrb5_la_SOURCES) || rm -f krb5-protos.h + +$(srcdir)/krb5-private.h: + cd $(srcdir) && perl ../../cf/make-proto.pl -q -P comment -p krb5-private.h $(dist_libkrb5_la_SOURCES) || rm -f krb5-private.h + +man_MANS = \ + kerberos.8 \ + krb5.3 \ + krb5.conf.5 \ + krb524_convert_creds_kdc.3 \ + krb5_425_conv_principal.3 \ + krb5_acl_match_file.3 \ + krb5_address.3 \ + krb5_aname_to_localname.3 \ + krb5_appdefault.3 \ + krb5_auth_context.3 \ + krb5_c_make_checksum.3 \ + krb5_ccache.3 \ + krb5_check_transited.3 \ + krb5_compare_creds.3 \ + krb5_config.3 \ + krb5_context.3 \ + krb5_create_checksum.3 \ + krb5_creds.3 \ + krb5_crypto_init.3 \ + krb5_data.3 \ + krb5_digest.3 \ + krb5_eai_to_heim_errno.3 \ + krb5_encrypt.3 \ + krb5_expand_hostname.3 \ + krb5_find_padata.3 \ + krb5_generate_random_block.3 \ + krb5_get_all_client_addrs.3 \ + krb5_get_credentials.3 \ + krb5_get_creds.3 \ + krb5_get_forwarded_creds.3 \ + krb5_get_in_cred.3 \ + krb5_get_init_creds.3 \ + krb5_get_krbhst.3 \ + krb5_getportbyname.3 \ + krb5_init_context.3 \ + krb5_is_thread_safe.3 \ + krb5_keyblock.3 \ + krb5_keytab.3 \ + krb5_krbhst_init.3 \ + krb5_kuserok.3 \ + krb5_mk_req.3 \ + krb5_mk_safe.3 \ + krb5_openlog.3 \ + krb5_parse_name.3 \ + krb5_principal.3 \ + krb5_rcache.3 \ + krb5_rd_error.3 \ + krb5_rd_safe.3 \ + krb5_set_default_realm.3 \ + krb5_set_password.3 \ + krb5_storage.3 \ + krb5_string_to_key.3 \ + krb5_ticket.3 \ + krb5_timeofday.3 \ + krb5_unparse_name.3 \ + krb5_verify_init_creds.3 \ + krb5_verify_user.3 \ + krb5_warn.3 \ + verify_krb5_conf.8 + +dist_include_HEADERS = \ + krb5.h \ + krb5-protos.h \ + krb5-private.h \ + krb5_ccapi.h + +nodist_include_HEADERS = krb5_err.h heim_err.h k524_err.h + +# XXX use nobase_include_HEADERS = krb5/locate_plugin.h +krb5dir = $(includedir)/krb5 +krb5_HEADERS = locate_plugin.h + +build_HEADERZ = \ + heim_threads.h \ + $(krb5_HEADERS) \ + krb_err.h + +CLEANFILES = \ + krb5_err.c krb5_err.h \ + krb_err.c krb_err.h \ + heim_err.c heim_err.h \ + k524_err.c k524_err.h + +$(libkrb5_la_OBJECTS): krb5_err.h krb_err.h heim_err.h k524_err.h + +EXTRA_DIST = \ + krb5_err.et \ + krb_err.et \ + heim_err.et \ + k524_err.et \ + $(man_MANS) \ + version-script.map \ + krb5.moduli + +#sysconf_DATA = krb5.moduli + +# to help stupid solaris make + +krb5_err.h: krb5_err.et + +krb_err.h: krb_err.et + +heim_err.h: heim_err.et + +k524_err.h: k524_err.et diff --git a/lib/krb5/Makefile.in b/lib/krb5/Makefile.in new file mode 100644 index 0000000..60e0925 --- /dev/null +++ b/lib/krb5/Makefile.in @@ -0,0 +1,2021 @@ +# Makefile.in generated by automake 1.10 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# $Id: Makefile.am 22501 2008-01-21 15:43:21Z lha $ + +# $Id: Makefile.am.common 10998 2002-05-19 18:35:37Z joda $ + +# $Id: Makefile.am.common 22488 2008-01-21 11:47:22Z lha $ + + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +DIST_COMMON = $(dist_include_HEADERS) $(krb5_HEADERS) \ + $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/Makefile.am.common \ + $(top_srcdir)/cf/Makefile.am.common +bin_PROGRAMS = verify_krb5_conf$(EXEEXT) +noinst_PROGRAMS = krbhst-test$(EXEEXT) test_alname$(EXEEXT) \ + test_crypto$(EXEEXT) test_get_addrs$(EXEEXT) \ + test_kuserok$(EXEEXT) test_renew$(EXEEXT) \ + test_forward$(EXEEXT) +TESTS = aes-test$(EXEEXT) derived-key-test$(EXEEXT) \ + n-fold-test$(EXEEXT) name-45-test$(EXEEXT) \ + parse-name-test$(EXEEXT) store-test$(EXEEXT) \ + string-to-key-test$(EXEEXT) test_acl$(EXEEXT) \ + test_addr$(EXEEXT) test_cc$(EXEEXT) test_config$(EXEEXT) \ + test_prf$(EXEEXT) test_store$(EXEEXT) \ + test_crypto_wrapping$(EXEEXT) test_keytab$(EXEEXT) \ + test_mem$(EXEEXT) test_pac$(EXEEXT) test_plugin$(EXEEXT) \ + test_princ$(EXEEXT) test_pkinit_dh2key$(EXEEXT) \ + test_time$(EXEEXT) +check_PROGRAMS = $(am__EXEEXT_1) test_hostname$(EXEEXT) +@versionscript_TRUE@am__append_1 = $(LDFLAGS_VERSION_SCRIPT)$(srcdir)/version-script.map +subdir = lib/krb5 +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/cf/aix.m4 \ + $(top_srcdir)/cf/auth-modules.m4 $(top_srcdir)/cf/autobuild.m4 \ + $(top_srcdir)/cf/broken-getaddrinfo.m4 \ + $(top_srcdir)/cf/broken-glob.m4 \ + $(top_srcdir)/cf/broken-realloc.m4 \ + $(top_srcdir)/cf/broken-snprintf.m4 $(top_srcdir)/cf/broken.m4 \ + $(top_srcdir)/cf/broken2.m4 $(top_srcdir)/cf/c-attribute.m4 \ + $(top_srcdir)/cf/capabilities.m4 \ + $(top_srcdir)/cf/check-compile-et.m4 \ + $(top_srcdir)/cf/check-getpwnam_r-posix.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/db.m4 $(top_srcdir)/cf/destdirs.m4 \ + $(top_srcdir)/cf/dlopen.m4 \ + $(top_srcdir)/cf/find-func-no-libs.m4 \ + $(top_srcdir)/cf/find-func-no-libs2.m4 \ + $(top_srcdir)/cf/find-func.m4 \ + $(top_srcdir)/cf/find-if-not-broken.m4 \ + $(top_srcdir)/cf/framework-security.m4 \ + $(top_srcdir)/cf/have-struct-field.m4 \ + $(top_srcdir)/cf/have-type.m4 $(top_srcdir)/cf/irix.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-readline.m4 \ + $(top_srcdir)/cf/krb-struct-spwd.m4 \ + $(top_srcdir)/cf/krb-struct-winsize.m4 \ + $(top_srcdir)/cf/largefile.m4 $(top_srcdir)/cf/mips-abi.m4 \ + $(top_srcdir)/cf/misc.m4 $(top_srcdir)/cf/need-proto.m4 \ + $(top_srcdir)/cf/osfc2.m4 $(top_srcdir)/cf/otp.m4 \ + $(top_srcdir)/cf/proto-compat.m4 $(top_srcdir)/cf/pthreads.m4 \ + $(top_srcdir)/cf/resolv.m4 $(top_srcdir)/cf/retsigtype.m4 \ + $(top_srcdir)/cf/roken-frag.m4 \ + $(top_srcdir)/cf/socket-wrapper.m4 $(top_srcdir)/cf/sunos.m4 \ + $(top_srcdir)/cf/telnet.m4 $(top_srcdir)/cf/test-package.m4 \ + $(top_srcdir)/cf/version-script.m4 $(top_srcdir)/cf/wflags.m4 \ + $(top_srcdir)/cf/win32.m4 $(top_srcdir)/cf/with-all.m4 \ + $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/include/config.h +CONFIG_CLEAN_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ + "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(man5dir)" \ + "$(DESTDIR)$(man8dir)" "$(DESTDIR)$(includedir)" \ + "$(DESTDIR)$(krb5dir)" "$(DESTDIR)$(includedir)" +libLTLIBRARIES_INSTALL = $(INSTALL) +LTLIBRARIES = $(lib_LTLIBRARIES) +am__DEPENDENCIES_1 = +libkrb5_la_DEPENDENCIES = $(LIB_pkinit) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(top_builddir)/lib/asn1/libasn1.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +dist_libkrb5_la_OBJECTS = libkrb5_la-acache.lo libkrb5_la-acl.lo \ + libkrb5_la-add_et_list.lo libkrb5_la-addr_families.lo \ + libkrb5_la-aname_to_localname.lo libkrb5_la-appdefault.lo \ + libkrb5_la-asn1_glue.lo libkrb5_la-auth_context.lo \ + libkrb5_la-build_ap_req.lo libkrb5_la-build_auth.lo \ + libkrb5_la-cache.lo libkrb5_la-changepw.lo libkrb5_la-codec.lo \ + libkrb5_la-config_file.lo libkrb5_la-config_file_netinfo.lo \ + libkrb5_la-convert_creds.lo libkrb5_la-constants.lo \ + libkrb5_la-context.lo libkrb5_la-copy_host_realm.lo \ + libkrb5_la-crc.lo libkrb5_la-creds.lo libkrb5_la-crypto.lo \ + libkrb5_la-doxygen.lo libkrb5_la-data.lo libkrb5_la-digest.lo \ + libkrb5_la-eai_to_heim_errno.lo libkrb5_la-error_string.lo \ + libkrb5_la-expand_hostname.lo libkrb5_la-fcache.lo \ + libkrb5_la-free.lo libkrb5_la-free_host_realm.lo \ + libkrb5_la-generate_seq_number.lo \ + libkrb5_la-generate_subkey.lo libkrb5_la-get_addrs.lo \ + libkrb5_la-get_cred.lo libkrb5_la-get_default_principal.lo \ + libkrb5_la-get_default_realm.lo libkrb5_la-get_for_creds.lo \ + libkrb5_la-get_host_realm.lo libkrb5_la-get_in_tkt.lo \ + libkrb5_la-get_in_tkt_pw.lo \ + libkrb5_la-get_in_tkt_with_keytab.lo \ + libkrb5_la-get_in_tkt_with_skey.lo libkrb5_la-get_port.lo \ + libkrb5_la-init_creds.lo libkrb5_la-init_creds_pw.lo \ + libkrb5_la-kcm.lo libkrb5_la-keyblock.lo libkrb5_la-keytab.lo \ + libkrb5_la-keytab_any.lo libkrb5_la-keytab_file.lo \ + libkrb5_la-keytab_keyfile.lo libkrb5_la-keytab_krb4.lo \ + libkrb5_la-keytab_memory.lo libkrb5_la-krbhst.lo \ + libkrb5_la-kuserok.lo libkrb5_la-log.lo libkrb5_la-mcache.lo \ + libkrb5_la-misc.lo libkrb5_la-mk_error.lo \ + libkrb5_la-mk_priv.lo libkrb5_la-mk_rep.lo \ + libkrb5_la-mk_req.lo libkrb5_la-mk_req_ext.lo \ + libkrb5_la-mk_safe.lo libkrb5_la-mit_glue.lo \ + libkrb5_la-net_read.lo libkrb5_la-net_write.lo \ + libkrb5_la-n-fold.lo libkrb5_la-pac.lo libkrb5_la-padata.lo \ + libkrb5_la-pkinit.lo libkrb5_la-principal.lo \ + libkrb5_la-prog_setup.lo libkrb5_la-prompter_posix.lo \ + libkrb5_la-rd_cred.lo libkrb5_la-rd_error.lo \ + libkrb5_la-rd_priv.lo libkrb5_la-rd_rep.lo \ + libkrb5_la-rd_req.lo libkrb5_la-rd_safe.lo \ + libkrb5_la-read_message.lo libkrb5_la-recvauth.lo \ + libkrb5_la-replay.lo libkrb5_la-send_to_kdc.lo \ + libkrb5_la-sendauth.lo libkrb5_la-set_default_realm.lo \ + libkrb5_la-sock_principal.lo libkrb5_la-store.lo \ + libkrb5_la-store_emem.lo libkrb5_la-store_fd.lo \ + libkrb5_la-store_mem.lo libkrb5_la-plugin.lo \ + libkrb5_la-ticket.lo libkrb5_la-time.lo \ + libkrb5_la-transited.lo libkrb5_la-v4_glue.lo \ + libkrb5_la-verify_init.lo libkrb5_la-verify_user.lo \ + libkrb5_la-version.lo libkrb5_la-warn.lo \ + libkrb5_la-write_message.lo +am__objects_1 = libkrb5_la-krb5_err.lo libkrb5_la-krb_err.lo \ + libkrb5_la-heim_err.lo libkrb5_la-k524_err.lo +nodist_libkrb5_la_OBJECTS = $(am__objects_1) +libkrb5_la_OBJECTS = $(dist_libkrb5_la_OBJECTS) \ + $(nodist_libkrb5_la_OBJECTS) +libkrb5_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libkrb5_la_LDFLAGS) $(LDFLAGS) -o $@ +binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) +am__EXEEXT_1 = aes-test$(EXEEXT) derived-key-test$(EXEEXT) \ + n-fold-test$(EXEEXT) name-45-test$(EXEEXT) \ + parse-name-test$(EXEEXT) store-test$(EXEEXT) \ + string-to-key-test$(EXEEXT) test_acl$(EXEEXT) \ + test_addr$(EXEEXT) test_cc$(EXEEXT) test_config$(EXEEXT) \ + test_prf$(EXEEXT) test_store$(EXEEXT) \ + test_crypto_wrapping$(EXEEXT) test_keytab$(EXEEXT) \ + test_mem$(EXEEXT) test_pac$(EXEEXT) test_plugin$(EXEEXT) \ + test_princ$(EXEEXT) test_pkinit_dh2key$(EXEEXT) \ + test_time$(EXEEXT) +PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) +aes_test_SOURCES = aes-test.c +aes_test_OBJECTS = aes-test.$(OBJEXT) +aes_test_LDADD = $(LDADD) +aes_test_DEPENDENCIES = libkrb5.la $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/asn1/libasn1.la $(am__DEPENDENCIES_1) +derived_key_test_SOURCES = derived-key-test.c +derived_key_test_OBJECTS = derived-key-test.$(OBJEXT) +derived_key_test_LDADD = $(LDADD) +derived_key_test_DEPENDENCIES = libkrb5.la $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/asn1/libasn1.la $(am__DEPENDENCIES_1) +krbhst_test_SOURCES = krbhst-test.c +krbhst_test_OBJECTS = krbhst-test.$(OBJEXT) +krbhst_test_LDADD = $(LDADD) +krbhst_test_DEPENDENCIES = libkrb5.la $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/asn1/libasn1.la $(am__DEPENDENCIES_1) +n_fold_test_SOURCES = n-fold-test.c +n_fold_test_OBJECTS = n-fold-test.$(OBJEXT) +n_fold_test_LDADD = $(LDADD) +n_fold_test_DEPENDENCIES = libkrb5.la $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/asn1/libasn1.la $(am__DEPENDENCIES_1) +name_45_test_SOURCES = name-45-test.c +name_45_test_OBJECTS = name-45-test.$(OBJEXT) +name_45_test_LDADD = $(LDADD) +name_45_test_DEPENDENCIES = libkrb5.la $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/asn1/libasn1.la $(am__DEPENDENCIES_1) +parse_name_test_SOURCES = parse-name-test.c +parse_name_test_OBJECTS = parse-name-test.$(OBJEXT) +parse_name_test_LDADD = $(LDADD) +parse_name_test_DEPENDENCIES = libkrb5.la $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/asn1/libasn1.la $(am__DEPENDENCIES_1) +store_test_SOURCES = store-test.c +store_test_OBJECTS = store-test.$(OBJEXT) +store_test_LDADD = $(LDADD) +store_test_DEPENDENCIES = libkrb5.la $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/asn1/libasn1.la $(am__DEPENDENCIES_1) +string_to_key_test_SOURCES = string-to-key-test.c +string_to_key_test_OBJECTS = string-to-key-test.$(OBJEXT) +string_to_key_test_LDADD = $(LDADD) +string_to_key_test_DEPENDENCIES = libkrb5.la $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/asn1/libasn1.la $(am__DEPENDENCIES_1) +test_acl_SOURCES = test_acl.c +test_acl_OBJECTS = test_acl.$(OBJEXT) +test_acl_LDADD = $(LDADD) +test_acl_DEPENDENCIES = libkrb5.la $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/asn1/libasn1.la $(am__DEPENDENCIES_1) +test_addr_SOURCES = test_addr.c +test_addr_OBJECTS = test_addr.$(OBJEXT) +test_addr_LDADD = $(LDADD) +test_addr_DEPENDENCIES = libkrb5.la $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/asn1/libasn1.la $(am__DEPENDENCIES_1) +test_alname_SOURCES = test_alname.c +test_alname_OBJECTS = test_alname.$(OBJEXT) +test_alname_LDADD = $(LDADD) +test_alname_DEPENDENCIES = libkrb5.la $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/asn1/libasn1.la $(am__DEPENDENCIES_1) +test_cc_SOURCES = test_cc.c +test_cc_OBJECTS = test_cc.$(OBJEXT) +test_cc_LDADD = $(LDADD) +test_cc_DEPENDENCIES = libkrb5.la $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/asn1/libasn1.la $(am__DEPENDENCIES_1) +test_config_SOURCES = test_config.c +test_config_OBJECTS = test_config.$(OBJEXT) +test_config_LDADD = $(LDADD) +test_config_DEPENDENCIES = libkrb5.la $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/asn1/libasn1.la $(am__DEPENDENCIES_1) +test_crypto_SOURCES = test_crypto.c +test_crypto_OBJECTS = test_crypto.$(OBJEXT) +test_crypto_LDADD = $(LDADD) +test_crypto_DEPENDENCIES = libkrb5.la $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/asn1/libasn1.la $(am__DEPENDENCIES_1) +test_crypto_wrapping_SOURCES = test_crypto_wrapping.c +test_crypto_wrapping_OBJECTS = test_crypto_wrapping.$(OBJEXT) +test_crypto_wrapping_LDADD = $(LDADD) +test_crypto_wrapping_DEPENDENCIES = libkrb5.la $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/asn1/libasn1.la $(am__DEPENDENCIES_1) +test_forward_SOURCES = test_forward.c +test_forward_OBJECTS = test_forward.$(OBJEXT) +test_forward_LDADD = $(LDADD) +test_forward_DEPENDENCIES = libkrb5.la $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/asn1/libasn1.la $(am__DEPENDENCIES_1) +test_get_addrs_SOURCES = test_get_addrs.c +test_get_addrs_OBJECTS = test_get_addrs.$(OBJEXT) +test_get_addrs_LDADD = $(LDADD) +test_get_addrs_DEPENDENCIES = libkrb5.la $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/asn1/libasn1.la $(am__DEPENDENCIES_1) +test_hostname_SOURCES = test_hostname.c +test_hostname_OBJECTS = test_hostname.$(OBJEXT) +test_hostname_LDADD = $(LDADD) +test_hostname_DEPENDENCIES = libkrb5.la $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/asn1/libasn1.la $(am__DEPENDENCIES_1) +test_keytab_SOURCES = test_keytab.c +test_keytab_OBJECTS = test_keytab.$(OBJEXT) +test_keytab_LDADD = $(LDADD) +test_keytab_DEPENDENCIES = libkrb5.la $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/asn1/libasn1.la $(am__DEPENDENCIES_1) +test_kuserok_SOURCES = test_kuserok.c +test_kuserok_OBJECTS = test_kuserok.$(OBJEXT) +test_kuserok_LDADD = $(LDADD) +test_kuserok_DEPENDENCIES = libkrb5.la $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/asn1/libasn1.la $(am__DEPENDENCIES_1) +test_mem_SOURCES = test_mem.c +test_mem_OBJECTS = test_mem.$(OBJEXT) +test_mem_LDADD = $(LDADD) +test_mem_DEPENDENCIES = libkrb5.la $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/asn1/libasn1.la $(am__DEPENDENCIES_1) +test_pac_SOURCES = test_pac.c +test_pac_OBJECTS = test_pac.$(OBJEXT) +test_pac_LDADD = $(LDADD) +test_pac_DEPENDENCIES = libkrb5.la $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/asn1/libasn1.la $(am__DEPENDENCIES_1) +test_pkinit_dh2key_SOURCES = test_pkinit_dh2key.c +test_pkinit_dh2key_OBJECTS = test_pkinit_dh2key.$(OBJEXT) +test_pkinit_dh2key_LDADD = $(LDADD) +test_pkinit_dh2key_DEPENDENCIES = libkrb5.la $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/asn1/libasn1.la $(am__DEPENDENCIES_1) +test_plugin_SOURCES = test_plugin.c +test_plugin_OBJECTS = test_plugin.$(OBJEXT) +test_plugin_LDADD = $(LDADD) +test_plugin_DEPENDENCIES = libkrb5.la $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/asn1/libasn1.la $(am__DEPENDENCIES_1) +test_prf_SOURCES = test_prf.c +test_prf_OBJECTS = test_prf.$(OBJEXT) +test_prf_LDADD = $(LDADD) +test_prf_DEPENDENCIES = libkrb5.la $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/asn1/libasn1.la $(am__DEPENDENCIES_1) +test_princ_SOURCES = test_princ.c +test_princ_OBJECTS = test_princ.$(OBJEXT) +test_princ_LDADD = $(LDADD) +test_princ_DEPENDENCIES = libkrb5.la $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/asn1/libasn1.la $(am__DEPENDENCIES_1) +test_renew_SOURCES = test_renew.c +test_renew_OBJECTS = test_renew.$(OBJEXT) +test_renew_LDADD = $(LDADD) +test_renew_DEPENDENCIES = libkrb5.la $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/asn1/libasn1.la $(am__DEPENDENCIES_1) +test_store_SOURCES = test_store.c +test_store_OBJECTS = test_store.$(OBJEXT) +test_store_LDADD = $(LDADD) +test_store_DEPENDENCIES = libkrb5.la $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/asn1/libasn1.la $(am__DEPENDENCIES_1) +test_time_SOURCES = test_time.c +test_time_OBJECTS = test_time.$(OBJEXT) +test_time_LDADD = $(LDADD) +test_time_DEPENDENCIES = libkrb5.la $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/asn1/libasn1.la $(am__DEPENDENCIES_1) +verify_krb5_conf_SOURCES = verify_krb5_conf.c +verify_krb5_conf_OBJECTS = verify_krb5_conf.$(OBJEXT) +verify_krb5_conf_LDADD = $(LDADD) +verify_krb5_conf_DEPENDENCIES = libkrb5.la $(am__DEPENDENCIES_1) \ + $(top_builddir)/lib/asn1/libasn1.la $(am__DEPENDENCIES_1) +DEFAULT_INCLUDES = -I. -I$(top_builddir)/include@am__isrc@ +depcomp = +am__depfiles_maybe = +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) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(dist_libkrb5_la_SOURCES) $(nodist_libkrb5_la_SOURCES) \ + aes-test.c derived-key-test.c krbhst-test.c n-fold-test.c \ + name-45-test.c parse-name-test.c store-test.c \ + string-to-key-test.c test_acl.c test_addr.c test_alname.c \ + test_cc.c test_config.c test_crypto.c test_crypto_wrapping.c \ + test_forward.c test_get_addrs.c test_hostname.c test_keytab.c \ + test_kuserok.c test_mem.c test_pac.c test_pkinit_dh2key.c \ + test_plugin.c test_prf.c test_princ.c test_renew.c \ + test_store.c test_time.c verify_krb5_conf.c +DIST_SOURCES = $(dist_libkrb5_la_SOURCES) aes-test.c \ + derived-key-test.c krbhst-test.c n-fold-test.c name-45-test.c \ + parse-name-test.c store-test.c string-to-key-test.c test_acl.c \ + test_addr.c test_alname.c test_cc.c test_config.c \ + test_crypto.c test_crypto_wrapping.c test_forward.c \ + test_get_addrs.c test_hostname.c test_keytab.c test_kuserok.c \ + test_mem.c test_pac.c test_pkinit_dh2key.c test_plugin.c \ + test_prf.c test_princ.c test_renew.c test_store.c test_time.c \ + verify_krb5_conf.c +man3dir = $(mandir)/man3 +man5dir = $(mandir)/man5 +man8dir = $(mandir)/man8 +MANS = $(man_MANS) +dist_includeHEADERS_INSTALL = $(INSTALL_HEADER) +krb5HEADERS_INSTALL = $(INSTALL_HEADER) +nodist_includeHEADERS_INSTALL = $(INSTALL_HEADER) +HEADERS = $(dist_include_HEADERS) $(krb5_HEADERS) \ + $(nodist_include_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AIX_EXTRA_KAFS = @AIX_EXTRA_KAFS@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CANONICAL_HOST = @CANONICAL_HOST@ +CATMAN = @CATMAN@ +CATMANEXT = @CATMANEXT@ +CC = @CC@ +CFLAGS = @CFLAGS@ +COMPILE_ET = @COMPILE_ET@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DBLIB = @DBLIB@ +DEFS = @DEFS@ +DIR_com_err = @DIR_com_err@ +DIR_hcrypto = @DIR_hcrypto@ +DIR_hdbdir = @DIR_hdbdir@ +DIR_roken = @DIR_roken@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GREP = @GREP@ +GROFF = @GROFF@ +INCLUDES_roken = @INCLUDES_roken@ +INCLUDE_hcrypto = @INCLUDE_hcrypto@ +INCLUDE_hesiod = @INCLUDE_hesiod@ +INCLUDE_krb4 = @INCLUDE_krb4@ +INCLUDE_openldap = @INCLUDE_openldap@ +INCLUDE_readline = @INCLUDE_readline@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LDFLAGS_VERSION_SCRIPT = @LDFLAGS_VERSION_SCRIPT@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_roken = @LIBADD_roken@ +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_com_err = @LIB_com_err@ +LIB_com_err_a = @LIB_com_err_a@ +LIB_com_err_so = @LIB_com_err_so@ +LIB_crypt = @LIB_crypt@ +LIB_db_create = @LIB_db_create@ +LIB_dbm_firstkey = @LIB_dbm_firstkey@ +LIB_dbopen = @LIB_dbopen@ +LIB_dlopen = @LIB_dlopen@ +LIB_dn_expand = @LIB_dn_expand@ +LIB_door_create = @LIB_door_create@ +LIB_el_init = @LIB_el_init@ +LIB_freeaddrinfo = @LIB_freeaddrinfo@ +LIB_gai_strerror = @LIB_gai_strerror@ +LIB_getaddrinfo = @LIB_getaddrinfo@ +LIB_gethostbyname = @LIB_gethostbyname@ +LIB_gethostbyname2 = @LIB_gethostbyname2@ +LIB_getnameinfo = @LIB_getnameinfo@ +LIB_getpwnam_r = @LIB_getpwnam_r@ +LIB_getsockopt = @LIB_getsockopt@ +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_loadquery = @LIB_loadquery@ +LIB_logout = @LIB_logout@ +LIB_logwtmp = @LIB_logwtmp@ +LIB_openldap = @LIB_openldap@ +LIB_openpty = @LIB_openpty@ +LIB_otp = @LIB_otp@ +LIB_pidfile = @LIB_pidfile@ +LIB_readline = @LIB_readline@ +LIB_res_ndestroy = @LIB_res_ndestroy@ +LIB_res_nsearch = @LIB_res_nsearch@ +LIB_res_search = @LIB_res_search@ +LIB_roken = @LIB_roken@ +LIB_security = @LIB_security@ +LIB_setsockopt = @LIB_setsockopt@ +LIB_socket = @LIB_socket@ +LIB_syslog = @LIB_syslog@ +LIB_tgetent = @LIB_tgetent@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NROFF = @NROFF@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PTHREADS_CFLAGS = @PTHREADS_CFLAGS@ +PTHREADS_LIBS = @PTHREADS_LIBS@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +VERSIONING = @VERSIONING@ +VOID_RETSIGTYPE = @VOID_RETSIGTYPE@ +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@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__leading_dot = @am__leading_dot@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dpagaix_cflags = @dpagaix_cflags@ +dpagaix_ldadd = @dpagaix_ldadd@ +dpagaix_ldflags = @dpagaix_ldflags@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUFFIXES = .et .h .x .z .1 .3 .5 .8 .cat1 .cat3 .cat5 .cat8 +AM_CPPFLAGS = -I$(top_builddir)/include $(INCLUDES_roken) \ + $(INCLUDE_krb4) $(INCLUDE_hcrypto) -I../com_err \ + -I$(srcdir)/../com_err +@do_roken_rename_TRUE@ROKEN_RENAME = -DROKEN_RENAME +AM_CFLAGS = $(WFLAGS) +CP = cp +buildinclude = $(top_builddir)/include +LIB_getattr = @LIB_getattr@ +LIB_getpwent_r = @LIB_getpwent_r@ +LIB_odm_initialize = @LIB_odm_initialize@ +LIB_setpcred = @LIB_setpcred@ +HESIODLIB = @HESIODLIB@ +HESIODINCLUDE = @HESIODINCLUDE@ +NROFF_MAN = groff -mandoc -Tascii +LIB_kafs = $(top_builddir)/lib/kafs/libkafs.la $(AIX_EXTRA_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 +@KRB5_TRUE@LIB_tsasl = $(top_builddir)/lib/tsasl/libtsasl.la +@DCE_TRUE@LIB_kdfs = $(top_builddir)/lib/kdfs/libkdfs.la +LDADD = libkrb5.la \ + $(LIB_hcrypto) \ + $(top_builddir)/lib/asn1/libasn1.la \ + $(LIB_roken) + +@PKINIT_TRUE@LIB_pkinit = ../hx509/libhx509.la +libkrb5_la_LIBADD = \ + $(LIB_pkinit) \ + $(LIB_com_err) \ + $(LIB_hcrypto) \ + $(top_builddir)/lib/asn1/libasn1.la \ + $(LIBADD_roken) \ + $(LIB_door_create) \ + $(LIB_dlopen) + +lib_LTLIBRARIES = libkrb5.la +ERR_FILES = krb5_err.c krb_err.c heim_err.c k524_err.c +libkrb5_la_CPPFLAGS = -DBUILD_KRB5_LIB $(AM_CPPFLAGS) +dist_libkrb5_la_SOURCES = \ + acache.c \ + acl.c \ + add_et_list.c \ + addr_families.c \ + aname_to_localname.c \ + appdefault.c \ + asn1_glue.c \ + auth_context.c \ + build_ap_req.c \ + build_auth.c \ + cache.c \ + changepw.c \ + codec.c \ + config_file.c \ + config_file_netinfo.c \ + convert_creds.c \ + constants.c \ + context.c \ + copy_host_realm.c \ + crc.c \ + creds.c \ + crypto.c \ + doxygen.c \ + data.c \ + digest.c \ + eai_to_heim_errno.c \ + error_string.c \ + expand_hostname.c \ + fcache.c \ + free.c \ + free_host_realm.c \ + generate_seq_number.c \ + generate_subkey.c \ + get_addrs.c \ + get_cred.c \ + get_default_principal.c \ + get_default_realm.c \ + get_for_creds.c \ + get_host_realm.c \ + get_in_tkt.c \ + get_in_tkt_pw.c \ + get_in_tkt_with_keytab.c \ + get_in_tkt_with_skey.c \ + get_port.c \ + heim_threads.h \ + init_creds.c \ + init_creds_pw.c \ + kcm.c \ + kcm.h \ + keyblock.c \ + keytab.c \ + keytab_any.c \ + keytab_file.c \ + keytab_keyfile.c \ + keytab_krb4.c \ + keytab_memory.c \ + krb5_locl.h \ + krb5-v4compat.h \ + krbhst.c \ + kuserok.c \ + log.c \ + mcache.c \ + misc.c \ + mk_error.c \ + mk_priv.c \ + mk_rep.c \ + mk_req.c \ + mk_req_ext.c \ + mk_safe.c \ + mit_glue.c \ + net_read.c \ + net_write.c \ + n-fold.c \ + pac.c \ + padata.c \ + pkinit.c \ + principal.c \ + prog_setup.c \ + prompter_posix.c \ + rd_cred.c \ + rd_error.c \ + rd_priv.c \ + rd_rep.c \ + rd_req.c \ + rd_safe.c \ + read_message.c \ + recvauth.c \ + replay.c \ + send_to_kdc.c \ + sendauth.c \ + set_default_realm.c \ + sock_principal.c \ + store.c \ + store-int.h \ + store_emem.c \ + store_fd.c \ + store_mem.c \ + plugin.c \ + ticket.c \ + time.c \ + transited.c \ + v4_glue.c \ + verify_init.c \ + verify_user.c \ + version.c \ + warn.c \ + write_message.c + +nodist_libkrb5_la_SOURCES = \ + $(ERR_FILES) + +libkrb5_la_LDFLAGS = -version-info 24:0:0 $(am__append_1) +man_MANS = \ + kerberos.8 \ + krb5.3 \ + krb5.conf.5 \ + krb524_convert_creds_kdc.3 \ + krb5_425_conv_principal.3 \ + krb5_acl_match_file.3 \ + krb5_address.3 \ + krb5_aname_to_localname.3 \ + krb5_appdefault.3 \ + krb5_auth_context.3 \ + krb5_c_make_checksum.3 \ + krb5_ccache.3 \ + krb5_check_transited.3 \ + krb5_compare_creds.3 \ + krb5_config.3 \ + krb5_context.3 \ + krb5_create_checksum.3 \ + krb5_creds.3 \ + krb5_crypto_init.3 \ + krb5_data.3 \ + krb5_digest.3 \ + krb5_eai_to_heim_errno.3 \ + krb5_encrypt.3 \ + krb5_expand_hostname.3 \ + krb5_find_padata.3 \ + krb5_generate_random_block.3 \ + krb5_get_all_client_addrs.3 \ + krb5_get_credentials.3 \ + krb5_get_creds.3 \ + krb5_get_forwarded_creds.3 \ + krb5_get_in_cred.3 \ + krb5_get_init_creds.3 \ + krb5_get_krbhst.3 \ + krb5_getportbyname.3 \ + krb5_init_context.3 \ + krb5_is_thread_safe.3 \ + krb5_keyblock.3 \ + krb5_keytab.3 \ + krb5_krbhst_init.3 \ + krb5_kuserok.3 \ + krb5_mk_req.3 \ + krb5_mk_safe.3 \ + krb5_openlog.3 \ + krb5_parse_name.3 \ + krb5_principal.3 \ + krb5_rcache.3 \ + krb5_rd_error.3 \ + krb5_rd_safe.3 \ + krb5_set_default_realm.3 \ + krb5_set_password.3 \ + krb5_storage.3 \ + krb5_string_to_key.3 \ + krb5_ticket.3 \ + krb5_timeofday.3 \ + krb5_unparse_name.3 \ + krb5_verify_init_creds.3 \ + krb5_verify_user.3 \ + krb5_warn.3 \ + verify_krb5_conf.8 + +dist_include_HEADERS = \ + krb5.h \ + krb5-protos.h \ + krb5-private.h \ + krb5_ccapi.h + +nodist_include_HEADERS = krb5_err.h heim_err.h k524_err.h + +# XXX use nobase_include_HEADERS = krb5/locate_plugin.h +krb5dir = $(includedir)/krb5 +krb5_HEADERS = locate_plugin.h +build_HEADERZ = \ + heim_threads.h \ + $(krb5_HEADERS) \ + krb_err.h + +CLEANFILES = \ + krb5_err.c krb5_err.h \ + krb_err.c krb_err.h \ + heim_err.c heim_err.h \ + k524_err.c k524_err.h + +EXTRA_DIST = \ + krb5_err.et \ + krb_err.et \ + heim_err.et \ + k524_err.et \ + $(man_MANS) \ + version-script.map \ + krb5.moduli + +all: all-am + +.SUFFIXES: +.SUFFIXES: .et .h .x .z .1 .3 .5 .8 .cat1 .cat3 .cat5 .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 \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign --ignore-deps lib/krb5/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign --ignore-deps lib/krb5/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + f=$(am__strip_dir) \ + echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \ + else :; fi; \ + done + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + p=$(am__strip_dir) \ + echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \ + $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \ + done + +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 +libkrb5.la: $(libkrb5_la_OBJECTS) $(libkrb5_la_DEPENDENCIES) + $(libkrb5_la_LINK) -rpath $(libdir) $(libkrb5_la_OBJECTS) $(libkrb5_la_LIBADD) $(LIBS) +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + if test -f $$p \ + || test -f $$p1 \ + ; then \ + f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \ + else :; fi; \ + done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ + rm -f "$(DESTDIR)$(bindir)/$$f"; \ + done + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f $$p $$f"; \ + rm -f $$p $$f ; \ + done + +clean-checkPROGRAMS: + @list='$(check_PROGRAMS)'; for p in $$list; do \ + f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f $$p $$f"; \ + rm -f $$p $$f ; \ + done + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; for p in $$list; do \ + f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f $$p $$f"; \ + rm -f $$p $$f ; \ + done +aes-test$(EXEEXT): $(aes_test_OBJECTS) $(aes_test_DEPENDENCIES) + @rm -f aes-test$(EXEEXT) + $(LINK) $(aes_test_OBJECTS) $(aes_test_LDADD) $(LIBS) +derived-key-test$(EXEEXT): $(derived_key_test_OBJECTS) $(derived_key_test_DEPENDENCIES) + @rm -f derived-key-test$(EXEEXT) + $(LINK) $(derived_key_test_OBJECTS) $(derived_key_test_LDADD) $(LIBS) +krbhst-test$(EXEEXT): $(krbhst_test_OBJECTS) $(krbhst_test_DEPENDENCIES) + @rm -f krbhst-test$(EXEEXT) + $(LINK) $(krbhst_test_OBJECTS) $(krbhst_test_LDADD) $(LIBS) +n-fold-test$(EXEEXT): $(n_fold_test_OBJECTS) $(n_fold_test_DEPENDENCIES) + @rm -f n-fold-test$(EXEEXT) + $(LINK) $(n_fold_test_OBJECTS) $(n_fold_test_LDADD) $(LIBS) +name-45-test$(EXEEXT): $(name_45_test_OBJECTS) $(name_45_test_DEPENDENCIES) + @rm -f name-45-test$(EXEEXT) + $(LINK) $(name_45_test_OBJECTS) $(name_45_test_LDADD) $(LIBS) +parse-name-test$(EXEEXT): $(parse_name_test_OBJECTS) $(parse_name_test_DEPENDENCIES) + @rm -f parse-name-test$(EXEEXT) + $(LINK) $(parse_name_test_OBJECTS) $(parse_name_test_LDADD) $(LIBS) +store-test$(EXEEXT): $(store_test_OBJECTS) $(store_test_DEPENDENCIES) + @rm -f store-test$(EXEEXT) + $(LINK) $(store_test_OBJECTS) $(store_test_LDADD) $(LIBS) +string-to-key-test$(EXEEXT): $(string_to_key_test_OBJECTS) $(string_to_key_test_DEPENDENCIES) + @rm -f string-to-key-test$(EXEEXT) + $(LINK) $(string_to_key_test_OBJECTS) $(string_to_key_test_LDADD) $(LIBS) +test_acl$(EXEEXT): $(test_acl_OBJECTS) $(test_acl_DEPENDENCIES) + @rm -f test_acl$(EXEEXT) + $(LINK) $(test_acl_OBJECTS) $(test_acl_LDADD) $(LIBS) +test_addr$(EXEEXT): $(test_addr_OBJECTS) $(test_addr_DEPENDENCIES) + @rm -f test_addr$(EXEEXT) + $(LINK) $(test_addr_OBJECTS) $(test_addr_LDADD) $(LIBS) +test_alname$(EXEEXT): $(test_alname_OBJECTS) $(test_alname_DEPENDENCIES) + @rm -f test_alname$(EXEEXT) + $(LINK) $(test_alname_OBJECTS) $(test_alname_LDADD) $(LIBS) +test_cc$(EXEEXT): $(test_cc_OBJECTS) $(test_cc_DEPENDENCIES) + @rm -f test_cc$(EXEEXT) + $(LINK) $(test_cc_OBJECTS) $(test_cc_LDADD) $(LIBS) +test_config$(EXEEXT): $(test_config_OBJECTS) $(test_config_DEPENDENCIES) + @rm -f test_config$(EXEEXT) + $(LINK) $(test_config_OBJECTS) $(test_config_LDADD) $(LIBS) +test_crypto$(EXEEXT): $(test_crypto_OBJECTS) $(test_crypto_DEPENDENCIES) + @rm -f test_crypto$(EXEEXT) + $(LINK) $(test_crypto_OBJECTS) $(test_crypto_LDADD) $(LIBS) +test_crypto_wrapping$(EXEEXT): $(test_crypto_wrapping_OBJECTS) $(test_crypto_wrapping_DEPENDENCIES) + @rm -f test_crypto_wrapping$(EXEEXT) + $(LINK) $(test_crypto_wrapping_OBJECTS) $(test_crypto_wrapping_LDADD) $(LIBS) +test_forward$(EXEEXT): $(test_forward_OBJECTS) $(test_forward_DEPENDENCIES) + @rm -f test_forward$(EXEEXT) + $(LINK) $(test_forward_OBJECTS) $(test_forward_LDADD) $(LIBS) +test_get_addrs$(EXEEXT): $(test_get_addrs_OBJECTS) $(test_get_addrs_DEPENDENCIES) + @rm -f test_get_addrs$(EXEEXT) + $(LINK) $(test_get_addrs_OBJECTS) $(test_get_addrs_LDADD) $(LIBS) +test_hostname$(EXEEXT): $(test_hostname_OBJECTS) $(test_hostname_DEPENDENCIES) + @rm -f test_hostname$(EXEEXT) + $(LINK) $(test_hostname_OBJECTS) $(test_hostname_LDADD) $(LIBS) +test_keytab$(EXEEXT): $(test_keytab_OBJECTS) $(test_keytab_DEPENDENCIES) + @rm -f test_keytab$(EXEEXT) + $(LINK) $(test_keytab_OBJECTS) $(test_keytab_LDADD) $(LIBS) +test_kuserok$(EXEEXT): $(test_kuserok_OBJECTS) $(test_kuserok_DEPENDENCIES) + @rm -f test_kuserok$(EXEEXT) + $(LINK) $(test_kuserok_OBJECTS) $(test_kuserok_LDADD) $(LIBS) +test_mem$(EXEEXT): $(test_mem_OBJECTS) $(test_mem_DEPENDENCIES) + @rm -f test_mem$(EXEEXT) + $(LINK) $(test_mem_OBJECTS) $(test_mem_LDADD) $(LIBS) +test_pac$(EXEEXT): $(test_pac_OBJECTS) $(test_pac_DEPENDENCIES) + @rm -f test_pac$(EXEEXT) + $(LINK) $(test_pac_OBJECTS) $(test_pac_LDADD) $(LIBS) +test_pkinit_dh2key$(EXEEXT): $(test_pkinit_dh2key_OBJECTS) $(test_pkinit_dh2key_DEPENDENCIES) + @rm -f test_pkinit_dh2key$(EXEEXT) + $(LINK) $(test_pkinit_dh2key_OBJECTS) $(test_pkinit_dh2key_LDADD) $(LIBS) +test_plugin$(EXEEXT): $(test_plugin_OBJECTS) $(test_plugin_DEPENDENCIES) + @rm -f test_plugin$(EXEEXT) + $(LINK) $(test_plugin_OBJECTS) $(test_plugin_LDADD) $(LIBS) +test_prf$(EXEEXT): $(test_prf_OBJECTS) $(test_prf_DEPENDENCIES) + @rm -f test_prf$(EXEEXT) + $(LINK) $(test_prf_OBJECTS) $(test_prf_LDADD) $(LIBS) +test_princ$(EXEEXT): $(test_princ_OBJECTS) $(test_princ_DEPENDENCIES) + @rm -f test_princ$(EXEEXT) + $(LINK) $(test_princ_OBJECTS) $(test_princ_LDADD) $(LIBS) +test_renew$(EXEEXT): $(test_renew_OBJECTS) $(test_renew_DEPENDENCIES) + @rm -f test_renew$(EXEEXT) + $(LINK) $(test_renew_OBJECTS) $(test_renew_LDADD) $(LIBS) +test_store$(EXEEXT): $(test_store_OBJECTS) $(test_store_DEPENDENCIES) + @rm -f test_store$(EXEEXT) + $(LINK) $(test_store_OBJECTS) $(test_store_LDADD) $(LIBS) +test_time$(EXEEXT): $(test_time_OBJECTS) $(test_time_DEPENDENCIES) + @rm -f test_time$(EXEEXT) + $(LINK) $(test_time_OBJECTS) $(test_time_LDADD) $(LIBS) +verify_krb5_conf$(EXEEXT): $(verify_krb5_conf_OBJECTS) $(verify_krb5_conf_DEPENDENCIES) + @rm -f verify_krb5_conf$(EXEEXT) + $(LINK) $(verify_krb5_conf_OBJECTS) $(verify_krb5_conf_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.c.o: + $(COMPILE) -c $< + +.c.obj: + $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: + $(LTCOMPILE) -c -o $@ $< + +libkrb5_la-acache.lo: acache.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-acache.lo `test -f 'acache.c' || echo '$(srcdir)/'`acache.c + +libkrb5_la-acl.lo: acl.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-acl.lo `test -f 'acl.c' || echo '$(srcdir)/'`acl.c + +libkrb5_la-add_et_list.lo: add_et_list.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-add_et_list.lo `test -f 'add_et_list.c' || echo '$(srcdir)/'`add_et_list.c + +libkrb5_la-addr_families.lo: addr_families.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-addr_families.lo `test -f 'addr_families.c' || echo '$(srcdir)/'`addr_families.c + +libkrb5_la-aname_to_localname.lo: aname_to_localname.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-aname_to_localname.lo `test -f 'aname_to_localname.c' || echo '$(srcdir)/'`aname_to_localname.c + +libkrb5_la-appdefault.lo: appdefault.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-appdefault.lo `test -f 'appdefault.c' || echo '$(srcdir)/'`appdefault.c + +libkrb5_la-asn1_glue.lo: asn1_glue.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-asn1_glue.lo `test -f 'asn1_glue.c' || echo '$(srcdir)/'`asn1_glue.c + +libkrb5_la-auth_context.lo: auth_context.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-auth_context.lo `test -f 'auth_context.c' || echo '$(srcdir)/'`auth_context.c + +libkrb5_la-build_ap_req.lo: build_ap_req.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-build_ap_req.lo `test -f 'build_ap_req.c' || echo '$(srcdir)/'`build_ap_req.c + +libkrb5_la-build_auth.lo: build_auth.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-build_auth.lo `test -f 'build_auth.c' || echo '$(srcdir)/'`build_auth.c + +libkrb5_la-cache.lo: cache.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-cache.lo `test -f 'cache.c' || echo '$(srcdir)/'`cache.c + +libkrb5_la-changepw.lo: changepw.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-changepw.lo `test -f 'changepw.c' || echo '$(srcdir)/'`changepw.c + +libkrb5_la-codec.lo: codec.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-codec.lo `test -f 'codec.c' || echo '$(srcdir)/'`codec.c + +libkrb5_la-config_file.lo: config_file.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-config_file.lo `test -f 'config_file.c' || echo '$(srcdir)/'`config_file.c + +libkrb5_la-config_file_netinfo.lo: config_file_netinfo.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-config_file_netinfo.lo `test -f 'config_file_netinfo.c' || echo '$(srcdir)/'`config_file_netinfo.c + +libkrb5_la-convert_creds.lo: convert_creds.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-convert_creds.lo `test -f 'convert_creds.c' || echo '$(srcdir)/'`convert_creds.c + +libkrb5_la-constants.lo: constants.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-constants.lo `test -f 'constants.c' || echo '$(srcdir)/'`constants.c + +libkrb5_la-context.lo: context.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-context.lo `test -f 'context.c' || echo '$(srcdir)/'`context.c + +libkrb5_la-copy_host_realm.lo: copy_host_realm.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-copy_host_realm.lo `test -f 'copy_host_realm.c' || echo '$(srcdir)/'`copy_host_realm.c + +libkrb5_la-crc.lo: crc.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-crc.lo `test -f 'crc.c' || echo '$(srcdir)/'`crc.c + +libkrb5_la-creds.lo: creds.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-creds.lo `test -f 'creds.c' || echo '$(srcdir)/'`creds.c + +libkrb5_la-crypto.lo: crypto.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-crypto.lo `test -f 'crypto.c' || echo '$(srcdir)/'`crypto.c + +libkrb5_la-doxygen.lo: doxygen.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-doxygen.lo `test -f 'doxygen.c' || echo '$(srcdir)/'`doxygen.c + +libkrb5_la-data.lo: data.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-data.lo `test -f 'data.c' || echo '$(srcdir)/'`data.c + +libkrb5_la-digest.lo: digest.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-digest.lo `test -f 'digest.c' || echo '$(srcdir)/'`digest.c + +libkrb5_la-eai_to_heim_errno.lo: eai_to_heim_errno.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-eai_to_heim_errno.lo `test -f 'eai_to_heim_errno.c' || echo '$(srcdir)/'`eai_to_heim_errno.c + +libkrb5_la-error_string.lo: error_string.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-error_string.lo `test -f 'error_string.c' || echo '$(srcdir)/'`error_string.c + +libkrb5_la-expand_hostname.lo: expand_hostname.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-expand_hostname.lo `test -f 'expand_hostname.c' || echo '$(srcdir)/'`expand_hostname.c + +libkrb5_la-fcache.lo: fcache.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-fcache.lo `test -f 'fcache.c' || echo '$(srcdir)/'`fcache.c + +libkrb5_la-free.lo: free.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-free.lo `test -f 'free.c' || echo '$(srcdir)/'`free.c + +libkrb5_la-free_host_realm.lo: free_host_realm.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-free_host_realm.lo `test -f 'free_host_realm.c' || echo '$(srcdir)/'`free_host_realm.c + +libkrb5_la-generate_seq_number.lo: generate_seq_number.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-generate_seq_number.lo `test -f 'generate_seq_number.c' || echo '$(srcdir)/'`generate_seq_number.c + +libkrb5_la-generate_subkey.lo: generate_subkey.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-generate_subkey.lo `test -f 'generate_subkey.c' || echo '$(srcdir)/'`generate_subkey.c + +libkrb5_la-get_addrs.lo: get_addrs.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-get_addrs.lo `test -f 'get_addrs.c' || echo '$(srcdir)/'`get_addrs.c + +libkrb5_la-get_cred.lo: get_cred.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-get_cred.lo `test -f 'get_cred.c' || echo '$(srcdir)/'`get_cred.c + +libkrb5_la-get_default_principal.lo: get_default_principal.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-get_default_principal.lo `test -f 'get_default_principal.c' || echo '$(srcdir)/'`get_default_principal.c + +libkrb5_la-get_default_realm.lo: get_default_realm.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-get_default_realm.lo `test -f 'get_default_realm.c' || echo '$(srcdir)/'`get_default_realm.c + +libkrb5_la-get_for_creds.lo: get_for_creds.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-get_for_creds.lo `test -f 'get_for_creds.c' || echo '$(srcdir)/'`get_for_creds.c + +libkrb5_la-get_host_realm.lo: get_host_realm.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-get_host_realm.lo `test -f 'get_host_realm.c' || echo '$(srcdir)/'`get_host_realm.c + +libkrb5_la-get_in_tkt.lo: get_in_tkt.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-get_in_tkt.lo `test -f 'get_in_tkt.c' || echo '$(srcdir)/'`get_in_tkt.c + +libkrb5_la-get_in_tkt_pw.lo: get_in_tkt_pw.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-get_in_tkt_pw.lo `test -f 'get_in_tkt_pw.c' || echo '$(srcdir)/'`get_in_tkt_pw.c + +libkrb5_la-get_in_tkt_with_keytab.lo: get_in_tkt_with_keytab.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-get_in_tkt_with_keytab.lo `test -f 'get_in_tkt_with_keytab.c' || echo '$(srcdir)/'`get_in_tkt_with_keytab.c + +libkrb5_la-get_in_tkt_with_skey.lo: get_in_tkt_with_skey.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-get_in_tkt_with_skey.lo `test -f 'get_in_tkt_with_skey.c' || echo '$(srcdir)/'`get_in_tkt_with_skey.c + +libkrb5_la-get_port.lo: get_port.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-get_port.lo `test -f 'get_port.c' || echo '$(srcdir)/'`get_port.c + +libkrb5_la-init_creds.lo: init_creds.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-init_creds.lo `test -f 'init_creds.c' || echo '$(srcdir)/'`init_creds.c + +libkrb5_la-init_creds_pw.lo: init_creds_pw.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-init_creds_pw.lo `test -f 'init_creds_pw.c' || echo '$(srcdir)/'`init_creds_pw.c + +libkrb5_la-kcm.lo: kcm.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-kcm.lo `test -f 'kcm.c' || echo '$(srcdir)/'`kcm.c + +libkrb5_la-keyblock.lo: keyblock.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-keyblock.lo `test -f 'keyblock.c' || echo '$(srcdir)/'`keyblock.c + +libkrb5_la-keytab.lo: keytab.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-keytab.lo `test -f 'keytab.c' || echo '$(srcdir)/'`keytab.c + +libkrb5_la-keytab_any.lo: keytab_any.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-keytab_any.lo `test -f 'keytab_any.c' || echo '$(srcdir)/'`keytab_any.c + +libkrb5_la-keytab_file.lo: keytab_file.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-keytab_file.lo `test -f 'keytab_file.c' || echo '$(srcdir)/'`keytab_file.c + +libkrb5_la-keytab_keyfile.lo: keytab_keyfile.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-keytab_keyfile.lo `test -f 'keytab_keyfile.c' || echo '$(srcdir)/'`keytab_keyfile.c + +libkrb5_la-keytab_krb4.lo: keytab_krb4.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-keytab_krb4.lo `test -f 'keytab_krb4.c' || echo '$(srcdir)/'`keytab_krb4.c + +libkrb5_la-keytab_memory.lo: keytab_memory.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-keytab_memory.lo `test -f 'keytab_memory.c' || echo '$(srcdir)/'`keytab_memory.c + +libkrb5_la-krbhst.lo: krbhst.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-krbhst.lo `test -f 'krbhst.c' || echo '$(srcdir)/'`krbhst.c + +libkrb5_la-kuserok.lo: kuserok.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-kuserok.lo `test -f 'kuserok.c' || echo '$(srcdir)/'`kuserok.c + +libkrb5_la-log.lo: log.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-log.lo `test -f 'log.c' || echo '$(srcdir)/'`log.c + +libkrb5_la-mcache.lo: mcache.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-mcache.lo `test -f 'mcache.c' || echo '$(srcdir)/'`mcache.c + +libkrb5_la-misc.lo: misc.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-misc.lo `test -f 'misc.c' || echo '$(srcdir)/'`misc.c + +libkrb5_la-mk_error.lo: mk_error.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-mk_error.lo `test -f 'mk_error.c' || echo '$(srcdir)/'`mk_error.c + +libkrb5_la-mk_priv.lo: mk_priv.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-mk_priv.lo `test -f 'mk_priv.c' || echo '$(srcdir)/'`mk_priv.c + +libkrb5_la-mk_rep.lo: mk_rep.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-mk_rep.lo `test -f 'mk_rep.c' || echo '$(srcdir)/'`mk_rep.c + +libkrb5_la-mk_req.lo: mk_req.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-mk_req.lo `test -f 'mk_req.c' || echo '$(srcdir)/'`mk_req.c + +libkrb5_la-mk_req_ext.lo: mk_req_ext.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-mk_req_ext.lo `test -f 'mk_req_ext.c' || echo '$(srcdir)/'`mk_req_ext.c + +libkrb5_la-mk_safe.lo: mk_safe.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-mk_safe.lo `test -f 'mk_safe.c' || echo '$(srcdir)/'`mk_safe.c + +libkrb5_la-mit_glue.lo: mit_glue.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-mit_glue.lo `test -f 'mit_glue.c' || echo '$(srcdir)/'`mit_glue.c + +libkrb5_la-net_read.lo: net_read.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-net_read.lo `test -f 'net_read.c' || echo '$(srcdir)/'`net_read.c + +libkrb5_la-net_write.lo: net_write.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-net_write.lo `test -f 'net_write.c' || echo '$(srcdir)/'`net_write.c + +libkrb5_la-n-fold.lo: n-fold.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-n-fold.lo `test -f 'n-fold.c' || echo '$(srcdir)/'`n-fold.c + +libkrb5_la-pac.lo: pac.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-pac.lo `test -f 'pac.c' || echo '$(srcdir)/'`pac.c + +libkrb5_la-padata.lo: padata.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-padata.lo `test -f 'padata.c' || echo '$(srcdir)/'`padata.c + +libkrb5_la-pkinit.lo: pkinit.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-pkinit.lo `test -f 'pkinit.c' || echo '$(srcdir)/'`pkinit.c + +libkrb5_la-principal.lo: principal.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-principal.lo `test -f 'principal.c' || echo '$(srcdir)/'`principal.c + +libkrb5_la-prog_setup.lo: prog_setup.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-prog_setup.lo `test -f 'prog_setup.c' || echo '$(srcdir)/'`prog_setup.c + +libkrb5_la-prompter_posix.lo: prompter_posix.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-prompter_posix.lo `test -f 'prompter_posix.c' || echo '$(srcdir)/'`prompter_posix.c + +libkrb5_la-rd_cred.lo: rd_cred.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-rd_cred.lo `test -f 'rd_cred.c' || echo '$(srcdir)/'`rd_cred.c + +libkrb5_la-rd_error.lo: rd_error.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-rd_error.lo `test -f 'rd_error.c' || echo '$(srcdir)/'`rd_error.c + +libkrb5_la-rd_priv.lo: rd_priv.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-rd_priv.lo `test -f 'rd_priv.c' || echo '$(srcdir)/'`rd_priv.c + +libkrb5_la-rd_rep.lo: rd_rep.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-rd_rep.lo `test -f 'rd_rep.c' || echo '$(srcdir)/'`rd_rep.c + +libkrb5_la-rd_req.lo: rd_req.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-rd_req.lo `test -f 'rd_req.c' || echo '$(srcdir)/'`rd_req.c + +libkrb5_la-rd_safe.lo: rd_safe.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-rd_safe.lo `test -f 'rd_safe.c' || echo '$(srcdir)/'`rd_safe.c + +libkrb5_la-read_message.lo: read_message.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-read_message.lo `test -f 'read_message.c' || echo '$(srcdir)/'`read_message.c + +libkrb5_la-recvauth.lo: recvauth.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-recvauth.lo `test -f 'recvauth.c' || echo '$(srcdir)/'`recvauth.c + +libkrb5_la-replay.lo: replay.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-replay.lo `test -f 'replay.c' || echo '$(srcdir)/'`replay.c + +libkrb5_la-send_to_kdc.lo: send_to_kdc.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-send_to_kdc.lo `test -f 'send_to_kdc.c' || echo '$(srcdir)/'`send_to_kdc.c + +libkrb5_la-sendauth.lo: sendauth.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-sendauth.lo `test -f 'sendauth.c' || echo '$(srcdir)/'`sendauth.c + +libkrb5_la-set_default_realm.lo: set_default_realm.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-set_default_realm.lo `test -f 'set_default_realm.c' || echo '$(srcdir)/'`set_default_realm.c + +libkrb5_la-sock_principal.lo: sock_principal.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-sock_principal.lo `test -f 'sock_principal.c' || echo '$(srcdir)/'`sock_principal.c + +libkrb5_la-store.lo: store.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-store.lo `test -f 'store.c' || echo '$(srcdir)/'`store.c + +libkrb5_la-store_emem.lo: store_emem.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-store_emem.lo `test -f 'store_emem.c' || echo '$(srcdir)/'`store_emem.c + +libkrb5_la-store_fd.lo: store_fd.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-store_fd.lo `test -f 'store_fd.c' || echo '$(srcdir)/'`store_fd.c + +libkrb5_la-store_mem.lo: store_mem.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-store_mem.lo `test -f 'store_mem.c' || echo '$(srcdir)/'`store_mem.c + +libkrb5_la-plugin.lo: plugin.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-plugin.lo `test -f 'plugin.c' || echo '$(srcdir)/'`plugin.c + +libkrb5_la-ticket.lo: ticket.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-ticket.lo `test -f 'ticket.c' || echo '$(srcdir)/'`ticket.c + +libkrb5_la-time.lo: time.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-time.lo `test -f 'time.c' || echo '$(srcdir)/'`time.c + +libkrb5_la-transited.lo: transited.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-transited.lo `test -f 'transited.c' || echo '$(srcdir)/'`transited.c + +libkrb5_la-v4_glue.lo: v4_glue.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-v4_glue.lo `test -f 'v4_glue.c' || echo '$(srcdir)/'`v4_glue.c + +libkrb5_la-verify_init.lo: verify_init.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-verify_init.lo `test -f 'verify_init.c' || echo '$(srcdir)/'`verify_init.c + +libkrb5_la-verify_user.lo: verify_user.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-verify_user.lo `test -f 'verify_user.c' || echo '$(srcdir)/'`verify_user.c + +libkrb5_la-version.lo: version.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-version.lo `test -f 'version.c' || echo '$(srcdir)/'`version.c + +libkrb5_la-warn.lo: warn.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-warn.lo `test -f 'warn.c' || echo '$(srcdir)/'`warn.c + +libkrb5_la-write_message.lo: write_message.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-write_message.lo `test -f 'write_message.c' || echo '$(srcdir)/'`write_message.c + +libkrb5_la-krb5_err.lo: krb5_err.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-krb5_err.lo `test -f 'krb5_err.c' || echo '$(srcdir)/'`krb5_err.c + +libkrb5_la-krb_err.lo: krb_err.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-krb_err.lo `test -f 'krb_err.c' || echo '$(srcdir)/'`krb_err.c + +libkrb5_la-heim_err.lo: heim_err.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-heim_err.lo `test -f 'heim_err.c' || echo '$(srcdir)/'`heim_err.c + +libkrb5_la-k524_err.lo: k524_err.c + $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libkrb5_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libkrb5_la-k524_err.lo `test -f 'k524_err.c' || echo '$(srcdir)/'`k524_err.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-man3: $(man3_MANS) $(man_MANS) + @$(NORMAL_INSTALL) + test -z "$(man3dir)" || $(MKDIR_P) "$(DESTDIR)$(man3dir)" + @list='$(man3_MANS) $(dist_man3_MANS) $(nodist_man3_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.3*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ + else file=$$i; fi; \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + case "$$ext" in \ + 3*) ;; \ + *) ext='3' ;; \ + esac; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed -e 's/^.*\///'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man3dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man3dir)/$$inst"; \ + done +uninstall-man3: + @$(NORMAL_UNINSTALL) + @list='$(man3_MANS) $(dist_man3_MANS) $(nodist_man3_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.3*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + case "$$ext" in \ + 3*) ;; \ + *) ext='3' ;; \ + esac; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed -e 's/^.*\///'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " rm -f '$(DESTDIR)$(man3dir)/$$inst'"; \ + rm -f "$(DESTDIR)$(man3dir)/$$inst"; \ + done +install-man5: $(man5_MANS) $(man_MANS) + @$(NORMAL_INSTALL) + test -z "$(man5dir)" || $(MKDIR_P) "$(DESTDIR)$(man5dir)" + @list='$(man5_MANS) $(dist_man5_MANS) $(nodist_man5_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.5*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ + else file=$$i; fi; \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + case "$$ext" in \ + 5*) ;; \ + *) ext='5' ;; \ + esac; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed -e 's/^.*\///'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man5dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man5dir)/$$inst"; \ + done +uninstall-man5: + @$(NORMAL_UNINSTALL) + @list='$(man5_MANS) $(dist_man5_MANS) $(nodist_man5_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.5*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + case "$$ext" in \ + 5*) ;; \ + *) ext='5' ;; \ + esac; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed -e 's/^.*\///'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " rm -f '$(DESTDIR)$(man5dir)/$$inst'"; \ + rm -f "$(DESTDIR)$(man5dir)/$$inst"; \ + done +install-man8: $(man8_MANS) $(man_MANS) + @$(NORMAL_INSTALL) + test -z "$(man8dir)" || $(MKDIR_P) "$(DESTDIR)$(man8dir)" + @list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.8*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ + else file=$$i; fi; \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + case "$$ext" in \ + 8*) ;; \ + *) ext='8' ;; \ + esac; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed -e 's/^.*\///'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst"; \ + done +uninstall-man8: + @$(NORMAL_UNINSTALL) + @list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.8*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + case "$$ext" in \ + 8*) ;; \ + *) ext='8' ;; \ + esac; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed -e 's/^.*\///'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " rm -f '$(DESTDIR)$(man8dir)/$$inst'"; \ + rm -f "$(DESTDIR)$(man8dir)/$$inst"; \ + done +install-dist_includeHEADERS: $(dist_include_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)" + @list='$(dist_include_HEADERS)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f=$(am__strip_dir) \ + echo " $(dist_includeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(includedir)/$$f'"; \ + $(dist_includeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(includedir)/$$f"; \ + done + +uninstall-dist_includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(dist_include_HEADERS)'; for p in $$list; do \ + f=$(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(includedir)/$$f'"; \ + rm -f "$(DESTDIR)$(includedir)/$$f"; \ + done +install-krb5HEADERS: $(krb5_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(krb5dir)" || $(MKDIR_P) "$(DESTDIR)$(krb5dir)" + @list='$(krb5_HEADERS)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f=$(am__strip_dir) \ + echo " $(krb5HEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(krb5dir)/$$f'"; \ + $(krb5HEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(krb5dir)/$$f"; \ + done + +uninstall-krb5HEADERS: + @$(NORMAL_UNINSTALL) + @list='$(krb5_HEADERS)'; for p in $$list; do \ + f=$(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(krb5dir)/$$f'"; \ + rm -f "$(DESTDIR)$(krb5dir)/$$f"; \ + done +install-nodist_includeHEADERS: $(nodist_include_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)" + @list='$(nodist_include_HEADERS)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f=$(am__strip_dir) \ + echo " $(nodist_includeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(includedir)/$$f'"; \ + $(nodist_includeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(includedir)/$$f"; \ + done + +uninstall-nodist_includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(nodist_include_HEADERS)'; for p in $$list; do \ + f=$(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(includedir)/$$f'"; \ + rm -f "$(DESTDIR)$(includedir)/$$f"; \ + done + +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; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + 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; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + 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; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +check-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; ws='[ ]'; \ + srcdir=$(srcdir); export srcdir; \ + list=' $(TESTS) '; \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *$$ws$$tst$$ws*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + echo "XPASS: $$tst"; \ + ;; \ + *) \ + echo "PASS: $$tst"; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *$$ws$$tst$$ws*) \ + xfail=`expr $$xfail + 1`; \ + echo "XFAIL: $$tst"; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + echo "FAIL: $$tst"; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + echo "SKIP: $$tst"; \ + fi; \ + done; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="All $$all tests passed"; \ + else \ + banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all tests failed"; \ + else \ + banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + skipped="($$skip tests were not run)"; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + test -z "$$skipped" || echo "$$skipped"; \ + test -z "$$report" || echo "$$report"; \ + echo "$$dashes"; \ + test "$$failed" -eq 0; \ + else :; fi + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" distdir="$(distdir)" \ + dist-hook +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) check-TESTS check-local +check: check-am +all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(MANS) $(HEADERS) \ + all-local +install-binPROGRAMS: install-libLTLIBRARIES + +installdirs: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)" "$(DESTDIR)$(includedir)" "$(DESTDIR)$(krb5dir)" "$(DESTDIR)$(includedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-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 +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ + clean-libLTLIBRARIES clean-libtool clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-dist_includeHEADERS install-krb5HEADERS \ + install-man install-nodist_includeHEADERS + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-data-hook + +install-dvi: install-dvi-am + +install-exec-am: install-binPROGRAMS install-libLTLIBRARIES + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-exec-hook + +install-html: install-html-am + +install-info: install-info-am + +install-man: install-man3 install-man5 install-man8 + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS uninstall-dist_includeHEADERS \ + uninstall-krb5HEADERS uninstall-libLTLIBRARIES uninstall-man \ + uninstall-nodist_includeHEADERS + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) uninstall-hook + +uninstall-man: uninstall-man3 uninstall-man5 uninstall-man8 + +.MAKE: install-am install-data-am install-exec-am install-strip \ + uninstall-am + +.PHONY: CTAGS GTAGS all all-am all-local check check-TESTS check-am \ + check-local clean clean-binPROGRAMS clean-checkPROGRAMS \ + clean-generic clean-libLTLIBRARIES clean-libtool \ + clean-noinstPROGRAMS ctags 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-dist_includeHEADERS \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-exec-hook install-html install-html-am install-info \ + install-info-am install-krb5HEADERS install-libLTLIBRARIES \ + install-man install-man3 install-man5 install-man8 \ + install-nodist_includeHEADERS install-pdf install-pdf-am \ + install-ps install-ps-am 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 uninstall-binPROGRAMS \ + uninstall-dist_includeHEADERS uninstall-hook \ + uninstall-krb5HEADERS uninstall-libLTLIBRARIES uninstall-man \ + uninstall-man3 uninstall-man5 uninstall-man8 \ + uninstall-nodist_includeHEADERS + + +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 + +install-exec-hook: 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)'; \ + for f in $$foo; do \ + f=`basename $$f`; \ + if test -f "$(srcdir)/$$f"; then file="$(srcdir)/$$f"; \ + else file="$$f"; fi; \ + if cmp -s $$file $(buildinclude)/$$f 2> /dev/null ; then \ + : ; else \ + echo " $(CP) $$file $(buildinclude)/$$f"; \ + $(CP) $$file $(buildinclude)/$$f; \ + fi ; \ + done ; \ + foo='$(nobase_include_HEADERS)'; \ + for f in $$foo; do \ + if test -f "$(srcdir)/$$f"; then file="$(srcdir)/$$f"; \ + else file="$$f"; fi; \ + $(mkdir_p) $(buildinclude)/`dirname $$f` ; \ + if cmp -s $$file $(buildinclude)/$$f 2> /dev/null ; then \ + : ; else \ + echo " $(CP) $$file $(buildinclude)/$$f"; \ + $(CP) $$file $(buildinclude)/$$f; \ + fi ; \ + done + +all-local: install-build-headers + +check-local:: + @if test '$(CHECK_LOCAL)' = "no-check-local"; then \ + foo=''; elif test '$(CHECK_LOCAL)'; then \ + foo='$(CHECK_LOCAL)'; else \ + foo='$(PROGRAMS)'; fi; \ + if test "$$foo"; then \ + failed=0; all=0; \ + for i in $$foo; do \ + all=`expr $$all + 1`; \ + if (./$$i --version && ./$$i --help) > /dev/null 2>&1; then \ + echo "PASS: $$i"; \ + else \ + echo "FAIL: $$i"; \ + failed=`expr $$failed + 1`; \ + fi; \ + done; \ + if test "$$failed" -eq 0; then \ + banner="All $$all tests passed"; \ + else \ + banner="$$failed of $$all tests failed"; \ + fi; \ + dashes=`echo "$$banner" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + echo "$$dashes"; \ + test "$$failed" -eq 0 || exit 1; \ + fi + +.x.c: + @cmp -s $< $@ 2> /dev/null || cp $< $@ +#NROFF_MAN = nroff -man +.1.cat1: + $(NROFF_MAN) $< > $@ +.3.cat3: + $(NROFF_MAN) $< > $@ +.5.cat5: + $(NROFF_MAN) $< > $@ +.8.cat8: + $(NROFF_MAN) $< > $@ + +dist-cat1-mans: + @foo='$(man1_MANS)'; \ + bar='$(man_MANS)'; \ + for i in $$bar; do \ + case $$i in \ + *.1) foo="$$foo $$i";; \ + esac; done ;\ + for i in $$foo; do \ + x=`echo $$i | sed 's/\.[^.]*$$/.cat1/'`; \ + echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \ + $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \ + done + +dist-cat3-mans: + @foo='$(man3_MANS)'; \ + bar='$(man_MANS)'; \ + for i in $$bar; do \ + case $$i in \ + *.3) foo="$$foo $$i";; \ + esac; done ;\ + for i in $$foo; do \ + x=`echo $$i | sed 's/\.[^.]*$$/.cat3/'`; \ + echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \ + $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \ + done + +dist-cat5-mans: + @foo='$(man5_MANS)'; \ + bar='$(man_MANS)'; \ + for i in $$bar; do \ + case $$i in \ + *.5) foo="$$foo $$i";; \ + esac; done ;\ + for i in $$foo; do \ + x=`echo $$i | sed 's/\.[^.]*$$/.cat5/'`; \ + echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \ + $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \ + done + +dist-cat8-mans: + @foo='$(man8_MANS)'; \ + bar='$(man_MANS)'; \ + for i in $$bar; do \ + case $$i in \ + *.8) foo="$$foo $$i";; \ + esac; done ;\ + for i in $$foo; do \ + x=`echo $$i | sed 's/\.[^.]*$$/.cat8/'`; \ + echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \ + $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \ + done + +dist-hook: dist-cat1-mans dist-cat3-mans dist-cat5-mans dist-cat8-mans + +install-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) + +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) + +install-data-hook: install-cat-mans +uninstall-hook: uninstall-cat-mans + +.et.h: + $(COMPILE_ET) $< +.et.c: + $(COMPILE_ET) $< + +# +# Useful target for debugging +# + +check-valgrind: + tobjdir=`cd $(top_builddir) && pwd` ; \ + tsrcdir=`cd $(top_srcdir) && pwd` ; \ + env TESTS_ENVIRONMENT="$${tobjdir}/libtool --mode execute valgrind --leak-check=full --trace-children=yes --quiet -q --num-callers=30 --suppressions=$${tsrcdir}/cf/valgrind-suppressions" make check + +# +# Target to please samba build farm, builds distfiles in-tree. +# Will break when automake changes... +# + +distdir-in-tree: $(DISTFILES) $(INFO_DEPS) + list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" != .; then \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) distdir-in-tree) ; \ + fi ; \ + done + +$(libkrb5_la_OBJECTS) $(verify_krb5_conf_OBJECTS): $(srcdir)/krb5-protos.h $(srcdir)/krb5-private.h + +$(srcdir)/krb5-protos.h: + cd $(srcdir) && perl ../../cf/make-proto.pl -E KRB5_LIB_FUNCTION -q -P comment -o krb5-protos.h $(dist_libkrb5_la_SOURCES) || rm -f krb5-protos.h + +$(srcdir)/krb5-private.h: + cd $(srcdir) && perl ../../cf/make-proto.pl -q -P comment -p krb5-private.h $(dist_libkrb5_la_SOURCES) || rm -f krb5-private.h + +$(libkrb5_la_OBJECTS): krb5_err.h krb_err.h heim_err.h k524_err.h + +#sysconf_DATA = krb5.moduli + +# to help stupid solaris make + +krb5_err.h: krb5_err.et + +krb_err.h: krb_err.et + +heim_err.h: heim_err.et + +k524_err.h: k524_err.et +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/lib/krb5/acache.c b/lib/krb5/acache.c new file mode 100644 index 0000000..30a6d90 --- /dev/null +++ b/lib/krb5/acache.c @@ -0,0 +1,961 @@ +/* + * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" +#include <krb5_ccapi.h> +#ifdef HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +RCSID("$Id: acache.c 22099 2007-12-03 17:14:34Z lha $"); + +/* XXX should we fetch these for each open ? */ +static HEIMDAL_MUTEX acc_mutex = HEIMDAL_MUTEX_INITIALIZER; +static cc_initialize_func init_func; + +#ifdef HAVE_DLOPEN +static void *cc_handle; +#endif + +typedef struct krb5_acc { + char *cache_name; + cc_context_t context; + cc_ccache_t ccache; +} krb5_acc; + +static krb5_error_code acc_close(krb5_context, krb5_ccache); + +#define ACACHE(X) ((krb5_acc *)(X)->data.data) + +static const struct { + cc_int32 error; + krb5_error_code ret; +} cc_errors[] = { + { ccErrBadName, KRB5_CC_BADNAME }, + { ccErrCredentialsNotFound, KRB5_CC_NOTFOUND }, + { ccErrCCacheNotFound, KRB5_FCC_NOFILE }, + { ccErrContextNotFound, KRB5_CC_NOTFOUND }, + { ccIteratorEnd, KRB5_CC_END }, + { ccErrNoMem, KRB5_CC_NOMEM }, + { ccErrServerUnavailable, KRB5_CC_NOSUPP }, + { ccNoError, 0 } +}; + +static krb5_error_code +translate_cc_error(krb5_context context, cc_int32 error) +{ + int i; + krb5_clear_error_string(context); + for(i = 0; i < sizeof(cc_errors)/sizeof(cc_errors[0]); i++) + if (cc_errors[i].error == error) + return cc_errors[i].ret; + return KRB5_FCC_INTERNAL; +} + +static krb5_error_code +init_ccapi(krb5_context context) +{ + const char *lib; + + HEIMDAL_MUTEX_lock(&acc_mutex); + if (init_func) { + HEIMDAL_MUTEX_unlock(&acc_mutex); + krb5_clear_error_string(context); + return 0; + } + + lib = krb5_config_get_string(context, NULL, + "libdefaults", "ccapi_library", + NULL); + if (lib == NULL) { +#ifdef __APPLE__ + lib = "/System/Library/Frameworks/Kerberos.framework/Kerberos"; +#else + lib = "/usr/lib/libkrb5_cc.so"; +#endif + } + +#ifdef HAVE_DLOPEN + +#ifndef RTLD_LAZY +#define RTLD_LAZY 0 +#endif + + cc_handle = dlopen(lib, RTLD_LAZY); + if (cc_handle == NULL) { + HEIMDAL_MUTEX_unlock(&acc_mutex); + krb5_set_error_string(context, "Failed to load %s", lib); + return KRB5_CC_NOSUPP; + } + + init_func = (cc_initialize_func)dlsym(cc_handle, "cc_initialize"); + HEIMDAL_MUTEX_unlock(&acc_mutex); + if (init_func == NULL) { + krb5_set_error_string(context, "Failed to find cc_initialize" + "in %s: %s", lib, dlerror()); + dlclose(cc_handle); + return KRB5_CC_NOSUPP; + } + + return 0; +#else + HEIMDAL_MUTEX_unlock(&acc_mutex); + krb5_set_error_string(context, "no support for shared object"); + return KRB5_CC_NOSUPP; +#endif +} + +static krb5_error_code +make_cred_from_ccred(krb5_context context, + const cc_credentials_v5_t *incred, + krb5_creds *cred) +{ + krb5_error_code ret; + int i; + + memset(cred, 0, sizeof(*cred)); + + ret = krb5_parse_name(context, incred->client, &cred->client); + if (ret) + goto fail; + + ret = krb5_parse_name(context, incred->server, &cred->server); + if (ret) + goto fail; + + cred->session.keytype = incred->keyblock.type; + cred->session.keyvalue.length = incred->keyblock.length; + cred->session.keyvalue.data = malloc(incred->keyblock.length); + if (cred->session.keyvalue.data == NULL) + goto nomem; + memcpy(cred->session.keyvalue.data, incred->keyblock.data, + incred->keyblock.length); + + cred->times.authtime = incred->authtime; + cred->times.starttime = incred->starttime; + cred->times.endtime = incred->endtime; + cred->times.renew_till = incred->renew_till; + + ret = krb5_data_copy(&cred->ticket, + incred->ticket.data, + incred->ticket.length); + if (ret) + goto nomem; + + ret = krb5_data_copy(&cred->second_ticket, + incred->second_ticket.data, + incred->second_ticket.length); + if (ret) + goto nomem; + + cred->authdata.val = NULL; + cred->authdata.len = 0; + + cred->addresses.val = NULL; + cred->addresses.len = 0; + + for (i = 0; incred->authdata && incred->authdata[i]; i++) + ; + + if (i) { + cred->authdata.val = calloc(i, sizeof(cred->authdata.val[0])); + if (cred->authdata.val == NULL) + goto nomem; + cred->authdata.len = i; + for (i = 0; i < cred->authdata.len; i++) { + cred->authdata.val[i].ad_type = incred->authdata[i]->type; + ret = krb5_data_copy(&cred->authdata.val[i].ad_data, + incred->authdata[i]->data, + incred->authdata[i]->length); + if (ret) + goto nomem; + } + } + + for (i = 0; incred->addresses && incred->addresses[i]; i++) + ; + + if (i) { + cred->addresses.val = calloc(i, sizeof(cred->addresses.val[0])); + if (cred->addresses.val == NULL) + goto nomem; + cred->addresses.len = i; + + for (i = 0; i < cred->addresses.len; i++) { + cred->addresses.val[i].addr_type = incred->addresses[i]->type; + ret = krb5_data_copy(&cred->addresses.val[i].address, + incred->addresses[i]->data, + incred->addresses[i]->length); + if (ret) + goto nomem; + } + } + + cred->flags.i = 0; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_FORWARDABLE) + cred->flags.b.forwardable = 1; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_FORWARDED) + cred->flags.b.forwarded = 1; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_PROXIABLE) + cred->flags.b.proxiable = 1; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_PROXY) + cred->flags.b.proxy = 1; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_MAY_POSTDATE) + cred->flags.b.may_postdate = 1; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_POSTDATED) + cred->flags.b.postdated = 1; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_INVALID) + cred->flags.b.invalid = 1; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_RENEWABLE) + cred->flags.b.renewable = 1; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_INITIAL) + cred->flags.b.initial = 1; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_PRE_AUTH) + cred->flags.b.pre_authent = 1; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_HW_AUTH) + cred->flags.b.hw_authent = 1; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_TRANSIT_POLICY_CHECKED) + cred->flags.b.transited_policy_checked = 1; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_OK_AS_DELEGATE) + cred->flags.b.ok_as_delegate = 1; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_ANONYMOUS) + cred->flags.b.anonymous = 1; + + return 0; + +nomem: + ret = ENOMEM; + krb5_set_error_string(context, "malloc - out of memory"); + +fail: + krb5_free_cred_contents(context, cred); + return ret; +} + +static void +free_ccred(cc_credentials_v5_t *cred) +{ + int i; + + if (cred->addresses) { + for (i = 0; cred->addresses[i] != 0; i++) { + if (cred->addresses[i]->data) + free(cred->addresses[i]->data); + free(cred->addresses[i]); + } + free(cred->addresses); + } + if (cred->server) + free(cred->server); + if (cred->client) + free(cred->client); + memset(cred, 0, sizeof(*cred)); +} + +static krb5_error_code +make_ccred_from_cred(krb5_context context, + const krb5_creds *incred, + cc_credentials_v5_t *cred) +{ + krb5_error_code ret; + int i; + + memset(cred, 0, sizeof(*cred)); + + ret = krb5_unparse_name(context, incred->client, &cred->client); + if (ret) + goto fail; + + ret = krb5_unparse_name(context, incred->server, &cred->server); + if (ret) + goto fail; + + cred->keyblock.type = incred->session.keytype; + cred->keyblock.length = incred->session.keyvalue.length; + cred->keyblock.data = incred->session.keyvalue.data; + + cred->authtime = incred->times.authtime; + cred->starttime = incred->times.starttime; + cred->endtime = incred->times.endtime; + cred->renew_till = incred->times.renew_till; + + cred->ticket.length = incred->ticket.length; + cred->ticket.data = incred->ticket.data; + + cred->second_ticket.length = incred->second_ticket.length; + cred->second_ticket.data = incred->second_ticket.data; + + /* XXX this one should also be filled in */ + cred->authdata = NULL; + + cred->addresses = calloc(incred->addresses.len + 1, + sizeof(cred->addresses[0])); + if (cred->addresses == NULL) { + + ret = ENOMEM; + goto fail; + } + + for (i = 0; i < incred->addresses.len; i++) { + cc_data *addr; + addr = malloc(sizeof(*addr)); + if (addr == NULL) { + ret = ENOMEM; + goto fail; + } + addr->type = incred->addresses.val[i].addr_type; + addr->length = incred->addresses.val[i].address.length; + addr->data = malloc(addr->length); + if (addr->data == NULL) { + ret = ENOMEM; + goto fail; + } + memcpy(addr->data, incred->addresses.val[i].address.data, + addr->length); + cred->addresses[i] = addr; + } + cred->addresses[i] = NULL; + + cred->ticket_flags = 0; + if (incred->flags.b.forwardable) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_FORWARDABLE; + if (incred->flags.b.forwarded) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_FORWARDED; + if (incred->flags.b.proxiable) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_PROXIABLE; + if (incred->flags.b.proxy) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_PROXY; + if (incred->flags.b.may_postdate) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_MAY_POSTDATE; + if (incred->flags.b.postdated) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_POSTDATED; + if (incred->flags.b.invalid) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_INVALID; + if (incred->flags.b.renewable) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_RENEWABLE; + if (incred->flags.b.initial) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_INITIAL; + if (incred->flags.b.pre_authent) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_PRE_AUTH; + if (incred->flags.b.hw_authent) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_HW_AUTH; + if (incred->flags.b.transited_policy_checked) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_TRANSIT_POLICY_CHECKED; + if (incred->flags.b.ok_as_delegate) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_OK_AS_DELEGATE; + if (incred->flags.b.anonymous) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_ANONYMOUS; + + return 0; + +fail: + free_ccred(cred); + + krb5_clear_error_string(context); + return ret; +} + +static char * +get_cc_name(cc_ccache_t cache) +{ + cc_string_t name; + cc_int32 error; + char *str; + + error = (*cache->func->get_name)(cache, &name); + if (error) + return NULL; + + str = strdup(name->data); + (*name->func->release)(name); + return str; +} + + +static const char* +acc_get_name(krb5_context context, + krb5_ccache id) +{ + krb5_acc *a = ACACHE(id); + static char n[255]; + char *name; + + name = get_cc_name(a->ccache); + if (name == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return NULL; + } + strlcpy(n, name, sizeof(n)); + free(name); + return n; +} + +static krb5_error_code +acc_alloc(krb5_context context, krb5_ccache *id) +{ + krb5_error_code ret; + cc_int32 error; + krb5_acc *a; + + ret = init_ccapi(context); + if (ret) + return ret; + + ret = krb5_data_alloc(&(*id)->data, sizeof(*a)); + if (ret) { + krb5_clear_error_string(context); + return ret; + } + + a = ACACHE(*id); + + error = (*init_func)(&a->context, ccapi_version_3, NULL, NULL); + if (error) { + krb5_data_free(&(*id)->data); + return translate_cc_error(context, error); + } + + a->cache_name = NULL; + + return 0; +} + +static krb5_error_code +acc_resolve(krb5_context context, krb5_ccache *id, const char *res) +{ + krb5_error_code ret; + cc_int32 error; + krb5_acc *a; + + ret = acc_alloc(context, id); + if (ret) + return ret; + + a = ACACHE(*id); + + error = (*a->context->func->open_ccache)(a->context, res, + &a->ccache); + if (error == 0) { + a->cache_name = get_cc_name(a->ccache); + if (a->cache_name == NULL) { + acc_close(context, *id); + *id = NULL; + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + } else if (error == ccErrCCacheNotFound) { + a->ccache = NULL; + a->cache_name = NULL; + error = 0; + } else { + *id = NULL; + return translate_cc_error(context, error); + } + + return 0; +} + +static krb5_error_code +acc_gen_new(krb5_context context, krb5_ccache *id) +{ + krb5_error_code ret; + krb5_acc *a; + + ret = acc_alloc(context, id); + if (ret) + return ret; + + a = ACACHE(*id); + + a->ccache = NULL; + a->cache_name = NULL; + + return 0; +} + +static krb5_error_code +acc_initialize(krb5_context context, + krb5_ccache id, + krb5_principal primary_principal) +{ + krb5_acc *a = ACACHE(id); + krb5_error_code ret; + int32_t error; + char *name; + + ret = krb5_unparse_name(context, primary_principal, &name); + if (ret) + return ret; + + error = (*a->context->func->create_new_ccache)(a->context, + cc_credentials_v5, + name, + &a->ccache); + free(name); + + return translate_cc_error(context, error); +} + +static krb5_error_code +acc_close(krb5_context context, + krb5_ccache id) +{ + krb5_acc *a = ACACHE(id); + + if (a->ccache) { + (*a->ccache->func->release)(a->ccache); + a->ccache = NULL; + } + if (a->cache_name) { + free(a->cache_name); + a->cache_name = NULL; + } + (*a->context->func->release)(a->context); + a->context = NULL; + krb5_data_free(&id->data); + return 0; +} + +static krb5_error_code +acc_destroy(krb5_context context, + krb5_ccache id) +{ + krb5_acc *a = ACACHE(id); + cc_int32 error = 0; + + if (a->ccache) { + error = (*a->ccache->func->destroy)(a->ccache); + a->ccache = NULL; + } + if (a->context) { + error = (a->context->func->release)(a->context); + a->context = NULL; + } + return translate_cc_error(context, error); +} + +static krb5_error_code +acc_store_cred(krb5_context context, + krb5_ccache id, + krb5_creds *creds) +{ + krb5_acc *a = ACACHE(id); + cc_credentials_union cred; + cc_credentials_v5_t v5cred; + krb5_error_code ret; + cc_int32 error; + + if (a->ccache == NULL) { + krb5_set_error_string(context, "No API credential found"); + return KRB5_CC_NOTFOUND; + } + + cred.version = cc_credentials_v5; + cred.credentials.credentials_v5 = &v5cred; + + ret = make_ccred_from_cred(context, + creds, + &v5cred); + if (ret) + return ret; + + error = (*a->ccache->func->store_credentials)(a->ccache, &cred); + if (error) + ret = translate_cc_error(context, error); + + free_ccred(&v5cred); + + return ret; +} + +static krb5_error_code +acc_get_principal(krb5_context context, + krb5_ccache id, + krb5_principal *principal) +{ + krb5_acc *a = ACACHE(id); + krb5_error_code ret; + int32_t error; + cc_string_t name; + + if (a->ccache == NULL) { + krb5_set_error_string(context, "No API credential found"); + return KRB5_CC_NOTFOUND; + } + + error = (*a->ccache->func->get_principal)(a->ccache, + cc_credentials_v5, + &name); + if (error) + return translate_cc_error(context, error); + + ret = krb5_parse_name(context, name->data, principal); + + (*name->func->release)(name); + return ret; +} + +static krb5_error_code +acc_get_first (krb5_context context, + krb5_ccache id, + krb5_cc_cursor *cursor) +{ + cc_credentials_iterator_t iter; + krb5_acc *a = ACACHE(id); + int32_t error; + + if (a->ccache == NULL) { + krb5_set_error_string(context, "No API credential found"); + return KRB5_CC_NOTFOUND; + } + + error = (*a->ccache->func->new_credentials_iterator)(a->ccache, &iter); + if (error) { + krb5_clear_error_string(context); + return ENOENT; + } + *cursor = iter; + return 0; +} + + +static krb5_error_code +acc_get_next (krb5_context context, + krb5_ccache id, + krb5_cc_cursor *cursor, + krb5_creds *creds) +{ + cc_credentials_iterator_t iter = *cursor; + cc_credentials_t cred; + krb5_error_code ret; + int32_t error; + + while (1) { + error = (*iter->func->next)(iter, &cred); + if (error) + return translate_cc_error(context, error); + if (cred->data->version == cc_credentials_v5) + break; + (*cred->func->release)(cred); + } + + ret = make_cred_from_ccred(context, + cred->data->credentials.credentials_v5, + creds); + (*cred->func->release)(cred); + return ret; +} + +static krb5_error_code +acc_end_get (krb5_context context, + krb5_ccache id, + krb5_cc_cursor *cursor) +{ + cc_credentials_iterator_t iter = *cursor; + (*iter->func->release)(iter); + return 0; +} + +static krb5_error_code +acc_remove_cred(krb5_context context, + krb5_ccache id, + krb5_flags which, + krb5_creds *cred) +{ + cc_credentials_iterator_t iter; + krb5_acc *a = ACACHE(id); + cc_credentials_t ccred; + krb5_error_code ret; + cc_int32 error; + char *client, *server; + + if (a->ccache == NULL) { + krb5_set_error_string(context, "No API credential found"); + return KRB5_CC_NOTFOUND; + } + + if (cred->client) { + ret = krb5_unparse_name(context, cred->client, &client); + if (ret) + return ret; + } else + client = NULL; + + ret = krb5_unparse_name(context, cred->server, &server); + if (ret) { + free(client); + return ret; + } + + error = (*a->ccache->func->new_credentials_iterator)(a->ccache, &iter); + if (error) { + free(server); + free(client); + return translate_cc_error(context, error); + } + + ret = KRB5_CC_NOTFOUND; + while (1) { + cc_credentials_v5_t *v5cred; + + error = (*iter->func->next)(iter, &ccred); + if (error) + break; + + if (ccred->data->version != cc_credentials_v5) + goto next; + + v5cred = ccred->data->credentials.credentials_v5; + + if (client && strcmp(v5cred->client, client) != 0) + goto next; + + if (strcmp(v5cred->server, server) != 0) + goto next; + + (*a->ccache->func->remove_credentials)(a->ccache, ccred); + ret = 0; + next: + (*ccred->func->release)(ccred); + } + + (*iter->func->release)(iter); + + if (ret) + krb5_set_error_string(context, "Can't find credential %s in cache", + server); + free(server); + free(client); + + return ret; +} + +static krb5_error_code +acc_set_flags(krb5_context context, + krb5_ccache id, + krb5_flags flags) +{ + return 0; +} + +static krb5_error_code +acc_get_version(krb5_context context, + krb5_ccache id) +{ + return 0; +} + +struct cache_iter { + cc_context_t context; + cc_ccache_iterator_t iter; +}; + +static krb5_error_code +acc_get_cache_first(krb5_context context, krb5_cc_cursor *cursor) +{ + struct cache_iter *iter; + krb5_error_code ret; + cc_int32 error; + + ret = init_ccapi(context); + if (ret) + return ret; + + iter = calloc(1, sizeof(*iter)); + if (iter == NULL) { + krb5_set_error_string(context, "malloc - out of memory"); + return ENOMEM; + } + + error = (*init_func)(&iter->context, ccapi_version_3, NULL, NULL); + if (error) { + free(iter); + return translate_cc_error(context, error); + } + + error = (*iter->context->func->new_ccache_iterator)(iter->context, + &iter->iter); + if (error) { + free(iter); + krb5_clear_error_string(context); + return ENOENT; + } + *cursor = iter; + return 0; +} + +static krb5_error_code +acc_get_cache_next(krb5_context context, krb5_cc_cursor cursor, krb5_ccache *id) +{ + struct cache_iter *iter = cursor; + cc_ccache_t cache; + krb5_acc *a; + krb5_error_code ret; + int32_t error; + + error = (*iter->iter->func->next)(iter->iter, &cache); + if (error) + return translate_cc_error(context, error); + + ret = _krb5_cc_allocate(context, &krb5_acc_ops, id); + if (ret) { + (*cache->func->release)(cache); + return ret; + } + + ret = acc_alloc(context, id); + if (ret) { + (*cache->func->release)(cache); + free(*id); + return ret; + } + + a = ACACHE(*id); + a->ccache = cache; + + a->cache_name = get_cc_name(a->ccache); + if (a->cache_name == NULL) { + acc_close(context, *id); + *id = NULL; + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + return 0; +} + +static krb5_error_code +acc_end_cache_get(krb5_context context, krb5_cc_cursor cursor) +{ + struct cache_iter *iter = cursor; + + (*iter->iter->func->release)(iter->iter); + iter->iter = NULL; + (*iter->context->func->release)(iter->context); + iter->context = NULL; + free(iter); + return 0; +} + +static krb5_error_code +acc_move(krb5_context context, krb5_ccache from, krb5_ccache to) +{ + krb5_acc *afrom = ACACHE(from); + krb5_acc *ato = ACACHE(to); + int32_t error; + + if (ato->ccache == NULL) { + cc_string_t name; + + error = (*afrom->ccache->func->get_principal)(afrom->ccache, + cc_credentials_v5, + &name); + if (error) + return translate_cc_error(context, error); + + error = (*ato->context->func->create_new_ccache)(ato->context, + cc_credentials_v5, + name->data, + &ato->ccache); + (*name->func->release)(name); + if (error) + return translate_cc_error(context, error); + } + + + error = (*ato->ccache->func->move)(afrom->ccache, ato->ccache); + return translate_cc_error(context, error); +} + +static krb5_error_code +acc_default_name(krb5_context context, char **str) +{ + krb5_error_code ret; + cc_context_t cc; + cc_string_t name; + int32_t error; + + ret = init_ccapi(context); + if (ret) + return ret; + + error = (*init_func)(&cc, ccapi_version_3, NULL, NULL); + if (error) + return translate_cc_error(context, error); + + error = (*cc->func->get_default_ccache_name)(cc, &name); + if (error) { + (*cc->func->release)(cc); + return translate_cc_error(context, error); + } + + asprintf(str, "API:%s", name->data); + (*name->func->release)(name); + (*cc->func->release)(cc); + + if (*str == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + return 0; +} + + +/** + * Variable containing the API based credential cache implemention. + * + * @ingroup krb5_ccache + */ + +const krb5_cc_ops krb5_acc_ops = { + "API", + acc_get_name, + acc_resolve, + acc_gen_new, + acc_initialize, + acc_destroy, + acc_close, + acc_store_cred, + NULL, /* acc_retrieve */ + acc_get_principal, + acc_get_first, + acc_get_next, + acc_end_get, + acc_remove_cred, + acc_set_flags, + acc_get_version, + acc_get_cache_first, + acc_get_cache_next, + acc_end_cache_get, + acc_move, + acc_default_name +}; diff --git a/lib/krb5/acl.c b/lib/krb5/acl.c new file mode 100644 index 0000000..cab6836 --- /dev/null +++ b/lib/krb5/acl.c @@ -0,0 +1,293 @@ +/* + * Copyright (c) 2000 - 2002, 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" +#include <fnmatch.h> + +RCSID("$Id: acl.c 22119 2007-12-03 22:02:48Z lha $"); + +struct acl_field { + enum { acl_string, acl_fnmatch, acl_retval } type; + union { + const char *cstr; + char **retv; + } u; + struct acl_field *next, **last; +}; + +static void +free_retv(struct acl_field *acl) +{ + while(acl != NULL) { + if (acl->type == acl_retval) { + if (*acl->u.retv) + free(*acl->u.retv); + *acl->u.retv = NULL; + } + acl = acl->next; + } +} + +static void +acl_free_list(struct acl_field *acl, int retv) +{ + struct acl_field *next; + if (retv) + free_retv(acl); + while(acl != NULL) { + next = acl->next; + free(acl); + acl = next; + } +} + +static krb5_error_code +acl_parse_format(krb5_context context, + struct acl_field **acl_ret, + const char *format, + va_list ap) +{ + const char *p; + struct acl_field *acl = NULL, *tmp; + + for(p = format; *p != '\0'; p++) { + tmp = malloc(sizeof(*tmp)); + if(tmp == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + acl_free_list(acl, 0); + return ENOMEM; + } + if(*p == 's') { + tmp->type = acl_string; + tmp->u.cstr = va_arg(ap, const char*); + } else if(*p == 'f') { + tmp->type = acl_fnmatch; + tmp->u.cstr = va_arg(ap, const char*); + } else if(*p == 'r') { + tmp->type = acl_retval; + tmp->u.retv = va_arg(ap, char **); + *tmp->u.retv = NULL; + } else { + krb5_set_error_string(context, "acl_parse_format: " + "unknown format specifier %c", *p); + acl_free_list(acl, 0); + free(tmp); + return EINVAL; + } + tmp->next = NULL; + if(acl == NULL) + acl = tmp; + else + *acl->last = tmp; + acl->last = &tmp->next; + } + *acl_ret = acl; + return 0; +} + +static krb5_boolean +acl_match_field(krb5_context context, + const char *string, + struct acl_field *field) +{ + if(field->type == acl_string) { + return !strcmp(field->u.cstr, string); + } else if(field->type == acl_fnmatch) { + return !fnmatch(field->u.cstr, string, 0); + } else if(field->type == acl_retval) { + *field->u.retv = strdup(string); + return TRUE; + } + return FALSE; +} + +static krb5_boolean +acl_match_acl(krb5_context context, + struct acl_field *acl, + const char *string) +{ + char buf[256]; + while(strsep_copy(&string, " \t", buf, sizeof(buf)) != -1) { + if(buf[0] == '\0') + continue; /* skip ws */ + if (acl == NULL) + return FALSE; + if(!acl_match_field(context, buf, acl)) { + return FALSE; + } + acl = acl->next; + } + if (acl) + return FALSE; + return TRUE; +} + +/** + * krb5_acl_match_string matches ACL format against a string. + * + * The ACL format has three format specifiers: s, f, and r. Each + * specifier will retrieve one argument from the variable arguments + * for either matching or storing data. The input string is split up + * using " " (space) and "\t" (tab) as a delimiter; multiple and "\t" + * in a row are considered to be the same. + * + * List of format specifiers: + * - s Matches a string using strcmp(3) (case sensitive). + * - f Matches the string with fnmatch(3). Theflags + * argument (the last argument) passed to the fnmatch function is 0. + * - r Returns a copy of the string in the char ** passed in; the copy + * must be freed with free(3). There is no need to free(3) the + * string on error: the function will clean up and set the pointer + * to NULL. + * + * @param context Kerberos 5 context + * @param string string to match with + * @param format format to match + * @param ... parameter to format string + * + * @return Return an error code or 0. + * + * + * @code + * char *s; + * + * ret = krb5_acl_match_string(context, "foo", "s", "foo"); + * if (ret) + * krb5_errx(context, 1, "acl didn't match"); + * ret = krb5_acl_match_string(context, "foo foo baz/kaka", + * "ss", "foo", &s, "foo/\\*"); + * if (ret) { + * // no need to free(s) on error + * assert(s == NULL); + * krb5_errx(context, 1, "acl didn't match"); + * } + * free(s); + * @endcode + * + * @sa krb5_acl_match_file + * @ingroup krb5_support + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_acl_match_string(krb5_context context, + const char *string, + const char *format, + ...) +{ + krb5_error_code ret; + krb5_boolean found; + struct acl_field *acl; + + va_list ap; + va_start(ap, format); + ret = acl_parse_format(context, &acl, format, ap); + va_end(ap); + if(ret) + return ret; + + found = acl_match_acl(context, acl, string); + acl_free_list(acl, !found); + if (found) { + return 0; + } else { + krb5_set_error_string(context, "ACL did not match"); + return EACCES; + } +} + +/** + * krb5_acl_match_file matches ACL format against each line in a file + * using krb5_acl_match_string(). Lines starting with # are treated + * like comments and ignored. + * + * @param context Kerberos 5 context. + * @param file file with acl listed in the file. + * @param format format to match. + * @param ... parameter to format string. + * + * @return Return an error code or 0. + * + * @sa krb5_acl_match_string + * @ingroup krb5_support + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_acl_match_file(krb5_context context, + const char *file, + const char *format, + ...) +{ + krb5_error_code ret; + struct acl_field *acl; + char buf[256]; + va_list ap; + FILE *f; + krb5_boolean found; + + f = fopen(file, "r"); + if(f == NULL) { + int save_errno = errno; + + krb5_set_error_string(context, "open(%s): %s", file, + strerror(save_errno)); + return save_errno; + } + + va_start(ap, format); + ret = acl_parse_format(context, &acl, format, ap); + va_end(ap); + if(ret) { + fclose(f); + return ret; + } + + found = FALSE; + while(fgets(buf, sizeof(buf), f)) { + if(buf[0] == '#') + continue; + if(acl_match_acl(context, acl, buf)) { + found = TRUE; + break; + } + free_retv(acl); + } + + fclose(f); + acl_free_list(acl, !found); + if (found) { + return 0; + } else { + krb5_set_error_string(context, "ACL did not match"); + return EACCES; + } +} diff --git a/lib/krb5/add_et_list.c b/lib/krb5/add_et_list.c new file mode 100644 index 0000000..a6005c6 --- /dev/null +++ b/lib/krb5/add_et_list.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: add_et_list.c 13713 2004-04-13 14:33:45Z lha $"); + +/* + * Add a specified list of error messages to the et list in context. + * Call func (probably a comerr-generated function) with a pointer to + * the current et_list. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_add_et_list (krb5_context context, + void (*func)(struct et_list **)) +{ + (*func)(&context->et_list); + return 0; +} diff --git a/lib/krb5/addr_families.c b/lib/krb5/addr_families.c new file mode 100644 index 0000000..f364f59 --- /dev/null +++ b/lib/krb5/addr_families.c @@ -0,0 +1,1463 @@ +/* + * Copyright (c) 1997-2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: addr_families.c 22039 2007-11-10 11:47:35Z lha $"); + +struct addr_operations { + int af; + krb5_address_type atype; + size_t max_sockaddr_size; + krb5_error_code (*sockaddr2addr)(const struct sockaddr *, krb5_address *); + krb5_error_code (*sockaddr2port)(const struct sockaddr *, int16_t *); + void (*addr2sockaddr)(const krb5_address *, struct sockaddr *, + krb5_socklen_t *sa_size, int port); + void (*h_addr2sockaddr)(const char *, struct sockaddr *, krb5_socklen_t *, int); + krb5_error_code (*h_addr2addr)(const char *, krb5_address *); + krb5_boolean (*uninteresting)(const struct sockaddr *); + void (*anyaddr)(struct sockaddr *, krb5_socklen_t *, int); + int (*print_addr)(const krb5_address *, char *, size_t); + int (*parse_addr)(krb5_context, const char*, krb5_address *); + int (*order_addr)(krb5_context, const krb5_address*, const krb5_address*); + int (*free_addr)(krb5_context, krb5_address*); + int (*copy_addr)(krb5_context, const krb5_address*, krb5_address*); + int (*mask_boundary)(krb5_context, const krb5_address*, unsigned long, + krb5_address*, krb5_address*); +}; + +/* + * AF_INET - aka IPv4 implementation + */ + +static krb5_error_code +ipv4_sockaddr2addr (const struct sockaddr *sa, krb5_address *a) +{ + const struct sockaddr_in *sin4 = (const struct sockaddr_in *)sa; + unsigned char buf[4]; + + a->addr_type = KRB5_ADDRESS_INET; + memcpy (buf, &sin4->sin_addr, 4); + return krb5_data_copy(&a->address, buf, 4); +} + +static krb5_error_code +ipv4_sockaddr2port (const struct sockaddr *sa, int16_t *port) +{ + const struct sockaddr_in *sin4 = (const struct sockaddr_in *)sa; + + *port = sin4->sin_port; + return 0; +} + +static void +ipv4_addr2sockaddr (const krb5_address *a, + struct sockaddr *sa, + krb5_socklen_t *sa_size, + int port) +{ + struct sockaddr_in tmp; + + memset (&tmp, 0, sizeof(tmp)); + tmp.sin_family = AF_INET; + memcpy (&tmp.sin_addr, a->address.data, 4); + tmp.sin_port = port; + memcpy(sa, &tmp, min(sizeof(tmp), *sa_size)); + *sa_size = sizeof(tmp); +} + +static void +ipv4_h_addr2sockaddr(const char *addr, + struct sockaddr *sa, + krb5_socklen_t *sa_size, + int port) +{ + struct sockaddr_in tmp; + + memset (&tmp, 0, sizeof(tmp)); + tmp.sin_family = AF_INET; + tmp.sin_port = port; + tmp.sin_addr = *((const struct in_addr *)addr); + memcpy(sa, &tmp, min(sizeof(tmp), *sa_size)); + *sa_size = sizeof(tmp); +} + +static krb5_error_code +ipv4_h_addr2addr (const char *addr, + krb5_address *a) +{ + unsigned char buf[4]; + + a->addr_type = KRB5_ADDRESS_INET; + memcpy(buf, addr, 4); + return krb5_data_copy(&a->address, buf, 4); +} + +/* + * Are there any addresses that should be considered `uninteresting'? + */ + +static krb5_boolean +ipv4_uninteresting (const struct sockaddr *sa) +{ + const struct sockaddr_in *sin4 = (const struct sockaddr_in *)sa; + + if (sin4->sin_addr.s_addr == INADDR_ANY) + return TRUE; + + return FALSE; +} + +static void +ipv4_anyaddr (struct sockaddr *sa, krb5_socklen_t *sa_size, int port) +{ + struct sockaddr_in tmp; + + memset (&tmp, 0, sizeof(tmp)); + tmp.sin_family = AF_INET; + tmp.sin_port = port; + tmp.sin_addr.s_addr = INADDR_ANY; + memcpy(sa, &tmp, min(sizeof(tmp), *sa_size)); + *sa_size = sizeof(tmp); +} + +static int +ipv4_print_addr (const krb5_address *addr, char *str, size_t len) +{ + struct in_addr ia; + + memcpy (&ia, addr->address.data, 4); + + return snprintf (str, len, "IPv4:%s", inet_ntoa(ia)); +} + +static int +ipv4_parse_addr (krb5_context context, const char *address, krb5_address *addr) +{ + const char *p; + struct in_addr a; + + p = strchr(address, ':'); + if(p) { + p++; + if(strncasecmp(address, "ip:", p - address) != 0 && + strncasecmp(address, "ip4:", p - address) != 0 && + strncasecmp(address, "ipv4:", p - address) != 0 && + strncasecmp(address, "inet:", p - address) != 0) + return -1; + } else + p = address; +#ifdef HAVE_INET_ATON + if(inet_aton(p, &a) == 0) + return -1; +#elif defined(HAVE_INET_ADDR) + a.s_addr = inet_addr(p); + if(a.s_addr == INADDR_NONE) + return -1; +#else + return -1; +#endif + addr->addr_type = KRB5_ADDRESS_INET; + if(krb5_data_alloc(&addr->address, 4) != 0) + return -1; + _krb5_put_int(addr->address.data, ntohl(a.s_addr), addr->address.length); + return 0; +} + +static int +ipv4_mask_boundary(krb5_context context, const krb5_address *inaddr, + unsigned long len, krb5_address *low, krb5_address *high) +{ + unsigned long ia; + uint32_t l, h, m = 0xffffffff; + + if (len > 32) { + krb5_set_error_string(context, "IPv4 prefix too large (%ld)", len); + return KRB5_PROG_ATYPE_NOSUPP; + } + m = m << (32 - len); + + _krb5_get_int(inaddr->address.data, &ia, inaddr->address.length); + + l = ia & m; + h = l | ~m; + + low->addr_type = KRB5_ADDRESS_INET; + if(krb5_data_alloc(&low->address, 4) != 0) + return -1; + _krb5_put_int(low->address.data, l, low->address.length); + + high->addr_type = KRB5_ADDRESS_INET; + if(krb5_data_alloc(&high->address, 4) != 0) { + krb5_free_address(context, low); + return -1; + } + _krb5_put_int(high->address.data, h, high->address.length); + + return 0; +} + + +/* + * AF_INET6 - aka IPv6 implementation + */ + +#ifdef HAVE_IPV6 + +static krb5_error_code +ipv6_sockaddr2addr (const struct sockaddr *sa, krb5_address *a) +{ + const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa; + + if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { + unsigned char buf[4]; + + a->addr_type = KRB5_ADDRESS_INET; +#ifndef IN6_ADDR_V6_TO_V4 +#ifdef IN6_EXTRACT_V4ADDR +#define IN6_ADDR_V6_TO_V4(x) (&IN6_EXTRACT_V4ADDR(x)) +#else +#define IN6_ADDR_V6_TO_V4(x) ((const struct in_addr *)&(x)->s6_addr[12]) +#endif +#endif + memcpy (buf, IN6_ADDR_V6_TO_V4(&sin6->sin6_addr), 4); + return krb5_data_copy(&a->address, buf, 4); + } else { + a->addr_type = KRB5_ADDRESS_INET6; + return krb5_data_copy(&a->address, + &sin6->sin6_addr, + sizeof(sin6->sin6_addr)); + } +} + +static krb5_error_code +ipv6_sockaddr2port (const struct sockaddr *sa, int16_t *port) +{ + const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa; + + *port = sin6->sin6_port; + return 0; +} + +static void +ipv6_addr2sockaddr (const krb5_address *a, + struct sockaddr *sa, + krb5_socklen_t *sa_size, + int port) +{ + struct sockaddr_in6 tmp; + + memset (&tmp, 0, sizeof(tmp)); + tmp.sin6_family = AF_INET6; + memcpy (&tmp.sin6_addr, a->address.data, sizeof(tmp.sin6_addr)); + tmp.sin6_port = port; + memcpy(sa, &tmp, min(sizeof(tmp), *sa_size)); + *sa_size = sizeof(tmp); +} + +static void +ipv6_h_addr2sockaddr(const char *addr, + struct sockaddr *sa, + krb5_socklen_t *sa_size, + int port) +{ + struct sockaddr_in6 tmp; + + memset (&tmp, 0, sizeof(tmp)); + tmp.sin6_family = AF_INET6; + tmp.sin6_port = port; + tmp.sin6_addr = *((const struct in6_addr *)addr); + memcpy(sa, &tmp, min(sizeof(tmp), *sa_size)); + *sa_size = sizeof(tmp); +} + +static krb5_error_code +ipv6_h_addr2addr (const char *addr, + krb5_address *a) +{ + a->addr_type = KRB5_ADDRESS_INET6; + return krb5_data_copy(&a->address, addr, sizeof(struct in6_addr)); +} + +/* + * + */ + +static krb5_boolean +ipv6_uninteresting (const struct sockaddr *sa) +{ + const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa; + const struct in6_addr *in6 = (const struct in6_addr *)&sin6->sin6_addr; + + return + IN6_IS_ADDR_LINKLOCAL(in6) + || IN6_IS_ADDR_V4COMPAT(in6); +} + +static void +ipv6_anyaddr (struct sockaddr *sa, krb5_socklen_t *sa_size, int port) +{ + struct sockaddr_in6 tmp; + + memset (&tmp, 0, sizeof(tmp)); + tmp.sin6_family = AF_INET6; + tmp.sin6_port = port; + tmp.sin6_addr = in6addr_any; + *sa_size = sizeof(tmp); +} + +static int +ipv6_print_addr (const krb5_address *addr, char *str, size_t len) +{ + char buf[128], buf2[3]; +#ifdef HAVE_INET_NTOP + if(inet_ntop(AF_INET6, addr->address.data, buf, sizeof(buf)) == NULL) +#endif + { + /* XXX this is pretty ugly, but better than abort() */ + int i; + unsigned char *p = addr->address.data; + buf[0] = '\0'; + for(i = 0; i < addr->address.length; i++) { + snprintf(buf2, sizeof(buf2), "%02x", p[i]); + if(i > 0 && (i & 1) == 0) + strlcat(buf, ":", sizeof(buf)); + strlcat(buf, buf2, sizeof(buf)); + } + } + return snprintf(str, len, "IPv6:%s", buf); +} + +static int +ipv6_parse_addr (krb5_context context, const char *address, krb5_address *addr) +{ + int ret; + struct in6_addr in6; + const char *p; + + p = strchr(address, ':'); + if(p) { + p++; + if(strncasecmp(address, "ip6:", p - address) == 0 || + strncasecmp(address, "ipv6:", p - address) == 0 || + strncasecmp(address, "inet6:", p - address) == 0) + address = p; + } + + ret = inet_pton(AF_INET6, address, &in6.s6_addr); + if(ret == 1) { + addr->addr_type = KRB5_ADDRESS_INET6; + ret = krb5_data_alloc(&addr->address, sizeof(in6.s6_addr)); + if (ret) + return -1; + memcpy(addr->address.data, in6.s6_addr, sizeof(in6.s6_addr)); + return 0; + } + return -1; +} + +static int +ipv6_mask_boundary(krb5_context context, const krb5_address *inaddr, + unsigned long len, krb5_address *low, krb5_address *high) +{ + struct in6_addr addr, laddr, haddr; + uint32_t m; + int i, sub_len; + + if (len > 128) { + krb5_set_error_string(context, "IPv6 prefix too large (%ld)", len); + return KRB5_PROG_ATYPE_NOSUPP; + } + + if (inaddr->address.length != sizeof(addr)) { + krb5_set_error_string(context, "IPv6 addr bad length"); + return KRB5_PROG_ATYPE_NOSUPP; + } + + memcpy(&addr, inaddr->address.data, inaddr->address.length); + + for (i = 0; i < 16; i++) { + sub_len = min(8, len); + + m = 0xff << (8 - sub_len); + + laddr.s6_addr[i] = addr.s6_addr[i] & m; + haddr.s6_addr[i] = (addr.s6_addr[i] & m) | ~m; + + if (len > 8) + len -= 8; + else + len = 0; + } + + low->addr_type = KRB5_ADDRESS_INET6; + if (krb5_data_alloc(&low->address, sizeof(laddr.s6_addr)) != 0) + return -1; + memcpy(low->address.data, laddr.s6_addr, sizeof(laddr.s6_addr)); + + high->addr_type = KRB5_ADDRESS_INET6; + if (krb5_data_alloc(&high->address, sizeof(haddr.s6_addr)) != 0) { + krb5_free_address(context, low); + return -1; + } + memcpy(high->address.data, haddr.s6_addr, sizeof(haddr.s6_addr)); + + return 0; +} + +#endif /* IPv6 */ + +/* + * table + */ + +#define KRB5_ADDRESS_ARANGE (-100) + +struct arange { + krb5_address low; + krb5_address high; +}; + +static int +arange_parse_addr (krb5_context context, + const char *address, krb5_address *addr) +{ + char buf[1024], *p; + krb5_address low0, high0; + struct arange *a; + krb5_error_code ret; + + if(strncasecmp(address, "RANGE:", 6) != 0) + return -1; + + address += 6; + + p = strrchr(address, '/'); + if (p) { + krb5_addresses addrmask; + char *q; + long num; + + if (strlcpy(buf, address, sizeof(buf)) > sizeof(buf)) + return -1; + buf[p - address] = '\0'; + ret = krb5_parse_address(context, buf, &addrmask); + if (ret) + return ret; + if(addrmask.len != 1) { + krb5_free_addresses(context, &addrmask); + return -1; + } + + address += p - address + 1; + + num = strtol(address, &q, 10); + if (q == address || *q != '\0' || num < 0) { + krb5_free_addresses(context, &addrmask); + return -1; + } + + ret = krb5_address_prefixlen_boundary(context, &addrmask.val[0], num, + &low0, &high0); + krb5_free_addresses(context, &addrmask); + if (ret) + return ret; + + } else { + krb5_addresses low, high; + + strsep_copy(&address, "-", buf, sizeof(buf)); + ret = krb5_parse_address(context, buf, &low); + if(ret) + return ret; + if(low.len != 1) { + krb5_free_addresses(context, &low); + return -1; + } + + strsep_copy(&address, "-", buf, sizeof(buf)); + ret = krb5_parse_address(context, buf, &high); + if(ret) { + krb5_free_addresses(context, &low); + return ret; + } + + if(high.len != 1 && high.val[0].addr_type != low.val[0].addr_type) { + krb5_free_addresses(context, &low); + krb5_free_addresses(context, &high); + return -1; + } + + ret = krb5_copy_address(context, &high.val[0], &high0); + if (ret == 0) { + ret = krb5_copy_address(context, &low.val[0], &low0); + if (ret) + krb5_free_address(context, &high0); + } + krb5_free_addresses(context, &low); + krb5_free_addresses(context, &high); + if (ret) + return ret; + } + + krb5_data_alloc(&addr->address, sizeof(*a)); + addr->addr_type = KRB5_ADDRESS_ARANGE; + a = addr->address.data; + + if(krb5_address_order(context, &low0, &high0) < 0) { + a->low = low0; + a->high = high0; + } else { + a->low = high0; + a->high = low0; + } + return 0; +} + +static int +arange_free (krb5_context context, krb5_address *addr) +{ + struct arange *a; + a = addr->address.data; + krb5_free_address(context, &a->low); + krb5_free_address(context, &a->high); + krb5_data_free(&addr->address); + return 0; +} + + +static int +arange_copy (krb5_context context, const krb5_address *inaddr, + krb5_address *outaddr) +{ + krb5_error_code ret; + struct arange *i, *o; + + outaddr->addr_type = KRB5_ADDRESS_ARANGE; + ret = krb5_data_alloc(&outaddr->address, sizeof(*o)); + if(ret) + return ret; + i = inaddr->address.data; + o = outaddr->address.data; + ret = krb5_copy_address(context, &i->low, &o->low); + if(ret) { + krb5_data_free(&outaddr->address); + return ret; + } + ret = krb5_copy_address(context, &i->high, &o->high); + if(ret) { + krb5_free_address(context, &o->low); + krb5_data_free(&outaddr->address); + return ret; + } + return 0; +} + +static int +arange_print_addr (const krb5_address *addr, char *str, size_t len) +{ + struct arange *a; + krb5_error_code ret; + size_t l, size, ret_len; + + a = addr->address.data; + + l = strlcpy(str, "RANGE:", len); + ret_len = l; + if (l > len) + l = len; + size = l; + + ret = krb5_print_address (&a->low, str + size, len - size, &l); + if (ret) + return ret; + ret_len += l; + if (len - size > l) + size += l; + else + size = len; + + l = strlcat(str + size, "-", len - size); + ret_len += l; + if (len - size > l) + size += l; + else + size = len; + + ret = krb5_print_address (&a->high, str + size, len - size, &l); + if (ret) + return ret; + ret_len += l; + + return ret_len; +} + +static int +arange_order_addr(krb5_context context, + const krb5_address *addr1, + const krb5_address *addr2) +{ + int tmp1, tmp2, sign; + struct arange *a; + const krb5_address *a2; + + if(addr1->addr_type == KRB5_ADDRESS_ARANGE) { + a = addr1->address.data; + a2 = addr2; + sign = 1; + } else if(addr2->addr_type == KRB5_ADDRESS_ARANGE) { + a = addr2->address.data; + a2 = addr1; + sign = -1; + } else + abort(); + + if(a2->addr_type == KRB5_ADDRESS_ARANGE) { + struct arange *b = a2->address.data; + tmp1 = krb5_address_order(context, &a->low, &b->low); + if(tmp1 != 0) + return sign * tmp1; + return sign * krb5_address_order(context, &a->high, &b->high); + } else if(a2->addr_type == a->low.addr_type) { + tmp1 = krb5_address_order(context, &a->low, a2); + if(tmp1 > 0) + return sign; + tmp2 = krb5_address_order(context, &a->high, a2); + if(tmp2 < 0) + return -sign; + return 0; + } else { + return sign * (addr1->addr_type - addr2->addr_type); + } +} + +static int +addrport_print_addr (const krb5_address *addr, char *str, size_t len) +{ + krb5_error_code ret; + krb5_address addr1, addr2; + uint16_t port = 0; + size_t ret_len = 0, l, size = 0; + krb5_storage *sp; + + sp = krb5_storage_from_data((krb5_data*)rk_UNCONST(&addr->address)); + /* for totally obscure reasons, these are not in network byteorder */ + krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_LE); + + krb5_storage_seek(sp, 2, SEEK_CUR); /* skip first two bytes */ + krb5_ret_address(sp, &addr1); + + krb5_storage_seek(sp, 2, SEEK_CUR); /* skip two bytes */ + krb5_ret_address(sp, &addr2); + krb5_storage_free(sp); + if(addr2.addr_type == KRB5_ADDRESS_IPPORT && addr2.address.length == 2) { + unsigned long value; + _krb5_get_int(addr2.address.data, &value, 2); + port = value; + } + l = strlcpy(str, "ADDRPORT:", len); + ret_len += l; + if (len > l) + size += l; + else + size = len; + + ret = krb5_print_address(&addr1, str + size, len - size, &l); + if (ret) + return ret; + ret_len += l; + if (len - size > l) + size += l; + else + size = len; + + ret = snprintf(str + size, len - size, ",PORT=%u", port); + if (ret < 0) + return EINVAL; + ret_len += ret; + return ret_len; +} + +static struct addr_operations at[] = { + {AF_INET, KRB5_ADDRESS_INET, sizeof(struct sockaddr_in), + ipv4_sockaddr2addr, + ipv4_sockaddr2port, + ipv4_addr2sockaddr, + ipv4_h_addr2sockaddr, + ipv4_h_addr2addr, + ipv4_uninteresting, ipv4_anyaddr, ipv4_print_addr, ipv4_parse_addr, + NULL, NULL, NULL, ipv4_mask_boundary }, +#ifdef HAVE_IPV6 + {AF_INET6, KRB5_ADDRESS_INET6, sizeof(struct sockaddr_in6), + ipv6_sockaddr2addr, + ipv6_sockaddr2port, + ipv6_addr2sockaddr, + ipv6_h_addr2sockaddr, + ipv6_h_addr2addr, + ipv6_uninteresting, ipv6_anyaddr, ipv6_print_addr, ipv6_parse_addr, + NULL, NULL, NULL, ipv6_mask_boundary } , +#endif + {KRB5_ADDRESS_ADDRPORT, KRB5_ADDRESS_ADDRPORT, 0, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, addrport_print_addr, NULL, NULL, NULL, NULL }, + /* fake address type */ + {KRB5_ADDRESS_ARANGE, KRB5_ADDRESS_ARANGE, sizeof(struct arange), + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + arange_print_addr, arange_parse_addr, + arange_order_addr, arange_free, arange_copy } +}; + +static int num_addrs = sizeof(at) / sizeof(at[0]); + +static size_t max_sockaddr_size = 0; + +/* + * generic functions + */ + +static struct addr_operations * +find_af(int af) +{ + struct addr_operations *a; + + for (a = at; a < at + num_addrs; ++a) + if (af == a->af) + return a; + return NULL; +} + +static struct addr_operations * +find_atype(int atype) +{ + struct addr_operations *a; + + for (a = at; a < at + num_addrs; ++a) + if (atype == a->atype) + return a; + return NULL; +} + +/** + * krb5_sockaddr2address stores a address a "struct sockaddr" sa in + * the krb5_address addr. + * + * @param context a Keberos context + * @param sa a struct sockaddr to extract the address from + * @param addr an Kerberos 5 address to store the address in. + * + * @return Return an error code or 0. + * + * @ingroup krb5_address + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_sockaddr2address (krb5_context context, + const struct sockaddr *sa, krb5_address *addr) +{ + struct addr_operations *a = find_af(sa->sa_family); + if (a == NULL) { + krb5_set_error_string (context, "Address family %d not supported", + sa->sa_family); + return KRB5_PROG_ATYPE_NOSUPP; + } + return (*a->sockaddr2addr)(sa, addr); +} + +/** + * krb5_sockaddr2port extracts a port (if possible) from a "struct + * sockaddr. + * + * @param context a Keberos context + * @param sa a struct sockaddr to extract the port from + * @param port a pointer to an int16_t store the port in. + * + * @return Return an error code or 0. Will return + * KRB5_PROG_ATYPE_NOSUPP in case address type is not supported. + * + * @ingroup krb5_address + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_sockaddr2port (krb5_context context, + const struct sockaddr *sa, int16_t *port) +{ + struct addr_operations *a = find_af(sa->sa_family); + if (a == NULL) { + krb5_set_error_string (context, "Address family %d not supported", + sa->sa_family); + return KRB5_PROG_ATYPE_NOSUPP; + } + return (*a->sockaddr2port)(sa, port); +} + +/** + * krb5_addr2sockaddr sets the "struct sockaddr sockaddr" from addr + * and port. The argument sa_size should initially contain the size of + * the sa and after the call, it will contain the actual length of the + * address. In case of the sa is too small to fit the whole address, + * the up to *sa_size will be stored, and then *sa_size will be set to + * the required length. + * + * @param context a Keberos context + * @param addr the address to copy the from + * @param sa the struct sockaddr that will be filled in + * @param sa_size pointer to length of sa, and after the call, it will + * contain the actual length of the address. + * @param port set port in sa. + * + * @return Return an error code or 0. Will return + * KRB5_PROG_ATYPE_NOSUPP in case address type is not supported. + * + * @ingroup krb5_address + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_addr2sockaddr (krb5_context context, + const krb5_address *addr, + struct sockaddr *sa, + krb5_socklen_t *sa_size, + int port) +{ + struct addr_operations *a = find_atype(addr->addr_type); + + if (a == NULL) { + krb5_set_error_string (context, "Address type %d not supported", + addr->addr_type); + return KRB5_PROG_ATYPE_NOSUPP; + } + if (a->addr2sockaddr == NULL) { + krb5_set_error_string (context, + "Can't convert address type %d to sockaddr", + addr->addr_type); + return KRB5_PROG_ATYPE_NOSUPP; + } + (*a->addr2sockaddr)(addr, sa, sa_size, port); + return 0; +} + +/** + * krb5_max_sockaddr_size returns the max size of the .Li struct + * sockaddr that the Kerberos library will return. + * + * @return Return an size_t of the maximum struct sockaddr. + * + * @ingroup krb5_address + */ + +size_t KRB5_LIB_FUNCTION +krb5_max_sockaddr_size (void) +{ + if (max_sockaddr_size == 0) { + struct addr_operations *a; + + for(a = at; a < at + num_addrs; ++a) + max_sockaddr_size = max(max_sockaddr_size, a->max_sockaddr_size); + } + return max_sockaddr_size; +} + +/** + * krb5_sockaddr_uninteresting returns TRUE for all .Fa sa that the + * kerberos library thinks are uninteresting. One example are link + * local addresses. + * + * @param sa pointer to struct sockaddr that might be interesting. + * + * @return Return a non zero for uninteresting addresses. + * + * @ingroup krb5_address + */ + +krb5_boolean KRB5_LIB_FUNCTION +krb5_sockaddr_uninteresting(const struct sockaddr *sa) +{ + struct addr_operations *a = find_af(sa->sa_family); + if (a == NULL || a->uninteresting == NULL) + return TRUE; + return (*a->uninteresting)(sa); +} + +/** + * krb5_h_addr2sockaddr initializes a "struct sockaddr sa" from af and + * the "struct hostent" (see gethostbyname(3) ) h_addr_list + * component. The argument sa_size should initially contain the size + * of the sa, and after the call, it will contain the actual length of + * the address. + * + * @param context a Keberos context + * @param af addresses + * @param addr address + * @param sa returned struct sockaddr + * @param sa_size size of sa + * @param port port to set in sa. + * + * @return Return an error code or 0. + * + * @ingroup krb5_address + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_h_addr2sockaddr (krb5_context context, + int af, + const char *addr, struct sockaddr *sa, + krb5_socklen_t *sa_size, + int port) +{ + struct addr_operations *a = find_af(af); + if (a == NULL) { + krb5_set_error_string (context, "Address family %d not supported", af); + return KRB5_PROG_ATYPE_NOSUPP; + } + (*a->h_addr2sockaddr)(addr, sa, sa_size, port); + return 0; +} + +/** + * krb5_h_addr2addr works like krb5_h_addr2sockaddr with the exception + * that it operates on a krb5_address instead of a struct sockaddr. + * + * @param context a Keberos context + * @param af address family + * @param haddr host address from struct hostent. + * @param addr returned krb5_address. + * + * @return Return an error code or 0. + * + * @ingroup krb5_address + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_h_addr2addr (krb5_context context, + int af, + const char *haddr, krb5_address *addr) +{ + struct addr_operations *a = find_af(af); + if (a == NULL) { + krb5_set_error_string (context, "Address family %d not supported", af); + return KRB5_PROG_ATYPE_NOSUPP; + } + return (*a->h_addr2addr)(haddr, addr); +} + +/** + * krb5_anyaddr fills in a "struct sockaddr sa" that can be used to + * bind(2) to. The argument sa_size should initially contain the size + * of the sa, and after the call, it will contain the actual length + * of the address. + * + * @param context a Keberos context + * @param af address family + * @param sa sockaddr + * @param sa_size lenght of sa. + * @param port for to fill into sa. + * + * @return Return an error code or 0. + * + * @ingroup krb5_address + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_anyaddr (krb5_context context, + int af, + struct sockaddr *sa, + krb5_socklen_t *sa_size, + int port) +{ + struct addr_operations *a = find_af (af); + + if (a == NULL) { + krb5_set_error_string (context, "Address family %d not supported", af); + return KRB5_PROG_ATYPE_NOSUPP; + } + + (*a->anyaddr)(sa, sa_size, port); + return 0; +} + +/** + * krb5_print_address prints the address in addr to the string string + * that have the length len. If ret_len is not NULL, it will be filled + * with the length of the string if size were unlimited (not including + * the final NUL) . + * + * @param addr address to be printed + * @param str pointer string to print the address into + * @param len length that will fit into area pointed to by "str". + * @param ret_len return length the str. + * + * @return Return an error code or 0. + * + * @ingroup krb5_address + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_print_address (const krb5_address *addr, + char *str, size_t len, size_t *ret_len) +{ + struct addr_operations *a = find_atype(addr->addr_type); + int ret; + + if (a == NULL || a->print_addr == NULL) { + char *s; + int l; + int i; + + s = str; + l = snprintf(s, len, "TYPE_%d:", addr->addr_type); + if (l < 0 || l >= len) + return EINVAL; + s += l; + len -= l; + for(i = 0; i < addr->address.length; i++) { + l = snprintf(s, len, "%02x", ((char*)addr->address.data)[i]); + if (l < 0 || l >= len) + return EINVAL; + len -= l; + s += l; + } + if(ret_len != NULL) + *ret_len = s - str; + return 0; + } + ret = (*a->print_addr)(addr, str, len); + if (ret < 0) + return EINVAL; + if(ret_len != NULL) + *ret_len = ret; + return 0; +} + +/** + * krb5_parse_address returns the resolved hostname in string to the + * krb5_addresses addresses . + * + * @param context a Keberos context + * @param string + * @param addresses + * + * @return Return an error code or 0. + * + * @ingroup krb5_address + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_parse_address(krb5_context context, + const char *string, + krb5_addresses *addresses) +{ + int i, n; + struct addrinfo *ai, *a; + int error; + int save_errno; + + addresses->len = 0; + addresses->val = NULL; + + for(i = 0; i < num_addrs; i++) { + if(at[i].parse_addr) { + krb5_address addr; + if((*at[i].parse_addr)(context, string, &addr) == 0) { + ALLOC_SEQ(addresses, 1); + if (addresses->val == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + addresses->val[0] = addr; + return 0; + } + } + } + + error = getaddrinfo (string, NULL, NULL, &ai); + if (error) { + save_errno = errno; + krb5_set_error_string (context, "%s: %s", string, gai_strerror(error)); + return krb5_eai_to_heim_errno(error, save_errno); + } + + n = 0; + for (a = ai; a != NULL; a = a->ai_next) + ++n; + + ALLOC_SEQ(addresses, n); + if (addresses->val == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + freeaddrinfo(ai); + return ENOMEM; + } + + addresses->len = 0; + for (a = ai, i = 0; a != NULL; a = a->ai_next) { + if (krb5_sockaddr2address (context, ai->ai_addr, &addresses->val[i])) + continue; + if(krb5_address_search(context, &addresses->val[i], addresses)) + continue; + addresses->len = i; + i++; + } + freeaddrinfo (ai); + return 0; +} + +/** + * krb5_address_order compares the addresses addr1 and addr2 so that + * it can be used for sorting addresses. If the addresses are the same + * address krb5_address_order will return 0. Behavies like memcmp(2). + * + * @param context a Keberos context + * @param addr1 krb5_address to compare + * @param addr2 krb5_address to compare + * + * @return < 0 if address addr1 in "less" then addr2. 0 if addr1 and + * addr2 is the same address, > 0 if addr2 is "less" then addr1. + * + * @ingroup krb5_address + */ + +int KRB5_LIB_FUNCTION +krb5_address_order(krb5_context context, + const krb5_address *addr1, + const krb5_address *addr2) +{ + /* this sucks; what if both addresses have order functions, which + should we call? this works for now, though */ + struct addr_operations *a; + a = find_atype(addr1->addr_type); + if(a == NULL) { + krb5_set_error_string (context, "Address family %d not supported", + addr1->addr_type); + return KRB5_PROG_ATYPE_NOSUPP; + } + if(a->order_addr != NULL) + return (*a->order_addr)(context, addr1, addr2); + a = find_atype(addr2->addr_type); + if(a == NULL) { + krb5_set_error_string (context, "Address family %d not supported", + addr2->addr_type); + return KRB5_PROG_ATYPE_NOSUPP; + } + if(a->order_addr != NULL) + return (*a->order_addr)(context, addr1, addr2); + + if(addr1->addr_type != addr2->addr_type) + return addr1->addr_type - addr2->addr_type; + if(addr1->address.length != addr2->address.length) + return addr1->address.length - addr2->address.length; + return memcmp (addr1->address.data, + addr2->address.data, + addr1->address.length); +} + +/** + * krb5_address_compare compares the addresses addr1 and addr2. + * Returns TRUE if the two addresses are the same. + * + * @param context a Keberos context + * @param addr1 address to compare + * @param addr2 address to compare + * + * @return Return an TRUE is the address are the same FALSE if not + * + * @ingroup krb5_address + */ + +krb5_boolean KRB5_LIB_FUNCTION +krb5_address_compare(krb5_context context, + const krb5_address *addr1, + const krb5_address *addr2) +{ + return krb5_address_order (context, addr1, addr2) == 0; +} + +/** + * krb5_address_search checks if the address addr is a member of the + * address set list addrlist . + * + * @param context a Keberos context. + * @param addr address to search for. + * @param addrlist list of addresses to look in for addr. + * + * @return Return an error code or 0. + * + * @ingroup krb5_address + */ + +krb5_boolean KRB5_LIB_FUNCTION +krb5_address_search(krb5_context context, + const krb5_address *addr, + const krb5_addresses *addrlist) +{ + int i; + + for (i = 0; i < addrlist->len; ++i) + if (krb5_address_compare (context, addr, &addrlist->val[i])) + return TRUE; + return FALSE; +} + +/** + * krb5_free_address frees the data stored in the address that is + * alloced with any of the krb5_address functions. + * + * @param context a Keberos context + * @param address addresss to be freed. + * + * @return Return an error code or 0. + * + * @ingroup krb5_address + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_free_address(krb5_context context, + krb5_address *address) +{ + struct addr_operations *a = find_atype (address->addr_type); + if(a != NULL && a->free_addr != NULL) + return (*a->free_addr)(context, address); + krb5_data_free (&address->address); + memset(address, 0, sizeof(*address)); + return 0; +} + +/** + * krb5_free_addresses frees the data stored in the address that is + * alloced with any of the krb5_address functions. + * + * @param context a Keberos context + * @param addresses addressses to be freed. + * + * @return Return an error code or 0. + * + * @ingroup krb5_address + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_free_addresses(krb5_context context, + krb5_addresses *addresses) +{ + int i; + for(i = 0; i < addresses->len; i++) + krb5_free_address(context, &addresses->val[i]); + free(addresses->val); + addresses->len = 0; + addresses->val = NULL; + return 0; +} + +/** + * krb5_copy_address copies the content of address + * inaddr to outaddr. + * + * @param context a Keberos context + * @param inaddr pointer to source address + * @param outaddr pointer to destination address + * + * @return Return an error code or 0. + * + * @ingroup krb5_address + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_address(krb5_context context, + const krb5_address *inaddr, + krb5_address *outaddr) +{ + struct addr_operations *a = find_af (inaddr->addr_type); + if(a != NULL && a->copy_addr != NULL) + return (*a->copy_addr)(context, inaddr, outaddr); + return copy_HostAddress(inaddr, outaddr); +} + +/** + * krb5_copy_addresses copies the content of addresses + * inaddr to outaddr. + * + * @param context a Keberos context + * @param inaddr pointer to source addresses + * @param outaddr pointer to destination addresses + * + * @return Return an error code or 0. + * + * @ingroup krb5_address + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_addresses(krb5_context context, + const krb5_addresses *inaddr, + krb5_addresses *outaddr) +{ + int i; + ALLOC_SEQ(outaddr, inaddr->len); + if(inaddr->len > 0 && outaddr->val == NULL) + return ENOMEM; + for(i = 0; i < inaddr->len; i++) + krb5_copy_address(context, &inaddr->val[i], &outaddr->val[i]); + return 0; +} + +/** + * krb5_append_addresses adds the set of addresses in source to + * dest. While copying the addresses, duplicates are also sorted out. + * + * @param context a Keberos context + * @param dest destination of copy operation + * @param source adresses that are going to be added to dest + * + * @return Return an error code or 0. + * + * @ingroup krb5_address + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_append_addresses(krb5_context context, + krb5_addresses *dest, + const krb5_addresses *source) +{ + krb5_address *tmp; + krb5_error_code ret; + int i; + if(source->len > 0) { + tmp = realloc(dest->val, (dest->len + source->len) * sizeof(*tmp)); + if(tmp == NULL) { + krb5_set_error_string(context, "realloc: out of memory"); + return ENOMEM; + } + dest->val = tmp; + for(i = 0; i < source->len; i++) { + /* skip duplicates */ + if(krb5_address_search(context, &source->val[i], dest)) + continue; + ret = krb5_copy_address(context, + &source->val[i], + &dest->val[dest->len]); + if(ret) + return ret; + dest->len++; + } + } + return 0; +} + +/** + * Create an address of type KRB5_ADDRESS_ADDRPORT from (addr, port) + * + * @param context a Keberos context + * @param res built address from addr/port + * @param addr address to use + * @param port port to use + * + * @return Return an error code or 0. + * + * @ingroup krb5_address + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_make_addrport (krb5_context context, + krb5_address **res, const krb5_address *addr, int16_t port) +{ + krb5_error_code ret; + size_t len = addr->address.length + 2 + 4 * 4; + u_char *p; + + *res = malloc (sizeof(**res)); + if (*res == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + (*res)->addr_type = KRB5_ADDRESS_ADDRPORT; + ret = krb5_data_alloc (&(*res)->address, len); + if (ret) { + krb5_set_error_string(context, "malloc: out of memory"); + free (*res); + *res = NULL; + return ret; + } + p = (*res)->address.data; + *p++ = 0; + *p++ = 0; + *p++ = (addr->addr_type ) & 0xFF; + *p++ = (addr->addr_type >> 8) & 0xFF; + + *p++ = (addr->address.length ) & 0xFF; + *p++ = (addr->address.length >> 8) & 0xFF; + *p++ = (addr->address.length >> 16) & 0xFF; + *p++ = (addr->address.length >> 24) & 0xFF; + + memcpy (p, addr->address.data, addr->address.length); + p += addr->address.length; + + *p++ = 0; + *p++ = 0; + *p++ = (KRB5_ADDRESS_IPPORT ) & 0xFF; + *p++ = (KRB5_ADDRESS_IPPORT >> 8) & 0xFF; + + *p++ = (2 ) & 0xFF; + *p++ = (2 >> 8) & 0xFF; + *p++ = (2 >> 16) & 0xFF; + *p++ = (2 >> 24) & 0xFF; + + memcpy (p, &port, 2); + p += 2; + + return 0; +} + +/** + * Calculate the boundary addresses of `inaddr'/`prefixlen' and store + * them in `low' and `high'. + * + * @param context a Keberos context + * @param inaddr address in prefixlen that the bondery searched + * @param prefixlen width of boundery + * @param low lowest address + * @param high highest address + * + * @return Return an error code or 0. + * + * @ingroup krb5_address + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_address_prefixlen_boundary(krb5_context context, + const krb5_address *inaddr, + unsigned long prefixlen, + krb5_address *low, + krb5_address *high) +{ + struct addr_operations *a = find_atype (inaddr->addr_type); + if(a != NULL && a->mask_boundary != NULL) + return (*a->mask_boundary)(context, inaddr, prefixlen, low, high); + krb5_set_error_string(context, "Address family %d doesn't support " + "address mask operation", inaddr->addr_type); + return KRB5_PROG_ATYPE_NOSUPP; +} diff --git a/lib/krb5/aes-test.c b/lib/krb5/aes-test.c new file mode 100644 index 0000000..82b3431 --- /dev/null +++ b/lib/krb5/aes-test.c @@ -0,0 +1,778 @@ +/* + * Copyright (c) 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include "krb5_locl.h" +#include <hex.h> +#include <err.h> + +#ifdef HAVE_OPENSSL +#include <openssl/evp.h> +#endif + +RCSID("$Id: aes-test.c 18301 2006-10-07 13:50:34Z lha $"); + +static int verbose = 0; + +static void +hex_dump_data(const void *data, size_t length) +{ + char *p; + + hex_encode(data, length, &p); + printf("%s\n", p); + free(p); +} + +struct { + char *password; + char *salt; + int saltlen; + int iterations; + krb5_enctype enctype; + size_t keylen; + char *pbkdf2; + char *key; +} keys[] = { + { + "password", "ATHENA.MIT.EDUraeburn", -1, + 1, + ETYPE_AES128_CTS_HMAC_SHA1_96, 16, + "\xcd\xed\xb5\x28\x1b\xb2\xf8\x01\x56\x5a\x11\x22\xb2\x56\x35\x15", + "\x42\x26\x3c\x6e\x89\xf4\xfc\x28\xb8\xdf\x68\xee\x09\x79\x9f\x15" + }, + { + "password", "ATHENA.MIT.EDUraeburn", -1, + 1, + ETYPE_AES256_CTS_HMAC_SHA1_96, 32, + "\xcd\xed\xb5\x28\x1b\xb2\xf8\x01\x56\x5a\x11\x22\xb2\x56\x35\x15" + "\x0a\xd1\xf7\xa0\x4b\xb9\xf3\xa3\x33\xec\xc0\xe2\xe1\xf7\x08\x37", + "\xfe\x69\x7b\x52\xbc\x0d\x3c\xe1\x44\x32\xba\x03\x6a\x92\xe6\x5b" + "\xbb\x52\x28\x09\x90\xa2\xfa\x27\x88\x39\x98\xd7\x2a\xf3\x01\x61" + }, + { + "password", "ATHENA.MIT.EDUraeburn", -1, + 2, + ETYPE_AES128_CTS_HMAC_SHA1_96, 16, + "\x01\xdb\xee\x7f\x4a\x9e\x24\x3e\x98\x8b\x62\xc7\x3c\xda\x93\x5d", + "\xc6\x51\xbf\x29\xe2\x30\x0a\xc2\x7f\xa4\x69\xd6\x93\xbd\xda\x13" + }, + { + "password", "ATHENA.MIT.EDUraeburn", -1, + 2, + ETYPE_AES256_CTS_HMAC_SHA1_96, 32, + "\x01\xdb\xee\x7f\x4a\x9e\x24\x3e\x98\x8b\x62\xc7\x3c\xda\x93\x5d" + "\xa0\x53\x78\xb9\x32\x44\xec\x8f\x48\xa9\x9e\x61\xad\x79\x9d\x86", + "\xa2\xe1\x6d\x16\xb3\x60\x69\xc1\x35\xd5\xe9\xd2\xe2\x5f\x89\x61" + "\x02\x68\x56\x18\xb9\x59\x14\xb4\x67\xc6\x76\x22\x22\x58\x24\xff" + }, + { + "password", "ATHENA.MIT.EDUraeburn", -1, + 1200, + ETYPE_AES128_CTS_HMAC_SHA1_96, 16, + "\x5c\x08\xeb\x61\xfd\xf7\x1e\x4e\x4e\xc3\xcf\x6b\xa1\xf5\x51\x2b", + "\x4c\x01\xcd\x46\xd6\x32\xd0\x1e\x6d\xbe\x23\x0a\x01\xed\x64\x2a" + }, + { + "password", "ATHENA.MIT.EDUraeburn", -1, + 1200, + ETYPE_AES256_CTS_HMAC_SHA1_96, 32, + "\x5c\x08\xeb\x61\xfd\xf7\x1e\x4e\x4e\xc3\xcf\x6b\xa1\xf5\x51\x2b" + "\xa7\xe5\x2d\xdb\xc5\xe5\x14\x2f\x70\x8a\x31\xe2\xe6\x2b\x1e\x13", + "\x55\xa6\xac\x74\x0a\xd1\x7b\x48\x46\x94\x10\x51\xe1\xe8\xb0\xa7" + "\x54\x8d\x93\xb0\xab\x30\xa8\xbc\x3f\xf1\x62\x80\x38\x2b\x8c\x2a" + }, + { + "password", "\x12\x34\x56\x78\x78\x56\x34\x12", 8, + 5, + ETYPE_AES128_CTS_HMAC_SHA1_96, 16, + "\xd1\xda\xa7\x86\x15\xf2\x87\xe6\xa1\xc8\xb1\x20\xd7\x06\x2a\x49", + "\xe9\xb2\x3d\x52\x27\x37\x47\xdd\x5c\x35\xcb\x55\xbe\x61\x9d\x8e" + }, + { + "password", "\x12\x34\x56\x78\x78\x56\x34\x12", 8, + 5, + ETYPE_AES256_CTS_HMAC_SHA1_96, 32, + "\xd1\xda\xa7\x86\x15\xf2\x87\xe6\xa1\xc8\xb1\x20\xd7\x06\x2a\x49" + "\x3f\x98\xd2\x03\xe6\xbe\x49\xa6\xad\xf4\xfa\x57\x4b\x6e\x64\xee", + "\x97\xa4\xe7\x86\xbe\x20\xd8\x1a\x38\x2d\x5e\xbc\x96\xd5\x90\x9c" + "\xab\xcd\xad\xc8\x7c\xa4\x8f\x57\x45\x04\x15\x9f\x16\xc3\x6e\x31" + }, + { + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + "pass phrase equals block size", -1, + 1200, + ETYPE_AES128_CTS_HMAC_SHA1_96, 16, + "\x13\x9c\x30\xc0\x96\x6b\xc3\x2b\xa5\x5f\xdb\xf2\x12\x53\x0a\xc9", + "\x59\xd1\xbb\x78\x9a\x82\x8b\x1a\xa5\x4e\xf9\xc2\x88\x3f\x69\xed" + }, + { + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + "pass phrase equals block size", -1, + 1200, + ETYPE_AES256_CTS_HMAC_SHA1_96, 32, + "\x13\x9c\x30\xc0\x96\x6b\xc3\x2b\xa5\x5f\xdb\xf2\x12\x53\x0a\xc9" + "\xc5\xec\x59\xf1\xa4\x52\xf5\xcc\x9a\xd9\x40\xfe\xa0\x59\x8e\xd1", + "\x89\xad\xee\x36\x08\xdb\x8b\xc7\x1f\x1b\xfb\xfe\x45\x94\x86\xb0" + "\x56\x18\xb7\x0c\xba\xe2\x20\x92\x53\x4e\x56\xc5\x53\xba\x4b\x34" + }, + { + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + "pass phrase exceeds block size", -1, + 1200, + ETYPE_AES128_CTS_HMAC_SHA1_96, 16, + "\x9c\xca\xd6\xd4\x68\x77\x0c\xd5\x1b\x10\xe6\xa6\x87\x21\xbe\x61", + "\xcb\x80\x05\xdc\x5f\x90\x17\x9a\x7f\x02\x10\x4c\x00\x18\x75\x1d" + }, + { + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + "pass phrase exceeds block size", -1, + 1200, + ETYPE_AES256_CTS_HMAC_SHA1_96, 32, + "\x9c\xca\xd6\xd4\x68\x77\x0c\xd5\x1b\x10\xe6\xa6\x87\x21\xbe\x61" + "\x1a\x8b\x4d\x28\x26\x01\xdb\x3b\x36\xbe\x92\x46\x91\x5e\xc8\x2a", + "\xd7\x8c\x5c\x9c\xb8\x72\xa8\xc9\xda\xd4\x69\x7f\x0b\xb5\xb2\xd2" + "\x14\x96\xc8\x2b\xeb\x2c\xae\xda\x21\x12\xfc\xee\xa0\x57\x40\x1b" + + }, + { + "\xf0\x9d\x84\x9e" /* g-clef */, "EXAMPLE.COMpianist", -1, + 50, + ETYPE_AES128_CTS_HMAC_SHA1_96, 16, + "\x6b\x9c\xf2\x6d\x45\x45\x5a\x43\xa5\xb8\xbb\x27\x6a\x40\x3b\x39", + "\xf1\x49\xc1\xf2\xe1\x54\xa7\x34\x52\xd4\x3e\x7f\xe6\x2a\x56\xe5" + }, + { + "\xf0\x9d\x84\x9e" /* g-clef */, "EXAMPLE.COMpianist", -1, + 50, + ETYPE_AES256_CTS_HMAC_SHA1_96, 32, + "\x6b\x9c\xf2\x6d\x45\x45\x5a\x43\xa5\xb8\xbb\x27\x6a\x40\x3b\x39" + "\xe7\xfe\x37\xa0\xc4\x1e\x02\xc2\x81\xff\x30\x69\xe1\xe9\x4f\x52", + "\x4b\x6d\x98\x39\xf8\x44\x06\xdf\x1f\x09\xcc\x16\x6d\xb4\xb8\x3c" + "\x57\x18\x48\xb7\x84\xa3\xd6\xbd\xc3\x46\x58\x9a\x3e\x39\x3f\x9e" + }, + { + "foo", "", -1, + 0, + ETYPE_ARCFOUR_HMAC_MD5, 16, + NULL, + "\xac\x8e\x65\x7f\x83\xdf\x82\xbe\xea\x5d\x43\xbd\xaf\x78\x00\xcc" + }, + { + "test", "", -1, + 0, + ETYPE_ARCFOUR_HMAC_MD5, 16, + NULL, + "\x0c\xb6\x94\x88\x05\xf7\x97\xbf\x2a\x82\x80\x79\x73\xb8\x95\x37" + } +}; + +static int +string_to_key_test(krb5_context context) +{ + krb5_data password, opaque; + krb5_error_code ret; + krb5_salt salt; + int i, val = 0; + char iter[4]; + + for (i = 0; i < sizeof(keys)/sizeof(keys[0]); i++) { + + password.data = keys[i].password; + password.length = strlen(password.data); + + salt.salttype = KRB5_PW_SALT; + salt.saltvalue.data = keys[i].salt; + if (keys[i].saltlen == -1) + salt.saltvalue.length = strlen(salt.saltvalue.data); + else + salt.saltvalue.length = keys[i].saltlen; + + opaque.data = iter; + opaque.length = sizeof(iter); + _krb5_put_int(iter, keys[i].iterations, 4); + + if (keys[i].pbkdf2) { + unsigned char keyout[32]; + + if (keys[i].keylen > sizeof(keyout)) + abort(); + + PKCS5_PBKDF2_HMAC_SHA1(password.data, password.length, + salt.saltvalue.data, salt.saltvalue.length, + keys[i].iterations, + keys[i].keylen, keyout); + + if (memcmp(keyout, keys[i].pbkdf2, keys[i].keylen) != 0) { + krb5_warnx(context, "%d: pbkdf2", i); + val = 1; + continue; + } + + if (verbose) { + printf("PBKDF2:\n"); + hex_dump_data(keyout, keys[i].keylen); + } + } + + { + krb5_keyblock key; + + ret = krb5_string_to_key_data_salt_opaque (context, + keys[i].enctype, + password, + salt, + opaque, + &key); + if (ret) { + krb5_warn(context, ret, "%d: string_to_key_data_salt_opaque", + i); + val = 1; + continue; + } + + if (key.keyvalue.length != keys[i].keylen) { + krb5_warnx(context, "%d: key wrong length (%lu/%lu)", + i, (unsigned long)key.keyvalue.length, + (unsigned long)keys[i].keylen); + val = 1; + continue; + } + + if (memcmp(key.keyvalue.data, keys[i].key, keys[i].keylen) != 0) { + krb5_warnx(context, "%d: key wrong", i); + val = 1; + continue; + } + + if (verbose) { + printf("key:\n"); + hex_dump_data(key.keyvalue.data, key.keyvalue.length); + } + krb5_free_keyblock_contents(context, &key); + } + } + return val; +} + +struct enc_test { + size_t len; + char *input; + char *output; + char *nextiv; +}; + +struct enc_test encs1[] = { + { + 17, + "\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65" + "\x20", + "\xc6\x35\x35\x68\xf2\xbf\x8c\xb4\xd8\xa5\x80\x36\x2d\xa7\xff\x7f" + "\x97", + "\xc6\x35\x35\x68\xf2\xbf\x8c\xb4\xd8\xa5\x80\x36\x2d\xa7\xff\x7f" + }, + { + 31, + "\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65" + "\x20\x47\x65\x6e\x65\x72\x61\x6c\x20\x47\x61\x75\x27\x73\x20", + "\xfc\x00\x78\x3e\x0e\xfd\xb2\xc1\xd4\x45\xd4\xc8\xef\xf7\xed\x22" + "\x97\x68\x72\x68\xd6\xec\xcc\xc0\xc0\x7b\x25\xe2\x5e\xcf\xe5", + "\xfc\x00\x78\x3e\x0e\xfd\xb2\xc1\xd4\x45\xd4\xc8\xef\xf7\xed\x22" + }, + { + 32, + "\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65" + "\x20\x47\x65\x6e\x65\x72\x61\x6c\x20\x47\x61\x75\x27\x73\x20\x43", + "\x39\x31\x25\x23\xa7\x86\x62\xd5\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8" + "\x97\x68\x72\x68\xd6\xec\xcc\xc0\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84", + "\x39\x31\x25\x23\xa7\x86\x62\xd5\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8" + }, + { + 47, + "\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65" + "\x20\x47\x65\x6e\x65\x72\x61\x6c\x20\x47\x61\x75\x27\x73\x20\x43" + "\x68\x69\x63\x6b\x65\x6e\x2c\x20\x70\x6c\x65\x61\x73\x65\x2c", + "\x97\x68\x72\x68\xd6\xec\xcc\xc0\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84" + "\xb3\xff\xfd\x94\x0c\x16\xa1\x8c\x1b\x55\x49\xd2\xf8\x38\x02\x9e" + "\x39\x31\x25\x23\xa7\x86\x62\xd5\xbe\x7f\xcb\xcc\x98\xeb\xf5", + "\xb3\xff\xfd\x94\x0c\x16\xa1\x8c\x1b\x55\x49\xd2\xf8\x38\x02\x9e" + }, + { + 48, + "\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65" + "\x20\x47\x65\x6e\x65\x72\x61\x6c\x20\x47\x61\x75\x27\x73\x20\x43" + "\x68\x69\x63\x6b\x65\x6e\x2c\x20\x70\x6c\x65\x61\x73\x65\x2c\x20", + "\x97\x68\x72\x68\xd6\xec\xcc\xc0\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84" + "\x9d\xad\x8b\xbb\x96\xc4\xcd\xc0\x3b\xc1\x03\xe1\xa1\x94\xbb\xd8" + "\x39\x31\x25\x23\xa7\x86\x62\xd5\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8", + "\x9d\xad\x8b\xbb\x96\xc4\xcd\xc0\x3b\xc1\x03\xe1\xa1\x94\xbb\xd8" + }, + { + 64, + "\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65" + "\x20\x47\x65\x6e\x65\x72\x61\x6c\x20\x47\x61\x75\x27\x73\x20\x43" + "\x68\x69\x63\x6b\x65\x6e\x2c\x20\x70\x6c\x65\x61\x73\x65\x2c\x20" + "\x61\x6e\x64\x20\x77\x6f\x6e\x74\x6f\x6e\x20\x73\x6f\x75\x70\x2e", + "\x97\x68\x72\x68\xd6\xec\xcc\xc0\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84" + "\x39\x31\x25\x23\xa7\x86\x62\xd5\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8" + "\x48\x07\xef\xe8\x36\xee\x89\xa5\x26\x73\x0d\xbc\x2f\x7b\xc8\x40" + "\x9d\xad\x8b\xbb\x96\xc4\xcd\xc0\x3b\xc1\x03\xe1\xa1\x94\xbb\xd8", + "\x48\x07\xef\xe8\x36\xee\x89\xa5\x26\x73\x0d\xbc\x2f\x7b\xc8\x40" + } +}; + + +struct enc_test encs2[] = { + { + 17, + "\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65" + "\x20", + "\x5c\x13\x26\x27\xc4\xcb\xca\x04\x14\x43\x8a\xb5\x97\x97\x7c\x10" + "\x16" + }, + { + 31, + "\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65" + "\x20\x47\x65\x6e\x65\x72\x61\x6c\x20\x47\x61\x75\x27\x73\x20", + "\x16\xb3\xd8\xe5\xcd\x93\xe6\x2c\x28\x70\xa0\x36\x6e\x9a\xb9\x74" + "\x16\xc1\xee\xdf\x39\xc8\x3f\xfb\xc5\xf6\x72\xe9\xc1\x6e\x53" + }, + { + 32, + "\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65" + "\x20\x47\x65\x6e\x65\x72\x61\x6c\x20\x47\x61\x75\x27\x73\x20\x43", + "\x69\xde\xce\x59\x83\x6a\x82\xe1\xcd\x21\x93\xd0\x9e\x2a\xff\xc8" + "\x16\xc1\xee\xdf\x39\xc8\x3f\xfb\xc5\xf6\x72\xe9\xc1\x6e\x53\x0c" + }, + { + 47, + "\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65" + "\x20\x47\x65\x6e\x65\x72\x61\x6c\x20\x47\x61\x75\x27\x73\x20\x43" + "\x68\x69\x63\x6b\x65\x6e\x2c\x20\x70\x6c\x65\x61\x73\x65\x2c", + "\x16\xc1\xee\xdf\x39\xc8\x3f\xfb\xc5\xf6\x72\xe9\xc1\x6e\x53\x0c" + "\xe5\x56\xb4\x88\x41\xb9\xde\x27\xf0\x07\xa1\x6e\x89\x94\x47\xf1" + "\x69\xde\xce\x59\x83\x6a\x82\xe1\xcd\x21\x93\xd0\x9e\x2a\xff" + }, + { + 48, + "\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65" + "\x20\x47\x65\x6e\x65\x72\x61\x6c\x20\x47\x61\x75\x27\x73\x20\x43" + "\x68\x69\x63\x6b\x65\x6e\x2c\x20\x70\x6c\x65\x61\x73\x65\x2c\x20", + "\x16\xc1\xee\xdf\x39\xc8\x3f\xfb\xc5\xf6\x72\xe9\xc1\x6e\x53\x0c" + "\xfd\x68\xd1\x56\x32\x23\x7b\xfa\xb0\x09\x86\x3b\x17\x53\xfa\x30" + "\x69\xde\xce\x59\x83\x6a\x82\xe1\xcd\x21\x93\xd0\x9e\x2a\xff\xc8" + }, + { + 64, + "\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65" + "\x20\x47\x65\x6e\x65\x72\x61\x6c\x20\x47\x61\x75\x27\x73\x20\x43" + "\x68\x69\x63\x6b\x65\x6e\x2c\x20\x70\x6c\x65\x61\x73\x65\x2c\x20" + "\x61\x6e\x64\x20\x77\x6f\x6e\x74\x6f\x6e\x20\x73\x6f\x75\x70\x2e", + "\x16\xc1\xee\xdf\x39\xc8\x3f\xfb\xc5\xf6\x72\xe9\xc1\x6e\x53\x0c" + "\x69\xde\xce\x59\x83\x6a\x82\xe1\xcd\x21\x93\xd0\x9e\x2a\xff\xc8" + "\x70\x29\xf2\x6f\x7c\x79\xc1\x77\x91\xad\x94\xb0\x78\x62\x27\x67" + "\xfd\x68\xd1\x56\x32\x23\x7b\xfa\xb0\x09\x86\x3b\x17\x53\xfa\x30" + }, + { + 78, + "\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65" + "\x20\x47\x65\x6e\x65\x72\x61\x6c\x20\x47\x61\x75\x27\x73\x20\x43" + "\x68\x69\x63\x6b\x65\x6e\x2c\x20\x70\x6c\x65\x61\x73\x65\x2c\x20" + "\x61\x6e\x64\x20\x77\x6f\x6e\x74\x6f\x6e\x20\x73\x6f\x75\x70\x2e" + "\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41", + "\x16\xc1\xee\xdf\x39\xc8\x3f\xfb\xc5\xf6\x72\xe9\xc1\x6e\x53\x0c" + "\x69\xde\xce\x59\x83\x6a\x82\xe1\xcd\x21\x93\xd0\x9e\x2a\xff\xc8" + "\xfd\x68\xd1\x56\x32\x23\x7b\xfa\xb0\x09\x86\x3b\x17\x53\xfa\x30" + "\x73\xfb\x2c\x36\x76\xaf\xcf\x31\xff\xe3\x8a\x89\x0c\x7e\x99\x3f" + "\x70\x29\xf2\x6f\x7c\x79\xc1\x77\x91\xad\x94\xb0\x78\x62" + }, + { + 83, + "\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65" + "\x20\x47\x65\x6e\x65\x72\x61\x6c\x20\x47\x61\x75\x27\x73\x20\x43" + "\x68\x69\x63\x6b\x65\x6e\x2c\x20\x70\x6c\x65\x61\x73\x65\x2c\x20" + "\x61\x6e\x64\x20\x77\x6f\x6e\x74\x6f\x6e\x20\x73\x6f\x75\x70\x2e" + "\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41" + "\x41\x41\x41", + "\x16\xc1\xee\xdf\x39\xc8\x3f\xfb\xc5\xf6\x72\xe9\xc1\x6e\x53\x0c" + "\x69\xde\xce\x59\x83\x6a\x82\xe1\xcd\x21\x93\xd0\x9e\x2a\xff\xc8" + "\xfd\x68\xd1\x56\x32\x23\x7b\xfa\xb0\x09\x86\x3b\x17\x53\xfa\x30" + "\x70\x29\xf2\x6f\x7c\x79\xc1\x77\x91\xad\x94\xb0\x78\x62\x27\x67" + "\x65\x39\x3a\xdb\x92\x05\x4d\x4f\x08\xa1\xfa\x59\xda\x56\x58\x0e" + "\x3b\xac\x12" + }, + { + 92, + "\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65" + "\x20\x47\x65\x6e\x65\x72\x61\x6c\x20\x47\x61\x75\x27\x73\x20\x43" + "\x68\x69\x63\x6b\x65\x6e\x2c\x20\x70\x6c\x65\x61\x73\x65\x2c\x20" + "\x61\x6e\x64\x20\x77\x6f\x6e\x74\x6f\x6e\x20\x73\x6f\x75\x70\x2e" + "\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41" + "\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41", + "\x16\xc1\xee\xdf\x39\xc8\x3f\xfb\xc5\xf6\x72\xe9\xc1\x6e\x53\x0c" + "\x69\xde\xce\x59\x83\x6a\x82\xe1\xcd\x21\x93\xd0\x9e\x2a\xff\xc8" + "\xfd\x68\xd1\x56\x32\x23\x7b\xfa\xb0\x09\x86\x3b\x17\x53\xfa\x30" + "\x70\x29\xf2\x6f\x7c\x79\xc1\x77\x91\xad\x94\xb0\x78\x62\x27\x67" + "\x0c\xff\xd7\x63\x50\xf8\x4e\xf9\xec\x56\x1c\x79\xc5\xc8\xfe\x50" + "\x3b\xac\x12\x6e\xd3\x2d\x02\xc4\xe5\x06\x43\x5f" + }, + { + 96, + "\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65" + "\x20\x47\x65\x6e\x65\x72\x61\x6c\x20\x47\x61\x75\x27\x73\x20\x43" + "\x68\x69\x63\x6b\x65\x6e\x2c\x20\x70\x6c\x65\x61\x73\x65\x2c\x20" + "\x61\x6e\x64\x20\x77\x6f\x6e\x74\x6f\x6e\x20\x73\x6f\x75\x70\x2e" + "\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41" + "\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41", + "\x16\xc1\xee\xdf\x39\xc8\x3f\xfb\xc5\xf6\x72\xe9\xc1\x6e\x53\x0c" + "\x69\xde\xce\x59\x83\x6a\x82\xe1\xcd\x21\x93\xd0\x9e\x2a\xff\xc8" + "\xfd\x68\xd1\x56\x32\x23\x7b\xfa\xb0\x09\x86\x3b\x17\x53\xfa\x30" + "\x70\x29\xf2\x6f\x7c\x79\xc1\x77\x91\xad\x94\xb0\x78\x62\x27\x67" + "\x08\x28\x49\xad\xfc\x2d\x8e\x86\xae\x69\xa5\xa8\xd9\x29\x9e\xe4" + "\x3b\xac\x12\x6e\xd3\x2d\x02\xc4\xe5\x06\x43\x5f\x4c\x41\xd1\xb8" + } +}; + + + +char *aes_key1 = + "\x63\x68\x69\x63\x6b\x65\x6e\x20\x74\x65\x72\x69\x79\x61\x6b\x69"; + +char *aes_key2 = + "\x63\x68\x69\x63\x6b\x65\x6e\x20\x74\x65\x72\x69\x79\x61\x6b\x69" + "\x2c\x20\x79\x75\x6d\x6d\x79\x20\x79\x75\x6d\x6d\x79\x21\x21\x21"; + + +static int +samep(int testn, char *type, const void *pp1, const void *pp2, size_t len) +{ + const unsigned char *p1 = pp1, *p2 = pp2; + size_t i; + int val = 1; + + for (i = 0; i < len; i++) { + if (p1[i] != p2[i]) { + if (verbose) + printf("M"); + val = 0; + } else { + if (verbose) + printf("."); + } + } + if (verbose) + printf("\n"); + return val; +} + +static int +encryption_test(krb5_context context, const void *key, size_t keylen, + struct enc_test *enc, int numenc) +{ + unsigned char iv[AES_BLOCK_SIZE]; + int i, val, failed = 0; + AES_KEY ekey, dkey; + unsigned char *p; + + AES_set_encrypt_key(key, keylen, &ekey); + AES_set_decrypt_key(key, keylen, &dkey); + + for (i = 0; i < numenc; i++) { + val = 0; + + if (verbose) + printf("test: %d\n", i); + memset(iv, 0, sizeof(iv)); + + p = malloc(enc[i].len + 1); + if (p == NULL) + krb5_errx(context, 1, "malloc"); + + p[enc[i].len] = '\0'; + + memcpy(p, enc[i].input, enc[i].len); + + _krb5_aes_cts_encrypt(p, p, enc[i].len, + &ekey, iv, AES_ENCRYPT); + + if (p[enc[i].len] != '\0') { + krb5_warnx(context, "%d: encrypt modified off end", i); + val = 1; + } + + if (!samep(i, "cipher", p, enc[i].output, enc[i].len)) { + krb5_warnx(context, "%d: cipher", i); + val = 1; + } + + if (enc[i].nextiv && !samep(i, "iv", iv, enc[i].nextiv, 16)){ /*XXX*/ + krb5_warnx(context, "%d: iv", i); + val = 1; + } + + memset(iv, 0, sizeof(iv)); + + _krb5_aes_cts_encrypt(p, p, enc[i].len, + &dkey, iv, AES_DECRYPT); + + if (p[enc[i].len] != '\0') { + krb5_warnx(context, "%d: decrypt modified off end", i); + val = 1; + } + + if (!samep(i, "clear", p, enc[i].input, enc[i].len)) + val = 1; + + if (enc[i].nextiv && !samep(i, "iv", iv, enc[i].nextiv, 16)){ /*XXX*/ + krb5_warnx(context, "%d: iv", i); + val = 1; + } + + free(p); + + if (val) { + printf("test %d failed\n", i); + failed = 1; + } + val = 0; + } + return failed; +} + +static int +krb_enc(krb5_context context, + krb5_crypto crypto, + unsigned usage, + krb5_data *cipher, + krb5_data *clear) +{ + krb5_data decrypt; + krb5_error_code ret; + + krb5_data_zero(&decrypt); + + ret = krb5_decrypt(context, + crypto, + usage, + cipher->data, + cipher->length, + &decrypt); + + if (ret) { + krb5_warn(context, ret, "krb5_decrypt"); + return ret; + } + + if (decrypt.length != clear->length || + memcmp(decrypt.data, clear->data, decrypt.length) != 0) { + krb5_warnx(context, "clear text not same"); + return EINVAL; + } + + krb5_data_free(&decrypt); + + return 0; +} + +static int +krb_enc_mit(krb5_context context, + krb5_enctype enctype, + krb5_keyblock *key, + unsigned usage, + krb5_data *cipher, + krb5_data *clear) +{ + krb5_error_code ret; + krb5_enc_data e; + krb5_data decrypt; + size_t len; + + e.kvno = 0; + e.enctype = enctype; + e.ciphertext = *cipher; + + ret = krb5_c_decrypt(context, *key, usage, NULL, &e, &decrypt); + if (ret) + return ret; + + if (decrypt.length != clear->length || + memcmp(decrypt.data, clear->data, decrypt.length) != 0) { + krb5_warnx(context, "clear text not same"); + return EINVAL; + } + + krb5_data_free(&decrypt); + + ret = krb5_c_encrypt_length(context, enctype, clear->length, &len); + if (ret) + return ret; + + if (len != cipher->length) { + krb5_warnx(context, "c_encrypt_length wrong %lu != %lu", + (unsigned long)len, (unsigned long)cipher->length); + return EINVAL; + } + + return 0; +} + + +struct { + krb5_enctype enctype; + unsigned usage; + size_t keylen; + void *key; + size_t elen; + void* edata; + size_t plen; + void *pdata; +} krbencs[] = { + { + ETYPE_AES256_CTS_HMAC_SHA1_96, + 7, + 32, + "\x47\x75\x69\x64\x65\x6c\x69\x6e\x65\x73\x20\x74\x6f\x20\x41\x75" + "\x74\x68\x6f\x72\x73\x20\x6f\x66\x20\x49\x6e\x74\x65\x72\x6e\x65", + 44, + "\xcf\x79\x8f\x0d\x76\xf3\xe0\xbe\x8e\x66\x94\x70\xfa\xcc\x9e\x91" + "\xa9\xec\x1c\x5c\x21\xfb\x6e\xef\x1a\x7a\xc8\xc1\xcc\x5a\x95\x24" + "\x6f\x9f\xf4\xd5\xbe\x5d\x59\x97\x44\xd8\x47\xcd", + 16, + "\x54\x68\x69\x73\x20\x69\x73\x20\x61\x20\x74\x65\x73\x74\x2e\x0a" + } +}; + + +static int +krb_enc_test(krb5_context context) +{ + krb5_error_code ret; + krb5_crypto crypto; + krb5_keyblock kb; + krb5_data cipher, plain; + int i, failed = 0; + + for (i = 0; i < sizeof(krbencs)/sizeof(krbencs[0]); i++) { + + kb.keytype = krbencs[i].enctype; + kb.keyvalue.length = krbencs[i].keylen; + kb.keyvalue.data = krbencs[i].key; + + ret = krb5_crypto_init(context, &kb, krbencs[i].enctype, &crypto); + + cipher.length = krbencs[i].elen; + cipher.data = krbencs[i].edata; + plain.length = krbencs[i].plen; + plain.data = krbencs[i].pdata; + + ret = krb_enc(context, crypto, krbencs[i].usage, &cipher, &plain); + + if (ret) { + failed = 1; + printf("krb_enc failed with %d\n", ret); + } + krb5_crypto_destroy(context, crypto); + + ret = krb_enc_mit(context, krbencs[i].enctype, &kb, + krbencs[i].usage, &cipher, &plain); + if (ret) { + failed = 1; + printf("krb_enc_mit failed with %d\n", ret); + } + + } + + return failed; +} + + +static int +random_to_key(krb5_context context) +{ + krb5_error_code ret; + krb5_keyblock key; + + ret = krb5_random_to_key(context, + ETYPE_DES3_CBC_SHA1, + "\x21\x39\x04\x58\x6A\xBD\x7F" + "\x21\x39\x04\x58\x6A\xBD\x7F" + "\x21\x39\x04\x58\x6A\xBD\x7F", + 21, + &key); + if (ret){ + krb5_warn(context, ret, "random_to_key"); + return 1; + } + if (key.keyvalue.length != 24) + return 1; + + if (memcmp(key.keyvalue.data, + "\x20\x38\x04\x58\x6b\xbc\x7f\xc7" + "\x20\x38\x04\x58\x6b\xbc\x7f\xc7" + "\x20\x38\x04\x58\x6b\xbc\x7f\xc7", + 24) != 0) + return 1; + + krb5_free_keyblock_contents(context, &key); + + return 0; +} + + +int +main(int argc, char **argv) +{ + krb5_error_code ret; + krb5_context context; + int val = 0; + + ret = krb5_init_context (&context); + if (ret) + errx (1, "krb5_init_context failed: %d", ret); + + val |= string_to_key_test(context); + + val |= encryption_test(context, aes_key1, 128, + encs1, sizeof(encs1)/sizeof(encs1[0])); + val |= encryption_test(context, aes_key2, 256, + encs2, sizeof(encs2)/sizeof(encs2[0])); + val |= krb_enc_test(context); + val |= random_to_key(context); + + if (verbose && val == 0) + printf("all ok\n"); + if (val) + printf("tests failed\n"); + + krb5_free_context(context); + + return val; +} diff --git a/lib/krb5/aname_to_localname.c b/lib/krb5/aname_to_localname.c new file mode 100644 index 0000000..5800404 --- /dev/null +++ b/lib/krb5/aname_to_localname.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 1997 - 1999, 2002 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <krb5_locl.h> + +RCSID("$Id: aname_to_localname.c 13863 2004-05-25 21:46:46Z lha $"); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_aname_to_localname (krb5_context context, + krb5_const_principal aname, + size_t lnsize, + char *lname) +{ + krb5_error_code ret; + krb5_realm *lrealms, *r; + int valid; + size_t len; + const char *res; + + ret = krb5_get_default_realms (context, &lrealms); + if (ret) + return ret; + + valid = 0; + for (r = lrealms; *r != NULL; ++r) { + if (strcmp (*r, aname->realm) == 0) { + valid = 1; + break; + } + } + krb5_free_host_realm (context, lrealms); + if (valid == 0) + return KRB5_NO_LOCALNAME; + + if (aname->name.name_string.len == 1) + res = aname->name.name_string.val[0]; + else if (aname->name.name_string.len == 2 + && strcmp (aname->name.name_string.val[1], "root") == 0) { + krb5_principal rootprinc; + krb5_boolean userok; + + res = "root"; + + ret = krb5_copy_principal(context, aname, &rootprinc); + if (ret) + return ret; + + userok = krb5_kuserok(context, rootprinc, res); + krb5_free_principal(context, rootprinc); + if (!userok) + return KRB5_NO_LOCALNAME; + + } else + return KRB5_NO_LOCALNAME; + + len = strlen (res); + if (len >= lnsize) + return ERANGE; + strlcpy (lname, res, lnsize); + + return 0; +} diff --git a/lib/krb5/appdefault.c b/lib/krb5/appdefault.c new file mode 100644 index 0000000..b0bb171 --- /dev/null +++ b/lib/krb5/appdefault.c @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2000 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: appdefault.c 14465 2005-01-05 05:40:59Z lukeh $"); + +void KRB5_LIB_FUNCTION +krb5_appdefault_boolean(krb5_context context, const char *appname, + krb5_const_realm realm, const char *option, + krb5_boolean def_val, krb5_boolean *ret_val) +{ + + if(appname == NULL) + appname = getprogname(); + + def_val = krb5_config_get_bool_default(context, NULL, def_val, + "libdefaults", option, NULL); + if(realm != NULL) + def_val = krb5_config_get_bool_default(context, NULL, def_val, + "realms", realm, option, NULL); + + def_val = krb5_config_get_bool_default(context, NULL, def_val, + "appdefaults", + option, + NULL); + if(realm != NULL) + def_val = krb5_config_get_bool_default(context, NULL, def_val, + "appdefaults", + realm, + option, + NULL); + if(appname != NULL) { + def_val = krb5_config_get_bool_default(context, NULL, def_val, + "appdefaults", + appname, + option, + NULL); + if(realm != NULL) + def_val = krb5_config_get_bool_default(context, NULL, def_val, + "appdefaults", + appname, + realm, + option, + NULL); + } + *ret_val = def_val; +} + +void KRB5_LIB_FUNCTION +krb5_appdefault_string(krb5_context context, const char *appname, + krb5_const_realm realm, const char *option, + const char *def_val, char **ret_val) +{ + if(appname == NULL) + appname = getprogname(); + + def_val = krb5_config_get_string_default(context, NULL, def_val, + "libdefaults", option, NULL); + if(realm != NULL) + def_val = krb5_config_get_string_default(context, NULL, def_val, + "realms", realm, option, NULL); + + def_val = krb5_config_get_string_default(context, NULL, def_val, + "appdefaults", + option, + NULL); + if(realm != NULL) + def_val = krb5_config_get_string_default(context, NULL, def_val, + "appdefaults", + realm, + option, + NULL); + if(appname != NULL) { + def_val = krb5_config_get_string_default(context, NULL, def_val, + "appdefaults", + appname, + option, + NULL); + if(realm != NULL) + def_val = krb5_config_get_string_default(context, NULL, def_val, + "appdefaults", + appname, + realm, + option, + NULL); + } + if(def_val != NULL) + *ret_val = strdup(def_val); + else + *ret_val = NULL; +} + +void KRB5_LIB_FUNCTION +krb5_appdefault_time(krb5_context context, const char *appname, + krb5_const_realm realm, const char *option, + time_t def_val, time_t *ret_val) +{ + krb5_deltat t; + char *val; + + krb5_appdefault_string(context, appname, realm, option, NULL, &val); + if (val == NULL) { + *ret_val = def_val; + return; + } + if (krb5_string_to_deltat(val, &t)) + *ret_val = def_val; + else + *ret_val = t; + free(val); +} diff --git a/lib/krb5/asn1_glue.c b/lib/krb5/asn1_glue.c new file mode 100644 index 0000000..b3f775b --- /dev/null +++ b/lib/krb5/asn1_glue.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 1997 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * + */ + +#include "krb5_locl.h" + +RCSID("$Id: asn1_glue.c 21745 2007-07-31 16:11:25Z lha $"); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_principal2principalname (PrincipalName *p, + const krb5_principal from) +{ + return copy_PrincipalName(&from->name, p); +} + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_principalname2krb5_principal (krb5_context context, + krb5_principal *principal, + const PrincipalName from, + const Realm realm) +{ + krb5_principal p = malloc(sizeof(*p)); + if (p == NULL) + return ENOMEM; + copy_PrincipalName(&from, &p->name); + p->realm = strdup(realm); + if (p->realm == NULL) + return ENOMEM; + *principal = p; + return 0; +} diff --git a/lib/krb5/auth_context.c b/lib/krb5/auth_context.c new file mode 100644 index 0000000..323f17a --- /dev/null +++ b/lib/krb5/auth_context.c @@ -0,0 +1,519 @@ +/* + * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: auth_context.c 21745 2007-07-31 16:11:25Z lha $"); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_init(krb5_context context, + krb5_auth_context *auth_context) +{ + krb5_auth_context p; + + ALLOC(p, 1); + if(!p) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + memset(p, 0, sizeof(*p)); + ALLOC(p->authenticator, 1); + if (!p->authenticator) { + krb5_set_error_string(context, "malloc: out of memory"); + free(p); + return ENOMEM; + } + memset (p->authenticator, 0, sizeof(*p->authenticator)); + p->flags = KRB5_AUTH_CONTEXT_DO_TIME; + + p->local_address = NULL; + p->remote_address = NULL; + p->local_port = 0; + p->remote_port = 0; + p->keytype = KEYTYPE_NULL; + p->cksumtype = CKSUMTYPE_NONE; + *auth_context = p; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_free(krb5_context context, + krb5_auth_context auth_context) +{ + if (auth_context != NULL) { + krb5_free_authenticator(context, &auth_context->authenticator); + if(auth_context->local_address){ + free_HostAddress(auth_context->local_address); + free(auth_context->local_address); + } + if(auth_context->remote_address){ + free_HostAddress(auth_context->remote_address); + free(auth_context->remote_address); + } + krb5_free_keyblock(context, auth_context->keyblock); + krb5_free_keyblock(context, auth_context->remote_subkey); + krb5_free_keyblock(context, auth_context->local_subkey); + free (auth_context); + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setflags(krb5_context context, + krb5_auth_context auth_context, + int32_t flags) +{ + auth_context->flags = flags; + return 0; +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getflags(krb5_context context, + krb5_auth_context auth_context, + int32_t *flags) +{ + *flags = auth_context->flags; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_addflags(krb5_context context, + krb5_auth_context auth_context, + int32_t addflags, + int32_t *flags) +{ + if (flags) + *flags = auth_context->flags; + auth_context->flags |= addflags; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_removeflags(krb5_context context, + krb5_auth_context auth_context, + int32_t removeflags, + int32_t *flags) +{ + if (flags) + *flags = auth_context->flags; + auth_context->flags &= ~removeflags; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setaddrs(krb5_context context, + krb5_auth_context auth_context, + krb5_address *local_addr, + krb5_address *remote_addr) +{ + if (local_addr) { + if (auth_context->local_address) + krb5_free_address (context, auth_context->local_address); + else + if ((auth_context->local_address = malloc(sizeof(krb5_address))) == NULL) + return ENOMEM; + krb5_copy_address(context, local_addr, auth_context->local_address); + } + if (remote_addr) { + if (auth_context->remote_address) + krb5_free_address (context, auth_context->remote_address); + else + if ((auth_context->remote_address = malloc(sizeof(krb5_address))) == NULL) + return ENOMEM; + krb5_copy_address(context, remote_addr, auth_context->remote_address); + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_genaddrs(krb5_context context, + krb5_auth_context auth_context, + int fd, int flags) +{ + krb5_error_code ret; + krb5_address local_k_address, remote_k_address; + krb5_address *lptr = NULL, *rptr = NULL; + struct sockaddr_storage ss_local, ss_remote; + struct sockaddr *local = (struct sockaddr *)&ss_local; + struct sockaddr *remote = (struct sockaddr *)&ss_remote; + socklen_t len; + + if(flags & KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR) { + if (auth_context->local_address == NULL) { + len = sizeof(ss_local); + if(getsockname(fd, local, &len) < 0) { + ret = errno; + krb5_set_error_string (context, "getsockname: %s", + strerror(ret)); + goto out; + } + ret = krb5_sockaddr2address (context, local, &local_k_address); + if(ret) goto out; + if(flags & KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR) { + krb5_sockaddr2port (context, local, &auth_context->local_port); + } else + auth_context->local_port = 0; + lptr = &local_k_address; + } + } + if(flags & KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR) { + len = sizeof(ss_remote); + if(getpeername(fd, remote, &len) < 0) { + ret = errno; + krb5_set_error_string (context, "getpeername: %s", strerror(ret)); + goto out; + } + ret = krb5_sockaddr2address (context, remote, &remote_k_address); + if(ret) goto out; + if(flags & KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR) { + krb5_sockaddr2port (context, remote, &auth_context->remote_port); + } else + auth_context->remote_port = 0; + rptr = &remote_k_address; + } + ret = krb5_auth_con_setaddrs (context, + auth_context, + lptr, + rptr); + out: + if (lptr) + krb5_free_address (context, lptr); + if (rptr) + krb5_free_address (context, rptr); + return ret; + +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setaddrs_from_fd (krb5_context context, + krb5_auth_context auth_context, + void *p_fd) +{ + int fd = *(int*)p_fd; + int flags = 0; + if(auth_context->local_address == NULL) + flags |= KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR; + if(auth_context->remote_address == NULL) + flags |= KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR; + return krb5_auth_con_genaddrs(context, auth_context, fd, flags); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getaddrs(krb5_context context, + krb5_auth_context auth_context, + krb5_address **local_addr, + krb5_address **remote_addr) +{ + if(*local_addr) + krb5_free_address (context, *local_addr); + *local_addr = malloc (sizeof(**local_addr)); + if (*local_addr == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + krb5_copy_address(context, + auth_context->local_address, + *local_addr); + + if(*remote_addr) + krb5_free_address (context, *remote_addr); + *remote_addr = malloc (sizeof(**remote_addr)); + if (*remote_addr == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + krb5_free_address (context, *local_addr); + *local_addr = NULL; + return ENOMEM; + } + krb5_copy_address(context, + auth_context->remote_address, + *remote_addr); + return 0; +} + +static krb5_error_code +copy_key(krb5_context context, + krb5_keyblock *in, + krb5_keyblock **out) +{ + if(in) + return krb5_copy_keyblock(context, in, out); + *out = NULL; /* is this right? */ + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getkey(krb5_context context, + krb5_auth_context auth_context, + krb5_keyblock **keyblock) +{ + return copy_key(context, auth_context->keyblock, keyblock); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getlocalsubkey(krb5_context context, + krb5_auth_context auth_context, + krb5_keyblock **keyblock) +{ + return copy_key(context, auth_context->local_subkey, keyblock); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getremotesubkey(krb5_context context, + krb5_auth_context auth_context, + krb5_keyblock **keyblock) +{ + return copy_key(context, auth_context->remote_subkey, keyblock); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setkey(krb5_context context, + krb5_auth_context auth_context, + krb5_keyblock *keyblock) +{ + if(auth_context->keyblock) + krb5_free_keyblock(context, auth_context->keyblock); + return copy_key(context, keyblock, &auth_context->keyblock); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setlocalsubkey(krb5_context context, + krb5_auth_context auth_context, + krb5_keyblock *keyblock) +{ + if(auth_context->local_subkey) + krb5_free_keyblock(context, auth_context->local_subkey); + return copy_key(context, keyblock, &auth_context->local_subkey); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_generatelocalsubkey(krb5_context context, + krb5_auth_context auth_context, + krb5_keyblock *key) +{ + krb5_error_code ret; + krb5_keyblock *subkey; + + ret = krb5_generate_subkey_extended (context, key, + auth_context->keytype, + &subkey); + if(ret) + return ret; + if(auth_context->local_subkey) + krb5_free_keyblock(context, auth_context->local_subkey); + auth_context->local_subkey = subkey; + return 0; +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setremotesubkey(krb5_context context, + krb5_auth_context auth_context, + krb5_keyblock *keyblock) +{ + if(auth_context->remote_subkey) + krb5_free_keyblock(context, auth_context->remote_subkey); + return copy_key(context, keyblock, &auth_context->remote_subkey); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setcksumtype(krb5_context context, + krb5_auth_context auth_context, + krb5_cksumtype cksumtype) +{ + auth_context->cksumtype = cksumtype; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getcksumtype(krb5_context context, + krb5_auth_context auth_context, + krb5_cksumtype *cksumtype) +{ + *cksumtype = auth_context->cksumtype; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setkeytype (krb5_context context, + krb5_auth_context auth_context, + krb5_keytype keytype) +{ + auth_context->keytype = keytype; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getkeytype (krb5_context context, + krb5_auth_context auth_context, + krb5_keytype *keytype) +{ + *keytype = auth_context->keytype; + return 0; +} + +#if 0 +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setenctype(krb5_context context, + krb5_auth_context auth_context, + krb5_enctype etype) +{ + if(auth_context->keyblock) + krb5_free_keyblock(context, auth_context->keyblock); + ALLOC(auth_context->keyblock, 1); + if(auth_context->keyblock == NULL) + return ENOMEM; + auth_context->keyblock->keytype = etype; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getenctype(krb5_context context, + krb5_auth_context auth_context, + krb5_enctype *etype) +{ + krb5_abortx(context, "unimplemented krb5_auth_getenctype called"); +} +#endif + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getlocalseqnumber(krb5_context context, + krb5_auth_context auth_context, + int32_t *seqnumber) +{ + *seqnumber = auth_context->local_seqnumber; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setlocalseqnumber (krb5_context context, + krb5_auth_context auth_context, + int32_t seqnumber) +{ + auth_context->local_seqnumber = seqnumber; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_getremoteseqnumber(krb5_context context, + krb5_auth_context auth_context, + int32_t *seqnumber) +{ + *seqnumber = auth_context->remote_seqnumber; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setremoteseqnumber (krb5_context context, + krb5_auth_context auth_context, + int32_t seqnumber) +{ + auth_context->remote_seqnumber = seqnumber; + return 0; +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getauthenticator(krb5_context context, + krb5_auth_context auth_context, + krb5_authenticator *authenticator) +{ + *authenticator = malloc(sizeof(**authenticator)); + if (*authenticator == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + copy_Authenticator(auth_context->authenticator, + *authenticator); + return 0; +} + + +void KRB5_LIB_FUNCTION +krb5_free_authenticator(krb5_context context, + krb5_authenticator *authenticator) +{ + free_Authenticator (*authenticator); + free (*authenticator); + *authenticator = NULL; +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setuserkey(krb5_context context, + krb5_auth_context auth_context, + krb5_keyblock *keyblock) +{ + if(auth_context->keyblock) + krb5_free_keyblock(context, auth_context->keyblock); + return krb5_copy_keyblock(context, keyblock, &auth_context->keyblock); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getrcache(krb5_context context, + krb5_auth_context auth_context, + krb5_rcache *rcache) +{ + *rcache = auth_context->rcache; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setrcache(krb5_context context, + krb5_auth_context auth_context, + krb5_rcache rcache) +{ + auth_context->rcache = rcache; + return 0; +} + +#if 0 /* not implemented */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_initivector(krb5_context context, + krb5_auth_context auth_context) +{ + krb5_abortx(context, "unimplemented krb5_auth_con_initivector called"); +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setivector(krb5_context context, + krb5_auth_context auth_context, + krb5_pointer ivector) +{ + krb5_abortx(context, "unimplemented krb5_auth_con_setivector called"); +} + +#endif /* not implemented */ diff --git a/lib/krb5/build_ap_req.c b/lib/krb5/build_ap_req.c new file mode 100644 index 0000000..b1968fe --- /dev/null +++ b/lib/krb5/build_ap_req.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <krb5_locl.h> + +RCSID("$Id: build_ap_req.c 13863 2004-05-25 21:46:46Z lha $"); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_build_ap_req (krb5_context context, + krb5_enctype enctype, + krb5_creds *cred, + krb5_flags ap_options, + krb5_data authenticator, + krb5_data *retdata) +{ + krb5_error_code ret = 0; + AP_REQ ap; + Ticket t; + size_t len; + + ap.pvno = 5; + ap.msg_type = krb_ap_req; + memset(&ap.ap_options, 0, sizeof(ap.ap_options)); + ap.ap_options.use_session_key = (ap_options & AP_OPTS_USE_SESSION_KEY) > 0; + ap.ap_options.mutual_required = (ap_options & AP_OPTS_MUTUAL_REQUIRED) > 0; + + ap.ticket.tkt_vno = 5; + copy_Realm(&cred->server->realm, &ap.ticket.realm); + copy_PrincipalName(&cred->server->name, &ap.ticket.sname); + + decode_Ticket(cred->ticket.data, cred->ticket.length, &t, &len); + copy_EncryptedData(&t.enc_part, &ap.ticket.enc_part); + free_Ticket(&t); + + ap.authenticator.etype = enctype; + ap.authenticator.kvno = NULL; + ap.authenticator.cipher = authenticator; + + ASN1_MALLOC_ENCODE(AP_REQ, retdata->data, retdata->length, + &ap, &len, ret); + if(ret == 0 && retdata->length != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + free_AP_REQ(&ap); + return ret; + +} diff --git a/lib/krb5/build_auth.c b/lib/krb5/build_auth.c new file mode 100644 index 0000000..f8739c0 --- /dev/null +++ b/lib/krb5/build_auth.c @@ -0,0 +1,202 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <krb5_locl.h> + +RCSID("$Id: build_auth.c 17033 2006-04-10 08:53:21Z lha $"); + +static krb5_error_code +make_etypelist(krb5_context context, + krb5_authdata **auth_data) +{ + EtypeList etypes; + krb5_error_code ret; + krb5_authdata ad; + u_char *buf; + size_t len; + size_t buf_size; + + ret = krb5_init_etype(context, &etypes.len, &etypes.val, NULL); + if (ret) + return ret; + + ASN1_MALLOC_ENCODE(EtypeList, buf, buf_size, &etypes, &len, ret); + if (ret) { + free_EtypeList(&etypes); + return ret; + } + if(buf_size != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + free_EtypeList(&etypes); + + ALLOC_SEQ(&ad, 1); + if (ad.val == NULL) { + free(buf); + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + ad.val[0].ad_type = KRB5_AUTHDATA_GSS_API_ETYPE_NEGOTIATION; + ad.val[0].ad_data.length = len; + ad.val[0].ad_data.data = buf; + + ASN1_MALLOC_ENCODE(AD_IF_RELEVANT, buf, buf_size, &ad, &len, ret); + if (ret) { + free_AuthorizationData(&ad); + return ret; + } + if(buf_size != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + free_AuthorizationData(&ad); + + ALLOC(*auth_data, 1); + if (*auth_data == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + ALLOC_SEQ(*auth_data, 1); + if ((*auth_data)->val == NULL) { + free(buf); + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + (*auth_data)->val[0].ad_type = KRB5_AUTHDATA_IF_RELEVANT; + (*auth_data)->val[0].ad_data.length = len; + (*auth_data)->val[0].ad_data.data = buf; + + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_build_authenticator (krb5_context context, + krb5_auth_context auth_context, + krb5_enctype enctype, + krb5_creds *cred, + Checksum *cksum, + Authenticator **auth_result, + krb5_data *result, + krb5_key_usage usage) +{ + Authenticator *auth; + u_char *buf = NULL; + size_t buf_size; + size_t len; + krb5_error_code ret; + krb5_crypto crypto; + + auth = calloc(1, sizeof(*auth)); + if (auth == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + auth->authenticator_vno = 5; + copy_Realm(&cred->client->realm, &auth->crealm); + copy_PrincipalName(&cred->client->name, &auth->cname); + + krb5_us_timeofday (context, &auth->ctime, &auth->cusec); + + ret = krb5_auth_con_getlocalsubkey(context, auth_context, &auth->subkey); + if(ret) + goto fail; + + if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) { + if(auth_context->local_seqnumber == 0) + krb5_generate_seq_number (context, + &cred->session, + &auth_context->local_seqnumber); + ALLOC(auth->seq_number, 1); + if(auth->seq_number == NULL) { + ret = ENOMEM; + goto fail; + } + *auth->seq_number = auth_context->local_seqnumber; + } else + auth->seq_number = NULL; + auth->authorization_data = NULL; + auth->cksum = cksum; + + if (cksum != NULL && cksum->cksumtype == CKSUMTYPE_GSSAPI) { + /* + * This is not GSS-API specific, we only enable it for + * GSS for now + */ + ret = make_etypelist(context, &auth->authorization_data); + if (ret) + goto fail; + } + + /* XXX - Copy more to auth_context? */ + + auth_context->authenticator->ctime = auth->ctime; + auth_context->authenticator->cusec = auth->cusec; + + ASN1_MALLOC_ENCODE(Authenticator, buf, buf_size, auth, &len, ret); + if (ret) + goto fail; + if(buf_size != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + + ret = krb5_crypto_init(context, &cred->session, enctype, &crypto); + if (ret) + goto fail; + ret = krb5_encrypt (context, + crypto, + usage /* KRB5_KU_AP_REQ_AUTH */, + buf + buf_size - len, + len, + result); + krb5_crypto_destroy(context, crypto); + + if (ret) + goto fail; + + free (buf); + + if (auth_result) + *auth_result = auth; + else { + /* Don't free the `cksum', it's allocated by the caller */ + auth->cksum = NULL; + free_Authenticator (auth); + free (auth); + } + return ret; + fail: + free_Authenticator (auth); + free (auth); + free (buf); + return ret; +} diff --git a/lib/krb5/cache.c b/lib/krb5/cache.c new file mode 100644 index 0000000..5db6d2b --- /dev/null +++ b/lib/krb5/cache.c @@ -0,0 +1,1073 @@ +/* + * Copyright (c) 1997 - 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: cache.c 22127 2007-12-04 00:54:37Z lha $"); + +/** + * Add a new ccache type with operations `ops', overwriting any + * existing one if `override'. + * + * @param context a Keberos context + * @param ops type of plugin symbol + * @param override flag to select if the registration is to overide + * an existing ops with the same name. + * + * @return Return an error code or 0. + * + * @ingroup krb5_ccache + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_register(krb5_context context, + const krb5_cc_ops *ops, + krb5_boolean override) +{ + int i; + + for(i = 0; i < context->num_cc_ops && context->cc_ops[i].prefix; i++) { + if(strcmp(context->cc_ops[i].prefix, ops->prefix) == 0) { + if(!override) { + krb5_set_error_string(context, + "ccache type %s already exists", + ops->prefix); + return KRB5_CC_TYPE_EXISTS; + } + break; + } + } + if(i == context->num_cc_ops) { + krb5_cc_ops *o = realloc(context->cc_ops, + (context->num_cc_ops + 1) * + sizeof(*context->cc_ops)); + if(o == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return KRB5_CC_NOMEM; + } + context->num_cc_ops++; + context->cc_ops = o; + memset(context->cc_ops + i, 0, + (context->num_cc_ops - i) * sizeof(*context->cc_ops)); + } + memcpy(&context->cc_ops[i], ops, sizeof(context->cc_ops[i])); + return 0; +} + +/* + * Allocate the memory for a `id' and the that function table to + * `ops'. Returns 0 or and error code. + */ + +krb5_error_code +_krb5_cc_allocate(krb5_context context, + const krb5_cc_ops *ops, + krb5_ccache *id) +{ + krb5_ccache p; + + p = malloc (sizeof(*p)); + if(p == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return KRB5_CC_NOMEM; + } + p->ops = ops; + *id = p; + + return 0; +} + +/* + * Allocate memory for a new ccache in `id' with operations `ops' + * and name `residual'. Return 0 or an error code. + */ + +static krb5_error_code +allocate_ccache (krb5_context context, + const krb5_cc_ops *ops, + const char *residual, + krb5_ccache *id) +{ + krb5_error_code ret; + + ret = _krb5_cc_allocate(context, ops, id); + if (ret) + return ret; + ret = (*id)->ops->resolve(context, id, residual); + if(ret) + free(*id); + return ret; +} + +/** + * Find and allocate a ccache in `id' from the specification in `residual'. + * If the ccache name doesn't contain any colon, interpret it as a file name. + * + * @param context a Keberos context. + * @param name string name of a credential cache. + * @param id return pointer to a found credential cache. + * + * @return Return 0 or an error code. In case of an error, id is set + * to NULL. + * + * @ingroup krb5_ccache + */ + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_resolve(krb5_context context, + const char *name, + krb5_ccache *id) +{ + int i; + + *id = NULL; + + for(i = 0; i < context->num_cc_ops && context->cc_ops[i].prefix; i++) { + size_t prefix_len = strlen(context->cc_ops[i].prefix); + + if(strncmp(context->cc_ops[i].prefix, name, prefix_len) == 0 + && name[prefix_len] == ':') { + return allocate_ccache (context, &context->cc_ops[i], + name + prefix_len + 1, + id); + } + } + if (strchr (name, ':') == NULL) + return allocate_ccache (context, &krb5_fcc_ops, name, id); + else { + krb5_set_error_string(context, "unknown ccache type %s", name); + return KRB5_CC_UNKNOWN_TYPE; + } +} + +/** + * Generate a new ccache of type `ops' in `id'. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache + */ + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_gen_new(krb5_context context, + const krb5_cc_ops *ops, + krb5_ccache *id) +{ + return krb5_cc_new_unique(context, ops->prefix, NULL, id); +} + +/** + * Generates a new unique ccache of `type` in `id'. If `type' is NULL, + * the library chooses the default credential cache type. The supplied + * `hint' (that can be NULL) is a string that the credential cache + * type can use to base the name of the credential on, this is to make + * it easier for the user to differentiate the credentials. + * + * @return Returns 0 or an error code. + * + * @ingroup krb5_ccache + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_new_unique(krb5_context context, const char *type, + const char *hint, krb5_ccache *id) +{ + const krb5_cc_ops *ops = KRB5_DEFAULT_CCTYPE; + krb5_error_code ret; + + if (type) { + ops = krb5_cc_get_prefix_ops(context, type); + if (ops == NULL) { + krb5_set_error_string(context, + "Credential cache type %s is unknown", type); + return KRB5_CC_UNKNOWN_TYPE; + } + } + + ret = _krb5_cc_allocate(context, ops, id); + if (ret) + return ret; + return (*id)->ops->gen_new(context, id); +} + +/** + * Return the name of the ccache `id' + * + * @ingroup krb5_ccache + */ + + +const char* KRB5_LIB_FUNCTION +krb5_cc_get_name(krb5_context context, + krb5_ccache id) +{ + return id->ops->get_name(context, id); +} + +/** + * Return the type of the ccache `id'. + * + * @ingroup krb5_ccache + */ + + +const char* KRB5_LIB_FUNCTION +krb5_cc_get_type(krb5_context context, + krb5_ccache id) +{ + return id->ops->prefix; +} + +/** + * Return the complete resolvable name the ccache `id' in `str´. + * `str` should be freed with free(3). + * Returns 0 or an error (and then *str is set to NULL). + * + * @ingroup krb5_ccache + */ + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_get_full_name(krb5_context context, + krb5_ccache id, + char **str) +{ + const char *type, *name; + + *str = NULL; + + type = krb5_cc_get_type(context, id); + if (type == NULL) { + krb5_set_error_string(context, "cache have no name of type"); + return KRB5_CC_UNKNOWN_TYPE; + } + + name = krb5_cc_get_name(context, id); + if (name == NULL) { + krb5_set_error_string(context, "cache of type %s have no name", type); + return KRB5_CC_BADNAME; + } + + if (asprintf(str, "%s:%s", type, name) == -1) { + krb5_set_error_string(context, "malloc - out of memory"); + *str = NULL; + return ENOMEM; + } + return 0; +} + +/** + * Return krb5_cc_ops of a the ccache `id'. + * + * @ingroup krb5_ccache + */ + + +const krb5_cc_ops * +krb5_cc_get_ops(krb5_context context, krb5_ccache id) +{ + return id->ops; +} + +/* + * Expand variables in `str' into `res' + */ + +krb5_error_code +_krb5_expand_default_cc_name(krb5_context context, const char *str, char **res) +{ + size_t tlen, len = 0; + char *tmp, *tmp2, *append; + + *res = NULL; + + while (str && *str) { + tmp = strstr(str, "%{"); + if (tmp && tmp != str) { + append = malloc((tmp - str) + 1); + if (append) { + memcpy(append, str, tmp - str); + append[tmp - str] = '\0'; + } + str = tmp; + } else if (tmp) { + tmp2 = strchr(tmp, '}'); + if (tmp2 == NULL) { + free(*res); + *res = NULL; + krb5_set_error_string(context, "variable missing }"); + return KRB5_CONFIG_BADFORMAT; + } + if (strncasecmp(tmp, "%{uid}", 6) == 0) + asprintf(&append, "%u", (unsigned)getuid()); + else if (strncasecmp(tmp, "%{null}", 7) == 0) + append = strdup(""); + else { + free(*res); + *res = NULL; + krb5_set_error_string(context, + "expand default cache unknown " + "variable \"%.*s\"", + (int)(tmp2 - tmp) - 2, tmp + 2); + return KRB5_CONFIG_BADFORMAT; + } + str = tmp2 + 1; + } else { + append = strdup(str); + str = NULL; + } + if (append == NULL) { + free(*res); + *res = NULL; + krb5_set_error_string(context, "malloc - out of memory"); + return ENOMEM; + } + + tlen = strlen(append); + tmp = realloc(*res, len + tlen + 1); + if (tmp == NULL) { + free(append); + free(*res); + *res = NULL; + krb5_set_error_string(context, "malloc - out of memory"); + return ENOMEM; + } + *res = tmp; + memcpy(*res + len, append, tlen + 1); + len = len + tlen; + free(append); + } + return 0; +} + +/* + * Return non-zero if envirnoment that will determine default krb5cc + * name has changed. + */ + +static int +environment_changed(krb5_context context) +{ + const char *e; + + /* if the cc name was set, don't change it */ + if (context->default_cc_name_set) + return 0; + + if(issuid()) + return 0; + + e = getenv("KRB5CCNAME"); + if (e == NULL) { + if (context->default_cc_name_env) { + free(context->default_cc_name_env); + context->default_cc_name_env = NULL; + return 1; + } + } else { + if (context->default_cc_name_env == NULL) + return 1; + if (strcmp(e, context->default_cc_name_env) != 0) + return 1; + } + return 0; +} + +/** + * Set the default cc name for `context' to `name'. + * + * @ingroup krb5_ccache + */ + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_set_default_name(krb5_context context, const char *name) +{ + krb5_error_code ret = 0; + char *p; + + if (name == NULL) { + const char *e = NULL; + + if(!issuid()) { + e = getenv("KRB5CCNAME"); + if (e) { + p = strdup(e); + if (context->default_cc_name_env) + free(context->default_cc_name_env); + context->default_cc_name_env = strdup(e); + } + } + if (e == NULL) { + e = krb5_config_get_string(context, NULL, "libdefaults", + "default_cc_name", NULL); + if (e) { + ret = _krb5_expand_default_cc_name(context, e, &p); + if (ret) + return ret; + } + if (e == NULL) { + const krb5_cc_ops *ops = KRB5_DEFAULT_CCTYPE; + ret = (*ops->default_name)(context, &p); + if (ret) + return ret; + } + } + context->default_cc_name_set = 0; + } else { + p = strdup(name); + context->default_cc_name_set = 1; + } + + if (p == NULL) { + krb5_set_error_string(context, "malloc - out of memory"); + return ENOMEM; + } + + if (context->default_cc_name) + free(context->default_cc_name); + + context->default_cc_name = p; + + return ret; +} + +/** + * Return a pointer to a context static string containing the default + * ccache name. + * + * @return String to the default credential cache name. + * + * @ingroup krb5_ccache + */ + + +const char* KRB5_LIB_FUNCTION +krb5_cc_default_name(krb5_context context) +{ + if (context->default_cc_name == NULL || environment_changed(context)) + krb5_cc_set_default_name(context, NULL); + + return context->default_cc_name; +} + +/** + * Open the default ccache in `id'. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache + */ + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_default(krb5_context context, + krb5_ccache *id) +{ + const char *p = krb5_cc_default_name(context); + + if (p == NULL) { + krb5_set_error_string(context, "malloc - out of memory"); + return ENOMEM; + } + return krb5_cc_resolve(context, p, id); +} + +/** + * Create a new ccache in `id' for `primary_principal'. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache + */ + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_initialize(krb5_context context, + krb5_ccache id, + krb5_principal primary_principal) +{ + return (*id->ops->init)(context, id, primary_principal); +} + + +/** + * Remove the ccache `id'. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache + */ + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_destroy(krb5_context context, + krb5_ccache id) +{ + krb5_error_code ret; + + ret = (*id->ops->destroy)(context, id); + krb5_cc_close (context, id); + return ret; +} + +/** + * Stop using the ccache `id' and free the related resources. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache + */ + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_close(krb5_context context, + krb5_ccache id) +{ + krb5_error_code ret; + ret = (*id->ops->close)(context, id); + free(id); + return ret; +} + +/** + * Store `creds' in the ccache `id'. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache + */ + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_store_cred(krb5_context context, + krb5_ccache id, + krb5_creds *creds) +{ + return (*id->ops->store)(context, id, creds); +} + +/** + * Retrieve the credential identified by `mcreds' (and `whichfields') + * from `id' in `creds'. 'creds' must be free by the caller using + * krb5_free_cred_contents. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache + */ + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_retrieve_cred(krb5_context context, + krb5_ccache id, + krb5_flags whichfields, + const krb5_creds *mcreds, + krb5_creds *creds) +{ + krb5_error_code ret; + krb5_cc_cursor cursor; + + if (id->ops->retrieve != NULL) { + return (*id->ops->retrieve)(context, id, whichfields, + mcreds, creds); + } + + ret = krb5_cc_start_seq_get(context, id, &cursor); + if (ret) + return ret; + while((ret = krb5_cc_next_cred(context, id, &cursor, creds)) == 0){ + if(krb5_compare_creds(context, whichfields, mcreds, creds)){ + ret = 0; + break; + } + krb5_free_cred_contents (context, creds); + } + krb5_cc_end_seq_get(context, id, &cursor); + return ret; +} + +/** + * Return the principal of `id' in `principal'. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache + */ + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_get_principal(krb5_context context, + krb5_ccache id, + krb5_principal *principal) +{ + return (*id->ops->get_princ)(context, id, principal); +} + +/** + * Start iterating over `id', `cursor' is initialized to the + * beginning. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache + */ + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_start_seq_get (krb5_context context, + const krb5_ccache id, + krb5_cc_cursor *cursor) +{ + return (*id->ops->get_first)(context, id, cursor); +} + +/** + * Retrieve the next cred pointed to by (`id', `cursor') in `creds' + * and advance `cursor'. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache + */ + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_next_cred (krb5_context context, + const krb5_ccache id, + krb5_cc_cursor *cursor, + krb5_creds *creds) +{ + return (*id->ops->get_next)(context, id, cursor, creds); +} + +/** + * Like krb5_cc_next_cred, but allow for selective retrieval + * + * @ingroup krb5_ccache + */ + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_next_cred_match(krb5_context context, + const krb5_ccache id, + krb5_cc_cursor * cursor, + krb5_creds * creds, + krb5_flags whichfields, + const krb5_creds * mcreds) +{ + krb5_error_code ret; + while (1) { + ret = krb5_cc_next_cred(context, id, cursor, creds); + if (ret) + return ret; + if (mcreds == NULL || krb5_compare_creds(context, whichfields, mcreds, creds)) + return 0; + krb5_free_cred_contents(context, creds); + } +} + +/** + * Destroy the cursor `cursor'. + * + * @ingroup krb5_ccache + */ + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_end_seq_get (krb5_context context, + const krb5_ccache id, + krb5_cc_cursor *cursor) +{ + return (*id->ops->end_get)(context, id, cursor); +} + +/** + * Remove the credential identified by `cred', `which' from `id'. + * + * @ingroup krb5_ccache + */ + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_remove_cred(krb5_context context, + krb5_ccache id, + krb5_flags which, + krb5_creds *cred) +{ + if(id->ops->remove_cred == NULL) { + krb5_set_error_string(context, + "ccache %s does not support remove_cred", + id->ops->prefix); + return EACCES; /* XXX */ + } + return (*id->ops->remove_cred)(context, id, which, cred); +} + +/** + * Set the flags of `id' to `flags'. + * + * @ingroup krb5_ccache + */ + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_set_flags(krb5_context context, + krb5_ccache id, + krb5_flags flags) +{ + return (*id->ops->set_flags)(context, id, flags); +} + +/** + * Copy the contents of `from' to `to'. + * + * @ingroup krb5_ccache + */ + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_copy_cache_match(krb5_context context, + const krb5_ccache from, + krb5_ccache to, + krb5_flags whichfields, + const krb5_creds * mcreds, + unsigned int *matched) +{ + krb5_error_code ret; + krb5_cc_cursor cursor; + krb5_creds cred; + krb5_principal princ; + + ret = krb5_cc_get_principal(context, from, &princ); + if (ret) + return ret; + ret = krb5_cc_initialize(context, to, princ); + if (ret) { + krb5_free_principal(context, princ); + return ret; + } + ret = krb5_cc_start_seq_get(context, from, &cursor); + if (ret) { + krb5_free_principal(context, princ); + return ret; + } + if (matched) + *matched = 0; + while (ret == 0 && + krb5_cc_next_cred_match(context, from, &cursor, &cred, + whichfields, mcreds) == 0) { + if (matched) + (*matched)++; + ret = krb5_cc_store_cred(context, to, &cred); + krb5_free_cred_contents(context, &cred); + } + krb5_cc_end_seq_get(context, from, &cursor); + krb5_free_principal(context, princ); + return ret; +} + +/** + * Just like krb5_cc_copy_cache_match, but copy everything. + * + * @ingroup krb5_ccache + */ + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_copy_cache(krb5_context context, + const krb5_ccache from, + krb5_ccache to) +{ + return krb5_cc_copy_cache_match(context, from, to, 0, NULL, NULL); +} + +/** + * Return the version of `id'. + * + * @ingroup krb5_ccache + */ + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_get_version(krb5_context context, + const krb5_ccache id) +{ + if(id->ops->get_version) + return (*id->ops->get_version)(context, id); + else + return 0; +} + +/** + * Clear `mcreds' so it can be used with krb5_cc_retrieve_cred + * + * @ingroup krb5_ccache + */ + + +void KRB5_LIB_FUNCTION +krb5_cc_clear_mcred(krb5_creds *mcred) +{ + memset(mcred, 0, sizeof(*mcred)); +} + +/** + * Get the cc ops that is registered in `context' to handle the + * `prefix'. `prefix' can be a complete credential cache name or a + * prefix, the function will only use part up to the first colon (:) + * if there is one. + * Returns NULL if ops not found. + * + * @ingroup krb5_ccache + */ + + +const krb5_cc_ops * +krb5_cc_get_prefix_ops(krb5_context context, const char *prefix) +{ + char *p, *p1; + int i; + + if (prefix[0] == '/') + return &krb5_fcc_ops; + + p = strdup(prefix); + if (p == NULL) { + krb5_set_error_string(context, "malloc - out of memory"); + return NULL; + } + p1 = strchr(p, ':'); + if (p1) + *p1 = '\0'; + + for(i = 0; i < context->num_cc_ops && context->cc_ops[i].prefix; i++) { + if(strcmp(context->cc_ops[i].prefix, p) == 0) { + free(p); + return &context->cc_ops[i]; + } + } + free(p); + return NULL; +} + +struct krb5_cc_cache_cursor_data { + const krb5_cc_ops *ops; + krb5_cc_cursor cursor; +}; + +/** + * Start iterating over all caches of `type'. If `type' is NULL, the + * default type is * used. `cursor' is initialized to the beginning. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache + */ + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_cache_get_first (krb5_context context, + const char *type, + krb5_cc_cache_cursor *cursor) +{ + const krb5_cc_ops *ops; + krb5_error_code ret; + + if (type == NULL) + type = krb5_cc_default_name(context); + + ops = krb5_cc_get_prefix_ops(context, type); + if (ops == NULL) { + krb5_set_error_string(context, "Unknown type \"%s\" when iterating " + "trying to iterate the credential caches", type); + return KRB5_CC_UNKNOWN_TYPE; + } + + if (ops->get_cache_first == NULL) { + krb5_set_error_string(context, "Credential cache type %s doesn't support " + "iterations over caches", ops->prefix); + return KRB5_CC_NOSUPP; + } + + *cursor = calloc(1, sizeof(**cursor)); + if (*cursor == NULL) { + krb5_set_error_string(context, "malloc - out of memory"); + return ENOMEM; + } + + (*cursor)->ops = ops; + + ret = ops->get_cache_first(context, &(*cursor)->cursor); + if (ret) { + free(*cursor); + *cursor = NULL; + } + return ret; +} + +/** + * Retrieve the next cache pointed to by (`cursor') in `id' + * and advance `cursor'. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache + */ + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_cache_next (krb5_context context, + krb5_cc_cache_cursor cursor, + krb5_ccache *id) +{ + return cursor->ops->get_cache_next(context, cursor->cursor, id); +} + +/** + * Destroy the cursor `cursor'. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache + */ + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_cache_end_seq_get (krb5_context context, + krb5_cc_cache_cursor cursor) +{ + krb5_error_code ret; + ret = cursor->ops->end_cache_get(context, cursor->cursor); + cursor->ops = NULL; + free(cursor); + return ret; +} + +/** + * Search for a matching credential cache of type `type' that have the + * `principal' as the default principal. If NULL is used for `type', + * the default type is used. On success, `id' needs to be freed with + * krb5_cc_close or krb5_cc_destroy. + * + * @return On failure, error code is returned and `id' is set to NULL. + * + * @ingroup krb5_ccache + */ + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_cache_match (krb5_context context, + krb5_principal client, + const char *type, + krb5_ccache *id) +{ + krb5_cc_cache_cursor cursor; + krb5_error_code ret; + krb5_ccache cache = NULL; + + *id = NULL; + + ret = krb5_cc_cache_get_first (context, type, &cursor); + if (ret) + return ret; + + while ((ret = krb5_cc_cache_next (context, cursor, &cache)) == 0) { + krb5_principal principal; + + ret = krb5_cc_get_principal(context, cache, &principal); + if (ret == 0) { + krb5_boolean match; + + match = krb5_principal_compare(context, principal, client); + krb5_free_principal(context, principal); + if (match) + break; + } + + krb5_cc_close(context, cache); + cache = NULL; + } + + krb5_cc_cache_end_seq_get(context, cursor); + + if (cache == NULL) { + char *str; + + krb5_unparse_name(context, client, &str); + + krb5_set_error_string(context, "Principal %s not found in a " + "credential cache", str ? str : "<out of memory>"); + if (str) + free(str); + return KRB5_CC_NOTFOUND; + } + *id = cache; + + return 0; +} + +/** + * Move the content from one credential cache to another. The + * operation is an atomic switch. + * + * @param context a Keberos context + * @param from the credential cache to move the content from + * @param to the credential cache to move the content to + + * @return On sucess, from is freed. On failure, error code is + * returned and from and to are both still allocated. + * + * @ingroup krb5_ccache + */ + +krb5_error_code +krb5_cc_move(krb5_context context, krb5_ccache from, krb5_ccache to) +{ + krb5_error_code ret; + + if (strcmp(from->ops->prefix, to->ops->prefix) != 0) { + krb5_set_error_string(context, "Moving credentials between diffrent " + "types not yet supported"); + return KRB5_CC_NOSUPP; + } + + ret = (*to->ops->move)(context, from, to); + if (ret == 0) { + memset(from, 0, sizeof(*from)); + free(from); + } + return ret; +} diff --git a/lib/krb5/changepw.c b/lib/krb5/changepw.c new file mode 100644 index 0000000..703cf43 --- /dev/null +++ b/lib/krb5/changepw.c @@ -0,0 +1,823 @@ +/* + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <krb5_locl.h> + +RCSID("$Id: changepw.c 21505 2007-07-12 12:28:38Z lha $"); + +static void +str2data (krb5_data *d, + const char *fmt, + ...) __attribute__ ((format (printf, 2, 3))); + +static void +str2data (krb5_data *d, + const char *fmt, + ...) +{ + va_list args; + char *str; + + va_start(args, fmt); + d->length = vasprintf (&str, fmt, args); + va_end(args); + d->data = str; +} + +/* + * Change password protocol defined by + * draft-ietf-cat-kerb-chg-password-02.txt + * + * Share the response part of the protocol with MS set password + * (RFC3244) + */ + +static krb5_error_code +chgpw_send_request (krb5_context context, + krb5_auth_context *auth_context, + krb5_creds *creds, + krb5_principal targprinc, + int is_stream, + int sock, + const char *passwd, + const char *host) +{ + krb5_error_code ret; + krb5_data ap_req_data; + krb5_data krb_priv_data; + krb5_data passwd_data; + size_t len; + u_char header[6]; + u_char *p; + struct iovec iov[3]; + struct msghdr msghdr; + + if (is_stream) + return KRB5_KPASSWD_MALFORMED; + + if (targprinc && + krb5_principal_compare(context, creds->client, targprinc) != TRUE) + return KRB5_KPASSWD_MALFORMED; + + krb5_data_zero (&ap_req_data); + + ret = krb5_mk_req_extended (context, + auth_context, + AP_OPTS_MUTUAL_REQUIRED | AP_OPTS_USE_SUBKEY, + NULL, /* in_data */ + creds, + &ap_req_data); + if (ret) + return ret; + + passwd_data.data = rk_UNCONST(passwd); + passwd_data.length = strlen(passwd); + + krb5_data_zero (&krb_priv_data); + + ret = krb5_mk_priv (context, + *auth_context, + &passwd_data, + &krb_priv_data, + NULL); + if (ret) + goto out2; + + len = 6 + ap_req_data.length + krb_priv_data.length; + p = header; + *p++ = (len >> 8) & 0xFF; + *p++ = (len >> 0) & 0xFF; + *p++ = 0; + *p++ = 1; + *p++ = (ap_req_data.length >> 8) & 0xFF; + *p++ = (ap_req_data.length >> 0) & 0xFF; + + memset(&msghdr, 0, sizeof(msghdr)); + msghdr.msg_name = NULL; + msghdr.msg_namelen = 0; + msghdr.msg_iov = iov; + msghdr.msg_iovlen = sizeof(iov)/sizeof(*iov); +#if 0 + msghdr.msg_control = NULL; + msghdr.msg_controllen = 0; +#endif + + iov[0].iov_base = (void*)header; + iov[0].iov_len = 6; + iov[1].iov_base = ap_req_data.data; + iov[1].iov_len = ap_req_data.length; + iov[2].iov_base = krb_priv_data.data; + iov[2].iov_len = krb_priv_data.length; + + if (sendmsg (sock, &msghdr, 0) < 0) { + ret = errno; + krb5_set_error_string(context, "sendmsg %s: %s", host, strerror(ret)); + } + + krb5_data_free (&krb_priv_data); +out2: + krb5_data_free (&ap_req_data); + return ret; +} + +/* + * Set password protocol as defined by RFC3244 -- + * Microsoft Windows 2000 Kerberos Change Password and Set Password Protocols + */ + +static krb5_error_code +setpw_send_request (krb5_context context, + krb5_auth_context *auth_context, + krb5_creds *creds, + krb5_principal targprinc, + int is_stream, + int sock, + const char *passwd, + const char *host) +{ + krb5_error_code ret; + krb5_data ap_req_data; + krb5_data krb_priv_data; + krb5_data pwd_data; + ChangePasswdDataMS chpw; + size_t len; + u_char header[4 + 6]; + u_char *p; + struct iovec iov[3]; + struct msghdr msghdr; + + krb5_data_zero (&ap_req_data); + + ret = krb5_mk_req_extended (context, + auth_context, + AP_OPTS_MUTUAL_REQUIRED | AP_OPTS_USE_SUBKEY, + NULL, /* in_data */ + creds, + &ap_req_data); + if (ret) + return ret; + + chpw.newpasswd.length = strlen(passwd); + chpw.newpasswd.data = rk_UNCONST(passwd); + if (targprinc) { + chpw.targname = &targprinc->name; + chpw.targrealm = &targprinc->realm; + } else { + chpw.targname = NULL; + chpw.targrealm = NULL; + } + + ASN1_MALLOC_ENCODE(ChangePasswdDataMS, pwd_data.data, pwd_data.length, + &chpw, &len, ret); + if (ret) { + krb5_data_free (&ap_req_data); + return ret; + } + + if(pwd_data.length != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + + ret = krb5_mk_priv (context, + *auth_context, + &pwd_data, + &krb_priv_data, + NULL); + if (ret) + goto out2; + + len = 6 + ap_req_data.length + krb_priv_data.length; + p = header; + if (is_stream) { + _krb5_put_int(p, len, 4); + p += 4; + } + *p++ = (len >> 8) & 0xFF; + *p++ = (len >> 0) & 0xFF; + *p++ = 0xff; + *p++ = 0x80; + *p++ = (ap_req_data.length >> 8) & 0xFF; + *p++ = (ap_req_data.length >> 0) & 0xFF; + + memset(&msghdr, 0, sizeof(msghdr)); + msghdr.msg_name = NULL; + msghdr.msg_namelen = 0; + msghdr.msg_iov = iov; + msghdr.msg_iovlen = sizeof(iov)/sizeof(*iov); +#if 0 + msghdr.msg_control = NULL; + msghdr.msg_controllen = 0; +#endif + + iov[0].iov_base = (void*)header; + if (is_stream) + iov[0].iov_len = 10; + else + iov[0].iov_len = 6; + iov[1].iov_base = ap_req_data.data; + iov[1].iov_len = ap_req_data.length; + iov[2].iov_base = krb_priv_data.data; + iov[2].iov_len = krb_priv_data.length; + + if (sendmsg (sock, &msghdr, 0) < 0) { + ret = errno; + krb5_set_error_string(context, "sendmsg %s: %s", host, strerror(ret)); + } + + krb5_data_free (&krb_priv_data); +out2: + krb5_data_free (&ap_req_data); + krb5_data_free (&pwd_data); + return ret; +} + +static krb5_error_code +process_reply (krb5_context context, + krb5_auth_context auth_context, + int is_stream, + int sock, + int *result_code, + krb5_data *result_code_string, + krb5_data *result_string, + const char *host) +{ + krb5_error_code ret; + u_char reply[1024 * 3]; + ssize_t len; + uint16_t pkt_len, pkt_ver; + krb5_data ap_rep_data; + int save_errno; + + len = 0; + if (is_stream) { + while (len < sizeof(reply)) { + unsigned long size; + + ret = recvfrom (sock, reply + len, sizeof(reply) - len, + 0, NULL, NULL); + if (ret < 0) { + save_errno = errno; + krb5_set_error_string(context, "recvfrom %s: %s", + host, strerror(save_errno)); + return save_errno; + } else if (ret == 0) { + krb5_set_error_string(context, "recvfrom timeout %s", host); + return 1; + } + len += ret; + if (len < 4) + continue; + _krb5_get_int(reply, &size, 4); + if (size + 4 < len) + continue; + memmove(reply, reply + 4, size); + len = size; + break; + } + if (len == sizeof(reply)) { + krb5_set_error_string(context, "message too large from %s", + host); + return ENOMEM; + } + } else { + ret = recvfrom (sock, reply, sizeof(reply), 0, NULL, NULL); + if (ret < 0) { + save_errno = errno; + krb5_set_error_string(context, "recvfrom %s: %s", + host, strerror(save_errno)); + return save_errno; + } + len = ret; + } + + if (len < 6) { + str2data (result_string, "server %s sent to too short message " + "(%ld bytes)", host, (long)len); + *result_code = KRB5_KPASSWD_MALFORMED; + return 0; + } + + pkt_len = (reply[0] << 8) | (reply[1]); + pkt_ver = (reply[2] << 8) | (reply[3]); + + if ((pkt_len != len) || (reply[1] == 0x7e || reply[1] == 0x5e)) { + KRB_ERROR error; + size_t size; + u_char *p; + + memset(&error, 0, sizeof(error)); + + ret = decode_KRB_ERROR(reply, len, &error, &size); + if (ret) + return ret; + + if (error.e_data->length < 2) { + str2data(result_string, "server %s sent too short " + "e_data to print anything usable", host); + free_KRB_ERROR(&error); + *result_code = KRB5_KPASSWD_MALFORMED; + return 0; + } + + p = error.e_data->data; + *result_code = (p[0] << 8) | p[1]; + if (error.e_data->length == 2) + str2data(result_string, "server only sent error code"); + else + krb5_data_copy (result_string, + p + 2, + error.e_data->length - 2); + free_KRB_ERROR(&error); + return 0; + } + + if (pkt_len != len) { + str2data (result_string, "client: wrong len in reply"); + *result_code = KRB5_KPASSWD_MALFORMED; + return 0; + } + if (pkt_ver != KRB5_KPASSWD_VERS_CHANGEPW) { + str2data (result_string, + "client: wrong version number (%d)", pkt_ver); + *result_code = KRB5_KPASSWD_MALFORMED; + return 0; + } + + ap_rep_data.data = reply + 6; + ap_rep_data.length = (reply[4] << 8) | (reply[5]); + + if (reply + len < (u_char *)ap_rep_data.data + ap_rep_data.length) { + str2data (result_string, "client: wrong AP len in reply"); + *result_code = KRB5_KPASSWD_MALFORMED; + return 0; + } + + if (ap_rep_data.length) { + krb5_ap_rep_enc_part *ap_rep; + krb5_data priv_data; + u_char *p; + + priv_data.data = (u_char*)ap_rep_data.data + ap_rep_data.length; + priv_data.length = len - ap_rep_data.length - 6; + + ret = krb5_rd_rep (context, + auth_context, + &ap_rep_data, + &ap_rep); + if (ret) + return ret; + + krb5_free_ap_rep_enc_part (context, ap_rep); + + ret = krb5_rd_priv (context, + auth_context, + &priv_data, + result_code_string, + NULL); + if (ret) { + krb5_data_free (result_code_string); + return ret; + } + + if (result_code_string->length < 2) { + *result_code = KRB5_KPASSWD_MALFORMED; + str2data (result_string, + "client: bad length in result"); + return 0; + } + + p = result_code_string->data; + + *result_code = (p[0] << 8) | p[1]; + krb5_data_copy (result_string, + (unsigned char*)result_code_string->data + 2, + result_code_string->length - 2); + return 0; + } else { + KRB_ERROR error; + size_t size; + u_char *p; + + ret = decode_KRB_ERROR(reply + 6, len - 6, &error, &size); + if (ret) { + return ret; + } + if (error.e_data->length < 2) { + krb5_warnx (context, "too short e_data to print anything usable"); + return 1; /* XXX */ + } + + p = error.e_data->data; + *result_code = (p[0] << 8) | p[1]; + krb5_data_copy (result_string, + p + 2, + error.e_data->length - 2); + return 0; + } +} + + +/* + * change the password using the credentials in `creds' (for the + * principal indicated in them) to `newpw', storing the result of + * the operation in `result_*' and an error code or 0. + */ + +typedef krb5_error_code (*kpwd_send_request) (krb5_context, + krb5_auth_context *, + krb5_creds *, + krb5_principal, + int, + int, + const char *, + const char *); +typedef krb5_error_code (*kpwd_process_reply) (krb5_context, + krb5_auth_context, + int, + int, + int *, + krb5_data *, + krb5_data *, + const char *); + +static struct kpwd_proc { + const char *name; + int flags; +#define SUPPORT_TCP 1 +#define SUPPORT_UDP 2 + kpwd_send_request send_req; + kpwd_process_reply process_rep; +} procs[] = { + { + "MS set password", + SUPPORT_TCP|SUPPORT_UDP, + setpw_send_request, + process_reply + }, + { + "change password", + SUPPORT_UDP, + chgpw_send_request, + process_reply + }, + { NULL } +}; + +static struct kpwd_proc * +find_chpw_proto(const char *name) +{ + struct kpwd_proc *p; + for (p = procs; p->name != NULL; p++) { + if (strcmp(p->name, name) == 0) + return p; + } + return NULL; +} + +/* + * + */ + +static krb5_error_code +change_password_loop (krb5_context context, + krb5_creds *creds, + krb5_principal targprinc, + const char *newpw, + int *result_code, + krb5_data *result_code_string, + krb5_data *result_string, + struct kpwd_proc *proc) +{ + krb5_error_code ret; + krb5_auth_context auth_context = NULL; + krb5_krbhst_handle handle = NULL; + krb5_krbhst_info *hi; + int sock; + int i; + int done = 0; + krb5_realm realm; + + if (targprinc) + realm = targprinc->realm; + else + realm = creds->client->realm; + + ret = krb5_auth_con_init (context, &auth_context); + if (ret) + return ret; + + krb5_auth_con_setflags (context, auth_context, + KRB5_AUTH_CONTEXT_DO_SEQUENCE); + + ret = krb5_krbhst_init (context, realm, KRB5_KRBHST_CHANGEPW, &handle); + if (ret) + goto out; + + while (!done && (ret = krb5_krbhst_next(context, handle, &hi)) == 0) { + struct addrinfo *ai, *a; + int is_stream; + + switch (hi->proto) { + case KRB5_KRBHST_UDP: + if ((proc->flags & SUPPORT_UDP) == 0) + continue; + is_stream = 0; + break; + case KRB5_KRBHST_TCP: + if ((proc->flags & SUPPORT_TCP) == 0) + continue; + is_stream = 1; + break; + default: + continue; + } + + ret = krb5_krbhst_get_addrinfo(context, hi, &ai); + if (ret) + continue; + + for (a = ai; !done && a != NULL; a = a->ai_next) { + int replied = 0; + + sock = socket (a->ai_family, a->ai_socktype, a->ai_protocol); + if (sock < 0) + continue; + + ret = connect(sock, a->ai_addr, a->ai_addrlen); + if (ret < 0) { + close (sock); + goto out; + } + + ret = krb5_auth_con_genaddrs (context, auth_context, sock, + KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR); + if (ret) { + close (sock); + goto out; + } + + for (i = 0; !done && i < 5; ++i) { + fd_set fdset; + struct timeval tv; + + if (!replied) { + replied = 0; + + ret = (*proc->send_req) (context, + &auth_context, + creds, + targprinc, + is_stream, + sock, + newpw, + hi->hostname); + if (ret) { + close(sock); + goto out; + } + } + + if (sock >= FD_SETSIZE) { + krb5_set_error_string(context, "fd %d too large", sock); + ret = ERANGE; + close (sock); + goto out; + } + + FD_ZERO(&fdset); + FD_SET(sock, &fdset); + tv.tv_usec = 0; + tv.tv_sec = 1 + (1 << i); + + ret = select (sock + 1, &fdset, NULL, NULL, &tv); + if (ret < 0 && errno != EINTR) { + close(sock); + goto out; + } + if (ret == 1) { + ret = (*proc->process_rep) (context, + auth_context, + is_stream, + sock, + result_code, + result_code_string, + result_string, + hi->hostname); + if (ret == 0) + done = 1; + else if (i > 0 && ret == KRB5KRB_AP_ERR_MUT_FAIL) + replied = 1; + } else { + ret = KRB5_KDC_UNREACH; + } + } + close (sock); + } + } + + out: + krb5_krbhst_free (context, handle); + krb5_auth_con_free (context, auth_context); + if (done) + return 0; + else { + if (ret == KRB5_KDC_UNREACH) { + krb5_set_error_string(context, + "unable to reach any changepw server " + " in realm %s", realm); + *result_code = KRB5_KPASSWD_HARDERROR; + } + return ret; + } +} + + +/* + * change the password using the credentials in `creds' (for the + * principal indicated in them) to `newpw', storing the result of + * the operation in `result_*' and an error code or 0. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_change_password (krb5_context context, + krb5_creds *creds, + const char *newpw, + int *result_code, + krb5_data *result_code_string, + krb5_data *result_string) +{ + struct kpwd_proc *p = find_chpw_proto("change password"); + + *result_code = KRB5_KPASSWD_MALFORMED; + result_code_string->data = result_string->data = NULL; + result_code_string->length = result_string->length = 0; + + if (p == NULL) + return KRB5_KPASSWD_MALFORMED; + + return change_password_loop(context, creds, NULL, newpw, + result_code, result_code_string, + result_string, p); +} + +/* + * + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_password(krb5_context context, + krb5_creds *creds, + const char *newpw, + krb5_principal targprinc, + int *result_code, + krb5_data *result_code_string, + krb5_data *result_string) +{ + krb5_principal principal = NULL; + krb5_error_code ret = 0; + int i; + + *result_code = KRB5_KPASSWD_MALFORMED; + result_code_string->data = result_string->data = NULL; + result_code_string->length = result_string->length = 0; + + if (targprinc == NULL) { + ret = krb5_get_default_principal(context, &principal); + if (ret) + return ret; + } else + principal = targprinc; + + for (i = 0; procs[i].name != NULL; i++) { + *result_code = 0; + ret = change_password_loop(context, creds, principal, newpw, + result_code, result_code_string, + result_string, + &procs[i]); + if (ret == 0 && *result_code == 0) + break; + } + + if (targprinc == NULL) + krb5_free_principal(context, principal); + return ret; +} + +/* + * + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_password_using_ccache(krb5_context context, + krb5_ccache ccache, + const char *newpw, + krb5_principal targprinc, + int *result_code, + krb5_data *result_code_string, + krb5_data *result_string) +{ + krb5_creds creds, *credsp; + krb5_error_code ret; + krb5_principal principal = NULL; + + *result_code = KRB5_KPASSWD_MALFORMED; + result_code_string->data = result_string->data = NULL; + result_code_string->length = result_string->length = 0; + + memset(&creds, 0, sizeof(creds)); + + if (targprinc == NULL) { + ret = krb5_cc_get_principal(context, ccache, &principal); + if (ret) + return ret; + } else + principal = targprinc; + + ret = krb5_make_principal(context, &creds.server, + krb5_principal_get_realm(context, principal), + "kadmin", "changepw", NULL); + if (ret) + goto out; + + ret = krb5_cc_get_principal(context, ccache, &creds.client); + if (ret) { + krb5_free_principal(context, creds.server); + goto out; + } + + ret = krb5_get_credentials(context, 0, ccache, &creds, &credsp); + krb5_free_principal(context, creds.server); + krb5_free_principal(context, creds.client); + if (ret) + goto out; + + ret = krb5_set_password(context, + credsp, + newpw, + principal, + result_code, + result_code_string, + result_string); + + krb5_free_creds(context, credsp); + + return ret; + out: + if (targprinc == NULL) + krb5_free_principal(context, principal); + return ret; +} + +/* + * + */ + +const char* KRB5_LIB_FUNCTION +krb5_passwd_result_to_string (krb5_context context, + int result) +{ + static const char *strings[] = { + "Success", + "Malformed", + "Hard error", + "Auth error", + "Soft error" , + "Access denied", + "Bad version", + "Initial flag needed" + }; + + if (result < 0 || result > KRB5_KPASSWD_INITIAL_FLAG_NEEDED) + return "unknown result code"; + else + return strings[result]; +} diff --git a/lib/krb5/codec.c b/lib/krb5/codec.c new file mode 100644 index 0000000..0d36b4b --- /dev/null +++ b/lib/krb5/codec.c @@ -0,0 +1,196 @@ +/* + * Copyright (c) 1998 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: codec.c 13863 2004-05-25 21:46:46Z lha $"); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decode_EncTicketPart (krb5_context context, + const void *data, + size_t length, + EncTicketPart *t, + size_t *len) +{ + return decode_EncTicketPart(data, length, t, len); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encode_EncTicketPart (krb5_context context, + void *data, + size_t length, + EncTicketPart *t, + size_t *len) +{ + return encode_EncTicketPart(data, length, t, len); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decode_EncASRepPart (krb5_context context, + const void *data, + size_t length, + EncASRepPart *t, + size_t *len) +{ + return decode_EncASRepPart(data, length, t, len); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encode_EncASRepPart (krb5_context context, + void *data, + size_t length, + EncASRepPart *t, + size_t *len) +{ + return encode_EncASRepPart(data, length, t, len); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decode_EncTGSRepPart (krb5_context context, + const void *data, + size_t length, + EncTGSRepPart *t, + size_t *len) +{ + return decode_EncTGSRepPart(data, length, t, len); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encode_EncTGSRepPart (krb5_context context, + void *data, + size_t length, + EncTGSRepPart *t, + size_t *len) +{ + return encode_EncTGSRepPart(data, length, t, len); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decode_EncAPRepPart (krb5_context context, + const void *data, + size_t length, + EncAPRepPart *t, + size_t *len) +{ + return decode_EncAPRepPart(data, length, t, len); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encode_EncAPRepPart (krb5_context context, + void *data, + size_t length, + EncAPRepPart *t, + size_t *len) +{ + return encode_EncAPRepPart(data, length, t, len); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decode_Authenticator (krb5_context context, + const void *data, + size_t length, + Authenticator *t, + size_t *len) +{ + return decode_Authenticator(data, length, t, len); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encode_Authenticator (krb5_context context, + void *data, + size_t length, + Authenticator *t, + size_t *len) +{ + return encode_Authenticator(data, length, t, len); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decode_EncKrbCredPart (krb5_context context, + const void *data, + size_t length, + EncKrbCredPart *t, + size_t *len) +{ + return decode_EncKrbCredPart(data, length, t, len); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encode_EncKrbCredPart (krb5_context context, + void *data, + size_t length, + EncKrbCredPart *t, + size_t *len) +{ + return encode_EncKrbCredPart (data, length, t, len); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decode_ETYPE_INFO (krb5_context context, + const void *data, + size_t length, + ETYPE_INFO *t, + size_t *len) +{ + return decode_ETYPE_INFO(data, length, t, len); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encode_ETYPE_INFO (krb5_context context, + void *data, + size_t length, + ETYPE_INFO *t, + size_t *len) +{ + return encode_ETYPE_INFO (data, length, t, len); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decode_ETYPE_INFO2 (krb5_context context, + const void *data, + size_t length, + ETYPE_INFO2 *t, + size_t *len) +{ + return decode_ETYPE_INFO2(data, length, t, len); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encode_ETYPE_INFO2 (krb5_context context, + void *data, + size_t length, + ETYPE_INFO2 *t, + size_t *len) +{ + return encode_ETYPE_INFO2 (data, length, t, len); +} diff --git a/lib/krb5/config_file.c b/lib/krb5/config_file.c new file mode 100644 index 0000000..ac5eba3 --- /dev/null +++ b/lib/krb5/config_file.c @@ -0,0 +1,771 @@ +/* + * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" +RCSID("$Id: config_file.c 19213 2006-12-04 23:36:36Z lha $"); + +#ifndef HAVE_NETINFO + +/* Gaah! I want a portable funopen */ +struct fileptr { + const char *s; + FILE *f; +}; + +static char * +config_fgets(char *str, size_t len, struct fileptr *ptr) +{ + /* XXX this is not correct, in that they don't do the same if the + line is longer than len */ + if(ptr->f != NULL) + return fgets(str, len, ptr->f); + else { + /* this is almost strsep_copy */ + const char *p; + ssize_t l; + if(*ptr->s == '\0') + return NULL; + p = ptr->s + strcspn(ptr->s, "\n"); + if(*p == '\n') + p++; + l = min(len, p - ptr->s); + if(len > 0) { + memcpy(str, ptr->s, l); + str[l] = '\0'; + } + ptr->s = p; + return str; + } +} + +static krb5_error_code parse_section(char *p, krb5_config_section **s, + krb5_config_section **res, + const char **error_message); +static krb5_error_code parse_binding(struct fileptr *f, unsigned *lineno, char *p, + krb5_config_binding **b, + krb5_config_binding **parent, + const char **error_message); +static krb5_error_code parse_list(struct fileptr *f, unsigned *lineno, + krb5_config_binding **parent, + const char **error_message); + +static krb5_config_section * +get_entry(krb5_config_section **parent, const char *name, int type) +{ + krb5_config_section **q; + + for(q = parent; *q != NULL; q = &(*q)->next) + if(type == krb5_config_list && + type == (*q)->type && + strcmp(name, (*q)->name) == 0) + return *q; + *q = calloc(1, sizeof(**q)); + if(*q == NULL) + return NULL; + (*q)->name = strdup(name); + (*q)->type = type; + if((*q)->name == NULL) { + free(*q); + *q = NULL; + return NULL; + } + return *q; +} + +/* + * Parse a section: + * + * [section] + * foo = bar + * b = { + * a + * } + * ... + * + * starting at the line in `p', storing the resulting structure in + * `s' and hooking it into `parent'. + * Store the error message in `error_message'. + */ + +static krb5_error_code +parse_section(char *p, krb5_config_section **s, krb5_config_section **parent, + const char **error_message) +{ + char *p1; + krb5_config_section *tmp; + + p1 = strchr (p + 1, ']'); + if (p1 == NULL) { + *error_message = "missing ]"; + return KRB5_CONFIG_BADFORMAT; + } + *p1 = '\0'; + tmp = get_entry(parent, p + 1, krb5_config_list); + if(tmp == NULL) { + *error_message = "out of memory"; + return KRB5_CONFIG_BADFORMAT; + } + *s = tmp; + return 0; +} + +/* + * Parse a brace-enclosed list from `f', hooking in the structure at + * `parent'. + * Store the error message in `error_message'. + */ + +static krb5_error_code +parse_list(struct fileptr *f, unsigned *lineno, krb5_config_binding **parent, + const char **error_message) +{ + char buf[BUFSIZ]; + krb5_error_code ret; + krb5_config_binding *b = NULL; + unsigned beg_lineno = *lineno; + + while(config_fgets(buf, sizeof(buf), f) != NULL) { + char *p; + + ++*lineno; + buf[strcspn(buf, "\r\n")] = '\0'; + p = buf; + while(isspace((unsigned char)*p)) + ++p; + if (*p == '#' || *p == ';' || *p == '\0') + continue; + while(isspace((unsigned char)*p)) + ++p; + if (*p == '}') + return 0; + if (*p == '\0') + continue; + ret = parse_binding (f, lineno, p, &b, parent, error_message); + if (ret) + return ret; + } + *lineno = beg_lineno; + *error_message = "unclosed {"; + return KRB5_CONFIG_BADFORMAT; +} + +/* + * + */ + +static krb5_error_code +parse_binding(struct fileptr *f, unsigned *lineno, char *p, + krb5_config_binding **b, krb5_config_binding **parent, + const char **error_message) +{ + krb5_config_binding *tmp; + char *p1, *p2; + krb5_error_code ret = 0; + + p1 = p; + while (*p && *p != '=' && !isspace((unsigned char)*p)) + ++p; + if (*p == '\0') { + *error_message = "missing ="; + return KRB5_CONFIG_BADFORMAT; + } + p2 = p; + while (isspace((unsigned char)*p)) + ++p; + if (*p != '=') { + *error_message = "missing ="; + return KRB5_CONFIG_BADFORMAT; + } + ++p; + while(isspace((unsigned char)*p)) + ++p; + *p2 = '\0'; + if (*p == '{') { + tmp = get_entry(parent, p1, krb5_config_list); + if (tmp == NULL) { + *error_message = "out of memory"; + return KRB5_CONFIG_BADFORMAT; + } + ret = parse_list (f, lineno, &tmp->u.list, error_message); + } else { + tmp = get_entry(parent, p1, krb5_config_string); + if (tmp == NULL) { + *error_message = "out of memory"; + return KRB5_CONFIG_BADFORMAT; + } + p1 = p; + p = p1 + strlen(p1); + while(p > p1 && isspace((unsigned char)*(p-1))) + --p; + *p = '\0'; + tmp->u.string = strdup(p1); + } + *b = tmp; + return ret; +} + +/* + * Parse the config file `fname', generating the structures into `res' + * returning error messages in `error_message' + */ + +static krb5_error_code +krb5_config_parse_debug (struct fileptr *f, + krb5_config_section **res, + unsigned *lineno, + const char **error_message) +{ + krb5_config_section *s = NULL; + krb5_config_binding *b = NULL; + char buf[BUFSIZ]; + krb5_error_code ret; + + while (config_fgets(buf, sizeof(buf), f) != NULL) { + char *p; + + ++*lineno; + buf[strcspn(buf, "\r\n")] = '\0'; + p = buf; + while(isspace((unsigned char)*p)) + ++p; + if (*p == '#' || *p == ';') + continue; + if (*p == '[') { + ret = parse_section(p, &s, res, error_message); + if (ret) + return ret; + b = NULL; + } else if (*p == '}') { + *error_message = "unmatched }"; + return EINVAL; /* XXX */ + } else if(*p != '\0') { + if (s == NULL) { + *error_message = "binding before section"; + return EINVAL; + } + ret = parse_binding(f, lineno, p, &b, &s->u.list, error_message); + if (ret) + return ret; + } + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_config_parse_string_multi(krb5_context context, + const char *string, + krb5_config_section **res) +{ + const char *str; + unsigned lineno = 0; + krb5_error_code ret; + struct fileptr f; + f.f = NULL; + f.s = string; + + ret = krb5_config_parse_debug (&f, res, &lineno, &str); + if (ret) { + krb5_set_error_string (context, "%s:%u: %s", "<constant>", lineno, str); + return ret; + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_config_parse_file_multi (krb5_context context, + const char *fname, + krb5_config_section **res) +{ + const char *str; + unsigned lineno = 0; + krb5_error_code ret; + struct fileptr f; + f.f = fopen(fname, "r"); + f.s = NULL; + if(f.f == NULL) { + ret = errno; + krb5_set_error_string (context, "open %s: %s", fname, strerror(ret)); + return ret; + } + + ret = krb5_config_parse_debug (&f, res, &lineno, &str); + fclose(f.f); + if (ret) { + krb5_set_error_string (context, "%s:%u: %s", fname, lineno, str); + return ret; + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_config_parse_file (krb5_context context, + const char *fname, + krb5_config_section **res) +{ + *res = NULL; + return krb5_config_parse_file_multi(context, fname, res); +} + +#endif /* !HAVE_NETINFO */ + +static void +free_binding (krb5_context context, krb5_config_binding *b) +{ + krb5_config_binding *next_b; + + while (b) { + free (b->name); + if (b->type == krb5_config_string) + free (b->u.string); + else if (b->type == krb5_config_list) + free_binding (context, b->u.list); + else + krb5_abortx(context, "unknown binding type (%d) in free_binding", + b->type); + next_b = b->next; + free (b); + b = next_b; + } +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_config_file_free (krb5_context context, krb5_config_section *s) +{ + free_binding (context, s); + return 0; +} + +const void * +krb5_config_get_next (krb5_context context, + const krb5_config_section *c, + const krb5_config_binding **pointer, + int type, + ...) +{ + const char *ret; + va_list args; + + va_start(args, type); + ret = krb5_config_vget_next (context, c, pointer, type, args); + va_end(args); + return ret; +} + +static const void * +vget_next(krb5_context context, + const krb5_config_binding *b, + const krb5_config_binding **pointer, + int type, + const char *name, + va_list args) +{ + const char *p = va_arg(args, const char *); + while(b != NULL) { + if(strcmp(b->name, name) == 0) { + if(b->type == type && p == NULL) { + *pointer = b; + return b->u.generic; + } else if(b->type == krb5_config_list && p != NULL) { + return vget_next(context, b->u.list, pointer, type, p, args); + } + } + b = b->next; + } + return NULL; +} + +const void * +krb5_config_vget_next (krb5_context context, + const krb5_config_section *c, + const krb5_config_binding **pointer, + int type, + va_list args) +{ + const krb5_config_binding *b; + const char *p; + + if(c == NULL) + c = context->cf; + + if (c == NULL) + return NULL; + + if (*pointer == NULL) { + /* first time here, walk down the tree looking for the right + section */ + p = va_arg(args, const char *); + if (p == NULL) + return NULL; + return vget_next(context, c, pointer, type, p, args); + } + + /* we were called again, so just look for more entries with the + same name and type */ + for (b = (*pointer)->next; b != NULL; b = b->next) { + if(strcmp(b->name, (*pointer)->name) == 0 && b->type == type) { + *pointer = b; + return b->u.generic; + } + } + return NULL; +} + +const void * +krb5_config_get (krb5_context context, + const krb5_config_section *c, + int type, + ...) +{ + const void *ret; + va_list args; + + va_start(args, type); + ret = krb5_config_vget (context, c, type, args); + va_end(args); + return ret; +} + +const void * +krb5_config_vget (krb5_context context, + const krb5_config_section *c, + int type, + va_list args) +{ + const krb5_config_binding *foo = NULL; + + return krb5_config_vget_next (context, c, &foo, type, args); +} + +const krb5_config_binding * +krb5_config_get_list (krb5_context context, + const krb5_config_section *c, + ...) +{ + const krb5_config_binding *ret; + va_list args; + + va_start(args, c); + ret = krb5_config_vget_list (context, c, args); + va_end(args); + return ret; +} + +const krb5_config_binding * +krb5_config_vget_list (krb5_context context, + const krb5_config_section *c, + va_list args) +{ + return krb5_config_vget (context, c, krb5_config_list, args); +} + +const char* KRB5_LIB_FUNCTION +krb5_config_get_string (krb5_context context, + const krb5_config_section *c, + ...) +{ + const char *ret; + va_list args; + + va_start(args, c); + ret = krb5_config_vget_string (context, c, args); + va_end(args); + return ret; +} + +const char* KRB5_LIB_FUNCTION +krb5_config_vget_string (krb5_context context, + const krb5_config_section *c, + va_list args) +{ + return krb5_config_vget (context, c, krb5_config_string, args); +} + +const char* KRB5_LIB_FUNCTION +krb5_config_vget_string_default (krb5_context context, + const krb5_config_section *c, + const char *def_value, + va_list args) +{ + const char *ret; + + ret = krb5_config_vget_string (context, c, args); + if (ret == NULL) + ret = def_value; + return ret; +} + +const char* KRB5_LIB_FUNCTION +krb5_config_get_string_default (krb5_context context, + const krb5_config_section *c, + const char *def_value, + ...) +{ + const char *ret; + va_list args; + + va_start(args, def_value); + ret = krb5_config_vget_string_default (context, c, def_value, args); + va_end(args); + return ret; +} + +char ** KRB5_LIB_FUNCTION +krb5_config_vget_strings(krb5_context context, + const krb5_config_section *c, + va_list args) +{ + char **strings = NULL; + int nstr = 0; + const krb5_config_binding *b = NULL; + const char *p; + + while((p = krb5_config_vget_next(context, c, &b, + krb5_config_string, args))) { + char *tmp = strdup(p); + char *pos = NULL; + char *s; + if(tmp == NULL) + goto cleanup; + s = strtok_r(tmp, " \t", &pos); + while(s){ + char **tmp2 = realloc(strings, (nstr + 1) * sizeof(*strings)); + if(tmp2 == NULL) + goto cleanup; + strings = tmp2; + strings[nstr] = strdup(s); + nstr++; + if(strings[nstr-1] == NULL) + goto cleanup; + s = strtok_r(NULL, " \t", &pos); + } + free(tmp); + } + if(nstr){ + char **tmp = realloc(strings, (nstr + 1) * sizeof(*strings)); + if(tmp == NULL) + goto cleanup; + strings = tmp; + strings[nstr] = NULL; + } + return strings; +cleanup: + while(nstr--) + free(strings[nstr]); + free(strings); + return NULL; + +} + +char** +krb5_config_get_strings(krb5_context context, + const krb5_config_section *c, + ...) +{ + va_list ap; + char **ret; + va_start(ap, c); + ret = krb5_config_vget_strings(context, c, ap); + va_end(ap); + return ret; +} + +void KRB5_LIB_FUNCTION +krb5_config_free_strings(char **strings) +{ + char **s = strings; + while(s && *s){ + free(*s); + s++; + } + free(strings); +} + +krb5_boolean KRB5_LIB_FUNCTION +krb5_config_vget_bool_default (krb5_context context, + const krb5_config_section *c, + krb5_boolean def_value, + va_list args) +{ + const char *str; + str = krb5_config_vget_string (context, c, args); + if(str == NULL) + return def_value; + if(strcasecmp(str, "yes") == 0 || + strcasecmp(str, "true") == 0 || + atoi(str)) return TRUE; + return FALSE; +} + +krb5_boolean KRB5_LIB_FUNCTION +krb5_config_vget_bool (krb5_context context, + const krb5_config_section *c, + va_list args) +{ + return krb5_config_vget_bool_default (context, c, FALSE, args); +} + +krb5_boolean KRB5_LIB_FUNCTION +krb5_config_get_bool_default (krb5_context context, + const krb5_config_section *c, + krb5_boolean def_value, + ...) +{ + va_list ap; + krb5_boolean ret; + va_start(ap, def_value); + ret = krb5_config_vget_bool_default(context, c, def_value, ap); + va_end(ap); + return ret; +} + +krb5_boolean KRB5_LIB_FUNCTION +krb5_config_get_bool (krb5_context context, + const krb5_config_section *c, + ...) +{ + va_list ap; + krb5_boolean ret; + va_start(ap, c); + ret = krb5_config_vget_bool (context, c, ap); + va_end(ap); + return ret; +} + +int KRB5_LIB_FUNCTION +krb5_config_vget_time_default (krb5_context context, + const krb5_config_section *c, + int def_value, + va_list args) +{ + const char *str; + krb5_deltat t; + + str = krb5_config_vget_string (context, c, args); + if(str == NULL) + return def_value; + if (krb5_string_to_deltat(str, &t)) + return def_value; + return t; +} + +int KRB5_LIB_FUNCTION +krb5_config_vget_time (krb5_context context, + const krb5_config_section *c, + va_list args) +{ + return krb5_config_vget_time_default (context, c, -1, args); +} + +int KRB5_LIB_FUNCTION +krb5_config_get_time_default (krb5_context context, + const krb5_config_section *c, + int def_value, + ...) +{ + va_list ap; + int ret; + va_start(ap, def_value); + ret = krb5_config_vget_time_default(context, c, def_value, ap); + va_end(ap); + return ret; +} + +int KRB5_LIB_FUNCTION +krb5_config_get_time (krb5_context context, + const krb5_config_section *c, + ...) +{ + va_list ap; + int ret; + va_start(ap, c); + ret = krb5_config_vget_time (context, c, ap); + va_end(ap); + return ret; +} + + +int KRB5_LIB_FUNCTION +krb5_config_vget_int_default (krb5_context context, + const krb5_config_section *c, + int def_value, + va_list args) +{ + const char *str; + str = krb5_config_vget_string (context, c, args); + if(str == NULL) + return def_value; + else { + char *endptr; + long l; + l = strtol(str, &endptr, 0); + if (endptr == str) + return def_value; + else + return l; + } +} + +int KRB5_LIB_FUNCTION +krb5_config_vget_int (krb5_context context, + const krb5_config_section *c, + va_list args) +{ + return krb5_config_vget_int_default (context, c, -1, args); +} + +int KRB5_LIB_FUNCTION +krb5_config_get_int_default (krb5_context context, + const krb5_config_section *c, + int def_value, + ...) +{ + va_list ap; + int ret; + va_start(ap, def_value); + ret = krb5_config_vget_int_default(context, c, def_value, ap); + va_end(ap); + return ret; +} + +int KRB5_LIB_FUNCTION +krb5_config_get_int (krb5_context context, + const krb5_config_section *c, + ...) +{ + va_list ap; + int ret; + va_start(ap, c); + ret = krb5_config_vget_int (context, c, ap); + va_end(ap); + return ret; +} diff --git a/lib/krb5/config_file_netinfo.c b/lib/krb5/config_file_netinfo.c new file mode 100644 index 0000000..1e01e7c --- /dev/null +++ b/lib/krb5/config_file_netinfo.c @@ -0,0 +1,180 @@ +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" +RCSID("$Id: config_file_netinfo.c 13863 2004-05-25 21:46:46Z lha $"); + +/* + * Netinfo implementation from Luke Howard <lukeh@xedoc.com.au> + */ + +#ifdef HAVE_NETINFO +#include <netinfo/ni.h> +static ni_status +ni_proplist2binding(ni_proplist *pl, krb5_config_section **ret) +{ + int i, j; + krb5_config_section **next = NULL; + + for (i = 0; i < pl->ni_proplist_len; i++) { + if (!strcmp(pl->nipl_val[i].nip_name, "name")) + continue; + + for (j = 0; j < pl->nipl_val[i].nip_val.ni_namelist_len; j++) { + krb5_config_binding *b; + + b = malloc(sizeof(*b)); + if (b == NULL) + return NI_FAILED; + + b->next = NULL; + b->type = krb5_config_string; + b->name = ni_name_dup(pl->nipl_val[i].nip_name); + b->u.string = ni_name_dup(pl->nipl_val[i].nip_val.ninl_val[j]); + + if (next == NULL) { + *ret = b; + } else { + *next = b; + } + next = &b->next; + } + } + return NI_OK; +} + +static ni_status +ni_idlist2binding(void *ni, ni_idlist *idlist, krb5_config_section **ret) +{ + int i; + ni_status nis; + krb5_config_section **next; + + for (i = 0; i < idlist->ni_idlist_len; i++) { + ni_proplist pl; + ni_id nid; + ni_idlist children; + krb5_config_binding *b; + ni_index index; + + nid.nii_instance = 0; + nid.nii_object = idlist->ni_idlist_val[i]; + + nis = ni_read(ni, &nid, &pl); + + if (nis != NI_OK) { + return nis; + } + index = ni_proplist_match(pl, "name", NULL); + b = malloc(sizeof(*b)); + if (b == NULL) return NI_FAILED; + + if (i == 0) { + *ret = b; + } else { + *next = b; + } + + b->type = krb5_config_list; + b->name = ni_name_dup(pl.nipl_val[index].nip_val.ninl_val[0]); + b->next = NULL; + b->u.list = NULL; + + /* get the child directories */ + nis = ni_children(ni, &nid, &children); + if (nis == NI_OK) { + nis = ni_idlist2binding(ni, &children, &b->u.list); + if (nis != NI_OK) { + return nis; + } + } + + nis = ni_proplist2binding(&pl, b->u.list == NULL ? &b->u.list : &b->u.list->next); + ni_proplist_free(&pl); + if (nis != NI_OK) { + return nis; + } + next = &b->next; + } + ni_idlist_free(idlist); + return NI_OK; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_config_parse_file (krb5_context context, + const char *fname, + krb5_config_section **res) +{ + void *ni = NULL, *lastni = NULL; + int i; + ni_status nis; + ni_id nid; + ni_idlist children; + + krb5_config_section *s; + int ret; + + s = NULL; + + for (i = 0; i < 256; i++) { + if (i == 0) { + nis = ni_open(NULL, ".", &ni); + } else { + if (lastni != NULL) ni_free(lastni); + lastni = ni; + nis = ni_open(lastni, "..", &ni); + } + if (nis != NI_OK) + break; + nis = ni_pathsearch(ni, &nid, "/locations/kerberos"); + if (nis == NI_OK) { + nis = ni_children(ni, &nid, &children); + if (nis != NI_OK) + break; + nis = ni_idlist2binding(ni, &children, &s); + break; + } + } + + if (ni != NULL) ni_free(ni); + if (ni != lastni && lastni != NULL) ni_free(lastni); + + ret = (nis == NI_OK) ? 0 : -1; + if (ret == 0) { + *res = s; + } else { + *res = NULL; + } + return ret; +} +#endif /* HAVE_NETINFO */ diff --git a/lib/krb5/constants.c b/lib/krb5/constants.c new file mode 100644 index 0000000..5188a1d --- /dev/null +++ b/lib/krb5/constants.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 1997-2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: constants.c 14253 2004-09-23 07:57:37Z joda $"); + +const char *krb5_config_file = +#ifdef __APPLE__ +"/Library/Preferences/edu.mit.Kerberos:" +#endif +SYSCONFDIR "/krb5.conf:/etc/krb5.conf"; +const char *krb5_defkeyname = KEYTAB_DEFAULT; diff --git a/lib/krb5/context.c b/lib/krb5/context.c new file mode 100644 index 0000000..2567833 --- /dev/null +++ b/lib/krb5/context.c @@ -0,0 +1,1033 @@ +/* + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" +#include <com_err.h> + +RCSID("$Id: context.c 22293 2007-12-14 05:25:59Z lha $"); + +#define INIT_FIELD(C, T, E, D, F) \ + (C)->E = krb5_config_get_ ## T ## _default ((C), NULL, (D), \ + "libdefaults", F, NULL) + +#define INIT_FLAG(C, O, V, D, F) \ + do { \ + if (krb5_config_get_bool_default((C), NULL, (D),"libdefaults", F, NULL)) { \ + (C)->O |= V; \ + } \ + } while(0) + +/* + * Set the list of etypes `ret_etypes' from the configuration variable + * `name' + */ + +static krb5_error_code +set_etypes (krb5_context context, + const char *name, + krb5_enctype **ret_enctypes) +{ + char **etypes_str; + krb5_enctype *etypes = NULL; + + etypes_str = krb5_config_get_strings(context, NULL, "libdefaults", + name, NULL); + if(etypes_str){ + int i, j, k; + for(i = 0; etypes_str[i]; i++); + etypes = malloc((i+1) * sizeof(*etypes)); + if (etypes == NULL) { + krb5_config_free_strings (etypes_str); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + for(j = 0, k = 0; j < i; j++) { + krb5_enctype e; + if(krb5_string_to_enctype(context, etypes_str[j], &e) != 0) + continue; + if (krb5_enctype_valid(context, e) != 0) + continue; + etypes[k++] = e; + } + etypes[k] = ETYPE_NULL; + krb5_config_free_strings(etypes_str); + } + *ret_enctypes = etypes; + return 0; +} + +/* + * read variables from the configuration file and set in `context' + */ + +static krb5_error_code +init_context_from_config_file(krb5_context context) +{ + krb5_error_code ret; + const char * tmp; + krb5_enctype *tmptypes; + + INIT_FIELD(context, time, max_skew, 5 * 60, "clockskew"); + INIT_FIELD(context, time, kdc_timeout, 3, "kdc_timeout"); + INIT_FIELD(context, int, max_retries, 3, "max_retries"); + + INIT_FIELD(context, string, http_proxy, NULL, "http_proxy"); + + ret = set_etypes (context, "default_etypes", &tmptypes); + if(ret) + return ret; + free(context->etypes); + context->etypes = tmptypes; + + ret = set_etypes (context, "default_etypes_des", &tmptypes); + if(ret) + return ret; + free(context->etypes_des); + context->etypes_des = tmptypes; + + /* default keytab name */ + tmp = NULL; + if(!issuid()) + tmp = getenv("KRB5_KTNAME"); + if(tmp != NULL) + context->default_keytab = tmp; + else + INIT_FIELD(context, string, default_keytab, + KEYTAB_DEFAULT, "default_keytab_name"); + + INIT_FIELD(context, string, default_keytab_modify, + NULL, "default_keytab_modify_name"); + + INIT_FIELD(context, string, time_fmt, + "%Y-%m-%dT%H:%M:%S", "time_format"); + + INIT_FIELD(context, string, date_fmt, + "%Y-%m-%d", "date_format"); + + INIT_FIELD(context, bool, log_utc, + FALSE, "log_utc"); + + + + /* init dns-proxy slime */ + tmp = krb5_config_get_string(context, NULL, "libdefaults", + "dns_proxy", NULL); + if(tmp) + roken_gethostby_setup(context->http_proxy, tmp); + krb5_free_host_realm (context, context->default_realms); + context->default_realms = NULL; + + { + krb5_addresses addresses; + char **adr, **a; + + krb5_set_extra_addresses(context, NULL); + adr = krb5_config_get_strings(context, NULL, + "libdefaults", + "extra_addresses", + NULL); + memset(&addresses, 0, sizeof(addresses)); + for(a = adr; a && *a; a++) { + ret = krb5_parse_address(context, *a, &addresses); + if (ret == 0) { + krb5_add_extra_addresses(context, &addresses); + krb5_free_addresses(context, &addresses); + } + } + krb5_config_free_strings(adr); + + krb5_set_ignore_addresses(context, NULL); + adr = krb5_config_get_strings(context, NULL, + "libdefaults", + "ignore_addresses", + NULL); + memset(&addresses, 0, sizeof(addresses)); + for(a = adr; a && *a; a++) { + ret = krb5_parse_address(context, *a, &addresses); + if (ret == 0) { + krb5_add_ignore_addresses(context, &addresses); + krb5_free_addresses(context, &addresses); + } + } + krb5_config_free_strings(adr); + } + + INIT_FIELD(context, bool, scan_interfaces, TRUE, "scan_interfaces"); + INIT_FIELD(context, int, fcache_vno, 0, "fcache_version"); + /* prefer dns_lookup_kdc over srv_lookup. */ + INIT_FIELD(context, bool, srv_lookup, TRUE, "srv_lookup"); + INIT_FIELD(context, bool, srv_lookup, context->srv_lookup, "dns_lookup_kdc"); + INIT_FIELD(context, int, large_msg_size, 1400, "large_message_size"); + INIT_FLAG(context, flags, KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME, TRUE, "dns_canonicalize_hostname"); + INIT_FLAG(context, flags, KRB5_CTX_F_CHECK_PAC, TRUE, "check_pac"); + context->default_cc_name = NULL; + context->default_cc_name_set = 0; + return 0; +} + +/** + * Initializes the context structure and reads the configuration file + * /etc/krb5.conf. The structure should be freed by calling + * krb5_free_context() when it is no longer being used. + * + * @param context pointer to returned context + * + * @return Returns 0 to indicate success. Otherwise an errno code is + * returned. Failure means either that something bad happened during + * initialization (typically ENOMEM) or that Kerberos should not be + * used ENXIO. + * + * @ingroup krb5 + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_init_context(krb5_context *context) +{ + krb5_context p; + krb5_error_code ret; + char **files; + + *context = NULL; + + p = calloc(1, sizeof(*p)); + if(!p) + return ENOMEM; + + p->mutex = malloc(sizeof(HEIMDAL_MUTEX)); + if (p->mutex == NULL) { + free(p); + return ENOMEM; + } + HEIMDAL_MUTEX_init(p->mutex); + + ret = krb5_get_default_config_files(&files); + if(ret) + goto out; + ret = krb5_set_config_files(p, files); + krb5_free_config_files(files); + if(ret) + goto out; + + /* init error tables */ + krb5_init_ets(p); + + p->cc_ops = NULL; + p->num_cc_ops = 0; + krb5_cc_register(p, &krb5_acc_ops, TRUE); + krb5_cc_register(p, &krb5_fcc_ops, TRUE); + krb5_cc_register(p, &krb5_mcc_ops, TRUE); +#ifdef HAVE_KCM + krb5_cc_register(p, &krb5_kcm_ops, TRUE); +#endif + + p->num_kt_types = 0; + p->kt_types = NULL; + krb5_kt_register (p, &krb5_fkt_ops); + krb5_kt_register (p, &krb5_wrfkt_ops); + krb5_kt_register (p, &krb5_javakt_ops); + krb5_kt_register (p, &krb5_mkt_ops); + krb5_kt_register (p, &krb5_akf_ops); + krb5_kt_register (p, &krb4_fkt_ops); + krb5_kt_register (p, &krb5_srvtab_fkt_ops); + krb5_kt_register (p, &krb5_any_ops); + +out: + if(ret) { + krb5_free_context(p); + p = NULL; + } + *context = p; + return ret; +} + +/** + * Frees the krb5_context allocated by krb5_init_context(). + * + * @param context context to be freed. + * + * @ingroup krb5 +*/ + +void KRB5_LIB_FUNCTION +krb5_free_context(krb5_context context) +{ + if (context->default_cc_name) + free(context->default_cc_name); + if (context->default_cc_name_env) + free(context->default_cc_name_env); + free(context->etypes); + free(context->etypes_des); + krb5_free_host_realm (context, context->default_realms); + krb5_config_file_free (context, context->cf); + free_error_table (context->et_list); + free(context->cc_ops); + free(context->kt_types); + krb5_clear_error_string(context); + if(context->warn_dest != NULL) + krb5_closelog(context, context->warn_dest); + krb5_set_extra_addresses(context, NULL); + krb5_set_ignore_addresses(context, NULL); + krb5_set_send_to_kdc_func(context, NULL, NULL); + if (context->mutex != NULL) { + HEIMDAL_MUTEX_destroy(context->mutex); + free(context->mutex); + } + memset(context, 0, sizeof(*context)); + free(context); +} + +/** + * Reinit the context from a new set of filenames. + * + * @param context context to add configuration too. + * @param filenames array of filenames, end of list is indicated with a NULL filename. + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_config_files(krb5_context context, char **filenames) +{ + krb5_error_code ret; + krb5_config_binding *tmp = NULL; + while(filenames != NULL && *filenames != NULL && **filenames != '\0') { + ret = krb5_config_parse_file_multi(context, *filenames, &tmp); + if(ret != 0 && ret != ENOENT && ret != EACCES) { + krb5_config_file_free(context, tmp); + return ret; + } + filenames++; + } +#if 0 + /* with this enabled and if there are no config files, Kerberos is + considererd disabled */ + if(tmp == NULL) + return ENXIO; +#endif + krb5_config_file_free(context, context->cf); + context->cf = tmp; + ret = init_context_from_config_file(context); + return ret; +} + +static krb5_error_code +add_file(char ***pfilenames, int *len, char *file) +{ + char **pp = *pfilenames; + int i; + + for(i = 0; i < *len; i++) { + if(strcmp(pp[i], file) == 0) { + free(file); + return 0; + } + } + + pp = realloc(*pfilenames, (*len + 2) * sizeof(*pp)); + if (pp == NULL) { + free(file); + return ENOMEM; + } + + pp[*len] = file; + pp[*len + 1] = NULL; + *pfilenames = pp; + *len += 1; + return 0; +} + +/* + * `pq' isn't free, it's up the the caller + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_prepend_config_files(const char *filelist, char **pq, char ***ret_pp) +{ + krb5_error_code ret; + const char *p, *q; + char **pp; + int len; + char *fn; + + pp = NULL; + + len = 0; + p = filelist; + while(1) { + ssize_t l; + q = p; + l = strsep_copy(&q, ":", NULL, 0); + if(l == -1) + break; + fn = malloc(l + 1); + if(fn == NULL) { + krb5_free_config_files(pp); + return ENOMEM; + } + l = strsep_copy(&p, ":", fn, l + 1); + ret = add_file(&pp, &len, fn); + if (ret) { + krb5_free_config_files(pp); + return ret; + } + } + + if (pq != NULL) { + int i; + + for (i = 0; pq[i] != NULL; i++) { + fn = strdup(pq[i]); + if (fn == NULL) { + krb5_free_config_files(pp); + return ENOMEM; + } + ret = add_file(&pp, &len, fn); + if (ret) { + krb5_free_config_files(pp); + return ret; + } + } + } + + *ret_pp = pp; + return 0; +} + +/** + * Prepend the filename to the global configuration list. + * + * @param filelist a filename to add to the default list of filename + * @param pfilenames return array of filenames, should be freed with krb5_free_config_files(). + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_prepend_config_files_default(const char *filelist, char ***pfilenames) +{ + krb5_error_code ret; + char **defpp, **pp = NULL; + + ret = krb5_get_default_config_files(&defpp); + if (ret) + return ret; + + ret = krb5_prepend_config_files(filelist, defpp, &pp); + krb5_free_config_files(defpp); + if (ret) { + return ret; + } + *pfilenames = pp; + return 0; +} + +/** + * Get the global configuration list. + * + * @param pfilenames return array of filenames, should be freed with krb5_free_config_files(). + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_default_config_files(char ***pfilenames) +{ + const char *files = NULL; + + if (pfilenames == NULL) + return EINVAL; + if(!issuid()) + files = getenv("KRB5_CONFIG"); + if (files == NULL) + files = krb5_config_file; + + return krb5_prepend_config_files(files, NULL, pfilenames); +} + +/** + * Free a list of configuration files. + * + * @param filenames list to be freed. + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + +void KRB5_LIB_FUNCTION +krb5_free_config_files(char **filenames) +{ + char **p; + for(p = filenames; *p != NULL; p++) + free(*p); + free(filenames); +} + +/** + * Returns the list of Kerberos encryption types sorted in order of + * most preferred to least preferred encryption type. Note that some + * encryption types might be disabled, so you need to check with + * krb5_enctype_valid() before using the encryption type. + * + * @return list of enctypes, terminated with ETYPE_NULL. Its a static + * array completed into the Kerberos library so the content doesn't + * need to be freed. + * + * @ingroup krb5 + */ + +const krb5_enctype * KRB5_LIB_FUNCTION +krb5_kerberos_enctypes(krb5_context context) +{ + static const krb5_enctype p[] = { + ETYPE_AES256_CTS_HMAC_SHA1_96, + ETYPE_AES128_CTS_HMAC_SHA1_96, + ETYPE_DES3_CBC_SHA1, + ETYPE_DES3_CBC_MD5, + ETYPE_ARCFOUR_HMAC_MD5, + ETYPE_DES_CBC_MD5, + ETYPE_DES_CBC_MD4, + ETYPE_DES_CBC_CRC, + ETYPE_NULL + }; + return p; +} + +/* + * set `etype' to a malloced list of the default enctypes + */ + +static krb5_error_code +default_etypes(krb5_context context, krb5_enctype **etype) +{ + const krb5_enctype *p; + krb5_enctype *e = NULL, *ep; + int i, n = 0; + + p = krb5_kerberos_enctypes(context); + + for (i = 0; p[i] != ETYPE_NULL; i++) { + if (krb5_enctype_valid(context, p[i]) != 0) + continue; + ep = realloc(e, (n + 2) * sizeof(*e)); + if (ep == NULL) { + free(e); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + e = ep; + e[n] = p[i]; + e[n + 1] = ETYPE_NULL; + n++; + } + *etype = e; + return 0; +} + +/** + * Set the default encryption types that will be use in communcation + * with the KDC, clients and servers. + * + * @param context Kerberos 5 context. + * @param etypes Encryption types, array terminated with ETYPE_NULL (0). + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_default_in_tkt_etypes(krb5_context context, + const krb5_enctype *etypes) +{ + krb5_enctype *p = NULL; + int i; + + if(etypes) { + for (i = 0; etypes[i]; ++i) { + krb5_error_code ret; + ret = krb5_enctype_valid(context, etypes[i]); + if (ret) + return ret; + } + ++i; + ALLOC(p, i); + if(!p) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + memmove(p, etypes, i * sizeof(krb5_enctype)); + } + if(context->etypes) + free(context->etypes); + context->etypes = p; + return 0; +} + +/** + * Get the default encryption types that will be use in communcation + * with the KDC, clients and servers. + * + * @param context Kerberos 5 context. + * @param etypes Encryption types, array terminated with + * ETYPE_NULL(0), caller should free array with krb5_xfree(): + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_default_in_tkt_etypes(krb5_context context, + krb5_enctype **etypes) +{ + krb5_enctype *p; + int i; + krb5_error_code ret; + + if(context->etypes) { + for(i = 0; context->etypes[i]; i++); + ++i; + ALLOC(p, i); + if(!p) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + memmove(p, context->etypes, i * sizeof(krb5_enctype)); + } else { + ret = default_etypes(context, &p); + if (ret) + return ret; + } + *etypes = p; + return 0; +} + +/** + * Return the error string for the error code. The caller must not + * free the string. + * + * @param context Kerberos 5 context. + * @param code Kerberos error code. + * + * @return the error message matching code + * + * @ingroup krb5 + */ + +const char* KRB5_LIB_FUNCTION +krb5_get_err_text(krb5_context context, krb5_error_code code) +{ + const char *p = NULL; + if(context != NULL) + p = com_right(context->et_list, code); + if(p == NULL) + p = strerror(code); + if (p == NULL) + p = "Unknown error"; + return p; +} + +/** + * Init the built-in ets in the Kerberos library. + * + * @param context kerberos context to add the ets too + * + * @ingroup krb5 + */ + +void KRB5_LIB_FUNCTION +krb5_init_ets(krb5_context context) +{ + if(context->et_list == NULL){ + krb5_add_et_list(context, initialize_krb5_error_table_r); + krb5_add_et_list(context, initialize_asn1_error_table_r); + krb5_add_et_list(context, initialize_heim_error_table_r); + krb5_add_et_list(context, initialize_k524_error_table_r); +#ifdef PKINIT + krb5_add_et_list(context, initialize_hx_error_table_r); +#endif + } +} + +/** + * Make the kerberos library default to the admin KDC. + * + * @param context Kerberos 5 context. + * @param flag boolean flag to select if the use the admin KDC or not. + * + * @ingroup krb5 + */ + +void KRB5_LIB_FUNCTION +krb5_set_use_admin_kdc (krb5_context context, krb5_boolean flag) +{ + context->use_admin_kdc = flag; +} + +/** + * Make the kerberos library default to the admin KDC. + * + * @param context Kerberos 5 context. + * + * @return boolean flag to telling the context will use admin KDC as the default KDC. + * + * @ingroup krb5 + */ + +krb5_boolean KRB5_LIB_FUNCTION +krb5_get_use_admin_kdc (krb5_context context) +{ + return context->use_admin_kdc; +} + +/** + * Add extra address to the address list that the library will add to + * the client's address list when communicating with the KDC. + * + * @param context Kerberos 5 context. + * @param addresses addreses to add + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_add_extra_addresses(krb5_context context, krb5_addresses *addresses) +{ + + if(context->extra_addresses) + return krb5_append_addresses(context, + context->extra_addresses, addresses); + else + return krb5_set_extra_addresses(context, addresses); +} + +/** + * Set extra address to the address list that the library will add to + * the client's address list when communicating with the KDC. + * + * @param context Kerberos 5 context. + * @param addresses addreses to set + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_extra_addresses(krb5_context context, const krb5_addresses *addresses) +{ + if(context->extra_addresses) + krb5_free_addresses(context, context->extra_addresses); + + if(addresses == NULL) { + if(context->extra_addresses != NULL) { + free(context->extra_addresses); + context->extra_addresses = NULL; + } + return 0; + } + if(context->extra_addresses == NULL) { + context->extra_addresses = malloc(sizeof(*context->extra_addresses)); + if(context->extra_addresses == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + } + return krb5_copy_addresses(context, addresses, context->extra_addresses); +} + +/** + * Get extra address to the address list that the library will add to + * the client's address list when communicating with the KDC. + * + * @param context Kerberos 5 context. + * @param addresses addreses to set + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_extra_addresses(krb5_context context, krb5_addresses *addresses) +{ + if(context->extra_addresses == NULL) { + memset(addresses, 0, sizeof(*addresses)); + return 0; + } + return krb5_copy_addresses(context,context->extra_addresses, addresses); +} + +/** + * Add extra addresses to ignore when fetching addresses from the + * underlaying operating system. + * + * @param context Kerberos 5 context. + * @param addresses addreses to ignore + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_add_ignore_addresses(krb5_context context, krb5_addresses *addresses) +{ + + if(context->ignore_addresses) + return krb5_append_addresses(context, + context->ignore_addresses, addresses); + else + return krb5_set_ignore_addresses(context, addresses); +} + +/** + * Set extra addresses to ignore when fetching addresses from the + * underlaying operating system. + * + * @param context Kerberos 5 context. + * @param addresses addreses to ignore + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_ignore_addresses(krb5_context context, const krb5_addresses *addresses) +{ + if(context->ignore_addresses) + krb5_free_addresses(context, context->ignore_addresses); + if(addresses == NULL) { + if(context->ignore_addresses != NULL) { + free(context->ignore_addresses); + context->ignore_addresses = NULL; + } + return 0; + } + if(context->ignore_addresses == NULL) { + context->ignore_addresses = malloc(sizeof(*context->ignore_addresses)); + if(context->ignore_addresses == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + } + return krb5_copy_addresses(context, addresses, context->ignore_addresses); +} + +/** + * Get extra addresses to ignore when fetching addresses from the + * underlaying operating system. + * + * @param context Kerberos 5 context. + * @param addresses list addreses ignored + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_ignore_addresses(krb5_context context, krb5_addresses *addresses) +{ + if(context->ignore_addresses == NULL) { + memset(addresses, 0, sizeof(*addresses)); + return 0; + } + return krb5_copy_addresses(context, context->ignore_addresses, addresses); +} + +/** + * Set version of fcache that the library should use. + * + * @param context Kerberos 5 context. + * @param version version number. + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_fcache_version(krb5_context context, int version) +{ + context->fcache_vno = version; + return 0; +} + +/** + * Get version of fcache that the library should use. + * + * @param context Kerberos 5 context. + * @param version version number. + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_fcache_version(krb5_context context, int *version) +{ + *version = context->fcache_vno; + return 0; +} + +/** + * Runtime check if the Kerberos library was complied with thread support. + * + * @return TRUE if the library was compiled with thread support, FALSE if not. + * + * @ingroup krb5 + */ + + +krb5_boolean KRB5_LIB_FUNCTION +krb5_is_thread_safe(void) +{ +#ifdef ENABLE_PTHREAD_SUPPORT + return TRUE; +#else + return FALSE; +#endif +} + +/** + * Set if the library should use DNS to canonicalize hostnames. + * + * @param context Kerberos 5 context. + * @param flag if its dns canonicalizion is used or not. + * + * @ingroup krb5 + */ + +void KRB5_LIB_FUNCTION +krb5_set_dns_canonicalize_hostname (krb5_context context, krb5_boolean flag) +{ + if (flag) + context->flags |= KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME; + else + context->flags &= ~KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME; +} + +/** + * Get if the library uses DNS to canonicalize hostnames. + * + * @param context Kerberos 5 context. + * + * @return return non zero if the library uses DNS to canonicalize hostnames. + * + * @ingroup krb5 + */ + +krb5_boolean KRB5_LIB_FUNCTION +krb5_get_dns_canonicalize_hostname (krb5_context context) +{ + return (context->flags & KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME) ? 1 : 0; +} + +/** + * Get current offset in time to the KDC. + * + * @param context Kerberos 5 context. + * @param sec seconds part of offset. + * @param usec micro seconds part of offset. + * + * @return return non zero if the library uses DNS to canonicalize hostnames. + * + * @ingroup krb5 + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_kdc_sec_offset (krb5_context context, int32_t *sec, int32_t *usec) +{ + if (sec) + *sec = context->kdc_sec_offset; + if (usec) + *usec = context->kdc_usec_offset; + return 0; +} + +/** + * Get max time skew allowed. + * + * @param context Kerberos 5 context. + * + * @return timeskew in seconds. + * + * @ingroup krb5 + */ + +time_t KRB5_LIB_FUNCTION +krb5_get_max_time_skew (krb5_context context) +{ + return context->max_skew; +} + +/** + * Set max time skew allowed. + * + * @param context Kerberos 5 context. + * @param t timeskew in seconds. + * + * @ingroup krb5 + */ + +void KRB5_LIB_FUNCTION +krb5_set_max_time_skew (krb5_context context, time_t t) +{ + context->max_skew = t; +} diff --git a/lib/krb5/convert_creds.c b/lib/krb5/convert_creds.c new file mode 100644 index 0000000..b2af018 --- /dev/null +++ b/lib/krb5/convert_creds.c @@ -0,0 +1,204 @@ +/* + * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" +RCSID("$Id: convert_creds.c 22050 2007-11-11 11:20:46Z lha $"); + +#include "krb5-v4compat.h" + +static krb5_error_code +check_ticket_flags(TicketFlags f) +{ + return 0; /* maybe add some more tests here? */ +} + +/** + * Convert the v5 credentials in in_cred to v4-dito in v4creds. This + * is done by sending them to the 524 function in the KDC. If + * `in_cred' doesn't contain a DES session key, then a new one is + * gotten from the KDC and stored in the cred cache `ccache'. + * + * @param context Kerberos 5 context. + * @param in_cred the credential to convert + * @param v4creds the converted credential + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5_v4compat + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb524_convert_creds_kdc(krb5_context context, + krb5_creds *in_cred, + struct credentials *v4creds) +{ + krb5_error_code ret; + krb5_data reply; + krb5_storage *sp; + int32_t tmp; + krb5_data ticket; + char realm[REALM_SZ]; + krb5_creds *v5_creds = in_cred; + + ret = check_ticket_flags(v5_creds->flags.b); + if(ret) + goto out2; + + { + krb5_krbhst_handle handle; + + ret = krb5_krbhst_init(context, + krb5_principal_get_realm(context, + v5_creds->server), + KRB5_KRBHST_KRB524, + &handle); + if (ret) + goto out2; + + ret = krb5_sendto (context, + &v5_creds->ticket, + handle, + &reply); + krb5_krbhst_free(context, handle); + if (ret) + goto out2; + } + sp = krb5_storage_from_mem(reply.data, reply.length); + if(sp == NULL) { + ret = ENOMEM; + krb5_set_error_string (context, "malloc: out of memory"); + goto out2; + } + krb5_ret_int32(sp, &tmp); + ret = tmp; + if(ret == 0) { + memset(v4creds, 0, sizeof(*v4creds)); + ret = krb5_ret_int32(sp, &tmp); + if(ret) + goto out; + v4creds->kvno = tmp; + ret = krb5_ret_data(sp, &ticket); + if(ret) + goto out; + v4creds->ticket_st.length = ticket.length; + memcpy(v4creds->ticket_st.dat, ticket.data, ticket.length); + krb5_data_free(&ticket); + ret = krb5_524_conv_principal(context, + v5_creds->server, + v4creds->service, + v4creds->instance, + v4creds->realm); + if(ret) + goto out; + v4creds->issue_date = v5_creds->times.starttime; + v4creds->lifetime = _krb5_krb_time_to_life(v4creds->issue_date, + v5_creds->times.endtime); + ret = krb5_524_conv_principal(context, v5_creds->client, + v4creds->pname, + v4creds->pinst, + realm); + if(ret) + goto out; + memcpy(v4creds->session, v5_creds->session.keyvalue.data, 8); + } else { + krb5_set_error_string(context, "converting credentials: %s", + krb5_get_err_text(context, ret)); + } +out: + krb5_storage_free(sp); + krb5_data_free(&reply); +out2: + if (v5_creds != in_cred) + krb5_free_creds (context, v5_creds); + return ret; +} + +/** + * Convert the v5 credentials in in_cred to v4-dito in v4creds, + * check the credential cache ccache before checking with the KDC. + * + * @param context Kerberos 5 context. + * @param ccache credential cache used to check for des-ticket. + * @param in_cred the credential to convert + * @param v4creds the converted credential + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5_v4compat + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb524_convert_creds_kdc_ccache(krb5_context context, + krb5_ccache ccache, + krb5_creds *in_cred, + struct credentials *v4creds) +{ + krb5_error_code ret; + krb5_creds *v5_creds = in_cred; + krb5_keytype keytype; + + keytype = v5_creds->session.keytype; + + if (keytype != ENCTYPE_DES_CBC_CRC) { + /* MIT krb524d doesn't like nothing but des-cbc-crc tickets, + so go get one */ + krb5_creds template; + + memset (&template, 0, sizeof(template)); + template.session.keytype = ENCTYPE_DES_CBC_CRC; + ret = krb5_copy_principal (context, in_cred->client, &template.client); + if (ret) { + krb5_free_cred_contents (context, &template); + return ret; + } + ret = krb5_copy_principal (context, in_cred->server, &template.server); + if (ret) { + krb5_free_cred_contents (context, &template); + return ret; + } + + ret = krb5_get_credentials (context, 0, ccache, + &template, &v5_creds); + krb5_free_cred_contents (context, &template); + if (ret) + return ret; + } + + ret = krb524_convert_creds_kdc(context, v5_creds, v4creds); + + if (v5_creds != in_cred) + krb5_free_creds (context, v5_creds); + return ret; +} diff --git a/lib/krb5/copy_host_realm.c b/lib/krb5/copy_host_realm.c new file mode 100644 index 0000000..8c4f39b --- /dev/null +++ b/lib/krb5/copy_host_realm.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 1999 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: copy_host_realm.c 22057 2007-11-11 15:13:13Z lha $"); + +/** + * Copy the list of realms from `from' to `to'. + * + * @param context Kerberos 5 context. + * @param from list of realms to copy from. + * @param to list of realms to copy to, free list of krb5_free_host_realm(). + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_host_realm(krb5_context context, + const krb5_realm *from, + krb5_realm **to) +{ + int n, i; + const krb5_realm *p; + + for (n = 0, p = from; *p != NULL; ++p) + ++n; + ++n; + *to = malloc (n * sizeof(**to)); + if (*to == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + for (i = 0; i < n; ++i) + (*to)[i] = NULL; + for (i = 0, p = from; *p != NULL; ++p, ++i) { + (*to)[i] = strdup(*p); + if ((*to)[i] == NULL) { + krb5_free_host_realm (context, *to); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + } + return 0; +} diff --git a/lib/krb5/crc.c b/lib/krb5/crc.c new file mode 100644 index 0000000..072c29d --- /dev/null +++ b/lib/krb5/crc.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 1997 - 2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: crc.c 17442 2006-05-05 09:31:15Z lha $"); + +static u_long table[256]; + +#define CRC_GEN 0xEDB88320L + +void +_krb5_crc_init_table(void) +{ + static int flag = 0; + unsigned long crc, poly; + int i, j; + + if(flag) return; + poly = CRC_GEN; + for (i = 0; i < 256; i++) { + crc = i; + for (j = 8; j > 0; j--) { + if (crc & 1) { + crc = (crc >> 1) ^ poly; + } else { + crc >>= 1; + } + } + table[i] = crc; + } + flag = 1; +} + +uint32_t +_krb5_crc_update (const char *p, size_t len, uint32_t res) +{ + while (len--) + res = table[(res ^ *p++) & 0xFF] ^ (res >> 8); + return res & 0xFFFFFFFF; +} diff --git a/lib/krb5/creds.c b/lib/krb5/creds.c new file mode 100644 index 0000000..17ef46d --- /dev/null +++ b/lib/krb5/creds.c @@ -0,0 +1,269 @@ +/* + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: creds.c 22062 2007-11-11 15:41:50Z lha $"); + +#undef __attribute__ +#define __attribute__(X) + +/* keep this for compatibility with older code */ +krb5_error_code KRB5_LIB_FUNCTION __attribute__((deprecated)) +krb5_free_creds_contents (krb5_context context, krb5_creds *c) +{ + return krb5_free_cred_contents (context, c); +} + +/** + * Free content of krb5_creds. + * + * @param context Kerberos 5 context. + * @param c krb5_creds to free. + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_free_cred_contents (krb5_context context, krb5_creds *c) +{ + krb5_free_principal (context, c->client); + c->client = NULL; + krb5_free_principal (context, c->server); + c->server = NULL; + krb5_free_keyblock_contents (context, &c->session); + krb5_data_free (&c->ticket); + krb5_data_free (&c->second_ticket); + free_AuthorizationData (&c->authdata); + krb5_free_addresses (context, &c->addresses); + memset(c, 0, sizeof(*c)); + return 0; +} + +/** + * Copy content of krb5_creds. + * + * @param context Kerberos 5 context. + * @param incred source credential + * @param c destination credential, free with krb5_free_cred_contents(). + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_creds_contents (krb5_context context, + const krb5_creds *incred, + krb5_creds *c) +{ + krb5_error_code ret; + + memset(c, 0, sizeof(*c)); + ret = krb5_copy_principal (context, incred->client, &c->client); + if (ret) + goto fail; + ret = krb5_copy_principal (context, incred->server, &c->server); + if (ret) + goto fail; + ret = krb5_copy_keyblock_contents (context, &incred->session, &c->session); + if (ret) + goto fail; + c->times = incred->times; + ret = krb5_data_copy (&c->ticket, + incred->ticket.data, + incred->ticket.length); + if (ret) + goto fail; + ret = krb5_data_copy (&c->second_ticket, + incred->second_ticket.data, + incred->second_ticket.length); + if (ret) + goto fail; + ret = copy_AuthorizationData(&incred->authdata, &c->authdata); + if (ret) + goto fail; + ret = krb5_copy_addresses (context, + &incred->addresses, + &c->addresses); + if (ret) + goto fail; + c->flags = incred->flags; + return 0; + +fail: + krb5_free_cred_contents (context, c); + return ret; +} + +/** + * Copy krb5_creds. + * + * @param context Kerberos 5 context. + * @param incred source credential + * @param outcred destination credential, free with krb5_free_creds(). + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_creds (krb5_context context, + const krb5_creds *incred, + krb5_creds **outcred) +{ + krb5_creds *c; + + c = malloc (sizeof (*c)); + if (c == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + memset (c, 0, sizeof(*c)); + *outcred = c; + return krb5_copy_creds_contents (context, incred, c); +} + +/** + * Free krb5_creds. + * + * @param context Kerberos 5 context. + * @param c krb5_creds to free. + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_free_creds (krb5_context context, krb5_creds *c) +{ + krb5_free_cred_contents (context, c); + free (c); + return 0; +} + +/* XXX this do not belong here */ +static krb5_boolean +krb5_times_equal(const krb5_times *a, const krb5_times *b) +{ + return a->starttime == b->starttime && + a->authtime == b->authtime && + a->endtime == b->endtime && + a->renew_till == b->renew_till; +} + +/** + * Return TRUE if `mcreds' and `creds' are equal (`whichfields' + * determines what equal means). + * + * @param context Kerberos 5 context. + * @param whichfields which fields to compare. + * @param mcreds cred to compare with. + * @param creds cred to compare with. + * + * @return return TRUE if mcred and creds are equal, FALSE if not. + * + * @ingroup krb5 + */ + +krb5_boolean KRB5_LIB_FUNCTION +krb5_compare_creds(krb5_context context, krb5_flags whichfields, + const krb5_creds * mcreds, const krb5_creds * creds) +{ + krb5_boolean match = TRUE; + + if (match && mcreds->server) { + if (whichfields & (KRB5_TC_DONT_MATCH_REALM | KRB5_TC_MATCH_SRV_NAMEONLY)) + match = krb5_principal_compare_any_realm (context, mcreds->server, + creds->server); + else + match = krb5_principal_compare (context, mcreds->server, + creds->server); + } + + if (match && mcreds->client) { + if(whichfields & KRB5_TC_DONT_MATCH_REALM) + match = krb5_principal_compare_any_realm (context, mcreds->client, + creds->client); + else + match = krb5_principal_compare (context, mcreds->client, + creds->client); + } + + if (match && (whichfields & KRB5_TC_MATCH_KEYTYPE)) + match = krb5_enctypes_compatible_keys(context, + mcreds->session.keytype, + creds->session.keytype); + + if (match && (whichfields & KRB5_TC_MATCH_FLAGS_EXACT)) + match = mcreds->flags.i == creds->flags.i; + + if (match && (whichfields & KRB5_TC_MATCH_FLAGS)) + match = (creds->flags.i & mcreds->flags.i) == mcreds->flags.i; + + if (match && (whichfields & KRB5_TC_MATCH_TIMES_EXACT)) + match = krb5_times_equal(&mcreds->times, &creds->times); + + if (match && (whichfields & KRB5_TC_MATCH_TIMES)) + /* compare only expiration times */ + match = (mcreds->times.renew_till <= creds->times.renew_till) && + (mcreds->times.endtime <= creds->times.endtime); + + if (match && (whichfields & KRB5_TC_MATCH_AUTHDATA)) { + unsigned int i; + if(mcreds->authdata.len != creds->authdata.len) + match = FALSE; + else + for(i = 0; match && i < mcreds->authdata.len; i++) + match = (mcreds->authdata.val[i].ad_type == + creds->authdata.val[i].ad_type) && + (krb5_data_cmp(&mcreds->authdata.val[i].ad_data, + &creds->authdata.val[i].ad_data) == 0); + } + if (match && (whichfields & KRB5_TC_MATCH_2ND_TKT)) + match = (krb5_data_cmp(&mcreds->second_ticket, &creds->second_ticket) == 0); + + if (match && (whichfields & KRB5_TC_MATCH_IS_SKEY)) + match = ((mcreds->second_ticket.length == 0) == + (creds->second_ticket.length == 0)); + + return match; +} diff --git a/lib/krb5/crypto.c b/lib/krb5/crypto.c new file mode 100644 index 0000000..2e63490 --- /dev/null +++ b/lib/krb5/crypto.c @@ -0,0 +1,4192 @@ +/* + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" +RCSID("$Id: crypto.c 22200 2007-12-07 13:48:01Z lha $"); + +#undef CRYPTO_DEBUG +#ifdef CRYPTO_DEBUG +static void krb5_crypto_debug(krb5_context, int, size_t, krb5_keyblock*); +#endif + + +struct key_data { + krb5_keyblock *key; + krb5_data *schedule; +}; + +struct key_usage { + unsigned usage; + struct key_data key; +}; + +struct krb5_crypto_data { + struct encryption_type *et; + struct key_data key; + int num_key_usage; + struct key_usage *key_usage; +}; + +#define CRYPTO_ETYPE(C) ((C)->et->type) + +/* bits for `flags' below */ +#define F_KEYED 1 /* checksum is keyed */ +#define F_CPROOF 2 /* checksum is collision proof */ +#define F_DERIVED 4 /* uses derived keys */ +#define F_VARIANT 8 /* uses `variant' keys (6.4.3) */ +#define F_PSEUDO 16 /* not a real protocol type */ +#define F_SPECIAL 32 /* backwards */ +#define F_DISABLED 64 /* enctype/checksum disabled */ + +struct salt_type { + krb5_salttype type; + const char *name; + krb5_error_code (*string_to_key)(krb5_context, krb5_enctype, krb5_data, + krb5_salt, krb5_data, krb5_keyblock*); +}; + +struct key_type { + krb5_keytype type; /* XXX */ + const char *name; + size_t bits; + size_t size; + size_t schedule_size; +#if 0 + krb5_enctype best_etype; +#endif + void (*random_key)(krb5_context, krb5_keyblock*); + void (*schedule)(krb5_context, struct key_data *); + struct salt_type *string_to_key; + void (*random_to_key)(krb5_context, krb5_keyblock*, const void*, size_t); +}; + +struct checksum_type { + krb5_cksumtype type; + const char *name; + size_t blocksize; + size_t checksumsize; + unsigned flags; + void (*checksum)(krb5_context context, + struct key_data *key, + const void *buf, size_t len, + unsigned usage, + Checksum *csum); + krb5_error_code (*verify)(krb5_context context, + struct key_data *key, + const void *buf, size_t len, + unsigned usage, + Checksum *csum); +}; + +struct encryption_type { + krb5_enctype type; + const char *name; + heim_oid *oid; + size_t blocksize; + size_t padsize; + size_t confoundersize; + struct key_type *keytype; + struct checksum_type *checksum; + struct checksum_type *keyed_checksum; + unsigned flags; + krb5_error_code (*encrypt)(krb5_context context, + struct key_data *key, + void *data, size_t len, + krb5_boolean encryptp, + int usage, + void *ivec); + size_t prf_length; + krb5_error_code (*prf)(krb5_context, + krb5_crypto, const krb5_data *, krb5_data *); +}; + +#define ENCRYPTION_USAGE(U) (((U) << 8) | 0xAA) +#define INTEGRITY_USAGE(U) (((U) << 8) | 0x55) +#define CHECKSUM_USAGE(U) (((U) << 8) | 0x99) + +static struct checksum_type *_find_checksum(krb5_cksumtype type); +static struct encryption_type *_find_enctype(krb5_enctype type); +static struct key_type *_find_keytype(krb5_keytype type); +static krb5_error_code _get_derived_key(krb5_context, krb5_crypto, + unsigned, struct key_data**); +static struct key_data *_new_derived_key(krb5_crypto crypto, unsigned usage); +static krb5_error_code derive_key(krb5_context context, + struct encryption_type *et, + struct key_data *key, + const void *constant, + size_t len); +static krb5_error_code hmac(krb5_context context, + struct checksum_type *cm, + const void *data, + size_t len, + unsigned usage, + struct key_data *keyblock, + Checksum *result); +static void free_key_data(krb5_context context, struct key_data *key); +static krb5_error_code usage2arcfour (krb5_context, unsigned *); +static void xor (DES_cblock *, const unsigned char *); + +/************************************************************ + * * + ************************************************************/ + +static HEIMDAL_MUTEX crypto_mutex = HEIMDAL_MUTEX_INITIALIZER; + + +static void +krb5_DES_random_key(krb5_context context, + krb5_keyblock *key) +{ + DES_cblock *k = key->keyvalue.data; + do { + krb5_generate_random_block(k, sizeof(DES_cblock)); + DES_set_odd_parity(k); + } while(DES_is_weak_key(k)); +} + +static void +krb5_DES_schedule(krb5_context context, + struct key_data *key) +{ + DES_set_key(key->key->keyvalue.data, key->schedule->data); +} + +#ifdef ENABLE_AFS_STRING_TO_KEY + +/* This defines the Andrew string_to_key function. It accepts a password + * string as input and converts it via a one-way encryption algorithm to a DES + * encryption key. It is compatible with the original Andrew authentication + * service password database. + */ + +/* + * Short passwords, i.e 8 characters or less. + */ +static void +krb5_DES_AFS3_CMU_string_to_key (krb5_data pw, + krb5_data cell, + DES_cblock *key) +{ + char password[8+1]; /* crypt is limited to 8 chars anyway */ + int i; + + for(i = 0; i < 8; i++) { + char c = ((i < pw.length) ? ((char*)pw.data)[i] : 0) ^ + ((i < cell.length) ? + tolower(((unsigned char*)cell.data)[i]) : 0); + password[i] = c ? c : 'X'; + } + password[8] = '\0'; + + memcpy(key, crypt(password, "p1") + 2, sizeof(DES_cblock)); + + /* parity is inserted into the LSB so left shift each byte up one + bit. This allows ascii characters with a zero MSB to retain as + much significance as possible. */ + for (i = 0; i < sizeof(DES_cblock); i++) + ((unsigned char*)key)[i] <<= 1; + DES_set_odd_parity (key); +} + +/* + * Long passwords, i.e 9 characters or more. + */ +static void +krb5_DES_AFS3_Transarc_string_to_key (krb5_data pw, + krb5_data cell, + DES_cblock *key) +{ + DES_key_schedule schedule; + DES_cblock temp_key; + DES_cblock ivec; + char password[512]; + size_t passlen; + + memcpy(password, pw.data, min(pw.length, sizeof(password))); + if(pw.length < sizeof(password)) { + int len = min(cell.length, sizeof(password) - pw.length); + int i; + + memcpy(password + pw.length, cell.data, len); + for (i = pw.length; i < pw.length + len; ++i) + password[i] = tolower((unsigned char)password[i]); + } + passlen = min(sizeof(password), pw.length + cell.length); + memcpy(&ivec, "kerberos", 8); + memcpy(&temp_key, "kerberos", 8); + DES_set_odd_parity (&temp_key); + DES_set_key (&temp_key, &schedule); + DES_cbc_cksum ((void*)password, &ivec, passlen, &schedule, &ivec); + + memcpy(&temp_key, &ivec, 8); + DES_set_odd_parity (&temp_key); + DES_set_key (&temp_key, &schedule); + DES_cbc_cksum ((void*)password, key, passlen, &schedule, &ivec); + memset(&schedule, 0, sizeof(schedule)); + memset(&temp_key, 0, sizeof(temp_key)); + memset(&ivec, 0, sizeof(ivec)); + memset(password, 0, sizeof(password)); + + DES_set_odd_parity (key); +} + +static krb5_error_code +DES_AFS3_string_to_key(krb5_context context, + krb5_enctype enctype, + krb5_data password, + krb5_salt salt, + krb5_data opaque, + krb5_keyblock *key) +{ + DES_cblock tmp; + if(password.length > 8) + krb5_DES_AFS3_Transarc_string_to_key(password, salt.saltvalue, &tmp); + else + krb5_DES_AFS3_CMU_string_to_key(password, salt.saltvalue, &tmp); + key->keytype = enctype; + krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp)); + memset(&key, 0, sizeof(key)); + return 0; +} +#endif /* ENABLE_AFS_STRING_TO_KEY */ + +static void +DES_string_to_key_int(unsigned char *data, size_t length, DES_cblock *key) +{ + DES_key_schedule schedule; + int i; + int reverse = 0; + unsigned char *p; + + unsigned char swap[] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, + 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf }; + memset(key, 0, 8); + + p = (unsigned char*)key; + for (i = 0; i < length; i++) { + unsigned char tmp = data[i]; + if (!reverse) + *p++ ^= (tmp << 1); + else + *--p ^= (swap[tmp & 0xf] << 4) | swap[(tmp & 0xf0) >> 4]; + if((i % 8) == 7) + reverse = !reverse; + } + DES_set_odd_parity(key); + if(DES_is_weak_key(key)) + (*key)[7] ^= 0xF0; + DES_set_key(key, &schedule); + DES_cbc_cksum((void*)data, key, length, &schedule, key); + memset(&schedule, 0, sizeof(schedule)); + DES_set_odd_parity(key); + if(DES_is_weak_key(key)) + (*key)[7] ^= 0xF0; +} + +static krb5_error_code +krb5_DES_string_to_key(krb5_context context, + krb5_enctype enctype, + krb5_data password, + krb5_salt salt, + krb5_data opaque, + krb5_keyblock *key) +{ + unsigned char *s; + size_t len; + DES_cblock tmp; + +#ifdef ENABLE_AFS_STRING_TO_KEY + if (opaque.length == 1) { + unsigned long v; + _krb5_get_int(opaque.data, &v, 1); + if (v == 1) + return DES_AFS3_string_to_key(context, enctype, password, + salt, opaque, key); + } +#endif + + len = password.length + salt.saltvalue.length; + s = malloc(len); + if(len > 0 && s == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + memcpy(s, password.data, password.length); + memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length); + DES_string_to_key_int(s, len, &tmp); + key->keytype = enctype; + krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp)); + memset(&tmp, 0, sizeof(tmp)); + memset(s, 0, len); + free(s); + return 0; +} + +static void +krb5_DES_random_to_key(krb5_context context, + krb5_keyblock *key, + const void *data, + size_t size) +{ + DES_cblock *k = key->keyvalue.data; + memcpy(k, data, key->keyvalue.length); + DES_set_odd_parity(k); + if(DES_is_weak_key(k)) + xor(k, (const unsigned char*)"\0\0\0\0\0\0\0\xf0"); +} + +/* + * + */ + +static void +DES3_random_key(krb5_context context, + krb5_keyblock *key) +{ + DES_cblock *k = key->keyvalue.data; + do { + krb5_generate_random_block(k, 3 * sizeof(DES_cblock)); + DES_set_odd_parity(&k[0]); + DES_set_odd_parity(&k[1]); + DES_set_odd_parity(&k[2]); + } while(DES_is_weak_key(&k[0]) || + DES_is_weak_key(&k[1]) || + DES_is_weak_key(&k[2])); +} + +static void +DES3_schedule(krb5_context context, + struct key_data *key) +{ + DES_cblock *k = key->key->keyvalue.data; + DES_key_schedule *s = key->schedule->data; + DES_set_key(&k[0], &s[0]); + DES_set_key(&k[1], &s[1]); + DES_set_key(&k[2], &s[2]); +} + +/* + * A = A xor B. A & B are 8 bytes. + */ + +static void +xor (DES_cblock *key, const unsigned char *b) +{ + unsigned char *a = (unsigned char*)key; + a[0] ^= b[0]; + a[1] ^= b[1]; + a[2] ^= b[2]; + a[3] ^= b[3]; + a[4] ^= b[4]; + a[5] ^= b[5]; + a[6] ^= b[6]; + a[7] ^= b[7]; +} + +static krb5_error_code +DES3_string_to_key(krb5_context context, + krb5_enctype enctype, + krb5_data password, + krb5_salt salt, + krb5_data opaque, + krb5_keyblock *key) +{ + char *str; + size_t len; + unsigned char tmp[24]; + DES_cblock keys[3]; + krb5_error_code ret; + + len = password.length + salt.saltvalue.length; + str = malloc(len); + if(len != 0 && str == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + memcpy(str, password.data, password.length); + memcpy(str + password.length, salt.saltvalue.data, salt.saltvalue.length); + { + DES_cblock ivec; + DES_key_schedule s[3]; + int i; + + ret = _krb5_n_fold(str, len, tmp, 24); + if (ret) { + memset(str, 0, len); + free(str); + krb5_set_error_string(context, "out of memory"); + return ret; + } + + for(i = 0; i < 3; i++){ + memcpy(keys + i, tmp + i * 8, sizeof(keys[i])); + DES_set_odd_parity(keys + i); + if(DES_is_weak_key(keys + i)) + xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0"); + DES_set_key(keys + i, &s[i]); + } + memset(&ivec, 0, sizeof(ivec)); + DES_ede3_cbc_encrypt(tmp, + tmp, sizeof(tmp), + &s[0], &s[1], &s[2], &ivec, DES_ENCRYPT); + memset(s, 0, sizeof(s)); + memset(&ivec, 0, sizeof(ivec)); + for(i = 0; i < 3; i++){ + memcpy(keys + i, tmp + i * 8, sizeof(keys[i])); + DES_set_odd_parity(keys + i); + if(DES_is_weak_key(keys + i)) + xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0"); + } + memset(tmp, 0, sizeof(tmp)); + } + key->keytype = enctype; + krb5_data_copy(&key->keyvalue, keys, sizeof(keys)); + memset(keys, 0, sizeof(keys)); + memset(str, 0, len); + free(str); + return 0; +} + +static krb5_error_code +DES3_string_to_key_derived(krb5_context context, + krb5_enctype enctype, + krb5_data password, + krb5_salt salt, + krb5_data opaque, + krb5_keyblock *key) +{ + krb5_error_code ret; + size_t len = password.length + salt.saltvalue.length; + char *s; + + s = malloc(len); + if(len != 0 && s == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + memcpy(s, password.data, password.length); + memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length); + ret = krb5_string_to_key_derived(context, + s, + len, + enctype, + key); + memset(s, 0, len); + free(s); + return ret; +} + +static void +DES3_random_to_key(krb5_context context, + krb5_keyblock *key, + const void *data, + size_t size) +{ + unsigned char *x = key->keyvalue.data; + const u_char *q = data; + DES_cblock *k; + int i, j; + + memset(x, 0, sizeof(x)); + for (i = 0; i < 3; ++i) { + unsigned char foo; + for (j = 0; j < 7; ++j) { + unsigned char b = q[7 * i + j]; + + x[8 * i + j] = b; + } + foo = 0; + for (j = 6; j >= 0; --j) { + foo |= q[7 * i + j] & 1; + foo <<= 1; + } + x[8 * i + 7] = foo; + } + k = key->keyvalue.data; + for (i = 0; i < 3; i++) { + DES_set_odd_parity(&k[i]); + if(DES_is_weak_key(&k[i])) + xor(&k[i], (const unsigned char*)"\0\0\0\0\0\0\0\xf0"); + } +} + +/* + * ARCFOUR + */ + +static void +ARCFOUR_schedule(krb5_context context, + struct key_data *kd) +{ + RC4_set_key (kd->schedule->data, + kd->key->keyvalue.length, kd->key->keyvalue.data); +} + +static krb5_error_code +ARCFOUR_string_to_key(krb5_context context, + krb5_enctype enctype, + krb5_data password, + krb5_salt salt, + krb5_data opaque, + krb5_keyblock *key) +{ + char *s, *p; + size_t len; + int i; + MD4_CTX m; + krb5_error_code ret; + + len = 2 * password.length; + s = malloc (len); + if (len != 0 && s == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + ret = ENOMEM; + goto out; + } + for (p = s, i = 0; i < password.length; ++i) { + *p++ = ((char *)password.data)[i]; + *p++ = 0; + } + MD4_Init (&m); + MD4_Update (&m, s, len); + key->keytype = enctype; + ret = krb5_data_alloc (&key->keyvalue, 16); + if (ret) { + krb5_set_error_string(context, "malloc: out of memory"); + goto out; + } + MD4_Final (key->keyvalue.data, &m); + memset (s, 0, len); + ret = 0; +out: + free (s); + return ret; +} + +/* + * AES + */ + +int _krb5_AES_string_to_default_iterator = 4096; + +static krb5_error_code +AES_string_to_key(krb5_context context, + krb5_enctype enctype, + krb5_data password, + krb5_salt salt, + krb5_data opaque, + krb5_keyblock *key) +{ + krb5_error_code ret; + uint32_t iter; + struct encryption_type *et; + struct key_data kd; + + if (opaque.length == 0) + iter = _krb5_AES_string_to_default_iterator; + else if (opaque.length == 4) { + unsigned long v; + _krb5_get_int(opaque.data, &v, 4); + iter = ((uint32_t)v); + } else + return KRB5_PROG_KEYTYPE_NOSUPP; /* XXX */ + + et = _find_enctype(enctype); + if (et == NULL) + return KRB5_PROG_KEYTYPE_NOSUPP; + + kd.schedule = NULL; + ALLOC(kd.key, 1); + if(kd.key == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + kd.key->keytype = enctype; + ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size); + if (ret) { + krb5_set_error_string(context, "Failed to allocate pkcs5 key"); + return ret; + } + + ret = PKCS5_PBKDF2_HMAC_SHA1(password.data, password.length, + salt.saltvalue.data, salt.saltvalue.length, + iter, + et->keytype->size, kd.key->keyvalue.data); + if (ret != 1) { + free_key_data(context, &kd); + krb5_set_error_string(context, "Error calculating s2k"); + return KRB5_PROG_KEYTYPE_NOSUPP; + } + + ret = derive_key(context, et, &kd, "kerberos", strlen("kerberos")); + if (ret == 0) + ret = krb5_copy_keyblock_contents(context, kd.key, key); + free_key_data(context, &kd); + + return ret; +} + +struct krb5_aes_schedule { + AES_KEY ekey; + AES_KEY dkey; +}; + +static void +AES_schedule(krb5_context context, + struct key_data *kd) +{ + struct krb5_aes_schedule *key = kd->schedule->data; + int bits = kd->key->keyvalue.length * 8; + + memset(key, 0, sizeof(*key)); + AES_set_encrypt_key(kd->key->keyvalue.data, bits, &key->ekey); + AES_set_decrypt_key(kd->key->keyvalue.data, bits, &key->dkey); +} + +/* + * + */ + +static struct salt_type des_salt[] = { + { + KRB5_PW_SALT, + "pw-salt", + krb5_DES_string_to_key + }, +#ifdef ENABLE_AFS_STRING_TO_KEY + { + KRB5_AFS3_SALT, + "afs3-salt", + DES_AFS3_string_to_key + }, +#endif + { 0 } +}; + +static struct salt_type des3_salt[] = { + { + KRB5_PW_SALT, + "pw-salt", + DES3_string_to_key + }, + { 0 } +}; + +static struct salt_type des3_salt_derived[] = { + { + KRB5_PW_SALT, + "pw-salt", + DES3_string_to_key_derived + }, + { 0 } +}; + +static struct salt_type AES_salt[] = { + { + KRB5_PW_SALT, + "pw-salt", + AES_string_to_key + }, + { 0 } +}; + +static struct salt_type arcfour_salt[] = { + { + KRB5_PW_SALT, + "pw-salt", + ARCFOUR_string_to_key + }, + { 0 } +}; + +/* + * + */ + +static struct key_type keytype_null = { + KEYTYPE_NULL, + "null", + 0, + 0, + 0, + NULL, + NULL, + NULL +}; + +static struct key_type keytype_des = { + KEYTYPE_DES, + "des", + 56, + sizeof(DES_cblock), + sizeof(DES_key_schedule), + krb5_DES_random_key, + krb5_DES_schedule, + des_salt, + krb5_DES_random_to_key +}; + +static struct key_type keytype_des3 = { + KEYTYPE_DES3, + "des3", + 168, + 3 * sizeof(DES_cblock), + 3 * sizeof(DES_key_schedule), + DES3_random_key, + DES3_schedule, + des3_salt, + DES3_random_to_key +}; + +static struct key_type keytype_des3_derived = { + KEYTYPE_DES3, + "des3", + 168, + 3 * sizeof(DES_cblock), + 3 * sizeof(DES_key_schedule), + DES3_random_key, + DES3_schedule, + des3_salt_derived, + DES3_random_to_key +}; + +static struct key_type keytype_aes128 = { + KEYTYPE_AES128, + "aes-128", + 128, + 16, + sizeof(struct krb5_aes_schedule), + NULL, + AES_schedule, + AES_salt +}; + +static struct key_type keytype_aes256 = { + KEYTYPE_AES256, + "aes-256", + 256, + 32, + sizeof(struct krb5_aes_schedule), + NULL, + AES_schedule, + AES_salt +}; + +static struct key_type keytype_arcfour = { + KEYTYPE_ARCFOUR, + "arcfour", + 128, + 16, + sizeof(RC4_KEY), + NULL, + ARCFOUR_schedule, + arcfour_salt +}; + +static struct key_type *keytypes[] = { + &keytype_null, + &keytype_des, + &keytype_des3_derived, + &keytype_des3, + &keytype_aes128, + &keytype_aes256, + &keytype_arcfour +}; + +static int num_keytypes = sizeof(keytypes) / sizeof(keytypes[0]); + +static struct key_type * +_find_keytype(krb5_keytype type) +{ + int i; + for(i = 0; i < num_keytypes; i++) + if(keytypes[i]->type == type) + return keytypes[i]; + return NULL; +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_salttype_to_string (krb5_context context, + krb5_enctype etype, + krb5_salttype stype, + char **string) +{ + struct encryption_type *e; + struct salt_type *st; + + e = _find_enctype (etype); + if (e == NULL) { + krb5_set_error_string(context, "encryption type %d not supported", + etype); + return KRB5_PROG_ETYPE_NOSUPP; + } + for (st = e->keytype->string_to_key; st && st->type; st++) { + if (st->type == stype) { + *string = strdup (st->name); + if (*string == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + return 0; + } + } + krb5_set_error_string(context, "salttype %d not supported", stype); + return HEIM_ERR_SALTTYPE_NOSUPP; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_salttype (krb5_context context, + krb5_enctype etype, + const char *string, + krb5_salttype *salttype) +{ + struct encryption_type *e; + struct salt_type *st; + + e = _find_enctype (etype); + if (e == NULL) { + krb5_set_error_string(context, "encryption type %d not supported", + etype); + return KRB5_PROG_ETYPE_NOSUPP; + } + for (st = e->keytype->string_to_key; st && st->type; st++) { + if (strcasecmp (st->name, string) == 0) { + *salttype = st->type; + return 0; + } + } + krb5_set_error_string(context, "salttype %s not supported", string); + return HEIM_ERR_SALTTYPE_NOSUPP; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_pw_salt(krb5_context context, + krb5_const_principal principal, + krb5_salt *salt) +{ + size_t len; + int i; + krb5_error_code ret; + char *p; + + salt->salttype = KRB5_PW_SALT; + len = strlen(principal->realm); + for (i = 0; i < principal->name.name_string.len; ++i) + len += strlen(principal->name.name_string.val[i]); + ret = krb5_data_alloc (&salt->saltvalue, len); + if (ret) + return ret; + p = salt->saltvalue.data; + memcpy (p, principal->realm, strlen(principal->realm)); + p += strlen(principal->realm); + for (i = 0; i < principal->name.name_string.len; ++i) { + memcpy (p, + principal->name.name_string.val[i], + strlen(principal->name.name_string.val[i])); + p += strlen(principal->name.name_string.val[i]); + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_free_salt(krb5_context context, + krb5_salt salt) +{ + krb5_data_free(&salt.saltvalue); + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_key_data (krb5_context context, + krb5_enctype enctype, + krb5_data password, + krb5_principal principal, + krb5_keyblock *key) +{ + krb5_error_code ret; + krb5_salt salt; + + ret = krb5_get_pw_salt(context, principal, &salt); + if(ret) + return ret; + ret = krb5_string_to_key_data_salt(context, enctype, password, salt, key); + krb5_free_salt(context, salt); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_key (krb5_context context, + krb5_enctype enctype, + const char *password, + krb5_principal principal, + krb5_keyblock *key) +{ + krb5_data pw; + pw.data = rk_UNCONST(password); + pw.length = strlen(password); + return krb5_string_to_key_data(context, enctype, pw, principal, key); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_key_data_salt (krb5_context context, + krb5_enctype enctype, + krb5_data password, + krb5_salt salt, + krb5_keyblock *key) +{ + krb5_data opaque; + krb5_data_zero(&opaque); + return krb5_string_to_key_data_salt_opaque(context, enctype, password, + salt, opaque, key); +} + +/* + * Do a string -> key for encryption type `enctype' operation on + * `password' (with salt `salt' and the enctype specific data string + * `opaque'), returning the resulting key in `key' + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_key_data_salt_opaque (krb5_context context, + krb5_enctype enctype, + krb5_data password, + krb5_salt salt, + krb5_data opaque, + krb5_keyblock *key) +{ + struct encryption_type *et =_find_enctype(enctype); + struct salt_type *st; + if(et == NULL) { + krb5_set_error_string(context, "encryption type %d not supported", + enctype); + return KRB5_PROG_ETYPE_NOSUPP; + } + for(st = et->keytype->string_to_key; st && st->type; st++) + if(st->type == salt.salttype) + return (*st->string_to_key)(context, enctype, password, + salt, opaque, key); + krb5_set_error_string(context, "salt type %d not supported", + salt.salttype); + return HEIM_ERR_SALTTYPE_NOSUPP; +} + +/* + * Do a string -> key for encryption type `enctype' operation on the + * string `password' (with salt `salt'), returning the resulting key + * in `key' + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_key_salt (krb5_context context, + krb5_enctype enctype, + const char *password, + krb5_salt salt, + krb5_keyblock *key) +{ + krb5_data pw; + pw.data = rk_UNCONST(password); + pw.length = strlen(password); + return krb5_string_to_key_data_salt(context, enctype, pw, salt, key); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_key_salt_opaque (krb5_context context, + krb5_enctype enctype, + const char *password, + krb5_salt salt, + krb5_data opaque, + krb5_keyblock *key) +{ + krb5_data pw; + pw.data = rk_UNCONST(password); + pw.length = strlen(password); + return krb5_string_to_key_data_salt_opaque(context, enctype, + pw, salt, opaque, key); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_keytype_to_string(krb5_context context, + krb5_keytype keytype, + char **string) +{ + struct key_type *kt = _find_keytype(keytype); + if(kt == NULL) { + krb5_set_error_string(context, "key type %d not supported", keytype); + return KRB5_PROG_KEYTYPE_NOSUPP; + } + *string = strdup(kt->name); + if(*string == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_keytype(krb5_context context, + const char *string, + krb5_keytype *keytype) +{ + int i; + for(i = 0; i < num_keytypes; i++) + if(strcasecmp(keytypes[i]->name, string) == 0){ + *keytype = keytypes[i]->type; + return 0; + } + krb5_set_error_string(context, "key type %s not supported", string); + return KRB5_PROG_KEYTYPE_NOSUPP; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_enctype_keysize(krb5_context context, + krb5_enctype type, + size_t *keysize) +{ + struct encryption_type *et = _find_enctype(type); + if(et == NULL) { + krb5_set_error_string(context, "encryption type %d not supported", + type); + return KRB5_PROG_ETYPE_NOSUPP; + } + *keysize = et->keytype->size; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_enctype_keybits(krb5_context context, + krb5_enctype type, + size_t *keybits) +{ + struct encryption_type *et = _find_enctype(type); + if(et == NULL) { + krb5_set_error_string(context, "encryption type %d not supported", + type); + return KRB5_PROG_ETYPE_NOSUPP; + } + *keybits = et->keytype->bits; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_generate_random_keyblock(krb5_context context, + krb5_enctype type, + krb5_keyblock *key) +{ + krb5_error_code ret; + struct encryption_type *et = _find_enctype(type); + if(et == NULL) { + krb5_set_error_string(context, "encryption type %d not supported", + type); + return KRB5_PROG_ETYPE_NOSUPP; + } + ret = krb5_data_alloc(&key->keyvalue, et->keytype->size); + if(ret) + return ret; + key->keytype = type; + if(et->keytype->random_key) + (*et->keytype->random_key)(context, key); + else + krb5_generate_random_block(key->keyvalue.data, + key->keyvalue.length); + return 0; +} + +static krb5_error_code +_key_schedule(krb5_context context, + struct key_data *key) +{ + krb5_error_code ret; + struct encryption_type *et = _find_enctype(key->key->keytype); + struct key_type *kt = et->keytype; + + if(kt->schedule == NULL) + return 0; + if (key->schedule != NULL) + return 0; + ALLOC(key->schedule, 1); + if(key->schedule == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + ret = krb5_data_alloc(key->schedule, kt->schedule_size); + if(ret) { + free(key->schedule); + key->schedule = NULL; + return ret; + } + (*kt->schedule)(context, key); + return 0; +} + +/************************************************************ + * * + ************************************************************/ + +static void +NONE_checksum(krb5_context context, + struct key_data *key, + const void *data, + size_t len, + unsigned usage, + Checksum *C) +{ +} + +static void +CRC32_checksum(krb5_context context, + struct key_data *key, + const void *data, + size_t len, + unsigned usage, + Checksum *C) +{ + uint32_t crc; + unsigned char *r = C->checksum.data; + _krb5_crc_init_table (); + crc = _krb5_crc_update (data, len, 0); + r[0] = crc & 0xff; + r[1] = (crc >> 8) & 0xff; + r[2] = (crc >> 16) & 0xff; + r[3] = (crc >> 24) & 0xff; +} + +static void +RSA_MD4_checksum(krb5_context context, + struct key_data *key, + const void *data, + size_t len, + unsigned usage, + Checksum *C) +{ + MD4_CTX m; + + MD4_Init (&m); + MD4_Update (&m, data, len); + MD4_Final (C->checksum.data, &m); +} + +static void +RSA_MD4_DES_checksum(krb5_context context, + struct key_data *key, + const void *data, + size_t len, + unsigned usage, + Checksum *cksum) +{ + MD4_CTX md4; + DES_cblock ivec; + unsigned char *p = cksum->checksum.data; + + krb5_generate_random_block(p, 8); + MD4_Init (&md4); + MD4_Update (&md4, p, 8); + MD4_Update (&md4, data, len); + MD4_Final (p + 8, &md4); + memset (&ivec, 0, sizeof(ivec)); + DES_cbc_encrypt(p, + p, + 24, + key->schedule->data, + &ivec, + DES_ENCRYPT); +} + +static krb5_error_code +RSA_MD4_DES_verify(krb5_context context, + struct key_data *key, + const void *data, + size_t len, + unsigned usage, + Checksum *C) +{ + MD4_CTX md4; + unsigned char tmp[24]; + unsigned char res[16]; + DES_cblock ivec; + krb5_error_code ret = 0; + + memset(&ivec, 0, sizeof(ivec)); + DES_cbc_encrypt(C->checksum.data, + (void*)tmp, + C->checksum.length, + key->schedule->data, + &ivec, + DES_DECRYPT); + MD4_Init (&md4); + MD4_Update (&md4, tmp, 8); /* confounder */ + MD4_Update (&md4, data, len); + MD4_Final (res, &md4); + if(memcmp(res, tmp + 8, sizeof(res)) != 0) { + krb5_clear_error_string (context); + ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; + } + memset(tmp, 0, sizeof(tmp)); + memset(res, 0, sizeof(res)); + return ret; +} + +static void +RSA_MD5_checksum(krb5_context context, + struct key_data *key, + const void *data, + size_t len, + unsigned usage, + Checksum *C) +{ + MD5_CTX m; + + MD5_Init (&m); + MD5_Update(&m, data, len); + MD5_Final (C->checksum.data, &m); +} + +static void +RSA_MD5_DES_checksum(krb5_context context, + struct key_data *key, + const void *data, + size_t len, + unsigned usage, + Checksum *C) +{ + MD5_CTX md5; + DES_cblock ivec; + unsigned char *p = C->checksum.data; + + krb5_generate_random_block(p, 8); + MD5_Init (&md5); + MD5_Update (&md5, p, 8); + MD5_Update (&md5, data, len); + MD5_Final (p + 8, &md5); + memset (&ivec, 0, sizeof(ivec)); + DES_cbc_encrypt(p, + p, + 24, + key->schedule->data, + &ivec, + DES_ENCRYPT); +} + +static krb5_error_code +RSA_MD5_DES_verify(krb5_context context, + struct key_data *key, + const void *data, + size_t len, + unsigned usage, + Checksum *C) +{ + MD5_CTX md5; + unsigned char tmp[24]; + unsigned char res[16]; + DES_cblock ivec; + DES_key_schedule *sched = key->schedule->data; + krb5_error_code ret = 0; + + memset(&ivec, 0, sizeof(ivec)); + DES_cbc_encrypt(C->checksum.data, + (void*)tmp, + C->checksum.length, + &sched[0], + &ivec, + DES_DECRYPT); + MD5_Init (&md5); + MD5_Update (&md5, tmp, 8); /* confounder */ + MD5_Update (&md5, data, len); + MD5_Final (res, &md5); + if(memcmp(res, tmp + 8, sizeof(res)) != 0) { + krb5_clear_error_string (context); + ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; + } + memset(tmp, 0, sizeof(tmp)); + memset(res, 0, sizeof(res)); + return ret; +} + +static void +RSA_MD5_DES3_checksum(krb5_context context, + struct key_data *key, + const void *data, + size_t len, + unsigned usage, + Checksum *C) +{ + MD5_CTX md5; + DES_cblock ivec; + unsigned char *p = C->checksum.data; + DES_key_schedule *sched = key->schedule->data; + + krb5_generate_random_block(p, 8); + MD5_Init (&md5); + MD5_Update (&md5, p, 8); + MD5_Update (&md5, data, len); + MD5_Final (p + 8, &md5); + memset (&ivec, 0, sizeof(ivec)); + DES_ede3_cbc_encrypt(p, + p, + 24, + &sched[0], &sched[1], &sched[2], + &ivec, + DES_ENCRYPT); +} + +static krb5_error_code +RSA_MD5_DES3_verify(krb5_context context, + struct key_data *key, + const void *data, + size_t len, + unsigned usage, + Checksum *C) +{ + MD5_CTX md5; + unsigned char tmp[24]; + unsigned char res[16]; + DES_cblock ivec; + DES_key_schedule *sched = key->schedule->data; + krb5_error_code ret = 0; + + memset(&ivec, 0, sizeof(ivec)); + DES_ede3_cbc_encrypt(C->checksum.data, + (void*)tmp, + C->checksum.length, + &sched[0], &sched[1], &sched[2], + &ivec, + DES_DECRYPT); + MD5_Init (&md5); + MD5_Update (&md5, tmp, 8); /* confounder */ + MD5_Update (&md5, data, len); + MD5_Final (res, &md5); + if(memcmp(res, tmp + 8, sizeof(res)) != 0) { + krb5_clear_error_string (context); + ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; + } + memset(tmp, 0, sizeof(tmp)); + memset(res, 0, sizeof(res)); + return ret; +} + +static void +SHA1_checksum(krb5_context context, + struct key_data *key, + const void *data, + size_t len, + unsigned usage, + Checksum *C) +{ + SHA_CTX m; + + SHA1_Init(&m); + SHA1_Update(&m, data, len); + SHA1_Final(C->checksum.data, &m); +} + +/* HMAC according to RFC2104 */ +static krb5_error_code +hmac(krb5_context context, + struct checksum_type *cm, + const void *data, + size_t len, + unsigned usage, + struct key_data *keyblock, + Checksum *result) +{ + unsigned char *ipad, *opad; + unsigned char *key; + size_t key_len; + int i; + + ipad = malloc(cm->blocksize + len); + if (ipad == NULL) + return ENOMEM; + opad = malloc(cm->blocksize + cm->checksumsize); + if (opad == NULL) { + free(ipad); + return ENOMEM; + } + memset(ipad, 0x36, cm->blocksize); + memset(opad, 0x5c, cm->blocksize); + + if(keyblock->key->keyvalue.length > cm->blocksize){ + (*cm->checksum)(context, + keyblock, + keyblock->key->keyvalue.data, + keyblock->key->keyvalue.length, + usage, + result); + key = result->checksum.data; + key_len = result->checksum.length; + } else { + key = keyblock->key->keyvalue.data; + key_len = keyblock->key->keyvalue.length; + } + for(i = 0; i < key_len; i++){ + ipad[i] ^= key[i]; + opad[i] ^= key[i]; + } + memcpy(ipad + cm->blocksize, data, len); + (*cm->checksum)(context, keyblock, ipad, cm->blocksize + len, + usage, result); + memcpy(opad + cm->blocksize, result->checksum.data, + result->checksum.length); + (*cm->checksum)(context, keyblock, opad, + cm->blocksize + cm->checksumsize, usage, result); + memset(ipad, 0, cm->blocksize + len); + free(ipad); + memset(opad, 0, cm->blocksize + cm->checksumsize); + free(opad); + + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_hmac(krb5_context context, + krb5_cksumtype cktype, + const void *data, + size_t len, + unsigned usage, + krb5_keyblock *key, + Checksum *result) +{ + struct checksum_type *c = _find_checksum(cktype); + struct key_data kd; + krb5_error_code ret; + + if (c == NULL) { + krb5_set_error_string (context, "checksum type %d not supported", + cktype); + return KRB5_PROG_SUMTYPE_NOSUPP; + } + + kd.key = key; + kd.schedule = NULL; + + ret = hmac(context, c, data, len, usage, &kd, result); + + if (kd.schedule) + krb5_free_data(context, kd.schedule); + + return ret; + } + +static void +SP_HMAC_SHA1_checksum(krb5_context context, + struct key_data *key, + const void *data, + size_t len, + unsigned usage, + Checksum *result) +{ + struct checksum_type *c = _find_checksum(CKSUMTYPE_SHA1); + Checksum res; + char sha1_data[20]; + krb5_error_code ret; + + res.checksum.data = sha1_data; + res.checksum.length = sizeof(sha1_data); + + ret = hmac(context, c, data, len, usage, key, &res); + if (ret) + krb5_abortx(context, "hmac failed"); + memcpy(result->checksum.data, res.checksum.data, result->checksum.length); +} + +/* + * checksum according to section 5. of draft-brezak-win2k-krb-rc4-hmac-03.txt + */ + +static void +HMAC_MD5_checksum(krb5_context context, + struct key_data *key, + const void *data, + size_t len, + unsigned usage, + Checksum *result) +{ + MD5_CTX md5; + struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5); + const char signature[] = "signaturekey"; + Checksum ksign_c; + struct key_data ksign; + krb5_keyblock kb; + unsigned char t[4]; + unsigned char tmp[16]; + unsigned char ksign_c_data[16]; + krb5_error_code ret; + + ksign_c.checksum.length = sizeof(ksign_c_data); + ksign_c.checksum.data = ksign_c_data; + ret = hmac(context, c, signature, sizeof(signature), 0, key, &ksign_c); + if (ret) + krb5_abortx(context, "hmac failed"); + ksign.key = &kb; + kb.keyvalue = ksign_c.checksum; + MD5_Init (&md5); + t[0] = (usage >> 0) & 0xFF; + t[1] = (usage >> 8) & 0xFF; + t[2] = (usage >> 16) & 0xFF; + t[3] = (usage >> 24) & 0xFF; + MD5_Update (&md5, t, 4); + MD5_Update (&md5, data, len); + MD5_Final (tmp, &md5); + ret = hmac(context, c, tmp, sizeof(tmp), 0, &ksign, result); + if (ret) + krb5_abortx(context, "hmac failed"); +} + +/* + * same as previous but being used while encrypting. + */ + +static void +HMAC_MD5_checksum_enc(krb5_context context, + struct key_data *key, + const void *data, + size_t len, + unsigned usage, + Checksum *result) +{ + struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5); + Checksum ksign_c; + struct key_data ksign; + krb5_keyblock kb; + unsigned char t[4]; + unsigned char ksign_c_data[16]; + krb5_error_code ret; + + t[0] = (usage >> 0) & 0xFF; + t[1] = (usage >> 8) & 0xFF; + t[2] = (usage >> 16) & 0xFF; + t[3] = (usage >> 24) & 0xFF; + + ksign_c.checksum.length = sizeof(ksign_c_data); + ksign_c.checksum.data = ksign_c_data; + ret = hmac(context, c, t, sizeof(t), 0, key, &ksign_c); + if (ret) + krb5_abortx(context, "hmac failed"); + ksign.key = &kb; + kb.keyvalue = ksign_c.checksum; + ret = hmac(context, c, data, len, 0, &ksign, result); + if (ret) + krb5_abortx(context, "hmac failed"); +} + +static struct checksum_type checksum_none = { + CKSUMTYPE_NONE, + "none", + 1, + 0, + 0, + NONE_checksum, + NULL +}; +static struct checksum_type checksum_crc32 = { + CKSUMTYPE_CRC32, + "crc32", + 1, + 4, + 0, + CRC32_checksum, + NULL +}; +static struct checksum_type checksum_rsa_md4 = { + CKSUMTYPE_RSA_MD4, + "rsa-md4", + 64, + 16, + F_CPROOF, + RSA_MD4_checksum, + NULL +}; +static struct checksum_type checksum_rsa_md4_des = { + CKSUMTYPE_RSA_MD4_DES, + "rsa-md4-des", + 64, + 24, + F_KEYED | F_CPROOF | F_VARIANT, + RSA_MD4_DES_checksum, + RSA_MD4_DES_verify +}; +#if 0 +static struct checksum_type checksum_des_mac = { + CKSUMTYPE_DES_MAC, + "des-mac", + 0, + 0, + 0, + DES_MAC_checksum +}; +static struct checksum_type checksum_des_mac_k = { + CKSUMTYPE_DES_MAC_K, + "des-mac-k", + 0, + 0, + 0, + DES_MAC_K_checksum +}; +static struct checksum_type checksum_rsa_md4_des_k = { + CKSUMTYPE_RSA_MD4_DES_K, + "rsa-md4-des-k", + 0, + 0, + 0, + RSA_MD4_DES_K_checksum, + RSA_MD4_DES_K_verify +}; +#endif +static struct checksum_type checksum_rsa_md5 = { + CKSUMTYPE_RSA_MD5, + "rsa-md5", + 64, + 16, + F_CPROOF, + RSA_MD5_checksum, + NULL +}; +static struct checksum_type checksum_rsa_md5_des = { + CKSUMTYPE_RSA_MD5_DES, + "rsa-md5-des", + 64, + 24, + F_KEYED | F_CPROOF | F_VARIANT, + RSA_MD5_DES_checksum, + RSA_MD5_DES_verify +}; +static struct checksum_type checksum_rsa_md5_des3 = { + CKSUMTYPE_RSA_MD5_DES3, + "rsa-md5-des3", + 64, + 24, + F_KEYED | F_CPROOF | F_VARIANT, + RSA_MD5_DES3_checksum, + RSA_MD5_DES3_verify +}; +static struct checksum_type checksum_sha1 = { + CKSUMTYPE_SHA1, + "sha1", + 64, + 20, + F_CPROOF, + SHA1_checksum, + NULL +}; +static struct checksum_type checksum_hmac_sha1_des3 = { + CKSUMTYPE_HMAC_SHA1_DES3, + "hmac-sha1-des3", + 64, + 20, + F_KEYED | F_CPROOF | F_DERIVED, + SP_HMAC_SHA1_checksum, + NULL +}; + +static struct checksum_type checksum_hmac_sha1_aes128 = { + CKSUMTYPE_HMAC_SHA1_96_AES_128, + "hmac-sha1-96-aes128", + 64, + 12, + F_KEYED | F_CPROOF | F_DERIVED, + SP_HMAC_SHA1_checksum, + NULL +}; + +static struct checksum_type checksum_hmac_sha1_aes256 = { + CKSUMTYPE_HMAC_SHA1_96_AES_256, + "hmac-sha1-96-aes256", + 64, + 12, + F_KEYED | F_CPROOF | F_DERIVED, + SP_HMAC_SHA1_checksum, + NULL +}; + +static struct checksum_type checksum_hmac_md5 = { + CKSUMTYPE_HMAC_MD5, + "hmac-md5", + 64, + 16, + F_KEYED | F_CPROOF, + HMAC_MD5_checksum, + NULL +}; + +static struct checksum_type checksum_hmac_md5_enc = { + CKSUMTYPE_HMAC_MD5_ENC, + "hmac-md5-enc", + 64, + 16, + F_KEYED | F_CPROOF | F_PSEUDO, + HMAC_MD5_checksum_enc, + NULL +}; + +static struct checksum_type *checksum_types[] = { + &checksum_none, + &checksum_crc32, + &checksum_rsa_md4, + &checksum_rsa_md4_des, +#if 0 + &checksum_des_mac, + &checksum_des_mac_k, + &checksum_rsa_md4_des_k, +#endif + &checksum_rsa_md5, + &checksum_rsa_md5_des, + &checksum_rsa_md5_des3, + &checksum_sha1, + &checksum_hmac_sha1_des3, + &checksum_hmac_sha1_aes128, + &checksum_hmac_sha1_aes256, + &checksum_hmac_md5, + &checksum_hmac_md5_enc +}; + +static int num_checksums = sizeof(checksum_types) / sizeof(checksum_types[0]); + +static struct checksum_type * +_find_checksum(krb5_cksumtype type) +{ + int i; + for(i = 0; i < num_checksums; i++) + if(checksum_types[i]->type == type) + return checksum_types[i]; + return NULL; +} + +static krb5_error_code +get_checksum_key(krb5_context context, + krb5_crypto crypto, + unsigned usage, /* not krb5_key_usage */ + struct checksum_type *ct, + struct key_data **key) +{ + krb5_error_code ret = 0; + + if(ct->flags & F_DERIVED) + ret = _get_derived_key(context, crypto, usage, key); + else if(ct->flags & F_VARIANT) { + int i; + + *key = _new_derived_key(crypto, 0xff/* KRB5_KU_RFC1510_VARIANT */); + if(*key == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + ret = krb5_copy_keyblock(context, crypto->key.key, &(*key)->key); + if(ret) + return ret; + for(i = 0; i < (*key)->key->keyvalue.length; i++) + ((unsigned char*)(*key)->key->keyvalue.data)[i] ^= 0xF0; + } else { + *key = &crypto->key; + } + if(ret == 0) + ret = _key_schedule(context, *key); + return ret; +} + +static krb5_error_code +create_checksum (krb5_context context, + struct checksum_type *ct, + krb5_crypto crypto, + unsigned usage, + void *data, + size_t len, + Checksum *result) +{ + krb5_error_code ret; + struct key_data *dkey; + int keyed_checksum; + + if (ct->flags & F_DISABLED) { + krb5_clear_error_string (context); + return KRB5_PROG_SUMTYPE_NOSUPP; + } + keyed_checksum = (ct->flags & F_KEYED) != 0; + if(keyed_checksum && crypto == NULL) { + krb5_set_error_string (context, "Checksum type %s is keyed " + "but no crypto context (key) was passed in", + ct->name); + return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */ + } + if(keyed_checksum) { + ret = get_checksum_key(context, crypto, usage, ct, &dkey); + if (ret) + return ret; + } else + dkey = NULL; + result->cksumtype = ct->type; + ret = krb5_data_alloc(&result->checksum, ct->checksumsize); + if (ret) + return (ret); + (*ct->checksum)(context, dkey, data, len, usage, result); + return 0; +} + +static int +arcfour_checksum_p(struct checksum_type *ct, krb5_crypto crypto) +{ + return (ct->type == CKSUMTYPE_HMAC_MD5) && + (crypto->key.key->keytype == KEYTYPE_ARCFOUR); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_create_checksum(krb5_context context, + krb5_crypto crypto, + krb5_key_usage usage, + int type, + void *data, + size_t len, + Checksum *result) +{ + struct checksum_type *ct = NULL; + unsigned keyusage; + + /* type 0 -> pick from crypto */ + if (type) { + ct = _find_checksum(type); + } else if (crypto) { + ct = crypto->et->keyed_checksum; + if (ct == NULL) + ct = crypto->et->checksum; + } + + if(ct == NULL) { + krb5_set_error_string (context, "checksum type %d not supported", + type); + return KRB5_PROG_SUMTYPE_NOSUPP; + } + + if (arcfour_checksum_p(ct, crypto)) { + keyusage = usage; + usage2arcfour(context, &keyusage); + } else + keyusage = CHECKSUM_USAGE(usage); + + return create_checksum(context, ct, crypto, keyusage, + data, len, result); +} + +static krb5_error_code +verify_checksum(krb5_context context, + krb5_crypto crypto, + unsigned usage, /* not krb5_key_usage */ + void *data, + size_t len, + Checksum *cksum) +{ + krb5_error_code ret; + struct key_data *dkey; + int keyed_checksum; + Checksum c; + struct checksum_type *ct; + + ct = _find_checksum(cksum->cksumtype); + if (ct == NULL || (ct->flags & F_DISABLED)) { + krb5_set_error_string (context, "checksum type %d not supported", + cksum->cksumtype); + return KRB5_PROG_SUMTYPE_NOSUPP; + } + if(ct->checksumsize != cksum->checksum.length) { + krb5_clear_error_string (context); + return KRB5KRB_AP_ERR_BAD_INTEGRITY; /* XXX */ + } + keyed_checksum = (ct->flags & F_KEYED) != 0; + if(keyed_checksum && crypto == NULL) { + krb5_set_error_string (context, "Checksum type %s is keyed " + "but no crypto context (key) was passed in", + ct->name); + return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */ + } + if(keyed_checksum) + ret = get_checksum_key(context, crypto, usage, ct, &dkey); + else + dkey = NULL; + if(ct->verify) + return (*ct->verify)(context, dkey, data, len, usage, cksum); + + ret = krb5_data_alloc (&c.checksum, ct->checksumsize); + if (ret) + return ret; + + (*ct->checksum)(context, dkey, data, len, usage, &c); + + if(c.checksum.length != cksum->checksum.length || + memcmp(c.checksum.data, cksum->checksum.data, c.checksum.length)) { + krb5_clear_error_string (context); + ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; + } else { + ret = 0; + } + krb5_data_free (&c.checksum); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_verify_checksum(krb5_context context, + krb5_crypto crypto, + krb5_key_usage usage, + void *data, + size_t len, + Checksum *cksum) +{ + struct checksum_type *ct; + unsigned keyusage; + + ct = _find_checksum(cksum->cksumtype); + if(ct == NULL) { + krb5_set_error_string (context, "checksum type %d not supported", + cksum->cksumtype); + return KRB5_PROG_SUMTYPE_NOSUPP; + } + + if (arcfour_checksum_p(ct, crypto)) { + keyusage = usage; + usage2arcfour(context, &keyusage); + } else + keyusage = CHECKSUM_USAGE(usage); + + return verify_checksum(context, crypto, keyusage, + data, len, cksum); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_crypto_get_checksum_type(krb5_context context, + krb5_crypto crypto, + krb5_cksumtype *type) +{ + struct checksum_type *ct = NULL; + + if (crypto != NULL) { + ct = crypto->et->keyed_checksum; + if (ct == NULL) + ct = crypto->et->checksum; + } + + if (ct == NULL) { + krb5_set_error_string (context, "checksum type not found"); + return KRB5_PROG_SUMTYPE_NOSUPP; + } + + *type = ct->type; + + return 0; +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_checksumsize(krb5_context context, + krb5_cksumtype type, + size_t *size) +{ + struct checksum_type *ct = _find_checksum(type); + if(ct == NULL) { + krb5_set_error_string (context, "checksum type %d not supported", + type); + return KRB5_PROG_SUMTYPE_NOSUPP; + } + *size = ct->checksumsize; + return 0; +} + +krb5_boolean KRB5_LIB_FUNCTION +krb5_checksum_is_keyed(krb5_context context, + krb5_cksumtype type) +{ + struct checksum_type *ct = _find_checksum(type); + if(ct == NULL) { + if (context) + krb5_set_error_string (context, "checksum type %d not supported", + type); + return KRB5_PROG_SUMTYPE_NOSUPP; + } + return ct->flags & F_KEYED; +} + +krb5_boolean KRB5_LIB_FUNCTION +krb5_checksum_is_collision_proof(krb5_context context, + krb5_cksumtype type) +{ + struct checksum_type *ct = _find_checksum(type); + if(ct == NULL) { + if (context) + krb5_set_error_string (context, "checksum type %d not supported", + type); + return KRB5_PROG_SUMTYPE_NOSUPP; + } + return ct->flags & F_CPROOF; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_checksum_disable(krb5_context context, + krb5_cksumtype type) +{ + struct checksum_type *ct = _find_checksum(type); + if(ct == NULL) { + if (context) + krb5_set_error_string (context, "checksum type %d not supported", + type); + return KRB5_PROG_SUMTYPE_NOSUPP; + } + ct->flags |= F_DISABLED; + return 0; +} + +/************************************************************ + * * + ************************************************************/ + +static krb5_error_code +NULL_encrypt(krb5_context context, + struct key_data *key, + void *data, + size_t len, + krb5_boolean encryptp, + int usage, + void *ivec) +{ + return 0; +} + +static krb5_error_code +DES_CBC_encrypt_null_ivec(krb5_context context, + struct key_data *key, + void *data, + size_t len, + krb5_boolean encryptp, + int usage, + void *ignore_ivec) +{ + DES_cblock ivec; + DES_key_schedule *s = key->schedule->data; + memset(&ivec, 0, sizeof(ivec)); + DES_cbc_encrypt(data, data, len, s, &ivec, encryptp); + return 0; +} + +static krb5_error_code +DES_CBC_encrypt_key_ivec(krb5_context context, + struct key_data *key, + void *data, + size_t len, + krb5_boolean encryptp, + int usage, + void *ignore_ivec) +{ + DES_cblock ivec; + DES_key_schedule *s = key->schedule->data; + memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec)); + DES_cbc_encrypt(data, data, len, s, &ivec, encryptp); + return 0; +} + +static krb5_error_code +DES3_CBC_encrypt(krb5_context context, + struct key_data *key, + void *data, + size_t len, + krb5_boolean encryptp, + int usage, + void *ivec) +{ + DES_cblock local_ivec; + DES_key_schedule *s = key->schedule->data; + if(ivec == NULL) { + ivec = &local_ivec; + memset(local_ivec, 0, sizeof(local_ivec)); + } + DES_ede3_cbc_encrypt(data, data, len, &s[0], &s[1], &s[2], ivec, encryptp); + return 0; +} + +static krb5_error_code +DES_CFB64_encrypt_null_ivec(krb5_context context, + struct key_data *key, + void *data, + size_t len, + krb5_boolean encryptp, + int usage, + void *ignore_ivec) +{ + DES_cblock ivec; + int num = 0; + DES_key_schedule *s = key->schedule->data; + memset(&ivec, 0, sizeof(ivec)); + + DES_cfb64_encrypt(data, data, len, s, &ivec, &num, encryptp); + return 0; +} + +static krb5_error_code +DES_PCBC_encrypt_key_ivec(krb5_context context, + struct key_data *key, + void *data, + size_t len, + krb5_boolean encryptp, + int usage, + void *ignore_ivec) +{ + DES_cblock ivec; + DES_key_schedule *s = key->schedule->data; + memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec)); + + DES_pcbc_encrypt(data, data, len, s, &ivec, encryptp); + return 0; +} + +/* + * AES draft-raeburn-krb-rijndael-krb-02 + */ + +void KRB5_LIB_FUNCTION +_krb5_aes_cts_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const AES_KEY *key, + unsigned char *ivec, const int encryptp) +{ + unsigned char tmp[AES_BLOCK_SIZE]; + int i; + + /* + * In the framework of kerberos, the length can never be shorter + * then at least one blocksize. + */ + + if (encryptp) { + + while(len > AES_BLOCK_SIZE) { + for (i = 0; i < AES_BLOCK_SIZE; i++) + tmp[i] = in[i] ^ ivec[i]; + AES_encrypt(tmp, out, key); + memcpy(ivec, out, AES_BLOCK_SIZE); + len -= AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + } + + for (i = 0; i < len; i++) + tmp[i] = in[i] ^ ivec[i]; + for (; i < AES_BLOCK_SIZE; i++) + tmp[i] = 0 ^ ivec[i]; + + AES_encrypt(tmp, out - AES_BLOCK_SIZE, key); + + memcpy(out, ivec, len); + memcpy(ivec, out - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + + } else { + unsigned char tmp2[AES_BLOCK_SIZE]; + unsigned char tmp3[AES_BLOCK_SIZE]; + + while(len > AES_BLOCK_SIZE * 2) { + memcpy(tmp, in, AES_BLOCK_SIZE); + AES_decrypt(in, out, key); + for (i = 0; i < AES_BLOCK_SIZE; i++) + out[i] ^= ivec[i]; + memcpy(ivec, tmp, AES_BLOCK_SIZE); + len -= AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + } + + len -= AES_BLOCK_SIZE; + + memcpy(tmp, in, AES_BLOCK_SIZE); /* save last iv */ + AES_decrypt(in, tmp2, key); + + memcpy(tmp3, in + AES_BLOCK_SIZE, len); + memcpy(tmp3 + len, tmp2 + len, AES_BLOCK_SIZE - len); /* xor 0 */ + + for (i = 0; i < len; i++) + out[i + AES_BLOCK_SIZE] = tmp2[i] ^ tmp3[i]; + + AES_decrypt(tmp3, out, key); + for (i = 0; i < AES_BLOCK_SIZE; i++) + out[i] ^= ivec[i]; + memcpy(ivec, tmp, AES_BLOCK_SIZE); + } +} + +static krb5_error_code +AES_CTS_encrypt(krb5_context context, + struct key_data *key, + void *data, + size_t len, + krb5_boolean encryptp, + int usage, + void *ivec) +{ + struct krb5_aes_schedule *aeskey = key->schedule->data; + char local_ivec[AES_BLOCK_SIZE]; + AES_KEY *k; + + if (encryptp) + k = &aeskey->ekey; + else + k = &aeskey->dkey; + + if (len < AES_BLOCK_SIZE) + krb5_abortx(context, "invalid use of AES_CTS_encrypt"); + if (len == AES_BLOCK_SIZE) { + if (encryptp) + AES_encrypt(data, data, k); + else + AES_decrypt(data, data, k); + } else { + if(ivec == NULL) { + memset(local_ivec, 0, sizeof(local_ivec)); + ivec = local_ivec; + } + _krb5_aes_cts_encrypt(data, data, len, k, ivec, encryptp); + } + + return 0; +} + +/* + * section 6 of draft-brezak-win2k-krb-rc4-hmac-03 + * + * warning: not for small children + */ + +static krb5_error_code +ARCFOUR_subencrypt(krb5_context context, + struct key_data *key, + void *data, + size_t len, + unsigned usage, + void *ivec) +{ + struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5); + Checksum k1_c, k2_c, k3_c, cksum; + struct key_data ke; + krb5_keyblock kb; + unsigned char t[4]; + RC4_KEY rc4_key; + unsigned char *cdata = data; + unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16]; + krb5_error_code ret; + + t[0] = (usage >> 0) & 0xFF; + t[1] = (usage >> 8) & 0xFF; + t[2] = (usage >> 16) & 0xFF; + t[3] = (usage >> 24) & 0xFF; + + k1_c.checksum.length = sizeof(k1_c_data); + k1_c.checksum.data = k1_c_data; + + ret = hmac(NULL, c, t, sizeof(t), 0, key, &k1_c); + if (ret) + krb5_abortx(context, "hmac failed"); + + memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data)); + + k2_c.checksum.length = sizeof(k2_c_data); + k2_c.checksum.data = k2_c_data; + + ke.key = &kb; + kb.keyvalue = k2_c.checksum; + + cksum.checksum.length = 16; + cksum.checksum.data = data; + + ret = hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum); + if (ret) + krb5_abortx(context, "hmac failed"); + + ke.key = &kb; + kb.keyvalue = k1_c.checksum; + + k3_c.checksum.length = sizeof(k3_c_data); + k3_c.checksum.data = k3_c_data; + + ret = hmac(NULL, c, data, 16, 0, &ke, &k3_c); + if (ret) + krb5_abortx(context, "hmac failed"); + + RC4_set_key (&rc4_key, k3_c.checksum.length, k3_c.checksum.data); + RC4 (&rc4_key, len - 16, cdata + 16, cdata + 16); + memset (k1_c_data, 0, sizeof(k1_c_data)); + memset (k2_c_data, 0, sizeof(k2_c_data)); + memset (k3_c_data, 0, sizeof(k3_c_data)); + return 0; +} + +static krb5_error_code +ARCFOUR_subdecrypt(krb5_context context, + struct key_data *key, + void *data, + size_t len, + unsigned usage, + void *ivec) +{ + struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5); + Checksum k1_c, k2_c, k3_c, cksum; + struct key_data ke; + krb5_keyblock kb; + unsigned char t[4]; + RC4_KEY rc4_key; + unsigned char *cdata = data; + unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16]; + unsigned char cksum_data[16]; + krb5_error_code ret; + + t[0] = (usage >> 0) & 0xFF; + t[1] = (usage >> 8) & 0xFF; + t[2] = (usage >> 16) & 0xFF; + t[3] = (usage >> 24) & 0xFF; + + k1_c.checksum.length = sizeof(k1_c_data); + k1_c.checksum.data = k1_c_data; + + ret = hmac(NULL, c, t, sizeof(t), 0, key, &k1_c); + if (ret) + krb5_abortx(context, "hmac failed"); + + memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data)); + + k2_c.checksum.length = sizeof(k2_c_data); + k2_c.checksum.data = k2_c_data; + + ke.key = &kb; + kb.keyvalue = k1_c.checksum; + + k3_c.checksum.length = sizeof(k3_c_data); + k3_c.checksum.data = k3_c_data; + + ret = hmac(NULL, c, cdata, 16, 0, &ke, &k3_c); + if (ret) + krb5_abortx(context, "hmac failed"); + + RC4_set_key (&rc4_key, k3_c.checksum.length, k3_c.checksum.data); + RC4 (&rc4_key, len - 16, cdata + 16, cdata + 16); + + ke.key = &kb; + kb.keyvalue = k2_c.checksum; + + cksum.checksum.length = 16; + cksum.checksum.data = cksum_data; + + ret = hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum); + if (ret) + krb5_abortx(context, "hmac failed"); + + memset (k1_c_data, 0, sizeof(k1_c_data)); + memset (k2_c_data, 0, sizeof(k2_c_data)); + memset (k3_c_data, 0, sizeof(k3_c_data)); + + if (memcmp (cksum.checksum.data, data, 16) != 0) { + krb5_clear_error_string (context); + return KRB5KRB_AP_ERR_BAD_INTEGRITY; + } else { + return 0; + } +} + +/* + * convert the usage numbers used in + * draft-ietf-cat-kerb-key-derivation-00.txt to the ones in + * draft-brezak-win2k-krb-rc4-hmac-04.txt + */ + +static krb5_error_code +usage2arcfour (krb5_context context, unsigned *usage) +{ + switch (*usage) { + case KRB5_KU_AS_REP_ENC_PART : /* 3 */ + case KRB5_KU_TGS_REP_ENC_PART_SUB_KEY : /* 9 */ + *usage = 8; + return 0; + case KRB5_KU_USAGE_SEAL : /* 22 */ + *usage = 13; + return 0; + case KRB5_KU_USAGE_SIGN : /* 23 */ + *usage = 15; + return 0; + case KRB5_KU_USAGE_SEQ: /* 24 */ + *usage = 0; + return 0; + default : + return 0; + } +} + +static krb5_error_code +ARCFOUR_encrypt(krb5_context context, + struct key_data *key, + void *data, + size_t len, + krb5_boolean encryptp, + int usage, + void *ivec) +{ + krb5_error_code ret; + unsigned keyusage = usage; + + if((ret = usage2arcfour (context, &keyusage)) != 0) + return ret; + + if (encryptp) + return ARCFOUR_subencrypt (context, key, data, len, keyusage, ivec); + else + return ARCFOUR_subdecrypt (context, key, data, len, keyusage, ivec); +} + + +/* + * + */ + +static krb5_error_code +AES_PRF(krb5_context context, + krb5_crypto crypto, + const krb5_data *in, + krb5_data *out) +{ + struct checksum_type *ct = crypto->et->checksum; + krb5_error_code ret; + Checksum result; + krb5_keyblock *derived; + + result.cksumtype = ct->type; + ret = krb5_data_alloc(&result.checksum, ct->checksumsize); + if (ret) { + krb5_set_error_string(context, "out memory"); + return ret; + } + + (*ct->checksum)(context, NULL, in->data, in->length, 0, &result); + + if (result.checksum.length < crypto->et->blocksize) + krb5_abortx(context, "internal prf error"); + + derived = NULL; + ret = krb5_derive_key(context, crypto->key.key, + crypto->et->type, "prf", 3, &derived); + if (ret) + krb5_abortx(context, "krb5_derive_key"); + + ret = krb5_data_alloc(out, crypto->et->blocksize); + if (ret) + krb5_abortx(context, "malloc failed"); + + { + AES_KEY key; + + AES_set_encrypt_key(derived->keyvalue.data, + crypto->et->keytype->bits, &key); + AES_encrypt(result.checksum.data, out->data, &key); + memset(&key, 0, sizeof(key)); + } + + krb5_data_free(&result.checksum); + krb5_free_keyblock(context, derived); + + return ret; +} + +/* + * these should currently be in reverse preference order. + * (only relevant for !F_PSEUDO) */ + +static struct encryption_type enctype_null = { + ETYPE_NULL, + "null", + NULL, + 1, + 1, + 0, + &keytype_null, + &checksum_none, + NULL, + F_DISABLED, + NULL_encrypt, + 0, + NULL +}; +static struct encryption_type enctype_des_cbc_crc = { + ETYPE_DES_CBC_CRC, + "des-cbc-crc", + NULL, + 8, + 8, + 8, + &keytype_des, + &checksum_crc32, + NULL, + 0, + DES_CBC_encrypt_key_ivec, + 0, + NULL +}; +static struct encryption_type enctype_des_cbc_md4 = { + ETYPE_DES_CBC_MD4, + "des-cbc-md4", + NULL, + 8, + 8, + 8, + &keytype_des, + &checksum_rsa_md4, + &checksum_rsa_md4_des, + 0, + DES_CBC_encrypt_null_ivec, + 0, + NULL +}; +static struct encryption_type enctype_des_cbc_md5 = { + ETYPE_DES_CBC_MD5, + "des-cbc-md5", + NULL, + 8, + 8, + 8, + &keytype_des, + &checksum_rsa_md5, + &checksum_rsa_md5_des, + 0, + DES_CBC_encrypt_null_ivec, + 0, + NULL +}; +static struct encryption_type enctype_arcfour_hmac_md5 = { + ETYPE_ARCFOUR_HMAC_MD5, + "arcfour-hmac-md5", + NULL, + 1, + 1, + 8, + &keytype_arcfour, + &checksum_hmac_md5, + NULL, + F_SPECIAL, + ARCFOUR_encrypt, + 0, + NULL +}; +static struct encryption_type enctype_des3_cbc_md5 = { + ETYPE_DES3_CBC_MD5, + "des3-cbc-md5", + NULL, + 8, + 8, + 8, + &keytype_des3, + &checksum_rsa_md5, + &checksum_rsa_md5_des3, + 0, + DES3_CBC_encrypt, + 0, + NULL +}; +static struct encryption_type enctype_des3_cbc_sha1 = { + ETYPE_DES3_CBC_SHA1, + "des3-cbc-sha1", + NULL, + 8, + 8, + 8, + &keytype_des3_derived, + &checksum_sha1, + &checksum_hmac_sha1_des3, + F_DERIVED, + DES3_CBC_encrypt, + 0, + NULL +}; +static struct encryption_type enctype_old_des3_cbc_sha1 = { + ETYPE_OLD_DES3_CBC_SHA1, + "old-des3-cbc-sha1", + NULL, + 8, + 8, + 8, + &keytype_des3, + &checksum_sha1, + &checksum_hmac_sha1_des3, + 0, + DES3_CBC_encrypt, + 0, + NULL +}; +static struct encryption_type enctype_aes128_cts_hmac_sha1 = { + ETYPE_AES128_CTS_HMAC_SHA1_96, + "aes128-cts-hmac-sha1-96", + NULL, + 16, + 1, + 16, + &keytype_aes128, + &checksum_sha1, + &checksum_hmac_sha1_aes128, + F_DERIVED, + AES_CTS_encrypt, + 16, + AES_PRF +}; +static struct encryption_type enctype_aes256_cts_hmac_sha1 = { + ETYPE_AES256_CTS_HMAC_SHA1_96, + "aes256-cts-hmac-sha1-96", + NULL, + 16, + 1, + 16, + &keytype_aes256, + &checksum_sha1, + &checksum_hmac_sha1_aes256, + F_DERIVED, + AES_CTS_encrypt, + 16, + AES_PRF +}; +static struct encryption_type enctype_des_cbc_none = { + ETYPE_DES_CBC_NONE, + "des-cbc-none", + NULL, + 8, + 8, + 0, + &keytype_des, + &checksum_none, + NULL, + F_PSEUDO, + DES_CBC_encrypt_null_ivec, + 0, + NULL +}; +static struct encryption_type enctype_des_cfb64_none = { + ETYPE_DES_CFB64_NONE, + "des-cfb64-none", + NULL, + 1, + 1, + 0, + &keytype_des, + &checksum_none, + NULL, + F_PSEUDO, + DES_CFB64_encrypt_null_ivec, + 0, + NULL +}; +static struct encryption_type enctype_des_pcbc_none = { + ETYPE_DES_PCBC_NONE, + "des-pcbc-none", + NULL, + 8, + 8, + 0, + &keytype_des, + &checksum_none, + NULL, + F_PSEUDO, + DES_PCBC_encrypt_key_ivec, + 0, + NULL +}; +static struct encryption_type enctype_des3_cbc_none = { + ETYPE_DES3_CBC_NONE, + "des3-cbc-none", + NULL, + 8, + 8, + 0, + &keytype_des3_derived, + &checksum_none, + NULL, + F_PSEUDO, + DES3_CBC_encrypt, + 0, + NULL +}; + +static struct encryption_type *etypes[] = { + &enctype_null, + &enctype_des_cbc_crc, + &enctype_des_cbc_md4, + &enctype_des_cbc_md5, + &enctype_arcfour_hmac_md5, + &enctype_des3_cbc_md5, + &enctype_des3_cbc_sha1, + &enctype_old_des3_cbc_sha1, + &enctype_aes128_cts_hmac_sha1, + &enctype_aes256_cts_hmac_sha1, + &enctype_des_cbc_none, + &enctype_des_cfb64_none, + &enctype_des_pcbc_none, + &enctype_des3_cbc_none +}; + +static unsigned num_etypes = sizeof(etypes) / sizeof(etypes[0]); + + +static struct encryption_type * +_find_enctype(krb5_enctype type) +{ + int i; + for(i = 0; i < num_etypes; i++) + if(etypes[i]->type == type) + return etypes[i]; + return NULL; +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_enctype_to_string(krb5_context context, + krb5_enctype etype, + char **string) +{ + struct encryption_type *e; + e = _find_enctype(etype); + if(e == NULL) { + krb5_set_error_string (context, "encryption type %d not supported", + etype); + *string = NULL; + return KRB5_PROG_ETYPE_NOSUPP; + } + *string = strdup(e->name); + if(*string == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_enctype(krb5_context context, + const char *string, + krb5_enctype *etype) +{ + int i; + for(i = 0; i < num_etypes; i++) + if(strcasecmp(etypes[i]->name, string) == 0){ + *etype = etypes[i]->type; + return 0; + } + krb5_set_error_string (context, "encryption type %s not supported", + string); + return KRB5_PROG_ETYPE_NOSUPP; +} + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_enctype_to_oid(krb5_context context, + krb5_enctype etype, + heim_oid *oid) +{ + struct encryption_type *et = _find_enctype(etype); + if(et == NULL) { + krb5_set_error_string (context, "encryption type %d not supported", + etype); + return KRB5_PROG_ETYPE_NOSUPP; + } + if(et->oid == NULL) { + krb5_set_error_string (context, "%s have not oid", et->name); + return KRB5_PROG_ETYPE_NOSUPP; + } + krb5_clear_error_string(context); + return der_copy_oid(et->oid, oid); +} + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_oid_to_enctype(krb5_context context, + const heim_oid *oid, + krb5_enctype *etype) +{ + int i; + for(i = 0; i < num_etypes; i++) { + if(etypes[i]->oid && der_heim_oid_cmp(etypes[i]->oid, oid) == 0) { + *etype = etypes[i]->type; + return 0; + } + } + krb5_set_error_string(context, "enctype for oid not supported"); + return KRB5_PROG_ETYPE_NOSUPP; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_enctype_to_keytype(krb5_context context, + krb5_enctype etype, + krb5_keytype *keytype) +{ + struct encryption_type *e = _find_enctype(etype); + if(e == NULL) { + krb5_set_error_string (context, "encryption type %d not supported", + etype); + return KRB5_PROG_ETYPE_NOSUPP; + } + *keytype = e->keytype->type; /* XXX */ + return 0; +} + +#if 0 +krb5_error_code KRB5_LIB_FUNCTION +krb5_keytype_to_enctype(krb5_context context, + krb5_keytype keytype, + krb5_enctype *etype) +{ + struct key_type *kt = _find_keytype(keytype); + krb5_warnx(context, "krb5_keytype_to_enctype(%u)", keytype); + if(kt == NULL) + return KRB5_PROG_KEYTYPE_NOSUPP; + *etype = kt->best_etype; + return 0; +} +#endif + +krb5_error_code KRB5_LIB_FUNCTION +krb5_keytype_to_enctypes (krb5_context context, + krb5_keytype keytype, + unsigned *len, + krb5_enctype **val) +{ + int i; + unsigned n = 0; + krb5_enctype *ret; + + for (i = num_etypes - 1; i >= 0; --i) { + if (etypes[i]->keytype->type == keytype + && !(etypes[i]->flags & F_PSEUDO)) + ++n; + } + ret = malloc(n * sizeof(*ret)); + if (ret == NULL && n != 0) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + n = 0; + for (i = num_etypes - 1; i >= 0; --i) { + if (etypes[i]->keytype->type == keytype + && !(etypes[i]->flags & F_PSEUDO)) + ret[n++] = etypes[i]->type; + } + *len = n; + *val = ret; + return 0; +} + +/* + * First take the configured list of etypes for `keytype' if available, + * else, do `krb5_keytype_to_enctypes'. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_keytype_to_enctypes_default (krb5_context context, + krb5_keytype keytype, + unsigned *len, + krb5_enctype **val) +{ + int i, n; + krb5_enctype *ret; + + if (keytype != KEYTYPE_DES || context->etypes_des == NULL) + return krb5_keytype_to_enctypes (context, keytype, len, val); + + for (n = 0; context->etypes_des[n]; ++n) + ; + ret = malloc (n * sizeof(*ret)); + if (ret == NULL && n != 0) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + for (i = 0; i < n; ++i) + ret[i] = context->etypes_des[i]; + *len = n; + *val = ret; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_enctype_valid(krb5_context context, + krb5_enctype etype) +{ + struct encryption_type *e = _find_enctype(etype); + if(e == NULL) { + krb5_set_error_string (context, "encryption type %d not supported", + etype); + return KRB5_PROG_ETYPE_NOSUPP; + } + if (e->flags & F_DISABLED) { + krb5_set_error_string (context, "encryption type %s is disabled", + e->name); + return KRB5_PROG_ETYPE_NOSUPP; + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cksumtype_valid(krb5_context context, + krb5_cksumtype ctype) +{ + struct checksum_type *c = _find_checksum(ctype); + if (c == NULL) { + krb5_set_error_string (context, "checksum type %d not supported", + ctype); + return KRB5_PROG_SUMTYPE_NOSUPP; + } + if (c->flags & F_DISABLED) { + krb5_set_error_string (context, "checksum type %s is disabled", + c->name); + return KRB5_PROG_SUMTYPE_NOSUPP; + } + return 0; +} + + +/* if two enctypes have compatible keys */ +krb5_boolean KRB5_LIB_FUNCTION +krb5_enctypes_compatible_keys(krb5_context context, + krb5_enctype etype1, + krb5_enctype etype2) +{ + struct encryption_type *e1 = _find_enctype(etype1); + struct encryption_type *e2 = _find_enctype(etype2); + return e1 != NULL && e2 != NULL && e1->keytype == e2->keytype; +} + +static krb5_boolean +derived_crypto(krb5_context context, + krb5_crypto crypto) +{ + return (crypto->et->flags & F_DERIVED) != 0; +} + +static krb5_boolean +special_crypto(krb5_context context, + krb5_crypto crypto) +{ + return (crypto->et->flags & F_SPECIAL) != 0; +} + +#define CHECKSUMSIZE(C) ((C)->checksumsize) +#define CHECKSUMTYPE(C) ((C)->type) + +static krb5_error_code +encrypt_internal_derived(krb5_context context, + krb5_crypto crypto, + unsigned usage, + const void *data, + size_t len, + krb5_data *result, + void *ivec) +{ + size_t sz, block_sz, checksum_sz, total_sz; + Checksum cksum; + unsigned char *p, *q; + krb5_error_code ret; + struct key_data *dkey; + const struct encryption_type *et = crypto->et; + + checksum_sz = CHECKSUMSIZE(et->keyed_checksum); + + sz = et->confoundersize + len; + block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */ + total_sz = block_sz + checksum_sz; + p = calloc(1, total_sz); + if(p == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + q = p; + krb5_generate_random_block(q, et->confoundersize); /* XXX */ + q += et->confoundersize; + memcpy(q, data, len); + + ret = create_checksum(context, + et->keyed_checksum, + crypto, + INTEGRITY_USAGE(usage), + p, + block_sz, + &cksum); + if(ret == 0 && cksum.checksum.length != checksum_sz) { + free_Checksum (&cksum); + krb5_clear_error_string (context); + ret = KRB5_CRYPTO_INTERNAL; + } + if(ret) + goto fail; + memcpy(p + block_sz, cksum.checksum.data, cksum.checksum.length); + free_Checksum (&cksum); + ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey); + if(ret) + goto fail; + ret = _key_schedule(context, dkey); + if(ret) + goto fail; +#ifdef CRYPTO_DEBUG + krb5_crypto_debug(context, 1, block_sz, dkey->key); +#endif + ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec); + if (ret) + goto fail; + result->data = p; + result->length = total_sz; + return 0; + fail: + memset(p, 0, total_sz); + free(p); + return ret; +} + + +static krb5_error_code +encrypt_internal(krb5_context context, + krb5_crypto crypto, + const void *data, + size_t len, + krb5_data *result, + void *ivec) +{ + size_t sz, block_sz, checksum_sz; + Checksum cksum; + unsigned char *p, *q; + krb5_error_code ret; + const struct encryption_type *et = crypto->et; + + checksum_sz = CHECKSUMSIZE(et->checksum); + + sz = et->confoundersize + checksum_sz + len; + block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */ + p = calloc(1, block_sz); + if(p == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + q = p; + krb5_generate_random_block(q, et->confoundersize); /* XXX */ + q += et->confoundersize; + memset(q, 0, checksum_sz); + q += checksum_sz; + memcpy(q, data, len); + + ret = create_checksum(context, + et->checksum, + crypto, + 0, + p, + block_sz, + &cksum); + if(ret == 0 && cksum.checksum.length != checksum_sz) { + krb5_clear_error_string (context); + free_Checksum(&cksum); + ret = KRB5_CRYPTO_INTERNAL; + } + if(ret) + goto fail; + memcpy(p + et->confoundersize, cksum.checksum.data, cksum.checksum.length); + free_Checksum(&cksum); + ret = _key_schedule(context, &crypto->key); + if(ret) + goto fail; +#ifdef CRYPTO_DEBUG + krb5_crypto_debug(context, 1, block_sz, crypto->key.key); +#endif + ret = (*et->encrypt)(context, &crypto->key, p, block_sz, 1, 0, ivec); + if (ret) { + memset(p, 0, block_sz); + free(p); + return ret; + } + result->data = p; + result->length = block_sz; + return 0; + fail: + memset(p, 0, block_sz); + free(p); + return ret; +} + +static krb5_error_code +encrypt_internal_special(krb5_context context, + krb5_crypto crypto, + int usage, + const void *data, + size_t len, + krb5_data *result, + void *ivec) +{ + struct encryption_type *et = crypto->et; + size_t cksum_sz = CHECKSUMSIZE(et->checksum); + size_t sz = len + cksum_sz + et->confoundersize; + char *tmp, *p; + krb5_error_code ret; + + tmp = malloc (sz); + if (tmp == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + p = tmp; + memset (p, 0, cksum_sz); + p += cksum_sz; + krb5_generate_random_block(p, et->confoundersize); + p += et->confoundersize; + memcpy (p, data, len); + ret = (*et->encrypt)(context, &crypto->key, tmp, sz, TRUE, usage, ivec); + if (ret) { + memset(tmp, 0, sz); + free(tmp); + return ret; + } + result->data = tmp; + result->length = sz; + return 0; +} + +static krb5_error_code +decrypt_internal_derived(krb5_context context, + krb5_crypto crypto, + unsigned usage, + void *data, + size_t len, + krb5_data *result, + void *ivec) +{ + size_t checksum_sz; + Checksum cksum; + unsigned char *p; + krb5_error_code ret; + struct key_data *dkey; + struct encryption_type *et = crypto->et; + unsigned long l; + + checksum_sz = CHECKSUMSIZE(et->keyed_checksum); + if (len < checksum_sz + et->confoundersize) { + krb5_set_error_string(context, "Encrypted data shorter then " + "checksum + confunder"); + return KRB5_BAD_MSIZE; + } + + if (((len - checksum_sz) % et->padsize) != 0) { + krb5_clear_error_string(context); + return KRB5_BAD_MSIZE; + } + + p = malloc(len); + if(len != 0 && p == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + memcpy(p, data, len); + + len -= checksum_sz; + + ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey); + if(ret) { + free(p); + return ret; + } + ret = _key_schedule(context, dkey); + if(ret) { + free(p); + return ret; + } +#ifdef CRYPTO_DEBUG + krb5_crypto_debug(context, 0, len, dkey->key); +#endif + ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec); + if (ret) { + free(p); + return ret; + } + + cksum.checksum.data = p + len; + cksum.checksum.length = checksum_sz; + cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum); + + ret = verify_checksum(context, + crypto, + INTEGRITY_USAGE(usage), + p, + len, + &cksum); + if(ret) { + free(p); + return ret; + } + l = len - et->confoundersize; + memmove(p, p + et->confoundersize, l); + result->data = realloc(p, l); + if(result->data == NULL && l != 0) { + free(p); + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + result->length = l; + return 0; +} + +static krb5_error_code +decrypt_internal(krb5_context context, + krb5_crypto crypto, + void *data, + size_t len, + krb5_data *result, + void *ivec) +{ + krb5_error_code ret; + unsigned char *p; + Checksum cksum; + size_t checksum_sz, l; + struct encryption_type *et = crypto->et; + + if ((len % et->padsize) != 0) { + krb5_clear_error_string(context); + return KRB5_BAD_MSIZE; + } + + checksum_sz = CHECKSUMSIZE(et->checksum); + p = malloc(len); + if(len != 0 && p == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + memcpy(p, data, len); + + ret = _key_schedule(context, &crypto->key); + if(ret) { + free(p); + return ret; + } +#ifdef CRYPTO_DEBUG + krb5_crypto_debug(context, 0, len, crypto->key.key); +#endif + ret = (*et->encrypt)(context, &crypto->key, p, len, 0, 0, ivec); + if (ret) { + free(p); + return ret; + } + ret = krb5_data_copy(&cksum.checksum, p + et->confoundersize, checksum_sz); + if(ret) { + free(p); + return ret; + } + memset(p + et->confoundersize, 0, checksum_sz); + cksum.cksumtype = CHECKSUMTYPE(et->checksum); + ret = verify_checksum(context, NULL, 0, p, len, &cksum); + free_Checksum(&cksum); + if(ret) { + free(p); + return ret; + } + l = len - et->confoundersize - checksum_sz; + memmove(p, p + et->confoundersize + checksum_sz, l); + result->data = realloc(p, l); + if(result->data == NULL && l != 0) { + free(p); + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + result->length = l; + return 0; +} + +static krb5_error_code +decrypt_internal_special(krb5_context context, + krb5_crypto crypto, + int usage, + void *data, + size_t len, + krb5_data *result, + void *ivec) +{ + struct encryption_type *et = crypto->et; + size_t cksum_sz = CHECKSUMSIZE(et->checksum); + size_t sz = len - cksum_sz - et->confoundersize; + unsigned char *p; + krb5_error_code ret; + + if ((len % et->padsize) != 0) { + krb5_clear_error_string(context); + return KRB5_BAD_MSIZE; + } + + p = malloc (len); + if (p == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + memcpy(p, data, len); + + ret = (*et->encrypt)(context, &crypto->key, p, len, FALSE, usage, ivec); + if (ret) { + free(p); + return ret; + } + + memmove (p, p + cksum_sz + et->confoundersize, sz); + result->data = realloc(p, sz); + if(result->data == NULL && sz != 0) { + free(p); + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + result->length = sz; + return 0; +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encrypt_ivec(krb5_context context, + krb5_crypto crypto, + unsigned usage, + const void *data, + size_t len, + krb5_data *result, + void *ivec) +{ + if(derived_crypto(context, crypto)) + return encrypt_internal_derived(context, crypto, usage, + data, len, result, ivec); + else if (special_crypto(context, crypto)) + return encrypt_internal_special (context, crypto, usage, + data, len, result, ivec); + else + return encrypt_internal(context, crypto, data, len, result, ivec); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encrypt(krb5_context context, + krb5_crypto crypto, + unsigned usage, + const void *data, + size_t len, + krb5_data *result) +{ + return krb5_encrypt_ivec(context, crypto, usage, data, len, result, NULL); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encrypt_EncryptedData(krb5_context context, + krb5_crypto crypto, + unsigned usage, + void *data, + size_t len, + int kvno, + EncryptedData *result) +{ + result->etype = CRYPTO_ETYPE(crypto); + if(kvno){ + ALLOC(result->kvno, 1); + *result->kvno = kvno; + }else + result->kvno = NULL; + return krb5_encrypt(context, crypto, usage, data, len, &result->cipher); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decrypt_ivec(krb5_context context, + krb5_crypto crypto, + unsigned usage, + void *data, + size_t len, + krb5_data *result, + void *ivec) +{ + if(derived_crypto(context, crypto)) + return decrypt_internal_derived(context, crypto, usage, + data, len, result, ivec); + else if (special_crypto (context, crypto)) + return decrypt_internal_special(context, crypto, usage, + data, len, result, ivec); + else + return decrypt_internal(context, crypto, data, len, result, ivec); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decrypt(krb5_context context, + krb5_crypto crypto, + unsigned usage, + void *data, + size_t len, + krb5_data *result) +{ + return krb5_decrypt_ivec (context, crypto, usage, data, len, result, + NULL); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decrypt_EncryptedData(krb5_context context, + krb5_crypto crypto, + unsigned usage, + const EncryptedData *e, + krb5_data *result) +{ + return krb5_decrypt(context, crypto, usage, + e->cipher.data, e->cipher.length, result); +} + +/************************************************************ + * * + ************************************************************/ + +#define ENTROPY_NEEDED 128 + +static int +seed_something(void) +{ + char buf[1024], seedfile[256]; + + /* If there is a seed file, load it. But such a file cannot be trusted, + so use 0 for the entropy estimate */ + if (RAND_file_name(seedfile, sizeof(seedfile))) { + int fd; + fd = open(seedfile, O_RDONLY); + if (fd >= 0) { + ssize_t ret; + ret = read(fd, buf, sizeof(buf)); + if (ret > 0) + RAND_add(buf, ret, 0.0); + close(fd); + } else + seedfile[0] = '\0'; + } else + seedfile[0] = '\0'; + + /* Calling RAND_status() will try to use /dev/urandom if it exists so + we do not have to deal with it. */ + if (RAND_status() != 1) { + krb5_context context; + const char *p; + + /* Try using egd */ + if (!krb5_init_context(&context)) { + p = krb5_config_get_string(context, NULL, "libdefaults", + "egd_socket", NULL); + if (p != NULL) + RAND_egd_bytes(p, ENTROPY_NEEDED); + krb5_free_context(context); + } + } + + if (RAND_status() == 1) { + /* Update the seed file */ + if (seedfile[0]) + RAND_write_file(seedfile); + + return 0; + } else + return -1; +} + +void KRB5_LIB_FUNCTION +krb5_generate_random_block(void *buf, size_t len) +{ + static int rng_initialized = 0; + + HEIMDAL_MUTEX_lock(&crypto_mutex); + if (!rng_initialized) { + if (seed_something()) + krb5_abortx(NULL, "Fatal: could not seed the " + "random number generator"); + + rng_initialized = 1; + } + HEIMDAL_MUTEX_unlock(&crypto_mutex); + if (RAND_bytes(buf, len) != 1) + krb5_abortx(NULL, "Failed to generate random block"); +} + +static void +DES3_postproc(krb5_context context, + unsigned char *k, size_t len, struct key_data *key) +{ + DES3_random_to_key(context, key->key, k, len); + + if (key->schedule) { + krb5_free_data(context, key->schedule); + key->schedule = NULL; + } +} + +static krb5_error_code +derive_key(krb5_context context, + struct encryption_type *et, + struct key_data *key, + const void *constant, + size_t len) +{ + unsigned char *k; + unsigned int nblocks = 0, i; + krb5_error_code ret = 0; + struct key_type *kt = et->keytype; + + ret = _key_schedule(context, key); + if(ret) + return ret; + if(et->blocksize * 8 < kt->bits || len != et->blocksize) { + nblocks = (kt->bits + et->blocksize * 8 - 1) / (et->blocksize * 8); + k = malloc(nblocks * et->blocksize); + if(k == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + ret = _krb5_n_fold(constant, len, k, et->blocksize); + if (ret) { + free(k); + krb5_set_error_string(context, "out of memory"); + return ret; + } + for(i = 0; i < nblocks; i++) { + if(i > 0) + memcpy(k + i * et->blocksize, + k + (i - 1) * et->blocksize, + et->blocksize); + (*et->encrypt)(context, key, k + i * et->blocksize, et->blocksize, + 1, 0, NULL); + } + } else { + /* this case is probably broken, but won't be run anyway */ + void *c = malloc(len); + size_t res_len = (kt->bits + 7) / 8; + + if(len != 0 && c == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + memcpy(c, constant, len); + (*et->encrypt)(context, key, c, len, 1, 0, NULL); + k = malloc(res_len); + if(res_len != 0 && k == NULL) { + free(c); + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + ret = _krb5_n_fold(c, len, k, res_len); + if (ret) { + free(k); + krb5_set_error_string(context, "out of memory"); + return ret; + } + free(c); + } + + /* XXX keytype dependent post-processing */ + switch(kt->type) { + case KEYTYPE_DES3: + DES3_postproc(context, k, nblocks * et->blocksize, key); + break; + case KEYTYPE_AES128: + case KEYTYPE_AES256: + memcpy(key->key->keyvalue.data, k, key->key->keyvalue.length); + break; + default: + krb5_set_error_string(context, + "derive_key() called with unknown keytype (%u)", + kt->type); + ret = KRB5_CRYPTO_INTERNAL; + break; + } + if (key->schedule) { + krb5_free_data(context, key->schedule); + key->schedule = NULL; + } + memset(k, 0, nblocks * et->blocksize); + free(k); + return ret; +} + +static struct key_data * +_new_derived_key(krb5_crypto crypto, unsigned usage) +{ + struct key_usage *d = crypto->key_usage; + d = realloc(d, (crypto->num_key_usage + 1) * sizeof(*d)); + if(d == NULL) + return NULL; + crypto->key_usage = d; + d += crypto->num_key_usage++; + memset(d, 0, sizeof(*d)); + d->usage = usage; + return &d->key; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_derive_key(krb5_context context, + const krb5_keyblock *key, + krb5_enctype etype, + const void *constant, + size_t constant_len, + krb5_keyblock **derived_key) +{ + krb5_error_code ret; + struct encryption_type *et; + struct key_data d; + + *derived_key = NULL; + + et = _find_enctype (etype); + if (et == NULL) { + krb5_set_error_string(context, "encryption type %d not supported", + etype); + return KRB5_PROG_ETYPE_NOSUPP; + } + + ret = krb5_copy_keyblock(context, key, &d.key); + if (ret) + return ret; + + d.schedule = NULL; + ret = derive_key(context, et, &d, constant, constant_len); + if (ret == 0) + ret = krb5_copy_keyblock(context, d.key, derived_key); + free_key_data(context, &d); + return ret; +} + +static krb5_error_code +_get_derived_key(krb5_context context, + krb5_crypto crypto, + unsigned usage, + struct key_data **key) +{ + int i; + struct key_data *d; + unsigned char constant[5]; + + for(i = 0; i < crypto->num_key_usage; i++) + if(crypto->key_usage[i].usage == usage) { + *key = &crypto->key_usage[i].key; + return 0; + } + d = _new_derived_key(crypto, usage); + if(d == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + krb5_copy_keyblock(context, crypto->key.key, &d->key); + _krb5_put_int(constant, usage, 5); + derive_key(context, crypto->et, d, constant, sizeof(constant)); + *key = d; + return 0; +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_crypto_init(krb5_context context, + const krb5_keyblock *key, + krb5_enctype etype, + krb5_crypto *crypto) +{ + krb5_error_code ret; + ALLOC(*crypto, 1); + if(*crypto == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + if(etype == ETYPE_NULL) + etype = key->keytype; + (*crypto)->et = _find_enctype(etype); + if((*crypto)->et == NULL || ((*crypto)->et->flags & F_DISABLED)) { + free(*crypto); + *crypto = NULL; + krb5_set_error_string (context, "encryption type %d not supported", + etype); + return KRB5_PROG_ETYPE_NOSUPP; + } + if((*crypto)->et->keytype->size != key->keyvalue.length) { + free(*crypto); + *crypto = NULL; + krb5_set_error_string (context, "encryption key has bad length"); + return KRB5_BAD_KEYSIZE; + } + ret = krb5_copy_keyblock(context, key, &(*crypto)->key.key); + if(ret) { + free(*crypto); + *crypto = NULL; + return ret; + } + (*crypto)->key.schedule = NULL; + (*crypto)->num_key_usage = 0; + (*crypto)->key_usage = NULL; + return 0; +} + +static void +free_key_data(krb5_context context, struct key_data *key) +{ + krb5_free_keyblock(context, key->key); + if(key->schedule) { + memset(key->schedule->data, 0, key->schedule->length); + krb5_free_data(context, key->schedule); + } +} + +static void +free_key_usage(krb5_context context, struct key_usage *ku) +{ + free_key_data(context, &ku->key); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_crypto_destroy(krb5_context context, + krb5_crypto crypto) +{ + int i; + + for(i = 0; i < crypto->num_key_usage; i++) + free_key_usage(context, &crypto->key_usage[i]); + free(crypto->key_usage); + free_key_data(context, &crypto->key); + free (crypto); + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_crypto_getblocksize(krb5_context context, + krb5_crypto crypto, + size_t *blocksize) +{ + *blocksize = crypto->et->blocksize; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_crypto_getenctype(krb5_context context, + krb5_crypto crypto, + krb5_enctype *enctype) +{ + *enctype = crypto->et->type; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_crypto_getpadsize(krb5_context context, + krb5_crypto crypto, + size_t *padsize) +{ + *padsize = crypto->et->padsize; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_crypto_getconfoundersize(krb5_context context, + krb5_crypto crypto, + size_t *confoundersize) +{ + *confoundersize = crypto->et->confoundersize; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_enctype_disable(krb5_context context, + krb5_enctype enctype) +{ + struct encryption_type *et = _find_enctype(enctype); + if(et == NULL) { + if (context) + krb5_set_error_string (context, "encryption type %d not supported", + enctype); + return KRB5_PROG_ETYPE_NOSUPP; + } + et->flags |= F_DISABLED; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_key_derived(krb5_context context, + const void *str, + size_t len, + krb5_enctype etype, + krb5_keyblock *key) +{ + struct encryption_type *et = _find_enctype(etype); + krb5_error_code ret; + struct key_data kd; + size_t keylen; + u_char *tmp; + + if(et == NULL) { + krb5_set_error_string (context, "encryption type %d not supported", + etype); + return KRB5_PROG_ETYPE_NOSUPP; + } + keylen = et->keytype->bits / 8; + + ALLOC(kd.key, 1); + if(kd.key == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size); + if(ret) { + free(kd.key); + return ret; + } + kd.key->keytype = etype; + tmp = malloc (keylen); + if(tmp == NULL) { + krb5_free_keyblock(context, kd.key); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + ret = _krb5_n_fold(str, len, tmp, keylen); + if (ret) { + free(tmp); + krb5_set_error_string(context, "out of memory"); + return ret; + } + kd.schedule = NULL; + DES3_postproc (context, tmp, keylen, &kd); /* XXX */ + memset(tmp, 0, keylen); + free(tmp); + ret = derive_key(context, + et, + &kd, + "kerberos", /* XXX well known constant */ + strlen("kerberos")); + ret = krb5_copy_keyblock_contents(context, kd.key, key); + free_key_data(context, &kd); + return ret; +} + +static size_t +wrapped_length (krb5_context context, + krb5_crypto crypto, + size_t data_len) +{ + struct encryption_type *et = crypto->et; + size_t padsize = et->padsize; + size_t checksumsize = CHECKSUMSIZE(et->checksum); + size_t res; + + res = et->confoundersize + checksumsize + data_len; + res = (res + padsize - 1) / padsize * padsize; + return res; +} + +static size_t +wrapped_length_dervied (krb5_context context, + krb5_crypto crypto, + size_t data_len) +{ + struct encryption_type *et = crypto->et; + size_t padsize = et->padsize; + size_t res; + + res = et->confoundersize + data_len; + res = (res + padsize - 1) / padsize * padsize; + if (et->keyed_checksum) + res += et->keyed_checksum->checksumsize; + else + res += et->checksum->checksumsize; + return res; +} + +/* + * Return the size of an encrypted packet of length `data_len' + */ + +size_t +krb5_get_wrapped_length (krb5_context context, + krb5_crypto crypto, + size_t data_len) +{ + if (derived_crypto (context, crypto)) + return wrapped_length_dervied (context, crypto, data_len); + else + return wrapped_length (context, crypto, data_len); +} + +/* + * Return the size of an encrypted packet of length `data_len' + */ + +static size_t +crypto_overhead (krb5_context context, + krb5_crypto crypto) +{ + struct encryption_type *et = crypto->et; + size_t res; + + res = CHECKSUMSIZE(et->checksum); + res += et->confoundersize; + if (et->padsize > 1) + res += et->padsize; + return res; +} + +static size_t +crypto_overhead_dervied (krb5_context context, + krb5_crypto crypto) +{ + struct encryption_type *et = crypto->et; + size_t res; + + if (et->keyed_checksum) + res = CHECKSUMSIZE(et->keyed_checksum); + else + res = CHECKSUMSIZE(et->checksum); + res += et->confoundersize; + if (et->padsize > 1) + res += et->padsize; + return res; +} + +size_t +krb5_crypto_overhead (krb5_context context, krb5_crypto crypto) +{ + if (derived_crypto (context, crypto)) + return crypto_overhead_dervied (context, crypto); + else + return crypto_overhead (context, crypto); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_random_to_key(krb5_context context, + krb5_enctype type, + const void *data, + size_t size, + krb5_keyblock *key) +{ + krb5_error_code ret; + struct encryption_type *et = _find_enctype(type); + if(et == NULL) { + krb5_set_error_string(context, "encryption type %d not supported", + type); + return KRB5_PROG_ETYPE_NOSUPP; + } + if ((et->keytype->bits + 7) / 8 > size) { + krb5_set_error_string(context, "encryption key %s needs %d bytes " + "of random to make an encryption key out of it", + et->name, (int)et->keytype->size); + return KRB5_PROG_ETYPE_NOSUPP; + } + ret = krb5_data_alloc(&key->keyvalue, et->keytype->size); + if(ret) + return ret; + key->keytype = type; + if (et->keytype->random_to_key) + (*et->keytype->random_to_key)(context, key, data, size); + else + memcpy(key->keyvalue.data, data, et->keytype->size); + + return 0; +} + +krb5_error_code +_krb5_pk_octetstring2key(krb5_context context, + krb5_enctype type, + const void *dhdata, + size_t dhsize, + const heim_octet_string *c_n, + const heim_octet_string *k_n, + krb5_keyblock *key) +{ + struct encryption_type *et = _find_enctype(type); + krb5_error_code ret; + size_t keylen, offset; + void *keydata; + unsigned char counter; + unsigned char shaoutput[20]; + + if(et == NULL) { + krb5_set_error_string(context, "encryption type %d not supported", + type); + return KRB5_PROG_ETYPE_NOSUPP; + } + keylen = (et->keytype->bits + 7) / 8; + + keydata = malloc(keylen); + if (keydata == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + counter = 0; + offset = 0; + do { + SHA_CTX m; + + SHA1_Init(&m); + SHA1_Update(&m, &counter, 1); + SHA1_Update(&m, dhdata, dhsize); + if (c_n) + SHA1_Update(&m, c_n->data, c_n->length); + if (k_n) + SHA1_Update(&m, k_n->data, k_n->length); + SHA1_Final(shaoutput, &m); + + memcpy((unsigned char *)keydata + offset, + shaoutput, + min(keylen - offset, sizeof(shaoutput))); + + offset += sizeof(shaoutput); + counter++; + } while(offset < keylen); + memset(shaoutput, 0, sizeof(shaoutput)); + + ret = krb5_random_to_key(context, type, keydata, keylen, key); + memset(keydata, 0, sizeof(keylen)); + free(keydata); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_crypto_prf_length(krb5_context context, + krb5_enctype type, + size_t *length) +{ + struct encryption_type *et = _find_enctype(type); + + if(et == NULL || et->prf_length == 0) { + krb5_set_error_string(context, "encryption type %d not supported", + type); + return KRB5_PROG_ETYPE_NOSUPP; + } + + *length = et->prf_length; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_crypto_prf(krb5_context context, + const krb5_crypto crypto, + const krb5_data *input, + krb5_data *output) +{ + struct encryption_type *et = crypto->et; + + krb5_data_zero(output); + + if(et->prf == NULL) { + krb5_set_error_string(context, "kerberos prf for %s not supported", + et->name); + return KRB5_PROG_ETYPE_NOSUPP; + } + + return (*et->prf)(context, crypto, input, output); +} + + + + +#ifdef CRYPTO_DEBUG + +static krb5_error_code +krb5_get_keyid(krb5_context context, + krb5_keyblock *key, + uint32_t *keyid) +{ + MD5_CTX md5; + unsigned char tmp[16]; + + MD5_Init (&md5); + MD5_Update (&md5, key->keyvalue.data, key->keyvalue.length); + MD5_Final (tmp, &md5); + *keyid = (tmp[12] << 24) | (tmp[13] << 16) | (tmp[14] << 8) | tmp[15]; + return 0; +} + +static void +krb5_crypto_debug(krb5_context context, + int encryptp, + size_t len, + krb5_keyblock *key) +{ + uint32_t keyid; + char *kt; + krb5_get_keyid(context, key, &keyid); + krb5_enctype_to_string(context, key->keytype, &kt); + krb5_warnx(context, "%s %lu bytes with key-id %#x (%s)", + encryptp ? "encrypting" : "decrypting", + (unsigned long)len, + keyid, + kt); + free(kt); +} + +#endif /* CRYPTO_DEBUG */ + +#if 0 +int +main() +{ +#if 0 + int i; + krb5_context context; + krb5_crypto crypto; + struct key_data *d; + krb5_keyblock key; + char constant[4]; + unsigned usage = ENCRYPTION_USAGE(3); + krb5_error_code ret; + + ret = krb5_init_context(&context); + if (ret) + errx (1, "krb5_init_context failed: %d", ret); + + key.keytype = ETYPE_NEW_DES3_CBC_SHA1; + key.keyvalue.data = "\xb3\x85\x58\x94\xd9\xdc\x7c\xc8" + "\x25\xe9\x85\xab\x3e\xb5\xfb\x0e" + "\xc8\xdf\xab\x26\x86\x64\x15\x25"; + key.keyvalue.length = 24; + + krb5_crypto_init(context, &key, 0, &crypto); + + d = _new_derived_key(crypto, usage); + if(d == NULL) + krb5_errx(context, 1, "_new_derived_key failed"); + krb5_copy_keyblock(context, crypto->key.key, &d->key); + _krb5_put_int(constant, usage, 4); + derive_key(context, crypto->et, d, constant, sizeof(constant)); + return 0; +#else + int i; + krb5_context context; + krb5_crypto crypto; + struct key_data *d; + krb5_keyblock key; + krb5_error_code ret; + Checksum res; + + char *data = "what do ya want for nothing?"; + + ret = krb5_init_context(&context); + if (ret) + errx (1, "krb5_init_context failed: %d", ret); + + key.keytype = ETYPE_NEW_DES3_CBC_SHA1; + key.keyvalue.data = "Jefe"; + /* "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"; */ + key.keyvalue.length = 4; + + d = ecalloc(1, sizeof(*d)); + d->key = &key; + res.checksum.length = 20; + res.checksum.data = emalloc(res.checksum.length); + SP_HMAC_SHA1_checksum(context, d, data, 28, &res); + + return 0; +#endif +} +#endif diff --git a/lib/krb5/data.c b/lib/krb5/data.c new file mode 100644 index 0000000..eda1a8b --- /dev/null +++ b/lib/krb5/data.c @@ -0,0 +1,224 @@ +/* + * Copyright (c) 1997 - 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: data.c 22064 2007-11-11 16:28:14Z lha $"); + +/** + * Reset the (potentially uninitalized) krb5_data structure. + * + * @param p krb5_data to reset. + * + * @ingroup krb5 + */ + +void KRB5_LIB_FUNCTION +krb5_data_zero(krb5_data *p) +{ + p->length = 0; + p->data = NULL; +} + +/** + * Free the content of krb5_data structure, its ok to free a zeroed + * structure. When done, the structure will be zeroed. + * + * @param p krb5_data to free. + * + * @ingroup krb5 + */ + +void KRB5_LIB_FUNCTION +krb5_data_free(krb5_data *p) +{ + if(p->data != NULL) + free(p->data); + krb5_data_zero(p); +} + +/** + * Same as krb5_data_free(). + * + * @param context Kerberos 5 context. + * @param data krb5_data to free. + * + * @ingroup krb5 + */ + +void KRB5_LIB_FUNCTION +krb5_free_data_contents(krb5_context context, krb5_data *data) +{ + krb5_data_free(data); +} + +/** + * Free krb5_data (and its content). + * + * @param context Kerberos 5 context. + * @param p krb5_data to free. + * + * @ingroup krb5 + */ + +void KRB5_LIB_FUNCTION +krb5_free_data(krb5_context context, + krb5_data *p) +{ + krb5_data_free(p); + free(p); +} + +/** + * Allocate data of and krb5_data. + * + * @param p krb5_data to free. + * @param len size to allocate. + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned. + * + * @ingroup krb5 + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_data_alloc(krb5_data *p, int len) +{ + p->data = malloc(len); + if(len && p->data == NULL) + return ENOMEM; + p->length = len; + return 0; +} + +/** + * Grow (or shrink) the content of krb5_data to a new size. + * + * @param p krb5_data to free. + * @param len new size. + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned. + * + * @ingroup krb5 + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_data_realloc(krb5_data *p, int len) +{ + void *tmp; + tmp = realloc(p->data, len); + if(len && !tmp) + return ENOMEM; + p->data = tmp; + p->length = len; + return 0; +} + +/** + * Copy the data of len into the krb5_data. + * + * @param p krb5_data to copy into. + * @param data data to copy.. + * @param len new size. + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned. + * + * @ingroup krb5 + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_data_copy(krb5_data *p, const void *data, size_t len) +{ + if (len) { + if(krb5_data_alloc(p, len)) + return ENOMEM; + memmove(p->data, data, len); + } else + p->data = NULL; + p->length = len; + return 0; +} + +/** + * Copy the data into a newly allocated krb5_data. + * + * @param context Kerberos 5 context. + * @param indata the krb5_data data to copy + * @param outdata new krb5_date to copy too. Free with krb5_free_data(). + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned. + * + * @ingroup krb5 + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_data(krb5_context context, + const krb5_data *indata, + krb5_data **outdata) +{ + krb5_error_code ret; + ALLOC(*outdata, 1); + if(*outdata == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + ret = der_copy_octet_string(indata, *outdata); + if(ret) { + krb5_clear_error_string (context); + free(*outdata); + *outdata = NULL; + } + return ret; +} + +/** + * Compare to data. + * + * @param data1 krb5_data to compare + * @param data2 krb5_data to compare + * + * @return return the same way as memcmp(), useful when sorting. + * + * @ingroup krb5 + */ + +int KRB5_LIB_FUNCTION +krb5_data_cmp(const krb5_data *data1, const krb5_data *data2) +{ + if (data1->length != data2->length) + return data1->length - data2->length; + return memcmp(data1->data, data2->data, data1->length); +} diff --git a/lib/krb5/derived-key-test.c b/lib/krb5/derived-key-test.c new file mode 100644 index 0000000..debadb8 --- /dev/null +++ b/lib/krb5/derived-key-test.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include "krb5_locl.h" +#include <err.h> + +RCSID("$Id: derived-key-test.c 16342 2005-12-02 14:14:43Z lha $"); + +enum { MAXSIZE = 24 }; + +static struct testcase { + krb5_enctype enctype; + unsigned char constant[MAXSIZE]; + size_t constant_len; + unsigned char key[MAXSIZE]; + unsigned char res[MAXSIZE]; +} tests[] = { + {ETYPE_DES3_CBC_SHA1, {0x00, 0x00, 0x00, 0x01, 0x55}, 5, + {0xdc, 0xe0, 0x6b, 0x1f, 0x64, 0xc8, 0x57, 0xa1, 0x1c, 0x3d, 0xb5, 0x7c, 0x51, 0x89, 0x9b, 0x2c, 0xc1, 0x79, 0x10, 0x08, 0xce, 0x97, 0x3b, 0x92}, + {0x92, 0x51, 0x79, 0xd0, 0x45, 0x91, 0xa7, 0x9b, 0x5d, 0x31, 0x92, 0xc4, 0xa7, 0xe9, 0xc2, 0x89, 0xb0, 0x49, 0xc7, 0x1f, 0x6e, 0xe6, 0x04, 0xcd}}, + {ETYPE_DES3_CBC_SHA1, {0x00, 0x00, 0x00, 0x01, 0xaa}, 5, + {0x5e, 0x13, 0xd3, 0x1c, 0x70, 0xef, 0x76, 0x57, 0x46, 0x57, 0x85, 0x31, 0xcb, 0x51, 0xc1, 0x5b, 0xf1, 0x1c, 0xa8, 0x2c, 0x97, 0xce, 0xe9, 0xf2}, + {0x9e, 0x58, 0xe5, 0xa1, 0x46, 0xd9, 0x94, 0x2a, 0x10, 0x1c, 0x46, 0x98, 0x45, 0xd6, 0x7a, 0x20, 0xe3, 0xc4, 0x25, 0x9e, 0xd9, 0x13, 0xf2, 0x07}}, + {ETYPE_DES3_CBC_SHA1, {0x00, 0x00, 0x00, 0x01, 0x55}, 5, + {0x98, 0xe6, 0xfd, 0x8a, 0x04, 0xa4, 0xb6, 0x85, 0x9b, 0x75, 0xa1, 0x76, 0x54, 0x0b, 0x97, 0x52, 0xba, 0xd3, 0xec, 0xd6, 0x10, 0xa2, 0x52, 0xbc}, + {0x13, 0xfe, 0xf8, 0x0d, 0x76, 0x3e, 0x94, 0xec, 0x6d, 0x13, 0xfd, 0x2c, 0xa1, 0xd0, 0x85, 0x07, 0x02, 0x49, 0xda, 0xd3, 0x98, 0x08, 0xea, 0xbf}}, + {ETYPE_DES3_CBC_SHA1, {0x00, 0x00, 0x00, 0x01, 0xaa}, 5, + {0x62, 0x2a, 0xec, 0x25, 0xa2, 0xfe, 0x2c, 0xad, 0x70, 0x94, 0x68, 0x0b, 0x7c, 0x64, 0x94, 0x02, 0x80, 0x08, 0x4c, 0x1a, 0x7c, 0xec, 0x92, 0xb5}, + {0xf8, 0xdf, 0xbf, 0x04, 0xb0, 0x97, 0xe6, 0xd9, 0xdc, 0x07, 0x02, 0x68, 0x6b, 0xcb, 0x34, 0x89, 0xd9, 0x1f, 0xd9, 0xa4, 0x51, 0x6b, 0x70, 0x3e}}, + {ETYPE_DES3_CBC_SHA1, {0x6b, 0x65, 0x72, 0x62, 0x65, 0x72, 0x6f, 0x73}, 8, + {0xd3, 0xf8, 0x29, 0x8c, 0xcb, 0x16, 0x64, 0x38, 0xdc, 0xb9, 0xb9, 0x3e, 0xe5, 0xa7, 0x62, 0x92, 0x86, 0xa4, 0x91, 0xf8, 0x38, 0xf8, 0x02, 0xfb}, + {0x23, 0x70, 0xda, 0x57, 0x5d, 0x2a, 0x3d, 0xa8, 0x64, 0xce, 0xbf, 0xdc, 0x52, 0x04, 0xd5, 0x6d, 0xf7, 0x79, 0xa7, 0xdf, 0x43, 0xd9, 0xda, 0x43}}, + {ETYPE_DES3_CBC_SHA1, {0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65}, 7, + {0xb5, 0x5e, 0x98, 0x34, 0x67, 0xe5, 0x51, 0xb3, 0xe5, 0xd0, 0xe5, 0xb6, 0xc8, 0x0d, 0x45, 0x76, 0x94, 0x23, 0xa8, 0x73, 0xdc, 0x62, 0xb3, 0x0e}, + {0x01, 0x26, 0x38, 0x8a, 0xad, 0xc8, 0x1a, 0x1f, 0x2a, 0x62, 0xbc, 0x45, 0xf8, 0xd5, 0xc1, 0x91, 0x51, 0xba, 0xcd, 0xd5, 0xcb, 0x79, 0x8a, 0x3e}}, + {ETYPE_DES3_CBC_SHA1, {0x00, 0x00, 0x00, 0x01, 0x55}, 5, + {0xc1, 0x08, 0x16, 0x49, 0xad, 0xa7, 0x43, 0x62, 0xe6, 0xa1, 0x45, 0x9d, 0x01, 0xdf, 0xd3, 0x0d, 0x67, 0xc2, 0x23, 0x4c, 0x94, 0x07, 0x04, 0xda}, + {0x34, 0x80, 0x57, 0xec, 0x98, 0xfd, 0xc4, 0x80, 0x16, 0x16, 0x1c, 0x2a, 0x4c, 0x7a, 0x94, 0x3e, 0x92, 0xae, 0x49, 0x2c, 0x98, 0x91, 0x75, 0xf7}}, + {ETYPE_DES3_CBC_SHA1, {0x00, 0x00, 0x00, 0x01, 0xaa}, 5, + {0x5d, 0x15, 0x4a, 0xf2, 0x38, 0xf4, 0x67, 0x13, 0x15, 0x57, 0x19, 0xd5, 0x5e, 0x2f, 0x1f, 0x79, 0x0d, 0xd6, 0x61, 0xf2, 0x79, 0xa7, 0x91, 0x7c}, + {0xa8, 0x80, 0x8a, 0xc2, 0x67, 0xda, 0xda, 0x3d, 0xcb, 0xe9, 0xa7, 0xc8, 0x46, 0x26, 0xfb, 0xc7, 0x61, 0xc2, 0x94, 0xb0, 0x13, 0x15, 0xe5, 0xc1}}, + {ETYPE_DES3_CBC_SHA1, {0x00, 0x00, 0x00, 0x01, 0x55}, 5, + {0x79, 0x85, 0x62, 0xe0, 0x49, 0x85, 0x2f, 0x57, 0xdc, 0x8c, 0x34, 0x3b, 0xa1, 0x7f, 0x2c, 0xa1, 0xd9, 0x73, 0x94, 0xef, 0xc8, 0xad, 0xc4, 0x43}, + {0xc8, 0x13, 0xf8, 0x8a, 0x3b, 0xe3, 0xb3, 0x34, 0xf7, 0x54, 0x25, 0xce, 0x91, 0x75, 0xfb, 0xe3, 0xc8, 0x49, 0x3b, 0x89, 0xc8, 0x70, 0x3b, 0x49}}, + {ETYPE_DES3_CBC_SHA1, {0x00, 0x00, 0x00, 0x01, 0xaa}, 5, + {0x26, 0xdc, 0xe3, 0x34, 0xb5, 0x45, 0x29, 0x2f, 0x2f, 0xea, 0xb9, 0xa8, 0x70, 0x1a, 0x89, 0xa4, 0xb9, 0x9e, 0xb9, 0x94, 0x2c, 0xec, 0xd0, 0x16}, + {0xf4, 0x8f, 0xfd, 0x6e, 0x83, 0xf8, 0x3e, 0x73, 0x54, 0xe6, 0x94, 0xfd, 0x25, 0x2c, 0xf8, 0x3b, 0xfe, 0x58, 0xf7, 0xd5, 0xba, 0x37, 0xec, 0x5d}}, + {0} +}; + +int KRB5_LIB_FUNCTION +main(int argc, char **argv) +{ + struct testcase *t; + krb5_context context; + krb5_error_code ret; + int val = 0; + + ret = krb5_init_context (&context); + if (ret) + errx (1, "krb5_init_context failed: %d", ret); + + for (t = tests; t->enctype != 0; ++t) { + krb5_keyblock key; + krb5_keyblock *dkey; + + key.keytype = KEYTYPE_DES3; + key.keyvalue.length = MAXSIZE; + key.keyvalue.data = t->key; + + ret = krb5_derive_key(context, &key, t->enctype, t->constant, + t->constant_len, &dkey); + if (ret) + krb5_err (context, 1, ret, "krb5_derive_key"); + if (memcmp (dkey->keyvalue.data, t->res, dkey->keyvalue.length) != 0) { + const unsigned char *p = dkey->keyvalue.data; + int i; + + printf ("derive_key failed\n"); + printf ("should be: "); + for (i = 0; i < dkey->keyvalue.length; ++i) + printf ("%02x", t->res[i]); + printf ("\nresult was: "); + for (i = 0; i < dkey->keyvalue.length; ++i) + printf ("%02x", p[i]); + printf ("\n"); + val = 1; + } + krb5_free_keyblock(context, dkey); + } + krb5_free_context(context); + + return val; +} diff --git a/lib/krb5/digest.c b/lib/krb5/digest.c new file mode 100644 index 0000000..6e612ed --- /dev/null +++ b/lib/krb5/digest.c @@ -0,0 +1,1199 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" +RCSID("$Id: digest.c 22156 2007-12-04 20:02:49Z lha $"); +#include "digest_asn1.h" + +struct krb5_digest_data { + char *cbtype; + char *cbbinding; + + DigestInit init; + DigestInitReply initReply; + DigestRequest request; + DigestResponse response; +}; + +krb5_error_code +krb5_digest_alloc(krb5_context context, krb5_digest *digest) +{ + krb5_digest d; + + d = calloc(1, sizeof(*d)); + if (d == NULL) { + *digest = NULL; + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + *digest = d; + + return 0; +} + +void +krb5_digest_free(krb5_digest digest) +{ + if (digest == NULL) + return; + free_DigestInit(&digest->init); + free_DigestInitReply(&digest->initReply); + free_DigestRequest(&digest->request); + free_DigestResponse(&digest->response); + memset(digest, 0, sizeof(*digest)); + free(digest); + return; +} + +krb5_error_code +krb5_digest_set_server_cb(krb5_context context, + krb5_digest digest, + const char *type, + const char *binding) +{ + if (digest->init.channel) { + krb5_set_error_string(context, "server channel binding already set"); + return EINVAL; + } + digest->init.channel = calloc(1, sizeof(*digest->init.channel)); + if (digest->init.channel == NULL) + goto error; + + digest->init.channel->cb_type = strdup(type); + if (digest->init.channel->cb_type == NULL) + goto error; + + digest->init.channel->cb_binding = strdup(binding); + if (digest->init.channel->cb_binding == NULL) + goto error; + return 0; +error: + if (digest->init.channel) { + free(digest->init.channel->cb_type); + free(digest->init.channel->cb_binding); + free(digest->init.channel); + digest->init.channel = NULL; + } + krb5_set_error_string(context, "out of memory"); + return ENOMEM; +} + +krb5_error_code +krb5_digest_set_type(krb5_context context, + krb5_digest digest, + const char *type) +{ + if (digest->init.type) { + krb5_set_error_string(context, "client type already set"); + return EINVAL; + } + digest->init.type = strdup(type); + if (digest->init.type == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + return 0; +} + +krb5_error_code +krb5_digest_set_hostname(krb5_context context, + krb5_digest digest, + const char *hostname) +{ + if (digest->init.hostname) { + krb5_set_error_string(context, "server hostname already set"); + return EINVAL; + } + digest->init.hostname = malloc(sizeof(*digest->init.hostname)); + if (digest->init.hostname == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + *digest->init.hostname = strdup(hostname); + if (*digest->init.hostname == NULL) { + krb5_set_error_string(context, "out of memory"); + free(digest->init.hostname); + digest->init.hostname = NULL; + return ENOMEM; + } + return 0; +} + +const char * +krb5_digest_get_server_nonce(krb5_context context, + krb5_digest digest) +{ + return digest->initReply.nonce; +} + +krb5_error_code +krb5_digest_set_server_nonce(krb5_context context, + krb5_digest digest, + const char *nonce) +{ + if (digest->request.serverNonce) { + krb5_set_error_string(context, "nonce already set"); + return EINVAL; + } + digest->request.serverNonce = strdup(nonce); + if (digest->request.serverNonce == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + return 0; +} + +const char * +krb5_digest_get_opaque(krb5_context context, + krb5_digest digest) +{ + return digest->initReply.opaque; +} + +krb5_error_code +krb5_digest_set_opaque(krb5_context context, + krb5_digest digest, + const char *opaque) +{ + if (digest->request.opaque) { + krb5_set_error_string(context, "opaque already set"); + return EINVAL; + } + digest->request.opaque = strdup(opaque); + if (digest->request.opaque == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + return 0; +} + +const char * +krb5_digest_get_identifier(krb5_context context, + krb5_digest digest) +{ + if (digest->initReply.identifier == NULL) + return NULL; + return *digest->initReply.identifier; +} + +krb5_error_code +krb5_digest_set_identifier(krb5_context context, + krb5_digest digest, + const char *id) +{ + if (digest->request.identifier) { + krb5_set_error_string(context, "identifier already set"); + return EINVAL; + } + digest->request.identifier = calloc(1, sizeof(*digest->request.identifier)); + if (digest->request.identifier == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + *digest->request.identifier = strdup(id); + if (*digest->request.identifier == NULL) { + krb5_set_error_string(context, "out of memory"); + free(digest->request.identifier); + digest->request.identifier = NULL; + return ENOMEM; + } + return 0; +} + +static krb5_error_code +digest_request(krb5_context context, + krb5_realm realm, + krb5_ccache ccache, + krb5_key_usage usage, + const DigestReqInner *ireq, + DigestRepInner *irep) +{ + DigestREQ req; + DigestREP rep; + krb5_error_code ret; + krb5_data data, data2; + size_t size; + krb5_crypto crypto = NULL; + krb5_auth_context ac = NULL; + krb5_principal principal = NULL; + krb5_ccache id = NULL; + krb5_realm r = NULL; + + krb5_data_zero(&data); + krb5_data_zero(&data2); + memset(&req, 0, sizeof(req)); + memset(&rep, 0, sizeof(rep)); + + if (ccache == NULL) { + ret = krb5_cc_default(context, &id); + if (ret) + goto out; + } else + id = ccache; + + if (realm == NULL) { + ret = krb5_get_default_realm(context, &r); + if (ret) + goto out; + } else + r = realm; + + /* + * + */ + + ret = krb5_make_principal(context, &principal, + r, KRB5_DIGEST_NAME, r, NULL); + if (ret) + goto out; + + ASN1_MALLOC_ENCODE(DigestReqInner, data.data, data.length, + ireq, &size, ret); + if (ret) { + krb5_set_error_string(context, + "Failed to encode digest inner request"); + goto out; + } + if (size != data.length) + krb5_abortx(context, "ASN.1 internal encoder error"); + + ret = krb5_mk_req_exact(context, &ac, + AP_OPTS_USE_SUBKEY|AP_OPTS_MUTUAL_REQUIRED, + principal, NULL, id, &req.apReq); + if (ret) + goto out; + + { + krb5_keyblock *key; + + ret = krb5_auth_con_getlocalsubkey(context, ac, &key); + if (ret) + goto out; + if (key == NULL) { + krb5_set_error_string(context, "Digest failed to get local subkey"); + ret = EINVAL; + goto out; + } + + ret = krb5_crypto_init(context, key, 0, &crypto); + krb5_free_keyblock (context, key); + if (ret) + goto out; + } + + ret = krb5_encrypt_EncryptedData(context, crypto, usage, + data.data, data.length, 0, + &req.innerReq); + if (ret) + goto out; + + krb5_data_free(&data); + + ASN1_MALLOC_ENCODE(DigestREQ, data.data, data.length, + &req, &size, ret); + if (ret) { + krb5_set_error_string(context, "Failed to encode DigestREQest"); + goto out; + } + if (size != data.length) + krb5_abortx(context, "ASN.1 internal encoder error"); + + ret = krb5_sendto_kdc(context, &data, &r, &data2); + if (ret) + goto out; + + ret = decode_DigestREP(data2.data, data2.length, &rep, NULL); + if (ret) { + krb5_set_error_string(context, "Failed to parse digest response"); + goto out; + } + + { + krb5_ap_rep_enc_part *repl; + + ret = krb5_rd_rep(context, ac, &rep.apRep, &repl); + if (ret) + goto out; + + krb5_free_ap_rep_enc_part(context, repl); + } + { + krb5_keyblock *key; + + ret = krb5_auth_con_getremotesubkey(context, ac, &key); + if (ret) + goto out; + if (key == NULL) { + ret = EINVAL; + krb5_set_error_string(context, + "Digest reply have no remote subkey"); + goto out; + } + + krb5_crypto_destroy(context, crypto); + ret = krb5_crypto_init(context, key, 0, &crypto); + krb5_free_keyblock (context, key); + if (ret) + goto out; + } + + krb5_data_free(&data); + ret = krb5_decrypt_EncryptedData(context, crypto, usage, + &rep.innerRep, &data); + if (ret) + goto out; + + ret = decode_DigestRepInner(data.data, data.length, irep, NULL); + if (ret) { + krb5_set_error_string(context, "Failed to decode digest inner reply"); + goto out; + } + +out: + if (ccache == NULL && id) + krb5_cc_close(context, id); + if (realm == NULL && r) + free(r); + if (crypto) + krb5_crypto_destroy(context, crypto); + if (ac) + krb5_auth_con_free(context, ac); + if (principal) + krb5_free_principal(context, principal); + + krb5_data_free(&data); + krb5_data_free(&data2); + + free_DigestREQ(&req); + free_DigestREP(&rep); + + return ret; +} + +krb5_error_code +krb5_digest_init_request(krb5_context context, + krb5_digest digest, + krb5_realm realm, + krb5_ccache ccache) +{ + DigestReqInner ireq; + DigestRepInner irep; + krb5_error_code ret; + + memset(&ireq, 0, sizeof(ireq)); + memset(&irep, 0, sizeof(irep)); + + if (digest->init.type == NULL) { + krb5_set_error_string(context, "Type missing from init req"); + return EINVAL; + } + + ireq.element = choice_DigestReqInner_init; + ireq.u.init = digest->init; + + ret = digest_request(context, realm, ccache, + KRB5_KU_DIGEST_ENCRYPT, &ireq, &irep); + if (ret) + goto out; + + if (irep.element == choice_DigestRepInner_error) { + krb5_set_error_string(context, "Digest init error: %s", + irep.u.error.reason); + ret = irep.u.error.code; + goto out; + } + + if (irep.element != choice_DigestRepInner_initReply) { + krb5_set_error_string(context, "digest reply not an initReply"); + ret = EINVAL; + goto out; + } + + ret = copy_DigestInitReply(&irep.u.initReply, &digest->initReply); + if (ret) { + krb5_set_error_string(context, "Failed to copy initReply"); + goto out; + } + +out: + free_DigestRepInner(&irep); + + return ret; +} + + +krb5_error_code +krb5_digest_set_client_nonce(krb5_context context, + krb5_digest digest, + const char *nonce) +{ + if (digest->request.clientNonce) { + krb5_set_error_string(context, "clientNonce already set"); + return EINVAL; + } + digest->request.clientNonce = + calloc(1, sizeof(*digest->request.clientNonce)); + if (digest->request.clientNonce == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + *digest->request.clientNonce = strdup(nonce); + if (*digest->request.clientNonce == NULL) { + krb5_set_error_string(context, "out of memory"); + free(digest->request.clientNonce); + digest->request.clientNonce = NULL; + return ENOMEM; + } + return 0; +} + +krb5_error_code +krb5_digest_set_digest(krb5_context context, + krb5_digest digest, + const char *dgst) +{ + if (digest->request.digest) { + krb5_set_error_string(context, "digest already set"); + return EINVAL; + } + digest->request.digest = strdup(dgst); + if (digest->request.digest == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + return 0; +} + +krb5_error_code +krb5_digest_set_username(krb5_context context, + krb5_digest digest, + const char *username) +{ + if (digest->request.username) { + krb5_set_error_string(context, "username already set"); + return EINVAL; + } + digest->request.username = strdup(username); + if (digest->request.username == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + return 0; +} + +krb5_error_code +krb5_digest_set_authid(krb5_context context, + krb5_digest digest, + const char *authid) +{ + if (digest->request.authid) { + krb5_set_error_string(context, "authid already set"); + return EINVAL; + } + digest->request.authid = malloc(sizeof(*digest->request.authid)); + if (digest->request.authid == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + *digest->request.authid = strdup(authid); + if (*digest->request.authid == NULL) { + krb5_set_error_string(context, "out of memory"); + free(digest->request.authid); + digest->request.authid = NULL; + return ENOMEM; + } + return 0; +} + +krb5_error_code +krb5_digest_set_authentication_user(krb5_context context, + krb5_digest digest, + krb5_principal authentication_user) +{ + krb5_error_code ret; + + if (digest->request.authentication_user) { + krb5_set_error_string(context, "authentication_user already set"); + return EINVAL; + } + ret = krb5_copy_principal(context, + authentication_user, + &digest->request.authentication_user); + if (digest->request.authentication_user == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + return 0; +} + +krb5_error_code +krb5_digest_set_realm(krb5_context context, + krb5_digest digest, + const char *realm) +{ + if (digest->request.realm) { + krb5_set_error_string(context, "realm already set"); + return EINVAL; + } + digest->request.realm = malloc(sizeof(*digest->request.realm)); + if (digest->request.realm == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + *digest->request.realm = strdup(realm); + if (*digest->request.realm == NULL) { + krb5_set_error_string(context, "out of memory"); + free(digest->request.realm); + digest->request.realm = NULL; + return ENOMEM; + } + return 0; +} + +krb5_error_code +krb5_digest_set_method(krb5_context context, + krb5_digest digest, + const char *method) +{ + if (digest->request.method) { + krb5_set_error_string(context, "method already set"); + return EINVAL; + } + digest->request.method = malloc(sizeof(*digest->request.method)); + if (digest->request.method == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + *digest->request.method = strdup(method); + if (*digest->request.method == NULL) { + krb5_set_error_string(context, "out of memory"); + free(digest->request.method); + digest->request.method = NULL; + return ENOMEM; + } + return 0; +} + +krb5_error_code +krb5_digest_set_uri(krb5_context context, + krb5_digest digest, + const char *uri) +{ + if (digest->request.uri) { + krb5_set_error_string(context, "uri already set"); + return EINVAL; + } + digest->request.uri = malloc(sizeof(*digest->request.uri)); + if (digest->request.uri == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + *digest->request.uri = strdup(uri); + if (*digest->request.uri == NULL) { + krb5_set_error_string(context, "out of memory"); + free(digest->request.uri); + digest->request.uri = NULL; + return ENOMEM; + } + return 0; +} + +krb5_error_code +krb5_digest_set_nonceCount(krb5_context context, + krb5_digest digest, + const char *nonce_count) +{ + if (digest->request.nonceCount) { + krb5_set_error_string(context, "nonceCount already set"); + return EINVAL; + } + digest->request.nonceCount = + malloc(sizeof(*digest->request.nonceCount)); + if (digest->request.nonceCount == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + *digest->request.nonceCount = strdup(nonce_count); + if (*digest->request.nonceCount == NULL) { + krb5_set_error_string(context, "out of memory"); + free(digest->request.nonceCount); + digest->request.nonceCount = NULL; + return ENOMEM; + } + return 0; +} + +krb5_error_code +krb5_digest_set_qop(krb5_context context, + krb5_digest digest, + const char *qop) +{ + if (digest->request.qop) { + krb5_set_error_string(context, "qop already set"); + return EINVAL; + } + digest->request.qop = malloc(sizeof(*digest->request.qop)); + if (digest->request.qop == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + *digest->request.qop = strdup(qop); + if (*digest->request.qop == NULL) { + krb5_set_error_string(context, "out of memory"); + free(digest->request.qop); + digest->request.qop = NULL; + return ENOMEM; + } + return 0; +} + +int +krb5_digest_set_responseData(krb5_context context, + krb5_digest digest, + const char *response) +{ + digest->request.responseData = strdup(response); + if (digest->request.responseData == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + return 0; +} + +krb5_error_code +krb5_digest_request(krb5_context context, + krb5_digest digest, + krb5_realm realm, + krb5_ccache ccache) +{ + DigestReqInner ireq; + DigestRepInner irep; + krb5_error_code ret; + + memset(&ireq, 0, sizeof(ireq)); + memset(&irep, 0, sizeof(irep)); + + ireq.element = choice_DigestReqInner_digestRequest; + ireq.u.digestRequest = digest->request; + + if (digest->request.type == NULL) { + if (digest->init.type == NULL) { + krb5_set_error_string(context, "Type missing from req"); + return EINVAL; + } + ireq.u.digestRequest.type = digest->init.type; + } + + if (ireq.u.digestRequest.digest == NULL) + ireq.u.digestRequest.digest = "md5"; + + ret = digest_request(context, realm, ccache, + KRB5_KU_DIGEST_ENCRYPT, &ireq, &irep); + if (ret) + return ret; + + if (irep.element == choice_DigestRepInner_error) { + krb5_set_error_string(context, "Digest response error: %s", + irep.u.error.reason); + ret = irep.u.error.code; + goto out; + } + + if (irep.element != choice_DigestRepInner_response) { + krb5_set_error_string(context, "digest reply not an DigestResponse"); + ret = EINVAL; + goto out; + } + + ret = copy_DigestResponse(&irep.u.response, &digest->response); + if (ret) { + krb5_set_error_string(context, "Failed to copy initReply"); + goto out; + } + +out: + free_DigestRepInner(&irep); + + return ret; +} + +krb5_boolean +krb5_digest_rep_get_status(krb5_context context, + krb5_digest digest) +{ + return digest->response.success ? TRUE : FALSE; +} + +const char * +krb5_digest_get_rsp(krb5_context context, + krb5_digest digest) +{ + if (digest->response.rsp == NULL) + return NULL; + return *digest->response.rsp; +} + +krb5_error_code +krb5_digest_get_tickets(krb5_context context, + krb5_digest digest, + Ticket **tickets) +{ + *tickets = NULL; + return 0; +} + + +krb5_error_code +krb5_digest_get_client_binding(krb5_context context, + krb5_digest digest, + char **type, + char **binding) +{ + if (digest->response.channel) { + *type = strdup(digest->response.channel->cb_type); + *binding = strdup(digest->response.channel->cb_binding); + if (*type == NULL || *binding == NULL) { + free(*type); + free(*binding); + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + } else { + *type = NULL; + *binding = NULL; + } + return 0; +} + +krb5_error_code +krb5_digest_get_session_key(krb5_context context, + krb5_digest digest, + krb5_data *data) +{ + krb5_error_code ret; + + krb5_data_zero(data); + if (digest->response.session_key == NULL) + return 0; + ret = der_copy_octet_string(digest->response.session_key, data); + if (ret) + krb5_clear_error_string(context); + + return ret; +} + +struct krb5_ntlm_data { + NTLMInit init; + NTLMInitReply initReply; + NTLMRequest request; + NTLMResponse response; +}; + +krb5_error_code +krb5_ntlm_alloc(krb5_context context, + krb5_ntlm *ntlm) +{ + *ntlm = calloc(1, sizeof(**ntlm)); + if (*ntlm == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + return 0; +} + +krb5_error_code +krb5_ntlm_free(krb5_context context, krb5_ntlm ntlm) +{ + free_NTLMInit(&ntlm->init); + free_NTLMInitReply(&ntlm->initReply); + free_NTLMRequest(&ntlm->request); + free_NTLMResponse(&ntlm->response); + memset(ntlm, 0, sizeof(*ntlm)); + free(ntlm); + return 0; +} + + +krb5_error_code +krb5_ntlm_init_request(krb5_context context, + krb5_ntlm ntlm, + krb5_realm realm, + krb5_ccache ccache, + uint32_t flags, + const char *hostname, + const char *domainname) +{ + DigestReqInner ireq; + DigestRepInner irep; + krb5_error_code ret; + + memset(&ireq, 0, sizeof(ireq)); + memset(&irep, 0, sizeof(irep)); + + ntlm->init.flags = flags; + if (hostname) { + ALLOC(ntlm->init.hostname, 1); + *ntlm->init.hostname = strdup(hostname); + } + if (domainname) { + ALLOC(ntlm->init.domain, 1); + *ntlm->init.domain = strdup(domainname); + } + + ireq.element = choice_DigestReqInner_ntlmInit; + ireq.u.ntlmInit = ntlm->init; + + ret = digest_request(context, realm, ccache, + KRB5_KU_DIGEST_ENCRYPT, &ireq, &irep); + if (ret) + goto out; + + if (irep.element == choice_DigestRepInner_error) { + krb5_set_error_string(context, "Digest init error: %s", + irep.u.error.reason); + ret = irep.u.error.code; + goto out; + } + + if (irep.element != choice_DigestRepInner_ntlmInitReply) { + krb5_set_error_string(context, "ntlm reply not an initReply"); + ret = EINVAL; + goto out; + } + + ret = copy_NTLMInitReply(&irep.u.ntlmInitReply, &ntlm->initReply); + if (ret) { + krb5_set_error_string(context, "Failed to copy initReply"); + goto out; + } + +out: + free_DigestRepInner(&irep); + + return ret; +} + +krb5_error_code +krb5_ntlm_init_get_flags(krb5_context context, + krb5_ntlm ntlm, + uint32_t *flags) +{ + *flags = ntlm->initReply.flags; + return 0; +} + +krb5_error_code +krb5_ntlm_init_get_challange(krb5_context context, + krb5_ntlm ntlm, + krb5_data *challange) +{ + krb5_error_code ret; + + ret = der_copy_octet_string(&ntlm->initReply.challange, challange); + if (ret) + krb5_clear_error_string(context); + + return ret; +} + +krb5_error_code +krb5_ntlm_init_get_opaque(krb5_context context, + krb5_ntlm ntlm, + krb5_data *opaque) +{ + krb5_error_code ret; + + ret = der_copy_octet_string(&ntlm->initReply.opaque, opaque); + if (ret) + krb5_clear_error_string(context); + + return ret; +} + +krb5_error_code +krb5_ntlm_init_get_targetname(krb5_context context, + krb5_ntlm ntlm, + char **name) +{ + *name = strdup(ntlm->initReply.targetname); + if (*name == NULL) { + krb5_clear_error_string(context); + return ENOMEM; + } + return 0; +} + +krb5_error_code +krb5_ntlm_init_get_targetinfo(krb5_context context, + krb5_ntlm ntlm, + krb5_data *data) +{ + krb5_error_code ret; + + if (ntlm->initReply.targetinfo == NULL) { + krb5_data_zero(data); + return 0; + } + + ret = krb5_data_copy(data, + ntlm->initReply.targetinfo->data, + ntlm->initReply.targetinfo->length); + if (ret) { + krb5_clear_error_string(context); + return ret; + } + return 0; +} + + +krb5_error_code +krb5_ntlm_request(krb5_context context, + krb5_ntlm ntlm, + krb5_realm realm, + krb5_ccache ccache) +{ + DigestReqInner ireq; + DigestRepInner irep; + krb5_error_code ret; + + memset(&ireq, 0, sizeof(ireq)); + memset(&irep, 0, sizeof(irep)); + + ireq.element = choice_DigestReqInner_ntlmRequest; + ireq.u.ntlmRequest = ntlm->request; + + ret = digest_request(context, realm, ccache, + KRB5_KU_DIGEST_ENCRYPT, &ireq, &irep); + if (ret) + return ret; + + if (irep.element == choice_DigestRepInner_error) { + krb5_set_error_string(context, "NTLM response error: %s", + irep.u.error.reason); + ret = irep.u.error.code; + goto out; + } + + if (irep.element != choice_DigestRepInner_ntlmResponse) { + krb5_set_error_string(context, "NTLM reply not an NTLMResponse"); + ret = EINVAL; + goto out; + } + + ret = copy_NTLMResponse(&irep.u.ntlmResponse, &ntlm->response); + if (ret) { + krb5_set_error_string(context, "Failed to copy NTLMResponse"); + goto out; + } + +out: + free_DigestRepInner(&irep); + + return ret; +} + +krb5_error_code +krb5_ntlm_req_set_flags(krb5_context context, + krb5_ntlm ntlm, + uint32_t flags) +{ + ntlm->request.flags = flags; + return 0; +} + +krb5_error_code +krb5_ntlm_req_set_username(krb5_context context, + krb5_ntlm ntlm, + const char *username) +{ + ntlm->request.username = strdup(username); + if (ntlm->request.username == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + return 0; +} + +krb5_error_code +krb5_ntlm_req_set_targetname(krb5_context context, + krb5_ntlm ntlm, + const char *targetname) +{ + ntlm->request.targetname = strdup(targetname); + if (ntlm->request.targetname == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + return 0; +} + +krb5_error_code +krb5_ntlm_req_set_lm(krb5_context context, + krb5_ntlm ntlm, + void *hash, size_t len) +{ + ntlm->request.lm.data = malloc(len); + if (ntlm->request.lm.data == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + ntlm->request.lm.length = len; + memcpy(ntlm->request.lm.data, hash, len); + return 0; +} + +krb5_error_code +krb5_ntlm_req_set_ntlm(krb5_context context, + krb5_ntlm ntlm, + void *hash, size_t len) +{ + ntlm->request.ntlm.data = malloc(len); + if (ntlm->request.ntlm.data == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + ntlm->request.ntlm.length = len; + memcpy(ntlm->request.ntlm.data, hash, len); + return 0; +} + +krb5_error_code +krb5_ntlm_req_set_opaque(krb5_context context, + krb5_ntlm ntlm, + krb5_data *opaque) +{ + ntlm->request.opaque.data = malloc(opaque->length); + if (ntlm->request.opaque.data == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + ntlm->request.opaque.length = opaque->length; + memcpy(ntlm->request.opaque.data, opaque->data, opaque->length); + return 0; +} + +krb5_error_code +krb5_ntlm_req_set_session(krb5_context context, + krb5_ntlm ntlm, + void *sessionkey, size_t length) +{ + ntlm->request.sessionkey = calloc(1, sizeof(*ntlm->request.sessionkey)); + if (ntlm->request.sessionkey == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + ntlm->request.sessionkey->data = malloc(length); + if (ntlm->request.sessionkey->data == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + memcpy(ntlm->request.sessionkey->data, sessionkey, length); + ntlm->request.sessionkey->length = length; + return 0; +} + +krb5_boolean +krb5_ntlm_rep_get_status(krb5_context context, + krb5_ntlm ntlm) +{ + return ntlm->response.success ? TRUE : FALSE; +} + +krb5_error_code +krb5_ntlm_rep_get_sessionkey(krb5_context context, + krb5_ntlm ntlm, + krb5_data *data) +{ + if (ntlm->response.sessionkey == NULL) { + krb5_set_error_string(context, "no ntlm session key"); + return EINVAL; + } + krb5_clear_error_string(context); + return krb5_data_copy(data, + ntlm->response.sessionkey->data, + ntlm->response.sessionkey->length); +} + +/** + * Get the supported/allowed mechanism for this principal. + * + * @param context A Keberos context. + * @param realm The realm of the KDC. + * @param ccache The credential cache to use when talking to the KDC. + * @param flags The supported mechanism. + * + * @return Return an error code or 0. + * + * @ingroup krb5_digest + */ + +krb5_error_code +krb5_digest_probe(krb5_context context, + krb5_realm realm, + krb5_ccache ccache, + unsigned *flags) +{ + DigestReqInner ireq; + DigestRepInner irep; + krb5_error_code ret; + + memset(&ireq, 0, sizeof(ireq)); + memset(&irep, 0, sizeof(irep)); + + ireq.element = choice_DigestReqInner_supportedMechs; + + ret = digest_request(context, realm, ccache, + KRB5_KU_DIGEST_ENCRYPT, &ireq, &irep); + if (ret) + goto out; + + if (irep.element == choice_DigestRepInner_error) { + krb5_set_error_string(context, "Digest probe error: %s", + irep.u.error.reason); + ret = irep.u.error.code; + goto out; + } + + if (irep.element != choice_DigestRepInner_supportedMechs) { + krb5_set_error_string(context, "Digest reply not an probe"); + ret = EINVAL; + goto out; + } + + *flags = DigestTypes2int(irep.u.supportedMechs); + +out: + free_DigestRepInner(&irep); + + return ret; +} diff --git a/lib/krb5/doxygen.c b/lib/krb5/doxygen.c new file mode 100644 index 0000000..b7c6f8f --- /dev/null +++ b/lib/krb5/doxygen.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" +RCSID("$Id$"); + +/** + * + */ + +/*! \mainpage Heimdal Kerberos 5 library + * + * \section intro Introduction + * + * Heimdal libkrb5 library is a implementation of the Kerberos + * protocol. + * + * Kerberos is a system for authenticating users and services on a + * network. It is built upon the assumption that the network is + * ``unsafe''. For example, data sent over the network can be + * eavesdropped and altered, and addresses can also be faked. + * Therefore they cannot be used for authentication purposes. + * + * The project web page:\n + * http://www.h5l.org/ + * + */ + +/** @defgroup krb5 Heimdal Kerberos 5 library */ +/** @defgroup krb5_address Heimdal Kerberos 5 address functions */ +/** @defgroup krb5_ccache Heimdal Kerberos 5 credential cache functions */ +/** @defgroup krb5_credential Heimdal Kerberos 5 credential handing functions */ +/** @defgroup krb5_deprecated Heimdal Kerberos 5 deprecated functions */ +/** @defgroup krb5_digest Heimdal Kerberos 5 digest service */ +/** @defgroup krb5_error Heimdal Kerberos 5 error reporting functions */ +/** @defgroup krb5_v4compat Heimdal Kerberos 4 compatiblity functions */ +/** @defgroup krb5_support Heimdal Kerberos 5 support functions */ diff --git a/lib/krb5/dump_config.c b/lib/krb5/dump_config.c new file mode 100644 index 0000000..074595e --- /dev/null +++ b/lib/krb5/dump_config.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include "krb5_locl.h" + +RCSID("$Id: dump_config.c,v 1.2 1999/10/28 23:22:41 assar Exp $"); + +/* print contents of krb5.conf */ + +static void +print_tree(struct krb5_config_binding *b, int level) +{ + if (b == NULL) + return; + + printf("%*s%s%s%s", level * 4, "", + (level == 0) ? "[" : "", b->name, (level == 0) ? "]" : ""); + if(b->type == krb5_config_list) { + if(level > 0) + printf(" = {"); + printf("\n"); + print_tree(b->u.list, level + 1); + if(level > 0) + printf("%*s}\n", level * 4, ""); + } else if(b->type == krb5_config_string) { + printf(" = %s\n", b->u.string); + } + if(b->next) + print_tree(b->next, level); +} + +int +main(int argc, char **argv) +{ + krb5_context context; + krb5_error_code ret = krb5_init_context(&context); + if(ret == 0) { + print_tree(context->cf, 0); + return 0; + } + return 1; +} diff --git a/lib/krb5/eai_to_heim_errno.c b/lib/krb5/eai_to_heim_errno.c new file mode 100644 index 0000000..19315ce --- /dev/null +++ b/lib/krb5/eai_to_heim_errno.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2000 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <krb5_locl.h> + +RCSID("$Id: eai_to_heim_errno.c 22065 2007-11-11 16:41:06Z lha $"); + +/** + * Convert the getaddrinfo() error code to a Kerberos et error code. + * + * @param eai_errno contains the error code from getaddrinfo(). + * @param system_error should have the value of errno after the failed getaddrinfo(). + * + * @return Kerberos error code representing the EAI errors. + * + * @ingroup krb5_error + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_eai_to_heim_errno(int eai_errno, int system_error) +{ + switch(eai_errno) { + case EAI_NOERROR: + return 0; +#ifdef EAI_ADDRFAMILY + case EAI_ADDRFAMILY: + return HEIM_EAI_ADDRFAMILY; +#endif + case EAI_AGAIN: + return HEIM_EAI_AGAIN; + case EAI_BADFLAGS: + return HEIM_EAI_BADFLAGS; + case EAI_FAIL: + return HEIM_EAI_FAIL; + case EAI_FAMILY: + return HEIM_EAI_FAMILY; + case EAI_MEMORY: + return HEIM_EAI_MEMORY; +#if defined(EAI_NODATA) && EAI_NODATA != EAI_NONAME + case EAI_NODATA: + return HEIM_EAI_NODATA; +#endif + case EAI_NONAME: + return HEIM_EAI_NONAME; + case EAI_SERVICE: + return HEIM_EAI_SERVICE; + case EAI_SOCKTYPE: + return HEIM_EAI_SOCKTYPE; + case EAI_SYSTEM: + return system_error; + default: + return HEIM_EAI_UNKNOWN; /* XXX */ + } +} + +/** + * Convert the gethostname() error code (h_error) to a Kerberos et + * error code. + * + * @param eai_errno contains the error code from gethostname(). + * + * @return Kerberos error code representing the gethostname errors. + * + * @ingroup krb5_error + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_h_errno_to_heim_errno(int eai_errno) +{ + switch(eai_errno) { + case 0: + return 0; + case HOST_NOT_FOUND: + return HEIM_EAI_NONAME; + case TRY_AGAIN: + return HEIM_EAI_AGAIN; + case NO_RECOVERY: + return HEIM_EAI_FAIL; + case NO_DATA: + return HEIM_EAI_NONAME; + default: + return HEIM_EAI_UNKNOWN; /* XXX */ + } +} diff --git a/lib/krb5/error_string.c b/lib/krb5/error_string.c new file mode 100644 index 0000000..ff6e98a --- /dev/null +++ b/lib/krb5/error_string.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2001, 2003, 2005 - 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: error_string.c 22142 2007-12-04 16:56:02Z lha $"); + +#undef __attribute__ +#define __attribute__(X) + +void KRB5_LIB_FUNCTION +krb5_free_error_string(krb5_context context, char *str) +{ + HEIMDAL_MUTEX_lock(context->mutex); + if (str != context->error_buf) + free(str); + HEIMDAL_MUTEX_unlock(context->mutex); +} + +void KRB5_LIB_FUNCTION +krb5_clear_error_string(krb5_context context) +{ + HEIMDAL_MUTEX_lock(context->mutex); + if (context->error_string != NULL + && context->error_string != context->error_buf) + free(context->error_string); + context->error_string = NULL; + HEIMDAL_MUTEX_unlock(context->mutex); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_error_string(krb5_context context, const char *fmt, ...) + __attribute__((format (printf, 2, 3))) +{ + krb5_error_code ret; + va_list ap; + + va_start(ap, fmt); + ret = krb5_vset_error_string (context, fmt, ap); + va_end(ap); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_vset_error_string(krb5_context context, const char *fmt, va_list args) + __attribute__ ((format (printf, 2, 0))) +{ + krb5_clear_error_string(context); + HEIMDAL_MUTEX_lock(context->mutex); + vasprintf(&context->error_string, fmt, args); + if(context->error_string == NULL) { + vsnprintf (context->error_buf, sizeof(context->error_buf), fmt, args); + context->error_string = context->error_buf; + } + HEIMDAL_MUTEX_unlock(context->mutex); + return 0; +} + +/** + * Return the error message in context. On error or no error string, + * the function returns NULL. + * + * @param context Kerberos 5 context + * + * @return an error string, needs to be freed with + * krb5_free_error_string(). The functions return NULL on error. + * + * @ingroup krb5_error + */ + +char * KRB5_LIB_FUNCTION +krb5_get_error_string(krb5_context context) +{ + char *ret = NULL; + + HEIMDAL_MUTEX_lock(context->mutex); + if (context->error_string) + ret = strdup(context->error_string); + HEIMDAL_MUTEX_unlock(context->mutex); + return ret; +} + +krb5_boolean KRB5_LIB_FUNCTION +krb5_have_error_string(krb5_context context) +{ + char *str; + HEIMDAL_MUTEX_lock(context->mutex); + str = context->error_string; + HEIMDAL_MUTEX_unlock(context->mutex); + return str != NULL; +} + +/** + * Return the error message for `code' in context. On error the + * function returns NULL. + * + * @param context Kerberos 5 context + * @param code Error code related to the error + * + * @return an error string, needs to be freed with + * krb5_free_error_string(). The functions return NULL on error. + * + * @ingroup krb5_error + */ + +char * KRB5_LIB_FUNCTION +krb5_get_error_message(krb5_context context, krb5_error_code code) +{ + const char *cstr; + char *str; + + str = krb5_get_error_string(context); + if (str) + return str; + + cstr = krb5_get_err_text(context, code); + if (cstr) + return strdup(cstr); + + if (asprintf(&str, "<unknown error: %d>", code) == -1) + return NULL; + + return str; +} + diff --git a/lib/krb5/expand_hostname.c b/lib/krb5/expand_hostname.c new file mode 100644 index 0000000..28e39af --- /dev/null +++ b/lib/krb5/expand_hostname.c @@ -0,0 +1,160 @@ +/* + * Copyright (c) 1999 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: expand_hostname.c 22229 2007-12-08 21:40:59Z lha $"); + +static krb5_error_code +copy_hostname(krb5_context context, + const char *orig_hostname, + char **new_hostname) +{ + *new_hostname = strdup (orig_hostname); + if (*new_hostname == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + strlwr (*new_hostname); + return 0; +} + +/* + * Try to make `orig_hostname' into a more canonical one in the newly + * allocated space returned in `new_hostname'. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_expand_hostname (krb5_context context, + const char *orig_hostname, + char **new_hostname) +{ + struct addrinfo *ai, *a, hints; + int error; + + if ((context->flags & KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME) == 0) + return copy_hostname (context, orig_hostname, new_hostname); + + memset (&hints, 0, sizeof(hints)); + hints.ai_flags = AI_CANONNAME; + + error = getaddrinfo (orig_hostname, NULL, &hints, &ai); + if (error) + return copy_hostname (context, orig_hostname, new_hostname); + for (a = ai; a != NULL; a = a->ai_next) { + if (a->ai_canonname != NULL) { + *new_hostname = strdup (a->ai_canonname); + freeaddrinfo (ai); + if (*new_hostname == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } else { + return 0; + } + } + } + freeaddrinfo (ai); + return copy_hostname (context, orig_hostname, new_hostname); +} + +/* + * handle the case of the hostname being unresolvable and thus identical + */ + +static krb5_error_code +vanilla_hostname (krb5_context context, + const char *orig_hostname, + char **new_hostname, + char ***realms) +{ + krb5_error_code ret; + + ret = copy_hostname (context, orig_hostname, new_hostname); + if (ret) + return ret; + strlwr (*new_hostname); + + ret = krb5_get_host_realm (context, *new_hostname, realms); + if (ret) { + free (*new_hostname); + return ret; + } + return 0; +} + +/* + * expand `hostname' to a name we believe to be a hostname in newly + * allocated space in `host' and return realms in `realms'. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_expand_hostname_realms (krb5_context context, + const char *orig_hostname, + char **new_hostname, + char ***realms) +{ + struct addrinfo *ai, *a, hints; + int error; + krb5_error_code ret = 0; + + if ((context->flags & KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME) == 0) + return vanilla_hostname (context, orig_hostname, new_hostname, + realms); + + memset (&hints, 0, sizeof(hints)); + hints.ai_flags = AI_CANONNAME; + + error = getaddrinfo (orig_hostname, NULL, &hints, &ai); + if (error) + return vanilla_hostname (context, orig_hostname, new_hostname, + realms); + + for (a = ai; a != NULL; a = a->ai_next) { + if (a->ai_canonname != NULL) { + ret = copy_hostname (context, a->ai_canonname, new_hostname); + if (ret) { + freeaddrinfo (ai); + return ret; + } + strlwr (*new_hostname); + ret = krb5_get_host_realm (context, *new_hostname, realms); + if (ret == 0) { + freeaddrinfo (ai); + return 0; + } + free (*new_hostname); + } + } + freeaddrinfo(ai); + return vanilla_hostname (context, orig_hostname, new_hostname, realms); +} diff --git a/lib/krb5/fcache.c b/lib/krb5/fcache.c new file mode 100644 index 0000000..3857b58 --- /dev/null +++ b/lib/krb5/fcache.c @@ -0,0 +1,881 @@ +/* + * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: fcache.c 22522 2008-01-24 11:56:25Z lha $"); + +typedef struct krb5_fcache{ + char *filename; + int version; +}krb5_fcache; + +struct fcc_cursor { + int fd; + krb5_storage *sp; +}; + +#define KRB5_FCC_FVNO_1 1 +#define KRB5_FCC_FVNO_2 2 +#define KRB5_FCC_FVNO_3 3 +#define KRB5_FCC_FVNO_4 4 + +#define FCC_TAG_DELTATIME 1 + +#define FCACHE(X) ((krb5_fcache*)(X)->data.data) + +#define FILENAME(X) (FCACHE(X)->filename) + +#define FCC_CURSOR(C) ((struct fcc_cursor*)(C)) + +static const char* +fcc_get_name(krb5_context context, + krb5_ccache id) +{ + return FILENAME(id); +} + +int +_krb5_xlock(krb5_context context, int fd, krb5_boolean exclusive, + const char *filename) +{ + int ret; +#ifdef HAVE_FCNTL + struct flock l; + + l.l_start = 0; + l.l_len = 0; + l.l_type = exclusive ? F_WRLCK : F_RDLCK; + l.l_whence = SEEK_SET; + ret = fcntl(fd, F_SETLKW, &l); +#else + ret = flock(fd, exclusive ? LOCK_EX : LOCK_SH); +#endif + if(ret < 0) + ret = errno; + if(ret == EACCES) /* fcntl can return EACCES instead of EAGAIN */ + ret = EAGAIN; + + switch (ret) { + case 0: + break; + case EINVAL: /* filesystem doesn't support locking, let the user have it */ + ret = 0; + break; + case EAGAIN: + krb5_set_error_string(context, "timed out locking cache file %s", + filename); + break; + default: + krb5_set_error_string(context, "error locking cache file %s: %s", + filename, strerror(ret)); + break; + } + return ret; +} + +int +_krb5_xunlock(krb5_context context, int fd) +{ + int ret; +#ifdef HAVE_FCNTL + struct flock l; + l.l_start = 0; + l.l_len = 0; + l.l_type = F_UNLCK; + l.l_whence = SEEK_SET; + ret = fcntl(fd, F_SETLKW, &l); +#else + ret = flock(fd, LOCK_UN); +#endif + if (ret < 0) + ret = errno; + switch (ret) { + case 0: + break; + case EINVAL: /* filesystem doesn't support locking, let the user have it */ + ret = 0; + break; + default: + krb5_set_error_string(context, + "Failed to unlock file: %s", strerror(ret)); + break; + } + return ret; +} + +static krb5_error_code +fcc_lock(krb5_context context, krb5_ccache id, + int fd, krb5_boolean exclusive) +{ + return _krb5_xlock(context, fd, exclusive, fcc_get_name(context, id)); +} + +static krb5_error_code +fcc_unlock(krb5_context context, int fd) +{ + return _krb5_xunlock(context, fd); +} + +static krb5_error_code +fcc_resolve(krb5_context context, krb5_ccache *id, const char *res) +{ + krb5_fcache *f; + f = malloc(sizeof(*f)); + if(f == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return KRB5_CC_NOMEM; + } + f->filename = strdup(res); + if(f->filename == NULL){ + free(f); + krb5_set_error_string(context, "malloc: out of memory"); + return KRB5_CC_NOMEM; + } + f->version = 0; + (*id)->data.data = f; + (*id)->data.length = sizeof(*f); + return 0; +} + +/* + * Try to scrub the contents of `filename' safely. + */ + +static int +scrub_file (int fd) +{ + off_t pos; + char buf[128]; + + pos = lseek(fd, 0, SEEK_END); + if (pos < 0) + return errno; + if (lseek(fd, 0, SEEK_SET) < 0) + return errno; + memset(buf, 0, sizeof(buf)); + while(pos > 0) { + ssize_t tmp = write(fd, buf, min(sizeof(buf), pos)); + + if (tmp < 0) + return errno; + pos -= tmp; + } + fsync (fd); + return 0; +} + +/* + * Erase `filename' if it exists, trying to remove the contents if + * it's `safe'. We always try to remove the file, it it exists. It's + * only overwritten if it's a regular file (not a symlink and not a + * hardlink) + */ + +static krb5_error_code +erase_file(const char *filename) +{ + int fd; + struct stat sb1, sb2; + int ret; + + ret = lstat (filename, &sb1); + if (ret < 0) + return errno; + + fd = open(filename, O_RDWR | O_BINARY); + if(fd < 0) { + if(errno == ENOENT) + return 0; + else + return errno; + } + if (unlink(filename) < 0) { + close (fd); + return errno; + } + ret = fstat (fd, &sb2); + if (ret < 0) { + close (fd); + return errno; + } + + /* check if someone was playing with symlinks */ + + if (sb1.st_dev != sb2.st_dev || sb1.st_ino != sb2.st_ino) { + close (fd); + return EPERM; + } + + /* there are still hard links to this file */ + + if (sb2.st_nlink != 0) { + close (fd); + return 0; + } + + ret = scrub_file (fd); + close (fd); + return ret; +} + +static krb5_error_code +fcc_gen_new(krb5_context context, krb5_ccache *id) +{ + krb5_fcache *f; + int fd; + char *file; + + f = malloc(sizeof(*f)); + if(f == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return KRB5_CC_NOMEM; + } + asprintf (&file, "%sXXXXXX", KRB5_DEFAULT_CCFILE_ROOT); + if(file == NULL) { + free(f); + krb5_set_error_string(context, "malloc: out of memory"); + return KRB5_CC_NOMEM; + } + fd = mkstemp(file); + if(fd < 0) { + int ret = errno; + krb5_set_error_string(context, "mkstemp %s", file); + free(f); + free(file); + return ret; + } + close(fd); + f->filename = file; + f->version = 0; + (*id)->data.data = f; + (*id)->data.length = sizeof(*f); + return 0; +} + +static void +storage_set_flags(krb5_context context, krb5_storage *sp, int vno) +{ + int flags = 0; + switch(vno) { + case KRB5_FCC_FVNO_1: + flags |= KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS; + flags |= KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE; + flags |= KRB5_STORAGE_HOST_BYTEORDER; + break; + case KRB5_FCC_FVNO_2: + flags |= KRB5_STORAGE_HOST_BYTEORDER; + break; + case KRB5_FCC_FVNO_3: + flags |= KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE; + break; + case KRB5_FCC_FVNO_4: + break; + default: + krb5_abortx(context, + "storage_set_flags called with bad vno (%x)", vno); + } + krb5_storage_set_flags(sp, flags); +} + +static krb5_error_code +fcc_open(krb5_context context, + krb5_ccache id, + int *fd_ret, + int flags, + mode_t mode) +{ + krb5_boolean exclusive = ((flags | O_WRONLY) == flags || + (flags | O_RDWR) == flags); + krb5_error_code ret; + const char *filename = FILENAME(id); + int fd; + fd = open(filename, flags, mode); + if(fd < 0) { + ret = errno; + krb5_set_error_string(context, "open(%s): %s", filename, + strerror(ret)); + return ret; + } + + if((ret = fcc_lock(context, id, fd, exclusive)) != 0) { + close(fd); + return ret; + } + *fd_ret = fd; + return 0; +} + +static krb5_error_code +fcc_initialize(krb5_context context, + krb5_ccache id, + krb5_principal primary_principal) +{ + krb5_fcache *f = FCACHE(id); + int ret = 0; + int fd; + char *filename = f->filename; + + unlink (filename); + + ret = fcc_open(context, id, &fd, O_RDWR | O_CREAT | O_EXCL | O_BINARY, 0600); + if(ret) + return ret; + { + krb5_storage *sp; + sp = krb5_storage_from_fd(fd); + krb5_storage_set_eof_code(sp, KRB5_CC_END); + if(context->fcache_vno != 0) + f->version = context->fcache_vno; + else + f->version = KRB5_FCC_FVNO_4; + ret |= krb5_store_int8(sp, 5); + ret |= krb5_store_int8(sp, f->version); + storage_set_flags(context, sp, f->version); + if(f->version == KRB5_FCC_FVNO_4 && ret == 0) { + /* V4 stuff */ + if (context->kdc_sec_offset) { + ret |= krb5_store_int16 (sp, 12); /* length */ + ret |= krb5_store_int16 (sp, FCC_TAG_DELTATIME); /* Tag */ + ret |= krb5_store_int16 (sp, 8); /* length of data */ + ret |= krb5_store_int32 (sp, context->kdc_sec_offset); + ret |= krb5_store_int32 (sp, context->kdc_usec_offset); + } else { + ret |= krb5_store_int16 (sp, 0); + } + } + ret |= krb5_store_principal(sp, primary_principal); + + krb5_storage_free(sp); + } + fcc_unlock(context, fd); + if (close(fd) < 0) + if (ret == 0) { + ret = errno; + krb5_set_error_string (context, "close %s: %s", + FILENAME(id), strerror(ret)); + } + return ret; +} + +static krb5_error_code +fcc_close(krb5_context context, + krb5_ccache id) +{ + free (FILENAME(id)); + krb5_data_free(&id->data); + return 0; +} + +static krb5_error_code +fcc_destroy(krb5_context context, + krb5_ccache id) +{ + erase_file(FILENAME(id)); + return 0; +} + +static krb5_error_code +fcc_store_cred(krb5_context context, + krb5_ccache id, + krb5_creds *creds) +{ + int ret; + int fd; + + ret = fcc_open(context, id, &fd, O_WRONLY | O_APPEND | O_BINARY, 0); + if(ret) + return ret; + { + krb5_storage *sp; + sp = krb5_storage_from_fd(fd); + krb5_storage_set_eof_code(sp, KRB5_CC_END); + storage_set_flags(context, sp, FCACHE(id)->version); + if (!krb5_config_get_bool_default(context, NULL, TRUE, + "libdefaults", + "fcc-mit-ticketflags", + NULL)) + krb5_storage_set_flags(sp, KRB5_STORAGE_CREDS_FLAGS_WRONG_BITORDER); + ret = krb5_store_creds(sp, creds); + krb5_storage_free(sp); + } + fcc_unlock(context, fd); + if (close(fd) < 0) + if (ret == 0) { + ret = errno; + krb5_set_error_string (context, "close %s: %s", + FILENAME(id), strerror(ret)); + } + return ret; +} + +static krb5_error_code +init_fcc (krb5_context context, + krb5_ccache id, + krb5_storage **ret_sp, + int *ret_fd) +{ + int fd; + int8_t pvno, tag; + krb5_storage *sp; + krb5_error_code ret; + + ret = fcc_open(context, id, &fd, O_RDONLY | O_BINARY, 0); + if(ret) + return ret; + + sp = krb5_storage_from_fd(fd); + if(sp == NULL) { + krb5_clear_error_string(context); + ret = ENOMEM; + goto out; + } + krb5_storage_set_eof_code(sp, KRB5_CC_END); + ret = krb5_ret_int8(sp, &pvno); + if(ret != 0) { + if(ret == KRB5_CC_END) { + krb5_set_error_string(context, "Empty credential cache file: %s", + FILENAME(id)); + ret = ENOENT; + } else + krb5_set_error_string(context, "Error reading pvno in " + "cache file: %s", FILENAME(id)); + goto out; + } + if(pvno != 5) { + krb5_set_error_string(context, "Bad version number in credential " + "cache file: %s", FILENAME(id)); + ret = KRB5_CCACHE_BADVNO; + goto out; + } + ret = krb5_ret_int8(sp, &tag); /* should not be host byte order */ + if(ret != 0) { + krb5_set_error_string(context, "Error reading tag in " + "cache file: %s", FILENAME(id)); + ret = KRB5_CC_FORMAT; + goto out; + } + FCACHE(id)->version = tag; + storage_set_flags(context, sp, FCACHE(id)->version); + switch (tag) { + case KRB5_FCC_FVNO_4: { + int16_t length; + + ret = krb5_ret_int16 (sp, &length); + if(ret) { + ret = KRB5_CC_FORMAT; + krb5_set_error_string(context, "Error reading tag length in " + "cache file: %s", FILENAME(id)); + goto out; + } + while(length > 0) { + int16_t dtag, data_len; + int i; + int8_t dummy; + + ret = krb5_ret_int16 (sp, &dtag); + if(ret) { + krb5_set_error_string(context, "Error reading dtag in " + "cache file: %s", FILENAME(id)); + ret = KRB5_CC_FORMAT; + goto out; + } + ret = krb5_ret_int16 (sp, &data_len); + if(ret) { + krb5_set_error_string(context, "Error reading dlength in " + "cache file: %s", FILENAME(id)); + ret = KRB5_CC_FORMAT; + goto out; + } + switch (dtag) { + case FCC_TAG_DELTATIME : + ret = krb5_ret_int32 (sp, &context->kdc_sec_offset); + if(ret) { + krb5_set_error_string(context, "Error reading kdc_sec in " + "cache file: %s", FILENAME(id)); + ret = KRB5_CC_FORMAT; + goto out; + } + ret = krb5_ret_int32 (sp, &context->kdc_usec_offset); + if(ret) { + krb5_set_error_string(context, "Error reading kdc_usec in " + "cache file: %s", FILENAME(id)); + ret = KRB5_CC_FORMAT; + goto out; + } + break; + default : + for (i = 0; i < data_len; ++i) { + ret = krb5_ret_int8 (sp, &dummy); + if(ret) { + krb5_set_error_string(context, "Error reading unknown " + "tag in cache file: %s", + FILENAME(id)); + ret = KRB5_CC_FORMAT; + goto out; + } + } + break; + } + length -= 4 + data_len; + } + break; + } + case KRB5_FCC_FVNO_3: + case KRB5_FCC_FVNO_2: + case KRB5_FCC_FVNO_1: + break; + default : + ret = KRB5_CCACHE_BADVNO; + krb5_set_error_string(context, "Unknown version number (%d) in " + "credential cache file: %s", + (int)tag, FILENAME(id)); + goto out; + } + *ret_sp = sp; + *ret_fd = fd; + + return 0; + out: + if(sp != NULL) + krb5_storage_free(sp); + fcc_unlock(context, fd); + close(fd); + return ret; +} + +static krb5_error_code +fcc_get_principal(krb5_context context, + krb5_ccache id, + krb5_principal *principal) +{ + krb5_error_code ret; + int fd; + krb5_storage *sp; + + ret = init_fcc (context, id, &sp, &fd); + if (ret) + return ret; + ret = krb5_ret_principal(sp, principal); + if (ret) + krb5_clear_error_string(context); + krb5_storage_free(sp); + fcc_unlock(context, fd); + close(fd); + return ret; +} + +static krb5_error_code +fcc_end_get (krb5_context context, + krb5_ccache id, + krb5_cc_cursor *cursor); + +static krb5_error_code +fcc_get_first (krb5_context context, + krb5_ccache id, + krb5_cc_cursor *cursor) +{ + krb5_error_code ret; + krb5_principal principal; + + *cursor = malloc(sizeof(struct fcc_cursor)); + if (*cursor == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + memset(*cursor, 0, sizeof(struct fcc_cursor)); + + ret = init_fcc (context, id, &FCC_CURSOR(*cursor)->sp, + &FCC_CURSOR(*cursor)->fd); + if (ret) { + free(*cursor); + *cursor = NULL; + return ret; + } + ret = krb5_ret_principal (FCC_CURSOR(*cursor)->sp, &principal); + if(ret) { + krb5_clear_error_string(context); + fcc_end_get(context, id, cursor); + return ret; + } + krb5_free_principal (context, principal); + fcc_unlock(context, FCC_CURSOR(*cursor)->fd); + return 0; +} + +static krb5_error_code +fcc_get_next (krb5_context context, + krb5_ccache id, + krb5_cc_cursor *cursor, + krb5_creds *creds) +{ + krb5_error_code ret; + if((ret = fcc_lock(context, id, FCC_CURSOR(*cursor)->fd, FALSE)) != 0) + return ret; + + ret = krb5_ret_creds(FCC_CURSOR(*cursor)->sp, creds); + if (ret) + krb5_clear_error_string(context); + + fcc_unlock(context, FCC_CURSOR(*cursor)->fd); + return ret; +} + +static krb5_error_code +fcc_end_get (krb5_context context, + krb5_ccache id, + krb5_cc_cursor *cursor) +{ + krb5_storage_free(FCC_CURSOR(*cursor)->sp); + close (FCC_CURSOR(*cursor)->fd); + free(*cursor); + *cursor = NULL; + return 0; +} + +static krb5_error_code +fcc_remove_cred(krb5_context context, + krb5_ccache id, + krb5_flags which, + krb5_creds *cred) +{ + krb5_error_code ret; + krb5_ccache copy; + + ret = krb5_cc_gen_new(context, &krb5_mcc_ops, ©); + if (ret) + return ret; + + ret = krb5_cc_copy_cache(context, id, copy); + if (ret) { + krb5_cc_destroy(context, copy); + return ret; + } + + ret = krb5_cc_remove_cred(context, copy, which, cred); + if (ret) { + krb5_cc_destroy(context, copy); + return ret; + } + + fcc_destroy(context, id); + + ret = krb5_cc_copy_cache(context, copy, id); + krb5_cc_destroy(context, copy); + + return ret; +} + +static krb5_error_code +fcc_set_flags(krb5_context context, + krb5_ccache id, + krb5_flags flags) +{ + return 0; /* XXX */ +} + +static krb5_error_code +fcc_get_version(krb5_context context, + krb5_ccache id) +{ + return FCACHE(id)->version; +} + +struct fcache_iter { + int first; +}; + +static krb5_error_code +fcc_get_cache_first(krb5_context context, krb5_cc_cursor *cursor) +{ + struct fcache_iter *iter; + + iter = calloc(1, sizeof(*iter)); + if (iter == NULL) { + krb5_set_error_string(context, "malloc - out of memory"); + return ENOMEM; + } + iter->first = 1; + *cursor = iter; + return 0; +} + +static krb5_error_code +fcc_get_cache_next(krb5_context context, krb5_cc_cursor cursor, krb5_ccache *id) +{ + struct fcache_iter *iter = cursor; + krb5_error_code ret; + const char *fn; + char *expandedfn = NULL; + + if (!iter->first) { + krb5_clear_error_string(context); + return KRB5_CC_END; + } + iter->first = 0; + + fn = krb5_cc_default_name(context); + if (strncasecmp(fn, "FILE:", 5) != 0) { + ret = _krb5_expand_default_cc_name(context, + KRB5_DEFAULT_CCNAME_FILE, + &expandedfn); + if (ret) + return ret; + } + ret = krb5_cc_resolve(context, fn, id); + if (expandedfn) + free(expandedfn); + + return ret; +} + +static krb5_error_code +fcc_end_cache_get(krb5_context context, krb5_cc_cursor cursor) +{ + struct fcache_iter *iter = cursor; + free(iter); + return 0; +} + +static krb5_error_code +fcc_move(krb5_context context, krb5_ccache from, krb5_ccache to) +{ + krb5_error_code ret = 0; + + ret = rename(FILENAME(from), FILENAME(to)); + if (ret && errno != EXDEV) { + ret = errno; + krb5_set_error_string(context, + "Rename of file from %s to %s failed: %s", + FILENAME(from), FILENAME(to), + strerror(ret)); + return ret; + } else if (ret && errno == EXDEV) { + /* make a copy and delete the orignal */ + krb5_ssize_t sz1, sz2; + int fd1, fd2; + char buf[BUFSIZ]; + + ret = fcc_open(context, from, &fd1, O_RDONLY | O_BINARY, 0); + if(ret) + return ret; + + unlink(FILENAME(to)); + + ret = fcc_open(context, to, &fd2, + O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0600); + if(ret) + goto out1; + + while((sz1 = read(fd1, buf, sizeof(buf))) > 0) { + sz2 = write(fd2, buf, sz1); + if (sz1 != sz2) { + ret = EIO; + krb5_set_error_string(context, + "Failed to write data from one file " + "credential cache to the other"); + goto out2; + } + } + if (sz1 < 0) { + ret = EIO; + krb5_set_error_string(context, + "Failed to read data from one file " + "credential cache to the other"); + goto out2; + } + erase_file(FILENAME(from)); + + out2: + fcc_unlock(context, fd2); + close(fd2); + + out1: + fcc_unlock(context, fd1); + close(fd1); + + if (ret) { + erase_file(FILENAME(to)); + return ret; + } + } + + /* make sure ->version is uptodate */ + { + krb5_storage *sp; + int fd; + ret = init_fcc (context, to, &sp, &fd); + krb5_storage_free(sp); + fcc_unlock(context, fd); + close(fd); + } + return ret; +} + +static krb5_error_code +fcc_default_name(krb5_context context, char **str) +{ + return _krb5_expand_default_cc_name(context, + KRB5_DEFAULT_CCNAME_FILE, + str); +} + +/** + * Variable containing the FILE based credential cache implemention. + * + * @ingroup krb5_ccache + */ + +const krb5_cc_ops krb5_fcc_ops = { + "FILE", + fcc_get_name, + fcc_resolve, + fcc_gen_new, + fcc_initialize, + fcc_destroy, + fcc_close, + fcc_store_cred, + NULL, /* fcc_retrieve */ + fcc_get_principal, + fcc_get_first, + fcc_get_next, + fcc_end_get, + fcc_remove_cred, + fcc_set_flags, + fcc_get_version, + fcc_get_cache_first, + fcc_get_cache_next, + fcc_end_cache_get, + fcc_move, + fcc_default_name +}; diff --git a/lib/krb5/free.c b/lib/krb5/free.c new file mode 100644 index 0000000..1b0bd05 --- /dev/null +++ b/lib/krb5/free.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 1997 - 1999, 2004 - 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: free.c 15175 2005-05-18 10:06:16Z lha $"); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_free_kdc_rep(krb5_context context, krb5_kdc_rep *rep) +{ + free_KDC_REP(&rep->kdc_rep); + free_EncTGSRepPart(&rep->enc_part); + free_KRB_ERROR(&rep->error); + memset(rep, 0, sizeof(*rep)); + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_xfree (void *ptr) +{ + free (ptr); + return 0; +} diff --git a/lib/krb5/free_host_realm.c b/lib/krb5/free_host_realm.c new file mode 100644 index 0000000..6b13ce7 --- /dev/null +++ b/lib/krb5/free_host_realm.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 1997, 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: free_host_realm.c 13863 2004-05-25 21:46:46Z lha $"); + +/* + * Free all memory allocated by `realmlist' + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_free_host_realm(krb5_context context, + krb5_realm *realmlist) +{ + krb5_realm *p; + + if(realmlist == NULL) + return 0; + for (p = realmlist; *p; ++p) + free (*p); + free (realmlist); + return 0; +} diff --git a/lib/krb5/generate_seq_number.c b/lib/krb5/generate_seq_number.c new file mode 100644 index 0000000..8a04f04 --- /dev/null +++ b/lib/krb5/generate_seq_number.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <krb5_locl.h> + +RCSID("$Id: generate_seq_number.c 17442 2006-05-05 09:31:15Z lha $"); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_generate_seq_number(krb5_context context, + const krb5_keyblock *key, + uint32_t *seqno) +{ + krb5_error_code ret; + krb5_keyblock *subkey; + uint32_t q; + u_char *p; + int i; + + ret = krb5_generate_subkey (context, key, &subkey); + if (ret) + return ret; + + q = 0; + for (p = (u_char *)subkey->keyvalue.data, i = 0; + i < subkey->keyvalue.length; + ++i, ++p) + q = (q << 8) | *p; + q &= 0xffffffff; + *seqno = q; + krb5_free_keyblock (context, subkey); + return 0; +} diff --git a/lib/krb5/generate_subkey.c b/lib/krb5/generate_subkey.c new file mode 100644 index 0000000..fb99cbb --- /dev/null +++ b/lib/krb5/generate_subkey.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <krb5_locl.h> + +RCSID("$Id: generate_subkey.c 14455 2005-01-05 02:39:21Z lukeh $"); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_generate_subkey(krb5_context context, + const krb5_keyblock *key, + krb5_keyblock **subkey) +{ + return krb5_generate_subkey_extended(context, key, key->keytype, subkey); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_generate_subkey_extended(krb5_context context, + const krb5_keyblock *key, + krb5_enctype etype, + krb5_keyblock **subkey) +{ + krb5_error_code ret; + + ALLOC(*subkey, 1); + if (*subkey == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + if (etype == ETYPE_NULL) + etype = key->keytype; /* use session key etype */ + + /* XXX should we use the session key as input to the RF? */ + ret = krb5_generate_random_keyblock(context, etype, *subkey); + if (ret != 0) { + free(*subkey); + *subkey = NULL; + } + + return ret; +} + diff --git a/lib/krb5/get_addrs.c b/lib/krb5/get_addrs.c new file mode 100644 index 0000000..a7fd2ea --- /dev/null +++ b/lib/krb5/get_addrs.c @@ -0,0 +1,291 @@ +/* + * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: get_addrs.c 13863 2004-05-25 21:46:46Z lha $"); + +#ifdef __osf__ +/* hate */ +struct rtentry; +struct mbuf; +#endif +#ifdef HAVE_NET_IF_H +#include <net/if.h> +#endif +#include <ifaddrs.h> + +static krb5_error_code +gethostname_fallback (krb5_context context, krb5_addresses *res) +{ + krb5_error_code ret; + char hostname[MAXHOSTNAMELEN]; + struct hostent *hostent; + + if (gethostname (hostname, sizeof(hostname))) { + ret = errno; + krb5_set_error_string (context, "gethostname: %s", strerror(ret)); + return ret; + } + hostent = roken_gethostbyname (hostname); + if (hostent == NULL) { + ret = errno; + krb5_set_error_string (context, "gethostbyname %s: %s", + hostname, strerror(ret)); + return ret; + } + res->len = 1; + res->val = malloc (sizeof(*res->val)); + if (res->val == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + res->val[0].addr_type = hostent->h_addrtype; + res->val[0].address.data = NULL; + res->val[0].address.length = 0; + ret = krb5_data_copy (&res->val[0].address, + hostent->h_addr, + hostent->h_length); + if (ret) { + free (res->val); + return ret; + } + return 0; +} + +enum { + LOOP = 1, /* do include loopback interfaces */ + LOOP_IF_NONE = 2, /* include loopback if no other if's */ + EXTRA_ADDRESSES = 4, /* include extra addresses */ + SCAN_INTERFACES = 8 /* scan interfaces for addresses */ +}; + +/* + * Try to figure out the addresses of all configured interfaces with a + * lot of magic ioctls. + */ + +static krb5_error_code +find_all_addresses (krb5_context context, krb5_addresses *res, int flags) +{ + struct sockaddr sa_zero; + struct ifaddrs *ifa0, *ifa; + krb5_error_code ret = ENXIO; + int num, idx; + krb5_addresses ignore_addresses; + + res->val = NULL; + + if (getifaddrs(&ifa0) == -1) { + ret = errno; + krb5_set_error_string(context, "getifaddrs: %s", strerror(ret)); + return (ret); + } + + memset(&sa_zero, 0, sizeof(sa_zero)); + + /* First, count all the ifaddrs. */ + for (ifa = ifa0, num = 0; ifa != NULL; ifa = ifa->ifa_next, num++) + /* nothing */; + + if (num == 0) { + freeifaddrs(ifa0); + krb5_set_error_string(context, "no addresses found"); + return (ENXIO); + } + + if (flags & EXTRA_ADDRESSES) { + /* we'll remove the addresses we don't care about */ + ret = krb5_get_ignore_addresses(context, &ignore_addresses); + if(ret) + return ret; + } + + /* Allocate storage for them. */ + res->val = calloc(num, sizeof(*res->val)); + if (res->val == NULL) { + krb5_free_addresses(context, &ignore_addresses); + freeifaddrs(ifa0); + krb5_set_error_string (context, "malloc: out of memory"); + return (ENOMEM); + } + + /* Now traverse the list. */ + for (ifa = ifa0, idx = 0; ifa != NULL; ifa = ifa->ifa_next) { + if ((ifa->ifa_flags & IFF_UP) == 0) + continue; + if (ifa->ifa_addr == NULL) + continue; + if (memcmp(ifa->ifa_addr, &sa_zero, sizeof(sa_zero)) == 0) + continue; + if (krb5_sockaddr_uninteresting(ifa->ifa_addr)) + continue; + if ((ifa->ifa_flags & IFF_LOOPBACK) != 0) { + /* We'll deal with the LOOP_IF_NONE case later. */ + if ((flags & LOOP) == 0) + continue; + } + + ret = krb5_sockaddr2address(context, ifa->ifa_addr, &res->val[idx]); + if (ret) { + /* + * The most likely error here is going to be "Program + * lacks support for address type". This is no big + * deal -- just continue, and we'll listen on the + * addresses who's type we *do* support. + */ + continue; + } + /* possibly skip this address? */ + if((flags & EXTRA_ADDRESSES) && + krb5_address_search(context, &res->val[idx], &ignore_addresses)) { + krb5_free_address(context, &res->val[idx]); + flags &= ~LOOP_IF_NONE; /* we actually found an address, + so don't add any loop-back + addresses */ + continue; + } + + idx++; + } + + /* + * If no addresses were found, and LOOP_IF_NONE is set, then find + * the loopback addresses and add them to our list. + */ + if ((flags & LOOP_IF_NONE) != 0 && idx == 0) { + for (ifa = ifa0; ifa != NULL; ifa = ifa->ifa_next) { + if ((ifa->ifa_flags & IFF_UP) == 0) + continue; + if (ifa->ifa_addr == NULL) + continue; + if (memcmp(ifa->ifa_addr, &sa_zero, sizeof(sa_zero)) == 0) + continue; + if (krb5_sockaddr_uninteresting(ifa->ifa_addr)) + continue; + + if ((ifa->ifa_flags & IFF_LOOPBACK) != 0) { + ret = krb5_sockaddr2address(context, + ifa->ifa_addr, &res->val[idx]); + if (ret) { + /* + * See comment above. + */ + continue; + } + if((flags & EXTRA_ADDRESSES) && + krb5_address_search(context, &res->val[idx], + &ignore_addresses)) { + krb5_free_address(context, &res->val[idx]); + continue; + } + idx++; + } + } + } + + if (flags & EXTRA_ADDRESSES) + krb5_free_addresses(context, &ignore_addresses); + freeifaddrs(ifa0); + if (ret) + free(res->val); + else + res->len = idx; /* Now a count. */ + return (ret); +} + +static krb5_error_code +get_addrs_int (krb5_context context, krb5_addresses *res, int flags) +{ + krb5_error_code ret = -1; + + if (flags & SCAN_INTERFACES) { + ret = find_all_addresses (context, res, flags); + if(ret || res->len == 0) + ret = gethostname_fallback (context, res); + } else { + res->len = 0; + res->val = NULL; + ret = 0; + } + + if(ret == 0 && (flags & EXTRA_ADDRESSES)) { + krb5_addresses a; + /* append user specified addresses */ + ret = krb5_get_extra_addresses(context, &a); + if(ret) { + krb5_free_addresses(context, res); + return ret; + } + ret = krb5_append_addresses(context, res, &a); + if(ret) { + krb5_free_addresses(context, res); + return ret; + } + krb5_free_addresses(context, &a); + } + if(res->len == 0) { + free(res->val); + res->val = NULL; + } + return ret; +} + +/* + * Try to get all addresses, but return the one corresponding to + * `hostname' if we fail. + * + * Only include loopback address if there are no other. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_all_client_addrs (krb5_context context, krb5_addresses *res) +{ + int flags = LOOP_IF_NONE | EXTRA_ADDRESSES; + + if (context->scan_interfaces) + flags |= SCAN_INTERFACES; + + return get_addrs_int (context, res, flags); +} + +/* + * Try to get all local addresses that a server should listen to. + * If that fails, we return the address corresponding to `hostname'. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_all_server_addrs (krb5_context context, krb5_addresses *res) +{ + return get_addrs_int (context, res, LOOP | SCAN_INTERFACES); +} diff --git a/lib/krb5/get_cred.c b/lib/krb5/get_cred.c new file mode 100644 index 0000000..ce0ec6d --- /dev/null +++ b/lib/krb5/get_cred.c @@ -0,0 +1,1277 @@ +/* + * Copyright (c) 1997 - 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <krb5_locl.h> + +RCSID("$Id: get_cred.c 21668 2007-07-22 11:28:05Z lha $"); + +/* + * Take the `body' and encode it into `padata' using the credentials + * in `creds'. + */ + +static krb5_error_code +make_pa_tgs_req(krb5_context context, + krb5_auth_context ac, + KDC_REQ_BODY *body, + PA_DATA *padata, + krb5_creds *creds, + krb5_key_usage usage) +{ + u_char *buf; + size_t buf_size; + size_t len; + krb5_data in_data; + krb5_error_code ret; + + ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, body, &len, ret); + if (ret) + goto out; + if(buf_size != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + + in_data.length = len; + in_data.data = buf; + ret = _krb5_mk_req_internal(context, &ac, 0, &in_data, creds, + &padata->padata_value, + KRB5_KU_TGS_REQ_AUTH_CKSUM, + usage + /* KRB5_KU_TGS_REQ_AUTH */); + out: + free (buf); + if(ret) + return ret; + padata->padata_type = KRB5_PADATA_TGS_REQ; + return 0; +} + +/* + * Set the `enc-authorization-data' in `req_body' based on `authdata' + */ + +static krb5_error_code +set_auth_data (krb5_context context, + KDC_REQ_BODY *req_body, + krb5_authdata *authdata, + krb5_keyblock *key) +{ + if(authdata->len) { + size_t len, buf_size; + unsigned char *buf; + krb5_crypto crypto; + krb5_error_code ret; + + ASN1_MALLOC_ENCODE(AuthorizationData, buf, buf_size, authdata, + &len, ret); + if (ret) + return ret; + if (buf_size != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + + ALLOC(req_body->enc_authorization_data, 1); + if (req_body->enc_authorization_data == NULL) { + free (buf); + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + ret = krb5_crypto_init(context, key, 0, &crypto); + if (ret) { + free (buf); + free (req_body->enc_authorization_data); + req_body->enc_authorization_data = NULL; + return ret; + } + krb5_encrypt_EncryptedData(context, + crypto, + KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY, + /* KRB5_KU_TGS_REQ_AUTH_DAT_SESSION? */ + buf, + len, + 0, + req_body->enc_authorization_data); + free (buf); + krb5_crypto_destroy(context, crypto); + } else { + req_body->enc_authorization_data = NULL; + } + return 0; +} + +/* + * Create a tgs-req in `t' with `addresses', `flags', `second_ticket' + * (if not-NULL), `in_creds', `krbtgt', and returning the generated + * subkey in `subkey'. + */ + +static krb5_error_code +init_tgs_req (krb5_context context, + krb5_ccache ccache, + krb5_addresses *addresses, + krb5_kdc_flags flags, + Ticket *second_ticket, + krb5_creds *in_creds, + krb5_creds *krbtgt, + unsigned nonce, + const METHOD_DATA *padata, + krb5_keyblock **subkey, + TGS_REQ *t, + krb5_key_usage usage) +{ + krb5_error_code ret = 0; + + memset(t, 0, sizeof(*t)); + t->pvno = 5; + t->msg_type = krb_tgs_req; + if (in_creds->session.keytype) { + ALLOC_SEQ(&t->req_body.etype, 1); + if(t->req_body.etype.val == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto fail; + } + t->req_body.etype.val[0] = in_creds->session.keytype; + } else { + ret = krb5_init_etype(context, + &t->req_body.etype.len, + &t->req_body.etype.val, + NULL); + } + if (ret) + goto fail; + t->req_body.addresses = addresses; + t->req_body.kdc_options = flags.b; + ret = copy_Realm(&in_creds->server->realm, &t->req_body.realm); + if (ret) + goto fail; + ALLOC(t->req_body.sname, 1); + if (t->req_body.sname == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto fail; + } + + /* some versions of some code might require that the client be + present in TGS-REQs, but this is clearly against the spec */ + + ret = copy_PrincipalName(&in_creds->server->name, t->req_body.sname); + if (ret) + goto fail; + + /* req_body.till should be NULL if there is no endtime specified, + but old MIT code (like DCE secd) doesn't like that */ + ALLOC(t->req_body.till, 1); + if(t->req_body.till == NULL){ + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto fail; + } + *t->req_body.till = in_creds->times.endtime; + + t->req_body.nonce = nonce; + if(second_ticket){ + ALLOC(t->req_body.additional_tickets, 1); + if (t->req_body.additional_tickets == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto fail; + } + ALLOC_SEQ(t->req_body.additional_tickets, 1); + if (t->req_body.additional_tickets->val == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto fail; + } + ret = copy_Ticket(second_ticket, t->req_body.additional_tickets->val); + if (ret) + goto fail; + } + ALLOC(t->padata, 1); + if (t->padata == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto fail; + } + ALLOC_SEQ(t->padata, 1 + padata->len); + if (t->padata->val == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto fail; + } + { + int i; + for (i = 0; i < padata->len; i++) { + ret = copy_PA_DATA(&padata->val[i], &t->padata->val[i + 1]); + if (ret) { + krb5_set_error_string(context, "malloc: out of memory"); + goto fail; + } + } + } + + { + krb5_auth_context ac; + krb5_keyblock *key = NULL; + + ret = krb5_auth_con_init(context, &ac); + if(ret) + goto fail; + + if (krb5_config_get_bool_default(context, NULL, FALSE, + "realms", + krbtgt->server->realm, + "tgs_require_subkey", + NULL)) + { + ret = krb5_generate_subkey (context, &krbtgt->session, &key); + if (ret) { + krb5_auth_con_free (context, ac); + goto fail; + } + + ret = krb5_auth_con_setlocalsubkey(context, ac, key); + if (ret) { + if (key) + krb5_free_keyblock (context, key); + krb5_auth_con_free (context, ac); + goto fail; + } + } + + ret = set_auth_data (context, &t->req_body, &in_creds->authdata, + key ? key : &krbtgt->session); + if (ret) { + if (key) + krb5_free_keyblock (context, key); + krb5_auth_con_free (context, ac); + goto fail; + } + + ret = make_pa_tgs_req(context, + ac, + &t->req_body, + &t->padata->val[0], + krbtgt, + usage); + if(ret) { + if (key) + krb5_free_keyblock (context, key); + krb5_auth_con_free(context, ac); + goto fail; + } + *subkey = key; + + krb5_auth_con_free(context, ac); + } +fail: + if (ret) { + t->req_body.addresses = NULL; + free_TGS_REQ (t); + } + return ret; +} + +krb5_error_code +_krb5_get_krbtgt(krb5_context context, + krb5_ccache id, + krb5_realm realm, + krb5_creds **cred) +{ + krb5_error_code ret; + krb5_creds tmp_cred; + + memset(&tmp_cred, 0, sizeof(tmp_cred)); + + ret = krb5_cc_get_principal(context, id, &tmp_cred.client); + if (ret) + return ret; + + ret = krb5_make_principal(context, + &tmp_cred.server, + realm, + KRB5_TGS_NAME, + realm, + NULL); + if(ret) { + krb5_free_principal(context, tmp_cred.client); + return ret; + } + ret = krb5_get_credentials(context, + KRB5_GC_CACHED, + id, + &tmp_cred, + cred); + krb5_free_principal(context, tmp_cred.client); + krb5_free_principal(context, tmp_cred.server); + if(ret) + return ret; + return 0; +} + +/* DCE compatible decrypt proc */ +static krb5_error_code +decrypt_tkt_with_subkey (krb5_context context, + krb5_keyblock *key, + krb5_key_usage usage, + krb5_const_pointer subkey, + krb5_kdc_rep *dec_rep) +{ + krb5_error_code ret; + krb5_data data; + size_t size; + krb5_crypto crypto; + + ret = krb5_crypto_init(context, key, 0, &crypto); + if (ret) + return ret; + ret = krb5_decrypt_EncryptedData (context, + crypto, + usage, + &dec_rep->kdc_rep.enc_part, + &data); + krb5_crypto_destroy(context, crypto); + if(ret && subkey){ + /* DCE compat -- try to decrypt with subkey */ + ret = krb5_crypto_init(context, subkey, 0, &crypto); + if (ret) + return ret; + ret = krb5_decrypt_EncryptedData (context, + crypto, + KRB5_KU_TGS_REP_ENC_PART_SUB_KEY, + &dec_rep->kdc_rep.enc_part, + &data); + krb5_crypto_destroy(context, crypto); + } + if (ret) + return ret; + + ret = krb5_decode_EncASRepPart(context, + data.data, + data.length, + &dec_rep->enc_part, + &size); + if (ret) + ret = krb5_decode_EncTGSRepPart(context, + data.data, + data.length, + &dec_rep->enc_part, + &size); + krb5_data_free (&data); + return ret; +} + +static krb5_error_code +get_cred_kdc_usage(krb5_context context, + krb5_ccache id, + krb5_kdc_flags flags, + krb5_addresses *addresses, + krb5_creds *in_creds, + krb5_creds *krbtgt, + krb5_principal impersonate_principal, + Ticket *second_ticket, + krb5_creds *out_creds, + krb5_key_usage usage) +{ + TGS_REQ req; + krb5_data enc; + krb5_data resp; + krb5_kdc_rep rep; + KRB_ERROR error; + krb5_error_code ret; + unsigned nonce; + krb5_keyblock *subkey = NULL; + size_t len; + Ticket second_ticket_data; + METHOD_DATA padata; + + krb5_data_zero(&resp); + krb5_data_zero(&enc); + padata.val = NULL; + padata.len = 0; + + krb5_generate_random_block(&nonce, sizeof(nonce)); + nonce &= 0xffffffff; + + if(flags.b.enc_tkt_in_skey && second_ticket == NULL){ + ret = decode_Ticket(in_creds->second_ticket.data, + in_creds->second_ticket.length, + &second_ticket_data, &len); + if(ret) + return ret; + second_ticket = &second_ticket_data; + } + + + if (impersonate_principal) { + krb5_crypto crypto; + PA_S4U2Self self; + krb5_data data; + void *buf; + size_t size; + + self.name = impersonate_principal->name; + self.realm = impersonate_principal->realm; + self.auth = estrdup("Kerberos"); + + ret = _krb5_s4u2self_to_checksumdata(context, &self, &data); + if (ret) { + free(self.auth); + goto out; + } + + ret = krb5_crypto_init(context, &krbtgt->session, 0, &crypto); + if (ret) { + free(self.auth); + krb5_data_free(&data); + goto out; + } + + ret = krb5_create_checksum(context, + crypto, + KRB5_KU_OTHER_CKSUM, + 0, + data.data, + data.length, + &self.cksum); + krb5_crypto_destroy(context, crypto); + krb5_data_free(&data); + if (ret) { + free(self.auth); + goto out; + } + + ASN1_MALLOC_ENCODE(PA_S4U2Self, buf, len, &self, &size, ret); + free(self.auth); + free_Checksum(&self.cksum); + if (ret) + goto out; + if (len != size) + krb5_abortx(context, "internal asn1 error"); + + ret = krb5_padata_add(context, &padata, KRB5_PADATA_S4U2SELF, buf, len); + if (ret) + goto out; + } + + ret = init_tgs_req (context, + id, + addresses, + flags, + second_ticket, + in_creds, + krbtgt, + nonce, + &padata, + &subkey, + &req, + usage); + if (ret) + goto out; + + ASN1_MALLOC_ENCODE(TGS_REQ, enc.data, enc.length, &req, &len, ret); + if (ret) + goto out; + if(enc.length != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + + /* don't free addresses */ + req.req_body.addresses = NULL; + free_TGS_REQ(&req); + + /* + * Send and receive + */ + { + krb5_sendto_ctx stctx; + ret = krb5_sendto_ctx_alloc(context, &stctx); + if (ret) + return ret; + krb5_sendto_ctx_set_func(stctx, _krb5_kdc_retry, NULL); + + ret = krb5_sendto_context (context, stctx, &enc, + krbtgt->server->name.name_string.val[1], + &resp); + krb5_sendto_ctx_free(context, stctx); + } + if(ret) + goto out; + + memset(&rep, 0, sizeof(rep)); + if(decode_TGS_REP(resp.data, resp.length, &rep.kdc_rep, &len) == 0){ + ret = krb5_copy_principal(context, + in_creds->client, + &out_creds->client); + if(ret) + goto out; + ret = krb5_copy_principal(context, + in_creds->server, + &out_creds->server); + if(ret) + goto out; + /* this should go someplace else */ + out_creds->times.endtime = in_creds->times.endtime; + + ret = _krb5_extract_ticket(context, + &rep, + out_creds, + &krbtgt->session, + NULL, + KRB5_KU_TGS_REP_ENC_PART_SESSION, + &krbtgt->addresses, + nonce, + EXTRACT_TICKET_ALLOW_CNAME_MISMATCH| + EXTRACT_TICKET_ALLOW_SERVER_MISMATCH, + decrypt_tkt_with_subkey, + subkey); + krb5_free_kdc_rep(context, &rep); + } else if(krb5_rd_error(context, &resp, &error) == 0) { + ret = krb5_error_from_rd_error(context, &error, in_creds); + krb5_free_error_contents(context, &error); + } else if(resp.data && ((char*)resp.data)[0] == 4) { + ret = KRB5KRB_AP_ERR_V4_REPLY; + krb5_clear_error_string(context); + } else { + ret = KRB5KRB_AP_ERR_MSG_TYPE; + krb5_clear_error_string(context); + } + +out: + if (second_ticket == &second_ticket_data) + free_Ticket(&second_ticket_data); + free_METHOD_DATA(&padata); + krb5_data_free(&resp); + krb5_data_free(&enc); + if(subkey){ + krb5_free_keyblock_contents(context, subkey); + free(subkey); + } + return ret; + +} + +static krb5_error_code +get_cred_kdc(krb5_context context, + krb5_ccache id, + krb5_kdc_flags flags, + krb5_addresses *addresses, + krb5_creds *in_creds, + krb5_creds *krbtgt, + krb5_principal impersonate_principal, + Ticket *second_ticket, + krb5_creds *out_creds) +{ + krb5_error_code ret; + + ret = get_cred_kdc_usage(context, id, flags, addresses, in_creds, + krbtgt, impersonate_principal, second_ticket, + out_creds, KRB5_KU_TGS_REQ_AUTH); + if (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY) { + krb5_clear_error_string (context); + ret = get_cred_kdc_usage(context, id, flags, addresses, in_creds, + krbtgt, impersonate_principal, second_ticket, + out_creds, KRB5_KU_AP_REQ_AUTH); + } + return ret; +} + +/* same as above, just get local addresses first */ + +static krb5_error_code +get_cred_kdc_la(krb5_context context, krb5_ccache id, krb5_kdc_flags flags, + krb5_creds *in_creds, krb5_creds *krbtgt, + krb5_principal impersonate_principal, Ticket *second_ticket, + krb5_creds *out_creds) +{ + krb5_error_code ret; + krb5_addresses addresses, *addrs = &addresses; + + krb5_get_all_client_addrs(context, &addresses); + /* XXX this sucks. */ + if(addresses.len == 0) + addrs = NULL; + ret = get_cred_kdc(context, id, flags, addrs, + in_creds, krbtgt, impersonate_principal, second_ticket, + out_creds); + krb5_free_addresses(context, &addresses); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_kdc_cred(krb5_context context, + krb5_ccache id, + krb5_kdc_flags flags, + krb5_addresses *addresses, + Ticket *second_ticket, + krb5_creds *in_creds, + krb5_creds **out_creds + ) +{ + krb5_error_code ret; + krb5_creds *krbtgt; + + *out_creds = calloc(1, sizeof(**out_creds)); + if(*out_creds == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + ret = _krb5_get_krbtgt (context, + id, + in_creds->server->realm, + &krbtgt); + if(ret) { + free(*out_creds); + return ret; + } + ret = get_cred_kdc(context, id, flags, addresses, + in_creds, krbtgt, NULL, NULL, *out_creds); + krb5_free_creds (context, krbtgt); + if(ret) + free(*out_creds); + return ret; +} + +static void +not_found(krb5_context context, krb5_const_principal p) +{ + krb5_error_code ret; + char *str; + + ret = krb5_unparse_name(context, p, &str); + if(ret) { + krb5_clear_error_string(context); + return; + } + krb5_set_error_string(context, "Matching credential (%s) not found", str); + free(str); +} + +static krb5_error_code +find_cred(krb5_context context, + krb5_ccache id, + krb5_principal server, + krb5_creds **tgts, + krb5_creds *out_creds) +{ + krb5_error_code ret; + krb5_creds mcreds; + + krb5_cc_clear_mcred(&mcreds); + mcreds.server = server; + ret = krb5_cc_retrieve_cred(context, id, KRB5_TC_DONT_MATCH_REALM, + &mcreds, out_creds); + if(ret == 0) + return 0; + while(tgts && *tgts){ + if(krb5_compare_creds(context, KRB5_TC_DONT_MATCH_REALM, + &mcreds, *tgts)){ + ret = krb5_copy_creds_contents(context, *tgts, out_creds); + return ret; + } + tgts++; + } + not_found(context, server); + return KRB5_CC_NOTFOUND; +} + +static krb5_error_code +add_cred(krb5_context context, krb5_creds ***tgts, krb5_creds *tkt) +{ + int i; + krb5_error_code ret; + krb5_creds **tmp = *tgts; + + for(i = 0; tmp && tmp[i]; i++); /* XXX */ + tmp = realloc(tmp, (i+2)*sizeof(*tmp)); + if(tmp == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + *tgts = tmp; + ret = krb5_copy_creds(context, tkt, &tmp[i]); + tmp[i+1] = NULL; + return ret; +} + +/* +get_cred(server) + creds = cc_get_cred(server) + if(creds) return creds + tgt = cc_get_cred(krbtgt/server_realm@any_realm) + if(tgt) + return get_cred_tgt(server, tgt) + if(client_realm == server_realm) + return NULL + tgt = get_cred(krbtgt/server_realm@client_realm) + while(tgt_inst != server_realm) + tgt = get_cred(krbtgt/server_realm@tgt_inst) + return get_cred_tgt(server, tgt) + */ + +static krb5_error_code +get_cred_from_kdc_flags(krb5_context context, + krb5_kdc_flags flags, + krb5_ccache ccache, + krb5_creds *in_creds, + krb5_principal impersonate_principal, + Ticket *second_ticket, + krb5_creds **out_creds, + krb5_creds ***ret_tgts) +{ + krb5_error_code ret; + krb5_creds *tgt, tmp_creds; + krb5_const_realm client_realm, server_realm, try_realm; + + *out_creds = NULL; + + client_realm = krb5_principal_get_realm(context, in_creds->client); + server_realm = krb5_principal_get_realm(context, in_creds->server); + memset(&tmp_creds, 0, sizeof(tmp_creds)); + ret = krb5_copy_principal(context, in_creds->client, &tmp_creds.client); + if(ret) + return ret; + + try_realm = krb5_config_get_string(context, NULL, "capaths", + client_realm, server_realm, NULL); + +#if 1 + /* XXX remove in future release */ + if(try_realm == NULL) + try_realm = krb5_config_get_string(context, NULL, "libdefaults", + "capath", server_realm, NULL); +#endif + + if (try_realm == NULL) + try_realm = client_realm; + + ret = krb5_make_principal(context, + &tmp_creds.server, + try_realm, + KRB5_TGS_NAME, + server_realm, + NULL); + if(ret){ + krb5_free_principal(context, tmp_creds.client); + return ret; + } + { + krb5_creds tgts; + /* XXX try krb5_cc_retrieve_cred first? */ + ret = find_cred(context, ccache, tmp_creds.server, + *ret_tgts, &tgts); + if(ret == 0){ + *out_creds = calloc(1, sizeof(**out_creds)); + if(*out_creds == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + ret = ENOMEM; + } else { + krb5_boolean noaddr; + + krb5_appdefault_boolean(context, NULL, tgts.server->realm, + "no-addresses", FALSE, &noaddr); + + if (noaddr) + ret = get_cred_kdc(context, ccache, flags, NULL, + in_creds, &tgts, + impersonate_principal, + second_ticket, + *out_creds); + else + ret = get_cred_kdc_la(context, ccache, flags, + in_creds, &tgts, + impersonate_principal, + second_ticket, + *out_creds); + if (ret) { + free (*out_creds); + *out_creds = NULL; + } + } + krb5_free_cred_contents(context, &tgts); + krb5_free_principal(context, tmp_creds.server); + krb5_free_principal(context, tmp_creds.client); + return ret; + } + } + if(krb5_realm_compare(context, in_creds->client, in_creds->server)) { + not_found(context, in_creds->server); + return KRB5_CC_NOTFOUND; + } + /* XXX this can loop forever */ + while(1){ + heim_general_string tgt_inst; + + ret = get_cred_from_kdc_flags(context, flags, ccache, &tmp_creds, + NULL, NULL, &tgt, ret_tgts); + if(ret) { + krb5_free_principal(context, tmp_creds.server); + krb5_free_principal(context, tmp_creds.client); + return ret; + } + ret = add_cred(context, ret_tgts, tgt); + if(ret) { + krb5_free_principal(context, tmp_creds.server); + krb5_free_principal(context, tmp_creds.client); + return ret; + } + tgt_inst = tgt->server->name.name_string.val[1]; + if(strcmp(tgt_inst, server_realm) == 0) + break; + krb5_free_principal(context, tmp_creds.server); + ret = krb5_make_principal(context, &tmp_creds.server, + tgt_inst, KRB5_TGS_NAME, server_realm, NULL); + if(ret) { + krb5_free_principal(context, tmp_creds.server); + krb5_free_principal(context, tmp_creds.client); + return ret; + } + ret = krb5_free_creds(context, tgt); + if(ret) { + krb5_free_principal(context, tmp_creds.server); + krb5_free_principal(context, tmp_creds.client); + return ret; + } + } + + krb5_free_principal(context, tmp_creds.server); + krb5_free_principal(context, tmp_creds.client); + *out_creds = calloc(1, sizeof(**out_creds)); + if(*out_creds == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + ret = ENOMEM; + } else { + krb5_boolean noaddr; + + krb5_appdefault_boolean(context, NULL, tgt->server->realm, + "no-addresses", KRB5_ADDRESSLESS_DEFAULT, + &noaddr); + if (noaddr) + ret = get_cred_kdc (context, ccache, flags, NULL, + in_creds, tgt, NULL, NULL, + *out_creds); + else + ret = get_cred_kdc_la(context, ccache, flags, + in_creds, tgt, NULL, NULL, + *out_creds); + if (ret) { + free (*out_creds); + *out_creds = NULL; + } + } + krb5_free_creds(context, tgt); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_cred_from_kdc_opt(krb5_context context, + krb5_ccache ccache, + krb5_creds *in_creds, + krb5_creds **out_creds, + krb5_creds ***ret_tgts, + krb5_flags flags) +{ + krb5_kdc_flags f; + f.i = flags; + return get_cred_from_kdc_flags(context, f, ccache, + in_creds, NULL, NULL, + out_creds, ret_tgts); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_cred_from_kdc(krb5_context context, + krb5_ccache ccache, + krb5_creds *in_creds, + krb5_creds **out_creds, + krb5_creds ***ret_tgts) +{ + return krb5_get_cred_from_kdc_opt(context, ccache, + in_creds, out_creds, ret_tgts, 0); +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_credentials_with_flags(krb5_context context, + krb5_flags options, + krb5_kdc_flags flags, + krb5_ccache ccache, + krb5_creds *in_creds, + krb5_creds **out_creds) +{ + krb5_error_code ret; + krb5_creds **tgts; + krb5_creds *res_creds; + int i; + + *out_creds = NULL; + res_creds = calloc(1, sizeof(*res_creds)); + if (res_creds == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + if (in_creds->session.keytype) + options |= KRB5_TC_MATCH_KEYTYPE; + + /* + * If we got a credential, check if credential is expired before + * returning it. + */ + ret = krb5_cc_retrieve_cred(context, + ccache, + in_creds->session.keytype ? + KRB5_TC_MATCH_KEYTYPE : 0, + in_creds, res_creds); + /* + * If we got a credential, check if credential is expired before + * returning it, but only if KRB5_GC_EXPIRED_OK is not set. + */ + if (ret == 0) { + krb5_timestamp timeret; + + /* If expired ok, don't bother checking */ + if(options & KRB5_GC_EXPIRED_OK) { + *out_creds = res_creds; + return 0; + } + + krb5_timeofday(context, &timeret); + if(res_creds->times.endtime > timeret) { + *out_creds = res_creds; + return 0; + } + if(options & KRB5_GC_CACHED) + krb5_cc_remove_cred(context, ccache, 0, res_creds); + + } else if(ret != KRB5_CC_END) { + free(res_creds); + return ret; + } + free(res_creds); + if(options & KRB5_GC_CACHED) { + not_found(context, in_creds->server); + return KRB5_CC_NOTFOUND; + } + if(options & KRB5_GC_USER_USER) + flags.b.enc_tkt_in_skey = 1; + if (flags.b.enc_tkt_in_skey) + options |= KRB5_GC_NO_STORE; + + tgts = NULL; + ret = get_cred_from_kdc_flags(context, flags, ccache, + in_creds, NULL, NULL, out_creds, &tgts); + for(i = 0; tgts && tgts[i]; i++) { + krb5_cc_store_cred(context, ccache, tgts[i]); + krb5_free_creds(context, tgts[i]); + } + free(tgts); + if(ret == 0 && (options & KRB5_GC_NO_STORE) == 0) + krb5_cc_store_cred(context, ccache, *out_creds); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_credentials(krb5_context context, + krb5_flags options, + krb5_ccache ccache, + krb5_creds *in_creds, + krb5_creds **out_creds) +{ + krb5_kdc_flags flags; + flags.i = 0; + return krb5_get_credentials_with_flags(context, options, flags, + ccache, in_creds, out_creds); +} + +struct krb5_get_creds_opt_data { + krb5_principal self; + krb5_flags options; + krb5_enctype enctype; + Ticket *ticket; +}; + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_creds_opt_alloc(krb5_context context, krb5_get_creds_opt *opt) +{ + *opt = calloc(1, sizeof(**opt)); + if (*opt == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + return 0; +} + +void KRB5_LIB_FUNCTION +krb5_get_creds_opt_free(krb5_context context, krb5_get_creds_opt opt) +{ + if (opt->self) + krb5_free_principal(context, opt->self); + memset(opt, 0, sizeof(*opt)); + free(opt); +} + +void KRB5_LIB_FUNCTION +krb5_get_creds_opt_set_options(krb5_context context, + krb5_get_creds_opt opt, + krb5_flags options) +{ + opt->options = options; +} + +void KRB5_LIB_FUNCTION +krb5_get_creds_opt_add_options(krb5_context context, + krb5_get_creds_opt opt, + krb5_flags options) +{ + opt->options |= options; +} + +void KRB5_LIB_FUNCTION +krb5_get_creds_opt_set_enctype(krb5_context context, + krb5_get_creds_opt opt, + krb5_enctype enctype) +{ + opt->enctype = enctype; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_creds_opt_set_impersonate(krb5_context context, + krb5_get_creds_opt opt, + krb5_const_principal self) +{ + if (opt->self) + krb5_free_principal(context, opt->self); + return krb5_copy_principal(context, self, &opt->self); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_creds_opt_set_ticket(krb5_context context, + krb5_get_creds_opt opt, + const Ticket *ticket) +{ + if (opt->ticket) { + free_Ticket(opt->ticket); + free(opt->ticket); + opt->ticket = NULL; + } + if (ticket) { + krb5_error_code ret; + + opt->ticket = malloc(sizeof(*ticket)); + if (opt->ticket == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + ret = copy_Ticket(ticket, opt->ticket); + if (ret) { + free(opt->ticket); + opt->ticket = NULL; + krb5_set_error_string(context, "malloc: out of memory"); + return ret; + } + } + return 0; +} + + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_creds(krb5_context context, + krb5_get_creds_opt opt, + krb5_ccache ccache, + krb5_const_principal inprinc, + krb5_creds **out_creds) +{ + krb5_kdc_flags flags; + krb5_flags options; + krb5_creds in_creds; + krb5_error_code ret; + krb5_creds **tgts; + krb5_creds *res_creds; + int i; + + memset(&in_creds, 0, sizeof(in_creds)); + in_creds.server = rk_UNCONST(inprinc); + + ret = krb5_cc_get_principal(context, ccache, &in_creds.client); + if (ret) + return ret; + + options = opt->options; + flags.i = 0; + + *out_creds = NULL; + res_creds = calloc(1, sizeof(*res_creds)); + if (res_creds == NULL) { + krb5_free_principal(context, in_creds.client); + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + if (opt->enctype) { + in_creds.session.keytype = opt->enctype; + options |= KRB5_TC_MATCH_KEYTYPE; + } + + /* + * If we got a credential, check if credential is expired before + * returning it. + */ + ret = krb5_cc_retrieve_cred(context, + ccache, + opt->enctype ? KRB5_TC_MATCH_KEYTYPE : 0, + &in_creds, res_creds); + /* + * If we got a credential, check if credential is expired before + * returning it, but only if KRB5_GC_EXPIRED_OK is not set. + */ + if (ret == 0) { + krb5_timestamp timeret; + + /* If expired ok, don't bother checking */ + if(options & KRB5_GC_EXPIRED_OK) { + *out_creds = res_creds; + krb5_free_principal(context, in_creds.client); + return 0; + } + + krb5_timeofday(context, &timeret); + if(res_creds->times.endtime > timeret) { + *out_creds = res_creds; + krb5_free_principal(context, in_creds.client); + return 0; + } + if(options & KRB5_GC_CACHED) + krb5_cc_remove_cred(context, ccache, 0, res_creds); + + } else if(ret != KRB5_CC_END) { + free(res_creds); + krb5_free_principal(context, in_creds.client); + return ret; + } + free(res_creds); + if(options & KRB5_GC_CACHED) { + not_found(context, in_creds.server); + krb5_free_principal(context, in_creds.client); + return KRB5_CC_NOTFOUND; + } + if(options & KRB5_GC_USER_USER) { + flags.b.enc_tkt_in_skey = 1; + options |= KRB5_GC_NO_STORE; + } + if (options & KRB5_GC_FORWARDABLE) + flags.b.forwardable = 1; + if (options & KRB5_GC_NO_TRANSIT_CHECK) + flags.b.disable_transited_check = 1; + if (options & KRB5_GC_CONSTRAINED_DELEGATION) { + flags.b.request_anonymous = 1; /* XXX ARGH confusion */ + flags.b.constrained_delegation = 1; + } + + tgts = NULL; + ret = get_cred_from_kdc_flags(context, flags, ccache, + &in_creds, opt->self, opt->ticket, + out_creds, &tgts); + krb5_free_principal(context, in_creds.client); + for(i = 0; tgts && tgts[i]; i++) { + krb5_cc_store_cred(context, ccache, tgts[i]); + krb5_free_creds(context, tgts[i]); + } + free(tgts); + if(ret == 0 && (options & KRB5_GC_NO_STORE) == 0) + krb5_cc_store_cred(context, ccache, *out_creds); + return ret; +} + +/* + * + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_renewed_creds(krb5_context context, + krb5_creds *creds, + krb5_const_principal client, + krb5_ccache ccache, + const char *in_tkt_service) +{ + krb5_error_code ret; + krb5_kdc_flags flags; + krb5_creds in, *template, *out = NULL; + + memset(&in, 0, sizeof(in)); + memset(creds, 0, sizeof(*creds)); + + ret = krb5_copy_principal(context, client, &in.client); + if (ret) + return ret; + + if (in_tkt_service) { + ret = krb5_parse_name(context, in_tkt_service, &in.server); + if (ret) { + krb5_free_principal(context, in.client); + return ret; + } + } else { + const char *realm = krb5_principal_get_realm(context, client); + + ret = krb5_make_principal(context, &in.server, realm, KRB5_TGS_NAME, + realm, NULL); + if (ret) { + krb5_free_principal(context, in.client); + return ret; + } + } + + flags.i = 0; + flags.b.renewable = flags.b.renew = 1; + + /* + * Get template from old credential cache for the same entry, if + * this failes, no worries. + */ + ret = krb5_get_credentials(context, KRB5_GC_CACHED, ccache, &in, &template); + if (ret == 0) { + flags.b.forwardable = template->flags.b.forwardable; + flags.b.proxiable = template->flags.b.proxiable; + krb5_free_creds (context, template); + } + + ret = krb5_get_kdc_cred(context, ccache, flags, NULL, NULL, &in, &out); + krb5_free_principal(context, in.client); + krb5_free_principal(context, in.server); + if (ret) + return ret; + + ret = krb5_copy_creds_contents(context, out, creds); + krb5_free_creds(context, out); + + return ret; +} diff --git a/lib/krb5/get_default_principal.c b/lib/krb5/get_default_principal.c new file mode 100644 index 0000000..83fb2b0 --- /dev/null +++ b/lib/krb5/get_default_principal.c @@ -0,0 +1,115 @@ +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: get_default_principal.c 14870 2005-04-20 20:53:29Z lha $"); + +/* + * Try to find out what's a reasonable default principal. + */ + +static const char* +get_env_user(void) +{ + const char *user = getenv("USER"); + if(user == NULL) + user = getenv("LOGNAME"); + if(user == NULL) + user = getenv("USERNAME"); + return user; +} + +/* + * Will only use operating-system dependant operation to get the + * default principal, for use of functions that in ccache layer to + * avoid recursive calls. + */ + +krb5_error_code +_krb5_get_default_principal_local (krb5_context context, + krb5_principal *princ) +{ + krb5_error_code ret; + const char *user; + uid_t uid; + + *princ = NULL; + + uid = getuid(); + if(uid == 0) { + user = getlogin(); + if(user == NULL) + user = get_env_user(); + if(user != NULL && strcmp(user, "root") != 0) + ret = krb5_make_principal(context, princ, NULL, user, "root", NULL); + else + ret = krb5_make_principal(context, princ, NULL, "root", NULL); + } else { + struct passwd *pw = getpwuid(uid); + if(pw != NULL) + user = pw->pw_name; + else { + user = get_env_user(); + if(user == NULL) + user = getlogin(); + } + if(user == NULL) { + krb5_set_error_string(context, + "unable to figure out current principal"); + return ENOTTY; /* XXX */ + } + ret = krb5_make_principal(context, princ, NULL, user, NULL); + } + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_default_principal (krb5_context context, + krb5_principal *princ) +{ + krb5_error_code ret; + krb5_ccache id; + + *princ = NULL; + + ret = krb5_cc_default (context, &id); + if (ret == 0) { + ret = krb5_cc_get_principal (context, id, princ); + krb5_cc_close (context, id); + if (ret == 0) + return 0; + } + + return _krb5_get_default_principal_local(context, princ); +} diff --git a/lib/krb5/get_default_realm.c b/lib/krb5/get_default_realm.c new file mode 100644 index 0000000..09c8577 --- /dev/null +++ b/lib/krb5/get_default_realm.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) 1997 - 2001, 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: get_default_realm.c 13863 2004-05-25 21:46:46Z lha $"); + +/* + * Return a NULL-terminated list of default realms in `realms'. + * Free this memory with krb5_free_host_realm. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_default_realms (krb5_context context, + krb5_realm **realms) +{ + if (context->default_realms == NULL) { + krb5_error_code ret = krb5_set_default_realm (context, NULL); + if (ret) + return KRB5_CONFIG_NODEFREALM; + } + + return krb5_copy_host_realm (context, + context->default_realms, + realms); +} + +/* + * Return the first default realm. For compatibility. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_default_realm(krb5_context context, + krb5_realm *realm) +{ + krb5_error_code ret; + char *res; + + if (context->default_realms == NULL + || context->default_realms[0] == NULL) { + krb5_clear_error_string(context); + ret = krb5_set_default_realm (context, NULL); + if (ret) + return ret; + } + + res = strdup (context->default_realms[0]); + if (res == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + *realm = res; + return 0; +} diff --git a/lib/krb5/get_for_creds.c b/lib/krb5/get_for_creds.c new file mode 100644 index 0000000..cb8b7c8 --- /dev/null +++ b/lib/krb5/get_for_creds.c @@ -0,0 +1,460 @@ +/* + * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <krb5_locl.h> + +RCSID("$Id: get_for_creds.c 22504 2008-01-21 15:49:58Z lha $"); + +static krb5_error_code +add_addrs(krb5_context context, + krb5_addresses *addr, + struct addrinfo *ai) +{ + krb5_error_code ret; + unsigned n, i; + void *tmp; + struct addrinfo *a; + + n = 0; + for (a = ai; a != NULL; a = a->ai_next) + ++n; + + tmp = realloc(addr->val, (addr->len + n) * sizeof(*addr->val)); + if (tmp == NULL && (addr->len + n) != 0) { + krb5_set_error_string(context, "malloc: out of memory"); + ret = ENOMEM; + goto fail; + } + addr->val = tmp; + for (i = addr->len; i < (addr->len + n); ++i) { + addr->val[i].addr_type = 0; + krb5_data_zero(&addr->val[i].address); + } + i = addr->len; + for (a = ai; a != NULL; a = a->ai_next) { + krb5_address ad; + + ret = krb5_sockaddr2address (context, a->ai_addr, &ad); + if (ret == 0) { + if (krb5_address_search(context, &ad, addr)) + krb5_free_address(context, &ad); + else + addr->val[i++] = ad; + } + else if (ret == KRB5_PROG_ATYPE_NOSUPP) + krb5_clear_error_string (context); + else + goto fail; + addr->len = i; + } + return 0; +fail: + krb5_free_addresses (context, addr); + return ret; +} + +/** + * Forward credentials for client to host hostname , making them + * forwardable if forwardable, and returning the blob of data to sent + * in out_data. If hostname == NULL, pick it from server. + * + * @param context A kerberos 5 context. + * @param auth_context the auth context with the key to encrypt the out_data. + * @param hostname the host to forward the tickets too. + * @param client the client to delegate from. + * @param server the server to delegate the credential too. + * @param ccache credential cache to use. + * @param forwardable make the forwarded ticket forwabledable. + * @param out_data the resulting credential. + * + * @return Return an error code or 0. + * + * @ingroup krb5_credential + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_fwd_tgt_creds (krb5_context context, + krb5_auth_context auth_context, + const char *hostname, + krb5_principal client, + krb5_principal server, + krb5_ccache ccache, + int forwardable, + krb5_data *out_data) +{ + krb5_flags flags = 0; + krb5_creds creds; + krb5_error_code ret; + krb5_const_realm client_realm; + + flags |= KDC_OPT_FORWARDED; + + if (forwardable) + flags |= KDC_OPT_FORWARDABLE; + + if (hostname == NULL && + krb5_principal_get_type(context, server) == KRB5_NT_SRV_HST) { + const char *inst = krb5_principal_get_comp_string(context, server, 0); + const char *host = krb5_principal_get_comp_string(context, server, 1); + + if (inst != NULL && + strcmp(inst, "host") == 0 && + host != NULL && + krb5_principal_get_comp_string(context, server, 2) == NULL) + hostname = host; + } + + client_realm = krb5_principal_get_realm(context, client); + + memset (&creds, 0, sizeof(creds)); + creds.client = client; + + ret = krb5_build_principal(context, + &creds.server, + strlen(client_realm), + client_realm, + KRB5_TGS_NAME, + client_realm, + NULL); + if (ret) + return ret; + + ret = krb5_get_forwarded_creds (context, + auth_context, + ccache, + flags, + hostname, + &creds, + out_data); + return ret; +} + +/** + * Gets tickets forwarded to hostname. If the tickets that are + * forwarded are address-less, the forwarded tickets will also be + * address-less. + * + * If the ticket have any address, hostname will be used for figure + * out the address to forward the ticket too. This since this might + * use DNS, its insecure and also doesn't represent configured all + * addresses of the host. For example, the host might have two + * adresses, one IPv4 and one IPv6 address where the later is not + * published in DNS. This IPv6 address might be used communications + * and thus the resulting ticket useless. + * + * @param context A kerberos 5 context. + * @param auth_context the auth context with the key to encrypt the out_data. + * @param ccache credential cache to use + * @param flags the flags to control the resulting ticket flags + * @param hostname the host to forward the tickets too. + * @param in_creds the in client and server ticket names. The client + * and server components forwarded to the remote host. + * @param out_data the resulting credential. + * + * @return Return an error code or 0. + * + * @ingroup krb5_credential + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_forwarded_creds (krb5_context context, + krb5_auth_context auth_context, + krb5_ccache ccache, + krb5_flags flags, + const char *hostname, + krb5_creds *in_creds, + krb5_data *out_data) +{ + krb5_error_code ret; + krb5_creds *out_creds; + krb5_addresses addrs, *paddrs; + KRB_CRED cred; + KrbCredInfo *krb_cred_info; + EncKrbCredPart enc_krb_cred_part; + size_t len; + unsigned char *buf; + size_t buf_size; + krb5_kdc_flags kdc_flags; + krb5_crypto crypto; + struct addrinfo *ai; + int save_errno; + krb5_creds *ticket; + + paddrs = NULL; + addrs.len = 0; + addrs.val = NULL; + + ret = krb5_get_credentials(context, 0, ccache, in_creds, &ticket); + if(ret == 0) { + if (ticket->addresses.len) + paddrs = &addrs; + krb5_free_creds (context, ticket); + } else { + krb5_boolean noaddr; + krb5_appdefault_boolean(context, NULL, + krb5_principal_get_realm(context, + in_creds->client), + "no-addresses", KRB5_ADDRESSLESS_DEFAULT, + &noaddr); + if (!noaddr) + paddrs = &addrs; + } + + /* + * If tickets have addresses, get the address of the remote host. + */ + + if (paddrs != NULL) { + + ret = getaddrinfo (hostname, NULL, NULL, &ai); + if (ret) { + save_errno = errno; + krb5_set_error_string(context, "resolving %s: %s", + hostname, gai_strerror(ret)); + return krb5_eai_to_heim_errno(ret, save_errno); + } + + ret = add_addrs (context, &addrs, ai); + freeaddrinfo (ai); + if (ret) + return ret; + } + + kdc_flags.b = int2KDCOptions(flags); + + ret = krb5_get_kdc_cred (context, + ccache, + kdc_flags, + paddrs, + NULL, + in_creds, + &out_creds); + krb5_free_addresses (context, &addrs); + if (ret) + return ret; + + memset (&cred, 0, sizeof(cred)); + cred.pvno = 5; + cred.msg_type = krb_cred; + ALLOC_SEQ(&cred.tickets, 1); + if (cred.tickets.val == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto out2; + } + ret = decode_Ticket(out_creds->ticket.data, + out_creds->ticket.length, + cred.tickets.val, &len); + if (ret) + goto out3; + + memset (&enc_krb_cred_part, 0, sizeof(enc_krb_cred_part)); + ALLOC_SEQ(&enc_krb_cred_part.ticket_info, 1); + if (enc_krb_cred_part.ticket_info.val == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto out4; + } + + if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) { + krb5_timestamp sec; + int32_t usec; + + krb5_us_timeofday (context, &sec, &usec); + + ALLOC(enc_krb_cred_part.timestamp, 1); + if (enc_krb_cred_part.timestamp == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto out4; + } + *enc_krb_cred_part.timestamp = sec; + ALLOC(enc_krb_cred_part.usec, 1); + if (enc_krb_cred_part.usec == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto out4; + } + *enc_krb_cred_part.usec = usec; + } else { + enc_krb_cred_part.timestamp = NULL; + enc_krb_cred_part.usec = NULL; + } + + if (auth_context->local_address && auth_context->local_port && paddrs) { + + ret = krb5_make_addrport (context, + &enc_krb_cred_part.s_address, + auth_context->local_address, + auth_context->local_port); + if (ret) + goto out4; + } + + if (auth_context->remote_address) { + if (auth_context->remote_port) { + krb5_boolean noaddr; + krb5_const_realm srealm; + + srealm = krb5_principal_get_realm(context, out_creds->server); + /* Is this correct, and should we use the paddrs == NULL + trick here as well? Having an address-less ticket may + indicate that we don't know our own global address, but + it does not necessary mean that we don't know the + server's. */ + krb5_appdefault_boolean(context, NULL, srealm, "no-addresses", + FALSE, &noaddr); + if (!noaddr) { + ret = krb5_make_addrport (context, + &enc_krb_cred_part.r_address, + auth_context->remote_address, + auth_context->remote_port); + if (ret) + goto out4; + } + } else { + ALLOC(enc_krb_cred_part.r_address, 1); + if (enc_krb_cred_part.r_address == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto out4; + } + + ret = krb5_copy_address (context, auth_context->remote_address, + enc_krb_cred_part.r_address); + if (ret) + goto out4; + } + } + + /* fill ticket_info.val[0] */ + + enc_krb_cred_part.ticket_info.len = 1; + + krb_cred_info = enc_krb_cred_part.ticket_info.val; + + copy_EncryptionKey (&out_creds->session, &krb_cred_info->key); + ALLOC(krb_cred_info->prealm, 1); + copy_Realm (&out_creds->client->realm, krb_cred_info->prealm); + ALLOC(krb_cred_info->pname, 1); + copy_PrincipalName(&out_creds->client->name, krb_cred_info->pname); + ALLOC(krb_cred_info->flags, 1); + *krb_cred_info->flags = out_creds->flags.b; + ALLOC(krb_cred_info->authtime, 1); + *krb_cred_info->authtime = out_creds->times.authtime; + ALLOC(krb_cred_info->starttime, 1); + *krb_cred_info->starttime = out_creds->times.starttime; + ALLOC(krb_cred_info->endtime, 1); + *krb_cred_info->endtime = out_creds->times.endtime; + ALLOC(krb_cred_info->renew_till, 1); + *krb_cred_info->renew_till = out_creds->times.renew_till; + ALLOC(krb_cred_info->srealm, 1); + copy_Realm (&out_creds->server->realm, krb_cred_info->srealm); + ALLOC(krb_cred_info->sname, 1); + copy_PrincipalName (&out_creds->server->name, krb_cred_info->sname); + ALLOC(krb_cred_info->caddr, 1); + copy_HostAddresses (&out_creds->addresses, krb_cred_info->caddr); + + krb5_free_creds (context, out_creds); + + /* encode EncKrbCredPart */ + + ASN1_MALLOC_ENCODE(EncKrbCredPart, buf, buf_size, + &enc_krb_cred_part, &len, ret); + free_EncKrbCredPart (&enc_krb_cred_part); + if (ret) { + free_KRB_CRED(&cred); + return ret; + } + if(buf_size != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + + /** + * Some older of the MIT gssapi library used clear-text tickets + * (warped inside AP-REQ encryption), use the krb5_auth_context + * flag KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED to support those + * tickets. The session key is used otherwise to encrypt the + * forwarded ticket. + */ + + if (auth_context->flags & KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED) { + cred.enc_part.etype = ENCTYPE_NULL; + cred.enc_part.kvno = NULL; + cred.enc_part.cipher.data = buf; + cred.enc_part.cipher.length = buf_size; + } else { + /* + * Here older versions then 0.7.2 of Heimdal used the local or + * remote subkey. That is wrong, the session key should be + * used. Heimdal 0.7.2 and newer have code to try both in the + * receiving end. + */ + + ret = krb5_crypto_init(context, auth_context->keyblock, 0, &crypto); + if (ret) { + free(buf); + free_KRB_CRED(&cred); + return ret; + } + ret = krb5_encrypt_EncryptedData (context, + crypto, + KRB5_KU_KRB_CRED, + buf, + len, + 0, + &cred.enc_part); + free(buf); + krb5_crypto_destroy(context, crypto); + if (ret) { + free_KRB_CRED(&cred); + return ret; + } + } + + ASN1_MALLOC_ENCODE(KRB_CRED, buf, buf_size, &cred, &len, ret); + free_KRB_CRED (&cred); + if (ret) + return ret; + if(buf_size != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + out_data->length = len; + out_data->data = buf; + return 0; + out4: + free_EncKrbCredPart(&enc_krb_cred_part); + out3: + free_KRB_CRED(&cred); + out2: + krb5_free_creds (context, out_creds); + return ret; +} diff --git a/lib/krb5/get_host_realm.c b/lib/krb5/get_host_realm.c new file mode 100644 index 0000000..d709e4b --- /dev/null +++ b/lib/krb5/get_host_realm.c @@ -0,0 +1,257 @@ +/* + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" +#include <resolve.h> + +RCSID("$Id: get_host_realm.c 18541 2006-10-17 19:28:36Z lha $"); + +/* To automagically find the correct realm of a host (without + * [domain_realm] in krb5.conf) add a text record for your domain with + * the name of your realm, like this: + * + * _kerberos IN TXT "FOO.SE" + * + * The search is recursive, so you can add entries for specific + * hosts. To find the realm of host a.b.c, it first tries + * _kerberos.a.b.c, then _kerberos.b.c and so on. + * + * This method is described in draft-ietf-cat-krb-dns-locate-03.txt. + * + */ + +static int +copy_txt_to_realms (struct resource_record *head, + krb5_realm **realms) +{ + struct resource_record *rr; + int n, i; + + for(n = 0, rr = head; rr; rr = rr->next) + if (rr->type == T_TXT) + ++n; + + if (n == 0) + return -1; + + *realms = malloc ((n + 1) * sizeof(krb5_realm)); + if (*realms == NULL) + return -1; + + for (i = 0; i < n + 1; ++i) + (*realms)[i] = NULL; + + for (i = 0, rr = head; rr; rr = rr->next) { + if (rr->type == T_TXT) { + char *tmp; + + tmp = strdup(rr->u.txt); + if (tmp == NULL) { + for (i = 0; i < n; ++i) + free ((*realms)[i]); + free (*realms); + return -1; + } + (*realms)[i] = tmp; + ++i; + } + } + return 0; +} + +static int +dns_find_realm(krb5_context context, + const char *domain, + krb5_realm **realms) +{ + static const char *default_labels[] = { "_kerberos", NULL }; + char dom[MAXHOSTNAMELEN]; + struct dns_reply *r; + const char **labels; + char **config_labels; + int i, ret; + + config_labels = krb5_config_get_strings(context, NULL, "libdefaults", + "dns_lookup_realm_labels", NULL); + if(config_labels != NULL) + labels = (const char **)config_labels; + else + labels = default_labels; + if(*domain == '.') + domain++; + for (i = 0; labels[i] != NULL; i++) { + ret = snprintf(dom, sizeof(dom), "%s.%s.", labels[i], domain); + if(ret < 0 || ret >= sizeof(dom)) { + if (config_labels) + krb5_config_free_strings(config_labels); + return -1; + } + r = dns_lookup(dom, "TXT"); + if(r != NULL) { + ret = copy_txt_to_realms (r->head, realms); + dns_free_data(r); + if(ret == 0) { + if (config_labels) + krb5_config_free_strings(config_labels); + return 0; + } + } + } + if (config_labels) + krb5_config_free_strings(config_labels); + return -1; +} + +/* + * Try to figure out what realms host in `domain' belong to from the + * configuration file. + */ + +static int +config_find_realm(krb5_context context, + const char *domain, + krb5_realm **realms) +{ + char **tmp = krb5_config_get_strings (context, NULL, + "domain_realm", + domain, + NULL); + + if (tmp == NULL) + return -1; + *realms = tmp; + return 0; +} + +/* + * This function assumes that `host' is a FQDN (and doesn't handle the + * special case of host == NULL either). + * Try to find mapping in the config file or DNS and it that fails, + * fall back to guessing + */ + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_get_host_realm_int (krb5_context context, + const char *host, + krb5_boolean use_dns, + krb5_realm **realms) +{ + const char *p, *q; + krb5_boolean dns_locate_enable; + + dns_locate_enable = krb5_config_get_bool_default(context, NULL, TRUE, + "libdefaults", "dns_lookup_realm", NULL); + for (p = host; p != NULL; p = strchr (p + 1, '.')) { + if(config_find_realm(context, p, realms) == 0) { + if(strcasecmp(*realms[0], "dns_locate") == 0) { + if(use_dns) + for (q = host; q != NULL; q = strchr(q + 1, '.')) + if(dns_find_realm(context, q, realms) == 0) + return 0; + continue; + } else + return 0; + } + else if(use_dns && dns_locate_enable) { + if(dns_find_realm(context, p, realms) == 0) + return 0; + } + } + p = strchr(host, '.'); + if(p != NULL) { + p++; + *realms = malloc(2 * sizeof(krb5_realm)); + if (*realms == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + (*realms)[0] = strdup(p); + if((*realms)[0] == NULL) { + free(*realms); + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + strupr((*realms)[0]); + (*realms)[1] = NULL; + return 0; + } + krb5_set_error_string(context, "unable to find realm of host %s", host); + return KRB5_ERR_HOST_REALM_UNKNOWN; +} + +/* + * Return the realm(s) of `host' as a NULL-terminated list in + * `realms'. Free `realms' with krb5_free_host_realm(). + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_host_realm(krb5_context context, + const char *targethost, + krb5_realm **realms) +{ + const char *host = targethost; + char hostname[MAXHOSTNAMELEN]; + krb5_error_code ret; + int use_dns; + + if (host == NULL) { + if (gethostname (hostname, sizeof(hostname))) { + *realms = NULL; + return errno; + } + host = hostname; + } + + /* + * If our local hostname is without components, don't even try to dns. + */ + + use_dns = (strchr(host, '.') != NULL); + + ret = _krb5_get_host_realm_int (context, host, use_dns, realms); + if (ret && targethost != NULL) { + /* + * If there was no realm mapping for the host (and we wasn't + * looking for ourself), guess at the local realm, maybe our + * KDC knows better then we do and we get a referral back. + */ + ret = krb5_get_default_realms(context, realms); + if (ret) { + krb5_set_error_string(context, "Unable to find realm of host %s", + host); + return KRB5_ERR_HOST_REALM_UNKNOWN; + } + } + return ret; +} diff --git a/lib/krb5/get_in_tkt.c b/lib/krb5/get_in_tkt.c new file mode 100644 index 0000000..ffd4ca2 --- /dev/null +++ b/lib/krb5/get_in_tkt.c @@ -0,0 +1,834 @@ +/* + * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: get_in_tkt.c 20226 2007-02-16 03:31:50Z lha $"); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_init_etype (krb5_context context, + unsigned *len, + krb5_enctype **val, + const krb5_enctype *etypes) +{ + int i; + krb5_error_code ret; + krb5_enctype *tmp = NULL; + + ret = 0; + if (etypes == NULL) { + ret = krb5_get_default_in_tkt_etypes(context, + &tmp); + if (ret) + return ret; + etypes = tmp; + } + + for (i = 0; etypes[i]; ++i) + ; + *len = i; + *val = malloc(i * sizeof(**val)); + if (i != 0 && *val == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto cleanup; + } + memmove (*val, + etypes, + i * sizeof(*tmp)); +cleanup: + if (tmp != NULL) + free (tmp); + return ret; +} + + +static krb5_error_code +decrypt_tkt (krb5_context context, + krb5_keyblock *key, + krb5_key_usage usage, + krb5_const_pointer decrypt_arg, + krb5_kdc_rep *dec_rep) +{ + krb5_error_code ret; + krb5_data data; + size_t size; + krb5_crypto crypto; + + ret = krb5_crypto_init(context, key, 0, &crypto); + if (ret) + return ret; + + ret = krb5_decrypt_EncryptedData (context, + crypto, + usage, + &dec_rep->kdc_rep.enc_part, + &data); + krb5_crypto_destroy(context, crypto); + + if (ret) + return ret; + + ret = krb5_decode_EncASRepPart(context, + data.data, + data.length, + &dec_rep->enc_part, + &size); + if (ret) + ret = krb5_decode_EncTGSRepPart(context, + data.data, + data.length, + &dec_rep->enc_part, + &size); + krb5_data_free (&data); + if (ret) + return ret; + return 0; +} + +int +_krb5_extract_ticket(krb5_context context, + krb5_kdc_rep *rep, + krb5_creds *creds, + krb5_keyblock *key, + krb5_const_pointer keyseed, + krb5_key_usage key_usage, + krb5_addresses *addrs, + unsigned nonce, + unsigned flags, + krb5_decrypt_proc decrypt_proc, + krb5_const_pointer decryptarg) +{ + krb5_error_code ret; + krb5_principal tmp_principal; + int tmp; + size_t len; + time_t tmp_time; + krb5_timestamp sec_now; + + ret = _krb5_principalname2krb5_principal (context, + &tmp_principal, + rep->kdc_rep.cname, + rep->kdc_rep.crealm); + if (ret) + goto out; + + /* compare client */ + + if((flags & EXTRACT_TICKET_ALLOW_CNAME_MISMATCH) == 0){ + tmp = krb5_principal_compare (context, tmp_principal, creds->client); + if (!tmp) { + krb5_free_principal (context, tmp_principal); + krb5_clear_error_string (context); + ret = KRB5KRB_AP_ERR_MODIFIED; + goto out; + } + } + + krb5_free_principal (context, creds->client); + creds->client = tmp_principal; + + /* extract ticket */ + ASN1_MALLOC_ENCODE(Ticket, creds->ticket.data, creds->ticket.length, + &rep->kdc_rep.ticket, &len, ret); + if(ret) + goto out; + if (creds->ticket.length != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + creds->second_ticket.length = 0; + creds->second_ticket.data = NULL; + + /* compare server */ + + ret = _krb5_principalname2krb5_principal (context, + &tmp_principal, + rep->kdc_rep.ticket.sname, + rep->kdc_rep.ticket.realm); + if (ret) + goto out; + if(flags & EXTRACT_TICKET_ALLOW_SERVER_MISMATCH){ + krb5_free_principal(context, creds->server); + creds->server = tmp_principal; + tmp_principal = NULL; + } else { + tmp = krb5_principal_compare (context, tmp_principal, + creds->server); + krb5_free_principal (context, tmp_principal); + if (!tmp) { + ret = KRB5KRB_AP_ERR_MODIFIED; + krb5_clear_error_string (context); + goto out; + } + } + + /* decrypt */ + + if (decrypt_proc == NULL) + decrypt_proc = decrypt_tkt; + + ret = (*decrypt_proc)(context, key, key_usage, decryptarg, rep); + if (ret) + goto out; + + /* verify names */ + if(flags & EXTRACT_TICKET_MATCH_REALM){ + const char *srealm = krb5_principal_get_realm(context, creds->server); + const char *crealm = krb5_principal_get_realm(context, creds->client); + + if (strcmp(rep->enc_part.srealm, srealm) != 0 || + strcmp(rep->enc_part.srealm, crealm) != 0) + { + ret = KRB5KRB_AP_ERR_MODIFIED; + krb5_clear_error_string(context); + goto out; + } + } + + /* compare nonces */ + + if (nonce != rep->enc_part.nonce) { + ret = KRB5KRB_AP_ERR_MODIFIED; + krb5_set_error_string(context, "malloc: out of memory"); + goto out; + } + + /* set kdc-offset */ + + krb5_timeofday (context, &sec_now); + if (rep->enc_part.flags.initial + && context->kdc_sec_offset == 0 + && krb5_config_get_bool (context, NULL, + "libdefaults", + "kdc_timesync", + NULL)) { + context->kdc_sec_offset = rep->enc_part.authtime - sec_now; + krb5_timeofday (context, &sec_now); + } + + /* check all times */ + + if (rep->enc_part.starttime) { + tmp_time = *rep->enc_part.starttime; + } else + tmp_time = rep->enc_part.authtime; + + if (creds->times.starttime == 0 + && abs(tmp_time - sec_now) > context->max_skew) { + ret = KRB5KRB_AP_ERR_SKEW; + krb5_set_error_string (context, + "time skew (%d) larger than max (%d)", + abs(tmp_time - sec_now), + (int)context->max_skew); + goto out; + } + + if (creds->times.starttime != 0 + && tmp_time != creds->times.starttime) { + krb5_clear_error_string (context); + ret = KRB5KRB_AP_ERR_MODIFIED; + goto out; + } + + creds->times.starttime = tmp_time; + + if (rep->enc_part.renew_till) { + tmp_time = *rep->enc_part.renew_till; + } else + tmp_time = 0; + + if (creds->times.renew_till != 0 + && tmp_time > creds->times.renew_till) { + krb5_clear_error_string (context); + ret = KRB5KRB_AP_ERR_MODIFIED; + goto out; + } + + creds->times.renew_till = tmp_time; + + creds->times.authtime = rep->enc_part.authtime; + + if (creds->times.endtime != 0 + && rep->enc_part.endtime > creds->times.endtime) { + krb5_clear_error_string (context); + ret = KRB5KRB_AP_ERR_MODIFIED; + goto out; + } + + creds->times.endtime = rep->enc_part.endtime; + + if(rep->enc_part.caddr) + krb5_copy_addresses (context, rep->enc_part.caddr, &creds->addresses); + else if(addrs) + krb5_copy_addresses (context, addrs, &creds->addresses); + else { + creds->addresses.len = 0; + creds->addresses.val = NULL; + } + creds->flags.b = rep->enc_part.flags; + + creds->authdata.len = 0; + creds->authdata.val = NULL; + creds->session.keyvalue.length = 0; + creds->session.keyvalue.data = NULL; + creds->session.keytype = rep->enc_part.key.keytype; + ret = krb5_data_copy (&creds->session.keyvalue, + rep->enc_part.key.keyvalue.data, + rep->enc_part.key.keyvalue.length); + +out: + memset (rep->enc_part.key.keyvalue.data, 0, + rep->enc_part.key.keyvalue.length); + return ret; +} + + +static krb5_error_code +make_pa_enc_timestamp(krb5_context context, PA_DATA *pa, + krb5_enctype etype, krb5_keyblock *key) +{ + 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_crypto crypto; + + 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_crypto_init(context, key, 0, &crypto); + if (ret) { + free(buf); + return ret; + } + ret = krb5_encrypt_EncryptedData(context, + crypto, + KRB5_KU_PA_ENC_TIMESTAMP, + buf, + len, + 0, + &encdata); + free(buf); + krb5_crypto_destroy(context, crypto); + 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"); + pa->padata_type = KRB5_PADATA_ENC_TIMESTAMP; + pa->padata_value.length = len; + pa->padata_value.data = buf; + return 0; +} + +static krb5_error_code +add_padata(krb5_context context, + METHOD_DATA *md, + krb5_principal client, + krb5_key_proc key_proc, + krb5_const_pointer keyseed, + krb5_enctype *enctypes, + unsigned netypes, + krb5_salt *salt) +{ + krb5_error_code ret; + PA_DATA *pa2; + krb5_salt salt2; + krb5_enctype *ep; + int i; + + if(salt == NULL) { + /* default to standard salt */ + ret = krb5_get_pw_salt (context, client, &salt2); + salt = &salt2; + } + if (!enctypes) { + enctypes = context->etypes; + netypes = 0; + for (ep = enctypes; *ep != ETYPE_NULL; ep++) + netypes++; + } + pa2 = realloc (md->val, (md->len + netypes) * sizeof(*md->val)); + if (pa2 == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + md->val = pa2; + + for (i = 0; i < netypes; ++i) { + krb5_keyblock *key; + + ret = (*key_proc)(context, enctypes[i], *salt, keyseed, &key); + if (ret) + continue; + ret = make_pa_enc_timestamp (context, &md->val[md->len], + enctypes[i], key); + krb5_free_keyblock (context, key); + if (ret) + return ret; + ++md->len; + } + if(salt == &salt2) + krb5_free_salt(context, salt2); + return 0; +} + +static krb5_error_code +init_as_req (krb5_context context, + KDCOptions opts, + krb5_creds *creds, + const krb5_addresses *addrs, + const krb5_enctype *etypes, + const krb5_preauthtype *ptypes, + const krb5_preauthdata *preauth, + krb5_key_proc key_proc, + krb5_const_pointer keyseed, + unsigned nonce, + AS_REQ *a) +{ + krb5_error_code ret; + krb5_salt salt; + + memset(a, 0, sizeof(*a)); + + a->pvno = 5; + a->msg_type = krb_as_req; + a->req_body.kdc_options = opts; + a->req_body.cname = malloc(sizeof(*a->req_body.cname)); + if (a->req_body.cname == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto fail; + } + a->req_body.sname = malloc(sizeof(*a->req_body.sname)); + if (a->req_body.sname == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto fail; + } + ret = _krb5_principal2principalname (a->req_body.cname, creds->client); + if (ret) + goto fail; + ret = _krb5_principal2principalname (a->req_body.sname, creds->server); + if (ret) + goto fail; + ret = copy_Realm(&creds->client->realm, &a->req_body.realm); + if (ret) + goto fail; + + if(creds->times.starttime) { + a->req_body.from = malloc(sizeof(*a->req_body.from)); + if (a->req_body.from == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto fail; + } + *a->req_body.from = creds->times.starttime; + } + if(creds->times.endtime){ + ALLOC(a->req_body.till, 1); + *a->req_body.till = creds->times.endtime; + } + if(creds->times.renew_till){ + a->req_body.rtime = malloc(sizeof(*a->req_body.rtime)); + if (a->req_body.rtime == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto fail; + } + *a->req_body.rtime = creds->times.renew_till; + } + a->req_body.nonce = nonce; + ret = krb5_init_etype (context, + &a->req_body.etype.len, + &a->req_body.etype.val, + etypes); + if (ret) + goto fail; + + /* + * This means no addresses + */ + + if (addrs && addrs->len == 0) { + a->req_body.addresses = NULL; + } else { + a->req_body.addresses = malloc(sizeof(*a->req_body.addresses)); + if (a->req_body.addresses == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto fail; + } + + if (addrs) + ret = krb5_copy_addresses(context, addrs, a->req_body.addresses); + else { + ret = krb5_get_all_client_addrs (context, a->req_body.addresses); + if(ret == 0 && a->req_body.addresses->len == 0) { + free(a->req_body.addresses); + a->req_body.addresses = NULL; + } + } + if (ret) + return ret; + } + + a->req_body.enc_authorization_data = NULL; + a->req_body.additional_tickets = NULL; + + if(preauth != NULL) { + int i; + ALLOC(a->padata, 1); + if(a->padata == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto fail; + } + a->padata->val = NULL; + a->padata->len = 0; + for(i = 0; i < preauth->len; i++) { + if(preauth->val[i].type == KRB5_PADATA_ENC_TIMESTAMP){ + int j; + + for(j = 0; j < preauth->val[i].info.len; j++) { + krb5_salt *sp = &salt; + if(preauth->val[i].info.val[j].salttype) + salt.salttype = *preauth->val[i].info.val[j].salttype; + else + salt.salttype = KRB5_PW_SALT; + if(preauth->val[i].info.val[j].salt) + salt.saltvalue = *preauth->val[i].info.val[j].salt; + else + if(salt.salttype == KRB5_PW_SALT) + sp = NULL; + else + krb5_data_zero(&salt.saltvalue); + ret = add_padata(context, a->padata, creds->client, + key_proc, keyseed, + &preauth->val[i].info.val[j].etype, 1, + sp); + if (ret == 0) + break; + } + } + } + } else + /* not sure this is the way to use `ptypes' */ + if (ptypes == NULL || *ptypes == KRB5_PADATA_NONE) + a->padata = NULL; + else if (*ptypes == KRB5_PADATA_ENC_TIMESTAMP) { + ALLOC(a->padata, 1); + if (a->padata == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto fail; + } + a->padata->len = 0; + a->padata->val = NULL; + + /* make a v5 salted pa-data */ + add_padata(context, a->padata, creds->client, + key_proc, keyseed, a->req_body.etype.val, + a->req_body.etype.len, NULL); + + /* make a v4 salted pa-data */ + salt.salttype = KRB5_PW_SALT; + krb5_data_zero(&salt.saltvalue); + add_padata(context, a->padata, creds->client, + key_proc, keyseed, a->req_body.etype.val, + a->req_body.etype.len, &salt); + } else { + krb5_set_error_string (context, "pre-auth type %d not supported", + *ptypes); + ret = KRB5_PREAUTH_BAD_TYPE; + goto fail; + } + return 0; +fail: + free_AS_REQ(a); + return ret; +} + +static int +set_ptypes(krb5_context context, + KRB_ERROR *error, + const krb5_preauthtype **ptypes, + krb5_preauthdata **preauth) +{ + static krb5_preauthdata preauth2; + static krb5_preauthtype ptypes2[] = { KRB5_PADATA_ENC_TIMESTAMP, KRB5_PADATA_NONE }; + + if(error->e_data) { + METHOD_DATA md; + int i; + decode_METHOD_DATA(error->e_data->data, + error->e_data->length, + &md, + NULL); + for(i = 0; i < md.len; i++){ + switch(md.val[i].padata_type){ + case KRB5_PADATA_ENC_TIMESTAMP: + *ptypes = ptypes2; + break; + case KRB5_PADATA_ETYPE_INFO: + *preauth = &preauth2; + ALLOC_SEQ(*preauth, 1); + (*preauth)->val[0].type = KRB5_PADATA_ENC_TIMESTAMP; + krb5_decode_ETYPE_INFO(context, + md.val[i].padata_value.data, + md.val[i].padata_value.length, + &(*preauth)->val[0].info, + NULL); + break; + default: + break; + } + } + free_METHOD_DATA(&md); + } else { + *ptypes = ptypes2; + } + return(1); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_in_cred(krb5_context context, + krb5_flags options, + const krb5_addresses *addrs, + const krb5_enctype *etypes, + const krb5_preauthtype *ptypes, + const krb5_preauthdata *preauth, + krb5_key_proc key_proc, + krb5_const_pointer keyseed, + krb5_decrypt_proc decrypt_proc, + krb5_const_pointer decryptarg, + krb5_creds *creds, + krb5_kdc_rep *ret_as_reply) +{ + krb5_error_code ret; + AS_REQ a; + krb5_kdc_rep rep; + krb5_data req, resp; + size_t len; + krb5_salt salt; + krb5_keyblock *key; + size_t size; + KDCOptions opts; + PA_DATA *pa; + krb5_enctype etype; + krb5_preauthdata *my_preauth = NULL; + unsigned nonce; + int done; + + opts = int2KDCOptions(options); + + krb5_generate_random_block (&nonce, sizeof(nonce)); + nonce &= 0xffffffff; + + do { + done = 1; + ret = init_as_req (context, + opts, + creds, + addrs, + etypes, + ptypes, + preauth, + key_proc, + keyseed, + nonce, + &a); + if (my_preauth) { + free_ETYPE_INFO(&my_preauth->val[0].info); + free (my_preauth->val); + my_preauth = NULL; + } + if (ret) + return ret; + + ASN1_MALLOC_ENCODE(AS_REQ, req.data, req.length, &a, &len, ret); + free_AS_REQ(&a); + if (ret) + return ret; + if(len != req.length) + krb5_abortx(context, "internal error in ASN.1 encoder"); + + ret = krb5_sendto_kdc (context, &req, &creds->client->realm, &resp); + krb5_data_free(&req); + if (ret) + return ret; + + memset (&rep, 0, sizeof(rep)); + ret = decode_AS_REP(resp.data, resp.length, &rep.kdc_rep, &size); + if(ret) { + /* let's try to parse it as a KRB-ERROR */ + KRB_ERROR error; + int ret2; + + ret2 = krb5_rd_error(context, &resp, &error); + if(ret2 && resp.data && ((char*)resp.data)[0] == 4) + ret = KRB5KRB_AP_ERR_V4_REPLY; + krb5_data_free(&resp); + if (ret2 == 0) { + ret = krb5_error_from_rd_error(context, &error, creds); + /* if no preauth was set and KDC requires it, give it + one more try */ + if (!ptypes && !preauth + && ret == KRB5KDC_ERR_PREAUTH_REQUIRED +#if 0 + || ret == KRB5KDC_ERR_BADOPTION +#endif + && set_ptypes(context, &error, &ptypes, &my_preauth)) { + done = 0; + preauth = my_preauth; + krb5_free_error_contents(context, &error); + krb5_clear_error_string(context); + continue; + } + if(ret_as_reply) + ret_as_reply->error = error; + else + free_KRB_ERROR (&error); + return ret; + } + return ret; + } + krb5_data_free(&resp); + } while(!done); + + pa = NULL; + etype = rep.kdc_rep.enc_part.etype; + if(rep.kdc_rep.padata){ + int i = 0; + pa = krb5_find_padata(rep.kdc_rep.padata->val, rep.kdc_rep.padata->len, + KRB5_PADATA_PW_SALT, &i); + if(pa == NULL) { + i = 0; + pa = krb5_find_padata(rep.kdc_rep.padata->val, + rep.kdc_rep.padata->len, + KRB5_PADATA_AFS3_SALT, &i); + } + } + if(pa) { + salt.salttype = pa->padata_type; + salt.saltvalue = pa->padata_value; + + ret = (*key_proc)(context, etype, salt, keyseed, &key); + } else { + /* make a v5 salted pa-data */ + ret = krb5_get_pw_salt (context, creds->client, &salt); + + if (ret) + goto out; + ret = (*key_proc)(context, etype, salt, keyseed, &key); + krb5_free_salt(context, salt); + } + if (ret) + goto out; + + { + unsigned flags = 0; + if (opts.request_anonymous) + flags |= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH; + + ret = _krb5_extract_ticket(context, + &rep, + creds, + key, + keyseed, + KRB5_KU_AS_REP_ENC_PART, + NULL, + nonce, + flags, + decrypt_proc, + decryptarg); + } + memset (key->keyvalue.data, 0, key->keyvalue.length); + krb5_free_keyblock_contents (context, key); + free (key); + +out: + if (ret == 0 && ret_as_reply) + *ret_as_reply = rep; + else + krb5_free_kdc_rep (context, &rep); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_in_tkt(krb5_context context, + krb5_flags options, + const krb5_addresses *addrs, + const krb5_enctype *etypes, + const krb5_preauthtype *ptypes, + krb5_key_proc key_proc, + krb5_const_pointer keyseed, + krb5_decrypt_proc decrypt_proc, + krb5_const_pointer decryptarg, + krb5_creds *creds, + krb5_ccache ccache, + krb5_kdc_rep *ret_as_reply) +{ + krb5_error_code ret; + + ret = krb5_get_in_cred (context, + options, + addrs, + etypes, + ptypes, + NULL, + key_proc, + keyseed, + decrypt_proc, + decryptarg, + creds, + ret_as_reply); + if(ret) + return ret; + if (ccache) + ret = krb5_cc_store_cred (context, ccache, creds); + return ret; +} diff --git a/lib/krb5/get_in_tkt_pw.c b/lib/krb5/get_in_tkt_pw.c new file mode 100644 index 0000000..21b27c6 --- /dev/null +++ b/lib/krb5/get_in_tkt_pw.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: get_in_tkt_pw.c 13863 2004-05-25 21:46:46Z lha $"); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_password_key_proc (krb5_context context, + krb5_enctype type, + krb5_salt salt, + krb5_const_pointer keyseed, + krb5_keyblock **key) +{ + krb5_error_code ret; + const char *password = (const char *)keyseed; + char buf[BUFSIZ]; + + *key = malloc (sizeof (**key)); + if (*key == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + if (password == NULL) { + if(UI_UTIL_read_pw_string (buf, sizeof(buf), "Password: ", 0)) { + free (*key); + krb5_clear_error_string(context); + return KRB5_LIBOS_PWDINTR; + } + password = buf; + } + ret = krb5_string_to_key_salt (context, type, password, salt, *key); + memset (buf, 0, sizeof(buf)); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_in_tkt_with_password (krb5_context context, + krb5_flags options, + krb5_addresses *addrs, + const krb5_enctype *etypes, + const krb5_preauthtype *pre_auth_types, + const char *password, + krb5_ccache ccache, + krb5_creds *creds, + krb5_kdc_rep *ret_as_reply) +{ + return krb5_get_in_tkt (context, + options, + addrs, + etypes, + pre_auth_types, + krb5_password_key_proc, + password, + NULL, + NULL, + creds, + ccache, + ret_as_reply); +} diff --git a/lib/krb5/get_in_tkt_with_keytab.c b/lib/krb5/get_in_tkt_with_keytab.c new file mode 100644 index 0000000..52f95c4 --- /dev/null +++ b/lib/krb5/get_in_tkt_with_keytab.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: get_in_tkt_with_keytab.c 15477 2005-06-17 04:56:44Z lha $"); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_keytab_key_proc (krb5_context context, + krb5_enctype enctype, + krb5_salt salt, + krb5_const_pointer keyseed, + krb5_keyblock **key) +{ + krb5_keytab_key_proc_args *args = rk_UNCONST(keyseed); + krb5_keytab keytab = args->keytab; + krb5_principal principal = args->principal; + krb5_error_code ret; + krb5_keytab real_keytab; + krb5_keytab_entry entry; + + if(keytab == NULL) + krb5_kt_default(context, &real_keytab); + else + real_keytab = keytab; + + ret = krb5_kt_get_entry (context, real_keytab, principal, + 0, enctype, &entry); + + if (keytab == NULL) + krb5_kt_close (context, real_keytab); + + if (ret) + return ret; + + ret = krb5_copy_keyblock (context, &entry.keyblock, key); + krb5_kt_free_entry(context, &entry); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_in_tkt_with_keytab (krb5_context context, + krb5_flags options, + krb5_addresses *addrs, + const krb5_enctype *etypes, + const krb5_preauthtype *pre_auth_types, + krb5_keytab keytab, + krb5_ccache ccache, + krb5_creds *creds, + krb5_kdc_rep *ret_as_reply) +{ + krb5_keytab_key_proc_args a; + + a.principal = creds->client; + a.keytab = keytab; + + return krb5_get_in_tkt (context, + options, + addrs, + etypes, + pre_auth_types, + krb5_keytab_key_proc, + &a, + NULL, + NULL, + creds, + ccache, + ret_as_reply); +} diff --git a/lib/krb5/get_in_tkt_with_skey.c b/lib/krb5/get_in_tkt_with_skey.c new file mode 100644 index 0000000..1936fa1 --- /dev/null +++ b/lib/krb5/get_in_tkt_with_skey.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 1997, 1998 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: get_in_tkt_with_skey.c 13863 2004-05-25 21:46:46Z lha $"); + +static krb5_error_code +krb5_skey_key_proc (krb5_context context, + krb5_enctype type, + krb5_salt salt, + krb5_const_pointer keyseed, + krb5_keyblock **key) +{ + return krb5_copy_keyblock (context, keyseed, key); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_in_tkt_with_skey (krb5_context context, + krb5_flags options, + krb5_addresses *addrs, + const krb5_enctype *etypes, + const krb5_preauthtype *pre_auth_types, + const krb5_keyblock *key, + krb5_ccache ccache, + krb5_creds *creds, + krb5_kdc_rep *ret_as_reply) +{ + if(key == NULL) + return krb5_get_in_tkt_with_keytab (context, + options, + addrs, + etypes, + pre_auth_types, + NULL, + ccache, + creds, + ret_as_reply); + else + return krb5_get_in_tkt (context, + options, + addrs, + etypes, + pre_auth_types, + krb5_skey_key_proc, + key, + NULL, + NULL, + creds, + ccache, + ret_as_reply); +} diff --git a/lib/krb5/get_port.c b/lib/krb5/get_port.c new file mode 100644 index 0000000..85587ea --- /dev/null +++ b/lib/krb5/get_port.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 1997-2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <krb5_locl.h> + +RCSID("$Id: get_port.c 13863 2004-05-25 21:46:46Z lha $"); + +int KRB5_LIB_FUNCTION +krb5_getportbyname (krb5_context context, + const char *service, + const char *proto, + int default_port) +{ + struct servent *sp; + + if ((sp = roken_getservbyname (service, proto)) == NULL) { +#if 0 + krb5_warnx(context, "%s/%s unknown service, using default port %d", + service, proto, default_port); +#endif + return htons(default_port); + } else + return sp->s_port; +} diff --git a/lib/krb5/heim_err.et b/lib/krb5/heim_err.et new file mode 100644 index 0000000..1b8ab49 --- /dev/null +++ b/lib/krb5/heim_err.et @@ -0,0 +1,44 @@ +# +# Error messages for the krb5 library +# +# This might look like a com_err file, but is not +# +id "$Id: heim_err.et 13352 2004-02-13 16:23:40Z lha $" + +error_table heim + +prefix HEIM_ERR + +error_code LOG_PARSE, "Error parsing log destination" +error_code V4_PRINC_NO_CONV, "Failed to convert v4 principal" +error_code SALTTYPE_NOSUPP, "Salt type is not supported by enctype" +error_code NOHOST, "Host not found" +error_code OPNOTSUPP, "Operation not supported" +error_code EOF, "End of file" +error_code BAD_MKEY, "Failed to get the master key" +error_code SERVICE_NOMATCH, "Unacceptable service used" + +index 64 +prefix HEIM_PKINIT +error_code NO_CERTIFICATE, "Certificate missing" +error_code NO_PRIVATE_KEY, "Private key missing" +error_code NO_VALID_CA, "No valid certificate authority" +error_code CERTIFICATE_INVALID, "Certificate invalid" +error_code PRIVATE_KEY_INVALID, "Private key invalid" + +index 128 +prefix HEIM_EAI +#error_code NOERROR, "no error" +error_code UNKNOWN, "unknown error from getaddrinfo" +error_code ADDRFAMILY, "address family for nodename not supported" +error_code AGAIN, "temporary failure in name resolution" +error_code BADFLAGS, "invalid value for ai_flags" +error_code FAIL, "non-recoverable failure in name resolution" +error_code FAMILY, "ai_family not supported" +error_code MEMORY, "memory allocation failure" +error_code NODATA, "no address associated with nodename" +error_code NONAME, "nodename nor servname provided, or not known" +error_code SERVICE, "servname not supported for ai_socktype" +error_code SOCKTYPE, "ai_socktype not supported" +error_code SYSTEM, "system error returned in errno" +end diff --git a/lib/krb5/heim_threads.h b/lib/krb5/heim_threads.h new file mode 100644 index 0000000..3c27d13 --- /dev/null +++ b/lib/krb5/heim_threads.h @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $Id: heim_threads.h 14409 2004-12-18 16:03:38Z lha $ */ + +/* + * Provide wrapper macros for thread synchronization primitives so we + * can use native thread functions for those operating system that + * supports it. + * + * This is so libkrb5.so (or more importantly, libgssapi.so) can have + * thread support while the program that that dlopen(3)s the library + * don't need to be linked to libpthread. + */ + +#ifndef HEIM_THREADS_H +#define HEIM_THREADS_H 1 + +/* assume headers already included */ + +#if defined(__NetBSD__) && __NetBSD_Version__ >= 106120000 && __NetBSD_Version__< 299001200 && defined(ENABLE_PTHREAD_SUPPORT) + +/* + * NetBSD have a thread lib that we can use that part of libc that + * works regardless if application are linked to pthreads or not. + * NetBSD newer then 2.99.11 just use pthread.h, and the same thing + * will happen. + */ +#include <threadlib.h> + +#define HEIMDAL_MUTEX mutex_t +#define HEIMDAL_MUTEX_INITIALIZER MUTEX_INITIALIZER +#define HEIMDAL_MUTEX_init(m) mutex_init(m, NULL) +#define HEIMDAL_MUTEX_lock(m) mutex_lock(m) +#define HEIMDAL_MUTEX_unlock(m) mutex_unlock(m) +#define HEIMDAL_MUTEX_destroy(m) mutex_destroy(m) + +#define HEIMDAL_RWLOCK rwlock_t +#define HEIMDAL_RWLOCK_INITIALIZER RWLOCK_INITIALIZER +#define HEIMDAL_RWLOCK_init(l) rwlock_init(l, NULL) +#define HEIMDAL_RWLOCK_rdlock(l) rwlock_rdlock(l) +#define HEIMDAL_RWLOCK_wrlock(l) rwlock_wrlock(l) +#define HEIMDAL_RWLOCK_tryrdlock(l) rwlock_tryrdlock(l) +#define HEIMDAL_RWLOCK_trywrlock(l) rwlock_trywrlock(l) +#define HEIMDAL_RWLOCK_unlock(l) rwlock_unlock(l) +#define HEIMDAL_RWLOCK_destroy(l) rwlock_destroy(l) + +#define HEIMDAL_thread_key thread_key_t +#define HEIMDAL_key_create(k,d,r) do { r = thr_keycreate(k,d); } while(0) +#define HEIMDAL_setspecific(k,s,r) do { r = thr_setspecific(k,s); } while(0) +#define HEIMDAL_getspecific(k) thr_getspecific(k) +#define HEIMDAL_key_delete(k) thr_keydelete(k) + +#elif defined(ENABLE_PTHREAD_SUPPORT) && (!defined(__NetBSD__) || __NetBSD_Version__ >= 299001200) + +#include <pthread.h> + +#define HEIMDAL_MUTEX pthread_mutex_t +#define HEIMDAL_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER +#define HEIMDAL_MUTEX_init(m) pthread_mutex_init(m, NULL) +#define HEIMDAL_MUTEX_lock(m) pthread_mutex_lock(m) +#define HEIMDAL_MUTEX_unlock(m) pthread_mutex_unlock(m) +#define HEIMDAL_MUTEX_destroy(m) pthread_mutex_destroy(m) + +#define HEIMDAL_RWLOCK rwlock_t +#define HEIMDAL_RWLOCK_INITIALIZER RWLOCK_INITIALIZER +#define HEIMDAL_RWLOCK_init(l) pthread_rwlock_init(l, NULL) +#define HEIMDAL_RWLOCK_rdlock(l) pthread_rwlock_rdlock(l) +#define HEIMDAL_RWLOCK_wrlock(l) pthread_rwlock_wrlock(l) +#define HEIMDAL_RWLOCK_tryrdlock(l) pthread_rwlock_tryrdlock(l) +#define HEIMDAL_RWLOCK_trywrlock(l) pthread_rwlock_trywrlock(l) +#define HEIMDAL_RWLOCK_unlock(l) pthread_rwlock_unlock(l) +#define HEIMDAL_RWLOCK_destroy(l) pthread_rwlock_destroy(l) + +#define HEIMDAL_thread_key pthread_key_t +#define HEIMDAL_key_create(k,d,r) do { r = pthread_key_create(k,d); } while(0) +#define HEIMDAL_setspecific(k,s,r) do { r = pthread_setspecific(k,s); } while(0) +#define HEIMDAL_getspecific(k) pthread_getspecific(k) +#define HEIMDAL_key_delete(k) pthread_key_delete(k) + +#elif defined(HEIMDAL_DEBUG_THREADS) + +/* no threads support, just do consistency checks */ +#include <stdlib.h> + +#define HEIMDAL_MUTEX int +#define HEIMDAL_MUTEX_INITIALIZER 0 +#define HEIMDAL_MUTEX_init(m) do { (*(m)) = 0; } while(0) +#define HEIMDAL_MUTEX_lock(m) do { if ((*(m))++ != 0) abort(); } while(0) +#define HEIMDAL_MUTEX_unlock(m) do { if ((*(m))-- != 1) abort(); } while(0) +#define HEIMDAL_MUTEX_destroy(m) do {if ((*(m)) != 0) abort(); } while(0) + +#define HEIMDAL_RWLOCK rwlock_t int +#define HEIMDAL_RWLOCK_INITIALIZER 0 +#define HEIMDAL_RWLOCK_init(l) do { } while(0) +#define HEIMDAL_RWLOCK_rdlock(l) do { } while(0) +#define HEIMDAL_RWLOCK_wrlock(l) do { } while(0) +#define HEIMDAL_RWLOCK_tryrdlock(l) do { } while(0) +#define HEIMDAL_RWLOCK_trywrlock(l) do { } while(0) +#define HEIMDAL_RWLOCK_unlock(l) do { } while(0) +#define HEIMDAL_RWLOCK_destroy(l) do { } while(0) + +#define HEIMDAL_internal_thread_key 1 + +#else /* no thread support, no debug case */ + +#define HEIMDAL_MUTEX int +#define HEIMDAL_MUTEX_INITIALIZER 0 +#define HEIMDAL_MUTEX_init(m) do { (void)(m); } while(0) +#define HEIMDAL_MUTEX_lock(m) do { (void)(m); } while(0) +#define HEIMDAL_MUTEX_unlock(m) do { (void)(m); } while(0) +#define HEIMDAL_MUTEX_destroy(m) do { (void)(m); } while(0) + +#define HEIMDAL_RWLOCK rwlock_t int +#define HEIMDAL_RWLOCK_INITIALIZER 0 +#define HEIMDAL_RWLOCK_init(l) do { } while(0) +#define HEIMDAL_RWLOCK_rdlock(l) do { } while(0) +#define HEIMDAL_RWLOCK_wrlock(l) do { } while(0) +#define HEIMDAL_RWLOCK_tryrdlock(l) do { } while(0) +#define HEIMDAL_RWLOCK_trywrlock(l) do { } while(0) +#define HEIMDAL_RWLOCK_unlock(l) do { } while(0) +#define HEIMDAL_RWLOCK_destroy(l) do { } while(0) + +#define HEIMDAL_internal_thread_key 1 + +#endif /* no thread support */ + +#ifdef HEIMDAL_internal_thread_key + +typedef struct heim_thread_key { + void *value; + void (*destructor)(void *); +} heim_thread_key; + +#define HEIMDAL_thread_key heim_thread_key +#define HEIMDAL_key_create(k,d,r) \ + do { (k)->value = NULL; (k)->destructor = (d); r = 0; } while(0) +#define HEIMDAL_setspecific(k,s,r) do { (k).value = s ; r = 0; } while(0) +#define HEIMDAL_getspecific(k) ((k).value) +#define HEIMDAL_key_delete(k) do { (*(k).destructor)((k).value); } while(0) + +#undef HEIMDAL_internal_thread_key +#endif /* HEIMDAL_internal_thread_key */ + +#endif /* HEIM_THREADS_H */ diff --git a/lib/krb5/init_creds.c b/lib/krb5/init_creds.c new file mode 100644 index 0000000..a59c903 --- /dev/null +++ b/lib/krb5/init_creds.c @@ -0,0 +1,442 @@ +/* + * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: init_creds.c 21711 2007-07-27 14:22:02Z lha $"); + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_init(krb5_get_init_creds_opt *opt) +{ + memset (opt, 0, sizeof(*opt)); + opt->flags = 0; + opt->opt_private = NULL; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_alloc(krb5_context context, + krb5_get_init_creds_opt **opt) +{ + krb5_get_init_creds_opt *o; + + *opt = NULL; + o = calloc(1, sizeof(*o)); + if (o == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + krb5_get_init_creds_opt_init(o); + o->opt_private = calloc(1, sizeof(*o->opt_private)); + if (o->opt_private == NULL) { + krb5_set_error_string(context, "out of memory"); + free(o); + return ENOMEM; + } + o->opt_private->refcount = 1; + *opt = o; + return 0; +} + +krb5_error_code +_krb5_get_init_creds_opt_copy(krb5_context context, + const krb5_get_init_creds_opt *in, + krb5_get_init_creds_opt **out) +{ + krb5_get_init_creds_opt *opt; + + *out = NULL; + opt = calloc(1, sizeof(*opt)); + if (opt == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + if (in) + *opt = *in; + if(opt->opt_private == NULL) { + opt->opt_private = calloc(1, sizeof(*opt->opt_private)); + if (opt->opt_private == NULL) { + krb5_set_error_string(context, "out of memory"); + free(opt); + return ENOMEM; + } + opt->opt_private->refcount = 1; + } else + opt->opt_private->refcount++; + *out = opt; + return 0; +} + +void KRB5_LIB_FUNCTION +_krb5_get_init_creds_opt_free_krb5_error(krb5_get_init_creds_opt *opt) +{ + if (opt->opt_private == NULL || opt->opt_private->error == NULL) + return; + free_KRB_ERROR(opt->opt_private->error); + free(opt->opt_private->error); + opt->opt_private->error = NULL; +} + +void KRB5_LIB_FUNCTION +_krb5_get_init_creds_opt_set_krb5_error(krb5_context context, + krb5_get_init_creds_opt *opt, + const KRB_ERROR *error) +{ + krb5_error_code ret; + + if (opt->opt_private == NULL) + return; + + _krb5_get_init_creds_opt_free_krb5_error(opt); + + opt->opt_private->error = malloc(sizeof(*opt->opt_private->error)); + if (opt->opt_private->error == NULL) + return; + ret = copy_KRB_ERROR(error, opt->opt_private->error); + if (ret) { + free(opt->opt_private->error); + opt->opt_private->error = NULL; + } +} + + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_free(krb5_context context, + krb5_get_init_creds_opt *opt) +{ + if (opt == NULL || opt->opt_private == NULL) + return; + if (opt->opt_private->refcount < 1) /* abort ? */ + return; + if (--opt->opt_private->refcount == 0) { + _krb5_get_init_creds_opt_free_krb5_error(opt); + _krb5_get_init_creds_opt_free_pkinit(opt); + free(opt->opt_private); + } + memset(opt, 0, sizeof(*opt)); + free(opt); +} + +static int +get_config_time (krb5_context context, + const char *realm, + const char *name, + int def) +{ + int ret; + + ret = krb5_config_get_time (context, NULL, + "realms", + realm, + name, + NULL); + if (ret >= 0) + return ret; + ret = krb5_config_get_time (context, NULL, + "libdefaults", + name, + NULL); + if (ret >= 0) + return ret; + return def; +} + +static krb5_boolean +get_config_bool (krb5_context context, + const char *realm, + const char *name) +{ + return krb5_config_get_bool (context, + NULL, + "realms", + realm, + name, + NULL) + || krb5_config_get_bool (context, + NULL, + "libdefaults", + name, + NULL); +} + +/* + * set all the values in `opt' to the appropriate values for + * application `appname' (default to getprogname() if NULL), and realm + * `realm'. First looks in [appdefaults] but falls back to + * [realms] or [libdefaults] for some of the values. + */ + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_default_flags(krb5_context context, + const char *appname, + krb5_const_realm realm, + krb5_get_init_creds_opt *opt) +{ + krb5_boolean b; + time_t t; + + b = get_config_bool (context, realm, "forwardable"); + krb5_appdefault_boolean(context, appname, realm, "forwardable", b, &b); + krb5_get_init_creds_opt_set_forwardable(opt, b); + + b = get_config_bool (context, realm, "proxiable"); + krb5_appdefault_boolean(context, appname, realm, "proxiable", b, &b); + krb5_get_init_creds_opt_set_proxiable (opt, b); + + krb5_appdefault_time(context, appname, realm, "ticket_lifetime", 0, &t); + if (t == 0) + t = get_config_time (context, realm, "ticket_lifetime", 0); + if(t != 0) + krb5_get_init_creds_opt_set_tkt_life(opt, t); + + krb5_appdefault_time(context, appname, realm, "renew_lifetime", 0, &t); + if (t == 0) + t = get_config_time (context, realm, "renew_lifetime", 0); + if(t != 0) + krb5_get_init_creds_opt_set_renew_life(opt, t); + + krb5_appdefault_boolean(context, appname, realm, "no-addresses", + KRB5_ADDRESSLESS_DEFAULT, &b); + krb5_get_init_creds_opt_set_addressless (context, opt, b); + +#if 0 + krb5_appdefault_boolean(context, appname, realm, "anonymous", FALSE, &b); + krb5_get_init_creds_opt_set_anonymous (opt, b); + + krb5_get_init_creds_opt_set_etype_list(opt, enctype, + etype_str.num_strings); + + krb5_get_init_creds_opt_set_salt(krb5_get_init_creds_opt *opt, + krb5_data *salt); + + krb5_get_init_creds_opt_set_preauth_list(krb5_get_init_creds_opt *opt, + krb5_preauthtype *preauth_list, + int preauth_list_length); +#endif +} + + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_tkt_life(krb5_get_init_creds_opt *opt, + krb5_deltat tkt_life) +{ + opt->flags |= KRB5_GET_INIT_CREDS_OPT_TKT_LIFE; + opt->tkt_life = tkt_life; +} + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_renew_life(krb5_get_init_creds_opt *opt, + krb5_deltat renew_life) +{ + opt->flags |= KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE; + opt->renew_life = renew_life; +} + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_forwardable(krb5_get_init_creds_opt *opt, + int forwardable) +{ + opt->flags |= KRB5_GET_INIT_CREDS_OPT_FORWARDABLE; + opt->forwardable = forwardable; +} + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_proxiable(krb5_get_init_creds_opt *opt, + int proxiable) +{ + opt->flags |= KRB5_GET_INIT_CREDS_OPT_PROXIABLE; + opt->proxiable = proxiable; +} + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_etype_list(krb5_get_init_creds_opt *opt, + krb5_enctype *etype_list, + int etype_list_length) +{ + opt->flags |= KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST; + opt->etype_list = etype_list; + opt->etype_list_length = etype_list_length; +} + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_address_list(krb5_get_init_creds_opt *opt, + krb5_addresses *addresses) +{ + opt->flags |= KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST; + opt->address_list = addresses; +} + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_preauth_list(krb5_get_init_creds_opt *opt, + krb5_preauthtype *preauth_list, + int preauth_list_length) +{ + opt->flags |= KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST; + opt->preauth_list_length = preauth_list_length; + opt->preauth_list = preauth_list; +} + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_salt(krb5_get_init_creds_opt *opt, + krb5_data *salt) +{ + opt->flags |= KRB5_GET_INIT_CREDS_OPT_SALT; + opt->salt = salt; +} + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_anonymous(krb5_get_init_creds_opt *opt, + int anonymous) +{ + opt->flags |= KRB5_GET_INIT_CREDS_OPT_ANONYMOUS; + opt->anonymous = anonymous; +} + +static krb5_error_code +require_ext_opt(krb5_context context, + krb5_get_init_creds_opt *opt, + const char *type) +{ + if (opt->opt_private == NULL) { + krb5_set_error_string(context, "%s on non extendable opt", type); + return EINVAL; + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_pa_password(krb5_context context, + krb5_get_init_creds_opt *opt, + const char *password, + krb5_s2k_proc key_proc) +{ + krb5_error_code ret; + ret = require_ext_opt(context, opt, "init_creds_opt_set_pa_password"); + if (ret) + return ret; + opt->opt_private->password = password; + opt->opt_private->key_proc = key_proc; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_pac_request(krb5_context context, + krb5_get_init_creds_opt *opt, + krb5_boolean req_pac) +{ + krb5_error_code ret; + ret = require_ext_opt(context, opt, "init_creds_opt_set_pac_req"); + if (ret) + return ret; + opt->opt_private->req_pac = req_pac ? + KRB5_INIT_CREDS_TRISTATE_TRUE : + KRB5_INIT_CREDS_TRISTATE_FALSE; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_get_error(krb5_context context, + krb5_get_init_creds_opt *opt, + KRB_ERROR **error) +{ + krb5_error_code ret; + + *error = NULL; + + ret = require_ext_opt(context, opt, "init_creds_opt_get_error"); + if (ret) + return ret; + + if (opt->opt_private->error == NULL) + return 0; + + *error = malloc(sizeof(**error)); + if (*error == NULL) { + krb5_set_error_string(context, "malloc - out memory"); + return ENOMEM; + } + + ret = copy_KRB_ERROR(opt->opt_private->error, *error); + if (ret) + krb5_clear_error_string(context); + + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_addressless(krb5_context context, + krb5_get_init_creds_opt *opt, + krb5_boolean addressless) +{ + krb5_error_code ret; + ret = require_ext_opt(context, opt, "init_creds_opt_set_pac_req"); + if (ret) + return ret; + if (addressless) + opt->opt_private->addressless = KRB5_INIT_CREDS_TRISTATE_TRUE; + else + opt->opt_private->addressless = KRB5_INIT_CREDS_TRISTATE_FALSE; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_canonicalize(krb5_context context, + krb5_get_init_creds_opt *opt, + krb5_boolean req) +{ + krb5_error_code ret; + ret = require_ext_opt(context, opt, "init_creds_opt_set_canonicalize"); + if (ret) + return ret; + if (req) + opt->opt_private->flags |= KRB5_INIT_CREDS_CANONICALIZE; + else + opt->opt_private->flags &= ~KRB5_INIT_CREDS_CANONICALIZE; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_win2k(krb5_context context, + krb5_get_init_creds_opt *opt, + krb5_boolean req) +{ + krb5_error_code ret; + ret = require_ext_opt(context, opt, "init_creds_opt_set_win2k"); + if (ret) + return ret; + if (req) + opt->opt_private->flags |= KRB5_INIT_CREDS_NO_C_CANON_CHECK; + else + opt->opt_private->flags &= ~KRB5_INIT_CREDS_NO_C_CANON_CHECK; + return 0; +} + diff --git a/lib/krb5/init_creds_pw.c b/lib/krb5/init_creds_pw.c new file mode 100644 index 0000000..441adff --- /dev/null +++ b/lib/krb5/init_creds_pw.c @@ -0,0 +1,1658 @@ +/* + * Copyright (c) 1997 - 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: init_creds_pw.c 21931 2007-08-27 14:11:55Z lha $"); + +typedef struct krb5_get_init_creds_ctx { + KDCOptions flags; + krb5_creds cred; + krb5_addresses *addrs; + krb5_enctype *etypes; + krb5_preauthtype *pre_auth_types; + const char *in_tkt_service; + unsigned nonce; + unsigned pk_nonce; + + krb5_data req_buffer; + AS_REQ as_req; + int pa_counter; + + const char *password; + krb5_s2k_proc key_proc; + + krb5_get_init_creds_tristate req_pac; + + krb5_pk_init_ctx pk_init_ctx; + int ic_flags; +} krb5_get_init_creds_ctx; + +static krb5_error_code +default_s2k_func(krb5_context context, krb5_enctype type, + krb5_const_pointer keyseed, + krb5_salt salt, krb5_data *s2kparms, + krb5_keyblock **key) +{ + krb5_error_code ret; + krb5_data password; + krb5_data opaque; + + password.data = rk_UNCONST(keyseed); + password.length = strlen(keyseed); + if (s2kparms) + opaque = *s2kparms; + else + krb5_data_zero(&opaque); + + *key = malloc(sizeof(**key)); + if (*key == NULL) + return ENOMEM; + ret = krb5_string_to_key_data_salt_opaque(context, type, password, + salt, opaque, *key); + if (ret) { + free(*key); + *key = NULL; + } + return ret; +} + +static void +free_init_creds_ctx(krb5_context context, krb5_get_init_creds_ctx *ctx) +{ + if (ctx->etypes) + free(ctx->etypes); + if (ctx->pre_auth_types) + free (ctx->pre_auth_types); + free_AS_REQ(&ctx->as_req); + memset(&ctx->as_req, 0, sizeof(ctx->as_req)); +} + +static int +get_config_time (krb5_context context, + const char *realm, + const char *name, + int def) +{ + int ret; + + ret = krb5_config_get_time (context, NULL, + "realms", + realm, + name, + NULL); + if (ret >= 0) + return ret; + ret = krb5_config_get_time (context, NULL, + "libdefaults", + name, + NULL); + if (ret >= 0) + return ret; + return def; +} + +static krb5_error_code +init_cred (krb5_context context, + krb5_creds *cred, + krb5_principal client, + krb5_deltat start_time, + const char *in_tkt_service, + krb5_get_init_creds_opt *options) +{ + krb5_error_code ret; + krb5_const_realm client_realm; + int tmp; + krb5_timestamp now; + + krb5_timeofday (context, &now); + + memset (cred, 0, sizeof(*cred)); + + if (client) + krb5_copy_principal(context, client, &cred->client); + else { + ret = krb5_get_default_principal (context, + &cred->client); + if (ret) + goto out; + } + + client_realm = krb5_principal_get_realm (context, cred->client); + + if (start_time) + cred->times.starttime = now + start_time; + + if (options->flags & KRB5_GET_INIT_CREDS_OPT_TKT_LIFE) + tmp = options->tkt_life; + else + tmp = 10 * 60 * 60; + cred->times.endtime = now + tmp; + + if ((options->flags & KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE) && + options->renew_life > 0) { + cred->times.renew_till = now + options->renew_life; + } + + if (in_tkt_service) { + krb5_realm server_realm; + + ret = krb5_parse_name (context, in_tkt_service, &cred->server); + if (ret) + goto out; + server_realm = strdup (client_realm); + free (*krb5_princ_realm(context, cred->server)); + krb5_princ_set_realm (context, cred->server, &server_realm); + } else { + ret = krb5_make_principal(context, &cred->server, + client_realm, KRB5_TGS_NAME, client_realm, + NULL); + if (ret) + goto out; + } + return 0; + +out: + krb5_free_cred_contents (context, cred); + return ret; +} + +/* + * Print a message (str) to the user about the expiration in `lr' + */ + +static void +report_expiration (krb5_context context, + krb5_prompter_fct prompter, + krb5_data *data, + const char *str, + time_t now) +{ + char *p; + + asprintf (&p, "%s%s", str, ctime(&now)); + (*prompter) (context, data, NULL, p, 0, NULL); + free (p); +} + +/* + * Parse the last_req data and show it to the user if it's interesting + */ + +static void +print_expire (krb5_context context, + krb5_const_realm realm, + krb5_kdc_rep *rep, + krb5_prompter_fct prompter, + krb5_data *data) +{ + int i; + LastReq *lr = &rep->enc_part.last_req; + krb5_timestamp sec; + time_t t; + krb5_boolean reported = FALSE; + + krb5_timeofday (context, &sec); + + t = sec + get_config_time (context, + realm, + "warn_pwexpire", + 7 * 24 * 60 * 60); + + for (i = 0; i < lr->len; ++i) { + if (lr->val[i].lr_value <= t) { + switch (abs(lr->val[i].lr_type)) { + case LR_PW_EXPTIME : + report_expiration(context, prompter, data, + "Your password will expire at ", + lr->val[i].lr_value); + reported = TRUE; + break; + case LR_ACCT_EXPTIME : + report_expiration(context, prompter, data, + "Your account will expire at ", + lr->val[i].lr_value); + reported = TRUE; + break; + } + } + } + + if (!reported + && rep->enc_part.key_expiration + && *rep->enc_part.key_expiration <= t) { + report_expiration(context, prompter, data, + "Your password/account will expire at ", + *rep->enc_part.key_expiration); + } +} + +static krb5_addresses no_addrs = { 0, NULL }; + +static krb5_error_code +get_init_creds_common(krb5_context context, + krb5_principal client, + krb5_deltat start_time, + const char *in_tkt_service, + krb5_get_init_creds_opt *options, + krb5_get_init_creds_ctx *ctx) +{ + krb5_get_init_creds_opt default_opt; + krb5_error_code ret; + krb5_enctype *etypes; + krb5_preauthtype *pre_auth_types; + + memset(ctx, 0, sizeof(*ctx)); + + if (options == NULL) { + krb5_get_init_creds_opt_init (&default_opt); + options = &default_opt; + } else { + _krb5_get_init_creds_opt_free_krb5_error(options); + } + + if (options->opt_private) { + ctx->password = options->opt_private->password; + ctx->key_proc = options->opt_private->key_proc; + ctx->req_pac = options->opt_private->req_pac; + ctx->pk_init_ctx = options->opt_private->pk_init_ctx; + ctx->ic_flags = options->opt_private->flags; + } else + ctx->req_pac = KRB5_INIT_CREDS_TRISTATE_UNSET; + + if (ctx->key_proc == NULL) + ctx->key_proc = default_s2k_func; + + if (ctx->ic_flags & KRB5_INIT_CREDS_CANONICALIZE) + ctx->flags.canonicalize = 1; + + ctx->pre_auth_types = NULL; + ctx->addrs = NULL; + ctx->etypes = NULL; + ctx->pre_auth_types = NULL; + ctx->in_tkt_service = in_tkt_service; + + ret = init_cred (context, &ctx->cred, client, start_time, + in_tkt_service, options); + if (ret) + return ret; + + if (options->flags & KRB5_GET_INIT_CREDS_OPT_FORWARDABLE) + ctx->flags.forwardable = options->forwardable; + + if (options->flags & KRB5_GET_INIT_CREDS_OPT_PROXIABLE) + ctx->flags.proxiable = options->proxiable; + + if (start_time) + ctx->flags.postdated = 1; + if (ctx->cred.times.renew_till) + ctx->flags.renewable = 1; + if (options->flags & KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST) { + ctx->addrs = options->address_list; + } else if (options->opt_private) { + switch (options->opt_private->addressless) { + case KRB5_INIT_CREDS_TRISTATE_UNSET: +#if KRB5_ADDRESSLESS_DEFAULT == TRUE + ctx->addrs = &no_addrs; +#else + ctx->addrs = NULL; +#endif + break; + case KRB5_INIT_CREDS_TRISTATE_FALSE: + ctx->addrs = NULL; + break; + case KRB5_INIT_CREDS_TRISTATE_TRUE: + ctx->addrs = &no_addrs; + break; + } + } + if (options->flags & KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST) { + etypes = malloc((options->etype_list_length + 1) + * sizeof(krb5_enctype)); + if (etypes == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + memcpy (etypes, options->etype_list, + options->etype_list_length * sizeof(krb5_enctype)); + etypes[options->etype_list_length] = ETYPE_NULL; + ctx->etypes = etypes; + } + if (options->flags & KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST) { + pre_auth_types = malloc((options->preauth_list_length + 1) + * sizeof(krb5_preauthtype)); + if (pre_auth_types == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + memcpy (pre_auth_types, options->preauth_list, + options->preauth_list_length * sizeof(krb5_preauthtype)); + pre_auth_types[options->preauth_list_length] = KRB5_PADATA_NONE; + ctx->pre_auth_types = pre_auth_types; + } + if (options->flags & KRB5_GET_INIT_CREDS_OPT_SALT) + ; /* XXX */ + if (options->flags & KRB5_GET_INIT_CREDS_OPT_ANONYMOUS) + ctx->flags.request_anonymous = options->anonymous; + return 0; +} + +static krb5_error_code +change_password (krb5_context context, + krb5_principal client, + const char *password, + char *newpw, + size_t newpw_sz, + krb5_prompter_fct prompter, + void *data, + krb5_get_init_creds_opt *old_options) +{ + krb5_prompt prompts[2]; + krb5_error_code ret; + krb5_creds cpw_cred; + char buf1[BUFSIZ], buf2[BUFSIZ]; + krb5_data password_data[2]; + int result_code; + krb5_data result_code_string; + krb5_data result_string; + char *p; + krb5_get_init_creds_opt options; + + memset (&cpw_cred, 0, sizeof(cpw_cred)); + + krb5_get_init_creds_opt_init (&options); + krb5_get_init_creds_opt_set_tkt_life (&options, 60); + krb5_get_init_creds_opt_set_forwardable (&options, FALSE); + krb5_get_init_creds_opt_set_proxiable (&options, FALSE); + if (old_options && old_options->flags & KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST) + krb5_get_init_creds_opt_set_preauth_list (&options, + old_options->preauth_list, + old_options->preauth_list_length); + + krb5_data_zero (&result_code_string); + krb5_data_zero (&result_string); + + ret = krb5_get_init_creds_password (context, + &cpw_cred, + client, + password, + prompter, + data, + 0, + "kadmin/changepw", + &options); + if (ret) + goto out; + + for(;;) { + password_data[0].data = buf1; + password_data[0].length = sizeof(buf1); + + prompts[0].hidden = 1; + prompts[0].prompt = "New password: "; + prompts[0].reply = &password_data[0]; + prompts[0].type = KRB5_PROMPT_TYPE_NEW_PASSWORD; + + password_data[1].data = buf2; + password_data[1].length = sizeof(buf2); + + prompts[1].hidden = 1; + prompts[1].prompt = "Repeat new password: "; + prompts[1].reply = &password_data[1]; + prompts[1].type = KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN; + + ret = (*prompter) (context, data, NULL, "Changing password", + 2, prompts); + if (ret) { + memset (buf1, 0, sizeof(buf1)); + memset (buf2, 0, sizeof(buf2)); + goto out; + } + + if (strcmp (buf1, buf2) == 0) + break; + memset (buf1, 0, sizeof(buf1)); + memset (buf2, 0, sizeof(buf2)); + } + + ret = krb5_change_password (context, + &cpw_cred, + buf1, + &result_code, + &result_code_string, + &result_string); + if (ret) + goto out; + asprintf (&p, "%s: %.*s\n", + result_code ? "Error" : "Success", + (int)result_string.length, + result_string.length > 0 ? (char*)result_string.data : ""); + + ret = (*prompter) (context, data, NULL, p, 0, NULL); + free (p); + if (result_code == 0) { + strlcpy (newpw, buf1, newpw_sz); + ret = 0; + } else { + krb5_set_error_string (context, "failed changing password"); + ret = ENOTTY; + } + +out: + memset (buf1, 0, sizeof(buf1)); + memset (buf2, 0, sizeof(buf2)); + krb5_data_free (&result_string); + krb5_data_free (&result_code_string); + krb5_free_cred_contents (context, &cpw_cred); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_keyblock_key_proc (krb5_context context, + krb5_keytype type, + krb5_data *salt, + krb5_const_pointer keyseed, + krb5_keyblock **key) +{ + return krb5_copy_keyblock (context, keyseed, key); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_keytab(krb5_context context, + krb5_creds *creds, + krb5_principal client, + krb5_keytab keytab, + krb5_deltat start_time, + const char *in_tkt_service, + krb5_get_init_creds_opt *options) +{ + krb5_get_init_creds_ctx ctx; + krb5_error_code ret; + krb5_keytab_key_proc_args *a; + + ret = get_init_creds_common(context, client, start_time, + in_tkt_service, options, &ctx); + if (ret) + goto out; + + a = malloc (sizeof(*a)); + if (a == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + ret = ENOMEM; + goto out; + } + a->principal = ctx.cred.client; + a->keytab = keytab; + + ret = krb5_get_in_cred (context, + KDCOptions2int(ctx.flags), + ctx.addrs, + ctx.etypes, + ctx.pre_auth_types, + NULL, + krb5_keytab_key_proc, + a, + NULL, + NULL, + &ctx.cred, + NULL); + free (a); + + if (ret == 0 && creds) + *creds = ctx.cred; + else + krb5_free_cred_contents (context, &ctx.cred); + + out: + free_init_creds_ctx(context, &ctx); + return ret; +} + +/* + * + */ + +static krb5_error_code +init_creds_init_as_req (krb5_context context, + KDCOptions opts, + const krb5_creds *creds, + const krb5_addresses *addrs, + const krb5_enctype *etypes, + AS_REQ *a) +{ + krb5_error_code ret; + + memset(a, 0, sizeof(*a)); + + a->pvno = 5; + a->msg_type = krb_as_req; + a->req_body.kdc_options = opts; + a->req_body.cname = malloc(sizeof(*a->req_body.cname)); + if (a->req_body.cname == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto fail; + } + a->req_body.sname = malloc(sizeof(*a->req_body.sname)); + if (a->req_body.sname == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto fail; + } + + ret = _krb5_principal2principalname (a->req_body.cname, creds->client); + if (ret) + goto fail; + ret = copy_Realm(&creds->client->realm, &a->req_body.realm); + if (ret) + goto fail; + + ret = _krb5_principal2principalname (a->req_body.sname, creds->server); + if (ret) + goto fail; + + if(creds->times.starttime) { + a->req_body.from = malloc(sizeof(*a->req_body.from)); + if (a->req_body.from == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto fail; + } + *a->req_body.from = creds->times.starttime; + } + if(creds->times.endtime){ + ALLOC(a->req_body.till, 1); + *a->req_body.till = creds->times.endtime; + } + if(creds->times.renew_till){ + a->req_body.rtime = malloc(sizeof(*a->req_body.rtime)); + if (a->req_body.rtime == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto fail; + } + *a->req_body.rtime = creds->times.renew_till; + } + a->req_body.nonce = 0; + ret = krb5_init_etype (context, + &a->req_body.etype.len, + &a->req_body.etype.val, + etypes); + if (ret) + goto fail; + + /* + * This means no addresses + */ + + if (addrs && addrs->len == 0) { + a->req_body.addresses = NULL; + } else { + a->req_body.addresses = malloc(sizeof(*a->req_body.addresses)); + if (a->req_body.addresses == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto fail; + } + + if (addrs) + ret = krb5_copy_addresses(context, addrs, a->req_body.addresses); + else { + ret = krb5_get_all_client_addrs (context, a->req_body.addresses); + if(ret == 0 && a->req_body.addresses->len == 0) { + free(a->req_body.addresses); + a->req_body.addresses = NULL; + } + } + if (ret) + goto fail; + } + + a->req_body.enc_authorization_data = NULL; + a->req_body.additional_tickets = NULL; + + a->padata = NULL; + + return 0; + fail: + free_AS_REQ(a); + memset(a, 0, sizeof(*a)); + return ret; +} + +struct pa_info_data { + krb5_enctype etype; + krb5_salt salt; + krb5_data *s2kparams; +}; + +static void +free_paid(krb5_context context, struct pa_info_data *ppaid) +{ + krb5_free_salt(context, ppaid->salt); + if (ppaid->s2kparams) + krb5_free_data(context, ppaid->s2kparams); +} + + +static krb5_error_code +set_paid(struct pa_info_data *paid, krb5_context context, + krb5_enctype etype, + krb5_salttype salttype, void *salt_string, size_t salt_len, + krb5_data *s2kparams) +{ + paid->etype = etype; + paid->salt.salttype = salttype; + paid->salt.saltvalue.data = malloc(salt_len + 1); + if (paid->salt.saltvalue.data == NULL) { + krb5_clear_error_string(context); + return ENOMEM; + } + memcpy(paid->salt.saltvalue.data, salt_string, salt_len); + ((char *)paid->salt.saltvalue.data)[salt_len] = '\0'; + paid->salt.saltvalue.length = salt_len; + if (s2kparams) { + krb5_error_code ret; + + ret = krb5_copy_data(context, s2kparams, &paid->s2kparams); + if (ret) { + krb5_clear_error_string(context); + krb5_free_salt(context, paid->salt); + return ret; + } + } else + paid->s2kparams = NULL; + + return 0; +} + +static struct pa_info_data * +pa_etype_info2(krb5_context context, + const krb5_principal client, + const AS_REQ *asreq, + struct pa_info_data *paid, + heim_octet_string *data) +{ + krb5_error_code ret; + ETYPE_INFO2 e; + size_t sz; + int i, j; + + memset(&e, 0, sizeof(e)); + ret = decode_ETYPE_INFO2(data->data, data->length, &e, &sz); + if (ret) + goto out; + if (e.len == 0) + goto out; + for (j = 0; j < asreq->req_body.etype.len; j++) { + for (i = 0; i < e.len; i++) { + if (asreq->req_body.etype.val[j] == e.val[i].etype) { + krb5_salt salt; + if (e.val[i].salt == NULL) + ret = krb5_get_pw_salt(context, client, &salt); + else { + salt.saltvalue.data = *e.val[i].salt; + salt.saltvalue.length = strlen(*e.val[i].salt); + ret = 0; + } + if (ret == 0) + ret = set_paid(paid, context, e.val[i].etype, + KRB5_PW_SALT, + salt.saltvalue.data, + salt.saltvalue.length, + e.val[i].s2kparams); + if (e.val[i].salt == NULL) + krb5_free_salt(context, salt); + if (ret == 0) { + free_ETYPE_INFO2(&e); + return paid; + } + } + } + } + out: + free_ETYPE_INFO2(&e); + return NULL; +} + +static struct pa_info_data * +pa_etype_info(krb5_context context, + const krb5_principal client, + const AS_REQ *asreq, + struct pa_info_data *paid, + heim_octet_string *data) +{ + krb5_error_code ret; + ETYPE_INFO e; + size_t sz; + int i, j; + + memset(&e, 0, sizeof(e)); + ret = decode_ETYPE_INFO(data->data, data->length, &e, &sz); + if (ret) + goto out; + if (e.len == 0) + goto out; + for (j = 0; j < asreq->req_body.etype.len; j++) { + for (i = 0; i < e.len; i++) { + if (asreq->req_body.etype.val[j] == e.val[i].etype) { + krb5_salt salt; + salt.salttype = KRB5_PW_SALT; + if (e.val[i].salt == NULL) + ret = krb5_get_pw_salt(context, client, &salt); + else { + salt.saltvalue = *e.val[i].salt; + ret = 0; + } + if (e.val[i].salttype) + salt.salttype = *e.val[i].salttype; + if (ret == 0) { + ret = set_paid(paid, context, e.val[i].etype, + salt.salttype, + salt.saltvalue.data, + salt.saltvalue.length, + NULL); + if (e.val[i].salt == NULL) + krb5_free_salt(context, salt); + } + if (ret == 0) { + free_ETYPE_INFO(&e); + return paid; + } + } + } + } + out: + free_ETYPE_INFO(&e); + return NULL; +} + +static struct pa_info_data * +pa_pw_or_afs3_salt(krb5_context context, + const krb5_principal client, + const AS_REQ *asreq, + struct pa_info_data *paid, + heim_octet_string *data) +{ + krb5_error_code ret; + if (paid->etype == ENCTYPE_NULL) + return NULL; + ret = set_paid(paid, context, + paid->etype, + paid->salt.salttype, + data->data, + data->length, + NULL); + if (ret) + return NULL; + return paid; +} + + +struct pa_info { + krb5_preauthtype type; + struct pa_info_data *(*salt_info)(krb5_context, + const krb5_principal, + const AS_REQ *, + struct pa_info_data *, + heim_octet_string *); +}; + +static struct pa_info pa_prefs[] = { + { KRB5_PADATA_ETYPE_INFO2, pa_etype_info2 }, + { KRB5_PADATA_ETYPE_INFO, pa_etype_info }, + { KRB5_PADATA_PW_SALT, pa_pw_or_afs3_salt }, + { KRB5_PADATA_AFS3_SALT, pa_pw_or_afs3_salt } +}; + +static PA_DATA * +find_pa_data(const METHOD_DATA *md, int type) +{ + int i; + if (md == NULL) + return NULL; + for (i = 0; i < md->len; i++) + if (md->val[i].padata_type == type) + return &md->val[i]; + return NULL; +} + +static struct pa_info_data * +process_pa_info(krb5_context context, + const krb5_principal client, + const AS_REQ *asreq, + struct pa_info_data *paid, + METHOD_DATA *md) +{ + struct pa_info_data *p = NULL; + int i; + + for (i = 0; p == NULL && i < sizeof(pa_prefs)/sizeof(pa_prefs[0]); i++) { + PA_DATA *pa = find_pa_data(md, pa_prefs[i].type); + if (pa == NULL) + continue; + paid->salt.salttype = pa_prefs[i].type; + p = (*pa_prefs[i].salt_info)(context, client, asreq, + paid, &pa->padata_value); + } + return p; +} + +static krb5_error_code +make_pa_enc_timestamp(krb5_context context, METHOD_DATA *md, + krb5_enctype etype, krb5_keyblock *key) +{ + 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_crypto crypto; + + 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_crypto_init(context, key, 0, &crypto); + if (ret) { + free(buf); + return ret; + } + ret = krb5_encrypt_EncryptedData(context, + crypto, + KRB5_KU_PA_ENC_TIMESTAMP, + buf, + len, + 0, + &encdata); + free(buf); + krb5_crypto_destroy(context, crypto); + 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_ENC_TIMESTAMP, buf, len); + if (ret) + free(buf); + return ret; +} + +static krb5_error_code +add_enc_ts_padata(krb5_context context, + METHOD_DATA *md, + krb5_principal client, + krb5_s2k_proc key_proc, + krb5_const_pointer keyseed, + krb5_enctype *enctypes, + unsigned netypes, + krb5_salt *salt, + krb5_data *s2kparams) +{ + krb5_error_code ret; + krb5_salt salt2; + krb5_enctype *ep; + int i; + + if(salt == NULL) { + /* default to standard salt */ + ret = krb5_get_pw_salt (context, client, &salt2); + salt = &salt2; + } + if (!enctypes) { + enctypes = context->etypes; + netypes = 0; + for (ep = enctypes; *ep != ETYPE_NULL; ep++) + netypes++; + } + + for (i = 0; i < netypes; ++i) { + krb5_keyblock *key; + + ret = (*key_proc)(context, enctypes[i], keyseed, + *salt, s2kparams, &key); + if (ret) + continue; + ret = make_pa_enc_timestamp (context, md, enctypes[i], key); + krb5_free_keyblock (context, key); + if (ret) + return ret; + } + if(salt == &salt2) + krb5_free_salt(context, salt2); + return 0; +} + +static krb5_error_code +pa_data_to_md_ts_enc(krb5_context context, + const AS_REQ *a, + const krb5_principal client, + krb5_get_init_creds_ctx *ctx, + struct pa_info_data *ppaid, + METHOD_DATA *md) +{ + if (ctx->key_proc == NULL || ctx->password == NULL) + return 0; + + if (ppaid) { + add_enc_ts_padata(context, md, client, + ctx->key_proc, ctx->password, + &ppaid->etype, 1, + &ppaid->salt, ppaid->s2kparams); + } else { + krb5_salt salt; + + /* make a v5 salted pa-data */ + add_enc_ts_padata(context, md, client, + ctx->key_proc, ctx->password, + a->req_body.etype.val, a->req_body.etype.len, + NULL, NULL); + + /* make a v4 salted pa-data */ + salt.salttype = KRB5_PW_SALT; + krb5_data_zero(&salt.saltvalue); + add_enc_ts_padata(context, md, client, + ctx->key_proc, ctx->password, + a->req_body.etype.val, a->req_body.etype.len, + &salt, NULL); + } + return 0; +} + +static krb5_error_code +pa_data_to_key_plain(krb5_context context, + const krb5_principal client, + krb5_get_init_creds_ctx *ctx, + krb5_salt salt, + krb5_data *s2kparams, + krb5_enctype etype, + krb5_keyblock **key) +{ + krb5_error_code ret; + + ret = (*ctx->key_proc)(context, etype, ctx->password, + salt, s2kparams, key); + return ret; +} + + +static krb5_error_code +pa_data_to_md_pkinit(krb5_context context, + const AS_REQ *a, + const krb5_principal client, + krb5_get_init_creds_ctx *ctx, + METHOD_DATA *md) +{ + if (ctx->pk_init_ctx == NULL) + return 0; +#ifdef PKINIT + return _krb5_pk_mk_padata(context, + ctx->pk_init_ctx, + &a->req_body, + ctx->pk_nonce, + md); +#else + krb5_set_error_string(context, "no support for PKINIT compiled in"); + return EINVAL; +#endif +} + +static krb5_error_code +pa_data_add_pac_request(krb5_context context, + krb5_get_init_creds_ctx *ctx, + METHOD_DATA *md) +{ + size_t len, length; + krb5_error_code ret; + PA_PAC_REQUEST req; + void *buf; + + switch (ctx->req_pac) { + case KRB5_INIT_CREDS_TRISTATE_UNSET: + return 0; /* don't bother */ + case KRB5_INIT_CREDS_TRISTATE_TRUE: + req.include_pac = 1; + break; + case KRB5_INIT_CREDS_TRISTATE_FALSE: + req.include_pac = 0; + } + + ASN1_MALLOC_ENCODE(PA_PAC_REQUEST, buf, length, + &req, &len, ret); + if (ret) + return ret; + if(len != length) + krb5_abortx(context, "internal error in ASN.1 encoder"); + + ret = krb5_padata_add(context, md, KRB5_PADATA_PA_PAC_REQUEST, buf, len); + if (ret) + free(buf); + + return 0; +} + +/* + * Assumes caller always will free `out_md', even on error. + */ + +static krb5_error_code +process_pa_data_to_md(krb5_context context, + const krb5_creds *creds, + const AS_REQ *a, + krb5_get_init_creds_ctx *ctx, + METHOD_DATA *in_md, + METHOD_DATA **out_md, + krb5_prompter_fct prompter, + void *prompter_data) +{ + krb5_error_code ret; + + ALLOC(*out_md, 1); + if (*out_md == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + (*out_md)->len = 0; + (*out_md)->val = NULL; + + /* + * Make sure we don't sent both ENC-TS and PK-INIT pa data, no + * need to expose our password protecting our PKCS12 key. + */ + + if (ctx->pk_init_ctx) { + + ret = pa_data_to_md_pkinit(context, a, creds->client, ctx, *out_md); + if (ret) + return ret; + + } else if (in_md->len != 0) { + struct pa_info_data paid, *ppaid; + + memset(&paid, 0, sizeof(paid)); + + paid.etype = ENCTYPE_NULL; + ppaid = process_pa_info(context, creds->client, a, &paid, in_md); + + pa_data_to_md_ts_enc(context, a, creds->client, ctx, ppaid, *out_md); + if (ppaid) + free_paid(context, ppaid); + } + + pa_data_add_pac_request(context, ctx, *out_md); + + if ((*out_md)->len == 0) { + free(*out_md); + *out_md = NULL; + } + + return 0; +} + +static krb5_error_code +process_pa_data_to_key(krb5_context context, + krb5_get_init_creds_ctx *ctx, + krb5_creds *creds, + AS_REQ *a, + krb5_kdc_rep *rep, + const krb5_krbhst_info *hi, + krb5_keyblock **key) +{ + struct pa_info_data paid, *ppaid = NULL; + krb5_error_code ret; + krb5_enctype etype; + PA_DATA *pa; + + memset(&paid, 0, sizeof(paid)); + + etype = rep->kdc_rep.enc_part.etype; + + if (rep->kdc_rep.padata) { + paid.etype = etype; + ppaid = process_pa_info(context, creds->client, a, &paid, + rep->kdc_rep.padata); + } + if (ppaid == NULL) { + ret = krb5_get_pw_salt (context, creds->client, &paid.salt); + if (ret) + return ret; + paid.etype = etype; + paid.s2kparams = NULL; + } + + pa = NULL; + if (rep->kdc_rep.padata) { + int idx = 0; + pa = krb5_find_padata(rep->kdc_rep.padata->val, + rep->kdc_rep.padata->len, + KRB5_PADATA_PK_AS_REP, + &idx); + if (pa == NULL) { + idx = 0; + pa = krb5_find_padata(rep->kdc_rep.padata->val, + rep->kdc_rep.padata->len, + KRB5_PADATA_PK_AS_REP_19, + &idx); + } + } + if (pa && ctx->pk_init_ctx) { +#ifdef PKINIT + ret = _krb5_pk_rd_pa_reply(context, + a->req_body.realm, + ctx->pk_init_ctx, + etype, + hi, + ctx->pk_nonce, + &ctx->req_buffer, + pa, + key); +#else + krb5_set_error_string(context, "no support for PKINIT compiled in"); + ret = EINVAL; +#endif + } else if (ctx->password) + ret = pa_data_to_key_plain(context, creds->client, ctx, + paid.salt, paid.s2kparams, etype, key); + else { + krb5_set_error_string(context, "No usable pa data type"); + ret = EINVAL; + } + + free_paid(context, &paid); + return ret; +} + +static krb5_error_code +init_cred_loop(krb5_context context, + krb5_get_init_creds_opt *init_cred_opts, + const krb5_prompter_fct prompter, + void *prompter_data, + krb5_get_init_creds_ctx *ctx, + krb5_creds *creds, + krb5_kdc_rep *ret_as_reply) +{ + krb5_error_code ret; + krb5_kdc_rep rep; + METHOD_DATA md; + krb5_data resp; + size_t len; + size_t size; + krb5_krbhst_info *hi = NULL; + krb5_sendto_ctx stctx = NULL; + + + memset(&md, 0, sizeof(md)); + memset(&rep, 0, sizeof(rep)); + + _krb5_get_init_creds_opt_free_krb5_error(init_cred_opts); + + if (ret_as_reply) + memset(ret_as_reply, 0, sizeof(*ret_as_reply)); + + ret = init_creds_init_as_req(context, ctx->flags, creds, + ctx->addrs, ctx->etypes, &ctx->as_req); + if (ret) + return ret; + + ret = krb5_sendto_ctx_alloc(context, &stctx); + if (ret) + goto out; + krb5_sendto_ctx_set_func(stctx, _krb5_kdc_retry, NULL); + + /* Set a new nonce. */ + krb5_generate_random_block (&ctx->nonce, sizeof(ctx->nonce)); + ctx->nonce &= 0xffffffff; + /* XXX these just needs to be the same when using Windows PK-INIT */ + ctx->pk_nonce = ctx->nonce; + + /* + * Increase counter when we want other pre-auth types then + * KRB5_PA_ENC_TIMESTAMP. + */ +#define MAX_PA_COUNTER 3 + + ctx->pa_counter = 0; + while (ctx->pa_counter < MAX_PA_COUNTER) { + + ctx->pa_counter++; + + if (ctx->as_req.padata) { + free_METHOD_DATA(ctx->as_req.padata); + free(ctx->as_req.padata); + ctx->as_req.padata = NULL; + } + + /* Set a new nonce. */ + ctx->as_req.req_body.nonce = ctx->nonce; + + /* fill_in_md_data */ + ret = process_pa_data_to_md(context, creds, &ctx->as_req, ctx, + &md, &ctx->as_req.padata, + prompter, prompter_data); + if (ret) + goto out; + + krb5_data_free(&ctx->req_buffer); + + ASN1_MALLOC_ENCODE(AS_REQ, + ctx->req_buffer.data, ctx->req_buffer.length, + &ctx->as_req, &len, ret); + if (ret) + goto out; + if(len != ctx->req_buffer.length) + krb5_abortx(context, "internal error in ASN.1 encoder"); + + ret = krb5_sendto_context (context, stctx, &ctx->req_buffer, + creds->client->realm, &resp); + if (ret) + goto out; + + memset (&rep, 0, sizeof(rep)); + ret = decode_AS_REP(resp.data, resp.length, &rep.kdc_rep, &size); + if (ret == 0) { + krb5_data_free(&resp); + krb5_clear_error_string(context); + break; + } else { + /* let's try to parse it as a KRB-ERROR */ + KRB_ERROR error; + + ret = krb5_rd_error(context, &resp, &error); + if(ret && resp.data && ((char*)resp.data)[0] == 4) + ret = KRB5KRB_AP_ERR_V4_REPLY; + krb5_data_free(&resp); + if (ret) + goto out; + + ret = krb5_error_from_rd_error(context, &error, creds); + + /* + * If no preauth was set and KDC requires it, give it one + * more try. + */ + + if (ret == KRB5KDC_ERR_PREAUTH_REQUIRED) { + free_METHOD_DATA(&md); + memset(&md, 0, sizeof(md)); + + if (error.e_data) { + ret = decode_METHOD_DATA(error.e_data->data, + error.e_data->length, + &md, + NULL); + if (ret) + krb5_set_error_string(context, + "failed to decode METHOD DATA"); + } else { + /* XXX guess what the server want here add add md */ + } + krb5_free_error_contents(context, &error); + if (ret) + goto out; + } else { + _krb5_get_init_creds_opt_set_krb5_error(context, + init_cred_opts, + &error); + if (ret_as_reply) + rep.error = error; + else + krb5_free_error_contents(context, &error); + goto out; + } + } + } + + { + krb5_keyblock *key = NULL; + unsigned flags = 0; + + if (ctx->flags.request_anonymous) + flags |= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH; + if (ctx->flags.canonicalize) { + flags |= EXTRACT_TICKET_ALLOW_CNAME_MISMATCH; + flags |= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH; + flags |= EXTRACT_TICKET_MATCH_REALM; + } + + ret = process_pa_data_to_key(context, ctx, creds, + &ctx->as_req, &rep, hi, &key); + if (ret) + goto out; + + ret = _krb5_extract_ticket(context, + &rep, + creds, + key, + NULL, + KRB5_KU_AS_REP_ENC_PART, + NULL, + ctx->nonce, + flags, + NULL, + NULL); + krb5_free_keyblock(context, key); + } + /* + * Verify referral data + */ + if ((ctx->ic_flags & KRB5_INIT_CREDS_CANONICALIZE) && + (ctx->ic_flags & KRB5_INIT_CREDS_NO_C_CANON_CHECK) == 0) + { + PA_ClientCanonicalized canon; + krb5_crypto crypto; + krb5_data data; + PA_DATA *pa; + size_t len; + + pa = find_pa_data(rep.kdc_rep.padata, KRB5_PADATA_CLIENT_CANONICALIZED); + if (pa == NULL) { + ret = EINVAL; + krb5_set_error_string(context, "Client canonicalizion not signed"); + goto out; + } + + ret = decode_PA_ClientCanonicalized(pa->padata_value.data, + pa->padata_value.length, + &canon, &len); + if (ret) { + krb5_set_error_string(context, "Failed to decode " + "PA_ClientCanonicalized"); + goto out; + } + + 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"); + + ret = krb5_crypto_init(context, &creds->session, 0, &crypto); + if (ret) { + free(data.data); + free_PA_ClientCanonicalized(&canon); + goto out; + } + + ret = krb5_verify_checksum(context, crypto, KRB5_KU_CANONICALIZED_NAMES, + data.data, data.length, + &canon.canon_checksum); + krb5_crypto_destroy(context, crypto); + free(data.data); + free_PA_ClientCanonicalized(&canon); + if (ret) { + krb5_set_error_string(context, "Failed to verify " + "client canonicalized data"); + goto out; + } + } +out: + if (stctx) + krb5_sendto_ctx_free(context, stctx); + krb5_data_free(&ctx->req_buffer); + free_METHOD_DATA(&md); + memset(&md, 0, sizeof(md)); + + if (ret == 0 && ret_as_reply) + *ret_as_reply = rep; + else + krb5_free_kdc_rep (context, &rep); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds(krb5_context context, + krb5_creds *creds, + krb5_principal client, + krb5_prompter_fct prompter, + void *data, + krb5_deltat start_time, + const char *in_tkt_service, + krb5_get_init_creds_opt *options) +{ + krb5_get_init_creds_ctx ctx; + krb5_kdc_rep kdc_reply; + krb5_error_code ret; + char buf[BUFSIZ]; + int done; + + memset(&kdc_reply, 0, sizeof(kdc_reply)); + + ret = get_init_creds_common(context, client, start_time, + in_tkt_service, options, &ctx); + if (ret) + goto out; + + done = 0; + while(!done) { + memset(&kdc_reply, 0, sizeof(kdc_reply)); + + ret = init_cred_loop(context, + options, + prompter, + data, + &ctx, + &ctx.cred, + &kdc_reply); + + switch (ret) { + case 0 : + done = 1; + break; + case KRB5KDC_ERR_KEY_EXPIRED : + /* try to avoid recursion */ + + /* don't try to change password where then where none */ + if (prompter == NULL || ctx.password == NULL) + goto out; + + krb5_clear_error_string (context); + + if (ctx.in_tkt_service != NULL + && strcmp (ctx.in_tkt_service, "kadmin/changepw") == 0) + goto out; + + ret = change_password (context, + client, + ctx.password, + buf, + sizeof(buf), + prompter, + data, + options); + if (ret) + goto out; + ctx.password = buf; + break; + default: + goto out; + } + } + + if (prompter) + print_expire (context, + krb5_principal_get_realm (context, ctx.cred.client), + &kdc_reply, + prompter, + data); + + out: + memset (buf, 0, sizeof(buf)); + free_init_creds_ctx(context, &ctx); + krb5_free_kdc_rep (context, &kdc_reply); + if (ret == 0) + *creds = ctx.cred; + else + krb5_free_cred_contents (context, &ctx.cred); + + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_password(krb5_context context, + krb5_creds *creds, + krb5_principal client, + const char *password, + krb5_prompter_fct prompter, + void *data, + krb5_deltat start_time, + const char *in_tkt_service, + krb5_get_init_creds_opt *in_options) +{ + krb5_get_init_creds_opt *options; + char buf[BUFSIZ]; + krb5_error_code ret; + + if (in_options == NULL) { + const char *realm = krb5_principal_get_realm(context, client); + ret = krb5_get_init_creds_opt_alloc(context, &options); + if (ret == 0) + krb5_get_init_creds_opt_set_default_flags(context, + NULL, + realm, + options); + } else + ret = _krb5_get_init_creds_opt_copy(context, in_options, &options); + if (ret) + return ret; + + if (password == NULL && + options->opt_private->password == NULL && + options->opt_private->pk_init_ctx == NULL) + { + krb5_prompt prompt; + krb5_data password_data; + char *p, *q; + + krb5_unparse_name (context, client, &p); + asprintf (&q, "%s's Password: ", p); + free (p); + prompt.prompt = q; + password_data.data = buf; + password_data.length = sizeof(buf); + prompt.hidden = 1; + prompt.reply = &password_data; + prompt.type = KRB5_PROMPT_TYPE_PASSWORD; + + ret = (*prompter) (context, data, NULL, NULL, 1, &prompt); + free (q); + if (ret) { + memset (buf, 0, sizeof(buf)); + krb5_get_init_creds_opt_free(context, options); + ret = KRB5_LIBOS_PWDINTR; + krb5_clear_error_string (context); + return ret; + } + password = password_data.data; + } + + if (options->opt_private->password == NULL) { + ret = krb5_get_init_creds_opt_set_pa_password(context, options, + password, NULL); + if (ret) { + krb5_get_init_creds_opt_free(context, options); + memset(buf, 0, sizeof(buf)); + return ret; + } + } + + ret = krb5_get_init_creds(context, creds, client, prompter, + data, start_time, in_tkt_service, options); + krb5_get_init_creds_opt_free(context, options); + memset(buf, 0, sizeof(buf)); + return ret; +} + +static krb5_error_code +init_creds_keyblock_key_proc (krb5_context context, + krb5_enctype type, + krb5_salt salt, + krb5_const_pointer keyseed, + krb5_keyblock **key) +{ + return krb5_copy_keyblock (context, keyseed, key); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_keyblock(krb5_context context, + krb5_creds *creds, + krb5_principal client, + krb5_keyblock *keyblock, + krb5_deltat start_time, + const char *in_tkt_service, + krb5_get_init_creds_opt *options) +{ + struct krb5_get_init_creds_ctx ctx; + krb5_error_code ret; + + ret = get_init_creds_common(context, client, start_time, + in_tkt_service, options, &ctx); + if (ret) + goto out; + + ret = krb5_get_in_cred (context, + KDCOptions2int(ctx.flags), + ctx.addrs, + ctx.etypes, + ctx.pre_auth_types, + NULL, + init_creds_keyblock_key_proc, + keyblock, + NULL, + NULL, + &ctx.cred, + NULL); + + if (ret == 0 && creds) + *creds = ctx.cred; + else + krb5_free_cred_contents (context, &ctx.cred); + + out: + free_init_creds_ctx(context, &ctx); + return ret; +} diff --git a/lib/krb5/k524_err.et b/lib/krb5/k524_err.et new file mode 100644 index 0000000..0ca25f7 --- /dev/null +++ b/lib/krb5/k524_err.et @@ -0,0 +1,20 @@ +# +# Error messages for the k524 functions +# +# This might look like a com_err file, but is not +# +id "$Id: k524_err.et 10141 2001-06-20 02:45:58Z joda $" + +error_table k524 + +prefix KRB524 +error_code BADKEY, "wrong keytype in ticket" +error_code BADADDR, "incorrect network address" +error_code BADPRINC, "cannot convert V5 principal" #unused +error_code BADREALM, "V5 realm name longer than V4 maximum" #unused +error_code V4ERR, "kerberos V4 error server" +error_code ENCFULL, "encoding too large at server" +error_code DECEMPTY, "decoding out of data" #unused +error_code NOTRESP, "service not responding" #unused +end + diff --git a/lib/krb5/kcm.c b/lib/krb5/kcm.c new file mode 100644 index 0000000..8afaa6e --- /dev/null +++ b/lib/krb5/kcm.c @@ -0,0 +1,1122 @@ +/* + * Copyright (c) 2005, PADL Software Pty Ltd. + * 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 PADL Software 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 PADL SOFTWARE 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 PADL SOFTWARE 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 "krb5_locl.h" + +#ifdef HAVE_KCM +/* + * Client library for Kerberos Credentials Manager (KCM) daemon + */ + +#ifdef HAVE_SYS_UN_H +#include <sys/un.h> +#endif + +#include "kcm.h" + +RCSID("$Id: kcm.c 22108 2007-12-03 17:23:53Z lha $"); + +typedef struct krb5_kcmcache { + char *name; + struct sockaddr_un path; + char *door_path; +} krb5_kcmcache; + +#define KCMCACHE(X) ((krb5_kcmcache *)(X)->data.data) +#define CACHENAME(X) (KCMCACHE(X)->name) +#define KCMCURSOR(C) (*(uint32_t *)(C)) + +static krb5_error_code +try_door(krb5_context context, const krb5_kcmcache *k, + krb5_data *request_data, + krb5_data *response_data) +{ +#ifdef HAVE_DOOR_CREATE + door_arg_t arg; + int fd; + int ret; + + memset(&arg, 0, sizeof(arg)); + + fd = open(k->door_path, O_RDWR); + if (fd < 0) + return KRB5_CC_IO; + + arg.data_ptr = request_data->data; + arg.data_size = request_data->length; + arg.desc_ptr = NULL; + arg.desc_num = 0; + arg.rbuf = NULL; + arg.rsize = 0; + + ret = door_call(fd, &arg); + close(fd); + if (ret != 0) + return KRB5_CC_IO; + + ret = krb5_data_copy(response_data, arg.rbuf, arg.rsize); + munmap(arg.rbuf, arg.rsize); + if (ret) + return ret; + + return 0; +#else + return KRB5_CC_IO; +#endif +} + +static krb5_error_code +try_unix_socket(krb5_context context, const krb5_kcmcache *k, + krb5_data *request_data, + krb5_data *response_data) +{ + krb5_error_code ret; + int fd; + + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd < 0) + return KRB5_CC_IO; + + if (connect(fd, rk_UNCONST(&k->path), sizeof(k->path)) != 0) { + close(fd); + return KRB5_CC_IO; + } + + ret = _krb5_send_and_recv_tcp(fd, context->kdc_timeout, + request_data, response_data); + close(fd); + return ret; +} + +static krb5_error_code +kcm_send_request(krb5_context context, + krb5_kcmcache *k, + krb5_storage *request, + krb5_data *response_data) +{ + krb5_error_code ret; + krb5_data request_data; + int i; + + response_data->data = NULL; + response_data->length = 0; + + ret = krb5_storage_to_data(request, &request_data); + if (ret) { + krb5_clear_error_string(context); + return KRB5_CC_NOMEM; + } + + ret = KRB5_CC_IO; + + for (i = 0; i < context->max_retries; i++) { + ret = try_door(context, k, &request_data, response_data); + if (ret == 0 && response_data->length != 0) + break; + ret = try_unix_socket(context, k, &request_data, response_data); + if (ret == 0 && response_data->length != 0) + break; + } + + krb5_data_free(&request_data); + + if (ret) { + krb5_clear_error_string(context); + ret = KRB5_CC_IO; + } + + return ret; +} + +static krb5_error_code +kcm_storage_request(krb5_context context, + kcm_operation opcode, + krb5_storage **storage_p) +{ + krb5_storage *sp; + krb5_error_code ret; + + *storage_p = NULL; + + sp = krb5_storage_emem(); + if (sp == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return KRB5_CC_NOMEM; + } + + /* Send MAJOR | VERSION | OPCODE */ + ret = krb5_store_int8(sp, KCM_PROTOCOL_VERSION_MAJOR); + if (ret) + goto fail; + ret = krb5_store_int8(sp, KCM_PROTOCOL_VERSION_MINOR); + if (ret) + goto fail; + ret = krb5_store_int16(sp, opcode); + if (ret) + goto fail; + + *storage_p = sp; + fail: + if (ret) { + krb5_set_error_string(context, "Failed to encode request"); + krb5_storage_free(sp); + } + + return ret; +} + +static krb5_error_code +kcm_alloc(krb5_context context, const char *name, krb5_ccache *id) +{ + krb5_kcmcache *k; + const char *path; + + k = malloc(sizeof(*k)); + if (k == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return KRB5_CC_NOMEM; + } + + if (name != NULL) { + k->name = strdup(name); + if (k->name == NULL) { + free(k); + krb5_set_error_string(context, "malloc: out of memory"); + return KRB5_CC_NOMEM; + } + } else + k->name = NULL; + + path = krb5_config_get_string_default(context, NULL, + _PATH_KCM_SOCKET, + "libdefaults", + "kcm_socket", + NULL); + + k->path.sun_family = AF_UNIX; + strlcpy(k->path.sun_path, path, sizeof(k->path.sun_path)); + + path = krb5_config_get_string_default(context, NULL, + _PATH_KCM_DOOR, + "libdefaults", + "kcm_door", + NULL); + k->door_path = strdup(path); + + (*id)->data.data = k; + (*id)->data.length = sizeof(*k); + + return 0; +} + +static krb5_error_code +kcm_call(krb5_context context, + krb5_kcmcache *k, + krb5_storage *request, + krb5_storage **response_p, + krb5_data *response_data_p) +{ + krb5_data response_data; + krb5_error_code ret; + int32_t status; + krb5_storage *response; + + if (response_p != NULL) + *response_p = NULL; + + ret = kcm_send_request(context, k, request, &response_data); + if (ret) { + return ret; + } + + response = krb5_storage_from_data(&response_data); + if (response == NULL) { + krb5_data_free(&response_data); + return KRB5_CC_IO; + } + + ret = krb5_ret_int32(response, &status); + if (ret) { + krb5_storage_free(response); + krb5_data_free(&response_data); + return KRB5_CC_FORMAT; + } + + if (status) { + krb5_storage_free(response); + krb5_data_free(&response_data); + return status; + } + + if (response_p != NULL) { + *response_data_p = response_data; + *response_p = response; + + return 0; + } + + krb5_storage_free(response); + krb5_data_free(&response_data); + + return 0; +} + +static void +kcm_free(krb5_context context, krb5_ccache *id) +{ + krb5_kcmcache *k = KCMCACHE(*id); + + if (k != NULL) { + if (k->name != NULL) + free(k->name); + if (k->door_path) + free(k->door_path); + memset(k, 0, sizeof(*k)); + krb5_data_free(&(*id)->data); + } + + *id = NULL; +} + +static const char * +kcm_get_name(krb5_context context, + krb5_ccache id) +{ + return CACHENAME(id); +} + +static krb5_error_code +kcm_resolve(krb5_context context, krb5_ccache *id, const char *res) +{ + return kcm_alloc(context, res, id); +} + +/* + * Request: + * + * Response: + * NameZ + */ +static krb5_error_code +kcm_gen_new(krb5_context context, krb5_ccache *id) +{ + krb5_kcmcache *k; + krb5_error_code ret; + krb5_storage *request, *response; + krb5_data response_data; + + ret = kcm_alloc(context, NULL, id); + if (ret) + return ret; + + k = KCMCACHE(*id); + + ret = kcm_storage_request(context, KCM_OP_GEN_NEW, &request); + if (ret) { + kcm_free(context, id); + return ret; + } + + ret = kcm_call(context, k, request, &response, &response_data); + if (ret) { + krb5_storage_free(request); + kcm_free(context, id); + return ret; + } + + ret = krb5_ret_stringz(response, &k->name); + if (ret) + ret = KRB5_CC_IO; + + krb5_storage_free(request); + krb5_storage_free(response); + krb5_data_free(&response_data); + + if (ret) + kcm_free(context, id); + + return ret; +} + +/* + * Request: + * NameZ + * Principal + * + * Response: + * + */ +static krb5_error_code +kcm_initialize(krb5_context context, + krb5_ccache id, + krb5_principal primary_principal) +{ + krb5_error_code ret; + krb5_kcmcache *k = KCMCACHE(id); + krb5_storage *request; + + ret = kcm_storage_request(context, KCM_OP_INITIALIZE, &request); + if (ret) + return ret; + + ret = krb5_store_stringz(request, k->name); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = krb5_store_principal(request, primary_principal); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = kcm_call(context, k, request, NULL, NULL); + + krb5_storage_free(request); + return ret; +} + +static krb5_error_code +kcm_close(krb5_context context, + krb5_ccache id) +{ + kcm_free(context, &id); + return 0; +} + +/* + * Request: + * NameZ + * + * Response: + * + */ +static krb5_error_code +kcm_destroy(krb5_context context, + krb5_ccache id) +{ + krb5_error_code ret; + krb5_kcmcache *k = KCMCACHE(id); + krb5_storage *request; + + ret = kcm_storage_request(context, KCM_OP_DESTROY, &request); + if (ret) + return ret; + + ret = krb5_store_stringz(request, k->name); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = kcm_call(context, k, request, NULL, NULL); + + krb5_storage_free(request); + return ret; +} + +/* + * Request: + * NameZ + * Creds + * + * Response: + * + */ +static krb5_error_code +kcm_store_cred(krb5_context context, + krb5_ccache id, + krb5_creds *creds) +{ + krb5_error_code ret; + krb5_kcmcache *k = KCMCACHE(id); + krb5_storage *request; + + ret = kcm_storage_request(context, KCM_OP_STORE, &request); + if (ret) + return ret; + + ret = krb5_store_stringz(request, k->name); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = krb5_store_creds(request, creds); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = kcm_call(context, k, request, NULL, NULL); + + krb5_storage_free(request); + return ret; +} + +/* + * Request: + * NameZ + * WhichFields + * MatchCreds + * + * Response: + * Creds + * + */ +static krb5_error_code +kcm_retrieve(krb5_context context, + krb5_ccache id, + krb5_flags which, + const krb5_creds *mcred, + krb5_creds *creds) +{ + krb5_error_code ret; + krb5_kcmcache *k = KCMCACHE(id); + krb5_storage *request, *response; + krb5_data response_data; + + ret = kcm_storage_request(context, KCM_OP_RETRIEVE, &request); + if (ret) + return ret; + + ret = krb5_store_stringz(request, k->name); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = krb5_store_int32(request, which); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = krb5_store_creds_tag(request, rk_UNCONST(mcred)); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = kcm_call(context, k, request, &response, &response_data); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = krb5_ret_creds(response, creds); + if (ret) + ret = KRB5_CC_IO; + + krb5_storage_free(request); + krb5_storage_free(response); + krb5_data_free(&response_data); + + return ret; +} + +/* + * Request: + * NameZ + * + * Response: + * Principal + */ +static krb5_error_code +kcm_get_principal(krb5_context context, + krb5_ccache id, + krb5_principal *principal) +{ + krb5_error_code ret; + krb5_kcmcache *k = KCMCACHE(id); + krb5_storage *request, *response; + krb5_data response_data; + + ret = kcm_storage_request(context, KCM_OP_GET_PRINCIPAL, &request); + if (ret) + return ret; + + ret = krb5_store_stringz(request, k->name); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = kcm_call(context, k, request, &response, &response_data); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = krb5_ret_principal(response, principal); + if (ret) + ret = KRB5_CC_IO; + + krb5_storage_free(request); + krb5_storage_free(response); + krb5_data_free(&response_data); + + return ret; +} + +/* + * Request: + * NameZ + * + * Response: + * Cursor + * + */ +static krb5_error_code +kcm_get_first (krb5_context context, + krb5_ccache id, + krb5_cc_cursor *cursor) +{ + krb5_error_code ret; + krb5_kcmcache *k = KCMCACHE(id); + krb5_storage *request, *response; + krb5_data response_data; + int32_t tmp; + + ret = kcm_storage_request(context, KCM_OP_GET_FIRST, &request); + if (ret) + return ret; + + ret = krb5_store_stringz(request, k->name); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = kcm_call(context, k, request, &response, &response_data); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = krb5_ret_int32(response, &tmp); + if (ret || tmp < 0) + ret = KRB5_CC_IO; + + krb5_storage_free(request); + krb5_storage_free(response); + krb5_data_free(&response_data); + + if (ret) + return ret; + + *cursor = malloc(sizeof(tmp)); + if (*cursor == NULL) + return KRB5_CC_NOMEM; + + KCMCURSOR(*cursor) = tmp; + + return 0; +} + +/* + * Request: + * NameZ + * Cursor + * + * Response: + * Creds + */ +static krb5_error_code +kcm_get_next (krb5_context context, + krb5_ccache id, + krb5_cc_cursor *cursor, + krb5_creds *creds) +{ + krb5_error_code ret; + krb5_kcmcache *k = KCMCACHE(id); + krb5_storage *request, *response; + krb5_data response_data; + + ret = kcm_storage_request(context, KCM_OP_GET_NEXT, &request); + if (ret) + return ret; + + ret = krb5_store_stringz(request, k->name); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = krb5_store_int32(request, KCMCURSOR(*cursor)); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = kcm_call(context, k, request, &response, &response_data); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = krb5_ret_creds(response, creds); + if (ret) + ret = KRB5_CC_IO; + + krb5_storage_free(request); + krb5_storage_free(response); + krb5_data_free(&response_data); + + return ret; +} + +/* + * Request: + * NameZ + * Cursor + * + * Response: + * + */ +static krb5_error_code +kcm_end_get (krb5_context context, + krb5_ccache id, + krb5_cc_cursor *cursor) +{ + krb5_error_code ret; + krb5_kcmcache *k = KCMCACHE(id); + krb5_storage *request; + + ret = kcm_storage_request(context, KCM_OP_END_GET, &request); + if (ret) + return ret; + + ret = krb5_store_stringz(request, k->name); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = krb5_store_int32(request, KCMCURSOR(*cursor)); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = kcm_call(context, k, request, NULL, NULL); + if (ret) { + krb5_storage_free(request); + return ret; + } + + krb5_storage_free(request); + + KCMCURSOR(*cursor) = 0; + free(*cursor); + *cursor = NULL; + + return ret; +} + +/* + * Request: + * NameZ + * WhichFields + * MatchCreds + * + * Response: + * + */ +static krb5_error_code +kcm_remove_cred(krb5_context context, + krb5_ccache id, + krb5_flags which, + krb5_creds *cred) +{ + krb5_error_code ret; + krb5_kcmcache *k = KCMCACHE(id); + krb5_storage *request; + + ret = kcm_storage_request(context, KCM_OP_REMOVE_CRED, &request); + if (ret) + return ret; + + ret = krb5_store_stringz(request, k->name); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = krb5_store_int32(request, which); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = krb5_store_creds_tag(request, cred); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = kcm_call(context, k, request, NULL, NULL); + + krb5_storage_free(request); + return ret; +} + +static krb5_error_code +kcm_set_flags(krb5_context context, + krb5_ccache id, + krb5_flags flags) +{ + krb5_error_code ret; + krb5_kcmcache *k = KCMCACHE(id); + krb5_storage *request; + + ret = kcm_storage_request(context, KCM_OP_SET_FLAGS, &request); + if (ret) + return ret; + + ret = krb5_store_stringz(request, k->name); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = krb5_store_int32(request, flags); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = kcm_call(context, k, request, NULL, NULL); + + krb5_storage_free(request); + return ret; +} + +static krb5_error_code +kcm_get_version(krb5_context context, + krb5_ccache id) +{ + return 0; +} + +static krb5_error_code +kcm_move(krb5_context context, krb5_ccache from, krb5_ccache to) +{ + krb5_set_error_string(context, "kcm_move not implemented"); + return EINVAL; +} + +static krb5_error_code +kcm_default_name(krb5_context context, char **str) +{ + return _krb5_expand_default_cc_name(context, + KRB5_DEFAULT_CCNAME_KCM, + str); +} + +/** + * Variable containing the KCM based credential cache implemention. + * + * @ingroup krb5_ccache + */ + +const krb5_cc_ops krb5_kcm_ops = { + "KCM", + kcm_get_name, + kcm_resolve, + kcm_gen_new, + kcm_initialize, + kcm_destroy, + kcm_close, + kcm_store_cred, + kcm_retrieve, + kcm_get_principal, + kcm_get_first, + kcm_get_next, + kcm_end_get, + kcm_remove_cred, + kcm_set_flags, + kcm_get_version, + NULL, + NULL, + NULL, + kcm_move, + kcm_default_name +}; + +krb5_boolean +_krb5_kcm_is_running(krb5_context context) +{ + krb5_error_code ret; + krb5_ccache_data ccdata; + krb5_ccache id = &ccdata; + krb5_boolean running; + + ret = kcm_alloc(context, NULL, &id); + if (ret) + return 0; + + running = (_krb5_kcm_noop(context, id) == 0); + + kcm_free(context, &id); + + return running; +} + +/* + * Request: + * + * Response: + * + */ +krb5_error_code +_krb5_kcm_noop(krb5_context context, + krb5_ccache id) +{ + krb5_error_code ret; + krb5_kcmcache *k = KCMCACHE(id); + krb5_storage *request; + + ret = kcm_storage_request(context, KCM_OP_NOOP, &request); + if (ret) + return ret; + + ret = kcm_call(context, k, request, NULL, NULL); + + krb5_storage_free(request); + return ret; +} + + +/* + * Request: + * NameZ + * Mode + * + * Response: + * + */ +krb5_error_code +_krb5_kcm_chmod(krb5_context context, + krb5_ccache id, + uint16_t mode) +{ + krb5_error_code ret; + krb5_kcmcache *k = KCMCACHE(id); + krb5_storage *request; + + ret = kcm_storage_request(context, KCM_OP_CHMOD, &request); + if (ret) + return ret; + + ret = krb5_store_stringz(request, k->name); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = krb5_store_int16(request, mode); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = kcm_call(context, k, request, NULL, NULL); + + krb5_storage_free(request); + return ret; +} + + +/* + * Request: + * NameZ + * UID + * GID + * + * Response: + * + */ +krb5_error_code +_krb5_kcm_chown(krb5_context context, + krb5_ccache id, + uint32_t uid, + uint32_t gid) +{ + krb5_error_code ret; + krb5_kcmcache *k = KCMCACHE(id); + krb5_storage *request; + + ret = kcm_storage_request(context, KCM_OP_CHOWN, &request); + if (ret) + return ret; + + ret = krb5_store_stringz(request, k->name); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = krb5_store_int32(request, uid); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = krb5_store_int32(request, gid); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = kcm_call(context, k, request, NULL, NULL); + + krb5_storage_free(request); + return ret; +} + + +/* + * Request: + * NameZ + * ServerPrincipalPresent + * ServerPrincipal OPTIONAL + * Key + * + * Repsonse: + * + */ +krb5_error_code +_krb5_kcm_get_initial_ticket(krb5_context context, + krb5_ccache id, + krb5_principal server, + krb5_keyblock *key) +{ + krb5_error_code ret; + krb5_kcmcache *k = KCMCACHE(id); + krb5_storage *request; + + ret = kcm_storage_request(context, KCM_OP_GET_INITIAL_TICKET, &request); + if (ret) + return ret; + + ret = krb5_store_stringz(request, k->name); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = krb5_store_int8(request, (server == NULL) ? 0 : 1); + if (ret) { + krb5_storage_free(request); + return ret; + } + + if (server != NULL) { + ret = krb5_store_principal(request, server); + if (ret) { + krb5_storage_free(request); + return ret; + } + } + + ret = krb5_store_keyblock(request, *key); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = kcm_call(context, k, request, NULL, NULL); + + krb5_storage_free(request); + return ret; +} + + +/* + * Request: + * NameZ + * KDCFlags + * EncryptionType + * ServerPrincipal + * + * Repsonse: + * + */ +krb5_error_code +_krb5_kcm_get_ticket(krb5_context context, + krb5_ccache id, + krb5_kdc_flags flags, + krb5_enctype enctype, + krb5_principal server) +{ + krb5_error_code ret; + krb5_kcmcache *k = KCMCACHE(id); + krb5_storage *request; + + ret = kcm_storage_request(context, KCM_OP_GET_TICKET, &request); + if (ret) + return ret; + + ret = krb5_store_stringz(request, k->name); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = krb5_store_int32(request, flags.i); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = krb5_store_int32(request, enctype); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = krb5_store_principal(request, server); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = kcm_call(context, k, request, NULL, NULL); + + krb5_storage_free(request); + return ret; +} + + +#endif /* HAVE_KCM */ diff --git a/lib/krb5/kcm.h b/lib/krb5/kcm.h new file mode 100644 index 0000000..10dfa44 --- /dev/null +++ b/lib/krb5/kcm.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2005, PADL Software Pty Ltd. + * 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 PADL Software 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 PADL SOFTWARE 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 PADL SOFTWARE 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. + */ + +#ifndef __KCM_H__ +#define __KCM_H__ + +/* + * KCM protocol definitions + */ + +#define KCM_PROTOCOL_VERSION_MAJOR 1 +#define KCM_PROTOCOL_VERSION_MINOR 0 + +typedef enum kcm_operation { + KCM_OP_NOOP, + KCM_OP_GET_NAME, + KCM_OP_RESOLVE, + KCM_OP_GEN_NEW, + KCM_OP_INITIALIZE, + KCM_OP_DESTROY, + KCM_OP_STORE, + KCM_OP_RETRIEVE, + KCM_OP_GET_PRINCIPAL, + KCM_OP_GET_FIRST, + KCM_OP_GET_NEXT, + KCM_OP_END_GET, + KCM_OP_REMOVE_CRED, + KCM_OP_SET_FLAGS, + KCM_OP_CHOWN, + KCM_OP_CHMOD, + KCM_OP_GET_INITIAL_TICKET, + KCM_OP_GET_TICKET, + KCM_OP_MAX +} kcm_operation; + +#define _PATH_KCM_SOCKET "/var/run/.kcm_socket" +#define _PATH_KCM_DOOR "/var/run/.kcm_door" + +#endif /* __KCM_H__ */ + diff --git a/lib/krb5/kerberos.8 b/lib/krb5/kerberos.8 new file mode 100644 index 0000000..e45c947 --- /dev/null +++ b/lib/krb5/kerberos.8 @@ -0,0 +1,107 @@ +.\" Copyright (c) 2000 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: kerberos.8 16121 2005-10-03 14:24:36Z lha $ +.\" +.Dd September 1, 2000 +.Dt KERBEROS 8 +.Os HEIMDAL +.Sh NAME +.Nm kerberos +.Nd introduction to the Kerberos system +.Sh DESCRIPTION +Kerberos is a network authentication system. Its purpose is to +securely authenticate users and services in an insecure network +environment. +.Pp +This is done with a Kerberos server acting as a trusted third party, +keeping a database with secret keys for all users and services +(collectively called +.Em principals ) . +.Pp +Each principal belongs to exactly one +.Em realm , +which is the administrative domain in Kerberos. A realm usually +corresponds to an organisation, and the realm should normally be +derived from that organisation's domain name. A realm is served by one +or more Kerberos servers. +.Pp +The authentication process involves exchange of +.Sq tickets +and +.Sq authenticators +which together prove the principal's identity. +.Pp +When you login to the Kerberos system, either through the normal +system login or with the +.Xr kinit 1 +program, you acquire a +.Em ticket granting ticket +which allows you to get new tickets for other services, such as +.Ic telnet +or +.Ic ftp , +without giving your password. +.Pp +For more information on how Kerberos works, and other general Kerberos +questions see the Kerberos FAQ at +.Pa http://www.nrl.navy.mil/CCS/people/kenh/kerberos-faq.html . +.Pp +For setup instructions see the Heimdal Texinfo manual. +.Sh SEE ALSO +.Xr ftp 1 , +.Xr kdestroy 1 , +.Xr kinit 1 , +.Xr klist 1 , +.Xr kpasswd 1 , +.Xr telnet 1 +.Sh HISTORY +The Kerberos authentication system was developed in the late 1980's as +part of the Athena Project at the Massachusetts Institute of +Technology. Versions one through three never reached outside MIT, but +version 4 was (and still is) quite popular, especially in the academic +community, but is also used in commercial products like the AFS +filesystem. +.Pp +The problems with version 4 are that it has many limitations, the code +was not too well written (since it had been developed over a long +time), and it has a number of known security problems. To resolve many +of these issues work on version five started, and resulted in IETF RFC +1510 in 1993. IETF RFC 1510 was obsoleted in 2005 with IETF RFC 4120, +also known as Kerberos clarifications. With the arrival of IETF RFC +4120, the work on adding extensibility and internationalization have +started (Kerberos extensions), and a new RFC will hopefully appear +soon. +.Pp +This manual page is part of the +.Nm Heimdal +Kerberos 5 distribution, which has been in development at the Royal +Institute of Technology in Stockholm, Sweden, since about 1997. diff --git a/lib/krb5/keyblock.c b/lib/krb5/keyblock.c new file mode 100644 index 0000000..ff4f972 --- /dev/null +++ b/lib/krb5/keyblock.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: keyblock.c 15167 2005-05-18 04:21:57Z lha $"); + +void KRB5_LIB_FUNCTION +krb5_keyblock_zero(krb5_keyblock *keyblock) +{ + keyblock->keytype = 0; + krb5_data_zero(&keyblock->keyvalue); +} + +void KRB5_LIB_FUNCTION +krb5_free_keyblock_contents(krb5_context context, + krb5_keyblock *keyblock) +{ + if(keyblock) { + if (keyblock->keyvalue.data != NULL) + memset(keyblock->keyvalue.data, 0, keyblock->keyvalue.length); + krb5_data_free (&keyblock->keyvalue); + keyblock->keytype = ENCTYPE_NULL; + } +} + +void KRB5_LIB_FUNCTION +krb5_free_keyblock(krb5_context context, + krb5_keyblock *keyblock) +{ + if(keyblock){ + krb5_free_keyblock_contents(context, keyblock); + free(keyblock); + } +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_keyblock_contents (krb5_context context, + const krb5_keyblock *inblock, + krb5_keyblock *to) +{ + return copy_EncryptionKey(inblock, to); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_keyblock (krb5_context context, + const krb5_keyblock *inblock, + krb5_keyblock **to) +{ + krb5_keyblock *k; + + k = malloc (sizeof(*k)); + if (k == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + *to = k; + return krb5_copy_keyblock_contents (context, inblock, k); +} + +krb5_enctype +krb5_keyblock_get_enctype(const krb5_keyblock *block) +{ + return block->keytype; +} + +/* + * Fill in `key' with key data of type `enctype' from `data' of length + * `size'. Key should be freed using krb5_free_keyblock_contents. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_keyblock_init(krb5_context context, + krb5_enctype type, + const void *data, + size_t size, + krb5_keyblock *key) +{ + krb5_error_code ret; + size_t len; + + memset(key, 0, sizeof(*key)); + + ret = krb5_enctype_keysize(context, type, &len); + if (ret) + return ret; + + if (len != size) { + krb5_set_error_string(context, "Encryption key %d is %lu bytes " + "long, %lu was passed in", + type, (unsigned long)len, (unsigned long)size); + return KRB5_PROG_ETYPE_NOSUPP; + } + ret = krb5_data_copy(&key->keyvalue, data, len); + if(ret) { + krb5_set_error_string(context, "malloc failed: %lu", + (unsigned long)len); + return ret; + } + key->keytype = type; + + return 0; +} diff --git a/lib/krb5/keytab.c b/lib/krb5/keytab.c new file mode 100644 index 0000000..f6c7858 --- /dev/null +++ b/lib/krb5/keytab.c @@ -0,0 +1,528 @@ +/* + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: keytab.c 20211 2007-02-09 07:11:03Z lha $"); + +/* + * Register a new keytab in `ops' + * Return 0 or an error. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_register(krb5_context context, + const krb5_kt_ops *ops) +{ + struct krb5_keytab_data *tmp; + + if (strlen(ops->prefix) > KRB5_KT_PREFIX_MAX_LEN - 1) { + krb5_set_error_string(context, "krb5_kt_register; prefix too long"); + return KRB5_KT_BADNAME; + } + + tmp = realloc(context->kt_types, + (context->num_kt_types + 1) * sizeof(*context->kt_types)); + if(tmp == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + memcpy(&tmp[context->num_kt_types], ops, + sizeof(tmp[context->num_kt_types])); + context->kt_types = tmp; + context->num_kt_types++; + return 0; +} + +/* + * Resolve the keytab name (of the form `type:residual') in `name' + * into a keytab in `id'. + * Return 0 or an error + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_resolve(krb5_context context, + const char *name, + krb5_keytab *id) +{ + krb5_keytab k; + int i; + const char *type, *residual; + size_t type_len; + krb5_error_code ret; + + residual = strchr(name, ':'); + if(residual == NULL) { + type = "FILE"; + type_len = strlen(type); + residual = name; + } else { + type = name; + type_len = residual - name; + residual++; + } + + for(i = 0; i < context->num_kt_types; i++) { + if(strncasecmp(type, context->kt_types[i].prefix, type_len) == 0) + break; + } + if(i == context->num_kt_types) { + krb5_set_error_string(context, "unknown keytab type %.*s", + (int)type_len, type); + return KRB5_KT_UNKNOWN_TYPE; + } + + k = malloc (sizeof(*k)); + if (k == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + memcpy(k, &context->kt_types[i], sizeof(*k)); + k->data = NULL; + ret = (*k->resolve)(context, residual, k); + if(ret) { + free(k); + k = NULL; + } + *id = k; + return ret; +} + +/* + * copy the name of the default keytab into `name'. + * Return 0 or KRB5_CONFIG_NOTENUFSPACE if `namesize' is too short. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_default_name(krb5_context context, char *name, size_t namesize) +{ + if (strlcpy (name, context->default_keytab, namesize) >= namesize) { + krb5_clear_error_string (context); + return KRB5_CONFIG_NOTENUFSPACE; + } + return 0; +} + +/* + * copy the name of the default modify keytab into `name'. + * Return 0 or KRB5_CONFIG_NOTENUFSPACE if `namesize' is too short. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_default_modify_name(krb5_context context, char *name, size_t namesize) +{ + const char *kt = NULL; + if(context->default_keytab_modify == NULL) { + if(strncasecmp(context->default_keytab, "ANY:", 4) != 0) + kt = context->default_keytab; + else { + size_t len = strcspn(context->default_keytab + 4, ","); + if(len >= namesize) { + krb5_clear_error_string(context); + return KRB5_CONFIG_NOTENUFSPACE; + } + strlcpy(name, context->default_keytab + 4, namesize); + name[len] = '\0'; + return 0; + } + } else + kt = context->default_keytab_modify; + if (strlcpy (name, kt, namesize) >= namesize) { + krb5_clear_error_string (context); + return KRB5_CONFIG_NOTENUFSPACE; + } + return 0; +} + +/* + * Set `id' to the default keytab. + * Return 0 or an error. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_default(krb5_context context, krb5_keytab *id) +{ + return krb5_kt_resolve (context, context->default_keytab, id); +} + +/* + * Read the key identified by `(principal, vno, enctype)' from the + * keytab in `keyprocarg' (the default if == NULL) into `*key'. + * Return 0 or an error. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_read_service_key(krb5_context context, + krb5_pointer keyprocarg, + krb5_principal principal, + krb5_kvno vno, + krb5_enctype enctype, + krb5_keyblock **key) +{ + krb5_keytab keytab; + krb5_keytab_entry entry; + krb5_error_code ret; + + if (keyprocarg) + ret = krb5_kt_resolve (context, keyprocarg, &keytab); + else + ret = krb5_kt_default (context, &keytab); + + if (ret) + return ret; + + ret = krb5_kt_get_entry (context, keytab, principal, vno, enctype, &entry); + krb5_kt_close (context, keytab); + if (ret) + return ret; + ret = krb5_copy_keyblock (context, &entry.keyblock, key); + krb5_kt_free_entry(context, &entry); + return ret; +} + +/* + * Return the type of the `keytab' in the string `prefix of length + * `prefixsize'. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_get_type(krb5_context context, + krb5_keytab keytab, + char *prefix, + size_t prefixsize) +{ + strlcpy(prefix, keytab->prefix, prefixsize); + return 0; +} + +/* + * Retrieve the name of the keytab `keytab' into `name', `namesize' + * Return 0 or an error. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_get_name(krb5_context context, + krb5_keytab keytab, + char *name, + size_t namesize) +{ + return (*keytab->get_name)(context, keytab, name, namesize); +} + +/* + * Retrieve the full name of the keytab `keytab' and store the name in + * `str'. `str' needs to be freed by the caller using free(3). + * Returns 0 or an error. On error, *str is set to NULL. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_get_full_name(krb5_context context, + krb5_keytab keytab, + char **str) +{ + char type[KRB5_KT_PREFIX_MAX_LEN]; + char name[MAXPATHLEN]; + krb5_error_code ret; + + *str = NULL; + + ret = krb5_kt_get_type(context, keytab, type, sizeof(type)); + if (ret) + return ret; + + ret = krb5_kt_get_name(context, keytab, name, sizeof(name)); + if (ret) + return ret; + + if (asprintf(str, "%s:%s", type, name) == -1) { + krb5_set_error_string(context, "malloc - out of memory"); + *str = NULL; + return ENOMEM; + } + + return 0; +} + +/* + * Finish using the keytab in `id'. All resources will be released, + * even on errors. Return 0 or an error. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_close(krb5_context context, + krb5_keytab id) +{ + krb5_error_code ret; + + ret = (*id->close)(context, id); + memset(id, 0, sizeof(*id)); + free(id); + return ret; +} + +/* + * Compare `entry' against `principal, vno, enctype'. + * Any of `principal, vno, enctype' might be 0 which acts as a wildcard. + * Return TRUE if they compare the same, FALSE otherwise. + */ + +krb5_boolean KRB5_LIB_FUNCTION +krb5_kt_compare(krb5_context context, + krb5_keytab_entry *entry, + krb5_const_principal principal, + krb5_kvno vno, + krb5_enctype enctype) +{ + if(principal != NULL && + !krb5_principal_compare(context, entry->principal, principal)) + return FALSE; + if(vno && vno != entry->vno) + return FALSE; + if(enctype && enctype != entry->keyblock.keytype) + return FALSE; + return TRUE; +} + +/* + * Retrieve the keytab entry for `principal, kvno, enctype' into `entry' + * from the keytab `id'. + * kvno == 0 is a wildcard and gives the keytab with the highest vno. + * Return 0 or an error. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_get_entry(krb5_context context, + krb5_keytab id, + krb5_const_principal principal, + krb5_kvno kvno, + krb5_enctype enctype, + krb5_keytab_entry *entry) +{ + krb5_keytab_entry tmp; + krb5_error_code ret; + krb5_kt_cursor cursor; + + if(id->get) + return (*id->get)(context, id, principal, kvno, enctype, entry); + + ret = krb5_kt_start_seq_get (context, id, &cursor); + if (ret) { + krb5_clear_error_string(context); + return KRB5_KT_NOTFOUND; /* XXX i.e. file not found */ + } + + entry->vno = 0; + while (krb5_kt_next_entry(context, id, &tmp, &cursor) == 0) { + if (krb5_kt_compare(context, &tmp, principal, 0, enctype)) { + /* the file keytab might only store the lower 8 bits of + the kvno, so only compare those bits */ + if (kvno == tmp.vno + || (tmp.vno < 256 && kvno % 256 == tmp.vno)) { + krb5_kt_copy_entry_contents (context, &tmp, entry); + krb5_kt_free_entry (context, &tmp); + krb5_kt_end_seq_get(context, id, &cursor); + return 0; + } else if (kvno == 0 && tmp.vno > entry->vno) { + if (entry->vno) + krb5_kt_free_entry (context, entry); + krb5_kt_copy_entry_contents (context, &tmp, entry); + } + } + krb5_kt_free_entry(context, &tmp); + } + krb5_kt_end_seq_get (context, id, &cursor); + if (entry->vno) { + return 0; + } else { + char princ[256], kvno_str[25], *kt_name; + char *enctype_str = NULL; + + krb5_unparse_name_fixed (context, principal, princ, sizeof(princ)); + krb5_kt_get_full_name (context, id, &kt_name); + krb5_enctype_to_string(context, enctype, &enctype_str); + + if (kvno) + snprintf(kvno_str, sizeof(kvno_str), "(kvno %d)", kvno); + else + kvno_str[0] = '\0'; + + krb5_set_error_string (context, + "Failed to find %s%s in keytab %s (%s)", + princ, + kvno_str, + kt_name ? kt_name : "unknown keytab", + enctype_str ? enctype_str : "unknown enctype"); + free(kt_name); + free(enctype_str); + return KRB5_KT_NOTFOUND; + } +} + +/* + * Copy the contents of `in' into `out'. + * Return 0 or an error. */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_copy_entry_contents(krb5_context context, + const krb5_keytab_entry *in, + krb5_keytab_entry *out) +{ + krb5_error_code ret; + + memset(out, 0, sizeof(*out)); + out->vno = in->vno; + + ret = krb5_copy_principal (context, in->principal, &out->principal); + if (ret) + goto fail; + ret = krb5_copy_keyblock_contents (context, + &in->keyblock, + &out->keyblock); + if (ret) + goto fail; + out->timestamp = in->timestamp; + return 0; +fail: + krb5_kt_free_entry (context, out); + return ret; +} + +/* + * Free the contents of `entry'. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_free_entry(krb5_context context, + krb5_keytab_entry *entry) +{ + krb5_free_principal (context, entry->principal); + krb5_free_keyblock_contents (context, &entry->keyblock); + memset(entry, 0, sizeof(*entry)); + return 0; +} + +/* + * Set `cursor' to point at the beginning of `id'. + * Return 0 or an error. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_start_seq_get(krb5_context context, + krb5_keytab id, + krb5_kt_cursor *cursor) +{ + if(id->start_seq_get == NULL) { + krb5_set_error_string(context, + "start_seq_get is not supported in the %s " + " keytab", id->prefix); + return HEIM_ERR_OPNOTSUPP; + } + return (*id->start_seq_get)(context, id, cursor); +} + +/* + * Get the next entry from `id' pointed to by `cursor' and advance the + * `cursor'. + * Return 0 or an error. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_next_entry(krb5_context context, + krb5_keytab id, + krb5_keytab_entry *entry, + krb5_kt_cursor *cursor) +{ + if(id->next_entry == NULL) { + krb5_set_error_string(context, + "next_entry is not supported in the %s " + " keytab", id->prefix); + return HEIM_ERR_OPNOTSUPP; + } + return (*id->next_entry)(context, id, entry, cursor); +} + +/* + * Release all resources associated with `cursor'. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_end_seq_get(krb5_context context, + krb5_keytab id, + krb5_kt_cursor *cursor) +{ + if(id->end_seq_get == NULL) { + krb5_set_error_string(context, + "end_seq_get is not supported in the %s " + " keytab", id->prefix); + return HEIM_ERR_OPNOTSUPP; + } + return (*id->end_seq_get)(context, id, cursor); +} + +/* + * Add the entry in `entry' to the keytab `id'. + * Return 0 or an error. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_add_entry(krb5_context context, + krb5_keytab id, + krb5_keytab_entry *entry) +{ + if(id->add == NULL) { + krb5_set_error_string(context, "Add is not supported in the %s keytab", + id->prefix); + return KRB5_KT_NOWRITE; + } + entry->timestamp = time(NULL); + return (*id->add)(context, id,entry); +} + +/* + * Remove the entry `entry' from the keytab `id'. + * Return 0 or an error. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_remove_entry(krb5_context context, + krb5_keytab id, + krb5_keytab_entry *entry) +{ + if(id->remove == NULL) { + krb5_set_error_string(context, + "Remove is not supported in the %s keytab", + id->prefix); + return KRB5_KT_NOWRITE; + } + return (*id->remove)(context, id, entry); +} diff --git a/lib/krb5/keytab_any.c b/lib/krb5/keytab_any.c new file mode 100644 index 0000000..54272d4 --- /dev/null +++ b/lib/krb5/keytab_any.c @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2001-2002 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: keytab_any.c 17035 2006-04-10 09:20:13Z lha $"); + +struct any_data { + krb5_keytab kt; + char *name; + struct any_data *next; +}; + +static void +free_list (krb5_context context, struct any_data *a) +{ + struct any_data *next; + + for (; a != NULL; a = next) { + next = a->next; + free (a->name); + if(a->kt) + krb5_kt_close(context, a->kt); + free (a); + } +} + +static krb5_error_code +any_resolve(krb5_context context, const char *name, krb5_keytab id) +{ + struct any_data *a, *a0 = NULL, *prev = NULL; + krb5_error_code ret; + char buf[256]; + + while (strsep_copy(&name, ",", buf, sizeof(buf)) != -1) { + a = malloc(sizeof(*a)); + if (a == NULL) { + ret = ENOMEM; + goto fail; + } + if (a0 == NULL) { + a0 = a; + a->name = strdup(buf); + if (a->name == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + ret = ENOMEM; + goto fail; + } + } else + a->name = NULL; + if (prev != NULL) + prev->next = a; + a->next = NULL; + ret = krb5_kt_resolve (context, buf, &a->kt); + if (ret) + goto fail; + prev = a; + } + if (a0 == NULL) { + krb5_set_error_string(context, "empty ANY: keytab"); + return ENOENT; + } + id->data = a0; + return 0; + fail: + free_list (context, a0); + return ret; +} + +static krb5_error_code +any_get_name (krb5_context context, + krb5_keytab id, + char *name, + size_t namesize) +{ + struct any_data *a = id->data; + strlcpy(name, a->name, namesize); + return 0; +} + +static krb5_error_code +any_close (krb5_context context, + krb5_keytab id) +{ + struct any_data *a = id->data; + + free_list (context, a); + return 0; +} + +struct any_cursor_extra_data { + struct any_data *a; + krb5_kt_cursor cursor; +}; + +static krb5_error_code +any_start_seq_get(krb5_context context, + krb5_keytab id, + krb5_kt_cursor *c) +{ + struct any_data *a = id->data; + struct any_cursor_extra_data *ed; + krb5_error_code ret; + + c->data = malloc (sizeof(struct any_cursor_extra_data)); + if(c->data == NULL){ + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + ed = (struct any_cursor_extra_data *)c->data; + ed->a = a; + ret = krb5_kt_start_seq_get(context, ed->a->kt, &ed->cursor); + if (ret) { + free (c->data); + c->data = NULL; + return ret; + } + return 0; +} + +static krb5_error_code +any_next_entry (krb5_context context, + krb5_keytab id, + krb5_keytab_entry *entry, + krb5_kt_cursor *cursor) +{ + krb5_error_code ret, ret2; + struct any_cursor_extra_data *ed; + + ed = (struct any_cursor_extra_data *)cursor->data; + do { + ret = krb5_kt_next_entry(context, ed->a->kt, entry, &ed->cursor); + if (ret == 0) + return 0; + else if (ret != KRB5_KT_END) + return ret; + + ret2 = krb5_kt_end_seq_get (context, ed->a->kt, &ed->cursor); + if (ret2) + return ret2; + while ((ed->a = ed->a->next) != NULL) { + ret2 = krb5_kt_start_seq_get(context, ed->a->kt, &ed->cursor); + if (ret2 == 0) + break; + } + if (ed->a == NULL) { + krb5_clear_error_string (context); + return KRB5_KT_END; + } + } while (1); +} + +static krb5_error_code +any_end_seq_get(krb5_context context, + krb5_keytab id, + krb5_kt_cursor *cursor) +{ + krb5_error_code ret = 0; + struct any_cursor_extra_data *ed; + + ed = (struct any_cursor_extra_data *)cursor->data; + if (ed->a != NULL) + ret = krb5_kt_end_seq_get(context, ed->a->kt, &ed->cursor); + free (ed); + cursor->data = NULL; + return ret; +} + +static krb5_error_code +any_add_entry(krb5_context context, + krb5_keytab id, + krb5_keytab_entry *entry) +{ + struct any_data *a = id->data; + krb5_error_code ret; + while(a != NULL) { + ret = krb5_kt_add_entry(context, a->kt, entry); + if(ret != 0 && ret != KRB5_KT_NOWRITE) { + krb5_set_error_string(context, "failed to add entry to %s", + a->name); + return ret; + } + a = a->next; + } + return 0; +} + +static krb5_error_code +any_remove_entry(krb5_context context, + krb5_keytab id, + krb5_keytab_entry *entry) +{ + struct any_data *a = id->data; + krb5_error_code ret; + int found = 0; + while(a != NULL) { + ret = krb5_kt_remove_entry(context, a->kt, entry); + if(ret == 0) + found++; + else { + if(ret != KRB5_KT_NOWRITE && ret != KRB5_KT_NOTFOUND) { + krb5_set_error_string(context, "failed to remove entry from %s", + a->name); + return ret; + } + } + a = a->next; + } + if(!found) + return KRB5_KT_NOTFOUND; + return 0; +} + +const krb5_kt_ops krb5_any_ops = { + "ANY", + any_resolve, + any_get_name, + any_close, + NULL, /* get */ + any_start_seq_get, + any_next_entry, + any_end_seq_get, + any_add_entry, + any_remove_entry +}; diff --git a/lib/krb5/keytab_file.c b/lib/krb5/keytab_file.c new file mode 100644 index 0000000..4ada3a4 --- /dev/null +++ b/lib/krb5/keytab_file.c @@ -0,0 +1,696 @@ +/* + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: keytab_file.c 17457 2006-05-05 12:36:57Z lha $"); + +#define KRB5_KT_VNO_1 1 +#define KRB5_KT_VNO_2 2 +#define KRB5_KT_VNO KRB5_KT_VNO_2 + +#define KRB5_KT_FL_JAVA 1 + + +/* file operations -------------------------------------------- */ + +struct fkt_data { + char *filename; + int flags; +}; + +static krb5_error_code +krb5_kt_ret_data(krb5_context context, + krb5_storage *sp, + krb5_data *data) +{ + int ret; + int16_t size; + ret = krb5_ret_int16(sp, &size); + if(ret) + return ret; + data->length = size; + data->data = malloc(size); + if (data->data == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + ret = krb5_storage_read(sp, data->data, size); + if(ret != size) + return (ret < 0)? errno : KRB5_KT_END; + return 0; +} + +static krb5_error_code +krb5_kt_ret_string(krb5_context context, + krb5_storage *sp, + heim_general_string *data) +{ + int ret; + int16_t size; + ret = krb5_ret_int16(sp, &size); + if(ret) + return ret; + *data = malloc(size + 1); + if (*data == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + ret = krb5_storage_read(sp, *data, size); + (*data)[size] = '\0'; + if(ret != size) + return (ret < 0)? errno : KRB5_KT_END; + return 0; +} + +static krb5_error_code +krb5_kt_store_data(krb5_context context, + krb5_storage *sp, + krb5_data data) +{ + int ret; + ret = krb5_store_int16(sp, data.length); + if(ret < 0) + return ret; + ret = krb5_storage_write(sp, data.data, data.length); + if(ret != data.length){ + if(ret < 0) + return errno; + return KRB5_KT_END; + } + return 0; +} + +static krb5_error_code +krb5_kt_store_string(krb5_storage *sp, + heim_general_string data) +{ + int ret; + size_t len = strlen(data); + ret = krb5_store_int16(sp, len); + if(ret < 0) + return ret; + ret = krb5_storage_write(sp, data, len); + if(ret != len){ + if(ret < 0) + return errno; + return KRB5_KT_END; + } + return 0; +} + +static krb5_error_code +krb5_kt_ret_keyblock(krb5_context context, krb5_storage *sp, krb5_keyblock *p) +{ + int ret; + int16_t tmp; + + ret = krb5_ret_int16(sp, &tmp); /* keytype + etype */ + if(ret) return ret; + p->keytype = tmp; + ret = krb5_kt_ret_data(context, sp, &p->keyvalue); + return ret; +} + +static krb5_error_code +krb5_kt_store_keyblock(krb5_context context, + krb5_storage *sp, + krb5_keyblock *p) +{ + int ret; + + ret = krb5_store_int16(sp, p->keytype); /* keytype + etype */ + if(ret) return ret; + ret = krb5_kt_store_data(context, sp, p->keyvalue); + return ret; +} + + +static krb5_error_code +krb5_kt_ret_principal(krb5_context context, + krb5_storage *sp, + krb5_principal *princ) +{ + int i; + int ret; + krb5_principal p; + int16_t len; + + ALLOC(p, 1); + if(p == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + + ret = krb5_ret_int16(sp, &len); + if(ret) { + krb5_set_error_string(context, + "Failed decoding length of keytab principal"); + goto out; + } + if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS)) + len--; + if (len < 0) { + krb5_set_error_string(context, + "Keytab principal contains invalid length"); + ret = KRB5_KT_END; + goto out; + } + ret = krb5_kt_ret_string(context, sp, &p->realm); + if(ret) + goto out; + p->name.name_string.val = calloc(len, sizeof(*p->name.name_string.val)); + if(p->name.name_string.val == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + ret = ENOMEM; + goto out; + } + p->name.name_string.len = len; + for(i = 0; i < p->name.name_string.len; i++){ + ret = krb5_kt_ret_string(context, sp, p->name.name_string.val + i); + if(ret) + goto out; + } + if (krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) + p->name.name_type = KRB5_NT_UNKNOWN; + else { + int32_t tmp32; + ret = krb5_ret_int32(sp, &tmp32); + p->name.name_type = tmp32; + if (ret) + goto out; + } + *princ = p; + return 0; +out: + krb5_free_principal(context, p); + return ret; +} + +static krb5_error_code +krb5_kt_store_principal(krb5_context context, + krb5_storage *sp, + krb5_principal p) +{ + int i; + int ret; + + if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS)) + ret = krb5_store_int16(sp, p->name.name_string.len + 1); + else + ret = krb5_store_int16(sp, p->name.name_string.len); + if(ret) return ret; + ret = krb5_kt_store_string(sp, p->realm); + if(ret) return ret; + for(i = 0; i < p->name.name_string.len; i++){ + ret = krb5_kt_store_string(sp, p->name.name_string.val[i]); + if(ret) + return ret; + } + if(!krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) { + ret = krb5_store_int32(sp, p->name.name_type); + if(ret) + return ret; + } + + return 0; +} + +static krb5_error_code +fkt_resolve(krb5_context context, const char *name, krb5_keytab id) +{ + struct fkt_data *d; + + d = malloc(sizeof(*d)); + if(d == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + d->filename = strdup(name); + if(d->filename == NULL) { + free(d); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + d->flags = 0; + id->data = d; + return 0; +} + +static krb5_error_code +fkt_resolve_java14(krb5_context context, const char *name, krb5_keytab id) +{ + krb5_error_code ret; + + ret = fkt_resolve(context, name, id); + if (ret == 0) { + struct fkt_data *d = id->data; + d->flags |= KRB5_KT_FL_JAVA; + } + return ret; +} + +static krb5_error_code +fkt_close(krb5_context context, krb5_keytab id) +{ + struct fkt_data *d = id->data; + free(d->filename); + free(d); + return 0; +} + +static krb5_error_code +fkt_get_name(krb5_context context, + krb5_keytab id, + char *name, + size_t namesize) +{ + /* This function is XXX */ + struct fkt_data *d = id->data; + strlcpy(name, d->filename, namesize); + return 0; +} + +static void +storage_set_flags(krb5_context context, krb5_storage *sp, int vno) +{ + int flags = 0; + switch(vno) { + case KRB5_KT_VNO_1: + flags |= KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS; + flags |= KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE; + flags |= KRB5_STORAGE_HOST_BYTEORDER; + break; + case KRB5_KT_VNO_2: + break; + default: + krb5_warnx(context, + "storage_set_flags called with bad vno (%d)", vno); + } + krb5_storage_set_flags(sp, flags); +} + +static krb5_error_code +fkt_start_seq_get_int(krb5_context context, + krb5_keytab id, + int flags, + int exclusive, + krb5_kt_cursor *c) +{ + int8_t pvno, tag; + krb5_error_code ret; + struct fkt_data *d = id->data; + + c->fd = open (d->filename, flags); + if (c->fd < 0) { + ret = errno; + krb5_set_error_string(context, "%s: %s", d->filename, + strerror(ret)); + return ret; + } + ret = _krb5_xlock(context, c->fd, exclusive, d->filename); + if (ret) { + close(c->fd); + return ret; + } + c->sp = krb5_storage_from_fd(c->fd); + if (c->sp == NULL) { + _krb5_xunlock(context, c->fd); + close(c->fd); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + krb5_storage_set_eof_code(c->sp, KRB5_KT_END); + ret = krb5_ret_int8(c->sp, &pvno); + if(ret) { + krb5_storage_free(c->sp); + _krb5_xunlock(context, c->fd); + close(c->fd); + krb5_clear_error_string(context); + return ret; + } + if(pvno != 5) { + krb5_storage_free(c->sp); + _krb5_xunlock(context, c->fd); + close(c->fd); + krb5_clear_error_string (context); + return KRB5_KEYTAB_BADVNO; + } + ret = krb5_ret_int8(c->sp, &tag); + if (ret) { + krb5_storage_free(c->sp); + _krb5_xunlock(context, c->fd); + close(c->fd); + krb5_clear_error_string(context); + return ret; + } + id->version = tag; + storage_set_flags(context, c->sp, id->version); + return 0; +} + +static krb5_error_code +fkt_start_seq_get(krb5_context context, + krb5_keytab id, + krb5_kt_cursor *c) +{ + return fkt_start_seq_get_int(context, id, O_RDONLY | O_BINARY, 0, c); +} + +static krb5_error_code +fkt_next_entry_int(krb5_context context, + krb5_keytab id, + krb5_keytab_entry *entry, + krb5_kt_cursor *cursor, + off_t *start, + off_t *end) +{ + int32_t len; + int ret; + int8_t tmp8; + int32_t tmp32; + off_t pos, curpos; + + pos = krb5_storage_seek(cursor->sp, 0, SEEK_CUR); +loop: + ret = krb5_ret_int32(cursor->sp, &len); + if (ret) + return ret; + if(len < 0) { + pos = krb5_storage_seek(cursor->sp, -len, SEEK_CUR); + goto loop; + } + ret = krb5_kt_ret_principal (context, cursor->sp, &entry->principal); + if (ret) + goto out; + ret = krb5_ret_int32(cursor->sp, &tmp32); + entry->timestamp = tmp32; + if (ret) + goto out; + ret = krb5_ret_int8(cursor->sp, &tmp8); + if (ret) + goto out; + entry->vno = tmp8; + ret = krb5_kt_ret_keyblock (context, cursor->sp, &entry->keyblock); + if (ret) + goto out; + /* there might be a 32 bit kvno here + * if it's zero, assume that the 8bit one was right, + * otherwise trust the new value */ + curpos = krb5_storage_seek(cursor->sp, 0, SEEK_CUR); + if(len + 4 + pos - curpos >= 4) { + ret = krb5_ret_int32(cursor->sp, &tmp32); + if (ret == 0 && tmp32 != 0) { + entry->vno = tmp32; + } + } + if(start) *start = pos; + if(end) *end = pos + 4 + len; + out: + krb5_storage_seek(cursor->sp, pos + 4 + len, SEEK_SET); + return ret; +} + +static krb5_error_code +fkt_next_entry(krb5_context context, + krb5_keytab id, + krb5_keytab_entry *entry, + krb5_kt_cursor *cursor) +{ + return fkt_next_entry_int(context, id, entry, cursor, NULL, NULL); +} + +static krb5_error_code +fkt_end_seq_get(krb5_context context, + krb5_keytab id, + krb5_kt_cursor *cursor) +{ + krb5_storage_free(cursor->sp); + _krb5_xunlock(context, cursor->fd); + close(cursor->fd); + return 0; +} + +static krb5_error_code +fkt_setup_keytab(krb5_context context, + krb5_keytab id, + krb5_storage *sp) +{ + krb5_error_code ret; + ret = krb5_store_int8(sp, 5); + if(ret) + return ret; + if(id->version == 0) + id->version = KRB5_KT_VNO; + return krb5_store_int8 (sp, id->version); +} + +static krb5_error_code +fkt_add_entry(krb5_context context, + krb5_keytab id, + krb5_keytab_entry *entry) +{ + int ret; + int fd; + krb5_storage *sp; + struct fkt_data *d = id->data; + krb5_data keytab; + int32_t len; + + fd = open (d->filename, O_RDWR | O_BINARY); + if (fd < 0) { + fd = open (d->filename, O_RDWR | O_CREAT | O_EXCL | O_BINARY, 0600); + if (fd < 0) { + ret = errno; + krb5_set_error_string(context, "open(%s): %s", d->filename, + strerror(ret)); + return ret; + } + ret = _krb5_xlock(context, fd, 1, d->filename); + if (ret) { + close(fd); + return ret; + } + sp = krb5_storage_from_fd(fd); + krb5_storage_set_eof_code(sp, KRB5_KT_END); + ret = fkt_setup_keytab(context, id, sp); + if(ret) { + goto out; + } + storage_set_flags(context, sp, id->version); + } else { + int8_t pvno, tag; + ret = _krb5_xlock(context, fd, 1, d->filename); + if (ret) { + close(fd); + return ret; + } + sp = krb5_storage_from_fd(fd); + krb5_storage_set_eof_code(sp, KRB5_KT_END); + ret = krb5_ret_int8(sp, &pvno); + if(ret) { + /* we probably have a zero byte file, so try to set it up + properly */ + ret = fkt_setup_keytab(context, id, sp); + if(ret) { + krb5_set_error_string(context, "%s: keytab is corrupted: %s", + d->filename, strerror(ret)); + goto out; + } + storage_set_flags(context, sp, id->version); + } else { + if(pvno != 5) { + ret = KRB5_KEYTAB_BADVNO; + krb5_set_error_string(context, "%s: %s", + d->filename, strerror(ret)); + goto out; + } + ret = krb5_ret_int8 (sp, &tag); + if (ret) { + krb5_set_error_string(context, "%s: reading tag: %s", + d->filename, strerror(ret)); + goto out; + } + id->version = tag; + storage_set_flags(context, sp, id->version); + } + } + + { + krb5_storage *emem; + emem = krb5_storage_emem(); + if(emem == NULL) { + ret = ENOMEM; + krb5_set_error_string (context, "malloc: out of memory"); + goto out; + } + ret = krb5_kt_store_principal(context, emem, entry->principal); + if(ret) { + krb5_storage_free(emem); + goto out; + } + ret = krb5_store_int32 (emem, entry->timestamp); + if(ret) { + krb5_storage_free(emem); + goto out; + } + ret = krb5_store_int8 (emem, entry->vno % 256); + if(ret) { + krb5_storage_free(emem); + goto out; + } + ret = krb5_kt_store_keyblock (context, emem, &entry->keyblock); + if(ret) { + krb5_storage_free(emem); + goto out; + } + if ((d->flags & KRB5_KT_FL_JAVA) == 0) { + ret = krb5_store_int32 (emem, entry->vno); + if (ret) { + krb5_storage_free(emem); + goto out; + } + } + + ret = krb5_storage_to_data(emem, &keytab); + krb5_storage_free(emem); + if(ret) + goto out; + } + + while(1) { + ret = krb5_ret_int32(sp, &len); + if(ret == KRB5_KT_END) { + len = keytab.length; + break; + } + if(len < 0) { + len = -len; + if(len >= keytab.length) { + krb5_storage_seek(sp, -4, SEEK_CUR); + break; + } + } + krb5_storage_seek(sp, len, SEEK_CUR); + } + ret = krb5_store_int32(sp, len); + if(krb5_storage_write(sp, keytab.data, keytab.length) < 0) + ret = errno; + memset(keytab.data, 0, keytab.length); + krb5_data_free(&keytab); + out: + krb5_storage_free(sp); + _krb5_xunlock(context, fd); + close(fd); + return ret; +} + +static krb5_error_code +fkt_remove_entry(krb5_context context, + krb5_keytab id, + krb5_keytab_entry *entry) +{ + krb5_keytab_entry e; + krb5_kt_cursor cursor; + off_t pos_start, pos_end; + int found = 0; + krb5_error_code ret; + + ret = fkt_start_seq_get_int(context, id, O_RDWR | O_BINARY, 1, &cursor); + if(ret != 0) + goto out; /* return other error here? */ + while(fkt_next_entry_int(context, id, &e, &cursor, + &pos_start, &pos_end) == 0) { + if(krb5_kt_compare(context, &e, entry->principal, + entry->vno, entry->keyblock.keytype)) { + int32_t len; + unsigned char buf[128]; + found = 1; + krb5_storage_seek(cursor.sp, pos_start, SEEK_SET); + len = pos_end - pos_start - 4; + krb5_store_int32(cursor.sp, -len); + memset(buf, 0, sizeof(buf)); + while(len > 0) { + krb5_storage_write(cursor.sp, buf, min(len, sizeof(buf))); + len -= min(len, sizeof(buf)); + } + } + krb5_kt_free_entry(context, &e); + } + krb5_kt_end_seq_get(context, id, &cursor); + out: + if (!found) { + krb5_clear_error_string (context); + return KRB5_KT_NOTFOUND; + } + return 0; +} + +const krb5_kt_ops krb5_fkt_ops = { + "FILE", + fkt_resolve, + fkt_get_name, + fkt_close, + NULL, /* get */ + fkt_start_seq_get, + fkt_next_entry, + fkt_end_seq_get, + fkt_add_entry, + fkt_remove_entry +}; + +const krb5_kt_ops krb5_wrfkt_ops = { + "WRFILE", + fkt_resolve, + fkt_get_name, + fkt_close, + NULL, /* get */ + fkt_start_seq_get, + fkt_next_entry, + fkt_end_seq_get, + fkt_add_entry, + fkt_remove_entry +}; + +const krb5_kt_ops krb5_javakt_ops = { + "JAVA14", + fkt_resolve_java14, + fkt_get_name, + fkt_close, + NULL, /* get */ + fkt_start_seq_get, + fkt_next_entry, + fkt_end_seq_get, + fkt_add_entry, + fkt_remove_entry +}; diff --git a/lib/krb5/keytab_keyfile.c b/lib/krb5/keytab_keyfile.c new file mode 100644 index 0000000..77455ba --- /dev/null +++ b/lib/krb5/keytab_keyfile.c @@ -0,0 +1,420 @@ +/* + * Copyright (c) 1997 - 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: keytab_keyfile.c 20695 2007-05-30 14:09:09Z lha $"); + +/* afs keyfile operations --------------------------------------- */ + +/* + * Minimum tools to handle the AFS KeyFile. + * + * Format of the KeyFile is: + * <int32_t numkeys> {[<int32_t kvno> <char[8] deskey>] * numkeys} + * + * It just adds to the end of the keyfile, deleting isn't implemented. + * Use your favorite text/hex editor to delete keys. + * + */ + +#define AFS_SERVERTHISCELL "/usr/afs/etc/ThisCell" +#define AFS_SERVERMAGICKRBCONF "/usr/afs/etc/krb.conf" + +struct akf_data { + int num_entries; + char *filename; + char *cell; + char *realm; +}; + +/* + * set `d->cell' and `d->realm' + */ + +static int +get_cell_and_realm (krb5_context context, struct akf_data *d) +{ + FILE *f; + char buf[BUFSIZ], *cp; + int ret; + + f = fopen (AFS_SERVERTHISCELL, "r"); + if (f == NULL) { + ret = errno; + krb5_set_error_string (context, "open %s: %s", AFS_SERVERTHISCELL, + strerror(ret)); + return ret; + } + if (fgets (buf, sizeof(buf), f) == NULL) { + fclose (f); + krb5_set_error_string (context, "no cell in %s", AFS_SERVERTHISCELL); + return EINVAL; + } + buf[strcspn(buf, "\n")] = '\0'; + fclose(f); + + d->cell = strdup (buf); + if (d->cell == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + + f = fopen (AFS_SERVERMAGICKRBCONF, "r"); + if (f != NULL) { + if (fgets (buf, sizeof(buf), f) == NULL) { + free (d->cell); + d->cell = NULL; + fclose (f); + krb5_set_error_string (context, "no realm in %s", + AFS_SERVERMAGICKRBCONF); + return EINVAL; + } + buf[strcspn(buf, "\n")] = '\0'; + fclose(f); + } + /* uppercase */ + for (cp = buf; *cp != '\0'; cp++) + *cp = toupper((unsigned char)*cp); + + d->realm = strdup (buf); + if (d->realm == NULL) { + free (d->cell); + d->cell = NULL; + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + return 0; +} + +/* + * init and get filename + */ + +static krb5_error_code +akf_resolve(krb5_context context, const char *name, krb5_keytab id) +{ + int ret; + struct akf_data *d = malloc(sizeof (struct akf_data)); + + if (d == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + + d->num_entries = 0; + ret = get_cell_and_realm (context, d); + if (ret) { + free (d); + return ret; + } + d->filename = strdup (name); + if (d->filename == NULL) { + free (d->cell); + free (d->realm); + free (d); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + id->data = d; + + return 0; +} + +/* + * cleanup + */ + +static krb5_error_code +akf_close(krb5_context context, krb5_keytab id) +{ + struct akf_data *d = id->data; + + free (d->filename); + free (d->cell); + free (d); + return 0; +} + +/* + * Return filename + */ + +static krb5_error_code +akf_get_name(krb5_context context, + krb5_keytab id, + char *name, + size_t name_sz) +{ + struct akf_data *d = id->data; + + strlcpy (name, d->filename, name_sz); + return 0; +} + +/* + * Init + */ + +static krb5_error_code +akf_start_seq_get(krb5_context context, + krb5_keytab id, + krb5_kt_cursor *c) +{ + int32_t ret; + struct akf_data *d = id->data; + + c->fd = open (d->filename, O_RDONLY|O_BINARY, 0600); + if (c->fd < 0) { + ret = errno; + krb5_set_error_string(context, "open(%s): %s", d->filename, + strerror(ret)); + return ret; + } + + c->sp = krb5_storage_from_fd(c->fd); + ret = krb5_ret_int32(c->sp, &d->num_entries); + if(ret) { + krb5_storage_free(c->sp); + close(c->fd); + krb5_clear_error_string (context); + if(ret == KRB5_KT_END) + return KRB5_KT_NOTFOUND; + return ret; + } + + return 0; +} + +static krb5_error_code +akf_next_entry(krb5_context context, + krb5_keytab id, + krb5_keytab_entry *entry, + krb5_kt_cursor *cursor) +{ + struct akf_data *d = id->data; + int32_t kvno; + off_t pos; + int ret; + + pos = krb5_storage_seek(cursor->sp, 0, SEEK_CUR); + + if ((pos - 4) / (4 + 8) >= d->num_entries) + return KRB5_KT_END; + + ret = krb5_make_principal (context, &entry->principal, + d->realm, "afs", d->cell, NULL); + if (ret) + goto out; + + ret = krb5_ret_int32(cursor->sp, &kvno); + if (ret) { + krb5_free_principal (context, entry->principal); + goto out; + } + + entry->vno = kvno; + + entry->keyblock.keytype = ETYPE_DES_CBC_MD5; + entry->keyblock.keyvalue.length = 8; + entry->keyblock.keyvalue.data = malloc (8); + if (entry->keyblock.keyvalue.data == NULL) { + krb5_free_principal (context, entry->principal); + krb5_set_error_string (context, "malloc: out of memory"); + ret = ENOMEM; + goto out; + } + + ret = krb5_storage_read(cursor->sp, entry->keyblock.keyvalue.data, 8); + if(ret != 8) + ret = (ret < 0) ? errno : KRB5_KT_END; + else + ret = 0; + + entry->timestamp = time(NULL); + + out: + krb5_storage_seek(cursor->sp, pos + 4 + 8, SEEK_SET); + return ret; +} + +static krb5_error_code +akf_end_seq_get(krb5_context context, + krb5_keytab id, + krb5_kt_cursor *cursor) +{ + krb5_storage_free(cursor->sp); + close(cursor->fd); + return 0; +} + +static krb5_error_code +akf_add_entry(krb5_context context, + krb5_keytab id, + krb5_keytab_entry *entry) +{ + struct akf_data *d = id->data; + int fd, created = 0; + krb5_error_code ret; + int32_t len; + krb5_storage *sp; + + + if (entry->keyblock.keyvalue.length != 8) + return 0; + switch(entry->keyblock.keytype) { + case ETYPE_DES_CBC_CRC: + case ETYPE_DES_CBC_MD4: + case ETYPE_DES_CBC_MD5: + break; + default: + return 0; + } + + fd = open (d->filename, O_RDWR | O_BINARY); + if (fd < 0) { + fd = open (d->filename, + O_RDWR | O_BINARY | O_CREAT | O_EXCL, 0600); + if (fd < 0) { + ret = errno; + krb5_set_error_string(context, "open(%s): %s", d->filename, + strerror(ret)); + return ret; + } + created = 1; + } + + sp = krb5_storage_from_fd(fd); + if(sp == NULL) { + close(fd); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + if (created) + len = 0; + else { + if(krb5_storage_seek(sp, 0, SEEK_SET) < 0) { + ret = errno; + krb5_storage_free(sp); + close(fd); + krb5_set_error_string (context, "seek: %s", strerror(ret)); + return ret; + } + + ret = krb5_ret_int32(sp, &len); + if(ret) { + krb5_storage_free(sp); + close(fd); + return ret; + } + } + + /* + * Make sure we don't add the entry twice, assumes the DES + * encryption types are all the same key. + */ + if (len > 0) { + int32_t kvno; + int i; + + for (i = 0; i < len; i++) { + ret = krb5_ret_int32(sp, &kvno); + if (ret) { + krb5_set_error_string (context, "Failed to get kvno "); + goto out; + } + if(krb5_storage_seek(sp, 8, SEEK_CUR) < 0) { + krb5_set_error_string (context, "seek: %s", strerror(ret)); + goto out; + } + if (kvno == entry->vno) { + ret = 0; + goto out; + } + } + } + + len++; + + if(krb5_storage_seek(sp, 0, SEEK_SET) < 0) { + ret = errno; + krb5_set_error_string (context, "seek: %s", strerror(ret)); + goto out; + } + + ret = krb5_store_int32(sp, len); + if(ret) { + krb5_set_error_string(context, "keytab keyfile failed new length"); + return ret; + } + + if(krb5_storage_seek(sp, (len - 1) * (8 + 4), SEEK_CUR) < 0) { + ret = errno; + krb5_set_error_string (context, "seek to end: %s", strerror(ret)); + goto out; + } + + ret = krb5_store_int32(sp, entry->vno); + if(ret) { + krb5_set_error_string(context, "keytab keyfile failed store kvno"); + goto out; + } + ret = krb5_storage_write(sp, entry->keyblock.keyvalue.data, + entry->keyblock.keyvalue.length); + if(ret != entry->keyblock.keyvalue.length) { + if (ret < 0) + ret = errno; + else + ret = ENOTTY; + krb5_set_error_string(context, "keytab keyfile failed to add key"); + goto out; + } + ret = 0; +out: + krb5_storage_free(sp); + close (fd); + return ret; +} + +const krb5_kt_ops krb5_akf_ops = { + "AFSKEYFILE", + akf_resolve, + akf_get_name, + akf_close, + NULL, /* get */ + akf_start_seq_get, + akf_next_entry, + akf_end_seq_get, + akf_add_entry, + NULL /* remove */ +}; diff --git a/lib/krb5/keytab_krb4.c b/lib/krb5/keytab_krb4.c new file mode 100644 index 0000000..907836c --- /dev/null +++ b/lib/krb5/keytab_krb4.c @@ -0,0 +1,448 @@ +/* + * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: keytab_krb4.c 17046 2006-04-10 17:10:53Z lha $"); + +struct krb4_kt_data { + char *filename; +}; + +static krb5_error_code +krb4_kt_resolve(krb5_context context, const char *name, krb5_keytab id) +{ + struct krb4_kt_data *d; + + d = malloc (sizeof(*d)); + if (d == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + d->filename = strdup (name); + if (d->filename == NULL) { + free(d); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + id->data = d; + return 0; +} + +static krb5_error_code +krb4_kt_get_name (krb5_context context, + krb5_keytab id, + char *name, + size_t name_sz) +{ + struct krb4_kt_data *d = id->data; + + strlcpy (name, d->filename, name_sz); + return 0; +} + +static krb5_error_code +krb4_kt_close (krb5_context context, + krb5_keytab id) +{ + struct krb4_kt_data *d = id->data; + + free (d->filename); + free (d); + return 0; +} + +struct krb4_cursor_extra_data { + krb5_keytab_entry entry; + int num; +}; + +static int +open_flock(const char *filename, int flags, int mode) +{ + int lock_mode; + int tries = 0; + int fd = open(filename, flags, mode); + if(fd < 0) + return fd; + if((flags & O_ACCMODE) == O_RDONLY) + lock_mode = LOCK_SH | LOCK_NB; + else + lock_mode = LOCK_EX | LOCK_NB; + while(flock(fd, lock_mode) < 0) { + if(++tries < 5) { + sleep(1); + } else { + close(fd); + return -1; + } + } + return fd; +} + + + +static krb5_error_code +krb4_kt_start_seq_get_int (krb5_context context, + krb5_keytab id, + int flags, + krb5_kt_cursor *c) +{ + struct krb4_kt_data *d = id->data; + struct krb4_cursor_extra_data *ed; + int ret; + + ed = malloc (sizeof(*ed)); + if (ed == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + ed->entry.principal = NULL; + ed->num = -1; + c->data = ed; + c->fd = open_flock (d->filename, flags, 0); + if (c->fd < 0) { + ret = errno; + free (ed); + krb5_set_error_string(context, "open(%s): %s", d->filename, + strerror(ret)); + return ret; + } + c->sp = krb5_storage_from_fd(c->fd); + if(c->sp == NULL) { + close(c->fd); + free(ed); + return ENOMEM; + } + krb5_storage_set_eof_code(c->sp, KRB5_KT_END); + return 0; +} + +static krb5_error_code +krb4_kt_start_seq_get (krb5_context context, + krb5_keytab id, + krb5_kt_cursor *c) +{ + return krb4_kt_start_seq_get_int (context, id, O_BINARY | O_RDONLY, c); +} + +static krb5_error_code +read_v4_entry (krb5_context context, + struct krb4_kt_data *d, + krb5_kt_cursor *c, + struct krb4_cursor_extra_data *ed) +{ + unsigned char des_key[8]; + krb5_error_code ret; + char *service, *instance, *realm; + int8_t kvno; + + ret = krb5_ret_stringz(c->sp, &service); + if (ret) + return ret; + ret = krb5_ret_stringz(c->sp, &instance); + if (ret) { + free (service); + return ret; + } + ret = krb5_ret_stringz(c->sp, &realm); + if (ret) { + free (service); + free (instance); + return ret; + } + ret = krb5_425_conv_principal (context, service, instance, realm, + &ed->entry.principal); + free (service); + free (instance); + free (realm); + if (ret) + return ret; + ret = krb5_ret_int8(c->sp, &kvno); + if (ret) { + krb5_free_principal (context, ed->entry.principal); + return ret; + } + ret = krb5_storage_read(c->sp, des_key, sizeof(des_key)); + if (ret < 0) { + krb5_free_principal(context, ed->entry.principal); + return ret; + } + if (ret < 8) { + krb5_free_principal(context, ed->entry.principal); + return EINVAL; + } + ed->entry.vno = kvno; + ret = krb5_data_copy (&ed->entry.keyblock.keyvalue, + des_key, sizeof(des_key)); + if (ret) + return ret; + ed->entry.timestamp = time(NULL); + ed->num = 0; + return 0; +} + +static krb5_error_code +krb4_kt_next_entry (krb5_context context, + krb5_keytab id, + krb5_keytab_entry *entry, + krb5_kt_cursor *c) +{ + krb5_error_code ret; + struct krb4_kt_data *d = id->data; + struct krb4_cursor_extra_data *ed = c->data; + const krb5_enctype keytypes[] = {ETYPE_DES_CBC_MD5, + ETYPE_DES_CBC_MD4, + ETYPE_DES_CBC_CRC}; + + if (ed->num == -1) { + ret = read_v4_entry (context, d, c, ed); + if (ret) + return ret; + } + ret = krb5_kt_copy_entry_contents (context, + &ed->entry, + entry); + if (ret) + return ret; + entry->keyblock.keytype = keytypes[ed->num]; + if (++ed->num == 3) { + krb5_kt_free_entry (context, &ed->entry); + ed->num = -1; + } + return 0; +} + +static krb5_error_code +krb4_kt_end_seq_get (krb5_context context, + krb5_keytab id, + krb5_kt_cursor *c) +{ + struct krb4_cursor_extra_data *ed = c->data; + + krb5_storage_free (c->sp); + if (ed->num != -1) + krb5_kt_free_entry (context, &ed->entry); + free (c->data); + close (c->fd); + return 0; +} + +static krb5_error_code +krb4_store_keytab_entry(krb5_context context, + krb5_keytab_entry *entry, + krb5_storage *sp) +{ + krb5_error_code ret; +#define ANAME_SZ 40 +#define INST_SZ 40 +#define REALM_SZ 40 + char service[ANAME_SZ]; + char instance[INST_SZ]; + char realm[REALM_SZ]; + ret = krb5_524_conv_principal (context, entry->principal, + service, instance, realm); + if (ret) + return ret; + if (entry->keyblock.keyvalue.length == 8 + && entry->keyblock.keytype == ETYPE_DES_CBC_MD5) { + ret = krb5_store_stringz(sp, service); + ret = krb5_store_stringz(sp, instance); + ret = krb5_store_stringz(sp, realm); + ret = krb5_store_int8(sp, entry->vno); + ret = krb5_storage_write(sp, entry->keyblock.keyvalue.data, 8); + } + return 0; +} + +static krb5_error_code +krb4_kt_add_entry (krb5_context context, + krb5_keytab id, + krb5_keytab_entry *entry) +{ + struct krb4_kt_data *d = id->data; + krb5_storage *sp; + krb5_error_code ret; + int fd; + + fd = open_flock (d->filename, O_WRONLY | O_APPEND | O_BINARY, 0); + if (fd < 0) { + fd = open_flock (d->filename, + O_WRONLY | O_APPEND | O_BINARY | O_CREAT, 0600); + if (fd < 0) { + ret = errno; + krb5_set_error_string(context, "open(%s): %s", d->filename, + strerror(ret)); + return ret; + } + } + sp = krb5_storage_from_fd(fd); + if(sp == NULL) { + close(fd); + return ENOMEM; + } + krb5_storage_set_eof_code(sp, KRB5_KT_END); + ret = krb4_store_keytab_entry(context, entry, sp); + krb5_storage_free(sp); + if(close (fd) < 0) + return errno; + return ret; +} + +static krb5_error_code +krb4_kt_remove_entry(krb5_context context, + krb5_keytab id, + krb5_keytab_entry *entry) +{ + struct krb4_kt_data *d = id->data; + krb5_error_code ret; + krb5_keytab_entry e; + krb5_kt_cursor cursor; + krb5_storage *sp; + int remove_flag = 0; + + sp = krb5_storage_emem(); + if (sp == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + ret = krb5_kt_start_seq_get(context, id, &cursor); + if (ret) { + krb5_storage_free(sp); + return ret; + } + while(krb5_kt_next_entry(context, id, &e, &cursor) == 0) { + if(!krb5_kt_compare(context, &e, entry->principal, + entry->vno, entry->keyblock.keytype)) { + ret = krb4_store_keytab_entry(context, &e, sp); + if(ret) { + krb5_kt_free_entry(context, &e); + krb5_storage_free(sp); + return ret; + } + } else + remove_flag = 1; + krb5_kt_free_entry(context, &e); + } + krb5_kt_end_seq_get(context, id, &cursor); + if(remove_flag) { + int fd; + unsigned char buf[1024]; + ssize_t n; + krb5_data data; + struct stat st; + + krb5_storage_to_data(sp, &data); + krb5_storage_free(sp); + + fd = open_flock (d->filename, O_RDWR | O_BINARY, 0); + if(fd < 0) { + memset(data.data, 0, data.length); + krb5_data_free(&data); + if(errno == EACCES || errno == EROFS) + return KRB5_KT_NOWRITE; + return errno; + } + + if(write(fd, data.data, data.length) != data.length) { + memset(data.data, 0, data.length); + krb5_data_free(&data); + close(fd); + krb5_set_error_string(context, "failed writing to \"%s\"", d->filename); + return errno; + } + memset(data.data, 0, data.length); + if(fstat(fd, &st) < 0) { + krb5_data_free(&data); + close(fd); + krb5_set_error_string(context, "failed getting size of \"%s\"", d->filename); + return errno; + } + st.st_size -= data.length; + memset(buf, 0, sizeof(buf)); + while(st.st_size > 0) { + n = min(st.st_size, sizeof(buf)); + n = write(fd, buf, n); + if(n <= 0) { + krb5_data_free(&data); + close(fd); + krb5_set_error_string(context, "failed writing to \"%s\"", d->filename); + return errno; + + } + st.st_size -= n; + } + if(ftruncate(fd, data.length) < 0) { + krb5_data_free(&data); + close(fd); + krb5_set_error_string(context, "failed truncating \"%s\"", d->filename); + return errno; + } + krb5_data_free(&data); + if(close(fd) < 0) { + krb5_set_error_string(context, "error closing \"%s\"", d->filename); + return errno; + } + return 0; + } else { + krb5_storage_free(sp); + return KRB5_KT_NOTFOUND; + } +} + + +const krb5_kt_ops krb4_fkt_ops = { + "krb4", + krb4_kt_resolve, + krb4_kt_get_name, + krb4_kt_close, + NULL, /* get */ + krb4_kt_start_seq_get, + krb4_kt_next_entry, + krb4_kt_end_seq_get, + krb4_kt_add_entry, /* add_entry */ + krb4_kt_remove_entry /* remove_entry */ +}; + +const krb5_kt_ops krb5_srvtab_fkt_ops = { + "SRVTAB", + krb4_kt_resolve, + krb4_kt_get_name, + krb4_kt_close, + NULL, /* get */ + krb4_kt_start_seq_get, + krb4_kt_next_entry, + krb4_kt_end_seq_get, + krb4_kt_add_entry, /* add_entry */ + krb4_kt_remove_entry /* remove_entry */ +}; diff --git a/lib/krb5/keytab_memory.c b/lib/krb5/keytab_memory.c new file mode 100644 index 0000000..0ad8720 --- /dev/null +++ b/lib/krb5/keytab_memory.c @@ -0,0 +1,234 @@ +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: keytab_memory.c 16352 2005-12-05 18:39:46Z lha $"); + +/* memory operations -------------------------------------------- */ + +struct mkt_data { + krb5_keytab_entry *entries; + int num_entries; + char *name; + int refcount; + struct mkt_data *next; +}; + +/* this mutex protects mkt_head, ->refcount, and ->next + * content is not protected (name is static and need no protection) + */ +static HEIMDAL_MUTEX mkt_mutex = HEIMDAL_MUTEX_INITIALIZER; +static struct mkt_data *mkt_head; + + +static krb5_error_code +mkt_resolve(krb5_context context, const char *name, krb5_keytab id) +{ + struct mkt_data *d; + + HEIMDAL_MUTEX_lock(&mkt_mutex); + + for (d = mkt_head; d != NULL; d = d->next) + if (strcmp(d->name, name) == 0) + break; + if (d) { + if (d->refcount < 1) + krb5_abortx(context, "Double close on memory keytab, " + "refcount < 1 %d", d->refcount); + d->refcount++; + id->data = d; + HEIMDAL_MUTEX_unlock(&mkt_mutex); + return 0; + } + + d = calloc(1, sizeof(*d)); + if(d == NULL) { + HEIMDAL_MUTEX_unlock(&mkt_mutex); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + d->name = strdup(name); + if (d->name == NULL) { + HEIMDAL_MUTEX_unlock(&mkt_mutex); + free(d); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + d->entries = NULL; + d->num_entries = 0; + d->refcount = 1; + d->next = mkt_head; + mkt_head = d; + HEIMDAL_MUTEX_unlock(&mkt_mutex); + id->data = d; + return 0; +} + +static krb5_error_code +mkt_close(krb5_context context, krb5_keytab id) +{ + struct mkt_data *d = id->data, **dp; + int i; + + HEIMDAL_MUTEX_lock(&mkt_mutex); + if (d->refcount < 1) + krb5_abortx(context, + "krb5 internal error, memory keytab refcount < 1 on close"); + + if (--d->refcount > 0) { + HEIMDAL_MUTEX_unlock(&mkt_mutex); + return 0; + } + for (dp = &mkt_head; *dp != NULL; dp = &(*dp)->next) { + if (*dp == d) { + *dp = d->next; + break; + } + } + HEIMDAL_MUTEX_unlock(&mkt_mutex); + + free(d->name); + for(i = 0; i < d->num_entries; i++) + krb5_kt_free_entry(context, &d->entries[i]); + free(d->entries); + free(d); + return 0; +} + +static krb5_error_code +mkt_get_name(krb5_context context, + krb5_keytab id, + char *name, + size_t namesize) +{ + struct mkt_data *d = id->data; + strlcpy(name, d->name, namesize); + return 0; +} + +static krb5_error_code +mkt_start_seq_get(krb5_context context, + krb5_keytab id, + krb5_kt_cursor *c) +{ + /* XXX */ + c->fd = 0; + return 0; +} + +static krb5_error_code +mkt_next_entry(krb5_context context, + krb5_keytab id, + krb5_keytab_entry *entry, + krb5_kt_cursor *c) +{ + struct mkt_data *d = id->data; + if(c->fd >= d->num_entries) + return KRB5_KT_END; + return krb5_kt_copy_entry_contents(context, &d->entries[c->fd++], entry); +} + +static krb5_error_code +mkt_end_seq_get(krb5_context context, + krb5_keytab id, + krb5_kt_cursor *cursor) +{ + return 0; +} + +static krb5_error_code +mkt_add_entry(krb5_context context, + krb5_keytab id, + krb5_keytab_entry *entry) +{ + struct mkt_data *d = id->data; + krb5_keytab_entry *tmp; + tmp = realloc(d->entries, (d->num_entries + 1) * sizeof(*d->entries)); + if(tmp == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + d->entries = tmp; + return krb5_kt_copy_entry_contents(context, entry, + &d->entries[d->num_entries++]); +} + +static krb5_error_code +mkt_remove_entry(krb5_context context, + krb5_keytab id, + krb5_keytab_entry *entry) +{ + struct mkt_data *d = id->data; + krb5_keytab_entry *e, *end; + int found = 0; + + if (d->num_entries == 0) { + krb5_clear_error_string(context); + return KRB5_KT_NOTFOUND; + } + + /* do this backwards to minimize copying */ + for(end = d->entries + d->num_entries, e = end - 1; e >= d->entries; e--) { + if(krb5_kt_compare(context, e, entry->principal, + entry->vno, entry->keyblock.keytype)) { + krb5_kt_free_entry(context, e); + memmove(e, e + 1, (end - e - 1) * sizeof(*e)); + memset(end - 1, 0, sizeof(*end)); + d->num_entries--; + end--; + found = 1; + } + } + if (!found) { + krb5_clear_error_string (context); + return KRB5_KT_NOTFOUND; + } + e = realloc(d->entries, d->num_entries * sizeof(*d->entries)); + if(e != NULL || d->num_entries == 0) + d->entries = e; + return 0; +} + +const krb5_kt_ops krb5_mkt_ops = { + "MEMORY", + mkt_resolve, + mkt_get_name, + mkt_close, + NULL, /* get */ + mkt_start_seq_get, + mkt_next_entry, + mkt_end_seq_get, + mkt_add_entry, + mkt_remove_entry +}; diff --git a/lib/krb5/krb5-private.h b/lib/krb5/krb5-private.h new file mode 100644 index 0000000..7e04446 --- /dev/null +++ b/lib/krb5/krb5-private.h @@ -0,0 +1,447 @@ +/* This is a generated file */ +#ifndef __krb5_private_h__ +#define __krb5_private_h__ + +#include <stdarg.h> + +void KRB5_LIB_FUNCTION +_krb5_aes_cts_encrypt ( + const unsigned char */*in*/, + unsigned char */*out*/, + size_t /*len*/, + const AES_KEY */*key*/, + unsigned char */*ivec*/, + const int /*encryptp*/); + +krb5_error_code +_krb5_cc_allocate ( + krb5_context /*context*/, + const krb5_cc_ops */*ops*/, + krb5_ccache */*id*/); + +void +_krb5_crc_init_table (void); + +uint32_t +_krb5_crc_update ( + const char */*p*/, + size_t /*len*/, + uint32_t /*res*/); + +krb5_error_code +_krb5_dh_group_ok ( + krb5_context /*context*/, + unsigned long /*bits*/, + heim_integer */*p*/, + heim_integer */*g*/, + heim_integer */*q*/, + struct krb5_dh_moduli **/*moduli*/, + char **/*name*/); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_enctype_to_oid ( + krb5_context /*context*/, + krb5_enctype /*etype*/, + heim_oid */*oid*/); + +krb5_error_code +_krb5_expand_default_cc_name ( + krb5_context /*context*/, + const char */*str*/, + char **/*res*/); + +int +_krb5_extract_ticket ( + krb5_context /*context*/, + krb5_kdc_rep */*rep*/, + krb5_creds */*creds*/, + krb5_keyblock */*key*/, + krb5_const_pointer /*keyseed*/, + krb5_key_usage /*key_usage*/, + krb5_addresses */*addrs*/, + unsigned /*nonce*/, + unsigned /*flags*/, + krb5_decrypt_proc /*decrypt_proc*/, + krb5_const_pointer /*decryptarg*/); + +void +_krb5_free_krbhst_info (krb5_krbhst_info */*hi*/); + +void +_krb5_free_moduli (struct krb5_dh_moduli **/*moduli*/); + +krb5_error_code +_krb5_get_default_principal_local ( + krb5_context /*context*/, + krb5_principal */*princ*/); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_get_host_realm_int ( + krb5_context /*context*/, + const char */*host*/, + krb5_boolean /*use_dns*/, + krb5_realm **/*realms*/); + +krb5_error_code +_krb5_get_init_creds_opt_copy ( + krb5_context /*context*/, + const krb5_get_init_creds_opt */*in*/, + krb5_get_init_creds_opt **/*out*/); + +void KRB5_LIB_FUNCTION +_krb5_get_init_creds_opt_free_krb5_error (krb5_get_init_creds_opt */*opt*/); + +void KRB5_LIB_FUNCTION +_krb5_get_init_creds_opt_free_pkinit (krb5_get_init_creds_opt */*opt*/); + +void KRB5_LIB_FUNCTION +_krb5_get_init_creds_opt_set_krb5_error ( + krb5_context /*context*/, + krb5_get_init_creds_opt */*opt*/, + const KRB_ERROR */*error*/); + +krb5_ssize_t KRB5_LIB_FUNCTION +_krb5_get_int ( + void */*buffer*/, + unsigned long */*value*/, + size_t /*size*/); + +krb5_error_code +_krb5_get_krbtgt ( + krb5_context /*context*/, + krb5_ccache /*id*/, + krb5_realm /*realm*/, + krb5_creds **/*cred*/); + +krb5_error_code +_krb5_kcm_chmod ( + krb5_context /*context*/, + krb5_ccache /*id*/, + uint16_t /*mode*/); + +krb5_error_code +_krb5_kcm_chown ( + krb5_context /*context*/, + krb5_ccache /*id*/, + uint32_t /*uid*/, + uint32_t /*gid*/); + +krb5_error_code +_krb5_kcm_get_initial_ticket ( + krb5_context /*context*/, + krb5_ccache /*id*/, + krb5_principal /*server*/, + krb5_keyblock */*key*/); + +krb5_error_code +_krb5_kcm_get_ticket ( + krb5_context /*context*/, + krb5_ccache /*id*/, + krb5_kdc_flags /*flags*/, + krb5_enctype /*enctype*/, + krb5_principal /*server*/); + +krb5_boolean +_krb5_kcm_is_running (krb5_context /*context*/); + +krb5_error_code +_krb5_kcm_noop ( + krb5_context /*context*/, + krb5_ccache /*id*/); + +krb5_error_code +_krb5_kdc_retry ( + krb5_context /*context*/, + krb5_sendto_ctx /*ctx*/, + void */*data*/, + const krb5_data */*reply*/, + int */*action*/); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_krb_cr_err_reply ( + krb5_context /*context*/, + const char */*name*/, + const char */*inst*/, + const char */*realm*/, + uint32_t /*time_ws*/, + uint32_t /*e*/, + const char */*e_string*/, + krb5_data */*data*/); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_krb_create_auth_reply ( + krb5_context /*context*/, + const char */*pname*/, + const char */*pinst*/, + const char */*prealm*/, + int32_t /*time_ws*/, + int /*n*/, + uint32_t /*x_date*/, + unsigned char /*kvno*/, + const krb5_data */*cipher*/, + krb5_data */*data*/); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_krb_create_ciph ( + krb5_context /*context*/, + const krb5_keyblock */*session*/, + const char */*service*/, + const char */*instance*/, + const char */*realm*/, + uint32_t /*life*/, + unsigned char /*kvno*/, + const krb5_data */*ticket*/, + uint32_t /*kdc_time*/, + const krb5_keyblock */*key*/, + krb5_data */*enc_data*/); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_krb_create_ticket ( + krb5_context /*context*/, + unsigned char /*flags*/, + const char */*pname*/, + const char */*pinstance*/, + const char */*prealm*/, + int32_t /*paddress*/, + const krb5_keyblock */*session*/, + int16_t /*life*/, + int32_t /*life_sec*/, + const char */*sname*/, + const char */*sinstance*/, + const krb5_keyblock */*key*/, + krb5_data */*enc_data*/); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_krb_decomp_ticket ( + krb5_context /*context*/, + const krb5_data */*enc_ticket*/, + const krb5_keyblock */*key*/, + const char */*local_realm*/, + char **/*sname*/, + char **/*sinstance*/, + struct _krb5_krb_auth_data */*ad*/); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_krb_dest_tkt ( + krb5_context /*context*/, + const char */*tkfile*/); + +void KRB5_LIB_FUNCTION +_krb5_krb_free_auth_data ( + krb5_context /*context*/, + struct _krb5_krb_auth_data */*ad*/); + +time_t KRB5_LIB_FUNCTION +_krb5_krb_life_to_time ( + int /*start*/, + int /*life_*/); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_krb_rd_req ( + krb5_context /*context*/, + krb5_data */*authent*/, + const char */*service*/, + const char */*instance*/, + const char */*local_realm*/, + int32_t /*from_addr*/, + const krb5_keyblock */*key*/, + struct _krb5_krb_auth_data */*ad*/); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_krb_tf_setup ( + krb5_context /*context*/, + struct credentials */*v4creds*/, + const char */*tkfile*/, + int /*append*/); + +int KRB5_LIB_FUNCTION +_krb5_krb_time_to_life ( + time_t /*start*/, + time_t /*end*/); + +krb5_error_code +_krb5_krbhost_info_move ( + krb5_context /*context*/, + krb5_krbhst_info */*from*/, + krb5_krbhst_info **/*to*/); + +krb5_error_code +_krb5_mk_req_internal ( + krb5_context /*context*/, + krb5_auth_context */*auth_context*/, + const krb5_flags /*ap_req_options*/, + krb5_data */*in_data*/, + krb5_creds */*in_creds*/, + krb5_data */*outbuf*/, + krb5_key_usage /*checksum_usage*/, + krb5_key_usage /*encrypt_usage*/); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_n_fold ( + const void */*str*/, + size_t /*len*/, + void */*key*/, + size_t /*size*/); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_oid_to_enctype ( + krb5_context /*context*/, + const heim_oid */*oid*/, + krb5_enctype */*etype*/); + +krb5_error_code +_krb5_pac_sign ( + krb5_context /*context*/, + krb5_pac /*p*/, + time_t /*authtime*/, + krb5_principal /*principal*/, + const krb5_keyblock */*server_key*/, + const krb5_keyblock */*priv_key*/, + krb5_data */*data*/); + +krb5_error_code +_krb5_parse_moduli ( + krb5_context /*context*/, + const char */*file*/, + struct krb5_dh_moduli ***/*moduli*/); + +krb5_error_code +_krb5_parse_moduli_line ( + krb5_context /*context*/, + const char */*file*/, + int /*lineno*/, + char */*p*/, + struct krb5_dh_moduli **/*m*/); + +void KRB5_LIB_FUNCTION +_krb5_pk_allow_proxy_certificate ( + struct krb5_pk_identity */*id*/, + int /*boolean*/); + +void KRB5_LIB_FUNCTION +_krb5_pk_cert_free (struct krb5_pk_cert */*cert*/); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_pk_load_id ( + krb5_context /*context*/, + struct krb5_pk_identity **/*ret_id*/, + const char */*user_id*/, + const char */*anchor_id*/, + char * const */*chain_list*/, + char * const */*revoke_list*/, + krb5_prompter_fct /*prompter*/, + void */*prompter_data*/, + char */*password*/); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_pk_mk_ContentInfo ( + krb5_context /*context*/, + const krb5_data */*buf*/, + const heim_oid */*oid*/, + struct ContentInfo */*content_info*/); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_pk_mk_padata ( + krb5_context /*context*/, + void */*c*/, + const KDC_REQ_BODY */*req_body*/, + unsigned /*nonce*/, + METHOD_DATA */*md*/); + +krb5_error_code +_krb5_pk_octetstring2key ( + krb5_context /*context*/, + krb5_enctype /*type*/, + const void */*dhdata*/, + size_t /*dhsize*/, + const heim_octet_string */*c_n*/, + const heim_octet_string */*k_n*/, + krb5_keyblock */*key*/); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_pk_rd_pa_reply ( + krb5_context /*context*/, + const char */*realm*/, + void */*c*/, + krb5_enctype /*etype*/, + const krb5_krbhst_info */*hi*/, + unsigned /*nonce*/, + const krb5_data */*req_buffer*/, + PA_DATA */*pa*/, + krb5_keyblock **/*key*/); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_pk_verify_sign ( + krb5_context /*context*/, + const void */*data*/, + size_t /*length*/, + struct krb5_pk_identity */*id*/, + heim_oid */*contentType*/, + krb5_data */*content*/, + struct krb5_pk_cert **/*signer*/); + +krb5_error_code +_krb5_plugin_find ( + krb5_context /*context*/, + enum krb5_plugin_type /*type*/, + const char */*name*/, + struct krb5_plugin **/*list*/); + +void +_krb5_plugin_free (struct krb5_plugin */*list*/); + +struct krb5_plugin * +_krb5_plugin_get_next (struct krb5_plugin */*p*/); + +void * +_krb5_plugin_get_symbol (struct krb5_plugin */*p*/); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_principal2principalname ( + PrincipalName */*p*/, + const krb5_principal /*from*/); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_principalname2krb5_principal ( + krb5_context /*context*/, + krb5_principal */*principal*/, + const PrincipalName /*from*/, + const Realm /*realm*/); + +krb5_ssize_t KRB5_LIB_FUNCTION +_krb5_put_int ( + void */*buffer*/, + unsigned long /*value*/, + size_t /*size*/); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_rd_req_out_ctx_alloc ( + krb5_context /*context*/, + krb5_rd_req_out_ctx */*ctx*/); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_s4u2self_to_checksumdata ( + krb5_context /*context*/, + const PA_S4U2Self */*self*/, + krb5_data */*data*/); + +int +_krb5_send_and_recv_tcp ( + int /*fd*/, + time_t /*tmout*/, + const krb5_data */*req*/, + krb5_data */*rep*/); + +int +_krb5_xlock ( + krb5_context /*context*/, + int /*fd*/, + krb5_boolean /*exclusive*/, + const char */*filename*/); + +int +_krb5_xunlock ( + krb5_context /*context*/, + int /*fd*/); + +#endif /* __krb5_private_h__ */ diff --git a/lib/krb5/krb5-protos.h b/lib/krb5/krb5-protos.h new file mode 100644 index 0000000..647d888 --- /dev/null +++ b/lib/krb5/krb5-protos.h @@ -0,0 +1,4114 @@ +/* This is a generated file */ +#ifndef __krb5_protos_h__ +#define __krb5_protos_h__ + +#include <stdarg.h> + +#if !defined(__GNUC__) && !defined(__attribute__) +#define __attribute__(x) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef KRB5_LIB_FUNCTION +#if defined(_WIN32) +#define KRB5_LIB_FUNCTION _stdcall +#else +#define KRB5_LIB_FUNCTION +#endif +#endif + +krb5_error_code KRB5_LIB_FUNCTION +krb524_convert_creds_kdc ( + krb5_context /*context*/, + krb5_creds */*in_cred*/, + struct credentials */*v4creds*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb524_convert_creds_kdc_ccache ( + krb5_context /*context*/, + krb5_ccache /*ccache*/, + krb5_creds */*in_cred*/, + struct credentials */*v4creds*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_425_conv_principal ( + krb5_context /*context*/, + const char */*name*/, + const char */*instance*/, + const char */*realm*/, + krb5_principal */*princ*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_425_conv_principal_ext ( + krb5_context /*context*/, + const char */*name*/, + const char */*instance*/, + const char */*realm*/, + krb5_boolean (*/*func*/)(krb5_context, krb5_principal), + krb5_boolean /*resolve*/, + krb5_principal */*principal*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_425_conv_principal_ext2 ( + krb5_context /*context*/, + const char */*name*/, + const char */*instance*/, + const char */*realm*/, + krb5_boolean (*/*func*/)(krb5_context, void *, krb5_principal), + void */*funcctx*/, + krb5_boolean /*resolve*/, + krb5_principal */*princ*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_524_conv_principal ( + krb5_context /*context*/, + const krb5_principal /*principal*/, + char */*name*/, + char */*instance*/, + char */*realm*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_abort ( + krb5_context /*context*/, + krb5_error_code /*code*/, + const char */*fmt*/, + ...) + __attribute__ ((noreturn, format (printf, 3, 4))); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_abortx ( + krb5_context /*context*/, + const char */*fmt*/, + ...) + __attribute__ ((noreturn, format (printf, 2, 3))); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_acl_match_file ( + krb5_context /*context*/, + const char */*file*/, + const char */*format*/, + ...); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_acl_match_string ( + krb5_context /*context*/, + const char */*string*/, + const char */*format*/, + ...); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_add_et_list ( + krb5_context /*context*/, + void (*/*func*/)(struct et_list **)); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_add_extra_addresses ( + krb5_context /*context*/, + krb5_addresses */*addresses*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_add_ignore_addresses ( + krb5_context /*context*/, + krb5_addresses */*addresses*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_addlog_dest ( + krb5_context /*context*/, + krb5_log_facility */*f*/, + const char */*orig*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_addlog_func ( + krb5_context /*context*/, + krb5_log_facility */*fac*/, + int /*min*/, + int /*max*/, + krb5_log_log_func_t /*log_func*/, + krb5_log_close_func_t /*close_func*/, + void */*data*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_addr2sockaddr ( + krb5_context /*context*/, + const krb5_address */*addr*/, + struct sockaddr */*sa*/, + krb5_socklen_t */*sa_size*/, + int /*port*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_address_compare ( + krb5_context /*context*/, + const krb5_address */*addr1*/, + const krb5_address */*addr2*/); + +int KRB5_LIB_FUNCTION +krb5_address_order ( + krb5_context /*context*/, + const krb5_address */*addr1*/, + const krb5_address */*addr2*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_address_prefixlen_boundary ( + krb5_context /*context*/, + const krb5_address */*inaddr*/, + unsigned long /*prefixlen*/, + krb5_address */*low*/, + krb5_address */*high*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_address_search ( + krb5_context /*context*/, + const krb5_address */*addr*/, + const krb5_addresses */*addrlist*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_aname_to_localname ( + krb5_context /*context*/, + krb5_const_principal /*aname*/, + size_t /*lnsize*/, + char */*lname*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_anyaddr ( + krb5_context /*context*/, + int /*af*/, + struct sockaddr */*sa*/, + krb5_socklen_t */*sa_size*/, + int /*port*/); + +void KRB5_LIB_FUNCTION +krb5_appdefault_boolean ( + krb5_context /*context*/, + const char */*appname*/, + krb5_const_realm /*realm*/, + const char */*option*/, + krb5_boolean /*def_val*/, + krb5_boolean */*ret_val*/); + +void KRB5_LIB_FUNCTION +krb5_appdefault_string ( + krb5_context /*context*/, + const char */*appname*/, + krb5_const_realm /*realm*/, + const char */*option*/, + const char */*def_val*/, + char **/*ret_val*/); + +void KRB5_LIB_FUNCTION +krb5_appdefault_time ( + krb5_context /*context*/, + const char */*appname*/, + krb5_const_realm /*realm*/, + const char */*option*/, + time_t /*def_val*/, + time_t */*ret_val*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_append_addresses ( + krb5_context /*context*/, + krb5_addresses */*dest*/, + const krb5_addresses */*source*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_addflags ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + int32_t /*addflags*/, + int32_t */*flags*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_free ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_genaddrs ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + int /*fd*/, + int /*flags*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_generatelocalsubkey ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_keyblock */*key*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getaddrs ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_address **/*local_addr*/, + krb5_address **/*remote_addr*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getauthenticator ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_authenticator */*authenticator*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getcksumtype ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_cksumtype */*cksumtype*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getflags ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + int32_t */*flags*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getkey ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_keyblock **/*keyblock*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getkeytype ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_keytype */*keytype*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getlocalseqnumber ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + int32_t */*seqnumber*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getlocalsubkey ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_keyblock **/*keyblock*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getrcache ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_rcache */*rcache*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getremotesubkey ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_keyblock **/*keyblock*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_init ( + krb5_context /*context*/, + krb5_auth_context */*auth_context*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_removeflags ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + int32_t /*removeflags*/, + int32_t */*flags*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setaddrs ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_address */*local_addr*/, + krb5_address */*remote_addr*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setaddrs_from_fd ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + void */*p_fd*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setcksumtype ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_cksumtype /*cksumtype*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setflags ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + int32_t /*flags*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setkey ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_keyblock */*keyblock*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setkeytype ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_keytype /*keytype*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setlocalseqnumber ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + int32_t /*seqnumber*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setlocalsubkey ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_keyblock */*keyblock*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setrcache ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_rcache /*rcache*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setremoteseqnumber ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + int32_t /*seqnumber*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setremotesubkey ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_keyblock */*keyblock*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setuserkey ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_keyblock */*keyblock*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_getremoteseqnumber ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + int32_t */*seqnumber*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_build_ap_req ( + krb5_context /*context*/, + krb5_enctype /*enctype*/, + krb5_creds */*cred*/, + krb5_flags /*ap_options*/, + krb5_data /*authenticator*/, + krb5_data */*retdata*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_build_authenticator ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_enctype /*enctype*/, + krb5_creds */*cred*/, + Checksum */*cksum*/, + Authenticator **/*auth_result*/, + krb5_data */*result*/, + krb5_key_usage /*usage*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_build_principal ( + krb5_context /*context*/, + krb5_principal */*principal*/, + int /*rlen*/, + krb5_const_realm /*realm*/, + ...); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_build_principal_ext ( + krb5_context /*context*/, + krb5_principal */*principal*/, + int /*rlen*/, + krb5_const_realm /*realm*/, + ...); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_build_principal_va ( + krb5_context /*context*/, + krb5_principal */*principal*/, + int /*rlen*/, + krb5_const_realm /*realm*/, + va_list /*ap*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_build_principal_va_ext ( + krb5_context /*context*/, + krb5_principal */*principal*/, + int /*rlen*/, + krb5_const_realm /*realm*/, + va_list /*ap*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_block_size ( + krb5_context /*context*/, + krb5_enctype /*enctype*/, + size_t */*blocksize*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_checksum_length ( + krb5_context /*context*/, + krb5_cksumtype /*cksumtype*/, + size_t */*length*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_decrypt ( + krb5_context /*context*/, + const krb5_keyblock /*key*/, + krb5_keyusage /*usage*/, + const krb5_data */*ivec*/, + krb5_enc_data */*input*/, + krb5_data */*output*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_encrypt ( + krb5_context /*context*/, + const krb5_keyblock */*key*/, + krb5_keyusage /*usage*/, + const krb5_data */*ivec*/, + const krb5_data */*input*/, + krb5_enc_data */*output*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_encrypt_length ( + krb5_context /*context*/, + krb5_enctype /*enctype*/, + size_t /*inputlen*/, + size_t */*length*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_enctype_compare ( + krb5_context /*context*/, + krb5_enctype /*e1*/, + krb5_enctype /*e2*/, + krb5_boolean */*similar*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_get_checksum ( + krb5_context /*context*/, + const krb5_checksum */*cksum*/, + krb5_cksumtype */*type*/, + krb5_data **/*data*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_c_is_coll_proof_cksum (krb5_cksumtype /*ctype*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_c_is_keyed_cksum (krb5_cksumtype /*ctype*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_keylengths ( + krb5_context /*context*/, + krb5_enctype /*enctype*/, + size_t */*ilen*/, + size_t */*keylen*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_make_checksum ( + krb5_context /*context*/, + krb5_cksumtype /*cksumtype*/, + const krb5_keyblock */*key*/, + krb5_keyusage /*usage*/, + const krb5_data */*input*/, + krb5_checksum */*cksum*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_make_random_key ( + krb5_context /*context*/, + krb5_enctype /*enctype*/, + krb5_keyblock */*random_key*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_prf ( + krb5_context /*context*/, + const krb5_keyblock */*key*/, + const krb5_data */*input*/, + krb5_data */*output*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_prf_length ( + krb5_context /*context*/, + krb5_enctype /*type*/, + size_t */*length*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_set_checksum ( + krb5_context /*context*/, + krb5_checksum */*cksum*/, + krb5_cksumtype /*type*/, + const krb5_data */*data*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_c_valid_cksumtype (krb5_cksumtype /*ctype*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_c_valid_enctype (krb5_enctype /*etype*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_verify_checksum ( + krb5_context /*context*/, + const krb5_keyblock */*key*/, + krb5_keyusage /*usage*/, + const krb5_data */*data*/, + const krb5_checksum */*cksum*/, + krb5_boolean */*valid*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_cache_end_seq_get ( + krb5_context /*context*/, + krb5_cc_cache_cursor /*cursor*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_cache_get_first ( + krb5_context /*context*/, + const char */*type*/, + krb5_cc_cache_cursor */*cursor*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_cache_match ( + krb5_context /*context*/, + krb5_principal /*client*/, + const char */*type*/, + krb5_ccache */*id*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_cache_next ( + krb5_context /*context*/, + krb5_cc_cache_cursor /*cursor*/, + krb5_ccache */*id*/); + +void KRB5_LIB_FUNCTION +krb5_cc_clear_mcred (krb5_creds */*mcred*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_close ( + krb5_context /*context*/, + krb5_ccache /*id*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_copy_cache ( + krb5_context /*context*/, + const krb5_ccache /*from*/, + krb5_ccache /*to*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_copy_cache_match ( + krb5_context /*context*/, + const krb5_ccache /*from*/, + krb5_ccache /*to*/, + krb5_flags /*whichfields*/, + const krb5_creds * /*mcreds*/, + unsigned int */*matched*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_default ( + krb5_context /*context*/, + krb5_ccache */*id*/); + +const char* KRB5_LIB_FUNCTION +krb5_cc_default_name (krb5_context /*context*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_destroy ( + krb5_context /*context*/, + krb5_ccache /*id*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_end_seq_get ( + krb5_context /*context*/, + const krb5_ccache /*id*/, + krb5_cc_cursor */*cursor*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_gen_new ( + krb5_context /*context*/, + const krb5_cc_ops */*ops*/, + krb5_ccache */*id*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_get_full_name ( + krb5_context /*context*/, + krb5_ccache /*id*/, + char **/*str*/); + +const char* KRB5_LIB_FUNCTION +krb5_cc_get_name ( + krb5_context /*context*/, + krb5_ccache /*id*/); + +const krb5_cc_ops * +krb5_cc_get_ops ( + krb5_context /*context*/, + krb5_ccache /*id*/); + +const krb5_cc_ops * +krb5_cc_get_prefix_ops ( + krb5_context /*context*/, + const char */*prefix*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_get_principal ( + krb5_context /*context*/, + krb5_ccache /*id*/, + krb5_principal */*principal*/); + +const char* KRB5_LIB_FUNCTION +krb5_cc_get_type ( + krb5_context /*context*/, + krb5_ccache /*id*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_get_version ( + krb5_context /*context*/, + const krb5_ccache /*id*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_initialize ( + krb5_context /*context*/, + krb5_ccache /*id*/, + krb5_principal /*primary_principal*/); + +krb5_error_code +krb5_cc_move ( + krb5_context /*context*/, + krb5_ccache /*from*/, + krb5_ccache /*to*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_new_unique ( + krb5_context /*context*/, + const char */*type*/, + const char */*hint*/, + krb5_ccache */*id*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_next_cred ( + krb5_context /*context*/, + const krb5_ccache /*id*/, + krb5_cc_cursor */*cursor*/, + krb5_creds */*creds*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_next_cred_match ( + krb5_context /*context*/, + const krb5_ccache /*id*/, + krb5_cc_cursor * /*cursor*/, + krb5_creds * /*creds*/, + krb5_flags /*whichfields*/, + const krb5_creds * /*mcreds*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_register ( + krb5_context /*context*/, + const krb5_cc_ops */*ops*/, + krb5_boolean /*override*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_remove_cred ( + krb5_context /*context*/, + krb5_ccache /*id*/, + krb5_flags /*which*/, + krb5_creds */*cred*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_resolve ( + krb5_context /*context*/, + const char */*name*/, + krb5_ccache */*id*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_retrieve_cred ( + krb5_context /*context*/, + krb5_ccache /*id*/, + krb5_flags /*whichfields*/, + const krb5_creds */*mcreds*/, + krb5_creds */*creds*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_set_default_name ( + krb5_context /*context*/, + const char */*name*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_set_flags ( + krb5_context /*context*/, + krb5_ccache /*id*/, + krb5_flags /*flags*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_start_seq_get ( + krb5_context /*context*/, + const krb5_ccache /*id*/, + krb5_cc_cursor */*cursor*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_store_cred ( + krb5_context /*context*/, + krb5_ccache /*id*/, + krb5_creds */*creds*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_change_password ( + krb5_context /*context*/, + krb5_creds */*creds*/, + const char */*newpw*/, + int */*result_code*/, + krb5_data */*result_code_string*/, + krb5_data */*result_string*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_check_transited ( + krb5_context /*context*/, + krb5_const_realm /*client_realm*/, + krb5_const_realm /*server_realm*/, + krb5_realm */*realms*/, + int /*num_realms*/, + int */*bad_realm*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_check_transited_realms ( + krb5_context /*context*/, + const char *const */*realms*/, + int /*num_realms*/, + int */*bad_realm*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_checksum_disable ( + krb5_context /*context*/, + krb5_cksumtype /*type*/); + +void KRB5_LIB_FUNCTION +krb5_checksum_free ( + krb5_context /*context*/, + krb5_checksum */*cksum*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_checksum_is_collision_proof ( + krb5_context /*context*/, + krb5_cksumtype /*type*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_checksum_is_keyed ( + krb5_context /*context*/, + krb5_cksumtype /*type*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_checksumsize ( + krb5_context /*context*/, + krb5_cksumtype /*type*/, + size_t */*size*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cksumtype_valid ( + krb5_context /*context*/, + krb5_cksumtype /*ctype*/); + +void KRB5_LIB_FUNCTION +krb5_clear_error_string (krb5_context /*context*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_closelog ( + krb5_context /*context*/, + krb5_log_facility */*fac*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_compare_creds ( + krb5_context /*context*/, + krb5_flags /*whichfields*/, + const krb5_creds * /*mcreds*/, + const krb5_creds * /*creds*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_config_file_free ( + krb5_context /*context*/, + krb5_config_section */*s*/); + +void KRB5_LIB_FUNCTION +krb5_config_free_strings (char **/*strings*/); + +const void * +krb5_config_get ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + int /*type*/, + ...); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_config_get_bool ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + ...); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_config_get_bool_default ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + krb5_boolean /*def_value*/, + ...); + +int KRB5_LIB_FUNCTION +krb5_config_get_int ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + ...); + +int KRB5_LIB_FUNCTION +krb5_config_get_int_default ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + int /*def_value*/, + ...); + +const krb5_config_binding * +krb5_config_get_list ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + ...); + +const void * +krb5_config_get_next ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + const krb5_config_binding **/*pointer*/, + int /*type*/, + ...); + +const char* KRB5_LIB_FUNCTION +krb5_config_get_string ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + ...); + +const char* KRB5_LIB_FUNCTION +krb5_config_get_string_default ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + const char */*def_value*/, + ...); + +char** +krb5_config_get_strings ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + ...); + +int KRB5_LIB_FUNCTION +krb5_config_get_time ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + ...); + +int KRB5_LIB_FUNCTION +krb5_config_get_time_default ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + int /*def_value*/, + ...); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_config_parse_file ( + krb5_context /*context*/, + const char */*fname*/, + krb5_config_section **/*res*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_config_parse_file_multi ( + krb5_context /*context*/, + const char */*fname*/, + krb5_config_section **/*res*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_config_parse_string_multi ( + krb5_context /*context*/, + const char */*string*/, + krb5_config_section **/*res*/); + +const void * +krb5_config_vget ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + int /*type*/, + va_list /*args*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_config_vget_bool ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + va_list /*args*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_config_vget_bool_default ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + krb5_boolean /*def_value*/, + va_list /*args*/); + +int KRB5_LIB_FUNCTION +krb5_config_vget_int ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + va_list /*args*/); + +int KRB5_LIB_FUNCTION +krb5_config_vget_int_default ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + int /*def_value*/, + va_list /*args*/); + +const krb5_config_binding * +krb5_config_vget_list ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + va_list /*args*/); + +const void * +krb5_config_vget_next ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + const krb5_config_binding **/*pointer*/, + int /*type*/, + va_list /*args*/); + +const char* KRB5_LIB_FUNCTION +krb5_config_vget_string ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + va_list /*args*/); + +const char* KRB5_LIB_FUNCTION +krb5_config_vget_string_default ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + const char */*def_value*/, + va_list /*args*/); + +char ** KRB5_LIB_FUNCTION +krb5_config_vget_strings ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + va_list /*args*/); + +int KRB5_LIB_FUNCTION +krb5_config_vget_time ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + va_list /*args*/); + +int KRB5_LIB_FUNCTION +krb5_config_vget_time_default ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + int /*def_value*/, + va_list /*args*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_address ( + krb5_context /*context*/, + const krb5_address */*inaddr*/, + krb5_address */*outaddr*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_addresses ( + krb5_context /*context*/, + const krb5_addresses */*inaddr*/, + krb5_addresses */*outaddr*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_checksum ( + krb5_context /*context*/, + const krb5_checksum */*old*/, + krb5_checksum **/*new*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_creds ( + krb5_context /*context*/, + const krb5_creds */*incred*/, + krb5_creds **/*outcred*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_creds_contents ( + krb5_context /*context*/, + const krb5_creds */*incred*/, + krb5_creds */*c*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_data ( + krb5_context /*context*/, + const krb5_data */*indata*/, + krb5_data **/*outdata*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_host_realm ( + krb5_context /*context*/, + const krb5_realm */*from*/, + krb5_realm **/*to*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_keyblock ( + krb5_context /*context*/, + const krb5_keyblock */*inblock*/, + krb5_keyblock **/*to*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_keyblock_contents ( + krb5_context /*context*/, + const krb5_keyblock */*inblock*/, + krb5_keyblock */*to*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_principal ( + krb5_context /*context*/, + krb5_const_principal /*inprinc*/, + krb5_principal */*outprinc*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_ticket ( + krb5_context /*context*/, + const krb5_ticket */*from*/, + krb5_ticket **/*to*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_create_checksum ( + krb5_context /*context*/, + krb5_crypto /*crypto*/, + krb5_key_usage /*usage*/, + int /*type*/, + void */*data*/, + size_t /*len*/, + Checksum */*result*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_crypto_destroy ( + krb5_context /*context*/, + krb5_crypto /*crypto*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_crypto_get_checksum_type ( + krb5_context /*context*/, + krb5_crypto /*crypto*/, + krb5_cksumtype */*type*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_crypto_getblocksize ( + krb5_context /*context*/, + krb5_crypto /*crypto*/, + size_t */*blocksize*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_crypto_getconfoundersize ( + krb5_context /*context*/, + krb5_crypto /*crypto*/, + size_t */*confoundersize*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_crypto_getenctype ( + krb5_context /*context*/, + krb5_crypto /*crypto*/, + krb5_enctype */*enctype*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_crypto_getpadsize ( + krb5_context /*context*/, + krb5_crypto /*crypto*/, + size_t */*padsize*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_crypto_init ( + krb5_context /*context*/, + const krb5_keyblock */*key*/, + krb5_enctype /*etype*/, + krb5_crypto */*crypto*/); + +size_t +krb5_crypto_overhead ( + krb5_context /*context*/, + krb5_crypto /*crypto*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_crypto_prf ( + krb5_context /*context*/, + const krb5_crypto /*crypto*/, + const krb5_data */*input*/, + krb5_data */*output*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_crypto_prf_length ( + krb5_context /*context*/, + krb5_enctype /*type*/, + size_t */*length*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_data_alloc ( + krb5_data */*p*/, + int /*len*/); + +int KRB5_LIB_FUNCTION +krb5_data_cmp ( + const krb5_data */*data1*/, + const krb5_data */*data2*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_data_copy ( + krb5_data */*p*/, + const void */*data*/, + size_t /*len*/); + +void KRB5_LIB_FUNCTION +krb5_data_free (krb5_data */*p*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_data_realloc ( + krb5_data */*p*/, + int /*len*/); + +void KRB5_LIB_FUNCTION +krb5_data_zero (krb5_data */*p*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decode_Authenticator ( + krb5_context /*context*/, + const void */*data*/, + size_t /*length*/, + Authenticator */*t*/, + size_t */*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decode_ETYPE_INFO ( + krb5_context /*context*/, + const void */*data*/, + size_t /*length*/, + ETYPE_INFO */*t*/, + size_t */*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decode_ETYPE_INFO2 ( + krb5_context /*context*/, + const void */*data*/, + size_t /*length*/, + ETYPE_INFO2 */*t*/, + size_t */*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decode_EncAPRepPart ( + krb5_context /*context*/, + const void */*data*/, + size_t /*length*/, + EncAPRepPart */*t*/, + size_t */*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decode_EncASRepPart ( + krb5_context /*context*/, + const void */*data*/, + size_t /*length*/, + EncASRepPart */*t*/, + size_t */*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decode_EncKrbCredPart ( + krb5_context /*context*/, + const void */*data*/, + size_t /*length*/, + EncKrbCredPart */*t*/, + size_t */*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decode_EncTGSRepPart ( + krb5_context /*context*/, + const void */*data*/, + size_t /*length*/, + EncTGSRepPart */*t*/, + size_t */*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decode_EncTicketPart ( + krb5_context /*context*/, + const void */*data*/, + size_t /*length*/, + EncTicketPart */*t*/, + size_t */*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decode_ap_req ( + krb5_context /*context*/, + const krb5_data */*inbuf*/, + krb5_ap_req */*ap_req*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decrypt ( + krb5_context /*context*/, + krb5_crypto /*crypto*/, + unsigned /*usage*/, + void */*data*/, + size_t /*len*/, + krb5_data */*result*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decrypt_EncryptedData ( + krb5_context /*context*/, + krb5_crypto /*crypto*/, + unsigned /*usage*/, + const EncryptedData */*e*/, + krb5_data */*result*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decrypt_ivec ( + krb5_context /*context*/, + krb5_crypto /*crypto*/, + unsigned /*usage*/, + void */*data*/, + size_t /*len*/, + krb5_data */*result*/, + void */*ivec*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decrypt_ticket ( + krb5_context /*context*/, + Ticket */*ticket*/, + krb5_keyblock */*key*/, + EncTicketPart */*out*/, + krb5_flags /*flags*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_derive_key ( + krb5_context /*context*/, + const krb5_keyblock */*key*/, + krb5_enctype /*etype*/, + const void */*constant*/, + size_t /*constant_len*/, + krb5_keyblock **/*derived_key*/); + +krb5_error_code +krb5_digest_alloc ( + krb5_context /*context*/, + krb5_digest */*digest*/); + +void +krb5_digest_free (krb5_digest /*digest*/); + +krb5_error_code +krb5_digest_get_client_binding ( + krb5_context /*context*/, + krb5_digest /*digest*/, + char **/*type*/, + char **/*binding*/); + +const char * +krb5_digest_get_identifier ( + krb5_context /*context*/, + krb5_digest /*digest*/); + +const char * +krb5_digest_get_opaque ( + krb5_context /*context*/, + krb5_digest /*digest*/); + +const char * +krb5_digest_get_rsp ( + krb5_context /*context*/, + krb5_digest /*digest*/); + +const char * +krb5_digest_get_server_nonce ( + krb5_context /*context*/, + krb5_digest /*digest*/); + +krb5_error_code +krb5_digest_get_session_key ( + krb5_context /*context*/, + krb5_digest /*digest*/, + krb5_data */*data*/); + +krb5_error_code +krb5_digest_get_tickets ( + krb5_context /*context*/, + krb5_digest /*digest*/, + Ticket **/*tickets*/); + +krb5_error_code +krb5_digest_init_request ( + krb5_context /*context*/, + krb5_digest /*digest*/, + krb5_realm /*realm*/, + krb5_ccache /*ccache*/); + +krb5_error_code +krb5_digest_probe ( + krb5_context /*context*/, + krb5_realm /*realm*/, + krb5_ccache /*ccache*/, + unsigned */*flags*/); + +krb5_boolean +krb5_digest_rep_get_status ( + krb5_context /*context*/, + krb5_digest /*digest*/); + +krb5_error_code +krb5_digest_request ( + krb5_context /*context*/, + krb5_digest /*digest*/, + krb5_realm /*realm*/, + krb5_ccache /*ccache*/); + +krb5_error_code +krb5_digest_set_authentication_user ( + krb5_context /*context*/, + krb5_digest /*digest*/, + krb5_principal /*authentication_user*/); + +krb5_error_code +krb5_digest_set_authid ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*authid*/); + +krb5_error_code +krb5_digest_set_client_nonce ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*nonce*/); + +krb5_error_code +krb5_digest_set_digest ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*dgst*/); + +krb5_error_code +krb5_digest_set_hostname ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*hostname*/); + +krb5_error_code +krb5_digest_set_identifier ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*id*/); + +krb5_error_code +krb5_digest_set_method ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*method*/); + +krb5_error_code +krb5_digest_set_nonceCount ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*nonce_count*/); + +krb5_error_code +krb5_digest_set_opaque ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*opaque*/); + +krb5_error_code +krb5_digest_set_qop ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*qop*/); + +krb5_error_code +krb5_digest_set_realm ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*realm*/); + +int +krb5_digest_set_responseData ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*response*/); + +krb5_error_code +krb5_digest_set_server_cb ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*type*/, + const char */*binding*/); + +krb5_error_code +krb5_digest_set_server_nonce ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*nonce*/); + +krb5_error_code +krb5_digest_set_type ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*type*/); + +krb5_error_code +krb5_digest_set_uri ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*uri*/); + +krb5_error_code +krb5_digest_set_username ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*username*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_domain_x500_decode ( + krb5_context /*context*/, + krb5_data /*tr*/, + char ***/*realms*/, + int */*num_realms*/, + const char */*client_realm*/, + const char */*server_realm*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_domain_x500_encode ( + char **/*realms*/, + int /*num_realms*/, + krb5_data */*encoding*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_eai_to_heim_errno ( + int /*eai_errno*/, + int /*system_error*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encode_Authenticator ( + krb5_context /*context*/, + void */*data*/, + size_t /*length*/, + Authenticator */*t*/, + size_t */*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encode_ETYPE_INFO ( + krb5_context /*context*/, + void */*data*/, + size_t /*length*/, + ETYPE_INFO */*t*/, + size_t */*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encode_ETYPE_INFO2 ( + krb5_context /*context*/, + void */*data*/, + size_t /*length*/, + ETYPE_INFO2 */*t*/, + size_t */*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encode_EncAPRepPart ( + krb5_context /*context*/, + void */*data*/, + size_t /*length*/, + EncAPRepPart */*t*/, + size_t */*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encode_EncASRepPart ( + krb5_context /*context*/, + void */*data*/, + size_t /*length*/, + EncASRepPart */*t*/, + size_t */*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encode_EncKrbCredPart ( + krb5_context /*context*/, + void */*data*/, + size_t /*length*/, + EncKrbCredPart */*t*/, + size_t */*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encode_EncTGSRepPart ( + krb5_context /*context*/, + void */*data*/, + size_t /*length*/, + EncTGSRepPart */*t*/, + size_t */*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encode_EncTicketPart ( + krb5_context /*context*/, + void */*data*/, + size_t /*length*/, + EncTicketPart */*t*/, + size_t */*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encrypt ( + krb5_context /*context*/, + krb5_crypto /*crypto*/, + unsigned /*usage*/, + const void */*data*/, + size_t /*len*/, + krb5_data */*result*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encrypt_EncryptedData ( + krb5_context /*context*/, + krb5_crypto /*crypto*/, + unsigned /*usage*/, + void */*data*/, + size_t /*len*/, + int /*kvno*/, + EncryptedData */*result*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encrypt_ivec ( + krb5_context /*context*/, + krb5_crypto /*crypto*/, + unsigned /*usage*/, + const void */*data*/, + size_t /*len*/, + krb5_data */*result*/, + void */*ivec*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_enctype_disable ( + krb5_context /*context*/, + krb5_enctype /*enctype*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_enctype_keybits ( + krb5_context /*context*/, + krb5_enctype /*type*/, + size_t */*keybits*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_enctype_keysize ( + krb5_context /*context*/, + krb5_enctype /*type*/, + size_t */*keysize*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_enctype_to_keytype ( + krb5_context /*context*/, + krb5_enctype /*etype*/, + krb5_keytype */*keytype*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_enctype_to_string ( + krb5_context /*context*/, + krb5_enctype /*etype*/, + char **/*string*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_enctype_valid ( + krb5_context /*context*/, + krb5_enctype /*etype*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_enctypes_compatible_keys ( + krb5_context /*context*/, + krb5_enctype /*etype1*/, + krb5_enctype /*etype2*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_err ( + krb5_context /*context*/, + int /*eval*/, + krb5_error_code /*code*/, + const char */*fmt*/, + ...) + __attribute__ ((noreturn, format (printf, 4, 5))); + +krb5_error_code KRB5_LIB_FUNCTION + __attribute__((deprecated)) krb5_free_creds_contents (krb5_context context, krb5_creds *c); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_error_from_rd_error ( + krb5_context /*context*/, + const krb5_error */*error*/, + const krb5_creds */*creds*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_errx ( + krb5_context /*context*/, + int /*eval*/, + const char */*fmt*/, + ...) + __attribute__ ((noreturn, format (printf, 3, 4))); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_expand_hostname ( + krb5_context /*context*/, + const char */*orig_hostname*/, + char **/*new_hostname*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_expand_hostname_realms ( + krb5_context /*context*/, + const char */*orig_hostname*/, + char **/*new_hostname*/, + char ***/*realms*/); + +PA_DATA * +krb5_find_padata ( + PA_DATA */*val*/, + unsigned /*len*/, + int /*type*/, + int */*idx*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_format_time ( + krb5_context /*context*/, + time_t /*t*/, + char */*s*/, + size_t /*len*/, + krb5_boolean /*include_time*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_free_address ( + krb5_context /*context*/, + krb5_address */*address*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_free_addresses ( + krb5_context /*context*/, + krb5_addresses */*addresses*/); + +void KRB5_LIB_FUNCTION +krb5_free_ap_rep_enc_part ( + krb5_context /*context*/, + krb5_ap_rep_enc_part */*val*/); + +void KRB5_LIB_FUNCTION +krb5_free_authenticator ( + krb5_context /*context*/, + krb5_authenticator */*authenticator*/); + +void KRB5_LIB_FUNCTION +krb5_free_checksum ( + krb5_context /*context*/, + krb5_checksum */*cksum*/); + +void KRB5_LIB_FUNCTION +krb5_free_checksum_contents ( + krb5_context /*context*/, + krb5_checksum */*cksum*/); + +void KRB5_LIB_FUNCTION +krb5_free_config_files (char **/*filenames*/); + +void KRB5_LIB_FUNCTION +krb5_free_context (krb5_context /*context*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_free_cred_contents ( + krb5_context /*context*/, + krb5_creds */*c*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_free_creds ( + krb5_context /*context*/, + krb5_creds */*c*/); + +void KRB5_LIB_FUNCTION +krb5_free_data ( + krb5_context /*context*/, + krb5_data */*p*/); + +void KRB5_LIB_FUNCTION +krb5_free_data_contents ( + krb5_context /*context*/, + krb5_data */*data*/); + +void KRB5_LIB_FUNCTION +krb5_free_error ( + krb5_context /*context*/, + krb5_error */*error*/); + +void KRB5_LIB_FUNCTION +krb5_free_error_contents ( + krb5_context /*context*/, + krb5_error */*error*/); + +void KRB5_LIB_FUNCTION +krb5_free_error_string ( + krb5_context /*context*/, + char */*str*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_free_host_realm ( + krb5_context /*context*/, + krb5_realm */*realmlist*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_free_kdc_rep ( + krb5_context /*context*/, + krb5_kdc_rep */*rep*/); + +void KRB5_LIB_FUNCTION +krb5_free_keyblock ( + krb5_context /*context*/, + krb5_keyblock */*keyblock*/); + +void KRB5_LIB_FUNCTION +krb5_free_keyblock_contents ( + krb5_context /*context*/, + krb5_keyblock */*keyblock*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_free_krbhst ( + krb5_context /*context*/, + char **/*hostlist*/); + +void KRB5_LIB_FUNCTION +krb5_free_principal ( + krb5_context /*context*/, + krb5_principal /*p*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_free_salt ( + krb5_context /*context*/, + krb5_salt /*salt*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_free_ticket ( + krb5_context /*context*/, + krb5_ticket */*ticket*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_fwd_tgt_creds ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + const char */*hostname*/, + krb5_principal /*client*/, + krb5_principal /*server*/, + krb5_ccache /*ccache*/, + int /*forwardable*/, + krb5_data */*out_data*/); + +void KRB5_LIB_FUNCTION +krb5_generate_random_block ( + void */*buf*/, + size_t /*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_generate_random_keyblock ( + krb5_context /*context*/, + krb5_enctype /*type*/, + krb5_keyblock */*key*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_generate_seq_number ( + krb5_context /*context*/, + const krb5_keyblock */*key*/, + uint32_t */*seqno*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_generate_subkey ( + krb5_context /*context*/, + const krb5_keyblock */*key*/, + krb5_keyblock **/*subkey*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_generate_subkey_extended ( + krb5_context /*context*/, + const krb5_keyblock */*key*/, + krb5_enctype /*etype*/, + krb5_keyblock **/*subkey*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_all_client_addrs ( + krb5_context /*context*/, + krb5_addresses */*res*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_all_server_addrs ( + krb5_context /*context*/, + krb5_addresses */*res*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_cred_from_kdc ( + krb5_context /*context*/, + krb5_ccache /*ccache*/, + krb5_creds */*in_creds*/, + krb5_creds **/*out_creds*/, + krb5_creds ***/*ret_tgts*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_cred_from_kdc_opt ( + krb5_context /*context*/, + krb5_ccache /*ccache*/, + krb5_creds */*in_creds*/, + krb5_creds **/*out_creds*/, + krb5_creds ***/*ret_tgts*/, + krb5_flags /*flags*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_credentials ( + krb5_context /*context*/, + krb5_flags /*options*/, + krb5_ccache /*ccache*/, + krb5_creds */*in_creds*/, + krb5_creds **/*out_creds*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_credentials_with_flags ( + krb5_context /*context*/, + krb5_flags /*options*/, + krb5_kdc_flags /*flags*/, + krb5_ccache /*ccache*/, + krb5_creds */*in_creds*/, + krb5_creds **/*out_creds*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_creds ( + krb5_context /*context*/, + krb5_get_creds_opt /*opt*/, + krb5_ccache /*ccache*/, + krb5_const_principal /*inprinc*/, + krb5_creds **/*out_creds*/); + +void KRB5_LIB_FUNCTION +krb5_get_creds_opt_add_options ( + krb5_context /*context*/, + krb5_get_creds_opt /*opt*/, + krb5_flags /*options*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_creds_opt_alloc ( + krb5_context /*context*/, + krb5_get_creds_opt */*opt*/); + +void KRB5_LIB_FUNCTION +krb5_get_creds_opt_free ( + krb5_context /*context*/, + krb5_get_creds_opt /*opt*/); + +void KRB5_LIB_FUNCTION +krb5_get_creds_opt_set_enctype ( + krb5_context /*context*/, + krb5_get_creds_opt /*opt*/, + krb5_enctype /*enctype*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_creds_opt_set_impersonate ( + krb5_context /*context*/, + krb5_get_creds_opt /*opt*/, + krb5_const_principal /*self*/); + +void KRB5_LIB_FUNCTION +krb5_get_creds_opt_set_options ( + krb5_context /*context*/, + krb5_get_creds_opt /*opt*/, + krb5_flags /*options*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_creds_opt_set_ticket ( + krb5_context /*context*/, + krb5_get_creds_opt /*opt*/, + const Ticket */*ticket*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_default_config_files (char ***/*pfilenames*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_default_in_tkt_etypes ( + krb5_context /*context*/, + krb5_enctype **/*etypes*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_default_principal ( + krb5_context /*context*/, + krb5_principal */*princ*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_default_realm ( + krb5_context /*context*/, + krb5_realm */*realm*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_default_realms ( + krb5_context /*context*/, + krb5_realm **/*realms*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_get_dns_canonicalize_hostname (krb5_context /*context*/); + +const char* KRB5_LIB_FUNCTION +krb5_get_err_text ( + krb5_context /*context*/, + krb5_error_code /*code*/); + +char * KRB5_LIB_FUNCTION +krb5_get_error_message ( + krb5_context /*context*/, + krb5_error_code /*code*/); + +char * KRB5_LIB_FUNCTION +krb5_get_error_string (krb5_context /*context*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_extra_addresses ( + krb5_context /*context*/, + krb5_addresses */*addresses*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_fcache_version ( + krb5_context /*context*/, + int */*version*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_forwarded_creds ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_ccache /*ccache*/, + krb5_flags /*flags*/, + const char */*hostname*/, + krb5_creds */*in_creds*/, + krb5_data */*out_data*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_host_realm ( + krb5_context /*context*/, + const char */*targethost*/, + krb5_realm **/*realms*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_ignore_addresses ( + krb5_context /*context*/, + krb5_addresses */*addresses*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_in_cred ( + krb5_context /*context*/, + krb5_flags /*options*/, + const krb5_addresses */*addrs*/, + const krb5_enctype */*etypes*/, + const krb5_preauthtype */*ptypes*/, + const krb5_preauthdata */*preauth*/, + krb5_key_proc /*key_proc*/, + krb5_const_pointer /*keyseed*/, + krb5_decrypt_proc /*decrypt_proc*/, + krb5_const_pointer /*decryptarg*/, + krb5_creds */*creds*/, + krb5_kdc_rep */*ret_as_reply*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_in_tkt ( + krb5_context /*context*/, + krb5_flags /*options*/, + const krb5_addresses */*addrs*/, + const krb5_enctype */*etypes*/, + const krb5_preauthtype */*ptypes*/, + krb5_key_proc /*key_proc*/, + krb5_const_pointer /*keyseed*/, + krb5_decrypt_proc /*decrypt_proc*/, + krb5_const_pointer /*decryptarg*/, + krb5_creds */*creds*/, + krb5_ccache /*ccache*/, + krb5_kdc_rep */*ret_as_reply*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_in_tkt_with_keytab ( + krb5_context /*context*/, + krb5_flags /*options*/, + krb5_addresses */*addrs*/, + const krb5_enctype */*etypes*/, + const krb5_preauthtype */*pre_auth_types*/, + krb5_keytab /*keytab*/, + krb5_ccache /*ccache*/, + krb5_creds */*creds*/, + krb5_kdc_rep */*ret_as_reply*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_in_tkt_with_password ( + krb5_context /*context*/, + krb5_flags /*options*/, + krb5_addresses */*addrs*/, + const krb5_enctype */*etypes*/, + const krb5_preauthtype */*pre_auth_types*/, + const char */*password*/, + krb5_ccache /*ccache*/, + krb5_creds */*creds*/, + krb5_kdc_rep */*ret_as_reply*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_in_tkt_with_skey ( + krb5_context /*context*/, + krb5_flags /*options*/, + krb5_addresses */*addrs*/, + const krb5_enctype */*etypes*/, + const krb5_preauthtype */*pre_auth_types*/, + const krb5_keyblock */*key*/, + krb5_ccache /*ccache*/, + krb5_creds */*creds*/, + krb5_kdc_rep */*ret_as_reply*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds ( + krb5_context /*context*/, + krb5_creds */*creds*/, + krb5_principal /*client*/, + krb5_prompter_fct /*prompter*/, + void */*data*/, + krb5_deltat /*start_time*/, + const char */*in_tkt_service*/, + krb5_get_init_creds_opt */*options*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_keyblock ( + krb5_context /*context*/, + krb5_creds */*creds*/, + krb5_principal /*client*/, + krb5_keyblock */*keyblock*/, + krb5_deltat /*start_time*/, + const char */*in_tkt_service*/, + krb5_get_init_creds_opt */*options*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_keytab ( + krb5_context /*context*/, + krb5_creds */*creds*/, + krb5_principal /*client*/, + krb5_keytab /*keytab*/, + krb5_deltat /*start_time*/, + const char */*in_tkt_service*/, + krb5_get_init_creds_opt */*options*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_alloc ( + krb5_context /*context*/, + krb5_get_init_creds_opt **/*opt*/); + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_free ( + krb5_context /*context*/, + krb5_get_init_creds_opt */*opt*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_get_error ( + krb5_context /*context*/, + krb5_get_init_creds_opt */*opt*/, + KRB_ERROR **/*error*/); + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_init (krb5_get_init_creds_opt */*opt*/); + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_address_list ( + krb5_get_init_creds_opt */*opt*/, + krb5_addresses */*addresses*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_addressless ( + krb5_context /*context*/, + krb5_get_init_creds_opt */*opt*/, + krb5_boolean /*addressless*/); + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_anonymous ( + krb5_get_init_creds_opt */*opt*/, + int /*anonymous*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_canonicalize ( + krb5_context /*context*/, + krb5_get_init_creds_opt */*opt*/, + krb5_boolean /*req*/); + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_default_flags ( + krb5_context /*context*/, + const char */*appname*/, + krb5_const_realm /*realm*/, + krb5_get_init_creds_opt */*opt*/); + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_etype_list ( + krb5_get_init_creds_opt */*opt*/, + krb5_enctype */*etype_list*/, + int /*etype_list_length*/); + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_forwardable ( + krb5_get_init_creds_opt */*opt*/, + int /*forwardable*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_pa_password ( + krb5_context /*context*/, + krb5_get_init_creds_opt */*opt*/, + const char */*password*/, + krb5_s2k_proc /*key_proc*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_pac_request ( + krb5_context /*context*/, + krb5_get_init_creds_opt */*opt*/, + krb5_boolean /*req_pac*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_pkinit ( + krb5_context /*context*/, + krb5_get_init_creds_opt */*opt*/, + krb5_principal /*principal*/, + const char */*user_id*/, + const char */*x509_anchors*/, + char * const * /*pool*/, + char * const * /*pki_revoke*/, + int /*flags*/, + krb5_prompter_fct /*prompter*/, + void */*prompter_data*/, + char */*password*/); + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_preauth_list ( + krb5_get_init_creds_opt */*opt*/, + krb5_preauthtype */*preauth_list*/, + int /*preauth_list_length*/); + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_proxiable ( + krb5_get_init_creds_opt */*opt*/, + int /*proxiable*/); + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_renew_life ( + krb5_get_init_creds_opt */*opt*/, + krb5_deltat /*renew_life*/); + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_salt ( + krb5_get_init_creds_opt */*opt*/, + krb5_data */*salt*/); + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_tkt_life ( + krb5_get_init_creds_opt */*opt*/, + krb5_deltat /*tkt_life*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_win2k ( + krb5_context /*context*/, + krb5_get_init_creds_opt */*opt*/, + krb5_boolean /*req*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_password ( + krb5_context /*context*/, + krb5_creds */*creds*/, + krb5_principal /*client*/, + const char */*password*/, + krb5_prompter_fct /*prompter*/, + void */*data*/, + krb5_deltat /*start_time*/, + const char */*in_tkt_service*/, + krb5_get_init_creds_opt */*in_options*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_kdc_cred ( + krb5_context /*context*/, + krb5_ccache /*id*/, + krb5_kdc_flags /*flags*/, + krb5_addresses */*addresses*/, + Ticket */*second_ticket*/, + krb5_creds */*in_creds*/, + krb5_creds **out_creds ); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_kdc_sec_offset ( + krb5_context /*context*/, + int32_t */*sec*/, + int32_t */*usec*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_krb524hst ( + krb5_context /*context*/, + const krb5_realm */*realm*/, + char ***/*hostlist*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_krb_admin_hst ( + krb5_context /*context*/, + const krb5_realm */*realm*/, + char ***/*hostlist*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_krb_changepw_hst ( + krb5_context /*context*/, + const krb5_realm */*realm*/, + char ***/*hostlist*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_krbhst ( + krb5_context /*context*/, + const krb5_realm */*realm*/, + char ***/*hostlist*/); + +time_t KRB5_LIB_FUNCTION +krb5_get_max_time_skew (krb5_context /*context*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_pw_salt ( + krb5_context /*context*/, + krb5_const_principal /*principal*/, + krb5_salt */*salt*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_renewed_creds ( + krb5_context /*context*/, + krb5_creds */*creds*/, + krb5_const_principal /*client*/, + krb5_ccache /*ccache*/, + const char */*in_tkt_service*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_server_rcache ( + krb5_context /*context*/, + const krb5_data */*piece*/, + krb5_rcache */*id*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_get_use_admin_kdc (krb5_context /*context*/); + +krb5_log_facility * KRB5_LIB_FUNCTION +krb5_get_warn_dest (krb5_context /*context*/); + +size_t +krb5_get_wrapped_length ( + krb5_context /*context*/, + krb5_crypto /*crypto*/, + size_t /*data_len*/); + +int KRB5_LIB_FUNCTION +krb5_getportbyname ( + krb5_context /*context*/, + const char */*service*/, + const char */*proto*/, + int /*default_port*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_h_addr2addr ( + krb5_context /*context*/, + int /*af*/, + const char */*haddr*/, + krb5_address */*addr*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_h_addr2sockaddr ( + krb5_context /*context*/, + int /*af*/, + const char */*addr*/, + struct sockaddr */*sa*/, + krb5_socklen_t */*sa_size*/, + int /*port*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_h_errno_to_heim_errno (int /*eai_errno*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_have_error_string (krb5_context /*context*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_hmac ( + krb5_context /*context*/, + krb5_cksumtype /*cktype*/, + const void */*data*/, + size_t /*len*/, + unsigned /*usage*/, + krb5_keyblock */*key*/, + Checksum */*result*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_init_context (krb5_context */*context*/); + +void KRB5_LIB_FUNCTION +krb5_init_ets (krb5_context /*context*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_init_etype ( + krb5_context /*context*/, + unsigned */*len*/, + krb5_enctype **/*val*/, + const krb5_enctype */*etypes*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_initlog ( + krb5_context /*context*/, + const char */*program*/, + krb5_log_facility **/*fac*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_is_thread_safe (void); + +const krb5_enctype * KRB5_LIB_FUNCTION +krb5_kerberos_enctypes (krb5_context /*context*/); + +krb5_enctype +krb5_keyblock_get_enctype (const krb5_keyblock */*block*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_keyblock_init ( + krb5_context /*context*/, + krb5_enctype /*type*/, + const void */*data*/, + size_t /*size*/, + krb5_keyblock */*key*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_keyblock_key_proc ( + krb5_context /*context*/, + krb5_keytype /*type*/, + krb5_data */*salt*/, + krb5_const_pointer /*keyseed*/, + krb5_keyblock **/*key*/); + +void KRB5_LIB_FUNCTION +krb5_keyblock_zero (krb5_keyblock */*keyblock*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_keytab_key_proc ( + krb5_context /*context*/, + krb5_enctype /*enctype*/, + krb5_salt /*salt*/, + krb5_const_pointer /*keyseed*/, + krb5_keyblock **/*key*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_keytype_to_enctypes ( + krb5_context /*context*/, + krb5_keytype /*keytype*/, + unsigned */*len*/, + krb5_enctype **/*val*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_keytype_to_enctypes_default ( + krb5_context /*context*/, + krb5_keytype /*keytype*/, + unsigned */*len*/, + krb5_enctype **/*val*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_keytype_to_string ( + krb5_context /*context*/, + krb5_keytype /*keytype*/, + char **/*string*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_krbhst_format_string ( + krb5_context /*context*/, + const krb5_krbhst_info */*host*/, + char */*hostname*/, + size_t /*hostlen*/); + +void KRB5_LIB_FUNCTION +krb5_krbhst_free ( + krb5_context /*context*/, + krb5_krbhst_handle /*handle*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_krbhst_get_addrinfo ( + krb5_context /*context*/, + krb5_krbhst_info */*host*/, + struct addrinfo **/*ai*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_krbhst_init ( + krb5_context /*context*/, + const char */*realm*/, + unsigned int /*type*/, + krb5_krbhst_handle */*handle*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_krbhst_init_flags ( + krb5_context /*context*/, + const char */*realm*/, + unsigned int /*type*/, + int /*flags*/, + krb5_krbhst_handle */*handle*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_krbhst_next ( + krb5_context /*context*/, + krb5_krbhst_handle /*handle*/, + krb5_krbhst_info **/*host*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_krbhst_next_as_string ( + krb5_context /*context*/, + krb5_krbhst_handle /*handle*/, + char */*hostname*/, + size_t /*hostlen*/); + +void KRB5_LIB_FUNCTION +krb5_krbhst_reset ( + krb5_context /*context*/, + krb5_krbhst_handle /*handle*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_add_entry ( + krb5_context /*context*/, + krb5_keytab /*id*/, + krb5_keytab_entry */*entry*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_close ( + krb5_context /*context*/, + krb5_keytab /*id*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_kt_compare ( + krb5_context /*context*/, + krb5_keytab_entry */*entry*/, + krb5_const_principal /*principal*/, + krb5_kvno /*vno*/, + krb5_enctype /*enctype*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_copy_entry_contents ( + krb5_context /*context*/, + const krb5_keytab_entry */*in*/, + krb5_keytab_entry */*out*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_default ( + krb5_context /*context*/, + krb5_keytab */*id*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_default_modify_name ( + krb5_context /*context*/, + char */*name*/, + size_t /*namesize*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_default_name ( + krb5_context /*context*/, + char */*name*/, + size_t /*namesize*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_end_seq_get ( + krb5_context /*context*/, + krb5_keytab /*id*/, + krb5_kt_cursor */*cursor*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_free_entry ( + krb5_context /*context*/, + krb5_keytab_entry */*entry*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_get_entry ( + krb5_context /*context*/, + krb5_keytab /*id*/, + krb5_const_principal /*principal*/, + krb5_kvno /*kvno*/, + krb5_enctype /*enctype*/, + krb5_keytab_entry */*entry*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_get_full_name ( + krb5_context /*context*/, + krb5_keytab /*keytab*/, + char **/*str*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_get_name ( + krb5_context /*context*/, + krb5_keytab /*keytab*/, + char */*name*/, + size_t /*namesize*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_get_type ( + krb5_context /*context*/, + krb5_keytab /*keytab*/, + char */*prefix*/, + size_t /*prefixsize*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_next_entry ( + krb5_context /*context*/, + krb5_keytab /*id*/, + krb5_keytab_entry */*entry*/, + krb5_kt_cursor */*cursor*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_read_service_key ( + krb5_context /*context*/, + krb5_pointer /*keyprocarg*/, + krb5_principal /*principal*/, + krb5_kvno /*vno*/, + krb5_enctype /*enctype*/, + krb5_keyblock **/*key*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_register ( + krb5_context /*context*/, + const krb5_kt_ops */*ops*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_remove_entry ( + krb5_context /*context*/, + krb5_keytab /*id*/, + krb5_keytab_entry */*entry*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_resolve ( + krb5_context /*context*/, + const char */*name*/, + krb5_keytab */*id*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_start_seq_get ( + krb5_context /*context*/, + krb5_keytab /*id*/, + krb5_kt_cursor */*cursor*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_kuserok ( + krb5_context /*context*/, + krb5_principal /*principal*/, + const char */*luser*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_log ( + krb5_context /*context*/, + krb5_log_facility */*fac*/, + int /*level*/, + const char */*fmt*/, + ...) + __attribute__((format (printf, 4, 5))); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_log_msg ( + krb5_context /*context*/, + krb5_log_facility */*fac*/, + int /*level*/, + char **/*reply*/, + const char */*fmt*/, + ...) + __attribute__((format (printf, 5, 6))); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_make_addrport ( + krb5_context /*context*/, + krb5_address **/*res*/, + const krb5_address */*addr*/, + int16_t /*port*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_make_principal ( + krb5_context /*context*/, + krb5_principal */*principal*/, + krb5_const_realm /*realm*/, + ...); + +size_t KRB5_LIB_FUNCTION +krb5_max_sockaddr_size (void); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_mk_error ( + krb5_context /*context*/, + krb5_error_code /*error_code*/, + const char */*e_text*/, + const krb5_data */*e_data*/, + const krb5_principal /*client*/, + const krb5_principal /*server*/, + time_t */*client_time*/, + int */*client_usec*/, + krb5_data */*reply*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_mk_priv ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + const krb5_data */*userdata*/, + krb5_data */*outbuf*/, + krb5_replay_data */*outdata*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_mk_rep ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_data */*outbuf*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_mk_req ( + krb5_context /*context*/, + krb5_auth_context */*auth_context*/, + const krb5_flags /*ap_req_options*/, + const char */*service*/, + const char */*hostname*/, + krb5_data */*in_data*/, + krb5_ccache /*ccache*/, + krb5_data */*outbuf*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_mk_req_exact ( + krb5_context /*context*/, + krb5_auth_context */*auth_context*/, + const krb5_flags /*ap_req_options*/, + const krb5_principal /*server*/, + krb5_data */*in_data*/, + krb5_ccache /*ccache*/, + krb5_data */*outbuf*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_mk_req_extended ( + krb5_context /*context*/, + krb5_auth_context */*auth_context*/, + const krb5_flags /*ap_req_options*/, + krb5_data */*in_data*/, + krb5_creds */*in_creds*/, + krb5_data */*outbuf*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_mk_safe ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + const krb5_data */*userdata*/, + krb5_data */*outbuf*/, + krb5_replay_data */*outdata*/); + +krb5_ssize_t KRB5_LIB_FUNCTION +krb5_net_read ( + krb5_context /*context*/, + void */*p_fd*/, + void */*buf*/, + size_t /*len*/); + +krb5_ssize_t KRB5_LIB_FUNCTION +krb5_net_write ( + krb5_context /*context*/, + void */*p_fd*/, + const void */*buf*/, + size_t /*len*/); + +krb5_ssize_t KRB5_LIB_FUNCTION +krb5_net_write_block ( + krb5_context /*context*/, + void */*p_fd*/, + const void */*buf*/, + size_t /*len*/, + time_t /*timeout*/); + +krb5_error_code +krb5_ntlm_alloc ( + krb5_context /*context*/, + krb5_ntlm */*ntlm*/); + +krb5_error_code +krb5_ntlm_free ( + krb5_context /*context*/, + krb5_ntlm /*ntlm*/); + +krb5_error_code +krb5_ntlm_init_get_challange ( + krb5_context /*context*/, + krb5_ntlm /*ntlm*/, + krb5_data */*challange*/); + +krb5_error_code +krb5_ntlm_init_get_flags ( + krb5_context /*context*/, + krb5_ntlm /*ntlm*/, + uint32_t */*flags*/); + +krb5_error_code +krb5_ntlm_init_get_opaque ( + krb5_context /*context*/, + krb5_ntlm /*ntlm*/, + krb5_data */*opaque*/); + +krb5_error_code +krb5_ntlm_init_get_targetinfo ( + krb5_context /*context*/, + krb5_ntlm /*ntlm*/, + krb5_data */*data*/); + +krb5_error_code +krb5_ntlm_init_get_targetname ( + krb5_context /*context*/, + krb5_ntlm /*ntlm*/, + char **/*name*/); + +krb5_error_code +krb5_ntlm_init_request ( + krb5_context /*context*/, + krb5_ntlm /*ntlm*/, + krb5_realm /*realm*/, + krb5_ccache /*ccache*/, + uint32_t /*flags*/, + const char */*hostname*/, + const char */*domainname*/); + +krb5_error_code +krb5_ntlm_rep_get_sessionkey ( + krb5_context /*context*/, + krb5_ntlm /*ntlm*/, + krb5_data */*data*/); + +krb5_boolean +krb5_ntlm_rep_get_status ( + krb5_context /*context*/, + krb5_ntlm /*ntlm*/); + +krb5_error_code +krb5_ntlm_req_set_flags ( + krb5_context /*context*/, + krb5_ntlm /*ntlm*/, + uint32_t /*flags*/); + +krb5_error_code +krb5_ntlm_req_set_lm ( + krb5_context /*context*/, + krb5_ntlm /*ntlm*/, + void */*hash*/, + size_t /*len*/); + +krb5_error_code +krb5_ntlm_req_set_ntlm ( + krb5_context /*context*/, + krb5_ntlm /*ntlm*/, + void */*hash*/, + size_t /*len*/); + +krb5_error_code +krb5_ntlm_req_set_opaque ( + krb5_context /*context*/, + krb5_ntlm /*ntlm*/, + krb5_data */*opaque*/); + +krb5_error_code +krb5_ntlm_req_set_session ( + krb5_context /*context*/, + krb5_ntlm /*ntlm*/, + void */*sessionkey*/, + size_t /*length*/); + +krb5_error_code +krb5_ntlm_req_set_targetname ( + krb5_context /*context*/, + krb5_ntlm /*ntlm*/, + const char */*targetname*/); + +krb5_error_code +krb5_ntlm_req_set_username ( + krb5_context /*context*/, + krb5_ntlm /*ntlm*/, + const char */*username*/); + +krb5_error_code +krb5_ntlm_request ( + krb5_context /*context*/, + krb5_ntlm /*ntlm*/, + krb5_realm /*realm*/, + krb5_ccache /*ccache*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_openlog ( + krb5_context /*context*/, + const char */*program*/, + krb5_log_facility **/*fac*/); + +krb5_error_code +krb5_pac_add_buffer ( + krb5_context /*context*/, + krb5_pac /*p*/, + uint32_t /*type*/, + const krb5_data */*data*/); + +void +krb5_pac_free ( + krb5_context /*context*/, + krb5_pac /*pac*/); + +krb5_error_code +krb5_pac_get_buffer ( + krb5_context /*context*/, + krb5_pac /*p*/, + uint32_t /*type*/, + krb5_data */*data*/); + +krb5_error_code +krb5_pac_get_types ( + krb5_context /*context*/, + krb5_pac /*p*/, + size_t */*len*/, + uint32_t **/*types*/); + +krb5_error_code +krb5_pac_init ( + krb5_context /*context*/, + krb5_pac */*pac*/); + +krb5_error_code +krb5_pac_parse ( + krb5_context /*context*/, + const void */*ptr*/, + size_t /*len*/, + krb5_pac */*pac*/); + +krb5_error_code +krb5_pac_verify ( + krb5_context /*context*/, + const krb5_pac /*pac*/, + time_t /*authtime*/, + krb5_const_principal /*principal*/, + const krb5_keyblock */*server*/, + const krb5_keyblock */*privsvr*/); + +int KRB5_LIB_FUNCTION +krb5_padata_add ( + krb5_context /*context*/, + METHOD_DATA */*md*/, + int /*type*/, + void */*buf*/, + size_t /*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_parse_address ( + krb5_context /*context*/, + const char */*string*/, + krb5_addresses */*addresses*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_parse_name ( + krb5_context /*context*/, + const char */*name*/, + krb5_principal */*principal*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_parse_name_flags ( + krb5_context /*context*/, + const char */*name*/, + int /*flags*/, + krb5_principal */*principal*/); + +krb5_error_code +krb5_parse_nametype ( + krb5_context /*context*/, + const char */*str*/, + int32_t */*nametype*/); + +const char* KRB5_LIB_FUNCTION +krb5_passwd_result_to_string ( + krb5_context /*context*/, + int /*result*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_password_key_proc ( + krb5_context /*context*/, + krb5_enctype /*type*/, + krb5_salt /*salt*/, + krb5_const_pointer /*keyseed*/, + krb5_keyblock **/*key*/); + +krb5_error_code +krb5_plugin_register ( + krb5_context /*context*/, + enum krb5_plugin_type /*type*/, + const char */*name*/, + void */*symbol*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_prepend_config_files ( + const char */*filelist*/, + char **/*pq*/, + char ***/*ret_pp*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_prepend_config_files_default ( + const char */*filelist*/, + char ***/*pfilenames*/); + +krb5_realm * KRB5_LIB_FUNCTION +krb5_princ_realm ( + krb5_context /*context*/, + krb5_principal /*principal*/); + +void KRB5_LIB_FUNCTION +krb5_princ_set_realm ( + krb5_context /*context*/, + krb5_principal /*principal*/, + krb5_realm */*realm*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_principal_compare ( + krb5_context /*context*/, + krb5_const_principal /*princ1*/, + krb5_const_principal /*princ2*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_principal_compare_any_realm ( + krb5_context /*context*/, + krb5_const_principal /*princ1*/, + krb5_const_principal /*princ2*/); + +const char* KRB5_LIB_FUNCTION +krb5_principal_get_comp_string ( + krb5_context /*context*/, + krb5_const_principal /*principal*/, + unsigned int /*component*/); + +const char* KRB5_LIB_FUNCTION +krb5_principal_get_realm ( + krb5_context /*context*/, + krb5_const_principal /*principal*/); + +int KRB5_LIB_FUNCTION +krb5_principal_get_type ( + krb5_context /*context*/, + krb5_const_principal /*principal*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_principal_match ( + krb5_context /*context*/, + krb5_const_principal /*princ*/, + krb5_const_principal /*pattern*/); + +void KRB5_LIB_FUNCTION +krb5_principal_set_type ( + krb5_context /*context*/, + krb5_principal /*principal*/, + int /*type*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_print_address ( + const krb5_address */*addr*/, + char */*str*/, + size_t /*len*/, + size_t */*ret_len*/); + +int KRB5_LIB_FUNCTION +krb5_program_setup ( + krb5_context */*context*/, + int /*argc*/, + char **/*argv*/, + struct getargs */*args*/, + int /*num_args*/, + void (*/*usage*/)(int, struct getargs*, int)); + +int KRB5_LIB_FUNCTION +krb5_prompter_posix ( + krb5_context /*context*/, + void */*data*/, + const char */*name*/, + const char */*banner*/, + int /*num_prompts*/, + krb5_prompt prompts[]); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_random_to_key ( + krb5_context /*context*/, + krb5_enctype /*type*/, + const void */*data*/, + size_t /*size*/, + krb5_keyblock */*key*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_close ( + krb5_context /*context*/, + krb5_rcache /*id*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_default ( + krb5_context /*context*/, + krb5_rcache */*id*/); + +const char* KRB5_LIB_FUNCTION +krb5_rc_default_name (krb5_context /*context*/); + +const char* KRB5_LIB_FUNCTION +krb5_rc_default_type (krb5_context /*context*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_destroy ( + krb5_context /*context*/, + krb5_rcache /*id*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_expunge ( + krb5_context /*context*/, + krb5_rcache /*id*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_get_lifespan ( + krb5_context /*context*/, + krb5_rcache /*id*/, + krb5_deltat */*auth_lifespan*/); + +const char* KRB5_LIB_FUNCTION +krb5_rc_get_name ( + krb5_context /*context*/, + krb5_rcache /*id*/); + +const char* KRB5_LIB_FUNCTION +krb5_rc_get_type ( + krb5_context /*context*/, + krb5_rcache /*id*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_initialize ( + krb5_context /*context*/, + krb5_rcache /*id*/, + krb5_deltat /*auth_lifespan*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_recover ( + krb5_context /*context*/, + krb5_rcache /*id*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_resolve ( + krb5_context /*context*/, + krb5_rcache /*id*/, + const char */*name*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_resolve_full ( + krb5_context /*context*/, + krb5_rcache */*id*/, + const char */*string_name*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_resolve_type ( + krb5_context /*context*/, + krb5_rcache */*id*/, + const char */*type*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_store ( + krb5_context /*context*/, + krb5_rcache /*id*/, + krb5_donot_replay */*rep*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_cred ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_data */*in_data*/, + krb5_creds ***/*ret_creds*/, + krb5_replay_data */*outdata*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_cred2 ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_ccache /*ccache*/, + krb5_data */*in_data*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_error ( + krb5_context /*context*/, + const krb5_data */*msg*/, + KRB_ERROR */*result*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_priv ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + const krb5_data */*inbuf*/, + krb5_data */*outbuf*/, + krb5_replay_data */*outdata*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_rep ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + const krb5_data */*inbuf*/, + krb5_ap_rep_enc_part **/*repl*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_req ( + krb5_context /*context*/, + krb5_auth_context */*auth_context*/, + const krb5_data */*inbuf*/, + krb5_const_principal /*server*/, + krb5_keytab /*keytab*/, + krb5_flags */*ap_req_options*/, + krb5_ticket **/*ticket*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_req_ctx ( + krb5_context /*context*/, + krb5_auth_context */*auth_context*/, + const krb5_data */*inbuf*/, + krb5_const_principal /*server*/, + krb5_rd_req_in_ctx /*inctx*/, + krb5_rd_req_out_ctx */*outctx*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_req_in_ctx_alloc ( + krb5_context /*context*/, + krb5_rd_req_in_ctx */*ctx*/); + +void KRB5_LIB_FUNCTION +krb5_rd_req_in_ctx_free ( + krb5_context /*context*/, + krb5_rd_req_in_ctx /*ctx*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_req_in_set_keyblock ( + krb5_context /*context*/, + krb5_rd_req_in_ctx /*in*/, + krb5_keyblock */*keyblock*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_req_in_set_keytab ( + krb5_context /*context*/, + krb5_rd_req_in_ctx /*in*/, + krb5_keytab /*keytab*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_req_in_set_pac_check ( + krb5_context /*context*/, + krb5_rd_req_in_ctx /*in*/, + krb5_boolean /*flag*/); + +void KRB5_LIB_FUNCTION +krb5_rd_req_out_ctx_free ( + krb5_context /*context*/, + krb5_rd_req_out_ctx /*ctx*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_req_out_get_ap_req_options ( + krb5_context /*context*/, + krb5_rd_req_out_ctx /*out*/, + krb5_flags */*ap_req_options*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_req_out_get_keyblock ( + krb5_context /*context*/, + krb5_rd_req_out_ctx /*out*/, + krb5_keyblock **/*keyblock*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_req_out_get_ticket ( + krb5_context /*context*/, + krb5_rd_req_out_ctx /*out*/, + krb5_ticket **/*ticket*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_req_with_keyblock ( + krb5_context /*context*/, + krb5_auth_context */*auth_context*/, + const krb5_data */*inbuf*/, + krb5_const_principal /*server*/, + krb5_keyblock */*keyblock*/, + krb5_flags */*ap_req_options*/, + krb5_ticket **/*ticket*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_safe ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + const krb5_data */*inbuf*/, + krb5_data */*outbuf*/, + krb5_replay_data */*outdata*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_read_message ( + krb5_context /*context*/, + krb5_pointer /*p_fd*/, + krb5_data */*data*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_read_priv_message ( + krb5_context /*context*/, + krb5_auth_context /*ac*/, + krb5_pointer /*p_fd*/, + krb5_data */*data*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_read_safe_message ( + krb5_context /*context*/, + krb5_auth_context /*ac*/, + krb5_pointer /*p_fd*/, + krb5_data */*data*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_realm_compare ( + krb5_context /*context*/, + krb5_const_principal /*princ1*/, + krb5_const_principal /*princ2*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_recvauth ( + krb5_context /*context*/, + krb5_auth_context */*auth_context*/, + krb5_pointer /*p_fd*/, + const char */*appl_version*/, + krb5_principal /*server*/, + int32_t /*flags*/, + krb5_keytab /*keytab*/, + krb5_ticket **/*ticket*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_recvauth_match_version ( + krb5_context /*context*/, + krb5_auth_context */*auth_context*/, + krb5_pointer /*p_fd*/, + krb5_boolean (*/*match_appl_version*/)(const void *, const char*), + const void */*match_data*/, + krb5_principal /*server*/, + int32_t /*flags*/, + krb5_keytab /*keytab*/, + krb5_ticket **/*ticket*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_address ( + krb5_storage */*sp*/, + krb5_address */*adr*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_addrs ( + krb5_storage */*sp*/, + krb5_addresses */*adr*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_authdata ( + krb5_storage */*sp*/, + krb5_authdata */*auth*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_creds ( + krb5_storage */*sp*/, + krb5_creds */*creds*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_creds_tag ( + krb5_storage */*sp*/, + krb5_creds */*creds*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_data ( + krb5_storage */*sp*/, + krb5_data */*data*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_int16 ( + krb5_storage */*sp*/, + int16_t */*value*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_int32 ( + krb5_storage */*sp*/, + int32_t */*value*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_int8 ( + krb5_storage */*sp*/, + int8_t */*value*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_keyblock ( + krb5_storage */*sp*/, + krb5_keyblock */*p*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_principal ( + krb5_storage */*sp*/, + krb5_principal */*princ*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_string ( + krb5_storage */*sp*/, + char **/*string*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_stringnl ( + krb5_storage */*sp*/, + char **/*string*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_stringz ( + krb5_storage */*sp*/, + char **/*string*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_times ( + krb5_storage */*sp*/, + krb5_times */*times*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_uint16 ( + krb5_storage */*sp*/, + uint16_t */*value*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_uint32 ( + krb5_storage */*sp*/, + uint32_t */*value*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_uint8 ( + krb5_storage */*sp*/, + uint8_t */*value*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_salttype_to_string ( + krb5_context /*context*/, + krb5_enctype /*etype*/, + krb5_salttype /*stype*/, + char **/*string*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_sendauth ( + krb5_context /*context*/, + krb5_auth_context */*auth_context*/, + krb5_pointer /*p_fd*/, + const char */*appl_version*/, + krb5_principal /*client*/, + krb5_principal /*server*/, + krb5_flags /*ap_req_options*/, + krb5_data */*in_data*/, + krb5_creds */*in_creds*/, + krb5_ccache /*ccache*/, + krb5_error **/*ret_error*/, + krb5_ap_rep_enc_part **/*rep_result*/, + krb5_creds **/*out_creds*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_sendto ( + krb5_context /*context*/, + const krb5_data */*send_data*/, + krb5_krbhst_handle /*handle*/, + krb5_data */*receive*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_sendto_context ( + krb5_context /*context*/, + krb5_sendto_ctx /*ctx*/, + const krb5_data */*send_data*/, + const krb5_realm /*realm*/, + krb5_data */*receive*/); + +void KRB5_LIB_FUNCTION +krb5_sendto_ctx_add_flags ( + krb5_sendto_ctx /*ctx*/, + int /*flags*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_sendto_ctx_alloc ( + krb5_context /*context*/, + krb5_sendto_ctx */*ctx*/); + +void KRB5_LIB_FUNCTION +krb5_sendto_ctx_free ( + krb5_context /*context*/, + krb5_sendto_ctx /*ctx*/); + +int KRB5_LIB_FUNCTION +krb5_sendto_ctx_get_flags (krb5_sendto_ctx /*ctx*/); + +void KRB5_LIB_FUNCTION +krb5_sendto_ctx_set_func ( + krb5_sendto_ctx /*ctx*/, + krb5_sendto_ctx_func /*func*/, + void */*data*/); + +void KRB5_LIB_FUNCTION +krb5_sendto_ctx_set_type ( + krb5_sendto_ctx /*ctx*/, + int /*type*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_sendto_kdc ( + krb5_context /*context*/, + const krb5_data */*send_data*/, + const krb5_realm */*realm*/, + krb5_data */*receive*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_sendto_kdc_flags ( + krb5_context /*context*/, + const krb5_data */*send_data*/, + const krb5_realm */*realm*/, + krb5_data */*receive*/, + int /*flags*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_config_files ( + krb5_context /*context*/, + char **/*filenames*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_default_in_tkt_etypes ( + krb5_context /*context*/, + const krb5_enctype */*etypes*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_default_realm ( + krb5_context /*context*/, + const char */*realm*/); + +void KRB5_LIB_FUNCTION +krb5_set_dns_canonicalize_hostname ( + krb5_context /*context*/, + krb5_boolean /*flag*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_error_string ( + krb5_context /*context*/, + const char */*fmt*/, + ...) + __attribute__((format (printf, 2, 3))); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_extra_addresses ( + krb5_context /*context*/, + const krb5_addresses */*addresses*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_fcache_version ( + krb5_context /*context*/, + int /*version*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_ignore_addresses ( + krb5_context /*context*/, + const krb5_addresses */*addresses*/); + +void KRB5_LIB_FUNCTION +krb5_set_max_time_skew ( + krb5_context /*context*/, + time_t /*t*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_password ( + krb5_context /*context*/, + krb5_creds */*creds*/, + const char */*newpw*/, + krb5_principal /*targprinc*/, + int */*result_code*/, + krb5_data */*result_code_string*/, + krb5_data */*result_string*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_password_using_ccache ( + krb5_context /*context*/, + krb5_ccache /*ccache*/, + const char */*newpw*/, + krb5_principal /*targprinc*/, + int */*result_code*/, + krb5_data */*result_code_string*/, + krb5_data */*result_string*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_real_time ( + krb5_context /*context*/, + krb5_timestamp /*sec*/, + int32_t /*usec*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_send_to_kdc_func ( + krb5_context /*context*/, + krb5_send_to_kdc_func /*func*/, + void */*data*/); + +void KRB5_LIB_FUNCTION +krb5_set_use_admin_kdc ( + krb5_context /*context*/, + krb5_boolean /*flag*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_warn_dest ( + krb5_context /*context*/, + krb5_log_facility */*fac*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_sname_to_principal ( + krb5_context /*context*/, + const char */*hostname*/, + const char */*sname*/, + int32_t /*type*/, + krb5_principal */*ret_princ*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_sock_to_principal ( + krb5_context /*context*/, + int /*sock*/, + const char */*sname*/, + int32_t /*type*/, + krb5_principal */*ret_princ*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_sockaddr2address ( + krb5_context /*context*/, + const struct sockaddr */*sa*/, + krb5_address */*addr*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_sockaddr2port ( + krb5_context /*context*/, + const struct sockaddr */*sa*/, + int16_t */*port*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_sockaddr_uninteresting (const struct sockaddr */*sa*/); + +void KRB5_LIB_FUNCTION +krb5_std_usage ( + int /*code*/, + struct getargs */*args*/, + int /*num_args*/); + +void KRB5_LIB_FUNCTION +krb5_storage_clear_flags ( + krb5_storage */*sp*/, + krb5_flags /*flags*/); + +krb5_storage * KRB5_LIB_FUNCTION +krb5_storage_emem (void); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_storage_free (krb5_storage */*sp*/); + +krb5_storage * KRB5_LIB_FUNCTION +krb5_storage_from_data (krb5_data */*data*/); + +krb5_storage * KRB5_LIB_FUNCTION +krb5_storage_from_fd (int /*fd*/); + +krb5_storage * KRB5_LIB_FUNCTION +krb5_storage_from_mem ( + void */*buf*/, + size_t /*len*/); + +krb5_storage * KRB5_LIB_FUNCTION +krb5_storage_from_readonly_mem ( + const void */*buf*/, + size_t /*len*/); + +krb5_flags KRB5_LIB_FUNCTION +krb5_storage_get_byteorder ( + krb5_storage */*sp*/, + krb5_flags /*byteorder*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_storage_is_flags ( + krb5_storage */*sp*/, + krb5_flags /*flags*/); + +krb5_ssize_t KRB5_LIB_FUNCTION +krb5_storage_read ( + krb5_storage */*sp*/, + void */*buf*/, + size_t /*len*/); + +off_t KRB5_LIB_FUNCTION +krb5_storage_seek ( + krb5_storage */*sp*/, + off_t /*offset*/, + int /*whence*/); + +void KRB5_LIB_FUNCTION +krb5_storage_set_byteorder ( + krb5_storage */*sp*/, + krb5_flags /*byteorder*/); + +void KRB5_LIB_FUNCTION +krb5_storage_set_eof_code ( + krb5_storage */*sp*/, + int /*code*/); + +void KRB5_LIB_FUNCTION +krb5_storage_set_flags ( + krb5_storage */*sp*/, + krb5_flags /*flags*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_storage_to_data ( + krb5_storage */*sp*/, + krb5_data */*data*/); + +krb5_ssize_t KRB5_LIB_FUNCTION +krb5_storage_write ( + krb5_storage */*sp*/, + const void */*buf*/, + size_t /*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_address ( + krb5_storage */*sp*/, + krb5_address /*p*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_addrs ( + krb5_storage */*sp*/, + krb5_addresses /*p*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_authdata ( + krb5_storage */*sp*/, + krb5_authdata /*auth*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_creds ( + krb5_storage */*sp*/, + krb5_creds */*creds*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_creds_tag ( + krb5_storage */*sp*/, + krb5_creds */*creds*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_data ( + krb5_storage */*sp*/, + krb5_data /*data*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_int16 ( + krb5_storage */*sp*/, + int16_t /*value*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_int32 ( + krb5_storage */*sp*/, + int32_t /*value*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_int8 ( + krb5_storage */*sp*/, + int8_t /*value*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_keyblock ( + krb5_storage */*sp*/, + krb5_keyblock /*p*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_principal ( + krb5_storage */*sp*/, + krb5_const_principal /*p*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_string ( + krb5_storage */*sp*/, + const char */*s*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_stringnl ( + krb5_storage */*sp*/, + const char */*s*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_stringz ( + krb5_storage */*sp*/, + const char */*s*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_times ( + krb5_storage */*sp*/, + krb5_times /*times*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_uint16 ( + krb5_storage */*sp*/, + uint16_t /*value*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_uint32 ( + krb5_storage */*sp*/, + uint32_t /*value*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_uint8 ( + krb5_storage */*sp*/, + uint8_t /*value*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_deltat ( + const char */*string*/, + krb5_deltat */*deltat*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_enctype ( + krb5_context /*context*/, + const char */*string*/, + krb5_enctype */*etype*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_key ( + krb5_context /*context*/, + krb5_enctype /*enctype*/, + const char */*password*/, + krb5_principal /*principal*/, + krb5_keyblock */*key*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_key_data ( + krb5_context /*context*/, + krb5_enctype /*enctype*/, + krb5_data /*password*/, + krb5_principal /*principal*/, + krb5_keyblock */*key*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_key_data_salt ( + krb5_context /*context*/, + krb5_enctype /*enctype*/, + krb5_data /*password*/, + krb5_salt /*salt*/, + krb5_keyblock */*key*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_key_data_salt_opaque ( + krb5_context /*context*/, + krb5_enctype /*enctype*/, + krb5_data /*password*/, + krb5_salt /*salt*/, + krb5_data /*opaque*/, + krb5_keyblock */*key*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_key_derived ( + krb5_context /*context*/, + const void */*str*/, + size_t /*len*/, + krb5_enctype /*etype*/, + krb5_keyblock */*key*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_key_salt ( + krb5_context /*context*/, + krb5_enctype /*enctype*/, + const char */*password*/, + krb5_salt /*salt*/, + krb5_keyblock */*key*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_key_salt_opaque ( + krb5_context /*context*/, + krb5_enctype /*enctype*/, + const char */*password*/, + krb5_salt /*salt*/, + krb5_data /*opaque*/, + krb5_keyblock */*key*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_keytype ( + krb5_context /*context*/, + const char */*string*/, + krb5_keytype */*keytype*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_salttype ( + krb5_context /*context*/, + krb5_enctype /*etype*/, + const char */*string*/, + krb5_salttype */*salttype*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ticket_get_authorization_data_type ( + krb5_context /*context*/, + krb5_ticket */*ticket*/, + int /*type*/, + krb5_data */*data*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ticket_get_client ( + krb5_context /*context*/, + const krb5_ticket */*ticket*/, + krb5_principal */*client*/); + +time_t KRB5_LIB_FUNCTION +krb5_ticket_get_endtime ( + krb5_context /*context*/, + const krb5_ticket */*ticket*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ticket_get_server ( + krb5_context /*context*/, + const krb5_ticket */*ticket*/, + krb5_principal */*server*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_timeofday ( + krb5_context /*context*/, + krb5_timestamp */*timeret*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_unparse_name ( + krb5_context /*context*/, + krb5_const_principal /*principal*/, + char **/*name*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_unparse_name_fixed ( + krb5_context /*context*/, + krb5_const_principal /*principal*/, + char */*name*/, + size_t /*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_unparse_name_fixed_flags ( + krb5_context /*context*/, + krb5_const_principal /*principal*/, + int /*flags*/, + char */*name*/, + size_t /*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_unparse_name_fixed_short ( + krb5_context /*context*/, + krb5_const_principal /*principal*/, + char */*name*/, + size_t /*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_unparse_name_flags ( + krb5_context /*context*/, + krb5_const_principal /*principal*/, + int /*flags*/, + char **/*name*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_unparse_name_short ( + krb5_context /*context*/, + krb5_const_principal /*principal*/, + char **/*name*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_us_timeofday ( + krb5_context /*context*/, + krb5_timestamp */*sec*/, + int32_t */*usec*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_vabort ( + krb5_context /*context*/, + krb5_error_code /*code*/, + const char */*fmt*/, + va_list /*ap*/) + __attribute__ ((noreturn, format (printf, 3, 0))); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_vabortx ( + krb5_context /*context*/, + const char */*fmt*/, + va_list /*ap*/) + __attribute__ ((noreturn, format (printf, 2, 0))); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_verify_ap_req ( + krb5_context /*context*/, + krb5_auth_context */*auth_context*/, + krb5_ap_req */*ap_req*/, + krb5_const_principal /*server*/, + krb5_keyblock */*keyblock*/, + krb5_flags /*flags*/, + krb5_flags */*ap_req_options*/, + krb5_ticket **/*ticket*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_verify_ap_req2 ( + krb5_context /*context*/, + krb5_auth_context */*auth_context*/, + krb5_ap_req */*ap_req*/, + krb5_const_principal /*server*/, + krb5_keyblock */*keyblock*/, + krb5_flags /*flags*/, + krb5_flags */*ap_req_options*/, + krb5_ticket **/*ticket*/, + krb5_key_usage /*usage*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_verify_authenticator_checksum ( + krb5_context /*context*/, + krb5_auth_context /*ac*/, + void */*data*/, + size_t /*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_verify_checksum ( + krb5_context /*context*/, + krb5_crypto /*crypto*/, + krb5_key_usage /*usage*/, + void */*data*/, + size_t /*len*/, + Checksum */*cksum*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_verify_init_creds ( + krb5_context /*context*/, + krb5_creds */*creds*/, + krb5_principal /*ap_req_server*/, + krb5_keytab /*ap_req_keytab*/, + krb5_ccache */*ccache*/, + krb5_verify_init_creds_opt */*options*/); + +void KRB5_LIB_FUNCTION +krb5_verify_init_creds_opt_init (krb5_verify_init_creds_opt */*options*/); + +void KRB5_LIB_FUNCTION +krb5_verify_init_creds_opt_set_ap_req_nofail ( + krb5_verify_init_creds_opt */*options*/, + int /*ap_req_nofail*/); + +int KRB5_LIB_FUNCTION +krb5_verify_opt_alloc ( + krb5_context /*context*/, + krb5_verify_opt **/*opt*/); + +void KRB5_LIB_FUNCTION +krb5_verify_opt_free (krb5_verify_opt */*opt*/); + +void KRB5_LIB_FUNCTION +krb5_verify_opt_init (krb5_verify_opt */*opt*/); + +void KRB5_LIB_FUNCTION +krb5_verify_opt_set_ccache ( + krb5_verify_opt */*opt*/, + krb5_ccache /*ccache*/); + +void KRB5_LIB_FUNCTION +krb5_verify_opt_set_flags ( + krb5_verify_opt */*opt*/, + unsigned int /*flags*/); + +void KRB5_LIB_FUNCTION +krb5_verify_opt_set_keytab ( + krb5_verify_opt */*opt*/, + krb5_keytab /*keytab*/); + +void KRB5_LIB_FUNCTION +krb5_verify_opt_set_secure ( + krb5_verify_opt */*opt*/, + krb5_boolean /*secure*/); + +void KRB5_LIB_FUNCTION +krb5_verify_opt_set_service ( + krb5_verify_opt */*opt*/, + const char */*service*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_verify_user ( + krb5_context /*context*/, + krb5_principal /*principal*/, + krb5_ccache /*ccache*/, + const char */*password*/, + krb5_boolean /*secure*/, + const char */*service*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_verify_user_lrealm ( + krb5_context /*context*/, + krb5_principal /*principal*/, + krb5_ccache /*ccache*/, + const char */*password*/, + krb5_boolean /*secure*/, + const char */*service*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_verify_user_opt ( + krb5_context /*context*/, + krb5_principal /*principal*/, + const char */*password*/, + krb5_verify_opt */*opt*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_verr ( + krb5_context /*context*/, + int /*eval*/, + krb5_error_code /*code*/, + const char */*fmt*/, + va_list /*ap*/) + __attribute__ ((noreturn, format (printf, 4, 0))); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_verrx ( + krb5_context /*context*/, + int /*eval*/, + const char */*fmt*/, + va_list /*ap*/) + __attribute__ ((noreturn, format (printf, 3, 0))); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_vlog ( + krb5_context /*context*/, + krb5_log_facility */*fac*/, + int /*level*/, + const char */*fmt*/, + va_list /*ap*/) + __attribute__((format (printf, 4, 0))); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_vlog_msg ( + krb5_context /*context*/, + krb5_log_facility */*fac*/, + char **/*reply*/, + int /*level*/, + const char */*fmt*/, + va_list /*ap*/) + __attribute__((format (printf, 5, 0))); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_vset_error_string ( + krb5_context /*context*/, + const char */*fmt*/, + va_list /*args*/) + __attribute__ ((format (printf, 2, 0))); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_vwarn ( + krb5_context /*context*/, + krb5_error_code /*code*/, + const char */*fmt*/, + va_list /*ap*/) + __attribute__ ((format (printf, 3, 0))); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_vwarnx ( + krb5_context /*context*/, + const char */*fmt*/, + va_list /*ap*/) + __attribute__ ((format (printf, 2, 0))); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_warn ( + krb5_context /*context*/, + krb5_error_code /*code*/, + const char */*fmt*/, + ...) + __attribute__ ((format (printf, 3, 4))); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_warnx ( + krb5_context /*context*/, + const char */*fmt*/, + ...) + __attribute__ ((format (printf, 2, 3))); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_write_message ( + krb5_context /*context*/, + krb5_pointer /*p_fd*/, + krb5_data */*data*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_write_priv_message ( + krb5_context /*context*/, + krb5_auth_context /*ac*/, + krb5_pointer /*p_fd*/, + krb5_data */*data*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_write_safe_message ( + krb5_context /*context*/, + krb5_auth_context /*ac*/, + krb5_pointer /*p_fd*/, + krb5_data */*data*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_xfree (void */*ptr*/); + +#ifdef __cplusplus +} +#endif + +#endif /* __krb5_protos_h__ */ diff --git a/lib/krb5/krb5-v4compat.h b/lib/krb5/krb5-v4compat.h new file mode 100644 index 0000000..dfd7e94 --- /dev/null +++ b/lib/krb5/krb5-v4compat.h @@ -0,0 +1,132 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $Id: krb5-v4compat.h 21575 2007-07-16 07:44:54Z lha $ */ + +#ifndef __KRB5_V4COMPAT_H__ +#define __KRB5_V4COMPAT_H__ + +#include "krb_err.h" + +/* + * This file must only be included with v4 compat glue stuff in + * heimdal sources. + * + * It MUST NOT be installed. + */ + +#define KRB_PROT_VERSION 4 + +#define AUTH_MSG_KDC_REQUEST (1<<1) +#define AUTH_MSG_KDC_REPLY (2<<1) +#define AUTH_MSG_APPL_REQUEST (3<<1) +#define AUTH_MSG_APPL_REQUEST_MUTUAL (4<<1) +#define AUTH_MSG_ERR_REPLY (5<<1) +#define AUTH_MSG_PRIVATE (6<<1) +#define AUTH_MSG_SAFE (7<<1) +#define AUTH_MSG_APPL_ERR (8<<1) +#define AUTH_MSG_KDC_FORWARD (9<<1) +#define AUTH_MSG_KDC_RENEW (10<<1) +#define AUTH_MSG_DIE (63<<1) + +/* General definitions */ +#define KSUCCESS 0 +#define KFAILURE 255 + +/* */ + +#define MAX_KTXT_LEN 1250 + +#define ANAME_SZ 40 +#define REALM_SZ 40 +#define SNAME_SZ 40 +#define INST_SZ 40 + +struct ktext { + unsigned int length; /* Length of the text */ + unsigned char dat[MAX_KTXT_LEN]; /* The data itself */ + uint32_t mbz; /* zero to catch runaway strings */ +}; + +struct credentials { + char service[ANAME_SZ]; /* Service name */ + char instance[INST_SZ]; /* Instance */ + char realm[REALM_SZ]; /* Auth domain */ + char session[8]; /* Session key */ + int lifetime; /* Lifetime */ + int kvno; /* Key version number */ + struct ktext ticket_st; /* The ticket itself */ + int32_t issue_date; /* The issue time */ + char pname[ANAME_SZ]; /* Principal's name */ + char pinst[INST_SZ]; /* Principal's instance */ +}; + +#define TKTLIFENUMFIXED 64 +#define TKTLIFEMINFIXED 0x80 +#define TKTLIFEMAXFIXED 0xBF +#define TKTLIFENOEXPIRE 0xFF +#define MAXTKTLIFETIME (30*24*3600) /* 30 days */ +#ifndef NEVERDATE +#define NEVERDATE ((time_t)0x7fffffffL) +#endif + +#define KERB_ERR_NULL_KEY 10 + +#define CLOCK_SKEW 5*60 + +#ifndef TKT_ROOT +#define TKT_ROOT "/tmp/tkt" +#endif + +struct _krb5_krb_auth_data { + int8_t k_flags; /* Flags from ticket */ + char *pname; /* Principal's name */ + char *pinst; /* His Instance */ + char *prealm; /* His Realm */ + uint32_t checksum; /* Data checksum (opt) */ + krb5_keyblock session; /* Session Key */ + unsigned char life; /* Life of ticket */ + uint32_t time_sec; /* Time ticket issued */ + uint32_t address; /* Address in ticket */ +}; + +time_t _krb5_krb_life_to_time (int, int); +int _krb5_krb_time_to_life (time_t, time_t); +krb5_error_code _krb5_krb_tf_setup (krb5_context, struct credentials *, + const char *, int); +krb5_error_code _krb5_krb_dest_tkt(krb5_context, const char *); + +#define krb_time_to_life _krb5_krb_time_to_life +#define krb_life_to_time _krb5_krb_life_to_time + +#endif /* __KRB5_V4COMPAT_H__ */ diff --git a/lib/krb5/krb5.3 b/lib/krb5/krb5.3 new file mode 100644 index 0000000..3ce8c1f --- /dev/null +++ b/lib/krb5/krb5.3 @@ -0,0 +1,526 @@ +.\" Copyright (c) 2001, 2003 - 2006 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5.3 18212 2006-10-03 10:39:35Z lha $ +.\" +.Dd May 1, 2006 +.Dt KRB5 3 +.Os +.Sh NAME +.Nm krb5 +.Nd Kerberos 5 library +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Sh DESCRIPTION +These functions constitute the Kerberos 5 library, +.Em libkrb5 . +.Sh LIST OF FUNCTIONS +.sp 2 +.nf +.ta \w'krb5_ticket_get_authorization_data_type.3'u+2n +\w'Description goes here'u +\fIName/Page\fP \fIDescription\fP +.ta \w'krb5_ticket_get_authorization_data_type.3'u+2n +\w'Description goes here'u+6nC +.sp 5p +krb524_convert_creds_kdc.3 +krb524_convert_creds_kdc_cache.3 +krb5_425_conv_principal.3 +krb5_425_conv_principal_ext.3 +krb5_524_conv_principal.3 +krb5_abort.3 +krb5_abortx.3 +krb5_acl_match_file.3 +krb5_acl_match_string.3 +krb5_add_et_list.3 +krb5_add_extra_addresses.3 +krb5_add_ignore_addresses.3 +krb5_addlog_dest.3 +krb5_addlog_func.3 +krb5_addr2sockaddr.3 +krb5_address.3 +krb5_address_compare.3 +krb5_address_order.3 +krb5_address_search.3 +krb5_addresses.3 +krb5_aname_to_localname.3 +krb5_anyaddr.3 +krb5_appdefault_boolean.3 +krb5_appdefault_string.3 +krb5_appdefault_time.3 +krb5_append_addresses.3 +krb5_auth_con_addflags.3 +krb5_auth_con_free.3 +krb5_auth_con_genaddrs.3 +krb5_auth_con_generatelocalsubkey.3 +krb5_auth_con_getaddrs.3 +krb5_auth_con_getauthenticator.3 +krb5_auth_con_getcksumtype.3 +krb5_auth_con_getflags.3 +krb5_auth_con_getkey.3 +krb5_auth_con_getkeytype.3 +krb5_auth_con_getlocalseqnumber.3 +krb5_auth_con_getlocalsubkey.3 +krb5_auth_con_getrcache.3 +krb5_auth_con_getremotesubkey.3 +krb5_auth_con_getuserkey.3 +krb5_auth_con_init.3 +krb5_auth_con_initivector.3 +krb5_auth_con_removeflags.3 +krb5_auth_con_setaddrs.3 +krb5_auth_con_setaddrs_from_fd.3 +krb5_auth_con_setcksumtype.3 +krb5_auth_con_setflags.3 +krb5_auth_con_setivector.3 +krb5_auth_con_setkey.3 +krb5_auth_con_setkeytype.3 +krb5_auth_con_setlocalseqnumber.3 +krb5_auth_con_setlocalsubkey.3 +krb5_auth_con_setrcache.3 +krb5_auth_con_setremoteseqnumber.3 +krb5_auth_con_setremotesubkey.3 +krb5_auth_con_setuserkey.3 +krb5_auth_context.3 +krb5_auth_getremoteseqnumber.3 +krb5_build_principal.3 +krb5_build_principal_ext.3 +krb5_build_principal_va.3 +krb5_build_principal_va_ext.3 +krb5_c_block_size.3 +krb5_c_checksum_length.3 +krb5_c_decrypt.3 +krb5_c_encrypt.3 +krb5_c_encrypt_length.3 +krb5_c_enctype_compare.3 +krb5_c_get_checksum.3 +krb5_c_is_coll_proof_cksum.3 +krb5_c_is_keyed_cksum.3 +krb5_c_make_checksum.3 +krb5_c_make_random_key.3 +krb5_c_set_checksum.3 +krb5_c_valid_cksumtype.3 +krb5_c_valid_enctype.3 +krb5_c_verify_checksum.3 +krb5_cc_cache_end_seq_get.3 +krb5_cc_cache_get_first.3 +krb5_cc_cache_match.3 +krb5_cc_cache_next.3 +krb5_cc_close.3 +krb5_cc_copy_cache.3 +krb5_cc_default.3 +krb5_cc_default_name.3 +krb5_cc_destroy.3 +krb5_cc_end_seq_get.3 +krb5_cc_gen_new.3 +krb5_cc_get_full_name.3 +krb5_cc_get_name.3 +krb5_cc_get_ops.3 +krb5_cc_get_principal.3 +krb5_cc_get_type.3 +krb5_cc_get_version.3 +krb5_cc_initialize.3 +krb5_cc_new_unique.3 +krb5_cc_next_cred.3 +krb5_cc_register.3 +krb5_cc_remove_cred.3 +krb5_cc_resolve.3 +krb5_cc_retrieve_cred.3 +krb5_cc_set_default_name.3 +krb5_cc_set_flags.3 +krb5_cc_store_cred.3 +krb5_change_password.3 +krb5_check_transited.3 +krb5_check_transited_realms.3 +krb5_checksum_disable.3 +krb5_checksum_free.3 +krb5_checksum_is_collision_proof.3 +krb5_checksum_is_keyed.3 +krb5_checksumsize.3 +krb5_clear_error_string.3 +krb5_closelog.3 +krb5_config_file_free.3 +krb5_config_free_strings.3 +krb5_config_get.3 +krb5_config_get_bool.3 +krb5_config_get_bool_default.3 +krb5_config_get_int.3 +krb5_config_get_int_default.3 +krb5_config_get_list.3 +krb5_config_get_next.3 +krb5_config_get_string.3 +krb5_config_get_string_default.3 +krb5_config_get_strings.3 +krb5_config_get_time.3 +krb5_config_get_time_default.3 +krb5_config_parse_file.3 +krb5_config_parse_file_multi.3 +krb5_config_vget.3 +krb5_config_vget_bool.3 +krb5_config_vget_bool_default.3 +krb5_config_vget_int.3 +krb5_config_vget_int_default.3 +krb5_config_vget_list.3 +krb5_config_vget_next.3 +krb5_config_vget_string.3 +krb5_config_vget_string_default.3 +krb5_config_vget_strings.3 +krb5_config_vget_time.3 +krb5_config_vget_time_default.3 +krb5_context.3 +krb5_copy_address.3 +krb5_copy_addresses.3 +krb5_copy_checksum.3 +krb5_copy_data.3 +krb5_copy_host_realm.3 +krb5_copy_keyblock.3 +krb5_copy_keyblock_contents.3 +krb5_copy_principal.3 +krb5_copy_ticket.3 +krb5_create_checksum.3 +krb5_creds.3 +krb5_crypto_destroy.3 +krb5_crypto_get_checksum_type.3 +krb5_crypto_getblocksize.3 +krb5_crypto_getconfoundersize.3 +krb5_crypto_getenctype.3 +krb5_crypto_getpadsize.3 +krb5_crypto_init.3 +krb5_data_alloc.3 +krb5_data_copy.3 +krb5_data_free.3 +krb5_data_realloc.3 +krb5_data_zero.3 +krb5_decrypt.3 +krb5_decrypt_EncryptedData.3 +krb5_digest.3 +krb5_digest_alloc.3 +krb5_digest_free.3 +krb5_digest_get_a1_hash.3 +krb5_digest_get_client_binding.3 +krb5_digest_get_identifier.3 +krb5_digest_get_opaque.3 +krb5_digest_get_responseData.3 +krb5_digest_get_rsp.3 +krb5_digest_get_server_nonce.3 +krb5_digest_get_tickets.3 +krb5_digest_init_request.3 +krb5_digest_request.3 +krb5_digest_set_authentication_user.3 +krb5_digest_set_authid.3 +krb5_digest_set_client_nonce.3 +krb5_digest_set_digest.3 +krb5_digest_set_hostname.3 +krb5_digest_set_identifier.3 +krb5_digest_set_method.3 +krb5_digest_set_nonceCount.3 +krb5_digest_set_opaque.3 +krb5_digest_set_qop.3 +krb5_digest_set_realm.3 +krb5_digest_set_server_cb.3 +krb5_digest_set_server_nonce.3 +krb5_digest_set_type.3 +krb5_digest_set_uri.3 +krb5_digest_set_username.3 +krb5_domain_x500_decode.3 +krb5_domain_x500_encode.3 +krb5_eai_to_heim_errno.3 +krb5_encrypt.3 +krb5_encrypt_EncryptedData.3 +krb5_enctype_disable.3 +krb5_enctype_to_string.3 +krb5_enctype_valid.3 +krb5_err.3 +krb5_errx.3 +krb5_expand_hostname.3 +krb5_expand_hostname_realms.3 +krb5_find_padata.3 +krb5_format_time.3 +krb5_free_address.3 +krb5_free_addresses.3 +krb5_free_authenticator.3 +krb5_free_checksum.3 +krb5_free_checksum_contents.3 +krb5_free_config_files.3 +krb5_free_context.3 +krb5_free_data.3 +krb5_free_data_contents.3 +krb5_free_error_string.3 +krb5_free_host_realm.3 +krb5_free_kdc_rep.3 +krb5_free_keyblock.3 +krb5_free_keyblock_contents.3 +krb5_free_krbhst.3 +krb5_free_principal.3 +krb5_free_salt.3 +krb5_free_ticket.3 +krb5_fwd_tgt_creds.3 +krb5_generate_random_block.3 +krb5_generate_random_keyblock.3 +krb5_generate_subkey.3 +krb5_get_all_client_addrs.3 +krb5_get_all_server_addrs.3 +krb5_get_cred_from_kdc.3 +krb5_get_cred_from_kdc_opt.3 +krb5_get_credentials.3 +krb5_get_credentials_with_flags.3 +krb5_get_default_config_files.3 +krb5_get_default_principal.3 +krb5_get_default_realm.3 +krb5_get_default_realms.3 +krb5_get_err_text.3 +krb5_get_error_message.3 +krb5_get_error_string.3 +krb5_get_extra_addresses.3 +krb5_get_fcache_version.3 +krb5_get_forwarded_creds.3 +krb5_get_host_realm.3 +krb5_get_ignore_addresses.3 +krb5_get_in_cred.3 +krb5_get_in_tkt.3 +krb5_get_in_tkt_with_keytab.3 +krb5_get_in_tkt_with_password.3 +krb5_get_in_tkt_with_skey.3 +krb5_get_init_creds.3 +krb5_get_init_creds_keytab.3 +krb5_get_init_creds_opt_alloc.3 +krb5_get_init_creds_opt_free.3 +krb5_get_init_creds_opt_free_pkinit.3 +krb5_get_init_creds_opt_init.3 +krb5_get_init_creds_opt_set_address_list.3 +krb5_get_init_creds_opt_set_anonymous.3 +krb5_get_init_creds_opt_set_default_flags.3 +krb5_get_init_creds_opt_set_etype_list.3 +krb5_get_init_creds_opt_set_forwardable.3 +krb5_get_init_creds_opt_set_pa_password.3 +krb5_get_init_creds_opt_set_paq_request.3 +krb5_get_init_creds_opt_set_pkinit.3 +krb5_get_init_creds_opt_set_preauth_list.3 +krb5_get_init_creds_opt_set_proxiable.3 +krb5_get_init_creds_opt_set_renew_life.3 +krb5_get_init_creds_opt_set_salt.3 +krb5_get_init_creds_opt_set_tkt_life.3 +krb5_get_init_creds_password.3 +krb5_get_kdc_cred.3 +krb5_get_krb524hst.3 +krb5_get_krb_admin_hst.3 +krb5_get_krb_changepw_hst.3 +krb5_get_krbhst.3 +krb5_get_pw_salt.3 +krb5_get_server_rcache.3 +krb5_get_use_admin_kdc.3 +krb5_get_wrapped_length.3 +krb5_getportbyname.3 +krb5_h_addr2addr.3 +krb5_h_addr2sockaddr.3 +krb5_h_errno_to_heim_errno.3 +krb5_have_error_string.3 +krb5_hmac.3 +krb5_init_context.3 +krb5_init_ets.3 +krb5_initlog.3 +krb5_keyblock_get_enctype.3 +krb5_keyblock_zero.3 +krb5_keytab_entry.3 +krb5_krbhst_format_string.3 +krb5_krbhst_free.3 +krb5_krbhst_get_addrinfo.3 +krb5_krbhst_init.3 +krb5_krbhst_init_flags.3 +krb5_krbhst_next.3 +krb5_krbhst_next_as_string.3 +krb5_krbhst_reset.3 +krb5_kt_add_entry.3 +krb5_kt_close.3 +krb5_kt_compare.3 +krb5_kt_copy_entry_contents.3 +krb5_kt_cursor.3 +krb5_kt_default.3 +krb5_kt_default_modify_name.3 +krb5_kt_default_name.3 +krb5_kt_end_seq_get.3 +krb5_kt_free_entry.3 +krb5_kt_get_entry.3 +krb5_kt_get_name.3 +krb5_kt_get_type.3 +krb5_kt_next_entry.3 +krb5_kt_ops.3 +krb5_kt_read_service_key.3 +krb5_kt_register.3 +krb5_kt_remove_entry.3 +krb5_kt_resolve.3.3 +krb5_kt_start_seq_get +krb5_kuserok.3 +krb5_log.3 +krb5_log_msg.3 +krb5_make_addrport.3 +krb5_make_principal.3 +krb5_max_sockaddr_size.3 +krb5_openlog.3 +krb5_padata_add.3 +krb5_parse_address.3 +krb5_parse_name.3 +krb5_passwd_result_to_string.3 +krb5_password_key_proc.3 +krb5_prepend_config_files.3 +krb5_prepend_config_files_default.3 +krb5_princ_realm.3 +krb5_princ_set_realm.3 +krb5_principal.3 +krb5_principal_compare.3 +krb5_principal_compare_any_realm.3 +krb5_principal_get_comp_string.3 +krb5_principal_get_realm.3 +krb5_principal_get_type.3 +krb5_principal_match.3 +krb5_principal_set_type.3 +krb5_print_address.3 +krb5_rc_close.3 +krb5_rc_default.3 +krb5_rc_default_name.3 +krb5_rc_default_type.3 +krb5_rc_destroy.3 +krb5_rc_expunge.3 +krb5_rc_get_lifespan.3 +krb5_rc_get_name.3 +krb5_rc_get_type.3 +krb5_rc_initialize.3 +krb5_rc_recover.3 +krb5_rc_resolve.3 +krb5_rc_resolve_full.3 +krb5_rc_resolve_type.3 +krb5_rc_store.3 +krb5_rcache.3 +krb5_realm_compare.3 +krb5_ret_address.3 +krb5_ret_addrs.3 +krb5_ret_authdata.3 +krb5_ret_creds.3 +krb5_ret_data.3 +krb5_ret_int16.3 +krb5_ret_int32.3 +krb5_ret_int8.3 +krb5_ret_keyblock.3 +krb5_ret_principal.3 +krb5_ret_string.3 +krb5_ret_stringz.3 +krb5_ret_times.3 +krb5_set_config_files.3 +krb5_set_default_realm.3 +krb5_set_error_string.3 +krb5_set_extra_addresses.3 +krb5_set_fcache_version.3 +krb5_set_ignore_addresses.3 +krb5_set_password.3 +krb5_set_password_using_ccache.3 +krb5_set_real_time.3 +krb5_set_use_admin_kdc.3 +krb5_set_warn_dest.3 +krb5_sname_to_principal.3 +krb5_sock_to_principal.3 +krb5_sockaddr2address.3 +krb5_sockaddr2port.3 +krb5_sockaddr_uninteresting.3 +krb5_storage.3 +krb5_storage_clear_flags.3 +krb5_storage_emem.3 +krb5_storage_free.3 +krb5_storage_from_data.3 +krb5_storage_from_fd.3 +krb5_storage_from_mem.3 +krb5_storage_get_byteorder.3 +krb5_storage_is_flags.3 +krb5_storage_read.3 +krb5_storage_seek.3 +krb5_storage_set_byteorder.3 +krb5_storage_set_eof_code.3 +krb5_storage_set_flags.3 +krb5_storage_to_data.3 +krb5_storage_write.3 +krb5_store_address.3 +krb5_store_addrs.3 +krb5_store_authdata.3 +krb5_store_creds.3 +krb5_store_data.3 +krb5_store_int16.3 +krb5_store_int32.3 +krb5_store_int8.3 +krb5_store_keyblock.3 +krb5_store_principal.3 +krb5_store_string.3 +krb5_store_stringz.3 +krb5_store_times.3 +krb5_string_to_deltat.3 +krb5_string_to_enctype.3 +krb5_string_to_key.3 +krb5_string_to_key_data.3 +krb5_string_to_key_data_salt.3 +krb5_string_to_key_data_salt_opaque.3 +krb5_string_to_key_salt.3 +krb5_string_to_key_salt_opaque.3 +krb5_ticket.3 +krb5_ticket_get_authorization_data_type.3 +krb5_ticket_get_client.3 +krb5_ticket_get_server.3 +krb5_timeofday.3 +krb5_unparse_name.3 +krb5_unparse_name_fixed.3 +krb5_unparse_name_fixed_short.3 +krb5_unparse_name_short.3 +krb5_us_timeofday.3 +krb5_vabort.3 +krb5_vabortx.3 +krb5_verify_checksum.3 +krb5_verify_init_creds.3 +krb5_verify_init_creds_opt_init.3 +krb5_verify_init_creds_opt_set_ap_req_nofail.3 +krb5_verify_opt_init.3 +krb5_verify_opt_set_ccache.3 +krb5_verify_opt_set_flags.3 +krb5_verify_opt_set_keytab.3 +krb5_verify_opt_set_secure.3 +krb5_verify_opt_set_service.3 +krb5_verify_user.3 +krb5_verify_user_lrealm.3 +krb5_verify_user_opt.3 +krb5_verr.3 +krb5_verrx.3 +krb5_vlog.3 +krb5_vlog_msg.3 +krb5_vset_error_string.3 +krb5_vwarn.3 +krb5_vwarnx.3 +krb5_warn.3 +krb5_warnx.3 +.ta +.Fi +.Sh SEE ALSO +.Xr krb5.conf 5 , +.Xr kerberos 8 diff --git a/lib/krb5/krb5.conf.5 b/lib/krb5/krb5.conf.5 new file mode 100644 index 0000000..ceb16a4 --- /dev/null +++ b/lib/krb5/krb5.conf.5 @@ -0,0 +1,530 @@ +.\" Copyright (c) 1999 - 2005 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5.conf.5 15514 2005-06-23 18:43:34Z lha $ +.\" +.Dd May 4, 2005 +.Dt KRB5.CONF 5 +.Os HEIMDAL +.Sh NAME +.Nm krb5.conf +.Nd configuration file for Kerberos 5 +.Sh SYNOPSIS +.In krb5.h +.Sh DESCRIPTION +The +.Nm +file specifies several configuration parameters for the Kerberos 5 +library, as well as for some programs. +.Pp +The file consists of one or more sections, containing a number of +bindings. +The value of each binding can be either a string or a list of other +bindings. +The grammar looks like: +.Bd -literal -offset indent +file: + /* empty */ + sections + +sections: + section sections + section + +section: + '[' section_name ']' bindings + +section_name: + STRING + +bindings: + binding bindings + binding + +binding: + name '=' STRING + name '=' '{' bindings '}' + +name: + STRING + +.Ed +.Li STRINGs +consists of one or more non-whitespace characters. +.Pp +STRINGs that are specified later in this man-page uses the following +notation. +.Bl -tag -width "xxx" -offset indent +.It boolean +values can be either yes/true or no/false. +.It time +values can be a list of year, month, day, hour, min, second. +Example: 1 month 2 days 30 min. +If no unit is given, seconds is assumed. +.It etypes +valid encryption types are: des-cbc-crc, des-cbc-md4, des-cbc-md5, +des3-cbc-sha1, arcfour-hmac-md5, aes128-cts-hmac-sha1-96, and +aes256-cts-hmac-sha1-96 . +.It address +an address can be either a IPv4 or a IPv6 address. +.El +.Pp +Currently recognised sections and bindings are: +.Bl -tag -width "xxx" -offset indent +.It Li [appdefaults] +Specifies the default values to be used for Kerberos applications. +You can specify defaults per application, realm, or a combination of +these. +The preference order is: +.Bl -enum -compact +.It +.Va application Va realm Va option +.It +.Va application Va option +.It +.Va realm Va option +.It +.Va option +.El +.Pp +The supported options are: +.Bl -tag -width "xxx" -offset indent +.It Li forwardable = Va boolean +When obtaining initial credentials, make the credentials forwardable. +.It Li proxiable = Va boolean +When obtaining initial credentials, make the credentials proxiable. +.It Li no-addresses = Va boolean +When obtaining initial credentials, request them for an empty set of +addresses, making the tickets valid from any address. +.It Li ticket_lifetime = Va time +Default ticket lifetime. +.It Li renew_lifetime = Va time +Default renewable ticket lifetime. +.It Li encrypt = Va boolean +Use encryption, when available. +.It Li forward = Va boolean +Forward credentials to remote host (for +.Xr rsh 1 , +.Xr telnet 1 , +etc). +.El +.It Li [libdefaults] +.Bl -tag -width "xxx" -offset indent +.It Li default_realm = Va REALM +Default realm to use, this is also known as your +.Dq local realm . +The default is the result of +.Fn krb5_get_host_realm "local hostname" . +.It Li clockskew = Va time +Maximum time differential (in seconds) allowed when comparing +times. +Default is 300 seconds (five minutes). +.It Li kdc_timeout = Va time +Maximum time to wait for a reply from the kdc, default is 3 seconds. +.It Li v4_name_convert +.It Li v4_instance_resolve +These are described in the +.Xr krb5_425_conv_principal 3 +manual page. +.It Li capath = { +.Bl -tag -width "xxx" -offset indent +.It Va destination-realm Li = Va next-hop-realm +.It ... +.It Li } +.El +This is deprecated, see the +.Li capaths +section below. +.It Li default_cc_name = Va ccname +the default credentials cache name. +The string can contain variables that are expanded on runtime. +Only support variable now is +.Li %{uid} +that expands to the current user id. +.It Li default_etypes = Va etypes ... +A list of default encryption types to use. +.It Li default_etypes_des = Va etypes ... +A list of default encryption types to use when requesting a DES credential. +.It Li default_keytab_name = Va keytab +The keytab to use if no other is specified, default is +.Dq FILE:/etc/krb5.keytab . +.It Li dns_lookup_kdc = Va boolean +Use DNS SRV records to lookup KDC services location. +.It Li dns_lookup_realm = Va boolean +Use DNS TXT records to lookup domain to realm mappings. +.It Li kdc_timesync = Va boolean +Try to keep track of the time differential between the local machine +and the KDC, and then compensate for that when issuing requests. +.It Li max_retries = Va number +The max number of times to try to contact each KDC. +.It Li large_msg_size = Va number +The threshold where protocols with tiny maximum message sizes are not +considered usable to send messages to the KDC. +.It Li ticket_lifetime = Va time +Default ticket lifetime. +.It Li renew_lifetime = Va time +Default renewable ticket lifetime. +.It Li forwardable = Va boolean +When obtaining initial credentials, make the credentials forwardable. +This option is also valid in the [realms] section. +.It Li proxiable = Va boolean +When obtaining initial credentials, make the credentials proxiable. +This option is also valid in the [realms] section. +.It Li verify_ap_req_nofail = Va boolean +If enabled, failure to verify credentials against a local key is a +fatal error. +The application has to be able to read the corresponding service key +for this to work. +Some applications, like +.Xr su 1 , +enable this option unconditionally. +.It Li warn_pwexpire = Va time +How soon to warn for expiring password. +Default is seven days. +.It Li http_proxy = Va proxy-spec +A HTTP-proxy to use when talking to the KDC via HTTP. +.It Li dns_proxy = Va proxy-spec +Enable using DNS via HTTP. +.It Li extra_addresses = Va address ... +A list of addresses to get tickets for along with all local addresses. +.It Li time_format = Va string +How to print time strings in logs, this string is passed to +.Xr strftime 3 . +.It Li date_format = Va string +How to print date strings in logs, this string is passed to +.Xr strftime 3 . +.It Li log_utc = Va boolean +Write log-entries using UTC instead of your local time zone. +.It Li scan_interfaces = Va boolean +Scan all network interfaces for addresses, as opposed to simply using +the address associated with the system's host name. +.It Li fcache_version = Va int +Use file credential cache format version specified. +.It Li krb4_get_tickets = Va boolean +Also get Kerberos 4 tickets in +.Nm kinit , +.Nm login , +and other programs. +This option is also valid in the [realms] section. +.It Li fcc-mit-ticketflags = Va boolean +Use MIT compatible format for file credential cache. +It's the field ticketflags that is stored in reverse bit order for +older than Heimdal 0.7. +Setting this flag to +.Dv TRUE +make it store the MIT way, this is default for Heimdal 0.7. +.El +.It Li [domain_realm] +This is a list of mappings from DNS domain to Kerberos realm. +Each binding in this section looks like: +.Pp +.Dl domain = realm +.Pp +The domain can be either a full name of a host or a trailing +component, in the latter case the domain-string should start with a +period. +The trailing component only matches hosts that are in the same domain, ie +.Dq .example.com +matches +.Dq foo.example.com , +but not +.Dq foo.test.example.com . +.Pp +The realm may be the token `dns_locate', in which case the actual +realm will be determined using DNS (independently of the setting +of the `dns_lookup_realm' option). +.It Li [realms] +.Bl -tag -width "xxx" -offset indent +.It Va REALM Li = { +.Bl -tag -width "xxx" -offset indent +.It Li kdc = Va [service/]host[:port] +Specifies a list of kdcs for this realm. +If the optional +.Va port +is absent, the +default value for the +.Dq kerberos/udp +.Dq kerberos/tcp , +and +.Dq http/tcp +port (depending on service) will be used. +The kdcs will be used in the order that they are specified. +.Pp +The optional +.Va service +specifies over what medium the kdc should be +contacted. +Possible services are +.Dq udp , +.Dq tcp , +and +.Dq http . +Http can also be written as +.Dq http:// . +Default service is +.Dq udp +and +.Dq tcp . +.It Li admin_server = Va host[:port] +Specifies the admin server for this realm, where all the modifications +to the database are performed. +.It Li kpasswd_server = Va host[:port] +Points to the server where all the password changes are performed. +If there is no such entry, the kpasswd port on the admin_server host +will be tried. +.It Li krb524_server = Va host[:port] +Points to the server that does 524 conversions. +If it is not mentioned, the krb524 port on the kdcs will be tried. +.It Li v4_instance_convert +.It Li v4_name_convert +.It Li default_domain +See +.Xr krb5_425_conv_principal 3 . +.It Li tgs_require_subkey +a boolan variable that defaults to false. +Old DCE secd (pre 1.1) might need this to be true. +.El +.It Li } +.El +.It Li [capaths] +.Bl -tag -width "xxx" -offset indent +.It Va client-realm Li = { +.Bl -tag -width "xxx" -offset indent +.It Va server-realm Li = Va hop-realm ... +This serves two purposes. First the first listed +.Va hop-realm +tells a client which realm it should contact in order to ultimately +obtain credentials for a service in the +.Va server-realm . +Secondly, it tells the KDC (and other servers) which realms are +allowed in a multi-hop traversal from +.Va client-realm +to +.Va server-realm . +Except for the client case, the order of the realms are not important. +.El +.It Va } +.El +.It Li [logging] +.Bl -tag -width "xxx" -offset indent +.It Va entity Li = Va destination +Specifies that +.Va entity +should use the specified +.Li destination +for logging. +See the +.Xr krb5_openlog 3 +manual page for a list of defined destinations. +.El +.It Li [kdc] +.Bl -tag -width "xxx" -offset indent +.It Li database Li = { +.Bl -tag -width "xxx" -offset indent +.It Li dbname Li = Va DATABASENAME +Use this database for this realm. +See the info documetation how to configure diffrent database backends. +.It Li realm Li = Va REALM +Specifies the realm that will be stored in this database. +It realm isn't set, it will used as the default database, there can +only be one entry that doesn't have a +.Li realm +stanza. +.It Li mkey_file Li = Pa FILENAME +Use this keytab file for the master key of this database. +If not specified +.Va DATABASENAME Ns .mkey +will be used. +.It Li acl_file Li = PA FILENAME +Use this file for the ACL list of this database. +.It Li log_file Li = Pa FILENAME +Use this file as the log of changes performed to the database. +This file is used by +.Nm ipropd-master +for propagating changes to slaves. +.El +.It Li } +.It Li max-request = Va SIZE +Maximum size of a kdc request. +.It Li require-preauth = Va BOOL +If set pre-authentication is required. +Since krb4 requests are not pre-authenticated they will be rejected. +.It Li ports = Va "list of ports" +List of ports the kdc should listen to. +.It Li addresses = Va "list of interfaces" +List of addresses the kdc should bind to. +.It Li enable-kerberos4 = Va BOOL +Turn on Kerberos 4 support. +.It Li v4-realm = Va REALM +To what realm v4 requests should be mapped. +.It Li enable-524 = Va BOOL +Should the Kerberos 524 converting facility be turned on. +Default is the same as +.Va enable-kerberos4 . +.It Li enable-http = Va BOOL +Should the kdc answer kdc-requests over http. +.It Li enable-kaserver = Va BOOL +If this kdc should emulate the AFS kaserver. +.It Li check-ticket-addresses = Va BOOL +Verify the addresses in the tickets used in tgs requests. +.\" XXX +.It Li allow-null-ticket-addresses = Va BOOL +Allow address-less tickets. +.\" XXX +.It Li allow-anonymous = Va BOOL +If the kdc is allowed to hand out anonymous tickets. +.It Li encode_as_rep_as_tgs_rep = Va BOOL +Encode as-rep as tgs-rep tobe compatible with mistakes older DCE secd did. +.\" XXX +.It Li kdc_warn_pwexpire = Va TIME +The time before expiration that the user should be warned that her +password is about to expire. +.It Li logging = Va Logging +What type of logging the kdc should use, see also [logging]/kdc. +.It Li use_2b = { +.Bl -tag -width "xxx" -offset indent +.It Va principal Li = Va BOOL +boolean value if the 524 daemon should return AFS 2b tokens for +.Fa principal . +.It ... +.El +.It Li } +.It Li hdb-ldap-structural-object Va structural object +If the LDAP backend is used for storing principals, this is the +structural object that will be used when creating and when reading +objects. +The default value is account . +.It Li hdb-ldap-create-base Va creation dn +is the dn that will be appended to the principal when creating entries. +Default value is the search dn. +.El +.It Li [kadmin] +.Bl -tag -width "xxx" -offset indent +.It Li require-preauth = Va BOOL +If pre-authentication is required to talk to the kadmin server. +.It Li password_lifetime = Va time +If a principal already have its password set for expiration, this is +the time it will be valid for after a change. +.It Li default_keys = Va keytypes... +For each entry in +.Va default_keys +try to parse it as a sequence of +.Va etype:salttype:salt +syntax of this if something like: +.Pp +[(des|des3|etype):](pw-salt|afs3-salt)[:string] +.Pp +If +.Ar etype +is omitted it means everything, and if string is omitted it means the +default salt string (for that principal and encryption type). +Additional special values of keytypes are: +.Bl -tag -width "xxx" -offset indent +.It Li v5 +The Kerberos 5 salt +.Va pw-salt +.It Li v4 +The Kerberos 4 salt +.Va des:pw-salt: +.El +.It Li use_v4_salt = Va BOOL +When true, this is the same as +.Pp +.Va default_keys = Va des3:pw-salt Va v4 +.Pp +and is only left for backwards compatibility. +.El +.It Li [password-quality] +Check the Password quality assurance in the info documentation for +more information. +.Bl -tag -width "xxx" -offset indent +.It Li check_library = Va library-name +Library name that contains the password check_function +.It Li check_function = Va function-name +Function name for checking passwords in check_library +.It Li policy_libraries = Va library1 ... libraryN +List of libraries that can do password policy checks +.It Li policies = Va policy1 ... policyN +List of policy names to apply to the password. Builtin policies are +among other minimum-length, character-class, external-check. +.El +.El +.Sh ENVIRONMENT +.Ev KRB5_CONFIG +points to the configuration file to read. +.Sh FILES +.Bl -tag -width "/etc/krb5.conf" +.It Pa /etc/krb5.conf +configuration file for Kerberos 5. +.El +.Sh EXAMPLES +.Bd -literal -offset indent +[libdefaults] + default_realm = FOO.SE +[domain_realm] + .foo.se = FOO.SE + .bar.se = FOO.SE +[realms] + FOO.SE = { + kdc = kerberos.foo.se + v4_name_convert = { + rcmd = host + } + v4_instance_convert = { + xyz = xyz.bar.se + } + default_domain = foo.se + } +[logging] + kdc = FILE:/var/heimdal/kdc.log + kdc = SYSLOG:INFO + default = SYSLOG:INFO:USER +.Ed +.Sh DIAGNOSTICS +Since +.Nm +is read and parsed by the krb5 library, there is not a lot of +opportunities for programs to report parsing errors in any useful +format. +To help overcome this problem, there is a program +.Nm verify_krb5_conf +that reads +.Nm +and tries to emit useful diagnostics from parsing errors. +Note that this program does not have any way of knowing what options +are actually used and thus cannot warn about unknown or misspelled +ones. +.Sh SEE ALSO +.Xr kinit 1 , +.Xr krb5_425_conv_principal 3 , +.Xr krb5_openlog 3 , +.Xr strftime 3 , +.Xr verify_krb5_conf 8 diff --git a/lib/krb5/krb5.h b/lib/krb5/krb5.h new file mode 100644 index 0000000..571eb61 --- /dev/null +++ b/lib/krb5/krb5.h @@ -0,0 +1,780 @@ +/* + * Copyright (c) 1997 - 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $Id: krb5.h 22100 2007-12-03 17:15:00Z lha $ */ + +#ifndef __KRB5_H__ +#define __KRB5_H__ + +#include <time.h> +#include <krb5-types.h> + +#include <asn1_err.h> +#include <krb5_err.h> +#include <heim_err.h> +#include <k524_err.h> + +#include <krb5_asn1.h> + +/* name confusion with MIT */ +#ifndef KRB5KDC_ERR_KEY_EXP +#define KRB5KDC_ERR_KEY_EXP KRB5KDC_ERR_KEY_EXPIRED +#endif + +/* simple constants */ + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +typedef int krb5_boolean; + +typedef int32_t krb5_error_code; + +typedef int krb5_kvno; + +typedef uint32_t krb5_flags; + +typedef void *krb5_pointer; +typedef const void *krb5_const_pointer; + +struct krb5_crypto_data; +typedef struct krb5_crypto_data *krb5_crypto; + +struct krb5_get_creds_opt_data; +typedef struct krb5_get_creds_opt_data *krb5_get_creds_opt; + +struct krb5_digest_data; +typedef struct krb5_digest_data *krb5_digest; +struct krb5_ntlm_data; +typedef struct krb5_ntlm_data *krb5_ntlm; + +struct krb5_pac_data; +typedef struct krb5_pac_data *krb5_pac; + +typedef struct krb5_rd_req_in_ctx_data *krb5_rd_req_in_ctx; +typedef struct krb5_rd_req_out_ctx_data *krb5_rd_req_out_ctx; + +typedef CKSUMTYPE krb5_cksumtype; + +typedef Checksum krb5_checksum; + +typedef ENCTYPE krb5_enctype; + +typedef heim_octet_string krb5_data; + +/* PKINIT related forward declarations */ +struct ContentInfo; +struct krb5_pk_identity; +struct krb5_pk_cert; + +/* krb5_enc_data is a mit compat structure */ +typedef struct krb5_enc_data { + krb5_enctype enctype; + krb5_kvno kvno; + krb5_data ciphertext; +} krb5_enc_data; + +/* alternative names */ +enum { + ENCTYPE_NULL = ETYPE_NULL, + ENCTYPE_DES_CBC_CRC = ETYPE_DES_CBC_CRC, + ENCTYPE_DES_CBC_MD4 = ETYPE_DES_CBC_MD4, + ENCTYPE_DES_CBC_MD5 = ETYPE_DES_CBC_MD5, + ENCTYPE_DES3_CBC_MD5 = ETYPE_DES3_CBC_MD5, + ENCTYPE_OLD_DES3_CBC_SHA1 = ETYPE_OLD_DES3_CBC_SHA1, + ENCTYPE_SIGN_DSA_GENERATE = ETYPE_SIGN_DSA_GENERATE, + ENCTYPE_ENCRYPT_RSA_PRIV = ETYPE_ENCRYPT_RSA_PRIV, + ENCTYPE_ENCRYPT_RSA_PUB = ETYPE_ENCRYPT_RSA_PUB, + ENCTYPE_DES3_CBC_SHA1 = ETYPE_DES3_CBC_SHA1, + ENCTYPE_AES128_CTS_HMAC_SHA1_96 = ETYPE_AES128_CTS_HMAC_SHA1_96, + ENCTYPE_AES256_CTS_HMAC_SHA1_96 = ETYPE_AES256_CTS_HMAC_SHA1_96, + ENCTYPE_ARCFOUR_HMAC = ETYPE_ARCFOUR_HMAC_MD5, + ENCTYPE_ARCFOUR_HMAC_MD5 = ETYPE_ARCFOUR_HMAC_MD5, + ENCTYPE_ARCFOUR_HMAC_MD5_56 = ETYPE_ARCFOUR_HMAC_MD5_56, + ENCTYPE_ENCTYPE_PK_CROSS = ETYPE_ENCTYPE_PK_CROSS, + ENCTYPE_DES_CBC_NONE = ETYPE_DES_CBC_NONE, + ENCTYPE_DES3_CBC_NONE = ETYPE_DES3_CBC_NONE, + ENCTYPE_DES_CFB64_NONE = ETYPE_DES_CFB64_NONE, + ENCTYPE_DES_PCBC_NONE = ETYPE_DES_PCBC_NONE +}; + +typedef PADATA_TYPE krb5_preauthtype; + +typedef enum krb5_key_usage { + KRB5_KU_PA_ENC_TIMESTAMP = 1, + /* AS-REQ PA-ENC-TIMESTAMP padata timestamp, encrypted with the + client key (section 5.4.1) */ + KRB5_KU_TICKET = 2, + /* AS-REP Ticket and TGS-REP Ticket (includes tgs session key or + application session key), encrypted with the service key + (section 5.4.2) */ + KRB5_KU_AS_REP_ENC_PART = 3, + /* AS-REP encrypted part (includes tgs session key or application + session key), encrypted with the client key (section 5.4.2) */ + KRB5_KU_TGS_REQ_AUTH_DAT_SESSION = 4, + /* TGS-REQ KDC-REQ-BODY AuthorizationData, encrypted with the tgs + session key (section 5.4.1) */ + KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY = 5, + /* TGS-REQ KDC-REQ-BODY AuthorizationData, encrypted with the tgs + authenticator subkey (section 5.4.1) */ + KRB5_KU_TGS_REQ_AUTH_CKSUM = 6, + /* TGS-REQ PA-TGS-REQ padata AP-REQ Authenticator cksum, keyed + with the tgs session key (sections 5.3.2, 5.4.1) */ + KRB5_KU_TGS_REQ_AUTH = 7, + /* TGS-REQ PA-TGS-REQ padata AP-REQ Authenticator (includes tgs + authenticator subkey), encrypted with the tgs session key + (section 5.3.2) */ + KRB5_KU_TGS_REP_ENC_PART_SESSION = 8, + /* TGS-REP encrypted part (includes application session key), + encrypted with the tgs session key (section 5.4.2) */ + KRB5_KU_TGS_REP_ENC_PART_SUB_KEY = 9, + /* TGS-REP encrypted part (includes application session key), + encrypted with the tgs authenticator subkey (section 5.4.2) */ + KRB5_KU_AP_REQ_AUTH_CKSUM = 10, + /* AP-REQ Authenticator cksum, keyed with the application session + key (section 5.3.2) */ + KRB5_KU_AP_REQ_AUTH = 11, + /* AP-REQ Authenticator (includes application authenticator + subkey), encrypted with the application session key (section + 5.3.2) */ + KRB5_KU_AP_REQ_ENC_PART = 12, + /* AP-REP encrypted part (includes application session subkey), + encrypted with the application session key (section 5.5.2) */ + KRB5_KU_KRB_PRIV = 13, + /* KRB-PRIV encrypted part, encrypted with a key chosen by the + application (section 5.7.1) */ + KRB5_KU_KRB_CRED = 14, + /* KRB-CRED encrypted part, encrypted with a key chosen by the + application (section 5.8.1) */ + KRB5_KU_KRB_SAFE_CKSUM = 15, + /* KRB-SAFE cksum, keyed with a key chosen by the application + (section 5.6.1) */ + KRB5_KU_OTHER_ENCRYPTED = 16, + /* Data which is defined in some specification outside of + Kerberos to be encrypted using an RFC1510 encryption type. */ + KRB5_KU_OTHER_CKSUM = 17, + /* Data which is defined in some specification outside of + Kerberos to be checksummed using an RFC1510 checksum type. */ + KRB5_KU_KRB_ERROR = 18, + /* Krb-error checksum */ + KRB5_KU_AD_KDC_ISSUED = 19, + /* AD-KDCIssued checksum */ + KRB5_KU_MANDATORY_TICKET_EXTENSION = 20, + /* Checksum for Mandatory Ticket Extensions */ + KRB5_KU_AUTH_DATA_TICKET_EXTENSION = 21, + /* Checksum in Authorization Data in Ticket Extensions */ + KRB5_KU_USAGE_SEAL = 22, + /* seal in GSSAPI krb5 mechanism */ + KRB5_KU_USAGE_SIGN = 23, + /* sign in GSSAPI krb5 mechanism */ + KRB5_KU_USAGE_SEQ = 24, + /* SEQ in GSSAPI krb5 mechanism */ + KRB5_KU_USAGE_ACCEPTOR_SEAL = 22, + /* acceptor sign in GSSAPI CFX krb5 mechanism */ + KRB5_KU_USAGE_ACCEPTOR_SIGN = 23, + /* acceptor seal in GSSAPI CFX krb5 mechanism */ + KRB5_KU_USAGE_INITIATOR_SEAL = 24, + /* initiator sign in GSSAPI CFX krb5 mechanism */ + KRB5_KU_USAGE_INITIATOR_SIGN = 25, + /* initiator seal in GSSAPI CFX krb5 mechanism */ + KRB5_KU_PA_SERVER_REFERRAL_DATA = 22, + /* encrypted server referral data */ + KRB5_KU_SAM_CHECKSUM = 25, + /* Checksum for the SAM-CHECKSUM field */ + KRB5_KU_SAM_ENC_TRACK_ID = 26, + /* Encryption of the SAM-TRACK-ID field */ + KRB5_KU_PA_SERVER_REFERRAL = 26, + /* Keyusage for the server referral in a TGS req */ + KRB5_KU_SAM_ENC_NONCE_SAD = 27, + /* Encryption of the SAM-NONCE-OR-SAD field */ + KRB5_KU_DIGEST_ENCRYPT = -18, + /* Encryption key usage used in the digest encryption field */ + KRB5_KU_DIGEST_OPAQUE = -19, + /* Checksum key usage used in the digest opaque field */ + KRB5_KU_KRB5SIGNEDPATH = -21, + /* Checksum key usage on KRB5SignedPath */ + KRB5_KU_CANONICALIZED_NAMES = -23 + /* Checksum key usage on PA-CANONICALIZED */ +} krb5_key_usage; + +typedef krb5_key_usage krb5_keyusage; + +typedef enum krb5_salttype { + KRB5_PW_SALT = KRB5_PADATA_PW_SALT, + KRB5_AFS3_SALT = KRB5_PADATA_AFS3_SALT +}krb5_salttype; + +typedef struct krb5_salt { + krb5_salttype salttype; + krb5_data saltvalue; +} krb5_salt; + +typedef ETYPE_INFO krb5_preauthinfo; + +typedef struct { + krb5_preauthtype type; + krb5_preauthinfo info; /* list of preauthinfo for this type */ +} krb5_preauthdata_entry; + +typedef struct krb5_preauthdata { + unsigned len; + krb5_preauthdata_entry *val; +}krb5_preauthdata; + +typedef enum krb5_address_type { + KRB5_ADDRESS_INET = 2, + KRB5_ADDRESS_NETBIOS = 20, + KRB5_ADDRESS_INET6 = 24, + KRB5_ADDRESS_ADDRPORT = 256, + KRB5_ADDRESS_IPPORT = 257 +} krb5_address_type; + +enum { + AP_OPTS_USE_SESSION_KEY = 1, + AP_OPTS_MUTUAL_REQUIRED = 2, + AP_OPTS_USE_SUBKEY = 4 /* library internal */ +}; + +typedef HostAddress krb5_address; + +typedef HostAddresses krb5_addresses; + +typedef enum krb5_keytype { + KEYTYPE_NULL = 0, + KEYTYPE_DES = 1, + KEYTYPE_DES3 = 7, + KEYTYPE_AES128 = 17, + KEYTYPE_AES256 = 18, + KEYTYPE_ARCFOUR = 23, + KEYTYPE_ARCFOUR_56 = 24 +} krb5_keytype; + +typedef EncryptionKey krb5_keyblock; + +typedef AP_REQ krb5_ap_req; + +struct krb5_cc_ops; + +#define KRB5_DEFAULT_CCFILE_ROOT "/tmp/krb5cc_" + +#define KRB5_DEFAULT_CCROOT "FILE:" KRB5_DEFAULT_CCFILE_ROOT + +#define KRB5_ACCEPT_NULL_ADDRESSES(C) \ + krb5_config_get_bool_default((C), NULL, TRUE, \ + "libdefaults", "accept_null_addresses", \ + NULL) + +typedef void *krb5_cc_cursor; + +typedef struct krb5_ccache_data { + const struct krb5_cc_ops *ops; + krb5_data data; +}krb5_ccache_data; + +typedef struct krb5_ccache_data *krb5_ccache; + +typedef struct krb5_context_data *krb5_context; + +typedef Realm krb5_realm; +typedef const char *krb5_const_realm; /* stupid language */ + +#define krb5_realm_length(r) strlen(r) +#define krb5_realm_data(r) (r) + +typedef Principal krb5_principal_data; +typedef struct Principal *krb5_principal; +typedef const struct Principal *krb5_const_principal; + +typedef time_t krb5_deltat; +typedef time_t krb5_timestamp; + +typedef struct krb5_times { + krb5_timestamp authtime; + krb5_timestamp starttime; + krb5_timestamp endtime; + krb5_timestamp renew_till; +} krb5_times; + +typedef union { + TicketFlags b; + krb5_flags i; +} krb5_ticket_flags; + +/* options for krb5_get_in_tkt() */ +#define KDC_OPT_FORWARDABLE (1 << 1) +#define KDC_OPT_FORWARDED (1 << 2) +#define KDC_OPT_PROXIABLE (1 << 3) +#define KDC_OPT_PROXY (1 << 4) +#define KDC_OPT_ALLOW_POSTDATE (1 << 5) +#define KDC_OPT_POSTDATED (1 << 6) +#define KDC_OPT_RENEWABLE (1 << 8) +#define KDC_OPT_REQUEST_ANONYMOUS (1 << 14) +#define KDC_OPT_DISABLE_TRANSITED_CHECK (1 << 26) +#define KDC_OPT_RENEWABLE_OK (1 << 27) +#define KDC_OPT_ENC_TKT_IN_SKEY (1 << 28) +#define KDC_OPT_RENEW (1 << 30) +#define KDC_OPT_VALIDATE (1 << 31) + +typedef union { + KDCOptions b; + krb5_flags i; +} krb5_kdc_flags; + +/* flags for krb5_verify_ap_req */ + +#define KRB5_VERIFY_AP_REQ_IGNORE_INVALID (1 << 0) + +#define KRB5_GC_CACHED (1U << 0) +#define KRB5_GC_USER_USER (1U << 1) +#define KRB5_GC_EXPIRED_OK (1U << 2) +#define KRB5_GC_NO_STORE (1U << 3) +#define KRB5_GC_FORWARDABLE (1U << 4) +#define KRB5_GC_NO_TRANSIT_CHECK (1U << 5) +#define KRB5_GC_CONSTRAINED_DELEGATION (1U << 6) + +/* constants for compare_creds (and cc_retrieve_cred) */ +#define KRB5_TC_DONT_MATCH_REALM (1U << 31) +#define KRB5_TC_MATCH_KEYTYPE (1U << 30) +#define KRB5_TC_MATCH_KTYPE KRB5_TC_MATCH_KEYTYPE /* MIT name */ +#define KRB5_TC_MATCH_SRV_NAMEONLY (1 << 29) +#define KRB5_TC_MATCH_FLAGS_EXACT (1 << 28) +#define KRB5_TC_MATCH_FLAGS (1 << 27) +#define KRB5_TC_MATCH_TIMES_EXACT (1 << 26) +#define KRB5_TC_MATCH_TIMES (1 << 25) +#define KRB5_TC_MATCH_AUTHDATA (1 << 24) +#define KRB5_TC_MATCH_2ND_TKT (1 << 23) +#define KRB5_TC_MATCH_IS_SKEY (1 << 22) + +typedef AuthorizationData krb5_authdata; + +typedef KRB_ERROR krb5_error; + +typedef struct krb5_creds { + krb5_principal client; + krb5_principal server; + krb5_keyblock session; + krb5_times times; + krb5_data ticket; + krb5_data second_ticket; + krb5_authdata authdata; + krb5_addresses addresses; + krb5_ticket_flags flags; +} krb5_creds; + +typedef struct krb5_cc_cache_cursor_data *krb5_cc_cache_cursor; + +typedef struct krb5_cc_ops { + const char *prefix; + const char* (*get_name)(krb5_context, krb5_ccache); + krb5_error_code (*resolve)(krb5_context, krb5_ccache *, const char *); + krb5_error_code (*gen_new)(krb5_context, krb5_ccache *); + krb5_error_code (*init)(krb5_context, krb5_ccache, krb5_principal); + krb5_error_code (*destroy)(krb5_context, krb5_ccache); + krb5_error_code (*close)(krb5_context, krb5_ccache); + krb5_error_code (*store)(krb5_context, krb5_ccache, krb5_creds*); + krb5_error_code (*retrieve)(krb5_context, krb5_ccache, + krb5_flags, const krb5_creds*, krb5_creds *); + krb5_error_code (*get_princ)(krb5_context, krb5_ccache, krb5_principal*); + krb5_error_code (*get_first)(krb5_context, krb5_ccache, krb5_cc_cursor *); + krb5_error_code (*get_next)(krb5_context, krb5_ccache, + krb5_cc_cursor*, krb5_creds*); + krb5_error_code (*end_get)(krb5_context, krb5_ccache, krb5_cc_cursor*); + krb5_error_code (*remove_cred)(krb5_context, krb5_ccache, + krb5_flags, krb5_creds*); + krb5_error_code (*set_flags)(krb5_context, krb5_ccache, krb5_flags); + int (*get_version)(krb5_context, krb5_ccache); + krb5_error_code (*get_cache_first)(krb5_context, krb5_cc_cursor *); + krb5_error_code (*get_cache_next)(krb5_context, krb5_cc_cursor, krb5_ccache *); + krb5_error_code (*end_cache_get)(krb5_context, krb5_cc_cursor); + krb5_error_code (*move)(krb5_context, krb5_ccache, krb5_ccache); + krb5_error_code (*default_name)(krb5_context, char **); +} krb5_cc_ops; + +struct krb5_log_facility; + +struct krb5_config_binding { + enum { krb5_config_string, krb5_config_list } type; + char *name; + struct krb5_config_binding *next; + union { + char *string; + struct krb5_config_binding *list; + void *generic; + } u; +}; + +typedef struct krb5_config_binding krb5_config_binding; + +typedef krb5_config_binding krb5_config_section; + +typedef struct krb5_ticket { + EncTicketPart ticket; + krb5_principal client; + krb5_principal server; +} krb5_ticket; + +typedef Authenticator krb5_authenticator_data; + +typedef krb5_authenticator_data *krb5_authenticator; + +struct krb5_rcache_data; +typedef struct krb5_rcache_data *krb5_rcache; +typedef Authenticator krb5_donot_replay; + +#define KRB5_STORAGE_HOST_BYTEORDER 0x01 /* old */ +#define KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS 0x02 +#define KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE 0x04 +#define KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE 0x08 +#define KRB5_STORAGE_BYTEORDER_MASK 0x60 +#define KRB5_STORAGE_BYTEORDER_BE 0x00 /* default */ +#define KRB5_STORAGE_BYTEORDER_LE 0x20 +#define KRB5_STORAGE_BYTEORDER_HOST 0x40 +#define KRB5_STORAGE_CREDS_FLAGS_WRONG_BITORDER 0x80 + +struct krb5_storage_data; +typedef struct krb5_storage_data krb5_storage; + +typedef struct krb5_keytab_entry { + krb5_principal principal; + krb5_kvno vno; + krb5_keyblock keyblock; + uint32_t timestamp; +} krb5_keytab_entry; + +typedef struct krb5_kt_cursor { + int fd; + krb5_storage *sp; + void *data; +} krb5_kt_cursor; + +struct krb5_keytab_data; + +typedef struct krb5_keytab_data *krb5_keytab; + +#define KRB5_KT_PREFIX_MAX_LEN 30 + +struct krb5_keytab_data { + const char *prefix; + krb5_error_code (*resolve)(krb5_context, const char*, krb5_keytab); + krb5_error_code (*get_name)(krb5_context, krb5_keytab, char*, size_t); + krb5_error_code (*close)(krb5_context, krb5_keytab); + krb5_error_code (*get)(krb5_context, krb5_keytab, krb5_const_principal, + krb5_kvno, krb5_enctype, krb5_keytab_entry*); + krb5_error_code (*start_seq_get)(krb5_context, krb5_keytab, krb5_kt_cursor*); + krb5_error_code (*next_entry)(krb5_context, krb5_keytab, + krb5_keytab_entry*, krb5_kt_cursor*); + krb5_error_code (*end_seq_get)(krb5_context, krb5_keytab, krb5_kt_cursor*); + krb5_error_code (*add)(krb5_context, krb5_keytab, krb5_keytab_entry*); + krb5_error_code (*remove)(krb5_context, krb5_keytab, krb5_keytab_entry*); + void *data; + int32_t version; +}; + +typedef struct krb5_keytab_data krb5_kt_ops; + +struct krb5_keytab_key_proc_args { + krb5_keytab keytab; + krb5_principal principal; +}; + +typedef struct krb5_keytab_key_proc_args krb5_keytab_key_proc_args; + +typedef struct krb5_replay_data { + krb5_timestamp timestamp; + int32_t usec; + uint32_t seq; +} krb5_replay_data; + +/* flags for krb5_auth_con_setflags */ +enum { + KRB5_AUTH_CONTEXT_DO_TIME = 1, + KRB5_AUTH_CONTEXT_RET_TIME = 2, + KRB5_AUTH_CONTEXT_DO_SEQUENCE = 4, + KRB5_AUTH_CONTEXT_RET_SEQUENCE = 8, + KRB5_AUTH_CONTEXT_PERMIT_ALL = 16, + KRB5_AUTH_CONTEXT_USE_SUBKEY = 32, + KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED = 64 +}; + +/* flags for krb5_auth_con_genaddrs */ +enum { + KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR = 1, + KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR = 3, + KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR = 4, + KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR = 12 +}; + +typedef struct krb5_auth_context_data { + unsigned int flags; + + krb5_address *local_address; + krb5_address *remote_address; + int16_t local_port; + int16_t remote_port; + krb5_keyblock *keyblock; + krb5_keyblock *local_subkey; + krb5_keyblock *remote_subkey; + + uint32_t local_seqnumber; + uint32_t remote_seqnumber; + + krb5_authenticator authenticator; + + krb5_pointer i_vector; + + krb5_rcache rcache; + + krb5_keytype keytype; /* ¿requested key type ? */ + krb5_cksumtype cksumtype; /* ¡requested checksum type! */ + +}krb5_auth_context_data, *krb5_auth_context; + +typedef struct { + KDC_REP kdc_rep; + EncKDCRepPart enc_part; + KRB_ERROR error; +} krb5_kdc_rep; + +extern const char *heimdal_version, *heimdal_long_version; + +typedef void (*krb5_log_log_func_t)(const char*, const char*, void*); +typedef void (*krb5_log_close_func_t)(void*); + +typedef struct krb5_log_facility { + char *program; + int len; + struct facility *val; +} krb5_log_facility; + +typedef EncAPRepPart krb5_ap_rep_enc_part; + +#define KRB5_RECVAUTH_IGNORE_VERSION 1 + +#define KRB5_SENDAUTH_VERSION "KRB5_SENDAUTH_V1.0" + +#define KRB5_TGS_NAME_SIZE (6) +#define KRB5_TGS_NAME ("krbtgt") + +#define KRB5_DIGEST_NAME ("digest") + +/* variables */ + +extern const char *krb5_config_file; +extern const char *krb5_defkeyname; + +typedef enum { + KRB5_PROMPT_TYPE_PASSWORD = 0x1, + KRB5_PROMPT_TYPE_NEW_PASSWORD = 0x2, + KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN = 0x3, + KRB5_PROMPT_TYPE_PREAUTH = 0x4, + KRB5_PROMPT_TYPE_INFO = 0x5 +} krb5_prompt_type; + +typedef struct _krb5_prompt { + const char *prompt; + int hidden; + krb5_data *reply; + krb5_prompt_type type; +} krb5_prompt; + +typedef int (*krb5_prompter_fct)(krb5_context /*context*/, + void * /*data*/, + const char * /*name*/, + const char * /*banner*/, + int /*num_prompts*/, + krb5_prompt /*prompts*/[]); +typedef krb5_error_code (*krb5_key_proc)(krb5_context /*context*/, + krb5_enctype /*type*/, + krb5_salt /*salt*/, + krb5_const_pointer /*keyseed*/, + krb5_keyblock ** /*key*/); +typedef krb5_error_code (*krb5_decrypt_proc)(krb5_context /*context*/, + krb5_keyblock * /*key*/, + krb5_key_usage /*usage*/, + krb5_const_pointer /*decrypt_arg*/, + krb5_kdc_rep * /*dec_rep*/); +typedef krb5_error_code (*krb5_s2k_proc)(krb5_context /*context*/, + krb5_enctype /*type*/, + krb5_const_pointer /*keyseed*/, + krb5_salt /*salt*/, + krb5_data * /*s2kparms*/, + krb5_keyblock ** /*key*/); + +struct _krb5_get_init_creds_opt_private; + +typedef struct _krb5_get_init_creds_opt { + krb5_flags flags; + krb5_deltat tkt_life; + krb5_deltat renew_life; + int forwardable; + int proxiable; + int anonymous; + krb5_enctype *etype_list; + int etype_list_length; + krb5_addresses *address_list; + /* XXX the next three should not be used, as they may be + removed later */ + krb5_preauthtype *preauth_list; + int preauth_list_length; + krb5_data *salt; + struct _krb5_get_init_creds_opt_private *opt_private; +} krb5_get_init_creds_opt; + +#define KRB5_GET_INIT_CREDS_OPT_TKT_LIFE 0x0001 +#define KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE 0x0002 +#define KRB5_GET_INIT_CREDS_OPT_FORWARDABLE 0x0004 +#define KRB5_GET_INIT_CREDS_OPT_PROXIABLE 0x0008 +#define KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST 0x0010 +#define KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST 0x0020 +#define KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST 0x0040 +#define KRB5_GET_INIT_CREDS_OPT_SALT 0x0080 +#define KRB5_GET_INIT_CREDS_OPT_ANONYMOUS 0x0100 +#define KRB5_GET_INIT_CREDS_OPT_DISABLE_TRANSITED_CHECK 0x0200 + +typedef struct _krb5_verify_init_creds_opt { + krb5_flags flags; + int ap_req_nofail; +} krb5_verify_init_creds_opt; + +#define KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL 0x0001 + +typedef struct krb5_verify_opt { + unsigned int flags; + krb5_ccache ccache; + krb5_keytab keytab; + krb5_boolean secure; + const char *service; +} krb5_verify_opt; + +#define KRB5_VERIFY_LREALMS 1 +#define KRB5_VERIFY_NO_ADDRESSES 2 + +extern const krb5_cc_ops krb5_acc_ops; +extern const krb5_cc_ops krb5_fcc_ops; +extern const krb5_cc_ops krb5_mcc_ops; +extern const krb5_cc_ops krb5_kcm_ops; + +extern const krb5_kt_ops krb5_fkt_ops; +extern const krb5_kt_ops krb5_wrfkt_ops; +extern const krb5_kt_ops krb5_javakt_ops; +extern const krb5_kt_ops krb5_mkt_ops; +extern const krb5_kt_ops krb5_akf_ops; +extern const krb5_kt_ops krb4_fkt_ops; +extern const krb5_kt_ops krb5_srvtab_fkt_ops; +extern const krb5_kt_ops krb5_any_ops; + +#define KRB5_KPASSWD_VERS_CHANGEPW 1 +#define KRB5_KPASSWD_VERS_SETPW 0xff80 + +#define KRB5_KPASSWD_SUCCESS 0 +#define KRB5_KPASSWD_MALFORMED 1 +#define KRB5_KPASSWD_HARDERROR 2 +#define KRB5_KPASSWD_AUTHERROR 3 +#define KRB5_KPASSWD_SOFTERROR 4 +#define KRB5_KPASSWD_ACCESSDENIED 5 +#define KRB5_KPASSWD_BAD_VERSION 6 +#define KRB5_KPASSWD_INITIAL_FLAG_NEEDED 7 + +#define KPASSWD_PORT 464 + +/* types for the new krbhst interface */ +struct krb5_krbhst_data; +typedef struct krb5_krbhst_data *krb5_krbhst_handle; + +#define KRB5_KRBHST_KDC 1 +#define KRB5_KRBHST_ADMIN 2 +#define KRB5_KRBHST_CHANGEPW 3 +#define KRB5_KRBHST_KRB524 4 +#define KRB5_KRBHST_KCA 5 + +typedef struct krb5_krbhst_info { + enum { KRB5_KRBHST_UDP, + KRB5_KRBHST_TCP, + KRB5_KRBHST_HTTP } proto; + unsigned short port; + unsigned short def_port; + struct addrinfo *ai; + struct krb5_krbhst_info *next; + char hostname[1]; /* has to come last */ +} krb5_krbhst_info; + +/* flags for krb5_krbhst_init_flags (and krb5_send_to_kdc_flags) */ +enum { + KRB5_KRBHST_FLAGS_MASTER = 1, + KRB5_KRBHST_FLAGS_LARGE_MSG = 2 +}; + +typedef krb5_error_code (*krb5_send_to_kdc_func)(krb5_context, + void *, + krb5_krbhst_info *, + const krb5_data *, + krb5_data *); + +/* flags for krb5_parse_name_flags */ +enum { + KRB5_PRINCIPAL_PARSE_NO_REALM = 1, + KRB5_PRINCIPAL_PARSE_MUST_REALM = 2, + KRB5_PRINCIPAL_PARSE_ENTERPRISE = 4 +}; + +/* flags for krb5_unparse_name_flags */ +enum { + KRB5_PRINCIPAL_UNPARSE_SHORT = 1, + KRB5_PRINCIPAL_UNPARSE_NO_REALM = 2, + KRB5_PRINCIPAL_UNPARSE_DISPLAY = 4 +}; + +typedef struct krb5_sendto_ctx_data *krb5_sendto_ctx; + +#define KRB5_SENDTO_DONE 0 +#define KRB5_SENDTO_RESTART 1 +#define KRB5_SENDTO_CONTINUE 2 + +typedef krb5_error_code (*krb5_sendto_ctx_func)(krb5_context, krb5_sendto_ctx, void *, const krb5_data *, int *); + +struct krb5_plugin; +enum krb5_plugin_type { + PLUGIN_TYPE_DATA = 1, + PLUGIN_TYPE_FUNC +}; + +struct credentials; /* this is to keep the compiler happy */ +struct getargs; +struct sockaddr; + +#include <krb5-protos.h> + +#endif /* __KRB5_H__ */ + diff --git a/lib/krb5/krb5.moduli b/lib/krb5/krb5.moduli new file mode 100644 index 0000000..f67d2b2 --- /dev/null +++ b/lib/krb5/krb5.moduli @@ -0,0 +1,3 @@ +# $Id: krb5.moduli 16154 2005-10-08 15:39:42Z lha $ +# comment security-bits-decimal secure-prime(p)-hex generator(g)-hex (q)-hex +rfc3526-MODP-group14 1760 FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF 02 7FFFFFFFFFFFFFFFE487ED5110B4611A62633145C06E0E68948127044533E63A0105DF531D89CD9128A5043CC71A026EF7CA8CD9E69D218D98158536F92F8A1BA7F09AB6B6A8E122F242DABB312F3F637A262174D31BF6B585FFAE5B7A035BF6F71C35FDAD44CFD2D74F9208BE258FF324943328F6722D9EE1003E5C50B1DF82CC6D241B0E2AE9CD348B1FD47E9267AFC1B2AE91EE51D6CB0E3179AB1042A95DCF6A9483B84B4B36B3861AA7255E4C0278BA3604650C10BE19482F23171B671DF1CF3B960C074301CD93C1D17603D147DAE2AEF837A62964EF15E5FB4AAC0B8C1CCAA4BE754AB5728AE9130C4C7D02880AB9472D455655347FFFFFFFFFFFFFFF diff --git a/lib/krb5/krb524_convert_creds_kdc.3 b/lib/krb5/krb524_convert_creds_kdc.3 new file mode 100644 index 0000000..1f4b9bf --- /dev/null +++ b/lib/krb5/krb524_convert_creds_kdc.3 @@ -0,0 +1,86 @@ +.\" Copyright (c) 2004 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb524_convert_creds_kdc.3 15239 2005-05-25 13:19:16Z lha $ +.\" +.Dd March 20, 2004 +.Dt KRB524_CONVERT_CREDS_KDC 3 +.Os HEIMDAL +.Sh NAME +.Nm krb524_convert_creds_kdc , +.Nm krb524_convert_creds_kdc_ccache +.Nd converts Kerberos 5 credentials to Kerberos 4 credentials +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Ft krb5_error_code +.Fo krb524_convert_creds_kdc +.Fa "krb5_context context" +.Fa "krb5_creds *in_cred" +.Fa "struct credentials *v4creds" +.Fc +.Ft krb5_error_code +.Fo krb524_convert_creds_kdc_ccache +.Fa "krb5_context context" +.Fa "krb5_ccache ccache" +.Fa "krb5_creds *in_cred" +.Fa "struct credentials *v4creds" +.Fc +.Sh DESCRIPTION +Convert the Kerberos 5 credential to Kerberos 4 credential. +This is done by sending them to the 524 service in the KDC. +.Pp +.Fn krb524_convert_creds_kdc +converts the Kerberos 5 credential in +.Fa in_cred +to Kerberos 4 credential that is stored in +.Fa credentials . +.Pp +.Fn krb524_convert_creds_kdc_ccache +is diffrent from +.Fn krb524_convert_creds_kdc +in that way that if +.Fa in_cred +doesn't contain a DES session key, then a new one is fetched from the +KDC and stored in the cred cache +.Fa ccache , +and then the KDC is queried to convert the credential. +.Pp +This interfaces are used to make the migration to Kerberos 5 from +Kerberos 4 easier. +There are few services that still need Kerberos 4, and this is mainly +for compatibility for those services. +Some services, like AFS, really have Kerberos 5 supports, but still +uses the 524 interface to make the migration easier. +.Sh SEE ALSO +.Xr krb5 3 , +.Xr krb5.conf 5 diff --git a/lib/krb5/krb5_425_conv_principal.3 b/lib/krb5/krb5_425_conv_principal.3 new file mode 100644 index 0000000..16c118f --- /dev/null +++ b/lib/krb5/krb5_425_conv_principal.3 @@ -0,0 +1,224 @@ +.\" Copyright (c) 1997-2003 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_425_conv_principal.3 12734 2003-09-03 00:13:07Z lha $ +.\" +.Dd September 3, 2003 +.Dt KRB5_425_CONV_PRINCIPAL 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_425_conv_principal , +.Nm krb5_425_conv_principal_ext , +.Nm krb5_524_conv_principal +.Nd converts to and from version 4 principals +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Ft krb5_error_code +.Fn krb5_425_conv_principal "krb5_context context" "const char *name" "const char *instance" "const char *realm" "krb5_principal *principal" +.Ft krb5_error_code +.Fn krb5_425_conv_principal_ext "krb5_context context" "const char *name" "const char *instance" "const char *realm" "krb5_boolean (*func)(krb5_context, krb5_principal)" "krb5_boolean resolve" "krb5_principal *principal" +.Ft krb5_error_code +.Fn krb5_524_conv_principal "krb5_context context" "const krb5_principal principal" "char *name" "char *instance" "char *realm" +.Sh DESCRIPTION +Converting between version 4 and version 5 principals can at best be +described as a mess. +.Pp +A version 4 principal consists of a name, an instance, and a realm. A +version 5 principal consists of one or more components, and a +realm. In some cases also the first component/name will differ between +version 4 and version 5. Furthermore the second component of a host +principal will be the fully qualified domain name of the host in +question, while the instance of a version 4 principal will only +contain the first part (short hostname). Because of these problems +the conversion between principals will have to be site customized. +.Pp +.Fn krb5_425_conv_principal_ext +will try to convert a version 4 principal, given by +.Fa name , +.Fa instance , +and +.Fa realm , +to a version 5 principal. This can result in several possible +principals, and if +.Fa func +is non-NULL, it will be called for each candidate principal. +.Fa func +should return true if the principal was +.Dq good . +To accomplish this, +.Fn krb5_425_conv_principal_ext +will look up the name in +.Pa krb5.conf . +It first looks in the +.Li v4_name_convert/host +subsection, which should contain a list of version 4 names whose +instance should be treated as a hostname. This list can be specified +for each realm (in the +.Li realms +section), or in the +.Li libdefaults +section. If the name is found the resulting name of the principal +will be the value of this binding. The instance is then first looked +up in +.Li v4_instance_convert +for the specified realm. If found the resulting value will be used as +instance (this can be used for special cases), no further attempts +will be made to find a conversion if this fails (with +.Fa func ) . +If the +.Fa resolve +parameter is true, the instance will be looked up with +.Fn gethostbyname . +This can be a time consuming, error prone, and unsafe operation. Next +a list of hostnames will be created from the instance and the +.Li v4_domains +variable, which should contain a list of possible domains for the +specific realm. +.Pp +On the other hand, if the name is not found in a +.Li host +section, it is looked up in a +.Li v4_name_convert/plain +binding. If found here the name will be converted, but the instance +will be untouched. +.Pp +This list of default host-type conversions is compiled-in: +.Bd -literal -offset indent +v4_name_convert = { + host = { + ftp = ftp + hprop = hprop + imap = imap + pop = pop + rcmd = host + smtp = smtp + } +} +.Ed +.Pp +It will only be used if there isn't an entry for these names in the +config file, so you can override these defaults. +.Pp +.Fn krb5_425_conv_principal +will call +.Fn krb5_425_conv_principal_ext +with +.Dv NULL +as +.Fa func , +and the value of +.Li v4_instance_resolve +(from the +.Li libdefaults +section) as +.Fa resolve . +.Pp +.Fn krb5_524_conv_principal +basically does the opposite of +.Fn krb5_425_conv_principal , +it just doesn't have to look up any names, but will instead truncate +instances found to belong to a host principal. The +.Fa name , +.Fa instance , +and +.Fa realm +should be at least 40 characters long. +.Sh EXAMPLES +Since this is confusing an example is in place. +.Pp +Assume that we have the +.Dq foo.com , +and +.Dq bar.com +domains that have shared a single version 4 realm, FOO.COM. The version 4 +.Pa krb.realms +file looked like: +.Bd -literal -offset indent +foo.com FOO.COM +\&.foo.com FOO.COM +\&.bar.com FOO.COM +.Ed +.Pp +A +.Pa krb5.conf +file that covers this case might look like: +.Bd -literal -offset indent +[libdefaults] + v4_instance_resolve = yes +[realms] + FOO.COM = { + kdc = kerberos.foo.com + v4_instance_convert = { + foo = foo.com + } + v4_domains = foo.com + } +.Ed +.Pp +With this setup and the following host table: +.Bd -literal -offset indent +foo.com +a-host.foo.com +b-host.bar.com +.Ed +the following conversions will be made: +.Bd -literal -offset indent +rcmd.a-host -\*(Gt host/a-host.foo.com +ftp.b-host -\*(Gt ftp/b-host.bar.com +pop.foo -\*(Gt pop/foo.com +ftp.other -\*(Gt ftp/other.foo.com +other.a-host -\*(Gt other/a-host +.Ed +.Pp +The first three are what you expect. If you remove the +.Dq v4_domains , +the fourth entry will result in an error (since the host +.Dq other +can't be found). Even if +.Dq a-host +is a valid host name, the last entry will not be converted, since the +.Dq other +name is not known to represent a host-type principal. +If you turn off +.Dq v4_instance_resolve +the second example will result in +.Dq ftp/b-host.foo.com +(because of the default domain). And all of this is of course only +valid if you have working name resolving. +.Sh SEE ALSO +.Xr krb5_build_principal 3 , +.Xr krb5_free_principal 3 , +.Xr krb5_parse_name 3 , +.Xr krb5_sname_to_principal 3 , +.Xr krb5_unparse_name 3 , +.Xr krb5.conf 5 diff --git a/lib/krb5/krb5_acl_match_file.3 b/lib/krb5/krb5_acl_match_file.3 new file mode 100644 index 0000000..342645e --- /dev/null +++ b/lib/krb5/krb5_acl_match_file.3 @@ -0,0 +1,111 @@ +.\" Copyright (c) 2004, 2006 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_acl_match_file.3 17534 2006-05-11 22:43:44Z lha $ +.\" +.Dd May 12, 2006 +.Dt KRB5_ACL_MATCH_FILE 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_acl_match_file , +.Nm krb5_acl_match_string +.Nd ACL matching functions +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.Ft krb5_error_code +.Fo krb5_acl_match_file +.Fa "krb5_context context" +.Fa "const char *file" +.Fa "const char *format" +.Fa "..." +.Fc +.Ft krb5_error_code +.Fo krb5_acl_match_string +.Fa "krb5_context context" +.Fa "const char *string" +.Fa "const char *format" +.Fa "..." +.Fc +.Sh DESCRIPTION +.Nm krb5_acl_match_file +matches ACL format against each line in a file. +Lines starting with # are treated like comments and ignored. +.Pp +.Nm krb5_acl_match_string +matches ACL format against a string. +.Pp +The ACL format has three format specifiers: s, f, and r. +Each specifier will retrieve one argument from the variable arguments +for either matching or storing data. +The input string is split up using " " and "\et" as a delimiter; multiple +" " and "\et" in a row are considered to be the same. +.Pp +.Bl -tag -width "fXX" -offset indent +.It s +Matches a string using +.Xr strcmp 3 +(case sensitive). +.It f +Matches the string with +.Xr fnmatch 3 . +The +.Fa flags +argument (the last argument) passed to the fnmatch function is 0. +.It r +Returns a copy of the string in the char ** passed in; the copy must be +freed with +.Xr free 3 . +There is no need to +.Xr free 3 +the string on error: the function will clean up and set the pointer to +.Dv NULL . +.El +.Pp +All unknown format specifiers cause an error. +.Sh EXAMPLES +.Bd -literal -offset indent +char *s; + +ret = krb5_acl_match_string(context, "foo", "s", "foo"); +if (ret) + krb5_errx(context, 1, "acl didn't match"); +ret = krb5_acl_match_string(context, "foo foo baz/kaka", + "ss", "foo", &s, "foo/*"); +if (ret) { + /* no need to free(s) on error */ + assert(s == NULL); + krb5_errx(context, 1, "acl didn't match"); +} +free(s); +.Ed +.Sh SEE ALSO +.Xr krb5 3 diff --git a/lib/krb5/krb5_address.3 b/lib/krb5/krb5_address.3 new file mode 100644 index 0000000..06f7fa5 --- /dev/null +++ b/lib/krb5/krb5_address.3 @@ -0,0 +1,359 @@ +.\" Copyright (c) 2003, 2005 - 2006 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_address.3 17461 2006-05-05 13:13:18Z lha $ +.\" +.Dd May 1, 2006 +.Dt KRB5_ADDRESS 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_address , +.Nm krb5_addresses , +.Nm krb5_sockaddr2address , +.Nm krb5_sockaddr2port , +.Nm krb5_addr2sockaddr , +.Nm krb5_max_sockaddr_size , +.Nm krb5_sockaddr_uninteresting , +.Nm krb5_h_addr2sockaddr , +.Nm krb5_h_addr2addr , +.Nm krb5_anyaddr , +.Nm krb5_print_address , +.Nm krb5_parse_address , +.Nm krb5_address_order , +.Nm krb5_address_compare , +.Nm krb5_address_search , +.Nm krb5_free_address , +.Nm krb5_free_addresses , +.Nm krb5_copy_address , +.Nm krb5_copy_addresses , +.Nm krb5_append_addresses , +.Nm krb5_make_addrport +.Nd mange addresses in Kerberos +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Pp +.Ft krb5_error_code +.Fo krb5_sockaddr2address +.Fa "krb5_context context" +.Fa "const struct sockaddr *sa" +.Fa "krb5_address *addr" +.Fc +.Ft krb5_error_code +.Fo krb5_sockaddr2port +.Fa "krb5_context context" +.Fa "const struct sockaddr *sa" +.Fa "int16_t *port" +.Fc +.Ft krb5_error_code +.Fo krb5_addr2sockaddr +.Fa "krb5_context context" +.Fa "const krb5_address *addr" +.Fa "struct sockaddr *sa" +.Fa "krb5_socklen_t *sa_size" +.Fa "int port" +.Fc +.Ft size_t +.Fo krb5_max_sockaddr_size +.Fa "void" +.Fc +.Ft "krb5_boolean" +.Fo krb5_sockaddr_uninteresting +.Fa "const struct sockaddr *sa" +.Fc +.Ft krb5_error_code +.Fo krb5_h_addr2sockaddr +.Fa "krb5_context context" +.Fa "int af" +.Fa "const char *addr" +.Fa "struct sockaddr *sa" +.Fa "krb5_socklen_t *sa_size" +.Fa "int port" +.Fc +.Ft krb5_error_code +.Fo krb5_h_addr2addr +.Fa "krb5_context context" +.Fa "int af" +.Fa "const char *haddr" +.Fa "krb5_address *addr" +.Fc +.Ft krb5_error_code +.Fo krb5_anyaddr +.Fa "krb5_context context" +.Fa "int af" +.Fa "struct sockaddr *sa" +.Fa "krb5_socklen_t *sa_size" +.Fa "int port" +.Fc +.Ft krb5_error_code +.Fo krb5_print_address +.Fa "const krb5_address *addr" +.Fa "char *str" +.Fa "size_t len" +.Fa "size_t *ret_len" +.Fc +.Ft krb5_error_code +.Fo krb5_parse_address +.Fa "krb5_context context" +.Fa "const char *string" +.Fa "krb5_addresses *addresses" +.Fc +.Ft int +.Fo "krb5_address_order" +.Fa "krb5_context context" +.Fa "const krb5_address *addr1" +.Fa "const krb5_address *addr2" +.Fc +.Ft "krb5_boolean" +.Fo krb5_address_compare +.Fa "krb5_context context" +.Fa "const krb5_address *addr1" +.Fa "const krb5_address *addr2" +.Fc +.Ft "krb5_boolean" +.Fo krb5_address_search +.Fa "krb5_context context" +.Fa "const krb5_address *addr" +.Fa "const krb5_addresses *addrlist" +.Fc +.Ft krb5_error_code +.Fo krb5_free_address +.Fa "krb5_context context" +.Fa "krb5_address *address" +.Fc +.Ft krb5_error_code +.Fo krb5_free_addresses +.Fa "krb5_context context" +.Fa "krb5_addresses *addresses" +.Fc +.Ft krb5_error_code +.Fo krb5_copy_address +.Fa "krb5_context context" +.Fa "const krb5_address *inaddr" +.Fa "krb5_address *outaddr" +.Fc +.Ft krb5_error_code +.Fo krb5_copy_addresses +.Fa "krb5_context context" +.Fa "const krb5_addresses *inaddr" +.Fa "krb5_addresses *outaddr" +.Fc +.Ft krb5_error_code +.Fo krb5_append_addresses +.Fa "krb5_context context" +.Fa "krb5_addresses *dest" +.Fa "const krb5_addresses *source" +.Fc +.Ft krb5_error_code +.Fo krb5_make_addrport +.Fa "krb5_context context" +.Fa "krb5_address **res" +.Fa "const krb5_address *addr" +.Fa "int16_t port" +.Fc +.Sh DESCRIPTION +The +.Li krb5_address +structure holds a address that can be used in Kerberos API +calls. There are help functions to set and extract address information +of the address. +.Pp +The +.Li krb5_addresses +structure holds a set of krb5_address:es. +.Pp +.Fn krb5_sockaddr2address +stores a address a +.Li "struct sockaddr" +.Fa sa +in the krb5_address +.Fa addr . +.Pp +.Fn krb5_sockaddr2port +extracts a +.Fa port +(if possible) from a +.Li "struct sockaddr" +.Fa sa . +.Pp +.Fn krb5_addr2sockaddr +sets the +struct sockaddr +.Fa sockaddr +from +.Fa addr +and +.Fa port . +The argument +.Fa sa_size +should initially contain the size of the +.Fa sa , +and after the call, it will contain the actual length of the address. +.Pp +.Fn krb5_max_sockaddr_size +returns the max size of the +.Li struct sockaddr +that the Kerberos library will return. +.Pp +.Fn krb5_sockaddr_uninteresting +returns +.Dv TRUE +for all +.Fa sa +that the kerberos library thinks are uninteresting. +One example are link local addresses. +.Pp +.Fn krb5_h_addr2sockaddr +initializes a +.Li "struct sockaddr" +.Fa sa +from +.Fa af +and the +.Li "struct hostent" +(see +.Xr gethostbyname 3 ) +.Fa h_addr_list +component. +The argument +.Fa sa_size +should initially contain the size of the +.Fa sa , +and after the call, it will contain the actual length of the address. +.Pp +.Fn krb5_h_addr2addr +works like +.Fn krb5_h_addr2sockaddr +with the exception that it operates on a +.Li krb5_address +instead of a +.Li struct sockaddr . +.Pp +.Fn krb5_anyaddr +fills in a +.Li "struct sockaddr" +.Fa sa +that can be used to +.Xr bind 2 +to. +The argument +.Fa sa_size +should initially contain the size of the +.Fa sa , +and after the call, it will contain the actual length of the address. +.Pp +.Fn krb5_print_address +prints the address in +.Fa addr +to the string +.Fa string +that have the length +.Fa len . +If +.Fa ret_len +is not +.Dv NULL , +it will be filled with the length of the string if size were unlimited (not +including the final +.Ql \e0 ) . +.Pp +.Fn krb5_parse_address +Returns the resolved hostname in +.Fa string +to the +.Li krb5_addresses +.Fa addresses . +.Pp +.Fn krb5_address_order +compares the addresses +.Fa addr1 +and +.Fa addr2 +so that it can be used for sorting addresses. If the addresses are the +same address +.Fa krb5_address_order +will return 0. +.Pp +.Fn krb5_address_compare +compares the addresses +.Fa addr1 +and +.Fa addr2 . +Returns +.Dv TRUE +if the two addresses are the same. +.Pp +.Fn krb5_address_search +checks if the address +.Fa addr +is a member of the address set list +.Fa addrlist . +.Pp +.Fn krb5_free_address +frees the data stored in the +.Fa address +that is alloced with any of the krb5_address functions. +.Pp +.Fn krb5_free_addresses +frees the data stored in the +.Fa addresses +that is alloced with any of the krb5_address functions. +.Pp +.Fn krb5_copy_address +copies the content of address +.Fa inaddr +to +.Fa outaddr . +.Pp +.Fn krb5_copy_addresses +copies the content of the address list +.Fa inaddr +to +.Fa outaddr . +.Pp +.Fn krb5_append_addresses +adds the set of addresses in +.Fa source +to +.Fa dest . +While copying the addresses, duplicates are also sorted out. +.Pp +.Fn krb5_make_addrport +allocates and creates an +krb5_address in +.Fa res +of type KRB5_ADDRESS_ADDRPORT from +.Fa ( addr , port ) . +.Sh SEE ALSO +.Xr krb5 3 , +.Xr krb5.conf 5 , +.Xr kerberos 8 diff --git a/lib/krb5/krb5_aname_to_localname.3 b/lib/krb5/krb5_aname_to_localname.3 new file mode 100644 index 0000000..a0c3e4b --- /dev/null +++ b/lib/krb5/krb5_aname_to_localname.3 @@ -0,0 +1,80 @@ +.\" Copyright (c) 2003 - 2007 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_aname_to_localname.3 22071 2007-11-14 20:04:50Z lha $ +.\" +.Dd February 18, 2006 +.Dt KRB5_ANAME_TO_LOCALNAME 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_aname_to_localname +.Nd converts a principal to a system local name +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Ft krb5_boolean +.Fo krb5_aname_to_localname +.Fa "krb5_context context" +.Fa "krb5_const_principal name" +.Fa "size_t lnsize" +.Fa "char *lname" +.Fc +.Sh DESCRIPTION +This function takes a principal +.Fa name , +verifies that it is in the local realm (using +.Fn krb5_get_default_realms ) +and then returns the local name of the principal. +.Pp +If +.Fa name +isn't in one of the local realms an error is returned. +.Pp +If the size +.Fa ( lnsize ) +of the local name +.Fa ( lname ) +is too small, an error is returned. +.Pp +.Fn krb5_aname_to_localname +should only be use by an application that implements protocols that +don't transport the login name and thus needs to convert a principal +to a local name. +.Pp +Protocols should be designed so that they authenticate using +Kerberos, send over the login name and then verify the principal +that is authenticated is allowed to login and the login name. +A way to check if a user is allowed to login is using the function +.Fn krb5_kuserok . +.Sh SEE ALSO +.Xr krb5_get_default_realms 3 , +.Xr krb5_kuserok 3 diff --git a/lib/krb5/krb5_appdefault.3 b/lib/krb5/krb5_appdefault.3 new file mode 100644 index 0000000..f5b5329 --- /dev/null +++ b/lib/krb5/krb5_appdefault.3 @@ -0,0 +1,88 @@ +.\" Copyright (c) 2000 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_appdefault.3 12329 2003-05-26 14:09:04Z lha $ +.\" +.Dd July 25, 2000 +.Dt KRB5_APPDEFAULT 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_appdefault_boolean , +.Nm krb5_appdefault_string , +.Nm krb5_appdefault_time +.Nd get application configuration value +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Ft void +.Fn krb5_appdefault_boolean "krb5_context context" "const char *appname" "krb5_realm realm" "const char *option" "krb5_boolean def_val" "krb5_boolean *ret_val" +.Ft void +.Fn krb5_appdefault_string "krb5_context context" "const char *appname" "krb5_realm realm" "const char *option" "const char *def_val" "char **ret_val" +.Ft void +.Fn krb5_appdefault_time "krb5_context context" "const char *appname" "krb5_realm realm" "const char *option" "time_t def_val" "time_t *ret_val" +.Sh DESCRIPTION +These functions get application defaults from the +.Dv appdefaults +section of the +.Xr krb5.conf 5 +configuration file. These defaults can be specified per application, +and/or per realm. +.Pp +These values will be looked for in +.Xr krb5.conf 5 , +in order of descending importance. +.Bd -literal -offset indent +[appdefaults] + appname = { + realm = { + option = value + } + } + appname = { + option = value + } + realm = { + option = value + } + option = value +.Ed +.Fa appname +is the name of the application, and +.Fa realm +is the realm name. If the realm is omitted it will not be used for +resolving values. +.Fa def_val +is the value to return if no value is found in +.Xr krb5.conf 5 . +.Sh SEE ALSO +.Xr krb5_config 3 , +.Xr krb5.conf 5 diff --git a/lib/krb5/krb5_auth_context.3 b/lib/krb5/krb5_auth_context.3 new file mode 100644 index 0000000..66d150e --- /dev/null +++ b/lib/krb5/krb5_auth_context.3 @@ -0,0 +1,395 @@ +.\" Copyright (c) 2001 - 2005 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_auth_context.3 15240 2005-05-25 13:47:58Z lha $ +.\" +.Dd May 17, 2005 +.Dt KRB5_AUTH_CONTEXT 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_auth_con_addflags , +.Nm krb5_auth_con_free , +.Nm krb5_auth_con_genaddrs , +.Nm krb5_auth_con_generatelocalsubkey , +.Nm krb5_auth_con_getaddrs , +.Nm krb5_auth_con_getauthenticator , +.Nm krb5_auth_con_getflags , +.Nm krb5_auth_con_getkey , +.Nm krb5_auth_con_getlocalsubkey , +.Nm krb5_auth_con_getrcache , +.Nm krb5_auth_con_getremotesubkey , +.Nm krb5_auth_con_getuserkey , +.Nm krb5_auth_con_init , +.Nm krb5_auth_con_initivector , +.Nm krb5_auth_con_removeflags , +.Nm krb5_auth_con_setaddrs , +.Nm krb5_auth_con_setaddrs_from_fd , +.Nm krb5_auth_con_setflags , +.Nm krb5_auth_con_setivector , +.Nm krb5_auth_con_setkey , +.Nm krb5_auth_con_setlocalsubkey , +.Nm krb5_auth_con_setrcache , +.Nm krb5_auth_con_setremotesubkey , +.Nm krb5_auth_con_setuserkey , +.Nm krb5_auth_context , +.Nm krb5_auth_getcksumtype , +.Nm krb5_auth_getkeytype , +.Nm krb5_auth_getlocalseqnumber , +.Nm krb5_auth_getremoteseqnumber , +.Nm krb5_auth_setcksumtype , +.Nm krb5_auth_setkeytype , +.Nm krb5_auth_setlocalseqnumber , +.Nm krb5_auth_setremoteseqnumber , +.Nm krb5_free_authenticator +.Nd manage authentication on connection level +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Ft krb5_error_code +.Fo krb5_auth_con_init +.Fa "krb5_context context" +.Fa "krb5_auth_context *auth_context" +.Fc +.Ft void +.Fo krb5_auth_con_free +.Fa "krb5_context context" +.Fa "krb5_auth_context auth_context" +.Fc +.Ft krb5_error_code +.Fo krb5_auth_con_setflags +.Fa "krb5_context context" +.Fa "krb5_auth_context auth_context" +.Fa "int32_t flags" +.Fc +.Ft krb5_error_code +.Fo krb5_auth_con_getflags +.Fa "krb5_context context" +.Fa "krb5_auth_context auth_context" +.Fa "int32_t *flags" +.Fc +.Ft krb5_error_code +.Fo krb5_auth_con_addflags +.Fa "krb5_context context" +.Fa "krb5_auth_context auth_context" +.Fa "int32_t addflags" +.Fa "int32_t *flags" +.Fc +.Ft krb5_error_code +.Fo krb5_auth_con_removeflags +.Fa "krb5_context context" +.Fa "krb5_auth_context auth_context" +.Fa "int32_t removelags" +.Fa "int32_t *flags" +.Fc +.Ft krb5_error_code +.Fo krb5_auth_con_setaddrs +.Fa "krb5_context context" +.Fa "krb5_auth_context auth_context" +.Fa "krb5_address *local_addr" +.Fa "krb5_address *remote_addr" +.Fc +.Ft krb5_error_code +.Fo krb5_auth_con_getaddrs +.Fa "krb5_context context" +.Fa "krb5_auth_context auth_context" +.Fa "krb5_address **local_addr" +.Fa "krb5_address **remote_addr" +.Fc +.Ft krb5_error_code +.Fo krb5_auth_con_genaddrs +.Fa "krb5_context context" +.Fa "krb5_auth_context auth_context" +.Fa "int fd" +.Fa "int flags" +.Fc +.Ft krb5_error_code +.Fo krb5_auth_con_setaddrs_from_fd +.Fa "krb5_context context" +.Fa "krb5_auth_context auth_context" +.Fa "void *p_fd" +.Fc +.Ft krb5_error_code +.Fo krb5_auth_con_getkey +.Fa "krb5_context context" +.Fa "krb5_auth_context auth_context" +.Fa "krb5_keyblock **keyblock" +.Fc +.Ft krb5_error_code +.Fo krb5_auth_con_getlocalsubkey +.Fa "krb5_context context" +.Fa "krb5_auth_context auth_context" +.Fa "krb5_keyblock **keyblock" +.Fc +.Ft krb5_error_code +.Fo krb5_auth_con_getremotesubkey +.Fa "krb5_context context" +.Fa "krb5_auth_context auth_context" +.Fa "krb5_keyblock **keyblock" +.Fc +.Ft krb5_error_code +.Fo krb5_auth_con_generatelocalsubkey +.Fa "krb5_context context" +.Fa "krb5_auth_context auth_context" +.Fa krb5_keyblock *key" +.Fc +.Ft krb5_error_code +.Fo krb5_auth_con_initivector +.Fa "krb5_context context" +.Fa "krb5_auth_context auth_context" +.Fc +.Ft krb5_error_code +.Fo krb5_auth_con_setivector +.Fa "krb5_context context" +.Fa "krb5_auth_context *auth_context" +.Fa "krb5_pointer ivector" +.Fc +.Ft void +.Fo krb5_free_authenticator +.Fa "krb5_context context" +.Fa "krb5_authenticator *authenticator" +.Fc +.Sh DESCRIPTION +The +.Nm krb5_auth_context +structure holds all context related to an authenticated connection, in +a similar way to +.Nm krb5_context +that holds the context for the thread or process. +.Nm krb5_auth_context +is used by various functions that are directly related to +authentication between the server/client. Example of data that this +structure contains are various flags, addresses of client and server, +port numbers, keyblocks (and subkeys), sequence numbers, replay cache, +and checksum-type. +.Pp +.Fn krb5_auth_con_init +allocates and initializes the +.Nm krb5_auth_context +structure. Default values can be changed with +.Fn krb5_auth_con_setcksumtype +and +.Fn krb5_auth_con_setflags . +The +.Nm auth_context +structure must be freed by +.Fn krb5_auth_con_free . +.Pp +.Fn krb5_auth_con_getflags , +.Fn krb5_auth_con_setflags , +.Fn krb5_auth_con_addflags +and +.Fn krb5_auth_con_removeflags +gets and modifies the flags for a +.Nm krb5_auth_context +structure. Possible flags to set are: +.Bl -tag -width Ds +.It Dv KRB5_AUTH_CONTEXT_DO_SEQUENCE +Generate and check sequence-number on each packet. +.It Dv KRB5_AUTH_CONTEXT_DO_TIME +Check timestamp on incoming packets. +.It Dv KRB5_AUTH_CONTEXT_RET_SEQUENCE , Dv KRB5_AUTH_CONTEXT_RET_TIME +Return sequence numbers and time stamps in the outdata parameters. +.It Dv KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED +will force +.Fn krb5_get_forwarded_creds +and +.Fn krb5_fwd_tgt_creds +to create unencrypted ) +.Dv ENCTYPE_NULL ) +credentials. +This is for use with old MIT server and JAVA based servers as +they can't handle encrypted +.Dv KRB-CRED . +Note that sending such +.Dv KRB-CRED +is clear exposes crypto keys and tickets and is insecure, +make sure the packet is encrypted in the protocol. +.Xr krb5_rd_cred 3 , +.Xr krb5_rd_priv 3 , +.Xr krb5_rd_safe 3 , +.Xr krb5_mk_priv 3 +and +.Xr krb5_mk_safe 3 . +Setting this flag requires that parameter to be passed to these +functions. +.Pp +The flags +.Dv KRB5_AUTH_CONTEXT_DO_TIME +also modifies the behavior the function +.Fn krb5_get_forwarded_creds +by removing the timestamp in the forward credential message, this have +backward compatibility problems since not all versions of the heimdal +supports timeless credentional messages. +Is very useful since it always the sender of the message to cache +forward message and thus avoiding a round trip to the KDC for each +time a credential is forwarded. +The same functionality can be obtained by using address-less tickets. +.\".It Dv KRB5_AUTH_CONTEXT_PERMIT_ALL +.El +.Pp +.Fn krb5_auth_con_setaddrs , +.Fn krb5_auth_con_setaddrs_from_fd +and +.Fn krb5_auth_con_getaddrs +gets and sets the addresses that are checked when a packet is received. +It is mandatory to set an address for the remote +host. If the local address is not set, it iss deduced from the underlaying +operating system. +.Fn krb5_auth_con_getaddrs +will call +.Fn krb5_free_address +on any address that is passed in +.Fa local_addr +or +.Fa remote_addr . +.Fn krb5_auth_con_setaddr +allows passing in a +.Dv NULL +pointer as +.Fa local_addr +and +.Fa remote_addr , +in that case it will just not set that address. +.Pp +.Fn krb5_auth_con_setaddrs_from_fd +fetches the addresses from a file descriptor. +.Pp +.Fn krb5_auth_con_genaddrs +fetches the address information from the given file descriptor +.Fa fd +depending on the bitmap argument +.Fa flags . +.Pp +Possible values on +.Fa flags +are: +.Bl -tag -width Ds +.It Va KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR +fetches the local address from +.Fa fd . +.It Va KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR +fetches the remote address from +.Fa fd . +.El +.Pp +.Fn krb5_auth_con_setkey , +.Fn krb5_auth_con_setuserkey +and +.Fn krb5_auth_con_getkey +gets and sets the key used for this auth context. The keyblock returned by +.Fn krb5_auth_con_getkey +should be freed with +.Fn krb5_free_keyblock . +The keyblock send into +.Fn krb5_auth_con_setkey +is copied into the +.Nm krb5_auth_context , +and thus no special handling is needed. +.Dv NULL +is not a valid keyblock to +.Fn krb5_auth_con_setkey . +.Pp +.Fn krb5_auth_con_setuserkey +is only useful when doing user to user authentication. +.Fn krb5_auth_con_setkey +is equivalent to +.Fn krb5_auth_con_setuserkey . +.Pp +.Fn krb5_auth_con_getlocalsubkey , +.Fn krb5_auth_con_setlocalsubkey , +.Fn krb5_auth_con_getremotesubkey +and +.Fn krb5_auth_con_setremotesubkey +gets and sets the keyblock for the local and remote subkey. +The keyblock returned by +.Fn krb5_auth_con_getlocalsubkey +and +.Fn krb5_auth_con_getremotesubkey +must be freed with +.Fn krb5_free_keyblock . +.Pp +.Fn krb5_auth_setcksumtype +and +.Fn krb5_auth_getcksumtype +sets and gets the checksum type that should be used for this +connection. +.Pp +.Fn krb5_auth_con_generatelocalsubkey +generates a local subkey that have the same encryption type as +.Fa key . +.Pp +.Fn krb5_auth_getremoteseqnumber +.Fn krb5_auth_setremoteseqnumber , +.Fn krb5_auth_getlocalseqnumber +and +.Fn krb5_auth_setlocalseqnumber +gets and sets the sequence-number for the local and remote +sequence-number counter. +.Pp +.Fn krb5_auth_setkeytype +and +.Fn krb5_auth_getkeytype +gets and gets the keytype of the keyblock in +.Nm krb5_auth_context . +.Pp +.Fn krb5_auth_con_getauthenticator +Retrieves the authenticator that was used during mutual +authentication. The +.Dv authenticator +returned should be freed by calling +.Fn krb5_free_authenticator . +.Pp +.Fn krb5_auth_con_getrcache +and +.Fn krb5_auth_con_setrcache +gets and sets the replay-cache. +.Pp +.Fn krb5_auth_con_initivector +allocates memory for and zeros the initial vector in the +.Fa auth_context +keyblock. +.Pp +.Fn krb5_auth_con_setivector +sets the i_vector portion of +.Fa auth_context +to +.Fa ivector . +.Pp +.Fn krb5_free_authenticator +free the content of +.Fa authenticator +and +.Fa authenticator +itself. +.Sh SEE ALSO +.Xr krb5_context 3 , +.Xr kerberos 8 diff --git a/lib/krb5/krb5_build_principal.3 b/lib/krb5/krb5_build_principal.3 new file mode 100644 index 0000000..e74c754 --- /dev/null +++ b/lib/krb5/krb5_build_principal.3 @@ -0,0 +1,101 @@ +.\" Copyright (c) 1997, 2001 - 2002 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_build_principal.3,v 1.7 2003/04/16 13:58:14 lha Exp $ +.\" +.Dd August 8, 1997 +.Dt KRB5_BUILD_PRINCIPAL 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_build_principal , +.Nm krb5_build_principal_ext , +.Nm krb5_build_principal_va , +.Nm krb5_build_principal_va_ext , +.Nm krb5_make_principal +.Nd principal creation functions +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Ft krb5_error_code +.Fn krb5_build_principal "krb5_context context" "krb5_principal *principal" "int realm_len" "krb5_const_realm realm" "..." +.Ft krb5_error_code +.Fn krb5_build_principal_ext "krb5_context context" "krb5_principal *principal" "int realm_len" "krb5_const_realm realm" "..." +.Ft krb5_error_code +.Fn krb5_build_principal_va "krb5_context context" "krb5_principal *principal" "int realm_len" "krb5_const_realm realm" "va_list ap" +.Ft krb5_error_code +.Fn krb5_build_principal_va_ext "krb5_context context" "krb5_principal *principal" "int realm_len" "krb5_const_realm realm" "va_list ap" +.Ft krb5_error_code +.Fn krb5_make_principal "krb5_context context" "krb5_principal *principal" "krb5_const_realm realm" "..." +.Sh DESCRIPTION +These functions create a Kerberos 5 principal from a realm and a list +of components. +All of these functions return an allocated principal in the +.Fa principal +parameter, this should be freed with +.Fn krb5_free_principal +after use. +.Pp +The +.Dq build +functions take a +.Fa realm +and the length of the realm. The +.Fn krb5_build_principal +and +.Fn krb5_build_principal_va +also takes a list of components (zero-terminated strings), terminated +with +.Dv NULL . +The +.Fn krb5_build_principal_ext +and +.Fn krb5_build_principal_va_ext +takes a list of length-value pairs, the list is terminated with a zero +length. +.Pp +The +.Fn krb5_make_principal +is a wrapper around +.Fn krb5_build_principal . +If the realm is +.Dv NULL , +the default realm will be used. +.Sh BUGS +You can not have a NUL in a component. Until someone can give a good +example of where it would be a good idea to have NUL's in a component, +this will not be fixed. +.Sh SEE ALSO +.Xr krb5_425_conv_principal 3 , +.Xr krb5_free_principal 3 , +.Xr krb5_parse_name 3 , +.Xr krb5_sname_to_principal 3 , +.Xr krb5_unparse_name 3 diff --git a/lib/krb5/krb5_c_make_checksum.3 b/lib/krb5/krb5_c_make_checksum.3 new file mode 100644 index 0000000..a323cce --- /dev/null +++ b/lib/krb5/krb5_c_make_checksum.3 @@ -0,0 +1,297 @@ +.\" Copyright (c) 2003 - 2006 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_c_make_checksum.3 19066 2006-11-17 22:09:25Z lha $ +.\" +.Dd Nov 17, 2006 +.Dt KRB5_C_MAKE_CHECKSUM 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_c_block_size , +.Nm krb5_c_decrypt , +.Nm krb5_c_encrypt , +.Nm krb5_c_encrypt_length , +.Nm krb5_c_enctype_compare , +.Nm krb5_c_get_checksum , +.Nm krb5_c_is_coll_proof_cksum , +.Nm krb5_c_is_keyed_cksum , +.Nm krb5_c_keylength , +.Nm krb5_c_make_checksum , +.Nm krb5_c_make_random_key , +.Nm krb5_c_set_checksum , +.Nm krb5_c_valid_cksumtype , +.Nm krb5_c_valid_enctype , +.Nm krb5_c_verify_checksum , +.Nm krb5_c_checksum_length +.Nd Kerberos 5 crypto API +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Pp +.Ft krb5_error_code +.Fo krb5_c_block_size +.Fa "krb5_context context" +.Fa "krb5_enctype enctype" +.Fa "size_t *blocksize" +.Fc +.Ft krb5_error_code +.Fo krb5_c_decrypt +.Fa "krb5_context context" +.Fa "const krb5_keyblock key" +.Fa "krb5_keyusage usage" +.Fa "const krb5_data *ivec" +.Fa "krb5_enc_data *input" +.Fa "krb5_data *output" +.Fc +.Ft krb5_error_code +.Fo krb5_c_encrypt +.Fa "krb5_context context" +.Fa "const krb5_keyblock *key" +.Fa "krb5_keyusage usage" +.Fa "const krb5_data *ivec" +.Fa "const krb5_data *input" +.Fa "krb5_enc_data *output" +.Fc +.Ft krb5_error_code +.Fo krb5_c_encrypt_length +.Fa "krb5_context context" +.Fa "krb5_enctype enctype" +.Fa "size_t inputlen" +.Fa "size_t *length" +.Fc +.Ft krb5_error_code +.Fo krb5_c_enctype_compare +.Fa "krb5_context context" +.Fa "krb5_enctype e1" +.Fa "krb5_enctype e2" +.Fa "krb5_boolean *similar" +.Fc +.Ft krb5_error_code +.Fo krb5_c_make_random_key +.Fa "krb5_context context" +.Fa "krb5_enctype enctype" +.Fa "krb5_keyblock *random_key" +.Fc +.Ft krb5_error_code +.Fo krb5_c_make_checksum +.Fa "krb5_context context" +.Fa "krb5_cksumtype cksumtype" +.Fa "const krb5_keyblock *key" +.Fa "krb5_keyusage usage" +.Fa "const krb5_data *input" +.Fa "krb5_checksum *cksum" +.Fc +.Ft krb5_error_code +.Fo krb5_c_verify_checksum +.Fa "krb5_context context +.Fa "const krb5_keyblock *key" +.Fa "krb5_keyusage usage" +.Fa "const krb5_data *data" +.Fa "const krb5_checksum *cksum" +.Fa "krb5_boolean *valid" +.Fc +.Ft krb5_error_code +.Fo krb5_c_checksum_length +.Fa "krb5_context context" +.Fa "krb5_cksumtype cksumtype" +.Fa "size_t *length" +.Fc +.Ft krb5_error_code +.Fo krb5_c_get_checksum +.Fa "krb5_context context" +.Fa "const krb5_checksum *cksum" +.Fa "krb5_cksumtype *type" +.Fa "krb5_data **data" +.Fc +.Ft krb5_error_code +.Fo krb5_c_set_checksum +.Fa "krb5_context context" +.Fa "krb5_checksum *cksum" +.Fa "krb5_cksumtype type" +.Fa "const krb5_data *data" +.Fc +.Ft krb5_boolean +.Fo krb5_c_valid_enctype +.Fa krb5_enctype etype" +.Fc +.Ft krb5_boolean +.Fo krb5_c_valid_cksumtype +.Fa "krb5_cksumtype ctype" +.Fc +.Ft krb5_boolean +.Fo krb5_c_is_coll_proof_cksum +.Fa "krb5_cksumtype ctype" +.Fc +.Ft krb5_boolean +.Fo krb5_c_is_keyed_cksum +.Fa "krb5_cksumtype ctype" +.Fc +.Ft krb5_error_code +.Fo krb5_c_keylengths +.Fa "krb5_context context" +.Fa "krb5_enctype enctype" +.Fa "size_t *inlength" +.Fa "size_t *keylength" +.Fc +.Sh DESCRIPTION +The functions starting with krb5_c are compat functions with MIT kerberos. +.Pp +The +.Li krb5_enc_data +structure holds and encrypted data. +There are two public accessable members of +.Li krb5_enc_data . +.Li enctype +that holds the encryption type of the data encrypted and +.Li ciphertext +that is a +.Ft krb5_data +that might contain the encrypted data. +.Pp +.Fn krb5_c_block_size +returns the blocksize of the encryption type. +.Pp +.Fn krb5_c_decrypt +decrypts +.Fa input +and store the data in +.Fa output. +If +.Fa ivec +is +.Dv NULL +the default initialization vector for that encryption type will be used. +.Pp +.Fn krb5_c_encrypt +encrypts the plaintext in +.Fa input +and store the ciphertext in +.Fa output . +.Pp +.Fn krb5_c_encrypt_length +returns the length the encrypted data given the plaintext length. +.Pp +.Fn krb5_c_enctype_compare +compares to encryption types and returns if they use compatible +encryption key types. +.Pp +.Fn krb5_c_make_checksum +creates a checksum +.Fa cksum +with the checksum type +.Fa cksumtype +of the data in +.Fa data . +.Fa key +and +.Fa usage +are used if the checksum is a keyed checksum type. +Returns 0 or an error code. +.Pp +.Fn krb5_c_verify_checksum +verifies the checksum +of +.Fa data +in +.Fa cksum +that was created with +.Fa key +using the key usage +.Fa usage . +.Fa verify +is set to non-zero if the checksum verifies correctly and zero if not. +Returns 0 or an error code. +.Pp +.Fn krb5_c_checksum_length +returns the length of the checksum. +.Pp +.Fn krb5_c_set_checksum +sets the +.Li krb5_checksum +structure given +.Fa type +and +.Fa data . +The content of +.Fa cksum +should be freeed with +.Fn krb5_c_free_checksum_contents . +.Pp +.Fn krb5_c_get_checksum +retrieves the components of the +.Li krb5_checksum . +structure. +.Fa data +should be free with +.Fn krb5_free_data . +If some either of +.Fa data +or +.Fa checksum +is not needed for the application, +.Dv NULL +can be passed in. +.Pp +.Fn krb5_c_valid_enctype +returns true if +.Fa etype +is a valid encryption type. +.Pp +.Fn krb5_c_valid_cksumtype +returns true if +.Fa ctype +is a valid checksum type. +.Pp +.Fn krb5_c_is_keyed_cksum +return true if +.Fa ctype +is a keyed checksum type. +.Pp +.Fn krb5_c_is_coll_proof_cksum +returns true if +.Fa ctype +is a collition proof checksum type. +.Pp +.Fn krb5_c_keylengths +return the minimum length ( +.Fa inlength ) +bytes needed to create a key and the +length ( +.Fa keylength ) +of the resulting key +for the +.Fa enctype . +.Sh SEE ALSO +.Xr krb5 3 , +.Xr krb5_create_checksum 3 , +.Xr krb5_free_data 3 , +.Xr kerberos 8 diff --git a/lib/krb5/krb5_ccache.3 b/lib/krb5/krb5_ccache.3 new file mode 100644 index 0000000..3fca595 --- /dev/null +++ b/lib/krb5/krb5_ccache.3 @@ -0,0 +1,517 @@ +.\" Copyright (c) 2003 - 2005 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_ccache.3 22071 2007-11-14 20:04:50Z lha $ +.\" +.Dd October 19, 2005 +.Dt KRB5_CCACHE 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_ccache , +.Nm krb5_cc_cursor , +.Nm krb5_cc_ops , +.Nm krb5_fcc_ops , +.Nm krb5_mcc_ops , +.Nm krb5_cc_clear_mcred , +.Nm krb5_cc_close , +.Nm krb5_cc_copy_cache , +.Nm krb5_cc_default , +.Nm krb5_cc_default_name , +.Nm krb5_cc_destroy , +.Nm krb5_cc_end_seq_get , +.Nm krb5_cc_gen_new , +.Nm krb5_cc_get_full_name , +.Nm krb5_cc_get_name , +.Nm krb5_cc_get_ops , +.Nm krb5_cc_get_prefix_ops , +.Nm krb5_cc_get_principal , +.Nm krb5_cc_get_type , +.Nm krb5_cc_get_version , +.Nm krb5_cc_initialize , +.Nm krb5_cc_next_cred , +.Nm krb5_cc_next_cred_match , +.Nm krb5_cc_new_unique , +.Nm krb5_cc_register , +.Nm krb5_cc_remove_cred , +.Nm krb5_cc_resolve , +.Nm krb5_cc_retrieve_cred , +.Nm krb5_cc_set_default_name , +.Nm krb5_cc_set_flags , +.Nm krb5_cc_start_seq_get , +.Nm krb5_cc_store_cred +.Nd mange credential cache +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Pp +.Li "struct krb5_ccache;" +.Pp +.Li "struct krb5_cc_cursor;" +.Pp +.Li "struct krb5_cc_ops;" +.Pp +.Li "struct krb5_cc_ops *krb5_fcc_ops;" +.Pp +.Li "struct krb5_cc_ops *krb5_mcc_ops;" +.Pp +.Ft void +.Fo krb5_cc_clear_mcred +.Fa "krb5_creds *mcred" +.Fc +.Ft krb5_error_code +.Fo krb5_cc_close +.Fa "krb5_context context" +.Fa "krb5_ccache id" +.Fc +.Ft krb5_error_code +.Fo krb5_cc_copy_cache +.Fa "krb5_context context" +.Fa "const krb5_ccache from" +.Fa "krb5_ccache to" +.Fc +.Ft krb5_error_code +.Fo krb5_cc_default +.Fa "krb5_context context" +.Fa "krb5_ccache *id" +.Fc +.Ft "const char *" +.Fo krb5_cc_default_name +.Fa "krb5_context context" +.Fc +.Ft krb5_error_code +.Fo krb5_cc_destroy +.Fa "krb5_context context" +.Fa "krb5_ccache id" +.Fc +.Ft krb5_error_code +.Fo krb5_cc_end_seq_get +.Fa "krb5_context context" +.Fa "const krb5_ccache id" +.Fa "krb5_cc_cursor *cursor" +.Fc +.Ft krb5_error_code +.Fo krb5_cc_gen_new +.Fa "krb5_context context" +.Fa "const krb5_cc_ops *ops" +.Fa "krb5_ccache *id" +.Fc +.Ft krb5_error_code +.Fo krb5_cc_get_full_name +.Fa "krb5_context context" +.Fa "krb5_ccache id" +.Fa "char **str" +.Fc +.Ft "const char *" +.Fo krb5_cc_get_name +.Fa "krb5_context context" +.Fa "krb5_ccache id" +.Fc +.Ft krb5_error_code +.Fo krb5_cc_get_principal +.Fa "krb5_context context" +.Fa "krb5_ccache id" +.Fa "krb5_principal *principal" +.Fc +.Ft "const char *" +.Fo krb5_cc_get_type +.Fa "krb5_context context" +.Fa "krb5_ccache id" +.Fc +.Ft "const krb5_cc_ops *" +.Fo krb5_cc_get_ops +.Fa "krb5_context context" +.Fa "krb5_ccache id" +.Fc +.Ft "const krb5_cc_ops *" +.Fo krb5_cc_get_prefix_ops +.Fa "krb5_context context" +.Fa "const char *prefix" +.Fc +.Ft krb5_error_code +.Fo krb5_cc_get_version +.Fa "krb5_context context" +.Fa "const krb5_ccache id" +.Fc +.Ft krb5_error_code +.Fo krb5_cc_initialize +.Fa "krb5_context context" +.Fa "krb5_ccache id" +.Fa "krb5_principal primary_principal" +.Fc +.Ft krb5_error_code +.Fo krb5_cc_register +.Fa "krb5_context context" +.Fa "const krb5_cc_ops *ops" +.Fa "krb5_boolean override" +.Fc +.Ft krb5_error_code +.Fo krb5_cc_resolve +.Fa "krb5_context context" +.Fa "const char *name" +.Fa "krb5_ccache *id" +.Fc +.Ft krb5_error_code +.Fo krb5_cc_retrieve_cred +.Fa "krb5_context context" +.Fa "krb5_ccache id" +.Fa "krb5_flags whichfields" +.Fa "const krb5_creds *mcreds" +.Fa "krb5_creds *creds" +.Fc +.Ft krb5_error_code +.Fo krb5_cc_remove_cred +.Fa "krb5_context context" +.Fa "krb5_ccache id" +.Fa "krb5_flags which" +.Fa "krb5_creds *cred" +.Fc +.Ft krb5_error_code +.Fo krb5_cc_set_default_name +.Fa "krb5_context context" +.Fa "const char *name" +.Fc +.Ft krb5_error_code +.Fo krb5_cc_start_seq_get +.Fa "krb5_context context" +.Fa "const krb5_ccache id" +.Fa "krb5_cc_cursor *cursor" +.Fc +.Ft krb5_error_code +.Fo krb5_cc_store_cred +.Fa "krb5_context context" +.Fa "krb5_ccache id" +.Fa "krb5_creds *creds" +.Fc +.Ft krb5_error_code +.Fo krb5_cc_set_flags +.Fa "krb5_context context" +.Fa "krb5_cc_set_flags id" +.Fa "krb5_flags flags" +.Fc +.Ft krb5_error_code +.Fo krb5_cc_next_cred +.Fa "krb5_context context" +.Fa "const krb5_ccache id" +.Fa "krb5_cc_cursor *cursor" +.Fa "krb5_creds *creds" +.Fc +.Ft krb5_error_code +.Fo krb5_cc_next_cred_match +.Fa "krb5_context context" +.Fa "const krb5_ccache id" +.Fa "krb5_cc_cursor *cursor" +.Fa "krb5_creds *creds" +.Fa "krb5_flags whichfields" +.Fa "const krb5_creds *mcreds" +.Fc +.Ft krb5_error_code +.Fo krb5_cc_new_unique +.Fa "krb5_context context" +.Fa "const char *type" +.Fa "const char *hint" +.Fa "krb5_ccache *id" +.Fc +.Sh DESCRIPTION +The +.Li krb5_ccache +structure holds a Kerberos credential cache. +.Pp +The +.Li krb5_cc_cursor +structure holds current position in a credential cache when +iterating over the cache. +.Pp +The +.Li krb5_cc_ops +structure holds a set of operations that can me preformed on a +credential cache. +.Pp +There is no component inside +.Li krb5_ccache , +.Li krb5_cc_cursor +nor +.Li krb5_fcc_ops +that is directly referable. +.Pp +The +.Li krb5_creds +holds a Kerberos credential, see manpage for +.Xr krb5_creds 3 . +.Pp +.Fn krb5_cc_default_name +and +.Fn krb5_cc_set_default_name +gets and sets the default name for the +.Fa context . +.Pp +.Fn krb5_cc_default +opens the default credential cache in +.Fa id . +Return 0 or an error code. +.Pp +.Fn krb5_cc_gen_new +generates a new credential cache of type +.Fa ops +in +.Fa id . +Return 0 or an error code. +The Heimdal version of this function also runs +.Fn krb5_cc_initialize +on the credential cache, but since the MIT version doesn't, portable +code must call krb5_cc_initialize. +.Pp +.Fn krb5_cc_new_unique +generates a new unique credential cache of +.Fa type +in +.Fa id . +If type is +.Dv NULL , +the library chooses the default credential cache type. +The supplied +.Fa hint +(that can be +.Dv NULL ) +is a string that the credential cache type can use to base the name of +the credential on, this is to make it easier for the user to +differentiate the credentials. +The returned credential cache +.Fa id +should be freed using +.Fn krb5_cc_close +or +.Fn krb5_cc_destroy . +Returns 0 or an error code. +.Pp +.Fn krb5_cc_resolve +finds and allocates a credential cache in +.Fa id +from the specification in +.Fa residual . +If the credential cache name doesn't contain any colon (:), interpret it as a +file name. +Return 0 or an error code. +.Pp +.Fn krb5_cc_initialize +creates a new credential cache in +.Fa id +for +.Fa primary_principal . +Return 0 or an error code. +.Pp +.Fn krb5_cc_close +stops using the credential cache +.Fa id +and frees the related resources. +Return 0 or an error code. +.Fn krb5_cc_destroy +removes the credential cache +and closes (by calling +.Fn krb5_cc_close ) +.Fa id . +Return 0 or an error code. +.Pp +.Fn krb5_cc_copy_cache +copys the contents of +.Fa from +to +.Fa to . +.Pp +.Fn krb5_cc_get_full_name +returns the complete resolvable name of the credential cache +.Fa id +in +.Fa str . +.Fa str +should be freed with +.Xr free 3 . +Returns 0 or an error, on error +.Fa *str +is set to +.Dv NULL . +.Pp +.Fn krb5_cc_get_name +returns the name of the credential cache +.Fa id . +.Pp +.Fn krb5_cc_get_principal +returns the principal of +.Fa id +in +.Fa principal . +Return 0 or an error code. +.Pp +.Fn krb5_cc_get_type +returns the type of the credential cache +.Fa id . +.Pp +.Fn krb5_cc_get_ops +returns the ops of the credential cache +.Fa id . +.Pp +.Fn krb5_cc_get_version +returns the version of +.Fa id . +.Pp +.Fn krb5_cc_register +Adds a new credential cache type with operations +.Fa ops , +overwriting any existing one if +.Fa override . +Return an error code or 0. +.Pp +.Fn krb5_cc_get_prefix_ops +Get the cc ops that is registered in +.Fa context +to handle the +.Fa prefix . +Returns +.Dv NULL +if ops not found. +.Pp +.Fn krb5_cc_remove_cred +removes the credential identified by +.Fa ( cred , +.Fa which ) +from +.Fa id . +.Pp +.Fn krb5_cc_store_cred +stores +.Fa creds +in the credential cache +.Fa id . +Return 0 or an error code. +.Pp +.Fn krb5_cc_set_flags +sets the flags of +.Fa id +to +.Fa flags . +.Pp +.Fn krb5_cc_clear_mcred +clears the +.Fa mcreds +argument so it is reset and can be used with +.Fa krb5_cc_retrieve_cred . +.Pp +.Fn krb5_cc_retrieve_cred , +retrieves the credential identified by +.Fa mcreds +(and +.Fa whichfields ) +from +.Fa id +in +.Fa creds . +.Fa creds +should be freed using +.Fn krb5_free_cred_contents . +Return 0 or an error code. +.Pp +.Fn krb5_cc_start_seq_get +initiates the +.Li krb5_cc_cursor +structure to be used for iteration over the credential cache. +.Pp +.Fn krb5_cc_next_cred +retrieves the next cred pointed to by +.Fa ( id , +.Fa cursor ) +in +.Fa creds , +and advance +.Fa cursor . +Return 0 or an error code. +.Pp +.Fn krb5_cc_next_cred_match +is similar to +.Fn krb5_cc_next_cred +except that it will only return creds matching +.Fa whichfields +and +.Fa mcreds +(as interpreted by +.Xr krb5_compare_creds 3 . ) +.Pp +.Fn krb5_cc_end_seq_get +Destroys the cursor +.Fa cursor . +.Sh EXAMPLE +This is a minimalistic version of +.Nm klist . +.Pp +.Bd -literal +#include <krb5.h> + +int +main (int argc, char **argv) +{ + krb5_context context; + krb5_cc_cursor cursor; + krb5_error_code ret; + krb5_ccache id; + krb5_creds creds; + + if (krb5_init_context (&context) != 0) + errx(1, "krb5_context"); + + ret = krb5_cc_default (context, &id); + if (ret) + krb5_err(context, 1, ret, "krb5_cc_default"); + + ret = krb5_cc_start_seq_get(context, id, &cursor); + if (ret) + krb5_err(context, 1, ret, "krb5_cc_start_seq_get"); + + while((ret = krb5_cc_next_cred(context, id, &cursor, &creds)) == 0){ + char *principal; + + krb5_unparse_name_short(context, creds.server, &principal); + printf("principal: %s\\n", principal); + free(principal); + krb5_free_cred_contents (context, &creds); + } + ret = krb5_cc_end_seq_get(context, id, &cursor); + if (ret) + krb5_err(context, 1, ret, "krb5_cc_end_seq_get"); + + krb5_cc_close(context, id); + + krb5_free_context(context); + return 0; +} +.Ed +.Sh SEE ALSO +.Xr krb5 3 , +.Xr krb5.conf 5 , +.Xr kerberos 8 diff --git a/lib/krb5/krb5_ccapi.h b/lib/krb5/krb5_ccapi.h new file mode 100644 index 0000000..59a3842 --- /dev/null +++ b/lib/krb5/krb5_ccapi.h @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $Id: krb5_ccapi.h 22090 2007-12-02 23:23:43Z lha $ */ + +#ifndef KRB5_CCAPI_H +#define KRB5_CCAPI_H 1 + +#include <krb5-types.h> + +enum { + cc_credentials_v5 = 2 +}; + +enum { + ccapi_version_3 = 3, + ccapi_version_4 = 4 +}; + +enum { + ccNoError = 0, + + ccIteratorEnd = 201, + ccErrBadParam, + ccErrNoMem, + ccErrInvalidContext, + ccErrInvalidCCache, + + ccErrInvalidString, /* 206 */ + ccErrInvalidCredentials, + ccErrInvalidCCacheIterator, + ccErrInvalidCredentialsIterator, + ccErrInvalidLock, + + ccErrBadName, /* 211 */ + ccErrBadCredentialsVersion, + ccErrBadAPIVersion, + ccErrContextLocked, + ccErrContextUnlocked, + + ccErrCCacheLocked, /* 216 */ + ccErrCCacheUnlocked, + ccErrBadLockType, + ccErrNeverDefault, + ccErrCredentialsNotFound, + + ccErrCCacheNotFound, /* 221 */ + ccErrContextNotFound, + ccErrServerUnavailable, + ccErrServerInsecure, + ccErrServerCantBecomeUID, + + ccErrTimeOffsetNotSet /* 226 */ +}; + +typedef int32_t cc_int32; +typedef uint32_t cc_uint32; +typedef struct cc_context_t *cc_context_t; +typedef struct cc_ccache_t *cc_ccache_t; +typedef struct cc_ccache_iterator_t *cc_ccache_iterator_t; +typedef struct cc_credentials_v5_t cc_credentials_v5_t; +typedef struct cc_credentials_t *cc_credentials_t; +typedef struct cc_credentials_iterator_t *cc_credentials_iterator_t; +typedef struct cc_string_t *cc_string_t; +typedef time_t cc_time_t; + +typedef struct cc_data { + cc_uint32 type; + cc_uint32 length; + void *data; +} cc_data; + +struct cc_credentials_v5_t { + char *client; + char *server; + cc_data keyblock; + cc_time_t authtime; + cc_time_t starttime; + cc_time_t endtime; + cc_time_t renew_till; + cc_uint32 is_skey; + cc_uint32 ticket_flags; +#define KRB5_CCAPI_TKT_FLG_FORWARDABLE 0x40000000 +#define KRB5_CCAPI_TKT_FLG_FORWARDED 0x20000000 +#define KRB5_CCAPI_TKT_FLG_PROXIABLE 0x10000000 +#define KRB5_CCAPI_TKT_FLG_PROXY 0x08000000 +#define KRB5_CCAPI_TKT_FLG_MAY_POSTDATE 0x04000000 +#define KRB5_CCAPI_TKT_FLG_POSTDATED 0x02000000 +#define KRB5_CCAPI_TKT_FLG_INVALID 0x01000000 +#define KRB5_CCAPI_TKT_FLG_RENEWABLE 0x00800000 +#define KRB5_CCAPI_TKT_FLG_INITIAL 0x00400000 +#define KRB5_CCAPI_TKT_FLG_PRE_AUTH 0x00200000 +#define KRB5_CCAPI_TKT_FLG_HW_AUTH 0x00100000 +#define KRB5_CCAPI_TKT_FLG_TRANSIT_POLICY_CHECKED 0x00080000 +#define KRB5_CCAPI_TKT_FLG_OK_AS_DELEGATE 0x00040000 +#define KRB5_CCAPI_TKT_FLG_ANONYMOUS 0x00020000 + cc_data **addresses; + cc_data ticket; + cc_data second_ticket; + cc_data **authdata; +}; + + +typedef struct cc_string_functions { + cc_int32 (*release)(cc_string_t); +} cc_string_functions; + +struct cc_string_t { + const char *data; + const cc_string_functions *func; +}; + +typedef struct cc_credentials_union { + cc_int32 version; + union { + cc_credentials_v5_t* credentials_v5; + } credentials; +} cc_credentials_union; + +struct cc_credentials_functions { + cc_int32 (*release)(cc_credentials_t); + cc_int32 (*compare)(cc_credentials_t, cc_credentials_t, cc_uint32*); +}; + +struct cc_credentials_t { + const cc_credentials_union* data; + const struct cc_credentials_functions* func; +}; + +struct cc_credentials_iterator_functions { + cc_int32 (*release)(cc_credentials_iterator_t); + cc_int32 (*next)(cc_credentials_iterator_t, cc_credentials_t*); +}; + +struct cc_credentials_iterator_t { + const struct cc_credentials_iterator_functions *func; +}; + +struct cc_ccache_iterator_functions { + cc_int32 (*release) (cc_ccache_iterator_t); + cc_int32 (*next)(cc_ccache_iterator_t, cc_ccache_t*); +}; + +struct cc_ccache_iterator_t { + const struct cc_ccache_iterator_functions* func; +}; + +typedef struct cc_ccache_functions { + cc_int32 (*release)(cc_ccache_t); + cc_int32 (*destroy)(cc_ccache_t); + cc_int32 (*set_default)(cc_ccache_t); + cc_int32 (*get_credentials_version)(cc_ccache_t, cc_uint32*); + cc_int32 (*get_name)(cc_ccache_t, cc_string_t*); + cc_int32 (*get_principal)(cc_ccache_t, cc_uint32, cc_string_t*); + cc_int32 (*set_principal)(cc_ccache_t, cc_uint32, const char*); + cc_int32 (*store_credentials)(cc_ccache_t, const cc_credentials_union*); + cc_int32 (*remove_credentials)(cc_ccache_t, cc_credentials_t); + cc_int32 (*new_credentials_iterator)(cc_ccache_t, + cc_credentials_iterator_t*); + cc_int32 (*move)(cc_ccache_t, cc_ccache_t); + cc_int32 (*lock)(cc_ccache_t, cc_uint32, cc_uint32); + cc_int32 (*unlock)(cc_ccache_t); + cc_int32 (*get_last_default_time)(cc_ccache_t, cc_time_t*); + cc_int32 (*get_change_time)(cc_ccache_t, cc_time_t*); + cc_int32 (*compare)(cc_ccache_t, cc_ccache_t, cc_uint32*); + cc_int32 (*get_kdc_time_offset)(cc_ccache_t, cc_int32, cc_time_t *); + cc_int32 (*set_kdc_time_offset)(cc_ccache_t, cc_int32, cc_time_t); + cc_int32 (*clear_kdc_time_offset)(cc_ccache_t, cc_int32); +} cc_ccache_functions; + +struct cc_ccache_t { + const cc_ccache_functions *func; +}; + +struct cc_context_functions { + cc_int32 (*release)(cc_context_t); + cc_int32 (*get_change_time)(cc_context_t, cc_time_t *); + cc_int32 (*get_default_ccache_name)(cc_context_t, cc_string_t*); + cc_int32 (*open_ccache)(cc_context_t, const char*, cc_ccache_t *); + cc_int32 (*open_default_ccache)(cc_context_t, cc_ccache_t*); + cc_int32 (*create_ccache)(cc_context_t,const char*, cc_uint32, + const char*, cc_ccache_t*); + cc_int32 (*create_default_ccache)(cc_context_t, cc_uint32, + const char*, cc_ccache_t*); + cc_int32 (*create_new_ccache)(cc_context_t, cc_uint32, + const char*, cc_ccache_t*); + cc_int32 (*new_ccache_iterator)(cc_context_t, cc_ccache_iterator_t*); + cc_int32 (*lock)(cc_context_t, cc_uint32, cc_uint32); + cc_int32 (*unlock)(cc_context_t); + cc_int32 (*compare)(cc_context_t, cc_context_t, cc_uint32*); +}; + +struct cc_context_t { + const struct cc_context_functions* func; +}; + +typedef cc_int32 +(*cc_initialize_func)(cc_context_t*, cc_int32, cc_int32 *, char const **); + +#endif /* KRB5_CCAPI_H */ diff --git a/lib/krb5/krb5_check_transited.3 b/lib/krb5/krb5_check_transited.3 new file mode 100644 index 0000000..65ce077 --- /dev/null +++ b/lib/krb5/krb5_check_transited.3 @@ -0,0 +1,106 @@ +.\" Copyright (c) 2004, 2006 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_check_transited.3 17382 2006-05-01 07:09:16Z lha $ +.\" +.Dd May 1, 2006 +.Dt KRB5_CHECK_TRANSITED 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_check_transited , +.Nm krb5_check_transited_realms , +.Nm krb5_domain_x500_decode , +.Nm krb5_domain_x500_encode +.Nd realm transit verification and encoding/decoding functions +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Ft krb5_error_code +.Fo krb5_check_transited +.Fa "krb5_context context" +.Fa "krb5_const_realm client_realm" +.Fa "krb5_const_realm server_realm" +.Fa "krb5_realm *realms" +.Fa "int num_realms" +.Fa "int *bad_realm" +.Fc +.Ft krb5_error_code +.Fo krb5_check_transited_realms +.Fa "krb5_context context" +.Fa "const char *const *realms" +.Fa "int num_realms" +.Fa "int *bad_realm" +.Fc +.Ft krb5_error_code +.Fo krb5_domain_x500_decode +.Fa "krb5_context context" +.Fa "krb5_data tr" +.Fa "char ***realms" +.Fa "int *num_realms" +.Fa "const char *client_realm" +.Fa "const char *server_realm" +.Fc +.Ft krb5_error_code +.Fo krb5_domain_x500_encode +.Fa "char **realms" +.Fa "int num_realms" +.Fa "krb5_data *encoding" +.Fc +.Sh DESCRIPTION +.Fn krb5_check_transited +checks the path from +.Fa client_realm +to +.Fa server_realm +where +.Fa realms +and +.Fa num_realms +is the realms between them. +If the function returns an error value, +.Fa bad_realm +will be set to the realm in the list causing the error. +.Fn krb5_check_transited +is used internally by the KDC and libkrb5 and should not be called by +client applications. +.Pp +.Fn krb5_check_transited_realms +is deprecated. +.Pp +.Fn krb5_domain_x500_encode +and +.Fn krb5_domain_x500_decode +encodes and decodes the realm names in the X500 format that Kerberos +uses to describe the transited realms in krbtgts. +.Sh SEE ALSO +.Xr krb5 3 , +.Xr krb5.conf 5 diff --git a/lib/krb5/krb5_compare_creds.3 b/lib/krb5/krb5_compare_creds.3 new file mode 100644 index 0000000..9fd2bbb --- /dev/null +++ b/lib/krb5/krb5_compare_creds.3 @@ -0,0 +1,104 @@ +.\" Copyright (c) 2004-2005 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_compare_creds.3 15110 2005-05-10 09:21:06Z lha $ +.\" +.Dd May 10, 2005 +.Dt KRB5_COMPARE_CREDS 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_compare_creds +.Nd compare Kerberos 5 credentials +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Ft krb5_boolean +.Fo krb5_compare_creds +.Fa "krb5_context context" +.Fa "krb5_flags whichfields" +.Fa "const krb5_creds *mcreds" +.Fa "const krb5_creds *creds" +.Fc +.Sh DESCRIPTION +.Fn krb5_compare_creds +compares +.Fa mcreds +(usually filled in by the application) +to +.Fa creds +(most often from a credentials cache) +and return +.Dv TRUE +if they are equal. +Unless +.Va mcreds-\*[Gt]server +is +.Dv NULL , +the service of the credentials are always compared. If the client +name in +.Fa mcreds +is present, the client names are also compared. This function is +normally only called indirectly via +.Xr krb5_cc_retrieve_cred 3 . +.Pp +The following flags, set in +.Fa whichfields , +affects the comparison: +.Bl -tag -width KRB5_TC_MATCH_SRV_NAMEONLY -compact -offset indent +.It KRB5_TC_MATCH_SRV_NAMEONLY +Consider all realms equal when comparing the service principal. +.It KRB5_TC_MATCH_KEYTYPE +Compare enctypes. +.It KRB5_TC_MATCH_FLAGS_EXACT +Make sure that the ticket flags are identical. +.It KRB5_TC_MATCH_FLAGS +Make sure that all ticket flags set in +.Fa mcreds +are also present in +.Fa creds . +.It KRB5_TC_MATCH_TIMES_EXACT +Compares the ticket times exactly. +.It KRB5_TC_MATCH_TIMES +Compares only the expiration times of the creds. +.It KRB5_TC_MATCH_AUTHDATA +Compares the authdata fields. +.It KRB5_TC_MATCH_2ND_TKT +Compares the second tickets (used by user-to-user authentication). +.It KRB5_TC_MATCH_IS_SKEY +Compares the existance of the second ticket. +.El +.Sh SEE ALSO +.Xr krb5 3 , +.Xr krb5_cc_retrieve_cred 3 , +.Xr krb5_creds 3 , +.Xr krb5_get_init_creds 3 , +.Xr kerberos 8 diff --git a/lib/krb5/krb5_config.3 b/lib/krb5/krb5_config.3 new file mode 100644 index 0000000..9c302ae --- /dev/null +++ b/lib/krb5/krb5_config.3 @@ -0,0 +1,307 @@ +.\" Copyright (c) 2000 - 2007 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" +.\" $Id: krb5_config.3 21905 2007-08-10 10:16:45Z lha $ +.\" +.Dd August 10, 2007 +.Dt KRB5_CONFIG_GET 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_config_file_free , +.Nm krb5_config_free_strings , +.Nm krb5_config_get , +.Nm krb5_config_get_bool , +.Nm krb5_config_get_bool_default , +.Nm krb5_config_get_int , +.Nm krb5_config_get_int_default , +.Nm krb5_config_get_list , +.Nm krb5_config_get_next , +.Nm krb5_config_get_string , +.Nm krb5_config_get_string_default , +.Nm krb5_config_get_strings , +.Nm krb5_config_get_time , +.Nm krb5_config_get_time_default , +.Nm krb5_config_parse_file , +.Nm krb5_config_parse_file_multi , +.Nm krb5_config_vget , +.Nm krb5_config_vget_bool , +.Nm krb5_config_vget_bool_default , +.Nm krb5_config_vget_int , +.Nm krb5_config_vget_int_default , +.Nm krb5_config_vget_list , +.Nm krb5_config_vget_next , +.Nm krb5_config_vget_string , +.Nm krb5_config_vget_string_default , +.Nm krb5_config_vget_strings , +.Nm krb5_config_vget_time , +.Nm krb5_config_vget_time_default +.Nd get configuration value +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Ft krb5_error_code +.Fo krb5_config_file_free +.Fa "krb5_context context" +.Fa "krb5_config_section *s" +.Fc +.Ft void +.Fo krb5_config_free_strings +.Fa "char **strings" +.Fc +.Ft "const void *" +.Fo krb5_config_get +.Fa "krb5_context context" +.Fa "const krb5_config_section *c" +.Fa "int type" +.Fa "..." +.Fc +.Ft krb5_boolean +.Fo krb5_config_get_bool +.Fa "krb5_context context" +.Fa "krb5_config_section *c" +.Fa "..." +.Fc +.Ft krb5_boolean +.Fo krb5_config_get_bool_default +.Fa "krb5_context context" +.Fa "krb5_config_section *c" +.Fa "krb5_boolean def_value" +.Fa "..." +.Fc +.Ft int +.Fo krb5_config_get_int +.Fa "krb5_context context" +.Fa "krb5_config_section *c" +.Fa "..." +.Fc +.Ft int +.Fo krb5_config_get_int_default +.Fa "krb5_context context" +.Fa "krb5_config_section *c" +.Fa "int def_value" +.Fa "..." +.Fc +.Ft const char* +.Fo krb5_config_get_string +.Fa "krb5_context context" +.Fa "krb5_config_section *c" +.Fa "..." +.Fc +.Ft const char* +.Fo krb5_config_get_string_default +.Fa "krb5_context context" +.Fa "krb5_config_section *c" +.Fa "const char *def_value" +.Fa "..." +.Fc +.Ft "char**" +.Fo krb5_config_get_strings +.Fa "krb5_context context" +.Fa "const krb5_config_section *c" +.Fa "..." +.Fc +.Ft int +.Fo krb5_config_get_time +.Fa "krb5_context context" +.Fa "krb5_config_section *c" +.Fa "..." +.Fc +.Ft int +.Fo krb5_config_get_time_default +.Fa "krb5_context context" +.Fa "krb5_config_section *c" +.Fa "int def_value" +.Fa "..." +.Fc +.Ft krb5_error_code +.Fo krb5_config_parse_file +.Fa "krb5_context context" +.Fa "const char *fname" +.Fa "krb5_config_section **res" +.Fc +.Ft krb5_error_code +.Fo krb5_config_parse_file_multi +.Fa "krb5_context context" +.Fa "const char *fname" +.Fa "krb5_config_section **res" +.Fc +.Ft "const void *" +.Fo krb5_config_vget +.Fa "krb5_context context" +.Fa "const krb5_config_section *c" +.Fa "int type" +.Fa "va_list args" +.Fc +.Ft krb5_boolean +.Fo krb5_config_vget_bool +.Fa "krb5_context context" +.Fa "const krb5_config_section *c" +.Fa "va_list args" +.Fc +.Ft krb5_boolean +.Fo krb5_config_vget_bool_default +.Fa "krb5_context context" +.Fa "const krb5_config_section *c" +.Fa "krb5_boolean def_value" +.Fa "va_list args" +.Fc +.Ft int +.Fo krb5_config_vget_int +.Fa "krb5_context context" +.Fa "const krb5_config_section *c" +.Fa "va_list args" +.Fc +.Ft int +.Fo krb5_config_vget_int_default +.Fa "krb5_context context" +.Fa "const krb5_config_section *c" +.Fa "int def_value" +.Fa "va_list args" +.Fc +.Ft "const krb5_config_binding *" +.Fo krb5_config_vget_list +.Fa "krb5_context context" +.Fa "const krb5_config_section *c" +.Fa "va_list args" +.Fc +.Ft "const void *" +.Fo krb5_config_vget_next +.Fa "krb5_context context" +.Fa "const krb5_config_section *c" +.Fa "const krb5_config_binding **pointer" +.Fa "int type" +.Fa "va_list args" +.Fc +.Ft "const char *" +.Fo krb5_config_vget_string +.Fa "krb5_context context" +.Fa "const krb5_config_section *c" +.Fa "va_list args" +.Fc +.Ft "const char *" +.Fo krb5_config_vget_string_default +.Fa "krb5_context context" +.Fa "const krb5_config_section *c" +.Fa "const char *def_value" +.Fa "va_list args" +.Fc +.Ft char ** +.Fo krb5_config_vget_strings +.Fa "krb5_context context" +.Fa "const krb5_config_section *c" +.Fa "va_list args" +.Fc +.Ft int +.Fo krb5_config_vget_time +.Fa "krb5_context context" +.Fa "const krb5_config_section *c" +.Fa "va_list args" +.Fc +.Ft int +.Fo krb5_config_vget_time_default +.Fa "krb5_context context" +.Fa "const krb5_config_section *c" +.Fa "int def_value" +.Fa "va_list args" +.Fc +.Sh DESCRIPTION +These functions get values from the +.Xr krb5.conf 5 +configuration file, or another configuration database specified by the +.Fa c +parameter. +.Pp +The variable arguments should be a list of strings naming each +subsection to look for. For example: +.Bd -literal -offset indent +krb5_config_get_bool_default(context, NULL, FALSE, + "libdefaults", "log_utc", NULL); +.Ed +.Pp +gets the boolean value for the +.Dv log_utc +option, defaulting to +.Dv FALSE . +.Pp +.Fn krb5_config_get_bool_default +will convert the option value to a boolean value, where +.Sq yes , +.Sq true , +and any non-zero number means +.Dv TRUE , +and any other value +.Dv FALSE . +.Pp +.Fn krb5_config_get_int_default +will convert the value to an integer. +.Pp +.Fn krb5_config_get_time_default +will convert the value to a period of time (not a time stamp) in +seconds, so the string +.Sq 2 weeks +will be converted to +1209600 (2 * 7 * 24 * 60 * 60). +.Pp +.Fn krb5_config_get_string +returns a +.Ft "const char *" +to a string in the configuration database. The string not be valid +after reload of the configuration database +.\" or a call to .Fn krb5_config_set_string , +so a caller should make a local copy if its need to keep the database. +.Pp +.Fn krb5_config_free_strings +free +.Fa strings +as returned by +.Fn krb5_config_get_strings +and +.Fn krb5_config_vget_strings . +If the argument +.Fa strings +is a +.Dv NULL +pointer, no action occurs. +.Pp +.Fn krb5_config_file_free +free the result of +.Fn krb5_config_parse_file +and +.Fn krb5_config_parse_file_multi . +.Sh SEE ALSO +.Xr krb5_appdefault 3 , +.Xr krb5_init_context 3 , +.Xr krb5.conf 5 +.Sh BUGS +For the default functions, other than for the string case, there's no +way to tell whether there was a value specified or not. diff --git a/lib/krb5/krb5_context.3 b/lib/krb5/krb5_context.3 new file mode 100644 index 0000000..5bfcc26 --- /dev/null +++ b/lib/krb5/krb5_context.3 @@ -0,0 +1,56 @@ +.\" Copyright (c) 2001 - 2003 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_context.3 12329 2003-05-26 14:09:04Z lha $ +.\" +.Dd January 21, 2001 +.Dt KRB5_CONTEXT 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_context +.Nd krb5 state structure +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Sh DESCRIPTION +The +.Nm +structure is designed to hold all per thread state. All global +variables that are context specific are stored in this structure, +including default encryption types, credentials-cache (ticket file), and +default realms. +.Pp +The internals of the structure should never be accessed directly, +functions exist for extracting information. +.Sh SEE ALSO +.Xr krb5_init_context 3 , +.Xr kerberos 8 diff --git a/lib/krb5/krb5_create_checksum.3 b/lib/krb5/krb5_create_checksum.3 new file mode 100644 index 0000000..43d5b4e --- /dev/null +++ b/lib/krb5/krb5_create_checksum.3 @@ -0,0 +1,226 @@ +.\" Copyright (c) 1999-2005 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_create_checksum.3 15921 2005-08-12 09:01:22Z lha $ +.\" +.Dd August 12, 2005 +.Dt NAME 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_checksum , +.Nm krb5_checksum_disable , +.Nm krb5_checksum_is_collision_proof , +.Nm krb5_checksum_is_keyed , +.Nm krb5_checksumsize , +.Nm krb5_cksumtype_valid , +.Nm krb5_copy_checksum , +.Nm krb5_create_checksum , +.Nm krb5_crypto_get_checksum_type +.Nm krb5_free_checksum , +.Nm krb5_free_checksum_contents , +.Nm krb5_hmac , +.Nm krb5_verify_checksum +.Nd creates, handles and verifies checksums +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Pp +.Li "typedef Checksum krb5_checksum;" +.Ft void +.Fo krb5_checksum_disable +.Fa "krb5_context context" +.Fa "krb5_cksumtype type" +.Fc +.Ft krb5_boolean +.Fo krb5_checksum_is_collision_proof +.Fa "krb5_context context" +.Fa "krb5_cksumtype type" +.Fc +.Ft krb5_boolean +.Fo krb5_checksum_is_keyed +.Fa "krb5_context context" +.Fa "krb5_cksumtype type" +.Fc +.Ft krb5_error_code +.Fo krb5_cksumtype_valid +.Fa "krb5_context context" +.Fa "krb5_cksumtype ctype" +.Fc +.Ft krb5_error_code +.Fo krb5_checksumsize +.Fa "krb5_context context" +.Fa "krb5_cksumtype type" +.Fa "size_t *size" +.Fc +.Ft krb5_error_code +.Fo krb5_create_checksum +.Fa "krb5_context context" +.Fa "krb5_crypto crypto" +.Fa "krb5_key_usage usage" +.Fa "int type" +.Fa "void *data" +.Fa "size_t len" +.Fa "Checksum *result" +.Fc +.Ft krb5_error_code +.Fo krb5_verify_checksum +.Fa "krb5_context context" +.Fa "krb5_crypto crypto" +.Fa "krb5_key_usage usage" +.Fa "void *data" +.Fa "size_t len" +.Fa "Checksum *cksum" +.Fc +.Ft krb5_error_code +.Fo krb5_crypto_get_checksum_type +.Fa "krb5_context context" +.Fa "krb5_crypto crypto" +.Fa "krb5_cksumtype *type" +.Fc +.Ft void +.Fo krb5_free_checksum +.Fa "krb5_context context" +.Fa "krb5_checksum *cksum" +.Fc +.Ft void +.Fo krb5_free_checksum_contents +.Fa "krb5_context context" +.Fa "krb5_checksum *cksum" +.Fc +.Ft krb5_error_code +.Fo krb5_hmac +.Fa "krb5_context context" +.Fa "krb5_cksumtype cktype" +.Fa "const void *data" +.Fa "size_t len" +.Fa "unsigned usage" +.Fa "krb5_keyblock *key" +.Fa "Checksum *result" +.Fc +.Ft krb5_error_code +.Fo krb5_copy_checksum +.Fa "krb5_context context" +.Fa "const krb5_checksum *old" +.Fa "krb5_checksum **new" +.Fc +.Sh DESCRIPTION +The +.Li krb5_checksum +structure holds a Kerberos checksum. +There is no component inside +.Li krb5_checksum +that is directly referable. +.Pp +The functions are used to create and verify checksums. +.Fn krb5_create_checksum +creates a checksum of the specified data, and puts it in +.Fa result . +If +.Fa crypto +is +.Dv NULL , +.Fa usage_or_type +specifies the checksum type to use; it must not be keyed. Otherwise +.Fa crypto +is an encryption context created by +.Fn krb5_crypto_init , +and +.Fa usage_or_type +specifies a key-usage. +.Pp +.Fn krb5_verify_checksum +verifies the +.Fa checksum +against the provided data. +.Pp +.Fn krb5_checksum_is_collision_proof +returns true is the specified checksum is collision proof (that it's +very unlikely that two strings has the same hash value, and that it's +hard to find two strings that has the same hash). Examples of +collision proof checksums are MD5, and SHA1, while CRC32 is not. +.Pp +.Fn krb5_checksum_is_keyed +returns true if the specified checksum type is keyed (that the hash +value is a function of both the data, and a separate key). Examples of +keyed hash algorithms are HMAC-SHA1-DES3, and RSA-MD5-DES. The +.Dq plain +hash functions MD5, and SHA1 are not keyed. +.Pp +.Fn krb5_crypto_get_checksum_type +returns the checksum type that will be used when creating a checksum for the given +.Fa crypto +context. +This function is useful in combination with +.Fn krb5_checksumsize +when you want to know the size a checksum will +use when you create it. +.Pp +.Fn krb5_cksumtype_valid +returns 0 or an error if the checksumtype is implemented and not +currently disabled in this kerberos library. +.Pp +.Fn krb5_checksumsize +returns the size of the outdata of checksum function. +.Pp +.Fn krb5_copy_checksum +returns a copy of the checksum +.Fn krb5_free_checksum +should use used to free the +.Fa new +checksum. +.Pp +.Fn krb5_free_checksum +free the checksum and the content of the checksum. +.Pp +.Fn krb5_free_checksum_contents +frees the content of checksum in +.Fa cksum . +.Pp +.Fn krb5_hmac +calculates the HMAC over +.Fa data +(with length +.Fa len ) +using the keyusage +.Fa usage +and keyblock +.Fa key . +Note that keyusage is not always used in checksums. +.Pp +.Nm krb5_checksum_disable +globally disables the checksum type. +.\" .Sh EXAMPLE +.\" .Sh BUGS +.Sh SEE ALSO +.Xr krb5_crypto_init 3 , +.Xr krb5_c_encrypt 3 , +.Xr krb5_encrypt 3 diff --git a/lib/krb5/krb5_creds.3 b/lib/krb5/krb5_creds.3 new file mode 100644 index 0000000..9eb9a2b --- /dev/null +++ b/lib/krb5/krb5_creds.3 @@ -0,0 +1,119 @@ +.\" Copyright (c) 2004, 2006 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_creds.3 17383 2006-05-01 07:13:03Z lha $ +.\" +.Dd May 1, 2006 +.Dt KRB5_CREDS 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_creds , +.Nm krb5_copy_creds , +.Nm krb5_copy_creds_contents , +.Nm krb5_free_creds , +.Nm krb5_free_cred_contents +.Nd Kerberos 5 credential handling functions +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Ft krb5_error_code +.Fo krb5_copy_creds +.Fa "krb5_context context" +.Fa "const krb5_creds *incred" +.Fa "krb5_creds **outcred" +.Fc +.Ft krb5_error_code +.Fo krb5_copy_creds_contents +.Fa "krb5_context context" +.Fa "const krb5_creds *incred" +.Fa "krb5_creds *outcred" +.Fc +.Ft krb5_error_code +.Fo krb5_free_creds +.Fa "krb5_context context" +.Fa "krb5_creds *outcred" +.Fc +.Ft krb5_error_code +.Fo krb5_free_cred_contents +.Fa "krb5_context context" +.Fa "krb5_creds *cred" +.Fc +.Sh DESCRIPTION +.Vt krb5_creds +holds Kerberos credentials: +.Bd -literal -offset +typedef struct krb5_creds { + krb5_principal client; + krb5_principal server; + krb5_keyblock session; + krb5_times times; + krb5_data ticket; + krb5_data second_ticket; + krb5_authdata authdata; + krb5_addresses addresses; + krb5_ticket_flags flags; +} krb5_creds; +.Ed +.Pp +.Fn krb5_copy_creds +makes a copy of +.Fa incred +to +.Fa outcred . +.Fa outcred +should be freed with +.Fn krb5_free_creds +by the caller. +.Pp +.Fn krb5_copy_creds_contents +makes a copy of the content of +.Fa incred +to +.Fa outcreds . +.Fa outcreds +should be freed by the called with +.Fn krb5_free_creds_contents . +.Pp +.Fn krb5_free_creds +frees the content of the +.Fa cred +structure and the structure itself. +.Pp +.Fn krb5_free_cred_contents +frees the content of the +.Fa cred +structure. +.Sh SEE ALSO +.Xr krb5 3 , +.Xr krb5_compare_creds 3 , +.Xr krb5_get_init_creds 3 , +.Xr kerberos 8 diff --git a/lib/krb5/krb5_crypto_init.3 b/lib/krb5/krb5_crypto_init.3 new file mode 100644 index 0000000..822006e --- /dev/null +++ b/lib/krb5/krb5_crypto_init.3 @@ -0,0 +1,67 @@ +.\" Copyright (c) 1999 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_crypto_init.3 13563 2004-03-20 12:00:01Z lha $ +.\" +.Dd April 7, 1999 +.Dt NAME 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_crypto_destroy , +.Nm krb5_crypto_init +.Nd encryption support in krb5 +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Ft krb5_error_code +.Fn krb5_crypto_init "krb5_context context" "krb5_keyblock *key" "krb5_enctype enctype" "krb5_crypto *crypto" +.Ft krb5_error_code +.Fn krb5_crypto_destroy "krb5_context context" "krb5_crypto crypto" +.Sh DESCRIPTION +Heimdal exports parts of the Kerberos crypto interface for applications. +.Pp +Each kerberos encrytion/checksum function takes a crypto context. +.Pp +To setup and destroy crypto contextes there are two functions +.Fn krb5_crypto_init +and +.Fn krb5_crypto_destroy . +The encryption type to use is taken from the key, but can be overridden +with the +.Fa enctype parameter . +This can be useful for encryptions types which is compatiable (DES for +example). +.\" .Sh EXAMPLE +.\" .Sh BUGS +.Sh SEE ALSO +.Xr krb5_create_checksum 3 , +.Xr krb5_encrypt 3 diff --git a/lib/krb5/krb5_data.3 b/lib/krb5/krb5_data.3 new file mode 100644 index 0000000..2ccff19 --- /dev/null +++ b/lib/krb5/krb5_data.3 @@ -0,0 +1,159 @@ +.\" Copyright (c) 2003 - 2005, 2007 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_data.3 20040 2007-01-23 20:35:12Z lha $ +.\" +.Dd Jan 23, 2007 +.Dt KRB5_DATA 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_data , +.Nm krb5_data_zero , +.Nm krb5_data_free , +.Nm krb5_free_data_contents , +.Nm krb5_free_data , +.Nm krb5_data_alloc , +.Nm krb5_data_realloc , +.Nm krb5_data_copy , +.Nm krb5_copy_data , +.Nm krb5_data_cmp +.Nd operates on the Kerberos datatype krb5_data +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Pp +.Li "struct krb5_data;" +.Ft void +.Fn krb5_data_zero "krb5_data *p" +.Ft void +.Fn krb5_data_free "krb5_data *p" +.Ft void +.Fn krb5_free_data_contents "krb5_context context" "krb5_data *p" +.Ft void +.Fn krb5_free_data "krb5_context context" "krb5_data *p" +.Ft krb5_error_code +.Fn krb5_data_alloc "krb5_data *p" "int len" +.Ft krb5_error_code +.Fn krb5_data_realloc "krb5_data *p" "int len" +.Ft krb5_error_code +.Fn krb5_data_copy "krb5_data *p" "const void *data" "size_t len" +.Ft krb5_error_code +.Fn krb5_copy_data "krb5_context context" "const krb5_data *indata" "krb5_data **outdata" +.Ft krb5_error_code +.Fn krb5_data_cmp "const krb5_data *data1" "const krb5_data *data2" +.Sh DESCRIPTION +The +.Li krb5_data +structure holds a data element. +The structure contains two public accessible elements +.Fa length +(the length of data) +and +.Fa data +(the data itself). +The structure must always be initiated and freed by the functions +documented in this manual. +.Pp +.Fn krb5_data_zero +resets the content of +.Fa p . +.Pp +.Fn krb5_data_free +free the data in +.Fa p +and reset the content of the structure with +.Fn krb5_data_zero . +.Pp +.Fn krb5_free_data_contents +works the same way as +.Fa krb5_data_free . +The diffrence is that krb5_free_data_contents is more portable (exists +in MIT api). +.Pp +.Fn krb5_free_data +frees the data in +.Fa p +and +.Fa p +itself. +.Pp +.Fn krb5_data_alloc +allocates +.Fa len +bytes in +.Fa p . +Returns 0 or an error. +.Pp +.Fn krb5_data_realloc +reallocates the length of +.Fa p +to the length in +.Fa len . +Returns 0 or an error. +.Pp +.Fn krb5_data_copy +copies the +.Fa data +that have the length +.Fa len +into +.Fa p . +.Fa p +is not freed so the calling function should make sure the +.Fa p +doesn't contain anything needs to be freed. +Returns 0 or an error. +.Pp +.Fn krb5_copy_data +copies the +.Li krb5_data +in +.Fa indata +to +.Fa outdata . +.Fa outdata +is not freed so the calling function should make sure the +.Fa outdata +doesn't contain anything needs to be freed. +.Fa outdata +should be freed using +.Fn krb5_free_data . +Returns 0 or an error. +.Pp +.Fn krb5_data_cmp +will compare two data object and check if they are the same in a +simular way as memcmp does it. The return value can be used for +sorting. +.Sh SEE ALSO +.Xr krb5 3 , +.Xr krb5_storage 3 , +.Xr kerberos 8 diff --git a/lib/krb5/krb5_digest.3 b/lib/krb5/krb5_digest.3 new file mode 100644 index 0000000..f9d7571 --- /dev/null +++ b/lib/krb5/krb5_digest.3 @@ -0,0 +1,260 @@ +.\" Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_digest.3 20259 2007-02-17 23:49:54Z lha $ +.\" +.Dd February 18, 2007 +.Dt KRB5_DIGEST 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_digest , +.Nm krb5_digest_alloc , +.Nm krb5_digest_free , +.Nm krb5_digest_set_server_cb , +.Nm krb5_digest_set_type , +.Nm krb5_digest_set_hostname , +.Nm krb5_digest_get_server_nonce , +.Nm krb5_digest_set_server_nonce , +.Nm krb5_digest_get_opaque , +.Nm krb5_digest_set_opaque , +.Nm krb5_digest_get_identifier , +.Nm krb5_digest_set_identifier , +.Nm krb5_digest_init_request , +.Nm krb5_digest_set_client_nonce , +.Nm krb5_digest_set_digest , +.Nm krb5_digest_set_username , +.Nm krb5_digest_set_authid , +.Nm krb5_digest_set_authentication_user , +.Nm krb5_digest_set_realm , +.Nm krb5_digest_set_method , +.Nm krb5_digest_set_uri , +.Nm krb5_digest_set_nonceCount , +.Nm krb5_digest_set_qop , +.Nm krb5_digest_request , +.Nm krb5_digest_get_responseData , +.Nm krb5_digest_get_rsp , +.Nm krb5_digest_get_tickets , +.Nm krb5_digest_get_client_binding , +.Nm krb5_digest_get_a1_hash +.Nd remote digest (HTTP-DIGEST, SASL, CHAP) suppport +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Pp +.Li "typedef struct krb5_digest *krb5_digest;" +.Pp +.Ft krb5_error_code +.Fo krb5_digest_alloc +.Fa "krb5_context context" +.Fa "krb5_digest *digest" +.Fc +.Ft void +.Fo krb5_digest_free +.Fa "krb5_digest digest" +.Fc +.Ft krb5_error_code +.Fo krb5_digest_set_type +.Fa "krb5_context context" +.Fa "krb5_digest digest" +.Fa "const char *type" +.Fc +.Ft krb5_error_code +.Fo krb5_digest_set_server_cb +.Fa "krb5_context context" +.Fa "krb5_digest digest" +.Fa "const char *type" +.Fa "const char *binding" +.Fc +.Ft krb5_error_code +.Fo krb5_digest_set_hostname +.Fa "krb5_context context" +.Fa "krb5_digest digest" +.Fa "const char *hostname" +.Fc +.Ft "const char *" +.Fo krb5_digest_get_server_nonce +.Fa "krb5_context context" +.Fa "krb5_digest digest" +.Fc +.Ft krb5_error_code +.Fo krb5_digest_set_server_nonce +.Fa "krb5_context context" +.Fa "krb5_digest digest" +.Fa "const char *nonce" +.Fc +.Ft "const char *" +.Fo krb5_digest_get_opaque +.Fa "krb5_context context" +.Fa "krb5_digest digest" +.Fc +.Ft krb5_error_code +.Fo krb5_digest_set_opaque +.Fa "krb5_context context" +.Fa "krb5_digest digest" +.Fa "const char *opaque" +.Fc +.Ft "const char *" +.Fo krb5_digest_get_identifier +.Fa "krb5_context context" +.Fa "krb5_digest digest" +.Fc +.Ft krb5_error_code +.Fo krb5_digest_set_identifier +.Fa "krb5_context context" +.Fa "krb5_digest digest" +.Fa "const char *id" +.Fc +.Ft krb5_error_code +.Fo krb5_digest_init_request +.Fa "krb5_context context" +.Fa "krb5_digest digest" +.Fa "krb5_realm realm" +.Fa "krb5_ccache ccache" +.Fc +.Ft krb5_error_code +.Fo krb5_digest_set_client_nonce +.Fa "krb5_context context" +.Fa "krb5_digest digest" +.Fa "const char *nonce" +.Fc +.Ft krb5_error_code +.Fo krb5_digest_set_digest +.Fa "krb5_context context" +.Fa "krb5_digest digest" +.Fa "const char *dgst" +.Fc +.Ft krb5_error_code +.Fo krb5_digest_set_username +.Fa "krb5_context context" +.Fa "krb5_digest digest" +.Fa "const char *username" +.Fc +.Ft krb5_error_code +.Fo krb5_digest_set_authid +.Fa "krb5_context context" +.Fa "krb5_digest digest" +.Fa "const char *authid" +.Fc +.Ft krb5_error_code +.Fo krb5_digest_set_authentication_user +.Fa "krb5_context context" +.Fa "krb5_digest digest" +.Fa "krb5_principal authentication_user" +.Fc +.Ft krb5_error_code +.Fo krb5_digest_set_realm +.Fa "krb5_context context" +.Fa "krb5_digest digest" +.Fa "const char *realm" +.Fc +.Ft krb5_error_code +.Fo krb5_digest_set_method +.Fa "krb5_context context" +.Fa "krb5_digest digest" +.Fa "const char *method" +.Fc +.Ft krb5_error_code +.Fo krb5_digest_set_uri +.Fa "krb5_context context" +.Fa "krb5_digest digest" +.Fa "const char *uri" +.Fc +.Ft krb5_error_code +.Fo krb5_digest_set_nonceCount +.Fa "krb5_context context" +.Fa "krb5_digest digest" +.Fa "const char *nonce_count" +.Fc +.Ft krb5_error_code +.Fo krb5_digest_set_qop +.Fa "krb5_context context" +.Fa "krb5_digest digest" +.Fa "const char *qop" +.Fc +.Ft krb5_error_code +.Fo krb5_digest_request +.Fa "krb5_context context" +.Fa "krb5_digest digest" +.Fa "krb5_realm realm" +.Fa "krb5_ccache ccache" +.Fc +.Ft "const char *" +.Fo krb5_digest_get_responseData +.Fa "krb5_context context" +.Fa "krb5_digest digest" +.Fc +.Ft "const char *" +.Fo krb5_digest_get_rsp +.Fa "krb5_context context" +.Fa "krb5_digest digest" +.Fc +.Ft krb5_error_code +.Fo krb5_digest_get_tickets +.Fa "krb5_context context" +.Fa "krb5_digest digest" +.Fa "Ticket **tickets" +.Fc +.Ft krb5_error_code +.Fo krb5_digest_get_client_binding +.Fa "krb5_context context" +.Fa "krb5_digest digest" +.Fa "char **type" +.Fa "char **binding" +.Fc +.Ft krb5_error_code +.Fo krb5_digest_get_a1_hash +.Fa "krb5_context context" +.Fa "krb5_digest digest" +.Fa "krb5_data *data" +.Fc +.Sh DESCRIPTION +The +.Fn krb5_digest_alloc +function allocatates the +.Fa digest +structure. The structure should be freed with +.Fn krb5_digest_free +when it is no longer being used. +.Pp +.Fn krb5_digest_alloc +returns 0 to indicate success. +Otherwise an kerberos code is returned and the pointer that +.Fa digest +points to is set to +.Dv NULL . +.Pp +.Fn krb5_digest_free +free the structure +.Fa digest . +.Sh SEE ALSO +.Xr krb5 3 , +.Xr kerberos 8 diff --git a/lib/krb5/krb5_eai_to_heim_errno.3 b/lib/krb5/krb5_eai_to_heim_errno.3 new file mode 100644 index 0000000..fcada92 --- /dev/null +++ b/lib/krb5/krb5_eai_to_heim_errno.3 @@ -0,0 +1,68 @@ +.\" Copyright (c) 2004 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_eai_to_heim_errno.3 14086 2004-08-03 11:13:46Z lha $ +.\" +.Dd April 13, 2004 +.Dt KRB5_EAI_TO_HEIM_ERRNO 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_eai_to_heim_errno , +.Nm krb5_h_errno_to_heim_errno +.Nd convert resolver error code to com_err error codes +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Ft krb5_error_code +.Fo krb5_eai_to_heim_errno +.Fa "int eai_errno" +.Fa "int system_error" +.Fc +.Ft krb5_error_code +.Fo krb5_h_errno_to_heim_errno +.Fa "int eai_errno" +.Fc +.Sh DESCRIPTION +.Fn krb5_eai_to_heim_errno +and +.Fn krb5_h_errno_to_heim_errno +convert +.Xr getaddrinfo 3 , +.Xr getnameinfo 3 , +and +.Xr h_errno 3 +to com_err error code that are used by Heimdal, this is useful for for +function returning kerberos errors and needs to communicate failures +from resolver function. +.Sh SEE ALSO +.Xr krb5 3 , +.Xr kerberos 8 diff --git a/lib/krb5/krb5_encrypt.3 b/lib/krb5/krb5_encrypt.3 new file mode 100644 index 0000000..76cb4c7 --- /dev/null +++ b/lib/krb5/krb5_encrypt.3 @@ -0,0 +1,278 @@ +.\" Copyright (c) 1999 - 2004 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_encrypt.3 22071 2007-11-14 20:04:50Z lha $ +.\" +.Dd March 20, 2004 +.Dt KRB5_ENCRYPT 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_crypto_getblocksize , +.Nm krb5_crypto_getconfoundersize +.Nm krb5_crypto_getenctype , +.Nm krb5_crypto_getpadsize , +.Nm krb5_crypto_overhead , +.Nm krb5_decrypt , +.Nm krb5_decrypt_EncryptedData , +.Nm krb5_decrypt_ivec , +.Nm krb5_decrypt_ticket , +.Nm krb5_encrypt , +.Nm krb5_encrypt_EncryptedData , +.Nm krb5_encrypt_ivec , +.Nm krb5_enctype_disable , +.Nm krb5_enctype_keysize , +.Nm krb5_enctype_to_string , +.Nm krb5_enctype_valid , +.Nm krb5_get_wrapped_length , +.Nm krb5_string_to_enctype +.Nd "encrypt and decrypt data, set and get encryption type parameters" +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Ft krb5_error_code +.Fo krb5_encrypt +.Fa "krb5_context context" +.Fa "krb5_crypto crypto" +.Fa "unsigned usage" +.Fa "void *data" +.Fa "size_t len" +.Fa "krb5_data *result" +.Fc +.Ft krb5_error_code +.Fo krb5_encrypt_EncryptedData +.Fa "krb5_context context" +.Fa "krb5_crypto crypto" +.Fa "unsigned usage" +.Fa "void *data" +.Fa "size_t len" +.Fa "int kvno" +.Fa "EncryptedData *result" +.Fc +.Ft krb5_error_code +.Fo krb5_encrypt_ivec +.Fa "krb5_context context" +.Fa "krb5_crypto crypto" +.Fa "unsigned usage" +.Fa "void *data" +.Fa "size_t len" +.Fa "krb5_data *result" +.Fa "void *ivec" +.Fc +.Ft krb5_error_code +.Fo krb5_decrypt +.Fa "krb5_context context" +.Fa "krb5_crypto crypto" +.Fa "unsigned usage" +.Fa "void *data" +.Fa "size_t len" +.Fa "krb5_data *result" +.Fc +.Ft krb5_error_code +.Fo krb5_decrypt_EncryptedData +.Fa "krb5_context context" +.Fa "krb5_crypto crypto" +.Fa "unsigned usage" +.Fa "EncryptedData *e" +.Fa "krb5_data *result" +.Fc +.Ft krb5_error_code +.Fo krb5_decrypt_ivec +.Fa "krb5_context context" +.Fa "krb5_crypto crypto" +.Fa "unsigned usage" +.Fa "void *data" +.Fa "size_t len" +.Fa "krb5_data *result" +.Fa "void *ivec" +.Fc +.Ft krb5_error_code +.Fo krb5_decrypt_ticket +.Fa "krb5_context context" +.Fa "Ticket *ticket" +.Fa "krb5_keyblock *key" +.Fa "EncTicketPart *out" +.Fa "krb5_flags flags" +.Fc +.Ft krb5_error_code +.Fo krb5_crypto_getblocksize +.Fa "krb5_context context" +.Fa "size_t *blocksize" +.Fc +.Ft krb5_error_code +.Fo krb5_crypto_getenctype +.Fa "krb5_context context" +.Fa "krb5_crypto crypto" +.Fa "krb5_enctype *enctype" +.Fc +.Ft krb5_error_code +.Fo krb5_crypto_getpadsize +.Fa "krb5_context context" +.Fa size_t *padsize" +.Fc +.Ft krb5_error_code +.Fo krb5_crypto_getconfoundersize +.Fa "krb5_context context" +.Fa "krb5_crypto crypto +.Fa size_t *confoundersize" +.Fc +.Ft krb5_error_code +.Fo krb5_enctype_keysize +.Fa "krb5_context context" +.Fa "krb5_enctype type" +.Fa "size_t *keysize" +.Fc +.Ft krb5_error_code +.Fo krb5_crypto_overhead +.Fa "krb5_context context" +.Fa size_t *padsize" +.Fc +.Ft krb5_error_code +.Fo krb5_string_to_enctype +.Fa "krb5_context context" +.Fa "const char *string" +.Fa "krb5_enctype *etype" +.Fc +.Ft krb5_error_code +.Fo krb5_enctype_to_string +.Fa "krb5_context context" +.Fa "krb5_enctype etype" +.Fa "char **string" +.Fc +.Ft krb5_error_code +.Fo krb5_enctype_valid +.Fa "krb5_context context" +.Fa "krb5_enctype etype" +.Fc +.Ft void +.Fo krb5_enctype_disable +.Fa "krb5_context context" +.Fa "krb5_enctype etype" +.Fc +.Ft size_t +.Fo krb5_get_wrapped_length +.Fa "krb5_context context" +.Fa "krb5_crypto crypto" +.Fa "size_t data_len" +.Fc +.Sh DESCRIPTION +These functions are used to encrypt and decrypt data. +.Pp +.Fn krb5_encrypt_ivec +puts the encrypted version of +.Fa data +(of size +.Fa len ) +in +.Fa result . +If the encryption type supports using derived keys, +.Fa usage +should be the appropriate key-usage. +.Fa ivec +is a pointer to a initial IV, it is modified to the end IV at the end of +the round. +Ivec should be the size of +If +.Dv NULL +is passed in, the default IV is used. +.Fn krb5_encrypt +does the same as +.Fn krb5_encrypt_ivec +but with +.Fa ivec +being +.Dv NULL . +.Fn krb5_encrypt_EncryptedData +does the same as +.Fn krb5_encrypt , +but it puts the encrypted data in a +.Fa EncryptedData +structure instead. If +.Fa kvno +is not zero, it will be put in the (optional) +.Fa kvno +field in the +.Fa EncryptedData . +.Pp +.Fn krb5_decrypt_ivec , +.Fn krb5_decrypt , +and +.Fn krb5_decrypt_EncryptedData +works similarly. +.Pp +.Fn krb5_decrypt_ticket +decrypts the encrypted part of +.Fa ticket +with +.Fa key . +.Fn krb5_decrypt_ticket +also verifies the timestamp in the ticket, invalid flag and if the KDC +haven't verified the transited path, the transit path. +.Pp +.Fn krb5_enctype_keysize , +.Fn krb5_crypto_getconfoundersize , +.Fn krb5_crypto_getblocksize , +.Fn krb5_crypto_getenctype , +.Fn krb5_crypto_getpadsize , +.Fn krb5_crypto_overhead +all returns various (sometimes) useful information from a crypto context. +.Fn krb5_crypto_overhead +is the combination of krb5_crypto_getconfoundersize, +krb5_crypto_getblocksize and krb5_crypto_getpadsize and return the +maximum overhead size. +.Pp +.Fn krb5_enctype_to_string +converts a encryption type number to a string that can be printable +and stored. The strings returned should be freed with +.Xr free 3 . +.Pp +.Fn krb5_string_to_enctype +converts a encryption type strings to a encryption type number that +can use used for other Kerberos crypto functions. +.Pp +.Fn krb5_enctype_valid +returns 0 if the encrypt is supported and not disabled, otherwise and +error code is returned. +.Pp +.Fn krb5_enctype_disable +(globally, for all contextes) disables the +.Fa enctype . +.Pp +.Fn krb5_get_wrapped_length +returns the size of an encrypted packet by +.Fa crypto +of length +.Fa data_len . +.\" .Sh EXAMPLE +.\" .Sh BUGS +.Sh SEE ALSO +.Xr krb5_create_checksum 3 , +.Xr krb5_crypto_init 3 diff --git a/lib/krb5/krb5_err.et b/lib/krb5/krb5_err.et new file mode 100644 index 0000000..6714401 --- /dev/null +++ b/lib/krb5/krb5_err.et @@ -0,0 +1,266 @@ +# +# Error messages for the krb5 library +# +# This might look like a com_err file, but is not +# +id "$Id: krb5_err.et 21050 2007-06-12 02:00:40Z lha $" + +error_table krb5 + +prefix KRB5KDC_ERR +error_code NONE, "No error" +error_code NAME_EXP, "Client's entry in database has expired" +error_code SERVICE_EXP, "Server's entry in database has expired" +error_code BAD_PVNO, "Requested protocol version not supported" +error_code C_OLD_MAST_KVNO, "Client's key is encrypted in an old master key" +error_code S_OLD_MAST_KVNO, "Server's key is encrypted in an old master key" +error_code C_PRINCIPAL_UNKNOWN, "Client not found in Kerberos database" +error_code S_PRINCIPAL_UNKNOWN, "Server not found in Kerberos database" +error_code PRINCIPAL_NOT_UNIQUE,"Principal has multiple entries in Kerberos database" +error_code NULL_KEY, "Client or server has a null key" +error_code CANNOT_POSTDATE, "Ticket is ineligible for postdating" +error_code NEVER_VALID, "Requested effective lifetime is negative or too short" +error_code POLICY, "KDC policy rejects request" +error_code BADOPTION, "KDC can't fulfill requested option" +error_code ETYPE_NOSUPP, "KDC has no support for encryption type" +error_code SUMTYPE_NOSUPP, "KDC has no support for checksum type" +error_code PADATA_TYPE_NOSUPP, "KDC has no support for padata type" +error_code TRTYPE_NOSUPP, "KDC has no support for transited type" +error_code CLIENT_REVOKED, "Clients credentials have been revoked" +error_code SERVICE_REVOKED, "Credentials for server have been revoked" +error_code TGT_REVOKED, "TGT has been revoked" +error_code CLIENT_NOTYET, "Client not yet valid - try again later" +error_code SERVICE_NOTYET, "Server not yet valid - try again later" +error_code KEY_EXPIRED, "Password has expired" +error_code PREAUTH_FAILED, "Preauthentication failed" +error_code PREAUTH_REQUIRED, "Additional pre-authentication required" +error_code SERVER_NOMATCH, "Requested server and ticket don't match" +error_code KDC_ERR_MUST_USE_USER2USER, "Server principal valid for user2user only" +error_code PATH_NOT_ACCEPTED, "KDC Policy rejects transited path" +error_code SVC_UNAVAILABLE, "A service is not available" + +index 31 +prefix KRB5KRB_AP +error_code ERR_BAD_INTEGRITY, "Decrypt integrity check failed" +error_code ERR_TKT_EXPIRED, "Ticket expired" +error_code ERR_TKT_NYV, "Ticket not yet valid" +error_code ERR_REPEAT, "Request is a replay" +error_code ERR_NOT_US, "The ticket isn't for us" +error_code ERR_BADMATCH, "Ticket/authenticator don't match" +error_code ERR_SKEW, "Clock skew too great" +error_code ERR_BADADDR, "Incorrect net address" +error_code ERR_BADVERSION, "Protocol version mismatch" +error_code ERR_MSG_TYPE, "Invalid message type" +error_code ERR_MODIFIED, "Message stream modified" +error_code ERR_BADORDER, "Message out of order" +error_code ERR_ILL_CR_TKT, "Invalid cross-realm ticket" +error_code ERR_BADKEYVER, "Key version is not available" +error_code ERR_NOKEY, "Service key not available" +error_code ERR_MUT_FAIL, "Mutual authentication failed" +error_code ERR_BADDIRECTION, "Incorrect message direction" +error_code ERR_METHOD, "Alternative authentication method required" +error_code ERR_BADSEQ, "Incorrect sequence number in message" +error_code ERR_INAPP_CKSUM, "Inappropriate type of checksum in message" +error_code PATH_NOT_ACCEPTED, "Policy rejects transited path" + +prefix KRB5KRB_ERR +error_code RESPONSE_TOO_BIG, "Response too big for UDP, retry with TCP" +# 53-59 are reserved +index 60 +error_code GENERIC, "Generic error (see e-text)" +error_code FIELD_TOOLONG, "Field is too long for this implementation" + +# pkinit +index 62 +prefix KRB5_KDC_ERR +error_code CLIENT_NOT_TRUSTED, "Client not trusted" +error_code KDC_NOT_TRUSTED, "KDC not trusted" +error_code INVALID_SIG, "Invalid signature" +error_code DH_KEY_PARAMETERS_NOT_ACCEPTED, "DH parameters not accepted" + +index 68 +prefix KRB5_KDC_ERR +error_code WRONG_REALM, "Wrong realm" + +index 69 +prefix KRB5_AP_ERR +error_code USER_TO_USER_REQUIRED, "User to user required" + +index 70 +prefix KRB5_KDC_ERR +error_code CANT_VERIFY_CERTIFICATE, "Cannot verify certificate" +error_code INVALID_CERTIFICATE, "Certificate invalid" +error_code REVOKED_CERTIFICATE, "Certificate revoked" +error_code REVOCATION_STATUS_UNKNOWN, "Revocation status unknown" +error_code REVOCATION_STATUS_UNAVAILABLE, "Revocation status unavaible" +error_code CLIENT_NAME_MISMATCH, "Client name mismatch in certificate" +error_code INCONSISTENT_KEY_PURPOSE, "Inconsistent key purpose" +error_code DIGEST_IN_CERT_NOT_ACCEPTED, "Digest in certificate not accepted" +error_code PA_CHECKSUM_MUST_BE_INCLUDED, "paChecksum must be included" +error_code DIGEST_IN_SIGNED_DATA_NOT_ACCEPTED, "Digest in signedData not accepted" +error_code PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED, "Public key encryption not supported" + +## these are never used +#index 80 +#prefix KRB5_IAKERB +#error_code ERR_KDC_NOT_FOUND, "IAKERB proxy could not find a KDC" +#error_code ERR_KDC_NO_RESPONSE, "IAKERB proxy never reeived a response from a KDC" + +# 82-127 are reserved + +index 128 +prefix +error_code KRB5_ERR_RCSID, "$Id: krb5_err.et 21050 2007-06-12 02:00:40Z lha $" + +error_code KRB5_LIBOS_BADLOCKFLAG, "Invalid flag for file lock mode" +error_code KRB5_LIBOS_CANTREADPWD, "Cannot read password" +error_code KRB5_LIBOS_BADPWDMATCH, "Password mismatch" +error_code KRB5_LIBOS_PWDINTR, "Password read interrupted" + +error_code KRB5_PARSE_ILLCHAR, "Invalid character in component name" +error_code KRB5_PARSE_MALFORMED, "Malformed representation of principal" + +error_code KRB5_CONFIG_CANTOPEN, "Can't open/find configuration file" +error_code KRB5_CONFIG_BADFORMAT, "Improper format of configuration file" +error_code KRB5_CONFIG_NOTENUFSPACE, "Insufficient space to return complete information" + +error_code KRB5_BADMSGTYPE, "Invalid message type specified for encoding" + +error_code KRB5_CC_BADNAME, "Credential cache name malformed" +error_code KRB5_CC_UNKNOWN_TYPE, "Unknown credential cache type" +error_code KRB5_CC_NOTFOUND, "Matching credential not found" +error_code KRB5_CC_END, "End of credential cache reached" + +error_code KRB5_NO_TKT_SUPPLIED, "Request did not supply a ticket" + +error_code KRB5KRB_AP_WRONG_PRINC, "Wrong principal in request" +error_code KRB5KRB_AP_ERR_TKT_INVALID, "Ticket has invalid flag set" + +error_code KRB5_PRINC_NOMATCH, "Requested principal and ticket don't match" +error_code KRB5_KDCREP_MODIFIED, "KDC reply did not match expectations" +error_code KRB5_KDCREP_SKEW, "Clock skew too great in KDC reply" +error_code KRB5_IN_TKT_REALM_MISMATCH, "Client/server realm mismatch in initial ticket request" + +error_code KRB5_PROG_ETYPE_NOSUPP, "Program lacks support for encryption type" +error_code KRB5_PROG_KEYTYPE_NOSUPP, "Program lacks support for key type" +error_code KRB5_WRONG_ETYPE, "Requested encryption type not used in message" +error_code KRB5_PROG_SUMTYPE_NOSUPP, "Program lacks support for checksum type" + +error_code KRB5_REALM_UNKNOWN, "Cannot find KDC for requested realm" +error_code KRB5_SERVICE_UNKNOWN, "Kerberos service unknown" +error_code KRB5_KDC_UNREACH, "Cannot contact any KDC for requested realm" +error_code KRB5_NO_LOCALNAME, "No local name found for principal name" + +error_code KRB5_MUTUAL_FAILED, "Mutual authentication failed" + +# some of these should be combined/supplanted by system codes + +error_code KRB5_RC_TYPE_EXISTS, "Replay cache type is already registered" +error_code KRB5_RC_MALLOC, "No more memory to allocate (in replay cache code)" +error_code KRB5_RC_TYPE_NOTFOUND, "Replay cache type is unknown" +error_code KRB5_RC_UNKNOWN, "Generic unknown RC error" +error_code KRB5_RC_REPLAY, "Message is a replay" +error_code KRB5_RC_IO, "Replay I/O operation failed XXX" +error_code KRB5_RC_NOIO, "Replay cache type does not support non-volatile storage" +error_code KRB5_RC_PARSE, "Replay cache name parse/format error" + +error_code KRB5_RC_IO_EOF, "End-of-file on replay cache I/O" +error_code KRB5_RC_IO_MALLOC, "No more memory to allocate (in replay cache I/O code)" +error_code KRB5_RC_IO_PERM, "Permission denied in replay cache code" +error_code KRB5_RC_IO_IO, "I/O error in replay cache i/o code" +error_code KRB5_RC_IO_UNKNOWN, "Generic unknown RC/IO error" +error_code KRB5_RC_IO_SPACE, "Insufficient system space to store replay information" + +error_code KRB5_TRANS_CANTOPEN, "Can't open/find realm translation file" +error_code KRB5_TRANS_BADFORMAT, "Improper format of realm translation file" + +error_code KRB5_LNAME_CANTOPEN, "Can't open/find lname translation database" +error_code KRB5_LNAME_NOTRANS, "No translation available for requested principal" +error_code KRB5_LNAME_BADFORMAT, "Improper format of translation database entry" + +error_code KRB5_CRYPTO_INTERNAL, "Cryptosystem internal error" + +error_code KRB5_KT_BADNAME, "Key table name malformed" +error_code KRB5_KT_UNKNOWN_TYPE, "Unknown Key table type" +error_code KRB5_KT_NOTFOUND, "Key table entry not found" +error_code KRB5_KT_END, "End of key table reached" +error_code KRB5_KT_NOWRITE, "Cannot write to specified key table" +error_code KRB5_KT_IOERR, "Error writing to key table" + +error_code KRB5_NO_TKT_IN_RLM, "Cannot find ticket for requested realm" +error_code KRB5DES_BAD_KEYPAR, "DES key has bad parity" +error_code KRB5DES_WEAK_KEY, "DES key is a weak key" + +error_code KRB5_BAD_ENCTYPE, "Bad encryption type" +error_code KRB5_BAD_KEYSIZE, "Key size is incompatible with encryption type" +error_code KRB5_BAD_MSIZE, "Message size is incompatible with encryption type" + +error_code KRB5_CC_TYPE_EXISTS, "Credentials cache type is already registered." +error_code KRB5_KT_TYPE_EXISTS, "Key table type is already registered." + +error_code KRB5_CC_IO, "Credentials cache I/O operation failed XXX" +error_code KRB5_FCC_PERM, "Credentials cache file permissions incorrect" +error_code KRB5_FCC_NOFILE, "No credentials cache file found" +error_code KRB5_FCC_INTERNAL, "Internal file credentials cache error" +error_code KRB5_CC_WRITE, "Error writing to credentials cache file" +error_code KRB5_CC_NOMEM, "No more memory to allocate (in credentials cache code)" +error_code KRB5_CC_FORMAT, "Bad format in credentials cache" +error_code KRB5_CC_NOT_KTYPE, "No credentials found with supported encryption types" + +# errors for dual tgt library calls +error_code KRB5_INVALID_FLAGS, "Invalid KDC option combination (library internal error)" +error_code KRB5_NO_2ND_TKT, "Request missing second ticket" + +error_code KRB5_NOCREDS_SUPPLIED, "No credentials supplied to library routine" + +# errors for sendauth (and recvauth) + +error_code KRB5_SENDAUTH_BADAUTHVERS, "Bad sendauth version was sent" +error_code KRB5_SENDAUTH_BADAPPLVERS, "Bad application version was sent (via sendauth)" +error_code KRB5_SENDAUTH_BADRESPONSE, "Bad response (during sendauth exchange)" +error_code KRB5_SENDAUTH_REJECTED, "Server rejected authentication (during sendauth exchange)" + +# errors for preauthentication + +error_code KRB5_PREAUTH_BAD_TYPE, "Unsupported preauthentication type" +error_code KRB5_PREAUTH_NO_KEY, "Required preauthentication key not supplied" +error_code KRB5_PREAUTH_FAILED, "Generic preauthentication failure" + +# version number errors + +error_code KRB5_RCACHE_BADVNO, "Unsupported replay cache format version number" +error_code KRB5_CCACHE_BADVNO, "Unsupported credentials cache format version number" +error_code KRB5_KEYTAB_BADVNO, "Unsupported key table format version number" + +# +# + +error_code KRB5_PROG_ATYPE_NOSUPP, "Program lacks support for address type" +error_code KRB5_RC_REQUIRED, "Message replay detection requires rcache parameter" +error_code KRB5_ERR_BAD_HOSTNAME, "Hostname cannot be canonicalized" +error_code KRB5_ERR_HOST_REALM_UNKNOWN, "Cannot determine realm for host" +error_code KRB5_SNAME_UNSUPP_NAMETYPE, "Conversion to service principal undefined for name type" + +error_code KRB5KRB_AP_ERR_V4_REPLY, "Initial Ticket response appears to be Version 4" +error_code KRB5_REALM_CANT_RESOLVE, "Cannot resolve KDC for requested realm" +error_code KRB5_TKT_NOT_FORWARDABLE, "Requesting ticket can't get forwardable tickets" +error_code KRB5_FWD_BAD_PRINCIPAL, "Bad principal name while trying to forward credentials" + +error_code KRB5_GET_IN_TKT_LOOP, "Looping detected inside krb5_get_in_tkt" +error_code KRB5_CONFIG_NODEFREALM, "Configuration file does not specify default realm" + +error_code KRB5_SAM_UNSUPPORTED, "Bad SAM flags in obtain_sam_padata" +error_code KRB5_SAM_INVALID_ETYPE, "Invalid encryption type in SAM challenge" +error_code KRB5_SAM_NO_CHECKSUM, "Missing checksum in SAM challenge" +error_code KRB5_SAM_BAD_CHECKSUM, "Bad checksum in SAM challenge" + +index 238 +error_code KRB5_OBSOLETE_FN, "Program called an obsolete, deleted function" + +index 245 +error_code KRB5_ERR_BAD_S2K_PARAMS, "Invalid key generation parameters from KDC" +error_code KRB5_ERR_NO_SERVICE, "Service not available" +error_code KRB5_CC_NOSUPP, "Credential cache function not supported" +error_code KRB5_DELTAT_BADFORMAT, "Invalid format of Kerberos lifetime or clock skew string" + +end diff --git a/lib/krb5/krb5_expand_hostname.3 b/lib/krb5/krb5_expand_hostname.3 new file mode 100644 index 0000000..ffd98da --- /dev/null +++ b/lib/krb5/krb5_expand_hostname.3 @@ -0,0 +1,93 @@ +.\" Copyright (c) 2004 - 2006 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_expand_hostname.3 17461 2006-05-05 13:13:18Z lha $ +.\" +.Dd May 5, 2006 +.Dt KRB5_EXPAND_HOSTNAME 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_expand_hostname , +.Nm krb5_expand_hostname_realms +.Nd Kerberos 5 host name canonicalization functions +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Pp +.Ft krb5_error_code +.Fo krb5_expand_hostname +.Fa "krb5_context context" +.Fa "const char *orig_hostname" +.Fa "char **new_hostname" +.Fc +.Ft krb5_error_code +.Fo krb5_expand_hostname_realms +.Fa "krb5_context context" +.Fa "const char *orig_hostname" +.Fa "char **new_hostname" +.Fa "char ***realms" +.Fc +.Sh DESCRIPTION +.Fn krb5_expand_hostname +tries to make +.Fa orig_hostname +into a more canonical one in the newly allocated space returned in +.Fa new_hostname . +Caller must free the hostname with +.Xr free 3 . +.Pp +.Fn krb5_expand_hostname_realms +expands +.Fa orig_hostname +to a name we believe to be a hostname in newly +allocated space in +.Fa new_hostname +and return the realms +.Fa new_hostname +is belive to belong to in +.Fa realms . +.Fa Realms +is a array terminated with +.Dv NULL . +Caller must free the +.Fa realms +with +.Fn krb5_free_host_realm +and +.Fa new_hostname +with +.Xr free 3 . +.Sh SEE ALSO +.Xr krb5 3 , +.Xr krb5_free_host_realm 3 , +.Xr krb5_get_host_realm 3 , +.Xr kerberos 8 diff --git a/lib/krb5/krb5_find_padata.3 b/lib/krb5/krb5_find_padata.3 new file mode 100644 index 0000000..b726784 --- /dev/null +++ b/lib/krb5/krb5_find_padata.3 @@ -0,0 +1,87 @@ +.\" Copyright (c) 2004 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_find_padata.3 13595 2004-03-21 13:17:41Z lha $ +.\" +.Dd March 21, 2004 +.Dt KRB5_FIND_PADATA 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_find_padata , +.Nm krb5_padata_add +.Nd Kerberos 5 pre-authentication data handling functions +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Pp +.Ft "PA_DATA *" +.Fo krb5_find_padata +.Fa "PA_DATA *val" +.Fa "unsigned len" +.Fa "int type" +.Fa "int *index" +.Fc +.Ft int +.Fo krb5_padata_add +.Fa "krb5_context context" +.Fa "METHOD_DATA *md" +.Fa "int type" +.Fa "void *buf" +.Fa "size_t len" +.Fc +.Sh DESCRIPTION +.Fn krb5_find_padata +tries to find the pre-authentication data entry of type +.Fa type +in the array +.Fa val +of length +.Fa len . +The search is started at entry pointed out by +.Fa *index +(zero based indexing). +If the type isn't found, +.Dv NULL +is returned. +.Pp +.Fn krb5_padata_add +adds a pre-authentication data entry of type +.Fa type +pointed out by +.Fa buf +and +.Fa len +to +.Fa md . +.Sh SEE ALSO +.Xr krb5 3 , +.Xr kerberos 8 diff --git a/lib/krb5/krb5_free_addresses.3 b/lib/krb5/krb5_free_addresses.3 new file mode 100644 index 0000000..6ac46d4 --- /dev/null +++ b/lib/krb5/krb5_free_addresses.3 @@ -0,0 +1,53 @@ +.\" Copyright (c) 2001 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_free_addresses.3,v 1.5 2003/04/16 13:58:15 lha Exp $ +.\" +.Dd November 20, 2001 +.Dt KRB5_FREE_ADDRESSES 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_free_addresses +.Nd free list of addresses +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Ft void +.Fn krb5_free_addresses "krb5_context context" "krb5_addresses *addresses" +.Sh DESCRIPTION +The +.Fn krb5_free_addresses +will free a list of addresses that has been created with +.Fn krb5_get_all_client_addrs +or with some other function. +.Sh SEE ALSO +.Xr krb5_get_all_client_addrs 3 diff --git a/lib/krb5/krb5_free_principal.3 b/lib/krb5/krb5_free_principal.3 new file mode 100644 index 0000000..e9900a7 --- /dev/null +++ b/lib/krb5/krb5_free_principal.3 @@ -0,0 +1,58 @@ +.\" Copyright (c) 1997, 2001 - 2002 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" Copyright (c) 1997 Kungliga Tekniska Högskolan +.\" $Id: krb5_free_principal.3,v 1.7 2003/04/16 13:58:11 lha Exp $ +.Dd August 8, 1997 +.Dt KRB5_FREE_PRINCIPAL 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_free_principal +.Nd principal free function +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Ft void +.Fn krb5_free_principal "krb5_context context" "krb5_principal principal" +.Sh DESCRIPTION +The +.Fn krb5_free_principal +will free a principal that has been created with +.Fn krb5_build_principal , +.Fn krb5_parse_name , +or with some other function. +.Sh SEE ALSO +.Xr krb5_425_conv_principal 3 , +.Xr krb5_build_principal 3 , +.Xr krb5_parse_name 3 , +.Xr krb5_sname_to_principal 3 , +.Xr krb5_unparse_name 3 diff --git a/lib/krb5/krb5_generate_random_block.3 b/lib/krb5/krb5_generate_random_block.3 new file mode 100644 index 0000000..4b46954 --- /dev/null +++ b/lib/krb5/krb5_generate_random_block.3 @@ -0,0 +1,57 @@ +.\" Copyright (c) 2004 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_generate_random_block.3 17385 2006-05-01 08:48:55Z lha $ +.\" +.Dd March 21, 2004 +.Dt KRB5_GENERATE_RANDOM_BLOCK 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_generate_random_block +.Nd Kerberos 5 random functions +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Ft void +.Fo krb5_generate_random_block +.Fa "void *buf" +.Fa "size_t len" +.Fc +.Sh DESCRIPTION +.Fn krb5_generate_random_block +generates a cryptographically strong pseudo-random block into the buffer +.Fa buf +of length +.Fa len . +.Sh SEE ALSO +.Xr krb5 3 , +.Xr krb5.conf 5 diff --git a/lib/krb5/krb5_get_all_client_addrs.3 b/lib/krb5/krb5_get_all_client_addrs.3 new file mode 100644 index 0000000..f6f4c85 --- /dev/null +++ b/lib/krb5/krb5_get_all_client_addrs.3 @@ -0,0 +1,74 @@ +.\" Copyright (c) 2001 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_get_all_client_addrs.3 12329 2003-05-26 14:09:04Z lha $ +.\" +.Dd July 1, 2001 +.Dt KRB5_GET_ADDRS 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_get_all_client_addrs , +.Nm krb5_get_all_server_addrs +.Nd return local addresses +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Ft "krb5_error_code" +.Fn krb5_get_all_client_addrs "krb5_context context" "krb5_addresses *addrs" +.Ft "krb5_error_code" +.Fn krb5_get_all_server_addrs "krb5_context context" "krb5_addresses *addrs" +.Sh DESCRIPTION +These functions return in +.Fa addrs +a list of addresses associated with the local +host. +.Pp +The server variant returns all configured interface addresses (if +possible), including loop-back addresses. This is useful if you want +to create sockets to listen to. +.Pp +The client version will also scan local interfaces (can be turned off +by setting +.Li libdefaults/scan_interfaces +to false in +.Pa krb5.conf ) , +but will not include loop-back addresses, unless there are no other +addresses found. It will remove all addresses included in +.Li libdefaults/ignore_addresses +but will unconditionally include addresses in +.Li libdefaults/extra_addresses . +.Pp +The returned addresses should be freed by calling +.Fn krb5_free_addresses . +.\".Sh EXAMPLE +.Sh SEE ALSO +.Xr krb5_free_addresses 3 diff --git a/lib/krb5/krb5_get_credentials.3 b/lib/krb5/krb5_get_credentials.3 new file mode 100644 index 0000000..32e0ffe --- /dev/null +++ b/lib/krb5/krb5_get_credentials.3 @@ -0,0 +1,208 @@ +.\" Copyright (c) 2004 - 2005 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_get_credentials.3 22071 2007-11-14 20:04:50Z lha $ +.\" +.Dd July 26, 2004 +.Dt KRB5_GET_CREDENTIALS 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_get_credentials , +.Nm krb5_get_credentials_with_flags , +.Nm krb5_get_cred_from_kdc , +.Nm krb5_get_cred_from_kdc_opt , +.Nm krb5_get_kdc_cred , +.Nm krb5_get_renewed_creds +.Nd get credentials from the KDC using krbtgt +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Ft krb5_error_code +.Fo krb5_get_credentials +.Fa "krb5_context context" +.Fa "krb5_flags options" +.Fa "krb5_ccache ccache" +.Fa "krb5_creds *in_creds" +.Fa "krb5_creds **out_creds" +.Fc +.Ft krb5_error_code +.Fo krb5_get_credentials_with_flags +.Fa "krb5_context context" +.Fa "krb5_flags options" +.Fa "krb5_kdc_flags flags" +.Fa "krb5_ccache ccache" +.Fa "krb5_creds *in_creds" +.Fa "krb5_creds **out_creds" +.Fc +.Ft krb5_error_code +.Fo krb5_get_cred_from_kdc +.Fa "krb5_context context" +.Fa "krb5_ccache ccache" +.Fa "krb5_creds *in_creds" +.Fa "krb5_creds **out_creds" +.Fa "krb5_creds ***ret_tgts" +.Fc +.Ft krb5_error_code +.Fo krb5_get_cred_from_kdc_opt +.Fa "krb5_context context" +.Fa "krb5_ccache ccache" +.Fa "krb5_creds *in_creds" +.Fa "krb5_creds **out_creds" +.Fa "krb5_creds ***ret_tgts" +.Fa "krb5_flags flags" +.Fc +.Ft krb5_error_code +.Fo krb5_get_kdc_cred +.Fa "krb5_context context" +.Fa "krb5_ccache id" +.Fa "krb5_kdc_flags flags" +.Fa "krb5_addresses *addresses" +.Fa "Ticket *second_ticket" +.Fa "krb5_creds *in_creds" +.Fa "krb5_creds **out_creds" +.Fc +.Ft krb5_error_code +.Fo krb5_get_renewed_creds +.Fa "krb5_context context" +.Fa "krb5_creds *creds" +.Fa "krb5_const_principal client" +.Fa "krb5_ccache ccache" +.Fa "const char *in_tkt_service" +.Fc +.Sh DESCRIPTION +.Fn krb5_get_credentials_with_flags +get credentials specified by +.Fa in_creds->server +and +.Fa in_creds->client +(the rest of the +.Fa in_creds +structure is ignored) +by first looking in the +.Fa ccache +and if doesn't exists or is expired, fetch the credential from the KDC +using the krbtgt in +.Fa ccache . +The credential is returned in +.Fa out_creds +and should be freed using the function +.Fn krb5_free_creds . +.Pp +Valid flags to pass into +.Fa options +argument are: +.Pp +.Bl -tag -width "KRB5_GC_USER_USER" -compact +.It KRB5_GC_CACHED +Only check the +.Fa ccache , +don't got out on network to fetch credential. +.It KRB5_GC_USER_USER +Request a user to user ticket. +This option doesn't store the resulting user to user credential in +the +.Fa ccache . +.It KRB5_GC_EXPIRED_OK +returns the credential even if it is expired, default behavior is trying +to refetch the credential from the KDC. +.El +.Pp +.Fa Flags +are KDCOptions, note the caller must fill in the bit-field and not +use the integer associated structure. +.Pp +.Fn krb5_get_credentials +works the same way as +.Fn krb5_get_credentials_with_flags +except that the +.Fa flags +field is missing. +.Pp +.Fn krb5_get_cred_from_kdc +and +.Fn krb5_get_cred_from_kdc_opt +fetches the credential from the KDC very much like +.Fn krb5_get_credentials, but doesn't look in the +.Fa ccache +if the credential exists there first. +.Pp +.Fn krb5_get_kdc_cred +does the same as the functions above, but the caller must fill in all +the information andits closer to the wire protocol. +.Pp +.Fn krb5_get_renewed_creds +renews a credential given by +.Fa in_tkt_service +(if +.Dv NULL +the default +.Li krbtgt ) +using the credential cache +.Fa ccache . +The result is stored in +.Fa creds +and should be freed using +.Fa krb5_free_creds . +.Sh EXAMPLES +Here is a example function that get a credential from a credential cache +.Fa id +or the KDC and returns it to the caller. +.Bd -literal +#include <krb5.h> + +int +getcred(krb5_context context, krb5_ccache id, krb5_creds **creds) +{ + krb5_error_code ret; + krb5_creds in; + + ret = krb5_parse_name(context, "client@EXAMPLE.COM", + &in.client); + if (ret) + krb5_err(context, 1, ret, "krb5_parse_name"); + + ret = krb5_parse_name(context, "host/server.example.com@EXAMPLE.COM", + &in.server); + if (ret) + krb5_err(context, 1, ret, "krb5_parse_name"); + + ret = krb5_get_credentials(context, 0, id, &in, creds); + if (ret) + krb5_err(context, 1, ret, "krb5_get_credentials"); + + return 0; +} +.Ed +.Sh SEE ALSO +.Xr krb5 3 , +.Xr krb5_get_forwarded_creds 3 , +.Xr krb5.conf 5 diff --git a/lib/krb5/krb5_get_creds.3 b/lib/krb5/krb5_get_creds.3 new file mode 100644 index 0000000..189c93f --- /dev/null +++ b/lib/krb5/krb5_get_creds.3 @@ -0,0 +1,173 @@ +.\" Copyright (c) 2006 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_get_creds.3 22071 2007-11-14 20:04:50Z lha $ +.\" +.Dd June 15, 2006 +.Dt KRB5_GET_CREDS 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_get_creds , +.Nm krb5_get_creds_opt_add_options , +.Nm krb5_get_creds_opt_alloc , +.Nm krb5_get_creds_opt_free , +.Nm krb5_get_creds_opt_set_enctype , +.Nm krb5_get_creds_opt_set_impersonate , +.Nm krb5_get_creds_opt_set_options , +.Nm krb5_get_creds_opt_set_ticket +.Nd get credentials from the KDC +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Ft krb5_error_code +.Fo krb5_get_creds +.Fa "krb5_context context" +.Fa "krb5_get_creds_opt opt" +.Fa "krb5_ccache ccache" +.Fa "krb5_const_principal inprinc" +.Fa "krb5_creds **out_creds" +.Fc +.Ft void +.Fo krb5_get_creds_opt_add_options +.Fa "krb5_context context" +.Fa "krb5_get_creds_opt opt" +.Fa "krb5_flags options" +.Fc +.Ft krb5_error_code +.Fo krb5_get_creds_opt_alloc +.Fa "krb5_context context" +.Fa "krb5_get_creds_opt *opt" +.Fc +.Ft void +.Fo krb5_get_creds_opt_free +.Fa "krb5_context context" +.Fa "krb5_get_creds_opt opt" +.Fc +.Ft void +.Fo krb5_get_creds_opt_set_enctype +.Fa "krb5_context context" +.Fa "krb5_get_creds_opt opt" +.Fa "krb5_enctype enctype" +.Fc +.Ft krb5_error_code +.Fo krb5_get_creds_opt_set_impersonate +.Fa "krb5_context context" +.Fa "krb5_get_creds_opt opt" +.Fa "krb5_const_principal self" +.Fc +.Ft void +.Fo krb5_get_creds_opt_set_options +.Fa "krb5_context context" +.Fa "krb5_get_creds_opt opt" +.Fa "krb5_flags options" +.Fc +.Ft krb5_error_code +.Fo krb5_get_creds_opt_set_ticket +.Fa "krb5_context context" +.Fa "krb5_get_creds_opt opt" +.Fa "const Ticket *ticket" +.Fc +.Sh DESCRIPTION +.Fn krb5_get_creds +fetches credentials specified by +.Fa opt +by first looking in the +.Fa ccache , +and then it doesn't exists, fetch the credential from the KDC +using the krbtgts in +.Fa ccache . +The credential is returned in +.Fa out_creds +and should be freed using the function +.Fn krb5_free_creds . +.Pp +The structure +.Li krb5_get_creds_opt +controls the behavior of +.Fn krb5_get_creds . +The structure is opaque to consumers that can set the content of the +structure with accessors functions. All accessor functions make copies +of the data that is passed into accessor functions, so external +consumers free the memory before calling +.Fn krb5_get_creds . +.Pp +The structure +.Li krb5_get_creds_opt +is allocated with +.Fn krb5_get_creds_opt_alloc +and freed with +.Fn krb5_get_creds_opt_free . +The free function also frees the content of the structure set by the +accessor functions. +.Pp +.Fn krb5_get_creds_opt_add_options +and +.Fn krb5_get_creds_opt_set_options +adds and sets options to the +.Fi krb5_get_creds_opt +structure . +The possible options to set are +.Bl -tag -width "KRB5_GC_USER_USER" -compact +.It KRB5_GC_CACHED +Only check the +.Fa ccache , +don't got out on network to fetch credential. +.It KRB5_GC_USER_USER +request a user to user ticket. +This options doesn't store the resulting user to user credential in +the +.Fa ccache . +.It KRB5_GC_EXPIRED_OK +returns the credential even if it is expired, default behavior is trying +to refetch the credential from the KDC. +.It KRB5_GC_NO_STORE +Do not store the resulting credentials in the +.Fa ccache . +.El +.Pp +.Fn krb5_get_creds_opt_set_enctype +sets the preferred encryption type of the application. Don't set this +unless you have to since if there is no match in the KDC, the function +call will fail. +.Pp +.Fn krb5_get_creds_opt_set_impersonate +sets the principal to impersonate., Returns a ticket that have the +impersonation principal as a client and the requestor as the +service. Note that the requested principal have to be the same as the +client principal in the krbtgt. +.Pp +.Fn krb5_get_creds_opt_set_ticket +sets the extra ticket used in user-to-user or contrained delegation use case. +.Sh SEE ALSO +.Xr krb5 3 , +.Xr krb5_get_credentials 3 , +.Xr krb5.conf 5 diff --git a/lib/krb5/krb5_get_forwarded_creds.3 b/lib/krb5/krb5_get_forwarded_creds.3 new file mode 100644 index 0000000..bbe46ec --- /dev/null +++ b/lib/krb5/krb5_get_forwarded_creds.3 @@ -0,0 +1,79 @@ +.\" Copyright (c) 2004 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_get_forwarded_creds.3 14068 2004-07-26 13:34:33Z lha $ +.\" +.Dd July 26, 2004 +.Dt KRB5_GET_FORWARDED_CREDS 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_get_forwarded_creds , +.Nm krb5_fwd_tgt_creds +.Nd get forwarded credentials from the KDC +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Ft krb5_error_code +.Fo krb5_get_forwarded_creds +.Fa "krb5_context context" +.Fa "krb5_auth_context auth_context" +.Fa "krb5_ccache ccache" +.Fa "krb5_flags flags" +.Fa "const char *hostname" +.Fa "krb5_creds *in_creds" +.Fa "krb5_data *out_data" +.Fc +.Ft krb5_error_code +.Fo krb5_fwd_tgt_creds +.Fa "krb5_context context" +.Fa "krb5_auth_context auth_context" +.Fa "const char *hostname" +.Fa "krb5_principal client" +.Fa "krb5_principal server" +.Fa "krb5_ccache ccache" +.Fa "int forwardable" +.Fa "krb5_data *out_data" +.Fc +.Sh DESCRIPTION +.Fn krb5_get_forwarded_creds +and +.Fn krb5_fwd_tgt_creds +get tickets forwarded to +.Fa hostname. +If the tickets that are forwarded are address-less, the forwarded +tickets will also be address-less, otherwise +.Fa hostname +will be used for figure out the address to forward the ticket too. +.Sh SEE ALSO +.Xr krb5 3 , +.Xr krb5_get_credentials 3 , +.Xr krb5.conf 5 diff --git a/lib/krb5/krb5_get_in_cred.3 b/lib/krb5/krb5_get_in_cred.3 new file mode 100644 index 0000000..290e3c5 --- /dev/null +++ b/lib/krb5/krb5_get_in_cred.3 @@ -0,0 +1,274 @@ +.\" Copyright (c) 2003 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_get_in_cred.3 17593 2006-05-29 14:55:18Z lha $ +.\" +.Dd May 31, 2003 +.Dt KRB5_GET_IN_TKT 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_get_in_tkt , +.Nm krb5_get_in_cred , +.Nm krb5_get_in_tkt_with_password , +.Nm krb5_get_in_tkt_with_keytab , +.Nm krb5_get_in_tkt_with_skey , +.Nm krb5_free_kdc_rep , +.Nm krb5_password_key_proc +.Nd deprecated initial authentication functions +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Pp +.Ft krb5_error_code +.Fo krb5_get_in_tkt +.Fa "krb5_context context" +.Fa "krb5_flags options" +.Fa "const krb5_addresses *addrs" +.Fa "const krb5_enctype *etypes" +.Fa "const krb5_preauthtype *ptypes" +.Fa "krb5_key_proc key_proc" +.Fa "krb5_const_pointer keyseed" +.Fa "krb5_decrypt_proc decrypt_proc" +.Fa "krb5_const_pointer decryptarg" +.Fa "krb5_creds *creds" +.Fa "krb5_ccache ccache" +.Fa "krb5_kdc_rep *ret_as_reply" +.Fc +.Ft krb5_error_code +.Fo krb5_get_in_cred +.Fa "krb5_context context" +.Fa "krb5_flags options" +.Fa "const krb5_addresses *addrs" +.Fa "const krb5_enctype *etypes" +.Fa "const krb5_preauthtype *ptypes" +.Fa "const krb5_preauthdata *preauth" +.Fa "krb5_key_proc key_proc" +.Fa "krb5_const_pointer keyseed" +.Fa "krb5_decrypt_proc decrypt_proc" +.Fa "krb5_const_pointer decryptarg" +.Fa "krb5_creds *creds" +.Fa "krb5_kdc_rep *ret_as_reply" +.Fc +.Ft krb5_error_code +.Fo krb5_get_in_tkt_with_password +.Fa "krb5_context context" +.Fa "krb5_flags options" +.Fa "krb5_addresses *addrs" +.Fa "const krb5_enctype *etypes" +.Fa "const krb5_preauthtype *pre_auth_types" +.Fa "const char *password" +.Fa "krb5_ccache ccache" +.Fa "krb5_creds *creds" +.Fa "krb5_kdc_rep *ret_as_reply" +.Fc +.Ft krb5_error_code +.Fo krb5_get_in_tkt_with_keytab +.Fa "krb5_context context" +.Fa "krb5_flags options" +.Fa "krb5_addresses *addrs" +.Fa "const krb5_enctype *etypes" +.Fa "const krb5_preauthtype *pre_auth_types" +.Fa "krb5_keytab keytab" +.Fa "krb5_ccache ccache" +.Fa "krb5_creds *creds" +.Fa "krb5_kdc_rep *ret_as_reply" +.Fc +.Ft krb5_error_code +.Fo krb5_get_in_tkt_with_skey +.Fa "krb5_context context" +.Fa "krb5_flags options" +.Fa "krb5_addresses *addrs" +.Fa "const krb5_enctype *etypes" +.Fa "const krb5_preauthtype *pre_auth_types" +.Fa "const krb5_keyblock *key" +.Fa "krb5_ccache ccache" +.Fa "krb5_creds *creds" +.Fa "krb5_kdc_rep *ret_as_reply" +.Fc +.Ft krb5_error_code +.Fo krb5_free_kdc_rep +.Fa "krb5_context context" +.Fa "krb5_kdc_rep *rep" +.Fc +.Ft krb5_error_code +.Fo krb5_password_key_proc +.Fa "krb5_context context" +.Fa "krb5_enctype type" +.Fa "krb5_salt salt" +.Fa "krb5_const_pointer keyseed" +.Fa "krb5_keyblock **key" +.Fc +.Sh DESCRIPTION +.Bf Em +All the functions in this manual page are deprecated in the MIT +implementation, and will soon be deprecated in Heimdal too, don't use them. +.Ef +.Pp +Getting initial credential ticket for a principal. +.Nm krb5_get_in_cred +is the function all other krb5_get_in function uses to fetch tickets. +The other krb5_get_in function are more specialized and therefor +somewhat easier to use. +.Pp +If your need is only to verify a user and password, consider using +.Xr krb5_verify_user 3 +instead, it have a much simpler interface. +.Pp +.Nm krb5_get_in_tkt +and +.Nm krb5_get_in_cred +fetches initial credential, queries after key using the +.Fa key_proc +argument. +The differences between the two function is that +.Nm krb5_get_in_tkt +stores the credential in a +.Li krb5_creds +while +.Nm krb5_get_in_cred +stores the credential in a +.Li krb5_ccache . +.Pp +.Nm krb5_get_in_tkt_with_password , +.Nm krb5_get_in_tkt_with_keytab , +and +.Nm krb5_get_in_tkt_with_skey +does the same work as +.Nm krb5_get_in_cred +but are more specialized. +.Pp +.Nm krb5_get_in_tkt_with_password +uses the clients password to authenticate. +If the password argument is +.DV NULL +the user user queried with the default password query function. +.Pp +.Nm krb5_get_in_tkt_with_keytab +searches the given keytab for a service entry for the client principal. +If the keytab is +.Dv NULL +the default keytab is used. +.Pp +.Nm krb5_get_in_tkt_with_skey +uses a key to get the initial credential. +.Pp +There are some common arguments to the krb5_get_in functions, these are: +.Pp +.Fa options +are the +.Dv KDC_OPT +flags. +.Pp +.Fa etypes +is a +.Dv NULL +terminated array of encryption types that the client approves. +.Pp +.Fa addrs +a list of the addresses that the initial ticket. +If it is +.Dv NULL +the list will be generated by the library. +.Pp +.Fa pre_auth_types +a +.Dv NULL +terminated array of pre-authentication types. +If +.Fa pre_auth_types +is +.Dv NULL +the function will try without pre-authentication and return those +pre-authentication that the KDC returned. +.Pp +.Fa ret_as_reply +will (if not +.Dv NULL ) +be filled in with the response of the KDC and should be free with +.Fn krb5_free_kdc_rep . +.Pp +.Fa key_proc +is a pointer to a function that should return a key salted appropriately. +Using +.Dv NULL +will use the default password query function. +.Pp +.Fa decrypt_proc +Using +.Dv NULL +will use the default decryption function. +.Pp +.Fa decryptarg +will be passed to the decryption function +.Fa decrypt_proc . +.Pp +.Fa creds +creds should be filled in with the template for a credential that +should be requested. +The client and server elements of the creds structure must be filled in. +Upon return of the function it will be contain the content of the +requested credential +.Fa ( krb5_get_in_cred ) , +or it will be freed with +.Xr krb5_free_creds 3 +(all the other krb5_get_in functions). +.Pp +.Fa ccache +will store the credential in the credential cache +.Fa ccache . +The credential cache will not be initialized, thats up the the caller. +.Pp +.Nm krb5_password_key_proc +is a library function that is suitable using as the +.Fa krb5_key_proc +argument to +.Nm krb5_get_in_cred +or +.Nm krb5_get_in_tkt . +.Fa keyseed +should be a pointer to a +.Dv NUL +terminated string or +.Dv NULL . +.Nm krb5_password_key_proc +will query the user for the pass on the console if the password isn't +given as the argument +.Fa keyseed . +.Pp +.Fn krb5_free_kdc_rep +frees the content of +.Fa rep . +.Sh SEE ALSO +.Xr krb5 3 , +.Xr krb5_verify_user 3 , +.Xr krb5.conf 5 , +.Xr kerberos 8 diff --git a/lib/krb5/krb5_get_init_creds.3 b/lib/krb5/krb5_get_init_creds.3 new file mode 100644 index 0000000..3838c14 --- /dev/null +++ b/lib/krb5/krb5_get_init_creds.3 @@ -0,0 +1,398 @@ +.\" Copyright (c) 2003 - 2007 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_get_init_creds.3 20266 2007-02-18 10:41:10Z lha $ +.\" +.Dd Sep 16, 2006 +.Dt KRB5_GET_INIT_CREDS 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_get_init_creds , +.Nm krb5_get_init_creds_keytab , +.Nm krb5_get_init_creds_opt , +.Nm krb5_get_init_creds_opt_alloc , +.Nm krb5_get_init_creds_opt_free , +.Nm krb5_get_init_creds_opt_init , +.Nm krb5_get_init_creds_opt_set_address_list , +.Nm krb5_get_init_creds_opt_set_addressless , +.Nm krb5_get_init_creds_opt_set_anonymous , +.Nm krb5_get_init_creds_opt_set_default_flags , +.Nm krb5_get_init_creds_opt_set_etype_list , +.Nm krb5_get_init_creds_opt_set_forwardable , +.Nm krb5_get_init_creds_opt_set_pa_password , +.Nm krb5_get_init_creds_opt_set_paq_request , +.Nm krb5_get_init_creds_opt_set_preauth_list , +.Nm krb5_get_init_creds_opt_set_proxiable , +.Nm krb5_get_init_creds_opt_set_renew_life , +.Nm krb5_get_init_creds_opt_set_salt , +.Nm krb5_get_init_creds_opt_set_tkt_life , +.Nm krb5_get_init_creds_opt_set_canonicalize , +.Nm krb5_get_init_creds_opt_set_win2k , +.Nm krb5_get_init_creds_password , +.Nm krb5_prompt , +.Nm krb5_prompter_posix +.Nd Kerberos 5 initial authentication functions +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Pp +.Ft krb5_get_init_creds_opt; +.Pp +.Ft krb5_error_code +.Fo krb5_get_init_creds_opt_alloc +.Fa "krb5_context context" +.Fa "krb5_get_init_creds_opt **opt" +.Fc +.Ft void +.Fo krb5_get_init_creds_opt_free +.Fa "krb5_context context" +.Fa "krb5_get_init_creds_opt *opt" +.Fc +.Ft void +.Fo krb5_get_init_creds_opt_init +.Fa "krb5_get_init_creds_opt *opt" +.Fc +.Ft void +.Fo krb5_get_init_creds_opt_set_address_list +.Fa "krb5_get_init_creds_opt *opt" +.Fa "krb5_addresses *addresses" +.Fc +.Ft void +.Fo krb5_get_init_creds_opt_set_addressless +.Fa "krb5_get_init_creds_opt *opt" +.Fa "krb5_boolean addressless" +.Fc +.Ft void +.Fo krb5_get_init_creds_opt_set_anonymous +.Fa "krb5_get_init_creds_opt *opt" +.Fa "int anonymous" +.Fc +.Ft void +.Fo krb5_get_init_creds_opt_set_default_flags +.Fa "krb5_context context" +.Fa "const char *appname" +.Fa "krb5_const_realm realm" +.Fa "krb5_get_init_creds_opt *opt" +.Fc +.Ft void +.Fo krb5_get_init_creds_opt_set_etype_list +.Fa "krb5_get_init_creds_opt *opt" +.Fa "krb5_enctype *etype_list" +.Fa "int etype_list_length" +.Fc +.Ft void +.Fo krb5_get_init_creds_opt_set_forwardable +.Fa "krb5_get_init_creds_opt *opt" +.Fa "int forwardable" +.Fc +.Ft krb5_error_code +.Fo krb5_get_init_creds_opt_set_pa_password +.Fa "krb5_context context" +.Fa "krb5_get_init_creds_opt *opt" +.Fa "const char *password" +.Fa "krb5_s2k_proc key_proc" +.Fc +.Ft krb5_error_code +.Fo krb5_get_init_creds_opt_set_paq_request +.Fa "krb5_context context" +.Fa "krb5_get_init_creds_opt *opt" +.Fa "krb5_boolean req_pac" +.Fc +.Ft krb5_error_code +.Fo krb5_get_init_creds_opt_set_pkinit +.Fa "krb5_context context" +.Fa "krb5_get_init_creds_opt *opt" +.Fa "const char *cert_file" +.Fa "const char *key_file" +.Fa "const char *x509_anchors" +.Fa "int flags" +.Fa "char *password" +.Fc +.Ft void +.Fo krb5_get_init_creds_opt_set_preauth_list +.Fa "krb5_get_init_creds_opt *opt" +.Fa "krb5_preauthtype *preauth_list" +.Fa "int preauth_list_length" +.Fc +.Ft void +.Fo krb5_get_init_creds_opt_set_proxiable +.Fa "krb5_get_init_creds_opt *opt" +.Fa "int proxiable" +.Fc +.Ft void +.Fo krb5_get_init_creds_opt_set_renew_life +.Fa "krb5_get_init_creds_opt *opt" +.Fa "krb5_deltat renew_life" +.Fc +.Ft void +.Fo krb5_get_init_creds_opt_set_salt +.Fa "krb5_get_init_creds_opt *opt" +.Fa "krb5_data *salt" +.Fc +.Ft void +.Fo krb5_get_init_creds_opt_set_tkt_life +.Fa "krb5_get_init_creds_opt *opt" +.Fa "krb5_deltat tkt_life" +.Fc +.Ft krb5_error_code +.Fo krb5_get_init_creds_opt_set_canonicalize +.Fa "krb5_context context" +.Fa "krb5_get_init_creds_opt *opt" +.Fa "krb5_boolean req" +.Fc +.Ft krb5_error_code +.Fo krb5_get_init_creds_opt_set_win2k +.Fa "krb5_context context" +.Fa "krb5_get_init_creds_opt *opt" +.Fa "krb5_boolean req" +.Fc +.Ft krb5_error_code +.Fo krb5_get_init_creds +.Fa "krb5_context context" +.Fa "krb5_creds *creds" +.Fa "krb5_principal client" +.Fa "krb5_prompter_fct prompter" +.Fa "void *prompter_data" +.Fa "krb5_deltat start_time" +.Fa "const char *in_tkt_service" +.Fa "krb5_get_init_creds_opt *options" +.Fc +.Ft krb5_error_code +.Fo krb5_get_init_creds_password +.Fa "krb5_context context" +.Fa "krb5_creds *creds" +.Fa "krb5_principal client" +.Fa "const char *password" +.Fa "krb5_prompter_fct prompter" +.Fa "void *prompter_data" +.Fa "krb5_deltat start_time" +.Fa "const char *in_tkt_service" +.Fa "krb5_get_init_creds_opt *in_options" +.Fc +.Ft krb5_error_code +.Fo krb5_get_init_creds_keytab +.Fa "krb5_context context" +.Fa "krb5_creds *creds" +.Fa "krb5_principal client" +.Fa "krb5_keytab keytab" +.Fa "krb5_deltat start_time" +.Fa "const char *in_tkt_service" +.Fa "krb5_get_init_creds_opt *options" +.Fc +.Ft int +.Fo krb5_prompter_posix +.Fa "krb5_context context" +.Fa "void *data" +.Fa "const char *name" +.Fa "const char *banner" +.Fa "int num_prompts" +.Fa "krb5_prompt prompts[]" +.Fc +.Sh DESCRIPTION +Getting initial credential ticket for a principal. +That may include changing an expired password, and doing preauthentication. +This interface that replaces the deprecated +.Fa krb5_in_tkt +and +.Fa krb5_in_cred +functions. +.Pp +If you only want to verify a username and password, consider using +.Xr krb5_verify_user 3 +instead, since it also verifies that initial credentials with using a +keytab to make sure the response was from the KDC. +.Pp +First a +.Li krb5_get_init_creds_opt +structure is initialized +with +.Fn krb5_get_init_creds_opt_alloc +or +.Fn krb5_get_init_creds_opt_init . +.Fn krb5_get_init_creds_opt_alloc +allocates a extendible structures that needs to be freed with +.Fn krb5_get_init_creds_opt_free . +The structure may be modified by any of the +.Fn krb5_get_init_creds_opt_set +functions to change request parameters and authentication information. +.Pp +If the caller want to use the default options, +.Dv NULL +can be passed instead. +.Pp +The the actual request to the KDC is done by any of the +.Fn krb5_get_init_creds , +.Fn krb5_get_init_creds_password , +or +.Fn krb5_get_init_creds_keytab +functions. +.Fn krb5_get_init_creds +is the least specialized function and can, with the right in data, +behave like the latter two. +The latter two are there for compatibility with older releases and +they are slightly easier to use. +.Pp +.Li krb5_prompt +is a structure containing the following elements: +.Bd -literal +typedef struct { + const char *prompt; + int hidden; + krb5_data *reply; + krb5_prompt_type type +} krb5_prompt; +.Ed +.Pp +.Fa prompt +is the prompt that should shown to the user +If +.Fa hidden +is set, the prompter function shouldn't echo the output to the display +device. +.Fa reply +must be preallocated; it will not be allocated by the prompter +function. +Possible values for the +.Fa type +element are: +.Pp +.Bl -tag -width Ds -compact -offset indent +.It KRB5_PROMPT_TYPE_PASSWORD +.It KRB5_PROMPT_TYPE_NEW_PASSWORD +.It KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN +.It KRB5_PROMPT_TYPE_PREAUTH +.It KRB5_PROMPT_TYPE_INFO +.El +.Pp +.Fn krb5_prompter_posix +is the default prompter function in a POSIX environment. +It matches the +.Fa krb5_prompter_fct +and can be used in the +.Fa krb5_get_init_creds +functions. +.Fn krb5_prompter_posix +doesn't require +.Fa prompter_data. +.Pp +If the +.Fa start_time +is zero, then the requested ticket will be valid +beginning immediately. +Otherwise, the +.Fa start_time +indicates how far in the future the ticket should be postdated. +.Pp +If the +.Fa in_tkt_service +name is +.Dv non-NULL , +that principal name will be +used as the server name for the initial ticket request. +The realm of the name specified will be ignored and will be set to the +realm of the client name. +If no in_tkt_service name is specified, +krbtgt/CLIENT-REALM@CLIENT-REALM will be used. +.Pp +For the rest of arguments, a configuration or library default will be +used if no value is specified in the options structure. +.Pp +.Fn krb5_get_init_creds_opt_set_address_list +sets the list of +.Fa addresses +that is should be stored in the ticket. +.Pp +.Fn krb5_get_init_creds_opt_set_addressless +controls if the ticket is requested with addresses or not, +.Fn krb5_get_init_creds_opt_set_address_list +overrides this option. +.Pp +.Fn krb5_get_init_creds_opt_set_anonymous +make the request anonymous if the +.Fa anonymous +parameter is non-zero. +.Pp +.Fn krb5_get_init_creds_opt_set_default_flags +sets the default flags using the configuration file. +.Pp +.Fn krb5_get_init_creds_opt_set_etype_list +set a list of enctypes that the client is willing to support in the +request. +.Pp +.Fn krb5_get_init_creds_opt_set_forwardable +request a forwardable ticket. +.Pp +.Fn krb5_get_init_creds_opt_set_pa_password +set the +.Fa password +and +.Fa key_proc +that is going to be used to get a new ticket. +.Fa password +or +.Fa key_proc +can be +.Dv NULL +if the caller wants to use the default values. +If the +.Fa password +is unset and needed, the user will be prompted for it. +.Pp +.Fn krb5_get_init_creds_opt_set_paq_request +sets the password that is going to be used to get a new ticket. +.Pp +.Fn krb5_get_init_creds_opt_set_preauth_list +sets the list of client-supported preauth types. +.Pp +.Fn krb5_get_init_creds_opt_set_proxiable +makes the request proxiable. +.Pp +.Fn krb5_get_init_creds_opt_set_renew_life +sets the requested renewable lifetime. +.Pp +.Fn krb5_get_init_creds_opt_set_salt +sets the salt that is going to be used in the request. +.Pp +.Fn krb5_get_init_creds_opt_set_tkt_life +sets requested ticket lifetime. +.Pp +.Fn krb5_get_init_creds_opt_set_canonicalize +requests that the KDC canonicalize the client pricipal if possible. +.Pp +.Fn krb5_get_init_creds_opt_set_win2k +turns on compatibility with Windows 2000. +.Sh SEE ALSO +.Xr krb5 3 , +.Xr krb5_creds 3 , +.Xr krb5_verify_user 3 , +.Xr krb5.conf 5 , +.Xr kerberos 8 diff --git a/lib/krb5/krb5_get_krbhst.3 b/lib/krb5/krb5_get_krbhst.3 new file mode 100644 index 0000000..d613a0d --- /dev/null +++ b/lib/krb5/krb5_get_krbhst.3 @@ -0,0 +1,86 @@ +.\" Copyright (c) 2001 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_get_krbhst.3 14905 2005-04-24 07:46:59Z lha $ +.\" +.Dd April 24, 2005 +.Dt KRB5_GET_KRBHST 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_get_krbhst , +.Nm krb5_get_krb_admin_hst , +.Nm krb5_get_krb_changepw_hst , +.Nm krb5_get_krb524hst , +.Nm krb5_free_krbhst +.Nd lookup Kerberos KDC hosts +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Ft krb5_error_code +.Fn krb5_get_krbhst "krb5_context context" "const krb5_realm *realm" "char ***hostlist" +.Ft krb5_error_code +.Fn krb5_get_krb_admin_hst "krb5_context context" "const krb5_realm *realm" "char ***hostlist" +.Ft krb5_error_code +.Fn krb5_get_krb_changepw_hst "krb5_context context" "const krb5_realm *realm" "char ***hostlist" +.Ft krb5_error_code +.Fn krb5_get_krb524hst "krb5_context context" "const krb5_realm *realm" "char ***hostlist" +.Ft krb5_error_code +.Fn krb5_free_krbhst "krb5_context context" "char **hostlist" +.Sh DESCRIPTION +These functions implement the old API to get a list of Kerberos hosts, +and are thus similar to the +.Fn krb5_krbhst_init +functions. However, since these functions returns +.Em all +hosts in one go, they potentially have to do more lookups than +necessary. These functions remain for compatibility reasons. +.Pp +After a call to one of these functions, +.Fa hostlist +is a +.Dv NULL +terminated list of strings, pointing to the requested Kerberos hosts. These should be freed with +.Fn krb5_free_krbhst +when done with. +.Sh EXAMPLES +The following code will print the KDCs of the realm +.Dq MY.REALM . +.Bd -literal -offset indent +char **hosts, **p; +krb5_get_krbhst(context, "MY.REALM", &hosts); +for(p = hosts; *p; p++) + printf("%s\\n", *p); +krb5_free_krbhst(context, hosts); +.Ed +.\" .Sh BUGS +.Sh SEE ALSO +.Xr krb5_krbhst_init 3 diff --git a/lib/krb5/krb5_getportbyname.3 b/lib/krb5/krb5_getportbyname.3 new file mode 100644 index 0000000..1436060 --- /dev/null +++ b/lib/krb5/krb5_getportbyname.3 @@ -0,0 +1,67 @@ +.\" Copyright (c) 2004 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_getportbyname.3 22071 2007-11-14 20:04:50Z lha $ +.\" +.Dd August 15, 2004 +.Dt NAME 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_getportbyname +.Nd get port number by name +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Ft int +.Fo krb5_getportbyname +.Fa "krb5_context context" +.Fa "const char *service" +.Fa "const char *proto" +.Fa "int default_port" +.Fc +.Sh DESCRIPTION +.Fn krb5_getportbyname +gets the port number for +.Fa service / +.Fa proto +pair from the global service table for and returns it in network order. +If it isn't found in the global table, the +.Fa default_port +(given in host order) +is returned. +.Sh EXAMPLE +.Bd -literal +int port = krb5_getportbyname(context, "kerberos", "tcp", 88); +.Ed +.\" .Sh BUGS +.Sh SEE ALSO +.Xr krb5 3 diff --git a/lib/krb5/krb5_init_context.3 b/lib/krb5/krb5_init_context.3 new file mode 100644 index 0000000..cf9d696 --- /dev/null +++ b/lib/krb5/krb5_init_context.3 @@ -0,0 +1,308 @@ +.\" Copyright (c) 2001 - 2004 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_init_context.3 19980 2007-01-17 18:06:33Z lha $ +.\" +.Dd December 8, 2004 +.Dt KRB5_CONTEXT 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_add_et_list , +.Nm krb5_add_extra_addresses , +.Nm krb5_add_ignore_addresses , +.Nm krb5_context , +.Nm krb5_free_config_files , +.Nm krb5_free_context , +.Nm krb5_get_default_config_files , +.Nm krb5_get_dns_canonize_hostname , +.Nm krb5_get_extra_addresses , +.Nm krb5_get_fcache_version , +.Nm krb5_get_ignore_addresses , +.Nm krb5_get_kdc_sec_offset , +.Nm krb5_get_max_time_skew , +.Nm krb5_get_use_admin_kdc +.Nm krb5_init_context , +.Nm krb5_init_ets , +.Nm krb5_prepend_config_files , +.Nm krb5_prepend_config_files_default , +.Nm krb5_set_config_files , +.Nm krb5_set_dns_canonize_hostname , +.Nm krb5_set_extra_addresses , +.Nm krb5_set_fcache_version , +.Nm krb5_set_ignore_addresses , +.Nm krb5_set_max_time_skew , +.Nm krb5_set_use_admin_kdc , +.Nd create, modify and delete krb5_context structures +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Pp +.Li "struct krb5_context;" +.Pp +.Ft krb5_error_code +.Fo krb5_init_context +.Fa "krb5_context *context" +.Fc +.Ft void +.Fo krb5_free_context +.Fa "krb5_context context" +.Fc +.Ft void +.Fo krb5_init_ets +.Fa "krb5_context context" +.Fc +.Ft krb5_error_code +.Fo krb5_add_et_list +.Fa "krb5_context context" +.Fa "void (*func)(struct et_list **)" +.Fc +.Ft krb5_error_code +.Fo krb5_add_extra_addresses +.Fa "krb5_context context" +.Fa "krb5_addresses *addresses" +.Fc +.Ft krb5_error_code +.Fo krb5_set_extra_addresses +.Fa "krb5_context context" +.Fa "const krb5_addresses *addresses" +.Fc +.Ft krb5_error_code +.Fo krb5_get_extra_addresses +.Fa "krb5_context context" +.Fa "krb5_addresses *addresses" +.Fc +.Ft krb5_error_code +.Fo krb5_add_ignore_addresses +.Fa "krb5_context context" +.Fa "krb5_addresses *addresses" +.Fc +.Ft krb5_error_code +.Fo krb5_set_ignore_addresses +.Fa "krb5_context context" +.Fa "const krb5_addresses *addresses" +.Fc +.Ft krb5_error_code +.Fo krb5_get_ignore_addresses +.Fa "krb5_context context" +.Fa "krb5_addresses *addresses" +.Fc +.Ft krb5_error_code +.Fo krb5_set_fcache_version +.Fa "krb5_context context" +.Fa "int version" +.Fc +.Ft krb5_error_code +.Fo krb5_get_fcache_version +.Fa "krb5_context context" +.Fa "int *version" +.Fc +.Ft void +.Fo krb5_set_dns_canonize_hostname +.Fa "krb5_context context" +.Fa "krb5_boolean flag" +.Fc +.Ft krb5_boolean +.Fo krb5_get_dns_canonize_hostname +.Fa "krb5_context context" +.Fc +.Ft krb5_error_code +.Fo krb5_get_kdc_sec_offset +.Fa "krb5_context context" +.Fa "int32_t *sec" +.Fa "int32_t *usec" +.Fc +.Ft krb5_error_code +.Fo krb5_set_config_files +.Fa "krb5_context context" +.Fa "char **filenames" +.Fc +.Ft krb5_error_code +.Fo krb5_prepend_config_files +.Fa "const char *filelist" +.Fa "char **pq" +.Fa "char ***ret_pp" +.Fc +.Ft krb5_error_code +.Fo krb5_prepend_config_files_default +.Fa "const char *filelist" +.Fa "char ***pfilenames" +.Fc +.Ft krb5_error_code +.Fo krb5_get_default_config_files +.Fa "char ***pfilenames" +.Fc +.Ft void +.Fo krb5_free_config_files +.Fa "char **filenames" +.Fc +.Ft void +.Fo krb5_set_use_admin_kdc +.Fa "krb5_context context" +.Fa "krb5_boolean flag" +.Fc +.Ft krb5_boolean +.Fo krb5_get_use_admin_kdc +.Fa "krb5_context context" +.Fc +.Ft time_t +.Fo krb5_get_max_time_skew +.Fa "krb5_context context" +.Fc +.Ft krb5_error_code +.Fo krb5_set_max_time_skew +.Fa "krb5_context context" +.Fa "time_t time" +.Fc +.Sh DESCRIPTION +The +.Fn krb5_init_context +function initializes the +.Fa context +structure and reads the configuration file +.Pa /etc/krb5.conf . +.Pp +The structure should be freed by calling +.Fn krb5_free_context +when it is no longer being used. +.Pp +.Fn krb5_init_context +returns 0 to indicate success. +Otherwise an errno code is returned. +Failure means either that something bad happened during initialization +(typically +.Bq ENOMEM ) +or that Kerberos should not be used +.Bq ENXIO . +.Pp +.Fn krb5_init_ets +adds all +.Xr com_err 3 +libs to +.Fa context . +This is done by +.Fn krb5_init_context . +.Pp +.Fn krb5_add_et_list +adds a +.Xr com_err 3 +error-code handler +.Fa func +to the specified +.Fa context . +The error handler must generated by the the re-rentrant version of the +.Xr compile_et 3 +program. +.Fn krb5_add_extra_addresses +add a list of addresses that should be added when requesting tickets. +.Pp +.Fn krb5_add_ignore_addresses +add a list of addresses that should be ignored when requesting tickets. +.Pp +.Fn krb5_get_extra_addresses +get the list of addresses that should be added when requesting tickets. +.Pp +.Fn krb5_get_ignore_addresses +get the list of addresses that should be ignored when requesting tickets. +.Pp +.Fn krb5_set_ignore_addresses +set the list of addresses that should be ignored when requesting tickets. +.Pp +.Fn krb5_set_extra_addresses +set the list of addresses that should be added when requesting tickets. +.Pp +.Fn krb5_set_fcache_version +sets the version of file credentials caches that should be used. +.Pp +.Fn krb5_get_fcache_version +gets the version of file credentials caches that should be used. +.Pp +.Fn krb5_set_dns_canonize_hostname +sets if the context is configured to canonicalize hostnames using DNS. +.Pp +.Fn krb5_get_dns_canonize_hostname +returns if the context is configured to canonicalize hostnames using DNS. +.Pp +.Fn krb5_get_kdc_sec_offset +returns the offset between the localtime and the KDC's time. +.Fa sec +and +.Fa usec +are both optional argument and +.Dv NULL +can be passed in. +.Pp +.Fn krb5_set_config_files +set the list of configuration files to use and re-initialize the +configuration from the files. +.Pp +.Fn krb5_prepend_config_files +parse the +.Fa filelist +and prepend the result to the already existing list +.Fa pq +The result is returned in +.Fa ret_pp +and should be freed with +.Fn krb5_free_config_files . +.Pp +.Fn krb5_prepend_config_files_default +parse the +.Fa filelist +and append that to the default +list of configuration files. +.Pp +.Fn krb5_get_default_config_files +get a list of default configuration files. +.Pp +.Fn krb5_free_config_files +free a list of configuration files returned by +.Fn krb5_get_default_config_files , +.Fn krb5_prepend_config_files_default , +or +.Fn krb5_prepend_config_files . +.Pp +.Fn krb5_set_use_admin_kdc +sets if all KDC requests should go admin KDC. +.Pp +.Fn krb5_get_use_admin_kdc +gets if all KDC requests should go admin KDC. +.Pp +.Fn krb5_get_max_time_skew +and +.Fn krb5_set_max_time_skew +get and sets the maximum allowed time skew between client and server. +.Sh SEE ALSO +.Xr errno 2 , +.Xr krb5 3 , +.Xr krb5_config 3 , +.Xr krb5_context 3 , +.Xr kerberos 8 diff --git a/lib/krb5/krb5_is_thread_safe.3 b/lib/krb5/krb5_is_thread_safe.3 new file mode 100644 index 0000000..9f0a919 --- /dev/null +++ b/lib/krb5/krb5_is_thread_safe.3 @@ -0,0 +1,58 @@ +.\" Copyright (c) 2005 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_is_thread_safe.3 17462 2006-05-05 13:18:39Z lha $ +.\" +.Dd May 5, 2006 +.Dt KRB5_IS_THREAD_SAFE 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_is_thread_safe +.Nd "is the Kerberos library compiled with multithread support" +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Ft krb5_boolean +.Fn krb5_is_thread_safe "void" +.Sh DESCRIPTION +.Nm +returns +.Dv TRUE +if the library was compiled with with multithread support. +If the library isn't compiled, the consumer have to use a global lock +to make sure Kerboros functions are not called at the same time by +diffrent threads. +.\" .Sh EXAMPLE +.\" .Sh BUGS +.Sh SEE ALSO +.Xr krb5_create_checksum 3 , +.Xr krb5_encrypt 3 diff --git a/lib/krb5/krb5_keyblock.3 b/lib/krb5/krb5_keyblock.3 new file mode 100644 index 0000000..9fabd32 --- /dev/null +++ b/lib/krb5/krb5_keyblock.3 @@ -0,0 +1,218 @@ +.\" Copyright (c) 2003 - 2004 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_keyblock.3 17385 2006-05-01 08:48:55Z lha $ +.\" +.Dd May 1, 2006 +.Dt KRB5_KEYBLOCK 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_keyblock , +.Nm krb5_keyblock_get_enctype , +.Nm krb5_copy_keyblock , +.Nm krb5_copy_keyblock_contents , +.Nm krb5_free_keyblock , +.Nm krb5_free_keyblock_contents , +.Nm krb5_generate_random_keyblock , +.Nm krb5_generate_subkey , +.Nm krb5_generate_subkey_extended , +.Nm krb5_keyblock_init , +.Nm krb5_keyblock_zero , +.Nm krb5_random_to_key +.Nd Kerberos 5 key handling functions +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Pp +.Li krb5_keyblock ; +.Ft krb5_enctype +.Fo krb5_keyblock_get_enctype +.Fa "const krb5_keyblock *block" +.Fc +.Ft krb5_error_code +.Fo krb5_copy_keyblock +.Fa "krb5_context context" +.Fa "krb5_keyblock **to" +.Fc +.Ft krb5_error_code +.Fo krb5_copy_keyblock_contents +.Fa "krb5_context context" +.Fa "const krb5_keyblock *inblock" +.Fa "krb5_keyblock *to" +.Fc +.Ft void +.Fo krb5_free_keyblock +.Fa "krb5_context context" +.Fa "krb5_keyblock *keyblock" +.Fc +.Ft void +.Fo krb5_free_keyblock_contents +.Fa "krb5_context context" +.Fa "krb5_keyblock *keyblock" +.Fc +.Ft krb5_error_code +.Fo krb5_generate_random_keyblock +.Fa "krb5_context context" +.Fa "krb5_enctype type" +.Fa "krb5_keyblock *key" +.Fc +.Ft krb5_error_code +.Fo krb5_generate_subkey +.Fa "krb5_context context" +.Fa "const krb5_keyblock *key" +.Fa "krb5_keyblock **subkey" +.Fc +.Ft krb5_error_code +.Fo krb5_generate_subkey_extended +.Fa "krb5_context context" +.Fa "const krb5_keyblock *key" +.Fa "krb5_enctype enctype" +.Fa "krb5_keyblock **subkey" +.Fc +.Ft krb5_error_code +.Fo krb5_keyblock_init +.Fa "krb5_context context" +.Fa "krb5_enctype type" +.Fa "const void *data" +.Fa "size_t size" +.Fa "krb5_keyblock *key" +.Fc +.Ft void +.Fo krb5_keyblock_zero +.Fa "krb5_keyblock *keyblock" +.Fc +.Ft krb5_error_code +.Fo krb5_random_to_key +.Fa "krb5_context context" +.Fa "krb5_enctype type" +.Fa "const void *data" +.Fa "size_t size" +.Fa "krb5_keyblock *key" +.Fc +.Sh DESCRIPTION +.Li krb5_keyblock +holds the encryption key for a specific encryption type. +There is no component inside +.Li krb5_keyblock +that is directly referable. +.Pp +.Fn krb5_keyblock_get_enctype +returns the encryption type of the keyblock. +.Pp +.Fn krb5_copy_keyblock +makes a copy the keyblock +.Fa inblock +to the +output +.Fa out . +.Fa out +should be freed by the caller with +.Fa krb5_free_keyblock . +.Pp +.Fn krb5_copy_keyblock_contents +copies the contents of +.Fa inblock +to the +.Fa to +keyblock. +The destination keyblock is overritten. +.Pp +.Fn krb5_free_keyblock +zeros out and frees the content and the keyblock itself. +.Pp +.Fn krb5_free_keyblock_contents +zeros out and frees the content of the keyblock. +.Pp +.Fn krb5_generate_random_keyblock +creates a new content of the keyblock +.Fa key +of type encrytion type +.Fa type . +The content of +.Fa key +is overwritten and not freed, so the caller should be sure it is +freed before calling the function. +.Pp +.Fn krb5_generate_subkey +generates a +.Fa subkey +of the same type as +.Fa key . +The caller must free the subkey with +.Fa krb5_free_keyblock . +.Pp +.Fn krb5_generate_subkey_extended +generates a +.Fa subkey +of the specified encryption type +.Fa type . +If +.Fa type +is +.Dv ETYPE_NULL , +of the same type as +.Fa key . +The caller must free the subkey with +.Fa krb5_free_keyblock . +.Pp +.Fn krb5_keyblock_init +Fill in +.Fa key +with key data of type +.Fa enctype +from +.Fa data +of length +.Fa size . +Key should be freed using +.Fn krb5_free_keyblock_contents . +.Pp +.Fn krb5_keyblock_zero +zeros out the keyblock to to make sure no keymaterial is in +memory. +Note that +.Fn krb5_free_keyblock_contents +also zeros out the memory. +.Pp +.Fn krb5_random_to_key +converts the random bytestring to a protocol key according to Kerberos +crypto frame work. +It the resulting key will be of type +.Fa enctype . +It may be assumed that all the bits of the input string are equally +random, even though the entropy present in the random source may be +limited +.\" .Sh EXAMPLES +.Sh SEE ALSO +.Xr krb5_crypto_init 3 , +.Xr krb5 3 , +.Xr krb5.conf 5 diff --git a/lib/krb5/krb5_keytab.3 b/lib/krb5/krb5_keytab.3 new file mode 100644 index 0000000..b6cb1a2 --- /dev/null +++ b/lib/krb5/krb5_keytab.3 @@ -0,0 +1,482 @@ +.\" Copyright (c) 2001 - 2005 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_keytab.3 22071 2007-11-14 20:04:50Z lha $ +.\" +.Dd August 12, 2005 +.Dt KRB5_KEYTAB 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_kt_ops , +.Nm krb5_keytab_entry , +.Nm krb5_kt_cursor , +.Nm krb5_kt_add_entry , +.Nm krb5_kt_close , +.Nm krb5_kt_compare , +.Nm krb5_kt_copy_entry_contents , +.Nm krb5_kt_default , +.Nm krb5_kt_default_modify_name , +.Nm krb5_kt_default_name , +.Nm krb5_kt_end_seq_get , +.Nm krb5_kt_free_entry , +.Nm krb5_kt_get_entry , +.Nm krb5_kt_get_name , +.Nm krb5_kt_get_type , +.Nm krb5_kt_next_entry , +.Nm krb5_kt_read_service_key , +.Nm krb5_kt_register , +.Nm krb5_kt_remove_entry , +.Nm krb5_kt_resolve , +.Nm krb5_kt_start_seq_get +.Nd manage keytab (key storage) files +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Pp +.Ft krb5_error_code +.Fo krb5_kt_add_entry +.Fa "krb5_context context" +.Fa "krb5_keytab id" +.Fa "krb5_keytab_entry *entry" +.Fc +.Ft krb5_error_code +.Fo krb5_kt_close +.Fa "krb5_context context" +.Fa "krb5_keytab id" +.Fc +.Ft krb5_boolean +.Fo krb5_kt_compare +.Fa "krb5_context context" +.Fa "krb5_keytab_entry *entry" +.Fa "krb5_const_principal principal" +.Fa "krb5_kvno vno" +.Fa "krb5_enctype enctype" +.Fc +.Ft krb5_error_code +.Fo krb5_kt_copy_entry_contents +.Fa "krb5_context context" +.Fa "const krb5_keytab_entry *in" +.Fa "krb5_keytab_entry *out" +.Fc +.Ft krb5_error_code +.Fo krb5_kt_default +.Fa "krb5_context context" +.Fa "krb5_keytab *id" +.Fc +.Ft krb5_error_code +.Fo krb5_kt_default_modify_name +.Fa "krb5_context context" +.Fa "char *name" +.Fa "size_t namesize" +.Fc +.Ft krb5_error_code +.Fo krb5_kt_default_name +.Fa "krb5_context context" +.Fa "char *name" +.Fa "size_t namesize" +.Fc +.Ft krb5_error_code +.Fo krb5_kt_end_seq_get +.Fa "krb5_context context" +.Fa "krb5_keytab id" +.Fa "krb5_kt_cursor *cursor" +.Fc +.Ft krb5_error_code +.Fo krb5_kt_free_entry +.Fa "krb5_context context" +.Fa "krb5_keytab_entry *entry" +.Fc +.Ft krb5_error_code +.Fo krb5_kt_get_entry +.Fa "krb5_context context" +.Fa "krb5_keytab id" +.Fa "krb5_const_principal principal" +.Fa "krb5_kvno kvno" +.Fa "krb5_enctype enctype" +.Fa "krb5_keytab_entry *entry" +.Fc +.Ft krb5_error_code +.Fo krb5_kt_get_name +.Fa "krb5_context context" +.Fa "krb5_keytab keytab" +.Fa "char *name" +.Fa "size_t namesize" +.Fc +.Ft krb5_error_code +.Fo krb5_kt_get_type +.Fa "krb5_context context" +.Fa "krb5_keytab keytab" +.Fa "char *prefix" +.Fa "size_t prefixsize" +.Fc +.Ft krb5_error_code +.Fo krb5_kt_next_entry +.Fa "krb5_context context" +.Fa "krb5_keytab id" +.Fa "krb5_keytab_entry *entry" +.Fa "krb5_kt_cursor *cursor" +.Fc +.Ft krb5_error_code +.Fo krb5_kt_read_service_key +.Fa "krb5_context context" +.Fa "krb5_pointer keyprocarg" +.Fa "krb5_principal principal" +.Fa "krb5_kvno vno" +.Fa "krb5_enctype enctype" +.Fa "krb5_keyblock **key" +.Fc +.Ft krb5_error_code +.Fo krb5_kt_register +.Fa "krb5_context context" +.Fa "const krb5_kt_ops *ops" +.Fc +.Ft krb5_error_code +.Fo krb5_kt_remove_entry +.Fa "krb5_context context" +.Fa "krb5_keytab id" +.Fa "krb5_keytab_entry *entry" +.Fc +.Ft krb5_error_code +.Fo krb5_kt_resolve +.Fa "krb5_context context" +.Fa "const char *name" +.Fa "krb5_keytab *id" +.Fc +.Ft krb5_error_code +.Fo krb5_kt_start_seq_get +.Fa "krb5_context context" +.Fa "krb5_keytab id" +.Fa "krb5_kt_cursor *cursor" +.Fc +.Sh DESCRIPTION +A keytab name is on the form +.Li type:residual . +The +.Li residual +part is specific to each keytab-type. +.Pp +When a keytab-name is resolved, the type is matched with an internal +list of keytab types. If there is no matching keytab type, +the default keytab is used. The current default type is +.Nm file . +The default value can be changed in the configuration file +.Pa /etc/krb5.conf +by setting the variable +.Li [defaults]default_keytab_name . +.Pp +The keytab types that are implemented in Heimdal +are: +.Bl -tag -width Ds +.It Nm file +store the keytab in a file, the type's name is +.Li FILE . +The residual part is a filename. +For compatibility with other Kerberos implemtation +.Li WRFILE +and +.LI JAVA14 +is also accepted. +.Li WRFILE +has the same format as +.Li FILE . +.Li JAVA14 +have a format that is compatible with older versions of MIT kerberos +and SUN's Java based installation. They store a truncted kvno, so +when the knvo excess 255, they are truncted in this format. +.It Nm keyfile +store the keytab in a +.Li AFS +keyfile (usually +.Pa /usr/afs/etc/KeyFile ) , +the type's name is +.Li AFSKEYFILE . +The residual part is a filename. +.It Nm krb4 +the keytab is a Kerberos 4 +.Pa srvtab +that is on-the-fly converted to a keytab. The type's name is +.Li krb4 . +The residual part is a filename. +.It Nm memory +The keytab is stored in a memory segment. This allows sensitive and/or +temporary data not to be stored on disk. The type's name is +.Li MEMORY . +Each +.Li MEMORY +keytab is referenced counted by and opened by the residual name, so two +handles can point to the same memory area. +When the last user closes the entry, it disappears. +.El +.Pp +.Nm krb5_keytab_entry +holds all data for an entry in a keytab file, like principal name, +key-type, key, key-version number, etc. +.Nm krb5_kt_cursor +holds the current position that is used when iterating through a +keytab entry with +.Fn krb5_kt_start_seq_get , +.Fn krb5_kt_next_entry , +and +.Fn krb5_kt_end_seq_get . +.Pp +.Nm krb5_kt_ops +contains the different operations that can be done to a keytab. This +structure is normally only used when doing a new keytab-type +implementation. +.Pp +.Fn krb5_kt_resolve +is the equivalent of an +.Xr open 2 +on keytab. Resolve the keytab name in +.Fa name +into a keytab in +.Fa id . +Returns 0 or an error. The opposite of +.Fn krb5_kt_resolve +is +.Fn krb5_kt_close . +.Pp +.Fn krb5_kt_close +frees all resources allocated to the keytab, even on failure. +Returns 0 or an error. +.Pp +.Fn krb5_kt_default +sets the argument +.Fa id +to the default keytab. +Returns 0 or an error. +.Pp +.Fn krb5_kt_default_modify_name +copies the name of the default modify keytab into +.Fa name . +Return 0 or KRB5_CONFIG_NOTENUFSPACE if +.Fa namesize +is too short. +.Pp +.Fn krb5_kt_default_name +copies the name of the default keytab into +.Fa name . +Return 0 or KRB5_CONFIG_NOTENUFSPACE if +.Fa namesize +is too short. +.Pp +.Fn krb5_kt_add_entry +adds a new +.Fa entry +to the keytab +.Fa id . +.Li KRB5_KT_NOWRITE +is returned if the keytab is a readonly keytab. +.Pp +.Fn krb5_kt_compare +compares the passed in +.Fa entry +against +.Fa principal , +.Fa vno , +and +.Fa enctype . +Any of +.Fa principal , +.Fa vno +or +.Fa enctype +might be 0 which acts as a wildcard. Return TRUE if they compare the +same, FALSE otherwise. +.Pp +.Fn krb5_kt_copy_entry_contents +copies the contents of +.Fa in +into +.Fa out . +Returns 0 or an error. +.Pp +.Fn krb5_kt_get_name +retrieves the name of the keytab +.Fa keytab +into +.Fa name , +.Fa namesize . +Returns 0 or an error. +.Pp +.Fn krb5_kt_get_type +retrieves the type of the keytab +.Fa keytab +and store the prefix/name for type of the keytab into +.Fa prefix , +.Fa prefixsize . +The prefix will have the maximum length of +.Dv KRB5_KT_PREFIX_MAX_LEN +(including terminating +.Dv NUL ) . +Returns 0 or an error. +.Pp +.Fn krb5_kt_free_entry +frees the contents of +.Fa entry . +.Pp +.Fn krb5_kt_start_seq_get +sets +.Fa cursor +to point at the beginning of +.Fa id . +Returns 0 or an error. +.Pp +.Fn krb5_kt_next_entry +gets the next entry from +.Fa id +pointed to by +.Fa cursor +and advance the +.Fa cursor . +On success the returne entry must be freed with +.Fn krb5_kt_free_entry . +Returns 0 or an error. +.Pp +.Fn krb5_kt_end_seq_get +releases all resources associated with +.Fa cursor . +.Pp +.Fn krb5_kt_get_entry +retrieves the keytab entry for +.Fa principal , +.Fa kvno , +.Fa enctype +into +.Fa entry +from the keytab +.Fa id . +When comparing an entry in the keytab to determine a match, the +function +.Fn krb5_kt_compare +is used, so the wildcard rules applies to the argument of +.F krb5_kt_get_entry +too. +On success the returne entry must be freed with +.Fn krb5_kt_free_entry . +Returns 0 or an error. +.Pp +.Fn krb5_kt_read_service_key +reads the key identified by +.Fa ( principal , +.Fa vno , +.Fa enctype ) +from the keytab in +.Fa keyprocarg +(the system default keytab if +.Dv NULL +is used) into +.Fa *key . +.Fa keyprocarg +is the same argument as to +.Fa name +argument to +.Fn krb5_kt_resolve . +Internal +.Fn krb5_kt_compare +will be used, so the same wildcard rules applies +to +.Fn krb5_kt_read_service_key . +On success the returned key must be freed with +.Fa krb5_free_keyblock . +Returns 0 or an error. +.Pp +.Fn krb5_kt_remove_entry +removes the entry +.Fa entry +from the keytab +.Fa id . +When comparing an entry in the keytab to determine a match, the +function +.Fn krb5_kt_compare +is use, so the wildcard rules applies to the argument of +.Fn krb5_kt_remove_entry . +Returns 0, +.Dv KRB5_KT_NOTFOUND +if not entry matched or another error. +.Pp +.Fn krb5_kt_register +registers a new keytab type +.Fa ops . +Returns 0 or an error. +.Sh EXAMPLES +This is a minimalistic version of +.Nm ktutil . +.Pp +.Bd -literal +int +main (int argc, char **argv) +{ + krb5_context context; + krb5_keytab keytab; + krb5_kt_cursor cursor; + krb5_keytab_entry entry; + krb5_error_code ret; + char *principal; + + if (krb5_init_context (&context) != 0) + errx(1, "krb5_context"); + + ret = krb5_kt_default (context, &keytab); + if (ret) + krb5_err(context, 1, ret, "krb5_kt_default"); + + ret = krb5_kt_start_seq_get(context, keytab, &cursor); + if (ret) + krb5_err(context, 1, ret, "krb5_kt_start_seq_get"); + while((ret = krb5_kt_next_entry(context, keytab, &entry, &cursor)) == 0){ + krb5_unparse_name_short(context, entry.principal, &principal); + printf("principal: %s\\n", principal); + free(principal); + krb5_kt_free_entry(context, &entry); + } + ret = krb5_kt_end_seq_get(context, keytab, &cursor); + if (ret) + krb5_err(context, 1, ret, "krb5_kt_end_seq_get"); + ret = krb5_kt_close(context, keytab); + if (ret) + krb5_err(context, 1, ret, "krb5_kt_close"); + krb5_free_context(context); + return 0; +} +.Ed +.Sh COMPATIBILITY +Heimdal stored the ticket flags in machine bit-field order before +Heimdal 0.7. The behavior is possible to change in with the option +.Li [libdefaults]fcc-mit-ticketflags . +Heimdal 0.7 also code to detech that ticket flags was in the wrong +order and correct them. This matters when doing delegation in GSS-API +because the client code looks at the flag to determin if it is possible +to do delegation if the user requested it. +.Sh SEE ALSO +.Xr krb5.conf 5 , +.Xr kerberos 8 diff --git a/lib/krb5/krb5_krbhst_init.3 b/lib/krb5/krb5_krbhst_init.3 new file mode 100644 index 0000000..1d906bf --- /dev/null +++ b/lib/krb5/krb5_krbhst_init.3 @@ -0,0 +1,174 @@ +.\" Copyright (c) 2001-2005 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_krbhst_init.3 15110 2005-05-10 09:21:06Z lha $ +.\" +.Dd May 10, 2005 +.Dt KRB5_KRBHST_INIT 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_krbhst_init , +.Nm krb5_krbhst_init_flags , +.Nm krb5_krbhst_next , +.Nm krb5_krbhst_next_as_string , +.Nm krb5_krbhst_reset , +.Nm krb5_krbhst_free , +.Nm krb5_krbhst_format_string , +.Nm krb5_krbhst_get_addrinfo +.Nd lookup Kerberos KDC hosts +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Ft krb5_error_code +.Fn krb5_krbhst_init "krb5_context context" "const char *realm" "unsigned int type" "krb5_krbhst_handle *handle" +.Ft krb5_error_code +.Fn krb5_krbhst_init_flags "krb5_context context" "const char *realm" "unsigned int type" "int flags" "krb5_krbhst_handle *handle" +.Ft krb5_error_code +.Fn "krb5_krbhst_next" "krb5_context context" "krb5_krbhst_handle handle" "krb5_krbhst_info **host" +.Ft krb5_error_code +.Fn krb5_krbhst_next_as_string "krb5_context context" "krb5_krbhst_handle handle" "char *hostname" "size_t hostlen" +.Ft void +.Fn krb5_krbhst_reset "krb5_context context" "krb5_krbhst_handle handle" +.Ft void +.Fn krb5_krbhst_free "krb5_context context" "krb5_krbhst_handle handle" +.Ft krb5_error_code +.Fn krb5_krbhst_format_string "krb5_context context" "const krb5_krbhst_info *host" "char *hostname" "size_t hostlen" +.Ft krb5_error_code +.Fn krb5_krbhst_get_addrinfo "krb5_context context" "krb5_krbhst_info *host" "struct addrinfo **ai" +.Sh DESCRIPTION +These functions are used to sequence through all Kerberos hosts of a +particular realm and service. The service type can be the KDCs, the +administrative servers, the password changing servers, or the servers +for Kerberos 4 ticket conversion. +.Pp +First a handle to a particular service is obtained by calling +.Fn krb5_krbhst_init +(or +.Fn krb5_krbhst_init_flags ) +with the +.Fa realm +of interest and the type of service to lookup. The +.Fa type +can be one of: +.Pp +.Bl -tag -width Ds -compact -offset indent +.It KRB5_KRBHST_KDC +.It KRB5_KRBHST_ADMIN +.It KRB5_KRBHST_CHANGEPW +.It KRB5_KRBHST_KRB524 +.El +.Pp +The +.Fa handle +is returned to the caller, and should be passed to the other +functions. +.Pp +The +.Fa flag +argument to +.Nm krb5_krbhst_init_flags +is the same flags as +.Fn krb5_send_to_kdc_flags +uses. +Possible values are: +.Pp +.Bl -tag -width KRB5_KRBHST_FLAGS_LARGE_MSG -compact -offset indent +.It KRB5_KRBHST_FLAGS_MASTER +only talk to master (readwrite) KDC +.It KRB5_KRBHST_FLAGS_LARGE_MSG +this is a large message, so use transport that can handle that. +.El +.Pp +For each call to +.Fn krb5_krbhst_next +information on a new host is returned. The former function returns in +.Fa host +a pointer to a structure containing information about the host, such +as protocol, hostname, and port: +.Bd -literal -offset indent +typedef struct krb5_krbhst_info { + enum { KRB5_KRBHST_UDP, + KRB5_KRBHST_TCP, + KRB5_KRBHST_HTTP } proto; + unsigned short port; + struct addrinfo *ai; + struct krb5_krbhst_info *next; + char hostname[1]; +} krb5_krbhst_info; +.Ed +.Pp +The related function, +.Fn krb5_krbhst_next_as_string , +return the same information as a URL-like string. +.Pp +When there are no more hosts, these functions return +.Dv KRB5_KDC_UNREACH . +.Pp +To re-iterate over all hosts, call +.Fn krb5_krbhst_reset +and the next call to +.Fn krb5_krbhst_next +will return the first host. +.Pp +When done with the handle, +.Fn krb5_krbhst_free +should be called. +.Pp +To use a +.Va krb5_krbhst_info , +there are two functions: +.Fn krb5_krbhst_format_string +that will return a printable representation of that struct +and +.Fn krb5_krbhst_get_addrinfo +that will return a +.Va struct addrinfo +that can then be used for communicating with the server mentioned. +.Sh EXAMPLES +The following code will print the KDCs of the realm +.Dq MY.REALM : +.Bd -literal -offset indent +krb5_krbhst_handle handle; +char host[MAXHOSTNAMELEN]; +krb5_krbhst_init(context, "MY.REALM", KRB5_KRBHST_KDC, &handle); +while(krb5_krbhst_next_as_string(context, handle, + host, sizeof(host)) == 0) + printf("%s\\n", host); +krb5_krbhst_free(context, handle); +.Ed +.\" .Sh BUGS +.Sh SEE ALSO +.Xr getaddrinfo 3 , +.Xr krb5_get_krbhst 3 , +.Xr krb5_send_to_kdc_flags 3 +.Sh HISTORY +These functions first appeared in Heimdal 0.3g. diff --git a/lib/krb5/krb5_kuserok.3 b/lib/krb5/krb5_kuserok.3 new file mode 100644 index 0000000..e5e5c99 --- /dev/null +++ b/lib/krb5/krb5_kuserok.3 @@ -0,0 +1,103 @@ +.\" Copyright (c) 2003-2005 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_kuserok.3 15083 2005-05-04 12:11:22Z joda $ +.\" +.Dd May 4, 2005 +.Dt KRB5_KUSEROK 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_kuserok +.Nd "checks if a principal is permitted to login as a user" +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Ft krb5_boolean +.Fo krb5_kuserok +.Fa "krb5_context context" +.Fa "krb5_principal principal" +.Fa "const char *user" +.Fc +.Sh DESCRIPTION +This function takes the name of a local +.Fa user +and checks if +.Fa principal +is allowed to log in as that user. +.Pp +The +.Fa user +may have a +.Pa ~/.k5login +file listing principals that are allowed to login as that user. If +that file does not exist, all principals with a first component +identical to the username, and a realm considered local, are allowed +access. +.Pp +The +.Pa .k5login +file must contain one principal per line, be owned by +.Fa user , +and not be writable by group or other (but must be readable by +anyone). +.Pp +Note that if the file exists, no implicit access rights are given to +.Fa user Ns @ Ns Aq localrealm . +.Pp +Optionally, a set of files may be put in +.Pa ~/.k5login.d ( Ns +a directory), in which case they will all be checked in the same +manner as +.Pa .k5login . +The files may be called anything, but files starting with a hash +.Dq ( # ) , +or ending with a tilde +.Dq ( ~ ) +are ignored. Subdirectories are not traversed. Note that this +directory may not be checked by other implementations. +.Sh RETURN VALUES +.Nm +returns +.Dv TRUE +if access should be granted, +.Dv FALSE +otherwise. +.Sh HISTORY +The +.Pa ~/.k5login.d +feature appeared in Heimdal 0.7. +.Sh SEE ALSO +.Xr krb5_get_default_realms 3 , +.Xr krb5_verify_user 3 , +.Xr krb5_verify_user_lrealm 3 , +.Xr krb5_verify_user_opt 3 , +.Xr krb5.conf 5 diff --git a/lib/krb5/krb5_locl.h b/lib/krb5/krb5_locl.h new file mode 100644 index 0000000..8b7c41c --- /dev/null +++ b/lib/krb5/krb5_locl.h @@ -0,0 +1,267 @@ +/* + * Copyright (c) 1997-2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $Id: krb5_locl.h 22226 2007-12-08 21:31:53Z lha $ */ + +#ifndef __KRB5_LOCL_H__ +#define __KRB5_LOCL_H__ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <errno.h> +#include <ctype.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <limits.h> + +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_SYS_MMAN_H +#include <sys/mman.h> +#endif +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif + +#if defined(HAVE_SYS_IOCTL_H) && SunOS != 40 +#include <sys/ioctl.h> +#endif +#ifdef HAVE_PWD_H +#undef _POSIX_PTHREAD_SEMANTICS +/* This gets us the 5-arg getpwnam_r on Solaris 9. */ +#define _POSIX_PTHREAD_SEMANTICS +#include <pwd.h> +#endif + +#ifdef HAVE_SYS_PARAM_H +#include <sys/param.h> +#endif +#include <time.h> +#ifdef HAVE_SYS_TIME_H +#include <sys/time.h> +#endif +#ifdef HAVE_SYS_SELECT_H +#include <sys/select.h> +#endif +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif +#ifdef HAVE_NETINET_IN6_H +#include <netinet/in6.h> +#endif +#ifdef HAVE_NETINET6_IN6_H +#include <netinet6/in6.h> +#endif +#ifdef HAVE_NETDB_H +#include <netdb.h> +#endif +#ifdef _AIX +struct ether_addr; +struct mbuf; +struct sockaddr_dl; +#endif +#ifdef HAVE_ARPA_INET_H +#include <arpa/inet.h> +#endif +#ifdef HAVE_ARPA_NAMESER_H +#include <arpa/nameser.h> +#endif +#ifdef HAVE_SYS_UIO_H +#include <sys/uio.h> +#endif +#ifdef HAVE_SYS_FILIO_H +#include <sys/filio.h> +#endif +#ifdef HAVE_SYS_FILE_H +#include <sys/file.h> +#endif + +#ifdef HAVE_CRYPT_H +#undef des_encrypt +#define des_encrypt wingless_pigs_mostly_fail_to_fly +#include <crypt.h> +#undef des_encrypt +#endif + +#ifdef HAVE_DOOR_CREATE +#include <door.h> +#endif + +#include <roken.h> +#include <parse_time.h> +#include <base64.h> + +#include "crypto-headers.h" + + +#include <krb5_asn1.h> + +struct send_to_kdc; + +/* XXX glue for pkinit */ +struct krb5_pk_identity; +struct krb5_pk_cert; +struct ContentInfo; +typedef struct krb5_pk_init_ctx_data *krb5_pk_init_ctx; +struct krb5_dh_moduli; + +/* v4 glue */ +struct _krb5_krb_auth_data; + +#include <der.h> + +#include <krb5.h> +#include <krb5_err.h> +#include <asn1_err.h> +#ifdef PKINIT +#include <hx509_err.h> +#endif +#include <krb5-private.h> + +#include "heim_threads.h" + +#define ALLOC(X, N) (X) = calloc((N), sizeof(*(X))) +#define ALLOC_SEQ(X, N) do { (X)->len = (N); ALLOC((X)->val, (N)); } while(0) + +/* should this be public? */ +#define KEYTAB_DEFAULT "ANY:FILE:" SYSCONFDIR "/krb5.keytab,krb4:" SYSCONFDIR "/srvtab" +#define KEYTAB_DEFAULT_MODIFY "FILE:" SYSCONFDIR "/krb5.keytab" + +#define MODULI_FILE SYSCONFDIR "/krb5.moduli" + +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +#define KRB5_BUFSIZ 1024 + +typedef enum { + KRB5_INIT_CREDS_TRISTATE_UNSET = 0, + KRB5_INIT_CREDS_TRISTATE_TRUE, + KRB5_INIT_CREDS_TRISTATE_FALSE +} krb5_get_init_creds_tristate; + +struct _krb5_get_init_creds_opt_private { + int refcount; + /* ENC_TIMESTAMP */ + const char *password; + krb5_s2k_proc key_proc; + /* PA_PAC_REQUEST */ + krb5_get_init_creds_tristate req_pac; + /* PKINIT */ + krb5_pk_init_ctx pk_init_ctx; + KRB_ERROR *error; + krb5_get_init_creds_tristate addressless; + int flags; +#define KRB5_INIT_CREDS_CANONICALIZE 1 +#define KRB5_INIT_CREDS_NO_C_CANON_CHECK 2 +}; + +typedef struct krb5_context_data { + krb5_enctype *etypes; + krb5_enctype *etypes_des; + char **default_realms; + time_t max_skew; + time_t kdc_timeout; + unsigned max_retries; + int32_t kdc_sec_offset; + int32_t kdc_usec_offset; + krb5_config_section *cf; + struct et_list *et_list; + struct krb5_log_facility *warn_dest; + krb5_cc_ops *cc_ops; + int num_cc_ops; + const char *http_proxy; + const char *time_fmt; + krb5_boolean log_utc; + const char *default_keytab; + const char *default_keytab_modify; + krb5_boolean use_admin_kdc; + krb5_addresses *extra_addresses; + krb5_boolean scan_interfaces; /* `ifconfig -a' */ + krb5_boolean srv_lookup; /* do SRV lookups */ + krb5_boolean srv_try_txt; /* try TXT records also */ + int32_t fcache_vno; /* create cache files w/ this + version */ + int num_kt_types; /* # of registered keytab types */ + struct krb5_keytab_data *kt_types; /* registered keytab types */ + const char *date_fmt; + char *error_string; + char error_buf[256]; + krb5_addresses *ignore_addresses; + char *default_cc_name; + char *default_cc_name_env; + int default_cc_name_set; + void *mutex; /* protects error_string/error_buf */ + int large_msg_size; + int flags; +#define KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME 1 +#define KRB5_CTX_F_CHECK_PAC 2 + struct send_to_kdc *send_to_kdc; +} krb5_context_data; + +#define KRB5_DEFAULT_CCNAME_FILE "FILE:/tmp/krb5cc_%{uid}" +#define KRB5_DEFAULT_CCNAME_API "API:" +#define KRB5_DEFAULT_CCNAME_KCM "KCM:%{uid}" + +#define EXTRACT_TICKET_ALLOW_CNAME_MISMATCH 1 +#define EXTRACT_TICKET_ALLOW_SERVER_MISMATCH 2 +#define EXTRACT_TICKET_MATCH_REALM 4 + +/* + * Configurable options + */ + +#ifndef KRB5_DEFAULT_CCTYPE +#ifdef __APPLE__ +#define KRB5_DEFAULT_CCTYPE (&krb5_acc_ops) +#else +#define KRB5_DEFAULT_CCTYPE (&krb5_fcc_ops) +#endif +#endif + +#ifndef KRB5_ADDRESSLESS_DEFAULT +#define KRB5_ADDRESSLESS_DEFAULT TRUE +#endif + +#endif /* __KRB5_LOCL_H__ */ diff --git a/lib/krb5/krb5_mk_req.3 b/lib/krb5/krb5_mk_req.3 new file mode 100644 index 0000000..e37d8e7 --- /dev/null +++ b/lib/krb5/krb5_mk_req.3 @@ -0,0 +1,187 @@ +.\" Copyright (c) 2005 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_mk_req.3 16100 2005-09-26 05:38:55Z lha $ +.\" +.Dd August 27, 2005 +.Dt KRB5_MK_REQ 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_mk_req , +.Nm krb5_mk_req_exact , +.Nm krb5_mk_req_extended , +.Nm krb5_rd_req , +.Nm krb5_rd_req_with_keyblock , +.Nm krb5_mk_rep , +.Nm krb5_mk_rep_exact , +.Nm krb5_mk_rep_extended , +.Nm krb5_rd_rep , +.Nm krb5_build_ap_req , +.Nm krb5_verify_ap_req +.Nd create and read application authentication request +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Ft krb5_error_code +.Fo krb5_mk_req +.Fa "krb5_context context" +.Fa "krb5_auth_context *auth_context" +.Fa "const krb5_flags ap_req_options" +.Fa "const char *service" +.Fa "const char *hostname" +.Fa "krb5_data *in_data" +.Fa "krb5_ccache ccache" +.Fa "krb5_data *outbuf" +.Fc +.Ft krb5_error_code +.Fo krb5_mk_req_extended +.Fa "krb5_context context" +.Fa "krb5_auth_context *auth_context" +.Fa "const krb5_flags ap_req_options" +.Fa "krb5_data *in_data" +.Fa "krb5_creds *in_creds" +.Fa "krb5_data *outbuf" +.Fc +.Ft krb5_error_code +.Fo krb5_rd_req +.Fa "krb5_context context" +.Fa "krb5_auth_context *auth_context" +.Fa "const krb5_data *inbuf" +.Fa "krb5_const_principal server" +.Fa "krb5_keytab keytab" +.Fa "krb5_flags *ap_req_options" +.Fa "krb5_ticket **ticket" +.Fc +.Ft krb5_error_code +.Fo krb5_build_ap_req +.Fa "krb5_context context" +.Fa "krb5_enctype enctype" +.Fa "krb5_creds *cred" +.Fa "krb5_flags ap_options" +.Fa "krb5_data authenticator" +.Fa "krb5_data *retdata" +.Fc +.Ft krb5_error_code +.Fo krb5_verify_ap_req +.Fa "krb5_context context" +.Fa "krb5_auth_context *auth_context" +.Fa "krb5_ap_req *ap_req" +.Fa "krb5_const_principal server" +.Fa "krb5_keyblock *keyblock" +.Fa "krb5_flags flags" +.Fa "krb5_flags *ap_req_options" +.Fa "krb5_ticket **ticket" +.Fc +.Sh DESCRIPTION +The functions documented in this manual page document the functions +that facilitates the exchange between a Kerberos client and server. +They are the core functions used in the authentication exchange +between the client and the server. +.Pp +The +.Nm krb5_mk_req +and +.Nm krb5_mk_req_extended +creates the Kerberos message +.Dv KRB_AP_REQ +that is sent from the client to the server as the first packet in a client/server exchange. The result that should be sent to server is stored in +.Fa outbuf . +.Pp +.Fa auth_context +should be allocated with +.Fn krb5_auth_con_init +or +.Dv NULL +passed in, in that case, it will be allocated and freed internally. +.Pp +The input data +.Fa in_data +will have a checksum calculated over it and checksum will be +transported in the message to the server. +.Pp +.Fa ap_req_options +can be set to one or more of the following flags: +.Pp +.Bl -tag -width indent +.It Dv AP_OPTS_USE_SESSION_KEY +Use the session key when creating the request, used for user to user +authentication. +.It Dv AP_OPTS_MUTUAL_REQUIRED +Mark the request as mutual authenticate required so that the receiver +returns a mutual authentication packet. +.El +.Pp +The +.Nm krb5_rd_req +read the AP_REQ in +.Fa inbuf +and verify and extract the content. +If +.Fa server +is specified, that server will be fetched from the +.Fa keytab +and used unconditionally. +If +.Fa server +is +.Dv NULL , +the +.Fa keytab +will be search for a matching principal. +.Pp +The +.Fa keytab +argument specifies what keytab to search for receiving principals. +The arguments +.Fa ap_req_options +and +.Fa ticket +returns the content. +.Pp +When the AS-REQ is a user to user request, neither of +.Fa keytab +or +.Fa principal +are used, instead +.Fn krb5_rd_req +expects the session key to be set in +.Fa auth_context . +.Pp +The +.Nm krb5_verify_ap_req +and +.Nm krb5_build_ap_req +both constructs and verify the AP_REQ message, should not be used by +external code. +.Sh SEE ALSO +.Xr krb5 3 , +.Xr krb5.conf 5 diff --git a/lib/krb5/krb5_mk_safe.3 b/lib/krb5/krb5_mk_safe.3 new file mode 100644 index 0000000..25b6541 --- /dev/null +++ b/lib/krb5/krb5_mk_safe.3 @@ -0,0 +1,82 @@ +.\" Copyright (c) 2003 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_mk_safe.3 17385 2006-05-01 08:48:55Z lha $ +.\" +.Dd May 1, 2006 +.Dt KRB5_MK_SAFE 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_mk_safe , +.Nm krb5_mk_priv +.Nd generates integrity protected and/or encrypted messages +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Pp +.Ft krb5_error_code +.Fn krb5_mk_priv "krb5_context context" "krb5_auth_context auth_context" "const krb5_data *userdata" "krb5_data *outbuf" "krb5_replay_data *outdata" +.Ft krb5_error_code +.Fn krb5_mk_safe "krb5_context context" "krb5_auth_context auth_context" "const krb5_data *userdata" "krb5_data *outbuf" "krb5_replay_data *outdata" +.Sh DESCRIPTION +.Fn krb5_mk_safe +and +.Fn krb5_mk_priv +formats +.Li KRB-SAFE +(integrity protected) +and +.Li KRB-PRIV +(also encrypted) +messages into +.Fa outbuf . +The actual message data is taken from +.Fa userdata . +If the +.Dv KRB5_AUTH_CONTEXT_DO_SEQUENCE +or +.Dv KRB5_AUTH_CONTEXT_DO_TIME +flags are set in the +.Fa auth_context , +sequence numbers and time stamps are generated. +If the +.Dv KRB5_AUTH_CONTEXT_RET_SEQUENCE +or +.Dv KRB5_AUTH_CONTEXT_RET_TIME +flags are set +they are also returned in the +.Fa outdata +parameter. +.Sh SEE ALSO +.Xr krb5_auth_con_init 3 , +.Xr krb5_rd_priv 3 , +.Xr krb5_rd_safe 3 diff --git a/lib/krb5/krb5_openlog.3 b/lib/krb5/krb5_openlog.3 new file mode 100644 index 0000000..4acad41 --- /dev/null +++ b/lib/krb5/krb5_openlog.3 @@ -0,0 +1,242 @@ +.\" Copyright (c) 1997, 1999, 2001 - 2002 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_openlog.3 12329 2003-05-26 14:09:04Z lha $ +.Dd August 6, 1997 +.Dt KRB5_OPENLOG 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_initlog , +.Nm krb5_openlog , +.Nm krb5_closelog , +.Nm krb5_addlog_dest , +.Nm krb5_addlog_func , +.Nm krb5_log , +.Nm krb5_vlog , +.Nm krb5_log_msg , +.Nm krb5_vlog_msg +.Nd Heimdal logging functions +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Ft "typedef void" +.Fn "\*(lp*krb5_log_log_func_t\*(rp" "const char *time" "const char *message" "void *data" +.Ft "typedef void" +.Fn "\*(lp*krb5_log_close_func_t\*(rp" "void *data" +.Ft krb5_error_code +.Fn krb5_addlog_dest "krb5_context context" "krb5_log_facility *facility" "const char *destination" +.Ft krb5_error_code +.Fn krb5_addlog_func "krb5_context context" "krb5_log_facility *facility" "int min" "int max" "krb5_log_log_func_t log" "krb5_log_close_func_t close" "void *data" +.Ft krb5_error_code +.Fn krb5_closelog "krb5_context context" "krb5_log_facility *facility" +.Ft krb5_error_code +.Fn krb5_initlog "krb5_context context" "const char *program" "krb5_log_facility **facility" +.Ft krb5_error_code +.Fn krb5_log "krb5_context context" "krb5_log_facility *facility" "int level" "const char *format" "..." +.Ft krb5_error_code +.Fn krb5_log_msg "krb5_context context" "krb5_log_facility *facility" "char **reply" "int level" "const char *format" "..." +.Ft krb5_error_code +.Fn krb5_openlog "krb5_context context" "const char *program" "krb5_log_facility **facility" +.Ft krb5_error_code +.Fn krb5_vlog "krb5_context context" "krb5_log_facility *facility" "int level" "const char *format" "va_list arglist" +.Ft krb5_error_code +.Fn krb5_vlog_msg "krb5_context context" "krb5_log_facility *facility" "char **reply" "int level" "const char *format" "va_list arglist" +.Sh DESCRIPTION +These functions logs messages to one or more destinations. +.Pp +The +.Fn krb5_openlog +function creates a logging +.Fa facility , +that is used to log messages. A facility consists of one or more +destinations (which can be files or syslog or some other device). The +.Fa program +parameter should be the generic name of the program that is doing the +logging. This name is used to lookup which destinations to use. This +information is contained in the +.Li logging +section of the +.Pa krb5.conf +configuration file. If no entry is found for +.Fa program , +the entry for +.Li default +is used, or if that is missing too, +.Li SYSLOG +will be used as destination. +.Pp +To close a logging facility, use the +.Fn krb5_closelog +function. +.Pp +To log a message to a facility use one of the functions +.Fn krb5_log , +.Fn krb5_log_msg , +.Fn krb5_vlog , +or +.Fn krb5_vlog_msg . +The functions ending in +.Li _msg +return in +.Fa reply +a pointer to the message that just got logged. This string is allocated, +and should be freed with +.Fn free . +The +.Fa format +is a standard +.Fn printf +style format string (but see the BUGS section). +.Pp +If you want better control of where things gets logged, you can instead of using +.Fn krb5_openlog +call +.Fn krb5_initlog , +which just initializes a facility, but doesn't define any actual logging +destinations. You can then add destinations with the +.Fn krb5_addlog_dest +and +.Fn krb5_addlog_func +functions. The first of these takes a string specifying a logging +destination, and adds this to the facility. If you want to do some +non-standard logging you can use the +.Fn krb5_addlog_func +function, which takes a function to use when logging. +The +.Fa log +function is called for each message with +.Fa time +being a string specifying the current time, and +.Fa message +the message to log. +.Fa close +is called when the facility is closed. You can pass application specific data in the +.Fa data +parameter. The +.Fa min +and +.Fa max +parameter are the same as in a destination (defined below). To specify a +max of infinity, pass -1. +.Pp +.Fn krb5_openlog +calls +.Fn krb5_initlog +and then calls +.Fn krb5_addlog_dest +for each destination found. +.Ss Destinations +The defined destinations (as specified in +.Pa krb5.conf ) +follows: +.Bl -tag -width "xxx" -offset indent +.It Li STDERR +This logs to the program's stderr. +.It Li FILE: Ns Pa /file +.It Li FILE= Ns Pa /file +Log to the specified file. The form using a colon appends to the file, the +form with an equal truncates the file. The truncating form keeps the file +open, while the appending form closes it after each log message (which +makes it possible to rotate logs). The truncating form is mainly for +compatibility with the MIT libkrb5. +.It Li DEVICE= Ns Pa /device +This logs to the specified device, at present this is the same as +.Li FILE:/device . +.It Li CONSOLE +Log to the console, this is the same as +.Li DEVICE=/dev/console . +.It Li SYSLOG Ns Op :priority Ns Op :facility +Send messages to the syslog system, using priority, and facility. To +get the name for one of these, you take the name of the macro passed +to +.Xr syslog 3 , +and remove the leading +.Li LOG_ +.No ( Li LOG_NOTICE +becomes +.Li NOTICE ) . +The default values (as well as the values used for unrecognised +values), are +.Li ERR , +and +.Li AUTH , +respectively. See +.Xr syslog 3 +for a list of priorities and facilities. +.El +.Pp +Each destination may optionally be prepended with a range of logging +levels, specified as +.Li min-max/ . +If the +.Fa level +parameter to +.Fn krb5_log +is within this range (inclusive) the message gets logged to this +destination, otherwise not. Either of the min and max valued may be +omitted, in this case min is assumed to be zero, and max is assumed to be +infinity. If you don't include a dash, both min and max gets set to the +specified value. If no range is specified, all messages gets logged. +.Sh EXAMPLES +.Bd -literal -offset indent +[logging] + kdc = 0/FILE:/var/log/kdc.log + kdc = 1-/SYSLOG:INFO:USER + default = STDERR +.Ed +.Pp +This will log all messages from the +.Nm kdc +program with level 0 to +.Pa /var/log/kdc.log , +other messages will be logged to syslog with priority +.Li LOG_INFO , +and facility +.Li LOG_USER . +All other programs will log all messages to their stderr. +.Sh SEE ALSO +.Xr syslog 3 , +.Xr krb5.conf 5 +.Sh BUGS +These functions use +.Fn asprintf +to format the message. If your operating system does not have a working +.Fn asprintf , +a replacement will be used. At present this replacement does not handle +some correct conversion specifications (like floating point numbers). Until +this is fixed, the use of these conversions should be avoided. +.Pp +If logging is done to the syslog facility, these functions might not be +thread-safe, depending on the implementation of +.Fn openlog , +and +.Fn syslog . diff --git a/lib/krb5/krb5_parse_name.3 b/lib/krb5/krb5_parse_name.3 new file mode 100644 index 0000000..e876ee3 --- /dev/null +++ b/lib/krb5/krb5_parse_name.3 @@ -0,0 +1,68 @@ +.\" Copyright (c) 1997 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_parse_name.3 17385 2006-05-01 08:48:55Z lha $ +.\" +.Dd May 1, 2006 +.Dt KRB5_PARSE_NAME 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_parse_name +.Nd string to principal conversion +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Ft krb5_error_code +.Fn krb5_parse_name "krb5_context context" "const char *name" "krb5_principal *principal" +.Sh DESCRIPTION +.Fn krb5_parse_name +converts a string representation of a principal name to +.Nm krb5_principal . +The +.Fa principal +will point to allocated data that should be freed with +.Fn krb5_free_principal . +.Pp +The string should consist of one or more name components separated with slashes +.Pq Dq / , +optionally followed with an +.Dq @ +and a realm name. A slash or @ may be contained in a name component by +quoting it with a backslash +.Pq Dq \e . +A realm should not contain slashes or colons. +.Sh SEE ALSO +.Xr krb5_425_conv_principal 3 , +.Xr krb5_build_principal 3 , +.Xr krb5_free_principal 3 , +.Xr krb5_sname_to_principal 3 , +.Xr krb5_unparse_name 3 diff --git a/lib/krb5/krb5_principal.3 b/lib/krb5/krb5_principal.3 new file mode 100644 index 0000000..1b0c2da --- /dev/null +++ b/lib/krb5/krb5_principal.3 @@ -0,0 +1,384 @@ +.\" Copyright (c) 2003 - 2007 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_principal.3 21255 2007-06-21 04:36:31Z lha $ +.\" +.Dd May 1, 2006 +.Dt KRB5_PRINCIPAL 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_get_default_principal , +.Nm krb5_principal , +.Nm krb5_build_principal , +.Nm krb5_build_principal_ext , +.Nm krb5_build_principal_va , +.Nm krb5_build_principal_va_ext , +.Nm krb5_copy_principal , +.Nm krb5_free_principal , +.Nm krb5_make_principal , +.Nm krb5_parse_name , +.Nm krb5_parse_name_flags , +.Nm krb5_parse_nametype , +.Nm krb5_princ_realm , +.Nm krb5_princ_set_realm , +.Nm krb5_principal_compare , +.Nm krb5_principal_compare_any_realm , +.Nm krb5_principal_get_comp_string , +.Nm krb5_principal_get_realm , +.Nm krb5_principal_get_type , +.Nm krb5_principal_match , +.Nm krb5_principal_set_type , +.Nm krb5_realm_compare , +.Nm krb5_sname_to_principal , +.Nm krb5_sock_to_principal , +.Nm krb5_unparse_name , +.Nm krb5_unparse_name_flags , +.Nm krb5_unparse_name_fixed , +.Nm krb5_unparse_name_fixed_flags , +.Nm krb5_unparse_name_fixed_short , +.Nm krb5_unparse_name_short +.Nd Kerberos 5 principal handling functions +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Pp +.Li krb5_principal ; +.Ft void +.Fn krb5_free_principal "krb5_context context" "krb5_principal principal" +.Ft krb5_error_code +.Fn krb5_parse_name "krb5_context context" "const char *name" "krb5_principal *principal" +.Ft krb5_error_code +.Fn krb5_parse_name_flags "krb5_context context" "const char *name" "int flags" "krb5_principal *principal" +.Ft krb5_error_code +.Fn "krb5_unparse_name" "krb5_context context" "krb5_const_principal principal" "char **name" +.Ft krb5_error_code +.Fn "krb5_unparse_name_flags" "krb5_context context" "krb5_const_principal principal" "int flags" "char **name" +.Ft krb5_error_code +.Fn krb5_unparse_name_fixed "krb5_context context" "krb5_const_principal principal" "char *name" "size_t len" +.Ft krb5_error_code +.Fn krb5_unparse_name_fixed_flags "krb5_context context" "krb5_const_principal principal" "int flags" "char *name" "size_t len" +.Ft krb5_error_code +.Fn "krb5_unparse_name_short" "krb5_context context" "krb5_const_principal principal" "char **name" +.Ft krb5_error_code +.Fn krb5_unparse_name_fixed_short "krb5_context context" "krb5_const_principal principal" "char *name" "size_t len" +.Ft krb5_realm * +.Fn krb5_princ_realm "krb5_context context" "krb5_principal principal" +.Ft void +.Fn krb5_princ_set_realm "krb5_context context" "krb5_principal principal" "krb5_realm *realm" +.Ft krb5_error_code +.Fn krb5_build_principal "krb5_context context" "krb5_principal *principal" "int rlen" "krb5_const_realm realm" "..." +.Ft krb5_error_code +.Fn krb5_build_principal_va "krb5_context context" "krb5_principal *principal" "int rlen" "krb5_const_realm realm" "va_list ap" +.Ft krb5_error_code +.Fn "krb5_build_principal_ext" "krb5_context context" "krb5_principal *principal" "int rlen" "krb5_const_realm realm" "..." +.Ft krb5_error_code +.Fn krb5_build_principal_va_ext "krb5_context context" "krb5_principal *principal" "int rlen" "krb5_const_realm realm" "va_list ap" +.Ft krb5_error_code +.Fn krb5_make_principal "krb5_context context" "krb5_principal *principal" "krb5_const_realm realm" "..." +.Ft krb5_error_code +.Fn krb5_copy_principal "krb5_context context" "krb5_const_principal inprinc" "krb5_principal *outprinc" +.Ft krb5_boolean +.Fn krb5_principal_compare "krb5_context context" "krb5_const_principal princ1" "krb5_const_principal princ2" +.Ft krb5_boolean +.Fn krb5_principal_compare_any_realm "krb5_context context" "krb5_const_principal princ1" "krb5_const_principal princ2" +.Ft "const char *" +.Fn krb5_principal_get_comp_string "krb5_context context" "krb5_const_principal principal" "unsigned int component" +.Ft "const char *" +.Fn krb5_principal_get_realm "krb5_context context" "krb5_const_principal principal" +.Ft int +.Fn krb5_principal_get_type "krb5_context context" "krb5_const_principal principal" +.Ft krb5_boolean +.Fn krb5_principal_match "krb5_context context" "krb5_const_principal principal" "krb5_const_principal pattern" +.Ft void +.Fn krb5_principal_set_type "krb5_context context" "krb5_principal principal" "int type" +.Ft krb5_boolean +.Fn krb5_realm_compare "krb5_context context" "krb5_const_principal princ1" "krb5_const_principal princ2" +.Ft krb5_error_code +.Fn krb5_sname_to_principal "krb5_context context" "const char *hostname" "const char *sname" "int32_t type" "krb5_principal *ret_princ" +.Ft krb5_error_code +.Fn krb5_sock_to_principal "krb5_context context" "int socket" "const char *sname" "int32_t type" "krb5_principal *principal" +.Ft krb5_error_code +.Fn krb5_get_default_principal "krb5_context context" "krb5_principal *princ" +.Ft krb5_error_code +.Fn krb5_parse_nametype "krb5_context context" "const char *str" "int32_t *type" +.Sh DESCRIPTION +.Li krb5_principal +holds the name of a user or service in Kerberos. +.Pp +A principal has two parts, a +.Li PrincipalName +and a +.Li realm . +The PrincipalName consists of one or more components. In printed form, +the components are separated by /. +The PrincipalName also has a name-type. +.Pp +Examples of a principal are +.Li nisse/root@EXAMPLE.COM +and +.Li host/datan.kth.se@KTH.SE . +.Fn krb5_parse_name +and +.Fn krb5_parse_name_flags +passes a principal name in +.Fa name +to the kerberos principal structure. +.Fn krb5_parse_name_flags +takes an extra +.Fa flags +argument the following flags can be passed in +.Bl -tag -width Ds +.It Dv KRB5_PRINCIPAL_PARSE_NO_REALM +requries the input string to be without a realm, and no realm is +stored in the +.Fa principal +return argument. +.It Dv KRB5_PRINCIPAL_PARSE_MUST_REALM +requries the input string to with a realm. +.El +.Pp +.Fn krb5_unparse_name +and +.Fn krb5_unparse_name_flags +prints the principal +.Fa princ +to the string +.Fa name . +.Fa name +should be freed with +.Xr free 3 . +To the +.Fa flags +argument the following flags can be passed in +.Bl -tag -width Ds +.It Dv KRB5_PRINCIPAL_UNPARSE_SHORT +no realm if the realm is one of the local realms. +.It Dv KRB5_PRINCIPAL_UNPARSE_NO_REALM +never include any realm in the principal name. +.It Dv KRB5_PRINCIPAL_UNPARSE_DISPLAY +don't quote +.El +On failure +.Fa name +is set to +.Dv NULL . +.Fn krb5_unparse_name_fixed +and +.Fn krb5_unparse_name_fixed_flags +behaves just like +.Fn krb5_unparse , +but instead unparses the principal into a fixed size buffer. +.Pp +.Fn krb5_unparse_name_short +just returns the principal without the realm if the principal is +in the default realm. If the principal isn't, the full name is +returned. +.Fn krb5_unparse_name_fixed_short +works just like +.Fn krb5_unparse_name_short +but on a fixed size buffer. +.Pp +.Fn krb5_build_principal +builds a principal from the realm +.Fa realm +that has the length +.Fa rlen . +The following arguments form the components of the principal. +The list of components is terminated with +.Dv NULL . +.Pp +.Fn krb5_build_principal_va +works like +.Fn krb5_build_principal +using vargs. +.Pp +.Fn krb5_build_principal_ext +and +.Fn krb5_build_principal_va_ext +take a list of length-value pairs, the list is terminated with a zero +length. +.Pp +.Fn krb5_make_principal +works the same way as +.Fn krb5_build_principal , +except it figures out the length of the realm itself. +.Pp +.Fn krb5_copy_principal +makes a copy of a principal. +The copy needs to be freed with +.Fn krb5_free_principal . +.Pp +.Fn krb5_principal_compare +compares the two principals, including realm of the principals and returns +.Dv TRUE +if they are the same and +.Dv FALSE +if not. +.Pp +.Fn krb5_principal_compare_any_realm +works the same way as +.Fn krb5_principal_compare +but doesn't compare the realm component of the principal. +.Pp +.Fn krb5_realm_compare +compares the realms of the two principals and returns +.Dv TRUE +is they are the same, and +.Dv FALSE +if not. +.Pp +.Fn krb5_principal_match +matches a +.Fa principal +against a +.Fa pattern . +The pattern is a globbing expression, where each component (separated +by /) is matched against the corresponding component of the principal. +.Pp +The +.Fn krb5_principal_get_realm +and +.Fn krb5_principal_get_comp_string +functions return parts of the +.Fa principal , +either the realm or a specific component. +Both functions return string pointers to data inside the principal, so +they are valid only as long as the principal exists. +.Pp +The +.Fa component +argument to +.Fn krb5_principal_get_comp_string +is the index of the component to return, from zero to the total number of +components minus one. If the index is out of range +.Dv NULL +is returned. +.Pp +.Fn krb5_principal_get_realm +and +.Fn krb5_principal_get_comp_string +are replacements for +.Fn krb5_princ_realm , +.Fn krb5_princ_component +and related macros, described as internal in the MIT API +specification. +Unlike the macros, these functions return strings, not +.Dv krb5_data . +A reason to return +.Dv krb5_data +was that it was believed that principal components could contain +binary data, but this belief was unfounded, and it has been decided +that principal components are infact UTF8, so it's safe to use zero +terminated strings. +.Pp +It's generally not necessary to look at the components of a principal. +.Pp +.Fn krb5_principal_get_type +and +.Fn krb5_principal_set_type +get and sets the name type for a principal. +Name type handling is tricky and not often needed, +don't use this unless you know what you do. +.Pp +.Fn krb5_princ_realm +returns the realm component of the principal. +The caller must not free realm unless +.Fn krb5_princ_set_realm +is called to set a new realm after freeing the realm. +.Fn krb5_princ_set_realm +sets the realm component of a principal. The old realm is not freed. +.Pp +.Fn krb5_sname_to_principal +and +.Fn krb5_sock_to_principal +are for easy creation of +.Dq service +principals that can, for instance, be used to lookup a key in a keytab. +For both functions the +.Fa sname +parameter will be used for the first component of the created principal. +If +.Fa sname +is +.Dv NULL , +.Dq host +will be used instead. +.Pp +.Fn krb5_sname_to_principal +will use the passed +.Fa hostname +for the second component. +If +.Fa type +is +.Dv KRB5_NT_SRV_HST +this name will be looked up with +.Fn gethostbyname . +If +.Fa hostname +is +.Dv NULL , +the local hostname will be used. +.Pp +.Fn krb5_sock_to_principal +will use the +.Dq sockname +of the passed +.Fa socket , +which should be a bound +.Dv AF_INET +or +.Dv AF_INET6 +socket. +There must be a mapping between the address and +.Dq sockname . +The function may try to resolve the name in DNS. +.Pp +.Fn krb5_get_default_principal +tries to find out what's a reasonable default principal by looking at +the environment it is running in. +.Pp +.Fn krb5_parse_nametype +parses and returns the name type integer value in +.Fa type . +On failure the function returns an error code and set the error +string. +.\" .Sh EXAMPLES +.Sh SEE ALSO +.Xr krb5_425_conv_principal 3 , +.Xr krb5_config 3 , +.Xr krb5.conf 5 +.Sh BUGS +You can not have a NUL in a component in some of the variable argument +functions above. +Until someone can give a good example of where it would be a good idea +to have NUL's in a component, this will not be fixed. diff --git a/lib/krb5/krb5_principal_get_realm.3 b/lib/krb5/krb5_principal_get_realm.3 new file mode 100644 index 0000000..1ece798 --- /dev/null +++ b/lib/krb5/krb5_principal_get_realm.3 @@ -0,0 +1,81 @@ +.\" Copyright (c) 2001 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_principal_get_realm.3,v 1.6 2003/04/16 13:58:17 lha Exp $ +.\" +.Dd June 20, 2001 +.Dt KRB5_PRINCIPAL_GET_REALM 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_principal_get_realm , +.Nm krb5_principal_get_comp_string +.Nd decompose a principal +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Ft "const char *" +.Fn krb5_principal_get_realm "krb5_context context" "krb5_principal principal" +.Ft "const char *" +.Fn krb5_principal_get_comp_string "krb5_context context" "krb5_principal principal" "unsigned int component" +.Sh DESCRIPTION +These functions return parts of the +.Fa principal , +either the realm or a specific component. The returned string points +to data inside the principal, so they are valid only as long as the +principal exists. +.Pp +The +.Fa component +argument to +.Fn krb5_principal_get_comp_string +is the component number to return, from zero to the total number of +components minus one. If a the requested component number is out of range, +.Dv NULL +is returned. +.Pp +These functions can be seen as a replacement for the +.Fn krb5_princ_realm , +.Fn krb5_princ_component +and related macros, described as intermal in the MIT API +specification. A difference is that these functions return strings, +not +.Dv krb5_data . +A reason to return +.Dv krb5_data +was that it was believed that principal components could contain +binary data, but this belief was unfounded, and it has been decided +that principal components are infact UTF8, so it's safe to use zero +terminated strings. +.Pp +It's generally not necessary to look at the components of a principal. +.Sh SEE ALSO +.Xr krb5_unparse_name 3 diff --git a/lib/krb5/krb5_rcache.3 b/lib/krb5/krb5_rcache.3 new file mode 100644 index 0000000..0b7e83a --- /dev/null +++ b/lib/krb5/krb5_rcache.3 @@ -0,0 +1,163 @@ +.\" Copyright (c) 2004 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_rcache.3 17462 2006-05-05 13:18:39Z lha $ +.\" +.Dd May 1, 2006 +.Dt KRB5_RCACHE 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_rcache , +.Nm krb5_rc_close , +.Nm krb5_rc_default , +.Nm krb5_rc_default_name , +.Nm krb5_rc_default_type , +.Nm krb5_rc_destroy , +.Nm krb5_rc_expunge , +.Nm krb5_rc_get_lifespan , +.Nm krb5_rc_get_name , +.Nm krb5_rc_get_type , +.Nm krb5_rc_initialize , +.Nm krb5_rc_recover , +.Nm krb5_rc_resolve , +.Nm krb5_rc_resolve_full , +.Nm krb5_rc_resolve_type , +.Nm krb5_rc_store , +.Nm krb5_get_server_rcache +.Nd Kerberos 5 replay cache +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Pp +.Li "struct krb5_rcache;" +.Pp +.Ft krb5_error_code +.Fo krb5_rc_close +.Fa "krb5_context context" +.Fa "krb5_rcache id" +.Fc +.Ft krb5_error_code +.Fo krb5_rc_default +.Fa "krb5_context context" +.Fa "krb5_rcache *id" +.Fc +.Ft "const char *" +.Fo krb5_rc_default_name +.Fa "krb5_context context" +.Fc +.Ft "const char *" +.Fo krb5_rc_default_type +.Fa "krb5_context context" +.Fc +.Ft krb5_error_code +.Fo krb5_rc_destroy +.Fa "krb5_context context" +.Fa "krb5_rcache id" +.Fc +.Ft krb5_error_code +.Fo krb5_rc_expunge +.Fa "krb5_context context" +.Fa "krb5_rcache id" +.Fc +.Ft krb5_error_code +.Fo krb5_rc_get_lifespan +.Fa "krb5_context context" +.Fa "krb5_rcache id" +.Fa "krb5_deltat *auth_lifespan" +.Fc +.Ft "const char*" +.Fo krb5_rc_get_name +.Fa "krb5_context context" +.Fa "krb5_rcache id" +.Fc +.Ft "const char*" +.Fo "krb5_rc_get_type" +.Fa "krb5_context context" +.Fa "krb5_rcache id" +.Fc +.Ft krb5_error_code +.Fo krb5_rc_initialize +.Fa "krb5_context context" +.Fa "krb5_rcache id" +.Fa "krb5_deltat auth_lifespan" +.Fc +.Ft krb5_error_code +.Fo krb5_rc_recover +.Fa "krb5_context context" +.Fa "krb5_rcache id" +.Fc +.Ft krb5_error_code +.Fo krb5_rc_resolve +.Fa "krb5_context context" +.Fa "krb5_rcache id" +.Fa "const char *name" +.Fc +.Ft krb5_error_code +.Fo krb5_rc_resolve_full +.Fa "krb5_context context" +.Fa "krb5_rcache *id" +.Fa "const char *string_name" +.Fc +.Ft krb5_error_code +.Fo krb5_rc_resolve_type +.Fa "krb5_context context" +.Fa "krb5_rcache *id" +.Fa "const char *type" +.Fc +.Ft krb5_error_code +.Fo krb5_rc_store +.Fa "krb5_context context" +.Fa "krb5_rcache id" +.Fa "krb5_donot_replay *rep" +.Fc +.Ft krb5_error_code +.Fo krb5_get_server_rcache +.Fa "krb5_context context" +.Fa "const krb5_data *piece" +.Fa "krb5_rcache *id" +.Fc +.Sh DESCRIPTION +The +.Li krb5_rcache +structure holds a storage element that is used for data manipulation. +The structure contains no public accessible elements. +.Pp +.Fn krb5_rc_initialize +Creates the reply cache +.Fa id +and sets it lifespan to +.Fa auth_lifespan . +If the cache already exists, the content is destroyed. +.Sh SEE ALSO +.Xr krb5 3 , +.Xr krb5_data 3 , +.Xr kerberos 8 diff --git a/lib/krb5/krb5_rd_error.3 b/lib/krb5/krb5_rd_error.3 new file mode 100644 index 0000000..00203cd --- /dev/null +++ b/lib/krb5/krb5_rd_error.3 @@ -0,0 +1,98 @@ +.\" Copyright (c) 2004 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_rd_error.3 21059 2007-06-12 17:52:46Z lha $ +.\" +.Dd July 26, 2004 +.Dt KRB5_RD_ERROR 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_rd_error , +.Nm krb5_free_error , +.Nm krb5_free_error_contents , +.Nm krb5_error_from_rd_error +.Nd parse, free and read error from KRB-ERROR message +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Ft krb5_error_code +.Fo krb5_rd_error +.Fa "krb5_context context" +.Fa "const krb5_data *msg" +.Fa "KRB_ERROR *result" +.Fc +.Ft void +.Fo krb5_free_error +.Fa "krb5_context context" +.Fa "krb5_error *error" +.Fc +.Ft void +.Fo krb5_free_error_contents +.Fa "krb5_context context" +.Fa "krb5_error *error" +.Fc +.Ft krb5_error_code +.Fo krb5_error_from_rd_error +.Fa "krb5_context context" +.Fa "const krb5_error *error" +.Fa "const krb5_creds *creds" +.Fc +.Sh DESCRIPTION +Usually applications never needs to parse and understand Kerberos +error messages since higher level functions will parse and push up the +error in the krb5_context. +These functions are described for completeness. +.Pp +.Fn krb5_rd_error +parses and returns the kerboeros error message, the structure should be freed with +.Fn krb5_free_error_contents +when the caller is done with the structure. +.Pp +.Fn krb5_free_error +frees the content and the memory region holding the structure iself. +.Pp +.Fn krb5_free_error_contents +free the content of the KRB-ERROR message. +.Pp +.Fn krb5_error_from_rd_error +will parse the error message and set the error buffer in krb5_context +to the error string passed back or the matching error code in the +KRB-ERROR message. +Caller should pick up the message with +.Fn krb5_get_error_string 3 +(don't forget to free the returned string with +.Fn krb5_free_error_string ) . +.Sh SEE ALSO +.Xr krb5 3 , +.Xr krb5_set_error_string 3 , +.Xr krb5_get_error_string 3 , +.Xr krb5.conf 5 diff --git a/lib/krb5/krb5_rd_safe.3 b/lib/krb5/krb5_rd_safe.3 new file mode 100644 index 0000000..d024ae4 --- /dev/null +++ b/lib/krb5/krb5_rd_safe.3 @@ -0,0 +1,81 @@ +.\" Copyright (c) 2003 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_rd_safe.3 17385 2006-05-01 08:48:55Z lha $ +.\" +.Dd May 1, 2006 +.Dt KRB5_RD_SAFE 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_rd_safe , +.Nm krb5_rd_priv +.Nd verifies authenticity of messages +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Pp +.Ft krb5_error_code +.Fn krb5_rd_priv "krb5_context context" "krb5_auth_context auth_context" "const krb5_data *inbuf" "krb5_data *outbuf" "krb5_replay_data *outdata" +.Ft krb5_error_code +.Fn krb5_rd_safe "krb5_context context" "krb5_auth_context auth_context" "const krb5_data *inbuf" "krb5_data *outbuf" "krb5_replay_data *outdata" +.Sh DESCRIPTION +.Fn krb5_rd_safe +and +.Fn krb5_rd_priv +parses +.Li KRB-SAFE +and +.Li KRB-PRIV +messages (as generated by +.Xr krb5_mk_safe 3 +and +.Xr krb5_mk_priv 3 ) +from +.Fa inbuf +and verifies its integrity. The user data part of the message in put +in +.Fa outbuf . +The encryption state, including keyblocks and addresses, is taken from +.Fa auth_context . +If the +.Dv KRB5_AUTH_CONTEXT_RET_SEQUENCE +or +.Dv KRB5_AUTH_CONTEXT_RET_TIME +flags are set in the +.Fa auth_context +the sequence number and time are returned in the +.Fa outdata +parameter. +.Sh SEE ALSO +.Xr krb5_auth_con_init 3 , +.Xr krb5_mk_priv 3 , +.Xr krb5_mk_safe 3 diff --git a/lib/krb5/krb5_set_default_realm.3 b/lib/krb5/krb5_set_default_realm.3 new file mode 100644 index 0000000..27467d8 --- /dev/null +++ b/lib/krb5/krb5_set_default_realm.3 @@ -0,0 +1,164 @@ +.\" Copyright (c) 2003 - 2005 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_set_default_realm.3 17462 2006-05-05 13:18:39Z lha $ +.\" +.Dd April 24, 2005 +.Dt KRB5_SET_DEFAULT_REALM 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_copy_host_realm , +.Nm krb5_free_host_realm , +.Nm krb5_get_default_realm , +.Nm krb5_get_default_realms , +.Nm krb5_get_host_realm , +.Nm krb5_set_default_realm +.Nd default and host realm read and manipulation routines +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Ft krb5_error_code +.Fo krb5_copy_host_realm +.Fa "krb5_context context" +.Fa "const krb5_realm *from" +.Fa "krb5_realm **to" +.Fc +.Ft krb5_error_code +.Fo krb5_free_host_realm +.Fa "krb5_context context" +.Fa "krb5_realm *realmlist" +.Fc +.Ft krb5_error_code +.Fo krb5_get_default_realm +.Fa "krb5_context context" +.Fa "krb5_realm *realm" +.Fc +.Ft krb5_error_code +.Fo krb5_get_default_realms +.Fa "krb5_context context" +.Fa "krb5_realm **realm" +.Fc +.Ft krb5_error_code +.Fo krb5_get_host_realm +.Fa "krb5_context context" +.Fa "const char *host" +.Fa "krb5_realm **realms" +.Fc +.Ft krb5_error_code +.Fo krb5_set_default_realm +.Fa "krb5_context context" +.Fa "const char *realm" +.Fc +.Sh DESCRIPTION +.Fn krb5_copy_host_realm +copies the list of realms from +.Fa from +to +.Fa to . +.Fa to +should be freed by the caller using +.Fa krb5_free_host_realm . +.Pp +.Fn krb5_free_host_realm +frees all memory allocated by +.Fa realmlist . +.Pp +.Fn krb5_get_default_realm +returns the first default realm for this host. +The realm returned should be freed with +.Fn free . +.Pp +.Fn krb5_get_default_realms +returns a +.Dv NULL +terminated list of default realms for this context. +Realms returned by +.Fn krb5_get_default_realms +should be freed with +.Fn krb5_free_host_realm . +.Pp +.Fn krb5_get_host_realm +returns a +.Dv NULL +terminated list of realms for +.Fa host +by looking up the information in the +.Li [domain_realm] +in +.Pa krb5.conf +or in +.Li DNS . +If the mapping in +.Li [domain_realm] +results in the string +.Li dns_locate , +DNS is used to lookup the realm. +.Pp +When using +.Li DNS +to a resolve the domain for the host a.b.c, +.Fn krb5_get_host_realm +looks for a +.Dv TXT +resource record named +.Li _kerberos.a.b.c , +and if not found, it strips off the first component and tries a again +(_kerberos.b.c) until it reaches the root. +.Pp +If there is no configuration or DNS information found, +.Fn krb5_get_host_realm +assumes it can use the domain part of the +.Fa host +to form a realm. +Caller must free +.Fa realmlist +with +.Fn krb5_free_host_realm . +.Pp +.Fn krb5_set_default_realm +sets the default realm for the +.Fa context . +If +.Dv NULL +is used as a +.Fa realm , +the +.Li [libdefaults]default_realm +stanza in +.Pa krb5.conf +is used. +If there is no such stanza in the configuration file, the +.Fn krb5_get_host_realm +function is used to form a default realm. +.Sh SEE ALSO +.Xr free 3 , +.Xr krb5.conf 5 diff --git a/lib/krb5/krb5_set_password.3 b/lib/krb5/krb5_set_password.3 new file mode 100644 index 0000000..45ed41d --- /dev/null +++ b/lib/krb5/krb5_set_password.3 @@ -0,0 +1,143 @@ +.\" Copyright (c) 2003 - 2004 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_set_password.3 14052 2004-07-15 14:39:06Z lha $ +.\" +.Dd July 15, 2004 +.Dt KRB5_SET_PASSWORD 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_change_password , +.Nm krb5_set_password , +.Nm krb5_set_password_using_ccache , +.Nm krb5_passwd_result_to_string +.Nd change password functions +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Ft krb5_error_code +.Fo krb5_change_password +.Fa "krb5_context context" +.Fa "krb5_creds *creds" +.Fa "char *newpw" +.Fa "int *result_code" +.Fa "krb5_data *result_code_string" +.Fa "krb5_data *result_string" +.Fc +.Ft krb5_error_code +.Fo krb5_set_password +.Fa "krb5_context context" +.Fa "krb5_creds *creds" +.Fa "char *newpw" +.Fa "krb5_principal targprinc" +.Fa "int *result_code" +.Fa "krb5_data *result_code_string" +.Fa "krb5_data *result_string" +.Fc +.Ft krb5_error_code +.Fo krb5_set_password_using_ccache +.Fa "krb5_context context" +.Fa "krb5_ccache ccache" +.Fa "char *newpw" +.Fa "krb5_principal targprinc" +.Fa "int *result_code" +.Fa "krb5_data *result_code_string" +.Fa "krb5_data *result_string" +.Fc +.Ft "const char *" +.Fo krb5_passwd_result_to_string +.Fa "krb5_context context" +.Fa "int result" +.Fc +.Sh DESCRIPTION +These functions change the password for a given principal. +.Pp +.Fn krb5_set_password +and +.Fn krb5_set_password_using_ccache +are the newer of the three functions, and use a newer version of the +protocol (and also fall back to the older set-password protocol if the +newer protocol doesn't work). +.Pp +.Fn krb5_change_password +sets the password +.Fa newpasswd +for the client principal in +.Fa creds . +The server principal of creds must be +.Li kadmin/changepw . +.Pp +.Fn krb5_set_password +and +.Fn krb5_set_password_using_ccache +change the password for the principal +.Fa targprinc . +.Pp +.Fn krb5_set_password +requires that the credential for +.Li kadmin/changepw@REALM +is in +.Fa creds . +If the user caller isn't an administrator, this credential +needs to be an initial credential, see +.Xr krb5_get_init_creds 3 +how to get such credentials. +.Pp +.Fn krb5_set_password_using_ccache +will get the credential from +.Fa ccache . +.Pp +If +.Fa targprinc +is +.Dv NULL , +.Fn krb5_set_password_using_ccache +uses the the default principal in +.Fa ccache +and +.Fn krb5_set_password +uses the global the default principal. +.Pp +All three functions return an error in +.Fa result_code +and maybe an error string to print in +.Fa result_string . +.Pp +.Fn krb5_passwd_result_to_string +returns an human readable string describing the error code in +.Fa result_code +from the +.Fn krb5_set_password +functions. +.Sh SEE ALSO +.Xr krb5_ccache 3 , +.Xr krb5_init_context 3 diff --git a/lib/krb5/krb5_sname_to_principal.3 b/lib/krb5/krb5_sname_to_principal.3 new file mode 100644 index 0000000..5724ce1 --- /dev/null +++ b/lib/krb5/krb5_sname_to_principal.3 @@ -0,0 +1,85 @@ +.\" Copyright (c) 1997 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_sname_to_principal.3,v 1.7 2003/04/16 13:58:17 lha Exp $ +.\" +.Dd August 8, 1997 +.Dt KRB5_PRINCIPAL 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_sname_to_principal , +.Nm krb5_sock_to_principal +.Nd create a service principal +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Ft krb5_error_code +.Fn krb5_sname_to_principal "krb5_context context" "const char *hostname" "const char *sname" "int32_t type" "krb5_principal *principal" +.Ft krb5_error_code +.Fn krb5_sock_to_principal "krb5_context context" "int socket" "const char *sname" "int32_t type" "krb5_principal *principal" +.Sh DESCRIPTION +These functions create a +.Dq service +principal that can, for instance, be used to lookup a key in a keytab. For both these function the +.Fa sname +parameter will be used for the first component of the created principal. If +.Fa sname +is +.Dv NULL , +.Dq host +will be used instead. +.Fn krb5_sname_to_principal +will use the passed +.Fa hostname +for the second component. If type +.Dv KRB5_NT_SRV_HST +this name will be looked up with +.Fn gethostbyname . +If +.Fa hostname is +.Dv NULL , +the local hostname will be used. +.Pp +.Fn krb5_sock_to_principal +will use the +.Dq sockname +of the passed +.Fa socket , +which should be a bound +.Dv AF_INET +socket. +.Sh SEE ALSO +.Xr krb5_425_conv_principal 3 , +.Xr krb5_build_principal 3 , +.Xr krb5_free_principal 3 , +.Xr krb5_parse_name 3 , +.Xr krb5_unparse_name 3 diff --git a/lib/krb5/krb5_storage.3 b/lib/krb5/krb5_storage.3 new file mode 100644 index 0000000..cc03c5b --- /dev/null +++ b/lib/krb5/krb5_storage.3 @@ -0,0 +1,427 @@ +.\" Copyright (c) 2003 - 2006 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_storage.3 17884 2006-08-18 08:41:09Z lha $ +.\" +.Dd Aug 18, 2006 +.Dt KRB5_STORAGE 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_storage , +.Nm krb5_storage_emem , +.Nm krb5_storage_from_data , +.Nm krb5_storage_from_fd , +.Nm krb5_storage_from_mem , +.Nm krb5_storage_set_flags , +.Nm krb5_storage_clear_flags , +.Nm krb5_storage_is_flags , +.Nm krb5_storage_set_byteorder , +.Nm krb5_storage_get_byteorder , +.Nm krb5_storage_set_eof_code , +.Nm krb5_storage_seek , +.Nm krb5_storage_read , +.Nm krb5_storage_write , +.Nm krb5_storage_free , +.Nm krb5_storage_to_data , +.Nm krb5_store_int32 , +.Nm krb5_ret_int32 , +.Nm krb5_store_uint32 , +.Nm krb5_ret_uint32 , +.Nm krb5_store_int16 , +.Nm krb5_ret_int16 , +.Nm krb5_store_uint16 , +.Nm krb5_ret_uint16 , +.Nm krb5_store_int8 , +.Nm krb5_ret_int8 , +.Nm krb5_store_uint8 , +.Nm krb5_ret_uint8 , +.Nm krb5_store_data , +.Nm krb5_ret_data , +.Nm krb5_store_string , +.Nm krb5_ret_string , +.Nm krb5_store_stringnl , +.Nm krb5_ret_stringnl , +.Nm krb5_store_stringz , +.Nm krb5_ret_stringz , +.Nm krb5_store_principal , +.Nm krb5_ret_principal , +.Nm krb5_store_keyblock , +.Nm krb5_ret_keyblock , +.Nm krb5_store_times , +.Nm krb5_ret_times , +.Nm krb5_store_address , +.Nm krb5_ret_address , +.Nm krb5_store_addrs , +.Nm krb5_ret_addrs , +.Nm krb5_store_authdata , +.Nm krb5_ret_authdata , +.Nm krb5_store_creds , +.Nm krb5_ret_creds +.Nd operates on the Kerberos datatype krb5_storage +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Pp +.Li "struct krb5_storage;" +.Pp +.Ft "krb5_storage *" +.Fn krb5_storage_from_fd "int fd" +.Ft "krb5_storage *" +.Fn krb5_storage_emem "void" +.Ft "krb5_storage *" +.Fn krb5_storage_from_mem "void *buf" "size_t len" +.Ft "krb5_storage *" +.Fn krb5_storage_from_data "krb5_data *data" +.Ft void +.Fn krb5_storage_set_flags "krb5_storage *sp" "krb5_flags flags" +.Ft void +.Fn krb5_storage_clear_flags "krb5_storage *sp" "krb5_flags flags" +.Ft krb5_boolean +.Fn krb5_storage_is_flags "krb5_storage *sp" "krb5_flags flags" +.Ft void +.Fn krb5_storage_set_byteorder "krb5_storage *sp" "krb5_flags byteorder" +.Ft krb5_flags +.Fn krb5_storage_get_byteorder "krb5_storage *sp" "krb5_flags byteorder" +.Ft void +.Fn krb5_storage_set_eof_code "krb5_storage *sp" "int code" +.Ft off_t +.Fn krb5_storage_seek "krb5_storage *sp" "off_t offset" "int whence" +.Ft krb5_ssize_t +.Fn krb5_storage_read "krb5_storage *sp" "void *buf" "size_t len" +.Ft krb5_ssize_t +.Fn krb5_storage_write "krb5_storage *sp" "const void *buf" "size_t len" +.Ft krb5_error_code +.Fn krb5_storage_free "krb5_storage *sp" +.Ft krb5_error_code +.Fn krb5_storage_to_data "krb5_storage *sp" "krb5_data *data" +.Ft krb5_error_code +.Fn krb5_store_int32 "krb5_storage *sp" "int32_t value" +.Ft krb5_error_code +.Fn krb5_ret_int32 "krb5_storage *sp" "int32_t *value" +.Ft krb5_error_code +.Fn krb5_ret_uint32 "krb5_storage *sp" "uint32_t *value" +.Ft krb5_error_code +.Fn krb5_store_uint32 "krb5_storage *sp" "uint32_t value" +.Ft krb5_error_code +.Fn krb5_store_int16 "krb5_storage *sp" "int16_t value" +.Ft krb5_error_code +.Fn krb5_ret_int16 "krb5_storage *sp" "int16_t *value" +.Ft krb5_error_code +.Fn krb5_store_uint16 "krb5_storage *sp" "uint16_t value" +.Ft krb5_error_code +.Fn krb5_ret_uint16 "krb5_storage *sp" "u_int16_t *value" +.Ft krb5_error_code +.Fn krb5_store_int8 "krb5_storage *sp" "int8_t value" +.Ft krb5_error_code +.Fn krb5_ret_int8 "krb5_storage *sp" "int8_t *value" +.Ft krb5_error_code +.Fn krb5_store_uint8 "krb5_storage *sp" "u_int8_t value" +.Ft krb5_error_code +.Fn krb5_ret_uint8 "krb5_storage *sp" "u_int8_t *value" +.Ft krb5_error_code +.Fn krb5_store_data "krb5_storage *sp" "krb5_data data" +.Ft krb5_error_code +.Fn krb5_ret_data "krb5_storage *sp" "krb5_data *data" +.Ft krb5_error_code +.Fn krb5_store_string "krb5_storage *sp" "const char *s" +.Ft krb5_error_code +.Fn krb5_ret_string "krb5_storage *sp" "char **string" +.Ft krb5_error_code +.Fn krb5_store_stringnl "krb5_storage *sp" "const char *s" +.Ft krb5_error_code +.Fn krb5_ret_stringnl "krb5_storage *sp" "char **string" +.Ft krb5_error_code +.Fn krb5_store_stringz "krb5_storage *sp" "const char *s" +.Ft krb5_error_code +.Fn krb5_ret_stringz "krb5_storage *sp" "char **string" +.Ft krb5_error_code +.Fn krb5_store_principal "krb5_storage *sp" "krb5_const_principal p" +.Ft krb5_error_code +.Fn krb5_ret_principal "krb5_storage *sp" "krb5_principal *princ" +.Ft krb5_error_code +.Fn krb5_store_keyblock "krb5_storage *sp" "krb5_keyblock p" +.Ft krb5_error_code +.Fn krb5_ret_keyblock "krb5_storage *sp" "krb5_keyblock *p" +.Ft krb5_error_code +.Fn krb5_store_times "krb5_storage *sp" "krb5_times times" +.Ft krb5_error_code +.Fn krb5_ret_times "krb5_storage *sp" "krb5_times *times" +.Ft krb5_error_code +.Fn krb5_store_address "krb5_storage *sp" "krb5_address p" +.Ft krb5_error_code +.Fn krb5_ret_address "krb5_storage *sp" "krb5_address *adr" +.Ft krb5_error_code +.Fn krb5_store_addrs "krb5_storage *sp" "krb5_addresses p" +.Ft krb5_error_code +.Fn krb5_ret_addrs "krb5_storage *sp" "krb5_addresses *adr" +.Ft krb5_error_code +.Fn krb5_store_authdata "krb5_storage *sp" "krb5_authdata auth" +.Ft krb5_error_code +.Fn krb5_ret_authdata "krb5_storage *sp" "krb5_authdata *auth" +.Ft krb5_error_code +.Fn krb5_store_creds "krb5_storage *sp" "krb5_creds *creds" +.Ft krb5_error_code +.Fn krb5_ret_creds "krb5_storage *sp" "krb5_creds *creds" +.Sh DESCRIPTION +The +.Li krb5_storage +structure holds a storage element that is used for data manipulation. +The structure contains no public accessible elements. +.Pp +.Fn krb5_storage_emem +create a memory based krb5 storage unit that dynamicly resized to the +ammount of data stored in. +The storage never returns errors, on memory allocation errors +.Xr exit 3 +will be called. +.Pp +.Fn krb5_storage_from_data +create a krb5 storage unit that will read is data from a +.Li krb5_data . +There is no copy made of the +.Fa data , +so the caller must not free +.Fa data +until the storage is freed. +.Pp +.Fn krb5_storage_from_fd +create a krb5 storage unit that will read is data from a +file descriptor. +The descriptor must be seekable if +.Fn krb5_storage_seek +is used. +Caller must not free the file descriptor before the storage is freed. +.Pp +.Fn krb5_storage_from_mem +create a krb5 storage unit that will read is data from a +memory region. +There is no copy made of the +.Fa data , +so the caller must not free +.Fa data +until the storage is freed. +.Pp +.Fn krb5_storage_set_flags +and +.Fn krb5_storage_clear_flags +modifies the behavior of the storage functions. +.Fn krb5_storage_is_flags +tests if the +.Fa flags +are set on the +.Li krb5_storage . +Valid flags to set, is and clear is are: +.Pp +.Bl -tag -width "Fan vet..." -compact -offset indent +.It KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS +Stores the number of principal componets one too many when storing +principal namees, used for compatibility with version 1 of file +keytabs and version 1 of file credential caches. +.It KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE +Doesn't store the name type in when storing a principal name, used for +compatibility with version 1 of file keytabs and version 1 of file +credential caches. +.It KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE +Stores the keyblock type twice storing a keyblock, used for +compatibility version 3 of file credential caches. +.It KRB5_STORAGE_BYTEORDER_MASK +bitmask that can be used to and out what type of byte order order is used. +.It KRB5_STORAGE_BYTEORDER_BE +Store integers in in big endian byte order, this is the default mode. +.It KRB5_STORAGE_BYTEORDER_LE +Store integers in in little endian byte order. +.It KRB5_STORAGE_BYTEORDER_HOST +Stores the integers in host byte order, used for compatibility with +version 1 of file keytabs and version 1 and 2 of file credential +caches. +.It KRB5_STORAGE_CREDS_FLAGS_WRONG_BITORDER +Store the credential flags in a krb5_creds in the reverse bit order. +.El +.Pp +.Fn krb5_storage_set_byteorder +and +.Fn krb5_storage_get_byteorder +modifies the byte order used in the storage for integers. +The flags used is same as above. +The valid flags are +.Dv KRB5_STORAGE_BYTEORDER_BE , +.Dv KRB5_STORAGE_BYTEORDER_LE +and +.Dv KRB5_STORAGE_BYTEORDER_HOST . +.Pp +.Fn krb5_storage_set_eof_code +sets the error code that will be returned on end of file condition to +.Fa code . +.Pp +.Fn krb5_storage_seek +seeks +.Fa offset +bytes in the storage +.Fa sp . +The +.Fa whence +argument is one of +.Bl -tag -width SEEK_SET -compact -offset indent +.It SEEK_SET +offset is from begining of storage. +.It SEEK_CUR +offset is relative from current offset. +.It SEEK_END +offset is from end of storage. +.El +.Pp +.Fn krb5_storage_read +reads +.Fa len +(or less bytes in case of end of file) into +.Fa buf +from the current offset in the storage +.Fa sp . +.Pp +.Fn krb5_storage_write +writes +.Fa len +or (less bytes in case of end of file) from +.Fa buf +from the current offset in the storage +.Fa sp . +.Pp +.Fn krb5_storage_free +frees the storage +.Fa sp . +.Pp +.Fn krb5_storage_to_data +converts the data in storage +.Fa sp +into a +.Li krb5_data +structure. +.Fa data +must be freed with +.Fn krb5_data_free +by the caller when done with the +.Fa data . +.Pp +All +.Li krb5_store +and +.Li krb5_ret +functions move the current offset forward when the functions returns. +.Pp +.Fn krb5_store_int32 , +.Fn krb5_ret_int32 , +.Fn krb5_store_uint32 , +.Fn krb5_ret_uint32 , +.Fn krb5_store_int16 , +.Fn krb5_ret_int16 , +.Fn krb5_store_uint16 , +.Fn krb5_ret_uint16 , +.Fn krb5_store_int8 , +.Fn krb5_ret_int8 +.Fn krb5_store_uint8 , +and +.Fn krb5_ret_uint8 +stores and reads an integer from +.Fa sp +in the byte order specified by the flags set on the +.Fa sp . +.Pp +.Fn krb5_store_data +and +.Fn krb5_ret_data +store and reads a krb5_data. +The length of the data is stored with +.Fn krb5_store_int32 . +.Pp +.Fn krb5_store_string +and +.Fn krb5_ret_string +store and reads a string by storing the length of the string with +.Fn krb5_store_int32 +followed by the string itself. +.Pp +.Fn krb5_store_stringnl +and +.Fn krb5_ret_stringnl +store and reads a string by storing string followed by a +.Dv '\n' . +.Pp +.Fn krb5_store_stringz +and +.Fn krb5_ret_stringz +store and reads a string by storing string followed by a +.Dv NUL . +.Pp +.Fn krb5_store_principal +and +.Fn krb5_ret_principal +store and reads a principal. +.Pp +.Fn krb5_store_keyblock +and +.Fn krb5_ret_keyblock +store and reads a +.Li krb5_keyblock . +.Pp +.Fn krb5_store_times +.Fn krb5_ret_times +store and reads +.Li krb5_times +structure . +.Pp +.Fn krb5_store_address +and +.Fn krb5_ret_address +store and reads a +.Li krb5_address . +.Pp +.Fn krb5_store_addrs +and +.Fn krb5_ret_addrs +store and reads a +.Li krb5_addresses . +.Pp +.Fn krb5_store_authdata +and +.Fn krb5_ret_authdata +store and reads a +.Li krb5_authdata . +.Pp +.Fn krb5_store_creds +and +.Fn krb5_ret_creds +store and reads a +.Li krb5_creds . +.Sh SEE ALSO +.Xr krb5 3 , +.Xr krb5_data 3 , +.Xr kerberos 8 diff --git a/lib/krb5/krb5_string_to_key.3 b/lib/krb5/krb5_string_to_key.3 new file mode 100644 index 0000000..cf96f4e --- /dev/null +++ b/lib/krb5/krb5_string_to_key.3 @@ -0,0 +1,156 @@ +.\" Copyright (c) 2004 - 2006 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_string_to_key.3 17820 2006-07-10 14:28:01Z lha $ +.\" +.Dd July 10, 2006 +.Dt KRB5_STRING_TO_KEY 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_string_to_key , +.Nm krb5_string_to_key_data , +.Nm krb5_string_to_key_data_salt , +.Nm krb5_string_to_key_data_salt_opaque , +.Nm krb5_string_to_key_salt , +.Nm krb5_string_to_key_salt_opaque , +.Nm krb5_get_pw_salt , +.Nm krb5_free_salt +.Nd turns a string to a Kerberos key +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Ft krb5_error_code +.Fo krb5_string_to_key +.Fa "krb5_context context" +.Fa "krb5_enctype enctype" +.Fa "const char *password" +.Fa "krb5_principal principal" +.Fa "krb5_keyblock *key" +.Fc +.Ft krb5_error_code +.Fo krb5_string_to_key_data +.Fa "krb5_context context" +.Fa "krb5_enctype enctype" +.Fa "krb5_data password" +.Fa "krb5_principal principal" +.Fa "krb5_keyblock *key" +.Fc +.Ft krb5_error_code +.Fo krb5_string_to_key_data_salt +.Fa "krb5_context context" +.Fa "krb5_enctype enctype" +.Fa "krb5_data password" +.Fa "krb5_salt salt" +.Fa "krb5_keyblock *key" +.Fc +.Ft krb5_error_code +.Fo krb5_string_to_key_data_salt_opaque +.Fa "krb5_context context" +.Fa "krb5_enctype enctype" +.Fa "krb5_data password" +.Fa "krb5_salt salt" +.Fa "krb5_data opaque" +.Fa "krb5_keyblock *key" +.Fc +.Ft krb5_error_code +.Fo krb5_string_to_key_salt +.Fa "krb5_context context" +.Fa "krb5_enctype enctype" +.Fa "const char *password" +.Fa "krb5_salt salt" +.Fa "krb5_keyblock *key" +.Fc +.Ft krb5_error_code +.Fo krb5_string_to_key_salt_opaque +.Fa "krb5_context context" +.Fa "krb5_enctype enctype" +.Fa "const char *password" +.Fa "krb5_salt salt" +.Fa "krb5_data opaque" +.Fa "krb5_keyblock *key" +.Fc +.Ft krb5_error_code +.Fo krb5_get_pw_salt +.Fa "krb5_context context" +.Fa "krb5_const_principal principal" +.Fa "krb5_salt *salt" +.Fc +.Ft krb5_error_code +.Fo krb5_free_salt +.Fa "krb5_context context" +.Fa "krb5_salt salt" +.Fc +.Sh DESCRIPTION +The string to key functions convert a string to a kerberos key. +.Pp +.Fn krb5_string_to_key_data_salt_opaque +is the function that does all the work, the rest of the functions are +just wrapers around +.Fn krb5_string_to_key_data_salt_opaque +that calls it with default values. +.Pp +.Fn krb5_string_to_key_data_salt_opaque +transforms the +.Fa password +with the given salt-string +.Fa salt +and the opaque, encryption type specific parameter +.Fa opaque +to a encryption key +.Fa key +according to the string to key function associated with +.Fa enctype . +.Pp +The +.Fa key +should be freed with +.Fn krb5_free_keyblock_contents . +.Pp +If one of the functions that doesn't take a +.Li krb5_salt +as it argument +.Fn krb5_get_pw_salt +is used to get the salt value. +.Pp +.Fn krb5_get_pw_salt +get the default password salt for a principal, use +.Fn krb5_free_salt +to free the salt when done. +.Pp +.Fn krb5_free_salt +frees the content of +.Fa salt . +.Sh SEE ALSO +.Xr krb5 3 , +.Xr krb5_data 3 , +.Xr krb5_keyblock 3 , +.Xr kerberos 8 diff --git a/lib/krb5/krb5_ticket.3 b/lib/krb5/krb5_ticket.3 new file mode 100644 index 0000000..4f6d45b --- /dev/null +++ b/lib/krb5/krb5_ticket.3 @@ -0,0 +1,137 @@ +.\" Copyright (c) 2003 - 2004 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_ticket.3 19543 2006-12-28 20:48:50Z lha $ +.\" +.Dd May 1, 2006 +.Dt KRB5_TICKET 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_ticket , +.Nm krb5_free_ticket , +.Nm krb5_copy_ticket , +.Nm krb5_ticket_get_authorization_data_type , +.Nm krb5_ticket_get_client , +.Nm krb5_ticket_get_server , +.Nm krb5_ticket_get_endtime +.Nd Kerberos 5 ticket access and handling functions +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Pp +.Li krb5_ticket ; +.Pp +.Ft krb5_error_code +.Fo krb5_free_ticket +.Fa "krb5_context context" +.Fa "krb5_ticket *ticket" +.Fc +.Ft krb5_error_code +.Fo krb5_copy_ticket +.Fa "krb5_context context" +.Fa "const krb5_ticket *from" +.Fa "krb5_ticket **to" +.Fc +.Ft krb5_error_code +.Fo krb5_ticket_get_authorization_data_type +.Fa "krb5_context context" +.Fa "krb5_ticket *ticket" +.Fa "int type" +.Fa "krb5_data *data" +.Fc +.Ft krb5_error_code +.Fo krb5_ticket_get_client +.Fa "krb5_context context" +.Fa "const krb5_ticket *ticket" +.Fa "krb5_principal *client" +.Fc +.Ft krb5_error_code +.Fo krb5_ticket_get_server +.Fa "krb5_context context" +.Fa "const krb5_ticket *ticket" +.Fa "krb5_principal *server" +.Fc +.Ft time_t +.Fo krb5_ticket_get_endtime +.Fa "krb5_context context" +.Fa "const krb5_ticket *ticket" +.Fc +.Sh DESCRIPTION +.Li krb5_ticket +holds a kerberos ticket. +The internals of the structure should never be accessed directly, +functions exist for extracting information. +.Pp +.Fn krb5_free_ticket +frees the +.Fa ticket +and its content. +Used to free the result of +.Fn krb5_copy_ticket +and +.Fn krb5_recvauth . +.Pp +.Fn krb5_copy_ticket +copies the content of the ticket +.Fa from +to the ticket +.Fa to . +The result +.Fa to +should be freed with +.Fn krb5_free_ticket . +.Pp +.Fn krb5_ticket_get_authorization_data_type +fetches the authorization data of the type +.Fa type +from the +.Fa ticket . +If there isn't any authorization data of type +.Fa type , +.Dv ENOENT +is returned. +.Fa data +needs to be freed with +.Fn krb5_data_free +on success. +.Pp +.Fn krb5_ticket_get_client +and +.Fn krb5_ticket_get_server +returns a copy of the client/server principal from the ticket. +The principal returned should be free using +.Xr krb5_free_principal 3 . +.Pp +.Fn krb5_ticket_get_endtime +return the end time of the ticket. +.Sh SEE ALSO +.Xr krb5 3 diff --git a/lib/krb5/krb5_timeofday.3 b/lib/krb5/krb5_timeofday.3 new file mode 100644 index 0000000..4163cc1 --- /dev/null +++ b/lib/krb5/krb5_timeofday.3 @@ -0,0 +1,118 @@ +.\" $Id: krb5_timeofday.3 18093 2006-09-16 09:27:28Z lha $ +.\" +.\" Copyright (c) 2001, 2003, 2006 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_timeofday.3 18093 2006-09-16 09:27:28Z lha $ +.\" +.Dd Sepember 16, 2006 +.Dt KRB5_TIMEOFDAY 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_timeofday , +.Nm krb5_set_real_time , +.Nm krb5_us_timeofday , +.Nm krb5_format_time , +.Nm krb5_string_to_deltat +.Nd Kerberos 5 time handling functions +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Pp +.Li krb5_timestamp ; +.Pp +.Li krb5_deltat ; +.Ft krb5_error_code +.Fo krb5_set_real_time +.Fa "krb5_context context" +.Fa "krb5_timestamp sec" +.Fa "int32_t usec" +.Fc +.Ft krb5_error_code +.Fo krb5_timeofday +.Fa "krb5_context context" +.Fa "krb5_timestamp *timeret" +.Fc +.Ft krb5_error_code +.Fo krb5_us_timeofday +.Fa "krb5_context context" +.Fa "krb5_timestamp *sec" +.Fa "int32_t *usec" +.Fc +.Ft krb5_error_code +.Fo krb5_format_time +.Fa "krb5_context context" +.Fa "time_t t" +.Fa "char *s" +.Fa "size_t len" +.Fa "krb5_boolean include_time" +.Fc +.Ft krb5_error_code +.Fo krb5_string_to_deltat +.Fa "const char *string" +.Fa "krb5_deltat *deltat" +.Fc +.Sh DESCRIPTION +.Nm krb5_set_real_time +sets the absolute time that the caller knows the KDC has. +With this the Kerberos library can calculate the relative +difference between the KDC time and the local system time and store it +in the +.Fa context . +With this information the Kerberos library can adjust all time stamps +in Kerberos packages. +.Pp +.Fn krb5_timeofday +returns the current time, but adjusted with the time difference +between the local host and the KDC. +.Fn krb5_us_timeofday +also returns microseconds. +.Pp +.Nm krb5_format_time +formats the time +.Fa t +into the string +.Fa s +of length +.Fa len . +If +.Fa include_time +is set, the time is set include_time. +.Pp +.Nm krb5_string_to_deltat +parses delta time +.Fa string +into +.Fa deltat . +.Sh SEE ALSO +.Xr gettimeofday 2 , +.Xr krb5 3 diff --git a/lib/krb5/krb5_unparse_name.3 b/lib/krb5/krb5_unparse_name.3 new file mode 100644 index 0000000..274d638 --- /dev/null +++ b/lib/krb5/krb5_unparse_name.3 @@ -0,0 +1,62 @@ +.\" Copyright (c) 1997 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_unparse_name.3 12329 2003-05-26 14:09:04Z lha $ +.\" +.Dd August 8, 1997 +.Dt KRB5_UNPARSE_NAME 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_unparse_name +.\" .Nm krb5_unparse_name_ext +.Nd principal to string conversion +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Ft krb5_error_code +.Fn krb5_unparse_name "krb5_context context" "krb5_principal principal" "char **name" +.\" .Ft krb5_error_code +.\" .Fn krb5_unparse_name_ext "krb5_context context" "krb5_const_principal principal" "char **name" "size_t *size" +.Sh DESCRIPTION +This function takes a +.Fa principal , +and will convert in to a printable representation with the same syntax +as described in +.Xr krb5_parse_name 3 . +.Fa *name +will point to allocated data and should be freed by the caller. +.Sh SEE ALSO +.Xr krb5_425_conv_principal 3 , +.Xr krb5_build_principal 3 , +.Xr krb5_free_principal 3 , +.Xr krb5_parse_name 3 , +.Xr krb5_sname_to_principal 3 diff --git a/lib/krb5/krb5_verify_init_creds.3 b/lib/krb5/krb5_verify_init_creds.3 new file mode 100644 index 0000000..9a34648 --- /dev/null +++ b/lib/krb5/krb5_verify_init_creds.3 @@ -0,0 +1,103 @@ +.\" Copyright (c) 2003 - 2006 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_verify_init_creds.3 22071 2007-11-14 20:04:50Z lha $ +.\" +.Dd May 1, 2006 +.Dt KRB5_VERIFY_INIT_CREDS 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_verify_init_creds_opt_init , +.Nm krb5_verify_init_creds_opt_set_ap_req_nofail , +.Nm krb5_verify_init_creds +.Nd "verifies a credential cache is correct by using a local keytab" +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Pp +.Li "struct krb5_verify_init_creds_opt;" +.Ft void +.Fo krb5_verify_init_creds_opt_init +.Fa "krb5_verify_init_creds_opt *options" +.Fc +.Ft void +.Fo krb5_verify_init_creds_opt_set_ap_req_nofail +.Fa "krb5_verify_init_creds_opt *options" +.Fa "int ap_req_nofail" +.Fc +.Ft krb5_error_code +.Fo krb5_verify_init_creds +.Fa "krb5_context context" +.Fa "krb5_creds *creds" +.Fa "krb5_principal ap_req_server" +.Fa "krb5_ccache *ccache" +.Fa "krb5_verify_init_creds_opt *options" +.Fc +.Sh DESCRIPTION +The +.Nm krb5_verify_init_creds +function verifies the initial tickets with the local keytab to make +sure the response of the KDC was spoof-ed. +.Pp +.Nm krb5_verify_init_creds +will use principal +.Fa ap_req_server +from the local keytab, if +.Dv NULL +is passed in, the code will guess the local hostname and use that to +form host/hostname/GUESSED-REALM-FOR-HOSTNAME. +.Fa creds +is the credential that +.Nm krb5_verify_init_creds +should verify. +If +.Fa ccache +is given +.Fn krb5_verify_init_creds +stores all credentials it fetched from the KDC there, otherwise it +will use a memory credential cache that is destroyed when done. +.Pp +.Fn krb5_verify_init_creds_opt_init +cleans the the structure, must be used before trying to pass it in to +.Fn krb5_verify_init_creds . +.Pp +.Fn krb5_verify_init_creds_opt_set_ap_req_nofail +controls controls the behavior if +.Fa ap_req_server +doesn't exists in the local keytab or in the KDC's database, if it's +true, the error will be ignored. Note that this use is possible +insecure. +.Sh SEE ALSO +.Xr krb5 3 , +.Xr krb5_get_init_creds 3 , +.Xr krb5_verify_user 3 , +.Xr krb5.conf 5 diff --git a/lib/krb5/krb5_verify_user.3 b/lib/krb5/krb5_verify_user.3 new file mode 100644 index 0000000..8086bc0 --- /dev/null +++ b/lib/krb5/krb5_verify_user.3 @@ -0,0 +1,241 @@ +.\" Copyright (c) 2001 - 2006 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_verify_user.3 22071 2007-11-14 20:04:50Z lha $ +.\" +.Dd May 1, 2006 +.Dt KRB5_VERIFY_USER 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_verify_user , +.Nm krb5_verify_user_lrealm , +.Nm krb5_verify_user_opt , +.Nm krb5_verify_opt_init , +.Nm krb5_verify_opt_alloc , +.Nm krb5_verify_opt_free , +.Nm krb5_verify_opt_set_ccache , +.Nm krb5_verify_opt_set_flags , +.Nm krb5_verify_opt_set_service , +.Nm krb5_verify_opt_set_secure , +.Nm krb5_verify_opt_set_keytab +.Nd Heimdal password verifying functions +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Ft krb5_error_code +.Fn "krb5_verify_user" "krb5_context context" " krb5_principal principal" "krb5_ccache ccache" "const char *password" "krb5_boolean secure" "const char *service" +.Ft krb5_error_code +.Fn "krb5_verify_user_lrealm" "krb5_context context" "krb5_principal principal" "krb5_ccache ccache" "const char *password" "krb5_boolean secure" "const char *service" +.Ft void +.Fn krb5_verify_opt_init "krb5_verify_opt *opt" +.Ft void +.Fn krb5_verify_opt_alloc "krb5_verify_opt **opt" +.Ft void +.Fn krb5_verify_opt_free "krb5_verify_opt *opt" +.Ft void +.Fn krb5_verify_opt_set_ccache "krb5_verify_opt *opt" "krb5_ccache ccache" +.Ft void +.Fn krb5_verify_opt_set_keytab "krb5_verify_opt *opt" "krb5_keytab keytab" +.Ft void +.Fn krb5_verify_opt_set_secure "krb5_verify_opt *opt" "krb5_boolean secure" +.Ft void +.Fn krb5_verify_opt_set_service "krb5_verify_opt *opt" "const char *service" +.Ft void +.Fn krb5_verify_opt_set_flags "krb5_verify_opt *opt" "unsigned int flags" +.Ft krb5_error_code +.Fo krb5_verify_user_opt +.Fa "krb5_context context" +.Fa "krb5_principal principal" +.Fa "const char *password" +.Fa "krb5_verify_opt *opt" +.Fc +.Sh DESCRIPTION +The +.Nm krb5_verify_user +function verifies the password supplied by a user. +The principal whose password will be verified is specified in +.Fa principal . +New tickets will be obtained as a side-effect and stored in +.Fa ccache +(if +.Dv NULL , +the default ccache is used). +.Fn krb5_verify_user +will call +.Fn krb5_cc_initialize +on the given +.Fa ccache , +so +.Fa ccache +must only initialized with +.Fn krb5_cc_resolve +or +.Fn krb5_cc_gen_new . +If the password is not supplied in +.Fa password +(and is given as +.Dv NULL ) +the user will be prompted for it. +If +.Fa secure +the ticket will be verified against the locally stored service key +.Fa service +(by default +.Ql host +if given as +.Dv NULL +). +.Pp +The +.Fn krb5_verify_user_lrealm +function does the same, except that it ignores the realm in +.Fa principal +and tries all the local realms (see +.Xr krb5.conf 5 ) . +After a successful return, the principal is set to the authenticated +realm. If the call fails, the principal will not be meaningful, and +should only be freed with +.Xr krb5_free_principal 3 . +.Pp +.Fn krb5_verify_opt_alloc +and +.Fn krb5_verify_opt_free +allocates and frees a +.Li krb5_verify_opt . +You should use the the alloc and free function instead of allocation +the structure yourself, this is because in a future release the +structure wont be exported. +.Pp +.Fn krb5_verify_opt_init +resets all opt to default values. +.Pp +None of the krb5_verify_opt_set function makes a copy of the data +structure that they are called with. It's up the caller to free them +after the +.Fn krb5_verify_user_opt +is called. +.Pp +.Fn krb5_verify_opt_set_ccache +sets the +.Fa ccache +that user of +.Fa opt +will use. If not set, the default credential cache will be used. +.Pp +.Fn krb5_verify_opt_set_keytab +sets the +.Fa keytab +that user of +.Fa opt +will use. If not set, the default keytab will be used. +.Pp +.Fn krb5_verify_opt_set_secure +if +.Fa secure +if true, the password verification will require that the ticket will +be verified against the locally stored service key. If not set, +default value is true. +.Pp +.Fn krb5_verify_opt_set_service +sets the +.Fa service +principal that user of +.Fa opt +will use. If not set, the +.Ql host +service will be used. +.Pp +.Fn krb5_verify_opt_set_flags +sets +.Fa flags +that user of +.Fa opt +will use. +If the flag +.Dv KRB5_VERIFY_LREALMS +is used, the +.Fa principal +will be modified like +.Fn krb5_verify_user_lrealm +modifies it. +.Pp +.Fn krb5_verify_user_opt +function verifies the +.Fa password +supplied by a user. +The principal whose password will be verified is specified in +.Fa principal . +Options the to the verification process is pass in in +.Fa opt . +.Sh EXAMPLES +Here is a example program that verifies a password. it uses the +.Ql host/`hostname` +service principal in +.Pa krb5.keytab . +.Bd -literal +#include <krb5.h> + +int +main(int argc, char **argv) +{ + char *user; + krb5_error_code error; + krb5_principal princ; + krb5_context context; + + if (argc != 2) + errx(1, "usage: verify_passwd <principal-name>"); + + user = argv[1]; + + if (krb5_init_context(&context) < 0) + errx(1, "krb5_init_context"); + + if ((error = krb5_parse_name(context, user, &princ)) != 0) + krb5_err(context, 1, error, "krb5_parse_name"); + + error = krb5_verify_user(context, princ, NULL, NULL, TRUE, NULL); + if (error) + krb5_err(context, 1, error, "krb5_verify_user"); + + return 0; +} +.Ed +.Sh SEE ALSO +.Xr krb5_cc_gen_new 3 , +.Xr krb5_cc_initialize 3 , +.Xr krb5_cc_resolve 3 , +.Xr krb5_err 3 , +.Xr krb5_free_principal 3 , +.Xr krb5_init_context 3 , +.Xr krb5_kt_default 3 , +.Xr krb5.conf 5 diff --git a/lib/krb5/krb5_warn.3 b/lib/krb5/krb5_warn.3 new file mode 100644 index 0000000..5610cd8 --- /dev/null +++ b/lib/krb5/krb5_warn.3 @@ -0,0 +1,233 @@ +.\" Copyright (c) 1997, 2001 - 2006 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: krb5_warn.3 19085 2006-11-21 07:55:20Z lha $ +.\" +.Dd May 1, 2006 +.Dt KRB5_WARN 3 +.Os HEIMDAL +.Sh NAME +.Nm krb5_abort , +.Nm krb5_abortx , +.Nm krb5_clear_error_string , +.Nm krb5_err , +.Nm krb5_errx , +.Nm krb5_free_error_string , +.Nm krb5_get_err_text , +.Nm krb5_get_error_message , +.Nm krb5_get_error_string , +.Nm krb5_have_error_string , +.Nm krb5_set_error_string , +.Nm krb5_set_warn_dest , +.Nm krb5_get_warn_dest , +.Nm krb5_vabort , +.Nm krb5_vabortx , +.Nm krb5_verr , +.Nm krb5_verrx , +.Nm krb5_vset_error_string , +.Nm krb5_vwarn , +.Nm krb5_vwarnx , +.Nm krb5_warn , +.Nm krb5_warnx +.Nd Heimdal warning and error functions +.Sh LIBRARY +Kerberos 5 Library (libkrb5, -lkrb5) +.Sh SYNOPSIS +.In krb5.h +.Ft krb5_error_code +.Fn krb5_abort "krb5_context context" "krb5_error_code code" "const char *fmt" "..." +.Ft krb5_error_code +.Fn krb5_abortx "krb5_context context" "krb5_error_code code" "const char *fmt" "..." +.Ft void +.Fn krb5_clear_error_string "krb5_context context" +.Ft krb5_error_code +.Fn krb5_err "krb5_context context" "int eval" "krb5_error_code code" "const char *format" "..." +.Ft krb5_error_code +.Fn krb5_errx "krb5_context context" "int eval" "const char *format" "..." +.Ft void +.Fn krb5_free_error_string "krb5_context context" "char *str" +.Ft krb5_error_code +.Fn krb5_verr "krb5_context context" "int eval" "krb5_error_code code" "const char *format" "va_list ap" +.Ft krb5_error_code +.Fn krb5_verrx "krb5_context context" "int eval" "const char *format" "va_list ap" +.Ft krb5_error_code +.Fn krb5_vset_error_string "krb5_context context" "const char *fmt" "va_list args" +.Ft krb5_error_code +.Fn krb5_vwarn "krb5_context context" "krb5_error_code code" "const char *format" "va_list ap" +.Ft krb5_error_code +.Fn krb5_vwarnx "krb5_context context" "const char *format" "va_list ap" +.Ft krb5_error_code +.Fn krb5_warn "krb5_context context" "krb5_error_code code" "const char *format" "..." +.Ft krb5_error_code +.Fn krb5_warnx "krb5_context context" "const char *format" "..." +.Ft krb5_error_code +.Fn krb5_set_error_string "krb5_context context" "const char *fmt" "..." +.Ft krb5_error_code +.Fn krb5_set_warn_dest "krb5_context context" "krb5_log_facility *facility" +.Ft "char *" +.Ft krb5_log_facility * +.Fo krb5_get_warn_dest +.Fa "krb5_context context" +.Fc +.Fn krb5_get_err_text "krb5_context context" "krb5_error_code code" +.Ft char* +.Fn krb5_get_error_string "krb5_context context" +.Ft char* +.Fn krb5_get_error_message "krb5_context context, krb5_error_code code" +.Ft krb5_boolean +.Fn krb5_have_error_string "krb5_context context" +.Ft krb5_error_code +.Fn krb5_vabortx "krb5_context context" "const char *fmt" "va_list ap" +.Ft krb5_error_code +.Fn krb5_vabort "krb5_context context" "const char *fmt" "va_list ap" +.Sh DESCRIPTION +These functions print a warning message to some destination. +.Fa format +is a printf style format specifying the message to print. The forms not ending in an +.Dq x +print the error string associated with +.Fa code +along with the message. +The +.Dq err +functions exit with exit status +.Fa eval +after printing the message. +.Pp +Applications that want to get the error message to report it to a user +or store it in a log want to use +.Fn krb5_get_error_message . +.Pp +The +.Fn krb5_set_warn_func +function sets the destination for warning messages to the specified +.Fa facility . +Messages logged with the +.Dq warn +functions have a log level of 1, while the +.Dq err +functions log with level 0. +.Pp +.Fn krb5_get_err_text +fetches the human readable strings describing the error-code. +.Pp +.Fn krb5_abort +and +.Nm krb5_abortx +behaves like +.Nm krb5_err +and +.Nm krb5_errx +but instead of exiting using the +.Xr exit 3 +call, +.Xr abort 3 +is used. +.Pp +.Fn krb5_free_error_string +frees the error string +.Fa str +returned by +.Fn krb5_get_error_string . +.Pp +.Fn krb5_clear_error_string +clears the error string from the +.Fa context . +.Pp +.Fn krb5_set_error_string +and +.Fn krb5_vset_error_string +sets an verbose error string in +.Fa context . +.Pp +.Fn krb5_get_error_string +fetches the error string from +.Fa context . +The error message in the context is consumed and must be freed using +.Fn krb5_free_error_string +by the caller. +See also +.Fn krb5_get_error_message , +what is usually less verbose to use. +.Pp +.Fn krb5_have_error_string +returns +.Dv TRUE +if there is a verbose error message in the +.Fa context . +.Pp +.Fn krb5_get_error_message +fetches the error string from the context, or if there +is no customized error string in +.Fa context , +uses +.Fa code +to return a error string. +In either case, the error message in the context is consumed and must +be freed using +.Fn krb5_free_error_string +by the caller. +.Pp +.Fn krb5_set_warn_dest +and +.Fn krb5_get_warn_dest +sets and get the log context that is used by +.Fn krb5_warn +and friends. By using this the application can control where the +output should go. For example, this is imperative to inetd servers +where logging status and error message will end up on the output +stream to the client. +.Sh EXAMPLES +Below is a simple example how to report error messages from the +Kerberos library in an application. +.Bd -literal +#include <krb5.h> + +krb5_error_code +function (krb5_context context) +{ + krb5_error_code ret; + + ret = krb5_function (context, arg1, arg2); + if (ret) { + char *s = krb5_get_error_message(context, ret); + if (s == NULL) + errx(1, "kerberos error: %d (and out of memory)", ret); + application_logger("krb5_function failed: %s", s); + krb5_free_error_string(context, s); + return ret; + } + return 0; +} +.Ed +.Sh SEE ALSO +.Xr krb5 3 , +.Xr krb5_openlog 3 diff --git a/lib/krb5/krb_err.et b/lib/krb5/krb_err.et new file mode 100644 index 0000000..f7dbb6c --- /dev/null +++ b/lib/krb5/krb_err.et @@ -0,0 +1,63 @@ +# +# Error messages for the krb4 library +# +# This might look like a com_err file, but is not +# +id "$Id: krb_err.et,v 1.7 1998/03/29 14:19:52 bg Exp $" + +error_table krb + +prefix KRB4ET +ec KSUCCESS, "Kerberos 4 successful" +ec KDC_NAME_EXP, "Kerberos 4 principal expired" +ec KDC_SERVICE_EXP, "Kerberos 4 service expired" +ec KDC_AUTH_EXP, "Kerberos 4 auth expired" +ec KDC_PKT_VER, "Incorrect Kerberos 4 master key version" +ec KDC_P_MKEY_VER, "Incorrect Kerberos 4 master key version" +ec KDC_S_MKEY_VER, "Incorrect Kerberos 4 master key version" +ec KDC_BYTE_ORDER, "Kerberos 4 byte order unknown" +ec KDC_PR_UNKNOWN, "Kerberos 4 principal unknown" +ec KDC_PR_N_UNIQUE, "Kerberos 4 principal not unique" +ec KDC_NULL_KEY, "Kerberos 4 principal has null key" +index 20 +ec KDC_GEN_ERR, "Generic error from KDC (Kerberos 4)" +ec GC_TKFIL, "Can't read Kerberos 4 ticket file" +ec GC_NOTKT, "Can't find Kerberos 4 ticket or TGT" +index 26 +ec MK_AP_TGTEXP, "Kerberos 4 TGT Expired" +index 31 +ec RD_AP_UNDEC, "Kerberos 4: Can't decode authenticator" +ec RD_AP_EXP, "Kerberos 4 ticket expired" +ec RD_AP_NYV, "Kerberos 4 ticket not yet valid" +ec RD_AP_REPEAT, "Kerberos 4: Repeated request" +ec RD_AP_NOT_US, "The Kerberos 4 ticket isn't for us" +ec RD_AP_INCON, "Kerberos 4 request inconsistent" +ec RD_AP_TIME, "Kerberos 4: delta_t too big" +ec RD_AP_BADD, "Kerberos 4: incorrect net address" +ec RD_AP_VERSION, "Kerberos protocol not version 4" +ec RD_AP_MSG_TYPE, "Kerberos 4: invalid msg type" +ec RD_AP_MODIFIED, "Kerberos 4: message stream modified" +ec RD_AP_ORDER, "Kerberos 4: message out of order" +ec RD_AP_UNAUTHOR, "Kerberos 4: unauthorized request" +index 51 +ec GT_PW_NULL, "Kerberos 4: current PW is null" +ec GT_PW_BADPW, "Kerberos 4: Incorrect current password" +ec GT_PW_PROT, "Kerberos 4 protocol error" +ec GT_PW_KDCERR, "Error returned by KDC (Kerberos 4)" +ec GT_PW_NULLTKT, "Null Kerberos 4 ticket returned by KDC" +ec SKDC_RETRY, "Kerberos 4: Retry count exceeded" +ec SKDC_CANT, "Kerberos 4: Can't send request" +index 61 +ec INTK_W_NOTALL, "Kerberos 4: not all tickets returned" +ec INTK_BADPW, "Kerberos 4: incorrect password" +ec INTK_PROT, "Kerberos 4: Protocol Error" +index 70 +ec INTK_ERR, "Other error in Kerberos 4" +ec AD_NOTGT, "Don't have Kerberos 4 ticket-granting ticket" +index 76 +ec NO_TKT_FIL, "No Kerberos 4 ticket file found" +ec TKT_FIL_ACC, "Couldn't access Kerberos 4 ticket file" +ec TKT_FIL_LCK, "Couldn't lock Kerberos 4 ticket file" +ec TKT_FIL_FMT, "Bad Kerberos 4 ticket file format" +ec TKT_FIL_INI, "Kerberos 4: tf_init not called first" +ec KNAME_FMT, "Bad Kerberos 4 name format" diff --git a/lib/krb5/krbhst-test.c b/lib/krb5/krbhst-test.c new file mode 100644 index 0000000..38b0b6a --- /dev/null +++ b/lib/krb5/krbhst-test.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2001 - 2002 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +#include <err.h> +#include <getarg.h> + +RCSID("$Id: krbhst-test.c 15466 2005-06-17 04:21:47Z lha $"); + +static int version_flag = 0; +static int help_flag = 0; + +static struct getargs args[] = { + {"version", 0, arg_flag, &version_flag, + "print version", NULL }, + {"help", 0, arg_flag, &help_flag, + NULL, NULL } +}; + +static void +usage (int ret) +{ + arg_printusage (args, + sizeof(args)/sizeof(*args), + NULL, + "[realms ...]"); + exit (ret); +} + +int +main(int argc, char **argv) +{ + int i, j; + krb5_context context; + int types[] = {KRB5_KRBHST_KDC, KRB5_KRBHST_ADMIN, KRB5_KRBHST_CHANGEPW, + KRB5_KRBHST_KRB524}; + const char *type_str[] = {"kdc", "admin", "changepw", "krb524"}; + int optidx = 0; + + setprogname (argv[0]); + + if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) + usage(1); + + if (help_flag) + usage (0); + + if(version_flag){ + print_version(NULL); + exit(0); + } + + argc -= optidx; + argv += optidx; + + krb5_init_context (&context); + for(i = 0; i < argc; i++) { + krb5_krbhst_handle handle; + char host[MAXHOSTNAMELEN]; + + for (j = 0; j < sizeof(types)/sizeof(*types); ++j) { + printf ("%s for %s:\n", type_str[j], argv[i]); + + krb5_krbhst_init(context, argv[i], types[j], &handle); + while(krb5_krbhst_next_as_string(context, handle, + host, sizeof(host)) == 0) + printf("%s\n", host); + krb5_krbhst_reset(context, handle); + printf ("\n"); + } + } + return 0; +} diff --git a/lib/krb5/krbhst.c b/lib/krb5/krbhst.c new file mode 100644 index 0000000..094fd4f --- /dev/null +++ b/lib/krb5/krbhst.c @@ -0,0 +1,1010 @@ +/* + * Copyright (c) 2001 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" +#include <resolve.h> +#include "locate_plugin.h" + +RCSID("$Id: krbhst.c 21457 2007-07-10 12:53:25Z lha $"); + +static int +string_to_proto(const char *string) +{ + if(strcasecmp(string, "udp") == 0) + return KRB5_KRBHST_UDP; + else if(strcasecmp(string, "tcp") == 0) + return KRB5_KRBHST_TCP; + else if(strcasecmp(string, "http") == 0) + return KRB5_KRBHST_HTTP; + return -1; +} + +/* + * set `res' and `count' to the result of looking up SRV RR in DNS for + * `proto', `proto', `realm' using `dns_type'. + * if `port' != 0, force that port number + */ + +static krb5_error_code +srv_find_realm(krb5_context context, krb5_krbhst_info ***res, int *count, + const char *realm, const char *dns_type, + const char *proto, const char *service, int port) +{ + char domain[1024]; + struct dns_reply *r; + struct resource_record *rr; + int num_srv; + int proto_num; + int def_port; + + *res = NULL; + *count = 0; + + proto_num = string_to_proto(proto); + if(proto_num < 0) { + krb5_set_error_string(context, "unknown protocol `%s'", proto); + return EINVAL; + } + + if(proto_num == KRB5_KRBHST_HTTP) + def_port = ntohs(krb5_getportbyname (context, "http", "tcp", 80)); + else if(port == 0) + def_port = ntohs(krb5_getportbyname (context, service, proto, 88)); + else + def_port = port; + + snprintf(domain, sizeof(domain), "_%s._%s.%s.", service, proto, realm); + + r = dns_lookup(domain, dns_type); + if(r == NULL) + return KRB5_KDC_UNREACH; + + for(num_srv = 0, rr = r->head; rr; rr = rr->next) + if(rr->type == T_SRV) + num_srv++; + + *res = malloc(num_srv * sizeof(**res)); + if(*res == NULL) { + dns_free_data(r); + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + dns_srv_order(r); + + for(num_srv = 0, rr = r->head; rr; rr = rr->next) + if(rr->type == T_SRV) { + krb5_krbhst_info *hi; + size_t len = strlen(rr->u.srv->target); + + hi = calloc(1, sizeof(*hi) + len); + if(hi == NULL) { + dns_free_data(r); + while(--num_srv >= 0) + free((*res)[num_srv]); + free(*res); + *res = NULL; + return ENOMEM; + } + (*res)[num_srv++] = hi; + + hi->proto = proto_num; + + hi->def_port = def_port; + if (port != 0) + hi->port = port; + else + hi->port = rr->u.srv->port; + + strlcpy(hi->hostname, rr->u.srv->target, len + 1); + } + + *count = num_srv; + + dns_free_data(r); + return 0; +} + + +struct krb5_krbhst_data { + char *realm; + unsigned int flags; + int def_port; + int port; /* hardwired port number if != 0 */ +#define KD_CONFIG 1 +#define KD_SRV_UDP 2 +#define KD_SRV_TCP 4 +#define KD_SRV_HTTP 8 +#define KD_FALLBACK 16 +#define KD_CONFIG_EXISTS 32 +#define KD_LARGE_MSG 64 +#define KD_PLUGIN 128 + krb5_error_code (*get_next)(krb5_context, struct krb5_krbhst_data *, + krb5_krbhst_info**); + + unsigned int fallback_count; + + struct krb5_krbhst_info *hosts, **index, **end; +}; + +static krb5_boolean +krbhst_empty(const struct krb5_krbhst_data *kd) +{ + return kd->index == &kd->hosts; +} + +/* + * Return the default protocol for the `kd' (either TCP or UDP) + */ + +static int +krbhst_get_default_proto(struct krb5_krbhst_data *kd) +{ + if (kd->flags & KD_LARGE_MSG) + return KRB5_KRBHST_TCP; + return KRB5_KRBHST_UDP; +} + + +/* + * parse `spec' into a krb5_krbhst_info, defaulting the port to `def_port' + * and forcing it to `port' if port != 0 + */ + +static struct krb5_krbhst_info* +parse_hostspec(krb5_context context, struct krb5_krbhst_data *kd, + const char *spec, int def_port, int port) +{ + const char *p = spec; + struct krb5_krbhst_info *hi; + + hi = calloc(1, sizeof(*hi) + strlen(spec)); + if(hi == NULL) + return NULL; + + hi->proto = krbhst_get_default_proto(kd); + + if(strncmp(p, "http://", 7) == 0){ + hi->proto = KRB5_KRBHST_HTTP; + p += 7; + } else if(strncmp(p, "http/", 5) == 0) { + hi->proto = KRB5_KRBHST_HTTP; + p += 5; + def_port = ntohs(krb5_getportbyname (context, "http", "tcp", 80)); + }else if(strncmp(p, "tcp/", 4) == 0){ + hi->proto = KRB5_KRBHST_TCP; + p += 4; + } else if(strncmp(p, "udp/", 4) == 0) { + p += 4; + } + + if(strsep_copy(&p, ":", hi->hostname, strlen(spec) + 1) < 0) { + free(hi); + return NULL; + } + /* get rid of trailing /, and convert to lower case */ + hi->hostname[strcspn(hi->hostname, "/")] = '\0'; + strlwr(hi->hostname); + + hi->port = hi->def_port = def_port; + if(p != NULL) { + char *end; + hi->port = strtol(p, &end, 0); + if(end == p) { + free(hi); + return NULL; + } + } + if (port) + hi->port = port; + return hi; +} + +void +_krb5_free_krbhst_info(krb5_krbhst_info *hi) +{ + if (hi->ai != NULL) + freeaddrinfo(hi->ai); + free(hi); +} + +krb5_error_code +_krb5_krbhost_info_move(krb5_context context, + krb5_krbhst_info *from, + krb5_krbhst_info **to) +{ + size_t hostnamelen = strlen(from->hostname); + /* trailing NUL is included in structure */ + *to = calloc(1, sizeof(**to) + hostnamelen); + if(*to == NULL) { + krb5_set_error_string(context, "malloc - out of memory"); + return ENOMEM; + } + + (*to)->proto = from->proto; + (*to)->port = from->port; + (*to)->def_port = from->def_port; + (*to)->ai = from->ai; + from->ai = NULL; + (*to)->next = NULL; + memcpy((*to)->hostname, from->hostname, hostnamelen + 1); + return 0; +} + + +static void +append_host_hostinfo(struct krb5_krbhst_data *kd, struct krb5_krbhst_info *host) +{ + struct krb5_krbhst_info *h; + + for(h = kd->hosts; h; h = h->next) + if(h->proto == host->proto && + h->port == host->port && + strcmp(h->hostname, host->hostname) == 0) { + _krb5_free_krbhst_info(host); + return; + } + *kd->end = host; + kd->end = &host->next; +} + +static krb5_error_code +append_host_string(krb5_context context, struct krb5_krbhst_data *kd, + const char *host, int def_port, int port) +{ + struct krb5_krbhst_info *hi; + + hi = parse_hostspec(context, kd, host, def_port, port); + if(hi == NULL) + return ENOMEM; + + append_host_hostinfo(kd, hi); + return 0; +} + +/* + * return a readable representation of `host' in `hostname, hostlen' + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_krbhst_format_string(krb5_context context, const krb5_krbhst_info *host, + char *hostname, size_t hostlen) +{ + const char *proto = ""; + char portstr[7] = ""; + if(host->proto == KRB5_KRBHST_TCP) + proto = "tcp/"; + else if(host->proto == KRB5_KRBHST_HTTP) + proto = "http://"; + if(host->port != host->def_port) + snprintf(portstr, sizeof(portstr), ":%d", host->port); + snprintf(hostname, hostlen, "%s%s%s", proto, host->hostname, portstr); + return 0; +} + +/* + * create a getaddrinfo `hints' based on `proto' + */ + +static void +make_hints(struct addrinfo *hints, int proto) +{ + memset(hints, 0, sizeof(*hints)); + hints->ai_family = AF_UNSPEC; + switch(proto) { + case KRB5_KRBHST_UDP : + hints->ai_socktype = SOCK_DGRAM; + break; + case KRB5_KRBHST_HTTP : + case KRB5_KRBHST_TCP : + hints->ai_socktype = SOCK_STREAM; + break; + } +} + +/* + * return an `struct addrinfo *' in `ai' corresponding to the information + * in `host'. free:ing is handled by krb5_krbhst_free. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_krbhst_get_addrinfo(krb5_context context, krb5_krbhst_info *host, + struct addrinfo **ai) +{ + struct addrinfo hints; + char portstr[NI_MAXSERV]; + int ret; + + if (host->ai == NULL) { + make_hints(&hints, host->proto); + snprintf (portstr, sizeof(portstr), "%d", host->port); + ret = getaddrinfo(host->hostname, portstr, &hints, &host->ai); + if (ret) + return krb5_eai_to_heim_errno(ret, errno); + } + *ai = host->ai; + return 0; +} + +static krb5_boolean +get_next(struct krb5_krbhst_data *kd, krb5_krbhst_info **host) +{ + struct krb5_krbhst_info *hi = *kd->index; + if(hi != NULL) { + *host = hi; + kd->index = &(*kd->index)->next; + return TRUE; + } + return FALSE; +} + +static void +srv_get_hosts(krb5_context context, struct krb5_krbhst_data *kd, + const char *proto, const char *service) +{ + krb5_krbhst_info **res; + int count, i; + + if (srv_find_realm(context, &res, &count, kd->realm, "SRV", proto, service, + kd->port)) + return; + for(i = 0; i < count; i++) + append_host_hostinfo(kd, res[i]); + free(res); +} + +/* + * read the configuration for `conf_string', defaulting to kd->def_port and + * forcing it to `kd->port' if kd->port != 0 + */ + +static void +config_get_hosts(krb5_context context, struct krb5_krbhst_data *kd, + const char *conf_string) +{ + int i; + + char **hostlist; + hostlist = krb5_config_get_strings(context, NULL, + "realms", kd->realm, conf_string, NULL); + + if(hostlist == NULL) + return; + kd->flags |= KD_CONFIG_EXISTS; + for(i = 0; hostlist && hostlist[i] != NULL; i++) + append_host_string(context, kd, hostlist[i], kd->def_port, kd->port); + + krb5_config_free_strings(hostlist); +} + +/* + * as a fallback, look for `serv_string.kd->realm' (typically + * kerberos.REALM, kerberos-1.REALM, ... + * `port' is the default port for the service, and `proto' the + * protocol + */ + +static krb5_error_code +fallback_get_hosts(krb5_context context, struct krb5_krbhst_data *kd, + const char *serv_string, int port, int proto) +{ + char *host; + int ret; + struct addrinfo *ai; + struct addrinfo hints; + char portstr[NI_MAXSERV]; + + /* + * Don't try forever in case the DNS server keep returning us + * entries (like wildcard entries or the .nu TLD) + */ + if(kd->fallback_count >= 5) { + kd->flags |= KD_FALLBACK; + return 0; + } + + if(kd->fallback_count == 0) + asprintf(&host, "%s.%s.", serv_string, kd->realm); + else + asprintf(&host, "%s-%d.%s.", + serv_string, kd->fallback_count, kd->realm); + + if (host == NULL) + return ENOMEM; + + make_hints(&hints, proto); + snprintf(portstr, sizeof(portstr), "%d", port); + ret = getaddrinfo(host, portstr, &hints, &ai); + if (ret) { + /* no more hosts, so we're done here */ + free(host); + kd->flags |= KD_FALLBACK; + } else { + struct krb5_krbhst_info *hi; + size_t hostlen = strlen(host); + + hi = calloc(1, sizeof(*hi) + hostlen); + if(hi == NULL) { + free(host); + return ENOMEM; + } + + hi->proto = proto; + hi->port = hi->def_port = port; + hi->ai = ai; + memmove(hi->hostname, host, hostlen); + hi->hostname[hostlen] = '\0'; + free(host); + append_host_hostinfo(kd, hi); + kd->fallback_count++; + } + return 0; +} + +/* + * Fetch hosts from plugin + */ + +static krb5_error_code +add_locate(void *ctx, int type, struct sockaddr *addr) +{ + struct krb5_krbhst_info *hi; + struct krb5_krbhst_data *kd = ctx; + char host[NI_MAXHOST], port[NI_MAXSERV]; + struct addrinfo hints, *ai; + socklen_t socklen; + size_t hostlen; + int ret; + + socklen = socket_sockaddr_size(addr); + + ret = getnameinfo(addr, socklen, host, sizeof(host), port, sizeof(port), + NI_NUMERICHOST|NI_NUMERICSERV); + if (ret != 0) + return 0; + + make_hints(&hints, krbhst_get_default_proto(kd)); + ret = getaddrinfo(host, port, &hints, &ai); + if (ret) + return 0; + + hostlen = strlen(host); + + hi = calloc(1, sizeof(*hi) + hostlen); + if(hi == NULL) + return ENOMEM; + + hi->proto = krbhst_get_default_proto(kd); + hi->port = hi->def_port = socket_get_port(addr); + hi->ai = ai; + memmove(hi->hostname, host, hostlen); + hi->hostname[hostlen] = '\0'; + append_host_hostinfo(kd, hi); + + return 0; +} + +static void +plugin_get_hosts(krb5_context context, + struct krb5_krbhst_data *kd, + enum locate_service_type type) +{ + struct krb5_plugin *list = NULL, *e; + krb5_error_code ret; + + ret = _krb5_plugin_find(context, PLUGIN_TYPE_DATA, "resolve", &list); + if(ret != 0 || list == NULL) + return; + + kd->flags |= KD_CONFIG_EXISTS; + + for (e = list; e != NULL; e = _krb5_plugin_get_next(e)) { + krb5plugin_service_locate_ftable *service; + void *ctx; + + service = _krb5_plugin_get_symbol(e); + if (service->minor_version != 0) + continue; + + (*service->init)(context, &ctx); + ret = (*service->lookup)(ctx, type, kd->realm, 0, 0, add_locate, kd); + (*service->fini)(ctx); + if (ret) { + krb5_set_error_string(context, "Plugin failed to lookup"); + break; + } + } + _krb5_plugin_free(list); +} + +/* + * + */ + +static krb5_error_code +kdc_get_next(krb5_context context, + struct krb5_krbhst_data *kd, + krb5_krbhst_info **host) +{ + krb5_error_code ret; + + if ((kd->flags & KD_PLUGIN) == 0) { + plugin_get_hosts(context, kd, locate_service_kdc); + kd->flags |= KD_PLUGIN; + if(get_next(kd, host)) + return 0; + } + + if((kd->flags & KD_CONFIG) == 0) { + config_get_hosts(context, kd, "kdc"); + kd->flags |= KD_CONFIG; + if(get_next(kd, host)) + return 0; + } + + if (kd->flags & KD_CONFIG_EXISTS) + return KRB5_KDC_UNREACH; /* XXX */ + + if(context->srv_lookup) { + if((kd->flags & KD_SRV_UDP) == 0 && (kd->flags & KD_LARGE_MSG) == 0) { + srv_get_hosts(context, kd, "udp", "kerberos"); + kd->flags |= KD_SRV_UDP; + if(get_next(kd, host)) + return 0; + } + + if((kd->flags & KD_SRV_TCP) == 0) { + srv_get_hosts(context, kd, "tcp", "kerberos"); + kd->flags |= KD_SRV_TCP; + if(get_next(kd, host)) + return 0; + } + if((kd->flags & KD_SRV_HTTP) == 0) { + srv_get_hosts(context, kd, "http", "kerberos"); + kd->flags |= KD_SRV_HTTP; + if(get_next(kd, host)) + return 0; + } + } + + while((kd->flags & KD_FALLBACK) == 0) { + ret = fallback_get_hosts(context, kd, "kerberos", + kd->def_port, + krbhst_get_default_proto(kd)); + if(ret) + return ret; + if(get_next(kd, host)) + return 0; + } + + return KRB5_KDC_UNREACH; /* XXX */ +} + +static krb5_error_code +admin_get_next(krb5_context context, + struct krb5_krbhst_data *kd, + krb5_krbhst_info **host) +{ + krb5_error_code ret; + + if ((kd->flags & KD_PLUGIN) == 0) { + plugin_get_hosts(context, kd, locate_service_kadmin); + kd->flags |= KD_PLUGIN; + if(get_next(kd, host)) + return 0; + } + + if((kd->flags & KD_CONFIG) == 0) { + config_get_hosts(context, kd, "admin_server"); + kd->flags |= KD_CONFIG; + if(get_next(kd, host)) + return 0; + } + + if (kd->flags & KD_CONFIG_EXISTS) + return KRB5_KDC_UNREACH; /* XXX */ + + if(context->srv_lookup) { + if((kd->flags & KD_SRV_TCP) == 0) { + srv_get_hosts(context, kd, "tcp", "kerberos-adm"); + kd->flags |= KD_SRV_TCP; + if(get_next(kd, host)) + return 0; + } + } + + if (krbhst_empty(kd) + && (kd->flags & KD_FALLBACK) == 0) { + ret = fallback_get_hosts(context, kd, "kerberos", + kd->def_port, + krbhst_get_default_proto(kd)); + if(ret) + return ret; + kd->flags |= KD_FALLBACK; + if(get_next(kd, host)) + return 0; + } + + return KRB5_KDC_UNREACH; /* XXX */ +} + +static krb5_error_code +kpasswd_get_next(krb5_context context, + struct krb5_krbhst_data *kd, + krb5_krbhst_info **host) +{ + krb5_error_code ret; + + if ((kd->flags & KD_PLUGIN) == 0) { + plugin_get_hosts(context, kd, locate_service_kpasswd); + kd->flags |= KD_PLUGIN; + if(get_next(kd, host)) + return 0; + } + + if((kd->flags & KD_CONFIG) == 0) { + config_get_hosts(context, kd, "kpasswd_server"); + kd->flags |= KD_CONFIG; + if(get_next(kd, host)) + return 0; + } + + if (kd->flags & KD_CONFIG_EXISTS) + return KRB5_KDC_UNREACH; /* XXX */ + + if(context->srv_lookup) { + if((kd->flags & KD_SRV_UDP) == 0) { + srv_get_hosts(context, kd, "udp", "kpasswd"); + kd->flags |= KD_SRV_UDP; + if(get_next(kd, host)) + return 0; + } + if((kd->flags & KD_SRV_TCP) == 0) { + srv_get_hosts(context, kd, "tcp", "kpasswd"); + kd->flags |= KD_SRV_TCP; + if(get_next(kd, host)) + return 0; + } + } + + /* no matches -> try admin */ + + if (krbhst_empty(kd)) { + kd->flags = 0; + kd->port = kd->def_port; + kd->get_next = admin_get_next; + ret = (*kd->get_next)(context, kd, host); + if (ret == 0) + (*host)->proto = krbhst_get_default_proto(kd); + return ret; + } + + return KRB5_KDC_UNREACH; /* XXX */ +} + +static krb5_error_code +krb524_get_next(krb5_context context, + struct krb5_krbhst_data *kd, + krb5_krbhst_info **host) +{ + if ((kd->flags & KD_PLUGIN) == 0) { + plugin_get_hosts(context, kd, locate_service_krb524); + kd->flags |= KD_PLUGIN; + if(get_next(kd, host)) + return 0; + } + + if((kd->flags & KD_CONFIG) == 0) { + config_get_hosts(context, kd, "krb524_server"); + if(get_next(kd, host)) + return 0; + kd->flags |= KD_CONFIG; + } + + if (kd->flags & KD_CONFIG_EXISTS) + return KRB5_KDC_UNREACH; /* XXX */ + + if(context->srv_lookup) { + if((kd->flags & KD_SRV_UDP) == 0) { + srv_get_hosts(context, kd, "udp", "krb524"); + kd->flags |= KD_SRV_UDP; + if(get_next(kd, host)) + return 0; + } + + if((kd->flags & KD_SRV_TCP) == 0) { + srv_get_hosts(context, kd, "tcp", "krb524"); + kd->flags |= KD_SRV_TCP; + if(get_next(kd, host)) + return 0; + } + } + + /* no matches -> try kdc */ + + if (krbhst_empty(kd)) { + kd->flags = 0; + kd->port = kd->def_port; + kd->get_next = kdc_get_next; + return (*kd->get_next)(context, kd, host); + } + + return KRB5_KDC_UNREACH; /* XXX */ +} + +static struct krb5_krbhst_data* +common_init(krb5_context context, + const char *realm, + int flags) +{ + struct krb5_krbhst_data *kd; + + if((kd = calloc(1, sizeof(*kd))) == NULL) + return NULL; + + if((kd->realm = strdup(realm)) == NULL) { + free(kd); + return NULL; + } + + /* For 'realms' without a . do not even think of going to DNS */ + if (!strchr(realm, '.')) + kd->flags |= KD_CONFIG_EXISTS; + + if (flags & KRB5_KRBHST_FLAGS_LARGE_MSG) + kd->flags |= KD_LARGE_MSG; + kd->end = kd->index = &kd->hosts; + return kd; +} + +/* + * initialize `handle' to look for hosts of type `type' in realm `realm' + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_krbhst_init(krb5_context context, + const char *realm, + unsigned int type, + krb5_krbhst_handle *handle) +{ + return krb5_krbhst_init_flags(context, realm, type, 0, handle); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_krbhst_init_flags(krb5_context context, + const char *realm, + unsigned int type, + int flags, + krb5_krbhst_handle *handle) +{ + struct krb5_krbhst_data *kd; + krb5_error_code (*next)(krb5_context, struct krb5_krbhst_data *, + krb5_krbhst_info **); + int def_port; + + switch(type) { + case KRB5_KRBHST_KDC: + next = kdc_get_next; + def_port = ntohs(krb5_getportbyname (context, "kerberos", "udp", 88)); + break; + case KRB5_KRBHST_ADMIN: + next = admin_get_next; + def_port = ntohs(krb5_getportbyname (context, "kerberos-adm", + "tcp", 749)); + break; + case KRB5_KRBHST_CHANGEPW: + next = kpasswd_get_next; + def_port = ntohs(krb5_getportbyname (context, "kpasswd", "udp", + KPASSWD_PORT)); + break; + case KRB5_KRBHST_KRB524: + next = krb524_get_next; + def_port = ntohs(krb5_getportbyname (context, "krb524", "udp", 4444)); + break; + default: + krb5_set_error_string(context, "unknown krbhst type (%u)", type); + return ENOTTY; + } + if((kd = common_init(context, realm, flags)) == NULL) + return ENOMEM; + kd->get_next = next; + kd->def_port = def_port; + *handle = kd; + return 0; +} + +/* + * return the next host information from `handle' in `host' + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_krbhst_next(krb5_context context, + krb5_krbhst_handle handle, + krb5_krbhst_info **host) +{ + if(get_next(handle, host)) + return 0; + + return (*handle->get_next)(context, handle, host); +} + +/* + * return the next host information from `handle' as a host name + * in `hostname' (or length `hostlen) + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_krbhst_next_as_string(krb5_context context, + krb5_krbhst_handle handle, + char *hostname, + size_t hostlen) +{ + krb5_error_code ret; + krb5_krbhst_info *host; + ret = krb5_krbhst_next(context, handle, &host); + if(ret) + return ret; + return krb5_krbhst_format_string(context, host, hostname, hostlen); +} + + +void KRB5_LIB_FUNCTION +krb5_krbhst_reset(krb5_context context, krb5_krbhst_handle handle) +{ + handle->index = &handle->hosts; +} + +void KRB5_LIB_FUNCTION +krb5_krbhst_free(krb5_context context, krb5_krbhst_handle handle) +{ + krb5_krbhst_info *h, *next; + + if (handle == NULL) + return; + + for (h = handle->hosts; h != NULL; h = next) { + next = h->next; + _krb5_free_krbhst_info(h); + } + + free(handle->realm); + free(handle); +} + +/* backwards compatibility ahead */ + +static krb5_error_code +gethostlist(krb5_context context, const char *realm, + unsigned int type, char ***hostlist) +{ + krb5_error_code ret; + int nhost = 0; + krb5_krbhst_handle handle; + char host[MAXHOSTNAMELEN]; + krb5_krbhst_info *hostinfo; + + ret = krb5_krbhst_init(context, realm, type, &handle); + if (ret) + return ret; + + while(krb5_krbhst_next(context, handle, &hostinfo) == 0) + nhost++; + if(nhost == 0) { + krb5_set_error_string(context, "No KDC found for realm %s", realm); + return KRB5_KDC_UNREACH; + } + *hostlist = calloc(nhost + 1, sizeof(**hostlist)); + if(*hostlist == NULL) { + krb5_krbhst_free(context, handle); + return ENOMEM; + } + + krb5_krbhst_reset(context, handle); + nhost = 0; + while(krb5_krbhst_next_as_string(context, handle, + host, sizeof(host)) == 0) { + if(((*hostlist)[nhost++] = strdup(host)) == NULL) { + krb5_free_krbhst(context, *hostlist); + krb5_krbhst_free(context, handle); + return ENOMEM; + } + } + (*hostlist)[nhost++] = NULL; + krb5_krbhst_free(context, handle); + return 0; +} + +/* + * return an malloced list of kadmin-hosts for `realm' in `hostlist' + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_krb_admin_hst (krb5_context context, + const krb5_realm *realm, + char ***hostlist) +{ + return gethostlist(context, *realm, KRB5_KRBHST_ADMIN, hostlist); +} + +/* + * return an malloced list of changepw-hosts for `realm' in `hostlist' + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_krb_changepw_hst (krb5_context context, + const krb5_realm *realm, + char ***hostlist) +{ + return gethostlist(context, *realm, KRB5_KRBHST_CHANGEPW, hostlist); +} + +/* + * return an malloced list of 524-hosts for `realm' in `hostlist' + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_krb524hst (krb5_context context, + const krb5_realm *realm, + char ***hostlist) +{ + return gethostlist(context, *realm, KRB5_KRBHST_KRB524, hostlist); +} + + +/* + * return an malloced list of KDC's for `realm' in `hostlist' + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_krbhst (krb5_context context, + const krb5_realm *realm, + char ***hostlist) +{ + return gethostlist(context, *realm, KRB5_KRBHST_KDC, hostlist); +} + +/* + * free all the memory allocated in `hostlist' + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_free_krbhst (krb5_context context, + char **hostlist) +{ + char **p; + + for (p = hostlist; *p; ++p) + free (*p); + free (hostlist); + return 0; +} diff --git a/lib/krb5/kuserok.c b/lib/krb5/kuserok.c new file mode 100644 index 0000000..8f0ff99 --- /dev/null +++ b/lib/krb5/kuserok.c @@ -0,0 +1,262 @@ +/* + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" +#include <dirent.h> + +RCSID("$Id: kuserok.c 16048 2005-09-09 10:33:33Z lha $"); + +/* see if principal is mentioned in the filename access file, return + TRUE (in result) if so, FALSE otherwise */ + +static krb5_error_code +check_one_file(krb5_context context, + const char *filename, + struct passwd *pwd, + krb5_principal principal, + krb5_boolean *result) +{ + FILE *f; + char buf[BUFSIZ]; + krb5_error_code ret; + struct stat st; + + *result = FALSE; + + f = fopen (filename, "r"); + if (f == NULL) + return errno; + + /* check type and mode of file */ + if (fstat(fileno(f), &st) != 0) { + fclose (f); + return errno; + } + if (S_ISDIR(st.st_mode)) { + fclose (f); + return EISDIR; + } + if (st.st_uid != pwd->pw_uid && st.st_uid != 0) { + fclose (f); + return EACCES; + } + if ((st.st_mode & (S_IWGRP | S_IWOTH)) != 0) { + fclose (f); + return EACCES; + } + + while (fgets (buf, sizeof(buf), f) != NULL) { + krb5_principal tmp; + char *newline = buf + strcspn(buf, "\n"); + + if(*newline != '\n') { + int c; + c = fgetc(f); + if(c != EOF) { + while(c != EOF && c != '\n') + c = fgetc(f); + /* line was too long, so ignore it */ + continue; + } + } + *newline = '\0'; + ret = krb5_parse_name (context, buf, &tmp); + if (ret) + continue; + *result = krb5_principal_compare (context, principal, tmp); + krb5_free_principal (context, tmp); + if (*result) { + fclose (f); + return 0; + } + } + fclose (f); + return 0; +} + +static krb5_error_code +check_directory(krb5_context context, + const char *dirname, + struct passwd *pwd, + krb5_principal principal, + krb5_boolean *result) +{ + DIR *d; + struct dirent *dent; + char filename[MAXPATHLEN]; + krb5_error_code ret = 0; + struct stat st; + + *result = FALSE; + + if(lstat(dirname, &st) < 0) + return errno; + + if (!S_ISDIR(st.st_mode)) + return ENOTDIR; + + if (st.st_uid != pwd->pw_uid && st.st_uid != 0) + return EACCES; + if ((st.st_mode & (S_IWGRP | S_IWOTH)) != 0) + return EACCES; + + if((d = opendir(dirname)) == NULL) + return errno; + +#ifdef HAVE_DIRFD + { + int fd; + struct stat st2; + + fd = dirfd(d); + if(fstat(fd, &st2) < 0) { + closedir(d); + return errno; + } + if(st.st_dev != st2.st_dev || st.st_ino != st2.st_ino) { + closedir(d); + return EACCES; + } + } +#endif + + while((dent = readdir(d)) != NULL) { + if(strcmp(dent->d_name, ".") == 0 || + strcmp(dent->d_name, "..") == 0 || + dent->d_name[0] == '#' || /* emacs autosave */ + dent->d_name[strlen(dent->d_name) - 1] == '~') /* emacs backup */ + continue; + snprintf(filename, sizeof(filename), "%s/%s", dirname, dent->d_name); + ret = check_one_file(context, filename, pwd, principal, result); + if(ret == 0 && *result == TRUE) + break; + ret = 0; /* don't propagate errors upstream */ + } + closedir(d); + return ret; +} + +static krb5_boolean +match_local_principals(krb5_context context, + krb5_principal principal, + const char *luser) +{ + krb5_error_code ret; + krb5_realm *realms, *r; + krb5_boolean result = FALSE; + + /* multi-component principals can never match */ + if(krb5_principal_get_comp_string(context, principal, 1) != NULL) + return FALSE; + + ret = krb5_get_default_realms (context, &realms); + if (ret) + return FALSE; + + for (r = realms; *r != NULL; ++r) { + if(strcmp(krb5_principal_get_realm(context, principal), + *r) != 0) + continue; + if(strcmp(krb5_principal_get_comp_string(context, principal, 0), + luser) == 0) { + result = TRUE; + break; + } + } + krb5_free_host_realm (context, realms); + return result; +} + +/** + * Return TRUE iff `principal' is allowed to login as `luser'. + */ + +krb5_boolean KRB5_LIB_FUNCTION +krb5_kuserok (krb5_context context, + krb5_principal principal, + const char *luser) +{ + char *buf; + size_t buflen; + struct passwd *pwd; + krb5_error_code ret; + krb5_boolean result = FALSE; + + krb5_boolean found_file = FALSE; + +#ifdef POSIX_GETPWNAM_R + char pwbuf[2048]; + struct passwd pw; + + if(getpwnam_r(luser, &pw, pwbuf, sizeof(pwbuf), &pwd) != 0) + return FALSE; +#else + pwd = getpwnam (luser); +#endif + if (pwd == NULL) + return FALSE; + +#define KLOGIN "/.k5login" + buflen = strlen(pwd->pw_dir) + sizeof(KLOGIN) + 2; /* 2 for .d */ + buf = malloc(buflen); + if(buf == NULL) + return FALSE; + /* check user's ~/.k5login */ + strlcpy(buf, pwd->pw_dir, buflen); + strlcat(buf, KLOGIN, buflen); + ret = check_one_file(context, buf, pwd, principal, &result); + + if(ret == 0 && result == TRUE) { + free(buf); + return TRUE; + } + + if(ret != ENOENT) + found_file = TRUE; + + strlcat(buf, ".d", buflen); + ret = check_directory(context, buf, pwd, principal, &result); + free(buf); + if(ret == 0 && result == TRUE) + return TRUE; + + if(ret != ENOENT && ret != ENOTDIR) + found_file = TRUE; + + /* finally if no files exist, allow all principals matching + <localuser>@<LOCALREALM> */ + if(found_file == FALSE) + return match_local_principals(context, principal, luser); + + return FALSE; +} diff --git a/lib/krb5/locate_plugin.h b/lib/krb5/locate_plugin.h new file mode 100644 index 0000000..251712c --- /dev/null +++ b/lib/krb5/locate_plugin.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $Id: locate_plugin.h 18998 2006-11-12 19:00:03Z lha $ */ + +#ifndef HEIMDAL_KRB5_LOCATE_PLUGIN_H +#define HEIMDAL_KRB5_LOCATE_PLUGIN_H 1 + +#include <krb5.h> + +enum locate_service_type { + locate_service_kdc = 1, + locate_service_master_kdc, + locate_service_kadmin, + locate_service_krb524, + locate_service_kpasswd +}; + +typedef krb5_error_code +(*krb5plugin_service_locate_lookup) (void *, enum locate_service_type, + const char *, int, int, + int (*)(void *,int,struct sockaddr *), + void *); + + +typedef struct krb5plugin_service_locate_ftable { + int minor_version; + krb5_error_code (*init)(krb5_context, void **); + void (*fini)(void *); + krb5plugin_service_locate_lookup lookup; +} krb5plugin_service_locate_ftable; + +#endif /* HEIMDAL_KRB5_LOCATE_PLUGIN_H */ + diff --git a/lib/krb5/log.c b/lib/krb5/log.c new file mode 100644 index 0000000..c04f50f --- /dev/null +++ b/lib/krb5/log.c @@ -0,0 +1,471 @@ +/* + * Copyright (c) 1997-2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: log.c 19088 2006-11-21 08:08:46Z lha $"); + +struct facility { + int min; + int max; + krb5_log_log_func_t log_func; + krb5_log_close_func_t close_func; + void *data; +}; + +static struct facility* +log_realloc(krb5_log_facility *f) +{ + struct facility *fp; + fp = realloc(f->val, (f->len + 1) * sizeof(*f->val)); + if(fp == NULL) + return NULL; + f->len++; + f->val = fp; + fp += f->len - 1; + return fp; +} + +struct s2i { + const char *s; + int val; +}; + +#define L(X) { #X, LOG_ ## X } + +static struct s2i syslogvals[] = { + L(EMERG), + L(ALERT), + L(CRIT), + L(ERR), + L(WARNING), + L(NOTICE), + L(INFO), + L(DEBUG), + + L(AUTH), +#ifdef LOG_AUTHPRIV + L(AUTHPRIV), +#endif +#ifdef LOG_CRON + L(CRON), +#endif + L(DAEMON), +#ifdef LOG_FTP + L(FTP), +#endif + L(KERN), + L(LPR), + L(MAIL), +#ifdef LOG_NEWS + L(NEWS), +#endif + L(SYSLOG), + L(USER), +#ifdef LOG_UUCP + L(UUCP), +#endif + L(LOCAL0), + L(LOCAL1), + L(LOCAL2), + L(LOCAL3), + L(LOCAL4), + L(LOCAL5), + L(LOCAL6), + L(LOCAL7), + { NULL, -1 } +}; + +static int +find_value(const char *s, struct s2i *table) +{ + while(table->s && strcasecmp(table->s, s)) + table++; + return table->val; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_initlog(krb5_context context, + const char *program, + krb5_log_facility **fac) +{ + krb5_log_facility *f = calloc(1, sizeof(*f)); + if(f == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + f->program = strdup(program); + if(f->program == NULL){ + free(f); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + *fac = f; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_addlog_func(krb5_context context, + krb5_log_facility *fac, + int min, + int max, + krb5_log_log_func_t log_func, + krb5_log_close_func_t close_func, + void *data) +{ + struct facility *fp = log_realloc(fac); + if(fp == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + fp->min = min; + fp->max = max; + fp->log_func = log_func; + fp->close_func = close_func; + fp->data = data; + return 0; +} + + +struct _heimdal_syslog_data{ + int priority; +}; + +static void +log_syslog(const char *timestr, + const char *msg, + void *data) + +{ + struct _heimdal_syslog_data *s = data; + syslog(s->priority, "%s", msg); +} + +static void +close_syslog(void *data) +{ + free(data); + closelog(); +} + +static krb5_error_code +open_syslog(krb5_context context, + krb5_log_facility *facility, int min, int max, + const char *sev, const char *fac) +{ + struct _heimdal_syslog_data *sd = malloc(sizeof(*sd)); + int i; + + if(sd == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + i = find_value(sev, syslogvals); + if(i == -1) + i = LOG_ERR; + sd->priority = i; + i = find_value(fac, syslogvals); + if(i == -1) + i = LOG_AUTH; + sd->priority |= i; + roken_openlog(facility->program, LOG_PID | LOG_NDELAY, i); + return krb5_addlog_func(context, facility, min, max, + log_syslog, close_syslog, sd); +} + +struct file_data{ + const char *filename; + const char *mode; + FILE *fd; + int keep_open; +}; + +static void +log_file(const char *timestr, + const char *msg, + void *data) +{ + struct file_data *f = data; + if(f->keep_open == 0) + f->fd = fopen(f->filename, f->mode); + if(f->fd == NULL) + return; + fprintf(f->fd, "%s %s\n", timestr, msg); + if(f->keep_open == 0) { + fclose(f->fd); + f->fd = NULL; + } +} + +static void +close_file(void *data) +{ + struct file_data *f = data; + if(f->keep_open && f->filename) + fclose(f->fd); + free(data); +} + +static krb5_error_code +open_file(krb5_context context, krb5_log_facility *fac, int min, int max, + const char *filename, const char *mode, FILE *f, int keep_open) +{ + struct file_data *fd = malloc(sizeof(*fd)); + if(fd == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + fd->filename = filename; + fd->mode = mode; + fd->fd = f; + fd->keep_open = keep_open; + + return krb5_addlog_func(context, fac, min, max, log_file, close_file, fd); +} + + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_addlog_dest(krb5_context context, krb5_log_facility *f, const char *orig) +{ + krb5_error_code ret = 0; + int min = 0, max = -1, n; + char c; + const char *p = orig; + + n = sscanf(p, "%d%c%d/", &min, &c, &max); + if(n == 2){ + if(c == '/') { + if(min < 0){ + max = -min; + min = 0; + }else{ + max = min; + } + } + } + if(n){ + p = strchr(p, '/'); + if(p == NULL) { + krb5_set_error_string (context, "failed to parse \"%s\"", orig); + return HEIM_ERR_LOG_PARSE; + } + p++; + } + if(strcmp(p, "STDERR") == 0){ + ret = open_file(context, f, min, max, NULL, NULL, stderr, 1); + }else if(strcmp(p, "CONSOLE") == 0){ + ret = open_file(context, f, min, max, "/dev/console", "w", NULL, 0); + }else if(strncmp(p, "FILE", 4) == 0 && (p[4] == ':' || p[4] == '=')){ + char *fn; + FILE *file = NULL; + int keep_open = 0; + fn = strdup(p + 5); + if(fn == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + if(p[4] == '='){ + int i = open(fn, O_WRONLY | O_CREAT | + O_TRUNC | O_APPEND, 0666); + if(i < 0) { + ret = errno; + krb5_set_error_string (context, "open(%s): %s", fn, + strerror(ret)); + free(fn); + return ret; + } + file = fdopen(i, "a"); + if(file == NULL){ + ret = errno; + close(i); + krb5_set_error_string (context, "fdopen(%s): %s", fn, + strerror(ret)); + free(fn); + return ret; + } + keep_open = 1; + } + ret = open_file(context, f, min, max, fn, "a", file, keep_open); + }else if(strncmp(p, "DEVICE", 6) == 0 && (p[6] == ':' || p[6] == '=')){ + ret = open_file(context, f, min, max, strdup(p + 7), "w", NULL, 0); + }else if(strncmp(p, "SYSLOG", 6) == 0 && (p[6] == '\0' || p[6] == ':')){ + char severity[128] = ""; + char facility[128] = ""; + p += 6; + if(*p != '\0') + p++; + if(strsep_copy(&p, ":", severity, sizeof(severity)) != -1) + strsep_copy(&p, ":", facility, sizeof(facility)); + if(*severity == '\0') + strlcpy(severity, "ERR", sizeof(severity)); + if(*facility == '\0') + strlcpy(facility, "AUTH", sizeof(facility)); + ret = open_syslog(context, f, min, max, severity, facility); + }else{ + krb5_set_error_string (context, "unknown log type: %s", p); + ret = HEIM_ERR_LOG_PARSE; /* XXX */ + } + return ret; +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_openlog(krb5_context context, + const char *program, + krb5_log_facility **fac) +{ + krb5_error_code ret; + char **p, **q; + + ret = krb5_initlog(context, program, fac); + if(ret) + return ret; + + p = krb5_config_get_strings(context, NULL, "logging", program, NULL); + if(p == NULL) + p = krb5_config_get_strings(context, NULL, "logging", "default", NULL); + if(p){ + for(q = p; *q; q++) + ret = krb5_addlog_dest(context, *fac, *q); + krb5_config_free_strings(p); + }else + ret = krb5_addlog_dest(context, *fac, "SYSLOG"); + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_closelog(krb5_context context, + krb5_log_facility *fac) +{ + int i; + for(i = 0; i < fac->len; i++) + (*fac->val[i].close_func)(fac->val[i].data); + free(fac->val); + free(fac->program); + fac->val = NULL; + fac->len = 0; + fac->program = NULL; + free(fac); + return 0; +} + +#undef __attribute__ +#define __attribute__(X) + +krb5_error_code KRB5_LIB_FUNCTION +krb5_vlog_msg(krb5_context context, + krb5_log_facility *fac, + char **reply, + int level, + const char *fmt, + va_list ap) + __attribute__((format (printf, 5, 0))) +{ + + char *msg = NULL; + const char *actual = NULL; + char buf[64]; + time_t t = 0; + int i; + + for(i = 0; fac && i < fac->len; i++) + if(fac->val[i].min <= level && + (fac->val[i].max < 0 || fac->val[i].max >= level)) { + if(t == 0) { + t = time(NULL); + krb5_format_time(context, t, buf, sizeof(buf), TRUE); + } + if(actual == NULL) { + vasprintf(&msg, fmt, ap); + if(msg == NULL) + actual = fmt; + else + actual = msg; + } + (*fac->val[i].log_func)(buf, actual, fac->val[i].data); + } + if(reply == NULL) + free(msg); + else + *reply = msg; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_vlog(krb5_context context, + krb5_log_facility *fac, + int level, + const char *fmt, + va_list ap) + __attribute__((format (printf, 4, 0))) +{ + return krb5_vlog_msg(context, fac, NULL, level, fmt, ap); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_log_msg(krb5_context context, + krb5_log_facility *fac, + int level, + char **reply, + const char *fmt, + ...) + __attribute__((format (printf, 5, 6))) +{ + va_list ap; + krb5_error_code ret; + + va_start(ap, fmt); + ret = krb5_vlog_msg(context, fac, reply, level, fmt, ap); + va_end(ap); + return ret; +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_log(krb5_context context, + krb5_log_facility *fac, + int level, + const char *fmt, + ...) + __attribute__((format (printf, 4, 5))) +{ + va_list ap; + krb5_error_code ret; + + va_start(ap, fmt); + ret = krb5_vlog(context, fac, level, fmt, ap); + va_end(ap); + return ret; +} + diff --git a/lib/krb5/mcache.c b/lib/krb5/mcache.c new file mode 100644 index 0000000..01bcb09 --- /dev/null +++ b/lib/krb5/mcache.c @@ -0,0 +1,477 @@ +/* + * Copyright (c) 1997-2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: mcache.c 22107 2007-12-03 17:22:51Z lha $"); + +typedef struct krb5_mcache { + char *name; + unsigned int refcnt; + int dead; + krb5_principal primary_principal; + struct link { + krb5_creds cred; + struct link *next; + } *creds; + struct krb5_mcache *next; +} krb5_mcache; + +static HEIMDAL_MUTEX mcc_mutex = HEIMDAL_MUTEX_INITIALIZER; +static struct krb5_mcache *mcc_head; + +#define MCACHE(X) ((krb5_mcache *)(X)->data.data) + +#define MISDEAD(X) ((X)->dead) + +static const char* +mcc_get_name(krb5_context context, + krb5_ccache id) +{ + return MCACHE(id)->name; +} + +static krb5_mcache * +mcc_alloc(const char *name) +{ + krb5_mcache *m, *m_c; + + ALLOC(m, 1); + if(m == NULL) + return NULL; + if(name == NULL) + asprintf(&m->name, "%p", m); + else + m->name = strdup(name); + if(m->name == NULL) { + free(m); + return NULL; + } + /* check for dups first */ + HEIMDAL_MUTEX_lock(&mcc_mutex); + for (m_c = mcc_head; m_c != NULL; m_c = m_c->next) + if (strcmp(m->name, m_c->name) == 0) + break; + if (m_c) { + free(m->name); + free(m); + HEIMDAL_MUTEX_unlock(&mcc_mutex); + return NULL; + } + + m->dead = 0; + m->refcnt = 1; + m->primary_principal = NULL; + m->creds = NULL; + m->next = mcc_head; + mcc_head = m; + HEIMDAL_MUTEX_unlock(&mcc_mutex); + return m; +} + +static krb5_error_code +mcc_resolve(krb5_context context, krb5_ccache *id, const char *res) +{ + krb5_mcache *m; + + HEIMDAL_MUTEX_lock(&mcc_mutex); + for (m = mcc_head; m != NULL; m = m->next) + if (strcmp(m->name, res) == 0) + break; + HEIMDAL_MUTEX_unlock(&mcc_mutex); + + if (m != NULL) { + m->refcnt++; + (*id)->data.data = m; + (*id)->data.length = sizeof(*m); + return 0; + } + + m = mcc_alloc(res); + if (m == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return KRB5_CC_NOMEM; + } + + (*id)->data.data = m; + (*id)->data.length = sizeof(*m); + + return 0; +} + + +static krb5_error_code +mcc_gen_new(krb5_context context, krb5_ccache *id) +{ + krb5_mcache *m; + + m = mcc_alloc(NULL); + + if (m == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return KRB5_CC_NOMEM; + } + + (*id)->data.data = m; + (*id)->data.length = sizeof(*m); + + return 0; +} + +static krb5_error_code +mcc_initialize(krb5_context context, + krb5_ccache id, + krb5_principal primary_principal) +{ + krb5_mcache *m = MCACHE(id); + m->dead = 0; + return krb5_copy_principal (context, + primary_principal, + &m->primary_principal); +} + +static int +mcc_close_internal(krb5_mcache *m) +{ + if (--m->refcnt != 0) + return 0; + + if (MISDEAD(m)) { + free (m->name); + return 1; + } + return 0; +} + +static krb5_error_code +mcc_close(krb5_context context, + krb5_ccache id) +{ + if (mcc_close_internal(MCACHE(id))) + krb5_data_free(&id->data); + return 0; +} + +static krb5_error_code +mcc_destroy(krb5_context context, + krb5_ccache id) +{ + krb5_mcache **n, *m = MCACHE(id); + struct link *l; + + if (m->refcnt == 0) + krb5_abortx(context, "mcc_destroy: refcnt already 0"); + + if (!MISDEAD(m)) { + /* if this is an active mcache, remove it from the linked + list, and free all data */ + HEIMDAL_MUTEX_lock(&mcc_mutex); + for(n = &mcc_head; n && *n; n = &(*n)->next) { + if(m == *n) { + *n = m->next; + break; + } + } + HEIMDAL_MUTEX_unlock(&mcc_mutex); + if (m->primary_principal != NULL) { + krb5_free_principal (context, m->primary_principal); + m->primary_principal = NULL; + } + m->dead = 1; + + l = m->creds; + while (l != NULL) { + struct link *old; + + krb5_free_cred_contents (context, &l->cred); + old = l; + l = l->next; + free (old); + } + m->creds = NULL; + } + return 0; +} + +static krb5_error_code +mcc_store_cred(krb5_context context, + krb5_ccache id, + krb5_creds *creds) +{ + krb5_mcache *m = MCACHE(id); + krb5_error_code ret; + struct link *l; + + if (MISDEAD(m)) + return ENOENT; + + l = malloc (sizeof(*l)); + if (l == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return KRB5_CC_NOMEM; + } + l->next = m->creds; + m->creds = l; + memset (&l->cred, 0, sizeof(l->cred)); + ret = krb5_copy_creds_contents (context, creds, &l->cred); + if (ret) { + m->creds = l->next; + free (l); + return ret; + } + return 0; +} + +static krb5_error_code +mcc_get_principal(krb5_context context, + krb5_ccache id, + krb5_principal *principal) +{ + krb5_mcache *m = MCACHE(id); + + if (MISDEAD(m) || m->primary_principal == NULL) + return ENOENT; + return krb5_copy_principal (context, + m->primary_principal, + principal); +} + +static krb5_error_code +mcc_get_first (krb5_context context, + krb5_ccache id, + krb5_cc_cursor *cursor) +{ + krb5_mcache *m = MCACHE(id); + + if (MISDEAD(m)) + return ENOENT; + + *cursor = m->creds; + return 0; +} + +static krb5_error_code +mcc_get_next (krb5_context context, + krb5_ccache id, + krb5_cc_cursor *cursor, + krb5_creds *creds) +{ + krb5_mcache *m = MCACHE(id); + struct link *l; + + if (MISDEAD(m)) + return ENOENT; + + l = *cursor; + if (l != NULL) { + *cursor = l->next; + return krb5_copy_creds_contents (context, + &l->cred, + creds); + } else + return KRB5_CC_END; +} + +static krb5_error_code +mcc_end_get (krb5_context context, + krb5_ccache id, + krb5_cc_cursor *cursor) +{ + return 0; +} + +static krb5_error_code +mcc_remove_cred(krb5_context context, + krb5_ccache id, + krb5_flags which, + krb5_creds *mcreds) +{ + krb5_mcache *m = MCACHE(id); + struct link **q, *p; + for(q = &m->creds, p = *q; p; p = *q) { + if(krb5_compare_creds(context, which, mcreds, &p->cred)) { + *q = p->next; + krb5_free_cred_contents(context, &p->cred); + free(p); + } else + q = &p->next; + } + return 0; +} + +static krb5_error_code +mcc_set_flags(krb5_context context, + krb5_ccache id, + krb5_flags flags) +{ + return 0; /* XXX */ +} + +struct mcache_iter { + krb5_mcache *cache; +}; + +static krb5_error_code +mcc_get_cache_first(krb5_context context, krb5_cc_cursor *cursor) +{ + struct mcache_iter *iter; + + iter = calloc(1, sizeof(*iter)); + if (iter == NULL) { + krb5_set_error_string(context, "malloc - out of memory"); + return ENOMEM; + } + + HEIMDAL_MUTEX_lock(&mcc_mutex); + iter->cache = mcc_head; + if (iter->cache) + iter->cache->refcnt++; + HEIMDAL_MUTEX_unlock(&mcc_mutex); + + *cursor = iter; + return 0; +} + +static krb5_error_code +mcc_get_cache_next(krb5_context context, krb5_cc_cursor cursor, krb5_ccache *id) +{ + struct mcache_iter *iter = cursor; + krb5_error_code ret; + krb5_mcache *m; + + if (iter->cache == NULL) + return KRB5_CC_END; + + HEIMDAL_MUTEX_lock(&mcc_mutex); + m = iter->cache; + if (m->next) + m->next->refcnt++; + iter->cache = m->next; + HEIMDAL_MUTEX_unlock(&mcc_mutex); + + ret = _krb5_cc_allocate(context, &krb5_mcc_ops, id); + if (ret) + return ret; + + (*id)->data.data = m; + (*id)->data.length = sizeof(*m); + + return 0; +} + +static krb5_error_code +mcc_end_cache_get(krb5_context context, krb5_cc_cursor cursor) +{ + struct mcache_iter *iter = cursor; + + if (iter->cache) + mcc_close_internal(iter->cache); + iter->cache = NULL; + free(iter); + return 0; +} + +static krb5_error_code +mcc_move(krb5_context context, krb5_ccache from, krb5_ccache to) +{ + krb5_mcache *mfrom = MCACHE(from), *mto = MCACHE(to); + struct link *creds; + krb5_principal principal; + krb5_mcache **n; + + HEIMDAL_MUTEX_lock(&mcc_mutex); + + /* drop the from cache from the linked list to avoid lookups */ + for(n = &mcc_head; n && *n; n = &(*n)->next) { + if(mfrom == *n) { + *n = mfrom->next; + break; + } + } + + /* swap creds */ + creds = mto->creds; + mto->creds = mfrom->creds; + mfrom->creds = creds; + /* swap principal */ + principal = mto->primary_principal; + mto->primary_principal = mfrom->primary_principal; + mfrom->primary_principal = principal; + + HEIMDAL_MUTEX_unlock(&mcc_mutex); + mcc_destroy(context, from); + + return 0; +} + +static krb5_error_code +mcc_default_name(krb5_context context, char **str) +{ + *str = strdup("MEMORY:"); + if (*str == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + return 0; +} + + +/** + * Variable containing the MEMORY based credential cache implemention. + * + * @ingroup krb5_ccache + */ + +const krb5_cc_ops krb5_mcc_ops = { + "MEMORY", + mcc_get_name, + mcc_resolve, + mcc_gen_new, + mcc_initialize, + mcc_destroy, + mcc_close, + mcc_store_cred, + NULL, /* mcc_retrieve */ + mcc_get_principal, + mcc_get_first, + mcc_get_next, + mcc_end_get, + mcc_remove_cred, + mcc_set_flags, + NULL, + mcc_get_cache_first, + mcc_get_cache_next, + mcc_end_cache_get, + mcc_move, + mcc_default_name +}; diff --git a/lib/krb5/misc.c b/lib/krb5/misc.c new file mode 100644 index 0000000..8050bdb --- /dev/null +++ b/lib/krb5/misc.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) 1997 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: misc.c 21174 2007-06-19 10:10:58Z lha $"); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_s4u2self_to_checksumdata(krb5_context context, + const PA_S4U2Self *self, + krb5_data *data) +{ + krb5_error_code ret; + krb5_ssize_t ssize; + krb5_storage *sp; + size_t size; + int i; + + sp = krb5_storage_emem(); + if (sp == NULL) { + krb5_clear_error_string(context); + return ENOMEM; + } + krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE); + ret = krb5_store_int32(sp, self->name.name_type); + if (ret) + goto out; + for (i = 0; i < self->name.name_string.len; i++) { + size = strlen(self->name.name_string.val[i]); + ssize = krb5_storage_write(sp, self->name.name_string.val[i], size); + if (ssize != size) { + ret = ENOMEM; + goto out; + } + } + size = strlen(self->realm); + ssize = krb5_storage_write(sp, self->realm, size); + if (ssize != size) { + ret = ENOMEM; + goto out; + } + size = strlen(self->auth); + ssize = krb5_storage_write(sp, self->auth, size); + if (ssize != size) { + ret = ENOMEM; + goto out; + } + + ret = krb5_storage_to_data(sp, data); + krb5_storage_free(sp); + return ret; + +out: + krb5_clear_error_string(context); + return ret; +} diff --git a/lib/krb5/mit_glue.c b/lib/krb5/mit_glue.c new file mode 100644 index 0000000..7440d54 --- /dev/null +++ b/lib/krb5/mit_glue.c @@ -0,0 +1,369 @@ +/* + * Copyright (c) 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" +RCSID("$Id: mit_glue.c 20042 2007-01-23 20:37:43Z lha $"); + +/* + * Glue for MIT API + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_make_checksum(krb5_context context, + krb5_cksumtype cksumtype, + const krb5_keyblock *key, + krb5_keyusage usage, + const krb5_data *input, + krb5_checksum *cksum) +{ + krb5_error_code ret; + krb5_crypto crypto; + + ret = krb5_crypto_init(context, key, 0, &crypto); + if (ret) + return ret; + + ret = krb5_create_checksum(context, crypto, usage, cksumtype, + input->data, input->length, cksum); + krb5_crypto_destroy(context, crypto); + + return ret ; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_verify_checksum(krb5_context context, const krb5_keyblock *key, + krb5_keyusage usage, const krb5_data *data, + const krb5_checksum *cksum, krb5_boolean *valid) +{ + krb5_error_code ret; + krb5_checksum data_cksum; + + *valid = 0; + + ret = krb5_c_make_checksum(context, cksum->cksumtype, + key, usage, data, &data_cksum); + if (ret) + return ret; + + if (data_cksum.cksumtype == cksum->cksumtype + && data_cksum.checksum.length == cksum->checksum.length + && memcmp(data_cksum.checksum.data, cksum->checksum.data, cksum->checksum.length) == 0) + *valid = 1; + + krb5_free_checksum_contents(context, &data_cksum); + + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_get_checksum(krb5_context context, const krb5_checksum *cksum, + krb5_cksumtype *type, krb5_data **data) +{ + krb5_error_code ret; + + if (type) + *type = cksum->cksumtype; + if (data) { + *data = malloc(sizeof(**data)); + if (*data == NULL) + return ENOMEM; + + ret = der_copy_octet_string(&cksum->checksum, *data); + if (ret) { + free(*data); + *data = NULL; + return ret; + } + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_set_checksum(krb5_context context, krb5_checksum *cksum, + krb5_cksumtype type, const krb5_data *data) +{ + cksum->cksumtype = type; + return der_copy_octet_string(data, &cksum->checksum); +} + +void KRB5_LIB_FUNCTION +krb5_free_checksum (krb5_context context, krb5_checksum *cksum) +{ + krb5_checksum_free(context, cksum); + free(cksum); +} + +void KRB5_LIB_FUNCTION +krb5_free_checksum_contents(krb5_context context, krb5_checksum *cksum) +{ + krb5_checksum_free(context, cksum); + memset(cksum, 0, sizeof(*cksum)); +} + +void KRB5_LIB_FUNCTION +krb5_checksum_free(krb5_context context, krb5_checksum *cksum) +{ + free_Checksum(cksum); +} + +krb5_boolean KRB5_LIB_FUNCTION +krb5_c_valid_enctype (krb5_enctype etype) +{ + return krb5_enctype_valid(NULL, etype); +} + +krb5_boolean KRB5_LIB_FUNCTION +krb5_c_valid_cksumtype(krb5_cksumtype ctype) +{ + return krb5_cksumtype_valid(NULL, ctype); +} + +krb5_boolean KRB5_LIB_FUNCTION +krb5_c_is_coll_proof_cksum(krb5_cksumtype ctype) +{ + return krb5_checksum_is_collision_proof(NULL, ctype); +} + +krb5_boolean KRB5_LIB_FUNCTION +krb5_c_is_keyed_cksum(krb5_cksumtype ctype) +{ + return krb5_checksum_is_keyed(NULL, ctype); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_checksum (krb5_context context, + const krb5_checksum *old, + krb5_checksum **new) +{ + *new = malloc(sizeof(**new)); + if (*new == NULL) + return ENOMEM; + return copy_Checksum(old, *new); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_checksum_length (krb5_context context, krb5_cksumtype cksumtype, + size_t *length) +{ + return krb5_checksumsize(context, cksumtype, length); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_block_size(krb5_context context, + krb5_enctype enctype, + size_t *blocksize) +{ + krb5_error_code ret; + krb5_crypto crypto; + krb5_keyblock key; + + ret = krb5_generate_random_keyblock(context, enctype, &key); + if (ret) + return ret; + + ret = krb5_crypto_init(context, &key, 0, &crypto); + krb5_free_keyblock_contents(context, &key); + if (ret) + return ret; + ret = krb5_crypto_getblocksize(context, crypto, blocksize); + krb5_crypto_destroy(context, crypto); + + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_decrypt(krb5_context context, + const krb5_keyblock key, + krb5_keyusage usage, + const krb5_data *ivec, + krb5_enc_data *input, + krb5_data *output) +{ + krb5_error_code ret; + krb5_crypto crypto; + + ret = krb5_crypto_init(context, &key, input->enctype, &crypto); + if (ret) + return ret; + + if (ivec) { + size_t blocksize; + + ret = krb5_crypto_getblocksize(context, crypto, &blocksize); + if (ret) { + krb5_crypto_destroy(context, crypto); + return ret; + } + + if (blocksize > ivec->length) { + krb5_crypto_destroy(context, crypto); + return KRB5_BAD_MSIZE; + } + } + + ret = krb5_decrypt_ivec(context, crypto, usage, + input->ciphertext.data, input->ciphertext.length, + output, + ivec ? ivec->data : NULL); + + krb5_crypto_destroy(context, crypto); + + return ret ; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_encrypt(krb5_context context, + const krb5_keyblock *key, + krb5_keyusage usage, + const krb5_data *ivec, + const krb5_data *input, + krb5_enc_data *output) +{ + krb5_error_code ret; + krb5_crypto crypto; + + ret = krb5_crypto_init(context, key, 0, &crypto); + if (ret) + return ret; + + if (ivec) { + size_t blocksize; + + ret = krb5_crypto_getblocksize(context, crypto, &blocksize); + if (ret) { + krb5_crypto_destroy(context, crypto); + return ret; + } + + if (blocksize > ivec->length) { + krb5_crypto_destroy(context, crypto); + return KRB5_BAD_MSIZE; + } + } + + ret = krb5_encrypt_ivec(context, crypto, usage, + input->data, input->length, + &output->ciphertext, + ivec ? ivec->data : NULL); + output->kvno = 0; + krb5_crypto_getenctype(context, crypto, &output->enctype); + + krb5_crypto_destroy(context, crypto); + + return ret ; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_encrypt_length(krb5_context context, + krb5_enctype enctype, + size_t inputlen, + size_t *length) +{ + krb5_error_code ret; + krb5_crypto crypto; + krb5_keyblock key; + + ret = krb5_generate_random_keyblock(context, enctype, &key); + if (ret) + return ret; + + ret = krb5_crypto_init(context, &key, 0, &crypto); + krb5_free_keyblock_contents(context, &key); + if (ret) + return ret; + + *length = krb5_get_wrapped_length(context, crypto, inputlen); + krb5_crypto_destroy(context, crypto); + + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_enctype_compare(krb5_context context, + krb5_enctype e1, + krb5_enctype e2, + krb5_boolean *similar) +{ + *similar = krb5_enctypes_compatible_keys(context, e1, e2); + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_make_random_key(krb5_context context, + krb5_enctype enctype, + krb5_keyblock *random_key) +{ + return krb5_generate_random_keyblock(context, enctype, random_key); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_keylengths(krb5_context context, + krb5_enctype enctype, + size_t *ilen, + size_t *keylen) +{ + krb5_error_code ret; + + ret = krb5_enctype_keybits(context, enctype, ilen); + if (ret) + return ret; + *ilen = (*ilen + 7) / 8; + return krb5_enctype_keysize(context, enctype, keylen); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_prf_length(krb5_context context, + krb5_enctype type, + size_t *length) +{ + return krb5_crypto_prf_length(context, type, length); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_prf(krb5_context context, + const krb5_keyblock *key, + const krb5_data *input, + krb5_data *output) +{ + krb5_crypto crypto; + krb5_error_code ret; + + ret = krb5_crypto_init(context, key, 0, &crypto); + if (ret) + return ret; + + ret = krb5_crypto_prf(context, crypto, input, output); + krb5_crypto_destroy(context, crypto); + + return ret; +} diff --git a/lib/krb5/mk_error.c b/lib/krb5/mk_error.c new file mode 100644 index 0000000..7046649 --- /dev/null +++ b/lib/krb5/mk_error.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: mk_error.c 15457 2005-06-16 21:16:40Z lha $"); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_mk_error(krb5_context context, + krb5_error_code error_code, + const char *e_text, + const krb5_data *e_data, + const krb5_principal client, + const krb5_principal server, + time_t *client_time, + int *client_usec, + krb5_data *reply) +{ + KRB_ERROR msg; + krb5_timestamp sec; + int32_t usec; + size_t len; + krb5_error_code ret = 0; + + krb5_us_timeofday (context, &sec, &usec); + + memset(&msg, 0, sizeof(msg)); + msg.pvno = 5; + msg.msg_type = krb_error; + msg.stime = sec; + msg.susec = usec; + msg.ctime = client_time; + msg.cusec = client_usec; + /* Make sure we only send `protocol' error codes */ + if(error_code < KRB5KDC_ERR_NONE || error_code >= KRB5_ERR_RCSID) { + if(e_text == NULL) + e_text = krb5_get_err_text(context, error_code); + error_code = KRB5KRB_ERR_GENERIC; + } + msg.error_code = error_code - KRB5KDC_ERR_NONE; + if (e_text) + msg.e_text = rk_UNCONST(&e_text); + if (e_data) + msg.e_data = rk_UNCONST(e_data); + if(server){ + msg.realm = server->realm; + msg.sname = server->name; + }else{ + msg.realm = "<unspecified realm>"; + } + if(client){ + msg.crealm = &client->realm; + msg.cname = &client->name; + } + + ASN1_MALLOC_ENCODE(KRB_ERROR, reply->data, reply->length, &msg, &len, ret); + if (ret) + return ret; + if(reply->length != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + return 0; +} diff --git a/lib/krb5/mk_priv.c b/lib/krb5/mk_priv.c new file mode 100644 index 0000000..87e429a --- /dev/null +++ b/lib/krb5/mk_priv.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <krb5_locl.h> + +RCSID("$Id: mk_priv.c 16680 2006-02-01 12:39:26Z lha $"); + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_mk_priv(krb5_context context, + krb5_auth_context auth_context, + const krb5_data *userdata, + krb5_data *outbuf, + krb5_replay_data *outdata) +{ + krb5_error_code ret; + KRB_PRIV s; + EncKrbPrivPart part; + u_char *buf = NULL; + size_t buf_size; + size_t len; + krb5_crypto crypto; + krb5_keyblock *key; + krb5_replay_data rdata; + + if ((auth_context->flags & + (KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE)) && + outdata == NULL) + return KRB5_RC_REQUIRED; /* XXX better error, MIT returns this */ + + if (auth_context->local_subkey) + key = auth_context->local_subkey; + else if (auth_context->remote_subkey) + key = auth_context->remote_subkey; + else + key = auth_context->keyblock; + + memset(&rdata, 0, sizeof(rdata)); + + part.user_data = *userdata; + + krb5_us_timeofday (context, &rdata.timestamp, &rdata.usec); + + if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) { + part.timestamp = &rdata.timestamp; + part.usec = &rdata.usec; + } else { + part.timestamp = NULL; + part.usec = NULL; + } + + if (auth_context->flags & KRB5_AUTH_CONTEXT_RET_TIME) { + outdata->timestamp = rdata.timestamp; + outdata->usec = rdata.usec; + } + + if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) { + rdata.seq = auth_context->local_seqnumber; + part.seq_number = &rdata.seq; + } else + part.seq_number = NULL; + + if (auth_context->flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE) + outdata->seq = auth_context->local_seqnumber; + + part.s_address = auth_context->local_address; + part.r_address = auth_context->remote_address; + + krb5_data_zero (&s.enc_part.cipher); + + ASN1_MALLOC_ENCODE(EncKrbPrivPart, buf, buf_size, &part, &len, ret); + if (ret) + goto fail; + if (buf_size != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + + s.pvno = 5; + s.msg_type = krb_priv; + s.enc_part.etype = key->keytype; + s.enc_part.kvno = NULL; + + ret = krb5_crypto_init(context, key, 0, &crypto); + if (ret) { + free (buf); + return ret; + } + ret = krb5_encrypt (context, + crypto, + KRB5_KU_KRB_PRIV, + buf + buf_size - len, + len, + &s.enc_part.cipher); + krb5_crypto_destroy(context, crypto); + if (ret) { + free(buf); + return ret; + } + free(buf); + + + ASN1_MALLOC_ENCODE(KRB_PRIV, buf, buf_size, &s, &len, ret); + if (ret) + goto fail; + if (buf_size != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + + krb5_data_free (&s.enc_part.cipher); + + ret = krb5_data_copy(outbuf, buf + buf_size - len, len); + if (ret) { + krb5_set_error_string (context, "malloc: out of memory"); + free(buf); + return ENOMEM; + } + free (buf); + if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) + auth_context->local_seqnumber = + (auth_context->local_seqnumber + 1) & 0xFFFFFFFF; + return 0; + + fail: + free (buf); + krb5_data_free (&s.enc_part.cipher); + return ret; +} diff --git a/lib/krb5/mk_rep.c b/lib/krb5/mk_rep.c new file mode 100644 index 0000000..570a837 --- /dev/null +++ b/lib/krb5/mk_rep.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <krb5_locl.h> + +RCSID("$Id: mk_rep.c 13863 2004-05-25 21:46:46Z lha $"); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_mk_rep(krb5_context context, + krb5_auth_context auth_context, + krb5_data *outbuf) +{ + krb5_error_code ret; + AP_REP ap; + EncAPRepPart body; + u_char *buf = NULL; + size_t buf_size; + size_t len; + krb5_crypto crypto; + + ap.pvno = 5; + ap.msg_type = krb_ap_rep; + + memset (&body, 0, sizeof(body)); + + body.ctime = auth_context->authenticator->ctime; + body.cusec = auth_context->authenticator->cusec; + if (auth_context->flags & KRB5_AUTH_CONTEXT_USE_SUBKEY) { + if (auth_context->local_subkey == NULL) { + ret = krb5_auth_con_generatelocalsubkey(context, + auth_context, + auth_context->keyblock); + if(ret) { + krb5_set_error_string (context, + "krb5_mk_rep: generating subkey"); + free_EncAPRepPart(&body); + return ret; + } + } + ret = krb5_copy_keyblock(context, auth_context->local_subkey, + &body.subkey); + if (ret) { + krb5_set_error_string (context, + "krb5_copy_keyblock: out of memory"); + free_EncAPRepPart(&body); + return ENOMEM; + } + } else + body.subkey = NULL; + if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) { + if(auth_context->local_seqnumber == 0) + krb5_generate_seq_number (context, + auth_context->keyblock, + &auth_context->local_seqnumber); + ALLOC(body.seq_number, 1); + if (body.seq_number == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + free_EncAPRepPart(&body); + return ENOMEM; + } + *(body.seq_number) = auth_context->local_seqnumber; + } else + body.seq_number = NULL; + + ap.enc_part.etype = auth_context->keyblock->keytype; + ap.enc_part.kvno = NULL; + + ASN1_MALLOC_ENCODE(EncAPRepPart, buf, buf_size, &body, &len, ret); + free_EncAPRepPart (&body); + if(ret) + return ret; + if (buf_size != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + ret = krb5_crypto_init(context, auth_context->keyblock, + 0 /* ap.enc_part.etype */, &crypto); + if (ret) { + free (buf); + return ret; + } + ret = krb5_encrypt (context, + crypto, + KRB5_KU_AP_REQ_ENC_PART, + buf + buf_size - len, + len, + &ap.enc_part.cipher); + krb5_crypto_destroy(context, crypto); + free(buf); + if (ret) + return ret; + + ASN1_MALLOC_ENCODE(AP_REP, outbuf->data, outbuf->length, &ap, &len, ret); + if (ret == 0 && outbuf->length != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + free_AP_REP (&ap); + return ret; +} diff --git a/lib/krb5/mk_req.c b/lib/krb5/mk_req.c new file mode 100644 index 0000000..5f64f01 --- /dev/null +++ b/lib/krb5/mk_req.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <krb5_locl.h> + +RCSID("$Id: mk_req.c 13863 2004-05-25 21:46:46Z lha $"); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_mk_req_exact(krb5_context context, + krb5_auth_context *auth_context, + const krb5_flags ap_req_options, + const krb5_principal server, + krb5_data *in_data, + krb5_ccache ccache, + krb5_data *outbuf) +{ + krb5_error_code ret; + krb5_creds this_cred, *cred; + + memset(&this_cred, 0, sizeof(this_cred)); + + ret = krb5_cc_get_principal(context, ccache, &this_cred.client); + + if(ret) + return ret; + + ret = krb5_copy_principal (context, server, &this_cred.server); + if (ret) { + krb5_free_cred_contents (context, &this_cred); + return ret; + } + + this_cred.times.endtime = 0; + if (auth_context && *auth_context && (*auth_context)->keytype) + this_cred.session.keytype = (*auth_context)->keytype; + + ret = krb5_get_credentials (context, 0, ccache, &this_cred, &cred); + krb5_free_cred_contents(context, &this_cred); + if (ret) + return ret; + + ret = krb5_mk_req_extended (context, + auth_context, + ap_req_options, + in_data, + cred, + outbuf); + krb5_free_creds(context, cred); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_mk_req(krb5_context context, + krb5_auth_context *auth_context, + const krb5_flags ap_req_options, + const char *service, + const char *hostname, + krb5_data *in_data, + krb5_ccache ccache, + krb5_data *outbuf) +{ + krb5_error_code ret; + char **realms; + char *real_hostname; + krb5_principal server; + + ret = krb5_expand_hostname_realms (context, hostname, + &real_hostname, &realms); + if (ret) + return ret; + + ret = krb5_build_principal (context, &server, + strlen(*realms), + *realms, + service, + real_hostname, + NULL); + free (real_hostname); + krb5_free_host_realm (context, realms); + if (ret) + return ret; + ret = krb5_mk_req_exact (context, auth_context, ap_req_options, + server, in_data, ccache, outbuf); + krb5_free_principal (context, server); + return ret; +} diff --git a/lib/krb5/mk_req_ext.c b/lib/krb5/mk_req_ext.c new file mode 100644 index 0000000..b6d55c8 --- /dev/null +++ b/lib/krb5/mk_req_ext.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <krb5_locl.h> + +RCSID("$Id: mk_req_ext.c 19511 2006-12-27 12:07:22Z lha $"); + +krb5_error_code +_krb5_mk_req_internal(krb5_context context, + krb5_auth_context *auth_context, + const krb5_flags ap_req_options, + krb5_data *in_data, + krb5_creds *in_creds, + krb5_data *outbuf, + krb5_key_usage checksum_usage, + krb5_key_usage encrypt_usage) +{ + krb5_error_code ret; + krb5_data authenticator; + Checksum c; + Checksum *c_opt; + krb5_auth_context ac; + + if(auth_context) { + if(*auth_context == NULL) + ret = krb5_auth_con_init(context, auth_context); + else + ret = 0; + ac = *auth_context; + } else + ret = krb5_auth_con_init(context, &ac); + if(ret) + return ret; + + if(ac->local_subkey == NULL && (ap_req_options & AP_OPTS_USE_SUBKEY)) { + ret = krb5_auth_con_generatelocalsubkey(context, + ac, + &in_creds->session); + if(ret) + goto out; + } + + krb5_free_keyblock(context, ac->keyblock); + ret = krb5_copy_keyblock(context, &in_creds->session, &ac->keyblock); + if (ret) + goto out; + + /* it's unclear what type of checksum we can use. try the best one, except: + * a) if it's configured differently for the current realm, or + * b) if the session key is des-cbc-crc + */ + + if (in_data) { + if(ac->keyblock->keytype == ETYPE_DES_CBC_CRC) { + /* this is to make DCE secd (and older MIT kdcs?) happy */ + ret = krb5_create_checksum(context, + NULL, + 0, + CKSUMTYPE_RSA_MD4, + in_data->data, + in_data->length, + &c); + } else if(ac->keyblock->keytype == ETYPE_ARCFOUR_HMAC_MD5 || + ac->keyblock->keytype == ETYPE_ARCFOUR_HMAC_MD5_56 || + ac->keyblock->keytype == ETYPE_DES_CBC_MD4 || + ac->keyblock->keytype == ETYPE_DES_CBC_MD5) { + /* this is to make MS kdc happy */ + ret = krb5_create_checksum(context, + NULL, + 0, + CKSUMTYPE_RSA_MD5, + in_data->data, + in_data->length, + &c); + } else { + krb5_crypto crypto; + + ret = krb5_crypto_init(context, ac->keyblock, 0, &crypto); + if (ret) + goto out; + ret = krb5_create_checksum(context, + crypto, + checksum_usage, + 0, + in_data->data, + in_data->length, + &c); + krb5_crypto_destroy(context, crypto); + } + c_opt = &c; + } else { + c_opt = NULL; + } + + if (ret) + goto out; + + ret = krb5_build_authenticator (context, + ac, + ac->keyblock->keytype, + in_creds, + c_opt, + NULL, + &authenticator, + encrypt_usage); + if (c_opt) + free_Checksum (c_opt); + if (ret) + goto out; + + ret = krb5_build_ap_req (context, ac->keyblock->keytype, + in_creds, ap_req_options, authenticator, outbuf); +out: + if(auth_context == NULL) + krb5_auth_con_free(context, ac); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_mk_req_extended(krb5_context context, + krb5_auth_context *auth_context, + const krb5_flags ap_req_options, + krb5_data *in_data, + krb5_creds *in_creds, + krb5_data *outbuf) +{ + return _krb5_mk_req_internal (context, + auth_context, + ap_req_options, + in_data, + in_creds, + outbuf, + KRB5_KU_AP_REQ_AUTH_CKSUM, + KRB5_KU_AP_REQ_AUTH); +} diff --git a/lib/krb5/mk_safe.c b/lib/krb5/mk_safe.c new file mode 100644 index 0000000..0b75759 --- /dev/null +++ b/lib/krb5/mk_safe.c @@ -0,0 +1,141 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <krb5_locl.h> + +RCSID("$Id: mk_safe.c 13863 2004-05-25 21:46:46Z lha $"); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_mk_safe(krb5_context context, + krb5_auth_context auth_context, + const krb5_data *userdata, + krb5_data *outbuf, + krb5_replay_data *outdata) +{ + krb5_error_code ret; + KRB_SAFE s; + u_char *buf = NULL; + size_t buf_size; + size_t len; + krb5_crypto crypto; + krb5_keyblock *key; + krb5_replay_data rdata; + + if ((auth_context->flags & + (KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE)) && + outdata == NULL) + return KRB5_RC_REQUIRED; /* XXX better error, MIT returns this */ + + if (auth_context->local_subkey) + key = auth_context->local_subkey; + else if (auth_context->remote_subkey) + key = auth_context->remote_subkey; + else + key = auth_context->keyblock; + + s.pvno = 5; + s.msg_type = krb_safe; + + memset(&rdata, 0, sizeof(rdata)); + + s.safe_body.user_data = *userdata; + + krb5_us_timeofday (context, &rdata.timestamp, &rdata.usec); + + if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) { + s.safe_body.timestamp = &rdata.timestamp; + s.safe_body.usec = &rdata.usec; + } else { + s.safe_body.timestamp = NULL; + s.safe_body.usec = NULL; + } + + if (auth_context->flags & KRB5_AUTH_CONTEXT_RET_TIME) { + outdata->timestamp = rdata.timestamp; + outdata->usec = rdata.usec; + } + + if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) { + rdata.seq = auth_context->local_seqnumber; + s.safe_body.seq_number = &rdata.seq; + } else + s.safe_body.seq_number = NULL; + + if (auth_context->flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE) + outdata->seq = auth_context->local_seqnumber; + + s.safe_body.s_address = auth_context->local_address; + s.safe_body.r_address = auth_context->remote_address; + + s.cksum.cksumtype = 0; + s.cksum.checksum.data = NULL; + s.cksum.checksum.length = 0; + + ASN1_MALLOC_ENCODE(KRB_SAFE, buf, buf_size, &s, &len, ret); + if (ret) + return ret; + if(buf_size != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + ret = krb5_crypto_init(context, key, 0, &crypto); + if (ret) { + free (buf); + return ret; + } + ret = krb5_create_checksum(context, + crypto, + KRB5_KU_KRB_SAFE_CKSUM, + 0, + buf, + len, + &s.cksum); + krb5_crypto_destroy(context, crypto); + if (ret) { + free (buf); + return ret; + } + + free(buf); + ASN1_MALLOC_ENCODE(KRB_SAFE, buf, buf_size, &s, &len, ret); + free_Checksum (&s.cksum); + if(ret) + return ret; + if(buf_size != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + + outbuf->length = len; + outbuf->data = buf; + if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) + auth_context->local_seqnumber = + (auth_context->local_seqnumber + 1) & 0xFFFFFFFF; + return 0; +} diff --git a/lib/krb5/n-fold-test.c b/lib/krb5/n-fold-test.c new file mode 100644 index 0000000..248e232 --- /dev/null +++ b/lib/krb5/n-fold-test.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 1999 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include "krb5_locl.h" + +RCSID("$Id: n-fold-test.c 21745 2007-07-31 16:11:25Z lha $"); + +enum { MAXSIZE = 24 }; + +static struct testcase { + const char *str; + unsigned n; + unsigned char res[MAXSIZE]; +} tests[] = { + {"012345", 8, + {0xbe, 0x07, 0x26, 0x31, 0x27, 0x6b, 0x19, 0x55} + }, + {"basch", 24, + {0x1a, 0xab, 0x6b, 0x42, 0x96, 0x4b, 0x98, 0xb2, 0x1f, 0x8c, 0xde, + 0x2d, 0x24, 0x48, 0xba, 0x34, 0x55, 0xd7, 0x86, 0x2c, 0x97, 0x31, + 0x64, 0x3f} + }, + {"eichin", 24, + {0x65, 0x69, 0x63, 0x68, 0x69, 0x6e, 0x4b, 0x73, 0x2b, 0x4b, + 0x1b, 0x43, 0xda, 0x1a, 0x5b, 0x99, 0x5a, 0x58, 0xd2, 0xc6, 0xd0, + 0xd2, 0xdc, 0xca} + }, + {"sommerfeld", 24, + {0x2f, 0x7a, 0x98, 0x55, 0x7c, 0x6e, 0xe4, 0xab, 0xad, 0xf4, + 0xe7, 0x11, 0x92, 0xdd, 0x44, 0x2b, 0xd4, 0xff, 0x53, 0x25, 0xa5, + 0xde, 0xf7, 0x5c} + }, + {"MASSACHVSETTS INSTITVTE OF TECHNOLOGY", 24, + {0xdb, 0x3b, 0x0d, 0x8f, 0x0b, 0x06, 0x1e, 0x60, 0x32, 0x82, + 0xb3, 0x08, 0xa5, 0x08, 0x41, 0x22, 0x9a, 0xd7, 0x98, 0xfa, 0xb9, + 0x54, 0x0c, 0x1b} + }, + {"assar@NADA.KTH.SE", 24, + {0x5c, 0x06, 0xc3, 0x4d, 0x2c, 0x89, 0x05, 0xbe, 0x7a, 0x51, + 0x83, 0x6c, 0xd6, 0xf8, 0x1c, 0x4b, 0x7a, 0x93, 0x49, 0x16, 0x5a, + 0xb3, 0xfa, 0xa9} + }, + {"testKRBTEST.MIT.EDUtestkey", 24, + {0x50, 0x2c, 0xf8, 0x29, 0x78, 0xe5, 0xfb, 0x1a, 0x29, 0x06, + 0xbd, 0x22, 0x28, 0x91, 0x56, 0xc0, 0x06, 0xa0, 0xdc, 0xf5, 0xb6, + 0xc2, 0xda, 0x6c} + }, + {"password", 7, + {0x78, 0xa0, 0x7b, 0x6c, 0xaf, 0x85, 0xfa} + }, + {"Rough Consensus, and Running Code", 8, + {0xbb, 0x6e, 0xd3, 0x08, 0x70, 0xb7, 0xf0, 0xe0}, + }, + {"password", 21, + {0x59, 0xe4, 0xa8, 0xca, 0x7c, 0x03, 0x85, 0xc3, 0xc3, 0x7b, 0x3f, + 0x6d, 0x20, 0x00, 0x24, 0x7c, 0xb6, 0xe6, 0xbd, 0x5b, 0x3e}, + }, + {"MASSACHVSETTS INSTITVTE OF TECHNOLOGY", 24, + {0xdb, 0x3b, 0x0d, 0x8f, 0x0b, 0x06, 0x1e, 0x60, 0x32, 0x82, 0xb3, + 0x08, 0xa5, 0x08, 0x41, 0x22, 0x9a, 0xd7, 0x98, 0xfa, 0xb9, 0x54, + 0x0c, 0x1b} + }, + {NULL, 0} +}; + +int +main(int argc, char **argv) +{ + unsigned char data[MAXSIZE]; + struct testcase *t; + int ret = 0; + + for (t = tests; t->str; ++t) { + int i; + + ret = _krb5_n_fold (t->str, strlen(t->str), data, t->n); + if (ret) + errx(1, "out of memory"); + if (memcmp (data, t->res, t->n) != 0) { + printf ("n-fold(\"%s\", %d) failed\n", t->str, t->n); + printf ("should be: "); + for (i = 0; i < t->n; ++i) + printf ("%02x", t->res[i]); + printf ("\nresult was: "); + for (i = 0; i < t->n; ++i) + printf ("%02x", data[i]); + printf ("\n"); + ret = 1; + } + } + return ret; +} diff --git a/lib/krb5/n-fold.c b/lib/krb5/n-fold.c new file mode 100644 index 0000000..53528cf --- /dev/null +++ b/lib/krb5/n-fold.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include "krb5_locl.h" + +RCSID("$Id: n-fold.c 22190 2007-12-06 16:24:22Z lha $"); + +static krb5_error_code +rr13(unsigned char *buf, size_t len) +{ + unsigned char *tmp; + int bytes = (len + 7) / 8; + int i; + if(len == 0) + return 0; + { + const int bits = 13 % len; + const int lbit = len % 8; + + tmp = malloc(bytes); + if (tmp == NULL) + return ENOMEM; + memcpy(tmp, buf, bytes); + if(lbit) { + /* pad final byte with inital bits */ + tmp[bytes - 1] &= 0xff << (8 - lbit); + for(i = lbit; i < 8; i += len) + tmp[bytes - 1] |= buf[0] >> i; + } + for(i = 0; i < bytes; i++) { + int bb; + int b1, s1, b2, s2; + /* calculate first bit position of this byte */ + bb = 8 * i - bits; + while(bb < 0) + bb += len; + /* byte offset and shift count */ + b1 = bb / 8; + s1 = bb % 8; + + if(bb + 8 > bytes * 8) + /* watch for wraparound */ + s2 = (len + 8 - s1) % 8; + else + s2 = 8 - s1; + b2 = (b1 + 1) % bytes; + buf[i] = (tmp[b1] << s1) | (tmp[b2] >> s2); + } + free(tmp); + } + return 0; +} + +/* Add `b' to `a', both being one's complement numbers. */ +static void +add1(unsigned char *a, unsigned char *b, size_t len) +{ + int i; + int carry = 0; + for(i = len - 1; i >= 0; i--){ + int x = a[i] + b[i] + carry; + carry = x > 0xff; + a[i] = x & 0xff; + } + for(i = len - 1; carry && i >= 0; i--){ + int x = a[i] + carry; + carry = x > 0xff; + a[i] = x & 0xff; + } +} + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_n_fold(const void *str, size_t len, void *key, size_t size) +{ + /* if len < size we need at most N * len bytes, ie < 2 * size; + if len > size we need at most 2 * len */ + krb5_error_code ret = 0; + size_t maxlen = 2 * max(size, len); + size_t l = 0; + unsigned char *tmp = malloc(maxlen); + unsigned char *buf = malloc(len); + + if (tmp == NULL || buf == NULL) + return ENOMEM; + + memcpy(buf, str, len); + memset(key, 0, size); + do { + memcpy(tmp + l, buf, len); + l += len; + ret = rr13(buf, len * 8); + if (ret) + goto out; + while(l >= size) { + add1(key, tmp, size); + l -= size; + if(l == 0) + break; + memmove(tmp, tmp + size, l); + } + } while(l != 0); +out: + memset(buf, 0, len); + free(buf); + memset(tmp, 0, maxlen); + free(tmp); + return ret; +} diff --git a/lib/krb5/name-45-test.c b/lib/krb5/name-45-test.c new file mode 100644 index 0000000..0bb05f5 --- /dev/null +++ b/lib/krb5/name-45-test.c @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2002 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include "krb5_locl.h" +#include <err.h> + +RCSID("$Id: name-45-test.c 19763 2007-01-08 13:35:49Z lha $"); + +enum { MAX_COMPONENTS = 3 }; + +static struct testcase { + const char *v4_name; + const char *v4_inst; + const char *v4_realm; + + krb5_realm v5_realm; + unsigned ncomponents; + char *comp_val[MAX_COMPONENTS]; + + const char *config_file; + krb5_error_code ret; /* expected error code from 524 */ + + krb5_error_code ret2; /* expected error code from 425 */ +} tests[] = { + {"", "", "", "", 1, {""}, NULL, 0, 0}, + {"a", "", "", "", 1, {"a"}, NULL, 0, 0}, + {"a", "b", "", "", 2, {"a", "b"}, NULL, 0, 0}, + {"a", "b", "c", "c", 2, {"a", "b"}, NULL, 0, 0}, + + {"krbtgt", "FOO.SE", "FOO.SE", "FOO.SE", 2, + {"krbtgt", "FOO.SE"}, NULL, 0, 0}, + + {"foo", "bar2", "BAZ", "BAZ", 2, + {"foo", "bar2"}, NULL, 0, 0}, + {"foo", "bar2", "BAZ", "BAZ", 2, + {"foo", "bar2"}, + "[libdefaults]\n" + " v4_name_convert = {\n" + " host = {\n" + " foo = foo5\n" + " }\n" + "}\n", + HEIM_ERR_V4_PRINC_NO_CONV, 0}, + {"foo", "bar2", "BAZ", "BAZ", 2, + {"foo5", "bar2.baz"}, + "[realms]\n" + " BAZ = {\n" + " v4_name_convert = {\n" + " host = {\n" + " foo = foo5\n" + " }\n" + " }\n" + " v4_instance_convert = {\n" + " bar2 = bar2.baz\n" + " }\n" + " }\n", + 0, 0}, + + {"rcmd", "foo", "realm", "realm", 2, {"host", "foo"}, NULL, + HEIM_ERR_V4_PRINC_NO_CONV, 0}, + {"rcmd", "foo", "realm", "realm", 2, {"host", "foo.realm"}, + "[realms]\n" + " realm = {\n" + " v4_instance_convert = {\n" + " foo = foo.realm\n" + " }\n" + " }\n", + 0, 0}, + + {"pop", "mail0", "NADA.KTH.SE", "NADA.KTH.SE", 2, + {"pop", "mail0.nada.kth.se"}, "", HEIM_ERR_V4_PRINC_NO_CONV, 0}, + {"pop", "mail0", "NADA.KTH.SE", "NADA.KTH.SE", 2, + {"pop", "mail0.nada.kth.se"}, + "[realms]\n" + " NADA.KTH.SE = {\n" + " default_domain = nada.kth.se\n" + " }\n", + 0, 0}, + {"pop", "mail0", "NADA.KTH.SE", "NADA.KTH.SE", 2, + {"pop", "mail0.nada.kth.se"}, + "[libdefaults]\n" + " v4_instance_resolve = true\n", + HEIM_ERR_V4_PRINC_NO_CONV, 0}, + + {"rcmd", "hokkigai", "NADA.KTH.SE", "NADA.KTH.SE", 2, + {"host", "hokkigai.pdc.kth.se"}, "", HEIM_ERR_V4_PRINC_NO_CONV, 0}, + {"rcmd", "hokkigai", "NADA.KTH.SE", "NADA.KTH.SE", 2, + {"host", "hokkigai.pdc.kth.se"}, + "[libdefaults]\n" + " v4_instance_resolve = true\n" + "[realms]\n" + " NADA.KTH.SE = {\n" + " v4_name_convert = {\n" + " host = {\n" + " rcmd = host\n" + " }\n" + " }\n" + " default_domain = pdc.kth.se\n" + " }\n", + 0, 0}, + + {"0123456789012345678901234567890123456789", + "0123456789012345678901234567890123456789", + "0123456789012345678901234567890123456789", + "0123456789012345678901234567890123456789", + 2, {"0123456789012345678901234567890123456789", + "0123456789012345678901234567890123456789"}, NULL, + 0, KRB5_PARSE_MALFORMED}, + + {"012345678901234567890123456789012345678", + "012345678901234567890123456789012345678", + "012345678901234567890123456789012345678", + "012345678901234567890123456789012345678", + 2, {"012345678901234567890123456789012345678", + "012345678901234567890123456789012345678"}, NULL, + 0, 0}, + + {NULL, NULL, NULL, NULL, 0, {NULL}, NULL, 0} +}; + +int +main(int argc, char **argv) +{ + struct testcase *t; + krb5_context context; + krb5_error_code ret; + char hostname[1024]; + int val = 0; + + setprogname(argv[0]); + + gethostname(hostname, sizeof(hostname)); + if (!(strstr(hostname, "kth.se") != NULL || strstr(hostname, "su.se") != NULL)) + return 0; + + for (t = tests; t->v4_name; ++t) { + krb5_principal princ; + int i; + char name[40], inst[40], realm[40]; + char printable_princ[256]; + + ret = krb5_init_context (&context); + if (ret) + errx (1, "krb5_init_context failed: %d", ret); + + if (t->config_file != NULL) { + char template[] = "/tmp/krb5-conf-XXXXXX"; + int fd = mkstemp(template); + char *files[2]; + + if (fd < 0) + krb5_err (context, 1, errno, "mkstemp %s", template); + + if (write (fd, t->config_file, strlen(t->config_file)) + != strlen(t->config_file)) + krb5_err (context, 1, errno, "write %s", template); + close (fd); + files[0] = template; + files[1] = NULL; + + ret = krb5_set_config_files (context, files); + unlink (template); + if (ret) + krb5_err (context, 1, ret, "krb5_set_config_files"); + } + + ret = krb5_425_conv_principal (context, + t->v4_name, + t->v4_inst, + t->v4_realm, + &princ); + if (ret) { + if (ret != t->ret) { + krb5_warn (context, ret, + "krb5_425_conv_principal %s.%s@%s", + t->v4_name, t->v4_inst, t->v4_realm); + val = 1; + } + } else { + if (t->ret) { + char *s; + krb5_unparse_name(context, princ, &s); + krb5_warnx (context, + "krb5_425_conv_principal %s.%s@%s " + "passed unexpected: %s", + t->v4_name, t->v4_inst, t->v4_realm, s); + free(s); + val = 1; + krb5_free_context(context); + continue; + } + } + + if (ret) { + krb5_free_context(context); + continue; + } + + if (strcmp (t->v5_realm, princ->realm) != 0) { + printf ("wrong realm (\"%s\" should be \"%s\")" + " for \"%s.%s@%s\"\n", + princ->realm, t->v5_realm, + t->v4_name, + t->v4_inst, + t->v4_realm); + val = 1; + } + + if (t->ncomponents != princ->name.name_string.len) { + printf ("wrong number of components (%u should be %u)" + " for \"%s.%s@%s\"\n", + princ->name.name_string.len, t->ncomponents, + t->v4_name, + t->v4_inst, + t->v4_realm); + val = 1; + } else { + for (i = 0; i < t->ncomponents; ++i) { + if (strcmp(t->comp_val[i], + princ->name.name_string.val[i]) != 0) { + printf ("bad component %d (\"%s\" should be \"%s\")" + " for \"%s.%s@%s\"\n", + i, + princ->name.name_string.val[i], + t->comp_val[i], + t->v4_name, + t->v4_inst, + t->v4_realm); + val = 1; + } + } + } + ret = krb5_524_conv_principal (context, princ, + name, inst, realm); + if (krb5_unparse_name_fixed(context, princ, + printable_princ, sizeof(printable_princ))) + strlcpy(printable_princ, "unknown principal", + sizeof(printable_princ)); + if (ret) { + if (ret != t->ret2) { + krb5_warn (context, ret, + "krb5_524_conv_principal %s", printable_princ); + val = 1; + } + } else { + if (t->ret2) { + krb5_warnx (context, + "krb5_524_conv_principal %s " + "passed unexpected", printable_princ); + val = 1; + krb5_free_context(context); + continue; + } + } + if (ret) { + krb5_free_principal (context, princ); + krb5_free_context(context); + continue; + } + + krb5_free_principal (context, princ); + krb5_free_context(context); + } + return val; +} diff --git a/lib/krb5/net_read.c b/lib/krb5/net_read.c new file mode 100644 index 0000000..f0fa2ce --- /dev/null +++ b/lib/krb5/net_read.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 1997, 1998, 2002 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: net_read.c 13863 2004-05-25 21:46:46Z lha $"); + +krb5_ssize_t KRB5_LIB_FUNCTION +krb5_net_read (krb5_context context, + void *p_fd, + void *buf, + size_t len) +{ + int fd = *((int *)p_fd); + + return net_read (fd, buf, len); +} diff --git a/lib/krb5/net_write.c b/lib/krb5/net_write.c new file mode 100644 index 0000000..868015f --- /dev/null +++ b/lib/krb5/net_write.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 1997, 1998 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: net_write.c 13863 2004-05-25 21:46:46Z lha $"); + +krb5_ssize_t KRB5_LIB_FUNCTION +krb5_net_write (krb5_context context, + void *p_fd, + const void *buf, + size_t len) +{ + int fd = *((int *)p_fd); + + return net_write (fd, buf, len); +} + +krb5_ssize_t KRB5_LIB_FUNCTION +krb5_net_write_block(krb5_context context, + void *p_fd, + const void *buf, + size_t len, + time_t timeout) +{ + int fd = *((int *)p_fd); + int ret; + struct timeval tv, *tvp; + const char *cbuf = (const char *)buf; + size_t rem = len; + ssize_t count; + fd_set wfds; + + do { + FD_ZERO(&wfds); + FD_SET(fd, &wfds); + + if (timeout != 0) { + tv.tv_sec = timeout; + tv.tv_usec = 0; + tvp = &tv; + } else + tvp = NULL; + + ret = select(fd + 1, NULL, &wfds, NULL, tvp); + if (ret < 0) { + if (errno == EINTR) + continue; + return -1; + } else if (ret == 0) + return 0; + + if (!FD_ISSET(fd, &wfds)) { + errno = ETIMEDOUT; + return -1; + } + +#ifdef WIN32 + count = send (fd, cbuf, rem, 0); +#else + count = write (fd, cbuf, rem); +#endif + if (count < 0) { + if (errno == EINTR) + continue; + else + return count; + } + cbuf += count; + rem -= count; + + } while (rem > 0); + + return len; +} diff --git a/lib/krb5/pac.c b/lib/krb5/pac.c new file mode 100644 index 0000000..1b21750 --- /dev/null +++ b/lib/krb5/pac.c @@ -0,0 +1,1041 @@ +/* + * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: pac.c 21934 2007-08-27 14:21:04Z lha $"); + +struct PAC_INFO_BUFFER { + uint32_t type; + uint32_t buffersize; + uint32_t offset_hi; + uint32_t offset_lo; +}; + +struct PACTYPE { + uint32_t numbuffers; + uint32_t version; + struct PAC_INFO_BUFFER buffers[1]; +}; + +struct krb5_pac_data { + struct PACTYPE *pac; + krb5_data data; + struct PAC_INFO_BUFFER *server_checksum; + struct PAC_INFO_BUFFER *privsvr_checksum; + struct PAC_INFO_BUFFER *logon_name; +}; + +#define PAC_ALIGNMENT 8 + +#define PACTYPE_SIZE 8 +#define PAC_INFO_BUFFER_SIZE 16 + +#define PAC_SERVER_CHECKSUM 6 +#define PAC_PRIVSVR_CHECKSUM 7 +#define PAC_LOGON_NAME 10 +#define PAC_CONSTRAINED_DELEGATION 11 + +#define CHECK(r,f,l) \ + do { \ + if (((r) = f ) != 0) { \ + krb5_clear_error_string(context); \ + goto l; \ + } \ + } while(0) + +static const char zeros[PAC_ALIGNMENT] = { 0 }; + +/* + * + */ + +krb5_error_code +krb5_pac_parse(krb5_context context, const void *ptr, size_t len, + krb5_pac *pac) +{ + krb5_error_code ret; + krb5_pac p; + krb5_storage *sp = NULL; + uint32_t i, tmp, tmp2, header_end; + + p = calloc(1, sizeof(*p)); + if (p == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "out of memory"); + goto out; + } + + sp = krb5_storage_from_readonly_mem(ptr, len); + if (sp == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "out of memory"); + goto out; + } + krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE); + + CHECK(ret, krb5_ret_uint32(sp, &tmp), out); + CHECK(ret, krb5_ret_uint32(sp, &tmp2), out); + if (tmp < 1) { + krb5_set_error_string(context, "PAC have too few buffer"); + ret = EINVAL; /* Too few buffers */ + goto out; + } + if (tmp2 != 0) { + krb5_set_error_string(context, "PAC have wrong version"); + ret = EINVAL; /* Wrong version */ + goto out; + } + + p->pac = calloc(1, + sizeof(*p->pac) + (sizeof(p->pac->buffers[0]) * (tmp - 1))); + if (p->pac == NULL) { + krb5_set_error_string(context, "out of memory"); + ret = ENOMEM; + goto out; + } + + p->pac->numbuffers = tmp; + p->pac->version = tmp2; + + header_end = PACTYPE_SIZE + (PAC_INFO_BUFFER_SIZE * p->pac->numbuffers); + if (header_end > len) { + ret = EINVAL; + goto out; + } + + for (i = 0; i < p->pac->numbuffers; i++) { + CHECK(ret, krb5_ret_uint32(sp, &p->pac->buffers[i].type), out); + CHECK(ret, krb5_ret_uint32(sp, &p->pac->buffers[i].buffersize), out); + CHECK(ret, krb5_ret_uint32(sp, &p->pac->buffers[i].offset_lo), out); + CHECK(ret, krb5_ret_uint32(sp, &p->pac->buffers[i].offset_hi), out); + + /* consistency checks */ + if (p->pac->buffers[i].offset_lo & (PAC_ALIGNMENT - 1)) { + krb5_set_error_string(context, "PAC out of allignment"); + ret = EINVAL; + goto out; + } + if (p->pac->buffers[i].offset_hi) { + krb5_set_error_string(context, "PAC high offset set"); + ret = EINVAL; + goto out; + } + if (p->pac->buffers[i].offset_lo > len) { + krb5_set_error_string(context, "PAC offset off end"); + ret = EINVAL; + goto out; + } + if (p->pac->buffers[i].offset_lo < header_end) { + krb5_set_error_string(context, "PAC offset inside header: %d %d", + p->pac->buffers[i].offset_lo, header_end); + ret = EINVAL; + goto out; + } + if (p->pac->buffers[i].buffersize > len - p->pac->buffers[i].offset_lo){ + krb5_set_error_string(context, "PAC length off end"); + ret = EINVAL; + goto out; + } + + /* let save pointer to data we need later */ + if (p->pac->buffers[i].type == PAC_SERVER_CHECKSUM) { + if (p->server_checksum) { + krb5_set_error_string(context, "PAC have two server checksums"); + ret = EINVAL; + goto out; + } + p->server_checksum = &p->pac->buffers[i]; + } else if (p->pac->buffers[i].type == PAC_PRIVSVR_CHECKSUM) { + if (p->privsvr_checksum) { + krb5_set_error_string(context, "PAC have two KDC checksums"); + ret = EINVAL; + goto out; + } + p->privsvr_checksum = &p->pac->buffers[i]; + } else if (p->pac->buffers[i].type == PAC_LOGON_NAME) { + if (p->logon_name) { + krb5_set_error_string(context, "PAC have two logon names"); + ret = EINVAL; + goto out; + } + p->logon_name = &p->pac->buffers[i]; + } + } + + ret = krb5_data_copy(&p->data, ptr, len); + if (ret) + goto out; + + krb5_storage_free(sp); + + *pac = p; + return 0; + +out: + if (sp) + krb5_storage_free(sp); + if (p) { + if (p->pac) + free(p->pac); + free(p); + } + *pac = NULL; + + return ret; +} + +krb5_error_code +krb5_pac_init(krb5_context context, krb5_pac *pac) +{ + krb5_error_code ret; + krb5_pac p; + + p = calloc(1, sizeof(*p)); + if (p == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + + p->pac = calloc(1, sizeof(*p->pac)); + if (p->pac == NULL) { + free(p); + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + + ret = krb5_data_alloc(&p->data, PACTYPE_SIZE); + if (ret) { + free (p->pac); + free(p); + krb5_set_error_string(context, "out of memory"); + return ret; + } + + + *pac = p; + return 0; +} + +krb5_error_code +krb5_pac_add_buffer(krb5_context context, krb5_pac p, + uint32_t type, const krb5_data *data) +{ + krb5_error_code ret; + void *ptr; + size_t len, offset, header_end, old_end; + uint32_t i; + + len = p->pac->numbuffers; + + ptr = realloc(p->pac, + sizeof(*p->pac) + (sizeof(p->pac->buffers[0]) * len)); + if (ptr == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + p->pac = ptr; + + for (i = 0; i < len; i++) + p->pac->buffers[i].offset_lo += PAC_INFO_BUFFER_SIZE; + + offset = p->data.length + PAC_INFO_BUFFER_SIZE; + + p->pac->buffers[len].type = type; + p->pac->buffers[len].buffersize = data->length; + p->pac->buffers[len].offset_lo = offset; + p->pac->buffers[len].offset_hi = 0; + + old_end = p->data.length; + len = p->data.length + data->length + PAC_INFO_BUFFER_SIZE; + if (len < p->data.length) { + krb5_set_error_string(context, "integer overrun"); + return EINVAL; + } + + /* align to PAC_ALIGNMENT */ + len = ((len + PAC_ALIGNMENT - 1) / PAC_ALIGNMENT) * PAC_ALIGNMENT; + + ret = krb5_data_realloc(&p->data, len); + if (ret) { + krb5_set_error_string(context, "out of memory"); + return ret; + } + + /* + * make place for new PAC INFO BUFFER header + */ + header_end = PACTYPE_SIZE + (PAC_INFO_BUFFER_SIZE * p->pac->numbuffers); + memmove((unsigned char *)p->data.data + header_end + PAC_INFO_BUFFER_SIZE, + (unsigned char *)p->data.data + header_end , + old_end - header_end); + memset((unsigned char *)p->data.data + header_end, 0, PAC_INFO_BUFFER_SIZE); + + /* + * copy in new data part + */ + + memcpy((unsigned char *)p->data.data + offset, + data->data, data->length); + memset((unsigned char *)p->data.data + offset + data->length, + 0, p->data.length - offset - data->length); + + p->pac->numbuffers += 1; + + return 0; +} + +krb5_error_code +krb5_pac_get_buffer(krb5_context context, krb5_pac p, + uint32_t type, krb5_data *data) +{ + krb5_error_code ret; + uint32_t i; + + /* + * Hide the checksums from external consumers + */ + + if (type == PAC_PRIVSVR_CHECKSUM || type == PAC_SERVER_CHECKSUM) { + ret = krb5_data_alloc(data, 16); + if (ret) { + krb5_set_error_string(context, "out of memory"); + return ret; + } + memset(data->data, 0, data->length); + return 0; + } + + for (i = 0; i < p->pac->numbuffers; i++) { + size_t len = p->pac->buffers[i].buffersize; + size_t offset = p->pac->buffers[i].offset_lo; + + if (p->pac->buffers[i].type != type) + continue; + + ret = krb5_data_copy(data, (unsigned char *)p->data.data + offset, len); + if (ret) { + krb5_set_error_string(context, "Out of memory"); + return ret; + } + return 0; + } + krb5_set_error_string(context, "No PAC buffer of type %lu was found", + (unsigned long)type); + return ENOENT; +} + +/* + * + */ + +krb5_error_code +krb5_pac_get_types(krb5_context context, + krb5_pac p, + size_t *len, + uint32_t **types) +{ + size_t i; + + *types = calloc(p->pac->numbuffers, sizeof(*types)); + if (*types == NULL) { + *len = 0; + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + for (i = 0; i < p->pac->numbuffers; i++) + (*types)[i] = p->pac->buffers[i].type; + *len = p->pac->numbuffers; + + return 0; +} + +/* + * + */ + +void +krb5_pac_free(krb5_context context, krb5_pac pac) +{ + krb5_data_free(&pac->data); + free(pac->pac); + free(pac); +} + +/* + * + */ + +static krb5_error_code +verify_checksum(krb5_context context, + const struct PAC_INFO_BUFFER *sig, + const krb5_data *data, + void *ptr, size_t len, + const krb5_keyblock *key) +{ + krb5_crypto crypto = NULL; + krb5_storage *sp = NULL; + uint32_t type; + krb5_error_code ret; + Checksum cksum; + + memset(&cksum, 0, sizeof(cksum)); + + sp = krb5_storage_from_mem((char *)data->data + sig->offset_lo, + sig->buffersize); + if (sp == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE); + + CHECK(ret, krb5_ret_uint32(sp, &type), out); + cksum.cksumtype = type; + cksum.checksum.length = + sig->buffersize - krb5_storage_seek(sp, 0, SEEK_CUR); + cksum.checksum.data = malloc(cksum.checksum.length); + if (cksum.checksum.data == NULL) { + krb5_set_error_string(context, "out of memory"); + ret = ENOMEM; + goto out; + } + ret = krb5_storage_read(sp, cksum.checksum.data, cksum.checksum.length); + if (ret != cksum.checksum.length) { + krb5_set_error_string(context, "PAC checksum missing checksum"); + ret = EINVAL; + goto out; + } + + if (!krb5_checksum_is_keyed(context, cksum.cksumtype)) { + krb5_set_error_string (context, "Checksum type %d not keyed", + cksum.cksumtype); + ret = EINVAL; + goto out; + } + + ret = krb5_crypto_init(context, key, 0, &crypto); + if (ret) + goto out; + + ret = krb5_verify_checksum(context, crypto, KRB5_KU_OTHER_CKSUM, + ptr, len, &cksum); + free(cksum.checksum.data); + krb5_crypto_destroy(context, crypto); + krb5_storage_free(sp); + + return ret; + +out: + if (cksum.checksum.data) + free(cksum.checksum.data); + if (sp) + krb5_storage_free(sp); + if (crypto) + krb5_crypto_destroy(context, crypto); + return ret; +} + +static krb5_error_code +create_checksum(krb5_context context, + const krb5_keyblock *key, + void *data, size_t datalen, + void *sig, size_t siglen) +{ + krb5_crypto crypto = NULL; + krb5_error_code ret; + Checksum cksum; + + ret = krb5_crypto_init(context, key, 0, &crypto); + if (ret) + return ret; + + ret = krb5_create_checksum(context, crypto, KRB5_KU_OTHER_CKSUM, 0, + data, datalen, &cksum); + krb5_crypto_destroy(context, crypto); + if (ret) + return ret; + + if (cksum.checksum.length != siglen) { + krb5_set_error_string(context, "pac checksum wrong length"); + free_Checksum(&cksum); + return EINVAL; + } + + memcpy(sig, cksum.checksum.data, siglen); + free_Checksum(&cksum); + + return 0; +} + + +/* + * + */ + +#define NTTIME_EPOCH 0x019DB1DED53E8000LL + +static uint64_t +unix2nttime(time_t unix_time) +{ + long long wt; + wt = unix_time * (uint64_t)10000000 + (uint64_t)NTTIME_EPOCH; + return wt; +} + +static krb5_error_code +verify_logonname(krb5_context context, + const struct PAC_INFO_BUFFER *logon_name, + const krb5_data *data, + time_t authtime, + krb5_const_principal principal) +{ + krb5_error_code ret; + krb5_principal p2; + uint32_t time1, time2; + krb5_storage *sp; + uint16_t len; + char *s; + + sp = krb5_storage_from_readonly_mem((const char *)data->data + logon_name->offset_lo, + logon_name->buffersize); + if (sp == NULL) { + krb5_set_error_string(context, "Out of memory"); + return ENOMEM; + } + + krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE); + + CHECK(ret, krb5_ret_uint32(sp, &time1), out); + CHECK(ret, krb5_ret_uint32(sp, &time2), out); + + { + uint64_t t1, t2; + t1 = unix2nttime(authtime); + t2 = ((uint64_t)time2 << 32) | time1; + if (t1 != t2) { + krb5_storage_free(sp); + krb5_set_error_string(context, "PAC timestamp mismatch"); + return EINVAL; + } + } + CHECK(ret, krb5_ret_uint16(sp, &len), out); + if (len == 0) { + krb5_storage_free(sp); + krb5_set_error_string(context, "PAC logon name length missing"); + return EINVAL; + } + + s = malloc(len); + if (s == NULL) { + krb5_storage_free(sp); + krb5_set_error_string(context, "Out of memory"); + return ENOMEM; + } + ret = krb5_storage_read(sp, s, len); + if (ret != len) { + krb5_storage_free(sp); + krb5_set_error_string(context, "Failed to read pac logon name"); + return EINVAL; + } + krb5_storage_free(sp); +#if 1 /* cheat for now */ + { + size_t i; + + if (len & 1) { + krb5_set_error_string(context, "PAC logon name malformed"); + return EINVAL; + } + + for (i = 0; i < len / 2; i++) { + if (s[(i * 2) + 1]) { + krb5_set_error_string(context, "PAC logon name not ASCII"); + return EINVAL; + } + s[i] = s[i * 2]; + } + s[i] = '\0'; + } +#else + { + uint16_t *ucs2; + ssize_t ucs2len; + size_t u8len; + + ucs2 = malloc(sizeof(ucs2[0]) * len / 2); + if (ucs2) + abort(); + ucs2len = wind_ucs2read(s, len / 2, ucs2); + free(s); + if (len < 0) + return -1; + ret = wind_ucs2toutf8(ucs2, ucs2len, NULL, &u8len); + if (ret < 0) + abort(); + s = malloc(u8len + 1); + if (s == NULL) + abort(); + wind_ucs2toutf8(ucs2, ucs2len, s, &u8len); + free(ucs2); + } +#endif + ret = krb5_parse_name_flags(context, s, KRB5_PRINCIPAL_PARSE_NO_REALM, &p2); + free(s); + if (ret) + return ret; + + if (krb5_principal_compare_any_realm(context, principal, p2) != TRUE) { + krb5_set_error_string(context, "PAC logon name mismatch"); + ret = EINVAL; + } + krb5_free_principal(context, p2); + return ret; +out: + return ret; +} + +/* + * + */ + +static krb5_error_code +build_logon_name(krb5_context context, + time_t authtime, + krb5_const_principal principal, + krb5_data *logon) +{ + krb5_error_code ret; + krb5_storage *sp; + uint64_t t; + char *s, *s2; + size_t i, len; + + t = unix2nttime(authtime); + + krb5_data_zero(logon); + + sp = krb5_storage_emem(); + if (sp == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE); + + CHECK(ret, krb5_store_uint32(sp, t & 0xffffffff), out); + CHECK(ret, krb5_store_uint32(sp, t >> 32), out); + + ret = krb5_unparse_name_flags(context, principal, + KRB5_PRINCIPAL_UNPARSE_NO_REALM, &s); + if (ret) + goto out; + + len = strlen(s); + + CHECK(ret, krb5_store_uint16(sp, len * 2), out); + +#if 1 /* cheat for now */ + s2 = malloc(len * 2); + if (s2 == NULL) { + ret = ENOMEM; + free(s); + goto out; + } + for (i = 0; i < len; i++) { + s2[i * 2] = s[i]; + s2[i * 2 + 1] = 0; + } + free(s); +#else + /* write libwind code here */ +#endif + + ret = krb5_storage_write(sp, s2, len * 2); + free(s2); + if (ret != len * 2) { + ret = ENOMEM; + goto out; + } + ret = krb5_storage_to_data(sp, logon); + if (ret) + goto out; + krb5_storage_free(sp); + + return 0; +out: + krb5_storage_free(sp); + return ret; +} + + +/* + * + */ + +krb5_error_code +krb5_pac_verify(krb5_context context, + const krb5_pac pac, + time_t authtime, + krb5_const_principal principal, + const krb5_keyblock *server, + const krb5_keyblock *privsvr) +{ + krb5_error_code ret; + + if (pac->server_checksum == NULL) { + krb5_set_error_string(context, "PAC missing server checksum"); + return EINVAL; + } + if (pac->privsvr_checksum == NULL) { + krb5_set_error_string(context, "PAC missing kdc checksum"); + return EINVAL; + } + if (pac->logon_name == NULL) { + krb5_set_error_string(context, "PAC missing logon name"); + return EINVAL; + } + + ret = verify_logonname(context, + pac->logon_name, + &pac->data, + authtime, + principal); + if (ret) + return ret; + + /* + * in the service case, clean out data option of the privsvr and + * server checksum before checking the checksum. + */ + { + krb5_data *copy; + + ret = krb5_copy_data(context, &pac->data, ©); + if (ret) + return ret; + + if (pac->server_checksum->buffersize < 4) + return EINVAL; + if (pac->privsvr_checksum->buffersize < 4) + return EINVAL; + + memset((char *)copy->data + pac->server_checksum->offset_lo + 4, + 0, + pac->server_checksum->buffersize - 4); + + memset((char *)copy->data + pac->privsvr_checksum->offset_lo + 4, + 0, + pac->privsvr_checksum->buffersize - 4); + + ret = verify_checksum(context, + pac->server_checksum, + &pac->data, + copy->data, + copy->length, + server); + krb5_free_data(context, copy); + if (ret) + return ret; + } + if (privsvr) { + ret = verify_checksum(context, + pac->privsvr_checksum, + &pac->data, + (char *)pac->data.data + + pac->server_checksum->offset_lo + 4, + pac->server_checksum->buffersize - 4, + privsvr); + if (ret) + return ret; + } + + return 0; +} + +/* + * + */ + +static krb5_error_code +fill_zeros(krb5_context context, krb5_storage *sp, size_t len) +{ + ssize_t sret; + size_t l; + + while (len) { + l = len; + if (l > sizeof(zeros)) + l = sizeof(zeros); + sret = krb5_storage_write(sp, zeros, l); + if (sret <= 0) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + len -= sret; + } + return 0; +} + +static krb5_error_code +pac_checksum(krb5_context context, + const krb5_keyblock *key, + uint32_t *cksumtype, + size_t *cksumsize) +{ + krb5_cksumtype cktype; + krb5_error_code ret; + krb5_crypto crypto = NULL; + + ret = krb5_crypto_init(context, key, 0, &crypto); + if (ret) + return ret; + + ret = krb5_crypto_get_checksum_type(context, crypto, &cktype); + ret = krb5_crypto_destroy(context, crypto); + if (ret) + return ret; + + if (krb5_checksum_is_keyed(context, cktype) == FALSE) { + krb5_set_error_string(context, "PAC checksum type is not keyed"); + return EINVAL; + } + + ret = krb5_checksumsize(context, cktype, cksumsize); + if (ret) + return ret; + + *cksumtype = (uint32_t)cktype; + + return 0; +} + +krb5_error_code +_krb5_pac_sign(krb5_context context, + krb5_pac p, + time_t authtime, + krb5_principal principal, + const krb5_keyblock *server_key, + const krb5_keyblock *priv_key, + krb5_data *data) +{ + krb5_error_code ret; + krb5_storage *sp = NULL, *spdata = NULL; + uint32_t end; + size_t server_size, priv_size; + uint32_t server_offset = 0, priv_offset = 0; + uint32_t server_cksumtype = 0, priv_cksumtype = 0; + int i, num = 0; + krb5_data logon, d; + + krb5_data_zero(&logon); + + if (p->logon_name == NULL) + num++; + if (p->server_checksum == NULL) + num++; + if (p->privsvr_checksum == NULL) + num++; + + if (num) { + void *ptr; + + ptr = realloc(p->pac, sizeof(*p->pac) + (sizeof(p->pac->buffers[0]) * (p->pac->numbuffers + num - 1))); + if (ptr == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + p->pac = ptr; + + if (p->logon_name == NULL) { + p->logon_name = &p->pac->buffers[p->pac->numbuffers++]; + memset(p->logon_name, 0, sizeof(*p->logon_name)); + p->logon_name->type = PAC_LOGON_NAME; + } + if (p->server_checksum == NULL) { + p->server_checksum = &p->pac->buffers[p->pac->numbuffers++]; + memset(p->server_checksum, 0, sizeof(*p->server_checksum)); + p->server_checksum->type = PAC_SERVER_CHECKSUM; + } + if (p->privsvr_checksum == NULL) { + p->privsvr_checksum = &p->pac->buffers[p->pac->numbuffers++]; + memset(p->privsvr_checksum, 0, sizeof(*p->privsvr_checksum)); + p->privsvr_checksum->type = PAC_PRIVSVR_CHECKSUM; + } + } + + /* Calculate LOGON NAME */ + ret = build_logon_name(context, authtime, principal, &logon); + if (ret) + goto out; + + /* Set lengths for checksum */ + ret = pac_checksum(context, server_key, &server_cksumtype, &server_size); + if (ret) + goto out; + ret = pac_checksum(context, priv_key, &priv_cksumtype, &priv_size); + if (ret) + goto out; + + /* Encode PAC */ + sp = krb5_storage_emem(); + if (sp == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE); + + spdata = krb5_storage_emem(); + if (spdata == NULL) { + krb5_storage_free(sp); + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + krb5_storage_set_flags(spdata, KRB5_STORAGE_BYTEORDER_LE); + + CHECK(ret, krb5_store_uint32(sp, p->pac->numbuffers), out); + CHECK(ret, krb5_store_uint32(sp, p->pac->version), out); + + end = PACTYPE_SIZE + (PAC_INFO_BUFFER_SIZE * p->pac->numbuffers); + + for (i = 0; i < p->pac->numbuffers; i++) { + uint32_t len; + size_t sret; + void *ptr = NULL; + + /* store data */ + + if (p->pac->buffers[i].type == PAC_SERVER_CHECKSUM) { + len = server_size + 4; + server_offset = end + 4; + CHECK(ret, krb5_store_uint32(spdata, server_cksumtype), out); + CHECK(ret, fill_zeros(context, spdata, server_size), out); + } else if (p->pac->buffers[i].type == PAC_PRIVSVR_CHECKSUM) { + len = priv_size + 4; + priv_offset = end + 4; + CHECK(ret, krb5_store_uint32(spdata, priv_cksumtype), out); + CHECK(ret, fill_zeros(context, spdata, priv_size), out); + } else if (p->pac->buffers[i].type == PAC_LOGON_NAME) { + len = krb5_storage_write(spdata, logon.data, logon.length); + if (logon.length != len) { + ret = EINVAL; + goto out; + } + } else { + len = p->pac->buffers[i].buffersize; + ptr = (char *)p->data.data + p->pac->buffers[i].offset_lo; + + sret = krb5_storage_write(spdata, ptr, len); + if (sret != len) { + krb5_set_error_string(context, "out of memory"); + ret = ENOMEM; + goto out; + } + /* XXX if not aligned, fill_zeros */ + } + + /* write header */ + CHECK(ret, krb5_store_uint32(sp, p->pac->buffers[i].type), out); + CHECK(ret, krb5_store_uint32(sp, len), out); + CHECK(ret, krb5_store_uint32(sp, end), out); + CHECK(ret, krb5_store_uint32(sp, 0), out); + + /* advance data endpointer and align */ + { + int32_t e; + + end += len; + e = ((end + PAC_ALIGNMENT - 1) / PAC_ALIGNMENT) * PAC_ALIGNMENT; + if (end != e) { + CHECK(ret, fill_zeros(context, spdata, e - end), out); + } + end = e; + } + + } + + /* assert (server_offset != 0 && priv_offset != 0); */ + + /* export PAC */ + ret = krb5_storage_to_data(spdata, &d); + if (ret) { + krb5_set_error_string(context, "out of memory"); + goto out; + } + ret = krb5_storage_write(sp, d.data, d.length); + if (ret != d.length) { + krb5_data_free(&d); + krb5_set_error_string(context, "out of memory"); + ret = ENOMEM; + goto out; + } + krb5_data_free(&d); + + ret = krb5_storage_to_data(sp, &d); + if (ret) { + krb5_set_error_string(context, "out of memory"); + goto out; + } + + /* sign */ + + ret = create_checksum(context, server_key, + d.data, d.length, + (char *)d.data + server_offset, server_size); + if (ret) { + krb5_data_free(&d); + goto out; + } + + ret = create_checksum(context, priv_key, + (char *)d.data + server_offset, server_size, + (char *)d.data + priv_offset, priv_size); + if (ret) { + krb5_data_free(&d); + goto out; + } + + /* done */ + *data = d; + + krb5_data_free(&logon); + krb5_storage_free(sp); + krb5_storage_free(spdata); + + return 0; +out: + krb5_data_free(&logon); + if (sp) + krb5_storage_free(sp); + if (spdata) + krb5_storage_free(spdata); + return ret; +} diff --git a/lib/krb5/padata.c b/lib/krb5/padata.c new file mode 100644 index 0000000..b2b70f5 --- /dev/null +++ b/lib/krb5/padata.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 1997 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: padata.c 15469 2005-06-17 04:28:35Z lha $"); + +PA_DATA * +krb5_find_padata(PA_DATA *val, unsigned len, int type, int *idx) +{ + for(; *idx < len; (*idx)++) + if(val[*idx].padata_type == type) + return val + *idx; + return NULL; +} + +int KRB5_LIB_FUNCTION +krb5_padata_add(krb5_context context, METHOD_DATA *md, + int type, void *buf, size_t len) +{ + PA_DATA *pa; + + pa = realloc (md->val, (md->len + 1) * sizeof(*md->val)); + if (pa == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + md->val = pa; + + pa[md->len].padata_type = type; + pa[md->len].padata_value.length = len; + pa[md->len].padata_value.data = buf; + md->len++; + + return 0; +} diff --git a/lib/krb5/parse-name-test.c b/lib/krb5/parse-name-test.c new file mode 100644 index 0000000..7e60705 --- /dev/null +++ b/lib/krb5/parse-name-test.c @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2002 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include "krb5_locl.h" +#include <err.h> + +RCSID("$Id: parse-name-test.c 16342 2005-12-02 14:14:43Z lha $"); + +enum { MAX_COMPONENTS = 3 }; + +static struct testcase { + const char *input_string; + const char *output_string; + krb5_realm realm; + unsigned ncomponents; + char *comp_val[MAX_COMPONENTS]; + int realmp; +} tests[] = { + {"", "@", "", 1, {""}, FALSE}, + {"a", "a@", "", 1, {"a"}, FALSE}, + {"\\n", "\\n@", "", 1, {"\n"}, FALSE}, + {"\\ ", "\\ @", "", 1, {" "}, FALSE}, + {"\\t", "\\t@", "", 1, {"\t"}, FALSE}, + {"\\b", "\\b@", "", 1, {"\b"}, FALSE}, + {"\\\\", "\\\\@", "", 1, {"\\"}, FALSE}, + {"\\/", "\\/@", "", 1, {"/"}, FALSE}, + {"\\@", "\\@@", "", 1, {"@"}, FALSE}, + {"@", "@", "", 1, {""}, TRUE}, + {"a/b", "a/b@", "", 2, {"a", "b"}, FALSE}, + {"a/", "a/@", "", 2, {"a", ""}, FALSE}, + {"a\\//\\/", "a\\//\\/@", "", 2, {"a/", "/"}, FALSE}, + {"/a", "/a@", "", 2, {"", "a"}, FALSE}, + {"\\@@\\@", "\\@@\\@", "@", 1, {"@"}, TRUE}, + {"a/b/c", "a/b/c@", "", 3, {"a", "b", "c"}, FALSE}, + {NULL, NULL, "", 0, { NULL }, FALSE}}; + +int KRB5_LIB_FUNCTION +main(int argc, char **argv) +{ + struct testcase *t; + krb5_context context; + krb5_error_code ret; + int val = 0; + + ret = krb5_init_context (&context); + if (ret) + errx (1, "krb5_init_context failed: %d", ret); + + /* to enable realm-less principal name above */ + + krb5_set_default_realm(context, ""); + + for (t = tests; t->input_string; ++t) { + krb5_principal princ; + int i, j; + char name_buf[1024]; + char *s; + + ret = krb5_parse_name(context, t->input_string, &princ); + if (ret) + krb5_err (context, 1, ret, "krb5_parse_name %s", + t->input_string); + if (strcmp (t->realm, princ->realm) != 0) { + printf ("wrong realm (\"%s\" should be \"%s\")" + " for \"%s\"\n", + princ->realm, t->realm, + t->input_string); + val = 1; + } + + if (t->ncomponents != princ->name.name_string.len) { + printf ("wrong number of components (%u should be %u)" + " for \"%s\"\n", + princ->name.name_string.len, t->ncomponents, + t->input_string); + val = 1; + } else { + for (i = 0; i < t->ncomponents; ++i) { + if (strcmp(t->comp_val[i], + princ->name.name_string.val[i]) != 0) { + printf ("bad component %d (\"%s\" should be \"%s\")" + " for \"%s\"\n", + i, + princ->name.name_string.val[i], + t->comp_val[i], + t->input_string); + val = 1; + } + } + } + for (j = 0; j < strlen(t->output_string); ++j) { + ret = krb5_unparse_name_fixed(context, princ, + name_buf, j); + if (ret != ERANGE) { + printf ("unparse_name %s with length %d should have failed\n", + t->input_string, j); + val = 1; + break; + } + } + ret = krb5_unparse_name_fixed(context, princ, + name_buf, sizeof(name_buf)); + if (ret) + krb5_err (context, 1, ret, "krb5_unparse_name_fixed"); + + if (strcmp (t->output_string, name_buf) != 0) { + printf ("failed comparing the re-parsed" + " (\"%s\" should be \"%s\")\n", + name_buf, t->output_string); + val = 1; + } + + ret = krb5_unparse_name(context, princ, &s); + if (ret) + krb5_err (context, 1, ret, "krb5_unparse_name"); + + if (strcmp (t->output_string, s) != 0) { + printf ("failed comparing the re-parsed" + " (\"%s\" should be \"%s\"\n", + s, t->output_string); + val = 1; + } + free(s); + + if (!t->realmp) { + for (j = 0; j < strlen(t->input_string); ++j) { + ret = krb5_unparse_name_fixed_short(context, princ, + name_buf, j); + if (ret != ERANGE) { + printf ("unparse_name_short %s with length %d" + " should have failed\n", + t->input_string, j); + val = 1; + break; + } + } + ret = krb5_unparse_name_fixed_short(context, princ, + name_buf, sizeof(name_buf)); + if (ret) + krb5_err (context, 1, ret, "krb5_unparse_name_fixed"); + + if (strcmp (t->input_string, name_buf) != 0) { + printf ("failed comparing the re-parsed" + " (\"%s\" should be \"%s\")\n", + name_buf, t->input_string); + val = 1; + } + + ret = krb5_unparse_name_short(context, princ, &s); + if (ret) + krb5_err (context, 1, ret, "krb5_unparse_name_short"); + + if (strcmp (t->input_string, s) != 0) { + printf ("failed comparing the re-parsed" + " (\"%s\" should be \"%s\"\n", + s, t->input_string); + val = 1; + } + free(s); + } + krb5_free_principal (context, princ); + } + krb5_free_context(context); + return val; +} diff --git a/lib/krb5/pkinit.c b/lib/krb5/pkinit.c new file mode 100644 index 0000000..a0b6a4e --- /dev/null +++ b/lib/krb5/pkinit.c @@ -0,0 +1,2070 @@ +/* + * Copyright (c) 2003 - 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: pkinit.c 22433 2008-01-13 14:11:46Z lha $"); + +struct krb5_dh_moduli { + char *name; + unsigned long bits; + heim_integer p; + heim_integer g; + heim_integer q; +}; + +#ifdef PKINIT + +#include <heim_asn1.h> +#include <rfc2459_asn1.h> +#include <cms_asn1.h> +#include <pkcs8_asn1.h> +#include <pkcs9_asn1.h> +#include <pkcs12_asn1.h> +#include <pkinit_asn1.h> +#include <asn1_err.h> + +#include <der.h> + +#include <hx509.h> + +enum { + COMPAT_WIN2K = 1, + COMPAT_IETF = 2 +}; + +struct krb5_pk_identity { + hx509_context hx509ctx; + hx509_verify_ctx verify_ctx; + hx509_certs certs; + hx509_certs anchors; + hx509_certs certpool; + hx509_revoke_ctx revokectx; +}; + +struct krb5_pk_cert { + hx509_cert cert; +}; + +struct krb5_pk_init_ctx_data { + struct krb5_pk_identity *id; + DH *dh; + krb5_data *clientDHNonce; + struct krb5_dh_moduli **m; + hx509_peer_info peer; + int type; + unsigned int require_binding:1; + unsigned int require_eku:1; + unsigned int require_krbtgt_otherName:1; + unsigned int require_hostname_match:1; + unsigned int trustedCertifiers:1; +}; + +static void +_krb5_pk_copy_error(krb5_context context, + hx509_context hx509ctx, + int hxret, + const char *fmt, + ...) + __attribute__ ((format (printf, 4, 5))); + +/* + * + */ + +void KRB5_LIB_FUNCTION +_krb5_pk_cert_free(struct krb5_pk_cert *cert) +{ + if (cert->cert) { + hx509_cert_free(cert->cert); + } + free(cert); +} + +static krb5_error_code +BN_to_integer(krb5_context context, BIGNUM *bn, heim_integer *integer) +{ + integer->length = BN_num_bytes(bn); + integer->data = malloc(integer->length); + if (integer->data == NULL) { + krb5_clear_error_string(context); + return ENOMEM; + } + BN_bn2bin(bn, integer->data); + integer->negative = BN_is_negative(bn); + return 0; +} + +static BIGNUM * +integer_to_BN(krb5_context context, const char *field, const heim_integer *f) +{ + BIGNUM *bn; + + bn = BN_bin2bn((const unsigned char *)f->data, f->length, NULL); + if (bn == NULL) { + krb5_set_error_string(context, "PKINIT: parsing BN failed %s", field); + return NULL; + } + BN_set_negative(bn, f->negative); + return bn; +} + + +static krb5_error_code +_krb5_pk_create_sign(krb5_context context, + const heim_oid *eContentType, + krb5_data *eContent, + struct krb5_pk_identity *id, + hx509_peer_info peer, + krb5_data *sd_data) +{ + hx509_cert cert; + hx509_query *q; + int ret; + + ret = hx509_query_alloc(id->hx509ctx, &q); + if (ret) { + _krb5_pk_copy_error(context, id->hx509ctx, ret, + "Allocate query to find signing certificate"); + return ret; + } + + hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY); + hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE); + + ret = hx509_certs_find(id->hx509ctx, id->certs, q, &cert); + hx509_query_free(id->hx509ctx, q); + if (ret) { + _krb5_pk_copy_error(context, id->hx509ctx, ret, + "Find certificate to signed CMS data"); + return ret; + } + + ret = hx509_cms_create_signed_1(id->hx509ctx, + 0, + eContentType, + eContent->data, + eContent->length, + NULL, + cert, + peer, + NULL, + id->certs, + sd_data); + if (ret) + _krb5_pk_copy_error(context, id->hx509ctx, ret, "create CMS signedData"); + hx509_cert_free(cert); + + return ret; +} + +static int +cert2epi(hx509_context context, void *ctx, hx509_cert c) +{ + ExternalPrincipalIdentifiers *ids = ctx; + ExternalPrincipalIdentifier id; + hx509_name subject = NULL; + void *p; + int ret; + + memset(&id, 0, sizeof(id)); + + ret = hx509_cert_get_subject(c, &subject); + if (ret) + return ret; + + if (hx509_name_is_null_p(subject) != 0) { + + id.subjectName = calloc(1, sizeof(*id.subjectName)); + if (id.subjectName == NULL) { + hx509_name_free(&subject); + free_ExternalPrincipalIdentifier(&id); + return ENOMEM; + } + + ret = hx509_name_binary(subject, id.subjectName); + if (ret) { + hx509_name_free(&subject); + free_ExternalPrincipalIdentifier(&id); + return ret; + } + } + hx509_name_free(&subject); + + + id.issuerAndSerialNumber = calloc(1, sizeof(*id.issuerAndSerialNumber)); + if (id.issuerAndSerialNumber == NULL) { + free_ExternalPrincipalIdentifier(&id); + return ENOMEM; + } + + { + IssuerAndSerialNumber iasn; + hx509_name issuer; + size_t size; + + memset(&iasn, 0, sizeof(iasn)); + + ret = hx509_cert_get_issuer(c, &issuer); + if (ret) { + free_ExternalPrincipalIdentifier(&id); + return ret; + } + + ret = hx509_name_to_Name(issuer, &iasn.issuer); + hx509_name_free(&issuer); + if (ret) { + free_ExternalPrincipalIdentifier(&id); + return ret; + } + + ret = hx509_cert_get_serialnumber(c, &iasn.serialNumber); + if (ret) { + free_IssuerAndSerialNumber(&iasn); + free_ExternalPrincipalIdentifier(&id); + return ret; + } + + ASN1_MALLOC_ENCODE(IssuerAndSerialNumber, + id.issuerAndSerialNumber->data, + id.issuerAndSerialNumber->length, + &iasn, &size, ret); + free_IssuerAndSerialNumber(&iasn); + if (ret) + return ret; + if (id.issuerAndSerialNumber->length != size) + abort(); + } + + id.subjectKeyIdentifier = NULL; + + p = realloc(ids->val, sizeof(ids->val[0]) * (ids->len + 1)); + if (p == NULL) { + free_ExternalPrincipalIdentifier(&id); + return ENOMEM; + } + + ids->val = p; + ids->val[ids->len] = id; + ids->len++; + + return 0; +} + +static krb5_error_code +build_edi(krb5_context context, + hx509_context hx509ctx, + hx509_certs certs, + ExternalPrincipalIdentifiers *ids) +{ + return hx509_certs_iter(hx509ctx, certs, cert2epi, ids); +} + +static krb5_error_code +build_auth_pack(krb5_context context, + unsigned nonce, + krb5_pk_init_ctx ctx, + DH *dh, + const KDC_REQ_BODY *body, + AuthPack *a) +{ + size_t buf_size, len; + krb5_error_code ret; + void *buf; + krb5_timestamp sec; + int32_t usec; + Checksum checksum; + + krb5_clear_error_string(context); + + memset(&checksum, 0, sizeof(checksum)); + + krb5_us_timeofday(context, &sec, &usec); + a->pkAuthenticator.ctime = sec; + a->pkAuthenticator.nonce = nonce; + + ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, body, &len, ret); + if (ret) + return ret; + if (buf_size != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + + ret = krb5_create_checksum(context, + NULL, + 0, + CKSUMTYPE_SHA1, + buf, + len, + &checksum); + free(buf); + if (ret) + return ret; + + ALLOC(a->pkAuthenticator.paChecksum, 1); + if (a->pkAuthenticator.paChecksum == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + ret = krb5_data_copy(a->pkAuthenticator.paChecksum, + checksum.checksum.data, checksum.checksum.length); + free_Checksum(&checksum); + if (ret) + return ret; + + if (dh) { + DomainParameters dp; + heim_integer dh_pub_key; + krb5_data dhbuf; + size_t size; + + if (1 /* support_cached_dh */) { + ALLOC(a->clientDHNonce, 1); + if (a->clientDHNonce == NULL) { + krb5_clear_error_string(context); + return ENOMEM; + } + ret = krb5_data_alloc(a->clientDHNonce, 40); + if (a->clientDHNonce == NULL) { + krb5_clear_error_string(context); + return ENOMEM; + } + memset(a->clientDHNonce->data, 0, a->clientDHNonce->length); + ret = krb5_copy_data(context, a->clientDHNonce, + &ctx->clientDHNonce); + if (ret) + return ret; + } + + ALLOC(a->clientPublicValue, 1); + if (a->clientPublicValue == NULL) + return ENOMEM; + ret = der_copy_oid(oid_id_dhpublicnumber(), + &a->clientPublicValue->algorithm.algorithm); + if (ret) + return ret; + + memset(&dp, 0, sizeof(dp)); + + ret = BN_to_integer(context, dh->p, &dp.p); + if (ret) { + free_DomainParameters(&dp); + return ret; + } + ret = BN_to_integer(context, dh->g, &dp.g); + if (ret) { + free_DomainParameters(&dp); + return ret; + } + ret = BN_to_integer(context, dh->q, &dp.q); + if (ret) { + free_DomainParameters(&dp); + return ret; + } + dp.j = NULL; + dp.validationParms = NULL; + + a->clientPublicValue->algorithm.parameters = + malloc(sizeof(*a->clientPublicValue->algorithm.parameters)); + if (a->clientPublicValue->algorithm.parameters == NULL) { + free_DomainParameters(&dp); + return ret; + } + + ASN1_MALLOC_ENCODE(DomainParameters, + a->clientPublicValue->algorithm.parameters->data, + a->clientPublicValue->algorithm.parameters->length, + &dp, &size, ret); + free_DomainParameters(&dp); + if (ret) + return ret; + if (size != a->clientPublicValue->algorithm.parameters->length) + krb5_abortx(context, "Internal ASN1 encoder error"); + + ret = BN_to_integer(context, dh->pub_key, &dh_pub_key); + if (ret) + return ret; + + ASN1_MALLOC_ENCODE(DHPublicKey, dhbuf.data, dhbuf.length, + &dh_pub_key, &size, ret); + der_free_heim_integer(&dh_pub_key); + if (ret) + return ret; + if (size != dhbuf.length) + krb5_abortx(context, "asn1 internal error"); + + a->clientPublicValue->subjectPublicKey.length = dhbuf.length * 8; + a->clientPublicValue->subjectPublicKey.data = dhbuf.data; + } + + { + a->supportedCMSTypes = calloc(1, sizeof(*a->supportedCMSTypes)); + if (a->supportedCMSTypes == NULL) + return ENOMEM; + + ret = hx509_crypto_available(ctx->id->hx509ctx, HX509_SELECT_ALL, NULL, + &a->supportedCMSTypes->val, + &a->supportedCMSTypes->len); + if (ret) + return ret; + } + + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_pk_mk_ContentInfo(krb5_context context, + const krb5_data *buf, + const heim_oid *oid, + struct ContentInfo *content_info) +{ + krb5_error_code ret; + + ret = der_copy_oid(oid, &content_info->contentType); + if (ret) + return ret; + ALLOC(content_info->content, 1); + if (content_info->content == NULL) + return ENOMEM; + content_info->content->data = malloc(buf->length); + if (content_info->content->data == NULL) + return ENOMEM; + memcpy(content_info->content->data, buf->data, buf->length); + content_info->content->length = buf->length; + return 0; +} + +static krb5_error_code +pk_mk_padata(krb5_context context, + krb5_pk_init_ctx ctx, + const KDC_REQ_BODY *req_body, + unsigned nonce, + METHOD_DATA *md) +{ + struct ContentInfo content_info; + krb5_error_code ret; + const heim_oid *oid; + size_t size; + krb5_data buf, sd_buf; + int pa_type; + + krb5_data_zero(&buf); + krb5_data_zero(&sd_buf); + memset(&content_info, 0, sizeof(content_info)); + + if (ctx->type == COMPAT_WIN2K) { + AuthPack_Win2k ap; + krb5_timestamp sec; + int32_t usec; + + memset(&ap, 0, sizeof(ap)); + + /* fill in PKAuthenticator */ + ret = copy_PrincipalName(req_body->sname, &ap.pkAuthenticator.kdcName); + if (ret) { + free_AuthPack_Win2k(&ap); + krb5_clear_error_string(context); + goto out; + } + ret = copy_Realm(&req_body->realm, &ap.pkAuthenticator.kdcRealm); + if (ret) { + free_AuthPack_Win2k(&ap); + krb5_clear_error_string(context); + goto out; + } + + krb5_us_timeofday(context, &sec, &usec); + ap.pkAuthenticator.ctime = sec; + ap.pkAuthenticator.cusec = usec; + ap.pkAuthenticator.nonce = nonce; + + ASN1_MALLOC_ENCODE(AuthPack_Win2k, buf.data, buf.length, + &ap, &size, ret); + free_AuthPack_Win2k(&ap); + if (ret) { + krb5_set_error_string(context, "AuthPack_Win2k: %d", ret); + goto out; + } + if (buf.length != size) + krb5_abortx(context, "internal ASN1 encoder error"); + + oid = oid_id_pkcs7_data(); + } else if (ctx->type == COMPAT_IETF) { + AuthPack ap; + + memset(&ap, 0, sizeof(ap)); + + ret = build_auth_pack(context, nonce, ctx, ctx->dh, req_body, &ap); + if (ret) { + free_AuthPack(&ap); + goto out; + } + + ASN1_MALLOC_ENCODE(AuthPack, buf.data, buf.length, &ap, &size, ret); + free_AuthPack(&ap); + if (ret) { + krb5_set_error_string(context, "AuthPack: %d", ret); + goto out; + } + if (buf.length != size) + krb5_abortx(context, "internal ASN1 encoder error"); + + oid = oid_id_pkauthdata(); + } else + krb5_abortx(context, "internal pkinit error"); + + ret = _krb5_pk_create_sign(context, + oid, + &buf, + ctx->id, + ctx->peer, + &sd_buf); + krb5_data_free(&buf); + if (ret) + goto out; + + ret = hx509_cms_wrap_ContentInfo(oid_id_pkcs7_signedData(), &sd_buf, &buf); + krb5_data_free(&sd_buf); + if (ret) { + krb5_set_error_string(context, + "ContentInfo wrapping of signedData failed"); + goto out; + } + + if (ctx->type == COMPAT_WIN2K) { + PA_PK_AS_REQ_Win2k winreq; + + pa_type = KRB5_PADATA_PK_AS_REQ_WIN; + + memset(&winreq, 0, sizeof(winreq)); + + winreq.signed_auth_pack = buf; + + ASN1_MALLOC_ENCODE(PA_PK_AS_REQ_Win2k, buf.data, buf.length, + &winreq, &size, ret); + free_PA_PK_AS_REQ_Win2k(&winreq); + + } else if (ctx->type == COMPAT_IETF) { + PA_PK_AS_REQ req; + + pa_type = KRB5_PADATA_PK_AS_REQ; + + memset(&req, 0, sizeof(req)); + req.signedAuthPack = buf; + + if (ctx->trustedCertifiers) { + + req.trustedCertifiers = calloc(1, sizeof(*req.trustedCertifiers)); + if (req.trustedCertifiers == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + free_PA_PK_AS_REQ(&req); + goto out; + } + ret = build_edi(context, ctx->id->hx509ctx, + ctx->id->anchors, req.trustedCertifiers); + if (ret) { + krb5_set_error_string(context, "pk-init: failed to build trustedCertifiers"); + free_PA_PK_AS_REQ(&req); + goto out; + } + } + req.kdcPkId = NULL; + + ASN1_MALLOC_ENCODE(PA_PK_AS_REQ, buf.data, buf.length, + &req, &size, ret); + + free_PA_PK_AS_REQ(&req); + + } else + krb5_abortx(context, "internal pkinit error"); + if (ret) { + krb5_set_error_string(context, "PA-PK-AS-REQ %d", ret); + goto out; + } + if (buf.length != size) + krb5_abortx(context, "Internal ASN1 encoder error"); + + ret = krb5_padata_add(context, md, pa_type, buf.data, buf.length); + if (ret) + free(buf.data); + + if (ret == 0 && ctx->type == COMPAT_WIN2K) + krb5_padata_add(context, md, KRB5_PADATA_PK_AS_09_BINDING, NULL, 0); + +out: + free_ContentInfo(&content_info); + + return ret; +} + + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_pk_mk_padata(krb5_context context, + void *c, + const KDC_REQ_BODY *req_body, + unsigned nonce, + METHOD_DATA *md) +{ + krb5_pk_init_ctx ctx = c; + int win2k_compat; + + win2k_compat = krb5_config_get_bool_default(context, NULL, + FALSE, + "realms", + req_body->realm, + "pkinit_win2k", + NULL); + + if (win2k_compat) { + ctx->require_binding = + krb5_config_get_bool_default(context, NULL, + FALSE, + "realms", + req_body->realm, + "pkinit_win2k_require_binding", + NULL); + ctx->type = COMPAT_WIN2K; + } else + ctx->type = COMPAT_IETF; + + ctx->require_eku = + krb5_config_get_bool_default(context, NULL, + TRUE, + "realms", + req_body->realm, + "pkinit_require_eku", + NULL); + ctx->require_krbtgt_otherName = + krb5_config_get_bool_default(context, NULL, + TRUE, + "realms", + req_body->realm, + "pkinit_require_krbtgt_otherName", + NULL); + + ctx->require_hostname_match = + krb5_config_get_bool_default(context, NULL, + FALSE, + "realms", + req_body->realm, + "pkinit_require_hostname_match", + NULL); + + ctx->trustedCertifiers = + krb5_config_get_bool_default(context, NULL, + TRUE, + "realms", + req_body->realm, + "pkinit_trustedCertifiers", + NULL); + + return pk_mk_padata(context, ctx, req_body, nonce, md); +} + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_pk_verify_sign(krb5_context context, + const void *data, + size_t length, + struct krb5_pk_identity *id, + heim_oid *contentType, + krb5_data *content, + struct krb5_pk_cert **signer) +{ + hx509_certs signer_certs; + int ret; + + *signer = NULL; + + ret = hx509_cms_verify_signed(id->hx509ctx, + id->verify_ctx, + data, + length, + NULL, + id->certpool, + contentType, + content, + &signer_certs); + if (ret) { + _krb5_pk_copy_error(context, id->hx509ctx, ret, + "CMS verify signed failed"); + return ret; + } + + *signer = calloc(1, sizeof(**signer)); + if (*signer == NULL) { + krb5_clear_error_string(context); + ret = ENOMEM; + goto out; + } + + ret = hx509_get_one_cert(id->hx509ctx, signer_certs, &(*signer)->cert); + if (ret) { + _krb5_pk_copy_error(context, id->hx509ctx, ret, + "Failed to get on of the signer certs"); + goto out; + } + +out: + hx509_certs_free(&signer_certs); + if (ret) { + if (*signer) { + hx509_cert_free((*signer)->cert); + free(*signer); + *signer = NULL; + } + } + + return ret; +} + +static krb5_error_code +get_reply_key_win(krb5_context context, + const krb5_data *content, + unsigned nonce, + krb5_keyblock **key) +{ + ReplyKeyPack_Win2k key_pack; + krb5_error_code ret; + size_t size; + + ret = decode_ReplyKeyPack_Win2k(content->data, + content->length, + &key_pack, + &size); + if (ret) { + krb5_set_error_string(context, "PKINIT decoding reply key failed"); + free_ReplyKeyPack_Win2k(&key_pack); + return ret; + } + + if (key_pack.nonce != nonce) { + krb5_set_error_string(context, "PKINIT enckey nonce is wrong"); + free_ReplyKeyPack_Win2k(&key_pack); + return KRB5KRB_AP_ERR_MODIFIED; + } + + *key = malloc (sizeof (**key)); + if (*key == NULL) { + krb5_set_error_string(context, "PKINIT failed allocating reply key"); + free_ReplyKeyPack_Win2k(&key_pack); + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + ret = copy_EncryptionKey(&key_pack.replyKey, *key); + free_ReplyKeyPack_Win2k(&key_pack); + if (ret) { + krb5_set_error_string(context, "PKINIT failed copying reply key"); + free(*key); + *key = NULL; + } + + return ret; +} + +static krb5_error_code +get_reply_key(krb5_context context, + const krb5_data *content, + const krb5_data *req_buffer, + krb5_keyblock **key) +{ + ReplyKeyPack key_pack; + krb5_error_code ret; + size_t size; + + ret = decode_ReplyKeyPack(content->data, + content->length, + &key_pack, + &size); + if (ret) { + krb5_set_error_string(context, "PKINIT decoding reply key failed"); + free_ReplyKeyPack(&key_pack); + return ret; + } + + { + krb5_crypto crypto; + + /* + * XXX Verify kp.replyKey is a allowed enctype in the + * configuration file + */ + + ret = krb5_crypto_init(context, &key_pack.replyKey, 0, &crypto); + if (ret) { + free_ReplyKeyPack(&key_pack); + return ret; + } + + ret = krb5_verify_checksum(context, crypto, 6, + req_buffer->data, req_buffer->length, + &key_pack.asChecksum); + krb5_crypto_destroy(context, crypto); + if (ret) { + free_ReplyKeyPack(&key_pack); + return ret; + } + } + + *key = malloc (sizeof (**key)); + if (*key == NULL) { + krb5_set_error_string(context, "PKINIT failed allocating reply key"); + free_ReplyKeyPack(&key_pack); + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + ret = copy_EncryptionKey(&key_pack.replyKey, *key); + free_ReplyKeyPack(&key_pack); + if (ret) { + krb5_set_error_string(context, "PKINIT failed copying reply key"); + free(*key); + *key = NULL; + } + + return ret; +} + + +static krb5_error_code +pk_verify_host(krb5_context context, + const char *realm, + const krb5_krbhst_info *hi, + struct krb5_pk_init_ctx_data *ctx, + struct krb5_pk_cert *host) +{ + krb5_error_code ret = 0; + + if (ctx->require_eku) { + ret = hx509_cert_check_eku(ctx->id->hx509ctx, host->cert, + oid_id_pkkdcekuoid(), 0); + if (ret) { + krb5_set_error_string(context, "No PK-INIT KDC EKU in kdc certificate"); + return ret; + } + } + if (ctx->require_krbtgt_otherName) { + hx509_octet_string_list list; + int i; + + ret = hx509_cert_find_subjectAltName_otherName(ctx->id->hx509ctx, + host->cert, + oid_id_pkinit_san(), + &list); + if (ret) { + krb5_set_error_string(context, "Failed to find the PK-INIT " + "subjectAltName in the KDC certificate"); + + return ret; + } + + for (i = 0; i < list.len; i++) { + KRB5PrincipalName r; + + ret = decode_KRB5PrincipalName(list.val[i].data, + list.val[i].length, + &r, + NULL); + if (ret) { + krb5_set_error_string(context, "Failed to decode the PK-INIT " + "subjectAltName in the KDC certificate"); + + break; + } + + if (r.principalName.name_string.len != 2 || + strcmp(r.principalName.name_string.val[0], KRB5_TGS_NAME) != 0 || + strcmp(r.principalName.name_string.val[1], realm) != 0 || + strcmp(r.realm, realm) != 0) + { + krb5_set_error_string(context, "KDC have wrong realm name in " + "the certificate"); + ret = KRB5_KDC_ERR_INVALID_CERTIFICATE; + } + + free_KRB5PrincipalName(&r); + if (ret) + break; + } + hx509_free_octet_string_list(&list); + } + if (ret) + return ret; + + if (hi) { + ret = hx509_verify_hostname(ctx->id->hx509ctx, host->cert, + ctx->require_hostname_match, + HX509_HN_HOSTNAME, + hi->hostname, + hi->ai->ai_addr, hi->ai->ai_addrlen); + + if (ret) + krb5_set_error_string(context, "Address mismatch in " + "the KDC certificate"); + } + return ret; +} + +static krb5_error_code +pk_rd_pa_reply_enckey(krb5_context context, + int type, + const heim_octet_string *indata, + const heim_oid *dataType, + const char *realm, + krb5_pk_init_ctx ctx, + krb5_enctype etype, + const krb5_krbhst_info *hi, + unsigned nonce, + const krb5_data *req_buffer, + PA_DATA *pa, + krb5_keyblock **key) +{ + krb5_error_code ret; + struct krb5_pk_cert *host = NULL; + krb5_data content; + heim_oid contentType = { 0, NULL }; + + if (der_heim_oid_cmp(oid_id_pkcs7_envelopedData(), dataType)) { + krb5_set_error_string(context, "PKINIT: Invalid content type"); + return EINVAL; + } + + ret = hx509_cms_unenvelope(ctx->id->hx509ctx, + ctx->id->certs, + HX509_CMS_UE_DONT_REQUIRE_KU_ENCIPHERMENT, + indata->data, + indata->length, + NULL, + &contentType, + &content); + if (ret) { + _krb5_pk_copy_error(context, ctx->id->hx509ctx, ret, + "Failed to unenvelope CMS data in PK-INIT reply"); + return ret; + } + der_free_oid(&contentType); + +#if 0 /* windows LH with interesting CMS packets, leaks memory */ + { + size_t ph = 1 + der_length_len (length); + unsigned char *ptr = malloc(length + ph); + size_t l; + + memcpy(ptr + ph, p, length); + + ret = der_put_length_and_tag (ptr + ph - 1, ph, length, + ASN1_C_UNIV, CONS, UT_Sequence, &l); + if (ret) + return ret; + ptr += ph - l; + length += l; + p = ptr; + } +#endif + + /* win2k uses ContentInfo */ + if (type == COMPAT_WIN2K) { + heim_oid type; + heim_octet_string out; + + ret = hx509_cms_unwrap_ContentInfo(&content, &type, &out, NULL); + if (der_heim_oid_cmp(&type, oid_id_pkcs7_signedData())) { + ret = EINVAL; /* XXX */ + krb5_set_error_string(context, "PKINIT: Invalid content type"); + der_free_oid(&type); + der_free_octet_string(&out); + goto out; + } + der_free_oid(&type); + krb5_data_free(&content); + ret = krb5_data_copy(&content, out.data, out.length); + der_free_octet_string(&out); + if (ret) { + krb5_set_error_string(context, "PKINIT: out of memory"); + goto out; + } + } + + ret = _krb5_pk_verify_sign(context, + content.data, + content.length, + ctx->id, + &contentType, + &content, + &host); + if (ret) + goto out; + + /* make sure that it is the kdc's certificate */ + ret = pk_verify_host(context, realm, hi, ctx, host); + if (ret) { + goto out; + } + +#if 0 + if (type == COMPAT_WIN2K) { + if (der_heim_oid_cmp(&contentType, oid_id_pkcs7_data()) != 0) { + krb5_set_error_string(context, "PKINIT: reply key, wrong oid"); + ret = KRB5KRB_AP_ERR_MSG_TYPE; + goto out; + } + } else { + if (der_heim_oid_cmp(&contentType, oid_id_pkrkeydata()) != 0) { + krb5_set_error_string(context, "PKINIT: reply key, wrong oid"); + ret = KRB5KRB_AP_ERR_MSG_TYPE; + goto out; + } + } +#endif + + switch(type) { + case COMPAT_WIN2K: + ret = get_reply_key(context, &content, req_buffer, key); + if (ret != 0 && ctx->require_binding == 0) + ret = get_reply_key_win(context, &content, nonce, key); + break; + case COMPAT_IETF: + ret = get_reply_key(context, &content, req_buffer, key); + break; + } + if (ret) + goto out; + + /* XXX compare given etype with key->etype */ + + out: + if (host) + _krb5_pk_cert_free(host); + der_free_oid(&contentType); + krb5_data_free(&content); + + return ret; +} + +static krb5_error_code +pk_rd_pa_reply_dh(krb5_context context, + const heim_octet_string *indata, + const heim_oid *dataType, + const char *realm, + krb5_pk_init_ctx ctx, + krb5_enctype etype, + const krb5_krbhst_info *hi, + const DHNonce *c_n, + const DHNonce *k_n, + unsigned nonce, + PA_DATA *pa, + krb5_keyblock **key) +{ + unsigned char *p, *dh_gen_key = NULL; + struct krb5_pk_cert *host = NULL; + BIGNUM *kdc_dh_pubkey = NULL; + KDCDHKeyInfo kdc_dh_info; + heim_oid contentType = { 0, NULL }; + krb5_data content; + krb5_error_code ret; + int dh_gen_keylen; + size_t size; + + krb5_data_zero(&content); + memset(&kdc_dh_info, 0, sizeof(kdc_dh_info)); + + if (der_heim_oid_cmp(oid_id_pkcs7_signedData(), dataType)) { + krb5_set_error_string(context, "PKINIT: Invalid content type"); + return EINVAL; + } + + ret = _krb5_pk_verify_sign(context, + indata->data, + indata->length, + ctx->id, + &contentType, + &content, + &host); + if (ret) + goto out; + + /* make sure that it is the kdc's certificate */ + ret = pk_verify_host(context, realm, hi, ctx, host); + if (ret) + goto out; + + if (der_heim_oid_cmp(&contentType, oid_id_pkdhkeydata())) { + krb5_set_error_string(context, "pkinit - dh reply contains wrong oid"); + ret = KRB5KRB_AP_ERR_MSG_TYPE; + goto out; + } + + ret = decode_KDCDHKeyInfo(content.data, + content.length, + &kdc_dh_info, + &size); + + if (ret) { + krb5_set_error_string(context, "pkinit - " + "failed to decode KDC DH Key Info"); + goto out; + } + + if (kdc_dh_info.nonce != nonce) { + krb5_set_error_string(context, "PKINIT: DH nonce is wrong"); + ret = KRB5KRB_AP_ERR_MODIFIED; + goto out; + } + + if (kdc_dh_info.dhKeyExpiration) { + if (k_n == NULL) { + krb5_set_error_string(context, "pkinit; got key expiration " + "without server nonce"); + ret = KRB5KRB_ERR_GENERIC; + goto out; + } + if (c_n == NULL) { + krb5_set_error_string(context, "pkinit; got DH reuse but no " + "client nonce"); + ret = KRB5KRB_ERR_GENERIC; + goto out; + } + } else { + if (k_n) { + krb5_set_error_string(context, "pkinit: got server nonce " + "without key expiration"); + ret = KRB5KRB_ERR_GENERIC; + goto out; + } + c_n = NULL; + } + + + p = kdc_dh_info.subjectPublicKey.data; + size = (kdc_dh_info.subjectPublicKey.length + 7) / 8; + + { + DHPublicKey k; + ret = decode_DHPublicKey(p, size, &k, NULL); + if (ret) { + krb5_set_error_string(context, "pkinit: can't decode " + "without key expiration"); + goto out; + } + + kdc_dh_pubkey = integer_to_BN(context, "DHPublicKey", &k); + free_DHPublicKey(&k); + if (kdc_dh_pubkey == NULL) { + ret = KRB5KRB_ERR_GENERIC; + goto out; + } + } + + dh_gen_keylen = DH_size(ctx->dh); + size = BN_num_bytes(ctx->dh->p); + if (size < dh_gen_keylen) + size = dh_gen_keylen; + + dh_gen_key = malloc(size); + if (dh_gen_key == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + ret = ENOMEM; + goto out; + } + memset(dh_gen_key, 0, size - dh_gen_keylen); + + dh_gen_keylen = DH_compute_key(dh_gen_key + (size - dh_gen_keylen), + kdc_dh_pubkey, ctx->dh); + if (dh_gen_keylen == -1) { + krb5_set_error_string(context, + "PKINIT: Can't compute Diffie-Hellman key"); + ret = KRB5KRB_ERR_GENERIC; + goto out; + } + + *key = malloc (sizeof (**key)); + if (*key == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + ret = ENOMEM; + goto out; + } + + ret = _krb5_pk_octetstring2key(context, + etype, + dh_gen_key, dh_gen_keylen, + c_n, k_n, + *key); + if (ret) { + krb5_set_error_string(context, + "PKINIT: can't create key from DH key"); + free(*key); + *key = NULL; + goto out; + } + + out: + if (kdc_dh_pubkey) + BN_free(kdc_dh_pubkey); + if (dh_gen_key) { + memset(dh_gen_key, 0, DH_size(ctx->dh)); + free(dh_gen_key); + } + if (host) + _krb5_pk_cert_free(host); + if (content.data) + krb5_data_free(&content); + der_free_oid(&contentType); + free_KDCDHKeyInfo(&kdc_dh_info); + + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_pk_rd_pa_reply(krb5_context context, + const char *realm, + void *c, + krb5_enctype etype, + const krb5_krbhst_info *hi, + unsigned nonce, + const krb5_data *req_buffer, + PA_DATA *pa, + krb5_keyblock **key) +{ + krb5_pk_init_ctx ctx = c; + krb5_error_code ret; + size_t size; + + /* Check for IETF PK-INIT first */ + if (ctx->type == COMPAT_IETF) { + PA_PK_AS_REP rep; + heim_octet_string os, data; + heim_oid oid; + + if (pa->padata_type != KRB5_PADATA_PK_AS_REP) { + krb5_set_error_string(context, "PKINIT: wrong padata recv"); + return EINVAL; + } + + ret = decode_PA_PK_AS_REP(pa->padata_value.data, + pa->padata_value.length, + &rep, + &size); + if (ret) { + krb5_set_error_string(context, "Failed to decode pkinit AS rep"); + return ret; + } + + switch (rep.element) { + case choice_PA_PK_AS_REP_dhInfo: + os = rep.u.dhInfo.dhSignedData; + break; + case choice_PA_PK_AS_REP_encKeyPack: + os = rep.u.encKeyPack; + break; + default: + free_PA_PK_AS_REP(&rep); + krb5_set_error_string(context, "PKINIT: -27 reply " + "invalid content type"); + return EINVAL; + } + + ret = hx509_cms_unwrap_ContentInfo(&os, &oid, &data, NULL); + if (ret) { + free_PA_PK_AS_REP(&rep); + krb5_set_error_string(context, "PKINIT: failed to unwrap CI"); + return ret; + } + + switch (rep.element) { + case choice_PA_PK_AS_REP_dhInfo: + ret = pk_rd_pa_reply_dh(context, &data, &oid, realm, ctx, etype, hi, + ctx->clientDHNonce, + rep.u.dhInfo.serverDHNonce, + nonce, pa, key); + break; + case choice_PA_PK_AS_REP_encKeyPack: + ret = pk_rd_pa_reply_enckey(context, COMPAT_IETF, &data, &oid, realm, + ctx, etype, hi, nonce, req_buffer, pa, key); + break; + default: + krb5_abortx(context, "pk-init as-rep case not possible to happen"); + } + der_free_octet_string(&data); + der_free_oid(&oid); + free_PA_PK_AS_REP(&rep); + + } else if (ctx->type == COMPAT_WIN2K) { + PA_PK_AS_REP_Win2k w2krep; + + /* Check for Windows encoding of the AS-REP pa data */ + +#if 0 /* should this be ? */ + if (pa->padata_type != KRB5_PADATA_PK_AS_REP) { + krb5_set_error_string(context, "PKINIT: wrong padata recv"); + return EINVAL; + } +#endif + + memset(&w2krep, 0, sizeof(w2krep)); + + ret = decode_PA_PK_AS_REP_Win2k(pa->padata_value.data, + pa->padata_value.length, + &w2krep, + &size); + if (ret) { + krb5_set_error_string(context, "PKINIT: Failed decoding windows " + "pkinit reply %d", ret); + return ret; + } + + krb5_clear_error_string(context); + + switch (w2krep.element) { + case choice_PA_PK_AS_REP_Win2k_encKeyPack: { + heim_octet_string data; + heim_oid oid; + + ret = hx509_cms_unwrap_ContentInfo(&w2krep.u.encKeyPack, + &oid, &data, NULL); + free_PA_PK_AS_REP_Win2k(&w2krep); + if (ret) { + krb5_set_error_string(context, "PKINIT: failed to unwrap CI"); + return ret; + } + + ret = pk_rd_pa_reply_enckey(context, COMPAT_WIN2K, &data, &oid, realm, + ctx, etype, hi, nonce, req_buffer, pa, key); + der_free_octet_string(&data); + der_free_oid(&oid); + + break; + } + default: + free_PA_PK_AS_REP_Win2k(&w2krep); + krb5_set_error_string(context, "PKINIT: win2k reply invalid " + "content type"); + ret = EINVAL; + break; + } + + } else { + krb5_set_error_string(context, "PKINIT: unknown reply type"); + ret = EINVAL; + } + + return ret; +} + +struct prompter { + krb5_context context; + krb5_prompter_fct prompter; + void *prompter_data; +}; + +static int +hx_pass_prompter(void *data, const hx509_prompt *prompter) +{ + krb5_error_code ret; + krb5_prompt prompt; + krb5_data password_data; + struct prompter *p = data; + + password_data.data = prompter->reply.data; + password_data.length = prompter->reply.length; + + prompt.prompt = prompter->prompt; + prompt.hidden = hx509_prompt_hidden(prompter->type); + prompt.reply = &password_data; + + switch (prompter->type) { + case HX509_PROMPT_TYPE_INFO: + prompt.type = KRB5_PROMPT_TYPE_INFO; + break; + case HX509_PROMPT_TYPE_PASSWORD: + case HX509_PROMPT_TYPE_QUESTION: + default: + prompt.type = KRB5_PROMPT_TYPE_PASSWORD; + break; + } + + ret = (*p->prompter)(p->context, p->prompter_data, NULL, NULL, 1, &prompt); + if (ret) { + memset (prompter->reply.data, 0, prompter->reply.length); + return 1; + } + return 0; +} + + +void KRB5_LIB_FUNCTION +_krb5_pk_allow_proxy_certificate(struct krb5_pk_identity *id, + int boolean) +{ + hx509_verify_set_proxy_certificate(id->verify_ctx, boolean); +} + + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_pk_load_id(krb5_context context, + struct krb5_pk_identity **ret_id, + const char *user_id, + const char *anchor_id, + char * const *chain_list, + char * const *revoke_list, + krb5_prompter_fct prompter, + void *prompter_data, + char *password) +{ + struct krb5_pk_identity *id = NULL; + hx509_lock lock = NULL; + struct prompter p; + int ret; + + *ret_id = NULL; + + if (anchor_id == NULL) { + krb5_set_error_string(context, "PKINIT: No anchor given"); + return HEIM_PKINIT_NO_VALID_CA; + } + + if (user_id == NULL) { + krb5_set_error_string(context, + "PKINIT: No user certificate given"); + return HEIM_PKINIT_NO_PRIVATE_KEY; + } + + /* load cert */ + + id = calloc(1, sizeof(*id)); + if (id == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + ret = hx509_context_init(&id->hx509ctx); + if (ret) + goto out; + + ret = hx509_lock_init(id->hx509ctx, &lock); + if (password && password[0]) + hx509_lock_add_password(lock, password); + + if (prompter) { + p.context = context; + p.prompter = prompter; + p.prompter_data = prompter_data; + + ret = hx509_lock_set_prompter(lock, hx_pass_prompter, &p); + if (ret) + goto out; + } + + ret = hx509_certs_init(id->hx509ctx, user_id, 0, lock, &id->certs); + if (ret) { + _krb5_pk_copy_error(context, id->hx509ctx, ret, + "Failed to init cert certs"); + goto out; + } + + ret = hx509_certs_init(id->hx509ctx, anchor_id, 0, NULL, &id->anchors); + if (ret) { + _krb5_pk_copy_error(context, id->hx509ctx, ret, + "Failed to init anchors"); + goto out; + } + + ret = hx509_certs_init(id->hx509ctx, "MEMORY:pkinit-cert-chain", + 0, NULL, &id->certpool); + if (ret) { + _krb5_pk_copy_error(context, id->hx509ctx, ret, + "Failed to init chain"); + goto out; + } + + while (chain_list && *chain_list) { + ret = hx509_certs_append(id->hx509ctx, id->certpool, + NULL, *chain_list); + if (ret) { + _krb5_pk_copy_error(context, id->hx509ctx, ret, + "Failed to laod chain %s", + *chain_list); + goto out; + } + chain_list++; + } + + if (revoke_list) { + ret = hx509_revoke_init(id->hx509ctx, &id->revokectx); + if (ret) { + _krb5_pk_copy_error(context, id->hx509ctx, ret, + "Failed init revoke list"); + goto out; + } + + while (*revoke_list) { + ret = hx509_revoke_add_crl(id->hx509ctx, + id->revokectx, + *revoke_list); + if (ret) { + _krb5_pk_copy_error(context, id->hx509ctx, ret, + "Failed load revoke list"); + goto out; + } + revoke_list++; + } + } else + hx509_context_set_missing_revoke(id->hx509ctx, 1); + + ret = hx509_verify_init_ctx(id->hx509ctx, &id->verify_ctx); + if (ret) { + _krb5_pk_copy_error(context, id->hx509ctx, ret, + "Failed init verify context"); + goto out; + } + + hx509_verify_attach_anchors(id->verify_ctx, id->anchors); + hx509_verify_attach_revoke(id->verify_ctx, id->revokectx); + +out: + if (ret) { + hx509_verify_destroy_ctx(id->verify_ctx); + hx509_certs_free(&id->certs); + hx509_certs_free(&id->anchors); + hx509_certs_free(&id->certpool); + hx509_revoke_free(&id->revokectx); + hx509_context_free(&id->hx509ctx); + free(id); + } else + *ret_id = id; + + hx509_lock_free(lock); + + return ret; +} + +static krb5_error_code +select_dh_group(krb5_context context, DH *dh, unsigned long bits, + struct krb5_dh_moduli **moduli) +{ + const struct krb5_dh_moduli *m; + + if (bits == 0) { + m = moduli[1]; /* XXX */ + if (m == NULL) + m = moduli[0]; /* XXX */ + } else { + int i; + for (i = 0; moduli[i] != NULL; i++) { + if (bits < moduli[i]->bits) + break; + } + if (moduli[i] == NULL) { + krb5_set_error_string(context, + "Did not find a DH group parameter " + "matching requirement of %lu bits", + bits); + return EINVAL; + } + m = moduli[i]; + } + + dh->p = integer_to_BN(context, "p", &m->p); + if (dh->p == NULL) + return ENOMEM; + dh->g = integer_to_BN(context, "g", &m->g); + if (dh->g == NULL) + return ENOMEM; + dh->q = integer_to_BN(context, "q", &m->q); + if (dh->q == NULL) + return ENOMEM; + + return 0; +} + +#endif /* PKINIT */ + +static int +parse_integer(krb5_context context, char **p, const char *file, int lineno, + const char *name, heim_integer *integer) +{ + int ret; + char *p1; + p1 = strsep(p, " \t"); + if (p1 == NULL) { + krb5_set_error_string(context, "moduli file %s missing %s on line %d", + file, name, lineno); + return EINVAL; + } + ret = der_parse_hex_heim_integer(p1, integer); + if (ret) { + krb5_set_error_string(context, "moduli file %s failed parsing %s " + "on line %d", + file, name, lineno); + return ret; + } + + return 0; +} + +krb5_error_code +_krb5_parse_moduli_line(krb5_context context, + const char *file, + int lineno, + char *p, + struct krb5_dh_moduli **m) +{ + struct krb5_dh_moduli *m1; + char *p1; + int ret; + + *m = NULL; + + m1 = calloc(1, sizeof(*m1)); + if (m1 == NULL) { + krb5_set_error_string(context, "malloc - out of memory"); + return ENOMEM; + } + + while (isspace((unsigned char)*p)) + p++; + if (*p == '#') + return 0; + ret = EINVAL; + + p1 = strsep(&p, " \t"); + if (p1 == NULL) { + krb5_set_error_string(context, "moduli file %s missing name " + "on line %d", file, lineno); + goto out; + } + m1->name = strdup(p1); + if (p1 == NULL) { + krb5_set_error_string(context, "malloc - out of memeory"); + ret = ENOMEM; + goto out; + } + + p1 = strsep(&p, " \t"); + if (p1 == NULL) { + krb5_set_error_string(context, "moduli file %s missing bits on line %d", + file, lineno); + goto out; + } + + m1->bits = atoi(p1); + if (m1->bits == 0) { + krb5_set_error_string(context, "moduli file %s have un-parsable " + "bits on line %d", file, lineno); + goto out; + } + + ret = parse_integer(context, &p, file, lineno, "p", &m1->p); + if (ret) + goto out; + ret = parse_integer(context, &p, file, lineno, "g", &m1->g); + if (ret) + goto out; + ret = parse_integer(context, &p, file, lineno, "q", &m1->q); + if (ret) + goto out; + + *m = m1; + + return 0; +out: + free(m1->name); + der_free_heim_integer(&m1->p); + der_free_heim_integer(&m1->g); + der_free_heim_integer(&m1->q); + free(m1); + return ret; +} + +void +_krb5_free_moduli(struct krb5_dh_moduli **moduli) +{ + int i; + for (i = 0; moduli[i] != NULL; i++) { + free(moduli[i]->name); + der_free_heim_integer(&moduli[i]->p); + der_free_heim_integer(&moduli[i]->g); + der_free_heim_integer(&moduli[i]->q); + free(moduli[i]); + } + free(moduli); +} + +static const char *default_moduli_RFC2412_MODP_group2 = + /* name */ + "RFC2412-MODP-group2 " + /* bits */ + "1024 " + /* p */ + "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1" + "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD" + "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245" + "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED" + "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381" + "FFFFFFFF" "FFFFFFFF " + /* g */ + "02 " + /* q */ + "7FFFFFFF" "FFFFFFFF" "E487ED51" "10B4611A" "62633145" "C06E0E68" + "94812704" "4533E63A" "0105DF53" "1D89CD91" "28A5043C" "C71A026E" + "F7CA8CD9" "E69D218D" "98158536" "F92F8A1B" "A7F09AB6" "B6A8E122" + "F242DABB" "312F3F63" "7A262174" "D31BF6B5" "85FFAE5B" "7A035BF6" + "F71C35FD" "AD44CFD2" "D74F9208" "BE258FF3" "24943328" "F67329C0" + "FFFFFFFF" "FFFFFFFF"; + +static const char *default_moduli_rfc3526_MODP_group14 = + /* name */ + "rfc3526-MODP-group14 " + /* bits */ + "1760 " + /* p */ + "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1" + "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD" + "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245" + "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED" + "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE45B3D" + "C2007CB8" "A163BF05" "98DA4836" "1C55D39A" "69163FA8" "FD24CF5F" + "83655D23" "DCA3AD96" "1C62F356" "208552BB" "9ED52907" "7096966D" + "670C354E" "4ABC9804" "F1746C08" "CA18217C" "32905E46" "2E36CE3B" + "E39E772C" "180E8603" "9B2783A2" "EC07A28F" "B5C55DF0" "6F4C52C9" + "DE2BCBF6" "95581718" "3995497C" "EA956AE5" "15D22618" "98FA0510" + "15728E5A" "8AACAA68" "FFFFFFFF" "FFFFFFFF " + /* g */ + "02 " + /* q */ + "7FFFFFFF" "FFFFFFFF" "E487ED51" "10B4611A" "62633145" "C06E0E68" + "94812704" "4533E63A" "0105DF53" "1D89CD91" "28A5043C" "C71A026E" + "F7CA8CD9" "E69D218D" "98158536" "F92F8A1B" "A7F09AB6" "B6A8E122" + "F242DABB" "312F3F63" "7A262174" "D31BF6B5" "85FFAE5B" "7A035BF6" + "F71C35FD" "AD44CFD2" "D74F9208" "BE258FF3" "24943328" "F6722D9E" + "E1003E5C" "50B1DF82" "CC6D241B" "0E2AE9CD" "348B1FD4" "7E9267AF" + "C1B2AE91" "EE51D6CB" "0E3179AB" "1042A95D" "CF6A9483" "B84B4B36" + "B3861AA7" "255E4C02" "78BA3604" "650C10BE" "19482F23" "171B671D" + "F1CF3B96" "0C074301" "CD93C1D1" "7603D147" "DAE2AEF8" "37A62964" + "EF15E5FB" "4AAC0B8C" "1CCAA4BE" "754AB572" "8AE9130C" "4C7D0288" + "0AB9472D" "45565534" "7FFFFFFF" "FFFFFFFF"; + +krb5_error_code +_krb5_parse_moduli(krb5_context context, const char *file, + struct krb5_dh_moduli ***moduli) +{ + /* name bits P G Q */ + krb5_error_code ret; + struct krb5_dh_moduli **m = NULL, **m2; + char buf[4096]; + FILE *f; + int lineno = 0, n = 0; + + *moduli = NULL; + + m = calloc(1, sizeof(m[0]) * 3); + if (m == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + strlcpy(buf, default_moduli_rfc3526_MODP_group14, sizeof(buf)); + ret = _krb5_parse_moduli_line(context, "builtin", 1, buf, &m[0]); + if (ret) { + _krb5_free_moduli(m); + return ret; + } + n++; + + strlcpy(buf, default_moduli_RFC2412_MODP_group2, sizeof(buf)); + ret = _krb5_parse_moduli_line(context, "builtin", 1, buf, &m[1]); + if (ret) { + _krb5_free_moduli(m); + return ret; + } + n++; + + + if (file == NULL) + file = MODULI_FILE; + + f = fopen(file, "r"); + if (f == NULL) { + *moduli = m; + return 0; + } + + while(fgets(buf, sizeof(buf), f) != NULL) { + struct krb5_dh_moduli *element; + + buf[strcspn(buf, "\n")] = '\0'; + lineno++; + + m2 = realloc(m, (n + 2) * sizeof(m[0])); + if (m2 == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + _krb5_free_moduli(m); + return ENOMEM; + } + m = m2; + + m[n] = NULL; + + ret = _krb5_parse_moduli_line(context, file, lineno, buf, &element); + if (ret) { + _krb5_free_moduli(m); + return ret; + } + if (element == NULL) + continue; + + m[n] = element; + m[n + 1] = NULL; + n++; + } + *moduli = m; + return 0; +} + +krb5_error_code +_krb5_dh_group_ok(krb5_context context, unsigned long bits, + heim_integer *p, heim_integer *g, heim_integer *q, + struct krb5_dh_moduli **moduli, + char **name) +{ + int i; + + if (name) + *name = NULL; + + for (i = 0; moduli[i] != NULL; i++) { + if (der_heim_integer_cmp(&moduli[i]->g, g) == 0 && + der_heim_integer_cmp(&moduli[i]->p, p) == 0 && + (q == NULL || der_heim_integer_cmp(&moduli[i]->q, q) == 0)) + { + if (bits && bits > moduli[i]->bits) { + krb5_set_error_string(context, "PKINIT: DH group parameter %s " + "no accepted, not enough bits generated", + moduli[i]->name); + return KRB5_KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED; + } + if (name) + *name = strdup(moduli[i]->name); + return 0; + } + } + krb5_set_error_string(context, "PKINIT: DH group parameter no ok"); + return KRB5_KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED; +} + +void KRB5_LIB_FUNCTION +_krb5_get_init_creds_opt_free_pkinit(krb5_get_init_creds_opt *opt) +{ +#ifdef PKINIT + krb5_pk_init_ctx ctx; + + if (opt->opt_private == NULL || opt->opt_private->pk_init_ctx == NULL) + return; + ctx = opt->opt_private->pk_init_ctx; + if (ctx->dh) + DH_free(ctx->dh); + ctx->dh = NULL; + if (ctx->id) { + hx509_verify_destroy_ctx(ctx->id->verify_ctx); + hx509_certs_free(&ctx->id->certs); + hx509_certs_free(&ctx->id->anchors); + hx509_certs_free(&ctx->id->certpool); + hx509_context_free(&ctx->id->hx509ctx); + + if (ctx->clientDHNonce) { + krb5_free_data(NULL, ctx->clientDHNonce); + ctx->clientDHNonce = NULL; + } + if (ctx->m) + _krb5_free_moduli(ctx->m); + free(ctx->id); + ctx->id = NULL; + } + free(opt->opt_private->pk_init_ctx); + opt->opt_private->pk_init_ctx = NULL; +#endif +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_pkinit(krb5_context context, + krb5_get_init_creds_opt *opt, + krb5_principal principal, + const char *user_id, + const char *x509_anchors, + char * const * pool, + char * const * pki_revoke, + int flags, + krb5_prompter_fct prompter, + void *prompter_data, + char *password) +{ +#ifdef PKINIT + krb5_error_code ret; + char *anchors = NULL; + + if (opt->opt_private == NULL) { + krb5_set_error_string(context, "PKINIT: on non extendable opt"); + return EINVAL; + } + + opt->opt_private->pk_init_ctx = + calloc(1, sizeof(*opt->opt_private->pk_init_ctx)); + if (opt->opt_private->pk_init_ctx == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + opt->opt_private->pk_init_ctx->dh = NULL; + opt->opt_private->pk_init_ctx->id = NULL; + opt->opt_private->pk_init_ctx->clientDHNonce = NULL; + opt->opt_private->pk_init_ctx->require_binding = 0; + opt->opt_private->pk_init_ctx->require_eku = 1; + opt->opt_private->pk_init_ctx->require_krbtgt_otherName = 1; + opt->opt_private->pk_init_ctx->peer = NULL; + + /* XXX implement krb5_appdefault_strings */ + if (pool == NULL) + pool = krb5_config_get_strings(context, NULL, + "appdefaults", + "pkinit_pool", + NULL); + + if (pki_revoke == NULL) + pki_revoke = krb5_config_get_strings(context, NULL, + "appdefaults", + "pkinit_revoke", + NULL); + + if (x509_anchors == NULL) { + krb5_appdefault_string(context, "kinit", + krb5_principal_get_realm(context, principal), + "pkinit_anchors", NULL, &anchors); + x509_anchors = anchors; + } + + ret = _krb5_pk_load_id(context, + &opt->opt_private->pk_init_ctx->id, + user_id, + x509_anchors, + pool, + pki_revoke, + prompter, + prompter_data, + password); + if (ret) { + free(opt->opt_private->pk_init_ctx); + opt->opt_private->pk_init_ctx = NULL; + return ret; + } + + if ((flags & 2) == 0) { + const char *moduli_file; + unsigned long dh_min_bits; + + moduli_file = krb5_config_get_string(context, NULL, + "libdefaults", + "moduli", + NULL); + + dh_min_bits = + krb5_config_get_int_default(context, NULL, 0, + "libdefaults", + "pkinit_dh_min_bits", + NULL); + + ret = _krb5_parse_moduli(context, moduli_file, + &opt->opt_private->pk_init_ctx->m); + if (ret) { + _krb5_get_init_creds_opt_free_pkinit(opt); + return ret; + } + + opt->opt_private->pk_init_ctx->dh = DH_new(); + if (opt->opt_private->pk_init_ctx->dh == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + _krb5_get_init_creds_opt_free_pkinit(opt); + return ENOMEM; + } + + ret = select_dh_group(context, opt->opt_private->pk_init_ctx->dh, + dh_min_bits, + opt->opt_private->pk_init_ctx->m); + if (ret) { + _krb5_get_init_creds_opt_free_pkinit(opt); + return ret; + } + + if (DH_generate_key(opt->opt_private->pk_init_ctx->dh) != 1) { + krb5_set_error_string(context, "pkinit: failed to generate DH key"); + _krb5_get_init_creds_opt_free_pkinit(opt); + return ENOMEM; + } + } + + return 0; +#else + krb5_set_error_string(context, "no support for PKINIT compiled in"); + return EINVAL; +#endif +} + +/* + * + */ + +static void +_krb5_pk_copy_error(krb5_context context, + hx509_context hx509ctx, + int hxret, + const char *fmt, + ...) +{ + va_list va; + char *s, *f; + + va_start(va, fmt); + vasprintf(&f, fmt, va); + va_end(va); + if (f == NULL) { + krb5_clear_error_string(context); + return; + } + + s = hx509_get_error_string(hx509ctx, hxret); + if (s == NULL) { + krb5_clear_error_string(context); + free(f); + return; + } + krb5_set_error_string(context, "%s: %s", f, s); + free(s); + free(f); +} diff --git a/lib/krb5/plugin.c b/lib/krb5/plugin.c new file mode 100644 index 0000000..bae2849 --- /dev/null +++ b/lib/krb5/plugin.c @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" +RCSID("$Id: plugin.c 22033 2007-11-10 10:39:47Z lha $"); +#ifdef HAVE_DLFCN_H +#include <dlfcn.h> +#endif +#include <dirent.h> + +struct krb5_plugin { + void *symbol; + void *dsohandle; + struct krb5_plugin *next; +}; + +struct plugin { + enum krb5_plugin_type type; + void *name; + void *symbol; + struct plugin *next; +}; + +static HEIMDAL_MUTEX plugin_mutex = HEIMDAL_MUTEX_INITIALIZER; +static struct plugin *registered = NULL; + +static const char *plugin_dir = LIBDIR "/plugin/krb5"; + +/* + * + */ + +void * +_krb5_plugin_get_symbol(struct krb5_plugin *p) +{ + return p->symbol; +} + +struct krb5_plugin * +_krb5_plugin_get_next(struct krb5_plugin *p) +{ + return p->next; +} + +/* + * + */ + +#ifdef HAVE_DLOPEN + +static krb5_error_code +loadlib(krb5_context context, + enum krb5_plugin_type type, + const char *name, + const char *lib, + struct krb5_plugin **e) +{ + *e = calloc(1, sizeof(**e)); + if (*e == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + +#ifndef RTLD_LAZY +#define RTLD_LAZY 0 +#endif + + (*e)->dsohandle = dlopen(lib, RTLD_LAZY); + if ((*e)->dsohandle == NULL) { + free(*e); + *e = NULL; + krb5_set_error_string(context, "Failed to load %s: %s", + lib, dlerror()); + return ENOMEM; + } + + /* dlsym doesn't care about the type */ + (*e)->symbol = dlsym((*e)->dsohandle, name); + if ((*e)->symbol == NULL) { + dlclose((*e)->dsohandle); + free(*e); + krb5_clear_error_string(context); + return ENOMEM; + } + + return 0; +} +#endif /* HAVE_DLOPEN */ + +/** + * Register a plugin symbol name of specific type. + * @param context a Keberos context + * @param type type of plugin symbol + * @param name name of plugin symbol + * @param symbol a pointer to the named symbol + * @return In case of error a non zero error com_err error is returned + * and the Kerberos error string is set. + * + * @ingroup krb5_support + */ + +krb5_error_code +krb5_plugin_register(krb5_context context, + enum krb5_plugin_type type, + const char *name, + void *symbol) +{ + struct plugin *e; + + e = calloc(1, sizeof(*e)); + if (e == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + e->type = type; + e->name = strdup(name); + if (e->name == NULL) { + free(e); + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + e->symbol = symbol; + + HEIMDAL_MUTEX_lock(&plugin_mutex); + e->next = registered; + registered = e; + HEIMDAL_MUTEX_unlock(&plugin_mutex); + + return 0; +} + +krb5_error_code +_krb5_plugin_find(krb5_context context, + enum krb5_plugin_type type, + const char *name, + struct krb5_plugin **list) +{ + struct krb5_plugin *e; + struct plugin *p; + krb5_error_code ret; + char *sysdirs[2] = { NULL, NULL }; + char **dirs = NULL, **di; + struct dirent *entry; + char *path; + DIR *d = NULL; + + *list = NULL; + + HEIMDAL_MUTEX_lock(&plugin_mutex); + + for (p = registered; p != NULL; p = p->next) { + if (p->type != type || strcmp(p->name, name) != 0) + continue; + + e = calloc(1, sizeof(*e)); + if (e == NULL) { + HEIMDAL_MUTEX_unlock(&plugin_mutex); + krb5_set_error_string(context, "out of memory"); + ret = ENOMEM; + goto out; + } + e->symbol = p->symbol; + e->dsohandle = NULL; + e->next = *list; + *list = e; + } + HEIMDAL_MUTEX_unlock(&plugin_mutex); + +#ifdef HAVE_DLOPEN + + dirs = krb5_config_get_strings(context, NULL, "libdefaults", + "plugin_dir", NULL); + if (dirs == NULL) { + sysdirs[0] = rk_UNCONST(plugin_dir); + dirs = sysdirs; + } + + for (di = dirs; *di != NULL; di++) { + + d = opendir(*di); + if (d == NULL) + continue; + + while ((entry = readdir(d)) != NULL) { + asprintf(&path, "%s/%s", *di, entry->d_name); + if (path == NULL) { + krb5_set_error_string(context, "out of memory"); + ret = ENOMEM; + goto out; + } + ret = loadlib(context, type, name, path, &e); + free(path); + if (ret) + continue; + + e->next = *list; + *list = e; + } + closedir(d); + } + if (dirs != sysdirs) + krb5_config_free_strings(dirs); +#endif /* HAVE_DLOPEN */ + + if (*list == NULL) { + krb5_set_error_string(context, "Did not find a plugin for %s", name); + return ENOENT; + } + + return 0; + +out: + if (dirs && dirs != sysdirs) + krb5_config_free_strings(dirs); + if (d) + closedir(d); + _krb5_plugin_free(*list); + *list = NULL; + + return ret; +} + +void +_krb5_plugin_free(struct krb5_plugin *list) +{ + struct krb5_plugin *next; + while (list) { + next = list->next; + if (list->dsohandle) + dlclose(list->dsohandle); + free(list); + list = next; + } +} diff --git a/lib/krb5/principal.c b/lib/krb5/principal.c new file mode 100644 index 0000000..8d9c880 --- /dev/null +++ b/lib/krb5/principal.c @@ -0,0 +1,1254 @@ +/* + * Copyright (c) 1997-2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" +#ifdef HAVE_RES_SEARCH +#define USE_RESOLVER +#endif +#ifdef HAVE_ARPA_NAMESER_H +#include <arpa/nameser.h> +#endif +#include <fnmatch.h> +#include "resolve.h" + +RCSID("$Id: principal.c 21741 2007-07-31 16:00:37Z lha $"); + +#define princ_num_comp(P) ((P)->name.name_string.len) +#define princ_type(P) ((P)->name.name_type) +#define princ_comp(P) ((P)->name.name_string.val) +#define princ_ncomp(P, N) ((P)->name.name_string.val[(N)]) +#define princ_realm(P) ((P)->realm) + +void KRB5_LIB_FUNCTION +krb5_free_principal(krb5_context context, + krb5_principal p) +{ + if(p){ + free_Principal(p); + free(p); + } +} + +void KRB5_LIB_FUNCTION +krb5_principal_set_type(krb5_context context, + krb5_principal principal, + int type) +{ + princ_type(principal) = type; +} + +int KRB5_LIB_FUNCTION +krb5_principal_get_type(krb5_context context, + krb5_const_principal principal) +{ + return princ_type(principal); +} + +const char* KRB5_LIB_FUNCTION +krb5_principal_get_realm(krb5_context context, + krb5_const_principal principal) +{ + return princ_realm(principal); +} + +const char* KRB5_LIB_FUNCTION +krb5_principal_get_comp_string(krb5_context context, + krb5_const_principal principal, + unsigned int component) +{ + if(component >= princ_num_comp(principal)) + return NULL; + return princ_ncomp(principal, component); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_parse_name_flags(krb5_context context, + const char *name, + int flags, + krb5_principal *principal) +{ + krb5_error_code ret; + heim_general_string *comp; + heim_general_string realm = NULL; + int ncomp; + + const char *p; + char *q; + char *s; + char *start; + + int n; + char c; + int got_realm = 0; + int first_at = 1; + int enterprise = (flags & KRB5_PRINCIPAL_PARSE_ENTERPRISE); + + *principal = NULL; + +#define RFLAGS (KRB5_PRINCIPAL_PARSE_NO_REALM|KRB5_PRINCIPAL_PARSE_MUST_REALM) + + if ((flags & RFLAGS) == RFLAGS) { + krb5_set_error_string(context, "Can't require both realm and " + "no realm at the same time"); + return KRB5_ERR_NO_SERVICE; + } +#undef RFLAGS + + /* count number of component, + * enterprise names only have one component + */ + ncomp = 1; + if (!enterprise) { + for(p = name; *p; p++){ + if(*p=='\\'){ + if(!p[1]) { + krb5_set_error_string (context, + "trailing \\ in principal name"); + return KRB5_PARSE_MALFORMED; + } + p++; + } else if(*p == '/') + ncomp++; + else if(*p == '@') + break; + } + } + comp = calloc(ncomp, sizeof(*comp)); + if (comp == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + + n = 0; + p = start = q = s = strdup(name); + if (start == NULL) { + free (comp); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + while(*p){ + c = *p++; + if(c == '\\'){ + c = *p++; + if(c == 'n') + c = '\n'; + else if(c == 't') + c = '\t'; + else if(c == 'b') + c = '\b'; + else if(c == '0') + c = '\0'; + else if(c == '\0') { + krb5_set_error_string (context, + "trailing \\ in principal name"); + ret = KRB5_PARSE_MALFORMED; + goto exit; + } + }else if(enterprise && first_at) { + if (c == '@') + first_at = 0; + }else if((c == '/' && !enterprise) || c == '@'){ + if(got_realm){ + krb5_set_error_string (context, + "part after realm in principal name"); + ret = KRB5_PARSE_MALFORMED; + goto exit; + }else{ + comp[n] = malloc(q - start + 1); + if (comp[n] == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + ret = ENOMEM; + goto exit; + } + memcpy(comp[n], start, q - start); + comp[n][q - start] = 0; + n++; + } + if(c == '@') + got_realm = 1; + start = q; + continue; + } + if(got_realm && (c == ':' || c == '/' || c == '\0')) { + krb5_set_error_string (context, + "part after realm in principal name"); + ret = KRB5_PARSE_MALFORMED; + goto exit; + } + *q++ = c; + } + if(got_realm){ + if (flags & KRB5_PRINCIPAL_PARSE_NO_REALM) { + krb5_set_error_string (context, "realm found in 'short' principal " + "expected to be without one"); + ret = KRB5_PARSE_MALFORMED; + goto exit; + } + realm = malloc(q - start + 1); + if (realm == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + ret = ENOMEM; + goto exit; + } + memcpy(realm, start, q - start); + realm[q - start] = 0; + }else{ + if (flags & KRB5_PRINCIPAL_PARSE_MUST_REALM) { + krb5_set_error_string (context, "realm NOT found in principal " + "expected to be with one"); + ret = KRB5_PARSE_MALFORMED; + goto exit; + } else if (flags & KRB5_PRINCIPAL_PARSE_NO_REALM) { + realm = NULL; + } else { + ret = krb5_get_default_realm (context, &realm); + if (ret) + goto exit; + } + + comp[n] = malloc(q - start + 1); + if (comp[n] == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + ret = ENOMEM; + goto exit; + } + memcpy(comp[n], start, q - start); + comp[n][q - start] = 0; + n++; + } + *principal = malloc(sizeof(**principal)); + if (*principal == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + ret = ENOMEM; + goto exit; + } + if (enterprise) + (*principal)->name.name_type = KRB5_NT_ENTERPRISE_PRINCIPAL; + else + (*principal)->name.name_type = KRB5_NT_PRINCIPAL; + (*principal)->name.name_string.val = comp; + princ_num_comp(*principal) = n; + (*principal)->realm = realm; + free(s); + return 0; +exit: + while(n>0){ + free(comp[--n]); + } + free(comp); + free(realm); + free(s); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_parse_name(krb5_context context, + const char *name, + krb5_principal *principal) +{ + return krb5_parse_name_flags(context, name, 0, principal); +} + +static const char quotable_chars[] = " \n\t\b\\/@"; +static const char replace_chars[] = " ntb\\/@"; +static const char nq_chars[] = " \\/@"; + +#define add_char(BASE, INDEX, LEN, C) do { if((INDEX) < (LEN)) (BASE)[(INDEX)++] = (C); }while(0); + +static size_t +quote_string(const char *s, char *out, size_t idx, size_t len, int display) +{ + const char *p, *q; + for(p = s; *p && idx < len; p++){ + q = strchr(quotable_chars, *p); + if (q && display) { + add_char(out, idx, len, replace_chars[q - quotable_chars]); + } else if (q) { + add_char(out, idx, len, '\\'); + add_char(out, idx, len, replace_chars[q - quotable_chars]); + }else + add_char(out, idx, len, *p); + } + if(idx < len) + out[idx] = '\0'; + return idx; +} + + +static krb5_error_code +unparse_name_fixed(krb5_context context, + krb5_const_principal principal, + char *name, + size_t len, + int flags) +{ + size_t idx = 0; + int i; + int short_form = (flags & KRB5_PRINCIPAL_UNPARSE_SHORT) != 0; + int no_realm = (flags & KRB5_PRINCIPAL_UNPARSE_NO_REALM) != 0; + int display = (flags & KRB5_PRINCIPAL_UNPARSE_DISPLAY) != 0; + + if (!no_realm && princ_realm(principal) == NULL) { + krb5_set_error_string(context, "Realm missing from principal, " + "can't unparse"); + return ERANGE; + } + + for(i = 0; i < princ_num_comp(principal); i++){ + if(i) + add_char(name, idx, len, '/'); + idx = quote_string(princ_ncomp(principal, i), name, idx, len, display); + if(idx == len) { + krb5_set_error_string(context, "Out of space printing principal"); + return ERANGE; + } + } + /* add realm if different from default realm */ + if(short_form && !no_realm) { + krb5_realm r; + krb5_error_code ret; + ret = krb5_get_default_realm(context, &r); + if(ret) + return ret; + if(strcmp(princ_realm(principal), r) != 0) + short_form = 0; + free(r); + } + if(!short_form && !no_realm) { + add_char(name, idx, len, '@'); + idx = quote_string(princ_realm(principal), name, idx, len, display); + if(idx == len) { + krb5_set_error_string(context, + "Out of space printing realm of principal"); + return ERANGE; + } + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_unparse_name_fixed(krb5_context context, + krb5_const_principal principal, + char *name, + size_t len) +{ + return unparse_name_fixed(context, principal, name, len, 0); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_unparse_name_fixed_short(krb5_context context, + krb5_const_principal principal, + char *name, + size_t len) +{ + return unparse_name_fixed(context, principal, name, len, + KRB5_PRINCIPAL_UNPARSE_SHORT); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_unparse_name_fixed_flags(krb5_context context, + krb5_const_principal principal, + int flags, + char *name, + size_t len) +{ + return unparse_name_fixed(context, principal, name, len, flags); +} + +static krb5_error_code +unparse_name(krb5_context context, + krb5_const_principal principal, + char **name, + int flags) +{ + size_t len = 0, plen; + int i; + krb5_error_code ret; + /* count length */ + if (princ_realm(principal)) { + plen = strlen(princ_realm(principal)); + + if(strcspn(princ_realm(principal), quotable_chars) == plen) + len += plen; + else + len += 2*plen; + len++; /* '@' */ + } + for(i = 0; i < princ_num_comp(principal); i++){ + plen = strlen(princ_ncomp(principal, i)); + if(strcspn(princ_ncomp(principal, i), quotable_chars) == plen) + len += plen; + else + len += 2*plen; + len++; + } + len++; /* '\0' */ + *name = malloc(len); + if(*name == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + ret = unparse_name_fixed(context, principal, *name, len, flags); + if(ret) { + free(*name); + *name = NULL; + } + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_unparse_name(krb5_context context, + krb5_const_principal principal, + char **name) +{ + return unparse_name(context, principal, name, 0); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_unparse_name_flags(krb5_context context, + krb5_const_principal principal, + int flags, + char **name) +{ + return unparse_name(context, principal, name, flags); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_unparse_name_short(krb5_context context, + krb5_const_principal principal, + char **name) +{ + return unparse_name(context, principal, name, KRB5_PRINCIPAL_UNPARSE_SHORT); +} + +#if 0 /* not implemented */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_unparse_name_ext(krb5_context context, + krb5_const_principal principal, + char **name, + size_t *size) +{ + krb5_abortx(context, "unimplemented krb5_unparse_name_ext called"); +} + +#endif + +krb5_realm * KRB5_LIB_FUNCTION +krb5_princ_realm(krb5_context context, + krb5_principal principal) +{ + return &princ_realm(principal); +} + + +void KRB5_LIB_FUNCTION +krb5_princ_set_realm(krb5_context context, + krb5_principal principal, + krb5_realm *realm) +{ + princ_realm(principal) = *realm; +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_build_principal(krb5_context context, + krb5_principal *principal, + int rlen, + krb5_const_realm realm, + ...) +{ + krb5_error_code ret; + va_list ap; + va_start(ap, realm); + ret = krb5_build_principal_va(context, principal, rlen, realm, ap); + va_end(ap); + return ret; +} + +static krb5_error_code +append_component(krb5_context context, krb5_principal p, + const char *comp, + size_t comp_len) +{ + heim_general_string *tmp; + size_t len = princ_num_comp(p); + + tmp = realloc(princ_comp(p), (len + 1) * sizeof(*tmp)); + if(tmp == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + princ_comp(p) = tmp; + princ_ncomp(p, len) = malloc(comp_len + 1); + if (princ_ncomp(p, len) == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + memcpy (princ_ncomp(p, len), comp, comp_len); + princ_ncomp(p, len)[comp_len] = '\0'; + princ_num_comp(p)++; + return 0; +} + +static void +va_ext_princ(krb5_context context, krb5_principal p, va_list ap) +{ + while(1){ + const char *s; + int len; + len = va_arg(ap, int); + if(len == 0) + break; + s = va_arg(ap, const char*); + append_component(context, p, s, len); + } +} + +static void +va_princ(krb5_context context, krb5_principal p, va_list ap) +{ + while(1){ + const char *s; + s = va_arg(ap, const char*); + if(s == NULL) + break; + append_component(context, p, s, strlen(s)); + } +} + + +static krb5_error_code +build_principal(krb5_context context, + krb5_principal *principal, + int rlen, + krb5_const_realm realm, + void (*func)(krb5_context, krb5_principal, va_list), + va_list ap) +{ + krb5_principal p; + + p = calloc(1, sizeof(*p)); + if (p == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + princ_type(p) = KRB5_NT_PRINCIPAL; + + princ_realm(p) = strdup(realm); + if(p->realm == NULL){ + free(p); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + + (*func)(context, p, ap); + *principal = p; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_make_principal(krb5_context context, + krb5_principal *principal, + krb5_const_realm realm, + ...) +{ + krb5_error_code ret; + krb5_realm r = NULL; + va_list ap; + if(realm == NULL) { + ret = krb5_get_default_realm(context, &r); + if(ret) + return ret; + realm = r; + } + va_start(ap, realm); + ret = krb5_build_principal_va(context, principal, strlen(realm), realm, ap); + va_end(ap); + if(r) + free(r); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_build_principal_va(krb5_context context, + krb5_principal *principal, + int rlen, + krb5_const_realm realm, + va_list ap) +{ + return build_principal(context, principal, rlen, realm, va_princ, ap); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_build_principal_va_ext(krb5_context context, + krb5_principal *principal, + int rlen, + krb5_const_realm realm, + va_list ap) +{ + return build_principal(context, principal, rlen, realm, va_ext_princ, ap); +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_build_principal_ext(krb5_context context, + krb5_principal *principal, + int rlen, + krb5_const_realm realm, + ...) +{ + krb5_error_code ret; + va_list ap; + va_start(ap, realm); + ret = krb5_build_principal_va_ext(context, principal, rlen, realm, ap); + va_end(ap); + return ret; +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_principal(krb5_context context, + krb5_const_principal inprinc, + krb5_principal *outprinc) +{ + krb5_principal p = malloc(sizeof(*p)); + if (p == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + if(copy_Principal(inprinc, p)) { + free(p); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + *outprinc = p; + return 0; +} + +/* + * return TRUE iff princ1 == princ2 (without considering the realm) + */ + +krb5_boolean KRB5_LIB_FUNCTION +krb5_principal_compare_any_realm(krb5_context context, + krb5_const_principal princ1, + krb5_const_principal princ2) +{ + int i; + if(princ_num_comp(princ1) != princ_num_comp(princ2)) + return FALSE; + for(i = 0; i < princ_num_comp(princ1); i++){ + if(strcmp(princ_ncomp(princ1, i), princ_ncomp(princ2, i)) != 0) + return FALSE; + } + return TRUE; +} + +/* + * return TRUE iff princ1 == princ2 + */ + +krb5_boolean KRB5_LIB_FUNCTION +krb5_principal_compare(krb5_context context, + krb5_const_principal princ1, + krb5_const_principal princ2) +{ + if(!krb5_realm_compare(context, princ1, princ2)) + return FALSE; + return krb5_principal_compare_any_realm(context, princ1, princ2); +} + +/* + * return TRUE iff realm(princ1) == realm(princ2) + */ + +krb5_boolean KRB5_LIB_FUNCTION +krb5_realm_compare(krb5_context context, + krb5_const_principal princ1, + krb5_const_principal princ2) +{ + return strcmp(princ_realm(princ1), princ_realm(princ2)) == 0; +} + +/* + * return TRUE iff princ matches pattern + */ + +krb5_boolean KRB5_LIB_FUNCTION +krb5_principal_match(krb5_context context, + krb5_const_principal princ, + krb5_const_principal pattern) +{ + int i; + if(princ_num_comp(princ) != princ_num_comp(pattern)) + return FALSE; + if(fnmatch(princ_realm(pattern), princ_realm(princ), 0) != 0) + return FALSE; + for(i = 0; i < princ_num_comp(princ); i++){ + if(fnmatch(princ_ncomp(pattern, i), princ_ncomp(princ, i), 0) != 0) + return FALSE; + } + return TRUE; +} + + +static struct v4_name_convert { + const char *from; + const char *to; +} default_v4_name_convert[] = { + { "ftp", "ftp" }, + { "hprop", "hprop" }, + { "pop", "pop" }, + { "imap", "imap" }, + { "rcmd", "host" }, + { "smtp", "smtp" }, + { NULL, NULL } +}; + +/* + * return the converted instance name of `name' in `realm'. + * look in the configuration file and then in the default set above. + * return NULL if no conversion is appropriate. + */ + +static const char* +get_name_conversion(krb5_context context, const char *realm, const char *name) +{ + struct v4_name_convert *q; + const char *p; + + p = krb5_config_get_string(context, NULL, "realms", realm, + "v4_name_convert", "host", name, NULL); + if(p == NULL) + p = krb5_config_get_string(context, NULL, "libdefaults", + "v4_name_convert", "host", name, NULL); + if(p) + return p; + + /* XXX should be possible to override default list */ + p = krb5_config_get_string(context, NULL, + "realms", + realm, + "v4_name_convert", + "plain", + name, + NULL); + if(p) + return NULL; + p = krb5_config_get_string(context, NULL, + "libdefaults", + "v4_name_convert", + "plain", + name, + NULL); + if(p) + return NULL; + for(q = default_v4_name_convert; q->from; q++) + if(strcmp(q->from, name) == 0) + return q->to; + return NULL; +} + +/* + * convert the v4 principal `name.instance@realm' to a v5 principal in `princ'. + * if `resolve', use DNS. + * if `func', use that function for validating the conversion + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_425_conv_principal_ext2(krb5_context context, + const char *name, + const char *instance, + const char *realm, + krb5_boolean (*func)(krb5_context, + void *, krb5_principal), + void *funcctx, + krb5_boolean resolve, + krb5_principal *princ) +{ + const char *p; + krb5_error_code ret; + krb5_principal pr; + char host[MAXHOSTNAMELEN]; + char local_hostname[MAXHOSTNAMELEN]; + + /* do the following: if the name is found in the + `v4_name_convert:host' part, is assumed to be a `host' type + principal, and the instance is looked up in the + `v4_instance_convert' part. if not found there the name is + (optionally) looked up as a hostname, and if that doesn't yield + anything, the `default_domain' is appended to the instance + */ + + if(instance == NULL) + goto no_host; + if(instance[0] == 0){ + instance = NULL; + goto no_host; + } + p = get_name_conversion(context, realm, name); + if(p == NULL) + goto no_host; + name = p; + p = krb5_config_get_string(context, NULL, "realms", realm, + "v4_instance_convert", instance, NULL); + if(p){ + instance = p; + ret = krb5_make_principal(context, &pr, realm, name, instance, NULL); + if(func == NULL || (*func)(context, funcctx, pr)){ + *princ = pr; + return 0; + } + krb5_free_principal(context, pr); + *princ = NULL; + krb5_clear_error_string (context); + return HEIM_ERR_V4_PRINC_NO_CONV; + } + if(resolve){ + krb5_boolean passed = FALSE; + char *inst = NULL; +#ifdef USE_RESOLVER + struct dns_reply *r; + + r = dns_lookup(instance, "aaaa"); + if (r) { + if (r->head && r->head->type == T_AAAA) { + inst = strdup(r->head->domain); + passed = TRUE; + } + dns_free_data(r); + } else { + r = dns_lookup(instance, "a"); + if (r) { + if(r->head && r->head->type == T_A) { + inst = strdup(r->head->domain); + passed = TRUE; + } + dns_free_data(r); + } + } +#else + struct addrinfo hints, *ai; + + memset (&hints, 0, sizeof(hints)); + hints.ai_flags = AI_CANONNAME; + ret = getaddrinfo(instance, NULL, &hints, &ai); + if (ret == 0) { + const struct addrinfo *a; + for (a = ai; a != NULL; a = a->ai_next) { + if (a->ai_canonname != NULL) { + inst = strdup (a->ai_canonname); + passed = TRUE; + break; + } + } + freeaddrinfo (ai); + } +#endif + if (passed) { + if (inst == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + strlwr(inst); + ret = krb5_make_principal(context, &pr, realm, name, inst, + NULL); + free (inst); + if(ret == 0) { + if(func == NULL || (*func)(context, funcctx, pr)){ + *princ = pr; + return 0; + } + krb5_free_principal(context, pr); + } + } + } + if(func != NULL) { + snprintf(host, sizeof(host), "%s.%s", instance, realm); + strlwr(host); + ret = krb5_make_principal(context, &pr, realm, name, host, NULL); + if((*func)(context, funcctx, pr)){ + *princ = pr; + return 0; + } + krb5_free_principal(context, pr); + } + + /* + * if the instance is the first component of the local hostname, + * the converted host should be the long hostname. + */ + + if (func == NULL && + gethostname (local_hostname, sizeof(local_hostname)) == 0 && + strncmp(instance, local_hostname, strlen(instance)) == 0 && + local_hostname[strlen(instance)] == '.') { + strlcpy(host, local_hostname, sizeof(host)); + goto local_host; + } + + { + char **domains, **d; + domains = krb5_config_get_strings(context, NULL, "realms", realm, + "v4_domains", NULL); + for(d = domains; d && *d; d++){ + snprintf(host, sizeof(host), "%s.%s", instance, *d); + ret = krb5_make_principal(context, &pr, realm, name, host, NULL); + if(func == NULL || (*func)(context, funcctx, pr)){ + *princ = pr; + krb5_config_free_strings(domains); + return 0; + } + krb5_free_principal(context, pr); + } + krb5_config_free_strings(domains); + } + + + p = krb5_config_get_string(context, NULL, "realms", realm, + "default_domain", NULL); + if(p == NULL){ + /* this should be an error, just faking a name is not good */ + krb5_clear_error_string (context); + return HEIM_ERR_V4_PRINC_NO_CONV; + } + + if (*p == '.') + ++p; + snprintf(host, sizeof(host), "%s.%s", instance, p); +local_host: + ret = krb5_make_principal(context, &pr, realm, name, host, NULL); + if(func == NULL || (*func)(context, funcctx, pr)){ + *princ = pr; + return 0; + } + krb5_free_principal(context, pr); + krb5_clear_error_string (context); + return HEIM_ERR_V4_PRINC_NO_CONV; +no_host: + p = krb5_config_get_string(context, NULL, + "realms", + realm, + "v4_name_convert", + "plain", + name, + NULL); + if(p == NULL) + p = krb5_config_get_string(context, NULL, + "libdefaults", + "v4_name_convert", + "plain", + name, + NULL); + if(p) + name = p; + + ret = krb5_make_principal(context, &pr, realm, name, instance, NULL); + if(func == NULL || (*func)(context, funcctx, pr)){ + *princ = pr; + return 0; + } + krb5_free_principal(context, pr); + krb5_clear_error_string (context); + return HEIM_ERR_V4_PRINC_NO_CONV; +} + +static krb5_boolean +convert_func(krb5_context conxtext, void *funcctx, krb5_principal principal) +{ + krb5_boolean (*func)(krb5_context, krb5_principal) = funcctx; + return (*func)(conxtext, principal); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_425_conv_principal_ext(krb5_context context, + const char *name, + const char *instance, + const char *realm, + krb5_boolean (*func)(krb5_context, krb5_principal), + krb5_boolean resolve, + krb5_principal *principal) +{ + return krb5_425_conv_principal_ext2(context, + name, + instance, + realm, + func ? convert_func : NULL, + func, + resolve, + principal); +} + + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_425_conv_principal(krb5_context context, + const char *name, + const char *instance, + const char *realm, + krb5_principal *princ) +{ + krb5_boolean resolve = krb5_config_get_bool(context, + NULL, + "libdefaults", + "v4_instance_resolve", + NULL); + + return krb5_425_conv_principal_ext(context, name, instance, realm, + NULL, resolve, princ); +} + + +static int +check_list(const krb5_config_binding *l, const char *name, const char **out) +{ + while(l){ + if (l->type != krb5_config_string) + continue; + if(strcmp(name, l->u.string) == 0) { + *out = l->name; + return 1; + } + l = l->next; + } + return 0; +} + +static int +name_convert(krb5_context context, const char *name, const char *realm, + const char **out) +{ + const krb5_config_binding *l; + l = krb5_config_get_list (context, + NULL, + "realms", + realm, + "v4_name_convert", + "host", + NULL); + if(l && check_list(l, name, out)) + return KRB5_NT_SRV_HST; + l = krb5_config_get_list (context, + NULL, + "libdefaults", + "v4_name_convert", + "host", + NULL); + if(l && check_list(l, name, out)) + return KRB5_NT_SRV_HST; + l = krb5_config_get_list (context, + NULL, + "realms", + realm, + "v4_name_convert", + "plain", + NULL); + if(l && check_list(l, name, out)) + return KRB5_NT_UNKNOWN; + l = krb5_config_get_list (context, + NULL, + "libdefaults", + "v4_name_convert", + "host", + NULL); + if(l && check_list(l, name, out)) + return KRB5_NT_UNKNOWN; + + /* didn't find it in config file, try built-in list */ + { + struct v4_name_convert *q; + for(q = default_v4_name_convert; q->from; q++) { + if(strcmp(name, q->to) == 0) { + *out = q->from; + return KRB5_NT_SRV_HST; + } + } + } + return -1; +} + +/* + * convert the v5 principal in `principal' into a v4 corresponding one + * in `name, instance, realm' + * this is limited interface since there's no length given for these + * three parameters. They have to be 40 bytes each (ANAME_SZ). + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_524_conv_principal(krb5_context context, + const krb5_principal principal, + char *name, + char *instance, + char *realm) +{ + const char *n, *i, *r; + char tmpinst[40]; + int type = princ_type(principal); + const int aname_sz = 40; + + r = principal->realm; + + switch(principal->name.name_string.len){ + case 1: + n = principal->name.name_string.val[0]; + i = ""; + break; + case 2: + n = principal->name.name_string.val[0]; + i = principal->name.name_string.val[1]; + break; + default: + krb5_set_error_string (context, + "cannot convert a %d component principal", + principal->name.name_string.len); + return KRB5_PARSE_MALFORMED; + } + + { + const char *tmp; + int t = name_convert(context, n, r, &tmp); + if(t >= 0) { + type = t; + n = tmp; + } + } + + if(type == KRB5_NT_SRV_HST){ + char *p; + + strlcpy (tmpinst, i, sizeof(tmpinst)); + p = strchr(tmpinst, '.'); + if(p) + *p = 0; + i = tmpinst; + } + + if (strlcpy (name, n, aname_sz) >= aname_sz) { + krb5_set_error_string (context, + "too long name component to convert"); + return KRB5_PARSE_MALFORMED; + } + if (strlcpy (instance, i, aname_sz) >= aname_sz) { + krb5_set_error_string (context, + "too long instance component to convert"); + return KRB5_PARSE_MALFORMED; + } + if (strlcpy (realm, r, aname_sz) >= aname_sz) { + krb5_set_error_string (context, + "too long realm component to convert"); + return KRB5_PARSE_MALFORMED; + } + return 0; +} + +/* + * Create a principal in `ret_princ' for the service `sname' running + * on host `hostname'. */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_sname_to_principal (krb5_context context, + const char *hostname, + const char *sname, + int32_t type, + krb5_principal *ret_princ) +{ + krb5_error_code ret; + char localhost[MAXHOSTNAMELEN]; + char **realms, *host = NULL; + + if(type != KRB5_NT_SRV_HST && type != KRB5_NT_UNKNOWN) { + krb5_set_error_string (context, "unsupported name type %d", + type); + return KRB5_SNAME_UNSUPP_NAMETYPE; + } + if(hostname == NULL) { + gethostname(localhost, sizeof(localhost)); + hostname = localhost; + } + if(sname == NULL) + sname = "host"; + if(type == KRB5_NT_SRV_HST) { + ret = krb5_expand_hostname_realms (context, hostname, + &host, &realms); + if (ret) + return ret; + strlwr(host); + hostname = host; + } else { + ret = krb5_get_host_realm(context, hostname, &realms); + if(ret) + return ret; + } + + ret = krb5_make_principal(context, ret_princ, realms[0], sname, + hostname, NULL); + if(host) + free(host); + krb5_free_host_realm(context, realms); + return ret; +} + +static const struct { + const char *type; + int32_t value; +} nametypes[] = { + { "UNKNOWN", KRB5_NT_UNKNOWN }, + { "PRINCIPAL", KRB5_NT_PRINCIPAL }, + { "SRV_INST", KRB5_NT_SRV_INST }, + { "SRV_HST", KRB5_NT_SRV_HST }, + { "SRV_XHST", KRB5_NT_SRV_XHST }, + { "UID", KRB5_NT_UID }, + { "X500_PRINCIPAL", KRB5_NT_X500_PRINCIPAL }, + { "SMTP_NAME", KRB5_NT_SMTP_NAME }, + { "ENTERPRISE_PRINCIPAL", KRB5_NT_ENTERPRISE_PRINCIPAL }, + { "ENT_PRINCIPAL_AND_ID", KRB5_NT_ENT_PRINCIPAL_AND_ID }, + { "MS_PRINCIPAL", KRB5_NT_MS_PRINCIPAL }, + { "MS_PRINCIPAL_AND_ID", KRB5_NT_MS_PRINCIPAL_AND_ID }, + { NULL } +}; + +krb5_error_code +krb5_parse_nametype(krb5_context context, const char *str, int32_t *nametype) +{ + size_t i; + + for(i = 0; nametypes[i].type; i++) { + if (strcasecmp(nametypes[i].type, str) == 0) { + *nametype = nametypes[i].value; + return 0; + } + } + krb5_set_error_string(context, "Failed to find name type %s", str); + return KRB5_PARSE_MALFORMED; +} diff --git a/lib/krb5/prog_setup.c b/lib/krb5/prog_setup.c new file mode 100644 index 0000000..0586155 --- /dev/null +++ b/lib/krb5/prog_setup.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" +#include <getarg.h> +#include <err.h> + +RCSID("$Id: prog_setup.c 15470 2005-06-17 04:29:41Z lha $"); + +void KRB5_LIB_FUNCTION +krb5_std_usage(int code, struct getargs *args, int num_args) +{ + arg_printusage(args, num_args, NULL, ""); + exit(code); +} + +int KRB5_LIB_FUNCTION +krb5_program_setup(krb5_context *context, int argc, char **argv, + struct getargs *args, int num_args, + void (*usage)(int, struct getargs*, int)) +{ + krb5_error_code ret; + int optidx = 0; + + if(usage == NULL) + usage = krb5_std_usage; + + setprogname(argv[0]); + ret = krb5_init_context(context); + if (ret) + errx (1, "krb5_init_context failed: %d", ret); + + if(getarg(args, num_args, argc, argv, &optidx)) + (*usage)(1, args, num_args); + return optidx; +} diff --git a/lib/krb5/prompter_posix.c b/lib/krb5/prompter_posix.c new file mode 100644 index 0000000..e0f407f --- /dev/null +++ b/lib/krb5/prompter_posix.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: prompter_posix.c 13863 2004-05-25 21:46:46Z lha $"); + +int KRB5_LIB_FUNCTION +krb5_prompter_posix (krb5_context context, + void *data, + const char *name, + const char *banner, + int num_prompts, + krb5_prompt prompts[]) +{ + int i; + + if (name) + fprintf (stderr, "%s\n", name); + if (banner) + fprintf (stderr, "%s\n", banner); + if (name || banner) + fflush(stderr); + for (i = 0; i < num_prompts; ++i) { + if (prompts[i].hidden) { + if(UI_UTIL_read_pw_string(prompts[i].reply->data, + prompts[i].reply->length, + prompts[i].prompt, + 0)) + return 1; + } else { + char *s = prompts[i].reply->data; + + fputs (prompts[i].prompt, stdout); + fflush (stdout); + if(fgets(prompts[i].reply->data, + prompts[i].reply->length, + stdin) == NULL) + return 1; + s[strcspn(s, "\n")] = '\0'; + } + } + return 0; +} diff --git a/lib/krb5/rd_cred.c b/lib/krb5/rd_cred.c new file mode 100644 index 0000000..c3f7322 --- /dev/null +++ b/lib/krb5/rd_cred.c @@ -0,0 +1,340 @@ +/* + * Copyright (c) 1997 - 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <krb5_locl.h> + +RCSID("$Id: rd_cred.c 20304 2007-04-11 11:15:05Z lha $"); + +static krb5_error_code +compare_addrs(krb5_context context, + krb5_address *a, + krb5_address *b, + const char *message) +{ + char a_str[64], b_str[64]; + size_t len; + + if(krb5_address_compare (context, a, b)) + return 0; + + krb5_print_address (a, a_str, sizeof(a_str), &len); + krb5_print_address (b, b_str, sizeof(b_str), &len); + krb5_set_error_string(context, "%s: %s != %s", message, b_str, a_str); + return KRB5KRB_AP_ERR_BADADDR; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_cred(krb5_context context, + krb5_auth_context auth_context, + krb5_data *in_data, + krb5_creds ***ret_creds, + krb5_replay_data *outdata) +{ + krb5_error_code ret; + size_t len; + KRB_CRED cred; + EncKrbCredPart enc_krb_cred_part; + krb5_data enc_krb_cred_part_data; + krb5_crypto crypto; + int i; + + memset(&enc_krb_cred_part, 0, sizeof(enc_krb_cred_part)); + + if ((auth_context->flags & + (KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE)) && + outdata == NULL) + return KRB5_RC_REQUIRED; /* XXX better error, MIT returns this */ + + *ret_creds = NULL; + + ret = decode_KRB_CRED(in_data->data, in_data->length, + &cred, &len); + if(ret) { + krb5_clear_error_string(context); + return ret; + } + + if (cred.pvno != 5) { + ret = KRB5KRB_AP_ERR_BADVERSION; + krb5_clear_error_string (context); + goto out; + } + + if (cred.msg_type != krb_cred) { + ret = KRB5KRB_AP_ERR_MSG_TYPE; + krb5_clear_error_string (context); + goto out; + } + + if (cred.enc_part.etype == ETYPE_NULL) { + /* DK: MIT GSS-API Compatibility */ + enc_krb_cred_part_data.length = cred.enc_part.cipher.length; + enc_krb_cred_part_data.data = cred.enc_part.cipher.data; + } else { + /* Try both subkey and session key. + * + * RFC4120 claims we should use the session key, but Heimdal + * before 0.8 used the remote subkey if it was send in the + * auth_context. + */ + + if (auth_context->remote_subkey) { + ret = krb5_crypto_init(context, auth_context->remote_subkey, + 0, &crypto); + if (ret) + goto out; + + ret = krb5_decrypt_EncryptedData(context, + crypto, + KRB5_KU_KRB_CRED, + &cred.enc_part, + &enc_krb_cred_part_data); + + krb5_crypto_destroy(context, crypto); + } + + /* + * If there was not subkey, or we failed using subkey, + * retry using the session key + */ + if (auth_context->remote_subkey == NULL || ret == KRB5KRB_AP_ERR_BAD_INTEGRITY) + { + + ret = krb5_crypto_init(context, auth_context->keyblock, + 0, &crypto); + + if (ret) + goto out; + + ret = krb5_decrypt_EncryptedData(context, + crypto, + KRB5_KU_KRB_CRED, + &cred.enc_part, + &enc_krb_cred_part_data); + + krb5_crypto_destroy(context, crypto); + } + if (ret) + goto out; + } + + ret = krb5_decode_EncKrbCredPart (context, + enc_krb_cred_part_data.data, + enc_krb_cred_part_data.length, + &enc_krb_cred_part, + &len); + if (enc_krb_cred_part_data.data != cred.enc_part.cipher.data) + krb5_data_free(&enc_krb_cred_part_data); + if (ret) + goto out; + + /* check sender address */ + + if (enc_krb_cred_part.s_address + && auth_context->remote_address + && auth_context->remote_port) { + krb5_address *a; + + ret = krb5_make_addrport (context, &a, + auth_context->remote_address, + auth_context->remote_port); + if (ret) + goto out; + + + ret = compare_addrs(context, a, enc_krb_cred_part.s_address, + "sender address is wrong in received creds"); + krb5_free_address(context, a); + free(a); + if(ret) + goto out; + } + + /* check receiver address */ + + if (enc_krb_cred_part.r_address + && auth_context->local_address) { + if(auth_context->local_port && + enc_krb_cred_part.r_address->addr_type == KRB5_ADDRESS_ADDRPORT) { + krb5_address *a; + ret = krb5_make_addrport (context, &a, + auth_context->local_address, + auth_context->local_port); + if (ret) + goto out; + + ret = compare_addrs(context, a, enc_krb_cred_part.r_address, + "receiver address is wrong in received creds"); + krb5_free_address(context, a); + free(a); + if(ret) + goto out; + } else { + ret = compare_addrs(context, auth_context->local_address, + enc_krb_cred_part.r_address, + "receiver address is wrong in received creds"); + if(ret) + goto out; + } + } + + /* check timestamp */ + if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) { + krb5_timestamp sec; + + krb5_timeofday (context, &sec); + + if (enc_krb_cred_part.timestamp == NULL || + enc_krb_cred_part.usec == NULL || + abs(*enc_krb_cred_part.timestamp - sec) + > context->max_skew) { + krb5_clear_error_string (context); + ret = KRB5KRB_AP_ERR_SKEW; + goto out; + } + } + + if ((auth_context->flags & + (KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE))) { + /* if these fields are not present in the cred-part, silently + return zero */ + memset(outdata, 0, sizeof(*outdata)); + if(enc_krb_cred_part.timestamp) + outdata->timestamp = *enc_krb_cred_part.timestamp; + if(enc_krb_cred_part.usec) + outdata->usec = *enc_krb_cred_part.usec; + if(enc_krb_cred_part.nonce) + outdata->seq = *enc_krb_cred_part.nonce; + } + + /* Convert to NULL terminated list of creds */ + + *ret_creds = calloc(enc_krb_cred_part.ticket_info.len + 1, + sizeof(**ret_creds)); + + if (*ret_creds == NULL) { + ret = ENOMEM; + krb5_set_error_string (context, "malloc: out of memory"); + goto out; + } + + for (i = 0; i < enc_krb_cred_part.ticket_info.len; ++i) { + KrbCredInfo *kci = &enc_krb_cred_part.ticket_info.val[i]; + krb5_creds *creds; + + creds = calloc(1, sizeof(*creds)); + if(creds == NULL) { + ret = ENOMEM; + krb5_set_error_string (context, "malloc: out of memory"); + goto out; + } + + ASN1_MALLOC_ENCODE(Ticket, creds->ticket.data, creds->ticket.length, + &cred.tickets.val[i], &len, ret); + if (ret) { + free(creds); + goto out; + } + if(creds->ticket.length != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + copy_EncryptionKey (&kci->key, &creds->session); + if (kci->prealm && kci->pname) + _krb5_principalname2krb5_principal (context, + &creds->client, + *kci->pname, + *kci->prealm); + if (kci->flags) + creds->flags.b = *kci->flags; + if (kci->authtime) + creds->times.authtime = *kci->authtime; + if (kci->starttime) + creds->times.starttime = *kci->starttime; + if (kci->endtime) + creds->times.endtime = *kci->endtime; + if (kci->renew_till) + creds->times.renew_till = *kci->renew_till; + if (kci->srealm && kci->sname) + _krb5_principalname2krb5_principal (context, + &creds->server, + *kci->sname, + *kci->srealm); + if (kci->caddr) + krb5_copy_addresses (context, + kci->caddr, + &creds->addresses); + + (*ret_creds)[i] = creds; + + } + (*ret_creds)[i] = NULL; + + free_KRB_CRED (&cred); + free_EncKrbCredPart(&enc_krb_cred_part); + + return 0; + + out: + free_EncKrbCredPart(&enc_krb_cred_part); + free_KRB_CRED (&cred); + if(*ret_creds) { + for(i = 0; (*ret_creds)[i]; i++) + krb5_free_creds(context, (*ret_creds)[i]); + free(*ret_creds); + *ret_creds = NULL; + } + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_cred2 (krb5_context context, + krb5_auth_context auth_context, + krb5_ccache ccache, + krb5_data *in_data) +{ + krb5_error_code ret; + krb5_creds **creds; + int i; + + ret = krb5_rd_cred(context, auth_context, in_data, &creds, NULL); + if(ret) + return ret; + + /* Store the creds in the ccache */ + + for(i = 0; creds && creds[i]; i++) { + krb5_cc_store_cred(context, ccache, creds[i]); + krb5_free_creds(context, creds[i]); + } + free(creds); + return 0; +} diff --git a/lib/krb5/rd_error.c b/lib/krb5/rd_error.c new file mode 100644 index 0000000..e764646 --- /dev/null +++ b/lib/krb5/rd_error.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: rd_error.c 21057 2007-06-12 17:22:31Z lha $"); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_error(krb5_context context, + const krb5_data *msg, + KRB_ERROR *result) +{ + + size_t len; + krb5_error_code ret; + + ret = decode_KRB_ERROR(msg->data, msg->length, result, &len); + if(ret) { + krb5_clear_error_string(context); + return ret; + } + result->error_code += KRB5KDC_ERR_NONE; + return 0; +} + +void KRB5_LIB_FUNCTION +krb5_free_error_contents (krb5_context context, + krb5_error *error) +{ + free_KRB_ERROR(error); + memset(error, 0, sizeof(*error)); +} + +void KRB5_LIB_FUNCTION +krb5_free_error (krb5_context context, + krb5_error *error) +{ + krb5_free_error_contents (context, error); + free (error); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_error_from_rd_error(krb5_context context, + const krb5_error *error, + const krb5_creds *creds) +{ + krb5_error_code ret; + + ret = error->error_code; + if (error->e_text != NULL) { + krb5_set_error_string(context, "%s", *error->e_text); + } else { + char clientname[256], servername[256]; + + if (creds != NULL) { + krb5_unparse_name_fixed(context, creds->client, + clientname, sizeof(clientname)); + krb5_unparse_name_fixed(context, creds->server, + servername, sizeof(servername)); + } + + switch (ret) { + case KRB5KDC_ERR_NAME_EXP : + krb5_set_error_string(context, "Client %s%s%s expired", + creds ? "(" : "", + creds ? clientname : "", + creds ? ")" : ""); + break; + case KRB5KDC_ERR_SERVICE_EXP : + krb5_set_error_string(context, "Server %s%s%s expired", + creds ? "(" : "", + creds ? servername : "", + creds ? ")" : ""); + break; + case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN : + krb5_set_error_string(context, "Client %s%s%s unknown", + creds ? "(" : "", + creds ? clientname : "", + creds ? ")" : ""); + break; + case KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN : + krb5_set_error_string(context, "Server %s%s%s unknown", + creds ? "(" : "", + creds ? servername : "", + creds ? ")" : ""); + break; + default : + krb5_clear_error_string(context); + break; + } + } + return ret; +} diff --git a/lib/krb5/rd_priv.c b/lib/krb5/rd_priv.c new file mode 100644 index 0000000..ed7a2cc --- /dev/null +++ b/lib/krb5/rd_priv.c @@ -0,0 +1,185 @@ +/* + * Copyright (c) 1997-2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <krb5_locl.h> + +RCSID("$Id: rd_priv.c 21751 2007-07-31 20:42:20Z lha $"); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_priv(krb5_context context, + krb5_auth_context auth_context, + const krb5_data *inbuf, + krb5_data *outbuf, + krb5_replay_data *outdata) +{ + krb5_error_code ret; + KRB_PRIV priv; + EncKrbPrivPart part; + size_t len; + krb5_data plain; + krb5_keyblock *key; + krb5_crypto crypto; + + if (outbuf) + krb5_data_zero(outbuf); + + if ((auth_context->flags & + (KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE)) && + outdata == NULL) { + krb5_clear_error_string (context); + return KRB5_RC_REQUIRED; /* XXX better error, MIT returns this */ + } + + memset(&priv, 0, sizeof(priv)); + ret = decode_KRB_PRIV (inbuf->data, inbuf->length, &priv, &len); + if (ret) { + krb5_clear_error_string (context); + goto failure; + } + if (priv.pvno != 5) { + krb5_clear_error_string (context); + ret = KRB5KRB_AP_ERR_BADVERSION; + goto failure; + } + if (priv.msg_type != krb_priv) { + krb5_clear_error_string (context); + ret = KRB5KRB_AP_ERR_MSG_TYPE; + goto failure; + } + + if (auth_context->remote_subkey) + key = auth_context->remote_subkey; + else if (auth_context->local_subkey) + key = auth_context->local_subkey; + else + key = auth_context->keyblock; + + ret = krb5_crypto_init(context, key, 0, &crypto); + if (ret) + goto failure; + ret = krb5_decrypt_EncryptedData(context, + crypto, + KRB5_KU_KRB_PRIV, + &priv.enc_part, + &plain); + krb5_crypto_destroy(context, crypto); + if (ret) + goto failure; + + ret = decode_EncKrbPrivPart (plain.data, plain.length, &part, &len); + krb5_data_free (&plain); + if (ret) { + krb5_clear_error_string (context); + goto failure; + } + + /* check sender address */ + + if (part.s_address + && auth_context->remote_address + && !krb5_address_compare (context, + auth_context->remote_address, + part.s_address)) { + krb5_clear_error_string (context); + ret = KRB5KRB_AP_ERR_BADADDR; + goto failure_part; + } + + /* check receiver address */ + + if (part.r_address + && auth_context->local_address + && !krb5_address_compare (context, + auth_context->local_address, + part.r_address)) { + krb5_clear_error_string (context); + ret = KRB5KRB_AP_ERR_BADADDR; + goto failure_part; + } + + /* check timestamp */ + if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) { + krb5_timestamp sec; + + krb5_timeofday (context, &sec); + if (part.timestamp == NULL || + part.usec == NULL || + abs(*part.timestamp - sec) > context->max_skew) { + krb5_clear_error_string (context); + ret = KRB5KRB_AP_ERR_SKEW; + goto failure_part; + } + } + + /* XXX - check replay cache */ + + /* check sequence number. since MIT krb5 cannot generate a sequence + number of zero but instead generates no sequence number, we accept that + */ + + if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) { + if ((part.seq_number == NULL + && auth_context->remote_seqnumber != 0) + || (part.seq_number != NULL + && *part.seq_number != auth_context->remote_seqnumber)) { + krb5_clear_error_string (context); + ret = KRB5KRB_AP_ERR_BADORDER; + goto failure_part; + } + auth_context->remote_seqnumber++; + } + + ret = krb5_data_copy (outbuf, part.user_data.data, part.user_data.length); + if (ret) + goto failure_part; + + if ((auth_context->flags & + (KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE))) { + /* if these fields are not present in the priv-part, silently + return zero */ + memset(outdata, 0, sizeof(*outdata)); + if(part.timestamp) + outdata->timestamp = *part.timestamp; + if(part.usec) + outdata->usec = *part.usec; + if(part.seq_number) + outdata->seq = *part.seq_number; + } + + failure_part: + free_EncKrbPrivPart (&part); + + failure: + free_KRB_PRIV (&priv); + return ret; +} diff --git a/lib/krb5/rd_rep.c b/lib/krb5/rd_rep.c new file mode 100644 index 0000000..8c9b7bb --- /dev/null +++ b/lib/krb5/rd_rep.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <krb5_locl.h> + +RCSID("$Id: rd_rep.c 17890 2006-08-21 09:19:22Z lha $"); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_rep(krb5_context context, + krb5_auth_context auth_context, + const krb5_data *inbuf, + krb5_ap_rep_enc_part **repl) +{ + krb5_error_code ret; + AP_REP ap_rep; + size_t len; + krb5_data data; + krb5_crypto crypto; + + krb5_data_zero (&data); + ret = 0; + + ret = decode_AP_REP(inbuf->data, inbuf->length, &ap_rep, &len); + if (ret) + return ret; + if (ap_rep.pvno != 5) { + ret = KRB5KRB_AP_ERR_BADVERSION; + krb5_clear_error_string (context); + goto out; + } + if (ap_rep.msg_type != krb_ap_rep) { + ret = KRB5KRB_AP_ERR_MSG_TYPE; + krb5_clear_error_string (context); + goto out; + } + + ret = krb5_crypto_init(context, auth_context->keyblock, 0, &crypto); + if (ret) + goto out; + ret = krb5_decrypt_EncryptedData (context, + crypto, + KRB5_KU_AP_REQ_ENC_PART, + &ap_rep.enc_part, + &data); + krb5_crypto_destroy(context, crypto); + if (ret) + goto out; + + *repl = malloc(sizeof(**repl)); + if (*repl == NULL) { + ret = ENOMEM; + krb5_set_error_string (context, "malloc: out of memory"); + goto out; + } + ret = krb5_decode_EncAPRepPart(context, + data.data, + data.length, + *repl, + &len); + if (ret) + return ret; + + if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) { + if ((*repl)->ctime != auth_context->authenticator->ctime || + (*repl)->cusec != auth_context->authenticator->cusec) + { + krb5_free_ap_rep_enc_part(context, *repl); + *repl = NULL; + ret = KRB5KRB_AP_ERR_MUT_FAIL; + krb5_clear_error_string (context); + goto out; + } + } + if ((*repl)->seq_number) + krb5_auth_con_setremoteseqnumber(context, auth_context, + *((*repl)->seq_number)); + if ((*repl)->subkey) + krb5_auth_con_setremotesubkey(context, auth_context, (*repl)->subkey); + + out: + krb5_data_free (&data); + free_AP_REP (&ap_rep); + return ret; +} + +void KRB5_LIB_FUNCTION +krb5_free_ap_rep_enc_part (krb5_context context, + krb5_ap_rep_enc_part *val) +{ + if (val) { + free_EncAPRepPart (val); + free (val); + } +} diff --git a/lib/krb5/rd_req.c b/lib/krb5/rd_req.c new file mode 100644 index 0000000..0f33b97 --- /dev/null +++ b/lib/krb5/rd_req.c @@ -0,0 +1,892 @@ +/* + * Copyright (c) 1997 - 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <krb5_locl.h> + +RCSID("$Id: rd_req.c 22235 2007-12-08 21:52:07Z lha $"); + +static krb5_error_code +decrypt_tkt_enc_part (krb5_context context, + krb5_keyblock *key, + EncryptedData *enc_part, + EncTicketPart *decr_part) +{ + krb5_error_code ret; + krb5_data plain; + size_t len; + krb5_crypto crypto; + + ret = krb5_crypto_init(context, key, 0, &crypto); + if (ret) + return ret; + ret = krb5_decrypt_EncryptedData (context, + crypto, + KRB5_KU_TICKET, + enc_part, + &plain); + krb5_crypto_destroy(context, crypto); + if (ret) + return ret; + + ret = krb5_decode_EncTicketPart(context, plain.data, plain.length, + decr_part, &len); + krb5_data_free (&plain); + return ret; +} + +static krb5_error_code +decrypt_authenticator (krb5_context context, + EncryptionKey *key, + EncryptedData *enc_part, + Authenticator *authenticator, + krb5_key_usage usage) +{ + krb5_error_code ret; + krb5_data plain; + size_t len; + krb5_crypto crypto; + + ret = krb5_crypto_init(context, key, 0, &crypto); + if (ret) + return ret; + ret = krb5_decrypt_EncryptedData (context, + crypto, + usage /* KRB5_KU_AP_REQ_AUTH */, + enc_part, + &plain); + /* for backwards compatibility, also try the old usage */ + if (ret && usage == KRB5_KU_TGS_REQ_AUTH) + ret = krb5_decrypt_EncryptedData (context, + crypto, + KRB5_KU_AP_REQ_AUTH, + enc_part, + &plain); + krb5_crypto_destroy(context, crypto); + if (ret) + return ret; + + ret = krb5_decode_Authenticator(context, plain.data, plain.length, + authenticator, &len); + krb5_data_free (&plain); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decode_ap_req(krb5_context context, + const krb5_data *inbuf, + krb5_ap_req *ap_req) +{ + krb5_error_code ret; + size_t len; + ret = decode_AP_REQ(inbuf->data, inbuf->length, ap_req, &len); + if (ret) + return ret; + if (ap_req->pvno != 5){ + free_AP_REQ(ap_req); + krb5_clear_error_string (context); + return KRB5KRB_AP_ERR_BADVERSION; + } + if (ap_req->msg_type != krb_ap_req){ + free_AP_REQ(ap_req); + krb5_clear_error_string (context); + return KRB5KRB_AP_ERR_MSG_TYPE; + } + if (ap_req->ticket.tkt_vno != 5){ + free_AP_REQ(ap_req); + krb5_clear_error_string (context); + return KRB5KRB_AP_ERR_BADVERSION; + } + return 0; +} + +static krb5_error_code +check_transited(krb5_context context, Ticket *ticket, EncTicketPart *enc) +{ + char **realms; + int num_realms; + krb5_error_code ret; + + /* + * Windows 2000 and 2003 uses this inside their TGT so it's normaly + * not seen by others, however, samba4 joined with a Windows AD as + * a Domain Controller gets exposed to this. + */ + if(enc->transited.tr_type == 0 && enc->transited.contents.length == 0) + return 0; + + if(enc->transited.tr_type != DOMAIN_X500_COMPRESS) + return KRB5KDC_ERR_TRTYPE_NOSUPP; + + if(enc->transited.contents.length == 0) + return 0; + + ret = krb5_domain_x500_decode(context, enc->transited.contents, + &realms, &num_realms, + enc->crealm, + ticket->realm); + if(ret) + return ret; + ret = krb5_check_transited(context, enc->crealm, + ticket->realm, + realms, num_realms, NULL); + free(realms); + return ret; +} + +static krb5_error_code +find_etypelist(krb5_context context, + krb5_auth_context auth_context, + EtypeList *etypes) +{ + krb5_error_code ret; + krb5_authdata *ad; + krb5_authdata adIfRelevant; + unsigned i; + + adIfRelevant.len = 0; + + etypes->len = 0; + etypes->val = NULL; + + ad = auth_context->authenticator->authorization_data; + if (ad == NULL) + return 0; + + for (i = 0; i < ad->len; i++) { + if (ad->val[i].ad_type == KRB5_AUTHDATA_IF_RELEVANT) { + ret = decode_AD_IF_RELEVANT(ad->val[i].ad_data.data, + ad->val[i].ad_data.length, + &adIfRelevant, + NULL); + if (ret) + return ret; + + if (adIfRelevant.len == 1 && + adIfRelevant.val[0].ad_type == + KRB5_AUTHDATA_GSS_API_ETYPE_NEGOTIATION) { + break; + } + free_AD_IF_RELEVANT(&adIfRelevant); + adIfRelevant.len = 0; + } + } + + if (adIfRelevant.len == 0) + return 0; + + ret = decode_EtypeList(adIfRelevant.val[0].ad_data.data, + adIfRelevant.val[0].ad_data.length, + etypes, + NULL); + if (ret) + krb5_clear_error_string(context); + + free_AD_IF_RELEVANT(&adIfRelevant); + + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decrypt_ticket(krb5_context context, + Ticket *ticket, + krb5_keyblock *key, + EncTicketPart *out, + krb5_flags flags) +{ + EncTicketPart t; + krb5_error_code ret; + ret = decrypt_tkt_enc_part (context, key, &ticket->enc_part, &t); + if (ret) + return ret; + + { + krb5_timestamp now; + time_t start = t.authtime; + + krb5_timeofday (context, &now); + if(t.starttime) + start = *t.starttime; + if(start - now > context->max_skew + || (t.flags.invalid + && !(flags & KRB5_VERIFY_AP_REQ_IGNORE_INVALID))) { + free_EncTicketPart(&t); + krb5_clear_error_string (context); + return KRB5KRB_AP_ERR_TKT_NYV; + } + if(now - t.endtime > context->max_skew) { + free_EncTicketPart(&t); + krb5_clear_error_string (context); + return KRB5KRB_AP_ERR_TKT_EXPIRED; + } + + if(!t.flags.transited_policy_checked) { + ret = check_transited(context, ticket, &t); + if(ret) { + free_EncTicketPart(&t); + return ret; + } + } + } + + if(out) + *out = t; + else + free_EncTicketPart(&t); + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_verify_authenticator_checksum(krb5_context context, + krb5_auth_context ac, + void *data, + size_t len) +{ + krb5_error_code ret; + krb5_keyblock *key; + krb5_authenticator authenticator; + krb5_crypto crypto; + + ret = krb5_auth_con_getauthenticator (context, + ac, + &authenticator); + if(ret) + return ret; + if(authenticator->cksum == NULL) { + krb5_free_authenticator(context, &authenticator); + return -17; + } + ret = krb5_auth_con_getkey(context, ac, &key); + if(ret) { + krb5_free_authenticator(context, &authenticator); + return ret; + } + ret = krb5_crypto_init(context, key, 0, &crypto); + if(ret) + goto out; + ret = krb5_verify_checksum (context, + crypto, + KRB5_KU_AP_REQ_AUTH_CKSUM, + data, + len, + authenticator->cksum); + krb5_crypto_destroy(context, crypto); +out: + krb5_free_authenticator(context, &authenticator); + krb5_free_keyblock(context, key); + return ret; +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_verify_ap_req(krb5_context context, + krb5_auth_context *auth_context, + krb5_ap_req *ap_req, + krb5_const_principal server, + krb5_keyblock *keyblock, + krb5_flags flags, + krb5_flags *ap_req_options, + krb5_ticket **ticket) +{ + return krb5_verify_ap_req2 (context, + auth_context, + ap_req, + server, + keyblock, + flags, + ap_req_options, + ticket, + KRB5_KU_AP_REQ_AUTH); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_verify_ap_req2(krb5_context context, + krb5_auth_context *auth_context, + krb5_ap_req *ap_req, + krb5_const_principal server, + krb5_keyblock *keyblock, + krb5_flags flags, + krb5_flags *ap_req_options, + krb5_ticket **ticket, + krb5_key_usage usage) +{ + krb5_ticket *t; + krb5_auth_context ac; + krb5_error_code ret; + EtypeList etypes; + + if (ticket) + *ticket = NULL; + + if (auth_context && *auth_context) { + ac = *auth_context; + } else { + ret = krb5_auth_con_init (context, &ac); + if (ret) + return ret; + } + + t = calloc(1, sizeof(*t)); + if (t == NULL) { + ret = ENOMEM; + krb5_clear_error_string (context); + goto out; + } + + if (ap_req->ap_options.use_session_key && ac->keyblock){ + ret = krb5_decrypt_ticket(context, &ap_req->ticket, + ac->keyblock, + &t->ticket, + flags); + krb5_free_keyblock(context, ac->keyblock); + ac->keyblock = NULL; + }else + ret = krb5_decrypt_ticket(context, &ap_req->ticket, + keyblock, + &t->ticket, + flags); + + if(ret) + goto out; + + ret = _krb5_principalname2krb5_principal(context, + &t->server, + ap_req->ticket.sname, + ap_req->ticket.realm); + if (ret) goto out; + ret = _krb5_principalname2krb5_principal(context, + &t->client, + t->ticket.cname, + t->ticket.crealm); + if (ret) goto out; + + /* save key */ + + ret = krb5_copy_keyblock(context, &t->ticket.key, &ac->keyblock); + if (ret) goto out; + + ret = decrypt_authenticator (context, + &t->ticket.key, + &ap_req->authenticator, + ac->authenticator, + usage); + if (ret) + goto out; + + { + krb5_principal p1, p2; + krb5_boolean res; + + _krb5_principalname2krb5_principal(context, + &p1, + ac->authenticator->cname, + ac->authenticator->crealm); + _krb5_principalname2krb5_principal(context, + &p2, + t->ticket.cname, + t->ticket.crealm); + res = krb5_principal_compare (context, p1, p2); + krb5_free_principal (context, p1); + krb5_free_principal (context, p2); + if (!res) { + ret = KRB5KRB_AP_ERR_BADMATCH; + krb5_clear_error_string (context); + goto out; + } + } + + /* check addresses */ + + if (t->ticket.caddr + && ac->remote_address + && !krb5_address_search (context, + ac->remote_address, + t->ticket.caddr)) { + ret = KRB5KRB_AP_ERR_BADADDR; + krb5_clear_error_string (context); + goto out; + } + + /* check timestamp in authenticator */ + { + krb5_timestamp now; + + krb5_timeofday (context, &now); + + if (abs(ac->authenticator->ctime - now) > context->max_skew) { + ret = KRB5KRB_AP_ERR_SKEW; + krb5_clear_error_string (context); + goto out; + } + } + + if (ac->authenticator->seq_number) + krb5_auth_con_setremoteseqnumber(context, ac, + *ac->authenticator->seq_number); + + /* XXX - Xor sequence numbers */ + + if (ac->authenticator->subkey) { + ret = krb5_auth_con_setremotesubkey(context, ac, + ac->authenticator->subkey); + if (ret) + goto out; + } + + ret = find_etypelist(context, ac, &etypes); + if (ret) + goto out; + + ac->keytype = ETYPE_NULL; + + if (etypes.val) { + int i; + + for (i = 0; i < etypes.len; i++) { + if (krb5_enctype_valid(context, etypes.val[i]) == 0) { + ac->keytype = etypes.val[i]; + break; + } + } + } + + if (ap_req_options) { + *ap_req_options = 0; + if (ac->keytype != ETYPE_NULL) + *ap_req_options |= AP_OPTS_USE_SUBKEY; + if (ap_req->ap_options.use_session_key) + *ap_req_options |= AP_OPTS_USE_SESSION_KEY; + if (ap_req->ap_options.mutual_required) + *ap_req_options |= AP_OPTS_MUTUAL_REQUIRED; + } + + if(ticket) + *ticket = t; + else + krb5_free_ticket (context, t); + if (auth_context) { + if (*auth_context == NULL) + *auth_context = ac; + } else + krb5_auth_con_free (context, ac); + free_EtypeList(&etypes); + return 0; + out: + if (t) + krb5_free_ticket (context, t); + if (auth_context == NULL || *auth_context == NULL) + krb5_auth_con_free (context, ac); + return ret; +} + +/* + * + */ + +struct krb5_rd_req_in_ctx_data { + krb5_keytab keytab; + krb5_keyblock *keyblock; + krb5_boolean check_pac; +}; + +struct krb5_rd_req_out_ctx_data { + krb5_keyblock *keyblock; + krb5_flags ap_req_options; + krb5_ticket *ticket; +}; + +/* + * + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_req_in_ctx_alloc(krb5_context context, krb5_rd_req_in_ctx *ctx) +{ + *ctx = calloc(1, sizeof(**ctx)); + if (*ctx == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + (*ctx)->check_pac = (context->flags & KRB5_CTX_F_CHECK_PAC) ? 1 : 0; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_req_in_set_keytab(krb5_context context, + krb5_rd_req_in_ctx in, + krb5_keytab keytab) +{ + in->keytab = keytab; /* XXX should make copy */ + return 0; +} + +/** + * Set if krb5_rq_red() is going to check the Windows PAC or not + * + * @param context Keberos 5 context. + * @param in krb5_rd_req_in_ctx to check the option on. + * @param flag flag to select if to check the pac (TRUE) or not (FALSE). + * + * @return Kerberos 5 error code, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_req_in_set_pac_check(krb5_context context, + krb5_rd_req_in_ctx in, + krb5_boolean flag) +{ + in->check_pac = flag; + return 0; +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_req_in_set_keyblock(krb5_context context, + krb5_rd_req_in_ctx in, + krb5_keyblock *keyblock) +{ + in->keyblock = keyblock; /* XXX should make copy */ + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_req_out_get_ap_req_options(krb5_context context, + krb5_rd_req_out_ctx out, + krb5_flags *ap_req_options) +{ + *ap_req_options = out->ap_req_options; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_req_out_get_ticket(krb5_context context, + krb5_rd_req_out_ctx out, + krb5_ticket **ticket) +{ + return krb5_copy_ticket(context, out->ticket, ticket); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_req_out_get_keyblock(krb5_context context, + krb5_rd_req_out_ctx out, + krb5_keyblock **keyblock) +{ + return krb5_copy_keyblock(context, out->keyblock, keyblock); +} + +void KRB5_LIB_FUNCTION +krb5_rd_req_in_ctx_free(krb5_context context, krb5_rd_req_in_ctx ctx) +{ + free(ctx); +} + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_rd_req_out_ctx_alloc(krb5_context context, krb5_rd_req_out_ctx *ctx) +{ + *ctx = calloc(1, sizeof(**ctx)); + if (*ctx == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + return 0; +} + +void KRB5_LIB_FUNCTION +krb5_rd_req_out_ctx_free(krb5_context context, krb5_rd_req_out_ctx ctx) +{ + krb5_free_keyblock(context, ctx->keyblock); + free(ctx); +} + +/* + * + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_req(krb5_context context, + krb5_auth_context *auth_context, + const krb5_data *inbuf, + krb5_const_principal server, + krb5_keytab keytab, + krb5_flags *ap_req_options, + krb5_ticket **ticket) +{ + krb5_error_code ret; + krb5_rd_req_in_ctx in; + krb5_rd_req_out_ctx out; + + ret = krb5_rd_req_in_ctx_alloc(context, &in); + if (ret) + return ret; + + ret = krb5_rd_req_in_set_keytab(context, in, keytab); + if (ret) { + krb5_rd_req_in_ctx_free(context, in); + return ret; + } + + ret = krb5_rd_req_ctx(context, auth_context, inbuf, server, in, &out); + krb5_rd_req_in_ctx_free(context, in); + if (ret) + return ret; + + if (ap_req_options) + *ap_req_options = out->ap_req_options; + if (ticket) { + ret = krb5_copy_ticket(context, out->ticket, ticket); + if (ret) + goto out; + } + +out: + krb5_rd_req_out_ctx_free(context, out); + return ret; +} + +/* + * + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_req_with_keyblock(krb5_context context, + krb5_auth_context *auth_context, + const krb5_data *inbuf, + krb5_const_principal server, + krb5_keyblock *keyblock, + krb5_flags *ap_req_options, + krb5_ticket **ticket) +{ + krb5_error_code ret; + krb5_rd_req_in_ctx in; + krb5_rd_req_out_ctx out; + + ret = krb5_rd_req_in_ctx_alloc(context, &in); + if (ret) + return ret; + + ret = krb5_rd_req_in_set_keyblock(context, in, keyblock); + if (ret) { + krb5_rd_req_in_ctx_free(context, in); + return ret; + } + + ret = krb5_rd_req_ctx(context, auth_context, inbuf, server, in, &out); + krb5_rd_req_in_ctx_free(context, in); + if (ret) + return ret; + + if (ap_req_options) + *ap_req_options = out->ap_req_options; + if (ticket) { + ret = krb5_copy_ticket(context, out->ticket, ticket); + if (ret) + goto out; + } + +out: + krb5_rd_req_out_ctx_free(context, out); + return ret; +} + +/* + * + */ + +static krb5_error_code +get_key_from_keytab(krb5_context context, + krb5_auth_context *auth_context, + krb5_ap_req *ap_req, + krb5_const_principal server, + krb5_keytab keytab, + krb5_keyblock **out_key) +{ + krb5_keytab_entry entry; + krb5_error_code ret; + int kvno; + krb5_keytab real_keytab; + + if(keytab == NULL) + krb5_kt_default(context, &real_keytab); + else + real_keytab = keytab; + + if (ap_req->ticket.enc_part.kvno) + kvno = *ap_req->ticket.enc_part.kvno; + else + kvno = 0; + + ret = krb5_kt_get_entry (context, + real_keytab, + server, + kvno, + ap_req->ticket.enc_part.etype, + &entry); + if(ret) + goto out; + ret = krb5_copy_keyblock(context, &entry.keyblock, out_key); + krb5_kt_free_entry (context, &entry); +out: + if(keytab == NULL) + krb5_kt_close(context, real_keytab); + + return ret; +} + +/* + * + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_req_ctx(krb5_context context, + krb5_auth_context *auth_context, + const krb5_data *inbuf, + krb5_const_principal server, + krb5_rd_req_in_ctx inctx, + krb5_rd_req_out_ctx *outctx) +{ + krb5_error_code ret; + krb5_ap_req ap_req; + krb5_principal service = NULL; + krb5_rd_req_out_ctx o = NULL; + + ret = _krb5_rd_req_out_ctx_alloc(context, &o); + if (ret) + goto out; + + if (*auth_context == NULL) { + ret = krb5_auth_con_init(context, auth_context); + if (ret) + goto out; + } + + ret = krb5_decode_ap_req(context, inbuf, &ap_req); + if(ret) + goto out; + + if(server == NULL){ + ret = _krb5_principalname2krb5_principal(context, + &service, + ap_req.ticket.sname, + ap_req.ticket.realm); + if (ret) + goto out; + server = service; + } + if (ap_req.ap_options.use_session_key && + (*auth_context)->keyblock == NULL) { + krb5_set_error_string(context, "krb5_rd_req: user to user auth " + "without session key given"); + ret = KRB5KRB_AP_ERR_NOKEY; + goto out; + } + + if((*auth_context)->keyblock){ + ret = krb5_copy_keyblock(context, + (*auth_context)->keyblock, + &o->keyblock); + if (ret) + goto out; + } else if(inctx->keyblock){ + ret = krb5_copy_keyblock(context, + inctx->keyblock, + &o->keyblock); + if (ret) + goto out; + } else { + krb5_keytab keytab = NULL; + + if (inctx && inctx->keytab) + keytab = inctx->keytab; + + ret = get_key_from_keytab(context, + auth_context, + &ap_req, + server, + keytab, + &o->keyblock); + if(ret) + goto out; + } + + ret = krb5_verify_ap_req2(context, + auth_context, + &ap_req, + server, + o->keyblock, + 0, + &o->ap_req_options, + &o->ticket, + KRB5_KU_AP_REQ_AUTH); + + if (ret) + goto out; + + /* If there is a PAC, verify its server signature */ + if (inctx->check_pac) { + krb5_pac pac; + krb5_data data; + + ret = krb5_ticket_get_authorization_data_type(context, + o->ticket, + KRB5_AUTHDATA_WIN2K_PAC, + &data); + if (ret == 0) { + ret = krb5_pac_parse(context, data.data, data.length, &pac); + krb5_data_free(&data); + if (ret) + goto out; + + ret = krb5_pac_verify(context, + pac, + o->ticket->ticket.authtime, + o->ticket->client, + o->keyblock, + NULL); + krb5_pac_free(context, pac); + if (ret) + goto out; + } + ret = 0; + } +out: + if (ret || outctx == NULL) { + krb5_rd_req_out_ctx_free(context, o); + } else + *outctx = o; + + free_AP_REQ(&ap_req); + if(service) + krb5_free_principal(context, service); + return ret; +} diff --git a/lib/krb5/rd_safe.c b/lib/krb5/rd_safe.c new file mode 100644 index 0000000..b2fb5c5 --- /dev/null +++ b/lib/krb5/rd_safe.c @@ -0,0 +1,213 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <krb5_locl.h> + +RCSID("$Id: rd_safe.c 19827 2007-01-11 02:54:59Z lha $"); + +static krb5_error_code +verify_checksum(krb5_context context, + krb5_auth_context auth_context, + KRB_SAFE *safe) +{ + krb5_error_code ret; + u_char *buf; + size_t buf_size; + size_t len; + Checksum c; + krb5_crypto crypto; + krb5_keyblock *key; + + c = safe->cksum; + safe->cksum.cksumtype = 0; + safe->cksum.checksum.data = NULL; + safe->cksum.checksum.length = 0; + + ASN1_MALLOC_ENCODE(KRB_SAFE, buf, buf_size, safe, &len, ret); + if(ret) + return ret; + if(buf_size != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + + if (auth_context->remote_subkey) + key = auth_context->remote_subkey; + else if (auth_context->local_subkey) + key = auth_context->local_subkey; + else + key = auth_context->keyblock; + + ret = krb5_crypto_init(context, key, 0, &crypto); + if (ret) + goto out; + ret = krb5_verify_checksum (context, + crypto, + KRB5_KU_KRB_SAFE_CKSUM, + buf + buf_size - len, + len, + &c); + krb5_crypto_destroy(context, crypto); +out: + safe->cksum = c; + free (buf); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_safe(krb5_context context, + krb5_auth_context auth_context, + const krb5_data *inbuf, + krb5_data *outbuf, + krb5_replay_data *outdata) +{ + krb5_error_code ret; + KRB_SAFE safe; + size_t len; + + if (outbuf) + krb5_data_zero(outbuf); + + if ((auth_context->flags & + (KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE)) && + outdata == NULL) { + krb5_set_error_string(context, "rd_safe: need outdata to return data"); + return KRB5_RC_REQUIRED; /* XXX better error, MIT returns this */ + } + + ret = decode_KRB_SAFE (inbuf->data, inbuf->length, &safe, &len); + if (ret) + return ret; + if (safe.pvno != 5) { + ret = KRB5KRB_AP_ERR_BADVERSION; + krb5_clear_error_string (context); + goto failure; + } + if (safe.msg_type != krb_safe) { + ret = KRB5KRB_AP_ERR_MSG_TYPE; + krb5_clear_error_string (context); + goto failure; + } + if (!krb5_checksum_is_keyed(context, safe.cksum.cksumtype) + || !krb5_checksum_is_collision_proof(context, safe.cksum.cksumtype)) { + ret = KRB5KRB_AP_ERR_INAPP_CKSUM; + krb5_clear_error_string (context); + goto failure; + } + + /* check sender address */ + + if (safe.safe_body.s_address + && auth_context->remote_address + && !krb5_address_compare (context, + auth_context->remote_address, + safe.safe_body.s_address)) { + ret = KRB5KRB_AP_ERR_BADADDR; + krb5_clear_error_string (context); + goto failure; + } + + /* check receiver address */ + + if (safe.safe_body.r_address + && auth_context->local_address + && !krb5_address_compare (context, + auth_context->local_address, + safe.safe_body.r_address)) { + ret = KRB5KRB_AP_ERR_BADADDR; + krb5_clear_error_string (context); + goto failure; + } + + /* check timestamp */ + if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) { + krb5_timestamp sec; + + krb5_timeofday (context, &sec); + + if (safe.safe_body.timestamp == NULL || + safe.safe_body.usec == NULL || + abs(*safe.safe_body.timestamp - sec) > context->max_skew) { + ret = KRB5KRB_AP_ERR_SKEW; + krb5_clear_error_string (context); + goto failure; + } + } + /* XXX - check replay cache */ + + /* check sequence number. since MIT krb5 cannot generate a sequence + number of zero but instead generates no sequence number, we accept that + */ + + if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) { + if ((safe.safe_body.seq_number == NULL + && auth_context->remote_seqnumber != 0) + || (safe.safe_body.seq_number != NULL + && *safe.safe_body.seq_number != + auth_context->remote_seqnumber)) { + ret = KRB5KRB_AP_ERR_BADORDER; + krb5_clear_error_string (context); + goto failure; + } + auth_context->remote_seqnumber++; + } + + ret = verify_checksum (context, auth_context, &safe); + if (ret) + goto failure; + + outbuf->length = safe.safe_body.user_data.length; + outbuf->data = malloc(outbuf->length); + if (outbuf->data == NULL && outbuf->length != 0) { + ret = ENOMEM; + krb5_set_error_string (context, "malloc: out of memory"); + krb5_data_zero(outbuf); + goto failure; + } + memcpy (outbuf->data, safe.safe_body.user_data.data, outbuf->length); + + if ((auth_context->flags & + (KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE))) { + /* if these fields are not present in the safe-part, silently + return zero */ + memset(outdata, 0, sizeof(*outdata)); + if(safe.safe_body.timestamp) + outdata->timestamp = *safe.safe_body.timestamp; + if(safe.safe_body.usec) + outdata->usec = *safe.safe_body.usec; + if(safe.safe_body.seq_number) + outdata->seq = *safe.safe_body.seq_number; + } + + failure: + free_KRB_SAFE (&safe); + return ret; +} diff --git a/lib/krb5/read_message.c b/lib/krb5/read_message.c new file mode 100644 index 0000000..5e03507 --- /dev/null +++ b/lib/krb5/read_message.c @@ -0,0 +1,106 @@ +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: read_message.c 21750 2007-07-31 20:41:25Z lha $"); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_read_message (krb5_context context, + krb5_pointer p_fd, + krb5_data *data) +{ + krb5_error_code ret; + uint32_t len; + uint8_t buf[4]; + + krb5_data_zero(data); + + ret = krb5_net_read (context, p_fd, buf, 4); + if(ret == -1) { + ret = errno; + krb5_clear_error_string (context); + return ret; + } + if(ret < 4) { + krb5_clear_error_string(context); + return HEIM_ERR_EOF; + } + len = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; + ret = krb5_data_alloc (data, len); + if (ret) { + krb5_clear_error_string(context); + return ret; + } + if (krb5_net_read (context, p_fd, data->data, len) != len) { + ret = errno; + krb5_data_free (data); + krb5_clear_error_string (context); + return ret; + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_read_priv_message(krb5_context context, + krb5_auth_context ac, + krb5_pointer p_fd, + krb5_data *data) +{ + krb5_error_code ret; + krb5_data packet; + + ret = krb5_read_message(context, p_fd, &packet); + if(ret) + return ret; + ret = krb5_rd_priv (context, ac, &packet, data, NULL); + krb5_data_free(&packet); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_read_safe_message(krb5_context context, + krb5_auth_context ac, + krb5_pointer p_fd, + krb5_data *data) +{ + krb5_error_code ret; + krb5_data packet; + + ret = krb5_read_message(context, p_fd, &packet); + if(ret) + return ret; + ret = krb5_rd_safe (context, ac, &packet, data, NULL); + krb5_data_free(&packet); + return ret; +} diff --git a/lib/krb5/recvauth.c b/lib/krb5/recvauth.c new file mode 100644 index 0000000..0348285 --- /dev/null +++ b/lib/krb5/recvauth.c @@ -0,0 +1,211 @@ +/* + * Copyright (c) 1997-2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: recvauth.c 20306 2007-04-11 11:15:55Z lha $"); + +/* + * See `sendauth.c' for the format. + */ + +static krb5_boolean +match_exact(const void *data, const char *appl_version) +{ + return strcmp(data, appl_version) == 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_recvauth(krb5_context context, + krb5_auth_context *auth_context, + krb5_pointer p_fd, + const char *appl_version, + krb5_principal server, + int32_t flags, + krb5_keytab keytab, + krb5_ticket **ticket) +{ + return krb5_recvauth_match_version(context, auth_context, p_fd, + match_exact, appl_version, + server, flags, + keytab, ticket); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_recvauth_match_version(krb5_context context, + krb5_auth_context *auth_context, + krb5_pointer p_fd, + krb5_boolean (*match_appl_version)(const void *, + const char*), + const void *match_data, + krb5_principal server, + int32_t flags, + krb5_keytab keytab, + krb5_ticket **ticket) +{ + krb5_error_code ret; + const char *version = KRB5_SENDAUTH_VERSION; + char her_version[sizeof(KRB5_SENDAUTH_VERSION)]; + char *her_appl_version; + uint32_t len; + u_char repl; + krb5_data data; + krb5_flags ap_options; + ssize_t n; + + /* + * If there are no addresses in auth_context, get them from `fd'. + */ + + if (*auth_context == NULL) { + ret = krb5_auth_con_init (context, auth_context); + if (ret) + return ret; + } + + ret = krb5_auth_con_setaddrs_from_fd (context, + *auth_context, + p_fd); + if (ret) + return ret; + + if(!(flags & KRB5_RECVAUTH_IGNORE_VERSION)) { + n = krb5_net_read (context, p_fd, &len, 4); + if (n < 0) { + ret = errno; + krb5_set_error_string (context, "read: %s", strerror(errno)); + return ret; + } + if (n == 0) { + krb5_set_error_string (context, "Failed to receive sendauth data"); + return KRB5_SENDAUTH_BADAUTHVERS; + } + len = ntohl(len); + if (len != sizeof(her_version) + || krb5_net_read (context, p_fd, her_version, len) != len + || strncmp (version, her_version, len)) { + repl = 1; + krb5_net_write (context, p_fd, &repl, 1); + krb5_clear_error_string (context); + return KRB5_SENDAUTH_BADAUTHVERS; + } + } + + n = krb5_net_read (context, p_fd, &len, 4); + if (n < 0) { + ret = errno; + krb5_set_error_string (context, "read: %s", strerror(errno)); + return ret; + } + if (n == 0) { + krb5_clear_error_string (context); + return KRB5_SENDAUTH_BADAPPLVERS; + } + len = ntohl(len); + her_appl_version = malloc (len); + if (her_appl_version == NULL) { + repl = 2; + krb5_net_write (context, p_fd, &repl, 1); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + if (krb5_net_read (context, p_fd, her_appl_version, len) != len + || !(*match_appl_version)(match_data, her_appl_version)) { + repl = 2; + krb5_net_write (context, p_fd, &repl, 1); + krb5_set_error_string (context, "wrong sendauth version (%s)", + her_appl_version); + free (her_appl_version); + return KRB5_SENDAUTH_BADAPPLVERS; + } + free (her_appl_version); + + repl = 0; + if (krb5_net_write (context, p_fd, &repl, 1) != 1) { + ret = errno; + krb5_set_error_string (context, "write: %s", strerror(errno)); + return ret; + } + + krb5_data_zero (&data); + ret = krb5_read_message (context, p_fd, &data); + if (ret) + return ret; + + ret = krb5_rd_req (context, + auth_context, + &data, + server, + keytab, + &ap_options, + ticket); + krb5_data_free (&data); + if (ret) { + krb5_data error_data; + krb5_error_code ret2; + + ret2 = krb5_mk_error (context, + ret, + NULL, + NULL, + NULL, + server, + NULL, + NULL, + &error_data); + if (ret2 == 0) { + krb5_write_message (context, p_fd, &error_data); + krb5_data_free (&error_data); + } + return ret; + } + + len = 0; + if (krb5_net_write (context, p_fd, &len, 4) != 4) { + ret = errno; + krb5_set_error_string (context, "write: %s", strerror(errno)); + return ret; + } + + if (ap_options & AP_OPTS_MUTUAL_REQUIRED) { + ret = krb5_mk_rep (context, *auth_context, &data); + if (ret) + return ret; + + ret = krb5_write_message (context, p_fd, &data); + if (ret) + return ret; + krb5_data_free (&data); + } + return 0; +} diff --git a/lib/krb5/replay.c b/lib/krb5/replay.c new file mode 100644 index 0000000..12894d9 --- /dev/null +++ b/lib/krb5/replay.c @@ -0,0 +1,312 @@ +/* + * Copyright (c) 1997-2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" +#include <vis.h> + +RCSID("$Id: replay.c 17047 2006-04-10 17:13:49Z lha $"); + +struct krb5_rcache_data { + char *name; +}; + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_resolve(krb5_context context, + krb5_rcache id, + const char *name) +{ + id->name = strdup(name); + if(id->name == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return KRB5_RC_MALLOC; + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_resolve_type(krb5_context context, + krb5_rcache *id, + const char *type) +{ + *id = NULL; + if(strcmp(type, "FILE")) { + krb5_set_error_string (context, "replay cache type %s not supported", + type); + return KRB5_RC_TYPE_NOTFOUND; + } + *id = calloc(1, sizeof(**id)); + if(*id == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return KRB5_RC_MALLOC; + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_resolve_full(krb5_context context, + krb5_rcache *id, + const char *string_name) +{ + krb5_error_code ret; + + *id = NULL; + + if(strncmp(string_name, "FILE:", 5)) { + krb5_set_error_string (context, "replay cache type %s not supported", + string_name); + return KRB5_RC_TYPE_NOTFOUND; + } + ret = krb5_rc_resolve_type(context, id, "FILE"); + if(ret) + return ret; + ret = krb5_rc_resolve(context, *id, string_name + 5); + if (ret) { + krb5_rc_close(context, *id); + *id = NULL; + } + return ret; +} + +const char* KRB5_LIB_FUNCTION +krb5_rc_default_name(krb5_context context) +{ + return "FILE:/var/run/default_rcache"; +} + +const char* KRB5_LIB_FUNCTION +krb5_rc_default_type(krb5_context context) +{ + return "FILE"; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_default(krb5_context context, + krb5_rcache *id) +{ + return krb5_rc_resolve_full(context, id, krb5_rc_default_name(context)); +} + +struct rc_entry{ + time_t stamp; + unsigned char data[16]; +}; + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_initialize(krb5_context context, + krb5_rcache id, + krb5_deltat auth_lifespan) +{ + FILE *f = fopen(id->name, "w"); + struct rc_entry tmp; + int ret; + + if(f == NULL) { + ret = errno; + krb5_set_error_string (context, "open(%s): %s", id->name, + strerror(ret)); + return ret; + } + tmp.stamp = auth_lifespan; + fwrite(&tmp, 1, sizeof(tmp), f); + fclose(f); + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_recover(krb5_context context, + krb5_rcache id) +{ + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_destroy(krb5_context context, + krb5_rcache id) +{ + int ret; + + if(remove(id->name) < 0) { + ret = errno; + krb5_set_error_string (context, "remove(%s): %s", id->name, + strerror(ret)); + return ret; + } + return krb5_rc_close(context, id); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_close(krb5_context context, + krb5_rcache id) +{ + free(id->name); + free(id); + return 0; +} + +static void +checksum_authenticator(Authenticator *auth, void *data) +{ + MD5_CTX md5; + int i; + + MD5_Init (&md5); + MD5_Update (&md5, auth->crealm, strlen(auth->crealm)); + for(i = 0; i < auth->cname.name_string.len; i++) + MD5_Update(&md5, auth->cname.name_string.val[i], + strlen(auth->cname.name_string.val[i])); + MD5_Update (&md5, &auth->ctime, sizeof(auth->ctime)); + MD5_Update (&md5, &auth->cusec, sizeof(auth->cusec)); + MD5_Final (data, &md5); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_store(krb5_context context, + krb5_rcache id, + krb5_donot_replay *rep) +{ + struct rc_entry ent, tmp; + time_t t; + FILE *f; + int ret; + + ent.stamp = time(NULL); + checksum_authenticator(rep, ent.data); + f = fopen(id->name, "r"); + if(f == NULL) { + ret = errno; + krb5_set_error_string (context, "open(%s): %s", id->name, + strerror(ret)); + return ret; + } + fread(&tmp, sizeof(ent), 1, f); + t = ent.stamp - tmp.stamp; + while(fread(&tmp, sizeof(ent), 1, f)){ + if(tmp.stamp < t) + continue; + if(memcmp(tmp.data, ent.data, sizeof(ent.data)) == 0){ + fclose(f); + krb5_clear_error_string (context); + return KRB5_RC_REPLAY; + } + } + if(ferror(f)){ + ret = errno; + fclose(f); + krb5_set_error_string (context, "%s: %s", id->name, strerror(ret)); + return ret; + } + fclose(f); + f = fopen(id->name, "a"); + if(f == NULL) { + krb5_set_error_string (context, "open(%s): %s", id->name, + strerror(errno)); + return KRB5_RC_IO_UNKNOWN; + } + fwrite(&ent, 1, sizeof(ent), f); + fclose(f); + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_expunge(krb5_context context, + krb5_rcache id) +{ + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_get_lifespan(krb5_context context, + krb5_rcache id, + krb5_deltat *auth_lifespan) +{ + FILE *f = fopen(id->name, "r"); + int r; + struct rc_entry ent; + r = fread(&ent, sizeof(ent), 1, f); + fclose(f); + if(r){ + *auth_lifespan = ent.stamp; + return 0; + } + krb5_clear_error_string (context); + return KRB5_RC_IO_UNKNOWN; +} + +const char* KRB5_LIB_FUNCTION +krb5_rc_get_name(krb5_context context, + krb5_rcache id) +{ + return id->name; +} + +const char* KRB5_LIB_FUNCTION +krb5_rc_get_type(krb5_context context, + krb5_rcache id) +{ + return "FILE"; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_server_rcache(krb5_context context, + const krb5_data *piece, + krb5_rcache *id) +{ + krb5_rcache rcache; + krb5_error_code ret; + + char *tmp = malloc(4 * piece->length + 1); + char *name; + + if(tmp == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + strvisx(tmp, piece->data, piece->length, VIS_WHITE | VIS_OCTAL); +#ifdef HAVE_GETEUID + asprintf(&name, "FILE:rc_%s_%u", tmp, (unsigned)geteuid()); +#else + asprintf(&name, "FILE:rc_%s", tmp); +#endif + free(tmp); + if(name == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + + ret = krb5_rc_resolve_full(context, &rcache, name); + free(name); + if(ret) + return ret; + *id = rcache; + return ret; +} diff --git a/lib/krb5/send_to_kdc.c b/lib/krb5/send_to_kdc.c new file mode 100644 index 0000000..2582a61 --- /dev/null +++ b/lib/krb5/send_to_kdc.c @@ -0,0 +1,604 @@ +/* + * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: send_to_kdc.c 21934 2007-08-27 14:21:04Z lha $"); + +struct send_to_kdc { + krb5_send_to_kdc_func func; + void *data; +}; + +/* + * send the data in `req' on the socket `fd' (which is datagram iff udp) + * waiting `tmout' for a reply and returning the reply in `rep'. + * iff limit read up to this many bytes + * returns 0 and data in `rep' if succesful, otherwise -1 + */ + +static int +recv_loop (int fd, + time_t tmout, + int udp, + size_t limit, + krb5_data *rep) +{ + fd_set fdset; + struct timeval timeout; + int ret; + int nbytes; + + if (fd >= FD_SETSIZE) { + return -1; + } + + krb5_data_zero(rep); + do { + FD_ZERO(&fdset); + FD_SET(fd, &fdset); + timeout.tv_sec = tmout; + timeout.tv_usec = 0; + ret = select (fd + 1, &fdset, NULL, NULL, &timeout); + if (ret < 0) { + if (errno == EINTR) + continue; + return -1; + } else if (ret == 0) { + return 0; + } else { + void *tmp; + + if (ioctl (fd, FIONREAD, &nbytes) < 0) { + krb5_data_free (rep); + return -1; + } + if(nbytes <= 0) + return 0; + + if (limit) + nbytes = min(nbytes, limit - rep->length); + + tmp = realloc (rep->data, rep->length + nbytes); + if (tmp == NULL) { + krb5_data_free (rep); + return -1; + } + rep->data = tmp; + ret = recv (fd, (char*)tmp + rep->length, nbytes, 0); + if (ret < 0) { + krb5_data_free (rep); + return -1; + } + rep->length += ret; + } + } while(!udp && (limit == 0 || rep->length < limit)); + return 0; +} + +/* + * Send kerberos requests and receive a reply on a udp or any other kind + * of a datagram socket. See `recv_loop'. + */ + +static int +send_and_recv_udp(int fd, + time_t tmout, + const krb5_data *req, + krb5_data *rep) +{ + if (send (fd, req->data, req->length, 0) < 0) + return -1; + + return recv_loop(fd, tmout, 1, 0, rep); +} + +/* + * `send_and_recv' for a TCP (or any other stream) socket. + * Since there are no record limits on a stream socket the protocol here + * is to prepend the request with 4 bytes of its length and the reply + * is similarly encoded. + */ + +static int +send_and_recv_tcp(int fd, + time_t tmout, + const krb5_data *req, + krb5_data *rep) +{ + unsigned char len[4]; + unsigned long rep_len; + krb5_data len_data; + + _krb5_put_int(len, req->length, 4); + if(net_write(fd, len, sizeof(len)) < 0) + return -1; + if(net_write(fd, req->data, req->length) < 0) + return -1; + if (recv_loop (fd, tmout, 0, 4, &len_data) < 0) + return -1; + if (len_data.length != 4) { + krb5_data_free (&len_data); + return -1; + } + _krb5_get_int(len_data.data, &rep_len, 4); + krb5_data_free (&len_data); + if (recv_loop (fd, tmout, 0, rep_len, rep) < 0) + return -1; + if(rep->length != rep_len) { + krb5_data_free (rep); + return -1; + } + return 0; +} + +int +_krb5_send_and_recv_tcp(int fd, + time_t tmout, + const krb5_data *req, + krb5_data *rep) +{ + return send_and_recv_tcp(fd, tmout, req, rep); +} + +/* + * `send_and_recv' tailored for the HTTP protocol. + */ + +static int +send_and_recv_http(int fd, + time_t tmout, + const char *prefix, + const krb5_data *req, + krb5_data *rep) +{ + char *request; + char *str; + int ret; + int len = base64_encode(req->data, req->length, &str); + + if(len < 0) + return -1; + asprintf(&request, "GET %s%s HTTP/1.0\r\n\r\n", prefix, str); + free(str); + if (request == NULL) + return -1; + ret = net_write (fd, request, strlen(request)); + free (request); + if (ret < 0) + return ret; + ret = recv_loop(fd, tmout, 0, 0, rep); + if(ret) + return ret; + { + unsigned long rep_len; + char *s, *p; + + s = realloc(rep->data, rep->length + 1); + if (s == NULL) { + krb5_data_free (rep); + return -1; + } + s[rep->length] = 0; + p = strstr(s, "\r\n\r\n"); + if(p == NULL) { + krb5_data_zero(rep); + free(s); + return -1; + } + p += 4; + rep->data = s; + rep->length -= p - s; + if(rep->length < 4) { /* remove length */ + krb5_data_zero(rep); + free(s); + return -1; + } + rep->length -= 4; + _krb5_get_int(p, &rep_len, 4); + if (rep_len != rep->length) { + krb5_data_zero(rep); + free(s); + return -1; + } + memmove(rep->data, p + 4, rep->length); + } + return 0; +} + +static int +init_port(const char *s, int fallback) +{ + if (s) { + int tmp; + + sscanf (s, "%d", &tmp); + return htons(tmp); + } else + return fallback; +} + +/* + * Return 0 if succesful, otherwise 1 + */ + +static int +send_via_proxy (krb5_context context, + const krb5_krbhst_info *hi, + const krb5_data *send_data, + krb5_data *receive) +{ + char *proxy2 = strdup(context->http_proxy); + char *proxy = proxy2; + char *prefix; + char *colon; + struct addrinfo hints; + struct addrinfo *ai, *a; + int ret; + int s = -1; + char portstr[NI_MAXSERV]; + + if (proxy == NULL) + return ENOMEM; + if (strncmp (proxy, "http://", 7) == 0) + proxy += 7; + + colon = strchr(proxy, ':'); + if(colon != NULL) + *colon++ = '\0'; + memset (&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + snprintf (portstr, sizeof(portstr), "%d", + ntohs(init_port (colon, htons(80)))); + ret = getaddrinfo (proxy, portstr, &hints, &ai); + free (proxy2); + if (ret) + return krb5_eai_to_heim_errno(ret, errno); + + for (a = ai; a != NULL; a = a->ai_next) { + s = socket (a->ai_family, a->ai_socktype, a->ai_protocol); + if (s < 0) + continue; + if (connect (s, a->ai_addr, a->ai_addrlen) < 0) { + close (s); + continue; + } + break; + } + if (a == NULL) { + freeaddrinfo (ai); + return 1; + } + freeaddrinfo (ai); + + asprintf(&prefix, "http://%s/", hi->hostname); + if(prefix == NULL) { + close(s); + return 1; + } + ret = send_and_recv_http(s, context->kdc_timeout, + prefix, send_data, receive); + close (s); + free(prefix); + if(ret == 0 && receive->length != 0) + return 0; + return 1; +} + +/* + * Send the data `send' to one host from `handle` and get back the reply + * in `receive'. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_sendto (krb5_context context, + const krb5_data *send_data, + krb5_krbhst_handle handle, + krb5_data *receive) +{ + krb5_error_code ret; + int fd; + int i; + + krb5_data_zero(receive); + + for (i = 0; i < context->max_retries; ++i) { + krb5_krbhst_info *hi; + + while (krb5_krbhst_next(context, handle, &hi) == 0) { + struct addrinfo *ai, *a; + + if (context->send_to_kdc) { + struct send_to_kdc *s = context->send_to_kdc; + + ret = (*s->func)(context, s->data, + hi, send_data, receive); + if (ret == 0 && receive->length != 0) + goto out; + continue; + } + + if(hi->proto == KRB5_KRBHST_HTTP && context->http_proxy) { + if (send_via_proxy (context, hi, send_data, receive) == 0) { + ret = 0; + goto out; + } + continue; + } + + ret = krb5_krbhst_get_addrinfo(context, hi, &ai); + if (ret) + continue; + + for (a = ai; a != NULL; a = a->ai_next) { + fd = socket (a->ai_family, a->ai_socktype, a->ai_protocol); + if (fd < 0) + continue; + if (connect (fd, a->ai_addr, a->ai_addrlen) < 0) { + close (fd); + continue; + } + switch (hi->proto) { + case KRB5_KRBHST_HTTP : + ret = send_and_recv_http(fd, context->kdc_timeout, + "", send_data, receive); + break; + case KRB5_KRBHST_TCP : + ret = send_and_recv_tcp (fd, context->kdc_timeout, + send_data, receive); + break; + case KRB5_KRBHST_UDP : + ret = send_and_recv_udp (fd, context->kdc_timeout, + send_data, receive); + break; + } + close (fd); + if(ret == 0 && receive->length != 0) + goto out; + } + } + krb5_krbhst_reset(context, handle); + } + krb5_clear_error_string (context); + ret = KRB5_KDC_UNREACH; +out: + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_sendto_kdc(krb5_context context, + const krb5_data *send_data, + const krb5_realm *realm, + krb5_data *receive) +{ + return krb5_sendto_kdc_flags(context, send_data, realm, receive, 0); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_sendto_kdc_flags(krb5_context context, + const krb5_data *send_data, + const krb5_realm *realm, + krb5_data *receive, + int flags) +{ + krb5_error_code ret; + krb5_sendto_ctx ctx; + + ret = krb5_sendto_ctx_alloc(context, &ctx); + if (ret) + return ret; + krb5_sendto_ctx_add_flags(ctx, flags); + krb5_sendto_ctx_set_func(ctx, _krb5_kdc_retry, NULL); + + ret = krb5_sendto_context(context, ctx, send_data, *realm, receive); + krb5_sendto_ctx_free(context, ctx); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_send_to_kdc_func(krb5_context context, + krb5_send_to_kdc_func func, + void *data) +{ + free(context->send_to_kdc); + if (func == NULL) { + context->send_to_kdc = NULL; + return 0; + } + + context->send_to_kdc = malloc(sizeof(*context->send_to_kdc)); + if (context->send_to_kdc == NULL) { + krb5_set_error_string(context, "Out of memory"); + return ENOMEM; + } + + context->send_to_kdc->func = func; + context->send_to_kdc->data = data; + return 0; +} + +struct krb5_sendto_ctx_data { + int flags; + int type; + krb5_sendto_ctx_func func; + void *data; +}; + +krb5_error_code KRB5_LIB_FUNCTION +krb5_sendto_ctx_alloc(krb5_context context, krb5_sendto_ctx *ctx) +{ + *ctx = calloc(1, sizeof(**ctx)); + if (*ctx == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + return 0; +} + +void KRB5_LIB_FUNCTION +krb5_sendto_ctx_add_flags(krb5_sendto_ctx ctx, int flags) +{ + ctx->flags |= flags; +} + +int KRB5_LIB_FUNCTION +krb5_sendto_ctx_get_flags(krb5_sendto_ctx ctx) +{ + return ctx->flags; +} + +void KRB5_LIB_FUNCTION +krb5_sendto_ctx_set_type(krb5_sendto_ctx ctx, int type) +{ + ctx->type = type; +} + + +void KRB5_LIB_FUNCTION +krb5_sendto_ctx_set_func(krb5_sendto_ctx ctx, + krb5_sendto_ctx_func func, + void *data) +{ + ctx->func = func; + ctx->data = data; +} + +void KRB5_LIB_FUNCTION +krb5_sendto_ctx_free(krb5_context context, krb5_sendto_ctx ctx) +{ + memset(ctx, 0, sizeof(*ctx)); + free(ctx); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_sendto_context(krb5_context context, + krb5_sendto_ctx ctx, + const krb5_data *send_data, + const krb5_realm realm, + krb5_data *receive) +{ + krb5_error_code ret; + krb5_krbhst_handle handle = NULL; + int type, freectx = 0; + int action; + + krb5_data_zero(receive); + + if (ctx == NULL) { + freectx = 1; + ret = krb5_sendto_ctx_alloc(context, &ctx); + if (ret) + return ret; + } + + type = ctx->type; + if (type == 0) { + if ((ctx->flags & KRB5_KRBHST_FLAGS_MASTER) || context->use_admin_kdc) + type = KRB5_KRBHST_ADMIN; + else + type = KRB5_KRBHST_KDC; + } + + if (send_data->length > context->large_msg_size) + ctx->flags |= KRB5_KRBHST_FLAGS_LARGE_MSG; + + /* loop until we get back a appropriate response */ + + do { + action = KRB5_SENDTO_DONE; + + krb5_data_free(receive); + + if (handle == NULL) { + ret = krb5_krbhst_init_flags(context, realm, type, + ctx->flags, &handle); + if (ret) { + if (freectx) + krb5_sendto_ctx_free(context, ctx); + return ret; + } + } + + ret = krb5_sendto(context, send_data, handle, receive); + if (ret) + break; + if (ctx->func) { + ret = (*ctx->func)(context, ctx, ctx->data, receive, &action); + if (ret) + break; + } + if (action != KRB5_SENDTO_CONTINUE) { + krb5_krbhst_free(context, handle); + handle = NULL; + } + } while (action != KRB5_SENDTO_DONE); + if (handle) + krb5_krbhst_free(context, handle); + if (ret == KRB5_KDC_UNREACH) + krb5_set_error_string(context, + "unable to reach any KDC in realm %s", realm); + if (ret) + krb5_data_free(receive); + if (freectx) + krb5_sendto_ctx_free(context, ctx); + return ret; +} + +krb5_error_code +_krb5_kdc_retry(krb5_context context, krb5_sendto_ctx ctx, void *data, + const krb5_data *reply, int *action) +{ + krb5_error_code ret; + KRB_ERROR error; + + if(krb5_rd_error(context, reply, &error)) + return 0; + + ret = krb5_error_from_rd_error(context, &error, NULL); + krb5_free_error_contents(context, &error); + + switch(ret) { + case KRB5KRB_ERR_RESPONSE_TOO_BIG: { + if (krb5_sendto_ctx_get_flags(ctx) & KRB5_KRBHST_FLAGS_LARGE_MSG) + break; + krb5_sendto_ctx_add_flags(ctx, KRB5_KRBHST_FLAGS_LARGE_MSG); + *action = KRB5_SENDTO_RESTART; + break; + } + case KRB5KDC_ERR_SVC_UNAVAILABLE: + *action = KRB5_SENDTO_CONTINUE; + break; + } + return 0; +} diff --git a/lib/krb5/sendauth.c b/lib/krb5/sendauth.c new file mode 100644 index 0000000..a7242f0 --- /dev/null +++ b/lib/krb5/sendauth.c @@ -0,0 +1,233 @@ +/* + * Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: sendauth.c 17442 2006-05-05 09:31:15Z lha $"); + +/* + * The format seems to be: + * client -> server + * + * 4 bytes - length + * KRB5_SENDAUTH_V1.0 (including zero) + * 4 bytes - length + * protocol string (with terminating zero) + * + * server -> client + * 1 byte - (0 = OK, else some kind of error) + * + * client -> server + * 4 bytes - length + * AP-REQ + * + * server -> client + * 4 bytes - length (0 = OK, else length of error) + * (error) + * + * if(mutual) { + * server -> client + * 4 bytes - length + * AP-REP + * } + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_sendauth(krb5_context context, + krb5_auth_context *auth_context, + krb5_pointer p_fd, + const char *appl_version, + krb5_principal client, + krb5_principal server, + krb5_flags ap_req_options, + krb5_data *in_data, + krb5_creds *in_creds, + krb5_ccache ccache, + krb5_error **ret_error, + krb5_ap_rep_enc_part **rep_result, + krb5_creds **out_creds) +{ + krb5_error_code ret; + uint32_t len, net_len; + const char *version = KRB5_SENDAUTH_VERSION; + u_char repl; + krb5_data ap_req, error_data; + krb5_creds this_cred; + krb5_principal this_client = NULL; + krb5_creds *creds; + ssize_t sret; + krb5_boolean my_ccache = FALSE; + + len = strlen(version) + 1; + net_len = htonl(len); + if (krb5_net_write (context, p_fd, &net_len, 4) != 4 + || krb5_net_write (context, p_fd, version, len) != len) { + ret = errno; + krb5_set_error_string (context, "write: %s", strerror(ret)); + return ret; + } + + len = strlen(appl_version) + 1; + net_len = htonl(len); + if (krb5_net_write (context, p_fd, &net_len, 4) != 4 + || krb5_net_write (context, p_fd, appl_version, len) != len) { + ret = errno; + krb5_set_error_string (context, "write: %s", strerror(ret)); + return ret; + } + + sret = krb5_net_read (context, p_fd, &repl, sizeof(repl)); + if (sret < 0) { + ret = errno; + krb5_set_error_string (context, "read: %s", strerror(ret)); + return ret; + } else if (sret != sizeof(repl)) { + krb5_clear_error_string (context); + return KRB5_SENDAUTH_BADRESPONSE; + } + + if (repl != 0) { + krb5_clear_error_string (context); + return KRB5_SENDAUTH_REJECTED; + } + + if (in_creds == NULL) { + if (ccache == NULL) { + ret = krb5_cc_default (context, &ccache); + if (ret) + return ret; + my_ccache = TRUE; + } + + if (client == NULL) { + ret = krb5_cc_get_principal (context, ccache, &this_client); + if (ret) { + if(my_ccache) + krb5_cc_close(context, ccache); + return ret; + } + client = this_client; + } + memset(&this_cred, 0, sizeof(this_cred)); + this_cred.client = client; + this_cred.server = server; + this_cred.times.endtime = 0; + this_cred.ticket.length = 0; + in_creds = &this_cred; + } + if (in_creds->ticket.length == 0) { + ret = krb5_get_credentials (context, 0, ccache, in_creds, &creds); + if (ret) { + if(my_ccache) + krb5_cc_close(context, ccache); + return ret; + } + } else { + creds = in_creds; + } + if(my_ccache) + krb5_cc_close(context, ccache); + ret = krb5_mk_req_extended (context, + auth_context, + ap_req_options, + in_data, + creds, + &ap_req); + + if (out_creds) + *out_creds = creds; + else + krb5_free_creds(context, creds); + if(this_client) + krb5_free_principal(context, this_client); + + if (ret) + return ret; + + ret = krb5_write_message (context, + p_fd, + &ap_req); + if (ret) + return ret; + + krb5_data_free (&ap_req); + + ret = krb5_read_message (context, p_fd, &error_data); + if (ret) + return ret; + + if (error_data.length != 0) { + KRB_ERROR error; + + ret = krb5_rd_error (context, &error_data, &error); + krb5_data_free (&error_data); + if (ret == 0) { + ret = krb5_error_from_rd_error(context, &error, NULL); + if (ret_error != NULL) { + *ret_error = malloc (sizeof(krb5_error)); + if (*ret_error == NULL) { + krb5_free_error_contents (context, &error); + } else { + **ret_error = error; + } + } else { + krb5_free_error_contents (context, &error); + } + return ret; + } else { + krb5_clear_error_string(context); + return ret; + } + } + + if (ap_req_options & AP_OPTS_MUTUAL_REQUIRED) { + krb5_data ap_rep; + krb5_ap_rep_enc_part *ignore; + + krb5_data_zero (&ap_rep); + ret = krb5_read_message (context, + p_fd, + &ap_rep); + if (ret) + return ret; + + ret = krb5_rd_rep (context, *auth_context, &ap_rep, + rep_result ? rep_result : &ignore); + krb5_data_free (&ap_rep); + if (ret) + return ret; + if (rep_result == NULL) + krb5_free_ap_rep_enc_part (context, ignore); + } + return 0; +} diff --git a/lib/krb5/set_default_realm.c b/lib/krb5/set_default_realm.c new file mode 100644 index 0000000..98040bc --- /dev/null +++ b/lib/krb5/set_default_realm.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: set_default_realm.c 13863 2004-05-25 21:46:46Z lha $"); + +/* + * Convert the simple string `s' into a NULL-terminated and freshly allocated + * list in `list'. Return an error code. + */ + +static krb5_error_code +string_to_list (krb5_context context, const char *s, krb5_realm **list) +{ + + *list = malloc (2 * sizeof(**list)); + if (*list == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + (*list)[0] = strdup (s); + if ((*list)[0] == NULL) { + free (*list); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + (*list)[1] = NULL; + return 0; +} + +/* + * Set the knowledge of the default realm(s) in `context'. + * If realm != NULL, that's the new default realm. + * Otherwise, the realm(s) are figured out from configuration or DNS. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_default_realm(krb5_context context, + const char *realm) +{ + krb5_error_code ret = 0; + krb5_realm *realms = NULL; + + if (realm == NULL) { + realms = krb5_config_get_strings (context, NULL, + "libdefaults", + "default_realm", + NULL); + if (realms == NULL) + ret = krb5_get_host_realm(context, NULL, &realms); + } else { + ret = string_to_list (context, realm, &realms); + } + if (ret) + return ret; + krb5_free_host_realm (context, context->default_realms); + context->default_realms = realms; + return 0; +} diff --git a/lib/krb5/sock_principal.c b/lib/krb5/sock_principal.c new file mode 100644 index 0000000..9b4ba97 --- /dev/null +++ b/lib/krb5/sock_principal.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: sock_principal.c 13863 2004-05-25 21:46:46Z lha $"); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_sock_to_principal (krb5_context context, + int sock, + const char *sname, + int32_t type, + krb5_principal *ret_princ) +{ + krb5_error_code ret; + struct sockaddr_storage __ss; + struct sockaddr *sa = (struct sockaddr *)&__ss; + socklen_t salen = sizeof(__ss); + char hostname[NI_MAXHOST]; + + if (getsockname (sock, sa, &salen) < 0) { + ret = errno; + krb5_set_error_string (context, "getsockname: %s", strerror(ret)); + return ret; + } + ret = getnameinfo (sa, salen, hostname, sizeof(hostname), NULL, 0, 0); + if (ret) { + int save_errno = errno; + + krb5_set_error_string (context, "getnameinfo: %s", gai_strerror(ret)); + return krb5_eai_to_heim_errno(ret, save_errno); + } + + ret = krb5_sname_to_principal (context, + hostname, + sname, + type, + ret_princ); + return ret; +} diff --git a/lib/krb5/store-int.h b/lib/krb5/store-int.h new file mode 100644 index 0000000..42e695a --- /dev/null +++ b/lib/krb5/store-int.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2002 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef __store_int_h__ +#define __store_int_h__ + +struct krb5_storage_data { + void *data; + ssize_t (*fetch)(struct krb5_storage_data*, void*, size_t); + ssize_t (*store)(struct krb5_storage_data*, const void*, size_t); + off_t (*seek)(struct krb5_storage_data*, off_t, int); + void (*free)(struct krb5_storage_data*); + krb5_flags flags; + int eof_code; +}; + +#endif /* __store_int_h__ */ diff --git a/lib/krb5/store-test.c b/lib/krb5/store-test.c new file mode 100644 index 0000000..aec2dfe --- /dev/null +++ b/lib/krb5/store-test.c @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include "krb5_locl.h" + +RCSID("$Id: store-test.c 16344 2005-12-02 15:15:43Z lha $"); + +static void +print_data(unsigned char *data, size_t len) +{ + int i; + for(i = 0; i < len; i++) { + if(i > 0 && (i % 16) == 0) + printf("\n "); + printf("%02x ", data[i]); + } + printf("\n"); +} + +static int +compare(const char *name, krb5_storage *sp, void *expected, size_t len) +{ + int ret = 0; + krb5_data data; + krb5_storage_to_data(sp, &data); + krb5_storage_free(sp); + if(data.length != len || memcmp(data.data, expected, len) != 0) { + printf("%s mismatch\n", name); + printf(" Expected: "); + print_data(expected, len); + printf(" Actual: "); + print_data(data.data, data.length); + ret++; + } + krb5_data_free(&data); + return ret; +} + +int +main(int argc, char **argv) +{ + int nerr = 0; + krb5_storage *sp; + krb5_context context; + krb5_principal principal; + + + krb5_init_context(&context); + + sp = krb5_storage_emem(); + krb5_store_int32(sp, 0x01020304); + nerr += compare("Integer", sp, "\x1\x2\x3\x4", 4); + + sp = krb5_storage_emem(); + krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_LE); + krb5_store_int32(sp, 0x01020304); + nerr += compare("Integer (LE)", sp, "\x4\x3\x2\x1", 4); + + sp = krb5_storage_emem(); + krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_BE); + krb5_store_int32(sp, 0x01020304); + nerr += compare("Integer (BE)", sp, "\x1\x2\x3\x4", 4); + + sp = krb5_storage_emem(); + krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_HOST); + krb5_store_int32(sp, 0x01020304); + { + int test = 1; + void *data; + if(*(char*)&test) + data = "\x4\x3\x2\x1"; + else + data = "\x1\x2\x3\x4"; + nerr += compare("Integer (host)", sp, data, 4); + } + + sp = krb5_storage_emem(); + krb5_make_principal(context, &principal, "TEST", "foobar", NULL); + krb5_store_principal(sp, principal); + krb5_free_principal(context, principal); + nerr += compare("Principal", sp, "\x0\x0\x0\x1" + "\x0\x0\x0\x1" + "\x0\x0\x0\x4TEST" + "\x0\x0\x0\x6""foobar", 26); + + krb5_free_context(context); + + return nerr ? 1 : 0; +} diff --git a/lib/krb5/store.c b/lib/krb5/store.c new file mode 100644 index 0000000..c9cbbb5 --- /dev/null +++ b/lib/krb5/store.c @@ -0,0 +1,1035 @@ +/* + * Copyright (c) 1997-2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" +#include "store-int.h" + +RCSID("$Id: store.c 22071 2007-11-14 20:04:50Z lha $"); + +#define BYTEORDER_IS(SP, V) (((SP)->flags & KRB5_STORAGE_BYTEORDER_MASK) == (V)) +#define BYTEORDER_IS_LE(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_LE) +#define BYTEORDER_IS_BE(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_BE) +#define BYTEORDER_IS_HOST(SP) (BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_HOST) || \ + krb5_storage_is_flags((SP), KRB5_STORAGE_HOST_BYTEORDER)) + +void KRB5_LIB_FUNCTION +krb5_storage_set_flags(krb5_storage *sp, krb5_flags flags) +{ + sp->flags |= flags; +} + +void KRB5_LIB_FUNCTION +krb5_storage_clear_flags(krb5_storage *sp, krb5_flags flags) +{ + sp->flags &= ~flags; +} + +krb5_boolean KRB5_LIB_FUNCTION +krb5_storage_is_flags(krb5_storage *sp, krb5_flags flags) +{ + return (sp->flags & flags) == flags; +} + +void KRB5_LIB_FUNCTION +krb5_storage_set_byteorder(krb5_storage *sp, krb5_flags byteorder) +{ + sp->flags &= ~KRB5_STORAGE_BYTEORDER_MASK; + sp->flags |= byteorder; +} + +krb5_flags KRB5_LIB_FUNCTION +krb5_storage_get_byteorder(krb5_storage *sp, krb5_flags byteorder) +{ + return sp->flags & KRB5_STORAGE_BYTEORDER_MASK; +} + +off_t KRB5_LIB_FUNCTION +krb5_storage_seek(krb5_storage *sp, off_t offset, int whence) +{ + return (*sp->seek)(sp, offset, whence); +} + +krb5_ssize_t KRB5_LIB_FUNCTION +krb5_storage_read(krb5_storage *sp, void *buf, size_t len) +{ + return sp->fetch(sp, buf, len); +} + +krb5_ssize_t KRB5_LIB_FUNCTION +krb5_storage_write(krb5_storage *sp, const void *buf, size_t len) +{ + return sp->store(sp, buf, len); +} + +void KRB5_LIB_FUNCTION +krb5_storage_set_eof_code(krb5_storage *sp, int code) +{ + sp->eof_code = code; +} + +krb5_ssize_t KRB5_LIB_FUNCTION +_krb5_put_int(void *buffer, unsigned long value, size_t size) +{ + unsigned char *p = buffer; + int i; + for (i = size - 1; i >= 0; i--) { + p[i] = value & 0xff; + value >>= 8; + } + return size; +} + +krb5_ssize_t KRB5_LIB_FUNCTION +_krb5_get_int(void *buffer, unsigned long *value, size_t size) +{ + unsigned char *p = buffer; + unsigned long v = 0; + int i; + for (i = 0; i < size; i++) + v = (v << 8) + p[i]; + *value = v; + return size; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_storage_free(krb5_storage *sp) +{ + if(sp->free) + (*sp->free)(sp); + free(sp->data); + free(sp); + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_storage_to_data(krb5_storage *sp, krb5_data *data) +{ + off_t pos; + size_t size; + krb5_error_code ret; + + pos = sp->seek(sp, 0, SEEK_CUR); + size = (size_t)sp->seek(sp, 0, SEEK_END); + ret = krb5_data_alloc (data, size); + if (ret) { + sp->seek(sp, pos, SEEK_SET); + return ret; + } + if (size) { + sp->seek(sp, 0, SEEK_SET); + sp->fetch(sp, data->data, data->length); + sp->seek(sp, pos, SEEK_SET); + } + return 0; +} + +static krb5_error_code +krb5_store_int(krb5_storage *sp, + int32_t value, + size_t len) +{ + int ret; + unsigned char v[16]; + + if(len > sizeof(v)) + return EINVAL; + _krb5_put_int(v, value, len); + ret = sp->store(sp, v, len); + if (ret != len) + return (ret<0)?errno:sp->eof_code; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_int32(krb5_storage *sp, + int32_t value) +{ + if(BYTEORDER_IS_HOST(sp)) + value = htonl(value); + else if(BYTEORDER_IS_LE(sp)) + value = bswap32(value); + return krb5_store_int(sp, value, 4); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_uint32(krb5_storage *sp, + uint32_t value) +{ + return krb5_store_int32(sp, (int32_t)value); +} + +static krb5_error_code +krb5_ret_int(krb5_storage *sp, + int32_t *value, + size_t len) +{ + int ret; + unsigned char v[4]; + unsigned long w; + ret = sp->fetch(sp, v, len); + if(ret != len) + return (ret<0)?errno:sp->eof_code; + _krb5_get_int(v, &w, len); + *value = w; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_int32(krb5_storage *sp, + int32_t *value) +{ + krb5_error_code ret = krb5_ret_int(sp, value, 4); + if(ret) + return ret; + if(BYTEORDER_IS_HOST(sp)) + *value = htonl(*value); + else if(BYTEORDER_IS_LE(sp)) + *value = bswap32(*value); + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_uint32(krb5_storage *sp, + uint32_t *value) +{ + krb5_error_code ret; + int32_t v; + + ret = krb5_ret_int32(sp, &v); + if (ret == 0) + *value = (uint32_t)v; + + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_int16(krb5_storage *sp, + int16_t value) +{ + if(BYTEORDER_IS_HOST(sp)) + value = htons(value); + else if(BYTEORDER_IS_LE(sp)) + value = bswap16(value); + return krb5_store_int(sp, value, 2); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_uint16(krb5_storage *sp, + uint16_t value) +{ + return krb5_store_int16(sp, (int16_t)value); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_int16(krb5_storage *sp, + int16_t *value) +{ + int32_t v; + int ret; + ret = krb5_ret_int(sp, &v, 2); + if(ret) + return ret; + *value = v; + if(BYTEORDER_IS_HOST(sp)) + *value = htons(*value); + else if(BYTEORDER_IS_LE(sp)) + *value = bswap16(*value); + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_uint16(krb5_storage *sp, + uint16_t *value) +{ + krb5_error_code ret; + int16_t v; + + ret = krb5_ret_int16(sp, &v); + if (ret == 0) + *value = (uint16_t)v; + + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_int8(krb5_storage *sp, + int8_t value) +{ + int ret; + + ret = sp->store(sp, &value, sizeof(value)); + if (ret != sizeof(value)) + return (ret<0)?errno:sp->eof_code; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_uint8(krb5_storage *sp, + uint8_t value) +{ + return krb5_store_int8(sp, (int8_t)value); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_int8(krb5_storage *sp, + int8_t *value) +{ + int ret; + + ret = sp->fetch(sp, value, sizeof(*value)); + if (ret != sizeof(*value)) + return (ret<0)?errno:sp->eof_code; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_uint8(krb5_storage *sp, + uint8_t *value) +{ + krb5_error_code ret; + int8_t v; + + ret = krb5_ret_int8(sp, &v); + if (ret == 0) + *value = (uint8_t)v; + + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_data(krb5_storage *sp, + krb5_data data) +{ + int ret; + ret = krb5_store_int32(sp, data.length); + if(ret < 0) + return ret; + ret = sp->store(sp, data.data, data.length); + if(ret != data.length){ + if(ret < 0) + return errno; + return sp->eof_code; + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_data(krb5_storage *sp, + krb5_data *data) +{ + int ret; + int32_t size; + + ret = krb5_ret_int32(sp, &size); + if(ret) + return ret; + ret = krb5_data_alloc (data, size); + if (ret) + return ret; + if (size) { + ret = sp->fetch(sp, data->data, size); + if(ret != size) + return (ret < 0)? errno : sp->eof_code; + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_string(krb5_storage *sp, const char *s) +{ + krb5_data data; + data.length = strlen(s); + data.data = rk_UNCONST(s); + return krb5_store_data(sp, data); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_string(krb5_storage *sp, + char **string) +{ + int ret; + krb5_data data; + ret = krb5_ret_data(sp, &data); + if(ret) + return ret; + *string = realloc(data.data, data.length + 1); + if(*string == NULL){ + free(data.data); + return ENOMEM; + } + (*string)[data.length] = 0; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_stringz(krb5_storage *sp, const char *s) +{ + size_t len = strlen(s) + 1; + ssize_t ret; + + ret = sp->store(sp, s, len); + if(ret != len) { + if(ret < 0) + return ret; + else + return sp->eof_code; + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_stringz(krb5_storage *sp, + char **string) +{ + char c; + char *s = NULL; + size_t len = 0; + ssize_t ret; + + while((ret = sp->fetch(sp, &c, 1)) == 1){ + char *tmp; + + len++; + tmp = realloc (s, len); + if (tmp == NULL) { + free (s); + return ENOMEM; + } + s = tmp; + s[len - 1] = c; + if(c == 0) + break; + } + if(ret != 1){ + free(s); + if(ret == 0) + return sp->eof_code; + return ret; + } + *string = s; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_stringnl(krb5_storage *sp, const char *s) +{ + size_t len = strlen(s); + ssize_t ret; + + ret = sp->store(sp, s, len); + if(ret != len) { + if(ret < 0) + return ret; + else + return sp->eof_code; + } + ret = sp->store(sp, "\n", 1); + if(ret != 1) { + if(ret < 0) + return ret; + else + return sp->eof_code; + } + + return 0; + +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_stringnl(krb5_storage *sp, + char **string) +{ + int expect_nl = 0; + char c; + char *s = NULL; + size_t len = 0; + ssize_t ret; + + while((ret = sp->fetch(sp, &c, 1)) == 1){ + char *tmp; + + if (c == '\r') { + expect_nl = 1; + continue; + } + if (expect_nl && c != '\n') { + free(s); + return KRB5_BADMSGTYPE; + } + + len++; + tmp = realloc (s, len); + if (tmp == NULL) { + free (s); + return ENOMEM; + } + s = tmp; + if(c == '\n') { + s[len - 1] = '\0'; + break; + } + s[len - 1] = c; + } + if(ret != 1){ + free(s); + if(ret == 0) + return sp->eof_code; + return ret; + } + *string = s; + return 0; +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_principal(krb5_storage *sp, + krb5_const_principal p) +{ + int i; + int ret; + + if(!krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) { + ret = krb5_store_int32(sp, p->name.name_type); + if(ret) return ret; + } + if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS)) + ret = krb5_store_int32(sp, p->name.name_string.len + 1); + else + ret = krb5_store_int32(sp, p->name.name_string.len); + + if(ret) return ret; + ret = krb5_store_string(sp, p->realm); + if(ret) return ret; + for(i = 0; i < p->name.name_string.len; i++){ + ret = krb5_store_string(sp, p->name.name_string.val[i]); + if(ret) return ret; + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_principal(krb5_storage *sp, + krb5_principal *princ) +{ + int i; + int ret; + krb5_principal p; + int32_t type; + int32_t ncomp; + + p = calloc(1, sizeof(*p)); + if(p == NULL) + return ENOMEM; + + if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) + type = KRB5_NT_UNKNOWN; + else if((ret = krb5_ret_int32(sp, &type))){ + free(p); + return ret; + } + if((ret = krb5_ret_int32(sp, &ncomp))){ + free(p); + return ret; + } + if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS)) + ncomp--; + if (ncomp < 0) { + free(p); + return EINVAL; + } + p->name.name_type = type; + p->name.name_string.len = ncomp; + ret = krb5_ret_string(sp, &p->realm); + if(ret) { + free(p); + return ret; + } + p->name.name_string.val = calloc(ncomp, sizeof(*p->name.name_string.val)); + if(p->name.name_string.val == NULL && ncomp != 0){ + free(p->realm); + free(p); + return ENOMEM; + } + for(i = 0; i < ncomp; i++){ + ret = krb5_ret_string(sp, &p->name.name_string.val[i]); + if(ret) { + while (i >= 0) + free(p->name.name_string.val[i--]); + free(p->realm); + free(p); + return ret; + } + } + *princ = p; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_keyblock(krb5_storage *sp, krb5_keyblock p) +{ + int ret; + ret = krb5_store_int16(sp, p.keytype); + if(ret) return ret; + + if(krb5_storage_is_flags(sp, KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE)){ + /* this should really be enctype, but it is the same as + keytype nowadays */ + ret = krb5_store_int16(sp, p.keytype); + if(ret) return ret; + } + + ret = krb5_store_data(sp, p.keyvalue); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_keyblock(krb5_storage *sp, krb5_keyblock *p) +{ + int ret; + int16_t tmp; + + ret = krb5_ret_int16(sp, &tmp); + if(ret) return ret; + p->keytype = tmp; + + if(krb5_storage_is_flags(sp, KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE)){ + ret = krb5_ret_int16(sp, &tmp); + if(ret) return ret; + } + + ret = krb5_ret_data(sp, &p->keyvalue); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_times(krb5_storage *sp, krb5_times times) +{ + int ret; + ret = krb5_store_int32(sp, times.authtime); + if(ret) return ret; + ret = krb5_store_int32(sp, times.starttime); + if(ret) return ret; + ret = krb5_store_int32(sp, times.endtime); + if(ret) return ret; + ret = krb5_store_int32(sp, times.renew_till); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_times(krb5_storage *sp, krb5_times *times) +{ + int ret; + int32_t tmp; + ret = krb5_ret_int32(sp, &tmp); + times->authtime = tmp; + if(ret) return ret; + ret = krb5_ret_int32(sp, &tmp); + times->starttime = tmp; + if(ret) return ret; + ret = krb5_ret_int32(sp, &tmp); + times->endtime = tmp; + if(ret) return ret; + ret = krb5_ret_int32(sp, &tmp); + times->renew_till = tmp; + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_address(krb5_storage *sp, krb5_address p) +{ + int ret; + ret = krb5_store_int16(sp, p.addr_type); + if(ret) return ret; + ret = krb5_store_data(sp, p.address); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_address(krb5_storage *sp, krb5_address *adr) +{ + int16_t t; + int ret; + ret = krb5_ret_int16(sp, &t); + if(ret) return ret; + adr->addr_type = t; + ret = krb5_ret_data(sp, &adr->address); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_addrs(krb5_storage *sp, krb5_addresses p) +{ + int i; + int ret; + ret = krb5_store_int32(sp, p.len); + if(ret) return ret; + for(i = 0; i<p.len; i++){ + ret = krb5_store_address(sp, p.val[i]); + if(ret) break; + } + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_addrs(krb5_storage *sp, krb5_addresses *adr) +{ + int i; + int ret; + int32_t tmp; + + ret = krb5_ret_int32(sp, &tmp); + if(ret) return ret; + adr->len = tmp; + ALLOC(adr->val, adr->len); + if (adr->val == NULL && adr->len != 0) + return ENOMEM; + for(i = 0; i < adr->len; i++){ + ret = krb5_ret_address(sp, &adr->val[i]); + if(ret) break; + } + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_authdata(krb5_storage *sp, krb5_authdata auth) +{ + krb5_error_code ret; + int i; + ret = krb5_store_int32(sp, auth.len); + if(ret) return ret; + for(i = 0; i < auth.len; i++){ + ret = krb5_store_int16(sp, auth.val[i].ad_type); + if(ret) break; + ret = krb5_store_data(sp, auth.val[i].ad_data); + if(ret) break; + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_authdata(krb5_storage *sp, krb5_authdata *auth) +{ + krb5_error_code ret; + int32_t tmp; + int16_t tmp2; + int i; + ret = krb5_ret_int32(sp, &tmp); + if(ret) return ret; + ALLOC_SEQ(auth, tmp); + if (auth->val == NULL && tmp != 0) + return ENOMEM; + for(i = 0; i < tmp; i++){ + ret = krb5_ret_int16(sp, &tmp2); + if(ret) break; + auth->val[i].ad_type = tmp2; + ret = krb5_ret_data(sp, &auth->val[i].ad_data); + if(ret) break; + } + return ret; +} + +static int32_t +bitswap32(int32_t b) +{ + int32_t r = 0; + int i; + for (i = 0; i < 32; i++) { + r = r << 1 | (b & 1); + b = b >> 1; + } + return r; +} + + +/* + * + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_creds(krb5_storage *sp, krb5_creds *creds) +{ + int ret; + + ret = krb5_store_principal(sp, creds->client); + if(ret) + return ret; + ret = krb5_store_principal(sp, creds->server); + if(ret) + return ret; + ret = krb5_store_keyblock(sp, creds->session); + if(ret) + return ret; + ret = krb5_store_times(sp, creds->times); + if(ret) + return ret; + ret = krb5_store_int8(sp, creds->second_ticket.length != 0); /* is_skey */ + if(ret) + return ret; + + if(krb5_storage_is_flags(sp, KRB5_STORAGE_CREDS_FLAGS_WRONG_BITORDER)) + ret = krb5_store_int32(sp, creds->flags.i); + else + ret = krb5_store_int32(sp, bitswap32(TicketFlags2int(creds->flags.b))); + if(ret) + return ret; + + ret = krb5_store_addrs(sp, creds->addresses); + if(ret) + return ret; + ret = krb5_store_authdata(sp, creds->authdata); + if(ret) + return ret; + ret = krb5_store_data(sp, creds->ticket); + if(ret) + return ret; + ret = krb5_store_data(sp, creds->second_ticket); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_creds(krb5_storage *sp, krb5_creds *creds) +{ + krb5_error_code ret; + int8_t dummy8; + int32_t dummy32; + + memset(creds, 0, sizeof(*creds)); + ret = krb5_ret_principal (sp, &creds->client); + if(ret) goto cleanup; + ret = krb5_ret_principal (sp, &creds->server); + if(ret) goto cleanup; + ret = krb5_ret_keyblock (sp, &creds->session); + if(ret) goto cleanup; + ret = krb5_ret_times (sp, &creds->times); + if(ret) goto cleanup; + ret = krb5_ret_int8 (sp, &dummy8); + if(ret) goto cleanup; + ret = krb5_ret_int32 (sp, &dummy32); + if(ret) goto cleanup; + /* + * Runtime detect the what is the higher bits of the bitfield. If + * any of the higher bits are set in the input data, it's either a + * new ticket flag (and this code need to be removed), or it's a + * MIT cache (or new Heimdal cache), lets change it to our current + * format. + */ + { + uint32_t mask = 0xffff0000; + creds->flags.i = 0; + creds->flags.b.anonymous = 1; + if (creds->flags.i & mask) + mask = ~mask; + if (dummy32 & mask) + dummy32 = bitswap32(dummy32); + } + creds->flags.i = dummy32; + ret = krb5_ret_addrs (sp, &creds->addresses); + if(ret) goto cleanup; + ret = krb5_ret_authdata (sp, &creds->authdata); + if(ret) goto cleanup; + ret = krb5_ret_data (sp, &creds->ticket); + if(ret) goto cleanup; + ret = krb5_ret_data (sp, &creds->second_ticket); +cleanup: + if(ret) { +#if 0 + krb5_free_cred_contents(context, creds); /* XXX */ +#endif + } + return ret; +} + +#define SC_CLIENT_PRINCIPAL 0x0001 +#define SC_SERVER_PRINCIPAL 0x0002 +#define SC_SESSION_KEY 0x0004 +#define SC_TICKET 0x0008 +#define SC_SECOND_TICKET 0x0010 +#define SC_AUTHDATA 0x0020 +#define SC_ADDRESSES 0x0040 + +/* + * + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_creds_tag(krb5_storage *sp, krb5_creds *creds) +{ + int ret; + int32_t header = 0; + + if (creds->client) + header |= SC_CLIENT_PRINCIPAL; + if (creds->server) + header |= SC_SERVER_PRINCIPAL; + if (creds->session.keytype != ETYPE_NULL) + header |= SC_SESSION_KEY; + if (creds->ticket.data) + header |= SC_TICKET; + if (creds->second_ticket.length) + header |= SC_SECOND_TICKET; + if (creds->authdata.len) + header |= SC_AUTHDATA; + if (creds->addresses.len) + header |= SC_ADDRESSES; + + ret = krb5_store_int32(sp, header); + + if (creds->client) { + ret = krb5_store_principal(sp, creds->client); + if(ret) + return ret; + } + + if (creds->server) { + ret = krb5_store_principal(sp, creds->server); + if(ret) + return ret; + } + + if (creds->session.keytype != ETYPE_NULL) { + ret = krb5_store_keyblock(sp, creds->session); + if(ret) + return ret; + } + + ret = krb5_store_times(sp, creds->times); + if(ret) + return ret; + ret = krb5_store_int8(sp, creds->second_ticket.length != 0); /* is_skey */ + if(ret) + return ret; + + ret = krb5_store_int32(sp, bitswap32(TicketFlags2int(creds->flags.b))); + if(ret) + return ret; + + if (creds->addresses.len) { + ret = krb5_store_addrs(sp, creds->addresses); + if(ret) + return ret; + } + + if (creds->authdata.len) { + ret = krb5_store_authdata(sp, creds->authdata); + if(ret) + return ret; + } + + if (creds->ticket.data) { + ret = krb5_store_data(sp, creds->ticket); + if(ret) + return ret; + } + + if (creds->second_ticket.data) { + ret = krb5_store_data(sp, creds->second_ticket); + if (ret) + return ret; + } + + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_creds_tag(krb5_storage *sp, + krb5_creds *creds) +{ + krb5_error_code ret; + int8_t dummy8; + int32_t dummy32, header; + + memset(creds, 0, sizeof(*creds)); + + ret = krb5_ret_int32 (sp, &header); + if (ret) goto cleanup; + + if (header & SC_CLIENT_PRINCIPAL) { + ret = krb5_ret_principal (sp, &creds->client); + if(ret) goto cleanup; + } + if (header & SC_SERVER_PRINCIPAL) { + ret = krb5_ret_principal (sp, &creds->server); + if(ret) goto cleanup; + } + if (header & SC_SESSION_KEY) { + ret = krb5_ret_keyblock (sp, &creds->session); + if(ret) goto cleanup; + } + ret = krb5_ret_times (sp, &creds->times); + if(ret) goto cleanup; + ret = krb5_ret_int8 (sp, &dummy8); + if(ret) goto cleanup; + ret = krb5_ret_int32 (sp, &dummy32); + if(ret) goto cleanup; + /* + * Runtime detect the what is the higher bits of the bitfield. If + * any of the higher bits are set in the input data, it's either a + * new ticket flag (and this code need to be removed), or it's a + * MIT cache (or new Heimdal cache), lets change it to our current + * format. + */ + { + uint32_t mask = 0xffff0000; + creds->flags.i = 0; + creds->flags.b.anonymous = 1; + if (creds->flags.i & mask) + mask = ~mask; + if (dummy32 & mask) + dummy32 = bitswap32(dummy32); + } + creds->flags.i = dummy32; + if (header & SC_ADDRESSES) { + ret = krb5_ret_addrs (sp, &creds->addresses); + if(ret) goto cleanup; + } + if (header & SC_AUTHDATA) { + ret = krb5_ret_authdata (sp, &creds->authdata); + if(ret) goto cleanup; + } + if (header & SC_TICKET) { + ret = krb5_ret_data (sp, &creds->ticket); + if(ret) goto cleanup; + } + if (header & SC_SECOND_TICKET) { + ret = krb5_ret_data (sp, &creds->second_ticket); + if(ret) goto cleanup; + } + +cleanup: + if(ret) { +#if 0 + krb5_free_cred_contents(context, creds); /* XXX */ +#endif + } + return ret; +} diff --git a/lib/krb5/store_emem.c b/lib/krb5/store_emem.c new file mode 100644 index 0000000..b59a647 --- /dev/null +++ b/lib/krb5/store_emem.c @@ -0,0 +1,143 @@ +/* + * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" +#include "store-int.h" + +RCSID("$Id: store_emem.c 21745 2007-07-31 16:11:25Z lha $"); + +typedef struct emem_storage{ + unsigned char *base; + size_t size; + size_t len; + unsigned char *ptr; +}emem_storage; + +static ssize_t +emem_fetch(krb5_storage *sp, void *data, size_t size) +{ + emem_storage *s = (emem_storage*)sp->data; + if(s->base + s->len - s->ptr < size) + size = s->base + s->len - s->ptr; + memmove(data, s->ptr, size); + sp->seek(sp, size, SEEK_CUR); + return size; +} + +static ssize_t +emem_store(krb5_storage *sp, const void *data, size_t size) +{ + emem_storage *s = (emem_storage*)sp->data; + if(size > s->base + s->size - s->ptr){ + void *base; + size_t sz, off; + off = s->ptr - s->base; + sz = off + size; + if (sz < 4096) + sz *= 2; + base = realloc(s->base, sz); + if(base == NULL) + return 0; + s->size = sz; + s->base = base; + s->ptr = (unsigned char*)base + off; + } + memmove(s->ptr, data, size); + sp->seek(sp, size, SEEK_CUR); + return size; +} + +static off_t +emem_seek(krb5_storage *sp, off_t offset, int whence) +{ + emem_storage *s = (emem_storage*)sp->data; + switch(whence){ + case SEEK_SET: + if(offset > s->size) + offset = s->size; + if(offset < 0) + offset = 0; + s->ptr = s->base + offset; + if(offset > s->len) + s->len = offset; + break; + case SEEK_CUR: + sp->seek(sp,s->ptr - s->base + offset, SEEK_SET); + break; + case SEEK_END: + sp->seek(sp, s->len + offset, SEEK_SET); + break; + default: + errno = EINVAL; + return -1; + } + return s->ptr - s->base; +} + +static void +emem_free(krb5_storage *sp) +{ + emem_storage *s = sp->data; + memset(s->base, 0, s->len); + free(s->base); +} + +krb5_storage * KRB5_LIB_FUNCTION +krb5_storage_emem(void) +{ + krb5_storage *sp = malloc(sizeof(krb5_storage)); + if (sp == NULL) + return NULL; + emem_storage *s = malloc(sizeof(*s)); + if (s == NULL) { + free(sp); + return NULL; + } + sp->data = s; + sp->flags = 0; + sp->eof_code = HEIM_ERR_EOF; + s->size = 1024; + s->base = malloc(s->size); + if (s->base == NULL) { + free(sp); + free(s); + return NULL; + } + s->len = 0; + s->ptr = s->base; + sp->fetch = emem_fetch; + sp->store = emem_store; + sp->seek = emem_seek; + sp->free = emem_free; + return sp; +} diff --git a/lib/krb5/store_fd.c b/lib/krb5/store_fd.c new file mode 100644 index 0000000..15f86fc --- /dev/null +++ b/lib/krb5/store_fd.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" +#include "store-int.h" + +RCSID("$Id: store_fd.c 17779 2006-06-30 21:23:19Z lha $"); + +typedef struct fd_storage { + int fd; +} fd_storage; + +#define FD(S) (((fd_storage*)(S)->data)->fd) + +static ssize_t +fd_fetch(krb5_storage * sp, void *data, size_t size) +{ + return net_read(FD(sp), data, size); +} + +static ssize_t +fd_store(krb5_storage * sp, const void *data, size_t size) +{ + return net_write(FD(sp), data, size); +} + +static off_t +fd_seek(krb5_storage * sp, off_t offset, int whence) +{ + return lseek(FD(sp), offset, whence); +} + +static void +fd_free(krb5_storage * sp) +{ + close(FD(sp)); +} + +krb5_storage * KRB5_LIB_FUNCTION +krb5_storage_from_fd(int fd) +{ + krb5_storage *sp; + + fd = dup(fd); + if (fd < 0) + return NULL; + + sp = malloc(sizeof(krb5_storage)); + if (sp == NULL) { + close(fd); + return NULL; + } + + sp->data = malloc(sizeof(fd_storage)); + if (sp->data == NULL) { + close(fd); + free(sp); + return NULL; + } + sp->flags = 0; + sp->eof_code = HEIM_ERR_EOF; + FD(sp) = fd; + sp->fetch = fd_fetch; + sp->store = fd_store; + sp->seek = fd_seek; + sp->free = fd_free; + return sp; +} diff --git a/lib/krb5/store_mem.c b/lib/krb5/store_mem.c new file mode 100644 index 0000000..e6e62b5 --- /dev/null +++ b/lib/krb5/store_mem.c @@ -0,0 +1,150 @@ +/* + * Copyright (c) 1997 - 2000, 2002 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" +#include "store-int.h" + +RCSID("$Id: store_mem.c 20307 2007-04-11 11:16:28Z lha $"); + +typedef struct mem_storage{ + unsigned char *base; + size_t size; + unsigned char *ptr; +}mem_storage; + +static ssize_t +mem_fetch(krb5_storage *sp, void *data, size_t size) +{ + mem_storage *s = (mem_storage*)sp->data; + if(size > s->base + s->size - s->ptr) + size = s->base + s->size - s->ptr; + memmove(data, s->ptr, size); + sp->seek(sp, size, SEEK_CUR); + return size; +} + +static ssize_t +mem_store(krb5_storage *sp, const void *data, size_t size) +{ + mem_storage *s = (mem_storage*)sp->data; + if(size > s->base + s->size - s->ptr) + size = s->base + s->size - s->ptr; + memmove(s->ptr, data, size); + sp->seek(sp, size, SEEK_CUR); + return size; +} + +static ssize_t +mem_no_store(krb5_storage *sp, const void *data, size_t size) +{ + return -1; +} + +static off_t +mem_seek(krb5_storage *sp, off_t offset, int whence) +{ + mem_storage *s = (mem_storage*)sp->data; + switch(whence){ + case SEEK_SET: + if(offset > s->size) + offset = s->size; + if(offset < 0) + offset = 0; + s->ptr = s->base + offset; + break; + case SEEK_CUR: + return sp->seek(sp, s->ptr - s->base + offset, SEEK_SET); + case SEEK_END: + return sp->seek(sp, s->size + offset, SEEK_SET); + default: + errno = EINVAL; + return -1; + } + return s->ptr - s->base; +} + +krb5_storage * KRB5_LIB_FUNCTION +krb5_storage_from_mem(void *buf, size_t len) +{ + krb5_storage *sp = malloc(sizeof(krb5_storage)); + mem_storage *s; + if(sp == NULL) + return NULL; + s = malloc(sizeof(*s)); + if(s == NULL) { + free(sp); + return NULL; + } + sp->data = s; + sp->flags = 0; + sp->eof_code = HEIM_ERR_EOF; + s->base = buf; + s->size = len; + s->ptr = buf; + sp->fetch = mem_fetch; + sp->store = mem_store; + sp->seek = mem_seek; + sp->free = NULL; + return sp; +} + +krb5_storage * KRB5_LIB_FUNCTION +krb5_storage_from_data(krb5_data *data) +{ + return krb5_storage_from_mem(data->data, data->length); +} + +krb5_storage * KRB5_LIB_FUNCTION +krb5_storage_from_readonly_mem(const void *buf, size_t len) +{ + krb5_storage *sp = malloc(sizeof(krb5_storage)); + mem_storage *s; + if(sp == NULL) + return NULL; + s = malloc(sizeof(*s)); + if(s == NULL) { + free(sp); + return NULL; + } + sp->data = s; + sp->flags = 0; + sp->eof_code = HEIM_ERR_EOF; + s->base = rk_UNCONST(buf); + s->size = len; + s->ptr = rk_UNCONST(buf); + sp->fetch = mem_fetch; + sp->store = mem_no_store; + sp->seek = mem_seek; + sp->free = NULL; + return sp; +} diff --git a/lib/krb5/string-to-key-test.c b/lib/krb5/string-to-key-test.c new file mode 100644 index 0000000..30075ea --- /dev/null +++ b/lib/krb5/string-to-key-test.c @@ -0,0 +1,140 @@ +/* + * Copyright (c) 1999 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include "krb5_locl.h" +#include <err.h> + +RCSID("$Id: string-to-key-test.c 16344 2005-12-02 15:15:43Z lha $"); + +enum { MAXSIZE = 24 }; + +static struct testcase { + const char *principal_name; + const char *password; + krb5_enctype enctype; + unsigned char res[MAXSIZE]; +} tests[] = { + {"@", "", ETYPE_DES_CBC_MD5, + {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xf1}}, + {"nisse@FOO.SE", "hej", ETYPE_DES_CBC_MD5, + {0xfe, 0x67, 0xbf, 0x9e, 0x57, 0x6b, 0xfe, 0x52}}, + {"assar/liten@FOO.SE", "hemligt", ETYPE_DES_CBC_MD5, + {0x5b, 0x9b, 0xcb, 0xf2, 0x97, 0x43, 0xc8, 0x40}}, +#if 0 + {"@", "", ETYPE_DES3_CBC_SHA1, + {0xce, 0xa2, 0x2f, 0x9b, 0x52, 0x2c, 0xb0, 0x15, 0x6e, 0x6b, 0x64, + 0x73, 0x62, 0x64, 0x73, 0x4f, 0x6e, 0x73, 0xce, 0xa2, 0x2f, 0x9b, + 0x52, 0x57}}, +#endif + {"nisse@FOO.SE", "hej", ETYPE_DES3_CBC_SHA1, + {0x0e, 0xbc, 0x23, 0x9d, 0x68, 0x46, 0xf2, 0xd5, 0x51, 0x98, 0x5b, + 0x57, 0xc1, 0x57, 0x01, 0x79, 0x04, 0xc4, 0xe9, 0xfe, 0xc1, 0x0e, + 0x13, 0xd0}}, + {"assar/liten@FOO.SE", "hemligt", ETYPE_DES3_CBC_SHA1, + {0x7f, 0x40, 0x67, 0xb9, 0xbc, 0xc4, 0x40, 0xfb, 0x43, 0x73, 0xd9, + 0xd3, 0xcd, 0x7c, 0xc7, 0x67, 0xe6, 0x79, 0x94, 0xd0, 0xa8, 0x34, + 0xdf, 0x62}}, + {"does/not@MATTER", "foo", ETYPE_ARCFOUR_HMAC_MD5, + {0xac, 0x8e, 0x65, 0x7f, 0x83, 0xdf, 0x82, 0xbe, + 0xea, 0x5d, 0x43, 0xbd, 0xaf, 0x78, 0x00, 0xcc}}, + {"raeburn@ATHENA.MIT.EDU", "password", ETYPE_DES_CBC_MD5, + {0xcb, 0xc2, 0x2f, 0xae, 0x23, 0x52, 0x98, 0xe3}}, + {"danny@WHITEHOUSE.GOV", "potatoe", ETYPE_DES_CBC_MD5, + {0xdf, 0x3d, 0x32, 0xa7, 0x4f, 0xd9, 0x2a, 0x01}}, + {"buckaroo@EXAMPLE.COM", "penny", ETYPE_DES_CBC_MD5, + {0x94, 0x43, 0xa2, 0xe5, 0x32, 0xfd, 0xc4, 0xf1}}, + {"Juri\xc5\xa1i\xc4\x87@ATHENA.MIT.EDU", "\xc3\x9f", ETYPE_DES_CBC_MD5, + {0x62, 0xc8, 0x1a, 0x52, 0x32, 0xb5, 0xe6, 0x9d}}, + {"AAAAAAAA", "11119999", ETYPE_DES_CBC_MD5, + {0x98, 0x40, 0x54, 0xd0, 0xf1, 0xa7, 0x3e, 0x31}}, + {"FFFFAAAA", "NNNN6666", ETYPE_DES_CBC_MD5, + {0xc4, 0xbf, 0x6b, 0x25, 0xad, 0xf7, 0xa4, 0xf8}}, + {"raeburn@ATHENA.MIT.EDU", "password", ETYPE_DES3_CBC_SHA1, + {0x85, 0x0b, 0xb5, 0x13, 0x58, 0x54, 0x8c, 0xd0, 0x5e, 0x86, 0x76, 0x8c, 0x31, 0x3e, 0x3b, 0xfe, 0xf7, 0x51, 0x19, 0x37, 0xdc, 0xf7, 0x2c, 0x3e}}, + {"danny@WHITEHOUSE.GOV", "potatoe", ETYPE_DES3_CBC_SHA1, + {0xdf, 0xcd, 0x23, 0x3d, 0xd0, 0xa4, 0x32, 0x04, 0xea, 0x6d, 0xc4, 0x37, 0xfb, 0x15, 0xe0, 0x61, 0xb0, 0x29, 0x79, 0xc1, 0xf7, 0x4f, 0x37, 0x7a}}, + {"buckaroo@EXAMPLE.COM", "penny", ETYPE_DES3_CBC_SHA1, + {0x6d, 0x2f, 0xcd, 0xf2, 0xd6, 0xfb, 0xbc, 0x3d, 0xdc, 0xad, 0xb5, 0xda, 0x57, 0x10, 0xa2, 0x34, 0x89, 0xb0, 0xd3, 0xb6, 0x9d, 0x5d, 0x9d, 0x4a}}, + {"Juri\xc5\xa1i\xc4\x87@ATHENA.MIT.EDU", "\xc3\x9f", ETYPE_DES3_CBC_SHA1, + {0x16, 0xd5, 0xa4, 0x0e, 0x1c, 0xe3, 0xba, 0xcb, 0x61, 0xb9, 0xdc, 0xe0, 0x04, 0x70, 0x32, 0x4c, 0x83, 0x19, 0x73, 0xa7, 0xb9, 0x52, 0xfe, 0xb0}}, + {NULL} +}; + +int +main(int argc, char **argv) +{ + struct testcase *t; + krb5_context context; + krb5_error_code ret; + int val = 0; + + ret = krb5_init_context (&context); + if (ret) + errx (1, "krb5_init_context failed: %d", ret); + + /* to enable realm-less principal name above */ + + krb5_set_default_realm(context, ""); + + for (t = tests; t->principal_name; ++t) { + krb5_keyblock key; + krb5_principal principal; + int i; + + ret = krb5_parse_name (context, t->principal_name, &principal); + if (ret) + krb5_err (context, 1, ret, "krb5_parse_name %s", + t->principal_name); + ret = krb5_string_to_key (context, t->enctype, t->password, + principal, &key); + if (ret) + krb5_err (context, 1, ret, "krb5_string_to_key"); + krb5_free_principal (context, principal); + if (memcmp (key.keyvalue.data, t->res, key.keyvalue.length) != 0) { + const unsigned char *p = key.keyvalue.data; + + printf ("string_to_key(%s, %s) failed\n", + t->principal_name, t->password); + printf ("should be: "); + for (i = 0; i < key.keyvalue.length; ++i) + printf ("%02x", t->res[i]); + printf ("\nresult was: "); + for (i = 0; i < key.keyvalue.length; ++i) + printf ("%02x", p[i]); + printf ("\n"); + val = 1; + } + krb5_free_keyblock_contents(context, &key); + } + krb5_free_context(context); + return val; +} diff --git a/lib/krb5/test_acl.c b/lib/krb5/test_acl.c new file mode 100644 index 0000000..e52f31a --- /dev/null +++ b/lib/krb5/test_acl.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include "krb5_locl.h" +#include <err.h> + +RCSID("$Id: test_acl.c 15036 2005-04-30 15:19:58Z lha $"); + +#define RETVAL(c, r, e, s) \ + do { if (r != e) krb5_errx(c, 1, "%s", s); } while (0) +#define STRINGMATCH(c, s, _s1, _s2) \ + do { \ + if (_s1 == NULL || _s2 == NULL) \ + krb5_errx(c, 1, "s1 or s2 is NULL"); \ + if (strcmp(_s1,_s2) != 0) \ + krb5_errx(c, 1, "%s", s); \ + } while (0) + +static void +test_match_string(krb5_context context) +{ + krb5_error_code ret; + char *s1, *s2; + + ret = krb5_acl_match_string(context, "foo", "s", "foo"); + RETVAL(context, ret, 0, "single s"); + ret = krb5_acl_match_string(context, "foo foo", "s", "foo"); + RETVAL(context, ret, EACCES, "too many strings"); + ret = krb5_acl_match_string(context, "foo bar", "ss", "foo", "bar"); + RETVAL(context, ret, 0, "two strings"); + ret = krb5_acl_match_string(context, "foo bar", "ss", "foo", "bar"); + RETVAL(context, ret, 0, "two strings double space"); + ret = krb5_acl_match_string(context, "foo \tbar", "ss", "foo", "bar"); + RETVAL(context, ret, 0, "two strings space + tab"); + ret = krb5_acl_match_string(context, "foo", "ss", "foo", "bar"); + RETVAL(context, ret, EACCES, "one string, two format strings"); + ret = krb5_acl_match_string(context, "foo", "ss", "foo", "foo"); + RETVAL(context, ret, EACCES, "one string, two format strings (same)"); + ret = krb5_acl_match_string(context, "foo \t", "s", "foo"); + RETVAL(context, ret, 0, "ending space"); + + ret = krb5_acl_match_string(context, "foo/bar", "f", "foo/bar"); + RETVAL(context, ret, 0, "liternal fnmatch"); + ret = krb5_acl_match_string(context, "foo/bar", "f", "foo/*"); + RETVAL(context, ret, 0, "foo/*"); + ret = krb5_acl_match_string(context, "foo/bar/baz", "f", "foo/*/baz"); + RETVAL(context, ret, 0, "foo/*/baz"); + + ret = krb5_acl_match_string(context, "foo", "r", &s1); + RETVAL(context, ret, 0, "ret 1"); + STRINGMATCH(context, "ret 1 match", s1, "foo"); free(s1); + + ret = krb5_acl_match_string(context, "foo bar", "rr", &s1, &s2); + RETVAL(context, ret, 0, "ret 2"); + STRINGMATCH(context, "ret 2 match 1", s1, "foo"); free(s1); + STRINGMATCH(context, "ret 2 match 2", s2, "bar"); free(s2); + + ret = krb5_acl_match_string(context, "foo bar", "sr", "bar", &s1); + RETVAL(context, ret, EACCES, "ret mismatch"); + if (s1 != NULL) krb5_errx(context, 1, "s1 not NULL"); + + ret = krb5_acl_match_string(context, "foo", "l", "foo"); + RETVAL(context, ret, EINVAL, "unknown letter"); +} + + +int +main(int argc, char **argv) +{ + krb5_context context; + krb5_error_code ret; + + setprogname(argv[0]); + + ret = krb5_init_context(&context); + if (ret) + errx (1, "krb5_init_context failed: %d", ret); + + test_match_string(context); + + krb5_free_context(context); + + return 0; +} diff --git a/lib/krb5/test_addr.c b/lib/krb5/test_addr.c new file mode 100644 index 0000000..1ab47ae --- /dev/null +++ b/lib/krb5/test_addr.c @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include "krb5_locl.h" +#include <err.h> + +RCSID("$Id: test_addr.c 15036 2005-04-30 15:19:58Z lha $"); + +static void +print_addr(krb5_context context, const char *addr) +{ + krb5_addresses addresses; + krb5_error_code ret; + char buf[38]; + char buf2[1000]; + size_t len; + int i; + + ret = krb5_parse_address(context, addr, &addresses); + if (ret) + krb5_err(context, 1, ret, "krb5_parse_address"); + + if (addresses.len < 1) + krb5_err(context, 1, ret, "too few addresses"); + + for (i = 0; i < addresses.len; i++) { + krb5_print_address(&addresses.val[i], buf, sizeof(buf), &len); +#if 0 + printf("addr %d: %s (%d/%d)\n", i, buf, (int)len, (int)strlen(buf)); +#endif + if (strlen(buf) > sizeof(buf)) + abort(); + krb5_print_address(&addresses.val[i], buf2, sizeof(buf2), &len); +#if 0 + printf("addr %d: %s (%d/%d)\n", i, buf2, (int)len, (int)strlen(buf2)); +#endif + if (strlen(buf2) > sizeof(buf2)) + abort(); + + } + krb5_free_addresses(context, &addresses); + +} + +static void +truncated_addr(krb5_context context, const char *addr, + size_t truncate_len, size_t outlen) +{ + krb5_addresses addresses; + krb5_error_code ret; + char *buf; + size_t len; + + buf = ecalloc(1, outlen + 1); + + ret = krb5_parse_address(context, addr, &addresses); + if (ret) + krb5_err(context, 1, ret, "krb5_parse_address"); + + if (addresses.len != 1) + krb5_err(context, 1, ret, "addresses should be one"); + + krb5_print_address(&addresses.val[0], buf, truncate_len, &len); + +#if 0 + printf("addr %s (%d/%d)\n", buf, (int)len, (int)strlen(buf)); +#endif + + if (truncate_len > strlen(buf) + 1) + abort(); + if (outlen != len) + abort(); + + krb5_print_address(&addresses.val[0], buf, outlen + 1, &len); + +#if 0 + printf("addr %s (%d/%d)\n", buf, (int)len, (int)strlen(buf)); +#endif + + if (len != outlen) + abort(); + if (strlen(buf) != len) + abort(); + + krb5_free_addresses(context, &addresses); + free(buf); +} + +static void +check_truncation(krb5_context context, const char *addr) +{ + int i, len = strlen(addr); + + for (i = 0; i < len; i++) + truncated_addr(context, addr, i, len); +} + +static void +match_addr(krb5_context context, const char *range_addr, + const char *one_addr, int match) +{ + krb5_addresses range, one; + krb5_error_code ret; + + ret = krb5_parse_address(context, range_addr, &range); + if (ret) + krb5_err(context, 1, ret, "krb5_parse_address"); + + if (range.len != 1) + krb5_err(context, 1, ret, "wrong num of addresses"); + + ret = krb5_parse_address(context, one_addr, &one); + if (ret) + krb5_err(context, 1, ret, "krb5_parse_address"); + + if (one.len != 1) + krb5_err(context, 1, ret, "wrong num of addresses"); + + if (krb5_address_order(context, &range.val[0], &one.val[0]) == 0) { + if (!match) + krb5_errx(context, 1, "match when one shouldn't be"); + } else { + if (match) + krb5_errx(context, 1, "no match when one should be"); + } + + krb5_free_addresses(context, &range); + krb5_free_addresses(context, &one); +} + +int +main(int argc, char **argv) +{ + krb5_context context; + krb5_error_code ret; + + setprogname(argv[0]); + + ret = krb5_init_context(&context); + if (ret) + errx (1, "krb5_init_context failed: %d", ret); + + print_addr(context, "RANGE:127.0.0.0/8"); + print_addr(context, "RANGE:127.0.0.0/24"); + print_addr(context, "RANGE:IPv4:127.0.0.0-IPv4:127.0.0.255"); + print_addr(context, "RANGE:130.237.237.4/29"); +#ifdef HAVE_IPV6 + print_addr(context, "RANGE:fe80::209:6bff:fea0:e522/64"); + print_addr(context, "RANGE:IPv6:fe80::209:6bff:fea0:e522/64"); + print_addr(context, "RANGE:IPv6:fe80::-IPv6:fe80::ffff:ffff:ffff:ffff"); + print_addr(context, "RANGE:fe80::-fe80::ffff:ffff:ffff:ffff"); +#endif + + check_truncation(context, "IPv4:127.0.0.0"); + check_truncation(context, "RANGE:IPv4:127.0.0.0-IPv4:127.0.0.255"); +#ifdef HAVE_IPV6 + check_truncation(context, "IPv6:::1"); + check_truncation(context, "IPv6:fe80::ffff:ffff:ffff:ffff"); +#endif + + match_addr(context, "RANGE:127.0.0.0/8", "inet:127.0.0.0", 1); + match_addr(context, "RANGE:127.0.0.0/8", "inet:127.255.255.255", 1); + match_addr(context, "RANGE:127.0.0.0/8", "inet:128.0.0.0", 0); + + match_addr(context, "RANGE:130.237.237.8/29", "inet:130.237.237.7", 0); + match_addr(context, "RANGE:130.237.237.8/29", "inet:130.237.237.8", 1); + match_addr(context, "RANGE:130.237.237.8/29", "inet:130.237.237.15", 1); + match_addr(context, "RANGE:130.237.237.8/29", "inet:130.237.237.16", 0); + + krb5_free_context(context); + + return 0; +} diff --git a/lib/krb5/test_alname.c b/lib/krb5/test_alname.c new file mode 100644 index 0000000..e8397b7 --- /dev/null +++ b/lib/krb5/test_alname.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include "krb5_locl.h" +#include <getarg.h> +#include <err.h> + +RCSID("$Id: test_alname.c 15474 2005-06-17 04:48:02Z lha $"); + +static void +test_alname(krb5_context context, krb5_const_realm realm, + const char *user, const char *inst, + const char *localuser, int ok) +{ + krb5_principal p; + char localname[1024]; + krb5_error_code ret; + char *princ; + + ret = krb5_make_principal(context, &p, realm, user, inst, NULL); + if (ret) + krb5_err(context, 1, ret, "krb5_build_principal"); + + ret = krb5_unparse_name(context, p, &princ); + if (ret) + krb5_err(context, 1, ret, "krb5_unparse_name"); + + ret = krb5_aname_to_localname(context, p, sizeof(localname), localname); + krb5_free_principal(context, p); + free(princ); + if (ret) { + if (!ok) + return; + krb5_err(context, 1, ret, "krb5_aname_to_localname: %s -> %s", + princ, localuser); + } + + if (strcmp(localname, localuser) != 0) { + if (ok) + errx(1, "compared failed %s != %s (should have succeded)", + localname, localuser); + } else { + if (!ok) + errx(1, "compared failed %s == %s (should have failed)", + localname, localuser); + } + +} + +static int version_flag = 0; +static int help_flag = 0; + +static struct getargs args[] = { + {"version", 0, arg_flag, &version_flag, + "print version", NULL }, + {"help", 0, arg_flag, &help_flag, + NULL, NULL } +}; + +static void +usage (int ret) +{ + arg_printusage (args, + sizeof(args)/sizeof(*args), + NULL, + ""); + exit (ret); +} + +int +main(int argc, char **argv) +{ + krb5_context context; + krb5_error_code ret; + krb5_realm realm; + int optidx = 0; + char *user; + + setprogname(argv[0]); + + if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) + usage(1); + + if (help_flag) + usage (0); + + if(version_flag){ + print_version(NULL); + exit(0); + } + + argc -= optidx; + argv += optidx; + + if (argc != 1) + errx(1, "first argument should be a local user that in root .k5login"); + + user = argv[0]; + + ret = krb5_init_context(&context); + if (ret) + errx (1, "krb5_init_context failed: %d", ret); + + ret = krb5_get_default_realm(context, &realm); + if (ret) + krb5_err(context, 1, ret, "krb5_get_default_realm"); + + test_alname(context, realm, user, NULL, user, 1); + test_alname(context, realm, user, "root", "root", 1); + + test_alname(context, "FOO.BAR.BAZ.KAKA", user, NULL, user, 0); + test_alname(context, "FOO.BAR.BAZ.KAKA", user, "root", "root", 0); + + test_alname(context, realm, user, NULL, + "not-same-as-user", 0); + test_alname(context, realm, user, "root", + "not-same-as-user", 0); + + test_alname(context, "FOO.BAR.BAZ.KAKA", user, NULL, + "not-same-as-user", 0); + test_alname(context, "FOO.BAR.BAZ.KAKA", user, "root", + "not-same-as-user", 0); + + krb5_free_context(context); + + return 0; +} diff --git a/lib/krb5/test_cc.c b/lib/krb5/test_cc.c new file mode 100644 index 0000000..075cfe2 --- /dev/null +++ b/lib/krb5/test_cc.c @@ -0,0 +1,532 @@ +/* + * Copyright (c) 2003 - 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include "krb5_locl.h" +#include <getarg.h> +#include <err.h> + +RCSID("$Id: test_cc.c 22115 2007-12-03 21:21:42Z lha $"); + +static int debug_flag = 0; +static int version_flag = 0; +static int help_flag = 0; + +static void +test_default_name(krb5_context context) +{ + krb5_error_code ret; + const char *p, *test_cc_name = "/tmp/krb5-cc-test-foo"; + char *p1, *p2, *p3; + + p = krb5_cc_default_name(context); + if (p == NULL) + krb5_errx (context, 1, "krb5_cc_default_name 1 failed"); + p1 = estrdup(p); + + ret = krb5_cc_set_default_name(context, NULL); + if (p == NULL) + krb5_errx (context, 1, "krb5_cc_set_default_name failed"); + + p = krb5_cc_default_name(context); + if (p == NULL) + krb5_errx (context, 1, "krb5_cc_default_name 2 failed"); + p2 = estrdup(p); + + if (strcmp(p1, p2) != 0) + krb5_errx (context, 1, "krb5_cc_default_name no longer same"); + + ret = krb5_cc_set_default_name(context, test_cc_name); + if (p == NULL) + krb5_errx (context, 1, "krb5_cc_set_default_name 1 failed"); + + p = krb5_cc_default_name(context); + if (p == NULL) + krb5_errx (context, 1, "krb5_cc_default_name 2 failed"); + p3 = estrdup(p); + + if (strcmp(p3, test_cc_name) != 0) + krb5_errx (context, 1, "krb5_cc_set_default_name 1 failed"); + + free(p1); + free(p2); + free(p3); +} + +/* + * Check that a closed cc still keeps it data and that it's no longer + * there when it's destroyed. + */ + +static void +test_mcache(krb5_context context) +{ + krb5_error_code ret; + krb5_ccache id, id2; + const char *nc, *tc; + char *c; + krb5_principal p, p2; + + ret = krb5_parse_name(context, "lha@SU.SE", &p); + if (ret) + krb5_err(context, 1, ret, "krb5_parse_name"); + + ret = krb5_cc_gen_new(context, &krb5_mcc_ops, &id); + if (ret) + krb5_err(context, 1, ret, "krb5_cc_gen_new"); + + ret = krb5_cc_initialize(context, id, p); + if (ret) + krb5_err(context, 1, ret, "krb5_cc_initialize"); + + nc = krb5_cc_get_name(context, id); + if (nc == NULL) + krb5_errx(context, 1, "krb5_cc_get_name"); + + tc = krb5_cc_get_type(context, id); + if (tc == NULL) + krb5_errx(context, 1, "krb5_cc_get_name"); + + asprintf(&c, "%s:%s", tc, nc); + + krb5_cc_close(context, id); + + ret = krb5_cc_resolve(context, c, &id2); + if (ret) + krb5_err(context, 1, ret, "krb5_cc_resolve"); + + ret = krb5_cc_get_principal(context, id2, &p2); + if (ret) + krb5_err(context, 1, ret, "krb5_cc_get_principal"); + + if (krb5_principal_compare(context, p, p2) == FALSE) + krb5_errx(context, 1, "p != p2"); + + krb5_cc_destroy(context, id2); + krb5_free_principal(context, p); + krb5_free_principal(context, p2); + + ret = krb5_cc_resolve(context, c, &id2); + if (ret) + krb5_err(context, 1, ret, "krb5_cc_resolve"); + + ret = krb5_cc_get_principal(context, id2, &p2); + if (ret == 0) + krb5_errx(context, 1, "krb5_cc_get_principal"); + + krb5_cc_destroy(context, id2); + free(c); +} + +/* + * Test that init works on a destroyed cc. + */ + +static void +test_init_vs_destroy(krb5_context context, const krb5_cc_ops *ops) +{ + krb5_error_code ret; + krb5_ccache id, id2; + krb5_principal p, p2; + char *n; + + ret = krb5_parse_name(context, "lha@SU.SE", &p); + if (ret) + krb5_err(context, 1, ret, "krb5_parse_name"); + + ret = krb5_cc_gen_new(context, ops, &id); + if (ret) + krb5_err(context, 1, ret, "krb5_cc_gen_new"); + + asprintf(&n, "%s:%s", + krb5_cc_get_type(context, id), + krb5_cc_get_name(context, id)); + + ret = krb5_cc_resolve(context, n, &id2); + free(n); + if (ret) + krb5_err(context, 1, ret, "krb5_cc_resolve"); + + krb5_cc_destroy(context, id); + + ret = krb5_cc_initialize(context, id2, p); + if (ret) + krb5_err(context, 1, ret, "krb5_cc_initialize"); + + ret = krb5_cc_get_principal(context, id2, &p2); + if (ret) + krb5_err(context, 1, ret, "krb5_cc_get_principal"); + + krb5_cc_destroy(context, id2); + krb5_free_principal(context, p); + krb5_free_principal(context, p2); +} + +static void +test_fcache_remove(krb5_context context) +{ + krb5_error_code ret; + krb5_ccache id; + krb5_principal p; + krb5_creds cred; + + ret = krb5_parse_name(context, "lha@SU.SE", &p); + if (ret) + krb5_err(context, 1, ret, "krb5_parse_name"); + + ret = krb5_cc_gen_new(context, &krb5_fcc_ops, &id); + if (ret) + krb5_err(context, 1, ret, "krb5_cc_gen_new"); + + ret = krb5_cc_initialize(context, id, p); + if (ret) + krb5_err(context, 1, ret, "krb5_cc_initialize"); + + /* */ + memset(&cred, 0, sizeof(cred)); + ret = krb5_parse_name(context, "krbtgt/SU.SE@SU.SE", &cred.server); + if (ret) + krb5_err(context, 1, ret, "krb5_parse_name"); + ret = krb5_parse_name(context, "lha@SU.SE", &cred.client); + if (ret) + krb5_err(context, 1, ret, "krb5_parse_name"); + + ret = krb5_cc_store_cred(context, id, &cred); + if (ret) + krb5_err(context, 1, ret, "krb5_cc_store_cred"); + + ret = krb5_cc_remove_cred(context, id, 0, &cred); + if (ret) + krb5_err(context, 1, ret, "krb5_cc_remove_cred"); + + ret = krb5_cc_destroy(context, id); + if (ret) + krb5_err(context, 1, ret, "krb5_cc_destroy"); + + krb5_free_principal(context, p); + krb5_free_principal(context, cred.server); + krb5_free_principal(context, cred.client); +} + +static void +test_mcc_default(void) +{ + krb5_context context; + krb5_error_code ret; + krb5_ccache id, id2; + int i; + + for (i = 0; i < 10; i++) { + + ret = krb5_init_context(&context); + if (ret) + krb5_err(context, 1, ret, "krb5_init_context"); + + ret = krb5_cc_set_default_name(context, "MEMORY:foo"); + if (ret) + krb5_err(context, 1, ret, "krb5_cc_set_default_name"); + + ret = krb5_cc_default(context, &id); + if (ret) + krb5_err(context, 1, ret, "krb5_cc_default"); + + ret = krb5_cc_default(context, &id2); + if (ret) + krb5_err(context, 1, ret, "krb5_cc_default"); + + ret = krb5_cc_close(context, id); + if (ret) + krb5_err(context, 1, ret, "krb5_cc_close"); + + ret = krb5_cc_close(context, id2); + if (ret) + krb5_err(context, 1, ret, "krb5_cc_close"); + + krb5_free_context(context); + } +} + +struct { + char *str; + int fail; + char *res; +} cc_names[] = { + { "foo", 0, "foo" }, + { "%{uid}", 0 }, + { "foo%{null}", 0, "foo" }, + { "foo%{null}bar", 0, "foobar" }, + { "%{", 1 }, + { "%{foo %{", 1 }, + { "%{{", 1 }, +}; + +static void +test_def_cc_name(krb5_context context) +{ + krb5_error_code ret; + char *str; + int i; + + for (i = 0; i < sizeof(cc_names)/sizeof(cc_names[0]); i++) { + ret = _krb5_expand_default_cc_name(context, cc_names[i].str, &str); + if (ret) { + if (cc_names[i].fail == 0) + krb5_errx(context, 1, "test %d \"%s\" failed", + i, cc_names[i].str); + } else { + if (cc_names[i].fail) + krb5_errx(context, 1, "test %d \"%s\" was successful", + i, cc_names[i].str); + if (cc_names[i].res && strcmp(cc_names[i].res, str) != 0) + krb5_errx(context, 1, "test %d %s != %s", + i, cc_names[i].res, str); + if (debug_flag) + printf("%s => %s\n", cc_names[i].str, str); + free(str); + } + } +} + +static void +test_cache_find(krb5_context context, const char *type, const char *principal, + int find) +{ + krb5_principal client; + krb5_error_code ret; + krb5_ccache id = NULL; + + ret = krb5_parse_name(context, principal, &client); + if (ret) + krb5_err(context, 1, ret, "parse_name for %s failed", principal); + + ret = krb5_cc_cache_match(context, client, type, &id); + if (ret && find) + krb5_err(context, 1, ret, "cc_cache_match for %s failed", principal); + if (ret == 0 && !find) + krb5_err(context, 1, ret, "cc_cache_match for %s found", principal); + + if (id) + krb5_cc_close(context, id); + krb5_free_principal(context, client); +} + + +static void +test_cache_iter(krb5_context context, const char *type, int destroy) +{ + krb5_cc_cache_cursor cursor; + krb5_error_code ret; + krb5_ccache id; + + ret = krb5_cc_cache_get_first (context, type, &cursor); + if (ret == KRB5_CC_NOSUPP) + return; + else if (ret) + krb5_err(context, 1, ret, "krb5_cc_cache_get_first(%s)", type); + + + while ((ret = krb5_cc_cache_next (context, cursor, &id)) == 0) { + krb5_principal principal; + char *name; + + if (debug_flag) + printf("name: %s\n", krb5_cc_get_name(context, id)); + ret = krb5_cc_get_principal(context, id, &principal); + if (ret == 0) { + ret = krb5_unparse_name(context, principal, &name); + if (ret == 0) { + if (debug_flag) + printf("\tprincipal: %s\n", name); + free(name); + } + krb5_free_principal(context, principal); + } + if (destroy) + krb5_cc_destroy(context, id); + else + krb5_cc_close(context, id); + } + + krb5_cc_cache_end_seq_get(context, cursor); +} + +static void +test_copy(krb5_context context, const char *fromtype, const char *totype) +{ + const krb5_cc_ops *from, *to; + krb5_ccache fromid, toid; + krb5_error_code ret; + krb5_principal p, p2; + + from = krb5_cc_get_prefix_ops(context, fromtype); + if (from == NULL) + krb5_errx(context, 1, "%s isn't a type", fromtype); + + to = krb5_cc_get_prefix_ops(context, totype); + if (to == NULL) + krb5_errx(context, 1, "%s isn't a type", totype); + + ret = krb5_parse_name(context, "lha@SU.SE", &p); + if (ret) + krb5_err(context, 1, ret, "krb5_parse_name"); + + ret = krb5_cc_gen_new(context, from, &fromid); + if (ret) + krb5_err(context, 1, ret, "krb5_cc_gen_new"); + + ret = krb5_cc_initialize(context, fromid, p); + if (ret) + krb5_err(context, 1, ret, "krb5_cc_initialize"); + + ret = krb5_cc_gen_new(context, to, &toid); + if (ret) + krb5_err(context, 1, ret, "krb5_cc_gen_new"); + + ret = krb5_cc_copy_cache(context, fromid, toid); + if (ret) + krb5_err(context, 1, ret, "krb5_cc_copy_cache"); + + ret = krb5_cc_get_principal(context, toid, &p2); + if (ret) + krb5_err(context, 1, ret, "krb5_cc_get_principal"); + + if (krb5_principal_compare(context, p, p2) == FALSE) + krb5_errx(context, 1, "p != p2"); + + krb5_free_principal(context, p); + krb5_free_principal(context, p2); + + krb5_cc_destroy(context, fromid); + krb5_cc_destroy(context, toid); +} + +static void +test_prefix_ops(krb5_context context, const char *name, const krb5_cc_ops *ops) +{ + const krb5_cc_ops *o; + + o = krb5_cc_get_prefix_ops(context, name); + if (o == NULL) + krb5_errx(context, 1, "found no match for prefix '%s'", name); + if (strcmp(o->prefix, ops->prefix) != 0) + krb5_errx(context, 1, "ops for prefix '%s' is not " + "the expected %s != %s", name, o->prefix, ops->prefix); +} + + +static struct getargs args[] = { + {"debug", 'd', arg_flag, &debug_flag, + "turn on debuggin", NULL }, + {"version", 0, arg_flag, &version_flag, + "print version", NULL }, + {"help", 0, arg_flag, &help_flag, + NULL, NULL } +}; + +static void +usage (int ret) +{ + arg_printusage (args, sizeof(args)/sizeof(*args), NULL, "hostname ..."); + exit (ret); +} + +int +main(int argc, char **argv) +{ + krb5_context context; + krb5_error_code ret; + int optidx = 0; + krb5_ccache id1, id2; + + setprogname(argv[0]); + + if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) + usage(1); + + if (help_flag) + usage (0); + + if(version_flag){ + print_version(NULL); + exit(0); + } + + argc -= optidx; + argv += optidx; + + ret = krb5_init_context(&context); + if (ret) + errx (1, "krb5_init_context failed: %d", ret); + + test_fcache_remove(context); + test_default_name(context); + test_mcache(context); + test_init_vs_destroy(context, &krb5_mcc_ops); + test_init_vs_destroy(context, &krb5_fcc_ops); + test_mcc_default(); + test_def_cc_name(context); + test_cache_iter(context, "MEMORY", 0); + { + krb5_principal p; + krb5_cc_new_unique(context, "MEMORY", "bar", &id1); + krb5_cc_new_unique(context, "MEMORY", "baz", &id2); + krb5_parse_name(context, "lha@SU.SE", &p); + krb5_cc_initialize(context, id1, p); + krb5_free_principal(context, p); + } + + test_cache_find(context, "MEMORY", "lha@SU.SE", 1); + test_cache_find(context, "MEMORY", "hulabundulahotentot@SU.SE", 0); + + test_cache_iter(context, "MEMORY", 0); + test_cache_iter(context, "MEMORY", 1); + test_cache_iter(context, "MEMORY", 0); + test_cache_iter(context, "FILE", 0); + test_cache_iter(context, "API", 0); + + test_copy(context, "FILE", "FILE"); + test_copy(context, "MEMORY", "MEMORY"); + test_copy(context, "FILE", "MEMORY"); + test_copy(context, "MEMORY", "FILE"); + + test_prefix_ops(context, "FILE:/tmp/foo", &krb5_fcc_ops); + test_prefix_ops(context, "FILE", &krb5_fcc_ops); + test_prefix_ops(context, "MEMORY", &krb5_mcc_ops); + test_prefix_ops(context, "MEMORY:foo", &krb5_mcc_ops); + test_prefix_ops(context, "/tmp/kaka", &krb5_fcc_ops); + + krb5_cc_destroy(context, id1); + krb5_cc_destroy(context, id2); + + krb5_free_context(context); + + return 0; +} diff --git a/lib/krb5/test_config.c b/lib/krb5/test_config.c new file mode 100644 index 0000000..7fe224e --- /dev/null +++ b/lib/krb5/test_config.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "krb5_locl.h" +#include <err.h> + +RCSID("$Id: test_config.c 15036 2005-04-30 15:19:58Z lha $"); + +static int +check_config_file(krb5_context context, char *filelist, char **res, int def) +{ + krb5_error_code ret; + char **pp; + int i; + + pp = NULL; + + if (def) + ret = krb5_prepend_config_files_default(filelist, &pp); + else + ret = krb5_prepend_config_files(filelist, NULL, &pp); + + if (ret) + krb5_err(context, 1, ret, "prepend_config_files"); + + for (i = 0; res[i] && pp[i]; i++) + if (strcmp(pp[i], res[i]) != 0) + krb5_errx(context, 1, "'%s' != '%s'", pp[i], res[i]); + + if (res[i] != NULL) + krb5_errx(context, 1, "pp ended before res list"); + + if (def) { + char **deflist; + int j; + + ret = krb5_get_default_config_files(&deflist); + if (ret) + krb5_err(context, 1, ret, "get_default_config_files"); + + for (j = 0 ; pp[i] && deflist[j]; i++, j++) + if (strcmp(pp[i], deflist[j]) != 0) + krb5_errx(context, 1, "'%s' != '%s'", pp[i], deflist[j]); + + if (deflist[j] != NULL) + krb5_errx(context, 1, "pp ended before def list"); + krb5_free_config_files(deflist); + } + + if (pp[i] != NULL) + krb5_errx(context, 1, "pp ended after res (and def) list"); + + krb5_free_config_files(pp); + + return 0; +} + +char *list0[] = { "/tmp/foo", NULL }; +char *list1[] = { "/tmp/foo", "/tmp/foo/bar", NULL }; +char *list2[] = { "", NULL }; + +struct { + char *fl; + char **res; +} test[] = { + { "/tmp/foo", NULL }, + { "/tmp/foo:/tmp/foo/bar", NULL }, + { "", NULL } +}; + +int +main(int argc, char **argv) +{ + krb5_context context; + krb5_error_code ret; + int i; + + ret = krb5_init_context(&context); + if (ret) + errx(1, "krb5_init_context %d", ret); + + test[0].res = list0; + test[1].res = list1; + test[2].res = list2; + + for (i = 0; i < sizeof(test)/sizeof(*test); i++) { + check_config_file(context, test[i].fl, test[i].res, 0); + check_config_file(context, test[i].fl, test[i].res, 1); + } + + krb5_free_context(context); + + return 0; +} diff --git a/lib/krb5/test_crypto.c b/lib/krb5/test_crypto.c new file mode 100644 index 0000000..0837911 --- /dev/null +++ b/lib/krb5/test_crypto.c @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2003-2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include "krb5_locl.h" +#include <err.h> +#include <getarg.h> + +RCSID("$Id: test_crypto.c 16290 2005-11-24 09:57:50Z lha $"); + +static void +time_encryption(krb5_context context, size_t size, + krb5_enctype etype, int iterations) +{ + struct timeval tv1, tv2; + krb5_error_code ret; + krb5_keyblock key; + krb5_crypto crypto; + krb5_data data; + char *etype_name; + void *buf; + int i; + + ret = krb5_generate_random_keyblock(context, etype, &key); + if (ret) + krb5_err(context, 1, ret, "krb5_generate_random_keyblock"); + + ret = krb5_enctype_to_string(context, etype, &etype_name); + if (ret) + krb5_err(context, 1, ret, "krb5_enctype_to_string"); + + buf = malloc(size); + if (buf == NULL) + krb5_errx(context, 1, "out of memory"); + memset(buf, 0, size); + + ret = krb5_crypto_init(context, &key, 0, &crypto); + if (ret) + krb5_err(context, 1, ret, "krb5_crypto_init"); + + gettimeofday(&tv1, NULL); + + for (i = 0; i < iterations; i++) { + ret = krb5_encrypt(context, crypto, 0, buf, size, &data); + if (ret) + krb5_err(context, 1, ret, "encrypt: %d", i); + krb5_data_free(&data); + } + + gettimeofday(&tv2, NULL); + + timevalsub(&tv2, &tv1); + + printf("%s size: %7lu iterations: %d time: %3ld.%06ld\n", + etype_name, (unsigned long)size, iterations, + (long)tv2.tv_sec, (long)tv2.tv_usec); + + free(buf); + free(etype_name); + krb5_crypto_destroy(context, crypto); + krb5_free_keyblock_contents(context, &key); +} + +static void +time_s2k(krb5_context context, + krb5_enctype etype, + const char *password, + krb5_salt salt, + int iterations) +{ + struct timeval tv1, tv2; + krb5_error_code ret; + krb5_keyblock key; + krb5_data opaque; + char *etype_name; + int i; + + ret = krb5_enctype_to_string(context, etype, &etype_name); + if (ret) + krb5_err(context, 1, ret, "krb5_enctype_to_string"); + + opaque.data = NULL; + opaque.length = 0; + + gettimeofday(&tv1, NULL); + + for (i = 0; i < iterations; i++) { + ret = krb5_string_to_key_salt_opaque(context, etype, password, salt, + opaque, &key); + if (ret) + krb5_err(context, 1, ret, "krb5_string_to_key_data_salt_opaque"); + krb5_free_keyblock_contents(context, &key); + } + + gettimeofday(&tv2, NULL); + + timevalsub(&tv2, &tv1); + + printf("%s string2key %d iterations time: %3ld.%06ld\n", + etype_name, iterations, (long)tv2.tv_sec, (long)tv2.tv_usec); + free(etype_name); + +} + +static int version_flag = 0; +static int help_flag = 0; + +static struct getargs args[] = { + {"version", 0, arg_flag, &version_flag, + "print version", NULL }, + {"help", 0, arg_flag, &help_flag, + NULL, NULL } +}; + +static void +usage (int ret) +{ + arg_printusage (args, + sizeof(args)/sizeof(*args), + NULL, + ""); + exit (ret); +} + +int +main(int argc, char **argv) +{ + krb5_context context; + krb5_error_code ret; + int i, enciter, s2kiter; + int optidx = 0; + krb5_salt salt; + + krb5_enctype enctypes[] = { + ETYPE_DES_CBC_CRC, + ETYPE_DES3_CBC_SHA1, + ETYPE_ARCFOUR_HMAC_MD5, + ETYPE_AES128_CTS_HMAC_SHA1_96, + ETYPE_AES256_CTS_HMAC_SHA1_96 + }; + + setprogname(argv[0]); + + if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) + usage(1); + + if (help_flag) + usage (0); + + if(version_flag){ + print_version(NULL); + exit(0); + } + + argc -= optidx; + argv += optidx; + + salt.salttype = KRB5_PW_SALT; + salt.saltvalue.data = NULL; + salt.saltvalue.length = 0; + + ret = krb5_init_context(&context); + if (ret) + errx (1, "krb5_init_context failed: %d", ret); + + enciter = 1000; + s2kiter = 100; + + for (i = 0; i < sizeof(enctypes)/sizeof(enctypes[0]); i++) { + + time_encryption(context, 16, enctypes[i], enciter); + time_encryption(context, 32, enctypes[i], enciter); + time_encryption(context, 512, enctypes[i], enciter); + time_encryption(context, 1024, enctypes[i], enciter); + time_encryption(context, 2048, enctypes[i], enciter); + time_encryption(context, 4096, enctypes[i], enciter); + time_encryption(context, 8192, enctypes[i], enciter); + time_encryption(context, 16384, enctypes[i], enciter); + time_encryption(context, 32768, enctypes[i], enciter); + + time_s2k(context, enctypes[i], "mYsecreitPassword", salt, s2kiter); + } + + krb5_free_context(context); + + return 0; +} diff --git a/lib/krb5/test_crypto_wrapping.c b/lib/krb5/test_crypto_wrapping.c new file mode 100644 index 0000000..1618fdf --- /dev/null +++ b/lib/krb5/test_crypto_wrapping.c @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include "krb5_locl.h" +#include <err.h> +#include <getarg.h> + +RCSID("$Id: test_crypto_wrapping.c 18809 2006-10-22 07:11:43Z lha $"); + +static void +test_wrapping(krb5_context context, + size_t min_size, + size_t max_size, + size_t step, + krb5_enctype etype) +{ + krb5_error_code ret; + krb5_keyblock key; + krb5_crypto crypto; + krb5_data data; + char *etype_name; + void *buf; + size_t size; + + ret = krb5_generate_random_keyblock(context, etype, &key); + if (ret) + krb5_err(context, 1, ret, "krb5_generate_random_keyblock"); + + ret = krb5_enctype_to_string(context, etype, &etype_name); + if (ret) + krb5_err(context, 1, ret, "krb5_enctype_to_string"); + + buf = malloc(max_size); + if (buf == NULL) + krb5_errx(context, 1, "out of memory"); + memset(buf, 0, max_size); + + ret = krb5_crypto_init(context, &key, 0, &crypto); + if (ret) + krb5_err(context, 1, ret, "krb5_crypto_init"); + + for (size = min_size; size < max_size; size += step) { + size_t wrapped_size; + + ret = krb5_encrypt(context, crypto, 0, buf, size, &data); + if (ret) + krb5_err(context, 1, ret, "encrypt size %lu using %s", + (unsigned long)size, etype_name); + + wrapped_size = krb5_get_wrapped_length(context, crypto, size); + + if (wrapped_size != data.length) + krb5_errx(context, 1, "calculated wrapped length %lu != " + "real wrapped length %lu for data length %lu using " + "enctype %s", + (unsigned long)wrapped_size, + (unsigned long)data.length, + (unsigned long)size, + etype_name); + krb5_data_free(&data); + } + + free(etype_name); + free(buf); + krb5_crypto_destroy(context, crypto); + krb5_free_keyblock_contents(context, &key); +} + + + +static int version_flag = 0; +static int help_flag = 0; + +static struct getargs args[] = { + {"version", 0, arg_flag, &version_flag, + "print version", NULL }, + {"help", 0, arg_flag, &help_flag, + NULL, NULL } +}; + +static void +usage (int ret) +{ + arg_printusage (args, + sizeof(args)/sizeof(*args), + NULL, + ""); + exit (ret); +} + +int +main(int argc, char **argv) +{ + krb5_context context; + krb5_error_code ret; + int i, optidx = 0; + + krb5_enctype enctypes[] = { + ETYPE_DES_CBC_CRC, + ETYPE_DES_CBC_MD4, + ETYPE_DES_CBC_MD5, + ETYPE_DES3_CBC_SHA1, + ETYPE_ARCFOUR_HMAC_MD5, + ETYPE_AES128_CTS_HMAC_SHA1_96, + ETYPE_AES256_CTS_HMAC_SHA1_96 + }; + + setprogname(argv[0]); + + if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) + usage(1); + + if (help_flag) + usage (0); + + if(version_flag){ + print_version(NULL); + exit(0); + } + + argc -= optidx; + argv += optidx; + + ret = krb5_init_context(&context); + if (ret) + errx (1, "krb5_init_context failed: %d", ret); + + for (i = 0; i < sizeof(enctypes)/sizeof(enctypes[0]); i++) { + test_wrapping(context, 0, 1024, 1, enctypes[i]); + test_wrapping(context, 1024, 1024 * 100, 1024, enctypes[i]); + } + krb5_free_context(context); + + return 0; +} diff --git a/lib/krb5/test_forward.c b/lib/krb5/test_forward.c new file mode 100644 index 0000000..1639953 --- /dev/null +++ b/lib/krb5/test_forward.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2008 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include "krb5_locl.h" +#include <err.h> +#include <getarg.h> + +RCSID("$Id$"); + +static int version_flag = 0; +static int help_flag = 0; + +static struct getargs args[] = { + {"version", 0, arg_flag, &version_flag, + "print version", NULL }, + {"help", 0, arg_flag, &help_flag, + NULL, NULL } +}; + +static void +usage (int ret) +{ + arg_printusage (args, + sizeof(args)/sizeof(*args), + NULL, + "hostname"); + exit (ret); +} + +int +main(int argc, char **argv) +{ + const char *hostname; + krb5_context context; + krb5_auth_context ac; + krb5_error_code ret; + krb5_creds cred; + krb5_ccache id; + krb5_data data; + int optidx = 0; + + setprogname (argv[0]); + + if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) + usage(1); + + if (help_flag) + usage (0); + + if(version_flag){ + print_version(NULL); + exit(0); + } + + argc -= optidx; + argv += optidx; + + if (argc < 1) + usage(1); + + hostname = argv[0]; + + memset(&cred, 0, sizeof(cred)); + + ret = krb5_init_context(&context); + if (ret) + errx (1, "krb5_init_context failed: %d", ret); + + ret = krb5_cc_default(context, &id); + if (ret) + krb5_err(context, 1, ret, "krb5_cc_default failed: %d", ret); + + ret = krb5_auth_con_init(context, &ac); + if (ret) + krb5_err(context, 1, ret, "krb5_auth_con_init failed: %d", ret); + + krb5_auth_con_addflags(context, ac, + KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED, NULL); + + ret = krb5_cc_get_principal(context, id, &cred.client); + if (ret) + krb5_err(context, 1, ret, "krb5_cc_get_principal"); + + ret = krb5_make_principal(context, + &cred.server, + krb5_principal_get_realm(context, cred.client), + KRB5_TGS_NAME, + krb5_principal_get_realm(context, cred.client), + NULL); + if (ret) + krb5_err(context, 1, ret, "krb5_make_principal(server)"); + + ret = krb5_get_forwarded_creds (context, + ac, + id, + KDC_OPT_FORWARDABLE, + hostname, + &cred, + &data); + if (ret) + krb5_err (context, 1, ret, "krb5_get_forwarded_creds"); + + krb5_data_free(&data); + krb5_free_context(context); + + return 0; +} diff --git a/lib/krb5/test_get_addrs.c b/lib/krb5/test_get_addrs.c new file mode 100644 index 0000000..1d53e0e --- /dev/null +++ b/lib/krb5/test_get_addrs.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2000 - 2002 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include "krb5_locl.h" +#include <err.h> +#include <getarg.h> + +RCSID("$Id: test_get_addrs.c 15474 2005-06-17 04:48:02Z lha $"); + +/* print all addresses that we find */ + +static void +print_addresses (krb5_context context, const krb5_addresses *addrs) +{ + int i; + char buf[256]; + size_t len; + + for (i = 0; i < addrs->len; ++i) { + krb5_print_address (&addrs->val[i], buf, sizeof(buf), &len); + printf ("%s\n", buf); + } +} + +static int version_flag = 0; +static int help_flag = 0; + +static struct getargs args[] = { + {"version", 0, arg_flag, &version_flag, + "print version", NULL }, + {"help", 0, arg_flag, &help_flag, + NULL, NULL } +}; + +static void +usage (int ret) +{ + arg_printusage (args, + sizeof(args)/sizeof(*args), + NULL, + ""); + exit (ret); +} + +int +main(int argc, char **argv) +{ + krb5_context context; + krb5_error_code ret; + krb5_addresses addrs; + int optidx = 0; + + setprogname (argv[0]); + + if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) + usage(1); + + if (help_flag) + usage (0); + + if(version_flag){ + print_version(NULL); + exit(0); + } + + argc -= optidx; + argv += optidx; + + ret = krb5_init_context(&context); + if (ret) + errx (1, "krb5_init_context failed: %d", ret); + + ret = krb5_get_all_client_addrs (context, &addrs); + if (ret) + krb5_err (context, 1, ret, "krb5_get_all_client_addrs"); + printf ("client addresses\n"); + print_addresses (context, &addrs); + krb5_free_addresses (context, &addrs); + + ret = krb5_get_all_server_addrs (context, &addrs); + if (ret) + krb5_err (context, 1, ret, "krb5_get_all_server_addrs"); + printf ("server addresses\n"); + print_addresses (context, &addrs); + krb5_free_addresses (context, &addrs); + return 0; +} diff --git a/lib/krb5/test_hostname.c b/lib/krb5/test_hostname.c new file mode 100644 index 0000000..095cb39 --- /dev/null +++ b/lib/krb5/test_hostname.c @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include "krb5_locl.h" +#include <err.h> +#include <getarg.h> + +RCSID("$Id: test_hostname.c 15965 2005-08-23 20:18:55Z lha $"); + +static int debug_flag = 0; +static int version_flag = 0; +static int help_flag = 0; + +static int +expand_hostname(krb5_context context, const char *host) +{ + krb5_error_code ret; + char *h, **r; + + ret = krb5_expand_hostname(context, host, &h); + if (ret) + krb5_err(context, 1, ret, "krb5_expand_hostname(%s)", host); + + free(h); + + if (debug_flag) + printf("hostname: %s -> %s\n", host, h); + + ret = krb5_expand_hostname_realms(context, host, &h, &r); + if (ret) + krb5_err(context, 1, ret, "krb5_expand_hostname_realms(%s)", host); + + if (debug_flag) { + int j; + + printf("hostname: %s -> %s\n", host, h); + for (j = 0; r[j]; j++) { + printf("\trealm: %s\n", r[j]); + } + } + free(h); + krb5_free_host_realm(context, r); + + return 0; +} + +static int +test_expand_hostname(krb5_context context) +{ + int i, errors = 0; + + struct t { + krb5_error_code ret; + const char *orig_hostname; + const char *new_hostname; + } tests[] = { + { 0, "pstn1.su.se", "pstn1.su.se" }, + { 0, "pstnproxy.su.se", "pstnproxy.su.se" }, + }; + + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + errors += expand_hostname(context, tests[i].orig_hostname); + } + + return errors; +} + +static struct getargs args[] = { + {"debug", 'd', arg_flag, &debug_flag, + "turn on debuggin", NULL }, + {"version", 0, arg_flag, &version_flag, + "print version", NULL }, + {"help", 0, arg_flag, &help_flag, + NULL, NULL } +}; + +static void +usage (int ret) +{ + arg_printusage (args, sizeof(args)/sizeof(*args), NULL, "hostname ..."); + exit (ret); +} + + +int +main(int argc, char **argv) +{ + krb5_context context; + krb5_error_code ret; + int optidx = 0, errors = 0; + + setprogname(argv[0]); + + if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) + usage(1); + + if (help_flag) + usage (0); + + if(version_flag){ + print_version(NULL); + exit(0); + } + + argc -= optidx; + argv += optidx; + + ret = krb5_init_context(&context); + if (ret) + errx (1, "krb5_init_context failed: %d", ret); + + if (argc > 0) { + while (argc-- > 0) + errors += expand_hostname(context, *argv++); + return errors; + } + + errors += test_expand_hostname(context); + + krb5_free_context(context); + + return errors; +} diff --git a/lib/krb5/test_keytab.c b/lib/krb5/test_keytab.c new file mode 100644 index 0000000..97361cc --- /dev/null +++ b/lib/krb5/test_keytab.c @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include "krb5_locl.h" +#include <err.h> + +RCSID("$Id: test_keytab.c 18809 2006-10-22 07:11:43Z lha $"); + +/* + * Test that removal entry from of empty keytab doesn't corrupts + * memory. + */ + +static void +test_empty_keytab(krb5_context context, const char *keytab) +{ + krb5_error_code ret; + krb5_keytab id; + krb5_keytab_entry entry; + + ret = krb5_kt_resolve(context, keytab, &id); + if (ret) + krb5_err(context, 1, ret, "krb5_kt_resolve"); + + memset(&entry, 0, sizeof(entry)); + + krb5_kt_remove_entry(context, id, &entry); + + ret = krb5_kt_close(context, id); + if (ret) + krb5_err(context, 1, ret, "krb5_kt_close"); +} + +/* + * Test that memory keytab are refcounted. + */ + +static void +test_memory_keytab(krb5_context context, const char *keytab, const char *keytab2) +{ + krb5_error_code ret; + krb5_keytab id, id2, id3; + krb5_keytab_entry entry, entry2, entry3; + + ret = krb5_kt_resolve(context, keytab, &id); + if (ret) + krb5_err(context, 1, ret, "krb5_kt_resolve"); + + memset(&entry, 0, sizeof(entry)); + ret = krb5_parse_name(context, "lha@SU.SE", &entry.principal); + if (ret) + krb5_err(context, 1, ret, "krb5_parse_name"); + entry.vno = 1; + ret = krb5_generate_random_keyblock(context, + ETYPE_AES256_CTS_HMAC_SHA1_96, + &entry.keyblock); + if (ret) + krb5_err(context, 1, ret, "krb5_generate_random_keyblock"); + + krb5_kt_add_entry(context, id, &entry); + + ret = krb5_kt_resolve(context, keytab, &id2); + if (ret) + krb5_err(context, 1, ret, "krb5_kt_resolve"); + + ret = krb5_kt_get_entry(context, id, + entry.principal, + 0, + ETYPE_AES256_CTS_HMAC_SHA1_96, + &entry2); + if (ret) + krb5_err(context, 1, ret, "krb5_kt_get_entry"); + krb5_kt_free_entry(context, &entry2); + + ret = krb5_kt_close(context, id); + if (ret) + krb5_err(context, 1, ret, "krb5_kt_close"); + + ret = krb5_kt_get_entry(context, id2, + entry.principal, + 0, + ETYPE_AES256_CTS_HMAC_SHA1_96, + &entry2); + if (ret) + krb5_err(context, 1, ret, "krb5_kt_get_entry"); + krb5_kt_free_entry(context, &entry2); + + ret = krb5_kt_close(context, id2); + if (ret) + krb5_err(context, 1, ret, "krb5_kt_close"); + + + ret = krb5_kt_resolve(context, keytab2, &id3); + if (ret) + krb5_err(context, 1, ret, "krb5_kt_resolve"); + + memset(&entry3, 0, sizeof(entry3)); + ret = krb5_parse_name(context, "lha3@SU.SE", &entry3.principal); + if (ret) + krb5_err(context, 1, ret, "krb5_parse_name"); + entry3.vno = 1; + ret = krb5_generate_random_keyblock(context, + ETYPE_AES256_CTS_HMAC_SHA1_96, + &entry3.keyblock); + if (ret) + krb5_err(context, 1, ret, "krb5_generate_random_keyblock"); + + krb5_kt_add_entry(context, id3, &entry3); + + + ret = krb5_kt_resolve(context, keytab, &id); + if (ret) + krb5_err(context, 1, ret, "krb5_kt_resolve"); + + ret = krb5_kt_get_entry(context, id, + entry.principal, + 0, + ETYPE_AES256_CTS_HMAC_SHA1_96, + &entry2); + if (ret == 0) + krb5_errx(context, 1, "krb5_kt_get_entry when if should fail"); + + krb5_kt_remove_entry(context, id, &entry); + + ret = krb5_kt_close(context, id); + if (ret) + krb5_err(context, 1, ret, "krb5_kt_close"); + + krb5_kt_free_entry(context, &entry); + + krb5_kt_remove_entry(context, id3, &entry3); + + ret = krb5_kt_close(context, id3); + if (ret) + krb5_err(context, 1, ret, "krb5_kt_close"); + + krb5_free_principal(context, entry3.principal); + krb5_free_keyblock_contents(context, &entry3.keyblock); +} + +int +main(int argc, char **argv) +{ + krb5_context context; + krb5_error_code ret; + + setprogname(argv[0]); + + ret = krb5_init_context(&context); + if (ret) + errx (1, "krb5_init_context failed: %d", ret); + + test_empty_keytab(context, "MEMORY:foo"); + test_empty_keytab(context, "FILE:foo"); + test_empty_keytab(context, "KRB4:foo"); + + test_memory_keytab(context, "MEMORY:foo", "MEMORY:foo2"); + + krb5_free_context(context); + + return 0; +} diff --git a/lib/krb5/test_kuserok.c b/lib/krb5/test_kuserok.c new file mode 100644 index 0000000..04a6f21 --- /dev/null +++ b/lib/krb5/test_kuserok.c @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include "krb5_locl.h" +#include <getarg.h> +#include <err.h> + +RCSID("$Id: test_kuserok.c 15033 2005-04-30 15:15:38Z lha $"); + +static int version_flag = 0; +static int help_flag = 0; + +static struct getargs args[] = { + {"version", 0, arg_flag, &version_flag, + "print version", NULL }, + {"help", 0, arg_flag, &help_flag, + NULL, NULL } +}; + +static void +usage (int ret) +{ + arg_printusage (args, + sizeof(args)/sizeof(*args), + NULL, + "principal luser"); + exit (ret); +} + +int +main(int argc, char **argv) +{ + krb5_context context; + krb5_error_code ret; + krb5_principal principal; + char *p; + int o = 0; + + setprogname(argv[0]); + + if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &o)) + usage(1); + + if (help_flag) + usage (0); + + if(version_flag){ + print_version(NULL); + exit(0); + } + + argc -= o; + argv += o; + + ret = krb5_init_context(&context); + if (ret) + errx (1, "krb5_init_context failed: %d", ret); + + if (argc != 2) + usage(1); + + ret = krb5_parse_name(context, argv[0], &principal); + if (ret) + krb5_err(context, 1, ret, "krb5_parse_name"); + + ret = krb5_unparse_name(context, principal, &p); + if (ret) + krb5_err(context, 1, ret, "krb5_unparse_name"); + + ret = krb5_kuserok(context, principal, argv[1]); + + krb5_free_context(context); + + printf("%s is %sallowed to login as %s\n", p, ret ? "" : "NOT ", argv[1]); + + return 0; +} diff --git a/lib/krb5/test_mem.c b/lib/krb5/test_mem.c new file mode 100644 index 0000000..8989cae --- /dev/null +++ b/lib/krb5/test_mem.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include "krb5_locl.h" +#include <err.h> + +RCSID("$Id: test_mem.c 15931 2005-08-12 13:43:46Z lha $"); + +/* + * Test run functions, to be used with valgrind to detect memoryleaks. + */ + +static void +check_log(void) +{ + int i; + + for (i = 0; i < 10; i++) { + krb5_log_facility *logfacility; + krb5_context context; + krb5_error_code ret; + + ret = krb5_init_context(&context); + if (ret) + errx (1, "krb5_init_context failed: %d", ret); + + krb5_initlog(context, "test-mem", &logfacility); + krb5_addlog_dest(context, logfacility, "0/STDERR:"); + krb5_set_warn_dest(context, logfacility); + + krb5_free_context(context); + } +} + + +int +main(int argc, char **argv) +{ + setprogname(argv[0]); + + check_log(); + + return 0; +} diff --git a/lib/krb5/test_pac.c b/lib/krb5/test_pac.c new file mode 100644 index 0000000..a22fe3a --- /dev/null +++ b/lib/krb5/test_pac.c @@ -0,0 +1,295 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: test_pac.c 21934 2007-08-27 14:21:04Z lha $"); + +/* + * This PAC and keys are copied (with permission) from Samba torture + * regression test suite, they where created by Andrew Bartlet. + */ + +static const unsigned char saved_pac[] = { + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xd8, 0x01, 0x00, 0x00, + 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x08, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, + 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x30, 0xdf, 0xa6, 0xcb, + 0x4f, 0x7d, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x7f, 0xc0, 0x3c, 0x4e, 0x59, 0x62, 0x73, 0xc5, 0x01, 0xc0, 0x3c, 0x4e, 0x59, + 0x62, 0x73, 0xc5, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x16, 0x00, 0x16, 0x00, + 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x02, 0x00, 0x65, 0x00, 0x00, 0x00, + 0xed, 0x03, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x02, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x16, 0x00, 0x20, 0x00, 0x02, 0x00, 0x16, 0x00, 0x18, 0x00, + 0x24, 0x00, 0x02, 0x00, 0x28, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, + 0x57, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00, + 0x41, 0x00, 0x4c, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x57, 0x00, 0x32, 0x00, + 0x30, 0x00, 0x30, 0x00, 0x33, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x41, 0x00, 0x4c, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x57, 0x00, 0x49, 0x00, + 0x4e, 0x00, 0x32, 0x00, 0x4b, 0x00, 0x33, 0x00, 0x54, 0x00, 0x48, 0x00, 0x49, 0x00, 0x4e, 0x00, + 0x4b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, + 0x15, 0x00, 0x00, 0x00, 0x11, 0x2f, 0xaf, 0xb5, 0x90, 0x04, 0x1b, 0xec, 0x50, 0x3b, 0xec, 0xdc, + 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x66, 0x28, 0xea, 0x37, 0x80, 0xc5, 0x01, 0x16, 0x00, 0x77, 0x00, 0x32, 0x00, 0x30, 0x00, + 0x30, 0x00, 0x33, 0x00, 0x66, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x24, 0x00, + 0x76, 0xff, 0xff, 0xff, 0x37, 0xd5, 0xb0, 0xf7, 0x24, 0xf0, 0xd6, 0xd4, 0xec, 0x09, 0x86, 0x5a, + 0xa0, 0xe8, 0xc3, 0xa9, 0x00, 0x00, 0x00, 0x00, 0x76, 0xff, 0xff, 0xff, 0xb4, 0xd8, 0xb8, 0xfe, + 0x83, 0xb3, 0x13, 0x3f, 0xfc, 0x5c, 0x41, 0xad, 0xe2, 0x64, 0x83, 0xe0, 0x00, 0x00, 0x00, 0x00 +}; + +static int type_1_length = 472; + +static const krb5_keyblock kdc_keyblock = { + ETYPE_ARCFOUR_HMAC_MD5, + { 16, "\xB2\x86\x75\x71\x48\xAF\x7F\xD2\x52\xC5\x36\x03\xA1\x50\xB7\xE7" } +}; + +static const krb5_keyblock member_keyblock = { + ETYPE_ARCFOUR_HMAC_MD5, + { 16, "\xD2\x17\xFA\xEA\xE5\xE6\xB5\xF9\x5C\xCC\x94\x07\x7A\xB8\xA5\xFC" } +}; + +static time_t authtime = 1120440609; +static const char *user = "w2003final$@WIN2K3.THINKER.LOCAL"; + +int +main(int argc, char **argv) +{ + krb5_error_code ret; + krb5_context context; + krb5_pac pac; + krb5_data data; + krb5_principal p; + + ret = krb5_init_context(&context); + if (ret) + errx(1, "krb5_init_contex"); + + ret = krb5_parse_name(context, user, &p); + if (ret) + krb5_err(context, 1, ret, "krb5_parse_name"); + + ret = krb5_pac_parse(context, saved_pac, sizeof(saved_pac), &pac); + if (ret) + krb5_err(context, 1, ret, "krb5_pac_parse"); + + ret = krb5_pac_verify(context, pac, authtime, p, + &member_keyblock, &kdc_keyblock); + if (ret) + krb5_err(context, 1, ret, "krb5_pac_verify"); + + ret = _krb5_pac_sign(context, pac, authtime, p, + &member_keyblock, &kdc_keyblock, &data); + if (ret) + krb5_err(context, 1, ret, "_krb5_pac_sign"); + + krb5_pac_free(context, pac); + + ret = krb5_pac_parse(context, data.data, data.length, &pac); + krb5_data_free(&data); + if (ret) + krb5_err(context, 1, ret, "krb5_pac_parse 2"); + + ret = krb5_pac_verify(context, pac, authtime, p, + &member_keyblock, &kdc_keyblock); + if (ret) + krb5_err(context, 1, ret, "krb5_pac_verify 2"); + + /* make a copy and try to reproduce it */ + { + uint32_t *list; + size_t len, i; + krb5_pac pac2; + + ret = krb5_pac_init(context, &pac2); + if (ret) + krb5_err(context, 1, ret, "krb5_pac_init"); + + /* our two user buffer plus the three "system" buffers */ + ret = krb5_pac_get_types(context, pac, &len, &list); + if (ret) + krb5_err(context, 1, ret, "krb5_pac_get_types"); + + for (i = 0; i < len; i++) { + /* skip server_cksum, privsvr_cksum, and logon_name */ + if (list[i] == 6 || list[i] == 7 || list[i] == 10) + continue; + + ret = krb5_pac_get_buffer(context, pac, list[i], &data); + if (ret) + krb5_err(context, 1, ret, "krb5_pac_get_buffer"); + + if (list[i] == 1) { + if (type_1_length != data.length) + krb5_errx(context, 1, "type 1 have wrong length: %lu", + (unsigned long)data.length); + } else + krb5_errx(context, 1, "unknown type %lu", + (unsigned long)list[i]); + + ret = krb5_pac_add_buffer(context, pac2, list[i], &data); + if (ret) + krb5_err(context, 1, ret, "krb5_pac_add_buffer"); + krb5_data_free(&data); + } + free(list); + + ret = _krb5_pac_sign(context, pac2, authtime, p, + &member_keyblock, &kdc_keyblock, &data); + if (ret) + krb5_err(context, 1, ret, "_krb5_pac_sign 4"); + + krb5_pac_free(context, pac2); + + ret = krb5_pac_parse(context, data.data, data.length, &pac2); + if (ret) + krb5_err(context, 1, ret, "krb5_pac_parse 4"); + + ret = krb5_pac_verify(context, pac2, authtime, p, + &member_keyblock, &kdc_keyblock); + if (ret) + krb5_err(context, 1, ret, "krb5_pac_verify 4"); + + krb5_pac_free(context, pac2); + } + + krb5_pac_free(context, pac); + + /* + * Test empty free + */ + + ret = krb5_pac_init(context, &pac); + if (ret) + krb5_err(context, 1, ret, "krb5_pac_init"); + krb5_pac_free(context, pac); + + /* + * Test add remove buffer + */ + + ret = krb5_pac_init(context, &pac); + if (ret) + krb5_err(context, 1, ret, "krb5_pac_init"); + + { + const krb5_data cdata = { 2, "\x00\x01" } ; + + ret = krb5_pac_add_buffer(context, pac, 1, &cdata); + if (ret) + krb5_err(context, 1, ret, "krb5_pac_add_buffer"); + } + { + ret = krb5_pac_get_buffer(context, pac, 1, &data); + if (ret) + krb5_err(context, 1, ret, "krb5_pac_get_buffer"); + if (data.length != 2 || memcmp(data.data, "\x00\x01", 2) != 0) + krb5_errx(context, 1, "krb5_pac_get_buffer data not the same"); + krb5_data_free(&data); + } + + { + const krb5_data cdata = { 2, "\x02\x00" } ; + + ret = krb5_pac_add_buffer(context, pac, 2, &cdata); + if (ret) + krb5_err(context, 1, ret, "krb5_pac_add_buffer"); + } + { + ret = krb5_pac_get_buffer(context, pac, 1, &data); + if (ret) + krb5_err(context, 1, ret, "krb5_pac_get_buffer"); + if (data.length != 2 || memcmp(data.data, "\x00\x01", 2) != 0) + krb5_errx(context, 1, "krb5_pac_get_buffer data not the same"); + krb5_data_free(&data); + /* */ + ret = krb5_pac_get_buffer(context, pac, 2, &data); + if (ret) + krb5_err(context, 1, ret, "krb5_pac_get_buffer"); + if (data.length != 2 || memcmp(data.data, "\x02\x00", 2) != 0) + krb5_errx(context, 1, "krb5_pac_get_buffer data not the same"); + krb5_data_free(&data); + } + + ret = _krb5_pac_sign(context, pac, authtime, p, + &member_keyblock, &kdc_keyblock, &data); + if (ret) + krb5_err(context, 1, ret, "_krb5_pac_sign"); + + krb5_pac_free(context, pac); + + ret = krb5_pac_parse(context, data.data, data.length, &pac); + krb5_data_free(&data); + if (ret) + krb5_err(context, 1, ret, "krb5_pac_parse 3"); + + ret = krb5_pac_verify(context, pac, authtime, p, + &member_keyblock, &kdc_keyblock); + if (ret) + krb5_err(context, 1, ret, "krb5_pac_verify 3"); + + { + uint32_t *list; + size_t len; + + /* our two user buffer plus the three "system" buffers */ + ret = krb5_pac_get_types(context, pac, &len, &list); + if (ret) + krb5_err(context, 1, ret, "krb5_pac_get_types"); + if (len != 5) + krb5_errx(context, 1, "list wrong length"); + free(list); + } + + krb5_pac_free(context, pac); + + krb5_free_principal(context, p); + krb5_free_context(context); + + return 0; +} diff --git a/lib/krb5/test_pkinit_dh2key.c b/lib/krb5/test_pkinit_dh2key.c new file mode 100644 index 0000000..e23bef9 --- /dev/null +++ b/lib/krb5/test_pkinit_dh2key.c @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include "krb5_locl.h" +#include <err.h> +#include <getarg.h> + +RCSID("$Id: test_pkinit_dh2key.c 18809 2006-10-22 07:11:43Z lha $"); + +static void +test_dh2key(int i, + krb5_context context, + const heim_octet_string *dh, + const heim_octet_string *c_n, + const heim_octet_string *k_n, + krb5_enctype etype, + const heim_octet_string *result) +{ + krb5_error_code ret; + krb5_keyblock key; + + ret = _krb5_pk_octetstring2key(context, + etype, + dh->data, dh->length, + c_n, + k_n, + &key); + if (ret != 0) + krb5_err(context, 1, ret, "_krb5_pk_octetstring2key: %d", i); + + if (key.keyvalue.length != result->length || + memcmp(key.keyvalue.data, result->data, result->length) != 0) + krb5_errx(context, 1, "resulting key wrong: %d", i); + + krb5_free_keyblock_contents(context, &key); +} + + +struct { + krb5_enctype type; + krb5_data X; + krb5_data key; +} tests[] = { + /* 0 */ + { + ETYPE_AES256_CTS_HMAC_SHA1_96, + { + 256, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + }, + { + 32, + "\x5e\xe5\x0d\x67\x5c\x80\x9f\xe5\x9e\x4a\x77\x62\xc5\x4b\x65\x83" + "\x75\x47\xea\xfb\x15\x9b\xd8\xcd\xc7\x5f\xfc\xa5\x91\x1e\x4c\x41" + } + }, + /* 1 */ + { + ETYPE_AES256_CTS_HMAC_SHA1_96, + { + 128, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + }, + { + 32, + "\xac\xf7\x70\x7c\x08\x97\x3d\xdf\xdb\x27\xcd\x36\x14\x42\xcc\xfb" + "\xa3\x55\xc8\x88\x4c\xb4\x72\xf3\x7d\xa6\x36\xd0\x7d\x56\x78\x7e" + } + }, + /* 2 */ + { + ETYPE_AES256_CTS_HMAC_SHA1_96, + { + 128, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e" + "\x0f\x10\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d" + "\x0e\x0f\x10\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c" + "\x0d\x0e\x0f\x10\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b" + "\x0c\x0d\x0e\x0f\x10\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a" + "\x0b\x0c\x0d\x0e\x0f\x10\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09" + "\x0a\x0b\x0c\x0d\x0e\x0f\x10\x00\x01\x02\x03\x04\x05\x06\x07\x08" + }, + { + 32, + "\xc4\x42\xda\x58\x5f\xcb\x80\xe4\x3b\x47\x94\x6f\x25\x40\x93\xe3" + "\x73\x29\xd9\x90\x01\x38\x0d\xb7\x83\x71\xdb\x3a\xcf\x5c\x79\x7e" + } + }, + /* 3 */ + { + ETYPE_AES256_CTS_HMAC_SHA1_96, + { + 77, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" + "\x10\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e" + "\x0f\x10\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d" + "\x0e\x0f\x10\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c" + "\x0d\x0e\x0f\x10\x00\x01\x02\x03" + "\x04\x05\x06\x07\x08" + }, + { + 32, + "\x00\x53\x95\x3b\x84\xc8\x96\xf4\xeb\x38\x5c\x3f\x2e\x75\x1c\x4a" + "\x59\x0e\xd6\xff\xad\xca\x6f\xf6\x4f\x47\xeb\xeb\x8d\x78\x0f\xfc" + } + } +}; + + +static int version_flag = 0; +static int help_flag = 0; + +static struct getargs args[] = { + {"version", 0, arg_flag, &version_flag, + "print version", NULL }, + {"help", 0, arg_flag, &help_flag, + NULL, NULL } +}; + +static void +usage (int ret) +{ + arg_printusage (args, + sizeof(args)/sizeof(*args), + NULL, + ""); + exit (ret); +} + + +int +main(int argc, char **argv) +{ + krb5_context context; + krb5_error_code ret; + int i, optidx = 0; + + setprogname(argv[0]); + + if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) + usage(1); + + if (help_flag) + usage (0); + + if(version_flag){ + print_version(NULL); + exit(0); + } + + argc -= optidx; + argv += optidx; + + ret = krb5_init_context(&context); + if (ret) + errx (1, "krb5_init_context failed: %d", ret); + + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + test_dh2key(i, context, &tests[i].X, NULL, NULL, + tests[i].type, &tests[i].key); + } + + krb5_free_context(context); + + return 0; +} diff --git a/lib/krb5/test_plugin.c b/lib/krb5/test_plugin.c new file mode 100644 index 0000000..18e9fcd --- /dev/null +++ b/lib/krb5/test_plugin.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <krb5_locl.h> +RCSID("$Id: test_plugin.c 22024 2007-11-03 21:36:55Z lha $"); +#include "locate_plugin.h" + +static krb5_error_code +resolve_init(krb5_context context, void **ctx) +{ + *ctx = NULL; + return 0; +} + +static void +resolve_fini(void *ctx) +{ +} + +static krb5_error_code +resolve_lookup(void *ctx, + enum locate_service_type service, + const char *realm, + int domain, + int type, + int (*add)(void *,int,struct sockaddr *), + void *addctx) +{ + struct sockaddr_in s; + + memset(&s, 0, sizeof(s)); + +#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN + s.sin_len = sizeof(s); +#endif + s.sin_family = AF_INET; + s.sin_port = htons(88); + s.sin_addr.s_addr = htonl(0x7f000002); + + if (strcmp(realm, "NOTHERE.H5L.SE") == 0) + (*add)(addctx, type, (struct sockaddr *)&s); + + return 0; +} + + +krb5plugin_service_locate_ftable resolve = { + 0, + resolve_init, + resolve_fini, + resolve_lookup +}; + + +int +main(int argc, char **argv) +{ + krb5_error_code ret; + krb5_context context; + krb5_krbhst_handle handle; + char host[MAXHOSTNAMELEN]; + int found = 0; + + setprogname(argv[0]); + + ret = krb5_init_context(&context); + if (ret) + errx(1, "krb5_init_contex"); + + ret = krb5_plugin_register(context, PLUGIN_TYPE_DATA, "resolve", &resolve); + if (ret) + krb5_err(context, 1, ret, "krb5_plugin_register"); + + + ret = krb5_krbhst_init_flags(context, + "NOTHERE.H5L.SE", + KRB5_KRBHST_KDC, + 0, + &handle); + if (ret) + krb5_err(context, 1, ret, "krb5_krbhst_init_flags"); + + + while(krb5_krbhst_next_as_string(context, handle, host, sizeof(host)) == 0){ + found++; + if (strcmp(host, "127.0.0.2") != 0) + krb5_errx(context, 1, "wrong address: %s", host); + } + if (!found) + krb5_errx(context, 1, "failed to find host"); + + krb5_krbhst_free(context, handle); + + krb5_free_context(context); + return 0; +} diff --git a/lib/krb5/test_prf.c b/lib/krb5/test_prf.c new file mode 100644 index 0000000..94fb67d --- /dev/null +++ b/lib/krb5/test_prf.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: test_prf.c 20843 2007-06-03 14:23:20Z lha $"); + +#include <hex.h> +#include <err.h> + +/* + * key: string2key(aes256, "testkey", "testkey", default_params) + * input: unhex(1122334455667788) + * output: 58b594b8a61df6e9439b7baa991ff5c1 + * + * key: string2key(aes128, "testkey", "testkey", default_params) + * input: unhex(1122334455667788) + * output: ffa2f823aa7f83a8ce3c5fb730587129 + */ + +int +main(int argc, char **argv) +{ + krb5_context context; + krb5_error_code ret; + krb5_keyblock key; + krb5_crypto crypto; + size_t length; + krb5_data input, output, output2; + krb5_enctype etype = ETYPE_AES256_CTS_HMAC_SHA1_96; + + ret = krb5_init_context(&context); + if (ret) + errx(1, "krb5_init_context %d", ret); + + ret = krb5_generate_random_keyblock(context, etype, &key); + if (ret) + krb5_err(context, 1, ret, "krb5_generate_random_keyblock"); + + ret = krb5_crypto_prf_length(context, etype, &length); + if (ret) + krb5_err(context, 1, ret, "krb5_crypto_prf_length"); + + ret = krb5_crypto_init(context, &key, 0, &crypto); + if (ret) + krb5_err(context, 1, ret, "krb5_crypto_init"); + + input.data = rk_UNCONST("foo"); + input.length = 3; + + ret = krb5_crypto_prf(context, crypto, &input, &output); + if (ret) + krb5_err(context, 1, ret, "krb5_crypto_prf"); + + ret = krb5_crypto_prf(context, crypto, &input, &output2); + if (ret) + krb5_err(context, 1, ret, "krb5_crypto_prf"); + + if (krb5_data_cmp(&output, &output2) != 0) + krb5_errx(context, 1, "krb5_data_cmp"); + + krb5_data_free(&output); + krb5_data_free(&output2); + + krb5_crypto_destroy(context, crypto); + + krb5_free_keyblock_contents(context, &key); + + krb5_free_context(context); + + return 0; +} diff --git a/lib/krb5/test_princ.c b/lib/krb5/test_princ.c new file mode 100644 index 0000000..d1036c1 --- /dev/null +++ b/lib/krb5/test_princ.c @@ -0,0 +1,366 @@ +/* + * Copyright (c) 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include "krb5_locl.h" +#include <err.h> + +RCSID("$Id: test_princ.c 22071 2007-11-14 20:04:50Z lha $"); + +/* + * Check that a closed cc still keeps it data and that it's no longer + * there when it's destroyed. + */ + +static void +test_princ(krb5_context context) +{ + const char *princ = "lha@SU.SE"; + const char *princ_short = "lha"; + const char *noquote; + krb5_error_code ret; + char *princ_unparsed; + char *princ_reformed = NULL; + const char *realm; + + krb5_principal p, p2; + + ret = krb5_parse_name(context, princ, &p); + if (ret) + krb5_err(context, 1, ret, "krb5_parse_name"); + + ret = krb5_unparse_name(context, p, &princ_unparsed); + if (ret) + krb5_err(context, 1, ret, "krb5_parse_name"); + + if (strcmp(princ, princ_unparsed)) { + krb5_errx(context, 1, "%s != %s", princ, princ_unparsed); + } + + free(princ_unparsed); + + ret = krb5_unparse_name_flags(context, p, + KRB5_PRINCIPAL_UNPARSE_NO_REALM, + &princ_unparsed); + if (ret) + krb5_err(context, 1, ret, "krb5_parse_name"); + + if (strcmp(princ_short, princ_unparsed)) + krb5_errx(context, 1, "%s != %s", princ_short, princ_unparsed); + free(princ_unparsed); + + realm = krb5_principal_get_realm(context, p); + + asprintf(&princ_reformed, "%s@%s", princ_short, realm); + + ret = krb5_parse_name(context, princ_reformed, &p2); + free(princ_reformed); + if (ret) + krb5_err(context, 1, ret, "krb5_parse_name"); + + if (!krb5_principal_compare(context, p, p2)) { + krb5_errx(context, 1, "p != p2"); + } + + krb5_free_principal(context, p2); + + ret = krb5_set_default_realm(context, "SU.SE"); + if (ret) + krb5_err(context, 1, ret, "krb5_parse_name"); + + ret = krb5_unparse_name_flags(context, p, + KRB5_PRINCIPAL_UNPARSE_SHORT, + &princ_unparsed); + if (ret) + krb5_err(context, 1, ret, "krb5_parse_name"); + + if (strcmp(princ_short, princ_unparsed)) + krb5_errx(context, 1, "'%s' != '%s'", princ_short, princ_unparsed); + free(princ_unparsed); + + ret = krb5_parse_name(context, princ_short, &p2); + if (ret) + krb5_err(context, 1, ret, "krb5_parse_name"); + + if (!krb5_principal_compare(context, p, p2)) + krb5_errx(context, 1, "p != p2"); + krb5_free_principal(context, p2); + + ret = krb5_unparse_name(context, p, &princ_unparsed); + if (ret) + krb5_err(context, 1, ret, "krb5_parse_name"); + + if (strcmp(princ, princ_unparsed)) + krb5_errx(context, 1, "'%s' != '%s'", princ, princ_unparsed); + free(princ_unparsed); + + ret = krb5_set_default_realm(context, "SAMBA.ORG"); + if (ret) + krb5_err(context, 1, ret, "krb5_parse_name"); + + ret = krb5_parse_name(context, princ_short, &p2); + if (ret) + krb5_err(context, 1, ret, "krb5_parse_name"); + + if (krb5_principal_compare(context, p, p2)) + krb5_errx(context, 1, "p == p2"); + + if (!krb5_principal_compare_any_realm(context, p, p2)) + krb5_errx(context, 1, "(ignoring realms) p != p2"); + + ret = krb5_unparse_name(context, p2, &princ_unparsed); + if (ret) + krb5_err(context, 1, ret, "krb5_parse_name"); + + if (strcmp(princ, princ_unparsed) == 0) + krb5_errx(context, 1, "%s == %s", princ, princ_unparsed); + free(princ_unparsed); + + krb5_free_principal(context, p2); + + ret = krb5_parse_name(context, princ, &p2); + if (ret) + krb5_err(context, 1, ret, "krb5_parse_name"); + + if (!krb5_principal_compare(context, p, p2)) + krb5_errx(context, 1, "p != p2"); + + ret = krb5_unparse_name(context, p2, &princ_unparsed); + if (ret) + krb5_err(context, 1, ret, "krb5_parse_name"); + + if (strcmp(princ, princ_unparsed)) + krb5_errx(context, 1, "'%s' != '%s'", princ, princ_unparsed); + free(princ_unparsed); + + krb5_free_principal(context, p2); + + ret = krb5_unparse_name_flags(context, p, + KRB5_PRINCIPAL_UNPARSE_SHORT, + &princ_unparsed); + if (ret) + krb5_err(context, 1, ret, "krb5_unparse_name_short"); + + if (strcmp(princ, princ_unparsed) != 0) + krb5_errx(context, 1, "'%s' != '%s'", princ, princ_unparsed); + free(princ_unparsed); + + ret = krb5_unparse_name(context, p, &princ_unparsed); + if (ret) + krb5_err(context, 1, ret, "krb5_unparse_name_short"); + + if (strcmp(princ, princ_unparsed)) + krb5_errx(context, 1, "'%s' != '%s'", princ, princ_unparsed); + free(princ_unparsed); + + ret = krb5_parse_name_flags(context, princ, + KRB5_PRINCIPAL_PARSE_NO_REALM, + &p2); + if (!ret) + krb5_err(context, 1, ret, "Should have failed to parse %s a " + "short name", princ); + + ret = krb5_parse_name_flags(context, princ_short, + KRB5_PRINCIPAL_PARSE_NO_REALM, + &p2); + if (ret) + krb5_err(context, 1, ret, "krb5_parse_name"); + + ret = krb5_unparse_name_flags(context, p2, + KRB5_PRINCIPAL_UNPARSE_NO_REALM, + &princ_unparsed); + krb5_free_principal(context, p2); + if (ret) + krb5_err(context, 1, ret, "krb5_unparse_name_norealm"); + + if (strcmp(princ_short, princ_unparsed)) + krb5_errx(context, 1, "'%s' != '%s'", princ_short, princ_unparsed); + free(princ_unparsed); + + ret = krb5_parse_name_flags(context, princ_short, + KRB5_PRINCIPAL_PARSE_MUST_REALM, + &p2); + if (!ret) + krb5_err(context, 1, ret, "Should have failed to parse %s " + "because it lacked a realm", princ_short); + + ret = krb5_parse_name_flags(context, princ, + KRB5_PRINCIPAL_PARSE_MUST_REALM, + &p2); + if (ret) + krb5_err(context, 1, ret, "krb5_parse_name"); + + if (!krb5_principal_compare(context, p, p2)) + krb5_errx(context, 1, "p != p2"); + + ret = krb5_unparse_name_flags(context, p2, + KRB5_PRINCIPAL_UNPARSE_NO_REALM, + &princ_unparsed); + krb5_free_principal(context, p2); + if (ret) + krb5_err(context, 1, ret, "krb5_unparse_name_norealm"); + + if (strcmp(princ_short, princ_unparsed)) + krb5_errx(context, 1, "'%s' != '%s'", princ_short, princ_unparsed); + free(princ_unparsed); + + krb5_free_principal(context, p); + + /* test quoting */ + + princ = "test\\ principal@SU.SE"; + noquote = "test principal@SU.SE"; + + ret = krb5_parse_name_flags(context, princ, 0, &p); + if (ret) + krb5_err(context, 1, ret, "krb5_parse_name"); + + ret = krb5_unparse_name_flags(context, p, 0, &princ_unparsed); + if (ret) + krb5_err(context, 1, ret, "krb5_unparse_name_flags"); + + if (strcmp(princ, princ_unparsed)) + krb5_errx(context, 1, "q '%s' != '%s'", princ, princ_unparsed); + free(princ_unparsed); + + ret = krb5_unparse_name_flags(context, p, KRB5_PRINCIPAL_UNPARSE_DISPLAY, + &princ_unparsed); + if (ret) + krb5_err(context, 1, ret, "krb5_unparse_name_flags"); + + if (strcmp(noquote, princ_unparsed)) + krb5_errx(context, 1, "nq '%s' != '%s'", noquote, princ_unparsed); + free(princ_unparsed); + + krb5_free_principal(context, p); +} + +static void +test_enterprise(krb5_context context) +{ + krb5_error_code ret; + char *unparsed; + krb5_principal p; + + ret = krb5_set_default_realm(context, "SAMBA.ORG"); + if (ret) + krb5_err(context, 1, ret, "krb5_parse_name"); + + ret = krb5_parse_name_flags(context, "lha@su.se@WIN.SU.SE", + KRB5_PRINCIPAL_PARSE_ENTERPRISE, &p); + if (ret) + krb5_err(context, 1, ret, "krb5_parse_name_flags"); + + ret = krb5_unparse_name(context, p, &unparsed); + if (ret) + krb5_err(context, 1, ret, "krb5_unparse_name"); + + krb5_free_principal(context, p); + + if (strcmp(unparsed, "lha\\@su.se@WIN.SU.SE") != 0) + krb5_errx(context, 1, "enterprise name failed 1"); + free(unparsed); + + /* + * + */ + + ret = krb5_parse_name_flags(context, "lha\\@su.se@WIN.SU.SE", + KRB5_PRINCIPAL_PARSE_ENTERPRISE, &p); + if (ret) + krb5_err(context, 1, ret, "krb5_parse_name_flags"); + + ret = krb5_unparse_name(context, p, &unparsed); + if (ret) + krb5_err(context, 1, ret, "krb5_unparse_name"); + + krb5_free_principal(context, p); + if (strcmp(unparsed, "lha\\@su.se\\@WIN.SU.SE@SAMBA.ORG") != 0) + krb5_errx(context, 1, "enterprise name failed 2: %s", unparsed); + free(unparsed); + + /* + * + */ + + ret = krb5_parse_name_flags(context, "lha\\@su.se@WIN.SU.SE", 0, &p); + if (ret) + krb5_err(context, 1, ret, "krb5_parse_name_flags"); + + ret = krb5_unparse_name(context, p, &unparsed); + if (ret) + krb5_err(context, 1, ret, "krb5_unparse_name"); + + krb5_free_principal(context, p); + if (strcmp(unparsed, "lha\\@su.se@WIN.SU.SE") != 0) + krb5_errx(context, 1, "enterprise name failed 3"); + free(unparsed); + + /* + * + */ + + ret = krb5_parse_name_flags(context, "lha@su.se", + KRB5_PRINCIPAL_PARSE_ENTERPRISE, &p); + if (ret) + krb5_err(context, 1, ret, "krb5_parse_name_flags"); + + ret = krb5_unparse_name(context, p, &unparsed); + if (ret) + krb5_err(context, 1, ret, "krb5_unparse_name"); + + krb5_free_principal(context, p); + if (strcmp(unparsed, "lha\\@su.se@SAMBA.ORG") != 0) + krb5_errx(context, 1, "enterprise name failed 2: %s", unparsed); + free(unparsed); +} + + +int +main(int argc, char **argv) +{ + krb5_context context; + krb5_error_code ret; + + setprogname(argv[0]); + + ret = krb5_init_context(&context); + if (ret) + errx (1, "krb5_init_context failed: %d", ret); + + test_princ(context); + + test_enterprise(context); + + krb5_free_context(context); + + return 0; +} diff --git a/lib/krb5/test_renew.c b/lib/krb5/test_renew.c new file mode 100644 index 0000000..5fa2de1 --- /dev/null +++ b/lib/krb5/test_renew.c @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "krb5_locl.h" +#include <err.h> +#include <getarg.h> + +RCSID("$Id$"); + + +static int version_flag = 0; +static int help_flag = 0; + +static struct getargs args[] = { + {"version", 0, arg_flag, &version_flag, + "print version", NULL }, + {"help", 0, arg_flag, &help_flag, + NULL, NULL } +}; + +static void +usage (int ret) +{ + arg_printusage (args, + sizeof(args)/sizeof(*args), + NULL, + "[principal]"); + exit (ret); +} + +int +main(int argc, char **argv) +{ + krb5_principal client; + krb5_context context; + const char *in_tkt_service = NULL; + krb5_ccache id; + krb5_error_code ret; + krb5_creds out;; + int optidx = 0; + + setprogname(argv[0]); + + if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) + usage(1); + + if (help_flag) + usage (0); + + if(version_flag){ + print_version(NULL); + exit(0); + } + + argc -= optidx; + argv += optidx; + + if (argc > 0) + in_tkt_service = argv[0]; + + memset(&out, 0, sizeof(out)); + + ret = krb5_init_context(&context); + if (ret) + krb5_err(context, 1, ret, "krb5_init_context"); + + ret = krb5_cc_default(context, &id); + if (ret) + krb5_err(context, 1, ret, "krb5_cc_default"); + + ret = krb5_cc_get_principal(context, id, &client); + if (ret) + krb5_err(context, 1, ret, "krb5_cc_default"); + + ret = krb5_get_renewed_creds(context, + &out, + client, + id, + in_tkt_service); + + if(ret) + krb5_err(context, 1, ret, "krb5_get_kdc_cred"); + + if (krb5_principal_compare(context, out.client, client) != TRUE) + krb5_errx(context, 1, "return principal is not as expected"); + + krb5_free_cred_contents(context, &out); + + krb5_free_context(context); + + return 0; +} diff --git a/lib/krb5/test_store.c b/lib/krb5/test_store.c new file mode 100644 index 0000000..2ce6c8d --- /dev/null +++ b/lib/krb5/test_store.c @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include "krb5_locl.h" +#include <getarg.h> + +RCSID("$Id: test_store.c 20192 2007-02-05 23:21:03Z lha $"); + +static void +test_int8(krb5_context context, krb5_storage *sp) +{ + krb5_error_code ret; + int i; + int8_t val[] = { + 0, 1, -1, 128, -127 + }, v; + + for (i = 0; i < sizeof(val[0])/sizeof(val); i++) { + + ret = krb5_store_int8(sp, val[i]); + if (ret) + krb5_err(context, 1, ret, "krb5_store_int8"); + krb5_storage_seek(sp, 0, SEEK_SET); + ret = krb5_ret_int8(sp, &v); + if (ret) + krb5_err(context, 1, ret, "krb5_ret_int8"); + if (v != val[i]) + krb5_errx(context, 1, "store and ret mismatch"); + } +} + +static void +test_int16(krb5_context context, krb5_storage *sp) +{ + krb5_error_code ret; + int i; + int16_t val[] = { + 0, 1, -1, 32768, -32767 + }, v; + + for (i = 0; i < sizeof(val[0])/sizeof(val); i++) { + + ret = krb5_store_int16(sp, val[i]); + if (ret) + krb5_err(context, 1, ret, "krb5_store_int16"); + krb5_storage_seek(sp, 0, SEEK_SET); + ret = krb5_ret_int16(sp, &v); + if (ret) + krb5_err(context, 1, ret, "krb5_ret_int16"); + if (v != val[i]) + krb5_errx(context, 1, "store and ret mismatch"); + } +} + +static void +test_int32(krb5_context context, krb5_storage *sp) +{ + krb5_error_code ret; + int i; + int32_t val[] = { + 0, 1, -1, 2147483647, -2147483646 + }, v; + + for (i = 0; i < sizeof(val[0])/sizeof(val); i++) { + + ret = krb5_store_int32(sp, val[i]); + if (ret) + krb5_err(context, 1, ret, "krb5_store_int32"); + krb5_storage_seek(sp, 0, SEEK_SET); + ret = krb5_ret_int32(sp, &v); + if (ret) + krb5_err(context, 1, ret, "krb5_ret_int32"); + if (v != val[i]) + krb5_errx(context, 1, "store and ret mismatch"); + } +} + +static void +test_uint8(krb5_context context, krb5_storage *sp) +{ + krb5_error_code ret; + int i; + uint8_t val[] = { + 0, 1, 255 + }, v; + + for (i = 0; i < sizeof(val[0])/sizeof(val); i++) { + + ret = krb5_store_uint8(sp, val[i]); + if (ret) + krb5_err(context, 1, ret, "krb5_store_uint8"); + krb5_storage_seek(sp, 0, SEEK_SET); + ret = krb5_ret_uint8(sp, &v); + if (ret) + krb5_err(context, 1, ret, "krb5_ret_uint8"); + if (v != val[i]) + krb5_errx(context, 1, "store and ret mismatch"); + } +} + +static void +test_uint16(krb5_context context, krb5_storage *sp) +{ + krb5_error_code ret; + int i; + uint16_t val[] = { + 0, 1, 65535 + }, v; + + for (i = 0; i < sizeof(val[0])/sizeof(val); i++) { + + ret = krb5_store_uint16(sp, val[i]); + if (ret) + krb5_err(context, 1, ret, "krb5_store_uint16"); + krb5_storage_seek(sp, 0, SEEK_SET); + ret = krb5_ret_uint16(sp, &v); + if (ret) + krb5_err(context, 1, ret, "krb5_ret_uint16"); + if (v != val[i]) + krb5_errx(context, 1, "store and ret mismatch"); + } +} + +static void +test_uint32(krb5_context context, krb5_storage *sp) +{ + krb5_error_code ret; + int i; + uint32_t val[] = { + 0, 1, 4294967295UL + }, v; + + for (i = 0; i < sizeof(val[0])/sizeof(val); i++) { + + ret = krb5_store_uint32(sp, val[i]); + if (ret) + krb5_err(context, 1, ret, "krb5_store_uint32"); + krb5_storage_seek(sp, 0, SEEK_SET); + ret = krb5_ret_uint32(sp, &v); + if (ret) + krb5_err(context, 1, ret, "krb5_ret_uint32"); + if (v != val[i]) + krb5_errx(context, 1, "store and ret mismatch"); + } +} + + +static void +test_storage(krb5_context context) +{ + krb5_storage *sp; + + sp = krb5_storage_emem(); + if (sp == NULL) + krb5_errx(context, 1, "krb5_storage_emem: no mem"); + + test_int8(context, sp); + test_int16(context, sp); + test_int32(context, sp); + test_uint8(context, sp); + test_uint16(context, sp); + test_uint32(context, sp); + + krb5_storage_free(sp); +} + +/* + * + */ + +static int version_flag = 0; +static int help_flag = 0; + +static struct getargs args[] = { + {"version", 0, arg_flag, &version_flag, + "print version", NULL }, + {"help", 0, arg_flag, &help_flag, + NULL, NULL } +}; + +static void +usage (int ret) +{ + arg_printusage (args, + sizeof(args)/sizeof(*args), + NULL, + ""); + exit (ret); +} + +int +main(int argc, char **argv) +{ + krb5_context context; + krb5_error_code ret; + int optidx = 0; + + setprogname(argv[0]); + + if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) + usage(1); + + if (help_flag) + usage (0); + + if(version_flag){ + print_version(NULL); + exit(0); + } + + argc -= optidx; + argv += optidx; + + ret = krb5_init_context (&context); + if (ret) + errx (1, "krb5_init_context failed: %d", ret); + + test_storage(context); + + krb5_free_context(context); + + return 0; +} diff --git a/lib/krb5/test_time.c b/lib/krb5/test_time.c new file mode 100644 index 0000000..02a0204 --- /dev/null +++ b/lib/krb5/test_time.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "krb5_locl.h" +#include <err.h> + +RCSID("$Id: test_time.c 18809 2006-10-22 07:11:43Z lha $"); + +static void +check_set_time(krb5_context context) +{ + krb5_error_code ret; + krb5_timestamp sec; + int32_t usec; + struct timeval tv; + int diff = 10; + int diff2; + + gettimeofday(&tv, NULL); + + ret = krb5_set_real_time(context, tv.tv_sec + diff, tv.tv_usec); + if (ret) + krb5_err(context, 1, ret, "krb5_us_timeofday"); + + ret = krb5_us_timeofday(context, &sec, &usec); + if (ret) + krb5_err(context, 1, ret, "krb5_us_timeofday"); + + diff2 = abs(sec - tv.tv_sec); + + if (diff2 < 9 || diff > 11) + krb5_errx(context, 1, "set time error: diff: %d", + abs(sec - tv.tv_sec)); +} + + + +int +main(int argc, char **argv) +{ + krb5_context context; + krb5_error_code ret; + + ret = krb5_init_context(&context); + if (ret) + errx(1, "krb5_init_context %d", ret); + + check_set_time(context); + check_set_time(context); + check_set_time(context); + check_set_time(context); + check_set_time(context); + + krb5_free_context(context); + + return 0; +} diff --git a/lib/krb5/ticket.c b/lib/krb5/ticket.c new file mode 100644 index 0000000..7eb4d32 --- /dev/null +++ b/lib/krb5/ticket.c @@ -0,0 +1,272 @@ +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: ticket.c 19544 2006-12-28 20:49:18Z lha $"); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_free_ticket(krb5_context context, + krb5_ticket *ticket) +{ + free_EncTicketPart(&ticket->ticket); + krb5_free_principal(context, ticket->client); + krb5_free_principal(context, ticket->server); + free(ticket); + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_ticket(krb5_context context, + const krb5_ticket *from, + krb5_ticket **to) +{ + krb5_error_code ret; + krb5_ticket *tmp; + + *to = NULL; + tmp = malloc(sizeof(*tmp)); + if(tmp == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + if((ret = copy_EncTicketPart(&from->ticket, &tmp->ticket))){ + free(tmp); + return ret; + } + ret = krb5_copy_principal(context, from->client, &tmp->client); + if(ret){ + free_EncTicketPart(&tmp->ticket); + free(tmp); + return ret; + } + ret = krb5_copy_principal(context, from->server, &tmp->server); + if(ret){ + krb5_free_principal(context, tmp->client); + free_EncTicketPart(&tmp->ticket); + free(tmp); + return ret; + } + *to = tmp; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ticket_get_client(krb5_context context, + const krb5_ticket *ticket, + krb5_principal *client) +{ + return krb5_copy_principal(context, ticket->client, client); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ticket_get_server(krb5_context context, + const krb5_ticket *ticket, + krb5_principal *server) +{ + return krb5_copy_principal(context, ticket->server, server); +} + +time_t KRB5_LIB_FUNCTION +krb5_ticket_get_endtime(krb5_context context, + const krb5_ticket *ticket) +{ + return ticket->ticket.endtime; +} + +static int +find_type_in_ad(krb5_context context, + int type, + krb5_data *data, + krb5_boolean *found, + krb5_boolean failp, + krb5_keyblock *sessionkey, + const AuthorizationData *ad, + int level) +{ + krb5_error_code ret = 0; + int i; + + if (level > 9) { + krb5_set_error_string(context, "Authorization data nested deeper " + "then %d levels, stop searching", level); + ret = ENOENT; /* XXX */ + goto out; + } + + /* + * Only copy out the element the first time we get to it, we need + * to run over the whole authorization data fields to check if + * there are any container clases we need to care about. + */ + for (i = 0; i < ad->len; i++) { + if (!*found && ad->val[i].ad_type == type) { + ret = der_copy_octet_string(&ad->val[i].ad_data, data); + if (ret) { + krb5_set_error_string(context, "malloc - out of memory"); + goto out; + } + *found = TRUE; + continue; + } + switch (ad->val[i].ad_type) { + case KRB5_AUTHDATA_IF_RELEVANT: { + AuthorizationData child; + ret = decode_AuthorizationData(ad->val[i].ad_data.data, + ad->val[i].ad_data.length, + &child, + NULL); + if (ret) { + krb5_set_error_string(context, "Failed to decode " + "IF_RELEVANT with %d", ret); + goto out; + } + ret = find_type_in_ad(context, type, data, found, FALSE, + sessionkey, &child, level + 1); + free_AuthorizationData(&child); + if (ret) + goto out; + break; + } +#if 0 /* XXX test */ + case KRB5_AUTHDATA_KDC_ISSUED: { + AD_KDCIssued child; + + ret = decode_AD_KDCIssued(ad->val[i].ad_data.data, + ad->val[i].ad_data.length, + &child, + NULL); + if (ret) { + krb5_set_error_string(context, "Failed to decode " + "AD_KDCIssued with %d", ret); + goto out; + } + if (failp) { + krb5_boolean valid; + krb5_data buf; + size_t len; + + ASN1_MALLOC_ENCODE(AuthorizationData, buf.data, buf.length, + &child.elements, &len, ret); + if (ret) { + free_AD_KDCIssued(&child); + krb5_clear_error_string(context); + goto out; + } + if(buf.length != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + + ret = krb5_c_verify_checksum(context, sessionkey, 19, &buf, + &child.ad_checksum, &valid); + krb5_data_free(&buf); + if (ret) { + free_AD_KDCIssued(&child); + goto out; + } + if (!valid) { + krb5_clear_error_string(context); + ret = ENOENT; + free_AD_KDCIssued(&child); + goto out; + } + } + ret = find_type_in_ad(context, type, data, found, failp, sessionkey, + &child.elements, level + 1); + free_AD_KDCIssued(&child); + if (ret) + goto out; + break; + } +#endif + case KRB5_AUTHDATA_AND_OR: + if (!failp) + break; + krb5_set_error_string(context, "Authorization data contains " + "AND-OR element that is unknown to the " + "application"); + ret = ENOENT; /* XXX */ + goto out; + default: + if (!failp) + break; + krb5_set_error_string(context, "Authorization data contains " + "unknown type (%d) ", ad->val[i].ad_type); + ret = ENOENT; /* XXX */ + goto out; + } + } +out: + if (ret) { + if (*found) { + krb5_data_free(data); + *found = 0; + } + } + return ret; +} + +/* + * Extract the authorization data type of `type' from the + * 'ticket'. Store the field in `data'. This function is to use for + * kerberos applications. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ticket_get_authorization_data_type(krb5_context context, + krb5_ticket *ticket, + int type, + krb5_data *data) +{ + AuthorizationData *ad; + krb5_error_code ret; + krb5_boolean found = FALSE; + + krb5_data_zero(data); + + ad = ticket->ticket.authorization_data; + if (ticket->ticket.authorization_data == NULL) { + krb5_set_error_string(context, "Ticket have not authorization data"); + return ENOENT; /* XXX */ + } + + ret = find_type_in_ad(context, type, data, &found, TRUE, + &ticket->ticket.key, ad, 0); + if (ret) + return ret; + if (!found) { + krb5_set_error_string(context, "Ticket have not authorization " + "data of type %d", type); + return ENOENT; /* XXX */ + } + return 0; +} diff --git a/lib/krb5/time.c b/lib/krb5/time.c new file mode 100644 index 0000000..4cd992d --- /dev/null +++ b/lib/krb5/time.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 1997-2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: time.c 14308 2004-10-13 17:57:11Z lha $"); + +/* + * Set the absolute time that the caller knows the kdc has so the + * kerberos library can calculate the relative diffrence beteen the + * KDC time and local system time. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_real_time (krb5_context context, + krb5_timestamp sec, + int32_t usec) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + + context->kdc_sec_offset = sec - tv.tv_sec; + context->kdc_usec_offset = usec - tv.tv_usec; + + if (context->kdc_usec_offset < 0) { + context->kdc_sec_offset--; + context->kdc_usec_offset += 1000000; + } + return 0; +} + +/* + * return ``corrected'' time in `timeret'. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_timeofday (krb5_context context, + krb5_timestamp *timeret) +{ + *timeret = time(NULL) + context->kdc_sec_offset; + return 0; +} + +/* + * like gettimeofday but with time correction to the KDC + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_us_timeofday (krb5_context context, + krb5_timestamp *sec, + int32_t *usec) +{ + struct timeval tv; + + gettimeofday (&tv, NULL); + + *sec = tv.tv_sec + context->kdc_sec_offset; + *usec = tv.tv_usec; /* XXX */ + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_format_time(krb5_context context, time_t t, + char *s, size_t len, krb5_boolean include_time) +{ + struct tm *tm; + if(context->log_utc) + tm = gmtime (&t); + else + tm = localtime(&t); + if(tm == NULL || + strftime(s, len, include_time ? context->time_fmt : context->date_fmt, tm) == 0) + snprintf(s, len, "%ld", (long)t); + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_deltat(const char *string, krb5_deltat *deltat) +{ + if((*deltat = parse_time(string, "s")) == -1) + return KRB5_DELTAT_BADFORMAT; + return 0; +} diff --git a/lib/krb5/transited.c b/lib/krb5/transited.c new file mode 100644 index 0000000..9b67ecc --- /dev/null +++ b/lib/krb5/transited.c @@ -0,0 +1,503 @@ +/* + * Copyright (c) 1997 - 2001, 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: transited.c 21745 2007-07-31 16:11:25Z lha $"); + +/* this is an attempt at one of the most horrible `compression' + schemes that has ever been invented; it's so amazingly brain-dead + that words can not describe it, and all this just to save a few + silly bytes */ + +struct tr_realm { + char *realm; + unsigned leading_space:1; + unsigned leading_slash:1; + unsigned trailing_dot:1; + struct tr_realm *next; +}; + +static void +free_realms(struct tr_realm *r) +{ + struct tr_realm *p; + while(r){ + p = r; + r = r->next; + free(p->realm); + free(p); + } +} + +static int +make_path(krb5_context context, struct tr_realm *r, + const char *from, const char *to) +{ + const char *p; + struct tr_realm *path = r->next; + struct tr_realm *tmp; + + if(strlen(from) < strlen(to)){ + const char *str; + str = from; + from = to; + to = str; + } + + if(strcmp(from + strlen(from) - strlen(to), to) == 0){ + p = from; + while(1){ + p = strchr(p, '.'); + if(p == NULL) { + krb5_clear_error_string (context); + return KRB5KDC_ERR_POLICY; + } + p++; + if(strcmp(p, to) == 0) + break; + tmp = calloc(1, sizeof(*tmp)); + if(tmp == NULL){ + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + tmp->next = path; + path = tmp; + path->realm = strdup(p); + if(path->realm == NULL){ + r->next = path; /* XXX */ + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM;; + } + } + }else if(strncmp(from, to, strlen(to)) == 0){ + p = from + strlen(from); + while(1){ + while(p >= from && *p != '/') p--; + if(p == from) { + r->next = path; /* XXX */ + return KRB5KDC_ERR_POLICY; + } + if(strncmp(to, from, p - from) == 0) + break; + tmp = calloc(1, sizeof(*tmp)); + if(tmp == NULL){ + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + tmp->next = path; + path = tmp; + path->realm = malloc(p - from + 1); + if(path->realm == NULL){ + r->next = path; /* XXX */ + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + memcpy(path->realm, from, p - from); + path->realm[p - from] = '\0'; + p--; + } + } else { + krb5_clear_error_string (context); + return KRB5KDC_ERR_POLICY; + } + r->next = path; + + return 0; +} + +static int +make_paths(krb5_context context, + struct tr_realm *realms, const char *client_realm, + const char *server_realm) +{ + struct tr_realm *r; + int ret; + const char *prev_realm = client_realm; + const char *next_realm = NULL; + for(r = realms; r; r = r->next){ + /* it *might* be that you can have more than one empty + component in a row, at least that's how I interpret the + "," exception in 1510 */ + if(r->realm[0] == '\0'){ + while(r->next && r->next->realm[0] == '\0') + r = r->next; + if(r->next) + next_realm = r->next->realm; + else + next_realm = server_realm; + ret = make_path(context, r, prev_realm, next_realm); + if(ret){ + free_realms(realms); + return ret; + } + } + prev_realm = r->realm; + } + return 0; +} + +static int +expand_realms(krb5_context context, + struct tr_realm *realms, const char *client_realm) +{ + struct tr_realm *r; + const char *prev_realm = NULL; + for(r = realms; r; r = r->next){ + if(r->trailing_dot){ + char *tmp; + size_t len; + + if(prev_realm == NULL) + prev_realm = client_realm; + + len = strlen(r->realm) + strlen(prev_realm) + 1; + + tmp = realloc(r->realm, len); + if(tmp == NULL){ + free_realms(realms); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + r->realm = tmp; + strlcat(r->realm, prev_realm, len); + }else if(r->leading_slash && !r->leading_space && prev_realm){ + /* yet another exception: if you use x500-names, the + leading realm doesn't have to be "quoted" with a space */ + char *tmp; + size_t len = strlen(r->realm) + strlen(prev_realm) + 1; + + tmp = malloc(len); + if(tmp == NULL){ + free_realms(realms); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + strlcpy(tmp, prev_realm, len); + strlcat(tmp, r->realm, len); + free(r->realm); + r->realm = tmp; + } + prev_realm = r->realm; + } + return 0; +} + +static struct tr_realm * +make_realm(char *realm) +{ + struct tr_realm *r; + char *p, *q; + int quote = 0; + r = calloc(1, sizeof(*r)); + if(r == NULL){ + free(realm); + return NULL; + } + r->realm = realm; + for(p = q = r->realm; *p; p++){ + if(p == r->realm && *p == ' '){ + r->leading_space = 1; + continue; + } + if(q == r->realm && *p == '/') + r->leading_slash = 1; + if(quote){ + *q++ = *p; + quote = 0; + continue; + } + if(*p == '\\'){ + quote = 1; + continue; + } + if(p[0] == '.' && p[1] == '\0') + r->trailing_dot = 1; + *q++ = *p; + } + *q = '\0'; + return r; +} + +static struct tr_realm* +append_realm(struct tr_realm *head, struct tr_realm *r) +{ + struct tr_realm *p; + if(head == NULL){ + r->next = NULL; + return r; + } + p = head; + while(p->next) p = p->next; + p->next = r; + return head; +} + +static int +decode_realms(krb5_context context, + const char *tr, int length, struct tr_realm **realms) +{ + struct tr_realm *r = NULL; + + char *tmp; + int quote = 0; + const char *start = tr; + int i; + + for(i = 0; i < length; i++){ + if(quote){ + quote = 0; + continue; + } + if(tr[i] == '\\'){ + quote = 1; + continue; + } + if(tr[i] == ','){ + tmp = malloc(tr + i - start + 1); + if(tmp == NULL){ + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + memcpy(tmp, start, tr + i - start); + tmp[tr + i - start] = '\0'; + r = make_realm(tmp); + if(r == NULL){ + free_realms(*realms); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + *realms = append_realm(*realms, r); + start = tr + i + 1; + } + } + tmp = malloc(tr + i - start + 1); + if(tmp == NULL){ + free(*realms); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + memcpy(tmp, start, tr + i - start); + tmp[tr + i - start] = '\0'; + r = make_realm(tmp); + if(r == NULL){ + free_realms(*realms); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + *realms = append_realm(*realms, r); + + return 0; +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_domain_x500_decode(krb5_context context, + krb5_data tr, char ***realms, int *num_realms, + const char *client_realm, const char *server_realm) +{ + struct tr_realm *r = NULL; + struct tr_realm *p, **q; + int ret; + + if(tr.length == 0) { + *realms = NULL; + *num_realms = 0; + return 0; + } + + /* split string in components */ + ret = decode_realms(context, tr.data, tr.length, &r); + if(ret) + return ret; + + /* apply prefix rule */ + ret = expand_realms(context, r, client_realm); + if(ret) + return ret; + + ret = make_paths(context, r, client_realm, server_realm); + if(ret) + return ret; + + /* remove empty components and count realms */ + q = &r; + *num_realms = 0; + for(p = r; p; ){ + if(p->realm[0] == '\0'){ + free(p->realm); + *q = p->next; + free(p); + p = *q; + }else{ + q = &p->next; + p = p->next; + (*num_realms)++; + } + } + if (*num_realms < 0 || *num_realms + 1 > UINT_MAX/sizeof(**realms)) + return ERANGE; + + { + char **R; + R = malloc((*num_realms + 1) * sizeof(*R)); + if (R == NULL) + return ENOMEM; + *realms = R; + while(r){ + *R++ = r->realm; + p = r->next; + free(r); + r = p; + } + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_domain_x500_encode(char **realms, int num_realms, krb5_data *encoding) +{ + char *s = NULL; + int len = 0; + int i; + krb5_data_zero(encoding); + if (num_realms == 0) + return 0; + for(i = 0; i < num_realms; i++){ + len += strlen(realms[i]); + if(realms[i][0] == '/') + len++; + } + len += num_realms - 1; + s = malloc(len + 1); + if (s == NULL) + return ENOMEM; + *s = '\0'; + for(i = 0; i < num_realms; i++){ + if(i && i < num_realms - 1) + strlcat(s, ",", len + 1); + if(realms[i][0] == '/') + strlcat(s, " ", len + 1); + strlcat(s, realms[i], len + 1); + } + encoding->data = s; + encoding->length = strlen(s); + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_check_transited(krb5_context context, + krb5_const_realm client_realm, + krb5_const_realm server_realm, + krb5_realm *realms, + int num_realms, + int *bad_realm) +{ + char **tr_realms; + char **p; + int i; + + if(num_realms == 0) + return 0; + + tr_realms = krb5_config_get_strings(context, NULL, + "capaths", + client_realm, + server_realm, + NULL); + for(i = 0; i < num_realms; i++) { + for(p = tr_realms; p && *p; p++) { + if(strcmp(*p, realms[i]) == 0) + break; + } + if(p == NULL || *p == NULL) { + krb5_config_free_strings(tr_realms); + krb5_set_error_string (context, "no transit through realm %s", + realms[i]); + if(bad_realm) + *bad_realm = i; + return KRB5KRB_AP_ERR_ILL_CR_TKT; + } + } + krb5_config_free_strings(tr_realms); + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_check_transited_realms(krb5_context context, + const char *const *realms, + int num_realms, + int *bad_realm) +{ + int i; + int ret = 0; + char **bad_realms = krb5_config_get_strings(context, NULL, + "libdefaults", + "transited_realms_reject", + NULL); + if(bad_realms == NULL) + return 0; + + for(i = 0; i < num_realms; i++) { + char **p; + for(p = bad_realms; *p; p++) + if(strcmp(*p, realms[i]) == 0) { + krb5_set_error_string (context, "no transit through realm %s", + *p); + ret = KRB5KRB_AP_ERR_ILL_CR_TKT; + if(bad_realm) + *bad_realm = i; + break; + } + } + krb5_config_free_strings(bad_realms); + return ret; +} + +#if 0 +int +main(int argc, char **argv) +{ + krb5_data x; + char **r; + int num, i; + x.data = argv[1]; + x.length = strlen(x.data); + if(domain_expand(x, &r, &num, argv[2], argv[3])) + exit(1); + for(i = 0; i < num; i++) + printf("%s\n", r[i]); + return 0; +} +#endif + diff --git a/lib/krb5/v4_glue.c b/lib/krb5/v4_glue.c new file mode 100644 index 0000000..37b1e35 --- /dev/null +++ b/lib/krb5/v4_glue.c @@ -0,0 +1,939 @@ +/* + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" +RCSID("$Id: v4_glue.c 22071 2007-11-14 20:04:50Z lha $"); + +#include "krb5-v4compat.h" + +/* + * + */ + +#define RCHECK(r,func,label) \ + do { (r) = func ; if (r) goto label; } while(0); + + +/* include this here, to avoid dependencies on libkrb */ + +static const int _tkt_lifetimes[TKTLIFENUMFIXED] = { + 38400, 41055, 43894, 46929, 50174, 53643, 57352, 61318, + 65558, 70091, 74937, 80119, 85658, 91581, 97914, 104684, + 111922, 119661, 127935, 136781, 146239, 156350, 167161, 178720, + 191077, 204289, 218415, 233517, 249664, 266926, 285383, 305116, + 326213, 348769, 372885, 398668, 426234, 455705, 487215, 520904, + 556921, 595430, 636601, 680618, 727680, 777995, 831789, 889303, + 950794, 1016537, 1086825, 1161973, 1242318, 1328218, 1420057, 1518247, + 1623226, 1735464, 1855462, 1983758, 2120925, 2267576, 2424367, 2592000 +}; + +int KRB5_LIB_FUNCTION +_krb5_krb_time_to_life(time_t start, time_t end) +{ + int i; + time_t life = end - start; + + if (life > MAXTKTLIFETIME || life <= 0) + return 0; +#if 0 + if (krb_no_long_lifetimes) + return (life + 5*60 - 1)/(5*60); +#endif + + if (end >= NEVERDATE) + return TKTLIFENOEXPIRE; + if (life < _tkt_lifetimes[0]) + return (life + 5*60 - 1)/(5*60); + for (i=0; i<TKTLIFENUMFIXED; i++) + if (life <= _tkt_lifetimes[i]) + return i + TKTLIFEMINFIXED; + return 0; + +} + +time_t KRB5_LIB_FUNCTION +_krb5_krb_life_to_time(int start, int life_) +{ + unsigned char life = (unsigned char) life_; + +#if 0 + if (krb_no_long_lifetimes) + return start + life*5*60; +#endif + + if (life == TKTLIFENOEXPIRE) + return NEVERDATE; + if (life < TKTLIFEMINFIXED) + return start + life*5*60; + if (life > TKTLIFEMAXFIXED) + return start + MAXTKTLIFETIME; + return start + _tkt_lifetimes[life - TKTLIFEMINFIXED]; +} + +/* + * Get the name of the krb4 credentials cache, will use `tkfile' as + * the name if that is passed in. `cc' must be free()ed by caller, + */ + +static krb5_error_code +get_krb4_cc_name(const char *tkfile, char **cc) +{ + + *cc = NULL; + if(tkfile == NULL) { + char *path; + if(!issuid()) { + path = getenv("KRBTKFILE"); + if (path) + *cc = strdup(path); + } + if(*cc == NULL) + if (asprintf(cc, "%s%u", TKT_ROOT, (unsigned)getuid()) < 0) + return errno; + } else { + *cc = strdup(tkfile); + if (*cc == NULL) + return ENOMEM; + } + return 0; +} + +/* + * Write a Kerberos 4 ticket file + */ + +#define KRB5_TF_LCK_RETRY_COUNT 50 +#define KRB5_TF_LCK_RETRY 1 + +static krb5_error_code +write_v4_cc(krb5_context context, const char *tkfile, + krb5_storage *sp, int append) +{ + krb5_error_code ret; + struct stat sb; + krb5_data data; + char *path; + int fd, i; + + ret = get_krb4_cc_name(tkfile, &path); + if (ret) { + krb5_set_error_string(context, + "krb5_krb_tf_setup: failed getting " + "the krb4 credentials cache name"); + return ret; + } + + fd = open(path, O_WRONLY|O_CREAT, 0600); + if (fd < 0) { + ret = errno; + krb5_set_error_string(context, + "krb5_krb_tf_setup: error opening file %s", + path); + free(path); + return ret; + } + + if (fstat(fd, &sb) != 0 || !S_ISREG(sb.st_mode)) { + krb5_set_error_string(context, + "krb5_krb_tf_setup: tktfile %s is not a file", + path); + free(path); + close(fd); + return KRB5_FCC_PERM; + } + + for (i = 0; i < KRB5_TF_LCK_RETRY_COUNT; i++) { + if (flock(fd, LOCK_EX | LOCK_NB) < 0) { + sleep(KRB5_TF_LCK_RETRY); + } else + break; + } + if (i == KRB5_TF_LCK_RETRY_COUNT) { + krb5_set_error_string(context, + "krb5_krb_tf_setup: failed to lock %s", + path); + free(path); + close(fd); + return KRB5_FCC_PERM; + } + + if (!append) { + ret = ftruncate(fd, 0); + if (ret < 0) { + flock(fd, LOCK_UN); + krb5_set_error_string(context, + "krb5_krb_tf_setup: failed to truncate %s", + path); + free(path); + close(fd); + return KRB5_FCC_PERM; + } + } + ret = lseek(fd, 0L, SEEK_END); + if (ret < 0) { + ret = errno; + flock(fd, LOCK_UN); + free(path); + close(fd); + return ret; + } + + krb5_storage_to_data(sp, &data); + + ret = write(fd, data.data, data.length); + if (ret != data.length) + ret = KRB5_CC_IO; + + krb5_free_data_contents(context, &data); + + flock(fd, LOCK_UN); + free(path); + close(fd); + + return 0; +} + +/* + * + */ + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_krb_tf_setup(krb5_context context, + struct credentials *v4creds, + const char *tkfile, + int append) +{ + krb5_error_code ret; + krb5_storage *sp; + + sp = krb5_storage_emem(); + if (sp == NULL) + return ENOMEM; + + krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_HOST); + krb5_storage_set_eof_code(sp, KRB5_CC_IO); + + krb5_clear_error_string(context); + + if (!append) { + RCHECK(ret, krb5_store_stringz(sp, v4creds->pname), error); + RCHECK(ret, krb5_store_stringz(sp, v4creds->pinst), error); + } + + /* cred */ + RCHECK(ret, krb5_store_stringz(sp, v4creds->service), error); + RCHECK(ret, krb5_store_stringz(sp, v4creds->instance), error); + RCHECK(ret, krb5_store_stringz(sp, v4creds->realm), error); + ret = krb5_storage_write(sp, v4creds->session, 8); + if (ret != 8) { + ret = KRB5_CC_IO; + goto error; + } + RCHECK(ret, krb5_store_int32(sp, v4creds->lifetime), error); + RCHECK(ret, krb5_store_int32(sp, v4creds->kvno), error); + RCHECK(ret, krb5_store_int32(sp, v4creds->ticket_st.length), error); + + ret = krb5_storage_write(sp, v4creds->ticket_st.dat, + v4creds->ticket_st.length); + if (ret != v4creds->ticket_st.length) { + ret = KRB5_CC_IO; + goto error; + } + RCHECK(ret, krb5_store_int32(sp, v4creds->issue_date), error); + + ret = write_v4_cc(context, tkfile, sp, append); + + error: + krb5_storage_free(sp); + + return ret; +} + +/* + * + */ + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_krb_dest_tkt(krb5_context context, const char *tkfile) +{ + krb5_error_code ret; + char *path; + + ret = get_krb4_cc_name(tkfile, &path); + if (ret) { + krb5_set_error_string(context, + "krb5_krb_tf_setup: failed getting " + "the krb4 credentials cache name"); + return ret; + } + + if (unlink(path) < 0) { + ret = errno; + krb5_set_error_string(context, + "krb5_krb_dest_tkt failed removing the cache " + "with error %s", strerror(ret)); + } + free(path); + + return ret; +} + +/* + * + */ + +static krb5_error_code +decrypt_etext(krb5_context context, const krb5_keyblock *key, + const krb5_data *cdata, krb5_data *data) +{ + krb5_error_code ret; + krb5_crypto crypto; + + ret = krb5_crypto_init(context, key, ETYPE_DES_PCBC_NONE, &crypto); + if (ret) + return ret; + + ret = krb5_decrypt(context, crypto, 0, cdata->data, cdata->length, data); + krb5_crypto_destroy(context, crypto); + + return ret; +} + + +/* + * + */ + +static const char eightzeros[8] = "\x00\x00\x00\x00\x00\x00\x00\x00"; + +static krb5_error_code +storage_to_etext(krb5_context context, + krb5_storage *sp, + const krb5_keyblock *key, + krb5_data *enc_data) +{ + krb5_error_code ret; + krb5_crypto crypto; + krb5_ssize_t size; + krb5_data data; + + /* multiple of eight bytes */ + + size = krb5_storage_seek(sp, 0, SEEK_END); + if (size < 0) + return KRB4ET_RD_AP_UNDEC; + size = 8 - (size & 7); + + ret = krb5_storage_write(sp, eightzeros, size); + if (ret != size) + return KRB4ET_RD_AP_UNDEC; + + ret = krb5_storage_to_data(sp, &data); + if (ret) + return ret; + + ret = krb5_crypto_init(context, key, ETYPE_DES_PCBC_NONE, &crypto); + if (ret) { + krb5_data_free(&data); + return ret; + } + + ret = krb5_encrypt(context, crypto, 0, data.data, data.length, enc_data); + + krb5_data_free(&data); + krb5_crypto_destroy(context, crypto); + + return ret; +} + +/* + * + */ + +static krb5_error_code +put_nir(krb5_storage *sp, const char *name, + const char *instance, const char *realm) +{ + krb5_error_code ret; + + RCHECK(ret, krb5_store_stringz(sp, name), error); + RCHECK(ret, krb5_store_stringz(sp, instance), error); + if (realm) { + RCHECK(ret, krb5_store_stringz(sp, realm), error); + } + error: + return ret; +} + +/* + * + */ + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_krb_create_ticket(krb5_context context, + unsigned char flags, + const char *pname, + const char *pinstance, + const char *prealm, + int32_t paddress, + const krb5_keyblock *session, + int16_t life, + int32_t life_sec, + const char *sname, + const char *sinstance, + const krb5_keyblock *key, + krb5_data *enc_data) +{ + krb5_error_code ret; + krb5_storage *sp; + + krb5_data_zero(enc_data); + + sp = krb5_storage_emem(); + if (sp == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_BE); + + RCHECK(ret, krb5_store_int8(sp, flags), error); + RCHECK(ret, put_nir(sp, pname, pinstance, prealm), error); + RCHECK(ret, krb5_store_int32(sp, ntohl(paddress)), error); + + /* session key */ + ret = krb5_storage_write(sp, + session->keyvalue.data, + session->keyvalue.length); + if (ret != session->keyvalue.length) { + ret = KRB4ET_INTK_PROT; + goto error; + } + + RCHECK(ret, krb5_store_int8(sp, life), error); + RCHECK(ret, krb5_store_int32(sp, life_sec), error); + RCHECK(ret, put_nir(sp, sname, sinstance, NULL), error); + + ret = storage_to_etext(context, sp, key, enc_data); + + error: + krb5_storage_free(sp); + if (ret) + krb5_set_error_string(context, "Failed to encode kerberos 4 ticket"); + + return ret; +} + +/* + * + */ + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_krb_create_ciph(krb5_context context, + const krb5_keyblock *session, + const char *service, + const char *instance, + const char *realm, + uint32_t life, + unsigned char kvno, + const krb5_data *ticket, + uint32_t kdc_time, + const krb5_keyblock *key, + krb5_data *enc_data) +{ + krb5_error_code ret; + krb5_storage *sp; + + krb5_data_zero(enc_data); + + sp = krb5_storage_emem(); + if (sp == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_BE); + + /* session key */ + ret = krb5_storage_write(sp, + session->keyvalue.data, + session->keyvalue.length); + if (ret != session->keyvalue.length) { + ret = KRB4ET_INTK_PROT; + goto error; + } + + RCHECK(ret, put_nir(sp, service, instance, realm), error); + RCHECK(ret, krb5_store_int8(sp, life), error); + RCHECK(ret, krb5_store_int8(sp, kvno), error); + RCHECK(ret, krb5_store_int8(sp, ticket->length), error); + ret = krb5_storage_write(sp, ticket->data, ticket->length); + if (ret != ticket->length) { + ret = KRB4ET_INTK_PROT; + goto error; + } + RCHECK(ret, krb5_store_int32(sp, kdc_time), error); + + ret = storage_to_etext(context, sp, key, enc_data); + + error: + krb5_storage_free(sp); + if (ret) + krb5_set_error_string(context, "Failed to encode kerberos 4 ticket"); + + return ret; +} + +/* + * + */ + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_krb_create_auth_reply(krb5_context context, + const char *pname, + const char *pinst, + const char *prealm, + int32_t time_ws, + int n, + uint32_t x_date, + unsigned char kvno, + const krb5_data *cipher, + krb5_data *data) +{ + krb5_error_code ret; + krb5_storage *sp; + + krb5_data_zero(data); + + sp = krb5_storage_emem(); + if (sp == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_BE); + + RCHECK(ret, krb5_store_int8(sp, KRB_PROT_VERSION), error); + RCHECK(ret, krb5_store_int8(sp, AUTH_MSG_KDC_REPLY), error); + RCHECK(ret, put_nir(sp, pname, pinst, prealm), error); + RCHECK(ret, krb5_store_int32(sp, time_ws), error); + RCHECK(ret, krb5_store_int8(sp, n), error); + RCHECK(ret, krb5_store_int32(sp, x_date), error); + RCHECK(ret, krb5_store_int8(sp, kvno), error); + RCHECK(ret, krb5_store_int16(sp, cipher->length), error); + ret = krb5_storage_write(sp, cipher->data, cipher->length); + if (ret != cipher->length) { + ret = KRB4ET_INTK_PROT; + goto error; + } + + ret = krb5_storage_to_data(sp, data); + + error: + krb5_storage_free(sp); + if (ret) + krb5_set_error_string(context, "Failed to encode kerberos 4 ticket"); + + return ret; +} + +/* + * + */ + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_krb_cr_err_reply(krb5_context context, + const char *name, + const char *inst, + const char *realm, + uint32_t time_ws, + uint32_t e, + const char *e_string, + krb5_data *data) +{ + krb5_error_code ret; + krb5_storage *sp; + + krb5_data_zero(data); + + if (name == NULL) name = ""; + if (inst == NULL) inst = ""; + if (realm == NULL) realm = ""; + if (e_string == NULL) e_string = ""; + + sp = krb5_storage_emem(); + if (sp == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_BE); + + RCHECK(ret, krb5_store_int8(sp, KRB_PROT_VERSION), error); + RCHECK(ret, krb5_store_int8(sp, AUTH_MSG_ERR_REPLY), error); + RCHECK(ret, put_nir(sp, name, inst, realm), error); + RCHECK(ret, krb5_store_int32(sp, time_ws), error); + /* If it is a Kerberos 4 error-code, remove the et BASE */ + if (e >= ERROR_TABLE_BASE_krb && e <= ERROR_TABLE_BASE_krb + 255) + e -= ERROR_TABLE_BASE_krb; + RCHECK(ret, krb5_store_int32(sp, e), error); + RCHECK(ret, krb5_store_stringz(sp, e_string), error); + + ret = krb5_storage_to_data(sp, data); + + error: + krb5_storage_free(sp); + if (ret) + krb5_set_error_string(context, "Failed to encode kerberos 4 error"); + + return 0; +} + +static krb5_error_code +get_v4_stringz(krb5_storage *sp, char **str, size_t max_len) +{ + krb5_error_code ret; + + ret = krb5_ret_stringz(sp, str); + if (ret) + return ret; + if (strlen(*str) > max_len) { + free(*str); + *str = NULL; + return KRB4ET_INTK_PROT; + } + return 0; +} + +/* + * + */ + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_krb_decomp_ticket(krb5_context context, + const krb5_data *enc_ticket, + const krb5_keyblock *key, + const char *local_realm, + char **sname, + char **sinstance, + struct _krb5_krb_auth_data *ad) +{ + krb5_error_code ret; + krb5_ssize_t size; + krb5_storage *sp = NULL; + krb5_data ticket; + unsigned char des_key[8]; + + memset(ad, 0, sizeof(*ad)); + krb5_data_zero(&ticket); + + *sname = NULL; + *sinstance = NULL; + + RCHECK(ret, decrypt_etext(context, key, enc_ticket, &ticket), error); + + sp = krb5_storage_from_data(&ticket); + if (sp == NULL) { + krb5_data_free(&ticket); + krb5_set_error_string(context, "alloc: out of memory"); + return ENOMEM; + } + + krb5_storage_set_eof_code(sp, KRB4ET_INTK_PROT); + + RCHECK(ret, krb5_ret_int8(sp, &ad->k_flags), error); + RCHECK(ret, get_v4_stringz(sp, &ad->pname, ANAME_SZ), error); + RCHECK(ret, get_v4_stringz(sp, &ad->pinst, INST_SZ), error); + RCHECK(ret, get_v4_stringz(sp, &ad->prealm, REALM_SZ), error); + RCHECK(ret, krb5_ret_uint32(sp, &ad->address), error); + + size = krb5_storage_read(sp, des_key, sizeof(des_key)); + if (size != sizeof(des_key)) { + ret = KRB4ET_INTK_PROT; + goto error; + } + + RCHECK(ret, krb5_ret_uint8(sp, &ad->life), error); + + if (ad->k_flags & 1) + krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_LE); + else + krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_BE); + + RCHECK(ret, krb5_ret_uint32(sp, &ad->time_sec), error); + + RCHECK(ret, get_v4_stringz(sp, sname, ANAME_SZ), error); + RCHECK(ret, get_v4_stringz(sp, sinstance, INST_SZ), error); + + ret = krb5_keyblock_init(context, ETYPE_DES_PCBC_NONE, + des_key, sizeof(des_key), &ad->session); + if (ret) + goto error; + + if (strlen(ad->prealm) == 0) { + free(ad->prealm); + ad->prealm = strdup(local_realm); + if (ad->prealm == NULL) { + ret = ENOMEM; + goto error; + } + } + + error: + memset(des_key, 0, sizeof(des_key)); + if (sp) + krb5_storage_free(sp); + krb5_data_free(&ticket); + if (ret) { + if (*sname) { + free(*sname); + *sname = NULL; + } + if (*sinstance) { + free(*sinstance); + *sinstance = NULL; + } + _krb5_krb_free_auth_data(context, ad); + krb5_set_error_string(context, "Failed to decode v4 ticket"); + } + return ret; +} + +/* + * + */ + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_krb_rd_req(krb5_context context, + krb5_data *authent, + const char *service, + const char *instance, + const char *local_realm, + int32_t from_addr, + const krb5_keyblock *key, + struct _krb5_krb_auth_data *ad) +{ + krb5_error_code ret; + krb5_storage *sp; + krb5_data ticket, eaut, aut; + krb5_ssize_t size; + int little_endian; + int8_t pvno; + int8_t type; + int8_t s_kvno; + uint8_t ticket_length; + uint8_t eaut_length; + uint8_t time_5ms; + char *realm = NULL; + char *sname = NULL; + char *sinstance = NULL; + char *r_realm = NULL; + char *r_name = NULL; + char *r_instance = NULL; + + uint32_t r_time_sec; /* Coarse time from authenticator */ + unsigned long delta_t; /* Time in authenticator - local time */ + long tkt_age; /* Age of ticket */ + + struct timeval tv; + + krb5_data_zero(&ticket); + krb5_data_zero(&eaut); + krb5_data_zero(&aut); + + sp = krb5_storage_from_data(authent); + if (sp == NULL) { + krb5_set_error_string(context, "alloc: out of memory"); + return ENOMEM; + } + + krb5_storage_set_eof_code(sp, KRB4ET_INTK_PROT); + + ret = krb5_ret_int8(sp, &pvno); + if (ret) { + krb5_set_error_string(context, "Failed reading v4 pvno"); + goto error; + } + + if (pvno != KRB_PROT_VERSION) { + ret = KRB4ET_RD_AP_VERSION; + krb5_set_error_string(context, "Failed v4 pvno not 4"); + goto error; + } + + ret = krb5_ret_int8(sp, &type); + if (ret) { + krb5_set_error_string(context, "Failed readin v4 type"); + goto error; + } + + little_endian = type & 1; + type &= ~1; + + if(type != AUTH_MSG_APPL_REQUEST && type != AUTH_MSG_APPL_REQUEST_MUTUAL) { + ret = KRB4ET_RD_AP_MSG_TYPE; + krb5_set_error_string(context, "Not a valid v4 request type"); + goto error; + } + + RCHECK(ret, krb5_ret_int8(sp, &s_kvno), error); + RCHECK(ret, get_v4_stringz(sp, &realm, REALM_SZ), error); + RCHECK(ret, krb5_ret_uint8(sp, &ticket_length), error); + RCHECK(ret, krb5_ret_uint8(sp, &eaut_length), error); + RCHECK(ret, krb5_data_alloc(&ticket, ticket_length), error); + + size = krb5_storage_read(sp, ticket.data, ticket.length); + if (size != ticket.length) { + ret = KRB4ET_INTK_PROT; + krb5_set_error_string(context, "Failed reading v4 ticket"); + goto error; + } + + /* Decrypt and take apart ticket */ + ret = _krb5_krb_decomp_ticket(context, &ticket, key, local_realm, + &sname, &sinstance, ad); + if (ret) + goto error; + + RCHECK(ret, krb5_data_alloc(&eaut, eaut_length), error); + + size = krb5_storage_read(sp, eaut.data, eaut.length); + if (size != eaut.length) { + ret = KRB4ET_INTK_PROT; + krb5_set_error_string(context, "Failed reading v4 authenticator"); + goto error; + } + + krb5_storage_free(sp); + sp = NULL; + + ret = decrypt_etext(context, &ad->session, &eaut, &aut); + if (ret) + goto error; + + sp = krb5_storage_from_data(&aut); + if (sp == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "alloc: out of memory"); + goto error; + } + + if (little_endian) + krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_LE); + else + krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_BE); + + RCHECK(ret, get_v4_stringz(sp, &r_name, ANAME_SZ), error); + RCHECK(ret, get_v4_stringz(sp, &r_instance, INST_SZ), error); + RCHECK(ret, get_v4_stringz(sp, &r_realm, REALM_SZ), error); + + RCHECK(ret, krb5_ret_uint32(sp, &ad->checksum), error); + RCHECK(ret, krb5_ret_uint8(sp, &time_5ms), error); + RCHECK(ret, krb5_ret_uint32(sp, &r_time_sec), error); + + if (strcmp(ad->pname, r_name) != 0 || + strcmp(ad->pinst, r_instance) != 0 || + strcmp(ad->prealm, r_realm) != 0) { + krb5_set_error_string(context, "v4 principal mismatch"); + ret = KRB4ET_RD_AP_INCON; + goto error; + } + + if (from_addr && ad->address && from_addr != ad->address) { + krb5_set_error_string(context, "v4 bad address in ticket"); + ret = KRB4ET_RD_AP_BADD; + goto error; + } + + gettimeofday(&tv, NULL); + delta_t = abs((int)(tv.tv_sec - r_time_sec)); + if (delta_t > CLOCK_SKEW) { + ret = KRB4ET_RD_AP_TIME; + krb5_set_error_string(context, "v4 clock skew"); + goto error; + } + + /* Now check for expiration of ticket */ + + tkt_age = tv.tv_sec - ad->time_sec; + + if ((tkt_age < 0) && (-tkt_age > CLOCK_SKEW)) { + ret = KRB4ET_RD_AP_NYV; + krb5_set_error_string(context, "v4 clock skew for expiration"); + goto error; + } + + if (tv.tv_sec > _krb5_krb_life_to_time(ad->time_sec, ad->life)) { + ret = KRB4ET_RD_AP_EXP; + krb5_set_error_string(context, "v4 ticket expired"); + goto error; + } + + ret = 0; + error: + krb5_data_free(&ticket); + krb5_data_free(&eaut); + krb5_data_free(&aut); + if (realm) + free(realm); + if (sname) + free(sname); + if (sinstance) + free(sinstance); + if (r_name) + free(r_name); + if (r_instance) + free(r_instance); + if (r_realm) + free(r_realm); + if (sp) + krb5_storage_free(sp); + + if (ret) + krb5_clear_error_string(context); + + return ret; +} + +/* + * + */ + +void KRB5_LIB_FUNCTION +_krb5_krb_free_auth_data(krb5_context context, struct _krb5_krb_auth_data *ad) +{ + if (ad->pname) + free(ad->pname); + if (ad->pinst) + free(ad->pinst); + if (ad->prealm) + free(ad->prealm); + krb5_free_keyblock_contents(context, &ad->session); + memset(ad, 0, sizeof(*ad)); +} diff --git a/lib/krb5/verify_init.c b/lib/krb5/verify_init.c new file mode 100644 index 0000000..37db346 --- /dev/null +++ b/lib/krb5/verify_init.c @@ -0,0 +1,199 @@ +/* + * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: verify_init.c 15555 2005-07-06 00:48:16Z lha $"); + +void KRB5_LIB_FUNCTION +krb5_verify_init_creds_opt_init(krb5_verify_init_creds_opt *options) +{ + memset (options, 0, sizeof(*options)); +} + +void KRB5_LIB_FUNCTION +krb5_verify_init_creds_opt_set_ap_req_nofail(krb5_verify_init_creds_opt *options, + int ap_req_nofail) +{ + options->flags |= KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL; + options->ap_req_nofail = ap_req_nofail; +} + +/* + * + */ + +static krb5_boolean +fail_verify_is_ok (krb5_context context, + krb5_verify_init_creds_opt *options) +{ + if ((options->flags & KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL + && options->ap_req_nofail != 0) + || krb5_config_get_bool (context, + NULL, + "libdefaults", + "verify_ap_req_nofail", + NULL)) + return FALSE; + else + return TRUE; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_verify_init_creds(krb5_context context, + krb5_creds *creds, + krb5_principal ap_req_server, + krb5_keytab ap_req_keytab, + krb5_ccache *ccache, + krb5_verify_init_creds_opt *options) +{ + krb5_error_code ret; + krb5_data req; + krb5_ccache local_ccache = NULL; + krb5_creds *new_creds = NULL; + krb5_auth_context auth_context = NULL; + krb5_principal server = NULL; + krb5_keytab keytab = NULL; + + krb5_data_zero (&req); + + if (ap_req_server == NULL) { + char local_hostname[MAXHOSTNAMELEN]; + + if (gethostname (local_hostname, sizeof(local_hostname)) < 0) { + ret = errno; + krb5_set_error_string (context, "gethostname: %s", + strerror(ret)); + return ret; + } + + ret = krb5_sname_to_principal (context, + local_hostname, + "host", + KRB5_NT_SRV_HST, + &server); + if (ret) + goto cleanup; + } else + server = ap_req_server; + + if (ap_req_keytab == NULL) { + ret = krb5_kt_default (context, &keytab); + if (ret) + goto cleanup; + } else + keytab = ap_req_keytab; + + if (ccache && *ccache) + local_ccache = *ccache; + else { + ret = krb5_cc_gen_new (context, &krb5_mcc_ops, &local_ccache); + if (ret) + goto cleanup; + ret = krb5_cc_initialize (context, + local_ccache, + creds->client); + if (ret) + goto cleanup; + ret = krb5_cc_store_cred (context, + local_ccache, + creds); + if (ret) + goto cleanup; + } + + if (!krb5_principal_compare (context, server, creds->server)) { + krb5_creds match_cred; + + memset (&match_cred, 0, sizeof(match_cred)); + + match_cred.client = creds->client; + match_cred.server = server; + + ret = krb5_get_credentials (context, + 0, + local_ccache, + &match_cred, + &new_creds); + if (ret) { + if (fail_verify_is_ok (context, options)) + ret = 0; + goto cleanup; + } + creds = new_creds; + } + + ret = krb5_mk_req_extended (context, + &auth_context, + 0, + NULL, + creds, + &req); + + krb5_auth_con_free (context, auth_context); + auth_context = NULL; + + if (ret) + goto cleanup; + + ret = krb5_rd_req (context, + &auth_context, + &req, + server, + keytab, + 0, + NULL); + + if (ret == KRB5_KT_NOTFOUND && fail_verify_is_ok (context, options)) + ret = 0; +cleanup: + if (auth_context) + krb5_auth_con_free (context, auth_context); + krb5_data_free (&req); + if (new_creds != NULL) + krb5_free_creds (context, new_creds); + if (ap_req_server == NULL && server) + krb5_free_principal (context, server); + if (ap_req_keytab == NULL && keytab) + krb5_kt_close (context, keytab); + if (local_ccache != NULL + && + (ccache == NULL + || (ret != 0 && *ccache == NULL))) + krb5_cc_destroy (context, local_ccache); + + if (ret == 0 && ccache != NULL && *ccache == NULL) + *ccache = local_ccache; + + return ret; +} diff --git a/lib/krb5/verify_krb5_conf.8 b/lib/krb5/verify_krb5_conf.8 new file mode 100644 index 0000000..28f84ab --- /dev/null +++ b/lib/krb5/verify_krb5_conf.8 @@ -0,0 +1,95 @@ +.\" Copyright (c) 2000 - 2004 Kungliga Tekniska Högskolan +.\" (Royal Institute of Technology, Stockholm, Sweden). +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" 3. Neither the name of the Institute nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: verify_krb5_conf.8 14375 2004-12-08 17:52:41Z lha $ +.\" +.Dd December 8, 2004 +.Dt VERIFY_KRB5_CONF 8 +.Os HEIMDAL +.Sh NAME +.Nm verify_krb5_conf +.Nd checks krb5.conf for obvious errors +.Sh SYNOPSIS +.Nm +.Ar [config-file] +.Sh DESCRIPTION +.Nm +reads the configuration file +.Pa krb5.conf , +or the file given on the command line, +and parses it, thereby verifying that the syntax is not correctly wrong. +.Pp +If the file is syntactically correct, +.Nm +tries to verify that the contents of the file is of relevant nature. +.Sh ENVIRONMENT +.Ev KRB5_CONFIG +points to the configuration file to read. +.Sh FILES +.Bl -tag -width /etc/krb5.conf -compact +.It Pa /etc/krb5.conf +Kerberos 5 configuration file +.El +.Sh DIAGNOSTICS +Possible output from +.Nm +include: +.Bl -tag -width "FpathF" +.It "<path>: failed to parse <something> as size/time/number/boolean" +Usually means that <something> is misspelled, or that it contains +weird characters. The parsing done by +.Nm +is more strict than the one performed by libkrb5, so strings that +work in real life might be reported as bad. +.It "<path>: host not found (<hostname>)" +Means that <path> is supposed to point to a host, but it can't be +recognised as one. +.It <path>: unknown or wrong type +Means that <path> is either a string when it should be a list, vice +versa, or just that +.Nm +is confused. +.It <path>: unknown entry +Means that <string> is not known by +.Nm "" . +.El +.Sh SEE ALSO +.Xr krb5.conf 5 +.Sh BUGS +Since each application can put almost anything in the config file, +it's hard to come up with a watertight verification process. Most of +the default settings are sanity checked, but this does not mean that +every problem is discovered, or that everything that is reported as a +possible problem actually is one. This tool should thus be used with +some care. +.Pp +It should warn about obsolete data, or bad practice, but currently +doesn't. diff --git a/lib/krb5/verify_krb5_conf.c b/lib/krb5/verify_krb5_conf.c new file mode 100644 index 0000000..b55fbd7 --- /dev/null +++ b/lib/krb5/verify_krb5_conf.c @@ -0,0 +1,676 @@ +/* + * Copyright (c) 1999 - 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" +#include <getarg.h> +#include <parse_bytes.h> +#include <err.h> +RCSID("$Id: verify_krb5_conf.c 22233 2007-12-08 21:43:37Z lha $"); + +/* verify krb5.conf */ + +static int dumpconfig_flag = 0; +static int version_flag = 0; +static int help_flag = 0; +static int warn_mit_syntax_flag = 0; + +static struct getargs args[] = { + {"dumpconfig", 0, arg_flag, &dumpconfig_flag, + "show the parsed config files", NULL }, + {"warn-mit-syntax", 0, arg_flag, &warn_mit_syntax_flag, + "show the parsed config files", NULL }, + {"version", 0, arg_flag, &version_flag, + "print version", NULL }, + {"help", 0, arg_flag, &help_flag, + NULL, NULL } +}; + +static void +usage (int ret) +{ + arg_printusage (args, + sizeof(args)/sizeof(*args), + NULL, + "[config-file]"); + exit (ret); +} + +static int +check_bytes(krb5_context context, const char *path, char *data) +{ + if(parse_bytes(data, NULL) == -1) { + krb5_warnx(context, "%s: failed to parse \"%s\" as size", path, data); + return 1; + } + return 0; +} + +static int +check_time(krb5_context context, const char *path, char *data) +{ + if(parse_time(data, NULL) == -1) { + krb5_warnx(context, "%s: failed to parse \"%s\" as time", path, data); + return 1; + } + return 0; +} + +static int +check_numeric(krb5_context context, const char *path, char *data) +{ + long int v; + char *end; + v = strtol(data, &end, 0); + if(*end != '\0') { + krb5_warnx(context, "%s: failed to parse \"%s\" as a number", + path, data); + return 1; + } + return 0; +} + +static int +check_boolean(krb5_context context, const char *path, char *data) +{ + long int v; + char *end; + if(strcasecmp(data, "yes") == 0 || + strcasecmp(data, "true") == 0 || + strcasecmp(data, "no") == 0 || + strcasecmp(data, "false") == 0) + return 0; + v = strtol(data, &end, 0); + if(*end != '\0') { + krb5_warnx(context, "%s: failed to parse \"%s\" as a boolean", + path, data); + return 1; + } + if(v != 0 && v != 1) + krb5_warnx(context, "%s: numeric value \"%s\" is treated as \"true\"", + path, data); + return 0; +} + +static int +check_524(krb5_context context, const char *path, char *data) +{ + if(strcasecmp(data, "yes") == 0 || + strcasecmp(data, "no") == 0 || + strcasecmp(data, "2b") == 0 || + strcasecmp(data, "local") == 0) + return 0; + + krb5_warnx(context, "%s: didn't contain a valid option `%s'", + path, data); + return 1; +} + +static int +check_host(krb5_context context, const char *path, char *data) +{ + int ret; + char hostname[128]; + const char *p = data; + struct addrinfo hints; + char service[32]; + int defport; + struct addrinfo *ai; + + hints.ai_flags = 0; + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = 0; + hints.ai_protocol = 0; + + hints.ai_addrlen = 0; + hints.ai_canonname = NULL; + hints.ai_addr = NULL; + hints.ai_next = NULL; + + /* XXX data could be a list of hosts that this code can't handle */ + /* XXX copied from krbhst.c */ + if(strncmp(p, "http://", 7) == 0){ + p += 7; + hints.ai_socktype = SOCK_STREAM; + strlcpy(service, "http", sizeof(service)); + defport = 80; + } else if(strncmp(p, "http/", 5) == 0) { + p += 5; + hints.ai_socktype = SOCK_STREAM; + strlcpy(service, "http", sizeof(service)); + defport = 80; + }else if(strncmp(p, "tcp/", 4) == 0){ + p += 4; + hints.ai_socktype = SOCK_STREAM; + strlcpy(service, "kerberos", sizeof(service)); + defport = 88; + } else if(strncmp(p, "udp/", 4) == 0) { + p += 4; + hints.ai_socktype = SOCK_DGRAM; + strlcpy(service, "kerberos", sizeof(service)); + defport = 88; + } else { + hints.ai_socktype = SOCK_DGRAM; + strlcpy(service, "kerberos", sizeof(service)); + defport = 88; + } + if(strsep_copy(&p, ":", hostname, sizeof(hostname)) < 0) { + return 1; + } + hostname[strcspn(hostname, "/")] = '\0'; + if(p != NULL) { + char *end; + int tmp = strtol(p, &end, 0); + if(end == p) { + krb5_warnx(context, "%s: failed to parse port number in %s", + path, data); + return 1; + } + defport = tmp; + snprintf(service, sizeof(service), "%u", defport); + } + ret = getaddrinfo(hostname, service, &hints, &ai); + if(ret == EAI_SERVICE && !isdigit((unsigned char)service[0])) { + snprintf(service, sizeof(service), "%u", defport); + ret = getaddrinfo(hostname, service, &hints, &ai); + } + if(ret != 0) { + krb5_warnx(context, "%s: %s (%s)", path, gai_strerror(ret), hostname); + return 1; + } + return 0; +} + +static int +mit_entry(krb5_context context, const char *path, char *data) +{ + if (warn_mit_syntax_flag) + krb5_warnx(context, "%s is only used by MIT Kerberos", path); + return 0; +} + +struct s2i { + const char *s; + int val; +}; + +#define L(X) { #X, LOG_ ## X } + +static struct s2i syslogvals[] = { + /* severity */ + L(EMERG), + L(ALERT), + L(CRIT), + L(ERR), + L(WARNING), + L(NOTICE), + L(INFO), + L(DEBUG), + /* facility */ + L(AUTH), +#ifdef LOG_AUTHPRIV + L(AUTHPRIV), +#endif +#ifdef LOG_CRON + L(CRON), +#endif + L(DAEMON), +#ifdef LOG_FTP + L(FTP), +#endif + L(KERN), + L(LPR), + L(MAIL), +#ifdef LOG_NEWS + L(NEWS), +#endif + L(SYSLOG), + L(USER), +#ifdef LOG_UUCP + L(UUCP), +#endif + L(LOCAL0), + L(LOCAL1), + L(LOCAL2), + L(LOCAL3), + L(LOCAL4), + L(LOCAL5), + L(LOCAL6), + L(LOCAL7), + { NULL, -1 } +}; + +static int +find_value(const char *s, struct s2i *table) +{ + while(table->s && strcasecmp(table->s, s)) + table++; + return table->val; +} + +static int +check_log(krb5_context context, const char *path, char *data) +{ + /* XXX sync with log.c */ + int min = 0, max = -1, n; + char c; + const char *p = data; + + n = sscanf(p, "%d%c%d/", &min, &c, &max); + if(n == 2){ + if(c == '/') { + if(min < 0){ + max = -min; + min = 0; + }else{ + max = min; + } + } + } + if(n){ + p = strchr(p, '/'); + if(p == NULL) { + krb5_warnx(context, "%s: failed to parse \"%s\"", path, data); + return 1; + } + p++; + } + if(strcmp(p, "STDERR") == 0 || + strcmp(p, "CONSOLE") == 0 || + (strncmp(p, "FILE", 4) == 0 && (p[4] == ':' || p[4] == '=')) || + (strncmp(p, "DEVICE", 6) == 0 && p[6] == '=')) + return 0; + if(strncmp(p, "SYSLOG", 6) == 0){ + int ret = 0; + char severity[128] = ""; + char facility[128] = ""; + p += 6; + if(*p != '\0') + p++; + if(strsep_copy(&p, ":", severity, sizeof(severity)) != -1) + strsep_copy(&p, ":", facility, sizeof(facility)); + if(*severity == '\0') + strlcpy(severity, "ERR", sizeof(severity)); + if(*facility == '\0') + strlcpy(facility, "AUTH", sizeof(facility)); + if(find_value(severity, syslogvals) == -1) { + krb5_warnx(context, "%s: unknown syslog facility \"%s\"", + path, facility); + ret++; + } + if(find_value(severity, syslogvals) == -1) { + krb5_warnx(context, "%s: unknown syslog severity \"%s\"", + path, severity); + ret++; + } + return ret; + }else{ + krb5_warnx(context, "%s: unknown log type: \"%s\"", path, data); + return 1; + } +} + +typedef int (*check_func_t)(krb5_context, const char*, char*); +struct entry { + const char *name; + int type; + void *check_data; +}; + +struct entry all_strings[] = { + { "", krb5_config_string, NULL }, + { NULL } +}; + +struct entry all_boolean[] = { + { "", krb5_config_string, check_boolean }, + { NULL } +}; + + +struct entry v4_name_convert_entries[] = { + { "host", krb5_config_list, all_strings }, + { "plain", krb5_config_list, all_strings }, + { NULL } +}; + +struct entry libdefaults_entries[] = { + { "accept_null_addresses", krb5_config_string, check_boolean }, + { "capath", krb5_config_list, all_strings }, + { "check_pac", krb5_config_string, check_boolean }, + { "clockskew", krb5_config_string, check_time }, + { "date_format", krb5_config_string, NULL }, + { "default_cc_name", krb5_config_string, NULL }, + { "default_etypes", krb5_config_string, NULL }, + { "default_etypes_des", krb5_config_string, NULL }, + { "default_keytab_modify_name", krb5_config_string, NULL }, + { "default_keytab_name", krb5_config_string, NULL }, + { "default_realm", krb5_config_string, NULL }, + { "dns_canonize_hostname", krb5_config_string, check_boolean }, + { "dns_proxy", krb5_config_string, NULL }, + { "dns_lookup_kdc", krb5_config_string, check_boolean }, + { "dns_lookup_realm", krb5_config_string, check_boolean }, + { "dns_lookup_realm_labels", krb5_config_string, NULL }, + { "egd_socket", krb5_config_string, NULL }, + { "encrypt", krb5_config_string, check_boolean }, + { "extra_addresses", krb5_config_string, NULL }, + { "fcache_version", krb5_config_string, check_numeric }, + { "fcc-mit-ticketflags", krb5_config_string, check_boolean }, + { "forward", krb5_config_string, check_boolean }, + { "forwardable", krb5_config_string, check_boolean }, + { "http_proxy", krb5_config_string, check_host /* XXX */ }, + { "ignore_addresses", krb5_config_string, NULL }, + { "kdc_timeout", krb5_config_string, check_time }, + { "kdc_timesync", krb5_config_string, check_boolean }, + { "log_utc", krb5_config_string, check_boolean }, + { "maxretries", krb5_config_string, check_numeric }, + { "scan_interfaces", krb5_config_string, check_boolean }, + { "srv_lookup", krb5_config_string, check_boolean }, + { "srv_try_txt", krb5_config_string, check_boolean }, + { "ticket_lifetime", krb5_config_string, check_time }, + { "time_format", krb5_config_string, NULL }, + { "transited_realms_reject", krb5_config_string, NULL }, + { "no-addresses", krb5_config_string, check_boolean }, + { "v4_instance_resolve", krb5_config_string, check_boolean }, + { "v4_name_convert", krb5_config_list, v4_name_convert_entries }, + { "verify_ap_req_nofail", krb5_config_string, check_boolean }, + { "max_retries", krb5_config_string, check_time }, + { "renew_lifetime", krb5_config_string, check_time }, + { "proxiable", krb5_config_string, check_boolean }, + { "warn_pwexpire", krb5_config_string, check_time }, + /* MIT stuff */ + { "permitted_enctypes", krb5_config_string, mit_entry }, + { "default_tgs_enctypes", krb5_config_string, mit_entry }, + { "default_tkt_enctypes", krb5_config_string, mit_entry }, + { NULL } +}; + +struct entry appdefaults_entries[] = { + { "afslog", krb5_config_string, check_boolean }, + { "afs-use-524", krb5_config_string, check_524 }, + { "encrypt", krb5_config_string, check_boolean }, + { "forward", krb5_config_string, check_boolean }, + { "forwardable", krb5_config_string, check_boolean }, + { "proxiable", krb5_config_string, check_boolean }, + { "ticket_lifetime", krb5_config_string, check_time }, + { "renew_lifetime", krb5_config_string, check_time }, + { "no-addresses", krb5_config_string, check_boolean }, + { "krb4_get_tickets", krb5_config_string, check_boolean }, + { "pkinit_anchors", krb5_config_string, NULL }, + { "pkinit_win2k", krb5_config_string, NULL }, + { "pkinit_win2k_require_binding", krb5_config_string, NULL }, + { "pkinit_require_eku", krb5_config_string, NULL }, + { "pkinit_require_krbtgt_otherName", krb5_config_string, NULL }, + { "pkinit_require_hostname_match", krb5_config_string, NULL }, +#if 0 + { "anonymous", krb5_config_string, check_boolean }, +#endif + { "", krb5_config_list, appdefaults_entries }, + { NULL } +}; + +struct entry realms_entries[] = { + { "forwardable", krb5_config_string, check_boolean }, + { "proxiable", krb5_config_string, check_boolean }, + { "ticket_lifetime", krb5_config_string, check_time }, + { "renew_lifetime", krb5_config_string, check_time }, + { "warn_pwexpire", krb5_config_string, check_time }, + { "kdc", krb5_config_string, check_host }, + { "admin_server", krb5_config_string, check_host }, + { "kpasswd_server", krb5_config_string, check_host }, + { "krb524_server", krb5_config_string, check_host }, + { "v4_name_convert", krb5_config_list, v4_name_convert_entries }, + { "v4_instance_convert", krb5_config_list, all_strings }, + { "v4_domains", krb5_config_string, NULL }, + { "default_domain", krb5_config_string, NULL }, + { "win2k_pkinit", krb5_config_string, NULL }, + /* MIT stuff */ + { "admin_keytab", krb5_config_string, mit_entry }, + { "acl_file", krb5_config_string, mit_entry }, + { "dict_file", krb5_config_string, mit_entry }, + { "kadmind_port", krb5_config_string, mit_entry }, + { "kpasswd_port", krb5_config_string, mit_entry }, + { "master_key_name", krb5_config_string, mit_entry }, + { "master_key_type", krb5_config_string, mit_entry }, + { "key_stash_file", krb5_config_string, mit_entry }, + { "max_life", krb5_config_string, mit_entry }, + { "max_renewable_life", krb5_config_string, mit_entry }, + { "default_principal_expiration", krb5_config_string, mit_entry }, + { "default_principal_flags", krb5_config_string, mit_entry }, + { "supported_enctypes", krb5_config_string, mit_entry }, + { "database_name", krb5_config_string, mit_entry }, + { NULL } +}; + +struct entry realms_foobar[] = { + { "", krb5_config_list, realms_entries }, + { NULL } +}; + + +struct entry kdc_database_entries[] = { + { "realm", krb5_config_string, NULL }, + { "dbname", krb5_config_string, NULL }, + { "mkey_file", krb5_config_string, NULL }, + { "acl_file", krb5_config_string, NULL }, + { "log_file", krb5_config_string, NULL }, + { NULL } +}; + +struct entry kdc_entries[] = { + { "database", krb5_config_list, kdc_database_entries }, + { "key-file", krb5_config_string, NULL }, + { "logging", krb5_config_string, check_log }, + { "max-request", krb5_config_string, check_bytes }, + { "require-preauth", krb5_config_string, check_boolean }, + { "ports", krb5_config_string, NULL }, + { "addresses", krb5_config_string, NULL }, + { "enable-kerberos4", krb5_config_string, check_boolean }, + { "enable-524", krb5_config_string, check_boolean }, + { "enable-http", krb5_config_string, check_boolean }, + { "check-ticket-addresses", krb5_config_string, check_boolean }, + { "allow-null-ticket-addresses", krb5_config_string, check_boolean }, + { "allow-anonymous", krb5_config_string, check_boolean }, + { "v4_realm", krb5_config_string, NULL }, + { "enable-kaserver", krb5_config_string, check_boolean }, + { "encode_as_rep_as_tgs_rep", krb5_config_string, check_boolean }, + { "kdc_warn_pwexpire", krb5_config_string, check_time }, + { "use_2b", krb5_config_list, NULL }, + { "enable-pkinit", krb5_config_string, check_boolean }, + { "pkinit_identity", krb5_config_string, NULL }, + { "pkinit_anchors", krb5_config_string, NULL }, + { "pkinit_pool", krb5_config_string, NULL }, + { "pkinit_revoke", krb5_config_string, NULL }, + { "pkinit_kdc_ocsp", krb5_config_string, NULL }, + { "pkinit_principal_in_certificate", krb5_config_string, NULL }, + { "pkinit_dh_min_bits", krb5_config_string, NULL }, + { "pkinit_allow_proxy_certificate", krb5_config_string, NULL }, + { "hdb-ldap-create-base", krb5_config_string, NULL }, + { "v4-realm", krb5_config_string, NULL }, + { NULL } +}; + +struct entry kadmin_entries[] = { + { "password_lifetime", krb5_config_string, check_time }, + { "default_keys", krb5_config_string, NULL }, + { "use_v4_salt", krb5_config_string, NULL }, + { "require-preauth", krb5_config_string, check_boolean }, + { NULL } +}; +struct entry log_strings[] = { + { "", krb5_config_string, check_log }, + { NULL } +}; + + +/* MIT stuff */ +struct entry kdcdefaults_entries[] = { + { "kdc_ports", krb5_config_string, mit_entry }, + { "v4_mode", krb5_config_string, mit_entry }, + { NULL } +}; + +struct entry capaths_entries[] = { + { "", krb5_config_list, all_strings }, + { NULL } +}; + +struct entry password_quality_entries[] = { + { "policies", krb5_config_string, NULL }, + { "external_program", krb5_config_string, NULL }, + { "min_classes", krb5_config_string, check_numeric }, + { "min_length", krb5_config_string, check_numeric }, + { "", krb5_config_list, all_strings }, + { NULL } +}; + +struct entry toplevel_sections[] = { + { "libdefaults" , krb5_config_list, libdefaults_entries }, + { "realms", krb5_config_list, realms_foobar }, + { "domain_realm", krb5_config_list, all_strings }, + { "logging", krb5_config_list, log_strings }, + { "kdc", krb5_config_list, kdc_entries }, + { "kadmin", krb5_config_list, kadmin_entries }, + { "appdefaults", krb5_config_list, appdefaults_entries }, + { "gssapi", krb5_config_list, NULL }, + { "capaths", krb5_config_list, capaths_entries }, + { "password_quality", krb5_config_list, password_quality_entries }, + /* MIT stuff */ + { "kdcdefaults", krb5_config_list, kdcdefaults_entries }, + { NULL } +}; + + +static int +check_section(krb5_context context, const char *path, krb5_config_section *cf, + struct entry *entries) +{ + int error = 0; + krb5_config_section *p; + struct entry *e; + + char *local; + + for(p = cf; p != NULL; p = p->next) { + asprintf(&local, "%s/%s", path, p->name); + for(e = entries; e->name != NULL; e++) { + if(*e->name == '\0' || strcmp(e->name, p->name) == 0) { + if(e->type != p->type) { + krb5_warnx(context, "%s: unknown or wrong type", local); + error |= 1; + } else if(p->type == krb5_config_string && e->check_data != NULL) { + error |= (*(check_func_t)e->check_data)(context, local, p->u.string); + } else if(p->type == krb5_config_list && e->check_data != NULL) { + error |= check_section(context, local, p->u.list, e->check_data); + } + break; + } + } + if(e->name == NULL) { + krb5_warnx(context, "%s: unknown entry", local); + error |= 1; + } + free(local); + } + return error; +} + + +static void +dumpconfig(int level, krb5_config_section *top) +{ + krb5_config_section *x; + for(x = top; x; x = x->next) { + switch(x->type) { + case krb5_config_list: + if(level == 0) { + printf("[%s]\n", x->name); + } else { + printf("%*s%s = {\n", 4 * level, " ", x->name); + } + dumpconfig(level + 1, x->u.list); + if(level > 0) + printf("%*s}\n", 4 * level, " "); + break; + case krb5_config_string: + printf("%*s%s = %s\n", 4 * level, " ", x->name, x->u.string); + break; + } + } +} + +int +main(int argc, char **argv) +{ + krb5_context context; + krb5_error_code ret; + krb5_config_section *tmp_cf; + int optidx = 0; + + setprogname (argv[0]); + + ret = krb5_init_context(&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 with %d", ret); + + if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) + usage(1); + + if (help_flag) + usage (0); + + if(version_flag){ + print_version(NULL); + exit(0); + } + + argc -= optidx; + argv += optidx; + + tmp_cf = NULL; + if(argc == 0) + krb5_get_default_config_files(&argv); + + while(*argv) { + ret = krb5_config_parse_file_multi(context, *argv, &tmp_cf); + if (ret != 0) + krb5_warn (context, ret, "krb5_config_parse_file"); + argv++; + } + + if(dumpconfig_flag) + dumpconfig(0, tmp_cf); + + return check_section(context, "", tmp_cf, toplevel_sections); +} diff --git a/lib/krb5/verify_user.c b/lib/krb5/verify_user.c new file mode 100644 index 0000000..1edbaff --- /dev/null +++ b/lib/krb5/verify_user.c @@ -0,0 +1,265 @@ +/* + * Copyright (c) 1997-2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: verify_user.c 19078 2006-11-20 18:12:41Z lha $"); + +static krb5_error_code +verify_common (krb5_context context, + krb5_principal principal, + krb5_ccache ccache, + krb5_keytab keytab, + krb5_boolean secure, + const char *service, + krb5_creds cred) +{ + krb5_error_code ret; + krb5_principal server; + krb5_verify_init_creds_opt vopt; + krb5_ccache id; + + ret = krb5_sname_to_principal (context, NULL, service, KRB5_NT_SRV_HST, + &server); + if(ret) + return ret; + + krb5_verify_init_creds_opt_init(&vopt); + krb5_verify_init_creds_opt_set_ap_req_nofail(&vopt, secure); + + ret = krb5_verify_init_creds(context, + &cred, + server, + keytab, + NULL, + &vopt); + krb5_free_principal(context, server); + if(ret) + return ret; + if(ccache == NULL) + ret = krb5_cc_default (context, &id); + else + id = ccache; + if(ret == 0){ + ret = krb5_cc_initialize(context, id, principal); + if(ret == 0){ + ret = krb5_cc_store_cred(context, id, &cred); + } + if(ccache == NULL) + krb5_cc_close(context, id); + } + krb5_free_cred_contents(context, &cred); + return ret; +} + +/* + * Verify user `principal' with `password'. + * + * If `secure', also verify against local service key for `service'. + * + * As a side effect, fresh tickets are obtained and stored in `ccache'. + */ + +void KRB5_LIB_FUNCTION +krb5_verify_opt_init(krb5_verify_opt *opt) +{ + memset(opt, 0, sizeof(*opt)); + opt->secure = TRUE; + opt->service = "host"; +} + +int KRB5_LIB_FUNCTION +krb5_verify_opt_alloc(krb5_context context, krb5_verify_opt **opt) +{ + *opt = calloc(1, sizeof(**opt)); + if ((*opt) == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + krb5_verify_opt_init(*opt); + return 0; +} + +void KRB5_LIB_FUNCTION +krb5_verify_opt_free(krb5_verify_opt *opt) +{ + free(opt); +} + +void KRB5_LIB_FUNCTION +krb5_verify_opt_set_ccache(krb5_verify_opt *opt, krb5_ccache ccache) +{ + opt->ccache = ccache; +} + +void KRB5_LIB_FUNCTION +krb5_verify_opt_set_keytab(krb5_verify_opt *opt, krb5_keytab keytab) +{ + opt->keytab = keytab; +} + +void KRB5_LIB_FUNCTION +krb5_verify_opt_set_secure(krb5_verify_opt *opt, krb5_boolean secure) +{ + opt->secure = secure; +} + +void KRB5_LIB_FUNCTION +krb5_verify_opt_set_service(krb5_verify_opt *opt, const char *service) +{ + opt->service = service; +} + +void KRB5_LIB_FUNCTION +krb5_verify_opt_set_flags(krb5_verify_opt *opt, unsigned int flags) +{ + opt->flags |= flags; +} + +static krb5_error_code +verify_user_opt_int(krb5_context context, + krb5_principal principal, + const char *password, + krb5_verify_opt *vopt) + +{ + krb5_error_code ret; + krb5_get_init_creds_opt *opt; + krb5_creds cred; + + ret = krb5_get_init_creds_opt_alloc (context, &opt); + if (ret) + return ret; + krb5_get_init_creds_opt_set_default_flags(context, NULL, + krb5_principal_get_realm(context, principal), + opt); + ret = krb5_get_init_creds_password (context, + &cred, + principal, + password, + krb5_prompter_posix, + NULL, + 0, + NULL, + opt); + krb5_get_init_creds_opt_free(context, opt); + if(ret) + return ret; +#define OPT(V, D) ((vopt && (vopt->V)) ? (vopt->V) : (D)) + return verify_common (context, principal, OPT(ccache, NULL), + OPT(keytab, NULL), vopt ? vopt->secure : TRUE, + OPT(service, "host"), cred); +#undef OPT +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_verify_user_opt(krb5_context context, + krb5_principal principal, + const char *password, + krb5_verify_opt *opt) +{ + krb5_error_code ret; + + if(opt && (opt->flags & KRB5_VERIFY_LREALMS)) { + krb5_realm *realms, *r; + ret = krb5_get_default_realms (context, &realms); + if (ret) + return ret; + ret = KRB5_CONFIG_NODEFREALM; + + for (r = realms; *r != NULL && ret != 0; ++r) { + char *tmp = strdup (*r); + + if (tmp == NULL) { + krb5_free_host_realm (context, realms); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + free (*krb5_princ_realm (context, principal)); + krb5_princ_set_realm (context, principal, &tmp); + + ret = verify_user_opt_int(context, principal, password, opt); + } + krb5_free_host_realm (context, realms); + if(ret) + return ret; + } else + ret = verify_user_opt_int(context, principal, password, opt); + return ret; +} + +/* compat function that calls above */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_verify_user(krb5_context context, + krb5_principal principal, + krb5_ccache ccache, + const char *password, + krb5_boolean secure, + const char *service) +{ + krb5_verify_opt opt; + + krb5_verify_opt_init(&opt); + + krb5_verify_opt_set_ccache(&opt, ccache); + krb5_verify_opt_set_secure(&opt, secure); + krb5_verify_opt_set_service(&opt, service); + + return krb5_verify_user_opt(context, principal, password, &opt); +} + +/* + * A variant of `krb5_verify_user'. The realm of `principal' is + * ignored and all the local realms are tried. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_verify_user_lrealm(krb5_context context, + krb5_principal principal, + krb5_ccache ccache, + const char *password, + krb5_boolean secure, + const char *service) +{ + krb5_verify_opt opt; + + krb5_verify_opt_init(&opt); + + krb5_verify_opt_set_ccache(&opt, ccache); + krb5_verify_opt_set_secure(&opt, secure); + krb5_verify_opt_set_service(&opt, service); + krb5_verify_opt_set_flags(&opt, KRB5_VERIFY_LREALMS); + + return krb5_verify_user_opt(context, principal, password, &opt); +} diff --git a/lib/krb5/version-script.map b/lib/krb5/version-script.map new file mode 100644 index 0000000..df8804a --- /dev/null +++ b/lib/krb5/version-script.map @@ -0,0 +1,722 @@ +# $Id$ + +HEIMDAL_KRB5_1.0 { + global: + krb524_convert_creds_kdc; + krb524_convert_creds_kdc_ccache; + krb5_425_conv_principal; + krb5_425_conv_principal_ext2; + krb5_425_conv_principal_ext; + krb5_524_conv_principal; + krb5_abort; + krb5_abortx; + krb5_acl_match_file; + krb5_acl_match_string; + krb5_add_et_list; + krb5_add_extra_addresses; + krb5_add_ignore_addresses; + krb5_addlog_dest; + krb5_addlog_func; + krb5_addr2sockaddr; + krb5_address_compare; + krb5_address_order; + krb5_address_prefixlen_boundary; + krb5_address_search; + krb5_aname_to_localname; + krb5_anyaddr; + krb5_appdefault_boolean; + krb5_appdefault_string; + krb5_appdefault_time; + krb5_append_addresses; + krb5_auth_con_addflags; + krb5_auth_con_free; + krb5_auth_con_genaddrs; + krb5_auth_con_generatelocalsubkey; + krb5_auth_con_getaddrs; + krb5_auth_con_getauthenticator; + krb5_auth_con_getcksumtype; + krb5_auth_con_getflags; + krb5_auth_con_getkey; + krb5_auth_con_getkeytype; + krb5_auth_con_getlocalseqnumber; + krb5_auth_con_getlocalsubkey; + krb5_auth_con_getrcache; + krb5_auth_con_getremotesubkey; + krb5_auth_con_init; + krb5_auth_con_removeflags; + krb5_auth_con_setaddrs; + krb5_auth_con_setaddrs_from_fd; + krb5_auth_con_setcksumtype; + krb5_auth_con_setflags; + krb5_auth_con_setkey; + krb5_auth_con_setkeytype; + krb5_auth_con_setlocalseqnumber; + krb5_auth_con_setlocalsubkey; + krb5_auth_con_setrcache; + krb5_auth_con_setremoteseqnumber; + krb5_auth_con_setremotesubkey; + krb5_auth_con_setuserkey; + krb5_auth_getremoteseqnumber; + krb5_build_ap_req; + krb5_build_authenticator; + krb5_build_principal; + krb5_build_principal_ext; + krb5_build_principal_va; + krb5_build_principal_va_ext; + krb5_c_block_size; + krb5_c_checksum_length; + krb5_c_decrypt; + krb5_c_encrypt; + krb5_c_encrypt_length; + krb5_c_enctype_compare; + krb5_c_get_checksum; + krb5_c_is_coll_proof_cksum; + krb5_c_is_keyed_cksum; + krb5_c_keylengths; + krb5_c_make_checksum; + krb5_c_make_random_key; + krb5_c_prf; + krb5_c_prf_length; + krb5_c_set_checksum; + krb5_c_valid_cksumtype; + krb5_c_valid_enctype; + krb5_c_verify_checksum; + krb5_cc_cache_end_seq_get; + krb5_cc_cache_get_first; + krb5_cc_cache_match; + krb5_cc_cache_next; + krb5_cc_clear_mcred; + krb5_cc_close; + krb5_cc_copy_cache; + krb5_cc_copy_cache_match; + krb5_cc_default; + krb5_cc_default_name; + krb5_cc_destroy; + krb5_cc_end_seq_get; + krb5_cc_gen_new; + krb5_cc_get_full_name; + krb5_cc_get_name; + krb5_cc_get_ops; + krb5_cc_get_prefix_ops; + krb5_cc_get_principal; + krb5_cc_get_type; + krb5_cc_get_version; + krb5_cc_initialize; + krb5_cc_move; + krb5_cc_new_unique; + krb5_cc_next_cred; + krb5_cc_next_cred_match; + krb5_cc_register; + krb5_cc_remove_cred; + krb5_cc_resolve; + krb5_cc_retrieve_cred; + krb5_cc_set_default_name; + krb5_cc_set_flags; + krb5_cc_start_seq_get; + krb5_cc_store_cred; + krb5_change_password; + krb5_check_transited; + krb5_check_transited_realms; + krb5_checksum_disable; + krb5_checksum_free; + krb5_checksum_is_collision_proof; + krb5_checksum_is_keyed; + krb5_checksumsize; + krb5_cksumtype_valid; + krb5_clear_error_string; + krb5_closelog; + krb5_compare_creds; + krb5_config_file_free; + krb5_config_free_strings; + krb5_config_get; + krb5_config_get_bool; + krb5_config_get_bool_default; + krb5_config_get_int; + krb5_config_get_int_default; + krb5_config_get_list; + krb5_config_get_next; + krb5_config_get_string; + krb5_config_get_string_default; + krb5_config_get_strings; + krb5_config_get_time; + krb5_config_get_time_default; + krb5_config_parse_file; + krb5_config_parse_file_multi; + krb5_config_parse_string_multi; + krb5_config_vget; + krb5_config_vget_bool; + krb5_config_vget_bool_default; + krb5_config_vget_int; + krb5_config_vget_int_default; + krb5_config_vget_list; + krb5_config_vget_next; + krb5_config_vget_string; + krb5_config_vget_string_default; + krb5_config_vget_strings; + krb5_config_vget_time; + krb5_config_vget_time_default; + krb5_copy_address; + krb5_copy_addresses; + krb5_copy_checksum; + krb5_copy_creds; + krb5_copy_creds_contents; + krb5_copy_data; + krb5_copy_host_realm; + krb5_copy_keyblock; + krb5_copy_keyblock_contents; + krb5_copy_principal; + krb5_copy_ticket; + krb5_create_checksum; + krb5_crypto_destroy; + krb5_crypto_get_checksum_type; + krb5_crypto_getblocksize; + krb5_crypto_getconfoundersize; + krb5_crypto_getenctype; + krb5_crypto_getpadsize; + krb5_crypto_init; + krb5_crypto_overhead; + krb5_crypto_prf; + krb5_crypto_prf_length; + krb5_data_alloc; + krb5_data_cmp; + krb5_data_copy; + krb5_data_free; + krb5_data_realloc; + krb5_data_zero; + krb5_decode_Authenticator; + krb5_decode_ETYPE_INFO2; + krb5_decode_ETYPE_INFO; + krb5_decode_EncAPRepPart; + krb5_decode_EncASRepPart; + krb5_decode_EncKrbCredPart; + krb5_decode_EncTGSRepPart; + krb5_decode_EncTicketPart; + krb5_decode_ap_req; + krb5_decrypt; + krb5_decrypt_EncryptedData; + krb5_decrypt_ivec; + krb5_decrypt_ticket; + krb5_derive_key; + krb5_digest_alloc; + krb5_digest_free; + krb5_digest_get_client_binding; + krb5_digest_get_identifier; + krb5_digest_get_opaque; + krb5_digest_get_rsp; + krb5_digest_get_server_nonce; + krb5_digest_get_session_key; + krb5_digest_get_tickets; + krb5_digest_init_request; + krb5_digest_probe; + krb5_digest_rep_get_status; + krb5_digest_request; + krb5_digest_set_authentication_user; + krb5_digest_set_authid; + krb5_digest_set_client_nonce; + krb5_digest_set_digest; + krb5_digest_set_hostname; + krb5_digest_set_identifier; + krb5_digest_set_method; + krb5_digest_set_nonceCount; + krb5_digest_set_opaque; + krb5_digest_set_qop; + krb5_digest_set_realm; + krb5_digest_set_responseData; + krb5_digest_set_server_cb; + krb5_digest_set_server_nonce; + krb5_digest_set_type; + krb5_digest_set_uri; + krb5_digest_set_username; + krb5_domain_x500_decode; + krb5_domain_x500_encode; + krb5_eai_to_heim_errno; + krb5_encode_Authenticator; + krb5_encode_ETYPE_INFO2; + krb5_encode_ETYPE_INFO; + krb5_encode_EncAPRepPart; + krb5_encode_EncASRepPart; + krb5_encode_EncKrbCredPart; + krb5_encode_EncTGSRepPart; + krb5_encode_EncTicketPart; + krb5_encrypt; + krb5_encrypt_EncryptedData; + krb5_encrypt_ivec; + krb5_enctype_disable; + krb5_enctype_keybits; + krb5_enctype_keysize; + krb5_enctype_to_keytype; + krb5_enctype_to_string; + krb5_enctype_valid; + krb5_enctypes_compatible_keys; + krb5_err; + krb5_error_from_rd_error; + krb5_errx; + krb5_expand_hostname; + krb5_expand_hostname_realms; + krb5_find_padata; + krb5_format_time; + krb5_free_address; + krb5_free_addresses; + krb5_free_ap_rep_enc_part; + krb5_free_authenticator; + krb5_free_checksum; + krb5_free_checksum_contents; + krb5_free_config_files; + krb5_free_context; + krb5_free_cred_contents; + krb5_free_creds; + krb5_free_creds_contents; + krb5_free_data; + krb5_free_data_contents; + krb5_free_error; + krb5_free_error_contents; + krb5_free_error_string; + krb5_free_host_realm; + krb5_free_kdc_rep; + krb5_free_keyblock; + krb5_free_keyblock_contents; + krb5_free_krbhst; + krb5_free_principal; + krb5_free_salt; + krb5_free_ticket; + krb5_fwd_tgt_creds; + krb5_generate_random_block; + krb5_generate_random_keyblock; + krb5_generate_seq_number; + krb5_generate_subkey; + krb5_generate_subkey_extended; + krb5_get_all_client_addrs; + krb5_get_all_server_addrs; + krb5_get_cred_from_kdc; + krb5_get_cred_from_kdc_opt; + krb5_get_credentials; + krb5_get_credentials_with_flags; + krb5_get_creds; + krb5_get_creds_opt_add_options; + krb5_get_creds_opt_alloc; + krb5_get_creds_opt_free; + krb5_get_creds_opt_set_enctype; + krb5_get_creds_opt_set_impersonate; + krb5_get_creds_opt_set_options; + krb5_get_creds_opt_set_ticket; + krb5_get_default_config_files; + krb5_get_default_in_tkt_etypes; + krb5_get_default_principal; + krb5_get_default_realm; + krb5_get_default_realms; + krb5_get_dns_canonicalize_hostname; + krb5_get_err_text; + krb5_get_error_message; + krb5_get_error_string; + krb5_get_extra_addresses; + krb5_get_fcache_version; + krb5_get_forwarded_creds; + krb5_get_host_realm; + krb5_get_ignore_addresses; + krb5_get_in_cred; + krb5_get_in_tkt; + krb5_get_in_tkt_with_keytab; + krb5_get_in_tkt_with_password; + krb5_get_in_tkt_with_skey; + krb5_get_init_creds; + krb5_get_init_creds_keyblock; + krb5_get_init_creds_keytab; + krb5_get_init_creds_opt_alloc; + krb5_get_init_creds_opt_free; + krb5_get_init_creds_opt_get_error; + krb5_get_init_creds_opt_init; + krb5_get_init_creds_opt_set_address_list; + krb5_get_init_creds_opt_set_addressless; + krb5_get_init_creds_opt_set_anonymous; + krb5_get_init_creds_opt_set_canonicalize; + krb5_get_init_creds_opt_set_default_flags; + krb5_get_init_creds_opt_set_etype_list; + krb5_get_init_creds_opt_set_forwardable; + krb5_get_init_creds_opt_set_pa_password; + krb5_get_init_creds_opt_set_pac_request; + krb5_get_init_creds_opt_set_pkinit; + krb5_get_init_creds_opt_set_preauth_list; + krb5_get_init_creds_opt_set_proxiable; + krb5_get_init_creds_opt_set_renew_life; + krb5_get_init_creds_opt_set_salt; + krb5_get_init_creds_opt_set_tkt_life; + krb5_get_init_creds_opt_set_win2k; + krb5_get_init_creds_password; + krb5_get_kdc_cred; + krb5_get_kdc_sec_offset; + krb5_get_krb524hst; + krb5_get_krb_admin_hst; + krb5_get_krb_changepw_hst; + krb5_get_krbhst; + krb5_get_max_time_skew; + krb5_get_pw_salt; + krb5_get_renewed_creds; + krb5_get_server_rcache; + krb5_get_use_admin_kdc; + krb5_get_warn_dest; + krb5_get_wrapped_length; + krb5_getportbyname; + krb5_h_addr2addr; + krb5_h_addr2sockaddr; + krb5_h_errno_to_heim_errno; + krb5_have_error_string; + krb5_hmac; + krb5_init_context; + krb5_init_ets; + krb5_init_etype; + krb5_initlog; + krb5_is_thread_safe; + krb5_kerberos_enctypes; + krb5_keyblock_get_enctype; + krb5_keyblock_init; + krb5_keyblock_key_proc; + krb5_keyblock_zero; + krb5_keytab_key_proc; + krb5_keytype_to_enctypes; + krb5_keytype_to_enctypes_default; + krb5_keytype_to_string; + krb5_krbhst_format_string; + krb5_krbhst_free; + krb5_krbhst_get_addrinfo; + krb5_krbhst_init; + krb5_krbhst_init_flags; + krb5_krbhst_next; + krb5_krbhst_next_as_string; + krb5_krbhst_reset; + krb5_kt_add_entry; + krb5_kt_close; + krb5_kt_compare; + krb5_kt_copy_entry_contents; + krb5_kt_default; + krb5_kt_default_modify_name; + krb5_kt_default_name; + krb5_kt_end_seq_get; + krb5_kt_free_entry; + krb5_kt_get_entry; + krb5_kt_get_full_name; + krb5_kt_get_name; + krb5_kt_get_type; + krb5_kt_next_entry; + krb5_kt_read_service_key; + krb5_kt_register; + krb5_kt_remove_entry; + krb5_kt_resolve; + krb5_kt_start_seq_get; + krb5_kuserok; + krb5_log; + krb5_log_msg; + krb5_make_addrport; + krb5_make_principal; + krb5_max_sockaddr_size; + krb5_mk_error; + krb5_mk_priv; + krb5_mk_rep; + krb5_mk_req; + krb5_mk_req_exact; + krb5_mk_req_extended; + krb5_mk_safe; + krb5_net_read; + krb5_net_write; + krb5_net_write_block; + krb5_ntlm_alloc; + krb5_ntlm_free; + krb5_ntlm_init_get_challange; + krb5_ntlm_init_get_flags; + krb5_ntlm_init_get_opaque; + krb5_ntlm_init_get_targetinfo; + krb5_ntlm_init_get_targetname; + krb5_ntlm_init_request; + krb5_ntlm_rep_get_sessionkey; + krb5_ntlm_rep_get_status; + krb5_ntlm_req_set_flags; + krb5_ntlm_req_set_lm; + krb5_ntlm_req_set_ntlm; + krb5_ntlm_req_set_opaque; + krb5_ntlm_req_set_session; + krb5_ntlm_req_set_targetname; + krb5_ntlm_req_set_username; + krb5_ntlm_request; + krb5_openlog; + krb5_pac_add_buffer; + krb5_pac_free; + krb5_pac_get_buffer; + krb5_pac_get_types; + krb5_pac_init; + krb5_pac_parse; + krb5_pac_verify; + krb5_padata_add; + krb5_parse_address; + krb5_parse_name; + krb5_parse_name_flags; + krb5_parse_nametype; + krb5_passwd_result_to_string; + krb5_password_key_proc; + krb5_plugin_register; + krb5_prepend_config_files; + krb5_prepend_config_files_default; + krb5_princ_realm; + krb5_princ_set_realm; + krb5_principal_compare; + krb5_principal_compare_any_realm; + krb5_principal_get_comp_string; + krb5_principal_get_realm; + krb5_principal_get_type; + krb5_principal_match; + krb5_principal_set_type; + krb5_print_address; + krb5_program_setup; + krb5_prompter_posix; + krb5_random_to_key; + krb5_rc_close; + krb5_rc_default; + krb5_rc_default_name; + krb5_rc_default_type; + krb5_rc_destroy; + krb5_rc_expunge; + krb5_rc_get_lifespan; + krb5_rc_get_name; + krb5_rc_get_type; + krb5_rc_initialize; + krb5_rc_recover; + krb5_rc_resolve; + krb5_rc_resolve_full; + krb5_rc_resolve_type; + krb5_rc_store; + krb5_rd_cred2; + krb5_rd_cred; + krb5_rd_error; + krb5_rd_priv; + krb5_rd_rep; + krb5_rd_req; + krb5_rd_req_ctx; + krb5_rd_req_in_ctx_alloc; + krb5_rd_req_in_ctx_free; + krb5_rd_req_in_set_keyblock; + krb5_rd_req_in_set_keytab; + krb5_rd_req_in_set_pac_check; + krb5_rd_req_out_ctx_free; + krb5_rd_req_out_get_ap_req_options; + krb5_rd_req_out_get_keyblock; + krb5_rd_req_out_get_ticket; + krb5_rd_req_with_keyblock; + krb5_rd_safe; + krb5_read_message; + krb5_read_priv_message; + krb5_read_safe_message; + krb5_realm_compare; + krb5_recvauth; + krb5_recvauth_match_version; + krb5_ret_address; + krb5_ret_addrs; + krb5_ret_authdata; + krb5_ret_creds; + krb5_ret_creds_tag; + krb5_ret_data; + krb5_ret_int16; + krb5_ret_int32; + krb5_ret_int8; + krb5_ret_keyblock; + krb5_ret_principal; + krb5_ret_string; + krb5_ret_stringnl; + krb5_ret_stringz; + krb5_ret_times; + krb5_ret_uint16; + krb5_ret_uint32; + krb5_ret_uint8; + krb5_salttype_to_string; + krb5_sendauth; + krb5_sendto; + krb5_sendto_context; + krb5_sendto_ctx_add_flags; + krb5_sendto_ctx_alloc; + krb5_sendto_ctx_free; + krb5_sendto_ctx_get_flags; + krb5_sendto_ctx_set_func; + krb5_sendto_ctx_set_type; + krb5_sendto_kdc; + krb5_sendto_kdc_flags; + krb5_set_config_files; + krb5_set_default_in_tkt_etypes; + krb5_set_default_realm; + krb5_set_dns_canonicalize_hostname; + krb5_set_error_string; + krb5_set_extra_addresses; + krb5_set_fcache_version; + krb5_set_ignore_addresses; + krb5_set_max_time_skew; + krb5_set_password; + krb5_set_password_using_ccache; + krb5_set_real_time; + krb5_set_send_to_kdc_func; + krb5_set_use_admin_kdc; + krb5_set_warn_dest; + krb5_sname_to_principal; + krb5_sock_to_principal; + krb5_sockaddr2address; + krb5_sockaddr2port; + krb5_sockaddr_uninteresting; + krb5_std_usage; + krb5_storage_clear_flags; + krb5_storage_emem; + krb5_storage_free; + krb5_storage_from_data; + krb5_storage_from_fd; + krb5_storage_from_mem; + krb5_storage_from_readonly_mem; + krb5_storage_get_byteorder; + krb5_storage_is_flags; + krb5_storage_read; + krb5_storage_seek; + krb5_storage_set_byteorder; + krb5_storage_set_eof_code; + krb5_storage_set_flags; + krb5_storage_to_data; + krb5_storage_write; + krb5_store_address; + krb5_store_addrs; + krb5_store_authdata; + krb5_store_creds; + krb5_store_creds_tag; + krb5_store_data; + krb5_store_int16; + krb5_store_int32; + krb5_store_int8; + krb5_store_keyblock; + krb5_store_principal; + krb5_store_string; + krb5_store_stringnl; + krb5_store_stringz; + krb5_store_times; + krb5_store_uint16; + krb5_store_uint32; + krb5_store_uint8; + krb5_string_to_deltat; + krb5_string_to_enctype; + krb5_string_to_key; + krb5_string_to_key_data; + krb5_string_to_key_data_salt; + krb5_string_to_key_data_salt_opaque; + krb5_string_to_key_derived; + krb5_string_to_key_salt; + krb5_string_to_key_salt_opaque; + krb5_string_to_keytype; + krb5_string_to_salttype; + krb5_ticket_get_authorization_data_type; + krb5_ticket_get_client; + krb5_ticket_get_endtime; + krb5_ticket_get_server; + krb5_timeofday; + krb5_unparse_name; + krb5_unparse_name_fixed; + krb5_unparse_name_fixed_flags; + krb5_unparse_name_fixed_short; + krb5_unparse_name_flags; + krb5_unparse_name_short; + krb5_us_timeofday; + krb5_vabort; + krb5_vabortx; + krb5_verify_ap_req2; + krb5_verify_ap_req; + krb5_verify_authenticator_checksum; + krb5_verify_checksum; + krb5_verify_init_creds; + krb5_verify_init_creds_opt_init; + krb5_verify_init_creds_opt_set_ap_req_nofail; + krb5_verify_opt_alloc; + krb5_verify_opt_free; + krb5_verify_opt_init; + krb5_verify_opt_set_ccache; + krb5_verify_opt_set_flags; + krb5_verify_opt_set_keytab; + krb5_verify_opt_set_secure; + krb5_verify_opt_set_service; + krb5_verify_user; + krb5_verify_user_lrealm; + krb5_verify_user_opt; + krb5_verr; + krb5_verrx; + krb5_vlog; + krb5_vlog_msg; + krb5_vset_error_string; + krb5_vwarn; + krb5_vwarnx; + krb5_warn; + krb5_warnx; + krb5_write_message; + krb5_write_priv_message; + krb5_write_safe_message; + krb5_xfree; + + # com_err error tables + initialize_krb5_error_table_r; + initialize_krb5_error_table; + initialize_krb_error_table_r; + initialize_krb_error_table; + initialize_heim_error_table_r; + initialize_heim_error_table; + initialize_k524_error_table_r; + initialize_k524_error_table; + + # variables + krb5_mcc_ops; + krb5_acc_ops; + krb5_fcc_ops; + krb5_kcm_ops; + krb4_fkt_ops; + krb5_wrfkt_ops; + krb5_mkt_ops; + krb5_fkt_ops; + krb5_akf_ops; + krb5_srvtab_fkt_ops; + krb5_any_ops; + heimdal_version; + heimdal_long_version; + krb5_config_file; + krb5_defkeyname; + + # Shared with GSSAPI krb5 + _krb5_crc_init_table; + _krb5_crc_update; + + # V4 compat glue + _krb5_krb_tf_setup; + _krb5_krb_dest_tkt; + _krb5_krb_life_to_time; + _krb5_krb_decomp_ticket; + _krb5_krb_decomp_ticket; + _krb5_krb_create_ticket; + _krb5_krb_create_ciph; + _krb5_krb_create_auth_reply; + _krb5_krb_rd_req; + _krb5_krb_free_auth_data; + _krb5_krb_time_to_life; + _krb5_krb_cr_err_reply; + + # Shared with libkdc + _krb5_principalname2krb5_principal; + _krb5_principal2principalname; + _krb5_s4u2self_to_checksumdata; + _krb5_put_int; + _krb5_get_int; + _krb5_pk_load_id; + _krb5_parse_moduli; + _krb5_pk_mk_ContentInfo; + _krb5_dh_group_ok; + _krb5_pk_octetstring2key; + _krb5_pk_allow_proxy_certificate; + _krb5_pac_sign; + _krb5_plugin_find; + _krb5_plugin_get_symbol; + _krb5_plugin_get_next; + _krb5_plugin_free; + _krb5_AES_string_to_default_iterator; + _krb5_get_host_realm_int; + + # testing + _krb5_aes_cts_encrypt; + _krb5_n_fold; + _krb5_expand_default_cc_name; + local: + *; +}; diff --git a/lib/krb5/version.c b/lib/krb5/version.c new file mode 100644 index 0000000..f7ccff5 --- /dev/null +++ b/lib/krb5/version.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 1997 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: version.c 7464 1999-12-02 17:05:13Z joda $"); + +/* this is just to get a version stamp in the library file */ + +#define heimdal_version __heimdal_version +#define heimdal_long_version __heimdal_long_version +#include "version.h" + diff --git a/lib/krb5/warn.c b/lib/krb5/warn.c new file mode 100644 index 0000000..85f143b --- /dev/null +++ b/lib/krb5/warn.c @@ -0,0 +1,211 @@ +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" +#include <err.h> + +RCSID("$Id: warn.c 19086 2006-11-21 08:06:40Z lha $"); + +static krb5_error_code _warnerr(krb5_context context, int do_errtext, + krb5_error_code code, int level, const char *fmt, va_list ap) + __attribute__((__format__(__printf__, 5, 0))); + +static krb5_error_code +_warnerr(krb5_context context, int do_errtext, + krb5_error_code code, int level, const char *fmt, va_list ap) +{ + char xfmt[7] = ""; + const char *args[2], **arg; + char *msg = NULL; + char *err_str = NULL; + + args[0] = args[1] = NULL; + arg = args; + if(fmt){ + strlcat(xfmt, "%s", sizeof(xfmt)); + if(do_errtext) + strlcat(xfmt, ": ", sizeof(xfmt)); + vasprintf(&msg, fmt, ap); + if(msg == NULL) + return ENOMEM; + *arg++ = msg; + } + if(context && do_errtext){ + const char *err_msg; + + strlcat(xfmt, "%s", sizeof(xfmt)); + + err_str = krb5_get_error_string(context); + if (err_str != NULL) { + *arg++ = err_str; + } else { + err_msg = krb5_get_err_text(context, code); + if (err_msg) + *arg++ = err_msg; + else + *arg++ = "<unknown error>"; + } + } + + if(context && context->warn_dest) + krb5_log(context, context->warn_dest, level, xfmt, args[0], args[1]); + else + warnx(xfmt, args[0], args[1]); + free(msg); + free(err_str); + return 0; +} + +#define FUNC(ETEXT, CODE, LEVEL) \ + krb5_error_code ret; \ + va_list ap; \ + va_start(ap, fmt); \ + ret = _warnerr(context, ETEXT, CODE, LEVEL, fmt, ap); \ + va_end(ap); + +#undef __attribute__ +#define __attribute__(X) + +krb5_error_code KRB5_LIB_FUNCTION +krb5_vwarn(krb5_context context, krb5_error_code code, + const char *fmt, va_list ap) + __attribute__ ((format (printf, 3, 0))) +{ + return _warnerr(context, 1, code, 1, fmt, ap); +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_warn(krb5_context context, krb5_error_code code, const char *fmt, ...) + __attribute__ ((format (printf, 3, 4))) +{ + FUNC(1, code, 1); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_vwarnx(krb5_context context, const char *fmt, va_list ap) + __attribute__ ((format (printf, 2, 0))) +{ + return _warnerr(context, 0, 0, 1, fmt, ap); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_warnx(krb5_context context, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))) +{ + FUNC(0, 0, 1); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_verr(krb5_context context, int eval, krb5_error_code code, + const char *fmt, va_list ap) + __attribute__ ((noreturn, format (printf, 4, 0))) +{ + _warnerr(context, 1, code, 0, fmt, ap); + exit(eval); +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_err(krb5_context context, int eval, krb5_error_code code, + const char *fmt, ...) + __attribute__ ((noreturn, format (printf, 4, 5))) +{ + FUNC(1, code, 0); + exit(eval); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_verrx(krb5_context context, int eval, const char *fmt, va_list ap) + __attribute__ ((noreturn, format (printf, 3, 0))) +{ + _warnerr(context, 0, 0, 0, fmt, ap); + exit(eval); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_errx(krb5_context context, int eval, const char *fmt, ...) + __attribute__ ((noreturn, format (printf, 3, 4))) +{ + FUNC(0, 0, 0); + exit(eval); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_vabort(krb5_context context, krb5_error_code code, + const char *fmt, va_list ap) + __attribute__ ((noreturn, format (printf, 3, 0))) +{ + _warnerr(context, 1, code, 0, fmt, ap); + abort(); +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_abort(krb5_context context, krb5_error_code code, const char *fmt, ...) + __attribute__ ((noreturn, format (printf, 3, 4))) +{ + FUNC(1, code, 0); + abort(); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_vabortx(krb5_context context, const char *fmt, va_list ap) + __attribute__ ((noreturn, format (printf, 2, 0))) +{ + _warnerr(context, 0, 0, 0, fmt, ap); + abort(); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_abortx(krb5_context context, const char *fmt, ...) + __attribute__ ((noreturn, format (printf, 2, 3))) +{ + FUNC(0, 0, 0); + abort(); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_warn_dest(krb5_context context, krb5_log_facility *fac) +{ + context->warn_dest = fac; + return 0; +} + +krb5_log_facility * KRB5_LIB_FUNCTION +krb5_get_warn_dest(krb5_context context) +{ + return context->warn_dest; +} diff --git a/lib/krb5/write_message.c b/lib/krb5/write_message.c new file mode 100644 index 0000000..1694a10 --- /dev/null +++ b/lib/krb5/write_message.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5_locl.h" + +RCSID("$Id: write_message.c 17442 2006-05-05 09:31:15Z lha $"); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_write_message (krb5_context context, + krb5_pointer p_fd, + krb5_data *data) +{ + uint32_t len; + uint8_t buf[4]; + int ret; + + len = data->length; + _krb5_put_int(buf, len, 4); + if (krb5_net_write (context, p_fd, buf, 4) != 4 + || krb5_net_write (context, p_fd, data->data, len) != len) { + ret = errno; + krb5_set_error_string (context, "write: %s", strerror(ret)); + return ret; + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_write_priv_message(krb5_context context, + krb5_auth_context ac, + krb5_pointer p_fd, + krb5_data *data) +{ + krb5_error_code ret; + krb5_data packet; + + ret = krb5_mk_priv (context, ac, data, &packet, NULL); + if(ret) + return ret; + ret = krb5_write_message(context, p_fd, &packet); + krb5_data_free(&packet); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_write_safe_message(krb5_context context, + krb5_auth_context ac, + krb5_pointer p_fd, + krb5_data *data) +{ + krb5_error_code ret; + krb5_data packet; + ret = krb5_mk_safe (context, ac, data, &packet, NULL); + if(ret) + return ret; + ret = krb5_write_message(context, p_fd, &packet); + krb5_data_free(&packet); + return ret; +} |