aboutsummaryrefslogtreecommitdiffstats
path: root/lib/krb5
diff options
context:
space:
mode:
authorStanislav Sedov <stas@FreeBSD.org>2011-09-29 05:23:57 +0000
committerStanislav Sedov <stas@FreeBSD.org>2011-09-29 05:23:57 +0000
commit31f1e9c17ffae440059e8cc532fa26b92d534f7b (patch)
treecf5b65423910d126fddaaf04b885d0de3507d692 /lib/krb5
parentc19800e8cd5640693f36f2040db4ab5e8d738146 (diff)
downloadsrc-31f1e9c17ffae440059e8cc532fa26b92d534f7b.tar.gz
src-31f1e9c17ffae440059e8cc532fa26b92d534f7b.zip
- Flatten the vendor heimdal tree.
Notes
Notes: svn path=/vendor-crypto/heimdal/dist/; revision=225864
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 000000000000..ced9616e162c
--- /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 000000000000..60e09251227f
--- /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 000000000000..30a6d90c3451
--- /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 000000000000..cab68367f80a
--- /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 000000000000..a6005c685903
--- /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 000000000000..f364f5974d47
--- /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 000000000000..82b3431add54
--- /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 000000000000..5800404d9819
--- /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 000000000000..b0bb171f4a14
--- /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 000000000000..b3f775b4bea3
--- /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 000000000000..323f17a24534
--- /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 000000000000..b1968fe817b7
--- /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 000000000000..f8739c044d16
--- /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 000000000000..5db6d2b2cf8a
--- /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 000000000000..703cf43eb6fb
--- /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 000000000000..0d36b4b44268
--- /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 000000000000..ac5eba39dcff
--- /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 000000000000..1e01e7c5ffbc
--- /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 000000000000..5188a1d3a864
--- /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 000000000000..256783310e93
--- /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 000000000000..b2af0187eac3
--- /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 000000000000..8c4f39b4ac4c
--- /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 000000000000..072c29d68974
--- /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 000000000000..17ef46dfa3b6
--- /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 000000000000..2e6349094683
--- /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 000000000000..eda1a8b2598b
--- /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 000000000000..debadb8bb956
--- /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 000000000000..6e612ed6bbb0
--- /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 000000000000..b7c6f8fcfdd0
--- /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 000000000000..074595e2139c
--- /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 000000000000..19315cea8678
--- /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 000000000000..ff6e98a3dcaf
--- /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 000000000000..28e39afb42f7
--- /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