summaryrefslogtreecommitdiffstats
path: root/lib/krb5
diff options
context:
space:
mode:
Diffstat (limited to 'lib/krb5')
-rw-r--r--lib/krb5/Makefile.am298
-rw-r--r--lib/krb5/Makefile.in2021
-rw-r--r--lib/krb5/acache.c961
-rw-r--r--lib/krb5/acl.c293
-rw-r--r--lib/krb5/add_et_list.c50
-rw-r--r--lib/krb5/addr_families.c1463
-rw-r--r--lib/krb5/aes-test.c778
-rw-r--r--lib/krb5/aname_to_localname.c92
-rw-r--r--lib/krb5/appdefault.c142
-rw-r--r--lib/krb5/asn1_glue.c64
-rw-r--r--lib/krb5/auth_context.c519
-rw-r--r--lib/krb5/build_ap_req.c76
-rw-r--r--lib/krb5/build_auth.c202
-rw-r--r--lib/krb5/cache.c1073
-rw-r--r--lib/krb5/changepw.c823
-rw-r--r--lib/krb5/codec.c196
-rw-r--r--lib/krb5/config_file.c771
-rw-r--r--lib/krb5/config_file_netinfo.c180
-rw-r--r--lib/krb5/constants.c43
-rw-r--r--lib/krb5/context.c1033
-rw-r--r--lib/krb5/convert_creds.c204
-rw-r--r--lib/krb5/copy_host_realm.c78
-rw-r--r--lib/krb5/crc.c71
-rw-r--r--lib/krb5/creds.c269
-rw-r--r--lib/krb5/crypto.c4192
-rw-r--r--lib/krb5/data.c224
-rw-r--r--lib/krb5/derived-key-test.c123
-rw-r--r--lib/krb5/digest.c1199
-rw-r--r--lib/krb5/doxygen.c67
-rw-r--r--lib/krb5/dump_config.c71
-rw-r--r--lib/krb5/eai_to_heim_errno.c114
-rw-r--r--lib/krb5/error_string.c155
-rw-r--r--lib/krb5/expand_hostname.c160
-rw-r--r--lib/krb5/fcache.c881
-rw-r--r--lib/krb5/free.c53
-rw-r--r--lib/krb5/free_host_realm.c54
-rw-r--r--lib/krb5/generate_seq_number.c62
-rw-r--r--lib/krb5/generate_subkey.c72
-rw-r--r--lib/krb5/get_addrs.c291
-rw-r--r--lib/krb5/get_cred.c1277
-rw-r--r--lib/krb5/get_default_principal.c115
-rw-r--r--lib/krb5/get_default_realm.c84
-rw-r--r--lib/krb5/get_for_creds.c460
-rw-r--r--lib/krb5/get_host_realm.c257
-rw-r--r--lib/krb5/get_in_tkt.c834
-rw-r--r--lib/krb5/get_in_tkt_pw.c90
-rw-r--r--lib/krb5/get_in_tkt_with_keytab.c99
-rw-r--r--lib/krb5/get_in_tkt_with_skey.c82
-rw-r--r--lib/krb5/get_port.c54
-rw-r--r--lib/krb5/heim_err.et44
-rw-r--r--lib/krb5/heim_threads.h175
-rw-r--r--lib/krb5/init_creds.c442
-rw-r--r--lib/krb5/init_creds_pw.c1658
-rw-r--r--lib/krb5/k524_err.et20
-rw-r--r--lib/krb5/kcm.c1122
-rw-r--r--lib/krb5/kcm.h69
-rw-r--r--lib/krb5/kerberos.8107
-rw-r--r--lib/krb5/keyblock.c133
-rw-r--r--lib/krb5/keytab.c528
-rw-r--r--lib/krb5/keytab_any.c255
-rw-r--r--lib/krb5/keytab_file.c696
-rw-r--r--lib/krb5/keytab_keyfile.c420
-rw-r--r--lib/krb5/keytab_krb4.c448
-rw-r--r--lib/krb5/keytab_memory.c234
-rw-r--r--lib/krb5/krb5-private.h447
-rw-r--r--lib/krb5/krb5-protos.h4114
-rw-r--r--lib/krb5/krb5-v4compat.h132
-rw-r--r--lib/krb5/krb5.3526
-rw-r--r--lib/krb5/krb5.conf.5530
-rw-r--r--lib/krb5/krb5.h780
-rw-r--r--lib/krb5/krb5.moduli3
-rw-r--r--lib/krb5/krb524_convert_creds_kdc.386
-rw-r--r--lib/krb5/krb5_425_conv_principal.3224
-rw-r--r--lib/krb5/krb5_acl_match_file.3111
-rw-r--r--lib/krb5/krb5_address.3359
-rw-r--r--lib/krb5/krb5_aname_to_localname.380
-rw-r--r--lib/krb5/krb5_appdefault.388
-rw-r--r--lib/krb5/krb5_auth_context.3395
-rw-r--r--lib/krb5/krb5_build_principal.3101
-rw-r--r--lib/krb5/krb5_c_make_checksum.3297
-rw-r--r--lib/krb5/krb5_ccache.3517
-rw-r--r--lib/krb5/krb5_ccapi.h230
-rw-r--r--lib/krb5/krb5_check_transited.3106
-rw-r--r--lib/krb5/krb5_compare_creds.3104
-rw-r--r--lib/krb5/krb5_config.3307
-rw-r--r--lib/krb5/krb5_context.356
-rw-r--r--lib/krb5/krb5_create_checksum.3226
-rw-r--r--lib/krb5/krb5_creds.3119
-rw-r--r--lib/krb5/krb5_crypto_init.367
-rw-r--r--lib/krb5/krb5_data.3159
-rw-r--r--lib/krb5/krb5_digest.3260
-rw-r--r--lib/krb5/krb5_eai_to_heim_errno.368
-rw-r--r--lib/krb5/krb5_encrypt.3278
-rw-r--r--lib/krb5/krb5_err.et266
-rw-r--r--lib/krb5/krb5_expand_hostname.393
-rw-r--r--lib/krb5/krb5_find_padata.387
-rw-r--r--lib/krb5/krb5_free_addresses.353
-rw-r--r--lib/krb5/krb5_free_principal.358
-rw-r--r--lib/krb5/krb5_generate_random_block.357
-rw-r--r--lib/krb5/krb5_get_all_client_addrs.374
-rw-r--r--lib/krb5/krb5_get_credentials.3208
-rw-r--r--lib/krb5/krb5_get_creds.3173
-rw-r--r--lib/krb5/krb5_get_forwarded_creds.379
-rw-r--r--lib/krb5/krb5_get_in_cred.3274
-rw-r--r--lib/krb5/krb5_get_init_creds.3398
-rw-r--r--lib/krb5/krb5_get_krbhst.386
-rw-r--r--lib/krb5/krb5_getportbyname.367
-rw-r--r--lib/krb5/krb5_init_context.3308
-rw-r--r--lib/krb5/krb5_is_thread_safe.358
-rw-r--r--lib/krb5/krb5_keyblock.3218
-rw-r--r--lib/krb5/krb5_keytab.3482
-rw-r--r--lib/krb5/krb5_krbhst_init.3174
-rw-r--r--lib/krb5/krb5_kuserok.3103
-rw-r--r--lib/krb5/krb5_locl.h267
-rw-r--r--lib/krb5/krb5_mk_req.3187
-rw-r--r--lib/krb5/krb5_mk_safe.382
-rw-r--r--lib/krb5/krb5_openlog.3242
-rw-r--r--lib/krb5/krb5_parse_name.368
-rw-r--r--lib/krb5/krb5_principal.3384
-rw-r--r--lib/krb5/krb5_principal_get_realm.381
-rw-r--r--lib/krb5/krb5_rcache.3163
-rw-r--r--lib/krb5/krb5_rd_error.398
-rw-r--r--lib/krb5/krb5_rd_safe.381
-rw-r--r--lib/krb5/krb5_set_default_realm.3164
-rw-r--r--lib/krb5/krb5_set_password.3143
-rw-r--r--lib/krb5/krb5_sname_to_principal.385
-rw-r--r--lib/krb5/krb5_storage.3427
-rw-r--r--lib/krb5/krb5_string_to_key.3156
-rw-r--r--lib/krb5/krb5_ticket.3137
-rw-r--r--lib/krb5/krb5_timeofday.3118
-rw-r--r--lib/krb5/krb5_unparse_name.362
-rw-r--r--lib/krb5/krb5_verify_init_creds.3103
-rw-r--r--lib/krb5/krb5_verify_user.3241
-rw-r--r--lib/krb5/krb5_warn.3233
-rw-r--r--lib/krb5/krb_err.et63
-rw-r--r--lib/krb5/krbhst-test.c104
-rw-r--r--lib/krb5/krbhst.c1010
-rw-r--r--lib/krb5/kuserok.c262
-rw-r--r--lib/krb5/locate_plugin.h64
-rw-r--r--lib/krb5/log.c471
-rw-r--r--lib/krb5/mcache.c477
-rw-r--r--lib/krb5/misc.c86
-rw-r--r--lib/krb5/mit_glue.c369
-rw-r--r--lib/krb5/mk_error.c92
-rw-r--r--lib/krb5/mk_priv.c155
-rw-r--r--lib/krb5/mk_rep.c126
-rw-r--r--lib/krb5/mk_req.c116
-rw-r--r--lib/krb5/mk_req_ext.c165
-rw-r--r--lib/krb5/mk_safe.c141
-rw-r--r--lib/krb5/n-fold-test.c121
-rw-r--r--lib/krb5/n-fold.c137
-rw-r--r--lib/krb5/name-45-test.c294
-rw-r--r--lib/krb5/net_read.c47
-rw-r--r--lib/krb5/net_write.c105
-rw-r--r--lib/krb5/pac.c1041
-rw-r--r--lib/krb5/padata.c66
-rw-r--r--lib/krb5/parse-name-test.c194
-rw-r--r--lib/krb5/pkinit.c2070
-rw-r--r--lib/krb5/plugin.c264
-rw-r--r--lib/krb5/principal.c1254
-rw-r--r--lib/krb5/prog_setup.c66
-rw-r--r--lib/krb5/prompter_posix.c74
-rw-r--r--lib/krb5/rd_cred.c340
-rw-r--r--lib/krb5/rd_error.c123
-rw-r--r--lib/krb5/rd_priv.c185
-rw-r--r--lib/krb5/rd_rep.c124
-rw-r--r--lib/krb5/rd_req.c892
-rw-r--r--lib/krb5/rd_safe.c213
-rw-r--r--lib/krb5/read_message.c106
-rw-r--r--lib/krb5/recvauth.c211
-rw-r--r--lib/krb5/replay.c312
-rw-r--r--lib/krb5/send_to_kdc.c604
-rw-r--r--lib/krb5/sendauth.c233
-rw-r--r--lib/krb5/set_default_realm.c90
-rw-r--r--lib/krb5/sock_principal.c70
-rw-r--r--lib/krb5/store-int.h47
-rw-r--r--lib/krb5/store-test.c118
-rw-r--r--lib/krb5/store.c1035
-rw-r--r--lib/krb5/store_emem.c143
-rw-r--r--lib/krb5/store_fd.c98
-rw-r--r--lib/krb5/store_mem.c150
-rw-r--r--lib/krb5/string-to-key-test.c140
-rw-r--r--lib/krb5/test_acl.c113
-rw-r--r--lib/krb5/test_addr.c202
-rw-r--r--lib/krb5/test_alname.c156
-rw-r--r--lib/krb5/test_cc.c532
-rw-r--r--lib/krb5/test_config.c124
-rw-r--r--lib/krb5/test_crypto.c215
-rw-r--r--lib/krb5/test_crypto_wrapping.c164
-rw-r--r--lib/krb5/test_forward.c136
-rw-r--r--lib/krb5/test_get_addrs.c116
-rw-r--r--lib/krb5/test_hostname.c152
-rw-r--r--lib/krb5/test_keytab.c191
-rw-r--r--lib/krb5/test_kuserok.c106
-rw-r--r--lib/krb5/test_mem.c73
-rw-r--r--lib/krb5/test_pac.c295
-rw-r--r--lib/krb5/test_pkinit_dh2key.c218
-rw-r--r--lib/krb5/test_plugin.c126
-rw-r--r--lib/krb5/test_prf.c102
-rw-r--r--lib/krb5/test_princ.c366
-rw-r--r--lib/krb5/test_renew.c122
-rw-r--r--lib/krb5/test_store.c252
-rw-r--r--lib/krb5/test_time.c87
-rw-r--r--lib/krb5/ticket.c272
-rw-r--r--lib/krb5/time.c114
-rw-r--r--lib/krb5/transited.c503
-rw-r--r--lib/krb5/v4_glue.c939
-rw-r--r--lib/krb5/verify_init.c199
-rw-r--r--lib/krb5/verify_krb5_conf.895
-rw-r--r--lib/krb5/verify_krb5_conf.c676
-rw-r--r--lib/krb5/verify_user.c265
-rw-r--r--lib/krb5/version-script.map722
-rw-r--r--lib/krb5/version.c43
-rw-r--r--lib/krb5/warn.c211
-rw-r--r--lib/krb5/write_message.c89
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, &copy);
+ 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, &copy);
+ 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;
+}
OpenPOWER on IntegriCloud