]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
third_party/heimdal: import lorikeet-heimdal-202203010107 (commit 0e7a12404c388e831fe...
authorJoseph Sutton <josephsutton@catalyst.net.nz>
Tue, 1 Mar 2022 01:17:54 +0000 (14:17 +1300)
committerJoseph Sutton <jsutton@samba.org>
Tue, 1 Mar 2022 22:34:34 +0000 (22:34 +0000)
NOTE: THIS COMMIT WON'T COMPILE/WORK ON ITS OWN!

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14995

Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
428 files changed:
third_party/heimdal/.github/workflows/build.yml [deleted file]
third_party/heimdal/.gitignore
third_party/heimdal/Makefile.am
third_party/heimdal/README.md
third_party/heimdal/admin/change.c
third_party/heimdal/appl/afsutil/afslog.c
third_party/heimdal/appl/gssmask/gssmask.c
third_party/heimdal/appl/kf/kf.c
third_party/heimdal/appl/otp/otp.c
third_party/heimdal/appl/test/gssapi_server.c
third_party/heimdal/appl/test/uu_server.c
third_party/heimdal/appveyor.yml
third_party/heimdal/cf/Makefile.am.common
third_party/heimdal/cf/ax_check_sign.m4 [new file with mode: 0644]
third_party/heimdal/cf/check-compile-flag.m4 [new file with mode: 0644]
third_party/heimdal/cf/db.m4
third_party/heimdal/cf/krb-prog-yacc.m4
third_party/heimdal/cf/roken-frag.m4
third_party/heimdal/configure.ac
third_party/heimdal/import-lorikeet.sh
third_party/heimdal/include/Makefile.am
third_party/heimdal/include/bits.c
third_party/heimdal/include/config.h.w32
third_party/heimdal/kadmin/add-random-users.c
third_party/heimdal/kadmin/add_enctype.c
third_party/heimdal/kadmin/ank.c
third_party/heimdal/kadmin/cpw.c
third_party/heimdal/kadmin/del.c
third_party/heimdal/kadmin/ext.c
third_party/heimdal/kadmin/get.c
third_party/heimdal/kadmin/init.c
third_party/heimdal/kadmin/kadm_conn.c
third_party/heimdal/kadmin/kadmin.1
third_party/heimdal/kadmin/kadmind.c
third_party/heimdal/kadmin/load.c
third_party/heimdal/kadmin/mod.c
third_party/heimdal/kadmin/rpc.c
third_party/heimdal/kadmin/server.c
third_party/heimdal/kadmin/stash.c
third_party/heimdal/kcm/cache.c
third_party/heimdal/kcm/client.c
third_party/heimdal/kcm/glue.c
third_party/heimdal/kcm/protocol.c
third_party/heimdal/kdc/Makefile.am
third_party/heimdal/kdc/NTMakefile
third_party/heimdal/kdc/altsecid_gss_preauth_authorizer.c
third_party/heimdal/kdc/bx509d.c
third_party/heimdal/kdc/ca.c
third_party/heimdal/kdc/cjwt_token_validator.c
third_party/heimdal/kdc/config.c
third_party/heimdal/kdc/connect.c
third_party/heimdal/kdc/csr_authorizer.c
third_party/heimdal/kdc/default_config.c
third_party/heimdal/kdc/digest-service.c
third_party/heimdal/kdc/digest.c
third_party/heimdal/kdc/fast.c
third_party/heimdal/kdc/gss_preauth.c
third_party/heimdal/kdc/gss_preauth_authorizer_plugin.h
third_party/heimdal/kdc/headers.h
third_party/heimdal/kdc/hprop.8
third_party/heimdal/kdc/hprop.c
third_party/heimdal/kdc/hprop.h
third_party/heimdal/kdc/hpropd.8
third_party/heimdal/kdc/hpropd.c
third_party/heimdal/kdc/httpkadmind.c
third_party/heimdal/kdc/ipc_csr_authorizer.c
third_party/heimdal/kdc/kdc-accessors.h [new file with mode: 0644]
third_party/heimdal/kdc/kdc-audit.h [moved from third_party/heimdal/kdc/rx.h with 50% similarity]
third_party/heimdal/kdc/kdc-plugin.c [new file with mode: 0644]
third_party/heimdal/kdc/kdc-plugin.h [new file with mode: 0644]
third_party/heimdal/kdc/kdc-replay.c
third_party/heimdal/kdc/kdc.h
third_party/heimdal/kdc/kdc_locl.h
third_party/heimdal/kdc/kerberos5.c
third_party/heimdal/kdc/krb5tgs.c
third_party/heimdal/kdc/kstash.c
third_party/heimdal/kdc/kx509.c
third_party/heimdal/kdc/libkdc-exports.def
third_party/heimdal/kdc/log.c
third_party/heimdal/kdc/misc.c
third_party/heimdal/kdc/mit_dump.c
third_party/heimdal/kdc/mssfu.c [new file with mode: 0644]
third_party/heimdal/kdc/negotiate_token_validator.c
third_party/heimdal/kdc/pkinit.c
third_party/heimdal/kdc/process.c
third_party/heimdal/kdc/set_dbinfo.c
third_party/heimdal/kdc/simple_csr_authorizer.c
third_party/heimdal/kdc/string2key.c
third_party/heimdal/kdc/test_kdc_ca.c
third_party/heimdal/kdc/token_validator.c
third_party/heimdal/kdc/version-script.map
third_party/heimdal/kdc/windc.c [deleted file]
third_party/heimdal/kdc/windc_plugin.h [deleted file]
third_party/heimdal/kpasswd/kpasswdd.c
third_party/heimdal/kuser/generate-requests.c
third_party/heimdal/kuser/kgetcred.c
third_party/heimdal/kuser/kimpersonate.c
third_party/heimdal/kuser/kinit.c
third_party/heimdal/kuser/klist.c
third_party/heimdal/kuser/kswitch.c
third_party/heimdal/kuser/kuser_locl.h
third_party/heimdal/lib/asn1/MANUAL.md [new file with mode: 0644]
third_party/heimdal/lib/asn1/Makefile.am
third_party/heimdal/lib/asn1/NTMakefile
third_party/heimdal/lib/asn1/README.md
third_party/heimdal/lib/asn1/asn1-template.h
third_party/heimdal/lib/asn1/asn1_compile.1
third_party/heimdal/lib/asn1/asn1_print.c
third_party/heimdal/lib/asn1/asn1parse.y
third_party/heimdal/lib/asn1/check-common.h
third_party/heimdal/lib/asn1/check-der.c
third_party/heimdal/lib/asn1/check-gen.c
third_party/heimdal/lib/asn1/check-gen.h [new file with mode: 0644]
third_party/heimdal/lib/asn1/check-template.c
third_party/heimdal/lib/asn1/der_copy.c
third_party/heimdal/lib/asn1/der_get.c
third_party/heimdal/lib/asn1/der_put.c
third_party/heimdal/lib/asn1/extra.c
third_party/heimdal/lib/asn1/gen.c
third_party/heimdal/lib/asn1/gen_copy.c
third_party/heimdal/lib/asn1/gen_decode.c
third_party/heimdal/lib/asn1/gen_encode.c
third_party/heimdal/lib/asn1/gen_free.c
third_party/heimdal/lib/asn1/gen_glue.c
third_party/heimdal/lib/asn1/gen_locl.h
third_party/heimdal/lib/asn1/gen_template.c
third_party/heimdal/lib/asn1/krb5.asn1
third_party/heimdal/lib/asn1/krb5.opt
third_party/heimdal/lib/asn1/libasn1-exports.def
third_party/heimdal/lib/asn1/main.c
third_party/heimdal/lib/asn1/oid_resolution.c
third_party/heimdal/lib/asn1/symbol.h
third_party/heimdal/lib/asn1/template.c
third_party/heimdal/lib/asn1/test.asn1
third_party/heimdal/lib/asn1/test.opt
third_party/heimdal/lib/base/array.c
third_party/heimdal/lib/base/bsearch.c
third_party/heimdal/lib/base/data.c
third_party/heimdal/lib/base/db.c
third_party/heimdal/lib/base/dict.c
third_party/heimdal/lib/base/dll.c
third_party/heimdal/lib/base/error.c
third_party/heimdal/lib/base/error_string.c
third_party/heimdal/lib/base/expand_path.c
third_party/heimdal/lib/base/heimbase-svc.h
third_party/heimdal/lib/base/heimbase.c
third_party/heimdal/lib/base/heimbase.h
third_party/heimdal/lib/base/heimbasepriv.h
third_party/heimdal/lib/base/log.c
third_party/heimdal/lib/base/number.c
third_party/heimdal/lib/base/plugin.c
third_party/heimdal/lib/base/string.c
third_party/heimdal/lib/base/test_base.c
third_party/heimdal/lib/base/version-script.map
third_party/heimdal/lib/com_err/Makefile.am
third_party/heimdal/lib/gss_preauth/pa_client.c
third_party/heimdal/lib/gss_preauth/pa_common.c
third_party/heimdal/lib/gssapi/Makefile.am
third_party/heimdal/lib/gssapi/NTMakefile
third_party/heimdal/lib/gssapi/gss-token.c
third_party/heimdal/lib/gssapi/gssapi/gssapi.h
third_party/heimdal/lib/gssapi/gssapi/gssapi_krb5.h
third_party/heimdal/lib/gssapi/krb5/accept_sec_context.c
third_party/heimdal/lib/gssapi/krb5/acquire_cred.c
third_party/heimdal/lib/gssapi/krb5/arcfour.c
third_party/heimdal/lib/gssapi/krb5/copy_ccache.c
third_party/heimdal/lib/gssapi/krb5/export_sec_context.c
third_party/heimdal/lib/gssapi/krb5/external.c
third_party/heimdal/lib/gssapi/krb5/import_name.c
third_party/heimdal/lib/gssapi/krb5/init_sec_context.c
third_party/heimdal/lib/gssapi/krb5/name_attrs.c [new file with mode: 0644]
third_party/heimdal/lib/gssapi/krb5/store_cred.c
third_party/heimdal/lib/gssapi/krb5/test_kcred.c
third_party/heimdal/lib/gssapi/libgssapi-exports.def
third_party/heimdal/lib/gssapi/mech/gss_compare_name.c
third_party/heimdal/lib/gssapi/mech/gss_cred.c
third_party/heimdal/lib/gssapi/mech/gss_export_sec_context.c
third_party/heimdal/lib/gssapi/mech/gss_import_name.c
third_party/heimdal/lib/gssapi/mech/gss_import_sec_context.c
third_party/heimdal/lib/gssapi/mech/gss_krb5.c
third_party/heimdal/lib/gssapi/mech/gss_mech_switch.c
third_party/heimdal/lib/gssapi/mech/gss_pname_to_uid.c
third_party/heimdal/lib/gssapi/mech/mech_locl.h
third_party/heimdal/lib/gssapi/ntlm/accept_sec_context.c
third_party/heimdal/lib/gssapi/ntlm/creds.c
third_party/heimdal/lib/gssapi/ntlm/crypto.c
third_party/heimdal/lib/gssapi/ntlm/delete_sec_context.c
third_party/heimdal/lib/gssapi/ntlm/init_sec_context.c
third_party/heimdal/lib/gssapi/ntlm/kdc.c
third_party/heimdal/lib/gssapi/sanon/import_name.c
third_party/heimdal/lib/gssapi/spnego/accept_sec_context.c
third_party/heimdal/lib/gssapi/spnego/negoex_ctx.c
third_party/heimdal/lib/gssapi/test_context.c
third_party/heimdal/lib/gssapi/test_kcred.c
third_party/heimdal/lib/gssapi/test_names.c
third_party/heimdal/lib/gssapi/version-script.map
third_party/heimdal/lib/hcrypto/Makefile.am
third_party/heimdal/lib/hcrypto/bn.c
third_party/heimdal/lib/hcrypto/des.c
third_party/heimdal/lib/hcrypto/dh-ltm.c
third_party/heimdal/lib/hcrypto/dh.c
third_party/heimdal/lib/hcrypto/engine.c
third_party/heimdal/lib/hcrypto/evp.c
third_party/heimdal/lib/hcrypto/hmac.c
third_party/heimdal/lib/hcrypto/hmac.h
third_party/heimdal/lib/hcrypto/libtommath/bn_mp_set_double.c
third_party/heimdal/lib/hcrypto/libtommath/bn_s_mp_rand_platform.c
third_party/heimdal/lib/hcrypto/libtommath/demo/test.c
third_party/heimdal/lib/hcrypto/libtommath/etc/tune.c
third_party/heimdal/lib/hcrypto/rsa-ltm.c
third_party/heimdal/lib/hcrypto/rsa.c
third_party/heimdal/lib/hcrypto/test_hmac.c
third_party/heimdal/lib/hcrypto/validate.c
third_party/heimdal/lib/hdb/Makefile.am
third_party/heimdal/lib/hdb/NTMakefile
third_party/heimdal/lib/hdb/common.c
third_party/heimdal/lib/hdb/db.c
third_party/heimdal/lib/hdb/db3.c
third_party/heimdal/lib/hdb/ext.c
third_party/heimdal/lib/hdb/hdb-keytab.c
third_party/heimdal/lib/hdb/hdb-ldap.c
third_party/heimdal/lib/hdb/hdb-mdb.c
third_party/heimdal/lib/hdb/hdb-mitdb.c
third_party/heimdal/lib/hdb/hdb-sqlite.c
third_party/heimdal/lib/hdb/hdb.asn1
third_party/heimdal/lib/hdb/hdb.c
third_party/heimdal/lib/hdb/hdb.h
third_party/heimdal/lib/hdb/hdb.opt [new file with mode: 0644]
third_party/heimdal/lib/hdb/keys.c
third_party/heimdal/lib/hdb/keytab.c
third_party/heimdal/lib/hdb/libhdb-exports.def
third_party/heimdal/lib/hdb/ndbm.c
third_party/heimdal/lib/hdb/print.c
third_party/heimdal/lib/hdb/test_concurrency.c
third_party/heimdal/lib/hdb/test_namespace.c
third_party/heimdal/lib/hdb/version-script.map
third_party/heimdal/lib/hx509/Makefile.am
third_party/heimdal/lib/hx509/ca.c
third_party/heimdal/lib/hx509/cert.c
third_party/heimdal/lib/hx509/cms.c
third_party/heimdal/lib/hx509/collector.c
third_party/heimdal/lib/hx509/crypto.c
third_party/heimdal/lib/hx509/error.c
third_party/heimdal/lib/hx509/file.c
third_party/heimdal/lib/hx509/hxtool.c
third_party/heimdal/lib/hx509/keyset.c
third_party/heimdal/lib/hx509/ks_file.c
third_party/heimdal/lib/hx509/name.c
third_party/heimdal/lib/hx509/print.c
third_party/heimdal/lib/hx509/req.c
third_party/heimdal/lib/hx509/revoke.c
third_party/heimdal/lib/hx509/sel-gram.y
third_party/heimdal/lib/hx509/softp11.c
third_party/heimdal/lib/ipc/Makefile.am
third_party/heimdal/lib/ipc/server.c
third_party/heimdal/lib/kadm5/ad.c
third_party/heimdal/lib/kadm5/chpass_s.c
third_party/heimdal/lib/kadm5/context_s.c
third_party/heimdal/lib/kadm5/create_s.c
third_party/heimdal/lib/kadm5/delete_s.c
third_party/heimdal/lib/kadm5/ent_setup.c
third_party/heimdal/lib/kadm5/get_princs_s.c
third_party/heimdal/lib/kadm5/get_s.c
third_party/heimdal/lib/kadm5/init_c.c
third_party/heimdal/lib/kadm5/init_s.c
third_party/heimdal/lib/kadm5/iprop-log.c
third_party/heimdal/lib/kadm5/ipropd_common.c
third_party/heimdal/lib/kadm5/ipropd_master.c
third_party/heimdal/lib/kadm5/ipropd_slave.c
third_party/heimdal/lib/kadm5/log.c
third_party/heimdal/lib/kadm5/marshall.c
third_party/heimdal/lib/kadm5/modify_s.c
third_party/heimdal/lib/kadm5/prune_s.c
third_party/heimdal/lib/kadm5/randkey_c.c
third_party/heimdal/lib/kadm5/randkey_s.c
third_party/heimdal/lib/kadm5/rename_s.c
third_party/heimdal/lib/kadm5/set_keys.c
third_party/heimdal/lib/kadm5/setkey3_s.c
third_party/heimdal/lib/kafs/Makefile.am
third_party/heimdal/lib/kafs/afskrb5.c
third_party/heimdal/lib/kafs/afssys.c
third_party/heimdal/lib/kafs/rxkad_kdf.c
third_party/heimdal/lib/krb5/Makefile.am
third_party/heimdal/lib/krb5/NTMakefile
third_party/heimdal/lib/krb5/acache.c
third_party/heimdal/lib/krb5/acl.c
third_party/heimdal/lib/krb5/addr_families.c
third_party/heimdal/lib/krb5/aes-test.c
third_party/heimdal/lib/krb5/asn1_glue.c
third_party/heimdal/lib/krb5/auth_context.c
third_party/heimdal/lib/krb5/cache.c
third_party/heimdal/lib/krb5/context.c
third_party/heimdal/lib/krb5/crypto-evp.c
third_party/heimdal/lib/krb5/crypto.c
third_party/heimdal/lib/krb5/data.c
third_party/heimdal/lib/krb5/dcache.c
third_party/heimdal/lib/krb5/deprecated.c
third_party/heimdal/lib/krb5/enomem.c
third_party/heimdal/lib/krb5/error_string.c
third_party/heimdal/lib/krb5/expand_path.c
third_party/heimdal/lib/krb5/fast.c
third_party/heimdal/lib/krb5/fcache.c
third_party/heimdal/lib/krb5/generate_subkey.c
third_party/heimdal/lib/krb5/get_cred.c
third_party/heimdal/lib/krb5/get_in_tkt.c
third_party/heimdal/lib/krb5/init_creds_pw.c
third_party/heimdal/lib/krb5/kcm.c
third_party/heimdal/lib/krb5/keytab.c
third_party/heimdal/lib/krb5/keytab_file.c
third_party/heimdal/lib/krb5/keytab_keyfile.c
third_party/heimdal/lib/krb5/krb5.conf.5
third_party/heimdal/lib/krb5/krb5.h
third_party/heimdal/lib/krb5/krb5_locl.h
third_party/heimdal/lib/krb5/krbhst-test.c
third_party/heimdal/lib/krb5/krbhst.c
third_party/heimdal/lib/krb5/krcache.c
third_party/heimdal/lib/krb5/kx509.c
third_party/heimdal/lib/krb5/libkrb5-exports.def.in
third_party/heimdal/lib/krb5/mcache.c
third_party/heimdal/lib/krb5/mk_cred.c
third_party/heimdal/lib/krb5/pac.c
third_party/heimdal/lib/krb5/pkinit.c
third_party/heimdal/lib/krb5/principal.c
third_party/heimdal/lib/krb5/rd_cred.c
third_party/heimdal/lib/krb5/rd_req.c
third_party/heimdal/lib/krb5/replay.c
third_party/heimdal/lib/krb5/salt-arcfour.c
third_party/heimdal/lib/krb5/scache.c
third_party/heimdal/lib/krb5/send_to_kdc.c
third_party/heimdal/lib/krb5/sp800-108-kdf.c
third_party/heimdal/lib/krb5/store.c
third_party/heimdal/lib/krb5/store_emem.c
third_party/heimdal/lib/krb5/store_stdio.c
third_party/heimdal/lib/krb5/test_alname.c
third_party/heimdal/lib/krb5/test_ap-req.c
third_party/heimdal/lib/krb5/test_cc.c
third_party/heimdal/lib/krb5/test_hostname.c
third_party/heimdal/lib/krb5/test_rfc3961.c
third_party/heimdal/lib/krb5/test_set_kvno0.c
third_party/heimdal/lib/krb5/ticket.c
third_party/heimdal/lib/krb5/transited.c
third_party/heimdal/lib/krb5/verify_user.c
third_party/heimdal/lib/krb5/version-script.map
third_party/heimdal/lib/ntlm/digest.c
third_party/heimdal/lib/ntlm/ntlm.c
third_party/heimdal/lib/otp/otp_md.c
third_party/heimdal/lib/roken/Makefile.am
third_party/heimdal/lib/roken/base32-test.c
third_party/heimdal/lib/roken/base32.c
third_party/heimdal/lib/roken/base64-test.c
third_party/heimdal/lib/roken/base64.c
third_party/heimdal/lib/roken/copyhostent.c
third_party/heimdal/lib/roken/detach.c
third_party/heimdal/lib/roken/dirent-test.c
third_party/heimdal/lib/roken/environment.c
third_party/heimdal/lib/roken/fnmatch.c
third_party/heimdal/lib/roken/freeaddrinfo.c
third_party/heimdal/lib/roken/freehostent.c
third_party/heimdal/lib/roken/getaddrinfo.c
third_party/heimdal/lib/roken/getcap.c [deleted file]
third_party/heimdal/lib/roken/getipnodebyaddr.c
third_party/heimdal/lib/roken/getipnodebyname.c
third_party/heimdal/lib/roken/getnameinfo.c
third_party/heimdal/lib/roken/getuserinfo.c
third_party/heimdal/lib/roken/hex-test.c
third_party/heimdal/lib/roken/hex.c
third_party/heimdal/lib/roken/mergesort_r.c
third_party/heimdal/lib/roken/ndbm_wrap.c
third_party/heimdal/lib/roken/net_write.c
third_party/heimdal/lib/roken/resolve-test.c
third_party/heimdal/lib/roken/roken-common.h
third_party/heimdal/lib/roken/roken.h.in
third_party/heimdal/lib/roken/snprintf.c
third_party/heimdal/lib/roken/socket.c
third_party/heimdal/lib/roken/strftime.c
third_party/heimdal/lib/roken/strptime.c
third_party/heimdal/lib/roken/strtoll.c
third_party/heimdal/lib/roken/strtoull.c
third_party/heimdal/lib/roken/test-getuserinfo.c
third_party/heimdal/lib/roken/test-mini_inetd.c
third_party/heimdal/lib/roken/timeval.c
third_party/heimdal/lib/roken/version-script.map
third_party/heimdal/lib/roken/vis.c
third_party/heimdal/lib/sl/Makefile.am
third_party/heimdal/lib/sl/sl.c
third_party/heimdal/lib/sl/slc-gram.y
third_party/heimdal/lib/wind/idn-lookup.c
third_party/heimdal/lib/wind/utf8.c
third_party/heimdal/packages/windows/installer/NTMakefile
third_party/heimdal/packages/windows/installer/heimdal-installer.wxs
third_party/heimdal/tests/bin/setup-env.in
third_party/heimdal/tests/gss/Makefile.am
third_party/heimdal/tests/gss/check-basic.in
third_party/heimdal/tests/gss/check-context.in
third_party/heimdal/tests/gss/check-gssmask.in
third_party/heimdal/tests/gss/check-ntlm.in
third_party/heimdal/tests/gss/check-spnego.in
third_party/heimdal/tests/gss/krb5.conf.in
third_party/heimdal/tests/java/check-kinit.in
third_party/heimdal/tests/kdc/Makefile.am
third_party/heimdal/tests/kdc/check-bx509.in
third_party/heimdal/tests/kdc/check-canon.in
third_party/heimdal/tests/kdc/check-cc.in
third_party/heimdal/tests/kdc/check-delegation.in
third_party/heimdal/tests/kdc/check-des.in
third_party/heimdal/tests/kdc/check-digest.in
third_party/heimdal/tests/kdc/check-fast.in
third_party/heimdal/tests/kdc/check-hdb-mitdb.in
third_party/heimdal/tests/kdc/check-httpkadmind.in
third_party/heimdal/tests/kdc/check-iprop.in
third_party/heimdal/tests/kdc/check-kadmin.in
third_party/heimdal/tests/kdc/check-kdc.in
third_party/heimdal/tests/kdc/check-kinit.in
third_party/heimdal/tests/kdc/check-kpasswdd.in
third_party/heimdal/tests/kdc/check-pkinit.in
third_party/heimdal/tests/kdc/check-referral.in
third_party/heimdal/tests/kdc/check-tester.in
third_party/heimdal/tests/kdc/check-uu.in
third_party/heimdal/tests/kdc/krb5-kcm.conf.in [new file with mode: 0644]
third_party/heimdal/tests/kdc/krb5.conf.in
third_party/heimdal/tests/ldap/check-ldap.in
third_party/heimdal/tests/plugin/Makefile.am
third_party/heimdal/tests/plugin/check-pac.in
third_party/heimdal/tests/plugin/kdc_test_plugin.c [new file with mode: 0644]
third_party/heimdal/tests/plugin/krb5.conf.in
third_party/heimdal/tests/plugin/windc.c [deleted file]
third_party/heimdal/windows/NTMakefile.sdk [new file with mode: 0644]
third_party/heimdal/windows/NTMakefile.w32

diff --git a/third_party/heimdal/.github/workflows/build.yml b/third_party/heimdal/.github/workflows/build.yml
deleted file mode 100644 (file)
index c9d4d9e..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-name: Build
-
-on:
-    push: {paths: [src/**, .github/workflows/build.yml]}
-    pull_request: {paths: [src/**, .github/workflows/build.yml]}
-
-jobs:
-
-    unix:
-        runs-on: ${{ matrix.os }}
-        strategy:
-            fail-fast: false
-            matrix:
-                name: [linux-clang, linux-gcc]
-                include:
-                    - name: linux-clang
-                      os: ubuntu-18.04
-                      compiler: clang
-                    - name: linux-gcc
-                      os: ubuntu-18.04
-                      compiler: gcc
-        steps:
-            - name: Clone repository
-              uses: actions/checkout@v1
-            - name: Install packages
-              if: startsWith(matrix.os, 'ubuntu')
-              run: |
-                sudo apt-get update -qq
-                sudo apt-get install -y bison comerr-dev flex libcap-ng-dev libdb-dev libedit-dev libjson-perl libldap2-dev libncurses5-dev libperl4-corelibs-perl libsqlite3-dev libkeyutils-dev pkg-config python ss-dev texinfo unzip netbase keyutils ldap-utils gdb apport curl libmicrohttpd-dev jq valgrind
-                # Temporary workaround for:
-                # https://github.com/actions/virtual-environments/issues/3185
-                sudo hostname localhost
-            - name: Build
-              env:
-                CC: ${{ matrix.compiler }}
-                MAKEVARS: ${{ matrix.makevars }}
-                CONFIGURE_OPTS:  ${{ matrix.configureopts }}
-              run: |
-                /bin/sh ./autogen.sh
-                mkdir build
-                cd build
-                ../configure --srcdir=`dirname "$PWD"` --enable-maintainer-mode --enable-developer --with-ldap $CONFIGURE_OPTS --prefix=$HOME/inst CFLAGS="-Wno-error=shadow -Wno-error=bad-function-cast -Wno-error=unused-function -Wno-error=unused-result -Wno-error=deprecated-declarations"
-                ulimit -c unlimited
-                make -j4
-                make check
-                make install
-            - name: Valgrind output
-              run: |
-                find . -name \*.log -print0|xargs -0 grep '^==[1-9]' || true
-            - name: Core dump stacks
-              run: |
-                echo "thread apply all bt" > /tmp/x
-                find . -name core -print | while read core; do gdb -batch -x x `file "$core"|sed -e "s/^[^']*'//" -e "s/[ '].*$//"` "$core"; done
-                if [ "$(find . -name core -print | wc -l)" -gt 0 ]; then false; fi
-            - name: Test logs
-              if: ${{ failure() }}
-              run: |
-                find build -name \*.trs|xargs grep -lw FAIL|sed -e 's/trs$/log/'|xargs cat
-            - name: distclean
-              run: |
-                cd build
-                make distclean
-                if [ "$(git ls-files -o|grep -v ^build/ | wc -l)" -ne 0 ]; then
-                  echo "Files not removed by make distclean:"
-                  git ls-files -o|grep -v ^build/
-                fi
-
index 2a09f94ac80d491a4a09644c77509367013bf1c1..e5b52468af54915ee626c7314f487844b8e5bc99 100644 (file)
 Makefile
 Makefile.in
 rs_state.ini
-asn1_*.[cx]
 tags
 !/lib/asn1/asn1_gen.c
 !/lib/asn1/asn1_print.c
 !/lib/krb5/asn1_glue.c
 *_asn1.h
 !/lib/asn1/heim_asn1.h
-*_asn1.hx
 *_asn1-priv.h
-*_asn1-priv.hx
-*_asn1-template.c
-*_asn1-template.x
+asn1_*_asn1.c
 *_asn1_files
 *_asn1_oids.x
+*_asn1_syms.x
 *_err.[ch]
 !/lib/com_err/com_err.[ch]
 *-commands.[ch]
@@ -153,6 +150,9 @@ tags
 /kdc/kdc-tester
 /kdc/kstash
 /kdc/string2key
+/kdc/test_csr_authorizer
+/kdc/test_kdc_ca
+/kdc/test_token_validator
 /kpasswd/kpasswd
 /kpasswd/kpasswd-generator
 /kpasswd/kpasswdd
@@ -176,13 +176,106 @@ tags
 /lib/asn1/check-ber
 /lib/asn1/check-der
 /lib/asn1/check-gen
+/lib/asn1/check-gen-template
 /lib/asn1/check-template
 /lib/asn1/check-timegm
-/lib/asn1/der-protos.h
+/lib/asn1/cms_asn1.json
+/lib/asn1/cms_asn1_oids.c
+/lib/asn1/cms_asn1_syms.c
+/lib/asn1/cms_template_asn1.json
+/lib/asn1/cms_template_asn1_oids.c
+/lib/asn1/cms_template_asn1_syms.c
+/lib/asn1/crmf_asn1.json
+/lib/asn1/crmf_asn1_oids.c
+/lib/asn1/crmf_asn1_syms.c
+/lib/asn1/crmf_template_asn1.json
+/lib/asn1/crmf_template_asn1_oids.c
+/lib/asn1/crmf_template_asn1_syms.c
 /lib/asn1/der-private.h
+/lib/asn1/der-protos.h
+/lib/asn1/digest_asn1.json
+/lib/asn1/digest_asn1_oids.c
+/lib/asn1/digest_asn1_syms.c
+/lib/asn1/digest_template_asn1.json
+/lib/asn1/digest_template_asn1_oids.c
+/lib/asn1/digest_template_asn1_syms.c
+/lib/asn1/krb5_asn1.json
+/lib/asn1/krb5_asn1_oids.c
+/lib/asn1/krb5_asn1_syms.c
+/lib/asn1/krb5_template_asn1.json
+/lib/asn1/krb5_template_asn1_oids.c
+/lib/asn1/krb5_template_asn1_syms.c
+/lib/asn1/kx509_asn1.json
+/lib/asn1/kx509_asn1_oids.c
+/lib/asn1/kx509_asn1_syms.c
+/lib/asn1/kx509_template_asn1.json
+/lib/asn1/kx509_template_asn1_oids.c
+/lib/asn1/kx509_template_asn1_syms.c
 /lib/asn1/lex.c
+/lib/asn1/ocsp_asn1.json
+/lib/asn1/ocsp_asn1_oids.c
+/lib/asn1/ocsp_asn1_syms.c
+/lib/asn1/ocsp_template_asn1.json
+/lib/asn1/ocsp_template_asn1_oids.c
+/lib/asn1/ocsp_template_asn1_syms.c
+/lib/asn1/pkcs10_asn1.json
+/lib/asn1/pkcs10_asn1_oids.c
+/lib/asn1/pkcs10_asn1_syms.c
+/lib/asn1/pkcs10_template_asn1.json
+/lib/asn1/pkcs10_template_asn1_oids.c
+/lib/asn1/pkcs10_template_asn1_syms.c
+/lib/asn1/pkcs12_asn1.json
+/lib/asn1/pkcs12_asn1_oids.c
+/lib/asn1/pkcs12_asn1_syms.c
+/lib/asn1/pkcs12_template_asn1.json
+/lib/asn1/pkcs12_template_asn1_oids.c
+/lib/asn1/pkcs12_template_asn1_syms.c
+/lib/asn1/pkcs8_asn1.json
+/lib/asn1/pkcs8_asn1_oids.c
+/lib/asn1/pkcs8_asn1_syms.c
+/lib/asn1/pkcs8_template_asn1.json
+/lib/asn1/pkcs8_template_asn1_oids.c
+/lib/asn1/pkcs8_template_asn1_syms.c
+/lib/asn1/pkcs9_asn1.json
+/lib/asn1/pkcs9_asn1_oids.c
+/lib/asn1/pkcs9_asn1_syms.c
+/lib/asn1/pkcs9_template_asn1.json
+/lib/asn1/pkcs9_template_asn1_oids.c
+/lib/asn1/pkcs9_template_asn1_syms.c
+/lib/asn1/pkinit_asn1.json
+/lib/asn1/pkinit_asn1_oids.c
+/lib/asn1/pkinit_asn1_syms.c
+/lib/asn1/pkinit_template_asn1.json
+/lib/asn1/pkinit_template_asn1_oids.c
+/lib/asn1/pkinit_template_asn1_syms.c
+/lib/asn1/rfc2459_asn1.json
+/lib/asn1/rfc2459_asn1_oids.c
+/lib/asn1/rfc2459_asn1_syms.c
+/lib/asn1/rfc2459_template_asn1.json
+/lib/asn1/rfc2459_template_asn1_oids.c
+/lib/asn1/rfc2459_template_asn1_syms.c
+/lib/asn1/rfc4108_asn1.json
+/lib/asn1/rfc4108_asn1_oids.c
+/lib/asn1/rfc4108_asn1_syms.c
+/lib/asn1/rfc4108_template_asn1.json
+/lib/asn1/rfc4108_template_asn1_oids.c
+/lib/asn1/rfc4108_template_asn1_syms.c
+/lib/asn1/test_asn1.json
+/lib/asn1/test_asn1_oids.c
+/lib/asn1/test_asn1_syms.c
+/lib/asn1/test_template_asn1.json
+/lib/asn1/test_template_asn1_oids.c
+/lib/asn1/test_template_asn1_syms.c
+/lib/asn1/x690sample_asn1.json
+/lib/asn1/x690sample_asn1_oids.c
+/lib/asn1/x690sample_asn1_syms.c
+/lib/asn1/x690sample_template_asn1.json
+/lib/asn1/x690sample_template_asn1_oids.c
+/lib/asn1/x690sample_template_asn1_syms.c
 /lib/auth/Makefile.in
 /lib/base/base64.c
+/lib/base/heimbase-protos.h
+/lib/base/json-journal
 /lib/base/test_base
 /lib/base/test_db.json
 /lib/com_err/compile_et
@@ -191,12 +284,31 @@ tags
 /lib/com_err/parse.h
 /lib/com_err/snprintf.c
 /lib/com_err/strlcpy.c
-/lib/gssapi/gss
+/lib/gssapi/asn1_ContextFlags.c
+/lib/gssapi/asn1_GSSAPIContextToken.c
+/lib/gssapi/asn1_MechType.c
+/lib/gssapi/asn1_MechTypeList.c
+/lib/gssapi/asn1_NegHints.c
+/lib/gssapi/asn1_NegStateEnum.c
+/lib/gssapi/asn1_NegTokenInit.c
+/lib/gssapi/asn1_NegTokenInit2.c
+/lib/gssapi/asn1_NegTokenResp.c
+/lib/gssapi/asn1_NegotiationToken.c
+/lib/gssapi/asn1_NegotiationToken2.c
+/lib/gssapi/gss-token
+/lib/gssapi/gssapi_asn1-template.c
+/lib/gssapi/gssapi_asn1.json
+/lib/gssapi/gssapi_asn1_oids.c
+/lib/gssapi/gssapi_asn1_syms.c
 /lib/gssapi/gsstool
 /lib/gssapi/krb5/gsskrb5-private.h
 /lib/gssapi/ntlm/ntlm-private.h
 /lib/gssapi/sanon/sanon-private.h
 /lib/gssapi/spnego/spnego-private.h
+/lib/gssapi/spnego_asn1-template.c
+/lib/gssapi/spnego_asn1.json
+/lib/gssapi/spnego_asn1_oids.c
+/lib/gssapi/spnego_asn1_syms.c
 /lib/gssapi/test_acquire_cred
 /lib/gssapi/test_add_store_cred
 /lib/gssapi/test_cfx
@@ -239,12 +351,44 @@ tags
 /lib/hcrypto/test_rsa
 /lib/hcrypto/unix
 /lib/hcrypto/libtommath/callgraph.txt
-/lib/hdb/hdb-protos.h
+/lib/hdb/asn1_Event.c
+/lib/hdb/asn1_GENERATION.c
+/lib/hdb/asn1_HDBFlags.c
+/lib/hdb/asn1_HDB_EncTypeList.c
+/lib/hdb/asn1_HDB_EntryOrAlias.c
+/lib/hdb/asn1_HDB_Ext_Aliases.c
+/lib/hdb/asn1_HDB_Ext_Constrained_delegation_acl.c
+/lib/hdb/asn1_HDB_Ext_KeyRotation.c
+/lib/hdb/asn1_HDB_Ext_KeySet.c
+/lib/hdb/asn1_HDB_Ext_Lan_Manager_OWF.c
+/lib/hdb/asn1_HDB_Ext_PKINIT_acl.c
+/lib/hdb/asn1_HDB_Ext_PKINIT_cert.c
+/lib/hdb/asn1_HDB_Ext_PKINIT_hash.c
+/lib/hdb/asn1_HDB_Ext_Password.c
+/lib/hdb/asn1_HDB_entry.c
+/lib/hdb/asn1_HDB_entry_alias.c
+/lib/hdb/asn1_HDB_extension.c
+/lib/hdb/asn1_HDB_extensions.c
+/lib/hdb/asn1_HDB_keyset.c
+/lib/hdb/asn1_Key.c
+/lib/hdb/asn1_KeyRotation.c
+/lib/hdb/asn1_KeyRotationFlags.c
+/lib/hdb/asn1_Keys.c
+/lib/hdb/asn1_Salt.c
 /lib/hdb/hdb-private.h
+/lib/hdb/hdb-protos.h
+/lib/hdb/hdb_asn1-template.c
+/lib/hdb/hdb_asn1.json
+/lib/hdb/hdb_asn1_oids.c
+/lib/hdb/hdb_asn1_syms.c
+/lib/hdb/test_concurrency
 /lib/hdb/test_dbinfo
 /lib/hdb/test_hdbkeys
-/lib/hdb/test_namespace
 /lib/hdb/test_mkey
+/lib/hdb/test_namespace
+/lib/hdb/testhdb-*-shm
+/lib/hdb/testhdb-*-wal
+/lib/hx509/actual
 /lib/hx509/PKITS_data/
 /lib/hx509/cert-ca.der
 /lib/hx509/cert-ca.pem
@@ -258,6 +402,7 @@ tags
 /lib/hx509/data/*.srl
 /lib/hx509/data/*.req
 /lib/hx509/data/sub-ca-combined.crt
+/lib/hx509/expected
 /lib/hx509/ev.data
 /lib/hx509/ev.data.out
 /lib/hx509/hx509-private.h
@@ -341,6 +486,7 @@ tags
 /lib/krb5/test_hostname
 /lib/krb5/test_keytab
 /lib/krb5/test_mem
+/lib/krb5/test_mkforwardable
 /lib/krb5/test_pac
 /lib/krb5/test_pkinit_dh2key
 /lib/krb5/test_pknistkdf
@@ -369,10 +515,10 @@ tags
 /lib/otp/strlcpy.c
 /lib/otp/strlwr.c
 /lib/otp/strncasecmp.c
+/lib/roken/base32-test
 /lib/roken/base64-test
 /lib/roken/getaddrinfo-test
 /lib/roken/getifaddrs-test
-/lib/roken/glob.h
 /lib/roken/hex-test
 /lib/roken/make-roken
 /lib/roken/make-roken.c
@@ -380,10 +526,13 @@ tags
 /lib/roken/parse_reply-test
 /lib/roken/parse_time-test
 /lib/roken/resolve-test
+/lib/roken/rkbase32
+/lib/roken/rkbase64
 /lib/roken/rkpty
+/lib/roken/rkvis
 /lib/roken/roken.h
+/lib/roken/rtbl
 /lib/roken/snprintf-test
-/lib/roken/snprintf-test.trs
 /lib/roken/strpftime-test
 /lib/roken/test-auxval
 /lib/roken/test-detach
@@ -415,6 +564,7 @@ tags
 /lib/wind/normalize_table.h
 /lib/wind/punycode_examples.c
 /lib/wind/punycode_examples.h
+/lib/wind/__pycache__/
 /lib/wind/test-bidi
 /lib/wind/test-ldap
 /lib/wind/test-map
@@ -453,33 +603,29 @@ tags
 /tests/gss/check-context
 /tests/gss/check-gss
 /tests/gss/check-gssmask
+/tests/gss/check-negoex
 /tests/gss/check-ntlm
 /tests/gss/check-spnego
 /tests/gss/current-db.db
 /tests/gss/foopassword
 /tests/gss/krb5.conf
-/tests/gss/krb5ccfile*
-/tests/gss/krb5ccfile2*
-/tests/gss/krb5ccfile-ds*
+/tests/gss/krb5ccfile
+/tests/gss/krb5ccfile-ds
+/tests/gss/krb5ccfile2
+/tests/gss/mech
+/tests/gss/new_clients_k5.conf
 /tests/gss/server.keytab
 /tests/gss/tempfile
-/tests/java/KerberosInit$1.class
-/tests/java/KerberosInit$TestCallBackHandler.class
-/tests/java/KerberosInit.class
 /tests/java/check-kinit
-/tests/java/current-db.db
-/tests/java/foopassword
-/tests/java/jgssapi_server.class
-/tests/java/server.keytab
 /tests/java/krb5.conf
-/tests/kdc/acache.krb5*
+/tests/kdc/acache.krb5
 /tests/kdc/barpassword
-/tests/kdc/ca.crt
-/tests/kdc/cache.krb5*
-/tests/kdc/cache1.krb5*
-/tests/kdc/cache2.krb5*
+/tests/kdc/bx509.pem
+/tests/kdc/cache.krb5
+/tests/kdc/cc_dir/
 /tests/kdc/cdigest-reply
 /tests/kdc/check-authz
+/tests/kdc/check-bx509
 /tests/kdc/check-canon
 /tests/kdc/check-cc
 /tests/kdc/check-delegation
@@ -487,6 +633,7 @@ tags
 /tests/kdc/check-digest
 /tests/kdc/check-fast
 /tests/kdc/check-hdb-mitdb
+/tests/kdc/check-httpkadmind
 /tests/kdc/check-iprop
 /tests/kdc/check-kadmin
 /tests/kdc/check-kdc
@@ -498,51 +645,62 @@ tags
 /tests/kdc/check-tester
 /tests/kdc/check-uu
 /tests/kdc/current-db.db
-/tests/kdc/current.log.save
 /tests/kdc/current-db.sqlite3
+/tests/kdc/current-db.sqlite3-shm
+/tests/kdc/current-db.sqlite3-wal
+/tests/kdc/current.log.save
+/tests/kdc/email.pem
 /tests/kdc/foopassword
 /tests/kdc/foopassword.rkpty
+/tests/kdc/icache.krb5
 /tests/kdc/iprop-stats
+/tests/kdc/iprop-stats2
 /tests/kdc/iprop.keytab
 /tests/kdc/ipropd.dumpfile
-/tests/kdc/kdc.crt
+/tests/kdc/k.der
 /tests/kdc/kdc-tester4.json
+/tests/kdc/kdc.pid
 /tests/kdc/krb5-authz.conf
 /tests/kdc/krb5-authz2.conf
+/tests/kdc/krb5-bx509.conf
 /tests/kdc/krb5-canon.conf
 /tests/kdc/krb5-canon2.conf
+/tests/kdc/krb5-cccol.conf
 /tests/kdc/krb5-hdb-mitdb.conf
+/tests/kdc/krb5-httpkadmind.conf
+/tests/kdc/krb5-master2.conf
 /tests/kdc/krb5-pkinit-win.conf
 /tests/kdc/krb5-pkinit.conf
+/tests/kdc/krb5-pkinit2.conf
 /tests/kdc/krb5-slave.conf
 /tests/kdc/krb5-slave2.conf
 /tests/kdc/krb5-weak.conf
 /tests/kdc/krb5.conf
-/tests/kdc/krb5-cc.conf
 /tests/kdc/krb5.conf.keys
-/tests/kdc/kx509-template.crt
-/tests/kdc/kx509.pem
 /tests/kdc/localname
+/tests/kdc/messages.log2
+/tests/kdc/mixed-issuer.pem
 /tests/kdc/notfoopassword
 /tests/kdc/o2cache.krb5
 /tests/kdc/ocache.krb5
-/tests/kdc/pkinit.crt
-/tests/kdc/pkinit2.crt
-/tests/kdc/pkinit3.crt
-/tests/kdc/pkinit4.crt
-/tests/kdc/req-kdc.der
-/tests/kdc/req-pkinit.der
-/tests/kdc/req-pkinit2.der
+/tests/kdc/pkinit-anchor.pem
+/tests/kdc/req
 /tests/kdc/s2digest-reply
+/tests/kdc/sdb
 /tests/kdc/sdigest-init
 /tests/kdc/sdigest-reply
+/tests/kdc/server-issuer.pem
 /tests/kdc/server.keytab
+/tests/kdc/server.pem
+/tests/kdc/simple_csr_authz/
 /tests/kdc/tempfile
 /tests/kdc/test-rc-file.rc
+/tests/kdc/trivial.pem
+/tests/kdc/user-issuer.pem
 /tests/ldap/check-ldap
 /tests/ldap/krb5.conf
 /tests/ldap/slapd-init
-/tests/plugin/cache.krb5*
+/tests/plugin/cache.krb5
 /tests/plugin/check-pac
 /tests/plugin/current-db.db
 /tests/plugin/foopassword
index 7fb69fdf4e08c0a502d5d18c7901d6e39d5b250e..b9bdcf4995e5ba595292b5730cfc4530f1bc9087 100644 (file)
@@ -45,7 +45,6 @@ EXTRA_DIST = \
        cf/ChangeLog \
        cf/have-pragma-weak.m4 \
        cf/have-types.m4 \
-       cf/krb-func-getcwd-broken.m4 \
        cf/krb-prog-ranlib.m4 \
        cf/krb-prog-yacc.m4 \
        cf/krb-sys-aix.m4 \
index bf9fca2a7be9256e071045510e7ee6c25dd414a1..5e49fd0e1a4da13c7a7f3c603f0ef32e521c2655 100644 (file)
@@ -1,4 +1,6 @@
-[![Travis-CI build (Linux, OS X)](https://travis-ci.org/heimdal/heimdal.svg?branch=master)](https://travis-ci.org/heimdal/heimdal#)
+[![GitHub Build Workflow](https://github.com/heimdal/heimdal/actions/workflows/linux.yml/badge.svg)](https://github.com/heimdal/heimdal/actions?query=workflow%3Alinux)
+[![GitHub Build Workflow](https://github.com/heimdal/heimdal/actions/workflows/osx.yml/badge.svg)](https://github.com/heimdal/heimdal/actions?query=workflow%3Aosx)
+[![GitHub Build Workflow](https://github.com/heimdal/heimdal/actions/workflows/windows.yml/badge.svg)](https://github.com/heimdal/heimdal/actions?query=workflow%3Awindows)
 [![Appveyor-CI build (Windows)](https://ci.appveyor.com/api/projects/status/6j0k0m7kd6jjj4tw/branch/master?svg=true)](https://ci.appveyor.com/project/heimdal/heimdal/branch/master)
 [![Coverage Status](https://coveralls.io/repos/github/heimdal/heimdal/badge.svg?branch=master)](https://coveralls.io/github/heimdal/heimdal?branch=master)
 
@@ -30,5 +32,8 @@ respectively to subscribe.
 Build Status
 ============
 
-[![Travis-CI build (Linux, OS X)](https://travis-ci.org/heimdal/heimdal.svg?branch=master)](https://travis-ci.org/heimdal/heimdal#)
+[![GitHub Build Workflow](https://github.com/heimdal/heimdal/actions/workflows/linux.yml/badge.svg)](https://github.com/heimdal/heimdal/actions?query=workflow%3Alinux)
+[![GitHub Build Workflow](https://github.com/heimdal/heimdal/actions/workflows/osx.yml/badge.svg)](https://github.com/heimdal/heimdal/actions?query=workflow%3Aosx)
+[![GitHub Build Workflow](https://github.com/heimdal/heimdal/actions/workflows/windows.yml/badge.svg)](https://github.com/heimdal/heimdal/actions?query=workflow%3Awindows)
 [![Appveyor-CI build (Windows)](https://ci.appveyor.com/api/projects/status/6j0k0m7kd6jjj4tw/branch/master?svg=true)](https://ci.appveyor.com/project/heimdal/heimdal/branch/master)
+[![Coverage Status](https://coveralls.io/repos/github/heimdal/heimdal/badge.svg?branch=master)](https://coveralls.io/github/heimdal/heimdal?branch=master)
index a46d484c18f0ae6e9fed640d0c3e4db074908bd4..b9d0e830d3886931f439bd768529a2d7c89851e6 100644 (file)
@@ -261,7 +261,6 @@ kt_change(struct change_options *opt, int argc, char **argv)
     krb5_kt_end_seq_get(context, keytab, &cursor);
 
     if (ret == KRB5_KT_END) {
-       ret = 0;
        for (i = 0; i < j; i++) {
            if (verbose_flag) {
                char *client_name;
index f2ade9425ea88990cfbe3353da54807b270f4cfd..05078ee8e1fe42868e00e2af39f79ca8f7dcde74 100644 (file)
@@ -118,7 +118,7 @@ expand_cell_name(const char *cell)
        if(c)
            return c;
     }
-    return cell;
+    return NULL;
 }
 
 static void
index 35c548979a6f287316c3838fcf05acb9a6cc88eb..44b59fe5eb90b0fd1b28a3baef95f4b75aee0908 100644 (file)
@@ -951,7 +951,9 @@ HandleOP(WrapExt)
     memcpy(p, iov[4].buffer.value, iov[4].buffer.length);
     p += iov[4].buffer.length;
     memcpy(p, iov[5].buffer.value, iov[5].buffer.length);
+#if 0 /* Would be needed to keep going, but presently unused */
     p += iov[5].buffer.length;
+#endif
 
     gss_release_iov_buffer(NULL, iov, iov_len);
 
index ecef93965ac14c08edd41660659879d6b103decd..fd4f174988ea27889be0f0ee42b3ad7019b2d91f 100644 (file)
@@ -312,7 +312,9 @@ doit (const char *hostname, int port, const char *svc,
            continue;
        }
        freeaddrinfo (ai);
-       return proto (s, hostname, svc, message, len);
+       error = proto(s, hostname, svc, message, len);
+       close(s);
+       return error;
     }
     warnx ("failed to contact %s", hostname);
     freeaddrinfo (ai);
index 1ca6a1f61bb8b4b873185c4846bfbda171ea82cc..deb7d303c66b031f8a94e7b863d52918679cec8f 100644 (file)
@@ -118,16 +118,22 @@ verify_user_otp(char *username)
 {
     OtpContext ctx;
     char passwd[OTP_MAX_PASSPHRASE + 1];
-    char prompt[128], ss[256];
+    char ss[256];
+    char *prompt = NULL;
 
     if (otp_challenge (&ctx, username, ss, sizeof(ss)) != 0) {
        warnx("no otp challenge found for %s", username);
        return 1;
     }
 
-    snprintf (prompt, sizeof(prompt), "%s's %s Password: ", username, ss);
-    if(UI_UTIL_read_pw_string(passwd, sizeof(passwd)-1, prompt, 0))
+    if (asprintf(&prompt, "%s's %s Password: ", username, ss) == -1 ||
+        prompt == NULL)
+        err(1, "out of memory");
+    if (UI_UTIL_read_pw_string(passwd, sizeof(passwd)-1, prompt, 0)) {
+        free(prompt);
        return 1;
+    }
+    free(prompt);
     return otp_verify_user (&ctx, passwd);
 }
 
index 5d2a39dd7c43d87c18bf2aa3c31c8bb16a8d478e..baf13ecff5fb4f0ab2b18809b4c232727eb2796c 100644 (file)
@@ -159,6 +159,8 @@ process_it(int sock,
                         input_token,
                         NULL,
                         output_token);
+    if (GSS_ERROR(maj_stat))
+       gss_err(1, min_stat, "gss_wrap");
 
     write_token (sock, output_token);
     gss_release_buffer (&min_stat, output_token);
@@ -184,7 +186,7 @@ proto (int sock, const char *service)
     gss_name_t client_name;
     struct gss_channel_bindings_struct input_chan_bindings;
     gss_cred_id_t delegated_cred_handle = NULL;
-    krb5_ccache ccache;
+    krb5_ccache ccache = NULL;
     u_char init_buf[4];
     u_char acct_buf[4];
     gss_OID mech_oid;
@@ -270,15 +272,21 @@ proto (int sock, const char *service)
     printf("Using mech: %s\n", mech);
 
     if (delegated_cred_handle != GSS_C_NO_CREDENTIAL) {
-       krb5_context context;
+       krb5_context context = NULL;
 
        printf("Delegated cred found\n");
 
-       maj_stat = krb5_init_context(&context);
-       maj_stat = krb5_cc_resolve(context, "FILE:/tmp/krb5cc_test", &ccache);
-       maj_stat = gss_krb5_copy_ccache(&min_stat,
-                                      delegated_cred_handle,
-                                      ccache);
+       min_stat = krb5_init_context(&context);
+       if (min_stat)
+           gss_err(1, min_stat, "krb5_init_context");
+       if (min_stat == 0)
+           min_stat = krb5_cc_resolve(context, "FILE:/tmp/krb5cc_test", &ccache);
+       if (min_stat == 0)
+           maj_stat = gss_krb5_copy_ccache(&min_stat,
+                                           delegated_cred_handle,
+                                           ccache);
+       else
+           maj_stat = GSS_S_FAILURE;
        if (maj_stat == 0) {
           krb5_principal p;
           maj_stat = krb5_cc_get_principal(context, ccache, &p);
@@ -293,6 +301,7 @@ proto (int sock, const char *service)
           }
        }
        krb5_cc_close(context, ccache);
+       krb5_free_context(context);
        gss_release_cred(&min_stat, &delegated_cred_handle);
     }
 
index 64a2b1279faeee675efe4a919b85dcc87bcbca8f..6e046990b165eeca186aa932cf8e93192a77e626 100644 (file)
@@ -102,6 +102,8 @@ proto (int sock, const char *service)
                                  &in_creds, &out_creds);
     if(status)
        krb5_err(context, 1, status, "krb5_get_credentials");
+    krb5_cc_close(context, ccache);
+    ccache = NULL;
 
     status = krb5_cc_default(context, &ccache);
     if(status)
@@ -120,6 +122,8 @@ proto (int sock, const char *service)
                           NULL,
                           NULL,
                           NULL);
+    krb5_cc_close(context, ccache);
+    ccache = NULL;
 
     if (status)
        krb5_err(context, 1, status, "krb5_sendauth");
@@ -134,6 +138,9 @@ proto (int sock, const char *service)
        free(str);
     }
 
+    krb5_free_principal(context, in_creds.client);
+    krb5_free_principal(context, in_creds.server);
+
     krb5_data_zero (&data);
     krb5_data_zero (&packet);
 
index bb1e12123e5bef646caea72eea2a61752d797671..fa56c4c59a66737e8843a2f345b94a5abfcdfd3f 100644 (file)
@@ -4,55 +4,51 @@
 # users, and is free for public repositories.
 #
 
+version: '1.0.{build}'
+
+image:
+  - Visual Studio 2019
+
 install:
   # HACK -- pacman installation in Appveyor seems broken
   # Taken from https://github.com/johnkerl/miller/blob/master/appveyor.yml
-  - set PATH=C:\msys64\usr\bin;%PATH%
-  - bash -lc "curl -Lo pacman-5.2.1-6-x86_64.pkg.tar.xz.sig http://repo.msys2.org/msys/x86_64/pacman-5.2.1-6-x86_64.pkg.tar.xz.sig"
-  - bash -lc "curl -Lo pacman-5.2.1-6-x86_64.pkg.tar.xz http://repo.msys2.org/msys/x86_64/pacman-5.2.1-6-x86_64.pkg.tar.xz"
-  - bash -lc "curl -Lo zstd-1.4.4-2-x86_64.pkg.tar.xz.sig http://repo.msys2.org/msys/x86_64/zstd-1.4.4-2-x86_64.pkg.tar.xz.sig"
-  - bash -lc "curl -Lo zstd-1.4.4-2-x86_64.pkg.tar.xz http://repo.msys2.org/msys/x86_64/zstd-1.4.4-2-x86_64.pkg.tar.xz"
-  - bash -lc "curl -Lo autoconf-2.69-5-any.pkg.tar.xz.sig http://repo.msys2.org/msys/x86_64/autoconf-2.69-5-any.pkg.tar.xz.sig"
-  - bash -lc "curl -Lo autoconf-2.69-5-any.pkg.tar.xz http://repo.msys2.org/msys/x86_64/autoconf-2.69-5-any.pkg.tar.xz"
-  - bash -lc "curl -Lo automake1.16-1.16.2-2-any.pkg.tar.zst.sig http://repo.msys2.org/msys/x86_64/automake1.16-1.16.2-2-any.pkg.tar.zst.sig"
-  - bash -lc "curl -Lo automake1.16-1.16.2-2-any.pkg.tar.zst http://repo.msys2.org/msys/x86_64/automake1.16-1.16.2-2-any.pkg.tar.zst"
-  - bash -lc "curl -Lo bison-3.5.4-1-x86_64.pkg.tar.xz.sig http://repo.msys2.org/msys/x86_64/bison-3.5.4-1-x86_64.pkg.tar.xz.sig"
-  - bash -lc "curl -Lo bison-3.5.4-1-x86_64.pkg.tar.xz http://repo.msys2.org/msys/x86_64/bison-3.5.4-1-x86_64.pkg.tar.xz"
-  - bash -lc "curl -Lo flex-2.6.4-1-x86_64.pkg.tar.xz.sig http://repo.msys2.org/msys/x86_64/flex-2.6.4-1-x86_64.pkg.tar.xz.sig"
-  - bash -lc "curl -Lo flex-2.6.4-1-x86_64.pkg.tar.xz http://repo.msys2.org/msys/x86_64/flex-2.6.4-1-x86_64.pkg.tar.xz"
-  - bash -lc "curl -Lo perl-5.30.2-1-x86_64.pkg.tar.xz.sig http://repo.msys2.org/msys/x86_64/perl-5.30.2-1-x86_64.pkg.tar.xz.sig"
-  - bash -lc "curl -Lo perl-5.30.2-1-x86_64.pkg.tar.xz http://repo.msys2.org/msys/x86_64/perl-5.30.2-1-x86_64.pkg.tar.xz"
-  - bash -lc "curl -Lo perl-JSON-4.02-1-any.pkg.tar.zst.sig http://repo.msys2.org/msys/x86_64/perl-JSON-4.02-1-any.pkg.tar.zst.sig"
-  - bash -lc "curl -Lo perl-JSON-4.02-1-any.pkg.tar.zst http://repo.msys2.org/msys/x86_64/perl-JSON-4.02-1-any.pkg.tar.zst"
+  # (which is gone)
+  #- ps: dir 'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Microsoft SDKs\Windows' -Recurse
+  - set "PATH=C:\msys64\usr\bin;%PATH%"
+  - set "PATH=C:\%MSYS2_DIR%\%MSYSTEM%\bin;C:\%MSYS2_DIR%\usr\bin;%PATH%"
+  - bash -lc "mkdir -p /var/lib/pacman/sync/"
+  - bash -lc "pacman-key --init"
+  - bash -lc "pacman-key --populate msys2"
+  - bash -lc "curl -O http://repo.msys2.org/msys/x86_64/msys2-keyring-1~20211228-1-any.pkg.tar.zst"
+  - bash -lc "curl -O http://repo.msys2.org/msys/x86_64/msys2-keyring-1~20211228-1-any.pkg.tar.zst.sig"
+  - bash -lc "pacman --noconfirm -U --config <(echo) msys2-keyring-1~20211228-1-any.pkg.tar.zst"
+  - bash -lc "mkdir -p /var/lib/pacman/sync/"
   - bash -lc "pacman-key --init"
   - bash -lc "pacman-key --populate msys2"
-  - bash -lc "pwd; ls -l"
-  - bash -lc "pacman-key --verify pacman-5.2.1-6-x86_64.pkg.tar.xz.sig"
-  - bash -lc "pacman --noconfirm -S zstd || pacman --ask 20 -U file://$PWD/zstd-1.4.4-2-x86_64.pkg.tar.xz"
-    #- bash -lc "pacman --ask 20 -U file://$PWD/pacman-5.2.1-6-x86_64.pkg.tar.xz"
-    #- bash -lc "pacman-key --populate zstd"
-    #- bash -lc "pacman-key --verify zstd-1.4.4-2-x86_64.pkg.tar.xz.sig"
-    #- bash -lc "pacman --ask 20 -U file://$PWD/zstd-1.4.4-2-x86_64.pkg.tar.xz"
-  - bash -lc "pacman --noconfirm -S autoconf || pacman --ask 20 -U file://$PWD/autoconf-2.69-5-any.pkg.tar.xz.sig"
-  - bash -lc "pacman --noconfirm -S automake || pacman --ask 20 -U file://$PWD/automake1.16-1.16.2-2-any.pkg.tar.zst"
-  - bash -lc "pacman --noconfirm -S flex || pacman --ask 20 -U file://$PWD/flex-2.6.4-1-x86_64.pkg.tar.xz"
-  - bash -lc "pacman --noconfirm -S bison || pacman --ask 20 -U file://$PWD/bison-3.5.4-1-x86_64.pkg.tar.xz"
-  - bash -lc "pacman --noconfirm -S perl || pacman --ask 20 -U file://$PWD/perl-5.30.2-1-x86_64.pkg.tar.xz"
-  - bash -lc "pacman --noconfirm -S perl-JSON || pacman --ask 20 -U file://$PWD/perl-JSON-4.02-1-any.pkg.tar.zst"
+  - bash -lc "pacman -S --noconfirm --refresh pacman"
+  - bash -lc "pacman -S --needed --noconfirm pacman-mirrors"
+  - bash -lc "pacman -S --needed --noconfirm mingw-w64-x86_64-toolchain autoconf automake libtool make patch mingw-w64-x86_64-libtool"
+  - bash -lc "pacman -S --needed --noconfirm bison flex"
+  - bash -lc "pacman -S --needed --noconfirm perl perl-JSON"
 
 build_script:
-  - set PSDKDir=C:\Program Files\Microsoft SDKs\Windows\v7.1
-  - call "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.Cmd" /xp /x64 /Release
-  - set WIXDIR="c:\Program Files (x86)\Windows Installer XML v3.5"
+  # build using Windows 10 SDK
+  - set "WINSDKVER=10.0.22000.0"
+  - call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" amd64 %WINSDKVER%
+  - set "WIXDIR=c:\Program Files (x86)\Windows Installer XML v3.5"
   # We're not doing any codesigning in the Appveyor build yet.
-  - SET CODESIGN_PKT=0000000000000000
-  - set PATH=%PATH%;C:\Python26;C:\Perl64\bin;C:\tools\cygwin\bin;C:\Program Files (x86)\HTML Help Workshop
-  - set PATH=%PATH%;C:/msys64/usr/bin
-  - set PATH=%PATH%;C:\program files (x86)\windows installer xml v3.5\bin;C:\cygwin\bin
+  - SET "CODESIGN_PKT=0000000000000000"
+  - set "PATH=%PATH%;C:\Perl64\bin;C:\tools\cygwin\bin;C:\Program Files (x86)\HTML Help Workshop"
+  - set "PATH=%PATH%;C:/msys64/usr/bin"
+  - set "PATH=%PATH%;C:\program files (x86)\windows installer xml v3.5\bin;C:\cygwin\bin"
+  # double check this, should it be x86 or x64?
+  - set "PATH=%PATH%;%WindowsSdkVerBinPath%\x86"
+  - set "PATH=C:\Python310-x64;%PATH%"
   - set dbg__type=Debug
   - title Heimdal Build %CPU% %dbg__type%
   - echo PATH=%PATH%
-  - C:\msys64\usr\bin\bash -lc "cp /c/Windows/System32/msvcr100d.dll /c/projects/heimdal"
+  # target Windows 10 API
+  - set APPVER=10.0
   # Newer texinfo has no .exe's, so we have to invoke it as
   # "perl ...\makeinfo ...".  See doc/NTMakefile.
   - nmake /f NTMakefile APPVEYOR=1 MAKEINFO=makeinfo NO_INSTALLERS=1
index 1b134f5b77f689a5352dfe935116f6e1f24d8752..90921fe46b961278f9e645ce034d35ca883aae06 100644 (file)
@@ -12,6 +12,8 @@ endif
 
 AM_CFLAGS = $(WFLAGS)
 
+CLANG_FORMAT_STYLE = '{BasedOnStyle: Mozilla, AlwaysBreakAfterReturnType: TopLevelDefinitions, IndentWidth: 4, SortIncludes: false}'
+
 CP     = cp
 
 ## set build_HEADERZ to headers that should just be installed in build tree
@@ -139,22 +141,7 @@ check-local::
          test "$$failed" -eq 0 || exit 1; \
        fi
 
-SUFFIXES += .x .z .hx
-
-# It's useful for debugging to format generated sources.  The default for all
-# clang-format styles is to sort includes, but in many cases in-tree we really
-# don't want to do that.
-.x.c:
-       @if [ ! -x "$(CLANG_FORMAT)" ]; then \
-           cmp -s $< $@ 2> /dev/null || cp $< $@; \
-       else \
-           cp $< $@.tmp.c; \
-            $(CLANG_FORMAT) -style='{BasedOnStyle: Mozilla, AlwaysBreakAfterReturnType: TopLevelDefinitions, IndentWidth: 4, SortIncludes: false}' -i $@.tmp.c; \
-           cmp -s $@.tmp.c $@ 2> /dev/null || mv $@.tmp.c $@; \
-       fi
-
-.hx.h:
-       @cmp -s $< $@ 2> /dev/null || cp $< $@;
+SUFFIXES += .x .z
 
 SUFFIXES += .1 .3 .5 .7 .8 .cat1 .cat3 .cat5 .cat7 .cat8
 
diff --git a/third_party/heimdal/cf/ax_check_sign.m4 b/third_party/heimdal/cf/ax_check_sign.m4
new file mode 100644 (file)
index 0000000..bc2c3f0
--- /dev/null
@@ -0,0 +1,54 @@
+# ===========================================================================
+#      https://www.gnu.org/software/autoconf-archive/ax_check_sign.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_CHECK_SIGN (TYPE, [ACTION-IF-SIGNED], [ACTION-IF-UNSIGNED], [INCLUDES])
+#
+# DESCRIPTION
+#
+#   Checks whether TYPE is signed or not. If no INCLUDES are specified, the
+#   default includes are used. If ACTION-IF-SIGNED is given, it is
+#   additional shell code to execute when the type is signed. If
+#   ACTION-IF-UNSIGNED is given, it is executed when the type is unsigned.
+#
+#   This macro assumes that the type exists. Therefore the existence of the
+#   type should be checked before calling this macro. For example:
+#
+#     AC_CHECK_HEADERS([wchar.h])
+#     AC_CHECK_TYPE([wchar_t],,[ AC_MSG_ERROR([Type wchar_t not found.]) ])
+#     AX_CHECK_SIGN([wchar_t],
+#       [ AC_DEFINE(WCHAR_T_SIGNED, 1, [Define if wchar_t is signed]) ],
+#       [ AC_DEFINE(WCHAR_T_UNSIGNED, 1, [Define if wchar_t is unsigned]) ], [
+#     #ifdef HAVE_WCHAR_H
+#     #include <wchar.h>
+#     #endif
+#     ])
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Ville Laurikari <vl@iki.fi>
+#
+#   Copying and distribution of this file, with or without modification, are
+#   permitted in any medium without royalty provided the copyright notice
+#   and this notice are preserved. This file is offered as-is, without any
+#   warranty.
+
+#serial 7
+
+AU_ALIAS([VL_CHECK_SIGN], [AX_CHECK_SIGN])
+AC_DEFUN([AX_CHECK_SIGN], [
+ typename=`echo $1 | sed "s/@<:@^a-zA-Z0-9_@:>@/_/g"`
+ AC_CACHE_CHECK([whether $1 is signed], ax_cv_decl_${typename}_signed, [
+   AC_TRY_COMPILE([$4],
+     [ int foo @<:@ 1 - 2 * !((($1) -1) < 0) @:>@ ],
+     [ eval "ax_cv_decl_${typename}_signed=\"yes\"" ],
+     [ eval "ax_cv_decl_${typename}_signed=\"no\"" ])])
+ symbolname=`echo $1 | sed "s/@<:@^a-zA-Z0-9_@:>@/_/g" | tr "a-z" "A-Z"`
+ if eval "test \"\${ax_cv_decl_${typename}_signed}\" = \"yes\""; then
+   $2
+ elif eval "test \"\${ax_cv_decl_${typename}_signed}\" = \"no\""; then
+   $3
+ fi
+])dnl
diff --git a/third_party/heimdal/cf/check-compile-flag.m4 b/third_party/heimdal/cf/check-compile-flag.m4
new file mode 100644 (file)
index 0000000..bd753b3
--- /dev/null
@@ -0,0 +1,53 @@
+# ===========================================================================
+#  https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT])
+#
+# DESCRIPTION
+#
+#   Check whether the given FLAG works with the current language's compiler
+#   or gives an error.  (Warnings, however, are ignored)
+#
+#   ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
+#   success/failure.
+#
+#   If EXTRA-FLAGS is defined, it is added to the current language's default
+#   flags (e.g. CFLAGS) when the check is done.  The check is thus made with
+#   the flags: "CFLAGS EXTRA-FLAGS FLAG".  This can for example be used to
+#   force the compiler to issue an error when a bad flag is given.
+#
+#   INPUT gives an alternative input source to AC_COMPILE_IFELSE.
+#
+#   NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
+#   macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
+#   Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
+#
+#   Copying and distribution of this file, with or without modification, are
+#   permitted in any medium without royalty provided the copyright notice
+#   and this notice are preserved.  This file is offered as-is, without any
+#   warranty.
+
+#serial 6
+
+AC_DEFUN([AX_CHECK_COMPILE_FLAG],
+[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF
+AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl
+AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [
+  ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS
+  _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1"
+  AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])],
+    [AS_VAR_SET(CACHEVAR,[yes])],
+    [AS_VAR_SET(CACHEVAR,[no])])
+  _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags])
+AS_VAR_IF(CACHEVAR,yes,
+  [m4_default([$2], :)],
+  [m4_default([$3], :)])
+AS_VAR_POPDEF([CACHEVAR])dnl
+])dnl AX_CHECK_COMPILE_FLAGS
index cf5e3a88c997881da97aed3b6124253199df03c1..c0b4510b62979c54749a49bcce9e824f9577122d 100644 (file)
@@ -57,9 +57,9 @@ AS_IF([test "x$with_berkeley_db" != xno],
                   db.h                                 \
     ])])
 
-dnl db_create is used by db3 and db4 and db5
+dnl db_create is used by db3 and db4 and db5 and db6
 
-  AC_FIND_FUNC_NO_LIBS(db_create, [$dbheader] db-5 db5 db4 db3 db, [
+  AC_FIND_FUNC_NO_LIBS(db_create, [$dbheader] db-6 db-5 db4 db3 db, [
   #include <stdio.h>
   #ifdef HAVE_DBHEADER
   #include <$dbheader/db.h>
@@ -83,7 +83,7 @@ dnl db_create is used by db3 and db4 and db5
     else
       DB3LIB=""
     fi
-    AC_DEFINE(HAVE_DB3, 1, [define if you have a berkeley db3/4/5 library])
+    AC_DEFINE(HAVE_DB3, 1, [define if you have a berkeley db3/4/5/6 library])
   fi
 
 dnl dbopen is used by db1/db2
index 380412ec7a0d04afb221b1a2d2d73ce319c8d599..4c0afd9b7c33ba9718474e6e2b18521cd121e61b 100644 (file)
@@ -1,12 +1,18 @@
 dnl $Id$
 dnl
 dnl
-dnl We prefer byacc or yacc because they do not use `alloca'
+dnl OLD: We prefer byacc or yacc because they do not use `alloca'
+dnl
+dnl CURRENT: We don't mind `alloca', but we do mind `bison -y' because
+dnl          newer versions of `bison', with `-y' complain about %expect and
+dnl          anything that yacc didn't document.  Because `bison' typically
+dnl          also installs a `yacc' link that acts like `bison y', we put
+dnl          `yacc' last in this list.
 dnl
 
 AC_DEFUN([AC_KRB_PROG_YACC],
-[AC_CHECK_PROGS(YACC, byacc yacc 'bison -y')
+[AC_CHECK_PROGS(YACC, 'bison -d' 'byacc -d' yacc)
 if test "$YACC" = ""; then
-  AC_MSG_WARN([yacc not found - some stuff will not build])
+  AC_MSG_WARN([byacc and bison not found - some stuff will not build])
 fi
 ])
index 1dfcb1860b5a401e246bd077e7a277cdb33ff8d0..2c2ef834e7a35bb02a9d36d26993d73959be0987 100644 (file)
@@ -183,7 +183,6 @@ AC_CHECK_FUNCS([                            \
        asnprintf                               \
        asprintf                                \
        atexit                                  \
-       cgetent                                 \
        getauxval                               \
        getconfattr                             \
        getprogname                             \
@@ -216,11 +215,6 @@ AC_CHECK_FUNCS([                           \
        vis                                     \
 ])
 
-if test "$ac_cv_func_cgetent" = no; then
-       AC_LIBOBJ(getcap)
-fi
-AM_CONDITIONAL(have_cgetent, test "$ac_cv_func_cgetent" = yes)
-
 AC_REQUIRE([AC_FUNC_GETLOGIN])
 
 AC_REQUIRE([AC_FUNC_MMAP])
index 37a2275c283a62cb5fb6d11b77c345a3a49331a0..8c0b746ba5ce61e95df2c09a1d16b9ae1e62f033 100644 (file)
@@ -20,6 +20,7 @@ AM_PROG_CC_C_O
 AC_PROG_CPP
 AM_PATH_PYTHON
 AC_CHECK_PROG(CLANG_FORMAT, clang-format, [clang-format], [no])
+test "$CLANG_FORMAT" = no && CLANG_FORMAT=true
 
 m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
 
@@ -58,8 +59,8 @@ if ! test -f "$srcdir/lib/asn1/der-protos.h" ||
     AC_KRB_PERL_MOD(JSON)
 fi
 
-dnl AC_KRB_PROG_YACC
-AC_PROG_YACC
+AC_KRB_PROG_YACC
+dnl AC_PROG_YACC
 AM_PROG_LEX
 AS_IF([$LEX --nounput -V > /dev/null 2>&1 && test $? -eq 0],
       [AC_SUBST([FLEXNOUNPUTARGS], ["--nounput"])],
@@ -87,8 +88,6 @@ dnl
 dnl Helper bits for cross compiling
 dnl
 
-
-
 AM_CONDITIONAL(CROSS_COMPILE, test "${cross_compiling}" = yes)
 
 AC_ARG_WITH(cross-tools,
@@ -117,6 +116,14 @@ else
 
 fi
 
+AX_CHECK_COMPILE_FLAG([-Wno-error=enum-conversion],
+                      [WFLAGS_ENUM_CONV=-Wno-error=enum-conversion],
+                      [WFLAGS_ENUM_CONV=], [-Werror])
+AX_CHECK_COMPILE_FLAG([-Wno-unused-but-set-variable],
+                      [WFLAGS_UNUSED_BUT_SET_VAR=-Wno-unused-but-set-variable],
+                      [WFLAGS_UNUSED_BUT_SET_VAR=], [-Werror])
+
+AC_SUBST([WFLAGS_ENUM_CONV])
 AC_SUBST([ASN1_COMPILE])
 AC_SUBST([ASN1_COMPILE_DEP])
 AC_SUBST([SLC])
@@ -496,6 +503,20 @@ dnl export symbols
 rk_WIN32_EXPORT(BUILD_KRB5_LIB, KRB5_LIB)
 rk_WIN32_EXPORT(BUILD_ROKEN_LIB, ROKEN_LIB)
 rk_WIN32_EXPORT(BUILD_GSSAPI_LIB, GSSAPI_LIB)
+rk_WIN32_EXPORT(BUILD_KDC_LIB, KDC_LIB)
+
+dnl Deal with switch FALLTHROUGH
+AH_TOP([
+#if defined(__GNUC__)
+#if __GNUC__ >= 7
+# define fallthrough __attribute__((fallthrough))
+#else
+# define fallthrough do {} while (0) /* fallthrough */
+#endif
+#else
+# define fallthrough  do {} while (0) /* fallthrough */
+#endif
+])
 
 dnl Checks for libraries.
 
@@ -605,6 +626,15 @@ AM_CONDITIONAL(HAVE_KEYUTILS, test "$ac_cv_func_keyctl_get_persistent" = yes)
 
 AC_CHECK_SIZEOF([time_t])
 
+AX_CHECK_SIGN([time_t],
+  [ AC_DEFINE(TIME_T_SIGNED, 1, [Define if time_t is signed]) ],
+  [ AC_DEFINE(TIME_T_UNSIGNED, 1, [Define if time_t is unsigned]) ], [
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+])
+
+
 AC_CHECK_TYPES([int8_t, int16_t, int32_t, int64_t, 
        u_int8_t, u_int16_t, u_int32_t, u_int64_t,
        uint8_t, uint16_t, uint32_t, uint64_t],,,[
index 6d36ced6c3fd8a82dc6240627b68b641e907728a..45a5888f721bb7ca2605393ba3e03f86132eb839 100755 (executable)
@@ -101,33 +101,33 @@ samba_create() {
                echo "git clean -d -x -f"
                git clean -d -x -f
                echo "git read-tree..."
-               git read-tree -u --prefix=source4/heimdal-new/ local-heimdal/$lorikeet_branch || bailout $?
+               git read-tree -u --prefix=third_party/heimdal-new/ local-heimdal/$lorikeet_branch || bailout $?
                echo "git reset --mixed HEAD"
                git reset --mixed HEAD
                echo "swap old -> new"
-               mv source4/heimdal source4/heimdal-old || bailout $?
-               rsync -a source4/heimdal-new/ source4/heimdal || bailout $?
+               mv third_party/heimdal third_party/heimdal-old || bailout $?
+               rsync -a third_party/heimdal-new/ third_party/heimdal || bailout $?
        #       echo "PS1=\"'import-heimdal shell'>\"" > ../.bashrc.samba_create
        #       bash --rcfile ../.bashrc.samba_create
        #       bailout 255
                echo "add changed files to the index"
-               git add -u source4/heimdal
+               git add -u third_party/heimdal
                echo "commit the changed files blindly"
-               git commit --no-verify -m "s4:heimdal: import $lorikeet_branch (commit $lorikeet_commit)"
-               echo "cleanup source4/heimdal"
-               rm -rf source4/heimdal
-               git checkout source4/heimdal
+               git commit --no-verify -m "third_party/heimdal: import $lorikeet_branch (commit $lorikeet_commit)"
+               echo "cleanup third_party/heimdal"
+               rm -rf third_party/heimdal
+               git checkout third_party/heimdal
                echo "try to build samba"
                build_samba || {
                        echo ""
                        echo "Now build the tree and make it compile."
-                       echo "Missing files can be copied from source4/heimdal-new/"
+                       echo "Missing files can be copied from third_party/heimdal-new/"
                        echo "Also run make test!"
                }
                echo ""
-               echo "Then do a 'git add source4/heimdal' and a 'git commit --amend'"
+               echo "Then do a 'git add third_party/heimdal' and a 'git commit --amend'"
                echo "and write a useful commit message..."
-               echo "Then commit all needed changes outside of source4/heimdal"
+               echo "Then commit all needed changes outside of third_party/heimdal"
                echo "maybe splitted into multiple commits."
                echo ""
                echo "!!!!!!!!!"
index 16dd2250c20cfa21c06a372936399c67667233bc..43ebe7069472ed15631eb4158c1fc65076e7b931 100644 (file)
@@ -36,21 +36,28 @@ CLEANFILES =                        \
        base64.h                \
        ccache_plugin.h         \
        cms_asn1.h              \
+       cms_template_asn1.h     \
        com_err.h               \
        com_right.h             \
+       common_plugin.h         \
        crmf_asn1.h             \
+       crmf_template_asn1.h    \
        db_plugin.h             \
        der-private.h           \
        der-protos.h            \
        der.h                   \
        digest_asn1.h           \
+       digest_template_asn1.h  \
        editline.h              \
        err.h                   \
        getarg.h                \
        glob.h                  \
+       gss-preauth-protos.h    \
+       gss-preauth-private.h   \
        gssapi.h                \
        gssapi_asn1.h           \
        gssapi_mech.h           \
+       gssapi/gssapi_preauth.h \
        hdb-private.h           \
        hdb-protos.h            \
        hdb.h                   \
@@ -60,6 +67,8 @@ CLEANFILES =                  \
        heim_asn1.h             \
        heim_err.h              \
        heimbase.h              \
+       heimbase-svc.h          \
+       heimbase-protos.h       \
        heimntlm-protos.h       \
        heimntlm.h              \
        hex.h                   \
@@ -79,26 +88,38 @@ CLEANFILES =                        \
        krb5-types.h            \
        krb5.h                  \
        krb5_asn1.h             \
+       krb5_template_asn1.h    \
        krb5_ccapi.h            \
        krb5_err.h              \
        krb_err.h               \
+       kuserok_plugin.h        \
        kx509_asn1.h            \
+       kx509_template_asn1.h   \
        kx509_err.h             \
        locate_plugin.h         \
        login-protos.h          \
        ntlm_err.h              \
        ocsp_asn1.h             \
+       ocsp_template_asn1.h    \
        otp.h                   \
        parse_bytes.h           \
        parse_time.h            \
        parse_units.h           \
        pkcs10_asn1.h           \
+       pkcs10_template_asn1.h  \
        pkcs12_asn1.h           \
+       pkcs12_template_asn1.h  \
        pkcs8_asn1.h            \
+       pkcs8_template_asn1.h   \
        pkcs9_asn1.h            \
+       pkcs9_template_asn1.h   \
        pkinit_asn1.h           \
+       pkinit_template_asn1.h  \
        resolve.h               \
        rfc2459_asn1.h          \
+       rfc2459_template_asn1.h \
+       rfc4108_asn1.h          \
+       rfc4108_template_asn1.h \
        roken-common.h          \
        roken.h                 \
        rtbl.h                  \
@@ -111,8 +132,16 @@ CLEANFILES =                       \
        vis.h                   \
        wind.h                  \
        wind_err.h              \
-       windc_plugin.h          \
-       xdbm.h
+       kdc-plugin.h            \
+       kdc-accessors.h         \
+       kdc-audit.h             \
+       csr_authorizer_plugin.h \
+       gss_preauth_authorizer_plugin.h \
+       token_validator_plugin.h        \
+       xdbm.h                  \
+       x25519_ref10.h          \
+       x690sample_asn1.h       \
+       x690sample_template_asn1.h
 
 DISTCLEANFILES =       \
        version.h       \
index 326b67b7cc901a0e567a1fc8bf298a0709708e19..6abdb15c9113069464d7a8f207582ae8b3691a9f 100644 (file)
@@ -46,23 +46,42 @@ RCSID("$Id$");
 #include <ws2tcpip.h>
 #endif
 
-#define BITSIZE(TYPE)                                          \
-{                                                              \
-    int b = 0; TYPE x = 1, zero = 0; const char *pre = "u";    \
-    char tmp[128], tmp2[128];                                  \
-    while(x){ x <<= 1; b++; if(x < zero) pre=""; }             \
-    if(b >= len){                                              \
-        size_t tabs;                                           \
-       sprintf(tmp, "%sint%d_t" , pre, len);                   \
-       sprintf(tmp2, "typedef %s %s;", #TYPE, tmp);            \
-       tabs = 5 - strlen(tmp2) / 8;                            \
-        fprintf(f, "%s", tmp2);                                        \
-       while(tabs-- > 0) fprintf(f, "\t");                     \
-       fprintf(f, "/* %2d bits */\n", b);                      \
-        return;                                                 \
-    }                                                          \
+#ifdef HAVE_SNPRINTF
+#define BITSIZE(TYPE)                                                  \
+{                                                                      \
+    int b = 0; TYPE x = 1, zero = 0; const char *pre = "u";            \
+    char tmp[128];                                                     \
+    while(x){ x <<= 1; b++; if(x < zero) pre=""; }                     \
+    if(b >= len){                                                      \
+        size_t tabs;                                                   \
+       snprintf(tmp, sizeof(tmp), "typedef %s %sint%d_t;", #TYPE,      \
+                 pre, len);                                            \
+       tabs = 5 - strlen(tmp) / 8;                                     \
+        fprintf(f, "%s", tmp);                                         \
+       while(tabs-- > 0) fprintf(f, "\t");                             \
+       fprintf(f, "/* %2d bits */\n", b);                              \
+        return;                                                        \
+    }                                                                  \
 }
-
+#else
+#define BITSIZE(TYPE)                                          \
+{                                                              \
+    int b = 0; TYPE x = 1, zero = 0; const char *pre = "u";    \
+    char tmp[128], tmp2[128];                                  \
+    while(x){ x <<= 1; b++; if(x < zero) pre=""; }             \
+    if(b >= len){                                              \
+        size_t tabs;                                           \
+        sprintf(tmp, "%sint%d_t" , pre, len);                  \
+        sprintf(tmp2, "typedef %s %s;", #TYPE, tmp);           \
+        tabs = 5 - strlen(tmp2) / 8;                           \
+        fprintf(f, "%s", tmp2);                                \
+       while(tabs-- > 0)                                      \
+           fprintf(f, "\t");                                  \
+        fprintf(f, "/* %2d bits */\n", b);                     \
+        return;                                                \
+    }                                                         \
+}
+#endif
 #ifndef HAVE___ATTRIBUTE__
 #define __attribute__(x)
 #endif
index 2d03bf264207e0c6357a9cdc789cde448d033d01..5521181d27ccaac8e009da23981c53162e9f22d5 100644 (file)
@@ -32,6 +32,8 @@
 #ifndef __CONFIG_H__
 #define __CONFIG_H__
 
+#define fallthrough do {} while(0) /* fallthrough */
+
 #ifndef RCSID
 #define RCSID(msg) \
 static const char *const rcsid[] = { (const char *)rcsid, "@(#)" msg }
@@ -122,6 +124,24 @@ static const char *const rcsid[] = { (const char *)rcsid, "@(#)" msg }
 #endif
 #endif
 
+
+#ifdef BUILD_KDC_LIB
+#ifndef KDC_LIB
+#ifdef _WIN32
+#define KDC_LIB_FUNCTION
+#define KDC_LIB_NORETURN_FUNCTION __declspec(noreturn)
+#define KDC_LIB_CALL     __stdcall
+#define KDC_LIB_VARIABLE
+#else
+#define KDC_LIB_FUNCTION
+#define KDC_LIB_NORETURN_FUNCTION
+#define KDC_LIB_CALL
+#define KDC_LIB_VARIABLE
+#endif
+#endif
+#endif
+
+
 /* Feature macros */
 
 @FEATURE_DEFS@
@@ -199,9 +219,6 @@ static const char *const rcsid[] = { (const char *)rcsid, "@(#)" msg }
 /* Define to 1 if you have the `cap_set_proc' function. */
 /* #undef HAVE_CAP_SET_PROC */
 
-/* Define to 1 if you have the `cgetent' function. */
-/* #undef HAVE_CGETENT */
-
 /* Define if the system defines 'CHAR' type */
 #define HAVE_CHAR 1
 
@@ -793,9 +810,6 @@ static const char *const rcsid[] = { (const char *)rcsid, "@(#)" msg }
 /* Define to 1 if you have the `setstate' function. */
 /* #define HAVE_SETSTATE 1 */
 
-/* Define to 1 if you have the `sgi_getcapabilitybyname' function. */
-/* #undef HAVE_SGI_GETCAPABILITYBYNAME */
-
 /* Define to 1 if you have the <sgtty.h> header file. */
 /* #undef HAVE_SGTTY_H */
 
@@ -887,6 +901,17 @@ static const char *const rcsid[] = { (const char *)rcsid, "@(#)" msg }
 /* Define if you have the function `strtok_r'. */
 /* #define HAVE_STRTOK_R 1 */
 
+#if defined(__has_include)
+# if __has_include(<corecrt.h>)
+#  define HAVE_UCRT 1
+# endif
+#endif
+
+#ifdef HAVE_UCRT
+#define HAVE_STRTOLL 1
+#define HAVE_STRTOULL 1
+#endif
+
 /* Define to 1 if the system has the type `struct addrinfo'. */
 #define HAVE_STRUCT_ADDRINFO 1
 
index b3d6d581d9b34a7bf51afd6b04035a96c9f4d688..e2dc303b8dc9c892aa9121ae0952f6a4fb38f966 100644 (file)
@@ -58,7 +58,7 @@ read_words (const char *filename, char ***ret_w)
        buf[strcspn(buf, "\r\n")] = '\0';
        if (n >= alloc) {
            alloc = max(alloc + 16, alloc * 2);
-           w = erealloc (w, alloc * sizeof(char **));
+           w = erealloc (w, alloc * sizeof(char *));
        }
        len = strlen(buf);
        if (wptr + len + 1 >= wend) {
index 0ababf4f1976532a02bfb8bc7a43dafde50ceef5..d128ab7f49ef690c4a47a474ff6c5a100665ed01 100644 (file)
@@ -46,7 +46,7 @@ add_enctype(struct add_enctype_options*opt, int argc, char **argv)
     krb5_error_code ret;
     const char *princ_name;
     int i, j;
-    krb5_key_data *new_key_data;
+    krb5_key_data *new_key_data = NULL;
     int n_etypes;
     krb5_enctype *etypes;
 
@@ -108,7 +108,6 @@ add_enctype(struct add_enctype_options*opt, int argc, char **argv)
                /* XXX Should this be an error?  The admin can del_enctype... */
                krb5_warnx(context, "enctype %d already exists",
                           (int)etypes[j]);
-               free(new_key_data);
                goto out;
            }
        }
@@ -163,6 +162,7 @@ add_enctype(struct add_enctype_options*opt, int argc, char **argv)
     if (ret)
        krb5_warn(context, ret, "kadm5_modify_principal");
 out:
+    free(new_key_data);
     krb5_free_principal (context, princ_ent);
     kadm5_free_principal_ent(kadm_handle, &princ);
 out2:
index 1e5cd6117dcfab40f2d4f3b55dbfd9b3d3f8f550..4b89ca6eedd4b6527ab589e5003a90426f940764 100644 (file)
@@ -89,6 +89,7 @@ add_one_principal(const char *name,
     int mask = 0;
     int default_mask = 0;
     char pwbuf[1024];
+    char *princ_name = NULL;
 
     memset(&princ, 0, sizeof(princ));
     ret = krb5_parse_name(context, name, &princ_ent);
@@ -96,6 +97,14 @@ add_one_principal(const char *name,
        krb5_warn(context, ret, "krb5_parse_name");
        return ret;
     }
+
+    if (rand_password) {
+       ret = krb5_unparse_name(context, princ_ent, &princ_name);
+       if (ret) {
+           krb5_warn(context, ret, "krb5_parse_name");
+           goto out;
+       }
+    }
     princ.principal = princ_ent;
     mask |= KADM5_PRINCIPAL;
 
@@ -129,7 +138,6 @@ add_one_principal(const char *name,
        random_password (pwbuf, sizeof(pwbuf));
        password = pwbuf;
     } else if(password == NULL) {
-       char *princ_name;
        char *prompt;
        int aret;
 
@@ -137,7 +145,6 @@ add_one_principal(const char *name,
        if (ret)
            goto out;
        aret = asprintf (&prompt, "%s's Password: ", princ_name);
-       free (princ_name);
        if (aret == -1) {
            ret = ENOMEM;
            krb5_set_error_message(context, ret, "out of memory");
@@ -205,18 +212,17 @@ add_one_principal(const char *name,
        kadm5_modify_principal(kadm_handle, &princ,
                               KADM5_PW_EXPIRATION | KADM5_ATTRIBUTES);
     } else if (rand_password) {
-       char *princ_name;
-
-       krb5_unparse_name(context, princ_ent, &princ_name);
        printf ("added %s with password \"%s\"\n", princ_name, password);
-       free (princ_name);
     }
 out:
+    free(princ_name);
     kadm5_free_principal_ent(kadm_handle, &princ); /* frees princ_ent */
     if(default_ent)
        kadm5_free_principal_ent (kadm_handle, default_ent);
-    if (password != NULL)
-       memset (password, 0, strlen(password));
+    if (password != NULL) {
+       size_t len = strlen(password);
+       memset_s(password, len, 0, len);
+    }
     return ret;
 }
 
@@ -354,7 +360,6 @@ add_one_namespace(const char *name,
 {
     krb5_error_code ret;
     kadm5_principal_ent_rec princ;
-    kadm5_principal_ent_rec *default_ent = NULL;
     krb5_principal princ_ent = NULL;
     int mask = 0;
     int default_mask = 0;
@@ -391,6 +396,8 @@ add_one_namespace(const char *name,
         ret = krb5_parse_name(context, name, &princ_ent);
         if (ret)
             krb5_warn(context, ret, "krb5_parse_name");
+       else
+           princ.principal = princ_ent;
     }
     if (ret != 0)
        return ret;
@@ -449,7 +456,6 @@ add_one_namespace(const char *name,
     }
 
     if (ret == 0) {
-        princ.principal = princ_ent;
         mask |= KADM5_PRINCIPAL | KADM5_KVNO;
 
         ret = set_entry(context, &princ, &mask,
@@ -457,21 +463,21 @@ add_one_namespace(const char *name,
                         "never", "never", attributes, NSPOLICY);
     }
     if (ret == 0)
-        ret = edit_entry(&princ, &mask, default_ent, default_mask);
+        ret = edit_entry(&princ, &mask, NULL, default_mask);
 
     if (ret == 0)
         ret = kstuple2etypes(&princ, &mask, nkstuple, kstuple);
 
     /* XXX Shouldn't need a password for this */
     random_password(pwbuf, sizeof(pwbuf));
-    ret = kadm5_create_principal_3(kadm_handle, &princ, mask,
-                                   nkstuple, kstuple, pwbuf);
-    if (ret)
-       krb5_warn(context, ret, "kadm5_create_principal_3");
+    if (ret == 0) {
+        ret = kadm5_create_principal_3(kadm_handle, &princ, mask,
+                                       nkstuple, kstuple, pwbuf);
+        if (ret)
+            krb5_warn(context, ret, "kadm5_create_principal_3");
+    }
 
     kadm5_free_principal_ent(kadm_handle, &princ); /* frees princ_ent */
-    if (default_ent)
-       kadm5_free_principal_ent(kadm_handle, default_ent);
     memset(pwbuf, 0, sizeof(pwbuf));
     return ret;
 }
index d254add4482dd5fb80f33c9ba8092b1086de47af..2f3c1c1bcd74f921d05fe8c52fce6f47a27afafe 100644 (file)
@@ -65,17 +65,17 @@ set_random_password (krb5_principal principal, int keepold)
 {
     krb5_error_code ret;
     char pw[128];
+    char *princ_name;
 
-    random_password (pw, sizeof(pw));
-    ret = kadm5_chpass_principal_3(kadm_handle, principal, keepold, 0, NULL, pw);
-    if (ret == 0) {
-       char *princ_name;
-
-       krb5_unparse_name(context, principal, &princ_name);
+    ret = krb5_unparse_name(context, principal, &princ_name);
+    if (ret)
+       return ret;
 
+    random_password(pw, sizeof(pw));
+    ret = kadm5_chpass_principal_3(kadm_handle, principal, keepold, 0, NULL, pw);
+    if (ret == 0)
        printf ("%s's password set to \"%s\"\n", princ_name, pw);
-       free (princ_name);
-    }
+    free(princ_name);
     memset_s(pw, sizeof(pw), 0, sizeof(pw));
     return ret;
 }
index 089ee8b0d805fd5e6944dbe8b8e5786482383d03..a066f56ea3875a240a6f2f07a1e9fd5370a0c621 100644 (file)
@@ -61,12 +61,15 @@ do_del_ns_entry(krb5_principal nsp, void *data)
     krb5_principal p = NULL;
     const char *comp0 = krb5_principal_get_comp_string(context, nsp, 0);
     const char *comp1 = krb5_principal_get_comp_string(context, nsp, 1);
-    char *unsp = NULL;
 
     if (krb5_principal_get_num_comp(context, nsp) != 2) {
-        (void) krb5_unparse_name(context, nsp, &unsp);
-        krb5_warn(context, ret = EINVAL, "Not a valid namespace name %s",
-                   unsp ? unsp : "<Out of memory>");
+        char *unsp = NULL;
+
+        ret = krb5_unparse_name(context, nsp, &unsp);
+        krb5_warn(context, ret,
+                  "Not a valid namespace name (component count is not 2): %s",
+                  unsp ? unsp : "<out of memory>");
+        free(unsp);
         return EINVAL;
     }
 
@@ -80,7 +83,6 @@ do_del_ns_entry(krb5_principal nsp, void *data)
     if (ret == 0)
         ret = kadm5_delete_principal(kadm_handle, p);
     krb5_free_principal(context, p);
-    free(unsp);
     return ret;
 }
 
index 01725d96e207dcc410e8d98ca7965642f99cc8a8..adb2e28518aad8f0097e4d14043e5a9db4fe8bd6 100644 (file)
@@ -148,7 +148,7 @@ do_ext_keytab(krb5_principal principal, void *data)
     }
     free(unparsed);
     free(keys);
-    return 0;
+    return ret;
 }
 
 int
index 35766aa1bfc57b1e80bcb2026f1b6fb9e2da5d79..a884e11e96be481fb40cdc39708871d5c24702f9 100644 (file)
@@ -349,6 +349,7 @@ format_field(struct get_entry_data *data,
                     if (i)
                         strlcat(buf, ",", buf_len);
                     strlcat(buf, str, buf_len);
+                   krb5_xfree(str);
                 }
             }
             free_HDB_EncTypeList(&etypes);
@@ -632,6 +633,7 @@ list_princs(struct list_options *opt, int argc, char **argv)
        krb5_warnx(context, "programmer error: sizeof(struct get_options) != sizeof(struct list_options)");
        return 0;
     }
+    memset(&get_opt, 0, sizeof(get_opt));
     get_opt.long_flag = opt->long_flag;
     get_opt.short_flag = opt->short_flag;
     get_opt.terse_flag = opt->terse_flag;
index 8b025e112f8a45344c4f61c1a26516931a076f66..8a3725e3c49c430b4e78cb041e8cbaab5e1e3602 100644 (file)
@@ -73,7 +73,20 @@ create_random_entry(krb5_principal princ,
     ent.attributes |= attributes | KRB5_KDB_DISALLOW_ALL_TIX;
     mask |= KADM5_ATTRIBUTES | KADM5_KEY_DATA;
 
-    /* Create the entry with no keys or password */
+    /*
+     * Create the entry with no keys or password.
+     *
+     * XXX Note that using kadm5_s_*() here means that `kadmin init` must
+     *     always be local (`kadmin -l init`).  This might seem like a very
+     *     obvious thing, but since our KDC daemons support multiple realms
+     *     there is no reason that `init SOME.REALM.EXAMPLE` couldn't be
+     *     remoted.
+     *
+     *     Granted, one might want all such operations to be local anyways --
+     *     perhaps for authorization reasons, since we don't really have that
+     *     great a story for authorization in kadmind at this time, especially
+     *     for realm creation.
+     */
     ret = kadm5_s_create_principal_with_key(kadm_handle, &ent, mask);
     if(ret) {
        if (ret == KADM5_DUP && (flags & CRE_DUP_OK))
@@ -127,21 +140,21 @@ init(struct init_options *opt, int argc, char **argv)
 
     if (!local_flag) {
        krb5_warnx(context, "init is only available in local (-l) mode");
-       return 0;
+       return 1;
     }
 
     if (opt->realm_max_ticket_life_string) {
        if (str2deltat (opt->realm_max_ticket_life_string, &max_life) != 0) {
            krb5_warnx (context, "unable to parse \"%s\"",
                        opt->realm_max_ticket_life_string);
-           return 0;
+           return 1;
        }
     }
     if (opt->realm_max_renewable_life_string) {
        if (str2deltat (opt->realm_max_renewable_life_string, &max_rlife) != 0) {
            krb5_warnx (context, "unable to parse \"%s\"",
                        opt->realm_max_renewable_life_string);
-           return 0;
+           return 1;
        }
     }
 
@@ -150,107 +163,164 @@ init(struct init_options *opt, int argc, char **argv)
     ret = db->hdb_open(context, db, O_RDWR | O_CREAT, 0600);
     if(ret){
        krb5_warn(context, ret, "hdb_open");
-       return 0;
+       return 1;
     }
     ret = kadm5_log_reinit(kadm_handle, 0);
-    if (ret)
-        krb5_err(context, 1, ret, "Failed iprop log initialization");
-    kadm5_log_end(kadm_handle);
+    if (ret) {
+        krb5_warn(context, ret, "Failed iprop log initialization");
+        return 1;
+    }
+    ret = kadm5_log_end(kadm_handle);
     db->hdb_close(context, db);
+    if (ret) {
+        krb5_warn(context, ret, "Failed iprop log initialization");
+        return 1;
+    }
+
     for(i = 0; i < argc; i++){
-       krb5_principal princ;
+       krb5_principal princ = NULL;
        const char *realm = argv[i];
 
        if (opt->realm_max_ticket_life_string == NULL) {
            max_life = 0;
            if(edit_deltat ("Realm max ticket life", &max_life, NULL, 0)) {
-               return 0;
+               return 1;
            }
        }
        if (opt->realm_max_renewable_life_string == NULL) {
            max_rlife = 0;
            if(edit_deltat("Realm max renewable ticket life", &max_rlife,
                           NULL, 0)) {
-               return 0;
+               return 1;
            }
        }
 
        /* Create `krbtgt/REALM' */
        ret = krb5_make_principal(context, &princ, realm,
                                  KRB5_TGS_NAME, realm, NULL);
-       if(ret)
-           return 0;
-
-       create_random_entry(princ, max_life, max_rlife, 0, 0);
+        if (ret == 0)
+            ret = create_random_entry(princ, max_life, max_rlife, 0, 0);
        krb5_free_principal(context, princ);
+        if (ret) {
+            krb5_warn(context, ret, "Failed to create %s@%s", KRB5_TGS_NAME,
+                      realm);
+           return 1;
+        }
 
        if (opt->bare_flag)
            continue;
 
        /* Create `kadmin/changepw' */
-       krb5_make_principal(context, &princ, realm,
-                           "kadmin", "changepw", NULL);
+       ret = krb5_make_principal(context, &princ, realm, "kadmin",
+                                  "changepw", NULL);
        /*
         * The Windows XP (at least) password changing protocol
         * request the `kadmin/changepw' ticket with `renewable_ok,
         * renewable, forwardable' and so fails if we disallow
         * forwardable here.
         */
-       create_random_entry(princ, 5*60, 5*60,
-                           KRB5_KDB_DISALLOW_TGT_BASED|
-                           KRB5_KDB_PWCHANGE_SERVICE|
-                           KRB5_KDB_DISALLOW_POSTDATED|
-                           KRB5_KDB_DISALLOW_RENEWABLE|
-                           KRB5_KDB_DISALLOW_PROXIABLE|
-                           KRB5_KDB_REQUIRES_PRE_AUTH,
-                           0);
+        if (ret == 0)
+            ret = create_random_entry(princ, 5*60, 5*60,
+                                      KRB5_KDB_DISALLOW_TGT_BASED|
+                                      KRB5_KDB_PWCHANGE_SERVICE|
+                                      KRB5_KDB_DISALLOW_POSTDATED|
+                                      KRB5_KDB_DISALLOW_RENEWABLE|
+                                      KRB5_KDB_DISALLOW_PROXIABLE|
+                                      KRB5_KDB_REQUIRES_PRE_AUTH,
+                                      0);
        krb5_free_principal(context, princ);
+        if (ret) {
+            krb5_warn(context, ret, "Failed to create kadmin/changepw@%s",
+                      realm);
+            return 1;
+        }
 
        /* Create `kadmin/admin' */
-       krb5_make_principal(context, &princ, realm,
-                           "kadmin", "admin", NULL);
-       create_random_entry(princ, 60*60, 60*60, KRB5_KDB_REQUIRES_PRE_AUTH, 0);
+       ret = krb5_make_principal(context, &princ, realm,
+                                  "kadmin", "admin", NULL);
+        if (ret == 0)
+            ret = create_random_entry(princ, 60*60, 60*60,
+                                      KRB5_KDB_REQUIRES_PRE_AUTH, 0);
        krb5_free_principal(context, princ);
+        if (ret) {
+            krb5_warn(context, ret, "Failed to create kadmin/admin@%s", realm);
+            return 1;
+        }
 
        /* Create `changepw/kerberos' (for v4 compat) */
-       krb5_make_principal(context, &princ, realm,
-                           "changepw", "kerberos", NULL);
-       create_random_entry(princ, 60*60, 60*60,
-                           KRB5_KDB_DISALLOW_TGT_BASED|
-                           KRB5_KDB_PWCHANGE_SERVICE, 0);
-
+       ret = krb5_make_principal(context, &princ, realm,
+                                  "changepw", "kerberos", NULL);
+        if (ret == 0)
+            ret = create_random_entry(princ, 60*60, 60*60,
+                                      KRB5_KDB_DISALLOW_TGT_BASED|
+                                      KRB5_KDB_PWCHANGE_SERVICE, 0);
        krb5_free_principal(context, princ);
+        if (ret) {
+            krb5_warn(context, ret, "Failed to create changepw/kerberos@%s",
+                      realm);
+            return 1;
+        }
 
        /* Create `kadmin/hprop' for database propagation */
-       krb5_make_principal(context, &princ, realm,
-                           "kadmin", "hprop", NULL);
-       create_random_entry(princ, 60*60, 60*60,
-                           KRB5_KDB_REQUIRES_PRE_AUTH|
-                           KRB5_KDB_DISALLOW_TGT_BASED, 0);
+        ret = krb5_make_principal(context, &princ, realm,
+                                  "kadmin", "hprop", NULL);
+        if (ret == 0)
+            ret = create_random_entry(princ, 60*60, 60*60,
+                                      KRB5_KDB_REQUIRES_PRE_AUTH|
+                                      KRB5_KDB_DISALLOW_TGT_BASED, 0);
        krb5_free_principal(context, princ);
+        if (ret) {
+            krb5_warn(context, ret, "Failed to create kadmin/hprop@%s", realm);
+            return 1;
+        }
 
        /* Create `WELLKNOWN/ANONYMOUS' for anonymous as-req */
-       krb5_make_principal(context, &princ, realm,
-                           KRB5_WELLKNOWN_NAME, KRB5_ANON_NAME, NULL);
-       create_random_entry(princ, 60*60, 60*60,
-                           KRB5_KDB_REQUIRES_PRE_AUTH, 0);
+        ret = krb5_make_principal(context, &princ, realm, KRB5_WELLKNOWN_NAME,
+                                  KRB5_ANON_NAME, NULL);
+        if (ret == 0)
+            ret = create_random_entry(princ, 60*60, 60*60,
+                                      KRB5_KDB_REQUIRES_PRE_AUTH, 0);
        krb5_free_principal(context, princ);
+        if (ret) {
+            krb5_warn(context, ret, "Failed to create %s/%s@%s",
+                      KRB5_WELLKNOWN_NAME, KRB5_ANON_NAME, realm);
+            return 1;
+        }
 
-       /* Create `WELLKNOWN/FEDERATED' for GSS preauth */
-       krb5_make_principal(context, &princ, realm,
-                           KRB5_WELLKNOWN_NAME, KRB5_FEDERATED_NAME, NULL);
-       create_random_entry(princ, 60*60, 60*60,
-                           KRB5_KDB_REQUIRES_PRE_AUTH, 0);
-       krb5_free_principal(context, princ);
+        /* Create `WELLKNOWN/FEDERATED' for GSS preauth */
+        ret = krb5_make_principal(context, &princ, realm,
+                                  KRB5_WELLKNOWN_NAME, KRB5_FEDERATED_NAME, NULL);
+        if (ret == 0)
+            ret = create_random_entry(princ, 60*60, 60*60,
+                                      KRB5_KDB_REQUIRES_PRE_AUTH, 0);
+        krb5_free_principal(context, princ);
+        if (ret) {
+            krb5_warn(context, ret, "Failed to create %s/%s@%s",
+                      KRB5_WELLKNOWN_NAME, KRB5_FEDERATED_NAME, realm);
+            return 1;
+        }
 
-       /* Create `WELLKNONW/org.h5l.fast-cookie@WELLKNOWN:ORG.H5L' for FAST cookie */
-       krb5_make_principal(context, &princ, KRB5_WELLKNOWN_ORG_H5L_REALM,
-                           KRB5_WELLKNOWN_NAME, "org.h5l.fast-cookie", NULL);
-       create_random_entry(princ, 60*60, 60*60,
-                           KRB5_KDB_REQUIRES_PRE_AUTH|
-                           KRB5_KDB_DISALLOW_TGT_BASED|
-                           KRB5_KDB_DISALLOW_ALL_TIX, CRE_DUP_OK);
-       krb5_free_principal(context, princ);
+        /*
+         * Create `WELLKNONW/org.h5l.fast-cookie@WELLKNOWN:ORG.H5L' for FAST cookie.
+         *
+         * There can be only one.
+         */
+        if (i == 0) {
+            ret = krb5_make_principal(context, &princ, KRB5_WELLKNOWN_ORG_H5L_REALM,
+                                      KRB5_WELLKNOWN_NAME, "org.h5l.fast-cookie", NULL);
+            if (ret == 0)
+                ret = create_random_entry(princ, 60*60, 60*60,
+                                          KRB5_KDB_REQUIRES_PRE_AUTH|
+                                          KRB5_KDB_DISALLOW_TGT_BASED|
+                                          KRB5_KDB_DISALLOW_ALL_TIX, CRE_DUP_OK);
+            krb5_free_principal(context, princ);
+            if (ret && ret != KADM5_DUP) {
+                krb5_warn(context, ret,
+                          "Failed to create %s/org.h5l.fast-cookie@%s",
+                          KRB5_WELLKNOWN_NAME, KRB5_WELLKNOWN_ORG_H5L_REALM);
+                return 1;
+            }
+        }
 
        /* Create `default' */
        {
@@ -259,18 +329,20 @@ init(struct init_options *opt, int argc, char **argv)
 
            memset (&ent, 0, sizeof(ent));
            mask |= KADM5_PRINCIPAL;
-           krb5_make_principal(context, &ent.principal, realm,
-                               "default", NULL);
            mask |= KADM5_MAX_LIFE;
-           ent.max_life = 24 * 60 * 60;
            mask |= KADM5_MAX_RLIFE;
+           mask |= KADM5_ATTRIBUTES;
+           ent.max_life = 24 * 60 * 60;
            ent.max_renewable_life = 7 * ent.max_life;
            ent.attributes = KRB5_KDB_DISALLOW_ALL_TIX;
-           mask |= KADM5_ATTRIBUTES;
-
-           ret = kadm5_create_principal(kadm_handle, &ent, mask, "");
-           if (ret)
-               krb5_err (context, 1, ret, "kadm5_create_principal");
+           ret = krb5_make_principal(context, &ent.principal, realm,
+                                      "default", NULL);
+            if (ret == 0)
+                ret = kadm5_create_principal(kadm_handle, &ent, mask, "");
+           if (ret) {
+               krb5_warn(context, ret, "Failed to create default@%s", realm);
+                return 1;
+            }
 
            krb5_free_principal(context, ent.principal);
        }
index 0817b7c93aa4f8a59861e041e42ae77483a2329b..0eeaf508da84b54e58520508dc7bd0a2869e67ce 100644 (file)
@@ -261,12 +261,9 @@ start_server(krb5_context contextp, const char *port_str)
        for(ap = ai; ap; ap = ap->ai_next)
            i++;
        tmp = realloc(socks, (num_socks + i) * sizeof(*socks));
-       if(tmp == NULL) {
-           krb5_warnx(contextp, "failed to reallocate %lu bytes",
-                      (unsigned long)(num_socks + i) * sizeof(*socks));
-            freeaddrinfo(ai);
-           continue;
-       }
+       if(tmp == NULL)
+           krb5_err(contextp, 1, errno, "failed to reallocate %lu bytes",
+                    (unsigned long)(num_socks + i) * sizeof(*socks));
        socks = tmp;
        for(ap = ai; ap; ap = ap->ai_next) {
            krb5_socket_t s = socket(ap->ai_family, ap->ai_socktype, ap->ai_protocol);
index 401b6a9f6ba0554193dd36e656bb30666492fab4..b0e852931c6b33f4c50a93bd2282fa4279bbd104 100644 (file)
@@ -166,13 +166,20 @@ and
 sub-commands rather than having to edit the KDC's configuration
 file and having to restart the KDC.
 .Pp
-However, there is currently no way to alias namespaces via HDB
-entry aliases.
-To issue referrals for entire namespaces use the
+There are two methods for issuing referrals for entire namespaces
+of hostnames.
+An alias of the form
+.Ar  WELLKNOWN/HOSTBASED-NAMESPACE/service/namespace-fqdn@REALM
+(see
+.Nm add_namespace
+below) will cause all requests for host-based principals in the
+given namespace to be referred to the given realm.
+Alternatively, the KDC will issue referrals for all host-based
+service principals whose hostname component matches a
 .Ar [domain_realm]
-section of the KDC's
+entry in the KDC's
 .Ar krb5.conf
-file.
+file referring to a different realm.
 .Ed
 .Pp
 .Nm add_namespace
@@ -182,18 +189,23 @@ file.
 .Op Fl Fl max-ticket-life= Ns Ar lifetime
 .Op Fl Fl max-renewable-life= Ns Ar lifetime
 .Op Fl Fl attributes= Ns Ar attributes
-.Ar principal...
+.Ar host-based-principal...
 .Bd -ragged -offset indent
 Adds a new namespace of virtual host-based or domain-based
 principals to the database, whose keys will be automatically
 derived from base keys stored in the namespace record, and which
 keys will be rotated automatically.
-The namespace names should look like
-.Ar hostname@REALM
+The namespace names are of the same form as host-based principal
+names:
+.Ar service/hostname@REALM
 and these will match all host-based or domain-based service names
 where hostname component of such a principal ends in the labels
 of the hostname in the namespace name.
 .Pp
+The service name component may be a wild-card (underscore,
+.Ar _ ),
+in which case it will match any service.
+.Pp
 For example,
 .Ar bar.baz.example@BAZ.EXAMPLE
 will match
@@ -223,6 +235,11 @@ The default enctypes is as for the
 .Nm add
 command.
 .Pp
+Note that namespaces are stored as principals whose names are of the form
+.Ar WELLKNOWN/HOSTBASED-NAMESPACE/service/namespace.fqdn@REALM ,
+with the
+.Ar service
+.Pp
 This command has the following alias:
 .Nm add_ns .
 .Ed
index 10bbea840576409692110f40f7ff5472b41fcc02..444950623f0b7c0c1f5e8ded0b822fccad33cb86 100644 (file)
@@ -134,6 +134,8 @@ main(int argc, char **argv)
 
     argc -= optidx;
     argv += optidx;
+    if (argc != 0)
+        usage(1);
 
     if (config_file == NULL) {
        int aret;
index 971c24793c05d11d5efb1a386b9a70a07f30ac27..f62f8b96dcc05d597a2578a70b753bcb500f9389 100644 (file)
@@ -367,7 +367,7 @@ my_fgetln(FILE *f, char **bufp, size_t *szp, size_t *lenp)
     size_t len;
     size_t sz = *szp;
     char *buf = *bufp;
-    char *p, *n;
+    char *n;
 
     if (!buf) {
         buf = malloc(sz ? sz : 8192);
@@ -378,7 +378,7 @@ my_fgetln(FILE *f, char **bufp, size_t *szp, size_t *lenp)
     }
 
     len = 0;
-    while ((p = fgets(&buf[len], sz-len, f)) != NULL) {
+    while (fgets(&buf[len], sz-len, f) != NULL) {
         len += strlen(&buf[len]);
         if (buf[len-1] == '\n')
             break;
@@ -418,7 +418,7 @@ doit(const char *filename, int mergep)
     int lineno;
     int flags = O_RDWR;
     struct entry e;
-    hdb_entry_ex ent;
+    hdb_entry ent;
     HDB *db = _kadm5_s_get_db(kadm_handle);
 
     f = fopen(filename, "r");
@@ -506,7 +506,7 @@ doit(const char *filename, int mergep)
        skip_next(p);
 
        memset(&ent, 0, sizeof(ent));
-       ret2 = krb5_parse_name(context, e.principal, &ent.entry.principal);
+       ret2 = krb5_parse_name(context, e.principal, &ent.principal);
        if (ret2) {
            const char *msg = krb5_get_error_message(context, ret);
            fprintf(stderr, "%s:%d:%s (%s)\n",
@@ -516,92 +516,92 @@ doit(const char *filename, int mergep)
            continue;
        }
 
-       if (parse_keys(&ent.entry, e.key)) {
+       if (parse_keys(&ent, e.key)) {
            fprintf (stderr, "%s:%d:error parsing keys (%s)\n",
                     filename, lineno, e.key);
-           hdb_free_entry (context, &ent);
+           hdb_free_entry (context, db, &ent);
             ret = 1;
            continue;
        }
 
-       if (parse_event(&ent.entry.created_by, e.created) == -1) {
+       if (parse_event(&ent.created_by, e.created) == -1) {
            fprintf (stderr, "%s:%d:error parsing created event (%s)\n",
                     filename, lineno, e.created);
-           hdb_free_entry (context, &ent);
+           hdb_free_entry (context, db, &ent);
             ret = 1;
            continue;
        }
-       if (parse_event_alloc (&ent.entry.modified_by, e.modified) == -1) {
+       if (parse_event_alloc (&ent.modified_by, e.modified) == -1) {
            fprintf (stderr, "%s:%d:error parsing event (%s)\n",
                     filename, lineno, e.modified);
-           hdb_free_entry (context, &ent);
+           hdb_free_entry (context, db, &ent);
             ret = 1;
            continue;
        }
-       if (parse_time_string_alloc (&ent.entry.valid_start, e.valid_start) == -1) {
+       if (parse_time_string_alloc (&ent.valid_start, e.valid_start) == -1) {
            fprintf (stderr, "%s:%d:error parsing time (%s)\n",
                     filename, lineno, e.valid_start);
-           hdb_free_entry (context, &ent);
+           hdb_free_entry (context, db, &ent);
             ret = 1;
            continue;
        }
-       if (parse_time_string_alloc (&ent.entry.valid_end,   e.valid_end) == -1) {
+       if (parse_time_string_alloc (&ent.valid_end,   e.valid_end) == -1) {
            fprintf (stderr, "%s:%d:error parsing time (%s)\n",
                     filename, lineno, e.valid_end);
-           hdb_free_entry (context, &ent);
+           hdb_free_entry (context, db, &ent);
             ret = 1;
            continue;
        }
-       if (parse_time_string_alloc (&ent.entry.pw_end,      e.pw_end) == -1) {
+       if (parse_time_string_alloc (&ent.pw_end,      e.pw_end) == -1) {
            fprintf (stderr, "%s:%d:error parsing time (%s)\n",
                     filename, lineno, e.pw_end);
-           hdb_free_entry (context, &ent);
+           hdb_free_entry (context, db, &ent);
             ret = 1;
            continue;
        }
 
-       if (parse_integer_alloc (&ent.entry.max_life,  e.max_life) == -1) {
+       if (parse_integer_alloc (&ent.max_life,  e.max_life) == -1) {
            fprintf (stderr, "%s:%d:error parsing lifetime (%s)\n",
                     filename, lineno, e.max_life);
-           hdb_free_entry (context, &ent);
+           hdb_free_entry (context, db, &ent);
             ret = 1;
            continue;
 
        }
-       if (parse_integer_alloc (&ent.entry.max_renew, e.max_renew) == -1) {
+       if (parse_integer_alloc (&ent.max_renew, e.max_renew) == -1) {
            fprintf (stderr, "%s:%d:error parsing lifetime (%s)\n",
                     filename, lineno, e.max_renew);
-           hdb_free_entry (context, &ent);
+           hdb_free_entry (context, db, &ent);
             ret = 1;
            continue;
        }
 
-       if (parse_hdbflags2int (&ent.entry.flags, e.flags) != 1) {
+       if (parse_hdbflags2int (&ent.flags, e.flags) != 1) {
            fprintf (stderr, "%s:%d:error parsing flags (%s)\n",
                     filename, lineno, e.flags);
-           hdb_free_entry (context, &ent);
+           hdb_free_entry (context, db, &ent);
             ret = 1;
            continue;
        }
 
-       if(parse_generation(e.generation, &ent.entry.generation) == -1) {
+       if(parse_generation(e.generation, &ent.generation) == -1) {
            fprintf (stderr, "%s:%d:error parsing generation (%s)\n",
                     filename, lineno, e.generation);
-           hdb_free_entry (context, &ent);
+           hdb_free_entry (context, db, &ent);
             ret = 1;
            continue;
        }
 
-       if (parse_extensions(&e.extensions, &ent.entry.extensions) == -1) {
+       if (parse_extensions(&e.extensions, &ent.extensions) == -1) {
            fprintf (stderr, "%s:%d:error parsing extension (%s)\n",
                     filename, lineno, e.extensions);
-           hdb_free_entry (context, &ent);
+           hdb_free_entry (context, db, &ent);
             ret = 1;
            continue;
        }
 
        ret2 = db->hdb_store(context, db, HDB_F_REPLACE, &ent);
-       hdb_free_entry (context, &ent);
+       hdb_free_entry (context, db, &ent);
        if (ret2) {
            krb5_warn(context, ret2, "db_store");
            break;
index 9541c6efcb41c0077e79821813aa13ea43dd0e85..7c7b2dd7ce447bcaadc739d95777aad402b2785d 100644 (file)
@@ -123,7 +123,7 @@ static void
 add_aliases(krb5_context contextp, kadm5_principal_ent_rec *princ,
            struct getarg_strings *strings)
 {
-    krb5_error_code ret;
+    krb5_error_code ret = 0;
     HDB_extension ext;
     krb5_data buf;
     krb5_principal p;
@@ -144,9 +144,16 @@ add_aliases(krb5_context contextp, kadm5_principal_ent_rec *princ,
                   sizeof(ext.data.u.aliases.aliases.val[0]));
        ext.data.u.aliases.aliases.len = strings->num_strings;
 
-       for (i = 0; i < strings->num_strings; i++) {
+       for (i = 0; ret == 0 && i < strings->num_strings; i++) {
            ret = krb5_parse_name(contextp, strings->strings[i], &p);
-           ret = copy_Principal(p, &ext.data.u.aliases.aliases.val[i]);
+            if (ret)
+                krb5_err(contextp, 1, ret, "Could not parse alias %s",
+                         strings->strings[i]);
+            if (ret == 0)
+                ret = copy_Principal(p, &ext.data.u.aliases.aliases.val[i]);
+            if (ret)
+                krb5_err(contextp, 1, ret, "Could not copy parsed alias %s",
+                         strings->strings[i]);
            krb5_free_principal(contextp, p);
        }
     }
@@ -224,6 +231,7 @@ add_etypes(krb5_context contextp,
         if (ret) {
             krb5_warn(contextp, ret, "Could not parse enctype %s",
                       strings->strings[i]);
+            free(etypes.val);
             return ret;
         }
         etypes.val[i] = etype;
@@ -236,6 +244,7 @@ add_etypes(krb5_context contextp,
     if (ret || buf.length != size)
         abort();
     add_tl(princ, KRB5_TL_ETYPES, &buf);
+    free(etypes.val);
     return 0;
 }
 
index 6ddb9dfa865433ef067a3c24622effaa1bb5f32f..1ae10f1af7caaa30bfe166d8bef3e45e24e59027 100644 (file)
@@ -142,7 +142,7 @@ parse_name(const unsigned char *p, size_t len,
     /* MECHNAME_LEN */
     if (len < 4)
        return 1;
-    l = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
+    l = (unsigned long)p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
     len -= 4;
     p += 4;
 
@@ -972,7 +972,7 @@ process_stream(krb5_context contextp,
            INSIST(gctx.ctx == NULL);
 
            gctx.inprogress = 1;
-           /* FALLTHROUGH */
+           fallthrough;
        case RPG_CONTINUE_INIT: {
            gss_name_t src_name = GSS_C_NO_NAME;
            krb5_data in;
index cbe16948c06c832eff6200424d039cbe915fef3b..52f20202e7fb511100118e4edfcf357ee8e54afe 100644 (file)
@@ -42,7 +42,8 @@ static kadm5_ret_t
 kadmind_dispatch(void *kadm_handlep, krb5_boolean initial,
                 krb5_data *in, krb5_data *out, int readonly)
 {
-    kadm5_ret_t ret;
+    kadm5_ret_t ret = 0;
+    kadm5_ret_t ret_sp = 0;
     int32_t cmd, mask, kvno, tmp;
     kadm5_server_context *contextp = kadm_handlep;
     char client[128], name[128], name2[128];
@@ -58,19 +59,31 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial,
     char **princs;
     int n_princs;
     int keys_ok = 0;
+    krb5_storage *rsp; /* response goes here */
     krb5_storage *sp;
     int len;
 
-    krb5_unparse_name_fixed(contextp->context, contextp->caller,
-                           client, sizeof(client));
+    memset(&ent, 0, sizeof(ent));
+    memset(&ent_prev, 0, sizeof(ent_prev));
+    krb5_data_zero(out);
+
+    rsp = krb5_storage_emem();
+    if (rsp == NULL)
+       return krb5_enomem(contextp->context);
 
     sp = krb5_storage_from_data(in);
     if (sp == NULL) {
-       ret = krb5_enomem(contextp->context);
-       goto fail;
+       krb5_storage_free(rsp);
+       return krb5_enomem(contextp->context);
     }
 
-    krb5_ret_int32(sp, &cmd);
+    ret = krb5_unparse_name_fixed(contextp->context, contextp->caller,
+                                 client, sizeof(client));
+    if (ret == 0)
+        ret = krb5_ret_int32(sp, &cmd);
+    if (ret)
+        goto fail;
+
     switch(cmd){
     case kadm_get:{
        op = "GET";
@@ -121,20 +134,14 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial,
         }
 
        ret = kadm5_get_principal(kadm_handlep, princ, &ent, mask);
-       krb5_storage_free(sp);
-       sp = krb5_storage_emem();
-        if (sp == NULL) {
-            ret = krb5_enomem(contextp->context);
-            goto fail;
-        }
-       krb5_store_int32(sp, ret);
-       if (ret == 0){
-           if (keys_ok)
-               kadm5_store_principal_ent(sp, &ent);
-           else
-               kadm5_store_principal_ent_nokeys(sp, &ent);
-           kadm5_free_principal_ent(kadm_handlep, &ent);
+       ret_sp = krb5_store_int32(rsp, ret);
+       if (ret == 0) {
+           if (ret_sp == 0 && keys_ok)
+               ret_sp = kadm5_store_principal_ent(rsp, &ent);
+           else if (ret_sp == 0)
+               ret_sp = kadm5_store_principal_ent_nokeys(rsp, &ent);
        }
+        kadm5_free_principal_ent(kadm_handlep, &ent);
        break;
     }
     case kadm_delete:{
@@ -144,27 +151,21 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial,
             goto fail;
         }
        ret = krb5_ret_principal(sp, &princ);
-       if (ret)
-           goto fail;
-       krb5_unparse_name_fixed(contextp->context, princ, name, sizeof(name));
-       krb5_warnx(contextp->context, "%s: %s %s", client, op, name);
-       ret = _kadm5_acl_check_permission(contextp, KADM5_PRIV_DELETE, princ);
-       if (ret)
-           goto fail;
+        if (ret == 0)
+            ret = krb5_unparse_name_fixed(contextp->context, princ, name, sizeof(name));
+        if (ret == 0) {
+            ret = _kadm5_acl_check_permission(contextp, KADM5_PRIV_DELETE, princ);
+            krb5_warnx(contextp->context, "%s: %s %s (%s)", client, op, name,
+                       ret == 0 ? "granted" : "denied");
+        }
 
         /*
          * There's no need to check that the caller has permission to
          * delete the victim principal's aliases.
          */
-
-       ret = kadm5_delete_principal(kadm_handlep, princ);
-       krb5_storage_free(sp);
-       sp = krb5_storage_emem();
-        if (sp == NULL) {
-            ret = krb5_enomem(contextp->context);
-            goto fail;
-        }
-       krb5_store_int32(sp, ret);
+        if (ret == 0)
+            ret = kadm5_delete_principal(kadm_handlep, princ);
+       ret_sp = krb5_store_int32(rsp, ret);
        break;
     }
     case kadm_create:{
@@ -209,13 +210,7 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial,
        ret = kadm5_create_principal(kadm_handlep, &ent,
                                     mask, password);
        kadm5_free_principal_ent(kadm_handlep, &ent);
-       krb5_storage_free(sp);
-       sp = krb5_storage_emem();
-        if (sp == NULL) {
-            ret = krb5_enomem(contextp->context);
-            goto fail;
-        }
-       krb5_store_int32(sp, ret);
+       ret_sp = krb5_store_int32(rsp, ret);
        break;
     }
     case kadm_modify:{
@@ -262,13 +257,7 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial,
         }
        ret = kadm5_modify_principal(kadm_handlep, &ent, mask);
        kadm5_free_principal_ent(kadm_handlep, &ent);
-       krb5_storage_free(sp);
-       sp = krb5_storage_emem();
-        if (sp == NULL) {
-            ret = krb5_enomem(contextp->context);
-            goto fail;
-        }
-       krb5_store_int32(sp, ret);
+       ret_sp = krb5_store_int32(rsp, ret);
        break;
     }
     case kadm_prune:{
@@ -293,13 +282,7 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial,
             goto fail;
 
         ret = kadm5_prune_principal(kadm_handlep, princ, kvno);
-        krb5_storage_free(sp);
-        sp = krb5_storage_emem();
-        if (sp == NULL) {
-            ret = krb5_enomem(contextp->context);
-            goto fail;
-        }
-        krb5_store_int32(sp, ret);
+        ret_sp = krb5_store_int32(rsp, ret);
         break;
     }
     case kadm_rename:{
@@ -342,13 +325,7 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial,
            goto fail;
 
        ret = kadm5_rename_principal(kadm_handlep, princ, princ2);
-       krb5_storage_free(sp);
-       sp = krb5_storage_emem();
-        if (sp == NULL) {
-            ret = krb5_enomem(contextp->context);
-            goto fail;
-        }
-       krb5_store_int32(sp, ret);
+       ret_sp = krb5_store_int32(sp, ret);
        break;
     }
     case kadm_chpass:{
@@ -360,18 +337,19 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial,
             goto fail;
         }
        ret = krb5_ret_principal(sp, &princ);
+        if (ret == 0)
+            ret = krb5_ret_string(sp, &password);
+        if (ret == 0)
+            ret = krb5_ret_int32(sp, &keepold);
+        if (ret == HEIM_ERR_EOF)
+            ret = 0;
+        if (ret == 0) {
+            ret = krb5_unparse_name_fixed(contextp->context, princ, name, sizeof(name));
+            if (ret == 0)
+                krb5_warnx(contextp->context, "%s: %s %s", client, op, name);
+        }
        if (ret)
            goto fail;
-       ret = krb5_ret_string(sp, &password);
-       if (ret)
-           goto fail;
-
-       ret = krb5_ret_int32(sp, &keepold);
-       if (ret && ret != HEIM_ERR_EOF)
-           goto fail;
-
-       krb5_unparse_name_fixed(contextp->context, princ, name, sizeof(name));
-       krb5_warnx(contextp->context, "%s: %s %s", client, op, name);
 
        /*
         * Change password requests are subject to ACLs unless the principal is
@@ -391,13 +369,7 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial,
 
        ret = kadm5_chpass_principal_3(kadm_handlep, princ, keepold, 0, NULL,
                                       password);
-       krb5_storage_free(sp);
-       sp = krb5_storage_emem();
-        if (sp == NULL) {
-            ret = krb5_enomem(contextp->context);
-            goto fail;
-        }
-       krb5_store_int32(sp, ret);
+       ret_sp = krb5_store_int32(rsp, ret);
        break;
     }
     case kadm_chpass_with_key:{
@@ -411,16 +383,16 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial,
             goto fail;
         }
        ret = krb5_ret_principal(sp, &princ);
-       if(ret)
-           goto fail;
-       ret = krb5_ret_int32(sp, &n_key_data);
+        if (ret == 0)
+           ret = krb5_ret_int32(sp, &n_key_data);
+        if (ret == 0) {
+           ret = krb5_ret_int32(sp, &keepold);
+           if (ret == HEIM_ERR_EOF)
+               ret = 0;
+       }
        if (ret)
            goto fail;
 
-       ret = krb5_ret_int32(sp, &keepold);
-       if (ret && ret != HEIM_ERR_EOF)
-           goto fail;
-
        /* n_key_data will be squeezed into an int16_t below. */
        if (n_key_data < 0 || n_key_data >= 1 << 16 ||
            (size_t)n_key_data > UINT_MAX/sizeof(*key_data)) {
@@ -445,15 +417,16 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial,
            }
        }
 
-       krb5_unparse_name_fixed(contextp->context, princ, name, sizeof(name));
-       krb5_warnx(contextp->context, "%s: %s %s", client, op, name);
-
        /*
         * The change is only allowed if the user is on the CPW ACL,
         * this it to force password quality check on the user.
         */
 
        ret = _kadm5_acl_check_permission(contextp, KADM5_PRIV_CPW, princ);
+       ret_sp = krb5_unparse_name_fixed(contextp->context, princ, name, sizeof(name));
+        if (ret_sp == 0)
+            krb5_warnx(contextp->context, "%s: %s %s (%s)", client, op, name,
+                       ret ? "denied" : "granted");
        if(ret) {
            int16_t dummy = n_key_data;
 
@@ -468,13 +441,7 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial,
            kadm5_free_key_data (contextp, &dummy, key_data);
        }
        free (key_data);
-       krb5_storage_free(sp);
-       sp = krb5_storage_emem();
-        if (sp == NULL) {
-            ret = krb5_enomem(contextp->context);
-            goto fail;
-        }
-       krb5_store_int32(sp, ret);
+       ret_sp = krb5_store_int32(rsp, ret);
        break;
     }
     case kadm_randkey:{
@@ -537,7 +504,7 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial,
             ret = EOVERFLOW;
             goto fail;
         }
-
+       free(ks_tuple);
         if ((ks_tuple = calloc(n_ks_tuple, sizeof (*ks_tuple))) == NULL) {
             ret = errno;
             goto fail;
@@ -560,18 +527,12 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial,
                                        &n_keys);
         free(ks_tuple);
 
-       krb5_storage_free(sp);
-       sp = krb5_storage_emem();
-        if (sp == NULL) {
-            ret = krb5_enomem(contextp->context);
-            goto fail;
-        }
-       krb5_store_int32(sp, ret);
-       if (ret == 0){
-           krb5_store_int32(sp, n_keys);
+       ret_sp = krb5_store_int32(rsp, ret);
+       if (ret == 0 && ret_sp == 0){
+           ret_sp = krb5_store_int32(rsp, n_keys);
            for (i = 0; i < n_keys; i++){
-                if (ret == 0)
-                    ret = krb5_store_keyblock(sp, new_keys[i]);
+                if (ret_sp == 0)
+                    ret_sp = krb5_store_keyblock(rsp, new_keys[i]);
                krb5_free_keyblock_contents(contextp->context, &new_keys[i]);
            }
            free(new_keys);
@@ -581,15 +542,8 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial,
     case kadm_get_privs:{
        uint32_t privs;
        ret = kadm5_get_privs(kadm_handlep, &privs);
-       krb5_storage_free(sp);
-       sp = krb5_storage_emem();
-        if (sp == NULL) {
-            ret = krb5_enomem(contextp->context);
-            goto fail;
-        }
-       krb5_store_int32(sp, ret);
-       if(ret == 0)
-           krb5_store_uint32(sp, privs);
+       if (ret == 0)
+           ret_sp = krb5_store_uint32(sp, privs);
        break;
     }
     case kadm_get_princs:{
@@ -612,62 +566,42 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial,
        }
        ret = kadm5_get_principals(kadm_handlep, expression, &princs, &n_princs);
        free(expression);
-       krb5_storage_free(sp);
-       sp = krb5_storage_emem();
-        if (sp == NULL) {
-            ret = krb5_enomem(contextp->context);
-            goto fail;
-        }
-       krb5_store_int32(sp, ret);
-       if(ret == 0){
+       ret_sp = krb5_store_int32(rsp, ret);
+       if (ret == 0) {
            int i;
-           krb5_store_int32(sp, n_princs);
-           for(i = 0; i < n_princs; i++)
-               krb5_store_string(sp, princs[i]);
+
+           ret_sp = krb5_store_int32(sp, n_princs);
+           for (i = 0; ret_sp == 0 && i < n_princs; i++)
+               ret_sp = krb5_store_string(sp, princs[i]);
            kadm5_free_name_list(kadm_handlep, princs, &n_princs);
        }
        break;
     }
     default:
        krb5_warnx(contextp->context, "%s: UNKNOWN OP %d", client, cmd);
-       krb5_storage_free(sp);
-       sp = krb5_storage_emem();
-        if (sp == NULL) {
-            ret = krb5_enomem(contextp->context);
-            goto fail;
-        }
-       krb5_store_int32(sp, KADM5_FAILURE);
+       ret_sp = krb5_store_int32(sp, KADM5_FAILURE);
        break;
     }
-    if (password != NULL) {
-       len = strlen(password);
-       memset_s(password, len, 0, len);
-       free(password);
-    }
-    krb5_storage_to_data(sp, out);
-    krb5_storage_free(sp);
-    if (princ != NULL)
-       krb5_free_principal(contextp->context, princ);
-    if (princ2 != NULL)
-       krb5_free_principal(contextp->context, princ2);
-    return 0;
+
 fail:
     if (password != NULL) {
        len = strlen(password);
        memset_s(password, len, 0, len);
        free(password);
     }
-    krb5_warn(contextp->context, ret, "%s", op);
-    if (sp != NULL) {
-       krb5_storage_seek(sp, 0, SEEK_SET);
-       krb5_store_int32(sp, ret);
-       krb5_storage_to_data(sp, out);
-       krb5_storage_free(sp);
-    }
-    if (princ != NULL)
-       krb5_free_principal(contextp->context, princ);
-    if (princ2 != NULL)
-       krb5_free_principal(contextp->context, princ2);
+    krb5_storage_to_data(rsp, out);
+    krb5_storage_free(rsp);
+    krb5_storage_free(sp);
+    krb5_free_principal(contextp->context, princ);
+    krb5_free_principal(contextp->context, princ2);
+    if (ret)
+        krb5_warn(contextp->context, ret, "%s", op);
+    if (out->length == 0)
+        krb5_warn(contextp->context, ret, "%s: reply failed", op);
+    else if (ret_sp)
+        krb5_warn(contextp->context, ret, "%s: reply incomplete", op);
+    if (ret_sp)
+        return ret_sp;
     return 0;
 }
 
@@ -691,6 +625,10 @@ iter_aliases(kadm5_principal_ent_rec *from,
 
     if (ctx->done > 0)
         return 0;
+    if (from == NULL) {
+        ctx->done = 1;
+        return 0;
+    }
 
     if (ctx->done == 0) {
         if (ctx->alias_idx < ctx->aliases.aliases.len) {
@@ -841,7 +779,6 @@ handle_v5(krb5_context contextp,
     void *kadm_handlep;
     krb5_boolean initial;
     krb5_auth_context ac = NULL;
-
     unsigned kadm_version = 1;
     kadm5_config_params realm_params;
 
@@ -849,35 +786,51 @@ handle_v5(krb5_context contextp,
                                      match_appl_version, &kadm_version,
                                      NULL, KRB5_RECVAUTH_IGNORE_VERSION,
                                      keytab, &ticket);
-    if (ret)
+    if (ret) {
        krb5_err(contextp, 1, ret, "krb5_recvauth");
-
-    ret = krb5_unparse_name (contextp, ticket->server, &server_name);
-    if (ret)
-       krb5_err (contextp, 1, ret, "krb5_unparse_name");
-
-    if (strncmp (server_name, KADM5_ADMIN_SERVICE,
-                strlen(KADM5_ADMIN_SERVICE)) != 0)
-       krb5_errx (contextp, 1, "ticket for strange principal (%s)",
-                  server_name);
-
-    free (server_name);
+        return;
+    }
+    ret = krb5_unparse_name(contextp, ticket->server, &server_name);
+    if (ret) {
+       krb5_err(contextp, 1, ret, "krb5_unparse_name");
+        krb5_free_ticket(contextp, ticket);
+        return;
+    }
+    if (strncmp(server_name, KADM5_ADMIN_SERVICE,
+                     strlen(KADM5_ADMIN_SERVICE)) != 0) {
+        krb5_errx(contextp, 1, "ticket for strange principal (%s)", server_name);
+        krb5_free_ticket(contextp, ticket);
+        free(server_name);
+        return;
+    }
+    free(server_name);
 
     memset(&realm_params, 0, sizeof(realm_params));
 
     if(kadm_version == 1) {
        krb5_data params;
        ret = krb5_read_priv_message(contextp, ac, &fd, &params);
-       if(ret)
+       if (ret) {
            krb5_err(contextp, 1, ret, "krb5_read_priv_message");
-       _kadm5_unmarshal_params(contextp, &params, &realm_params);
+            krb5_free_ticket(contextp, ticket);
+            return;
+        }
+       ret = _kadm5_unmarshal_params(contextp, &params, &realm_params);
+        if (ret) {
+           krb5_err(contextp, 1, ret,
+                      "Could not read or parse kadm5 parameters");
+            krb5_free_ticket(contextp, ticket);
+            return;
+        }
     }
 
     initial = ticket->ticket.flags.initial;
     ret = krb5_unparse_name(contextp, ticket->client, &client);
-    if (ret)
-       krb5_err (contextp, 1, ret, "krb5_unparse_name");
-    krb5_free_ticket (contextp, ticket);
+    krb5_free_ticket(contextp, ticket);
+    if (ret) {
+       krb5_err(contextp, 1, ret, "krb5_unparse_name");
+        return;
+    }
     ret = kadm5_s_init_with_password_ctx(contextp,
                                         client,
                                         NULL,
@@ -885,9 +838,11 @@ handle_v5(krb5_context contextp,
                                         &realm_params,
                                         0, 0,
                                         &kadm_handlep);
-    if(ret)
-       krb5_err (contextp, 1, ret, "kadm5_init_with_password_ctx");
-    v5_loop (contextp, ac, initial, kadm_handlep, fd, readonly);
+    if (ret) {
+       krb5_err(contextp, 1, ret, "kadm5_init_with_password_ctx");
+        return;
+    }
+    v5_loop(contextp, ac, initial, kadm_handlep, fd, readonly);
 }
 
 krb5_error_code
index 785de43f872e7eb7f08288de37690cfe0a23dc99..c33623038ce4452f14404782abad8deb730f4919 100644 (file)
@@ -106,7 +106,10 @@ stash(struct stash_options *opt, int argc, char **argv)
            }
        }
        ret = krb5_string_to_key_salt(context, enctype, buf, salt, &key);
-       ret = hdb_add_master_key(context, &key, &mkey);
+        if (ret == 0)
+            ret = hdb_add_master_key(context, &key, &mkey);
+        if (ret)
+            krb5_warn(context, errno, "setting master key");
        krb5_free_keyblock_contents(context, &key);
     }
 
index 02624dfd1c83ee5020d62f4c9e867716281358d1..b11812769b670f5d7e668fd240b3ab4188a8359c 100644 (file)
@@ -168,9 +168,9 @@ krb5_error_code kcm_debug_ccache(krb5_context context)
            ncreds++;
 
        if (p->client != NULL)
-           krb5_unparse_name(context, p->client, &cpn);
+           (void) krb5_unparse_name(context, p->client, &cpn);
        if (p->server != NULL)
-           krb5_unparse_name(context, p->server, &spn);
+           (void) krb5_unparse_name(context, p->server, &spn);
 
        kcm_log(7, "cache %08x: name %s refcnt %d flags %04x mode %04o "
                "uid %d gid %d client %s server %s ncreds %d",
@@ -179,10 +179,8 @@ krb5_error_code kcm_debug_ccache(krb5_context context)
                (spn == NULL) ? "<none>" : spn,
                ncreds);
 
-       if (cpn != NULL)
-           free(cpn);
-       if (spn != NULL)
-           free(spn);
+        free(cpn);
+        free(spn);
     }
 
     return 0;
index 09c94b6e8ddd4caa808b9bf3bc5796b7a6219991..061d4e9726760022b5d9859d38e0bf1ae66e5742 100644 (file)
@@ -46,6 +46,43 @@ kcm_ccache_resolve_client(krb5_context context,
     const char *estr;
 
     ret = kcm_ccache_resolve(context, name, ccache);
+    if (ret) {
+        char *uid = NULL;
+
+        /*
+         * Both MIT and Heimdal are unable to, in krb5_cc_default(), call to
+         * KCM (or CCAPI, or LSA, or...) to get the user's default ccache name
+         * in their collection.  Instead, the default ccache name is obtained
+         * in a static way, and for KCM that's "%{UID}".  When we
+         * krb5_cc_switch(), we simply maintain a pointer to the name of the
+         * ccache that was made the default, but klist can't make use of this
+         * because krb5_cc_default() can't.
+         *
+         * The solution here is to first try resolving the ccache name given by
+         * the client, and if that fails but the name happens to be what would
+         * be the library's default KCM ccache name for that user, then try
+         * resolving it through the default ccache name pointer saved at switch
+         * time.
+         */
+        if (asprintf(&uid, "%llu", (unsigned long long)client->uid) == -1 ||
+            uid == NULL)
+            return ENOMEM;
+
+        if (strcmp(name, uid) == 0) {
+            struct kcm_default_cache *c;
+
+            for (c = default_caches; c != NULL; c = c->next) {
+                if (kcm_is_same_session(client, c->uid, c->session)) {
+                    if (strcmp(c->name, name) != 0) {
+                        ret = kcm_ccache_resolve(context, c->name, ccache);
+                        break;
+                    }
+                }
+            }
+        }
+        free(uid);
+    }
+
     if (ret) {
        estr = krb5_get_error_message(context, ret);
        kcm_log(1, "Failed to resolve cache %s: %s", name, estr);
index 713af7f8650c4760c90c3cba7d0dfd735b833c13..0895f48f051cde8e2077efb72f8e9dcdde7b2712 100644 (file)
@@ -55,7 +55,7 @@ kcmss_get_name_2(krb5_context context,
         *name = CACHENAME(id);
     if (col)
         *col = NULL;
-    if (name)
+    if (sub)
         *sub = CACHENAME(id);
     return 0;
 }
index c36bbe9c6c673f1b182e5399d61f1db8637fba92..31f17623d01d2c1a3d3d689bca3326c46cf7777f 100644 (file)
@@ -423,7 +423,7 @@ kcm_op_get_principal(krb5_context context,
     free(name);
     kcm_release_ccache(context, ccache);
 
-    return 0;
+    return ret;
 }
 
 /*
@@ -1537,13 +1537,6 @@ kcm_op_do_ntlm(krb5_context context,
        }
 
        free(tmpsesskey.data);
-       if (ret) {
-           if (type3.lm.data)
-               free(type3.lm.data);
-           if (type3.ntlm.data)
-               free(type3.ntlm.data);
-           goto error;
-       }
        flags |= NTLM_FLAG_SESSIONKEY;
 #if 0
     } else {
@@ -1754,6 +1747,7 @@ kcm_dispatch(krb5_context context,
     krb5_storage *resp_sp = NULL;
     uint16_t opcode;
 
+    krb5_data_zero(resp_data);
     resp_sp = krb5_storage_emem();
     if (resp_sp == NULL) {
        return ENOMEM;
@@ -1803,11 +1797,17 @@ out:
        krb5_storage_free(req_sp);
     }
 
-    krb5_storage_seek(resp_sp, 0, SEEK_SET);
-    krb5_store_int32(resp_sp, ret);
+    if (resp_sp) {
+        krb5_error_code ret2;
 
-    ret = krb5_storage_to_data(resp_sp, resp_data);
-    krb5_storage_free(resp_sp);
+        krb5_storage_seek(resp_sp, 0, SEEK_SET);
+        ret2 = krb5_store_int32(resp_sp, ret);
+        if (ret2 == 0)
+            ret2 = krb5_storage_to_data(resp_sp, resp_data);
+        krb5_storage_free(resp_sp);
+        if (ret2)
+            ret = ret2;
+    }
 
     return ret;
 }
index 54382a842bf43a46e30bf82fdea0deba2153ea67..c7f57251f7c8aedbef0a58603b4f7ed51756584b 100644 (file)
@@ -2,6 +2,8 @@
 
 include $(top_srcdir)/Makefile.am.common
 
+WFLAGS += $(WFLAGS_ENUM_CONV)
+
 AM_CPPFLAGS += $(INCLUDE_libintl) $(INCLUDE_openssl_crypto) -I$(srcdir)/../lib/krb5
 
 lib_LTLIBRARIES = simple_csr_authorizer.la  ipc_csr_authorizer.la \
@@ -112,6 +114,8 @@ altsecid_gss_preauth_authorizer_la_LDFLAGS = -module \
                                             $(LIB_openldap)
 endif
 
+libkdc_la_CPPFLAGS = -DBUILD_KDC_LIB $(AM_CPPFLAGS)
+
 libkdc_la_SOURCES =            \
        default_config.c        \
        ca.c                    \
@@ -123,15 +127,15 @@ libkdc_la_SOURCES =               \
        krb5tgs.c               \
        pkinit.c                \
        pkinit-ec.c             \
+       mssfu.c                 \
        log.c                   \
        misc.c                  \
        kx509.c                 \
        token_validator.c       \
        csr_authorizer.c        \
        process.c               \
-       windc.c                 \
-       gss_preauth.c           \
-       rx.h
+       kdc-plugin.c            \
+       gss_preauth.c
 
 KDC_PROTOS = $(srcdir)/kdc-protos.h $(srcdir)/kdc-private.h
 
@@ -168,7 +172,7 @@ endif
 $(libkdc_la_OBJECTS): $(srcdir)/version-script.map
 
 $(srcdir)/kdc-protos.h: $(libkdc_la_SOURCES)
-       cd $(srcdir) && perl ../cf/make-proto.pl -q -P comment -o kdc-protos.h $(libkdc_la_SOURCES) || rm -f kdc-protos.h
+       cd $(srcdir) && perl ../cf/make-proto.pl -E KDC_LIB -q -P comment -o kdc-protos.h $(libkdc_la_SOURCES) || rm -f kdc-protos.h
 
 $(srcdir)/kdc-private.h: $(libkdc_la_SOURCES)
        cd $(srcdir) && perl ../cf/make-proto.pl -q -P comment -p kdc-private.h $(libkdc_la_SOURCES) || rm -f kdc-private.h
@@ -240,7 +244,7 @@ include_HEADERS = kdc.h $(srcdir)/kdc-protos.h
 noinst_HEADERS = $(srcdir)/kdc-private.h
 
 krb5dir = $(includedir)/krb5
-krb5_HEADERS = windc_plugin.h token_validator_plugin.h csr_authorizer_plugin.h
+krb5_HEADERS = kdc-audit.h kdc-plugin.h kdc-accessors.h token_validator_plugin.h csr_authorizer_plugin.h gss_preauth_authorizer_plugin.h
 
 build_HEADERZ = $(krb5_HEADERS) # XXX
 
index 58eb7577141e253fcbcaa6ee510c2e9cbb23ff58..aca65b104ae89337e7a8c89ab59018062d0ed9c8 100644 (file)
@@ -33,7 +33,7 @@ RELDIR=kdc
 
 !include ../windows/NTMakefile.w32 
 
-intcflags=-I$(OBJ) -I$(SRC)\lib\gssapi -I$(OBJDIR)\lib\gssapi -I$(OBJDIR)\lib\gss_preauth
+intcflags=-I$(OBJ) -I$(SRC)\lib\gssapi -I$(OBJDIR)\lib\gssapi -I$(OBJDIR)\lib\gss_preauth -DBUILD_KDC_LIB
 
 BINPROGRAMS=$(BINDIR)\string2key.exe
 
@@ -51,7 +51,9 @@ INCFILES=\
        $(INCDIR)\kdc.h         \
        $(INCDIR)\kdc-protos.h  \
        $(INCDIR)\kdc-private.h \
-       $(INCDIR)\krb5\windc_plugin.h
+       $(INCDIR)\krb5\kdc-audit.h \
+       $(INCDIR)\krb5\kdc-plugin.h \
+       $(INCDIR)\krb5\kdc-accessors.h
 
 all:: $(INCFILES) $(LIBKDC) $(BINPROGRAMS) $(SBINPROGRAMS) $(LIBEXECPROGRAMS)
 
@@ -103,13 +105,14 @@ LIBKDC_OBJS=\
        $(OBJ)\krb5tgs.obj              \
        $(OBJ)\pkinit.obj               \
        $(OBJ)\pkinit-ec.obj            \
+       $(OBJ)\mssfu.obj                        \
        $(OBJ)\log.obj                  \
        $(OBJ)\misc.obj                 \
        $(OBJ)\kx509.obj                \
        $(OBJ)\token_validator.obj      \
        $(OBJ)\csr_authorizer.obj       \
        $(OBJ)\process.obj              \
-       $(OBJ)\windc.obj                \
+       $(OBJ)\kdc-plugin.obj           \
        $(OBJ)\gss_preauth.obj
 
 LIBKDC_LIBS=\
@@ -144,18 +147,19 @@ libkdc_la_SOURCES =               \
        krb5tgs.c               \
        pkinit.c                \
        pkinit-ec.c             \
+       mssfu.c                 \
        log.c                   \
        misc.c                  \
        kx509.c                 \
        token_validator.c       \
        csr_authorizer.c        \
        process.c               \
-       windc.c                 \
-       gss_preauth.c           \
-       rx.h
+       kdc-plugin.c            \
+       gss_preauth.c
 
 $(OBJ)\kdc-protos.h: $(libkdc_la_SOURCES)
-       $(PERL) ..\cf\make-proto.pl -q -P remove -o $@ $(libkdc_la_SOURCES) \
+       cd $(SRCDIR)
+       $(PERL) ..\cf\make-proto.pl -E KDC_LIB -q -P remove -o $@ $(libkdc_la_SOURCES) \
        || $(RM) $@
 
 $(OBJ)\kdc-private.h: $(libkdc_la_SOURCES)
index 961ced0db9a63b333dbc2e3c57518ead8ac24ace..d48ea584bc8e32ba6d02e3d974f557e304dd4c66 100644 (file)
@@ -272,7 +272,7 @@ ad_lookup(krb5_context context,
           gss_const_name_t initiator_name,
           gss_const_OID mech_type,
           krb5_principal *canon_principal,
-          krb5_data *requestor_sid)
+          kdc_data_t *requestor_sid)
 {
     krb5_error_code ret;
     OM_uint32 minor;
@@ -286,7 +286,8 @@ ad_lookup(krb5_context context,
     struct berval **values = NULL;
 
     *canon_principal = NULL;
-    krb5_data_zero(requestor_sid);
+    if (requestor_sid)
+       *requestor_sid = NULL;
 
     mech_type_str = gss_oid_to_name(mech_type);
     if (mech_type_str == NULL) {
@@ -335,25 +336,29 @@ ad_lookup(krb5_context context,
     if (m0 == NULL)
         goto out;
 
+    values = ldap_get_values_len(server->ld, m0, "sAMAccountName");
+    if (values == NULL ||
+        ldap_count_values_len(values) == 0)
+        goto out;
+
+    ret = krb5_make_principal(context, canon_principal, realm,
+                              values[0]->bv_val, NULL);
+    if (ret)
+       goto out;
+
     if (requestor_sid) {
+       ldap_value_free_len(values);
+
        values = ldap_get_values_len(server->ld, m0, "objectSid");
        if (values == NULL ||
            ldap_count_values_len(values) == 0)
            goto out;
 
-       if (krb5_data_copy(requestor_sid, values[0]->bv_val, values[0]->bv_len) != 0)
+       *requestor_sid = kdc_data_create(values[0]->bv_val, values[0]->bv_len);
+       if (*requestor_sid == NULL)
            goto enomem;
-
-       ldap_value_free_len(values);
     }
 
-    values = ldap_get_values_len(server->ld, m0, "sAMAccountName");
-    if (values == NULL ||
-        ldap_count_values_len(values) == 0)
-        goto out;
-
-    ret = krb5_make_principal(context, canon_principal, realm,
-                              values[0]->bv_val, NULL);
     goto out;
 
 enomem:
@@ -361,6 +366,16 @@ enomem:
     goto out;
 
 out:
+    if (ret) {
+       krb5_free_principal(context, *canon_principal);
+       *canon_principal = NULL;
+
+       if (requestor_sid) {
+           kdc_object_release(*requestor_sid);
+           *requestor_sid = NULL;
+       }
+    }
+
     ldap_value_free_len(values);
     ldap_msgfree(m);
     ldap_memfree(basedn);
@@ -377,25 +392,27 @@ authorize(void *ctx,
           gss_const_OID mech_type,
           OM_uint32 ret_flags,
           krb5_boolean *authorized,
-          krb5_principal *mapped_name,
-         krb5_data *requestor_sid)
+          krb5_principal *mapped_name)
 {
     struct altsecid_gss_preauth_authorizer_context *c = ctx;
     struct ad_server_tuple *server = NULL;
     krb5_error_code ret;
-    krb5_const_realm realm = krb5_principal_get_realm(r->context, r->client->entry.principal);
+    krb5_context context = kdc_request_get_context((kdc_request_t)r);
+    const hdb_entry *client = kdc_request_get_client(r);
+    krb5_const_principal server_princ = kdc_request_get_server_princ(r);
+    krb5_const_realm realm = krb5_principal_get_realm(context, client->principal);
     krb5_boolean reconnect_p = FALSE;
     krb5_boolean is_tgs;
+    kdc_data_t requestor_sid = NULL;
 
     *authorized = FALSE;
     *mapped_name = NULL;
-    krb5_data_zero(requestor_sid);
 
-    if (!krb5_principal_is_federated(r->context, r->client->entry.principal) ||
+    if (!krb5_principal_is_federated(context, client->principal) ||
         (ret_flags & GSS_C_ANON_FLAG))
         return KRB5_PLUGIN_NO_HANDLE;
 
-    is_tgs = krb5_principal_is_krbtgt(r->context, r->server_princ);
+    is_tgs = krb5_principal_is_krbtgt(context, server_princ);
 
     HEIM_TAILQ_FOREACH(server, &c->servers, link) {
         if (strcmp(realm, server->realm) == 0)
@@ -405,12 +422,12 @@ authorize(void *ctx,
     if (server == NULL) {
         server = calloc(1, sizeof(*server));
         if (server == NULL)
-            return krb5_enomem(r->context);
+            return krb5_enomem(context);
 
         server->realm = strdup(realm);
         if (server->realm == NULL) {
             free(server);
-            return krb5_enomem(r->context);
+            return krb5_enomem(context);
         }
 
         HEIM_TAILQ_INSERT_HEAD(&c->servers, server, link);
@@ -418,14 +435,14 @@ authorize(void *ctx,
 
     do {
         if (server->ld == NULL) {
-            ret = ad_connect(r->context, realm, server);
+            ret = ad_connect(context, realm, server);
             if (ret)
                 return ret;
         }
 
-        ret = ad_lookup(r->context, realm, server,
+        ret = ad_lookup(context, realm, server,
                         initiator_name, mech_type,
-                        mapped_name, is_tgs ? requestor_sid : NULL);
+                        mapped_name, is_tgs ? &requestor_sid : NULL);
         if (ret == KRB5KDC_ERR_SVC_UNAVAILABLE) {
             ldap_unbind_ext_s(server->ld, NULL, NULL);
             server->ld = NULL;
@@ -437,17 +454,29 @@ authorize(void *ctx,
         *authorized = (ret == 0);
     } while (reconnect_p);
 
+    if (requestor_sid) {
+       kdc_request_set_attribute((kdc_request_t)r,
+                                 HSTR("org.h5l.gss-pa-requestor-sid"), requestor_sid);
+       kdc_object_release(requestor_sid);
+    }
+
     return ret;
 }
 
 static KRB5_LIB_CALL krb5_error_code
-finalize_pac(void *ctx, astgs_request_t r, krb5_data *requestor_sid)
+finalize_pac(void *ctx, astgs_request_t r)
 {
-    if (requestor_sid->length == 0)
+    kdc_data_t requestor_sid;
+
+    requestor_sid = kdc_request_get_attribute((kdc_request_t)r,
+                                             HSTR("org.h5l.gss-pa-requestor-sid"));
+    if (requestor_sid == NULL)
        return 0;
 
-    return krb5_pac_add_buffer(r->context, r->pac,
-                              PAC_REQUESTOR_SID, requestor_sid);
+    kdc_audit_setkv_object((kdc_request_t)r, "gss_requestor_sid", requestor_sid);
+
+    return kdc_request_add_pac_buffer(r, PAC_REQUESTOR_SID,
+                                     kdc_data_get_data(requestor_sid));
 }
 
 static KRB5_LIB_CALL krb5_error_code
@@ -494,8 +523,6 @@ altsecid_gss_preauth_authorizer_get_instance(const char *libname)
         return krb5_get_instance(libname);
     if (strcmp(libname, "kdc") == 0)
         return kdc_get_instance(libname);
-    if (strcmp(libname, "gssapi") == 0)
-        return gss_get_instance(libname);
     return 0;
 }
 
index 2f30744bf31d9e9693af8b7c48275a763e6208cf..064c424b7c29fa3e76997c0af737edc50871b0ca 100644 (file)
 #define heim_pconfig krb5_context
 #include <heimbase-svc.h>
 
+#if MHD_VERSION < 0x00097002 || defined(MHD_YES)
+/* libmicrohttpd changed these from int valued macros to an enum in 0.9.71 */
+#ifdef MHD_YES
+#undef MHD_YES
+#undef MHD_NO
+#endif
+enum MHD_Result { MHD_NO = 0, MHD_YES = 1 };
+#define MHD_YES 1
+#define MHD_NO 0
+typedef int heim_mhd_result;
+#else
+typedef enum MHD_Result heim_mhd_result;
+#endif
+
+enum k5_creds_kind { K5_CREDS_EPHEMERAL, K5_CREDS_CACHED };
+
 typedef struct bx509_request_desc {
     HEIM_SVC_REQUEST_DESC_COMMON_ELEMENTS;
 
@@ -122,6 +138,7 @@ typedef struct bx509_request_desc {
     const char *for_cname;
     const char *target;
     const char *redir;
+    enum k5_creds_kind cckind;
     char *pkix_store;
     char *ccname;
     char *freeme1;
@@ -485,8 +502,8 @@ bad_reqv(struct bx509_request_desc *r,
     char *formatted = NULL;
     char *msg = NULL;
 
-    heim_audit_addkv((heim_svc_req_desc)r, 0, "http-status-code", "%d",
-                     http_status_code);
+    heim_audit_setkv_number((heim_svc_req_desc)r, "http-status-code",
+                           http_status_code);
     (void) gettimeofday(&r->tv_end, NULL);
     if (code == ENOMEM) {
         if (r->context)
@@ -511,7 +528,7 @@ bad_reqv(struct bx509_request_desc *r,
         msg = formatted;
         formatted = NULL;
     }
-    heim_audit_addreason((heim_svc_req_desc)r, "%s", formatted);
+    heim_audit_addreason((heim_svc_req_desc)r, "%s", msg);
     audit_trail(r, code);
     krb5_free_error_message(context, k5msg);
 
@@ -606,10 +623,20 @@ static krb5_error_code
 good_bx509(struct bx509_request_desc *r)
 {
     krb5_error_code ret;
+    const char *fn;
     size_t bodylen;
     void *body;
 
-    ret = rk_undumpdata(strchr(r->pkix_store, ':') + 1, &body, &bodylen);
+    /*
+     * This `fn' thing is just to quiet linters that think "hey, strchr() can
+     * return NULL so...", but here we've build `r->pkix_store' and know it has
+     * a ':'.
+     */
+    if (r->pkix_store == NULL)
+        return bad_503(r, EINVAL, "Internal error"); /* Quiet warnings */
+    fn = strchr(r->pkix_store, ':');
+    fn = fn ? fn + 1 : r->pkix_store;
+    ret = rk_undumpdata(fn, &body, &bodylen);
     if (ret)
         return bad_503(r, ret, "Could not recover issued certificate "
                        "from PKIX store");
@@ -621,7 +648,7 @@ good_bx509(struct bx509_request_desc *r)
     return ret;
 }
 
-static int
+static heim_mhd_result
 bx509_param_cb(void *d,
                enum MHD_ValueKind kind,
                const char *key,
@@ -633,53 +660,53 @@ bx509_param_cb(void *d,
     if (strcmp(key, "eku") == 0 && val) {
         heim_audit_addkv((heim_svc_req_desc)r, KDC_AUDIT_VIS, "requested_eku",
                          "%s", val);
-        r->ret = der_parse_heim_oid(val, ".", &oid);
-        if (r->ret == 0)
-            r->ret = hx509_request_add_eku(r->context->hx509ctx, r->req, &oid);
+        r->error_code = der_parse_heim_oid(val, ".", &oid);
+        if (r->error_code == 0)
+            r->error_code = hx509_request_add_eku(r->context->hx509ctx, r->req, &oid);
         der_free_oid(&oid);
     } else if (strcmp(key, "dNSName") == 0 && val) {
         heim_audit_addkv((heim_svc_req_desc)r, KDC_AUDIT_VIS,
                          "requested_dNSName", "%s", val);
-        r->ret = hx509_request_add_dns_name(r->context->hx509ctx, r->req, val);
+        r->error_code = hx509_request_add_dns_name(r->context->hx509ctx, r->req, val);
     } else if (strcmp(key, "rfc822Name") == 0 && val) {
         heim_audit_addkv((heim_svc_req_desc)r, KDC_AUDIT_VIS,
                          "requested_rfc822Name", "%s", val);
-        r->ret = hx509_request_add_email(r->context->hx509ctx, r->req, val);
+        r->error_code = hx509_request_add_email(r->context->hx509ctx, r->req, val);
     } else if (strcmp(key, "xMPPName") == 0 && val) {
         heim_audit_addkv((heim_svc_req_desc)r, KDC_AUDIT_VIS,
                          "requested_xMPPName", "%s", val);
-        r->ret = hx509_request_add_xmpp_name(r->context->hx509ctx, r->req,
+        r->error_code = hx509_request_add_xmpp_name(r->context->hx509ctx, r->req,
                                              val);
     } else if (strcmp(key, "krb5PrincipalName") == 0 && val) {
         heim_audit_addkv((heim_svc_req_desc)r, KDC_AUDIT_VIS,
                          "requested_krb5PrincipalName", "%s", val);
-        r->ret = hx509_request_add_pkinit(r->context->hx509ctx, r->req,
+        r->error_code = hx509_request_add_pkinit(r->context->hx509ctx, r->req,
                                           val);
     } else if (strcmp(key, "ms-upn") == 0 && val) {
         heim_audit_addkv((heim_svc_req_desc)r, KDC_AUDIT_VIS,
                          "requested_ms_upn", "%s", val);
-        r->ret = hx509_request_add_ms_upn_name(r->context->hx509ctx, r->req,
+        r->error_code = hx509_request_add_ms_upn_name(r->context->hx509ctx, r->req,
                                                val);
     } else if (strcmp(key, "registeredID") == 0 && val) {
         heim_audit_addkv((heim_svc_req_desc)r, KDC_AUDIT_VIS,
                          "requested_registered_id", "%s", val);
-        r->ret = der_parse_heim_oid(val, ".", &oid);
-        if (r->ret == 0)
-            r->ret = hx509_request_add_registered(r->context->hx509ctx, r->req,
+        r->error_code = der_parse_heim_oid(val, ".", &oid);
+        if (r->error_code == 0)
+            r->error_code = hx509_request_add_registered(r->context->hx509ctx, r->req,
                                                   &oid);
         der_free_oid(&oid);
     } else if (strcmp(key, "csr") == 0 && val) {
-        heim_audit_addkv((heim_svc_req_desc)r, 0, "requested_csr", "true");
-        r->ret = 0; /* Handled upstairs */
+        heim_audit_setkv_bool((heim_svc_req_desc)r, "requested_csr", TRUE);
+        r->error_code = 0; /* Handled upstairs */
     } else if (strcmp(key, "lifetime") == 0 && val) {
         r->req_life = parse_time(val, "day");
     } else {
         /* Produce error for unknown params */
-        heim_audit_addkv((heim_svc_req_desc)r, 0, "requested_unknown", "true");
-        krb5_set_error_message(r->context, r->ret = ENOTSUP,
+        heim_audit_setkv_bool((heim_svc_req_desc)r, "requested_unknown", TRUE);
+        krb5_set_error_message(r->context, r->error_code = ENOTSUP,
                                "Query parameter %s not supported", key);
     }
-    return r->ret == 0 ? MHD_YES : MHD_NO /* Stop iterating */;
+    return r->error_code == 0 ? MHD_YES : MHD_NO /* Stop iterating */;
 }
 
 static krb5_error_code
@@ -693,10 +720,10 @@ authorize_CSR(struct bx509_request_desc *r,
     if (ret)
         return bad_req(r, ret, MHD_HTTP_SERVICE_UNAVAILABLE,
                        "Could not parse CSR");
-    r->ret = 0;
+    r->error_code = 0;
     (void) MHD_get_connection_values(r->connection, MHD_GET_ARGUMENT_KIND,
                                      bx509_param_cb, r);
-    ret = r->ret;
+    ret = r->error_code;
     if (ret)
         return bad_req(r, ret, MHD_HTTP_SERVICE_UNAVAILABLE,
                        "Could not handle query parameters");
@@ -771,6 +798,7 @@ do_CA(struct bx509_request_desc *r, const char *csr)
     /* Set CSR */
     if ((d.data = malloc(strlen(csr2))) == NULL) {
         krb5_free_principal(r->context, p);
+        free(csr2);
         return bad_enomem(r, ENOMEM);
     }
 
@@ -818,11 +846,9 @@ do_CA(struct bx509_request_desc *r, const char *csr)
 
     ret = store_certs(r->context->hx509ctx, r->pkix_store, certs, NULL);
     hx509_certs_free(&certs);
-    if (ret) {
-        (void) unlink(strchr(r->pkix_store, ':') + 1);
-        return bad_500(r, ret,
-                       "Failed convert issued certificate and chain to PEM");
-    }
+    if (ret)
+        return bad_500(r, ret, "Failed to convert issued"
+                       " certificate and chain to PEM");
     return 0;
 }
 
@@ -864,7 +890,7 @@ set_req_desc(struct MHD_Connection *connection,
     r->from = r->frombuf;
     r->tgt_addresses.len = 0;
     r->tgt_addresses.val = 0;
-    r->hcontext = r->context->hcontext;
+    r->hcontext = r->context ? r->context->hcontext : NULL;
     r->config = NULL;
     r->logf = logfac;
     r->reqtype = url;
@@ -880,8 +906,11 @@ set_req_desc(struct MHD_Connection *connection,
     r->addr = NULL;
     r->req = NULL;
     r->req_life = 0;
-    r->ret = 0;
-    r->kv = heim_array_create();
+    r->error_code = ret;
+    r->kv = heim_dict_create(10);
+    r->attributes = heim_dict_create(1);
+    if (ret == 0 && (r->kv == NULL || r->attributes == NULL))
+        r->error_code = ret = ENOMEM;
     ci = MHD_get_connection_info(connection,
                                  MHD_CONNECTION_INFO_CLIENT_ADDRESS);
     if (ci) {
@@ -905,10 +934,6 @@ set_req_desc(struct MHD_Connection *connection,
 
     }
 
-    if (ret == 0 && r->kv == NULL) {
-        krb5_log_msg(r->context, logfac, 1, NULL, "Out of memory");
-        ret = ENOMEM;
-    }
     return ret;
 }
 
@@ -917,12 +942,28 @@ clean_req_desc(struct bx509_request_desc *r)
 {
     if (!r)
         return;
-    if (r->pkix_store)
-        (void) unlink(strchr(r->pkix_store, ':') + 1);
+    if (r->pkix_store) {
+        const char *fn = strchr(r->pkix_store, ':');
+
+        /*
+         * This `fn' thing is just to quiet linters that think "hey, strchr() can
+         * return NULL so...", but here we've build `r->pkix_store' and know it has
+         * a ':'.
+         */
+        fn = fn ? fn + 1 : r->pkix_store;
+        (void) unlink(fn);
+    }
     krb5_free_addresses(r->context, &r->tgt_addresses);
     hx509_request_free(&r->req);
     heim_release(r->reason);
     heim_release(r->kv);
+    if (r->ccname && r->cckind == K5_CREDS_EPHEMERAL) {
+        const char *fn = r->ccname;
+
+        if (strncmp(fn, "FILE:", sizeof("FILE:") - 1) == 0)
+            fn += sizeof("FILE:") - 1;
+        (void) unlink(fn);
+    }
     free(r->pkix_store);
     free(r->freeme1);
     free(r->ccname);
@@ -966,6 +1007,8 @@ bx509(struct bx509_request_desc *r)
  * '~' and '.' also get encoded, and '@' does not.
  *
  * A corresponding decoder is not needed.
+ *
+ * XXX Maybe use krb5_cc_default_for()!
  */
 static size_t
 princ_fs_encode_sz(const char *in)
@@ -1045,8 +1088,10 @@ find_ccache(krb5_context context, const char *princ, char **ccname)
      */
     if ((s = princ_fs_encode(princ)) == NULL ||
         asprintf(ccname, "FILE:%s/%s.cc", cache_dir, s) == -1 ||
-        *ccname == NULL)
+        *ccname == NULL) {
+        free(s);
         return ENOMEM;
+    }
     free(s);
 
     if ((ret = krb5_cc_resolve(context, *ccname, &cc))) {
@@ -1067,13 +1112,10 @@ find_ccache(krb5_context context, const char *princ, char **ccname)
     return ret ? ret : ENOENT;
 }
 
-enum k5_creds_kind { K5_CREDS_EPHEMERAL, K5_CREDS_CACHED };
-
 static krb5_error_code
 get_ccache(struct bx509_request_desc *r, krb5_ccache *cc, int *won)
 {
     krb5_error_code ret = 0;
-    struct stat st1, st2;
     char *temp_ccname = NULL;
     const char *fn = NULL;
     time_t life;
@@ -1103,6 +1145,7 @@ get_ccache(struct bx509_request_desc *r, krb5_ccache *cc, int *won)
     if (ret == 0)
         fn = temp_ccname + sizeof("FILE:") - 1;
     if (ret == 0) do {
+        struct stat st1, st2;
         /*
          * Open and flock the temp ccache file.
          *
@@ -1115,6 +1158,8 @@ get_ccache(struct bx509_request_desc *r, krb5_ccache *cc, int *won)
             fd = -1;
         }
         errno = 0;
+        memset(&st1, 0, sizeof(st1));
+        memset(&st2, 0xff, sizeof(st2));
         if (ret == 0 &&
             ((fd = open(fn, O_RDWR | O_CREAT, 0600)) == -1 ||
              flock(fd, LOCK_EX) == -1 ||
@@ -1186,7 +1231,8 @@ do_pkinit(struct bx509_request_desc *r, enum k5_creds_kind kind)
         ret = krb5_cc_new_unique(r->context, "FILE", NULL, &temp_cc);
     }
 
-    ret = krb5_parse_name(r->context, cname, &p);
+    if (ret == 0)
+        ret = krb5_parse_name(r->context, cname, &p);
     if (ret == 0)
         crealm = krb5_principal_get_realm(r->context, p);
     if (ret == 0)
@@ -1304,7 +1350,7 @@ k5_do_CA(struct bx509_request_desc *r)
     if (ret == 0)
         ret = krb5_parse_name(r->context, cname, &p);
     if (ret == 0)
-        hx509_private_key2SPKI(r->context->hx509ctx, key, &spki);
+        ret = hx509_private_key2SPKI(r->context->hx509ctx, key, &spki);
     if (ret == 0)
         hx509_request_set_SubjectPublicKeyInfo(r->context->hx509ctx, req,
                                                &spki);
@@ -1366,6 +1412,7 @@ k5_get_creds(struct bx509_request_desc *r, enum k5_creds_kind kind)
     const char *cname = r->for_cname ? r->for_cname : r->cname;
 
     /* If we have a live ccache for `cprinc', we're done */
+    r->cckind = kind;
     if (kind == K5_CREDS_CACHED &&
         (ret = find_ccache(r->context, cname, &r->ccname)) == 0)
         return ret; /* Success */
@@ -1638,8 +1685,7 @@ bnegotiate(struct bx509_request_desc *r)
     if (ret == 0) {
         heim_audit_addkv((heim_svc_req_desc)r, KDC_AUDIT_VIS, "target", "%s",
                          r->target ? r->target : "<unknown>");
-        heim_audit_addkv((heim_svc_req_desc)r, 0, "redir", "%s",
-                         r->redir ? "yes" : "no");
+        heim_audit_setkv_bool((heim_svc_req_desc)r, "redir", !!r->redir);
         ret = validate_token(r);
     }
     /* bnegotiate_get_target() and validate_token() call bad_req() */
@@ -1688,7 +1734,8 @@ authorize_TGT_REQ(struct bx509_request_desc *r)
         return 0;
 
     ret = krb5_parse_name(r->context, r->cname, &p);
-    ret = hx509_request_init(r->context->hx509ctx, &r->req);
+    if (ret == 0)
+        ret = hx509_request_init(r->context->hx509ctx, &r->req);
     if (ret)
         return bad_500(r, ret, "Out of resources");
     heim_audit_addkv((heim_svc_req_desc)r, KDC_AUDIT_VIS,
@@ -1707,7 +1754,7 @@ authorize_TGT_REQ(struct bx509_request_desc *r)
     return ret;
 }
 
-static int
+static heim_mhd_result
 get_tgt_param_cb(void *d,
                  enum MHD_ValueKind kind,
                  const char *key,
@@ -1719,15 +1766,15 @@ get_tgt_param_cb(void *d,
         if (!krb5_config_get_bool_default(r->context, NULL,
                                          FALSE,
                                          "get-tgt", "allow_addresses", NULL)) {
-            krb5_set_error_message(r->context, r->ret = ENOTSUP,
+            krb5_set_error_message(r->context, r->error_code = ENOTSUP,
                                    "Query parameter %s not allowed", key);
         } else {
             krb5_addresses addresses;
 
-            r->ret = _krb5_parse_address_no_lookup(r->context, val,
+            r->error_code = _krb5_parse_address_no_lookup(r->context, val,
                                                    &addresses);
-            if (r->ret == 0)
-                r->ret = krb5_append_addresses(r->context, &r->tgt_addresses,
+            if (r->error_code == 0)
+                r->error_code = krb5_append_addresses(r->context, &r->tgt_addresses,
                                                &addresses);
             krb5_free_addresses(r->context, &addresses);
         }
@@ -1738,11 +1785,11 @@ get_tgt_param_cb(void *d,
         r->req_life = parse_time(val, "day");
     } else {
         /* Produce error for unknown params */
-        heim_audit_addkv((heim_svc_req_desc)r, 0, "requested_unknown", "true");
-        krb5_set_error_message(r->context, r->ret = ENOTSUP,
+        heim_audit_setkv_bool((heim_svc_req_desc)r, "requested_unknown", TRUE);
+        krb5_set_error_message(r->context, r->error_code = ENOTSUP,
                                "Query parameter %s not supported", key);
     }
-    return r->ret == 0 ? MHD_YES : MHD_NO /* Stop iterating */;
+    return r->error_code == 0 ? MHD_YES : MHD_NO /* Stop iterating */;
 }
 
 /*
@@ -1772,13 +1819,14 @@ get_tgt(struct bx509_request_desc *r)
     if (ret)
         return ret;
 
-    r->ret = 0;
+    r->error_code = 0;
     (void) MHD_get_connection_values(r->connection, MHD_GET_ARGUMENT_KIND,
                                      get_tgt_param_cb, r);
-    ret = r->ret;
+    ret = r->error_code;
 
     /* k5_get_creds() calls bad_req() */
-    ret = k5_get_creds(r, K5_CREDS_EPHEMERAL);
+    if (ret == 0)
+        ret = k5_get_creds(r, K5_CREDS_EPHEMERAL);
     if (ret)
         return ret;
 
@@ -1786,10 +1834,8 @@ get_tgt(struct bx509_request_desc *r)
     if (fn == NULL)
         return bad_500(r, ret, "Impossible error");
     fn++;
-    if ((errno = rk_undumpdata(fn, &body, &bodylen))) {
-        (void) unlink(fn);
+    if ((errno = rk_undumpdata(fn, &body, &bodylen)))
         return bad_503(r, ret, "Could not get TGT");
-    }
 
     ret = resp(r, MHD_HTTP_OK, MHD_RESPMEM_MUST_COPY,
                "application/x-krb5-ccache", body, bodylen, NULL);
@@ -1811,7 +1857,7 @@ health(const char *method, struct bx509_request_desc *r)
 }
 
 /* Implements the entirety of this REST service */
-static int
+static heim_mhd_result
 route(void *cls,
       struct MHD_Connection *connection,
       const char *url,
@@ -2013,6 +2059,8 @@ main(int argc, char **argv)
 
     argc -= optidx;
     argv += optidx;
+    if (argc != 0)
+        usage(1);
 
     if ((errno = pthread_key_create(&k5ctx, k5_free_context)))
         err(1, "Could not create thread-specific storage");
index 0d92ca7fc89fe26112154046a88c00c051345d09..4402c44677fb0528faaf56f14056dfe8bc83a8fd 100644 (file)
@@ -97,7 +97,7 @@ get_cf(krb5_context context,
 /*
  * Build a certifate for `principal' and its CSR.
  */
-krb5_error_code
+KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL
 kdc_issue_certificate(krb5_context context,
                       const char *app_name,
                       krb5_log_facility *logf,
@@ -129,5 +129,5 @@ kdc_issue_certificate(krb5_context context,
                                           out);
     if (ret == EACCES)
         ret = KRB5KDC_ERR_POLICY;
-    return (ret == EACCES) ? KRB5KDC_ERR_POLICY : ret;
+    return ret;
 }
index 68fe01594f8e7ba7072bfb6677af50b1681e737d..93742e5ddd5588f0128e93fec3978186eac60647 100644 (file)
@@ -107,13 +107,13 @@ get_issuer_pubkeys(krb5_context context,
     if (!previous->length && !current->length && !next->length)
         krb5_set_error_message(context, save_ret,
                                "Could not read jwk issuer public key files");
-    if (current->length == next->length &&
+    if (current->length && current->length == next->length &&
         memcmp(current->data, next->data, next->length) == 0) {
         free(next->data);
         next->data = 0;
         next->length = 0;
     }
-    if (current->length == previous->length &&
+    if (current->length && current->length == previous->length &&
         memcmp(current->data, previous->data, previous->length) == 0) {
         free(previous->data);
         previous->data = 0;
@@ -255,6 +255,11 @@ validate(void *ctx,
     tokstr = NULL;
     switch (ret) {
     case 0:
+        if (jwt == NULL) {
+            krb5_set_error_message(context, EINVAL, "JWT validation failed");
+            free(defrealm);
+            return EPERM;
+        }
         if (jwt->header.alg == alg_none) {
             krb5_set_error_message(context, EINVAL, "JWT signature algorithm "
                                    "not supported");
index 507cb195af3f30cde5b74c143603002b8732a697..e217b9dadfa5dc0f5fd8ac14af4ced0397873343 100644 (file)
@@ -309,7 +309,7 @@ configure(krb5_context context, int argc, char **argv, int *optidx)
        krb5_enctype_disable(context, ETYPE_DES_PCBC_NONE);
     }
 
-    krb5_kdc_windc_init(context);
+    krb5_kdc_plugin_init(context);
 
     krb5_kdc_pkinit_config(context, config);
 
index 975f24cb269abe178fe62a848230f8c893fb1c6e..ba8c8ad7ba5425f67903a4c45e519f044d88d5a5 100644 (file)
@@ -263,7 +263,8 @@ init_socket(krb5_context context,
 #if defined(HAVE_SETSOCKOPT) && defined(SOL_SOCKET) && defined(SO_REUSEADDR)
     {
        int one = 1;
-       setsockopt(d->s, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(one));
+        (void) setsockopt(d->s, SOL_SOCKET, SO_REUSEADDR, (void *)&one,
+                          sizeof(one));
     }
 #endif
     d->type = type;
@@ -620,15 +621,22 @@ handle_vanilla_tcp (krb5_context context,
                    krb5_kdc_configuration *config,
                    struct descr *d)
 {
+    krb5_error_code ret;
     krb5_storage *sp;
     uint32_t len;
 
+    if (d->len < 4)
+        return 0;
     sp = krb5_storage_from_mem(d->buf, d->len);
     if (sp == NULL) {
        kdc_log (context, config, 1, "krb5_storage_from_mem failed");
        return -1;
     }
-    krb5_ret_uint32(sp, &len);
+    ret = krb5_ret_uint32(sp, &len);
+    if (ret) {
+       kdc_log(context, config, 4, "failed to read request length");
+       return -1;
+    }
     krb5_storage_free(sp);
     if(d->len - 4 >= len) {
        memmove(d->buf, d->buf + 4, d->len - 4);
@@ -1064,7 +1072,7 @@ reap_kid(krb5_context context, krb5_kdc_configuration *config,
         pid_t *pids, int max_kids, int options)
 {
     pid_t pid;
-    char *what;
+    char *what = "untracked";
     int status;
     int i = 0; /* quiet warnings */
     int ret = 0;
@@ -1090,7 +1098,6 @@ reap_kid(krb5_context context, krb5_kdc_configuration *config,
 
         if (i == max_kids) {
             /* should not happen */
-            what = "untracked";
             sev = "warning: ";
             level = 2;
         }
@@ -1156,7 +1163,7 @@ start_kdc(krb5_context context,
 #endif
 
 #ifdef __APPLE__
-    if (do_bonjour > 0)
+    if (!testing_flag && do_bonjour > 0)
         bonjour_kid(context, config, argv0, NULL);
 #endif
 
@@ -1191,7 +1198,7 @@ start_kdc(krb5_context context,
 #ifdef HAVE_FORK
 
 # ifdef __APPLE__
-    if (do_bonjour < 0)
+    if (!testing_flag && do_bonjour < 0)
         bonjour_kid(context, config, argv0, islive);
 # endif
 
index fa20519d73a67f8f71e51dc41c0646b9a6039ee6..52bc37c42965127fc721451e8a6888d74edb5a04 100644 (file)
@@ -65,7 +65,7 @@ static struct heim_plugin_data csr_authorizer_data = {
  * Invoke a plugin to validate a JWT/SAML/OIDC token and partially-evaluate
  * access control.
  */
-krb5_error_code
+KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL
 kdc_authorize_csr(krb5_context context,
                   const char *app,
                   hx509_request csr,
index 627dc74f45801baffb28538cfb4ee30c8285c351..01f8f7b54a69c4eeb71724885e0a86d5c6634764 100644 (file)
@@ -69,7 +69,7 @@ load_kdc_plugins_once(void *ctx)
 #endif
 }
 
-krb5_error_code
+KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL
 krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config)
 {
     static heim_base_once_t load_kdc_plugins = HEIM_BASE_ONCE_INIT;
@@ -93,7 +93,6 @@ krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config)
     c->preauth_use_strongest_session_key = FALSE;
     c->svc_use_strongest_session_key = FALSE;
     c->use_strongest_server_key = TRUE;
-    c->autodetect_referrals = TRUE;
     c->check_ticket_addresses = TRUE;
     c->warn_ticket_addresses = FALSE;
     c->allow_null_ticket_addresses = TRUE;
@@ -392,7 +391,7 @@ krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config)
     return 0;
 }
 
-krb5_error_code
+KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL
 krb5_kdc_pkinit_config(krb5_context context, krb5_kdc_configuration *config)
 {
 #ifdef PKINIT
index 3a4f4c551db633557fe72e0b4f6b2d34e5be286c..4ea76dbe7e28588b3ee6af84f6d38aa1a027486d 100644 (file)
@@ -60,7 +60,8 @@ ntlm_service(void *ctx, const heim_idata *req,
     unsigned char sessionkey[16];
     heim_idata rep = { 0, NULL };
     krb5_context context = ctx;
-    hdb_entry_ex *user = NULL;
+    hdb_entry *user = NULL;
+    HDB *db = NULL;
     Key *key = NULL;
     NTLMReply ntp;
     size_t size;
@@ -113,12 +114,12 @@ ntlm_service(void *ctx, const heim_idata *req,
        krb5_principal_set_type(context, client, KRB5_NT_NTLM);
 
        ret = _kdc_db_fetch(context, config, client,
-                           HDB_F_GET_CLIENT, NULL, NULL, &user);
+                           HDB_F_GET_CLIENT, NULL, &db, &user);
        krb5_free_principal(context, client);
        if (ret)
            goto failed;
 
-       ret = hdb_enctype2key(context, &user->entry, NULL,
+       ret = hdb_enctype2key(context, user, NULL,
                              ETYPE_ARCFOUR_HMAC_MD5, &key);
        if (ret) {
            krb5_set_error_message(context, ret, "NTLM missing arcfour key");
@@ -213,7 +214,7 @@ ntlm_service(void *ctx, const heim_idata *req,
 
     free_NTLMRequest2(&ntq);
     if (user)
-       _kdc_free_ent (context, user);
+       _kdc_free_ent (context, db, user);
 }
 
 static int help_flag;
index a8652891f535b9f4f55e71660125c17f4017f3b8..092b4a75a4be36234d09601537aa0bc3bcaaed12 100644 (file)
@@ -57,7 +57,7 @@ const struct units _kdc_digestunits[] = {
 static krb5_error_code
 get_digest_key(krb5_context context,
               krb5_kdc_configuration *config,
-              hdb_entry_ex *server,
+              hdb_entry *server,
               krb5_crypto *crypto)
 {
     krb5_error_code ret;
@@ -81,12 +81,12 @@ get_digest_key(krb5_context context,
 
 static char *
 get_ntlm_targetname(krb5_context context,
-                   hdb_entry_ex *client)
+                   hdb_entry *client)
 {
     char *targetname, *p;
 
     targetname = strdup(krb5_principal_get_realm(context,
-                                                client->entry.principal));
+                                                client->principal));
     if (targetname == NULL)
        return NULL;
 
@@ -101,7 +101,7 @@ get_ntlm_targetname(krb5_context context,
 static krb5_error_code
 fill_targetinfo(krb5_context context,
                char *targetname,
-               hdb_entry_ex *client,
+               hdb_entry *client,
                krb5_data *data)
 {
     struct ntlm_targetinfo ti;
@@ -113,7 +113,7 @@ fill_targetinfo(krb5_context context,
     memset(&ti, 0, sizeof(ti));
 
     ti.domainname = targetname;
-    p = client->entry.principal;
+    p = client->principal;
     str = krb5_principal_get_comp_string(context, p, 0);
     if (str != NULL &&
        (strcmp("host", str) == 0 ||
@@ -168,7 +168,7 @@ get_password_entry(krb5_context context,
 {
     krb5_principal clientprincipal;
     krb5_error_code ret;
-    hdb_entry_ex *user;
+    hdb_entry *user;
     HDB *db;
 
     /* get username */
@@ -182,7 +182,7 @@ get_password_entry(krb5_context context,
     if (ret)
        return ret;
 
-    ret = hdb_entry_get_password(context, db, &user->entry, password);
+    ret = hdb_entry_get_password(context, db, user, password);
     if (ret || password == NULL) {
        if (ret == 0) {
            ret = EINVAL;
@@ -190,7 +190,7 @@ get_password_entry(krb5_context context,
        }
        memset(user, 0, sizeof(*user));
     }
-    _kdc_free_ent (context, user);
+    _kdc_free_ent (context, db, user);
     return ret;
 }
 
@@ -217,8 +217,10 @@ _kdc_do_digest(krb5_context context,
     size_t size;
     krb5_storage *sp = NULL;
     Checksum res;
-    hdb_entry_ex *server = NULL, *user = NULL;
-    hdb_entry_ex *client = NULL;
+    HDB *serverdb, *userdb;
+    hdb_entry *server = NULL, *user = NULL;
+    HDB *clientdb;
+    hdb_entry *client = NULL;
     char *client_name = NULL, *password = NULL;
     krb5_data serverNonce;
 
@@ -292,7 +294,7 @@ _kdc_do_digest(krb5_context context,
        krb5_clear_error_message(context);
 
        ret = _kdc_db_fetch(context, config, principal,
-                           HDB_F_GET_SERVER, NULL, NULL, &server);
+                           HDB_F_GET_SERVER, NULL, &serverdb, &server);
        if (ret)
            goto out;
 
@@ -314,12 +316,12 @@ _kdc_do_digest(krb5_context context,
        }
 
        ret = _kdc_db_fetch(context, config, principal,
-                           HDB_F_GET_CLIENT, NULL, NULL, &client);
+                           HDB_F_GET_CLIENT, NULL, &clientdb, &client);
        krb5_free_principal(context, principal);
        if (ret)
            goto out;
 
-       if (client->entry.flags.allow_digest == 0) {
+       if (client->flags.allow_digest == 0) {
            kdc_log(context, config, 2,
                    "Client %s tried to use digest "
                    "but is not allowed to",
@@ -877,7 +879,7 @@ _kdc_do_digest(krb5_context context,
                goto failed;
 
            ret = _kdc_db_fetch(context, config, clientprincipal,
-                               HDB_F_GET_CLIENT, NULL, NULL, &user);
+                               HDB_F_GET_CLIENT, NULL, &userdb, &user);
            krb5_free_principal(context, clientprincipal);
            if (ret) {
                krb5_set_error_message(context, ret,
@@ -886,7 +888,7 @@ _kdc_do_digest(krb5_context context,
                goto failed;
            }
 
-           ret = hdb_enctype2key(context, &user->entry, NULL,
+           ret = hdb_enctype2key(context, user, NULL,
                                  ETYPE_ARCFOUR_HMAC_MD5, &key);
            if (ret) {
                krb5_set_error_message(context, ret,
@@ -1163,7 +1165,7 @@ _kdc_do_digest(krb5_context context,
            goto failed;
 
        ret = _kdc_db_fetch(context, config, clientprincipal,
-                           HDB_F_GET_CLIENT, NULL, NULL, &user);
+                           HDB_F_GET_CLIENT, NULL, &userdb, &user);
        krb5_free_principal(context, clientprincipal);
        if (ret) {
            krb5_set_error_message(context, ret, "NTLM user %s not in database",
@@ -1214,7 +1216,7 @@ _kdc_do_digest(krb5_context context,
            goto out;
        }
 
-       ret = hdb_enctype2key(context, &user->entry, NULL,
+       ret = hdb_enctype2key(context, user, NULL,
                              ETYPE_ARCFOUR_HMAC_MD5, &key);
        if (ret) {
            krb5_set_error_message(context, ret, "NTLM missing arcfour key");
@@ -1466,6 +1468,10 @@ _kdc_do_digest(krb5_context context,
     ret = krb5_encrypt_EncryptedData(context, crypto, KRB5_KU_DIGEST_ENCRYPT,
                                     buf.data, buf.length, 0,
                                     &rep.innerRep);
+    if (ret) {
+        krb5_prepend_error_message(context, ret, "Failed to encrypt digest: ");
+        goto out;
+    }
 
     ASN1_MALLOC_ENCODE(DigestREP, reply->data, reply->length, &rep, &size, ret);
     if (ret) {
@@ -1490,11 +1496,11 @@ _kdc_do_digest(krb5_context context,
     if (sp)
        krb5_storage_free(sp);
     if (user)
-       _kdc_free_ent (context, user);
+       _kdc_free_ent (context, userdb, user);
     if (server)
-       _kdc_free_ent (context, server);
+       _kdc_free_ent (context, serverdb, server);
     if (client)
-       _kdc_free_ent (context, client);
+       _kdc_free_ent (context, clientdb, client);
     if (password) {
        memset(password, 0, strlen(password));
        free (password);
index d4cd650284b8e80e7c1dbc7cfce6b51121af98b2..25cab3096b7f5c17b0133ee5dbfdfd6e48c9580d 100644 (file)
@@ -108,7 +108,8 @@ get_fastuser_crypto(astgs_request_t r,
                    krb5_crypto *crypto)
 {
     krb5_principal fast_princ;
-    hdb_entry_ex *fast_user = NULL;
+    HDB *fast_db;
+    hdb_entry *fast_user = NULL;
     Key *cookie_key = NULL;
     krb5_crypto fast_crypto = NULL;
     krb5_error_code ret;
@@ -122,7 +123,7 @@ get_fastuser_crypto(astgs_request_t r,
        goto out;
 
     ret = _kdc_db_fetch(r->context, r->config, fast_princ,
-                       HDB_F_GET_FAST_COOKIE, NULL, NULL, &fast_user);
+                       HDB_F_GET_FAST_COOKIE, NULL, &fast_db, &fast_user);
     if (ret)
        goto out;
 
@@ -130,7 +131,7 @@ get_fastuser_crypto(astgs_request_t r,
        ret = _kdc_get_preferred_key(r->context, r->config, fast_user,
                                     "fast-cookie", &enctype, &cookie_key);
     else
-       ret = hdb_enctype2key(r->context, &fast_user->entry, NULL,
+       ret = hdb_enctype2key(r->context, fast_user, NULL,
                              enctype, &cookie_key);
     if (ret)
        goto out;
@@ -148,7 +149,7 @@ get_fastuser_crypto(astgs_request_t r,
 
  out:
     if (fast_user)
-       _kdc_free_ent(r->context, fast_user);
+       _kdc_free_ent(r->context, fast_db, fast_user);
     if (fast_crypto)
        krb5_crypto_destroy(r->context, fast_crypto);
     krb5_free_principal(r->context, fast_princ);
@@ -457,7 +458,7 @@ fast_unwrap_request(astgs_request_t r,
     krb5_principal armor_server_principal = NULL;
     char *armor_client_principal_name = NULL;
     char *armor_server_principal_name = NULL;
-    PA_FX_FAST_REQUEST fxreq = {0};
+    PA_FX_FAST_REQUEST fxreq;
     krb5_auth_context ac = NULL;
     krb5_ticket *ticket = NULL;
     krb5_flags ap_req_options;
@@ -466,12 +467,15 @@ fast_unwrap_request(astgs_request_t r,
     krb5_boolean explicit_armor;
     krb5_error_code ret;
     krb5_ap_req ap_req;
-    KrbFastReq fastreq = {0};
+    KrbFastReq fastreq;
     const PA_DATA *pa;
     krb5_data data;
     size_t len;
     int i = 0;
 
+    memset(&fxreq, 0, sizeof(fxreq));
+    memset(&fastreq, 0, sizeof(fastreq));
+
     pa = _kdc_find_padata(&r->req, &i, KRB5_PADATA_FX_FAST);
     if (pa == NULL) {
        if (tgs_ac && r->fast_asserted) {
@@ -548,7 +552,7 @@ fast_unwrap_request(astgs_request_t r,
        ret = _kdc_db_fetch(r->context, r->config, armor_server_principal,
                            HDB_F_GET_KRBTGT | HDB_F_DELAY_NEW_KEYS,
                            (krb5uint32 *)ap_req.ticket.enc_part.kvno,
-                           NULL, &r->armor_server);
+                           &r->armor_serverdb, &r->armor_server);
        if(ret == HDB_ERR_NOT_FOUND_HERE) {
            free_AP_REQ(&ap_req);
            kdc_log(r->context, r->config, 5,
@@ -561,7 +565,7 @@ fast_unwrap_request(astgs_request_t r,
            goto out;
        }
 
-       ret = hdb_enctype2key(r->context, &r->armor_server->entry, NULL,
+       ret = hdb_enctype2key(r->context, r->armor_server, NULL,
                              ap_req.ticket.enc_part.etype,
                              &r->armor_key);
        if (ret) {
@@ -591,8 +595,8 @@ fast_unwrap_request(astgs_request_t r,
                                &r->armor_ticket->ticket,
                                armor_server_principal_name);
        if (ret) {
-           _kdc_audit_addreason((kdc_request_t)r,
-                                "Armor TGT expired or invalid");
+           kdc_audit_addreason((kdc_request_t)r,
+                               "Armor TGT expired or invalid");
            goto out;
        }
        ticket = r->armor_ticket;
@@ -603,8 +607,8 @@ fast_unwrap_request(astgs_request_t r,
     }
 
     krb5_unparse_name(r->context, ticket->client, &armor_client_principal_name);
-    _kdc_audit_addkv((kdc_request_t)r, 0, "armor_client_name", "%s",
-                     armor_client_principal_name ? armor_client_principal_name : "<unknown>");
+    kdc_audit_addkv((kdc_request_t)r, 0, "armor_client_name", "%s",
+                   armor_client_principal_name ? armor_client_principal_name : "<unknown>");
 
     if (ac->remote_subkey == NULL) {
        krb5_auth_con_free(r->context, ac);
@@ -833,7 +837,8 @@ _kdc_fast_check_armor_pac(astgs_request_t r)
     krb5_boolean ad_kdc_issued = FALSE;
     krb5_pac mspac = NULL;
     krb5_principal armor_client_principal = NULL;
-    hdb_entry_ex *armor_client = NULL;
+    HDB *armor_db;
+    hdb_entry *armor_client = NULL;
     char *armor_client_principal_name = NULL;
 
     flags = HDB_F_FOR_TGS_REQ;
@@ -856,7 +861,7 @@ _kdc_fast_check_armor_pac(astgs_request_t r)
 
     ret = _kdc_db_fetch_client(r->context, r->config, flags,
                               armor_client_principal, armor_client_principal_name,
-                              r->req.req_body.realm, NULL, &armor_client);
+                              r->req.req_body.realm, &armor_db, &armor_client);
     if (ret)
        goto out;
 
@@ -885,7 +890,7 @@ _kdc_fast_check_armor_pac(astgs_request_t r)
 out:
     krb5_xfree(armor_client_principal_name);
     if (armor_client)
-       _kdc_free_ent(r->context, armor_client);
+       _kdc_free_ent(r->context, armor_db, armor_client);
     krb5_free_principal(r->context, armor_client_principal);
     krb5_pac_free(r->context, mspac);
 
index ce62a29afccc3e70217e94c64b6690c78c4eb78c..d8a2a24fd941f1be286fdaaac60d399a3bfa64a8 100644 (file)
@@ -51,7 +51,6 @@ struct gss_client_params {
     OM_uint32 flags;
     OM_uint32 lifetime;
     krb5_checksum req_body_checksum;
-    krb5_data pac_data;
 };
 
 static void
@@ -66,6 +65,9 @@ pa_gss_display_name(gss_name_t name,
                     gss_buffer_t namebuf,
                     gss_const_buffer_t *namebuf_p);
 
+static void HEIM_CALLCONV
+pa_gss_dealloc_client_params(void *ptr);
+
 /*
  * Create a checksum over KDC-REQ-BODY (without the nonce), used to
  * assert the request is invariant within the preauth conversation.
@@ -132,6 +134,7 @@ pa_gss_decode_context_state(astgs_request_t r,
     krb5_storage *sp;
     size_t cksumsize;
     krb5_data data;
+    int32_t cksumtype;
 
     memset(req_body_checksum, 0, sizeof(*req_body_checksum));
     sec_context_token->length = 0;
@@ -152,10 +155,12 @@ pa_gss_decode_context_state(astgs_request_t r,
     if (ret)
         goto out;
 
-    ret = krb5_ret_int32(sp, &req_body_checksum->cksumtype);
+    ret = krb5_ret_int32(sp, &cksumtype);
     if (ret)
         goto out;
 
+    req_body_checksum->cksumtype = (CKSUMTYPE)cksumtype;
+
     if (req_body_checksum->cksumtype == CKSUMTYPE_NONE ||
        krb5_checksum_is_keyed(r->context, req_body_checksum->cksumtype)) {
        ret = KRB5KDC_ERR_SUMTYPE_NOSUPP;
@@ -271,7 +276,7 @@ pa_gss_encode_context_state(astgs_request_t r,
     if (ret)
         goto out;
 
-    ret = krb5_store_int32(sp, req_body_checksum->cksumtype);
+    ret = krb5_store_int32(sp, (int32_t)req_body_checksum->cksumtype);
     if (ret)
         goto out;
 
@@ -421,7 +426,7 @@ _kdc_gss_rd_padata(astgs_request_t r,
         goto out;
     }
 
-    gcp = calloc(1, sizeof(*gcp));
+    gcp = kdc_object_alloc(sizeof(*gcp), "pa-gss-client-params", pa_gss_dealloc_client_params);
     if (gcp == NULL) {
         ret = krb5_enomem(r->context);
         goto out;
@@ -471,7 +476,7 @@ out:
     if (gcp && gcp->major != GSS_S_NO_CONTEXT)
         *pgcp = gcp;
     else
-        _kdc_gss_free_client_param(r, gcp);
+        kdc_object_release(gcp);
 
     return ret;
 }
@@ -498,7 +503,6 @@ struct pa_gss_authorize_plugin_ctx {
     struct gss_client_params *gcp;
     krb5_boolean authorized;
     krb5_principal initiator_princ;
-    krb5_data pac_data;
 };
 
 static krb5_error_code KRB5_LIB_CALL
@@ -516,8 +520,7 @@ pa_gss_authorize_cb(krb5_context context,
                                  pa_gss_authorize_plugin_ctx->gcp->mech_type,
                                  pa_gss_authorize_plugin_ctx->gcp->flags,
                                  &pa_gss_authorize_plugin_ctx->authorized,
-                                 &pa_gss_authorize_plugin_ctx->initiator_princ,
-                                &pa_gss_authorize_plugin_ctx->pac_data);
+                                 &pa_gss_authorize_plugin_ctx->initiator_princ);
 }
 
 static const char *plugin_deps[] = {
@@ -542,8 +545,7 @@ pa_gss_authorize_plugin(astgs_request_t r,
                         struct gss_client_params *gcp,
                         gss_const_buffer_t display_name,
                         krb5_boolean *authorized,
-                        krb5_principal *initiator_princ,
-                       krb5_data *pac_data)
+                        krb5_principal *initiator_princ)
 {
     krb5_error_code ret;
     struct pa_gss_authorize_plugin_ctx ctx;
@@ -552,7 +554,6 @@ pa_gss_authorize_plugin(astgs_request_t r,
     ctx.gcp = gcp;
     ctx.authorized = 0;
     ctx.initiator_princ = NULL;
-    krb5_data_zero(&ctx.pac_data);
 
     krb5_clear_error_message(r->context);
     ret = _krb5_plugin_run_f(r->context, &gss_preauth_authorizer_data,
@@ -573,7 +574,6 @@ pa_gss_authorize_plugin(astgs_request_t r,
 
     *authorized = ctx.authorized;
     *initiator_princ = ctx.initiator_princ;
-    *pac_data = ctx.pac_data;
 
     return ret;
 }
@@ -583,12 +583,11 @@ pa_gss_authorize_default(astgs_request_t r,
                          struct gss_client_params *gcp,
                          gss_const_buffer_t display_name,
                          krb5_boolean *authorized,
-                         krb5_principal *initiator_princ,
-                        krb5_data *pac_data)
+                         krb5_principal *initiator_princ)
 {
     krb5_error_code ret;
     krb5_principal principal;
-    krb5_const_realm realm = r->server->entry.principal->realm;
+    krb5_const_realm realm = r->server->principal->realm;
     int flags = 0, cross_realm_allowed = 0, unauth_anon;
 
     /*
@@ -684,16 +683,15 @@ _kdc_gss_check_client(astgs_request_t r,
 {
     krb5_error_code ret;
     krb5_principal initiator_princ = NULL;
-    hdb_entry_ex *initiator = NULL;
+    hdb_entry *initiator = NULL;
     krb5_boolean authorized = FALSE;
-    krb5_data pac_data;
+    HDB *clientdb = r->clientdb;
 
     OM_uint32 minor;
     gss_buffer_desc display_name = GSS_C_EMPTY_BUFFER;
     gss_const_buffer_t display_name_p;
 
     *client_name = NULL;
-    krb5_data_zero(&pac_data);
 
     pa_gss_display_name(gcp->initiator_name, &display_name, &display_name_p);
 
@@ -702,10 +700,10 @@ _kdc_gss_check_client(astgs_request_t r,
      * are authorized as the directly corresponding Kerberos principal.
      */
     ret = pa_gss_authorize_plugin(r, gcp, display_name_p,
-                                  &authorized, &initiator_princ, &pac_data);
+                                  &authorized, &initiator_princ);
     if (ret == KRB5_PLUGIN_NO_HANDLE)
         ret = pa_gss_authorize_default(r, gcp, display_name_p,
-                                       &authorized, &initiator_princ, &pac_data);
+                                       &authorized, &initiator_princ);
     if (ret == 0 && !authorized)
         ret = KRB5_KDC_ERR_CLIENT_NAME_MISMATCH;
     if (ret)
@@ -745,15 +743,15 @@ _kdc_gss_check_client(astgs_request_t r,
      * two principals must match, noting that GSS pre-authentication is
      * for authentication, not general purpose impersonation.
      */
-    if (krb5_principal_is_federated(r->context, r->client->entry.principal)) {
-        initiator->entry.flags.force_canonicalize = 1;
+    if (krb5_principal_is_federated(r->context, r->client->principal)) {
+        initiator->flags.force_canonicalize = 1;
 
-        _kdc_free_ent(r->context, r->client);
+        _kdc_free_ent(r->context, clientdb, r->client);
         r->client = initiator;
         initiator = NULL;
     } else if (!krb5_principal_compare(r->context,
-                                       r->client->entry.principal,
-                                       initiator->entry.principal)) {
+                                       r->client->principal,
+                                       initiator->principal)) {
         kdc_log(r->context, r->config, 2,
                 "GSS %s initiator %.*s does not match principal %s",
                 gss_oid_to_name(gcp->mech_type),
@@ -763,14 +761,10 @@ _kdc_gss_check_client(astgs_request_t r,
         goto out;
     }
 
-    gcp->pac_data = pac_data;
-    krb5_data_zero(&pac_data);
-
 out:
     krb5_free_principal(r->context, initiator_princ);
     if (initiator)
-        _kdc_free_ent(r->context, initiator);
-    krb5_data_free(&pac_data);
+        _kdc_free_ent(r->context, r->clientdb, initiator);
     gss_release_buffer(&minor, &display_name);
 
     return ret;
@@ -864,10 +858,10 @@ _kdc_gss_mk_composite_name_ad(astgs_request_t r,
     return ret;
 }
 
-void
-_kdc_gss_free_client_param(astgs_request_t r,
-                           gss_client_params *gcp)
+static void HEIM_CALLCONV
+pa_gss_dealloc_client_params(void *ptr)
 {
+    gss_client_params *gcp = ptr;
     OM_uint32 minor;
 
     if (gcp == NULL)
@@ -877,9 +871,7 @@ _kdc_gss_free_client_param(astgs_request_t r,
     gss_release_name(&minor, &gcp->initiator_name);
     gss_release_buffer(&minor, &gcp->output_token);
     free_Checksum(&gcp->req_body_checksum);
-    krb5_data_free(&gcp->pac_data);
     memset(gcp, 0, sizeof(*gcp));
-    free(gcp);
 }
 
 krb5_error_code
@@ -1013,11 +1005,6 @@ pa_gss_display_name(gss_name_t name,
         *namebuf_p = namebuf;
 }
 
-struct pa_gss_finalize_pac_plugin_ctx {
-    astgs_request_t r;
-    krb5_data *pac_data;
-};
-
 static krb5_error_code KRB5_LIB_CALL
 pa_gss_finalize_pac_cb(krb5_context context,
                        const void *plug,
@@ -1025,11 +1012,8 @@ pa_gss_finalize_pac_cb(krb5_context context,
                        void *userctx)
 {
     const krb5plugin_gss_preauth_authorizer_ftable *authorizer = plug;
-    struct pa_gss_finalize_pac_plugin_ctx *pa_gss_finalize_pac_ctx = userctx;
 
-    return authorizer->finalize_pac(plugctx,
-                                   pa_gss_finalize_pac_ctx->r,
-                                   pa_gss_finalize_pac_ctx->pac_data);
+    return authorizer->finalize_pac(plugctx, userctx);
 }
 
 
@@ -1038,14 +1022,10 @@ _kdc_gss_finalize_pac(astgs_request_t r,
                      gss_client_params *gcp)
 {
     krb5_error_code ret;
-    struct pa_gss_finalize_pac_plugin_ctx ctx;
-
-    ctx.r = r;
-    ctx.pac_data = &gcp->pac_data;
 
     krb5_clear_error_message(r->context);
     ret = _krb5_plugin_run_f(r->context, &gss_preauth_authorizer_data,
-                             0, &ctx, pa_gss_finalize_pac_cb);
+                             0, r, pa_gss_finalize_pac_cb);
 
     if (ret == KRB5_PLUGIN_NO_HANDLE)
        ret = 0;
index 69bd5fc1ae5b1c1d597c2f60f0c704a47fd1bb02..293e59da47baecdf412c695899f581a9309e062e 100644 (file)
@@ -69,11 +69,9 @@ typedef struct krb5plugin_gss_preauth_authorizer_ftable_desc {
                                                    gss_const_OID,       /*mech_type*/
                                                    OM_uint32,           /*ret_flags*/
                                                    krb5_boolean *,      /*authorized*/
-                                                   krb5_principal *,    /*mapped_name*/
-                                                   krb5_data *);        /*pac_data*/
+                                                   krb5_principal *);  /*mapped_name*/
     krb5_error_code     (KRB5_LIB_CALL *finalize_pac)(void *,           /*plug_ctx*/
-                                                      astgs_request_t,  /*r*/
-                                                      krb5_data *);     /*pac_data*/
+                                                      astgs_request_t); /*r*/
 } krb5plugin_gss_preauth_authorizer_ftable;
 
 #endif /* HEIMDAL_KDC_GSS_PREAUTH_AUTHORIZER_PLUGIN_H */
index 6f4d56ae95cb64f8afa9c755cd10a3a95e0d952a..ffe49c8bdfd6efe55785a1a93b77bbd52b822150 100644 (file)
 #include <heimntlm.h>
 #endif
 #include <kdc.h>
-#include <windc_plugin.h>
+#include <kdc-plugin.h>
+#include <kdc-audit.h>
 
 #include <heimbase.h>
 
index 2746e1d8fccc026318bc113c98aa3a004890f7a0..acf66bcd6147d5c594e993a16fa75f75ba583e85 100644 (file)
@@ -50,7 +50,6 @@
 .Oc
 .Op Fl Fl source= Ns Ar heimdal|mit-dump
 .Oo Fl r Ar string \*(Ba Xo
-.Fl Fl v4-realm= Ns Ar string
 .Xc
 .Oc
 .Oo Fl c Ar cell \*(Ba Xo
index 880a6f746406d983919cb2ad969493cf05f6c05d..c1db11b978ec5f621b075f03c31dbe9d954dfa3d 100644 (file)
@@ -87,28 +87,28 @@ open_socket(krb5_context context, const char *hostname, const char *port)
 }
 
 krb5_error_code
-v5_prop(krb5_context context, HDB *db, hdb_entry_ex *entry, void *appdata)
+v5_prop(krb5_context context, HDB *db, hdb_entry *entry, void *appdata)
 {
     krb5_error_code ret;
     struct prop_data *pd = appdata;
     krb5_data data;
 
     if(encrypt_flag) {
-       ret = hdb_seal_keys_mkey(context, &entry->entry, mkey5);
+       ret = hdb_seal_keys_mkey(context, entry, mkey5);
        if (ret) {
            krb5_warn(context, ret, "hdb_seal_keys_mkey");
            return ret;
        }
     }
     if(decrypt_flag) {
-       ret = hdb_unseal_keys_mkey(context, &entry->entry, mkey5);
+       ret = hdb_unseal_keys_mkey(context, entry, mkey5);
        if (ret) {
            krb5_warn(context, ret, "hdb_unseal_keys_mkey");
            return ret;
        }
     }
 
-    ret = hdb_entry2value(context, &entry->entry, &data);
+    ret = hdb_entry2value(context, entry, &data);
     if(ret) {
        krb5_warn(context, ret, "hdb_entry2value");
        return ret;
@@ -316,9 +316,18 @@ propagate_database (krb5_context context, int type,
 
         if (local_realm) {
             krb5_realm my_realm;
-            krb5_get_default_realm(context,&my_realm);
-            krb5_principal_set_realm(context,server,my_realm);
-           krb5_xfree(my_realm);
+            ret = krb5_get_default_realm(context,&my_realm);
+           if (ret == 0) {
+               ret = krb5_principal_set_realm(context,server,my_realm);
+               krb5_xfree(my_realm);
+           }
+           if (ret) {
+               failed++;
+               krb5_warn(context, ret, "unable to obtain default or set realm");
+               krb5_free_principal(context, server);
+               close(fd);
+               continue;
+           }
         }
 
        auth_context = NULL;
index 426bf6ed7fd502d80d462d3b21d37c200818cee6..59c39ea478479aeccefdcf690e126317160c293d 100644 (file)
@@ -53,23 +53,7 @@ struct prop_data{
 #define NEVERDATE ((1U << 31) - 1)
 #endif
 
-krb5_error_code v5_prop(krb5_context, HDB*, hdb_entry_ex*, void*);
+krb5_error_code v5_prop(krb5_context, HDB*, hdb_entry*, void*);
 int mit_prop_dump(void*, const char*);
 
-struct v4_principal {
-    char name[64];
-    char instance[64];
-    DES_cblock key;
-    int kvno;
-    int mkvno;
-    time_t exp_date;
-    time_t mod_date;
-    char mod_name[64];
-    char mod_instance[64];
-    int max_life;
-};
-
-int v4_prop(void*, struct v4_principal*);
-int v4_prop_dump(void *arg, const char*);
-
 #endif /* __HPROP_H__ */
index 31b44e28a59c76e0cc8f56cc72ad7ed091a8b7d2..9056b05a8d242232df668dc3118d05167fe3797d 100644 (file)
@@ -51,7 +51,6 @@
 .Fl Fl keytab= Ns Ar keytab
 .Xc
 .Oc
-.Op Fl 4 | Fl Fl v4dump
 .Ek
 .Sh DESCRIPTION
 .Nm
@@ -83,8 +82,6 @@ print dump to stdout
 not started from inetd
 .It Fl k Ar keytab , Fl Fl keytab= Ns Ar keytab
 keytab to use for authentication
-.It Fl 4 , Fl Fl v4dump
-create v4 type DB
 .El
 .Sh SEE ALSO
 .Xr hprop 8
index fd9df08e8d78f3378e3980e269303d9c1b87c4b2..fa06a1fd40198398e038e724381cb371eb821213 100644 (file)
@@ -125,6 +125,7 @@ main(int argc, char **argv)
        krb5_ticket *ticket;
        char *server;
 
+        memset(&ss, 0, sizeof(ss));
        sock = STDIN_FILENO;
 #ifdef SUPPORT_INETD
        if (inetd_flag == -1) {
@@ -146,7 +147,7 @@ main(int argc, char **argv)
        if (getpeername(sock, sa, &sin_len) < 0)
            krb5_err(context, 1, errno, "getpeername");
 
-       if (inet_ntop(ss.ss_family,
+       if (inet_ntop(sa->sa_family,
                      socket_get_address (sa),
                      addr_name,
                      sizeof(addr_name)) == NULL)
@@ -225,7 +226,7 @@ main(int argc, char **argv)
     nprincs = 0;
     while (1){
        krb5_data data;
-       hdb_entry_ex entry;
+       hdb_entry entry;
 
        if (from_stdin) {
            ret = krb5_read_message(context, &sock, &data);
@@ -254,7 +255,7 @@ main(int argc, char **argv)
            break;
        }
        memset(&entry, 0, sizeof(entry));
-       ret = hdb_value2entry(context, &data, &entry.entry);
+       ret = hdb_value2entry(context, &data, &entry);
        krb5_data_free(&data);
        if (ret)
            krb5_err(context, 1, ret, "hdb_value2entry");
@@ -268,7 +269,7 @@ main(int argc, char **argv)
            ret = db->hdb_store(context, db, 0, &entry);
            if (ret == HDB_ERR_EXISTS) {
                char *s;
-               ret = krb5_unparse_name(context, entry.entry.principal, &s);
+               ret = krb5_unparse_name(context, entry.principal, &s);
                if (ret)
                    s = strdup(unparseable_name);
                krb5_warnx(context, "Entry exists: %s", s);
@@ -278,7 +279,7 @@ main(int argc, char **argv)
            else
                nprincs++;
        }
-       hdb_free_entry(context, &entry);
+       hdb_free_entry(context, db, &entry);
     }
     if (!print_dump)
        krb5_log(context, fac, 0, "Received %d principals", nprincs);
index 3dfb365186af2ffcdb02c9f300a0289772d6b311..0e31b4044c3ca2577a28904b5e558cc4dbf1e7ef 100644 (file)
 #define heim_pconfig krb5_context
 #include <heimbase-svc.h>
 
+#if MHD_VERSION < 0x00097002 || defined(MHD_YES)
+/* libmicrohttpd changed these from int valued macros to an enum in 0.9.71 */
+#ifdef MHD_YES
+#undef MHD_YES
+#undef MHD_NO
+#endif
+enum MHD_Result { MHD_NO = 0, MHD_YES = 1 };
+#define MHD_YES 1
+#define MHD_NO 0
+typedef int heim_mhd_result;
+#else
+typedef enum MHD_Result heim_mhd_result;
+#endif
+
 #define BODYLEN_IS_STRLEN (~0)
 
 /*
@@ -565,7 +579,7 @@ redirect_uri_appends(struct redirect_uri *redirect,
         redirect->len += len;
 }
 
-static int
+static heim_mhd_result
 make_redirect_uri_param_cb(void *d,
                            enum MHD_ValueKind kind,
                            const char *key,
@@ -700,9 +714,10 @@ bad_reqv(kadmin_request_desc r,
     if (r && r->context)
         context = r->context;
     if (r && r->hcontext && r->kv)
-        heim_audit_addkv((heim_svc_req_desc)r, 0, "http-status-code", "%d",
-                         http_status_code);
-    (void) gettimeofday(&r->tv_end, NULL);
+        heim_audit_setkv_number((heim_svc_req_desc)r, "http-status-code",
+                               http_status_code);
+    if (r)
+        (void) gettimeofday(&r->tv_end, NULL);
     if (code == ENOMEM) {
         if (context)
             krb5_log_msg(context, logfac, 1, NULL, "Out of memory");
@@ -881,7 +896,7 @@ check_service_name(kadmin_request_desc r, const char *name)
     return EACCES;
 }
 
-static int
+static heim_mhd_result
 param_cb(void *d,
          enum MHD_ValueKind kind,
          const char *key,
@@ -1046,12 +1061,12 @@ param_cb(void *d,
 #endif
     } else {
         /* Produce error for unknown params */
-        heim_audit_addkv((heim_svc_req_desc)r, 0, "requested_unknown", "true");
+        heim_audit_setkv_bool((heim_svc_req_desc)r, "requested_unknown", TRUE);
         krb5_set_error_message(r->context, ret = ENOTSUP,
                                "Query parameter %s not supported", key);
     }
-    if (ret && !r->ret)
-        r->ret = ret;
+    if (ret && !r->error_code)
+        r->error_code = ret;
     heim_release(s);
     return ret ? MHD_NO /* Stop iterating */ : MHD_YES;
 }
@@ -1067,7 +1082,7 @@ authorize_req(kadmin_request_desc r)
         return bad_enomem(r, ret);
     (void) MHD_get_connection_values(r->connection, MHD_GET_ARGUMENT_KIND,
                                      param_cb, r);
-    ret = r->ret;
+    ret = r->error_code;
     if (ret == EACCES)
         return bad_403(r, ret, "Not authorized to requested principal(s)");
     if (ret)
@@ -1189,7 +1204,7 @@ make_kstuple(krb5_context context,
 
     if (p->n_key_data < 1)
         return 0;
-    *kstuple = calloc(p->n_key_data, sizeof (*kstuple));
+    *kstuple = calloc(p->n_key_data, sizeof (**kstuple));
     for (i = 0; *kstuple && i < p->n_key_data; i++) {
         if (p->key_data[i].key_data_kvno == p->kvno) {
             (*kstuple)[i].ks_enctype = p->key_data[i].key_data_type[0];
@@ -1417,6 +1432,8 @@ get_keysN(kadmin_request_desc r, const char *method)
             ret = heim_array_append_value(r->service_names, s);
         heim_release(s);
         nsvcs = 1;
+        if (ret)
+            return bad_503(r, ret, "Out of memory");
     }
 
     /* FIXME: Make this configurable */
@@ -1528,7 +1545,8 @@ set_req_desc(struct MHD_Connection *connection,
     r->sname = NULL;
     r->cname = NULL;
     r->addr = NULL;
-    r->kv = heim_array_create();
+    r->kv = heim_dict_create(10);
+    r->attributes = heim_dict_create(1);
     /* Our fields */
     r->connection = connection;
     r->kadm_handle = NULL;
@@ -1570,7 +1588,7 @@ set_req_desc(struct MHD_Connection *connection,
 
     if (ret == 0 && r->kv == NULL) {
         krb5_log_msg(r->context, logfac, 1, NULL, "Out of memory");
-        ret = r->ret = ENOMEM;
+        ret = r->error_code = ENOMEM;
     }
     return ret;
 }
@@ -1643,6 +1661,8 @@ get_config(kadmin_request_desc r)
 
     ret = get_kadm_handle(r->context, r->realm ? r->realm : realm,
                           0 /* want_write */, &r->kadm_handle);
+    if (ret)
+        return bad_503(r, ret, "Could not access KDC database");
 
     memset(&princ, 0, sizeof(princ));
     princ.key_data = NULL;
@@ -1665,7 +1685,7 @@ get_config(kadmin_request_desc r)
                 break;
             }
         } else {
-            r->ret = ret;
+            r->error_code = ret;
             return bad_404(r, "/get-config");
         }
     }
@@ -1725,15 +1745,22 @@ mac_csrf_token(kadmin_request_desc r, krb5_storage *sp)
             ret = krb5_enomem(r->context);
     /* HMAC the token body and the client principal name */
     if (ret == 0) {
-        HMAC_Init_ex(ctx, princ.key_data[i].key_data_contents[0], princ.key_data[i].key_data_length[0], EVP_sha256(), NULL);
-        HMAC_Update(ctx, data.data, data.length);
-        HMAC_Update(ctx, r->cname, strlen(r->cname));
-        HMAC_Final(ctx, mac, &maclen);
-        krb5_data_free(&data);
-        data.length = maclen;
-        data.data = mac;
-        if (krb5_storage_write(sp, mac, maclen) != maclen)
+        if (HMAC_Init_ex(ctx, princ.key_data[i].key_data_contents[0],
+                         princ.key_data[i].key_data_length[0], EVP_sha256(),
+                         NULL) == 0) {
+            HMAC_CTX_cleanup(ctx);
             ret = krb5_enomem(r->context);
+        } else {
+            HMAC_Update(ctx, data.data, data.length);
+            HMAC_Update(ctx, r->cname, strlen(r->cname));
+            HMAC_Final(ctx, mac, &maclen);
+            HMAC_CTX_cleanup(ctx);
+            krb5_data_free(&data);
+            data.length = maclen;
+            data.data = mac;
+            if (krb5_storage_write(sp, mac, maclen) != maclen)
+                ret = krb5_enomem(r->context);
+        }
     }
     krb5_free_principal(r->context, p);
     if (freeit)
@@ -1874,7 +1901,7 @@ health(const char *method, kadmin_request_desc r)
 }
 
 /* Implements the entirety of this REST service */
-static int
+static heim_mhd_result
 route(void *cls,
       struct MHD_Connection *connection,
       const char *url,
@@ -2100,6 +2127,8 @@ main(int argc, char **argv)
 
     argc -= optidx;
     argv += optidx;
+    if (argc != 0)
+        usage(1);
 
     if ((errno = pthread_key_create(&k5ctx, k5_free_context)))
         err(1, "Could not create thread-specific storage");
index fad3919a2a6bfbaee107c828f841dcb15eafc2c5..7d77e7f812a4a0936958d8a252c7190cc77505e9 100644 (file)
@@ -169,6 +169,7 @@ cmd_append(struct rk_strpool **cmd, const char *s0, ...)
 {
     va_list ap;
     const char *arg;
+    int ret = 0;
 
     if ((*cmd = rk_strpoolprintf(*cmd, "%s", s0)) == NULL)
         return ENOMEM;
@@ -177,14 +178,23 @@ cmd_append(struct rk_strpool **cmd, const char *s0, ...)
     while ((arg = va_arg(ap, const char *))) {
         char *s;
 
-        if ((s = string_encode(arg)) == NULL)
-            return rk_strpoolfree(*cmd), *cmd = NULL, ENOMEM;
+        if ((s = string_encode(arg)) == NULL) {
+            rk_strpoolfree(*cmd);
+           *cmd = NULL;
+           ret = ENOMEM;
+           goto out;
+       }
         *cmd = rk_strpoolprintf(*cmd, "%s", s);
         free(s);
-        if (*cmd == NULL)
-            return ENOMEM;
+        if (*cmd == NULL) {
+            ret = ENOMEM;
+           goto out;
+       }
     }
-    return 0;
+
+ out:
+    va_end(ap);
+    return ret;
 }
 
 static int
diff --git a/third_party/heimdal/kdc/kdc-accessors.h b/third_party/heimdal/kdc/kdc-accessors.h
new file mode 100644 (file)
index 0000000..81c03d2
--- /dev/null
@@ -0,0 +1,349 @@
+/*
+ * Copyright (c) 2022, PADL Software Pty Ltd.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of PADL Software nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef HEIMDAL_KDC_KDC_ACCESSORS_H
+#define HEIMDAL_KDC_KDC_ACCESSORS_H 1
+
+/* read-only accessor */
+#ifndef _KDC_REQUEST_GET_ACCESSOR
+#define _KDC_REQUEST_GET_ACCESSOR(R, T, f)                 \
+    KDC_LIB_FUNCTION T KDC_LIB_CALL                        \
+    kdc_request_get_ ## f(R);
+#endif
+
+#ifndef _KDC_REQUEST_SET_ACCESSOR
+#define _KDC_REQUEST_SET_ACCESSOR(R, T, f)                 \
+    KDC_LIB_FUNCTION void KDC_LIB_CALL                     \
+    kdc_request_set_ ## f(R, T);
+#endif
+
+#ifndef KDC_REQUEST_GET_ACCESSOR
+#define KDC_REQUEST_GET_ACCESSOR(T, f)                     \
+    _KDC_REQUEST_GET_ACCESSOR(kdc_request_t, T, f)
+#endif
+
+#ifndef KDC_REQUEST_SET_ACCESSOR
+#define KDC_REQUEST_SET_ACCESSOR(T, f)                     \
+    _KDC_REQUEST_SET_ACCESSOR(kdc_request_t, T, f)
+#endif
+
+#ifndef ASTGS_REQUEST_GET_ACCESSOR
+#define ASTGS_REQUEST_GET_ACCESSOR(T, f)                   \
+    _KDC_REQUEST_GET_ACCESSOR(astgs_request_t, T, f)
+#endif
+
+#ifndef ASTGS_REQUEST_SET_ACCESSOR
+#define ASTGS_REQUEST_SET_ACCESSOR(T, f)                   \
+    _KDC_REQUEST_SET_ACCESSOR(astgs_request_t, T, f)
+#endif
+
+/* get/set accessor for pointer type */
+#ifndef _KDC_REQUEST_GET_ACCESSOR_PTR
+#define _KDC_REQUEST_GET_ACCESSOR_PTR(R, T, f)             \
+    KDC_LIB_FUNCTION const T KDC_LIB_CALL                  \
+    kdc_request_get_ ## f(R);
+#endif
+
+#ifndef _KDC_REQUEST_SET_ACCESSOR_PTR
+#define _KDC_REQUEST_SET_ACCESSOR_PTR(R, T, t, f)          \
+    KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL          \
+    kdc_request_set_ ## f(R, const T);
+#endif
+
+#ifndef KDC_REQUEST_GET_ACCESSOR_PTR
+#define KDC_REQUEST_GET_ACCESSOR_PTR(T, f)                 \
+    _KDC_REQUEST_GET_ACCESSOR_PTR(kdc_request_t, T, f)
+#endif
+
+#ifndef KDC_REQUEST_SET_ACCESSOR_PTR
+#define KDC_REQUEST_SET_ACCESSOR_PTR(T, t, f)              \
+    _KDC_REQUEST_SET_ACCESSOR_PTR(kdc_request_t, T, t, f)
+#endif
+
+#ifndef ASTGS_REQUEST_GET_ACCESSOR_PTR
+#define ASTGS_REQUEST_GET_ACCESSOR_PTR(T, f)               \
+    _KDC_REQUEST_GET_ACCESSOR_PTR(astgs_request_t, T, f)
+#endif
+
+#ifndef ASTGS_REQUEST_SET_ACCESSOR_PTR
+#define ASTGS_REQUEST_SET_ACCESSOR_PTR(T, t, f)                    \
+    _KDC_REQUEST_SET_ACCESSOR_PTR(astgs_request_t, T, t, f)
+#endif
+
+/* get/set accessor for struct type */
+#ifndef _KDC_REQUEST_GET_ACCESSOR_STRUCT
+#define _KDC_REQUEST_GET_ACCESSOR_STRUCT(R, T, f)          \
+    KDC_LIB_FUNCTION const T * KDC_LIB_CALL                \
+    kdc_request_get_ ## f(R);
+#endif
+
+#ifndef _KDC_REQUEST_SET_ACCESSOR_STRUCT
+#define _KDC_REQUEST_SET_ACCESSOR_STRUCT(R, T, t, f)       \
+    KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL          \
+    kdc_request_set_ ## f(R, const T *);
+#endif
+
+#ifndef KDC_REQUEST_GET_ACCESSOR_STRUCT
+#define KDC_REQUEST_GET_ACCESSOR_STRUCT(T, f)              \
+    _KDC_REQUEST_GET_ACCESSOR_STRUCT(kdc_request_t, T, f)
+#endif
+
+#ifndef KDC_REQUEST_SET_ACCESSOR_STRUCT
+#define KDC_REQUEST_SET_ACCESSOR_STRUCT(T, t, f)           \
+    _KDC_REQUEST_SET_ACCESSOR_STRUCT(kdc_request_t, T, t, f)
+#endif
+
+#ifndef ASTGS_REQUEST_GET_ACCESSOR_STRUCT
+#define ASTGS_REQUEST_GET_ACCESSOR_STRUCT(T, f)                    \
+    _KDC_REQUEST_GET_ACCESSOR_STRUCT(astgs_request_t, T, f)
+#endif
+
+#ifndef ASTGS_REQUEST_SET_ACCESSOR_STRUCT
+#define ASTGS_REQUEST_SET_ACCESSOR_STRUCT(T, t, f)         \
+    _KDC_REQUEST_SET_ACCESSOR_STRUCT(astgs_request_t, T, t, f)
+#endif
+
+/*
+ * krb5_context
+ * kdc_request_get_context(kdc_request_t);
+ */
+
+KDC_REQUEST_GET_ACCESSOR(krb5_context, context)
+
+/*
+ * krb5_kdc_configuration *
+ * kdc_request_get_config(kdc_request_t);
+ */
+
+KDC_REQUEST_GET_ACCESSOR(krb5_kdc_configuration *, config)
+
+/*
+ * heim_log_facility *
+ * kdc_request_get_logf(kdc_request_t);
+ */
+
+KDC_REQUEST_GET_ACCESSOR(heim_log_facility *, logf)
+
+/*
+ * const char *
+ * kdc_request_get_from(kdc_request_t);
+ */
+
+KDC_REQUEST_GET_ACCESSOR_PTR(char *, from)
+
+/*
+ * const struct sockaddr *
+ * kdc_request_get_addr(kdc_request_t);
+ */
+
+KDC_REQUEST_GET_ACCESSOR_PTR(struct sockaddr *, addr)
+
+/*
+ * krb5_data
+ * kdc_request_get_request(kdc_request_t);
+ */
+
+KDC_REQUEST_GET_ACCESSOR(krb5_data, request)
+
+/*
+ * struct timeval
+ * kdc_request_get_tv_start(kdc_request_t);
+ */
+
+KDC_REQUEST_GET_ACCESSOR(struct timeval, tv_start)
+
+/*
+ * struct timeval
+ * kdc_request_get_tv_end(kdc_request_t);
+ */
+
+KDC_REQUEST_GET_ACCESSOR(struct timeval, tv_end)
+
+/*
+ * krb5_error_code
+ * kdc_request_get_error_code(kdc_request_t);
+ */
+KDC_REQUEST_GET_ACCESSOR(krb5_error_code, error_code)
+
+/*
+ * void
+ * kdc_request_set_error_code(kdc_request_t, krb5_error_code);
+ */
+KDC_REQUEST_SET_ACCESSOR(krb5_error_code, error_code)
+
+/*
+ * const KDC_REQ *
+ * kdc_request_get_req(astgs_request_t);
+ */
+
+ASTGS_REQUEST_GET_ACCESSOR_STRUCT(KDC_REQ, req)
+
+/*
+ * const KDC_REP *
+ * kdc_request_get_rep(astgs_request_t);
+ */
+
+ASTGS_REQUEST_GET_ACCESSOR_STRUCT(KDC_REP, rep)
+
+/*
+ * krb5_error_code
+ * kdc_request_set_rep(astgs_request_t, const KDC_REP *);
+ */
+
+ASTGS_REQUEST_SET_ACCESSOR_STRUCT(KDC_REP, KDC_REP, rep)
+
+/*
+ * const char *
+ * kdc_request_get_cname(kdc_request_t);
+ */
+
+KDC_REQUEST_GET_ACCESSOR_PTR(char *, cname)
+
+/*
+ * krb5_error_code
+ * kdc_request_set_cname(kdc_request_t, const char *);
+ */
+
+KDC_REQUEST_SET_ACCESSOR_PTR(char *, string_ptr, cname)
+
+/*
+ * const Principal *
+ * kdc_request_get_client_princ(astgs_request_t);
+ */
+
+ASTGS_REQUEST_GET_ACCESSOR_PTR(Principal *, client_princ)
+
+/*
+ * krb5_error_code
+ * kdc_request_set_client_princ(astgs_request_t, const Principal *);
+ */
+
+ASTGS_REQUEST_SET_ACCESSOR_PTR(Principal *, Principal_ptr, client_princ)
+
+/*
+ * const Principal *
+ * kdc_request_get_canon_client_princ(astgs_request_t);
+ */
+
+ASTGS_REQUEST_GET_ACCESSOR_PTR(Principal *, canon_client_princ)
+
+/*
+ * krb5_error_code
+ * kdc_request_set_canon_client_princ(astgs_request_t, const Principal *);
+ */
+
+ASTGS_REQUEST_SET_ACCESSOR_PTR(Principal *, Principal_ptr, canon_client_princ)
+
+/*
+ * const HDB *
+ * kdc_request_get_clientdb(astgs_request_t);
+ */
+
+ASTGS_REQUEST_GET_ACCESSOR_PTR(HDB *, clientdb)
+
+/*
+ * const hdb_entry *
+ * kdc_request_get_client(astgs_request_t);
+ */
+
+ASTGS_REQUEST_GET_ACCESSOR_PTR(hdb_entry *, client)
+
+/*
+ * See client accessors
+ */
+
+KDC_REQUEST_GET_ACCESSOR_PTR(char *, sname)
+KDC_REQUEST_SET_ACCESSOR_PTR(char *, string_ptr, sname)
+ASTGS_REQUEST_GET_ACCESSOR_PTR(Principal *, server_princ)
+ASTGS_REQUEST_SET_ACCESSOR_PTR(Principal *, Principal_ptr, server_princ)
+ASTGS_REQUEST_GET_ACCESSOR_PTR(HDB *, serverdb)
+ASTGS_REQUEST_GET_ACCESSOR_PTR(hdb_entry *, server)
+
+/*
+ * See client accessors
+ */
+
+ASTGS_REQUEST_GET_ACCESSOR_PTR(Principal *, krbtgt_princ)
+ASTGS_REQUEST_SET_ACCESSOR_PTR(Principal *, Principal_ptr, krbtgt_princ)
+ASTGS_REQUEST_GET_ACCESSOR_PTR(HDB *, krbtgtdb)
+ASTGS_REQUEST_GET_ACCESSOR_PTR(hdb_entry *, krbtgt)
+
+/*
+ * krb5_ticket *
+ * kdc_request_get_ticket(astgs_request_t);
+ */
+
+ASTGS_REQUEST_GET_ACCESSOR(krb5_ticket *, ticket)
+
+/*
+ * const krb5_keyblock *
+ * kdc_request_get_reply_key(astgs_request_t);
+ */
+
+ASTGS_REQUEST_GET_ACCESSOR_STRUCT(krb5_keyblock, reply_key)
+
+/*
+ * krb5_error_code
+ * kdc_request_set_reply_key(astgs_request_t, const krb5_keyblock *);
+ */
+
+ASTGS_REQUEST_SET_ACCESSOR_STRUCT(krb5_keyblock, keyblock, reply_key)
+
+/*
+ * krb5_const_pac
+ * kdc_request_get_pac(astgs_request_t);
+ */
+
+ASTGS_REQUEST_GET_ACCESSOR_PTR(struct krb5_pac_data *, pac)
+
+/*
+ * krb5_error_code
+ * kdc_request_set_pac(astgs_request_t, krb5_const_pac);
+ */
+
+ASTGS_REQUEST_SET_ACCESSOR_PTR(struct krb5_pac_data *, pac, pac)
+
+/*
+ * uint64_t
+ * kdc_request_get_pac_attributes(astgs_request_t);
+ */
+
+ASTGS_REQUEST_GET_ACCESSOR(uint64_t, pac_attributes)
+
+/*
+ * void
+ * kdc_request_set_pac_attributes(astgs_request_t, uint64_t);
+ */
+
+ASTGS_REQUEST_SET_ACCESSOR(uint64_t, pac_attributes)
+
+#endif /* HEIMDAL_KDC_KDC_ACCESSORS_H */
similarity index 50%
rename from third_party/heimdal/kdc/rx.h
rename to third_party/heimdal/kdc/kdc-audit.h
index f914e93e6efcb9ca01a2417b1d3ccb46edb33707..4b2203f226799e459b049dd23d628043658052d9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997 Kungliga Tekniska Högskolan
+ * Copyright (c) 2006 Kungliga Tekniska Högskolan
  * (Royal Institute of Technology, Stockholm, Sweden).
  * All rights reserved.
  *
 
 /* $Id$ */
 
-#ifndef __RX_H__
-#define __RX_H__
+#ifndef HEIMDAL_KDC_KDC_AUDIT_H
+#define HEIMDAL_KDC_KDC_AUDIT_H 1
 
-/* header of a RPC packet */
-
-enum rx_header_type {
-     HT_DATA = 1,
-     HT_ACK = 2,
-     HT_BUSY = 3,
-     HT_ABORT = 4,
-     HT_ACKALL = 5,
-     HT_CHAL = 6,
-     HT_RESP = 7,
-     HT_DEBUG = 8
-};
-
-/* For flags in header */
+/*
+ * KDC auditing
+ */
 
-enum rx_header_flag {
-     HF_CLIENT_INITIATED = 1,
-     HF_REQ_ACK = 2,
-     HF_LAST = 4,
-     HF_MORE = 8
-};
+/* auth event type enumeration, currently for AS only */
+#define KDC_AUTH_EVENT_INVALID                 0   /* no event logged */
+#define KDC_AUTH_EVENT_CLIENT_AUTHORIZED       1   /* all authn/authz checks passed */
+#define KDC_AUTH_EVENT_CLIENT_UNKNOWN          2   /* client unknown */
+#define KDC_AUTH_EVENT_CLIENT_LOCKED_OUT       3   /* client locked out */
+#define KDC_AUTH_EVENT_CLIENT_TIME_SKEW                4   /* client time skew */
+#define KDC_AUTH_EVENT_WRONG_LONG_TERM_KEY     5   /* PA failed to validate long term key */
+#define KDC_AUTH_EVENT_VALIDATED_LONG_TERM_KEY 6   /* PA validated long term key */
+#define KDC_AUTH_EVENT_CLIENT_NAME_UNAUTHORIZED        7   /* couldn't map GSS/PKINIT name to principal */
+#define KDC_AUTH_EVENT_PREAUTH_FAILED          8   /* generic PA failure */
+#define KDC_AUTH_EVENT_PREAUTH_SUCCEEDED       9   /* generic (non-long term key) PA success */
 
-struct rx_header {
-     uint32_t epoch;
-     uint32_t connid;          /* And channel ID */
-     uint32_t callid;
-     uint32_t seqno;
-     uint32_t serialno;
-     u_char type;
-     u_char flags;
-     u_char status;
-     u_char secindex;
-     uint16_t reserved;        /* ??? verifier? */
-     uint16_t serviceid;
-/* This should be the other way around according to everything but */
-/* tcpdump */
-};
+/*
+ * Audit keys to be queried using kdc_audit_getkv(). There are other keys
+ * intended for logging that are not defined below; the constants below are
+ * there to ease migration from the older auth_status HDB API.
+ */
 
-#define RX_HEADER_SIZE 28
+#define KDC_REQUEST_KV_AUTH_EVENT              "#auth_event"           /* heim_number_t */
+#define KDC_REQUEST_KV_PA_NAME                 "pa"                    /* heim_string_t */
+#define KDC_REQUEST_KV_PA_ETYPE                        "pa-etype"              /* heim_number_t */
+#define KDC_REQUEST_KV_GSS_INITIATOR           "gss_initiator"         /* heim_string_t */
+#define KDC_REQUEST_KV_PKINIT_CLIENT_CERT      "pkinit_client_cert"    /* heim_string_t */
 
-#endif /* __RX_H__ */
+#endif /* HEIMDAL_KDC_KDC_AUDIT_H */
diff --git a/third_party/heimdal/kdc/kdc-plugin.c b/third_party/heimdal/kdc/kdc-plugin.c
new file mode 100644 (file)
index 0000000..8759893
--- /dev/null
@@ -0,0 +1,658 @@
+/*
+ * Copyright (c) 2007 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Portions (c) 2021, 2022 PADL Software Pty Ltd.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "kdc_locl.h"
+
+static int have_plugin = 0;
+
+/*
+ * Pick the first KDC plugin module that we find.
+ */
+
+static const char *kdc_plugin_deps[] = {
+    "kdc",
+    "krb5",
+    "hdb",
+    NULL
+};
+
+static struct heim_plugin_data kdc_plugin_data = {
+    "krb5",
+    "kdc",
+    KRB5_PLUGIN_KDC_VERSION_10,
+    kdc_plugin_deps,
+    kdc_get_instance
+};
+
+static krb5_error_code KRB5_LIB_CALL
+load(krb5_context context, const void *plug, void *plugctx, void *userctx)
+{
+    have_plugin = 1;
+    return KRB5_PLUGIN_NO_HANDLE;
+}
+
+KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL
+krb5_kdc_plugin_init(krb5_context context)
+{
+    (void)_krb5_plugin_run_f(context, &kdc_plugin_data, 0, NULL, load);
+
+    return 0;
+}
+
+struct generate_uc {
+    krb5_kdc_configuration *config;
+    hdb_entry *client;
+    hdb_entry *server;
+    const krb5_keyblock *reply_key;
+    uint64_t pac_attributes;
+    krb5_pac *pac;
+};
+
+static krb5_error_code KRB5_LIB_CALL
+generate(krb5_context context, const void *plug, void *plugctx, void *userctx)
+{
+    const krb5plugin_kdc_ftable *ft = (const krb5plugin_kdc_ftable *)plug;
+    struct generate_uc *uc = (struct generate_uc *)userctx;    
+
+    if (ft->pac_generate == NULL)
+       return KRB5_PLUGIN_NO_HANDLE;
+
+    return ft->pac_generate((void *)plug,
+                           context,
+                           uc->config,
+                           uc->client,
+                           uc->server,
+                           uc->reply_key,
+                           uc->pac_attributes,
+                           uc->pac);
+}
+
+
+krb5_error_code
+_kdc_pac_generate(krb5_context context,
+                 krb5_kdc_configuration *config,
+                 hdb_entry *client,
+                 hdb_entry *server,
+                 const krb5_keyblock *reply_key,
+                 uint64_t pac_attributes,
+                 krb5_pac *pac)
+{
+    krb5_error_code ret = 0;
+    struct generate_uc uc;
+
+    *pac = NULL;
+
+    if (krb5_config_get_bool_default(context, NULL, FALSE, "realms",
+                                    client->principal->realm,
+                                    "disable_pac", NULL))
+       return 0;
+
+    if (have_plugin) {
+       uc.config = config;
+       uc.client = client;
+       uc.server = server;
+       uc.reply_key = reply_key;
+       uc.pac = pac;
+       uc.pac_attributes = pac_attributes;
+
+       ret = _krb5_plugin_run_f(context, &kdc_plugin_data,
+                                0, &uc, generate);
+       if (ret != KRB5_PLUGIN_NO_HANDLE)
+           return ret;
+       ret = 0;
+    }
+
+    if (*pac == NULL)
+       ret = krb5_pac_init(context, pac);
+
+    return ret;
+}
+
+struct verify_uc {
+    krb5_kdc_configuration *config;
+    krb5_principal client_principal;
+    krb5_principal delegated_proxy_principal;
+    hdb_entry *client;
+    hdb_entry *server;
+    hdb_entry *krbtgt;
+    krb5_pac *pac;
+};
+
+static krb5_error_code KRB5_LIB_CALL
+verify(krb5_context context, const void *plug, void *plugctx, void *userctx)
+{
+    const krb5plugin_kdc_ftable *ft = (const krb5plugin_kdc_ftable *)plug;
+    struct verify_uc *uc = (struct verify_uc *)userctx;
+    krb5_error_code ret;
+
+    if (ft->pac_verify == NULL)
+       return KRB5_PLUGIN_NO_HANDLE;
+
+    ret = ft->pac_verify((void *)plug,
+                        context,
+                        uc->config,
+                        uc->client_principal,
+                        uc->delegated_proxy_principal,
+                        uc->client, uc->server, uc->krbtgt, uc->pac);
+    return ret;
+}
+
+krb5_error_code
+_kdc_pac_verify(krb5_context context,
+               krb5_kdc_configuration *config,
+               const krb5_principal client_principal,
+               const krb5_principal delegated_proxy_principal,
+               hdb_entry *client,
+               hdb_entry *server,
+               hdb_entry *krbtgt,
+               krb5_pac *pac)
+{
+    struct verify_uc uc;
+
+    if (!have_plugin)
+       return KRB5_PLUGIN_NO_HANDLE;
+
+    uc.config = config;
+    uc.client_principal = client_principal;
+    uc.delegated_proxy_principal = delegated_proxy_principal;
+    uc.client = client;
+    uc.server = server;
+    uc.krbtgt = krbtgt;
+    uc.pac = pac;
+
+    return _krb5_plugin_run_f(context, &kdc_plugin_data,
+                            0, &uc, verify);
+}
+
+static krb5_error_code KRB5_LIB_CALL
+check(krb5_context context, const void *plug, void *plugctx, void *userctx)
+{
+    const krb5plugin_kdc_ftable *ft = (const krb5plugin_kdc_ftable *)plug;
+
+    if (ft->client_access == NULL)
+       return KRB5_PLUGIN_NO_HANDLE;
+    return ft->client_access((void *)plug, userctx);
+}
+
+krb5_error_code
+_kdc_check_access(astgs_request_t r)
+{
+    krb5_error_code ret = KRB5_PLUGIN_NO_HANDLE;
+
+    if (have_plugin) {
+        ret = _krb5_plugin_run_f(r->context, &kdc_plugin_data,
+                                 0, r, check);
+    }
+
+    if (ret == KRB5_PLUGIN_NO_HANDLE)
+        return kdc_check_flags(r, r->req.msg_type == krb_as_req,
+                               r->client, r->server);
+    return ret;
+}
+
+static krb5_error_code KRB5_LIB_CALL
+referral_policy(krb5_context context, const void *plug, void *plugctx, void *userctx)
+{
+    const krb5plugin_kdc_ftable *ft = (const krb5plugin_kdc_ftable *)plug;
+
+    if (ft->referral_policy == NULL)
+       return KRB5_PLUGIN_NO_HANDLE;
+    return ft->referral_policy((void *)plug, userctx);
+}
+
+krb5_error_code
+_kdc_referral_policy(astgs_request_t r)
+{
+    krb5_error_code ret = KRB5_PLUGIN_NO_HANDLE;
+
+    if (have_plugin)
+        ret = _krb5_plugin_run_f(r->context, &kdc_plugin_data, 0, r, referral_policy);
+
+    return ret;
+}
+
+static krb5_error_code KRB5_LIB_CALL
+finalize_reply(krb5_context context, const void *plug, void *plugctx, void *userctx)
+{
+    const krb5plugin_kdc_ftable *ft = (const krb5plugin_kdc_ftable *)plug;
+
+    if (ft->finalize_reply == NULL)
+       return KRB5_PLUGIN_NO_HANDLE;
+    return ft->finalize_reply((void *)plug, userctx);
+}
+
+krb5_error_code
+_kdc_finalize_reply(astgs_request_t r)
+{
+    krb5_error_code ret = KRB5_PLUGIN_NO_HANDLE;
+
+    if (have_plugin)
+        ret = _krb5_plugin_run_f(r->context, &kdc_plugin_data, 0, r, finalize_reply);
+
+    if (ret == KRB5_PLUGIN_NO_HANDLE)
+        ret = 0;
+
+    return ret;
+}
+
+static krb5_error_code KRB5_LIB_CALL
+audit(krb5_context context, const void *plug, void *plugctx, void *userctx)
+{
+    const krb5plugin_kdc_ftable *ft = (const krb5plugin_kdc_ftable *)plug;
+
+    if (ft->audit == NULL)
+       return KRB5_PLUGIN_NO_HANDLE;
+    return ft->audit((void *)plug, userctx);
+}
+
+krb5_error_code
+_kdc_plugin_audit(astgs_request_t r)
+{
+    krb5_error_code ret = KRB5_PLUGIN_NO_HANDLE;
+
+    if (have_plugin)
+        ret = _krb5_plugin_run_f(r->context, &kdc_plugin_data, 0, r, audit);
+
+    if (ret == KRB5_PLUGIN_NO_HANDLE)
+        ret = 0;
+
+    return ret;
+}
+
+KDC_LIB_FUNCTION uintptr_t KDC_LIB_CALL
+kdc_get_instance(const char *libname)
+{
+    static const char *instance = "libkdc";
+
+    if (strcmp(libname, "kdc") == 0)
+        return (uintptr_t)instance;
+    else if (strcmp(libname, "hdb") == 0)
+       return hdb_get_instance(libname);
+    else if (strcmp(libname, "krb5") == 0)
+        return krb5_get_instance(libname);
+
+    return 0;
+}
+
+/*
+ * Minimum API surface wrapper for libheimbase object types so it
+ * may remain a private interface, yet plugins can interact with
+ * objects.
+ */
+
+KDC_LIB_FUNCTION kdc_object_t KDC_LIB_CALL
+kdc_object_alloc(size_t size, const char *name, kdc_type_dealloc dealloc)
+{
+    return heim_alloc(size, name, dealloc);
+}
+
+KDC_LIB_FUNCTION kdc_object_t KDC_LIB_CALL
+kdc_object_retain(kdc_object_t o)
+{
+    return heim_retain(o);
+}
+
+KDC_LIB_FUNCTION void KDC_LIB_CALL
+kdc_object_release(kdc_object_t o)
+{
+    heim_release(o);
+}
+
+KDC_LIB_FUNCTION kdc_object_t KDC_LIB_CALL
+kdc_bool_create(krb5_boolean v)
+{
+    return heim_bool_create(v);
+}
+
+KDC_LIB_FUNCTION krb5_boolean KDC_LIB_CALL
+kdc_bool_get_value(kdc_object_t o)
+{
+    return heim_bool_val(o);
+}
+
+struct kdc_array_iterator_trampoline_data {
+    kdc_array_iterator_t iter;
+    void *data;
+};
+
+/*
+ * Calling convention shim to avoid needing to update all internal
+ * consumers of heim_array_iterate_f()
+ */
+static void
+_kdc_array_iterator_trampoline(kdc_object_t o, void *data, int *stop)
+{
+    struct kdc_array_iterator_trampoline_data *t = data;
+
+    t->iter(o, t->data, stop);
+}
+
+KDC_LIB_FUNCTION void KDC_LIB_CALL
+kdc_array_iterate(kdc_array_t a, void *d, kdc_array_iterator_t iter)
+{
+    struct kdc_array_iterator_trampoline_data t;
+
+    t.iter = iter;
+    t.data = d;
+
+    heim_array_iterate_f((heim_array_t)a, &t, _kdc_array_iterator_trampoline);
+}
+
+KDC_LIB_FUNCTION size_t KDC_LIB_CALL
+kdc_array_get_length(kdc_array_t a)
+{
+    return heim_array_get_length((heim_array_t)a);
+}
+
+KDC_LIB_FUNCTION kdc_object_t KDC_LIB_CALL
+kdc_array_get_value(heim_array_t a, size_t i)
+{
+    return heim_array_get_value((heim_array_t)a, i);
+}
+
+KDC_LIB_FUNCTION kdc_object_t KDC_LIB_CALL
+kdc_array_copy_value(heim_array_t a, size_t i)
+{
+    return heim_array_copy_value((heim_array_t)a, i);
+}
+
+KDC_LIB_FUNCTION kdc_string_t KDC_LIB_CALL
+kdc_string_create(const char *s)
+{
+    return (kdc_string_t)heim_string_create(s);
+}
+
+KDC_LIB_FUNCTION const char * KDC_LIB_CALL
+kdc_string_get_utf8(kdc_string_t s)
+{
+    return heim_string_get_utf8((heim_string_t)s);
+}
+
+KDC_LIB_FUNCTION kdc_data_t
+kdc_data_create(const void *d, size_t len)
+{
+    return (kdc_data_t)heim_data_create(d, len);
+}
+
+KDC_LIB_FUNCTION const krb5_data * KDC_LIB_CALL
+kdc_data_get_data(kdc_data_t d)
+{
+    return heim_data_get_data((heim_data_t)d);
+}
+
+KDC_LIB_FUNCTION kdc_number_t KDC_LIB_CALL
+kdc_number_create(int64_t v)
+{
+    return (kdc_number_t)heim_number_create(v);
+}
+
+KDC_LIB_FUNCTION int64_t KDC_LIB_CALL
+kdc_number_get_value(kdc_number_t n)
+{
+    return heim_number_get_long((heim_number_t)n);
+}
+
+/*
+ * Plugin accessors
+ */
+
+KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL
+kdc_request_add_reply_padata(astgs_request_t r, PA_DATA *md)
+{
+    heim_assert(r->rep.padata != NULL, "reply padata not allocated");
+    return add_METHOD_DATA(r->rep.padata, md);
+}
+
+KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL
+kdc_request_add_encrypted_padata(astgs_request_t r, PA_DATA *md)
+{
+    if (r->ek.encrypted_pa_data == NULL) {
+       r->ek.encrypted_pa_data = calloc(1, sizeof *(r->ek.encrypted_pa_data));
+       if (r->ek.encrypted_pa_data == NULL) {
+           return ENOMEM;
+       }
+    }
+
+    return add_METHOD_DATA(r->ek.encrypted_pa_data, md);
+}
+
+KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL
+kdc_request_add_pac_buffer(astgs_request_t r,
+                          uint32_t pactype,
+                          const krb5_data *d)
+{
+    krb5_error_code ret;
+    krb5_pac pac;
+
+    if (r->pac == NULL) {
+       ret = krb5_pac_init(r->context, &pac);
+       if (ret)
+           return ret;
+    } else
+       pac = heim_retain(r->pac);
+
+    ret = krb5_pac_add_buffer(r->context, pac, pactype, d);
+    if (ret == 0 && r->pac == NULL)
+       r->pac = pac;
+    else
+       heim_release(pac);
+
+    return ret;
+}
+
+#undef _KDC_REQUEST_GET_ACCESSOR
+#define _KDC_REQUEST_GET_ACCESSOR(R, T, f)                 \
+    KDC_LIB_FUNCTION T KDC_LIB_CALL                        \
+    kdc_request_get_ ## f(R r)                             \
+    {                                                      \
+       return r->f;                                        \
+    }
+
+#undef _KDC_REQUEST_SET_ACCESSOR
+#define _KDC_REQUEST_SET_ACCESSOR(R, T, f)                 \
+    KDC_LIB_FUNCTION void KDC_LIB_CALL                     \
+    kdc_request_set_ ## f(R r, T v)                        \
+    {                                                      \
+       r->f = v;                                           \
+    }
+
+#undef _KDC_REQUEST_GET_ACCESSOR_PTR
+#define _KDC_REQUEST_GET_ACCESSOR_PTR(R, T,  f)                    \
+    KDC_LIB_FUNCTION const T KDC_LIB_CALL                  \
+    kdc_request_get_ ## f(R r)                             \
+    {                                                      \
+       return r->f;                                        \
+    }
+
+#undef _KDC_REQUEST_SET_ACCESSOR_PTR
+#define _KDC_REQUEST_SET_ACCESSOR_PTR(R, T, t, f)          \
+    KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL          \
+    kdc_request_set_ ## f(R r, const T v)                  \
+    {                                                      \
+       krb5_error_code ret;                                \
+       T tmp;                                              \
+                                                           \
+       if (v == r->f)                                      \
+           return 0;                                       \
+       else if (v) {                                       \
+           ret = copy_##t(v, &tmp);                        \
+           if (ret)                                        \
+               return ret;                                 \
+       } else                                              \
+           tmp = NULL;                                     \
+                                                           \
+       free_##t(r->f);                                     \
+       r->f = tmp;                                         \
+                                                           \
+       return 0;                                           \
+    }
+
+#undef _KDC_REQUEST_GET_ACCESSOR_STRUCT
+#define _KDC_REQUEST_GET_ACCESSOR_STRUCT(R, T, f)          \
+    KDC_LIB_FUNCTION const T * KDC_LIB_CALL                \
+    kdc_request_get_ ## f(R r)                             \
+    {                                                      \
+       return &r->f;                                       \
+    }
+
+#undef _KDC_REQUEST_SET_ACCESSOR_STRUCT
+#define _KDC_REQUEST_SET_ACCESSOR_STRUCT(R, T, t, f)       \
+    KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL          \
+    kdc_request_set_ ## f(R r, const T *v)                 \
+    {                                                      \
+       krb5_error_code ret;                                \
+       T tmp;                                              \
+                                                           \
+       if (v == NULL)                                      \
+           return EINVAL;                                  \
+       else if (v == &r->f)                                \
+           return 0;                                       \
+                                                           \
+       ret = copy_##t(v, &tmp);                            \
+       if (ret)                                            \
+           return ret;                                     \
+                                                           \
+       free_##t(&r->f);                                    \
+       r->f = tmp;                                         \
+                                                           \
+       return 0;                                           \
+    }
+
+static krb5_error_code
+copy_string_ptr(const char *src, char **dst)
+{
+    *dst = strdup(src);
+    if (*dst == NULL)
+       return ENOMEM;
+
+    return 0;
+}
+
+static void
+free_string_ptr(char *s)
+{
+    free(s);
+}
+
+static krb5_error_code
+copy_Principal_ptr(krb5_const_principal src, krb5_principal *dst)
+{
+    krb5_error_code ret;
+    krb5_principal p;
+
+    *dst = NULL;
+
+    p = calloc(1, sizeof(*p));
+    if (p == NULL)
+       return ENOMEM;
+
+    ret = copy_Principal(src, p);
+    if (ret == 0)
+       *dst = p;
+    else
+       free(p);
+
+    return ret;
+}
+
+static void
+free_Principal_ptr(krb5_principal p)
+{
+    if (p) {
+       free_Principal(p);
+       free(p);
+    }
+}
+
+static krb5_error_code
+copy_pac(const struct krb5_pac_data *src, struct krb5_pac_data **dst)
+{
+    /* FIXME use heim_copy() when it exists */
+    *dst = (krb5_pac)heim_retain((heim_object_t)src);
+    return 0;
+}
+
+static void
+free_pac(struct krb5_pac_data *o)
+{
+    heim_release(o);
+}
+
+static krb5_error_code
+copy_keyblock(const EncryptionKey *src, EncryptionKey *dst)
+{
+    return copy_EncryptionKey(src, dst);
+}
+
+static void
+free_keyblock(EncryptionKey *key)
+{
+    krb5_free_keyblock_contents(NULL, key);
+}
+
+#undef HEIMDAL_KDC_KDC_ACCESSORS_H
+#include "kdc-accessors.h"
+
+#undef _KDC_REQUEST_GET_ACCESSOR
+#undef _KDC_REQUEST_SET_ACCESSOR
+
+#undef _KDC_REQUEST_GET_ACCESSOR_PTR
+#undef _KDC_REQUEST_SET_ACCESSOR_PTR
+#define _KDC_REQUEST_SET_ACCESSOR_PTR(R, T, t, f)          \
+    void                                                   \
+    _kdc_request_set_ ## f ## _nocopy(R r, T *v)           \
+    {                                                      \
+       if (*v != r->f) {                                   \
+           free_##t(r->f);                                 \
+           r->f = *v;                                      \
+       }                                                   \
+       *v = NULL;                                          \
+    }
+
+#undef _KDC_REQUEST_GET_ACCESSOR_STRUCT
+#undef _KDC_REQUEST_SET_ACCESSOR_STRUCT
+#define _KDC_REQUEST_SET_ACCESSOR_STRUCT(R, T, t, f)       \
+    void                                                   \
+    _kdc_request_set_ ## f ## _nocopy(R r, T *v)           \
+    {                                                      \
+       if (v != &r->f) {                                   \
+           free_##t(&r->f);                                \
+           r->f = *v;                                      \
+       }                                                   \
+       memset(v, 0, sizeof(*v));                           \
+    }
+
+#undef HEIMDAL_KDC_KDC_ACCESSORS_H
+#include "kdc-accessors.h"
diff --git a/third_party/heimdal/kdc/kdc-plugin.h b/third_party/heimdal/kdc/kdc-plugin.h
new file mode 100644 (file)
index 0000000..efe8dd6
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2006 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $Id$ */
+
+#ifndef HEIMDAL_KDC_KDC_PLUGIN_H
+#define HEIMDAL_KDC_KDC_PLUGIN_H 1
+
+#include <krb5.h>
+#include <kdc.h>
+#include <kdc-accessors.h>
+#include <hdb.h>
+
+/*
+ * Allocate a PAC for the given client with krb5_pac_init(),
+ * and fill its contents in with krb5_pac_add_buffer().
+ */
+
+typedef krb5_error_code
+(KRB5_CALLCONV *krb5plugin_kdc_pac_generate)(void *,
+                                            krb5_context, /* context */
+                                            krb5_kdc_configuration *, /* configuration */
+                                            hdb_entry *, /* client */
+                                            hdb_entry *, /* server */
+                                            const krb5_keyblock *, /* pk_replykey */
+                                            uint64_t,        /* pac_attributes */
+                                            krb5_pac *);
+
+/*
+ * Verify the PAC KDC signatures by fetching the appropriate TGS key
+ * and calling krb5_pac_verify() with that key. Optionally update the
+ * PAC buffers on success.
+ */
+
+typedef krb5_error_code
+(KRB5_CALLCONV *krb5plugin_kdc_pac_verify)(void *,
+                                          krb5_context, /* context */
+                                          krb5_kdc_configuration *, /* configuration */
+                                          const krb5_principal, /* new ticket client */
+                                          const krb5_principal, /* delegation proxy */
+                                          hdb_entry *,/* client */
+                                          hdb_entry *,/* server */
+                                          hdb_entry *,/* krbtgt */
+                                          krb5_pac *);
+
+/*
+ * Authorize the client principal's access to the Authentication Service (AS).
+ * This function is called after any pre-authentication has completed.
+ */
+
+typedef krb5_error_code
+(KRB5_CALLCONV *krb5plugin_kdc_client_access)(void *, astgs_request_t);
+
+/*
+ * A referral policy plugin can either rewrite the server principal
+ * by resetting priv->server_princ, or it can disable referral
+ * processing entirely by returning an error.
+ *
+ * The error code from the previous server lookup is available as r->ret.
+ *
+ * If the function returns KRB5_PLUGIN_NO_HANDLE, the TGS will continue
+ * with its default referral handling.
+ *
+ * Note well: the plugin should free priv->server_princ is replacing.
+ */
+
+typedef krb5_error_code
+(KRB5_CALLCONV *krb5plugin_kdc_referral_policy)(void *, astgs_request_t);
+
+/*
+ * Update the AS or TGS reply immediately prior to encoding.
+ */
+
+typedef krb5_error_code
+(KRB5_CALLCONV *krb5plugin_kdc_finalize_reply)(void *, astgs_request_t);
+
+/*
+ * Audit an AS or TGS request. This function is called after encoding the
+ * reply (on success), or before encoding the error message. If a HDB audit
+ * function is also present, it is called after this one.
+ *
+ * The request should not be modified by the plugin.
+ */
+
+typedef krb5_error_code
+(KRB5_CALLCONV *krb5plugin_kdc_audit)(void *, astgs_request_t);
+
+/*
+ * Plugins should carefully check API contract notes for changes
+ * between plugin API versions.
+ */
+#define KRB5_PLUGIN_KDC_VERSION_10     10
+
+typedef struct krb5plugin_kdc_ftable {
+    int                        minor_version;
+    krb5_error_code    (KRB5_CALLCONV *init)(krb5_context, void **);
+    void               (KRB5_CALLCONV *fini)(void *);
+    krb5plugin_kdc_pac_generate                pac_generate;
+    krb5plugin_kdc_pac_verify          pac_verify;
+    krb5plugin_kdc_client_access       client_access;
+    krb5plugin_kdc_referral_policy     referral_policy;
+    krb5plugin_kdc_finalize_reply      finalize_reply;
+    krb5plugin_kdc_audit               audit;
+} krb5plugin_kdc_ftable;
+
+#endif /* HEIMDAL_KDC_KDC_PLUGIN_H */
index af4e55c356d9d60fda0cab30907aa7989f92f802..29190f7837f8b8a8506f2b48793041f04aea7d85 100644 (file)
@@ -184,6 +184,8 @@ main(int argc, char **argv)
            unsigned int tag2;
            ret = der_get_tag (r.data, r.length,
                               &cl, &ty, &tag2, NULL);
+            if (ret)
+                krb5_err(context, 1, ret, "Could not decode replay data");
            if (MAKE_TAG(cl, ty, 0) != clty)
                krb5_errx(context, 1, "class|type mismatch: %d != %d",
                          (int)MAKE_TAG(cl, ty, 0), (int)clty);
index cbf4f51173824b8da5fbc2baacd5b4989b7ea7b6..e3709ada6b0a2922efca87975b38bf7d581af767 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997-2003 Kungliga Tekniska Högskolan
+ * Copyright (c) 1997-2022 Kungliga Tekniska Högskolan
  * (Royal Institute of Technology, Stockholm, Sweden).
  *
  * Copyright (c) 2005 Andrew Bartlett <abartlet@samba.org>
 #include <kx509_asn1.h>
 #include <gssapi/gssapi.h>
 
-#define heim_pcontext krb5_context
-#define heim_pconfig krb5_kdc_configuration *
-#include <heimbase-svc.h>
-
 enum krb5_kdc_trpolicy {
     TRPOLICY_ALWAYS_CHECK,
     TRPOLICY_ALLOW_PER_PRINCIPAL,
     TRPOLICY_ALWAYS_HONOUR_REQUEST
 };
 
-typedef struct krb5_kdc_configuration {
-    krb5_boolean require_preauth; /* require preauth for all principals */
-    time_t kdc_warn_pwexpire; /* time before expiration to print a warning */
-
-    struct HDB **db;
-    int num_db;
-
-    int num_kdc_processes;
-
-    krb5_boolean encode_as_rep_as_tgs_rep; /* bug compatibility */
-
-    /*
-     * Windows 2019 (and earlier versions) always sends the salt
-     * and Samba has testsuites that check this behaviour, so a
-     * Samba AD DC will set this flag to match the AS-REP packet
-     * exactly.
-     */
-    krb5_boolean force_include_pa_etype_salt;
-
-    krb5_boolean tgt_use_strongest_session_key;
-    krb5_boolean preauth_use_strongest_session_key;
-    krb5_boolean svc_use_strongest_session_key;
-    krb5_boolean use_strongest_server_key;
-
-    krb5_boolean check_ticket_addresses;
-    krb5_boolean warn_ticket_addresses;
-    krb5_boolean allow_null_ticket_addresses;
-    krb5_boolean allow_anonymous;
-    krb5_boolean historical_anon_realm;
-    krb5_boolean strict_nametypes;
-    enum krb5_kdc_trpolicy trpolicy;
-
-    krb5_boolean require_pac;
-    krb5_boolean enable_armored_pa_enc_timestamp;
-    krb5_boolean enable_unarmored_pa_enc_timestamp;
-
-    krb5_boolean autodetect_referrals;
-
-    krb5_boolean enable_pkinit;
-    krb5_boolean pkinit_princ_in_cert;
-    const char *pkinit_kdc_identity;
-    const char *pkinit_kdc_anchors;
-    const char *pkinit_kdc_friendly_name;
-    const char *pkinit_kdc_ocsp_file;
-    char **pkinit_kdc_cert_pool;
-    char **pkinit_kdc_revoke;
-    int pkinit_dh_min_bits;
-    /* XXX Turn these into bit-fields */
-    int pkinit_require_binding;
-    int pkinit_allow_proxy_certs;
-    int synthetic_clients;
-    int pkinit_max_life_from_cert_extension;
-    krb5_timestamp pkinit_max_life_from_cert;
-    krb5_timestamp pkinit_max_life_bound;
-    krb5_timestamp synthetic_clients_max_life;
-    krb5_timestamp synthetic_clients_max_renew;
-
-    krb5_log_facility *logf;
-
-    int enable_digest;
-    int digests_allowed;
-
-    int enable_gss_preauth;
-    int enable_gss_auth_data;
-    gss_OID_set gss_mechanisms_allowed;
-    gss_OID_set gss_cross_realm_mechanisms_allowed;
-
-    size_t max_datagram_reply_length;
-
-    int enable_kx509;
-
-    const char *app;
-} krb5_kdc_configuration;
-
-#define ASTGS_REQUEST_DESC_COMMON_ELEMENTS                     \
-    HEIM_SVC_REQUEST_DESC_COMMON_ELEMENTS;                     \
-                                                               \
-    KDC_REQ req;                                               \
-                                                               \
-    KDC_REP rep;                                               \
-    EncTicketPart et;                                          \
-    EncKDCRepPart ek;                                          \
-                                                               \
-    /* princ requested by client (AS) or canon princ (TGT) */  \
-    krb5_principal client_princ;                               \
-    hdb_entry_ex *client;                                      \
-    HDB *clientdb;                                             \
-                                                               \
-    krb5_principal server_princ;                               \
-    hdb_entry_ex *server;                                      \
-                                                               \
-    krb5_keyblock reply_key;                                   \
-                                                               \
-    krb5_pac pac;                                              \
-    uint64_t pac_attributes;
+struct krb5_kdc_configuration;
+typedef struct krb5_kdc_configuration krb5_kdc_configuration;
 
-#ifndef __KDC_LOCL_H__
-struct astgs_request_desc {
-    ASTGS_REQUEST_DESC_COMMON_ELEMENTS
-};
-#endif
+/*
+ * Access to request fields by plugins and other out-of-tree
+ * consumers should be via the functions in kdc-accessors.h.
+ */
 
+struct kdc_request_desc;
 typedef struct kdc_request_desc *kdc_request_t;
+
+struct astgs_request_desc;
 typedef struct astgs_request_desc *astgs_request_t;
+
+struct kx509_req_context_desc;
 typedef struct kx509_req_context_desc *kx509_req_context;
 
 struct krb5_kdc_service {
@@ -170,9 +77,54 @@ struct krb5_kdc_service {
     krb5_error_code (*process)(kdc_request_t *, int *claim);
 };
 
-#include <kdc-protos.h>
+/*
+ * The following fields are guaranteed stable within a major
+ * release of Heimdal and can be manipulated by applications
+ * that manage KDC requests themselves using libkdc.
+ *
+ * Applications can make custom KDC configuration available
+ * to libkdc by using krb5_set_config().
+ */
 
-#undef heim_pcontext
-#undef heim_pconfig
+#define KRB5_KDC_CONFIGURATION_COMMON_ELEMENTS                 \
+    krb5_log_facility *logf;                                   \
+    struct HDB **db;                                           \
+    size_t num_db;                                             \
+    const char *app;                                           \
+                                                               \
+    /*                                                         \
+     * Windows 2019 (and earlier versions) always sends the salt\
+     * and Samba has testsuites that check this behaviour, so a \
+     * Samba AD DC will set this flag to match the AS-REP packet\
+     * exactly.                                                \
+     */                                                        \
+    unsigned int force_include_pa_etype_salt : 1;              \
+                                                               \
+    unsigned int tgt_use_strongest_session_key : 1;            \
+    unsigned int preauth_use_strongest_session_key : 1;        \
+    unsigned int svc_use_strongest_session_key : 1;            \
+    unsigned int use_strongest_server_key : 1;                 \
+                                                               \
+    unsigned int require_pac : 1;                              \
+    unsigned int enable_armored_pa_enc_timestamp : 1
 
+#ifndef __KDC_LOCL_H__
+struct krb5_kdc_configuration {
+    KRB5_KDC_CONFIGURATION_COMMON_ELEMENTS;
+};
 #endif
+
+typedef void *kdc_object_t;
+typedef struct kdc_array_data *kdc_array_t;
+typedef struct kdc_dict_data *kdc_dict_t;
+typedef struct kdc_string_data *kdc_string_t;
+typedef struct kdc_data_data *kdc_data_t;
+typedef struct kdc_number_data *kdc_number_t;
+
+typedef void (KRB5_CALLCONV *kdc_array_iterator_t)(kdc_object_t, void *, int *);
+
+typedef void (KRB5_CALLCONV *kdc_type_dealloc)(kdc_object_t);
+
+#include <kdc-protos.h>
+
+#endif /* __KDC_H__ */
index e7b86151def0099b4d0d847bf8042369d04f06c6..8418a91a0a4bc91e34f785a70d2e747c62614530 100644 (file)
@@ -64,15 +64,95 @@ struct kdc_request_desc {
     HEIM_SVC_REQUEST_DESC_COMMON_ELEMENTS;
 };
 
-struct as_request_pa_state;
 struct kdc_patypes;
 
+struct krb5_kdc_configuration {
+    KRB5_KDC_CONFIGURATION_COMMON_ELEMENTS;
+
+    int num_kdc_processes;
+
+    size_t max_datagram_reply_length;
+
+    time_t kdc_warn_pwexpire; /* time before expiration to print a warning */
+
+    unsigned int require_preauth : 1; /* require preauth for all principals */
+    unsigned int encode_as_rep_as_tgs_rep : 1; /* bug compatibility */
+
+    unsigned int check_ticket_addresses : 1;
+    unsigned int warn_ticket_addresses : 1;
+    unsigned int allow_null_ticket_addresses : 1;
+    unsigned int allow_anonymous : 1;
+    unsigned int historical_anon_realm : 1;
+    unsigned int strict_nametypes : 1;
+    enum krb5_kdc_trpolicy trpolicy;
+
+    unsigned int enable_unarmored_pa_enc_timestamp : 1;
+
+    unsigned int enable_pkinit : 1;
+    unsigned int pkinit_princ_in_cert : 1;
+    const char *pkinit_kdc_identity;
+    const char *pkinit_kdc_anchors;
+    const char *pkinit_kdc_friendly_name;
+    const char *pkinit_kdc_ocsp_file;
+    char **pkinit_kdc_cert_pool;
+    char **pkinit_kdc_revoke;
+    int pkinit_dh_min_bits;
+    unsigned int pkinit_require_binding : 1;
+    unsigned int pkinit_allow_proxy_certs : 1;
+    unsigned int synthetic_clients : 1;
+    unsigned int pkinit_max_life_from_cert_extension : 1;
+    krb5_timestamp pkinit_max_life_from_cert;
+    krb5_timestamp pkinit_max_life_bound;
+    krb5_timestamp synthetic_clients_max_life;
+    krb5_timestamp synthetic_clients_max_renew;
+
+    int digests_allowed;
+    unsigned int enable_digest : 1;
+
+    unsigned int enable_kx509 : 1;
+
+    unsigned int enable_gss_preauth : 1;
+    unsigned int enable_gss_auth_data : 1;
+    gss_OID_set gss_mechanisms_allowed;
+    gss_OID_set gss_cross_realm_mechanisms_allowed;
+
+};
+
 struct astgs_request_desc {
-    ASTGS_REQUEST_DESC_COMMON_ELEMENTS;
+    HEIM_SVC_REQUEST_DESC_COMMON_ELEMENTS;
+
+    /* AS-REQ or TGS-REQ */
+    KDC_REQ req;
+
+    /* AS-REP or TGS-REP */
+    KDC_REP rep;
+    EncTicketPart et;
+    EncKDCRepPart ek;
+
+    /* client principal (AS) or TGT/S4U principal (TGS) */
+    krb5_principal client_princ;
+    hdb_entry *client;
+    HDB *clientdb;
+    krb5_principal canon_client_princ;
+
+    /* server principal */
+    krb5_principal server_princ;
+    HDB *serverdb;
+    hdb_entry *server;
+
+    /* presented ticket in TGS-REQ (unused by AS) */
+    krb5_principal krbtgt_princ;
+    hdb_entry *krbtgt;
+    HDB *krbtgtdb;
+    krb5_ticket *ticket;
+
+    krb5_keyblock reply_key;
+
+    krb5_pac pac;
+    uint64_t pac_attributes;
 
     /* Only AS */
     const struct kdc_patypes *pa_used;
-    struct as_request_pa_state *pa_state;
 
     /* PA methods can affect both the reply key and the session key (pkinit) */
     krb5_enctype sessionetype;
@@ -89,7 +169,8 @@ struct astgs_request_desc {
     unsigned int fast_asserted : 1;
 
     krb5_crypto armor_crypto;
-    hdb_entry_ex *armor_server;
+    hdb_entry *armor_server;
+    HDB *armor_serverdb;
     krb5_ticket *armor_ticket;
     Key *armor_key;
 
@@ -148,4 +229,24 @@ configure(krb5_context context, int argc, char **argv, int *optidx);
 void bonjour_announce(krb5_context, krb5_kdc_configuration *);
 #endif
 
+/* no-copy setters */
+
+#undef _KDC_REQUEST_GET_ACCESSOR
+#undef _KDC_REQUEST_SET_ACCESSOR
+
+#undef _KDC_REQUEST_GET_ACCESSOR_PTR
+#undef _KDC_REQUEST_SET_ACCESSOR_PTR
+#define _KDC_REQUEST_SET_ACCESSOR_PTR(R, T, t, f)          \
+    void                                                   \
+    _kdc_request_set_ ## f ## _nocopy(R r, T *v);
+
+#undef _KDC_REQUEST_GET_ACCESSOR_STRUCT
+#undef _KDC_REQUEST_SET_ACCESSOR_STRUCT
+#define _KDC_REQUEST_SET_ACCESSOR_STRUCT(R, T, t, f)       \
+    void                                                   \
+    _kdc_request_set_ ## f ## _nocopy(R r, T *v);
+
+#undef HEIMDAL_KDC_KDC_ACCESSORS_H
+#include "kdc-accessors.h"
+
 #endif /* __KDC_LOCL_H__ */
index ee7e56c5f27d37a9f05f391c514c82b5502fd2b1..b30d321f6f149cd8e77dde81e0f6b2a59fecaab7 100644 (file)
 
 #include "kdc_locl.h"
 
-#define MAX_TIME ((time_t)((1U << 31) - 1))
+#ifdef TIME_T_SIGNED
+#if SIZEOF_TIME_T == 4
+#define MAX_TIME ((time_t)INT32_MAX)
+#elif SIZEOF_TIME_T == 8
+#define MAX_TIME ((time_t)INT64_MAX)
+#else
+#error "Unexpected sizeof(time_t)"
+#endif
+#else
+
+#if SIZEOF_TIME_T == 4
+#define MAX_TIME ((time_t)UINT32_MAX)
+#else
+#define MAX_TIME ((time_t)UINT64_MAX)
+#endif
+#endif
 
 #undef __attribute__
 #define __attribute__(X)
 
-struct kdc_pa_auth_status {
-    int auth_status;
-    const char *auth_details;
-    void *free_ptr;
-};
-
-static krb5_error_code
-_kdc_audit_auth_status(astgs_request_t r,
-                      struct kdc_pa_auth_status *status,
-                      const char *pa_type)
-{
-    struct HDB *hdb;
-    krb5_error_code ret = 0;
-
-    if (r->clientdb)
-       hdb = r->clientdb;
-    else
-       hdb = r->config->db[0];
-
-    if (hdb && hdb->hdb_auth_status)
-       ret = hdb->hdb_auth_status(r->context,
-                                  hdb,
-                                  r->client,
-                                  &r->tv_start,
-                                  r->addr,
-                                  r->cname,
-                                  status->auth_status,
-                                  status->auth_details,
-                                  pa_type);
-
-    return ret;
-}
-
 void
 _kdc_fix_time(time_t **t)
 {
@@ -104,10 +86,10 @@ set_salt_padata(krb5_context context,
                 krb5_kdc_configuration *config,
                 METHOD_DATA *md, Key *key)
 {
-    if (key->salt)
-       return get_pa_etype_info2(context, config, md, key, TRUE);
+    if (!key->salt)
+        return 0;
 
-    return 0;
+    return get_pa_etype_info2(context, config, md, key, TRUE);
 }
 
 const PA_DATA*
@@ -134,9 +116,9 @@ _kdc_is_weak_exception(krb5_principal principal, krb5_enctype etype)
 {
     if (principal->name.name_string.len > 0 &&
        strcmp(principal->name.name_string.val[0], "afs") == 0 &&
-       (etype == (krb5_enctype)ETYPE_DES_CBC_CRC
-        || etype == (krb5_enctype)ETYPE_DES_CBC_MD4
-        || etype == (krb5_enctype)ETYPE_DES_CBC_MD5))
+       (etype == ETYPE_DES_CBC_CRC
+        || etype == ETYPE_DES_CBC_MD4
+        || etype == ETYPE_DES_CBC_MD5))
        return TRUE;
     return FALSE;
 }
@@ -153,7 +135,7 @@ is_default_salt_p(const krb5_salt *default_salt, const Key *key)
        return TRUE;
     if (default_salt->salttype != key->salt->type)
        return FALSE;
-    if (krb5_data_cmp(&default_salt->saltvalue, &key->salt->salt))
+    if (krb5_data_cmp(&default_salt->saltvalue, &key->salt->salt) != 0)
        return FALSE;
     return TRUE;
 }
@@ -170,11 +152,11 @@ is_default_salt_p(const krb5_salt *default_salt, const Key *key)
 static krb5_boolean
 is_good_salt_p(const krb5_salt *default_salt, const Key *key)
 {
-    if (key->key.keytype != (krb5_enctype)ETYPE_DES_CBC_CRC)
-       return TRUE;
-    return is_default_salt_p(default_salt, key);
-}
+    if (key->key.keytype == KRB5_ENCTYPE_DES_CBC_CRC)
+       return is_default_salt_p(default_salt, key);
 
+    return TRUE;
+}
 
 krb5_boolean
 _kdc_is_anon_request(const KDC_REQ *req)
@@ -217,25 +199,25 @@ _kdc_find_etype(astgs_request_t r, uint32_t flags,
     krb5_boolean use_strongest_session_key;
     krb5_boolean is_preauth = flags & KFE_IS_PREAUTH;
     krb5_boolean is_tgs = flags & KFE_IS_TGS;
-    hdb_entry_ex *princ;
+    hdb_entry *princ;
     krb5_principal request_princ;
     krb5_error_code ret;
     krb5_salt def_salt;
-    krb5_enctype enctype = (krb5_enctype)ETYPE_NULL;
+    krb5_enctype enctype = ETYPE_NULL;
     const krb5_enctype *p;
     Key *key = NULL;
     size_t i, k, m;
 
     if (is_preauth && (flags & KFE_USE_CLIENT) &&
-        r->client->entry.flags.synthetic)
+        r->client->flags.synthetic)
         return KRB5KDC_ERR_ETYPE_NOSUPP;
 
-    if ((flags & KFE_USE_CLIENT) && !r->client->entry.flags.synthetic) {
+    if ((flags & KFE_USE_CLIENT) && !r->client->flags.synthetic) {
        princ = r->client;
        request_princ = r->client_princ;
     } else {
        princ = r->server;
-       request_princ = r->server->entry.principal;
+       request_princ = r->server->principal;
     }
 
     use_strongest_session_key =
@@ -280,14 +262,14 @@ _kdc_find_etype(astgs_request_t r, uint32_t flags,
        /* drive the search with local supported enctypes list */
        p = krb5_kerberos_enctypes(r->context);
        for (i = 0;
-           p[i] != (krb5_enctype)ETYPE_NULL && enctype == (krb5_enctype)ETYPE_NULL;
+           p[i] != ETYPE_NULL && enctype == ETYPE_NULL;
            i++) {
            if (krb5_enctype_valid(r->context, p[i]) != 0 &&
-                !_kdc_is_weak_exception(princ->entry.principal, p[i]))
+                !_kdc_is_weak_exception(princ->principal, p[i]))
                continue;
 
            /* check that the client supports it too */
-           for (k = 0; k < len && enctype == (krb5_enctype)ETYPE_NULL; k++) {
+           for (k = 0; k < len && enctype == ETYPE_NULL; k++) {
 
                if (p[i] != etypes[k])
                    continue;
@@ -304,15 +286,15 @@ _kdc_find_etype(astgs_request_t r, uint32_t flags,
 
                 /* check target princ support */
                key = NULL;
-                if (!(flags & KFE_USE_CLIENT) && princ->entry.etypes) {
+                if (!is_preauth && !(flags & KFE_USE_CLIENT) && princ->etypes) {
                     /*
                      * Use the etypes list from the server's HDB entry instead
                      * of deriving it from its long-term keys.  This allows an
                      * entry to have just one long-term key but record support
                      * for multiple enctypes.
                      */
-                    for (m = 0; m < princ->entry.etypes->len; m++) {
-                        if (p[i] == princ->entry.etypes->val[m]) {
+                    for (m = 0; m < princ->etypes->len; m++) {
+                        if (p[i] == princ->etypes->val[m]) {
                             ret = 0;
                             break;
                         }
@@ -324,7 +306,7 @@ _kdc_find_etype(astgs_request_t r, uint32_t flags,
                      * PA-ETYPE-INFO* or because we're selecting a session key
                      * enctype.
                      */
-                    while (hdb_next_enctype2key(r->context, &princ->entry, NULL,
+                    while (hdb_next_enctype2key(r->context, princ, NULL,
                                                  p[i], &key) == 0) {
                         if (key->key.keyvalue.length == 0) {
                             ret = KRB5KDC_ERR_NULL_KEY;
@@ -352,12 +334,12 @@ _kdc_find_etype(astgs_request_t r, uint32_t flags,
        for(i = 0; ret != 0 && i < len; i++) {
 
            if (krb5_enctype_valid(r->context, etypes[i]) != 0 &&
-               !_kdc_is_weak_exception(princ->entry.principal, etypes[i]))
+               !_kdc_is_weak_exception(princ->principal, etypes[i]))
                continue;
 
            key = NULL;
            while (ret != 0 &&
-                   hdb_next_enctype2key(r->context, &princ->entry, NULL,
+                   hdb_next_enctype2key(r->context, princ, NULL,
                                        etypes[i], &key) == 0) {
                if (key->key.keyvalue.length == 0) {
                    ret = KRB5KDC_ERR_NULL_KEY;
@@ -372,14 +354,14 @@ _kdc_find_etype(astgs_request_t r, uint32_t flags,
        }
     }
 
-    if (enctype == (krb5_enctype)ETYPE_NULL) {
+    if (ret == 0 && enctype == ETYPE_NULL) {
         /*
          * if the service principal is one for which there is a known 1DES
          * exception and no other enctype matches both the client request and
          * the service key list, provide a DES-CBC-CRC key.
          */
        if (ret_key == NULL &&
-           _kdc_is_weak_exception(princ->entry.principal, ETYPE_DES_CBC_CRC)) {
+           _kdc_is_weak_exception(princ->principal, ETYPE_DES_CBC_CRC)) {
             ret = 0;
             enctype = ETYPE_DES_CBC_CRC;
         } else {
@@ -498,15 +480,13 @@ _kdc_log_timestamp(astgs_request_t r, const char *type,
        endtime_str[100], renewtime_str[100];
 
     if (authtime)
-       _kdc_audit_addkv((kdc_request_t)r, 0, "auth", "%ld", (long)authtime);
+       kdc_audit_setkv_number((kdc_request_t)r, "auth", authtime);
     if (starttime && *starttime)
-       _kdc_audit_addkv((kdc_request_t)r, 0, "start", "%ld",
-                        (long)*starttime);
+       kdc_audit_setkv_number((kdc_request_t)r, "start", *starttime);
     if (endtime)
-       _kdc_audit_addkv((kdc_request_t)r, 0, "end", "%ld", (long)endtime);
+       kdc_audit_setkv_number((kdc_request_t)r, "end", endtime);
     if (renew_till && *renew_till)
-       _kdc_audit_addkv((kdc_request_t)r, 0, "renew", "%ld",
-                        (long)*renew_till);
+       kdc_audit_setkv_number((kdc_request_t)r, "renew", *renew_till);
 
     krb5_format_time(r->context, authtime,
                     authtime_str, sizeof(authtime_str), TRUE);
@@ -535,9 +515,7 @@ _kdc_log_timestamp(astgs_request_t r, const char *type,
 #ifdef PKINIT
 
 static krb5_error_code
-pa_pkinit_validate(astgs_request_t r,
-                  const PA_DATA *pa,
-                  struct kdc_pa_auth_status *auth_status)
+pa_pkinit_validate(astgs_request_t r, const PA_DATA *pa)
 {
     pk_client_params *pkp = NULL;
     char *client_cert = NULL;
@@ -548,22 +526,23 @@ pa_pkinit_validate(astgs_request_t r,
        ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
        _kdc_r_log(r, 4, "Failed to decode PKINIT PA-DATA -- %s",
                   r->cname);
-       auth_status->auth_status = HDB_AUTHSTATUS_PKINIT_FAILURE;
        goto out;
     }
 
     ret = _kdc_pk_check_client(r, pkp, &client_cert);
+    if (client_cert)
+       kdc_audit_addkv((kdc_request_t)r, 0, KDC_REQUEST_KV_PKINIT_CLIENT_CERT,
+                       "%s", client_cert);
     if (ret) {
        _kdc_set_e_text(r, "PKINIT certificate not allowed to "
                        "impersonate principal");
-       auth_status->auth_status = HDB_AUTHSTATUS_PKINIT_FAILURE;
+       kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
+                              KDC_AUTH_EVENT_CLIENT_NAME_UNAUTHORIZED);
        goto out;
     }
-    auth_status->auth_details = client_cert;
-    auth_status->free_ptr = client_cert;
 
     r->pa_endtime = _kdc_pk_endtime(pkp);
-    if (!r->client->entry.flags.synthetic)
+    if (!r->client->flags.synthetic)
         r->pa_max_life = _kdc_pk_max_life(pkp);
 
     _kdc_r_log(r, 4, "PKINIT pre-authentication succeeded -- %s using %s",
@@ -577,10 +556,13 @@ pa_pkinit_validate(astgs_request_t r,
     ret = _kdc_add_initial_verified_cas(r->context, r->config,
                                        pkp, &r->et);
 
-    auth_status->auth_status = HDB_AUTHSTATUS_PKINIT_SUCCESS;
+    kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
+                          KDC_AUTH_EVENT_PREAUTH_SUCCEEDED);
+
  out:
     if (pkp)
        _kdc_pk_free_client_param(r->context, pkp);
+    free(client_cert);
 
     return ret;
 }
@@ -588,9 +570,7 @@ pa_pkinit_validate(astgs_request_t r,
 #endif /* PKINIT */
 
 static krb5_error_code
-pa_gss_validate(astgs_request_t r,
-               const PA_DATA *pa,
-               struct kdc_pa_auth_status *auth_status)
+pa_gss_validate(astgs_request_t r, const PA_DATA *pa)
 {
     gss_client_params *gcp = NULL;
     char *client_name = NULL;
@@ -603,19 +583,23 @@ pa_gss_validate(astgs_request_t r,
 
     if (open) {
        ret = _kdc_gss_check_client(r, gcp, &client_name);
+       if (client_name)
+           kdc_audit_addkv((kdc_request_t)r, 0, KDC_REQUEST_KV_GSS_INITIATOR,
+                           "%s", client_name);
        if (ret) {
            _kdc_set_e_text(r, "GSS-API client not allowed to "
                            "impersonate principal");
-           auth_status->auth_status = HDB_AUTHSTATUS_GSS_FAILURE;
+           kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
+                                  KDC_AUTH_EVENT_CLIENT_NAME_UNAUTHORIZED);
            goto out;
        }
-       auth_status->auth_details = client_name;
-       auth_status->free_ptr = client_name;
 
        r->pa_endtime = _kdc_gss_endtime(r, gcp);
 
        _kdc_r_log(r, 4, "GSS pre-authentication succeeded -- %s using %s",
                   r->cname, client_name);
+       kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
+                              KDC_AUTH_EVENT_PREAUTH_SUCCEEDED);
 
        ret = _kdc_gss_mk_composite_name_ad(r, gcp);
        if (ret) {
@@ -628,19 +612,17 @@ pa_gss_validate(astgs_request_t r,
     if (ret) {
        if (ret != KRB5_KDC_ERR_MORE_PREAUTH_DATA_REQUIRED)
            _kdc_set_e_text(r, "Failed to build GSS pre-authentication reply");
-
        goto out;
     }
 
-    auth_status->auth_status = HDB_AUTHSTATUS_GSS_SUCCESS;
-
-    heim_assert(r->pa_state == NULL, "already have PA state, should be NULL");
-    r->pa_state = (struct as_request_pa_state *)gcp;
-    gcp = NULL;
+    ret = kdc_request_set_attribute((kdc_request_t)r,
+                                   HSTR("org.h5l.pa-gss-client-params"), gcp);
+    if (ret)
+       goto out;
 
 out:
-    if (gcp)
-       _kdc_gss_free_client_param(r, gcp);
+    kdc_object_release(gcp);
+    free(client_name);
 
     return ret;
 }
@@ -648,28 +630,17 @@ out:
 static krb5_error_code
 pa_gss_finalize_pac(astgs_request_t r)
 {
-    gss_client_params *gcp = (gss_client_params *)r->pa_state;
+    gss_client_params *gcp;
+
+    gcp = kdc_request_get_attribute((kdc_request_t)r, HSTR("org.h5l.pa-gss-client-params"));
 
     heim_assert(gcp != NULL, "invalid GSS-API client params");
 
     return _kdc_gss_finalize_pac(r, gcp);
 }
 
-static void
-pa_gss_cleanup(astgs_request_t r)
-{
-    gss_client_params *gcp = (gss_client_params *)r->pa_state;
-
-    if (gcp) {
-       _kdc_gss_free_client_param(r, gcp);
-       r->pa_state = NULL;
-    }
-}
-
 static krb5_error_code
-pa_enc_chal_validate(astgs_request_t r,
-                    const PA_DATA *pa,
-                    struct kdc_pa_auth_status *auth_status)
+pa_enc_chal_validate(astgs_request_t r, const PA_DATA *pa)
 {
     krb5_data pepper1, pepper2;
     int invalidPassword = 0;
@@ -688,11 +659,12 @@ pa_enc_chal_validate(astgs_request_t r,
        return ret;
     }
 
-    if (r->client->entry.flags.locked_out) {
+    if (r->client->flags.locked_out) {
        ret = KRB5KDC_ERR_CLIENT_REVOKED;
        kdc_log(r->context, r->config, 0,
                "Client (%s) is locked out", r->cname);
-       auth_status->auth_status = HDB_AUTHSTATUS_CLIENT_LOCKED_OUT;
+       kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
+                             KDC_AUTH_EVENT_CLIENT_LOCKED_OUT);
        return ret;
     }
 
@@ -716,11 +688,11 @@ pa_enc_chal_validate(astgs_request_t r,
 
     kdc_log(r->context, r->config, 5, "FAST armor enctype is: %d", (int)aenctype);
 
-    for (i = 0; i < r->client->entry.keys.len; i++) {
+    for (i = 0; i < r->client->keys.len; i++) {
        krb5_crypto challengecrypto, longtermcrypto;
        krb5_keyblock challengekey;
 
-       k = &r->client->entry.keys.val[i];
+       k = &r->client->keys.val[i];
        
        ret = krb5_crypto_init(r->context, &k->key, 0, &longtermcrypto);
        if (ret)
@@ -813,20 +785,21 @@ pa_enc_chal_validate(astgs_request_t r,
        if (ret)
            goto out;
                                            
-       ret = set_salt_padata(r->context, r->config,
-                             r->rep.padata, k);
-       if (ret)
-           goto out;
+        if (ret == 0)
+            ret = set_salt_padata(r->context, r->config,
+                                 r->rep.padata, k);
 
        /*
         * Success
         */
-       auth_status->auth_status = HDB_AUTHSTATUS_CORRECT_PASSWORD;
+       kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
+                              KDC_AUTH_EVENT_VALIDATED_LONG_TERM_KEY);
        goto out;
     }
 
     if (invalidPassword) {
-       auth_status->auth_status = HDB_AUTHSTATUS_WRONG_PASSWORD;
+       kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
+                              KDC_AUTH_EVENT_WRONG_LONG_TERM_KEY);
        ret = KRB5KDC_ERR_PREAUTH_FAILED;
     } else {
        ret = KRB5KDC_ERR_ETYPE_NOSUPP;
@@ -838,9 +811,7 @@ pa_enc_chal_validate(astgs_request_t r,
 }
 
 static krb5_error_code
-pa_enc_ts_validate(astgs_request_t r,
-                  const PA_DATA *pa,
-                  struct kdc_pa_auth_status *auth_status)
+pa_enc_ts_validate(astgs_request_t r, const PA_DATA *pa)
 {
     EncryptedData enc_data;
     krb5_error_code ret;
@@ -863,11 +834,12 @@ pa_enc_ts_validate(astgs_request_t r,
        return ret;
     }
 
-    if (r->client->entry.flags.locked_out) {
+    if (r->client->flags.locked_out) {
        ret = KRB5KDC_ERR_CLIENT_REVOKED;
        kdc_log(r->context, r->config, 0,
                "Client (%s) is locked out", r->cname);
-       auth_status->auth_status = HDB_AUTHSTATUS_CLIENT_LOCKED_OUT;
+       kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
+                             KDC_AUTH_EVENT_CLIENT_LOCKED_OUT);
        return ret;
     }
 
@@ -882,7 +854,7 @@ pa_enc_ts_validate(astgs_request_t r,
        goto out;
     }
        
-    ret = hdb_enctype2key(r->context, &r->client->entry, NULL,
+    ret = hdb_enctype2key(r->context, r->client, NULL,
                          enc_data.etype, &pa_key);
     if(ret){
        char *estr;
@@ -935,14 +907,13 @@ pa_enc_ts_validate(astgs_request_t r,
        _kdc_r_log(r, 2, "Failed to decrypt PA-DATA -- %s "
                   "(enctype %s) error %s",
                   r->cname, str ? str : "unknown enctype", msg);
+       krb5_xfree(str);
        krb5_free_error_message(r->context, msg);
-
-       free(auth_status->free_ptr);
-       auth_status->auth_status = HDB_AUTHSTATUS_WRONG_PASSWORD;
-       auth_status->auth_details = str ? str : "unknown enctype";
-       auth_status->free_ptr = str;
-
-       if(hdb_next_enctype2key(r->context, &r->client->entry, NULL,
+       kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_PA_ETYPE,
+                              pa_key->key.keytype);
+       kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
+                              KDC_AUTH_EVENT_WRONG_LONG_TERM_KEY);
+       if(hdb_next_enctype2key(r->context, r->client, NULL,
                                enc_data.etype, &pa_key) == 0)
            goto try_next_key;
 
@@ -952,10 +923,6 @@ pa_enc_ts_validate(astgs_request_t r,
        goto out;
     }
     free_EncryptedData(&enc_data);
-    free(auth_status->free_ptr);
-    auth_status->auth_status = HDB_AUTHSTATUS_INVALID;
-    auth_status->auth_details = NULL;
-    auth_status->free_ptr = NULL;
     ret = decode_PA_ENC_TS_ENC(ts_data.data,
                               ts_data.length,
                               &p,
@@ -980,7 +947,8 @@ pa_enc_ts_validate(astgs_request_t r,
                   (unsigned)labs(kdc_time - p.patimestamp),
                   r->context->max_skew,
                   r->cname);
-       auth_status->auth_details = "AP_ERR_SKEW";
+       kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
+                              KDC_AUTH_EVENT_CLIENT_TIME_SKEW);
 
        /*
         * The following is needed to make windows clients to
@@ -995,10 +963,8 @@ pa_enc_ts_validate(astgs_request_t r,
 
     ret = set_salt_padata(r->context, r->config,
                          r->rep.padata, pa_key);
-    if (ret)
-       return ret;
-
-    ret = krb5_copy_keyblock_contents(r->context, &pa_key->key, &r->reply_key);
+    if (ret == 0)
+        ret = krb5_copy_keyblock_contents(r->context, &pa_key->key, &r->reply_key);
     if (ret)
        return ret;
 
@@ -1007,11 +973,11 @@ pa_enc_ts_validate(astgs_request_t r,
        str = NULL;
     _kdc_r_log(r, 4, "ENC-TS Pre-authentication succeeded -- %s using %s",
               r->cname, str ? str : "unknown enctype");
-    _kdc_audit_addkv((kdc_request_t)r, 0, "pa-etype", "%d",
-                    (int)pa_key->key.keytype);
-    auth_status->auth_status = HDB_AUTHSTATUS_CORRECT_PASSWORD;
-    auth_status->auth_details = str ? str : "unknown enctype";
-    auth_status->free_ptr = str;
+    krb5_xfree(str);
+    kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_PA_ETYPE,
+                          pa_key->key.keytype);
+    kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
+                          KDC_AUTH_EVENT_VALIDATED_LONG_TERM_KEY);
 
     ret = 0;
 
@@ -1029,9 +995,7 @@ struct kdc_patypes {
 #define PA_SYNTHETIC_OK        4
 #define PA_REPLACE_REPLY_KEY   8   /* PA mech replaces reply key */
 #define PA_USES_LONG_TERM_KEY  16  /* PA mech uses client's long-term key */
-    krb5_error_code (*validate)(astgs_request_t,
-                               const PA_DATA *pa,
-                               struct kdc_pa_auth_status *auth_status);
+    krb5_error_code (*validate)(astgs_request_t, const PA_DATA *pa);
     krb5_error_code (*finalize_pac)(astgs_request_t r);
     void (*cleanup)(astgs_request_t r);
 };
@@ -1074,7 +1038,7 @@ static const struct kdc_patypes pat[] = {
     {
        KRB5_PADATA_GSS , "GSS",
        PA_ANNOUNCE | PA_SYNTHETIC_OK | PA_REPLACE_REPLY_KEY,
-       pa_gss_validate, pa_gss_finalize_pac, pa_gss_cleanup
+       pa_gss_validate, pa_gss_finalize_pac, NULL
     },
 };
 
@@ -1107,8 +1071,8 @@ log_patypes(astgs_request_t r, METHOD_DATA *padata)
 
     str = rk_strpoolcollect(p);
     kdc_log(r->context, config, 4, "Client sent patypes: %s", str);
-    _kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_EATWHITE,
-                    "client-pa", "%s", str);
+    kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_EATWHITE,
+                   "client-pa", "%s", str);
     free(str);
 }
 
@@ -1273,25 +1237,29 @@ _kdc_encode_reply(krb5_context context,
        return ret;
     }
     if(rep->msg_type == krb_as_rep) {
-       krb5_encrypt_EncryptedData(context,
-                                  crypto,
-                                  KRB5_KU_AS_REP_ENC_PART,
-                                  buf,
-                                  len,
-                                  ckvno,
-                                  &rep->enc_part);
-       free(buf);
-       ASN1_MALLOC_ENCODE(AS_REP, buf, buf_size, rep, &len, ret);
+        ret = krb5_encrypt_EncryptedData(context,
+                                         crypto,
+                                         KRB5_KU_AS_REP_ENC_PART,
+                                         buf,
+                                         len,
+                                         ckvno,
+                                         &rep->enc_part);
+        free(buf);
+        if (ret == 0)
+            ASN1_MALLOC_ENCODE(AS_REP, buf, buf_size, rep, &len, ret);
     } else {
-       krb5_encrypt_EncryptedData(context,
-                                  crypto,
-                                  rk_is_subkey ? KRB5_KU_TGS_REP_ENC_PART_SUB_KEY : KRB5_KU_TGS_REP_ENC_PART_SESSION,
-                                  buf,
-                                  len,
-                                  ckvno,
-                                  &rep->enc_part);
-       free(buf);
-       ASN1_MALLOC_ENCODE(TGS_REP, buf, buf_size, rep, &len, ret);
+        ret = krb5_encrypt_EncryptedData(context,
+                                         crypto,
+                                         rk_is_subkey ?
+                                             KRB5_KU_TGS_REP_ENC_PART_SUB_KEY :
+                                             KRB5_KU_TGS_REP_ENC_PART_SESSION,
+                                         buf,
+                                         len,
+                                         ckvno,
+                                         &rep->enc_part);
+        free(buf);
+        if (ret == 0)
+            ASN1_MALLOC_ENCODE(TGS_REP, buf, buf_size, rep, &len, ret);
     }
     krb5_crypto_destroy(context, crypto);
     if(ret) {
@@ -1315,57 +1283,6 @@ _kdc_encode_reply(krb5_context context,
  *
  */
 
-static krb5_error_code
-make_etype_info_entry(krb5_context context,
-                     ETYPE_INFO_ENTRY *ent,
-                     Key *key,
-                     krb5_boolean include_salt)
-{
-    ent->etype = key->key.keytype;
-    if (key->salt && include_salt){
-#if 0
-       ALLOC(ent->salttype);
-
-       if(key->salt->type == hdb_pw_salt)
-           *ent->salttype = 0; /* or 1? or NULL? */
-       else if(key->salt->type == hdb_afs3_salt)
-           *ent->salttype = 2;
-       else {
-           kdc_log(context, config, 4, "unknown salt-type: %d",
-                   key->salt->type);
-           return KRB5KRB_ERR_GENERIC;
-       }
-       /* according to `the specs', we can't send a salt if
-          we have AFS3 salted key, but that requires that you
-          *know* what cell you are using (e.g by assuming
-          that the cell is the same as the realm in lower
-          case) */
-#elif 0
-       ALLOC(ent->salttype);
-       *ent->salttype = key->salt->type;
-#else
-       /*
-        * We shouldn't sent salttype since it is incompatible with the
-        * specification and it breaks windows clients.  The afs
-        * salting problem is solved by using KRB5-PADATA-AFS3-SALT
-        * implemented in Heimdal 0.7 and later.
-        */
-       ent->salttype = NULL;
-#endif
-       krb5_copy_data(context, &key->salt->salt,
-                      &ent->salt);
-    } else {
-       /* we return no salt type at all, as that should indicate
-        * the default salt type and make everybody happy.  some
-        * systems (like w2k) dislike being told the salt type
-        * here. */
-
-       ent->salttype = NULL;
-       ent->salt = NULL;
-    }
-    return 0;
-}
-
 static krb5_error_code
 get_pa_etype_info(krb5_context context,
                  krb5_kdc_configuration *config,
@@ -1373,35 +1290,51 @@ get_pa_etype_info(krb5_context context,
                  krb5_boolean include_salt)
 {
     krb5_error_code ret = 0;
-    ETYPE_INFO pa;
-    unsigned char *buf;
+    ETYPE_INFO_ENTRY eie; /* do not free this one */
+    ETYPE_INFO ei;
+    PA_DATA pa;
     size_t len;
 
+    /*
+     * Code moved here from what used to be make_etype_info_entry() because
+     * using the ASN.1 compiler-generated SEQUENCE OF add functions makes that
+     * old function's body and this one's small and clean.
+     *
+     * The following comment blocks were there:
+     *
+     *  According to `the specs', we can't send a salt if we have AFS3 salted
+     *  key, but that requires that you *know* what cell you are using (e.g by
+     *  assuming that the cell is the same as the realm in lower case)
+     *
+     *  We shouldn't sent salttype since it is incompatible with the
+     *  specification and it breaks windows clients.  The afs salting problem
+     *  is solved by using KRB5-PADATA-AFS3-SALT implemented in Heimdal 0.7 and
+     *  later.
+     *
+     *  We return no salt type at all, as that should indicate the default salt
+     *  type and make everybody happy.  some systems (like w2k) dislike being
+     *  told the salt type here.
+     */
 
-    pa.len = 1;
-    pa.val = calloc(1, sizeof(pa.val[0]));
-    if(pa.val == NULL)
-       return ENOMEM;
-
-    ret = make_etype_info_entry(context, &pa.val[0], ckey, include_salt);
-    if (ret) {
-       free_ETYPE_INFO(&pa);
-       return ret;
-    }
-
-    ASN1_MALLOC_ENCODE(ETYPE_INFO, buf, len, &pa, &len, ret);
-    free_ETYPE_INFO(&pa);
-    if(ret)
-       return ret;
-    ret = realloc_method_data(md);
-    if(ret) {
-       free(buf);
-       return ret;
-    }
-    md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO;
-    md->val[md->len - 1].padata_value.length = len;
-    md->val[md->len - 1].padata_value.data = buf;
-    return 0;
+    pa.padata_type = KRB5_PADATA_ETYPE_INFO;
+    pa.padata_value.data = NULL;
+    pa.padata_value.length = 0;
+    ei.len = 0;
+    ei.val = NULL;
+    eie.etype = ckey->key.keytype;
+    eie.salttype = NULL;
+    eie.salt = NULL;
+    if (include_salt && ckey->salt)
+        eie.salt = &ckey->salt->salt;
+    ret = add_ETYPE_INFO(&ei, &eie);
+    if (ret == 0)
+        ASN1_MALLOC_ENCODE(ETYPE_INFO, pa.padata_value.data, pa.padata_value.length,
+                           &ei, &len, ret);
+    if (ret == 0)
+        add_METHOD_DATA(md, &pa);
+    free_ETYPE_INFO(&ei);
+    free_PA_DATA(&pa);
+    return ret;
 }
 
 /*
@@ -1642,8 +1575,8 @@ _log_astgs_req(astgs_request_t r, krb5_enctype setype)
 
     str = rk_strpoolcollect(s);
     if (str)
-        _kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_EATWHITE, "etypes", "%s",
-                         str);
+        kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_EATWHITE, "etypes", "%s",
+                        str);
     free(str);
 
     ret = krb5_enctype_to_string(r->context, cetype, &cet);
@@ -1664,7 +1597,7 @@ _log_astgs_req(astgs_request_t r, krb5_enctype setype)
        _kdc_r_log(r, 4, "%s", str);
     free(str);
 
-    _kdc_audit_addkv((kdc_request_t)r, 0, "etype", "%d/%d", cetype, setype);
+    kdc_audit_addkv((kdc_request_t)r, 0, "etype", "%d/%d", cetype, setype);
 
     {
        char fixedstr[128];
@@ -1674,8 +1607,8 @@ _log_astgs_req(astgs_request_t r, krb5_enctype setype)
                               fixedstr, sizeof(fixedstr));
        if (result > 0) {
            _kdc_r_log(r, 4, "Requested flags: %s", fixedstr);
-           _kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_EATWHITE,
-                            "flags", "%s", fixedstr);
+           kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_EATWHITE,
+                           "flags", "%s", fixedstr);
        }
     }
 }
@@ -1686,30 +1619,28 @@ _log_astgs_req(astgs_request_t r, krb5_enctype setype)
  * and error code otherwise.
  */
 
-krb5_error_code
+KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL
 kdc_check_flags(astgs_request_t r,
                 krb5_boolean is_as_req,
-                hdb_entry_ex *client_ex,
-                hdb_entry_ex *server_ex)
+                hdb_entry *client,
+                hdb_entry *server)
 {
-    if (client_ex != NULL) {
-       hdb_entry *client = &client_ex->entry;
-
+    if (client != NULL) {
        /* check client */
        if (client->flags.locked_out) {
-           _kdc_audit_addreason((kdc_request_t)r, "Client is locked out");
+           kdc_audit_addreason((kdc_request_t)r, "Client is locked out");
            return KRB5KDC_ERR_CLIENT_REVOKED;
        }
 
        if (client->flags.invalid) {
-           _kdc_audit_addreason((kdc_request_t)r,
-                                 "Client has invalid bit set");
+           kdc_audit_addreason((kdc_request_t)r,
+                                "Client has invalid bit set");
            return KRB5KDC_ERR_POLICY;
        }
 
        if (!client->flags.client) {
-           _kdc_audit_addreason((kdc_request_t)r,
-                                 "Principal may not act as client");
+           kdc_audit_addreason((kdc_request_t)r,
+                                "Principal may not act as client");
            return KRB5KDC_ERR_POLICY;
        }
 
@@ -1717,8 +1648,8 @@ kdc_check_flags(astgs_request_t r,
            char starttime_str[100];
            krb5_format_time(r->context, *client->valid_start,
                             starttime_str, sizeof(starttime_str), TRUE);
-           _kdc_audit_addreason((kdc_request_t)r, "Client not yet valid "
-                                 "until %s", starttime_str);
+           kdc_audit_addreason((kdc_request_t)r, "Client not yet valid "
+                                "until %s", starttime_str);
            return KRB5KDC_ERR_CLIENT_NOTYET;
        }
 
@@ -1726,49 +1657,47 @@ kdc_check_flags(astgs_request_t r,
            char endtime_str[100];
            krb5_format_time(r->context, *client->valid_end,
                             endtime_str, sizeof(endtime_str), TRUE);
-           _kdc_audit_addreason((kdc_request_t)r, "Client expired at %s",
-                                 endtime_str);
+           kdc_audit_addreason((kdc_request_t)r, "Client expired at %s",
+                                endtime_str);
            return  KRB5KDC_ERR_NAME_EXP;
        }
 
        if (client->flags.require_pwchange &&
-           (server_ex == NULL || !server_ex->entry.flags.change_pw))
+           (server == NULL || !server->flags.change_pw))
            return KRB5KDC_ERR_KEY_EXPIRED;
 
        if (client->pw_end && *client->pw_end < kdc_time
-           && (server_ex == NULL || !server_ex->entry.flags.change_pw)) {
+           && (server == NULL || !server->flags.change_pw)) {
            char pwend_str[100];
            krb5_format_time(r->context, *client->pw_end,
                             pwend_str, sizeof(pwend_str), TRUE);
-           _kdc_audit_addreason((kdc_request_t)r, "Client's key has expired "
-                                 "at %s", pwend_str);
+           kdc_audit_addreason((kdc_request_t)r, "Client's key has expired "
+                                "at %s", pwend_str);
            return KRB5KDC_ERR_KEY_EXPIRED;
        }
     }
 
     /* check server */
 
-    if (server_ex != NULL) {
-       hdb_entry *server = &server_ex->entry;
-
+    if (server != NULL) {
        if (server->flags.locked_out) {
-           _kdc_audit_addreason((kdc_request_t)r, "Server locked out");
+           kdc_audit_addreason((kdc_request_t)r, "Server locked out");
            return KRB5KDC_ERR_SERVICE_REVOKED;
        }
        if (server->flags.invalid) {
-           _kdc_audit_addreason((kdc_request_t)r,
-                                 "Server has invalid flag set");
+           kdc_audit_addreason((kdc_request_t)r,
+                               "Server has invalid flag set");
            return KRB5KDC_ERR_POLICY;
        }
        if (!server->flags.server) {
-           _kdc_audit_addreason((kdc_request_t)r,
-                                 "Principal may not act as server");
+           kdc_audit_addreason((kdc_request_t)r,
+                                "Principal may not act as server");
            return KRB5KDC_ERR_POLICY;
        }
 
        if (!is_as_req && server->flags.initial) {
-           _kdc_audit_addreason((kdc_request_t)r,
-                                 "AS-REQ is required for server");
+           kdc_audit_addreason((kdc_request_t)r,
+                                "AS-REQ is required for server");
            return KRB5KDC_ERR_POLICY;
        }
 
@@ -1776,8 +1705,8 @@ kdc_check_flags(astgs_request_t r,
            char starttime_str[100];
            krb5_format_time(r->context, *server->valid_start,
                             starttime_str, sizeof(starttime_str), TRUE);
-           _kdc_audit_addreason((kdc_request_t)r, "Server not yet valid "
-                                 "until %s", starttime_str);
+           kdc_audit_addreason((kdc_request_t)r, "Server not yet valid "
+                                "until %s", starttime_str);
            return KRB5KDC_ERR_SERVICE_NOTYET;
        }
 
@@ -1785,8 +1714,8 @@ kdc_check_flags(astgs_request_t r,
            char endtime_str[100];
            krb5_format_time(r->context, *server->valid_end,
                             endtime_str, sizeof(endtime_str), TRUE);
-           _kdc_audit_addreason((kdc_request_t)r, "Server expired at %s",
-                                 endtime_str);
+           kdc_audit_addreason((kdc_request_t)r, "Server expired at %s",
+                                endtime_str);
            return KRB5KDC_ERR_SERVICE_EXP;
        }
 
@@ -1794,8 +1723,8 @@ kdc_check_flags(astgs_request_t r,
            char pwend_str[100];
            krb5_format_time(r->context, *server->pw_end,
                             pwend_str, sizeof(pwend_str), TRUE);
-           _kdc_audit_addreason((kdc_request_t)r, "Server's key has expired "
-                                 "at %s", pwend_str);
+           kdc_audit_addreason((kdc_request_t)r, "Server's key has expired "
+                                "at %s", pwend_str);
            return KRB5KDC_ERR_KEY_EXPIRED;
        }
     }
@@ -1861,8 +1790,8 @@ krb5_error_code
 _kdc_check_anon_policy(astgs_request_t r)
 {
     if (!r->config->allow_anonymous) {
-       _kdc_audit_addreason((kdc_request_t)r,
-                             "Anonymous tickets denied by local policy");
+       kdc_audit_addreason((kdc_request_t)r,
+                            "Anonymous tickets denied by local policy");
        return KRB5KDC_ERR_POLICY;
     }
 
@@ -1914,8 +1843,8 @@ generate_pac(astgs_request_t r, const Key *skey, const Key *tkey,
     krb5_const_principal canon_princ = NULL;
 
     r->pac_attributes = get_pac_attributes(r->context, &r->req);
-    _kdc_audit_addkv((kdc_request_t)r, 0, "pac_attributes", "%lx",
-                    (long)r->pac_attributes);
+    kdc_audit_setkv_number((kdc_request_t)r, "pac_attributes",
+                          r->pac_attributes);
 
     if (!is_tgs && !(r->pac_attributes & (KRB5_PAC_WAS_REQUESTED | KRB5_PAC_WAS_GIVEN_IMPLICITLY)))
        return 0;
@@ -1928,6 +1857,7 @@ generate_pac(astgs_request_t r, const Key *skey, const Key *tkey,
      */
 
     ret = _kdc_pac_generate(r->context,
+                           r->config,
                            r->client,
                            r->server,
                            r->pa_used && !pa_used_flag_isset(r, PA_USES_LONG_TERM_KEY)
@@ -1942,7 +1872,7 @@ generate_pac(astgs_request_t r, const Key *skey, const Key *tkey,
     if (r->pac == NULL)
        return 0;
 
-    rodc_id = r->server->entry.kvno >> 16;
+    rodc_id = r->server->kvno >> 16;
 
     /* libkrb5 expects ticket and PAC client names to match */
     ret = _krb5_principalname2krb5_principal(r->context, &client,
@@ -1956,14 +1886,14 @@ generate_pac(astgs_request_t r, const Key *skey, const Key *tkey,
      * impersonate any realm. Windows always canonicalizes the realm,
      * but Heimdal permits aliases between realms.)
      */
-    if (krb5_realm_compare(r->context, client, r->client->entry.principal)) {
+    if (krb5_realm_compare(r->context, client, r->canon_client_princ)) {
        char *cpn = NULL;
 
-       canon_princ = r->client->entry.principal;
+       canon_princ = r->canon_client_princ;
 
-       krb5_unparse_name(r->context, canon_princ, &cpn);
-       _kdc_audit_addkv((kdc_request_t)r, 0, "canon_client_name", "%s",
-                            cpn ? cpn : "<unknown>");
+       (void) krb5_unparse_name(r->context, canon_princ, &cpn);
+       kdc_audit_addkv((kdc_request_t)r, 0, "canon_client_name", "%s",
+                       cpn ? cpn : "<unknown>");
        krb5_xfree(cpn);
     }
 
@@ -2027,8 +1957,8 @@ static int
 require_preauth_p(astgs_request_t r)
 {
     return r->config->require_preauth
-       || r->client->entry.flags.require_preauth
-       || r->server->entry.flags.require_preauth;
+       || r->client->flags.require_preauth
+       || r->server->flags.require_preauth;
 }
 
 
@@ -2099,11 +2029,13 @@ static krb5_error_code
 get_local_tgs(krb5_context context,
              krb5_kdc_configuration *config,
              krb5_const_realm realm,
-             hdb_entry_ex **krbtgt)
+             HDB **krbtgtdb,
+             hdb_entry **krbtgt)
 {
     krb5_error_code ret;
     krb5_principal tgs_name;
 
+    *krbtgtdb = NULL;
     *krbtgt = NULL;
 
     ret = krb5_make_principal(context,
@@ -2116,7 +2048,7 @@ get_local_tgs(krb5_context context,
        return ret;
 
     ret = _kdc_db_fetch(context, config, tgs_name,
-                       HDB_F_GET_KRBTGT, NULL, NULL, krbtgt);
+                       HDB_F_GET_KRBTGT, NULL, krbtgtdb, krbtgt);
     krb5_free_principal(context, tgs_name);
 
     return ret;
@@ -2143,7 +2075,6 @@ _kdc_as_rep(astgs_request_t r)
     const PA_DATA *pa;
     krb5_boolean is_tgs;
     const char *msg;
-    hdb_entry_ex *krbtgt = NULL;
     Key *krbtgt_key;
 
     memset(rep, 0, sizeof(*rep));
@@ -2227,7 +2158,7 @@ _kdc_as_rep(astgs_request_t r)
     case HDB_ERR_WRONG_REALM: {
        char *fixed_client_name = NULL;
 
-       ret = krb5_unparse_name(r->context, r->client->entry.principal,
+       ret = krb5_unparse_name(r->context, r->client->principal,
                                &fixed_client_name);
        if (ret) {
            goto out;
@@ -2240,26 +2171,26 @@ _kdc_as_rep(astgs_request_t r)
         r->e_text = NULL;
        ret = _kdc_fast_mk_error(r, r->rep.padata, r->armor_crypto,
                                 &req->req_body,
-                                 r->ret = KRB5_KDC_ERR_WRONG_REALM,
-                                r->client->entry.principal, r->server_princ,
+                                 r->error_code = KRB5_KDC_ERR_WRONG_REALM,
+                                r->client->principal, r->server_princ,
                                 NULL, NULL, r->reply);
        goto out;
     }
     default:
     {
-       struct kdc_pa_auth_status auth_status = {HDB_AUTHSTATUS_CLIENT_UNKNOWN, NULL, NULL};
        msg = krb5_get_error_message(r->context, ret);
        kdc_log(r->context, config, 4, "UNKNOWN -- %s: %s", r->cname, msg);
        krb5_free_error_message(r->context, msg);
        ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
-       _kdc_audit_auth_status(r, &auth_status, NULL);
+       kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
+                              KDC_AUTH_EVENT_CLIENT_UNKNOWN);
        goto out;
     }
     }
     ret = _kdc_db_fetch(r->context, config, r->server_princ,
                        HDB_F_GET_SERVER | HDB_F_DELAY_NEW_KEYS |
                        flags | (is_tgs ? HDB_F_GET_KRBTGT : 0),
-                       NULL, NULL, &r->server);
+                       NULL, &r->serverdb, &r->server);
     switch (ret) {
     case 0:    /* Success */
        break;
@@ -2313,28 +2244,24 @@ _kdc_as_rep(astgs_request_t r)
            i = 0;
            pa = _kdc_find_padata(req, &i, pat[n].type);
            if (pa) {
-               struct kdc_pa_auth_status auth_status = {HDB_AUTHSTATUS_INVALID, NULL, NULL};
-
-                if (r->client->entry.flags.synthetic &&
+                if (r->client->flags.synthetic &&
                     !(pat[n].flags & PA_SYNTHETIC_OK)) {
                     kdc_log(r->context, config, 4, "UNKNOWN -- %s", r->cname);
-                    ret = HDB_ERR_NOENTRY;
+                    ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
                     goto out;
                 }
-                _kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_VIS, "pa", "%s",
-                                 pat[n].name);
-               ret = pat[n].validate(r, pa, &auth_status);
+               kdc_audit_addkv((kdc_request_t)r, KDC_AUDIT_VIS, "pa", "%s",
+                               pat[n].name);
+               ret = pat[n].validate(r, pa);
                if (ret != 0) {
                    krb5_error_code  ret2;
                    Key *ckey = NULL;
                    krb5_boolean default_salt;
 
-                   if (auth_status.auth_status == HDB_AUTHSTATUS_INVALID)
-                       auth_status.auth_status = HDB_AUTHSTATUS_GENERIC_FAILURE;
-                   _kdc_audit_auth_status(r,
-                                          &auth_status,
-                                          pat[n].name);
-                   free(auth_status.free_ptr);
+                   if (ret != KRB5_KDC_ERR_MORE_PREAUTH_DATA_REQUIRED &&
+                       !kdc_audit_getkv((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT))
+                       kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
+                                              KDC_AUTH_EVENT_PREAUTH_FAILED);
 
                    /*
                     * If there is a client key, send ETYPE_INFO{,2}
@@ -2350,17 +2277,14 @@ _kdc_as_rep(astgs_request_t r)
                    }
                    goto out;
                }
+               if (!kdc_audit_getkv((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT))
+                   kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
+                                          KDC_AUTH_EVENT_PREAUTH_SUCCEEDED);
                kdc_log(r->context, config, 4,
                        "%s pre-authentication succeeded -- %s",
                        pat[n].name, r->cname);
                found_pa = 1;
                r->pa_used = &pat[n];
-
-               if (auth_status.auth_status == HDB_AUTHSTATUS_INVALID)
-                   auth_status.auth_status = HDB_AUTHSTATUS_GENERIC_SUCCESS;
-
-               _kdc_audit_auth_status(r, &auth_status, r->pa_used->name);
-               free(auth_status.free_ptr);
                r->et.flags.pre_authent = 1;
            }
        }
@@ -2371,9 +2295,9 @@ _kdc_as_rep(astgs_request_t r)
        size_t n;
        krb5_boolean default_salt;
 
-        if (r->client->entry.flags.synthetic) {
+        if (r->client->flags.synthetic) {
             kdc_log(r->context, config, 4, "UNKNOWN -- %s", r->cname);
-            ret = HDB_ERR_NOENTRY;
+            ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
             goto out;
         }
 
@@ -2430,6 +2354,8 @@ _kdc_as_rep(astgs_request_t r)
            goto out;
     }
 
+    r->canon_client_princ = r->client->principal;
+
     /*
      * Verify flags after the user been required to prove its identity
      * with in a preauth mech.
@@ -2449,14 +2375,8 @@ _kdc_as_rep(astgs_request_t r)
        r->et.flags.anonymous = 1;
     }
 
-    {
-       struct kdc_pa_auth_status auth_status
-               = {HDB_AUTHSTATUS_AUTHORIZATION_SUCCESS,
-                  NULL,
-                  NULL};
-
-       _kdc_audit_auth_status(r, &auth_status, NULL);
-    }
+    kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
+                          KDC_AUTH_EVENT_CLIENT_AUTHORIZED);
 
     /*
      * Select the best encryption type for the KDC with out regard to
@@ -2474,11 +2394,11 @@ _kdc_as_rep(astgs_request_t r)
        krbtgt_key = skey;
     } else {
        ret = get_local_tgs(r->context, config, r->server_princ->realm,
-                           &krbtgt);
+                           &r->krbtgtdb, &r->krbtgt);
        if (ret)
            goto out;
 
-       ret = _kdc_get_preferred_key(r->context, config, krbtgt,
+       ret = _kdc_get_preferred_key(r->context, config, r->krbtgt,
                                      r->server_princ->realm,
                                      NULL, &krbtgt_key);
        if (ret)
@@ -2501,31 +2421,31 @@ _kdc_as_rep(astgs_request_t r)
         _kdc_is_anonymous(r->context, r->client_princ)) {
        Realm anon_realm = KRB5_ANON_REALM;
        ret = copy_Realm(&anon_realm, &rep->crealm);
-    } else if (f.canonicalize || r->client->entry.flags.force_canonicalize)
-       ret = copy_Realm(&r->client->entry.principal->realm, &rep->crealm);
+    } else if (f.canonicalize || r->client->flags.force_canonicalize)
+       ret = copy_Realm(&r->canon_client_princ->realm, &rep->crealm);
     else
        ret = copy_Realm(&r->client_princ->realm, &rep->crealm);
     if (ret)
        goto out;
     if (r->et.flags.anonymous)
        ret = _kdc_make_anonymous_principalname(&rep->cname);
-    else if (f.canonicalize || r->client->entry.flags.force_canonicalize)
-       ret = _krb5_principal2principalname(&rep->cname, r->client->entry.principal);
+    else if (f.canonicalize || r->client->flags.force_canonicalize)
+       ret = _krb5_principal2principalname(&rep->cname, r->canon_client_princ);
     else
        ret = _krb5_principal2principalname(&rep->cname, r->client_princ);
     if (ret)
        goto out;
 
     rep->ticket.tkt_vno = 5;
-    if (f.canonicalize || r->server->entry.flags.force_canonicalize)
-       ret = copy_Realm(&r->server->entry.principal->realm, &rep->ticket.realm);
+    if (f.canonicalize || r->server->flags.force_canonicalize)
+       ret = copy_Realm(&r->server->principal->realm, &rep->ticket.realm);
     else
        ret = copy_Realm(&r->server_princ->realm, &rep->ticket.realm);
     if (ret)
        goto out;
-    if (f.canonicalize || r->server->entry.flags.force_canonicalize)
+    if (f.canonicalize || r->server->flags.force_canonicalize)
        _krb5_principal2principalname(&rep->ticket.sname,
-                                     r->server->entry.principal);
+                                     r->server->principal);
     else
        _krb5_principal2principalname(&rep->ticket.sname,
                                      r->server_princ);
@@ -2540,16 +2460,16 @@ _kdc_as_rep(astgs_request_t r)
 #undef CNT
 
     r->et.flags.initial = 1;
-    if(r->client->entry.flags.forwardable && r->server->entry.flags.forwardable)
+    if(r->client->flags.forwardable && r->server->flags.forwardable)
        r->et.flags.forwardable = f.forwardable;
-    if(r->client->entry.flags.proxiable && r->server->entry.flags.proxiable)
+    if(r->client->flags.proxiable && r->server->flags.proxiable)
        r->et.flags.proxiable = f.proxiable;
     else if (f.proxiable) {
        _kdc_set_e_text(r, "Ticket may not be proxiable");
        ret = KRB5KDC_ERR_POLICY;
        goto out;
     }
-    if(r->client->entry.flags.postdate && r->server->entry.flags.postdate)
+    if(r->client->flags.postdate && r->server->flags.postdate)
        r->et.flags.may_postdate = f.allow_postdate;
     else if (f.allow_postdate){
        _kdc_set_e_text(r, "Ticket may not be postdate");
@@ -2558,12 +2478,12 @@ _kdc_as_rep(astgs_request_t r)
     }
 
     if (b->addresses)
-        _kdc_audit_addaddrs((kdc_request_t)r, b->addresses, "reqaddrs");
+        kdc_audit_addaddrs((kdc_request_t)r, b->addresses, "reqaddrs");
 
     /* check for valid set of addresses */
     if (!_kdc_check_addresses(r, b->addresses, r->addr)) {
         if (r->config->warn_ticket_addresses) {
-            _kdc_audit_addkv((kdc_request_t)r, 0, "wrongaddr", "yes");
+            kdc_audit_setkv_bool((kdc_request_t)r, "wrongaddr", TRUE);
         } else {
             _kdc_set_e_text(r, "Request from wrong address");
             ret = KRB5KRB_AP_ERR_BADADDR;
@@ -2596,24 +2516,26 @@ _kdc_as_rep(astgs_request_t r)
        /* be careful not overflowing */
 
         /*
-         * Pre-auth can override r->client->entry.max_life if configured.
+         * Pre-auth can override r->client->max_life if configured.
          *
          * See pre-auth methods, specifically PKINIT, which can get or derive
          * this from the client's certificate.
          */
         if (r->pa_max_life > 0)
-            t = start + min(t - start, r->pa_max_life);
-        else if (r->client->entry.max_life)
-           t = start + min(t - start, *r->client->entry.max_life);
+            t = rk_time_add(start, min(rk_time_sub(t, start), r->pa_max_life));
+        else if (r->client->max_life && *r->client->max_life)
+           t = rk_time_add(start, min(rk_time_sub(t, start),
+                                       *r->client->max_life));
 
-       if (r->server->entry.max_life)
-           t = start + min(t - start, *r->server->entry.max_life);
+       if (r->server->max_life && *r->server->max_life)
+           t = rk_time_add(start, min(rk_time_sub(t, start),
+                                       *r->server->max_life));
 
         /* Pre-auth can bound endtime as well */
         if (r->pa_endtime > 0)
-            t = start + min(t - start, r->pa_endtime);
+            t = rk_time_add(start, min(rk_time_sub(t, start), r->pa_endtime));
 #if 0
-       t = min(t, start + realm->max_life);
+       t = min(t, rk_time_add(start, realm->max_life));
 #endif
        r->et.endtime = t;
        if(f.renewable_ok && r->et.endtime < *b->till){
@@ -2629,12 +2551,14 @@ _kdc_as_rep(astgs_request_t r)
            t = *b->rtime;
            if(t == 0)
                t = MAX_TIME;
-           if(r->client->entry.max_renew)
-               t = start + min(t - start, *r->client->entry.max_renew);
-           if(r->server->entry.max_renew)
-               t = start + min(t - start, *r->server->entry.max_renew);
+           if(r->client->max_renew && *r->client->max_renew)
+               t = rk_time_add(start, min(rk_time_sub(t, start),
+                                           *r->client->max_renew));
+           if(r->server->max_renew && *r->server->max_renew)
+               t = rk_time_add(start, min(rk_time_sub(t, start),
+                                           *r->server->max_renew));
 #if 0
-           t = min(t, start + realm->max_renew);
+           t = min(t, rk_time_add(start, realm->max_renew));
 #endif
            ALLOC(r->et.renew_till);
            *r->et.renew_till = t;
@@ -2665,16 +2589,16 @@ _kdc_as_rep(astgs_request_t r)
        goto out;
     }
     r->ek.last_req.len = 0;
-    if (r->client->entry.pw_end
+    if (r->client->pw_end
        && (config->kdc_warn_pwexpire == 0
-           || kdc_time + config->kdc_warn_pwexpire >= *r->client->entry.pw_end)) {
+           || kdc_time + config->kdc_warn_pwexpire >= *r->client->pw_end)) {
        r->ek.last_req.val[r->ek.last_req.len].lr_type  = LR_PW_EXPTIME;
-       r->ek.last_req.val[r->ek.last_req.len].lr_value = *r->client->entry.pw_end;
+       r->ek.last_req.val[r->ek.last_req.len].lr_value = *r->client->pw_end;
        ++r->ek.last_req.len;
     }
-    if (r->client->entry.valid_end) {
+    if (r->client->valid_end) {
        r->ek.last_req.val[r->ek.last_req.len].lr_type  = LR_ACCT_EXPTIME;
-       r->ek.last_req.val[r->ek.last_req.len].lr_value = *r->client->entry.valid_end;
+       r->ek.last_req.val[r->ek.last_req.len].lr_value = *r->client->valid_end;
        ++r->ek.last_req.len;
     }
     if (r->ek.last_req.len == 0) {
@@ -2683,16 +2607,16 @@ _kdc_as_rep(astgs_request_t r)
        ++r->ek.last_req.len;
     }
     r->ek.nonce = b->nonce;
-    if (r->client->entry.valid_end || r->client->entry.pw_end) {
+    if (r->client->valid_end || r->client->pw_end) {
        ALLOC(r->ek.key_expiration);
-       if (r->client->entry.valid_end) {
-           if (r->client->entry.pw_end)
-               *r->ek.key_expiration = min(*r->client->entry.valid_end,
-                                        *r->client->entry.pw_end);
+       if (r->client->valid_end) {
+           if (r->client->pw_end)
+               *r->ek.key_expiration = min(*r->client->valid_end,
+                                        *r->client->pw_end);
            else
-               *r->ek.key_expiration = *r->client->entry.valid_end;
+               *r->ek.key_expiration = *r->client->valid_end;
        } else
-           *r->ek.key_expiration = *r->client->entry.pw_end;
+           *r->ek.key_expiration = *r->client->pw_end;
     } else
        r->ek.key_expiration = NULL;
     r->ek.flags = r->et.flags;
@@ -2746,7 +2670,7 @@ _kdc_as_rep(astgs_request_t r)
        generate_pac(r, skey, krbtgt_key, is_tgs);
     }
 
-    if (r->client->entry.flags.synthetic) {
+    if (r->client->flags.synthetic) {
        ret = add_synthetic_princ_ad(r);
        if (ret)
            goto out;
@@ -2803,8 +2727,8 @@ _kdc_as_rep(astgs_request_t r)
 
     ret = _kdc_encode_reply(r->context, config,
                            r, req->req_body.nonce, setype,
-                           r->server->entry.kvno, &skey->key,
-                           pa_used_flag_isset(r, PA_REPLACE_REPLY_KEY) ? 0 : r->client->entry.kvno,
+                           r->server->kvno, &skey->key,
+                           pa_used_flag_isset(r, PA_REPLACE_REPLY_KEY) ? 0 : r->client->kvno,
                            0, r->reply);
     if (ret)
        goto out;
@@ -2819,6 +2743,9 @@ _kdc_as_rep(astgs_request_t r)
     }
 
 out:
+    r->error_code = ret;
+    _kdc_audit_request(r);
+
     /*
      * In case of a non proxy error, build an error message.
      */
@@ -2827,7 +2754,7 @@ out:
                                 r->rep.padata,
                                 r->armor_crypto,
                                 &req->req_body,
-                                r->ret = ret,
+                                r->error_code,
                                 r->client_princ,
                                 r->server_princ,
                                 NULL, NULL,
@@ -2850,11 +2777,11 @@ out:
        r->server_princ = NULL;
     }
     if (r->client)
-       _kdc_free_ent(r->context, r->client);
+       _kdc_free_ent(r->context, r->clientdb, r->client);
     if (r->server)
-       _kdc_free_ent(r->context, r->server);
-    if (krbtgt)
-       _kdc_free_ent(r->context, krbtgt);
+       _kdc_free_ent(r->context, r->serverdb, r->server);
+    if (r->krbtgt)
+       _kdc_free_ent(r->context, r->krbtgtdb, r->krbtgt);
     if (r->armor_crypto) {
        krb5_crypto_destroy(r->context, r->armor_crypto);
        r->armor_crypto = NULL;
@@ -2862,7 +2789,7 @@ out:
     if (r->armor_ticket)
        krb5_free_ticket(r->context, r->armor_ticket);
     if (r->armor_server)
-       _kdc_free_ent(r->context, r->armor_server);
+       _kdc_free_ent(r->context, r->armor_serverdb, r->armor_server);
     krb5_free_keyblock_contents(r->context, &r->reply_key);
     krb5_free_keyblock_contents(r->context, &r->session_key);
     krb5_free_keyblock_contents(r->context, &r->strengthen_key);
index c9878dd6af52f010c2245314b733269ae167d143..39d42106e01e7a95ef4a60d8840b2ef292fd3004 100644 (file)
@@ -80,10 +80,10 @@ _kdc_check_pac(krb5_context context,
               krb5_kdc_configuration *config,
               const krb5_principal client_principal,
               const krb5_principal delegated_proxy_principal,
-              hdb_entry_ex *client,
-              hdb_entry_ex *server,
-              hdb_entry_ex *krbtgt,
-              hdb_entry_ex *ticket_server,
+              hdb_entry *client,
+              hdb_entry *server,
+              hdb_entry *krbtgt,
+              hdb_entry *ticket_server,
               const EncryptionKey *server_check_key,
               const EncryptionKey *krbtgt_check_key,
               EncTicketPart *tkt,
@@ -139,7 +139,8 @@ _kdc_check_pac(krb5_context context,
     }
 
     /* Verify the KDC signatures. */
-    ret = _kdc_pac_verify(context, client_principal, delegated_proxy_principal,
+    ret = _kdc_pac_verify(context, config,
+                         client_principal, delegated_proxy_principal,
                          client, server, krbtgt, &pac);
     if (ret == 0) {
        if (pac == NULL) {
@@ -151,8 +152,8 @@ _kdc_check_pac(krb5_context context,
         * We can't verify the KDC signatures if the ticket was issued by
         * another realm's KDC.
         */
-       if (krb5_realm_compare(context, server->entry.principal,
-                              ticket_server->entry.principal)) {
+       if (krb5_realm_compare(context, server->principal,
+                              ticket_server->principal)) {
            ret = krb5_pac_verify(context, pac, 0, NULL, NULL,
                                  krbtgt_check_key);
            if (ret) {
@@ -173,7 +174,7 @@ _kdc_check_pac(krb5_context context,
 
     *kdc_issued = signedticket ||
                  krb5_principal_is_krbtgt(context,
-                                          ticket_server->entry.principal);
+                                          ticket_server->principal);
     *ppac = pac;
 
     return 0;
@@ -210,35 +211,35 @@ check_tgs_flags(astgs_request_t r, KDC_REQ_BODY *b,
 
     if(f.validate){
        if (!tgt->flags.invalid || tgt->starttime == NULL) {
-           _kdc_audit_addreason((kdc_request_t)r,
-                                 "Bad request to validate ticket");
+           kdc_audit_addreason((kdc_request_t)r,
+                                "Bad request to validate ticket");
            return KRB5KDC_ERR_BADOPTION;
        }
        if(*tgt->starttime > kdc_time){
-           _kdc_audit_addreason((kdc_request_t)r,
-                                 "Early request to validate ticket");
+           kdc_audit_addreason((kdc_request_t)r,
+                                "Early request to validate ticket");
            return KRB5KRB_AP_ERR_TKT_NYV;
        }
        /* XXX  tkt = tgt */
        et->flags.invalid = 0;
     } else if (tgt->flags.invalid) {
-       _kdc_audit_addreason((kdc_request_t)r,
-                             "Ticket-granting ticket has INVALID flag set");
+       kdc_audit_addreason((kdc_request_t)r,
+                            "Ticket-granting ticket has INVALID flag set");
        return KRB5KRB_AP_ERR_TKT_INVALID;
     }
 
     if(f.forwardable){
        if (!tgt->flags.forwardable) {
-           _kdc_audit_addreason((kdc_request_t)r,
-                                 "Bad request for forwardable ticket");
+           kdc_audit_addreason((kdc_request_t)r,
+                                "Bad request for forwardable ticket");
            return KRB5KDC_ERR_BADOPTION;
        }
        et->flags.forwardable = 1;
     }
     if(f.forwarded){
        if (!tgt->flags.forwardable) {
-           _kdc_audit_addreason((kdc_request_t)r,
-                                 "Request to forward non-forwardable ticket");
+           kdc_audit_addreason((kdc_request_t)r,
+                                "Request to forward non-forwardable ticket");
            return KRB5KDC_ERR_BADOPTION;
        }
        et->flags.forwarded = 1;
@@ -249,16 +250,16 @@ check_tgs_flags(astgs_request_t r, KDC_REQ_BODY *b,
 
     if(f.proxiable){
        if (!tgt->flags.proxiable) {
-           _kdc_audit_addreason((kdc_request_t)r,
-                                 "Bad request for proxiable ticket");
+           kdc_audit_addreason((kdc_request_t)r,
+                                "Bad request for proxiable ticket");
            return KRB5KDC_ERR_BADOPTION;
        }
        et->flags.proxiable = 1;
     }
     if(f.proxy){
        if (!tgt->flags.proxiable) {
-           _kdc_audit_addreason((kdc_request_t)r,
-                                 "Request to proxy non-proxiable ticket");
+           kdc_audit_addreason((kdc_request_t)r,
+                                "Request to proxy non-proxiable ticket");
            return KRB5KDC_ERR_BADOPTION;
        }
        et->flags.proxy = 1;
@@ -269,16 +270,16 @@ check_tgs_flags(astgs_request_t r, KDC_REQ_BODY *b,
 
     if(f.allow_postdate){
        if (!tgt->flags.may_postdate) {
-           _kdc_audit_addreason((kdc_request_t)r,
-                                 "Bad request for post-datable ticket");
+           kdc_audit_addreason((kdc_request_t)r,
+                                "Bad request for post-datable ticket");
            return KRB5KDC_ERR_BADOPTION;
        }
        et->flags.may_postdate = 1;
     }
     if(f.postdated){
        if (!tgt->flags.may_postdate) {
-           _kdc_audit_addreason((kdc_request_t)r,
-                                 "Bad request for postdated ticket");
+           kdc_audit_addreason((kdc_request_t)r,
+                                "Bad request for postdated ticket");
            return KRB5KDC_ERR_BADOPTION;
        }
        if(b->from)
@@ -286,15 +287,15 @@ check_tgs_flags(astgs_request_t r, KDC_REQ_BODY *b,
        et->flags.postdated = 1;
        et->flags.invalid = 1;
     } else if (b->from && *b->from > kdc_time + r->context->max_skew) {
-       _kdc_audit_addreason((kdc_request_t)r,
-                             "Ticket cannot be postdated");
+       kdc_audit_addreason((kdc_request_t)r,
+                            "Ticket cannot be postdated");
        return KRB5KDC_ERR_CANNOT_POSTDATE;
     }
 
     if(f.renewable){
        if (!tgt->flags.renewable || tgt->renew_till == NULL) {
-           _kdc_audit_addreason((kdc_request_t)r,
-                                 "Bad request for renewable ticket");
+           kdc_audit_addreason((kdc_request_t)r,
+                                "Bad request for renewable ticket");
            return KRB5KDC_ERR_BADOPTION;
        }
        et->flags.renewable = 1;
@@ -305,8 +306,8 @@ check_tgs_flags(astgs_request_t r, KDC_REQ_BODY *b,
     if(f.renew){
        time_t old_life;
        if (!tgt->flags.renewable || tgt->renew_till == NULL) {
-           _kdc_audit_addreason((kdc_request_t)r,
-                                 "Request to renew non-renewable ticket");
+           kdc_audit_addreason((kdc_request_t)r,
+                                "Request to renew non-renewable ticket");
            return KRB5KDC_ERR_BADOPTION;
        }
        old_life = tgt->endtime;
@@ -325,8 +326,8 @@ check_tgs_flags(astgs_request_t r, KDC_REQ_BODY *b,
      */
     if (tgt->flags.anonymous &&
        !_kdc_is_anonymous(r->context, tgt_name)) {
-       _kdc_audit_addreason((kdc_request_t)r,
-                             "Anonymous ticket flag set without "
+       kdc_audit_addreason((kdc_request_t)r,
+                            "Anonymous ticket flag set without "
                         "anonymous principal");
        return KRB5KDC_ERR_BADOPTION;
     }
@@ -342,63 +343,6 @@ check_tgs_flags(astgs_request_t r, KDC_REQ_BODY *b,
     return 0;
 }
 
-/*
- * Determine if constrained delegation is allowed from this client to this server
- */
-
-static krb5_error_code
-check_constrained_delegation(krb5_context context,
-                            krb5_kdc_configuration *config,
-                            HDB *clientdb,
-                            hdb_entry_ex *client,
-                            hdb_entry_ex *server,
-                            krb5_const_principal target)
-{
-    const HDB_Ext_Constrained_delegation_acl *acl;
-    krb5_error_code ret;
-    size_t i;
-
-    /*
-     * constrained_delegation (S4U2Proxy) only works within
-     * the same realm. We use the already canonicalized version
-     * of the principals here, while "target" is the principal
-     * provided by the client.
-     */
-    if(!krb5_realm_compare(context, client->entry.principal, server->entry.principal)) {
-       ret = KRB5KDC_ERR_BADOPTION;
-       kdc_log(context, config, 4,
-           "Bad request for constrained delegation");
-       return ret;
-    }
-
-    if (clientdb->hdb_check_constrained_delegation) {
-       ret = clientdb->hdb_check_constrained_delegation(context, clientdb, client, target);
-       if (ret == 0)
-           return 0;
-    } else {
-       /* if client delegates to itself, that ok */
-       if (krb5_principal_compare(context, client->entry.principal, server->entry.principal) == TRUE)
-           return 0;
-
-       ret = hdb_entry_get_ConstrainedDelegACL(&client->entry, &acl);
-       if (ret) {
-           krb5_clear_error_message(context);
-           return ret;
-       }
-
-       if (acl) {
-           for (i = 0; i < acl->len; i++) {
-               if (krb5_principal_compare(context, target, &acl->val[i]) == TRUE)
-                   return 0;
-           }
-       }
-       ret = KRB5KDC_ERR_BADOPTION;
-    }
-    kdc_log(context, config, 4,
-           "Bad request for constrained delegation");
-    return ret;
-}
-
 /*
  * Determine if s4u2self is allowed from this client to this server
  *
@@ -412,13 +356,13 @@ check_constrained_delegation(krb5_context context,
  * alias of client, then it's safe.
  */
 
-static krb5_error_code
-check_client_matches_target_service(krb5_context context,
-                                   krb5_kdc_configuration *config,
-                                   HDB *clientdb,
-                                   hdb_entry_ex *client,
-                                   hdb_entry_ex *target_server,
-                                   krb5_const_principal target_server_principal)
+krb5_error_code
+_kdc_check_client_matches_target_service(krb5_context context,
+                                        krb5_kdc_configuration *config,
+                                        HDB *clientdb,
+                                        hdb_entry *client,
+                                        hdb_entry *target_server,
+                                        krb5_const_principal target_server_principal)
 {
     krb5_error_code ret;
 
@@ -435,7 +379,7 @@ check_client_matches_target_service(krb5_context context,
        if (ret == 0)
            return 0;
     } else if (krb5_principal_compare(context,
-                                     client->entry.principal,
+                                     client->principal,
                                      target_server_principal) == TRUE) {
        /* if client does a s4u2self to itself, and there is no plugin, that is ok */
        return 0;
@@ -587,17 +531,12 @@ fix_transited_encoding(krb5_context context,
 
 static krb5_error_code
 tgs_make_reply(astgs_request_t r,
-              krb5_principal tgt_name,
               const EncTicketPart *tgt,
               const EncryptionKey *serverkey,
               const EncryptionKey *krbtgtkey,
               const krb5_keyblock *sessionkey,
               krb5_kvno kvno,
               AuthorizationData *auth_data,
-              hdb_entry_ex *server,
-              krb5_principal server_principal,
-              hdb_entry_ex *client,
-              krb5_principal client_principal,
               const char *tgt_realm,
               uint16_t rodc_id,
               krb5_boolean add_ticket_sig)
@@ -611,6 +550,8 @@ tgs_make_reply(astgs_request_t r,
     krb5_error_code ret;
     int is_weak = 0;
 
+    heim_assert(r->client_princ != NULL, "invalid client name passed to tgs_make_reply");
+
     rep->pvno = 5;
     rep->msg_type = krb_tgs_rep;
 
@@ -620,7 +561,7 @@ tgs_make_reply(astgs_request_t r,
     ALLOC(et->starttime);
     *et->starttime = kdc_time;
 
-    ret = check_tgs_flags(r, b, tgt_name, tgt, et);
+    ret = check_tgs_flags(r, b, r->client_princ, tgt, et);
     if(ret)
        goto out;
 
@@ -646,24 +587,39 @@ tgs_make_reply(astgs_request_t r,
     ret = fix_transited_encoding(r->context, r->config,
                                 !f.disable_transited_check ||
                                 GLOBAL_FORCE_TRANSITED_CHECK ||
-                                PRINCIPAL_FORCE_TRANSITED_CHECK(server) ||
+                                PRINCIPAL_FORCE_TRANSITED_CHECK(r->server) ||
                                 !((GLOBAL_ALLOW_PER_PRINCIPAL &&
-                                   PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(server)) ||
+                                   PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(r->server)) ||
                                   GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK),
                                 &tgt->transited, et,
-                                krb5_principal_get_realm(r->context, client_principal),
-                                krb5_principal_get_realm(r->context, server->entry.principal),
+                                krb5_principal_get_realm(r->context, r->client_princ),
+                                krb5_principal_get_realm(r->context, r->server->principal),
                                 tgt_realm);
-    if(ret)
-       goto out;
 
-    ret = copy_Realm(&server_principal->realm, &rep->ticket.realm);
-    if (ret)
-       goto out;
-    _krb5_principal2principalname(&rep->ticket.sname, server_principal);
-    ret = copy_Realm(&tgt_name->realm, &rep->crealm);
+    {
+        /*
+         * RFC 6806 notes that names MUST NOT be changed in the response to a
+         * TGS request. Hence we ignore the setting of the canonicalize KDC
+         * option. However, for legacy interoperability we do allow the backend
+         * to override this by setting the force-canonicalize HDB flag in the
+         * server entry.
+         */
+        krb5_const_principal rsp;
+
+        if (r->server->flags.force_canonicalize)
+            rsp = r->server->principal;
+        else
+            rsp = r->server_princ;
+        if (ret == 0)
+            ret = copy_Realm(&rsp->realm, &rep->ticket.realm);
+        if (ret == 0)
+            ret = _krb5_principal2principalname(&rep->ticket.sname, rsp);
+    }
+
+    if (ret == 0)
+        ret = copy_Realm(&r->client_princ->realm, &rep->crealm);
     if (ret)
-       goto out;
+        goto out;
 
     /*
      * RFC 8062 states "if the ticket in the TGS request is an anonymous
@@ -674,7 +630,7 @@ tgs_make_reply(astgs_request_t r,
     if (et->flags.anonymous && !tgt->flags.anonymous)
        _kdc_make_anonymous_principalname(&rep->cname);
     else
-       ret = copy_PrincipalName(&tgt_name->name, &rep->cname);
+       ret = copy_PrincipalName(&r->client_princ->name, &rep->cname);
     if (ret)
        goto out;
     rep->ticket.tkt_vno = 5;
@@ -684,10 +640,10 @@ tgs_make_reply(astgs_request_t r,
     {
        time_t life;
        life = et->endtime - *et->starttime;
-       if(client && client->entry.max_life)
-           life = min(life, *client->entry.max_life);
-       if(server->entry.max_life)
-           life = min(life, *server->entry.max_life);
+       if(r->client && r->client->max_life)
+           life = min(life, *r->client->max_life);
+       if(r->server->max_life)
+           life = min(life, *r->server->max_life);
        et->endtime = *et->starttime + life;
     }
     if(f.renewable_ok && tgt->flags.renewable &&
@@ -701,10 +657,10 @@ tgs_make_reply(astgs_request_t r,
     if(et->renew_till){
        time_t renew;
        renew = *et->renew_till - *et->starttime;
-       if(client && client->entry.max_renew)
-           renew = min(renew, *client->entry.max_renew);
-       if(server->entry.max_renew)
-           renew = min(renew, *server->entry.max_renew);
+       if(r->client && r->client->max_renew)
+           renew = min(renew, *r->client->max_renew);
+       if(r->server->max_renew)
+           renew = min(renew, *r->server->max_renew);
        *et->renew_till = *et->starttime + renew;
     }
 
@@ -728,12 +684,12 @@ tgs_make_reply(astgs_request_t r,
 
     et->flags.pre_authent = tgt->flags.pre_authent;
     et->flags.hw_authent  = tgt->flags.hw_authent;
-    et->flags.ok_as_delegate = server->entry.flags.ok_as_delegate;
+    et->flags.ok_as_delegate = r->server->flags.ok_as_delegate;
 
     /* See MS-KILE 3.3.5.1 */
-    if (!server->entry.flags.forwardable)
+    if (!r->server->flags.forwardable)
        et->flags.forwardable = 0;
-    if (!server->entry.flags.proxiable)
+    if (!r->server->flags.proxiable)
        et->flags.proxiable = 0;
 
     if (auth_data) {
@@ -785,18 +741,18 @@ tgs_make_reply(astgs_request_t r,
                       et->endtime, et->renew_till);
 
     if (krb5_enctype_valid(r->context, serverkey->keytype) != 0
-       && _kdc_is_weak_exception(server->entry.principal, serverkey->keytype))
+       && _kdc_is_weak_exception(r->server->principal, serverkey->keytype))
     {
        krb5_enctype_enable(r->context, serverkey->keytype);
        is_weak = 1;
     }
 
-    if (r->client_princ) {
+    if (r->canon_client_princ) {
        char *cpn;
 
-       krb5_unparse_name(r->context, r->client_princ, &cpn);
-       _kdc_audit_addkv((kdc_request_t)r, 0, "canon_client_name", "%s",
-                        cpn ? cpn : "<unknown>");
+       (void) krb5_unparse_name(r->context, r->canon_client_princ, &cpn);
+       kdc_audit_addkv((kdc_request_t)r, 0, "canon_client_name", "%s",
+                       cpn ? cpn : "<unknown>");
        krb5_xfree(cpn);
     }
 
@@ -807,8 +763,8 @@ tgs_make_reply(astgs_request_t r,
      * is implementation dependent.
      */
     if (r->pac && !et->flags.anonymous) {
-       _kdc_audit_addkv((kdc_request_t)r, 0, "pac_attributes", "%lx",
-                        (long)r->pac_attributes);
+       kdc_audit_setkv_number((kdc_request_t)r, "pac_attributes",
+                              r->pac_attributes);
 
        /*
         * PACs are included when issuing TGTs, if there is no PAC_ATTRIBUTES
@@ -817,10 +773,10 @@ tgs_make_reply(astgs_request_t r,
         */
        if (_kdc_include_pac_p(r)) {
            krb5_boolean is_tgs =
-               krb5_principal_is_krbtgt(r->context, server->entry.principal);
+               krb5_principal_is_krbtgt(r->context, r->server->principal);
 
-           ret = _krb5_kdc_pac_sign_ticket(r->context, r->pac, tgt_name, serverkey,
-                                           krbtgtkey, rodc_id, NULL, r->client_princ,
+           ret = _krb5_kdc_pac_sign_ticket(r->context, r->pac, r->client_princ, serverkey,
+                                           krbtgtkey, rodc_id, NULL, r->canon_client_princ,
                                            add_ticket_sig, et,
                                            is_tgs ? &r->pac_attributes : NULL);
            if (ret)
@@ -865,7 +821,12 @@ tgs_check_authenticator(krb5_context context,
     krb5_error_code ret;
     krb5_crypto crypto;
 
-    krb5_auth_con_getauthenticator(context, ac, &auth);
+    ret = krb5_auth_con_getauthenticator(context, ac, &auth);
+    if (ret) {
+       kdc_log(context, config, 2,
+                "Out of memory checking PA-TGS Authenticator");
+        goto out;
+    }
     if(auth->cksum == NULL){
        kdc_log(context, config, 4, "No authenticator in request");
        ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
@@ -922,23 +883,7 @@ need_referral(krb5_context context, krb5_kdc_configuration *config,
 
     if (server->name.name_string.len == 1)
        name = server->name.name_string.val[0];
-    else if (server->name.name_string.len == 3) {
-       /*
-         This is used to give referrals for the
-         E3514235-4B06-11D1-AB04-00C04FC2DCD2/NTDSGUID/DNSDOMAIN
-         SPN form, which is used for inter-domain communication in AD
-        */
-       name = server->name.name_string.val[2];
-       kdc_log(context, config, 4, "Giving 3 part referral for %s", name);
-       *realms = malloc(sizeof(char *)*2);
-       if (*realms == NULL) {
-           krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
-           return FALSE;
-       }
-       (*realms)[0] = strdup(name);
-       (*realms)[1] = NULL;
-       return TRUE;
-    } else if (server->name.name_string.len > 1)
+    else if (server->name.name_string.len > 1)
        name = server->name.name_string.val[1];
     else
        return FALSE;
@@ -978,9 +923,7 @@ validate_fast_ad(astgs_request_t r, krb5_authdata *auth_data)
 static krb5_error_code
 tgs_parse_request(astgs_request_t r,
                  const PA_DATA *tgs_req,
-                 hdb_entry_ex **krbtgt,
                  krb5_enctype *krbtgt_etype,
-                 krb5_ticket **ticket,
                  const char *from,
                  const struct sockaddr *from_addr,
                  time_t **csec,
@@ -1032,7 +975,7 @@ tgs_parse_request(astgs_request_t r,
 
     krbtgt_kvno = ap_req.ticket.enc_part.kvno ? *ap_req.ticket.enc_part.kvno : 0;
     ret = _kdc_db_fetch(r->context, config, princ, HDB_F_GET_KRBTGT,
-                       &krbtgt_kvno, NULL, krbtgt);
+                       &krbtgt_kvno, &r->krbtgtdb, &r->krbtgt);
 
     if (ret == HDB_ERR_NOT_FOUND_HERE) {
        /* XXX Factor out this unparsing of the same princ all over */
@@ -1090,12 +1033,12 @@ tgs_parse_request(astgs_request_t r,
        goto out;
     }
 
-    krbtgt_kvno_try = krbtgt_kvno ? krbtgt_kvno : (*krbtgt)->entry.kvno;
+    krbtgt_kvno_try = krbtgt_kvno ? krbtgt_kvno : r->krbtgt->kvno;
     *krbtgt_etype = ap_req.ticket.enc_part.etype;
 
 next_kvno:
-    krbtgt_keys = hdb_kvno2keys(r->context, &(*krbtgt)->entry, krbtgt_kvno_try);
-    ret = hdb_enctype2key(r->context, &(*krbtgt)->entry, krbtgt_keys,
+    krbtgt_keys = hdb_kvno2keys(r->context, r->krbtgt, krbtgt_kvno_try);
+    ret = hdb_enctype2key(r->context, r->krbtgt, krbtgt_keys,
                          ap_req.ticket.enc_part.etype, &tkey);
     if (ret && krbtgt_kvno == 0 && kvno_search_tries > 0) {
        kvno_search_tries--;
@@ -1129,13 +1072,13 @@ next_kvno:
                              &tkey->key,
                              verify_ap_req_flags,
                              &ap_req_options,
-                             ticket,
+                             &r->ticket,
                              KRB5_KU_TGS_REQ_AUTH);
-    if (*ticket && (*ticket)->ticket.caddr)
-        _kdc_audit_addaddrs((kdc_request_t)r, (*ticket)->ticket.caddr, "tixaddrs");
+    if (r->ticket && r->ticket->ticket.caddr)
+        kdc_audit_addaddrs((kdc_request_t)r, r->ticket->ticket.caddr, "tixaddrs");
     if (r->config->warn_ticket_addresses && ret == KRB5KRB_AP_ERR_BADADDR &&
-        *ticket != NULL) {
-        _kdc_audit_addkv((kdc_request_t)r, 0, "wrongaddr", "yes");
+        r->ticket != NULL) {
+        kdc_audit_setkv_bool((kdc_request_t)r, "wrongaddr", TRUE);
         ret = 0;
     }
     if (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY && kvno_search_tries > 0) {
@@ -1181,8 +1124,7 @@ next_kvno:
        }
     }
 
-    ret = tgs_check_authenticator(r->context, config, ac, b,
-                                  &(*ticket)->ticket.key);
+    ret = tgs_check_authenticator(r->context, config, ac, b, &r->ticket->ticket.key);
     if (ret) {
        krb5_auth_con_free(r->context, ac);
        goto out;
@@ -1267,7 +1209,7 @@ next_kvno:
        }
     }
 
-    ret = validate_fast_ad(r, (*ticket)->ticket.authorization_data);
+    ret = validate_fast_ad(r, r->ticket->ticket.authorization_data);
     if (ret)
        goto out;
 
@@ -1276,7 +1218,7 @@ next_kvno:
      * Check for FAST request
      */
 
-    ret = _kdc_fast_unwrap_request(r, *ticket, ac);
+    ret = _kdc_fast_unwrap_request(r, r->ticket, ac);
     if (ret)
        goto out;
 
@@ -1376,10 +1318,10 @@ _kdc_db_fetch_client(krb5_context context,
                     const char *cpn,
                     const char *krbtgt_realm,
                     HDB **clientdb,
-                    hdb_entry_ex **client_out)
+                    hdb_entry **client_out)
 {
     krb5_error_code ret;
-    hdb_entry_ex *client = NULL;
+    hdb_entry *client = NULL;
 
     *client_out = NULL;
 
@@ -1408,9 +1350,9 @@ _kdc_db_fetch_client(krb5_context context,
        msg = krb5_get_error_message(context, ret);
        kdc_log(context, config, 4, "Client not found in database: %s", msg);
        krb5_free_error_message(context, msg);
-    } else if (client->entry.flags.invalid || !client->entry.flags.client) {
+    } else if (client->flags.invalid || !client->flags.client) {
         kdc_log(context, config, 4, "Client has invalid bit set");
-       _kdc_free_ent(context, client);
+       _kdc_free_ent(context, *clientdb, client);
         return KRB5KDC_ERR_POLICY;
     }
 
@@ -1421,29 +1363,25 @@ _kdc_db_fetch_client(krb5_context context,
 
 static krb5_error_code
 tgs_build_reply(astgs_request_t priv,
-               hdb_entry_ex *krbtgt,
                krb5_enctype krbtgt_etype,
-               krb5_ticket *ticket,
                AuthorizationData **auth_data,
                const struct sockaddr *from_addr)
 {
     krb5_context context = priv->context;
     krb5_kdc_configuration *config = priv->config;
-    KDC_REQ *req = &priv->req;
     KDC_REQ_BODY *b = &priv->req.req_body;
     const char *from = priv->from;
     krb5_error_code ret, ret2;
-    krb5_principal cp = NULL, sp = NULL, rsp = NULL, tp = NULL, dp = NULL;
     krb5_principal krbtgt_out_principal = NULL;
     krb5_principal user2user_princ = NULL;
-    char *spn = NULL, *cpn = NULL, *tpn = NULL, *dpn = NULL, *krbtgt_out_n = NULL;
+    char *spn = NULL, *cpn = NULL, *krbtgt_out_n = NULL;
     char *user2user_name = NULL;
-    hdb_entry_ex *server = NULL, *client = NULL, *s4u2self_impersonated_client = NULL;
-    hdb_entry_ex *user2user_krbtgt = NULL;
-    HDB *clientdb, *s4u2self_impersonated_clientdb;
+    HDB *user2user_krbtgtdb;
+    hdb_entry *user2user_krbtgt = NULL;
+    HDB *clientdb;
     HDB *serverdb = NULL;
     krb5_realm ref_realm = NULL;
-    EncTicketPart *tgt = &ticket->ticket;
+    EncTicketPart *tgt = &priv->ticket->ticket;
     const EncryptionKey *ekey;
     krb5_keyblock sessionkey;
     krb5_kvno kvno;
@@ -1451,13 +1389,14 @@ tgs_build_reply(astgs_request_t priv,
     uint16_t rodc_id;
     krb5_boolean add_ticket_sig = FALSE;
     const char *tgt_realm = /* Realm of TGT issuer */
-        krb5_principal_get_realm(context, krbtgt->entry.principal);
+        krb5_principal_get_realm(context, priv->krbtgt->principal);
     const char *our_realm = /* Realm of this KDC */
-        krb5_principal_get_comp_string(context, krbtgt->entry.principal, 1);
+        krb5_principal_get_comp_string(context, priv->krbtgt->principal, 1);
     char **capath = NULL;
     size_t num_capath = 0;
 
-    hdb_entry_ex *krbtgt_out = NULL;
+    HDB *krbtgt_outdb;
+    hdb_entry *krbtgt_out = NULL;
 
     PrincipalName *s;
     Realm r;
@@ -1491,13 +1430,14 @@ tgs_build_reply(astgs_request_t priv,
        goto out;
     }
 
-    _krb5_principalname2krb5_principal(context, &sp, *s, r);
-    ret = krb5_unparse_name(context, sp, &priv->sname);
+    _krb5_principalname2krb5_principal(context, &priv->server_princ, *s, r);
+    ret = krb5_unparse_name(context, priv->server_princ, &priv->sname);
     if (ret)
        goto out;
     spn = priv->sname;
-    _krb5_principalname2krb5_principal(context, &cp, tgt->cname, tgt->crealm);
-    ret = krb5_unparse_name(context, cp, &priv->cname);
+    _krb5_principalname2krb5_principal(context, &priv->client_princ,
+                                      tgt->cname, tgt->crealm);
+    ret = krb5_unparse_name(context, priv->client_princ, &priv->cname);
     if (ret)
        goto out;
     cpn = priv->cname;
@@ -1517,21 +1457,20 @@ tgs_build_reply(astgs_request_t priv,
      */
 
 server_lookup:
+    if (priv->server)
+        _kdc_free_ent(context, serverdb, priv->server);
     priv->server = NULL;
-    if (server)
-        _kdc_free_ent(context, server);
-    server = NULL;
-    ret = _kdc_db_fetch(context, config, sp,
+    ret = _kdc_db_fetch(context, config, priv->server_princ,
                         HDB_F_GET_SERVER | HDB_F_DELAY_NEW_KEYS | flags,
-                       NULL, &serverdb, &server);
-    priv->server = server;
+                       NULL, &serverdb, &priv->server);
+    priv->serverdb = serverdb;
     if (ret == HDB_ERR_NOT_FOUND_HERE) {
        kdc_log(context, config, 5, "target %s does not have secrets at this KDC, need to proxy", spn);
-        _kdc_audit_addreason((kdc_request_t)priv, "Target not found here");
+        kdc_audit_addreason((kdc_request_t)priv, "Target not found here");
        goto out;
     } else if (ret == HDB_ERR_WRONG_REALM) {
         free(ref_realm);
-       ref_realm = strdup(server->entry.principal->realm);
+       ref_realm = strdup(priv->server->principal->realm);
        if (ref_realm == NULL) {
             ret = krb5_enomem(context);
            goto out;
@@ -1541,15 +1480,15 @@ server_lookup:
                "Returning a referral to realm %s for "
                "server %s.",
                ref_realm, spn);
-       krb5_free_principal(context, sp);
-       sp = NULL;
-       ret = krb5_make_principal(context, &sp, r, KRB5_TGS_NAME,
+       krb5_free_principal(context, priv->server_princ);
+       priv->server_princ = NULL;
+       ret = krb5_make_principal(context, &priv->server_princ, r, KRB5_TGS_NAME,
                                  ref_realm, NULL);
        if (ret)
            goto out;
        free(priv->sname);
         priv->sname = NULL;
-       ret = krb5_unparse_name(context, sp, &priv->sname);
+       ret = krb5_unparse_name(context, priv->server_princ, &priv->sname);
        if (ret)
            goto out;
        spn = priv->sname;
@@ -1560,17 +1499,26 @@ server_lookup:
        Realm req_rlm;
        krb5_realm *realms;
 
-       if (!config->autodetect_referrals) {
-               /* noop */
-        } else if ((req_rlm = get_krbtgt_realm(&sp->name)) != NULL) {
+       priv->error_code = ret; /* advise policy plugin of failure reason */
+       ret2 = _kdc_referral_policy(priv);
+       if (ret2 == 0) {
+           krb5_xfree(priv->sname);
+           priv->sname = NULL;
+           ret = krb5_unparse_name(context, priv->server_princ, &priv->sname);
+           if (ret)
+               goto out;
+           goto server_lookup;
+       } else if (ret2 != KRB5_PLUGIN_NO_HANDLE) {
+           ret = ret2;
+       } else if ((req_rlm = get_krbtgt_realm(&priv->server_princ->name)) != NULL) {
             if (capath == NULL) {
                 /* With referalls, hierarchical capaths are always enabled */
                 ret2 = _krb5_find_capath(context, tgt->crealm, our_realm,
                                          req_rlm, TRUE, &capath, &num_capath);
                 if (ret2) {
                     ret = ret2;
-                    _kdc_audit_addreason((kdc_request_t)priv,
-                                         "No trusted path from client realm to ours");
+                    kdc_audit_addreason((kdc_request_t)priv,
+                                        "No trusted path from client realm to ours");
                     goto out;
                 }
             }
@@ -1587,31 +1535,31 @@ server_lookup:
                     goto out;
                 }
 
-                krb5_free_principal(context, sp);
-                sp = NULL;
-                krb5_make_principal(context, &sp, r,
+                krb5_free_principal(context, priv->server_princ);
+                priv->server_princ = NULL;
+                krb5_make_principal(context, &priv->server_princ, r,
                                     KRB5_TGS_NAME, ref_realm, NULL);
                 free(priv->sname);
                 priv->sname = NULL;
-                ret = krb5_unparse_name(context, sp, &priv->sname);
+                ret = krb5_unparse_name(context, priv->server_princ, &priv->sname);
                 if (ret)
                     goto out;
                 spn = priv->sname;
                 goto server_lookup;
             }
-       } else if (need_referral(context, config, &b->kdc_options, sp, &realms)) {
-           if (strcmp(realms[0], sp->realm) != 0) {
+       } else if (need_referral(context, config, &b->kdc_options, priv->server_princ, &realms)) {
+           if (strcmp(realms[0], priv->server_princ->realm) != 0) {
                kdc_log(context, config, 4,
                        "Returning a referral to realm %s for "
                        "server %s that was not found",
                        realms[0], spn);
-               krb5_free_principal(context, sp);
-                sp = NULL;
-               krb5_make_principal(context, &sp, r, KRB5_TGS_NAME,
+               krb5_free_principal(context, priv->server_princ);
+                priv->server_princ = NULL;
+               krb5_make_principal(context, &priv->server_princ, r, KRB5_TGS_NAME,
                                    realms[0], NULL);
                free(priv->sname);
                 priv->sname = NULL;
-               ret = krb5_unparse_name(context, sp, &priv->sname);
+               ret = krb5_unparse_name(context, priv->server_princ, &priv->sname);
                if (ret) {
                    krb5_free_host_realm(context, realms);
                    goto out;
@@ -1632,23 +1580,11 @@ server_lookup:
        krb5_free_error_message(context, msg);
        if (ret == HDB_ERR_NOENTRY)
            ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
-        _kdc_audit_addreason((kdc_request_t)priv,
-                             "Service principal unknown");
+        kdc_audit_addreason((kdc_request_t)priv,
+                            "Service principal unknown");
        goto out;
     }
 
-    /*
-     * RFC 6806 notes that names MUST NOT be changed in the response to
-     * a TGS request. Hence we ignore the setting of the canonicalize
-     * KDC option. However, for legacy interoperability we do allow the
-     * backend to override this by setting the force-canonicalize HDB
-     * flag in the server entry.
-     */
-    if (server->entry.flags.force_canonicalize)
-       rsp = server->entry.principal;
-    else
-       rsp = sp;
-
     /*
      * Now refetch the primary krbtgt, and get the current kvno (the
      * sign check may have been on an old kvno, and the server may
@@ -1676,10 +1612,10 @@ server_lookup:
     }
 
     ret = _kdc_db_fetch(context, config, krbtgt_out_principal,
-                       HDB_F_GET_KRBTGT, NULL, NULL, &krbtgt_out);
+                       HDB_F_GET_KRBTGT, NULL, &krbtgt_outdb, &krbtgt_out);
     if (ret) {
        char *ktpn = NULL;
-       ret = krb5_unparse_name(context, krbtgt->entry.principal, &ktpn);
+       ret = krb5_unparse_name(context, priv->krbtgt->principal, &ktpn);
        kdc_log(context, config, 4,
                "No such principal %s (needed for authz-data signature keys) "
                "while processing TGS-REQ for service %s with krbtg %s",
@@ -1703,24 +1639,26 @@ server_lookup:
            krb5uint32 second_kvno = 0;
            krb5uint32 *kvno_ptr = NULL;
            size_t i;
-           hdb_entry_ex *user2user_client = NULL;
+           HDB *user2user_db;
+           hdb_entry *user2user_client = NULL;
            krb5_boolean user2user_kdc_issued = FALSE;
+           char *tpn;
 
            if(b->additional_tickets == NULL ||
               b->additional_tickets->len == 0){
                ret = KRB5KDC_ERR_BADOPTION; /* ? */
                kdc_log(context, config, 4,
                        "No second ticket present in user-to-user request");
-               _kdc_audit_addreason((kdc_request_t)priv,
-                                    "No second ticket present in user-to-user request");
+               kdc_audit_addreason((kdc_request_t)priv,
+                                   "No second ticket present in user-to-user request");
                goto out;
            }
            t = &b->additional_tickets->val[0];
            if(!get_krbtgt_realm(&t->sname)){
                kdc_log(context, config, 4,
                        "Additional ticket is not a ticket-granting ticket");
-               _kdc_audit_addreason((kdc_request_t)priv,
-                                    "Additional ticket is not a ticket-granting ticket");
+               kdc_audit_addreason((kdc_request_t)priv,
+                                   "Additional ticket is not a ticket-granting ticket");
                ret = KRB5KDC_ERR_POLICY;
                goto out;
            }
@@ -1737,36 +1675,41 @@ server_lookup:
            }
            ret = _kdc_db_fetch(context, config, p,
                                HDB_F_GET_KRBTGT, kvno_ptr,
-                               NULL, &user2user_krbtgt);
+                               &user2user_krbtgtdb, &user2user_krbtgt);
            krb5_free_principal(context, p);
            if(ret){
                if (ret == HDB_ERR_NOENTRY)
                    ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
-               _kdc_audit_addreason((kdc_request_t)priv,
-                                    "User-to-user service principal (TGS) unknown");
+               kdc_audit_addreason((kdc_request_t)priv,
+                                   "User-to-user service principal (TGS) unknown");
+               krb5_xfree(tpn);
                goto out;
            }
-           ret = hdb_enctype2key(context, &user2user_krbtgt->entry, NULL,
+           ret = hdb_enctype2key(context, user2user_krbtgt, NULL,
                                  t->enc_part.etype, &uukey);
            if(ret){
                ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */
-               _kdc_audit_addreason((kdc_request_t)priv,
-                                    "User-to-user enctype not supported");
+               kdc_audit_addreason((kdc_request_t)priv,
+                                   "User-to-user enctype not supported");
+               krb5_xfree(tpn);
                goto out;
            }
            ret = krb5_decrypt_ticket(context, t, &uukey->key, &adtkt, 0);
            if(ret) {
-               _kdc_audit_addreason((kdc_request_t)priv,
-                                    "User-to-user TGT decrypt failure");
+               kdc_audit_addreason((kdc_request_t)priv,
+                                   "User-to-user TGT decrypt failure");
+               krb5_xfree(tpn);
                goto out;
            }
 
            ret = _kdc_verify_flags(context, config, &adtkt, tpn);
            if (ret) {
-               _kdc_audit_addreason((kdc_request_t)priv,
-                                    "User-to-user TGT expired or invalid");
+               kdc_audit_addreason((kdc_request_t)priv,
+                                   "User-to-user TGT expired or invalid");
+               krb5_xfree(tpn);
                goto out;
            }
+           krb5_xfree(tpn);
 
            /* Fetch the name from the TGT. */
            ret = _krb5_principalname2krb5_principal(context, &user2user_princ,
@@ -1786,7 +1729,7 @@ server_lookup:
             */
            ret = _kdc_db_fetch(context, config, user2user_princ,
                                HDB_F_GET_CLIENT | flags,
-                               NULL, NULL, &user2user_client);
+                               NULL, &user2user_db, &user2user_client);
            if (ret == HDB_ERR_NOENTRY)
                ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
            if (ret)
@@ -1807,7 +1750,7 @@ server_lookup:
                                  user2user_client,
                                  NULL);
            if (ret) {
-               _kdc_free_ent(context, user2user_client);
+               _kdc_free_ent(context, user2user_db, user2user_client);
                goto out;
            }
 
@@ -1815,14 +1758,14 @@ server_lookup:
             * Also check that the account is the same one specified in the
             * request.
             */
-           ret = check_client_matches_target_service(context,
-                                                     config,
-                                                     serverdb,
-                                                     server,
-                                                     user2user_client,
-                                                     user2user_princ);
+           ret = _kdc_check_client_matches_target_service(context,
+                                                          config,
+                                                          serverdb,
+                                                          priv->server,
+                                                          user2user_client,
+                                                          user2user_princ);
            if (ret) {
-               _kdc_free_ent(context, user2user_client);
+               _kdc_free_ent(context, user2user_db, user2user_client);
                goto out;
            }
 
@@ -1831,7 +1774,7 @@ server_lookup:
                                 user2user_client, user2user_krbtgt, user2user_krbtgt, user2user_krbtgt,
                                 &uukey->key, &priv->ticket_key->key, &adtkt,
                                 &user2user_kdc_issued, &user2user_pac, NULL, NULL);
-           _kdc_free_ent(context, user2user_client);
+           _kdc_free_ent(context, user2user_db, user2user_client);
            if (ret) {
                const char *msg = krb5_get_error_message(context, ret);
                kdc_log(context, config, 0,
@@ -1860,8 +1803,8 @@ server_lookup:
                        "Addition ticket have not matching etypes");
                krb5_clear_error_message(context);
                ret = KRB5KDC_ERR_ETYPE_NOSUPP;
-                _kdc_audit_addreason((kdc_request_t)priv,
-                                     "No matching enctypes for 2nd ticket");
+                kdc_audit_addreason((kdc_request_t)priv,
+                                    "No matching enctypes for 2nd ticket");
                goto out;
            }
            etype = b->etype.val[i];
@@ -1869,28 +1812,28 @@ server_lookup:
        } else {
            Key *skey;
 
-           ret = _kdc_find_etype(priv, krb5_principal_is_krbtgt(context, sp)
+           ret = _kdc_find_etype(priv, krb5_principal_is_krbtgt(context, priv->server_princ)
                                                             ? KFE_IS_TGS : 0,
                                  b->etype.val, b->etype.len, &etype, NULL,
                                  NULL);
            if(ret) {
                kdc_log(context, config, 4,
                        "Server (%s) has no support for etypes", spn);
-                _kdc_audit_addreason((kdc_request_t)priv,
-                                     "Enctype not supported");
+                kdc_audit_addreason((kdc_request_t)priv,
+                                    "Enctype not supported");
                goto out;
            }
-           ret = _kdc_get_preferred_key(context, config, server, spn,
+           ret = _kdc_get_preferred_key(context, config, priv->server, spn,
                                         NULL, &skey);
            if(ret) {
                kdc_log(context, config, 4,
                        "Server (%s) has no supported etypes", spn);
-                _kdc_audit_addreason((kdc_request_t)priv,
-                                     "Enctype not supported");
+                kdc_audit_addreason((kdc_request_t)priv,
+                                    "Enctype not supported");
                goto out;
            }
            ekey = &skey->key;
-           kvno = server->entry.kvno;
+           kvno = priv->server->kvno;
        }
 
        ret = krb5_generate_random_keyblock(context, etype, &sessionkey);
@@ -1911,17 +1854,17 @@ server_lookup:
      * the DB to possibly correct the case of the realm (Samba4 does
      * this) before the strcmp() 
      */
-    if (strcmp(krb5_principal_get_realm(context, server->entry.principal),
-              krb5_principal_get_realm(context, krbtgt_out->entry.principal)) != 0) {
+    if (strcmp(krb5_principal_get_realm(context, priv->server->principal),
+              krb5_principal_get_realm(context, krbtgt_out->principal)) != 0) {
        char *ktpn;
-       ret = krb5_unparse_name(context, krbtgt_out->entry.principal, &ktpn);
+       ret = krb5_unparse_name(context, krbtgt_out->principal, &ktpn);
        kdc_log(context, config, 4,
                "Request with wrong krbtgt: %s",
                (ret == 0) ? ktpn : "<unknown>");
        if(ret == 0)
            free(ktpn);
        ret = KRB5KRB_AP_ERR_NOT_US;
-        _kdc_audit_addreason((kdc_request_t)priv, "Request with wrong TGT");
+        kdc_audit_addreason((kdc_request_t)priv, "Request with wrong TGT");
        goto out;
     }
 
@@ -1930,38 +1873,39 @@ server_lookup:
     if (ret) {
        kdc_log(context, config, 4,
                    "Failed to find key for krbtgt PAC signature");
-        _kdc_audit_addreason((kdc_request_t)priv,
-                             "Failed to find key for krbtgt PAC signature");
+        kdc_audit_addreason((kdc_request_t)priv,
+                            "Failed to find key for krbtgt PAC signature");
        goto out;
     }
-    ret = hdb_enctype2key(context, &krbtgt_out->entry, NULL,
+    ret = hdb_enctype2key(context, krbtgt_out, NULL,
                          tkey_sign->key.keytype, &tkey_sign);
     if(ret) {
        kdc_log(context, config, 4,
                    "Failed to find key for krbtgt PAC signature");
-        _kdc_audit_addreason((kdc_request_t)priv,
-                             "Failed to find key for krbtgt PAC signature");
+        kdc_audit_addreason((kdc_request_t)priv,
+                            "Failed to find key for krbtgt PAC signature");
        goto out;
     }
 
-    if (_kdc_synthetic_princ_used_p(context, ticket))
+    if (_kdc_synthetic_princ_used_p(context, priv->ticket))
        flags |= HDB_F_SYNTHETIC_OK;
 
-    ret = _kdc_db_fetch_client(context, config, flags, cp, cpn, our_realm,
-                              &clientdb, &client);
+    ret = _kdc_db_fetch_client(context, config, flags, priv->client_princ,
+                              cpn, our_realm, &clientdb, &priv->client);
     if (ret)
        goto out;
     flags &= ~HDB_F_SYNTHETIC_OK;
-    priv->client = client;
-
-    heim_assert(priv->client_princ == NULL, "client_princ should be NULL for TGS");
+    priv->clientdb = clientdb;
 
-    ret = _kdc_check_pac(context, config, cp, NULL, client, server, krbtgt, krbtgt,
+    ret = _kdc_check_pac(context, config, priv->client_princ, NULL,
+                        priv->client, priv->server,
+                        priv->krbtgt, priv->krbtgt,
                         &priv->ticket_key->key, &priv->ticket_key->key, tgt,
-                        &kdc_issued, &priv->pac, &priv->client_princ, &priv->pac_attributes);
+                        &kdc_issued, &priv->pac, &priv->canon_client_princ,
+                        &priv->pac_attributes);
     if (ret) {
        const char *msg = krb5_get_error_message(context, ret);
-        _kdc_audit_addreason((kdc_request_t)priv, "PAC check failed");
+        kdc_audit_addreason((kdc_request_t)priv, "PAC check failed");
        kdc_log(context, config, 4,
                "Verify PAC failed for %s (%s) from %s with %s",
                spn, cpn, from, msg);
@@ -1973,352 +1917,13 @@ server_lookup:
      * Process request
      */
 
-    /* by default the tgt principal matches the client principal */
-    tp = cp;
-    tpn = cpn;
-
-    if (client) {
-       const PA_DATA *sdata;
-       int i = 0;
-
-       sdata = _kdc_find_padata(req, &i, KRB5_PADATA_FOR_USER);
-       if (sdata) {
-           krb5_crypto crypto;
-           krb5_data datack;
-           PA_S4U2Self self;
-           const char *str;
-
-           ret = decode_PA_S4U2Self(sdata->padata_value.data,
-                                    sdata->padata_value.length,
-                                    &self, NULL);
-           if (ret) {
-                _kdc_audit_addreason((kdc_request_t)priv,
-                                     "Failed to decode PA-S4U2Self");
-               kdc_log(context, config, 4, "Failed to decode PA-S4U2Self");
-               goto out;
-           }
-
-           if (!krb5_checksum_is_keyed(context, self.cksum.cksumtype)) {
-               free_PA_S4U2Self(&self);
-                _kdc_audit_addreason((kdc_request_t)priv,
-                                     "PA-S4U2Self with unkeyed checksum");
-               kdc_log(context, config, 4, "Reject PA-S4U2Self with unkeyed checksum");
-               ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
-               goto out;
-           }
-
-           ret = _krb5_s4u2self_to_checksumdata(context, &self, &datack);
-           if (ret)
-               goto out;
-
-           ret = krb5_crypto_init(context, &tgt->key, 0, &crypto);
-           if (ret) {
-               const char *msg = krb5_get_error_message(context, ret);
-               free_PA_S4U2Self(&self);
-               krb5_data_free(&datack);
-               kdc_log(context, config, 4, "krb5_crypto_init failed: %s", msg);
-               krb5_free_error_message(context, msg);
-               goto out;
-           }
-
-           /* Allow HMAC_MD5 checksum with any key type */
-           if (self.cksum.cksumtype == CKSUMTYPE_HMAC_MD5) {
-               struct krb5_crypto_iov iov;
-               unsigned char csdata[16];
-               Checksum cs;
-
-               cs.checksum.length = sizeof(csdata);
-               cs.checksum.data = &csdata;
-
-               iov.data.data = datack.data;
-               iov.data.length = datack.length;
-               iov.flags = KRB5_CRYPTO_TYPE_DATA;
-
-               ret = _krb5_HMAC_MD5_checksum(context, NULL, &crypto->key,
-                                             KRB5_KU_OTHER_CKSUM, &iov, 1,
-                                             &cs);
-               if (ret == 0 &&
-                   krb5_data_ct_cmp(&cs.checksum, &self.cksum.checksum) != 0)
-                   ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
-           }
-           else {
-               ret = _kdc_verify_checksum(context,
-                                          crypto,
-                                          KRB5_KU_OTHER_CKSUM,
-                                          &datack,
-                                          &self.cksum);
-           }
-           krb5_data_free(&datack);
-           krb5_crypto_destroy(context, crypto);
-           if (ret) {
-               const char *msg = krb5_get_error_message(context, ret);
-               free_PA_S4U2Self(&self);
-                _kdc_audit_addreason((kdc_request_t)priv,
-                                     "S4U2Self checksum failed");
-               kdc_log(context, config, 4,
-                       "krb5_verify_checksum failed for S4U2Self: %s", msg);
-               krb5_free_error_message(context, msg);
-               goto out;
-           }
-
-           ret = _krb5_principalname2krb5_principal(context,
-                                                    &tp,
-                                                    self.name,
-                                                    self.realm);
-           free_PA_S4U2Self(&self);
-           if (ret)
-               goto out;
-
-           ret = krb5_unparse_name(context, tp, &tpn);
-           if (ret)
-               goto out;
-
-            /*
-             * Note no HDB_F_SYNTHETIC_OK -- impersonating non-existent clients
-             * is probably not desirable!
-             */
-           ret = _kdc_db_fetch(context, config, tp, HDB_F_GET_CLIENT | flags,
-                               NULL, &s4u2self_impersonated_clientdb,
-                               &s4u2self_impersonated_client);
-           if (ret) {
-               const char *msg;
-
-               /*
-                * If the client belongs to the same realm as our krbtgt, it
-                * should exist in the local database.
-                *
-                */
-
-               if (ret == HDB_ERR_NOENTRY)
-                   ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
-               msg = krb5_get_error_message(context, ret);
-                _kdc_audit_addreason((kdc_request_t)priv,
-                                     "S4U2Self principal to impersonate not found");
-               kdc_log(context, config, 2,
-                       "S4U2Self principal to impersonate %s not found in database: %s",
-                       tpn, msg);
-               krb5_free_error_message(context, msg);
-               goto out;
-           }
-
-           /* Ignore require_pwchange and pw_end attributes (as Windows does),
-            * since S4U2Self is not password authentication. */
-           s4u2self_impersonated_client->entry.flags.require_pwchange = FALSE;
-           free(s4u2self_impersonated_client->entry.pw_end);
-           s4u2self_impersonated_client->entry.pw_end = NULL;
-
-           ret = kdc_check_flags(priv, FALSE, s4u2self_impersonated_client, priv->server);
-           if (ret)
-               goto out; /* kdc_check_flags() calls _kdc_audit_addreason() */
-
-           /* If we were about to put a PAC into the ticket, we better fix it to be the right PAC */
-           krb5_pac_free(context, priv->pac);
-           priv->pac = NULL;
-
-           ret = _kdc_pac_generate(context,
-                                   s4u2self_impersonated_client,
-                                   server,
-                                   NULL,
-                                   KRB5_PAC_WAS_GIVEN_IMPLICITLY,
-                                   &priv->pac);
-           if (ret) {
-               kdc_log(context, config, 4, "PAC generation failed for -- %s", tpn);
-               goto out;
-           }
-
-           /*
-            * Check that service doing the impersonating is
-            * requesting a ticket to it-self.
-            */
-           ret = check_client_matches_target_service(context,
-                                                     config,
-                                                     clientdb,
-                                                     client,
-                                                     server,
-                                                     sp);
-           if (ret) {
-               kdc_log(context, config, 4, "S4U2Self: %s is not allowed "
-                       "to impersonate to service "
-                       "(tried for user %s to service %s)",
-                       cpn, tpn, spn);
-               goto out;
-           }
-
-           /*
-            * If the service isn't trusted for authentication to
-            * delegation or if the impersonate client is disallowed
-            * forwardable, remove the forwardable flag.
-            */
-
-           if (client->entry.flags.trusted_for_delegation &&
-               s4u2self_impersonated_client->entry.flags.forwardable) {
-               str = "[forwardable]";
-           } else {
-               b->kdc_options.forwardable = 0;
-               str = "";
-           }
-           kdc_log(context, config, 4, "s4u2self %s impersonating %s to "
-                   "service %s %s", cpn, tpn, spn, str);
-       }
-    }
-
     /*
-     * Constrained delegation
+     * Services for User: protocol transition and constrained delegation
      */
 
-    if (client != NULL
-       && b->additional_tickets != NULL
-       && b->additional_tickets->len != 0
-       && b->kdc_options.cname_in_addl_tkt
-       && b->kdc_options.enc_tkt_in_skey == 0)
-    {
-       hdb_entry_ex *adclient = NULL;
-       krb5_boolean ad_kdc_issued = FALSE;
-       Key *clientkey;
-       Ticket *t;
-
-       /*
-        * We require that the service's krbtgt has a PAC.
-        */
-       if (priv->pac == NULL) {
-           ret = KRB5KDC_ERR_BADOPTION;
-           _kdc_audit_addreason((kdc_request_t)priv, "Missing PAC");
-           kdc_log(context, config, 4,
-                   "Constrained delegation without PAC, %s/%s",
-                   cpn, spn);
-           goto out;
-       }
-
-       krb5_pac_free(context, priv->pac);
-       priv->pac = NULL;
-
-       krb5_free_principal(context, priv->client_princ);
-       priv->client_princ = NULL;
-
-       t = &b->additional_tickets->val[0];
-
-       ret = hdb_enctype2key(context, &client->entry,
-                             hdb_kvno2keys(context, &client->entry,
-                                           t->enc_part.kvno ? * t->enc_part.kvno : 0),
-                             t->enc_part.etype, &clientkey);
-       if(ret){
-           ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */
-           goto out;
-       }
-
-       ret = krb5_decrypt_ticket(context, t, &clientkey->key, &adtkt, 0);
-       if (ret) {
-            _kdc_audit_addreason((kdc_request_t)priv,
-                                 "Failed to decrypt constrained delegation ticket");
-           kdc_log(context, config, 4,
-                   "failed to decrypt ticket for "
-                   "constrained delegation from %s to %s ", cpn, spn);
-           goto out;
-       }
-
-       ret = _krb5_principalname2krb5_principal(context,
-                                                &tp,
-                                                adtkt.cname,
-                                                adtkt.crealm);
-       if (ret)
-           goto out;
-
-       ret = krb5_unparse_name(context, tp, &tpn);
-       if (ret)
-           goto out;
-
-        _kdc_audit_addkv((kdc_request_t)priv, 0, "impersonatee", "%s", tpn);
-
-       ret = _krb5_principalname2krb5_principal(context,
-                                                &dp,
-                                                t->sname,
-                                                t->realm);
-       if (ret)
-           goto out;
-
-       ret = krb5_unparse_name(context, dp, &dpn);
-       if (ret)
-           goto out;
-
-       /* check that ticket is valid */
-       if (adtkt.flags.forwardable == 0) {
-            _kdc_audit_addreason((kdc_request_t)priv,
-                                 "Missing forwardable flag on ticket for constrained delegation");
-           kdc_log(context, config, 4,
-                   "Missing forwardable flag on ticket for "
-                   "constrained delegation from %s (%s) as %s to %s ",
-                   cpn, dpn, tpn, spn);
-           ret = KRB5KDC_ERR_BADOPTION;
-           goto out;
-       }
-
-       ret = check_constrained_delegation(context, config, clientdb,
-                                          client, server, sp);
-       if (ret) {
-            _kdc_audit_addreason((kdc_request_t)priv,
-                                 "Constrained delegation not allowed");
-           kdc_log(context, config, 4,
-                   "constrained delegation from %s (%s) as %s to %s not allowed",
-                   cpn, dpn, tpn, spn);
-           goto out;
-       }
-
-       ret = _kdc_verify_flags(context, config, &adtkt, tpn);
-       if (ret) {
-            _kdc_audit_addreason((kdc_request_t)priv,
-                                 "Constrained delegation ticket expired or invalid");
-           goto out;
-       }
-
-       /* Try lookup the delegated client in DB */
-       ret = _kdc_db_fetch_client(context, config, flags, tp, tpn, our_realm,
-                                  NULL, &adclient);
-       if (ret)
-           goto out;
-
-       if (adclient != NULL) {
-           ret = kdc_check_flags(priv, FALSE, adclient, priv->server);
-           if (ret) {
-               _kdc_free_ent(context, adclient);
-               goto out;
-           }
-       }
-
-       /*
-        * TODO: pass in t->sname and t->realm and build
-        * a S4U_DELEGATION_INFO blob to the PAC.
-        */
-       ret = _kdc_check_pac(context, config, tp, dp, adclient, server, krbtgt, client,
-                            &clientkey->key, &priv->ticket_key->key, &adtkt,
-                            &ad_kdc_issued, &priv->pac, &priv->client_princ, &priv->pac_attributes);
-       if (adclient)
-           _kdc_free_ent(context, adclient);
-       if (ret) {
-           const char *msg = krb5_get_error_message(context, ret);
-            _kdc_audit_addreason((kdc_request_t)priv,
-                                 "Constrained delegation ticket PAC check failed");
-           kdc_log(context, config, 4,
-                   "Verify delegated PAC failed to %s for client"
-                   "%s (%s) as %s from %s with %s",
-                   spn, cpn, dpn, tpn, from, msg);
-           krb5_free_error_message(context, msg);
-           goto out;
-       }
-
-       if (priv->pac == NULL || !ad_kdc_issued) {
-           ret = KRB5KDC_ERR_BADOPTION;
-           kdc_log(context, config, 4,
-                   "Ticket not signed with PAC; service %s failed for "
-                   "for delegation to %s for client %s (%s) from %s; (%s).",
-                   spn, tpn, dpn, cpn, from, priv->pac ? "Ticket unsigned" : "No PAC");
-            _kdc_audit_addreason((kdc_request_t)priv,
-                                 "Constrained delegation ticket not signed");
-           goto out;
-       }
-
-       kdc_log(context, config, 4, "constrained delegation for %s "
-               "from %s (%s) to %s", tpn, cpn, dpn, spn);
-    }
+    ret = _kdc_validate_services_for_user(priv);
+    if (ret)
+       goto out;
 
     /*
      * Check flags
@@ -2330,9 +1935,9 @@ server_lookup:
 
     if((b->kdc_options.validate || b->kdc_options.renew) &&
        !krb5_principal_compare(context,
-                              krbtgt->entry.principal,
-                              server->entry.principal)){
-        _kdc_audit_addreason((kdc_request_t)priv, "Inconsistent request");
+                              priv->krbtgt->principal,
+                              priv->server->principal)){
+        kdc_audit_addreason((kdc_request_t)priv, "Inconsistent request");
        kdc_log(context, config, 4, "Inconsistent request.");
        ret = KRB5KDC_ERR_SERVER_NOMATCH;
        goto out;
@@ -2342,12 +1947,12 @@ server_lookup:
     if (!_kdc_check_addresses(priv, tgt->caddr, from_addr)) {
         if (config->check_ticket_addresses) {
             ret = KRB5KRB_AP_ERR_BADADDR;
-            _kdc_audit_addkv((kdc_request_t)priv, 0, "wrongaddr", "yes");
+            kdc_audit_setkv_bool((kdc_request_t)priv, "wrongaddr", TRUE);
             kdc_log(context, config, 4, "Request from wrong address");
-            _kdc_audit_addreason((kdc_request_t)priv, "Request from wrong address");
+            kdc_audit_addreason((kdc_request_t)priv, "Request from wrong address");
             goto out;
         } else if (config->warn_ticket_addresses) {
-            _kdc_audit_addkv((kdc_request_t)priv, 0, "wrongaddr", "yes");
+            kdc_audit_setkv_bool((kdc_request_t)priv, "wrongaddr", TRUE);
         }
     }
 
@@ -2377,7 +1982,7 @@ server_lookup:
                                    NULL, s, &pa.padata_value);
        krb5_crypto_destroy(context, crypto);
        if (ret) {
-            _kdc_audit_addreason((kdc_request_t)priv, "Referral build failed");
+            kdc_audit_addreason((kdc_request_t)priv, "Referral build failed");
            kdc_log(context, config, 4,
                    "Failed building server referral");
            goto out;
@@ -2402,7 +2007,7 @@ server_lookup:
      */
 
     if (kdc_issued &&
-       !krb5_principal_is_krbtgt(context, server->entry.principal)) {
+       !krb5_principal_is_krbtgt(context, priv->server->principal)) {
 
        /* Validate armor TGT before potentially including device claims */
        if (priv->armor_ticket) {
@@ -2419,54 +2024,35 @@ server_lookup:
      * read-only-dc identifier, we need to embed it in the PAC KDC signatures.
      */
 
-    rodc_id = krbtgt_out->entry.kvno >> 16;
+    rodc_id = krbtgt_out->kvno >> 16;
 
     /*
      *
      */
 
     ret = tgs_make_reply(priv,
-                        tp,
                         tgt,
                         ekey,
                         &tkey_sign->key,
                         &sessionkey,
                         kvno,
                         *auth_data,
-                        server,
-                        rsp,
-                        client,
-                        cp,
                          tgt_realm,
                         rodc_id,
                         add_ticket_sig);
 
 out:
     free(user2user_name);
-    if (tpn != cpn)
-           free(tpn);
-    free(dpn);
     free(krbtgt_out_n);
     _krb5_free_capath(context, capath);
 
     krb5_free_keyblock_contents(context, &sessionkey);
     if(krbtgt_out)
-       _kdc_free_ent(context, krbtgt_out);
-    if(server)
-       _kdc_free_ent(context, server);
-    if(client)
-       _kdc_free_ent(context, client);
-    if(s4u2self_impersonated_client)
-       _kdc_free_ent(context, s4u2self_impersonated_client);
+       _kdc_free_ent(context, krbtgt_outdb, krbtgt_out);
     if(user2user_krbtgt)
-       _kdc_free_ent(context, user2user_krbtgt);
+       _kdc_free_ent(context, user2user_krbtgtdb, user2user_krbtgt);
 
     krb5_free_principal(context, user2user_princ);
-    if (tp && tp != cp)
-       krb5_free_principal(context, tp);
-    krb5_free_principal(context, cp);
-    krb5_free_principal(context, dp);
-    krb5_free_principal(context, sp);
     krb5_free_principal(context, krbtgt_out_principal);
     free(ref_realm);
 
@@ -2494,9 +2080,6 @@ _kdc_tgs_rep(astgs_request_t r)
     krb5_error_code ret;
     int i = 0;
     const PA_DATA *tgs_req, *pa;
-
-    hdb_entry_ex *krbtgt = NULL;
-    krb5_ticket *ticket = NULL;
     krb5_enctype krbtgt_etype = ETYPE_NULL;
 
     time_t *csec = NULL;
@@ -2529,9 +2112,7 @@ _kdc_tgs_rep(astgs_request_t r)
        goto out;
     }
     ret = tgs_parse_request(r, tgs_req,
-                           &krbtgt,
                            &krbtgt_etype,
-                           &ticket,
                            from, from_addr,
                            &csec, &cusec,
                            &auth_data);
@@ -2557,9 +2138,7 @@ _kdc_tgs_rep(astgs_request_t r)
     }
 
     ret = tgs_build_reply(r,
-                         krbtgt,
                          krbtgt_etype,
-                         ticket,
                          &auth_data,
                          from_addr);
     if (ret) {
@@ -2576,6 +2155,9 @@ _kdc_tgs_rep(astgs_request_t r)
     }
 
 out:
+    r->error_code = ret;
+    _kdc_audit_request(r);
+
     if(ret && ret != HDB_ERR_NOT_FOUND_HERE && data->data == NULL){
        METHOD_DATA error_method = { 0, NULL };
 
@@ -2584,9 +2166,9 @@ out:
                                 &error_method,
                                 r->armor_crypto,
                                 &req->req_body,
-                                r->ret = ret,
-                                ticket != NULL ? ticket->client : NULL,
-                                ticket != NULL ? ticket->server : NULL,
+                                r->error_code,
+                                r->client_princ ? r->client_princ :(r->ticket != NULL ? r->ticket->client : NULL),
+                                r->server_princ ? r->server_princ :(r->ticket != NULL ? r->ticket->server : NULL),
                                 csec, cusec,
                                 data);
        free_METHOD_DATA(&error_method);
@@ -2609,9 +2191,9 @@ out:
     }
     free_EncryptionKey(&r->et.key);
 
-    if (r->client_princ) {
-       krb5_free_principal(r->context, r->client_princ);
-       r->client_princ = NULL;
+    if (r->canon_client_princ) {
+       krb5_free_principal(r->context, r->canon_client_princ);
+       r->canon_client_princ = NULL;
     }
     if (r->armor_crypto) {
        krb5_crypto_destroy(r->context, r->armor_crypto);
@@ -2620,15 +2202,21 @@ out:
     if (r->armor_ticket)
        krb5_free_ticket(r->context, r->armor_ticket);
     if (r->armor_server)
-       _kdc_free_ent(r->context, r->armor_server);
+       _kdc_free_ent(r->context, r->armor_serverdb, r->armor_server);
     krb5_free_keyblock_contents(r->context, &r->reply_key);
     krb5_free_keyblock_contents(r->context, &r->strengthen_key);
 
-    if (ticket)
-       krb5_free_ticket(r->context, ticket);
-    if(krbtgt)
-       _kdc_free_ent(r->context, krbtgt);
-
+    if (r->ticket)
+       krb5_free_ticket(r->context, r->ticket);
+    if (r->krbtgt)
+       _kdc_free_ent(r->context, r->krbtgtdb, r->krbtgt);
+
+    if (r->client)
+       _kdc_free_ent(r->context, r->clientdb, r->client);
+    krb5_free_principal(r->context, r->client_princ);
+    if (r->server)
+       _kdc_free_ent(r->context, r->serverdb, r->server);
+    krb5_free_principal(r->context, r->server_princ);
     _kdc_free_fast_state(&r->fast);
     krb5_pac_free(r->context, r->pac);
 
index bba2b11d0f0dd0caafb7ba9d1b289f2006e5ad1b..6ec1a548aca6e41068a1ec357b77e4676151abf9 100644 (file)
@@ -131,6 +131,8 @@ main(int argc, char **argv)
            krb5_string_to_key_salt(context, enctype, buf, salt, &key);
        }
        ret = hdb_add_master_key(context, &key, &mkey);
+        if (ret)
+            krb5_err(context, 1, ret, "hdb_add_master_key");
 
        krb5_free_keyblock_contents(context, &key);
 
index bc3ca9deca6bed897e23ac6c9068c23fdc4c7266..6efd94e3a12dddefd1f0fba1b27831e872a90311 100644 (file)
@@ -157,9 +157,11 @@ verify_req_hash(krb5_context context,
     }
 
     HMAC_CTX_init(&ctx);
-    HMAC_Init_ex(&ctx,
-                 key->keyvalue.data, key->keyvalue.length,
-                 EVP_sha1(), NULL);
+    if (HMAC_Init_ex(&ctx, key->keyvalue.data, key->keyvalue.length,
+                     EVP_sha1(), NULL) == 0) {
+        HMAC_CTX_cleanup(&ctx);
+        return krb5_enomem(context);
+    }
     if (sizeof(digest) != HMAC_size(&ctx))
         krb5_abortx(context, "runtime error, hmac buffer wrong size in kx509");
     HMAC_Update(&ctx, version_2_0, sizeof(version_2_0));
@@ -186,14 +188,17 @@ calculate_reply_hash(krb5_context context,
                      krb5_keyblock *key,
                      Kx509Response *rep)
 {
-    krb5_error_code ret;
+    krb5_error_code ret = 0;
     HMAC_CTX ctx;
 
     HMAC_CTX_init(&ctx);
 
-    HMAC_Init_ex(&ctx, key->keyvalue.data, key->keyvalue.length,
-                 EVP_sha1(), NULL);
-    ret = krb5_data_alloc(rep->hash, HMAC_size(&ctx));
+    if (HMAC_Init_ex(&ctx, key->keyvalue.data, key->keyvalue.length,
+                     EVP_sha1(), NULL) == 0)
+        ret = krb5_enomem(context);
+
+    if (ret == 0)
+        ret = krb5_data_alloc(rep->hash, HMAC_size(&ctx));
     if (ret) {
         HMAC_CTX_cleanup(&ctx);
         return krb5_enomem(context);
@@ -248,7 +253,8 @@ is_local_realm(krb5_context context,
 {
     krb5_error_code ret;
     krb5_principal tgs;
-    hdb_entry_ex *ent = NULL;
+    HDB *db;
+    hdb_entry *ent = NULL;
 
     ret = krb5_make_principal(context, &tgs, realm, KRB5_TGS_NAME, realm,
                               NULL);
@@ -256,9 +262,9 @@ is_local_realm(krb5_context context,
         return ret;
     if (ret == 0)
         ret = _kdc_db_fetch(context, reqctx->config, tgs, HDB_F_GET_KRBTGT,
-                            NULL, NULL, &ent);
+                            NULL, &db, &ent);
     if (ent)
-        _kdc_free_ent(context, ent);
+        _kdc_free_ent(context, db, ent);
     krb5_free_principal(context, tgs);
     if (ret == HDB_ERR_NOENTRY || ret == HDB_ERR_NOT_FOUND_HERE)
         return KRB5KRB_AP_ERR_NOT_US;
@@ -299,8 +305,8 @@ kdc_kx509_verify_service_principal(krb5_context context,
                KRB5_TGS_NAME) == 0) {
         const char *r = krb5_principal_get_comp_string(context, sprincipal, 1);
         if ((ret = is_local_realm(context, reqctx, r)))
-            _kdc_audit_addreason((kdc_request_t)reqctx,
-                                 "Client used wrong krbtgt for kx509");
+            kdc_audit_addreason((kdc_request_t)reqctx,
+                                "Client used wrong krbtgt for kx509");
         goto out;
     }
 
@@ -309,8 +315,8 @@ kdc_kx509_verify_service_principal(krb5_context context,
     if (ret != 0) {
         ret = errno;
         kdc_log(context, reqctx->config, 0, "Failed to get local hostname");
-        _kdc_audit_addreason((kdc_request_t)reqctx,
-                             "Failed to get local hostname");
+        kdc_audit_addreason((kdc_request_t)reqctx,
+                            "Failed to get local hostname");
         return ret;
     }
     localhost[sizeof(localhost) - 1] = '\0';
@@ -329,8 +335,8 @@ err:
         goto out;
 
     ret = KRB5KDC_ERR_SERVER_NOMATCH;
-    _kdc_audit_addreason((kdc_request_t)reqctx, "Client used wrong kx509 "
-                         "service principal (expected %s)", expected);
+    kdc_audit_addreason((kdc_request_t)reqctx, "Client used wrong kx509 "
+                        "service principal (expected %s)", expected);
 
 out:
     krb5_xfree(expected);
@@ -394,7 +400,7 @@ mk_error_response(krb5_context context,
         }
 
         va_start(ap, fmt);
-        _kdc_audit_vaddreason((kdc_request_t)reqctx, fmt, ap);
+        kdc_audit_vaddreason((kdc_request_t)reqctx, fmt, ap);
         va_end(ap);
     }
 
@@ -536,12 +542,13 @@ update_csr(krb5_context context, kx509_req_context reqctx, Extensions *exts)
         }
     }
     if (ret) {
+       const char *emsg = krb5_get_error_message(context, ret);
         kdc_log(context, reqctx->config, 1,
-                "Error handling requested extensions: %s",
-                krb5_get_error_message(context, ret));
-        _kdc_audit_addreason((kdc_request_t)reqctx,
-                             "Error handling requested extensions: %s",
-                             krb5_get_error_message(context, ret));
+                "Error handling requested extensions: %s", emsg);
+        kdc_audit_addreason((kdc_request_t)reqctx,
+                            "Error handling requested extensions: %s",
+                            emsg);
+       krb5_free_error_message(context, emsg);
     }
     return ret;
 }
@@ -574,7 +581,7 @@ get_csr(krb5_context context, kx509_req_context reqctx)
          */
         if (ret == 0)
             return update_csr(context, reqctx, reqctx->csr_plus.exts);
-        _kdc_audit_addreason((kdc_request_t)reqctx, "Invalid CSR");
+        kdc_audit_addreason((kdc_request_t)reqctx, "Invalid CSR");
         return ret;
     }
     reqctx->send_chain = 0;
@@ -582,8 +589,8 @@ get_csr(krb5_context context, kx509_req_context reqctx)
 
     /* Check if proof of possession is required by configuration */
     if (!get_bool_param(context, FALSE, reqctx->realm, "require_csr")) {
-        _kdc_audit_addreason((kdc_request_t)reqctx,
-                             "CSRs required but client did not send one");
+        kdc_audit_addreason((kdc_request_t)reqctx,
+                            "CSRs required but client did not send one");
         krb5_set_error_message(context, KX509_STATUS_CLIENT_USE_CSR,
                                "CSRs required but kx509 client did not send "
                                "one");
@@ -601,14 +608,14 @@ get_csr(krb5_context context, kx509_req_context reqctx)
     /* Not an RSAPublicKey or garbage follows it */
     if (ret == 0) {
         ret = KRB5KDC_ERR_NULL_KEY;
-        _kdc_audit_addreason((kdc_request_t)reqctx,
-                             "Request has garbage after key");
+        kdc_audit_addreason((kdc_request_t)reqctx,
+                            "Request has garbage after key");
         krb5_set_error_message(context, ret, "Request has garbage after key");
         return ret;
     }
 
-    _kdc_audit_addreason((kdc_request_t)reqctx,
-                         "Could not decode CSR or RSA subject public key");
+    kdc_audit_addreason((kdc_request_t)reqctx,
+                        "Could not decode CSR or RSA subject public key");
     krb5_set_error_message(context, ret,
                            "Could not decode CSR or RSA subject public key");
     return ret;
@@ -668,7 +675,7 @@ check_authz(krb5_context context,
     ret = kdc_authorize_csr(context, reqctx->config->app, reqctx->csr,
                             cprincipal);
     if (ret == 0) {
-        _kdc_audit_addkv((kdc_request_t)reqctx, 0, "authorized", "true");
+        kdc_audit_setkv_bool((kdc_request_t)reqctx, "authorized", TRUE);
 
         ret = hx509_request_get_san(reqctx->csr, 0, &san_type, &s);
         if (ret == 0) {
@@ -685,20 +692,19 @@ check_authz(krb5_context context,
             case HX509_SAN_TYPE_MS_UPN: san_type_s = "ms-UPN"; break;
             default: san_type_s = "unknown"; break;
             }
-            _kdc_audit_addkv((kdc_request_t)reqctx, 0, "san0_type", "%s",
-                             san_type_s);
-            _kdc_audit_addkv((kdc_request_t)reqctx, 0, "san0", "%s", s);
-            free(s);
+            kdc_audit_addkv((kdc_request_t)reqctx, 0, "san0_type", "%s",
+                            san_type_s);
+            kdc_audit_addkv((kdc_request_t)reqctx, 0, "san0", "%s", s);
         }
+       frees(&s);
         ret = hx509_request_get_eku(reqctx->csr, 0, &s);
-        if (ret == 0) {
-            _kdc_audit_addkv((kdc_request_t)reqctx, 0, "eku0", "%s", s);
-            free(s);
-        }
+        if (ret == 0)
+            kdc_audit_addkv((kdc_request_t)reqctx, 0, "eku0", "%s", s);
+       free(s);
         return 0;
     }
     if (ret != KRB5_PLUGIN_NO_HANDLE) {
-        _kdc_audit_addreason((kdc_request_t)reqctx,
+        kdc_audit_addreason((kdc_request_t)reqctx,
                              "Requested extensions rejected by plugin");
         return ret;
     }
@@ -718,27 +724,27 @@ check_authz(krb5_context context,
             if (ncomp != 2 || strcasecmp(comp1, s) != 0 ||
                 strchr(s, '.') == NULL ||
                 !check_authz_svc_ok(context, comp0)) {
-                _kdc_audit_addreason((kdc_request_t)reqctx,
-                                     "Requested extensions rejected by "
-                                     "default policy (dNSName SAN "
-                                     "does not match client)");
+                kdc_audit_addreason((kdc_request_t)reqctx,
+                                    "Requested extensions rejected by "
+                                    "default policy (dNSName SAN "
+                                    "does not match client)");
                 goto eacces;
             }
             break;
         case HX509_SAN_TYPE_PKINIT:
             if (strcmp(cprinc, s) != 0) {
-                _kdc_audit_addreason((kdc_request_t)reqctx,
-                                     "Requested extensions rejected by "
-                                     "default policy (PKINIT SAN "
-                                     "does not match client)");
+                kdc_audit_addreason((kdc_request_t)reqctx,
+                                    "Requested extensions rejected by "
+                                    "default policy (PKINIT SAN "
+                                    "does not match client)");
                 goto eacces;
             }
             break;
         default:
-            _kdc_audit_addreason((kdc_request_t)reqctx,
-                                 "Requested extensions rejected by "
-                                 "default policy (non-default SAN "
-                                 "requested)");
+            kdc_audit_addreason((kdc_request_t)reqctx,
+                                "Requested extensions rejected by "
+                                "default policy (non-default SAN "
+                                "requested)");
             goto eacces;
         }
     }
@@ -766,8 +772,8 @@ check_authz(krb5_context context,
         }
         der_free_oid(&oid);
         if (k == sizeof(eku_whitelist)/sizeof(eku_whitelist[0])) {
-            _kdc_audit_addreason((kdc_request_t)reqctx,
-                                 "Requested EKU rejected by default policy");
+            kdc_audit_addreason((kdc_request_t)reqctx,
+                                "Requested EKU rejected by default policy");
             goto eacces;
         }
     }
@@ -785,7 +791,8 @@ check_authz(krb5_context context,
     if (KeyUsage2int(ku) != (KeyUsage2int(ku) & KeyUsage2int(ku_allowed)))
         goto eacces;
 
-    _kdc_audit_addkv((kdc_request_t)reqctx, 0, "authorized", "true");
+    kdc_audit_setkv_bool((kdc_request_t)reqctx, "authorized", TRUE);
+    free(cprinc);
     return 0;
 
 eacces:
@@ -794,7 +801,7 @@ eacces:
 
 out:
     /* XXX Display error code */
-    _kdc_audit_addreason((kdc_request_t)reqctx,
+    kdc_audit_addreason((kdc_request_t)reqctx,
                          "Error handling requested extensions");
 out2:
     free(cprinc);
@@ -884,7 +891,7 @@ _kdc_do_kx509(kx509_req_context r)
          * possibly change the error code and message.
          */
         is_probe = 1;
-        _kdc_audit_addkv((kdc_request_t)r, 0, "probe", "unauthenticated");
+        kdc_audit_addkv((kdc_request_t)r, 0, "probe", "unauthenticated");
         ret = mk_error_response(r->context, r, 4, 0,
                                 "kx509 service is available");
         goto out;
@@ -933,7 +940,8 @@ _kdc_do_kx509(kx509_req_context r)
         goto out;
     }
 
-    ret = krb5_unparse_name(r->context, cprincipal, &r->cname);
+    if (ret == 0)
+       ret = krb5_unparse_name(r->context, cprincipal, &r->cname);
 
     /* Check that the service name is a valid kx509 service name */
     if (ret == 0)
@@ -966,7 +974,7 @@ _kdc_do_kx509(kx509_req_context r)
          * possibly change the error code and message.
          */
         is_probe = 1;
-        _kdc_audit_addkv((kdc_request_t)r, 0, "probe", "authenticated");
+        kdc_audit_addkv((kdc_request_t)r, 0, "probe", "authenticated");
         ret = mk_error_response(r->context, r, 4, 0,
                                 "kx509 authenticated probe request");
         goto out;
@@ -1041,14 +1049,14 @@ _kdc_do_kx509(kx509_req_context r)
     ret = encode_reply(r->context, r, &rep);
     if (ret)
         /* Can't send an error message either in this case, surely */
-        _kdc_audit_addreason((kdc_request_t)r, "Could not encode response");
+        kdc_audit_addreason((kdc_request_t)r, "Could not encode response");
 
 out:
     hx509_certs_free(&certs);
     if (ret == 0 && !is_probe)
-        _kdc_audit_addkv((kdc_request_t)r, 0, "cert_issued", "true");
+        kdc_audit_setkv_bool((kdc_request_t)r, "cert_issued", TRUE);
     else
-        _kdc_audit_addkv((kdc_request_t)r, 0, "cert_issued", "false");
+        kdc_audit_setkv_bool((kdc_request_t)r, "cert_issued", FALSE);
     if (r->ac)
         krb5_auth_con_free(r->context, r->ac);
     if (ticket)
index a4ed75bfb6a5151b3262b78d9a37496b881ecb9a..3cc929e6025b8da09edc7df0d0b24549ea34b5ea 100644 (file)
@@ -6,8 +6,9 @@ EXPORTS
        kdc_log_msg
        kdc_log_msg_va
        kdc_openlog
+       kdc_check_flags
        kdc_validate_token
-       krb5_kdc_windc_init
+       krb5_kdc_plugin_init
        krb5_kdc_get_config
        krb5_kdc_pkinit_config
        krb5_kdc_set_dbinfo
@@ -16,8 +17,80 @@ EXPORTS
        krb5_kdc_save_request
        krb5_kdc_update_time
        krb5_kdc_pk_initialize
-       _kdc_audit_addkv
-       _kdc_audit_addreason
-       _kdc_audit_vaddkv
-       _kdc_audit_vaddreason
+       kdc_request_set_attribute
+       kdc_request_get_attribute
+       kdc_request_copy_attribute
+       kdc_request_delete_attribute
+       kdc_request_add_encrypted_padata
+       kdc_request_add_pac_buffer
+       kdc_request_add_reply_padata
+       kdc_request_get_addr
+       kdc_request_get_canon_client_princ
+       kdc_request_get_client
+       kdc_request_get_clientdb
+       kdc_request_get_client_princ
+       kdc_request_get_context
+       kdc_request_get_config
+       kdc_request_get_cname
+       kdc_request_get_error_code
+       kdc_request_get_from
+       kdc_request_get_krbtgt
+       kdc_request_get_krbtgtdb
+       kdc_request_get_krbtgt_princ
+       kdc_request_get_pac
+       kdc_request_get_pac_attributes
+       kdc_request_get_rep
+       kdc_request_get_reply_key
+       kdc_request_get_req
+       kdc_request_get_request
+       kdc_request_get_server
+       kdc_request_get_serverdb
+       kdc_request_get_server_princ
+       kdc_request_get_sname
+       kdc_request_get_ticket
+       kdc_request_get_tv_end
+       kdc_request_get_tv_start
+       kdc_request_set_canon_client_princ
+       kdc_request_set_client_princ
+       kdc_request_set_cname
+       kdc_request_set_error_code
+       kdc_request_set_krbtgt_princ
+       kdc_request_set_pac
+       kdc_request_set_pac_attributes
+       kdc_request_set_rep
+       kdc_request_set_reply_key
+       kdc_request_set_server_princ
+       kdc_request_set_sname
+       kdc_audit_addkv
+       kdc_audit_addkv_number
+       kdc_audit_addkv_object
+       kdc_audit_addkv_timediff
+       kdc_audit_addaddrs
+       kdc_audit_addreason
+       kdc_audit_getkv
+       kdc_audit_setkv_bool
+       kdc_audit_setkv_number
+       kdc_audit_setkv_object
+       kdc_audit_vaddkv
+       kdc_audit_vaddreason
        _kdc_audit_trail
+
+       kdc_object_alloc
+       kdc_object_retain
+       kdc_object_release
+       kdc_bool_create
+       kdc_bool_get_value
+       kdc_array_iterate
+       kdc_array_get_length
+       kdc_array_get_value
+       kdc_array_copy_value
+       kdc_string_create
+       kdc_string_get_utf8
+       kdc_data_create
+       kdc_data_get_data
+       kdc_number_create
+       kdc_number_get_value
+
+       ; needed for digest-service
+       _kdc_db_fetch
+       _kdc_free_ent
index 895f1c9c6e4bea90570b3fee1e917f6b333703ce..bfb0f54ff899995060a03082e40ca79f70c68ec0 100644 (file)
@@ -35,7 +35,7 @@
 
 #include "kdc_locl.h"
 
-void
+KDC_LIB_FUNCTION void KDC_LIB_CALL
 kdc_openlog(krb5_context context,
            const char *service,
            krb5_kdc_configuration *config)
@@ -63,7 +63,7 @@ kdc_openlog(krb5_context context,
 #undef __attribute__
 #define __attribute__(X)
 
-char*
+KDC_LIB_FUNCTION char * KDC_LIB_CALL
 kdc_log_msg_va(krb5_context context,
               krb5_kdc_configuration *config,
               int level, const char *fmt, va_list ap)
@@ -74,7 +74,7 @@ kdc_log_msg_va(krb5_context context,
     return msg;
 }
 
-char*
+KDC_LIB_FUNCTION char * KDC_LIB_CALL
 kdc_log_msg(krb5_context context,
            krb5_kdc_configuration *config,
            int level, const char *fmt, ...)
@@ -88,7 +88,7 @@ kdc_log_msg(krb5_context context,
     return s;
 }
 
-void
+KDC_LIB_FUNCTION void KDC_LIB_CALL
 kdc_vlog(krb5_context context,
          krb5_kdc_configuration *config,
          int level, const char *fmt, va_list ap)
@@ -97,7 +97,7 @@ kdc_vlog(krb5_context context,
     free(kdc_log_msg_va(context, config, level, fmt, ap));
 }
 
-void
+KDC_LIB_FUNCTION void KDC_LIB_CALL
 kdc_log(krb5_context context,
        krb5_kdc_configuration *config,
        int level, const char *fmt, ...)
index e6a5c5c2340d2761777f4e988913efa9e9d5ccab..b48503d26a0e2c9d78cc6a6b9e41894c5d4dccf4 100644 (file)
@@ -60,18 +60,18 @@ synthesize_hdb_close(krb5_context context, struct HDB *db)
 }
 
 /*
- * Synthesize an HDB entry suitable for PKINIT and only PKINIT.
+ * Synthesize an HDB entry suitable for PKINIT and GSS preauth.
  */
 static krb5_error_code
 synthesize_client(krb5_context context,
                   krb5_kdc_configuration *config,
                   krb5_const_principal princ,
                   HDB **db,
-                  hdb_entry_ex **h)
+                  hdb_entry **h)
 {
     static HDB null_db;
     krb5_error_code ret;
-    hdb_entry_ex *e;
+    hdb_entry *e;
 
     /* Hope this works! */
     null_db.hdb_destroy = synthesize_hdb_close;
@@ -81,57 +81,57 @@ synthesize_client(krb5_context context,
 
     ret = (e = calloc(1, sizeof(*e))) ? 0 : krb5_enomem(context);
     if (ret == 0) {
-        e->entry.flags.client = 1;
-        e->entry.flags.immutable = 1;
-        e->entry.flags.virtual = 1;
-        e->entry.flags.synthetic = 1;
-        e->entry.flags.do_not_store = 1;
-        e->entry.kvno = 1;
-        e->entry.keys.len = 0;
-        e->entry.keys.val = NULL;
-        e->entry.created_by.time = time(NULL);
-        e->entry.modified_by = NULL;
-        e->entry.valid_start = NULL;
-        e->entry.valid_end = NULL;
-        e->entry.pw_end = NULL;
-        e->entry.etypes = NULL;
-        e->entry.generation = NULL;
-        e->entry.extensions = NULL;
+        e->flags.client = 1;
+        e->flags.immutable = 1;
+        e->flags.virtual = 1;
+        e->flags.synthetic = 1;
+        e->flags.do_not_store = 1;
+        e->kvno = 1;
+        e->keys.len = 0;
+        e->keys.val = NULL;
+        e->created_by.time = time(NULL);
+        e->modified_by = NULL;
+        e->valid_start = NULL;
+        e->valid_end = NULL;
+        e->pw_end = NULL;
+        e->etypes = NULL;
+        e->generation = NULL;
+        e->extensions = NULL;
     }
     if (ret == 0)
-        ret = (e->entry.max_renew = calloc(1, sizeof(*e->entry.max_renew))) ?
+        ret = (e->max_renew = calloc(1, sizeof(*e->max_renew))) ?
             0 : krb5_enomem(context);
     if (ret == 0)
-        ret = (e->entry.max_life = calloc(1, sizeof(*e->entry.max_life))) ?
+        ret = (e->max_life = calloc(1, sizeof(*e->max_life))) ?
             0 : krb5_enomem(context);
     if (ret == 0)
-        ret = krb5_copy_principal(context, princ, &e->entry.principal);
+        ret = krb5_copy_principal(context, princ, &e->principal);
     if (ret == 0)
-        ret = krb5_copy_principal(context, princ, &e->entry.created_by.principal);
+        ret = krb5_copy_principal(context, princ, &e->created_by.principal);
     if (ret == 0) {
         /*
          * We can't check OCSP in the TGS path, so we can't let tickets for
          * synthetic principals live very long.
          */
-        *(e->entry.max_renew) = config->synthetic_clients_max_renew;
-        *(e->entry.max_life) = config->synthetic_clients_max_life;
+        *(e->max_renew) = config->synthetic_clients_max_renew;
+        *(e->max_life) = config->synthetic_clients_max_life;
         *h = e;
-    } else {
-        hdb_free_entry(context, e);
+    } else if (e) {
+        hdb_free_entry(context, &null_db, e);
     }
     return ret;
 }
 
-krb5_error_code
+KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL
 _kdc_db_fetch(krb5_context context,
              krb5_kdc_configuration *config,
              krb5_const_principal principal,
              unsigned flags,
              krb5uint32 *kvno_ptr,
              HDB **db,
-             hdb_entry_ex **h)
+             hdb_entry **h)
 {
-    hdb_entry_ex *ent = NULL;
+    hdb_entry *ent = NULL;
     krb5_error_code ret = HDB_ERR_NOENTRY;
     int i;
     unsigned kvno = 0;
@@ -245,10 +245,10 @@ out:
     return ret;
 }
 
-void
-_kdc_free_ent(krb5_context context, hdb_entry_ex *ent)
+KDC_LIB_FUNCTION void KDC_LIB_CALL
+_kdc_free_ent(krb5_context context, HDB *db, hdb_entry *ent)
 {
-    hdb_free_entry (context, ent);
+    hdb_free_entry (context, db, ent);
     free (ent);
 }
 
@@ -260,7 +260,7 @@ _kdc_free_ent(krb5_context context, hdb_entry_ex *ent)
 krb5_error_code
 _kdc_get_preferred_key(krb5_context context,
                       krb5_kdc_configuration *config,
-                      hdb_entry_ex *h,
+                      hdb_entry *h,
                       const char *name,
                       krb5_enctype *enctype,
                       Key **key)
@@ -271,11 +271,11 @@ _kdc_get_preferred_key(krb5_context context,
     if (config->use_strongest_server_key) {
        const krb5_enctype *p = krb5_kerberos_enctypes(context);
 
-       for (i = 0; p[i] != (krb5_enctype)ETYPE_NULL; i++) {
+       for (i = 0; p[i] != ETYPE_NULL; i++) {
            if (krb5_enctype_valid(context, p[i]) != 0 &&
-               !_kdc_is_weak_exception(h->entry.principal, p[i]))
+               !_kdc_is_weak_exception(h->principal, p[i]))
                continue;
-           ret = hdb_enctype2key(context, &h->entry, NULL, p[i], key);
+           ret = hdb_enctype2key(context, h, NULL, p[i], key);
            if (ret != 0)
                continue;
            if (enctype != NULL)
@@ -285,12 +285,12 @@ _kdc_get_preferred_key(krb5_context context,
     } else {
        *key = NULL;
 
-       for (i = 0; i < h->entry.keys.len; i++) {
-           if (krb5_enctype_valid(context, h->entry.keys.val[i].key.keytype) != 0 &&
-               !_kdc_is_weak_exception(h->entry.principal, h->entry.keys.val[i].key.keytype))
+       for (i = 0; i < h->keys.len; i++) {
+           if (krb5_enctype_valid(context, h->keys.val[i].key.keytype) != 0 &&
+               !_kdc_is_weak_exception(h->principal, h->keys.val[i].key.keytype))
                continue;
-           ret = hdb_enctype2key(context, &h->entry, NULL,
-                                 h->entry.keys.val[i].key.keytype, key);
+           ret = hdb_enctype2key(context, h, NULL,
+                                 h->keys.val[i].key.keytype, key);
            if (ret != 0)
                continue;
            if (enctype != NULL)
@@ -336,3 +336,22 @@ _kdc_include_pac_p(astgs_request_t r)
 {
     return TRUE;
 }
+
+/*
+ * Notify the HDB backend and KDC plugin of the audited event.
+ */
+
+krb5_error_code
+_kdc_audit_request(astgs_request_t r)
+{
+    krb5_error_code ret;
+    struct HDB *hdb;
+
+    ret = _kdc_plugin_audit(r);
+    if (ret == 0 &&
+       (hdb = r->clientdb ? r->clientdb : r->config->db[0]) &&
+       hdb->hdb_audit)
+       ret = hdb->hdb_audit(r->context, hdb, r->client, (hdb_request_t)r);
+
+    return ret;
+}
index 3e4b47d7e1b9c4be41f55d7927f375435f72e71e..32cf5dc65cea002b04426657f602d3664fb0bb94 100644 (file)
@@ -146,7 +146,7 @@ mit_prop_dump(void *arg, const char *file)
     char *line = NULL;
     int lineno = 0;
     FILE *f;
-    struct hdb_entry_ex ent;
+    hdb_entry ent;
     struct prop_data *pd = arg;
     krb5_storage *sp = NULL;
     krb5_data kdb_ent;
@@ -202,14 +202,14 @@ mit_prop_dump(void *arg, const char *file)
         }
         ret = krb5_storage_to_data(sp, &kdb_ent);
         if (ret) break;
-        ret = _hdb_mdb_value2entry(pd->context, &kdb_ent, 0, &ent.entry);
+        ret = _hdb_mdb_value2entry(pd->context, &kdb_ent, 0, &ent);
         krb5_data_free(&kdb_ent);
         if (ret) {
             warnx("line: %d: failed to store; ignoring", lineno);
             continue;
         }
        ret = v5_prop(pd->context, NULL, &ent, arg);
-        hdb_free_entry(pd->context, &ent);
+        hdb_free_entry(pd->context, NULL, &ent); /* XXX */
         if (ret) break;
     }
 
diff --git a/third_party/heimdal/kdc/mssfu.c b/third_party/heimdal/kdc/mssfu.c
new file mode 100644 (file)
index 0000000..9e67aad
--- /dev/null
@@ -0,0 +1,568 @@
+/*
+ * Copyright (c) 1997-2008 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "kdc_locl.h"
+
+/*
+ * [MS-SFU] Kerberos Protocol Extensions:
+ * Service for User (S4U2Self) and Constrained Delegation Protocol (S4U2Proxy)
+ * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-sfu/
+ */
+
+/*
+ * Determine if constrained delegation is allowed from this client to this server
+ */
+
+static krb5_error_code
+check_constrained_delegation(krb5_context context,
+                            krb5_kdc_configuration *config,
+                            HDB *clientdb,
+                            hdb_entry *client,
+                            hdb_entry *server,
+                            krb5_const_principal target)
+{
+    const HDB_Ext_Constrained_delegation_acl *acl;
+    krb5_error_code ret;
+    size_t i;
+
+    /*
+     * constrained delegation (S4U2Proxy) only works within
+     * the same realm. We use the already canonicalized version
+     * of the principals here, while "target" is the principal
+     * provided by the client.
+     */
+    if (!krb5_realm_compare(context, client->principal, server->principal)) {
+       ret = KRB5KDC_ERR_BADOPTION;
+       kdc_log(context, config, 4,
+           "Bad request for constrained delegation");
+       return ret;
+    }
+
+    if (clientdb->hdb_check_constrained_delegation) {
+       ret = clientdb->hdb_check_constrained_delegation(context, clientdb, client, target);
+       if (ret == 0)
+           return 0;
+    } else {
+       /* if client delegates to itself, that ok */
+       if (krb5_principal_compare(context, client->principal, server->principal) == TRUE)
+           return 0;
+
+       ret = hdb_entry_get_ConstrainedDelegACL(client, &acl);
+       if (ret) {
+           krb5_clear_error_message(context);
+           return ret;
+       }
+
+       if (acl) {
+           for (i = 0; i < acl->len; i++) {
+               if (krb5_principal_compare(context, target, &acl->val[i]) == TRUE)
+                   return 0;
+           }
+       }
+       ret = KRB5KDC_ERR_BADOPTION;
+    }
+    kdc_log(context, config, 4,
+           "Bad request for constrained delegation");
+    return ret;
+}
+
+/*
+ * Validate a protocol transition (S4U2Self) request. If present and
+ * successfully validated then the client in the request structure
+ * will be replaced with the impersonated client.
+ */
+
+static krb5_error_code
+validate_protocol_transition(astgs_request_t r)
+{
+    krb5_error_code ret;
+    KDC_REQ_BODY *b = &r->req.req_body;
+    EncTicketPart *ticket = &r->ticket->ticket;
+    hdb_entry *s4u_client = NULL;
+    HDB *s4u_clientdb;
+    int flags = HDB_F_FOR_TGS_REQ;
+    krb5_principal s4u_client_name = NULL, s4u_canon_client_name = NULL;
+    krb5_pac s4u_pac = NULL;
+    const PA_DATA *sdata;
+    char *s4ucname = NULL;
+    int i = 0;
+    krb5_crypto crypto;
+    krb5_data datack;
+    PA_S4U2Self self;
+    const char *str;
+
+    if (r->client == NULL)
+       return 0;
+
+    sdata = _kdc_find_padata(&r->req, &i, KRB5_PADATA_FOR_USER);
+    if (sdata == NULL)
+       return 0;
+
+    memset(&self, 0, sizeof(self));
+
+    if (b->kdc_options.canonicalize)
+       flags |= HDB_F_CANON;
+
+    ret = decode_PA_S4U2Self(sdata->padata_value.data,
+                            sdata->padata_value.length,
+                            &self, NULL);
+    if (ret) {
+       kdc_audit_addreason((kdc_request_t)r,
+                           "Failed to decode PA-S4U2Self");
+       kdc_log(r->context, r->config, 4, "Failed to decode PA-S4U2Self");
+       goto out;
+    }
+
+    if (!krb5_checksum_is_keyed(r->context, self.cksum.cksumtype)) {
+       kdc_audit_addreason((kdc_request_t)r,
+                           "PA-S4U2Self with unkeyed checksum");
+       kdc_log(r->context, r->config, 4, "Reject PA-S4U2Self with unkeyed checksum");
+       ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
+       goto out;
+    }
+
+    ret = _krb5_s4u2self_to_checksumdata(r->context, &self, &datack);
+    if (ret)
+       goto out;
+
+    ret = krb5_crypto_init(r->context, &ticket->key, 0, &crypto);
+    if (ret) {
+       const char *msg = krb5_get_error_message(r->context, ret);
+       krb5_data_free(&datack);
+       kdc_log(r->context, r->config, 4, "krb5_crypto_init failed: %s", msg);
+       krb5_free_error_message(r->context, msg);
+       goto out;
+    }
+
+    /* Allow HMAC_MD5 checksum with any key type */
+    if (self.cksum.cksumtype == CKSUMTYPE_HMAC_MD5) {
+       struct krb5_crypto_iov iov;
+       unsigned char csdata[16];
+       Checksum cs;
+
+       cs.checksum.length = sizeof(csdata);
+       cs.checksum.data = &csdata;
+
+       iov.data.data = datack.data;
+       iov.data.length = datack.length;
+       iov.flags = KRB5_CRYPTO_TYPE_DATA;
+
+       ret = _krb5_HMAC_MD5_checksum(r->context, NULL, &crypto->key,
+                                     KRB5_KU_OTHER_CKSUM, &iov, 1,
+                                     &cs);
+       if (ret == 0 &&
+           krb5_data_ct_cmp(&cs.checksum, &self.cksum.checksum) != 0)
+           ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+    } else {
+       ret = _kdc_verify_checksum(r->context,
+                                  crypto,
+                                  KRB5_KU_OTHER_CKSUM,
+                                  &datack,
+                                  &self.cksum);
+    }
+    krb5_data_free(&datack);
+    krb5_crypto_destroy(r->context, crypto);
+    if (ret) {
+       const char *msg = krb5_get_error_message(r->context, ret);
+       kdc_audit_addreason((kdc_request_t)r,
+                           "S4U2Self checksum failed");
+       kdc_log(r->context, r->config, 4,
+               "krb5_verify_checksum failed for S4U2Self: %s", msg);
+       krb5_free_error_message(r->context, msg);
+       goto out;
+    }
+
+    ret = _krb5_principalname2krb5_principal(r->context,
+                                            &s4u_client_name,
+                                            self.name,
+                                            self.realm);
+    if (ret)
+       goto out;
+
+    ret = krb5_unparse_name(r->context, s4u_client_name, &s4ucname);
+    if (ret)
+       goto out;
+
+    /*
+     * Note no HDB_F_SYNTHETIC_OK -- impersonating non-existent clients
+     * is probably not desirable!
+     */
+    ret = _kdc_db_fetch(r->context, r->config, s4u_client_name,
+                       HDB_F_GET_CLIENT | flags, NULL,
+                       &s4u_clientdb, &s4u_client);
+    if (ret) {
+       const char *msg;
+
+       /*
+        * If the client belongs to the same realm as our krbtgt, it
+        * should exist in the local database.
+        *
+        */
+       if (ret == HDB_ERR_NOENTRY)
+           ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
+       msg = krb5_get_error_message(r->context, ret);
+       kdc_audit_addreason((kdc_request_t)r,
+                           "S4U2Self principal to impersonate not found");
+       kdc_log(r->context, r->config, 2,
+               "S4U2Self principal to impersonate %s not found in database: %s",
+               s4ucname, msg);
+       krb5_free_error_message(r->context, msg);
+       goto out;
+    }
+
+    /*
+     * Ignore require_pwchange and pw_end attributes (as Windows does),
+     * since S4U2Self is not password authentication.
+     */
+    s4u_client->flags.require_pwchange = FALSE;
+    free(s4u_client->pw_end);
+    s4u_client->pw_end = NULL;
+
+    ret = kdc_check_flags(r, FALSE, s4u_client, r->server);
+    if (ret)
+       goto out; /* kdc_check_flags() calls kdc_audit_addreason() */
+
+    ret = _kdc_pac_generate(r->context,
+                           r->config,
+                           s4u_client,
+                           r->server,
+                           NULL,
+                           KRB5_PAC_WAS_GIVEN_IMPLICITLY,
+                           &s4u_pac);
+    if (ret) {
+       kdc_log(r->context, r->config, 4, "PAC generation failed for -- %s", s4ucname);
+       goto out;
+    }
+
+    /*
+     * Check that service doing the impersonating is
+     * requesting a ticket to it-self.
+     */
+    ret = _kdc_check_client_matches_target_service(r->context,
+                                                  r->config,
+                                                  r->clientdb,
+                                                  r->client,
+                                                  r->server,
+                                                  r->server_princ);
+    if (ret) {
+       kdc_log(r->context, r->config, 4, "S4U2Self: %s is not allowed "
+               "to impersonate to service "
+                "(tried for user %s to service %s)",
+                r->cname, s4ucname, r->sname);
+       goto out;
+    }
+
+    ret = krb5_copy_principal(r->context, s4u_client->principal,
+                             &s4u_canon_client_name);
+    if (ret)
+       goto out;
+
+    /*
+     * If the service isn't trusted for authentication to
+     * delegation or if the impersonate client is disallowed
+     * forwardable, remove the forwardable flag.
+     */
+    if (r->client->flags.trusted_for_delegation &&
+       s4u_client->flags.forwardable) {
+       str = "[forwardable]";
+    } else {
+       b->kdc_options.forwardable = 0;
+       str = "";
+    }
+    kdc_log(r->context, r->config, 4, "s4u2self %s impersonating %s to "
+           "service %s %s", r->cname, s4ucname, r->sname, str);
+
+    /*
+     * Replace all client information in the request with the
+     * impersonated client. (The audit entry containing the original
+     * client name will have been created before this point.)
+     */
+    _kdc_request_set_cname_nocopy((kdc_request_t)r, &s4ucname);
+    _kdc_request_set_client_princ_nocopy(r, &s4u_client_name);
+
+    _kdc_free_ent(r->context, r->clientdb, r->client);
+    r->client = s4u_client;
+    s4u_client = NULL;
+    r->clientdb = s4u_clientdb;
+    s4u_clientdb = NULL;
+
+    _kdc_request_set_canon_client_princ_nocopy(r, &s4u_canon_client_name);
+    _kdc_request_set_pac_nocopy(r, &s4u_pac);
+
+out:
+    if (s4u_client)
+       _kdc_free_ent(r->context, s4u_clientdb, s4u_client);
+    krb5_free_principal(r->context, s4u_client_name);
+    krb5_xfree(s4ucname);
+    krb5_free_principal(r->context, s4u_canon_client_name);
+    krb5_pac_free(r->context, s4u_pac);
+
+    free_PA_S4U2Self(&self);
+
+    return ret;
+}
+
+/*
+ * Validate a constrained delegation (S4U2Proxy) request. If present
+ * and successfully validated then the client in the request structure
+ * will be replaced with the client from the evidence ticket.
+ */
+
+static krb5_error_code
+validate_constrained_delegation(astgs_request_t r)
+{
+    krb5_error_code ret;
+    KDC_REQ_BODY *b = &r->req.req_body;
+    int flags = HDB_F_FOR_TGS_REQ;
+    krb5_principal s4u_client_name = NULL, s4u_server_name = NULL;
+    krb5_principal s4u_canon_client_name = NULL;
+    krb5_pac s4u_pac = NULL;
+    uint64_t s4u_pac_attributes;
+    char *s4ucname = NULL, *s4usname = NULL;
+    EncTicketPart evidence_tkt;
+    HDB *s4u_clientdb;
+    hdb_entry *s4u_client = NULL;
+    krb5_boolean ad_kdc_issued = FALSE;
+    Key *clientkey;
+    Ticket *t;
+    krb5_const_realm local_realm;
+
+    if (r->client == NULL
+       || b->additional_tickets == NULL
+       || b->additional_tickets->len == 0
+       || b->kdc_options.cname_in_addl_tkt == 0
+       || b->kdc_options.enc_tkt_in_skey)
+       return 0;
+
+    memset(&evidence_tkt, 0, sizeof(evidence_tkt));
+    local_realm =
+           krb5_principal_get_comp_string(r->context, r->krbtgt->principal, 1);
+
+    /*
+     * We require that the service's TGT has a PAC; this will have been
+     * validated prior to this function being called.
+     */
+    if (r->pac == NULL) {
+       ret = KRB5KDC_ERR_BADOPTION;
+       kdc_audit_addreason((kdc_request_t)r, "Missing PAC");
+       kdc_log(r->context, r->config, 4,
+               "Constrained delegation without PAC, %s/%s",
+               r->cname, r->sname);
+       goto out;
+    }
+
+    t = &b->additional_tickets->val[0];
+
+    ret = hdb_enctype2key(r->context, r->client,
+                         hdb_kvno2keys(r->context, r->client,
+                                       t->enc_part.kvno ? * t->enc_part.kvno : 0),
+                         t->enc_part.etype, &clientkey);
+    if (ret) {
+       ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */
+       goto out;
+    }
+
+    ret = krb5_decrypt_ticket(r->context, t, &clientkey->key, &evidence_tkt, 0);
+    if (ret) {
+       kdc_audit_addreason((kdc_request_t)r,
+                           "Failed to decrypt constrained delegation ticket");
+       kdc_log(r->context, r->config, 4,
+               "failed to decrypt ticket for "
+               "constrained delegation from %s to %s ", r->cname, r->sname);
+       goto out;
+    }
+
+    ret = _krb5_principalname2krb5_principal(r->context,
+                                            &s4u_client_name,
+                                            evidence_tkt.cname,
+                                            evidence_tkt.crealm);
+    if (ret)
+       goto out;
+
+    ret = krb5_unparse_name(r->context, s4u_client_name, &s4ucname);
+    if (ret)
+       goto out;
+
+    kdc_audit_addkv((kdc_request_t)r, 0, "impersonatee", "%s", s4ucname);
+
+    ret = _krb5_principalname2krb5_principal(r->context,
+                                            &s4u_server_name,
+                                            t->sname,
+                                            t->realm);
+    if (ret)
+       goto out;
+
+    ret = krb5_unparse_name(r->context, s4u_server_name, &s4usname);
+    if (ret)
+       goto out;
+
+       /* check that ticket is valid */
+    if (evidence_tkt.flags.forwardable == 0) {
+       kdc_audit_addreason((kdc_request_t)r,
+                           "Missing forwardable flag on ticket for constrained delegation");
+       kdc_log(r->context, r->config, 4,
+               "Missing forwardable flag on ticket for "
+               "constrained delegation from %s (%s) as %s to %s ",
+               r->cname, s4usname, s4ucname, r->sname);
+       ret = KRB5KDC_ERR_BADOPTION;
+       goto out;
+    }
+
+    ret = check_constrained_delegation(r->context, r->config, r->clientdb,
+                                      r->client, r->server, r->server_princ);
+    if (ret) {
+       kdc_audit_addreason((kdc_request_t)r,
+                           "Constrained delegation not allowed");
+       kdc_log(r->context, r->config, 4,
+               "constrained delegation from %s (%s) as %s to %s not allowed",
+               r->cname, s4usname, s4ucname, r->sname);
+       goto out;
+    }
+
+    ret = _kdc_verify_flags(r->context, r->config, &evidence_tkt, s4ucname);
+    if (ret) {
+       kdc_audit_addreason((kdc_request_t)r,
+                           "Constrained delegation ticket expired or invalid");
+       goto out;
+    }
+
+    /* Try lookup the delegated client in DB */
+    ret = _kdc_db_fetch_client(r->context, r->config, flags,
+                              s4u_client_name, s4ucname, local_realm,
+                              &s4u_clientdb, &s4u_client);
+    if (ret)
+       goto out;
+
+    if (s4u_client != NULL) {
+       ret = kdc_check_flags(r, FALSE, s4u_client, r->server);
+       if (ret)
+           goto out;
+    }
+
+    /*
+     * TODO: pass in t->sname and t->realm and build
+     * a S4U_DELEGATION_INFO blob to the PAC.
+     */
+    ret = _kdc_check_pac(r->context, r->config, s4u_client_name, s4u_server_name,
+                        s4u_client, r->server, r->krbtgt, r->client,
+                        &clientkey->key, &r->ticket_key->key, &evidence_tkt,
+                        &ad_kdc_issued, &s4u_pac,
+                        &s4u_canon_client_name, &s4u_pac_attributes);
+    if (ret) {
+       const char *msg = krb5_get_error_message(r->context, ret);
+        kdc_audit_addreason((kdc_request_t)r,
+                           "Constrained delegation ticket PAC check failed");
+       kdc_log(r->context, r->config, 4,
+               "Verify delegated PAC failed to %s for client"
+               "%s (%s) as %s from %s with %s",
+               r->sname, r->cname, s4usname, s4ucname, r->from, msg);
+       krb5_free_error_message(r->context, msg);
+       goto out;
+    }
+
+    if (s4u_pac == NULL || !ad_kdc_issued) {
+       ret = KRB5KDC_ERR_BADOPTION;
+       kdc_log(r->context, r->config, 4,
+               "Ticket not signed with PAC; service %s failed for "
+               "for delegation to %s for client %s (%s) from %s; (%s).",
+               r->sname, s4ucname, s4usname, r->cname, r->from,
+               s4u_pac ? "Ticket unsigned" : "No PAC");
+       kdc_audit_addreason((kdc_request_t)r,
+                           "Constrained delegation ticket not signed");
+       goto out;
+    }
+
+    /*
+     * If the evidence ticket PAC didn't include PAC_UPN_DNS_INFO with
+     * the canonical client name, but the user is local to our KDC, we
+     * can insert the canonical client name ourselves.
+     */
+    if (s4u_canon_client_name == NULL && s4u_client != NULL) {
+       ret = krb5_copy_principal(r->context, s4u_client->principal,
+                                 &s4u_canon_client_name);
+       if (ret)
+           goto out;
+    }
+
+    kdc_log(r->context, r->config, 4, "constrained delegation for %s "
+           "from %s (%s) to %s", s4ucname, r->cname, s4usname, r->sname);
+
+    /*
+     * Replace all client information in the request with the
+     * impersonated client. (The audit entry containing the original
+     * client name will have been created before this point.)
+     */
+    _kdc_request_set_cname_nocopy((kdc_request_t)r, &s4ucname);
+    _kdc_request_set_client_princ_nocopy(r, &s4u_client_name);
+
+    _kdc_free_ent(r->context, r->clientdb, r->client);
+    r->client = s4u_client;
+    s4u_client = NULL;
+    r->clientdb = s4u_clientdb;
+    s4u_clientdb = NULL;
+
+    _kdc_request_set_canon_client_princ_nocopy(r, &s4u_canon_client_name);
+    _kdc_request_set_pac_nocopy(r, &s4u_pac);
+
+    r->pac_attributes = s4u_pac_attributes;
+
+out:
+    if (s4u_client)
+       _kdc_free_ent(r->context, s4u_clientdb, s4u_client);
+    krb5_free_principal(r->context, s4u_client_name);
+    krb5_xfree(s4ucname);
+    krb5_free_principal(r->context, s4u_server_name);
+    krb5_xfree(s4usname);
+    krb5_free_principal(r->context, s4u_canon_client_name);
+    krb5_pac_free(r->context, s4u_pac);
+
+    free_EncTicketPart(&evidence_tkt);
+
+    return ret;
+}
+
+/*
+ *
+ */
+
+krb5_error_code
+_kdc_validate_services_for_user(astgs_request_t r)
+{
+    krb5_error_code ret;
+
+    ret = validate_protocol_transition(r);
+    if (ret == 0)
+       ret = validate_constrained_delegation(r);
+
+    return ret;
+}
index ad5db1e3ca46909061fde86b4036edb1697a0233..20250c6dc897ec2ae28493e9e849e8e825f95d9b 100644 (file)
@@ -304,8 +304,6 @@ negotiate_get_instance(const char *libname)
 {
     if (strcmp(libname, "krb5") == 0)
         return krb5_get_instance(libname);
-    else if (strcmp(libname, "gssapi") == 0)
-       return gss_get_instance(libname);
 
     return 0;
 }
index b355e4c8830b3ea15ec6e6f0e1a3c216f5f6d7e0..f01178983f3c826333c989b682ea4bbb2241268c 100644 (file)
@@ -231,8 +231,6 @@ generate_dh_keyblock(krb5_context context,
            memmove(dh_gen_key + size, dh_gen_key, dh_gen_keylen);
            memset(dh_gen_key, 0, size);
        }
-
-       ret = 0;
     } else if (client_params->keyex == USE_ECDH) {
        if (client_params->u.ecdh.public_key == NULL) {
            ret = KRB5KRB_ERR_GENERIC;
@@ -390,7 +388,7 @@ _kdc_pk_rd_padata(astgs_request_t priv,
     krb5_context context = priv->context;
     krb5_kdc_configuration *config = priv->config;
     const KDC_REQ *req = &priv->req;
-    hdb_entry_ex *client = priv->client;
+    hdb_entry *client = priv->client;
     pk_client_params *cp;
     krb5_error_code ret;
     heim_oid eContentType = { 0, NULL }, contentInfoOid = { 0, NULL };
@@ -433,7 +431,7 @@ _kdc_pk_rd_padata(astgs_request_t priv,
     }
 
     /* Add any registered certificates for this client as trust anchors */
-    ret = hdb_entry_get_pkinit_cert(&client->entry, &pc);
+    ret = hdb_entry_get_pkinit_cert(client, &pc);
     if (ret == 0 && pc != NULL) {
        hx509_cert cert;
        unsigned int i;
@@ -469,7 +467,7 @@ _kdc_pk_rd_padata(astgs_request_t priv,
 
        type = "PK-INIT-Win2k";
 
-       if (_kdc_is_anonymous(context, client->entry.principal)) {
+       if (_kdc_is_anonymous(context, client->principal)) {
            ret = KRB5_KDC_ERR_PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED;
            krb5_set_error_message(context, ret,
                "Anonymous client not supported in RSA mode");
@@ -615,7 +613,7 @@ _kdc_pk_rd_padata(astgs_request_t priv,
        hx509_certs signer_certs;
        int flags = HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH; /* BTMM */
 
-       if (_kdc_is_anonymous(context, client->entry.principal)
+       if (_kdc_is_anonymous(context, client->principal)
            || (config->historical_anon_realm && _kdc_is_anon_request(req)))
            flags |= HX509_CMS_VS_ALLOW_ZERO_SIGNER;
 
@@ -701,7 +699,7 @@ _kdc_pk_rd_padata(astgs_request_t priv,
            goto out;
        }
 
-       if (_kdc_is_anonymous(context, client->entry.principal) &&
+       if (_kdc_is_anonymous(context, client->principal) &&
            ap.clientPublicValue == NULL) {
            free_AuthPack(&ap);
            ret = KRB5_KDC_ERR_PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED;
@@ -1600,7 +1598,7 @@ match_ms_upn_san(krb5_context context,
                 hx509_context hx509ctx,
                 hx509_cert client_cert,
                 HDB *clientdb,
-                hdb_entry_ex *client)
+                hdb_entry *client)
 {
     hx509_octet_string_list list;
     krb5_principal principal = NULL;
@@ -1654,7 +1652,7 @@ match_ms_upn_san(krb5_context context,
         */
        strupr(principal->realm);
 
-       if (krb5_principal_compare(context, principal, client->entry.principal) == FALSE)
+       if (krb5_principal_compare(context, principal, client->principal) == FALSE)
            ret = KRB5_KDC_ERR_CLIENT_NAME_MISMATCH;
     }
 
@@ -1673,7 +1671,7 @@ _kdc_pk_check_client(astgs_request_t r,
 {
     krb5_kdc_configuration *config = r->config;
     HDB *clientdb = r->clientdb;
-    hdb_entry_ex *client = r->client;
+    hdb_entry *client = r->client;
     const HDB_Ext_PKINIT_acl *acl;
     const HDB_Ext_PKINIT_cert *pc;
     krb5_error_code ret;
@@ -1681,7 +1679,7 @@ _kdc_pk_check_client(astgs_request_t r,
     size_t i;
 
     if (cp->cert == NULL) {
-       if (!_kdc_is_anonymous(r->context, client->entry.principal)
+       if (!_kdc_is_anonymous(r->context, client->principal)
            && !config->historical_anon_realm)
            return KRB5KDC_ERR_BADOPTION;
 
@@ -1718,7 +1716,7 @@ _kdc_pk_check_client(astgs_request_t r,
            "Trying to authorize PKINIT subject DN %s",
            *subject_name);
 
-    ret = hdb_entry_get_pkinit_cert(&client->entry, &pc);
+    ret = hdb_entry_get_pkinit_cert(client, &pc);
     if (ret == 0 && pc) {
        hx509_cert cert;
        size_t j;
@@ -1745,7 +1743,7 @@ _kdc_pk_check_client(astgs_request_t r,
        ret = match_rfc_san(r->context, config,
                            r->context->hx509ctx,
                            cp->cert,
-                           client->entry.principal);
+                           client->principal);
        if (ret == 0) {
            kdc_log(r->context, config, 5,
                    "Found matching PKINIT SAN in certificate");
@@ -1763,7 +1761,7 @@ _kdc_pk_check_client(astgs_request_t r,
        }
     }
 
-    ret = hdb_entry_get_pkinit_acl(&client->entry, &acl);
+    ret = hdb_entry_get_pkinit_acl(client, &acl);
     if (ret == 0 && acl != NULL) {
        /*
         * Cheat here and compare the generated name with the string
@@ -1789,7 +1787,7 @@ _kdc_pk_check_client(astgs_request_t r,
        krb5_boolean b;
 
        b = krb5_principal_compare(r->context,
-                                  client->entry.principal,
+                                  client->principal,
                                   principal_mappings.val[i].principal);
        if (b == FALSE)
            continue;
@@ -1926,7 +1924,7 @@ load_mappings(krb5_context context, const char *fn)
  *
  */
 
-krb5_error_code
+KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL
 krb5_kdc_pk_initialize(krb5_context context,
                       krb5_kdc_configuration *config,
                       const char *user_id,
index 23a0fe0102d0ad4b4f26dc3f9e70ab88070b8817..cf8ab060ec96c5e2d2ee333f326f70d2cb3ce2b7 100644 (file)
 #undef  __attribute__
 #define __attribute__(x)
 
-void
-_kdc_audit_vaddreason(kdc_request_t r, const char *fmt, va_list ap)
+KDC_LIB_FUNCTION void KDC_LIB_CALL
+kdc_audit_vaddreason(kdc_request_t r, const char *fmt, va_list ap)
        __attribute__ ((__format__ (__printf__, 2, 0)))
 {
     heim_audit_vaddreason((heim_svc_req_desc)r, fmt, ap);
 }
 
-void
-_kdc_audit_addreason(kdc_request_t r, const char *fmt, ...)
+KDC_LIB_FUNCTION void KDC_LIB_CALL
+kdc_audit_addreason(kdc_request_t r, const char *fmt, ...)
        __attribute__ ((__format__ (__printf__, 2, 3)))
 {
     va_list ap;
@@ -66,16 +66,16 @@ _kdc_audit_addreason(kdc_request_t r, const char *fmt, ...)
  * not a kv-pair.
  */
 
-void
-_kdc_audit_vaddkv(kdc_request_t r, int flags, const char *k,
+KDC_LIB_FUNCTION void KDC_LIB_CALL
+kdc_audit_vaddkv(kdc_request_t r, int flags, const char *k,
                  const char *fmt, va_list ap)
        __attribute__ ((__format__ (__printf__, 4, 0)))
 {
     heim_audit_vaddkv((heim_svc_req_desc)r, flags, k, fmt, ap);
 }
 
-void
-_kdc_audit_addkv(kdc_request_t r, int flags, const char *k,
+KDC_LIB_FUNCTION void KDC_LIB_CALL
+kdc_audit_addkv(kdc_request_t r, int flags, const char *k,
                 const char *fmt, ...)
        __attribute__ ((__format__ (__printf__, 4, 5)))
 {
@@ -86,20 +86,56 @@ _kdc_audit_addkv(kdc_request_t r, int flags, const char *k,
     va_end(ap);
 }
 
-void
-_kdc_audit_addkv_timediff(kdc_request_t r, const char *k,
+KDC_LIB_FUNCTION void KDC_LIB_CALL
+kdc_audit_addkv_timediff(kdc_request_t r, const char *k,
                          const struct timeval *start,
                          const struct timeval *end)
 {
     heim_audit_addkv_timediff((heim_svc_req_desc)r,k, start, end);
 }
 
+KDC_LIB_FUNCTION void KDC_LIB_CALL
+kdc_audit_setkv_bool(kdc_request_t r, const char *k, krb5_boolean v)
+{
+    heim_audit_setkv_bool((heim_svc_req_desc)r, k, (int)v);
+}
+
+KDC_LIB_FUNCTION void KDC_LIB_CALL
+kdc_audit_addkv_number(kdc_request_t r, const char *k, int64_t v)
+{
+    heim_audit_addkv_number((heim_svc_req_desc)r, k, v);
+}
+
+KDC_LIB_FUNCTION void KDC_LIB_CALL
+kdc_audit_setkv_number(kdc_request_t r, const char *k, int64_t v)
+{
+    heim_audit_setkv_number((heim_svc_req_desc)r, k, v);
+}
+
+KDC_LIB_FUNCTION void KDC_LIB_CALL
+kdc_audit_addkv_object(kdc_request_t r, const char *k, kdc_object_t obj)
+{
+    heim_audit_addkv_object((heim_svc_req_desc)r, k, obj);
+}
+
+KDC_LIB_FUNCTION void KDC_LIB_CALL
+kdc_audit_setkv_object(kdc_request_t r, const char *k, kdc_object_t obj)
+{
+    heim_audit_setkv_object((heim_svc_req_desc)r, k, obj);
+}
+
+KDC_LIB_FUNCTION kdc_object_t KDC_LIB_CALL
+kdc_audit_getkv(kdc_request_t r, const char *k)
+{
+    return heim_audit_getkv((heim_svc_req_desc)r, k);
+}
+
 /*
  * Add up to 3 key value pairs to record HostAddresses from request body or
  * PA-TGS ticket or whatever.
  */
-void
-_kdc_audit_addaddrs(kdc_request_t r, HostAddresses *a, const char *key)
+KDC_LIB_FUNCTION void KDC_LIB_CALL
+kdc_audit_addaddrs(kdc_request_t r, HostAddresses *a, const char *key)
 {
     size_t i;
     char buf[128];
@@ -109,23 +145,23 @@ _kdc_audit_addaddrs(kdc_request_t r, HostAddresses *a, const char *key)
 
         if (snprintf(numkey, sizeof(numkey), "num%s", key) >= sizeof(numkey))
             numkey[31] = '\0';
-        _kdc_audit_addkv(r, 0, numkey, "%llu", (unsigned long long)a->len);
+        kdc_audit_addkv(r, 0, numkey, "%llu", (unsigned long long)a->len);
     }
 
     for (i = 0; i < 3 && i < a->len; i++) {
         if (krb5_print_address(&a->val[i], buf, sizeof(buf), NULL) == 0)
-            _kdc_audit_addkv(r, 0, key, "%s", buf);
+            kdc_audit_addkv(r, 0, key, "%s", buf);
     }
 }
 
-void
+KDC_LIB_FUNCTION void KDC_LIB_CALL
 _kdc_audit_trail(kdc_request_t r, krb5_error_code ret)
 {
     const char *retname = NULL;
 
     /* Get a symbolic name for some error codes */
 #define CASE(x)        case x : retname = #x; break
-    switch (ret ? ret : r->ret) {
+    switch (ret ? ret : r->error_code) {
     CASE(ENOMEM);
     CASE(EACCES);
     CASE(HDB_ERR_NOT_FOUND_HERE);
@@ -171,7 +207,7 @@ _kdc_audit_trail(kdc_request_t r, krb5_error_code ret)
     heim_audit_trail((heim_svc_req_desc)r, ret, retname);
 }
 
-void
+KDC_LIB_FUNCTION void KDC_LIB_CALL
 krb5_kdc_update_time(struct timeval *tv)
 {
     if (tv == NULL)
@@ -334,8 +370,11 @@ process_request(krb5_context context,
     r->request.length = len;
     r->datagram_reply = datagram_reply;
     r->reply = reply;
-    r->kv = heim_array_create();
-    if (!r->kv) {
+    r->kv = heim_dict_create(10);
+    r->attributes = heim_dict_create(1);
+    if (r->kv == NULL || r->attributes == NULL) {
+       heim_release(r->kv);
+       heim_release(r->attributes);
        free(r);
        return krb5_enomem(context);
     }
@@ -361,6 +400,7 @@ process_request(krb5_context context,
 
             heim_release(r->reason);
             heim_release(r->kv);
+           heim_release(r->attributes);
             free(r);
            return ret;
        }
@@ -368,6 +408,7 @@ process_request(krb5_context context,
 
     heim_release(r->reason);
     heim_release(r->kv);
+    heim_release(r->attributes);
     free(r);
     return -1;
 }
@@ -377,7 +418,7 @@ process_request(krb5_context context,
  * sending a reply in `reply'.
  */
 
-int
+KDC_LIB_FUNCTION int KDC_LIB_CALL
 krb5_kdc_process_request(krb5_context context,
                         krb5_kdc_configuration *config,
                         unsigned char *buf,
@@ -399,7 +440,7 @@ krb5_kdc_process_request(krb5_context context,
  * This only processes krb5 requests
  */
 
-int
+KDC_LIB_FUNCTION int KDC_LIB_CALL
 krb5_kdc_process_krb5_request(krb5_context context,
                              krb5_kdc_configuration *config,
                              unsigned char *buf,
@@ -418,7 +459,7 @@ krb5_kdc_process_krb5_request(krb5_context context,
  *
  */
 
-int
+KDC_LIB_FUNCTION int KDC_LIB_CALL
 krb5_kdc_save_request(krb5_context context,
                      const char *fn,
                      const unsigned char *buf,
@@ -428,56 +469,109 @@ krb5_kdc_save_request(krb5_context context,
 {
     krb5_storage *sp;
     krb5_address a;
-    int fd, ret;
+    int fd = -1;
+    int ret = 0;
     uint32_t t;
     krb5_data d;
 
     memset(&a, 0, sizeof(a));
 
-    d.data = rk_UNCONST(buf);
+    d.data = rk_UNCONST(buf); /* do not free here */
     d.length = len;
     t = _kdc_now.tv_sec;
 
-    fd = open(fn, O_WRONLY|O_CREAT|O_APPEND, 0600);
-    if (fd < 0) {
-       int saved_errno = errno;
-       krb5_set_error_message(context, saved_errno, "Failed to open: %s", fn);
-       return saved_errno;
-    }
-
-    sp = krb5_storage_from_fd(fd);
-    close(fd);
-    if (sp == NULL) {
-       krb5_set_error_message(context, ENOMEM, "Storage failed to open fd");
-       return ENOMEM;
-    }
-
-    ret = krb5_sockaddr2address(context, sa, &a);
-    if (ret)
-       goto out;
-
-    krb5_store_uint32(sp, 1);
-    krb5_store_uint32(sp, t);
-    krb5_store_address(sp, a);
-    krb5_store_data(sp, d);
-    {
+    sp = krb5_storage_emem();
+    if (sp == NULL)
+        ret = krb5_enomem(context);
+
+    if (ret == 0)
+        ret = krb5_sockaddr2address(context, sa, &a);
+    if (ret == 0)
+        ret = krb5_store_uint32(sp, 1);
+    if (ret == 0)
+        ret = krb5_store_uint32(sp, t);
+    if (ret == 0)
+        ret = krb5_store_address(sp, a);
+    if (ret == 0)
+        ret = krb5_store_data(sp, d);
+    d.length = 0;
+    d.data = NULL;
+    if (ret == 0) {
        Der_class cl;
        Der_type ty;
        unsigned int tag;
        ret = der_get_tag (reply->data, reply->length,
                           &cl, &ty, &tag, NULL);
        if (ret) {
-           krb5_store_uint32(sp, 0xffffffff);
-           krb5_store_uint32(sp, 0xffffffff);
-       } else {
-           krb5_store_uint32(sp, MAKE_TAG(cl, ty, 0));
-           krb5_store_uint32(sp, tag);
+            ret = krb5_store_uint32(sp, 0xffffffff);
+            if (ret == 0)
+                ret = krb5_store_uint32(sp, 0xffffffff);
+        } else {
+            ret = krb5_store_uint32(sp, MAKE_TAG(cl, ty, 0));
+            if (ret == 0)
+                ret = krb5_store_uint32(sp, tag);
        }
     }
 
-    krb5_free_address(context, &a);
-out:
+    if (ret == 0)
+        ret = krb5_storage_to_data(sp, &d);
     krb5_storage_free(sp);
+    sp = NULL;
+
+    /*
+     * We've got KDC concurrency, so we're going to try to do a single O_APPEND
+     * write(2).  Hopefully we manage to write enough of the header that one
+     * can skip this request if it fails to write completely.
+     */
+    if (ret == 0)
+        fd = open(fn, O_WRONLY|O_CREAT|O_APPEND, 0600);
+    if (fd < 0)
+       krb5_set_error_message(context, ret = errno, "Failed to open: %s", fn);
+    if (ret == 0) {
+        sp = krb5_storage_from_fd(fd);
+        if (sp == NULL)
+            krb5_set_error_message(context, ret = ENOMEM,
+                                   "Storage failed to open fd");
+    }
+    (void) close(fd);
+    if (ret == 0)
+        ret = krb5_store_data(sp, d);
+    krb5_free_address(context, &a);
+    /*
+     * krb5_storage_free() currently always returns 0, but for FDs it sets
+     * errno to whatever close() set it to if it failed.
+     */
+    errno = 0;
+    if (ret == 0)
+        ret = krb5_storage_free(sp);
+    else
+        (void) krb5_storage_free(sp);
+    if (ret == 0 && errno)
+        ret = errno;
+
+    return ret;
+}
 
-    return 0;
+KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL
+kdc_request_set_attribute(kdc_request_t r, kdc_object_t key, kdc_object_t value)
+{
+    return heim_dict_set_value(r->attributes, key, value);
+}
+
+KDC_LIB_FUNCTION kdc_object_t KDC_LIB_CALL
+kdc_request_get_attribute(kdc_request_t r, kdc_object_t key)
+{
+    return heim_dict_get_value(r->attributes, key);
+}
+
+KDC_LIB_FUNCTION kdc_object_t KDC_LIB_CALL
+kdc_request_copy_attribute(kdc_request_t r, kdc_object_t key)
+{
+    return heim_dict_copy_value(r->attributes, key);
+}
+
+KDC_LIB_FUNCTION void KDC_LIB_CALL
+kdc_request_delete_attribute(kdc_request_t r, kdc_object_t key)
+{
+    heim_dict_delete_key(r->attributes, key);
 }
index 93ded4ec2ae85fbe8435c947cbf00616cd17c290..683eaaf7be4c978b598d6f22708b71871554e567 100644 (file)
@@ -64,7 +64,7 @@ add_db(krb5_context context, struct krb5_kdc_configuration *c,
     return 0;
 }
 
-krb5_error_code
+KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL
 krb5_kdc_set_dbinfo(krb5_context context, struct krb5_kdc_configuration *c)
 {
     struct hdb_dbinfo *info, *d;
index 1ae9efd676cb74202477b168bf29e5c0cfbedb1e..2300eb53299db0fd61bc3bf9aa0203a3fbb51325 100644 (file)
@@ -157,6 +157,13 @@ string_encode(const char *in)
     return s;
 }
 
+static void
+frees(char **s)
+{
+    free(*s);
+    *s = NULL;
+}
+
 static KRB5_LIB_CALL krb5_error_code
 authorize(void *ctx,
           krb5_context context,
@@ -228,17 +235,19 @@ authorize(void *ctx,
 
         if ((san = string_encode(s)) == NULL ||
             asprintf(&p, "%s/%s/%s-%s", d, princ, prefix, san) == -1 ||
-            p == NULL)
+            p == NULL) {
+            free(san);
             goto enomem;
+        }
         ret = stat(p, &st) == -1 ? errno : 0;
         free(san);
         free(p);
-        free(s);
-        s = NULL;
+        frees(&s);
         if (ret)
             goto skip;
         ret = hx509_request_authorize_san(csr, i);
     }
+    frees(&s);
     if (ret == HX509_NO_ITEM)
         ret = 0;
     if (ret)
@@ -251,14 +260,11 @@ authorize(void *ctx,
         ret = hx509_request_get_eku(csr, i, &s);
         if (ret)
             break;
-        if (asprintf(&p, "%s/%s/eku-%s", d, princ, s) == -1 || p == NULL) {
-            free(princ);
-            free(s);
-        }
+        if (asprintf(&p, "%s/%s/eku-%s", d, princ, s) == -1 || p == NULL)
+            goto enomem;
         ret = stat(p, &st) == -1 ? errno : 0;
         free(p);
-        free(s);
-        s = NULL;
+        frees(&s);
         if (ret)
             goto skip;
         ret = hx509_request_authorize_eku(csr, i);
index 1b603dece58d4508f691cd10f48fd386fe875e25..4b9c62e5a5d0d0ff8eb2f0577256052718d61c7d 100644 (file)
@@ -128,9 +128,9 @@ main(int argc, char **argv)
     if(ret)
        krb5_err(context, 1, ret, "krb5_string_to_enctype");
 
-    if((etype != (krb5_enctype)ETYPE_DES_CBC_CRC &&
-       etype != (krb5_enctype)ETYPE_DES_CBC_MD4 &&
-       etype != (krb5_enctype)ETYPE_DES_CBC_MD5) &&
+    if((etype != ETYPE_DES_CBC_CRC &&
+       etype != ETYPE_DES_CBC_MD4 &&
+       etype != ETYPE_DES_CBC_MD5) &&
        (afs || version4)) {
        if(!version5) {
            etype = ETYPE_DES_CBC_CRC;
index 12b873c039b7a43e8c6328bd5f876968b0004309..4d80c96a034a7d0929277ee9ed70570ea71c3877 100644 (file)
@@ -137,8 +137,9 @@ main(int argc, char **argv)
             if (ret == 0)
                 hx509_request_authorize_san(req, i);
         }
-        if (ret == HX509_NO_ITEM)
-            ret = 0;
+        if (ret && ret != HX509_NO_ITEM)
+            krb5_err(context, 1, ret,
+                     "Failed to mark requested extensions authorized");
     } else if ((ret = kdc_authorize_csr(context, app_string, req, p))) {
         krb5_err(context, 1, ret,
                  "Requested certificate extensions rejected by policy");
index cdb50e47752c32973ba4d6d4089239ad15280b51..858fdfa7b2142fc1e1e37a4c16c494c64aa2afa6 100644 (file)
@@ -78,7 +78,7 @@ static struct heim_plugin_data token_validator_data = {
  * Invoke a plugin to validate a JWT/SAML/OIDC token and partially-evaluate
  * access control.
  */
-krb5_error_code
+KDC_LIB_FUNCTION krb5_error_code KDC_LIB_CALL
 kdc_validate_token(krb5_context context,
                    const char *realm,
                    const char *token_kind,
index 4b27e6943ccc06b76de6f90b15e903d052245227..9067bb6e43f4249a5c29c3f6565d19016d3fee30 100644 (file)
@@ -11,7 +11,7 @@ HEIMDAL_KDC_1.0 {
                kdc_openlog;
                kdc_check_flags;
                kdc_validate_token;
-               krb5_kdc_windc_init;
+               krb5_kdc_plugin_init;
                krb5_kdc_get_config;
                krb5_kdc_pkinit_config;
                krb5_kdc_set_dbinfo;
@@ -20,12 +20,80 @@ HEIMDAL_KDC_1.0 {
                krb5_kdc_save_request;
                krb5_kdc_update_time;
                krb5_kdc_pk_initialize;
-               _kdc_audit_addkv;
-               _kdc_audit_addreason;
-               _kdc_audit_vaddkv;
-               _kdc_audit_vaddreason;
+               kdc_request_set_attribute;
+               kdc_request_get_attribute;
+               kdc_request_copy_attribute;
+               kdc_request_delete_attribute;
+               kdc_request_add_encrypted_padata;
+               kdc_request_add_pac_buffer;
+               kdc_request_add_reply_padata;
+               kdc_request_get_addr;
+               kdc_request_get_canon_client_princ;
+               kdc_request_get_client;
+               kdc_request_get_clientdb;
+               kdc_request_get_client_princ;
+               kdc_request_get_context;
+               kdc_request_get_config;
+               kdc_request_get_cname;
+               kdc_request_get_error_code;
+               kdc_request_get_from;
+               kdc_request_get_krbtgt;
+               kdc_request_get_krbtgtdb;
+               kdc_request_get_krbtgt_princ;
+               kdc_request_get_pac;
+               kdc_request_get_pac_attributes;
+               kdc_request_get_rep;
+               kdc_request_get_reply_key;
+               kdc_request_get_req;
+               kdc_request_get_request;
+               kdc_request_get_server;
+               kdc_request_get_serverdb;
+               kdc_request_get_server_princ;
+               kdc_request_get_sname;
+               kdc_request_get_ticket;
+               kdc_request_get_tv_end;
+               kdc_request_get_tv_start;
+               kdc_request_set_canon_client_princ;
+               kdc_request_set_client_princ;
+               kdc_request_set_cname;
+               kdc_request_set_error_code;
+               kdc_request_set_krbtgt_princ;
+               kdc_request_set_pac;
+               kdc_request_set_pac_attributes;
+               kdc_request_set_rep;
+               kdc_request_set_reply_key;
+               kdc_request_set_server_princ;
+               kdc_request_set_sname;
+               kdc_audit_addkv;
+               kdc_audit_addkv_number;
+               kdc_audit_addkv_object;
+               kdc_audit_addkv_timediff;
+               kdc_audit_addaddrs;
+               kdc_audit_addreason;
+               kdc_audit_getkv;
+               kdc_audit_setkv_bool;
+               kdc_audit_setkv_number;
+               kdc_audit_setkv_object;
+               kdc_audit_vaddkv;
+               kdc_audit_vaddreason;
                _kdc_audit_trail;
 
+               kdc_object_alloc;
+               kdc_object_retain;
+               kdc_object_release;
+               kdc_bool_create;
+               kdc_bool_get_value;
+               kdc_array_iterate;
+               kdc_array_get_length;
+               kdc_array_get_value;
+               kdc_array_copy_value;
+               kdc_string_create;
+               kdc_string_get_utf8;
+               kdc_data_create;
+               kdc_data_get_data;
+               kdc_number_create;
+               kdc_number_get_value;
+
                # needed for digest-service
                _kdc_db_fetch;
                _kdc_free_ent;
diff --git a/third_party/heimdal/kdc/windc.c b/third_party/heimdal/kdc/windc.c
deleted file mode 100644 (file)
index eb834cd..0000000
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * 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 "kdc_locl.h"
-
-static int have_plugin = 0;
-
-/*
- * Pick the first WINDC module that we find.
- */
-
-static const char *windc_plugin_deps[] = {
-    "kdc",
-    "krb5",
-    "hdb",
-    NULL
-};
-
-static struct heim_plugin_data windc_plugin_data = {
-    "krb5",
-    "windc",
-    KRB5_WINDC_PLUGIN_MINOR,
-    windc_plugin_deps,
-    kdc_get_instance
-};
-
-static krb5_error_code KRB5_LIB_CALL
-load(krb5_context context, const void *plug, void *plugctx, void *userctx)
-{
-    have_plugin = 1;
-    return KRB5_PLUGIN_NO_HANDLE;
-}
-
-krb5_error_code
-krb5_kdc_windc_init(krb5_context context)
-{
-    (void)_krb5_plugin_run_f(context, &windc_plugin_data, 0, NULL, load);
-
-    return 0;
-}
-
-struct generate_uc {
-    hdb_entry_ex *client;
-    hdb_entry_ex *server;
-    const krb5_keyblock *reply_key;
-    uint64_t pac_attributes;
-    krb5_pac *pac;
-};
-
-static krb5_error_code KRB5_LIB_CALL
-generate(krb5_context context, const void *plug, void *plugctx, void *userctx)
-{
-    krb5plugin_windc_ftable *ft = (krb5plugin_windc_ftable *)plug;
-    struct generate_uc *uc = (struct generate_uc *)userctx;    
-
-    if (ft->pac_generate == NULL)
-       return KRB5_PLUGIN_NO_HANDLE;
-
-    return ft->pac_generate((void *)plug, context,
-                           uc->client,
-                           uc->server,
-                           uc->reply_key,
-                           uc->pac_attributes,
-                           uc->pac);
-}
-
-
-krb5_error_code
-_kdc_pac_generate(krb5_context context,
-                 hdb_entry_ex *client,
-                 hdb_entry_ex *server,
-                 const krb5_keyblock *reply_key,
-                 uint64_t pac_attributes,
-                 krb5_pac *pac)
-{
-    krb5_error_code ret = 0;
-    struct generate_uc uc;
-
-    *pac = NULL;
-
-    if (krb5_config_get_bool_default(context, NULL, FALSE, "realms",
-                                    client->entry.principal->realm,
-                                    "disable_pac", NULL))
-       return 0;
-
-    if (have_plugin) {
-       uc.client = client;
-       uc.server = server;
-       uc.reply_key = reply_key;
-       uc.pac = pac;
-       uc.pac_attributes = pac_attributes;
-
-       ret = _krb5_plugin_run_f(context, &windc_plugin_data,
-                                0, &uc, generate);
-       if (ret != KRB5_PLUGIN_NO_HANDLE)
-           return ret;
-       ret = 0;
-    }
-
-    if (*pac == NULL)
-       ret = krb5_pac_init(context, pac);
-
-    return ret;
-}
-
-struct verify_uc {
-    krb5_principal client_principal;
-    krb5_principal delegated_proxy_principal;
-    hdb_entry_ex *client;
-    hdb_entry_ex *server;
-    hdb_entry_ex *krbtgt;
-    krb5_pac *pac;
-};
-
-static krb5_error_code KRB5_LIB_CALL
-verify(krb5_context context, const void *plug, void *plugctx, void *userctx)
-{
-    krb5plugin_windc_ftable *ft = (krb5plugin_windc_ftable *)plug;
-    struct verify_uc *uc = (struct verify_uc *)userctx;
-    krb5_error_code ret;
-
-    if (ft->pac_verify == NULL)
-       return KRB5_PLUGIN_NO_HANDLE;
-
-    ret = ft->pac_verify((void *)plug, context,
-                        uc->client_principal,
-                        uc->delegated_proxy_principal,
-                        uc->client, uc->server, uc->krbtgt, uc->pac);
-    return ret;
-}
-
-krb5_error_code
-_kdc_pac_verify(krb5_context context,
-               const krb5_principal client_principal,
-               const krb5_principal delegated_proxy_principal,
-               hdb_entry_ex *client,
-               hdb_entry_ex *server,
-               hdb_entry_ex *krbtgt,
-               krb5_pac *pac)
-{
-    struct verify_uc uc;
-
-    if (!have_plugin)
-       return KRB5_PLUGIN_NO_HANDLE;
-
-    uc.client_principal = client_principal;
-    uc.delegated_proxy_principal = delegated_proxy_principal;
-    uc.client = client;
-    uc.server = server;
-    uc.krbtgt = krbtgt;
-    uc.pac = pac;
-
-    return _krb5_plugin_run_f(context, &windc_plugin_data,
-                            0, &uc, verify);
-}
-
-static krb5_error_code KRB5_LIB_CALL
-check(krb5_context context, const void *plug, void *plugctx, void *userctx)
-{
-    krb5plugin_windc_ftable *ft = (krb5plugin_windc_ftable *)plug;
-
-    if (ft->client_access == NULL)
-       return KRB5_PLUGIN_NO_HANDLE;
-    return ft->client_access((void *)plug, userctx);
-}
-
-krb5_error_code
-_kdc_check_access(astgs_request_t r)
-{
-    krb5_error_code ret = KRB5_PLUGIN_NO_HANDLE;
-
-    if (have_plugin) {
-        ret = _krb5_plugin_run_f(r->context, &windc_plugin_data,
-                                 0, r, check);
-    }
-
-    if (ret == KRB5_PLUGIN_NO_HANDLE)
-        return kdc_check_flags(r, r->req.msg_type == krb_as_req,
-                               r->client, r->server);
-    return ret;
-}
-
-static krb5_error_code KRB5_LIB_CALL
-finalize(krb5_context context, const void *plug, void *plugctx, void *userctx)
-{
-    krb5plugin_windc_ftable *ft = (krb5plugin_windc_ftable *)plug;
-
-    if (ft->finalize_reply == NULL)
-       return KRB5_PLUGIN_NO_HANDLE;
-    return ft->finalize_reply((void *)plug, (astgs_request_t)userctx);
-}
-
-krb5_error_code
-_kdc_finalize_reply(astgs_request_t r)
-{
-    krb5_error_code ret = KRB5_PLUGIN_NO_HANDLE;
-
-    if (have_plugin)
-        ret = _krb5_plugin_run_f(r->context, &windc_plugin_data, 0, r, finalize);
-
-    if (ret == KRB5_PLUGIN_NO_HANDLE)
-        ret = 0;
-
-    return ret;
-}
-
-uintptr_t KRB5_CALLCONV
-kdc_get_instance(const char *libname)
-{
-    static const char *instance = "libkdc";
-
-    if (strcmp(libname, "kdc") == 0)
-        return (uintptr_t)instance;
-    else if (strcmp(libname, "hdb") == 0)
-       return hdb_get_instance(libname);
-    else if (strcmp(libname, "krb5") == 0)
-        return krb5_get_instance(libname);
-    else if (strcmp(libname, "gssapi") == 0)
-        return gss_get_instance(libname);
-
-    return 0;
-}
diff --git a/third_party/heimdal/kdc/windc_plugin.h b/third_party/heimdal/kdc/windc_plugin.h
deleted file mode 100644 (file)
index ae0c6d1..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2006 Kungliga Tekniska Högskolan
- * (Royal Institute of Technology, Stockholm, Sweden).
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * 3. Neither the name of the Institute nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/* $Id$ */
-
-#ifndef HEIMDAL_KDC_WINDC_PLUGIN_H
-#define HEIMDAL_KDC_WINDC_PLUGIN_H 1
-
-#include <krb5.h>
-#include <kdc.h>
-
-/*
- * The PAC generate function should allocate a krb5_pac using
- * krb5_pac_init and fill in the PAC structure for the principal using
- * krb5_pac_add_buffer.
- *
- * The PAC verify function should verify the PAC KDC signatures by fetching
- * the right KDC key and calling krb5_pac_verify() with that KDC key.
- * Optionally, update the PAC buffers upon success.
- *
- * Check client access function check if the client is authorized.
- */
-
-struct hdb_entry_ex;
-
-typedef krb5_error_code
-(KRB5_CALLCONV *krb5plugin_windc_pac_generate)(void *, krb5_context,
-                                              struct hdb_entry_ex *, /* client */
-                                              struct hdb_entry_ex *, /* server */
-                                              const krb5_keyblock *, /* pk_replykey */
-                                              uint64_t,              /* pac_attributes */
-                                              krb5_pac *);
-
-typedef krb5_error_code
-(KRB5_CALLCONV *krb5plugin_windc_pac_verify)(void *, krb5_context,
-                              const krb5_principal, /* new ticket client */
-                              const krb5_principal, /* delegation proxy */
-                              struct hdb_entry_ex *,/* client */
-                              struct hdb_entry_ex *,/* server */
-                              struct hdb_entry_ex *,/* krbtgt */
-                              krb5_pac *);
-
-typedef krb5_error_code
-(KRB5_CALLCONV *krb5plugin_windc_client_access)(void *, astgs_request_t);
-
-typedef krb5_error_code
-(KRB5_CALLCONV *krb5plugin_windc_finalize_reply)(void *, astgs_request_t r);
-
-#define KRB5_WINDC_PLUGIN_MINOR                        8
-#define KRB5_WINDC_PLUGING_MINOR KRB5_WINDC_PLUGIN_MINOR
-
-typedef struct krb5plugin_windc_ftable {
-    int                        minor_version;
-    krb5_error_code    (KRB5_CALLCONV *init)(krb5_context, void **);
-    void               (KRB5_CALLCONV *fini)(void *);
-    krb5plugin_windc_pac_generate      pac_generate;
-    krb5plugin_windc_pac_verify                pac_verify;
-    krb5plugin_windc_client_access     client_access;
-    krb5plugin_windc_finalize_reply    finalize_reply;
-} krb5plugin_windc_ftable;
-
-#endif /* HEIMDAL_KDC_WINDC_PLUGIN_H */
index 344688e296e06243e60ea135b906278a2f339195..e04eebe46e1f4a57bb1af8007d0d06599dc2e52b 100644 (file)
@@ -406,6 +406,7 @@ change (krb5_auth_context auth_context,
            krb5_warnx(context,
                       "%s didn't pass password quality check with error: %s",
                       client, str);
+            break;
         default:
            krb5_warnx(context, "kadm5_s_chpass_principal_cond: %s", str);
        }
@@ -772,6 +773,7 @@ doit(krb5_keytab keytab, int port)
     free(sockets);
 
     krb5_free_addresses(context, &addrs);
+    krb5_kt_close(context, keytab);
     krb5_free_context(context);
     return 0;
 }
index 1196c16dc6795e28ab18d939928a2f50ae61b5b5..2dd71bf7ab8a92221ce9a22c2541e19d51023891 100644 (file)
@@ -49,7 +49,7 @@ read_words (const char *filename, char ***ret_w)
        buf[strcspn(buf, "\r\n")] = '\0';
        if (n >= alloc) {
            alloc += 16;
-           w = erealloc (w, alloc * sizeof(char **));
+           w = erealloc (w, alloc * sizeof(*w));
        }
        w[n++] = estrdup (buf);
     }
index 92eb770990c5c2e640e49cfdf0b8bb9d3b52012a..4982f8a796a8110126e44e6b0f6a78b6ddabcaad 100644 (file)
@@ -283,6 +283,9 @@ main(int argc, char **argv)
 
            ret = krb5_sname_to_principal(context, hname, sname,
                                           KRB5_NT_SRV_HST, &server2);
+            if (ret)
+                krb5_err(context, 1, ret, "krb5_sname_to_principal %s %s",
+                         sname, hname);
             sname = krb5_principal_get_comp_string(context, server2, 0);
             hname = krb5_principal_get_comp_string(context, server2, 1);
 
index 04a16fb6ade69c9b7bf091f56d58fe9786177e37..35b4295fb36d17ba080f28cf3967f129ed29922e 100644 (file)
@@ -82,9 +82,7 @@ encode_ticket(krb5_context context,
     et.flags = cred->flags.b;
     et.key = cred->session;
     et.crealm = cred->client->realm;
-    ret = copy_PrincipalName(&cred->client->name, &et.cname);
-    if (ret)
-       krb5_err(context, 1, ret, "copy_PrincipalName");
+    et.cname = cred->client->name;
     {
        krb5_data empty_string;
 
@@ -129,16 +127,11 @@ encode_ticket(krb5_context context,
 
     ticket.tkt_vno = 5;
     ticket.realm = cred->server->realm;
-    ret = copy_PrincipalName(&cred->server->name, &ticket.sname);
-    if (ret)
-       krb5_err(context, 1, ret, "copy_PrincipalName");
-
-    ASN1_MALLOC_ENCODE(Ticket, buf, len, &ticket, &size, ret);
+    ticket.sname = cred->server->name;
+    ASN1_MALLOC_ENCODE(Ticket, cred->ticket.data, cred->ticket.length, &ticket, &size, ret);
+    free_EncryptedData(&ticket.enc_part);
     if(ret)
        krb5_err(context, 1, ret, "encode_Ticket");
-
-    krb5_data_copy(&cred->ticket, buf, len);
-    free(buf);
 }
 
 /*
@@ -173,12 +166,13 @@ create_krb5_tickets(krb5_context context, krb5_keytab kt)
 
 
     ret = krb5_copy_principal(context, client_principal, &cred.client);
+    if (ret == 0)
+        ret = krb5_copy_principal(context, server_principal, &cred.server);
     if (ret)
        krb5_err(context, 1, ret, "krb5_copy_principal");
-    ret = krb5_copy_principal(context, server_principal, &cred.server);
+    ret = krb5_generate_random_keyblock(context, session_etype, &cred.session);
     if (ret)
-       krb5_err(context, 1, ret, "krb5_copy_principal");
-    krb5_generate_random_keyblock(context, session_etype, &cred.session);
+       krb5_err(context, 1, ret, "krb5_generate_random_keyblock");
 
     cred.times.authtime = time(NULL);
     cred.times.starttime = time(NULL);
@@ -283,13 +277,13 @@ setup_env(krb5_context context, krb5_keytab *kt)
        krb5_errx(context, 1, "missing client principal");
     ret = krb5_parse_name(context, client_principal_str, &client_principal);
     if (ret)
-       krb5_err(context, 1, ret, "resolvning client name");
+       krb5_err(context, 1, ret, "resolving client name");
 
     if (server_principal_str == NULL)
        krb5_errx(context, 1, "missing server principal");
     ret = krb5_parse_name(context, server_principal_str, &server_principal);
     if (ret)
-       krb5_err(context, 1, ret, "resolvning server name");
+       krb5_err(context, 1, ret, "resolving server name");
 
     /* If no session-enc-type specified on command line and this is an afs */
     /* service ticket, change default of session_enc_type to DES.       */
@@ -395,6 +389,7 @@ main(int argc, char **argv)
        create_krb5_tickets(context, kt);
 
     krb5_kt_close(context, kt);
+    krb5_free_context(context);
 
     return 0;
 }
index 0b22e715095040718c3b8f2fc0db00e156d0cbe8..6ac4b45426a9927a45b6aff808fa53771d0ba4d1 100644 (file)
@@ -34,6 +34,8 @@
  */
 
 #include "kuser_locl.h"
+#undef HC_DEPRECATED_CRYPTO
+#include <krb5_locl.h>
 
 #ifdef HAVE_FRAMEWORK_SECURITY
 #include <Security/Security.h>
@@ -78,7 +80,7 @@ int pk_enterprise_flag = 0;
 struct hx509_certs_data *ent_user_id = NULL;
 char *pk_x509_anchors  = NULL;
 int pk_use_enckey      = 0;
-int pk_anon_fast_armor = 0;
+int pk_anon_fast_armor = -1;
 char *gss_preauth_mech = NULL;
 char *gss_preauth_name = NULL;
 char *kdc_hostname     = NULL;
@@ -500,7 +502,7 @@ renew_validate(krb5_context context,
         * no need to check the error here, it's only to be
         * friendly to the user
         */
-       krb5_get_credentials(context, KRB5_GC_CACHED, cache, &in, &out);
+       (void) krb5_get_credentials(context, KRB5_GC_CACHED, cache, &in, &out);
     }
 
     flags.i = 0;
@@ -828,6 +830,8 @@ get_new_tickets(krb5_context context,
     if (pk_enterprise_flag || enterprise_flag || canonicalize_flag || windows_flag)
        krb5_get_init_creds_opt_set_win2k(context, opt, TRUE);
     if (pk_user_id || ent_user_id || anonymous_pkinit) {
+        if (pk_anon_fast_armor == -1)
+            pk_anon_fast_armor = 0;
        ret = krb5_get_init_creds_opt_set_pkinit(context, opt,
                                                 principal,
                                                 pk_user_id,
@@ -936,13 +940,22 @@ get_new_tickets(krb5_context context,
        }
     }
 
+    if (anonymous_flag && pk_anon_fast_armor == -1)
+        pk_anon_fast_armor = 0;
+    if (!gss_preauth_mech && anonymous_flag && pk_anon_fast_armor) {
+        krb5_warnx(context, N_("Ignoring --pk-anon-fast-armor because "
+                               "--anonymous given", ""));
+        pk_anon_fast_armor = 0;
+    }
+
     if (fast_armor_cache_string) {
        krb5_ccache fastid = NULL;
 
-       if (pk_anon_fast_armor)
+       if (pk_anon_fast_armor > 0)
            krb5_errx(context, 1,
                N_("cannot specify FAST armor cache with FAST "
                     "anonymous PKINIT option", ""));
+        pk_anon_fast_armor = 0;
 
        ret = krb5_cc_resolve(context, fast_armor_cache_string, &fastid);
        if (ret) {
@@ -955,6 +968,12 @@ get_new_tickets(krb5_context context,
            krb5_warn(context, ret, "krb5_init_creds_set_fast_ccache");
            goto out;
        }
+    } else if (pk_anon_fast_armor == -1) {
+       ret = _krb5_init_creds_set_fast_anon_pkinit_optimistic(context, ctx);
+       if (ret) {
+           krb5_warn(context, ret, "_krb5_init_creds_set_fast_anon_pkinit_optimistic");
+           goto out;
+       }
     } else if (pk_anon_fast_armor) {
        ret = krb5_init_creds_set_fast_anon_pkinit(context, ctx);
        if (ret) {
@@ -1659,6 +1678,10 @@ main(int argc, char **argv)
            krb5_err(context, 1, ret, "krb5_pk_enterprise_certs");
 
        pk_user_id = NULL;
+        if (pk_anon_fast_armor > 0)
+            krb5_warnx(context, N_("Ignoring --pk-anon-fast-armor "
+                                   "because --pk-user given", ""));
+        pk_anon_fast_armor = 0;
     } else if (argc && argv[0][0] == '@' &&
        (gss_preauth_mech || anonymous_flag)) {
        const char *instance;
@@ -1673,6 +1696,11 @@ main(int argc, char **argv)
        ret = make_wellknown_name(context, &argv[0][1], instance, &principal);
        if (ret)
            krb5_err(context, 1, ret, "make_wellknown_name");
+        if (!gss_preauth_mech && pk_anon_fast_armor > 1) {
+            krb5_warnx(context, N_("Ignoring --pk-anon-fast-armor "
+                                   "because --anonymous given", ""));
+            pk_anon_fast_armor = 0;
+        }
     } else if (anonymous_flag && historical_anon_pkinit) {
         char *realm = argc == 0 ? get_default_realm(context) :
                       argv[0][0] == '@' ? &argv[0][1] : argv[0];
index 5dbabcaad85e76606c3da38130a25d70a98ed549..b33c3c28a7aa33ec0623b0ca9ef787e218a2278a 100644 (file)
@@ -362,7 +362,6 @@ print_tickets(krb5_context context,
     if (ret)
        krb5_err(context, 1, ret, "krb5_cc_end_seq_get");
 
-    print_comma = 0;
     if(!do_verbose) {
        rtbl_format(ct, stdout);
        rtbl_destroy(ct);
@@ -523,16 +522,16 @@ static int
 list_caches(krb5_context context, struct klist_options *opt)
 {
     krb5_cccol_cursor cursor;
-    const char *cdef_name;
+    const char *cdef_name = krb5_cc_default_name(context);
     char *def_name;
     krb5_error_code ret;
     krb5_ccache id;
     rtbl_t ct;
 
-    cdef_name = krb5_cc_default_name(context);
-    if (cdef_name == NULL)
-       krb5_errx(context, 1, "krb5_cc_default_name");
-    def_name = strdup(cdef_name);
+    if ((def_name = krb5_cccol_get_default_ccname(context)) == NULL)
+        cdef_name = krb5_cc_default_name(context);
+    if (!def_name && cdef_name && (def_name = strdup(cdef_name)) == NULL)
+        krb5_err(context, 1, ENOMEM, "Out of memory");
 
     ret = krb5_cccol_cursor_new(context, &cursor);
     if (ret == KRB5_CC_NOSUPP) {
@@ -554,7 +553,7 @@ list_caches(krb5_context context, struct klist_options *opt)
     if (opt->json_flag)
        rtbl_set_flags(ct, RTBL_JSON);
 
-    while (krb5_cccol_cursor_next(context, cursor, &id) == 0) {
+    while (krb5_cccol_cursor_next(context, cursor, &id) == 0 && id != NULL) {
        int expired = 0;
        char *name;
        time_t t;
@@ -582,7 +581,7 @@ list_caches(krb5_context context, struct klist_options *opt)
            rtbl_add_column_entry(ct, COL_CACHENAME, fname);
            if (opt->json_flag)
                ;
-           else if (strcmp(fname, def_name) == 0)
+           else if (def_name && strcmp(fname, def_name) == 0)
                rtbl_add_column_entry(ct, COL_DEFCACHE, "*");
            else
                rtbl_add_column_entry(ct, COL_DEFCACHE, "");
index d897a8e74513f306c2490b0356478a76ebbc045d..3bb3b700dbd152510c36003fe033c362b5be3d3c 100644 (file)
@@ -86,16 +86,17 @@ kswitch(struct kswitch_options *opt, int argc, char **argv)
            krb5_err(heimtools_context, 1, ret, "krb5_cc_cache_get_first");
 
        while (krb5_cc_cache_next(heimtools_context, cursor, &id) == 0) {
-           krb5_principal p;
+           krb5_principal p = NULL;
            char num[10];
 
            ret = krb5_cc_get_principal(heimtools_context, id, &p);
+            if (ret == 0)
+                ret = krb5_unparse_name(heimtools_context, p, &name);
            if (ret) {
                 krb5_cc_close(heimtools_context, id);
                continue;
             }
 
-           ret = krb5_unparse_name(heimtools_context, p, &name);
            krb5_free_principal(heimtools_context, p);
 
            snprintf(num, sizeof(num), "%d", (int)(len + 1));
index 8218a6f096fd91ebc396078713f74ad22430ad84..b1a097a8d6f7aea7e6ea062944fbc46dda119937 100644 (file)
 
 #ifdef LIBINTL
 #include <libintl.h>
+#undef N_
 #define N_(x,y) gettext(x)
+#undef NP_
 #define NP_(x,y) (x)
 #define getarg_i18n gettext
 #else
+#undef N_
 #define N_(x,y) (x)
+#undef NP_
 #define NP_(x,y) (x)
 #define getarg_i18n NULL
 #define bindtextdomain(package, localedir)
diff --git a/third_party/heimdal/lib/asn1/MANUAL.md b/third_party/heimdal/lib/asn1/MANUAL.md
new file mode 100644 (file)
index 0000000..89c452a
--- /dev/null
@@ -0,0 +1,1287 @@
+# Introduction
+
+Heimdal is an implementation of PKIX and Kerberos.  As such it must handle the
+use of [Abstract Syntax Notation One (ASN.1)](https://www.itu.int/rec/T-REC-X.680-X.693-202102-I/en)
+by those protocols.  ASN.1 is a language for describing the schemata of network
+protocol messages.  Associated with ASN.1 are the ASN.1 Encoding Rules (ERs)
+that specify how to encode such messages.
+
+In short:
+
+ - ASN.1 is just a _schema description language_
+
+ - ASN.1 Encoding Rules are specifications for encoding formats for values of
+   types described by ASN.1 schemas ("modules")
+
+Similar languages include:
+
+ - [DCE RPC's Interface Description Language (IDL)](https://pubs.opengroup.org/onlinepubs/9629399/chap4.htm#tagcjh_08)
+ - [Microsoft Interface Description Language (IDL)](https://docs.microsoft.com/en-us/windows/win32/midl/midl-start-page)
+   (MIDL is derived from the DCE RPC IDL)
+ - ONC RPC's eXternal Data Representation (XDR) [RFC4506](https://datatracker.ietf.org/doc/html/rfc4506)
+ - [XML Schema](https://en.wikipedia.org/wiki/XML_schema)
+ - Various JSON schema languages
+ - [Protocol Buffers](https://developers.google.com/protocol-buffers)
+ - and [many, many others](https://en.wikipedia.org/wiki/Comparison_of_data-serialization_formats)!
+   Many are not even listed there.
+
+Similar encoding rules include:
+
+ - DCE RPC's [NDR](https://pubs.opengroup.org/onlinepubs/9629399/chap14.htm)
+ - ONC RPC's [XDR](https://datatracker.ietf.org/doc/html/rfc4506)
+ - XML
+ - FastInfoSet
+ - JSON
+ - CBOR
+ - [Protocol Buffers](https://developers.google.com/protocol-buffers)
+ - [Flat Buffers](https://google.github.io/flatbuffers/)
+ - and [many, many others](https://en.wikipedia.org/wiki/Comparison_of_data-serialization_formats)!
+   Many are not even listed there.
+
+Many such languages are quite old.  ASN.1 itself dates to the early 1980s, with
+the first specification published in 1984.  XDR was first published in 1987.
+IDL's lineage dates back to sometime during the 1980s, via the Apollo Domain
+operating system.
+
+ASN.1 is standardized by the International Telecommunications Union (ITU-T),
+and has continued evolving over the years, with frequent updates.
+
+The two most useful and transcending features of ASN.1 are:
+
+ - the ability to formally express what some know as "open types", "typed
+   holes", or "references";
+
+ - the ability to add encoding rules over type, which for ASN.1 includes:
+
+    - binary, tag-length-value (TLV) encoding rules
+    - binary, non-TLV encoding rules
+    - textual encoding rules using XML and JSON
+    - an ad-hoc generic text-based ER called GSER
+
+   In principle ASN.1 can add encoding rules that would allow it to
+   interoperate with many others, such as: CBOR, protocol buffers, flat
+   buffers, NDR, and others.
+
+   Readers may recognize that some alternatives to ASN.1 have followed a
+   similar arc.  For example, Protocol Buffers was originally a syntax and
+   encoding, and has become a syntax and set of various encodings (e.g., Flat
+   Buffers was added later).  And XML has FastInfoSet as a binary encoding
+   alternative to XML's textual encoding.
+
+As well, ASN.1 has [high-quality, freely-available specifications](https://www.itu.int/rec/T-REC-X.680-X.693-202102-I/en).
+
+## ASN.1 Example
+
+For example, this is a `Certificate` as used in TLS and other protocols, taken
+from [RFC5280](https://datatracker.ietf.org/doc/html/rfc5280):
+
+   ```ASN.1
+   Certificate  ::=  SEQUENCE  {
+        tbsCertificate       TBSCertificate,
+        signatureAlgorithm   AlgorithmIdentifier,
+        signatureValue       BIT STRING
+   }
+
+   TBSCertificate  ::=  SEQUENCE  {
+        version         [0]  EXPLICIT Version DEFAULT v1,
+        serialNumber         CertificateSerialNumber,
+        signature            AlgorithmIdentifier,
+        issuer               Name,
+        validity             Validity,
+        subject              Name,
+        subjectPublicKeyInfo SubjectPublicKeyInfo,
+        issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
+        subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
+        extensions      [3]  EXPLICIT Extensions OPTIONAL
+   }
+   ```
+
+and the same `Certificate` taken from a more modern version -from
+[RFC5912](https://datatracker.ietf.org/doc/html/rfc5912)- using newer features
+of ASN.1:
+
+   ```ASN.1
+   Certificate  ::=  SIGNED{TBSCertificate}
+
+   TBSCertificate  ::=  SEQUENCE  {
+       version         [0]  Version DEFAULT v1,
+       serialNumber         CertificateSerialNumber,
+       signature            AlgorithmIdentifier{SIGNATURE-ALGORITHM,
+                                 {SignatureAlgorithms}},
+       issuer               Name,
+       validity             Validity,
+       subject              Name,
+       subjectPublicKeyInfo SubjectPublicKeyInfo,
+       ... ,
+       [[2:
+       issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
+       subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL
+       ]],
+       [[3:
+       extensions      [3]  Extensions{{CertExtensions}} OPTIONAL
+       ]], ...
+   }
+   ```
+
+As you can see, a `Certificate` is a structure containing a to-be-signed
+sub-structure, and a signature of that sub-structure, and the sub-structure
+has: a version number, a serial number, a signature algorithm, an issuer name,
+a validity period, a subject name, a public key for the subject name, "unique
+identifiers" for the issuer and subject entities, and "extensions".
+
+To understand more we'd have to look at the types of those fields of
+`TBSCertificate`, but for now we won't do that.  The point here is to show that
+ASN.1 allows us to describe "types" of data in a way that resembles
+"structures", "records", or "classes" in various programming languages.
+
+To be sure, there are some "noisy" artifacts in the definition of
+`TBSCertificate` which mostly have to do with the original encoding rules for
+ASN.1.  The original encoding rules for ASN.1 were tag-length-value (TLV)
+binary encodings, meaning that for every type, the encoding of a value of that
+type consisted of a _tag_, a _length_ of the value's encoding, and the _actual
+value's encoding_.  Over time other encoding rules were added that do not
+require tags, such as the octet encoding rules (OER), but also JSON encoding
+rules (JER), XML encoding rules (XER), and others.  There is almost no need for
+tagging directives like `[1] IMPLICIT` when using OER.  But in existing
+protocols like PKIX and Kerberos that date back to the days when DER was king,
+tagging directives are unfortunately commonplace.
+
+## ASN.1 Crash Course
+
+This is not a specification.  Readers should refer to the ITU-T's X.680 base
+specification for ASN.1's syntax.
+
+A schema is called a "module".
+
+A module looks like:
+
+```ASN.1
+-- This is a comment
+
+-- Here's the name of the module, here given as an "object identifier" or
+-- OID:
+PKIXAlgs-2009 { iso(1) identified-organization(3) dod(6)
+  internet(1) security(5) mechanisms(5) pkix(7) id-mod(0)
+  id-mod-pkix1-algorithms2008-02(56) }
+
+
+-- `DEFINITIONS` is a required keyword
+-- `EXPLICIT TAGS` will be explained later
+DEFINITIONS EXPLICIT TAGS ::=
+BEGIN
+-- list exported types, or `ALL`:
+EXPORTS ALL;
+-- import some types:
+IMPORTS PUBLIC-KEY, SIGNATURE-ALGORITHM, ... FROM AlgorithmInformation-2009
+        mda-sha224, mda-sha256, ... FROM PKIX1-PSS-OAEP-Algorithms-2009;
+
+-- type definitions follow:
+...
+
+END
+```
+
+Type names start with capital upper-case letters.  Value names start with
+lower-case letters.
+
+Type definitions are of the form `TypeName ::= TypeDefinition`.
+
+Value (constant) definitions are of the form `valueName ::= TypeName <literal>`.
+
+There are some "universal" primitive types (e.g., string types, numeric types),
+and several "constructed" types (arrays, structures.
+
+Some useful primitive types include `BOOLEAN`, `INTEGER` and `UTF8String`.
+
+Structures are either `SEQUENCE { ... }` or `SET { ... }`.  The "fields" of
+these are known as "members".
+
+Arrays are either `SEQUENCE OF SomeType` or `SET OF SomeType`.
+
+A `SEQUENCE`'s elements or members are ordered, while a `SET`'s are not.  In
+practice this means that for _canonical_ encoding rules a `SET OF` type's
+values must be sorted, while a `SET { ... }` type's members need not be sorted
+at run-time, but are sorted by _tag_ at compile-time.
+
+Anonymous types are supported, such as `SET OF SET { a A, b B }` (which is a
+set of structures with an `a` field (member) of type `A` and a `b` member of
+type `B`).
+
+The members of structures can be `OPTIONAL` or have a `DEFAULT` value.
+
+There are also discriminated union types known as `CHOICE`s: `U ::= CHOICE { a
+A, b B, c C }` (in this case `U` is either an `A`, a `B`, or a `C`.
+
+Extensibility is supported.  "Extensibility" means: the ability to add new
+members to structures, new alternatives to discriminated unions, etc.  For
+example, `A ::= SEQUENCE { a0 A0, a1 A1, ... }` means that type `A` is a
+structure that has two fields and which may have more fields added in future
+revisions, therefore decoders _must_ be able to receive and decode encodings of
+extended versions of `A`, even encoders produced prior to the extensions being
+specified!  (Normally a decoder "skips" extensions it doesn't know about, and
+the encoding rules need only make it possible to do so.)
+
+## TLV Encoding Rules
+
+The TLV encoding rules for ASN.1 are:
+
+ - Basic Encoding Rules (BER)
+ - Distinguished Encoding Rules (DER), a canonical subset of BER
+ - Canonical Encoding Rules (CER), another canonical subset of BER
+
+"Canonical" encoding rules yield just one way to encode any value of any type,
+while non-canonical rules possibly yield many ways to encode values of certain
+types.  For example, JSON is not a canonical data encoding.  A canonical form
+of JSON would have to specify what interstitial whitespace is allowed, a
+canonical representation of strings (which Unicode codepoints must be escaped
+and in what way, and which must not), and a canonical representation of decimal
+numbers.
+
+It is important to understand that originally ASN.1 came with TLV encoding
+rules, and some considerations around TLV encoding rules leaked into the
+language.  For example, `A ::= SET { a0 [0] A0, a1 [1] A1 }` is a structure
+that has two members `a0` and `a1`, and when encoded those members will be
+tagged with a "context-specific" tags `0` and `1`, respectively.
+
+Tags only have to be specified when needed to disambiguate encodings.
+Ambiguities arise only in `CHOICE` types and sometimes in `SEQUENCE`/`SET`
+types that have `OPTIONAL`/`DEFAULT`ed members.
+
+In modern ASN.1 it is possible to specify that a module uses `AUTOMATIC`
+tagging so that one need never specify tags explicitly in order to fix
+ambiguities.
+
+Also, there are two types of tags: `IMPLICIT` and `EXPLICIT`.  Implicit tags
+replace the tags that the tagged type would have otherwise.  Explicit tags
+treat the encoding of a type's value (including its tag and length) as the
+value of the tagged type, thus yielding a tag-length-tag-length-value encoding
+-- a TLTLV encoding!
+
+Thus explicit tagging is more redundant and wasteful than implicit tagging.
+But implicit tagging loses metadata that is useful for tools that can decode
+TLV encodings without reference to the schema (module) corresponding to the
+types of values encoded.
+
+TLV encodings were probably never justified except by lack of tooling and
+belief that codecs for TLV ERs can be hand-coded.  But TLV RTs exist, and
+because they are widely used, cannot be removed.
+
+## Other Encoding Rules
+
+The Packed Encoding Rules (PER) and Octet Encoding Rules (OER) are rules that
+resemble XDR, but with a 1-byte word size instead of 4-byte word size, and also
+with a 1-byte alignment instead of 4-byte alignment, yielding space-efficient
+encodings.
+
+Hand-coding XDR codecs is quite common and fairly easy.  Hand-coding PER and
+OER is widely considered difficult because PER and OER try to be quite
+space-efficient.
+
+Hand-coding TLV codecs used to be considered easy, but really, never was.
+
+But no one should hand-code codecs for any encoding rules.
+
+Instead, one should use a compiler.  This is true for ASN.1, and for all schema
+languages.
+
+## Encoding Rule Specific Syntactic Forms
+
+Some encoding rules require specific syntactic forms for some aspects of them.
+
+For example, the JER (JSON Encoding Rules) provide for syntax to select the use
+of JSON arrays vs. JSON objects for encoding structure types.
+
+For example, the TLV encoding rules provide for syntax for specifying
+alternative tags for disambiguation.
+
+## ASN.1 Syntax Specifications
+
+ - The base specification is ITU-T
+   [X.680](https://www.itu.int/rec/T-REC-X.680-202102-I/en).
+
+ - Additional syntax extensions include:
+
+    - [X.681 ASN.1 Information object specification](https://www.itu.int/rec/T-REC-X.681/en)
+    - [X.682 ASN.1 Constraint specification](https://www.itu.int/rec/T-REC-X.682/en)
+    - [X.682 ASN.1 Parameterization of ASN.1 specifications](https://www.itu.int/rec/T-REC-X.683/en)
+
+   Together these three specifications make the formal specification of open
+   types possible.
+
+## ASN.1 Encoding Rules Specifications
+
+ - The TLV Basic, Distinguished, and Canonical Encoding Rules (BER, DER, CER)
+   are described in ITU-T [X.690](https://www.itu.int/rec/T-REC-X.690/en).
+
+ - The more flat-buffers/XDR-like Packed Encoding Rules (PER) are described in
+   ITU-T [X.691](https://www.itu.int/rec/T-REC-X.691/en), and its successor,
+   the Octet Encoding Rules (OER) are described in
+   [X.696](https://www.itu.int/rec/T-REC-X.692/en).
+
+ - The XML Encoding Rules (XER) are described in ITU-T
+   [X.693](https://www.itu.int/rec/T-REC-X.693/en).
+
+   Related is the [X.694 Mapping W3C XML schema definitions into ASN.1](https://www.itu.int/rec/T-REC-X.694/en)
+
+ - The JSON Encoding Rules (JER) are described in ITU-T
+   [X.697](https://www.itu.int/rec/T-REC-X.697/en).
+
+ - The Generic String Encoding Rules are specified by IETF RFCs
+   [RFC3641](https://datatracker.ietf.org/doc/html/rfc3641),
+   [RFC3642](https://datatracker.ietf.org/doc/html/rfc3642),
+   [RFC4792](https://datatracker.ietf.org/doc/html/rfc4792).
+
+Additional ERs can be added.
+
+For example, XDR can clearly encode a very large subset of ASN.1, and with a
+few additional conventions, all of ASN.1.
+
+NDR too can clearly encode a very large subset of ASN.1, and with a few
+additional conventions, all of ASN.  However, ASN.1 is not sufficiently rich a
+_syntax_ to express all of what NDR can express (think of NDR conformant and/or
+varying arrays), though with some extensions it could.
+
+## Commentary
+
+The text in this section is the personal opinion of the author(s).
+
+ - ASN.1 gets a bad rap because BER/DER/CER are terrible encoding rules, as are
+   all TLV encoding rules.
+
+   The BER family of encoding rules is a disaster, yes, but ASN.1 itself is
+   not.  On the contrary, ASN.1 is quite rich in features and semantics -as
+   rich as any competitor- while also being very easy to write and understand
+   _as a syntax_.
+
+ - ASN.1 also gets a bad rap because its full syntax is not context-free, and
+   so parsing it can be tricky.
+
+   And yet the Heimdal ASN.1 compiler manages, using LALR(1) `yacc`/`bison`/`byacc`
+   parser-generators.  For the subset of ASN.1 that this compiler handles,
+   there are no ambiguities.  However, we understand that eventually we will
+   need run into ambiguities.
+
+   For example, `ValueSet` and `ObjectSet` are ambiguous.  X.680 says:
+
+   ```
+   ValueSet ::= "{" ElementSetSpecs "}"
+   ```
+
+   while X.681 says:
+
+   ```
+   ObjectSet ::= "{" ObjectSetSpec "}"
+   ```
+
+   and the set members can be just the symbolic names of members, in which case
+   there's no grammatical difference between those two productions.  These then
+   cause a conflict in the `FieldSetting` production, which is used in the
+   `ObjectDefn` production, which is used in defining an object (which is to be
+   referenced from some `ObjectSet` or `FieldSetting`).
+
+   This particular conflict can be resolved by one of:
+
+    - limiting the power of object sets by disallowing recursion (object sets
+      containing objects that have field settings that are object sets ...),
+
+    - or by introducing additional required and disambiguating syntactic
+      elements that preclude full compliance with ASN.1,
+
+    - or by simply using the same production and type internally to handle
+      both, the `ValueSet` and `ObjectSet` productions and then internally
+      resolving the actual type as late as possible by either inspecting the
+      types of the set members or by inspecting the expected kind of field that
+      the `ValueSet`-or-`ObjectSet` is setting.
+
+   Clearly, only the last of these is satisfying, but it is more work for the
+   compiler developer.
+
+ - TLV encodings are bad because they yield unnecessary redundance in
+   encodings.  This is space-inefficient, but also a source of bugs in
+   hand-coded codecs for TLV encodings.
+
+   EXPLICIT tagging makes this worse by making the encoding a TLTLV encoding
+   (tag length tag length value).  (The inner TLV is the V for the outer TL.)
+
+ - TLV encodings are often described as "self-describing" because one can
+   usually write a `dumpasn1` style of tool that attempts to decode a TLV
+   encoding of a value without reference to the value's type definition.
+
+   The use of `IMPLICIT` tagging with BER/DER/CER makes schema-less `dumpasn1`
+   style tools harder to use, as some type information is lost.  E.g., a
+   primitive type implicitly tagged with a context tag results in a TLV
+   encoding where -without reference to the schema- the tag denotes no
+   information about the type of the value encoded.  The user is left to figure
+   out what kind of data that is and to then decode it by hand.  For
+   constructed types (arrays and structures), implicit tagging does not really
+   lose any metadata about the type that wasn't already lost by BER/DER/CER, so
+   there is no great loss there.
+
+   However, Heimdal's ASN.1 compiler includes an `asn1_print(1)` utility that
+   can print DER-encoded values in much more detail than a schema-less
+   `dumpasn1` style of tool can.  This is because `asn1_print(1)` includes
+   a number of compiled ASN.1 modules, and it can be extended to include more.
+
+ - There is some merit to BER, however.  Specifically, an appropriate use of
+   indeterminate length encoding with BER can yield on-line encoding.  Think of
+   encoding streams of indeterminate size -- this cannot be done with DER or
+   Flat Buffers, or most encodings, though it can be done with some encodings,
+   such as BER and NDR (NDR has "pipes" for this).
+
+   Some clues are needed in order to produce an codec that can handle such
+   on-line behavior.  In IDL/NDR that clue comes from the "pipe" type.  In
+   ASN.1 there is no such clue and it would have to be provided separately to
+   the ASN.1 compiler (e.g., as a command-line option).
+
+ - Protocol Buffers is a TLV encoding.  There was no need to make it a TLV
+   encoding.
+
+   Public opinion seems to prefer Flat Buffers now, which is not a TLV encoding
+   and which is more comparable to XDR/NDR/PER/OER.
+
+# Heimdal ASN.1 Compiler
+
+The Heimdal ASN.1 compiler and library implement a very large subset of the
+ASN.1 syntax, meanign large parts of X.680, X.681, X.682, and X.683.
+
+The compiler currently emits:
+
+ - a JSON representation of ASN.1 modules
+ - C types corresponding to ASN.1 modules' types
+ - C functions for DER (and some BER) codecs for ASN.1 modules' types
+
+We vaguely hope to eventually move to using the JSON representation of ASN.1
+modules to do code generation in a programming language like `jq` rather than
+in C.  The idea there is to make it much easier to target other programming
+languages than C, especially Rust, so that we can start moving Heimdal to Rust
+(first after this would be `lib/hx509`, then `lib/krb5`, then `lib/hdb`, then
+`lib/gssapi`, then `kdc/`).
+
+The compiler has two "backends":
+
+ - C code generation
+ - "template" (byte-code) generation and interpretation
+
+## Features and Limitations
+
+Supported encoding rules:
+
+ - DER
+ - BER decoding (but not encoding)
+
+As well, the Heimdal ASN.1 compiler can render values as JSON using an ad-hoc
+metaschema that is not quite JER-compliant.  A sample rendering of a complex
+PKIX `Certificate` with all typed holes automatically decoded is shown in
+[README.md#features](README.md#features).
+
+The Heimdal ASN.1 compiler supports open types via X.681/X.682/X.683 syntax.
+Specifically: (when using the template backend) the generated codecs can
+automatically and recursively decode and encode through "typed holes".
+
+An "open type", also known as "typed holes" or "references", is a part of a
+structure that can contain the encoding of a value of some arbitrary data type,
+with a hint of that value's type expressed in some way such as: via an "object
+identifier", or an integer, or even a string (e.g., like a URN).
+
+Open types are widely used as a form of extensibility.
+
+Historically, open types were never documented formally, but with natural
+language (e.g., English) meant only for humans to understand.  Documenting open
+types with formal syntax allows compilers to support them specially.
+
+See the the [`asn1_compile(1)` manual page](#Manual-Page-for-asn1_compile)
+below and [README.md#features](README.md#features), for more details on
+limitations.  Excerpt from the manual page:
+
+```
+The Information Object System support includes automatic codec support
+for encoding and decoding through “open types” which are also known as
+“typed holes”.  See RFC5912 for examples of how to use the ASN.1 Infor-
+mation Object System via X.681/X.682/X.683 annotations.  See the com-
+piler's README files for more information on ASN.1 Information Object
+System support.
+
+Extensions specific to Heimdal are generally not syntactic in nature but
+rather command-line options to this program.  For example, one can use
+command-line options to:
+      •       enable decoding of BER-encoded values;
+      •       enable RFC1510-style handling of ‘BIT STRING’ types;
+      •       enable saving of as-received encodings of specific types
+              for the purpose of signature validation;
+      •       generate add/remove utility functions for array types;
+      •       decorate generated ‘struct’ types with fields that are nei-
+              ther encoded nor decoded;
+etc.
+
+ASN.1 x.680 features supported:
+      •       most primitive types (except BMPString and REAL);
+      •       all constructed types, including SET and SET OF;
+      •       explicit and implicit tagging.
+
+Size and range constraints on the ‘INTEGER’ type cause the compiler to
+generate appropriate C types such as ‘int’, ‘unsigned int’, ‘int64_t’,
+‘uint64_t’.  Unconstrained ‘INTEGER’ is treated as ‘heim_integer’, which
+represents an integer of arbitrary size.
+
+Caveats and ASN.1 x.680 features not supported:
+      •       JSON encoding support is not quite X.697 (JER) compatible.
+              Its JSON schema is subject to change without notice.
+      •       Control over C types generated is very limited, mainly only
+              for integer types.
+      •       When using the template backend, `SET { .. }` types are
+              currently not sorted by tag as they should be, but if the
+              module author sorts them by hand then correct DER will be
+              produced.
+      •       ‘AUTOMATIC TAGS’ is not supported.
+      •       The REAL type is not supported.
+      •       The EmbeddedPDV type is not supported.
+      •       The BMPString type is not supported.
+      •       The IA5String is not properly supported, as it's essen‐
+              tially treated as a UTF8String with a different tag.
+      •       All supported non-octet strings are treated as like the
+              UTF8String type.
+      •       Only types can be imported into ASN.1 modules at this time.
+      •       Only simple value syntax is supported.  Constructed value
+              syntax (i.e., values of SET, SEQUENCE, SET OF, and SEQUENCE
+              OF types), is not supported.  Values of `CHOICE` types are
+              also not supported.
+```
+
+## Easy-to-Use C Types
+
+The Heimdal ASN.1 compiler generates easy-to-use C types for ASN.1 types.
+
+Unconstrained `INTEGER` becomes `heim_integer` -- a large integer type.
+
+Constrained `INTEGER` types become `int`, `unsigned int`, `int64_t`, or
+`uint64_t`.
+
+String types generally become `char *` (C strings, i.e., NUL-terminated) or
+`heim_octet_string` (a counted byte string type).
+
+`SET` and `SEQUENCE` types become `struct` types.
+
+`SET OF SomeType` and `SEQUENCE OF SomeType` types become `struct` types with a
+`size_t len` field counting the number of elements of the array, and a pointer
+to `len` consecutive elements of the `SomeType` type.
+
+`CHOICE` types become a `struct` type with an `enum` discriminant and a
+`union`.
+
+Type names have hyphens turned to underscores.
+
+Every ASN.1 gets a `typedef`.
+
+`OPTIONAL` members of `SET`s and `SEQUENCE`s become pointer types (`NULL`
+values mean "absent", while non-`NULL` values mean "present").
+
+Tags are of no consequence to the C types generated.
+
+Types definitions to be topographically sorted because of the need to have
+forward declarations.
+
+Forward `typedef` declarations are emmitted.
+
+Circular type dependencies are allowed provided that `OPTIONAL` members are
+used for enough circular references so as to avoid creating types whose values
+have infinite size!  (Circular type dependencies can be used to build linked
+lists, though that is a bit of a silly trick when one can use arrays instead,
+though in principle this could be used to do on-line encoding and decoding of
+arbitrarily large streams of objects.  See the [commentary](#Commentary)
+section.)
+
+Thus `Certificate` becomes:
+
+```C
+typedef struct TBSCertificate {
+  heim_octet_string _save; /* see below! */
+  Version *version;
+  CertificateSerialNumber serialNumber;
+  AlgorithmIdentifier signature;
+  Name issuer;
+  Validity validity;
+  Name subject;
+  SubjectPublicKeyInfo subjectPublicKeyInfo;
+  heim_bit_string *issuerUniqueID;
+  heim_bit_string *subjectUniqueID;
+  Extensions *extensions;
+} TBSCertificate;
+
+typedef struct Certificate {
+  TBSCertificate tbsCertificate;
+  AlgorithmIdentifier signatureAlgorithm;
+  heim_bit_string signatureValue;
+} Certificate;
+```
+
+The `_save` field in `TBSCertificate` is generated when the compiler is invoked
+with `--preserve-binary=TBSCertificate`, and the decoder will place the
+original encoding of the value of a `TBSCertificate` in the decoded
+`TBSCertificate`'s `_save` field.  This is very useful for signature
+validation: the application need not attempt to re-encode a `TBSCertificate` in
+order to validate its signature from the containing `Certificate`!
+
+Let's compare to the `Certificate` as defined in ASN.1:
+
+```ASN.1
+   Certificate  ::=  SEQUENCE  {
+        tbsCertificate       TBSCertificate,
+        signatureAlgorithm   AlgorithmIdentifier,
+        signatureValue       BIT STRING
+   }
+
+   TBSCertificate  ::=  SEQUENCE  {
+        version         [0]  EXPLICIT Version DEFAULT v1,
+        serialNumber         CertificateSerialNumber,
+        signature            AlgorithmIdentifier,
+        issuer               Name,
+        validity             Validity,
+        subject              Name,
+        subjectPublicKeyInfo SubjectPublicKeyInfo,
+        issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
+        subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
+        extensions      [3]  EXPLICIT Extensions OPTIONAL
+   }
+```
+
+The conversion from ASN.1 to C is quite mechanical and natural.  That's what
+code-generators do, of course, so it's not surprising.  But you can see that
+`Certificate` in ASN.1 and C differs only in:
+
+ - in C `SEQUENCE { }` becomes `struct { }`
+ - in C the type name comes first
+ - in C we drop the tagging directives (e.g., `[0]  EXPLICIT`)
+ - `DEFAULT` and `OPTIONAL` become pointers
+ - in C we use `typedef`s to make the type names usable without having to add
+   `struct`
+
+## Circular Type Dependencies
+
+As noted above, circular type dependencies are supported.
+
+Here's a toy example from [XDR](https://datatracker.ietf.org/doc/html/rfc4506)
+-- a linked list:
+
+```XDR
+struct stringentry {
+   string item<>;
+   stringentry *next;
+};
+
+typedef stringentry *stringlist;
+```
+
+Here is the same example in ASN.1:
+
+```ASN.1
+Stringentry ::= SEQUENCE {
+    item UTF8String,
+    next Stringentry OPTIONAL
+}
+```
+
+which compiles to:
+
+```C
+typedef struct Stringentry Stringentry;
+struct Stringentry {
+    char *item;
+    Stringentry *next;
+};
+```
+
+This illustrates that `OPTIONAL` members in ASN.1 are like pointers in XDR.
+
+Making the `next` member not `OPTIONAL` would cause `Stringentry` to be
+infinitely large, and there is no way to declare the equivalent in C anyways
+(`struct foo { int a; struct foo b; };` will not compile in C).
+
+Mutual circular references are allowed too.  In the following example `A`
+refers to `B` and `B` refers to `A`, but as long as one (or both) of those
+references is `OPTIONAL`, then it will be allowed:
+
+```ASN1
+A ::= SEQUENCE { name UTF8String, b B }
+B ::= SEQUENCE { name UTF8String, a A OPTIONAL }
+```
+
+```ASN1
+A ::= SEQUENCE { name UTF8String, b B OPTIONAL }
+B ::= SEQUENCE { name UTF8String, a A }
+```
+
+```ASN1
+A ::= SEQUENCE { name UTF8String, b B OPTIONAL }
+B ::= SEQUENCE { name UTF8String, a A OPTIONAL }
+```
+
+In the above example values of types `A` and `B` together form a linked list.
+
+Whereas this is broken and will not compile:
+
+```ASN1
+A ::= SEQUENCE { name UTF8String, b B }
+B ::= SEQUENCE { name UTF8String, a A } -- infinite size!
+```
+
+## Generated APIs For Any Given Type T
+
+The C functions generated for ASN.1 types are all of the same form, for any
+type `T`:
+
+```C
+int    decode_T(const unsigned char *, size_t, TBSCertificate *, size_t *);
+int    encode_T(unsigned char *, size_t, const TBSCertificate *, size_t *);
+size_t length_T(const TBSCertificate *);
+int      copy_T(const TBSCertificate *, TBSCertificate *);
+void     free_T(TBSCertificate *);
+char *  print_T(const TBSCertificate *, int);
+```
+
+The `decode_T()` functions take a pointer to the encoded data, its length in
+bytes, a pointer to a C object of type `T` to decode into, and a pointer into
+which the number of bytes consumed will be written.
+
+The `length_T()` functions take a pointer to a C object of type `T` and return
+the number of bytes its encoding would need.
+
+The `encode_T()` functions take a pointer to enough bytes to encode the value,
+the number of bytes found there, a pointer to a C object of type `T` whose
+value to encode, and a pointer into which the number of bytes output will be
+written.
+
+> NOTE WELL: The first argument to `encode_T()` functions must point to the
+> last byte in the buffer into which the encoder will encode the value.  This
+> is because the encoder encodes from the end towards the beginning.
+
+The `print_T()` functions encode the value of a C object of type `T` in JSON
+(though not in JER-compliant JSON).  A sample printing of a complex PKIX
+`Certificate` can be seen in [README.md#features](README.md#features).
+
+The `copy_T()` functions take a pointer to a source C object of type `T` whose
+value they then copy to the destination C object of the same type.  The copy
+constructor is equivalent to encoding the source value and decoding it onto the
+destination.
+
+The `free_T()` functions take a pointer to a C object of type `T` whose value's
+memory resources will be released.  Note that the C object _itself_ is not
+freed, only its _content_.
+
+See [sample usage](#Using-the-Generated-APIs).
+
+These functions are all recursive.
+
+> NOTE WELL: These functions use the standard C memory allocator.
+> When using the Windows statically-linked C run-time, you must link with
+> `LIBASN1.LIB` to avoid possibly freeing memory allocated by a different
+> allocator.
+
+## Error Handling
+
+All codec functions that return errors return them as `int`.
+
+Error values are:
+
+ - system error codes (use `strerror()` to display them)
+
+or
+
+ - `ASN1_BAD_TIMEFORMAT`
+ - `ASN1_MISSING_FIELD`
+ - `ASN1_MISPLACED_FIELD`
+ - `ASN1_TYPE_MISMATCH`
+ - `ASN1_OVERFLOW`
+ - `ASN1_OVERRUN`
+ - `ASN1_BAD_ID`
+ - `ASN1_BAD_LENGTH`
+ - `ASN1_BAD_FORMAT`
+ - `ASN1_PARSE_ERROR`
+ - `ASN1_EXTRA_DATA`
+ - `ASN1_BAD_CHARACTER`
+ - `ASN1_MIN_CONSTRAINT`
+ - `ASN1_MAX_CONSTRAINT`
+ - `ASN1_EXACT_CONSTRAINT`
+ - `ASN1_INDEF_OVERRUN`
+ - `ASN1_INDEF_UNDERRUN`
+ - `ASN1_GOT_BER`
+ - `ASN1_INDEF_EXTRA_DATA`
+
+You can use the `com_err` library to display these errors as strings:
+
+```C
+    struct et_list *etl = NULL;
+    initialize_asn1_error_table_r(&etl);
+    int ret;
+
+    ...
+
+    ret = decode_T(...);
+    if (ret) {
+        const char *error_message;
+
+        if ((error_message = com_right(etl, ret)) == NULL)
+            error_message = strerror(ret);
+
+        fprintf(stderr, "Failed to decode T: %s\n",
+                error_message ? error_message : "<unknown error>");
+    }
+```
+
+## Using the Generated APIs
+
+Value construction is as usual in C.  Use the standard C allocator for
+allocating values of `OPTIONAL` fields.
+
+Value destruction is done with the `free_T()` destructors.
+
+Decoding is just:
+
+```C
+    Certificate c;
+    size_t sz;
+    int ret;
+
+    ret = decode_Certificate(pointer_to_encoded_bytes,
+                             number_of_encoded_bytes,
+                             &c, &sz);
+    if (ret == 0) {
+        if (sz != number_of_encoded_bytes)
+            warnx("Extra bytes after Certificate!");
+    } else {
+        warnx("Failed to decode certificate!");
+        return ret;
+    }
+
+    /* Now do stuff with the Certificate */
+    ...
+
+    /* Now release the memory */
+    free_Certificate(&c);
+```
+
+Encoding involves calling the `length_T()` function to compute the number of
+bytes needed for the encoding, then allocating that many bytes, then calling
+`encode_T()` to encode into that memory.  A convenience macro,
+`ASN1_MALLOC_ENCODE()`, does all three operations:
+
+```C
+    Certificate c;
+    size_t num_bytes, sz;
+    char *bytes = NULL;
+    int ret;
+
+    /* Build a `Certificate` in `c` */
+    ...
+
+    /* Encode `c` */
+    ASN1_MALLOC_ENCODE(Certificate, bytes, num_bytes, &c, sz, ret);
+    if (ret)
+        errx(1, "Out of memory encoding a Certificate");
+
+    /* This check isn't really needed -- it never fails */
+    if (num_bytes != sz)
+        errx(1, "ASN.1 encoder internal error");
+
+    /* Send the `num_bytes` in `bytes` */
+    ...
+
+    /* Free the memory allocated by `ASN1_MALLOC_ENCODE()` */
+    free(bytes);
+```
+
+or, the same code w/o the `ASN1_MALLOC_ENCODE()` macro:
+
+```C
+    Certificate c;
+    size_t num_bytes, sz;
+    char *bytes = NULL;
+    int ret;
+
+    /* Build a `Certificate` in `c` */
+    ...
+
+    /* Encode `c` */
+    num_bytes = length_Certificate(&c);
+    bytes = malloc(num_bytes);
+    if (bytes == NULL)
+        errx(1, "Out of memory");
+
+    /*
+     * Note that the memory to encode into, passed to encode_Certificate()
+     * must be a pointer to the _last_ byte of that memory, not the first!
+     */
+    ret = encode_Certificate(bytes + num_bytes - 1, num_bytes,
+                             &c, &sz);
+    if (ret)
+        errx(1, "Out of memory encoding a Certificate");
+
+    /* This check isn't really needed -- it never fails */
+    if (num_bytes != sz)
+        errx(1, "ASN.1 encoder internal error");
+
+    /* Send the `num_bytes` in `bytes` */
+    ...
+
+    /* Free the memory allocated by `ASN1_MALLOC_ENCODE()` */
+    free(bytes);
+```
+
+## Open Types
+
+The handling of X.681/X.682/X.683 syntax for open types is described at length
+in [README-X681.md](README-X681.md).
+
+## Command-line Usage
+
+The compiler takes an ASN.1 module file name and outputs a C header and C
+source files, as well as various other metadata files:
+
+ - `<module>_asn1.h`
+
+   This file defines all the exported types from the given ASN.1 module as C
+   types.
+
+ - `<module>_asn1-priv.h`
+
+   This file defines all the non-exported types from the given ASN.1 module as
+   C types.
+
+ - `<module>_asn1_files`
+
+   This file is needed because the default is to place the code for each type
+   in a separate C source file, which can help improve the performance of
+   builds by making it easier to parallelize the building of the ASN.1 module.
+
+ - `asn1_<Type>.c` or `asn1_<module>_asn1.c`
+
+   If `--one-code-file` is used, then the implementation of the module will be
+   in a file named `asn1_<module>_asn1.c`, otherwise the implementation of each
+   type in the module will be in `asn1_<Type>.c`.
+
+ - `<module>_asn1.json`
+
+   This file contains a JSON description of the module (the schema for this
+   file is ad-hoc and subject to change w/o notice).
+
+ - `<module>_asn1_oids.c`
+
+   This file is meant to be `#include`d, and contains just calls to a
+   `DEFINE_OID_WITH_NAME(sym)` macro that the user must define, where `sym` is
+   the suffix of the name of a variable of type `heim_oid`.  The full name of
+   the variable is `asn1_oid_ ## sym`.
+
+ - `<module>_asn1_syms.c`
+
+   This file is meant to be `#include`d, and contains just calls to these
+   macros that the user must define:
+
+    - `ASN1_SYM_INTVAL(name, genname, sym, num)`
+    - `ASN1_SYM_OID(name, genname, sym)`
+    - `ASN1_SYM_TYPE(name, genname, sym)`
+
+   where `name` is the C string literal name of the value or type as it appears
+   in the ASN.1 module, `genname` is the C string literal name of the value or
+   type as generated (e.g., with hyphens replaced by underscores), `sym` is the
+   symbol or symbol suffix (see above0, and `num` is the numeric value of the
+   integer value.
+
+Control over the C types used for ASN.1 `INTEGER` types is done by ASN.1 usage
+convention:
+
+ - unconstrained `INTEGER` types, or `INTEGER` types where only the minimum, or
+   only the maximum value is specified generate `heim_integer`
+
+ - constrained `INTEGER` types whose minimum and maximum fit in `unsigned`'s
+   range generate `unsigned`
+
+ - constrained `INTEGER` types whose minimum and maximum fit in `int`'s
+   range generate `int`
+
+ - constrained `INTEGER` types whose minimum and maximum fit in `uin64_t`'s
+   range generate `uin64_t`
+
+ - constrained `INTEGER` types whose minimum and maximum fit in `in64_t`'s
+   range generate `in64_t`
+
+ - `INTEGER` types with named members generate a C `struct` with `unsigned int`
+   bit-field members
+
+ - all other `INTEGER` types generate `heim_integer`
+
+Various code generation options are provided as command-line options or as
+ASN.1 usage conventions:
+
+ - `--type-file=C-HEADER-FILE` -- generate an `#include` directive to include
+   that header for some useful base types (within Heimdal we use `krb5-types.h`
+   as that header)
+
+ - `--template` -- use the "template" (byte-coded) backend
+
+ - `--one-code-file` -- causes all the code generated to be placed in one C
+   source file (mutually exclusive with `--template`)
+
+ - `--support-ber` -- accept non-DER BER when decoding
+
+ - `--preserve-binary=TYPE` -- add a `_save` field to the C struct type for the
+   ASN.1 `TYPE` where the decoder will save the original encoding of the value
+   of `TYPE` it decodes (useful for cryptographic signature verification!)
+
+ - `--sequence=TYPE` -- generate `add_TYPE()` and `remove_TYPE()` utility
+   functions (`TYPE` must be a `SET OF` or `SEQUENCE OF` type)
+
+ - `--decorate=DECORATION` -- add fields to generated C struct types as
+   described in the `DECORATION` (see the
+   [manual page](#Manual-Page-for-asn1_compile) below)
+
+   Decoration fields are never encoded or decoded.  They are meant to be used
+   for, e.g., application state keeping.
+
+ - `--no-parse-units` -- normally the compiler generates code to use the
+   Heimdal `libroken` "units" utility for displaying bit fields; this option
+   disables this
+
+See the [manual page for `asn1_compile(1)`](#Manual-Page-for-asn1_compile) for
+a full listing of command-line options.
+
+### Manual Page for `asn1_compile(1)`
+
+```
+ASN1_COMPILE(1)                  BSD General Commands Manual          ASN1_COMPILE(1)
+
+NAME
+     asn1_compile — compile ASN.1 modules
+
+SYNOPSIS
+     asn1_compile [--template] [--prefix-enum] [--enum-prefix=PREFIX]
+                 [--encode-rfc1510-bit-string] [--decode-dce-ber]
+                 [--support-ber] [--preserve-binary=TYPE] [--sequence=TYPE]
+                 [--decorate=DECORATION] [--one-code-file] [--gen-name=NAME]
+                 [--option-file=FILE] [--original-order] [--no-parse-units]
+                 [--type-file=C-HEADER-FILE] [--version] [--help]
+                 [FILE.asn1 [NAME]]
+
+DESCRIPTION
+     asn1_compile compiles an ASN.1 module into C source code and header
+     files.
+
+     A fairly large subset of ASN.1 as specified in X.680, and the ASN.1 In‐
+     formation Object System as specified in X.681, X.682, and X.683 is sup‐
+     ported, with support for the Distinguished Encoding Rules (DER), partial
+     Basic Encoding Rules (BER) support, and experimental JSON support (encod‐
+     ing only at this time).
+
+     See the compiler's README files for details about the C code and inter‐
+     faces it generates.
+
+     The Information Object System support includes automatic codec support
+     for encoding and decoding through “open types” which are also known as
+     “typed holes”.  See RFC 5912 for examples of how to use the ASN.1 Infor‐
+     mation Object System via X.681/X.682/X.683 annotations.  See the com‐
+     piler's README files for more information on ASN.1 Information Object
+     System support.
+
+     Extensions specific to Heimdal are generally not syntactic in nature but
+     rather command-line options to this program.  For example, one can use
+     command-line options to:
+          •     enable decoding of BER-encoded values;
+          •     enable RFC1510-style handling of ‘BIT STRING’ types;
+          •     enable saving of as-received encodings of specific types
+                  for the purpose of signature validation;
+          •     generate add/remove utility functions for array types;
+          •     decorate generated ‘struct’ types with fields that are nei‐
+                  ther encoded nor decoded;
+     etc.
+
+     ASN.1 x.680 features supported:
+          •     most primitive types (except BMPString and REAL);
+          •     all constructed types, including SET and SET OF;
+          •     explicit and implicit tagging.
+
+     Size and range constraints on the ‘INTEGER’ type cause the compiler to
+     generate appropriate C types such as ‘int’, ‘unsigned int’, ‘int64_t’,
+     ‘uint64_t’.  Unconstrained ‘INTEGER’ is treated as ‘heim_integer’, which
+     represents an integer of arbitrary size.
+
+     Caveats and ASN.1 x.680 features not supported:
+          •     JSON encoding support is not quite X.697 (JER) compatible.
+                  Its JSON schema is subject to change without notice.
+          •     Control over C types generated is very limited, mainly only
+                  for integer types.
+          •     When using the template backend, `SET { .. }` types are
+                  currently not sorted by tag as they should be, but if the
+                  module author sorts them by hand then correct DER will be
+                  produced.
+          •     ‘AUTOMATIC TAGS’ is not supported.
+          •     The REAL type is not supported.
+          •     The EmbeddedPDV type is not supported.
+          •     The BMPString type is not supported.
+          •     The IA5String is not properly supported, as it's essen‐
+                  tially treated as a UTF8String with a different tag.
+          •     All supported non-octet strings are treated as like the
+                  UTF8String type.
+          •     Only types can be imported into ASN.1 modules at this time.
+          •     Only simple value syntax is supported.  Constructed value
+                  syntax (i.e., values of SET, SEQUENCE, SET OF, and SEQUENCE
+                  OF types), is not supported.  Values of `CHOICE` types are
+                  also not supported.
+
+     Options supported:
+
+     --template
+            Use the “template” backend instead of the “codegen” backend
+            (which is the default backend).
+
+            The template backend generates “templates” which are akin to
+            bytecode, and which are interpreted at run-time.
+
+            The codegen backend generates C code for all functions directly,
+            with no template interpretation.
+
+            The template backend scales better than the codegen backend be‐
+            cause as we add support for more encoding rules and more opera‐
+            tions (we may add value comparators) the templates stay mostly
+            the same, thus scaling linearly with size of module.  Whereas the
+            codegen backend scales linear with the product of module size and
+            number of encoding rules supported.
+
+     --prefix-enum
+            This option should be removed because ENUMERATED types should al‐
+            ways have their labels prefixed.
+
+     --enum-prefix=PREFIX
+            This option should be removed because ENUMERATED types should al‐
+            ways have their labels prefixed.
+
+     --encode-rfc1510-bit-string
+            Use RFC1510, non-standard handling of “BIT STRING” types.
+
+     --decode-dce-ber
+
+     --support-ber
+
+     --preserve-binary=TYPE
+            Generate a field named ‘_save’ in the C struct generated for the
+            named TYPE.  This field is used to preserve the original encoding
+            of the value of the TYPE.
+
+            This is useful for cryptographic applications so that they can
+            check signatures of encoded values as-received without having to
+            re-encode those values.
+
+            For example, the TBSCertificate type should have values preserved
+            so that Certificate validation can check the signatureValue over
+            the tbsCertificate's value as-received.
+
+            The alternative of encoding a value to check a signature of it is
+            brittle.  For types where non-canonical encodings (such as BER)
+            are allowed, this alternative is bound to fail.  Thus the point
+            of this option.
+
+     --sequence=TYPE
+            Generate add/remove functions for the named ASN.1 TYPE which must
+            be a ‘SET OF’ or ‘SEQUENCE OF’ type.
+
+     --decorate=ASN1-TYPE:FIELD-ASN1-TYPE:fname[?]
+            Add to the C struct generated for the given ASN.1 SET, SEQUENCE,
+            or CHOICE type named ASN1-TYPE a “hidden” field named fname of
+            the given ASN.1 type FIELD-ASN1-TYPE, but do not encode or decode
+            it.  If the fname ends in a question mark, then treat the field
+            as OPTIONAL.
+
+            This is useful for adding fields to existing types that can be
+            used for internal bookkeeping but which do not affect interoper‐
+            ability because they are neither encoded nor decoded.  For exam‐
+            ple, one might decorate a request type with state needed during
+            processing of the request.
+
+     --decorate=ASN1-TYPE:void*:fname
+            Add to the C struct generated for the given ASN.1 SET, SEQUENCE,
+            or CHOICE type named ASN1-TYPE a “hidden” field named fname of
+            type ‘void *’ (but do not encode or decode it.
+
+            The destructor and copy constructor functions generated by this
+            compiler for ASN1-TYPE will set this field to the ‘NULL’ pointer.
+
+     --decorate=ASN1-TYPE:FIELD-C-TYPE:fname[?]:[copyfn]:[freefn]:header
+            Add to the C struct generated for the given ASN.1 SET, SEQUENCE,
+            or CHOICE type named ASN1-TYPE a “hidden” field named fname of
+            the given external C type FIELD-C-TYPE, declared in the given
+            header but do not encode or decode this field.  If the fname ends
+            in a question mark, then treat the field as OPTIONAL.
+
+            The header must include double quotes or angle brackets.  The
+            copyfn must be the name of a copy constructor function that takes
+            a pointer to a source value of the type, and a pointer to a des‐
+            tination value of the type, in that order, and which returns zero
+            on success or else a system error code on failure.  The freefn
+            must be the name of a destructor function that takes a pointer to
+            a value of the type and which releases resources referenced by
+            that value, but does not free the value itself (the run-time al‐
+            locates this value as needed from the C heap).  The freefn should
+            also reset the value to a pristine state (such as all zeros).
+
+            If the copyfn and freefn are empty strings, then the decoration
+            field will neither be copied nor freed by the functions generated
+            for the TYPE.
+
+     --one-code-file
+            Generate a single source code file.  Otherwise a separate code
+            file will be generated for every type.
+
+     --gen-name=NAME
+            Use NAME to form the names of the files generated.
+
+     --option-file=FILE
+            Take additional command-line options from FILE.
+
+     --original-order
+            Attempt to preserve the original order of type definition in the
+            ASN.1 module.  By default the compiler generates types in a topo‐
+            logical sort order.
+
+     --no-parse-units
+            Do not generate to-int / from-int functions for enumeration
+            types.
+
+     --type-file=C-HEADER-FILE
+            Generate an include of the named header file that might be needed
+            for common type defintions.
+
+     --version
+
+     --help
+
+NOTES
+     Currently only the template backend supports automatic encoding and de‐
+     coding of open types via the ASN.1 Information Object System and
+     X.681/X.682/X.683 annotations.
+
+HEIMDAL                               February 22, 2021                       HEIMDAL
+```
+
+# Future Directions
+
+The Heimdal ASN.1 compiler is focused on PKIX and Kerberos, and is almost
+feature-complete for dealing with those.  It could use additional support for
+X.681/X.682/X.683 elements that would allow the compiler to understand
+`Certificate ::= SIGNED{TBSCertificate}`, particularly the ability to
+automatically validate cryptographic algorithm parameters.  However, this is
+not that important.
+
+Another feature that might be nice is the ability of callers to specify smaller
+information object sets when decoding values of types like `Certificate`,
+mainly to avoid spending CPU cycles and memory allocations on decoding types in
+typed holes that are not of interest to the application.
+
+For testing purposes, a JSON reader to go with the JSON printer might be nice,
+and anyways, would make for a generally useful tool.
+
+Another feature that would be nice would to automatically generate SQL and LDAP
+code for HDB based on `lib/hdb/hdb.asn1` (with certain usage conventions and/or
+compiler command-line options to make it possible to map schemas usefully).
+
+For the `hxtool` command, it would be nice if the user could input arbitrary
+certificate extensions and `subjectAlternativeName` (SAN) values in JSON + an
+ASN.1 module and type reference that `hxtool` could then parse and encode using
+the ASN.1 compiler and library.  Currently the `hx509` library and its `hxtool`
+command must be taught about every SAN type.
index 94d24fc47eb6cc02c1618bd06485061eb74193d9..eb0308ee13cc3da15837d856a68f88e7b11b9bcf 100644 (file)
@@ -2,9 +2,11 @@
 
 include $(top_srcdir)/Makefile.am.common
 
-YFLAGS = -d -t
+WFLAGS += $(WFLAGS_ENUM_CONV)
 
-AM_CPPFLAGS += $(ROKEN_RENAME)
+YFLAGS = -o asn1parse.c -t
+
+AM_CPPFLAGS += $(ROKEN_RENAME) -I$(top_builddir)/include -I$(top_srcdir)/lib/base
 
 man_MANS = asn1_print.1 asn1_compile.1
 
@@ -30,64 +32,64 @@ libasn1template_la_LIBADD = \
        @LIB_com_err@ \
        $(LIBADD_roken)
 
-BUILT_SOURCES =                                \
-       $(gen_files_rfc2459:.x=.c)      \
-       $(gen_files_rfc4108:.x=.c)      \
-       $(gen_files_cms:.x=.c)          \
-       $(gen_files_krb5:.x=.c)         \
-       $(gen_files_ocsp:.x=.c)         \
-       $(gen_files_pkinit:.x=.c)       \
-       $(gen_files_pkcs8:.x=.c)        \
-       $(gen_files_pkcs9:.x=.c)        \
-       $(gen_files_pkcs10:.x=.c)       \
-       $(gen_files_pkcs12:.x=.c)       \
-       $(gen_files_digest:.x=.c)       \
-       $(gen_files_kx509:.x=.c)
-
-BUILT_TEMPLATE_SOURCES =                       \
-       $(gen_files_rfc2459_template:.x=.c)     \
-       $(gen_files_rfc4108_template:.x=.c)     \
-       $(gen_files_cms_template:.x=.c)         \
-       $(gen_files_krb5_template:.x=.c)        \
-       $(gen_files_ocsp_template:.x=.c)        \
-       $(gen_files_pkinit_template:.x=.c)      \
-       $(gen_files_pkcs8_template:.x=.c)       \
-       $(gen_files_pkcs9_template:.x=.c)       \
-       $(gen_files_pkcs10_template:.x=.c)      \
-       $(gen_files_pkcs12_template:.x=.c)      \
-       $(gen_files_digest_template:.x=.c)      \
-       $(gen_files_kx509_template:.x=.c)
-
-gen_files_krb5 = asn1_krb5_asn1.x
-gen_files_krb5_template = asn1_krb5_template_asn1.x
-gen_files_cms = asn1_cms_asn1.x
-gen_files_cms_template = asn1_cms_template_asn1.x
-gen_files_crmf = asn1_crmf_asn1.x
-gen_files_crmf_template = asn1_crmf_template_asn1.x
-gen_files_rfc2459 = asn1_rfc2459_asn1.x
-gen_files_rfc2459_template = asn1_rfc2459_template_asn1.x
-gen_files_rfc4108 = asn1_rfc4108_asn1.x
-gen_files_rfc4108_template = asn1_rfc4108_template_asn1.x
-gen_files_ocsp = asn1_ocsp_asn1.x
-gen_files_ocsp_template = asn1_ocsp_template_asn1.x
-gen_files_pkinit = asn1_pkinit_asn1.x
-gen_files_pkinit_template = asn1_pkinit_template_asn1.x
-gen_files_pkcs10 = asn1_pkcs10_asn1.x
-gen_files_pkcs10_template = asn1_pkcs10_template_asn1.x
-gen_files_pkcs12 = asn1_pkcs12_asn1.x
-gen_files_pkcs12_template = asn1_pkcs12_template_asn1.x
-gen_files_pkcs8 = asn1_pkcs8_asn1.x
-gen_files_pkcs8_template = asn1_pkcs8_template_asn1.x
-gen_files_pkcs9 = asn1_pkcs9_asn1.x
-gen_files_pkcs9_template = asn1_pkcs9_template_asn1.x
-gen_files_test = asn1_test_asn1.x
-gen_files_test_template = asn1_test_template_asn1.x
-gen_files_digest = asn1_digest_asn1.x
-gen_files_digest_template = asn1_digest_template_asn1.x
-gen_files_kx509 = asn1_kx509_asn1.x
-gen_files_kx509_template = asn1_kx509_template_asn1.x
-gen_files_x690sample = asn1_x690sample_asn1.x
-gen_files_x690sample_template = asn1_x690sample_template_asn1.x
+BUILT_SOURCES =                        \
+       $(gen_files_rfc2459)    \
+       $(gen_files_rfc4108)    \
+       $(gen_files_cms)        \
+       $(gen_files_krb5)       \
+       $(gen_files_ocsp)       \
+       $(gen_files_pkinit)     \
+       $(gen_files_pkcs8)      \
+       $(gen_files_pkcs9)      \
+       $(gen_files_pkcs10)     \
+       $(gen_files_pkcs12)     \
+       $(gen_files_digest)     \
+       $(gen_files_kx509)
+
+BUILT_TEMPLATE_SOURCES =               \
+       $(gen_files_rfc2459_template)   \
+       $(gen_files_rfc4108_template)   \
+       $(gen_files_cms_template)       \
+       $(gen_files_krb5_template)      \
+       $(gen_files_ocsp_template)      \
+       $(gen_files_pkinit_template)    \
+       $(gen_files_pkcs8_template)     \
+       $(gen_files_pkcs9_template)     \
+       $(gen_files_pkcs10_template)    \
+       $(gen_files_pkcs12_template)    \
+       $(gen_files_digest_template)    \
+       $(gen_files_kx509_template)
+
+gen_files_krb5 = asn1_krb5_asn1.c
+gen_files_krb5_template = asn1_krb5_template_asn1.c
+gen_files_cms = asn1_cms_asn1.c
+gen_files_cms_template = asn1_cms_template_asn1.c
+gen_files_crmf = asn1_crmf_asn1.c
+gen_files_crmf_template = asn1_crmf_template_asn1.c
+gen_files_rfc2459 = asn1_rfc2459_asn1.c
+gen_files_rfc2459_template = asn1_rfc2459_template_asn1.c
+gen_files_rfc4108 = asn1_rfc4108_asn1.c
+gen_files_rfc4108_template = asn1_rfc4108_template_asn1.c
+gen_files_ocsp = asn1_ocsp_asn1.c
+gen_files_ocsp_template = asn1_ocsp_template_asn1.c
+gen_files_pkinit = asn1_pkinit_asn1.c
+gen_files_pkinit_template = asn1_pkinit_template_asn1.c
+gen_files_pkcs10 = asn1_pkcs10_asn1.c
+gen_files_pkcs10_template = asn1_pkcs10_template_asn1.c
+gen_files_pkcs12 = asn1_pkcs12_asn1.c
+gen_files_pkcs12_template = asn1_pkcs12_template_asn1.c
+gen_files_pkcs8 = asn1_pkcs8_asn1.c
+gen_files_pkcs8_template = asn1_pkcs8_template_asn1.c
+gen_files_pkcs9 = asn1_pkcs9_asn1.c
+gen_files_pkcs9_template = asn1_pkcs9_template_asn1.c
+gen_files_test = asn1_test_asn1.c
+gen_files_test_template = asn1_test_template_asn1.c
+gen_files_digest = asn1_digest_asn1.c
+gen_files_digest_template = asn1_digest_template_asn1.c
+gen_files_kx509 = asn1_kx509_asn1.c
+gen_files_kx509_template = asn1_kx509_template_asn1.c
+gen_files_x690sample = asn1_x690sample_asn1.c
+gen_files_x690sample_template = asn1_x690sample_template_asn1.c
 
 oid_resolution.lo: $(BUILT_SOURCES)
 
@@ -100,20 +102,20 @@ check_PROGRAMS = $(TESTS)
 
 asn1_gen_SOURCES = asn1_gen.c
 asn1_print_SOURCES = asn1_print.c
-asn1_print_SOURCES += $(gen_files_x690sample_template:.x=.c)
+asn1_print_SOURCES += $(gen_files_x690sample_template)
 asn1_print_CPPFLAGS = -DASN1_PRINT_SUPPORTED
 check_der_SOURCES = check-der.c check-common.c check-common.h
 
 check_template_SOURCES = check-template.c check-common.c check-common.h
-nodist_check_template_SOURCES = $(gen_files_test_template:.x=.c)
+nodist_check_template_SOURCES = $(gen_files_test_template)
 
 check_gen_template_CPPFLAGS = -DASN1_IOS_SUPPORTED
 dist_check_gen_template_SOURCES = check-gen.c check-common.c check-common.h
-nodist_check_gen_template_SOURCES =    $(gen_files_test_template:.x=.c) \
-                                       $(gen_files_x690sample_template:.x=.c)
+nodist_check_gen_template_SOURCES =    $(gen_files_test_template) \
+                                       $(gen_files_x690sample_template)
 
 dist_check_gen_SOURCES = check-gen.c check-common.c check-common.h
-nodist_check_gen_SOURCES = $(gen_files_test:.x=.c) $(gen_files_x690sample:.x=.c)
+nodist_check_gen_SOURCES = $(gen_files_test) $(gen_files_x690sample)
 
 build_HEADERZ = asn1-template.h
 
@@ -229,37 +231,37 @@ CLEANFILES = \
        $(nodist_check_gen_SOURCES) \
        asn1parse.c asn1parse.h lex.c \
        asn1_err.c asn1_err.h \
-       rfc2459_asn1_files rfc2459_asn1*.h* rfc2459_asn1*.x \
-       rfc2459_template_asn1_files rfc2459_template_asn1*.h* rfc2459_template_asn1*.x \
-       rfc4108_asn1_files rfc4108_asn1*.h* rfc4108_asn1*.x \
-       rfc4108_template_asn1_files rfc4108_template_asn1*.h* rfc4108_template_asn1*.x \
-       cms_asn1_files cms_asn1*.h* cms_asn1*.x \
-       cms_template_asn1_files cms_template_asn1*.h* cms_template_asn1*.x \
-       crmf_asn1_files crmf_asn1*.h* crmf_asn1*.x \
-       crmf_template_asn1_files crmf_template_asn1*.h* crmf_template_asn1*.x \
-       krb5_asn1_files krb5_asn1*.h* krb5_asn1*.x \
-       krb5_template_asn1_files krb5_template_asn1*.h* krb5_template_asn1*.x \
-       ocsp_asn1_files ocsp_asn1*.h* ocsp_asn1*.x \
-       ocsp_template_asn1_files ocsp_template_asn1*.h* ocsp_template_asn1*.x \
-       pkinit_asn1_files pkinit_asn1*.h* pkinit_asn1*.x \
-       pkinit_template_asn1_files pkinit_template_asn1*.h* pkinit_template_asn1*.x \
-       pkcs8_asn1_files pkcs8_asn1*.h* pkcs8_asn1*.x* \
-       pkcs8_template_asn1_files pkcs8_template_asn1*.h* pkcs8_template_asn1*.x* \
-       pkcs9_asn1_files pkcs9_asn1*.h* pkcs9_asn1*.x \
-       pkcs9_template_asn1_files pkcs9_template_asn1*.h* pkcs9_template_asn1*.x \
-       pkcs10_asn1_files pkcs10_asn1*.h* pkcs10_asn1*.x \
-       pkcs10_template_asn1_files pkcs10_template_asn1*.h* pkcs10_template_asn1*.x \
-       pkcs12_asn1_files pkcs12_asn1*.h* pkcs12_asn1*.x \
-       pkcs12_template_asn1_files pkcs12_template_asn1*.h* pkcs12_template_asn1*.x \
-       digest_asn1_files digest_asn1*.h* digest_asn1*.x \
-       digest_template_asn1_files digest_template_asn1*.h* digest_template_asn1*.x \
-       kx509_asn1_files kx509_asn1*.h* kx509_asn1*.x \
-       kx509_template_asn1_files kx509_template_asn1*.h* kx509_template_asn1*.x \
-       x690sample_asn1_files x690sample_asn1*.h* x690sample_asn1*.x \
-       x690sample_template_asn1_files x690sample_template_asn1*.h* x690sample_template_asn1*.x \
-       test_asn1_files test_asn1*.h* test_asn1*.x \
-       test_template_asn1_files test_template_asn1*.h* test_template_asn1*.x \
-       asn1_*.tmp.c asn1_*.x asn1_*.json 
+       rfc2459_asn1_files rfc2459_asn1*.h \
+       rfc2459_template_asn1_files rfc2459_template_asn1*.h \
+       rfc4108_asn1_files rfc4108_asn1*.h \
+       rfc4108_template_asn1_files rfc4108_template_asn1*.h \
+       cms_asn1_files cms_asn1*.h \
+       cms_template_asn1_files cms_template_asn1* \
+       crmf_asn1_files crmf_asn1* \
+       crmf_template_asn1_files crmf_template_asn1* \
+       krb5_asn1_files krb5_asn1* \
+       krb5_template_asn1_files krb5_template_asn1* \
+       ocsp_asn1_files ocsp_asn1* \
+       ocsp_template_asn1_files ocsp_template_asn1* \
+       pkinit_asn1_files pkinit_asn1* \
+       pkinit_template_asn1_files pkinit_template_asn1* \
+       pkcs8_asn1_files pkcs8_asn1* \
+       pkcs8_template_asn1_files pkcs8_template_asn1* \
+       pkcs9_asn1_files pkcs9_asn1* \
+       pkcs9_template_asn1_files pkcs9_template_asn1* \
+       pkcs10_asn1_files pkcs10_asn1* \
+       pkcs10_template_asn1_files pkcs10_template_asn1* \
+       pkcs12_asn1_files pkcs12_asn1* \
+       pkcs12_template_asn1_files pkcs12_template_asn1* \
+       digest_asn1_files digest_asn1* \
+       digest_template_asn1_files digest_template_asn1* \
+       kx509_asn1_files kx509_asn1* \
+       kx509_template_asn1_files kx509_template_asn1* \
+       x690sample_asn1_files x690sample_asn1* \
+       x690sample_template_asn1_files x690sample_template_asn1* \
+       test_asn1_files test_asn1* \
+       test_template_asn1_files test_template_asn1* \
+       asn1_*_asn1.c *_asn1.json *_asn1_syms.c *_asn1_oids.c
 
 dist_include_HEADERS = der.h heim_asn1.h
 dist_include_HEADERS += $(srcdir)/der-protos.h $(srcdir)/der-private.h
@@ -338,36 +340,36 @@ $(asn1_print_OBJECTS): $(nodist_include_HEADERS) $(priv_headers)
 
 asn1parse.h: asn1parse.c
 
-$(gen_files_krb5) krb5_asn1.hx krb5_asn1-priv.hx: krb5_asn1_files
-$(gen_files_krb5_template) krb5_template_asn1.hx krb5_template_asn1-priv.hx: krb5_template_asn1_files
-$(gen_files_ocsp) ocsp_asn1.hx ocsp_asn1-priv.hx: ocsp_asn1_files
-$(gen_files_ocsp_template) ocsp_template_asn1.hx ocsp_template_asn1-priv.hx: ocsp_template_asn1_files
-$(gen_files_pkinit) pkinit_asn1.hx pkinit_asn1-priv.hx: pkinit_asn1_files
-$(gen_files_pkinit_template) pkinit_template_asn1.hx pkinit_template_asn1-priv.hx: pkinit_template_asn1_files
-$(gen_files_pkcs8) pkcs8_asn1.hx pkcs8_asn1-priv.hx: pkcs8_asn1_files
-$(gen_files_pkcs8_template) pkcs8_template_asn1.hx pkcs8_template_asn1-priv.hx: pkcs8_template_asn1_files
-$(gen_files_pkcs9) pkcs9_asn1.hx pkcs9_asn1-priv.hx: pkcs9_asn1_files
-$(gen_files_pkcs9_template) pkcs9_template_asn1.hx pkcs9_template_asn1-priv.hx: pkcs9_template_asn1_files
-$(gen_files_pkcs10) pkcs10_asn1.hx pkcs10_asn1-priv.hx: pkcs10_asn1_files
-$(gen_files_pkcs10_template) pkcs10_template_asn1.hx pkcs10_template_asn1-priv.hx: pkcs10_template_asn1_files
-$(gen_files_pkcs12) pkcs12_asn1.hx pkcs12_asn1-priv.hx: pkcs12_asn1_files
-$(gen_files_pkcs12_template) pkcs12_template_asn1.hx pkcs12_template_asn1-priv.hx: pkcs12_template_asn1_files
-$(gen_files_digest) digest_asn1.hx digest_asn1-priv.hx: digest_asn1_files
-$(gen_files_digest_template) digest_template_asn1.hx digest_template_asn1-priv.hx: digest_template_asn1_files
-$(gen_files_kx509) kx509_asn1.hx kx509_asn1-priv.hx: kx509_asn1_files
-$(gen_files_kx509_template) kx509_template_asn1.hx kx509_template_asn1-priv.hx: kx509_template_asn1_files
-$(gen_files_rfc2459) rfc2459_asn1.hx rfc2459_asn1-priv.hx: rfc2459_asn1_files
-$(gen_files_rfc2459_template) rfc2459_template_asn1.hx rfc2459_template_asn1-priv.hx: rfc2459_template_asn1_files
-$(gen_files_rfc4108) rfc4108_asn1.hx rfc4108_asn1-priv.hx: rfc4108_asn1_files
-$(gen_files_rfc4108_template) rfc4108_template_asn1.hx rfc4108_template_asn1-priv.hx: rfc4108_template_asn1_files
-$(gen_files_cms) cms_asn1.hx cms_asn1-priv.hx: cms_asn1_files
-$(gen_files_cms_template) cms_template_asn1.hx cms_template_asn1-priv.hx: cms_template_asn1_files
-$(gen_files_crmf) crmf_asn1.hx crmf_asn1-priv.hx: crmf_asn1_files
-$(gen_files_crmf_template) crmf_template_asn1.hx crmf_template_asn1-priv.hx: crmf_template_asn1_files
-$(gen_files_x690sample) x690sample_asn1.hx x690sample_asn1-priv.hx: x690sample_asn1_files
-$(gen_files_x690sample_template) x690sample_template_asn1.hx x690sample_template_asn1-priv.hx: x690sample_template_asn1_files
-$(gen_files_test) test_asn1.hx test_asn1-priv.hx: test_asn1_files
-$(gen_files_test_template) test_template_asn1.hx test_template_asn1-priv.hx: test_template_asn1_files
+$(gen_files_krb5) krb5_asn1.h krb5_asn1-priv.h: krb5_asn1_files
+$(gen_files_krb5_template) krb5_template_asn1.h krb5_template_asn1-priv.h: krb5_template_asn1_files
+$(gen_files_ocsp) ocsp_asn1.h ocsp_asn1-priv.h: ocsp_asn1_files
+$(gen_files_ocsp_template) ocsp_template_asn1.h ocsp_template_asn1-priv.h: ocsp_template_asn1_files
+$(gen_files_pkinit) pkinit_asn1.h pkinit_asn1-priv.h: pkinit_asn1_files
+$(gen_files_pkinit_template) pkinit_template_asn1.h pkinit_template_asn1-priv.h: pkinit_template_asn1_files
+$(gen_files_pkcs8) pkcs8_asn1.h pkcs8_asn1-priv.h: pkcs8_asn1_files
+$(gen_files_pkcs8_template) pkcs8_template_asn1.h pkcs8_template_asn1-priv.h: pkcs8_template_asn1_files
+$(gen_files_pkcs9) pkcs9_asn1.h pkcs9_asn1-priv.h: pkcs9_asn1_files
+$(gen_files_pkcs9_template) pkcs9_template_asn1.h pkcs9_template_asn1-priv.h: pkcs9_template_asn1_files
+$(gen_files_pkcs10) pkcs10_asn1.h pkcs10_asn1-priv.h: pkcs10_asn1_files
+$(gen_files_pkcs10_template) pkcs10_template_asn1.h pkcs10_template_asn1-priv.h: pkcs10_template_asn1_files
+$(gen_files_pkcs12) pkcs12_asn1.h pkcs12_asn1-priv.h: pkcs12_asn1_files
+$(gen_files_pkcs12_template) pkcs12_template_asn1.h pkcs12_template_asn1-priv.h: pkcs12_template_asn1_files
+$(gen_files_digest) digest_asn1.h digest_asn1-priv.h: digest_asn1_files
+$(gen_files_digest_template) digest_template_asn1.h digest_template_asn1-priv.h: digest_template_asn1_files
+$(gen_files_kx509) kx509_asn1.h kx509_asn1-priv.h: kx509_asn1_files
+$(gen_files_kx509_template) kx509_template_asn1.h kx509_template_asn1-priv.h: kx509_template_asn1_files
+$(gen_files_rfc2459) rfc2459_asn1.h rfc2459_asn1-priv.h: rfc2459_asn1_files
+$(gen_files_rfc2459_template) rfc2459_template_asn1.h rfc2459_template_asn1-priv.h: rfc2459_template_asn1_files
+$(gen_files_rfc4108) rfc4108_asn1.h rfc4108_asn1-priv.h: rfc4108_asn1_files
+$(gen_files_rfc4108_template) rfc4108_template_asn1.h rfc4108_template_asn1-priv.h: rfc4108_template_asn1_files
+$(gen_files_cms) cms_asn1.h cms_asn1-priv.h: cms_asn1_files
+$(gen_files_cms_template) cms_template_asn1.h cms_template_asn1-priv.h: cms_template_asn1_files
+$(gen_files_crmf) crmf_asn1.h crmf_asn1-priv.h: crmf_asn1_files
+$(gen_files_crmf_template) crmf_template_asn1.h crmf_template_asn1-priv.h: crmf_template_asn1_files
+$(gen_files_x690sample) x690sample_asn1.h x690sample_asn1-priv.h: x690sample_asn1_files
+$(gen_files_x690sample_template) x690sample_template_asn1.h x690sample_template_asn1-priv.h: x690sample_template_asn1_files
+$(gen_files_test) test_asn1.h test_asn1-priv.h: test_asn1_files
+$(gen_files_test_template) test_template_asn1.h test_template_asn1-priv.h: test_template_asn1_files
 
 if ASN1_TEMPLATING
 TEMPLATE_OPTION=--template
@@ -379,136 +381,171 @@ endif
 # templated anyways.
 rfc2459_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/rfc2459.asn1
        $(ASN1_COMPILE) --one-code-file --template --option-file=$(srcdir)/rfc2459.opt $(srcdir)/rfc2459.asn1 rfc2459_template_asn1 || (rm -f rfc2459_template_asn1_files ; exit 1)
+       @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_rfc2459_template_asn1.c
 
 rfc4108_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/rfc4108.asn1
        $(ASN1_COMPILE) --one-code-file --template $(srcdir)/rfc4108.asn1 rfc4108_template_asn1 || (rm -f rfc4108_template_asn1_files ; exit 1)
+       @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_rfc4108_template_asn1.c
 
 cms_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/cms.asn1 $(srcdir)/cms.opt
        $(ASN1_COMPILE) --one-code-file --template --option-file=$(srcdir)/cms.opt $(srcdir)/cms.asn1 cms_template_asn1 || (rm -f cms_template_asn1_files ; exit 1)
+       @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_cms_template_asn1.c
 
 crmf_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/crmf.asn1 $(srcdir)/crmf.opt
        $(ASN1_COMPILE) --one-code-file --template --option-file=$(srcdir)/crmf.opt $(srcdir)/crmf.asn1 crmf_template_asn1 || (rm -f crmf_template_asn1_files ; exit 1)
+       @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_crmf_template_asn1.c
 
 krb5_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/krb5.asn1 $(srcdir)/krb5.opt
        $(ASN1_COMPILE) --one-code-file --template                      \
                        --option-file=$(srcdir)/krb5.opt                \
-                       --decorate='Principal:PrincipalNameAttrs:nameattrs?'    \
                        $(srcdir)/krb5.asn1 krb5_template_asn1 || (rm -f krb5_template_asn1_files ; exit 1)
+       @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_krb5_template_asn1.c
 
 ocsp_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/ocsp.asn1
        $(ASN1_COMPILE) --one-code-file --template --option-file=$(srcdir)/ocsp.opt $(srcdir)/ocsp.asn1 ocsp_template_asn1 || (rm -f ocsp_template_asn1_files ; exit 1)
+       @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_ocsp_template_asn1.c
 
 pkinit_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkinit.asn1
        $(ASN1_COMPILE) --one-code-file --template $(srcdir)/pkinit.asn1 pkinit_template_asn1 || (rm -f pkinit_template_asn1_files ; exit 1)
+       @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_pkinit_template_asn1.c
 
 pkcs8_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkcs8.asn1
        $(ASN1_COMPILE) --one-code-file --template $(srcdir)/pkcs8.asn1 pkcs8_template_asn1 || (rm -f pkcs8_template_asn1_files ; exit 1)
+       @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_pkcs8_template_asn1.c
 
 pkcs9_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkcs9.asn1
        $(ASN1_COMPILE) --one-code-file --template $(srcdir)/pkcs9.asn1 pkcs9_template_asn1 || (rm -f pkcs9_template_asn1_files ; exit 1)
+       @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_pkcs9_template_asn1.c
 
 pkcs10_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkcs10.asn1
        $(ASN1_COMPILE) --one-code-file --template --option-file=$(srcdir)/pkcs10.opt $(srcdir)/pkcs10.asn1 pkcs10_template_asn1 || (rm -f pkcs10_template_asn1_files ; exit 1)
+       @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_pkcs10_template_asn1.c
 
 pkcs12_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkcs12.asn1
        $(ASN1_COMPILE) --one-code-file --template $(srcdir)/pkcs12.asn1 pkcs12_template_asn1 || (rm -f pkcs12_template_asn1_files ; exit 1)
+       @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_pkcs12_template_asn1.c
 
 digest_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/digest.asn1
        $(ASN1_COMPILE) --one-code-file --template $(srcdir)/digest.asn1 digest_template_asn1 || (rm -f digest_template_asn1_files ; exit 1)
+       @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_digest_template_asn1.c
 
 kx509_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/kx509.asn1
        $(ASN1_COMPILE) --one-code-file --template $(srcdir)/kx509.asn1 kx509_template_asn1 || (rm -f kx509_template_asn1_files ; exit 1)
+       @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_kx509_template_asn1.c
 
 rfc2459_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/rfc2459.asn1
        $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) --option-file=$(srcdir)/rfc2459.opt $(srcdir)/rfc2459.asn1 rfc2459_asn1 || (rm -f rfc2459_asn1_files ; exit 1)
+       @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_rfc2459_asn1.c
 
 rfc4108_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/rfc4108.asn1
        $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) $(srcdir)/rfc4108.asn1 rfc4108_asn1 || (rm -f rfc4108_asn1_files ; exit 1)
+       @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_rfc4108_asn1.c
 
 cms_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/cms.asn1 $(srcdir)/cms.opt
        $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) --option-file=$(srcdir)/cms.opt $(srcdir)/cms.asn1 cms_asn1 || (rm -f cms_asn1_files ; exit 1)
+       @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_cms_asn1.c
 
 crmf_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/crmf.asn1 $(srcdir)/crmf.opt
        $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) --option-file=$(srcdir)/crmf.opt $(srcdir)/crmf.asn1 crmf_asn1 || (rm -f crmf_asn1_files ; exit 1)
+       @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_crmf_asn1.c
 
 krb5_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/krb5.asn1 $(srcdir)/krb5.opt
        $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION)              \
                        --option-file=$(srcdir)/krb5.opt                \
-                       --decorate='Principal:PrincipalNameAttrs:nameattrs?'    \
                        $(srcdir)/krb5.asn1 krb5_asn1 || (rm -f krb5_asn1_files ; exit 1)
+       @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_krb5_asn1.c
 
 ocsp_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/ocsp.asn1
        $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) --option-file=$(srcdir)/ocsp.opt $(srcdir)/ocsp.asn1 ocsp_asn1 || (rm -f ocsp_asn1_files ; exit 1)
+       @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_ocsp_asn1.c
 
 pkinit_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkinit.asn1
        $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) $(srcdir)/pkinit.asn1 pkinit_asn1 || (rm -f pkinit_asn1_files ; exit 1)
+       @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_pkinit_asn1.c
 
 pkcs8_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkcs8.asn1
        $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) $(srcdir)/pkcs8.asn1 pkcs8_asn1 || (rm -f pkcs8_asn1_files ; exit 1)
+       @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_pkcs8_asn1.c
 
 pkcs9_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkcs9.asn1
        $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) $(srcdir)/pkcs9.asn1 pkcs9_asn1 || (rm -f pkcs9_asn1_files ; exit 1)
+       @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_pkcs9_asn1.c
 
 pkcs10_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkcs10.asn1
        $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) --option-file=$(srcdir)/pkcs10.opt $(srcdir)/pkcs10.asn1 pkcs10_asn1 || (rm -f pkcs10_asn1_files ; exit 1)
+       @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_pkcs10_asn1.c
 
 pkcs12_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkcs12.asn1
        $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) $(srcdir)/pkcs12.asn1 pkcs12_asn1 || (rm -f pkcs12_asn1_files ; exit 1)
+       @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_pkcs12_asn1.c
 
 digest_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/digest.asn1
        $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) $(srcdir)/digest.asn1 digest_asn1 || (rm -f digest_asn1_files ; exit 1)
+       @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_digest_asn1.c
 
 kx509_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/kx509.asn1
        $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) $(srcdir)/kx509.asn1 kx509_asn1 || (rm -f kx509_asn1_files ; exit 1)
+       @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_kx509_asn1.c
 
 x690sample_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/x690sample.asn1
        $(ASN1_COMPILE) --one-code-file --template $(srcdir)/x690sample.asn1 x690sample_template_asn1 || (rm -f x690sample_template_asn1_files ; exit 1)
+       @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_x690sample_template_asn1.c
 
 x690sample_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/x690sample.asn1
        $(ASN1_COMPILE) --one-code-file $(srcdir)/x690sample.asn1 x690sample_asn1 || (rm -f x690sample_asn1_files ; exit 1)
+       @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_x690sample_asn1.c
 
 test_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/test.asn1
        $(ASN1_COMPILE) --one-code-file                                 \
                        --template                                      \
-                       --sequence=TESTSeqOf                            \
-                       --decorate='TESTDecorated:TESTuint32:version2?' \
+                       --option-file=$(srcdir)/test.opt                \
                        $(srcdir)/test.asn1 test_template_asn1 || (rm -f test_template_asn1_files ; exit 1)
+       @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_test_template_asn1.c
 
 test_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/test.asn1
        $(ASN1_COMPILE) --one-code-file                                 \
-                       --decorate='TESTDecorated:TESTuint32:version2?' \
-                       --sequence=TESTSeqOf                            \
+                       --option-file=$(srcdir)/test.opt                \
                        $(srcdir)/test.asn1 test_asn1 || (rm -f test_asn1_files ; exit 1)
-
-
-EXTRA_DIST =           \
-       NTMakefile      \
-       README.template \
-       asn1_compile-version.rc \
-       libasn1-exports.def \
-       cms.asn1        \
-       cms.opt         \
-       crmf.asn1       \
-       crmf.opt        \
-       asn1_err.et     \
-       canthandle.asn1 \
-       digest.asn1     \
-       krb5.asn1       \
-       krb5.opt        \
-       kx509.asn1      \
-       ocsp.asn1       \
-       pkcs12.asn1     \
-       pkcs8.asn1      \
-       pkcs9.asn1      \
-       pkcs10.asn1     \
-       pkinit.asn1     \
-       rfc2459.asn1    \
-       rfc4108.asn1    \
-       tcg.asn1        \
-       setchgpw2.asn1  \
-       x690sample.asn1 \
-       test.asn1       \
-       test.gen        \
+       @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_test_asn1.c
+
+
+EXTRA_DIST =                   \
+       NTMakefile              \
+       README-template.md      \
+       asn1_compile-version.rc \
+       libasn1-exports.def     \
+       canthandle.asn1         \
+       cms.asn1                \
+       cms.opt                 \
+       crmf.asn1               \
+       crmf.opt                \
+       digest.asn1             \
+       krb5.asn1               \
+       krb5.opt                \
+       kx509.asn1              \
+       ocsp.asn1               \
+       ocsp.opt                \
+       pkcs10.asn1             \
+       pkcs10.opt              \
+       pkcs12.asn1             \
+       pkcs8.asn1              \
+       pkcs9.asn1              \
+       pkinit.asn1             \
+       pku2u.asn1              \
+       rfc2459.asn1            \
+       rfc2459.opt             \
+       rfc4108.asn1            \
+       setchgpw2.asn1          \
+       tcg.asn1                \
+       test.asn1               \
+       test.opt                \
+       x690sample.asn1         \
+       test.gen                \
+       asn1_err.et             \
+       asn1_err.c              \
+       asn1_err.h              \
+       asn1_print.1            \
+       asn1_compile.1          \
        version-script.map
 
 DER_PROTOS = $(srcdir)/der-protos.h $(srcdir)/der-private.h
index eca92bd3853c5408133337be8dcb90273c3a0ab9..19255c6cf710f67c4307eba7223c486cd437971a 100644 (file)
@@ -1,6 +1,6 @@
 ########################################################################
 #
-# Copyright (c) 2009, Secure Endpoints Inc.
+# Copyright (c) 2009-2022, Secure Endpoints Inc.
 # All rights reserved.
 # 
 # Redistribution and use in source and binary forms, with or without
 
 RELDIR=lib\asn1
 
-intcflags=-I$(SRCDIR) -I$(OBJ) -DROKEN_RENAME -DASN1_IOS_SUPPORTED
+intcflags=-I$(SRCDIR) -I$(OBJ) -DROKEN_RENAME -DASN1_IOS_SUPPORTED -DASN1_LIB
 
 !include ../../windows/NTMakefile.w32
 
-gen_files_krb5         = $(OBJ)\asn1_krb5_asn1.x
-
-gen_files_cms          = $(OBJ)\asn1_cms_asn1.x
-
-gen_files_crmf         = $(OBJ)\asn1_crmf_asn1.x
-
-gen_files_rfc2459      = $(OBJ)\asn1_rfc2459_asn1.x
-
-gen_files_rfc4108      = $(OBJ)\asn1_rfc4108_asn1.x
-
-gen_files_ocsp         = $(OBJ)\asn1_ocsp_asn1.x
-
-gen_files_pkinit       = $(OBJ)\asn1_pkinit_asn1.x
-
-gen_files_pkcs12       = $(OBJ)\asn1_pkcs12_asn1.x
-
-gen_files_pkcs8                = $(OBJ)\asn1_pkcs8_asn1.x
-
-gen_files_pkcs9                = $(OBJ)\asn1_pkcs9_asn1.x
-
-gen_files_pkcs10       = $(OBJ)\asn1_pkcs10_asn1.x
-
-gen_files_test         = $(OBJ)\asn1_test_asn1.x
-
-gen_files_test_template        = $(OBJ)\asn1_test_template_asn1.x
-
-gen_files_digest       = $(OBJ)\asn1_digest_asn1.x
-
-gen_files_kx509                = $(OBJ)\asn1_kx509_asn1.x
-
-gen_files_x690sample   = $(OBJ)\asn1_x690sample_asn1.x
-
 ASN1_BINARIES =                                                    \
        $(LIBEXECDIR)\asn1_compile.exe
 
@@ -112,6 +80,21 @@ $(BINDIR)\asn1_gen.exe: $(OBJ)\asn1_gen.obj $(LIBHEIMDAL)
        $(EXECONLINK) $(LIBVERS) $(LIBROKEN)
        $(EXEPREP)
 
+LIBASN1_X= \
+       $(OBJ)\asn1_rfc2459_asn1.c              \
+       $(OBJ)\asn1_rfc4108_asn1.c              \
+       $(OBJ)\asn1_cms_asn1.c                  \
+       $(OBJ)\asn1_krb5_asn1.c                 \
+       $(OBJ)\asn1_ocsp_asn1.c                 \
+       $(OBJ)\asn1_pkinit_asn1.c               \
+       $(OBJ)\asn1_pkcs8_asn1.c                \
+       $(OBJ)\asn1_pkcs9_asn1.c                \
+       $(OBJ)\asn1_pkcs10_asn1.c               \
+       $(OBJ)\asn1_pkcs12_asn1.c               \
+       $(OBJ)\asn1_digest_asn1.c               \
+       $(OBJ)\asn1_kx509_asn1.c                \
+       $(OBJ)\asn1_x690sample_asn1.c
+
 LIBASN1_OBJS=  \
        $(OBJ)\der.obj                          \
        $(OBJ)\der_get.obj                      \
@@ -124,27 +107,26 @@ LIBASN1_OBJS=     \
        $(OBJ)\der_format.obj                   \
        $(OBJ)\template.obj                     \
        $(OBJ)\extra.obj                        \
+       $(OBJ)\oid_resolution.obj               \
        $(OBJ)\timegm.obj                       \
-       $(gen_files_rfc2459:.x=.obj)            \
-       $(gen_files_rfc4108:.x=.obj)            \
-       $(gen_files_cms:.x=.obj)                \
-       $(gen_files_krb5:.x=.obj)               \
-       $(gen_files_ocsp:.x=.obj)               \
-       $(gen_files_pkinit:.x=.obj)             \
-       $(gen_files_pkcs8:.x=.obj)              \
-       $(gen_files_pkcs9:.x=.obj)              \
-       $(gen_files_pkcs10:.x=.obj)             \
-       $(gen_files_pkcs12:.x=.obj)             \
-       $(gen_files_digest:.x=.obj)             \
-       $(gen_files_kx509:.x=.obj)              \
-       $(gen_files_x690sample:.x=.obj)         \
+       $(OBJ)\asn1_rfc2459_asn1.obj            \
+       $(OBJ)\asn1_rfc4108_asn1.obj            \
+       $(OBJ)\asn1_cms_asn1.obj                \
+       $(OBJ)\asn1_krb5_asn1.obj               \
+       $(OBJ)\asn1_ocsp_asn1.obj               \
+       $(OBJ)\asn1_pkinit_asn1.obj             \
+       $(OBJ)\asn1_pkcs8_asn1.obj              \
+       $(OBJ)\asn1_pkcs9_asn1.obj              \
+       $(OBJ)\asn1_pkcs10_asn1.obj             \
+       $(OBJ)\asn1_pkcs12_asn1.obj             \
+       $(OBJ)\asn1_digest_asn1.obj             \
+       $(OBJ)\asn1_kx509_asn1.obj              \
+       $(OBJ)\asn1_x690sample_asn1.obj         \
        $(OBJ)\asn1_err.obj
 
-$(OBJ)\oid_resolution.obj: $(LIBASN1_OBJS)
-
-LIBASN1_OBJS2= $(LIBASN1_OBJS) $(OBJ)\oid_resolution.obj
+$(OBJ)\oid_resolution.obj: $(LIBASN1_X)
 
-$(LIBASN1): $(LIBASN1_OBJS2)
+$(LIBASN1): $(LIBASN1_OBJS)
        $(LIBCON_C) -out:$@ @<<
 $(**: =
 )
@@ -154,61 +136,159 @@ clean::
        -$(RM) $(LIBASN1)
 
 #
-# Generate list of exports
-#
-# This target is only used during development to generate a list of
-# symbols that are exported from all the object files in LIBASN1_OBJS.
-#
-exports-list.txt: $(LIBASN1_OBJS)
-       $(PERL) ..\..\cf\w32-list-externs-from-objs.pl -q -u @<< > $@
-$(**: =
-)
-<<
+# The static runtime version LIBASN1_S is for use by thirdparty
+# components.  It is not used in the construction of the Heimdal
+# DLLs.
+
+LIBASN1_S_OBJS=        \
+       $(OBJ)\der.s.obj                        \
+       $(OBJ)\der_get.s.obj                    \
+       $(OBJ)\der_put.s.obj                    \
+       $(OBJ)\der_free.s.obj                   \
+       $(OBJ)\der_print.s.obj                  \
+       $(OBJ)\der_length.s.obj                 \
+       $(OBJ)\der_copy.s.obj                   \
+       $(OBJ)\der_cmp.s.obj                    \
+       $(OBJ)\der_format.s.obj                 \
+       $(OBJ)\template.s.obj                   \
+       $(OBJ)\extra.s.obj                      \
+       $(OBJ)\oid_resolution.s.obj             \
+       $(OBJ)\timegm.s.obj                     \
+       $(OBJ)\asn1_rfc2459_asn1.s.obj          \
+       $(OBJ)\asn1_rfc4108_asn1.s.obj          \
+       $(OBJ)\asn1_cms_asn1.s.obj              \
+       $(OBJ)\asn1_krb5_asn1.s.obj             \
+       $(OBJ)\asn1_ocsp_asn1.s.obj             \
+       $(OBJ)\asn1_pkinit_asn1.s.obj           \
+       $(OBJ)\asn1_pkcs8_asn1.s.obj            \
+       $(OBJ)\asn1_pkcs9_asn1.s.obj            \
+       $(OBJ)\asn1_pkcs10_asn1.s.obj           \
+       $(OBJ)\asn1_pkcs12_asn1.s.obj           \
+       $(OBJ)\asn1_digest_asn1.s.obj           \
+       $(OBJ)\asn1_kx509_asn1.s.obj            \
+       $(OBJ)\asn1_x690sample_asn1.s.obj       \
+       $(OBJ)\asn1_err.s.obj
+
+$(OBJ)\oid_resolution.s.obj: oid_resolution.c $(LIBASN1_X)
+       $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ oid_resolution.c
+
+$(OBJ)\der.s.obj: der.c
+       $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
+
+$(OBJ)\der_get.s.obj: der_get.c
+       $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
 
-$(gen_files_krb5:.x=.c)            : $$(@R).x
+$(OBJ)\der_put.s.obj: der_put.c
+       $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
 
-$(gen_files_ocsp:.x=.c)   : $$(@R).x
+$(OBJ)\der_free.s.obj: der_free.c
+       $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
 
-$(gen_files_pkinit:.x=.c)   : $$(@R).x
+$(OBJ)\der_print.s.obj: der_print.c
+       $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
 
-$(gen_files_pkcs8:.x=.c)    : $$(@R).x
+$(OBJ)\der_length.s.obj: der_length.c
+       $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
 
-$(gen_files_pkcs9:.x=.c)    : $$(@R).x
+$(OBJ)\der_copy.s.obj: der_copy.c
+       $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
 
-$(gen_files_pkcs10:.x=.c)   : $$(@R).x
+$(OBJ)\der_cmp.s.obj: der_cmp.c
+       $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
 
-$(gen_files_pkcs12:.x=.c)   : $$(@R).x
+$(OBJ)\der_format.s.obj: der_format.c
+       $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
 
-$(gen_files_digest:.x=.c)   : $$(@R).x
+$(OBJ)\template.s.obj: template.c
+       $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
 
-$(gen_files_kx509:.x=.c)    : $$(@R).x
+$(OBJ)\extra.s.obj: extra.c
+       $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
 
-$(gen_files_rfc2459:.x=.c)  : $$(@R).x
+$(OBJ)\timegm.s.obj: timegm.c
+       $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
 
-$(gen_files_rfc4108:.x=.c)  : $$(@R).x
+$(OBJ)\asn1_rfc2459_asn1.s.obj: $(OBJ)\asn1_rfc2459_asn1.c
+       $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
 
-$(gen_files_cms:.x=.c)     : $$(@R).x
+$(OBJ)\asn1_rfc4108_asn1.s.obj: $(OBJ)\asn1_rfc4108_asn1.c
+       $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
 
-$(gen_files_crmf:.x=.c)            : $$(@R).x
+$(OBJ)\asn1_cms_asn1.s.obj: $(OBJ)\asn1_cms_asn1.c
+       $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
 
-$(gen_files_x690sample:.x=.c)      : $$(@R).x
+$(OBJ)\asn1_krb5_asn1.s.obj: $(OBJ)\asn1_krb5_asn1.c
+       $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
 
-$(gen_files_test:.x=.c)            : $$(@R).x
+$(OBJ)\asn1_ocsp_asn1.s.obj: $(OBJ)\asn1_ocsp_asn1.c
+       $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
 
-$(gen_files_test_template:.x=.c)           : $$(@R).x
+$(OBJ)\asn1_pkinit_asn1.s.obj: $(OBJ)\asn1_pkinit_asn1.c
+       $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
 
-$(gen_files_krb5) $(OBJ)\krb5_asn1.hx: $(BINDIR)\asn1_compile.exe krb5.asn1 krb5.opt
+$(OBJ)\asn1_pkcs8_asn1.s.obj: $(OBJ)\asn1_pkcs8_asn1.c
+       $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
+
+$(OBJ)\asn1_pkcs9_asn1.s.obj: $(OBJ)\asn1_pkcs9_asn1.c
+       $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
+
+$(OBJ)\asn1_pkcs10_asn1.s.obj: $(OBJ)\asn1_pkcs10_asn1.c
+       $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
+
+$(OBJ)\asn1_pkcs12_asn1.s.obj: $(OBJ)\asn1_pkcs12_asn1.c
+       $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
+
+$(OBJ)\asn1_digest_asn1.s.obj: $(OBJ)\asn1_digest_asn1.c
+       $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
+
+$(OBJ)\asn1_kx509_asn1.s.obj: $(OBJ)\asn1_kx509_asn1.c
+       $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
+
+$(OBJ)\asn1_x690sample_asn1.s.obj: $(OBJ)\asn1_x690sample_asn1.c
+       $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
+
+$(OBJ)\asn1_test_asn1.s.obj: $(OBJ)\asn1_test_asn1.c
+       $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
+
+$(OBJ)\asn1_test_template_asn1.s.obj: $(OBJ)\asn1_test_template_asn1.c
+       $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
+
+$(OBJ)\asn1_err.s.obj: $(OBJ)\asn1_err.c
+       $(C2OBJ_C_MT) -Fo$@ -Fd$(@D)\ $**
+
+$(LIBASN1_S): $(LIBASN1_S_OBJS)
+       $(LIBCON_C) -out:$@ @<<
+$(**: =
+)
+<<
+
+clean::
+       -$(RM) $(LIBASN1_S)
+
+
+#
+# Generate list of exports
+#
+# This target is only used during development to generate a list of
+# symbols that are exported from all the object files in LIBASN1_OBJS.
+#
+exports-list.txt: $(LIBASN1_OBJS)
+       $(PERL) ..\..\cf\w32-list-externs-from-objs.pl -q -u @<< > $@
+$(**: =
+)
+<<
+
+$(OBJ)\asn1_krb5_asn1.c $(OBJ)\krb5_asn1.h: $(BINDIR)\asn1_compile.exe krb5.asn1 krb5.opt
        cd $(OBJ)
        $(BINDIR)\asn1_compile.exe \
                --template      \
                --one-code-file \
-               --decorate="Principal:PrincipalNameAttrs:nameattrs?" \
                --option-file=$(SRCDIR)\krb5.opt \
                $(SRCDIR)\krb5.asn1 krb5_asn1 \
        || ($(RM) $(OBJ)\krb5_asn1.h ; exit /b 1)
        cd $(SRCDIR)
 
-$(gen_files_ocsp) $(OBJ)\ocsp_asn1.hx: $(BINDIR)\asn1_compile.exe ocsp.asn1
+$(OBJ)\asn1_ocsp_asn1.c $(OBJ)\ocsp_asn1.h: $(BINDIR)\asn1_compile.exe ocsp.asn1
        cd $(OBJ)
        $(BINDIR)\asn1_compile.exe \
                --template      \
@@ -219,25 +299,25 @@ $(gen_files_ocsp) $(OBJ)\ocsp_asn1.hx: $(BINDIR)\asn1_compile.exe ocsp.asn1
        || ($(RM) $(OBJ)\ocsp_asn1.h ; exit /b 1)
        cd $(SRCDIR)
 
-$(gen_files_pkinit) $(OBJ)\pkinit_asn1.hx: $(BINDIR)\asn1_compile.exe pkinit.asn1
+$(OBJ)\asn1_pkinit_asn1.c $(OBJ)\pkinit_asn1.h: $(BINDIR)\asn1_compile.exe pkinit.asn1
        cd $(OBJ)
        $(BINDIR)\asn1_compile.exe --template --one-code-file $(SRCDIR)\pkinit.asn1 pkinit_asn1 \
        || ($(RM) $(OBJ)\pkinit_asn1.h ; exit /b 1)
        cd $(SRCDIR)
 
-$(gen_files_pkcs8) $(OBJ)\pkcs8_asn1.hx: $(BINDIR)\asn1_compile.exe pkcs8.asn1
+$(OBJ)\asn1_pkcs8_asn1.c $(OBJ)\pkcs8_asn1.h: $(BINDIR)\asn1_compile.exe pkcs8.asn1
        cd $(OBJ)
        $(BINDIR)\asn1_compile.exe --template --one-code-file $(SRCDIR)\pkcs8.asn1 pkcs8_asn1 \
        || ($(RM) $(OBJ)\pkcs8_asn1.h ; exit /b 1)
        cd $(SRCDIR)
 
-$(gen_files_pkcs9) $(OBJ)\pkcs9_asn1.hx: $(BINDIR)\asn1_compile.exe pkcs9.asn1
+$(OBJ)\asn1_pkcs9_asn1.c $(OBJ)\pkcs9_asn1.h: $(BINDIR)\asn1_compile.exe pkcs9.asn1
        cd $(OBJ)
        $(BINDIR)\asn1_compile.exe --template --one-code-file $(SRCDIR)\pkcs9.asn1 pkcs9_asn1 \
        || ($(RM) $(OBJ)\pkcs9_asn1.h ; exit /b 1)
        cd $(SRCDIR)
 
-$(gen_files_pkcs10) $(OBJ)\pkcs10_asn1.hx: $(BINDIR)\asn1_compile.exe pkcs10.asn1
+$(OBJ)\asn1_pkcs10_asn1.c $(OBJ)\pkcs10_asn1.h: $(BINDIR)\asn1_compile.exe pkcs10.asn1
        cd $(OBJ)
        $(BINDIR)\asn1_compile.exe \
                --template      \
@@ -248,25 +328,25 @@ $(gen_files_pkcs10) $(OBJ)\pkcs10_asn1.hx: $(BINDIR)\asn1_compile.exe pkcs10.asn
        || ($(RM) $(OBJ)\pkcs10_asn1.h ; exit /b 1)
        cd $(SRCDIR)
 
-$(gen_files_pkcs12) $(OBJ)\pkcs12_asn1.hx: $(BINDIR)\asn1_compile.exe pkcs12.asn1
+$(OBJ)\asn1_pkcs12_asn1.c $(OBJ)\pkcs12_asn1.h: $(BINDIR)\asn1_compile.exe pkcs12.asn1
        cd $(OBJ)
        $(BINDIR)\asn1_compile.exe --template --one-code-file $(SRCDIR)\pkcs12.asn1 pkcs12_asn1 \
        || ($(RM) $(OBJ)\pkcs12_asn1.h ; exit /b 1)
        cd $(SRCDIR)
 
-$(gen_files_digest) $(OBJ)\digest_asn1.hx: $(BINDIR)\asn1_compile.exe digest.asn1
+$(OBJ)\asn1_digest_asn1.c $(OBJ)\digest_asn1.h: $(BINDIR)\asn1_compile.exe digest.asn1
        cd $(OBJ)
        $(BINDIR)\asn1_compile.exe --template --one-code-file $(SRCDIR)\digest.asn1 digest_asn1 \
        || ($(RM) $(OBJ)\digest_asn1.h ; exit /b 1)
        cd $(SRCDIR)
 
-$(gen_files_kx509) $(OBJ)\kx509_asn1.hx: $(BINDIR)\asn1_compile.exe kx509.asn1
+$(OBJ)\asn1_kx509_asn1.c $(OBJ)\kx509_asn1.h: $(BINDIR)\asn1_compile.exe kx509.asn1
        cd $(OBJ)
        $(BINDIR)\asn1_compile.exe --template --one-code-file $(SRCDIR)\kx509.asn1 kx509_asn1 \
        || ($(RM) $(OBJ)\kx509_asn1.h ; exit /b 1)
        cd $(SRCDIR)
 
-$(gen_files_rfc2459) $(OBJ)\rfc2459_asn1.hx: $(BINDIR)\asn1_compile.exe rfc2459.asn1
+$(OBJ)\asn1_rfc2459_asn1.c $(OBJ)\rfc2459_asn1.h: $(BINDIR)\asn1_compile.exe rfc2459.asn1
        cd $(OBJ)
        $(BINDIR)\asn1_compile.exe \
                --template      \
@@ -276,7 +356,7 @@ $(gen_files_rfc2459) $(OBJ)\rfc2459_asn1.hx: $(BINDIR)\asn1_compile.exe rfc2459.
        || ($(RM) $(OBJ)\rfc2459_asn1.h ; exit /b 1)
        cd $(SRCDIR)
 
-$(gen_files_rfc4108) $(OBJ)\rfc4108_asn1.hx: $(BINDIR)\asn1_compile.exe rfc4108.asn1
+$(OBJ)\asn1_rfc4108_asn1.c $(OBJ)\rfc4108_asn1.h: $(BINDIR)\asn1_compile.exe rfc4108.asn1
        cd $(OBJ)
        $(BINDIR)\asn1_compile.exe \
                --template      \
@@ -285,7 +365,7 @@ $(gen_files_rfc4108) $(OBJ)\rfc4108_asn1.hx: $(BINDIR)\asn1_compile.exe rfc4108.
        || ($(RM) $(OBJ)\rfc4108_asn1.h ; exit /b 1)
        cd $(SRCDIR)
 
-$(gen_files_cms) $(OBJ)\cms_asn1.hx: $(BINDIR)\asn1_compile.exe cms.asn1 cms.opt
+$(OBJ)\asn1_cms_asn1.c $(OBJ)\cms_asn1.h: $(BINDIR)\asn1_compile.exe cms.asn1 cms.opt
        cd $(OBJ)
        $(BINDIR)\asn1_compile.exe \
                --template      \
@@ -294,7 +374,7 @@ $(gen_files_cms) $(OBJ)\cms_asn1.hx: $(BINDIR)\asn1_compile.exe cms.asn1 cms.opt
        || ($(RM) $(OBJ)\cms_asn1.h ; exit /b 1)
        cd $(SRCDIR)
 
-$(gen_files_crmf) $(OBJ)\crmf_asn1.hx: $(BINDIR)\asn1_compile.exe crmf.asn1 crmf.opt
+$(gen_files_crmf) $(OBJ)\crmf_asn1.h: $(BINDIR)\asn1_compile.exe crmf.asn1 crmf.opt
        cd $(OBJ)
        $(BINDIR)\asn1_compile.exe \
                --template      \
@@ -303,7 +383,7 @@ $(gen_files_crmf) $(OBJ)\crmf_asn1.hx: $(BINDIR)\asn1_compile.exe crmf.asn1 crmf
        || ($(RM) $(OBJ)\crmf_asn1.h ; exit /b 1)
        cd $(SRCDIR)
 
-$(gen_files_x690sample) $(OBJ)\x690sample_asn1.hx: $(BINDIR)\asn1_compile.exe x690sample.asn1
+$(OBJ)\asn1_x690sample_asn1.c $(OBJ)\x690sample_asn1.h: $(BINDIR)\asn1_compile.exe x690sample.asn1
        cd $(OBJ)
        $(BINDIR)\asn1_compile.exe \
                --template      \
@@ -312,23 +392,22 @@ $(gen_files_x690sample) $(OBJ)\x690sample_asn1.hx: $(BINDIR)\asn1_compile.exe x6
        || ($(RM) $(OBJ)\x690sample_asn1.h ; exit /b 1)
        cd $(SRCDIR)
 
-$(gen_files_test) $(OBJ)\test_asn1.hx: $(BINDIR)\asn1_compile.exe test.asn1
+$(OBJ)\asn1_test_asn1.c $(OBJ)\test_asn1.h: $(BINDIR)\asn1_compile.exe test.asn1
        cd $(OBJ)
        $(BINDIR)\asn1_compile.exe \
                --template      \
-               --decorate="TESTDecorated:TESTuint32:version2?" \
-               --one-code-file --sequence=TESTSeqOf \
+               --option-file=$(SRCDIR)/test.opt                \
+               --one-code-file \
                $(SRCDIR)\test.asn1 test_asn1 \
        || ($(RM) $(OBJ)\test_asn1.h ; exit /b 1)
        cd $(SRCDIR)
 
-$(gen_files_test_template) $(OBJ)\test_template_asn1.hx: $(BINDIR)\asn1_compile.exe test.asn1
+$(OBJ)\asn1_test_template_asn1.c $(OBJ)\test_template_asn1.h: $(BINDIR)\asn1_compile.exe test.asn1
        cd $(OBJ)
        $(BINDIR)\asn1_compile.exe \
                --template      \
-               --decorate="TESTDecorated:TESTuint32:version2?" \
+               --option-file=$(SRCDIR)/test.opt                \
                --one-code-file \
-               --sequence=TESTSeqOf \
                $(SRCDIR)\test.asn1 test_template_asn1 \
        || ($(RM) $(OBJ)\test_template_asn1.h ; exit /b 1)
        cd $(SRCDIR)
@@ -408,7 +487,7 @@ $(OBJ)\der-private.h: $(libasn1_SOURCES)
 clean::
        -$(RM) $(INCDIR)\der-protos.h
 
-all:: $(INCFILES) $(GENINCFILES) $(ASN1_BINARIES) $(LIBASN1)
+all:: $(INCFILES) $(GENINCFILES) $(ASN1_BINARIES) $(LIBASN1) $(LIBASN1_S)
 
 all-tools:: $(LIBEXECDIR)\asn1_print.exe $(BINDIR)\asn1_gen.exe
 
@@ -454,7 +533,7 @@ $(OBJ)\check-der.exe: $(OBJ)\check-der.obj $(OBJ)\check-common.obj \
        $(EXEPREP_NODIST)
 
 $(OBJ)\check-gen-template.exe: $(OBJ)\check-gen.obj $(OBJ)\check-common.obj \
-               $(LIBHEIMDAL) $(LIBROKEN) $(gen_files_test_template:.x=.obj)
+               $(LIBHEIMDAL) $(LIBROKEN) $(OBJ)\asn1_test_template_asn1.obj
        $(EXECONLINK)
        $(EXEPREP_NODIST)
 
@@ -464,6 +543,6 @@ $(OBJ)\check-timegm.exe: $(OBJ)\check-timegm.obj \
        $(EXEPREP_NODIST)
 
 $(OBJ)\check-template.exe: $(OBJ)\check-template.obj $(OBJ)\check-common.obj \
-               $(LIBHEIMDAL) $(LIBROKEN) $(gen_files_test:.x=.obj)
+               $(LIBHEIMDAL) $(LIBROKEN) $(OBJ)\asn1_test_asn1.obj
        $(EXECONLINK)
        $(EXEPREP_NODIST)
index a00dde72227ffb06d13f07c3a2213745d125ec7e..9c4e6979569ca2200b6e33cc3c009d3db4963636 100644 (file)
@@ -14,7 +14,7 @@ annotations](/lib/asn1/README-X681.md).
  5. [Limitations](#Limitations)
  6. [Compiler Usage](#Compiler-usage)
  7. [APIs Generated by the Compiler](#APIs-generated-by-the-compiler)
- 8. [asn1_print Usage](#asn1_print-usage)
+ 8. [`asn1_print` Usage](#asn1_print-usage)
  9. [Implementation](#implementation)
  10. [Moving From C](#moving-from-c)
 
@@ -166,11 +166,14 @@ In recent times the following features have been added:
  - Automatic open type traversal, using a subset of X.681/X.682/X.683 for
    expressing the requisite metadata.
 
+ - Decoration of ASN.1 types with "hidden" fields (ones that don't get encoded
+   or decoded) of ASN.1 or C types.
+
 ## Futures
 
  - JER support?
 
- - XDR/OER support?
+ - XDR/NDR/OER support?
 
  - Generate comparators?  (lib/hx509 has a half-baked Certificate comparator)
 
@@ -181,6 +184,43 @@ In recent times the following features have been added:
  - Most of X.690 is supported for decoding, with only DER supported for
    encoding.
 
+ - For cryptographic applications there is a `--preserve-binary=TYPE` compiler
+   option that causes the `TYPE`'s C `struct` to gain a `_save` field where the
+   original encoding of the `TYPE` is preserved by the decoder.  This allows
+   cryptographic applications to validate signatures, MACs, authenticated
+   decryption tags, checksums, etc., without having to re-encode the `TYPE`
+   (which wouldn't even work if the encoding received were BER and BER were
+   permitted for that `TYPE`).
+
+ - Unconstrained integer types have a large integer representation in C that is
+   not terribly useful in common cases.  Range and member constraints on
+   integer types cause the compiler to use `int`, `int64_t`, `unsigned int`,
+   and/or `uint64_t` as appropriate.
+
+ - The Heimdal ASN.1 compiler currently handles a large subset of X.680, and
+   (in a branch) a small subset of X.681, X.682, and X.683, which manifests as
+   automatic handling of all open types contained in `SET`/`SEQUENCE` types
+   that are parameterized with information object sets.  This allows all open
+   types in PKIX certificates, for example, to get decoded automatically no
+   matter how deeply nested.  We use a TCG EK certificate that has eight
+   certificate extensions, including subject alternative names and subject
+   directory attributes where the attribute values are not string types, and
+   all of these things get decoded automatically.
+
+ - The template backend dedups templates to save space.  This is an O(N^2) kind
+   of feature that we need to make optional, but it works.  (When we implement
+   JER this will have the side-effect of printing the wrong type names in some
+   cases because two or more types have the same templates and get deduped.)
+
+ - There is an _experimental_ ASN.1 module -> JSON feature in the compiler.  It
+   currently dumps type and value definitions, but not class, or object set
+   definitions.  Even for types, it is not complete, and the JSON schema used
+   is subject to change *WITHOUT NOTICE*.
+
+   Perhaps eventually we can re-write the compiler as a C-coded ASN.1 -> JSON
+   stage followed by a jq-coded code and template generator state, which would
+   make it much easier to extend the compiler.
+
  - We have an `asn1_print` program that can decode DER from any exported types
    from any ASN.1 modules committed in Heimdal:
 
@@ -780,40 +820,12 @@ In recent times the following features have been added:
    slightly different names in the ASN.1 modules in Heimdal's source tree.
    We'll fix this eventually.)
 
- - Unconstrained integer types have a large integer representation in C that is
-   not terribly useful in common cases.  Range constraints on integer types
-   cause the compiler to use `int32_t`, `int64_t`, `uint32_t`, and/or
-   `uint64_t`.
-
- - The Heimdal ASN.1 compiler currently handles a large subset of X.680, and
-   (in a branch) a small subset of X.681, X.682, and X.683, which manifests as
-   automatic handling of all open types contained in `SET`/`SEQUENCE` types
-   that are parameterized with information object sets.  This allows all open
-   types in PKIX certificates, for example, to get decoded automatically no
-   matter how deeply nested.  We use a TCG EK certificate that has eight
-   certificate extensions, including subject alternative names and subject
-   directory attributes where the attribute values are not string types, and
-   all of these things get decoded automatically.
-
- - The template backend dedups templates to save space.  This is an O(N^2) kind
-   of feature that we need to make optional, but it works.  (When we implement
-   JER this will have the side-effect of printing the wrong type names in some
-   cases because two or more types have the same templates and get deduped.)
-
- - There is an _experimental_ ASN.1 -> JSON feature in the compiler.  It
-   currently dumps type and value definitions, but not class, or object set
-   definitions.  Even for types, it is not complete, and the JSON schema used
-   is subject to change *WITHOUT NOTICE*.
-
-   Perhaps eventually we can re-write the compiler as a C-coded ASN.1 -> JSON
-   stage followed by a jq-coded code and template generator state, which would
-   make it much easier to extend the compiler.
-
 ...
 
 ## Limitations
 
- - `asn1_print`'s JSON support is not X.697 (JER) compatible.
+ - `libasn1`'s and, therefore, `asn1_print`'s JSON support is not X.697 (JER)
+   compatible.
 
  - Control over C types generated is very limited, mainly only for integer
    types.
@@ -839,6 +851,12 @@ In recent times the following features have been added:
    values of `SET`, `SEQUENCE`, `SET OF`, and `SEQUENCE OF`), is not supported.
    Values of `CHOICE` types are also not supported.
 
+ - There is no way to substitute object sets at run-time.  This means that
+   automatic decoding through open types will spend more CPU cycles than the
+   application might want, by decoding more types than the application might
+   care about.  The ability to substitute object sets at run-time would require
+   a change to the APIs generated.
+
  - ...
 
 ## Compiler Usage
@@ -861,104 +879,218 @@ functions for adding or removing items from the named type when it is a
 
 See the manual page `asn1_compile.1`:
 
-```
-ASN1_COMPILE(1)       HEIMDAL General Commands Manual          ASN1_COMPILE(1)
+```text
+ASN1_COMPILE(1)                  BSD General Commands Manual          ASN1_COMPILE(1)
 
 NAME
      asn1_compile — compile ASN.1 modules
 
 SYNOPSIS
      asn1_compile [--template] [--prefix-enum] [--enum-prefix=PREFIX]
-                  [--encode-rfc1510-bit-string] [--decode-dce-ber]
-                  [--support-ber] [--preserve-binary=TYPE-NAME]
-                  [--sequence=TYPE-NAME] [--one-code-file] [--gen-name=NAME]
-                  [--decorate=TYPE-NAME:FIELD-TYPE:field-name[?]]
-                  [--option-file=FILE] [--original-order] [--no-parse-units]
-                  [--type-file=C-HEADER-FILE] [--version] [--help]
-                  [FILE.asn1 [NAME]]
+                 [--encode-rfc1510-bit-string] [--decode-dce-ber]
+                 [--support-ber] [--preserve-binary=TYPE] [--sequence=TYPE]
+                 [--decorate=DECORATION] [--one-code-file] [--gen-name=NAME]
+                 [--option-file=FILE] [--original-order] [--no-parse-units]
+                 [--type-file=C-HEADER-FILE] [--version] [--help]
+                 [FILE.asn1 [NAME]]
 
 DESCRIPTION
-     asn1_compile Compiles an ASN.1 module into C source code and header
+     asn1_compile compiles an ASN.1 module into C source code and header
      files.
 
+     A fairly large subset of ASN.1 as specified in X.680, and the ASN.1 In‐
+     formation Object System as specified in X.681, X.682, and X.683 is sup‐
+     ported, with support for the Distinguished Encoding Rules (DER), partial
+     Basic Encoding Rules (BER) support, and experimental JSON support (encod‐
+     ing only at this time).
+
+     See the compiler's README files for details about the C code and inter‐
+     faces it generates.
+
+     The Information Object System support includes automatic codec support
+     for encoding and decoding through “open types” which are also known as
+     “typed holes”.  See RFC 5912 for examples of how to use the ASN.1 Infor‐
+     mation Object System via X.681/X.682/X.683 annotations.  See the com‐
+     piler's README files for more information on ASN.1 Information Object
+     System support.
+
+     Extensions specific to Heimdal are generally not syntactic in nature but
+     rather command-line options to this program.  For example, one can use
+     command-line options to:
+          •     enable decoding of BER-encoded values;
+          •     enable RFC1510-style handling of ‘BIT STRING’ types;
+          •     enable saving of as-received encodings of specific types
+                  for the purpose of signature validation;
+          •     generate add/remove utility functions for array types;
+          •     decorate generated ‘struct’ types with fields that are nei‐
+                  ther encoded nor decoded;
+     etc.
+
+     ASN.1 x.680 features supported:
+          •     most primitive types (except BMPString and REAL);
+          •     all constructed types, including SET and SET OF;
+          •     explicit and implicit tagging.
+
+     Size and range constraints on the ‘INTEGER’ type cause the compiler to
+     generate appropriate C types such as ‘int’, ‘unsigned int’, ‘int64_t’,
+     ‘uint64_t’.  Unconstrained ‘INTEGER’ is treated as ‘heim_integer’, which
+     represents an integer of arbitrary size.
+
+     Caveats and ASN.1 x.680 features not supported:
+          •     JSON encoding support is not quite X.697 (JER) compatible.
+                  Its JSON schema is subject to change without notice.
+          •     Control over C types generated is very limited, mainly only
+                  for integer types.
+          •     When using the template backend, `SET { .. }` types are
+                  currently not sorted by tag as they should be, but if the
+                  module author sorts them by hand then correct DER will be
+                  produced.
+          •     ‘AUTOMATIC TAGS’ is not supported.
+          •     The REAL type is not supported.
+          •     The EmbeddedPDV type is not supported.
+          •     The BMPString type is not supported.
+          •     The IA5String is not properly supported, as it's essen‐
+                  tially treated as a UTF8String with a different tag.
+          •     All supported non-octet strings are treated as like the
+                  UTF8String type.
+          •     Only types can be imported into ASN.1 modules at this time.
+          •     Only simple value syntax is supported.  Constructed value
+                  syntax (i.e., values of SET, SEQUENCE, SET OF, and SEQUENCE
+                  OF types), is not supported.  Values of `CHOICE` types are
+                  also not supported.
+
      Options supported:
 
      --template
-             Use the “template” backend instead of the “codegen” backend
-             (which is the default backend).  The template backend generates
-             “templates” which are akin to bytecode, and which are interpreted
-             at run-time.  The codegen backend generates C code for all func-
-             tions directly, with no template interpretation.  The template
-             backend scales better than the codegen backend because as we add
-             support for more encoding rules the templates stay mostly the
-             same, thus scaling linearly with size of module.  Whereas the
-             codegen backend scales linear with the product of module size and
-             number of encoding rules supported.  More importantly, currently
-             only the template backend supports automatic decoding of open
-             types via X.681/X.682/X.683 annotations.
+            Use the “template” backend instead of the “codegen” backend
+            (which is the default backend).
+
+            The template backend generates “templates” which are akin to
+            bytecode, and which are interpreted at run-time.
+
+            The codegen backend generates C code for all functions directly,
+            with no template interpretation.
+
+            The template backend scales better than the codegen backend be‐
+            cause as we add support for more encoding rules and more opera‐
+            tions (we may add value comparators) the templates stay mostly
+            the same, thus scaling linearly with size of module.  Whereas the
+            codegen backend scales linear with the product of module size and
+            number of encoding rules supported.
 
      --prefix-enum
-             This option should be removed because ENUMERATED types should
-             always have their labels prefixed.
+            This option should be removed because ENUMERATED types should al‐
+            ways have their labels prefixed.
 
      --enum-prefix=PREFIX
-             This option should be removed because ENUMERATED types should
-             always have their labels prefixed.
+            This option should be removed because ENUMERATED types should al‐
+            ways have their labels prefixed.
 
      --encode-rfc1510-bit-string
-             Use RFC1510, non-standard handling of “BIT STRING” types.
+            Use RFC1510, non-standard handling of “BIT STRING” types.
 
      --decode-dce-ber
+
      --support-ber
 
-     --preserve-binary=TYPE-NAME
-             Generate ‘_save’ fields in structs to preserve the original
-             encoding of some sub-value.  This is useful for cryptographic
-             applications to avoid having to re-encode values to check signa-
-             tures, etc.
-
-     --sequence=TYPE-NAME
-             Generate add/remove functions for ‘SET OF’ and ‘SEQUENCE OF’
-             types.
-
-     --decorate=TYPE-NAME:FIELD-TYPE:field-name[?]
-             Add to the TYPE-NAME SET or SEQUENCE type a field of the given
-             FIELD-TYPE and field-name, but do not encode or decode this
-             field.  If the field-name ends in a question mark, then treat the
-             field as OPTIONAL for the purposes of copy/free function stubs.
-             This is useful for adding fields to existing types that can be
-             used for internal bookkeeping but which do not affect interoper-
-             ability because they are not encoded.
+     --preserve-binary=TYPE
+            Generate a field named ‘_save’ in the C struct generated for the
+            named TYPE.  This field is used to preserve the original encoding
+            of the value of the TYPE.
+
+            This is useful for cryptographic applications so that they can
+            check signatures of encoded values as-received without having to
+            re-encode those values.
+
+            For example, the TBSCertificate type should have values preserved
+            so that Certificate validation can check the signatureValue over
+            the tbsCertificate's value as-received.
+
+            The alternative of encoding a value to check a signature of it is
+            brittle.  For types where non-canonical encodings (such as BER)
+            are allowed, this alternative is bound to fail.  Thus the point
+            of this option.
+
+     --sequence=TYPE
+            Generate add/remove functions for the named ASN.1 TYPE which must
+            be a ‘SET OF’ or ‘SEQUENCE OF’ type.
+
+     --decorate=ASN1-TYPE:FIELD-ASN1-TYPE:fname[?]
+            Add to the C struct generated for the given ASN.1 SET, SEQUENCE,
+            or CHOICE type named ASN1-TYPE a “hidden” field named fname of
+            the given ASN.1 type FIELD-ASN1-TYPE, but do not encode or decode
+            it.  If the fname ends in a question mark, then treat the field
+            as OPTIONAL.
+
+            This is useful for adding fields to existing types that can be
+            used for internal bookkeeping but which do not affect interoper‐
+            ability because they are neither encoded nor decoded.  For exam‐
+            ple, one might decorate a request type with state needed during
+            processing of the request.
+
+     --decorate=ASN1-TYPE:void*:fname
+            Add to the C struct generated for the given ASN.1 SET, SEQUENCE,
+            or CHOICE type named ASN1-TYPE a “hidden” field named fname of
+            type ‘void *’ (but do not encode or decode it.
+
+            The destructor and copy constructor functions generated by this
+            compiler for ASN1-TYPE will set this field to the ‘NULL’ pointer.
+
+     --decorate=ASN1-TYPE:FIELD-C-TYPE:fname[?]:[copyfn]:[freefn]:header
+            Add to the C struct generated for the given ASN.1 SET, SEQUENCE,
+            or CHOICE type named ASN1-TYPE a “hidden” field named fname of
+            the given external C type FIELD-C-TYPE, declared in the given
+            header but do not encode or decode this field.  If the fname ends
+            in a question mark, then treat the field as OPTIONAL.
+
+            The header must include double quotes or angle brackets.  The
+            copyfn must be the name of a copy constructor function that takes
+            a pointer to a source value of the type, and a pointer to a des‐
+            tination value of the type, in that order, and which returns zero
+            on success or else a system error code on failure.  The freefn
+            must be the name of a destructor function that takes a pointer to
+            a value of the type and which releases resources referenced by
+            that value, but does not free the value itself (the run-time al‐
+            locates this value as needed from the C heap).  The freefn should
+            also reset the value to a pristine state (such as all zeros).
+
+            If the copyfn and freefn are empty strings, then the decoration
+            field will neither be copied nor freed by the functions generated
+            for the TYPE.
 
      --one-code-file
-             Generate a single source code file.  Otherwise a separate code
-             file will be generated for every type.
+            Generate a single source code file.  Otherwise a separate code
+            file will be generated for every type.
 
      --gen-name=NAME
-             Use NAME to form the names of the files generated.
+            Use NAME to form the names of the files generated.
 
      --option-file=FILE
-             Take additional command-line options from FILE.
+            Take additional command-line options from FILE.
 
      --original-order
-             Attempt to preserve the original order of type definition in the
-             ASN.1 module.  By default the compiler generates types in a topo-
-             logical sort order.
+            Attempt to preserve the original order of type definition in the
+            ASN.1 module.  By default the compiler generates types in a topo‐
+            logical sort order.
 
      --no-parse-units
-             Do not generate to-int / from-int functions for enumeration
-             types.
+            Do not generate to-int / from-int functions for enumeration
+            types.
 
      --type-file=C-HEADER-FILE
-             Generate an include of the named header file that might be needed
-             for common type defintions.
+            Generate an include of the named header file that might be needed
+            for common type defintions.
 
      --version
 
      --help
 
-HEIMDAL                        February 22, 2021                       HEIMDAL
+NOTES
+     Currently only the template backend supports automatic encoding and de‐
+     coding of open types via the ASN.1 Information Object System and
+     X.681/X.682/X.683 annotations.
 
+HEIMDAL                               February 22, 2021                       HEIMDAL
 ```
 
 ## APIs Generated by the Compiler
@@ -1076,9 +1208,9 @@ absence and non-NULL indicating presence.
 
 And so on.
 
-## asn1_print Usage
+## `asn1_print` Usage
 
-```
+```text
 ASN1_PRINT(1)            BSD General Commands Manual            ASN1_PRINT(1)
 
 NAME
@@ -1170,13 +1302,19 @@ See:
 
  - Add JER support so we can convert between JER and DER?
 
- - Add XDR support?
+ - Add XDR support?  There are no ASN.1 Encoding Rules based on XDR, but it is
+   trivial to construct such for at least that subset of ASN.1 for which the
+   XDR syntax has equivalent semantics.
 
  - Add OER support?
 
- - Add NDR support?
+ - Add NDR support?  There are no ASN.1 Encoding Rules based on NDR, but it is
+   trivial to construct such for at least that subset of ASN.1 for which the
+   IDL syntax has equivalent semantics.
 
- - Perhaps third parties will contribute more control over generate types?
+ - Perhaps third parties will contribute more control over generated types?
+   This may require separate publication of the Heimdal ASN.1 compiler from the
+   rest of Heimdal.
 
 ## Moving From C
 
index e75734ea26ce29a2e48c017301813e591409554d..07c4461e3e9ae1eed353d6152df7f79e9b3bae49 100644 (file)
  * TBD:
  * 
  *  - For OER also encode number of optional/default/extension elements into
- *    header entry's ptr field, not just the number of entries that follow it
+ *    header entry's ptr field, not just the number of entries that follow it.
  *
- *  - For JER/GSER/whatver, and probably for not-C-coded template interpreters,
- *    we'll need to have an entry type for the names of structures and their
- *    fields.
+ *  - For JER we'll need to encode encoding options (encode as array, encode as
+ *    object, etc.)
  *
- *  - For auto open types we need a new opcode, let's call it
- *    A1_OP_OPENTYPE_OBJSET, and we need to encode into its entry:
- *    a) the index of the template entry for the type ID field, and
- *    b) the index of the template entry for the open type field,
- *    c) 1 bit to indicate whether the object set is sorted by type ID value,
- *    d) a pointer to the object set's template.
- *    With that we can then find the struct offsets of those, and also their
- *    types (since we can find their template entries).
- *    The object set entries should be encoded into two template entries each:
- *    one pointing to the value of the type ID field for that object (unless
- *    the value is an integer, in which case the ptr should be the integer
- *    value directly), and the other pointing to the template for the type
- *    identified by the type ID.  These will need an opcode each...
- *    A1_OP_OPENTYPE_ID and A1_OP_OPENTYPE.
- *    We should also end the object set with an A1_OP_OPENTYPE_OBJSET entry so
- *    that iterating backwards can be fast.  Unless... unless we don't inline
- *    the object set and its objects but point to the object set's template.
- *    Also, for extensible object sets we can point to the object set's name,
- *    and we can then have a function to get an object set template by name,
- *    one to release that, and one to add an object to the object set (there's
- *    no need to remove objects from object sets, which helps with thread-
- *    safety).  And then we don't need (c) either.
- *    The decoder will then not see these entries until after decoding the type
- *    ID and open type field (as its outer type, so OCTET STRING, BIT STRING,
- *    or HEIM_ANY) and so it will be able to find those values in the struct at
- *    their respective offsets.
- *    The encoder and decoder both need to identify the relevant object in the
- *    object set, either by linear search or binary search if they are sorted
- *    by type ID value, then interpret the template for the identified type.
- *    The encoder needs to place the encoding into the normal location for it
- *    in the struct, then it can execute the normal template entry for it.
+ *  - For open types we'll need to be able to indicate what encoding rules the
+ *    type uses.
+ *
+ *  - We have too many bits for tags (20) and probably not enough for ops (4
+ *    bits, and we've used all but one).
  */
 
 /* header:
  * 28..31 op
  */
 
-#define A1_OP_MASK             (0xf0000000)
-#define A1_OP_TYPE             (0x10000000)
-#define A1_OP_TYPE_EXTERN      (0x20000000)
-#define A1_OP_TAG              (0x30000000)
-#define A1_OP_PARSE            (0x40000000)
-#define A1_OP_SEQOF            (0x50000000)
-#define A1_OP_SETOF            (0x60000000)
-#define A1_OP_BMEMBER          (0x70000000)
-#define A1_OP_CHOICE           (0x80000000)
-#define A1_OP_DEFVAL           (0x90000000)
-#define A1_OP_OPENTYPE_OBJSET  (0xa0000000)
-#define A1_OP_OPENTYPE_ID      (0xb0000000)
-#define A1_OP_OPENTYPE         (0xc0000000)
-#define A1_OP_NAME             (0xd0000000)
-#define A1_OP_TYPE_DECORATE    (0xe0000000)
+#define A1_OP_MASK                     (0xf0000000)
+#define A1_OP_TYPE                     (0x10000000) /* templated type */
+#define A1_OP_TYPE_EXTERN              (0x20000000) /* templated type (imported) */
+#define A1_OP_TAG                      (0x30000000) /* a tag */
+#define A1_OP_PARSE                    (0x40000000) /* primitive type */
+#define A1_OP_SEQOF                    (0x50000000) /* sequence of */
+#define A1_OP_SETOF                    (0x60000000) /* set      of */
+#define A1_OP_BMEMBER                  (0x70000000) /* BIT STRING member */
+#define A1_OP_CHOICE                   (0x80000000) /* CHOICE */
+#define A1_OP_DEFVAL                   (0x90000000) /* def. value */
+#define A1_OP_OPENTYPE_OBJSET          (0xa0000000) /* object set for open type */
+#define A1_OP_OPENTYPE_ID              (0xb0000000) /* open type id field */
+#define A1_OP_OPENTYPE                 (0xc0000000) /* open type    field */
+#define A1_OP_NAME                     (0xd0000000) /* symbol */
+#define A1_OP_TYPE_DECORATE            (0xe0000000) /* decoration w/ templated type */
+#define A1_OP_TYPE_DECORATE_EXTERN     (0xf0000000) /* decoration w/ some C type */
+                                                    /* 0x00.. is still free */
 
 #define A1_FLAG_MASK           (0x0f000000)
 #define A1_FLAG_OPTIONAL       (0x01000000)
index 74cf314f16e4b719ed3e24e39eef69c5bcd2e77a..a7953df5fa17df10b32371eed598f0bb9a2a9dcb 100644 (file)
@@ -46,9 +46,9 @@
 .Op Fl Fl encode-rfc1510-bit-string
 .Op Fl Fl decode-dce-ber
 .Op Fl Fl support-ber
-.Op Fl Fl preserve-binary=TYPE-NAME
-.Op Fl Fl sequence=TYPE-NAME
-.Op Fl Fl decorate=TYPE-NAME:FIELD-TYPE:field-name[?]
+.Op Fl Fl preserve-binary=TYPE
+.Op Fl Fl sequence=TYPE
+.Op Fl Fl decorate=DECORATION
 .Op Fl Fl one-code-file
 .Op Fl Fl gen-name=NAME
 .Op Fl Fl option-file=FILE
 .Ek
 .Sh DESCRIPTION
 .Nm
-Compiles an ASN.1 module into C source code and header files.
+compiles an ASN.1 module into C source code and header files.
+.Pp
+A fairly large subset of ASN.1 as specified in X.680, and the
+ASN.1 Information Object System as specified in X.681, X.682, and
+X.683 is supported, with support for the Distinguished Encoding
+Rules (DER), partial Basic Encoding Rules (BER) support, and
+experimental JSON support (encoding only at this time).
+.Pp
+See the compiler's README files for details about the C code and
+interfaces it generates.
+.Pp
+The Information Object System support includes automatic codec
+support for encoding and decoding through
+.Dq open types
+which are also known as
+.Dq typed holes .
+See RFC 5912 for examples of how to use the ASN.1
+Information Object System via X.681/X.682/X.683 annotations.  See
+the compiler's README files for more information on ASN.1
+Information Object System support.
+.Pp
+Extensions specific to Heimdal are generally not syntactic in
+nature but rather command-line options to this program.
+For example, one can use command-line options to:
+.Bl -bullet -compact -width Ds -offset indent
+.It
+enable decoding of BER-encoded values;
+.It
+enable RFC1510-style handling of
+.Sq BIT STRING
+types;
+.It
+enable saving of as-received encodings of specific types for the
+purpose of signature validation;
+.It
+generate add/remove utility functions for array types;
+.It
+decorate generated
+.Sq struct
+types with fields that are neither encoded nor decoded;
+.El
+etc.
+.Pp
+ASN.1 x.680 features supported:
+.Bl -bullet -compact -width Ds -offset indent
+.It
+most primitive types (except BMPString and REAL);
+.It
+all constructed types, including SET and SET OF;
+.It
+explicit and implicit tagging.
+.El
+.Pp
+Size and range constraints on the
+.Sq INTEGER
+type cause the compiler to generate appropriate C types such as
+.Sq int ,
+.Sq unsigned int ,
+.Sq int64_t ,
+.Sq uint64_t .
+Unconstrained
+.Sq INTEGER
+is treated as
+.Sq heim_integer ,
+which represents an integer of arbitrary size.
+.Pp
+Caveats and ASN.1 x.680 features not supported:
+.Bl -bullet -compact -width Ds -offset indent
+.It
+JSON encoding support is not quite X.697 (JER) compatible.
+Its JSON schema is subject to change without notice.
+.It
+Control over C types generated is very limited, mainly only for
+integer types.
+.It
+When using the template backend, `SET { .. }` types are currently
+not sorted by tag as they should be, but if the module author
+sorts them by hand then correct DER will be produced.
+.It
+.Sq AUTOMATIC TAGS
+is not supported.
+.It
+The
+.Va REAL
+type is not supported.
+.It
+The
+.Va EmbeddedPDV
+type is not supported.
+.It
+The
+.Va BMPString
+type is not supported.
+.It
+The
+.Va IA5String
+is not properly supported, as it's essentially treated as a
+.Va UTF8String
+with a different tag.
+.It
+All supported non-octet strings are treated as like the
+.Va UTF8String
+type.
+.It
+Only types can be imported into ASN.1 modules at this time.
+.It
+Only simple value syntax is supported.
+Constructed value syntax (i.e., values of SET, SEQUENCE, SET OF,
+and SEQUENCE OF types), is not supported.
+Values of `CHOICE` types are also not supported.
+.El
 .Pp
 Options supported:
 .Bl -tag -width Ds
@@ -71,20 +181,21 @@ Use the
 backend instead of the
 .Dq codegen
 backend (which is the default backend).
+.Pp
 The template backend generates
 .Dq templates
 which are akin to bytecode, and which are interpreted at
 run-time.
+.Pp
 The codegen backend generates C code for all functions directly,
 with no template interpretation.
+.Pp
 The template backend scales better than the codegen backend
-because as we add support for more encoding rules the templates
-stay mostly the same, thus scaling linearly with size of module.
+because as we add support for more encoding rules and more
+operations (we may add value comparators) the templates stay
+mostly the same, thus scaling linearly with size of module.
 Whereas the codegen backend scales linear with the product of
 module size and number of encoding rules supported.
-More importantly, currently only the template backend supports
-automatic decoding of open types via X.681/X.682/X.683
-annotations.
 .It Fl Fl prefix-enum
 This option should be removed because ENUMERATED types should
 always have their labels prefixed.
@@ -97,34 +208,118 @@ Use RFC1510, non-standard handling of
 types.
 .It Fl Fl decode-dce-ber
 .It Fl Fl support-ber
-.It Fl Fl preserve-binary=TYPE-NAME
-Generate
+.It Fl Fl preserve-binary=TYPE
+Generate a field named
 .Sq _save
-fields in structs to preserve the original encoding of some
-sub-value.
-This is useful for cryptographic applications to avoid having to
-re-encode values to check signatures, etc.
-.It Fl Fl sequence=TYPE-NAME
-Generate add/remove functions for
+in the C struct generated for the named
+.Ar TYPE .
+This field is used to preserve the original encoding of the value
+of the
+.Ar TYPE .
+.Pp
+This is useful for cryptographic applications so that they can
+check signatures of encoded values as-received without having to
+re-encode those values.
+.Pp
+For example, the TBSCertificate type should have values preserved
+so that Certificate validation can check the signatureValue over
+the tbsCertificate's value as-received.
+.Pp
+The alternative of encoding a value to check a signature of it is
+brittle.
+For types where non-canonical encodings (such as BER) are
+allowed, this alternative is bound to fail.
+Thus the point of this option.
+.It Fl Fl sequence=TYPE
+Generate add/remove functions for the named ASN.1
+.Ar TYPE
+which must be a
 .Sq SET OF
-and
+or
 .Sq SEQUENCE OF
-types.
-.It Fl Fl decorate=TYPE-NAME:FIELD-TYPE:field-name[?]
-Add to the
-.Va TYPE-NAME
-SET or SEQUENCE type a field of the given
-.Va FIELD-TYPE
-and
-.Va field-name ,
+type.
+.It Fl Fl decorate=ASN1-TYPE:FIELD-ASN1-TYPE:fname[?]
+Add to the C struct generated for the given ASN.1 SET, SEQUENCE, or
+CHOICE type named
+.Ar ASN1-TYPE
+a
+.Dq hidden
+field named
+.Ar fname
+of the given ASN.1 type
+.Ar FIELD-ASN1-TYPE ,
+but do not encode or decode it.
+If the
+.Ar fname
+ends in a question mark, then treat the field as OPTIONAL.
+.Pp
+This is useful for adding fields to existing types that can be
+used for internal bookkeeping but which do not affect
+interoperability because they are neither encoded nor decoded.
+For example, one might decorate a request type with state needed
+during processing of the request.
+.It Fl Fl decorate=ASN1-TYPE:void*:fname
+Add to the C struct generated for the given ASN.1 SET, SEQUENCE, or
+CHOICE type named
+.Ar ASN1-TYPE
+a
+.Dq hidden
+field named
+.Ar fname
+of type
+.Sq void *
+(but do not encode or decode it.
+.Pp
+The destructor and copy constructor functions generated by this
+compiler for
+.Ar ASN1-TYPE
+will set this field to the
+.Sq NULL
+pointer.
+.It Fl Fl decorate=ASN1-TYPE:FIELD-C-TYPE:fname[?]:[copyfn]:[freefn]:header
+Add to the C struct generated for the given ASN.1 SET, SEQUENCE, or
+CHOICE type named
+.Ar ASN1-TYPE
+a
+.Dq hidden
+field named
+.Ar fname
+of the given external C type
+.Ar FIELD-C-TYPE ,
+declared in the given
+.Ar header
 but do not encode or decode this field.
 If the
-.Va field-name
-ends in a question mark, then treat the field as OPTIONAL for
-the purposes of copy/free function stubs.
-This is useful for adding fields to existing types that can be used
-for internal bookkeeping but which do not affect interoperability
-because they are not encoded.
+.Ar fname
+ends in a question mark, then treat the field as OPTIONAL.
+.Pp
+The
+.Ar header
+must include double quotes or angle brackets.
+The
+.Ar copyfn
+must be the name of a copy constructor function that takes a
+pointer to a source value of the type, and a pointer to a
+destination value of the type, in that order, and which returns
+zero on success or else a system error code on failure.
+The
+.Ar freefn
+must be the name of a destructor function that takes a pointer to
+a value of the type and which releases resources referenced by
+that value, but does not free the value itself (the run-time
+allocates this value as needed from the C heap).
+The
+.Ar freefn
+should also reset the value to a pristine state (such as all
+zeros).
+.Pp
+If the
+.Ar copyfn
+and
+.Ar freefn
+are empty strings, then the decoration field will neither be
+copied nor freed by the functions generated for the
+.Ar TYPE .
 .It Fl Fl one-code-file
 Generate a single source code file.
 Otherwise a separate code file will be generated for every type.
@@ -149,3 +344,7 @@ for common type defintions.
 .It Fl Fl version
 .It Fl Fl help
 .El
+.Sh NOTES
+Currently only the template backend supports automatic encoding
+and decoding of open types via the ASN.1 Information Object
+System and X.681/X.682/X.683 annotations.
index 39c43341aa62d278f7440618230b69d591748177..40c37fbbb9461c040f9cc43d2b17dcb23bb0a86a 100644 (file)
@@ -114,22 +114,22 @@ const struct types {
         (releaser)free_ ## gns,         \
     },
 #endif
-#include "cms_asn1_syms.x"
-#include "digest_asn1_syms.x"
-#include "krb5_asn1_syms.x"
-#include "kx509_asn1_syms.x"
-#include "ocsp_asn1_syms.x"
-#include "pkcs10_asn1_syms.x"
-#include "pkcs12_asn1_syms.x"
-#include "pkcs8_asn1_syms.x"
-#include "pkcs9_asn1_syms.x"
-#include "pkinit_asn1_syms.x"
-#include "rfc2459_asn1_syms.x"
-#include "rfc4108_asn1_syms.x"
+#include "cms_asn1_syms.c"
+#include "digest_asn1_syms.c"
+#include "krb5_asn1_syms.c"
+#include "kx509_asn1_syms.c"
+#include "ocsp_asn1_syms.c"
+#include "pkcs10_asn1_syms.c"
+#include "pkcs12_asn1_syms.c"
+#include "pkcs8_asn1_syms.c"
+#include "pkcs9_asn1_syms.c"
+#include "pkinit_asn1_syms.c"
+#include "rfc2459_asn1_syms.c"
+#include "rfc4108_asn1_syms.c"
 #ifdef ASN1_PRINT_SUPPORTED
-#include "x690sample_template_asn1_syms.x"
+#include "x690sample_template_asn1_syms.c"
 #else
-#include "x690sample_asn1_syms.x"
+#include "x690sample_asn1_syms.c"
 #endif
 };
 
@@ -453,10 +453,8 @@ dotype(unsigned char *buf, size_t len, char **argv, size_t *size)
                     char *s;
 
                     s = sorted_types[i].print(v, indent_flag ? ASN1_PRINT_INDENT : 0);
-                    if (!s) {
-                        ret = errno;
+                    if (!s)
                         err(1, "Could not print %s\n", typename);
-                    }
                     if (!quiet_flag)
                         printf("%s\n", s);
                     free(s);
index 290cb86310edfd83318aed1008ec6e2efbcf5302..f6f6ec0e5c46af3170d1ab869358abc27aa9f429 100644 (file)
@@ -242,6 +242,7 @@ static unsigned long idcounter;
 %type <type> BooleanType
 %type <type> ChoiceType
 %type <type> ConstrainedType
+%type <type> UnconstrainedType
 %type <type> EnumeratedType
 %type <type> IntegerType
 %type <type> NullType
@@ -288,6 +289,7 @@ static unsigned long idcounter;
 
 %type <constraint_spec> Constraint
 %type <constraint_spec> ConstraintSpec
+%type <constraint_spec> SubtypeConstraint
 %type <constraint_spec> GeneralConstraint
 %type <constraint_spec> ContentsConstraint
 %type <constraint_spec> UserDefinedConstraint
@@ -295,7 +297,6 @@ static unsigned long idcounter;
 %type <constraint_spec> ComponentRelationConstraint
 
 
-
 %start ModuleDefinition
 
 %%
@@ -304,6 +305,9 @@ static unsigned long idcounter;
  * We have sinned by allowing types to have names that start with lower-case,
  * and values that have names that start with upper-case.
  *
+ * UPDATE: We sin no more.  However, parts of this block comment are still
+ * relevant.
+ *
  * That worked when we only supported basic X.680 because the rules for
  * TypeAssignment and ValueAssignment are clearly unambiguous in spite of the
  * case issue.
@@ -312,35 +316,41 @@ static unsigned long idcounter;
  * have to help us distinguish certain rules is the form of an identifier: the
  * case of its first letter.
  *
- * We have begun to undo our sin by not allowing wrong-case identifiers in
- * certain situations.
+ * We have cleansed our sin by not allowing wrong-case identifiers any more.
  *
  * Some historical instances of this sin in-tree:
  *
- *  - DOMAIN-X500-COMPRESS (value (enum) but name starts with upper-case)
- *  - krb5int32                   (type         but name starts with lower-case)
- *  - krb5uint32          (type         but name starts with lower-case)
- *  - hdb_keyset          (type         but name starts with lower-case)
- *  - hdb_entry                   (type         but name starts with lower-case)
- *  - hdb_entry_alias      (type         but name starts with lower-case)
+ *  - DOMAIN-X500-COMPRESS  (value (enum) but name starts with upper-case)
+ *  - krb5int32                    (type         but name starts with lower-case)
+ *  - krb5uint32           (type         but name starts with lower-case)
+ *  - hdb_keyset           (type         but name starts with lower-case)
+ *  - hdb_entry                    (type         but name starts with lower-case)
+ *  - hdb_entry_alias       (type         but name starts with lower-case)
+ *  - HDB_DB_FORMAT INTEGER (value (int)  but name starts with upper-case)
  *
- * We have fixed most of these, in some cases leaving behind aliases in header
- * files as needed.
+ * We have fixed all of these and others, in some cases leaving behind aliases
+ * in header files as needed.
  *
- * This issue is probably also the source of remaining shift/reduce conflicts.
+ * We have one shift/reduce conflict (shift ObjectClassAssignment, reduce
+ * TypeAssignment) and one reduce/reduce conflict (ObjectAssignment vs
+ * ValueAssignment) that we avoid by requiring CLASS names to start with an
+ * underscore.
  *
- * In the FieldSetting rule in particular, we get a reduce/reduce conflict if
- * we use `Identifier' instead of `TYPE_IDENTIFIER' for type field settings and
+ * In the FieldSetting rule, also, we get a reduce/reduce conflict if we use
+ * `Identifier' instead of `TYPE_IDENTIFIER' for type field settings and
  * `VALUE_IDENTIFIER' for value field settings, and then we can't make
  * progress.
  *
  * Looking forward, we may not (will not) be able to distinguish ValueSet and
- * ObjectSet field settings from each other either even without committing this
- * leading-identifier-character-case sin, and we may not (will not) be able
- * distinguish Object and Value field settings from each other as well.  To
- * deal with those we will have to run-time type-tag/pun the C structures for
- * valueset/objectset and value/object, and have one rule for each of those
- * that inspects the type of the item to decide what kind of setting it is.
+ * ObjectSet field settings from each other either, and we may not (will not)
+ * be able distinguish Object and Value field settings from each other as well.
+ * To deal with those we will have to run-time type-tag and type-pun the C
+ * structures for valueset/objectset and value/object, and have one rule for
+ * each of those that inspects the type of the item to decide what kind of
+ * setting it is.
+ *
+ * Sadly, the extended syntax for ASN.1 (x.680 + x.681/2/3) appears to have
+ * ambiguities that cannot be resolved with bison/yacc.
  */
 Identifier     : TYPE_IDENTIFIER { $$ = $1; }
                | VALUE_IDENTIFIER { $$ = $1; };
@@ -364,8 +374,6 @@ ModuleDefinition: Identifier objid_opt kw_DEFINITIONS TagDefault ExtensionDefaul
                     fprintf(jsonfile, "]}\n");
                     free(o);
                }
-               | CLASS_IDENTIFIER objid_opt kw_DEFINITIONS TagDefault ExtensionDefault
-                       EEQUAL kw_BEGIN ModuleBody kw_END
                ;
 
 TagDefault     : kw_EXPLICIT kw_TAGS
@@ -914,10 +922,20 @@ ParamGovernor   : DefinedObjectClass
             /* | Type */
                ;
 
-Type           : BuiltinType
-               | ReferencedType
-               | ConstrainedType
-               ;
+UnconstrainedType : BitStringType
+                  | BooleanType
+                  | CharacterStringType
+                  | ChoiceType
+                  | EnumeratedType
+                  | IntegerType
+                  | NullType
+                  | ObjectIdentifierType
+                  | OctetStringType
+                  | SequenceType
+                  | SetType
+                  | ObjectClassFieldType; /* X.681 */
+
+Type           : BuiltinType | ReferencedType | ConstrainedType ;
 
 BuiltinType    : BitStringType
                | BooleanType
@@ -948,39 +966,49 @@ BooleanType       : kw_BOOLEAN
                }
                ;
 
-range          : '(' Value RANGE Value ')'
+             /*
+              * The spec says the values in a ValueRange are Values, but a) all
+              * the various value ranges do not involve OBJECT IDENTIFIER, b)
+              * we only support integer value ranges at this time (as opposed
+              * to, e.g., time ranges, and we don't even support time values at
+              * this time), c) allowing OBJECT IDENTIFIER here causes a
+              * shift-reduce conflict, so we limit ourselves to integer values
+              * in ranges.  We could always define IntegerValueRange,
+              * TimeValueRange, etc. when we add support for more value types.
+              */
+range          : IntegerValue RANGE IntegerValue
                {
-                   if($2->type != integervalue)
+                   if($1->type != integervalue)
                        lex_error_message("Non-integer used in first part of range");
-                   if($2->type != integervalue)
+                   if($1->type != integervalue)
                        lex_error_message("Non-integer in second part of range");
                    $$ = ecalloc(1, sizeof(*$$));
-                   $$->min = $2->u.integervalue;
-                   $$->max = $4->u.integervalue;
+                   $$->min = $1->u.integervalue;
+                   $$->max = $3->u.integervalue;
                }
-               | '(' Value RANGE kw_MAX ')'
+               | IntegerValue RANGE kw_MAX
                {
-                   if($2->type != integervalue)
+                   if($1->type != integervalue)
                        lex_error_message("Non-integer in first part of range");
                    $$ = ecalloc(1, sizeof(*$$));
-                   $$->min = $2->u.integervalue;
+                   $$->min = $1->u.integervalue;
                    $$->max = INT_MAX;
                }
-               | '(' kw_MIN RANGE Value ')'
+               | kw_MIN RANGE IntegerValue
                {
-                   if($4->type != integervalue)
+                   if($3->type != integervalue)
                        lex_error_message("Non-integer in second part of range");
                    $$ = ecalloc(1, sizeof(*$$));
                    $$->min = INT_MIN;
-                   $$->max = $4->u.integervalue;
+                   $$->max = $3->u.integervalue;
                }
-               | '(' Value ')'
+               | IntegerValue
                {
-                   if($2->type != integervalue)
+                   if($1->type != integervalue)
                        lex_error_message("Non-integer used in limit");
                    $$ = ecalloc(1, sizeof(*$$));
-                   $$->min = $2->u.integervalue;
-                   $$->max = $2->u.integervalue;
+                   $$->min = $1->u.integervalue;
+                   $$->max = $1->u.integervalue;
                }
                ;
 
@@ -990,12 +1018,6 @@ IntegerType       : kw_INTEGER
                        $$ = new_tag(ASN1_C_UNIV, UT_Integer,
                                     TE_EXPLICIT, new_type(TInteger));
                }
-               | kw_INTEGER range
-               {
-                       $$ = new_type(TInteger);
-                       $$->range = $2;
-                       $$ = new_tag(ASN1_C_UNIV, UT_Integer, TE_EXPLICIT, $$);
-               }
                | kw_INTEGER '{' NamedNumberList '}'
                {
                  $$ = new_type(TInteger);
@@ -1101,8 +1123,8 @@ NullType  : kw_NULL
 
 size           :
                { $$ = NULL; }
-               | kw_SIZE range
-               { $$ = $2; }
+               | kw_SIZE '(' range ')'
+               { $$ = $3; }
                ;
 
 
@@ -1250,10 +1272,17 @@ UsefulType      : kw_GeneralizedTime
                }
                ;
 
-ConstrainedType        : Type Constraint
+ConstrainedType        : UnconstrainedType Constraint
                {
                    $$ = $1;
-                   $$->constraint = $2;
+                    if ($2->ctype == CT_RANGE) {
+                        if ($1->type != TTag || $1->subtype->type != TInteger)
+                            lex_error_message("RANGE constraints apply only to INTEGER types");
+                        $$->subtype->range = $2->u.range;
+                        free($2);
+                    } else {
+                        $$->constraint = $2;
+                    }
                    /* if (Constraint.type == contentConstraint) {
                       assert(Constraint.u.constraint.type == octetstring|bitstring-w/o-NamedBitList); // remember to check type reference too
                       if (Constraint.u.constraint.type) {
@@ -1274,9 +1303,15 @@ Constraint       : '(' ConstraintSpec ')'
                }
                ;
 
-ConstraintSpec : GeneralConstraint
+ConstraintSpec : SubtypeConstraint | GeneralConstraint
                ;
 
+SubtypeConstraint: range
+               {
+                        $$ = new_constraint_spec(CT_RANGE);
+                        $$->u.range = $1;
+               }
+
 GeneralConstraint: ContentsConstraint
                | UserDefinedConstraint
                | TableConstraint
@@ -1452,7 +1487,7 @@ tagenv            : /* */
                ;
 
 
-ValueAssignment        : Identifier Type EEQUAL Value
+ValueAssignment        : VALUE_IDENTIFIER Type EEQUAL Value
                {
                        Symbol *s;
                        s = addsym ($1);
index 97d1189973979c5c9d82dffa8463d89d2da402c2..6ea1f812651e3d4d784dfa161ff6e909fb69fbc2 100644 (file)
@@ -34,7 +34,8 @@
  */
 
 #define IF_OPT_COMPARE(ac,bc,e) \
-       if (((ac)->e == NULL && (bc)->e != NULL) || (((ac)->e != NULL && (bc)->e == NULL))) return 1; if ((ac)->e)
+       if (((ac)->e == NULL && (bc)->e != NULL) || (((ac)->e != NULL && (bc)->e == NULL))) return 1; \
+        if ((ac)->e)
 #define COMPARE_OPT_STRING(ac,bc,e) \
        do { if (strcmp(*(ac)->e, *(bc)->e) != 0) return 1; } while(0)
 #define COMPARE_OPT_OCTET_STRING(ac,bc,e) \
index 15fd2bcff920068af4a5b2673696a6420528f7be..a8956a74bd26884e33fa0f901b65c69f7838213f 100644 (file)
@@ -900,6 +900,8 @@ test_heim_oid_format_same(const char *str, const heim_oid *oid)
     ret = der_heim_oid_cmp(&o2, oid);
     der_free_oid(&o2);
 
+    if (ret != 0)
+        return 1;
     return 0;
 }
 
index f49f5e8edf92b423c1bc51394decd8fef932a8d8..6b5c71c39f57834c0738a3ef0adc62d557c0db00 100644 (file)
 
 #include "check-common.h"
 
+static int my_copy_vers_called;
+static int my_free_vers_called;
+
+int
+my_copy_vers(const my_vers *from, my_vers *to)
+{
+    my_copy_vers_called++;
+    *to = *from;
+    return 0;
+}
+
+void
+my_free_vers(my_vers *v)
+{
+    my_free_vers_called++;
+    v->v = -1;
+}
+
 static char *lha_principal[] = { "lha" };
 static char *lharoot_princ[] = { "lha", "root" };
 static char *datan_princ[] = { "host", "nutcracker.e.kth.se" };
@@ -1021,7 +1039,7 @@ static int
 test_decorated(void)
 {
     TESTNotDecorated tnd;
-    TESTDecorated td;
+    TESTDecorated td, td_copy;
     size_t len, size;
     void *ptr;
     int ret;
@@ -1029,7 +1047,12 @@ test_decorated(void)
     memset(&td, 0, sizeof(td));
     memset(&tnd, 0, sizeof(tnd));
 
+    my_copy_vers_called = 0;
+    my_free_vers_called = 0;
+
     td.version = 3;
+    td.version3.v = 5;
+    td.privthing = &td;
     if ((td.version2 = malloc(sizeof(*td.version2))) == NULL)
         errx(1, "out of memory");
     *td.version2 = 5;
@@ -1043,6 +1066,7 @@ test_decorated(void)
         warnx("could not decode a TESTDecorated struct as TESTNotDecorated");
         return 1;
     }
+    free(ptr);
     if (size != len) {
         warnx("TESTDecorated encoded size mismatch");
         return 1;
@@ -1051,9 +1075,122 @@ test_decorated(void)
         warnx("TESTDecorated did not decode as a TESTNotDecorated correctly");
         return 1;
     }
+    if (copy_TESTDecorated(&td, &td_copy)) {
+        warnx("copy_TESTDecorated() failed");
+        return 1;
+    }
+    if (td.version != td_copy.version) {
+        warnx("copy_TESTDecorated() did not work correctly (1)");
+        return 1;
+    }
+    if (td_copy.version2 == NULL || *td.version2 != *td_copy.version2) {
+        warnx("copy_TESTDecorated() did not work correctly (2)");
+        return 1;
+    }
+    if (td.version3.v != td_copy.version3.v ||
+        my_copy_vers_called != 1) {
+        warnx("copy_TESTDecorated() did not work correctly (3)");
+        return 1;
+    }
+    if (td_copy.privthing != 0) {
+        warnx("copy_TESTDecorated() did not work correctly (4)");
+        return 1;
+    }
+
+    free_TESTDecorated(&td_copy);
     free_TESTDecorated(&td);
     if (td.version2) {
-        warnx("free_TESTDecorated() did not work correctly");
+        warnx("free_TESTDecorated() did not work correctly (1)");
+        return 1;
+    }
+    if (td.version3.v != 0 || my_free_vers_called != 2) {
+        warnx("free_TESTDecorated() did not work correctly (2)");
+        return 1;
+    }
+    if (td.privthing != 0) {
+        warnx("free_TESTDecorated() did not work correctly (3)");
+        return 1;
+    }
+    return 0;
+}
+
+static int
+test_decorated_choice(void)
+{
+    TESTNotDecoratedChoice tndc;
+    TESTDecoratedChoice tdc, tdc_copy;
+    size_t len, size;
+    void *ptr;
+    int ret;
+
+    memset(&tdc, 0, sizeof(tdc));
+    memset(&tndc, 0, sizeof(tndc));
+
+    my_copy_vers_called = 0;
+    my_free_vers_called = 0;
+
+    tdc.element = choice_TESTDecoratedChoice_version;
+    tdc.u.version = 3;
+    tdc.version3.v = 5;
+    tdc.privthing = &tdc;
+    if ((tdc.version2 = malloc(sizeof(*tdc.version2))) == NULL)
+        errx(1, "out of memory");
+    *tdc.version2 = 5;
+    ASN1_MALLOC_ENCODE(TESTDecoratedChoice, ptr, len, &tdc, &size, ret);
+    if (ret) {
+        warnx("could not encode a TESTDecoratedChoice struct");
+        return 1;
+    }
+    ret = decode_TESTNotDecoratedChoice(ptr, len, &tndc, &size);
+    if (ret) {
+        warnx("could not decode a TESTDecoratedChoice struct as TESTNotDecoratedChoice");
+        return 1;
+    }
+    free(ptr);
+    if (size != len) {
+        warnx("TESTDecoratedChoice encoded size mismatch");
+        return 1;
+    }
+    if ((int)tdc.element != (int)tndc.element ||
+        tdc.u.version != tndc.u.version) {
+        warnx("TESTDecoratedChoice did not decode as a TESTNotDecoratedChoice correctly");
+        return 1;
+    }
+    if (copy_TESTDecoratedChoice(&tdc, &tdc_copy)) {
+        warnx("copy_TESTDecoratedChoice() failed");
+        return 1;
+    }
+    if ((int)tdc.element != (int)tdc_copy.element ||
+        tdc.u.version != tdc_copy.u.version) {
+        warnx("copy_TESTDecoratedChoice() did not work correctly (1)");
+        return 1;
+    }
+    if (tdc_copy.version2 == NULL || *tdc.version2 != *tdc_copy.version2) {
+        warnx("copy_TESTDecoratedChoice() did not work correctly (2)");
+        return 1;
+    }
+    if (tdc.version3.v != tdc_copy.version3.v ||
+        my_copy_vers_called != 1) {
+        warnx("copy_TESTDecoratedChoice() did not work correctly (3)");
+        return 1;
+    }
+    if (tdc_copy.privthing != 0) {
+        warnx("copy_TESTDecoratedChoice() did not work correctly (4)");
+        return 1;
+    }
+
+    free_TESTDecoratedChoice(&tdc_copy);
+    free_TESTDecoratedChoice(&tdc);
+    if (tdc.version2) {
+        warnx("free_TESTDecoratedChoice() did not work correctly (1)");
+        return 1;
+    }
+    if (tdc.version3.v != 0 || my_free_vers_called != 2) {
+        warnx("free_TESTDecoratedChoice() did not work correctly (2)");
+        return 1;
+    }
+    if (tdc.privthing != 0) {
+        warnx("free_TESTDecoratedChoice() did not work correctly (3)");
         return 1;
     }
     return 0;
@@ -1521,7 +1658,7 @@ static int
 check_seq(void)
 {
     TESTSeqOf seq;
-    TESTInteger i;
+    TESTInteger i = 0;
     int ret;
 
     seq.val = NULL;
@@ -2537,6 +2674,7 @@ main(int argc, char **argv)
 
     DO_ONE(test_default);
 
+    DO_ONE(test_decorated_choice);
     DO_ONE(test_decorated);
 
 #if ASN1_IOS_SUPPORTED
diff --git a/third_party/heimdal/lib/asn1/check-gen.h b/third_party/heimdal/lib/asn1/check-gen.h
new file mode 100644 (file)
index 0000000..df8c474
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef _CHECK_GEN_H
+#define _CHECK_GEN_H
+typedef struct my_vers_s {
+    int v;
+} my_vers;
+
+int my_copy_vers(const my_vers *, my_vers *);
+void my_free_vers(my_vers *);
+#endif /* _CHECK_GEN_H */
index 21132c8d1a4d3d38f1046d8c2c5214b0410f1fba..ef5bd6990ded999e56816891cf34d487ab461a1a 100644 (file)
 #include "check-common.h"
 #include "der_locl.h"
 
+int
+my_copy_vers(const my_vers *from, my_vers *to)
+{
+    *to = *from;
+    return 0;
+}
+
+void
+my_free_vers(my_vers *v)
+{
+    v->v = -1;
+}
+
 static int
 cmp_dummy (void *a, void *b)
 {
index 854131e2ab478701db8fe92f730735d3d8c62055..2084cef5f088142e9fe6e3644fa2bc58ce15acfc 100644 (file)
@@ -99,11 +99,14 @@ int ASN1CALL
 der_copy_printable_string (const heim_printable_string *from,
                       heim_printable_string *to)
 {
-    to->length = from->length;
-    to->data   = malloc(to->length + 1);
-    if(to->data == NULL)
+    assert(from->length == 0 || (from->length > 0 && from->data != NULL));
+    to->data = malloc(from->length + 1);
+    if (to->data == NULL) {
+       to->length = 0;
        return ENOMEM;
-    if (from->data != NULL)
+    }
+    to->length = from->length;
+    if (to->length > 0)
        memcpy(to->data, from->data, to->length);
     ((char *)to->data)[to->length] = '\0';
     return 0;
@@ -119,11 +122,17 @@ der_copy_ia5_string (const heim_ia5_string *from,
 int ASN1CALL
 der_copy_bmp_string (const heim_bmp_string *from, heim_bmp_string *to)
 {
-    to->length = from->length;
-    to->data   = malloc(to->length * sizeof(to->data[0]));
-    if(to->length != 0 && to->data == NULL)
+    assert(from->length == 0 || (from->length > 0 && from->data != NULL));
+    if (from->length == 0)
+       to->data = calloc(1, sizeof(from->data[0]));
+    else
+       to->data = malloc(from->length * sizeof(from->data[0]));
+    if (to->data == NULL) {
+       to->length = 0;
        return ENOMEM;
-    if (to->data != NULL && from->data != NULL)
+    }
+    to->length = from->length;
+    if (to->length > 0)
        memcpy(to->data, from->data, to->length * sizeof(to->data[0]));
     return 0;
 }
@@ -132,11 +141,17 @@ int ASN1CALL
 der_copy_universal_string (const heim_universal_string *from,
                           heim_universal_string *to)
 {
-    to->length = from->length;
-    to->data   = malloc(to->length * sizeof(to->data[0]));
-    if(to->length != 0 && to->data == NULL)
+    assert(from->length == 0 || (from->length > 0 && from->data != NULL));
+    if (from->length == 0)
+       to->data = calloc(1, sizeof(from->data[0]));
+    else
+       to->data = malloc(from->length * sizeof(from->data[0]));
+    if (to->data == NULL) {
+       to->length = 0;
        return ENOMEM;
-    if (to->data != NULL && from->data != NULL)
+    }
+    to->length = from->length;
+    if (to->length > 0)
        memcpy(to->data, from->data, to->length * sizeof(to->data[0]));
     return 0;
 }
@@ -151,11 +166,17 @@ der_copy_visible_string (const heim_visible_string *from,
 int ASN1CALL
 der_copy_octet_string (const heim_octet_string *from, heim_octet_string *to)
 {
-    to->length = from->length;
-    to->data   = malloc(to->length);
-    if(to->length != 0 && to->data == NULL)
+    assert(from->length == 0 || (from->length > 0 && from->data != NULL));
+    if (from->length == 0)
+       to->data = calloc(1, 1);
+    else
+       to->data = malloc(from->length);
+    if (to->data == NULL) {
+       to->length = 0;
        return ENOMEM;
-    if (to->data != NULL && from->data != NULL)
+    }
+    to->length = from->length;
+    if (to->length > 0)
        memcpy(to->data, from->data, to->length);
     return 0;
 }
@@ -163,11 +184,17 @@ der_copy_octet_string (const heim_octet_string *from, heim_octet_string *to)
 int ASN1CALL
 der_copy_heim_integer (const heim_integer *from, heim_integer *to)
 {
-    to->length = from->length;
-    to->data   = malloc(to->length);
-    if(to->length != 0 && to->data == NULL)
+    assert(from->length == 0 || (from->length > 0 && from->data != NULL));
+    if (from->length == 0)
+       to->data = calloc(1, 1);
+    else
+       to->data = malloc(from->length);
+    if (to->data == NULL) {
+       to->length = 0;
        return ENOMEM;
-    if (to->data != NULL && from->data != NULL)
+    }
+    to->length = from->length;
+    if (to->length > 0)
        memcpy(to->data, from->data, to->length);
     to->negative = from->negative;
     return 0;
@@ -176,13 +203,22 @@ der_copy_heim_integer (const heim_integer *from, heim_integer *to)
 int ASN1CALL
 der_copy_oid (const heim_oid *from, heim_oid *to)
 {
-    to->length     = from->length;
-    to->components = malloc(to->length * sizeof(*to->components));
-    if (to->length != 0 && to->components == NULL)
+    if (from->length == 0) {
+       to->length = 0;
+       to->components = calloc(1, sizeof(*from->components));
+       if (to->components == NULL)
+           return ENOMEM;
+       return 0;
+    }
+    assert(from->components != NULL);
+    to->components = malloc(from->length * sizeof(*from->components));
+    if (to->components == NULL) {
+       to->length = 0;
        return ENOMEM;
-    if (to->components != NULL && from->components != NULL)
-       memcpy(to->components, from->components,
-              to->length * sizeof(*to->components));
+    }
+    to->length = from->length;
+    memcpy(to->components, from->components,
+          to->length * sizeof(*to->components));
     return 0;
 }
 
@@ -191,12 +227,19 @@ der_copy_bit_string (const heim_bit_string *from, heim_bit_string *to)
 {
     size_t len;
 
+    assert(from->length == 0 || (from->length > 0 && from->data != NULL));
+
     len = (from->length + 7) / 8;
-    to->length = from->length;
-    to->data   = malloc(len);
-    if(len != 0 && to->data == NULL)
+    if (len == 0)
+       to->data = calloc(1, 1);
+    else
+       to->data = malloc(len);
+    if (to->data == NULL) {
+       to->length = 0;
        return ENOMEM;
-    if (to->data != NULL && from->data != NULL)
+    }
+    to->length = from->length;
+    if (len > 0)
        memcpy(to->data, from->data, len);
     return 0;
 }
index 55ba626235953976e3d00e65917560848847fec5..c12f817002518aeb0444aecf869ef791e0f5a3be 100644 (file)
@@ -174,6 +174,11 @@ der_get_general_string (const unsigned char *p, size_t len,
     const unsigned char *p1;
     char *s;
 
+    assert(p != NULL);
+
+    if (size)
+       *size = 0;
+
     p1 = memchr(p, 0, len);
     if (p1 != NULL) {
        /*
@@ -217,6 +222,11 @@ int ASN1CALL
 der_get_printable_string(const unsigned char *p, size_t len,
                         heim_printable_string *str, size_t *size)
 {
+    assert(p != NULL);
+
+    if (size)
+       *size = 0;
+
     if (len == SIZE_MAX) {
        gen_data_zero(str);
        return ASN1_BAD_LENGTH;
@@ -227,6 +237,7 @@ der_get_printable_string(const unsigned char *p, size_t len,
        gen_data_zero(str);
        return ENOMEM;
     }
+
     memcpy(str->data, p, len);
     ((char *)str->data)[len] = '\0';
     if(size) *size = len;
@@ -246,6 +257,11 @@ der_get_bmp_string (const unsigned char *p, size_t len,
 {
     size_t i;
 
+    assert(p != NULL);
+
+    if (size)
+       *size = 0;
+
     if (len & 1) {
        gen_data_zero(data);
        return ASN1_BAD_FORMAT;
@@ -282,6 +298,11 @@ der_get_universal_string (const unsigned char *p, size_t len,
 {
     size_t i;
 
+    assert(p != NULL);
+
+    if (size)
+       *size = 0;
+
     if (len & 3) {
        gen_data_zero(data);
        return ASN1_BAD_FORMAT;
@@ -322,13 +343,23 @@ int ASN1CALL
 der_get_octet_string (const unsigned char *p, size_t len,
                      heim_octet_string *data, size_t *size)
 {
-    data->length = len;
-    data->data = malloc(len);
-    if (data->data == NULL && data->length != 0)
+    assert(p != NULL);
+
+    if (size)
+       *size = 0;
+
+    if (len == 0)
+       data->data = malloc(1);
+    else
+       data->data = malloc(len);
+    if (data->data == NULL) {
+       data->length = 0;
        return ENOMEM;
-    if (data->data != NULL)
-       memcpy (data->data, p, len);
-    if(size) *size = len;
+    }
+    data->length = len;
+    memcpy (data->data, p, len);
+    if (size)
+       *size = len;
     return 0;
 }
 
@@ -342,6 +373,11 @@ der_get_octet_string_ber (const unsigned char *p, size_t len,
     unsigned int tag, depth = 0;
     size_t l, datalen, oldlen = len;
 
+    assert(p != NULL);
+
+    if (size)
+       *size = 0;
+
     data->length = 0;
     data->data = NULL;
 
@@ -409,11 +445,14 @@ der_get_heim_integer (const unsigned char *p, size_t len,
     data->negative = 0;
     data->data = NULL;
 
-    if (len == 0) {
-       if (size)
-           *size = 0;
+    if (size)
+       *size = 0;
+
+    if (len == 0)
        return 0;
-    }
+
+    assert(p != NULL);
+
     if (p[0] & 0x80) {
        unsigned char *q;
        int carry = 1;
@@ -494,6 +533,11 @@ der_get_time (const unsigned char *p, size_t len,
     char *times;
     int e;
 
+    assert(p != NULL);
+
+    if (size)
+       *size = 0;
+
     if (len == SIZE_MAX || len == 0)
        return ASN1_BAD_LENGTH;
 
@@ -529,6 +573,11 @@ der_get_oid (const unsigned char *p, size_t len,
     size_t n;
     size_t oldlen = len;
 
+    assert(p != NULL);
+
+    if (size)
+       *size = 0;
+
     if (len < 1)
        return ASN1_OVERRUN;
 
@@ -539,8 +588,10 @@ der_get_oid (const unsigned char *p, size_t len,
        return ERANGE;
 
     data->components = malloc((len + 1) * sizeof(data->components[0]));
-    if (data->components == NULL)
+    if (data->components == NULL) {
+       data->length = 0;
        return ENOMEM;
+    }
     data->components[0] = (*p) / 40;
     data->components[1] = (*p) % 40;
     --len;
@@ -576,8 +627,15 @@ der_get_tag (const unsigned char *p, size_t len,
             unsigned int *tag, size_t *size)
 {
     size_t ret = 0;
+
+    if (size)
+       *size = 0;
+
     if (len < 1)
        return ASN1_MISSING_FIELD;
+
+    assert(p != NULL);
+
     *cls = (Der_class)(((*p) >> 6) & 0x03);
     *type = (Der_type)(((*p) >> 5) & 0x01);
     *tag = (*p) & 0x1f;
@@ -626,6 +684,9 @@ der_match_tag2 (const unsigned char *p, size_t len,
     unsigned int thistag;
     int e;
 
+    if (size)
+       *size = 0;
+
     e = der_get_tag(p, len, &thisclass, type, &thistag, &l);
     if (e) return e;
     /*
@@ -701,6 +762,11 @@ int ASN1CALL
 der_get_bit_string (const unsigned char *p, size_t len,
                    heim_bit_string *data, size_t *size)
 {
+    assert(p != NULL);
+
+    if (size)
+       *size = 0;
+
     if (len < 1)
        return ASN1_OVERRUN;
     if (p[0] > 7)
@@ -717,8 +783,10 @@ der_get_bit_string (const unsigned char *p, size_t len,
     if (len - 1 > 0) {
        data->length = (len - 1) * 8;
        data->data = malloc(len - 1);
-       if (data->data == NULL)
+       if (data->data == NULL) {
+           data->length = 0;
            return ENOMEM;
+       }
        memcpy (data->data, p + 1, len - 1);
        data->length -= p[0];
     } else {
index 5f40fba161528164cab2557dd88c0d81816c8e75..8fbd6f3da1c0838b7802351206222b417ac4af9c 100644 (file)
@@ -49,6 +49,8 @@ der_put_unsigned (unsigned char *p, size_t len, const unsigned *v, size_t *size)
     unsigned char *base = p;
     unsigned val = *v;
 
+    *size = 0;
+
     if (val) {
        while (len > 0 && val) {
            *p-- = val % 256;
@@ -81,6 +83,8 @@ der_put_unsigned64 (unsigned char *p, size_t len, const uint64_t *v, size_t *siz
     unsigned char *base = p;
     uint64_t val = *v;
 
+    *size = 0;
+
     if (val) {
        while (len > 0 && val) {
            *p-- = val % 256;
@@ -113,6 +117,8 @@ der_put_integer (unsigned char *p, size_t len, const int *v, size_t *size)
     unsigned char *base = p;
     int val = *v;
 
+    *size = 0;
+
     if(val >= 0) {
        do {
            if(len < 1)
@@ -153,6 +159,8 @@ der_put_integer64 (unsigned char *p, size_t len, const int64_t *v, size_t *size)
     unsigned char *base = p;
     int64_t val = *v;
 
+    *size = 0;
+
     if(val >= 0) {
        do {
            if(len < 1)
@@ -191,12 +199,16 @@ der_put_integer64 (unsigned char *p, size_t len, const int64_t *v, size_t *size)
 int ASN1CALL
 der_put_length (unsigned char *p, size_t len, size_t val, size_t *size)
 {
+    if (size)
+       *size = 0;
+
     if (len < 1)
        return ASN1_OVERFLOW;
 
     if (val < 128) {
        *p = val;
-       *size = 1;
+       if (size)
+           *size = 1;
     } else {
        size_t l = 0;
 
@@ -218,6 +230,8 @@ der_put_length (unsigned char *p, size_t len, size_t val, size_t *size)
 int ASN1CALL
 der_put_boolean(unsigned char *p, size_t len, const int *data, size_t *size)
 {
+    *size = 0;
+
     if(len < 1)
        return ASN1_OVERFLOW;
     if(*data != 0)
@@ -232,13 +246,15 @@ int ASN1CALL
 der_put_general_string (unsigned char *p, size_t len,
                        const heim_general_string *str, size_t *size)
 {
-    size_t slen = strlen(*str);
+    size_t slen;
 
+    assert(p != NULL && str != NULL && *str != NULL && size != NULL);
+    *size = 0;
+    slen = strlen(*str);
     if (len < slen)
        return ASN1_OVERFLOW;
     p -= slen;
-    if (*str != NULL)
-       memcpy (p+1, *str, slen);
+    memcpy (p+1, *str, slen);
     *size = slen;
     return 0;
 }
@@ -269,6 +285,12 @@ der_put_bmp_string (unsigned char *p, size_t len,
                    const heim_bmp_string *data, size_t *size)
 {
     size_t i;
+
+    assert(p != NULL && data != NULL);
+
+    if (size)
+       *size = 0;
+
     if (len / 2 < data->length)
        return ASN1_OVERFLOW;
     p -= data->length * 2;
@@ -286,6 +308,10 @@ der_put_universal_string (unsigned char *p, size_t len,
                          const heim_universal_string *data, size_t *size)
 {
     size_t i;
+
+    if (size)
+       *size = 0;
+
     if (len / 4 < data->length)
        return ASN1_OVERFLOW;
     p -= data->length * 4;
@@ -311,11 +337,13 @@ int ASN1CALL
 der_put_octet_string (unsigned char *p, size_t len,
                      const heim_octet_string *data, size_t *size)
 {
+    assert(p != NULL && data != NULL && size != NULL);
+
+    *size = 0;
     if (len < data->length)
        return ASN1_OVERFLOW;
     p -= data->length;
-    if (data->data)
-       memcpy (p+1, data->data, data->length);
+    memcpy (p+1, data->data, data->length);
     *size = data->length;
     return 0;
 }
@@ -324,9 +352,14 @@ int ASN1CALL
 der_put_heim_integer (unsigned char *p, size_t len,
                     const heim_integer *data, size_t *size)
 {
-    unsigned char *buf = data->data;
+    unsigned char *buf;
     int hibitset = 0;
 
+    assert(p != NULL);
+
+    if (size)
+       *size = 0;
+
     if (data->length == 0) {
        if (len < 1)
            return ASN1_OVERFLOW;
@@ -338,6 +371,8 @@ der_put_heim_integer (unsigned char *p, size_t len,
     if (len < data->length)
        return ASN1_OVERFLOW;
 
+    assert(data->data != NULL);
+    buf = data->data;
     len -= data->length;
 
     if (data->negative) {
@@ -461,6 +496,8 @@ der_replace_tag(const unsigned char *p, size_t len,
     size_t payload_len, l, tag_len, len_len;
     int e;
 
+    assert(p != NULL && out != NULL && outlen != NULL);
+
     e = der_get_tag(p, len, &found_class, &found_type, &found_tag, &l);
     if (e)
         return e;
@@ -506,6 +543,8 @@ der_encode_implicit(unsigned char *p, size_t len,
     unsigned char *p2;
     int e;
 
+    assert(p != NULL && size != NULL);
+
     /* Attempt to encode in place */
     e = encoder(p, len, obj, size);
     if (e == 0) {
@@ -630,13 +669,17 @@ int ASN1CALL
 der_put_bit_string (unsigned char *p, size_t len,
                    const heim_bit_string *data, size_t *size)
 {
-    size_t data_size = (data->length + 7) / 8;
+    size_t data_size;
+
+    assert(p != NULL && data != NULL && size != NULL);
+
+    *size = 0;
+    data_size = (data->length + 7) / 8;
     if (len < data_size + 1)
        return ASN1_OVERFLOW;
     p -= data_size + 1;
 
-    if (data->data != NULL)
-       memcpy (p+2, data->data, data_size);
+    memcpy (p+2, data->data, data_size);
     if (data->length && (data->length % 8) != 0)
        p[1] = 8 - (data->length % 8);
     else
@@ -648,9 +691,12 @@ der_put_bit_string (unsigned char *p, size_t len,
 int
 _heim_der_set_sort(const void *a1, const void *a2)
 {
-    const heim_octet_string *s1 = a1, *s2 = a2;
+    const heim_octet_string *s1, *s2;
     int ret;
 
+    assert(a1 != NULL && a2 != NULL);
+    s1 = a1;
+    s2 = a2;
     ret = memcmp(s1->data, s2->data,
                 s1->length < s2->length ? s1->length : s2->length);
     if (ret != 0)
index 5a494d23acaf92b94bb75c8295e0255953d13368..253ac5aca6f38b86f41efdc93e87792e712d155e 100644 (file)
@@ -105,7 +105,7 @@ print_heim_any(const heim_any *data, int flags)
     free(s);
     s = NULL;
     if (r > -1)
-        r = asprintf(&s, "\"%s\"", s2);
+        (void) asprintf(&s, "\"%s\"", s2);
     free(s2);
     return s;
 }
@@ -155,7 +155,7 @@ print_HEIM_ANY(const heim_any *data, int flags)
     free(s);
     s = NULL;
     if (r > -1)
-        r = asprintf(&s, "\"%s\"", s2);
+        (void) asprintf(&s, "\"%s\"", s2);
     free(s2);
     return s;
 }
@@ -205,7 +205,7 @@ print_heim_any_set(const heim_any_set *data, int flags)
     free(s);
     s = NULL;
     if (r > -1)
-        r = asprintf(&s, "\"%s\"", s2);
+        (void) asprintf(&s, "\"%s\"", s2);
     free(s2);
     return s;
 }
@@ -261,7 +261,7 @@ print_HEIM_ANY_SET(const heim_any_set *data, int flags)
     free(s);
     s = NULL;
     if (r > -1)
-        r = asprintf(&s, "\"%s\"", s2);
+        (void) asprintf(&s, "\"%s\"", s2);
     free(s2);
     return s;
 }
index 8e323188fff9919aa18903ec1a3785688544037b..10153c60379ea09a9036c69f17f1ee345ab9b61f 100644 (file)
@@ -159,7 +159,7 @@ init_generate (const char *filename, const char *base)
     /* public header file */
     if (asprintf(&header, "%s.h", headerbase) < 0 || header == NULL)
        errx(1, "malloc");
-    if (asprintf(&fn, "%s.hx", headerbase) < 0 || fn == NULL)
+    if (asprintf(&fn, "%s.h", headerbase) < 0 || fn == NULL)
        errx(1, "malloc");
     headerfile = fopen (fn, "w");
     if (headerfile == NULL)
@@ -170,7 +170,7 @@ init_generate (const char *filename, const char *base)
     /* private header file */
     if (asprintf(&privheader, "%s-priv.h", headerbase) < 0 || privheader == NULL)
        errx(1, "malloc");
-    if (asprintf(&fn, "%s-priv.hx", headerbase) < 0 || fn == NULL)
+    if (asprintf(&fn, "%s-priv.h", headerbase) < 0 || fn == NULL)
        errx(1, "malloc");
     privheaderfile = fopen (fn, "w");
     if (privheaderfile == NULL)
@@ -179,7 +179,7 @@ init_generate (const char *filename, const char *base)
     fn = NULL;
 
     /* template file */
-    if (asprintf(&template, "%s-template.x", headerbase) < 0 || template == NULL)
+    if (asprintf(&template, "%s-template.c", headerbase) < 0 || template == NULL)
        errx(1, "malloc");
     fprintf (headerfile,
             "/* Generated from %s */\n"
@@ -258,7 +258,7 @@ init_generate (const char *filename, const char *base)
     fputs("#define ASN1_MALLOC_ENCODE(T, B, BL, S, L, R)                  \\\n"
          "  do {                                                         \\\n"
          "    (BL) = length_##T((S));                                    \\\n"
-         "    (B) = malloc((BL));                                        \\\n"
+         "    (B) = calloc(1, (BL));                                     \\\n"
          "    if((B) == NULL) {                                          \\\n"
          "      *(L) = 0;                                                \\\n"
          "      (R) = ENOMEM;                                            \\\n"
@@ -300,12 +300,12 @@ init_generate (const char *filename, const char *base)
     free(fn);
     fn = NULL;
 
-    if (asprintf(&fn, "%s_oids.x", base) < 0 || fn == NULL)
+    if (asprintf(&fn, "%s_oids.c", base) < 0 || fn == NULL)
        errx(1, "malloc");
     oidsfile = fopen(fn, "w");
     if (oidsfile == NULL)
        err (1, "open %s", fn);
-    if (asprintf(&fn, "%s_syms.x", base) < 0 || fn == NULL)
+    if (asprintf(&fn, "%s_syms.c", base) < 0 || fn == NULL)
        errx(1, "malloc");
     symsfile = fopen(fn, "w");
     if (symsfile == NULL)
@@ -356,11 +356,19 @@ close_generate (void)
         err(1, "writes to private header file failed");
     if (templatefile && fclose(templatefile) == EOF)
         err(1, "writes to template file failed");
-    if (logfile) {
-        fprintf(logfile, "\n");
-        if (fclose(logfile) == EOF)
-            err(1, "writes to log file failed");
-    }
+    if (!jsonfile) abort();
+    if (fclose(jsonfile) == EOF)
+        err(1, "writes to JSON file failed");
+    if (!oidsfile) abort();
+    if (fclose(oidsfile) == EOF)
+        err(1, "writes to OIDs file failed");
+    if (!symsfile) abort();
+    if (fclose(symsfile) == EOF)
+        err(1, "writes to symbols file failed");
+    if (!logfile) abort();
+    fprintf(logfile, "\n");
+    if (fclose(logfile) == EOF)
+        err(1, "writes to log file failed");
 }
 
 void
@@ -415,7 +423,7 @@ generate_header_of_codefile(const char *name)
     if (codefile != NULL)
        abort();
 
-    if (asprintf (&filename, "%s_%s.x", STEM, name) < 0 || filename == NULL)
+    if (asprintf (&filename, "%s_%s.c", STEM, name) < 0 || filename == NULL)
        errx(1, "malloc");
     codefile = fopen (filename, "w");
     if (codefile == NULL)
@@ -427,7 +435,9 @@ generate_header_of_codefile(const char *name)
     fprintf (codefile,
             "/* Generated from %s */\n"
             "/* Do not edit */\n\n"
-            "#define  ASN1_LIB\n\n"
+            "#if defined(_WIN32) && !defined(ASN1_LIB)\n"
+            "# error \"ASN1_LIB must be defined\"\n"
+            "#endif\n"
             "#include <stdio.h>\n"
             "#include <stdlib.h>\n"
             "#include <time.h>\n"
@@ -757,8 +767,10 @@ define_asn1 (int level, Type *t)
             fprintf(headerfile, "%s.&%s",
                     t->typeref.iosclass->symbol->name,
                     t->typeref.field->name);
-        } else
+        } else if (t->symbol)
             fprintf(headerfile, "%s", t->symbol->name);
+        else
+            abort();
        break;
     case TInteger:
        if(t->members == NULL) {
@@ -772,8 +784,8 @@ define_asn1 (int level, Type *t)
             fprintf (headerfile, "INTEGER {\n");
            HEIM_TAILQ_FOREACH(m, t->members, members) {
                 space (level + 1);
-               fprintf(headerfile, "%s(%d)%s\n", m->gen_name, m->val,
-                       last_member_p(m));
+               fprintf(headerfile, "%s(%lld)%s\n", m->gen_name,
+                        (long long)m->val, last_member_p(m));
             }
            space(level);
             fprintf (headerfile, "}");
@@ -796,8 +808,8 @@ define_asn1 (int level, Type *t)
            fprintf (headerfile, "ENUMERATED {\n");
        HEIM_TAILQ_FOREACH(m, t->members, members) {
            space(level + 1);
-           fprintf (headerfile, "%s(%d)%s\n", m->name, m->val,
-                    last_member_p(m));
+           fprintf(headerfile, "%s(%lld)%s\n", m->name,
+                    (long long)m->val, last_member_p(m));
        }
        space(level);
        fprintf (headerfile, "}");
@@ -1022,6 +1034,10 @@ get_open_type_defn_fields(const Type *t,
             subtype->constraint->u.content.type->constraint &&
             subtype->constraint->u.content.type->constraint->ctype == CT_TABLE_CONSTRAINT) {
             /* Type like OCTET STRING or BIT STRING CONTAINING open type */
+            if (*opentypemember)
+                errx(1, "Multiple open type members %s and %s for the same "
+                     "field %s?", (*opentypemember)->name, m->name,
+                     (*opentypefield)->name);
             *opentypemember = m;
             *opentypefield = subtype->constraint->u.content.type->typeref.field;
             *is_array_of = sOfType != NULL;
@@ -1029,6 +1045,10 @@ get_open_type_defn_fields(const Type *t,
             break;
         } else if (subtype->symbol && strcmp(subtype->symbol->name, "HEIM_ANY") == 0) {
             /* Open type, but NOT embedded in OCTET STRING or BIT STRING */
+            if (*opentypemember)
+                errx(1, "Multiple open type members %s and %s for the same "
+                     "field %s?", (*opentypemember)->name, m->name,
+                     (*opentypefield)->name);
             *opentypemember = m;
             *opentypefield = subtype->typeref.field;
             *is_array_of = sOfType != NULL;
@@ -1036,6 +1056,10 @@ get_open_type_defn_fields(const Type *t,
             break;
         }
     }
+
+    if (!idmembername)
+        errx(1, "Missing open type id member in %s",
+             t->symbol ? t->symbol->name : "<unknown type>");
     /* Look for the type ID member identified in the previous loop */
     HEIM_TAILQ_FOREACH(m, t->members, members) {
         if (!m->type->subtype || strcmp(m->name, idmembername) != 0)
@@ -1169,11 +1193,12 @@ define_type(int level, const char *name, const char *basename, Type *pt, Type *t
             define_open_type(level, newbasename, name, basename, t, t);
         } else if (!t->symbol && pt->actual_parameter) {
             define_open_type(level, newbasename, name, basename, pt, t);
-        } else {
+        } else if (t->symbol) {
             fprintf(headerfile, "%s %s;\n", t->symbol->gen_name, name);
             fprintf(jsonfile, "\"ttype\":\"%s\","
                     "\"alias\":true\n", t->symbol->gen_name);
-        }
+        } else
+            abort();
        break;
     case TInteger:
         if (t->symbol && t->symbol->emitted_definition)
@@ -1190,12 +1215,12 @@ define_type(int level, const char *name, const char *basename, Type *pt, Type *t
                     "\"members\":[\n");
            HEIM_TAILQ_FOREACH(m, t->members, members) {
                 space (level + 1);
-                fprintf(headerfile, "%s%s%s = %d%s\n",
+                fprintf(headerfile, "%s%s%s = %lld%s\n",
                         label_prefix, label_prefix_sep,
-                        m->gen_name, m->val, last_member_p(m));
-                fprintf(jsonfile, "{\"%s%s%s\":%d}%s\n",
+                        m->gen_name, (long long)m->val, last_member_p(m));
+                fprintf(jsonfile, "{\"%s%s%s\":%lld}%s\n",
                         label_prefix, label_prefix_sep,
-                        m->gen_name, m->val, last_member_p(m));
+                        m->gen_name, (long long)m->val, last_member_p(m));
             }
             fprintf(headerfile, "} %s;\n", name);
             fprintf(jsonfile, "]");
@@ -1268,7 +1293,7 @@ define_type(int level, const char *name, const char *basename, Type *pt, Type *t
            fprintf (headerfile, "heim_bit_string %s;\n", name);
             fprintf(jsonfile, "\"ctype\":\"heim_bit_string\"");
         } else {
-           int pos = 0;
+           int64_t pos = 0;
            getnewbasename(&newbasename, typedefp || level == 0, basename, name);
 
            fprintf (headerfile, "struct %s {\n", newbasename);
@@ -1281,7 +1306,8 @@ define_type(int level, const char *name, const char *basename, Type *pt, Type *t
                  * forces the compiler to give us an obvious layout)
                  */
                while (pos < m->val) {
-                   if (asprintf (&n, "_unused%d:1", pos) < 0 || n == NULL)
+                   if (asprintf (&n, "_unused%lld:1", (long long)pos) < 0 ||
+                        n == NULL)
                        err(1, "malloc");
                    define_type(level + 1, n, newbasename, NULL, &i, FALSE, FALSE);
                     fprintf(jsonfile, ",");
@@ -1308,7 +1334,8 @@ define_type(int level, const char *name, const char *basename, Type *pt, Type *t
                 fprintf(jsonfile, ",");
            while (pos < bitset_size) {
                char *n = NULL;
-               if (asprintf (&n, "_unused%d:1", pos) < 0 || n == NULL)
+               if (asprintf (&n, "_unused%lld:1", (long long)pos) < 0 ||
+                    n == NULL)
                    errx(1, "malloc");
                define_type(level + 1, n, newbasename, NULL, &i, FALSE, FALSE);
                 fprintf(jsonfile, "%s", (pos + 1) < bitset_size ? "," : "");
@@ -1339,12 +1366,12 @@ define_type(int level, const char *name, const char *basename, Type *pt, Type *t
            if (m->ellipsis) {
                fprintf (headerfile, "/* ... */\n");
             } else {
-               fprintf(headerfile, "%s%s%s = %d%s\n",
+               fprintf(headerfile, "%s%s%s = %lld%s\n",
                         label_prefix, label_prefix_sep,
-                        m->gen_name, m->val, last_member_p(m));
-                fprintf(jsonfile, "{\"%s%s%s\":%d%s}\n",
+                        m->gen_name, (long long)m->val, last_member_p(m));
+                fprintf(jsonfile, "{\"%s%s%s\":%lld%s}\n",
                         label_prefix, label_prefix_sep,
-                        m->gen_name, m->val, last_member_p(m));
+                        m->gen_name, (long long)m->val, last_member_p(m));
             }
        }
        space(level);
@@ -1355,12 +1382,14 @@ define_type(int level, const char *name, const char *basename, Type *pt, Type *t
     case TSet:
     case TSequence: {
        Member *m;
-        char *ft, *fn;
-        int deco_opt;
+        struct decoration deco;
+        ssize_t more_deco = -1;
+        int decorated = 0;
 
        getnewbasename(&newbasename, typedefp || level == 0, basename, name);
 
        space(level);
+
        fprintf (headerfile, "struct %s {\n", newbasename);
         fprintf(jsonfile, "\"ttype\":\"%s\",\"extensible\":%s,"
                 "\"ctype\":\"struct %s\"",
@@ -1397,15 +1426,37 @@ define_type(int level, const char *name, const char *basename, Type *pt, Type *t
             fprintf(jsonfile, ",\"opentype\":");
             define_open_type(level, newbasename, name, basename, t, t);
         }
-        if (decorate_type(newbasename, &ft, &fn, &deco_opt)) {
+        while (decorate_type(newbasename, &deco, &more_deco)) {
+            decorated++;
            space(level + 1);
-            fprintf(headerfile, "%s %s%s;\n", ft, deco_opt ? "*" : "", fn);
-            fprintf(jsonfile, ",\"decorate\":{\"type\":\"%s\",\"name\":\"%s\", \"optional\":%s}", ft, fn, deco_opt ? "true" : "false");
-            free(ft);
-            free(fn);
+            fprintf(headerfile, "%s %s%s;\n", deco.field_type,
+                    deco.opt ? "*" : "", deco.field_name);
+            if (deco.first)
+                fprintf(jsonfile, ",\"decorate\":[");
+            fprintf(jsonfile, "%s{"
+                    "\"type\":\"%s\",\"name\":\"%s\",\"optional\":%s,"
+                    "\"external\":%s,\"pointer\":%s,\"void_star\":%s,"
+                    "\"struct_star\":%s,"
+                    "\"copy_function\":\"%s\","
+                    "\"free_function\":\"%s\",\"header_name\":%s%s%s"
+                    "}",
+                    deco.first ? "" : ",",
+                    deco.field_type, deco.field_name,
+                    deco.opt ? "true" : "false", deco.ext ? "true" : "false",
+                    deco.ptr ? "true" : "false", deco.void_star ? "true" : "false",
+                    deco.struct_star ? "true" : "false",
+                    deco.copy_function_name ? deco.copy_function_name : "",
+                    deco.free_function_name ? deco.free_function_name : "",
+                    deco.header_name && deco.header_name[0] == '"' ? "" : "\"",
+                    deco.header_name ? deco.header_name : "",
+                    deco.header_name && deco.header_name[0] == '"' ? "" : "\""
+                    );
         }
+        if (decorated)
+            fprintf(jsonfile, "]");
        space(level);
        fprintf (headerfile, "} %s;\n", name);
+        free(deco.field_type);
        break;
     }
     case TSetOf:
@@ -1454,6 +1505,9 @@ define_type(int level, const char *name, const char *basename, Type *pt, Type *t
         define_type(level, name, basename, t, t->subtype, typedefp, preservep);
        break;
     case TChoice: {
+        struct decoration deco;
+        ssize_t more_deco = -1;
+        int decorated = 0;
        int first = 1;
        Member *m;
 
@@ -1512,9 +1566,39 @@ define_type(int level, const char *name, const char *basename, Type *pt, Type *t
        }
        space(level + 1);
        fprintf (headerfile, "} u;\n");
+        fprintf(jsonfile, "]");
+
+        while (decorate_type(newbasename, &deco, &more_deco)) {
+            decorated++;
+           space(level + 1);
+            fprintf(headerfile, "%s %s%s;\n", deco.field_type,
+                    deco.opt ? "*" : "", deco.field_name);
+            if (deco.first)
+                fprintf(jsonfile, ",\"decorate\":[");
+            fprintf(jsonfile, "%s{"
+                    "\"type\":\"%s\",\"name\":\"%s\",\"optional\":%s,"
+                    "\"external\":%s,\"pointer\":%s,\"void_star\":%s,"
+                    "\"struct_star\":%s,"
+                    "\"copy_function\":\"%s\","
+                    "\"free_function\":\"%s\",\"header_name\":%s%s%s"
+                    "}",
+                    deco.first ? "" : ",",
+                    deco.field_type, deco.field_name,
+                    deco.opt ? "true" : "false", deco.ext ? "true" : "false",
+                    deco.ptr ? "true" : "false", deco.void_star ? "true" : "false",
+                    deco.struct_star ? "true" : "false",
+                    deco.copy_function_name ? deco.copy_function_name : "",
+                    deco.free_function_name ? deco.free_function_name : "",
+                    deco.header_name && deco.header_name[0] == '"' ? "" : "\"",
+                    deco.header_name ? deco.header_name : "",
+                    deco.header_name && deco.header_name[0] == '"' ? "" : "\""
+                    );
+        }
+        if (decorated)
+            fprintf(jsonfile, "]");
+
        space(level);
        fprintf (headerfile, "} %s;\n", name);
-        fprintf(jsonfile, "]");
        break;
     }
     case TUTCTime:
@@ -1617,19 +1701,37 @@ declare_type(const Symbol *s, Type *t, int typedefp)
 
     switch (t->type) {
     case TSet:
-    case TSequence:
+    case TSequence: {
+        struct decoration deco;
+        ssize_t more_deco = -1;
+
        getnewbasename(&newbasename, TRUE, s->gen_name, s->gen_name);
        fprintf(headerfile, "struct %s %s;\n", newbasename, s->gen_name);
+        while (decorate_type(newbasename, &deco, &more_deco)) {
+            if (deco.header_name)
+                fprintf(headerfile, "#include %s\n", deco.header_name);
+            free(deco.field_type);
+        }
        break;
+    }
     case TSetOf:
     case TSequenceOf:
        getnewbasename(&newbasename, TRUE, s->gen_name, s->gen_name);
        fprintf(headerfile, "struct %s %s;\n", newbasename, s->gen_name);
        break;
-    case TChoice:
+    case TChoice: {
+        struct decoration deco;
+        ssize_t more_deco = -1;
+
        getnewbasename(&newbasename, TRUE, s->gen_name, s->gen_name);
        fprintf(headerfile, "struct %s %s;\n", newbasename, s->gen_name);
+        while (decorate_type(newbasename, &deco, &more_deco)) {
+            if (deco.header_name)
+                fprintf(headerfile, "#include %s\n", deco.header_name);
+            free(deco.field_type);
+        }
        break;
+    }
     default:
        abort ();
     }
@@ -1755,6 +1857,7 @@ static void
 generate_type_header (const Symbol *s)
 {
     Type *t = s->type;
+
     if (!s->type)
         return;
 
@@ -1823,6 +1926,7 @@ generate_type_header (const Symbol *s)
     if (is_export(s->name))
         fprintf(symsfile, "ASN1_SYM_TYPE(\"%s\", \"%s\", %s)\n",
                 s->name, s->gen_name, s->gen_name);
+
     fprintf(headerfile, "typedef ");
     define_type(0, s->gen_name, s->gen_name, NULL, s->type, TRUE,
                 preserve_type(s->name) ? TRUE : FALSE);
index 243aa2b0ccae06bb3c691cff61d3fa4476e9a641..bec6f8b059f58785ea42fa2a9f56e795adf44af3 100644 (file)
@@ -62,7 +62,7 @@ copy_type (const char *from, const char *to, const Type *t, int preserve)
            copy_primitive ("heim_integer", from, to);
            break;
        }
-        /* FALLTHROUGH */
+        fallthrough;
     case TBoolean:
     case TEnumerated :
        fprintf(codefile, "*(%s) = *(%s);\n", to, from);
@@ -125,7 +125,7 @@ copy_type (const char *from, const char *to, const Type *t, int preserve)
                errx(1, "malloc");
            if(m->optional){
                fprintf(codefile, "if(%s) {\n", fs);
-               fprintf(codefile, "%s = malloc(sizeof(*%s));\n", ts, ts);
+               fprintf(codefile, "%s = calloc(1, sizeof(*%s));\n", ts, ts);
                fprintf(codefile, "if(%s == NULL) goto fail;\n", ts);
                used_fail++;
            }
@@ -161,7 +161,7 @@ copy_type (const char *from, const char *to, const Type *t, int preserve)
        char *f = NULL, *T = NULL;
 
        fprintf (codefile, "if(((%s)->val = "
-                "malloc((%s)->len * sizeof(*(%s)->val))) == NULL && (%s)->len != 0)\n",
+                "calloc(1, (%s)->len * sizeof(*(%s)->val))) == NULL && (%s)->len != 0)\n",
                 to, from, to, from);
        fprintf (codefile, "goto fail;\n");
        used_fail++;
@@ -228,10 +228,10 @@ copy_type (const char *from, const char *to, const Type *t, int preserve)
 void
 generate_type_copy (const Symbol *s)
 {
+  struct decoration deco;
+  ssize_t more_deco = -1;
   int preserve = preserve_type(s->name) ? TRUE : FALSE;
   int save_used_fail = used_fail;
-  int deco_opt;
-  char *ft, *fn;
 
   used_fail = 0;
 
@@ -241,18 +241,39 @@ generate_type_copy (const Symbol *s)
           "memset(to, 0, sizeof(*to));\n",
           s->gen_name, s->gen_name, s->gen_name);
   copy_type ("from", "to", s->type, preserve);
-  if (decorate_type(s->gen_name, &ft, &fn, &deco_opt)) {
-      if (deco_opt) {
-          fprintf(codefile, "if (from->%s) {\n", fn);
-          fprintf(codefile, "(to)->%s = malloc(sizeof(*(to)->%s));\n", fn, fn);
-          fprintf(codefile, "if (copy_%s((from)->%s, (to)->%s)) goto fail;\n", ft, fn, fn);
+  while (decorate_type(s->gen_name, &deco, &more_deco)) {
+      if (deco.ext && deco.copy_function_name == NULL) {
+          /* Decorated with field of external type but no copy function */
+          if (deco.ptr)
+              fprintf(codefile, "(to)->%s = 0;\n", deco.field_name);
+          else
+              fprintf(codefile, "memset(&(to)->%s, 0, sizeof((to)->%s));\n",
+                      deco.field_name, deco.field_name);
+      } else if (deco.ext) {
+          /* Decorated with field of external type w/ copy function */
+          if (deco.ptr) {
+              fprintf(codefile, "if (from->%s) {\n", deco.field_name);
+              fprintf(codefile, "(to)->%s = calloc(1, sizeof(*(to)->%s));\n",
+                      deco.field_name, deco.field_name);
+              fprintf(codefile, "if (%s((from)->%s, (to)->%s)) goto fail;\n",
+                      deco.copy_function_name, deco.field_name, deco.field_name);
+              fprintf(codefile, "}\n");
+          } else {
+              fprintf(codefile, "if (%s(&(from)->%s, &(to)->%s)) goto fail;\n",
+                      deco.copy_function_name, deco.field_name, deco.field_name);
+          }
+      } else if (deco.opt) {
+          /* Decorated with optional field of ASN.1 type */
+          fprintf(codefile, "if (from->%s) {\n", deco.field_name);
+          fprintf(codefile, "(to)->%s = calloc(1, sizeof(*(to)->%s));\n", deco.field_name, deco.field_name);
+          fprintf(codefile, "if (copy_%s((from)->%s, (to)->%s)) goto fail;\n", deco.field_type, deco.field_name, deco.field_name);
           fprintf(codefile, "}\n");
       } else {
-          fprintf(codefile, "if (copy_%s(&(from)->%s, &(to)->%s)) goto fail;\n", ft, fn, fn);
+          /* Decorated with required field of ASN.1 type */
+          fprintf(codefile, "if (copy_%s(&(from)->%s, &(to)->%s)) goto fail;\n", deco.field_type, deco.field_name, deco.field_name);
       }
       used_fail++;
-      free(ft);
-      free(fn);
+      free(deco.field_type);
   }
   fprintf (codefile, "return 0;\n");
 
index 739f9d85f70af8e8940209879ac04a6eaad71930..93d412f633561bde6e45646ac3392fcd3ce8577a 100644 (file)
@@ -328,9 +328,9 @@ decode_type(const char *name, const Type *t, int optional, struct value *defval,
                         "if (len < 1) break;\n");
                pos += 8;
            }
-           fprintf (codefile,
-                    "(%s)->%s = (*p >> %d) & 1;\n",
-                    name, m->gen_name, 7 - m->val % 8);
+           fprintf(codefile,
+                   "(%s)->%s = (*p >> %d) & 1;\n",
+                   name, m->gen_name, (int)(7 - m->val % 8));
        }
        fprintf(codefile,
                "} while(0);\n");
index b0123a8be1762b235da02f6b294fd70b25d126e1..d61dc2e6d5020cc028a28848d3ea475fb8720754 100644 (file)
@@ -226,7 +226,7 @@ encode_type (const char *name, const Type *t, const char *tmpstr)
            fprintf (codefile,
                     "if((%s)->%s) {\n"
                     "c |= 1<<%d;\n",
-                    name, m->gen_name, 7 - m->val % 8);
+                    name, m->gen_name, (int)(7 - m->val % 8));
            fprintf (codefile,
                     "}\n");
        }
@@ -313,7 +313,7 @@ encode_type (const char *name, const Type *t, const char *tmpstr)
                name);
 
        fprintf(codefile,
-               "val = malloc(sizeof(val[0]) * (%s)->len);\n"
+               "val = calloc(1, sizeof(val[0]) * (%s)->len);\n"
                "if (val == NULL && (%s)->len != 0) return ENOMEM;\n",
                name, name);
 
@@ -461,23 +461,24 @@ encode_type (const char *name, const Type *t, const char *tmpstr)
 
         if (replace_tag)
             fprintf(codefile,
-                    "{ unsigned char *psave_%s = p;\n"
+                    "{ unsigned char *psave_%s = p, *pfree_%s = NULL;\n"
                     "size_t l2_%s, lensave_%s = len;\n"
                     "len = length_%s(%s);\n"
                     /* Allocate a temp buffer for the encoder */
-                    "if ((p = malloc(len)) == NULL) return ENOMEM;\n"
+                    "if ((p = pfree_%s = calloc(1, len)) == NULL) return ENOMEM;\n"
                     /* Make p point to the last byte of the allocated buf */
                     "p += len - 1;\n",
-                    tmpstr, tmpstr, tmpstr,
-                    t->subtype->symbol->gen_name, name);
+                    tmpstr, tmpstr, tmpstr, tmpstr,
+                    t->subtype->symbol->gen_name, name, tmpstr);
 
+        /* XXX Currently we generate code that leaks `pfree_%s` here.  */
        c = encode_type (name, t->subtype, tname);
         /* Explicit non-UNIVERSAL tags are always constructed */
         if (!c && t->tag.tagclass != ASN1_C_UNIV && t->tag.tagenv == TE_EXPLICIT)
             c = 1;
         if (replace_tag)
             fprintf(codefile,
-                    "if (len) abort();\n"
+                    "if (len) { free(pfree_%s); return EINVAL; }\n"
                     /*
                      * Here we have `p' pointing to one byte before the buffer
                      * we allocated above.
@@ -552,16 +553,16 @@ encode_type (const char *name, const Type *t, const char *tmpstr)
                      *                 +-- psave_<fieldName>
                      */
                     "e = der_put_tag(psave_%s, %lu, %s, %s, %d, &l2_%s);\n"
-                    "if (e) return e;\n"
+                    "if (e) { free(pfree_%s); return e; }\n"
                     /* Restore `len' and adjust it (see `p' below) */
-                    "len = lensave_%s - (l + %lu - asn1_tag_length_%s);\n"
+                    "len = lensave_%s - (l + %zu - asn1_tag_length_%s);\n"
                     /*
                      * Adjust `ret' to account for the difference in size
                      * between the length of the right and wrong tags.
                      */
-                    "ret += %lu - asn1_tag_length_%s;\n"
+                    "ret += %zu - asn1_tag_length_%s;\n"
                     /* Free the buffer and restore `p' */
-                    "free(p + 1);\n"
+                    "free(pfree_%s);\n"
                     /*
                      * Make `p' point into the original buffer again, to one
                      * byte before the bytes we wrote:
@@ -573,7 +574,7 @@ encode_type (const char *name, const Type *t, const char *tmpstr)
                      *       +-- p
                      */
                     "p = psave_%s - (1 + %lu - asn1_tag_length_%s); }\n",
-                    tmpstr, tmpstr, t->subtype->symbol->name,
+                    tmpstr, tmpstr, tmpstr, t->subtype->symbol->name,
                     tmpstr, t->subtype->symbol->name, t->subtype->symbol->name,
                     tmpstr, length_tag(t->tag.tagvalue),
                     classname(t->tag.tagclass),
@@ -581,9 +582,9 @@ encode_type (const char *name, const Type *t, const char *tmpstr)
                     t->tag.tagvalue,
                     tmpstr,
 
-                    tmpstr, length_tag(t->tag.tagvalue), t->subtype->symbol->name,
+                    tmpstr, tmpstr, length_tag(t->tag.tagvalue), t->subtype->symbol->name,
                     length_tag(t->tag.tagvalue), t->subtype->symbol->name,
-                    tmpstr, length_tag(t->tag.tagvalue), t->subtype->symbol->name);
+                    tmpstr, tmpstr, length_tag(t->tag.tagvalue), t->subtype->symbol->name);
         else
             fprintf(codefile,
                     "e = der_put_length_and_tag (p, len, ret, %s, %s, %s, &l);\n"
index 6c9424cbf351fa4d096d40c3901dd5eef2b211b8..0507d54218031994fe1a0d26438553d2127c5b99 100644 (file)
@@ -56,6 +56,7 @@ free_type (const char *name, const Type *t, int preserve)
            free_primitive ("heim_integer", name);
            break;
        }
+        /* fallthrough; */
     case TBoolean:
     case TEnumerated :
     case TNull:
@@ -126,14 +127,14 @@ free_type (const char *name, const Type *t, int preserve)
     case TSequenceOf: {
        char *n;
 
-       fprintf (codefile, "while((%s)->len){\n", name);
+       fprintf (codefile, "if ((%s)->val)\nwhile((%s)->len){\n", name, name);
        if (asprintf (&n, "&(%s)->val[(%s)->len-1]", name, name) < 0 || n == NULL)
            errx(1, "malloc");
        free_type(n, t->subtype, FALSE);
        fprintf(codefile,
                "(%s)->len--;\n"
-               "}\n",
-               name);
+               "} else (%s)->len = 0;\n",
+               name, name);
        fprintf(codefile,
                "free((%s)->val);\n"
                "(%s)->val = NULL;\n", name, name);
@@ -178,9 +179,9 @@ free_type (const char *name, const Type *t, int preserve)
 void
 generate_type_free (const Symbol *s)
 {
+    struct decoration deco;
+    ssize_t more_deco = -1;
     int preserve = preserve_type(s->name) ? TRUE : FALSE;
-    int deco_opt;
-    char *ft, *fn;
 
     fprintf (codefile, "void ASN1CALL\n"
             "free_%s(%s *data)\n"
@@ -188,18 +189,44 @@ generate_type_free (const Symbol *s)
             s->gen_name, s->gen_name);
 
     free_type ("data", s->type, preserve);
-    if (decorate_type(s->gen_name, &ft, &fn, &deco_opt)) {
-        if (deco_opt) {
-            fprintf(codefile, "if ((data)->%s) {\n", fn);
-            fprintf(codefile, "free_%s((data)->%s);\n", ft, fn);
-            fprintf(codefile, "free((data)->%s);\n", fn);
-            fprintf(codefile, "(data)->%s = NULL;\n", fn);
+    while (decorate_type(s->gen_name, &deco, &more_deco)) {
+        if (deco.ext && deco.free_function_name == NULL) {
+            /* Decorated with field of external type but no free function */
+            if (deco.ptr)
+                fprintf(codefile, "(data)->%s = 0;\n", deco.field_name);
+            else
+                fprintf(codefile,
+                        "memset(&(data)->%s, 0, sizeof((data)->%s));\n",
+                        deco.field_name, deco.field_name);
+        } else if (deco.ext) {
+            /* Decorated with field of external type w/ free function */
+            if (deco.ptr) {
+                fprintf(codefile, "if ((data)->%s) {\n", deco.field_name);
+                fprintf(codefile, "%s((data)->%s);\n",
+                        deco.free_function_name, deco.field_name);
+                fprintf(codefile, "(data)->%s = 0;\n", deco.field_name);
+                fprintf(codefile, "}\n");
+            } else {
+                fprintf(codefile, "%s(&(data)->%s);\n",
+                        deco.free_function_name, deco.field_name);
+                fprintf(codefile,
+                        "memset(&(data)->%s, 0, sizeof((data)->%s));\n",
+                        deco.field_name, deco.field_name);
+            }
+        } else if (deco.opt) {
+            /* Decorated with optional field of ASN.1 type */
+            fprintf(codefile, "if ((data)->%s) {\n", deco.field_name);
+            fprintf(codefile, "free_%s((data)->%s);\n",
+                    deco.field_type, deco.field_name);
+            fprintf(codefile, "free((data)->%s);\n", deco.field_name);
+            fprintf(codefile, "(data)->%s = NULL;\n", deco.field_name);
             fprintf(codefile, "}\n");
         } else {
-            fprintf(codefile, "free_%s(&(data)->%s);\n", ft, fn);
+            /* Decorated with required field of ASN.1 type */
+            fprintf(codefile, "free_%s(&(data)->%s);\n",
+                    deco.field_type, deco.field_name);
         }
-        free(ft);
-        free(fn);
+        free(deco.field_type);
     }
     fprintf (codefile, "}\n\n");
 }
index 24f16528c6309bf1a80249f1c43137029545f42f..424e5de5d5eb7bfb8376b7824facce4d2d541cd0 100644 (file)
@@ -62,7 +62,7 @@ generate_2int (const Type *t, const char *gen_name)
 
     HEIM_TAILQ_FOREACH(m, t->members, members) {
        fprintf (get_code_file(), "if(f.%s) r |= (1ULL << %d);\n",
-                m->gen_name, m->val);
+                m->gen_name, (int)m->val);
     }
     fprintf (get_code_file(), "return r;\n"
             "}\n\n");
@@ -87,7 +87,7 @@ generate_int2 (const Type *t, const char *gen_name)
     if(t->members) {
        HEIM_TAILQ_FOREACH(m, t->members, members) {
            fprintf (get_code_file(), "\tflags.%s = (n >> %d) & 1;\n",
-                    m->gen_name, m->val);
+                    m->gen_name, (int)m->val);
        }
     }
     fprintf (get_code_file(), "\treturn flags;\n"
@@ -114,7 +114,7 @@ generate_units (const Type *t, const char *gen_name)
     if(t->members) {
        HEIM_TAILQ_FOREACH_REVERSE(m, t->members, memhead, members) {
            fprintf (get_code_file(),
-                    "\t{\"%s\",\t1ULL << %d},\n", m->name, m->val);
+                    "\t{\"%s\",\t1ULL << %d},\n", m->name, (int)m->val);
        }
     }
 
@@ -144,8 +144,11 @@ generate_glue (const Type *t, const char *gen_name)
         if (HEIM_TAILQ_EMPTY(t->members))
             break;
         HEIM_TAILQ_FOREACH(m, t->members, members) {
-            if (m->val > 63)
+            if (m->val > 63) {
+                warnx("Not generating 2int, int2, or units for %s due to "
+                      "having a member valued more than 63", gen_name);
                 return;
+            }
         }
         generate_2int (t, gen_name);
         generate_int2 (t, gen_name);
index ccef2acd231949844410f312c0f163d1ab53fc46..f37f1490320b869ae87e5d293c76600416e580a2 100644 (file)
@@ -144,7 +144,22 @@ int is_tagged_type(const Type *);
 
 int preserve_type(const char *);
 int seq_type(const char *);
-int decorate_type(const char *, char **, char **, int *);
+
+struct decoration {
+    char *field_type;           /* C type name */
+    char *field_name;           /* C struct field name */
+    char *copy_function_name;   /* copy constructor function name */
+    char *free_function_name;   /* destructor function name */
+    char *header_name;          /* header name */
+    unsigned int decorated:1;
+    unsigned int first:1;       /* optional */
+    unsigned int opt:1;         /* optional */
+    unsigned int ext:1;         /* external */
+    unsigned int ptr:1;         /* external, pointer */
+    unsigned int void_star:1;   /* external, void * */
+    unsigned int struct_star:1; /* external, struct foo * */
+};
+int decorate_type(const char *, struct decoration *, ssize_t *);
 
 void generate_header_of_codefile(const char *);
 void close_codefile(void);
index af1e44ee68b3c1adc1063160fb30c1ad942f04b0..883eab4b6714ea637dfd0fc559ad7c1c7ae2b27b 100644 (file)
@@ -449,14 +449,17 @@ add_line_pointer(struct templatehead *t,
        errx(1, "malloc");
     va_end(ap);
 
-    q = add_line(t, "{ %s, %s, asn1_%s }", tt, offset, ptr);
+    if (ptr[0] == '&')
+        q = add_line(t, "{ %s, %s, %s }", tt, offset, ptr);
+    else
+        q = add_line(t, "{ %s, %s, asn1_%s }", tt, offset, ptr);
     q->tt = tt;
     q->offset = strdup(offset);
     q->ptr = strdup(ptr);
 }
 
 /*
- * Add an entry to a template where the pointer firled is a string literal.
+ * Add an entry to a template where the pointer field is a string literal.
  */
 static void
 add_line_string(struct templatehead *t,
@@ -549,11 +552,11 @@ defval(struct templatehead *temp, Member *m)
 {
     switch (m->defval->type) {
     case booleanvalue:
-        add_line(temp, "{ A1_OP_DEFVAL|A1_DV_BOOLEAN, ~0, (void *)%u }",
+       add_line(temp, "{ A1_OP_DEFVAL|A1_DV_BOOLEAN, ~0, (void *)(uintptr_t)%u }",
                  m->defval->u.booleanvalue);
         break;
     case nullvalue:
-        add_line(temp, "{ A1_OP_DEFVAL|A1_DV_NULL, ~0, (void *)0 }");
+       add_line(temp, "{ A1_OP_DEFVAL|A1_DV_NULL, ~0, (void *)(uintptr_t)0 }");
         break;
     case integervalue: {
         const char *dv = "A1_DV_INTEGER";
@@ -576,16 +579,16 @@ defval(struct templatehead *temp, Member *m)
 
         if (t->members)
             dv = "A1_DV_INTEGER32"; /* XXX Enum size assumptions!  No good! */
-        else if (t->range->min < 0 &&
+        else if (t->range && t->range->min < 0 &&
                  (t->range->min < INT_MIN || t->range->max > INT_MAX))
             dv = "A1_DV_INTEGER64";
-        else if (t->range->min < 0)
+        else if (t->range && t->range->min < 0)
             dv = "A1_DV_INTEGER32";
-        else if (t->range->max > UINT_MAX)
+        else if (t->range && t->range->max > UINT_MAX)
             dv = "A1_DV_INTEGER64";
         else
             dv = "A1_DV_INTEGER32";
-        add_line(temp, "{ A1_OP_DEFVAL|%s, ~0, (void *)%llu }",
+       add_line(temp, "{ A1_OP_DEFVAL|%s, ~0, (void *)(uintptr_t)%llu }",
                  dv, (long long)m->defval->u.integervalue);
         break;
     }
@@ -595,7 +598,7 @@ defval(struct templatehead *temp, Member *m)
         if (rk_strasvis(&quoted, m->defval->u.stringvalue,
                         VIS_CSTYLE | VIS_NL, "\"") < 0)
             err(1, "Could not quote a string");
-        add_line(temp, "{ A1_OP_DEFVAL|A1_DV_UTF8STRING, ~0, (void *)\"%s\" }",
+       add_line(temp, "{ A1_OP_DEFVAL|A1_DV_UTF8STRING, ~0, (void *)(uintptr_t)\"%s\" }",
                  quoted);
         free(quoted);
         break;
@@ -624,11 +627,13 @@ defval(struct templatehead *temp, Member *m)
             sz -= len;
             p += len;
         }
-        len = snprintf(p, sz, " }");
+        if ((len = snprintf(p, sz, " }")) >= sz)
+            abort();
         sz -= len;
-        p += len;
+        if (sz != 0)
+            abort();
 
-        add_line(temp, "{ A1_OP_DEFVAL|A1_DV_INTEGER, ~0, (void *)\"%s\" }", s);
+       add_line(temp, "{ A1_OP_DEFVAL|A1_DV_INTEGER, ~0, (void *)(uintptr_t)\"%s\" }", s);
         free(s);
         break;
     }
@@ -711,6 +716,8 @@ sort_object_set(IOSObjectSet *os,       /* Object set to sort fields of */
     IOSObject *o;
     size_t i, nobjs = 0;
 
+    *objectsp = NULL;
+
     HEIM_TAILQ_FOREACH(o, os->objects, objects) {
         ObjectField *typeidobjf = NULL;
         ObjectField *of;
@@ -730,6 +737,9 @@ sort_object_set(IOSObjectSet *os,       /* Object set to sort fields of */
     }
     *nobjsp = nobjs;
 
+    if (nobjs == 0)
+        return;
+
     if ((objects = calloc(nobjs, sizeof(*objects))) == NULL)
         err(1, "Out of memory");
     *objectsp = objects;
@@ -752,7 +762,7 @@ sort_object_set(IOSObjectSet *os,       /* Object set to sort fields of */
 static void
 template_object_set(IOSObjectSet *os, Field *typeidfield, Field *opentypefield)
 {
-    IOSObject **objects;
+    IOSObject **objects = NULL;
     IOSObject *o;
     struct tlist *tl;
     size_t nobjs, i;
@@ -794,7 +804,7 @@ template_object_set(IOSObjectSet *os, Field *typeidfield, Field *opentypefield)
         switch (typeidobjf->value->type) {
         case integervalue:
             add_line(&tl->template,
-                     "{ A1_OP_OPENTYPE_ID | A1_OTI_IS_INTEGER, 0, (void *)%lld }",
+                    "{ A1_OP_OPENTYPE_ID | A1_OTI_IS_INTEGER, 0, (void *)(uintptr_t)%lld }",
                      (long long)typeidobjf->value->u.integervalue);
             break;
         case objectidentifiervalue:
@@ -820,7 +830,7 @@ template_object_set(IOSObjectSet *os, Field *typeidfield, Field *opentypefield)
     }
     free(objects);
 
-    tlist_header(tl, "{ 0, 0, ((void *)%lu) }", nobjs);
+    tlist_header(tl, "{ 0, 0, ((void *)(uintptr_t)%lu) }", nobjs);
     tlist_print(tl);
     tlist_add(tl);
     os->symbol->emitted_template = 1;
@@ -952,12 +962,15 @@ template_members(struct templatehead *temp,
              */
             HEIM_TAILQ_FOREACH(m, t->members, members) {
                 if (m->val > UINT32_MAX)
-                    continue; /* Wouldn't fit in the offset field */
+                    errx(1, "Cannot handle %s type %s with named bit %s "
+                         "larger than 63",
+                         t->type == TEnumerated ? "ENUMERATED" : "INTEGER",
+                         name, m->gen_name);
                 add_line(&tl->template,
-                         "{ A1_OP_NAME, %d, \"%s\" }", m->val, m->name);
+                         "{ A1_OP_NAME, %d, \"%s\" }", (int)m->val, m->name);
                 nmemb++;
             }
-            tlist_header(tl, "{ 0, 0, ((void *)%lu) }", nmemb);
+           tlist_header(tl, "{ 0, 0, ((void *)(uintptr_t)%lu) }", nmemb);
             /* XXX Accidentally O(N^2)? */
             if (!tlist_find_dup(tl)) {
                 tlist_print(tl);
@@ -1031,7 +1044,10 @@ template_members(struct templatehead *temp,
        output_name(bname);
 
        HEIM_TAILQ_FOREACH(m, t->members, members) {
-           add_line(&template, "{ 0, %d, \"%s\" }", m->val, m->gen_name);
+            if (m->val > UINT32_MAX)
+                errx(1, "Cannot handle BIT STRING type %s with named bit %s "
+                     "larger than 63", name, m->gen_name);
+           add_line(&template, "{ 0, %d, \"%s\" }", (int)m->val, m->gen_name);
        }
 
        HEIM_TAILQ_FOREACH(q, &template, members) {
@@ -1039,7 +1055,7 @@ template_members(struct templatehead *temp,
        }
 
        fprintf(f, "static const struct asn1_template asn1_%s_%s[] = {\n", basetype, bname);
-       fprintf(f, "/* 0 */ { 0%s, sizeof(%s), ((void *)%lu) },\n",
+       fprintf(f, "/* 0 */ { 0%s, sizeof(%s), ((void *)(uintptr_t)%lu) },\n",
                rfc1510_bitstring ? "|A1_HBF_RFC1510" : "",
                basetype, (unsigned long)count);
        i = 1;
@@ -1061,10 +1077,10 @@ template_members(struct templatehead *temp,
         Field *opentypefield = NULL;
         Field *typeidfield = NULL;
        Member *m;
+        struct decoration deco;
+        ssize_t more_deco = -1;
         size_t i = 0, typeididx = 0, opentypeidx = 0;
         int is_array_of_open_type = 0;
-        int deco_opt;
-        char *ft, *fn;
 
         if (isstruct && t->actual_parameter)
             get_open_type_defn_fields(t, &typeidmember, &opentypemember,
@@ -1104,15 +1120,29 @@ template_members(struct templatehead *temp,
                                typeidfield, opentypefield, opentypemember,
                                is_array_of_open_type);
 
-        if (decorate_type(basetype, &ft, &fn, &deco_opt)) {
+        while (decorate_type(basetype, &deco, &more_deco)) {
             char *poffset2;
 
-            poffset2 = partial_offset(basetype, fn, 1, isstruct);
-           add_line_pointer(temp, ft, poffset2, "A1_OP_TYPE_DECORATE %s",
-                            deco_opt ? "|A1_FLAG_OPTIONAL" : "");
+            poffset2 = partial_offset(basetype, deco.field_name, 1, isstruct);
+
+            if (deco.ext) {
+                char *ptr = NULL;
+
+                /* Decorated with external C type */
+                if (asprintf(&ptr, "&asn1_extern_%s_%s",
+                             basetype, deco.field_name) == -1 || ptr == NULL)
+                    err(1, "out of memory");
+                add_line_pointer(temp, ptr, poffset2,
+                                 "A1_OP_TYPE_DECORATE_EXTERN %s",
+                                 deco.opt ? "|A1_FLAG_OPTIONAL" : "");
+                free(ptr);
+            } else
+                /* Decorated with a templated ASN.1 type */
+                add_line_pointer(temp, deco.field_type, poffset2,
+                                 "A1_OP_TYPE_DECORATE %s",
+                                 deco.opt ? "|A1_FLAG_OPTIONAL" : "");
             free(poffset2);
-            free(ft);
-            free(fn);
+            free(deco.field_type);
         }
 
         if (isstruct)
@@ -1125,10 +1155,10 @@ template_members(struct templatehead *temp,
         Field *opentypefield = NULL;
         Field *typeidfield = NULL;
        Member *m;
+        struct decoration deco;
+        ssize_t more_deco = -1;
         size_t i = 0, typeididx = 0, opentypeidx = 0;
         int is_array_of_open_type = 0;
-        int deco_opt;
-        char *ft, *fn;
 
         if (isstruct && t->actual_parameter)
             get_open_type_defn_fields(t, &typeidmember, &opentypemember,
@@ -1168,15 +1198,29 @@ template_members(struct templatehead *temp,
                                typeidfield, opentypefield, opentypemember,
                                is_array_of_open_type);
 
-        if (decorate_type(basetype, &ft, &fn, &deco_opt)) {
+        while (decorate_type(basetype, &deco, &more_deco)) {
             char *poffset2;
 
-            poffset2 = partial_offset(basetype, fn, 1, isstruct);
-           add_line_pointer(temp, ft, poffset2, "A1_OP_TYPE_DECORATE %s",
-                            deco_opt ? "|A1_FLAG_OPTIONAL" : "");
+            poffset2 = partial_offset(basetype, deco.field_name, 1, isstruct);
+
+            if (deco.ext) {
+                char *ptr = NULL;
+
+                /* Decorated with external C type */
+                if (asprintf(&ptr, "&asn1_extern_%s_%s",
+                             basetype, deco.field_name) == -1 || ptr == NULL)
+                    err(1, "out of memory");
+                add_line_pointer(temp, ptr, poffset2,
+                                 "A1_OP_TYPE_DECORATE_EXTERN %s",
+                                 deco.opt ? "|A1_FLAG_OPTIONAL" : "");
+                free(ptr);
+            } else
+                /* Decorated with a templated ASN.1 type */
+                add_line_pointer(temp, deco.field_type, poffset2,
+                                 "A1_OP_TYPE_DECORATE %s",
+                                 deco.opt ? "|A1_FLAG_OPTIONAL" : "");
             free(poffset2);
-            free(ft);
-            free(fn);
+            free(deco.field_type);
         }
 
         if (isstruct)
@@ -1273,6 +1317,8 @@ template_members(struct templatehead *temp,
        break;
     }
     case TChoice: {
+        struct decoration deco;
+        ssize_t more_deco = -1;
        struct templatehead template;
        struct template *q;
        size_t count = 0, i;
@@ -1343,7 +1389,7 @@ template_members(struct templatehead *temp,
        }
 
        fprintf(f, "static const struct asn1_template %s[] = {\n", tname);
-       fprintf(f, "/* 0 */ { %s, offsetof(%s%s, element), ((void *)%lu) },\n",
+       fprintf(f, "/* 0 */ { %s, offsetof(%s%s, element), ((void *)(uintptr_t)%lu) },\n",
                e ? e : "0", isstruct ? "struct " : "", basetype, (unsigned long)count);
        i = 1;
        HEIM_TAILQ_FOREACH(q, &template, members) {
@@ -1354,6 +1400,31 @@ template_members(struct templatehead *temp,
 
        add_line(temp, "{ A1_OP_CHOICE, %s, %s }", poffset, tname);
 
+        while (decorate_type(basetype, &deco, &more_deco)) {
+            char *poffset2;
+
+            poffset2 = partial_offset(basetype, deco.field_name, 1, isstruct);
+
+            if (deco.ext) {
+                char *ptr = NULL;
+
+                /* Decorated with external C type */
+                if (asprintf(&ptr, "&asn1_extern_%s_%s",
+                             basetype, deco.field_name) == -1 || ptr == NULL)
+                    err(1, "out of memory");
+                add_line_pointer(temp, ptr, poffset2,
+                                 "A1_OP_TYPE_DECORATE_EXTERN %s",
+                                 deco.opt ? "|A1_FLAG_OPTIONAL" : "");
+                free(ptr);
+            } else
+                /* Decorated with a templated ASN.1 type */
+                add_line_pointer(temp, deco.field_type, poffset2,
+                                 "A1_OP_TYPE_DECORATE %s",
+                                 deco.opt ? "|A1_FLAG_OPTIONAL" : "");
+            free(poffset2);
+            free(deco.field_type);
+        }
+
        free(e);
        free(tname);
        break;
@@ -1464,7 +1535,7 @@ generate_template_type(const char *varname,
 
     fprintf(get_code_file(), "/* generate_template_type: %s */\n", tl->name);
 
-    tlist_header(tl, "{ 0%s%s, sizeof(%s), ((void *)%lu) }",
+    tlist_header(tl, "{ 0%s%s, sizeof(%s), ((void *)(uintptr_t)%lu) }",
                 (symname && preserve_type(symname)) ? "|A1_HF_PRESERVE" : "",
                 have_ellipsis ? "|A1_HF_ELLIPSIS" : "", szt, tlist_count(tl));
 
@@ -1491,12 +1562,37 @@ generate_template(const Symbol *s)
 {
     FILE *f = get_code_file();
     const char *dupname;
+    struct decoration deco;
+    ssize_t more_deco = -1;
 
     if (use_extern(s)) {
        gen_extern_stubs(f, s->gen_name);
        return;
     }
 
+    while (decorate_type(s->gen_name, &deco, &more_deco)) {
+        if (!deco.ext)
+            continue;
+        if (deco.void_star && deco.header_name)
+           fprintf(f, "#include %s\n", deco.header_name);
+        fprintf(f,
+                "static const struct asn1_type_func asn1_extern_%s_%s = {\n"
+                "\t(asn1_type_encode)0,\n"
+                "\t(asn1_type_decode)0,\n"
+                "\t(asn1_type_length)0,\n"
+                "\t(asn1_type_copy)%s,\n"
+                "\t(asn1_type_release)%s,\n"
+                "\t(asn1_type_print)0,\n"
+                "\tsizeof(%s)\n"
+                "};\n", s->gen_name, deco.field_name,
+                deco.copy_function_name && deco.copy_function_name[0] ?
+                deco.copy_function_name : "0",
+                deco.free_function_name && deco.free_function_name[0] ?
+                deco.free_function_name : "0",
+                deco.void_star ? "void *" : deco.field_type);
+        free(deco.field_type);
+    }
+
     generate_template_type(s->gen_name, &dupname, s->name, s->gen_name, NULL, s->type, 0, 0, 1);
 
     fprintf(f,
index baaec52f5f836c386c9c9d8e77bd9ed21f96314b..639ec5af2d25e877179b68779edd52954b0e95ef 100644 (file)
@@ -18,6 +18,7 @@ EXPORTS
        CKSUMTYPE,
        ChangePasswdDataMS,
        Checksum,
+        CompositePrincipal,
        ENCTYPE,
        ETYPE-INFO,
        ETYPE-INFO-ENTRY,
@@ -440,9 +441,9 @@ Checksum ::= SEQUENCE {
 --
 -- Attributes have three possible sources in Heimdal Kerberos at this time:
 --
---  - the EncKDCRepPart
---  - the EncTicketPart
---  - the Authenticator's AuthorizationData (if any)
+--  - the EncKDCRepPart (for the client's attributes on the client side)
+--  - the EncTicketPart (for the client's attributes on the server side)
+--  - the Authenticator's AuthorizationData (if any; server-side)
 --
 -- In principle there can be more:
 --
@@ -461,18 +462,47 @@ PrincipalNameAttrSrc ::= CHOICE {
         enc-ticket-part     [1] EncTicketPart   -- minus session key
 }
 PrincipalNameAttrs ::= SEQUENCE {
+        -- True if this name was authenticated via an AP-REQ or a KDC-REP
         authenticated       [0]     BOOLEAN,
-        -- These are compiled from the Ticket and Authenticator:
+        -- These are compiled from the Ticket, KDC-REP, and/or Authenticator
         source              [1]     PrincipalNameAttrSrc OPTIONAL,
-        authenticator-ad    [2]     AuthorizationData OPTIONAL
+        authenticator-ad    [2]     AuthorizationData OPTIONAL,
+        -- For the server on the client side we should keep track of the
+        -- transit path taken to reach it (if absent -> unknown).
+        --
+        -- We don't learn much more about the server from the KDC.
+        peer-realm          [3]     Realm OPTIONAL,
+        transited           [4]     TransitedEncoding OPTIONAL,
+        -- True if the PAC was verified
+        pac-verified        [5]     BOOLEAN,
+        -- True if any AD-KDC-ISSUEDs in the Ticket were validated
+        kdc-issued-verified [6]     BOOLEAN,
+        -- TODO: Add requested attributes, for gss_set_name_attribute(), which
+        --       should cause corresponding authz-data elements to be added to
+        --       any TGS-REQ or to the AP-REQ's Authenticator as appropriate.
+        want-ad             [7]     AuthorizationData OPTIONAL
+}
+-- This is our type for exported composite name tokens for GSS [RFC6680].
+-- It's the same as Principal (below) as decorated with (see krb5.opt file and
+-- asn1_compile usage), except it's not decorated, so the name attributes are
+-- encoded/decoded.
+CompositePrincipal ::= [APPLICATION 48] SEQUENCE {
+       name[0]                 PrincipalName,
+       realm[1]                Realm,
+        nameattrs[2]            PrincipalNameAttrs OPTIONAL
 }
 
--- this is not part of RFC1510
+-- This is not part of RFC1510/RFC4120.  We use this internally as our
+-- krb5_principal (which is a typedef of *Principal), and in HDB entries.
 Principal ::= SEQUENCE {
        name[0]                 PrincipalName,
        realm[1]                Realm
-        -- This will be decorated with a name-attrs field of
-        -- PrincipalNameAttrs type that doesn't get encoded
+        -- This will be decorated with an optional nameattrs field of
+        -- PrincipalNameAttrs type that doesn't get encoded.  Same as
+        -- CompositePrincipal above, except that CompositePrincipal's
+        -- nameattrs field does get encoded, while Principal's does not:
+        --
+        -- nameattrs[2]         PrincipalNameAttrs OPTIONAL
 }
 
 Principals ::= SEQUENCE OF Principal
index 5acc596d39ce23bbd9e3428b69a1dbc3504bc9d2..a8bd85c522fb9ed85a34f8bb4f117d2056b41f11 100644 (file)
@@ -5,3 +5,5 @@
 --sequence=ETYPE-INFO
 --sequence=ETYPE-INFO2
 --preserve-binary=KDC-REQ-BODY
+--decorate=PrincipalNameAttrs:void *:pac
+--decorate=Principal:PrincipalNameAttrs:nameattrs?
index ade5e2d0bfd09a47572cfe6653bfa3ad0e3201fc..15d3a37bebafe9af709047357bd97c89386ebaf0 100644 (file)
@@ -335,6 +335,7 @@ EXPORTS
        copy_CommonCriteriaMeasures
        copy_CommunityIdentifier
        copy_CommunityIdentifiers
+       copy_CompositePrincipal
        copy_ContentEncryptionAlgorithmIdentifier
        copy_ContentInfo
        copy_ContentType
@@ -691,6 +692,7 @@ EXPORTS
        decode_CommonCriteriaMeasures
        decode_CommunityIdentifier
        decode_CommunityIdentifiers
+       decode_CompositePrincipal
        decode_ContentEncryptionAlgorithmIdentifier
        decode_ContentInfo
        decode_ContentType
@@ -1196,6 +1198,7 @@ EXPORTS
        encode_CommonCriteriaMeasures
        encode_CommunityIdentifier
        encode_CommunityIdentifiers
+       encode_CompositePrincipal
        encode_ContentEncryptionAlgorithmIdentifier
        encode_ContentInfo
        encode_ContentType
@@ -1556,6 +1559,7 @@ EXPORTS
        free_CommonCriteriaMeasures
        free_CommunityIdentifier
        free_CommunityIdentifiers
+       free_CompositePrincipal
        free_ContentEncryptionAlgorithmIdentifier
        free_ContentInfo
        free_ContentType
@@ -1938,6 +1942,7 @@ EXPORTS
        length_CommonCriteriaMeasures
        length_CommunityIdentifier
        length_CommunityIdentifiers
+       length_CompositePrincipal
        length_ContentEncryptionAlgorithmIdentifier
        length_ContentInfo
        length_ContentType
@@ -2294,6 +2299,7 @@ EXPORTS
        print_CommonCriteriaMeasures
        print_CommunityIdentifier
        print_CommunityIdentifiers
+       print_CompositePrincipal
        print_ContentEncryptionAlgorithmIdentifier
        print_ContentInfo
        print_ContentType
index 64db63ab2ecb3ab6890f016bdc59a947ecd8e97c..bcfdad62e2e75b9fcfa4dd42a239bb9429c91f59 100644 (file)
@@ -41,60 +41,195 @@ static getarg_strings preserve;
 static getarg_strings seq;
 static getarg_strings decorate;
 
+static int
+strcmp4mergesort_r(const void *ap, const void *bp, void *d)
+{
+    const char *a = *(const char **)ap;
+    const char *b = *(const char **)bp;
+    char sep = *(const char *)d;
+    int cmp;
+
+    if (sep) {
+        const char *sepa = strchr(a, sep);
+        const char *sepb = strchr(b, sep);
+        size_t alen, blen;
+
+        if (sepa == NULL) sepa = a + strlen(a);
+        if (sepb == NULL) sepb = b + strlen(b);
+        alen = sepa - a;
+        blen = sepb - b;
+        cmp = strncmp(a, b, alen > blen ? alen : blen);
+        if (cmp == 0)
+            cmp = alen - blen;
+    } else
+        cmp = strcmp(a, b);
+    if (cmp == 0)
+        return (uintptr_t)ap - (uintptr_t)bp; /* stable sort */
+    return cmp;
+}
+
+static int
+prefix_check(const char *s, const char *p, size_t plen, char sep, int *cmp)
+{
+    if ((*cmp = strncmp(p, s, plen)) == 0 && s[plen] == sep)
+        return 1;
+    if (*cmp == 0)
+        *cmp = 1;
+    return 0;
+}
+
+static ssize_t
+bsearch_strings(struct getarg_strings *strs, const char *p,
+                char sep, ssize_t *more)
+{
+    ssize_t right = (ssize_t)strs->num_strings - 1;
+    ssize_t left = 0;
+    ssize_t plen = 0;
+    int cmp;
+
+    if (sep)
+        plen = strlen(p);
+
+    if (strs->num_strings == 0)
+        return -1;
+
+    if (sep && more && *more > -1) {
+        /* If *more > -1 we're continuing an iteration */
+        if (*more > right)
+            return -1;
+        if (prefix_check(strs->strings[*more], p, plen, sep, &cmp))
+            return (*more)++;
+        (*more)++;
+        return -1;
+    }
+
+    while (left <= right) {
+        ssize_t mid = left + (right - left) / 2;
+
+        if (sep) {
+            int cmp2;
+
+            while (prefix_check(strs->strings[mid], p, plen, sep, &cmp) &&
+                   mid > 0 &&
+                   prefix_check(strs->strings[mid - 1], p, plen, sep, &cmp2))
+                mid--;
+        } else
+            cmp = strcmp(p, strs->strings[mid]);
+        if (cmp == 0) {
+            if (more)
+                *more = mid + 1;
+            return mid;
+        }
+        if (cmp < 0)
+            right = mid - 1; /* -1 if `p' is smaller than smallest in strs */
+        else
+            left = mid + 1;
+    }
+    return -1;
+}
+
 int
 preserve_type(const char *p)
 {
-    int i;
-    for (i = 0; i < preserve.num_strings; i++)
-       if (strcmp(preserve.strings[i], p) == 0)
-           return 1;
-    return 0;
+    return bsearch_strings(&preserve, p, '\0', 0) > -1;
 }
 
 int
 seq_type(const char *p)
 {
-    size_t i;
-
-    for (i = 0; i < seq.num_strings; i++)
-       if (strcmp(seq.strings[i], p) == 0)
-           return 1;
-    return 0;
+    return bsearch_strings(&seq, p, '\0', 0) > -1;
 }
 
-int
-decorate_type(const char *p, char **field_type, char **field_name, int *opt)
+/*
+ * Split `s' on `sep' and fill fs[] with pointers to the substrings.
+ *
+ * Only the first substring is to be freed -- the rest share the same
+ * allocation.
+ *
+ * The last element may contain `sep' chars if there are more fields in `s'
+ * than output locations in `fs[]'.
+ */
+static void
+split_str(const char *s, char sep, char ***fs)
 {
-    size_t plen = strlen(p);
     size_t i;
 
-    *field_type = NULL;
-    *field_name = NULL;
-    *opt = 0;
-
-    for (i = 0; i < decorate.num_strings; i++) {
-        const char *r;
+    fs[0][0] = estrdup(s);
+    for (i = 1; fs[i]; i++) {
         char *q;
 
-       if (strncmp(decorate.strings[i], p, plen) != 0)
-            continue;
-       if (decorate.strings[i][plen] != ':')
-            errx(1, "--decorate argument missing field type");
-
-        p = &decorate.strings[i][plen + 1];
-        if ((r = strchr(p, ':')) == NULL)
-            errx(1, "--decorate argument missing field name");
-        r++;
-        *field_type = estrdup(p);
-        *(strchr(*field_type, ':')) = '\0';
-        *field_name = estrdup(r);
-        if ((q = strchr(*field_name, '?'))) {
-            *q = '\0';
-            *opt = 1;
-        }
-        return 1;
+        if ((q = strchr(fs[i-1][0], sep)) == NULL)
+            break;
+        *(q++) = '\0';
+        fs[i][0] = q;
     }
-    return 0;
+    for (; fs[i]; i++)
+        fs[i][0] = NULL;
+}
+
+/*
+ * If `p' is "decorated" with a not-to-be-encoded-or-decoded field,
+ * output the field's typename and fieldname, whether it's optional, whether
+ * it's an ASN.1 type or an "external" type, and if external the names of
+ * functions to copy and free values of that type.
+ */
+int
+decorate_type(const char *p, struct decoration *deco, ssize_t *more)
+{
+    ssize_t i;
+    char **s[7];
+    char *junk = NULL;
+    char *cp;
+
+    deco->first = *more == -1;
+    deco->decorated = 0;
+    deco->field_type = NULL;
+    if ((i = bsearch_strings(&decorate, p, ':', more)) == -1)
+        return 0;
+
+    deco->decorated = 1;
+    deco->opt = deco->ext = deco->ptr = 0;
+    deco->void_star = deco->struct_star = 0;
+    deco->field_name = deco->copy_function_name = deco->free_function_name =
+        deco->header_name = NULL;
+
+    s[0] = &deco->field_type;
+    s[1] = &deco->field_name;
+    s[2] = &deco->copy_function_name;
+    s[3] = &deco->free_function_name;
+    s[4] = &deco->header_name;
+    s[5] = &junk;
+    s[6] = NULL;
+    split_str(decorate.strings[i] + strlen(p) + 1, ':', s);
+
+    if (junk || deco->field_type[0] == '\0' || !deco->field_name ||
+        deco->field_name[0] == '\0' || deco->field_name[0] == '?') {
+        errx(1, "Invalidate type decoration specification: --decorate=\"%s\"",
+              decorate.strings[i]);
+    }
+    if ((cp = strchr(deco->field_name, '?'))) {
+        deco->opt = 1;
+        *cp = '\0';
+    }
+    if (strcmp(deco->field_type, "void*") == 0 ||
+        strcmp(deco->field_type, "void *") == 0) {
+        deco->ext = deco->ptr = deco->void_star = 1;
+        deco->opt = 1;
+        deco->header_name = NULL;
+    } else if (strncmp(deco->field_type, "struct ", sizeof("struct ") - 1) == 0 &&
+             deco->field_type[strlen(deco->field_type) - 1] == '*')
+        deco->ptr = deco->struct_star = 1;
+    if (deco->ptr || deco->copy_function_name)
+        deco->ext = 1;
+    if (deco->ext && deco->copy_function_name && !deco->copy_function_name[0])
+        deco->copy_function_name = NULL;
+    if (deco->ext && deco->free_function_name && !deco->free_function_name[0])
+        deco->free_function_name = NULL;
+    if (deco->header_name && !deco->header_name[0])
+        deco->header_name = NULL;
+    if (deco->ptr)
+        deco->opt = 0;
+    return 1;
 }
 
 static const char *
@@ -147,11 +282,11 @@ struct getargs args[] = {
     { "preserve-binary", 0, arg_strings, &preserve,
         "Names of types for which to generate _save fields, saving original "
             "encoding, in containing structures (useful for signature "
-            "verification)", "TYPE-NAME" },
+            "verification)", "TYPE" },
     { "sequence", 0, arg_strings, &seq,
-        "Generate add/remove functions for SEQUENCE OF types", "TYPE-NAME" },
+        "Generate add/remove functions for SEQUENCE OF types", "TYPE" },
     { "decorate", 0, arg_strings, &decorate,
-        "Generate private field for SEQUENCE/SET type", "TYPE-NAME:FIELD_TYPE:field_name[?]" },
+        "Generate private field for SEQUENCE/SET type", "DECORATION" },
     { "one-code-file", 0, arg_flag, &one_code_file, NULL, NULL },
     { "gen-name", 0, arg_string, &name,
         "Name of generated module", "NAME" },
@@ -166,7 +301,7 @@ struct getargs args[] = {
         "Do not generate roken-style units", NULL },
     { "type-file", 0, arg_string, &type_file_string,
         "Name of a C header file to generate includes of for base types",
-        "C-HEADER-FILE" },
+        "FILE" },
     { "version", 0, arg_flag, &version_flag, NULL, NULL },
     { "help", 0, arg_flag, &help_flag, NULL, NULL }
 };
@@ -175,7 +310,17 @@ int num_args = sizeof(args) / sizeof(args[0]);
 static void
 usage(int code)
 {
+    if (code)
+        dup2(STDERR_FILENO, STDOUT_FILENO);
+    else
+        dup2(STDOUT_FILENO, STDERR_FILENO);
     arg_printusage(args, num_args, NULL, "[asn1-file [name]]");
+    fprintf(stderr,
+            "\nA DECORATION is one of:\n\n"
+            "\tTYPE:FTYPE:fname[?]\n"
+            "\tTYPE:FTYPE:fname[?]:[copy_function]:[free_function]:header\n"
+            "\tTYPE:void:fname:::\n"
+            "\nSee the manual page.\n");
     exit(code);
 }
 
@@ -304,6 +449,15 @@ main(int argc, char **argv)
 #endif
     }
 
+    if (preserve.num_strings)
+        mergesort_r(preserve.strings, preserve.num_strings,
+                    sizeof(preserve.strings[0]), strcmp4mergesort_r, "");
+    if (seq.num_strings)
+        mergesort_r(seq.strings, seq.num_strings, sizeof(seq.strings[0]),
+                    strcmp4mergesort_r, "");
+    if (decorate.num_strings)
+        mergesort_r(decorate.strings, decorate.num_strings,
+                    sizeof(decorate.strings[0]), strcmp4mergesort_r, ":");
 
     init_generate(file, name);
 
@@ -316,12 +470,12 @@ main(int argc, char **argv)
        exit(1);
     if (!original_order)
         generate_types();
-    close_generate ();
     if (argc != optidx)
        fclose(yyin);
 
     if (one_code_file)
        close_codefile();
+    close_generate();
 
     if (arg) {
        for (i = 1; i < len; i++)
index 63155efbd0730e77d8959d5ea95d8aebcc4a5e49..db11b114282e7c8a6f6e3a7342c8216bd09ed05d 100644 (file)
@@ -59,19 +59,19 @@ struct sym_oid {
     { #sym, &asn1_oid_ ## sym },
 
 static const struct sym_oid sym_oids[] = {
-#include "cms_asn1_oids.x"
-#include "crmf_asn1_oids.x"
-#include "digest_asn1_oids.x"
-#include "krb5_asn1_oids.x"
-#include "kx509_asn1_oids.x"
-#include "ocsp_asn1_oids.x"
-#include "pkcs10_asn1_oids.x"
-#include "pkcs12_asn1_oids.x"
-#include "pkcs8_asn1_oids.x"
-#include "pkcs9_asn1_oids.x"
-#include "pkinit_asn1_oids.x"
-#include "rfc2459_asn1_oids.x"
-#include "rfc4108_asn1_oids.x"
+#include "cms_asn1_oids.c"
+#include "crmf_asn1_oids.c"
+#include "digest_asn1_oids.c"
+#include "krb5_asn1_oids.c"
+#include "kx509_asn1_oids.c"
+#include "ocsp_asn1_oids.c"
+#include "pkcs10_asn1_oids.c"
+#include "pkcs12_asn1_oids.c"
+#include "pkcs8_asn1_oids.c"
+#include "pkcs9_asn1_oids.c"
+#include "pkinit_asn1_oids.c"
+#include "rfc2459_asn1_oids.c"
+#include "rfc4108_asn1_oids.c"
 };
 
 static size_t num_sym_oids = sizeof(sym_oids) / sizeof(sym_oids[0]);
@@ -95,18 +95,18 @@ static size_t
 count_sym_oids(void)
 {
     size_t c = 0;
-#include "cms_asn1_oids.x"
-#include "crmf_asn1_oids.x"
-#include "digest_asn1_oids.x"
-#include "krb5_asn1_oids.x"
-#include "kx509_asn1_oids.x"
-#include "ocsp_asn1_oids.x"
-#include "pkcs10_asn1_oids.x"
-#include "pkcs12_asn1_oids.x"
-#include "pkcs8_asn1_oids.x"
-#include "pkcs9_asn1_oids.x"
-#include "pkinit_asn1_oids.x"
-#include "rfc2459_asn1_oids.x"
+#include "cms_asn1_oids.c"
+#include "crmf_asn1_oids.c"
+#include "digest_asn1_oids.c"
+#include "krb5_asn1_oids.c"
+#include "kx509_asn1_oids.c"
+#include "ocsp_asn1_oids.c"
+#include "pkcs10_asn1_oids.c"
+#include "pkcs12_asn1_oids.c"
+#include "pkcs8_asn1_oids.c"
+#include "pkcs9_asn1_oids.c"
+#include "pkinit_asn1_oids.c"
+#include "rfc2459_asn1_oids.c"
     return c;
 }
 #undef DEFINE_OID_WITH_NAME
@@ -125,18 +125,18 @@ init_sym_oids(void)
     if (!sym_oids &&
         (c = count_sym_oids()) &&
         (tmp = calloc(c, sizeof(tmp[0])))) {
-#include "cms_asn1_oids.x"
-#include "crmf_asn1_oids.x"
-#include "digest_asn1_oids.x"
-#include "krb5_asn1_oids.x"
-#include "kx509_asn1_oids.x"
-#include "ocsp_asn1_oids.x"
-#include "pkcs10_asn1_oids.x"
-#include "pkcs12_asn1_oids.x"
-#include "pkcs8_asn1_oids.x"
-#include "pkcs9_asn1_oids.x"
-#include "pkinit_asn1_oids.x"
-#include "rfc2459_asn1_oids.x"
+#include "cms_asn1_oids.c"
+#include "crmf_asn1_oids.c"
+#include "digest_asn1_oids.c"
+#include "krb5_asn1_oids.c"
+#include "kx509_asn1_oids.c"
+#include "ocsp_asn1_oids.c"
+#include "pkcs10_asn1_oids.c"
+#include "pkcs12_asn1_oids.c"
+#include "pkcs8_asn1_oids.c"
+#include "pkcs9_asn1_oids.c"
+#include "pkinit_asn1_oids.c"
+#include "rfc2459_asn1_oids.c"
         num_sym_oids = c;
         sym_oids = tmp;
     }
@@ -331,7 +331,6 @@ der_print_heim_oid_sym(const heim_oid *oid, char delim, char **strp)
         *strp = s1;
         return 0;
     }
-    p = s2 + strlen(s1) + 1;
     for (p = s2 + strlen(s1) + 1; *p; p++) {
         if (*p == '_')
             *p = '-';
index b88386223b30590379e0e0b35905980fa8212b07..8a24e251565762bbaeae8b5af7680d6eb5aa997a 100644 (file)
@@ -91,7 +91,7 @@ struct member {
     char *name;
     char *gen_name;
     char *label;
-    int val;
+    int64_t val;
     int optional;
     int ellipsis;
     struct type *type;
@@ -120,7 +120,7 @@ struct range {
     int64_t max;
 };
 
-enum ctype { CT_CONTENTS, CT_USER, CT_TABLE_CONSTRAINT } ;
+enum ctype { CT_CONTENTS, CT_USER, CT_TABLE_CONSTRAINT, CT_RANGE } ;
 
 struct constraint_spec;
 
@@ -217,6 +217,7 @@ struct constraint_spec {
            struct value *encoding;
             struct component_relation_constraint crel;
        } content;
+        struct range *range;
     } u;
 };
 
index 7f5670f3456fc30dcbda37c15b4753aee7664939..7a19e7477e3db5415480747819bff2400374ebd6 100644 (file)
@@ -37,6 +37,7 @@
 #include <com_err.h>
 #include <vis.h>
 #include <vis-extras.h>
+#include <heimbase.h>
 
 #ifndef ENOTSUP
 /* Very old MSVC CRTs don't have ENOTSUP */
@@ -774,6 +775,7 @@ _asn1_decode(const struct asn1_template *t, unsigned flags,
                 return ret;
             break;
         }
+       case A1_OP_TYPE_DECORATE_EXTERN: break;
        case A1_OP_TYPE_DECORATE: break;
         case A1_OP_NAME: break;
        case A1_OP_DEFVAL:
@@ -829,6 +831,8 @@ _asn1_decode(const struct asn1_template *t, unsigned flags,
            if (ret) {
                if (t->tt & A1_FLAG_OPTIONAL) {
                } else if (t->tt & A1_FLAG_DEFAULT) {
+                    if (!tdefval)
+                        return ASN1_PARSE_ERROR; /* Can't happen */
                     /*
                      * Defaulted field not present in encoding, presumably,
                      * though we should really look more carefully at `ret'.
@@ -895,6 +899,8 @@ _asn1_decode(const struct asn1_template *t, unsigned flags,
                     data = olddata;
                    break;
                 } else if (t->tt & A1_FLAG_DEFAULT) {
+                    if (!tdefval)
+                        return ASN1_PARSE_ERROR; /* Can't happen */
                     /*
                      * Defaulted field not present in encoding, presumably,
                      * though we should really look more carefully at `ret'.
@@ -1418,6 +1424,7 @@ _asn1_encode(const struct asn1_template *t, unsigned char *p, size_t len, const
         }
         case A1_OP_NAME: break;
        case A1_OP_DEFVAL: break;
+       case A1_OP_TYPE_DECORATE_EXTERN: break;
        case A1_OP_TYPE_DECORATE: break;
        case A1_OP_TYPE:
        case A1_OP_TYPE_EXTERN: {
@@ -1583,10 +1590,9 @@ _asn1_encode(const struct asn1_template *t, unsigned char *p, size_t len, const
                 }
                 if (ret == 0) {
                     /* Copy the encoding where it belongs */
-                    len -= l; p -= l;
                     psave -= (datalen + l - oldtaglen);
                     lensave -= (datalen + l - oldtaglen);
-                    memcpy(psave + 1, p + 1, datalen + l - oldtaglen);
+                    memcpy(psave + 1, p + 1 - l, datalen + l - oldtaglen);
                     p = psave;
                     len = lensave;
                 }
@@ -1828,7 +1834,7 @@ _asn1_length_open_type_id(const struct asn1_template *t,
                           const void *data)
 {
     struct asn1_template pretend[2] = {
-        { 0, 0, ((void*)1) },
+       { 0, 0, ((void*)(uintptr_t)1) },
     };
     pretend[1] = *t;
     while ((t->tt & A1_OP_MASK) == A1_OP_TAG)
@@ -1895,8 +1901,6 @@ _asn1_length_open_type(const struct asn1_template *tbase,
         break;
     default: return 0;
     }
-    if (!typeid_is_int && !typeid_is_oid)
-        return 0;
     if (!(t->tt & A1_OS_OT_IS_ARRAY)) {
         struct heim_base_data *os = DPO(data, topentype->offset);
 
@@ -1994,6 +1998,7 @@ _asn1_length(const struct asn1_template *t, const void *data)
         }
         case A1_OP_NAME: break;
        case A1_OP_DEFVAL: break;
+       case A1_OP_TYPE_DECORATE_EXTERN: break;
        case A1_OP_TYPE_DECORATE: break;
        case A1_OP_TYPE:
        case A1_OP_TYPE_EXTERN: {
@@ -2256,6 +2261,7 @@ _asn1_free(const struct asn1_template *t, void *data)
         }
         case A1_OP_NAME: break;
        case A1_OP_DEFVAL: break;
+       case A1_OP_TYPE_DECORATE_EXTERN:
        case A1_OP_TYPE_DECORATE:
        case A1_OP_TYPE:
        case A1_OP_TYPE_EXTERN: {
@@ -2270,9 +2276,17 @@ _asn1_free(const struct asn1_template *t, void *data)
 
            if ((t->tt & A1_OP_MASK) == A1_OP_TYPE || (t->tt & A1_OP_MASK) == A1_OP_TYPE_DECORATE) {
                _asn1_free(t->ptr, el);
-           } else {
+           } else if ((t->tt & A1_OP_MASK) == A1_OP_TYPE_EXTERN) {
                const struct asn1_type_func *f = t->ptr;
                (f->release)(el);
+           } else {
+                /* A1_OP_TYPE_DECORATE_EXTERN */
+               const struct asn1_type_func *f = t->ptr;
+
+                if (f && f->release)
+                    (f->release)(el);
+                else if (f)
+                    memset(el, 0, f->size);
            }
            if (t->tt & A1_FLAG_OPTIONAL) {
                free(el);
@@ -2432,9 +2446,9 @@ _asn1_print_open_type(const struct asn1_template *t, /* object set template */
             if (s)
                 r = rk_strpoolprintf(r, ",%s\"_%s\":%s",
                                      indents ? indents : "", opentype_name, s);
-            free(indents);
             free(s);
         }
+       free(indents);
         return r;
     }
 
@@ -2450,8 +2464,7 @@ _asn1_print_open_type(const struct asn1_template *t, /* object set template */
                          opentype_name);
     free(indents);
     indents = getindent(flags, indent + 1);
-    if (indents)
-        r = rk_strpoolprintf(r, "%s", indents ? indents : "");
+    r = rk_strpoolprintf(r, "%s", indents ? indents : "");
     for (i = 0; r && i < len; i++) {
         struct rk_strpool *r2 = NULL;
         char *s = NULL;;
@@ -2545,6 +2558,7 @@ _asn1_print(const struct asn1_template *t,
             break;
         case A1_OP_NAME: break;
        case A1_OP_DEFVAL: break;
+       case A1_OP_TYPE_DECORATE_EXTERN: break;
        case A1_OP_TYPE_DECORATE: break; /* We could probably print this though */
        case A1_OP_TYPE:
        case A1_OP_TYPE_EXTERN: {
@@ -2816,7 +2830,7 @@ _asn1_copy_open_type(const struct asn1_template *t, /* object set template */
     *dtop = NULL;
     if ((valto = calloc(len, sizeof(valto[0]))) == NULL)
         ret = ENOMEM;
-    for (i = 0, len = *lenfromp; ret == 0 && i < len; (*lentop)++, i++) {
+    for (i = 0, len = *lenfromp; ret == 0 && i < len; i++) {
         if (valfrom[i] == NULL) {
             valto[i] = NULL;
             continue;
@@ -2825,17 +2839,19 @@ _asn1_copy_open_type(const struct asn1_template *t, /* object set template */
             ret = ENOMEM;
         else
             ret = _asn1_copy(tactual_type->ptr, valfrom[i], valto[i]);
+        (*lentop)++;
     }
 
-    for (i = 0; ret && i < len; i++) {
+    for (i = 0; ret && i < (*lentop); i++) {
         if (valto[i]) {
             _asn1_free(tactual_type->ptr, valto[i]);
             free(valto[i]);
         }
     }
-    if (ret)
+    if (ret) {
         free(valto);
-    else
+        *lentop = 0;
+    } else
         *dtop = valto;
     return ret;
 }
@@ -2863,6 +2879,7 @@ _asn1_copy(const struct asn1_template *t, const void *from, void *to)
         }
         case A1_OP_NAME: break;
        case A1_OP_DEFVAL: break;
+       case A1_OP_TYPE_DECORATE_EXTERN:
        case A1_OP_TYPE_DECORATE:
        case A1_OP_TYPE:
        case A1_OP_TYPE_EXTERN: {
@@ -2871,7 +2888,8 @@ _asn1_copy(const struct asn1_template *t, const void *from, void *to)
            void **ptel = (void **)tel;
            size_t size;
 
-           if ((t->tt & A1_OP_MASK) == A1_OP_TYPE) {
+           if ((t->tt & A1_OP_MASK) == A1_OP_TYPE ||
+                (t->tt & A1_OP_MASK) == A1_OP_TYPE_DECORATE) {
                size = _asn1_sizeofType(t->ptr);
            } else {
                const struct asn1_type_func *f = t->ptr;
@@ -2892,9 +2910,17 @@ _asn1_copy(const struct asn1_template *t, const void *from, void *to)
            if ((t->tt & A1_OP_MASK) == A1_OP_TYPE ||
                 (t->tt & A1_OP_MASK) == A1_OP_TYPE_DECORATE) {
                ret = _asn1_copy(t->ptr, fel, tel);
+           } else if ((t->tt & A1_OP_MASK) == A1_OP_TYPE_EXTERN) {
+               const struct asn1_type_func *f = t->ptr;
+                ret = (f->copy)(fel, tel);
            } else {
                const struct asn1_type_func *f = t->ptr;
-               ret = (f->copy)(fel, tel);
+
+                /* A1_OP_TYPE_DECORATE_EXTERN */
+                if (f && f->copy)
+                    ret = (f->copy)(fel, tel);
+                else if (f)
+                    memset(tel, 0, f->size);
            }
 
            if (ret) {
index a76152712d9e5b1a520d054888a010b3cc70b526..08c7dcd93ee18d80fae59558b3d58c5d1ac606bb 100644 (file)
@@ -288,7 +288,7 @@ TESTExtensible ::= SEQUENCE {
 
 TESTDecorated ::= SEQUENCE {
   version     TESTuint32
-  -- gets decorated
+  -- gets decorated with varius fields (see test.opt)
 }
 
 TESTNotDecorated ::= SEQUENCE {
@@ -296,4 +296,14 @@ TESTNotDecorated ::= SEQUENCE {
   -- should have the same encoding as TESTDecorated
 }
 
+TESTDecoratedChoice ::= CHOICE {
+  version     TESTuint32
+  -- gets decorated with varius fields (see test.opt)
+}
+
+TESTNotDecoratedChoice ::= CHOICE {
+  version     TESTuint32
+  -- should have the same encoding as TESTDecoratedChoice
+}
+
 END
index 500ee4ec81112be329c7821714d241c584f1307e..755eba01bfb98baa99ee1cd7271e2661f980309b 100644 (file)
@@ -1 +1,7 @@
 --sequence=TESTSeqOf
+--decorate=TESTDecorated:TESTuint32:version2?
+--decorate=TESTDecorated:my_vers:version3:my_copy_vers:my_free_vers:"check-gen.h"
+--decorate=TESTDecorated:void *:privthing
+--decorate=TESTDecoratedChoice:TESTuint32:version2?
+--decorate=TESTDecoratedChoice:my_vers:version3:my_copy_vers:my_free_vers:"check-gen.h"
+--decorate=TESTDecoratedChoice:void *:privthing
index b34f9de488000509ed423242964e15f54da46748..994fa7d38e4cd9c9122682c304648dc407566982 100644 (file)
@@ -46,7 +46,7 @@ struct heim_array_data {
     heim_object_t *allocated;
 };
 
-static void
+static void HEIM_CALLCONV
 array_dealloc(heim_object_t ptr)
 {
     heim_array_t array = ptr;
@@ -58,7 +58,7 @@ array_dealloc(heim_object_t ptr)
 
 struct heim_type_data array_object = {
     HEIM_TID_ARRAY,
-    "dict-object",
+    "array-object",
     NULL,
     array_dealloc,
     NULL,
index 278962172683096cb4adb1e9a8d29a034799cb37..268cc018df6fe1fd058f337791aa51508a96fdd9 100644 (file)
@@ -275,11 +275,12 @@ bsearch_common(const char *buf, size_t sz, const char *key,
            ret = 0;
            if (val_len && value) {
                /* Avoid strndup() so we don't need libroken here yet */
-               *value = malloc(val_len + 1);
-               if (!*value)
-                   ret = errno;
-               (void) memcpy(*value, &buf[val_start], val_len);
-               (*value)[val_len] = '\0';
+               if ((*value = malloc(val_len + 1))) {
+                    (void) memcpy(*value, &buf[val_start], val_len);
+                    (*value)[val_len] = '\0';
+                } else {
+                    ret = errno;
+                }
            }
            break;
        }
@@ -708,6 +709,10 @@ _bsearch_file(bsearch_file_handle bfh, const char *key,
 
     if (reads)
        *reads = 0;
+    if (value)
+       *value = NULL;
+    if (loops)
+       *loops = 0;
 
     /* If whole file is in memory then search that and we're done */
     if (bfh->file_sz == bfh->cache_sz)
@@ -715,11 +720,6 @@ _bsearch_file(bsearch_file_handle bfh, const char *key,
 
     /* Else block-wise binary search */
 
-    if (value)
-       *value = NULL;
-    if (loops)
-       *loops = 0;
-
     l = 0;
     r = (bfh->file_sz / bfh->page_sz) + 1;
     for (level = 0, page = r >> 1; page >= l && page < r ; level++) {
@@ -851,7 +851,7 @@ stdb_copy_value(void *db, heim_string_t table, heim_data_t key,
 {
     bsearch_file_handle bfh = db;
     const char *k;
-    char *v;
+    char *v = NULL;
     heim_data_t value;
     int ret;
 
@@ -869,6 +869,8 @@ stdb_copy_value(void *db, heim_string_t table, heim_data_t key,
     else
        k = (const char *)heim_data_get_ptr(key);
     ret = _bsearch_file(bfh, k, &v, NULL, NULL, NULL);
+    if (ret == 0 && v == NULL)
+        ret = -1; /* Quiet lint */
     if (ret != 0) {
        if (ret > 0 && error)
            *error = heim_error_create(ret, "%s", strerror(ret));
index 4aa6efc66774f5dead0c764a599a54fb968f6b9a..cefdde0c1bbe43c96bd1c5e429363646d5873539 100644 (file)
@@ -34,7 +34,7 @@
 #include "baselocl.h"
 #include <string.h>
 
-static void
+static void HEIM_CALLCONV
 data_dealloc(void *ptr)
 {
     heim_data_t d = ptr;
@@ -61,7 +61,7 @@ data_cmp(void *a, void *b)
     return memcmp(osa->data, osb->data, osa->length);
 }
 
-static unsigned long
+static uintptr_t
 data_hash(void *ptr)
 {
     heim_octet_string *os = ptr;
@@ -69,8 +69,9 @@ data_hash(void *ptr)
 
     if (os->length < 4)
        return os->length;
-    return s[0] | (s[1] << 8) |
-       (s[os->length - 2] << 16) | (s[os->length - 1] << 24);
+
+    return ((unsigned long)s[os->length - 1] << 24)
+       | (s[os->length - 2] << 16) | (s[1] << 8) | s[0];
 }
 
 struct heim_type_data _heim_data_object = {
index cd750386accfeb223d838f5a5fd7136f3f4edc50..b206ff6d766bd4e69d7b9fe165cc43c8dd528db8 100644 (file)
@@ -84,7 +84,7 @@ static int open_file(const char *, int , int, int *, heim_error_t *);
 static int read_json(const char *, heim_object_t *, heim_error_t *);
 static struct heim_db_type json_dbt;
 
-static void db_dealloc(void *ptr);
+static void HEIM_CALLCONV db_dealloc(void *ptr);
 
 struct heim_type_data db_object = {
     HEIM_TID_DB,
@@ -150,7 +150,7 @@ db_init_plugins_once(void *arg)
     db_plugins = heim_retain(arg);
 }
 
-static void
+static void HEIM_CALLCONV
 plugin_dealloc(void *arg)
 {
     db_plugin plug = arg;
@@ -242,7 +242,7 @@ heim_db_register(const char *dbtype,
     return ret;
 }
 
-static void
+static void HEIM_CALLCONV
 db_dealloc(void *arg)
 {
     heim_db_t db = arg;
@@ -577,7 +577,7 @@ heim_db_commit(heim_db_t db, heim_error_t *error)
        goto done;
     }
 
-    if (db->options == NULL)
+    if (db->options)
        journal_fname = heim_dict_get_value(db->options, HSTR("journal-filename"));
 
     if (journal_fname != NULL) {
@@ -1144,21 +1144,15 @@ enomem:
 static
 heim_data_t from_base64(heim_string_t s, heim_error_t *error)
 {
+    ssize_t len = -1;
     void *buf;
-    size_t len;
     heim_data_t d;
 
     buf = malloc(strlen(heim_string_get_utf8(s)));
-    if (buf == NULL)
-       goto enomem;
-
-    len = rk_base64_decode(heim_string_get_utf8(s), buf);
-    d = heim_data_ref_create(buf, len, free);
-    if (d == NULL)
-       goto enomem;
-    return d;
-
-enomem:
+    if (buf)
+        len = rk_base64_decode(heim_string_get_utf8(s), buf);
+    if (len > -1 && (d = heim_data_ref_create(buf, len, free)))
+        return d;
     free(buf);
     if (error)
        *error = heim_error_create_enomem();
index 8d73846b2bbbb345d96b0bd723f2946765112fc8..86be109ffc5e7a273b21588e476a1ea408b76983 100644 (file)
@@ -47,7 +47,7 @@ struct heim_dict_data {
     struct hashentry **tab;
 };
 
-static void
+static void HEIM_CALLCONV
 dict_dealloc(void *ptr)
 {
     heim_dict_t dict = ptr;
@@ -115,6 +115,8 @@ heim_dict_create(size_t size)
     heim_dict_t dict;
 
     dict = _heim_alloc_object(&dict_object, sizeof(*dict));
+    if (dict == NULL)
+        return NULL;
 
     dict->size = findprime(size);
     if (dict->size == 0) {
@@ -149,7 +151,7 @@ heim_dict_get_type_id(void)
 static struct hashentry *
 _search(heim_dict_t dict, heim_object_t ptr)
 {
-    unsigned long v = heim_get_hash(ptr);
+    uintptr_t v = heim_get_hash(ptr);
     struct hashentry *p;
 
     for (p = dict->tab[v % dict->size]; p != NULL; p = p->next)
@@ -219,7 +221,7 @@ heim_dict_set_value(heim_dict_t dict, heim_object_t key, heim_object_t value)
        heim_release(h->value);
        h->value = heim_retain(value);
     } else {
-       unsigned long v;
+       uintptr_t v;
 
        h = malloc(sizeof(*h));
        if (h == NULL)
index 31017a01191b038afc172672fb483051005b2a49..59c39137b72779101ee09b5e0a3ba259b7a2d575 100644 (file)
@@ -83,7 +83,8 @@ struct tls_values {
 
 static HEIMDAL_THREAD_LOCAL struct tls_values values;
 
-#define DEAD_KEY ((void *)8)
+static char dead_key;
+#define DEAD_KEY ((void *)&dead_key)
 
 void
 heim_w32_service_thread_detach(void *unused)
index 8ae65de4981ef887dd96fcbbc782ab34f83d3e89..6ba3bea412db6554b3115cd782bd918bb6167c0b 100644 (file)
@@ -41,7 +41,7 @@ struct heim_error {
     struct heim_error *next;
 };
 
-static void
+static void HEIM_CALLCONV
 error_dealloc(void *ptr)
 {
     struct heim_error *p = ptr;
@@ -58,7 +58,7 @@ error_cmp(void *a, void *b)
     return heim_cmp(ap->msg, bp->msg);
 }
 
-static unsigned long
+static uintptr_t
 error_hash(void *ptr)
 {
     struct heim_error *p = ptr;
index 5c787ba2ce5157ca152bddab07bdeaea0af7f681..a562833a91a00080cc9cb844fdd69241e0b0cbfa 100644 (file)
@@ -39,6 +39,8 @@
 void
 heim_clear_error_message(heim_context context)
 {
+    if (!context)
+        return;
     if (context->error_string)
         free(context->error_string);
     context->error_code = 0;
@@ -53,7 +55,8 @@ heim_set_error_message(heim_context context, heim_error_code ret,
     va_list ap;
 
     va_start(ap, fmt);
-    heim_vset_error_message(context, ret, fmt, ap);
+    if (context)
+        heim_vset_error_message(context, ret, fmt, ap);
     va_end(ap);
 }
 
@@ -164,7 +167,7 @@ heim_get_error_string(heim_context context)
 int
 heim_have_error_string(heim_context context)
 {
-    return context->error_string != NULL;
+    return context && context->error_string != NULL;
 }
 
 void
index df382b99887d931c73fab67d56d360f754247b40..cf249917e8feb8a001a53913ee6c51cd0a940ffd 100644 (file)
@@ -59,10 +59,9 @@ expand_temp_folder(heim_context context, PTYPE param, const char *postfix,
     size_t len;
 
     if (!GetTempPath(sizeof(tpath)/sizeof(tpath[0]), tpath)) {
-        if (context)
-            heim_set_error_message(context, EINVAL,
-                                   "Failed to get temporary path (GLE=%d)",
-                                   GetLastError());
+        heim_set_error_message(context, EINVAL,
+                               "Failed to get temporary path (GLE=%d)",
+                               GetLastError());
         return EINVAL;
     }
 
@@ -170,55 +169,52 @@ expand_userid(heim_context context, PTYPE param, const char *postfix,
         }
 
         if (le != 0) {
-            if (context)
-                heim_set_error_message(context, rv,
-                                       "Can't open thread token (GLE=%d)", le);
+            heim_set_error_message(context, rv,
+                                   "Can't open thread token (GLE=%d)", le);
             goto _exit;
         }
     }
 
     if (!GetTokenInformation(hToken, TokenOwner, NULL, 0, &len)) {
         if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
-            if (context)
-                heim_set_error_message(context, rv,
-                                       "Unexpected error reading token information (GLE=%d)",
-                                       GetLastError());
+            heim_set_error_message(context, rv,
+                                   "Unexpected error reading token information (GLE=%d)",
+                                   GetLastError());
             goto _exit;
         }
 
         if (len == 0) {
-            if (context)
-                heim_set_error_message(context, rv,
-                                      "GetTokenInformation() returned truncated buffer");
+            heim_set_error_message(context, rv,
+                                   "GetTokenInformation() returned truncated buffer");
             goto _exit;
         }
 
         pOwner = malloc(len);
         if (pOwner == NULL) {
-            if (context)
-                heim_set_error_message(context, rv, "Out of memory");
+            heim_set_error_message(context, rv, "Out of memory");
             goto _exit;
         }
     } else {
-        if (context)
-            heim_set_error_message(context, rv, "GetTokenInformation() returned truncated buffer");
+        heim_set_error_message(context, rv, "GetTokenInformation() returned truncated buffer");
         goto _exit;
     }
 
     if (!GetTokenInformation(hToken, TokenOwner, pOwner, len, &len)) {
-        if (context)
-            heim_set_error_message(context, rv, "GetTokenInformation() failed. GLE=%d", GetLastError());
+        heim_set_error_message(context, rv,
+                               "GetTokenInformation() failed. GLE=%d",
+                               GetLastError());
         goto _exit;
     }
 
     if (!ConvertSidToStringSid(pOwner->Owner, &strSid)) {
-        if (context)
-            heim_set_error_message(context, rv, "Can't convert SID to string. GLE=%d", GetLastError());
+        heim_set_error_message(context, rv,
+                               "Can't convert SID to string. GLE=%d",
+                               GetLastError());
         goto _exit;
     }
 
     *ret = strdup(strSid);
-    if (*ret == NULL && context)
+    if (*ret == NULL)
         heim_set_error_message(context, rv, "Out of memory");
 
     rv = 0;
@@ -248,8 +244,7 @@ expand_csidl(heim_context context, PTYPE folder, const char *postfix,
     size_t len;
 
     if (SHGetFolderPath(NULL, folder, NULL, SHGFP_TYPE_CURRENT, path) != S_OK) {
-        if (context)
-            heim_set_error_message(context, EINVAL, "Unable to determine folder path");
+        heim_set_error_message(context, EINVAL, "Unable to determine folder path");
         return EINVAL;
     }
 
@@ -387,7 +382,7 @@ expand_strftime(heim_context context, PTYPE param, const char *postfix,
     t = time(NULL);
     len = strftime(buf, sizeof(buf), arg, localtime(&t));
     if (len == 0 || len >= sizeof(buf))
-        return ENOMEM;
+        return heim_enomem(context);
     *ret = strdup(buf);
     return 0;
 }
@@ -488,8 +483,7 @@ expand_token(heim_context context,
 
     if (token[0] != '%' || token[1] != '{' || token_end[0] != '}' ||
         token_end - token <= 2) {
-        if (context)
-            heim_set_error_message(context, EINVAL,"Invalid token.");
+        heim_set_error_message(context, EINVAL,"Invalid token.");
         return EINVAL;
     }
 
@@ -521,8 +515,7 @@ expand_token(heim_context context,
             return errcode;
         }
 
-    if (context)
-        heim_set_error_message(context, EINVAL, "Invalid token.");
+    heim_set_error_message(context, EINVAL, "Invalid token.");
     return EINVAL;
 }
 
@@ -630,7 +623,6 @@ heim_expand_path_tokensv(heim_context context,
                 break;
             extra_tokens[i] = strdup(s);
             if (extra_tokens[i++] == NULL) {
-                va_end(ap);
                 free_extra_tokens(extra_tokens);
                 return heim_enomem(context);
             }
@@ -639,7 +631,6 @@ heim_expand_path_tokensv(heim_context context,
                 s = "";
             extra_tokens[i] = strdup(s);
             if (extra_tokens[i] == NULL) {
-                va_end(ap);
                 free_extra_tokens(extra_tokens);
                 return heim_enomem(context);
             }
@@ -667,8 +658,7 @@ heim_expand_path_tokensv(heim_context context,
                 if (*ppath_out)
                     free(*ppath_out);
                 *ppath_out = NULL;
-                if (context)
-                    heim_set_error_message(context, EINVAL, "variable missing }");
+                heim_set_error_message(context, EINVAL, "variable missing }");
                 return EINVAL;
             }
 
index 1f0abd622e5055e5e492106ef2a501fdd353fa29..083917fb806aec02d5e2bde50a4563ccaa814c38 100644 (file)
@@ -36,6 +36,8 @@
 #ifndef HEIMBASE_SVC_H
 #define HEIMBASE_SVC_H 1
 
+#include <heimbase.h>
+
 /*
  * This file is meant to be included in services, which can
  *
@@ -68,7 +70,9 @@
     const char *e_text;                                         \
     char *e_text_buf;                                           \
     heim_string_t reason;                                       \
-    heim_array_t kv;                                            \
-    int32_t ret
+    /* auditing key/value store */                              \
+    heim_dict_t kv;                                             \
+    heim_dict_t attributes;                                     \
+    int32_t error_code
 
 #endif /* HEIMBASE_SVC_H */
index 8aacdb9187d25f8ea811096a19ea8f84e0653d99..1e6805a25e7f397644220afb384a4dcb6b401948 100644 (file)
@@ -53,7 +53,7 @@ struct heim_base_mem {
     HEIM_TAILQ_ENTRY(heim_base) autorel;
     heim_auto_release_t autorelpool;
     const char *name;
-    void (*dealloc)(void *);
+    void (HEIM_CALLCONV *dealloc)(void *);
     uintptr_t isaextra[1];
 };
 
@@ -83,10 +83,10 @@ struct heim_auto_release {
  * @return the same object as passed in
  */
 
-void *
-heim_retain(void *ptr)
+heim_object_t
+heim_retain(heim_object_t ptr)
 {
-    struct heim_base *p = NULL;
+    struct heim_base *p;
 
     if (ptr == NULL || heim_base_is_tagged(ptr))
        return ptr;
@@ -111,7 +111,7 @@ void
 heim_release(void *ptr)
 {
     heim_base_atomic_integer_type old;
-    struct heim_base *p = NULL;
+    struct heim_base *p;
 
     if (ptr == NULL || heim_base_is_tagged(ptr))
        return;
@@ -214,13 +214,13 @@ heim_get_tid(heim_object_t ptr)
  * @return a hash value
  */
 
-unsigned long
+uintptr_t
 heim_get_hash(heim_object_t ptr)
 {
     heim_type_t isa = _heim_get_isa(ptr);
     if (isa->hash)
        return isa->hash(ptr);
-    return (unsigned long)ptr;
+    return (uintptr_t)ptr;
 }
 
 /**
@@ -257,7 +257,7 @@ heim_cmp(heim_object_t a, heim_object_t b)
  * Private - allocates an memory object
  */
 
-static void
+static void HEIM_CALLCONV
 memory_dealloc(void *ptr)
 {
     struct heim_base_mem *p = (struct heim_base_mem *)PTR2BASE(ptr);
@@ -346,7 +346,7 @@ _heim_alloc_object(heim_type_t type, size_t size)
 void *
 _heim_get_isaextra(heim_object_t ptr, size_t idx)
 {
-    struct heim_base *p = NULL;
+    struct heim_base *p;
 
     heim_assert(ptr != NULL, "internal error");
     p = (struct heim_base *)PTR2BASE(ptr);
@@ -585,7 +585,7 @@ autorel_tls(void)
 
 }
 
-static void
+static void HEIM_CALLCONV
 autorel_dealloc(void *ptr)
 {
     heim_auto_release_t ar = ptr;
@@ -614,10 +614,10 @@ autorel_cmp(void *a, void *b)
     return (a == b);
 }
 
-static unsigned long
+static uintptr_t
 autorel_hash(void *ptr)
 {
-    return (unsigned long)ptr;
+    return (uintptr_t)ptr;
 }
 
 
@@ -671,7 +671,7 @@ heim_auto_release_create(void)
 heim_object_t
 heim_auto_release(heim_object_t ptr)
 {
-    struct heim_base *p = NULL;
+    struct heim_base *p;
     struct ar_tls *tls = autorel_tls();
     heim_auto_release_t ar;
 
@@ -763,9 +763,10 @@ heim_path_vget2(heim_object_t ptr, heim_object_t *parent, heim_object_t *key,
            next_node = heim_dict_get_value(node, path_element);
        } else if (node_type == HEIM_TID_DB) {
            next_node = _heim_db_get_value(node, NULL, path_element, NULL);
-       } else if (node_type == HEIM_TID_ARRAY) {
+       } else {
            int idx = -1;
 
+            /* node_type == HEIM_TID_ARRAY */
            if (heim_get_tid(path_element) == HEIM_TID_NUMBER)
                idx = heim_number_get_int(path_element);
            if (idx < 0) {
@@ -777,12 +778,6 @@ heim_path_vget2(heim_object_t ptr, heim_object_t *parent, heim_object_t *key,
                return NULL;
            }
            next_node = heim_array_get_value(node, idx);
-       } else {
-           if (error)
-               *error = heim_error_create(EINVAL,
-                                          "heim_path_get() node in path "
-                                          "not a container type");
-           return NULL;
        }
        node = next_node;
     }
index c0c94e2649b27e68fb492bdf50725cce48edf2aa..3706fc8710d2f1b3a7b2a3fe9dac0ce3e096f89c 100644 (file)
@@ -168,12 +168,12 @@ typedef long heim_base_once_t; /* XXX arch dependant */
 #endif
 
 
-void * heim_retain(heim_object_t);
+heim_object_t  heim_retain(heim_object_t);
 void   heim_release(heim_object_t);
 
 void   heim_show(heim_object_t);
 
-typedef void (*heim_type_dealloc)(void *);
+typedef void (HEIM_CALLCONV *heim_type_dealloc)(void *);
 
 void *
 heim_alloc(size_t size, const char *name, heim_type_dealloc dealloc);
@@ -184,7 +184,7 @@ heim_get_tid(heim_object_t object);
 int
 heim_cmp(heim_object_t a, heim_object_t b);
 
-unsigned long
+uintptr_t
 heim_get_hash(heim_object_t ptr);
 
 void
@@ -436,9 +436,10 @@ void    heim_db_iterate(heim_db_t, heim_string_t,
 
 typedef struct heim_number_data *heim_number_t;
 
-heim_number_t heim_number_create(int);
+heim_number_t heim_number_create(int64_t);
 heim_tid_t heim_number_get_type_id(void);
 int heim_number_get_int(heim_number_t);
+int64_t heim_number_get_long(heim_number_t);
 
 /*
  *
index 8f8fad0fc8c34956eacfd819495647e09daf6adf..b9f63e56b6a136b768dbcb6c65654c9750a079ab 100644 (file)
@@ -42,7 +42,7 @@
 typedef void (*heim_type_init)(void *);
 typedef heim_object_t (*heim_type_copy)(void *);
 typedef int (*heim_type_cmp)(void *, void *);
-typedef unsigned long (*heim_type_hash)(void *);
+typedef uintptr_t (*heim_type_hash)(void *);
 typedef heim_string_t (*heim_type_description)(void *);
 
 typedef struct heim_type_data *heim_type_t;
@@ -65,6 +65,7 @@ enum {
     HEIM_TID_DATA = 134,
     HEIM_TID_DB = 135,
     HEIM_TID_PA_AUTH_MECH = 136,
+    HEIM_TID_PAC = 137,
     HEIM_TID_USER = 255
 
 };
index 904d0c3ba1243265d97747f1515010aff6dddd81..818ac8398d53a9ae5ec287f0321ad0ebce00ecf3 100644 (file)
@@ -40,6 +40,7 @@
 #include <assert.h>
 #include <stdarg.h>
 #include <vis.h>
+#include <base64.h>
 
 struct heim_log_facility_internal {
     int min;
@@ -204,10 +205,13 @@ open_syslog(heim_context context,
             heim_log_facility *facility, int min, int max,
             const char *sev, const char *fac)
 {
-    struct _heimdal_syslog_data *sd = malloc(sizeof(*sd));
+    struct _heimdal_syslog_data *sd;
+    heim_error_code ret;
     int i;
 
-    if (sd == NULL)
+    if (facility == NULL)
+        return EINVAL;
+    if ((sd = calloc(1, sizeof(*sd))) == NULL)
         return heim_enomem(context);
     i = find_value(sev, syslogvals);
     if (i == -1)
@@ -218,8 +222,11 @@ open_syslog(heim_context context,
         i = LOG_AUTH;
     sd->priority |= i;
     roken_openlog(facility->program, LOG_PID | LOG_NDELAY, i);
-    return heim_addlog_func(context, facility, min, max,
-                            log_syslog, close_syslog, sd);
+    ret = heim_addlog_func(context, facility, min, max, log_syslog,
+                           close_syslog, sd);
+    if (ret)
+        free(sd);
+    return ret;
 }
 
 struct file_data {
@@ -247,7 +254,7 @@ log_file(heim_context context, const char *timestr, const char *msg, void *data)
     size_t i = 0;
     size_t j;
 
-    if (logf == NULL || (f->disp & FILEDISP_REOPEN)) {
+    if (f->filename && (logf == NULL || (f->disp & FILEDISP_REOPEN))) {
         int flags = O_WRONLY|O_APPEND;
         int fd;
 
@@ -338,9 +345,9 @@ open_file(heim_context context, heim_log_facility *fac, int min, int max,
     if (ret) {
         free(fd->filename);
         free(fd);
-    }
-    if (disp & FILEDISP_KEEPOPEN)
+    } else if (disp & FILEDISP_KEEPOPEN) {
         log_file(context, NULL, NULL, fd);
+    }
     return ret;
 }
 
@@ -384,7 +391,7 @@ heim_addlog_dest(heim_context context, heim_log_facility *f, const char *orig)
         p++;
     }
     if (strcmp(p, "STDERR") == 0) {
-        ret = open_file(context, f, min, max, NULL, NULL, stderr,
+        ret = open_file(context, f, min, max, NULL, "a", stderr,
                         FILEDISP_KEEPOPEN, 0);
     } else if (strcmp(p, "CONSOLE") == 0) {
         /* XXX WIN32 */
@@ -608,10 +615,7 @@ __attribute__ ((__format__ (__printf__, 3, 0)))
 heim_error_code
 heim_have_debug(heim_context context, int level)
 {
-    heim_log_facility *fac;
-
-    return (context != NULL &&
-        (fac = heim_get_debug_dest(context)) != NULL);
+    return (context != NULL && heim_get_debug_dest(context) != NULL);
 }
 
 heim_error_code
@@ -655,32 +659,34 @@ heim_add_debug_dest(heim_context context, const char *program,
     return 0;
 }
 
-static heim_string_t
+struct heim_audit_kv_tuple {
+    heim_string_t key;
+    heim_object_t value;
+};
+
+static struct heim_audit_kv_tuple zero_tuple;
+
+static struct heim_audit_kv_tuple
 fmtkv(int flags, const char *k, const char *fmt, va_list ap)
         __attribute__ ((__format__ (__printf__, 3, 0)))
 {
-    heim_string_t str;
     size_t i;
     ssize_t j;
-    char *buf1;
-    char *buf2;
-    char *buf3;
-    int ret = vasprintf(&buf1, fmt, ap);
-    if (ret < 0 || !buf1)
-       return NULL;;
-
-    j = asprintf(&buf2, "%s=%s", k, buf1);
-    free(buf1);
-    if (j < 0 || !buf2)
-       return NULL;;
+    struct heim_audit_kv_tuple kv;
+    char *value;
+    char *value_vis;
+
+    j = vasprintf(&value, fmt, ap);
+    if (j < 0 || value == NULL)
+       return zero_tuple;
 
     /* We optionally eat the whitespace. */
 
     if (flags & HEIM_SVC_AUDIT_EATWHITE) {
-       for (i=0, j=0; buf2[i]; i++)
-           if (buf2[i] != ' ' && buf2[i] != '\t')
-               buf2[j++] = buf2[i];
-       buf2[j] = '\0';
+       for (i=0, j=0; value[i]; i++)
+           if (value[i] != ' ' && value[i] != '\t')
+               value[j++] = value[i];
+       value[j] = '\0';
     }
 
     if (flags & (HEIM_SVC_AUDIT_VIS | HEIM_SVC_AUDIT_VISLAST)) {
@@ -688,48 +694,52 @@ fmtkv(int flags, const char *k, const char *fmt, va_list ap)
 
         if (flags & HEIM_SVC_AUDIT_VIS)
             vis_flags |= VIS_WHITE;
-       buf3 = malloc((j + 1) * 4 + 1);
-        if (buf3)
-            strvisx(buf3, buf2, j, vis_flags);
-       free(buf2);
-        if (buf3 == NULL)
-            return NULL;
+       value_vis = malloc((j + 1) * 4 + 1);
+        if (value_vis)
+            strvisx(value_vis, value, j, vis_flags);
+       free(value);
+        if (value_vis == NULL)
+            return zero_tuple;
     } else
-       buf3 = buf2;
+       value_vis = value;
 
-    str = heim_string_create(buf3);
-    free(buf3);
-    return str;
+    if (k)
+       kv.key = heim_string_create(k);
+    else
+       kv.key = NULL;
+    kv.value = heim_string_ref_create(value_vis, free);
+
+    return kv;
 }
 
 void
 heim_audit_vaddreason(heim_svc_req_desc r, const char *fmt, va_list ap)
        __attribute__ ((__format__ (__printf__, 2, 0)))
 {
-    heim_string_t str;
+    struct heim_audit_kv_tuple kv;
 
-    str = fmtkv(HEIM_SVC_AUDIT_VISLAST, "reason", fmt, ap);
-    if (!str) {
+    kv = fmtkv(HEIM_SVC_AUDIT_VISLAST, NULL, fmt, ap);
+    if (kv.value == NULL) {
         heim_log(r->hcontext, r->logf, 1, "heim_audit_vaddreason: "
                  "failed to add reason (out of memory)");
         return;
     }
 
     heim_log(r->hcontext, r->logf, 7, "heim_audit_vaddreason(): "
-             "adding reason %s", heim_string_get_utf8(str));
+             "adding reason %s", heim_string_get_utf8(kv.value));
     if (r->reason) {
         heim_string_t str2;
 
         str2 = heim_string_create_with_format("%s: %s",
-                                              heim_string_get_utf8(str),
+                                              heim_string_get_utf8(kv.value),
                                               heim_string_get_utf8(r->reason));
         if (str2) {
-            heim_release(str);
-            str = str2;
+            heim_release(kv.value);
+            kv.value = str2;
         }
     }
     heim_release(r->reason);
-    r->reason = str;
+    r->reason = kv.value;
 }
 
 void
@@ -743,10 +753,37 @@ heim_audit_addreason(heim_svc_req_desc r, const char *fmt, ...)
     va_end(ap);
 }
 
+size_t
+addkv(heim_svc_req_desc r, heim_object_t key, heim_object_t value)
+{
+    size_t index;
+    heim_object_t obj;
+
+    obj = heim_dict_get_value(r->kv, key);
+    if (obj) {
+       if (heim_get_tid(obj) == HEIM_TID_ARRAY) {
+           index = heim_array_get_length(obj);
+           heim_array_append_value(obj, value);
+       } else {
+           heim_array_t array = heim_array_create();
+
+           index = 1;
+           heim_array_append_value(array, obj);
+           heim_array_append_value(array, value);
+           heim_dict_set_value(r->kv, key, array);
+           heim_release(array); /* retained by r->kv */
+       }
+    } else {
+       index = 0;
+       heim_dict_set_value(r->kv, key, value);
+    }
+
+    return index;
+}
+
 /*
- * append_token adds a token which is optionally a kv-pair and it
- * also optionally eats the whitespace.  If k == NULL, then it's
- * not a kv-pair.
+ * add a key-value token. if the key already exists, the value is
+ * promoted to an array of values.
  */
 
 void
@@ -754,19 +791,26 @@ heim_audit_vaddkv(heim_svc_req_desc r, int flags, const char *k,
                  const char *fmt, va_list ap)
        __attribute__ ((__format__ (__printf__, 4, 0)))
 {
-    heim_string_t str;
+    struct heim_audit_kv_tuple kv;
+    size_t index;
 
-    str = fmtkv(flags, k, fmt, ap);
-    if (!str) {
+    kv = fmtkv(flags, k, fmt, ap);
+    if (kv.key == NULL || kv.value == NULL) {
         heim_log(r->hcontext, r->logf, 1, "heim_audit_vaddkv: "
                  "failed to add kv pair (out of memory)");
+       heim_release(kv.key);
+       heim_release(kv.value);
         return;
     }
 
+    index = addkv(r, kv.key, kv.value);
+
     heim_log(r->hcontext, r->logf, 7, "heim_audit_vaddkv(): "
-             "adding kv pair %s", heim_string_get_utf8(str));
-    heim_array_append_value(r->kv, str);
-    heim_release(str);
+             "kv pair[%zu] %s=%s", index,
+            heim_string_get_utf8(kv.key), heim_string_get_utf8(kv.value));
+
+    heim_release(kv.key);
+    heim_release(kv.value);
 }
 
 void
@@ -808,19 +852,197 @@ heim_audit_addkv_timediff(heim_svc_req_desc r, const char *k,
     heim_audit_addkv(r, 0, k, "%s%ld.%06d", sign, sec, usec);
 }
 
+void
+heim_audit_setkv_bool(heim_svc_req_desc r, const char *k, int v)
+{
+    heim_string_t key = heim_string_create(k);
+    heim_number_t value;
+
+    if (key == NULL)
+       return;
+
+    heim_log(r->hcontext, r->logf, 7, "heim_audit_setkv_bool(): "
+            "setting kv pair %s=%s", k, v ? "true" : "false");
+
+    value = heim_bool_create(v);
+    heim_dict_set_value(r->kv, key, value);
+    heim_release(key);
+    heim_release(value);
+}
+
+void
+heim_audit_addkv_number(heim_svc_req_desc r, const char *k, int64_t v)
+{
+    heim_string_t key = heim_string_create(k);
+    heim_number_t value;
+
+    if (key == NULL)
+       return;
+
+    heim_log(r->hcontext, r->logf, 7, "heim_audit_addkv_number(): "
+            "adding kv pair %s=%lld", k, (long long)v);
+
+    value = heim_number_create(v);
+    addkv(r, key, value);
+    heim_release(key);
+    heim_release(value);
+}
+
+void
+heim_audit_setkv_number(heim_svc_req_desc r, const char *k, int64_t v)
+{
+    heim_string_t key = heim_string_create(k);
+    heim_number_t value;
+
+    if (key == NULL)
+       return;
+
+    heim_log(r->hcontext, r->logf, 7, "heim_audit_setkv_number(): "
+            "setting kv pair %s=%lld", k, (long long)v);
+
+    value = heim_number_create(v);
+    heim_dict_set_value(r->kv, key, value);
+    heim_release(key);
+    heim_release(value);
+}
+
+void
+heim_audit_addkv_object(heim_svc_req_desc r, const char *k, heim_object_t value)
+{
+    heim_string_t key = heim_string_create(k);
+    heim_string_t descr;
+
+    if (key == NULL)
+       return;
+
+    descr = heim_json_copy_serialize(value, HEIM_JSON_F_NO_DATA_DICT, NULL);
+    heim_log(r->hcontext, r->logf, 7, "heim_audit_addkv_object(): "
+            "adding kv pair %s=%s",
+            k, descr ? heim_string_get_utf8(descr) : "<unprintable>");
+    addkv(r, key, value);
+    heim_release(key);
+    heim_release(descr);
+}
+
+void
+heim_audit_setkv_object(heim_svc_req_desc r, const char *k, heim_object_t value)
+{
+    heim_string_t key = heim_string_create(k);
+    heim_string_t descr;
+
+    if (key == NULL)
+       return;
+
+    descr = heim_json_copy_serialize(value, HEIM_JSON_F_NO_DATA_DICT, NULL);
+    heim_log(r->hcontext, r->logf, 7, "heim_audit_setkv_object(): "
+            "setting kv pair %s=%s",
+            k, descr ? heim_string_get_utf8(descr) : "<unprintable>");
+    heim_dict_set_value(r->kv, key, value);
+    heim_release(key);
+    heim_release(descr);
+}
+
+heim_object_t
+heim_audit_getkv(heim_svc_req_desc r, const char *k)
+{
+    heim_string_t key;
+    heim_object_t value;
+
+    key = heim_string_create(k);
+    if (key == NULL)
+       return NULL;
+
+    value = heim_dict_get_value(r->kv, key);
+    heim_release(key);
+    return value;
+}
+
+struct heim_audit_kv_buf {
+    char buf[1024];
+    size_t pos;
+    heim_object_t iter;
+};
+
+static void
+audit_trail_iterator(heim_object_t key, heim_object_t value, void *arg);
+
+static void
+audit_trail_iterator_array(heim_object_t value, void *arg, int *stop)
+{
+    struct heim_audit_kv_buf *kvb = arg;
+
+    audit_trail_iterator(kvb->iter, value, kvb);
+}
+
+static void
+audit_trail_iterator(heim_object_t key, heim_object_t value, void *arg)
+{
+    struct heim_audit_kv_buf *kvb = arg;
+    char num[32];
+    const char *k = heim_string_get_utf8(key), *v = NULL;
+    char *b64 = NULL;
+
+    if (k == NULL || *k == '#') /* # keys are hidden */
+       return;
+
+    switch (heim_get_tid(value)) {
+    case HEIM_TID_STRING:
+       v = heim_string_get_utf8(value);
+       break;
+    case HEIM_TID_NUMBER:
+       snprintf(num, sizeof(num), "%lld", (long long)heim_number_get_long(value));
+       v = num;
+       break;
+    case HEIM_TID_NULL:
+       v = "null";
+       break;
+    case HEIM_TID_BOOL:
+       v = heim_bool_val(value) ? "true" : "false";
+       break;
+    case HEIM_TID_ARRAY:
+       if (kvb->iter)
+           break; /* arrays cannot be nested */
+
+       kvb->iter = key;
+       heim_array_iterate_f(value, kvb, audit_trail_iterator_array);
+       kvb->iter = NULL;
+       break;
+    case HEIM_TID_DATA: {
+       const heim_octet_string *data = heim_data_get_data(value);
+       if (rk_base64_encode(data->data, data->length, &b64) >= 0)
+           v = b64;
+       break;
+    }
+    default:
+       break;
+    }
+
+    if (v == NULL)
+       return;
+
+    if (kvb->pos < sizeof(kvb->buf) - 1)
+       kvb->buf[kvb->pos++] = ' ';
+    for (; *k && kvb->pos < sizeof(kvb->buf) - 1; kvb->pos++)
+       kvb->buf[kvb->pos] = *k++;
+    if (kvb->pos < sizeof(kvb->buf) - 1)
+       kvb->buf[kvb->pos++] = '=';
+    for (; *v && kvb->pos < sizeof(kvb->buf) - 1; kvb->pos++)
+       kvb->buf[kvb->pos] = *v++;
+
+    free(b64);
+}
+
 void
 heim_audit_trail(heim_svc_req_desc r, heim_error_code ret, const char *retname)
 {
     const char *retval;
-    char kvbuf[1024];
+    struct heim_audit_kv_buf kvb;
     char retvalbuf[30]; /* Enough for UNKNOWN-%d */
-    size_t nelem;
-    size_t i, j;
 
 #define CASE(x)        case x : retval = #x; break
     if (retname) {
         retval = retname;
-    } else switch (ret ? ret : r->ret) {
+    } else switch (ret ? ret : r->error_code) {
     CASE(ENOMEM);
     CASE(ENOENT);
     CASE(EACCES);
@@ -838,26 +1060,15 @@ heim_audit_trail(heim_svc_req_desc r, heim_error_code ret, const char *retname)
     if (r->e_text && r->kv)
        heim_audit_addkv(r, HEIM_SVC_AUDIT_VIS, "e-text", "%s", r->e_text);
 
-    nelem = r->kv ? heim_array_get_length(r->kv) : 0;
-    for (i=0, j=0; i < nelem; i++) {
-       heim_string_t s;
-       const char *kvpair;
-
-        /* We know these are strings... */
-       s = heim_array_get_value(r->kv, i);
-       kvpair = heim_string_get_utf8(s);
-
-       if (j < sizeof(kvbuf) - 1)
-           kvbuf[j++] = ' ';
-       for (; *kvpair && j < sizeof(kvbuf) - 1; j++)
-           kvbuf[j] = *kvpair++;
-    }
-    kvbuf[j] = '\0';
+    memset(&kvb, 0, sizeof(kvb));
+    if (r->kv)
+        heim_dict_iterate_f(r->kv, &kvb, audit_trail_iterator);
+    kvb.buf[kvb.pos] = '\0';
 
     heim_log(r->hcontext, r->logf, 3, "%s %s %s %s %s%s%s%s",
              r->reqtype, retval, r->from,
              r->cname ? r->cname : "<unknown>",
              r->sname ? r->sname : "<unknown>",
-             kvbuf, r->reason ? " " : "",
+             kvb.buf, r->reason ? " reason=" : "",
              r->reason ? heim_string_get_utf8(r->reason) : "");
 }
index c259f69971d0fb7ddc2fcf1db3b9cc5505326559..8833c8b15233136292a42a0ccf2cc5f7f3fe3126 100644 (file)
@@ -35,7 +35,7 @@
 
 #include "baselocl.h"
 
-static void
+static void HEIM_CALLCONV
 number_dealloc(void *ptr)
 {
 }
@@ -58,12 +58,12 @@ number_cmp(void *a, void *b)
     return na - nb;
 }
 
-static unsigned long
+static uintptr_t
 number_hash(void *ptr)
 {
     if (heim_base_is_tagged_object(ptr))
        return heim_base_tagged_object_value(ptr);
-    return (unsigned long)*(int *)ptr;
+    return (uintptr_t)*(int64_t *)ptr;
 }
 
 struct heim_type_data _heim_number_object = {
@@ -86,16 +86,16 @@ struct heim_type_data _heim_number_object = {
  */
 
 heim_number_t
-heim_number_create(int number)
+heim_number_create(int64_t number)
 {
     heim_number_t n;
 
     if (number < 0xffffff && number >= 0)
        return heim_base_make_tagged_object(number, HEIM_TID_NUMBER);
 
-    n = _heim_alloc_object(&_heim_number_object, sizeof(int));
+    n = _heim_alloc_object(&_heim_number_object, sizeof(int64_t));
     if (n)
-       *((int *)n) = number;
+       *((int64_t *)n) = number;
     return n;
 }
 
@@ -124,5 +124,13 @@ heim_number_get_int(heim_number_t number)
 {
     if (heim_base_is_tagged_object(number))
        return heim_base_tagged_object_value(number);
-    return *(int *)number;
+    return (int)(*(int64_t *)number);
+}
+
+int64_t
+heim_number_get_long(heim_number_t number)
+{
+    if (heim_base_is_tagged_object(number))
+       return heim_base_tagged_object_value(number);
+    return *(int64_t *)number;
 }
index df225a939c2502e1992f7cb363719f0239df2094..631a3386c831cb74bca1ceac5a956ff14fc07c2c 100644 (file)
@@ -112,7 +112,7 @@ struct heim_dso {
     void *dsohandle;
 };
 
-static void
+static void HEIM_CALLCONV
 dso_dealloc(void *ptr)
 {
     struct heim_dso *p = ptr;
@@ -156,7 +156,7 @@ struct heim_plugin {
     void *ctx;
 };
 
-static void
+static void HEIM_CALLCONV
 plugin_free(void *ptr)
 {
     struct heim_plugin *pl = ptr;
@@ -590,34 +590,37 @@ add_dso_plugins_load_fn(heim_context context,
     heim_error_code ret;
     heim_array_t plugins;
     heim_plugin_load_t load_fn;
-    char *sym;
+    char *sym = NULL;
     size_t i;
     heim_get_instance_func_t get_instance;
     size_t n_ftables;
     heim_plugin_common_ftable_cp *ftables;
 
-    if (asprintf(&sym, "%s_plugin_load", caller->name) == -1)
+    if (asprintf(&sym, "%s_plugin_load", caller->name) == -1 || sym == NULL)
         return NULL;
 
     /* suppress error here because we may be looking for a different plugin type */
     load_fn = (heim_plugin_load_t)dlsym(dsohandle, sym);
-    free(sym);
     if (load_fn == NULL) {
         heim_debug(context, 15, "Symbol %s not found in %s", sym, dsopath);
+        free(sym);
         return NULL;
     }
 
     ret = load_fn(pcontext, &get_instance, &n_ftables, &ftables);
     if (ret) {
         heim_warn(context, ret, "plugin %s failed to load", dsopath);
+        free(sym);
 
         /* fallback to loading structure directly */
         return add_dso_plugin_struct(context, pcontext, dsopath,
                                      dsohandle, caller->name);
     }
 
-    if (!validate_plugin_deps(context, caller, dsopath, get_instance))
+    if (!validate_plugin_deps(context, caller, dsopath, get_instance)) {
+        free(sym);
         return NULL;
+    }
 
     plugins = heim_array_create();
 
@@ -639,6 +642,7 @@ add_dso_plugins_load_fn(heim_context context,
     }
 
     heim_debug(context, 15, "DSO %s loaded (%s)", dsopath, sym);
+    free(sym);
     return plugins;
 }
 #endif /* HAVE_DLOPEN */
index 5384998080a511f22998d94bef21933a462c433c..f942447163db434f3e15dcefdbd266d12bf49272 100644 (file)
@@ -36,7 +36,7 @@
 #include "baselocl.h"
 #include <string.h>
 
-static void
+static void HEIM_CALLCONV
 string_dealloc(void *ptr)
 {
     heim_string_t s = ptr;
@@ -73,11 +73,11 @@ string_cmp(void *a, void *b)
     return strcmp(a, b);
 }
 
-static unsigned long
+static uintptr_t
 string_hash(void *ptr)
 {
     const char *s = ptr;
-    unsigned long n;
+    uintptr_t n;
 
     for (n = 0; *s; ++s)
        n += *s;
index fba675cf488eb4d9ce8ea9add83ce67e10b6c6f9..be6c860e26b9d201134dcda9b6176b8c5b889929 100644 (file)
@@ -64,7 +64,7 @@
 
 #include "baselocl.h"
 
-static void
+static void HEIM_CALLCONV
 memory_free(heim_object_t obj)
 {
 }
@@ -238,8 +238,8 @@ test_json(void)
        "{ \"k1\" : \"s1\", \"k2\" : \"s2\" }",
        "{ \"k1\" : [\"s1\", \"s2\", \"s3\"], \"k2\" : \"s3\" }",
        "{ \"k1\" : {\"k2\":\"s1\",\"k3\":\"s2\",\"k4\":\"s3\"}, \"k5\" : \"s4\" }",
-       "[ \"v1\", \"v2\", [\"v3\",\"v4\",[\"v 5\",\" v 7 \"]], -123456789, "
-           "null, true, false, 123456789, \"\"]",
+       ("[ \"v1\", \"v2\", [\"v3\",\"v4\",[\"v 5\",\" v 7 \"]], -123456789, "
+           "null, true, false, 123456789, \"\"]"),
        " -1"
     };
     char *s;
index 0cd0c8444cb76359562f430a61cb0d0fc41f1c17..928e86199955e899fb761c585a39310dad9c81c2 100644 (file)
@@ -29,8 +29,14 @@ HEIMDAL_BASE_1.0 {
                heim_array_iterate_reverse_f;
                heim_array_set_value;
                heim_audit_addkv;
+               heim_audit_addkv_number;
+               heim_audit_addkv_object;
                heim_audit_addkv_timediff;
+               heim_audit_setkv_bool;
+               heim_audit_setkv_number;
+               heim_audit_setkv_object;
                heim_audit_addreason;
+               heim_audit_getkv;
                heim_audit_trail;
                heim_audit_vaddkv;
                heim_audit_vaddreason;
@@ -147,6 +153,7 @@ HEIMDAL_BASE_1.0 {
                heim_null_create;
                heim_number_create;
                heim_number_get_int;
+               heim_number_get_long;
                heim_number_get_type_id;
                heim_openlog;
                heim_path_copy;
index 8c027c74da9f726e4a93d23d515d9f06d627346e..14e8e66fcdc6673083827f20bfc39259267c1a16 100644 (file)
@@ -2,7 +2,7 @@
 
 include $(top_srcdir)/Makefile.am.common
 
-YFLAGS = -d
+YFLAGS = -d -o parse.c
 LFLAGS = @FLEXNOUNPUTARGS@
 
 lib_LTLIBRARIES = libcom_err.la
index 1159e63c2a4622d1f791e8938eb10b6f2113ac78..de2d7b5cbe6da3eed9569803f6913c26aceb46fc 100644 (file)
@@ -95,9 +95,10 @@ pa_gss_step(krb5_context context,
     gss_name_t target_name = GSS_C_NO_NAME;
     OM_uint32 req_flags = GSS_C_MUTUAL_FLAG;
     OM_uint32 ret_flags;
-    struct gss_channel_bindings_struct cb = { 0 };
+    struct gss_channel_bindings_struct cb;
     gss_buffer_desc input_token, output_token = GSS_C_EMPTY_BUFFER;
 
+    memset(&cb, 0, sizeof(cb));
     krb5_data_zero(out);
 
     if (flags.request_anonymous)
index c2287ca707a7303dc4eb266eb187ac804e95fb14..00efde72d662ba97bb2c3b74e121068c859c3e3d 100644 (file)
@@ -64,11 +64,6 @@ _krb5_gss_map_error(OM_uint32 major, OM_uint32 minor)
         ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
         break;
     case GSS_S_FAILURE:
-        if (minor == (OM_uint32)KRB5KRB_AP_ERR_BAD_INTEGRITY ||
-            minor == (OM_uint32)HNTLM_ERR_AUTH) {
-            ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
-            break;
-        }
     default:
         ret = KRB5KDC_ERR_PREAUTH_FAILED;
         break;
index 744232e2e35b09c11b1d9d77092f99353dcebec6..a69ebffb04ecb246de7c0923287510619321d64e 100644 (file)
@@ -2,9 +2,12 @@
 
 include $(top_srcdir)/Makefile.am.common
 
+WFLAGS += $(WFLAGS_ENUM_CONV)
+
 AUTOMAKE_OPTIONS = subdir-objects
 
 AM_CPPFLAGS += \
+       -I$(top_srcdir)/lib \
        -I$(srcdir)/../krb5 \
        -I$(srcdir) \
        -I$(srcdir)/gssapi \
@@ -59,6 +62,7 @@ krb5src = \
        krb5/inquire_mechs_for_name.c \
        krb5/inquire_names_for_mech.c \
        krb5/inquire_sec_context_by_oid.c \
+       krb5/name_attrs.c \
        krb5/pname_to_uid.c \
        krb5/process_context_token.c \
        krb5/prf.c \
@@ -249,6 +253,7 @@ sanonsrc = \
        sanon/process_context_token.c \
        sanon/release_cred.c \
        sanon/release_name.c \
+       sanon/sanon_locl.h \
        sanon/sanon-private.h
 
 dist_libgssapi_la_SOURCES  = \
@@ -302,19 +307,20 @@ nobase_include_HEADERS = \
 gssapidir = $(includedir)/gssapi
 nodist_gssapi_HEADERS = gkrb5_err.h negoex_err.h
 
-gssapi_files = asn1_GSSAPIContextToken.x
+gssapi_files =                                         \
+       asn1_GSSAPIContextToken.c
 
 spnego_files =                                 \
-       asn1_ContextFlags.x                     \
-       asn1_MechType.x                         \
-       asn1_MechTypeList.x                     \
-       asn1_NegotiationToken.x                 \
-       asn1_NegotiationToken2.x                \
-       asn1_NegHints.x                         \
-       asn1_NegTokenInit.x                     \
-       asn1_NegTokenInit2.x                    \
-       asn1_NegTokenResp.x                     \
-       asn1_NegStateEnum.x
+       asn1_ContextFlags.c                     \
+       asn1_MechType.c                         \
+       asn1_MechTypeList.c                     \
+       asn1_NegHints.c                         \
+       asn1_NegStateEnum.c                     \
+       asn1_NegTokenInit.c                     \
+       asn1_NegTokenInit2.c                    \
+       asn1_NegTokenResp.c                     \
+       asn1_NegotiationToken.c                 \
+       asn1_NegotiationToken2.c
 
 BUILTHEADERS = \
        $(srcdir)/krb5/gsskrb5-private.h \
@@ -327,7 +333,7 @@ $(test_context_OBJECTS): $(BUILTHEADERS)
 
 $(libgssapi_la_OBJECTS): $(srcdir)/version-script.map
 
-BUILT_SOURCES = $(spnego_files:.x=.c) $(gssapi_files:.x=.c)
+BUILT_SOURCES = $(spnego_files) $(gssapi_files)
 
 $(libgssapi_la_OBJECTS): gkrb5_err.h negoex_err.h
 gkrb5_err.h: $(srcdir)/krb5/gkrb5_err.et
@@ -337,16 +343,27 @@ CLEANFILES = $(BUILT_SOURCES) \
        gkrb5_err.[ch] negoex_err.[ch] \
        $(spnego_files) spnego_asn1*.h* spnego_asn1_files spnego_asn1-template.[cx] \
        $(gssapi_files) gssapi_asn1*.h* gssapi_asn1_files gssapi_asn1-template.[cx] \
-       gss-commands.h gss-commands.c
+       gss-commands.h gss-commands.c \
+       gssapi_asn1.json gssapi_asn1_oids.c gssapi_asn1_syms.c \
+       spnego_asn1.json spnego_asn1_oids.c spnego_asn1_syms.c
+
+$(spnego_files) spnego_asn1.h spnego_asn1-priv.h: spnego_asn1_files
+       for genfile in '$(spnego_files)'; do \
+               $(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i $${genfile}; \
+       done
 
-$(spnego_files) spnego_asn1.hx spnego_asn1-priv.hx: spnego_asn1_files
-$(gssapi_files) gssapi_asn1.hx gssapi_asn1-priv.hx: gssapi_asn1_files
+$(gssapi_files) gssapi_asn1.h gssapi_asn1-priv.h: gssapi_asn1_files
+       for genfile in '$(gssapi_files)'; do \
+               $(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i $${genfile}; \
+       done
 
 spnego_asn1_files: $(ASN1_COMPILE_DEP) $(srcdir)/spnego/spnego.asn1 $(srcdir)/spnego/spnego.opt
        $(ASN1_COMPILE) --option-file=$(srcdir)/spnego/spnego.opt $(srcdir)/spnego/spnego.asn1 spnego_asn1
+       @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i $$(cat spnego_asn1_files)
 
 gssapi_asn1_files: $(ASN1_COMPILE_DEP) $(srcdir)/mech/gssapi.asn1
        $(ASN1_COMPILE) $(srcdir)/mech/gssapi.asn1 gssapi_asn1
+       @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i $$(cat gssapi_asn1_files)
 
 $(srcdir)/krb5/gsskrb5-private.h:
        cd $(srcdir) && perl ../../cf/make-proto.pl -q -P comment -p krb5/gsskrb5-private.h $(krb5src) || rm -f krb5/gsskrb5-private.h
@@ -358,7 +375,7 @@ $(srcdir)/sanon/sanon-private.h:
        cd $(srcdir) && perl ../../cf/make-proto.pl -q -P comment -p sanon/sanon-private.h $(sanonsrc) || rm -f sanon/sanon-private.h
 
 TESTS = test_oid test_names test_cfx
-# test_sequence 
+# test_sequence
 
 test_cfx_SOURCES = krb5/test_cfx.c
 
@@ -381,6 +398,9 @@ LDADD = libgssapi.la \
        $(top_builddir)/lib/krb5/libkrb5.la \
        $(LIB_roken)
 
+test_names_LDADD = $(LDADD) $(top_builddir)/lib/asn1/libasn1.la
+test_context_LDADD = $(LDADD) $(top_builddir)/lib/asn1/libasn1.la $(top_builddir)/lib/wind/libwind.la
+
 # gss
 
 dist_gsstool_SOURCES = gsstool.c
@@ -441,9 +461,8 @@ $(srcdir)/gssapi/gssapi_oid.h $(srcdir)/mech/gss_oid.c:
 # NegoEx test mechanism, uses decode_GSSAPIContextToken
 #
 
-test_negoex_mech_la_SOURCES = test_negoex_mech.c $(gssapi_files:.x=.c)
+test_negoex_mech_la_SOURCES = test_negoex_mech.c $(gssapi_files)
 test_negoex_mech_la_LDFLAGS = -module
 test_negoex_mech_la_LIBADD = \
        $(top_builddir)/lib/asn1/libasn1.la \
        libgssapi.la
-
index 8d5784f17f11f0a8e9b695fe1ca4603c4d1108b9..ffba9d52be05c16ae6021c6da9c3ea7d673d8643 100644 (file)
@@ -33,6 +33,8 @@
 
 RELDIR=lib\gssapi 
 
+intcflags=-DASN1_LIB
+
 !include ../../windows/NTMakefile.w32 
 
 krb5src = \
@@ -77,6 +79,7 @@ krb5src = \
        krb5/inquire_mechs_for_name.c \
        krb5/inquire_names_for_mech.c \
        krb5/inquire_sec_context_by_oid.c \
+        krb5/name_attrs.c \
         krb5/pname_to_uid.c \
        krb5/process_context_token.c \
        krb5/prf.c \
@@ -274,22 +277,14 @@ $(OBJ)\spnego\spnego-private.h: $(spnegosrc)
 $(OBJ)\sanon\sanon-private.h: $(sanonsrc)
        $(PERL) ../../cf/make-proto.pl -q -P remove -p $@ $(sanonsrc)
 
-gssapi_files = $(OBJ)\gssapi\asn1_gssapi_asn1.x
-
-spnego_files = $(OBJ)\spnego\asn1_spnego_asn1.x
-
-$(gssapi_files:.x=.c): $$(@R).x
-
-$(spnego_files:.x=.c): $$(@R).x
-
-$(gssapi_files) $(OBJ)\gssapi\gssapi_asn1.hx $(OBJ)\gssapi\gssapi_asn1-priv.hx: \
+$(OBJ)\gssapi\asn1_gssapi_asn1.c $(OBJ)\gssapi\gssapi_asn1.h $(OBJ)\gssapi\gssapi_asn1-priv.h: \
 $(BINDIR)\asn1_compile.exe mech\gssapi.asn1
        cd $(OBJ)\gssapi
        $(BINDIR)\asn1_compile.exe --one-code-file $(SRCDIR)\mech\gssapi.asn1 gssapi_asn1 \
        || ( $(RM) $(OBJ)\gssapi\gssapi_asn1.h ; exit /b 1 )
        cd $(SRCDIR)
 
-$(spnego_files) $(OBJ)\spnego\spnego_asn1.hx $(OBJ)\spnego\spnego_asn1-priv.hx: \
+$(OBJ)\spnego\asn1_spnego_asn1.c $(OBJ)\spnego\spnego_asn1.h $(OBJ)\spnego\spnego_asn1-priv.h: \
 $(BINDIR)\asn1_compile.exe spnego\spnego.asn1
        cd $(OBJ)\spnego
        $(BINDIR)\asn1_compile --one-code-file --sequence=MechTypeList \
@@ -368,6 +363,7 @@ libgssapi_OBJs = \
        $(OBJ)\krb5/inquire_mechs_for_name.obj \
        $(OBJ)\krb5/inquire_names_for_mech.obj \
        $(OBJ)\krb5/inquire_sec_context_by_oid.obj \
+        $(OBJ)\krb5/name_attrs.obj \
         $(OBJ)\krb5/pname_to_uid.obj \
        $(OBJ)\krb5/process_context_token.obj \
        $(OBJ)\krb5/prf.obj \
@@ -537,8 +533,8 @@ libgssapi_OBJs = \
        $(OBJ)\sanon/release_name.obj \
        $(OBJ)\gkrb5_err.obj \
        $(OBJ)\negoex_err.obj \
-       $(spnego_files:.x=.obj) \
-       $(gssapi_files:.x=.obj)
+       $(OBJ)\spnego\asn1_spnego_asn1.obj \
+       $(OBJ)\gssapi\asn1_gssapi_asn1.obj
 
 GCOPTS=-I$(SRCDIR) -I$(OBJ) -Igssapi -DBUILD_GSSAPI_LIB
 
@@ -578,24 +574,12 @@ GCOPTS=-I$(SRCDIR) -I$(OBJ) -Igssapi -DBUILD_GSSAPI_LIB
 {$(OBJ)}.c{$(OBJ)}.obj::
        $(C2OBJ_P) $(GCOPTS)
 
-{$(OBJ)\spnego}.x{$(OBJ)\spnego}.c:
-       $(CP) $** $@
-
-{$(OBJ)\gssapi}.x{$(OBJ)\gssapi}.c:
-       $(CP) $** $@
-
 {gssapi}.h{$(INCDIR)\gssapi}.h:
        $(CP) $** $@
 
 {$(OBJ)}.h{$(INCDIR)\gssapi}.h:
        $(CP) $** $@
 
-{$(OBJ)\gssapi}.hx{$(OBJ)\gssapi}.h:
-       $(CP) $** $@
-
-{$(OBJ)\spnego}.hx{$(OBJ)\spnego}.h:
-       $(CP) $** $@
-
 LIBGSSAPI_LIBS=\
         $(LIBHEIMBASE)  \
        $(LIBROKEN)     \
@@ -690,8 +674,8 @@ $(OBJ)\gss-commands.c $(OBJ)\gss-commands.h: gss-commands.in
 (generate-obj-macro "libgssapi_OBJs"
                    (concat "\t$(OBJ)\\gkrb5_err.obj \\\n"
                             "\t$(OBJ)\\negoex_err.obj \\\n"
-                            "\t$(spnego_files:.x=.obj) \\\n"
-                            "\t$(gssapi_files:.x=.obj)")
+                           "\t$(OBJ)\\spnego\\asn1_spnego_asn1.obj \\\n"
+                           "\t$(OBJ)\\gssapi\\asn1_gssapi_asn1.obj")
                     "krb5src" "mechsrc" "spnegosrc" "ntlmsrc")
 !endif
 
@@ -715,7 +699,7 @@ $(OBJ)\test_oid.exe: $(OBJ)\test_oid.obj $(LIBGSSAPI) $(LIBROKEN)
        $(EXECONLINK)
        $(EXEPREP_NODIST)
 
-$(OBJ)\test_names.exe: $(OBJ)\test_names.obj $(LIBGSSAPI) $(LIBROKEN) $(LIBVERS)
+$(OBJ)\test_names.exe: $(OBJ)\test_names.obj $(LIBGSSAPI) $(LIBHEIMDAL) $(LIBROKEN) $(LIBVERS)
        $(EXECONLINK)
        $(EXEPREP_NODIST)
 
index 1ead3e15b32f6b2b61faef59909d74cac3a2d931..844fa4d3820630319de822f5a2f4eade8d33535f 100644 (file)
@@ -250,7 +250,7 @@ write_and_free_token(gss_buffer_t out, int negotiate)
 
 bail:
        gss_release_buffer(&min, out);
-       return 0;
+       return ret;
 }
 
 static int
@@ -402,7 +402,7 @@ static int
 initiate_many(gss_name_t service, int delegate, int negotiate, int memcache,
              size_t count)
 {
-       krb5_error_code kret;
+       krb5_error_code kret = 0;
        krb5_context    kctx = NULL;
        krb5_ccache     def_cache = NULL;
        krb5_ccache     mem_cache = NULL;
@@ -443,7 +443,8 @@ accept_one(gss_name_t service, const char *ccname, int negotiate)
         gss_OID          mech_oid;
         gss_ctx_id_t     ctx = GSS_C_NO_CONTEXT;
         gss_buffer_desc  in = GSS_C_EMPTY_BUFFER;
-        gss_buffer_desc  out, dname;
+        gss_buffer_desc  out;
+        gss_buffer_desc  dname = GSS_C_EMPTY_BUFFER;
        krb5_context     kctx = NULL;
        krb5_ccache      ccache = NULL;
        krb5_error_code  kret;
@@ -488,6 +489,8 @@ accept_one(gss_name_t service, const char *ccname, int negotiate)
        if (!nflag)
                printf("Authenticated: %.*s\n", (int)dname.length,
                    (char *)dname.value);
+       (void) gss_release_buffer(&min, &dname);
+       (void) gss_release_name(&min, &client);
 
        if (ccname) {
 #ifdef HAVE_GSS_STORE_CRED_INTO
@@ -565,7 +568,7 @@ print_all_mechs(void)
        for (i=0; i < mech_set->count; i++)
                printf("%s\n", gss_oid_to_name(&mech_set->elements[i]));
 
-       maj = gss_release_oid_set(&min, &mech_set);
+       (void) gss_release_oid_set(&min, &mech_set);
 
 bail:
        exit(ret);
index 4214acc0e5f7d99d4a72e07c25d29c65eb2f85ee..726543f5a382e628f1722e6ef952656f210e3a57 100644 (file)
@@ -233,6 +233,7 @@ typedef OM_uint32 gss_qop_t;
 #define GSS_C_NO_CREDENTIAL ((gss_cred_id_t) 0)
 #define GSS_C_NO_CHANNEL_BINDINGS ((gss_channel_bindings_t) 0)
 #define GSS_C_EMPTY_BUFFER {0, NULL}
+#define GSS_C_EMPTY_BUFFER_SET {0, NULL}
 #define GSS_C_NO_IOV_BUFFER ((gss_iov_buffer_t)0)
 #define GSS_C_NO_CRED_STORE ((gss_key_value_set_t)0)
 
@@ -393,6 +394,18 @@ extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_nt_anonymous_oid_desc;
 extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_nt_export_name_oid_desc;
 #define GSS_C_NT_EXPORT_NAME (&__gss_c_nt_export_name_oid_desc)
 
+/*
+ * The implementation must reserve static storage for a
+ * gss_OID_desc object containing the value
+ * {6, (void *)"\x2b\x06\x01\x05\x06\x06"}, corresponding to an
+ * object-identifier value of {iso(1) identified-organization(3) dod(6)
+ * internet(1) security(5) nametypes(6) gss-composite-export(6)}.
+ * The constant GSS_C_NT_COMPOSITE_EXPORT [RFC6680] should be initialized to
+ * point to that gss_OID_desc.
+ */
+extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_nt_composite_export_oid_desc;
+#define GSS_C_NT_COMPOSITE_EXPORT (&__gss_c_nt_composite_export_oid_desc)
+
 /* Major status codes */
 
 #define GSS_S_COMPLETE 0
@@ -1240,9 +1253,6 @@ GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_destroy_cred(OM_uint32 *minor_status,
                 gss_cred_id_t *cred_handle);
 
-GSSAPI_LIB_FUNCTION uintptr_t GSSAPI_CALLCONV
-gss_get_instance(const char *libname);
-
 /*
  * S4UProxy and S4USelf extensions.
  */
index 74d5109aa19c41a384825f38f34597847f7cae98..818042fa773967cbbe2f737ae78e605dec91b7c3 100644 (file)
@@ -218,6 +218,8 @@ gss_krb5_set_allowable_enctypes(OM_uint32 *minor_status,
                                OM_uint32 num_enctypes,
                                int32_t *enctypes);
 
+#define GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "urn:ietf:kerberos:nameattr-"
+
 GSSAPI_CPP_END
 
 #endif /* GSSAPI_SPNEGO_H_ */
index f125573c13722c57699d56556e6855971a8afb51..3f8e2740e2127615e4ddd29bdda47a8e95f5952b 100644 (file)
@@ -157,39 +157,31 @@ gsskrb5_accept_delegated_token(OM_uint32 *minor_status,
     krb5_ccache ccache = NULL;
     krb5_error_code kret;
     int32_t ac_flags, ret = GSS_S_COMPLETE;
+    gsskrb5_cred handle;
 
     *minor_status = 0;
 
     /* XXX Create a new delegated_cred_handle? */
-    if (delegated_cred_handle == NULL) {
-        ret = GSS_S_COMPLETE;
-        goto out;
-    }
+    if (delegated_cred_handle == NULL)
+        return GSS_S_COMPLETE;
 
     *delegated_cred_handle = NULL;
     kret = krb5_cc_resolve(context, "MEMORY:anonymous", &ccache);
-    if (kret) {
-       ctx->flags &= ~GSS_C_DELEG_FLAG;
-       goto out;
+    if (kret == 0)
+        kret = krb5_cc_initialize(context, ccache, ctx->source);
+    if (kret == 0) {
+        (void) krb5_auth_con_removeflags(context,
+                                         ctx->auth_context,
+                                         KRB5_AUTH_CONTEXT_DO_TIME,
+                                         &ac_flags);
+        kret = krb5_rd_cred2(context,
+                             ctx->auth_context,
+                             ccache,
+                             &ctx->fwd_data);
+        (void) krb5_auth_con_setflags(context,
+                                      ctx->auth_context,
+                                      ac_flags);
     }
-
-    kret = krb5_cc_initialize(context, ccache, ctx->source);
-    if (kret) {
-       ctx->flags &= ~GSS_C_DELEG_FLAG;
-       goto out;
-    }
-
-    krb5_auth_con_removeflags(context,
-                             ctx->auth_context,
-                             KRB5_AUTH_CONTEXT_DO_TIME,
-                             &ac_flags);
-    kret = krb5_rd_cred2(context,
-                        ctx->auth_context,
-                        ccache,
-                        &ctx->fwd_data);
-    krb5_auth_con_setflags(context,
-                          ctx->auth_context,
-                          ac_flags);
     if (kret) {
        ctx->flags &= ~GSS_C_DELEG_FLAG;
        ret = GSS_S_FAILURE;
@@ -197,62 +189,54 @@ gsskrb5_accept_delegated_token(OM_uint32 *minor_status,
        goto out;
     }
 
-    if (delegated_cred_handle) {
-       gsskrb5_cred handle;
+    ret = _gsskrb5_krb5_import_cred(minor_status,
+                                    &ccache,
+                                    NULL,
+                                    NULL,
+                                    delegated_cred_handle);
+    if (ret != GSS_S_COMPLETE)
+        goto out;
 
-       ret = _gsskrb5_krb5_import_cred(minor_status,
-                                       &ccache,
-                                       NULL,
-                                       NULL,
-                                       delegated_cred_handle);
-       if (ret != GSS_S_COMPLETE)
-           goto out;
-
-       handle = (gsskrb5_cred) *delegated_cred_handle;
-       handle->cred_flags |= GSS_CF_DESTROY_CRED_ON_RELEASE;
-
-        /*
-         * A root TGT is one of the form krbtgt/REALM@SAME-REALM.
-         *
-         * A destination TGT is a root TGT for the same realm as the acceptor
-         * service's realm.
-         *
-         * Normally clients delegate a root TGT for the client's realm.
-         *
-         * In some deployments clients may want to delegate destination TGTs as
-         * a form of constrained delegation: so that the destination service
-         * cannot use the delegated credential to impersonate the client
-         * principal to services in its home realm (due to KDC lineage/transit
-         * checks).  In those deployments there may not even be a route back to
-         * the KDCs of the client's realm, and attempting to use a
-         * non-destination TGT might even lead to timeouts.
-         *
-         * We could simply pretend not to have obtained a credential, except
-         * that a) we don't (yet) have an app name here for the appdefault we
-         * need to check, b) the application really wants to be able to log a
-         * message about the delegated credential being no good.
-         *
-         * Thus we leave it to _gsskrb5_store_cred_into2() to decide what to do
-         * with non-destination TGTs.  To do that, it needs the realm of the
-         * acceptor service, which we record here.
-         */
-        handle->destination_realm =
-            strdup(krb5_principal_get_realm(context, ctx->target));
-        if (handle->destination_realm == NULL) {
-            _gsskrb5_release_cred(minor_status, delegated_cred_handle);
-            *minor_status = krb5_enomem(context);
-            ret = GSS_S_FAILURE;
-            goto out;
-        }
+    handle = (gsskrb5_cred) *delegated_cred_handle;
+    handle->cred_flags |= GSS_CF_DESTROY_CRED_ON_RELEASE;
+
+    /*
+     * A root TGT is one of the form krbtgt/REALM@SAME-REALM.
+     *
+     * A destination TGT is a root TGT for the same realm as the acceptor
+     * service's realm.
+     *
+     * Normally clients delegate a root TGT for the client's realm.
+     *
+     * In some deployments clients may want to delegate destination TGTs as
+     * a form of constrained delegation: so that the destination service
+     * cannot use the delegated credential to impersonate the client
+     * principal to services in its home realm (due to KDC lineage/transit
+     * checks).  In those deployments there may not even be a route back to
+     * the KDCs of the client's realm, and attempting to use a
+     * non-destination TGT might even lead to timeouts.
+     *
+     * We could simply pretend not to have obtained a credential, except
+     * that a) we don't (yet) have an app name here for the appdefault we
+     * need to check, b) the application really wants to be able to log a
+     * message about the delegated credential being no good.
+     *
+     * Thus we leave it to _gsskrb5_store_cred_into2() to decide what to do
+     * with non-destination TGTs.  To do that, it needs the realm of the
+     * acceptor service, which we record here.
+     */
+    handle->destination_realm =
+        strdup(krb5_principal_get_realm(context, ctx->target));
+    if (handle->destination_realm == NULL) {
+        _gsskrb5_release_cred(minor_status, delegated_cred_handle);
+        *minor_status = krb5_enomem(context);
+        ret = GSS_S_FAILURE;
+        goto out;
     }
 
 out:
     if (ccache) {
-       /* Don't destroy the default cred cache */
-       if (delegated_cred_handle == NULL)
-           krb5_cc_close(context, ccache);
-       else
-           krb5_cc_destroy(context, ccache);
+        krb5_cc_close(context, ccache);
     }
     return ret;
 }
@@ -478,6 +462,10 @@ gsskrb5_acceptor_start(OM_uint32 * minor_status,
             * lets only send the error token on clock skew, that
             * limit when send error token for non-MUTUAL.
             */
+            krb5_auth_con_free(context, ctx->auth_context);
+            krb5_auth_con_free(context, ctx->deleg_auth_context);
+            ctx->deleg_auth_context = NULL;
+            ctx->auth_context = NULL;
            return send_error_token(minor_status, context, kret,
                                    server, &indata, output_token);
        } else if (kret) {
index 6b625160668a500af73d63df5b658ac0b7eaf593..211dcaa7f7532b467e6b76a3c54673e2cad806b8 100644 (file)
@@ -203,7 +203,8 @@ acquire_cred_with_password(OM_uint32 *minor_status,
 {
     OM_uint32 ret = GSS_S_FAILURE;
     krb5_creds cred;
-    krb5_get_init_creds_opt *opt;
+    krb5_init_creds_context ctx = NULL;
+    krb5_get_init_creds_opt *opt = NULL;
     krb5_ccache ccache = NULL;
     krb5_error_code kret;
     time_t now;
@@ -236,13 +237,19 @@ acquire_cred_with_password(OM_uint32 *minor_status,
         if (kret)
             goto end;
     }
-    kret = krb5_get_init_creds_opt_alloc(context, &opt);
-    if (kret)
-        goto end;
-
     realm = krb5_principal_get_realm(context, handle->principal);
 
-    krb5_get_init_creds_opt_set_default_flags(context, "gss_krb5", realm, opt);
+    kret = krb5_get_init_creds_opt_alloc(context, &opt);
+    if (kret == 0) {
+        krb5_get_init_creds_opt_set_default_flags(context, "gss_krb5", realm,
+                                                  opt);
+        kret = krb5_init_creds_init(context, handle->principal, NULL, NULL, 0,
+                                    opt, &ctx);
+    }
+    if (kret == 0)
+        kret = _krb5_init_creds_set_fast_anon_pkinit_optimistic(context, ctx);
+    if (kret == 0)
+        kret = krb5_init_creds_set_password(context, ctx, password);
 
     /*
      * Get the current time before the AS exchange so we don't
@@ -256,21 +263,18 @@ acquire_cred_with_password(OM_uint32 *minor_status,
      */
     krb5_timeofday(context, &now);
 
-    kret = krb5_get_init_creds_password(context, &cred, handle->principal,
-                                        password, NULL, NULL, 0, NULL, opt);
-    krb5_get_init_creds_opt_free(context, opt);
-    if (kret)
-        goto end;
-
-    kret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, &ccache);
-    if (kret)
-        goto end;
-
-    kret = krb5_cc_initialize(context, ccache, cred.client);
-    if (kret)
-        goto end;
-
-    kret = krb5_cc_store_cred(context, ccache, &cred);
+    if (kret == 0)
+        kret = krb5_init_creds_get(context, ctx);
+    if (kret == 0)
+        kret = krb5_init_creds_get_creds(context, ctx, &cred);
+    if (kret == 0)
+        kret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, &ccache);
+    if (kret == 0)
+        kret = krb5_cc_initialize(context, ccache, cred.client);
+    if (kret == 0)
+        kret = krb5_init_creds_store(context, ctx, ccache);
+    if (kret == 0)
+        kret = krb5_cc_store_cred(context, ccache, &cred);
     if (kret)
         goto end;
 
@@ -284,14 +288,16 @@ acquire_cred_with_password(OM_uint32 *minor_status,
     handle->ccache = ccache;
     ccache = NULL;
     ret = GSS_S_COMPLETE;
-    kret = 0;
 
 end:
+    krb5_get_init_creds_opt_free(context, opt);
+    if (ctx)
+        krb5_init_creds_free(context, ctx);
     if (ccache != NULL)
         krb5_cc_destroy(context, ccache);
     if (cred.client != NULL)
        krb5_free_cred_contents(context, &cred);
-    if (ret != GSS_S_COMPLETE && kret != 0)
+    if (ret != GSS_S_COMPLETE)
        *minor_status = kret;
     return (ret);
 }
index 9093b7a1d36a3a9c3f7f99d0ada9673e0b5b000b..8931b32e1c99666be479f8c840f30d2f8c85453a 100644 (file)
@@ -167,18 +167,20 @@ arcfour_mic_cksum_iov(krb5_context context,
            continue;
        }
 
-       if (iov[i].buffer.value != NULL)
+       if (iov[i].buffer.length > 0) {
+           assert(iov[i].buffer.value != NULL);
            memcpy(ptr + ofs,
                   iov[i].buffer.value,
                   iov[i].buffer.length);
-       ofs += iov[i].buffer.length;
+           ofs += iov[i].buffer.length;
+       }
     }
 
     if (padding) {
        memcpy(ptr + ofs,
               padding->buffer.value,
               padding->buffer.length);
-       ofs += padding->buffer.length;
+       /* ofs += padding->buffer.length; */
     }
 
     ret = krb5_crypto_init(context, key, 0, &crypto);
@@ -881,6 +883,11 @@ _gssapi_wrap_iov_length_arcfour(OM_uint32 *minor_status,
        }
     }
 
+    if (header == NULL) {
+        *minor_status = EINVAL;
+        return GSS_S_FAILURE;
+    }
+
     major_status = _gk_verify_buffers(minor_status, ctx, header,
                                      padding, trailer, FALSE);
     if (major_status != GSS_S_COMPLETE) {
index 182421581a8ca38466a9fba10864b37140e419d6..fc0b9b128723eb8d9caf4676df0e386c908bc5bc 100644 (file)
@@ -82,6 +82,7 @@ _gsskrb5_krb5_import_cred(OM_uint32 *minor_status,
     krb5_error_code kret;
     gsskrb5_cred handle;
     OM_uint32 ret;
+    int id_given = (*id != NULL);
 
     *cred = NULL;
 
@@ -142,8 +143,6 @@ _gsskrb5_krb5_import_cred(OM_uint32 *minor_status,
 
         handle->ccache = *id;
         *id = NULL;
-       if (kret)
-           goto out;
     }
 
 
@@ -171,7 +170,7 @@ _gsskrb5_krb5_import_cred(OM_uint32 *minor_status,
     }
 
 
-    if (id || keytab) {
+    if (id_given || keytab) {
        ret = gss_create_empty_oid_set(minor_status, &handle->mechanisms);
        if (ret == GSS_S_COMPLETE)
            ret = gss_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM,
index 981baed6edd6374980509e2cb85fdfa4f7c5c555..c29841537526364caeeaf703a78e1917ea33286f 100644 (file)
@@ -195,7 +195,7 @@ _gsskrb5_export_sec_context(
     }
 
     if (ctx->target) {
-        kret = krb5_store_principal(sp, ctx->source);
+        kret = krb5_store_principal(sp, ctx->target);
        if (kret) {
            *minor_status = kret;
            goto failure;
index 91947025cc7fcbf003335c049690f37a025dc625..e58df18c5f0aa0e5658d38554801f2f23ab80875 100644 (file)
@@ -152,6 +152,13 @@ gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_nt_export_name_oid_desc =
 gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_nt_principal_name_oid_desc =
     {10, rk_UNCONST("\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x01") };
 
+/*
+ * GSS_C_NT_COMPOSITE_EXPORT [RFC6680], OID {iso(1) identified-organization(3)
+ * dod(6) internet(1) security(5) nametypes(6) gss-composite-export(6)}.
+ */
+gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_nt_composite_export_oid_desc =
+    {6, rk_UNCONST("\x2b\x06\x01\x05\x06\x06")};
+
 /*
  * draft-ietf-cat-iakerb-09, IAKERB:
  *   The mechanism ID for IAKERB proxy GSS-API Kerberos, in accordance
@@ -383,12 +390,12 @@ static gssapi_mech_interface_desc krb5_mech = {
     sizeof(krb5_mo) / sizeof(krb5_mo[0]),
     _gsskrb5_localname,
     _gsskrb5_authorize_localname,
-    NULL, /* gm_display_name_ext */
-    NULL, /* gm_inquire_name */
-    NULL, /* gm_get_name_attribute */
-    NULL, /* gm_set_name_attribute */
-    NULL, /* gm_delete_name_attribute */
-    NULL, /* gm_export_name_composite */
+    _gsskrb5_display_name_ext,
+    _gsskrb5_inquire_name,
+    _gsskrb5_get_name_attribute,
+    _gsskrb5_set_name_attribute,
+    _gsskrb5_delete_name_attribute,
+    _gsskrb5_export_name_composite,
     _gsskrb5_duplicate_cred,
     _gsskrb5_add_cred_from,
     _gsskrb5_store_cred_into,
index 77449612d05cf9771c56724e81854072cb832d6d..f4ee2313c16fa521dfe251bcbfc783d02ae8a301 100644 (file)
@@ -183,9 +183,12 @@ import_export_name (OM_uint32 *minor_status,
                    const gss_buffer_t input_name_buffer,
                    gss_name_t *output_name)
 {
+    CompositePrincipal *composite;
     unsigned char *p;
     uint32_t length;
+    size_t sz;
     OM_uint32 ret;
+    int is_composite;
     char *name;
 
     if (input_name_buffer->length < 10 + GSS_KRB5_MECHANISM->length)
@@ -195,7 +198,9 @@ import_export_name (OM_uint32 *minor_status,
 
     p = input_name_buffer->value;
 
-    if (memcmp(&p[0], "\x04\x01\x00", 3) != 0 ||
+    if (p[0] != 0x04 ||
+        (p[1] != 0x01 && p[1] != 0x02) ||
+        p[2] != 0x00 ||
        p[3] != GSS_KRB5_MECHANISM->length + 2 ||
        p[4] != 0x06 ||
        p[5] != GSS_KRB5_MECHANISM->length ||
@@ -203,6 +208,8 @@ import_export_name (OM_uint32 *minor_status,
               GSS_KRB5_MECHANISM->length) != 0)
        return GSS_S_BAD_NAME;
 
+    is_composite = p[1] == 0x02;
+
     p += 6 + GSS_KRB5_MECHANISM->length;
 
     length = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
@@ -211,6 +218,28 @@ import_export_name (OM_uint32 *minor_status,
     if (length > input_name_buffer->length - 10 - GSS_KRB5_MECHANISM->length)
        return GSS_S_BAD_NAME;
 
+    if (is_composite) {
+        if ((composite = calloc(1, sizeof(*composite))) == NULL) {
+            *minor_status = ENOMEM;
+            return GSS_S_FAILURE;
+        }
+
+        ret = decode_CompositePrincipal(p, length, composite, &sz);
+       if (ret) {
+            *minor_status = ret;
+            return GSS_S_FAILURE;
+       }
+        if (sz != length) {
+            free_CompositePrincipal(composite);
+            free(composite);
+            *minor_status = EINVAL;
+            return GSS_S_FAILURE;
+        }
+
+        *output_name = (void *)composite;
+        return GSS_S_COMPLETE;
+    }
+
     name = malloc(length + 1);
     if (name == NULL) {
        *minor_status = ENOMEM;
@@ -221,7 +250,6 @@ import_export_name (OM_uint32 *minor_status,
 
     ret = parse_krb5_name(minor_status, context, name, output_name);
     free(name);
-
     return ret;
 }
 
@@ -253,7 +281,8 @@ OM_uint32 GSSAPI_CALLCONV _gsskrb5_import_name
                                 context,
                                 input_name_buffer,
                                 output_name);
-    else if (gss_oid_equal(input_name_type, GSS_C_NT_EXPORT_NAME)) {
+    else if (gss_oid_equal(input_name_type, GSS_C_NT_EXPORT_NAME) ||
+             gss_oid_equal(input_name_type, GSS_C_NT_COMPOSITE_EXPORT)) {
        return import_export_name(minor_status,
                                  context,
                                  input_name_buffer,
index c7dfdc85166cbff68a23c043178569fc70e09556..62b26ed7eb91a0d4602d9d8e213f4dc17bb4af27 100644 (file)
 
 #include "gsskrb5_locl.h"
 
+static OM_uint32
+gsskrb5_set_authorization_data(OM_uint32 *,
+                               krb5_context,
+                               krb5_auth_context,
+                               gss_const_name_t);
+
 /*
  * copy the addresses from `input_chan_bindings' (if any) to
  * the auth context `ac'
@@ -418,6 +424,11 @@ init_auth
     if (ret)
        goto failure;
 
+    ret = gsskrb5_set_authorization_data(minor_status, context,
+                                         ctx->auth_context, name);
+    if (ret)
+       goto failure;
+
     ctx->endtime = ctx->kcred->times.endtime;
 
     ret = _gss_DES3_get_mic_compat(minor_status, ctx, context);
@@ -921,7 +932,7 @@ OM_uint32 GSSAPI_CALLCONV _gsskrb5_init_sec_context
                        time_rec);
        if (ret != GSS_S_COMPLETE)
            break;
-       /* FALLTHROUGH */
+        fallthrough;
     case INITIATOR_RESTART:
        ret = init_auth_restart(minor_status,
                                cred,
@@ -980,3 +991,31 @@ OM_uint32 GSSAPI_CALLCONV _gsskrb5_init_sec_context
     return ret;
 
 }
+
+static OM_uint32
+gsskrb5_set_authorization_data(OM_uint32 *minor_status,
+                               krb5_context context,
+                               krb5_auth_context auth_context,
+                               gss_const_name_t gn)
+{
+    const CompositePrincipal *name = (const void *)gn;
+    AuthorizationData *ad;
+    krb5_error_code kret = 0;
+    size_t i;
+
+    if (name->nameattrs == NULL || name->nameattrs->want_ad == NULL)
+        return GSS_S_COMPLETE;
+
+    ad = name->nameattrs->want_ad;
+    for (i = 0; kret == 0 && i < ad->len; i++) {
+        kret = krb5_auth_con_add_AuthorizationData(context, auth_context,
+                                                   ad->val[0].ad_type,
+                                                   &ad->val[0].ad_data);
+    }
+
+    if (kret) {
+        *minor_status = kret;
+        return GSS_S_FAILURE;
+    }
+    return GSS_S_COMPLETE;
+}
diff --git a/third_party/heimdal/lib/gssapi/krb5/name_attrs.c b/third_party/heimdal/lib/gssapi/krb5/name_attrs.c
new file mode 100644 (file)
index 0000000..11fc2ef
--- /dev/null
@@ -0,0 +1,1171 @@
+/*
+ * Copyright (c) 2021 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "gsskrb5_locl.h"
+
+/*
+ * (Not-yet-)Standard name attributes for Kerberos MNs,
+ * GSS_KRB5_NAME_ATTRIBUTE_BASE_URN + "...".
+ *
+ * I.e., "urn:ietf:kerberos:nameattr-...".  (XXX Register this URN namespace
+ * with IANA.)
+ *
+ * Note that we do use URN fragments.
+ *
+ * Specific attributes below the base URN:
+ *
+ *  - name access attributes:
+ *     - "realm"                    -> realm of name
+ *     - "name-ncomp"               -> count of name components
+ *     - "name-ncomp#<digit>"       -> name component N (0 <= N <= 9)
+ *
+ * Ticket and Authenticator access attributes:
+ *
+ *  - "transit-path"                -> encoding of the transited path
+ *  - "authenticator-authz-data"    -> encoding of all of the authz-data from
+ *                                     the AP-REQ's Authenticator
+ *  - "ticket-authz-data"           -> encoding of all of the authz-data from
+ *                                     the AP-REQ's Ticket
+ *  - "ticket-authz-data#pac"       -> the PAC
+ *  - "authz-data#<N>"              -> encoding of all of a specific auth-data
+ *                                     element type N (e.g., 2, meaning
+ *                                     AD-INTENDED-FOR-SERVER)
+ *
+ * Misc. attributes:
+ *
+ *  - "peer-realm"                  -> name of peer's realm (if this is an MN
+ *                                     resulting for establishing a security
+ *                                     context)
+ *  - "canonical-name"              -> exported name token and RFC1964 display
+ *                                     syntax of the name's canonical name
+ *
+ * Compatibility with MIT:
+ *
+ *  - "urn:mspac:"                  -> the PAC and its individual info buffers
+ *
+ * TODO:
+ *
+ *  - Add some sort of display syntax for transit path
+ *  - Add support for URN q-components or attribute prefixes to specify
+ *    alternative raw and/or display value encodings (JSON?)
+ *  - Add support for attributes for accessing other parts of the Ticket / KDC
+ *    reply enc-parts, like auth times
+ *  - Add support for getting PAC logon fields, including SIDs (one at a time)
+ *  - Add support for CAMMAC?
+ */
+
+static int
+attr_eq(gss_const_buffer_t attr, const char *aname, size_t aname_len, \
+       int prefix_check)
+{
+    if (attr->length < aname_len)
+        return 0;
+
+    if (strncmp((char *)attr->value, aname, aname_len) != 0)
+       return 0;
+
+    return prefix_check || attr->length == aname_len;
+}
+
+#define ATTR_EQ(a, an) (attr_eq(a, an, sizeof(an) - 1, FALSE))
+#define ATTR_EQ_PREFIX(a, an) (attr_eq(a, an, sizeof(an) - 1, TRUE))
+
+/* Split attribute into prefix, suffix, and fragment.  See RFC6680. */
+static void
+split_attr(gss_const_buffer_t orig,
+           gss_buffer_t prefix,
+           gss_buffer_t attr,
+           gss_buffer_t frag,
+           int *is_urn)
+{
+    char *last = NULL;
+    char *p = orig->value;
+
+    *attr = *orig;
+    prefix->value = orig->value;
+    prefix->length = 0;
+    frag->length = 0;
+    frag->value = NULL;
+
+    /* FIXME We don't have a memrchr() in lib/roken */
+    for (p = memchr(p, ' ', orig->length);
+         p;
+         p = memchr(p + 1, ' ', orig->length)) {
+        last = p;
+        prefix->length = last - (const char *)orig->value;
+        attr->value = last + 1;
+        attr->length = orig->length - (prefix->length + 1);
+    }
+    if (prefix->length == 0)
+        prefix->value = NULL;
+
+    if ((*is_urn = (strncmp(attr->value, "urn:", sizeof("urn:") - 1) == 0)) &&
+        (p = memchr((char *)attr->value + 1, '#', attr->length - 1))) {
+        frag->value = ++p;
+        frag->length = attr->length - (p - (const char *)attr->value);
+        attr->length = --p - (const char *)attr->value;
+    }
+}
+
+typedef OM_uint32 get_name_attr_f(OM_uint32 *,
+                                  const CompositePrincipal *,
+                                  gss_const_buffer_t,
+                                  gss_const_buffer_t,
+                                  gss_const_buffer_t,
+                                  int *,
+                                  int *,
+                                  gss_buffer_t,
+                                  gss_buffer_t,
+                                  int *);
+
+typedef OM_uint32 set_name_attr_f(OM_uint32 *,
+                                  CompositePrincipal *,
+                                  gss_const_buffer_t,
+                                  gss_const_buffer_t,
+                                  gss_const_buffer_t,
+                                  int,
+                                  gss_buffer_t);
+
+typedef OM_uint32 del_name_attr_f(OM_uint32 *,
+                                  CompositePrincipal *,
+                                  gss_const_buffer_t,
+                                  gss_const_buffer_t,
+                                  gss_const_buffer_t);
+typedef get_name_attr_f *get_name_attr_fp;
+typedef set_name_attr_f *set_name_attr_fp;
+typedef del_name_attr_f *del_name_attr_fp;
+
+static get_name_attr_f get_realm;
+static get_name_attr_f get_ncomps;
+static get_name_attr_f get_peer_realm;
+static get_name_attr_f get_pac;
+static get_name_attr_f get_pac_buffer;
+static get_name_attr_f get_authz_data;
+static get_name_attr_f get_ticket_authz_data;
+static get_name_attr_f get_authenticator_authz_data;
+static set_name_attr_f set_authenticator_authz_data;
+static get_name_attr_f get_transited;
+static get_name_attr_f get_canonical_name;
+
+#define NB(n) \
+    GSS_KRB5_NAME_ATTRIBUTE_BASE_URN n, n, \
+    sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN n) - 1, \
+    sizeof(n) - 1
+#define NM(n) \
+    "urn:mspac:" n, n, sizeof("urn:mspac:" n) - 1, sizeof(n) - 1
+
+static struct krb5_name_attrs {
+    const char *fullname;
+    const char *name;
+    size_t fullnamelen;
+    size_t namelen;
+    get_name_attr_fp getter;
+    set_name_attr_fp setter;
+    del_name_attr_fp deleter;
+    unsigned int indicate:1;
+    unsigned int is_krb5_name_attr_urn:1;
+} name_attrs[] = {
+    /* XXX We should sort these so we can binary search them */
+    { NB("realm"),          get_realm,      NULL, NULL, 1, 1 },
+    { NB("name-ncomp"),     get_ncomps,     NULL, NULL, 1, 1 },
+    { NB("name-ncomp#0"),   get_ncomps,     NULL, NULL, 1, 1 },
+    { NB("name-ncomp#1"),   get_ncomps,     NULL, NULL, 1, 1 },
+    { NB("name-ncomp#2"),   get_ncomps,     NULL, NULL, 1, 1 },
+    { NB("name-ncomp#3"),   get_ncomps,     NULL, NULL, 1, 1 },
+    { NB("name-ncomp#4"),   get_ncomps,     NULL, NULL, 1, 1 },
+    { NB("name-ncomp#5"),   get_ncomps,     NULL, NULL, 1, 1 },
+    { NB("name-ncomp#6"),   get_ncomps,     NULL, NULL, 1, 1 },
+    { NB("name-ncomp#7"),   get_ncomps,     NULL, NULL, 1, 1 },
+    { NB("name-ncomp#8"),   get_ncomps,     NULL, NULL, 1, 1 },
+    { NB("name-ncomp#9"),   get_ncomps,     NULL, NULL, 1, 1 },
+    { NB("peer-realm"),     get_peer_realm, NULL, NULL, 1, 1 },
+    { NB("ticket-authz-data#pac"), get_pac, NULL, NULL, 1, 1 },
+    { NM(""),                   get_pac,    NULL, NULL, 1, 0 },
+    { NM("logon-info"),         get_pac_buffer,    NULL, NULL, 1, 0 },
+    { NM("credentials-info"),   get_pac_buffer,    NULL, NULL, 1, 0 },
+    { NM("server-checksum"),    get_pac_buffer,    NULL, NULL, 1, 0 },
+    { NM("privsvr-checksum"),   get_pac_buffer,    NULL, NULL, 1, 0 },
+    { NM("client-info"),        get_pac_buffer,    NULL, NULL, 1, 0 },
+    { NM("delegation-info"),    get_pac_buffer,    NULL, NULL, 1, 0 },
+    { NM("upn-dns-info"),       get_pac_buffer,    NULL, NULL, 1, 0 },
+    { NM("ticket-checksum"),    get_pac_buffer,    NULL, NULL, 1, 0 },
+    { NM("attributes-info"),    get_pac_buffer,    NULL, NULL, 1, 0 },
+    { NM("requestor-sid"),      get_pac_buffer,    NULL, NULL, 1, 0 },
+    { NB("ticket-authz-data#kdc-issued"),
+         get_ticket_authz_data, NULL, NULL, 1, 1 },
+    { NB("ticket-authz-data"),
+         get_ticket_authz_data, NULL, NULL, 1, 1 },
+    { NB("authenticator-authz-data"),
+         get_authenticator_authz_data,
+         set_authenticator_authz_data, NULL, 1, 1 },
+    { NB("authz-data"),     get_authz_data,  NULL, NULL, 1, 1 },
+    { NB("transit-path"),   get_transited,   NULL, NULL, 1, 1 },
+    { NB("canonical-name"), get_canonical_name, NULL, NULL, 1, 1 },
+};
+
+OM_uint32 GSSAPI_CALLCONV
+_gsskrb5_get_name_attribute(OM_uint32 *minor_status,
+                            gss_name_t name,
+                            gss_buffer_t original_attr,
+                            int *authenticated,
+                            int *complete,
+                            gss_buffer_t value,
+                            gss_buffer_t display_value,
+                            int *more)
+{
+    gss_buffer_desc prefix, attr, suffix, frag;
+    size_t i;
+    int is_krb5_name_attr_urn = 0;
+    int is_urn = 0;
+
+    *minor_status = 0;
+    if (authenticated)
+        *authenticated = 0;
+    if (complete)
+        *complete = 0;
+    if (more)
+        *more = 0;
+    if (value) {
+        value->length = 0;
+        value->value = NULL;
+    }
+    if (display_value) {
+        display_value->length = 0;
+        display_value->value = NULL;
+    }
+
+    suffix.value = NULL;
+    suffix.length = 0;
+
+    split_attr(original_attr, &prefix, &attr, &frag, &is_urn);
+
+    if (prefix.length || !is_urn)
+        return GSS_S_UNAVAILABLE;
+
+    is_krb5_name_attr_urn =
+        ATTR_EQ_PREFIX(&attr, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN);
+    if (is_krb5_name_attr_urn) {
+        suffix.value =
+            (char *)attr.value + sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN) - 1;
+        suffix.length = attr.length - (sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN) - 1);
+    }
+
+    for (i = 0; i < sizeof(name_attrs)/sizeof(name_attrs[0]); i++) {
+        if (!name_attrs[i].getter)
+            continue;
+        if (name_attrs[i].is_krb5_name_attr_urn && is_krb5_name_attr_urn) {
+            if (!attr_eq(&suffix, name_attrs[i].name, name_attrs[i].namelen, 0))
+                continue;
+        } else if (!name_attrs[i].is_krb5_name_attr_urn && !is_krb5_name_attr_urn) {
+            if (!attr_eq(&attr, name_attrs[i].fullname, name_attrs[i].fullnamelen, 0))
+                continue;
+        } else
+            continue;
+
+        return name_attrs[i].getter(minor_status,
+                                    (const CompositePrincipal *)name,
+                                    &prefix, &attr, &frag, authenticated,
+                                    complete, value, display_value, more);
+    }
+    return GSS_S_UNAVAILABLE;
+}
+
+OM_uint32 GSSAPI_CALLCONV
+_gsskrb5_set_name_attribute(OM_uint32 *minor_status,
+                            gss_name_t name,
+                            int complete,
+                            gss_buffer_t original_attr,
+                            gss_buffer_t value)
+{
+    gss_buffer_desc prefix, attr, suffix, frag;
+    size_t i;
+    int is_krb5_name_attr_urn = 0;
+    int is_urn = 0;
+
+    *minor_status = 0;
+
+    suffix.value = NULL;
+    suffix.length = 0;
+
+    split_attr(original_attr, &prefix, &attr, &frag, &is_urn);
+
+    if (prefix.length || !is_urn)
+        return GSS_S_UNAVAILABLE;
+
+    is_krb5_name_attr_urn =
+        ATTR_EQ_PREFIX(&attr, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN);
+    if (is_krb5_name_attr_urn) {
+        suffix.value =
+            (char *)attr.value + sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN) - 1;
+        suffix.length = attr.length - (sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN) - 1);
+    }
+
+    for (i = 0; i < sizeof(name_attrs)/sizeof(name_attrs[0]); i++) {
+        if (!name_attrs[i].setter)
+            continue;
+        if (name_attrs[i].is_krb5_name_attr_urn && is_krb5_name_attr_urn) {
+            if (!attr_eq(&suffix, name_attrs[i].name, name_attrs[i].namelen, 0))
+                continue;
+        } else if (!name_attrs[i].is_krb5_name_attr_urn && !is_krb5_name_attr_urn) {
+            if (!attr_eq(&attr, name_attrs[i].name, name_attrs[i].namelen, 0))
+                continue;
+        } else
+            continue;
+
+        return name_attrs[i].setter(minor_status, (CompositePrincipal *)name,
+                                    &prefix, &attr, &frag, complete, value);
+    }
+    return GSS_S_UNAVAILABLE;
+}
+
+OM_uint32 GSSAPI_CALLCONV
+_gsskrb5_delete_name_attribute(OM_uint32 *minor_status,
+                               gss_name_t name,
+                               gss_buffer_t original_attr)
+{
+    gss_buffer_desc prefix, attr, suffix, frag;
+    size_t i;
+    int is_krb5_name_attr_urn = 0;
+    int is_urn = 0;
+
+    *minor_status = 0;
+
+    suffix.value = NULL;
+    suffix.length = 0;
+
+    split_attr(original_attr, &prefix, &attr, &frag, &is_urn);
+
+    if (prefix.length || !is_urn)
+        return GSS_S_UNAVAILABLE;
+
+    is_krb5_name_attr_urn =
+        ATTR_EQ_PREFIX(&attr, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN);
+    if (is_krb5_name_attr_urn) {
+        suffix.value =
+            (char *)attr.value + sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN) - 1;
+        suffix.length = attr.length - (sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN) - 1);
+    }
+
+    for (i = 0; i < sizeof(name_attrs)/sizeof(name_attrs[0]); i++) {
+        if (!name_attrs[i].deleter)
+            continue;
+        if (name_attrs[i].is_krb5_name_attr_urn && is_krb5_name_attr_urn) {
+            if (!attr_eq(&suffix, name_attrs[i].name, name_attrs[i].namelen, 0))
+                continue;
+        } else if (!name_attrs[i].is_krb5_name_attr_urn && !is_krb5_name_attr_urn) {
+            if (!attr_eq(&attr, name_attrs[i].fullname, name_attrs[i].fullnamelen, 0))
+                continue;
+        } else
+            continue;
+
+        return name_attrs[i].deleter(minor_status, (CompositePrincipal *)name,
+                                    &prefix, &attr, &frag);
+    }
+    return GSS_S_UNAVAILABLE;
+}
+
+OM_uint32 GSSAPI_CALLCONV
+_gsskrb5_inquire_name(OM_uint32 *minor_status,
+                      gss_name_t name,
+                      int *name_is_MN,
+                      gss_OID *MN_mech,
+                      gss_buffer_set_t *attrs)
+{
+    gss_buffer_desc prefix, attr, frag, a;
+    OM_uint32 major = GSS_S_UNAVAILABLE;
+    size_t i;
+    int authenticated, is_urn;
+
+    *minor_status = 0;
+    if (name_is_MN)
+        *name_is_MN = 1;
+    if (MN_mech)
+        *MN_mech = GSS_KRB5_MECHANISM;
+    if (name == GSS_C_NO_NAME)
+        return GSS_S_CALL_INACCESSIBLE_READ;
+    if (attrs == NULL)
+        return GSS_S_CALL_INACCESSIBLE_WRITE;
+
+    for (i = 0; i < sizeof(name_attrs)/sizeof(name_attrs[0]); i++) {
+        if (!name_attrs[i].indicate)
+            continue;
+        a.value = (void *)(uintptr_t)name_attrs[i].fullname;
+        a.length = name_attrs[i].fullnamelen;
+        split_attr(&a, &prefix, &attr, &frag, &is_urn);
+        major = name_attrs[i].getter(minor_status,
+                                     (const CompositePrincipal *)name,
+                                     &prefix, &attr, &frag, &authenticated,
+                                     NULL, NULL, NULL, NULL);
+        if (major == GSS_S_UNAVAILABLE)
+            continue;
+        if (major != GSS_S_COMPLETE)
+            break;
+        major = gss_add_buffer_set_member(minor_status, &a, attrs);
+    }
+    if (major == GSS_S_UNAVAILABLE)
+        major = GSS_S_COMPLETE;
+    return major;
+}
+
+OM_uint32 GSSAPI_CALLCONV
+_gsskrb5_display_name_ext(OM_uint32 *minor_status,
+                          gss_name_t name,
+                          gss_OID display_as_name_type,
+                          gss_buffer_t display_name)
+{
+    krb5_const_principal p = (void *)name;
+    char *s = NULL;
+
+    *minor_status = 0;
+    if (display_name == NULL)
+        return GSS_S_CALL_INACCESSIBLE_WRITE;
+    display_name->length = 0;
+    display_name->value = NULL;
+
+    if (gss_oid_equal(display_as_name_type, GSS_C_NT_USER_NAME)) {
+        if (p->name.name_string.len != 1)
+            return GSS_S_UNAVAILABLE;
+        return _gsskrb5_localname(minor_status, name, GSS_KRB5_MECHANISM,
+                                  display_name);
+    }
+    if (!gss_oid_equal(display_as_name_type, GSS_C_NT_HOSTBASED_SERVICE) ||
+        p->name.name_string.len != 2 ||
+        strchr(p->name.name_string.val[0], '@') ||
+        strchr(p->name.name_string.val[1], '.') == NULL)
+        return GSS_S_UNAVAILABLE;
+    if (asprintf(&s, "%s@%s", p->name.name_string.val[0],
+                 p->name.name_string.val[1]) == -1 || s == NULL) {
+        *minor_status = ENOMEM;
+        return GSS_S_FAILURE;
+    }
+    display_name->length = strlen(s);
+    display_name->value = s;
+    return GSS_S_COMPLETE;
+}
+
+OM_uint32 GSSAPI_CALLCONV
+_gsskrb5_export_name_composite(OM_uint32 *minor_status,
+                               gss_name_t name,
+                               gss_buffer_t exported_name)
+{
+    krb5_error_code kret;
+    gss_buffer_desc inner = GSS_C_EMPTY_BUFFER;
+    unsigned char *buf;
+    size_t sz;
+
+    if (name == NULL)
+        return GSS_S_CALL_INACCESSIBLE_READ;
+    if (exported_name == NULL)
+        return GSS_S_CALL_INACCESSIBLE_WRITE;
+
+    ASN1_MALLOC_ENCODE(CompositePrincipal, inner.value, inner.length,
+                       (void *)name, &sz, kret);
+    if (kret != 0) {
+        *minor_status = kret;
+        return GSS_S_FAILURE;
+    }
+
+    exported_name->length = 10 + inner.length + GSS_KRB5_MECHANISM->length;
+    exported_name->value  = malloc(exported_name->length);
+    if (exported_name->value == NULL) {
+       free(inner.value);
+       *minor_status = ENOMEM;
+       return GSS_S_FAILURE;
+    }
+
+    /* TOK, MECH_OID_LEN, DER(MECH_OID), NAME_LEN, NAME */
+
+    buf = exported_name->value;
+    buf[0] = 0x04;
+    buf[1] = 0x02;
+    buf[2] = ((GSS_KRB5_MECHANISM->length + 2) >> 8) & 0xff;
+    buf[3] = (GSS_KRB5_MECHANISM->length + 2) & 0xff;
+    buf[4] = 0x06;
+    buf[5] = (GSS_KRB5_MECHANISM->length) & 0xFF;
+
+    memcpy(buf + 6, GSS_KRB5_MECHANISM->elements, GSS_KRB5_MECHANISM->length);
+    buf += 6 + GSS_KRB5_MECHANISM->length;
+
+    buf[0] = (inner.length >> 24) & 0xff;
+    buf[1] = (inner.length >> 16) & 0xff;
+    buf[2] = (inner.length >> 8) & 0xff;
+    buf[3] = (inner.length) & 0xff;
+    buf += 4;
+
+    memcpy(buf, inner.value, inner.length);
+    free(inner.value);
+
+    *minor_status = 0;
+    return GSS_S_COMPLETE;
+}
+
+#define CHECK_ENOMEM(v, dv) \
+    do { \
+        if (((v) && !(v)->value) || ((dv) && !(dv)->value)) { \
+            if ((v) && (v)->value) { \
+                free((v)->value); \
+                (v)->length = 0; \
+                (v)->value = NULL; \
+            } \
+            *minor_status = ENOMEM; \
+            return GSS_S_FAILURE; \
+        } \
+    } while (0)
+
+static OM_uint32
+get_realm(OM_uint32 *minor_status,
+          const CompositePrincipal *name,
+          gss_const_buffer_t prefix,
+          gss_const_buffer_t attr,
+          gss_const_buffer_t frag,
+          int *authenticated,
+          int *complete,
+          gss_buffer_t value,
+          gss_buffer_t display_value,
+          int *more)
+{
+    PrincipalNameAttrs *nameattrs = name->nameattrs;
+
+    if (prefix->length || frag->length || !name->realm)
+        return GSS_S_UNAVAILABLE;
+    if (authenticated && nameattrs && nameattrs->authenticated)
+        *authenticated = 1;
+    if (complete)
+        *complete = 1;
+    if (value && (value->value = strdup(name->realm)))
+        value->length = strlen(name->realm);
+    if (display_value && (display_value->value = strdup(name->realm)))
+        display_value->length = strlen(name->realm);
+    CHECK_ENOMEM(value, display_value);
+    return GSS_S_COMPLETE;
+}
+
+static OM_uint32
+get_ncomps(OM_uint32 *minor_status,
+           const CompositePrincipal *name,
+           gss_const_buffer_t prefix,
+           gss_const_buffer_t attr,
+           gss_const_buffer_t frag,
+           int *authenticated,
+           int *complete,
+           gss_buffer_t value,
+           gss_buffer_t display_value,
+           int *more)
+{
+    PrincipalNameAttrs *nameattrs = name->nameattrs;
+    int n = -1;
+
+    if (authenticated && nameattrs && nameattrs->authenticated)
+        *authenticated = 1;
+    if (complete)
+        *complete = 1;
+
+    if (frag->length == 1 &&
+        ((const char *)frag->value)[0] >= '0' &&
+        ((const char *)frag->value)[0] <= '9') {
+        n = ((const char *)frag->value)[0] - '0';
+    } else if (frag->length == sizeof("all") - 1 &&
+               strncmp(frag->value, "all", sizeof("all") - 1) == 0) {
+        if (!more || *more < -1 || *more == 0 || *more > CHAR_MAX ||
+            *more > (int)name->name.name_string.len) {
+            *minor_status = EINVAL;
+            return GSS_S_UNAVAILABLE;
+        }
+        if (*more == -1) {
+            *more = name->name.name_string.len - 1;
+            n = 0;
+        } else {
+            n = name->name.name_string.len - *more;
+            (*more)--;
+        }
+    }
+
+    if (frag->length == 0) {
+        char *s = NULL;
+
+        /* Outut count of components */
+        if (value && (value->value = malloc(sizeof(size_t)))) {
+            *((size_t *)value->value) = name->name.name_string.len;
+            value->length = sizeof(size_t);
+        }
+        if (display_value &&
+            asprintf(&s, "%u", (unsigned int)name->name.name_string.len) > 0) {
+            display_value->value = s;
+            display_value->length = strlen(display_value->value);
+        }
+    } else {
+        /*
+         * Output a component.  The value and the display value are the same in
+         * this case.
+         */
+        if (n < 0 || n >= name->name.name_string.len) {
+            *minor_status = EINVAL;
+            return GSS_S_UNAVAILABLE;
+        }
+        if (value && (value->value = strdup(name->name.name_string.val[n])))
+            value->length = strlen(name->name.name_string.val[n]);
+        if (display_value &&
+            (display_value->value = strdup(name->name.name_string.val[n])))
+            display_value->length = strlen(name->name.name_string.val[n]);
+    }
+
+    CHECK_ENOMEM(value, display_value);
+    return GSS_S_COMPLETE;
+}
+
+static OM_uint32
+get_peer_realm(OM_uint32 *minor_status,
+               const CompositePrincipal *name,
+               gss_const_buffer_t prefix,
+               gss_const_buffer_t attr,
+               gss_const_buffer_t frag,
+               int *authenticated,
+               int *complete,
+               gss_buffer_t value,
+               gss_buffer_t display_value,
+               int *more)
+{
+    PrincipalNameAttrs *nameattrs = name->nameattrs;
+
+    if (prefix->length || frag->length || !nameattrs || !nameattrs->peer_realm)
+        return GSS_S_UNAVAILABLE;
+    if (authenticated)
+        *authenticated = 1;
+    if (complete)
+        *complete = 1;
+    if (value && (value->value = strdup(nameattrs->peer_realm[0])))
+        value->length = strlen(value->value);
+    if (display_value &&
+        (display_value->value = strdup(nameattrs->peer_realm[0])))
+        display_value->length = strlen(display_value->value);
+
+    CHECK_ENOMEM(value, display_value);
+    return GSS_S_COMPLETE;
+}
+
+static OM_uint32
+get_pac(OM_uint32 *minor_status,
+        const CompositePrincipal *name,
+        gss_const_buffer_t prefix,
+        gss_const_buffer_t attr,
+        gss_const_buffer_t frag,
+        int *authenticated,
+        int *complete,
+        gss_buffer_t value,
+        gss_buffer_t display_value,
+        int *more)
+{
+    krb5_error_code kret;
+    krb5_context context;
+    krb5_data data;
+    PrincipalNameAttrs *nameattrs = name->nameattrs;
+    PrincipalNameAttrSrc *src = nameattrs ? nameattrs->source : NULL;
+    EncTicketPart *ticket = NULL;
+
+    krb5_data_zero(&data);
+
+    if (src == NULL ||
+       src->element != choice_PrincipalNameAttrSrc_enc_ticket_part)
+       return GSS_S_UNAVAILABLE;
+
+    ticket = &src->u.enc_ticket_part;
+
+    if (prefix->length || !authenticated || !ticket)
+        return GSS_S_UNAVAILABLE;
+
+    GSSAPI_KRB5_INIT(&context);
+
+    *authenticated = nameattrs->pac_verified;
+    if (complete)
+        *complete = 1;
+
+    kret = _krb5_get_ad(context, ticket->authorization_data,
+                        NULL, KRB5_AUTHDATA_WIN2K_PAC,
+                        value ? &data : NULL);
+
+    if (value) {
+       value->length = data.length;
+       value->value = data.data;
+    }
+
+    *minor_status = kret;
+    if (kret == ENOENT)
+        return GSS_S_UNAVAILABLE;
+    return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE;
+}
+
+static OM_uint32
+get_pac_buffer(OM_uint32 *minor_status,
+              const CompositePrincipal *name,
+              gss_const_buffer_t prefix,
+              gss_const_buffer_t attr,
+              gss_const_buffer_t frag,
+              int *authenticated,
+              int *complete,
+              gss_buffer_t value,
+              gss_buffer_t display_value,
+              int *more)
+{
+    krb5_error_code kret;
+    krb5_context context;
+    krb5_data data;
+    PrincipalNameAttrs *nameattrs = name->nameattrs;
+    krb5_data suffix;
+
+    krb5_data_zero(&data);
+
+    if (prefix->length || !authenticated ||
+       !nameattrs || !nameattrs->pac)
+        return GSS_S_UNAVAILABLE;
+
+    GSSAPI_KRB5_INIT(&context);
+
+    if (ATTR_EQ_PREFIX(attr, "urn:mspac:")) {
+        suffix.length = attr->length - (sizeof("urn:mspac:") - 1);
+        suffix.data = (char *)attr->value + sizeof("urn:mspac:") - 1;
+    } else if (ATTR_EQ_PREFIX(frag, "pac-")) {
+        suffix.length = frag->length - sizeof("pac-") - 1;
+        suffix.data = (char *)frag->value + sizeof("pac-") - 1;
+    } else
+        return GSS_S_UNAVAILABLE; /* should not be reached */
+
+    *authenticated = nameattrs->pac_verified;
+    if (complete)
+        *complete = 1;
+
+    kret = _krb5_pac_get_buffer_by_name(context, nameattrs->pac, &suffix,
+                                       value ? &data : NULL);
+
+    if (value) {
+       value->length = data.length;
+       value->value = data.data;
+    }
+
+    *minor_status = kret;
+    if (kret == ENOENT)
+        return GSS_S_UNAVAILABLE;
+    return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE;
+}
+
+static OM_uint32
+get_authz_data(OM_uint32 *minor_status,
+               const CompositePrincipal *name,
+               gss_const_buffer_t prefix,
+               gss_const_buffer_t attr,
+               gss_const_buffer_t frag,
+               int *authenticated,
+               int *complete,
+               gss_buffer_t value,
+               gss_buffer_t display_value,
+               int *more)
+{
+    krb5_error_code kret = 0;
+    PrincipalNameAttrs *nameattrs = name->nameattrs;
+    PrincipalNameAttrSrc *src = nameattrs ? nameattrs->source : NULL;
+    EncTicketPart *ticket = NULL;
+    krb5_context context;
+    krb5_data data;
+    char s[22];
+    char *end;
+    int64_t n;
+
+    if (src) switch (src->element) {
+    case choice_PrincipalNameAttrSrc_enc_ticket_part:
+        ticket = &src->u.enc_ticket_part;
+        break;
+    case choice_PrincipalNameAttrSrc_enc_kdc_rep_part:
+    default:
+        return GSS_S_UNAVAILABLE;
+    }
+
+    if (!nameattrs || !frag->length || frag->length > sizeof(s) - 1)
+        return GSS_S_UNAVAILABLE;
+
+    /* Output a specific AD element from the ticket or authenticator */
+    krb5_data_zero(&data);
+    memcpy(s, frag->value, frag->length);
+    s[frag->length] = '\0';
+    errno = 0;
+    n = strtoll(s, &end, 10);
+    if (end[0] == '\0' && (errno || n > INT_MAX || n < INT_MIN)) {
+        *minor_status = ERANGE;
+        return GSS_S_UNAVAILABLE;
+    }
+    if (end[0] != '\0') {
+        *minor_status = EINVAL;
+        return GSS_S_UNAVAILABLE;
+    }
+
+    if (authenticated)
+        *authenticated = 0;
+    if (complete)
+        *complete = 1;
+
+    GSSAPI_KRB5_INIT(&context);
+
+    kret = ENOENT;
+    if (ticket && ticket->authorization_data) {
+        kret = _krb5_get_ad(context, ticket->authorization_data,
+                            NULL, n, value ? &data : NULL);
+
+        /* If it's from the ticket, it _may_ be authenticated: */
+        if (kret == 0 && authenticated) {
+            if (n == KRB5_AUTHDATA_KDC_ISSUED)
+                *authenticated = nameattrs->kdc_issued_verified;
+            else if (n == KRB5_AUTHDATA_WIN2K_PAC)
+                *authenticated = nameattrs->pac_verified;
+        }
+    }
+    if (kret == ENOENT && nameattrs->authenticator_ad &&
+        n != KRB5_AUTHDATA_KDC_ISSUED &&
+        n != KRB5_AUTHDATA_WIN2K_PAC) {
+        kret = _krb5_get_ad(context, nameattrs->authenticator_ad,
+                            NULL, n, value ? &data : NULL);
+    }
+
+    if (value) {
+        value->length = data.length;
+        value->value = data.data;
+    }
+    *minor_status = kret;
+    if (kret == ENOENT)
+        return GSS_S_UNAVAILABLE;
+    return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE;
+}
+
+static OM_uint32
+get_ticket_authz_data(OM_uint32 *minor_status,
+                      const CompositePrincipal *name,
+                      gss_const_buffer_t prefix,
+                      gss_const_buffer_t attr,
+                      gss_const_buffer_t frag,
+                      int *authenticated,
+                      int *complete,
+                      gss_buffer_t value,
+                      gss_buffer_t display_value,
+                      int *more)
+{
+    krb5_error_code kret = 0;
+    PrincipalNameAttrs *nameattrs = name->nameattrs;
+    PrincipalNameAttrSrc *src = nameattrs ? nameattrs->source : NULL;
+    EncTicketPart *ticket = NULL;
+    size_t sz;
+
+    if (src) switch (src->element) {
+    case choice_PrincipalNameAttrSrc_enc_ticket_part:
+        ticket = &src->u.enc_ticket_part;
+        break;
+    case choice_PrincipalNameAttrSrc_enc_kdc_rep_part:
+    default:
+        return GSS_S_UNAVAILABLE;
+    }
+
+    if (!ticket)
+        return GSS_S_UNAVAILABLE;
+
+    if (complete)
+        *complete = 1;
+
+    if (frag->length == sizeof("kdc-issued") - 1 &&
+        strncmp(frag->value, "kdc-issued", sizeof("kdc-issued") - 1) == 0) {
+        krb5_context context;
+        krb5_data data;
+
+        GSSAPI_KRB5_INIT(&context);
+        if (authenticated)
+            *authenticated = nameattrs->kdc_issued_verified;
+
+        kret = _krb5_get_ad(context, ticket->authorization_data,
+                            NULL, KRB5_AUTHDATA_KDC_ISSUED,
+                            value ? &data : NULL);
+        if (value) {
+            value->length = data.length;
+            value->value = data.data;
+        }
+        if (kret == ENOENT)
+            return GSS_S_UNAVAILABLE;
+        *minor_status = kret;
+        return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE;
+    } else if (frag->length) {
+        return GSS_S_UNAVAILABLE;
+    }
+
+    /* Just because it's in the Ticket doesn't make it authenticated */
+    if (authenticated)
+        *authenticated = 0;
+
+    if (value) {
+        ASN1_MALLOC_ENCODE(AuthorizationData, value->value, value->length,
+                           ticket->authorization_data, &sz, kret);
+        *minor_status = kret;
+    }
+    return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE;
+}
+
+static OM_uint32
+get_authenticator_authz_data(OM_uint32 *minor_status,
+                             const CompositePrincipal *name,
+                             gss_const_buffer_t prefix,
+                             gss_const_buffer_t attr,
+                             gss_const_buffer_t frag,
+                             int *authenticated,
+                             int *complete,
+                             gss_buffer_t value,
+                             gss_buffer_t display_value,
+                             int *more)
+{
+    krb5_error_code kret = 0;
+    PrincipalNameAttrs *nameattrs = name->nameattrs;
+    size_t sz;
+
+    if (!nameattrs || !nameattrs->authenticator_ad)
+        return GSS_S_UNAVAILABLE;
+    if (authenticated)
+        *authenticated = 0;
+    if (complete)
+        *complete = 1;
+
+    if (value) {
+        ASN1_MALLOC_ENCODE(AuthorizationData, value->value, value->length,
+                           nameattrs->authenticator_ad, &sz, kret);
+        *minor_status = kret;
+    }
+    return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE;
+}
+
+static OM_uint32
+set_authenticator_authz_data(OM_uint32 *minor_status,
+                             CompositePrincipal *name,
+                             gss_const_buffer_t prefix,
+                             gss_const_buffer_t attr,
+                             gss_const_buffer_t frag,
+                             int complete,
+                             gss_buffer_t value)
+{
+    AuthorizationDataElement e;
+    krb5_error_code kret;
+    size_t sz;
+
+    if (!value)
+        return GSS_S_CALL_INACCESSIBLE_READ;
+    if (frag->length &&
+        !ATTR_EQ(frag, "if-relevant"))
+        return GSS_S_UNAVAILABLE;
+
+    if ((name->nameattrs == NULL &&
+        (name->nameattrs = calloc(1, sizeof(*name->nameattrs))) == NULL) ||
+        (name->nameattrs->want_ad == NULL &&
+         (name->nameattrs->want_ad =
+          calloc(1, sizeof(*name->nameattrs->want_ad))) == NULL)) {
+        *minor_status = ENOMEM;
+        return GSS_S_FAILURE;
+    }
+
+    memset(&e, 0, sizeof(e));
+    kret = decode_AuthorizationDataElement(value->value, value->length, &e,
+                                           &sz);
+    if (kret == 0) {
+        if (frag->length) {
+            AuthorizationData ir;
+
+            ir.len = 0;
+            ir.val = NULL;
+            kret = add_AuthorizationData(&ir, &e);
+            free_AuthorizationDataElement(&e);
+            if (kret == 0) {
+                e.ad_type = KRB5_AUTHDATA_IF_RELEVANT;
+                ASN1_MALLOC_ENCODE(AuthorizationData, e.ad_data.data,
+                                   e.ad_data.length, &ir, &sz, kret);
+                kret = add_AuthorizationData(name->nameattrs->want_ad, &e);
+            }
+            free_AuthorizationData(&ir);
+        } else {
+            kret = add_AuthorizationData(name->nameattrs->want_ad, &e);
+            free_AuthorizationDataElement(&e);
+        }
+    }
+
+    *minor_status = kret;
+    return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE;
+}
+
+static OM_uint32
+get_transited(OM_uint32 *minor_status,
+              const CompositePrincipal *name,
+              gss_const_buffer_t prefix,
+              gss_const_buffer_t attr,
+              gss_const_buffer_t frag,
+              int *authenticated,
+              int *complete,
+              gss_buffer_t value,
+              gss_buffer_t display_value,
+              int *more)
+{
+    krb5_error_code kret = 0;
+    PrincipalNameAttrs *nameattrs = name->nameattrs;
+    PrincipalNameAttrSrc *src = nameattrs ? nameattrs->source : NULL;
+    EncTicketPart *ticket = NULL;
+    size_t sz;
+
+    if (src) switch (src->element) {
+    case choice_PrincipalNameAttrSrc_enc_kdc_rep_part:
+        break;
+    case choice_PrincipalNameAttrSrc_enc_ticket_part:
+        ticket = &src->u.enc_ticket_part;
+        break;
+    default:
+        return GSS_S_UNAVAILABLE;
+    }
+
+    if (!nameattrs && !ticket)
+        return GSS_S_UNAVAILABLE;
+    if (nameattrs && !nameattrs->transited && !ticket)
+        return GSS_S_UNAVAILABLE;
+
+    if (authenticated)
+        *authenticated = 1;
+    if (complete)
+        *complete = 1;
+
+    if (value && ticket)
+        ASN1_MALLOC_ENCODE(TransitedEncoding, value->value, value->length,
+                           &ticket->transited, &sz, kret);
+    else if (value && nameattrs->transited)
+        ASN1_MALLOC_ENCODE(TransitedEncoding, value->value, value->length,
+                           nameattrs->transited, &sz, kret);
+    *minor_status = kret;
+    return kret == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE;
+}
+
+static OM_uint32
+get_canonical_name(OM_uint32 *minor_status,
+                   const CompositePrincipal *name,
+                   gss_const_buffer_t prefix,
+                   gss_const_buffer_t attr,
+                   gss_const_buffer_t frag,
+                   int *authenticated,
+                   int *complete,
+                   gss_buffer_t value,
+                   gss_buffer_t display_value,
+                   int *more)
+{
+    krb5_error_code kret = 0;
+    PrincipalNameAttrs *nameattrs = name->nameattrs;
+    PrincipalNameAttrSrc *src = nameattrs ? nameattrs->source : NULL;
+    krb5_principal p = NULL;
+    krb5_context context;
+    EncTicketPart *ticket = NULL;
+    EncKDCRepPart *kdcrep = NULL;
+
+    if (src) switch (src->element) {
+    case choice_PrincipalNameAttrSrc_enc_kdc_rep_part:
+        kdcrep = &src->u.enc_kdc_rep_part;
+        break;
+    case choice_PrincipalNameAttrSrc_enc_ticket_part:
+        ticket = &src->u.enc_ticket_part;
+        break;
+    default:
+        return GSS_S_UNAVAILABLE;
+    }
+
+    GSSAPI_KRB5_INIT(&context);
+
+    if (authenticated)
+        *authenticated = 1;
+    if (complete)
+        *complete = 1;
+
+    if (kdcrep) {
+        kret = _krb5_principalname2krb5_principal(context, &p,
+                                                  kdcrep->sname,
+                                                  kdcrep->srealm);
+    } else if (nameattrs && nameattrs->pac &&
+       (_krb5_pac_get_canon_principal(context, nameattrs->pac, &p)) == 0) {
+       if (authenticated)
+           *authenticated = nameattrs->pac_verified;
+    } else if (ticket) {
+        krb5_data data;
+        krb5_pac pac = NULL;
+
+        krb5_data_zero(&data);
+
+        /* Use canonical name from PAC if available */
+        kret = _krb5_get_ad(context, ticket->authorization_data,
+                            NULL, KRB5_AUTHDATA_WIN2K_PAC, &data);
+        if (kret == 0)
+            kret = krb5_pac_parse(context, data.data, data.length, &pac);
+        if (kret == 0)
+            kret = _krb5_pac_get_canon_principal(context, pac, &p);
+        if (kret == 0 && authenticated)
+            *authenticated = nameattrs->pac_verified;
+        else if (kret == ENOENT)
+            kret = _krb5_principalname2krb5_principal(context, &p,
+                                                      ticket->cname,
+                                                      ticket->crealm);
+
+        krb5_data_free(&data);
+        krb5_pac_free(context, pac);
+    } else
+        return GSS_S_UNAVAILABLE;
+    if (kret == 0 && value) {
+        OM_uint32 major;
+        /*
+         * Value is exported name token (exported composite name token
+         * should also work).
+         */
+        major = _gsskrb5_export_name(minor_status, (gss_name_t)p, value);
+        if (major != GSS_S_COMPLETE) {
+            krb5_free_principal(context, p);
+            return major;
+        }
+    }
+    if (kret == 0 && display_value) {
+        /* Display value is principal name display form */
+        kret = krb5_unparse_name(context, p,
+                                 (char **)&display_value->value);
+        if (kret == 0)
+            display_value->length = strlen(display_value->value);
+    }
+
+    krb5_free_principal(context, p);
+    if (kret) {
+        if (value) {
+            free(value->value);
+            value->length = 0;
+            value->value = NULL;
+        }
+        *minor_status = kret;
+        return GSS_S_UNAVAILABLE;
+    }
+    return GSS_S_COMPLETE;
+}
index 311686dc13a877223576ea6e02635e0b2cfe2420..6d727b4e289e871128aa1a0ad9437a044877d7af 100644 (file)
@@ -185,7 +185,8 @@ _gsskrb5_store_cred_into2(OM_uint32         *minor_status,
     const char *cs_user_name = NULL;
     const char *cs_app_name = NULL;
     char *ccache_name = NULL;
-    OM_uint32 major_status, junk;
+    OM_uint32 major_status = GSS_S_FAILURE;
+    OM_uint32 junk;
     OM_uint32 overwrite_cred = store_cred_flags & GSS_C_STORE_CRED_OVERWRITE;
     int default_for = 0;
 
@@ -346,7 +347,7 @@ _gsskrb5_store_cred_into2(OM_uint32         *minor_status,
     (void) gss_release_buffer_set(&junk, &env);
     free(ccache_name);
     *minor_status = ret;
-    return ret ? GSS_S_FAILURE : GSS_S_COMPLETE;
+    return ret ? major_status : GSS_S_COMPLETE;
 }
 
 OM_uint32 GSSAPI_CALLCONV
index 3cbba243f0b86c508ca58741ca6855e0e5429c06..c90a1443bc607f85e75df22591c2e9f3e12c7045 100644 (file)
@@ -90,9 +90,11 @@ copy_import(void)
     if (!equal)
        errx(1, "names not equal");
 
-    /* FIXME: This check is racy! */
-    if (lifetime1 != lifetime2)
+    /* This check is racy! */
+    if (getenv("TESTS_ENVIRONMENT") == NULL) && lifetime1 != lifetime2)
        errx(1, "lifetime not equal");
+    if (lifetime1 != lifetime2)
+       warnx("lifetime not equal");
 
     if (usage1 != usage1)
        errx(1, "usage not equal");
index b8f9e75c4bcc0d1ac9392e8704f5c8c36b336762..6077c8e26f4f0cdcb834fa47a8771e12fd66f067 100644 (file)
@@ -1,5 +1,6 @@
 EXPORTS
        __gss_c_nt_anonymous_oid_desc   DATA
+       __gss_c_nt_composite_export_oid_desc    DATA
        __gss_c_nt_export_name_oid_desc DATA
        __gss_c_nt_hostbased_service_oid_desc   DATA
        __gss_c_nt_hostbased_service_x_oid_desc DATA
@@ -41,7 +42,6 @@ EXPORTS
        gss_export_name
        gss_export_name_composite
        gss_export_sec_context
-       gss_get_instance
        gss_get_mic
        gss_get_neg_mechs
        gss_get_name_attribute
index fd2523fd8e3ea120aa9506e7ae4f8f25ce079b38..97ef57898da1d3dff141f8888236442760ad216e 100644 (file)
@@ -44,7 +44,15 @@ gss_compare_name(OM_uint32 *minor_status,
         * names have one. Otherwise, try to find common mechanism
         * names and compare them.
         */
-       if (name1->gn_value.value && name2->gn_value.value) {
+       if (name1->gn_value.value && name2->gn_value.value &&
+           name1->gn_type == GSS_C_NO_OID && name2->gn_type == GSS_C_NO_OID) {
+           *name_equal =
+               name1->gn_value.length == name2->gn_value.length &&
+               memcmp(name1->gn_value.value, name2->gn_value.value,
+                      name1->gn_value.length) == 0;
+       } else if (name1->gn_value.value && name2->gn_value.value &&
+                  name1->gn_type != GSS_C_NO_OID &&
+                  name2->gn_type != GSS_C_NO_OID) {
                *name_equal = 1;
                /* RFC 2743: anonymous names always compare false */
                if (gss_oid_equal(name1->gn_type, GSS_C_NT_ANONYMOUS) ||
index 3ba2dd84621e243a122723b8a62762adff5ff100..00561ce928e9fd8c769ceeae51e3c41f5cb95663 100644 (file)
@@ -262,8 +262,7 @@ gss_import_cred(OM_uint32 * minor_status,
            goto out;
        }
 
-       if (m->gm_import_cred == NULL &&
-           !gss_oid_equal(&m->gm_mech_oid, GSS_SPNEGO_MECHANISM)) {
+       if (m->gm_import_cred == NULL) {
            *minor_status = 0;
            major = GSS_S_BAD_MECH;
            goto out;
@@ -287,8 +286,7 @@ gss_import_cred(OM_uint32 * minor_status,
                continue;
        }
 
-       major = m->gm_import_cred(minor_status,
-                                 &buffer, &mcred);
+       major = m->gm_import_cred(minor_status, &buffer, &mcred);
        gss_release_buffer(&junk, &buffer);
        if (major != GSS_S_COMPLETE)
            goto out;
index 05a05f508dea3cf2226bc1f4cecbaae6fa1db19a..c0309809f74556ede164123f6f9061babd21acb6 100644 (file)
@@ -72,6 +72,10 @@ gss_export_sec_context(OM_uint32 *minor_status,
             verflags |= EXPORT_CONTEXT_FLAG_MECH_CTX;
 
         kret = krb5_store_uint8(sp, verflags);
+        if (kret) {
+            *minor_status = kret;
+            goto failure;
+        }
 
         if (ctx->gc_target_len) {
             _gss_mg_log(10, "gss-esc: exporting partial token %zu/%zu",
index d7559981dc532e8830e0c820b6f930641da29947..54930bf464525bb605aa135949819a7d03d9c645 100644 (file)
@@ -31,6 +31,7 @@
 static OM_uint32
 _gss_import_export_name(OM_uint32 *minor_status,
     const gss_buffer_t input_name_buffer,
+    const gss_OID name_type,
     gss_name_t *output_name)
 {
        OM_uint32 major_status;
@@ -65,6 +66,24 @@ _gss_import_export_name(OM_uint32 *minor_status,
        p += 2;
        len -= 2;
 
+        /*
+         * If the name token is a composite token (TOK_ID 0x04 0x02) then per
+         * RFC6680 everything after that is implementation-specific.  This
+         * mech-glue is pluggable however, so we need the format of the rest of
+         * the header to be stable, otherwise we couldn't reliably determine
+         * what mechanism the token is for and we'd have to try all of them.
+         *
+         * So... we keep the same format for the exported composite name token
+         * as for normal exported name tokens (see RFC2743, section 3.2), with
+         * the TOK_ID 0x04 0x02, but only up to the mechanism OID.  We don't
+         * enforce that there be a NAME_LEN in the exported composite name
+         * token, or that it match the length of the remainder of the token.
+         *
+         * FYI, at least one out-of-tree mechanism implements exported
+         * composite name tokens as the same as exported name tokens with
+         * attributes appended and the NAME_LEN not modified to match.
+         */
+
        /*
         * Get the mech length and the name length and sanity
         * check the size of of the buffer.
@@ -107,17 +126,19 @@ _gss_import_export_name(OM_uint32 *minor_status,
 
        mech_oid.elements = p;
 
-       if (len < t + 4)
-               return (GSS_S_BAD_NAME);
-       p += t;
-       len -= t;
+        if (!composite) {
+                if (len < t + 4)
+                        return (GSS_S_BAD_NAME);
+                p += t;
+                len -= t;
 
-       t = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
-       p += 4;
-       len -= 4;
+                t = ((unsigned long)p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
+                /* p += 4; // we're done using `p' now */
+                len -= 4;
 
-       if (!composite && len != t)
-               return (GSS_S_BAD_NAME);
+                if (len != t)
+                        return (GSS_S_BAD_NAME);
+        }
 
        m = __gss_get_mechanism(&mech_oid);
        if (!m || !m->gm_import_name)
@@ -127,7 +148,7 @@ _gss_import_export_name(OM_uint32 *minor_status,
         * Ask the mechanism to import the name.
         */
        major_status = m->gm_import_name(minor_status,
-           input_name_buffer, GSS_C_NT_EXPORT_NAME, &new_canonical_name);
+            input_name_buffer, name_type, &new_canonical_name);
        if (major_status != GSS_S_COMPLETE) {
                _gss_mg_error(m, *minor_status);
                return major_status;
@@ -156,6 +177,7 @@ _gss_import_export_name(OM_uint32 *minor_status,
  * - GSS_C_NT_USER_NAME
  * - GSS_C_NT_HOSTBASED_SERVICE
  * - GSS_C_NT_EXPORT_NAME
+ * - GSS_C_NT_COMPOSITE_EXPORT
  * - GSS_C_NT_ANONYMOUS
  * - GSS_KRB5_NT_PRINCIPAL_NAME
  *
@@ -197,20 +219,15 @@ gss_import_name(OM_uint32 *minor_status,
 
        _gss_load_mech();
 
-       /*
-        * Use GSS_NT_USER_NAME as default name type.
-        */
-       if (name_type == GSS_C_NO_OID)
-               name_type = GSS_C_NT_USER_NAME;
-
        /*
         * If this is an exported name, we need to parse it to find
         * the mechanism and then import it as an MN. See RFC 2743
         * section 3.2 for a description of the format.
         */
-       if (gss_oid_equal(name_type, GSS_C_NT_EXPORT_NAME)) {
-               return _gss_import_export_name(minor_status,
-                   input_name_buffer, output_name);
+       if (gss_oid_equal(name_type, GSS_C_NT_EXPORT_NAME) ||
+            gss_oid_equal(name_type, GSS_C_NT_COMPOSITE_EXPORT)) {
+                return _gss_import_export_name(minor_status, input_name_buffer,
+                                               name_type, output_name);
        }
 
 
@@ -221,13 +238,16 @@ gss_import_name(OM_uint32 *minor_status,
                return (GSS_S_FAILURE);
        }
 
-       major_status = _gss_intern_oid(minor_status,
-           name_type, &name->gn_type);
-       if (major_status) {
-               rname = (gss_name_t)name;
-               gss_release_name(&ms, (gss_name_t *)&rname);
-               return (GSS_S_FAILURE);
-       }
+       if (name_type != GSS_C_NO_OID) {
+               major_status = _gss_intern_oid(minor_status,
+                                              name_type, &name->gn_type);
+               if (major_status) {
+                       rname = (gss_name_t)name;
+                       gss_release_name(&ms, (gss_name_t *)&rname);
+                       return (GSS_S_FAILURE);
+               }
+       } else
+               name->gn_type = GSS_C_NO_OID;
 
        major_status = _gss_copy_buffer(minor_status,
            input_name_buffer, &name->gn_value);
@@ -245,11 +265,13 @@ gss_import_name(OM_uint32 *minor_status,
                 if ((m->gm_mech.gm_flags & GM_USE_MG_NAME))
                     continue;
 
-               major_status = gss_test_oid_set_member(minor_status,
-                   name_type, m->gm_name_types, &present);
+               if (name_type != GSS_C_NO_OID) {
+                           major_status = gss_test_oid_set_member(minor_status,
+                                   name_type, m->gm_name_types, &present);
 
-               if (major_status || present == 0)
-                       continue;
+                           if (GSS_ERROR(major_status) || present == 0)
+                                       continue;
+               }
 
                mn = malloc(sizeof(struct _gss_mechanism_name));
                if (!mn) {
index 0acae853324245dae70e4a18c94582ea28170aef..39b717e3dc2f96f7ce6021093413b1d79a77d233 100644 (file)
@@ -42,9 +42,9 @@ gss_import_sec_context(OM_uint32 *minor_status,
 
         _gss_mg_log(10, "gss-isc called");
 
-        if (!minor_status || !context_handle) {
+        if (!context_handle) {
             *minor_status = EFAULT;
-            return GSS_S_FAILURE;
+            return GSS_S_CALL_INACCESSIBLE_WRITE;
         }
 
        *minor_status = 0;
@@ -87,7 +87,7 @@ gss_import_sec_context(OM_uint32 *minor_status,
             if (ret != GSS_S_COMPLETE)
                 goto failure;
 
-            ctx->gc_input.value = calloc(target_len, 1);
+            ctx->gc_free_this = ctx->gc_input.value = calloc(target_len, 1);
            if (ctx->gc_input.value == NULL)
                goto failure;
 
index 0f6d14209af269ff95cb16dacea850bdead835cc..78c305689f007074cd76b41d258017a26bf593c1 100644 (file)
@@ -520,7 +520,8 @@ gss_krb5_ccache_name(OM_uint32 *minor_status,
        }
     }
 
-    *out_name = args.out_name;
+    if (out_name)
+        *out_name = args.out_name;
 
     return major_status;
 }
@@ -571,7 +572,7 @@ gsskrb5_extract_authtime_from_sec_context(OM_uint32 *minor_status,
 
     {
        unsigned char *buf = data_set->elements[0].value;
-       *authtime = (buf[3] <<24) | (buf[2] << 16) |
+       *authtime = ((unsigned long)buf[3] <<24) | (buf[2] << 16) |
            (buf[1] << 8) | (buf[0] << 0);
     }
 
@@ -729,7 +730,7 @@ gsskrb5_extract_key(OM_uint32 *minor_status,
     }
 
     *keyblock = calloc(1, sizeof(**keyblock));
-    if (keyblock == NULL) {
+    if (*keyblock == NULL) {
        ret = ENOMEM;
        goto out;
     }
index 60fe376a914e4592f51e91b67054e455b185a566..372e72dd5da8724a6976374cb5583045941d596e 100644 (file)
@@ -137,6 +137,8 @@ _gss_string_to_oid(const char* s, gss_OID *oidp)
                                }
                        }
                }
+                if (byte_count == 0)
+                    return EINVAL;
                if (!res) {
                        res = malloc(byte_count);
                        if (!res)
@@ -228,8 +230,12 @@ add_builtin(gssapi_mech_interface mech)
        free(m);
        return minor_status;
     }
-    gss_add_oid_set_member(&minor_status,
-                          &m->gm_mech.gm_mech_oid, &_gss_mech_oids);
+
+    if (gss_add_oid_set_member(&minor_status, &m->gm_mech.gm_mech_oid,
+                              &_gss_mech_oids) != GSS_S_COMPLETE) {
+       free(m);
+       return ENOMEM;
+    }
 
     /* pick up the oid sets of names */
 
@@ -237,8 +243,12 @@ add_builtin(gssapi_mech_interface mech)
        (*m->gm_mech.gm_inquire_names_for_mech)(&minor_status,
            &m->gm_mech.gm_mech_oid, &m->gm_name_types);
 
-    if (m->gm_name_types == NULL)
-       gss_create_empty_oid_set(&minor_status, &m->gm_name_types);
+    if (m->gm_name_types == NULL &&
+       gss_create_empty_oid_set(&minor_status,
+                                 &m->gm_name_types) != GSS_S_COMPLETE) {
+       free(m);
+       return ENOMEM;
+    }
 
     HEIM_TAILQ_INSERT_TAIL(&_gss_mechs, m, gm_link);
     return 0;
@@ -288,9 +298,15 @@ _gss_load_mech(void)
                return;
        }
 
-       add_builtin(__gss_krb5_initialize());
-       add_builtin(__gss_spnego_initialize());
-       add_builtin(__gss_ntlm_initialize());
+       if (add_builtin(__gss_krb5_initialize()))
+            _gss_mg_log(1, "Out of memory while adding builtin Kerberos GSS "
+                        "mechanism to the GSS mechanism switch");
+       if (add_builtin(__gss_spnego_initialize()))
+            _gss_mg_log(1, "Out of memory while adding builtin SPNEGO "
+                        "mechanism to the GSS mechanism switch");
+       if (add_builtin(__gss_ntlm_initialize()))
+            _gss_mg_log(1, "Out of memory while adding builtin NTLM "
+                        "mechanism to the GSS mechanism switch");
 
 #ifdef HAVE_DLOPEN
        fp = fopen(conf ? conf : _PATH_GSS_MECH, "r");
@@ -461,7 +477,9 @@ _gss_load_mech(void)
 out:
 
 #endif
-       add_builtin(__gss_sanon_initialize());
+       if (add_builtin(__gss_sanon_initialize()))
+            _gss_mg_log(1, "Out of memory while adding builtin SANON "
+                        "mechanism to the GSS mechanism switch");
        HEIMDAL_MUTEX_unlock(&_gss_mech_mutex);
 }
 
@@ -565,16 +583,3 @@ gss_oid_to_name(gss_const_OID oid)
 
        return NULL;
 }
-
-GSSAPI_LIB_FUNCTION uintptr_t GSSAPI_CALLCONV
-gss_get_instance(const char *libname)
-{
-    static const char *instance = "libgssapi";
-
-    if (strcmp(libname, "gssapi") == 0)
-       return (uintptr_t)instance;
-    else if (strcmp(libname, "krb5") == 0)
-       return krb5_get_instance(libname);
-
-    return 0;
-}
index 72fd9de4624599b0f98889bb091f53e56b929f43..5046faed02672710eb1d4d436bb00c2d2ba47a8c 100644 (file)
@@ -158,6 +158,10 @@ gss_pname_to_uid(OM_uint32 *minor_status,
     major = gss_localname(minor_status, pname, mech_type, &localname);
     if (GSS_ERROR(major))
         return major;
+    if (localname.length == 0) {
+        *minor_status = KRB5_NO_LOCALNAME;
+        return GSS_S_FAILURE;
+    }
 
     szLocalname = malloc(localname.length + 1);
     if (szLocalname == NULL) {
index 0d74091e054c2b68090b6b1e329477f918b00124..d451b87c4a71590dac297f35c8e50a9fd59bfa7e 100644 (file)
 
 #include <config.h>
 
-#include <krb5-types.h>
+#include <roken.h>
 
-#include <sys/types.h>
+#include <krb5-types.h>
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
 #include <ctype.h>
-#include <dlfcn.h>
-#include <errno.h>
 
 #include <heimbase.h>
 
 #include <gssapi_asn1.h>
 #include <der.h>
 
-#include <roken.h>
-
 #include <gssapi.h>
 #include <gssapi_mech.h>
 #include <gssapi_krb5.h>
index d6300006b21009aa295bb069cfdcde7234541470..6a3e8899ee76e5e8ec1ae6550fb92d329d5295f0 100644 (file)
@@ -171,12 +171,14 @@ _gss_ntlm_accept_sec_context
        output_token->value = malloc(out.length);
        if (output_token->value == NULL && out.length != 0) {
            OM_uint32 gunk;
+           heim_ntlm_free_buf(&out);
            _gss_ntlm_delete_sec_context(&gunk, context_handle, NULL);
            *minor_status = ENOMEM;
            return GSS_S_FAILURE;
        }
        memcpy(output_token->value, out.data, out.length);
        output_token->length = out.length;
+       heim_ntlm_free_buf(&out);
 
        ctx->flags = retflags;
 
index 84a710c69e6019262d7bf4f7f07b247543785d8a..57940156cb5924fa416b2ea3c3db5a948996b4f3 100644 (file)
@@ -76,10 +76,6 @@ _gss_ntlm_inquire_cred
        *cred_usage = 0;
     if (mechanisms)
        *mechanisms = GSS_C_NO_OID_SET;
-
-    if (cred_handle == GSS_C_NO_CREDENTIAL)
-       return GSS_S_NO_CRED;
-
     if (mechanisms) {
         ret = gss_create_empty_oid_set(minor_status, mechanisms);
         if (ret)
index a8c670c50b28497face21a859a26b06457469c9e..efa71d911dcbd08aa25b206126aa950d755c36e0 100644 (file)
@@ -194,7 +194,10 @@ v2_sign_message(gss_buffer_t in,
     HMAC_CTX c;
 
     HMAC_CTX_init(&c);
-    HMAC_Init_ex(&c, signkey, 16, EVP_md5(), NULL);
+    if (HMAC_Init_ex(&c, signkey, 16, EVP_md5(), NULL) == 0) {
+        HMAC_CTX_cleanup(&c);
+        return GSS_S_FAILURE;
+    }
 
     encode_le_uint32(seq, hmac);
     HMAC_Update(&c, hmac, 4);
index 41c30b76f1a8f6a3c53f740d39a743d278395b67..57587a020db31a4951bc70ad1e4b650ec6a08a9c 100644 (file)
@@ -39,6 +39,8 @@ OM_uint32 GSSAPI_CALLCONV _gss_ntlm_delete_sec_context
             gss_buffer_t output_token
            )
 {
+    OM_uint32 min;
+
     if (context_handle) {
        ntlm_ctx ctx = (ntlm_ctx)*context_handle;
        gss_cred_id_t cred = (gss_cred_id_t)ctx->client;
@@ -49,6 +51,10 @@ OM_uint32 GSSAPI_CALLCONV _gss_ntlm_delete_sec_context
            (*ctx->server->nsi_destroy)(minor_status, ctx->ictx);
 
        _gss_ntlm_release_cred(NULL, &cred);
+       memset_s(ctx->sessionkey.data, ctx->sessionkey.length, 0,
+                ctx->sessionkey.length);
+       krb5_data_free(&ctx->sessionkey);
+       gss_release_buffer(&min, &ctx->pac);
 
        memset(ctx, 0, sizeof(*ctx));
        free(ctx);
index 1063db19b0f1c32a20ba2156d508e70570f79ede..be9c987c4ca0b4546c1e8f59a4925d7c3dc66b12 100644 (file)
@@ -56,20 +56,25 @@ from_file(const char *fn, const char *target_domain,
        d = strtok_r(buf, ":", &str);
         free(*domainp);
        *domainp = NULL;
+        if (!d)
+            continue;
        if (d && target_domain != NULL && strcasecmp(target_domain, d) != 0)
            continue;
         *domainp = strdup(d);
-        if (*domainp == NULL)
+        if (*domainp == NULL) {
+           fclose(f);
             return ENOMEM;
+       }
        u = strtok_r(NULL, ":", &str);
        p = strtok_r(NULL, ":", &str);
        if (u == NULL || p == NULL)
            continue;
 
        *usernamep = strdup(u);
-        if (*usernamep == NULL)
+        if (*usernamep == NULL) {
+           fclose(f);
             return ENOMEM;
-
+       }
        heim_ntlm_nt_key(p, key);
 
        memset_s(buf, sizeof(buf), 0, sizeof(buf));
@@ -376,6 +381,7 @@ _gss_ntlm_init_sec_context
                if (RAND_bytes(nonce, sizeof(nonce)) != 1) {
                    _gss_ntlm_delete_sec_context(minor_status,
                                                 context_handle, NULL);
+                   heim_ntlm_free_type2(&type2);
                    *minor_status = EINVAL;
                    return GSS_S_FAILURE;
                }
@@ -394,6 +400,7 @@ _gss_ntlm_init_sec_context
            }
            if (ret) {
                _gss_ntlm_delete_sec_context(minor_status,context_handle,NULL);
+               heim_ntlm_free_type2(&type2);
                *minor_status = ret;
                return GSS_S_FAILURE;
            }
@@ -408,6 +415,7 @@ _gss_ntlm_init_sec_context
                if (type3.ntlm.data)
                    free(type3.ntlm.data);
                _gss_ntlm_delete_sec_context(minor_status,context_handle,NULL);
+               heim_ntlm_free_type2(&type2);
                *minor_status = ret;
                return GSS_S_FAILURE;
            }
@@ -421,6 +429,7 @@ _gss_ntlm_init_sec_context
                if (type3.ntlm.data)
                    free(type3.ntlm.data);
                _gss_ntlm_delete_sec_context(minor_status,context_handle,NULL);
+               heim_ntlm_free_type2(&type2);
                *minor_status = ret;
                return GSS_S_FAILURE;
            }
@@ -437,6 +446,7 @@ _gss_ntlm_init_sec_context
            if(ret) {
                _gss_ntlm_delete_sec_context(minor_status,
                                             context_handle, NULL);
+               heim_ntlm_free_type2(&type2);
                *minor_status = ret;
                return GSS_S_DEFECTIVE_TOKEN;
            }
@@ -444,6 +454,7 @@ _gss_ntlm_init_sec_context
            if (ti.domainname && strcmp(ti.domainname, name->domain) != 0) {
                _gss_ntlm_delete_sec_context(minor_status,
                                             context_handle, NULL);
+               heim_ntlm_free_type2(&type2);
                *minor_status = EINVAL;
                return GSS_S_FAILURE;
            }
@@ -459,6 +470,7 @@ _gss_ntlm_init_sec_context
            if (ret) {
                _gss_ntlm_delete_sec_context(minor_status,
                                             context_handle, NULL);
+               heim_ntlm_free_type2(&type2);
                *minor_status = ret;
                return GSS_S_FAILURE;
            }
@@ -470,6 +482,7 @@ _gss_ntlm_init_sec_context
            if (ret) {
                _gss_ntlm_delete_sec_context(minor_status,
                                             context_handle, NULL);
+               heim_ntlm_free_type2(&type2);
                *minor_status = ret;
                return GSS_S_FAILURE;
            }
@@ -482,6 +495,7 @@ _gss_ntlm_init_sec_context
            if (ret) {
                _gss_ntlm_delete_sec_context(minor_status,
                                             context_handle, NULL);
+               heim_ntlm_free_type2(&type2);
                *minor_status = ret;
                return GSS_S_FAILURE;
            }
@@ -499,6 +513,7 @@ _gss_ntlm_init_sec_context
            free(type3.ntlm.data);
        if (ret) {
            _gss_ntlm_delete_sec_context(minor_status, context_handle, NULL);
+           heim_ntlm_free_type2(&type2);
            *minor_status = ret;
            return GSS_S_FAILURE;
        }
@@ -515,6 +530,7 @@ _gss_ntlm_init_sec_context
 
        ctx->status |= STATUS_OPEN;
 
+       heim_ntlm_free_type2(&type2);
        return GSS_S_COMPLETE;
     }
 }
index e5c25596aa6d234b49e35156edaedaa8abd19cc7..1bce00fc5d6f6458ea72e56d84e74388fede96be 100644 (file)
@@ -252,6 +252,7 @@ kdc_type2(OM_uint32 *minor_status,
     krb5_data ti;
 
     memset(&type2, 0, sizeof(type2));
+    memset(out, 0, sizeof(*out));
 
     /*
      * Request data for type 2 packet from the KDC.
index 189308d96ea02e83375a76e5e435d4c6f46e90cb..1a228b69e1a98b16c33a2c79053e534aaddc40fe 100644 (file)
@@ -36,7 +36,8 @@ is_anonymous_identity_p(gss_buffer_t name_string, gss_OID name_type)
 {
     if (gss_oid_equal(name_type, GSS_C_NT_ANONYMOUS))
        return TRUE;
-    else if ((gss_oid_equal(name_type, GSS_C_NT_USER_NAME) ||
+    else if ((name_type == GSS_C_NO_OID ||
+             gss_oid_equal(name_type, GSS_C_NT_USER_NAME) ||
              gss_oid_equal(name_type, GSS_KRB5_NT_PRINCIPAL_NAME)) &&
        buffer_equal_p(name_string, _gss_sanon_wellknown_user_name))
        return TRUE;
@@ -58,17 +59,15 @@ storage_ret_der_oid(krb5_storage *sp, gss_OID_desc *oid)
     oid->elements = NULL;
 
     ret = krb5_ret_uint16(sp, &der_oid_len);
-    if (ret != 0)
+    if (ret == 0)
+        ret = krb5_ret_uint8(sp, &tag);
+    if (ret == 0)
+        ret = krb5_ret_uint8(sp, &oid_len);
+    if (ret)
        return ret;
-
-    ret = krb5_ret_uint8(sp, &tag);
     if (tag != 0x06)
        return EINVAL;
 
-    ret = krb5_ret_uint8(sp, &oid_len);
-    if (ret != 0)
-       return ret;
-
     if (der_oid_len != 2 + oid_len)
        return EINVAL;
 
@@ -125,10 +124,11 @@ import_export_name(OM_uint32 *minor,
     }
     if (ret == 0)
        ret = krb5_ret_uint32(sp, &name_len);
-    if (name_len != 1)
-       ret = EINVAL;
-    ret = krb5_ret_uint8(sp, &is_anonymous);
+    if (ret == 0)
+        ret = krb5_ret_uint8(sp, &is_anonymous);
     if (ret == 0) {
+        if (name_len != 1)
+            ret = EINVAL;
        if (is_anonymous == 1) {
            *output_name = _gss_sanon_anonymous_identity;
            major = GSS_S_COMPLETE;
@@ -151,9 +151,6 @@ _gss_sanon_import_name(OM_uint32 *minor,
                       const gss_OID input_name_type,
                       gss_name_t *output_name)
 {
-    heim_assert(input_name_type != GSS_C_NO_OID,
-               "Mechglue passed null OID to _gss_sanon_import_name");
-
     if (gss_oid_equal(input_name_type, GSS_C_NT_EXPORT_NAME))
        return import_export_name(minor, input_name_buffer, output_name);
 
index 8cb4211da266bebbfd7e5710dda9162ae095a005..c4ac7455cf6ef859e64abeeca7d8c49131bf6cf9 100644 (file)
@@ -743,6 +743,7 @@ acceptor_start
        }
     } else {
        *minor_status = 0;
+       gss_release_oid_set(&junk, &supported_mechs);
        HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
        return gss_mg_set_error_string(GSS_C_NO_OID, GSS_S_NO_CONTEXT,
                                       *minor_status,
index 13e28bb59fddb0fda8d7ee89e27c02d37e5b96ab..3f8aa5c3e7b112006b0ec3d367d7f2c52714a475 100644 (file)
@@ -904,12 +904,14 @@ cleanup:
 
     if (GSS_ERROR(major)) {
        if (!mech_error) {
-          krb5_context context = _gss_mg_krb5_context();
-
-          gss_mg_set_error_string(GSS_SPNEGO_MECHANISM,
-                                  major, *minor,
-                                  "NegoEx failed to initialize security context: %s",
-                                  krb5_get_error_message(context, *minor));
+           krb5_context context = _gss_mg_krb5_context();
+           const char *emsg = krb5_get_error_message(context, *minor);
+
+           gss_mg_set_error_string(GSS_SPNEGO_MECHANISM,
+                                   major, *minor,
+                                   "NegoEx failed to initialize security context: %s",
+                                   emsg);
+           krb5_free_error_message(context, emsg);
        }
 
        _gss_negoex_release_context(ctx);
@@ -1022,12 +1024,14 @@ cleanup:
 
     if (GSS_ERROR(major)) {
        if (!mech_error) {
-          krb5_context context = _gss_mg_krb5_context();
-
-          gss_mg_set_error_string(GSS_SPNEGO_MECHANISM,
-                                  major, *minor,
-                                  "NegoEx failed to accept security context: %s",
-                                  krb5_get_error_message(context, *minor));
+           krb5_context context = _gss_mg_krb5_context();
+           const char *emsg = krb5_get_error_message(context, *minor);
+
+           gss_mg_set_error_string(GSS_SPNEGO_MECHANISM,
+                                   major, *minor,
+                                   "NegoEx failed to accept security context: %s",
+                                   emsg);
+           krb5_free_error_message(context, emsg);
        }
 
        _gss_negoex_release_context(ctx);
index 30fb5cb231f75e593d55990a3bb5959beb596cd0..7446d15e0df13ec37f7a2aa7594de046bfc4e8ba 100644 (file)
@@ -56,6 +56,7 @@ static char *localname_string;
 static char *client_name;
 static char *client_password;
 static char *localname_string;
+static char *on_behalf_of_string;
 static int dns_canon_flag = -1;
 static int mutual_auth_flag = 0;
 static int dce_style_flag = 0;
@@ -134,6 +135,112 @@ string_to_oids(gss_OID_set *oidsetp, char *names)
     }
 }
 
+static void
+show_pac_client_info(gss_name_t n)
+{
+    gss_buffer_desc dv = GSS_C_EMPTY_BUFFER;
+    gss_buffer_desc v = GSS_C_EMPTY_BUFFER;
+    gss_buffer_desc a;
+    OM_uint32 maj, min;
+    int authenticated, complete, more, name_is_MN, found;
+    gss_OID MN_mech;
+    gss_buffer_set_t attrs = GSS_C_NO_BUFFER_SET;
+    size_t i;
+
+    krb5_error_code ret;
+    krb5_storage *sp = NULL;
+    uint16_t len = 0, *s;
+    uint64_t tmp;
+    char *logon_string = NULL;
+
+    maj = gss_inquire_name(&min, n, &name_is_MN, &MN_mech, &attrs);
+    if (maj != GSS_S_COMPLETE)
+       errx(1, "gss_inquire_name: %s",
+            gssapi_err(maj, min, GSS_KRB5_MECHANISM));
+
+    a.value = "urn:mspac:client-info";
+    a.length = sizeof("urn:mspac:client-info") - 1;
+
+    for (found = 0, i = 0; i < attrs->count; i++) {
+       gss_buffer_t attr = &attrs->elements[i];
+
+       if (attr->length == a.length &&
+           memcmp(attr->value, a.value, a.length) == 0) {
+           found++;
+           break;
+       }
+    }
+
+    gss_release_buffer_set(&min, &attrs);
+
+    if (!found)
+       errx(1, "gss_inquire_name: attribute %.*s not enumerated",
+            (int)a.length, (char *)a.value);
+
+    more = 0;
+    maj = gss_get_name_attribute(&min, n, &a, &authenticated, &complete, &v,
+                                 &dv, &more);
+    if (maj != GSS_S_COMPLETE)
+       errx(1, "gss_get_name_attribute: %s",
+            gssapi_err(maj, min, GSS_KRB5_MECHANISM));
+
+
+    sp = krb5_storage_from_readonly_mem(v.value, v.length);
+    if (sp == NULL)
+       errx(1, "show_pac_client_info: out of memory");
+
+    krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE);
+
+    ret = krb5_ret_uint64(sp, &tmp); /* skip over time */
+    if (ret == 0)
+       ret = krb5_ret_uint16(sp, &len);
+    if (ret || len == 0)
+       errx(1, "show_pac_client_info: invalid PAC logon info length");
+
+    s = malloc(len);
+    ret = krb5_storage_read(sp, s, len);
+    if (ret != len)
+       errx(1, "show_pac_client_info:, failed to read PAC logon name");
+
+    krb5_storage_free(sp);
+
+    {
+       size_t ucs2len = len / 2;
+       uint16_t *ucs2;
+       size_t u8len;
+       unsigned int flags = WIND_RW_LE;
+
+       ucs2 = malloc(sizeof(ucs2[0]) * ucs2len);
+       if (ucs2 == NULL)
+           errx(1, "show_pac_client_info: out of memory");
+
+       ret = wind_ucs2read(s, len, &flags, ucs2, &ucs2len);
+       free(s);
+       if (ret)
+           errx(1, "failed to convert string to UCS-2");
+
+       ret = wind_ucs2utf8_length(ucs2, ucs2len, &u8len);
+       if (ret)
+           errx(1, "failed to count length of UCS-2 string");
+
+       u8len += 1; /* Add space for NUL */
+       logon_string = malloc(u8len);
+       if (logon_string == NULL)
+           errx(1, "show_pac_client_info: out of memory");
+
+       ret = wind_ucs2utf8(ucs2, ucs2len, logon_string, &u8len);
+       free(ucs2);
+       if (ret)
+           errx(1, "failed to convert to UTF-8");
+    }
+
+    printf("logon name: %s\n", logon_string);
+    free(logon_string);
+
+    gss_release_buffer(&min, &dv);
+    gss_release_buffer(&min, &v);
+}
+
 static void
 loop(gss_OID mechoid,
      gss_OID nameoid, const char *target,
@@ -155,12 +262,15 @@ loop(gss_OID mechoid,
     OM_uint32 flags = 0, ret_cflags = 0, ret_sflags = 0;
     gss_OID actual_mech_client = GSS_C_NO_OID;
     gss_OID actual_mech_server = GSS_C_NO_OID;
-    struct gss_channel_bindings_struct i_channel_bindings_data = {0};
-    struct gss_channel_bindings_struct a_channel_bindings_data = {0};
+    struct gss_channel_bindings_struct i_channel_bindings_data;
+    struct gss_channel_bindings_struct a_channel_bindings_data;
     gss_channel_bindings_t i_channel_bindings_p = GSS_C_NO_CHANNEL_BINDINGS;
     gss_channel_bindings_t a_channel_bindings_p = GSS_C_NO_CHANNEL_BINDINGS;
     size_t offset = 0;
 
+    memset(&i_channel_bindings_data, 0, sizeof(i_channel_bindings_data));
+    memset(&a_channel_bindings_data, 0, sizeof(a_channel_bindings_data));
+
     *actual_mech = GSS_C_NO_OID;
 
     flags |= GSS_C_REPLAY_FLAG;
@@ -188,6 +298,32 @@ loop(gss_OID mechoid,
     if (GSS_ERROR(maj_stat))
        err(1, "import name creds failed with: %d", maj_stat);
 
+    if (on_behalf_of_string) {
+        AuthorizationDataElement e;
+        gss_buffer_desc attr, value;
+        int32_t kret;
+        size_t sz;
+
+        memset(&e, 0, sizeof(e));
+        e.ad_type = KRB5_AUTHDATA_ON_BEHALF_OF;
+        e.ad_data.length = strlen(on_behalf_of_string);
+        e.ad_data.data = on_behalf_of_string;
+        ASN1_MALLOC_ENCODE(AuthorizationDataElement, value.value, value.length,
+                           &e, &sz, kret);
+        if (kret)
+            errx(1, "Could not encode AD-ON-BEHALF-OF AuthorizationDataElement");
+        attr.value =
+            GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "authenticator-authz-data";
+        attr.length =
+            sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "authenticator-authz-data") - 1;
+        maj_stat = gss_set_name_attribute(&min_stat, gss_target_name, 1, &attr,
+                                          &value);
+        if (maj_stat != GSS_S_COMPLETE)
+            errx(1, "gss_set_name_attribute() failed with: %s",
+                 gssapi_err(maj_stat, min_stat, GSS_KRB5_MECHANISM));
+        free(value.value);
+    }
+
     input_token.length = 0;
     input_token.value = NULL;
 
@@ -351,6 +487,25 @@ loop(gss_OID mechoid,
        errx(1, "mech mismatch");
     *actual_mech = actual_mech_server;
 
+    if (on_behalf_of_string) {
+        gss_buffer_desc attr, value;
+
+        attr.value =
+            GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "authz-data#580";
+        attr.length =
+            sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "authz-data#580") - 1;
+        maj_stat = gss_get_name_attribute(&min_stat, src_name, &attr, NULL,
+                                          NULL, &value, NULL, NULL);
+        if (maj_stat != GSS_S_COMPLETE)
+            errx(1, "gss_get_name_attribute(authz-data#580) failed with %s",
+                 gssapi_err(maj_stat, min_stat, GSS_KRB5_MECHANISM));
+
+        if (value.length != strlen(on_behalf_of_string) ||
+            strncmp(value.value, on_behalf_of_string,
+                    strlen(on_behalf_of_string)) != 0)
+            errx(1, "AD-ON-BEHALF-OF did not match");
+        (void) gss_release_buffer(&min_stat, &value);
+    }
     if (localname_string) {
         gss_buffer_desc lname;
 
@@ -393,6 +548,9 @@ loop(gss_OID mechoid,
         } else
             warnx("display_name: %s",
                  gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
+       if (!anon_flag &&
+           gss_oid_equal(actual_mech_server, GSS_KRB5_MECHANISM))
+           show_pac_client_info(src_name);
     }
     gss_release_name(&min_stat, &src_name);
 
@@ -756,6 +914,8 @@ static struct getargs args[] = {
     {"server-time-offset",     0, arg_integer, &server_time_offset, "time", NULL },
     {"max-loops",      0, arg_integer, &max_loops, "time", NULL },
     {"token-split",    0, arg_integer, &token_split, "bytes", NULL },
+    {"on-behalf-of",   0, arg_string, &on_behalf_of_string, "principal",
+        "send authenticator authz-data AD-ON-BEHALF-OF" },
     {"version",        0,      arg_flag,       &version_flag, "print version", NULL },
     {"verbose",        'v',    arg_flag,       &verbose_flag, "verbose", NULL },
     {"help",   0,      arg_flag,       &help_flag,  NULL, NULL }
@@ -1102,7 +1262,7 @@ main(int argc, char **argv)
 
        if (maj_stat != GSS_S_COMPLETE)
            keyblock2 = NULL;
-       else if (limit_enctype && keyblock->keytype != limit_enctype)
+       else if (limit_enctype && keyblock && keyblock->keytype != limit_enctype)
            errx(1, "gsskrb5_get_subkey wrong enctype");
 
        if (keyblock || keyblock2) {
@@ -1130,7 +1290,7 @@ main(int argc, char **argv)
            if (ret)
                krb5_err(context, 1, ret, "krb5_string_to_enctype");
 
-           if (enctype != keyblock->keytype)
+           if (keyblock && enctype != keyblock->keytype)
                errx(1, "keytype is not the expected %d != %d",
                     (int)enctype, (int)keyblock2->keytype);
        }
index 866ee78ecf1fcfdd161321c8fd1b615be09d34c8..abfe390449d92505b6523d7d0ae8a1866ae10b9c 100644 (file)
@@ -102,10 +102,17 @@ copy_import(void)
     if (!equal)
        errx(1, "names not equal");
 
-    /* FIXME: This check is racy! */
-    if (lifetime1 != lifetime2)
+    /*
+     * This check is racy!  It tends to fail when run with valgrind.
+     *
+     * make check-valgrind sets TESTS_ENVIRONMENT in the environment...
+     */
+    if (getenv("TESTS_ENVIRONMENT") == NULL && lifetime1 != lifetime2)
        errx(1, "lifetime not equal %lu != %lu",
             (unsigned long)lifetime1, (unsigned long)lifetime2);
+    if (lifetime1 != lifetime2)
+       warnx("lifetime not equal %lu != %lu",
+              (unsigned long)lifetime1, (unsigned long)lifetime2);
 
     if (usage1 != usage2) {
        /* as long any of them is both are everything it ok */
@@ -127,10 +134,13 @@ copy_import(void)
     if (!equal)
        errx(1, "names not equal");
 
-    /* FIXME: This check is racy! */
-    if (lifetime1 != lifetime2)
+    /* This check is racy! */
+    if (getenv("TESTS_ENVIRONMENT") == NULL && lifetime1 != lifetime2)
        errx(1, "lifetime not equal %lu != %lu",
             (unsigned long)lifetime1, (unsigned long)lifetime2);
+    if (lifetime1 != lifetime2)
+       warnx("lifetime not equal %lu != %lu",
+              (unsigned long)lifetime1, (unsigned long)lifetime2);
 
     gss_release_cred(&min_stat, &cred1);
     gss_release_cred(&min_stat, &cred2);
index e195313505c4e5611b9aaf235e7b76a49e655716..933635e78c01afe139a2d104bb3f31aab68183e1 100644 (file)
 #include <gssapi.h>
 #include <gssapi_krb5.h>
 #include <gssapi_spnego.h>
+#include <krb5_asn1.h>
 #include <err.h>
 #include <getarg.h>
 
+static void make_composite_name(CompositePrincipal *, gss_name_t *);
+static void assert_attr(gss_name_t, const char *, OM_uint32, gss_buffer_t,
+                        const char *, int, int, int);
+static void assert_attr_unavail(gss_name_t, const char *);
+static void assert_attr_set(gss_name_t, gss_buffer_set_t);
+
 static void
-gss_print_errors (int min_stat)
+gss_print_errors(OM_uint32 stat, gss_OID mech)
 {
-    OM_uint32 new_stat;
-    OM_uint32 msg_ctx = 0;
-    gss_buffer_desc status_string;
+    OM_uint32 junk;
+    OM_uint32 more = 0;
+    gss_buffer_desc buf = GSS_C_EMPTY_BUFFER;
     OM_uint32 ret;
 
+    if (mech) {
+        junk = gss_oid_to_str(&junk, mech, &buf);
+        if (junk == GSS_S_COMPLETE)
+            fprintf(stderr, "mech = %.*s\n", (int)buf.length, (char *)buf.value);
+        gss_release_buffer(&junk, &buf);
+    }
     do {
-       ret = gss_display_status (&new_stat,
-                                 min_stat,
-                                 GSS_C_MECH_CODE,
-                                 GSS_C_NO_OID,
-                                 &msg_ctx,
-                                 &status_string);
-       if (!GSS_ERROR(ret)) {
-           fprintf (stderr, "%.*s\n", (int)status_string.length,
-                                       (char *)status_string.value);
-           gss_release_buffer (&new_stat, &status_string);
-       }
-    } while (!GSS_ERROR(ret) && msg_ctx != 0);
+       ret = gss_display_status(&junk,
+                                stat,
+                                mech ? GSS_C_MECH_CODE : GSS_C_GSS_CODE,
+                                mech,
+                                &more,
+                                &buf);
+       if (ret != GSS_S_COMPLETE)
+            errx(1, "gss_display_status() failed");
+        fprintf(stderr, "%.*s\n", (int)buf.length, (char *)buf.value);
+        gss_release_buffer(&junk, &buf);
+    } while (more);
 }
 
 static void
-gss_err(int exitval, int status, const char *fmt, ...)
+    __attribute__ ((__format__ (__printf__, 5, 6)))
+gss_err(int exitval,
+        OM_uint32 maj,
+        OM_uint32 min,
+        gss_OID mech,
+        const char *fmt, ...)
 {
     va_list args;
 
     va_start(args, fmt);
-    vwarnx (fmt, args);
-    gss_print_errors (status);
+    vwarnx(fmt, args);
     va_end(args);
-    exit (exitval);
+    gss_print_errors(maj, GSS_C_NO_OID);
+    if (mech)
+        gss_print_errors(min, mech);
+    exit(exitval);
+}
+
+#define MAKE_URN(tail)                                          \
+    { sizeof(GSS_KRB5_NAME_ATTRIBUTE_BASE_URN tail) - 1,        \
+        GSS_KRB5_NAME_ATTRIBUTE_BASE_URN tail }
+
+/*
+ * Test RFC6680 name attributes for Kerberos.
+ */
+static void
+check_name_attrs(void)
+{
+    CompositePrincipal p;
+    EncTicketPart *t;
+    gss_buffer_desc v = GSS_C_EMPTY_BUFFER;
+    gss_name_t n;
+    OM_uint32 maj, min;
+    int32_t ret;
+    gss_buffer_desc attrs[] = {
+        MAKE_URN("realm"),
+        MAKE_URN("name-ncomp"),
+        MAKE_URN("name-ncomp#0"),
+        MAKE_URN("peer-realm"),
+        MAKE_URN("ticket-authz-data"),
+        MAKE_URN("transit-path"),
+        MAKE_URN("canonical-name"),
+    }; /* Set of attributes we expect to see indicated */
+    gss_buffer_set_desc attr_set;
+    size_t i, sz;
+
+    memset(&p, 0, sizeof(p));
+    attr_set.elements = attrs;
+    /*
+     * attr_set.count is set in each of the following sections to ever more
+     * items.
+     */
+
+    /*
+     * Testing name attributes is pretty tricky.
+     *
+     * Our approach is to construct a composite name, construct an exported
+     * composite name token for it, import it, then test the gss_inquire_name()
+     * and gss_get_name_attribute() accessors, and then gss_display_name_ext().
+     *
+     * Ideally we'd test the accessors on names imported from query forms with
+     * gss_import_name(), and on names from established contexts.  However,
+     * that belongs in the test_context program.
+     *
+     * TODO: Implement and test gss_set_name_attribute() and
+     *       gss_delete_name_attribute().
+     */
+
+    /* First construct and test an unauthenticated name */
+    p.realm = estrdup("TEST.H5L.SE");
+    p.name.name_type = KRB5_NT_PRINCIPAL;
+    p.name.name_string.val = ecalloc(1, sizeof(p.name.name_string.val[0]));
+    p.name.name_string.len = 1;
+    p.name.name_string.val[0] = estrdup("someuser");
+    p.nameattrs = NULL;
+    make_composite_name(&p, &n);
+
+    /* Test the attributes we expect it to have */
+    v.length = sizeof("TEST.H5L.SE") - 1;
+    v.value = "TEST.H5L.SE";
+    assert_attr(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "realm", GSS_S_COMPLETE,
+                &v, "TEST.H5L.SE", 0, 1, 0);
+
+    i = 1;
+    v.length = sizeof(size_t);
+    v.value = &i;
+    assert_attr(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "name-ncomp",
+                GSS_S_COMPLETE, &v, "1", 0, 1, 0);
+
+    v.length = sizeof("someuser") - 1;
+    v.value = "someuser";
+    assert_attr(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "name-ncomp#0",
+                GSS_S_COMPLETE, &v, "someuser", 0, 1, 0);
+
+    attr_set.count = 3;
+    assert_attr_set(n, &attr_set);
+
+    /* Check that it does not have prefixed attributes */
+    assert_attr_unavail(n, "whatever " GSS_KRB5_NAME_ATTRIBUTE_BASE_URN
+                        "realm");
+    assert_attr_unavail(n, "whatever " GSS_KRB5_NAME_ATTRIBUTE_BASE_URN
+                        "name-ncomp");
+    assert_attr_unavail(n, "whatever " GSS_KRB5_NAME_ATTRIBUTE_BASE_URN
+                        "name-ncomp#0");
+    assert_attr_unavail(n, "what ever " GSS_KRB5_NAME_ATTRIBUTE_BASE_URN
+                        "name-ncomp#0");
+
+    /* Check that it does not have various other supported attributes */
+    assert_attr_unavail(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "peer-realm");
+    assert_attr_unavail(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "name-ncomp#1");
+    assert_attr_unavail(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "canonical-name");
+    assert_attr_unavail(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN
+                        "ticket-authz-data#pac");
+    assert_attr_unavail(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN
+                        "ticket-authz-data");
+    assert_attr_unavail(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "transit-path");
+
+    /* Exercise URN parser */
+    assert_attr_unavail(n, "urn:whatever");
+    assert_attr_unavail(n, "urn:whatever#");
+    assert_attr_unavail(n, "urn:what#ever");
+    assert_attr_unavail(n, "#");
+    assert_attr_unavail(n, "#whatever");
+    assert_attr_unavail(n, "whatever");
+    assert_attr_unavail(n, "what ever");
+    assert_attr_unavail(n, "what ever#");
+
+    /* Now test an authenticated name */
+    gss_release_name(&min, &n);
+    p.nameattrs = ecalloc(1, sizeof(p.nameattrs[0]));
+    p.nameattrs->authenticated = 1;
+    make_composite_name(&p, &n);
+
+    v.length = sizeof("TEST.H5L.SE") - 1;
+    v.value = "TEST.H5L.SE";
+    assert_attr(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "realm", GSS_S_COMPLETE,
+                &v, "TEST.H5L.SE", 1, 1, 0);
+
+    i = 1;
+    v.length = sizeof(size_t);
+    v.value = &i;
+    assert_attr(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "name-ncomp",
+                GSS_S_COMPLETE, &v, "1", 1, 1, 0);
+
+    v.length = sizeof("someuser") - 1;
+    v.value = "someuser";
+    assert_attr(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "name-ncomp#0",
+                GSS_S_COMPLETE, &v, "someuser", 1, 1, 0);
+
+    assert_attr_set(n, &attr_set);
+
+    /* Now add a peer realm */
+    gss_release_name(&min, &n);
+    p.nameattrs->peer_realm = ecalloc(1, sizeof(p.nameattrs->peer_realm[0]));
+    p.nameattrs->peer_realm[0] = estrdup("FOO.TEST.H5L.SE");
+    make_composite_name(&p, &n);
+
+    v.length = sizeof("FOO.TEST.H5L.SE") - 1;
+    v.value = "FOO.TEST.H5L.SE";
+    assert_attr(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "peer-realm",
+                GSS_S_COMPLETE, &v, "FOO.TEST.H5L.SE", 1, 1, 0);
+    attr_set.count = 4;
+    assert_attr_set(n, &attr_set);
+
+    /* Now add canonical name and an authz-data element */
+    gss_release_name(&min, &n);
+    p.nameattrs->source = ecalloc(1, sizeof(p.nameattrs->source[0]));
+    p.nameattrs->source->element = choice_PrincipalNameAttrSrc_enc_ticket_part;
+
+    t = &p.nameattrs->source->u.enc_ticket_part;
+    t->cname.name_type = KRB5_NT_PRINCIPAL;
+    t->cname.name_string.val = ecalloc(1, sizeof(t->cname.name_string.val[0]));
+    t->crealm = estrdup("TEST.H5L.SE");
+    t->cname.name_string.len = 1;
+    t->cname.name_string.val[0] = estrdup("realusername");
+    t->authorization_data = ecalloc(1, sizeof(t->authorization_data[0]));
+    t->authorization_data->val =
+        ecalloc(1, sizeof(t->authorization_data->val[0]));
+    t->authorization_data->len = 1;
+    t->authorization_data->val[0].ad_type =
+        KRB5_AUTHDATA_ON_BEHALF_OF; /* whatever */
+    t->authorization_data->val[0].ad_data.data =
+        estrdup("foobar@TEST.H5L.SE");
+    t->authorization_data->val[0].ad_data.length =
+        sizeof("foobar@TEST.H5L.SE") - 1;
+    make_composite_name(&p, &n);
+
+    assert_attr(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "canonical-name",
+                GSS_S_COMPLETE, GSS_C_NO_BUFFER, "realusername@TEST.H5L.SE", 1,
+                1, 0);
+
+    ASN1_MALLOC_ENCODE(AuthorizationData, v.value, v.length,
+                       t->authorization_data, &sz, ret);
+    if (ret)
+        errx(1, "Failed to encode AuthorizationData");
+
+    assert_attr(n, GSS_KRB5_NAME_ATTRIBUTE_BASE_URN "ticket-authz-data",
+                GSS_S_COMPLETE, &v, NULL, 0, 1, 0);
+    free(v.value);
+
+    attr_set.count = 7;
+    assert_attr_set(n, &attr_set);
+
+    gss_release_name(&min, &n);
+    free_CompositePrincipal(&p);
+
+    /*
+     * Test gss_display_name_ext() with a host-based service principal
+     * "host/somehost.test.h5l.se@TEST.H5L.SE".
+     *
+     * Where gss_display_name() would display this as a Kerberos principal
+     * name, gss_display_name_ext() with GSS_C_NT_HOSTBASED_SERVICE should
+     * display it as "host@somehost.test.h5l.se".
+     */
+    p.realm = estrdup("TEST.H5L.SE");
+    p.name.name_type = KRB5_NT_SRV_HST;
+    p.name.name_string.val = ecalloc(2, sizeof(p.name.name_string.val[0]));
+    p.name.name_string.len = 2;
+    p.name.name_string.val[0] = estrdup("host");
+    p.name.name_string.val[1] = estrdup("somehost.test.h5l.se");
+    p.nameattrs = NULL;
+    make_composite_name(&p, &n);
+
+    maj = gss_display_name_ext(&min, n, GSS_C_NT_HOSTBASED_SERVICE, &v);
+    if (maj)
+       gss_err(1, maj, min, GSS_KRB5_MECHANISM, "display name ext");
+    if (v.length != sizeof("host@somehost.test.h5l.se") - 1 ||
+        strncmp(v.value, "host@somehost.test.h5l.se", v.length) != 0)
+        errx(1, "display name ext");
+    gss_release_buffer(&min, &v);
+    gss_release_name(&min, &n);
+    free_CompositePrincipal(&p);
+
+    /*
+     * TODO:
+     *
+     *  - test URN fragments for access to specific authorization data element
+     *    types
+     *  - test GSS_C_ATTR_LOCAL_LOGIN_USER support (requires configuration or
+     *    that we register a plugin here)
+     */
 }
 
 static int version_flag = 0;
@@ -145,7 +389,7 @@ main(int argc, char **argv)
                               GSS_C_NT_HOSTBASED_SERVICE,
                               &name);
     if (maj_stat != GSS_S_COMPLETE)
-       gss_err(1, min_stat, "import name error");
+       gss_err(1, maj_stat, min_stat, GSS_C_NO_OID, "import name error");
     free(str);
 
     if (anon_flag)
@@ -158,13 +402,13 @@ main(int argc, char **argv)
                                      mech_oid,
                                      &MNname);
     if (maj_stat != GSS_S_COMPLETE)
-       gss_err(1, min_stat, "canonicalize name error");
+       gss_err(1, maj_stat, min_stat, mech_oid, "canonicalize name error");
 
     maj_stat = gss_export_name(&min_stat,
                               MNname,
                               &name_buffer);
     if (maj_stat != GSS_S_COMPLETE)
-       gss_err(1, min_stat, "export name error (KRB5)");
+       gss_err(1, maj_stat, min_stat, mech_oid, "export name error");
 
     /*
      * Import the exported name and compare
@@ -174,13 +418,13 @@ main(int argc, char **argv)
                               GSS_C_NT_EXPORT_NAME,
                               &MNname2);
     if (maj_stat != GSS_S_COMPLETE)
-       gss_err(1, min_stat, "import name error (exported KRB5 name)");
+       gss_err(1, maj_stat, min_stat, mech_oid, "export name error");
 
 
     maj_stat = gss_compare_name(&min_stat, MNname, MNname2, &equal);
     if (maj_stat != GSS_S_COMPLETE)
-       errx(1, "gss_compare_name");
-    if (equal == anon_flag)
+       gss_err(1, maj_stat, min_stat, mech_oid, "compare name error");
+    if (equal && anon_flag)
        errx(1, "names %s equal", anon_flag ? "incorrectly" : "not");
 
     gss_release_name(&min_stat, &MNname2);
@@ -205,13 +449,13 @@ main(int argc, char **argv)
                               GSS_C_NO_OID,
                               &name);
     if (maj_stat != GSS_S_COMPLETE)
-       gss_err(1, min_stat, "import (no oid) name error");
+       gss_err(1, maj_stat, min_stat, NULL, "import (no oid) name error");
 
     maj_stat = gss_import_name(&min_stat, &name_buffer,
                               GSS_KRB5_NT_USER_NAME,
                               &MNname);
     if (maj_stat != GSS_S_COMPLETE)
-       gss_err(1, min_stat, "import (krb5 mn) name error");
+       gss_err(1, maj_stat, min_stat, NULL, "import (krb5 mn) name error");
 
     free(str);
 
@@ -230,14 +474,16 @@ main(int argc, char **argv)
                                      GSS_SPNEGO_MECHANISM,
                                      &MNname);
     if (maj_stat != GSS_S_COMPLETE)
-       gss_err(1, min_stat, "canonicalize name error");
+       gss_err(1, maj_stat, min_stat, GSS_SPNEGO_MECHANISM,
+                "canonicalize name error");
 
 
     maj_stat = gss_export_name(&maj_stat,
                               MNname,
                               &name_buffer);
     if (maj_stat != GSS_S_COMPLETE)
-       gss_err(1, min_stat, "export name error (SPNEGO)");
+       gss_err(1, maj_stat, min_stat, GSS_SPNEGO_MECHANISM,
+                "export name error (SPNEGO)");
 
     gss_release_name(&min_stat, &MNname);
     gss_release_buffer(&min_stat, &name_buffer);
@@ -253,29 +499,177 @@ main(int argc, char **argv)
        maj_stat = gss_import_name(&min_stat, &name_buffer,
                                   GSS_C_NT_ANONYMOUS, &name);
        if (maj_stat != GSS_S_COMPLETE)
-           gss_err(1, min_stat, "import (anon) name error");
+            gss_err(1, maj_stat, min_stat, GSS_C_NO_OID,
+                    "import (anon) name error");
 
        maj_stat = gss_canonicalize_name(&min_stat, name,
                                         GSS_SANON_X25519_MECHANISM,
                                         &MNname);
        if (maj_stat != GSS_S_COMPLETE)
-           gss_err(1, min_stat, "canonicalize (anon) name error");
+            gss_err(1, maj_stat, min_stat, GSS_SANON_X25519_MECHANISM,
+                    "canonicalize (anon) name error");
 
        maj_stat = gss_display_name(&min_stat, MNname,
                                    &name_buffer, &name_type);
        if (maj_stat != GSS_S_COMPLETE)
-           gss_err(1, min_stat, "display_name (anon) name error");
+            gss_err(1, maj_stat, min_stat, GSS_SANON_X25519_MECHANISM,
+                    "display_name (anon) name error");
 
        if (!gss_oid_equal(name_type, GSS_C_NT_ANONYMOUS))
-           gss_err(1, 0, "display name type not anonymous");
+           errx(1, "display name type not anonymous");
        if (memcmp(name_buffer.value, "WELLKNOWN/ANONYMOUS@WELLKNOWN:ANONYMOUS",
                   sizeof("WELLKNOWN/ANONYMOUS@WELLKNOWN:ANONYMOUS") - 1) != 0)
-           gss_err(1, 0, "display name string not well known anonymous name");
+           errx(1, "display name string not well known anonymous name");
 
        gss_release_name(&min_stat, &MNname);
        gss_release_name(&min_stat, &name);
        gss_release_buffer(&min_stat, &name_buffer);
     }
 
+    check_name_attrs();
     return 0;
 }
+
+/* Copied from _gsskrb5_export_name_composite() */
+static void
+export_name_composite(CompositePrincipal *name, gss_buffer_t exported_name)
+{
+    gss_buffer_desc inner = GSS_C_EMPTY_BUFFER;
+    unsigned char *buf;
+    int32_t ret;
+    size_t sz;
+
+    ASN1_MALLOC_ENCODE(CompositePrincipal, inner.value, inner.length,
+                       (void *)name, &sz, ret);
+    if (ret)
+        errx(1, "Failed to encode exported composite name token");
+
+    exported_name->length = 10 + inner.length + GSS_KRB5_MECHANISM->length;
+    exported_name->value  = malloc(exported_name->length);
+    if (exported_name->value == NULL)
+        errx(1, "Failed to allocate exported composite name token");
+
+    /* TOK, MECH_OID_LEN, DER(MECH_OID), NAME_LEN, NAME */
+
+    buf = exported_name->value;
+    buf[0] = 0x04;
+    buf[1] = 0x02;
+    buf[2] = ((GSS_KRB5_MECHANISM->length + 2) >> 8) & 0xff;
+    buf[3] = (GSS_KRB5_MECHANISM->length + 2) & 0xff;
+    buf[4] = 0x06;
+    buf[5] = (GSS_KRB5_MECHANISM->length) & 0xFF;
+
+    memcpy(buf + 6, GSS_KRB5_MECHANISM->elements, GSS_KRB5_MECHANISM->length);
+    buf += 6 + GSS_KRB5_MECHANISM->length;
+
+    buf[0] = (inner.length >> 24) & 0xff;
+    buf[1] = (inner.length >> 16) & 0xff;
+    buf[2] = (inner.length >> 8) & 0xff;
+    buf[3] = (inner.length) & 0xff;
+    buf += 4;
+
+    memcpy(buf, inner.value, inner.length);
+    free(inner.value);
+}
+
+static void
+make_composite_name(CompositePrincipal *princ, gss_name_t *n)
+{
+    gss_buffer_desc token, exported;
+    OM_uint32 maj, min;
+
+    export_name_composite(princ, &token);
+    maj = gss_import_name(&min, &token, GSS_C_NT_COMPOSITE_EXPORT, n);
+    if (maj)
+       gss_err(1, maj, min, GSS_KRB5_MECHANISM, "import composite name");
+    maj = gss_export_name_composite(&min, *n, &exported);
+    if (maj)
+       gss_err(1, maj, min, GSS_KRB5_MECHANISM, "export composite name");
+    if (token.length != exported.length ||
+        memcmp(token.value, exported.value, token.length) != 0)
+        errx(1, "import/export composite token disagreement");
+    gss_release_buffer(&min, &exported);
+    free(token.value); /* Use free because we allocated this one */
+}
+
+static void
+assert_attr(gss_name_t n,
+            const char *aname,
+            OM_uint32 exp_maj,
+            gss_buffer_t exp_v,
+            const char *exp_dv,
+            int exp_authenticated,
+            int exp_complete,
+            int exp_multivalued)
+{
+    gss_buffer_desc dv = GSS_C_EMPTY_BUFFER;
+    gss_buffer_desc v = GSS_C_EMPTY_BUFFER;
+    gss_buffer_desc a;
+    OM_uint32 maj, min;
+    int authenticated, complete, more;
+
+    a.value = (void*)(uintptr_t)aname;
+    a.length = strlen(aname);
+    more = 0;
+    maj = gss_get_name_attribute(&min, n, &a, &authenticated, &complete, &v,
+                                 &dv, &more);
+    if (maj != GSS_S_COMPLETE && maj != exp_maj)
+       gss_err(1, maj, min, GSS_KRB5_MECHANISM,
+                "import composite name error");
+    if (maj == GSS_S_COMPLETE && maj != exp_maj)
+        errx(1, "unexpected name attribute %s", aname);
+    if (maj == GSS_S_COMPLETE) {
+        if (exp_v &&
+            (v.length != exp_v->length ||
+             memcmp(v.value, exp_v->value, exp_v->length) != 0))
+            errx(1, "import composite name: wrong %s value", aname);
+        if (exp_dv &&
+            (dv.length != strlen(exp_dv) ||
+             strncmp(dv.value, exp_dv, dv.length) != 0))
+            errx(1, "import composite name: wrong %s display value "
+                 "(wanted %s, got %.*s)", aname, exp_dv,
+                 (int)dv.length, (char *)dv.value);
+        if (authenticated != exp_authenticated)
+            errx(1, "import composite name: %s incorrectly marked "
+                 "%sauthenticated", aname, authenticated ? "" : "un");
+        if (complete != exp_complete)
+            errx(1, "import composite name: %s incorrectly marked "
+                 "%scomplete", aname, complete ? "" : "in");
+        if (more != exp_multivalued)
+            errx(1, "import composite name: %s incorrectly marked "
+                 "%s-valued", aname, more ? "multi" : "single");
+    }
+    gss_release_buffer(&min, &dv);
+    gss_release_buffer(&min, &v);
+}
+
+static void
+assert_attr_unavail(gss_name_t n, const char *aname)
+{
+    assert_attr(n, aname, GSS_S_UNAVAILABLE, GSS_C_NO_BUFFER, NULL, 0, 0, 0);
+}
+
+static void
+assert_attr_set(gss_name_t n, gss_buffer_set_t exp_as)
+{
+    OM_uint32 maj, min;
+    gss_buffer_set_t as = NULL;
+    gss_OID MN_mech = GSS_C_NO_OID;
+    size_t i;
+    int name_is_MN = 0;
+
+    maj = gss_inquire_name(&min, n, &name_is_MN, &MN_mech, &as);
+    if (maj)
+       gss_err(1, maj, min, MN_mech, "inquire name");
+    for (i = 0; i < as->count && i < exp_as->count; i++) {
+        if (as->elements[i].length != exp_as->elements[i].length ||
+            memcmp(as->elements[i].value, exp_as->elements[i].value,
+                   as->elements[i].length) != 0)
+            errx(1, "attribute sets differ");
+    }
+    if (i < as->count)
+            errx(1, "more attributes indicated than expected");
+    if (i < exp_as->count)
+            errx(1, "fewer attributes indicated than expected");
+    gss_release_buffer_set(&min, &as);
+}
index be266da773c43d7314c75657a452f6fac5a35902..7f482b53624066788f4f206bf5883808f4633481 100644 (file)
@@ -4,6 +4,7 @@ HEIMDAL_GSS_2.0 {
        global:
 #              __gss_c_nt_anonymous;
                __gss_c_nt_anonymous_oid_desc;
+               __gss_c_nt_composite_export_oid_desc;
                __gss_c_nt_export_name_oid_desc;
                __gss_c_nt_hostbased_service_oid_desc;
                __gss_c_nt_hostbased_service_x_oid_desc;
@@ -44,7 +45,6 @@ HEIMDAL_GSS_2.0 {
                gss_export_name;
                gss_export_name_composite;
                gss_export_sec_context;
-               gss_get_instance;
                gss_get_mic;
                gss_get_neg_mechs;
                gss_get_name_attribute;
index 1c610829feb3bf90183ffef146b3d1b2305d2878..bb36f74519070b26d5f0b6b775955d4ddf5e7cb3 100644 (file)
@@ -16,6 +16,7 @@ AM_CPPFLAGS += -I$(top_srcdir)/lib/hx509 \
 WFLAGS += $(WFLAGS_LITE) -Wno-error=unused-function
 # XXX: Make these not necessary:
 WFLAGS += -Wno-error=unused-result -Wno-error=deprecated-declarations
+WFLAGS += $(WFLAGS_UNUSED_BUT_SET_VAR)
 
 lib_LTLIBRARIES = libhcrypto.la
 check_LTLIBRARIES = libhctest.la
@@ -60,8 +61,7 @@ hcryptoinclude_HEADERS =      \
        rsa.h                   \
        sha.h                   \
        ui.h                    \
-       undef.h                 \
-       x25519_ref10.h
+       undef.h
 
 install-build-headers:: $(hcryptoinclude_HEADERS) $(x25519include_HEADERS)
        @foo='$(hcryptoinclude_HEADERS)'; \
@@ -103,6 +103,22 @@ SCRIPT_TESTS = \
 
 noinst_PROGRAMS = test_rand
 
+noinst_HEADERS = \
+       x25519/ed25519_ref10_fe_51.h    \
+       x25519/ed25519_ref10_fe_25_5.h  \
+       x25519/ed25519_ref10.h  \
+       x25519/fe_25_5/base.h   \
+       x25519/fe_25_5/base2.h  \
+       x25519/fe_25_5/constants.h  \
+       x25519/fe_25_5/fe.h \
+       x25519/fe_51/base.h \
+       x25519/fe_51/base2.h    \
+       x25519/fe_51/constants.h    \
+       x25519/fe_51/fe.h   \
+       x25519/align.h  \
+       x25519_ref10.h
+
+
 check_PROGRAMS = $(PROGRAM_TESTS) test_rsa test_dh example_evp_cipher
 check_SCRIPTS = $(SCRIPT_TESTS)
 
@@ -335,7 +351,12 @@ ltmsources = \
        libtommath/bn_s_mp_sqr_fast.c \
        libtommath/bn_s_mp_sub.c \
        libtommath/bn_s_mp_toom_mul.c \
-       libtommath/bn_s_mp_toom_sqr.c
+       libtommath/bn_s_mp_toom_sqr.c \
+       libtommath/tommath_private.h \
+       libtommath/tommath_cutoffs.h \
+       libtommath/tommath_superclass.h \
+       libtommath/tommath_class.h \
+       libtommath/tommath.h
 
 x25519sources = \
        x25519/ed25519_ref10.c \
index 15bf78738adf8b0151512e526b407da1c18bf635..62297b145f10273e12a7e3f390bebcf6e117c42f 100644 (file)
@@ -142,7 +142,8 @@ BN_bin2bn(const void *s, int len, BIGNUM *bn)
        return NULL;
     }
     hi->length = len;
-    memcpy(hi->data, s, len);
+    if (len)
+        memcpy(hi->data, s, len);
     return (BIGNUM *)hi;
 }
 
@@ -250,7 +251,7 @@ BN_set_bit(BIGNUM *bn, int bit)
     unsigned char *p;
 
     if ((bit / 8) > hi->length || hi->length == 0) {
-       size_t len = (bit + 7) / 8;
+       size_t len = bit == 0 ? 1 : (bit + 7) / 8;
        void *d = realloc(hi->data, len);
        if (d == NULL)
            return 0;
@@ -286,6 +287,9 @@ BN_set_word(BIGNUM *bn, unsigned long num)
     unsigned long num2;
     int i, len;
 
+    if (bn == NULL)
+       return 0;
+
     for (num2 = num, i = 0; num2 > 0; i++)
        num2 = num2 >> 8;
 
index 9f5c648ec945edacaccb7d8600022deee1fb2005..ac174180fb9262df86499fc36cd7d2e7cad97ab4 100644 (file)
@@ -728,6 +728,7 @@ DES_cfb64_encrypt(const void *in, void *out,
        int i = *num;
        unsigned char c;
 
+       memset(tmp, 0, DES_CBLOCK_LEN);
        while (length > 0) {
            if (i == 0) {
                DES_encrypt(uiv, ks, 1);
index 774f0e1176ab7840d47c32462655878767023e5e..720662199f99c990b055fc5386e67ebec80b7e10 100644 (file)
@@ -40,7 +40,7 @@
 
 #include "tommath.h"
 
-static void
+static int
 BN2mpz(mp_int *s, const BIGNUM *bn)
 {
     size_t len;
@@ -49,8 +49,12 @@ BN2mpz(mp_int *s, const BIGNUM *bn)
     len = BN_num_bytes(bn);
     p = malloc(len);
     BN_bn2bin(bn, p);
-    mp_read_unsigned_bin(s, p, len);
+    if (mp_from_ubin(s, p, len) != MP_OKAY) {
+       free(p);
+       return -1;
+    }
     free(p);
+    return 0;
 }
 
 
@@ -61,11 +65,14 @@ mpz2BN(mp_int *s)
     BIGNUM *bn;
     void *p;
 
-    size = mp_unsigned_bin_size(s);
+    size = mp_ubin_size(s);
     p = malloc(size);
-    if (p == NULL && size != 0)
+    if (p == NULL)
+       return NULL;
+    if (mp_to_ubin(s, p, SIZE_MAX, NULL) != MP_OKAY) {
+       free(p);
        return NULL;
-    mp_to_unsigned_bin(s, p);
+    };
 
     bn = BN_bin2bn(p, size, NULL);
     free(p);
@@ -110,11 +117,17 @@ ltm_dh_generate_key(DH *dh)
            dh->pub_key = NULL;
        }
 
-       mp_init_multi(&pub, &priv_key, &g, &p, NULL);
+       if (mp_init_multi(&pub, &priv_key, &g, &p, NULL) != MP_OKAY)
+           continue;
 
-       BN2mpz(&priv_key, dh->priv_key);
-       BN2mpz(&g, dh->g);
-       BN2mpz(&p, dh->p);
+       if (BN2mpz(&priv_key, dh->priv_key) != 0)
+           continue;
+
+       if (BN2mpz(&g, dh->g) != 0)
+           continue;
+
+       if (BN2mpz(&p, dh->p) != 0)
+           continue;
 
        res = mp_exptmod(&g, &priv_key, &p, &pub);
 
@@ -157,9 +170,18 @@ ltm_dh_compute_key(unsigned char *shared, const BIGNUM * pub, DH *dh)
     if (dh->pub_key == NULL || dh->g == NULL || dh->priv_key == NULL)
        return -1;
 
-    mp_init_multi(&s, &priv_key, &p, &peer_pub, NULL);
-    BN2mpz(&p, dh->p);
-    BN2mpz(&peer_pub, pub);
+    if (mp_init_multi(&s, &priv_key, &p, &peer_pub, NULL) != MP_OKAY)
+        return -1;
+
+    if (BN2mpz(&p, dh->p) != 0) {
+       ret = -1;
+       goto out;
+    }
+
+    if (BN2mpz(&peer_pub, pub) != 0) {
+       ret = 1;
+       goto out;
+    }
 
     /* check if peers pubkey is reasonable */
     if (mp_isneg(&peer_pub)
@@ -170,17 +192,20 @@ ltm_dh_compute_key(unsigned char *shared, const BIGNUM * pub, DH *dh)
        goto out;
     }
 
-    BN2mpz(&priv_key, dh->priv_key);
+    if (BN2mpz(&priv_key, dh->priv_key) != 0) {
+       ret = -1;
+       goto out;
+    }
 
     ret = mp_exptmod(&peer_pub, &priv_key, &p, &s);
-
     if (ret != 0) {
        ret = -1;
        goto out;
     }
 
-    ret = mp_unsigned_bin_size(&s);
-    mp_to_unsigned_bin(&s, shared);
+    ret = mp_ubin_size(&s);
+    if (mp_to_ubin(&s, shared, SIZE_MAX, NULL) != MP_OKAY)
+        ret = -1;
 
  out:
     mp_clear_multi(&s, &priv_key, &p, &peer_pub, NULL);
index 0447c4f48384ec37c362fb66f111cf31e49f89e5..5d2d214f7526a217404a98714aba7a793f6de576 100644 (file)
@@ -98,7 +98,7 @@ DH_new_method(ENGINE *engine)
     if (dh->engine) {
        dh->meth = ENGINE_get_DH(dh->engine);
        if (dh->meth == NULL) {
-           ENGINE_finish(engine);
+           ENGINE_finish(dh->engine);
            free(dh);
            return 0;
        }
index 9cea24821767fd4a9f4b5da966cc23d0bfe9c7af..3dae960fd0c8d64c521e1abd00427b2d14c33c4f 100644 (file)
@@ -44,15 +44,22 @@ struct hc_engine {
     const RSA_METHOD *rsa;
     const DH_METHOD *dh;
     const RAND_METHOD *rand;
+    void *dso_handle;
 };
 
-ENGINE *
+ENGINE *
 ENGINE_new(void)
 {
     ENGINE *engine;
 
     engine = calloc(1, sizeof(*engine));
+    if (engine == NULL)
+        return NULL;
     engine->references = 1;
+    engine->destroy = 0;
+    engine->dh = 0;
+    engine->rand = 0;
+    engine->dso_handle = 0;
 
     return engine;
 }
@@ -77,6 +84,8 @@ ENGINE_finish(ENGINE *engine)
        free(engine->id);
     if(engine->destroy)
        (*engine->destroy)(engine);
+    if (engine->dso_handle)
+       dlclose(engine->dso_handle);
 
     memset(engine, 0, sizeof(*engine));
     engine->references = -1;
@@ -299,15 +308,17 @@ ENGINE_by_dso(const char *path, const char *id)
 {
 #ifdef HAVE_DLOPEN
     ENGINE *engine;
-    void *handle;
     int ret;
 
     engine = calloc(1, sizeof(*engine));
     if (engine == NULL)
        return NULL;
-
-    handle = dlopen(path, RTLD_NOW | RTLD_LOCAL | RTLD_GROUP);
-    if (handle == NULL) {
+    engine->references = 0; /* ref will be added below */
+    engine->destroy = 0;
+    engine->dh = 0;
+    engine->rand = 0;
+    engine->dso_handle = dlopen(path, RTLD_NOW | RTLD_LOCAL | RTLD_GROUP);
+    if (engine->dso_handle == NULL) {
        /* printf("error: %s\n", dlerror()); */
        free(engine);
        return NULL;
@@ -317,16 +328,16 @@ ENGINE_by_dso(const char *path, const char *id)
        unsigned long version;
        openssl_v_check v_check;
 
-       v_check = (openssl_v_check)dlsym(handle, "v_check");
+       v_check = (openssl_v_check)dlsym(engine->dso_handle, "v_check");
        if (v_check == NULL) {
-           dlclose(handle);
+           dlclose(engine->dso_handle);
            free(engine);
            return NULL;
        }
 
        version = (*v_check)(OPENSSL_DYNAMIC_VERSION);
        if (version == 0) {
-           dlclose(handle);
+           dlclose(engine->dso_handle);
            free(engine);
            return NULL;
        }
@@ -335,16 +346,17 @@ ENGINE_by_dso(const char *path, const char *id)
     {
        openssl_bind_engine bind_engine;
 
-       bind_engine = (openssl_bind_engine)dlsym(handle, "bind_engine");
+       bind_engine =
+            (openssl_bind_engine)dlsym(engine->dso_handle, "bind_engine");
        if (bind_engine == NULL) {
-           dlclose(handle);
+           dlclose(engine->dso_handle);
            free(engine);
            return NULL;
        }
 
        ret = (*bind_engine)(engine, id, NULL); /* XXX fix third arg */
        if (ret != 1) {
-           dlclose(handle);
+           dlclose(engine->dso_handle);
            free(engine);
            return NULL;
        }
@@ -354,7 +366,6 @@ ENGINE_by_dso(const char *path, const char *id)
 
     ret = add_engine(engine);
     if (ret != 1) {
-       dlclose(handle);
        ENGINE_finish(engine);
        return NULL;
     }
index 23838709c8e9e178c90955d1a1ec598d1609d199..9cced4c536ce6c5b609cd7420f7940eeeaca3e59 100644 (file)
@@ -485,17 +485,20 @@ EVP_md2(void) HC_DEPRECATED_CRYPTO
  *
  */
 
-static void
+static int
 null_Init (void *m)
 {
+    return 1;
 }
-static void
+static int
 null_Update (void *m, const void * data, size_t size)
 {
+    return 1;
 }
-static void
+static int
 null_Final(void *res, void *m)
 {
+    return 1;
 }
 
 /**
index 6cdf4e97a4e90969e5d082c1fa1dfa55a27293ed..6b387ae90dc71e23db38756364b0a9b19ec86008 100644 (file)
@@ -85,7 +85,7 @@ HMAC_size(const HMAC_CTX *ctx)
     return EVP_MD_size(ctx->md);
 }
 
-void
+int
 HMAC_Init_ex(HMAC_CTX *ctx,
             const void *key,
             size_t keylen,
@@ -103,17 +103,26 @@ HMAC_Init_ex(HMAC_CTX *ctx,
 
        ctx->md = md;
        ctx->key_length = EVP_MD_size(ctx->md);
+        ctx->opad = NULL;
+        ctx->ipad = NULL;
+        ctx->ctx = NULL;
        ctx->buf = malloc(ctx->key_length);
-        ctx->opad = malloc(blockSize);
-        ctx->ipad = malloc(blockSize);
-        ctx->ctx = EVP_MD_CTX_create();
+        if (ctx->buf)
+            ctx->opad = malloc(blockSize);
+        if (ctx->opad)
+            ctx->ipad = malloc(blockSize);
+        if (ctx->ipad)
+            ctx->ctx = EVP_MD_CTX_create();
+        if (!ctx->buf || !ctx->opad || !ctx->ipad || !ctx->ctx)
+            return 0;
     }
 #if 0
     ctx->engine = engine;
 #endif
 
     if (keylen > blockSize) {
-       EVP_Digest(key, keylen, ctx->buf, NULL, ctx->md, engine);
+       if (EVP_Digest(key, keylen, ctx->buf, NULL, ctx->md, engine) == 0)
+            return 0;
        key = ctx->buf;
        keylen = EVP_MD_size(ctx->md);
     }
@@ -126,8 +135,10 @@ HMAC_Init_ex(HMAC_CTX *ctx,
     for (i = 0, p = ctx->opad; i < keylen; i++)
        p[i] ^= ((const unsigned char *)key)[i];
 
-    EVP_DigestInit_ex(ctx->ctx, ctx->md, ctx->engine);
+    if (EVP_DigestInit_ex(ctx->ctx, ctx->md, ctx->engine) == 0)
+        return 0;
     EVP_DigestUpdate(ctx->ctx, ctx->ipad, EVP_MD_block_size(ctx->md));
+    return 1;
 }
 
 void
@@ -156,7 +167,10 @@ HMAC(const EVP_MD *md,
     HMAC_CTX ctx;
 
     HMAC_CTX_init(&ctx);
-    HMAC_Init_ex(&ctx, key, key_size, md, NULL);
+    if (HMAC_Init_ex(&ctx, key, key_size, md, NULL) == 0) {
+        HMAC_CTX_cleanup(&ctx);
+        return NULL;
+    }
     HMAC_Update(&ctx, data, data_size);
     HMAC_Final(&ctx, hash, hash_len);
     HMAC_CTX_cleanup(&ctx);
index 2c7d9b8803a9f9ed6dd75a67c4cf0ee1ec87ac5f..cc99c879fb91cea584e055fb6ec032ffd2d193f6 100644 (file)
@@ -75,7 +75,7 @@ void    HMAC_CTX_free(HMAC_CTX *ctx);
 
 size_t HMAC_size(const HMAC_CTX *ctx);
 
-void   HMAC_Init_ex(HMAC_CTX *, const void *, size_t,
+int    HMAC_Init_ex(HMAC_CTX *, const void *, size_t,
                     const EVP_MD *, ENGINE *);
 void   HMAC_Update(HMAC_CTX *ctx, const void *data, size_t len);
 void   HMAC_Final(HMAC_CTX *ctx, void *md, unsigned int *len);
index a42fc70d9086028b43982fd93d5cbc7d8ee89a9b..6f91b64f50340211daf4796fc21d3c72f8347737 100644 (file)
@@ -3,7 +3,7 @@
 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
 /* SPDX-License-Identifier: Unlicense */
 
-#if defined(__STDC_IEC_559__) || defined(__GCC_IEC_559)
+#if defined(__STDC_IEC_559__) || defined(__GCC_IEC_559) || defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(_M_X86) || defined(__aarch64__) || defined(__arm__)
 mp_err mp_set_double(mp_int *a, double b)
 {
    uint64_t frac;
index 55c69390eef7a5c38b5bf90b53cefbb1032f1099..79879c35039a53413dc15b436ee45ff19071dc7d 100644 (file)
@@ -96,7 +96,7 @@ static mp_err s_read_urandom(void *p, size_t n)
    if (fd == -1) return MP_ERR;
 
    while (n > 0u) {
-      ssize_t ret = read(fd, p, n);
+      ssize_t ret = read(fd, q, n);
       if (ret < 0) {
          if (errno == EINTR) {
             continue;
index 7b29a4ce94893eb15216c527a508dd1a1aa380b6..9049fa81f91aeae389049885a1f13793d371399a 100644 (file)
@@ -625,7 +625,7 @@ LBL_ERR:
 
 }
 
-#if defined(__STDC_IEC_559__) || defined(__GCC_IEC_559)
+#if defined(__STDC_IEC_559__) || defined(__GCC_IEC_559) || defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(_M_X86) || defined(__aarch64__) || defined(__arm__)
 static int test_mp_set_double(void)
 {
    int i;
index bc2cdfe6e03e1a986120e60ffe52031f19fb19f6..e7b99fce2895b8e380a4bb445190a2ad0219a7ef 100644 (file)
@@ -424,7 +424,7 @@ int main(int argc, char **argv)
             break;
          case 'h':
             s_exit_code = EXIT_SUCCESS;
-         /* FALLTHROUGH */
+            /* FALLTHROUGH */
          default:
             s_usage(argv[0]);
          }
index 2852bd4d6b8a61bea202c43f2eb8da2c6c7d754e..1d5b73e60e5a99d02311309e6e9bf07c614349d5 100644 (file)
@@ -456,8 +456,11 @@ mpz2BN(mp_int *s)
     void *p;
 
     size = mp_ubin_size(s);
+    if (size == 0)
+       return NULL;
+
     p = malloc(size);
-    if (p == NULL && size != 0)
+    if (p == NULL)
        return NULL;
 
     ret = mp_to_ubin(s, p, SIZE_MAX, NULL);
@@ -534,8 +537,6 @@ ltm_rsa_generate_key(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb)
 
     bitsp = (bits + 1) / 2;
 
-    ret = -1;
-
     FIRST(mp_init_multi(&el, &p, &q, &n, &d,
                         &dmp1, &dmq1, &iqmp,
                         &t1, &t2, &t3, NULL));
index c99b2b6cbe95da6d908e010a892cf8686929fad2..6172b25413f1fe8deee264daf58e394416ba8e89 100644 (file)
@@ -114,7 +114,7 @@ RSA_new_method(ENGINE *engine)
     if (rsa->engine) {
        rsa->meth = ENGINE_get_RSA(rsa->engine);
        if (rsa->meth == NULL) {
-           ENGINE_finish(engine);
+           ENGINE_finish(rsa->engine);
            free(rsa);
            return 0;
        }
@@ -272,7 +272,10 @@ RSA_check_key(const RSA *key)
      * and then decrypt/verify.
      */
 
-    if ((rsa->d == NULL || rsa->n == NULL) &&
+    if (rsa->n == NULL)
+       return 0;
+
+    if (rsa->d == NULL &&
        (rsa->p == NULL || rsa->q || rsa->dmp1 == NULL || rsa->dmq1 == NULL || rsa->iqmp == NULL))
        return 0;
 
index 063a461cc161f65e52f2fd2d61563e71bb2e804c..36a5626a70864f75810c056e16c201f3cc50b41d 100644 (file)
@@ -51,7 +51,11 @@ main(int argc, char **argv)
                      "\x6f\xd1\x52\x4d\x54\x58\x73\x0f\xf3\x24";
 
     HMAC_CTX_init(&c);
-    HMAC_Init_ex(&c, hmackey, hmackey_size, EVP_sha1(), NULL);
+    if (HMAC_Init_ex(&c, hmackey, hmackey_size, EVP_sha1(), NULL) == 0) {
+        HMAC_CTX_cleanup(&c);
+        printf("out of memory\n");
+        return 1;
+    }
     HMAC_Update(&c, buf, sizeof(buf));
     HMAC_Final(&c, hmac, &hmaclen);
     HMAC_CTX_cleanup(&c);
index 562e5aa4dd027391f995559f545ed75be4c7b9d7..4b655f262c875dc8dab7c7dd76ff0cbefe53df0d 100644 (file)
@@ -276,7 +276,8 @@ check_hmac(void)
                      "\x6f\xd1\x52\x4d\x54\x58\x73\x0f\xf3\x24";
 
     HMAC_CTX_init(&c);
-    HMAC_Init_ex(&c, hmackey, hmackey_size, EVP_sha1(), NULL);
+    if (HMAC_Init_ex(&c, hmackey, hmackey_size, EVP_sha1(), NULL) == 0)
+        errx(1, "HMAC_Init_ex() out of memory");
     HMAC_Update(&c, buf, sizeof(buf));
     HMAC_Final(&c, hmac, &hmaclen);
     HMAC_CTX_cleanup(&c);
index 342aaffbe9604bf48a1de42b2010a37cf8149451..89ab15d9d3e50bc65778b7a09a30d2256c0ddfd2 100644 (file)
@@ -2,6 +2,8 @@
 
 include $(top_srcdir)/Makefile.am.common
 
+WFLAGS += $(WFLAGS_ENUM_CONV)
+
 AM_CPPFLAGS += -I../asn1 -I$(srcdir)/../asn1
 AM_CPPFLAGS += $(INCLUDE_openldap) -DHDB_DB_DIR=\"$(DIR_hdbdir)\"
 AM_CPPFLAGS += -I$(srcdir)/../krb5
@@ -13,38 +15,40 @@ AM_CPPFLAGS += -I$(DBHEADER)
 endif
 
 BUILT_SOURCES = \
-       $(gen_files_hdb:.x=.c)  \
+       $(gen_files_hdb)        \
        hdb_err.c \
        hdb_err.h
 
 gen_files_hdb = \
-       asn1_Salt.x \
-       asn1_Key.x \
-       asn1_Event.x \
-       asn1_HDBFlags.x \
-       asn1_GENERATION.x \
-       asn1_HDB_Ext_PKINIT_acl.x \
-       asn1_HDB_Ext_PKINIT_cert.x \
-       asn1_HDB_Ext_PKINIT_hash.x \
-       asn1_HDB_Ext_Constrained_delegation_acl.x \
-       asn1_HDB_Ext_KeyRotation.x \
-       asn1_HDB_Ext_Lan_Manager_OWF.x \
-       asn1_HDB_Ext_Password.x \
-       asn1_HDB_Ext_Aliases.x \
-       asn1_HDB_Ext_KeySet.x \
-       asn1_HDB_extension.x \
-       asn1_HDB_extensions.x \
-       asn1_HDB_EncTypeList.x \
-       asn1_HDB_EntryOrAlias.x \
-       asn1_KeyRotation.x \
-       asn1_KeyRotationFlags.x \
-       asn1_HDB_entry.x \
-       asn1_HDB_entry_alias.x \
-       asn1_HDB_keyset.x \
-       asn1_Keys.x
+       asn1_Event.c \
+       asn1_GENERATION.c \
+       asn1_HDB_EncTypeList.c \
+       asn1_HDB_Ext_Aliases.c \
+       asn1_HDB_Ext_Constrained_delegation_acl.c \
+       asn1_HDB_Ext_KeyRotation.c \
+       asn1_HDB_Ext_KeySet.c \
+       asn1_HDB_Ext_Lan_Manager_OWF.c \
+       asn1_HDB_Ext_Password.c \
+       asn1_HDB_Ext_PKINIT_acl.c \
+       asn1_HDB_Ext_PKINIT_cert.c \
+       asn1_HDB_Ext_PKINIT_hash.c \
+       asn1_HDB_EntryOrAlias.c \
+       asn1_HDB_entry_alias.c \
+       asn1_HDB_entry.c \
+       asn1_HDB_extension.c \
+       asn1_HDB_extensions.c \
+       asn1_HDB_keyset.c \
+       asn1_HDBFlags.c \
+       asn1_Key.c \
+       asn1_KeyRotation.c \
+       asn1_KeyRotationFlags.c \
+       asn1_Keys.c \
+       asn1_Salt.c
 
 CLEANFILES = $(BUILT_SOURCES) $(gen_files_hdb) \
-       hdb_asn1{,-priv}.h* hdb_asn1_files hdb_asn1-template.[cx]
+       hdb_asn1{,-priv}.h hdb_asn1_files hdb_asn1-template.c \
+       hdb_asn1_syms.c hdb_asn1_oids.c hdb_asn1.json \
+       testhdb-*
 
 LDADD = libhdb.la \
        ../krb5/libkrb5.la \
@@ -139,13 +143,14 @@ $(srcdir)/hdb-protos.h: $(dist_libhdb_la_SOURCES)
 $(srcdir)/hdb-private.h: $(dist_libhdb_la_SOURCES)
        cd $(srcdir); perl ../../cf/make-proto.pl -q -P comment -p hdb-private.h $(dist_libhdb_la_SOURCES) || rm -f hdb-private.h
 
-$(gen_files_hdb) hdb_asn1.hx hdb_asn1-priv.hx: hdb_asn1_files
+$(gen_files_hdb) hdb_asn1.h hdb_asn1-priv.h: hdb_asn1_files
+       for genfile in '$(gen_files_hdb)'; do \
+               $(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i $${genfile}; \
+       done
 
 hdb_asn1_files: $(ASN1_COMPILE_DEP) $(srcdir)/hdb.asn1
-       $(ASN1_COMPILE) --sequence=HDB-extensions       \
-                       --sequence=HDB-Ext-KeyRotation  \
-                       --sequence=HDB-Ext-KeySet       \
-                       --sequence=Keys $(srcdir)/hdb.asn1 hdb_asn1
+       $(ASN1_COMPILE) --option-file=$(srcdir)/hdb.opt $(srcdir)/hdb.asn1 hdb_asn1
+       @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i $$(cat hdb_asn1_files)
 
 # to help stupid solaris make
 
index 5ad9d9c5742489b04a564832d21029657709d91a..f4801f7c54e963b5e101d2b32a5c636d1b07af9d 100644 (file)
 
 RELDIR=lib\hdb
 
-!include ../../windows/NTMakefile.w32 
+intcflags=-DASN1_LIB
 
-gen_files_hdb = $(OBJ)\asn1_hdb_asn1.x
+!include ../../windows/NTMakefile.w32 
 
-$(gen_files_hdb) $(OBJ)\hdb_asn1.hx $(OBJ)\hdb_asn1-priv.hx: $(BINDIR)\asn1_compile.exe hdb.asn1
+$(OBJ)\asn1_hdb_asn1.c $(OBJ)\hdb_asn1.h $(OBJ)\hdb_asn1-priv.h: $(BINDIR)\asn1_compile.exe hdb.asn1
        cd $(OBJ)
-       $(BINDIR)\asn1_compile.exe --sequence=HDB-extensions --sequence=HDB-Ext-KeyRotation --sequence=HDB-Ext-KeySet --sequence=Keys --one-code-file $(SRCDIR)\hdb.asn1 hdb_asn1
+       $(BINDIR)\asn1_compile.exe --one-code-file --option-file=$(SRCDIR)\hdb.opt $(SRCDIR)\hdb.asn1 hdb_asn1
        cd $(SRCDIR)
 
-$(gen_files_hdb:.x=.c): $$(@R).x
-
 !ifdef OPENLDAP_MODULE
 
 ldap_dll = $(BINDIR)\hdb_ldap.dll
@@ -98,7 +96,7 @@ libhdb_OBJs = \
        $(OBJ)\mkey.obj         \
        $(OBJ)\ndbm.obj         \
        $(OBJ)\print.obj        \
-       $(gen_files_hdb:.x=.obj)        \
+       $(OBJ)\asn1_hdb_asn1.obj \
        $(OBJ)\hdb_err.obj
 
 $(OBJ)\hdb_err.c $(OBJ)\hdb_err.h: hdb_err.et
index 251eb9b77148d165fc1e7e0b4ad7f84dc43e0610..a92cc1372db5ca481eed5671590875eb52b7514d 100644 (file)
@@ -148,7 +148,7 @@ fetch_entry_or_alias(krb5_context context,
                      HDB *db,
                      krb5_const_principal principal,
                      unsigned flags,
-                     hdb_entry_ex *entry)
+                     hdb_entry *entry)
 {
     HDB_EntryOrAlias eoa;
     krb5_principal enterprise_principal = NULL;
@@ -180,7 +180,7 @@ fetch_entry_or_alias(krb5_context context,
     if (ret == 0)
         ret = decode_HDB_EntryOrAlias(value.data, value.length, &eoa, NULL);
     if (ret == 0 && eoa.element == choice_HDB_EntryOrAlias_entry) {
-        entry->entry = eoa.u.entry;
+        *entry = eoa.u.entry;
     } else if (ret == 0 && eoa.element == choice_HDB_EntryOrAlias_alias) {
         krb5_data_free(&key);
        ret = hdb_principal2key(context, eoa.u.alias.principal, &key);
@@ -190,7 +190,7 @@ fetch_entry_or_alias(krb5_context context,
        }
         if (ret == 0)
             /* No alias chaining */
-            ret = hdb_value2entry(context, &value, &entry->entry);
+            ret = hdb_value2entry(context, &value, entry);
        krb5_free_principal(context, eoa.u.alias.principal);
     } else if (ret == 0)
         ret = ENOTSUP;
@@ -200,7 +200,7 @@ fetch_entry_or_alias(krb5_context context,
         * the canonicalize flag is unset, the original specification in
         * draft-ietf-krb-wg-kerberos-referrals-03.txt says we should.
         */
-       entry->entry.flags.force_canonicalize = 1;
+       entry->flags.force_canonicalize = 1;
     }
 
     /* HDB_F_GET_ANY indicates request originated from KDC (not kadmin) */
@@ -208,7 +208,7 @@ fetch_entry_or_alias(krb5_context context,
         (flags & (HDB_F_CANON|HDB_F_GET_ANY)) == 0) {
 
         /* `principal' was alias but canon not req'd */
-        free_HDB_entry(&entry->entry);
+        free_HDB_entry(entry);
         ret = HDB_ERR_NOENTRY;
     }
 
@@ -221,7 +221,7 @@ fetch_entry_or_alias(krb5_context context,
 
 krb5_error_code
 _hdb_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal,
-               unsigned flags, krb5_kvno kvno, hdb_entry_ex *entry)
+               unsigned flags, krb5_kvno kvno, hdb_entry *entry)
 {
     krb5_error_code ret;
 
@@ -231,23 +231,23 @@ _hdb_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal,
 
     if ((flags & HDB_F_DECRYPT) && (flags & HDB_F_ALL_KVNOS)) {
        /* Decrypt the current keys */
-       ret = hdb_unseal_keys(context, db, &entry->entry);
+       ret = hdb_unseal_keys(context, db, entry);
        if (ret) {
-           hdb_free_entry(context, entry);
+           hdb_free_entry(context, db, entry);
            return ret;
        }
        /* Decrypt the key history too */
-       ret = hdb_unseal_keys_kvno(context, db, 0, flags, &entry->entry);
+       ret = hdb_unseal_keys_kvno(context, db, 0, flags, entry);
        if (ret) {
-           hdb_free_entry(context, entry);
+           hdb_free_entry(context, db, entry);
            return ret;
        }
     } else if ((flags & HDB_F_DECRYPT)) {
-       if ((flags & HDB_F_KVNO_SPECIFIED) == 0 || kvno == entry->entry.kvno) {
+       if ((flags & HDB_F_KVNO_SPECIFIED) == 0 || kvno == entry->kvno) {
            /* Decrypt the current keys */
-           ret = hdb_unseal_keys(context, db, &entry->entry);
+           ret = hdb_unseal_keys(context, db, entry);
            if (ret) {
-               hdb_free_entry(context, entry);
+               hdb_free_entry(context, db, entry);
                return ret;
            }
        } else {
@@ -257,9 +257,9 @@ _hdb_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal,
             * Find and decrypt the keys from the history that we want,
             * and swap them with the current keys
             */
-           ret = hdb_unseal_keys_kvno(context, db, kvno, flags, &entry->entry);
+           ret = hdb_unseal_keys_kvno(context, db, kvno, flags, entry);
            if (ret) {
-               hdb_free_entry(context, entry);
+               hdb_free_entry(context, db, entry);
                return ret;
            }
        }
@@ -271,9 +271,9 @@ _hdb_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal,
         * key was generated, but given the salt will be ignored by a keytab
         * client it doesn't hurt to include the default salt.
         */
-       ret = add_default_salts(context, db, &entry->entry);
+       ret = add_default_salts(context, db, entry);
        if (ret) {
-           hdb_free_entry(context, entry);
+           hdb_free_entry(context, db, entry);
            return ret;
        }
     }
@@ -325,20 +325,20 @@ hdb_remove_aliases(krb5_context context, HDB *db, krb5_data *key)
 
 static krb5_error_code
 hdb_add_aliases(krb5_context context, HDB *db,
-               unsigned flags, hdb_entry_ex *entry)
+               unsigned flags, hdb_entry *entry)
 {
     const HDB_Ext_Aliases *aliases;
     krb5_error_code code;
     krb5_data key, value;
     size_t i;
 
-    code = hdb_entry_get_aliases(&entry->entry, &aliases);
+    code = hdb_entry_get_aliases(entry, &aliases);
     if (code || aliases == NULL)
        return code;
 
     for (i = 0; i < aliases->aliases.len; i++) {
        hdb_entry_alias entryalias;
-       entryalias.principal = entry->entry.principal;
+       entryalias.principal = entry->principal;
 
        code = hdb_entry_alias2value(context, &entryalias, &value);
        if (code)
@@ -358,7 +358,7 @@ hdb_add_aliases(krb5_context context, HDB *db,
 
 /* Check if new aliases are already used for other entries */
 static krb5_error_code
-hdb_check_aliases(krb5_context context, HDB *db, hdb_entry_ex *entry)
+hdb_check_aliases(krb5_context context, HDB *db, hdb_entry *entry)
 {
     const HDB_Ext_Aliases *aliases = NULL;
     HDB_EntryOrAlias eoa;
@@ -370,7 +370,7 @@ hdb_check_aliases(krb5_context context, HDB *db, hdb_entry_ex *entry)
     krb5_data_zero(&value);
     akey = value;
 
-    ret = hdb_entry_get_aliases(&entry->entry, &aliases);
+    ret = hdb_entry_get_aliases(entry, &aliases);
     for (i = 0; ret == 0 && aliases && i < aliases->aliases.len; i++) {
        ret = hdb_principal2key(context, &aliases->aliases.val[i], &akey);
         if (ret == 0)
@@ -385,7 +385,7 @@ hdb_check_aliases(krb5_context context, HDB *db, hdb_entry_ex *entry)
             ret = HDB_ERR_EXISTS;
         if (ret == 0 && eoa.element == choice_HDB_EntryOrAlias_alias &&
             !krb5_principal_compare(context, eoa.u.alias.principal,
-                                    entry->entry.principal))
+                                    entry->principal))
             /* New alias names an existing alias of a different entry */
             ret = HDB_ERR_EXISTS;
         if (ret == HDB_ERR_NOENTRY) /* from db->hdb__get */
@@ -433,14 +433,8 @@ hdb_derive_etypes(krb5_context context, hdb_entry *e, HDB_Ext_KeySet *base_keys)
         free(e->etypes->val);
         e->etypes->len = 0;
         e->etypes->val = 0;
-    }
-
-    if (e->etypes == NULL &&
-        (e->etypes = malloc(sizeof(e->etypes[0]))) == NULL)
+    } else if ((e->etypes = calloc(1, sizeof(e->etypes[0]))) == NULL) {
         ret = krb5_enomem(context);
-    if (ret == 0) {
-        e->etypes->len = 0;
-        e->etypes->val = 0;
     }
     if (ret == 0 &&
         (e->etypes->val = calloc(netypes, sizeof(e->etypes->val[0]))) == NULL)
@@ -465,13 +459,13 @@ hdb_derive_etypes(krb5_context context, hdb_entry *e, HDB_Ext_KeySet *base_keys)
 }
 
 krb5_error_code
-_hdb_store(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry)
+_hdb_store(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry)
 {
     krb5_data key, value;
     int code;
 
-    if (entry->entry.flags.do_not_store ||
-       entry->entry.flags.force_canonicalize)
+    if (entry->flags.do_not_store ||
+       entry->flags.force_canonicalize)
        return HDB_ERR_MISUSE;
     /* check if new aliases already is used */
     code = hdb_check_aliases(context, db, entry);
@@ -482,7 +476,7 @@ _hdb_store(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry)
         return 0;
 
     if ((flags & HDB_F_PRECHECK)) {
-        code = hdb_principal2key(context, entry->entry.principal, &key);
+        code = hdb_principal2key(context, entry->principal, &key);
         if (code)
             return code;
         code = db->hdb__get(context, db, key, &value);
@@ -494,29 +488,31 @@ _hdb_store(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry)
         return code ? code : HDB_ERR_EXISTS;
     }
 
-    if ((entry->entry.etypes == NULL || entry->entry.etypes->len == 0) &&
-        (code = hdb_derive_etypes(context, &entry->entry, NULL)))
+    if ((entry->etypes == NULL || entry->etypes->len == 0) &&
+        (code = hdb_derive_etypes(context, entry, NULL)))
         return code;
 
-    if (entry->entry.generation == NULL) {
+    if (entry->generation == NULL) {
        struct timeval t;
-       entry->entry.generation = malloc(sizeof(*entry->entry.generation));
-       if(entry->entry.generation == NULL) {
+       entry->generation = malloc(sizeof(*entry->generation));
+       if(entry->generation == NULL) {
            krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
            return ENOMEM;
        }
        gettimeofday(&t, NULL);
-       entry->entry.generation->time = t.tv_sec;
-       entry->entry.generation->usec = t.tv_usec;
-       entry->entry.generation->gen = 0;
+       entry->generation->time = t.tv_sec;
+       entry->generation->usec = t.tv_usec;
+       entry->generation->gen = 0;
     } else
-       entry->entry.generation->gen++;
+       entry->generation->gen++;
 
-    code = hdb_seal_keys(context, db, &entry->entry);
+    code = hdb_seal_keys(context, db, entry);
     if (code)
        return code;
 
-    hdb_principal2key(context, entry->entry.principal, &key);
+    code = hdb_principal2key(context, entry->principal, &key);
+    if (code)
+        return code;
 
     /* remove aliases */
     code = hdb_remove_aliases(context, db, &key);
@@ -524,8 +520,9 @@ _hdb_store(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry)
        krb5_data_free(&key);
        return code;
     }
-    hdb_entry2value(context, &entry->entry, &value);
-    code = db->hdb__put(context, db, flags & HDB_F_REPLACE, key, value);
+    code = hdb_entry2value(context, entry, &value);
+    if (code == 0)
+        code = db->hdb__put(context, db, flags & HDB_F_REPLACE, key, value);
     krb5_data_free(&value);
     krb5_data_free(&key);
     if (code)
@@ -554,8 +551,9 @@ _hdb_remove(krb5_context context, HDB *db,
      * HDB_entry_alias instead and assume it's an entry if decoding fails...
      */
 
-    hdb_principal2key(context, principal, &key);
-    code = db->hdb__get(context, db, key, &value);
+    code = hdb_principal2key(context, principal, &key);
+    if (code == 0)
+        code = db->hdb__get(context, db, key, &value);
     if (code == 0) {
         code = decode_HDB_EntryOrAlias(value.data, value.length, &eoa, NULL);
         krb5_data_free(&value);
@@ -573,7 +571,8 @@ _hdb_remove(krb5_context context, HDB *db,
         return code;
     }
 
-    code = hdb_remove_aliases(context, db, &key);
+    if (code == 0)
+        code = hdb_remove_aliases(context, db, &key);
     if (code == 0)
         code = db->hdb__del(context, db, key);
     krb5_data_free(&key);
@@ -714,7 +713,7 @@ derive_keyset(krb5_context context,
 {
     dks->kvno = kvno;
     dks->keys.val = 0;
-    dks->set_time = malloc(sizeof(*dks->set_time));
+    dks->set_time = malloc(sizeof(*(dks->set_time)));
     if (dks->set_time == NULL)
         return krb5_enomem(context);
     *dks->set_time = set_time;
@@ -724,7 +723,7 @@ derive_keyset(krb5_context context,
 /* Possibly derive and install in `h' a keyset identified by `t' */
 static krb5_error_code
 derive_keys_for_kr(krb5_context context,
-                   hdb_entry_ex *h,
+                   hdb_entry *h,
                    HDB_Ext_KeySet *base_keys,
                    int is_current_keyset,
                    int rotation_period_offset,
@@ -798,7 +797,7 @@ derive_keys_for_kr(krb5_context context,
     ret = derive_keyset(context, &base_keys->val[i].keys, princ, etype, kvno,
                         set_time, &dks);
     if (ret == 0)
-        ret = hdb_install_keyset(context, &h->entry, is_current_keyset, &dks);
+        ret = hdb_install_keyset(context, h, is_current_keyset, &dks);
 
     free_HDB_keyset(&dks);
     return ret;
@@ -807,7 +806,7 @@ derive_keys_for_kr(krb5_context context,
 /* Derive and install current keys, and possibly preceding or next keys */
 static krb5_error_code
 derive_keys_for_current_kr(krb5_context context,
-                           hdb_entry_ex *h, 
+                           hdb_entry *h, 
                            HDB_Ext_KeySet *base_keys,
                            const char *princ,
                            unsigned int flags,
@@ -873,12 +872,12 @@ derive_keys_for_current_kr(krb5_context context,
  * Arguments:
  *
  *  - `flags' is the flags passed to `hdb_fetch_kvno()'
- *  - `princ' is the name of the principal we'll end up with in `h->entry'
+ *  - `princ' is the name of the principal we'll end up with in `entry'
  *  - `h_is_namespace' indicates whether `h' is for a namespace or a concrete
  *     principal (that might nonetheless have virtual/derived keys)
  *  - `t' is the time such that the derived keys are for kvnos needed at `t'
  *  - `etype' indicates what enctype to derive keys for (0 for all enctypes in
- *    `h->entry.etypes')
+ *    `entry->etypes')
  *  - `kvno' requests a particular kvno, or all if zero
  *
  * The caller doesn't know if the principal needs key derivation -- we make
@@ -970,7 +969,7 @@ derive_keys(krb5_context context,
             krb5_timestamp t,
             krb5int32 etype,
             krb5uint32 kvno,
-            hdb_entry_ex *h)
+            hdb_entry *h)
 {
     HDB_Ext_KeyRotation kr;
     HDB_Ext_KeySet base_keys;
@@ -979,14 +978,9 @@ derive_keys(krb5_context context,
     char *p = NULL;
     int valid = 1;
 
-    if (!h_is_namespace && !h->entry.flags.virtual_keys)
+    if (!h_is_namespace && !h->flags.virtual_keys)
         return 0;
-    h->entry.flags.virtual = 1;
-    if (h_is_namespace) {
-        /* Set the entry's principal name */
-        free_Principal(h->entry.principal);
-        ret = copy_Principal(princ, h->entry.principal);
-    }
+    h->flags.virtual = 1;
 
     kr.len = 0;
     kr.val = 0;
@@ -994,7 +988,7 @@ derive_keys(krb5_context context,
         const HDB_Ext_KeyRotation *ckr;
 
         /* Installing keys invalidates `ckr', so we copy it */
-        ret = hdb_entry_get_key_rotation(context, &h->entry, &ckr);
+        ret = hdb_entry_get_key_rotation(context, h, &ckr);
         if (!ckr)
             return ret;
         if (ret == 0)
@@ -1005,11 +999,11 @@ derive_keys(krb5_context context,
     base_keys.val = 0;
     base_keys.len = 0;
     if (ret == 0)
-        ret = hdb_remove_base_keys(context, &h->entry, &base_keys);
+        ret = _hdb_remove_base_keys(context, h, &base_keys, &kr);
 
-    /* Make sure we have h->entry.etypes */
-    if (ret == 0 && !h->entry.etypes)
-        ret = hdb_derive_etypes(context, &h->entry, &base_keys);
+    /* Make sure we have h->etypes */
+    if (ret == 0 && !h->etypes)
+        ret = hdb_derive_etypes(context, h, &base_keys);
 
     /* Keys not desired?  Don't derive them! */
     if (ret || !(flags & HDB_F_DECRYPT)) {
@@ -1019,7 +1013,7 @@ derive_keys(krb5_context context,
     }
 
     /* The principal name will be used in key derivation and error messages */
-    if (ret == 0 && h_is_namespace)
+    if (ret == 0)
         ret = krb5_unparse_name(context, princ, &p);
 
     /* Sanity check key rotations, determine current & last kr */
@@ -1101,10 +1095,10 @@ derive_keys(krb5_context context,
     /*
      * Derive and set in `h' its current kvno and current keys.
      *
-     * This will set h->entry.kvno as well.
+     * This will set h->kvno as well.
      *
      * This may set up to TWO keysets for the current key rotation period:
-     *  - current keys (h->entry.keys and h->entry.kvno)
+     *  - current keys (h->keys and h->kvno)
      *  - possibly one future
      *    OR
      *    possibly one past keyset in hist_keys for the current_kr
@@ -1137,14 +1131,14 @@ derive_keys(krb5_context context,
                                  kr.val[current_kr].epoch - 1, &kr.val[past_kr]);
 
     /*
-     * Impose a bound on h->entry.max_life so that [when the KDC is the caller]
+     * Impose a bound on h->max_life so that [when the KDC is the caller]
      * the KDC won't issue tickets longer lived than this.
      */
-    if (ret == 0 && !h->entry.max_life &&
-        (h->entry.max_life = malloc(sizeof(h->entry.max_life[0]))) == NULL)
+    if (ret == 0 && !h->max_life &&
+        (h->max_life = calloc(1, sizeof(h->max_life[0]))) == NULL)
         ret = krb5_enomem(context);
-    if (ret == 0 && *h->entry.max_life > kr.val[current_kr].period >> 1)
-        *h->entry.max_life = kr.val[current_kr].period >> 1;
+    if (ret == 0 && *h->max_life > kr.val[current_kr].period >> 1)
+        *h->max_life = kr.val[current_kr].period >> 1;
 
     free_HDB_Ext_KeyRotation(&kr);
     free_HDB_Ext_KeySet(&base_keys);
@@ -1153,6 +1147,10 @@ derive_keys(krb5_context context,
 }
 
 /*
+ * Pick a best kvno for the given principal at the given time.
+ *
+ * Implements the [hdb] new_service_key_delay configuration parameter.
+ *
  * In order for disparate keytab provisioning systems such as OSKT and our own
  * kadmin ext_keytab and httpkadmind's get-keys to coexist, we need to be able
  * to force keys set by the former to not become current keys until users of
@@ -1163,9 +1161,9 @@ derive_keys(krb5_context context,
  * The context is that OSKT's krb5_keytab is very happy to change keys in a way
  * that requires all members of a cluster to rekey together.  If one also
  * wishes to have cluster members that opt out of this and just fetch current,
- * past, and future keys periodically, then the keys set by OSKT need to not
- * come into effect until all the opt-out members have had a chance to fetch
- * the new keys.
+ * past, and future keys periodically, then the keys set by OSKT must not come
+ * into effect until all the opt-out members have had a chance to fetch the new
+ * keys.
  *
  * The assumption is that services will fetch new keys periodically, say, every
  * four hours.  Then one can set `[hdb] new_service_key_delay = 8h' in the
@@ -1175,12 +1173,12 @@ derive_keys(krb5_context context,
  * Naturally, this applies only to concrete principals with concrete keys.
  */
 static krb5_error_code
-fix_keys(krb5_context context,
-         HDB *db,
-         unsigned flags,
-         krb5_timestamp now,
-         krb5uint32 kvno,
-         hdb_entry_ex *h)
+pick_kvno(krb5_context context,
+          HDB *db,
+          unsigned flags,
+          krb5_timestamp now,
+          krb5uint32 kvno,
+          hdb_entry *h)
 {
     HDB_extension *ext;
     HDB_Ext_KeySet keys;
@@ -1193,25 +1191,25 @@ fix_keys(krb5_context context,
      * delayed, or if there's no new-key delay configured, or we're not
      * fetching for use as a service principal, then we're out.
      */
-    if (!(flags & HDB_F_DELAY_NEW_KEYS) || kvno || h->entry.flags.virtual ||
-        h->entry.flags.virtual_keys || db->new_service_key_delay <= 0)
+    if (!(flags & HDB_F_DELAY_NEW_KEYS) || kvno || h->flags.virtual ||
+        h->flags.virtual_keys || db->new_service_key_delay <= 0)
         return 0;
 
     /* No history -> current keyset is the only one and therefore the best */
-    ext = hdb_find_extension(&h->entry, choice_HDB_extension_data_hist_keys);
+    ext = hdb_find_extension(h, choice_HDB_extension_data_hist_keys);
     if (!ext)
         return 0;
 
     /* Assume the current keyset is the best to start with */
-    (void) hdb_entry_get_pw_change_time(&h->entry, &current);
-    if (current == 0 && h->entry.modified_by)
-        current = h->entry.modified_by->time;
+    (void) hdb_entry_get_pw_change_time(h, &current);
+    if (current == 0 && h->modified_by)
+        current = h->modified_by->time;
     if (current == 0)
-        current = h->entry.created_by.time;
+        current = h->created_by.time;
 
     /* Current keyset starts out as best */
     best = current;
-    kvno = h->entry.kvno;
+    kvno = h->kvno;
 
     /* Look for a better keyset in the history */
     keys = ext->data.u.hist_keys;
@@ -1251,7 +1249,7 @@ fix_keys(krb5_context context,
         best = keys.val[i].set_time[0];
         kvno = keys.val[i].kvno;
     }
-    return hdb_change_kvno(context, kvno, &h->entry);
+    return hdb_change_kvno(context, kvno, h);
 }
 
 /*
@@ -1296,7 +1294,7 @@ make_namespace_princ(krb5_context context,
 
     /* First go around, need a namespace princ.  Make it! */
     ret = krb5_build_principal(context, namespace, strlen(realm),
-                                realm, "WELLKNOWN",
+                                realm, KRB5_WELLKNOWN_NAME,
                                 HDB_WK_NAMESPACE, comp0, NULL);
     if (ret == 0)
         ret = krb5_principal_set_comp_string(context, *namespace, 3, comp1);
@@ -1307,6 +1305,138 @@ make_namespace_princ(krb5_context context,
     return ret;
 }
 
+static int
+is_namespace_princ_p(krb5_context context,
+                     krb5_const_principal princ)
+{
+    return
+        krb5_principal_get_num_comp(context, princ) >= 4
+        && strcmp(krb5_principal_get_comp_string(context, princ, 0),
+                  KRB5_WELLKNOWN_NAME) == 0
+        && strcmp(krb5_principal_get_comp_string(context, princ, 1),
+                  HDB_WK_NAMESPACE) == 0;
+}
+
+/* See call site */
+static krb5_error_code
+rewrite_hostname(krb5_context context,
+                 krb5_const_principal wanted_princ,
+                 krb5_const_principal ns_princ,
+                 krb5_const_principal found_ns_princ,
+                 char **s)
+{
+    const char *ns_host_part, *wanted_host_part, *found_host_part;
+    const char *p, *r;
+    size_t ns_host_part_len, wanted_host_part_len;
+
+    wanted_host_part = krb5_principal_get_comp_string(context, wanted_princ, 1);
+    wanted_host_part_len = strlen(wanted_host_part);
+    if (wanted_host_part_len > 256) {
+       krb5_set_error_message(context, HDB_ERR_NOENTRY,
+                               "Aliases of host-based principals longer than "
+                               "256 bytes not supported");
+        return HDB_ERR_NOENTRY;
+    }
+
+    ns_host_part = krb5_principal_get_comp_string(context, ns_princ, 3);
+    ns_host_part_len = strlen(ns_host_part);
+
+    /* Find `ns_host_part' as the tail of `wanted_host_part' */
+    for (r = p = strstr(wanted_host_part, ns_host_part);
+         r && strnlen(r, ns_host_part_len + 1) > ns_host_part_len;
+         p = (r = strstr(r, ns_host_part)) ? r : p)
+        ;
+    if (!p || strnlen(p, ns_host_part_len + 1) != ns_host_part_len)
+        return HDB_ERR_NOENTRY; /* Can't happen */
+    if (p == wanted_host_part || p[-1] != '.')
+        return HDB_ERR_NOENTRY;
+
+    found_host_part =
+        krb5_principal_get_comp_string(context, found_ns_princ, 3);
+    return
+        asprintf(s, "%.*s%s", (int)(p - wanted_host_part), wanted_host_part,
+                 found_host_part) < 0 ||
+        *s == NULL ? krb5_enomem(context) : 0;
+}
+
+/*
+ * Fix `h->principal' to match the desired `princ' in the namespace
+ * `nsprinc' (which is either the same as `h->principal' or an alias
+ * of it).
+ */
+static krb5_error_code
+fix_princ_name(krb5_context context,
+               krb5_const_principal princ,
+               krb5_const_principal nsprinc,
+               hdb_entry *h)
+{
+    krb5_error_code ret = 0;
+    char *s = NULL;
+
+    if (!nsprinc)
+        return 0;
+    if (krb5_principal_get_num_comp(context, princ) < 2)
+        return HDB_ERR_NOENTRY;
+
+    /* `nsprinc' must be a namespace principal */
+
+    if (krb5_principal_compare(context, nsprinc, h->principal)) {
+        /*
+         * `h' is the HDB entry for `nsprinc', and `nsprinc' is its canonical
+         * name.
+         *
+         * Set the entry's principal name to the desired name.  The keys will
+         * be fixed next (upstairs, but don't forget to!).
+         */
+        free_Principal(h->principal);
+        return copy_Principal(princ, h->principal);
+    }
+
+    if (!is_namespace_princ_p(context, h->principal)) {
+        /*
+         * The alias is a namespace, but the canonical name is not.  WAT.
+         *
+         * Well, the KDC will just issue a referral anyways, so we can leave
+         * `h->principal' as is...
+         *
+         * Remove all of `h's keys just in case, and leave
+         * `h->principal' as-is.
+         */
+        free_Keys(&h->keys);
+        (void) hdb_entry_clear_password(context, h);
+        return hdb_clear_extension(context, h,
+                                   choice_HDB_extension_data_hist_keys);
+    }
+
+    /*
+     * A namespace alias of a namespace entry.
+     *
+     * We'll want to rewrite the original principal accordingly.
+     *
+     * E.g., if the caller wanted host/foo.ns.test.h5l.se and we
+     * found WELLKNOWN/HOSTBASED-NAMESPACE/ns.test.h5l.se is an
+     * alias of WELLKNOWN/HOSTBASED-NAMESPACE/ns.example.org, then
+     * we'll want to treat host/foo.ns.test.h5l.se as an alias of
+     * host/foo.ns.example.org.
+     */
+    if (krb5_principal_get_num_comp(context, h->principal) !=
+        2 + krb5_principal_get_num_comp(context, princ))
+        ret = HDB_ERR_NOENTRY; /* Only host-based services for now */
+    if (ret == 0)
+        ret = rewrite_hostname(context, princ, nsprinc, h->principal, &s);
+    if (ret == 0) {
+        krb5_free_principal(context, h->principal);
+        h->principal = NULL;
+        ret = krb5_make_principal(context, &h->principal,
+                                  krb5_principal_get_realm(context, princ),
+                                  krb5_principal_get_comp_string(context,
+                                                                 princ, 0),
+                                  s,
+                                  NULL);
+    }
+    return ret;
+}
+
 /* Wrapper around db->hdb_fetch_kvno() that implements virtual princs/keys */
 static krb5_error_code
 fetch_it(krb5_context context,
@@ -1316,10 +1446,10 @@ fetch_it(krb5_context context,
          krb5_timestamp t,
          krb5int32 etype,
          krb5uint32 kvno,
-         hdb_entry_ex *ent)
+         hdb_entry *ent)
 {
     krb5_const_principal tmpprinc = princ;
-    krb5_principal baseprinc = NULL;
+    krb5_principal nsprinc = NULL;
     krb5_error_code ret = 0;
     const char *comp0 = krb5_principal_get_comp_string(context, princ, 0);
     const char *comp1 = krb5_principal_get_comp_string(context, princ, 1);
@@ -1330,8 +1460,10 @@ fetch_it(krb5_context context,
     char *host = NULL;
     int do_search = 0;
 
+    if (!db->enable_virtual_hostbased_princs)
+        maxdots = mindots = 0;
     if (db->enable_virtual_hostbased_princs && comp1 &&
-        strcmp("krbtgt", comp0) != 0 && strcmp("WELLKNOWN", comp0) != 0) {
+        strcmp("krbtgt", comp0) != 0 && strcmp(KRB5_WELLKNOWN_NAME, comp0) != 0) {
         char *htmp;
 
         if ((host = strdup(comp1)) == NULL)
@@ -1358,7 +1490,7 @@ fetch_it(krb5_context context,
     }
 
     tmp = host ? host : comp1;
-    for (ret = HDB_ERR_NOENTRY; ret == HDB_ERR_NOENTRY; tmpprinc = baseprinc) {
+    for (ret = HDB_ERR_NOENTRY; ret == HDB_ERR_NOENTRY; tmpprinc = nsprinc) {
         krb5_error_code ret2 = 0;
 
         /*
@@ -1376,7 +1508,7 @@ fetch_it(krb5_context context,
        ret = db->hdb_fetch_kvno(context, db, tmpprinc, flags, kvno, ent);
        if (ret != HDB_ERR_NOENTRY || hdots == 0 || hdots < mindots || !tmp ||
             !do_search)
-           break;
+            break;
 
         /*
          * Breadcrumb:
@@ -1398,17 +1530,22 @@ fetch_it(krb5_context context,
          */
         while (maxdots && hdots > maxdots && tmp) {
             tmp = strchr(tmp, '.');
-            /* tmp != NULL because maxdots > 0 */
+            /* tmp != NULL because maxdots > 0; we check to quiet linters */
+            if (tmp == NULL) {
+                ret = HDB_ERR_NOENTRY;
+                goto out;
+            }
             tmp++;
             hdots--;
         }
 
-        if (baseprinc == NULL)
+        if (nsprinc == NULL)
             /* First go around, need a namespace princ.  Make it! */
-            ret2 = make_namespace_princ(context, db, tmpprinc, &baseprinc);
-            /* Update the hostname component */
+            ret2 = make_namespace_princ(context, db, tmpprinc, &nsprinc);
+
+        /* Update the hostname component of the namespace principal */
         if (ret2 == 0)
-            ret2 = krb5_principal_set_comp_string(context, baseprinc, 3, tmp);
+            ret2 = krb5_principal_set_comp_string(context, nsprinc, 3, tmp);
         if (ret2)
             ret = ret2;
 
@@ -1425,14 +1562,22 @@ fetch_it(krb5_context context,
      * key derivation to do, but that's decided in derive_keys().
      */
     if (ret == 0) {
-        ret = derive_keys(context, flags, princ, !!baseprinc, t, etype, kvno,
-                          ent);
+        /* Fix the principal name if namespaced */
+        ret = fix_princ_name(context, princ, nsprinc, ent);
+
+        /* Derive keys if namespaced or virtual */
         if (ret == 0)
-            ret = fix_keys(context, db, flags, t, kvno, ent);
-        if (ret)
-            hdb_free_entry(context, ent);
+            ret = derive_keys(context, flags, princ, !!nsprinc, t, etype, kvno,
+                              ent);
+        /* Pick the best kvno for this principal at the given time */
+        if (ret == 0)
+            ret = pick_kvno(context, db, flags, t, kvno, ent);
     }
-    krb5_free_principal(context, baseprinc);
+
+out:
+    if (ret != 0 && ret != HDB_ERR_WRONG_REALM)
+        hdb_free_entry(context, db, ent);
+    krb5_free_principal(context, nsprinc);
     free(host);
     return ret;
 }
@@ -1468,7 +1613,7 @@ hdb_fetch_kvno(krb5_context context,
                krb5_timestamp t,
                krb5int32 etype,
                krb5uint32 kvno,
-               hdb_entry_ex *h)
+               hdb_entry *h)
 {
     krb5_error_code ret = HDB_ERR_NOENTRY;
 
@@ -1485,8 +1630,8 @@ hdb_fetch_kvno(krb5_context context,
      * independently of principal aliases (used by Samba).
      */
     if (ret == 0 && !(flags & HDB_F_ADMIN_DATA) &&
-        !h->entry.flags.force_canonicalize &&
-        !krb5_realm_compare(context, principal, h->entry.principal))
+        !h->flags.force_canonicalize &&
+        !krb5_realm_compare(context, principal, h->principal))
             ret = HDB_ERR_WRONG_REALM;
     return ret;
 }
index 6e415b95f1691e52829f3edafe03996d14a2bfb2..5fcce7b8e8b305c8421b00fc22106cfae74b6e5f 100644 (file)
@@ -114,7 +114,7 @@ DB_unlock(krb5_context context, HDB *db)
 
 static krb5_error_code
 DB_seq(krb5_context context, HDB *db,
-       unsigned flags, hdb_entry_ex *entry, int flag)
+       unsigned flags, hdb_entry *entry, int flag)
 {
     DB *d = (DB*)db->hdb_db;
     DBT key, value;
@@ -138,21 +138,21 @@ DB_seq(krb5_context context, HDB *db,
     data.data = value.data;
     data.length = value.size;
     memset(entry, 0, sizeof(*entry));
-    if (hdb_value2entry(context, &data, &entry->entry))
+    if (hdb_value2entry(context, &data, entry))
        return DB_seq(context, db, flags, entry, R_NEXT);
     if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) {
-       code = hdb_unseal_keys (context, db, &entry->entry);
+       code = hdb_unseal_keys (context, db, entry);
        if (code)
-           hdb_free_entry (context, entry);
+           hdb_free_entry (context, db, entry);
     }
-    if (code == 0 && entry->entry.principal == NULL) {
-       entry->entry.principal = malloc(sizeof(*entry->entry.principal));
-       if (entry->entry.principal == NULL) {
+    if (code == 0 && entry->principal == NULL) {
+       entry->principal = malloc(sizeof(*entry->principal));
+       if (entry->principal == NULL) {
            code = ENOMEM;
            krb5_set_error_message(context, code, "malloc: out of memory");
-           hdb_free_entry (context, entry);
+           hdb_free_entry (context, db, entry);
        } else {
-           hdb_key2principal(context, &key_data, entry->entry.principal);
+           hdb_key2principal(context, &key_data, entry->principal);
        }
     }
     return code;
@@ -160,14 +160,14 @@ DB_seq(krb5_context context, HDB *db,
 
 
 static krb5_error_code
-DB_firstkey(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry)
+DB_firstkey(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry)
 {
     return DB_seq(context, db, flags, entry, R_FIRST);
 }
 
 
 static krb5_error_code
-DB_nextkey(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry)
+DB_nextkey(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry)
 {
     return DB_seq(context, db, flags, entry, R_NEXT);
 }
index 0daa25bbec462a9802d9352a36a4d7f6fabbb0fc..9d0c0a97d9ab545d6f95b2445e6fa78a09e9797c 100644 (file)
@@ -136,7 +136,7 @@ DB_unlock(krb5_context context, HDB *db)
 
 static krb5_error_code
 DB_seq(krb5_context context, HDB *db,
-       unsigned flags, hdb_entry_ex *entry, int flag)
+       unsigned flags, hdb_entry *entry, int flag)
 {
     DBT key, value;
     DBC *dbcp = db->hdb_dbc;
@@ -156,21 +156,21 @@ DB_seq(krb5_context context, HDB *db,
     data.data = value.data;
     data.length = value.size;
     memset(entry, 0, sizeof(*entry));
-    if (hdb_value2entry(context, &data, &entry->entry))
+    if (hdb_value2entry(context, &data, entry))
        return DB_seq(context, db, flags, entry, DB_NEXT);
     if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) {
-       code = hdb_unseal_keys (context, db, &entry->entry);
+       code = hdb_unseal_keys (context, db, entry);
        if (code)
-           hdb_free_entry (context, entry);
+           hdb_free_entry (context, db, entry);
     }
-    if (entry->entry.principal == NULL) {
-       entry->entry.principal = malloc(sizeof(*entry->entry.principal));
-       if (entry->entry.principal == NULL) {
-           hdb_free_entry (context, entry);
+    if (entry->principal == NULL) {
+       entry->principal = malloc(sizeof(*entry->principal));
+       if (entry->principal == NULL) {
+           hdb_free_entry (context, db, entry);
            krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
            return ENOMEM;
        } else {
-           hdb_key2principal(context, &key_data, entry->entry.principal);
+           hdb_key2principal(context, &key_data, entry->principal);
        }
     }
     return 0;
@@ -178,14 +178,14 @@ DB_seq(krb5_context context, HDB *db,
 
 
 static krb5_error_code
-DB_firstkey(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry)
+DB_firstkey(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry)
 {
     return DB_seq(context, db, flags, entry, DB_FIRST);
 }
 
 
 static krb5_error_code
-DB_nextkey(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry)
+DB_nextkey(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry)
 {
     return DB_seq(context, db, flags, entry, DB_NEXT);
 }
index ec52d35dcba7def368323d4ac91ef678f18544fc..48683ef1607fc11f54645debe325409ba172c231 100644 (file)
@@ -712,7 +712,7 @@ hdb_entry_add_key_rotation(krb5_context context,
 {
     krb5_error_code ret;
     HDB_extension new_ext;
-    HDB_extension *ext = 0;
+    HDB_extension *ext = &new_ext;
     KeyRotation tmp;
     size_t i, sz;
 
@@ -734,8 +734,6 @@ hdb_entry_add_key_rotation(krb5_context context,
         ext = hdb_find_extension(entry, choice_HDB_extension_data_key_rotation);
         if (!ext)
             ext = &new_ext;
-        else
-            krs = &ext->data.u.key_rotation;
     } else {
         const KeyRotation *prev_kr = &krs->val[0];
         unsigned int last_kvno = 0;
index f3cb8fbe61da81c870bf7531dfd376f963198731..c9b469cb1a85c6321ff6981cdd1facf8d9c70aff 100644 (file)
@@ -90,14 +90,14 @@ hkt_unlock(krb5_context context, HDB *db)
 
 static krb5_error_code
 hkt_firstkey(krb5_context context, HDB *db,
-            unsigned flags, hdb_entry_ex *entry)
+            unsigned flags, hdb_entry *entry)
 {
     return HDB_ERR_DB_INUSE;
 }
 
 static krb5_error_code
 hkt_nextkey(krb5_context context, HDB * db, unsigned flags,
-            hdb_entry_ex * entry)
+            hdb_entry * entry)
 {
     return HDB_ERR_DB_INUSE;
 }
@@ -119,7 +119,7 @@ hkt_open(krb5_context context, HDB * db, int flags, mode_t mode)
 
 static krb5_error_code
 hkt_fetch_kvno(krb5_context context, HDB * db, krb5_const_principal principal,
-              unsigned flags, krb5_kvno kvno, hdb_entry_ex * entry)
+              unsigned flags, krb5_kvno kvno, hdb_entry * entry)
 {
     hdb_keytab k = (hdb_keytab)db->hdb_db;
     krb5_error_code ret;
@@ -132,13 +132,13 @@ hkt_fetch_kvno(krb5_context context, HDB * db, krb5_const_principal principal,
 
     memset(&ktentry, 0, sizeof(ktentry));
 
-    entry->entry.flags.server = 1;
-    entry->entry.flags.forwardable = 1;
-    entry->entry.flags.renewable = 1;
+    entry->flags.server = 1;
+    entry->flags.forwardable = 1;
+    entry->flags.renewable = 1;
 
     /* Not recorded in the OD backend, make something up */
     ret = krb5_parse_name(context, "hdb/keytab@WELL-KNOWN:KEYTAB-BACKEND",
-                         &entry->entry.created_by.principal);
+                         &entry->created_by.principal);
     if (ret)
        goto out;
 
@@ -155,7 +155,7 @@ hkt_fetch_kvno(krb5_context context, HDB * db, krb5_const_principal principal,
        goto out;
     }
 
-    ret = krb5_copy_principal(context, principal, &entry->entry.principal);
+    ret = krb5_copy_principal(context, principal, &entry->principal);
     if (ret)
        goto out;
 
@@ -163,8 +163,8 @@ hkt_fetch_kvno(krb5_context context, HDB * db, krb5_const_principal principal,
 
  out:
     if (ret) {
-       free_HDB_entry(&entry->entry);
-       memset(&entry->entry, 0, sizeof(entry->entry));
+       free_HDB_entry(entry);
+       memset(entry, 0, sizeof(*entry));
     }
     krb5_kt_free_entry(context, &ktentry);
 
@@ -173,7 +173,7 @@ hkt_fetch_kvno(krb5_context context, HDB * db, krb5_const_principal principal,
 
 static krb5_error_code
 hkt_store(krb5_context context, HDB * db, unsigned flags,
-         hdb_entry_ex * entry)
+         hdb_entry * entry)
 {
     return HDB_ERR_DB_INUSE;
 }
index 1dbb00d3e5f70cce532680208a1ff853f816eb8d..6a2876c51d714fba537fb3ab84106d18c5d200a9 100644 (file)
@@ -47,7 +47,7 @@ static krb5_error_code LDAP_close(krb5_context context, HDB *);
 
 static krb5_error_code
 LDAP_message2entry(krb5_context context, HDB * db, LDAPMessage * msg,
-                  int flags, hdb_entry_ex * ent);
+                  int flags, hdb_entry * ent);
 
 static const char *default_structural_object = "account";
 static char *structural_object;
@@ -388,14 +388,14 @@ bervalstrcmp(struct berval *v, const char *str)
 
 
 static krb5_error_code
-LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry_ex * ent,
+LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry * ent,
                LDAPMessage * msg, LDAPMod *** pmods, krb5_boolean *pis_new_entry)
 {
     krb5_error_code ret;
     krb5_boolean is_new_entry = FALSE;
     char *tmp = NULL;
     LDAPMod **mods = NULL;
-    hdb_entry_ex orig;
+    hdb_entry orig;
     unsigned long oflags, nflags;
     int i;
 
@@ -477,12 +477,12 @@ LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry_ex * ent,
     }
 
     if (is_new_entry ||
-       krb5_principal_compare(context, ent->entry.principal, orig.entry.principal)
+       krb5_principal_compare(context, ent->principal, orig.principal)
        == FALSE)
     {
        if (is_heimdal_principal || is_heimdal_entry) {
 
-           ret = krb5_unparse_name(context, ent->entry.principal, &tmp);
+           ret = krb5_unparse_name(context, ent->principal, &tmp);
            if (ret)
                goto out;
 
@@ -496,7 +496,7 @@ LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry_ex * ent,
        }
 
        if (is_account || is_samba_account) {
-           ret = krb5_unparse_name_short(context, ent->entry.principal, &tmp);
+           ret = krb5_unparse_name_short(context, ent->principal, &tmp);
            if (ret)
                goto out;
            ret = LDAP_addmod(&mods, LDAP_MOD_REPLACE, "uid", tmp);
@@ -508,15 +508,15 @@ LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry_ex * ent,
        }
     }
 
-    if (is_heimdal_entry && (ent->entry.kvno != orig.entry.kvno || is_new_entry)) {
+    if (is_heimdal_entry && (ent->kvno != orig.kvno || is_new_entry)) {
        ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE,
                            "krb5KeyVersionNumber",
-                           ent->entry.kvno);
+                           ent->kvno);
        if (ret)
            goto out;
     }
 
-    if (is_heimdal_entry && ent->entry.extensions) {
+    if (is_heimdal_entry && ent->extensions) {
        if (!is_new_entry) {
            vals = ldap_get_values_len(HDB2LDAP(db), msg, "krb5ExtendedAttributes");
            if (vals) {
@@ -527,11 +527,11 @@ LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry_ex * ent,
            }
        }
 
-       for (i = 0; i < ent->entry.extensions->len; i++) {
+       for (i = 0; i < ent->extensions->len; i++) {
            unsigned char *buf;
            size_t size, sz = 0;
 
-           ASN1_MALLOC_ENCODE(HDB_extension, buf, size, &ent->entry.extensions->val[i], &sz, ret);
+           ASN1_MALLOC_ENCODE(HDB_extension, buf, size, &ent->extensions->val[i], &sz, ret);
            if (ret)
                goto out;
            if (size != sz)
@@ -543,42 +543,42 @@ LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry_ex * ent,
        }
     }
 
-    if (is_heimdal_entry && ent->entry.valid_start) {
-       if (orig.entry.valid_end == NULL
-           || (*(ent->entry.valid_start) != *(orig.entry.valid_start))) {
+    if (is_heimdal_entry && ent->valid_start) {
+       if (orig.valid_end == NULL
+           || (*(ent->valid_start) != *(orig.valid_start))) {
            ret = LDAP_addmod_generalized_time(&mods, LDAP_MOD_REPLACE,
                                               "krb5ValidStart",
-                                              ent->entry.valid_start);
+                                              ent->valid_start);
            if (ret)
                goto out;
        }
     }
 
-    if (ent->entry.valid_end) {
-       if (orig.entry.valid_end == NULL || (*(ent->entry.valid_end) != *(orig.entry.valid_end))) {
+    if (ent->valid_end) {
+       if (orig.valid_end == NULL || (*(ent->valid_end) != *(orig.valid_end))) {
            if (is_heimdal_entry) {
                ret = LDAP_addmod_generalized_time(&mods, LDAP_MOD_REPLACE,
                                                   "krb5ValidEnd",
-                                                  ent->entry.valid_end);
+                                                  ent->valid_end);
                if (ret)
                    goto out;
             }
            if (is_samba_account) {
                ret = LDAP_addmod_integer(context, &mods,  LDAP_MOD_REPLACE,
                                          "sambaKickoffTime",
-                                         *(ent->entry.valid_end));
+                                         *(ent->valid_end));
                if (ret)
                    goto out;
            }
        }
     }
 
-    if (ent->entry.pw_end) {
-       if (orig.entry.pw_end == NULL || (*(ent->entry.pw_end) != *(orig.entry.pw_end))) {
+    if (ent->pw_end) {
+       if (orig.pw_end == NULL || (*(ent->pw_end) != *(orig.pw_end))) {
            if (is_heimdal_entry) {
                ret = LDAP_addmod_generalized_time(&mods, LDAP_MOD_REPLACE,
                                                   "krb5PasswordEnd",
-                                                  ent->entry.pw_end);
+                                                  ent->pw_end);
                if (ret)
                    goto out;
            }
@@ -586,7 +586,7 @@ LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry_ex * ent,
            if (is_samba_account) {
                ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE,
                                          "sambaPwdMustChange",
-                                         *(ent->entry.pw_end));
+                                         *(ent->pw_end));
                if (ret)
                    goto out;
            }
@@ -595,43 +595,43 @@ LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry_ex * ent,
 
 
 #if 0 /* we we have last_pw_change */
-    if (is_samba_account && ent->entry.last_pw_change) {
-       if (orig.entry.last_pw_change == NULL || (*(ent->entry.last_pw_change) != *(orig.entry.last_pw_change))) {
+    if (is_samba_account && ent->last_pw_change) {
+       if (orig.last_pw_change == NULL || (*(ent->last_pw_change) != *(orig.last_pw_change))) {
            ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE,
                                      "sambaPwdLastSet",
-                                     *(ent->entry.last_pw_change));
+                                     *(ent->last_pw_change));
            if (ret)
                goto out;
        }
     }
 #endif
 
-    if (is_heimdal_entry && ent->entry.max_life) {
-       if (orig.entry.max_life == NULL
-           || (*(ent->entry.max_life) != *(orig.entry.max_life))) {
+    if (is_heimdal_entry && ent->max_life) {
+       if (orig.max_life == NULL
+           || (*(ent->max_life) != *(orig.max_life))) {
 
            ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE,
                                      "krb5MaxLife",
-                                     *(ent->entry.max_life));
+                                     *(ent->max_life));
            if (ret)
                goto out;
        }
     }
 
-    if (is_heimdal_entry && ent->entry.max_renew) {
-       if (orig.entry.max_renew == NULL
-           || (*(ent->entry.max_renew) != *(orig.entry.max_renew))) {
+    if (is_heimdal_entry && ent->max_renew) {
+       if (orig.max_renew == NULL
+           || (*(ent->max_renew) != *(orig.max_renew))) {
 
            ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE,
                                      "krb5MaxRenew",
-                                     *(ent->entry.max_renew));
+                                     *(ent->max_renew));
            if (ret)
                goto out;
        }
     }
 
-    oflags = HDBFlags2int(orig.entry.flags);
-    nflags = HDBFlags2int(ent->entry.flags);
+    oflags = HDBFlags2int(orig.flags);
+    nflags = HDBFlags2int(ent->flags);
 
     if (is_heimdal_entry && oflags != nflags) {
 
@@ -643,7 +643,7 @@ LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry_ex * ent,
     }
 
     /* Remove keys if they exists, and then replace keys. */
-    if (!is_new_entry && orig.entry.keys.len > 0) {
+    if (!is_new_entry && orig.keys.len > 0) {
        vals = ldap_get_values_len(HDB2LDAP(db), msg, "krb5Key");
        if (vals) {
            ldap_value_free_len(vals);
@@ -654,21 +654,21 @@ LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry_ex * ent,
        }
     }
 
-    for (i = 0; i < ent->entry.keys.len; i++) {
+    for (i = 0; i < ent->keys.len; i++) {
 
        if (is_samba_account
-           && ent->entry.keys.val[i].key.keytype == ETYPE_ARCFOUR_HMAC_MD5) {
+           && ent->keys.val[i].key.keytype == ETYPE_ARCFOUR_HMAC_MD5) {
            char *ntHexPassword;
            char *nt;
            time_t now = time(NULL);
 
            /* the key might have been 'sealed', but samba passwords
               are clear in the directory */
-           ret = hdb_unseal_key(context, db, &ent->entry.keys.val[i]);
+           ret = hdb_unseal_key(context, db, &ent->keys.val[i]);
            if (ret)
                goto out;
 
-           nt = ent->entry.keys.val[i].key.keyvalue.data;
+           nt = ent->keys.val[i].key.keyvalue.data;
            /* store in ntPassword, not krb5key */
            ret = hex_encode(nt, 16, &ntHexPassword);
            if (ret < 0) {
@@ -701,7 +701,7 @@ LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry_ex * ent,
            unsigned char *buf;
            size_t len, buf_size;
 
-           ASN1_MALLOC_ENCODE(Key, buf, buf_size, &ent->entry.keys.val[i], &len, ret);
+           ASN1_MALLOC_ENCODE(Key, buf, buf_size, &ent->keys.val[i], &len, ret);
            if (ret)
                goto out;
            if(buf_size != len)
@@ -714,7 +714,7 @@ LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry_ex * ent,
        }
     }
 
-    if (ent->entry.etypes) {
+    if (ent->etypes) {
        int add_krb5EncryptionType = 0;
 
        /*
@@ -736,15 +736,15 @@ LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry_ex * ent,
            add_krb5EncryptionType = 1;
 
        if (add_krb5EncryptionType) {
-           for (i = 0; i < ent->entry.etypes->len; i++) {
+           for (i = 0; i < ent->etypes->len; i++) {
                if (is_samba_account &&
-                   ent->entry.keys.val[i].key.keytype == ETYPE_ARCFOUR_HMAC_MD5)
+                   ent->keys.val[i].key.keytype == ETYPE_ARCFOUR_HMAC_MD5)
                {
                    ;
                } else if (is_heimdal_entry) {
                    ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_ADD,
                                              "krb5EncryptionType",
-                                             ent->entry.etypes->val[i]);
+                                             ent->etypes->val[i]);
                    if (ret)
                        goto out;
                }
@@ -767,7 +767,7 @@ LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry_ex * ent,
     }
 
     if (msg)
-       hdb_free_entry(context, &orig);
+       hdb_free_entry(context, db, &orig);
 
     return ret;
 }
@@ -1005,7 +1005,7 @@ LDAP_principal2message(krb5_context context, HDB * db,
  */
 static krb5_error_code
 LDAP_message2entry(krb5_context context, HDB * db, LDAPMessage * msg,
-                  int flags, hdb_entry_ex * ent)
+                  int flags, hdb_entry * ent)
 {
     char *unparsed_name = NULL, *dn = NULL, *ntPasswordIN = NULL;
     char *samba_acct_flags = NULL;
@@ -1015,18 +1015,18 @@ LDAP_message2entry(krb5_context context, HDB * db, LDAPMessage * msg,
     int tmp, tmp_time, i, ret, have_arcfour = 0;
 
     memset(ent, 0, sizeof(*ent));
-    ent->entry.flags = int2HDBFlags(0);
+    ent->flags = int2HDBFlags(0);
 
     ret = LDAP_get_string_value(db, msg, "krb5PrincipalName", &unparsed_name);
     if (ret == 0) {
-       ret = krb5_parse_name(context, unparsed_name, &ent->entry.principal);
+       ret = krb5_parse_name(context, unparsed_name, &ent->principal);
        if (ret)
            goto out;
     } else {
        ret = LDAP_get_string_value(db, msg, "uid",
                                    &unparsed_name);
        if (ret == 0) {
-           ret = krb5_parse_name(context, unparsed_name, &ent->entry.principal);
+           ret = krb5_parse_name(context, unparsed_name, &ent->principal);
            if (ret)
                goto out;
        } else {
@@ -1042,25 +1042,25 @@ LDAP_message2entry(krb5_context context, HDB * db, LDAPMessage * msg,
        ret = LDAP_get_integer_value(db, msg, "krb5KeyVersionNumber",
                                     &integer);
        if (ret)
-           ent->entry.kvno = 0;
+           ent->kvno = 0;
        else
-           ent->entry.kvno = integer;
+           ent->kvno = integer;
     }
 
     keys = ldap_get_values_len(HDB2LDAP(db), msg, "krb5Key");
     if (keys != NULL) {
        size_t l;
 
-       ent->entry.keys.len = ldap_count_values_len(keys);
-       ent->entry.keys.val = (Key *) calloc(ent->entry.keys.len, sizeof(Key));
-       if (ent->entry.keys.val == NULL) {
+       ent->keys.len = ldap_count_values_len(keys);
+       ent->keys.val = (Key *) calloc(ent->keys.len, sizeof(Key));
+       if (ent->keys.val == NULL) {
            ret = ENOMEM;
            krb5_set_error_message(context, ret, "calloc: out of memory");
            goto out;
        }
-       for (i = 0; i < ent->entry.keys.len; i++) {
+       for (i = 0; i < ent->keys.len; i++) {
            decode_Key((unsigned char *) keys[i]->bv_val,
-                      (size_t) keys[i]->bv_len, &ent->entry.keys.val[i], &l);
+                      (size_t) keys[i]->bv_len, &ent->keys.val[i], &l);
        }
        ber_bvecfree(keys);
     } else {
@@ -1070,8 +1070,8 @@ LDAP_message2entry(krb5_context context, HDB * db, LDAPMessage * msg,
         * be related to a general directory entry without creating
         * the keys. Hopefully it's OK.
         */
-       ent->entry.keys.len = 0;
-       ent->entry.keys.val = NULL;
+       ent->keys.len = 0;
+       ent->keys.val = NULL;
 #else
        ret = HDB_ERR_NOENTRY;
        goto out;
@@ -1082,47 +1082,47 @@ LDAP_message2entry(krb5_context context, HDB * db, LDAPMessage * msg,
     if (extensions != NULL) {
        size_t l;
 
-       ent->entry.extensions = calloc(1, sizeof(*(ent->entry.extensions)));
-       if (ent->entry.extensions == NULL) {
+       ent->extensions = calloc(1, sizeof(*(ent->extensions)));
+       if (ent->extensions == NULL) {
            ret = krb5_enomem(context);
            goto out;
        }
-       ent->entry.extensions->len = ldap_count_values_len(extensions);
-       ent->entry.extensions->val = (HDB_extension *) calloc(ent->entry.extensions->len, sizeof(HDB_extension));
-       if (ent->entry.extensions->val == NULL) {
-           ent->entry.extensions->len = 0;
+       ent->extensions->len = ldap_count_values_len(extensions);
+       ent->extensions->val = (HDB_extension *) calloc(ent->extensions->len, sizeof(HDB_extension));
+       if (ent->extensions->val == NULL) {
+           ent->extensions->len = 0;
            ret = krb5_enomem(context);
            goto out;
        }
-       for (i = 0; i < ent->entry.extensions->len; i++) {
+       for (i = 0; i < ent->extensions->len; i++) {
            ret = decode_HDB_extension((unsigned char *) extensions[i]->bv_val,
-                      (size_t) extensions[i]->bv_len, &ent->entry.extensions->val[i], &l);
+                      (size_t) extensions[i]->bv_len, &ent->extensions->val[i], &l);
            if (ret)
                krb5_set_error_message(context, ret, "decode_HDB_extension failed");
        }
        ber_bvecfree(extensions);
     } else {
-       ent->entry.extensions = NULL;
+       ent->extensions = NULL;
     }
 
     vals = ldap_get_values_len(HDB2LDAP(db), msg, "krb5EncryptionType");
     if (vals != NULL) {
-       ent->entry.etypes = malloc(sizeof(*(ent->entry.etypes)));
-       if (ent->entry.etypes == NULL) {
+       ent->etypes = malloc(sizeof(*(ent->etypes)));
+       if (ent->etypes == NULL) {
            ret = ENOMEM;
            krb5_set_error_message(context, ret,"malloc: out of memory");
            goto out;
        }
-       ent->entry.etypes->len = ldap_count_values_len(vals);
-       ent->entry.etypes->val = calloc(ent->entry.etypes->len,
-                                        sizeof(ent->entry.etypes->val[0]));
-       if (ent->entry.etypes->val == NULL) {
+       ent->etypes->len = ldap_count_values_len(vals);
+       ent->etypes->val = calloc(ent->etypes->len,
+                                        sizeof(ent->etypes->val[0]));
+       if (ent->etypes->val == NULL) {
            ret = ENOMEM;
            krb5_set_error_message(context, ret, "malloc: out of memory");
-           ent->entry.etypes->len = 0;
+           ent->etypes->len = 0;
            goto out;
        }
-       for (i = 0; i < ent->entry.etypes->len; i++) {
+       for (i = 0; i < ent->etypes->len; i++) {
            char *buf;
 
            buf = malloc(vals[i]->bv_len + 1);
@@ -1133,14 +1133,14 @@ LDAP_message2entry(krb5_context context, HDB * db, LDAPMessage * msg,
            }
            memcpy(buf, vals[i]->bv_val, vals[i]->bv_len);
            buf[vals[i]->bv_len] = '\0';
-           ent->entry.etypes->val[i] = atoi(buf);
+           ent->etypes->val[i] = atoi(buf);
            free(buf);
        }
        ldap_value_free_len(vals);
     }
 
-    for (i = 0; i < ent->entry.keys.len; i++) {
-       if (ent->entry.keys.val[i].key.keytype == ETYPE_ARCFOUR_HMAC_MD5) {
+    for (i = 0; i < ent->keys.len; i++) {
+       if (ent->keys.val[i].key.keytype == ETYPE_ARCFOUR_HMAC_MD5) {
            have_arcfour = 1;
            break;
        }
@@ -1152,146 +1152,151 @@ LDAP_message2entry(krb5_context context, HDB * db, LDAPMessage * msg,
        unsigned *etypes;
         Key *ks;
 
-       ks = realloc(ent->entry.keys.val,
-                    (ent->entry.keys.len + 1) *
-                     sizeof(ent->entry.keys.val[0]));
+       ks = realloc(ent->keys.val,
+                    (ent->keys.len + 1) *
+                     sizeof(ent->keys.val[0]));
        if (ks == NULL) {
            ret = ENOMEM;
            krb5_set_error_message(context, ret, "malloc: out of memory");
            goto out;
        }
-       ent->entry.keys.val = ks;
-       memset(&ent->entry.keys.val[ent->entry.keys.len], 0, sizeof(Key));
-       ent->entry.keys.val[ent->entry.keys.len].key.keytype = ETYPE_ARCFOUR_HMAC_MD5;
-       ret = krb5_data_alloc (&ent->entry.keys.val[ent->entry.keys.len].key.keyvalue, 16);
+       ent->keys.val = ks;
+       memset(&ent->keys.val[ent->keys.len], 0, sizeof(Key));
+       ent->keys.val[ent->keys.len].key.keytype = ETYPE_ARCFOUR_HMAC_MD5;
+       ret = krb5_data_alloc (&ent->keys.val[ent->keys.len].key.keyvalue, 16);
        if (ret) {
            krb5_set_error_message(context, ret, "malloc: out of memory");
            ret = ENOMEM;
            goto out;
        }
        ret = hex_decode(ntPasswordIN,
-                        ent->entry.keys.val[ent->entry.keys.len].key.keyvalue.data, 16);
-       ent->entry.keys.len++;
-
-       if (ent->entry.etypes == NULL) {
-           ent->entry.etypes = malloc(sizeof(*(ent->entry.etypes)));
-           if (ent->entry.etypes == NULL) {
+                        ent->keys.val[ent->keys.len].key.keyvalue.data, 16);
+       ent->keys.len++;
+        if (ret == -1) {
+            krb5_set_error_message(context, ret = EINVAL,
+                                   "invalid hex encoding of password");
+            goto out;
+        }
+
+       if (ent->etypes == NULL) {
+           ent->etypes = malloc(sizeof(*(ent->etypes)));
+           if (ent->etypes == NULL) {
                ret = ENOMEM;
                krb5_set_error_message(context, ret, "malloc: out of memory");
                goto out;
            }
-           ent->entry.etypes->val = NULL;
-           ent->entry.etypes->len = 0;
+           ent->etypes->val = NULL;
+           ent->etypes->len = 0;
        }
 
-       for (i = 0; i < ent->entry.etypes->len; i++)
-           if (ent->entry.etypes->val[i] == ETYPE_ARCFOUR_HMAC_MD5)
+       for (i = 0; i < ent->etypes->len; i++)
+           if (ent->etypes->val[i] == ETYPE_ARCFOUR_HMAC_MD5)
                break;
        /* If there is no ARCFOUR enctype, add one */
-       if (i == ent->entry.etypes->len) {
-           etypes = realloc(ent->entry.etypes->val,
-                            (ent->entry.etypes->len + 1) *
-                            sizeof(ent->entry.etypes->val[0]));
+       if (i == ent->etypes->len) {
+           etypes = realloc(ent->etypes->val,
+                            (ent->etypes->len + 1) *
+                            sizeof(ent->etypes->val[0]));
            if (etypes == NULL) {
                ret = ENOMEM;
                krb5_set_error_message(context, ret, "malloc: out of memory");
                goto out;
            }
-           ent->entry.etypes->val = etypes;
-           ent->entry.etypes->val[ent->entry.etypes->len] =
+           ent->etypes->val = etypes;
+           ent->etypes->val[ent->etypes->len] =
                ETYPE_ARCFOUR_HMAC_MD5;
-           ent->entry.etypes->len++;
+           ent->etypes->len++;
        }
     }
 
     ret = LDAP_get_generalized_time_value(db, msg, "createTimestamp",
-                                         &ent->entry.created_by.time);
+                                         &ent->created_by.time);
     if (ret)
-       ent->entry.created_by.time = time(NULL);
+       ent->created_by.time = time(NULL);
 
-    ent->entry.created_by.principal = NULL;
+    ent->created_by.principal = NULL;
 
     if (flags & HDB_F_ADMIN_DATA) {
        ret = LDAP_get_string_value(db, msg, "creatorsName", &dn);
        if (ret == 0) {
-           LDAP_dn2principal(context, db, dn, &ent->entry.created_by.principal);
+           LDAP_dn2principal(context, db, dn, &ent->created_by.principal);
            free(dn);
        }
 
-       ent->entry.modified_by = calloc(1, sizeof(*ent->entry.modified_by));
-       if (ent->entry.modified_by == NULL) {
+       ent->modified_by = calloc(1, sizeof(*ent->modified_by));
+       if (ent->modified_by == NULL) {
            ret = ENOMEM;
            krb5_set_error_message(context, ret, "malloc: out of memory");
            goto out;
        }
 
        ret = LDAP_get_generalized_time_value(db, msg, "modifyTimestamp",
-                                             &ent->entry.modified_by->time);
+                                             &ent->modified_by->time);
        if (ret == 0) {
            ret = LDAP_get_string_value(db, msg, "modifiersName", &dn);
            if (ret == 0) {
-               LDAP_dn2principal(context, db, dn, &ent->entry.modified_by->principal);
+               LDAP_dn2principal(context, db, dn, &ent->modified_by->principal);
                free(dn);
            } else {
-               free(ent->entry.modified_by);
-               ent->entry.modified_by = NULL;
+               free(ent->modified_by);
+               ent->modified_by = NULL;
            }
        }
     }
 
-    ent->entry.valid_start = malloc(sizeof(*ent->entry.valid_start));
-    if (ent->entry.valid_start == NULL) {
+    ent->valid_start = malloc(sizeof(*ent->valid_start));
+    if (ent->valid_start == NULL) {
        ret = ENOMEM;
        krb5_set_error_message(context, ret, "malloc: out of memory");
        goto out;
     }
     ret = LDAP_get_generalized_time_value(db, msg, "krb5ValidStart",
-                                         ent->entry.valid_start);
+                                         ent->valid_start);
     if (ret) {
        /* OPTIONAL */
-       free(ent->entry.valid_start);
-       ent->entry.valid_start = NULL;
+       free(ent->valid_start);
+       ent->valid_start = NULL;
     }
 
-    ent->entry.valid_end = malloc(sizeof(*ent->entry.valid_end));
-    if (ent->entry.valid_end == NULL) {
+    ent->valid_end = malloc(sizeof(*ent->valid_end));
+    if (ent->valid_end == NULL) {
        ret = ENOMEM;
        krb5_set_error_message(context, ret, "malloc: out of memory");
        goto out;
     }
     ret = LDAP_get_generalized_time_value(db, msg, "krb5ValidEnd",
-                                         ent->entry.valid_end);
+                                         ent->valid_end);
     if (ret) {
        /* OPTIONAL */
-       free(ent->entry.valid_end);
-       ent->entry.valid_end = NULL;
+       free(ent->valid_end);
+       ent->valid_end = NULL;
     }
 
     ret = LDAP_get_integer_value(db, msg, "sambaKickoffTime", &tmp_time);
     if (ret == 0) {
-       if (ent->entry.valid_end == NULL) {
-           ent->entry.valid_end = malloc(sizeof(*ent->entry.valid_end));
-           if (ent->entry.valid_end == NULL) {
+       if (ent->valid_end == NULL) {
+           ent->valid_end = malloc(sizeof(*ent->valid_end));
+           if (ent->valid_end == NULL) {
                ret = ENOMEM;
                krb5_set_error_message(context, ret, "malloc: out of memory");
                goto out;
            }
        }
-       *ent->entry.valid_end = tmp_time;
+       *ent->valid_end = tmp_time;
     }
 
-    ent->entry.pw_end = malloc(sizeof(*ent->entry.pw_end));
-    if (ent->entry.pw_end == NULL) {
+    ent->pw_end = malloc(sizeof(*ent->pw_end));
+    if (ent->pw_end == NULL) {
        ret = ENOMEM;
        krb5_set_error_message(context, ret, "malloc: out of memory");
        goto out;
     }
     ret = LDAP_get_generalized_time_value(db, msg, "krb5PasswordEnd",
-                                         ent->entry.pw_end);
+                                         ent->pw_end);
     if (ret) {
        /* OPTIONAL */
-       free(ent->entry.pw_end);
-       ent->entry.pw_end = NULL;
+       free(ent->pw_end);
+       ent->pw_end = NULL;
     }
 
     ret = LDAP_get_integer_value(db, msg, "sambaPwdLastSet", &tmp_time);
@@ -1305,76 +1310,76 @@ LDAP_message2entry(krb5_context context, HDB * db, LDAPMessage * msg,
                                             NULL);
 
        if (delta) {
-               if (ent->entry.pw_end == NULL) {
-                   ent->entry.pw_end = malloc(sizeof(*ent->entry.pw_end));
-                   if (ent->entry.pw_end == NULL) {
+               if (ent->pw_end == NULL) {
+                   ent->pw_end = malloc(sizeof(*ent->pw_end));
+                   if (ent->pw_end == NULL) {
                        ret = ENOMEM;
                        krb5_set_error_message(context, ret, "malloc: out of memory");
                        goto out;
                    }
                }
 
-               *ent->entry.pw_end = tmp_time + delta;
+               *ent->pw_end = tmp_time + delta;
        }
     }
 
     ret = LDAP_get_integer_value(db, msg, "sambaPwdMustChange", &tmp_time);
     if (ret == 0) {
-       if (ent->entry.pw_end == NULL) {
-           ent->entry.pw_end = malloc(sizeof(*ent->entry.pw_end));
-           if (ent->entry.pw_end == NULL) {
+       if (ent->pw_end == NULL) {
+           ent->pw_end = malloc(sizeof(*ent->pw_end));
+           if (ent->pw_end == NULL) {
                ret = ENOMEM;
                krb5_set_error_message(context, ret, "malloc: out of memory");
                goto out;
            }
        }
-       *ent->entry.pw_end = tmp_time;
+       *ent->pw_end = tmp_time;
     }
 
     /* OPTIONAL */
     ret = LDAP_get_integer_value(db, msg, "sambaPwdLastSet", &tmp_time);
     if (ret == 0)
-       hdb_entry_set_pw_change_time(context, &ent->entry, tmp_time);
+       hdb_entry_set_pw_change_time(context, ent, tmp_time);
 
     {
        int max_life;
 
-       ent->entry.max_life = malloc(sizeof(*ent->entry.max_life));
-       if (ent->entry.max_life == NULL) {
+       ent->max_life = malloc(sizeof(*ent->max_life));
+       if (ent->max_life == NULL) {
            ret = ENOMEM;
            krb5_set_error_message(context, ret, "malloc: out of memory");
            goto out;
        }
        ret = LDAP_get_integer_value(db, msg, "krb5MaxLife", &max_life);
        if (ret) {
-           free(ent->entry.max_life);
-           ent->entry.max_life = NULL;
+           free(ent->max_life);
+           ent->max_life = NULL;
        } else
-           *ent->entry.max_life = max_life;
+           *ent->max_life = max_life;
     }
 
     {
        int max_renew;
 
-       ent->entry.max_renew = malloc(sizeof(*ent->entry.max_renew));
-       if (ent->entry.max_renew == NULL) {
+       ent->max_renew = malloc(sizeof(*ent->max_renew));
+       if (ent->max_renew == NULL) {
            ret = ENOMEM;
            krb5_set_error_message(context, ret, "malloc: out of memory");
            goto out;
        }
        ret = LDAP_get_integer_value(db, msg, "krb5MaxRenew", &max_renew);
        if (ret) {
-           free(ent->entry.max_renew);
-           ent->entry.max_renew = NULL;
+           free(ent->max_renew);
+           ent->max_renew = NULL;
        } else
-           *ent->entry.max_renew = max_renew;
+           *ent->max_renew = max_renew;
     }
 
     ret = LDAP_get_integer_value(db, msg, "krb5KDCFlags", &tmp);
     if (ret)
        tmp = 0;
 
-    ent->entry.flags = int2HDBFlags(tmp);
+    ent->flags = int2HDBFlags(tmp);
 
     /* Try and find Samba flags to put into the mix */
     ret = LDAP_get_string_value(db, msg, "sambaAcctFlags", &samba_acct_flags);
@@ -1406,7 +1411,7 @@ LDAP_message2entry(krb5_context context, HDB * db, LDAPMessage * msg,
 
        /* Allow forwarding */
        if (samba_forwardable)
-           ent->entry.flags.forwardable = TRUE;
+           ent->flags.forwardable = TRUE;
 
        for (i=0; i < flags_len; i++) {
            switch (samba_acct_flags[i]) {
@@ -1418,36 +1423,36 @@ LDAP_message2entry(krb5_context context, HDB * db, LDAPMessage * msg,
                /* how to handle no password in kerberos? */
                break;
            case 'D':
-               ent->entry.flags.invalid = TRUE;
+               ent->flags.invalid = TRUE;
                break;
            case 'H':
                break;
            case 'T':
                /* temp duplicate */
-               ent->entry.flags.invalid = TRUE;
+               ent->flags.invalid = TRUE;
                break;
            case 'U':
-               ent->entry.flags.client = TRUE;
+               ent->flags.client = TRUE;
                break;
            case 'M':
                break;
            case 'W':
            case 'S':
-               ent->entry.flags.server = TRUE;
-               ent->entry.flags.client = TRUE;
+               ent->flags.server = TRUE;
+               ent->flags.client = TRUE;
                break;
            case 'L':
-               ent->entry.flags.invalid = TRUE;
+               ent->flags.invalid = TRUE;
                break;
            case 'X':
-               if (ent->entry.pw_end) {
-                   free(ent->entry.pw_end);
-                   ent->entry.pw_end = NULL;
+               if (ent->pw_end) {
+                   free(ent->pw_end);
+                   ent->pw_end = NULL;
                }
                break;
            case 'I':
-               ent->entry.flags.server = TRUE;
-               ent->entry.flags.client = TRUE;
+               ent->flags.server = TRUE;
+               ent->flags.client = TRUE;
                break;
            }
        }
@@ -1462,7 +1467,7 @@ out:
     free(ntPasswordIN);
 
     if (ret)
-       hdb_free_entry(context, ent);
+       hdb_free_entry(context, db, ent);
 
     return ret;
 }
@@ -1491,7 +1496,7 @@ LDAP_unlock(krb5_context context, HDB * db)
 }
 
 static krb5_error_code
-LDAP_seq(krb5_context context, HDB * db, unsigned flags, hdb_entry_ex * entry)
+LDAP_seq(krb5_context context, HDB * db, unsigned flags, hdb_entry * entry)
 {
     int msgid, rc, parserc;
     krb5_error_code ret;
@@ -1545,9 +1550,9 @@ LDAP_seq(krb5_context context, HDB * db, unsigned flags, hdb_entry_ex * entry)
 
     if (ret == 0) {
        if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) {
-           ret = hdb_unseal_keys(context, db, &entry->entry);
+           ret = hdb_unseal_keys(context, db, entry);
            if (ret)
-               hdb_free_entry(context, entry);
+               hdb_free_entry(context, db, entry);
        }
     }
 
@@ -1556,7 +1561,7 @@ LDAP_seq(krb5_context context, HDB * db, unsigned flags, hdb_entry_ex * entry)
 
 static krb5_error_code
 LDAP_firstkey(krb5_context context, HDB *db, unsigned flags,
-             hdb_entry_ex *entry)
+             hdb_entry *entry)
 {
     krb5_error_code ret;
     int msgid;
@@ -1584,7 +1589,7 @@ LDAP_firstkey(krb5_context context, HDB *db, unsigned flags,
 
 static krb5_error_code
 LDAP_nextkey(krb5_context context, HDB * db, unsigned flags,
-            hdb_entry_ex * entry)
+            hdb_entry * entry)
 {
     return LDAP_seq(context, db, flags, entry);
 }
@@ -1687,7 +1692,7 @@ LDAP_open(krb5_context context, HDB * db, int flags, mode_t mode)
 
 static krb5_error_code
 LDAP_fetch_kvno(krb5_context context, HDB * db, krb5_const_principal principal,
-               unsigned flags, krb5_kvno kvno, hdb_entry_ex * entry)
+               unsigned flags, krb5_kvno kvno, hdb_entry * entry)
 {
     LDAPMessage *msg, *e;
     krb5_error_code ret;
@@ -1705,9 +1710,9 @@ LDAP_fetch_kvno(krb5_context context, HDB * db, krb5_const_principal principal,
     ret = LDAP_message2entry(context, db, e, flags, entry);
     if (ret == 0) {
        if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) {
-           ret = hdb_unseal_keys(context, db, &entry->entry);
+           ret = hdb_unseal_keys(context, db, entry);
            if (ret)
-               hdb_free_entry(context, entry);
+               hdb_free_entry(context, db, entry);
        }
     }
 
@@ -1720,7 +1725,7 @@ LDAP_fetch_kvno(krb5_context context, HDB * db, krb5_const_principal principal,
 #if 0
 static krb5_error_code
 LDAP_fetch(krb5_context context, HDB * db, krb5_const_principal principal,
-          unsigned flags, hdb_entry_ex * entry)
+          unsigned flags, hdb_entry * entry)
 {
     return LDAP_fetch_kvno(context, db, principal,
                           flags & (~HDB_F_KVNO_SPECIFIED), 0, entry);
@@ -1729,7 +1734,7 @@ LDAP_fetch(krb5_context context, HDB * db, krb5_const_principal principal,
 
 static krb5_error_code
 LDAP_store(krb5_context context, HDB * db, unsigned flags,
-          hdb_entry_ex * entry)
+          hdb_entry * entry)
 {
     LDAPMod **mods = NULL;
     krb5_error_code ret;
@@ -1742,17 +1747,17 @@ LDAP_store(krb5_context context, HDB * db, unsigned flags,
     if ((flags & HDB_F_PRECHECK))
         return 0; /* we can't guarantee whether we'll be able to perform it */
 
-    ret = LDAP_principal2message(context, db, entry->entry.principal, &msg);
+    ret = LDAP_principal2message(context, db, entry->principal, &msg);
     if (ret == 0)
        e = ldap_first_entry(HDB2LDAP(db), msg);
 
-    ret = krb5_unparse_name(context, entry->entry.principal, &name);
+    ret = krb5_unparse_name(context, entry->principal, &name);
     if (ret) {
        free(name);
        return ret;
     }
 
-    ret = hdb_seal_keys(context, db, &entry->entry);
+    ret = hdb_seal_keys(context, db, entry);
     if (ret)
        goto out;
 
index cabda277f4ee15018802fd4c9378747250fb8b20..6aa5201eb8a5df99573ae7103b1f7d67062f379b 100644 (file)
@@ -383,7 +383,7 @@ DB_unlock(krb5_context context, HDB *db)
 
 static krb5_error_code
 DB_seq(krb5_context context, HDB *db,
-       unsigned flags, hdb_entry_ex *entry, int flag)
+       unsigned flags, hdb_entry *entry, int flag)
 {
     mdb_info *mi = db->hdb_db;
     MDB_val key, value;
@@ -406,21 +406,21 @@ DB_seq(krb5_context context, HDB *db,
     data.data = value.mv_data;
     data.length = value.mv_size;
     memset(entry, 0, sizeof(*entry));
-    if (hdb_value2entry(context, &data, &entry->entry))
+    if (hdb_value2entry(context, &data, entry))
        return DB_seq(context, db, flags, entry, MDB_NEXT);
     if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) {
-       code = hdb_unseal_keys (context, db, &entry->entry);
+       code = hdb_unseal_keys (context, db, entry);
        if (code)
-           hdb_free_entry (context, entry);
+           hdb_free_entry (context, db, entry);
     }
-    if (entry->entry.principal == NULL) {
-       entry->entry.principal = malloc(sizeof(*entry->entry.principal));
-       if (entry->entry.principal == NULL) {
-           hdb_free_entry (context, entry);
+    if (entry->principal == NULL) {
+       entry->principal = malloc(sizeof(*entry->principal));
+       if (entry->principal == NULL) {
+           hdb_free_entry (context, db, entry);
            krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
            return ENOMEM;
        } else {
-           hdb_key2principal(context, &key_data, entry->entry.principal);
+           hdb_key2principal(context, &key_data, entry->principal);
        }
     }
     return 0;
@@ -428,7 +428,7 @@ DB_seq(krb5_context context, HDB *db,
 
 
 static krb5_error_code
-DB_firstkey(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry)
+DB_firstkey(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry)
 {
     krb5_error_code ret = 0;
     mdb_info *mi = db->hdb_db;
@@ -462,7 +462,7 @@ DB_firstkey(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry)
 
 
 static krb5_error_code
-DB_nextkey(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry)
+DB_nextkey(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry)
 {
     return DB_seq(context, db, flags, entry, MDB_NEXT);
 }
index 1ae013157c2b44b460fdea31d819c219cedb0328..7436f39edbbe6dbf284ae16e7e9a5778af5e7872 100644 (file)
@@ -555,7 +555,7 @@ _hdb_mdb_value2entry(krb5_context context, krb5_data *data,
                 goto out;
             }
             CHECK(ret = krb5_parse_name(context, p, &modby));
-            ret = hdb_set_last_modified_by(context, entry, modby, u32);
+            CHECK(ret = hdb_set_last_modified_by(context, entry, modby, u32));
             krb5_free_principal(context, modby);
             free(p);
             break;
@@ -765,7 +765,7 @@ mdb_unlock(krb5_context context, HDB *db)
 
 static krb5_error_code
 mdb_seq(krb5_context context, HDB *db,
-       unsigned flags, hdb_entry_ex *entry, int flag)
+       unsigned flags, hdb_entry *entry, int flag)
 {
     DB *d = (DB*)db->hdb_db;
     DBT key, value;
@@ -796,13 +796,13 @@ mdb_seq(krb5_context context, HDB *db,
     data.length = value.size;
     memset(entry, 0, sizeof(*entry));
 
-    if (_hdb_mdb_value2entry(context, &data, 0, &entry->entry))
+    if (_hdb_mdb_value2entry(context, &data, 0, entry))
        return mdb_seq(context, db, flags, entry, R_NEXT);
 
     if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) {
-       code = hdb_unseal_keys (context, db, &entry->entry);
+       code = hdb_unseal_keys (context, db, entry);
        if (code)
-           hdb_free_entry (context, entry);
+           hdb_free_entry (context, db, entry);
     }
 
     return code;
@@ -810,14 +810,14 @@ mdb_seq(krb5_context context, HDB *db,
 
 
 static krb5_error_code
-mdb_firstkey(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry)
+mdb_firstkey(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry)
 {
     return mdb_seq(context, db, flags, entry, R_FIRST);
 }
 
 
 static krb5_error_code
-mdb_nextkey(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry)
+mdb_nextkey(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry)
 {
     return mdb_seq(context, db, flags, entry, R_NEXT);
 }
@@ -941,7 +941,7 @@ mdb__del(krb5_context context, HDB *db, krb5_data key)
 
 static krb5_error_code
 mdb_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal,
-              unsigned flags, krb5_kvno kvno, hdb_entry_ex *entry)
+              unsigned flags, krb5_kvno kvno, hdb_entry *entry)
 {
     krb5_data key, value;
     krb5_error_code ret;
@@ -953,15 +953,15 @@ mdb_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal,
     krb5_data_free(&key);
     if(ret)
        return ret;
-    ret = _hdb_mdb_value2entry(context, &value, kvno, &entry->entry);
+    ret = _hdb_mdb_value2entry(context, &value, kvno, entry);
     krb5_data_free(&value);
     if (ret)
        return ret;
 
     if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) {
-       ret = hdb_unseal_keys (context, db, &entry->entry);
+       ret = hdb_unseal_keys (context, db, entry);
        if (ret) {
-           hdb_free_entry(context, entry);
+           hdb_free_entry(context, db, entry);
             return ret;
         }
     }
@@ -970,7 +970,7 @@ mdb_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal,
 }
 
 static krb5_error_code
-mdb_store(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry)
+mdb_store(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry)
 {
     krb5_error_code ret;
     krb5_storage *sp = NULL;
@@ -985,7 +985,7 @@ mdb_store(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry)
         return 0;
 
     if ((flags & HDB_F_PRECHECK)) {
-        ret = mdb_principal2key(context, entry->entry.principal, &key);
+        ret = mdb_principal2key(context, entry->principal, &key);
         if (ret) return ret;
         ret = db->hdb__get(context, db, key, &value);
         krb5_data_free(&key);
@@ -999,9 +999,9 @@ mdb_store(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry)
     sp = krb5_storage_emem();
     if (!sp) return ENOMEM;
     ret = _hdb_set_master_key_usage(context, db, 0); /* MIT KDB uses KU 0 */
-    ret = hdb_seal_keys(context, db, &entry->entry);
+    ret = hdb_seal_keys(context, db, entry);
     if (ret) return ret;
-    ret = entry2mit_string_int(context, sp, &entry->entry);
+    ret = entry2mit_string_int(context, sp, entry);
     if (ret) goto out;
     sz = krb5_storage_write(sp, "\n", 2); /* NUL-terminate */
     ret = ENOMEM;
@@ -1016,7 +1016,7 @@ mdb_store(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry)
     if (ret) goto out;
     ret = krb5_storage_to_data(spent, &kdb_ent);
     if (ret) goto out;
-    ret = mdb_principal2key(context, entry->entry.principal, &key);
+    ret = mdb_principal2key(context, entry->principal, &key);
     if (ret) goto out;
     ret = mdb__put(context, db, 1, key, kdb_ent);
 
@@ -1253,17 +1253,16 @@ getdata(char **p, unsigned char *buf, size_t len, const char *what)
 }
 
 static int
-getint(char **p, const char *what)
+getint(char **p, const char *what, int *val)
 {
-    int val;
     char *q = nexttoken(p, 0, what);
     if (!q) {
         warnx("Failed to find a signed integer (%s) in dump", what);
-        return -1;
+        return 1;
     }
-    if (sscanf(q, "%d", &val) != 1)
-        return -1;
-    return val;
+    if (sscanf(q, "%d", val) != 1)
+        return 1;
+    return 0;
 }
 
 static unsigned int
@@ -1327,7 +1326,7 @@ _hdb_mit_dump2mitdb_entry(krb5_context context, char *line, krb5_storage *sp)
               "'policy', nor 'princ'");
         return -1;
     }
-    if (getint(&p, "constant '38'") != 38) {
+    if (getint(&p, "constant '38'", &tmp) || tmp != 38) {
         warnx("Dump entry does not start with '38<TAB>'");
         return EINVAL;
     }
@@ -1343,7 +1342,7 @@ _hdb_mit_dump2mitdb_entry(krb5_context context, char *line, krb5_storage *sp)
     }
     num_tl_data = getuint(&p, "number of TL data");
     num_key_data = getuint(&p, "number of key data");
-    getint(&p, "5th field, length of 'extra data'");
+    (void) getint(&p, "5th field, length of 'extra data'", &tmp);
     princ = nexttoken(&p, (int)princ_len, "principal name");
     if (princ == NULL) {
         warnx("Failed to read principal name (expected length %llu)",
@@ -1355,38 +1354,31 @@ _hdb_mit_dump2mitdb_entry(krb5_context context, char *line, krb5_storage *sp)
     ret = krb5_store_uint32(sp, attributes);
     if (ret) return ret;
 
-    tmp = getint(&p, "max life");
-    CHECK_UINT(tmp);
+    if (getint(&p, "max life", &tmp)) return EINVAL;
     ret = krb5_store_uint32(sp, tmp);
     if (ret) return ret;
 
-    tmp = getint(&p, "max renewable life");
-    CHECK_UINT(tmp);
+    if (getint(&p, "max renewable life", &tmp)) return EINVAL;
     ret = krb5_store_uint32(sp, tmp);
     if (ret) return ret;
 
-    tmp = getint(&p, "expiration");
-    CHECK_UINT(tmp);
+    if (getint(&p, "expiration", &tmp)) return EINVAL;
     ret = krb5_store_uint32(sp, tmp);
     if (ret) return ret;
 
-    tmp = getint(&p, "pw expiration");
-    CHECK_UINT(tmp);
+    if (getint(&p, "pw expiration", &tmp)) return EINVAL;
     ret = krb5_store_uint32(sp, tmp);
     if (ret) return ret;
 
-    tmp = getint(&p, "last auth");
-    CHECK_UINT(tmp);
+    if (getint(&p, "last auth", &tmp)) return EINVAL;
     ret = krb5_store_uint32(sp, tmp);
     if (ret) return ret;
 
-    tmp = getint(&p, "last failed auth");
-    CHECK_UINT(tmp);
+    if (getint(&p, "last failed auth", &tmp)) return EINVAL;
     ret = krb5_store_uint32(sp, tmp);
     if (ret) return ret;
 
-    tmp = getint(&p,"fail auth count");
-    CHECK_UINT(tmp);
+    if (getint(&p,"fail auth count", &tmp)) return EINVAL;
     ret = krb5_store_uint32(sp, tmp);
     if (ret) return ret;
 
@@ -1414,8 +1406,9 @@ _hdb_mit_dump2mitdb_entry(krb5_context context, char *line, krb5_storage *sp)
         int tl_type, tl_length;
         unsigned char *buf;
 
-        tl_type = getint(&p, "TL data type");
-        tl_length = getint(&p, "data length");
+        if (getint(&p, "TL data type", &tl_type) ||
+            getint(&p, "data length", &tl_length))
+            return EINVAL;
 
         if (asprintf(&reading_what, "TL data type %d (length %d)",
                      tl_type, tl_length) < 0)
@@ -1435,8 +1428,10 @@ _hdb_mit_dump2mitdb_entry(krb5_context context, char *line, krb5_storage *sp)
         if (tl_length) {
             buf = malloc(tl_length);
             if (!buf) return ENOMEM;
-            if (getdata(&p, buf, tl_length, reading_what) != tl_length)
+            if (getdata(&p, buf, tl_length, reading_what) != tl_length) {
+                free(buf);
                 return EINVAL;
+            }
             sz = krb5_storage_write(sp, buf, tl_length);
             free(buf);
             if (sz != tl_length) return ENOMEM;
@@ -1454,23 +1449,23 @@ _hdb_mit_dump2mitdb_entry(krb5_context context, char *line, krb5_storage *sp)
         int keylen;
         size_t k;
 
-        key_versions = getint(&p, "key data 'version'");
+        if (getint(&p, "key data 'version'", &key_versions)) return EINVAL;
         CHECK_UINT16(key_versions);
         ret = krb5_store_int16(sp, key_versions);
         if (ret) return ret;
 
-        kvno = getint(&p, "kvno");
+        if (getint(&p, "kvno", &kvno)) return EINVAL;
         CHECK_UINT16(kvno);
         ret = krb5_store_int16(sp, kvno);
         if (ret) return ret;
 
         for (k = 0; k < key_versions; k++) {
-            keytype = getint(&p, "enctype");
+            if (getint(&p, "enctype", &keytype)) return EINVAL;
             CHECK_UINT16(keytype);
             ret = krb5_store_int16(sp, keytype);
             if (ret) return ret;
 
-            keylen = getint(&p, "encrypted key length");
+            if (getint(&p, "encrypted key length", &keylen)) return EINVAL;
             CHECK_UINT16(keylen);
             ret = krb5_store_int16(sp, keylen);
             if (ret) return ret;
@@ -1478,8 +1473,10 @@ _hdb_mit_dump2mitdb_entry(krb5_context context, char *line, krb5_storage *sp)
             if (keylen) {
                 buf = malloc(keylen);
                 if (!buf) return ENOMEM;
-                if (getdata(&p, buf, keylen, "key (or salt) data") != keylen)
+                if (getdata(&p, buf, keylen, "key (or salt) data") != keylen) {
+                    free(buf);
                     return EINVAL;
+                }
                 sz = krb5_storage_write(sp, buf, keylen);
                 free(buf);
                 if (sz != keylen) return ENOMEM;
index 3cab9178965ed08a6f34f8f1452979782dfa0033..4bb2f8e8553cb412b090dc8a138cdfcc642ab2c1 100644 (file)
@@ -495,7 +495,7 @@ hdb_sqlite_make_database(krb5_context context, HDB *db, const char *filename)
  */
 static krb5_error_code
 hdb_sqlite_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal,
-                     unsigned flags, krb5_kvno kvno, hdb_entry_ex *entry)
+                     unsigned flags, krb5_kvno kvno, hdb_entry *entry)
 {
     int sqlite_error;
     krb5_error_code ret;
@@ -541,14 +541,14 @@ hdb_sqlite_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal princi
     value.length = sqlite3_column_bytes(fetch, 0);
     value.data = (void *) sqlite3_column_blob(fetch, 0);
 
-    ret = hdb_value2entry(context, &value, &entry->entry);
+    ret = hdb_value2entry(context, &value, entry);
     if(ret)
         goto out;
 
     if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) {
-        ret = hdb_unseal_keys(context, db, &entry->entry);
+        ret = hdb_unseal_keys(context, db, entry);
         if(ret) {
-           hdb_free_entry(context, entry);
+           hdb_free_entry(context, db, entry);
            goto out;
         }
     }
@@ -600,7 +600,7 @@ hdb_sqlite_step_once(krb5_context context, HDB *db, sqlite3_stmt *statement)
  */
 static krb5_error_code
 hdb_sqlite_store(krb5_context context, HDB *db, unsigned flags,
-                 hdb_entry_ex *entry)
+                 hdb_entry *entry)
 {
     int ret;
     int i;
@@ -624,17 +624,17 @@ hdb_sqlite_store(krb5_context context, HDB *db, unsigned flags,
         goto rollback;
     }
 
-    ret = hdb_seal_keys(context, db, &entry->entry);
+    ret = hdb_seal_keys(context, db, entry);
     if(ret) {
         goto rollback;
     }
 
-    ret = hdb_entry2value(context, &entry->entry, &value);
+    ret = hdb_entry2value(context, entry, &value);
     if(ret) {
         goto rollback;
     }
 
-    ret = bind_principal(context, entry->entry.principal, get_ids, 1);
+    ret = bind_principal(context, entry->principal, get_ids, 1);
     if (ret)
        goto rollback;
 
@@ -656,7 +656,7 @@ hdb_sqlite_store(krb5_context context, HDB *db, unsigned flags,
             goto rollback;
         }
 
-       ret = bind_principal(context, entry->entry.principal, hsdb->add_principal, 1);
+       ret = bind_principal(context, entry->principal, hsdb->add_principal, 1);
        if (ret)
            goto rollback;
 
@@ -684,8 +684,10 @@ hdb_sqlite_store(krb5_context context, HDB *db, unsigned flags,
 
     } else if(ret == SQLITE_ROW) { /* Found a principal */
 
-        if(! (flags & HDB_F_REPLACE)) /* Not allowed to replace it */
+        if(!(flags & HDB_F_REPLACE)) {
+            ret = HDB_ERR_EXISTS;
             goto rollback;
+        }
 
         entry_id = sqlite3_column_int64(get_ids, 1);
 
@@ -711,7 +713,7 @@ hdb_sqlite_store(krb5_context context, HDB *db, unsigned flags,
         goto rollback;
     }
 
-    ret = hdb_entry_get_aliases(&entry->entry, &aliases);
+    ret = hdb_entry_get_aliases(entry, &aliases);
     if(ret || aliases == NULL)
         goto commit;
 
@@ -862,7 +864,7 @@ hdb_sqlite_unlock(krb5_context context, HDB *db)
  */
 static krb5_error_code
 hdb_sqlite_nextkey(krb5_context context, HDB *db, unsigned flags,
-                   hdb_entry_ex *entry)
+                   hdb_entry *entry)
 {
     krb5_error_code ret = 0;
     int sqlite_error;
@@ -876,7 +878,7 @@ hdb_sqlite_nextkey(krb5_context context, HDB *db, unsigned flags,
         value.length = sqlite3_column_bytes(hsdb->get_all_entries, 0);
         value.data = (void *) sqlite3_column_blob(hsdb->get_all_entries, 0);
         memset(entry, 0, sizeof(*entry));
-        ret = hdb_value2entry(context, &value, &entry->entry);
+        ret = hdb_value2entry(context, &value, entry);
     }
     else if(sqlite_error == SQLITE_DONE) {
        /* No more entries */
@@ -900,7 +902,7 @@ hdb_sqlite_nextkey(krb5_context context, HDB *db, unsigned flags,
  */
 static krb5_error_code
 hdb_sqlite_firstkey(krb5_context context, HDB *db, unsigned flags,
-                    hdb_entry_ex *entry)
+                    hdb_entry *entry)
 {
     hdb_sqlite_db *hsdb = (hdb_sqlite_db *) db->hdb_db;
     krb5_error_code ret;
@@ -950,11 +952,12 @@ hdb_sqlite_remove(krb5_context context, HDB *db,
     sqlite3_stmt *get_ids = hsdb->get_ids;
     sqlite3_stmt *rm = hsdb->remove;
 
-    bind_principal(context, principal, rm, 1);
+    ret = bind_principal(context, principal, rm, 1);
 
-    ret = hdb_sqlite_exec_stmt(context, hsdb,
-                               "BEGIN IMMEDIATE TRANSACTION",
-                               HDB_ERR_UK_SERROR);
+    if (ret == 0)
+        ret = hdb_sqlite_exec_stmt(context, hsdb,
+                                   "BEGIN IMMEDIATE TRANSACTION",
+                                   HDB_ERR_UK_SERROR);
     if (ret != SQLITE_OK) {
        ret = HDB_ERR_UK_SERROR;
         (void) hdb_sqlite_exec_stmt(context, hsdb, "ROLLBACK", 0);
index f6490783a6cd272cc6367a4e3544981a7754fc0a..9eb96be73d06fe456ea93ecbfeb1bc6d16fb0ef6 100644 (file)
@@ -4,7 +4,7 @@ BEGIN
 
 IMPORTS EncryptionKey, KerberosTime, Principal FROM krb5;
 
-HDB_DB_FORMAT INTEGER ::= 2    -- format of database, 
+hdb_db_format INTEGER ::= 2    -- format of database, 
                                -- update when making changes
 
 -- these must have the same value as the pa-* counterparts
index 3978048ad17fd538f81a0fc7571b955e16154ec7..56c403842e60f95e9822505d9b6aa50d34973b25 100644 (file)
@@ -232,38 +232,25 @@ hdb_remove_keys(krb5_context context,
  * @param context Context
  * @param e The HDB entry
  * @param ks A pointer to a variable of type HDB_Ext_KeySet
+ * @param ckr A pointer to stable (copied) HDB_Ext_KeyRotation
  *
  * @return Zero on success, an error code otherwise.
  */
 krb5_error_code
-hdb_remove_base_keys(krb5_context context,
-                     hdb_entry *e,
-                     HDB_Ext_KeySet *base_keys)
+_hdb_remove_base_keys(krb5_context context,
+                      hdb_entry *e,
+                      HDB_Ext_KeySet *base_keys,
+                      const HDB_Ext_KeyRotation *ckr)
 {
-    krb5_error_code ret;
-    const HDB_Ext_KeyRotation *ckr;
-    HDB_Ext_KeyRotation kr;
+    krb5_error_code ret = 0;
     size_t i, k;
 
-    ret = hdb_entry_get_key_rotation(context, e, &ckr);
-    if (!ckr)
-        return 0;
-
-    if (ret == 0) {
-        /*
-         * Changing the entry's extensions invalidates extensions obtained
-         * before the change.
-         */
-        ret = copy_HDB_Ext_KeyRotation(ckr, &kr);
-        ckr = NULL;
-    }
     base_keys->len = 0;
-    if (ret == 0 &&
-        (base_keys->val = calloc(kr.len, sizeof(base_keys->val[0]))) == NULL)
+    if ((base_keys->val = calloc(ckr->len, sizeof(base_keys->val[0]))) == NULL)
         ret = krb5_enomem(context);
 
-    for (k = i = 0; ret == 0 && i < kr.len; i++) {
-        const KeyRotation *krp = &kr.val[i];
+    for (k = i = 0; ret == 0 && i < ckr->len; i++) {
+        const KeyRotation *krp = &ckr->val[i];
 
         /*
          * WARNING: O(N * M) where M is number of keysets and N is the number
@@ -284,7 +271,6 @@ hdb_remove_base_keys(krb5_context context,
         base_keys->len = k;
     else
         free_HDB_Ext_KeySet(base_keys);
-    free_HDB_Ext_KeyRotation(&kr);
     return 0;
 }
 
@@ -312,12 +298,12 @@ hdb_install_keyset(krb5_context context,
             (ret = hdb_add_current_keys_to_history(context, e)))
             return ret;
         free_Keys(&e->keys);
+        e->kvno = ks->kvno;
         if (ret == 0)
             ret = copy_Keys(&ks->keys, &e->keys);
-        e->kvno = ks->kvno;
-        if (ks->set_time)
-            return hdb_entry_set_pw_change_time(context, e, *ks->set_time);
-        return 0;
+        if (ret == 0 && ks->set_time)
+            ret = hdb_entry_set_pw_change_time(context, e, *ks->set_time);
+        return ret;
     }
     return hdb_add_history_keyset(context, e, ks);
 }
@@ -359,9 +345,10 @@ hdb_enctype2key(krb5_context context,
 void
 hdb_free_key(Key *key)
 {
-    memset(key->key.keyvalue.data,
-          0,
-          key->key.keyvalue.length);
+    memset_s(key->key.keyvalue.data,
+            key->key.keyvalue.length,
+            0,
+            key->key.keyvalue.length);
     free_Key(key);
     free(key);
 }
@@ -396,20 +383,23 @@ hdb_unlock(int fd)
 }
 
 void
-hdb_free_entry(krb5_context context, hdb_entry_ex *ent)
+hdb_free_entry(krb5_context context, HDB *db, hdb_entry *ent)
 {
     Key *k;
     size_t i;
 
-    if (ent->free_entry)
-       (*ent->free_entry)(context, ent);
+    if (db && db->hdb_free_entry_context)
+       db->hdb_free_entry_context(context, db, ent);
 
-    for(i = 0; i < ent->entry.keys.len; i++) {
-       k = &ent->entry.keys.val[i];
+    for(i = 0; i < ent->keys.len; i++) {
+       k = &ent->keys.val[i];
 
-       memset (k->key.keyvalue.data, 0, k->key.keyvalue.length);
+       memset_s(k->key.keyvalue.data,
+                k->key.keyvalue.length,
+                0,
+                k->key.keyvalue.length);
     }
-    free_HDB_entry(&ent->entry);
+    free_HDB_entry(ent);
 }
 
 krb5_error_code
@@ -420,13 +410,13 @@ hdb_foreach(krb5_context context,
            void *data)
 {
     krb5_error_code ret;
-    hdb_entry_ex entry;
+    hdb_entry entry;
     ret = db->hdb_firstkey(context, db, flags, &entry);
     if (ret == 0)
        krb5_clear_error_message(context);
     while(ret == 0){
        ret = (*func)(context, db, &entry, data);
-       hdb_free_entry(context, &entry);
+       hdb_free_entry(context, db, &entry);
        if(ret == 0)
            ret = db->hdb_nextkey(context, db, flags, &entry);
     }
@@ -661,22 +651,22 @@ hdb_list_builtin(krb5_context context, char **list)
 krb5_error_code
 _hdb_keytab2hdb_entry(krb5_context context,
                      const krb5_keytab_entry *ktentry,
-                     hdb_entry_ex *entry)
+                     hdb_entry *entry)
 {
-    entry->entry.kvno = ktentry->vno;
-    entry->entry.created_by.time = ktentry->timestamp;
+    entry->kvno = ktentry->vno;
+    entry->created_by.time = ktentry->timestamp;
 
-    entry->entry.keys.val = calloc(1, sizeof(entry->entry.keys.val[0]));
-    if (entry->entry.keys.val == NULL)
+    entry->keys.val = calloc(1, sizeof(entry->keys.val[0]));
+    if (entry->keys.val == NULL)
        return ENOMEM;
-    entry->entry.keys.len = 1;
+    entry->keys.len = 1;
 
-    entry->entry.keys.val[0].mkvno = NULL;
-    entry->entry.keys.val[0].salt = NULL;
+    entry->keys.val[0].mkvno = NULL;
+    entry->keys.val[0].salt = NULL;
 
     return krb5_copy_keyblock_contents(context,
                                       &ktentry->keyblock,
-                                      &entry->entry.keys.val[0].key);
+                                      &entry->keys.val[0].key);
 }
 
 static krb5_error_code
@@ -789,7 +779,7 @@ hdb_create(krb5_context context, HDB **db, const char *filename)
             return ret;
         }
         for (cb_ctx.h = methods; cb_ctx.h->prefix != NULL; cb_ctx.h++) {
-            if (cb_ctx.h->is_file_based && !pathish)
+            if (cb_ctx.h->is_file_based)
                 continue;
             if (!cb_ctx.h->can_taste)
                 continue;
@@ -805,9 +795,11 @@ hdb_create(krb5_context context, HDB **db, const char *filename)
                 (*db)->hdb_destroy(context, *db);
             *db = NULL;
         }
+       if (cb_ctx.h->prefix == NULL)
+            cb_ctx.h = NULL;
     }
 #ifdef HDB_DEFAULT_DB_TYPE
-    if (cb_ctx.h == NULL || cb_ctx.h->prefix == NULL) {
+    if (cb_ctx.h == NULL) {
         /*
          * If still we've not picked a backend, use a build configuration time
          * default.
@@ -815,12 +807,14 @@ hdb_create(krb5_context context, HDB **db, const char *filename)
         for (cb_ctx.h = methods; cb_ctx.h->prefix != NULL; cb_ctx.h++)
             if (strcmp(cb_ctx.h->prefix, HDB_DEFAULT_DB_TYPE) == 0)
                 break;
+        if (cb_ctx.h->prefix == NULL)
+            cb_ctx.h = NULL;
     }
 #endif
-    if (cb_ctx.h == NULL || cb_ctx.h->prefix == NULL)
+    if (cb_ctx.h == NULL)
         /* Last resort default */
         cb_ctx.h = &default_dbmethod;
-    if (cb_ctx.h == NULL || cb_ctx.h->prefix == NULL) {
+    if (cb_ctx.h->prefix == NULL) {
         krb5_set_error_message(context, ENOTSUP,
                                "Could not determine default DB backend for %s",
                                filename);
index 97ca70c0a7e8bdf4280a732910ba73025453cbd3..0f2c92151e5f6cc5427eea0eef86fe4bb8acb595 100644 (file)
 
 #include <hdb_err.h>
 
+#include <heimbase-svc.h>
 #include <heim_asn1.h>
 #include <hdb_asn1.h>
+
+#define HDB_DB_FORMAT hdb_db_format
+
 typedef HDB_keyset hdb_keyset;
 typedef HDB_entry hdb_entry;
 typedef HDB_entry_alias hdb_entry_alias;
@@ -53,25 +57,26 @@ struct hdb_dbinfo;
 enum hdb_lockop{ HDB_RLOCK, HDB_WLOCK };
 
 /* flags for various functions */
-#define HDB_F_DECRYPT          1       /* decrypt keys */
-#define HDB_F_REPLACE          2       /* replace entry */
-#define HDB_F_GET_CLIENT       4       /* fetch client */
-#define HDB_F_GET_SERVER       8       /* fetch server */
-#define HDB_F_GET_KRBTGT       16      /* fetch krbtgt */
-#define HDB_F_GET_ANY          28      /* fetch any of client,server,krbtgt */
-#define HDB_F_CANON            32      /* want canonicalition */
-#define HDB_F_ADMIN_DATA       64      /* want data that kdc don't use  */
-#define HDB_F_KVNO_SPECIFIED   128     /* we want a particular KVNO */
-#define HDB_F_CURRENT_KVNO     256     /* we want the current KVNO */
-#define HDB_F_LIVE_CLNT_KVNOS  512     /* we want all live keys for pre-auth */
-#define HDB_F_LIVE_SVC_KVNOS   1024    /* we want all live keys for tix */
-#define HDB_F_ALL_KVNOS                2048    /* we want all the keys, live or not */
-#define HDB_F_FOR_AS_REQ       4096    /* fetch is for a AS REQ */
-#define HDB_F_FOR_TGS_REQ      8192    /* fetch is for a TGS REQ */
-#define HDB_F_PRECHECK         16384   /* check that the operation would succeed */
-#define HDB_F_DELAY_NEW_KEYS   32768   /* apply [hdb] new_service_key_delay */
-#define HDB_F_SYNTHETIC_OK     65536   /* synthetic principal for PKINIT or GSS preauth OK */
-#define HDB_F_GET_FAST_COOKIE  131072  /* fetch the FX-COOKIE key (not a normal principal) */
+#define HDB_F_DECRYPT          0x00001 /* decrypt keys */
+#define HDB_F_REPLACE          0x00002 /* replace entry */
+#define HDB_F_GET_CLIENT       0x00004 /* fetch client */
+#define HDB_F_GET_SERVER       0x00008 /* fetch server */
+#define HDB_F_GET_KRBTGT       0x00010 /* fetch krbtgt */
+#define HDB_F_GET_ANY          ( HDB_F_GET_CLIENT | \
+                                 HDB_F_GET_SERVER | \
+                                 HDB_F_GET_KRBTGT ) /* fetch any of client,server,krbtgt */
+#define HDB_F_CANON            0x00020 /* want canonicalition */
+#define HDB_F_ADMIN_DATA       0x00040 /* want data that kdc don't use  */
+#define HDB_F_KVNO_SPECIFIED   0x00080 /* we want a particular KVNO */
+#define HDB_F_LIVE_CLNT_KVNOS  0x00200 /* we want all live keys for pre-auth */
+#define HDB_F_LIVE_SVC_KVNOS   0x00400 /* we want all live keys for tix */
+#define HDB_F_ALL_KVNOS                0x00800 /* we want all the keys, live or not */
+#define HDB_F_FOR_AS_REQ       0x01000 /* fetch is for a AS REQ */
+#define HDB_F_FOR_TGS_REQ      0x02000 /* fetch is for a TGS REQ */
+#define HDB_F_PRECHECK         0x04000 /* check that the operation would succeed */
+#define HDB_F_DELAY_NEW_KEYS   0x08000 /* apply [hdb] new_service_key_delay */
+#define HDB_F_SYNTHETIC_OK     0x10000 /* synthetic principal for PKINIT or GSS preauth OK */
+#define HDB_F_GET_FAST_COOKIE  0x20000 /* fetch the FX-COOKIE key (not a normal principal) */
 
 /* hdb_capability_flags */
 #define HDB_CAP_F_HANDLE_ENTERPRISE_PRINCIPAL 1
@@ -79,78 +84,15 @@ enum hdb_lockop{ HDB_RLOCK, HDB_WLOCK };
 #define HDB_CAP_F_PASSWORD_UPDATE_KEYS 4
 #define HDB_CAP_F_SHARED_DIRECTORY      8
 
-/* auth status values */
-
-/*
- * Un-initialised value, not permitted, used to indicate that a value
- * wasn't set for the benifit of logic in the caller, must not be
- * passed to hdb_auth_status()
- */
-
-#define HDB_AUTHSTATUS_INVALID                  0
+#define heim_pcontext krb5_context
+#define heim_pconfig void *
 
-/*
- * A ticket was issued after authorization was successfully completed
- * (eg flags on the entry and expiry times were checked)
- */
-#define HDB_AUTHSTATUS_AUTHORIZATION_SUCCESS   1
+typedef struct hdb_request_desc {
+    HEIM_SVC_REQUEST_DESC_COMMON_ELEMENTS;
+} *hdb_request_t;
 
-/*
- * The user supplied the wrong password to a password-based
- * authentication mechanism (eg ENC-TS, ENC-CHAL)
- *
- * The HDB backend might increment a bad password count.
- */
-#define HDB_AUTHSTATUS_WRONG_PASSWORD          2
-
-/*
- * The user supplied a correct password to a password-based
- * authentication mechanism (eg ENC-TS, ENC-CHAL)
- *
- * The HDB backend might reset a bad password count.
- */
-#define HDB_AUTHSTATUS_CORRECT_PASSWORD                3
-
-/*
- * Attempted authenticaton with an unknown user
- */
-#define HDB_AUTHSTATUS_CLIENT_UNKNOWN          4
-
-/*
- * Attempted authenticaton with an known user that is already locked
- * out.
- */
-#define HDB_AUTHSTATUS_CLIENT_LOCKED_OUT       5
-
-/*
- * Successful authentication with a pre-authentication mechanism
- */
-#define HDB_AUTHSTATUS_GENERIC_SUCCESS         6
-
-/*
- * Failed authentication with a pre-authentication mechanism
- */
-#define HDB_AUTHSTATUS_GENERIC_FAILURE         7
-
-/*
- * Successful pre-authentication with PKINIT (smart card login etc)
- */
-#define HDB_AUTHSTATUS_PKINIT_SUCCESS          8
-
-/*
- * Failed pre-authentication with PKINIT (smart card login etc)
- */
-#define HDB_AUTHSTATUS_PKINIT_FAILURE          9
-
-/*
- * Successful pre-authentication with GSS pre-authentication
- */
-#define HDB_AUTHSTATUS_GSS_SUCCESS             10
-
-/*
- * Failed pre-authentication with GSS pre-authentication
- */
-#define HDB_AUTHSTATUS_GSS_FAILURE             11
+#undef heim_pcontext
+#undef heim_pconfig
 
 /* key usage for master key */
 #define HDB_KU_MKEY    0x484442
@@ -163,20 +105,6 @@ enum hdb_lockop{ HDB_RLOCK, HDB_WLOCK };
 
 typedef struct hdb_master_key_data *hdb_master_key;
 
-/**
- * hdb_entry_ex is a wrapper structure around the hdb_entry structure
- * that allows backends to keep a pointer to the backing store, ie in
- * ->hdb_fetch_kvno(), so that we the kadmin/kpasswd backend gets around to
- * ->hdb_store(), the backend doesn't need to lookup the entry again.
- */
-
-typedef struct hdb_entry_ex {
-    void *ctx;
-    hdb_entry entry;
-    void (*free_entry)(krb5_context, struct hdb_entry_ex *);
-} hdb_entry_ex;
-
-
 /**
  * HDB backend function pointer structure
  *
@@ -226,9 +154,9 @@ typedef struct HDB {
      */
     krb5_error_code (*hdb_close)(krb5_context, struct HDB*);
     /**
-     * Free an entry after use.
+     * Free backend-specific entry context.
      */
-    void           (*hdb_free)(krb5_context, struct HDB*, hdb_entry_ex*);
+    void           (*hdb_free_entry_context)(krb5_context, struct HDB*, hdb_entry*);
     /**
      * Fetch an entry from the backend
      *
@@ -238,12 +166,12 @@ typedef struct HDB {
      */
     krb5_error_code (*hdb_fetch_kvno)(krb5_context, struct HDB*,
                                      krb5_const_principal, unsigned, krb5_kvno,
-                                     hdb_entry_ex*);
+                                     hdb_entry*);
     /**
      * Store an entry to database
      */
     krb5_error_code (*hdb_store)(krb5_context, struct HDB*,
-                                unsigned, hdb_entry_ex*);
+                                unsigned, hdb_entry*);
     /**
      * Remove an entry from the database.
      */
@@ -253,12 +181,12 @@ typedef struct HDB {
      * As part of iteration, fetch one entry
      */
     krb5_error_code (*hdb_firstkey)(krb5_context, struct HDB*,
-                                   unsigned, hdb_entry_ex*);
+                                   unsigned, hdb_entry*);
     /**
      * As part of iteration, fetch next entry
      */
     krb5_error_code (*hdb_nextkey)(krb5_context, struct HDB*,
-                                  unsigned, hdb_entry_ex*);
+                                  unsigned, hdb_entry*);
     /**
      * Lock database
      *
@@ -337,40 +265,35 @@ typedef struct HDB {
      * The backend needs to call _kadm5_set_keys() and perform password
      * quality checks.
      */
-    krb5_error_code (*hdb_password)(krb5_context, struct HDB*, hdb_entry_ex*, const char *, int);
+    krb5_error_code (*hdb_password)(krb5_context, struct HDB*, hdb_entry*, const char *, int);
 
     /**
-     * Auth feedback
+     * Authentication auditing. Note that this function is called by
+     * both the AS and TGS, but currently only the AS sets the auth
+     * event type. This may change in a future version.
      *
-     * This is a feedback call that allows backends that provides
-     * lockout functionality to register failure and/or successes.
+     * Event details are available by querying the request using
+     * heim_audit_getkv(HDB_REQUEST_KV_...).
      *
      * In case the entry is locked out, the backend should set the
      * hdb_entry.flags.locked-out flag.
      */
-    krb5_error_code (*hdb_auth_status)(krb5_context,
-                                      struct HDB *,
-                                      hdb_entry_ex *,
-                                      const struct timeval *start_time,
-                                      const struct sockaddr *from_addr,
-                                      const char *original_client_name,
-                                      int auth_type,
-                                      const char *auth_details,
-                                      const char *pa_type);
+    krb5_error_code (*hdb_audit)(krb5_context, struct HDB *, hdb_entry *, hdb_request_t);
+
     /**
      * Check if delegation is allowed.
      */
-    krb5_error_code (*hdb_check_constrained_delegation)(krb5_context, struct HDB *, hdb_entry_ex *, krb5_const_principal);
+    krb5_error_code (*hdb_check_constrained_delegation)(krb5_context, struct HDB *, hdb_entry *, krb5_const_principal);
 
     /**
      * Check if this name is an alias for the supplied client for PKINIT userPrinicpalName logins
      */
-    krb5_error_code (*hdb_check_pkinit_ms_upn_match)(krb5_context, struct HDB *, hdb_entry_ex *, krb5_const_principal);
+    krb5_error_code (*hdb_check_pkinit_ms_upn_match)(krb5_context, struct HDB *, hdb_entry *, krb5_const_principal);
 
     /**
      * Check if s4u2self is allowed from this client to this server or the SPN is a valid SPN of this client (for user2user)
      */
-    krb5_error_code (*hdb_check_client_matches_target_service)(krb5_context, struct HDB *, hdb_entry_ex *, hdb_entry_ex *);
+    krb5_error_code (*hdb_check_client_matches_target_service)(krb5_context, struct HDB *, hdb_entry *, hdb_entry *);
 
     /**
      * Enable/disable synchronous updates
@@ -405,7 +328,7 @@ struct hdb_print_entry_arg {
 };
 
 typedef krb5_error_code (*hdb_foreach_func_t)(krb5_context, HDB*,
-                                             hdb_entry_ex*, void*);
+                                             hdb_entry*, void*);
 extern krb5_kt_ops hdb_kt_ops;
 extern krb5_kt_ops hdb_get_kt_ops;
 
diff --git a/third_party/heimdal/lib/hdb/hdb.opt b/third_party/heimdal/lib/hdb/hdb.opt
new file mode 100644 (file)
index 0000000..626f8c7
--- /dev/null
@@ -0,0 +1,5 @@
+--sequence=HDB-extensions
+--sequence=HDB-Ext-KeyRotation
+--sequence=HDB-Ext-KeySet
+--sequence=Keys
+--decorate=HDB_entry:void:context?:::
index ae0b067f79ba65d8512acd56d45baebba2adf065..457e5daf7a7bd06054c67dd7766cc09289cb6002 100644 (file)
@@ -305,7 +305,7 @@ hdb_add_history_keyset(krb5_context context,
     HDB_Ext_KeySet *hist_keys;
     HDB_extension ext;
     HDB_extension *extp;
-    krb5_error_code ret;
+    krb5_error_code ret = 0;
 
     memset(&ext, 0, sizeof (ext));
 
index 83cc851d91f5c7940e1dfa16076492f1435c809a..b1aa0207c9780dce7f5faa85bd4c5be3561b1cbc 100644 (file)
@@ -42,7 +42,7 @@ struct hdb_data {
 
 struct hdb_cursor {
     HDB *db;
-    hdb_entry_ex hdb_entry;
+    hdb_entry hdb_entry;
     int first, next;
     int key_idx;
 };
@@ -160,8 +160,11 @@ find_db (krb5_context context,
     }
     hdb_free_dbinfo(context, &head);
     if (*dbname == NULL &&
-        (*dbname = strdup(hdb_default_db(context))) == NULL)
+        (*dbname = strdup(hdb_default_db(context))) == NULL) {
+        free(*mkey);
+        *mkey = NULL;
         return krb5_enomem(context);
+    }
     return 0;
 }
 
@@ -178,7 +181,7 @@ hdb_get_entry(krb5_context context,
              krb5_enctype enctype,
              krb5_keytab_entry *entry)
 {
-    hdb_entry_ex ent;
+    hdb_entry ent;
     krb5_error_code ret;
     struct hdb_data *d = id->data;
     const char *dbname = d->dbname;
@@ -187,6 +190,9 @@ hdb_get_entry(krb5_context context,
     HDB *db;
     size_t i;
 
+    if (!principal)
+        return KRB5_KT_NOTFOUND;
+
     memset(&ent, 0, sizeof(ent));
 
     if (dbname == NULL) {
@@ -223,27 +229,27 @@ hdb_get_entry(krb5_context context,
     }else if(ret)
        goto out;
 
-    if(kvno && (krb5_kvno)ent.entry.kvno != kvno) {
-       hdb_free_entry(context, &ent);
+    if(kvno && (krb5_kvno)ent.kvno != kvno) {
+       hdb_free_entry(context, db, &ent);
        ret = KRB5_KT_NOTFOUND;
        goto out;
     }
     if(enctype == 0)
-       if(ent.entry.keys.len > 0)
-           enctype = ent.entry.keys.val[0].key.keytype;
+       if(ent.keys.len > 0)
+           enctype = ent.keys.val[0].key.keytype;
     ret = KRB5_KT_NOTFOUND;
-    for(i = 0; i < ent.entry.keys.len; i++) {
-       if(ent.entry.keys.val[i].key.keytype == enctype) {
+    for(i = 0; i < ent.keys.len; i++) {
+       if(ent.keys.val[i].key.keytype == enctype) {
            krb5_copy_principal(context, principal, &entry->principal);
-           entry->vno = ent.entry.kvno;
+           entry->vno = ent.kvno;
            krb5_copy_keyblock_contents(context,
-                                       &ent.entry.keys.val[i].key,
+                                       &ent.keys.val[i].key,
                                        &entry->keyblock);
            ret = 0;
            break;
        }
     }
-    hdb_free_entry(context, &ent);
+    hdb_free_entry(context, db, &ent);
  out:
     (*db->hdb_close)(context, db);
     (*db->hdb_destroy)(context, db);
@@ -333,8 +339,8 @@ hdb_next_entry(krb5_context context,
        else if (ret)
            return ret;
 
-       if (c->hdb_entry.entry.keys.len == 0)
-           hdb_free_entry(context, &c->hdb_entry);
+       if (c->hdb_entry.keys.len == 0)
+           hdb_free_entry(context, c->db, &c->hdb_entry);
        else
            c->next = FALSE;
     }
@@ -350,8 +356,8 @@ hdb_next_entry(krb5_context context,
            return ret;
 
        /* If no keys on this entry, try again */
-       if (c->hdb_entry.entry.keys.len == 0)
-           hdb_free_entry(context, &c->hdb_entry);
+       if (c->hdb_entry.keys.len == 0)
+           hdb_free_entry(context, c->db, &c->hdb_entry);
        else
            c->next = FALSE;
     }
@@ -362,14 +368,14 @@ hdb_next_entry(krb5_context context,
      */
 
     ret = krb5_copy_principal(context,
-                             c->hdb_entry.entry.principal,
+                             c->hdb_entry.principal,
                              &entry->principal);
     if (ret)
        return ret;
 
-    entry->vno = c->hdb_entry.entry.kvno;
+    entry->vno = c->hdb_entry.kvno;
     ret = krb5_copy_keyblock_contents(context,
-                                     &c->hdb_entry.entry.keys.val[c->key_idx].key,
+                                     &c->hdb_entry.keys.val[c->key_idx].key,
                                      &entry->keyblock);
     if (ret) {
        krb5_free_principal(context, entry->principal);
@@ -383,8 +389,8 @@ hdb_next_entry(krb5_context context,
      * next entry
      */
 
-    if ((size_t)c->key_idx == c->hdb_entry.entry.keys.len) {
-       hdb_free_entry(context, &c->hdb_entry);
+    if ((size_t)c->key_idx == c->hdb_entry.keys.len) {
+       hdb_free_entry(context, c->db, &c->hdb_entry);
        c->next = TRUE;
        c->key_idx = 0;
     }
@@ -401,7 +407,7 @@ hdb_end_seq_get(krb5_context context,
     struct hdb_cursor *c = cursor->data;
 
     if (!c->next)
-       hdb_free_entry(context, &c->hdb_entry);
+       hdb_free_entry(context, c->db, &c->hdb_entry);
 
     (c->db->hdb_close)(context, c->db);
     (c->db->hdb_destroy)(context, c->db);
index a124f93f6456517fa94ddf74aecf36d04ddb9d9b..72a7fb7aaad74166b4fdc86473e7b4cd2a9f786a 100644 (file)
@@ -69,7 +69,6 @@ EXPORTS
        hdb_prune_keys
        hdb_prune_keys_kvno
        hdb_read_master_key
-       hdb_remove_base_keys
        hdb_remove_keys
        hdb_replace_extension
        hdb_seal_key
index 4e3a340fe55504a17da848a13aa6be1f29a0b903..52c52c890dc0f5e7501195b930a440defa6fad7d 100644 (file)
@@ -76,7 +76,7 @@ NDBM_unlock(krb5_context context, HDB *db)
 
 static krb5_error_code
 NDBM_seq(krb5_context context, HDB *db,
-        unsigned flags, hdb_entry_ex *entry, int first)
+        unsigned flags, hdb_entry *entry, int first)
 
 {
     struct ndbm_db *d = (struct ndbm_db *)db->hdb_db;
@@ -99,21 +99,21 @@ NDBM_seq(krb5_context context, HDB *db,
     data.data = value.dptr;
     data.length = value.dsize;
     memset(entry, 0, sizeof(*entry));
-    if(hdb_value2entry(context, &data, &entry->entry))
+    if(hdb_value2entry(context, &data, entry))
        return NDBM_seq(context, db, flags, entry, 0);
     if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) {
-       ret = hdb_unseal_keys (context, db, &entry->entry);
+       ret = hdb_unseal_keys (context, db, entry);
        if (ret)
-           hdb_free_entry (context, entry);
+           hdb_free_entry (context, db, entry);
     }
-    if (ret == 0 && entry->entry.principal == NULL) {
-       entry->entry.principal = malloc (sizeof(*entry->entry.principal));
-       if (entry->entry.principal == NULL) {
-           hdb_free_entry (context, entry);
+    if (ret == 0 && entry->principal == NULL) {
+       entry->principal = malloc (sizeof(*entry->principal));
+       if (entry->principal == NULL) {
+           hdb_free_entry (context, db, entry);
            ret = ENOMEM;
            krb5_set_error_message(context, ret, "malloc: out of memory");
        } else {
-           hdb_key2principal (context, &key_data, entry->entry.principal);
+           hdb_key2principal (context, &key_data, entry->principal);
        }
     }
     return ret;
@@ -121,14 +121,14 @@ NDBM_seq(krb5_context context, HDB *db,
 
 
 static krb5_error_code
-NDBM_firstkey(krb5_context context, HDB *db,unsigned flags,hdb_entry_ex *entry)
+NDBM_firstkey(krb5_context context, HDB *db,unsigned flags,hdb_entry *entry)
 {
     return NDBM_seq(context, db, flags, entry, 1);
 }
 
 
 static krb5_error_code
-NDBM_nextkey(krb5_context context, HDB *db, unsigned flags,hdb_entry_ex *entry)
+NDBM_nextkey(krb5_context context, HDB *db, unsigned flags,hdb_entry *entry)
 {
     return NDBM_seq(context, db, flags, entry, 0);
 }
@@ -140,8 +140,7 @@ open_lock_file(krb5_context context, const char *db_name, int *fd)
     int ret = 0;
 
     /* lock old and new databases */
-    asprintf(&lock_file, "%s.lock", db_name);
-    if(lock_file == NULL) {
+    if (asprintf(&lock_file, "%s.lock", db_name) == -1) {
        krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
        return ENOMEM;
     }
@@ -161,7 +160,8 @@ static krb5_error_code
 NDBM_rename(krb5_context context, HDB *db, const char *new_name)
 {
     int ret;
-    char *old_dir, *old_pag, *new_dir, *new_pag;
+    char *old_dir = NULL, *old_pag = NULL;
+    char *new_dir = NULL, *new_pag = NULL;
     int old_lock_fd, new_lock_fd;
 
     /* lock old and new databases */
@@ -190,10 +190,26 @@ NDBM_rename(krb5_context context, HDB *db, const char *new_name)
        return ret;
     }
 
-    asprintf(&old_dir, "%s.dir", db->hdb_name);
-    asprintf(&old_pag, "%s.pag", db->hdb_name);
-    asprintf(&new_dir, "%s.dir", new_name);
-    asprintf(&new_pag, "%s.pag", new_name);
+    if (asprintf(&old_dir, "%s.dir", db->hdb_name) == -1) {
+       old_dir = NULL;
+       ret = ENOMEM;
+       goto out;
+    }
+    if (asprintf(&old_pag, "%s.pag", db->hdb_name) == -1) {
+       old_pag = NULL;
+       ret = ENOMEM;
+       goto out;
+    }
+    if (asprintf(&new_dir, "%s.dir", new_name) == -1) {
+       new_dir = NULL;
+       ret = ENOMEM;
+       goto out;
+    }
+    if (asprintf(&new_pag, "%s.pag", new_name) == -1) {
+       new_pag = NULL;
+       ret = ENOMEM;
+       goto out;
+    }
 
     ret = rename(old_dir, new_dir) || rename(old_pag, new_pag);
     if (ret) {
@@ -203,6 +219,7 @@ NDBM_rename(krb5_context context, HDB *db, const char *new_name)
        krb5_set_error_message(context, ret, "rename: %s", strerror(ret));
     }
 
+ out:
     free(old_dir);
     free(old_pag);
     free(new_dir);
index 0d1e2855217d0f1cddfc4c90a2604ed35fb1a56d..7f2535881892c28bd5da7891b1e83acedfe2e8d7 100644 (file)
@@ -453,7 +453,8 @@ entry2mit_string_int(krb5_context context, krb5_storage *sp, hdb_entry *ent)
         unsigned char *ptr;
         
         ptr = (unsigned char *)&last_pw_chg;
-        val = ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24);
+        val = ((unsigned long)ptr[3] << 24) | (ptr[2] << 16)
+           | (ptr[1] << 8) | ptr[0];
         d.data = &val;
         d.length = sizeof (last_pw_chg);
         sz = append_string(context, sp, "\t%u\t%u\t",
@@ -474,12 +475,16 @@ entry2mit_string_int(krb5_context context, krb5_storage *sp, hdb_entry *ent)
         d.data = &val;
         d.length = sizeof (ent->modified_by->time);
         ret = krb5_unparse_name(context, ent->modified_by->principal, &modby_p);
-        if (ret) return ret;
+        if (ret)
+           return ret;
         plen = strlen(modby_p);
         sz = append_string(context, sp, "\t%u\t%u\t",
                            mit_KRB5_TL_MOD_PRINC,
                            d.length + plen + 1 /* NULL counted */);
-        if (sz == -1) return ENOMEM;
+        if (sz == -1) {
+           free(modby_p);
+           return ENOMEM;
+       }
         sz = append_hex(context, sp, 1, 1, &d);
         if (sz == -1) {
             free(modby_p);
@@ -489,7 +494,8 @@ entry2mit_string_int(krb5_context context, krb5_storage *sp, hdb_entry *ent)
         d.length = plen + 1;
         sz = append_hex(context, sp, 1, 1, &d);
         free(modby_p);
-        if (sz == -1) return ENOMEM;
+        if (sz == -1)
+           return ENOMEM;
     }
     /*
      * Dump keys (remembering to not include any with kvno higher than
@@ -556,7 +562,7 @@ hdb_entry2string(krb5_context context, hdb_entry *ent, char **str)
 /* print a hdb_entry to (FILE*)data; suitable for hdb_foreach */
 
 krb5_error_code
-hdb_print_entry(krb5_context context, HDB *db, hdb_entry_ex *entry,
+hdb_print_entry(krb5_context context, HDB *db, hdb_entry *entry,
                 void *data)
 {
     struct hdb_print_entry_arg *parg = data;
@@ -572,10 +578,10 @@ hdb_print_entry(krb5_context context, HDB *db, hdb_entry_ex *entry,
 
     switch (parg->fmt) {
     case HDB_DUMP_HEIMDAL:
-        ret = entry2string_int(context, sp, &entry->entry);
+        ret = entry2string_int(context, sp, entry);
         break;
     case HDB_DUMP_MIT:
-        ret = entry2mit_string_int(context, sp, &entry->entry);
+        ret = entry2mit_string_int(context, sp, entry);
         break;
     default:
         heim_abort("Only two dump formats supported: Heimdal and MIT");
index 9c95e6390f40eb8eed65fb3133769e076f469937..35c01f59f594f6bee5d3d76b6003bca3cf8de717 100644 (file)
@@ -70,7 +70,7 @@ threaded_reader(void *d)
     krb5_error_code ret;
     krb5_context context;
     struct tsync *s = d;
-    hdb_entry_ex entr;
+    hdb_entry entr;
     HDB *dbr = NULL;
 
     printf("Reader thread opening HDB\n");
@@ -101,7 +101,7 @@ threaded_reader(void *d)
         //(void) unlink(s->fname);
         krb5_err(context, 1, ret, "Could not iterate HDB %s", s->hdb_name);
     }
-    free_HDB_entry(&entr.entry);
+    free_HDB_entry(&entr);
 
     /* Tell the writer to go ahead and write */
     printf("Reader thread iterated one entry; telling writer to write more\n");
@@ -124,7 +124,7 @@ threaded_reader(void *d)
                  "Could not iterate while writing to HDB %s", s->hdb_name);
     }
     printf("Reader thread iterated another entry\n");
-    free_HDB_entry(&entr.entry);
+    free_HDB_entry(&entr);
     if ((ret = dbr->hdb_nextkey(context, dbr, 0, &entr)) == 0) {
         //(void) unlink(s->fname);
         krb5_warn(context, ret,
@@ -154,7 +154,7 @@ forked_reader(struct tsync *s)
 {
     krb5_error_code ret;
     krb5_context context;
-    hdb_entry_ex entr;
+    hdb_entry entr;
     ssize_t bytes;
     char b[1];
     HDB *dbr = NULL;
@@ -172,6 +172,8 @@ forked_reader(struct tsync *s)
     while ((bytes = read(s->reader_go_pipe[0], b, sizeof(b))) == -1 &&
            errno == EINTR)
         ;
+    if (bytes == -1)
+        err(1, "Could not read from reader-go pipe (error)");
 
     /* Open a new HDB handle to read */
     if ((ret = hdb_create(context, &dbr, s->hdb_name))) {
@@ -188,13 +190,15 @@ forked_reader(struct tsync *s)
         krb5_err(context, 1, ret, "Could not iterate HDB %s", s->hdb_name);
     }
     printf("Reader process iterated one entry\n");
-    free_HDB_entry(&entr.entry);
+    free_HDB_entry(&entr);
 
     /* Tell the writer to go ahead and write */
     printf("Reader process iterated one entry; telling writer to write more\n");
     while ((bytes = write(s->writer_go_pipe[1], "", sizeof(""))) == -1 &&
            errno == EINTR)
         ;
+    if (bytes == -1)
+        err(1, "Could not write to writer-go pipe (error)");
 
 
     /* Wait for the writer to have written one more entry to the HDB */
@@ -213,13 +217,13 @@ forked_reader(struct tsync *s)
         krb5_err(context, 1, ret,
                  "Could not iterate while writing to HDB %s", s->hdb_name);
     }
-    free_HDB_entry(&entr.entry);
+    free_HDB_entry(&entr);
     printf("Reader process iterated another entry\n");
     if ((ret = dbr->hdb_nextkey(context, dbr, 0, &entr)) == 0) {
         //(void) unlink(s->fname);
         krb5_warn(context, ret,
                  "HDB %s sees writes committed since starting iteration (%s)",
-                 s->hdb_name, entr.entry.principal->name.name_string.val[0]);
+                 s->hdb_name, entr.principal->name.name_string.val[0]);
     } else if (ret != HDB_ERR_NOENTRY) {
         //(void) unlink(s->fname);
         krb5_err(context, 1, ret,
@@ -231,6 +235,8 @@ forked_reader(struct tsync *s)
     while ((bytes = write(s->writer_go_pipe[1], "", sizeof(""))) == -1 &&
            errno == EINTR)
         ;
+    if (bytes == -1)
+        err(1, "Could not write to writer-go pipe (error)");
 
     dbr->hdb_close(context, dbr);
     dbr->hdb_destroy(context, dbr);
@@ -242,27 +248,27 @@ forked_reader(struct tsync *s)
 }
 
 static krb5_error_code
-make_entry(krb5_context context, hdb_entry_ex *entry, const char *name)
+make_entry(krb5_context context, hdb_entry *entry, const char *name)
 {
     krb5_error_code ret;
 
     memset(entry, 0, sizeof(*entry));
-    entry->entry.kvno = 2;
-    entry->entry.keys.len = 0;
-    entry->entry.keys.val = NULL;
-    entry->entry.created_by.time = time(NULL);
-    entry->entry.modified_by = NULL;
-    entry->entry.valid_start = NULL;
-    entry->entry.valid_end = NULL;
-    entry->entry.max_life = NULL;
-    entry->entry.max_renew = NULL;
-    entry->entry.etypes = NULL;
-    entry->entry.generation = NULL;
-    entry->entry.extensions = NULL;
-    if ((ret = krb5_make_principal(context, &entry->entry.principal,
+    entry->kvno = 2;
+    entry->keys.len = 0;
+    entry->keys.val = NULL;
+    entry->created_by.time = time(NULL);
+    entry->modified_by = NULL;
+    entry->valid_start = NULL;
+    entry->valid_end = NULL;
+    entry->max_life = NULL;
+    entry->max_renew = NULL;
+    entry->etypes = NULL;
+    entry->generation = NULL;
+    entry->extensions = NULL;
+    if ((ret = krb5_make_principal(context, &entry->principal,
                                    "TEST.H5L.SE", name, NULL)))
         return ret;
-    if ((ret = krb5_make_principal(context, &entry->entry.created_by.principal,
+    if ((ret = krb5_make_principal(context, &entry->created_by.principal,
                                    "TEST.H5L.SE", "tester", NULL)))
         return ret;
     return 0;
@@ -320,7 +326,7 @@ test_hdb_concurrency(char *name, const char *ext, int threaded)
     char *fname_ext = NULL;
     pthread_t reader_thread;
     struct tsync ts;
-    hdb_entry_ex entw;
+    hdb_entry entw;
     pid_t child = getpid();
     HDB *dbw = NULL;
     int status;
@@ -387,14 +393,14 @@ test_hdb_concurrency(char *name, const char *ext, int threaded)
         krb5_err(context, 1, ret,
                  "Could not store entry for \"foo\" in HDB %s", name);
     }
-    free_HDB_entry(&entw.entry);
+    free_HDB_entry(&entw);
     if ((ret = make_entry(context, &entw, "bar")) ||
         (ret = dbw->hdb_store(context, dbw, 0, &entw))) {
         (void) unlink(fname_ext);
         krb5_err(context, 1, ret,
                  "Could not store entry for \"foo\" in HDB %s", name);
     }
-    free_HDB_entry(&entw.entry);
+    free_HDB_entry(&entw);
 
     /* Tell the reader to start reading */
     readers_turn(&ts, child, threaded);
@@ -407,7 +413,7 @@ test_hdb_concurrency(char *name, const char *ext, int threaded)
                  "Could not store entry for \"foobar\" in HDB %s "
                  "while iterating it", name);
     }
-    free_HDB_entry(&entw.entry);
+    free_HDB_entry(&entw);
 
     /* Tell the reader to go again */
     readers_turn(&ts, child, threaded);
index 6aaecc083ec7518c0c9273b965a937542913f80f..a4c44ba190e5139d46b29a5822c35dbe9f246886 100644 (file)
@@ -106,7 +106,7 @@ TDB_unlock(krb5_context context, HDB *db)
 }
 
 static krb5_error_code
-TDB_firstkey(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry)
+TDB_firstkey(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry)
 {
     /* XXX Implement */
     /* Tricky thing: heim_dict_iterate_f() is inconvenient here */
@@ -115,7 +115,7 @@ TDB_firstkey(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry)
 }
 
 static krb5_error_code
-TDB_nextkey(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry)
+TDB_nextkey(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry)
 {
     /* XXX Implement */
     /* Tricky thing: heim_dict_iterate_f() is inconvenient here */
@@ -151,14 +151,13 @@ TDB__put(krb5_context context, HDB *db, int rplc, krb5_data kd, krb5_data vd)
 {
     krb5_error_code ret = 0;
     TEST_HDB *tdb = (void *)db;
-    heim_object_t e = NULL;
     heim_object_t k = NULL;
     heim_object_t v = NULL;
 
     if ((k = heim_data_create(kd.data, kd.length)) == NULL ||
         (v = heim_data_create(vd.data, vd.length)) == NULL)
         ret = krb5_enomem(context);
-    if (ret == 0 && !rplc && (e = heim_dict_get_value(tdb->dict, k)) != NULL)
+    if (ret == 0 && !rplc && heim_dict_get_value(tdb->dict, k) != NULL)
         ret = HDB_ERR_EXISTS;
     if (ret == 0 && heim_dict_set_value(tdb->dict, k, v))
         ret = krb5_enomem(context);
@@ -172,11 +171,11 @@ TDB__del(krb5_context context, HDB *db, krb5_data key)
 {
     krb5_error_code ret = 0;
     TEST_HDB *tdb = (void *)db;
-    heim_object_t k, v;
+    heim_object_t k;
 
     if ((k = heim_data_create(key.data, key.length)) == NULL)
         ret = krb5_enomem(context);
-    if (ret == 0 && (v = heim_dict_get_value(tdb->dict, k)) == NULL)
+    if (ret == 0 && heim_dict_get_value(tdb->dict, k) == NULL)
         ret = HDB_ERR_NOENTRY;
     if (ret == 0)
         heim_dict_delete_key(tdb->dict, k);
@@ -198,7 +197,8 @@ hdb_test_create(krb5_context context, struct HDB **db, const char *arg)
     if ((tdb = calloc(1, sizeof(tdb[0]))) == NULL ||
         (tdb->hdb.hdb_name = strdup(arg)) == NULL ||
         (tdb->dict = heim_dict_create(10)) == NULL) {
-        free(tdb->hdb.hdb_name);
+        if (tdb)
+            free(tdb->hdb.hdb_name);
         free(tdb);
         return krb5_enomem(context);
     }
@@ -337,7 +337,7 @@ static void
 make_namespace(krb5_context context, HDB *db, const char *name)
 {
     krb5_error_code ret = 0;
-    hdb_entry_ex e;
+    hdb_entry e;
     Key k;
 
     memset(&k, 0, sizeof(k));
@@ -346,85 +346,83 @@ make_namespace(krb5_context context, HDB *db, const char *name)
 
     /* Setup the HDB entry */
     memset(&e, 0, sizeof(e));
-    e.ctx = 0;
-    e.free_entry = 0;
-    e.entry.created_by.time = krs[0].epoch;
-    e.entry.valid_start = e.entry.valid_end = e.entry.pw_end = 0;
-    e.entry.generation = 0;
-    e.entry.flags = int2HDBFlags(0);
-    e.entry.flags.server = e.entry.flags.client = 1;
-    e.entry.flags.virtual = 1;
+    e.created_by.time = krs[0].epoch;
+    e.valid_start = e.valid_end = e.pw_end = 0;
+    e.generation = 0;
+    e.flags = int2HDBFlags(0);
+    e.flags.server = e.flags.client = 1;
+    e.flags.virtual = 1;
 
     /* Setup etypes */
     if (ret == 0 &&
-        (e.entry.etypes = malloc(sizeof(*e.entry.etypes))) == NULL)
+        (e.etypes = malloc(sizeof(*e.etypes))) == NULL)
         ret = krb5_enomem(context);
     if (ret == 0)
-        e.entry.etypes->len = 3;
+        e.etypes->len = 3;
     if (ret == 0 &&
-        (e.entry.etypes->val = calloc(e.entry.etypes->len,
-                                      sizeof(e.entry.etypes->val[0]))) == NULL)
+        (e.etypes->val = calloc(e.etypes->len,
+                                      sizeof(e.etypes->val[0]))) == NULL)
         ret = krb5_enomem(context);
     if (ret == 0) {
-        e.entry.etypes->val[0] = KRB5_ENCTYPE_AES128_CTS_HMAC_SHA256_128;
-        e.entry.etypes->val[1] = KRB5_ENCTYPE_AES256_CTS_HMAC_SHA384_192;
-        e.entry.etypes->val[2] = KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96;
+        e.etypes->val[0] = KRB5_ENCTYPE_AES128_CTS_HMAC_SHA256_128;
+        e.etypes->val[1] = KRB5_ENCTYPE_AES256_CTS_HMAC_SHA384_192;
+        e.etypes->val[2] = KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96;
     }
 
     /* Setup max_life and max_renew */
     if (ret == 0 &&
-        (e.entry.max_life = malloc(sizeof(*e.entry.max_life))) == NULL)
+        (e.max_life = malloc(sizeof(*e.max_life))) == NULL)
         ret = krb5_enomem(context);
     if (ret == 0 &&
-        (e.entry.max_renew = malloc(sizeof(*e.entry.max_renew))) == NULL)
+        (e.max_renew = malloc(sizeof(*e.max_renew))) == NULL)
         ret = krb5_enomem(context);
     if (ret == 0)
         /* Make it long, so we see the clamped max */
-        *e.entry.max_renew = 2 * ((*e.entry.max_life = 15 * 24 * 3600));
+        *e.max_renew = 2 * ((*e.max_life = 15 * 24 * 3600));
 
     /* Setup principal name and created_by */
     if (ret == 0)
-        ret = krb5_parse_name(context, name, &e.entry.principal);
+        ret = krb5_parse_name(context, name, &e.principal);
     if (ret == 0)
         ret = krb5_parse_name(context, "admin@BAR.EXAMPLE",
-                              &e.entry.created_by.principal);
+                              &e.created_by.principal);
 
     /* Make base keys for first epoch */
     if (ret == 0)
-        ret = make_base_key(context, e.entry.principal, base_pw[0], &k.key);
+        ret = make_base_key(context, e.principal, base_pw[0], &k.key);
     if (ret == 0)
-        add_Keys(&e.entry.keys, &k);
+        add_Keys(&e.keys, &k);
     if (ret == 0)
-        ret = hdb_entry_set_pw_change_time(context, &e.entry, krs[0].epoch);
+        ret = hdb_entry_set_pw_change_time(context, &e, krs[0].epoch);
     free_Key(&k);
-    e.entry.kvno = krs[0].base_key_kvno;
+    e.kvno = krs[0].base_key_kvno;
 
     /* Move them to history */
     if (ret == 0)
-        ret = hdb_add_current_keys_to_history(context, &e.entry);
-    free_Keys(&e.entry.keys);
+        ret = hdb_add_current_keys_to_history(context, &e);
+    free_Keys(&e.keys);
 
     /* Make base keys for second epoch */
     if (ret == 0)
-        ret = make_base_key(context, e.entry.principal, base_pw[1], &k.key);
+        ret = make_base_key(context, e.principal, base_pw[1], &k.key);
     if (ret == 0)
-        add_Keys(&e.entry.keys, &k);
-    e.entry.kvno = krs[1].base_key_kvno;
+        add_Keys(&e.keys, &k);
+    e.kvno = krs[1].base_key_kvno;
     if (ret == 0)
-        ret = hdb_entry_set_pw_change_time(context, &e.entry, krs[1].epoch);
+        ret = hdb_entry_set_pw_change_time(context, &e, krs[1].epoch);
 
     /* Add the key rotation metadata */
     if (ret == 0)
-        ret = hdb_entry_add_key_rotation(context, &e.entry, 0, &krs[0]);
+        ret = hdb_entry_add_key_rotation(context, &e, 0, &krs[0]);
     if (ret == 0)
-        ret = hdb_entry_add_key_rotation(context, &e.entry, 0, &krs[1]);
+        ret = hdb_entry_add_key_rotation(context, &e, 0, &krs[1]);
 
     if (ret == 0)
         ret = db->hdb_store(context, db, 0, &e);
     if (ret)
         krb5_err(context, 1, ret, "failed to setup a namespace principal");
     free_Key(&k);
-    hdb_free_entry(context, &e);
+    hdb_free_entry(context, db, &e);
 }
 
 #define WK_PREFIX "WELLKNOWN/" HDB_WK_NAMESPACE "/"
@@ -449,7 +447,7 @@ static const char *unexpected[] = {
  * different time offsets in each period.
  */
 #define NUM_OFFSETS 5
-static hdb_entry_ex e[
+static hdb_entry e[
     (sizeof(expected) / sizeof(expected[0])) *
     (sizeof(krs) / sizeof(krs[0])) *
     NUM_OFFSETS
@@ -481,8 +479,8 @@ fetch_entries(krb5_context context,
     krb5_error_code ret = 0;
     krb5_principal p = NULL;
     krb5_keyblock base_key, dk;
-    hdb_entry_ex *ep;
-    hdb_entry_ex no;
+    hdb_entry *ep;
+    hdb_entry no;
     size_t i, b;
     int toffset = 0;
 
@@ -543,14 +541,14 @@ fetch_entries(krb5_context context,
             }
         } else {
             if (ret == 0 &&
-                !krb5_principal_compare(context, p, ep->entry.principal))
+                !krb5_principal_compare(context, p, ep->principal))
             krb5_errx(context, 1, "wrong principal in fetched entry");
         }
 
         {
             HDB_Ext_KeySet *hist_keys;
             HDB_extension *ext;
-            ext = hdb_find_extension(&ep->entry,
+            ext = hdb_find_extension(ep,
                                      choice_HDB_extension_data_hist_keys);
             if (ext) {
                 /* Sort key history by kvno, why not */
@@ -613,23 +611,23 @@ fetch_entries(krb5_context context,
         if (ret)
             krb5_err(context, 1, ret, "deriving keys for comparison");
 
-        if (kvno != ep->entry.kvno)
-            krb5_errx(context, 1, "kvno mismatch (%u != %u)", kvno, ep->entry.kvno);
-        (void) hdb_entry_get_pw_change_time(&ep->entry, &chg_time);
+        if (kvno != ep->kvno)
+            krb5_errx(context, 1, "kvno mismatch (%u != %u)", kvno, ep->kvno);
+        (void) hdb_entry_get_pw_change_time(ep, &chg_time);
         if (set_time != chg_time)
             krb5_errx(context, 1, "key change time mismatch");
-        if (ep->entry.keys.len == 0)
+        if (ep->keys.len == 0)
             krb5_errx(context, 1, "no keys!");
-        if (ep->entry.keys.val[0].key.keytype != dk.keytype)
+        if (ep->keys.val[0].key.keytype != dk.keytype)
             krb5_errx(context, 1, "enctype mismatch!");
-        if (ep->entry.keys.val[0].key.keyvalue.length !=
+        if (ep->keys.val[0].key.keyvalue.length !=
             dk.keyvalue.length)
             krb5_errx(context, 1, "key length mismatch!");
-        if (memcmp(ep->entry.keys.val[0].key.keyvalue.data,
+        if (memcmp(ep->keys.val[0].key.keyvalue.data,
                    dk.keyvalue.data, dk.keyvalue.length) != 0)
             krb5_errx(context, 1, "key mismatch!");
-        if (memcmp(ep->entry.keys.val[0].key.keyvalue.data,
-                   e[b + i - 1].entry.keys.val[0].key.keyvalue.data,
+        if (memcmp(ep->keys.val[0].key.keyvalue.data,
+                   e[b + i - 1].keys.val[0].key.keyvalue.data,
                    dk.keyvalue.length) == 0)
             krb5_errx(context, 1, "different virtual principals have the same keys!");
         /* XXX Add check that we have the expected number of history keys */
@@ -655,14 +653,14 @@ check_kvnos(krb5_context context)
         for (k = 0; k < sizeof(e)/sizeof(e[0]); k++) {
             HDB_Ext_KeySet *hist_keys;
             HDB_extension *ext;
-            hdb_entry_ex *ep;
+            hdb_entry *ep;
             int match = 0;
 
             if ((k % NUM_OFFSETS) != i)
                 continue;
 
             ep = &e[k];
-            if (ep->entry.principal == NULL)
+            if (ep->principal == NULL)
                 continue; /* Didn't fetch this one */
 
             /*
@@ -670,15 +668,15 @@ check_kvnos(krb5_context context)
              * or else add them to `keysets'.
              */
             for (m = 0; m < keysets.len; m++) {
-                if (ep->entry.kvno == keysets.val[m].kvno) {
+                if (ep->kvno == keysets.val[m].kvno) {
                     /* Check the key is the same */
-                    if (ep->entry.keys.val[0].key.keytype !=
+                    if (ep->keys.val[0].key.keytype !=
                         keysets.val[m].keys.val[0].key.keytype ||
-                        ep->entry.keys.val[0].key.keyvalue.length !=
+                        ep->keys.val[0].key.keyvalue.length !=
                         keysets.val[m].keys.val[0].key.keyvalue.length ||
-                        memcmp(ep->entry.keys.val[0].key.keyvalue.data,
+                        memcmp(ep->keys.val[0].key.keyvalue.data,
                                keysets.val[m].keys.val[0].key.keyvalue.data,
-                               ep->entry.keys.val[0].key.keyvalue.length) != 0)
+                               ep->keys.val[0].key.keyvalue.length) != 0)
                         krb5_errx(context, 1,
                                   "key mismatch for same princ & kvno");
                     match = 1;
@@ -687,8 +685,8 @@ check_kvnos(krb5_context context)
             if (m == keysets.len) {
                 hdb_keyset ks;
 
-                ks.kvno = ep->entry.kvno;
-                ks.keys = ep->entry.keys;
+                ks.kvno = ep->kvno;
+                ks.keys = ep->keys;
                 ks.set_time = 0;
                 if (add_HDB_Ext_KeySet(&keysets, &ks))
                     krb5_err(context, 1, ENOMEM, "out of memory");
@@ -698,7 +696,7 @@ check_kvnos(krb5_context context)
                 continue;
 
             /* For all non-current keysets, repeat the above */
-            ext = hdb_find_extension(&ep->entry,
+            ext = hdb_find_extension(ep,
                                      choice_HDB_extension_data_hist_keys);
             if (!ext)
                 continue;
@@ -706,20 +704,20 @@ check_kvnos(krb5_context context)
             for (p = 0; p < hist_keys->len; p++) {
                 for (m = 0; m < keysets.len; m++) {
                     if (keysets.val[m].kvno == hist_keys->val[p].kvno)
-                        if (ep->entry.keys.val[0].key.keytype !=
+                        if (ep->keys.val[0].key.keytype !=
                             keysets.val[m].keys.val[0].key.keytype ||
-                            ep->entry.keys.val[0].key.keyvalue.length !=
+                            ep->keys.val[0].key.keyvalue.length !=
                             keysets.val[m].keys.val[0].key.keyvalue.length ||
-                            memcmp(ep->entry.keys.val[0].key.keyvalue.data,
+                            memcmp(ep->keys.val[0].key.keyvalue.data,
                                    keysets.val[m].keys.val[0].key.keyvalue.data,
-                                   ep->entry.keys.val[0].key.keyvalue.length) != 0)
+                                   ep->keys.val[0].key.keyvalue.length) != 0)
                             krb5_errx(context, 1,
                                       "key mismatch for same princ & kvno");
                 }
                 if (m == keysets.len) {
                     hdb_keyset ks;
-                    ks.kvno = ep->entry.kvno;
-                    ks.keys = ep->entry.keys;
+                    ks.kvno = ep->kvno;
+                    ks.keys = ep->keys;
                     ks.set_time = 0;
                     if (add_HDB_Ext_KeySet(&keysets, &ks))
                         krb5_err(context, 1, ENOMEM, "out of memory");
@@ -743,15 +741,14 @@ print_em(krb5_context context)
 
         if (0 == i % (sizeof(expected)/sizeof(expected[0])))
             continue;
-        if (e[i].entry.principal == NULL)
+        if (e[i].principal == NULL)
             continue;
-        hex_encode(e[i].entry.keys.val[0].key.keyvalue.data,
-                   e[i].entry.keys.val[0].key.keyvalue.length, &x);
-        printf("%s %u %s\n", x, e[i].entry.kvno, name);
+        hex_encode(e[i].keys.val[0].key.keyvalue.data,
+                   e[i].keys.val[0].key.keyvalue.length, &x);
+        printf("%s %u %s\n", x, e[i].kvno, name);
         free(x);
 
-        ext = hdb_find_extension(&e[i].entry,
-                                 choice_HDB_extension_data_hist_keys);
+        ext = hdb_find_extension(&e[i], choice_HDB_extension_data_hist_keys);
         if (!ext)
             continue;
         hist_keys = &ext->data.u.hist_keys;
@@ -759,6 +756,7 @@ print_em(krb5_context context)
             hex_encode(hist_keys->val[p].keys.val[0].key.keyvalue.data,
                        hist_keys->val[p].keys.val[0].key.keyvalue.length, &x);
             printf("%s %u %s\n", x, hist_keys->val[p].kvno, name);
+           free(x);
         }
     }
 }
@@ -773,12 +771,12 @@ check_expected_kvnos(krb5_context context)
 
     for (i = 0; i < sizeof(expected)/sizeof(expected[0]); i++) {
         for (k = 0; k < sizeof(krs)/sizeof(krs[0]); k++) {
-            hdb_entry_ex *ep = &e[k * sizeof(expected)/sizeof(expected[0]) + i];
+            hdb_entry *ep = &e[k * sizeof(expected)/sizeof(expected[0]) + i];
 
-            if (ep->entry.principal == NULL)
+            if (ep->principal == NULL)
                 continue;
             for (m = 0; m < NUM_OFFSETS; m++) {
-                ext = hdb_find_extension(&ep->entry,
+                ext = hdb_find_extension(ep,
                                          choice_HDB_extension_data_hist_keys);
                 if (!ext)
                     continue;
@@ -789,7 +787,7 @@ check_expected_kvnos(krb5_context context)
                 }
             }
             fprintf(stderr, "%s at %lu: kvno %u\n", expected[i], k,
-                    ep->entry.kvno);
+                    ep->kvno);
         }
     }
 }
@@ -936,7 +934,7 @@ main(int argc, char **argv)
 
     /* Cleanup */
     for (i = 0; ret == 0 && i < sizeof(e) / sizeof(e[0]); i++)
-        hdb_free_entry(context, &e[i]);
+        hdb_free_entry(context, db, &e[i]);
     db->hdb_destroy(context, db);
     krb5_free_context(context);
     return 0;
index 0846f7337430804993f369cd3932c8a042f12125..058060dae0c1832c8f88fd7a97ecf44c1fa9fa25 100644 (file)
@@ -70,7 +70,6 @@ HEIMDAL_HDB_1.0 {
                hdb_prune_keys;
                hdb_prune_keys_kvno;
                hdb_read_master_key;
-               hdb_remove_base_keys;
                hdb_remove_keys;
                hdb_replace_extension;
                hdb_seal_key;
index e32da3b93c3dc2a25c5d379223200a0285068436..214dabf0e831d44a171c9603e5c782d862ac3ec1 100644 (file)
@@ -11,7 +11,7 @@ BUILT_SOURCES =                               \
        hx509_err.c                     \
        hx509_err.h
 
-AM_YFLAGS = -d
+AM_YFLAGS = -o sel-gram.c
 
 dist_libhx509_la_SOURCES = \
        ca.c \
@@ -50,6 +50,7 @@ dist_libhx509_la_SOURCES = \
 
 dist_libhx509template_la_SOURCES = $(dist_libhx509_la_SOURCES)
 
+sel-gram.h: sel-gram.c
 sel-lex.c: sel-gram.h
 
 libhx509_la_DEPENDENCIES = version-script.map
index 807621c21d153c93f39708cd86c6273a9b960bf8..3d62b93fa57e0ca5518a317d468643ccb9685a06 100644 (file)
@@ -2353,7 +2353,6 @@ count_sans(hx509_request req, size_t *n)
     for (i = 0; ret == 0; i++) {
         hx509_san_type san_type;
 
-        frees(&s);
         ret = hx509_request_get_san(req, i, &san_type, &s);
         if (ret)
             break;
@@ -2370,6 +2369,7 @@ count_sans(hx509_request req, size_t *n)
         }
         frees(&s);
     }
+    free(s);
     return ret == HX509_NO_ITEM ? 0 : ret;
 }
 
@@ -2565,9 +2565,9 @@ get_cf(hx509_context context,
     }
 
     *out = heim_config_get_list(context->hcontext, cf, label, svc, NULL);
-    if (*out)
+    if (*out) {
         ret = 0;
-    if (ret) {
+    } else {
         heim_log_msg(context->hcontext, logf, 3, NULL,
                      "No configuration for %s %s certificate's realm "
                      "-> %s -> kx509 -> %s%s%s", def, label, realm, label,
@@ -2741,7 +2741,8 @@ set_tbs(hx509_context context,
                             realm);
 
     /* Populate requested certificate extensions from CSR/CSRPlus if allowed */
-    ret = hx509_ca_tbs_set_from_csr(context, tbs, req);
+    if (ret == 0)
+        ret = hx509_ca_tbs_set_from_csr(context, tbs, req);
     if (ret == 0)
         ret = set_template(context, logf, cf, tbs);
 
@@ -2939,6 +2940,8 @@ _hx509_ca_issue_certificate(hx509_context context,
     hx509_request_authorize_ku(req, ku);
 
     ret = get_cf(context, cf, logf, req, cprinc, &cf);
+    if (ret)
+        return ret;
 
     if ((ca = heim_config_get_string(context->hcontext, cf,
                                      "ca", NULL)) == NULL) {
@@ -3050,9 +3053,8 @@ _hx509_ca_issue_certificate(hx509_context context,
     hx509_env_free(&env);
 
     /* All done with the TBS, sign/issue the certificate */
-    ret = hx509_ca_sign(context, tbs, signer, &cert);
-    if (ret)
-        goto out;
+    if (ret == 0)
+        ret = hx509_ca_sign(context, tbs, signer, &cert);
 
     /*
      * Gather the certificate and chain into a MEMORY store, being careful not
@@ -3063,8 +3065,9 @@ _hx509_ca_issue_certificate(hx509_context context,
      * the full chain in the issuer credential store and copying only the certs
      * (but not the private keys) is safer and easier to configure.
      */
-    ret = hx509_certs_init(context, "MEMORY:certs",
-                           HX509_CERTS_NO_PRIVATE_KEYS, NULL, out);
+    if (ret == 0)
+        ret = hx509_certs_init(context, "MEMORY:certs",
+                               HX509_CERTS_NO_PRIVATE_KEYS, NULL, out);
     if (ret == 0)
         ret = hx509_certs_add(context, *out, cert);
     if (ret == 0 && send_chain) {
index 0d99a748fc6aa2367380193db5fb85b07fa7f4e6..33805b8ed1a781081ee08756a462804f464db37b 100644 (file)
@@ -893,9 +893,12 @@ HX509_LIB_FUNCTION void HX509_LIB_CALL
 hx509_free_octet_string_list(hx509_octet_string_list *list)
 {
     size_t i;
-    for (i = 0; i < list->len; i++)
-       der_free_octet_string(&list->val[i]);
-    free(list->val);
+
+    if (list->val) {
+        for (i = 0; i < list->len; i++)
+            der_free_octet_string(&list->val[i]);
+        free(list->val);
+    }
     list->val = NULL;
     list->len = 0;
 }
@@ -2438,10 +2441,9 @@ hx509_verify_path(hx509_context context,
                 * EE checking below.
                 */
                type = EE_CERT;
-                /* FALLTHROUGH */
            }
        }
-        /* FALLTHROUGH */
+        fallthrough;
        case EE_CERT:
            /*
             * If there where any proxy certificates in the chain
@@ -2808,6 +2810,12 @@ _hx509_set_cert_attribute(hx509_context context,
 {
     hx509_cert_attribute a;
     void *d;
+    int ret;
+
+    /*
+     * TODO: Rewrite this (and hx509_cert_attribute, and _hx509_cert_attrs) to
+     * use the add_AttributeValues() util generated by asn1_compile.
+     */
 
     if (hx509_cert_get_attribute(cert, oid) != NULL)
        return 0;
@@ -2824,13 +2832,18 @@ _hx509_set_cert_attribute(hx509_context context,
     if (a == NULL)
        return ENOMEM;
 
-    der_copy_octet_string(attr, &a->data);
-    der_copy_oid(oid, &a->oid);
-
-    cert->attrs.val[cert->attrs.len] = a;
-    cert->attrs.len++;
+    ret = der_copy_octet_string(attr, &a->data);
+    if (ret == 0)
+        ret = der_copy_oid(oid, &a->oid);
+    if (ret == 0) {
+        cert->attrs.val[cert->attrs.len] = a;
+        cert->attrs.len++;
+    } else {
+        der_free_octet_string(&a->data);
+        free(a);
+    }
 
-    return 0;
+    return ret;
 }
 
 /**
@@ -3705,13 +3718,12 @@ _hx509_cert_to_env(hx509_context context, hx509_cert cert, hx509_env *env)
        goto out;
 
     ret = hx509_name_to_string(name, &buf);
-    if (ret) {
-       hx509_name_free(&name);
+    hx509_name_free(&name);
+    if (ret)
        goto out;
-    }
 
     ret = hx509_env_add(context, &envcert, "subject", buf);
-    hx509_name_free(&name);
+    hx509_xfree(buf);
     if (ret)
        goto out;
 
index 453762bd10f6dbb6a076b0e38b40305de74c0fd7..d2728a38c2f9f20b10503a523a65878b3df964e5 100644 (file)
@@ -182,7 +182,7 @@ fill_CMSIdentifier(const hx509_cert cert,
                                                   &id->u.subjectKeyIdentifier);
        if (ret == 0)
            break;
-       /* FALLTHROUGH */
+        fallthrough;
     case CMS_ID_NAME: {
        hx509_name name;
 
@@ -1565,7 +1565,9 @@ hx509_cms_create_signed(hx509_context context,
 
     sigctx.sd.version = cMSVersion_v3;
 
-    der_copy_oid(eContentType, &sigctx.sd.encapContentInfo.eContentType);
+    ret = der_copy_oid(eContentType, &sigctx.sd.encapContentInfo.eContentType);
+    if (ret)
+        goto out;
 
     /**
      * Use HX509_CMS_SIGNATURE_DETACHED to create detached signatures.
index dd6222687af4b106100402a57e96317149eb8d55..7b46809816cf8a8c6efe274d40314a75b1e01947 100644 (file)
@@ -191,8 +191,9 @@ match_localkeyid(hx509_context context,
     q.local_key_id = &value->localKeyId;
 
     ret = hx509_certs_find(context, certs, &q, &cert);
+    if (ret == 0 && cert == NULL)
+        ret = HX509_CERT_NOT_FOUND;
     if (ret == 0) {
-
        if (value->private_key)
            _hx509_cert_assign_key(cert, value->private_key);
        hx509_cert_free(cert);
index 77e721064ef11e158ae033e93cc43146967222a1..8d368ed9c4d102e5120e055627940a01866050de 100644 (file)
@@ -436,6 +436,8 @@ rsa_private_key2SPKI(hx509_context context,
     memset(spki, 0, sizeof(*spki));
 
     len = i2d_RSAPublicKey(private_key->private_key.rsa, NULL);
+    if (len < 0)
+       return -1;
 
     spki->subjectPublicKey.data = malloc(len);
     if (spki->subjectPublicKey.data == NULL) {
@@ -1625,6 +1627,8 @@ _hx509_private_key_export(hx509_context context,
                          hx509_key_format_t format,
                          heim_octet_string *data)
 {
+    data->length = 0;
+    data->data = NULL;
     if (key->ops->export == NULL) {
        hx509_clear_error_string(context);
        return HX509_UNIMPLEMENTED_OPERATION;
index d3ebd1bf64870752e8af5051bce52d23cb85aab2..aee4f79e747da6525f12cd70c1887f3eae783840 100644 (file)
@@ -147,48 +147,28 @@ hx509_enomem(hx509_context context)
 HX509_LIB_FUNCTION char * HX509_LIB_CALL
 hx509_get_error_string(hx509_context context, int error_code)
 {
-    heim_error_t msg;
-    heim_string_t s;
-    char *str = NULL;
-
-    if (context == NULL) {
-        const char *sys_err_msg;
-
-        /* This case should only happen on hx509_context_init() failure */
-        if ((sys_err_msg = strerror(error_code))) {
-            if (asprintf(&str, "hx509_context_init system error: %s (%d)",
-                         sys_err_msg, error_code) == -1)
-                return NULL;
-            return str;
-        }
-        if (asprintf(&str, "hx509_context_init unknown error: %d",
-                     error_code) == -1)
-            return NULL;
-        return str;
-    }
+    heim_string_t s = NULL;
+    const char *cstr = NULL;
+    char *str;
 
-    msg = context->error;
-    if (msg == NULL || heim_error_get_code(msg) != error_code) {
-       const char *cstr;
-
-       cstr = com_right(context->et_list, error_code);
-       if (cstr)
-           return strdup(cstr);
-       cstr = strerror(error_code);
-       if (cstr)
-           return strdup(cstr);
-       if (asprintf(&str, "<unknown error: %d>", error_code) == -1)
-           return NULL;
-       return str;
-    }
+    if (context) {
+        if (context->error &&
+            heim_error_get_code(context->error) == error_code &&
+            (s = heim_error_copy_string(context->error)))
+            cstr = heim_string_get_utf8(s);
 
-    s = heim_error_copy_string(msg);
-    if (s) {
-       const char *cstr = heim_string_get_utf8(s);
-       if (cstr)
-           str = strdup(cstr);
-       heim_release(s);
-    }
+        if (cstr == NULL)
+            cstr = com_right(context->et_list, error_code);
+
+        if (cstr == NULL && error_code > -1)
+            cstr = strerror(error_code);
+    } /* else this could be an error in hx509_context_init() */
+
+    if (cstr == NULL)
+        cstr = error_message(error_code); /* never returns NULL */
+
+    str = strdup(cstr);
+    heim_release(s);
     return str;
 }
 
@@ -218,9 +198,11 @@ hx509_free_error_string(char *str)
  * @ingroup hx509_error
  */
 
-HX509_LIB_FUNCTION void HX509_LIB_CALL
+HX509_LIB_NORETURN_FUNCTION
+     __attribute__ ((__noreturn__, __format__ (__printf__, 4, 5)))
+void HX509_LIB_CALL
 hx509_err(hx509_context context, int exit_code,
-         int error_code, const char *fmt, ...)
+          int error_code, const char *fmt, ...)
 {
     va_list ap;
     const char *msg;
index 1b5ca3eae7105fb6921d852399ea39faf6ea7af2..a22f6252cfa7a824bd31ffce8d318f64a4d15fd2 100644 (file)
@@ -230,7 +230,7 @@ hx509_pem_read(hx509_context context,
                where = INDATA;
                goto indata;
            }
-           /* FALLTHROUGH */
+            fallthrough;
        case INHEADER:
            if (buf[0] == '\0') {
                where = INDATA;
@@ -342,17 +342,15 @@ _hx509_erase_file(hx509_context context, const char *fn)
     if (ret == -1 && errno == ENOENT)
         return 0;
     if (ret == -1) {
-        hx509_set_error_string(context, 0, ret, "hx509_certs_destroy: "
-                               "stat of \"%s\": %s", fn, strerror(ret));
+        hx509_set_error_string(context, 0, errno, "hx509_certs_destroy: "
+                               "stat of \"%s\": %s", fn, strerror(errno));
         return errno;
     }
 
     fd = open(fn, O_RDWR | O_BINARY | O_CLOEXEC | O_NOFOLLOW);
+    if (fd < 0)
+       return errno == ENOENT ? 0 : errno;
     rk_cloexec(fd);
-    if (ret == -1 && errno == ENOENT)
-        return 0;
-    if (ret == -1)
-        return errno;
 
     if (unlink(fn) < 0) {
        ret = errno;
index 43c4713d11632ae5787a85bb1f0eb712be49b4e4..1bcfdfa44e9db6a3c2cdfabfbf4c1a35f4bc9cd2 100644 (file)
@@ -412,17 +412,19 @@ cms_create_sd(struct cms_create_sd_options *opt, int argc, char **argv)
     size_t sz;
     void *p;
     int ret, flags = 0;
-    char *infile, *outfile = NULL;
+    const char *outfile = NULL;
+    char *infile, *freeme = NULL;
 
     memset(&contentType, 0, sizeof(contentType));
 
     infile = argv[0];
 
     if (argc < 2) {
-       ret = asprintf(&outfile, "%s.%s", infile,
+       ret = asprintf(&freeme, "%s.%s", infile,
                       opt->pem_flag ? "pem" : "cms-signeddata");
-       if (ret == -1 || outfile == NULL)
+       if (ret == -1 || freeme == NULL)
            errx(1, "out of memory");
+        outfile = freeme;
     } else
        outfile = argv[1];
 
@@ -549,6 +551,7 @@ cms_create_sd(struct cms_create_sd_options *opt, int argc, char **argv)
 
     hx509_certs_free(&signer);
     free(o.data);
+    free(freeme);
 
     return 0;
 }
@@ -843,6 +846,7 @@ pcert_validate(struct validate_options *opt, int argc, char **argv)
        hx509_certs_iter_f(context, certs, validate_f, ctx);
        hx509_certs_free(&certs);
        argv++;
+        free(sn);
     }
     hx509_validate_ctx_free(ctx);
 
@@ -1263,6 +1267,7 @@ revoke_print(struct revoke_print_options *opt, int argc, char **argv)
     if (ret)
        warnx("hx509_revoke_print: %d", ret);
 
+    hx509_revoke_free(&revoke_ctx);
     return ret;
 }
 
@@ -1363,7 +1368,7 @@ get_key(const char *fn, const char *type, int optbits,
     int ret = 0;
 
     if (type) {
-        struct hx509_generate_private_context *gen_ctx;
+        struct hx509_generate_private_context *gen_ctx = NULL;
 
        if (strcasecmp(type, "rsa") != 0)
            errx(1, "can only handle rsa keys for now");
@@ -1375,6 +1380,7 @@ get_key(const char *fn, const char *type, int optbits,
             ret = _hx509_generate_private_key_bits(context, gen_ctx, optbits);
         if (ret == 0)
             ret = _hx509_generate_private_key(context, gen_ctx, signer);
+        _hx509_generate_private_key_free(&gen_ctx);
         if (ret)
             hx509_err(context, 1, ret, "failed to generate private key of type %s", type);
 
@@ -1420,6 +1426,7 @@ generate_key(struct generate_key_options *opt, int argc, char **argv)
     const char *type = opt->type_string ? opt->type_string : "rsa";
     int bits = opt->key_bits_integer ? opt->key_bits_integer : 2048;
 
+    memset(&signer, 0, sizeof(signer));
     get_key(argv[0], type, bits, &signer);
     hx509_private_key_free(&signer);
     return 0;
@@ -1436,6 +1443,7 @@ request_create(struct request_create_options *opt, int argc, char **argv)
     const char *outfile = argv[0];
 
     memset(&key, 0, sizeof(key));
+    memset(&signer, 0, sizeof(signer));
 
     get_key(opt->key_string,
            opt->generate_key_string,
@@ -2416,6 +2424,7 @@ test_crypto(struct test_crypto_options *opt, int argc, char ** argv)
        hx509_err(context, 1, ret, "hx509_cert_iter");
 
     hx509_certs_free(&certs);
+    hx509_verify_destroy_ctx(vctx);
 
     return 0;
 }
@@ -2507,6 +2516,7 @@ crl_sign(struct crl_sign_options *opt, int argc, char **argv)
            ret = hx509_certs_append(context, revoked, lock, sn);
            if (ret)
                hx509_err(context, 1, ret, "hx509_certs_append: %s", sn);
+            free(sn);
        }
 
        hx509_crl_add_revoked_certs(context, crl, revoked);
@@ -2775,9 +2785,12 @@ acert1_kus(struct acert_options *opt,
     size_t unwanted = 0;
     size_t wanted = opt->has_ku_strings.num_strings;
     size_t i, k, sz;
+    int ret;
 
     memset(&ku, 0, sizeof(ku));
-    decode_KeyUsage(e->extnValue.data, e->extnValue.length, &ku, &sz);
+    ret = decode_KeyUsage(e->extnValue.data, e->extnValue.length, &ku, &sz);
+    if (ret)
+        return ret;
     ku_num = KeyUsage2int(ku);
 
     /* Validate requested key usage values */
@@ -2983,7 +2996,7 @@ acert1(struct acert_options *opt, size_t cert_num, hx509_cert cert, int *matched
     ekus_wanted = opt->has_eku_strings.num_strings;
     kus_wanted = opt->has_ku_strings.num_strings;
     wanted = sans_wanted + ekus_wanted + kus_wanted;
-    found = sans_found = ekus_found = kus_found = 0;
+    sans_found = ekus_found = kus_found = 0;
 
     if (e == NULL) {
         if (wanted)
@@ -3080,6 +3093,8 @@ acert(struct acert_options *opt, int argc, char **argv)
             ret = acert1(opt, n++, cert, &matched);
             if (matched)
                 break;
+            hx509_cert_free(cert);
+            cert = NULL;
         }
         if (cursor)
             (void) hx509_certs_end_seq(context, certs, cursor);
@@ -3093,6 +3108,7 @@ acert(struct acert_options *opt, int argc, char **argv)
     if (ret)
         hx509_err(context, 1, ret, "Matching certificate did not meet "
                   "requirements");
+    hx509_cert_free(cert);
     free(sn);
     return 0;
 }
index ef3465050225c24411de0eb93da3fb79bdb9cae2..f25cdf4e419b3cec94b41edb81f37a8a0a416654 100644 (file)
@@ -561,11 +561,14 @@ hx509_certs_find(hx509_context context,
            break;
        if (_hx509_query_match_cert(context, q, c)) {
            *r = c;
+            c = NULL;
            break;
        }
        hx509_cert_free(c);
+        c = NULL;
     }
 
+    hx509_cert_free(c);
     hx509_certs_end_seq(context, certs, cursor);
     if (ret)
        return ret;
@@ -573,7 +576,7 @@ hx509_certs_find(hx509_context context,
      * Return HX509_CERT_NOT_FOUND if no certificate in certs matched
      * the query.
      */
-    if (c == NULL) {
+    if (*r == NULL) {
        hx509_clear_error_string(context);
        return HX509_CERT_NOT_FOUND;
     }
index b22093cd4526e9fe4658e6ea4fc85de875246362..880668b4561603a6a103c1c448c298fa57333278 100644 (file)
@@ -548,7 +548,7 @@ store_func(hx509_context context, void *ctx, hx509_cert c)
 {
     struct store_ctx *sc = ctx;
     heim_octet_string data;
-    int ret;
+    int ret = 0;
 
     if (hx509_cert_have_private_key_only(c)) {
         data.length = 0;
@@ -564,15 +564,17 @@ store_func(hx509_context context, void *ctx, hx509_cert c)
         /* Can't store both.  Well, we could, but nothing will support it */
         if (data.data) {
             fwrite(data.data, data.length, 1, sc->f);
-            free(data.data);
         } else if (_hx509_cert_private_key_exportable(c) &&
                    !(sc->store_flags & HX509_CERTS_STORE_NO_PRIVATE_KEYS)) {
             hx509_private_key key = _hx509_cert_private_key(c);
 
+            free(data.data);
+            data.length = 0;
+            data.data = NULL;
             ret = _hx509_private_key_export(context, key,
                                             HX509_KEY_FORMAT_DER, &data);
-            fwrite(data.data, data.length, 1, sc->f);
-            free(data.data);
+            if (ret == 0 && data.length)
+                fwrite(data.data, data.length, 1, sc->f);
         }
        break;
     case USE_PEM:
@@ -583,23 +585,20 @@ store_func(hx509_context context, void *ctx, hx509_cert c)
 
            ret = _hx509_private_key_export(context, key,
                                            HX509_KEY_FORMAT_DER, &priv_key);
-           if (ret) {
-                free(data.data);
-               break;
-            }
-           hx509_pem_write(context, _hx509_private_pem_name(key), NULL, sc->f,
-                           priv_key.data, priv_key.length);
+            if (ret == 0)
+                ret = hx509_pem_write(context, _hx509_private_pem_name(key), NULL,
+                                      sc->f, priv_key.data, priv_key.length);
            free(priv_key.data);
        }
-        if (data.data) {
-            hx509_pem_write(context, "CERTIFICATE", NULL, sc->f,
-                            data.data, data.length);
-            free(data.data);
+        if (ret == 0 && data.data) {
+            ret = hx509_pem_write(context, "CERTIFICATE", NULL, sc->f,
+                                  data.data, data.length);
         }
        break;
     }
 
-    return 0;
+    free(data.data);
+    return ret;
 }
 
 static int
index 9b6a156af6c528a503f3405ed9df8014f667d9cc..7d67716b953ab2e9689d7bf7c2321379b6342ead 100644 (file)
@@ -358,29 +358,29 @@ _hx509_Name_to_string(const Name *n, char **str)
     return 0;
 }
 
-#define COPYCHARARRAY(_ds,_el,_l,_n)           \
-        (_l) = strlen(_ds->u._el);             \
-       (_n) = malloc((_l) * sizeof((_n)[0]));  \
-       if ((_n) == NULL)                       \
-           return ENOMEM;                      \
-       for (i = 0; i < (_l); i++)              \
+#define COPYCHARARRAY(_ds,_el,_l,_n)                   \
+        (_l) = strlen(_ds->u._el);                     \
+       (_n) = malloc((_l + 1) * sizeof((_n)[0]));      \
+       if ((_n) == NULL)                               \
+           return ENOMEM;                              \
+       for (i = 0; i < (_l); i++)                      \
            (_n)[i] = _ds->u._el[i]
 
 
-#define COPYVALARRAY(_ds,_el,_l,_n)            \
-        (_l) = _ds->u._el.length;              \
-       (_n) = malloc((_l) * sizeof((_n)[0]));  \
-       if ((_n) == NULL)                       \
-           return ENOMEM;                      \
-       for (i = 0; i < (_l); i++)              \
+#define COPYVALARRAY(_ds,_el,_l,_n)                    \
+        (_l) = _ds->u._el.length;                      \
+       (_n) = malloc((_l + 1) * sizeof((_n)[0]));      \
+       if ((_n) == NULL)                               \
+           return ENOMEM;                              \
+       for (i = 0; i < (_l); i++)                      \
            (_n)[i] = _ds->u._el.data[i]
 
-#define COPYVOIDARRAY(_ds,_el,_l,_n)           \
-        (_l) = _ds->u._el.length;              \
-       (_n) = malloc((_l) * sizeof((_n)[0]));  \
-       if ((_n) == NULL)                       \
-           return ENOMEM;                      \
-       for (i = 0; i < (_l); i++)              \
+#define COPYVOIDARRAY(_ds,_el,_l,_n)                   \
+        (_l) = _ds->u._el.length;                      \
+       (_n) = malloc((_l + 1) * sizeof((_n)[0]));      \
+       if ((_n) == NULL)                               \
+           return ENOMEM;                              \
+       for (i = 0; i < (_l); i++)                      \
            (_n)[i] = ((unsigned char *)_ds->u._el.data)[i]
 
 
@@ -423,7 +423,7 @@ dsstringprep(const DirectoryString *ds, uint32_t **rname, size_t *rlen)
        ret = wind_utf8ucs4_length(ds->u.utf8String, &len);
        if (ret)
            return ret;
-       name = malloc(len * sizeof(name[0]));
+       name = malloc((len + 1) * sizeof(name[0]));
        if (name == NULL)
            return ENOMEM;
        ret = wind_utf8ucs4(ds->u.utf8String, name, &len);
@@ -440,7 +440,7 @@ dsstringprep(const DirectoryString *ds, uint32_t **rname, size_t *rlen)
     /* try a couple of times to get the length right, XXX gross */
     for (i = 0; i < 4; i++) {
        *rlen = *rlen * 2;
-       if ((*rname = malloc(*rlen * sizeof((*rname)[0]))) == NULL) {
+       if ((*rname = malloc((rlen[0] + 1) * sizeof((*rname)[0]))) == NULL) {
             ret = ENOMEM;
             break;
         }
@@ -579,9 +579,9 @@ _hx509_name_modify(hx509_context context,
 {
     RelativeDistinguishedName rdn;
     size_t max_len = oidtomaxlen(oid);
-    int type_choice, ret;
-    const char *a = oidtostring(oid, &type_choice);
     char *s = NULL;
+    int type_choice = choice_DirectoryString_printableString;
+    int ret;
 
     /*
      * Check string length upper bounds.
@@ -591,10 +591,13 @@ _hx509_name_modify(hx509_context context,
      * here.
      */
     if (max_len && strlen(str) > max_len) {
+        char *a = oidtostring(oid, &type_choice);
+
         ret = HX509_PARSING_NAME_FAILED;
         hx509_set_error_string(context, 0, ret, "RDN attribute %s value too "
                                "long (max %llu): %s", a ? a : "<unknown>",
                                max_len, str);
+        free(a);
         return ret;
     }
 
@@ -622,7 +625,7 @@ _hx509_name_modify(hx509_context context,
      */
     rdn.val[0].value.element = type_choice;
     if ((s = strdup(str)) == NULL ||
-        (ret = der_copy_oid(oid, &rdn.val[0].type))) {
+        der_copy_oid(oid, &rdn.val[0].type)) {
         free(rdn.val);
         free(s);
        return hx509_enomem(context);
@@ -934,9 +937,6 @@ hx509_name_expand(hx509_context context,
                    return ENOMEM;
                }
            }
-            free(s);
-            sval = NULL;
-            s = NULL;
 
            while (p != NULL) {
                /* expand variables */
@@ -945,6 +945,7 @@ hx509_name_expand(hx509_context context,
                if (p2 == NULL) {
                    hx509_set_error_string(context, 0, EINVAL, "missing }");
                    rk_strpoolfree(strpool);
+                    free(s);
                    return EINVAL;
                }
                p += 2;
@@ -954,11 +955,13 @@ hx509_name_expand(hx509_context context,
                                           "variable %.*s missing",
                                           (int)(p2 - p), p);
                    rk_strpoolfree(strpool);
+                    free(s);
                    return EINVAL;
                }
                strpool = rk_strpoolprintf(strpool, "%s", value);
                if (strpool == NULL) {
                    hx509_set_error_string(context, 0, ENOMEM, "out of memory");
+                    free(s);
                    return ENOMEM;
                }
                p2++;
@@ -971,9 +974,14 @@ hx509_name_expand(hx509_context context,
                    strpool = rk_strpoolprintf(strpool, "%s", p2);
                if (strpool == NULL) {
                    hx509_set_error_string(context, 0, ENOMEM, "out of memory");
+                    free(s);
                    return ENOMEM;
                }
            }
+
+            free(s);
+            s = NULL;
+
            if (strpool) {
                 size_t max_bytes;
 
@@ -1392,7 +1400,9 @@ hx509_general_name_unparse(GeneralName *name, char **str)
 
     if ((ret = hx509_context_init(&context)))
         return ret;
-    return hx509_general_name_unparse2(context, name, str);
+    ret = hx509_general_name_unparse2(context, name, str);
+    hx509_context_free(&context);
+    return ret;
 }
 
 /**
@@ -1511,8 +1521,9 @@ hx509_general_name_unparse2(hx509_context context,
     default:
        return EINVAL;
     }
-    if (strpool == NULL ||
-        (*str = rk_strpoolcollect(strpool)) == NULL)
+    if (ret)
+        rk_strpoolfree(strpool);
+    else if (strpool == NULL || (*str = rk_strpoolcollect(strpool)) == NULL)
        return ENOMEM;
-    return 0;
+    return ret;
 }
index 544001ebc0dfa04fc02b80a051d6d22120ae090f..3309913f3575fededad409b3d66dea6eaa492b77 100644 (file)
@@ -361,6 +361,7 @@ check_authorityKeyIdentifier(hx509_validate_ctx ctx,
        }
     }
 
+    free_AuthorityKeyIdentifier(&ai);
     return 0;
 }
 
@@ -771,6 +772,7 @@ check_certificatePolicies(hx509_validate_ctx ctx,
                         validate_print(ctx, HX509_VALIDATE_F_VERBOSE,
                                        " Unknown:%s", qoid);
                     }
+                    free_UserNotice(&un);
                 }
             } else {
                 validate_print(ctx, HX509_VALIDATE_F_VERBOSE,
@@ -842,8 +844,11 @@ check_policyMappings(hx509_validate_ctx ctx,
         else
             validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
                            "ret=%d while decoding PolicyMappings\n", ret);
+        free(sdpoid);
+        free(idpoid);
     }
 
+    free_PolicyMappings(&pm);
     return 0;
 }
 
index f0a7c2186575cf81e43ed4759c5fb05f2e4134ae..2b3f46d532a6563a6b4f8726c7cf6dde24baaca4 100644 (file)
@@ -518,14 +518,13 @@ get_exts(hx509_context context,
          const hx509_request req,
          Extensions *exts)
 {
-    uint64_t ku_num;
     size_t size;
     int ret = 0;
 
     exts->val = NULL;
     exts->len = 0;
 
-    if ((ku_num = KeyUsage2int(req->ku))) {
+    if (KeyUsage2int(req->ku)) {
         Extension e;
 
         memset(&e, 0, sizeof(e));
@@ -718,6 +717,7 @@ hx509_request_to_pkcs10(hx509_context context,
        abort();
 
     free_CertificationRequest(&r);
+    free_Extensions(&exts);
     return ret;
 }
 
@@ -899,9 +899,9 @@ hx509_request_parse_der(hx509_context context,
 
 out:
     free_CertificationRequest(&r);
+    free_Extensions(&exts);
     if (ret)
         hx509_request_free(req);
-    free_CertificationRequest(&r);
     return ret;
 }
 
@@ -1046,7 +1046,7 @@ authorize_feat(hx509_request req, abitstring a, size_t n, int idx)
     switch (ret) {
     case 0:
         req->nauthorized++;
-        /*fallthrough*/
+        fallthrough;
     case -1:
         return 0;
     default:
@@ -1063,7 +1063,7 @@ reject_feat(hx509_request req, abitstring a, size_t n, int idx)
     switch (ret) {
     case 0:
         req->nauthorized--;
-        /*fallthrough*/
+        fallthrough;
     case -1:
         return 0;
     default:
@@ -1245,7 +1245,7 @@ san_map_type(GeneralName *san)
             if (der_heim_oid_cmp(&san->u.otherName.type_id, map[i].oid) == 0)
                 return map[i].type;
     }
-        /*fallthrough*/
+        fallthrough;
     default:                               return HX509_SAN_TYPE_UNSUPPORTED;
     }
 }
@@ -1360,14 +1360,13 @@ hx509_request_get_san(hx509_request req,
     case HX509_SAN_TYPE_REGISTERED_ID:
         return der_print_heim_oid(&san->u.registeredID, '.', out);
     case HX509_SAN_TYPE_XMPP:
-        /*fallthrough*/
+        fallthrough;
     case HX509_SAN_TYPE_MS_UPN: {
         int ret;
 
         ret = _hx509_unparse_utf8_string_name(req->context, &pool,
                                               &san->u.otherName.value);
-        if (ret == 0 &&
-            (*out = rk_strpoolcollect(pool)) == NULL)
+        if ((*out = rk_strpoolcollect(pool)) == NULL)
             return hx509_enomem(req->context);
         return ret;
     }
@@ -1376,10 +1375,9 @@ hx509_request_get_san(hx509_request req,
 
         ret = _hx509_unparse_KRB5PrincipalName(req->context, &pool,
                                                &san->u.otherName.value);
-        if (ret == 0 &&
-            (*out = rk_strpoolcollect(pool)) == NULL)
+        if ((*out = rk_strpoolcollect(pool)) == NULL)
             return hx509_enomem(req->context);
-        return 0;
+        return ret;
     }
     default:
         *type = HX509_SAN_TYPE_UNSUPPORTED;
index c2f2e00cc297793e1084efed8a9353de8eec6e88..18b2f8f8f96dc24dd6d3e4e894d4343201f18bb7 100644 (file)
@@ -202,6 +202,8 @@ verify_ocsp(hx509_context context,
     ret = hx509_certs_find(context, certs, &q, &signer);
     if (ret && ocsp->certs)
        ret = hx509_certs_find(context, ocsp->certs, &q, &signer);
+    if (ret == 0 && signer == NULL)
+        ret = HX509_CERT_NOT_FOUND;
     if (ret)
        goto out;
 
@@ -500,6 +502,8 @@ verify_crl(hx509_context context,
        q.subject_name = &crl->tbsCertList.issuer;
 
        ret = hx509_certs_find(context, certs, &q, &signer);
+        if (ret == 0 && signer == NULL)
+            ret = HX509_CERT_NOT_FOUND;
        if (ret) {
            hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
                                   "Failed to find certificate for CRL");
index 7e9d4f26d9c2cb19054d252edf873a6b35d409e9..09f641d7c051a7354e7dff21a8947eaeb2d6231b 100644 (file)
 %token <string> STRING
 %token <string> IDENTIFIER
 
+%left '!'
+%left kw_AND
+%left kw_OR
+
 %start start
 
 %%
index 0a1445ba5233154a8221fe64afdc7edd073671a5..75f675579c77d6ccc24bf4074870f62677d88582 100644 (file)
@@ -311,7 +311,7 @@ add_st_object(void)
        return NULL;
 
     for (i = 0; i < soft_token.object.num_objs; i++) {
-       if (soft_token.object.objs == NULL) {
+       if (soft_token.object.objs[i] == NULL) {
            soft_token.object.objs[i] = o;
            break;
        }
@@ -342,6 +342,9 @@ add_object_attribute(struct st_object *o,
     struct st_attr *a;
     int i;
 
+    if (pValue == NULL && ulValueLen)
+        return CKR_ARGUMENTS_BAD;
+
     i = o->num_attributes;
     a = realloc(o->attrs, (i + 1) * sizeof(o->attrs[0]));
     if (a == NULL)
@@ -352,7 +355,8 @@ add_object_attribute(struct st_object *o,
     o->attrs[i].attribute.pValue = malloc(ulValueLen);
     if (o->attrs[i].attribute.pValue == NULL && ulValueLen != 0)
        return CKR_DEVICE_MEMORY;
-    memcpy(o->attrs[i].attribute.pValue, pValue, ulValueLen);
+    if (ulValueLen)
+        memcpy(o->attrs[i].attribute.pValue, pValue, ulValueLen);
     o->attrs[i].attribute.ulValueLen = ulValueLen;
     o->num_attributes++;
 
index 9338b141e171b0be02f188dabbd5664f4abf0a8b..6915175618e50aca8bee666c3cb75f8af0c59c04 100644 (file)
@@ -38,6 +38,10 @@ EXTRA_DIST = heim_ipc.defs heim_ipc_async.defs heim_ipc_reply.defs
 
 if have_gcd
 
+# We still use dispatch_get_current_queue(), which is deprecated, and that
+# stops building on recent OS X releases unless we disable this warning.
+WFLAGS += -Wno-deprecated-declarations
+
 heim_ipc.h heim_ipcUser.c heim_ipcServer.c heim_ipcServer.h: heim_ipc.defs
        mig -header heim_ipc.h -user heim_ipcUser.c -sheader heim_ipcServer.h -server heim_ipcServer.c -I$(srcdir) $(srcdir)/heim_ipc.defs
 
index 839a596388a55020f8b28df69492b81faaa1343d..40601b9744fad01ba5a725d3cd9180c44380fd91 100644 (file)
@@ -1014,15 +1014,12 @@ process_loop(void)
        for (n = 0 ; n < num_fds; n++) {
            if (clients[n] == NULL)
                continue;
-           if (fds[n].revents & POLLERR) {
-               clients[n]->flags |= WAITING_CLOSE;
-               continue;
-           }
-
            if (fds[n].revents & POLLIN)
                handle_read(clients[n]);
            if (fds[n].revents & POLLOUT)
                handle_write(clients[n]);
+           if (fds[n].revents & POLLERR)
+               clients[n]->flags |= WAITING_CLOSE;
        }
 
        n = 0;
@@ -1055,12 +1052,16 @@ heim_sipc_stream_listener(int fd, int type,
                          heim_ipc_callback callback,
                          void *user, heim_sipc *ctx)
 {
-    heim_sipc ct = calloc(1, sizeof(*ct));
+    heim_sipc ct;
     struct client *c;
 
     if ((type & HEIM_SIPC_TYPE_IPC) && (type & (HEIM_SIPC_TYPE_UINT32|HEIM_SIPC_TYPE_HTTP)))
        return EINVAL;
 
+    ct = calloc(1, sizeof(*ct));
+    if (ct == NULL)
+       return ENOMEM;
+
     switch (type) {
     case HEIM_SIPC_TYPE_IPC:
        c = add_new_socket(fd, LISTEN_SOCKET|WAITING_READ|INCLUDE_ERROR_CODE, callback, user);
@@ -1111,7 +1112,7 @@ heim_sipc_service_unix(const char *service,
 #ifdef LOCAL_CREDS
     {
        int one = 1;
-       setsockopt(fd, 0, LOCAL_CREDS, (void *)&one, sizeof(one));
+       (void) setsockopt(fd, 0, LOCAL_CREDS, (void *)&one, sizeof(one));
     }
 #endif
 
index 0b4ee656604e1ef836cb5da994abe02c2994e07b..58ccf32eacdde035c903a9b50c95bad2797cfc38 100644 (file)
@@ -1438,6 +1438,7 @@ kadm5_ad_init_with_password_ctx(krb5_context context,
        ret = ad_get_cred(ctx, NULL);
     if(ret) {
        kadm5_ad_destroy(ctx);
+       free(ctx);
        return ret;
     }
 
@@ -1445,6 +1446,7 @@ kadm5_ad_init_with_password_ctx(krb5_context context,
     ret = _kadm5_ad_connect(ctx);
     if (ret) {
        kadm5_ad_destroy(ctx);
+       free(ctx);
        return ret;
     }
 #endif
index e0d63d2ef42103f3451f8f42d3f123d2f626480d..c89448f4882ae2393b234c9ab276c4c9841256ff 100644 (file)
@@ -111,7 +111,7 @@ change(void *server_handle,
        int cond)
 {
     kadm5_server_context *context = server_handle;
-    hdb_entry_ex ent;
+    hdb_entry ent;
     kadm5_ret_t ret;
     Key *keys;
     size_t num_keys;
@@ -167,7 +167,7 @@ change(void *server_handle,
         * We save these for now so we can handle password history checking;
         * we handle keepold further below.
         */
-       ret = hdb_add_current_keys_to_history(context->context, &ent.entry);
+       ret = hdb_add_current_keys_to_history(context->context, &ent);
        if (ret)
            goto out3;
     }
@@ -179,13 +179,13 @@ change(void *server_handle,
            goto out3;
     } else {
 
-       num_keys = ent.entry.keys.len;
-       keys     = ent.entry.keys.val;
+       num_keys = ent.keys.len;
+       keys     = ent.keys.val;
 
-       ent.entry.keys.len = 0;
-       ent.entry.keys.val = NULL;
+       ent.keys.len = 0;
+       ent.keys.val = NULL;
 
-       ret = _kadm5_set_keys(context, &ent.entry, n_ks_tuple, ks_tuple,
+       ret = _kadm5_set_keys(context, &ent, n_ks_tuple, ks_tuple,
                              password);
        if(ret) {
            _kadm5_free_keys(context->context, num_keys, keys);
@@ -196,10 +196,10 @@ change(void *server_handle,
        if (cond) {
            HDB_extension *ext;
 
-           ext = hdb_find_extension(&ent.entry, choice_HDB_extension_data_hist_keys);
+           ext = hdb_find_extension(&ent, choice_HDB_extension_data_hist_keys);
            if (ext != NULL)
-               existsp = _kadm5_exists_keys_hist(ent.entry.keys.val,
-                                                 ent.entry.keys.len,
+               existsp = _kadm5_exists_keys_hist(ent.keys.val,
+                                                 ent.keys.len,
                                                  &ext->data.u.hist_keys);
        }
 
@@ -210,9 +210,9 @@ change(void *server_handle,
            goto out3;
        }
     }
-    ent.entry.kvno++;
+    ent.kvno++;
 
-    ent.entry.flags.require_pwchange = 0;
+    ent.flags.require_pwchange = 0;
 
     if (!keepold) {
        HDB_extension ext;
@@ -220,25 +220,25 @@ change(void *server_handle,
        memset(&ext, 0, sizeof (ext));
         ext.mandatory = FALSE;
        ext.data.element = choice_HDB_extension_data_hist_keys;
-       ret = hdb_replace_extension(context->context, &ent.entry, &ext);
+       ret = hdb_replace_extension(context->context, &ent, &ext);
        if (ret)
            goto out3;
     }
 
-    ret = hdb_seal_keys(context->context, context->db, &ent.entry);
+    ret = hdb_seal_keys(context->context, context->db, &ent);
     if (ret)
         goto out3;
 
-    ret = _kadm5_set_modifier(context, &ent.entry);
+    ret = _kadm5_set_modifier(context, &ent);
     if(ret)
        goto out3;
 
-    ret = _kadm5_bump_pw_expire(context, &ent.entry);
+    ret = _kadm5_bump_pw_expire(context, &ent);
     if (ret)
        goto out3;
 
     /* This logs the change for iprop and writes to the HDB */
-    ret = kadm5_log_modify(context, &ent.entry,
+    ret = kadm5_log_modify(context, &ent,
                            KADM5_ATTRIBUTES | KADM5_PRINCIPAL |
                            KADM5_MOD_NAME | KADM5_MOD_TIME |
                            KADM5_KEY_DATA | KADM5_KVNO |
@@ -249,7 +249,7 @@ change(void *server_handle,
                                 n_ks_tuple, ks_tuple, password);
 
  out3:
-    hdb_free_entry(context->context, &ent);
+    hdb_free_entry(context->context, context->db, &ent);
  out2:
     (void) kadm5_log_end(context);
  out:
@@ -367,7 +367,7 @@ kadm5_s_chpass_principal_with_key(void *server_handle,
                                  krb5_key_data *key_data)
 {
     kadm5_server_context *context = server_handle;
-    hdb_entry_ex ent;
+    hdb_entry ent;
     kadm5_ret_t ret;
     uint32_t hook_flags = 0;
 
@@ -396,23 +396,23 @@ kadm5_s_chpass_principal_with_key(void *server_handle,
        goto out3;
 
     if (keepold) {
-       ret = hdb_add_current_keys_to_history(context->context, &ent.entry);
+       ret = hdb_add_current_keys_to_history(context->context, &ent);
        if (ret)
            goto out3;
     }
-    ret = _kadm5_set_keys2(context, &ent.entry, n_key_data, key_data);
+    ret = _kadm5_set_keys2(context, &ent, n_key_data, key_data);
     if (ret)
        goto out3;
-    ent.entry.kvno++;
-    ret = _kadm5_set_modifier(context, &ent.entry);
+    ent.kvno++;
+    ret = _kadm5_set_modifier(context, &ent);
     if (ret)
        goto out3;
-    ret = _kadm5_bump_pw_expire(context, &ent.entry);
+    ret = _kadm5_bump_pw_expire(context, &ent);
     if (ret)
        goto out3;
 
     if (keepold) {
-       ret = hdb_seal_keys(context->context, context->db, &ent.entry);
+       ret = hdb_seal_keys(context->context, context->db, &ent);
        if (ret)
            goto out3;
     } else {
@@ -423,11 +423,11 @@ kadm5_s_chpass_principal_with_key(void *server_handle,
        ext.data.element = choice_HDB_extension_data_hist_keys;
        ext.data.u.hist_keys.len = 0;
        ext.data.u.hist_keys.val = NULL;
-       hdb_replace_extension(context->context, &ent.entry, &ext);
+       hdb_replace_extension(context->context, &ent, &ext);
     }
 
     /* This logs the change for iprop and writes to the HDB */
-    ret = kadm5_log_modify(context, &ent.entry,
+    ret = kadm5_log_modify(context, &ent,
                            KADM5_PRINCIPAL | KADM5_MOD_NAME |
                            KADM5_MOD_TIME | KADM5_KEY_DATA | KADM5_KVNO |
                            KADM5_PW_EXPIRATION | KADM5_TL_DATA);
@@ -437,7 +437,7 @@ kadm5_s_chpass_principal_with_key(void *server_handle,
                                          n_key_data, key_data);
 
  out3:
-    hdb_free_entry(context->context, &ent);
+    hdb_free_entry(context->context, context->db, &ent);
  out2:
     (void) kadm5_log_end(context);
  out:
index b5674f19ab6eaccbe1288bd465e8df9b20fb4ca6..0c154ecfef08e92aae4c24f8f3b3279f3213a14c 100644 (file)
@@ -161,29 +161,37 @@ find_db_spec(kadm5_server_context *ctx)
            p = hdb_dbinfo_get_dbname(context, d);
            if (p) {
                ctx->config.dbname = strdup(p);
-                if (ctx->config.dbname == NULL)
+                if (ctx->config.dbname == NULL) {
+                   hdb_free_dbinfo(context, &info);
                    return krb5_enomem(context);
+               }
             }
 
            p = hdb_dbinfo_get_acl_file(context, d);
            if (p) {
                ctx->config.acl_file = strdup(p);
-                if (ctx->config.acl_file == NULL)
+                if (ctx->config.acl_file == NULL) {
+                   hdb_free_dbinfo(context, &info);
                    return krb5_enomem(context);
+               }
             }
 
            p = hdb_dbinfo_get_mkey_file(context, d);
            if (p) {
                ctx->config.stash_file = strdup(p);
-                if (ctx->config.stash_file == NULL)
+                if (ctx->config.stash_file == NULL) {
+                   hdb_free_dbinfo(context, &info);
                    return krb5_enomem(context);
+               }
             }
 
            p = hdb_dbinfo_get_log_file(context, d);
            if (p) {
                ctx->log_context.log_file = strdup(p);
-                if (ctx->log_context.log_file == NULL)
+                if (ctx->log_context.log_file == NULL) {
+                   hdb_free_dbinfo(context, &info);
                    return krb5_enomem(context);
+               }
             }
            break;
        }
index 42125e28a7e09455a80478ae4ef3e4f015236c00..1c2ab15f30dbab5917857ca5143d8b8ffe86815b 100644 (file)
@@ -57,7 +57,7 @@ static kadm5_ret_t
 create_principal(kadm5_server_context *context,
                 kadm5_principal_ent_t princ,
                 uint32_t mask,
-                hdb_entry_ex *ent,
+                hdb_entry *ent,
                 uint32_t required_mask,
                 uint32_t forbidden_mask)
 {
@@ -74,7 +74,7 @@ create_principal(kadm5_server_context *context,
        /* XXX no real policies for now */
        return KADM5_UNK_POLICY;
     ret  = krb5_copy_principal(context->context, princ->principal,
-                              &ent->entry.principal);
+                              &ent->principal);
     if(ret)
        return ret;
 
@@ -96,10 +96,10 @@ create_principal(kadm5_server_context *context,
     if (ret)
        return ret;
 
-    ent->entry.created_by.time = time(NULL);
+    ent->created_by.time = time(NULL);
 
     return krb5_copy_principal(context->context, context->caller,
-                              &ent->entry.created_by.principal);
+                              &ent->created_by.principal);
 }
 
 struct create_principal_hook_ctx {
@@ -167,7 +167,7 @@ kadm5_s_create_principal_with_key(void *server_handle,
                                  uint32_t mask)
 {
     kadm5_ret_t ret;
-    hdb_entry_ex ent;
+    hdb_entry ent;
     kadm5_server_context *context = server_handle;
 
     if ((mask & KADM5_KVNO) == 0) {
@@ -194,7 +194,7 @@ kadm5_s_create_principal_with_key(void *server_handle,
     if (!context->keep_open) {
         ret = context->db->hdb_open(context->context, context->db, O_RDWR, 0);
         if (ret) {
-            hdb_free_entry(context->context, &ent);
+            hdb_free_entry(context->context, context->db, &ent);
             return ret;
         }
     }
@@ -203,7 +203,7 @@ kadm5_s_create_principal_with_key(void *server_handle,
     if (ret)
         goto out;
 
-    ret = hdb_seal_keys(context->context, context->db, &ent.entry);
+    ret = hdb_seal_keys(context->context, context->db, &ent);
     if (ret)
        goto out2;
 
@@ -213,7 +213,7 @@ kadm5_s_create_principal_with_key(void *server_handle,
      * Creation of would-be virtual principals w/o the materialize flag will be
      * rejected in kadm5_log_create().
      */
-    ret = kadm5_log_create(context, &ent.entry);
+    ret = kadm5_log_create(context, &ent);
 
     (void) create_principal_hook(context, KADM5_HOOK_STAGE_POSTCOMMIT,
                                 ret, princ, mask, NULL);
@@ -227,7 +227,7 @@ kadm5_s_create_principal_with_key(void *server_handle,
         if (ret == 0 && ret2 != 0)
             ret = ret2;
     }
-    hdb_free_entry(context->context, &ent);
+    hdb_free_entry(context->context, context->db, &ent);
     return _kadm5_error_code(ret);
 }
 
@@ -241,7 +241,7 @@ kadm5_s_create_principal(void *server_handle,
                         const char *password)
 {
     kadm5_ret_t ret;
-    hdb_entry_ex ent;
+    hdb_entry ent;
     kadm5_server_context *context = server_handle;
     int use_pw = 1;
 
@@ -315,7 +315,7 @@ kadm5_s_create_principal(void *server_handle,
     if (!context->keep_open) {
         ret = context->db->hdb_open(context->context, context->db, O_RDWR, 0);
         if (ret) {
-            hdb_free_entry(context->context, &ent);
+            hdb_free_entry(context->context, context->db, &ent);
             return ret;
         }
     }
@@ -324,20 +324,20 @@ kadm5_s_create_principal(void *server_handle,
     if (ret)
         goto out;
 
-    free_Keys(&ent.entry.keys);
+    free_Keys(&ent.keys);
 
     if (use_pw) {
-        ret = _kadm5_set_keys(context, &ent.entry, n_ks_tuple, ks_tuple, password);
+        ret = _kadm5_set_keys(context, &ent, n_ks_tuple, ks_tuple, password);
         if (ret)
             goto out2;
     }
 
-    ret = hdb_seal_keys(context->context, context->db, &ent.entry);
+    ret = hdb_seal_keys(context->context, context->db, &ent);
     if (ret)
        goto out2;
 
     /* This logs the change for iprop and writes to the HDB */
-    ret = kadm5_log_create(context, &ent.entry);
+    ret = kadm5_log_create(context, &ent);
 
     (void) create_principal_hook(context, KADM5_HOOK_STAGE_POSTCOMMIT,
                                 ret, princ, mask, password);
@@ -351,7 +351,7 @@ kadm5_s_create_principal(void *server_handle,
         if (ret == 0 && ret2 != 0)
             ret = ret2;
     }
-    hdb_free_entry(context->context, &ent);
+    hdb_free_entry(context->context, context->db, &ent);
     return _kadm5_error_code(ret);
 }
 
index 6942148dbb534807c660f41d7b6005af283b617a..aa9fdb4fc0a2ce0e6cd7ce7d34d890b07e6d7ab2 100644 (file)
@@ -92,7 +92,7 @@ kadm5_s_delete_principal(void *server_handle, krb5_principal princ)
 {
     kadm5_server_context *context = server_handle;
     kadm5_ret_t ret;
-    hdb_entry_ex ent;
+    hdb_entry ent;
 
     memset(&ent, 0, sizeof(ent));
     if (!context->keep_open) {
@@ -112,7 +112,7 @@ kadm5_s_delete_principal(void *server_handle, krb5_principal princ)
                                       0, &ent);
     if (ret == HDB_ERR_NOENTRY)
        goto out2;
-    if (ent.entry.flags.immutable) {
+    if (ent.flags.immutable) {
        ret = KADM5_PROTECT_PRINCIPAL;
        goto out3;
     }
@@ -121,7 +121,7 @@ kadm5_s_delete_principal(void *server_handle, krb5_principal princ)
     if (ret)
        goto out3;
 
-    ret = hdb_seal_keys(context->context, context->db, &ent.entry);
+    ret = hdb_seal_keys(context->context, context->db, &ent);
     if (ret)
        goto out3;
 
@@ -131,7 +131,7 @@ kadm5_s_delete_principal(void *server_handle, krb5_principal princ)
     (void) delete_principal_hook(context, KADM5_HOOK_STAGE_POSTCOMMIT, ret, princ);
 
  out3:
-    hdb_free_entry(context->context, &ent);
+    hdb_free_entry(context->context, context->db, &ent);
  out2:
     (void) kadm5_log_end(context);
  out:
index 677bda6d897362e30518afd2609d955de184d2b3..24a7983b6e1ffb48249c10cf658f840293f78a23 100644 (file)
@@ -73,7 +73,7 @@ attr_to_flags(unsigned attr, HDBFlags *flags)
 static kadm5_ret_t
 perform_tl_data(krb5_context context,
                HDB *db,
-               hdb_entry_ex *ent,
+               hdb_entry *ent,
                const krb5_tl_data *tl_data)
 {
     kadm5_ret_t ret = 0;
@@ -84,7 +84,7 @@ perform_tl_data(krb5_context context,
        if (pw[tl_data->tl_data_length] != '\0')
            return KADM5_BAD_TL_TYPE;
 
-       ret = hdb_entry_set_password(context, db, &ent->entry, pw);
+       ret = hdb_entry_set_password(context, db, ent, pw);
 
     } else if (tl_data->tl_data_type == KRB5_TL_LAST_PWD_CHANGE) {
         unsigned long t;
@@ -96,7 +96,7 @@ perform_tl_data(krb5_context context,
        s = tl_data->tl_data_contents;
 
         (void) _krb5_get_int(s, &t, tl_data->tl_data_length);
-        ret = hdb_entry_set_pw_change_time(context, &ent->entry, t);
+        ret = hdb_entry_set_pw_change_time(context, ent, t);
 
     } else if (tl_data->tl_data_type == KRB5_TL_KEY_ROTATION) {
         HDB_Ext_KeyRotation *prev_kr = 0;
@@ -105,7 +105,7 @@ perform_tl_data(krb5_context context,
 
         ext.mandatory = 0;
         ext.data.element = choice_HDB_extension_data_key_rotation;
-        prev_ext = hdb_find_extension(&ent->entry, ext.data.element);
+        prev_ext = hdb_find_extension(ent, ext.data.element);
         if (prev_ext)
             prev_kr = &prev_ext->data.u.key_rotation;
         ret = decode_HDB_Ext_KeyRotation(tl_data->tl_data_contents,
@@ -115,7 +115,7 @@ perform_tl_data(krb5_context context,
             ret = hdb_validate_key_rotations(context, prev_kr,
                                              &ext.data.u.key_rotation);
         if (ret == 0)
-            ret = hdb_replace_extension(context, &ent->entry, &ext);
+            ret = hdb_replace_extension(context, ent, &ext);
        free_HDB_extension(&ext);
     } else if (tl_data->tl_data_type == KRB5_TL_EXTENSION) {
        HDB_extension ext;
@@ -128,7 +128,7 @@ perform_tl_data(krb5_context context,
            return KADM5_BAD_TL_TYPE;
 
         if (ext.data.element == choice_HDB_extension_data_key_rotation) {
-            HDB_extension *prev_ext = hdb_find_extension(&ent->entry,
+            HDB_extension *prev_ext = hdb_find_extension(ent,
                                                          ext.data.element);
             HDB_Ext_KeyRotation *prev_kr = 0;
 
@@ -140,19 +140,19 @@ perform_tl_data(krb5_context context,
        if (ret)
            ret = KADM5_BAD_TL_TYPE; /* XXX Need new error code */
         if (ret == 0)
-            ret = hdb_replace_extension(context, &ent->entry, &ext);
+            ret = hdb_replace_extension(context, ent, &ext);
        free_HDB_extension(&ext);
     } else if (tl_data->tl_data_type == KRB5_TL_ETYPES) {
-        if (!ent->entry.etypes &&
-            (ent->entry.etypes = calloc(1,
-                                        sizeof(ent->entry.etypes[0]))) == NULL)
+        if (!ent->etypes &&
+            (ent->etypes = calloc(1,
+                                        sizeof(ent->etypes[0]))) == NULL)
             ret = krb5_enomem(context);
-        if (ent->entry.etypes)
-            free_HDB_EncTypeList(ent->entry.etypes);
+        if (ent->etypes)
+            free_HDB_EncTypeList(ent->etypes);
         if (ret == 0)
             ret = decode_HDB_EncTypeList(tl_data->tl_data_contents,
                                          tl_data->tl_data_length,
-                                         ent->entry.etypes, NULL);
+                                         ent->etypes, NULL);
        if (ret)
            return KADM5_BAD_TL_TYPE;
     } else if (tl_data->tl_data_type == KRB5_TL_ALIASES) {
@@ -164,14 +164,14 @@ perform_tl_data(krb5_context context,
 }
 
 static void
-default_flags(hdb_entry_ex *ent)
+default_flags(hdb_entry *ent)
 {
-    ent->entry.flags.client      = 1;
-    ent->entry.flags.server      = 1;
-    ent->entry.flags.forwardable = 1;
-    ent->entry.flags.proxiable   = 1;
-    ent->entry.flags.renewable   = 1;
-    ent->entry.flags.postdate    = 1;
+    ent->flags.client      = 1;
+    ent->flags.server      = 1;
+    ent->flags.forwardable = 1;
+    ent->flags.proxiable   = 1;
+    ent->flags.renewable   = 1;
+    ent->flags.postdate    = 1;
 }
 
 
@@ -183,7 +183,7 @@ default_flags(hdb_entry_ex *ent)
 
 kadm5_ret_t
 _kadm5_setup_entry(kadm5_server_context *context,
-                  hdb_entry_ex *ent,
+                  hdb_entry *ent,
                   uint32_t mask,
                   kadm5_principal_ent_t princ,
                   uint32_t princ_mask,
@@ -193,23 +193,23 @@ _kadm5_setup_entry(kadm5_server_context *context,
     if(mask & KADM5_PRINC_EXPIRE_TIME
        && princ_mask & KADM5_PRINC_EXPIRE_TIME) {
        if (princ->princ_expire_time)
-           set_value(ent->entry.valid_end, princ->princ_expire_time);
+           set_value(ent->valid_end, princ->princ_expire_time);
        else
-           set_null(ent->entry.valid_end);
+           set_null(ent->valid_end);
     }
     if(mask & KADM5_PW_EXPIRATION
        && princ_mask & KADM5_PW_EXPIRATION) {
        if (princ->pw_expiration)
-           set_value(ent->entry.pw_end, princ->pw_expiration);
+           set_value(ent->pw_end, princ->pw_expiration);
        else
-           set_null(ent->entry.pw_end);
+           set_null(ent->pw_end);
     }
     if(mask & KADM5_ATTRIBUTES) {
        if (princ_mask & KADM5_ATTRIBUTES) {
-           attr_to_flags(princ->attributes, &ent->entry.flags);
+           attr_to_flags(princ->attributes, &ent->flags);
        } else if(def_mask & KADM5_ATTRIBUTES) {
-           attr_to_flags(def->attributes, &ent->entry.flags);
-           ent->entry.flags.invalid = 0;
+           attr_to_flags(def->attributes, &ent->flags);
+           ent->flags.invalid = 0;
        } else {
            default_flags(ent);
        }
@@ -218,41 +218,41 @@ _kadm5_setup_entry(kadm5_server_context *context,
     if(mask & KADM5_MAX_LIFE) {
        if(princ_mask & KADM5_MAX_LIFE) {
            if(princ->max_life)
-             set_value(ent->entry.max_life, princ->max_life);
+             set_value(ent->max_life, princ->max_life);
            else
-             set_null(ent->entry.max_life);
+             set_null(ent->max_life);
        } else if(def_mask & KADM5_MAX_LIFE) {
            if(def->max_life)
-             set_value(ent->entry.max_life, def->max_life);
+             set_value(ent->max_life, def->max_life);
            else
-             set_null(ent->entry.max_life);
+             set_null(ent->max_life);
        }
     }
     if(mask & KADM5_KVNO
        && (princ_mask & KADM5_KVNO)) {
        krb5_error_code ret;
 
-       ret = hdb_change_kvno(context->context, princ->kvno, &ent->entry);
+       ret = hdb_change_kvno(context->context, princ->kvno, ent);
        if (ret && ret != HDB_ERR_KVNO_NOT_FOUND)
            return ret;
-       ent->entry.kvno = princ->kvno; /* force it */
+       ent->kvno = princ->kvno; /* force it */
     }
     if(mask & KADM5_MAX_RLIFE) {
        if(princ_mask & KADM5_MAX_RLIFE) {
          if(princ->max_renewable_life)
-           set_value(ent->entry.max_renew, princ->max_renewable_life);
+           set_value(ent->max_renew, princ->max_renewable_life);
          else
-           set_null(ent->entry.max_renew);
+           set_null(ent->max_renew);
        } else if(def_mask & KADM5_MAX_RLIFE) {
          if(def->max_renewable_life)
-           set_value(ent->entry.max_renew, def->max_renewable_life);
+           set_value(ent->max_renew, def->max_renewable_life);
          else
-           set_null(ent->entry.max_renew);
+           set_null(ent->max_renew);
        }
     }
     if(mask & KADM5_KEY_DATA
        && princ_mask & KADM5_KEY_DATA) {
-       _kadm5_set_keys2(context, &ent->entry,
+       _kadm5_set_keys2(context, ent,
                         princ->n_key_data, princ->key_data);
     }
     if(mask & KADM5_TL_DATA) {
index f7182d7ec88d4b5542ee5c327d91a411965fa027..27fac2bbb0bce38969d2c34b99a7ebe0664fc99c 100644 (file)
@@ -55,12 +55,12 @@ add_princ(krb5_context context, struct foreach_data *d, char *princ)
 }
 
 static krb5_error_code
-foreach(krb5_context context, HDB *db, hdb_entry_ex *ent, void *data)
+foreach(krb5_context context, HDB *db, hdb_entry *ent, void *data)
 {
     struct foreach_data *d = data;
     char *princ;
     krb5_error_code ret;
-    ret = krb5_unparse_name(context, ent->entry.principal, &princ);
+    ret = krb5_unparse_name(context, ent->principal, &princ);
     if(ret)
        return ret;
     if(d->exp){
@@ -98,7 +98,9 @@ kadm5_s_get_principals(void *server_handle,
        krb5_realm r;
        int aret;
 
-       krb5_get_default_realm(context->context, &r);
+       ret = krb5_get_default_realm(context->context, &r);
+        if (ret)
+            goto out;
        aret = asprintf(&d.exp2, "%s@%s", expression, r);
        free(r);
        if (aret == -1 || d.exp2 == NULL) {
index 56aec67a223161ca331e1c609acb15405f10bb64..0c87343d2e1724eccbe7ae15dae39ff60dfa8f03 100644 (file)
@@ -122,7 +122,7 @@ kadm5_s_get_principal(void *server_handle,
 {
     kadm5_server_context *context = server_handle;
     kadm5_ret_t ret;
-    hdb_entry_ex ent;
+    hdb_entry ent;
     unsigned int flags = HDB_F_GET_ANY | HDB_F_ADMIN_DATA;
 
     if ((mask & KADM5_KEY_DATA) || (mask & KADM5_KVNO))
@@ -157,57 +157,57 @@ kadm5_s_get_principal(void *server_handle,
        return _kadm5_error_code(ret);
 
     if(mask & KADM5_PRINCIPAL)
-       ret  = krb5_copy_principal(context->context, ent.entry.principal,
+       ret  = krb5_copy_principal(context->context, ent.principal,
                                   &out->principal);
     if(ret)
        goto out;
-    if(mask & KADM5_PRINC_EXPIRE_TIME && ent.entry.valid_end)
-       out->princ_expire_time = *ent.entry.valid_end;
-    if(mask & KADM5_PW_EXPIRATION && ent.entry.pw_end)
-       out->pw_expiration = *ent.entry.pw_end;
+    if(mask & KADM5_PRINC_EXPIRE_TIME && ent.valid_end)
+       out->princ_expire_time = *ent.valid_end;
+    if(mask & KADM5_PW_EXPIRATION && ent.pw_end)
+       out->pw_expiration = *ent.pw_end;
     if(mask & KADM5_LAST_PWD_CHANGE)
-       hdb_entry_get_pw_change_time(&ent.entry, &out->last_pwd_change);
+       hdb_entry_get_pw_change_time(&ent, &out->last_pwd_change);
     if(mask & KADM5_ATTRIBUTES){
-       out->attributes |= ent.entry.flags.postdate ? 0 : KRB5_KDB_DISALLOW_POSTDATED;
-       out->attributes |= ent.entry.flags.forwardable ? 0 : KRB5_KDB_DISALLOW_FORWARDABLE;
-       out->attributes |= ent.entry.flags.initial ? KRB5_KDB_DISALLOW_TGT_BASED : 0;
-       out->attributes |= ent.entry.flags.renewable ? 0 : KRB5_KDB_DISALLOW_RENEWABLE;
-       out->attributes |= ent.entry.flags.proxiable ? 0 : KRB5_KDB_DISALLOW_PROXIABLE;
-       out->attributes |= ent.entry.flags.invalid ? KRB5_KDB_DISALLOW_ALL_TIX : 0;
-       out->attributes |= ent.entry.flags.require_preauth ? KRB5_KDB_REQUIRES_PRE_AUTH : 0;
-       out->attributes |= ent.entry.flags.require_pwchange ? KRB5_KDB_REQUIRES_PWCHANGE : 0;
-       out->attributes |= ent.entry.flags.client ? 0 : KRB5_KDB_DISALLOW_CLIENT;
-       out->attributes |= ent.entry.flags.server ? 0 : KRB5_KDB_DISALLOW_SVR;
-       out->attributes |= ent.entry.flags.change_pw ? KRB5_KDB_PWCHANGE_SERVICE : 0;
-       out->attributes |= ent.entry.flags.ok_as_delegate ? KRB5_KDB_OK_AS_DELEGATE : 0;
-       out->attributes |= ent.entry.flags.trusted_for_delegation ? KRB5_KDB_TRUSTED_FOR_DELEGATION : 0;
-       out->attributes |= ent.entry.flags.allow_kerberos4 ? KRB5_KDB_ALLOW_KERBEROS4 : 0;
-       out->attributes |= ent.entry.flags.allow_digest ? KRB5_KDB_ALLOW_DIGEST : 0;
-       out->attributes |= ent.entry.flags.virtual_keys ? KRB5_KDB_VIRTUAL_KEYS : 0;
-       out->attributes |= ent.entry.flags.virtual ? KRB5_KDB_VIRTUAL : 0;
-       out->attributes |= ent.entry.flags.no_auth_data_reqd ? KRB5_KDB_NO_AUTH_DATA_REQUIRED : 0;
+       out->attributes |= ent.flags.postdate ? 0 : KRB5_KDB_DISALLOW_POSTDATED;
+       out->attributes |= ent.flags.forwardable ? 0 : KRB5_KDB_DISALLOW_FORWARDABLE;
+       out->attributes |= ent.flags.initial ? KRB5_KDB_DISALLOW_TGT_BASED : 0;
+       out->attributes |= ent.flags.renewable ? 0 : KRB5_KDB_DISALLOW_RENEWABLE;
+       out->attributes |= ent.flags.proxiable ? 0 : KRB5_KDB_DISALLOW_PROXIABLE;
+       out->attributes |= ent.flags.invalid ? KRB5_KDB_DISALLOW_ALL_TIX : 0;
+       out->attributes |= ent.flags.require_preauth ? KRB5_KDB_REQUIRES_PRE_AUTH : 0;
+       out->attributes |= ent.flags.require_pwchange ? KRB5_KDB_REQUIRES_PWCHANGE : 0;
+       out->attributes |= ent.flags.client ? 0 : KRB5_KDB_DISALLOW_CLIENT;
+       out->attributes |= ent.flags.server ? 0 : KRB5_KDB_DISALLOW_SVR;
+       out->attributes |= ent.flags.change_pw ? KRB5_KDB_PWCHANGE_SERVICE : 0;
+       out->attributes |= ent.flags.ok_as_delegate ? KRB5_KDB_OK_AS_DELEGATE : 0;
+       out->attributes |= ent.flags.trusted_for_delegation ? KRB5_KDB_TRUSTED_FOR_DELEGATION : 0;
+       out->attributes |= ent.flags.allow_kerberos4 ? KRB5_KDB_ALLOW_KERBEROS4 : 0;
+       out->attributes |= ent.flags.allow_digest ? KRB5_KDB_ALLOW_DIGEST : 0;
+       out->attributes |= ent.flags.virtual_keys ? KRB5_KDB_VIRTUAL_KEYS : 0;
+       out->attributes |= ent.flags.virtual ? KRB5_KDB_VIRTUAL : 0;
+       out->attributes |= ent.flags.no_auth_data_reqd ? KRB5_KDB_NO_AUTH_DATA_REQUIRED : 0;
     }
     if(mask & KADM5_MAX_LIFE) {
-       if(ent.entry.max_life)
-           out->max_life = *ent.entry.max_life;
+       if(ent.max_life)
+           out->max_life = *ent.max_life;
        else
            out->max_life = INT_MAX;
     }
     if(mask & KADM5_MOD_TIME) {
-       if(ent.entry.modified_by)
-           out->mod_date = ent.entry.modified_by->time;
+       if(ent.modified_by)
+           out->mod_date = ent.modified_by->time;
        else
-           out->mod_date = ent.entry.created_by.time;
+           out->mod_date = ent.created_by.time;
     }
     if(mask & KADM5_MOD_NAME) {
-       if(ent.entry.modified_by) {
-           if (ent.entry.modified_by->principal != NULL)
+       if(ent.modified_by) {
+           if (ent.modified_by->principal != NULL)
                ret = krb5_copy_principal(context->context,
-                                         ent.entry.modified_by->principal,
+                                         ent.modified_by->principal,
                                          &out->mod_name);
-       } else if(ent.entry.created_by.principal != NULL)
+       } else if(ent.created_by.principal != NULL)
            ret = krb5_copy_principal(context->context,
-                                     ent.entry.created_by.principal,
+                                     ent.created_by.principal,
                                      &out->mod_name);
        else
            out->mod_name = NULL;
@@ -216,13 +216,13 @@ kadm5_s_get_principal(void *server_handle,
        goto out;
 
     if(mask & KADM5_KVNO)
-       out->kvno = ent.entry.kvno;
+       out->kvno = ent.kvno;
     if(mask & KADM5_MKVNO) {
        size_t n;
        out->mkvno = 0; /* XXX */
-       for(n = 0; n < ent.entry.keys.len; n++)
-           if(ent.entry.keys.val[n].mkvno) {
-               out->mkvno = *ent.entry.keys.val[n].mkvno; /* XXX this isn't right */
+       for(n = 0; n < ent.keys.len; n++)
+           if(ent.keys.val[n].mkvno) {
+               out->mkvno = *ent.keys.val[n].mkvno; /* XXX this isn't right */
                break;
            }
     }
@@ -239,7 +239,7 @@ kadm5_s_get_principal(void *server_handle,
     if(mask & KADM5_POLICY) {
        HDB_extension *ext;
 
-       ext = hdb_find_extension(&ent.entry, choice_HDB_extension_data_policy);
+       ext = hdb_find_extension(&ent, choice_HDB_extension_data_policy);
        if (ext == NULL) {
            out->policy = strdup("default");
            /* It's OK if we retun NULL instead of "default" */
@@ -252,27 +252,27 @@ kadm5_s_get_principal(void *server_handle,
        }
     }
     if(mask & KADM5_MAX_RLIFE) {
-       if(ent.entry.max_renew)
-           out->max_renewable_life = *ent.entry.max_renew;
+       if(ent.max_renew)
+           out->max_renewable_life = *ent.max_renew;
        else
            out->max_renewable_life = INT_MAX;
     }
     if(mask & KADM5_KEY_DATA){
        size_t i;
-       size_t n_keys = ent.entry.keys.len;
+       size_t n_keys = ent.keys.len;
        krb5_salt salt;
        HDB_extension *ext;
        HDB_Ext_KeySet *hist_keys = NULL;
 
        /* Don't return stale keys to kadm5 clients */
-       ret = hdb_prune_keys(context->context, &ent.entry);
+       ret = hdb_prune_keys(context->context, &ent);
        if (ret)
            goto out;
-       ext = hdb_find_extension(&ent.entry, choice_HDB_extension_data_hist_keys);
+       ext = hdb_find_extension(&ent, choice_HDB_extension_data_hist_keys);
        if (ext != NULL)
            hist_keys = &ext->data.u.hist_keys;
 
-       krb5_get_pw_salt(context->context, ent.entry.principal, &salt);
+       krb5_get_pw_salt(context->context, ent.principal, &salt);
        for (i = 0; hist_keys != NULL && i < hist_keys->len; i++)
            n_keys += hist_keys->val[i].keys.len;
        out->key_data = malloc(n_keys * sizeof(*out->key_data));
@@ -281,8 +281,8 @@ kadm5_s_get_principal(void *server_handle,
            goto out;
        }
        out->n_key_data = 0;
-       ret = copy_keyset_to_kadm5(context, ent.entry.kvno, ent.entry.keys.len,
-                                  ent.entry.keys.val, &salt, out);
+       ret = copy_keyset_to_kadm5(context, ent.kvno, ent.keys.len,
+                                  ent.keys.val, &salt, out);
        if (ret)
            goto out;
        for (i = 0; hist_keys != NULL && i < hist_keys->len; i++) {
@@ -296,8 +296,7 @@ kadm5_s_get_principal(void *server_handle,
        krb5_free_salt(context->context, salt);
        assert( out->n_key_data == n_keys );
     }
-    if (ret)
-       goto out;
+    assert(ret == 0);
     if(mask & KADM5_TL_DATA) {
        time_t last_pw_expire;
        const HDB_Ext_PKINIT_acl *acl;
@@ -305,12 +304,12 @@ kadm5_s_get_principal(void *server_handle,
         const HDB_Ext_KeyRotation *kr;
         heim_octet_string krb5_config;
 
-        if (ent.entry.etypes) {
+        if (ent.etypes) {
             krb5_data buf;
             size_t len;
 
             ASN1_MALLOC_ENCODE(HDB_EncTypeList, buf.data, buf.length,
-                               ent.entry.etypes, &len, ret);
+                               ent.etypes, &len, ret);
             if (ret == 0) {
                 ret = add_tl_data(out, KRB5_TL_ETYPES, buf.data, buf.length);
                 free(buf.data);
@@ -319,20 +318,22 @@ kadm5_s_get_principal(void *server_handle,
                 goto out;
         }
 
-       ret = hdb_entry_get_pw_change_time(&ent.entry, &last_pw_expire);
+       ret = hdb_entry_get_pw_change_time(&ent, &last_pw_expire);
        if (ret == 0 && last_pw_expire) {
            unsigned char buf[4];
            _krb5_put_int(buf, last_pw_expire, sizeof(buf));
            ret = add_tl_data(out, KRB5_TL_LAST_PWD_CHANGE, buf, sizeof(buf));
+            if (ret)
+                goto out;
        }
-        if (ret == 0)
-            ret = hdb_entry_get_krb5_config(&ent.entry, &krb5_config);
+
+        ret = hdb_entry_get_krb5_config(&ent, &krb5_config);
         if (ret == 0 && krb5_config.length) {
             ret = add_tl_data(out, KRB5_TL_KRB5_CONFIG, krb5_config.data,
                               krb5_config.length);
+            if (ret)
+                goto out;
         }
-       if (ret)
-           goto out;
        /*
         * If the client was allowed to get key data, let it have the
         * password too.
@@ -342,15 +343,17 @@ kadm5_s_get_principal(void *server_handle,
 
             /* XXX But not if the client doesn't have ext-keys */
            ret = hdb_entry_get_password(context->context,
-                                        context->db, &ent.entry, &pw);
+                                        context->db, &ent, &pw);
            if (ret == 0) {
                ret = add_tl_data(out, KRB5_TL_PASSWORD, pw, strlen(pw) + 1);
                free(pw);
+                if (ret)
+                    goto out;
            }
            krb5_clear_error_message(context->context);
        }
 
-       ret = hdb_entry_get_pkinit_acl(&ent.entry, &acl);
+        ret = hdb_entry_get_pkinit_acl(&ent, &acl);
        if (ret == 0 && acl) {
            krb5_data buf;
            size_t len;
@@ -367,10 +370,8 @@ kadm5_s_get_principal(void *server_handle,
            if (ret)
                goto out;
        }
-       if (ret)
-           goto out;
 
-       ret = hdb_entry_get_aliases(&ent.entry, &aliases);
+        ret = hdb_entry_get_aliases(&ent, &aliases);
        if (ret == 0 && aliases) {
            krb5_data buf;
            size_t len;
@@ -387,34 +388,24 @@ kadm5_s_get_principal(void *server_handle,
            if (ret)
                goto out;
        }
-       if (ret)
-           goto out;
 
-        ret = hdb_entry_get_key_rotation(context->context, &ent.entry, &kr);
+        ret = hdb_entry_get_key_rotation(context->context, &ent, &kr);
        if (ret == 0 && kr) {
            krb5_data buf;
            size_t len;
 
            ASN1_MALLOC_ENCODE(HDB_Ext_KeyRotation, buf.data, buf.length,
                               kr, &len, ret);
-           if (ret)
-               goto out;
-           if (len != buf.length)
-               krb5_abortx(context->context,
-                           "internal ASN.1 encoder error");
-           ret = add_tl_data(out, KRB5_TL_KEY_ROTATION, buf.data, buf.length);
+            if (ret == 0)
+                ret = add_tl_data(out, KRB5_TL_KEY_ROTATION, buf.data, buf.length);
            free(buf.data);
-           if (ret)
-               goto out;
        }
-       if (ret)
-           goto out;
     }
 
  out:
     if (ret)
         kadm5_free_principal_ent(context, out);
-    hdb_free_entry(context->context, &ent);
+    hdb_free_entry(context->context, context->db, &ent);
 
     return _kadm5_error_code(ret);
 }
index a0a3443898a5fd732f4a3e784d9fe4bfb1e80fcc..5d585d1a29514f725e83ec50b642f92bb1748ea4 100644 (file)
@@ -427,12 +427,15 @@ _kadm5_c_get_cred_cache(krb5_context context,
                 user = roken_get_username(userbuf, sizeof(userbuf));
            if (user == NULL) {
                krb5_set_error_message(context, KADM5_FAILURE, "Unable to find local user name");
+               krb5_free_principal(context, client);
                return KADM5_FAILURE;
            }
            ret = krb5_make_principal(context, &default_client,
                                      NULL, user, "admin", NULL);
-           if(ret)
+           if (ret) {
+               krb5_free_principal(context, client);
                return ret;
+           }
        }
     }
 
@@ -509,9 +512,9 @@ kadm_connect(kadm5_client_context *ctx)
     hints.ai_socktype = SOCK_STREAM;
     hints.ai_protocol = IPPROTO_TCP;
 
-    snprintf(portstr, sizeof(portstr), "%u", ntohs(ctx->kadmind_port));
+    snprintf(portstr, sizeof(portstr), "%u", ntohs(kadmin_port));
 
-    hostname = ctx->admin_server;
+    hostname = admin_server;
     slash = strchr(hostname, '/');
     if (slash != NULL)
        hostname = slash + 1;
@@ -530,6 +533,7 @@ kadm_connect(kadm5_client_context *ctx)
        if (connect(s, a->ai_addr, a->ai_addrlen) < 0) {
            krb5_warn(context, errno, "connect(%s)", hostname);
            rk_closesocket(s);
+           s = rk_INVALID_SOCKET;
            continue;
        }
        break;
@@ -640,7 +644,7 @@ kadm5_c_init_with_context(krb5_context context,
                          void **server_handle)
 {
     kadm5_ret_t ret;
-    kadm5_client_context *ctx;
+    kadm5_client_context *ctx = NULL;
     krb5_ccache cc;
 
     ret = _kadm5_c_init_context(&ctx, realm_params, context);
index 926c23510e9e04bfa29174ccd913409b89177773..1b1d7f2ff58c0043fd5826977975a75b8f2bfadf 100644 (file)
@@ -45,14 +45,16 @@ kadm5_s_init_with_context(krb5_context context,
                          void **server_handle)
 {
     kadm5_ret_t ret;
-    kadm5_server_context *ctx;
+    kadm5_server_context *ctx = NULL;
     char *dbname;
     char *stash_file;
 
     *server_handle = NULL;
     ret = _kadm5_s_init_context(&ctx, realm_params, context);
-    if (ret)
+    if (ret) {
+        kadm5_s_destroy(ctx);
        return ret;
+    }
 
     if (realm_params->mask & KADM5_CONFIG_DBNAME)
        dbname = realm_params->dbname;
index 9c18f832e132207aa6dd9213823f6c59a4b09dcc..a2ad51e7d0816d630bcb962c686ce0bfd047a70b 100644 (file)
@@ -137,21 +137,29 @@ print_entry(kadm5_server_context *server_context,
            entry_kind, op_names[op], ver, t, len);
     switch(op) {
     case kadm_delete:
-       krb5_ret_principal(sp, &source);
-       krb5_unparse_name(scontext, source, &name1);
+        ret = krb5_ret_principal(sp, &source);
+        if (ret == 0)
+            ret = krb5_unparse_name(scontext, source, &name1);
+        if (ret)
+            krb5_err(scontext, 1, ret, "Failed to read a delete record");
        printf("    %s\n", name1);
        free(name1);
        krb5_free_principal(scontext, source);
        break;
     case kadm_rename:
        ret = krb5_data_alloc(&data, len);
-       if (ret)
-           krb5_err (scontext, 1, ret, "kadm_rename: data alloc: %d", len);
-       krb5_ret_principal(sp, &source);
-       krb5_storage_read(sp, data.data, data.length);
-       hdb_value2entry(scontext, &data, &ent);
-       krb5_unparse_name(scontext, source, &name1);
-       krb5_unparse_name(scontext, ent.principal, &name2);
+        if (ret == 0)
+            ret = krb5_ret_principal(sp, &source);
+        if (ret == 0 && krb5_storage_read(sp, data.data, data.length) == -1)
+            ret = errno;
+        if (ret == 0)
+            ret = hdb_value2entry(scontext, &data, &ent);
+        if (ret == 0)
+            ret = krb5_unparse_name(scontext, source, &name1);
+        if (ret == 0)
+            ret = krb5_unparse_name(scontext, ent.principal, &name2);
+        if (ret)
+            krb5_err(scontext, 1, ret, "Failed to read a rename record");
        printf("    %s -> %s\n", name1, name2);
        free(name1);
        free(name2);
@@ -160,26 +168,30 @@ print_entry(kadm5_server_context *server_context,
        break;
     case kadm_create:
        ret = krb5_data_alloc(&data, len);
+        if (ret == 0 && krb5_storage_read(sp, data.data, data.length) == -1)
+            ret = errno;
+        if (ret == 0)
+            ret = hdb_value2entry(scontext, &data, &ent);
        if (ret)
-           krb5_err (scontext, 1, ret, "kadm_create: data alloc: %d", len);
-       krb5_storage_read(sp, data.data, data.length);
-       ret = hdb_value2entry(scontext, &data, &ent);
-       if(ret)
-           abort();
+            krb5_err(scontext, 1, ret, "Failed to read a create record");
        mask = ~0;
        goto foo;
     case kadm_modify:
        ret = krb5_data_alloc(&data, len);
+        if (ret == 0)
+            ret = krb5_ret_int32(sp, &mask);
+        if (ret == 0 && krb5_storage_read(sp, data.data, data.length) == -1)
+            ret = errno;
+        if (ret == 0)
+            ret = hdb_value2entry(scontext, &data, &ent);
        if (ret)
-           krb5_err (scontext, 1, ret, "kadm_modify: data alloc: %d", len);
-       krb5_ret_int32(sp, &mask);
-       krb5_storage_read(sp, data.data, data.length);
-       ret = hdb_value2entry(scontext, &data, &ent);
-       if(ret)
-           abort();
+            krb5_err(scontext, 1, ret, "Failed to read a modify record");
     foo:
        if(ent.principal /* mask & KADM5_PRINCIPAL */) {
-           krb5_unparse_name(scontext, ent.principal, &name1);
+           ret = krb5_unparse_name(scontext, ent.principal, &name1);
+            if (ret)
+                krb5_err(scontext, 1, ret,
+                         "Failed to process a create or modify record");
            printf("    principal = %s\n", name1);
            free(name1);
        }
@@ -263,14 +275,19 @@ print_entry(kadm5_server_context *server_context,
     case kadm_nop :
         if (len == 16) {
             uint64_t off;
-            krb5_ret_uint64(sp, &off);
+            ret = krb5_ret_uint64(sp, &off);
+            if (ret)
+                krb5_err(scontext, 1, ret, "Failed to read a no-op record");
             printf("uberblock offset %llu ", (unsigned long long)off);
         } else {
             printf("nop");
         }
         if (len == 16 || len == 8) {
-            krb5_ret_int32(sp, &nop_time);
-            krb5_ret_uint32(sp, &nop_ver);
+            ret = krb5_ret_int32(sp, &nop_time);
+            if (ret == 0)
+                ret = krb5_ret_uint32(sp, &nop_ver);
+            if (ret)
+                krb5_err(scontext, 1, ret, "Failed to read a no-op record");
 
             timestamp = nop_time;
             strftime(t, sizeof(t), "%Y-%m-%d %H:%M:%S", localtime(&timestamp));
@@ -279,7 +296,7 @@ print_entry(kadm5_server_context *server_context,
         printf("\n");
        break;
     default:
-       abort();
+        krb5_errx(scontext, 1, "Unknown record type");
     }
     krb5_data_free(&data);
 
index be0adc1b3802e42142f4cad99af4b5206de9471b..1decfe3333d9d24ffce1205e93e49e86f8d26930 100644 (file)
@@ -53,6 +53,7 @@ setup_signal(void)
     {
        struct sigaction sa;
 
+        memset(&sa, 0, sizeof(sa));
        sa.sa_flags = 0;
        sa.sa_handler = sigterm;
        sigemptyset(&sa.sa_mask);
index a27d8f75a38b9ce3c8a4331e1f3eeadf2656ccc1..b3f7d8105ea73e511f861295cb0bea4e5f58bff4 100644 (file)
@@ -95,7 +95,7 @@ make_listen_socket (krb5_context context, const char *port_str)
     fd = socket (AF_INET, SOCK_STREAM, 0);
     if (rk_IS_BAD_SOCKET(fd))
        krb5_err (context, 1, rk_SOCK_ERRNO, "socket AF_INET");
-    setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(one));
+    (void) setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(one));
     memset (&addr, 0, sizeof(addr));
     addr.sin_family = AF_INET;
 
@@ -392,14 +392,14 @@ error:
 }
 
 static int
-dump_one (krb5_context context, HDB *db, hdb_entry_ex *entry, void *v)
+dump_one (krb5_context context, HDB *db, hdb_entry *entry, void *v)
 {
     krb5_error_code ret;
     krb5_storage *dump = (krb5_storage *)v;
     krb5_storage *sp;
     krb5_data data;
 
-    ret = hdb_entry2value (context, &entry->entry, &data);
+    ret = hdb_entry2value (context, entry, &data);
     if (ret)
        return ret;
     ret = krb5_data_realloc (&data, data.length + 4);
@@ -450,6 +450,8 @@ write_dump (krb5_context context, krb5_storage *dump,
      */
 
     ret = krb5_store_uint32(dump, 0);
+    if (ret)
+        return ret;
 
     ret = hdb_create (context, &db, database);
     if (ret)
@@ -1117,7 +1119,7 @@ send_diffs(kadm5_server_context *server_context, slave *s, int log_fd,
     krb5_storage *sp;
     uint32_t initial_version;
     uint32_t initial_tstamp;
-    uint32_t ver;
+    uint32_t ver = 0;
     off_t left = 0;
     off_t right = 0;
     krb5_ssize_t bytes;
@@ -1251,7 +1253,8 @@ fill_input(krb5_context context, slave *s)
             return EWOULDBLOCK;
 
         buf = s->input.header_buf;
-        len = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
+        len = ((unsigned long)buf[0] << 24) | (buf[1] << 16)
+           | (buf[2] << 8) | buf[3];
         if (len > SLAVE_MSG_MAX)
             return EINVAL;
         ret = krb5_data_alloc(&s->input.packet, len);
@@ -1432,11 +1435,13 @@ write_master_down(krb5_context context)
         fp = fopen(slave_stats_temp_file, "w");
     if (fp == NULL)
        return;
-    krb5_format_time(context, t, str, sizeof(str), TRUE);
-    fprintf(fp, "master down at %s\n", str);
+    if (krb5_format_time(context, t, str, sizeof(str), TRUE) == 0)
+        fprintf(fp, "master down at %s\n", str);
+    else
+        fprintf(fp, "master down\n");
 
     if (fclose(fp) != EOF)
-        rk_rename(slave_stats_temp_file, slave_stats_file);
+        (void) rk_rename(slave_stats_temp_file, slave_stats_file);
 }
 
 static void
@@ -1452,7 +1457,8 @@ write_stats(krb5_context context, slave *slaves, uint32_t current_version)
     if (fp == NULL)
        return;
 
-    krb5_format_time(context, t, str, sizeof(str), TRUE);
+    if (krb5_format_time(context, t, str, sizeof(str), TRUE))
+        snprintf(str, sizeof(str), "<unknown-time>");
     fprintf(fp, "Status for slaves, last updated: %s\n\n", str);
 
     fprintf(fp, "Master version: %lu\n\n", (unsigned long)current_version);
@@ -1494,7 +1500,10 @@ write_stats(krb5_context context, slave *slaves, uint32_t current_version)
            rtbl_add_column_entry(tbl, SLAVE_STATUS, "Up");
 
        ret = krb5_format_time(context, slaves->seen, str, sizeof(str), TRUE);
-       rtbl_add_column_entry(tbl, SLAVE_SEEN, str);
+        if (ret)
+            rtbl_add_column_entry(tbl, SLAVE_SEEN, "<error-formatting-time>");
+        else
+            rtbl_add_column_entry(tbl, SLAVE_SEEN, str);
 
        slaves = slaves->next;
     }
@@ -1503,7 +1512,7 @@ write_stats(krb5_context context, slave *slaves, uint32_t current_version)
     rtbl_destroy(tbl);
 
     if (fclose(fp) != EOF)
-        rk_rename(slave_stats_temp_file, slave_stats_file);
+        (void) rk_rename(slave_stats_temp_file, slave_stats_file);
 }
 
 
index cd9a6f57a3b991a2ad68d6d95c50c491724a199c..2b1be00ea606321c447c8820de7e0652963a7893 100644 (file)
@@ -184,6 +184,8 @@ ihave(krb5_context context, krb5_auth_context auth_context,
     krb5_data data;
 
     sp = krb5_storage_from_mem(buf, 8);
+    if (sp == NULL)
+        krb5_err(context, IPROPD_RESTART_SLOW, ENOMEM, "Out of memory");
     ret = krb5_store_uint32(sp, I_HAVE);
     if (ret == 0)
         ret = krb5_store_uint32(sp, version);
@@ -571,7 +573,7 @@ receive_everything(krb5_context context, int fd,
        krb5_ret_uint32(sp, &opcode);
        if (opcode == ONE_PRINC) {
            krb5_data fake_data;
-           hdb_entry_ex entry;
+           hdb_entry entry;
 
            krb5_storage_free(sp);
 
@@ -580,7 +582,7 @@ receive_everything(krb5_context context, int fd,
 
            memset(&entry, 0, sizeof(entry));
 
-           ret = hdb_value2entry(context, &fake_data, &entry.entry);
+           ret = hdb_value2entry(context, &fake_data, &entry);
            if (ret)
                krb5_err(context, IPROPD_RESTART, ret, "hdb_value2entry");
            ret = mydb->hdb_store(server_context->context,
@@ -589,7 +591,7 @@ receive_everything(krb5_context context, int fd,
            if (ret)
                krb5_err(context, IPROPD_RESTART_SLOW, ret, "hdb_store");
 
-           hdb_free_entry(context, &entry);
+           hdb_free_entry(context, mydb, &entry);
            krb5_data_free(&data);
        } else if (opcode == NOW_YOU_HAVE)
            ;
index 376cecd9e40b5424375f3945f95ae985519d3260..4f66426c4ca63ad6ce9b8698d6b32a831b765842 100644 (file)
@@ -974,14 +974,12 @@ kadm5_log_create(kadm5_server_context *context, hdb_entry *entry)
     krb5_ssize_t bytes;
     kadm5_ret_t ret;
     krb5_data value;
-    hdb_entry_ex ent, existing;
+    hdb_entry ent, existing;
     kadm5_log_context *log_context = &context->log_context;
 
     memset(&existing, 0, sizeof(existing));
     memset(&ent, 0, sizeof(ent));
-    ent.ctx = 0;
-    ent.free_entry = 0;
-    ent.entry = *entry;
+    ent = *entry;
 
     /*
      * Do not allow creation of concrete entries within namespaces unless
@@ -991,14 +989,14 @@ kadm5_log_create(kadm5_server_context *context, hdb_entry *entry)
                          0, 0, 0, &existing);
     if (ret != 0 && ret != HDB_ERR_NOENTRY)
         return ret;
-    if (ret == 0 && !ent.entry.flags.materialize &&
-        (existing.entry.flags.virtual || existing.entry.flags.virtual_keys)) {
-        hdb_free_entry(context->context, &existing);
+    if (ret == 0 && !ent.flags.materialize &&
+        (existing.flags.virtual || existing.flags.virtual_keys)) {
+        hdb_free_entry(context->context, context->db, &existing);
         return HDB_ERR_EXISTS;
     }
     if (ret == 0)
-        hdb_free_entry(context->context, &existing);
-    ent.entry.flags.materialize = 0; /* Clear in stored entry */
+        hdb_free_entry(context->context, context->db, &existing);
+    ent.flags.materialize = 0; /* Clear in stored entry */
 
     /*
      * If we're not logging then we can't recover-to-perform, so just
@@ -1057,7 +1055,7 @@ kadm5_log_replay_create(kadm5_server_context *context,
 {
     krb5_error_code ret;
     krb5_data data;
-    hdb_entry_ex ent;
+    hdb_entry ent;
 
     memset(&ent, 0, sizeof(ent));
 
@@ -1067,7 +1065,7 @@ kadm5_log_replay_create(kadm5_server_context *context,
        return ret;
     }
     krb5_storage_read(sp, data.data, len);
-    ret = hdb_value2entry(context->context, &data, &ent.entry);
+    ret = hdb_value2entry(context->context, &data, &ent);
     krb5_data_free(&data);
     if (ret) {
        krb5_set_error_message(context->context, ret,
@@ -1076,7 +1074,7 @@ kadm5_log_replay_create(kadm5_server_context *context,
        return ret;
     }
     ret = context->db->hdb_store(context->context, context->db, 0, &ent);
-    hdb_free_entry(context->context, &ent);
+    hdb_free_entry(context->context, context->db, &ent);
     return ret;
 }
 
@@ -1198,13 +1196,11 @@ kadm5_log_rename(kadm5_server_context *context,
     off_t end_off = 0;  /* Ditto; this allows de-indentation by two levels */
     off_t off;
     krb5_data value;
-    hdb_entry_ex ent;
+    hdb_entry ent;
     kadm5_log_context *log_context = &context->log_context;
 
     memset(&ent, 0, sizeof(ent));
-    ent.ctx = 0;
-    ent.free_entry = 0;
-    ent.entry = *entry;
+    ent = *entry;
 
     if (strcmp(log_context->log_file, "/dev/null") == 0) {
         ret = context->db->hdb_store(context->context, context->db, 0, &ent);
@@ -1310,7 +1306,7 @@ kadm5_log_replay_rename(kadm5_server_context *context,
 {
     krb5_error_code ret;
     krb5_principal source;
-    hdb_entry_ex target_ent;
+    hdb_entry target_ent;
     krb5_data value;
     off_t off;
     size_t princ_len, data_len;
@@ -1332,7 +1328,7 @@ kadm5_log_replay_rename(kadm5_server_context *context,
        return ret;
     }
     krb5_storage_read(sp, value.data, data_len);
-    ret = hdb_value2entry(context->context, &value, &target_ent.entry);
+    ret = hdb_value2entry(context->context, &value, &target_ent);
     krb5_data_free(&value);
     if (ret) {
        krb5_free_principal(context->context, source);
@@ -1340,7 +1336,7 @@ kadm5_log_replay_rename(kadm5_server_context *context,
     }
     ret = context->db->hdb_store(context->context, context->db,
                                 0, &target_ent);
-    hdb_free_entry(context->context, &target_ent);
+    hdb_free_entry(context->context, context->db, &target_ent);
     if (ret) {
        krb5_free_principal(context->context, source);
        return ret;
@@ -1364,13 +1360,11 @@ kadm5_log_modify(kadm5_server_context *context,
     kadm5_ret_t ret;
     krb5_data value;
     uint32_t len;
-    hdb_entry_ex ent;
+    hdb_entry ent;
     kadm5_log_context *log_context = &context->log_context;
 
     memset(&ent, 0, sizeof(ent));
-    ent.ctx = 0;
-    ent.free_entry = 0;
-    ent.entry = *entry;
+    ent = *entry;
 
     if (strcmp(log_context->log_file, "/dev/null") == 0)
         return context->db->hdb_store(context->context, context->db,
@@ -1434,7 +1428,7 @@ kadm5_log_replay_modify(kadm5_server_context *context,
     krb5_error_code ret;
     uint32_t mask;
     krb5_data value;
-    hdb_entry_ex ent, log_ent;
+    hdb_entry ent, log_ent;
 
     memset(&log_ent, 0, sizeof(log_ent));
 
@@ -1452,7 +1446,7 @@ kadm5_log_replay_modify(kadm5_server_context *context,
         ret = errno ? errno : EIO;
         return ret;
     }
-    ret = hdb_value2entry (context->context, &value, &log_ent.entry);
+    ret = hdb_value2entry (context->context, &value, &log_ent);
     krb5_data_free(&value);
     if (ret)
        return ret;
@@ -1460,37 +1454,37 @@ kadm5_log_replay_modify(kadm5_server_context *context,
     memset(&ent, 0, sizeof(ent));
     /* NOTE: We do not use hdb_fetch_kvno() here */
     ret = context->db->hdb_fetch_kvno(context->context, context->db,
-                                     log_ent.entry.principal,
+                                     log_ent.principal,
                                      HDB_F_DECRYPT|HDB_F_ALL_KVNOS|
                                      HDB_F_GET_ANY|HDB_F_ADMIN_DATA, 0, &ent);
     if (ret)
        goto out;
     if (mask & KADM5_PRINC_EXPIRE_TIME) {
-       if (log_ent.entry.valid_end == NULL) {
-           ent.entry.valid_end = NULL;
+       if (log_ent.valid_end == NULL) {
+           ent.valid_end = NULL;
        } else {
-           if (ent.entry.valid_end == NULL) {
-               ent.entry.valid_end = malloc(sizeof(*ent.entry.valid_end));
-               if (ent.entry.valid_end == NULL) {
+           if (ent.valid_end == NULL) {
+               ent.valid_end = malloc(sizeof(*ent.valid_end));
+               if (ent.valid_end == NULL) {
                    ret = krb5_enomem(context->context);
                    goto out;
                }
            }
-           *ent.entry.valid_end = *log_ent.entry.valid_end;
+           *ent.valid_end = *log_ent.valid_end;
        }
     }
     if (mask & KADM5_PW_EXPIRATION) {
-       if (log_ent.entry.pw_end == NULL) {
-           ent.entry.pw_end = NULL;
+       if (log_ent.pw_end == NULL) {
+           ent.pw_end = NULL;
        } else {
-           if (ent.entry.pw_end == NULL) {
-               ent.entry.pw_end = malloc(sizeof(*ent.entry.pw_end));
-               if (ent.entry.pw_end == NULL) {
+           if (ent.pw_end == NULL) {
+               ent.pw_end = malloc(sizeof(*ent.pw_end));
+               if (ent.pw_end == NULL) {
                    ret = krb5_enomem(context->context);
                    goto out;
                }
            }
-           *ent.entry.pw_end = *log_ent.entry.pw_end;
+           *ent.pw_end = *log_ent.pw_end;
        }
     }
     if (mask & KADM5_LAST_PWD_CHANGE) {
@@ -1498,39 +1492,39 @@ kadm5_log_replay_modify(kadm5_server_context *context,
                     "Unimplemented mask KADM5_LAST_PWD_CHANGE");
     }
     if (mask & KADM5_ATTRIBUTES) {
-       ent.entry.flags = log_ent.entry.flags;
+       ent.flags = log_ent.flags;
     }
     if (mask & KADM5_MAX_LIFE) {
-       if (log_ent.entry.max_life == NULL) {
-           ent.entry.max_life = NULL;
+       if (log_ent.max_life == NULL) {
+           ent.max_life = NULL;
        } else {
-           if (ent.entry.max_life == NULL) {
-               ent.entry.max_life = malloc (sizeof(*ent.entry.max_life));
-               if (ent.entry.max_life == NULL) {
+           if (ent.max_life == NULL) {
+               ent.max_life = malloc (sizeof(*ent.max_life));
+               if (ent.max_life == NULL) {
                    ret = krb5_enomem(context->context);
                    goto out;
                }
            }
-           *ent.entry.max_life = *log_ent.entry.max_life;
+           *ent.max_life = *log_ent.max_life;
        }
     }
     if ((mask & KADM5_MOD_TIME) && (mask & KADM5_MOD_NAME)) {
-       if (ent.entry.modified_by == NULL) {
-           ent.entry.modified_by = malloc(sizeof(*ent.entry.modified_by));
-           if (ent.entry.modified_by == NULL) {
+       if (ent.modified_by == NULL) {
+           ent.modified_by = malloc(sizeof(*ent.modified_by));
+           if (ent.modified_by == NULL) {
                ret = krb5_enomem(context->context);
                goto out;
            }
        } else
-           free_Event(ent.entry.modified_by);
-       ret = copy_Event(log_ent.entry.modified_by, ent.entry.modified_by);
+           free_Event(ent.modified_by);
+       ret = copy_Event(log_ent.modified_by, ent.modified_by);
        if (ret) {
            ret = krb5_enomem(context->context);
            goto out;
        }
     }
     if (mask & KADM5_KVNO) {
-       ent.entry.kvno = log_ent.entry.kvno;
+       ent.kvno = log_ent.kvno;
     }
     if (mask & KADM5_MKVNO) {
         krb5_warnx(context->context, "Unimplemented mask KADM5_KVNO");
@@ -1543,17 +1537,17 @@ kadm5_log_replay_modify(kadm5_server_context *context,
         krb5_warnx(context->context, "Unimplemented mask KADM5_POLICY_CLR");
     }
     if (mask & KADM5_MAX_RLIFE) {
-       if (log_ent.entry.max_renew == NULL) {
-           ent.entry.max_renew = NULL;
+       if (log_ent.max_renew == NULL) {
+           ent.max_renew = NULL;
        } else {
-           if (ent.entry.max_renew == NULL) {
-               ent.entry.max_renew = malloc (sizeof(*ent.entry.max_renew));
-               if (ent.entry.max_renew == NULL) {
+           if (ent.max_renew == NULL) {
+               ent.max_renew = malloc (sizeof(*ent.max_renew));
+               if (ent.max_renew == NULL) {
                    ret = krb5_enomem(context->context);
                    goto out;
                }
            }
-           *ent.entry.max_renew = *log_ent.entry.max_renew;
+           *ent.max_renew = *log_ent.max_renew;
        }
     }
     if (mask & KADM5_LAST_SUCCESS) {
@@ -1579,70 +1573,70 @@ kadm5_log_replay_modify(kadm5_server_context *context,
         */
        mask |= KADM5_TL_DATA;
 
-       for (i = 0; i < ent.entry.keys.len; ++i)
-           free_Key(&ent.entry.keys.val[i]);
-       free (ent.entry.keys.val);
+       for (i = 0; i < ent.keys.len; ++i)
+           free_Key(&ent.keys.val[i]);
+       free (ent.keys.val);
 
-       num = log_ent.entry.keys.len;
+       num = log_ent.keys.len;
 
-       ent.entry.keys.len = num;
-       ent.entry.keys.val = malloc(len * sizeof(*ent.entry.keys.val));
-       if (ent.entry.keys.val == NULL) {
+       ent.keys.len = num;
+       ent.keys.val = malloc(len * sizeof(*ent.keys.val));
+       if (ent.keys.val == NULL) {
            krb5_enomem(context->context);
            goto out;
        }
-       for (i = 0; i < ent.entry.keys.len; ++i) {
-           ret = copy_Key(&log_ent.entry.keys.val[i],
-                          &ent.entry.keys.val[i]);
+       for (i = 0; i < ent.keys.len; ++i) {
+           ret = copy_Key(&log_ent.keys.val[i],
+                          &ent.keys.val[i]);
            if (ret) {
                krb5_set_error_message(context->context, ret, "out of memory");
                goto out;
            }
        }
     }
-    if ((mask & KADM5_TL_DATA) && log_ent.entry.etypes) {
-        if (ent.entry.etypes)
-            free_HDB_EncTypeList(ent.entry.etypes);
-        free(ent.entry.etypes);
-        ent.entry.etypes = calloc(1, sizeof(*ent.entry.etypes));
-        if (ent.entry.etypes == NULL)
+    if ((mask & KADM5_TL_DATA) && log_ent.etypes) {
+        if (ent.etypes)
+            free_HDB_EncTypeList(ent.etypes);
+        free(ent.etypes);
+        ent.etypes = calloc(1, sizeof(*ent.etypes));
+        if (ent.etypes == NULL)
             ret = ENOMEM;
         if (ret == 0)
-            ret = copy_HDB_EncTypeList(log_ent.entry.etypes, ent.entry.etypes);
+            ret = copy_HDB_EncTypeList(log_ent.etypes, ent.etypes);
         if (ret) {
             ret = krb5_enomem(context->context);
-            free(ent.entry.etypes);
-            ent.entry.etypes = NULL;
+            free(ent.etypes);
+            ent.etypes = NULL;
             goto out;
         }
     }
 
-    if ((mask & KADM5_TL_DATA) && log_ent.entry.extensions) {
-       if (ent.entry.extensions) {
-           free_HDB_extensions(ent.entry.extensions);
-           free(ent.entry.extensions);
-            ent.entry.extensions = NULL;
+    if ((mask & KADM5_TL_DATA) && log_ent.extensions) {
+       if (ent.extensions) {
+           free_HDB_extensions(ent.extensions);
+           free(ent.extensions);
+            ent.extensions = NULL;
        }
 
-       ent.entry.extensions = calloc(1, sizeof(*ent.entry.extensions));
-       if (ent.entry.extensions == NULL)
+       ent.extensions = calloc(1, sizeof(*ent.extensions));
+       if (ent.extensions == NULL)
            ret = ENOMEM;
 
         if (ret == 0)
-            ret = copy_HDB_extensions(log_ent.entry.extensions,
-                                      ent.entry.extensions);
+            ret = copy_HDB_extensions(log_ent.extensions,
+                                      ent.extensions);
        if (ret) {
            ret = krb5_enomem(context->context);
-           free(ent.entry.extensions);
-           ent.entry.extensions = NULL;
+           free(ent.extensions);
+           ent.extensions = NULL;
            goto out;
        }
     }
     ret = context->db->hdb_store(context->context, context->db,
                                 HDB_F_REPLACE, &ent);
  out:
-    hdb_free_entry(context->context, &ent);
-    hdb_free_entry(context->context, &log_ent);
+    hdb_free_entry(context->context, context->db, &ent);
+    hdb_free_entry(context->context, context->db, &log_ent);
     return ret;
 }
 
index c66bcd75ae67026554d2451829876f71422ef64b..9d24233ba6eab633923e5a604570b8c69063d112 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "kadm5_locl.h"
 
-RCSID("$Id$");
+#define CHECK(e) do { if ((ret = e)) goto out; } while (0)
 
 int
 kadm5_some_keys_are_bogus(size_t n_keys, krb5_key_data *keys)
@@ -72,29 +72,34 @@ kadm5_ret_t
 kadm5_store_key_data(krb5_storage *sp,
                     krb5_key_data *key)
 {
+    kadm5_ret_t ret;
     krb5_data c;
-    krb5_store_int32(sp, key->key_data_ver);
-    krb5_store_int32(sp, key->key_data_kvno);
-    krb5_store_int32(sp, key->key_data_type[0]);
+
+    CHECK(krb5_store_int32(sp, key->key_data_ver));
+    CHECK(krb5_store_int32(sp, key->key_data_kvno));
+    CHECK(krb5_store_int32(sp, key->key_data_type[0]));
     c.length = key->key_data_length[0];
     c.data = key->key_data_contents[0];
-    krb5_store_data(sp, c);
-    krb5_store_int32(sp, key->key_data_type[1]);
+    CHECK(krb5_store_data(sp, c));
+    CHECK(krb5_store_int32(sp, key->key_data_type[1]));
     c.length = key->key_data_length[1];
     c.data = key->key_data_contents[1];
-    krb5_store_data(sp, c);
-    return 0;
+    CHECK(krb5_store_data(sp, c));
+
+out:
+    return ret;
 }
 
 kadm5_ret_t
 kadm5_store_fake_key_data(krb5_storage *sp,
                          krb5_key_data *key)
 {
+    kadm5_ret_t ret;
     krb5_data c;
 
-    krb5_store_int32(sp, key->key_data_ver);
-    krb5_store_int32(sp, key->key_data_kvno);
-    krb5_store_int32(sp, key->key_data_type[0]);
+    CHECK(krb5_store_int32(sp, key->key_data_ver));
+    CHECK(krb5_store_int32(sp, key->key_data_kvno));
+    CHECK(krb5_store_int32(sp, key->key_data_type[0]));
 
     /*
      * This is the key contents.  We want it to be obvious to the client
@@ -106,63 +111,88 @@ kadm5_store_fake_key_data(krb5_storage *sp,
      */
     c.length = sizeof (KADM5_BOGUS_KEY_DATA) - 1;
     c.data = KADM5_BOGUS_KEY_DATA;
-    krb5_store_data(sp, c);
+    CHECK(krb5_store_data(sp, c));
 
     /* This is the salt -- no need to send garbage */
-    krb5_store_int32(sp, key->key_data_type[1]);
+    CHECK(krb5_store_int32(sp, key->key_data_type[1]));
     c.length = key->key_data_length[1];
     c.data = key->key_data_contents[1];
-    krb5_store_data(sp, c);
-    return 0;
+    CHECK(krb5_store_data(sp, c));
+
+out:
+    return ret;
 }
 
 kadm5_ret_t
 kadm5_ret_key_data(krb5_storage *sp,
                   krb5_key_data *key)
 {
+    kadm5_ret_t ret;
     krb5_data c;
     int32_t tmp;
-    krb5_ret_int32(sp, &tmp);
-    key->key_data_ver = tmp;
-    krb5_ret_int32(sp, &tmp);
-    key->key_data_kvno = tmp;
-    krb5_ret_int32(sp, &tmp);
-    key->key_data_type[0] = tmp;
-    krb5_ret_data(sp, &c);
-    key->key_data_length[0] = c.length;
-    key->key_data_contents[0] = c.data;
-    krb5_ret_int32(sp, &tmp);
-    key->key_data_type[1] = tmp;
-    krb5_ret_data(sp, &c);
-    key->key_data_length[1] = c.length;
-    key->key_data_contents[1] = c.data;
-    return 0;
+
+    ret = krb5_ret_int32(sp, &tmp);
+    if (ret == 0) {
+        key->key_data_ver = tmp;
+        ret = krb5_ret_int32(sp, &tmp);
+    }
+    if (ret == 0) {
+        key->key_data_kvno = tmp;
+        ret = krb5_ret_int32(sp, &tmp);
+    }
+    if (ret == 0) {
+        key->key_data_type[0] = tmp;
+        ret = krb5_ret_data(sp, &c);
+    }
+    if (ret == 0) {
+        key->key_data_length[0] = c.length;
+        key->key_data_contents[0] = c.data;
+        ret = krb5_ret_int32(sp, &tmp);
+    }
+    if (ret == 0) {
+        key->key_data_type[1] = tmp;
+        ret = krb5_ret_data(sp, &c);
+    }
+    if (ret == 0) {
+        key->key_data_length[1] = c.length;
+        key->key_data_contents[1] = c.data;
+        return 0;
+    }
+    return KADM5_FAILURE;
 }
 
 kadm5_ret_t
 kadm5_store_tl_data(krb5_storage *sp,
                    krb5_tl_data *tl)
 {
+    kadm5_ret_t ret;
     krb5_data c;
-    krb5_store_int32(sp, tl->tl_data_type);
+
+    CHECK(krb5_store_int32(sp, tl->tl_data_type));
     c.length = tl->tl_data_length;
     c.data = tl->tl_data_contents;
-    krb5_store_data(sp, c);
-    return 0;
+    CHECK(krb5_store_data(sp, c));
+
+out:
+    return ret;
 }
 
 kadm5_ret_t
 kadm5_ret_tl_data(krb5_storage *sp,
                  krb5_tl_data *tl)
 {
+    kadm5_ret_t ret;
     krb5_data c;
     int32_t tmp;
-    krb5_ret_int32(sp, &tmp);
+
+    CHECK(krb5_ret_int32(sp, &tmp));
     tl->tl_data_type = tmp;
-    krb5_ret_data(sp, &c);
+    CHECK(krb5_ret_data(sp, &c));
     tl->tl_data_length = c.length;
     tl->tl_data_contents = c.data;
-    return 0;
+
+out:
+    return ret;
 }
 
 static kadm5_ret_t
@@ -170,63 +200,66 @@ store_principal_ent(krb5_storage *sp,
                    kadm5_principal_ent_t princ,
                    uint32_t mask, int wkeys)
 {
+    kadm5_ret_t ret = 0;
     int i;
 
     if (mask & KADM5_PRINCIPAL)
-       krb5_store_principal(sp, princ->principal);
+       CHECK(krb5_store_principal(sp, princ->principal));
     if (mask & KADM5_PRINC_EXPIRE_TIME)
-       krb5_store_int32(sp, princ->princ_expire_time);
+       CHECK(krb5_store_int32(sp, princ->princ_expire_time));
     if (mask & KADM5_PW_EXPIRATION)
-       krb5_store_int32(sp, princ->pw_expiration);
+       CHECK(krb5_store_int32(sp, princ->pw_expiration));
     if (mask & KADM5_LAST_PWD_CHANGE)
-       krb5_store_int32(sp, princ->last_pwd_change);
+       CHECK(krb5_store_int32(sp, princ->last_pwd_change));
     if (mask & KADM5_MAX_LIFE)
-       krb5_store_int32(sp, princ->max_life);
+       CHECK(krb5_store_int32(sp, princ->max_life));
     if (mask & KADM5_MOD_NAME) {
-       krb5_store_int32(sp, princ->mod_name != NULL);
+       CHECK(krb5_store_int32(sp, princ->mod_name != NULL));
        if(princ->mod_name)
-           krb5_store_principal(sp, princ->mod_name);
+           CHECK(krb5_store_principal(sp, princ->mod_name));
     }
     if (mask & KADM5_MOD_TIME)
-       krb5_store_int32(sp, princ->mod_date);
+       CHECK(krb5_store_int32(sp, princ->mod_date));
     if (mask & KADM5_ATTRIBUTES)
-       krb5_store_int32(sp, princ->attributes);
+       CHECK(krb5_store_int32(sp, princ->attributes));
     if (mask & KADM5_KVNO)
-       krb5_store_int32(sp, princ->kvno);
+       CHECK(krb5_store_int32(sp, princ->kvno));
     if (mask & KADM5_MKVNO)
-       krb5_store_int32(sp, princ->mkvno);
+       CHECK(krb5_store_int32(sp, princ->mkvno));
     if (mask & KADM5_POLICY) {
-       krb5_store_int32(sp, princ->policy != NULL);
+       CHECK(krb5_store_int32(sp, princ->policy != NULL));
        if(princ->policy)
-           krb5_store_string(sp, princ->policy);
+           CHECK(krb5_store_string(sp, princ->policy));
     }
     if (mask & KADM5_AUX_ATTRIBUTES)
-       krb5_store_int32(sp, princ->aux_attributes);
+       CHECK(krb5_store_int32(sp, princ->aux_attributes));
     if (mask & KADM5_MAX_RLIFE)
-       krb5_store_int32(sp, princ->max_renewable_life);
+       CHECK(krb5_store_int32(sp, princ->max_renewable_life));
     if (mask & KADM5_LAST_SUCCESS)
-       krb5_store_int32(sp, princ->last_success);
+       CHECK(krb5_store_int32(sp, princ->last_success));
     if (mask & KADM5_LAST_FAILED)
-       krb5_store_int32(sp, princ->last_failed);
+       CHECK(krb5_store_int32(sp, princ->last_failed));
     if (mask & KADM5_FAIL_AUTH_COUNT)
-       krb5_store_int32(sp, princ->fail_auth_count);
+       CHECK(krb5_store_int32(sp, princ->fail_auth_count));
     if (mask & KADM5_KEY_DATA) {
-       krb5_store_int32(sp, princ->n_key_data);
+       CHECK(krb5_store_int32(sp, princ->n_key_data));
        for(i = 0; i < princ->n_key_data; i++) {
            if (wkeys)
-               kadm5_store_key_data(sp, &princ->key_data[i]);
-           else
-               kadm5_store_fake_key_data(sp, &princ->key_data[i]);
+               CHECK(kadm5_store_key_data(sp, &princ->key_data[i]));
+            else
+                CHECK(kadm5_store_fake_key_data(sp, &princ->key_data[i]));
        }
     }
     if (mask & KADM5_TL_DATA) {
        krb5_tl_data *tp;
 
-       krb5_store_int32(sp, princ->n_tl_data);
-       for(tp = princ->tl_data; tp; tp = tp->tl_data_next)
-           kadm5_store_tl_data(sp, tp);
+       CHECK(krb5_store_int32(sp, princ->n_tl_data));
+       for (tp = princ->tl_data; tp; tp = tp->tl_data_next)
+           CHECK(kadm5_store_tl_data(sp, tp));
     }
-    return 0;
+
+out:
+    return ret;
 }
 
 
@@ -249,8 +282,12 @@ kadm5_store_principal_ent_mask(krb5_storage *sp,
                               kadm5_principal_ent_t princ,
                               uint32_t mask)
 {
-    krb5_store_int32(sp, mask);
-    return store_principal_ent (sp, princ, mask, 1);
+    kadm5_ret_t ret;
+
+    ret = krb5_store_int32(sp, mask);
+    if (ret == 0)
+        ret = store_principal_ent(sp, princ, mask, 1);
+    return ret;
 }
 
 static kadm5_ret_t
@@ -258,101 +295,112 @@ ret_principal_ent(krb5_storage *sp,
                  kadm5_principal_ent_t princ,
                  uint32_t mask)
 {
+    kadm5_ret_t ret = 0;
     int i;
     int32_t tmp;
 
     if (mask & KADM5_PRINCIPAL)
-       krb5_ret_principal(sp, &princ->principal);
+       CHECK(krb5_ret_principal(sp, &princ->principal));
 
     if (mask & KADM5_PRINC_EXPIRE_TIME) {
-       krb5_ret_int32(sp, &tmp);
+       CHECK(krb5_ret_int32(sp, &tmp));
        princ->princ_expire_time = tmp;
     }
     if (mask & KADM5_PW_EXPIRATION) {
-       krb5_ret_int32(sp, &tmp);
+       CHECK(krb5_ret_int32(sp, &tmp));
        princ->pw_expiration = tmp;
     }
     if (mask & KADM5_LAST_PWD_CHANGE) {
-       krb5_ret_int32(sp, &tmp);
+       CHECK(krb5_ret_int32(sp, &tmp));
        princ->last_pwd_change = tmp;
     }
     if (mask & KADM5_MAX_LIFE) {
-       krb5_ret_int32(sp, &tmp);
+       CHECK(krb5_ret_int32(sp, &tmp));
        princ->max_life = tmp;
     }
     if (mask & KADM5_MOD_NAME) {
-       krb5_ret_int32(sp, &tmp);
+       CHECK(krb5_ret_int32(sp, &tmp));
        if(tmp)
-           krb5_ret_principal(sp, &princ->mod_name);
+           CHECK(krb5_ret_principal(sp, &princ->mod_name));
        else
            princ->mod_name = NULL;
     }
     if (mask & KADM5_MOD_TIME) {
-       krb5_ret_int32(sp, &tmp);
+       CHECK(krb5_ret_int32(sp, &tmp));
        princ->mod_date = tmp;
     }
     if (mask & KADM5_ATTRIBUTES) {
-       krb5_ret_int32(sp, &tmp);
+       CHECK(krb5_ret_int32(sp, &tmp));
        princ->attributes = tmp;
     }
     if (mask & KADM5_KVNO) {
-       krb5_ret_int32(sp, &tmp);
+       CHECK(krb5_ret_int32(sp, &tmp));
        princ->kvno = tmp;
     }
     if (mask & KADM5_MKVNO) {
-       krb5_ret_int32(sp, &tmp);
+       CHECK(krb5_ret_int32(sp, &tmp));
        princ->mkvno = tmp;
     }
     if (mask & KADM5_POLICY) {
-       krb5_ret_int32(sp, &tmp);
+       CHECK(krb5_ret_int32(sp, &tmp));
        if(tmp)
-           krb5_ret_string(sp, &princ->policy);
+           CHECK(krb5_ret_string(sp, &princ->policy));
        else
            princ->policy = NULL;
     }
     if (mask & KADM5_AUX_ATTRIBUTES) {
-       krb5_ret_int32(sp, &tmp);
+       CHECK(krb5_ret_int32(sp, &tmp));
        princ->aux_attributes = tmp;
     }
     if (mask & KADM5_MAX_RLIFE) {
-       krb5_ret_int32(sp, &tmp);
+       CHECK(krb5_ret_int32(sp, &tmp));
        princ->max_renewable_life = tmp;
     }
     if (mask & KADM5_LAST_SUCCESS) {
-       krb5_ret_int32(sp, &tmp);
+       CHECK(krb5_ret_int32(sp, &tmp));
        princ->last_success = tmp;
     }
     if (mask & KADM5_LAST_FAILED) {
-       krb5_ret_int32(sp, &tmp);
+       CHECK(krb5_ret_int32(sp, &tmp));
        princ->last_failed = tmp;
     }
     if (mask & KADM5_FAIL_AUTH_COUNT) {
-       krb5_ret_int32(sp, &tmp);
+       CHECK(krb5_ret_int32(sp, &tmp));
        princ->fail_auth_count = tmp;
     }
     if (mask & KADM5_KEY_DATA) {
-       krb5_ret_int32(sp, &tmp);
+       CHECK(krb5_ret_int32(sp, &tmp));
        princ->n_key_data = tmp;
        princ->key_data = malloc(princ->n_key_data * sizeof(*princ->key_data));
        if (princ->key_data == NULL && princ->n_key_data != 0)
            return ENOMEM;
        for(i = 0; i < princ->n_key_data; i++)
-           kadm5_ret_key_data(sp, &princ->key_data[i]);
+           ret = kadm5_ret_key_data(sp, &princ->key_data[i]);
     }
     if (mask & KADM5_TL_DATA) {
-       krb5_ret_int32(sp, &tmp);
+       CHECK(krb5_ret_int32(sp, &tmp));
        princ->n_tl_data = tmp;
        princ->tl_data = NULL;
        for(i = 0; i < princ->n_tl_data; i++){
            krb5_tl_data *tp = malloc(sizeof(*tp));
-           if (tp == NULL)
-               return ENOMEM;
-           kadm5_ret_tl_data(sp, tp);
-           tp->tl_data_next = princ->tl_data;
-           princ->tl_data = tp;
+           if (tp == NULL) {
+                ret = ENOMEM;
+                goto out;
+            }
+           ret = kadm5_ret_tl_data(sp, tp);
+            if (ret == 0) {
+                tp->tl_data_next = princ->tl_data;
+                princ->tl_data = tp;
+            } else {
+                free(tp);
+                goto out;
+            }
        }
     }
-    return 0;
+
+out:
+    /* Can't free princ here -- we don't have a context */
+    return ret;
 }
 
 kadm5_ret_t
@@ -367,9 +415,14 @@ kadm5_ret_principal_ent_mask(krb5_storage *sp,
                             kadm5_principal_ent_t princ,
                             uint32_t *mask)
 {
+    kadm5_ret_t ret;
     int32_t tmp;
 
-    krb5_ret_int32 (sp, &tmp);
+    ret = krb5_ret_int32 (sp, &tmp);
+    if (ret) {
+        *mask = 0;
+        return ret;
+    }
     *mask = tmp;
     return ret_principal_ent (sp, princ, *mask);
 }
@@ -379,18 +432,19 @@ _kadm5_marshal_params(krb5_context context,
                      kadm5_config_params *params,
                      krb5_data *out)
 {
+    kadm5_ret_t ret;
+
     krb5_storage *sp = krb5_storage_emem();
     if (sp == NULL)
        return krb5_enomem(context);
 
-    krb5_store_int32(sp, params->mask & (KADM5_CONFIG_REALM));
-
-    if(params->mask & KADM5_CONFIG_REALM)
-       krb5_store_string(sp, params->realm);
-    krb5_storage_to_data(sp, out);
+    ret = krb5_store_int32(sp, params->mask & (KADM5_CONFIG_REALM));
+    if (ret == 0 && (params->mask & KADM5_CONFIG_REALM))
+       ret = krb5_store_string(sp, params->realm);
+    if (ret == 0)
+        ret = krb5_storage_to_data(sp, out);
     krb5_storage_free(sp);
-
-    return 0;
+    return ret;
 }
 
 kadm5_ret_t
@@ -398,7 +452,7 @@ _kadm5_unmarshal_params(krb5_context context,
                        krb5_data *in,
                        kadm5_config_params *params)
 {
-    krb5_error_code ret;
+    kadm5_ret_t ret;
     krb5_storage *sp;
     int32_t mask;
 
index cb2e1fd1decace0e59623951bee3cb3bf7ac23f7..2159caf5517c64ec89d3ae4eb13d26d6d3df9c60 100644 (file)
@@ -97,7 +97,7 @@ modify_principal(void *server_handle,
                 uint32_t forbidden_mask)
 {
     kadm5_server_context *context = server_handle;
-    hdb_entry_ex ent;
+    hdb_entry ent;
     kadm5_ret_t ret;
 
     memset(&ent, 0, sizeof(ent));
@@ -139,7 +139,7 @@ modify_principal(void *server_handle,
     ret = _kadm5_setup_entry(context, &ent, mask, princ, mask, NULL, 0);
     if (ret)
        goto out3;
-    ret = _kadm5_set_modifier(context, &ent.entry);
+    ret = _kadm5_set_modifier(context, &ent);
     if (ret)
        goto out3;
 
@@ -157,7 +157,7 @@ modify_principal(void *server_handle,
        goto out3;
     }
 
-    ret = hdb_seal_keys(context->context, context->db, &ent.entry);
+    ret = hdb_seal_keys(context->context, context->db, &ent);
     if (ret)
        goto out3;
 
@@ -174,21 +174,21 @@ modify_principal(void *server_handle,
            goto out3;
        }
        /* This calls free_HDB_extension(), freeing ext.data.u.policy */
-       ret = hdb_replace_extension(context->context, &ent.entry, &ext);
+       ret = hdb_replace_extension(context->context, &ent, &ext);
         free(ext.data.u.policy);
        if (ret)
            goto out3;
     }
 
     /* This logs the change for iprop and writes to the HDB */
-    ret = kadm5_log_modify(context, &ent.entry,
+    ret = kadm5_log_modify(context, &ent,
                            mask | KADM5_MOD_NAME | KADM5_MOD_TIME);
 
     (void) modify_principal_hook(context, KADM5_HOOK_STAGE_POSTCOMMIT,
                                 ret, princ, mask);
 
  out3:
-    hdb_free_entry(context->context, &ent);
+    hdb_free_entry(context->context, context->db, &ent);
  out2:
     (void) kadm5_log_end(context);
  out:
index e5d77f6cfd746219b01b046bf6c59d46bf738e2f..96133f242a9f99155b6951a1661c4b19b310fcb5 100644 (file)
@@ -95,7 +95,7 @@ kadm5_s_prune_principal(void *server_handle,
                         int kvno)
 {
     kadm5_server_context *context = server_handle;
-    hdb_entry_ex ent;
+    hdb_entry ent;
     kadm5_ret_t ret;
 
     memset(&ent, 0, sizeof(ent));
@@ -121,21 +121,21 @@ kadm5_s_prune_principal(void *server_handle,
     if (ret)
         goto out3;
 
-    ret = hdb_prune_keys_kvno(context->context, &ent.entry, kvno);
+    ret = hdb_prune_keys_kvno(context->context, &ent, kvno);
     if (ret)
         goto out3;
 
-    ret = hdb_seal_keys(context->context, context->db, &ent.entry);
+    ret = hdb_seal_keys(context->context, context->db, &ent);
     if (ret)
         goto out3;
 
-    ret = kadm5_log_modify(context, &ent.entry, KADM5_KEY_DATA);
+    ret = kadm5_log_modify(context, &ent, KADM5_KEY_DATA);
 
     (void) prune_principal_hook(context, KADM5_HOOK_STAGE_POSTCOMMIT,
                                ret, princ, kvno);
 
 out3:
-    hdb_free_entry(context->context, &ent);
+    hdb_free_entry(context->context, context->db, &ent);
 out2:
     (void) kadm5_log_end(context);
 out:
index ace0687613c3a03966af38447038146ac58e6333..cb0ec86ae5706e38f6f7ec42c7f312b77bc8d235 100644 (file)
@@ -93,7 +93,7 @@ kadm5_c_randkey_principal(void *server_handle,
     for (i = 0; ret == 0 && i < n_ks_tuple; i++) {
        ret = krb5_store_int32(sp, ks_tuple[i].ks_enctype);
         if (ret == 0)
-            krb5_store_int32(sp, ks_tuple[i].ks_salttype);
+            ret = krb5_store_int32(sp, ks_tuple[i].ks_salttype);
     }
     /* Future extensions go here */
     if (ret)
index 9bb83cd14a143393c1aff18c78b5785c140c1386..cb3696720f913a33950992c9c6a7363c3bc5b3e5 100644 (file)
@@ -102,7 +102,7 @@ kadm5_s_randkey_principal(void *server_handle,
                          int *n_keys)
 {
     kadm5_server_context *context = server_handle;
-    hdb_entry_ex ent;
+    hdb_entry ent;
     kadm5_ret_t ret;
     size_t i;
 
@@ -129,36 +129,36 @@ kadm5_s_randkey_principal(void *server_handle,
        goto out3;
 
     if (keepold) {
-       ret = hdb_add_current_keys_to_history(context->context, &ent.entry);
+       ret = hdb_add_current_keys_to_history(context->context, &ent);
         if (ret == 0 && keepold == 1)
-            ret = hdb_prune_keys_kvno(context->context, &ent.entry, 0);
+            ret = hdb_prune_keys_kvno(context->context, &ent, 0);
        if (ret)
            goto out3;
     } else {
         /* Remove all key history */
-        ret = hdb_clear_extension(context->context, &ent.entry,
+        ret = hdb_clear_extension(context->context, &ent,
                                   choice_HDB_extension_data_hist_keys);
        if (ret)
            goto out3;
     }
 
-    ret = _kadm5_set_keys_randomly(context, &ent.entry, n_ks_tuple, ks_tuple,
+    ret = _kadm5_set_keys_randomly(context, &ent, n_ks_tuple, ks_tuple,
                                    new_keys, n_keys);
     if (ret)
        goto out3;
-    ent.entry.kvno++;
+    ent.kvno++;
 
-    ent.entry.flags.require_pwchange = 0;
+    ent.flags.require_pwchange = 0;
 
-    ret = _kadm5_set_modifier(context, &ent.entry);
+    ret = _kadm5_set_modifier(context, &ent);
     if(ret)
        goto out4;
-    ret = _kadm5_bump_pw_expire(context, &ent.entry);
+    ret = _kadm5_bump_pw_expire(context, &ent);
     if (ret)
        goto out4;
 
     if (keepold) {
-       ret = hdb_seal_keys(context->context, context->db, &ent.entry);
+       ret = hdb_seal_keys(context->context, context->db, &ent);
        if (ret)
            goto out4;
     } else {
@@ -169,11 +169,11 @@ kadm5_s_randkey_principal(void *server_handle,
        ext.data.element = choice_HDB_extension_data_hist_keys;
        ext.data.u.hist_keys.len = 0;
        ext.data.u.hist_keys.val = NULL;
-       hdb_replace_extension(context->context, &ent.entry, &ext);
+       hdb_replace_extension(context->context, &ent, &ext);
     }
 
     /* This logs the change for iprop and writes to the HDB */
-    ret = kadm5_log_modify(context, &ent.entry,
+    ret = kadm5_log_modify(context, &ent,
                            KADM5_ATTRIBUTES | KADM5_PRINCIPAL |
                            KADM5_MOD_NAME | KADM5_MOD_TIME |
                            KADM5_KEY_DATA | KADM5_KVNO |
@@ -190,7 +190,7 @@ kadm5_s_randkey_principal(void *server_handle,
        *n_keys = 0;
     }
  out3:
-    hdb_free_entry(context->context, &ent);
+    hdb_free_entry(context->context, context->db, &ent);
  out2:
     (void) kadm5_log_end(context);
  out:
index 1052042af05a6db84f2a63dd1fecded42b1156cc..9143318176b73316f1ace3d895e055eab2d89a81 100644 (file)
@@ -97,7 +97,7 @@ kadm5_s_rename_principal(void *server_handle,
 {
     kadm5_server_context *context = server_handle;
     kadm5_ret_t ret;
-    hdb_entry_ex ent;
+    hdb_entry ent;
     krb5_principal oldname;
     size_t i;
 
@@ -121,14 +121,14 @@ kadm5_s_rename_principal(void *server_handle,
                                       0, &ent);
     if (ret)
        goto out2;
-    oldname = ent.entry.principal;
+    oldname = ent.principal;
 
     ret = rename_principal_hook(context, KADM5_HOOK_STAGE_PRECOMMIT,
                                0, source, target);
     if (ret)
        goto out3;
 
-    ret = _kadm5_set_modifier(context, &ent.entry);
+    ret = _kadm5_set_modifier(context, &ent);
     if (ret)
        goto out3;
     {
@@ -136,17 +136,19 @@ kadm5_s_rename_principal(void *server_handle,
        Salt salt;
        krb5_salt salt2;
        memset(&salt, 0, sizeof(salt));
-       krb5_get_pw_salt(context->context, source, &salt2);
+       ret = krb5_get_pw_salt(context->context, source, &salt2);
+        if (ret)
+            goto out3;
        salt.type = hdb_pw_salt;
        salt.salt = salt2.saltvalue;
-       for(i = 0; i < ent.entry.keys.len; i++){
-           if(ent.entry.keys.val[i].salt == NULL){
-               ent.entry.keys.val[i].salt =
-                   malloc(sizeof(*ent.entry.keys.val[i].salt));
-               if (ent.entry.keys.val[i].salt == NULL)
+       for(i = 0; i < ent.keys.len; i++){
+           if(ent.keys.val[i].salt == NULL){
+               ent.keys.val[i].salt =
+                   malloc(sizeof(*ent.keys.val[i].salt));
+               if (ent.keys.val[i].salt == NULL)
                    ret = krb5_enomem(context->context);
                 else
-                    ret = copy_Salt(&salt, ent.entry.keys.val[i].salt);
+                    ret = copy_Salt(&salt, ent.keys.val[i].salt);
                if (ret)
                    break;
            }
@@ -157,20 +159,20 @@ kadm5_s_rename_principal(void *server_handle,
        goto out3;
 
     /* Borrow target */
-    ent.entry.principal = target;
-    ret = hdb_seal_keys(context->context, context->db, &ent.entry);
+    ent.principal = target;
+    ret = hdb_seal_keys(context->context, context->db, &ent);
     if (ret)
        goto out3;
 
     /* This logs the change for iprop and writes to the HDB */
-    ret = kadm5_log_rename(context, source, &ent.entry);
+    ret = kadm5_log_rename(context, source, &ent);
 
     (void) rename_principal_hook(context, KADM5_HOOK_STAGE_POSTCOMMIT,
                                 ret, source, target);
 
  out3:
-    ent.entry.principal = oldname; /* Unborrow target */
-    hdb_free_entry(context->context, &ent);
+    ent.principal = oldname; /* Unborrow target */
+    hdb_free_entry(context->context, context->db, &ent);
 
  out2:
     (void) kadm5_log_end(context);
index 1f458258592f32f4f317933de450524c28bb02ee..c30c5d82934712a5392d748acc6e0e12ef230d5a 100644 (file)
@@ -177,6 +177,8 @@ _kadm5_set_keys2(kadm5_server_context *context,
            /* A current key; add to current key set */
            setup_Key(&key, &salt, key_data, i);
            ret = add_Keys(&keys, &key);
+            if (ret)
+                goto out;
            continue;
        }
 
index 2f8eda54c093e23f0b5bc9f8613796c242a299fc..584c194dd1838e896f7c4f99d84ab81f1ceb4605 100644 (file)
@@ -115,7 +115,7 @@ kadm5_s_setkey_principal_3(void *server_handle,
                           krb5_keyblock *keyblocks, int n_keys)
 {
     kadm5_server_context *context = server_handle;
-    hdb_entry_ex ent;
+    hdb_entry ent;
     kadm5_ret_t ret = 0;
     size_t i;
 
@@ -154,9 +154,9 @@ kadm5_s_setkey_principal_3(void *server_handle,
     }
 
     if (keepold) {
-        ret = hdb_add_current_keys_to_history(context->context, &ent.entry);
+        ret = hdb_add_current_keys_to_history(context->context, &ent);
     } else
-       ret = hdb_clear_extension(context->context, &ent.entry,
+       ret = hdb_clear_extension(context->context, &ent,
                                  choice_HDB_extension_data_hist_keys);
 
     /*
@@ -167,7 +167,7 @@ kadm5_s_setkey_principal_3(void *server_handle,
      * each ks_tuple's enctype matches the corresponding key enctype.
      */
     if (ret == 0) {
-       free_Keys(&ent.entry.keys);
+       free_Keys(&ent.keys);
        for (i = 0; i < n_keys; ++i) {
            Key k;
            Salt s;
@@ -186,22 +186,22 @@ kadm5_s_setkey_principal_3(void *server_handle,
                s.opaque = 0;
                k.salt = &s;
            }
-           if ((ret = add_Keys(&ent.entry.keys, &k)) != 0)
+           if ((ret = add_Keys(&ent.keys, &k)) != 0)
                break;
        }
     }
 
     if (ret == 0) {
-       ent.entry.kvno++;
-       ent.entry.flags.require_pwchange = 0;
-       hdb_entry_set_pw_change_time(context->context, &ent.entry, 0);
-       hdb_entry_clear_password(context->context, &ent.entry);
+       ent.kvno++;
+       ent.flags.require_pwchange = 0;
+       hdb_entry_set_pw_change_time(context->context, &ent, 0);
+       hdb_entry_clear_password(context->context, &ent);
 
        if ((ret = hdb_seal_keys(context->context, context->db,
-                                &ent.entry)) == 0
-           && (ret = _kadm5_set_modifier(context, &ent.entry)) == 0
-           && (ret = _kadm5_bump_pw_expire(context, &ent.entry)) == 0)
-           ret = kadm5_log_modify(context, &ent.entry,
+                                &ent)) == 0
+           && (ret = _kadm5_set_modifier(context, &ent)) == 0
+           && (ret = _kadm5_bump_pw_expire(context, &ent)) == 0)
+           ret = kadm5_log_modify(context, &ent,
                                    KADM5_ATTRIBUTES | KADM5_PRINCIPAL |
                                    KADM5_MOD_NAME | KADM5_MOD_TIME |
                                    KADM5_KEY_DATA | KADM5_KVNO |
@@ -212,7 +212,7 @@ kadm5_s_setkey_principal_3(void *server_handle,
                                 princ, keepold, n_ks_tuple, ks_tuple,
                                 n_keys, keyblocks);
 
-    hdb_free_entry(context->context, &ent);
+    hdb_free_entry(context->context, context->db, &ent);
     (void) kadm5_log_end(context);
     if (!context->keep_open)
        context->db->hdb_close(context->context, context->db);
index dd23aef7665a23c1c1d77009fc5debaaedb31303..50d4878ae6cdbf1f88b35b26480ddcf4a9ba0e4f 100644 (file)
@@ -2,6 +2,8 @@
 
 include $(top_srcdir)/Makefile.am.common
 
+WFLAGS += $(WFLAGS_ENUM_CONV)
+
 AM_CPPFLAGS += $(AFS_EXTRA_DEFS) $(ROKEN_RENAME)
 
 if KRB5
index 6033f2958b45418dcad04283590268631951e216..0077016f6242f0f1f4e8848aa91fca0ba36af049 100644 (file)
@@ -85,8 +85,6 @@ v5_to_kt(krb5_creds *cred, uid_t uid, struct kafs_token *kt, int local524)
            return ENOMEM;
        kt->ticket_len = cred->ticket.length;
        memcpy(kt->ticket, cred->ticket.data, kt->ticket_len);
-
-       ret = 0;
     }
 
 
index ae33ff1829940ac154a934f9bb6287b0bfbc6d37..b400626075ce06c9543062bd5cc94376177602f8 100644 (file)
@@ -106,7 +106,9 @@ int _kafs_debug; /* this should be done in a better way */
 #define SUN_PROC_POINT         8
 
 static int afs_entry_point = UNKNOWN_ENTRY_POINT;
+#if defined(AFS_SYSCALL) || defined(AFS_SYSCALL2) || defined(AFS_SYSCALL3) || defined(AFS_PIOCTL)
 static int afs_syscalls[2];
+#endif
 static char *afs_ioctlpath;
 static unsigned long afs_ioctlnum;
 
index 174fa3a6189a73faeaa023d7526749fdee65edea..5af391ed99b5414914f1594be7cf4023ecc322f9 100644 (file)
@@ -89,12 +89,16 @@ rxkad_derive_des_key(const void *in, size_t insize, char out[8])
     /* stop when 8 bit counter wraps to 0 */
     for (i = 1; i; i++) {
        HMAC_CTX_init(&mctx);
-       HMAC_Init_ex(&mctx, in, insize, EVP_md5(), NULL);
+       if (HMAC_Init_ex(&mctx, in, insize, EVP_md5(), NULL) == 0) {
+            HMAC_CTX_cleanup(&mctx);
+            return ENOMEM;
+        }
        HMAC_Update(&mctx, &i, 1);
        HMAC_Update(&mctx, label, sizeof(label));   /* includes label and separator */
        HMAC_Update(&mctx, Lbuf, 4);
        mdsize = sizeof(tmp);
        HMAC_Final(&mctx, tmp, &mdsize);
+        HMAC_CTX_cleanup(&mctx);
        memcpy(ktmp, tmp, 8);
        DES_set_odd_parity(&ktmp);
        if (!DES_is_weak_key(&ktmp)) {
@@ -205,7 +209,7 @@ _kafs_derive_des_key(krb5_enctype enctype, void *keydata, size_t keylen,
        ret = compress_parity_bits(keydata, &keylen);
        if (ret)
            return ret;
-       /* FALLTHROUGH */
+        fallthrough;
     default:
        if (enctype < 0)
            return KRB5_PROG_ETYPE_NOSUPP;
index 99171e727ce836fe293b58dcf5812d819e6ae638..c1345c28a5ab5d41cf9ab97bc40f68620c105a44 100644 (file)
@@ -2,7 +2,9 @@
 
 include $(top_srcdir)/Makefile.am.common
 
-AM_CPPFLAGS += -I../com_err -I$(srcdir)/../com_err $(INCLUDE_sqlite3) $(INCLUDE_libintl) $(INCLUDE_openssl_crypto)
+WFLAGS += $(WFLAGS_ENUM_CONV)
+
+AM_CPPFLAGS += -I../com_err -I$(srcdir)/../com_err -I../base -I$(srcdir)/../base $(INCLUDE_sqlite3) $(INCLUDE_libintl) $(INCLUDE_openssl_crypto)
 
 bin_PROGRAMS = verify_krb5_conf
 
index d32025130989396c564401df03abb67efa73c2f7..40ca0fb0bccc1bd7a76cc7dbf2e00f85b2d4d549 100644 (file)
@@ -31,6 +31,8 @@
 
 RELDIR=lib\krb5
 
+intcflags=-I$(SRCDIR) -I$(SRCDIR)\..\com_err -I$(SRCDIR)\..\base
+
 !include ../../windows/NTMakefile.w32
 
 libkrb5_OBJS =                 \
index 5bc9762632452441a33bcf4b3a3e579b09ca740d..63d56c400bf5bcde3408cb8a633fd76628d8d1e5 100644 (file)
@@ -121,10 +121,9 @@ init_ccapi(krb5_context context)
 
     if (cc_handle == NULL) {
        HEIMDAL_MUTEX_unlock(&acc_mutex);
-       if (context)
-           krb5_set_error_message(context, KRB5_CC_NOSUPP,
-                                  N_("Failed to load API cache module %s", "file"),
-                                  lib);
+        krb5_set_error_message(context, KRB5_CC_NOSUPP,
+                               N_("Failed to load API cache module %s", "file"),
+                               lib);
        return KRB5_CC_NOSUPP;
     }
 
@@ -135,10 +134,9 @@ init_ccapi(krb5_context context)
        dlsym(cc_handle, "krb5_ipc_client_clear_target");
     HEIMDAL_MUTEX_unlock(&acc_mutex);
     if (init_func == NULL) {
-       if (context)
-           krb5_set_error_message(context, KRB5_CC_NOSUPP,
-                                  N_("Failed to find cc_initialize"
-                                     "in %s: %s", "file, error"), lib, dlerror());
+        krb5_set_error_message(context, KRB5_CC_NOSUPP,
+                               N_("Failed to find cc_initialize"
+                                  "in %s: %s", "file, error"), lib, dlerror());
        dlclose(cc_handle);
        return KRB5_CC_NOSUPP;
     }
@@ -146,9 +144,8 @@ init_ccapi(krb5_context context)
     return 0;
 #else
     HEIMDAL_MUTEX_unlock(&acc_mutex);
-    if (context)
-       krb5_set_error_message(context, KRB5_CC_NOSUPP,
-                              N_("no support for shared object", ""));
+    krb5_set_error_message(context, KRB5_CC_NOSUPP,
+                           N_("no support for shared object", ""));
     return KRB5_CC_NOSUPP;
 #endif
 }
@@ -988,6 +985,7 @@ acc_end_cache_get(krb5_context context, krb5_cc_cursor cursor)
 static krb5_error_code KRB5_CALLCONV
 acc_move(krb5_context context, krb5_ccache from, krb5_ccache to)
 {
+    krb5_error_code ret;
     krb5_acc *afrom = ACACHE(from);
     krb5_acc *ato = ACACHE(to);
     int32_t error;
@@ -1011,9 +1009,10 @@ acc_move(krb5_context context, krb5_ccache from, krb5_ccache to)
     }
 
     error = (*ato->ccache->func->move)(afrom->ccache, ato->ccache);
-
-    krb5_cc_destroy(context, from);
-    return translate_cc_error(context, error);
+    ret = translate_cc_error(context, error);
+    if (ret == 0)
+        krb5_cc_destroy(context, from);
+    return ret;
 }
 
 static krb5_error_code KRB5_CALLCONV
index b53c179b72ed220eb7cae25cf063cbbaf0520628..d3196148287e72f34aa8cc1c770c3c381f243b76 100644 (file)
@@ -246,7 +246,7 @@ krb5_acl_match_file(krb5_context context,
                    ...)
 {
     krb5_error_code ret;
-    struct acl_field *acl;
+    struct acl_field *acl = NULL;
     char buf[256];
     va_list ap;
     FILE *f;
index 4d235fff4318df90e9b64cf63bcd81754aaba4a9..864c9cde884534a14c7303bbb776ba38b93c7380 100644 (file)
@@ -525,7 +525,7 @@ arange_parse_addr (krb5_context context,
            return ret;
        }
 
-       if(high.len != 1 && high.val[0].addr_type != low.val[0].addr_type) {
+       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;
@@ -543,7 +543,13 @@ arange_parse_addr (krb5_context context,
            return ret;
     }
 
-    krb5_data_alloc(&addr->address, sizeof(*a));
+    ret = krb5_data_alloc(&addr->address, sizeof(*a));
+    if (ret) {
+       krb5_free_address(context, &low0);
+       krb5_free_address(context, &high0);
+        return ret;
+    }
+
     addr->addr_type = KRB5_ADDRESS_ARANGE;
     a = addr->address.data;
 
@@ -1208,7 +1214,7 @@ krb5_parse_address(krb5_context context,
     if (error) {
        krb5_error_code ret2;
        save_errno = errno;
-       ret2 = krb5_eai_to_heim_errno(error, save_errno);
+       ret2 = krb5_eai_to_heim_errno(save_errno, error);
        krb5_set_error_message (context, ret2, "%s: %s",
                                string, gai_strerror(error));
        return ret2;
@@ -1377,12 +1383,7 @@ KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_free_addresses(krb5_context context,
                    krb5_addresses *addresses)
 {
-    size_t i;
-    for(i = 0; i < addresses->len; i++)
-       krb5_free_address(context, &addresses->val[i]);
-    free(addresses->val);
-    addresses->len = 0;
-    addresses->val = NULL;
+    free_HostAddresses(addresses);
     return 0;
 }
 
index 7bca78ab6068b5a0e960e11ab2ad0b0448ae43a7..01522dd593ab5484d41634545209278290ce7134 100644 (file)
@@ -754,6 +754,9 @@ krb_enc_test(krb5_context context)
        kb.keyvalue.data = krbencs[i].key;
 
        ret = krb5_crypto_init(context, &kb, krbencs[i].enctype, &crypto);
+       if (ret)
+           krb5_err(context, 1, ret, "krb5_crypto_init failed with %d for test %d",
+                     ret, i);
 
        cipher.length = krbencs[i].elen;
        cipher.data = krbencs[i].edata;
@@ -763,20 +766,24 @@ krb_enc_test(krb5_context context)
        ret = krb_enc(context, crypto, krbencs[i].usage, &cipher, &plain);
 
        if (ret)
-           errx(1, "krb_enc failed with %d for test %d", ret, i);
+           krb5_err(context, 1, ret, "krb_enc failed with %d for test %d",
+                     ret, i);
 
        ret = krb_enc_iov(context, crypto, krbencs[i].usage, &cipher, &plain);
        if (ret)
-           errx(1, "krb_enc_iov failed with %d for test %d", ret, i);
+           krb5_err(context, 1, ret, "krb_enc_iov failed with %d for test %d",
+                     ret, i);
 
        ret = krb_enc_iov2(context, crypto, krbencs[i].usage,
                           cipher.length, &plain);
        if (ret)
-           errx(1, "krb_enc_iov2 failed with %d for test %d", ret, i);
+           krb5_err(context, 1, ret, "krb_enc_iov2 failed with %d for test %d",
+                     ret, i);
 
        ret = krb_checksum_iov(context, crypto, krbencs[i].usage, &plain, NULL);
        if (ret)
-           errx(1, "krb_checksum_iov failed with %d for test %d", ret, i);
+            krb5_err(context, 1, ret,
+                     "krb_checksum_iov failed with %d for test %d", ret, i);
 
        if (krbencs[i].cdata) {
            krb5_data checksum;
@@ -787,7 +794,9 @@ krb_enc_test(krb5_context context)
            ret = krb_checksum_iov(context, crypto, krbencs[i].usage,
                                   &plain, &checksum);
            if (ret)
-               errx(1, "krb_checksum_iov(2) failed with %d for test %d", ret, i);
+               krb5_err(context, 1, ret,
+                         "krb_checksum_iov(2) failed with %d for test %d",
+                         ret, i);
        }
 
        krb5_crypto_destroy(context, crypto);
@@ -795,7 +804,8 @@ krb_enc_test(krb5_context context)
        ret = krb_enc_mit(context, krbencs[i].enctype, &kb,
                          krbencs[i].usage, &cipher, &plain);
        if (ret)
-           errx(1, "krb_enc_mit failed with %d for test %d", ret, i);
+           krb5_err(context, 1, ret, "krb_enc_mit failed with %d for test %d",
+                     ret, i);
     }
 
     return 0;
index 6df8defbce9ab7f674700d29de1cba6ea248c898..16eda2f6f73d3da0a00ca1a388122c2b83a219fe 100644 (file)
@@ -38,8 +38,8 @@
 #include "krb5_locl.h"
 
 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
-_krb5_principal2principalname (PrincipalName *p,
-                              const krb5_principal from)
+_krb5_principal2principalname(PrincipalName *p,
+                             krb5_const_principal from)
 {
     return copy_PrincipalName(&from->name, p);
 }
@@ -70,3 +70,93 @@ _krb5_principalname2krb5_principal (krb5_context context,
     *principal = p;
     return 0;
 }
+
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
+_krb5_ticket2krb5_principal(krb5_context context,
+                            krb5_principal *principal,
+                            const EncTicketPart *ticket,
+                            const AuthorizationData *authenticator_ad)
+{
+    krb5_error_code ret;
+    krb5_principal p = NULL;
+
+    *principal = NULL;
+
+    ret = _krb5_principalname2krb5_principal(context,
+                                             &p,
+                                             ticket->cname,
+                                             ticket->crealm);
+    if (ret == 0 &&
+        (p->nameattrs = calloc(1, sizeof(p->nameattrs[0]))) == NULL)
+        ret = krb5_enomem(context);
+    if (ret == 0)
+        p->nameattrs->authenticated = 1;
+    if (ret == 0 &&
+        (p->nameattrs->source =
+         calloc(1, sizeof(p->nameattrs->source[0]))) == NULL)
+        ret = krb5_enomem(context);
+    if (ret == 0) {
+        p->nameattrs->source->element =
+            choice_PrincipalNameAttrSrc_enc_ticket_part;
+        ret = copy_EncTicketPart(ticket,
+                                 &p->nameattrs->source->u.enc_ticket_part);
+        /* NOTE: we don't want to keep a copy of the session key here! */
+        if (ret == 0)
+            der_free_octet_string(&p->nameattrs->source->u.enc_ticket_part.key.keyvalue);
+    }
+    if (ret == 0 && authenticator_ad) {
+        p->nameattrs->authenticator_ad =
+            calloc(1, sizeof(p->nameattrs->authenticator_ad[0]));
+        if (p->nameattrs->authenticator_ad == NULL)
+            ret = krb5_enomem(context);
+        if (ret == 0)
+            ret = copy_AuthorizationData(authenticator_ad,
+                                         p->nameattrs->authenticator_ad);
+    }
+
+    if (ret == 0)
+        *principal = p;
+    else
+        krb5_free_principal(context, p);
+    return ret;
+}
+
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
+_krb5_kdcrep2krb5_principal(krb5_context context,
+                            krb5_principal *principal,
+                            const EncKDCRepPart *kdcrep)
+{
+    krb5_error_code ret;
+    krb5_principal p = NULL;
+
+    *principal = NULL;
+
+    ret = _krb5_principalname2krb5_principal(context,
+                                             &p,
+                                             kdcrep->sname,
+                                             kdcrep->srealm);
+    if (ret == 0 &&
+        (p->nameattrs = calloc(1, sizeof(p->nameattrs[0]))) == NULL)
+        ret = krb5_enomem(context);
+    if (ret == 0)
+        p->nameattrs->authenticated = 1;
+    if (ret == 0 &&
+        (p->nameattrs->source =
+         calloc(1, sizeof(p->nameattrs->source[0]))) == NULL)
+        ret = krb5_enomem(context);
+    if (ret == 0) {
+        p->nameattrs->source->element =
+            choice_PrincipalNameAttrSrc_enc_kdc_rep_part;
+        ret = copy_EncKDCRepPart(kdcrep,
+                                 &p->nameattrs->source->u.enc_kdc_rep_part);
+        /* NOTE: we don't want to keep a copy of the session key here! */
+        if (ret == 0)
+            der_free_octet_string(&p->nameattrs->source->u.enc_kdc_rep_part.key.keyvalue);
+    }
+
+    if (ret == 0)
+        *principal = p;
+    else
+        krb5_free_principal(context, p);
+    return ret;
+}
index 43c762b7699b2521dc240aafab085ce53b5f0e22..8b43b63706c9e10ede61f8692695ffb8551c7095 100644 (file)
@@ -557,9 +557,8 @@ krb5_auth_con_getauthenticator(krb5_context context,
     if (*authenticator == NULL)
        return krb5_enomem(context);
 
-    copy_Authenticator(auth_context->authenticator,
-                      *authenticator);
-    return 0;
+    return copy_Authenticator(auth_context->authenticator,
+                              *authenticator);
 }
 
 
index 1920796ffc3c8627ed11ca2518dd686b6145878e..75083f8284083497d615c150c4f4e3f22b0b503a 100644 (file)
@@ -514,7 +514,7 @@ krb5_cc_get_subsidiary(krb5_context context, krb5_ccache id)
     const char *name = NULL;
 
     if (id->ops->version >= KRB5_CC_OPS_VERSION_5
-       && id->ops->get_name_2 == NULL)
+       && id->ops->get_name_2 != NULL)
         (void) id->ops->get_name_2(context, id, NULL, NULL, &name);
     return name;
 }
@@ -822,6 +822,17 @@ krb5_cc_configured_default_name(krb5_context context)
     return context->configured_default_cc_name = expanded;
 }
 
+KRB5_LIB_FUNCTION char * KRB5_LIB_CALL
+krb5_cccol_get_default_ccname(krb5_context context)
+{
+    const char *cfg = get_default_cc_type(context, 1);
+    char *cccol_default_ccname;
+    const krb5_cc_ops *ops = krb5_cc_get_prefix_ops(context, cfg);
+
+    (void) (*ops->get_default_name)(context, &cccol_default_ccname);
+    return cccol_default_ccname;
+}
+
 /**
  * Open the default ccache in `id'.
  *
@@ -923,7 +934,7 @@ krb5_cc_destroy(krb5_context context,
     /*
      * Destroy associated hx509 PKIX credential store created by krb5_kx509*().
      */
-    if ((ret = krb5_cc_get_config(context, id, NULL, "kx509store", &d)) == 0) {
+    if (krb5_cc_get_config(context, id, NULL, "kx509store", &d) == 0) {
         char *name;
 
         if ((name = strndup(d.data, d.length)) == NULL) {
@@ -1001,7 +1012,6 @@ krb5_cc_close(krb5_context context,
                 _krb5_debug(context, 2, "failed to fetch a certificate");
             else
                 _krb5_debug(context, 2, "fetched a certificate");
-            ret = 0;
         }
     }
 
@@ -1607,8 +1617,7 @@ krb5_cc_cache_match (krb5_context context,
     } else if (cache == NULL) {
        char *str;
 
-       krb5_unparse_name(context, client, &str);
-
+       (void) krb5_unparse_name(context, client, &str);
        krb5_set_error_message(context, KRB5_CC_NOTFOUND,
                               N_("Principal %s not found in any "
                                  "credential cache", ""),
@@ -1653,7 +1662,8 @@ krb5_cc_move(krb5_context context, krb5_ccache from, krb5_ccache to)
         ret = (*to->ops->move)(context, from, to);
         if (ret == 0)
             return 0;
-        if (ret != EXDEV && ret != ENOTSUP)
+        if (ret != EXDEV && ret != ENOTSUP && ret != KRB5_CC_NOSUPP &&
+            ret != KRB5_FCC_INTERNAL)
             return ret;
         /* Fallback to high-level copy */
     }   /* Else        high-level copy */
@@ -1766,7 +1776,8 @@ krb5_cc_set_config(krb5_context context, krb5_ccache id,
 
     /* Remove old configuration */
     ret = krb5_cc_remove_cred(context, id, 0, &cred);
-    if (ret && ret != KRB5_CC_NOTFOUND)
+    if (ret && ret != KRB5_CC_NOTFOUND && ret != KRB5_CC_NOSUPP &&
+        ret != KRB5_FCC_INTERNAL)
         goto out;
 
     if (data) {
index 51faf8de99d63c89102214eb2f0c74ee5af75b6c..4040a983518e77b55266a9f6a64256e08d409591 100644 (file)
@@ -106,7 +106,7 @@ init_context_from_config_file(krb5_context context)
     krb5_error_code ret;
     const char * tmp;
     char **s;
-    krb5_enctype *tmptypes;
+    krb5_enctype *tmptypes = NULL;
 
     INIT_FIELD(context, time, max_skew, 5 * 60, "clockskew");
     INIT_FIELD(context, time, kdc_timeout, 30, "kdc_timeout");
@@ -246,10 +246,10 @@ init_context_from_config_file(krb5_context context)
     if (context->flags & KRB5_CTX_F_REPORT_CANONICAL_CLIENT_NAME)
        context->flags |= KRB5_CTX_F_CHECK_PAC;
 
-    if (context->default_cc_name)
-       free(context->default_cc_name);
+    free(context->default_cc_name);
     context->default_cc_name = NULL;
     context->default_cc_name_set = 0;
+    free(context->configured_default_cc_name);
     context->configured_default_cc_name = NULL;
 
     tmp = secure_getenv("KRB5_TRACE");
@@ -646,12 +646,9 @@ KRB5_LIB_FUNCTION void KRB5_LIB_CALL
 krb5_free_context(krb5_context context)
 {
     _krb5_free_name_canon_rules(context, context->name_canon_rules);
-    if (context->default_cc_name)
-       free(context->default_cc_name);
-    if (context->default_cc_name_env)
-       free(context->default_cc_name_env);
-    if (context->configured_default_cc_name)
-       free(context->configured_default_cc_name);
+    free(context->default_cc_name);
+    free(context->default_cc_name_env);
+    free(context->configured_default_cc_name);
     free(context->etypes);
     free(context->cfg_etypes);
     free(context->etypes_des);
index a16b83cb0e070f37deb43634daf6bdf8e31f6927..a03cdca2ebc1149d9065223681de5134949652e7 100644 (file)
@@ -137,8 +137,11 @@ _krb5_evp_hmac_iov(krb5_context context,
     if (ctx == NULL)
         return krb5_enomem(context);
 
-    HMAC_Init_ex(ctx, key->key->keyvalue.data, key->key->keyvalue.length,
-                 md, engine);
+    if (HMAC_Init_ex(ctx, key->key->keyvalue.data, key->key->keyvalue.length,
+                     md, engine) == 0) {
+        HMAC_CTX_free(ctx);
+        return krb5_enomem(context);
+    }
 
     for (i = 0; i < niov; i++) {
         if (_krb5_crypto_iov_should_sign(&iov[i])) {
index 524b2e78681db532c2cd436a5a10e2a214558af9..2fb4f0620f763df4d23e9347881481db6c422550 100644 (file)
@@ -2152,7 +2152,10 @@ krb5_crypto_length(krb5_context context,
            *len = 0;
        return 0;
     case KRB5_CRYPTO_TYPE_TRAILER:
-       *len = CHECKSUMSIZE(crypto->et->keyed_checksum);
+        if (crypto->et->keyed_checksum)
+            *len = CHECKSUMSIZE(crypto->et->keyed_checksum);
+        else
+            *len = 0;
        return 0;
     case KRB5_CRYPTO_TYPE_CHECKSUM:
        if (crypto->et->keyed_checksum)
@@ -2572,7 +2575,7 @@ krb5_crypto_init(krb5_context context,
     ALLOC(*crypto, 1);
     if (*crypto == NULL)
        return krb5_enomem(context);
-    if(etype == (krb5_enctype)ETYPE_NULL)
+    if(etype == ETYPE_NULL)
        etype = key->keytype;
     (*crypto)->et = _krb5_find_enctype(etype);
     if((*crypto)->et == NULL || ((*crypto)->et->flags & F_DISABLED)) {
index eafc4520b9e0f96cc0c80539b7df55b6c3f5ab02..abfa0531f0efd6dafa83157193d80e3196811c41 100644 (file)
@@ -200,9 +200,12 @@ krb5_copy_data(krb5_context context,
 KRB5_LIB_FUNCTION int KRB5_LIB_CALL
 krb5_data_cmp(const krb5_data *data1, const krb5_data *data2)
 {
-    if (data1->length != data2->length)
+    size_t len = data1->length < data2->length ? data1->length : data2->length;
+    int cmp = memcmp(data1->data, data2->data, len);
+
+    if (cmp == 0)
        return data1->length - data2->length;
-    return memcmp(data1->data, data2->data, data1->length);
+    return cmp;
 }
 
 /**
index 22183efcafbe41374974c38485fe5b0a4a99840e..af88aed91561861506eebcbf3571c1b49bcdab35 100644 (file)
@@ -452,7 +452,7 @@ dcc_resolve_2(krb5_context context,
     /* Strip off extra slashes on the end */
     for (len = strlen(dc->dir);
          len && ISPATHSEP(dc->dir[len - 1]);
-         len -= len ? 1 : 0)
+         len--)
         dc->dir[len - 1] = '\0';
 
     /* If we got here then `dc->dir' and `dc->sub' must both be set */
@@ -676,17 +676,17 @@ dcc_get_cache_first(krb5_context context, krb5_cc_cursor *cursor)
     /* Strip off extra slashes on the end */
     for (len = strlen(iter->dc->dir);
          len && ISPATHSEP(iter->dc->dir[len - 1]);
-         len -= len ? 1 : 0) {
+         len--) {
         iter->dc->dir[len - 1] = '\0';
     }
 
     if ((iter->d = opendir(iter->dc->dir)) == NULL) {
-        free(iter->dc->dir);
-        free(iter->dc);
-        free(iter);
        krb5_set_error_message(context, KRB5_CC_FORMAT,
                                N_("Can't open DIR %s: %s", ""),
                                iter->dc->dir, strerror(errno));
+        free(iter->dc->dir);
+        free(iter->dc);
+        free(iter);
        return KRB5_CC_FORMAT;
     }
 
@@ -709,8 +709,8 @@ dcc_get_cache_next(krb5_context context, krb5_cc_cursor cursor, krb5_ccache *id)
 
     /* Emit primary subsidiary first */
     if (iter->first &&
-        (ret = get_default_cache(context, iter->dc, NULL, &iter->primary)) == 0 &&
-        is_filename_cacheish(iter->primary)) {
+        get_default_cache(context, iter->dc, NULL, &iter->primary) == 0 &&
+        iter->primary && is_filename_cacheish(iter->primary)) {
         iter->first = 0;
         ret = KRB5_CC_END;
         if (asprintf(&p, "FILE:%s/%s", iter->dc->dir, iter->primary) > -1 && p != NULL &&
index bcd07e3c2d83957e643cb821664f7080aad6ab9e..0efa162702cbc93fe8206295e47a32845326d177 100644 (file)
@@ -324,15 +324,13 @@ krb5_keytab_key_proc (krb5_context context,
 
     ret = krb5_kt_get_entry (context, real_keytab, principal,
                             0, enctype, &entry);
+    if (ret == 0) {
+        ret = krb5_copy_keyblock (context, &entry.keyblock, key);
+        krb5_kt_free_entry(context, &entry);
+    }
 
     if (keytab == NULL)
        krb5_kt_close (context, real_keytab);
-
-    if (ret)
-       return ret;
-
-    ret = krb5_copy_keyblock (context, &entry.keyblock, key);
-    krb5_kt_free_entry(context, &entry);
     return ret;
 }
 
index 371b07ff5833d3c2ac6db111895933c92432b385..b4444e5a2cdce54e0ebb20e2ccca7e535e17cf0e 100644 (file)
 
 #include "krb5_locl.h"
 
+#undef krb5_enomem
 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_enomem(krb5_context context)
 {
     krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
     return ENOMEM;
 }
-
index 0e42f51bc211af0c63c0980e5b95ba151f5d0ba4..da86b375f83c6dca20d6f7a46586f4629b307892 100644 (file)
@@ -95,15 +95,16 @@ krb5_vset_error_message(krb5_context context, krb5_error_code ret,
                         const char *fmt, va_list args)
     __attribute__ ((__format__ (__printf__, 3, 0)))
 {
-    if (context) {
-        const char *msg;
-
-        heim_vset_error_message(context->hcontext, ret, fmt, args);
-        msg = heim_get_error_message(context->hcontext, ret);
-        if (msg) {
-            _krb5_debug(context, 100, "error message: %s: %d", msg, ret);
-            heim_free_error_message(context->hcontext, msg);
-        }
+    const char *msg;
+
+    if (context == NULL)
+       return;
+
+    heim_vset_error_message(context->hcontext, ret, fmt, args);
+    msg = heim_get_error_message(context->hcontext, ret);
+    if (msg) {
+       _krb5_debug(context, 100, "error message: %s: %d", msg, ret);
+       heim_free_error_message(context->hcontext, msg);
     }
 }
 
index a1f4dfcfcf78565e8bedf736148dd8ab31914d63..a0402350d0f3bd1979be50a33d7e6220424a9c97 100644 (file)
@@ -55,8 +55,8 @@ _krb5_expand_path_tokens(krb5_context context,
                         int filepath,
                         char **ppath_out)
 {
-    return heim_expand_path_tokens(context->hcontext, path_in, filepath,
-                                   ppath_out, NULL);
+    return heim_expand_path_tokens(context ? context->hcontext : NULL, path_in,
+                                   filepath, ppath_out, NULL);
 }
 
 /**
index dcca7cc5eec3f0cf1300f9c73e1b2ff5ab64da58..617446c363424324338d23ba831e75d63daa4761 100644 (file)
@@ -138,6 +138,12 @@ make_local_fast_ap_fxarmor(krb5_context context,
     krb5_data empty;
     krb5_const_realm tgs_realm;
 
+    if (armor_ccache == NULL) {
+       krb5_set_error_message(context, EINVAL,
+                              "Armor credential cache required");
+       return EINVAL;
+    }
+
     krb5_data_zero(&empty);
     memset(&cred, 0, sizeof(cred));
 
@@ -225,6 +231,8 @@ make_fast_ap_fxarmor(krb5_context context,
     KrbFastArmor *fxarmor = NULL;
     krb5_error_code ret;
 
+    *armor = NULL;
+
     ALLOC(fxarmor, 1);
     if (fxarmor == NULL) {
        ret = ENOMEM;
@@ -429,6 +437,7 @@ _krb5_fast_create_armor(krb5_context context,
            if (state->armor_data) {
                free_KrbFastArmor(state->armor_data);
                free(state->armor_data);
+                state->armor_data = NULL;
            }
            ret = make_fast_ap_fxarmor(context, state, realm,
                                       &state->armor_data);
@@ -539,8 +548,6 @@ _krb5_fast_wrap_req(krb5_context context,
     if (state->type == choice_PA_FX_FAST_REQUEST_armored_data) {
        fxreq.u.armored_data.armor = state->armor_data;
        state->armor_data = NULL;
-       if (ret)
-           goto out;
 
        heim_assert(state->armor_crypto != NULL,
                    "FAST armor key missing when FAST started");
@@ -850,7 +857,7 @@ _krb5_fast_anon_pkinit_step(krb5_context context,
 
     ret = krb5_cc_set_config(context, ccache, cred.server,
                             "fast_avail", &data);
-    if (ret)
+    if (ret && ret != KRB5_CC_NOSUPP)
        return ret;
 
     if (_krb5_pk_is_kdc_verified(context, state->anon_pkinit_opt))
index 08d4f4217e4c6855315a91b63c3bf3ddce18260a..30dff35893b31079abac03fb8070ad929a976aec 100644 (file)
@@ -477,7 +477,6 @@ fcc_open(krb5_context context,
         return krb5_einval(context, 2);
 
     if ((flags & O_EXCL)) {
-        flags &= ~O_EXCL;
         /*
          * FIXME Instead of mkostemp()... we could instead try to use a .new
          * file... with care.  Or the O_TMPFILE / linkat() extensions.  We need
@@ -1177,7 +1176,7 @@ fcc_remove_cred(krb5_context context,
        krb5_free_cred_contents(context, &found_cred);
     }
     ret2 = krb5_cc_end_seq_get(context, id, &cursor);
-    if (ret == 0)
+    if (ret2)  /* not expected to fail */
        return ret2;
     if (ret == KRB5_CC_END)
        return 0;
@@ -1548,8 +1547,10 @@ static krb5_error_code KRB5_CALLCONV
 fcc_move(krb5_context context, krb5_ccache from, krb5_ccache to)
 {
     krb5_error_code ret = 0;
+    krb5_fcache *f = FCACHE(from);
+    krb5_fcache *t = FCACHE(to);
 
-    if (TMPFILENAME(from)) {
+    if (f->tmpfn) {
         /*
          * If `from' has a temp file and we haven't renamed it into place yet,
          * then we should rename TMPFILENAME(from) to FILENAME(to).
@@ -1557,13 +1558,13 @@ fcc_move(krb5_context context, krb5_ccache from, krb5_ccache to)
          * This can only happen if we're moving a ccache where only cc config
          * entries, or no entries, have been written.  That's not likely.
          */
-        if (rk_rename(TMPFILENAME(from), FILENAME(to))) {
+        if (rk_rename(f->tmpfn, t->filename)) {
             ret = errno;
         } else {
-            free(TMPFILENAME(from));
-            TMPFILENAME(from) = NULL;
+            free(f->tmpfn);
+            f->tmpfn = NULL;
         }
-    } else if ((ret = rk_rename(FILENAME(from), FILENAME(to)))) {
+    } else if (rk_rename(f->filename, t->filename)) {
         ret = errno;
     }
     /*
index 07047461ee7787a6dc7904c85fe8a88a3e6cfdf3..767d94cf7fe64cd9b82ffe52770f86c12255146e 100644 (file)
@@ -58,7 +58,7 @@ krb5_generate_subkey_extended(krb5_context context,
     if (*subkey == NULL)
        return krb5_enomem(context);
 
-    if (etype == (krb5_enctype)ETYPE_NULL)
+    if (etype == ETYPE_NULL)
        etype = key->keytype; /* use session key etype */
 
     /* XXX should we use the session key as input to the RF? */
index 3072cbf5f6bf53b67955ec34d1bb375656e5115e..ec757797866d44a6117e4662fffae3d6ff09c7b4 100644 (file)
@@ -50,7 +50,7 @@ get_cred_kdc_capath(krb5_context, krb5_kdc_flags,
 
 static krb5_error_code
 make_pa_tgs_req(krb5_context context,
-               krb5_auth_context ac,
+               krb5_auth_context *ac,
                KDC_REQ_BODY *body,
                krb5_ccache ccache,
                krb5_creds *creds,
@@ -71,7 +71,7 @@ make_pa_tgs_req(krb5_context context,
 
     in_data.length = len;
     in_data.data   = buf;
-    ret = _krb5_mk_req_internal(context, &ac, 0, &in_data,
+    ret = _krb5_mk_req_internal(context, ac, 0, &in_data,
                                creds, tgs_req,
                                KRB5_KU_TGS_REQ_AUTH_CKSUM,
                                KRB5_KU_TGS_REQ_AUTH);
@@ -114,19 +114,20 @@ set_auth_data (krb5_context context,
            req_body->enc_authorization_data = NULL;
            return ret;
        }
-       krb5_encrypt_EncryptedData(context,
-                                  crypto,
-                                  KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY,
-                                  buf,
-                                  len,
-                                  0,
-                                  req_body->enc_authorization_data);
+        ret = krb5_encrypt_EncryptedData(context,
+                                         crypto,
+                                         KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY,
+                                         buf,
+                                         len,
+                                         0,
+                                         req_body->enc_authorization_data);
        free (buf);
        krb5_crypto_destroy(context, crypto);
+        return ret;
     } else {
        req_body->enc_authorization_data = NULL;
+        return 0;
     }
-    return 0;
 }
 
 /*
@@ -286,7 +287,7 @@ init_tgs_req (krb5_context context,
     }
 
     ret = make_pa_tgs_req(context,
-                         ac,
+                         &ac,
                          &t->req_body,
                          ccache,
                          krbtgt,
@@ -516,7 +517,7 @@ get_cred_kdc(krb5_context context,
     TGS_REQ req;
     krb5_data enc;
     krb5_data resp;
-    krb5_kdc_rep rep = {0};
+    krb5_kdc_rep rep;
     krb5_error_code ret;
     unsigned nonce;
     krb5_keyblock *subkey = NULL;
@@ -524,6 +525,7 @@ get_cred_kdc(krb5_context context,
     Ticket second_ticket_data;
     METHOD_DATA padata;
 
+    memset(&rep, 0, sizeof(rep));
     krb5_data_zero(&resp);
     krb5_data_zero(&enc);
     padata.val = NULL;
@@ -777,7 +779,9 @@ get_cred_kdc_address(krb5_context context,
                                "no-addresses", FALSE, &noaddr);
 
        if (!noaddr) {
-           krb5_get_all_client_addrs(context, &addresses);
+           ret = krb5_get_all_client_addrs(context, &addresses);
+            if (ret)
+                return ret;
            /* XXX this sucks. */
            addrs = &addresses;
            if(addresses.len == 0)
@@ -1375,6 +1379,8 @@ _krb5_get_cred_kdc_any(krb5_context context,
     krb5_deltat offset;
     krb5_data data;
 
+    krb5_data_zero(&data);
+
     /*
      * If we are using LKDC, lets pull out the addreses from the
      * ticket and use that.
@@ -1382,23 +1388,19 @@ _krb5_get_cred_kdc_any(krb5_context context,
     
     ret = krb5_cc_get_config(context, ccache, NULL, "lkdc-hostname", &data);
     if (ret == 0) {
-       kdc_hostname = malloc(data.length + 1);
-       if (kdc_hostname == NULL)
-           return krb5_enomem(context);
-       
-       memcpy(kdc_hostname, data.data, data.length);
-       kdc_hostname[data.length] = '\0';
+       if ((kdc_hostname = strndup(data.data, data.length)) == NULL) {
+            ret = krb5_enomem(context);
+            goto out;
+        }
        krb5_data_free(&data);
     }
 
     ret = krb5_cc_get_config(context, ccache, NULL, "sitename", &data);
     if (ret == 0) {
-       sitename = malloc(data.length + 1);
-       if (sitename == NULL)
-           return krb5_enomem(context);
-
-       memcpy(sitename, data.data, data.length);
-       sitename[data.length] = '\0';
+       if ((sitename = strndup(data.data, data.length)) == NULL) {
+           ret = krb5_enomem(context);
+            goto out;
+        }
        krb5_data_free(&data);
     }
 
@@ -1441,9 +1443,9 @@ _krb5_get_cred_kdc_any(krb5_context context,
                                 out_creds);
     
 out:
+    krb5_data_free(&data);
     free(kdc_hostname);
     free(sitename);
-
     return ret;
 }
 
index d6a1a9345dca2cdc7d887360e340f2e2d69d8713..c19fc6992816690bd333c860fb75615e9d3707b4 100644 (file)
@@ -115,7 +115,7 @@ add_padata(krb5_context context,
     if (!enctypes) {
        enctypes = context->etypes;
        netypes = 0;
-       for (ep = enctypes; *ep != (krb5_enctype)ETYPE_NULL; ep++)
+       for (ep = enctypes; *ep != ETYPE_NULL; ep++)
            netypes++;
     }
     pa2 = realloc (md->val, (md->len + netypes) * sizeof(*md->val));
index 4ad5deba0900d14b3a87d2d5f472642f1543a961..e42fcf10bc1781eb6237d37bf676d9e08beae42c 100644 (file)
@@ -35,7 +35,8 @@
  */
 
 #include "krb5_locl.h"
-#include "../base/heimbasepriv.h" /* XXX */
+
+#include <heimbasepriv.h>
 
 struct pa_info_data {
     krb5_enctype etype;
@@ -431,8 +432,8 @@ krb5_init_creds_warn_user(krb5_context context,
        if (!suppress) {
            char *str = NULL, *p = NULL;
            int aret;
-           krb5_enctype_to_string(context, weak_enctype, &str);
 
+           (void) krb5_enctype_to_string(context, weak_enctype, &str);
            aret = asprintf(&p, "Encryption type %s(%d) used for authentication is weak and will be deprecated",
                            str ? str : "unknown", weak_enctype);
            if (aret >= 0 && p) {
@@ -467,7 +468,9 @@ get_init_creds_common(krb5_context context,
     if (options == NULL) {
        const char *realm = krb5_principal_get_realm(context, client);
 
-        krb5_get_init_creds_opt_alloc (context, &default_opt);
+        ret = krb5_get_init_creds_opt_alloc(context, &default_opt);
+        if (ret)
+            return ret;
        options = default_opt;
        krb5_get_init_creds_opt_set_default_flags(context, NULL, realm, options);
     }
@@ -501,11 +504,8 @@ get_init_creds_common(krb5_context context,
     ctx->pre_auth_types = NULL;
 
     ret = init_cred(context, &ctx->cred, client, start_time, options);
-    if (ret) {
-       if (default_opt)
-           krb5_get_init_creds_opt_free(context, default_opt);
-       return ret;
-    }
+    if (ret)
+        goto out;
 
     ret = krb5_init_creds_set_service(context, ctx, NULL);
     if (ret)
@@ -579,10 +579,6 @@ get_init_creds_common(krb5_context context,
     else
        ctx->runflags.change_password_prompt = ctx->prompter != NULL;
 
-    if (default_opt)
-        krb5_get_init_creds_opt_free(context, default_opt);
-    return 0;
-
  out:
     if (default_opt)
        krb5_get_init_creds_opt_free(context, default_opt);
@@ -703,8 +699,7 @@ change_password (krb5_context context,
        strlcpy (newpw, buf1, newpw_sz);
        ret = 0;
     } else {
-       ret = ENOTTY;
-       krb5_set_error_message(context, ret,
+       krb5_set_error_message(context, ret = KRB5_CHPW_FAIL,
                               N_("failed changing password: %s", ""), p);
     }
     free (p);
@@ -1089,7 +1084,7 @@ add_enc_ts_padata(krb5_context context,
     if (!enctypes) {
        enctypes = context->etypes;
        netypes = 0;
-       for (ep = enctypes; *ep != (krb5_enctype)ETYPE_NULL; ep++)
+       for (ep = enctypes; *ep != ETYPE_NULL; ep++)
            netypes++;
     }
 
@@ -1427,12 +1422,13 @@ pa_gss_step(krb5_context context,
        char *from = NULL;
        char *to = NULL;
 
-       if (krb5_unparse_name(context, ctx->cred.client, &from) == 0 &&
-           krb5_unparse_name(context, cname, &to) == 0) {
-           _krb5_debug(context, 1, "pa_gss_step: %s as %s",
-                       from, to);
+       if (krb5_unparse_name(context, ctx->cred.client, &from) == 0) {
+           if (krb5_unparse_name(context, cname, &to) == 0) {
+               _krb5_debug(context, 1, "pa_gss_step: %s as %s",
+                           from, to);
+               krb5_xfree(to);
+           }
            krb5_xfree(from);
-           krb5_xfree(to);
        }
     }
 
@@ -1661,11 +1657,6 @@ enc_chal_step(krb5_context context, krb5_init_creds_context ctx, void *pa_ctx, P
        EncryptedData enc_data;
        size_t size;
 
-       if (ret) {
-           _krb5_debug(context, 5, "enc-chal: failed to create reply key");
-           return ret;
-       }
-
        _krb5_debug(context, 5, "ENC_CHAL rep key");
 
        if (ctx->fast_state.strengthen_key == NULL) {
@@ -2139,28 +2130,30 @@ process_pa_info(krb5_context context,
     return p;
 }
 
-static void
+static krb5_error_code
 pa_announce(krb5_context context,
            int types,
            krb5_init_creds_context ctx,
            METHOD_DATA *in_md,
            METHOD_DATA *out_md)
 {
+    krb5_error_code ret = 0;
     size_t n;
 
-    for (n = 0; n < sizeof(patypes)/sizeof(patypes[0]); n++) {
+    for (n = 0; ret == 0 && n < sizeof(patypes)/sizeof(patypes[0]); n++) {
        if ((patypes[n].flags & types) == 0)
            continue;
 
        if (patypes[n].step)
            patypes[n].step(context, ctx, NULL, NULL, NULL, NULL, NULL, in_md, out_md);
        else
-           krb5_padata_add(context, out_md, patypes[n].type, NULL, 0);
+           ret = krb5_padata_add(context, out_md, patypes[n].type, NULL, 0);
     }
+    return ret;
 }
 
 
-static void
+static void HEIM_CALLCONV
 mech_dealloc(void *ctx)
 {
     struct pa_auth_mech *pa_mech = ctx;
@@ -2406,8 +2399,7 @@ process_pa_data_to_md(krb5_context context,
      * Send announcement (what we support) and configuration (user
      * introduced behavior change)
      */
-
-    pa_announce(context, PA_F_ANNOUNCE|PA_F_CONFIG, ctx, in_md, *out_md);
+    ret = pa_announce(context, PA_F_ANNOUNCE|PA_F_CONFIG, ctx, in_md, *out_md);
 
     /*
      *
@@ -2418,7 +2410,7 @@ process_pa_data_to_md(krb5_context context,
        *out_md = NULL;
     }
 
-    return 0;
+    return ret;
 }
 
 static krb5_error_code
@@ -2634,7 +2626,11 @@ krb5_init_creds_set_service(krb5_context context,
        ret = krb5_parse_name (context, service, &principal);
        if (ret)
            return ret;
-       krb5_principal_set_realm (context, principal, client_realm);
+       ret = krb5_principal_set_realm (context, principal, client_realm);
+       if (ret) {
+           krb5_free_principal(context, principal);
+           return ret;
+       }
     } else {
        ret = krb5_make_principal(context, &principal,
                                  client_realm, KRB5_TGS_NAME, client_realm,
@@ -2704,27 +2700,23 @@ keytab_key_proc(krb5_context context, krb5_enctype enctype,
     krb5_keytab keytab = args->keytab;
     krb5_principal principal = args->principal;
     krb5_error_code ret;
-    krb5_keytab real_keytab;
+    krb5_keytab real_keytab = NULL;
     krb5_keytab_entry entry;
 
     if (keytab == NULL) {
        ret = krb5_kt_default(context, &real_keytab);
        if (ret)
            return ret;
-    } else
-       real_keytab = keytab;
-
-    ret = krb5_kt_get_entry (context, real_keytab, principal,
-                            0, enctype, &entry);
-
-    if (keytab == NULL)
-       krb5_kt_close (context, real_keytab);
+        keytab = real_keytab;
+    }
 
-    if (ret)
-       return ret;
+    ret = krb5_kt_get_entry (context, keytab, principal, 0, enctype, &entry);
+    if (ret == 0) {
+        ret = krb5_copy_keyblock(context, &entry.keyblock, key);
+        krb5_kt_free_entry(context, &entry);
+    }
 
-    ret = krb5_copy_keyblock (context, &entry.keyblock, key);
-    krb5_kt_free_entry(context, &entry);
+    krb5_kt_close(context, real_keytab);
     return ret;
 }
 
@@ -2870,25 +2862,9 @@ krb5_init_creds_set_fast_ccache(krb5_context context,
                                krb5_init_creds_context ctx,
                                krb5_ccache fast_ccache)
 {
-    krb5_creds *cred = NULL;
-    krb5_error_code ret;
-    krb5_data data;
-
-    ret = _krb5_get_krbtgt(context, fast_ccache, NULL, &cred);
-    if (ret)
-       return ret;
-
-    ret = krb5_cc_get_config(context, fast_ccache, cred->server,
-                            "fast_avail", &data);
-    krb5_free_creds(context, cred);
-    if (ret == 0) {
-       ctx->fast_state.armor_ccache = fast_ccache;
-       ctx->fast_state.flags |= KRB5_FAST_REQUIRED;
-       ctx->fast_state.flags |= KRB5_FAST_KDC_VERIFIED;
-    } else {
-       krb5_set_error_message(context, EINVAL, N_("FAST not available for the KDC in the armor ccache", ""));
-       return EINVAL;
-    }
+    ctx->fast_state.armor_ccache = fast_ccache;
+    ctx->fast_state.flags |= KRB5_FAST_REQUIRED;
+    ctx->fast_state.flags |= KRB5_FAST_KDC_VERIFIED;
     return 0;
 }
 
@@ -2956,6 +2932,19 @@ krb5_init_creds_set_fast_anon_pkinit(krb5_context context,
     return 0;
 }
 
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
+_krb5_init_creds_set_fast_anon_pkinit_optimistic(krb5_context context,
+                                                 krb5_init_creds_context ctx)
+{
+    if (ctx->fast_state.armor_ccache)
+       return EINVAL;
+
+    ctx->fast_state.flags |= KRB5_FAST_REQUIRED;
+    ctx->fast_state.flags |= KRB5_FAST_ANON_PKINIT_ARMOR;
+    ctx->fast_state.flags |= KRB5_FAST_OPTIMISTIC;
+    return 0;
+}
+
 static size_t
 available_padata_count(METHOD_DATA *md)
 {
@@ -3352,16 +3341,6 @@ init_creds_step(krb5_context context,
                    goto out;
                }
 
-               if ((ctx->fast_state.flags & KRB5_FAST_OPTIMISTIC) == 0) {
-                   _krb5_debug(context, 10, "Preauth failed");
-                   goto out;
-               }
-
-               _krb5_debug(context, 10, "preauth failed with optimistic FAST, trying w/o FAST");
-
-               ctx->fast_state.flags &= ~KRB5_FAST_OPTIMISTIC;
-               ctx->fast_state.flags |= KRB5_FAST_DISABLED;
-
            retry:
                pa_restart(context, ctx);
 
@@ -3370,6 +3349,8 @@ init_creds_step(krb5_context context,
                            "Some other error %d failed with optimistic FAST, trying w/o FAST", ret);
 
                ctx->fast_state.flags &= ~KRB5_FAST_OPTIMISTIC;
+                ctx->fast_state.flags &= ~KRB5_FAST_REQUIRED;
+                ctx->fast_state.flags &= ~KRB5_FAST_ANON_PKINIT_ARMOR;
                ctx->fast_state.flags |= KRB5_FAST_DISABLED;
                pa_restart(context, ctx);
            } else {
@@ -3485,9 +3466,15 @@ krb5_init_creds_step(krb5_context context,
        ctx->fast_state.armor_ccache == NULL) {
        ret = _krb5_fast_anon_pkinit_step(context, ctx, &ctx->fast_state,
                                          in, out, hostinfo, flags);
-       if (ret ||
-           ((*flags & KRB5_INIT_CREDS_STEP_FLAG_CONTINUE) == 0) ||
-           out->length)
+        if (ret && (ctx->fast_state.flags & KRB5_FAST_OPTIMISTIC)) {
+            _krb5_debug(context, 5, "Preauth failed with optimistic "
+                        "FAST, trying w/o FAST");
+            ctx->fast_state.flags &= ~KRB5_FAST_OPTIMISTIC;
+            ctx->fast_state.flags &= ~KRB5_FAST_REQUIRED;
+            ctx->fast_state.flags &= ~KRB5_FAST_ANON_PKINIT_ARMOR;
+        } else if (ret ||
+                   ((*flags & KRB5_INIT_CREDS_STEP_FLAG_CONTINUE) == 0) ||
+                   out->length)
            return ret;
 
        in = &empty;
@@ -3649,7 +3636,7 @@ krb5_init_creds_store(krb5_context context,
        krb5_data data = { 3, rk_UNCONST("yes") };
        ret = krb5_cc_set_config(context, id, ctx->cred.server,
                                 "fast_avail", &data);
-       if (ret)
+       if (ret && ret != KRB5_CC_NOSUPP)
            return ret;
     }
 
@@ -4001,7 +3988,7 @@ _krb5_init_creds_init_gss(krb5_context context,
                          const struct gss_OID_desc_struct *gss_mech,
                          unsigned int flags)
 {
-    krb5_gss_init_ctx gssic = ctx->gss_init_ctx;
+    krb5_gss_init_ctx gssic;
 
     gssic = calloc(1, sizeof(*gssic));
     if (gssic == NULL)
index 760abf5c59dd39f741b9bd6d1a2a4580fed9f782..a75fc03f985d33a3e3d51e1992c7d08b323438b5 100644 (file)
@@ -73,6 +73,8 @@ kcm_send_request(krb5_context context,
     krb5_error_code ret = 0;
     krb5_data request_data;
 
+    krb5_data_zero(response_data);
+
     HEIMDAL_MUTEX_lock(&kcm_mutex);
     if (kcm_ipc == NULL)
        ret = heim_ipc_init_context(kcm_ipc_name, &kcm_ipc);
@@ -82,18 +84,11 @@ kcm_send_request(krb5_context context,
 
     ret = krb5_storage_to_data(request, &request_data);
     if (ret) {
-       krb5_clear_error_message(context);
-       return KRB5_CC_NOMEM;
+       return krb5_enomem(context);
     }
 
     ret = heim_ipc_call(kcm_ipc, &request_data, response_data, NULL);
     krb5_data_free(&request_data);
-
-    if (ret) {
-       krb5_clear_error_message(context);
-       ret = KRB5_CC_NOSUPP;
-    }
-
     return ret;
 }
 
@@ -108,10 +103,8 @@ krb5_kcm_storage_request(krb5_context context,
     *storage_p = NULL;
 
     sp = krb5_storage_emem();
-    if (sp == NULL) {
-       krb5_set_error_message(context, KRB5_CC_NOMEM, N_("malloc: out of memory", ""));
-       return KRB5_CC_NOMEM;
-    }
+    if (sp == NULL)
+       return krb5_enomem(context);
 
     /* Send MAJOR | VERSION | OPCODE */
     ret  = krb5_store_int8(sp, KCM_PROTOCOL_VERSION_MAJOR);
@@ -135,31 +128,166 @@ krb5_kcm_storage_request(krb5_context context,
     return ret;
 }
 
+/*
+ * A sort of a state() for caches -- we use this to see if the local default
+ * cache name for KCM happens to exist.  See kcm_alloc() below.
+ */
+static krb5_error_code
+kcm_stat(krb5_context context, const char *name)
+{
+    krb5_error_code ret;
+    krb5_storage *request = NULL;
+    krb5_data response_data;
+
+    krb5_data_zero(&response_data);
+
+    ret = krb5_kcm_storage_request(context, KCM_OP_GET_PRINCIPAL, &request);
+    if (ret == 0)
+        ret = krb5_store_stringz(request, name);
+    if (ret == 0)
+        ret = krb5_kcm_call(context, request, NULL, &response_data);
+    krb5_storage_free(request);
+    krb5_data_free(&response_data);
+    return ret;
+}
+
+static krb5_error_code kcm_get_default_name(krb5_context,
+                                            const krb5_cc_ops *,
+                                            const char *, char **);
+
 static krb5_error_code
 kcm_alloc(krb5_context context,
-          const char *name,
+          const krb5_cc_ops *ops,
+          const char *residual,
+          const char *sub,
           krb5_ccache *id)
 {
+    krb5_error_code ret;
     krb5_kcmcache *k;
+    size_t ops_prefix_len = strlen(ops->prefix);
+    size_t plen = 0;
+    size_t local_def_name_len;
+    char *local_def_name = NULL; /* Our idea of default KCM cache name */
+    char *kcm_def_name = NULL; /* KCM's knowledge of default cache name */
+    int aret;
 
-    k = malloc(sizeof(*k));
-    if (k == NULL) {
-       krb5_set_error_message(context, KRB5_CC_NOMEM,
-                              N_("malloc: out of memory", ""));
-       return KRB5_CC_NOMEM;
+    /* Get the KCM:%{UID} default */
+    if (ops == &krb5_kcm_ops)
+        ret = _krb5_expand_default_cc_name(context, KRB5_DEFAULT_CCNAME_KCM_KCM, &local_def_name);
+    else
+        ret = _krb5_expand_default_cc_name(context, KRB5_DEFAULT_CCNAME_KCM_API, &local_def_name);
+    if (ret)
+        return ret;
+    local_def_name_len = strlen(local_def_name);
+
+    /* Get the default ccache name from KCM if possible */
+    (void) kcm_get_default_name(context, ops, NULL, &kcm_def_name);
+
+    /*
+     * We have a sticky situation in that applications that call
+     * krb5_cc_default() will be getting the locally configured or compiled-in
+     * default KCM cache name, which may not exist in the user's KCM session,
+     * and which the KCM daemon may not be able to alias to the actual default
+     * for the user's session.
+     *
+     * To deal with this we heuristically detect when an application uses the
+     * default KCM ccache name.
+     *
+     * If the residual happens to be the local default KCM name we may end up
+     * using whatever the default KCM cache name is instead of the local
+     * default.
+     *
+     * Note that here `residual' may be any of:
+     *
+     *  - %{UID}
+     *  - %{UID}:
+     *  - %{UID}:<subsidiary>
+     *  - <something not starting with %{UID}:>
+     *  - <empty string>
+     *  - <NULL>
+     *
+     * Only the first two count as "maybe I mean the default KCM cache".
+     */
+    if (residual && !sub &&
+        strncmp(residual, local_def_name + ops_prefix_len + 1,
+                local_def_name_len - (ops_prefix_len + 1)) == 0) {
+        if (residual[local_def_name_len - (ops_prefix_len + 1)] == '\0' ||
+            (residual[local_def_name_len - (ops_prefix_len + 1)] == ':' &&
+             residual[local_def_name_len - ops_prefix_len] == '\0')) {
+            /*
+             * If we got a default cache name from KCM and the requested default
+             * cache does not exist, use the former.
+             */
+            if (kcm_def_name && kcm_stat(context, residual))
+                residual = kcm_def_name + ops_prefix_len + 1;
+        }
     }
 
-    if (name != NULL) {
-       k->name = strdup(name);
-       if (k->name == NULL) {
-           free(k);
-           krb5_set_error_message(context, KRB5_CC_NOMEM,
-                                  N_("malloc: out of memory", ""));
-           return KRB5_CC_NOMEM;
-       }
-    } else
-       k->name = NULL;
+    if (residual && residual[0] == '\0')
+        residual = NULL;
+    if (sub && sub[0] == '\0')
+        sub = NULL;
+
+    if (residual == NULL && sub == NULL) {
+        /* Use the default cache name, either from KCM or local default */
+        if (kcm_def_name)
+            residual = kcm_def_name + ops_prefix_len + 1;
+        else
+            residual = local_def_name + ops_prefix_len + 1;
+    }
+
+    if (residual) {
+        /* KCM cache names must start with {UID} or {UID}: */
+        if (residual[0] != '0')
+            plen = strspn(residual, "0123456789");
+        if (plen && residual[plen] != ':' && residual[plen] != '\0')
+            plen = 0;
+        /*
+         * If `plen', then residual is such a residual, else we'll want to
+         * prefix the {UID}:.
+         */
+    }
+
+    k = calloc(1, sizeof(*k));
+    if (k == NULL) {
+        free(local_def_name);
+        free(kcm_def_name);
+       return krb5_enomem(context);
+    }
+    k->name = NULL;
+
+    if (residual == NULL && sub == NULL) {
+        /* One more way to get a default */
+        aret = asprintf(&k->name, "%llu", (unsigned long long)getuid());
+    } else if (residual == NULL) {
+        /*
+         * Treat the subsidiary as the residual (maybe this will turn out to be
+         * wrong).
+         */
+        aret = asprintf(&k->name, "%llu:%s", (unsigned long long)getuid(),
+                        sub);
+    } else if (plen) {
+        /* The residual is a UID */
+        aret = asprintf(&k->name, "%s%s%s", residual,
+                        sub ? ":" : "", sub ? sub : "");
+    } else if (sub == NULL) {
+        /* The residual is NOT a UID */
+        aret = asprintf(&k->name, "%llu:%s", (unsigned long long)getuid(),
+                        residual);
+    } else {
+        /* Ditto, plus we have a subsidiary.  `residual && sub && !plen' */
+        aret = asprintf(&k->name, "%llu:%s:%s", (unsigned long long)getuid(),
+                        residual, sub);
+    }
+    if (aret == -1 || k->name == NULL) {
+        free(local_def_name);
+        free(kcm_def_name);
+        free(k);
+        return krb5_enomem(context);
+    }
 
+    free(local_def_name);
+    free(kcm_def_name);
     (*id)->data.data = k;
     (*id)->data.length = sizeof(*k);
 
@@ -181,10 +309,11 @@ krb5_kcm_call(krb5_context context,
        *response_p = NULL;
 
     krb5_data_zero(&response_data);
-
     ret = kcm_send_request(context, request, &response_data);
-    if (ret)
-       return ret;
+    if (ret) {
+        krb5_data_free(&response_data);
+        return ret;
+    }
 
     response = krb5_storage_from_data(&response_data);
     if (response == NULL) {
@@ -224,8 +353,7 @@ kcm_free(krb5_context context, krb5_ccache *id)
     krb5_kcmcache *k = KCMCACHE(*id);
 
     if (k != NULL) {
-       if (k->name != NULL)
-           free(k->name);
+        free(k->name);
        memset_s(k, sizeof(*k), 0, sizeof(*k));
        krb5_data_free(&(*id)->data);
     }
@@ -255,10 +383,10 @@ kcm_get_name_2(krb5_context context,
 }
 
 static krb5_error_code
-kcm_resolve_2(krb5_context context,
-             krb5_ccache *id,
-             const char *res,
-             const char *sub)
+kcm_resolve_2_kcm(krb5_context context,
+                  krb5_ccache *id,
+                  const char *res,
+                  const char *sub)
 {
     /*
      * For now, for KCM the `res' is the `sub'.
@@ -266,7 +394,22 @@ kcm_resolve_2(krb5_context context,
      * TODO: We should use `res' as the IPC name instead of the one currently
      *       hard-coded in `kcm_ipc_name'.
      */
-    return kcm_alloc(context, sub && *sub ? sub : res, id);
+    return kcm_alloc(context, &krb5_kcm_ops, res, sub, id);
+}
+
+static krb5_error_code
+kcm_resolve_2_api(krb5_context context,
+                  krb5_ccache *id,
+                  const char *res,
+                  const char *sub)
+{
+    /*
+     * For now, for KCM the `res' is the `sub'.
+     *
+     * TODO: We should use `res' as the IPC name instead of the one currently
+     *       hard-coded in `kcm_ipc_name'.
+     */
+    return kcm_alloc(context, &krb5_akcm_ops, res, sub, id);
 }
 
 /*
@@ -276,14 +419,14 @@ kcm_resolve_2(krb5_context context,
  *      NameZ
  */
 static krb5_error_code
-kcm_gen_new(krb5_context context, krb5_ccache *id)
+kcm_gen_new(krb5_context context, const krb5_cc_ops *ops, krb5_ccache *id)
 {
     krb5_kcmcache *k;
     krb5_error_code ret;
     krb5_storage *request, *response;
     krb5_data response_data;
 
-    ret = kcm_alloc(context, NULL, id);
+    ret = kcm_alloc(context, ops, NULL, NULL, id);
     if (ret)
        return ret;
 
@@ -302,6 +445,8 @@ kcm_gen_new(krb5_context context, krb5_ccache *id)
        return ret;
     }
 
+    free(k->name);
+    k->name = NULL;
     ret = krb5_ret_stringz(response, &k->name);
     if (ret)
        ret = KRB5_CC_IO;
@@ -316,6 +461,18 @@ kcm_gen_new(krb5_context context, krb5_ccache *id)
     return ret;
 }
 
+static krb5_error_code
+kcm_gen_new_kcm(krb5_context context, krb5_ccache *id)
+{
+    return kcm_gen_new(context, &krb5_kcm_ops, id);
+}
+
+static krb5_error_code
+kcm_gen_new_api(krb5_context context, krb5_ccache *id)
+{
+    return kcm_gen_new(context, &krb5_akcm_ops, id);
+}
+
 /*
  * Request:
  *      NameZ
@@ -666,8 +823,7 @@ kcm_get_next (krb5_context context,
     c->offset++;
     if (sret != sizeof(c->uuids[c->offset])) {
        krb5_storage_free(request);
-       krb5_clear_error_message(context);
-       return ENOMEM;
+       return krb5_enomem(context);
     }
 
     ret = krb5_kcm_call(context, request, &response, &response_data);
@@ -895,8 +1051,7 @@ kcm_get_cache_next(krb5_context context, krb5_cc_cursor cursor, const krb5_cc_op
     c->offset++;
     if (sret != sizeof(c->uuids[c->offset])) {
        krb5_storage_free(request);
-       krb5_clear_error_message(context);
-       return ENOMEM;
+       return krb5_enomem(context);
     }
 
     ret = krb5_kcm_call(context, request, &response, &response_data);
@@ -913,7 +1068,7 @@ kcm_get_cache_next(krb5_context context, krb5_cc_cursor cursor, const krb5_cc_op
     if (ret == 0) {
        ret = _krb5_cc_allocate(context, ops, id);
        if (ret == 0)
-           ret = kcm_alloc(context, name, id);
+           ret = kcm_alloc(context, ops, name, NULL, id);
        krb5_xfree(name);
     }
 
@@ -998,8 +1153,11 @@ kcm_get_default_name(krb5_context context, const krb5_cc_ops *ops,
 
     ret = krb5_kcm_call(context, request, &response, &response_data);
     krb5_storage_free(request);
-    if (ret)
-       return _krb5_expand_default_cc_name(context, defstr, str);
+    if (ret) {
+        if (defstr)
+            return _krb5_expand_default_cc_name(context, defstr, str);
+        return ret;
+    }
 
     ret = krb5_ret_stringz(response, &name);
     krb5_storage_free(response);
@@ -1009,8 +1167,8 @@ kcm_get_default_name(krb5_context context, const krb5_cc_ops *ops,
 
     aret = asprintf(str, "%s:%s", ops->prefix, name);
     free(name);
-    if (aret == -1 || str == NULL)
-       return ENOMEM;
+    if (aret == -1 || *str == NULL)
+       return krb5_enomem(context);
 
     return 0;
 }
@@ -1133,7 +1291,7 @@ KRB5_LIB_VARIABLE const krb5_cc_ops krb5_kcm_ops = {
     "KCM",
     NULL,
     NULL,
-    kcm_gen_new,
+    kcm_gen_new_kcm,
     kcm_initialize,
     kcm_destroy,
     kcm_close,
@@ -1156,7 +1314,7 @@ KRB5_LIB_VARIABLE const krb5_cc_ops krb5_kcm_ops = {
     kcm_set_kdc_offset,
     kcm_get_kdc_offset,
     kcm_get_name_2,
-    kcm_resolve_2
+    kcm_resolve_2_kcm
 };
 
 KRB5_LIB_VARIABLE const krb5_cc_ops krb5_akcm_ops = {
@@ -1164,7 +1322,7 @@ KRB5_LIB_VARIABLE const krb5_cc_ops krb5_akcm_ops = {
     "API",
     NULL,
     NULL,
-    kcm_gen_new,
+    kcm_gen_new_api,
     kcm_initialize,
     kcm_destroy,
     kcm_close,
@@ -1187,10 +1345,9 @@ KRB5_LIB_VARIABLE const krb5_cc_ops krb5_akcm_ops = {
     NULL,
     NULL,
     kcm_get_name_2,
-    kcm_resolve_2
+    kcm_resolve_2_api
 };
 
-
 KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
 _krb5_kcm_is_running(krb5_context context)
 {
@@ -1199,7 +1356,7 @@ _krb5_kcm_is_running(krb5_context context)
     krb5_ccache id = &ccdata;
     krb5_boolean running;
 
-    ret = kcm_alloc(context, NULL, &id);
+    ret = kcm_alloc(context, NULL, NULL, NULL, &id);
     if (ret)
        return 0;
 
index 6ec14b8e17193fceaafa0c624a95d1937a3a1427..559d640f002ca158cfb3b95b62618013bc220667 100644 (file)
@@ -358,10 +358,11 @@ krb5_kt_read_service_key(krb5_context context,
                         krb5_enctype enctype,
                         krb5_keyblock **key)
 {
-    krb5_keytab keytab;
+    krb5_keytab keytab = NULL; /* Quiet lint */
     krb5_keytab_entry entry;
     krb5_error_code ret;
 
+    memset(&entry, 0, sizeof(entry));
     if (keyprocarg)
        ret = krb5_kt_resolve (context, keyprocarg, &keytab);
     else
@@ -371,11 +372,11 @@ krb5_kt_read_service_key(krb5_context context,
        return ret;
 
     ret = krb5_kt_get_entry (context, keytab, principal, vno, enctype, &entry);
+    if (ret == 0) {
+        ret = krb5_copy_keyblock (context, &entry.keyblock, key);
+        krb5_kt_free_entry(context, &entry);
+    }
     krb5_kt_close (context, keytab);
-    if (ret)
-       return ret;
-    ret = krb5_copy_keyblock (context, &entry.keyblock, key);
-    krb5_kt_free_entry(context, &entry);
     return ret;
 }
 
@@ -482,11 +483,13 @@ KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_kt_close(krb5_context context,
              krb5_keytab id)
 {
-    krb5_error_code ret;
+    krb5_error_code ret = 0;
 
-    ret = (*id->close)(context, id);
-    memset(id, 0, sizeof(*id));
-    free(id);
+    if (id) {
+        ret = (id->close)(context, id);
+        memset(id, 0, sizeof(*id));
+        free(id);
+    }
     return ret;
 }
 
@@ -579,29 +582,31 @@ _krb5_kt_principal_not_found(krb5_context context,
                             krb5_enctype enctype,
                             int kvno)
 {
-    char princ[256], kvno_str[25], *kt_name;
+    char kvno_str[25];
     char *enctype_str = NULL;
+    char *kt_name = NULL;
+    char *princ = NULL;
 
-    krb5_unparse_name_fixed (context, principal, princ, sizeof(princ));
-    krb5_kt_get_full_name (context, id, &kt_name);
+    (void) krb5_unparse_name(context, principal, &princ);
+    (void) krb5_kt_get_full_name(context, id, &kt_name);
     if (enctype)
-       krb5_enctype_to_string(context, enctype, &enctype_str);
+       (void) krb5_enctype_to_string(context, enctype, &enctype_str);
 
     if (kvno)
        snprintf(kvno_str, sizeof(kvno_str), "(kvno %d)", kvno);
     else
        kvno_str[0] = '\0';
 
-    krb5_set_error_message (context, ret,
-                           N_("Failed to find %s%s in keytab %s (%s)",
-                              "principal, kvno, keytab file, enctype"),
-                           princ,
-                           kvno_str,
-                           kt_name ? kt_name : "unknown keytab",
-                           enctype_str ? enctype_str : "unknown enctype");
+    krb5_set_error_message(context, ret,
+                          N_("Failed to find %s%s in keytab %s (%s)",
+                             "principal, kvno, keytab file, enctype"),
+                          princ ? princ : "<unknown>",
+                          kvno_str,
+                          kt_name ? kt_name : "unknown keytab",
+                          enctype_str ? enctype_str : "unknown enctype");
+    free(princ);
     free(kt_name);
-    if (enctype_str)
-       free(enctype_str);
+    free(enctype_str);
     return ret;
 }
 
@@ -620,6 +625,7 @@ krb5_kt_get_entry_wrapped(krb5_context context,
     if(id->get)
        return (*id->get)(context, id, principal, kvno, enctype, entry);
 
+    memset(&tmp, 0, sizeof(tmp));
     ret = krb5_kt_start_seq_get (context, id, &cursor);
     if (ret) {
        /* This is needed for krb5_verify_init_creds, but keep error
@@ -683,7 +689,8 @@ krb5_kt_get_entry(krb5_context context,
     krb5_name_canon_iterator name_canon_iter;
 
     if (!principal)
-       return krb5_kt_get_entry_wrapped(context, id, principal, kvno, enctype,
+        /* Use `NULL' instead of `principal' to quiet static analizers */
+       return krb5_kt_get_entry_wrapped(context, id, NULL, kvno, enctype,
                                         entry);
 
     ret = krb5_name_canon_iterator_start(context, principal, &name_canon_iter);
@@ -731,21 +738,21 @@ krb5_kt_copy_entry_contents(krb5_context context,
     krb5_error_code ret;
 
     memset(out, 0, sizeof(*out));
-    out->vno = in->vno;
 
     ret = krb5_copy_principal (context, in->principal, &out->principal);
     if (ret)
-       goto fail;
+       return ret;
     ret = krb5_copy_keyblock_contents (context,
                                       &in->keyblock,
                                       &out->keyblock);
-    if (ret)
-       goto fail;
+    if (ret) {
+        krb5_free_principal(context, out->principal);
+        memset(out, 0, sizeof(*out));
+        return ret;
+    }
+    out->vno = in->vno;
     out->timestamp = in->timestamp;
     return 0;
-fail:
-    krb5_kt_free_entry (context, out);
-    return ret;
 }
 
 /**
@@ -927,6 +934,7 @@ krb5_kt_have_content(krb5_context context,
     krb5_error_code ret;
     char *name;
 
+    memset(&entry, 0, sizeof(entry));
     ret = krb5_kt_start_seq_get(context, id, &cursor);
     if (ret)
        goto notfound;
index 595966ed38760621dbbad9de6d5017d4180c2421..61b5d6d29cf872b671e14a2f272cf5438c2b8165 100644 (file)
@@ -371,6 +371,7 @@ fkt_start_seq_get_int(krb5_context context,
     struct fkt_data *d = id->data;
     const char *stdio_mode = "rb";
 
+    memset(c, 0, sizeof(*c));
     c->fd = open (d->filename, flags);
     if (c->fd < 0) {
        ret = errno;
@@ -797,7 +798,7 @@ fkt_remove_entry(krb5_context context,
         krb5_set_error_message(context, ret,
                                N_("Could not remove keytab entry from %s: %s", ""),
                                fkt->filename,
-                               krb5_get_error_message(context, ret));
+                               emsg);
         krb5_free_error_message(context, emsg);
     } else if (!found) {
        krb5_clear_error_message(context);
index cb865a794c08c7ac4a822d7926ac58f8b919a130..af3ac86faf0aecd44431b6554bcb4986ed864352 100644 (file)
@@ -403,7 +403,7 @@ akf_add_entry(krb5_context context,
        ret = errno;
        krb5_set_error_message (context, ret,
                                N_("keytab keyfile failed new length", ""));
-       return ret;
+       goto out;
     }
 
     if(krb5_storage_seek(sp, (len - 1) * (8 + 4), SEEK_CUR) < 0) {
index bac94b5f7dfe7e8bdf2b124a2a63ea34b20bcc0d..1013a78d873135d9072470d2517b28998bad0cb3 100644 (file)
@@ -1077,12 +1077,6 @@ an optional unit (the default unit is
 Indicates whether a client may request longer lifetimes than
 their authentication credentials.
 Defaults to false.
-If a
-.Li force_cert_lifetime
-is specified, then
-.Li allow_extra_lifetime
-is implicitly forced to
-.Va true .
 .It Li require_initial_kca_tickets = Va boolean
 Specified whether to require that tickets for the
 .Li kca_service
index 3950bd30a4ec3a22b5384a506613d1cc67feef4b..e78edcac9af5c4b5960989da09c28db1b6c8b66c 100644 (file)
@@ -95,6 +95,7 @@ typedef struct krb5_ntlm_data *krb5_ntlm;
 
 struct krb5_pac_data;
 typedef struct krb5_pac_data *krb5_pac;
+typedef const struct krb5_pac_data *krb5_const_pac;
 
 typedef struct krb5_rd_req_in_ctx_data *krb5_rd_req_in_ctx;
 typedef struct krb5_rd_req_out_ctx_data *krb5_rd_req_out_ctx;
@@ -122,55 +123,53 @@ typedef struct krb5_enc_data {
 } krb5_enc_data;
 
 /* alternative names */
-enum {
-    ENCTYPE_NULL               = KRB5_ENCTYPE_NULL,
-    ENCTYPE_DES_CBC_CRC                = KRB5_ENCTYPE_DES_CBC_CRC,
-    ENCTYPE_DES_CBC_MD4                = KRB5_ENCTYPE_DES_CBC_MD4,
-    ENCTYPE_DES_CBC_MD5                = KRB5_ENCTYPE_DES_CBC_MD5,
-    ENCTYPE_DES3_CBC_MD5       = KRB5_ENCTYPE_DES3_CBC_MD5,
-    ENCTYPE_OLD_DES3_CBC_SHA1  = KRB5_ENCTYPE_OLD_DES3_CBC_SHA1,
-    ENCTYPE_SIGN_DSA_GENERATE  = KRB5_ENCTYPE_SIGN_DSA_GENERATE,
-    ENCTYPE_ENCRYPT_RSA_PRIV   = KRB5_ENCTYPE_ENCRYPT_RSA_PRIV,
-    ENCTYPE_ENCRYPT_RSA_PUB    = KRB5_ENCTYPE_ENCRYPT_RSA_PUB,
-    ENCTYPE_DES3_CBC_SHA1      = KRB5_ENCTYPE_DES3_CBC_SHA1,
-    ENCTYPE_AES128_CTS_HMAC_SHA1_96 = KRB5_ENCTYPE_AES128_CTS_HMAC_SHA1_96,
-    ENCTYPE_AES256_CTS_HMAC_SHA1_96 = KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96,
-    ENCTYPE_ARCFOUR_HMAC       = KRB5_ENCTYPE_ARCFOUR_HMAC_MD5,
-    ENCTYPE_ARCFOUR_HMAC_MD5   = KRB5_ENCTYPE_ARCFOUR_HMAC_MD5,
-    ENCTYPE_ARCFOUR_HMAC_MD5_56        = KRB5_ENCTYPE_ARCFOUR_HMAC_MD5_56,
-    ENCTYPE_ENCTYPE_PK_CROSS   = KRB5_ENCTYPE_ENCTYPE_PK_CROSS,
-    ENCTYPE_DES_CBC_NONE       = KRB5_ENCTYPE_DES_CBC_NONE,
-    ENCTYPE_DES3_CBC_NONE      = KRB5_ENCTYPE_DES3_CBC_NONE,
-    ENCTYPE_DES_CFB64_NONE     = KRB5_ENCTYPE_DES_CFB64_NONE,
-    ENCTYPE_DES_PCBC_NONE      = KRB5_ENCTYPE_DES_PCBC_NONE,
-    ETYPE_NULL                 = KRB5_ENCTYPE_NULL,
-    ETYPE_DES_CBC_CRC          = KRB5_ENCTYPE_DES_CBC_CRC,
-    ETYPE_DES_CBC_MD4          = KRB5_ENCTYPE_DES_CBC_MD4,
-    ETYPE_DES_CBC_MD5          = KRB5_ENCTYPE_DES_CBC_MD5,
-    ETYPE_DES3_CBC_MD5         = KRB5_ENCTYPE_DES3_CBC_MD5,
-    ETYPE_OLD_DES3_CBC_SHA1    = KRB5_ENCTYPE_OLD_DES3_CBC_SHA1,
-    ETYPE_SIGN_DSA_GENERATE    = KRB5_ENCTYPE_SIGN_DSA_GENERATE,
-    ETYPE_ENCRYPT_RSA_PRIV     = KRB5_ENCTYPE_ENCRYPT_RSA_PRIV,
-    ETYPE_ENCRYPT_RSA_PUB      = KRB5_ENCTYPE_ENCRYPT_RSA_PUB,
-    ETYPE_DES3_CBC_SHA1                = KRB5_ENCTYPE_DES3_CBC_SHA1,
-    ETYPE_AES128_CTS_HMAC_SHA1_96      = KRB5_ENCTYPE_AES128_CTS_HMAC_SHA1_96,
-    ETYPE_AES256_CTS_HMAC_SHA1_96      = KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96,
-    ETYPE_AES128_CTS_HMAC_SHA256_128   = KRB5_ENCTYPE_AES128_CTS_HMAC_SHA256_128,
-    ETYPE_AES256_CTS_HMAC_SHA384_192   = KRB5_ENCTYPE_AES256_CTS_HMAC_SHA384_192,
-    ETYPE_ARCFOUR_HMAC_MD5     = KRB5_ENCTYPE_ARCFOUR_HMAC_MD5,
-    ETYPE_ARCFOUR_HMAC_MD5_56  = KRB5_ENCTYPE_ARCFOUR_HMAC_MD5_56,
-    ETYPE_ENCTYPE_PK_CROSS     = KRB5_ENCTYPE_ENCTYPE_PK_CROSS,
-    ETYPE_ARCFOUR_MD4          = KRB5_ENCTYPE_ARCFOUR_MD4,
-    ETYPE_ARCFOUR_HMAC_OLD     = KRB5_ENCTYPE_ARCFOUR_HMAC_OLD,
-    ETYPE_ARCFOUR_HMAC_OLD_EXP = KRB5_ENCTYPE_ARCFOUR_HMAC_OLD_EXP,
-    ETYPE_DES_CBC_NONE         = KRB5_ENCTYPE_DES_CBC_NONE,
-    ETYPE_DES3_CBC_NONE                = KRB5_ENCTYPE_DES3_CBC_NONE,
-    ETYPE_DES_CFB64_NONE       = KRB5_ENCTYPE_DES_CFB64_NONE,
-    ETYPE_DES_PCBC_NONE                = KRB5_ENCTYPE_DES_PCBC_NONE,
-    ETYPE_DIGEST_MD5_NONE      = KRB5_ENCTYPE_DIGEST_MD5_NONE,
-    ETYPE_CRAM_MD5_NONE                = KRB5_ENCTYPE_CRAM_MD5_NONE
-
-};
+#define ENCTYPE_NULL           KRB5_ENCTYPE_NULL
+#define ENCTYPE_DES_CBC_CRC    KRB5_ENCTYPE_DES_CBC_CRC
+#define ENCTYPE_DES_CBC_MD4    KRB5_ENCTYPE_DES_CBC_MD4
+#define ENCTYPE_DES_CBC_MD5    KRB5_ENCTYPE_DES_CBC_MD5
+#define ENCTYPE_DES3_CBC_MD5   KRB5_ENCTYPE_DES3_CBC_MD5
+#define ENCTYPE_OLD_DES3_CBC_SHA1      KRB5_ENCTYPE_OLD_DES3_CBC_SHA1
+#define ENCTYPE_SIGN_DSA_GENERATE      KRB5_ENCTYPE_SIGN_DSA_GENERATE
+#define ENCTYPE_ENCRYPT_RSA_PRIV       KRB5_ENCTYPE_ENCRYPT_RSA_PRIV
+#define ENCTYPE_ENCRYPT_RSA_PUB        KRB5_ENCTYPE_ENCRYPT_RSA_PUB
+#define ENCTYPE_DES3_CBC_SHA1  KRB5_ENCTYPE_DES3_CBC_SHA1
+#define ENCTYPE_AES128_CTS_HMAC_SHA1_96 KRB5_ENCTYPE_AES128_CTS_HMAC_SHA1_96
+#define ENCTYPE_AES256_CTS_HMAC_SHA1_96 KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96
+#define ENCTYPE_ARCFOUR_HMAC   KRB5_ENCTYPE_ARCFOUR_HMAC_MD5
+#define ENCTYPE_ARCFOUR_HMAC_MD5       KRB5_ENCTYPE_ARCFOUR_HMAC_MD5
+#define ENCTYPE_ARCFOUR_HMAC_MD5_56    KRB5_ENCTYPE_ARCFOUR_HMAC_MD5_56
+#define ENCTYPE_ENCTYPE_PK_CROSS       KRB5_ENCTYPE_ENCTYPE_PK_CROSS
+#define ENCTYPE_DES_CBC_NONE   KRB5_ENCTYPE_DES_CBC_NONE
+#define ENCTYPE_DES3_CBC_NONE  KRB5_ENCTYPE_DES3_CBC_NONE
+#define ENCTYPE_DES_CFB64_NONE KRB5_ENCTYPE_DES_CFB64_NONE
+#define ENCTYPE_DES_PCBC_NONE  KRB5_ENCTYPE_DES_PCBC_NONE
+#define ETYPE_NULL             KRB5_ENCTYPE_NULL
+#define ETYPE_DES_CBC_CRC      KRB5_ENCTYPE_DES_CBC_CRC
+#define ETYPE_DES_CBC_MD4      KRB5_ENCTYPE_DES_CBC_MD4
+#define ETYPE_DES_CBC_MD5      KRB5_ENCTYPE_DES_CBC_MD5
+#define ETYPE_DES3_CBC_MD5     KRB5_ENCTYPE_DES3_CBC_MD5
+#define ETYPE_OLD_DES3_CBC_SHA1        KRB5_ENCTYPE_OLD_DES3_CBC_SHA1
+#define ETYPE_SIGN_DSA_GENERATE        KRB5_ENCTYPE_SIGN_DSA_GENERATE
+#define ETYPE_ENCRYPT_RSA_PRIV KRB5_ENCTYPE_ENCRYPT_RSA_PRIV
+#define ETYPE_ENCRYPT_RSA_PUB  KRB5_ENCTYPE_ENCRYPT_RSA_PUB
+#define ETYPE_DES3_CBC_SHA1    KRB5_ENCTYPE_DES3_CBC_SHA1
+#define ETYPE_AES128_CTS_HMAC_SHA1_96  KRB5_ENCTYPE_AES128_CTS_HMAC_SHA1_96
+#define ETYPE_AES256_CTS_HMAC_SHA1_96  KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96
+#define ETYPE_AES128_CTS_HMAC_SHA256_128       KRB5_ENCTYPE_AES128_CTS_HMAC_SHA256_128
+#define ETYPE_AES256_CTS_HMAC_SHA384_192       KRB5_ENCTYPE_AES256_CTS_HMAC_SHA384_192
+#define ETYPE_ARCFOUR_HMAC_MD5 KRB5_ENCTYPE_ARCFOUR_HMAC_MD5
+#define ETYPE_ARCFOUR_HMAC_MD5_56      KRB5_ENCTYPE_ARCFOUR_HMAC_MD5_56
+#define ETYPE_ENCTYPE_PK_CROSS KRB5_ENCTYPE_ENCTYPE_PK_CROSS
+#define ETYPE_ARCFOUR_MD4      KRB5_ENCTYPE_ARCFOUR_MD4
+#define ETYPE_ARCFOUR_HMAC_OLD KRB5_ENCTYPE_ARCFOUR_HMAC_OLD
+#define ETYPE_ARCFOUR_HMAC_OLD_EXP     KRB5_ENCTYPE_ARCFOUR_HMAC_OLD_EXP
+#define ETYPE_DES_CBC_NONE     KRB5_ENCTYPE_DES_CBC_NONE
+#define ETYPE_DES3_CBC_NONE    KRB5_ENCTYPE_DES3_CBC_NONE
+#define ETYPE_DES_CFB64_NONE   KRB5_ENCTYPE_DES_CFB64_NONE
+#define ETYPE_DES_PCBC_NONE    KRB5_ENCTYPE_DES_PCBC_NONE
+#define ETYPE_DIGEST_MD5_NONE  KRB5_ENCTYPE_DIGEST_MD5_NONE
+#define ETYPE_CRAM_MD5_NONE    KRB5_ENCTYPE_CRAM_MD5_NONE
+#define DOMAIN_X500_COMPRESS   domain_X500_Compress
 
 /* PDU types */
 typedef enum krb5_pdu {
@@ -1043,5 +1042,24 @@ extern KRB5_LIB_VARIABLE const char *krb5_cc_type_scc;
 extern KRB5_LIB_VARIABLE const char *krb5_cc_type_dcc;
 extern KRB5_LIB_VARIABLE const char *krb5_cc_type_keyring;
 
+/* clang analyzer workarounds */
+
+#ifdef __clang_analyzer__
+/*
+ * The clang analyzer (lint) can't know that krb5_enomem() always returns
+ * non-zero, so code like:
+ *
+ *      if ((x = malloc(...)) == NULL)
+ *          ret = krb5_enomem(context)
+ *      if (ret == 0)
+ *          *x = ...;
+ *
+ * causes false positives.
+ *
+ * The fix is to make krb5_enomem() a macro that always evaluates to ENOMEM.
+ */
+#define krb5_enomem(c) (krb5_enomem(c), ENOMEM)
+#endif
+
 #endif /* __KRB5_H__ */
 
index 6b74653f565ba3442f7c0b40c7f1b2acc195c407..7045c5bb60165b009d90e3dc96e734d63ac24556 100644 (file)
@@ -87,8 +87,10 @@ struct mbuf;
 
 #ifdef LIBINTL
 #include <libintl.h>
+#undef N_
 #define N_(x,y) dgettext(HEIMDAL_TEXTDOMAIN, x)
 #else
+#undef N_
 #define N_(x,y) (x)
 #define bindtextdomain(package, localedir)
 #endif
index 873734fce77a97d601fa858268422ce84a6139a0..cd388ecfaaa059ecb5929652568b02f1bd69bff5 100644 (file)
@@ -59,6 +59,7 @@ usage (int ret)
 int
 main(int argc, char **argv)
 {
+    krb5_error_code ret;
     int i, j;
     krb5_context context;
     int types[] = {KRB5_KRBHST_KDC, KRB5_KRBHST_ADMIN, KRB5_KRBHST_CHANGEPW,
@@ -82,7 +83,9 @@ main(int argc, char **argv)
     argc -= optidx;
     argv += optidx;
 
-    krb5_init_context (&context);
+    ret = krb5_init_context(&context);
+    if (ret)
+        krb5_err(NULL, 1, ret, "Failed to initialize context");
     for(i = 0; i < argc; i++) {
        krb5_krbhst_handle handle;
        char host[MAXHOSTNAMELEN];
@@ -90,12 +93,16 @@ main(int argc, char **argv)
        for (j = 0; j < sizeof(types)/sizeof(*types); ++j) {
            printf ("%s for %s:\n", type_str[j], argv[i]);
 
-           krb5_krbhst_init(context, argv[i], types[j], &handle);
-           while(krb5_krbhst_next_as_string(context, handle,
-                                            host, sizeof(host)) == 0)
+           ret = krb5_krbhst_init(context, argv[i], types[j], &handle);
+            if (ret)
+                krb5_err(context, 1, ret, "Could not init krbhst iterator");
+           while ((ret = krb5_krbhst_next_as_string(context, handle, host,
+                                                     sizeof(host))) == 0)
                printf("\thost: %s\n", host);
            krb5_krbhst_reset(context, handle);
-           printf ("\n");
+           printf("\n");
+            if (ret)
+                krb5_err(context, 1, ret, "Could not iterate all krbhst");
        }
     }
     return 0;
index adb8e00e6dc82b830db99546cf9fd5e6c3a397bf..3688d6ad7ce9b897494c74d9a4954c8b45b541aa 100644 (file)
@@ -107,8 +107,24 @@ srv_find_realm(krb5_context context, krb5_krbhst_info ***res, int *count,
     }
 
     for(num_srv = 0, rr = r->head; rr; rr = rr->next)
-       if(rr->type == rk_ns_t_srv)
+       if(rr->type == rk_ns_t_srv) {
+           if (num_srv >= INT_MAX) {
+               rk_dns_free_data(r);
+               return KRB5_KDC_UNREACH;
+           }
+           if (num_srv >= SIZE_MAX / sizeof(**res)) {
+               rk_dns_free_data(r);
+               return KRB5_KDC_UNREACH;
+           }
            num_srv++;
+       }
+
+    if (num_srv == 0) {
+       _krb5_debug(context, 0,
+                   "DNS SRV RR lookup domain nodata: %s", domain);
+       rk_dns_free_data(r);
+       return KRB5_KDC_UNREACH;
+    }
 
     *res = malloc(num_srv * sizeof(**res));
     if(*res == NULL) {
@@ -431,7 +447,7 @@ krb5_krbhst_get_addrinfo(krb5_context context, krb5_krbhst_info *host,
 static krb5_boolean
 get_next(struct krb5_krbhst_data *kd, krb5_krbhst_info **host)
 {
-    struct krb5_krbhst_info *hi = *kd->index;
+    struct krb5_krbhst_info *hi = kd ? *kd->index : NULL;
     if(hi != NULL) {
        *host = hi;
        kd->index = &(*kd->index)->next;
@@ -555,6 +571,7 @@ fallback_get_hosts(krb5_context context, struct krb5_krbhst_data *kd,
                           "Realm %s needs immediate attention "
                           "see https://icann.org/namecollision",
                           kd->realm);
+               freeaddrinfo(ai);
                return KRB5_KDC_UNREACH;
            }
        }
@@ -563,6 +580,7 @@ fallback_get_hosts(krb5_context context, struct krb5_krbhst_data *kd,
        hi = calloc(1, sizeof(*hi) + hostlen);
        if(hi == NULL) {
            free(host);
+           freeaddrinfo(ai);
            return krb5_enomem(context);
        }
 
@@ -920,7 +938,7 @@ kpasswd_get_next(krb5_context context,
     return KRB5_KDC_UNREACH;
 }
 
-static void
+static void KRB5_CALLCONV
 krbhost_dealloc(void *ptr)
 {
     struct krb5_krbhst_data *handle = (struct krb5_krbhst_data *)ptr;
index dbf81850ea34de31f1c7ce9d267eeed3e471c8f0..9e992216153dd57863b9eacfc1fcadd3ba6b81a8 100644 (file)
@@ -367,6 +367,9 @@ parse_residual(krb5_context context,
     *pcollection_name = NULL;
     *psubsidiary_name = NULL;
 
+    if (residual == NULL)
+        residual = "";
+
     /* Parse out the anchor name.  Use the legacy anchor if not present. */
     sep = strchr(residual, ':');
     if (sep == NULL) {
@@ -473,7 +476,7 @@ make_subsidiary_residual(krb5_context context,
                         char **presidual)
 {
     if (asprintf(presidual, "%s:%s:%s", anchor_name, collection_name,
-                subsidiary_name) < 0) {
+                subsidiary_name ? subsidiary_name : "tkt") < 0) {
        *presidual = NULL;
        return krb5_enomem(context);
     }
@@ -498,6 +501,9 @@ get_collection(krb5_context context,
 
     heim_base_atomic_init(pcollection_id, 0);
 
+    if (!anchor_name || !collection_name)
+       return KRB5_KCC_INVALID_ANCHOR;
+
     if (strcmp(anchor_name, KRCC_PERSISTENT_ANCHOR) == 0) {
        /*
         * The collection name is a uid (or empty for the current effective
@@ -1262,7 +1268,7 @@ alloc_cache(krb5_context context,
                                   subsidiary_name, &data->krc_name);
     if (ret ||
         (data->krc_collection = strdup(collection_name)) == NULL ||
-        (data->krc_subsidiary = strdup(subsidiary_name)) == NULL) {
+        (data->krc_subsidiary = strdup(subsidiary_name ? subsidiary_name : "tkt")) == NULL) {
         if (data) {
             free(data->krc_collection);
             free(data->krc_name);
@@ -1702,7 +1708,7 @@ krcc_get_kdc_offset(krb5_context context,
     key_serial_t key, cache_id;
     krb5_storage *sp = NULL;
     krb5_data payload;
-    int32_t sec_offset, usec_offset;
+    int32_t sec_offset = 0;
 
     if (data == NULL)
        return krb5_einval(context, 2);
@@ -1730,26 +1736,22 @@ krcc_get_kdc_offset(krb5_context context,
 
     sp = krb5_storage_from_data(&payload);
     if (sp == NULL) {
-       ret = KRB5_CC_IO;
+       ret = krb5_enomem(context);;
        goto cleanup;
     }
 
     krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_BE);
 
     ret = krb5_ret_int32(sp, &sec_offset);
-    if (ret == 0)
-       krb5_ret_int32(sp, &usec_offset);
-    if (ret) {
-       ret = KRB5_CC_END;
-       goto cleanup;
-    }
-
-    *offset = sec_offset;
+    /*
+     * We can't output nor use the usec_offset here, so we don't bother to read
+     * it, though we do write it.
+     */
 
 cleanup:
+    *offset = sec_offset;
     krb5_storage_free(sp);
     krb5_data_free(&payload);
-
     return ret;
 }
 
@@ -1887,7 +1889,8 @@ krcc_get_cache_next(krb5_context context,
            continue;
 
        /* Don't repeat the primary cache. */
-       if (strcmp(subsidiary_name, iter->primary_name) == 0)
+       if (iter->primary_name &&
+            strcmp(subsidiary_name, iter->primary_name) == 0)
            continue;
 
        /* We found a valid key */
index bd5991fcbf81f549c74dc6468994b7e6329e5623..7525739f66ca09288e0aac41bb3b8a8de63aeeb8 100644 (file)
@@ -376,10 +376,13 @@ load_priv_key(krb5_context context,
         ret = ENOENT;
     if (ret == 0)
         kx509_ctx->priv_key = _hx509_private_key_ref(keys[0]);
-    if (ret)
+    if (ret) {
+       char *emsg = hx509_get_error_string(context->hx509ctx, ret);
+
         krb5_set_error_message(context, ret, "Could not load private key "
-                               "from %s for kx509: %s", fn,
-                               hx509_get_error_string(context->hx509ctx, ret));
+                               "from %s for kx509: %s", fn, emsg);
+       hx509_free_error_string(emsg);
+    }
     hx509_certs_free(&certs);
     return ret;
 }
@@ -443,10 +446,13 @@ gen_priv_key(krb5_context context,
     if (ret == 0)
         ret = _hx509_generate_private_key(context->hx509ctx, key_gen_ctx, key);
     _hx509_generate_private_key_free(&key_gen_ctx);
-    if (ret)
+    if (ret) {
+       char *emsg = hx509_get_error_string(context->hx509ctx, ret);
+
         krb5_set_error_message(context, ret,
-                               "Could not generate a private key: %s",
-                               hx509_get_error_string(context->hx509ctx, ret));
+                               "Could not generate a private key: %s", emsg);
+       hx509_free_error_string(emsg);
+    }
     return ret;
 }
 
@@ -848,21 +854,28 @@ mk_kx509_req(krb5_context context,
 
     /* Add the the key and HMAC to the message */
     HMAC_CTX_init(&ctx);
-    HMAC_Init_ex(&ctx, kx509_ctx->hmac_key->keyvalue.data,
-                 kx509_ctx->hmac_key->keyvalue.length, EVP_sha1(), NULL);
-    HMAC_Update(&ctx, version_2_0, sizeof(version_2_0));
-    if (private_key || kx509_ctx->given_csr.data) {
-        HMAC_Update(&ctx, kx509_req.pk_key.data, kx509_req.pk_key.length);
+    if (HMAC_Init_ex(&ctx, kx509_ctx->hmac_key->keyvalue.data,
+                     kx509_ctx->hmac_key->keyvalue.length,
+                     EVP_sha1(), NULL) == 0) {
+        HMAC_CTX_cleanup(&ctx);
+        ret = krb5_enomem(context);
     } else {
-        /* Probe */
-        HMAC_Update(&ctx, kx509_req.authenticator.data, kx509_req.authenticator.length);
+        HMAC_Update(&ctx, version_2_0, sizeof(version_2_0));
+        if (private_key || kx509_ctx->given_csr.data) {
+            HMAC_Update(&ctx, kx509_req.pk_key.data, kx509_req.pk_key.length);
+        } else {
+            /* Probe */
+            HMAC_Update(&ctx, kx509_req.authenticator.data, kx509_req.authenticator.length);
+        }
+        HMAC_Final(&ctx, kx509_req.pk_hash.data, 0);
+        HMAC_CTX_cleanup(&ctx);
     }
-    HMAC_Final(&ctx, kx509_req.pk_hash.data, 0);
-    HMAC_CTX_cleanup(&ctx);
 
     /* Encode the message, prefix `version_2_0', output the result */
-    ASN1_MALLOC_ENCODE(Kx509Request, pre_req.data, pre_req.length, &kx509_req, &len, ret);
-    ret = krb5_data_alloc(req, pre_req.length + sizeof(version_2_0));
+    if (ret == 0)
+        ASN1_MALLOC_ENCODE(Kx509Request, pre_req.data, pre_req.length, &kx509_req, &len, ret);
+    if (ret == 0)
+        ret = krb5_data_alloc(req, pre_req.length + sizeof(version_2_0));
     if (ret == 0) {
         memcpy(req->data, version_2_0, sizeof(version_2_0));
         memcpy(((unsigned char *)req->data) + sizeof(version_2_0),
@@ -984,8 +997,13 @@ rd_kx509_resp(krb5_context context,
     }
 
     HMAC_CTX_init(&ctx);
-    HMAC_Init_ex(&ctx, kx509_ctx->hmac_key->keyvalue.data,
-                 kx509_ctx->hmac_key->keyvalue.length, EVP_sha1(), NULL);
+    if (HMAC_Init_ex(&ctx, kx509_ctx->hmac_key->keyvalue.data,
+                     kx509_ctx->hmac_key->keyvalue.length, EVP_sha1(), NULL) == 0) {
+        free_Kx509Response(&r);
+        HMAC_CTX_cleanup(&ctx);
+        return krb5_enomem(context);
+    }
+
     HMAC_Update(&ctx, version_2_0, sizeof(version_2_0));
 
     {
@@ -1090,7 +1108,7 @@ rd_kx509_resp(krb5_context context,
             ret = errno;
     }
     free_Kx509Response(&r);
-    if (cert) {
+    if (*cert) {
         heim_release(herr);
         return 0;
     }
@@ -1250,7 +1268,9 @@ krb5_kx509(krb5_context context, krb5_ccache cc, const char *realm)
     char *store_exp = NULL;
 
     ret = krb5_kx509_ctx_init(context, &kx509_ctx);
-    if (ret == 0 && realm)
+    if (ret)
+        return ret;
+    if (realm)
         ret = krb5_kx509_ctx_set_realm(context, kx509_ctx, realm);
 
     /*
index 245f4b1bf43703d0bb5b81ec3fb8fa223f46bdaa..191a0c48c8614482e283945919746be5a0aaf750 100644 (file)
@@ -23,6 +23,8 @@ EXPORTS
        krb5_appdefault_time
        krb5_append_addresses
        krb5_auth_con_addflags
+       krb5_auth_con_add_AuthorizationData
+       krb5_auth_con_add_AuthorizationDataIfRelevant
        krb5_auth_con_free
        krb5_auth_con_genaddrs
        krb5_auth_con_generatelocalsubkey
@@ -500,6 +502,7 @@ EXPORTS
        krb5_pac_add_buffer
        krb5_pac_free
        krb5_pac_get_buffer
+       _krb5_pac_get_buffer_by_name
        krb5_pac_get_kdc_checksum_info
        krb5_pac_get_types
        krb5_pac_init
@@ -747,6 +750,7 @@ EXPORTS
        krb5_cccol_cursor_new
        krb5_cccol_cursor_next
        krb5_cccol_cursor_free
+       krb5_cccol_get_default_ccname
 
        ; com_err error tables
        initialize_krb5_error_table_r
@@ -837,6 +841,8 @@ EXPORTS
        _krb5_enctype_requires_random_salt
        _krb5_principal2principalname
        _krb5_principalname2krb5_principal
+       _krb5_kdcrep2krb5_principal
+       _krb5_ticket2krb5_principal
        _krb5_put_int
        _krb5_s4u2self_to_checksumdata
        _krb5_HMAC_MD5_checksum
@@ -857,6 +863,7 @@ EXPORTS
        krb5_init_creds_get_error
        krb5_init_creds_init
        krb5_init_creds_set_fast_anon_pkinit
+       _krb5_init_creds_set_fast_anon_pkinit_optimistic
        krb5_init_creds_set_fast_ccache
        krb5_init_creds_set_keytab
        krb5_init_creds_set_kdc_hostname
index 4ccc415a2619c64acffce4a221f35fc67791dfac..fdd5674c3b87f980f5f35c8af579557f42d67a1f 100644 (file)
@@ -112,10 +112,10 @@ again:
         if (strcmp(m->name, m_c->name) == 0)
             break;
     if (m_c) {
-        free(m->name);
-        free(m);
         if (name && !create_anonymous) {
             /* We raced with another thread to create this cache */
+            free(m->name);
+            free(m);
             m = m_c;
             HEIMDAL_MUTEX_lock(&(m->mutex));
             m->refcnt++;
index 33e62e5b0d2614876cce600b241c706c59f14346..41e858f8058834ba0ab9b096878fd854dc9b897d 100644 (file)
@@ -258,15 +258,16 @@ _krb5_mk_ncred(krb5_context context,
          */
 
         ret = krb5_crypto_init(context, auth_context->keyblock, 0, &crypto);
+        if (ret == 0)
+            ret = krb5_encrypt_EncryptedData(context,
+                                             crypto,
+                                             KRB5_KU_KRB_CRED,
+                                             buf,
+                                             len,
+                                             0,
+                                             &cred.enc_part);
         if (ret)
             goto out;
-        ret = krb5_encrypt_EncryptedData(context,
-                                         crypto,
-                                         KRB5_KU_KRB_CRED,
-                                         buf,
-                                         len,
-                                         0,
-                                         &cred.enc_part);
         DISOWN_BUF(buf);
         krb5_crypto_destroy(context, crypto);
     }
index cd9a6d6d310778e19f3c3a39d528e5e803a1e774..2bdeae8ecd1d006ac5f6385668c1b6e000507fe2 100644 (file)
  */
 
 #include "krb5_locl.h"
+
+#include <heimbasepriv.h>
 #include <wind.h>
+#include <assert.h>
 
 struct PAC_INFO_BUFFER {
     uint32_t type;
@@ -73,6 +76,8 @@ struct krb5_pac_data {
 #define PACTYPE_SIZE                   8
 #define PAC_INFO_BUFFER_SIZE           16
 
+#define PAC_LOGON_INFO                 1
+#define PAC_CREDENTIALS_INFO           2
 #define PAC_SERVER_CHECKSUM            6
 #define PAC_PRIVSVR_CHECKSUM           7
 #define PAC_LOGON_NAME                 10
@@ -94,7 +99,39 @@ struct krb5_pac_data {
                }                                               \
        } while(0)
 
-static const char zeros[PAC_ALIGNMENT] = { 0 };
+static const char zeros[PAC_ALIGNMENT];
+
+static void HEIM_CALLCONV
+pac_dealloc(void *ctx)
+{
+    krb5_pac pac = (krb5_pac)ctx;
+
+    krb5_data_free(&pac->data);
+    krb5_data_free(&pac->ticket_sign_data);
+
+    if (pac->upn_princ) {
+       free_Principal(pac->upn_princ);
+       free(pac->upn_princ);
+    }
+    if (pac->canon_princ) {
+       free_Principal(pac->canon_princ);
+       free(pac->canon_princ);
+    }
+    krb5_data_free(&pac->sid);
+
+    free(pac->pac);
+}
+
+struct heim_type_data pac_object = {
+    HEIM_TID_PAC,
+    "heim-pac",
+    NULL,
+    pac_dealloc,
+    NULL,
+    NULL,
+    NULL,
+    NULL
+};
 
 /*
  * HMAC-MD5 checksum over any key (needed for the PAC routines)
@@ -152,7 +189,7 @@ krb5_pac_parse(krb5_context context, const void *ptr, size_t len,
     krb5_storage *sp = NULL;
     uint32_t i, tmp, tmp2, header_end;
 
-    p = calloc(1, sizeof(*p));
+    p = _heim_alloc_object(&pac_object, sizeof(*p));
     if (p == NULL) {
        ret = krb5_enomem(context);
        goto out;
@@ -302,7 +339,7 @@ out:
     if (p) {
        if (p->pac)
            free(p->pac);
-       free(p);
+       krb5_pac_free(context, p);
     }
     *pac = NULL;
 
@@ -315,21 +352,21 @@ krb5_pac_init(krb5_context context, krb5_pac *pac)
     krb5_error_code ret;
     krb5_pac p;
 
-    p = calloc(1, sizeof(*p));
+    p = _heim_alloc_object(&pac_object, sizeof(*p));
     if (p == NULL) {
        return krb5_enomem(context);
     }
 
     p->pac = calloc(1, sizeof(*p->pac));
     if (p->pac == NULL) {
-       free(p);
+       krb5_pac_free(context, p);
        return krb5_enomem(context);
     }
 
     ret = krb5_data_alloc(&p->data, PACTYPE_SIZE);
     if (ret) {
        free (p->pac);
-       free(p);
+       krb5_pac_free(context, p);
        return krb5_enomem(context);
     }
 
@@ -346,6 +383,8 @@ krb5_pac_add_buffer(krb5_context context, krb5_pac p,
     size_t len, offset, header_end, old_end;
     uint32_t i;
 
+    assert(data->length > 0 && data->data != NULL);
+
     len = p->pac->numbuffers;
 
     ptr = realloc(p->pac,
@@ -394,9 +433,8 @@ krb5_pac_add_buffer(krb5_context context, krb5_pac p,
      * copy in new data part
      */
 
-    if (data->data != NULL)
-       memcpy((unsigned char *)p->data.data + offset,
-              data->data, data->length);
+    memcpy((unsigned char *)p->data.data + offset,
+          data->data, data->length);
     memset((unsigned char *)p->data.data + offset + data->length,
           0, p->data.length - offset - data->length);
 
@@ -433,11 +471,14 @@ krb5_pac_get_buffer(krb5_context context, krb5_pac p,
        if (p->pac->buffers[i].type != type)
            continue;
 
-       ret = krb5_data_copy(data, (unsigned char *)p->data.data + offset, len);
-       if (ret) {
-           krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
-           return ret;
+       if (data) {
+           ret = krb5_data_copy(data, (unsigned char *)p->data.data + offset, len);
+           if (ret) {
+               krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
+               return ret;
+           }
        }
+
        return 0;
     }
     krb5_set_error_message(context, ENOENT, "No PAC buffer of type %lu was found",
@@ -445,6 +486,45 @@ krb5_pac_get_buffer(krb5_context context, krb5_pac p,
     return ENOENT;
 }
 
+static struct {
+    uint32_t type;
+    krb5_data name;
+} pac_buffer_name_map[] = {
+#define PAC_MAP_ENTRY(type, name) { PAC_##type, { sizeof(name) - 1, name } }
+    PAC_MAP_ENTRY(LOGON_INFO,              "logon-info"        ),
+    PAC_MAP_ENTRY(CREDENTIALS_INFO,        "credentials-info"  ),
+    PAC_MAP_ENTRY(SERVER_CHECKSUM,         "server-checksum"   ),
+    PAC_MAP_ENTRY(PRIVSVR_CHECKSUM,        "privsvr-checksum"  ),
+    PAC_MAP_ENTRY(LOGON_NAME,              "client-info"       ),
+    PAC_MAP_ENTRY(CONSTRAINED_DELEGATION,   "delegation-info"   ),
+    PAC_MAP_ENTRY(UPN_DNS_INFO,                    "upn-dns-info"      ),
+    PAC_MAP_ENTRY(TICKET_CHECKSUM,         "ticket-checksum"   ),
+    PAC_MAP_ENTRY(ATTRIBUTES_INFO,         "attributes-info"   ),
+    PAC_MAP_ENTRY(REQUESTOR_SID,           "requestor-sid"     )
+};
+
+/*
+ *
+ */
+
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
+_krb5_pac_get_buffer_by_name(krb5_context context, krb5_pac p,
+                            const krb5_data *name, krb5_data *data)
+{
+    size_t i;
+
+    for (i = 0;
+        i < sizeof(pac_buffer_name_map) / sizeof(pac_buffer_name_map[0]);
+        i++) {
+       if (krb5_data_cmp(name, &pac_buffer_name_map[i].name) == 0)
+           return krb5_pac_get_buffer(context, p, pac_buffer_name_map[i].type, data);
+    }
+
+    krb5_set_error_message(context, ENOENT, "No PAC buffer with name %.*s was found",
+                          (int)name->length, (char *)name->data);
+    return ENOENT;
+}
+
 /*
  *
  */
@@ -476,17 +556,7 @@ krb5_pac_get_types(krb5_context context,
 KRB5_LIB_FUNCTION void KRB5_LIB_CALL
 krb5_pac_free(krb5_context context, krb5_pac pac)
 {
-    if (pac == NULL)
-       return;
-    krb5_data_free(&pac->data);
-    krb5_data_free(&pac->ticket_sign_data);
-
-    krb5_free_principal(context, pac->upn_princ);
-    krb5_free_principal(context, pac->canon_princ);
-    krb5_data_free(&pac->sid);
-
-    free(pac->pac);
-    free(pac);
+    heim_release(pac);
 }
 
 /*
@@ -889,7 +959,7 @@ build_logon_name(krb5_context context,
     krb5_error_code ret;
     krb5_storage *sp;
     uint64_t t;
-    char *s, *s2;
+    char *s, *s2 = NULL;
     size_t s2_len;
 
     t = unix2nttime(authtime);
@@ -936,7 +1006,7 @@ build_logon_name(krb5_context context,
            krb5_set_error_message(context, ret, "Principal %s is not valid UTF-8", s);
            free(s);
            return ret;
-       } else 
+       } else
            free(s);
 
        s2_len = (ucs2_len + 1) * 2;
@@ -965,18 +1035,14 @@ build_logon_name(krb5_context context,
     CHECK(ret, krb5_store_uint16(sp, s2_len), out);
 
     ret = krb5_storage_write(sp, s2, s2_len);
-    free(s2);
     if (ret != (int)s2_len) {
        ret = krb5_enomem(context);
        goto out;
     }
     ret = krb5_storage_to_data(sp, logon);
-    if (ret)
-       goto out;
-    krb5_storage_free(sp);
 
-    return 0;
-out:
+ out:
+    free(s2);
     krb5_storage_free(sp);
     return ret;
 }
@@ -1350,10 +1416,8 @@ _krb5_pac_sign(krb5_context context,
     if (ret == 0) {
         krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE);
         spdata = krb5_storage_emem();
-        if (spdata == NULL) {
-            krb5_storage_free(sp);
+        if (spdata == NULL)
             ret = krb5_enomem(context);
-        }
     }
 
     if (ret)
@@ -1472,7 +1536,8 @@ _krb5_pac_sign(krb5_context context,
        krb5_storage *rs = krb5_storage_emem();
        if (rs == NULL)
            ret = krb5_enomem(context);
-       krb5_storage_set_flags(rs, KRB5_STORAGE_BYTEORDER_LE);
+        else
+            krb5_storage_set_flags(rs, KRB5_STORAGE_BYTEORDER_LE);
         if (ret == 0)
             ret = krb5_store_uint16(rs, rodc_id);
         if (ret == 0)
index 0198400d9eb136a34c4e4d8726462bb013fe6fc9..c9a6e3e8f8b92d97476c587482c92ca2aa4d25b3 100644 (file)
@@ -114,6 +114,14 @@ select_dh_group(krb5_context context, DH *dh, unsigned long bits,
 {
     const struct krb5_dh_moduli *m;
 
+    if (moduli[0] == NULL) {
+        krb5_set_error_message(context, EINVAL,
+                               N_("Did not find a DH group parameter "
+                                  "matching requirement of %lu bits", ""),
+                               bits);
+        return EINVAL;
+    }
+
     if (bits == 0) {
        m = moduli[1]; /* XXX */
        if (m == NULL)
@@ -1198,11 +1206,13 @@ pk_rd_pa_reply_enckey(krb5_context context,
                         &contentType,
                         &unwrapped,
                         &host);
+    if (ret == 0) {
+        krb5_data_free(&content);
+        ret = krb5_data_copy(&content, unwrapped.data, unwrapped.length);
+        der_free_octet_string(&unwrapped);
+    }
     if (ret)
        goto out;
-    krb5_data_free(&content);
-    ret = krb5_data_copy(&content, unwrapped.data, unwrapped.length);
-    der_free_octet_string(&unwrapped);
 
     heim_assert(host || (ctx->id->flags & PKINIT_NO_KDC_ANCHOR),
                "KDC signature must be verified unless PKINIT_NO_KDC_ANCHOR set");
@@ -1831,7 +1841,7 @@ _krb5_pk_set_user_id(krb5_context context,
        ret = der_print_hex_heim_integer(&i, &sn);
        der_free_heim_integer(&i);
        if (ret) {
-           free(name);
+           free(str);
            goto out;
        }
 
@@ -1857,7 +1867,7 @@ _krb5_pk_load_id(krb5_context context,
 {
     struct krb5_pk_identity *id = NULL;
     struct prompter p;
-    int ret;
+    krb5_error_code ret;
 
     *ret_id = NULL;
 
@@ -2100,7 +2110,6 @@ _krb5_parse_moduli_line(krb5_context context,
         m1->q.length = 0;
         m1->q.data = 0;
         krb5_clear_error_message(context);
-       ret = 0;
     }
 
     *m = m1;
index ee25f6acb59dc604d8128f6b91a3a79604e12803..6080e462341594580437de8f4247652161fc91d4 100644 (file)
@@ -103,6 +103,8 @@ krb5_free_principal(krb5_context context,
                    krb5_principal p)
 {
     if(p){
+       if (p->nameattrs && p->nameattrs->pac)
+           heim_release(p->nameattrs->pac);
        free_Principal(p);
        free(p);
     }
@@ -457,6 +459,22 @@ unparse_name_fixed(krb5_context context,
     int no_realm = (flags & KRB5_PRINCIPAL_UNPARSE_NO_REALM) != 0;
     int display = (flags & KRB5_PRINCIPAL_UNPARSE_DISPLAY) != 0;
 
+    if (name == NULL) {
+       krb5_set_error_message(context, EINVAL,
+                              N_("Invalid name buffer, "
+                                 "can't unparse", ""));
+       return EINVAL;
+    }
+
+    if (len == 0) {
+       krb5_set_error_message(context, ERANGE,
+                              N_("Invalid name buffer length, "
+                                 "can't unparse", ""));
+       return ERANGE;
+    }
+
+    name[0] = '\0';
+
     if (!no_realm && princ_realm(principal) == NULL) {
        krb5_set_error_message(context, ERANGE,
                               N_("Realm missing from principal, "
@@ -932,6 +950,9 @@ krb5_copy_principal(krb5_context context,
        free(p);
        return krb5_enomem(context);
     }
+    if (inprinc->nameattrs && inprinc->nameattrs->pac)
+       p->nameattrs->pac = heim_retain(inprinc->nameattrs->pac);
+
     *outprinc = p;
     return 0;
 }
@@ -1766,7 +1787,7 @@ _krb5_get_name_canon_rules(krb5_context context, krb5_name_canon_rule *rules)
                                      "libdefaults", "safe_name_canon", NULL))
         make_rules_safe(context, *rules);
 
-    heim_assert(rules != NULL && (*rules)[0].type != KRB5_NCRT_BOGUS,
+    heim_assert((*rules)[0].type != KRB5_NCRT_BOGUS,
                 "internal error in parsing principal name "
                 "canonicalization rules");
 
@@ -1968,10 +1989,12 @@ apply_name_canon_rule(krb5_context context, krb5_name_canon_rule rules,
         new_hostname = hostname_with_port;
     }
 
-    if (new_realm != NULL)
-        krb5_principal_set_realm(context, *out_princ, new_realm);
-    if (new_hostname != NULL)
-        krb5_principal_set_comp_string(context, *out_princ, 1, new_hostname);
+    if (new_realm != NULL &&
+        (ret = krb5_principal_set_realm(context, *out_princ, new_realm)))
+        goto out;
+    if (new_hostname != NULL &&
+        (ret = krb5_principal_set_comp_string(context, *out_princ, 1, new_hostname)))
+        goto out;
     if (princ_type(*out_princ) == KRB5_NT_SRV_HST_NEEDS_CANON)
         princ_type(*out_princ) = KRB5_NT_SRV_HST;
 
index b24973978409a741353c076806db8495569bdc8d..f8d57362310bb3ef5363d1a7ffa24589d9d64926 100644 (file)
@@ -96,7 +96,7 @@ krb5_rd_cred(krb5_context context,
        goto out;
     }
 
-    if (cred.enc_part.etype == (krb5_enctype)ETYPE_NULL) {
+    if (cred.enc_part.etype == ETYPE_NULL) {
        /* DK: MIT GSS-API Compatibility */
        enc_krb_cred_part_data.length = cred.enc_part.cipher.length;
        enc_krb_cred_part_data.data   = cred.enc_part.cipher.data;
index bd0b68b9cfb5474b7e3acf6f1c3658856d3f99fd..371037c8403f48c2dafc2e8d6eb61b00af102426 100644 (file)
@@ -351,11 +351,6 @@ krb5_verify_ap_req2(krb5_context context,
                                             ap_req->ticket.sname,
                                             ap_req->ticket.realm);
     if (ret) goto out;
-    ret = _krb5_principalname2krb5_principal(context,
-                                            &t->client,
-                                            t->ticket.cname,
-                                            t->ticket.crealm);
-    if (ret) goto out;
 
     ret = decrypt_authenticator (context,
                                 &t->ticket.key,
@@ -387,6 +382,27 @@ krb5_verify_ap_req2(krb5_context context,
        }
     }
 
+    /*
+     * The ticket authenticates the client, and conveys naming attributes that
+     * we want to expose in GSS using RFC6680 APIs.
+     *
+     * So we same the ticket enc-part in the client's krb5_principal object
+     * (note though that the session key will be absent in that copy of the
+     * ticket enc-part).
+     */
+    ret = _krb5_ticket2krb5_principal(context, &t->client, &t->ticket,
+                                      ac->authenticator->authorization_data);
+    if (ret) goto out;
+
+    t->client->nameattrs->peer_realm =
+        calloc(1, sizeof(t->client->nameattrs->peer_realm[0]));
+    if (t->client->nameattrs->peer_realm == NULL) {
+        ret = krb5_enomem(context);
+        goto out;
+    }
+    ret = copy_Realm(&ap_req->ticket.realm, t->client->nameattrs->peer_realm);
+    if (ret) goto out;
+
     /* check addresses */
 
     if (t->ticket.caddr
@@ -458,7 +474,7 @@ krb5_verify_ap_req2(krb5_context context,
 
     if (ap_req_options) {
        *ap_req_options = 0;
-       if (ac->keytype != (krb5_enctype)ETYPE_NULL)
+       if (ac->keytype != ETYPE_NULL)
            *ap_req_options |= AP_OPTS_USE_SUBKEY;
        if (ap_req->ap_options.use_session_key)
            *ap_req_options |= AP_OPTS_USE_SESSION_KEY;
@@ -791,11 +807,10 @@ get_key_from_keytab(krb5_context context,
                             kvno,
                             ap_req->ticket.enc_part.etype,
                             &entry);
-    if(ret)
-       goto out;
-    ret = krb5_copy_keyblock(context, &entry.keyblock, out_key);
-    krb5_kt_free_entry (context, &entry);
-out:
+    if(ret == 0) {
+        ret = krb5_copy_keyblock(context, &entry.keyblock, out_key);
+        krb5_kt_free_entry(context, &entry);
+    }
     if(keytab == NULL)
        krb5_kt_close(context, real_keytab);
 
@@ -840,7 +855,8 @@ krb5_rd_req_ctx(krb5_context context,
     krb5_keytab id = NULL, keytab = NULL;
     krb5_principal service = NULL;
 
-    *outctx = NULL;
+    if (outctx)
+        *outctx = NULL;
 
     o = calloc(1, sizeof(*o));
     if (o == NULL)
@@ -1021,6 +1037,12 @@ krb5_rd_req_ctx(krb5_context context,
             goto out;
     }
 
+    ret = krb5_ticket_get_authorization_data_type(context, o->ticket,
+                                                  KRB5_AUTHDATA_KDC_ISSUED,
+                                                  NULL);
+    if (ret == 0)
+        o->ticket->client->nameattrs->kdc_issued_verified = 1;
+
     /* If there is a PAC, verify its server signature */
     if (inctx == NULL || inctx->check_pac) {
        krb5_pac pac;
@@ -1042,28 +1064,36 @@ krb5_rd_req_ctx(krb5_context context,
                                  o->ticket->client,
                                  o->keyblock,
                                  NULL);
+            if (ret == 0)
+                o->ticket->client->nameattrs->pac_verified = 1;
            if (ret == 0 && (context->flags & KRB5_CTX_F_REPORT_CANONICAL_CLIENT_NAME)) {
                krb5_error_code ret2;
                krb5_principal canon_name;
 
                ret2 = _krb5_pac_get_canon_principal(context, pac, &canon_name);
                if (ret2 == 0) {
-                   krb5_free_principal(context, o->ticket->client);
-                   o->ticket->client = canon_name;
+                    free_Realm(&o->ticket->client->realm);
+                    free_PrincipalName(&o->ticket->client->name);
+                    ret = copy_Realm(&canon_name->realm, &o->ticket->client->realm);
+                    if (ret == 0)
+                        ret = copy_PrincipalName(&canon_name->name, &o->ticket->client->name);
+                    krb5_free_principal(context, canon_name);
                } else if (ret2 != ENOENT)
                    ret = ret2;
            }
-           krb5_pac_free(context, pac);
-           if (ret)
+           if (ret) {
+               krb5_pac_free(context, pac);
                goto out;
+           }
+           o->ticket->client->nameattrs->pac = pac;
        } else
          ret = 0;
     }
 out:
 
-    if (ret || outctx == NULL) {
+    if (ret || outctx == NULL)
        krb5_rd_req_out_ctx_free(context, o);
-    else
+    else
        *outctx = o;
 
     free_AP_REQ(&ap_req);
index d9c442bb27da7823cf7da48b6a1fe8de78d7fb29..2fec8afd1043e013a231e1a93d7e1a1c047ac85b 100644 (file)
@@ -220,8 +220,10 @@ krb5_rc_store(krb5_context context,
     }
     rk_cloexec_file(f);
     count = fread(&tmp, sizeof(ent), 1, f);
-    if(count != 1)
+    if (count != 1) {
+       fclose(f);
        return KRB5_RC_IO_UNKNOWN;
+    }
     t = ent.stamp - tmp.stamp;
     while(fread(&tmp, sizeof(ent), 1, f)){
        if(tmp.stamp < t)
index 38aaa25024e67952dd1a3e5e37cd2dfd04ab92e4..033128ed803d30b790ecc222da5a51f9acdb14e4 100644 (file)
@@ -47,10 +47,8 @@ ARCFOUR_string_to_key(krb5_context context,
     EVP_MD_CTX *m;
 
     m = EVP_MD_CTX_create();
-    if (m == NULL) {
-       ret = krb5_enomem(context);
-       goto out;
-    }
+    if (m == NULL)
+       return krb5_enomem(context);
 
     EVP_DigestInit_ex(m, EVP_md4(), NULL);
 
index 554f377125e3db20dead3583e859581838a4f6bf..7a39664946b8537e45f5698a0e4d7f08245150ef 100644 (file)
@@ -276,9 +276,9 @@ make_dir(krb5_context context, const char *name)
 static krb5_error_code
 default_db(krb5_context context, const char *name, sqlite3 **db, char **file)
 {
+    krb5_error_code ret = 0;
     char *s = NULL;
     char *f = NULL;
-    int ret;
 
     if (file)
         *file = NULL;
@@ -315,13 +315,24 @@ default_db(krb5_context context, const char *name, sqlite3 **db, char **file)
 #endif
 
     ret = make_dir(context, f);
-    if (ret == 0)
-        ret = sqlite3_open_v2(f, db, SQLITE_OPEN_READWRITE, NULL);
-    if (ret != SQLITE_OK) {
-        sqlite3_close(*db);
-       krb5_clear_error_message(context);
-        free(f);
-       return ENOENT;
+    if (ret == 0) {
+        int sret;
+
+        sret = sqlite3_open_v2(f, db, SQLITE_OPEN_READWRITE, NULL);
+        if (sret != SQLITE_OK) {
+            if (*db) {
+                krb5_set_error_message(context, ENOENT,
+                                       N_("Error opening scache file %s: %s (%d)", ""),
+                                       f, sqlite3_errmsg(*db), sret);
+                sqlite3_close(*db);
+                *db = NULL;
+            } else
+                krb5_set_error_message(context, ENOENT,
+                                       N_("Error opening scache file %s: %s (%d)", ""),
+                                       f, sqlite3_errstr(sret), sret);
+            free(f);
+            return ENOENT;
+        }
     }
 
 #ifndef WIN32
@@ -341,7 +352,7 @@ default_db(krb5_context context, const char *name, sqlite3 **db, char **file)
     sqlite3_trace(*db, trace, NULL);
 #endif
 
-    return 0;
+    return ret;
 }
 
 static krb5_error_code
@@ -435,10 +446,8 @@ scc_alloc(krb5_context context,
             name += sizeof("SCC:") - 1;
 
         if ((s->file = strdup(name)) == NULL) {
-            (void) krb5_enomem(context);
-            scc_free(s);
-            free(freeme);
-            return NULL;
+            ret = krb5_enomem(context);
+           goto out;
         }
 
         if ((subsidiary = strrchr(s->file, ':'))) {
@@ -469,19 +478,23 @@ scc_alloc(krb5_context context,
     if (ret == 0 && s->file && s->sub &&
         (asprintf(&s->name, "%s:%s", s->file, s->sub) < 0 || s->name == NULL))
         ret = krb5_enomem(context);
+
+ out:
     if (ret || s->file == NULL || s->sub == NULL || s->name == NULL) {
        scc_free(s);
-        free(freeme);
-       return NULL;
+       s = NULL;
     }
+
+    free(freeme);
     return s;
 }
 
 static krb5_error_code
 open_database(krb5_context context, krb5_scache *s, int flags)
 {
+    krb5_error_code ret;
     struct stat st;
-    int ret;
+    int sret;
 
 
     if (!(flags & SQLITE_OPEN_CREATE) && stat(s->file, &st) == 0 &&
@@ -489,18 +502,20 @@ open_database(krb5_context context, krb5_scache *s, int flags)
         return ENOENT;
 
     ret = make_dir(context, s->file);
-    if (ret == 0)
-    ret = sqlite3_open_v2(s->file, &s->db, SQLITE_OPEN_READWRITE|flags, NULL);
-    if (ret) {
+    if (ret)
+        return ret;
+    sret = sqlite3_open_v2(s->file, &s->db, SQLITE_OPEN_READWRITE|flags, NULL);
+    if (sret != SQLITE_OK) {
        if (s->db) {
            krb5_set_error_message(context, ENOENT,
-                                  N_("Error opening scache file %s: %s", ""),
-                                  s->file, sqlite3_errmsg(s->db));
+                                  N_("Error opening scache file %s: %s (%d)", ""),
+                                  s->file, sqlite3_errmsg(s->db), sret);
            sqlite3_close(s->db);
            s->db = NULL;
        } else
            krb5_set_error_message(context, ENOENT,
-                                  N_("malloc: out of memory", ""));
+                                  N_("Error opening scache file %s: %s (%d)", ""),
+                                   s->file, sqlite3_errstr(sret), sret);
        return ENOENT;
     }
     return 0;
@@ -1270,24 +1285,22 @@ scc_remove_cred(krb5_context context,
 
     sqlite3_finalize(stmt);
 
-    if (id) {
-       ret = prepare_stmt(context, s->db, &stmt,
-                          "DELETE FROM credentials WHERE oid=?");
-       if (ret)
-           return ret;
-       sqlite3_bind_int(stmt, 1, credid);
+    ret = prepare_stmt(context, s->db, &stmt,
+                       "DELETE FROM credentials WHERE oid=?");
+    if (ret)
+        return ret;
+    sqlite3_bind_int(stmt, 1, credid);
 
-       do {
-           ret = sqlite3_step(stmt);
-       } while (ret == SQLITE_ROW);
-       sqlite3_finalize(stmt);
-       if (ret != SQLITE_DONE) {
-           ret = KRB5_CC_IO;
-           krb5_set_error_message(context, ret,
-                                  N_("failed to delete scache credental", ""));
-       } else
-           ret = 0;
-    }
+    do {
+        ret = sqlite3_step(stmt);
+    } while (ret == SQLITE_ROW);
+    sqlite3_finalize(stmt);
+    if (ret != SQLITE_DONE) {
+        ret = KRB5_CC_IO;
+        krb5_set_error_message(context, ret,
+                               N_("failed to delete scache credental", ""));
+    } else
+        ret = 0;
 
     return ret;
 }
index 704b095b5355bab4fe10ca20230272fd8f4220d7..086f2edcd5db58a43e5e3ec2f6c878fc781645b8 100644 (file)
@@ -176,7 +176,7 @@ struct krb5_sendto_ctx_data {
     unsigned int stid;
 };
 
-static void
+static void KRB5_CALLCONV
 dealloc_sendto_ctx(void *ptr)
 {
     krb5_sendto_ctx ctx = (krb5_sendto_ctx)ptr;
@@ -386,7 +386,7 @@ debug_host(krb5_context context, int level, struct host *host, const char *fmt,
 }
 
 
-static void
+static void HEIM_CALLCONV
 deallocate_host(void *ptr)
 {
     struct host *host = ptr;
@@ -1180,7 +1180,7 @@ krb5_sendto_context(krb5_context context,
 
     action = KRB5_SENDTO_INITIAL;
 
-    while (action != KRB5_SENDTO_DONE && action != KRB5_SENDTO_FAILED) {
+    while (1) {
        krb5_krbhst_info *hi;
 
        switch (action) {
@@ -1192,7 +1192,7 @@ krb5_sendto_context(krb5_context context,
                break;
            }
            action = KRB5_SENDTO_KRBHST;
-           /* FALLTHROUGH */
+            fallthrough;
        case KRB5_SENDTO_KRBHST:
            if (ctx->krbhst == NULL) {
                ret = krb5_krbhst_init_flags(context, realm, type,
@@ -1214,7 +1214,7 @@ krb5_sendto_context(krb5_context context,
                handle = heim_retain(ctx->krbhst);
            }
            action = KRB5_SENDTO_TIMEOUT;
-           /* FALLTHROUGH */
+            fallthrough;
        case KRB5_SENDTO_TIMEOUT:
 
            /*
@@ -1308,10 +1308,10 @@ krb5_sendto_context(krb5_context context,
            break;
        case KRB5_SENDTO_FAILED:
            ret = KRB5_KDC_UNREACH;
-           break;
+           goto out;
        case KRB5_SENDTO_DONE:
            ret = 0;
-           break;
+           goto out;
        default:
            heim_abort("invalid krb5_sendto_context state");
        }
index 37e06dec3e84bbfe3f5bd6a8c8d14d0106f2b304..4a12067c68bdeae689bb4b2b40b52699f75c9264 100755 (executable)
@@ -73,7 +73,10 @@ _krb5_SP800_108_HMAC_KDF(krb5_context context,
        unsigned char tmp[4];
        size_t len;
 
-       HMAC_Init_ex(&c, kdf_K1->data, kdf_K1->length, md, NULL);
+        if (HMAC_Init_ex(&c, kdf_K1->data, kdf_K1->length, md, NULL) == 0) {
+            HMAC_CTX_cleanup(&c);
+            return krb5_enomem(context);
+        }
 
        _krb5_put_int(tmp, i + 1, 4);
        HMAC_Update(&c, tmp, 4);
index 6a287bdf950db5d076a8b99288c5338b3dc4fff8..79f8e3adbab096d6b96d66d6836e371448ce582b 100644 (file)
@@ -975,6 +975,10 @@ KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_store_string(krb5_storage *sp, const char *s)
 {
     krb5_data data;
+
+    if (s == NULL)
+       return EINVAL;
+
     data.length = strlen(s);
     data.data = rk_UNCONST(s);
     return krb5_store_data(sp, data);
@@ -1025,9 +1029,13 @@ krb5_ret_string(krb5_storage *sp,
 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_store_stringz(krb5_storage *sp, const char *s)
 {
-    size_t len = strlen(s) + 1;
+    size_t len;
     ssize_t ret;
 
+    if (s == NULL)
+       return EINVAL;
+
+    len = strlen(s) + 1;
     ret = sp->store(sp, s, len);
     if(ret < 0)
        return ret;
@@ -1089,9 +1097,13 @@ krb5_ret_stringz(krb5_storage *sp,
 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_store_stringnl(krb5_storage *sp, const char *s)
 {
-    size_t len = strlen(s);
+    size_t len;
     ssize_t ret;
 
+    if (s == NULL)
+       return EINVAL;
+
+    len = strlen(s);
     ret = sp->store(sp, s, len);
     if(ret < 0)
        return ret;
@@ -1370,16 +1382,18 @@ krb5_ret_times(krb5_storage *sp, krb5_times *times)
 {
     int ret;
     int32_t tmp;
+
     ret = krb5_ret_int32(sp, &tmp);
+    if (ret) return ret;
     times->authtime = tmp;
-    if(ret) return ret;
     ret = krb5_ret_int32(sp, &tmp);
+    if (ret) return ret;
     times->starttime = tmp;
-    if(ret) return ret;
     ret = krb5_ret_int32(sp, &tmp);
+    if (ret) return ret;
     times->endtime = tmp;
-    if(ret) return ret;
     ret = krb5_ret_int32(sp, &tmp);
+    if (ret) return ret;
     times->renew_till = tmp;
     return ret;
 }
index da66e5fa75e552b19cd2f6ba78d667038e1e625b..6a3908f746358c48f08e77632d7758f4b607eaf0 100644 (file)
@@ -33,6 +33,7 @@
 
 #include "krb5_locl.h"
 #include "store-int.h"
+#include <assert.h>
 
 typedef struct emem_storage{
     unsigned char *base;
@@ -45,10 +46,12 @@ static ssize_t
 emem_fetch(krb5_storage *sp, void *data, size_t size)
 {
     emem_storage *s = (emem_storage*)sp->data;
+
+    assert(data != NULL && s->ptr != NULL);
+
     if((size_t)(s->base + s->len - s->ptr) < size)
        size = s->base + s->len - s->ptr;
-    if (data != NULL)
-       memmove(data, s->ptr, size);
+    memmove(data, s->ptr, size);
     sp->seek(sp, size, SEEK_CUR);
     return size;
 }
@@ -56,7 +59,17 @@ emem_fetch(krb5_storage *sp, void *data, size_t size)
 static ssize_t
 emem_store(krb5_storage *sp, const void *data, size_t size)
 {
-    emem_storage *s = (emem_storage*)sp->data;
+    emem_storage *s;
+
+    if (size == 0) {
+       sp->seek(sp, 0, SEEK_CUR);
+       return 0;
+    }
+
+    s = (emem_storage*)sp->data;
+
+    assert(data != NULL);
+
     if(size > (size_t)(s->base + s->size - s->ptr)){
        void *base;
        size_t sz, off;
@@ -71,8 +84,7 @@ emem_store(krb5_storage *sp, const void *data, size_t size)
        s->base = base;
        s->ptr = (unsigned char*)base + off;
     }
-    if (data != NULL)
-       memmove(s->ptr, data, size);
+    memmove(s->ptr, data, size);
     sp->seek(sp, size, SEEK_CUR);
     return size;
 }
@@ -141,6 +153,9 @@ static void
 emem_free(krb5_storage *sp)
 {
     emem_storage *s = sp->data;
+
+    assert(s->base != NULL);
+
     memset_s(s->base, s->len, 0, s->len);
     free(s->base);
 }
index 80323e1d8f263a2a413e68096ac08fb1b90e6aa9..dddaa92457825c17f59e73f55e4b08c633ba81b4 100644 (file)
@@ -137,6 +137,8 @@ stdio_trunc(krb5_storage * sp, off_t offset)
     if (fflush(F(sp)) == EOF)
         return errno;
     tmpoff = ftello(F(sp));
+    if (tmpoff < 0)
+       return errno;
     if (tmpoff > offset)
        tmpoff = offset;
     if (ftruncate(fileno(F(sp)), offset) == -1)
index 120143e51e7b0132a5325b7d1859bf8c3700bd63..36775adef1b4328e4b17ba2fe7d7526b6fe0ce95 100644 (file)
@@ -81,8 +81,8 @@ test_alname(krb5_context context, krb5_const_realm realm,
        }
        krb5_err(context, 1, ret, "krb5_aname_to_localname: %s -> %s",
                 princ, localuser);
-       free(princ);
     }
+    free(princ);
 
     if (strcmp(localname, localuser) != 0) {
        if (ok)
index c3aaef3606a788c731505d04af70bb81dde85f5a..0fd1078339762f7af67bb1e3ce7725d6ca3940c3 100644 (file)
@@ -153,6 +153,7 @@ test_ap(krb5_context context,
            krb5_err(context, 1, ret, "pac parse");
 
        krb5_pac_free(context, pac);
+        krb5_data_free(&data);
     }
 
     krb5_free_ticket(context, ticket);
index 213bb0780d9be99edbdae4c784c4db4fcba9c8ae..0ca582eaaca6e27f1090a76fb7e63336f03e060b 100644 (file)
@@ -670,6 +670,8 @@ test_move(krb5_context context, const char *type)
        krb5_err(context, 1, ret, "krb5_cc_new_unique");
 
     ret = krb5_cc_move(context, fromid, toid);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_cc_move");
 
     ret = krb5_cc_get_principal(context, toid, &p2);
     if (ret)
@@ -916,7 +918,7 @@ test_cccol_dcache(krb5_context context)
     ret = test_cccol(context, dcc, &what);
     free(dcc);
     if (ret)
-        krb5_err(context, 1, errno, "%s", what);
+        krb5_err(context, 1, ret, "%s", what);
 }
 
 static void
@@ -1117,9 +1119,6 @@ main(int argc, char **argv)
 
     test_move(context, krb5_cc_type_file);
     test_move(context, krb5_cc_type_memory);
-#ifdef HAVE_KCM
-    test_move(context, krb5_cc_type_kcm);
-#endif
     test_move(context, krb5_cc_type_scc);
 #if 0
     test_move(context, krb5_cc_type_dcc);
@@ -1204,6 +1203,9 @@ main(int argc, char **argv)
         ret = test_cccol(context, fname, &what);
         if (ret)
             krb5_err(context, 1, ret, "%s", what);
+        free(config);
+        free(fname);
+        free(d);
     }
 
     krb5_free_context(context);
index fbdb5c9c322a1e1b94f357cc8831454be941555d..f722353f664a2d350114998246bac47ac387f998 100644 (file)
@@ -48,11 +48,11 @@ expand_hostname(krb5_context context, const char *host)
     if (ret)
        krb5_err(context, 1, ret, "krb5_expand_hostname(%s)", host);
 
-    free(h);
-
     if (debug_flag)
        printf("hostname: %s -> %s\n", host, h);
 
+    free(h);
+
     ret = krb5_expand_hostname_realms(context, host, &h, &r);
     if (ret)
        krb5_err(context, 1, ret, "krb5_expand_hostname_realms(%s)", host);
index f1255948fc460141934135967a02c1ec5aab79c6..ed8ee9b5f3f46d4039f6075a246c1f5ec86e768b 100644 (file)
@@ -133,6 +133,7 @@ time_hmac_evp(krb5_context context, size_t size, int iterations)
 
     free(buf);
     krb5_free_keyblock_contents(context, &key);
+    krb5_crypto_destroy(context, crypto);
 }
 
 static void
index 526c240f1c4b84cc4f316eade5f68ac5da429b9d..0c7e6b447ae81cf2e53f37afb2b3fbe47cacf45b 100644 (file)
@@ -119,8 +119,11 @@ main(int argc, char **argv)
        during = "decode_Ticket";
        memset(&t, 0, sizeof (t));
        ret = decode_Ticket(cred.ticket.data, cred.ticket.length, &t, &len);
-       if (ret == ASN1_MISSING_FIELD)
+       if (ret == ASN1_MISSING_FIELD) {
+            krb5_free_cred_contents(context, &cred);
+            memset(&cred, 0, sizeof (cred));
            continue;
+        }
        if (ret) goto err;
        if (t.enc_part.kvno) {
            *t.enc_part.kvno = 0;
index 11e4e84963b2d48835ded9a55b00dcb8e820b80a..e2f2ab2085c6532c46cd100cc2298f1c39af8825 100644 (file)
@@ -204,13 +204,38 @@ krb5_ticket_get_flags(krb5_context context,
     return TicketFlags2int(ticket->ticket.flags);
 }
 
+/*
+ * Find an authz-data element in the given `ad'.  If `failp', then validate any
+ * containing AD-KDC-ISSUED's keyed checksum with the `sessionkey' (if given).
+ *
+ * All AD-KDC-ISSUED will be validated (if requested) even when `type' is
+ * `KRB5_AUTHDATA_KDC_ISSUED'.
+ *
+ * Only the first matching element will be output (via `data').
+ *
+ * Note that all AD-KDC-ISSUEDs found while traversing the authz-data will be
+ * validated, though only the first one will be returned.
+ *
+ * XXX We really need a better interface though.  First, forget AD-AND-OR --
+ * just remove it.  Second, probably forget AD-KDC-ISSUED, but still, between
+ * that, the PAC, and the CAMMAC, we need an interface that can:
+ *
+ * a) take the derived keys instead of the service key or the session key,
+ * b) can indicate whether the element was marked critical,
+ * c) can indicate whether the element was authenticated to the KDC,
+ * d) can iterate over all the instances found (if more than one is found).
+ *
+ * Also, we need to know here if the authz-data is from a Ticket or from an
+ * Authenticator -- if the latter then we must refuse to find AD-KDC-ISSUED /
+ * PAC / CAMMAC or anything of the sort, ever.
+ */
 static int
 find_type_in_ad(krb5_context context,
                int type,
-               krb5_data *data,
+               krb5_data *data,                /* optional */
                krb5_boolean *found,
-               krb5_boolean failp,
-               krb5_keyblock *sessionkey,
+               krb5_boolean failp,             /* validate AD-KDC-ISSUED */
+               krb5_keyblock *sessionkey,      /* ticket session key */
                const AuthorizationData *ad,
                int level)
 {
@@ -233,14 +258,19 @@ find_type_in_ad(krb5_context context,
      */
     for (i = 0; i < ad->len; i++) {
        if (!*found && ad->val[i].ad_type == type) {
-           ret = der_copy_octet_string(&ad->val[i].ad_data, data);
-           if (ret) {
-               krb5_set_error_message(context, ret,
-                                      N_("malloc: out of memory", ""));
-               goto out;
-           }
+            if (data) {
+                ret = der_copy_octet_string(&ad->val[i].ad_data, data);
+                if (ret) {
+                    krb5_set_error_message(context, ret,
+                                           N_("malloc: out of memory", ""));
+                    goto out;
+                }
+            }
            *found = TRUE;
-           continue;
+            if (type != KRB5_AUTHDATA_KDC_ISSUED ||
+                !failp || !sessionkey || !sessionkey->keyvalue.length)
+                continue;
+            /* else go on to validate the AD-KDC-ISSUED's keyed checksum */
        }
        switch (ad->val[i].ad_type) {
        case KRB5_AUTHDATA_IF_RELEVANT: {
@@ -263,7 +293,6 @@ find_type_in_ad(krb5_context context,
                goto out;
            break;
        }
-#if 0 /* XXX test */
        case KRB5_AUTHDATA_KDC_ISSUED: {
            AD_KDCIssued child;
 
@@ -278,7 +307,7 @@ find_type_in_ad(krb5_context context,
                                       ret);
                goto out;
            }
-           if (failp) {
+           if (failp && sessionkey && sessionkey->keyvalue.length) {
                krb5_boolean valid;
                krb5_data buf;
                size_t len;
@@ -306,7 +335,12 @@ find_type_in_ad(krb5_context context,
                    free_AD_KDCIssued(&child);
                    goto out;
                }
-           }
+           } else if (failp) {
+                   krb5_clear_error_message(context);
+                   ret = ENOENT;
+                   free_AD_KDCIssued(&child);
+                   goto out;
+            }
            ret = find_type_in_ad(context, type, data, found, failp, sessionkey,
                                  &child.elements, level + 1);
            free_AD_KDCIssued(&child);
@@ -314,7 +348,6 @@ find_type_in_ad(krb5_context context,
                goto out;
            break;
        }
-#endif
        case KRB5_AUTHDATA_AND_OR:
            if (!failp)
                break;
@@ -338,7 +371,8 @@ find_type_in_ad(krb5_context context,
 out:
     if (ret) {
        if (*found) {
-           krb5_data_free(data);
+            if (data)
+                krb5_data_free(data);
            *found = 0;
        }
     }
@@ -355,7 +389,8 @@ _krb5_get_ad(krb5_context context,
     krb5_boolean found = FALSE;
     krb5_error_code ret;
 
-    krb5_data_zero(data);
+    if (data)
+        krb5_data_zero(data);
 
     if (ad == NULL) {
        krb5_set_error_message(context, ENOENT,
@@ -399,7 +434,8 @@ krb5_ticket_get_authorization_data_type(krb5_context context,
     krb5_error_code ret;
     krb5_boolean found = FALSE;
 
-    krb5_data_zero(data);
+    if (data)
+        krb5_data_zero(data);
 
     ad = ticket->ticket.authorization_data;
     if (ticket->ticket.authorization_data == NULL) {
@@ -752,9 +788,9 @@ _krb5_extract_ticket(krb5_context context,
 
     /* compare client and save */
     ret = _krb5_principalname2krb5_principal(context,
-                                            &tmp_principal,
-                                            rep->kdc_rep.cname,
-                                            rep->kdc_rep.crealm);
+                                             &tmp_principal,
+                                             rep->kdc_rep.cname,
+                                             rep->kdc_rep.crealm);
     if (ret)
        goto out;
 
@@ -785,12 +821,19 @@ _krb5_extract_ticket(krb5_context context,
     creds->client = tmp_principal;
 
     /* check server referral and save principal */
-    ret = _krb5_principalname2krb5_principal (context,
-                                             &tmp_principal,
-                                             rep->enc_part.sname,
-                                             rep->enc_part.srealm);
+    ret = _krb5_kdcrep2krb5_principal(context, &tmp_principal, &rep->enc_part);
     if (ret)
        goto out;
+
+    tmp_principal->nameattrs->peer_realm =
+        calloc(1, sizeof(tmp_principal->nameattrs->peer_realm[0]));
+    if (tmp_principal->nameattrs->peer_realm == NULL) {
+        ret = krb5_enomem(context);
+        goto out;
+    }
+    ret = copy_Realm(&creds->client->realm, tmp_principal->nameattrs->peer_realm);
+    if (ret) goto out;
+
     if((flags & EXTRACT_TICKET_ALLOW_SERVER_MISMATCH) == 0){
        ret = check_server_referral(context,
                                    rep,
index 35c00e65add4a22c2439d03b3cb8461ce9925ab6..484fd398c29609bf628b5292658f73060cdf4ebc 100644 (file)
@@ -274,13 +274,17 @@ decode_realms(krb5_context context,
        }
        if(tr[i] == ','){
            tmp = malloc(tr + i - start + 1);
-           if(tmp == NULL)
+           if(tmp == NULL) {
+               free_realms(*realms);
+                *realms = NULL;
                return krb5_enomem(context);
+            }
            memcpy(tmp, start, tr + i - start);
            tmp[tr + i - start] = '\0';
            r = make_realm(tmp);
            if(r == NULL){
                free_realms(*realms);
+                *realms = NULL;
                return krb5_enomem(context);
            }
            *realms = append_realm(*realms, r);
@@ -289,7 +293,8 @@ decode_realms(krb5_context context,
     }
     tmp = malloc(tr + i - start + 1);
     if(tmp == NULL){
-       free(*realms);
+        free_realms(*realms);
+        *realms = NULL;
        return krb5_enomem(context);
     }
     memcpy(tmp, start, tr + i - start);
@@ -297,6 +302,7 @@ decode_realms(krb5_context context,
     r = make_realm(tmp);
     if(r == NULL){
        free_realms(*realms);
+        *realms = NULL;
        return krb5_enomem(context);
     }
     *realms = append_realm(*realms, r);
@@ -353,8 +359,6 @@ krb5_domain_x500_decode(krb5_context context,
     {
        char **R;
        R = malloc((*num_realms + 1) * sizeof(*R));
-       if (R == NULL)
-           return krb5_enomem(context);
        *realms = R;
        while(r){
            *R++ = r->realm;
@@ -362,6 +366,8 @@ krb5_domain_x500_decode(krb5_context context,
            free(r);
            r = p;
        }
+       if (*realms == NULL)
+           return krb5_enomem(context);
     }
     return 0;
 }
@@ -621,11 +627,12 @@ krb5_check_transited(krb5_context context,
         return ret;
 
     for (i = 0; i < num_realms; i++) {
-       for (j = 0; j < num_capath; ++j) {
+       for (j = 0; j < num_capath && capath[j]; ++j) {
+            /* `capath[j]' can't be NULL, but compilers be dumb */
            if (strcmp(realms[i], capath[j]) == 0)
                break;
        }
-       if (j == num_capath) {
+       if (j == num_capath || !capath[j]) {
             _krb5_free_capath(context, capath);
            krb5_set_error_message (context, KRB5KRB_AP_ERR_ILL_CR_TKT,
                                    N_("no transit allowed "
index 663196b29b15a210aa2e826d651a134658c3207c..c6ead8e42b2de185e1013568fa443c71bf5b6b9f 100644 (file)
@@ -40,7 +40,7 @@ verify_common (krb5_context context,
               krb5_keytab keytab,
               krb5_boolean secure,
               const char *service,
-              krb5_creds cred)
+              krb5_creds *cred)
 {
     krb5_error_code ret;
     krb5_principal server;
@@ -56,7 +56,7 @@ verify_common (krb5_context context,
     krb5_verify_init_creds_opt_set_ap_req_nofail(&vopt, secure);
 
     ret = krb5_verify_init_creds(context,
-                                &cred,
+                                cred,
                                 server,
                                 keytab,
                                 NULL,
@@ -71,12 +71,11 @@ verify_common (krb5_context context,
     if(ret == 0){
        ret = krb5_cc_initialize(context, id, principal);
        if(ret == 0){
-           ret = krb5_cc_store_cred(context, id, &cred);
+           ret = krb5_cc_store_cred(context, id, cred);
        }
        if(ccache == NULL)
            krb5_cc_close(context, id);
     }
-    krb5_free_cred_contents(context, &cred);
     return ret;
 }
 
@@ -172,10 +171,12 @@ verify_user_opt_int(krb5_context context,
     if(ret)
        return ret;
 #define OPT(V, D) ((vopt && (vopt->V)) ? (vopt->V) : (D))
-    return verify_common (context, principal, OPT(ccache, NULL),
+    ret = verify_common (context, principal, OPT(ccache, NULL),
                          OPT(keytab, NULL), vopt ? vopt->secure : TRUE,
-                         OPT(service, "host"), cred);
+                         OPT(service, "host"), &cred);
 #undef OPT
+    krb5_free_cred_contents(context, &cred);
+    return ret;
 }
 
 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
index ce2783c3575286b39fe5e4bf5fb335eb61ffc38e..f6278e9ecbf64016b47d581af751c44242b28bd7 100644 (file)
@@ -24,6 +24,8 @@ HEIMDAL_KRB5_2.0 {
                krb5_appdefault_time;
                krb5_append_addresses;
                krb5_auth_con_addflags;
+               krb5_auth_con_add_AuthorizationData;
+               krb5_auth_con_add_AuthorizationDataIfRelevant;
                krb5_auth_con_free;
                krb5_auth_con_genaddrs;
                krb5_auth_con_generatelocalsubkey;
@@ -493,6 +495,7 @@ HEIMDAL_KRB5_2.0 {
                krb5_pac_add_buffer;
                krb5_pac_free;
                krb5_pac_get_buffer;
+               _krb5_pac_get_buffer_by_name;
                krb5_pac_get_kdc_checksum_info;
                krb5_pac_get_types;
                krb5_pac_init;
@@ -739,6 +742,7 @@ HEIMDAL_KRB5_2.0 {
                krb5_cccol_cursor_new;
                krb5_cccol_cursor_next;
                krb5_cccol_cursor_free;
+               krb5_cccol_get_default_ccname;
 
                # com_err error tables
                initialize_krb5_error_table_r;
@@ -828,6 +832,8 @@ HEIMDAL_KRB5_2.0 {
                _krb5_plugin_run_f;
                _krb5_principal2principalname;
                _krb5_principalname2krb5_principal;
+               _krb5_kdcrep2krb5_principal;
+               _krb5_ticket2krb5_principal;
                _krb5_put_int;
                _krb5_s4u2self_to_checksumdata;
                _krb5_HMAC_MD5_checksum;
@@ -842,6 +848,7 @@ HEIMDAL_KRB5_2.0 {
                krb5_init_creds_init;
                krb5_init_creds_set_service;
                krb5_init_creds_set_fast_anon_pkinit;
+               _krb5_init_creds_set_fast_anon_pkinit_optimistic;
                krb5_init_creds_set_fast_ccache;
                krb5_init_creds_set_keytab;
                krb5_init_creds_set_kdc_hostname;
index a1d6b5f3a6492be3213bb56a864088f1b23fbfa3..761e1f497fcb9c7ddbfc9d90c5b9f3867690db21 100644 (file)
@@ -471,7 +471,7 @@ heim_digest_generate_challenge(heim_digest_t context)
            break;
        case HEIM_DIGEST_TYPE_AUTO:
            context->type = HEIM_DIGEST_TYPE_RFC2831;
-           /* FALLTHROUGH */
+            fallthrough;
        case HEIM_DIGEST_TYPE_RFC2831:
            asprintf(&challenge, "realm=\"%s\",nonce=\"%s\",qop=\"%s\",algorithm=md5-sess,charset=utf-8,maxbuf=%s",
                     context->serverRealm, context->serverNonce, context->serverQOP, context->serverMaxbuf);
index 9670a9718301903b53315e91ed1a44c4ddbc209d..d75752ea00075e39a0d9be3bedb486004b3df74d 100644 (file)
@@ -354,7 +354,7 @@ ret_string(krb5_storage *sp, int ucs2, size_t len, char **s)
        utf8len += 1;
        
        *s = malloc(utf8len);
-       if (s == NULL) {
+       if (*s == NULL) {
            ret = ENOMEM;
            goto out;
        }
@@ -1324,7 +1324,10 @@ heim_ntlm_v2_base_session(void *key, size_t len,
 
     /* Note: key is the NTLMv2 key */
     HMAC_CTX_init(&c);
-    HMAC_Init_ex(&c, key, len, EVP_md5(), NULL);
+    if (HMAC_Init_ex(&c, key, len, EVP_md5(), NULL) == 0) {
+        HMAC_CTX_cleanup(&c);
+        return ENOMEM;
+    }
     HMAC_Update(&c, ntlmResponse->data, 16);
     HMAC_Final(&c, session->data, &hmaclen);
     HMAC_CTX_cleanup(&c);
@@ -1443,7 +1446,7 @@ heim_ntlm_build_ntlm2_master(void *key, size_t len,
 
     ret = heim_ntlm_v2_base_session(key, len, blob, &sess);
     if (ret)
-       return ret;
+        return ret;
 
     ret = heim_ntlm_keyex_wrap(&sess, session, master);
     heim_ntlm_free_buf(&sess);
@@ -1523,25 +1526,26 @@ heim_ntlm_ntlmv2_key(const void *key, size_t len,
 {
     int ret;
     unsigned int hmaclen;
+    struct ntlm_buf buf;
     HMAC_CTX c;
 
     HMAC_CTX_init(&c);
-    HMAC_Init_ex(&c, key, len, EVP_md5(), NULL);
-    {
-       struct ntlm_buf buf;
-       /* uppercase username and turn it into ucs2-le */
-       ret = ascii2ucs2le(username, 1, &buf);
-       if (ret)
-           goto out;
-       HMAC_Update(&c, buf.data, buf.length);
-       free(buf.data);
-       /* turn target into ucs2-le */
-       ret = ascii2ucs2le(target, upper_case_target, &buf);
-       if (ret)
-           goto out;
-       HMAC_Update(&c, buf.data, buf.length);
-       free(buf.data);
+    if (HMAC_Init_ex(&c, key, len, EVP_md5(), NULL) == 0) {
+        ret = ENOMEM;
+        goto out;
     }
+    /* uppercase username and turn it into ucs2-le */
+    ret = ascii2ucs2le(username, 1, &buf);
+    if (ret)
+        goto out;
+    HMAC_Update(&c, buf.data, buf.length);
+    free(buf.data);
+    /* turn target into ucs2-le */
+    ret = ascii2ucs2le(target, upper_case_target, &buf);
+    if (ret)
+        goto out;
+    HMAC_Update(&c, buf.data, buf.length);
+    free(buf.data);
     HMAC_Final(&c, ntlmv2, &hmaclen);
  out:
     HMAC_CTX_cleanup(&c);
@@ -1599,6 +1603,7 @@ heim_ntlm_calculate_lm2(const void *key, size_t len,
                        struct ntlm_buf *answer)
 {
     unsigned char clientchallenge[8];
+    krb5_error_code ret;
 
     if (RAND_bytes(clientchallenge, sizeof(clientchallenge)) != 1)
        return HNTLM_ERR_RAND;
@@ -1612,12 +1617,12 @@ heim_ntlm_calculate_lm2(const void *key, size_t len,
         return ENOMEM;
     answer->length = 24;
 
-    heim_ntlm_derive_ntlm2_sess(ntlmv2, clientchallenge, 8,
-                               serverchallenge, answer->data);
-
-    memcpy(((unsigned char *)answer->data) + 16, clientchallenge, 8);
+    ret = heim_ntlm_derive_ntlm2_sess(ntlmv2, clientchallenge, 8,
+                                      serverchallenge, answer->data);
+    if (ret == 0)
+        memcpy(((unsigned char *)answer->data) + 16, clientchallenge, 8);
 
-    return 0;
+    return ret;
 }
 
 
@@ -1695,7 +1700,10 @@ heim_ntlm_calculate_ntlm2(const void *key, size_t len,
     krb5_storage_free(sp);
     sp = NULL;
 
-    heim_ntlm_derive_ntlm2_sess(ntlmv2, data.data, data.length, serverchallenge, ntlmv2answer);
+    ret = heim_ntlm_derive_ntlm2_sess(ntlmv2, data.data, data.length,
+                                      serverchallenge, ntlmv2answer);
+    if (ret)
+        return ret;
 
     sp = krb5_storage_emem();
     if (sp == NULL) {
@@ -1809,10 +1817,13 @@ verify_ntlm2(const void *key, size_t len,
        goto out;
     }
 
-    heim_ntlm_derive_ntlm2_sess(ntlmv2,
-                               ((unsigned char *)answer->data) + 16, answer->length - 16,
-                               serverchallenge,
-                               serveranswer);
+    ret = heim_ntlm_derive_ntlm2_sess(ntlmv2,
+                                      ((unsigned char *)answer->data) + 16,
+                                      answer->length - 16,
+                                      serverchallenge,
+                                      serveranswer);
+    if (ret)
+        goto out;
 
     if (memcmp(serveranswer, clientanswer, 16) != 0) {
        heim_ntlm_free_buf(infotarget);
@@ -1995,7 +2006,7 @@ heim_ntlm_calculate_ntlm2_sess_hash(const unsigned char clnt_nonce[8],
  * @ingroup ntlm_core
  */
 
-void
+int
 heim_ntlm_derive_ntlm2_sess(const unsigned char sessionkey[16],
                            const unsigned char *clnt_nonce, size_t clnt_nonce_length,
                            const unsigned char svr_chal[8],
@@ -2006,10 +2017,14 @@ heim_ntlm_derive_ntlm2_sess(const unsigned char sessionkey[16],
 
     /* HMAC(Ksession, serverchallenge || clientchallenge) */
     HMAC_CTX_init(&c);
-    HMAC_Init_ex(&c, sessionkey, 16, EVP_md5(), NULL);
+    if (HMAC_Init_ex(&c, sessionkey, 16, EVP_md5(), NULL) == 0) {
+        HMAC_CTX_cleanup(&c);
+        return ENOMEM;
+    }
     HMAC_Update(&c, svr_chal, 8);
     HMAC_Update(&c, clnt_nonce, clnt_nonce_length);
     HMAC_Final(&c, derivedkey, &hmaclen);
     HMAC_CTX_cleanup(&c);
     memset(&c, 0, sizeof(c));
+    return 0;
 }
index 1d6fe9594373cc9bb04a727de4a1d7d5e71ce007..9338a204def5a975c43781e33e639bfe98dd45e1 100644 (file)
@@ -92,8 +92,6 @@ otp_md_init (OtpKey key,
     char *p;
     int len;
 
-    ctx = EVP_MD_CTX_create();
-
     len = strlen(pwd) + strlen(seed);
     p = malloc (len + 1);
     if (p == NULL)
@@ -102,6 +100,8 @@ otp_md_init (OtpKey key,
     strlwr (p);
     strlcat (p, pwd, len + 1);
 
+    ctx = EVP_MD_CTX_create();
+
     EVP_DigestInit_ex(ctx, md, NULL);
     EVP_DigestUpdate(ctx, p, len);
     EVP_DigestFinal_ex(ctx, res, NULL);
index a6168f944d47f1406c2aa4d62b47ac3ca4787a1e..35d753204e79dab90c02851106d88e1ce3166900 100644 (file)
@@ -21,7 +21,7 @@ AM_CPPFLAGS += -I$(DBHEADER)
 endif
 
 bin_PROGRAMS = rkvis rkbase32 rkbase64
-noinst_PROGRAMS = snprintf-test resolve-test rkpty test-detach test-auxval rtbl
+noinst_PROGRAMS = snprintf-test resolve-test rkpty test-detach test-auxval rtbl timeval
 
 CHECK_LOCAL = snprintf-test resolve-test rkpty make-roken
 
@@ -40,6 +40,7 @@ check_PROGRAMS =                              \
                parse_time-test                 \
                snprintf-test                   \
                strpftime-test                  \
+               timeval                         \
                tsearch-test
 
 TESTS = $(check_PROGRAMS)
@@ -89,6 +90,9 @@ else
 vis_h = vis.h
 endif
 
+timeval_SOURCES = timeval.c
+timeval_CPPFLAGS = -DTEST
+
 rkvis_SOURCES = vis.c $(vis_h) vis-extras.h
 rkvis_CPPFLAGS = -DTEST
 
index bea2866e47d367b583b3243038474aab9c21ddab..e30c193c478eba976e517e99a0dbd24e1718741d 100644 (file)
@@ -66,7 +66,8 @@ main(int argc, char **argv)
     for(t = tests; t->data; t++) {
        char *str;
        int len;
-       len = rk_base32_encode(t->data, t->len, &str, t->preserve_order);
+
+       (void) rk_base32_encode(t->data, t->len, &str, t->preserve_order);
        if (strcmp(str, t->result) != 0) {
            fprintf(stderr, "failed test %d: %s != %s\n", numtest,
                    str, t->result);
index 638ec2925f2e1e93ce4e442d783caa7eebde635d..ef74336d70a6618344ca3076380c9d354cd9bed9 100644 (file)
@@ -100,10 +100,10 @@ rk_base32_encode(const void *data, int size, char **str, enum rk_base32_flags fl
        p[6] = chars[(c & 0x0000000000000003e0ULL) >> 5];
        p[7] = chars[(c & 0x00000000000000001fULL) >> 0];
         switch (i - size) {
-        case 4: p[2] = p[3] = '=';  /*fallthrough*/
-        case 3: p[4] = '=';         /*fallthrough*/
-        case 2: p[5] = p[6] = '=';  /*fallthrough*/
-        case 1: p[7] = '=';         /*fallthrough*/
+        case 4: p[2] = p[3] = '=';  fallthrough;
+        case 3: p[4] = '=';         fallthrough;
+        case 2: p[5] = p[6] = '=';  fallthrough;
+        case 1: p[7] = '=';         fallthrough;
         default:                    break;
         }
        p += 8;
@@ -271,7 +271,7 @@ main(int argc, char **argv)
     } else {
         void *d;
 
-        if ((ret = rk_undumpdata(argv[0], &d, &bufsz)))
+        if ((errno = rk_undumpdata(argv[0], &d, &bufsz)))
             err(1, "Could not read %s", argv[0]);
         buflen = bufsz;
         buf = d;
@@ -298,7 +298,7 @@ main(int argc, char **argv)
         if (fwrite(d, ret, 1, stdout) != 1)
             err(1, "Could not write decoded data");
         free(d);
-    } else {
+    } else if (buf) { /* buf can be NULL if we read from an empty file */
         char *e;
 
         if ((ret = rk_base32_encode(buf, buflen, &e, flags)) < 0)
index 86cccbb1d4f95c5d07f080638bcd487190a74b84..8fb3f528001fa9cf4a025551bf39e671b3490da3 100644 (file)
@@ -58,7 +58,8 @@ main(int argc, char **argv)
     for(t = tests; t->data; t++) {
        char *str;
        int len;
-       len = rk_base64_encode(t->data, t->len, &str);
+
+       (void) rk_base64_encode(t->data, t->len, &str);
        if(strcmp(str, t->result) != 0) {
            fprintf(stderr, "failed test %d: %s != %s\n", numtest,
                    str, t->result);
index a6dacdd1d294405b5b476465a41d5bd8e3b6c24f..582d183bcf731dcf9ccb1c8edcbd55c0439b532e 100644 (file)
@@ -214,7 +214,7 @@ main(int argc, char **argv)
             err(1, "Could not read stdin");
     } else {
         void *d;
-        if ((ret = rk_undumpdata(argv[0], &d, &bufsz)))
+        if ((errno = rk_undumpdata(argv[0], &d, &bufsz)))
             err(1, "Could not read %s", argv[0]);
         buflen = bufsz;
         buf = d;
@@ -241,7 +241,7 @@ main(int argc, char **argv)
         if (fwrite(d, ret, 1, stdout) != 1)
             err(1, "Could not write decoded data");
         free(d);
-    } else {
+    } else if (buf) { /* buf can be NULL if we read from an empty file */
         char *e;
 
         if ((ret = rk_base64_encode(buf, buflen, &e)) < 0)
index 4ed630210fc82a925b97dc6b7748a1c9c1f3736d..9b9dba2aea595f064a040aac4a2b37ff6543a70a 100644 (file)
@@ -40,7 +40,7 @@
  */
 
 ROKEN_LIB_FUNCTION struct hostent * ROKEN_LIB_CALL
-copyhostent (const struct hostent *h)
+rk_copyhostent(const struct hostent *h)
 {
     struct hostent *res;
     char **p;
@@ -96,4 +96,3 @@ copyhostent (const struct hostent *h)
     }
     return res;
 }
-
index 36e6cda1e027dcd055c7893cde927d6a2b8a591e..4a00682511fa179f6db01dcbc71477883dcd642b 100644 (file)
@@ -75,7 +75,8 @@ roken_detach_prep(int argc, char **argv, char *special_arg)
     if (pipefds[1] == -1)
         err(1, "Out of memory");
 #else
-    fcntl(pipefds[1], F_SETFD, fcntl(pipefds[1], F_GETFD & ~(O_CLOEXEC)));
+    (void) fcntl(pipefds[1], F_SETFD,
+                 fcntl(pipefds[1], F_GETFD & ~(O_CLOEXEC)));
 #endif
 
     if (snprintf(fildes, sizeof(fildes), "%d", pipefds[1]) >= sizeof(fildes))
index f1035a1aed6adcf1f5ec9c10f3df82f6dcd3fb53..dc4518ad5b0412704b6d1a3f9b80281528ad4fb1 100644 (file)
@@ -28,7 +28,7 @@
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  **********************************************************************/
-
+#include <config.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdarg.h>
@@ -148,7 +148,7 @@ int teardown_test(void)
 
         strcmp(dirname + len + 1 - sizeof(TESTDIR)/sizeof(char), TESTDIR) == 0) {
 
-        /* fallthrough */
+        fallthrough;
 
     } else {
         /* did we create the directory? */
@@ -162,7 +162,7 @@ int teardown_test(void)
                     fprintf(stderr, "Can't change to test directory. Aborting cleanup.\n");
                     return -1;
                 } else {
-                    /* fallthrough */
+                    fallthrough;
                 }
             } else {
                 return -1;
index 64c354d62bbd5f93e1a2615e5c14f23aecd4138a..a14f27b8a93129f83a936555cbef31c91eb4a332 100644 (file)
@@ -62,7 +62,8 @@ find_var(char **env, char *assignment, size_t len)
 static int
 read_env_file(FILE *F, char ***env, int *assigned)
 {
-    int idx = 0;
+    size_t alloced = 0;
+    size_t idx = 0;
     int i;
     char **l;
     char buf[BUFSIZ], *p, *r;
@@ -71,8 +72,11 @@ read_env_file(FILE *F, char ***env, int *assigned)
 
     *assigned = 0;
 
-    for(idx = 0; *env != NULL && (*env)[idx] != NULL; idx++);
     l = *env;
+    for (idx = 0; l != NULL && l[idx] != NULL; idx++)
+        ;
+    if (l)
+        alloced = idx + 1;
 
     /* This is somewhat more relaxed on what it accepts then
      * Wietses sysv_environ from K4 was...
@@ -90,7 +94,11 @@ read_env_file(FILE *F, char ***env, int *assigned)
            continue;
 
        if((i = find_var(l, p, r - p + 1)) >= 0) {
-           char *val = strdup(p);
+           char *val;
+
+            if ((size_t)i >= alloced)
+                continue; /* Doesn't happen (fix scan-build noise) */
+           val = strdup(p);
            if(val == NULL) {
                ret = ENOMEM;
                break;
@@ -114,6 +122,7 @@ read_env_file(FILE *F, char ***env, int *assigned)
            break;
        }
        l[++idx] = NULL;
+        alloced = idx + 1;
        (*assigned)++;
     }
     if(ferror(F))
index 7dfe492179d132ad8144f0199115b8a1fee328fc..74f35283d3570da10606f9ecada4bf0167620e52 100644 (file)
@@ -129,7 +129,7 @@ rk_fnmatch(const char *pattern, const char *string, int flags)
                                        --pattern;
                                }
                        }
-                       /* FALLTHROUGH */
+                        fallthrough;
                default:
                        if (c != *string++)
                                return (FNM_NOMATCH);
index 7132e95dd38d505ba0f1edd15746ffc8ab8ff343..80a7487b8d5e589d89628621efc0a77eaf70cbf5 100644 (file)
@@ -40,7 +40,7 @@
  */
 
 ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
-freeaddrinfo(struct addrinfo *ai)
+rk_freeaddrinfo(struct addrinfo *ai)
 {
     struct addrinfo *tofree;
 
index 61fbb223b5ec09af9c6d1e2207458969d4622c0d..05dd0fe385ce3c3c1e6e4af858ec5fe26eb1f57c 100644 (file)
@@ -40,7 +40,7 @@
  */
 
 ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
-freehostent (struct hostent *h)
+rk_freehostent(struct hostent *h)
 {
     char **p;
 
index c8ed95413fe35c45294a549478e6daad6d99b769..12a26a712259639635e0724eb65f567c9c4d79e4 100644 (file)
@@ -366,10 +366,10 @@ get_nodes (const char *nodename,
  */
 
 ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
-getaddrinfo(const char *nodename,
-           const char *servname,
-           const struct addrinfo *hints,
-           struct addrinfo **res)
+rk_getaddrinfo(const char *nodename,
+              const char *servname,
+              const struct addrinfo *hints,
+              struct addrinfo **res)
 {
     int ret;
     int port     = 0;
@@ -409,6 +409,6 @@ getaddrinfo(const char *nodename,
        ret = get_null (hints, port, protocol, socktype, res);
     }
     if (ret)
-       freeaddrinfo (*res);
+       rk_freeaddrinfo(*res);
     return ret;
 }
diff --git a/third_party/heimdal/lib/roken/getcap.c b/third_party/heimdal/lib/roken/getcap.c
deleted file mode 100644 (file)
index a8dd94b..0000000
+++ /dev/null
@@ -1,996 +0,0 @@
-/*     $NetBSD: getcap.c,v 1.29 1999/03/29 09:27:29 abs Exp $  */
-
-/*-
- * Copyright (c) 1992, 1993
- *     The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Casey Leedom of Lawrence Livermore National Laboratory.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <config.h>
-
-#include "roken.h"
-
-#include <sys/types.h>
-#include <ctype.h>
-#if defined(HAVE_DB_185_H)
-#include <db_185.h>
-#elif defined(HAVE_DB_H)
-#include <db.h>
-#endif
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#define        BFRAG           1024
-#define        ESC             ('[' & 037)     /* ASCII ESC */
-#define        MAX_RECURSION   32              /* maximum getent recursion */
-#define        SFRAG           100             /* cgetstr mallocs in SFRAG chunks */
-
-#define RECOK  (char)0
-#define TCERR  (char)1
-#define        SHADOW  (char)2
-
-static size_t   topreclen;     /* toprec length */
-static char    *toprec;        /* Additional record specified by cgetset() */
-static int      gottoprec;     /* Flag indicating retrieval of toprecord */
-
-#ifdef USE_DB
-static int     cdbget (DB *, char **, const char *);
-#endif
-static int     getent (char **, size_t *, char **, int, const char *, int, char *);
-static int     nfcmp (char *, char *);
-
-
-ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL cgetset(const char *ent);
-ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL cgetcap(char *buf, const char *cap, int type);
-ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL cgetent(char **buf, char **db_array, const char *name);
-ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL cgetmatch(const char *buf, const char *name);
-ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL cgetclose(void);
-ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL cgetstr(char *buf, const char *cap, char **str);
-ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL cgetustr(char *buf, const char *cap, char **str);
-ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL cgetnum(char *buf, const char *cap, long *num);
-/*
- * Cgetset() allows the addition of a user specified buffer to be added
- * to the database array, in effect "pushing" the buffer on top of the
- * virtual database. 0 is returned on success, -1 on failure.
- */
-ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
-cgetset(const char *ent)
-{
-    const char *source, *check;
-    char *dest;
-
-    if (ent == NULL) {
-       if (toprec)
-           free(toprec);
-       toprec = NULL;
-       topreclen = 0;
-       return (0);
-    }
-    topreclen = strlen(ent);
-    if ((toprec = malloc (topreclen + 1)) == NULL) {
-       errno = ENOMEM;
-       return (-1);
-    }
-    gottoprec = 0;
-
-    source=ent;
-    dest=toprec;
-    while (*source) { /* Strip whitespace */
-       *dest++ = *source++; /* Do not check first field */
-       while (*source == ':') {
-           check=source+1;
-           while (*check && (isspace((unsigned char)*check) ||
-                             (*check=='\\' && isspace((unsigned char)check[1]))))
-               ++check;
-           if( *check == ':' )
-               source=check;
-           else
-               break;
-
-       }
-    }
-    *dest=0;
-
-    return (0);
-}
-
-/*
- * Cgetcap searches the capability record buf for the capability cap with
- * type `type'.  A pointer to the value of cap is returned on success, NULL
- * if the requested capability couldn't be found.
- *
- * Specifying a type of ':' means that nothing should follow cap (:cap:).
- * In this case a pointer to the terminating ':' or NUL will be returned if
- * cap is found.
- *
- * If (cap, '@') or (cap, terminator, '@') is found before (cap, terminator)
- * return NULL.
- */
-ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL
-cgetcap(char *buf, const char *cap, int type)
-{
-    char *bp;
-    const char *cp;
-
-    bp = buf;
-    for (;;) {
-       /*
-        * Skip past the current capability field - it's either the
-        * name field if this is the first time through the loop, or
-        * the remainder of a field whose name failed to match cap.
-        */
-       for (;;)
-           if (*bp == '\0')
-               return (NULL);
-           else
-               if (*bp++ == ':')
-                   break;
-
-       /*
-        * Try to match (cap, type) in buf.
-        */
-       for (cp = cap; *cp == *bp && *bp != '\0'; cp++, bp++)
-           continue;
-       if (*cp != '\0')
-           continue;
-       if (*bp == '@')
-           return (NULL);
-       if (type == ':') {
-           if (*bp != '\0' && *bp != ':')
-               continue;
-           return(bp);
-       }
-       if (*bp != type)
-           continue;
-       bp++;
-       return (*bp == '@' ? NULL : bp);
-    }
-    /* NOTREACHED */
-}
-
-/*
- * Cgetent extracts the capability record name from the NULL terminated file
- * array db_array and returns a pointer to a malloc'd copy of it in buf.
- * Buf must be retained through all subsequent calls to cgetcap, cgetnum,
- * cgetflag, and cgetstr, but may then be free'd.  0 is returned on success,
- * -1 if the requested record couldn't be found, -2 if a system error was
- * encountered (couldn't open/read a file, etc.), and -3 if a potential
- * reference loop is detected.
- */
-ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
-cgetent(char **buf, char **db_array, const char *name)
-{
-    size_t dummy;
-
-    return (getent(buf, &dummy, db_array, -1, name, 0, NULL));
-}
-
-/*
- * Getent implements the functions of cgetent.  If fd is non-negative,
- * *db_array has already been opened and fd is the open file descriptor.  We
- * do this to save time and avoid using up file descriptors for tc=
- * recursions.
- *
- * Getent returns the same success/failure codes as cgetent.  On success, a
- * pointer to a malloc'ed capability record with all tc= capabilities fully
- * expanded and its length (not including trailing ASCII NUL) are left in
- * *cap and *len.
- *
- * Basic algorithm:
- *     + Allocate memory incrementally as needed in chunks of size BFRAG
- *       for capability buffer.
- *     + Recurse for each tc=name and interpolate result.  Stop when all
- *       names interpolated, a name can't be found, or depth exceeds
- *       MAX_RECURSION.
- */
-static int
-getent(char **cap, size_t *len, char **db_array, int fd,
-       const char *name, int depth, char *nfield)
-{
-    char *r_end, *rp = NULL, **db_p;   /* pacify gcc */
-    int myfd = 0, eof, foundit;
-    char *record;
-    int tc_not_resolved;
-
-    /*
-     * Return with ``loop detected'' error if we've recursed more than
-     * MAX_RECURSION times.
-     */
-    if (depth > MAX_RECURSION)
-       return (-3);
-
-    /*
-     * Check if we have a top record from cgetset().
-     */
-    if (depth == 0 && toprec != NULL && cgetmatch(toprec, name) == 0) {
-       size_t tmplen = topreclen + BFRAG;
-       if ((record = malloc (tmplen)) == NULL) {
-           errno = ENOMEM;
-           return (-2);
-       }
-       (void)strlcpy(record, toprec, tmplen);
-       db_p = db_array;
-       rp = record + topreclen + 1;
-       r_end = rp + BFRAG;
-       goto tc_exp;
-    }
-    /*
-     * Allocate first chunk of memory.
-     */
-    if ((record = malloc(BFRAG)) == NULL) {
-       errno = ENOMEM;
-       return (-2);
-    }
-    r_end = record + BFRAG;
-    foundit = 0;
-    /*
-     * Loop through database array until finding the record.
-     */
-
-    for (db_p = db_array; *db_p != NULL; db_p++) {
-       eof = 0;
-
-       /*
-        * Open database if not already open.
-        */
-
-       if (fd >= 0) {
-           (void)lseek(fd, (off_t)0, SEEK_SET);
-       } else {
-#ifdef USE_DB
-           char pbuf[_POSIX_PATH_MAX];
-           char *cbuf;
-           size_t clen;
-           int retval;
-           DB *capdbp;
-
-           (void)snprintf(pbuf, sizeof(pbuf), "%s.db", *db_p);
-           if ((capdbp = dbopen(pbuf, O_RDONLY, 0, DB_HASH, 0))
-               != NULL) {
-               free(record);
-               retval = cdbget(capdbp, &record, name);
-                /* record is no longer for us to free here */
-               if (retval < 0) {
-                   /* no record available */
-                   (void)capdbp->close(capdbp);
-                   return (retval);
-               }
-                               /* save the data; close frees it */
-               clen = strlen(record);
-               cbuf = malloc(clen + 1);
-               if (cbuf == NULL)
-                   return (-2);
-               memmove(cbuf, record, clen + 1);
-               if (capdbp->close(capdbp) < 0) {
-                   free(cbuf);
-                   return (-2);
-               }
-               *len = clen;
-               *cap = cbuf;
-               return (retval);
-           } else
-#endif
-           {
-               fd = open(*db_p, O_RDONLY, 0);
-               if (fd < 0) {
-                   /* No error on unfound file. */
-                   continue;
-               }
-               myfd = 1;
-           }
-       }
-       /*
-        * Find the requested capability record ...
-        */
-       {
-           char buf[BUFSIZ];
-           char *b_end, *bp, *cp;
-           int c, slash;
-
-           /*
-            * Loop invariants:
-            *  There is always room for one more character in record.
-            *  R_end always points just past end of record.
-            *  Rp always points just past last character in record.
-            *  B_end always points just past last character in buf.
-            *  Bp always points at next character in buf.
-            *  Cp remembers where the last colon was.
-            */
-           b_end = buf;
-           bp = buf;
-           cp = 0;
-           slash = 0;
-           for (;;) {
-
-               /*
-                * Read in a line implementing (\, newline)
-                * line continuation.
-                */
-               rp = record;
-               for (;;) {
-                   if (bp >= b_end) {
-                       int n;
-
-                       n = read(fd, buf, sizeof(buf));
-                       if (n <= 0) {
-                           if (myfd)
-                               (void)close(fd);
-                           if (n < 0) {
-                               free(record);
-                               return (-2);
-                           } else {
-                               fd = -1;
-                               eof = 1;
-                               break;
-                           }
-                       }
-                       b_end = buf+n;
-                       bp = buf;
-                   }
-
-                   c = *bp++;
-                   if (c == '\n') {
-                       if (slash) {
-                           slash = 0;
-                           rp--;
-                           continue;
-                       } else
-                           break;
-                   }
-                   if (slash) {
-                       slash = 0;
-                       cp = 0;
-                   }
-                   if (c == ':') {
-                       /*
-                        * If the field was `empty' (i.e.
-                        * contained only white space), back up
-                        * to the colon (eliminating the
-                        * field).
-                        */
-                       if (cp)
-                           rp = cp;
-                       else
-                           cp = rp;
-                   } else if (c == '\\') {
-                       slash = 1;
-                   } else if (c != ' ' && c != '\t') {
-                       /*
-                        * Forget where the colon was, as this
-                        * is not an empty field.
-                        */
-                       cp = 0;
-                   }
-                   *rp++ = c;
-
-                               /*
-                                * Enforce loop invariant: if no room
-                                * left in record buffer, try to get
-                                * some more.
-                                */
-                   if (rp >= r_end) {
-                       u_int pos;
-                        char *tmp;
-                       size_t newsize;
-
-                       pos = rp - record;
-                       newsize = r_end - record + BFRAG;
-                       tmp = realloc(record, newsize);
-                       if (tmp == NULL) {
-                           errno = ENOMEM;
-                           if (myfd)
-                               (void)close(fd);
-                            free(record);
-                           return (-2);
-                       }
-                        record = tmp;
-                       r_end = record + newsize;
-                       rp = record + pos;
-                   }
-               }
-               /* Eliminate any white space after the last colon. */
-               if (cp)
-                   rp = cp + 1;
-               /* Loop invariant lets us do this. */
-               *rp++ = '\0';
-
-               /*
-                * If encountered eof check next file.
-                */
-               if (eof)
-                   break;
-
-               /*
-                * Toss blank lines and comments.
-                */
-               if (*record == '\0' || *record == '#')
-                   continue;
-
-               /*
-                * See if this is the record we want ...
-                */
-               if (cgetmatch(record, name) == 0) {
-                   if (nfield == NULL || !nfcmp(nfield, record)) {
-                       foundit = 1;
-                       break;  /* found it! */
-                   }
-               }
-           }
-       }
-       if (foundit)
-           break;
-    }
-
-    if (!foundit) {
-        free(record);
-       return (-1);
-    }
-
-    /*
-     * Got the capability record, but now we have to expand all tc=name
-     * references in it ...
-     */
- tc_exp:       {
-       char *newicap, *s;
-       size_t ilen, newilen;
-       int diff, iret, tclen;
-       char *icap, *scan, *tc, *tcstart, *tcend;
-
-       /*
-        * Loop invariants:
-        *      There is room for one more character in record.
-        *      R_end points just past end of record.
-        *      Rp points just past last character in record.
-        *      Scan points at remainder of record that needs to be
-        *      scanned for tc=name constructs.
-        */
-       scan = record;
-       tc_not_resolved = 0;
-       for (;;) {
-           if ((tc = cgetcap(scan, "tc", '=')) == NULL)
-               break;
-
-           /*
-            * Find end of tc=name and stomp on the trailing `:'
-            * (if present) so we can use it to call ourselves.
-            */
-           s = tc;
-           for (;;)
-               if (*s == '\0')
-                   break;
-               else
-                   if (*s++ == ':') {
-                       *(s - 1) = '\0';
-                       break;
-                   }
-           tcstart = tc - 3;
-           tclen = s - tcstart;
-           tcend = s;
-
-           iret = getent(&icap, &ilen, db_p, fd, tc, depth+1,
-                         NULL);
-           newicap = icap;             /* Put into a register. */
-           newilen = ilen;
-           if (iret != 0) {
-                               /* an error */
-               if (iret < -1) {
-                   if (myfd)
-                       (void)close(fd);
-                   free(record);
-                   return (iret);
-               }
-               if (iret == 1)
-                   tc_not_resolved = 1;
-                               /* couldn't resolve tc */
-               if (iret == -1) {
-                   *(s - 1) = ':';
-                   scan = s - 1;
-                   tc_not_resolved = 1;
-                   continue;
-
-               }
-           }
-           /* not interested in name field of tc'ed record */
-           s = newicap;
-           for (;;)
-               if (*s == '\0')
-                   break;
-               else
-                   if (*s++ == ':')
-                       break;
-           newilen -= s - newicap;
-           newicap = s;
-
-           /* make sure interpolated record is `:'-terminated */
-           s += newilen;
-           if (*(s-1) != ':') {
-               *s = ':';       /* overwrite NUL with : */
-               newilen++;
-           }
-
-           /*
-            * Make sure there's enough room to insert the
-            * new record.
-            */
-           diff = newilen - tclen;
-           if (diff >= r_end - rp) {
-               u_int pos, tcpos, tcposend;
-               size_t newsize;
-                char *tmp;
-
-               pos = rp - record;
-               newsize = r_end - record + diff + BFRAG;
-               tcpos = tcstart - record;
-               tcposend = tcend - record;
-               tmp = realloc(record, newsize);
-               if (tmp == NULL) {
-                   errno = ENOMEM;
-                   if (myfd)
-                       (void)close(fd);
-                   free(icap);
-                    free(record);
-                   return (-2);
-               }
-                record = tmp;
-               r_end = record + newsize;
-               rp = record + pos;
-               tcstart = record + tcpos;
-               tcend = record + tcposend;
-           }
-
-           /*
-            * Insert tc'ed record into our record.
-            */
-           s = tcstart + newilen;
-           memmove(s, tcend,  (size_t)(rp - tcend));
-           memmove(tcstart, newicap, newilen);
-           rp += diff;
-           free(icap);
-
-           /*
-            * Start scan on `:' so next cgetcap works properly
-            * (cgetcap always skips first field).
-            */
-           scan = s-1;
-       }
-
-    }
-    /*
-     * Close file (if we opened it), give back any extra memory, and
-     * return capability, length and success.
-     */
-    if (myfd)
-       (void)close(fd);
-    *len = rp - record - 1;    /* don't count NUL */
-    if (r_end > rp) {
-        char *tmp = realloc(record, (size_t)(rp - record));
-       if (tmp == NULL) {
-           errno = ENOMEM;
-            free(record);
-           return (-2);
-       }
-        record = tmp;
-    }
-
-    *cap = record;
-    if (tc_not_resolved)
-       return (1);
-    return (0);
-}
-
-#ifdef USE_DB
-static int
-cdbget(DB *capdbp, char **bp, const char *name)
-{
-       DBT key;
-       DBT data;
-
-       /* LINTED key is not modified */
-       key.data = (char *)name;
-       key.size = strlen(name);
-
-       for (;;) {
-               /* Get the reference. */
-               switch(capdbp->get(capdbp, &key, &data, 0)) {
-               case -1:
-                       return (-2);
-               case 1:
-                       return (-1);
-               }
-
-               /* If not an index to another record, leave. */
-               if (((char *)data.data)[0] != SHADOW)
-                       break;
-
-               key.data = (char *)data.data + 1;
-               key.size = data.size - 1;
-       }
-
-       *bp = (char *)data.data + 1;
-       return (((char *)(data.data))[0] == TCERR ? 1 : 0);
-}
-#endif /* USE_DB */
-
-/*
- * Cgetmatch will return 0 if name is one of the names of the capability
- * record buf, -1 if not.
- */
-int
-cgetmatch(const char *buf, const char *name)
-{
-    const char *np, *bp;
-
-    /*
-     * Start search at beginning of record.
-     */
-    bp = buf;
-    for (;;) {
-       /*
-        * Try to match a record name.
-        */
-       np = name;
-       for (;;)
-           if (*np == '\0') {
-               if (*bp == '|' || *bp == ':' || *bp == '\0')
-                   return (0);
-               else
-                   break;
-           } else
-               if (*bp++ != *np++)
-                   break;
-
-       /*
-        * Match failed, skip to next name in record.
-        */
-       bp--;   /* a '|' or ':' may have stopped the match */
-       for (;;)
-           if (*bp == '\0' || *bp == ':')
-               return (-1);    /* match failed totally */
-           else
-               if (*bp++ == '|')
-                   break;      /* found next name */
-    }
-}
-
-static FILE *pfp;
-static int slash;
-static char **dbp;
-
-ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
-cgetclose(void)
-{
-    if (pfp != NULL) {
-       (void)fclose(pfp);
-       pfp = NULL;
-    }
-    dbp = NULL;
-    gottoprec = 0;
-    slash = 0;
-    return(0);
-}
-
-/*
- * Cgetstr retrieves the value of the string capability cap from the
- * capability record pointed to by buf.  A pointer to a decoded, NUL
- * terminated, malloc'd copy of the string is returned in the char *
- * pointed to by str.  The length of the string not including the trailing
- * NUL is returned on success, -1 if the requested string capability
- * couldn't be found, -2 if a system error was encountered (storage
- * allocation failure).
- */
-ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
-cgetstr(char *buf, const char *cap, char **str)
-{
-    u_int m_room;
-    const char *bp;
-    char *mp;
-    int len;
-    char *mem, *nmem;
-
-    *str = NULL;
-
-    /*
-     * Find string capability cap
-     */
-    bp = cgetcap(buf, cap, '=');
-    if (bp == NULL)
-       return (-1);
-
-    /*
-     * Conversion / storage allocation loop ...  Allocate memory in
-     * chunks SFRAG in size.
-     */
-    if ((mem = malloc(SFRAG)) == NULL) {
-       errno = ENOMEM;
-       return (-2);    /* couldn't even allocate the first fragment */
-    }
-    m_room = SFRAG;
-    mp = mem;
-
-    while (*bp != ':' && *bp != '\0') {
-       /*
-        * Loop invariants:
-        *      There is always room for one more character in mem.
-        *      Mp always points just past last character in mem.
-        *      Bp always points at next character in buf.
-        */
-       if (*bp == '^') {
-           bp++;
-           if (*bp == ':' || *bp == '\0')
-               break;  /* drop unfinished escape */
-           *mp++ = *bp++ & 037;
-       } else if (*bp == '\\') {
-           bp++;
-           if (*bp == ':' || *bp == '\0')
-               break;  /* drop unfinished escape */
-           if ('0' <= *bp && *bp <= '7') {
-               int n, i;
-
-               n = 0;
-               i = 3;  /* maximum of three octal digits */
-               do {
-                   n = n * 8 + (*bp++ - '0');
-               } while (--i && '0' <= *bp && *bp <= '7');
-               *mp++ = n;
-           }
-           else switch (*bp++) {
-           case 'b': case 'B':
-               *mp++ = '\b';
-               break;
-           case 't': case 'T':
-               *mp++ = '\t';
-               break;
-           case 'n': case 'N':
-               *mp++ = '\n';
-               break;
-           case 'f': case 'F':
-               *mp++ = '\f';
-               break;
-           case 'r': case 'R':
-               *mp++ = '\r';
-               break;
-           case 'e': case 'E':
-               *mp++ = ESC;
-               break;
-           case 'c': case 'C':
-               *mp++ = ':';
-               break;
-           default:
-               /*
-                * Catches '\', '^', and
-                *  everything else.
-                */
-               *mp++ = *(bp-1);
-               break;
-           }
-       } else
-           *mp++ = *bp++;
-       m_room--;
-
-       /*
-        * Enforce loop invariant: if no room left in current
-        * buffer, try to get some more.
-        */
-       if (m_room == 0) {
-           size_t size = mp - mem;
-
-           if ((nmem = realloc(mem, size + SFRAG)) == NULL) {
-               free(mem);
-               return (-2);
-           }
-           mem = nmem;
-           m_room = SFRAG;
-           mp = mem + size;
-       }
-    }
-    *mp++ = '\0';      /* loop invariant let's us do this */
-    m_room--;
-    len = mp - mem - 1;
-
-    /*
-     * Give back any extra memory and return value and success.
-     */
-    if (m_room != 0) {
-       if ((nmem = realloc(mem, (size_t)(mp - mem))) == NULL) {
-           free(mem);
-           return (-2);
-       }
-       mem = nmem;
-    }
-    *str = mem;
-    return (len);
-}
-
-/*
- * Cgetustr retrieves the value of the string capability cap from the
- * capability record pointed to by buf.  The difference between cgetustr()
- * and cgetstr() is that cgetustr does not decode escapes but rather treats
- * all characters literally.  A pointer to a  NUL terminated malloc'd
- * copy of the string is returned in the char pointed to by str.  The
- * length of the string not including the trailing NUL is returned on success,
- * -1 if the requested string capability couldn't be found, -2 if a system
- * error was encountered (storage allocation failure).
- */
-ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
-cgetustr(char *buf, const char *cap, char **str)
-{
-    u_int m_room;
-    const char *bp;
-    char *mp;
-    int len;
-    char *mem;
-
-    /*
-     * Find string capability cap
-     */
-    if ((bp = cgetcap(buf, cap, '=')) == NULL)
-       return (-1);
-
-    /*
-     * Conversion / storage allocation loop ...  Allocate memory in
-     * chunks SFRAG in size.
-     */
-    if ((mem = malloc(SFRAG)) == NULL) {
-       errno = ENOMEM;
-       return (-2);    /* couldn't even allocate the first fragment */
-    }
-    m_room = SFRAG;
-    mp = mem;
-
-    while (*bp != ':' && *bp != '\0') {
-       /*
-        * Loop invariants:
-        *      There is always room for one more character in mem.
-        *      Mp always points just past last character in mem.
-        *      Bp always points at next character in buf.
-        */
-       *mp++ = *bp++;
-       m_room--;
-
-       /*
-        * Enforce loop invariant: if no room left in current
-        * buffer, try to get some more.
-        */
-       if (m_room == 0) {
-           size_t size = mp - mem;
-
-           if ((mem = realloc(mem, size + SFRAG)) == NULL)
-               return (-2);
-           m_room = SFRAG;
-           mp = mem + size;
-       }
-    }
-    *mp++ = '\0';      /* loop invariant let's us do this */
-    m_room--;
-    len = mp - mem - 1;
-
-    /*
-     * Give back any extra memory and return value and success.
-     */
-    if (m_room != 0) {
-        char *tmp = realloc(mem, (size_t)(mp - mem));
-       if (tmp == NULL) {
-            free(mem);
-           return (-2);
-        }
-        mem = tmp;
-    }
-    *str = mem;
-    return (len);
-}
-
-/*
- * Cgetnum retrieves the value of the numeric capability cap from the
- * capability record pointed to by buf.  The numeric value is returned in
- * the long pointed to by num.  0 is returned on success, -1 if the requested
- * numeric capability couldn't be found.
- */
-ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
-cgetnum(char *buf, const char *cap, long *num)
-{
-    long n;
-    int base, digit;
-    const char *bp;
-
-    /*
-     * Find numeric capability cap
-     */
-    bp = cgetcap(buf, cap, '#');
-    if (bp == NULL)
-       return (-1);
-
-    /*
-     * Look at value and determine numeric base:
-     * 0x... or 0X...  hexadecimal,
-     * else    0...            octal,
-     * else                    decimal.
-     */
-    if (*bp == '0') {
-       bp++;
-       if (*bp == 'x' || *bp == 'X') {
-           bp++;
-           base = 16;
-       } else
-           base = 8;
-    } else
-       base = 10;
-
-    /*
-     * Conversion loop ...
-     */
-    n = 0;
-    for (;;) {
-       if ('0' <= *bp && *bp <= '9')
-           digit = *bp - '0';
-       else if ('a' <= *bp && *bp <= 'f')
-           digit = 10 + *bp - 'a';
-       else if ('A' <= *bp && *bp <= 'F')
-           digit = 10 + *bp - 'A';
-       else
-           break;
-
-       if (digit >= base)
-           break;
-
-       n = n * base + digit;
-       bp++;
-    }
-
-    /*
-     * Return value and success.
-     */
-    *num = n;
-    return (0);
-}
-
-
-/*
- * Compare name field of record.
- */
-static int
-nfcmp(char *nf, char *rec)
-{
-    char *cp, tmp;
-    int ret;
-
-    for (cp = rec; *cp != ':'; cp++)
-       ;
-
-    tmp = *(cp + 1);
-    *(cp + 1) = '\0';
-    ret = strcmp(nf, rec);
-    *(cp + 1) = tmp;
-
-    return (ret);
-}
index 7d4095f1d8405b41b85cfac6e2b07d2923bf7c9e..afebe914950099b9323e4df55f3e829e53a8f7ca 100644 (file)
@@ -41,7 +41,7 @@
  */
 
 ROKEN_LIB_FUNCTION struct hostent * ROKEN_LIB_CALL
-getipnodebyaddr (const void *src, size_t len, int af, int *error_num)
+rk_getipnodebyaddr(const void *src, size_t len, int af, int *error_num)
 {
     struct hostent *tmp;
 
index 2ff282707c23aa3eb30a2edebf60fca3bd2beae4..ee430c76eb651f3d22deafeb1e56889996fdeb72 100644 (file)
@@ -45,7 +45,7 @@ static int h_errno = NO_RECOVERY;
  */
 
 ROKEN_LIB_FUNCTION struct hostent * ROKEN_LIB_CALL
-getipnodebyname (const char *name, int af, int flags, int *error_num)
+rk_getipnodebyname(const char *name, int af, int flags, int *error_num)
 {
     struct hostent *tmp;
 
index b23ad01ebdd93b37e069324de1f6743e50aaece6..9d118600f264fbbf6e4c895e07019a9b9aa1da1a 100644 (file)
@@ -92,10 +92,10 @@ doit (int af,
  */
 
 ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
-getnameinfo(const struct sockaddr *sa, socklen_t salen,
-           char *host, size_t hostlen,
-           char *serv, size_t servlen,
-           int flags)
+rk_getnameinfo(const struct sockaddr *sa, socklen_t salen,
+              char *host, size_t hostlen,
+              char *serv, size_t servlen,
+              int flags)
 {
     switch (sa->sa_family) {
 #ifdef HAVE_IPV6
index 76cd78241be936b02128f4ceb92b99207b94602b..7fd2ca9f151fe02475097f1ee88080935adc6f79 100644 (file)
@@ -53,12 +53,12 @@ roken_get_shell(char *shell, size_t shellsz)
     char *p;
 
 #ifndef WIN32
-    char user[128];
-    const char *username = roken_get_username(user, sizeof(user));
+#ifdef HAVE_GETPWNAM_R
     size_t buflen = 2048;
 
     if (sysconf(_SC_GETPW_R_SIZE_MAX) > 0)
         buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
+#endif
 
     if (issuid())
         return "/bin/sh";
@@ -76,8 +76,11 @@ roken_get_shell(char *shell, size_t shellsz)
         struct passwd pwd;
         struct passwd *pwdp;
         char buf[buflen];
+        char user[128];
+        const char *username = roken_get_username(user, sizeof(user));
 
-        if (getpwnam_r(username, &pwd, buf, buflen, &pwdp) == 0 &&
+        if (username &&
+            getpwnam_r(username, &pwd, buf, buflen, &pwdp) == 0 &&
             pwdp != NULL && pwdp->pw_shell != NULL) {
             if (strlcpy(shell, pwdp->pw_shell, shellsz) < shellsz)
                 return shell;
@@ -133,14 +136,14 @@ roken_get_homedir(char *home, size_t homesz)
         }
         return home;
     }
-    /* Fallthru to return NULL */
+    fallthrough;
 #else
-    char user[128];
-    const char *username = roken_get_username(user, sizeof(user));
+#ifdef HAVE_GETPWNAM_R
     size_t buflen = 2048;
 
     if (sysconf(_SC_GETPW_R_SIZE_MAX) > 0)
         buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
+#endif
 
     if (issuid()) {
         errno = 0;
@@ -156,12 +159,15 @@ roken_get_homedir(char *home, size_t homesz)
     }
 
 #ifdef HAVE_GETPWNAM_R
-    if (username) {
+    {
+        char user[128];
+        const char *username = roken_get_username(user, sizeof(user));
         struct passwd pwd;
         struct passwd *pwdp;
         char buf[buflen];
 
-        if (getpwnam_r(username, &pwd, buf, buflen, &pwdp) == 0 &&
+        if (username &&
+            getpwnam_r(username, &pwd, buf, buflen, &pwdp) == 0 &&
             pwdp != NULL && pwdp->pw_dir != NULL) {
             if (strlcpy(home, pwdp->pw_dir, homesz) < homesz)
                 return home;
@@ -255,8 +261,13 @@ roken_get_username(char *user, size_t usersz)
         }
     }
 #else
+#ifdef HAVE_GETPWUID_R
     size_t buflen = 2048;
 
+    if (sysconf(_SC_GETPW_R_SIZE_MAX) > 0)
+        buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
+#endif
+
     p = secure_getenv("USER");
     if (p == NULL || p[0] == '\0')
         p = secure_getenv("LOGNAME");
@@ -268,9 +279,6 @@ roken_get_username(char *user, size_t usersz)
     }
 
 #ifdef HAVE_GETPWUID_R
-    if (sysconf(_SC_GETPW_R_SIZE_MAX) > 0)
-        buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
-
     {
         struct passwd pwd;
         struct passwd *pwdp;
index a81422e1f4a56324688add7b3c67249cdf32fcca..01f21c821d1a0567cab8f33c1e9e81cb3e34a757 100644 (file)
@@ -43,7 +43,7 @@ main(int argc, char **argv)
     int numtest = 1;
     struct test {
        void *data;
-       size_t len;
+       ssize_t len;
        const char *result;
     } *t, tests[] = {
        { "", 0 , "" },
@@ -55,26 +55,35 @@ main(int argc, char **argv)
        { "abcdef", 6, "616263646566" },
        { "abcdefg", 7, "61626364656667" },
        { "=", 1, "3D" },
+        /* Embedded NUL, non-ASCII / binary */
+       { "\0\x01\x1a\xad\xf1\xff", 6, "00011AADF1FF" },
+        /* Invalid encodings */
+       { "", -1, "00.11AADF1FF" },
+       { "", -1, "000x1AADF1FF" },
+       { "", -1, "00011?ADF1FF" },
        { NULL, 0, NULL }
     };
     for(t = tests; t->data; t++) {
+       ssize_t len;
        char *str;
-       int len;
-       len = hex_encode(t->data, t->len, &str);
-       if(strcmp(str, t->result) != 0) {
-           fprintf(stderr, "failed test %d: %s != %s\n", numtest,
-                   str, t->result);
-           numerr++;
-       }
-       free(str);
+
+        if (t->len > -1) {
+            (void) hex_encode(t->data, t->len, &str);
+            if (strcmp(str, t->result) != 0) {
+                fprintf(stderr, "failed test %d: %s != %s\n", numtest,
+                        str, t->result);
+                numerr++;
+            }
+            free(str);
+        }
        str = strdup(t->result);
        len = strlen(str);
        len = hex_decode(t->result, str, len);
-       if(len != t->len) {
-           fprintf(stderr, "failed test %d: len %lu != %lu\n", numtest,
-                   (unsigned long)len, (unsigned long)t->len);
+       if (len != t->len) {
+           fprintf(stderr, "failed test %d: len %lu != %ld\n", numtest,
+                   (long)len, (long)t->len);
            numerr++;
-       } else if(memcmp(str, t->data, t->len) != 0) {
+       } else if (t->len > -1 && memcmp(str, t->data, t->len) != 0) {
            fprintf(stderr, "failed test %d: data\n", numtest);
            numerr++;
        }
index c66b324f7900f0d5329b49218ddf3a03d33048ce..cc47fa4d52de4cd560efdff5117a6bdb40784213 100644 (file)
 
 static const char hexchar[16] = "0123456789ABCDEF";
 
-static int
+static inline int
 pos(char c)
 {
-    const char *p;
-    c = toupper((unsigned char)c);
-    for (p = hexchar; *p; p++)
-       if (*p == c)
-           return p - hexchar;
+    if (c >= '0' && c <= '9')
+        return c - '0';
+    if (c >= 'A' && c <= 'F')
+        return 10 + c - 'A';
+    if (c >= 'a' && c <= 'f')
+        return 10 + c - 'a';
     return -1;
 }
 
@@ -86,6 +87,7 @@ hex_decode(const char *str, void *data, size_t len)
     size_t l;
     unsigned char *p = data;
     size_t i;
+    int d;
 
     l = strlen(str);
 
@@ -94,11 +96,19 @@ hex_decode(const char *str, void *data, size_t len)
        return -1;
 
     if (l & 1) {
-       p[0] = pos(str[0]);
+        if ((d = pos(str[0])) == -1)
+            return -1;
+       p[0] = d;
        str++;
        p++;
     }
-    for (i = 0; i < l / 2; i++)
-       p[i] = pos(str[i * 2]) << 4 | pos(str[(i * 2) + 1]);
+    for (i = 0; i < l / 2; i++) {
+        if ((d = pos(str[i * 2])) == -1)
+            return -1;
+       p[i] = d << 4;
+        if ((d = pos(str[(i * 2) + 1])) == -1)
+            return -1;
+       p[i] |= d;
+    }
     return i + (l & 1);
 }
index 2d551a607a210e128af64e763a2fcb0f7b5b7fc2..39b0301c45436049209fb7e19a2b71b7e7f1761e 100644 (file)
@@ -85,7 +85,7 @@ static void insertionsort(u_char *, size_t, size_t, cmp_t, void *);
  */
 /* Assumption: PSIZE is a power of 2. */
 #define EVAL(p) (u_char **)                                            \
-       ((((u_char *)p + PSIZE - 1 - (u_char *) 0) & ~(PSIZE - 1)))
+       ((((uintptr_t)p + PSIZE - 1) & ~(PSIZE - 1)))
 
 /*
  * Arguments are as for qsort_r, except thunk is moved to the last
@@ -114,7 +114,7 @@ mergesort_r(void *base, size_t nmemb, size_t size, cmp_t cmp, void *thunk)
         * Stupid subtraction for the Cray.
         */
        iflag = 0;
-       if (!(size % ISIZE) && !(((char *)base - (char *)0) % ISIZE))
+       if (!(size % ISIZE) && !(((uintptr_t)base) % ISIZE))
                iflag = 1;
 
        if ((list2 = malloc(nmemb * size + PSIZE)) == NULL)
index f7b87f1203e9eb16fbf829c1ca1dde324da4c362..f8403da44ab2639a5fcdb15b6696050bb376020c 100644 (file)
@@ -36,6 +36,8 @@
 #include "ndbm_wrap.h"
 #if defined(HAVE_DBHEADER)
 #include <db.h>
+#elif defined(HAVE_DB6_DB_H)
+#include <db6/db.h>
 #elif defined(HAVE_DB5_DB_H)
 #include <db5/db.h>
 #elif defined(HAVE_DB4_DB_H)
index 1e8361999ea80240152595a68f2c8579c00f00d7..e66f56b7595285134fece1c8d1b32372958daba4 100644 (file)
@@ -71,7 +71,7 @@ net_write (rk_socket_t fd, const void *buf, size_t nbytes)
     return nbytes;
 }
 
-#else
+#else /* defined(_WIN32) */
 
 ROKEN_LIB_FUNCTION ssize_t ROKEN_LIB_CALL
 net_write(rk_socket_t sock, const void *buf, size_t nbytes)
@@ -102,6 +102,7 @@ net_write(rk_socket_t sock, const void *buf, size_t nbytes)
        count = send (sock, cbuf, rem, 0);
 #endif
        if (count < 0) {
+#ifdef SOCKET_IS_NOT_AN_FD
             if (!use_write) {
                 switch (rk_SOCK_ERRNO) {
                 case WSAEINTR:
@@ -111,7 +112,9 @@ net_write(rk_socket_t sock, const void *buf, size_t nbytes)
                 default:
                     return count;
                 }
-            } else {
+            } else
+#endif
+           {
                 switch (errno) {
                 case EINTR:
                     continue;
index 25cc98aafe3a118fc9a32189dafbaf7599e37659..581600a5937d0149b03d900d79c81b65d6c99283 100644 (file)
@@ -159,7 +159,7 @@ test_rk_dns_srv_order(size_t run)
         if (rr->u.srv->priority < prio0 ||
            (rr->u.srv->priority != prio0 &&
             (i % 4 != 0 || rr->u.srv->priority > prio0 + 1))) {
-            printf("SRV RR order run %lu failed\n", run);
+            printf("SRV RR order run %zu failed\n", run);
             fail = 1;
         }
        prio0 = rr->u.srv->priority;
index f05f88668f3d2aa7658fc693d9065175382d8216..035b99b8b9736e34b41b4002b1d62b2624473bd1 100644 (file)
@@ -472,6 +472,12 @@ vstrcollect(va_list *ap);
 ROKEN_LIB_FUNCTION char ** ROKEN_LIB_CALL
 strcollect(char *first, ...);
 
+ROKEN_LIB_FUNCTION time_t ROKEN_LIB_CALL
+rk_time_add(time_t, time_t);
+
+ROKEN_LIB_FUNCTION time_t ROKEN_LIB_CALL
+rk_time_sub(time_t, time_t);
+
 #define timevalfix rk_timevalfix
 ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
 timevalfix(struct timeval *t1);
index e1aa6b7b60c0fc8d5074ea9e9e7c58b157503333..e1902f582dcb4527f146edff22428304ba3d31d1 100644 (file)
@@ -356,7 +356,12 @@ ROKEN_CPP_START
 
 #define fsync   _commit
 
-/* The MSVC implementation of snprintf is not C99 compliant.  */
+#define _PIPE_BUFFER_SZ 8192
+#define pipe(fds) _pipe((fds), _PIPE_BUFFER_SZ, O_BINARY);
+
+#define ftruncate(fd, sz) _chsize((fd), (sz))
+
+#if !defined(HAVE_UCRT)
 #define snprintf    rk_snprintf
 #define vsnprintf   rk_vsnprintf
 #define vasnprintf  rk_vasnprintf
@@ -364,11 +369,6 @@ ROKEN_CPP_START
 #define asnprintf   rk_asnprintf
 #define asprintf    rk_asprintf
 
-#define _PIPE_BUFFER_SZ 8192
-#define pipe(fds) _pipe((fds), _PIPE_BUFFER_SZ, O_BINARY);
-
-#define ftruncate(fd, sz) _chsize((fd), (sz))
-
 ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
 rk_snprintf (char *str, size_t sz, const char *format, ...);
 
@@ -386,6 +386,7 @@ rk_vasnprintf (char **ret, size_t max_sz, const char *format, va_list args);
 
 ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
 rk_vsnprintf (char *str, size_t sz, const char *format, va_list args);
+#endif /* !defined(HAVE_UCRT) */
 
 /* missing stat.h predicates */
 
@@ -716,13 +717,6 @@ ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL mkostemp(char *, int);
 ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL mkdtemp(char *);
 #endif
 
-#ifndef HAVE_CGETENT
-#define cgetent rk_cgetent
-#define cgetstr rk_cgetstr
-ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL cgetent(char **, char **, const char *);
-ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL cgetstr(char *, const char *, char **);
-#endif
-
 #ifndef HAVE_INITGROUPS
 #define initgroups rk_initgroups
 ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL initgroups(const char *, gid_t);
@@ -912,27 +906,27 @@ ROKEN_LIB_VARIABLE extern int opterr;
 
 #ifndef HAVE_GETIPNODEBYNAME
 #define getipnodebyname rk_getipnodebyname
-ROKEN_LIB_FUNCTION struct hostent * ROKEN_LIB_CALL
-getipnodebyname (const char *, int, int, int *);
 #endif
+ROKEN_LIB_FUNCTION struct hostent * ROKEN_LIB_CALL
+rk_getipnodebyname(const char *, int, int, int *);
 
 #ifndef HAVE_GETIPNODEBYADDR
 #define getipnodebyaddr rk_getipnodebyaddr
-ROKEN_LIB_FUNCTION struct hostent * ROKEN_LIB_CALL
-getipnodebyaddr (const void *, size_t, int, int *);
 #endif
+ROKEN_LIB_FUNCTION struct hostent * ROKEN_LIB_CALL
+rk_getipnodebyaddr(const void *, size_t, int, int *);
 
 #ifndef HAVE_FREEHOSTENT
 #define freehostent rk_freehostent
-ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
-freehostent (struct hostent *);
 #endif
+ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
+rk_freehostent(struct hostent *);
 
 #ifndef HAVE_COPYHOSTENT
 #define copyhostent rk_copyhostent
-ROKEN_LIB_FUNCTION struct hostent * ROKEN_LIB_CALL
-copyhostent (const struct hostent *);
 #endif
+ROKEN_LIB_FUNCTION struct hostent * ROKEN_LIB_CALL
+rk_copyhostent(const struct hostent *);
 
 #ifndef HAVE_SOCKLEN_T
 typedef int socklen_t;
@@ -998,27 +992,27 @@ struct addrinfo {
 
 #ifndef HAVE_GETADDRINFO
 #define getaddrinfo rk_getaddrinfo
-ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
-getaddrinfo(const char *,
-           const char *,
-           const struct addrinfo *,
-           struct addrinfo **);
 #endif
+ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
+rk_getaddrinfo(const char *,
+              const char *,
+              const struct addrinfo *,
+              struct addrinfo **);
 
 #ifndef HAVE_GETNAMEINFO
 #define getnameinfo rk_getnameinfo
-ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
-getnameinfo(const struct sockaddr *, socklen_t,
-               char *, size_t,
-               char *, size_t,
-               int);
 #endif
+ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
+rk_getnameinfo(const struct sockaddr *, socklen_t,
+              char *, size_t,
+              char *, size_t,
+              int);
 
 #ifndef HAVE_FREEADDRINFO
 #define freeaddrinfo rk_freeaddrinfo
-ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
-freeaddrinfo(struct addrinfo *);
 #endif
+ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
+rk_freeaddrinfo(struct addrinfo *);
 
 #ifndef HAVE_GAI_STRERROR
 #define gai_strerror rk_gai_strerror
index 620875f379c8b049f25a29629cded3e55c57e5b5..3da48962ee3ad1825da1b70a601f87243f264a8f 100644 (file)
@@ -515,7 +515,7 @@ xyzprintf (struct snprintf_state *state, const char *char_format, va_list ap)
            }
            case '\0' :
                --format;
-               /* FALLTHROUGH */
+                fallthrough;
            case '%' :
                (*state->append_char)(state, c);
                ++len;
index 9feb343f50836c74d3b993fd5138de6be1d1cba0..a790e082d822f124b40cc00400b74cb0dee06cf6 100644 (file)
@@ -221,16 +221,16 @@ ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
 socket_set_portrange (rk_socket_t sock, int restr, int af)
 {
 #if defined(IP_PORTRANGE)
-       if (af == AF_INET) {
-               int on = restr ? IP_PORTRANGE_HIGH : IP_PORTRANGE_DEFAULT;
-               setsockopt (sock, IPPROTO_IP, IP_PORTRANGE, &on, sizeof(on));
-       }
+    if (af == AF_INET) {
+        int on = restr ? IP_PORTRANGE_HIGH : IP_PORTRANGE_DEFAULT;
+        (void) setsockopt(sock, IPPROTO_IP, IP_PORTRANGE, &on, sizeof(on));
+    }
 #endif
 #if defined(IPV6_PORTRANGE)
-       if (af == AF_INET6) {
-               int on = restr ? IPV6_PORTRANGE_HIGH : IPV6_PORTRANGE_DEFAULT;
-               setsockopt (sock, IPPROTO_IPV6, IPV6_PORTRANGE, &on, sizeof(on));
-       }
+    if (af == AF_INET6) {
+        int on = restr ? IPV6_PORTRANGE_HIGH : IPV6_PORTRANGE_DEFAULT;
+        (void) setsockopt(sock, IPPROTO_IPV6, IPV6_PORTRANGE, &on, sizeof(on));
+    }
 #endif
 }
 
@@ -243,7 +243,7 @@ socket_set_debug (rk_socket_t sock)
 {
 #if defined(SO_DEBUG) && defined(HAVE_SETSOCKOPT)
     int on = 1;
-    setsockopt (sock, SOL_SOCKET, SO_DEBUG, (void *) &on, sizeof (on));
+    (void) setsockopt(sock, SOL_SOCKET, SO_DEBUG, (void *) &on, sizeof (on));
 #endif
 }
 
@@ -255,7 +255,7 @@ ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
 socket_set_tos (rk_socket_t sock, int tos)
 {
 #if defined(IP_TOS) && defined(HAVE_SETSOCKOPT)
-    setsockopt (sock, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof(int));
+    (void) setsockopt (sock, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof(int));
 #endif
 }
 
@@ -289,7 +289,8 @@ ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
 socket_set_reuseaddr (rk_socket_t sock, int val)
 {
 #if defined(SO_REUSEADDR) && defined(HAVE_SETSOCKOPT)
-    setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&val, sizeof(val));
+    (void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&val,
+                      sizeof(val));
 #endif
 }
 
@@ -301,7 +302,8 @@ ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
 socket_set_ipv6only (rk_socket_t sock, int val)
 {
 #if defined(IPV6_V6ONLY) && defined(HAVE_SETSOCKOPT)
-    setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&val, sizeof(val));
+    (void) setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&val,
+                      sizeof(val));
 #endif
 }
 
@@ -312,7 +314,8 @@ socket_set_ipv6only (rk_socket_t sock, int val)
 ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
 socket_set_keepalive(rk_socket_t sock, int val)
 {
-    setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&val, sizeof(val));
+    (void) setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&val,
+                      sizeof(val));
 }
 
 /**
index 447c1554337feacb2e1820b3281ed8d882314203..9a951dd3008008a6e86fd9c84311ca513140681a 100644 (file)
 #include "strpftime-test.h"
 #endif
 
+#if defined(_WIN32)
+# define timezone _timezone
+# define tzname   _tzname
+#endif
+
 static const char *abb_weekdays[] = {
     "Sun",
     "Mon",
@@ -372,7 +377,7 @@ strftime (char *buf, size_t maxsize, const char *format,
                break;
            case '\0' :
                --format;
-               /* FALLTHROUGH */
+                fallthrough;
            case '%' :
                ret = snprintf (buf, maxsize - n,
                                "%%");
index 75c27a328773657636a8f5d1046d5cc402894866..86216d2d6dcc6e4f54236600cb688f0f453566c5 100644 (file)
@@ -424,7 +424,7 @@ strptime (const char *buf, const char *format, struct tm *timeptr)
                abort ();
            case '\0' :
                --format;
-               /* FALLTHROUGH */
+                fallthrough;
            case '%' :
                if (*buf == '%')
                    ++buf;
index 0d895d54a255ea95d79e71d059610d1b5f74f0f6..96c1b250974d3406896256b3da8a2113929d7a28 100644 (file)
@@ -38,6 +38,8 @@
 
 #include "roken.h"
 
+#ifndef HAVE_STRTOLL
+
 /* #include <sys/cdefs.h> */
 
 #include <limits.h>
@@ -150,3 +152,4 @@ noconv:
        *endptr = (char *)(any ? s - 1 : nptr);
     return ret;
 }
+#endif /* !HAVE_STRTOLL */
index 94530e574d12557f5f1e1da7ab1e5b60fcddeb2f..0516e18f9135c2cb727befcc89c1c8d8ec7a1d30 100644 (file)
@@ -38,6 +38,8 @@
 
 #include "roken.h"
 
+#ifndef HAVE_STRTOULL
+
 /* #include <sys/cdefs.h> */
 
 #include <limits.h>
@@ -124,3 +126,4 @@ noconv:
        *endptr = (char *)(any ? s - 1 : nptr);
     return (acc);
 }
+#endif /* !HAVE_STRTOULL */
index b3f15214b56ac2246917cd4f2395f966ab1ef7fa..4feae177aed63195289e6a674ecdb4e6de1e3ee3 100644 (file)
@@ -50,7 +50,8 @@ main(void)
     char buf2[MAX_PATH * 2];
     int ret = 0;
     if (!issuid() && getuid() != 0) {
-        const char *s, *s2;
+        const char *s = NULL;
+        const char *s2 = NULL;
 
         if (getenv("USER") != NULL && strlen(getenv("USER")) != 0 &&
             (s = roken_get_username(buf, sizeof(buf))) == NULL) {
index 079ace266a1f63bd24282102cb42f13663fed776..7ab996ae8b4c5f459a1de8e734b45abab370d229 100644 (file)
@@ -144,7 +144,7 @@ test_simple_echo_client(void)
        }
 
        if (rv != strlen(test_strings[i])) {
-           fprintf (stderr, "[%s] Data length mismatch %d != %d\n", prog, rv, strlen(test_strings[i]));
+           fprintf (stderr, "[%s] Data length mismatch %d != %zu\n", prog, rv, strlen(test_strings[i]));
            rk_closesocket(s);
            return 1;
        }
index 38b1f7ce9c343c09d6a4d5ce8f8a094c404c703a..3012513ee7d199bd93442877ffdd1ee6389b3090 100644 (file)
 
 #include "roken.h"
 
+ROKEN_LIB_FUNCTION time_t ROKEN_LIB_CALL
+rk_time_add(time_t t, time_t delta)
+{
+    if (delta == 0)
+        return t;
+
+#ifdef TIME_T_SIGNED
+    /* Signed overflow is UB in C */
+#if SIZEOF_TIME_T == 4
+    if (t >= 0 && delta > 0 && INT32_MAX - t < delta)
+        /* Time left to hit INT32_MAX is less than what we want to add */
+        return INT32_MAX;
+    else if (t == INT32_MIN && delta < 0)
+        /* Avoid computing -t when t == INT32_MIN! */
+        return INT32_MIN;
+    else if (t < 0 && delta < 0 && INT32_MIN + (-t) > delta)
+        /* Time left to hit INT32_MIN is less than what we want to subtract */
+        return INT32_MIN;
+    else
+        return t + delta;
+#elif SIZEOF_TIME_T == 8
+    if (t >= 0 && delta > 0 && INT64_MAX - t < delta)
+        return INT64_MAX;
+    else if (t == INT64_MIN && delta < 0)
+        /* Avoid computing -t when t == INT64_MIN! */
+        return INT64_MIN;
+    else if (t < 0 && delta < 0 && INT64_MIN + (-t) > delta)
+        return INT64_MIN;
+    else
+        return t + delta;
+#else
+#error "Unexpected sizeof(time_t)"
+#endif
+#else
+
+    /* Unsigned overflow is defined in C */
+#if SIZEOF_TIME_T == 4
+    if (t + delta < t)
+        return UINT32_MAX;
+#elif SIZEOF_TIME_T == 8
+    if (t + delta < t)
+        return UINT64_MAX;
+#else
+#error "Unexpected sizeof(time_t)"
+#endif
+#endif
+    return t + delta;
+}
+
+ROKEN_LIB_FUNCTION time_t ROKEN_LIB_CALL
+rk_time_sub(time_t t, time_t delta)
+{
+    if (delta == 0)
+        return t;
+#ifdef TIME_T_SIGNED
+    if (delta > 0)
+        return rk_time_add(t, -delta);
+#if SIZEOF_TIME_T == 4
+    if (delta == INT32_MIN) {
+        if (t < 0) {
+            t = t + INT32_MAX;
+            return t + 1;
+        }
+        return INT32_MAX;
+    }
+    /* Safe to compute -delta, so use rk_time_add() to add -delta */
+    return rk_time_add(t, -delta);
+#elif SIZEOF_TIME_T == 8
+    if (delta == INT64_MIN) {
+        if (t < 0) {
+            t = t + INT64_MAX;
+            return t + 1;
+        }
+        return INT64_MAX;
+    }
+    return rk_time_add(t, -delta);
+#else
+#error "Unexpected sizeof(time_t)"
+#endif
+#else
+    /* Both t and delta are non-negative. */
+    if (delta > t)
+        return 0;
+#endif
+    return t - delta;
+}
+
 /*
  * Make `t1' consistent.
  */
@@ -47,11 +134,11 @@ ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
 timevalfix(struct timeval *t1)
 {
     if (t1->tv_usec < 0) {
-        t1->tv_sec--;
-        t1->tv_usec += 1000000;
+        t1->tv_sec = rk_time_sub(t1->tv_sec, 1);
+        t1->tv_usec = 1000000;
     }
     if (t1->tv_usec >= 1000000) {
-        t1->tv_sec++;
+        t1->tv_sec = rk_time_add(t1->tv_sec, 1);
         t1->tv_usec -= 1000000;
     }
 }
@@ -63,7 +150,7 @@ timevalfix(struct timeval *t1)
 ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
 timevaladd(struct timeval *t1, const struct timeval *t2)
 {
-    t1->tv_sec  += t2->tv_sec;
+    t1->tv_sec   = rk_time_add(t1->tv_sec, t2->tv_sec);
     t1->tv_usec += t2->tv_usec;
     timevalfix(t1);
 }
@@ -75,7 +162,125 @@ timevaladd(struct timeval *t1, const struct timeval *t2)
 ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
 timevalsub(struct timeval *t1, const struct timeval *t2)
 {
-    t1->tv_sec  -= t2->tv_sec;
+    t1->tv_sec   = rk_time_sub(t1->tv_sec, t2->tv_sec);
     t1->tv_usec -= t2->tv_usec;
     timevalfix(t1);
 }
+
+#ifdef TEST
+int
+main(int argc, char **argv)
+{
+    time_t t, delta, r;
+    int e = 0;
+
+    if (argc == 0)
+        return 0; /* Apparently POSIX and Linux allow this case */
+
+    argc--;
+    argv++;
+
+    while (argc > 0) {
+        int64_t n;
+        time_t a;
+        char *ends;
+
+        if (argc < 3)
+            errx(1, "Usage: [TIME +|- DELTA [== TIME]]");
+
+        errno = 0;
+        n = strtoll(argv[0], &ends, 0);
+        if (errno)
+            err(1, "Time value is invalid");
+        if (*ends != '\0')
+            errx(1, "Time value is invalid");
+        t = n;
+
+        n = strtoll(argv[2], &ends, 0);
+        if (errno)
+            err(1, "Delta value is invalid");
+        if (*ends != '\0')
+            errx(1, "Delta value is invalid");
+        delta = n;
+
+        if (argv[1][0] == '+' && argv[1][1] == '\0')
+            r = rk_time_add(t, delta);
+        else if (argv[1][0] == '-' && argv[1][1] == '\0')
+            r = rk_time_sub(t, delta);
+        else
+            errx(1, "Operator must be a + or a - arithmetic operator");
+
+        if (delta == 0 && r != t) {
+            warnx("%s %s %s != %s!", argv[0], argv[1], argv[2], argv[0]);
+            e = 1;
+        }
+        if (t == 0 && r != delta) {
+            warnx("%s %s %s != %s!", argv[0], argv[1], argv[2], argv[2]);
+            e = 1;
+        }
+
+        if (argc > 4 && strcmp(argv[3], "==") == 0) {
+            n = strtoll(argv[4], &ends, 0);
+            if (errno)
+                err(1, "Time value is invalid");
+            if (*ends != '\0')
+                errx(1, "Time value is invalid");
+            a = n;
+            if (a != r) {
+                warnx("%s %s %s != %s!", argv[0], argv[1], argv[2], argv[4]);
+                e = 1;
+            }
+            argc -= 5;
+            argv += 5;
+        } else {
+#ifdef TIME_T_SIGNED
+            printf("%s %s %s == %lld\n", argv[0], argv[1], argv[2],
+                   (long long)r);
+#else
+            printf("%s %s %s == %llu\n", argv[0], argv[1], argv[2],
+                   (unsigned long long)r);
+#endif
+            argc -= 3;
+            argv += 3;
+        }
+    }
+
+#define CHECK(e) do { if (!(e)) errx(1, "Expression not true: " #e "!"); } while (0)
+#ifdef TIME_T_SIGNED
+#if SIZEOF_TIME_T == 4
+    CHECK(rk_time_add(INT32_MIN, -1) == INT32_MIN);
+    CHECK(rk_time_sub(INT32_MIN,  1) == INT32_MIN);
+    CHECK(rk_time_sub(-1, INT32_MAX) == INT32_MIN);
+    CHECK(rk_time_add(INT32_MAX,  0) == INT32_MAX);
+    CHECK(rk_time_add(INT32_MAX,  1) == INT32_MAX);
+    CHECK(rk_time_add(1,  INT32_MAX) == INT32_MAX);
+    CHECK(rk_time_add(0,  INT32_MAX) == INT32_MAX);
+#elif SIZEOF_TIME_T == 8
+    CHECK(rk_time_add(INT64_MIN, -1) == INT64_MIN);
+    CHECK(rk_time_sub(INT64_MIN,  1) == INT64_MIN);
+    CHECK(rk_time_sub(-1, INT64_MAX) == INT64_MIN);
+    CHECK(rk_time_add(INT64_MAX,  0) == INT64_MAX);
+    CHECK(rk_time_add(INT64_MAX,  1) == INT64_MAX);
+    CHECK(rk_time_add(1,  INT64_MAX) == INT64_MAX);
+    CHECK(rk_time_add(0,  INT64_MAX) == INT64_MAX);
+#endif
+    CHECK(rk_time_add(0, -1) == -1);
+    CHECK(rk_time_sub(0,  1) == -1);
+#else
+#if SIZEOF_TIME_T == 4
+    CHECK(rk_time_add(UINT32_MAX, 0) == UINT32_MAX);
+    CHECK(rk_time_add(UINT32_MAX, 1) == UINT32_MAX);
+    CHECK(rk_time_add(1, UINT32_MAX) == UINT32_MAX);
+    CHECK(rk_time_add(0, UINT32_MAX) == UINT32_MAX);
+#elif SIZEOF_TIME_T == 8
+    CHECK(rk_time_add(UINT64_MAX, 0) == UINT64_MAX);
+    CHECK(rk_time_add(UINT64_MAX, 1) == UINT64_MAX);
+    CHECK(rk_time_add(1, UINT64_MAX) == UINT64_MAX);
+    CHECK(rk_time_add(0, UINT64_MAX) == UINT64_MAX);
+#endif
+#endif
+    CHECK(rk_time_add(0, 1) == 1);
+    CHECK(rk_time_add(1, 0) == 1);
+    return e;
+}
+#endif
index 3307341c049440e905e4acae5a6e378ef5d4fef9..be1713e826102def021dc7dedf0efafecc5bbb1d 100644 (file)
@@ -2,7 +2,6 @@ HEIMDAL_ROKEN_2.0 {
        global:
                arg_printusage;
                arg_printusage_i18n;
-               cgetcap;
                cgetclose;
                cgetmatch;
                cgetnum;
@@ -40,8 +39,6 @@ HEIMDAL_ROKEN_2.0 {
                rk_bswap16;
                rk_bswap32;
                rk_bswap64;
-               rk_cgetent;
-               rk_cgetstr;
                rk_cloexec;
                rk_cloexec_dir;
                rk_cloexec_file;
@@ -164,6 +161,8 @@ HEIMDAL_ROKEN_2.0 {
                rk_tdelete;
                rk_tfind;
                rk_timegm;
+               rk_time_add;
+               rk_time_sub;
                rk_timevaladd;
                rk_timevalfix;
                rk_timevalsub;
index c598967fb72a832edb3426cf651317844ffb502a..0fe44ae350231b2bf65ccfaa2c665b0b95316141 100644 (file)
@@ -377,12 +377,12 @@ rk_strsvisx(char *dst, const char *csrc, size_t len, int flag, const char *extra
        if (flag & VIS_HTTPSTYLE) {
                for (start = dst; len > 0; len--) {
                        c = *src++;
-                       dst = do_hvis(dst, c, flag, len ? *src : '\0', nextra);
+                       dst = do_hvis(dst, c, flag, *src, nextra);
                }
        } else {
                for (start = dst; len > 0; len--) {
                        c = *src++;
-                       dst = do_svis(dst, c, flag, len ? *src : '\0', nextra);
+                       dst = do_svis(dst, c, flag, *src, nextra);
                }
        }
        free(nextra);
@@ -440,16 +440,18 @@ rk_strrasvisx(char **out,
                return -1;
        }
        if (have < want) {
-               if ((s = realloc(*out, want)) == NULL)
+               if ((s = realloc(s, want)) == NULL)
                        return -1;
                *outsz = want;
                *out = s;
        }
+        if (*out == NULL) {
+            errno = EINVAL;
+            return -1;
+        }
        **out = '\0'; /* Makes source debugging nicer, that's all */
-       if ((r = strsvisx(*out, csrc, len, flag, extra)) < 0)
-               return r;
-       errno = *out ? errno : EINVAL;
-       return *out ? r : -1;
+       r = strsvisx(*out, csrc, len, flag, extra);
+        return r;
 }
 
 #if !HAVE_VIS
@@ -641,6 +643,7 @@ main(int argc, char **argv)
     }
 
     free(nextra);
+    free(s);
     return 0;
 }
 #endif
index 152b86a330a2120de26990a890d88213c31ee9c1..1213d8c9df976855de7755c120c4dd5196bd2ed3 100644 (file)
@@ -8,7 +8,7 @@ endif
 
 AM_CPPFLAGS += $(ROKEN_RENAME)
 
-YFLAGS = -d
+YFLAGS = -d -o slc-gram.c
 LFLAGS = @FLEXNOUNPUTARGS@
 
 include_HEADERS = sl.h
index 03f577b5f59494b00982043a972a1e58b8bf7e93..b78f9f675b252d1b1d03bc0735624826d594d37e 100644 (file)
@@ -460,6 +460,8 @@ sl_did_you_mean(SL_cmd *cmds, const char *match)
 
     for (n = 0, c = cmds; c->name; c++, n++)
         ;
+    if (n == 0)
+        return;
     metrics = calloc(n, sizeof(metrics[0]));
     if (metrics == NULL)
         return;
index 767ffc833c86a325461ca62c60324410938be7c4..38045c10048ac4c265fe0afce8dff3491c67ebf9 100644 (file)
@@ -689,6 +689,7 @@ gen_wrapper(struct assignment *as)
     cprint(1, "return 0;\n");
     cprint(0, "}\n");
     cprint(0, "\n");
+    free(n);
 }
 
 char cname[PATH_MAX];
index 1bc63a33dd8a253d26249b9ee3f2678c70b37152..378c912a392d4dbab543ea8cefbd191d0d75f46b 100644 (file)
@@ -156,7 +156,9 @@ main(int argc, char **argv)
     if (argc == 0)
        usage(1);
 
-    for (i = 0; i < argc; ++i)
-       lookup(argv[i]);
+    for (i = 0; i < argc; ++i) {
+        if (argv[i][0]) /* Quiet lint */
+            lookup(argv[i]);
+    }
     return 0;
 }
index d69db0c0cec1f6bc86ddb0fddf7b850b9ef839ea..452b7b260d8445bd73c18134101f8ef51ca77e0c 100644 (file)
@@ -205,18 +205,20 @@ wind_ucs4utf8(const uint32_t *in, size_t in_len, char *out, size_t *out_len)
            case 4:
                out[3] = (ch | 0x80) & 0xbf;
                ch = ch >> 6;
-                /* FALLTHROUGH */
+                fallthrough;
            case 3:
                out[2] = (ch | 0x80) & 0xbf;
                ch = ch >> 6;
-                /* FALLTHROUGH */
+                fallthrough;
            case 2:
                out[1] = (ch | 0x80) & 0xbf;
                ch = ch >> 6;
-                /* FALLTHROUGH */
+                fallthrough;
            case 1:
                out[0] = ch | first_char[len - 1];
-                /* FALLTHROUGH */
+                fallthrough;
+            default:
+                break;
            }
        }
        out += len;
@@ -484,14 +486,16 @@ wind_ucs2utf8(const uint16_t *in, size_t in_len, char *out, size_t *out_len)
            case 3:
                out[2] = (ch | 0x80) & 0xbf;
                ch = ch >> 6;
-                /* FALLTHROUGH */
+                fallthrough;
            case 2:
                out[1] = (ch | 0x80) & 0xbf;
                ch = ch >> 6;
-                /* FALLTHROUGH */
+                fallthrough;
            case 1:
                out[0] = ch | first_char[len - 1];
-                /* FALLTHROUGH */
+                fallthrough;
+            default:
+                break;
            }
            out += len;
        }
index ad63ae04f4c85149d08e3ee78aa104bb178d8206..2923e649b969273653a46e0ec27c7b9966a65739 100644 (file)
@@ -133,7 +133,13 @@ clean::
 ######################################################################
 # Runtime modules
 
-!if [ $(PERL) $(SRC)\cf\w32-detect-vc-version.pl $(CC) ]==16
+!if [ $(PERL) $(SRC)\cf\w32-detect-vc-version.pl $(CC) ]==19
+VCVER=VC2019
+!elseif [ $(PERL) $(SRC)\cf\w32-detect-vc-version.pl $(CC) ]==18
+VCVER=VC2018
+!elseif [ $(PERL) $(SRC)\cf\w32-detect-vc-version.pl $(CC) ]==17
+VCVER=VC2017
+!elseif [ $(PERL) $(SRC)\cf\w32-detect-vc-version.pl $(CC) ]==16
 VCVER=VC100
 !elseif [ $(PERL) $(SRC)\cf\w32-detect-vc-version.pl $(CC) ]==15
 VCVER=VC90
@@ -164,22 +170,27 @@ MMDIR=$(SystemDrive)\Program Files (x86)\Common Files\Merge Modules
 !endif
 !endif
 
-!if exist("$(MMDIR)")
-
-RUNTIMEMODULE32="$(MMDIR)\Microsoft_$(VCVER)_$(CRTNAME)_x86.msm"
-!if "$(VCVER)"=="VC100"
-RUNTIMEMODULE64="$(MMDIR)\Microsoft_$(VCVER)_$(CRTNAME)_x64.msm"
+#
+# Don't specify a runtime module when the Universal C Runtime
+# is available.
+#
+!if "$(APPVER)"=="10.0"
+RUNTIMEMODULE32=""
+RUNTIMEMODULE64=""
 !else
+! if exist("$(MMDIR)")
+RUNTIMEMODULE32="$(MMDIR)\Microsoft_$(VCVER)_$(CRTNAME)_x86.msm"
+!  if "$(VCVER)"=="VC90" || "$(VCVER)"=="VC80"
 RUNTIMEMODULE64="$(MMDIR)\Microsoft_$(VCVER)_$(CRTNAME)_x86_x64.msm"
-!endif
-
-!else
+!  else
+RUNTIMEMODULE64="$(MMDIR)\Microsoft_$(VCVER)_$(CRTNAME)_x64.msm"
+!  endif
+! else
 RUNTIMEMODULE32="$(MSSDK)\Redist\VC\microsoft.vcxx.crt.x86_msm.msm"
 RUNTIMEMODULE64="$(MSSDK)\Redist\VC\microsoft.vcxx.crt.x64_msm.msm"
-
+! endif
 !endif
 
-
 ######################################################################
 # Heimdal installer
 
index 0b6000d1bfa0700aa352d067de76aba498e4a418..8ac6cc665fdb6e344e5df6618e525d5f7dfbbfb3 100644 (file)
       <Merge Id='Heimdal.Policy.32' Language='0'
              SourceFile='$(var.InstDir32)\Heimdal.Policy.msm' />
 
-      <Merge Id='Runtime.32' Language='0'
-             SourceFile='$(var.RuntimeModule32)' />
-
+      <?if "$(var.RuntimeModule32)" != "" ?>
+       <Merge Id='Runtime.32' Language='0'
+              SourceFile='$(var.RuntimeModule32)' />
+      <?endif?>
     </DirectoryRef>
     <?endif?>
 
       <Merge Id='Heimdal.Policy.64' Language='0'
              SourceFile='$(var.InstDir64)\Heimdal.Policy.msm' />
 
-      <Merge Id='Runtime.64' Language='0'
-             SourceFile='$(var.RuntimeModule64)' />
-
+      <?if "$(var.RuntimeModule64)" != "" ?>
+       <Merge Id='Runtime.64' Language='0'
+              SourceFile='$(var.RuntimeModule64)' />
+      <?endif?>
     </DirectoryRef>
     <?endif?>
 
       <MergeRef Id='Heimdal.Assemblies.64' />
       <MergeRef Id='Heimdal.GSS.64' />
       <MergeRef Id='Heimdal.Policy.64' />
-      <MergeRef Id='Runtime.64' />
+      <?if "$(var.RuntimeModule64)" != "" ?><MergeRef Id='Runtime.64' /><?endif?>
       <?else?>
       <MergeRef Id='Heimdal.Assemblies.32' />
       <MergeRef Id='Heimdal.GSS.32' />
       <MergeRef Id='Heimdal.Policy.32' />
-      <MergeRef Id='Runtime.32' />
+      <?if "$(var.RuntimeModule32)" != "" ?><MergeRef Id='Runtime.32' /><?endif?>
       <?endif?>
 
       <?ifdef Target32?>
         <MergeRef Id='Heimdal.Assemblies.32' />
        <MergeRef Id='Heimdal.GSS.32' />
         <MergeRef Id='Heimdal.Policy.32' />
-        <MergeRef Id='Runtime.32' />
+       <?if "$(var.RuntimeModule32)" != "" ?><MergeRef Id='Runtime.32' /><?endif?>
       </Feature>
       <?endif?>
       <?endif?>
index 954a2c1d5f5fe25f711382732336a3199650ceea..c9291d08bf206e38a5a796b56ad625e1341e36fc 100644 (file)
@@ -28,6 +28,7 @@ kadmin="${TESTS_ENVIRONMENT} ${top_builddir}/kadmin/kadmin"
 kadmind="${TESTS_ENVIRONMENT} ${top_builddir}/kadmin/kadmind"
 kdc="${TESTS_ENVIRONMENT} ${top_builddir}/kdc/kdc"
 kdc_tester="${TESTS_ENVIRONMENT} ${top_builddir}/kdc/kdc-tester"
+kcm="${TESTS_ENVIRONMENT} ${top_builddir}/kcm/kcm"
 test_csr_authorizer="${TESTS_ENVIRONMENT} ${top_builddir}/kdc/test_csr_authorizer"
 test_kdc_ca="${TESTS_ENVIRONMENT} ${top_builddir}/kdc/test_kdc_ca"
 test_token_validator="${TESTS_ENVIRONMENT} ${top_builddir}/kdc/test_token_validator"
index ca40ae26bd2dbace94b127f68cb39e840a968127..2de36bfe24cfde6eec5366373facefa2fe69cdd7 100644 (file)
@@ -95,7 +95,9 @@ EXTRA_DIST = \
        check-spnego.in \
        check-ntlm.in \
        check-context.in \
+       check-negoex.in \
        ntlm-user-file.txt \
        krb5.conf.in \
+       include-krb5.conf \
        new_clients_k5.conf.in \
        mech.in
index d4916bd46d4bb61f7905351bf945cd40dbb907df..c5151c4c94f100838090f0b5a9638fd68b03f19c 100644 (file)
@@ -94,10 +94,10 @@ echo "Doing database check"
 ${kadmin} check ${R} || exit 1
 
 echo Starting kdc
-${kdc} --testing --detach || { echo "kdc failed to start"; exit 1; }
+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; }
 kdcpid=`getpid kdc`
 
-trap "kill ${kdcpid}; echo signal killing kdc; exit 1;" EXIT
+trap "kill -9 ${kdcpid}; echo signal killing kdc; cat messages.log; exit 1;" EXIT
 
 exitcode=0
 
index 42ea15eecb9c481f09705d27b80c056af89b6f1e..46c058d068b49f0166d8c99a4a66e9bd7503d3c2 100644 (file)
@@ -115,10 +115,10 @@ ${kadmin} check ${R} || exit 1
 echo u1 > ${objdir}/foopassword
 
 echo Starting kdc
-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; }
+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; }
 kdcpid=`getpid kdc`
 
-trap "kill ${kdcpid}; echo signal killing kdc; exit 1;" EXIT
+trap "kill -9 ${kdcpid}; echo signal killing kdc; exit 1;" EXIT
 
 testfailed="echo test failed; cat messages.log; exit 1"
 
@@ -245,6 +245,14 @@ for mech in krb5 krb5iov spnego spnegoiov; do
                { eval "$testfailed"; }
 done
 
+echo "======test authz-data (krb5)"
+${context} --mech-type=krb5 \
+    --mutual \
+    --wrapunwrap \
+    --on-behalf-of=foo@BAR.TEST.H5L.SE \
+    --name-type=hostbased-service host@lucid.test.h5l.se ||
+    { eval "$testfailed"; }
+
 echo "======dce-style"
 for mech in krb5 krb5iov spnego; do
        iov=""
index 44769eff58407623c69b5581a438179e67c9dbed..539e2e94e5277882c5438cb79b4030735ff1b449 100644 (file)
@@ -93,10 +93,10 @@ echo "Doing database check"
 ${kadmin} check ${R} || exit 1
 
 echo Starting kdc
-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; }
+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; }
 kdcpid=`getpid kdc`
 
-trap "kill ${kdcpid}; echo signal killing kdc; exit 1;" EXIT
+trap "kill -9 ${kdcpid}; echo signal killing kdc; exit 1;" EXIT
 
 exitcode=0
 
index f5bf3446ae617a06c920610a1afbfe1abf2847e5..f953630d09dbda2829c6dfd05ae48539eb730722 100644 (file)
@@ -107,10 +107,10 @@ echo u1 > ${objdir}/foopassword
 echo ds > ${objdir}/barpassword
 
 echo Starting kdc
-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; }
+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; }
 kdcpid=`getpid kdc`
 
-trap "kill ${kdcpid}; echo signal killing kdc; exit 1;" EXIT
+trap "kill -9 ${kdcpid}; echo signal killing kdc; exit 1;" EXIT
 
 exitcode=0
 
index 3cf5608960216e745233858f43a79072a2d4afc5..d6e4d8331529311b2ecec64049cd5e894eee15a4 100644 (file)
@@ -106,10 +106,10 @@ echo u1 > ${objdir}/foopassword
 echo ds > ${objdir}/barpassword
 
 echo Starting kdc
-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; }
+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; }
 kdcpid=`getpid kdc`
 
-trap "kill ${kdcpid}; echo signal killing kdc; exit 1;" EXIT
+trap "kill -9 ${kdcpid}; echo signal killing kdc; exit 1;" EXIT
 
 exitcode=0
 
index b8e04b65159e043d2bd6bfbf79148e95a41d04ab..aae031db645ebe06da1862f268de1d2e59d26682 100644 (file)
@@ -18,6 +18,21 @@ include @srcdirabs@/include-krb5.conf
        }
 
 [kdc]
+       enable-digest = true
+       allow-anonymous = true
+       digests_allowed = chap-md5,digest-md5,ntlm-v1,ntlm-v1-session,ntlm-v2,ms-chap-v2
+        strict-nametypes = true
+        synthetic_clients = true
+       enable_gss_preauth = true
+       gss_mechanisms_allowed = sanon-x25519
+       enable-pkinit = true
+       pkinit_identity = FILE:@srcdir@/../../lib/hx509/data/kdc.crt,@srcdir@/../../lib/hx509/data/kdc.key
+       pkinit_anchors = FILE:@srcdir@/../../lib/hx509/data/ca.crt
+       pkinit_pool = FILE:@srcdir@/../../lib/hx509/data/sub-ca.crt
+#      pkinit_revoke = CRL:@srcdir@/../../lib/hx509/data/crl1.crl
+       pkinit_mappings_file = @srcdir@/pki-mapping
+       pkinit_allow_proxy_certificate = true
+
        database = {
                dbname = @objdir@/current-db
                realm = TEST.H5L.SE
index 04043ca02e21094fec384ea428b416fba295e993..820334474095221d9ef7120852a6a2c590568e27 100644 (file)
@@ -90,7 +90,7 @@ ${kadmin} add -p kaka --use-defaults ${server}@${R} || exit 1
 ${kadmin} ext -k ${keytab} ${server}@${R} || exit 1
 
 echo Starting kdc
-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; }
+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; }
 kdcpid=`getpid kdc`
 
 trap "kill -9 ${kdcpid}; echo signal killing kdc; exit 1;" EXIT
index a07f776eb23c89fc17e47578f743c499815ba412..f61a7e853077c78fc08e1b4cd644b3e201f0e167 100644 (file)
@@ -4,6 +4,7 @@ noinst_DATA = \
        an2ln-db.txt \
        kdc-tester4.json \
        krb5.conf \
+       krb5-kcm.conf \
        krb5-cccol.conf \
        krb5-authz.conf \
        krb5-authz2.conf \
@@ -204,6 +205,13 @@ krb5.conf: krb5.conf.in Makefile
           -e 's,[@]kdc[@],,g' < $(srcdir)/krb5.conf.in > krb5.conf.tmp && \
        mv krb5.conf.tmp krb5.conf
 
+krb5-kcm.conf: krb5-kcm.conf.in Makefile
+       $(do_subst) \
+          -e 's,[@]WEAK[@],false,g' \
+          -e 's,[@]dk[@],,g' \
+          -e 's,[@]kdc[@],,g' < $(srcdir)/krb5-kcm.conf.in > krb5-kcm.conf.tmp && \
+       mv krb5-kcm.conf.tmp krb5-kcm.conf
+
 krb5-cccol.conf: krb5-cccol.conf.in Makefile
        $(do_subst) \
           -e 's,[@]WEAK[@],false,g' \
@@ -383,23 +391,23 @@ EXTRA_DIST = \
        NTMakefile \
        an2ln-db.txt \
        check-authz.in \
+       check-bx509.in \
        check-canon.in \
        check-cc.in \
        check-delegation.in \
        check-des.in \
        check-digest.in \
        check-fast.in \
+       check-hdb-mitdb.in \
+       check-httpkadmind.in \
        check-iprop.in \
        check-kadmin.in \
-       check-kinit.in \
-       check-hdb-mitdb.in \
-       check-kdc.in \
        check-kdc-weak.in \
+       check-kdc.in \
        check-keys.in \
+       check-kinit.in \
        check-kpasswdd.in \
        check-pkinit.in \
-       check-bx509.in \
-       check-httpkadmind.in \
        check-referral.in \
        check-tester.in \
        check-uu.in \
@@ -409,23 +417,25 @@ EXTRA_DIST = \
        hdb-mitdb.mkey \
        heimdal.acl \
        iprop-acl \
+       k5login/foo \
+       k5login/mapped_user1 \
        kdc-tester1.json \
        kdc-tester2.json \
        kdc-tester3.json \
        kdc-tester4.json.in \
-       krb5-pkinit.conf.in \
-       krb5-bx509.conf.in \
-       krb5-httpkadmind.conf.in \
-       krb5.conf.in \
        krb5-authz.conf.in \
        krb5-authz2.conf.in \
+       krb5-bx509.conf.in \
        krb5-canon.conf.in \
        krb5-canon2.conf.in \
+       krb5-cccol.conf.in \
        krb5-hdb-mitdb.conf.in \
+       krb5-httpkadmind.conf.in \
+       krb5-pkinit.conf.in \
+       krb5.conf.in \
        krb5.conf.keys.in \
-       k5login/foo \
-       ntlm-user-file.txt \
        leaks-kill.sh \
+       ntlm-user-file.txt \
        pki-mapping \
        uuserver.txt \
        wait-kdc.sh
index 1cef2e0e766de168cfeac462201307b0be6f2849..b50239d844001509f11353d400864f0ca34cc07e 100644 (file)
@@ -428,7 +428,7 @@ ${kadmin} add -r --use-defaults HTTP/${otherserver}@${R} || exit 1
 ${kadmin} ext_keytab -r -k $ukeytab foo@${R} || exit 1
 
 echo "Starting kdc";
-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; }
+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; }
 kdcpid=`getpid kdc`
 trap "kill -9 ${kdcpid} ${bx509pid}; echo signal killing kdc and bx509d; exit 1;" EXIT
 
@@ -590,7 +590,8 @@ KRB5CCNAME=$cache $gsstoken HTTP@$server | KRB5_KTNAME="$keytab" $gsstoken -r ||
     { echo "Trivial offline CA test failed (gss-token)"; exit 2; }
 
 # Check that we get up to three tixaddrs k/v in the log
-grep 'REQ.*numtixaddrs=4 tixaddrs=IPv4:8.8.8.8 tixaddrs=IPv4:8.9.10.11 tixaddrs=IPv4:11.11.11.11.*wrongaddr=yes' ${objdir}/messages.log ||
+grep 'REQ.*wrongaddr=true' ${objdir}/messages.log |
+    grep 'tixaddrs=IPv4:11.11.11.11' ||
     { echo "KDC not warning about requests from wrong address"; exit 2; }
 
 echo "Fetching a Negotiate token"
index 0bb5a413f3cf953e29290d8f483970931fe59c19..18b83a9b7a6905e92371f3b7beb98f56df6f79fc 100644 (file)
@@ -99,7 +99,7 @@ ${kadmin} check ${R3} || exit 1
 echo foo > ${objdir}/foopassword
 
 echo "Starting kdc" ; > messages.log
-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; }
+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; }
 kdcpid=`getpid kdc`
 
 trap "kill -9 ${kdcpid}; echo signal killing kdc; exit 1;" EXIT
index ce95b300664a9e1b35bcb8c5f1d6b4c3e972b305..46e846a10ea1e466b278fd0fcafb03ccbbfb0f5a 100644 (file)
@@ -86,9 +86,16 @@ ${kadmin} check ${R} || exit 1
 echo foo > ${objdir}/foopassword
 
 echo Starting kdc ; > messages.log
-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; }
+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; }
 kdcpid=`getpid kdc`
 
+echo Starting kcm ; > messages.log
+${kcm} -s ${objdir} --detach || { echo "kcm failed to start"; cat messages.log; exit 1; }
+kcmpid=`getpid kcm`
+
+HEIM_IPC_DIR=${objdir}
+export HEIM_IPC_DIR
+
 trap "kill -9 ${kdcpid}; echo signal killing kdc; exit 1;" EXIT
 
 ec=0
@@ -133,6 +140,41 @@ ${klist} -l | grep foo@ >/dev/null && { ec=1 ; eval "${testfailed}"; }
 echo "check that bar is gone"
 ${klist} -l | grep bar@ >/dev/null && { ec=1 ; eval "${testfailed}"; }
 
+echo "getting tickets (KCM)"; > messages.log
+KRB5_CONFIG="${objdir}/krb5-kcm.conf"
+export KRB5_CONFIG
+unset KRB5CCNAME
+${kinit} --default-for-principal foo@${R}
+${kinit} --default-for-principal bar@${R}
+${kinit} bar@${R}
+${klist} > /dev/null || { ec=1 ; eval "${testfailed}"; }
+${klist} | grep bar@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; }
+${klist} | grep foo@${R} > /dev/null && { ec=1 ; eval "${testfailed}"; }
+${klist} -l | grep bar@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; }
+${klist} -l | grep foo@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; }
+${klist} -c KCM: | grep bar@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; }
+KRB5CCNAME=KCM: ${klist} | grep bar@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; }
+if [ -n "$BASH_VERSION" ]; then
+    ${klist} -c KCM:${UID} | grep bar@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; }
+    ${klist} -c KCM:${UID}: | grep bar@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; }
+    KRB5CCNAME=KCM:${UID} ${klist} | grep bar@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; }
+    KRB5CCNAME=KCM:${UID}: ${klist} | grep bar@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; }
+fi
+${kdestroy} -A
+${klist} 2>/dev/null && { ec=1 ; eval "${testfailed}"; }
+${klist} -l | grep bar@${R} > /dev/null && { ec=1 ; eval "${testfailed}"; }
+${klist} -l | grep foo@${R} > /dev/null && { ec=1 ; eval "${testfailed}"; }
+${kinit} bar@${R}
+${kinit} --default-for-principal foo@${R}
+${klist} > /dev/null || { ec=1 ; eval "${testfailed}"; }
+${klist} | grep bar@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; }
+${klist} | grep foo@${R} > /dev/null && { ec=1 ; eval "${testfailed}"; }
+${klist} -l | grep bar@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; }
+${klist} -l | grep foo@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; }
+${klist} -c KCM: | grep bar@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; }
+KRB5CCNAME=KCM: ${klist} | grep bar@${R} > /dev/null || { ec=1 ; eval "${testfailed}"; }
+${kdestroy} -A
+
 echo "getting tickets (DIR)"; > messages.log
 KRB5_CONFIG="${objdir}/krb5-cccol.conf"
 export KRB5_CONFIG
@@ -150,6 +192,9 @@ ${klist} -l |
     grep "bar@TEST.H5L.SE.*FILE:${objdir}/cc_dir/tkt.bar@TEST.H5L.SE" > /dev/null ||
     { ec=1 ; eval "${testfailed}"; }
 
+echo "killing kcm (${kcmpid})"
+sh ${leaks_kill} kcm $kcmpid || exit 1
+
 echo "killing kdc (${kdcpid})"
 sh ${leaks_kill} kdc $kdcpid || exit 1
 
index 8657946168ad480b6ca8aebdaa6d69a2b63c7ae4..fdff0f6a0f0faf5cdf689f7fa886d5945fa47792 100644 (file)
@@ -102,7 +102,7 @@ ${kadmin} check ${R4} || exit 1
 echo foo > ${objdir}/foopassword
 
 echo Starting kdc; > messages.log
-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; }
+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; }
 kdcpid=`getpid kdc`
 
 trap "kill -9 ${kdcpid}; echo signal killing kdc; exit 1;" EXIT
index d45b119dfa5ddea622aafab86aa034d4afd29f34..144613df4f991bd5214986a8b1755243733e35c9 100644 (file)
@@ -96,7 +96,7 @@ ${kadmin} check ${R} || exit 1
 echo foo > ${objdir}/foopassword
 
 echo Starting kdc; > messages.log
-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; }
+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; }
 kdcpid=`getpid kdc`
 
 trap "kill -9 ${kdcpid}; echo signal killing kdc; exit 1;" EXIT
index 1623783eba6d0ce57405f89d99b8cddde4d6cb59..d934f4e2898379e952820348970d137de95f878e 100644 (file)
@@ -95,7 +95,7 @@ echo $password > ${objdir}/foopassword
 
 echo "Starting kdc" ; > messages.log
 env ${HEIM_MALLOC_DEBUG} ${kdc} --detach --testing ||
-    { echo "kdc failed to start"; exit 1; }
+    { echo "kdc failed to start"; cat messages.log; exit 1; }
 kdcpid=`getpid kdc`
 
 trap "kill -9 ${kdcpid}; echo signal killing kdc; cat messages.log; exit 1;" EXIT
index 136bf3ed62b0e8281ba1082fd3ec5eb6310eb129..3fbda813a63bf1272c34fb23b23bde430f8558a1 100644 (file)
@@ -88,7 +88,7 @@ echo bar > ${objdir}/barpassword
 
 echo Starting kdc ; > messages.log
 env MallocStackLogging=1 MallocStackLoggingNoCompact=1 MallocErrorAbort=1 MallocLogFile=${objdir}/malloc-log \
-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; }
+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; }
 kdcpid=`getpid kdc`
 
 trap "kill -9 ${kdcpid}; echo signal killing kdc; cat messages.log; exit 1;" EXIT
index e9de58799a3126d238103fe449c76d0ff42ee165..a241aeb4a8ffb2bfda26f35fe44f2f89380c0f34 100644 (file)
@@ -85,7 +85,7 @@ echo foo > ${objdir}/foopassword
 
 echo Starting kdc ; > messages.log
 env MallocStackLogging=1 MallocStackLoggingNoCompact=1 MallocErrorAbort=1 MallocLogFile=${objdir}/malloc-log \
-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; }
+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; }
 kdcpid=`getpid kdc`
 
 trap "kill -9 ${kdcpid}; echo signal killing kdc; exit 1;" EXIT
index b593925a3524e0aef3813a879e0e9f8500ce00da..f57f2af85928f82a4ce2620670fbcccf7eadfedd 100644 (file)
@@ -519,7 +519,7 @@ ${hxtool} issue-certificate \
          { echo "Failed to make PKINIT client cert"; exit 1; }
 
 echo "Starting kdc needed for httpkadmind authentication to kadmind"
-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; }
+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; }
 kdcpid=`getpid kdc`
 
 echo "Starting httpkadmind with remote HDBs only"
index 212968779435e909665a2e89da4c870745fb2f80..524379393faaa8e1706b38314a06cd309da780df 100644 (file)
@@ -314,7 +314,7 @@ cleanup() {
 trap cleanup EXIT
 
 echo Starting kdc ; > messages.log
-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; }
+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; }
 kdcpid=`getpid kdc`
 
 echo "starting master" ; > messages.log
index 3d3f41003d8604089f440b761052106f73660bac..45d679ceb4a4c82186045c8c90cad579cd9a733c 100644 (file)
@@ -97,7 +97,7 @@ ${kadmin} -l cpw --pruneall --random-key pruneall@${R} || exit 1
 echo "$foopassword" > ${objdir}/foopassword
 
 echo Starting kdc ; > messages.log
-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; }
+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; }
 kdcpid=`getpid kdc`
 
 trap "kill -9 ${kdcpid} ${kadmpid}" EXIT
index 75626f6ce85354b4891c1d1c34300645e6f25948..e53293b2427f3565a6475ba3187b32075ee6f1e6 100644 (file)
@@ -78,6 +78,8 @@ server=host/datan.test.h5l.se
 server2=host/computer.example.com
 server3=host/refer-me-out.test.h5l.se
 server4=host/no-auth-data-reqd.test.h5l.se
+server5=host/a-host.refer-all-out.test.h5l.se
+namespace=WELLKNOWN/HOSTBASED-NAMESPACE/_/refer-all-out.test.h5l.se
 serverip=host/10.11.12.13
 serveripname=host/ip.test.h5l.org
 serveripname2=host/10.11.12.14
@@ -240,6 +242,9 @@ ${kadmin} add -p foo  --use-defaults referral-placeholder@${R5} || exit 1
 ${kadmin} add_alias referral-placeholder@${R5} ${server3}@${R} || exit 1
 ${kadmin5} add -p kaka --use-defaults ${server3}@${R5} || exit 1
 ${kadmin5} ext -k ${keytab} ${server3}@${R5} || exit 1
+${kadmin} add_alias referral-placeholder@${R5} ${namespace}@${R} || exit 1
+${kadmin5} add -p kaka --use-defaults ${server5}@${R5} || exit 1
+${kadmin5} ext -k ${keytab} ${server5}@${R5} || exit 1
 ${kadmin} add -p kaka --use-defaults ${serverip}@${R} || exit 1
 ${kadmin} ext -k ${keytab} ${serverip}@${R} || exit 1
 ${kadmin} add -p kaka --use-defaults ${serveripname}@${R} || exit 1
@@ -364,7 +369,7 @@ echo notfoo > ${objdir}/notfoopassword
 echo Starting kdc ; > messages.log
 env MallocStackLogging=1 MallocStackLoggingNoCompact=1 MallocErrorAbort=1 MallocLogFile=${objdir}/malloc-log \
 ${kdc} --detach --testing ||
-    { echo "kdc failed to start"; exit 1; }
+    { echo "kdc failed to start"; cat messages.log; exit 1; }
 kdcpid=`getpid kdc`
 
 echo Starting kpasswdd; > messages.log
@@ -444,6 +449,8 @@ echo "Getting x-realm tickets with capaths for $R -> $R5"
 ${kgetcred} foo@${R5} || { ec=1 ; eval "${testfailed}"; }
 echo "Testing HDB referral entry"
 ${kgetcred} --canonicalize ${server3}@${R} || { ec=1 ; eval "${testfailed}"; }
+echo "Testing HDB namespace referral entry"
+${kgetcred} --canonicalize ${server5}@${R} || { ec=1 ; eval "${testfailed}"; }
 ${klist}
 ${kdestroy}
 
index 35ec6deadbfa5904b19bb27e0f8a2ec59ae61683..c6cb23ff6f8cadd27ecdc7132b0ce041ec370a53 100644 (file)
@@ -107,7 +107,7 @@ if (($# == 0)); then
     echo foo > ${objdir}/foopassword
 
     echo Starting kdc ; > messages.log
-    ${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; }
+    ${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; }
     kdcpid=`getpid kdc`
 
     trap "kill -9 ${kdcpid}; echo signal killing kdc; exit 1;" EXIT
index 4f63ce240fad83df82e4c649ac6bc67cc52507e9..39f12e1be8c3456788601a54df67cd3305351daf 100644 (file)
@@ -103,7 +103,7 @@ echo foo > ${objdir}/foopassword
 
 echo Starting kdc ; > messages.log
 env ${HEIM_MALLOC_DEBUG} ${kdc} --detach --testing ||
-    { echo "kdc failed to start"; exit 1; }
+    { echo "kdc failed to start"; cat messages.log; exit 1; }
 kdcpid=`getpid kdc`
 
 echo Starting kpasswdd
index baa9fb30691656588ce2837a36c0adbef77bee6c..9f90fd040f9a15ed690bc53846d5dcd225ffeca1 100644 (file)
@@ -199,7 +199,7 @@ echo foo > ${objdir}/foopassword
 
 echo Starting kdc ; > messages.log
 KRB5_CONFIG="${objdir}/krb5-pkinit2.conf"
-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; }
+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; }
 kdcpid=`getpid kdc`
 
 trap 'kill -9 ${kdcpid}; echo signal killing kdc; cat ca.crt kdc.crt pkinit.crt pkinit-synthetic.crt; exit 1;' EXIT
@@ -232,7 +232,7 @@ ${kdestroy}
 echo "Restarting kdc ($kdcpid)"
 sh ${leaks_kill} kdc $kdcpid || ec=1
 KRB5_CONFIG="${objdir}/krb5-pkinit.conf"
-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; }
+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; }
 kdcpid=`getpid kdc`
 
 echo "Trying pk-init (principal in cert)"; > messages.log
index d028e39ef1fa1c13005a41d64beb713f8c6d47de..73c26c368caa3b41102d23ba4a24c20ba8a9732d 100644 (file)
@@ -105,7 +105,7 @@ ${kadmin} check ${R2} || exit 1
 echo foo > ${objdir}/foopassword
 
 echo Starting kdc ; > messages.log
-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; }
+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; }
 kdcpid=`getpid kdc`
 
 trap "kill -9 ${kdcpid}; echo signal killing kdc; exit 1;" EXIT
index dba154c299b9358bb0df765a0305a3c1457ebe2c..83b48baf27fa0312f4b4dfe641c6fce84dc2f568 100644 (file)
@@ -46,6 +46,9 @@ testfailed="echo test failed; cat messages.log; exit 1"
 # If there is no useful db support compiled in, disable test
 ${have_db} || exit 77
 
+# Do not run in GutHub valgrind builds -- too slow / not necessary
+[ -n "$CHECK_TESTER_NO_VALGRIND" ] && exit 77
+
 R=TEST.H5L.SE
 
 keytabfile=${objdir}/server.keytab
index 7e819a14ad0d8e036a9af833e6127fa8a97a2f97..ef831ca4d94aa0c6b4dbaa3a37bf78c977e4d24c 100644 (file)
@@ -86,7 +86,7 @@ ${kadmin} check ${R} || exit 1
 echo foo > ${objdir}/foopassword
 
 echo Starting kdc ; > messages.log
-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; }
+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; }
 kdcpid=`getpid kdc`
 
 trap "kill -9 ${kdcpid} ${uuspid}; echo signal killing kdc; exit 1;" EXIT
diff --git a/third_party/heimdal/tests/kdc/krb5-kcm.conf.in b/third_party/heimdal/tests/kdc/krb5-kcm.conf.in
new file mode 100644 (file)
index 0000000..bdcca07
--- /dev/null
@@ -0,0 +1,165 @@
+[libdefaults]
+       default_realm = TEST.H5L.SE TEST2.H5L.SE
+        default_ccache_name = KCM:%{uid}
+       no-addresses = TRUE
+       allow_weak_crypto = @WEAK@
+       dns_lookup_kdc = no
+       dns_lookup_realm = no
+
+
+[appdefaults]
+       pkinit_anchors = FILE:@srcdir@/../../lib/hx509/data/ca.crt
+       reconnect-min = 2s
+       reconnect-backoff = 2s
+       reconnect-max = 10s
+
+[realms]
+       TEST.H5L.SE = {
+               kdc = localhost:@port@
+               admin_server = localhost:@admport@
+               kpasswd_server = localhost:@pwport@
+       }
+       SUB.TEST.H5L.SE = {
+               kdc = localhost:@port@
+       }
+       TEST2.H5L.SE = {
+               kdc = localhost:@port@
+               kpasswd_server = localhost:@pwport@
+       }
+       TEST3.H5L.SE = {
+               kdc = localhost:@port@
+       }
+       TEST4.H5L.SE = {
+               kdc = localhost:@port@
+       }
+       SOME-REALM5.FR = {
+               kdc = localhost:@port@
+       }
+       SOME-REALM6.US = {
+               kdc = localhost:@port@
+       }
+       SOME-REALM7.UK = {
+               kdc = localhost:@port@
+       }
+       SOME-REALM8.UK = {
+               kdc = localhost:@port@
+       }
+       TEST-HTTP.H5L.SE = {
+               kdc = http/localhost:@port@
+       }
+       H1.TEST.H5L.SE = {
+               kdc = localhost:@port@
+       }
+       H2.TEST.H5L.SE = {
+               kdc = localhost:@port@
+       }
+       H3.H2.TEST.H5L.SE = {
+               kdc = localhost:@port@
+       }
+       H4.H2.TEST.H5L.SE = {
+               kdc = localhost:@port@
+       }
+
+[domain_realm]
+       .test.h5l.se = TEST.H5L.SE
+       .sub.test.h5l.se = SUB.TEST.H5L.SE
+       .h1.test.h5l.se = H1.TEST.H5L.SE
+       .h2.test.h5l.se = H2.TEST.H5L.SE
+       .h3.h2.test.h5l.se = H3.H2.TEST.H5L.SE
+       .h4.h2.test.h5l.se = H4.H2.TEST.H5L.SE
+       .example.com = TEST2.H5L.SE
+       localhost = TEST.H5L.SE
+       .localdomain = TEST.H5L.SE
+       localdomain = TEST.H5L.SE
+       .localdomain6 = TEST.H5L.SE
+       localdomain6 = TEST.H5L.SE
+       
+
+[kdc]
+       enable-digest = true
+       allow-anonymous = true
+       digests_allowed = chap-md5,digest-md5,ntlm-v1,ntlm-v1-session,ntlm-v2,ms-chap-v2
+        strict-nametypes = true
+
+       enable-http = true
+
+       enable-pkinit = true
+       pkinit_identity = FILE:@srcdir@/../../lib/hx509/data/kdc.crt,@srcdir@/../../lib/hx509/data/kdc.key
+       pkinit_anchors = FILE:@srcdir@/../../lib/hx509/data/ca.crt
+       pkinit_pool = FILE:@srcdir@/../../lib/hx509/data/sub-ca.crt
+#      pkinit_revoke = CRL:@srcdir@/../../lib/hx509/data/crl1.crl
+       pkinit_mappings_file = @srcdir@/pki-mapping
+       pkinit_allow_proxy_certificate = true
+
+       database = {
+               label = { 
+                       dbname = @db_type@:@objdir@/current-db@kdc@
+                       realm = TEST.H5L.SE
+                       mkey_file = @objdir@/mkey.file
+                       acl_file = @srcdir@/heimdal.acl
+                       log_file = @objdir@/current@kdc@.log
+               }
+               label2 = { 
+                       dbname = @db_type@:@objdir@/current-db@kdc@
+                       realm = TEST2.H5L.SE
+                       mkey_file = @objdir@/mkey.file
+                       acl_file = @srcdir@/heimdal.acl
+                       log_file = @objdir@/current@kdc@.log
+               }
+               label3 = { 
+                       dbname = sqlite:@objdir@/current-db@kdc@.sqlite3
+                       realm = SOME-REALM5.FR
+                       mkey_file = @objdir@/mkey.file
+                       acl_file = @srcdir@/heimdal.acl
+                       log_file = @objdir@/current@kdc@.log
+               }
+       }
+
+       signal_socket = @objdir@/signal
+       iprop-stats = @objdir@/iprop-stats
+       iprop-acl = @srcdir@/iprop-acl
+        log-max-size = 40000
+
+[hdb]
+       db-dir = @objdir@
+
+[logging]
+       kdc = 0-/FILE:@objdir@/messages.log
+       krb5 = 0-/FILE:@objdir@/messages.log
+       default = 0-/FILE:@objdir@/messages.log
+
+# If you are doing preformance measurements on OSX you want to change
+# the kdc LOG line from = to - below to keep the FILE open and avoid
+# open/write/close which is blocking (rdar:// ) on OSX.
+#      kdc = 0-/FILE=@objdir@/messages.log
+
+[kadmin]
+       save-password = true
+       default_key_rules = {
+               */des3-only@* = des3-cbc-sha1:pw-salt
+               */aes-only@* = aes256-cts-hmac-sha1-96:pw-salt
+       }
+       @dk@
+
+[capaths]
+       TEST.H5L.SE = {
+               TEST2.H5L.SE = .
+               SOME-REALM5.FR = 1
+               TEST3.H5L.SE = TEST2.H5L.SE
+               TEST4.H5L.SE = TEST2.H5L.SE
+               TEST4.H5L.SE = TEST3.H5L.SE
+               SOME-REALM6.US = SOME-REALM5.FR
+               SOME-REALM7.UK = SOME-REALM6.US
+               SOME-REALM7.UK = SOME-REALM5.FR
+               SOME-REALM8.UK = SOME-REALM6.US
+       }
+        H4.H2.TEST.H5L.SE = {
+                H1.TEST.H5L.SE = H3.H2.TEST.H5L.SE
+                H1.TEST.H5L.SE = H2.TEST.H5L.SE
+                H1.TEST.H5L.SE = TEST.H5L.SE
+
+                TEST.H5L.SE = H3.H2.TEST.H5L.SE
+                TEST.H5L.SE = H2.TEST.H5L.SE
+
+                H2.TEST.H5L.SE = H3.H2.TEST.H5L.SE
+        }
index 19b4e3ef64eae66e34b2622e43abfa5386142d33..a85836d76b2439f0c2aeef484ef21d08ae310e59 100644 (file)
 
 [hdb]
        db-dir = @objdir@
+       enable_virtual_hostbased_princs = true
+       virtual_hostbased_princ_mindots = 1
+       virtual_hostbased_princ_maxdots = 3
 
 [logging]
        kdc = 0-/FILE:@objdir@/@messages@.log
index b99c951032bbd8c282376503bac21bc96988bd2c..f73eb6e1b88be3d51991e865040e9dcd143dddca 100644 (file)
@@ -120,7 +120,7 @@ ${kadmin} list '*' > /dev/null || exit 1
 echo "$foopassword" > ${objdir}/foopassword
 
 echo Starting kdc
-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; }
+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; }
 kdcpid=`getpid kdc`
 
 trap "kill ${kdcpid}; echo signal killing kdc; sh ${srcdir}/slapd-stop ; exit 1;" EXIT
index 3fb1a2324b9b4adfe90f568273a73d5db44c74fd..5dd43ccb04da3b8f3abb92373313b29ed183655f 100644 (file)
@@ -29,10 +29,10 @@ krb5.conf: krb5.conf.in Makefile
        $(do_subst) < $(srcdir)/krb5.conf.in > krb5.conf.tmp
        mv krb5.conf.tmp krb5.conf
 
-lib_LTLIBRARIES = windc.la
+lib_LTLIBRARIES = kdc_test_plugin.la
 
-windc_la_SOURCES = windc.c
-windc_la_LDFLAGS = -module
+kdc_test_plugin_la_SOURCES = kdc_test_plugin.c
+kdc_test_plugin_la_LDFLAGS = -module
 
 CLEANFILES= \
        $(TESTS) \
index 60ec21a31f360b73592c88950613c26d76bc387a..85bf8cd9a98d073c82598e6c94125eae81b7904b 100644 (file)
@@ -108,15 +108,15 @@ echo "Empty log"
 > messages.log
 
 echo Starting kdc
-${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; }
+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; }
 kdcpid=`getpid kdc`
 
 trap "kill ${kdcpid}; echo signal killing kdc; exit 1;" EXIT
 
 ec=0
 
-echo "Check that WINDC module was loaded "
-grep "windc init" messages.log >/dev/null || \
+echo "Check that KDC plugin module was loaded "
+grep "kdc plugin init" messages.log >/dev/null || \
        { ec=1 ; eval "${testfailed}"; }
 
 echo "Getting client initial tickets"; > messages.log
diff --git a/third_party/heimdal/tests/plugin/kdc_test_plugin.c b/third_party/heimdal/tests/plugin/kdc_test_plugin.c
new file mode 100644 (file)
index 0000000..4fcf311
--- /dev/null
@@ -0,0 +1,207 @@
+#include <string.h>
+#include <krb5_locl.h>
+#include <hdb.h>
+#include <hx509.h>
+#include <kdc.h>
+#include <kdc-plugin.h>
+
+static krb5_error_code KRB5_CALLCONV
+init(krb5_context context, void **ctx)
+{
+    krb5_warnx(context, "kdc plugin init");
+    *ctx = NULL;
+    return 0;
+}
+
+static void KRB5_CALLCONV
+fini(void *ctx)
+{
+}
+
+static krb5_error_code KRB5_CALLCONV
+pac_generate(void *ctx,
+            krb5_context context,
+            krb5_kdc_configuration *config,
+            hdb_entry *client,
+            hdb_entry *server,
+            const krb5_keyblock *pk_replykey,
+            uint64_t pac_attributes,
+            krb5_pac *pac)
+{
+    krb5_error_code ret;
+    krb5_data data;
+
+    if ((pac_attributes & (KRB5_PAC_WAS_REQUESTED |
+                          KRB5_PAC_WAS_GIVEN_IMPLICITLY)) == 0) {
+       *pac = NULL;
+       return 0;
+    }
+
+    krb5_warnx(context, "pac generate");
+
+    data.data = "\x00\x01";
+    data.length = 2;
+
+    ret = krb5_pac_init(context, pac);
+    if (ret)
+       return ret;
+
+    ret = krb5_pac_add_buffer(context, *pac, 1, &data);
+    if (ret)
+       return ret;
+
+    return 0;
+}
+
+static krb5_error_code KRB5_CALLCONV
+pac_verify(void *ctx,
+          krb5_context context,
+          krb5_kdc_configuration *config,
+          const krb5_principal new_ticket_client,
+          const krb5_principal delegation_proxy,
+          hdb_entry * client,
+          hdb_entry * server,
+          hdb_entry * krbtgt,
+          krb5_pac *pac)
+{
+    krb5_error_code ret;
+    krb5_data data;
+    krb5_cksumtype cstype;
+    uint16_t rodc_id;
+    krb5_enctype etype;
+    Key *key;
+
+    krb5_warnx(context, "pac_verify");
+
+    ret = krb5_pac_get_buffer(context, *pac, 1, &data);
+    if (ret)
+       return ret;
+    krb5_data_free(&data);
+
+    ret = krb5_pac_get_kdc_checksum_info(context, *pac, &cstype, &rodc_id);
+    if (ret)
+       return ret;
+
+    if (rodc_id == 0 || rodc_id != krbtgt->kvno >> 16) {
+       krb5_warnx(context, "Wrong RODCIdentifier");
+       return EINVAL;
+    }
+
+    ret = krb5_cksumtype_to_enctype(context, cstype, &etype);
+    if (ret)
+       return ret;
+
+    ret = hdb_enctype2key(context, krbtgt, NULL, etype, &key);
+    if (ret)
+       return ret;
+
+    return krb5_pac_verify(context, *pac, 0, NULL, NULL, &key->key);
+}
+
+static void logit(const char *what, astgs_request_t r)
+{
+    krb5_context context = kdc_request_get_context((kdc_request_t)r);
+    const char *cname = kdc_request_get_cname((kdc_request_t)r);
+    const char *sname = kdc_request_get_sname((kdc_request_t)r);
+
+    krb5_warnx(context, "%s: client %s server %s",
+              what,
+              cname ? cname : "<unknown>",
+              sname ? sname : "<unknown>");
+}
+
+static krb5_error_code KRB5_CALLCONV
+client_access(void *ctx, astgs_request_t r)
+{
+    logit("client_access", r);
+
+    return 0;
+}
+
+static krb5_error_code KRB5_CALLCONV
+finalize_reply(void *ctx, astgs_request_t r)
+{
+    heim_number_t n;
+    krb5_error_code ret;
+
+    logit("finalize_reply", r);
+
+    n = heim_number_create(1234);
+    if (n == NULL)
+       return ENOMEM;
+
+    ret = kdc_request_set_attribute((kdc_request_t)r,
+                                   HSTR("org.h5l.tests.kdc-plugin"), n);
+    heim_release(n);
+
+    return ret;
+}
+
+static krb5_error_code KRB5_CALLCONV
+audit(void *ctx, astgs_request_t r)
+{
+    krb5_error_code ret = kdc_request_get_error_code((kdc_request_t)r);
+    heim_number_t n;
+
+    logit("audit", r);
+
+    if (ret)
+       return 0; /* finalize_reply only called in success */
+
+    n = kdc_request_get_attribute((kdc_request_t)r,
+                                 HSTR("org.h5l.tests.kdc-plugin"));
+
+    heim_assert(n && heim_number_get_int(n) == 1234,
+               "attribute not passed from finalize_reply");
+
+    if (n == NULL || heim_number_get_int(n) != 1234)
+       return EINVAL; /* return value is ignored, but for completeness */
+
+    return 0;
+}
+
+static krb5plugin_kdc_ftable kdc_plugin = {
+    KRB5_PLUGIN_KDC_VERSION_10,
+    init,
+    fini,
+    pac_generate,
+    pac_verify,
+    client_access,
+    NULL, /* referral_policy */
+    finalize_reply,
+    audit
+};
+
+static const krb5plugin_kdc_ftable *const kdc_plugins[] = {
+    &kdc_plugin
+};
+
+krb5_error_code KRB5_CALLCONV
+kdc_plugin_load(krb5_context context,
+               krb5_get_instance_func_t *get_instance,
+               size_t *num_plugins,
+               const krb5plugin_kdc_ftable *const **plugins);
+
+static uintptr_t KRB5_CALLCONV
+kdc_plugin_get_instance(const char *libname)
+{
+    if (strcmp(libname, "hdb") == 0)
+       return hdb_get_instance(libname);
+    else if (strcmp(libname, "krb5") == 0)
+       return krb5_get_instance(libname);
+
+    return 0;
+}
+
+krb5_error_code KRB5_CALLCONV
+kdc_plugin_load(krb5_context context,
+               krb5_get_instance_func_t *get_instance,
+               size_t *num_plugins,
+               const krb5plugin_kdc_ftable *const **plugins)
+{
+    *get_instance = kdc_plugin_get_instance;
+    *num_plugins = sizeof(kdc_plugins) / sizeof(kdc_plugins[0]);
+    *plugins = kdc_plugins;
+
+    return 0;
+}
index 8ab2f17177c17d4124be2692d8cab281c62f296a..d188c314b360f4dcf29a4f97bfb6d10adba5e7ed 100644 (file)
        }
 
 [kdc]
+       enable-digest = true
+       allow-anonymous = true
+       digests_allowed = chap-md5,digest-md5,ntlm-v1,ntlm-v1-session,ntlm-v2,ms-chap-v2
+        strict-nametypes = true
+        synthetic_clients = true
+       enable_gss_preauth = true
+       gss_mechanisms_allowed = sanon-x25519
+       enable-pkinit = true
+       pkinit_identity = FILE:@srcdir@/../../lib/hx509/data/kdc.crt,@srcdir@/../../lib/hx509/data/kdc.key
+       pkinit_anchors = FILE:@srcdir@/../../lib/hx509/data/ca.crt
+       pkinit_pool = FILE:@srcdir@/../../lib/hx509/data/sub-ca.crt
+#      pkinit_revoke = CRL:@srcdir@/../../lib/hx509/data/crl1.crl
+       pkinit_mappings_file = @srcdir@/pki-mapping
+       pkinit_allow_proxy_certificate = true
+
        database = {
                dbname = @objdir@/current-db
                realm = TEST.H5L.SE
diff --git a/third_party/heimdal/tests/plugin/windc.c b/third_party/heimdal/tests/plugin/windc.c
deleted file mode 100644 (file)
index 3571480..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-#include <string.h>
-#include <krb5_locl.h>
-#include <hdb.h>
-#include <hx509.h>
-#include <kdc.h>
-#include <windc_plugin.h>
-
-static krb5_error_code KRB5_CALLCONV
-windc_init(krb5_context context, void **ctx)
-{
-    krb5_warnx(context, "windc init");
-    *ctx = NULL;
-    return 0;
-}
-
-static void KRB5_CALLCONV
-windc_fini(void *ctx)
-{
-}
-
-static krb5_error_code KRB5_CALLCONV
-pac_generate(void *ctx, krb5_context context,
-            struct hdb_entry_ex *client,
-            struct hdb_entry_ex *server,
-            const krb5_keyblock *pk_replykey,
-            uint64_t pac_attributes,
-            krb5_pac *pac)
-{
-    krb5_error_code ret;
-    krb5_data data;
-
-    if ((pac_attributes & (KRB5_PAC_WAS_REQUESTED |
-                          KRB5_PAC_WAS_GIVEN_IMPLICITLY)) == 0) {
-       *pac = NULL;
-       return 0;
-    }
-
-    krb5_warnx(context, "pac generate");
-
-    data.data = "\x00\x01";
-    data.length = 2;
-
-    ret = krb5_pac_init(context, pac);
-    if (ret)
-       return ret;
-
-    ret = krb5_pac_add_buffer(context, *pac, 1, &data);
-    if (ret)
-       return ret;
-
-    return 0;
-}
-
-static krb5_error_code KRB5_CALLCONV
-pac_verify(void *ctx, krb5_context context,
-          const krb5_principal new_ticket_client,
-          const krb5_principal delegation_proxy,
-          struct hdb_entry_ex * client,
-          struct hdb_entry_ex * server,
-          struct hdb_entry_ex * krbtgt,
-          krb5_pac *pac)
-{
-    krb5_error_code ret;
-    krb5_data data;
-    krb5_cksumtype cstype;
-    uint16_t rodc_id;
-    krb5_enctype etype;
-    Key *key;
-
-    krb5_warnx(context, "pac_verify");
-
-    ret = krb5_pac_get_buffer(context, *pac, 1, &data);
-    if (ret)
-       return ret;
-    krb5_data_free(&data);
-
-    ret = krb5_pac_get_kdc_checksum_info(context, *pac, &cstype, &rodc_id);
-    if (ret)
-       return ret;
-
-    if (rodc_id == 0 || rodc_id != krbtgt->entry.kvno >> 16) {
-       krb5_warnx(context, "Wrong RODCIdentifier");
-       return EINVAL;
-    }
-
-    ret = krb5_cksumtype_to_enctype(context, cstype, &etype);
-    if (ret)
-       return ret;
-
-    ret = hdb_enctype2key(context, &krbtgt->entry, NULL, etype, &key);
-    if (ret)
-       return ret;
-
-    return krb5_pac_verify(context, *pac, 0, NULL, NULL, &key->key);
-}
-
-static void logit(const char *what, astgs_request_t r)
-{
-    krb5_warnx(r->context, "%s: client %s server %s",
-              what,
-              r->cname ? r->cname : "<unknown>",
-              r->sname ? r->sname : "<unknown>");
-}
-
-static krb5_error_code KRB5_CALLCONV
-client_access(void *ctx, astgs_request_t r)
-{
-    logit("client_access", r);
-    return 0;
-}
-
-static krb5_error_code KRB5_CALLCONV
-finalize_reply(void *ctx, astgs_request_t r)
-{
-    logit("finalize_reply", r);
-    return 0;
-}
-
-static krb5plugin_windc_ftable windc = {
-    KRB5_WINDC_PLUGING_MINOR,
-    windc_init,
-    windc_fini,
-    pac_generate,
-    pac_verify,
-    client_access,
-    finalize_reply
-};
-
-static const krb5plugin_windc_ftable *const windc_plugins[] = {
-    &windc
-};
-
-krb5_error_code KRB5_CALLCONV
-windc_plugin_load(krb5_context context,
-                      krb5_get_instance_func_t *get_instance,
-                      size_t *num_plugins,
-                      const krb5plugin_windc_ftable *const **plugins);
-
-static uintptr_t KRB5_CALLCONV
-windc_get_instance(const char *libname)
-{
-    if (strcmp(libname, "hdb") == 0)
-       return hdb_get_instance(libname);
-    else if (strcmp(libname, "krb5") == 0)
-       return krb5_get_instance(libname);
-
-    return 0;
-}
-
-krb5_error_code KRB5_CALLCONV
-windc_plugin_load(krb5_context context,
-                 krb5_get_instance_func_t *get_instance,
-                 size_t *num_plugins,
-                 const krb5plugin_windc_ftable *const **plugins)
-{
-    *get_instance = windc_get_instance;
-    *num_plugins = sizeof(windc_plugins) / sizeof(windc_plugins[0]);
-    *plugins = windc_plugins;
-
-    return 0;
-}
diff --git a/third_party/heimdal/windows/NTMakefile.sdk b/third_party/heimdal/windows/NTMakefile.sdk
new file mode 100644 (file)
index 0000000..a9f2b30
--- /dev/null
@@ -0,0 +1,130 @@
+########################################################################
+#
+# Copyright (c) 2021, PADL Software Pty Ltd.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+#
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in
+#   the documentation and/or other materials provided with the
+#   distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN if ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+!if !defined(CPU) || "$(CPU)" == ""
+CPU         =AMD64
+!endif
+
+!if "$(CPU)" == "X86" || "$(CPU)" == "x86"
+CPU         =i386
+!endif
+
+!if !defined(APPVER)
+APPVER      =6.1
+!endif
+
+!if "$(APPVER)" == "5.0"
+NMAKE_WINVER=0x0500
+!elseif "$(APPVER)" == "5.01"
+NMAKE_WINVER=0x0501
+!elseif "$(APPVER)" == "5.02"
+NMAKE_WINVER=0x0502
+!elseif "$(APPVER)" == "6.0"
+NMAKE_WINVER=0x0600
+!elseif "$(APPVER)" == "6.1"
+NMAKE_WINVER=0x0601
+!elseif "$(APPVER)" == "10.0"
+NMAKE_WINVER=0x0A00
+!else
+!error Unknown value for APPVER
+!endif
+
+cc          = cl
+link        = link
+implib      = lib
+
+cflags      = -c -DCRTAPI1=_cdecl -DCRTAPI2=_cdecl -nologo -GS -W4
+
+!if "$(CPU)" == "i386"
+cflags      = $(cflags) -D_X86_=1
+!endif
+!if "$(CPU)" == "AMD64"
+cflags      = $(cflags) -D_AMD64_=1
+!endif
+!if "$(CPU)" == "ARM"
+cflags      = $(cflags) -D_ARM_=1
+!endif
+!if "$(CPU)" == "ARM64"
+cflags      = $(cflags) -D_ARM64_=1
+!endif
+
+cflags      = $(cflags) -DWIN32 -D_WIN32
+!if "$(CPU)" == "AMD64" || "$(CPU)" == "ARM64"
+cflags      = $(cflags) -DWIN64 -D_WIN64
+!endif
+
+cflags      = $(cflags) -D_WINNT -D_WIN32_WINNT=$(NMAKE_WINVER)
+cflags      = $(cflags) -DNTDDI_VERSION=$(NMAKE_WINVER)0000
+cflags      = $(cflags) -D_WIN32_IE=$(NMAKE_WINVER) -DWINVER=$(NMAKE_WINVER)
+
+!ifdef NODEBUG
+cdebug      = -Ox -DNDEBUG
+!else
+cdebug      = -Zi -Od -DDEBUG
+!endif
+
+cvarsmt     = -D_MT
+cvarsdll    = -D_MT -D_DLL
+!ifdef NODEBUG
+cvarsmt     = $(cvarsmt) -MT
+cvarsdll    = $(cvarsdll) -MD
+!else
+cvarsmt     = $(cvarsmt) -MTd
+cvarsdll    = $(cvarsdll) -MDd
+!endif
+cvars       = $(cvarsmt)
+
+lflags      = $(lflags) /INCREMENTAL:NO /NOLOGO
+!ifdef NODEBUG
+ldebug      = /RELEASE
+!else
+ldebug      = /DEBUG /DEBUGTYPE:cv
+!endif
+
+!if "$(CPU)" == "i386"
+dllentry    = _DllMainCRTStartup@12
+!else
+dllentry    = _DllMainCRTStartup
+!endif
+
+conlflags   = $(lflags) -subsystem:console,$(APPVER)
+guilflags   = $(lflags) -subsystem:windows,$(APPVER)
+dlllflags   = $(lflags) -entry:$(dllentry) -dll
+
+baselibs    = kernel32.lib ws2_32.lib mswsock.lib advapi32.lib
+conlibs     = $(baselibs)
+conlibsmt   = $(baselibs)
+conlibsdll  = $(baselibs)
+
+winlibs     = $(baselibs) user32.lib gdi32.lib comdlg32.lib winspool.lib
+guilibs     = $(winlibs)
+guilibsmt   = $(winlibs)
+guilibsdll  = $(winlibs)
index 47df51042a284464e28f054060e66b6fbf2eea48..471e783912be174e7ac63a0c45f402158db79ddd 100644 (file)
@@ -39,7 +39,7 @@ prep::
 
 all:: prep
 
-!include <Win32.Mak>
+!include "NTMakefile.sdk"
 
 !ifdef NODEBUG
 BUILD=rel
@@ -207,6 +207,8 @@ EXEGUILINK_C = $(LINK) $(ldebug) $(guilflags) $(guilibsdll) $(libmach)
 DLLCONLINK_C = $(LINK) $(ldebug) $(dlllflags) $(conlibsdll) $(libmach)
 DLLGUILINK_C = $(LINK) $(ldebug) $(dlllflags) $(guilibsdll) $(libmach)
 
+C2OBJ_C_MT = $(CC) $(cdebug) $(cflags) $(cvarsmt) $(AUXCFLAGS) $(intcflags) $(cdefines) $(cincdirs) $(cwarn)
+
 !else # STATICRUNTIME
 
 C2OBJ_C = $(CC) $(cdebug) $(cflags) $(cvarsmt) $(AUXCFLAGS) $(intcflags) $(cdefines) $(cincdirs) $(cwarn)
@@ -440,7 +442,7 @@ clean::
        -$(RM) $(OBJ)\*.*
 !endif
 
-.SUFFIXES: .c .cpp .hin .h .x .hx
+.SUFFIXES: .c .cpp .hin .h .hx
 
 #----------------------------------------------------------------------
 # Manifest handling
@@ -574,6 +576,7 @@ DLLPREP_MERGE=\
 #
 
 LIBASN1            =$(LIBDIR)\libasn1.lib
+LIBASN1_S   =$(LIBDIR)\libasn1_s.lib
 LIBCOMERR   =$(LIBDIR)\libcom_err.lib
 LIBEDITLINE =$(LIBDIR)\libeditline.lib
 LIBGSSAPI   =$(LIBDIR)\libgssapi.lib