summaryrefslogtreecommitdiff
path: root/third_party/heimdal
diff options
context:
space:
mode:
authorJoseph Sutton <josephsutton@catalyst.net.nz>2022-03-01 14:17:54 +1300
committerJoseph Sutton <jsutton@samba.org>2022-03-01 22:34:34 +0000
commit51569b3152a952d07fddaa3a70d60c920618c704 (patch)
tree4e447f5d9eb04c7acadf3cff4547068fc79d2113 /third_party/heimdal
parentfccf9859786dfb50b317ea2296c2494997f0ae09 (diff)
downloadsamba-51569b3152a952d07fddaa3a70d60c920618c704.tar.gz
third_party/heimdal: import lorikeet-heimdal-202203010107 (commit 0e7a12404c388e831fe6933fcc3c86e7eb334825)
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>
Diffstat (limited to 'third_party/heimdal')
-rw-r--r--third_party/heimdal/.github/workflows/build.yml67
-rw-r--r--third_party/heimdal/.gitignore236
-rw-r--r--third_party/heimdal/Makefile.am1
-rw-r--r--third_party/heimdal/README.md9
-rw-r--r--third_party/heimdal/admin/change.c1
-rw-r--r--third_party/heimdal/appl/afsutil/afslog.c2
-rw-r--r--third_party/heimdal/appl/gssmask/gssmask.c2
-rw-r--r--third_party/heimdal/appl/kf/kf.c4
-rw-r--r--third_party/heimdal/appl/otp/otp.c12
-rw-r--r--third_party/heimdal/appl/test/gssapi_server.c23
-rw-r--r--third_party/heimdal/appl/test/uu_server.c7
-rw-r--r--third_party/heimdal/appveyor.yml72
-rw-r--r--third_party/heimdal/cf/Makefile.am.common19
-rw-r--r--third_party/heimdal/cf/ax_check_sign.m454
-rw-r--r--third_party/heimdal/cf/check-compile-flag.m453
-rw-r--r--third_party/heimdal/cf/db.m46
-rw-r--r--third_party/heimdal/cf/krb-prog-yacc.m412
-rw-r--r--third_party/heimdal/cf/roken-frag.m46
-rw-r--r--third_party/heimdal/configure.ac38
-rwxr-xr-xthird_party/heimdal/import-lorikeet.sh22
-rw-r--r--third_party/heimdal/include/Makefile.am33
-rw-r--r--third_party/heimdal/include/bits.c51
-rw-r--r--third_party/heimdal/include/config.h.w3237
-rw-r--r--third_party/heimdal/kadmin/add-random-users.c2
-rw-r--r--third_party/heimdal/kadmin/add_enctype.c4
-rw-r--r--third_party/heimdal/kadmin/ank.c40
-rw-r--r--third_party/heimdal/kadmin/cpw.c16
-rw-r--r--third_party/heimdal/kadmin/del.c12
-rw-r--r--third_party/heimdal/kadmin/ext.c2
-rw-r--r--third_party/heimdal/kadmin/get.c2
-rw-r--r--third_party/heimdal/kadmin/init.c202
-rw-r--r--third_party/heimdal/kadmin/kadm_conn.c9
-rw-r--r--third_party/heimdal/kadmin/kadmin.133
-rw-r--r--third_party/heimdal/kadmin/kadmind.c2
-rw-r--r--third_party/heimdal/kadmin/load.c54
-rw-r--r--third_party/heimdal/kadmin/mod.c15
-rw-r--r--third_party/heimdal/kadmin/rpc.c4
-rw-r--r--third_party/heimdal/kadmin/server.c315
-rw-r--r--third_party/heimdal/kadmin/stash.c5
-rw-r--r--third_party/heimdal/kcm/cache.c10
-rw-r--r--third_party/heimdal/kcm/client.c37
-rw-r--r--third_party/heimdal/kcm/glue.c2
-rw-r--r--third_party/heimdal/kcm/protocol.c24
-rw-r--r--third_party/heimdal/kdc/Makefile.am14
-rw-r--r--third_party/heimdal/kdc/NTMakefile18
-rw-r--r--third_party/heimdal/kdc/altsecid_gss_preauth_authorizer.c85
-rw-r--r--third_party/heimdal/kdc/bx509d.c170
-rw-r--r--third_party/heimdal/kdc/ca.c4
-rw-r--r--third_party/heimdal/kdc/cjwt_token_validator.c9
-rw-r--r--third_party/heimdal/kdc/config.c2
-rw-r--r--third_party/heimdal/kdc/connect.c19
-rw-r--r--third_party/heimdal/kdc/csr_authorizer.c2
-rw-r--r--third_party/heimdal/kdc/default_config.c5
-rw-r--r--third_party/heimdal/kdc/digest-service.c9
-rw-r--r--third_party/heimdal/kdc/digest.c46
-rw-r--r--third_party/heimdal/kdc/fast.c35
-rw-r--r--third_party/heimdal/kdc/gss_preauth.c78
-rw-r--r--third_party/heimdal/kdc/gss_preauth_authorizer_plugin.h6
-rw-r--r--third_party/heimdal/kdc/headers.h3
-rw-r--r--third_party/heimdal/kdc/hprop.81
-rw-r--r--third_party/heimdal/kdc/hprop.c23
-rw-r--r--third_party/heimdal/kdc/hprop.h18
-rw-r--r--third_party/heimdal/kdc/hpropd.83
-rw-r--r--third_party/heimdal/kdc/hpropd.c11
-rw-r--r--third_party/heimdal/kdc/httpkadmind.c73
-rw-r--r--third_party/heimdal/kdc/ipc_csr_authorizer.c20
-rw-r--r--third_party/heimdal/kdc/kdc-accessors.h349
-rw-r--r--third_party/heimdal/kdc/kdc-audit.h (renamed from third_party/heimdal/kdc/rx.h)68
-rw-r--r--third_party/heimdal/kdc/kdc-plugin.c658
-rw-r--r--third_party/heimdal/kdc/kdc-plugin.h136
-rw-r--r--third_party/heimdal/kdc/kdc-replay.c2
-rw-r--r--third_party/heimdal/kdc/kdc.h168
-rw-r--r--third_party/heimdal/kdc/kdc_locl.h109
-rw-r--r--third_party/heimdal/kdc/kerberos5.c691
-rw-r--r--third_party/heimdal/kdc/krb5tgs.c946
-rw-r--r--third_party/heimdal/kdc/kstash.c2
-rw-r--r--third_party/heimdal/kdc/kx509.c130
-rw-r--r--third_party/heimdal/kdc/libkdc-exports.def83
-rw-r--r--third_party/heimdal/kdc/log.c10
-rw-r--r--third_party/heimdal/kdc/misc.c103
-rw-r--r--third_party/heimdal/kdc/mit_dump.c6
-rw-r--r--third_party/heimdal/kdc/mssfu.c568
-rw-r--r--third_party/heimdal/kdc/negotiate_token_validator.c2
-rw-r--r--third_party/heimdal/kdc/pkinit.c30
-rw-r--r--third_party/heimdal/kdc/process.c204
-rw-r--r--third_party/heimdal/kdc/set_dbinfo.c2
-rw-r--r--third_party/heimdal/kdc/simple_csr_authorizer.c24
-rw-r--r--third_party/heimdal/kdc/string2key.c6
-rw-r--r--third_party/heimdal/kdc/test_kdc_ca.c5
-rw-r--r--third_party/heimdal/kdc/token_validator.c2
-rw-r--r--third_party/heimdal/kdc/version-script.map78
-rw-r--r--third_party/heimdal/kdc/windc.c252
-rw-r--r--third_party/heimdal/kdc/windc_plugin.h92
-rw-r--r--third_party/heimdal/kpasswd/kpasswdd.c2
-rw-r--r--third_party/heimdal/kuser/generate-requests.c2
-rw-r--r--third_party/heimdal/kuser/kgetcred.c3
-rw-r--r--third_party/heimdal/kuser/kimpersonate.c27
-rw-r--r--third_party/heimdal/kuser/kinit.c34
-rw-r--r--third_party/heimdal/kuser/klist.c15
-rw-r--r--third_party/heimdal/kuser/kswitch.c5
-rw-r--r--third_party/heimdal/kuser/kuser_locl.h4
-rw-r--r--third_party/heimdal/lib/asn1/MANUAL.md1287
-rw-r--r--third_party/heimdal/lib/asn1/Makefile.am361
-rw-r--r--third_party/heimdal/lib/asn1/NTMakefile281
-rw-r--r--third_party/heimdal/lib/asn1/README.md326
-rw-r--r--third_party/heimdal/lib/asn1/asn1-template.h75
-rw-r--r--third_party/heimdal/lib/asn1/asn1_compile.1263
-rw-r--r--third_party/heimdal/lib/asn1/asn1_print.c32
-rw-r--r--third_party/heimdal/lib/asn1/asn1parse.y141
-rw-r--r--third_party/heimdal/lib/asn1/check-common.h3
-rw-r--r--third_party/heimdal/lib/asn1/check-der.c2
-rw-r--r--third_party/heimdal/lib/asn1/check-gen.c144
-rw-r--r--third_party/heimdal/lib/asn1/check-gen.h9
-rw-r--r--third_party/heimdal/lib/asn1/check-template.c13
-rw-r--r--third_party/heimdal/lib/asn1/der_copy.c103
-rw-r--r--third_party/heimdal/lib/asn1/der_get.c92
-rw-r--r--third_party/heimdal/lib/asn1/der_put.c68
-rw-r--r--third_party/heimdal/lib/asn1/extra.c8
-rw-r--r--third_party/heimdal/lib/asn1/gen.c186
-rw-r--r--third_party/heimdal/lib/asn1/gen_copy.c47
-rw-r--r--third_party/heimdal/lib/asn1/gen_decode.c6
-rw-r--r--third_party/heimdal/lib/asn1/gen_encode.c29
-rw-r--r--third_party/heimdal/lib/asn1/gen_free.c55
-rw-r--r--third_party/heimdal/lib/asn1/gen_glue.c11
-rw-r--r--third_party/heimdal/lib/asn1/gen_locl.h17
-rw-r--r--third_party/heimdal/lib/asn1/gen_template.c172
-rw-r--r--third_party/heimdal/lib/asn1/krb5.asn146
-rw-r--r--third_party/heimdal/lib/asn1/krb5.opt2
-rw-r--r--third_party/heimdal/lib/asn1/libasn1-exports.def6
-rw-r--r--third_party/heimdal/lib/asn1/main.c240
-rw-r--r--third_party/heimdal/lib/asn1/oid_resolution.c75
-rw-r--r--third_party/heimdal/lib/asn1/symbol.h5
-rw-r--r--third_party/heimdal/lib/asn1/template.c56
-rw-r--r--third_party/heimdal/lib/asn1/test.asn112
-rw-r--r--third_party/heimdal/lib/asn1/test.opt6
-rw-r--r--third_party/heimdal/lib/base/array.c4
-rw-r--r--third_party/heimdal/lib/base/bsearch.c24
-rw-r--r--third_party/heimdal/lib/base/data.c9
-rw-r--r--third_party/heimdal/lib/base/db.c24
-rw-r--r--third_party/heimdal/lib/base/dict.c8
-rw-r--r--third_party/heimdal/lib/base/dll.c3
-rw-r--r--third_party/heimdal/lib/base/error.c4
-rw-r--r--third_party/heimdal/lib/base/error_string.c7
-rw-r--r--third_party/heimdal/lib/base/expand_path.c58
-rw-r--r--third_party/heimdal/lib/base/heimbase-svc.h8
-rw-r--r--third_party/heimdal/lib/base/heimbase.c35
-rw-r--r--third_party/heimdal/lib/base/heimbase.h9
-rw-r--r--third_party/heimdal/lib/base/heimbasepriv.h3
-rw-r--r--third_party/heimdal/lib/base/log.c363
-rw-r--r--third_party/heimdal/lib/base/number.c22
-rw-r--r--third_party/heimdal/lib/base/plugin.c16
-rw-r--r--third_party/heimdal/lib/base/string.c6
-rw-r--r--third_party/heimdal/lib/base/test_base.c6
-rw-r--r--third_party/heimdal/lib/base/version-script.map7
-rw-r--r--third_party/heimdal/lib/com_err/Makefile.am2
-rw-r--r--third_party/heimdal/lib/gss_preauth/pa_client.c3
-rw-r--r--third_party/heimdal/lib/gss_preauth/pa_common.c5
-rw-r--r--third_party/heimdal/lib/gssapi/Makefile.am55
-rw-r--r--third_party/heimdal/lib/gssapi/NTMakefile38
-rw-r--r--third_party/heimdal/lib/gssapi/gss-token.c11
-rw-r--r--third_party/heimdal/lib/gssapi/gssapi/gssapi.h16
-rw-r--r--third_party/heimdal/lib/gssapi/gssapi/gssapi_krb5.h2
-rw-r--r--third_party/heimdal/lib/gssapi/krb5/accept_sec_context.c140
-rw-r--r--third_party/heimdal/lib/gssapi/krb5/acquire_cred.c52
-rw-r--r--third_party/heimdal/lib/gssapi/krb5/arcfour.c13
-rw-r--r--third_party/heimdal/lib/gssapi/krb5/copy_ccache.c5
-rw-r--r--third_party/heimdal/lib/gssapi/krb5/export_sec_context.c2
-rw-r--r--third_party/heimdal/lib/gssapi/krb5/external.c19
-rw-r--r--third_party/heimdal/lib/gssapi/krb5/import_name.c35
-rw-r--r--third_party/heimdal/lib/gssapi/krb5/init_sec_context.c41
-rw-r--r--third_party/heimdal/lib/gssapi/krb5/name_attrs.c1171
-rw-r--r--third_party/heimdal/lib/gssapi/krb5/store_cred.c5
-rw-r--r--third_party/heimdal/lib/gssapi/krb5/test_kcred.c6
-rw-r--r--third_party/heimdal/lib/gssapi/libgssapi-exports.def2
-rw-r--r--third_party/heimdal/lib/gssapi/mech/gss_compare_name.c10
-rw-r--r--third_party/heimdal/lib/gssapi/mech/gss_cred.c6
-rw-r--r--third_party/heimdal/lib/gssapi/mech/gss_export_sec_context.c4
-rw-r--r--third_party/heimdal/lib/gssapi/mech/gss_import_name.c82
-rw-r--r--third_party/heimdal/lib/gssapi/mech/gss_import_sec_context.c6
-rw-r--r--third_party/heimdal/lib/gssapi/mech/gss_krb5.c7
-rw-r--r--third_party/heimdal/lib/gssapi/mech/gss_mech_switch.c47
-rw-r--r--third_party/heimdal/lib/gssapi/mech/gss_pname_to_uid.c4
-rw-r--r--third_party/heimdal/lib/gssapi/mech/mech_locl.h11
-rw-r--r--third_party/heimdal/lib/gssapi/ntlm/accept_sec_context.c2
-rw-r--r--third_party/heimdal/lib/gssapi/ntlm/creds.c4
-rw-r--r--third_party/heimdal/lib/gssapi/ntlm/crypto.c5
-rw-r--r--third_party/heimdal/lib/gssapi/ntlm/delete_sec_context.c6
-rw-r--r--third_party/heimdal/lib/gssapi/ntlm/init_sec_context.c22
-rw-r--r--third_party/heimdal/lib/gssapi/ntlm/kdc.c1
-rw-r--r--third_party/heimdal/lib/gssapi/sanon/import_name.c25
-rw-r--r--third_party/heimdal/lib/gssapi/spnego/accept_sec_context.c1
-rw-r--r--third_party/heimdal/lib/gssapi/spnego/negoex_ctx.c28
-rw-r--r--third_party/heimdal/lib/gssapi/test_context.c168
-rw-r--r--third_party/heimdal/lib/gssapi/test_kcred.c18
-rw-r--r--third_party/heimdal/lib/gssapi/test_names.c464
-rw-r--r--third_party/heimdal/lib/gssapi/version-script.map2
-rw-r--r--third_party/heimdal/lib/hcrypto/Makefile.am27
-rw-r--r--third_party/heimdal/lib/hcrypto/bn.c8
-rw-r--r--third_party/heimdal/lib/hcrypto/des.c1
-rw-r--r--third_party/heimdal/lib/hcrypto/dh-ltm.c57
-rw-r--r--third_party/heimdal/lib/hcrypto/dh.c2
-rw-r--r--third_party/heimdal/lib/hcrypto/engine.c35
-rw-r--r--third_party/heimdal/lib/hcrypto/evp.c9
-rw-r--r--third_party/heimdal/lib/hcrypto/hmac.c28
-rw-r--r--third_party/heimdal/lib/hcrypto/hmac.h2
-rw-r--r--third_party/heimdal/lib/hcrypto/libtommath/bn_mp_set_double.c2
-rw-r--r--third_party/heimdal/lib/hcrypto/libtommath/bn_s_mp_rand_platform.c2
-rw-r--r--third_party/heimdal/lib/hcrypto/libtommath/demo/test.c2
-rw-r--r--third_party/heimdal/lib/hcrypto/libtommath/etc/tune.c2
-rw-r--r--third_party/heimdal/lib/hcrypto/rsa-ltm.c7
-rw-r--r--third_party/heimdal/lib/hcrypto/rsa.c7
-rw-r--r--third_party/heimdal/lib/hcrypto/test_hmac.c6
-rw-r--r--third_party/heimdal/lib/hcrypto/validate.c3
-rw-r--r--third_party/heimdal/lib/hdb/Makefile.am67
-rw-r--r--third_party/heimdal/lib/hdb/NTMakefile12
-rw-r--r--third_party/heimdal/lib/hdb/common.c375
-rw-r--r--third_party/heimdal/lib/hdb/db.c22
-rw-r--r--third_party/heimdal/lib/hdb/db3.c22
-rw-r--r--third_party/heimdal/lib/hdb/ext.c4
-rw-r--r--third_party/heimdal/lib/hdb/hdb-keytab.c22
-rw-r--r--third_party/heimdal/lib/hdb/hdb-ldap.c363
-rw-r--r--third_party/heimdal/lib/hdb/hdb-mdb.c22
-rw-r--r--third_party/heimdal/lib/hdb/hdb-mitdb.c89
-rw-r--r--third_party/heimdal/lib/hdb/hdb-sqlite.c39
-rw-r--r--third_party/heimdal/lib/hdb/hdb.asn12
-rw-r--r--third_party/heimdal/lib/hdb/hdb.c98
-rw-r--r--third_party/heimdal/lib/hdb/hdb.h175
-rw-r--r--third_party/heimdal/lib/hdb/hdb.opt5
-rw-r--r--third_party/heimdal/lib/hdb/keys.c2
-rw-r--r--third_party/heimdal/lib/hdb/keytab.c50
-rw-r--r--third_party/heimdal/lib/hdb/libhdb-exports.def1
-rw-r--r--third_party/heimdal/lib/hdb/ndbm.c53
-rw-r--r--third_party/heimdal/lib/hdb/print.c20
-rw-r--r--third_party/heimdal/lib/hdb/test_concurrency.c58
-rw-r--r--third_party/heimdal/lib/hdb/test_namespace.c162
-rw-r--r--third_party/heimdal/lib/hdb/version-script.map1
-rw-r--r--third_party/heimdal/lib/hx509/Makefile.am3
-rw-r--r--third_party/heimdal/lib/hx509/ca.c21
-rw-r--r--third_party/heimdal/lib/hx509/cert.c42
-rw-r--r--third_party/heimdal/lib/hx509/cms.c6
-rw-r--r--third_party/heimdal/lib/hx509/collector.c3
-rw-r--r--third_party/heimdal/lib/hx509/crypto.c4
-rw-r--r--third_party/heimdal/lib/hx509/error.c66
-rw-r--r--third_party/heimdal/lib/hx509/file.c12
-rw-r--r--third_party/heimdal/lib/hx509/hxtool.c28
-rw-r--r--third_party/heimdal/lib/hx509/keyset.c5
-rw-r--r--third_party/heimdal/lib/hx509/ks_file.c29
-rw-r--r--third_party/heimdal/lib/hx509/name.c71
-rw-r--r--third_party/heimdal/lib/hx509/print.c5
-rw-r--r--third_party/heimdal/lib/hx509/req.c22
-rw-r--r--third_party/heimdal/lib/hx509/revoke.c4
-rw-r--r--third_party/heimdal/lib/hx509/sel-gram.y4
-rw-r--r--third_party/heimdal/lib/hx509/softp11.c8
-rw-r--r--third_party/heimdal/lib/ipc/Makefile.am4
-rw-r--r--third_party/heimdal/lib/ipc/server.c15
-rw-r--r--third_party/heimdal/lib/kadm5/ad.c2
-rw-r--r--third_party/heimdal/lib/kadm5/chpass_s.c56
-rw-r--r--third_party/heimdal/lib/kadm5/context_s.c16
-rw-r--r--third_party/heimdal/lib/kadm5/create_s.c32
-rw-r--r--third_party/heimdal/lib/kadm5/delete_s.c8
-rw-r--r--third_party/heimdal/lib/kadm5/ent_setup.c78
-rw-r--r--third_party/heimdal/lib/kadm5/get_princs_s.c8
-rw-r--r--third_party/heimdal/lib/kadm5/get_s.c143
-rw-r--r--third_party/heimdal/lib/kadm5/init_c.c12
-rw-r--r--third_party/heimdal/lib/kadm5/init_s.c6
-rw-r--r--third_party/heimdal/lib/kadm5/iprop-log.c67
-rw-r--r--third_party/heimdal/lib/kadm5/ipropd_common.c1
-rw-r--r--third_party/heimdal/lib/kadm5/ipropd_master.c31
-rw-r--r--third_party/heimdal/lib/kadm5/ipropd_slave.c8
-rw-r--r--third_party/heimdal/lib/kadm5/log.c172
-rw-r--r--third_party/heimdal/lib/kadm5/marshall.c254
-rw-r--r--third_party/heimdal/lib/kadm5/modify_s.c12
-rw-r--r--third_party/heimdal/lib/kadm5/prune_s.c10
-rw-r--r--third_party/heimdal/lib/kadm5/randkey_c.c2
-rw-r--r--third_party/heimdal/lib/kadm5/randkey_s.c26
-rw-r--r--third_party/heimdal/lib/kadm5/rename_s.c32
-rw-r--r--third_party/heimdal/lib/kadm5/set_keys.c2
-rw-r--r--third_party/heimdal/lib/kadm5/setkey3_s.c28
-rw-r--r--third_party/heimdal/lib/kafs/Makefile.am2
-rw-r--r--third_party/heimdal/lib/kafs/afskrb5.c2
-rw-r--r--third_party/heimdal/lib/kafs/afssys.c2
-rw-r--r--third_party/heimdal/lib/kafs/rxkad_kdf.c8
-rw-r--r--third_party/heimdal/lib/krb5/Makefile.am4
-rw-r--r--third_party/heimdal/lib/krb5/NTMakefile2
-rw-r--r--third_party/heimdal/lib/krb5/acache.c27
-rw-r--r--third_party/heimdal/lib/krb5/acl.c2
-rw-r--r--third_party/heimdal/lib/krb5/addr_families.c19
-rw-r--r--third_party/heimdal/lib/krb5/aes-test.c22
-rw-r--r--third_party/heimdal/lib/krb5/asn1_glue.c94
-rw-r--r--third_party/heimdal/lib/krb5/auth_context.c5
-rw-r--r--third_party/heimdal/lib/krb5/cache.c25
-rw-r--r--third_party/heimdal/lib/krb5/context.c15
-rw-r--r--third_party/heimdal/lib/krb5/crypto-evp.c7
-rw-r--r--third_party/heimdal/lib/krb5/crypto.c7
-rw-r--r--third_party/heimdal/lib/krb5/data.c7
-rw-r--r--third_party/heimdal/lib/krb5/dcache.c14
-rw-r--r--third_party/heimdal/lib/krb5/deprecated.c10
-rw-r--r--third_party/heimdal/lib/krb5/enomem.c2
-rw-r--r--third_party/heimdal/lib/krb5/error_string.c19
-rw-r--r--third_party/heimdal/lib/krb5/expand_path.c4
-rw-r--r--third_party/heimdal/lib/krb5/fast.c13
-rw-r--r--third_party/heimdal/lib/krb5/fcache.c15
-rw-r--r--third_party/heimdal/lib/krb5/generate_subkey.c2
-rw-r--r--third_party/heimdal/lib/krb5/get_cred.c54
-rw-r--r--third_party/heimdal/lib/krb5/get_in_tkt.c2
-rw-r--r--third_party/heimdal/lib/krb5/init_creds_pw.c147
-rw-r--r--third_party/heimdal/lib/krb5/kcm.c267
-rw-r--r--third_party/heimdal/lib/krb5/keytab.c68
-rw-r--r--third_party/heimdal/lib/krb5/keytab_file.c3
-rw-r--r--third_party/heimdal/lib/krb5/keytab_keyfile.c2
-rw-r--r--third_party/heimdal/lib/krb5/krb5.conf.56
-rw-r--r--third_party/heimdal/lib/krb5/krb5.h116
-rw-r--r--third_party/heimdal/lib/krb5/krb5_locl.h2
-rw-r--r--third_party/heimdal/lib/krb5/krbhst-test.c17
-rw-r--r--third_party/heimdal/lib/krb5/krbhst.c24
-rw-r--r--third_party/heimdal/lib/krb5/krcache.c31
-rw-r--r--third_party/heimdal/lib/krb5/kx509.c62
-rw-r--r--third_party/heimdal/lib/krb5/libkrb5-exports.def.in7
-rw-r--r--third_party/heimdal/lib/krb5/mcache.c4
-rw-r--r--third_party/heimdal/lib/krb5/mk_cred.c15
-rw-r--r--third_party/heimdal/lib/krb5/pac.c137
-rw-r--r--third_party/heimdal/lib/krb5/pkinit.c21
-rw-r--r--third_party/heimdal/lib/krb5/principal.c33
-rw-r--r--third_party/heimdal/lib/krb5/rd_cred.c2
-rw-r--r--third_party/heimdal/lib/krb5/rd_req.c66
-rw-r--r--third_party/heimdal/lib/krb5/replay.c4
-rw-r--r--third_party/heimdal/lib/krb5/salt-arcfour.c6
-rw-r--r--third_party/heimdal/lib/krb5/scache.c91
-rw-r--r--third_party/heimdal/lib/krb5/send_to_kdc.c14
-rwxr-xr-xthird_party/heimdal/lib/krb5/sp800-108-kdf.c5
-rw-r--r--third_party/heimdal/lib/krb5/store.c24
-rw-r--r--third_party/heimdal/lib/krb5/store_emem.c25
-rw-r--r--third_party/heimdal/lib/krb5/store_stdio.c2
-rw-r--r--third_party/heimdal/lib/krb5/test_alname.c2
-rw-r--r--third_party/heimdal/lib/krb5/test_ap-req.c1
-rw-r--r--third_party/heimdal/lib/krb5/test_cc.c10
-rw-r--r--third_party/heimdal/lib/krb5/test_hostname.c4
-rw-r--r--third_party/heimdal/lib/krb5/test_rfc3961.c1
-rw-r--r--third_party/heimdal/lib/krb5/test_set_kvno0.c5
-rw-r--r--third_party/heimdal/lib/krb5/ticket.c91
-rw-r--r--third_party/heimdal/lib/krb5/transited.c19
-rw-r--r--third_party/heimdal/lib/krb5/verify_user.c13
-rw-r--r--third_party/heimdal/lib/krb5/version-script.map7
-rw-r--r--third_party/heimdal/lib/ntlm/digest.c2
-rw-r--r--third_party/heimdal/lib/ntlm/ntlm.c75
-rw-r--r--third_party/heimdal/lib/otp/otp_md.c4
-rw-r--r--third_party/heimdal/lib/roken/Makefile.am6
-rw-r--r--third_party/heimdal/lib/roken/base32-test.c3
-rw-r--r--third_party/heimdal/lib/roken/base32.c12
-rw-r--r--third_party/heimdal/lib/roken/base64-test.c3
-rw-r--r--third_party/heimdal/lib/roken/base64.c4
-rw-r--r--third_party/heimdal/lib/roken/copyhostent.c3
-rw-r--r--third_party/heimdal/lib/roken/detach.c3
-rw-r--r--third_party/heimdal/lib/roken/dirent-test.c6
-rw-r--r--third_party/heimdal/lib/roken/environment.c15
-rw-r--r--third_party/heimdal/lib/roken/fnmatch.c2
-rw-r--r--third_party/heimdal/lib/roken/freeaddrinfo.c2
-rw-r--r--third_party/heimdal/lib/roken/freehostent.c2
-rw-r--r--third_party/heimdal/lib/roken/getaddrinfo.c10
-rw-r--r--third_party/heimdal/lib/roken/getcap.c996
-rw-r--r--third_party/heimdal/lib/roken/getipnodebyaddr.c2
-rw-r--r--third_party/heimdal/lib/roken/getipnodebyname.c2
-rw-r--r--third_party/heimdal/lib/roken/getnameinfo.c8
-rw-r--r--third_party/heimdal/lib/roken/getuserinfo.c30
-rw-r--r--third_party/heimdal/lib/roken/hex-test.c35
-rw-r--r--third_party/heimdal/lib/roken/hex.c28
-rw-r--r--third_party/heimdal/lib/roken/mergesort_r.c4
-rw-r--r--third_party/heimdal/lib/roken/ndbm_wrap.c2
-rw-r--r--third_party/heimdal/lib/roken/net_write.c7
-rw-r--r--third_party/heimdal/lib/roken/resolve-test.c2
-rw-r--r--third_party/heimdal/lib/roken/roken-common.h6
-rw-r--r--third_party/heimdal/lib/roken/roken.h.in60
-rw-r--r--third_party/heimdal/lib/roken/snprintf.c2
-rw-r--r--third_party/heimdal/lib/roken/socket.c29
-rw-r--r--third_party/heimdal/lib/roken/strftime.c7
-rw-r--r--third_party/heimdal/lib/roken/strptime.c2
-rw-r--r--third_party/heimdal/lib/roken/strtoll.c3
-rw-r--r--third_party/heimdal/lib/roken/strtoull.c3
-rw-r--r--third_party/heimdal/lib/roken/test-getuserinfo.c3
-rw-r--r--third_party/heimdal/lib/roken/test-mini_inetd.c2
-rw-r--r--third_party/heimdal/lib/roken/timeval.c215
-rw-r--r--third_party/heimdal/lib/roken/version-script.map5
-rw-r--r--third_party/heimdal/lib/roken/vis.c17
-rw-r--r--third_party/heimdal/lib/sl/Makefile.am2
-rw-r--r--third_party/heimdal/lib/sl/sl.c2
-rw-r--r--third_party/heimdal/lib/sl/slc-gram.y1
-rw-r--r--third_party/heimdal/lib/wind/idn-lookup.c6
-rw-r--r--third_party/heimdal/lib/wind/utf8.c18
-rw-r--r--third_party/heimdal/packages/windows/installer/NTMakefile33
-rw-r--r--third_party/heimdal/packages/windows/installer/heimdal-installer.wxs20
-rw-r--r--third_party/heimdal/tests/bin/setup-env.in1
-rw-r--r--third_party/heimdal/tests/gss/Makefile.am2
-rw-r--r--third_party/heimdal/tests/gss/check-basic.in4
-rw-r--r--third_party/heimdal/tests/gss/check-context.in12
-rw-r--r--third_party/heimdal/tests/gss/check-gssmask.in4
-rw-r--r--third_party/heimdal/tests/gss/check-ntlm.in4
-rw-r--r--third_party/heimdal/tests/gss/check-spnego.in4
-rw-r--r--third_party/heimdal/tests/gss/krb5.conf.in15
-rw-r--r--third_party/heimdal/tests/java/check-kinit.in2
-rw-r--r--third_party/heimdal/tests/kdc/Makefile.am32
-rw-r--r--third_party/heimdal/tests/kdc/check-bx509.in5
-rw-r--r--third_party/heimdal/tests/kdc/check-canon.in2
-rw-r--r--third_party/heimdal/tests/kdc/check-cc.in47
-rw-r--r--third_party/heimdal/tests/kdc/check-delegation.in2
-rw-r--r--third_party/heimdal/tests/kdc/check-des.in2
-rw-r--r--third_party/heimdal/tests/kdc/check-digest.in2
-rw-r--r--third_party/heimdal/tests/kdc/check-fast.in2
-rw-r--r--third_party/heimdal/tests/kdc/check-hdb-mitdb.in2
-rw-r--r--third_party/heimdal/tests/kdc/check-httpkadmind.in2
-rw-r--r--third_party/heimdal/tests/kdc/check-iprop.in2
-rw-r--r--third_party/heimdal/tests/kdc/check-kadmin.in2
-rw-r--r--third_party/heimdal/tests/kdc/check-kdc.in9
-rw-r--r--third_party/heimdal/tests/kdc/check-kinit.in2
-rw-r--r--third_party/heimdal/tests/kdc/check-kpasswdd.in2
-rw-r--r--third_party/heimdal/tests/kdc/check-pkinit.in4
-rw-r--r--third_party/heimdal/tests/kdc/check-referral.in2
-rw-r--r--third_party/heimdal/tests/kdc/check-tester.in3
-rw-r--r--third_party/heimdal/tests/kdc/check-uu.in2
-rw-r--r--third_party/heimdal/tests/kdc/krb5-kcm.conf.in165
-rw-r--r--third_party/heimdal/tests/kdc/krb5.conf.in3
-rw-r--r--third_party/heimdal/tests/ldap/check-ldap.in2
-rw-r--r--third_party/heimdal/tests/plugin/Makefile.am6
-rw-r--r--third_party/heimdal/tests/plugin/check-pac.in6
-rw-r--r--third_party/heimdal/tests/plugin/kdc_test_plugin.c207
-rw-r--r--third_party/heimdal/tests/plugin/krb5.conf.in15
-rw-r--r--third_party/heimdal/tests/plugin/windc.c161
-rw-r--r--third_party/heimdal/windows/NTMakefile.sdk130
-rw-r--r--third_party/heimdal/windows/NTMakefile.w327
428 files changed, 14519 insertions, 7392 deletions
diff --git a/third_party/heimdal/.github/workflows/build.yml b/third_party/heimdal/.github/workflows/build.yml
deleted file mode 100644
index c9d4d9e7981..00000000000
--- a/third_party/heimdal/.github/workflows/build.yml
+++ /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
-
diff --git a/third_party/heimdal/.gitignore b/third_party/heimdal/.gitignore
index 2a09f94ac80..e5b52468af5 100644
--- a/third_party/heimdal/.gitignore
+++ b/third_party/heimdal/.gitignore
@@ -15,20 +15,17 @@
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
diff --git a/third_party/heimdal/Makefile.am b/third_party/heimdal/Makefile.am
index 7fb69fdf4e0..b9bdcf4995e 100644
--- a/third_party/heimdal/Makefile.am
+++ b/third_party/heimdal/Makefile.am
@@ -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 \
diff --git a/third_party/heimdal/README.md b/third_party/heimdal/README.md
index bf9fca2a7be..5e49fd0e1a4 100644
--- a/third_party/heimdal/README.md
+++ b/third_party/heimdal/README.md
@@ -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)
diff --git a/third_party/heimdal/admin/change.c b/third_party/heimdal/admin/change.c
index a46d484c18f..b9d0e830d38 100644
--- a/third_party/heimdal/admin/change.c
+++ b/third_party/heimdal/admin/change.c
@@ -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;
diff --git a/third_party/heimdal/appl/afsutil/afslog.c b/third_party/heimdal/appl/afsutil/afslog.c
index f2ade9425ea..05078ee8e1f 100644
--- a/third_party/heimdal/appl/afsutil/afslog.c
+++ b/third_party/heimdal/appl/afsutil/afslog.c
@@ -118,7 +118,7 @@ expand_cell_name(const char *cell)
if(c)
return c;
}
- return cell;
+ return NULL;
}
static void
diff --git a/third_party/heimdal/appl/gssmask/gssmask.c b/third_party/heimdal/appl/gssmask/gssmask.c
index 35c548979a6..44b59fe5eb9 100644
--- a/third_party/heimdal/appl/gssmask/gssmask.c
+++ b/third_party/heimdal/appl/gssmask/gssmask.c
@@ -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);
diff --git a/third_party/heimdal/appl/kf/kf.c b/third_party/heimdal/appl/kf/kf.c
index ecef93965ac..fd4f174988e 100644
--- a/third_party/heimdal/appl/kf/kf.c
+++ b/third_party/heimdal/appl/kf/kf.c
@@ -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);
diff --git a/third_party/heimdal/appl/otp/otp.c b/third_party/heimdal/appl/otp/otp.c
index 1ca6a1f61bb..deb7d303c66 100644
--- a/third_party/heimdal/appl/otp/otp.c
+++ b/third_party/heimdal/appl/otp/otp.c
@@ -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);
}
diff --git a/third_party/heimdal/appl/test/gssapi_server.c b/third_party/heimdal/appl/test/gssapi_server.c
index 5d2a39dd7c4..baf13ecff5f 100644
--- a/third_party/heimdal/appl/test/gssapi_server.c
+++ b/third_party/heimdal/appl/test/gssapi_server.c
@@ -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);
}
diff --git a/third_party/heimdal/appl/test/uu_server.c b/third_party/heimdal/appl/test/uu_server.c
index 64a2b1279fa..6e046990b16 100644
--- a/third_party/heimdal/appl/test/uu_server.c
+++ b/third_party/heimdal/appl/test/uu_server.c
@@ -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);
diff --git a/third_party/heimdal/appveyor.yml b/third_party/heimdal/appveyor.yml
index bb1e12123e5..fa56c4c59a6 100644
--- a/third_party/heimdal/appveyor.yml
+++ b/third_party/heimdal/appveyor.yml
@@ -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
diff --git a/third_party/heimdal/cf/Makefile.am.common b/third_party/heimdal/cf/Makefile.am.common
index 1b134f5b77f..90921fe46b9 100644
--- a/third_party/heimdal/cf/Makefile.am.common
+++ b/third_party/heimdal/cf/Makefile.am.common
@@ -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
index 00000000000..bc2c3f034ce
--- /dev/null
+++ b/third_party/heimdal/cf/ax_check_sign.m4
@@ -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
index 00000000000..bd753b34d7d
--- /dev/null
+++ b/third_party/heimdal/cf/check-compile-flag.m4
@@ -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
diff --git a/third_party/heimdal/cf/db.m4 b/third_party/heimdal/cf/db.m4
index cf5e3a88c99..c0b4510b629 100644
--- a/third_party/heimdal/cf/db.m4
+++ b/third_party/heimdal/cf/db.m4
@@ -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
diff --git a/third_party/heimdal/cf/krb-prog-yacc.m4 b/third_party/heimdal/cf/krb-prog-yacc.m4
index 380412ec7a0..4c0afd9b7c3 100644
--- a/third_party/heimdal/cf/krb-prog-yacc.m4
+++ b/third_party/heimdal/cf/krb-prog-yacc.m4
@@ -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
])
diff --git a/third_party/heimdal/cf/roken-frag.m4 b/third_party/heimdal/cf/roken-frag.m4
index 1dfcb1860b5..2c2ef834e7a 100644
--- a/third_party/heimdal/cf/roken-frag.m4
+++ b/third_party/heimdal/cf/roken-frag.m4
@@ -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])
diff --git a/third_party/heimdal/configure.ac b/third_party/heimdal/configure.ac
index 37a2275c283..8c0b746ba5c 100644
--- a/third_party/heimdal/configure.ac
+++ b/third_party/heimdal/configure.ac
@@ -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],,,[
diff --git a/third_party/heimdal/import-lorikeet.sh b/third_party/heimdal/import-lorikeet.sh
index 6d36ced6c3f..45a5888f721 100755
--- a/third_party/heimdal/import-lorikeet.sh
+++ b/third_party/heimdal/import-lorikeet.sh
@@ -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 "!!!!!!!!!"
diff --git a/third_party/heimdal/include/Makefile.am b/third_party/heimdal/include/Makefile.am
index 16dd2250c20..43ebe706947 100644
--- a/third_party/heimdal/include/Makefile.am
+++ b/third_party/heimdal/include/Makefile.am
@@ -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 \
diff --git a/third_party/heimdal/include/bits.c b/third_party/heimdal/include/bits.c
index 326b67b7cc9..6abdb15c911 100644
--- a/third_party/heimdal/include/bits.c
+++ b/third_party/heimdal/include/bits.c
@@ -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
diff --git a/third_party/heimdal/include/config.h.w32 b/third_party/heimdal/include/config.h.w32
index 2d03bf26420..5521181d27c 100644
--- a/third_party/heimdal/include/config.h.w32
+++ b/third_party/heimdal/include/config.h.w32
@@ -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
diff --git a/third_party/heimdal/kadmin/add-random-users.c b/third_party/heimdal/kadmin/add-random-users.c
index b3d6d581d9b..e2dc303b8dc 100644
--- a/third_party/heimdal/kadmin/add-random-users.c
+++ b/third_party/heimdal/kadmin/add-random-users.c
@@ -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) {
diff --git a/third_party/heimdal/kadmin/add_enctype.c b/third_party/heimdal/kadmin/add_enctype.c
index 0ababf4f197..d128ab7f49e 100644
--- a/third_party/heimdal/kadmin/add_enctype.c
+++ b/third_party/heimdal/kadmin/add_enctype.c
@@ -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:
diff --git a/third_party/heimdal/kadmin/ank.c b/third_party/heimdal/kadmin/ank.c
index 1e5cd6117dc..4b89ca6eedd 100644
--- a/third_party/heimdal/kadmin/ank.c
+++ b/third_party/heimdal/kadmin/ank.c
@@ -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;
}
diff --git a/third_party/heimdal/kadmin/cpw.c b/third_party/heimdal/kadmin/cpw.c
index d254add4482..2f3c1c1bcd7 100644
--- a/third_party/heimdal/kadmin/cpw.c
+++ b/third_party/heimdal/kadmin/cpw.c
@@ -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;
}
diff --git a/third_party/heimdal/kadmin/del.c b/third_party/heimdal/kadmin/del.c
index 089ee8b0d80..a066f56ea38 100644
--- a/third_party/heimdal/kadmin/del.c
+++ b/third_party/heimdal/kadmin/del.c
@@ -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;
}
diff --git a/third_party/heimdal/kadmin/ext.c b/third_party/heimdal/kadmin/ext.c
index 01725d96e20..adb2e28518a 100644
--- a/third_party/heimdal/kadmin/ext.c
+++ b/third_party/heimdal/kadmin/ext.c
@@ -148,7 +148,7 @@ do_ext_keytab(krb5_principal principal, void *data)
}
free(unparsed);
free(keys);
- return 0;
+ return ret;
}
int
diff --git a/third_party/heimdal/kadmin/get.c b/third_party/heimdal/kadmin/get.c
index 35766aa1bfc..a884e11e96b 100644
--- a/third_party/heimdal/kadmin/get.c
+++ b/third_party/heimdal/kadmin/get.c
@@ -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;
diff --git a/third_party/heimdal/kadmin/init.c b/third_party/heimdal/kadmin/init.c
index 8b025e112f8..8a3725e3c49 100644
--- a/third_party/heimdal/kadmin/init.c
+++ b/third_party/heimdal/kadmin/init.c
@@ -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);
}
diff --git a/third_party/heimdal/kadmin/kadm_conn.c b/third_party/heimdal/kadmin/kadm_conn.c
index 0817b7c93aa..0eeaf508da8 100644
--- a/third_party/heimdal/kadmin/kadm_conn.c
+++ b/third_party/heimdal/kadmin/kadm_conn.c
@@ -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);
diff --git a/third_party/heimdal/kadmin/kadmin.1 b/third_party/heimdal/kadmin/kadmin.1
index 401b6a9f6ba..b0e852931c6 100644
--- a/third_party/heimdal/kadmin/kadmin.1
+++ b/third_party/heimdal/kadmin/kadmin.1
@@ -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
diff --git a/third_party/heimdal/kadmin/kadmind.c b/third_party/heimdal/kadmin/kadmind.c
index 10bbea84057..444950623f0 100644
--- a/third_party/heimdal/kadmin/kadmind.c
+++ b/third_party/heimdal/kadmin/kadmind.c
@@ -134,6 +134,8 @@ main(int argc, char **argv)
argc -= optidx;
argv += optidx;
+ if (argc != 0)
+ usage(1);
if (config_file == NULL) {
int aret;
diff --git a/third_party/heimdal/kadmin/load.c b/third_party/heimdal/kadmin/load.c
index 971c24793c0..f62f8b96dcc 100644
--- a/third_party/heimdal/kadmin/load.c
+++ b/third_party/heimdal/kadmin/load.c
@@ -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;
diff --git a/third_party/heimdal/kadmin/mod.c b/third_party/heimdal/kadmin/mod.c
index 9541c6efcb4..7c7b2dd7ce4 100644
--- a/third_party/heimdal/kadmin/mod.c
+++ b/third_party/heimdal/kadmin/mod.c
@@ -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;
}
diff --git a/third_party/heimdal/kadmin/rpc.c b/third_party/heimdal/kadmin/rpc.c
index 6ddb9dfa865..1ae10f1af7c 100644
--- a/third_party/heimdal/kadmin/rpc.c
+++ b/third_party/heimdal/kadmin/rpc.c
@@ -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;
diff --git a/third_party/heimdal/kadmin/server.c b/third_party/heimdal/kadmin/server.c
index cbe16948c06..52f20202e7f 100644
--- a/third_party/heimdal/kadmin/server.c
+++ b/third_party/heimdal/kadmin/server.c
@@ -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
diff --git a/third_party/heimdal/kadmin/stash.c b/third_party/heimdal/kadmin/stash.c
index 785de43f872..c33623038ce 100644
--- a/third_party/heimdal/kadmin/stash.c
+++ b/third_party/heimdal/kadmin/stash.c
@@ -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);
}
diff --git a/third_party/heimdal/kcm/cache.c b/third_party/heimdal/kcm/cache.c
index 02624dfd1c8..b11812769b6 100644
--- a/third_party/heimdal/kcm/cache.c
+++ b/third_party/heimdal/kcm/cache.c
@@ -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;
diff --git a/third_party/heimdal/kcm/client.c b/third_party/heimdal/kcm/client.c
index 09c94b6e8dd..061d4e97267 100644
--- a/third_party/heimdal/kcm/client.c
+++ b/third_party/heimdal/kcm/client.c
@@ -47,6 +47,43 @@ kcm_ccache_resolve_client(krb5_context context,
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);
krb5_free_error_message(context, estr);
diff --git a/third_party/heimdal/kcm/glue.c b/third_party/heimdal/kcm/glue.c
index 713af7f8650..0895f48f051 100644
--- a/third_party/heimdal/kcm/glue.c
+++ b/third_party/heimdal/kcm/glue.c
@@ -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;
}
diff --git a/third_party/heimdal/kcm/protocol.c b/third_party/heimdal/kcm/protocol.c
index c36bbe9c6c6..31f17623d01 100644
--- a/third_party/heimdal/kcm/protocol.c
+++ b/third_party/heimdal/kcm/protocol.c
@@ -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;
}
diff --git a/third_party/heimdal/kdc/Makefile.am b/third_party/heimdal/kdc/Makefile.am
index 54382a842bf..c7f57251f7c 100644
--- a/third_party/heimdal/kdc/Makefile.am
+++ b/third_party/heimdal/kdc/Makefile.am
@@ -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
diff --git a/third_party/heimdal/kdc/NTMakefile b/third_party/heimdal/kdc/NTMakefile
index 58eb7577141..aca65b104ae 100644
--- a/third_party/heimdal/kdc/NTMakefile
+++ b/third_party/heimdal/kdc/NTMakefile
@@ -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)
diff --git a/third_party/heimdal/kdc/altsecid_gss_preauth_authorizer.c b/third_party/heimdal/kdc/altsecid_gss_preauth_authorizer.c
index 961ced0db9a..d48ea584bc8 100644
--- a/third_party/heimdal/kdc/altsecid_gss_preauth_authorizer.c
+++ b/third_party/heimdal/kdc/altsecid_gss_preauth_authorizer.c
@@ -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;
}
diff --git a/third_party/heimdal/kdc/bx509d.c b/third_party/heimdal/kdc/bx509d.c
index 2f30744bf31..064c424b7c2 100644
--- a/third_party/heimdal/kdc/bx509d.c
+++ b/third_party/heimdal/kdc/bx509d.c
@@ -112,6 +112,22 @@
#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");
diff --git a/third_party/heimdal/kdc/ca.c b/third_party/heimdal/kdc/ca.c
index 0d92ca7fc89..4402c44677f 100644
--- a/third_party/heimdal/kdc/ca.c
+++ b/third_party/heimdal/kdc/ca.c
@@ -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;
}
diff --git a/third_party/heimdal/kdc/cjwt_token_validator.c b/third_party/heimdal/kdc/cjwt_token_validator.c
index 68fe01594f8..93742e5ddd5 100644
--- a/third_party/heimdal/kdc/cjwt_token_validator.c
+++ b/third_party/heimdal/kdc/cjwt_token_validator.c
@@ -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");
diff --git a/third_party/heimdal/kdc/config.c b/third_party/heimdal/kdc/config.c
index 507cb195af3..e217b9dadfa 100644
--- a/third_party/heimdal/kdc/config.c
+++ b/third_party/heimdal/kdc/config.c
@@ -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);
diff --git a/third_party/heimdal/kdc/connect.c b/third_party/heimdal/kdc/connect.c
index 975f24cb269..ba8c8ad7ba5 100644
--- a/third_party/heimdal/kdc/connect.c
+++ b/third_party/heimdal/kdc/connect.c
@@ -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
diff --git a/third_party/heimdal/kdc/csr_authorizer.c b/third_party/heimdal/kdc/csr_authorizer.c
index fa20519d73a..52bc37c4296 100644
--- a/third_party/heimdal/kdc/csr_authorizer.c
+++ b/third_party/heimdal/kdc/csr_authorizer.c
@@ -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,
diff --git a/third_party/heimdal/kdc/default_config.c b/third_party/heimdal/kdc/default_config.c
index 627dc74f458..01f8f7b54a6 100644
--- a/third_party/heimdal/kdc/default_config.c
+++ b/third_party/heimdal/kdc/default_config.c
@@ -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
diff --git a/third_party/heimdal/kdc/digest-service.c b/third_party/heimdal/kdc/digest-service.c
index 3a4f4c551db..4ea76dbe7e2 100644
--- a/third_party/heimdal/kdc/digest-service.c
+++ b/third_party/heimdal/kdc/digest-service.c
@@ -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;
diff --git a/third_party/heimdal/kdc/digest.c b/third_party/heimdal/kdc/digest.c
index a8652891f53..092b4a75a4b 100644
--- a/third_party/heimdal/kdc/digest.c
+++ b/third_party/heimdal/kdc/digest.c
@@ -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);
diff --git a/third_party/heimdal/kdc/fast.c b/third_party/heimdal/kdc/fast.c
index d4cd650284b..25cab3096b7 100644
--- a/third_party/heimdal/kdc/fast.c
+++ b/third_party/heimdal/kdc/fast.c
@@ -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);
diff --git a/third_party/heimdal/kdc/gss_preauth.c b/third_party/heimdal/kdc/gss_preauth.c
index ce62a29afcc..d8a2a24fd94 100644
--- a/third_party/heimdal/kdc/gss_preauth.c
+++ b/third_party/heimdal/kdc/gss_preauth.c
@@ -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;
diff --git a/third_party/heimdal/kdc/gss_preauth_authorizer_plugin.h b/third_party/heimdal/kdc/gss_preauth_authorizer_plugin.h
index 69bd5fc1ae5..293e59da47b 100644
--- a/third_party/heimdal/kdc/gss_preauth_authorizer_plugin.h
+++ b/third_party/heimdal/kdc/gss_preauth_authorizer_plugin.h
@@ -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 */
diff --git a/third_party/heimdal/kdc/headers.h b/third_party/heimdal/kdc/headers.h
index 6f4d56ae95c..ffe49c8bdfd 100644
--- a/third_party/heimdal/kdc/headers.h
+++ b/third_party/heimdal/kdc/headers.h
@@ -104,7 +104,8 @@
#include <heimntlm.h>
#endif
#include <kdc.h>
-#include <windc_plugin.h>
+#include <kdc-plugin.h>
+#include <kdc-audit.h>
#include <heimbase.h>
diff --git a/third_party/heimdal/kdc/hprop.8 b/third_party/heimdal/kdc/hprop.8
index 2746e1d8fcc..acf66bcd614 100644
--- a/third_party/heimdal/kdc/hprop.8
+++ b/third_party/heimdal/kdc/hprop.8
@@ -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
diff --git a/third_party/heimdal/kdc/hprop.c b/third_party/heimdal/kdc/hprop.c
index 880a6f74640..c1db11b978e 100644
--- a/third_party/heimdal/kdc/hprop.c
+++ b/third_party/heimdal/kdc/hprop.c
@@ -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;
diff --git a/third_party/heimdal/kdc/hprop.h b/third_party/heimdal/kdc/hprop.h
index 426bf6ed7fd..59c39ea4784 100644
--- a/third_party/heimdal/kdc/hprop.h
+++ b/third_party/heimdal/kdc/hprop.h
@@ -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__ */
diff --git a/third_party/heimdal/kdc/hpropd.8 b/third_party/heimdal/kdc/hpropd.8
index 31b44e28a59..9056b05a8d2 100644
--- a/third_party/heimdal/kdc/hpropd.8
+++ b/third_party/heimdal/kdc/hpropd.8
@@ -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
diff --git a/third_party/heimdal/kdc/hpropd.c b/third_party/heimdal/kdc/hpropd.c
index fd9df08e8d7..fa06a1fd401 100644
--- a/third_party/heimdal/kdc/hpropd.c
+++ b/third_party/heimdal/kdc/hpropd.c
@@ -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);
diff --git a/third_party/heimdal/kdc/httpkadmind.c b/third_party/heimdal/kdc/httpkadmind.c
index 3dfb365186a..0e31b4044c3 100644
--- a/third_party/heimdal/kdc/httpkadmind.c
+++ b/third_party/heimdal/kdc/httpkadmind.c
@@ -80,6 +80,20 @@
#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");
diff --git a/third_party/heimdal/kdc/ipc_csr_authorizer.c b/third_party/heimdal/kdc/ipc_csr_authorizer.c
index fad3919a2a6..7d77e7f812a 100644
--- a/third_party/heimdal/kdc/ipc_csr_authorizer.c
+++ b/third_party/heimdal/kdc/ipc_csr_authorizer.c
@@ -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
index 00000000000..81c03d2f222
--- /dev/null
+++ b/third_party/heimdal/kdc/kdc-accessors.h
@@ -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 */
diff --git a/third_party/heimdal/kdc/rx.h b/third_party/heimdal/kdc/kdc-audit.h
index f914e93e6ef..4b2203f2267 100644
--- a/third_party/heimdal/kdc/rx.h
+++ b/third_party/heimdal/kdc/kdc-audit.h
@@ -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.
*
@@ -33,47 +33,35 @@
/* $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
index 00000000000..8759893a956
--- /dev/null
+++ b/third_party/heimdal/kdc/kdc-plugin.c
@@ -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
index 00000000000..efe8dd6abe0
--- /dev/null
+++ b/third_party/heimdal/kdc/kdc-plugin.h
@@ -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 */
diff --git a/third_party/heimdal/kdc/kdc-replay.c b/third_party/heimdal/kdc/kdc-replay.c
index af4e55c356d..29190f7837f 100644
--- a/third_party/heimdal/kdc/kdc-replay.c
+++ b/third_party/heimdal/kdc/kdc-replay.c
@@ -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);
diff --git a/third_party/heimdal/kdc/kdc.h b/third_party/heimdal/kdc/kdc.h
index cbf4f511738..e3709ada6b0 100644
--- a/third_party/heimdal/kdc/kdc.h
+++ b/third_party/heimdal/kdc/kdc.h
@@ -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>
@@ -46,120 +46,27 @@
#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__ */
diff --git a/third_party/heimdal/kdc/kdc_locl.h b/third_party/heimdal/kdc/kdc_locl.h
index e7b86151def..8418a91a0a4 100644
--- a/third_party/heimdal/kdc/kdc_locl.h
+++ b/third_party/heimdal/kdc/kdc_locl.h
@@ -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__ */
diff --git a/third_party/heimdal/kdc/kerberos5.c b/third_party/heimdal/kdc/kerberos5.c
index ee7e56c5f27..b30d321f6f1 100644
--- a/third_party/heimdal/kdc/kerberos5.c
+++ b/third_party/heimdal/kdc/kerberos5.c
@@ -33,44 +33,26 @@
#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) {
@@ -1316,92 +1284,57 @@ _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,
METHOD_DATA *md, Key *ckey,
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);
diff --git a/third_party/heimdal/kdc/krb5tgs.c b/third_party/heimdal/kdc/krb5tgs.c
index c9878dd6af5..39d42106e01 100644
--- a/third_party/heimdal/kdc/krb5tgs.c
+++ b/third_party/heimdal/kdc/krb5tgs.c
@@ -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;
}
@@ -343,63 +344,6 @@ check_tgs_flags(astgs_request_t r, KDC_REQ_BODY *b,
}
/*
- * 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
*
* also:
@@ -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,24 +1580,12 @@ 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
* have been an incoming trust)
@@ -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);
diff --git a/third_party/heimdal/kdc/kstash.c b/third_party/heimdal/kdc/kstash.c
index bba2b11d0f0..6ec1a548aca 100644
--- a/third_party/heimdal/kdc/kstash.c
+++ b/third_party/heimdal/kdc/kstash.c
@@ -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);
diff --git a/third_party/heimdal/kdc/kx509.c b/third_party/heimdal/kdc/kx509.c
index bc3ca9deca6..6efd94e3a12 100644
--- a/third_party/heimdal/kdc/kx509.c
+++ b/third_party/heimdal/kdc/kx509.c
@@ -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)
diff --git a/third_party/heimdal/kdc/libkdc-exports.def b/third_party/heimdal/kdc/libkdc-exports.def
index a4ed75bfb6a..3cc929e6025 100644
--- a/third_party/heimdal/kdc/libkdc-exports.def
+++ b/third_party/heimdal/kdc/libkdc-exports.def
@@ -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
diff --git a/third_party/heimdal/kdc/log.c b/third_party/heimdal/kdc/log.c
index 895f1c9c6e4..bfb0f54ff89 100644
--- a/third_party/heimdal/kdc/log.c
+++ b/third_party/heimdal/kdc/log.c
@@ -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, ...)
diff --git a/third_party/heimdal/kdc/misc.c b/third_party/heimdal/kdc/misc.c
index e6a5c5c2340..b48503d26a0 100644
--- a/third_party/heimdal/kdc/misc.c
+++ b/third_party/heimdal/kdc/misc.c
@@ -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;
+}
diff --git a/third_party/heimdal/kdc/mit_dump.c b/third_party/heimdal/kdc/mit_dump.c
index 3e4b47d7e1b..32cf5dc65ce 100644
--- a/third_party/heimdal/kdc/mit_dump.c
+++ b/third_party/heimdal/kdc/mit_dump.c
@@ -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
index 00000000000..9e67aad3319
--- /dev/null
+++ b/third_party/heimdal/kdc/mssfu.c
@@ -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;
+}
diff --git a/third_party/heimdal/kdc/negotiate_token_validator.c b/third_party/heimdal/kdc/negotiate_token_validator.c
index ad5db1e3ca4..20250c6dc89 100644
--- a/third_party/heimdal/kdc/negotiate_token_validator.c
+++ b/third_party/heimdal/kdc/negotiate_token_validator.c
@@ -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;
}
diff --git a/third_party/heimdal/kdc/pkinit.c b/third_party/heimdal/kdc/pkinit.c
index b355e4c8830..f01178983f3 100644
--- a/third_party/heimdal/kdc/pkinit.c
+++ b/third_party/heimdal/kdc/pkinit.c
@@ -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,
diff --git a/third_party/heimdal/kdc/process.c b/third_party/heimdal/kdc/process.c
index 23a0fe0102d..cf8ab060ec9 100644
--- a/third_party/heimdal/kdc/process.c
+++ b/third_party/heimdal/kdc/process.c
@@ -42,15 +42,15 @@
#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);
}
diff --git a/third_party/heimdal/kdc/set_dbinfo.c b/third_party/heimdal/kdc/set_dbinfo.c
index 93ded4ec2ae..683eaaf7be4 100644
--- a/third_party/heimdal/kdc/set_dbinfo.c
+++ b/third_party/heimdal/kdc/set_dbinfo.c
@@ -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;
diff --git a/third_party/heimdal/kdc/simple_csr_authorizer.c b/third_party/heimdal/kdc/simple_csr_authorizer.c
index 1ae9efd676c..2300eb53299 100644
--- a/third_party/heimdal/kdc/simple_csr_authorizer.c
+++ b/third_party/heimdal/kdc/simple_csr_authorizer.c
@@ -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);
diff --git a/third_party/heimdal/kdc/string2key.c b/third_party/heimdal/kdc/string2key.c
index 1b603dece58..4b9c62e5a5d 100644
--- a/third_party/heimdal/kdc/string2key.c
+++ b/third_party/heimdal/kdc/string2key.c
@@ -128,9 +128,9 @@ main(int argc, char **argv)
if(ret)
krb5_err(context, 1, ret, "krb5_string_to_enctype");
- if((etype != (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;
diff --git a/third_party/heimdal/kdc/test_kdc_ca.c b/third_party/heimdal/kdc/test_kdc_ca.c
index 12b873c039b..4d80c96a034 100644
--- a/third_party/heimdal/kdc/test_kdc_ca.c
+++ b/third_party/heimdal/kdc/test_kdc_ca.c
@@ -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");
diff --git a/third_party/heimdal/kdc/token_validator.c b/third_party/heimdal/kdc/token_validator.c
index cdb50e47752..858fdfa7b21 100644
--- a/third_party/heimdal/kdc/token_validator.c
+++ b/third_party/heimdal/kdc/token_validator.c
@@ -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,
diff --git a/third_party/heimdal/kdc/version-script.map b/third_party/heimdal/kdc/version-script.map
index 4b27e6943cc..9067bb6e43f 100644
--- a/third_party/heimdal/kdc/version-script.map
+++ b/third_party/heimdal/kdc/version-script.map
@@ -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
index eb834cd6cfd..00000000000
--- a/third_party/heimdal/kdc/windc.c
+++ /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
index ae0c6d181ea..00000000000
--- a/third_party/heimdal/kdc/windc_plugin.h
+++ /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 */
diff --git a/third_party/heimdal/kpasswd/kpasswdd.c b/third_party/heimdal/kpasswd/kpasswdd.c
index 344688e296e..e04eebe46e1 100644
--- a/third_party/heimdal/kpasswd/kpasswdd.c
+++ b/third_party/heimdal/kpasswd/kpasswdd.c
@@ -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;
}
diff --git a/third_party/heimdal/kuser/generate-requests.c b/third_party/heimdal/kuser/generate-requests.c
index 1196c16dc67..2dd71bf7ab8 100644
--- a/third_party/heimdal/kuser/generate-requests.c
+++ b/third_party/heimdal/kuser/generate-requests.c
@@ -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);
}
diff --git a/third_party/heimdal/kuser/kgetcred.c b/third_party/heimdal/kuser/kgetcred.c
index 92eb770990c..4982f8a796a 100644
--- a/third_party/heimdal/kuser/kgetcred.c
+++ b/third_party/heimdal/kuser/kgetcred.c
@@ -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);
diff --git a/third_party/heimdal/kuser/kimpersonate.c b/third_party/heimdal/kuser/kimpersonate.c
index 04a16fb6ade..35b4295fb36 100644
--- a/third_party/heimdal/kuser/kimpersonate.c
+++ b/third_party/heimdal/kuser/kimpersonate.c
@@ -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;
}
diff --git a/third_party/heimdal/kuser/kinit.c b/third_party/heimdal/kuser/kinit.c
index 0b22e715095..6ac4b45426a 100644
--- a/third_party/heimdal/kuser/kinit.c
+++ b/third_party/heimdal/kuser/kinit.c
@@ -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];
diff --git a/third_party/heimdal/kuser/klist.c b/third_party/heimdal/kuser/klist.c
index 5dbabcaad85..b33c3c28a7a 100644
--- a/third_party/heimdal/kuser/klist.c
+++ b/third_party/heimdal/kuser/klist.c
@@ -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, "");
diff --git a/third_party/heimdal/kuser/kswitch.c b/third_party/heimdal/kuser/kswitch.c
index d897a8e7451..3bb3b700dbd 100644
--- a/third_party/heimdal/kuser/kswitch.c
+++ b/third_party/heimdal/kuser/kswitch.c
@@ -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));
diff --git a/third_party/heimdal/kuser/kuser_locl.h b/third_party/heimdal/kuser/kuser_locl.h
index 8218a6f096f..b1a097a8d6f 100644
--- a/third_party/heimdal/kuser/kuser_locl.h
+++ b/third_party/heimdal/kuser/kuser_locl.h
@@ -97,11 +97,15 @@
#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
index 00000000000..89c452a031c
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/MANUAL.md
@@ -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.
diff --git a/third_party/heimdal/lib/asn1/Makefile.am b/third_party/heimdal/lib/asn1/Makefile.am
index 94d24fc47eb..eb0308ee13c 100644
--- a/third_party/heimdal/lib/asn1/Makefile.am
+++ b/third_party/heimdal/lib/asn1/Makefile.am
@@ -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
diff --git a/third_party/heimdal/lib/asn1/NTMakefile b/third_party/heimdal/lib/asn1/NTMakefile
index eca92bd3853..19255c6cf71 100644
--- a/third_party/heimdal/lib/asn1/NTMakefile
+++ b/third_party/heimdal/lib/asn1/NTMakefile
@@ -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
@@ -31,42 +31,10 @@
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)
diff --git a/third_party/heimdal/lib/asn1/README.md b/third_party/heimdal/lib/asn1/README.md
index a00dde72227..9c4e6979569 100644
--- a/third_party/heimdal/lib/asn1/README.md
+++ b/third_party/heimdal/lib/asn1/README.md
@@ -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
diff --git a/third_party/heimdal/lib/asn1/asn1-template.h b/third_party/heimdal/lib/asn1/asn1-template.h
index e75734ea26c..07c4461e3e9 100644
--- a/third_party/heimdal/lib/asn1/asn1-template.h
+++ b/third_party/heimdal/lib/asn1/asn1-template.h
@@ -42,43 +42,16 @@
* 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:
@@ -155,21 +128,23 @@
* 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)
diff --git a/third_party/heimdal/lib/asn1/asn1_compile.1 b/third_party/heimdal/lib/asn1/asn1_compile.1
index 74cf314f16e..a7953df5fa1 100644
--- a/third_party/heimdal/lib/asn1/asn1_compile.1
+++ b/third_party/heimdal/lib/asn1/asn1_compile.1
@@ -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
@@ -61,7 +61,117 @@
.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.
diff --git a/third_party/heimdal/lib/asn1/asn1_print.c b/third_party/heimdal/lib/asn1/asn1_print.c
index 39c43341aa6..40c37fbbb94 100644
--- a/third_party/heimdal/lib/asn1/asn1_print.c
+++ b/third_party/heimdal/lib/asn1/asn1_print.c
@@ -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);
diff --git a/third_party/heimdal/lib/asn1/asn1parse.y b/third_party/heimdal/lib/asn1/asn1parse.y
index 290cb86310e..f6f6ec0e5c4 100644
--- a/third_party/heimdal/lib/asn1/asn1parse.y
+++ b/third_party/heimdal/lib/asn1/asn1parse.y
@@ -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);
diff --git a/third_party/heimdal/lib/asn1/check-common.h b/third_party/heimdal/lib/asn1/check-common.h
index 97d11899739..6ea1f812651 100644
--- a/third_party/heimdal/lib/asn1/check-common.h
+++ b/third_party/heimdal/lib/asn1/check-common.h
@@ -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) \
diff --git a/third_party/heimdal/lib/asn1/check-der.c b/third_party/heimdal/lib/asn1/check-der.c
index 15fd2bcff92..a8956a74bd2 100644
--- a/third_party/heimdal/lib/asn1/check-der.c
+++ b/third_party/heimdal/lib/asn1/check-der.c
@@ -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;
}
diff --git a/third_party/heimdal/lib/asn1/check-gen.c b/third_party/heimdal/lib/asn1/check-gen.c
index f49f5e8edf9..6b5c71c39f5 100644
--- a/third_party/heimdal/lib/asn1/check-gen.c
+++ b/third_party/heimdal/lib/asn1/check-gen.c
@@ -51,6 +51,24 @@
#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
index 00000000000..df8c4747b6b
--- /dev/null
+++ b/third_party/heimdal/lib/asn1/check-gen.h
@@ -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 */
diff --git a/third_party/heimdal/lib/asn1/check-template.c b/third_party/heimdal/lib/asn1/check-template.c
index 21132c8d1a4..ef5bd6990de 100644
--- a/third_party/heimdal/lib/asn1/check-template.c
+++ b/third_party/heimdal/lib/asn1/check-template.c
@@ -48,6 +48,19 @@
#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)
{
diff --git a/third_party/heimdal/lib/asn1/der_copy.c b/third_party/heimdal/lib/asn1/der_copy.c
index 854131e2ab4..2084cef5f08 100644
--- a/third_party/heimdal/lib/asn1/der_copy.c
+++ b/third_party/heimdal/lib/asn1/der_copy.c
@@ -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;
}
diff --git a/third_party/heimdal/lib/asn1/der_get.c b/third_party/heimdal/lib/asn1/der_get.c
index 55ba6262359..c12f8170025 100644
--- a/third_party/heimdal/lib/asn1/der_get.c
+++ b/third_party/heimdal/lib/asn1/der_get.c
@@ -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 {
diff --git a/third_party/heimdal/lib/asn1/der_put.c b/third_party/heimdal/lib/asn1/der_put.c
index 5f40fba1615..8fbd6f3da1c 100644
--- a/third_party/heimdal/lib/asn1/der_put.c
+++ b/third_party/heimdal/lib/asn1/der_put.c
@@ -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)
diff --git a/third_party/heimdal/lib/asn1/extra.c b/third_party/heimdal/lib/asn1/extra.c
index 5a494d23aca..253ac5aca6f 100644
--- a/third_party/heimdal/lib/asn1/extra.c
+++ b/third_party/heimdal/lib/asn1/extra.c
@@ -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;
}
diff --git a/third_party/heimdal/lib/asn1/gen.c b/third_party/heimdal/lib/asn1/gen.c
index 8e323188fff..10153c60379 100644
--- a/third_party/heimdal/lib/asn1/gen.c
+++ b/third_party/heimdal/lib/asn1/gen.c
@@ -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);
diff --git a/third_party/heimdal/lib/asn1/gen_copy.c b/third_party/heimdal/lib/asn1/gen_copy.c
index 243aa2b0cca..bec6f8b059f 100644
--- a/third_party/heimdal/lib/asn1/gen_copy.c
+++ b/third_party/heimdal/lib/asn1/gen_copy.c
@@ -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");
diff --git a/third_party/heimdal/lib/asn1/gen_decode.c b/third_party/heimdal/lib/asn1/gen_decode.c
index 739f9d85f70..93d412f6335 100644
--- a/third_party/heimdal/lib/asn1/gen_decode.c
+++ b/third_party/heimdal/lib/asn1/gen_decode.c
@@ -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");
diff --git a/third_party/heimdal/lib/asn1/gen_encode.c b/third_party/heimdal/lib/asn1/gen_encode.c
index b0123a8be17..d61dc2e6d50 100644
--- a/third_party/heimdal/lib/asn1/gen_encode.c
+++ b/third_party/heimdal/lib/asn1/gen_encode.c
@@ -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"
diff --git a/third_party/heimdal/lib/asn1/gen_free.c b/third_party/heimdal/lib/asn1/gen_free.c
index 6c9424cbf35..0507d542180 100644
--- a/third_party/heimdal/lib/asn1/gen_free.c
+++ b/third_party/heimdal/lib/asn1/gen_free.c
@@ -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");
}
diff --git a/third_party/heimdal/lib/asn1/gen_glue.c b/third_party/heimdal/lib/asn1/gen_glue.c
index 24f16528c63..424e5de5d5e 100644
--- a/third_party/heimdal/lib/asn1/gen_glue.c
+++ b/third_party/heimdal/lib/asn1/gen_glue.c
@@ -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);
diff --git a/third_party/heimdal/lib/asn1/gen_locl.h b/third_party/heimdal/lib/asn1/gen_locl.h
index ccef2acd231..f37f1490320 100644
--- a/third_party/heimdal/lib/asn1/gen_locl.h
+++ b/third_party/heimdal/lib/asn1/gen_locl.h
@@ -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);
diff --git a/third_party/heimdal/lib/asn1/gen_template.c b/third_party/heimdal/lib/asn1/gen_template.c
index af1e44ee68b..883eab4b671 100644
--- a/third_party/heimdal/lib/asn1/gen_template.c
+++ b/third_party/heimdal/lib/asn1/gen_template.c
@@ -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,
diff --git a/third_party/heimdal/lib/asn1/krb5.asn1 b/third_party/heimdal/lib/asn1/krb5.asn1
index baaec52f5f8..639ec5af2d2 100644
--- a/third_party/heimdal/lib/asn1/krb5.asn1
+++ b/third_party/heimdal/lib/asn1/krb5.asn1
@@ -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
diff --git a/third_party/heimdal/lib/asn1/krb5.opt b/third_party/heimdal/lib/asn1/krb5.opt
index 5acc596d39c..a8bd85c522f 100644
--- a/third_party/heimdal/lib/asn1/krb5.opt
+++ b/third_party/heimdal/lib/asn1/krb5.opt
@@ -5,3 +5,5 @@
--sequence=ETYPE-INFO
--sequence=ETYPE-INFO2
--preserve-binary=KDC-REQ-BODY
+--decorate=PrincipalNameAttrs:void *:pac
+--decorate=Principal:PrincipalNameAttrs:nameattrs?
diff --git a/third_party/heimdal/lib/asn1/libasn1-exports.def b/third_party/heimdal/lib/asn1/libasn1-exports.def
index ade5e2d0bfd..15d3a37beba 100644
--- a/third_party/heimdal/lib/asn1/libasn1-exports.def
+++ b/third_party/heimdal/lib/asn1/libasn1-exports.def
@@ -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
diff --git a/third_party/heimdal/lib/asn1/main.c b/third_party/heimdal/lib/asn1/main.c
index 64db63ab2ec..bcfdad62e2e 100644
--- a/third_party/heimdal/lib/asn1/main.c
+++ b/third_party/heimdal/lib/asn1/main.c
@@ -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++)
diff --git a/third_party/heimdal/lib/asn1/oid_resolution.c b/third_party/heimdal/lib/asn1/oid_resolution.c
index 63155efbd07..db11b114282 100644
--- a/third_party/heimdal/lib/asn1/oid_resolution.c
+++ b/third_party/heimdal/lib/asn1/oid_resolution.c
@@ -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 = '-';
diff --git a/third_party/heimdal/lib/asn1/symbol.h b/third_party/heimdal/lib/asn1/symbol.h
index b88386223b3..8a24e251565 100644
--- a/third_party/heimdal/lib/asn1/symbol.h
+++ b/third_party/heimdal/lib/asn1/symbol.h
@@ -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;
};
diff --git a/third_party/heimdal/lib/asn1/template.c b/third_party/heimdal/lib/asn1/template.c
index 7f5670f3456..7a19e7477e3 100644
--- a/third_party/heimdal/lib/asn1/template.c
+++ b/third_party/heimdal/lib/asn1/template.c
@@ -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) {
diff --git a/third_party/heimdal/lib/asn1/test.asn1 b/third_party/heimdal/lib/asn1/test.asn1
index a76152712d9..08c7dcd93ee 100644
--- a/third_party/heimdal/lib/asn1/test.asn1
+++ b/third_party/heimdal/lib/asn1/test.asn1
@@ -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
diff --git a/third_party/heimdal/lib/asn1/test.opt b/third_party/heimdal/lib/asn1/test.opt
index 500ee4ec811..755eba01bfb 100644
--- a/third_party/heimdal/lib/asn1/test.opt
+++ b/third_party/heimdal/lib/asn1/test.opt
@@ -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
diff --git a/third_party/heimdal/lib/base/array.c b/third_party/heimdal/lib/base/array.c
index b34f9de4880..994fa7d38e4 100644
--- a/third_party/heimdal/lib/base/array.c
+++ b/third_party/heimdal/lib/base/array.c
@@ -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,
diff --git a/third_party/heimdal/lib/base/bsearch.c b/third_party/heimdal/lib/base/bsearch.c
index 27896217268..268cc018df6 100644
--- a/third_party/heimdal/lib/base/bsearch.c
+++ b/third_party/heimdal/lib/base/bsearch.c
@@ -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));
diff --git a/third_party/heimdal/lib/base/data.c b/third_party/heimdal/lib/base/data.c
index 4aa6efc6677..cefdde0c1bb 100644
--- a/third_party/heimdal/lib/base/data.c
+++ b/third_party/heimdal/lib/base/data.c
@@ -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 = {
diff --git a/third_party/heimdal/lib/base/db.c b/third_party/heimdal/lib/base/db.c
index cd750386acc..b206ff6d766 100644
--- a/third_party/heimdal/lib/base/db.c
+++ b/third_party/heimdal/lib/base/db.c
@@ -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();
diff --git a/third_party/heimdal/lib/base/dict.c b/third_party/heimdal/lib/base/dict.c
index 8d73846b2bb..86be109ffc5 100644
--- a/third_party/heimdal/lib/base/dict.c
+++ b/third_party/heimdal/lib/base/dict.c
@@ -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)
diff --git a/third_party/heimdal/lib/base/dll.c b/third_party/heimdal/lib/base/dll.c
index 31017a01191..59c39137b72 100644
--- a/third_party/heimdal/lib/base/dll.c
+++ b/third_party/heimdal/lib/base/dll.c
@@ -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)
diff --git a/third_party/heimdal/lib/base/error.c b/third_party/heimdal/lib/base/error.c
index 8ae65de4981..6ba3bea412d 100644
--- a/third_party/heimdal/lib/base/error.c
+++ b/third_party/heimdal/lib/base/error.c
@@ -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;
diff --git a/third_party/heimdal/lib/base/error_string.c b/third_party/heimdal/lib/base/error_string.c
index 5c787ba2ce5..a562833a91a 100644
--- a/third_party/heimdal/lib/base/error_string.c
+++ b/third_party/heimdal/lib/base/error_string.c
@@ -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
diff --git a/third_party/heimdal/lib/base/expand_path.c b/third_party/heimdal/lib/base/expand_path.c
index df382b99887..cf249917e8f 100644
--- a/third_party/heimdal/lib/base/expand_path.c
+++ b/third_party/heimdal/lib/base/expand_path.c
@@ -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;
}
diff --git a/third_party/heimdal/lib/base/heimbase-svc.h b/third_party/heimdal/lib/base/heimbase-svc.h
index 1f0abd622e5..083917fb806 100644
--- a/third_party/heimdal/lib/base/heimbase-svc.h
+++ b/third_party/heimdal/lib/base/heimbase-svc.h
@@ -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 */
diff --git a/third_party/heimdal/lib/base/heimbase.c b/third_party/heimdal/lib/base/heimbase.c
index 8aacdb9187d..1e6805a25e7 100644
--- a/third_party/heimdal/lib/base/heimbase.c
+++ b/third_party/heimdal/lib/base/heimbase.c
@@ -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;
}
diff --git a/third_party/heimdal/lib/base/heimbase.h b/third_party/heimdal/lib/base/heimbase.h
index c0c94e2649b..3706fc8710d 100644
--- a/third_party/heimdal/lib/base/heimbase.h
+++ b/third_party/heimdal/lib/base/heimbase.h
@@ -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);
/*
*
diff --git a/third_party/heimdal/lib/base/heimbasepriv.h b/third_party/heimdal/lib/base/heimbasepriv.h
index 8f8fad0fc8c..b9f63e56b6a 100644
--- a/third_party/heimdal/lib/base/heimbasepriv.h
+++ b/third_party/heimdal/lib/base/heimbasepriv.h
@@ -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
};
diff --git a/third_party/heimdal/lib/base/log.c b/third_party/heimdal/lib/base/log.c
index 904d0c3ba12..818ac8398d5 100644
--- a/third_party/heimdal/lib/base/log.c
+++ b/third_party/heimdal/lib/base/log.c
@@ -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
@@ -809,18 +853,196 @@ heim_audit_addkv_timediff(heim_svc_req_desc r, const char *k,
}
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) : "");
}
diff --git a/third_party/heimdal/lib/base/number.c b/third_party/heimdal/lib/base/number.c
index c259f69971d..8833c8b1523 100644
--- a/third_party/heimdal/lib/base/number.c
+++ b/third_party/heimdal/lib/base/number.c
@@ -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;
}
diff --git a/third_party/heimdal/lib/base/plugin.c b/third_party/heimdal/lib/base/plugin.c
index df225a939c2..631a3386c83 100644
--- a/third_party/heimdal/lib/base/plugin.c
+++ b/third_party/heimdal/lib/base/plugin.c
@@ -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 */
diff --git a/third_party/heimdal/lib/base/string.c b/third_party/heimdal/lib/base/string.c
index 5384998080a..f942447163d 100644
--- a/third_party/heimdal/lib/base/string.c
+++ b/third_party/heimdal/lib/base/string.c
@@ -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;
diff --git a/third_party/heimdal/lib/base/test_base.c b/third_party/heimdal/lib/base/test_base.c
index fba675cf488..be6c860e26b 100644
--- a/third_party/heimdal/lib/base/test_base.c
+++ b/third_party/heimdal/lib/base/test_base.c
@@ -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;
diff --git a/third_party/heimdal/lib/base/version-script.map b/third_party/heimdal/lib/base/version-script.map
index 0cd0c8444cb..928e8619995 100644
--- a/third_party/heimdal/lib/base/version-script.map
+++ b/third_party/heimdal/lib/base/version-script.map
@@ -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;
diff --git a/third_party/heimdal/lib/com_err/Makefile.am b/third_party/heimdal/lib/com_err/Makefile.am
index 8c027c74da9..14e8e66fcdc 100644
--- a/third_party/heimdal/lib/com_err/Makefile.am
+++ b/third_party/heimdal/lib/com_err/Makefile.am
@@ -2,7 +2,7 @@
include $(top_srcdir)/Makefile.am.common
-YFLAGS = -d
+YFLAGS = -d -o parse.c
LFLAGS = @FLEXNOUNPUTARGS@
lib_LTLIBRARIES = libcom_err.la
diff --git a/third_party/heimdal/lib/gss_preauth/pa_client.c b/third_party/heimdal/lib/gss_preauth/pa_client.c
index 1159e63c2a4..de2d7b5cbe6 100644
--- a/third_party/heimdal/lib/gss_preauth/pa_client.c
+++ b/third_party/heimdal/lib/gss_preauth/pa_client.c
@@ -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)
diff --git a/third_party/heimdal/lib/gss_preauth/pa_common.c b/third_party/heimdal/lib/gss_preauth/pa_common.c
index c2287ca707a..00efde72d66 100644
--- a/third_party/heimdal/lib/gss_preauth/pa_common.c
+++ b/third_party/heimdal/lib/gss_preauth/pa_common.c
@@ -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;
diff --git a/third_party/heimdal/lib/gssapi/Makefile.am b/third_party/heimdal/lib/gssapi/Makefile.am
index 744232e2e35..a69ebffb04e 100644
--- a/third_party/heimdal/lib/gssapi/Makefile.am
+++ b/third_party/heimdal/lib/gssapi/Makefile.am
@@ -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
-
diff --git a/third_party/heimdal/lib/gssapi/NTMakefile b/third_party/heimdal/lib/gssapi/NTMakefile
index 8d5784f17f1..ffba9d52be0 100644
--- a/third_party/heimdal/lib/gssapi/NTMakefile
+++ b/third_party/heimdal/lib/gssapi/NTMakefile
@@ -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)
diff --git a/third_party/heimdal/lib/gssapi/gss-token.c b/third_party/heimdal/lib/gssapi/gss-token.c
index 1ead3e15b32..844fa4d3820 100644
--- a/third_party/heimdal/lib/gssapi/gss-token.c
+++ b/third_party/heimdal/lib/gssapi/gss-token.c
@@ -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);
diff --git a/third_party/heimdal/lib/gssapi/gssapi/gssapi.h b/third_party/heimdal/lib/gssapi/gssapi/gssapi.h
index 4214acc0e5f..726543f5a38 100644
--- a/third_party/heimdal/lib/gssapi/gssapi/gssapi.h
+++ b/third_party/heimdal/lib/gssapi/gssapi/gssapi.h
@@ -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.
*/
diff --git a/third_party/heimdal/lib/gssapi/gssapi/gssapi_krb5.h b/third_party/heimdal/lib/gssapi/gssapi/gssapi_krb5.h
index 74d5109aa19..818042fa773 100644
--- a/third_party/heimdal/lib/gssapi/gssapi/gssapi_krb5.h
+++ b/third_party/heimdal/lib/gssapi/gssapi/gssapi_krb5.h
@@ -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_ */
diff --git a/third_party/heimdal/lib/gssapi/krb5/accept_sec_context.c b/third_party/heimdal/lib/gssapi/krb5/accept_sec_context.c
index f125573c137..3f8e2740e21 100644
--- a/third_party/heimdal/lib/gssapi/krb5/accept_sec_context.c
+++ b/third_party/heimdal/lib/gssapi/krb5/accept_sec_context.c
@@ -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) {
diff --git a/third_party/heimdal/lib/gssapi/krb5/acquire_cred.c b/third_party/heimdal/lib/gssapi/krb5/acquire_cred.c
index 6b625160668..211dcaa7f75 100644
--- a/third_party/heimdal/lib/gssapi/krb5/acquire_cred.c
+++ b/third_party/heimdal/lib/gssapi/krb5/acquire_cred.c
@@ -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);
}
diff --git a/third_party/heimdal/lib/gssapi/krb5/arcfour.c b/third_party/heimdal/lib/gssapi/krb5/arcfour.c
index 9093b7a1d36..8931b32e1c9 100644
--- a/third_party/heimdal/lib/gssapi/krb5/arcfour.c
+++ b/third_party/heimdal/lib/gssapi/krb5/arcfour.c
@@ -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) {
diff --git a/third_party/heimdal/lib/gssapi/krb5/copy_ccache.c b/third_party/heimdal/lib/gssapi/krb5/copy_ccache.c
index 182421581a8..fc0b9b12872 100644
--- a/third_party/heimdal/lib/gssapi/krb5/copy_ccache.c
+++ b/third_party/heimdal/lib/gssapi/krb5/copy_ccache.c
@@ -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,
diff --git a/third_party/heimdal/lib/gssapi/krb5/export_sec_context.c b/third_party/heimdal/lib/gssapi/krb5/export_sec_context.c
index 981baed6edd..c2984153752 100644
--- a/third_party/heimdal/lib/gssapi/krb5/export_sec_context.c
+++ b/third_party/heimdal/lib/gssapi/krb5/export_sec_context.c
@@ -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;
diff --git a/third_party/heimdal/lib/gssapi/krb5/external.c b/third_party/heimdal/lib/gssapi/krb5/external.c
index 91947025cc7..e58df18c5f0 100644
--- a/third_party/heimdal/lib/gssapi/krb5/external.c
+++ b/third_party/heimdal/lib/gssapi/krb5/external.c
@@ -153,6 +153,13 @@ 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
* with the mechanism proposed by SPNEGO [7] for negotiating protocol
@@ -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,
diff --git a/third_party/heimdal/lib/gssapi/krb5/import_name.c b/third_party/heimdal/lib/gssapi/krb5/import_name.c
index 77449612d05..f4ee2313c16 100644
--- a/third_party/heimdal/lib/gssapi/krb5/import_name.c
+++ b/third_party/heimdal/lib/gssapi/krb5/import_name.c
@@ -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,
diff --git a/third_party/heimdal/lib/gssapi/krb5/init_sec_context.c b/third_party/heimdal/lib/gssapi/krb5/init_sec_context.c
index c7dfdc85166..62b26ed7eb9 100644
--- a/third_party/heimdal/lib/gssapi/krb5/init_sec_context.c
+++ b/third_party/heimdal/lib/gssapi/krb5/init_sec_context.c
@@ -33,6 +33,12 @@
#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
index 00000000000..11fc2ef969f
--- /dev/null
+++ b/third_party/heimdal/lib/gssapi/krb5/name_attrs.c
@@ -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;
+}
diff --git a/third_party/heimdal/lib/gssapi/krb5/store_cred.c b/third_party/heimdal/lib/gssapi/krb5/store_cred.c
index 311686dc13a..6d727b4e289 100644
--- a/third_party/heimdal/lib/gssapi/krb5/store_cred.c
+++ b/third_party/heimdal/lib/gssapi/krb5/store_cred.c
@@ -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
diff --git a/third_party/heimdal/lib/gssapi/krb5/test_kcred.c b/third_party/heimdal/lib/gssapi/krb5/test_kcred.c
index 3cbba243f0b..c90a1443bc6 100644
--- a/third_party/heimdal/lib/gssapi/krb5/test_kcred.c
+++ b/third_party/heimdal/lib/gssapi/krb5/test_kcred.c
@@ -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");
diff --git a/third_party/heimdal/lib/gssapi/libgssapi-exports.def b/third_party/heimdal/lib/gssapi/libgssapi-exports.def
index b8f9e75c4bc..6077c8e26f4 100644
--- a/third_party/heimdal/lib/gssapi/libgssapi-exports.def
+++ b/third_party/heimdal/lib/gssapi/libgssapi-exports.def
@@ -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
diff --git a/third_party/heimdal/lib/gssapi/mech/gss_compare_name.c b/third_party/heimdal/lib/gssapi/mech/gss_compare_name.c
index fd2523fd8e3..97ef57898da 100644
--- a/third_party/heimdal/lib/gssapi/mech/gss_compare_name.c
+++ b/third_party/heimdal/lib/gssapi/mech/gss_compare_name.c
@@ -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) ||
diff --git a/third_party/heimdal/lib/gssapi/mech/gss_cred.c b/third_party/heimdal/lib/gssapi/mech/gss_cred.c
index 3ba2dd84621..00561ce928e 100644
--- a/third_party/heimdal/lib/gssapi/mech/gss_cred.c
+++ b/third_party/heimdal/lib/gssapi/mech/gss_cred.c
@@ -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;
diff --git a/third_party/heimdal/lib/gssapi/mech/gss_export_sec_context.c b/third_party/heimdal/lib/gssapi/mech/gss_export_sec_context.c
index 05a05f508de..c0309809f74 100644
--- a/third_party/heimdal/lib/gssapi/mech/gss_export_sec_context.c
+++ b/third_party/heimdal/lib/gssapi/mech/gss_export_sec_context.c
@@ -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",
diff --git a/third_party/heimdal/lib/gssapi/mech/gss_import_name.c b/third_party/heimdal/lib/gssapi/mech/gss_import_name.c
index d7559981dc5..54930bf4645 100644
--- a/third_party/heimdal/lib/gssapi/mech/gss_import_name.c
+++ b/third_party/heimdal/lib/gssapi/mech/gss_import_name.c
@@ -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
*
@@ -198,19 +220,14 @@ 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) {
diff --git a/third_party/heimdal/lib/gssapi/mech/gss_import_sec_context.c b/third_party/heimdal/lib/gssapi/mech/gss_import_sec_context.c
index 0acae853324..39b717e3dc2 100644
--- a/third_party/heimdal/lib/gssapi/mech/gss_import_sec_context.c
+++ b/third_party/heimdal/lib/gssapi/mech/gss_import_sec_context.c
@@ -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;
diff --git a/third_party/heimdal/lib/gssapi/mech/gss_krb5.c b/third_party/heimdal/lib/gssapi/mech/gss_krb5.c
index 0f6d14209af..78c305689f0 100644
--- a/third_party/heimdal/lib/gssapi/mech/gss_krb5.c
+++ b/third_party/heimdal/lib/gssapi/mech/gss_krb5.c
@@ -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;
}
diff --git a/third_party/heimdal/lib/gssapi/mech/gss_mech_switch.c b/third_party/heimdal/lib/gssapi/mech/gss_mech_switch.c
index 60fe376a914..372e72dd5da 100644
--- a/third_party/heimdal/lib/gssapi/mech/gss_mech_switch.c
+++ b/third_party/heimdal/lib/gssapi/mech/gss_mech_switch.c
@@ -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;
-}
diff --git a/third_party/heimdal/lib/gssapi/mech/gss_pname_to_uid.c b/third_party/heimdal/lib/gssapi/mech/gss_pname_to_uid.c
index 72fd9de4624..5046faed026 100644
--- a/third_party/heimdal/lib/gssapi/mech/gss_pname_to_uid.c
+++ b/third_party/heimdal/lib/gssapi/mech/gss_pname_to_uid.c
@@ -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) {
diff --git a/third_party/heimdal/lib/gssapi/mech/mech_locl.h b/third_party/heimdal/lib/gssapi/mech/mech_locl.h
index 0d74091e054..d451b87c4a7 100644
--- a/third_party/heimdal/lib/gssapi/mech/mech_locl.h
+++ b/third_party/heimdal/lib/gssapi/mech/mech_locl.h
@@ -35,24 +35,17 @@
#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>
diff --git a/third_party/heimdal/lib/gssapi/ntlm/accept_sec_context.c b/third_party/heimdal/lib/gssapi/ntlm/accept_sec_context.c
index d6300006b21..6a3e8899ee7 100644
--- a/third_party/heimdal/lib/gssapi/ntlm/accept_sec_context.c
+++ b/third_party/heimdal/lib/gssapi/ntlm/accept_sec_context.c
@@ -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;
diff --git a/third_party/heimdal/lib/gssapi/ntlm/creds.c b/third_party/heimdal/lib/gssapi/ntlm/creds.c
index 84a710c69e6..57940156cb5 100644
--- a/third_party/heimdal/lib/gssapi/ntlm/creds.c
+++ b/third_party/heimdal/lib/gssapi/ntlm/creds.c
@@ -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)
diff --git a/third_party/heimdal/lib/gssapi/ntlm/crypto.c b/third_party/heimdal/lib/gssapi/ntlm/crypto.c
index a8c670c50b2..efa71d911dc 100644
--- a/third_party/heimdal/lib/gssapi/ntlm/crypto.c
+++ b/third_party/heimdal/lib/gssapi/ntlm/crypto.c
@@ -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);
diff --git a/third_party/heimdal/lib/gssapi/ntlm/delete_sec_context.c b/third_party/heimdal/lib/gssapi/ntlm/delete_sec_context.c
index 41c30b76f1a..57587a020db 100644
--- a/third_party/heimdal/lib/gssapi/ntlm/delete_sec_context.c
+++ b/third_party/heimdal/lib/gssapi/ntlm/delete_sec_context.c
@@ -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);
diff --git a/third_party/heimdal/lib/gssapi/ntlm/init_sec_context.c b/third_party/heimdal/lib/gssapi/ntlm/init_sec_context.c
index 1063db19b0f..be9c987c4ca 100644
--- a/third_party/heimdal/lib/gssapi/ntlm/init_sec_context.c
+++ b/third_party/heimdal/lib/gssapi/ntlm/init_sec_context.c
@@ -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;
}
}
diff --git a/third_party/heimdal/lib/gssapi/ntlm/kdc.c b/third_party/heimdal/lib/gssapi/ntlm/kdc.c
index e5c25596aa6..1bce00fc5d6 100644
--- a/third_party/heimdal/lib/gssapi/ntlm/kdc.c
+++ b/third_party/heimdal/lib/gssapi/ntlm/kdc.c
@@ -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.
diff --git a/third_party/heimdal/lib/gssapi/sanon/import_name.c b/third_party/heimdal/lib/gssapi/sanon/import_name.c
index 189308d96ea..1a228b69e1a 100644
--- a/third_party/heimdal/lib/gssapi/sanon/import_name.c
+++ b/third_party/heimdal/lib/gssapi/sanon/import_name.c
@@ -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);
diff --git a/third_party/heimdal/lib/gssapi/spnego/accept_sec_context.c b/third_party/heimdal/lib/gssapi/spnego/accept_sec_context.c
index 8cb4211da26..c4ac7455cf6 100644
--- a/third_party/heimdal/lib/gssapi/spnego/accept_sec_context.c
+++ b/third_party/heimdal/lib/gssapi/spnego/accept_sec_context.c
@@ -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,
diff --git a/third_party/heimdal/lib/gssapi/spnego/negoex_ctx.c b/third_party/heimdal/lib/gssapi/spnego/negoex_ctx.c
index 13e28bb59fd..3f8aa5c3e7b 100644
--- a/third_party/heimdal/lib/gssapi/spnego/negoex_ctx.c
+++ b/third_party/heimdal/lib/gssapi/spnego/negoex_ctx.c
@@ -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);
diff --git a/third_party/heimdal/lib/gssapi/test_context.c b/third_party/heimdal/lib/gssapi/test_context.c
index 30fb5cb231f..7446d15e0df 100644
--- a/third_party/heimdal/lib/gssapi/test_context.c
+++ b/third_party/heimdal/lib/gssapi/test_context.c
@@ -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;
@@ -135,6 +136,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,
gss_cred_id_t init_cred,
@@ -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);
}
diff --git a/third_party/heimdal/lib/gssapi/test_kcred.c b/third_party/heimdal/lib/gssapi/test_kcred.c
index 866ee78ecf1..abfe390449d 100644
--- a/third_party/heimdal/lib/gssapi/test_kcred.c
+++ b/third_party/heimdal/lib/gssapi/test_kcred.c
@@ -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);
diff --git a/third_party/heimdal/lib/gssapi/test_names.c b/third_party/heimdal/lib/gssapi/test_names.c
index e195313505c..933635e78c0 100644
--- a/third_party/heimdal/lib/gssapi/test_names.c
+++ b/third_party/heimdal/lib/gssapi/test_names.c
@@ -43,42 +43,286 @@
#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);
+}
diff --git a/third_party/heimdal/lib/gssapi/version-script.map b/third_party/heimdal/lib/gssapi/version-script.map
index be266da773c..7f482b53624 100644
--- a/third_party/heimdal/lib/gssapi/version-script.map
+++ b/third_party/heimdal/lib/gssapi/version-script.map
@@ -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;
diff --git a/third_party/heimdal/lib/hcrypto/Makefile.am b/third_party/heimdal/lib/hcrypto/Makefile.am
index 1c610829feb..bb36f745190 100644
--- a/third_party/heimdal/lib/hcrypto/Makefile.am
+++ b/third_party/heimdal/lib/hcrypto/Makefile.am
@@ -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 \
diff --git a/third_party/heimdal/lib/hcrypto/bn.c b/third_party/heimdal/lib/hcrypto/bn.c
index 15bf78738ad..62297b145f1 100644
--- a/third_party/heimdal/lib/hcrypto/bn.c
+++ b/third_party/heimdal/lib/hcrypto/bn.c
@@ -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;
diff --git a/third_party/heimdal/lib/hcrypto/des.c b/third_party/heimdal/lib/hcrypto/des.c
index 9f5c648ec94..ac174180fb9 100644
--- a/third_party/heimdal/lib/hcrypto/des.c
+++ b/third_party/heimdal/lib/hcrypto/des.c
@@ -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);
diff --git a/third_party/heimdal/lib/hcrypto/dh-ltm.c b/third_party/heimdal/lib/hcrypto/dh-ltm.c
index 774f0e1176a..720662199f9 100644
--- a/third_party/heimdal/lib/hcrypto/dh-ltm.c
+++ b/third_party/heimdal/lib/hcrypto/dh-ltm.c
@@ -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);
diff --git a/third_party/heimdal/lib/hcrypto/dh.c b/third_party/heimdal/lib/hcrypto/dh.c
index 0447c4f4838..5d2d214f752 100644
--- a/third_party/heimdal/lib/hcrypto/dh.c
+++ b/third_party/heimdal/lib/hcrypto/dh.c
@@ -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;
}
diff --git a/third_party/heimdal/lib/hcrypto/engine.c b/third_party/heimdal/lib/hcrypto/engine.c
index 9cea2482176..3dae960fd0c 100644
--- a/third_party/heimdal/lib/hcrypto/engine.c
+++ b/third_party/heimdal/lib/hcrypto/engine.c
@@ -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;
}
diff --git a/third_party/heimdal/lib/hcrypto/evp.c b/third_party/heimdal/lib/hcrypto/evp.c
index 23838709c8e..9cced4c536c 100644
--- a/third_party/heimdal/lib/hcrypto/evp.c
+++ b/third_party/heimdal/lib/hcrypto/evp.c
@@ -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;
}
/**
diff --git a/third_party/heimdal/lib/hcrypto/hmac.c b/third_party/heimdal/lib/hcrypto/hmac.c
index 6cdf4e97a4e..6b387ae90dc 100644
--- a/third_party/heimdal/lib/hcrypto/hmac.c
+++ b/third_party/heimdal/lib/hcrypto/hmac.c
@@ -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);
diff --git a/third_party/heimdal/lib/hcrypto/hmac.h b/third_party/heimdal/lib/hcrypto/hmac.h
index 2c7d9b8803a..cc99c879fb9 100644
--- a/third_party/heimdal/lib/hcrypto/hmac.h
+++ b/third_party/heimdal/lib/hcrypto/hmac.h
@@ -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);
diff --git a/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_set_double.c b/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_set_double.c
index a42fc70d908..6f91b64f503 100644
--- a/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_set_double.c
+++ b/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_set_double.c
@@ -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;
diff --git a/third_party/heimdal/lib/hcrypto/libtommath/bn_s_mp_rand_platform.c b/third_party/heimdal/lib/hcrypto/libtommath/bn_s_mp_rand_platform.c
index 55c69390eef..79879c35039 100644
--- a/third_party/heimdal/lib/hcrypto/libtommath/bn_s_mp_rand_platform.c
+++ b/third_party/heimdal/lib/hcrypto/libtommath/bn_s_mp_rand_platform.c
@@ -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;
diff --git a/third_party/heimdal/lib/hcrypto/libtommath/demo/test.c b/third_party/heimdal/lib/hcrypto/libtommath/demo/test.c
index 7b29a4ce948..9049fa81f91 100644
--- a/third_party/heimdal/lib/hcrypto/libtommath/demo/test.c
+++ b/third_party/heimdal/lib/hcrypto/libtommath/demo/test.c
@@ -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;
diff --git a/third_party/heimdal/lib/hcrypto/libtommath/etc/tune.c b/third_party/heimdal/lib/hcrypto/libtommath/etc/tune.c
index bc2cdfe6e03..e7b99fce289 100644
--- a/third_party/heimdal/lib/hcrypto/libtommath/etc/tune.c
+++ b/third_party/heimdal/lib/hcrypto/libtommath/etc/tune.c
@@ -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]);
}
diff --git a/third_party/heimdal/lib/hcrypto/rsa-ltm.c b/third_party/heimdal/lib/hcrypto/rsa-ltm.c
index 2852bd4d6b8..1d5b73e60e5 100644
--- a/third_party/heimdal/lib/hcrypto/rsa-ltm.c
+++ b/third_party/heimdal/lib/hcrypto/rsa-ltm.c
@@ -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));
diff --git a/third_party/heimdal/lib/hcrypto/rsa.c b/third_party/heimdal/lib/hcrypto/rsa.c
index c99b2b6cbe9..6172b25413f 100644
--- a/third_party/heimdal/lib/hcrypto/rsa.c
+++ b/third_party/heimdal/lib/hcrypto/rsa.c
@@ -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;
diff --git a/third_party/heimdal/lib/hcrypto/test_hmac.c b/third_party/heimdal/lib/hcrypto/test_hmac.c
index 063a461cc16..36a5626a708 100644
--- a/third_party/heimdal/lib/hcrypto/test_hmac.c
+++ b/third_party/heimdal/lib/hcrypto/test_hmac.c
@@ -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);
diff --git a/third_party/heimdal/lib/hcrypto/validate.c b/third_party/heimdal/lib/hcrypto/validate.c
index 562e5aa4dd0..4b655f262c8 100644
--- a/third_party/heimdal/lib/hcrypto/validate.c
+++ b/third_party/heimdal/lib/hcrypto/validate.c
@@ -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);
diff --git a/third_party/heimdal/lib/hdb/Makefile.am b/third_party/heimdal/lib/hdb/Makefile.am
index 342aaffbe96..89ab15d9d3e 100644
--- a/third_party/heimdal/lib/hdb/Makefile.am
+++ b/third_party/heimdal/lib/hdb/Makefile.am
@@ -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
diff --git a/third_party/heimdal/lib/hdb/NTMakefile b/third_party/heimdal/lib/hdb/NTMakefile
index 5ad9d9c5742..f4801f7c54e 100644
--- a/third_party/heimdal/lib/hdb/NTMakefile
+++ b/third_party/heimdal/lib/hdb/NTMakefile
@@ -31,17 +31,15 @@
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
diff --git a/third_party/heimdal/lib/hdb/common.c b/third_party/heimdal/lib/hdb/common.c
index 251eb9b7714..a92cc1372db 100644
--- a/third_party/heimdal/lib/hdb/common.c
+++ b/third_party/heimdal/lib/hdb/common.c
@@ -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;
}
diff --git a/third_party/heimdal/lib/hdb/db.c b/third_party/heimdal/lib/hdb/db.c
index 6e415b95f16..5fcce7b8e8b 100644
--- a/third_party/heimdal/lib/hdb/db.c
+++ b/third_party/heimdal/lib/hdb/db.c
@@ -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);
}
diff --git a/third_party/heimdal/lib/hdb/db3.c b/third_party/heimdal/lib/hdb/db3.c
index 0daa25bbec4..9d0c0a97d9a 100644
--- a/third_party/heimdal/lib/hdb/db3.c
+++ b/third_party/heimdal/lib/hdb/db3.c
@@ -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);
}
diff --git a/third_party/heimdal/lib/hdb/ext.c b/third_party/heimdal/lib/hdb/ext.c
index ec52d35dcba..48683ef1607 100644
--- a/third_party/heimdal/lib/hdb/ext.c
+++ b/third_party/heimdal/lib/hdb/ext.c
@@ -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;
diff --git a/third_party/heimdal/lib/hdb/hdb-keytab.c b/third_party/heimdal/lib/hdb/hdb-keytab.c
index f3cb8fbe61d..c9b469cb1a8 100644
--- a/third_party/heimdal/lib/hdb/hdb-keytab.c
+++ b/third_party/heimdal/lib/hdb/hdb-keytab.c
@@ -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;
}
diff --git a/third_party/heimdal/lib/hdb/hdb-ldap.c b/third_party/heimdal/lib/hdb/hdb-ldap.c
index 1dbb00d3e5f..6a2876c51d7 100644
--- a/third_party/heimdal/lib/hdb/hdb-ldap.c
+++ b/third_party/heimdal/lib/hdb/hdb-ldap.c
@@ -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;
diff --git a/third_party/heimdal/lib/hdb/hdb-mdb.c b/third_party/heimdal/lib/hdb/hdb-mdb.c
index cabda277f4e..6aa5201eb8a 100644
--- a/third_party/heimdal/lib/hdb/hdb-mdb.c
+++ b/third_party/heimdal/lib/hdb/hdb-mdb.c
@@ -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);
}
diff --git a/third_party/heimdal/lib/hdb/hdb-mitdb.c b/third_party/heimdal/lib/hdb/hdb-mitdb.c
index 1ae013157c2..7436f39edbb 100644
--- a/third_party/heimdal/lib/hdb/hdb-mitdb.c
+++ b/third_party/heimdal/lib/hdb/hdb-mitdb.c
@@ -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;
diff --git a/third_party/heimdal/lib/hdb/hdb-sqlite.c b/third_party/heimdal/lib/hdb/hdb-sqlite.c
index 3cab9178965..4bb2f8e8553 100644
--- a/third_party/heimdal/lib/hdb/hdb-sqlite.c
+++ b/third_party/heimdal/lib/hdb/hdb-sqlite.c
@@ -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);
diff --git a/third_party/heimdal/lib/hdb/hdb.asn1 b/third_party/heimdal/lib/hdb/hdb.asn1
index f6490783a6c..9eb96be73d0 100644
--- a/third_party/heimdal/lib/hdb/hdb.asn1
+++ b/third_party/heimdal/lib/hdb/hdb.asn1
@@ -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
diff --git a/third_party/heimdal/lib/hdb/hdb.c b/third_party/heimdal/lib/hdb/hdb.c
index 3978048ad17..56c403842e6 100644
--- a/third_party/heimdal/lib/hdb/hdb.c
+++ b/third_party/heimdal/lib/hdb/hdb.c
@@ -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);
diff --git a/third_party/heimdal/lib/hdb/hdb.h b/third_party/heimdal/lib/hdb/hdb.h
index 97ca70c0a7e..0f2c92151e5 100644
--- a/third_party/heimdal/lib/hdb/hdb.h
+++ b/third_party/heimdal/lib/hdb/hdb.h
@@ -42,8 +42,12 @@
#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
@@ -164,20 +106,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
*
* The HDB structure is what the KDC and kadmind framework uses to
@@ -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
index 00000000000..626f8c7b07a
--- /dev/null
+++ b/third_party/heimdal/lib/hdb/hdb.opt
@@ -0,0 +1,5 @@
+--sequence=HDB-extensions
+--sequence=HDB-Ext-KeyRotation
+--sequence=HDB-Ext-KeySet
+--sequence=Keys
+--decorate=HDB_entry:void:context?:::
diff --git a/third_party/heimdal/lib/hdb/keys.c b/third_party/heimdal/lib/hdb/keys.c
index ae0b067f79b..457e5daf7a7 100644
--- a/third_party/heimdal/lib/hdb/keys.c
+++ b/third_party/heimdal/lib/hdb/keys.c
@@ -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));
diff --git a/third_party/heimdal/lib/hdb/keytab.c b/third_party/heimdal/lib/hdb/keytab.c
index 83cc851d91f..b1aa0207c97 100644
--- a/third_party/heimdal/lib/hdb/keytab.c
+++ b/third_party/heimdal/lib/hdb/keytab.c
@@ -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);
diff --git a/third_party/heimdal/lib/hdb/libhdb-exports.def b/third_party/heimdal/lib/hdb/libhdb-exports.def
index a124f93f645..72a7fb7aaad 100644
--- a/third_party/heimdal/lib/hdb/libhdb-exports.def
+++ b/third_party/heimdal/lib/hdb/libhdb-exports.def
@@ -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
diff --git a/third_party/heimdal/lib/hdb/ndbm.c b/third_party/heimdal/lib/hdb/ndbm.c
index 4e3a340fe55..52c52c890dc 100644
--- a/third_party/heimdal/lib/hdb/ndbm.c
+++ b/third_party/heimdal/lib/hdb/ndbm.c
@@ -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);
diff --git a/third_party/heimdal/lib/hdb/print.c b/third_party/heimdal/lib/hdb/print.c
index 0d1e2855217..7f253588189 100644
--- a/third_party/heimdal/lib/hdb/print.c
+++ b/third_party/heimdal/lib/hdb/print.c
@@ -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");
diff --git a/third_party/heimdal/lib/hdb/test_concurrency.c b/third_party/heimdal/lib/hdb/test_concurrency.c
index 9c95e6390f4..35c01f59f59 100644
--- a/third_party/heimdal/lib/hdb/test_concurrency.c
+++ b/third_party/heimdal/lib/hdb/test_concurrency.c
@@ -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);
diff --git a/third_party/heimdal/lib/hdb/test_namespace.c b/third_party/heimdal/lib/hdb/test_namespace.c
index 6aaecc083ec..a4c44ba190e 100644
--- a/third_party/heimdal/lib/hdb/test_namespace.c
+++ b/third_party/heimdal/lib/hdb/test_namespace.c
@@ -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;
diff --git a/third_party/heimdal/lib/hdb/version-script.map b/third_party/heimdal/lib/hdb/version-script.map
index 0846f733743..058060dae0c 100644
--- a/third_party/heimdal/lib/hdb/version-script.map
+++ b/third_party/heimdal/lib/hdb/version-script.map
@@ -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;
diff --git a/third_party/heimdal/lib/hx509/Makefile.am b/third_party/heimdal/lib/hx509/Makefile.am
index e32da3b93c3..214dabf0e83 100644
--- a/third_party/heimdal/lib/hx509/Makefile.am
+++ b/third_party/heimdal/lib/hx509/Makefile.am
@@ -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
diff --git a/third_party/heimdal/lib/hx509/ca.c b/third_party/heimdal/lib/hx509/ca.c
index 807621c21d1..3d62b93fa57 100644
--- a/third_party/heimdal/lib/hx509/ca.c
+++ b/third_party/heimdal/lib/hx509/ca.c
@@ -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) {
diff --git a/third_party/heimdal/lib/hx509/cert.c b/third_party/heimdal/lib/hx509/cert.c
index 0d99a748fc6..33805b8ed1a 100644
--- a/third_party/heimdal/lib/hx509/cert.c
+++ b/third_party/heimdal/lib/hx509/cert.c
@@ -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;
diff --git a/third_party/heimdal/lib/hx509/cms.c b/third_party/heimdal/lib/hx509/cms.c
index 453762bd10f..d2728a38c2f 100644
--- a/third_party/heimdal/lib/hx509/cms.c
+++ b/third_party/heimdal/lib/hx509/cms.c
@@ -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.
diff --git a/third_party/heimdal/lib/hx509/collector.c b/third_party/heimdal/lib/hx509/collector.c
index dd6222687af..7b46809816c 100644
--- a/third_party/heimdal/lib/hx509/collector.c
+++ b/third_party/heimdal/lib/hx509/collector.c
@@ -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);
diff --git a/third_party/heimdal/lib/hx509/crypto.c b/third_party/heimdal/lib/hx509/crypto.c
index 77e721064ef..8d368ed9c4d 100644
--- a/third_party/heimdal/lib/hx509/crypto.c
+++ b/third_party/heimdal/lib/hx509/crypto.c
@@ -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;
diff --git a/third_party/heimdal/lib/hx509/error.c b/third_party/heimdal/lib/hx509/error.c
index d3ebd1bf648..aee4f79e747 100644
--- a/third_party/heimdal/lib/hx509/error.c
+++ b/third_party/heimdal/lib/hx509/error.c
@@ -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;
diff --git a/third_party/heimdal/lib/hx509/file.c b/third_party/heimdal/lib/hx509/file.c
index 1b5ca3eae71..a22f6252cfa 100644
--- a/third_party/heimdal/lib/hx509/file.c
+++ b/third_party/heimdal/lib/hx509/file.c
@@ -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;
diff --git a/third_party/heimdal/lib/hx509/hxtool.c b/third_party/heimdal/lib/hx509/hxtool.c
index 43c4713d116..1bcfdfa44e9 100644
--- a/third_party/heimdal/lib/hx509/hxtool.c
+++ b/third_party/heimdal/lib/hx509/hxtool.c
@@ -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;
}
diff --git a/third_party/heimdal/lib/hx509/keyset.c b/third_party/heimdal/lib/hx509/keyset.c
index ef346505022..f25cdf4e419 100644
--- a/third_party/heimdal/lib/hx509/keyset.c
+++ b/third_party/heimdal/lib/hx509/keyset.c
@@ -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;
}
diff --git a/third_party/heimdal/lib/hx509/ks_file.c b/third_party/heimdal/lib/hx509/ks_file.c
index b22093cd452..880668b4561 100644
--- a/third_party/heimdal/lib/hx509/ks_file.c
+++ b/third_party/heimdal/lib/hx509/ks_file.c
@@ -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
diff --git a/third_party/heimdal/lib/hx509/name.c b/third_party/heimdal/lib/hx509/name.c
index 9b6a156af6c..7d67716b953 100644
--- a/third_party/heimdal/lib/hx509/name.c
+++ b/third_party/heimdal/lib/hx509/name.c
@@ -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;
}
diff --git a/third_party/heimdal/lib/hx509/print.c b/third_party/heimdal/lib/hx509/print.c
index 544001ebc0d..3309913f357 100644
--- a/third_party/heimdal/lib/hx509/print.c
+++ b/third_party/heimdal/lib/hx509/print.c
@@ -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;
}
diff --git a/third_party/heimdal/lib/hx509/req.c b/third_party/heimdal/lib/hx509/req.c
index f0a7c218657..2b3f46d532a 100644
--- a/third_party/heimdal/lib/hx509/req.c
+++ b/third_party/heimdal/lib/hx509/req.c
@@ -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;
diff --git a/third_party/heimdal/lib/hx509/revoke.c b/third_party/heimdal/lib/hx509/revoke.c
index c2f2e00cc29..18b2f8f8f96 100644
--- a/third_party/heimdal/lib/hx509/revoke.c
+++ b/third_party/heimdal/lib/hx509/revoke.c
@@ -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");
diff --git a/third_party/heimdal/lib/hx509/sel-gram.y b/third_party/heimdal/lib/hx509/sel-gram.y
index 7e9d4f26d9c..09f641d7c05 100644
--- a/third_party/heimdal/lib/hx509/sel-gram.y
+++ b/third_party/heimdal/lib/hx509/sel-gram.y
@@ -78,6 +78,10 @@
%token <string> STRING
%token <string> IDENTIFIER
+%left '!'
+%left kw_AND
+%left kw_OR
+
%start start
%%
diff --git a/third_party/heimdal/lib/hx509/softp11.c b/third_party/heimdal/lib/hx509/softp11.c
index 0a1445ba523..75f675579c7 100644
--- a/third_party/heimdal/lib/hx509/softp11.c
+++ b/third_party/heimdal/lib/hx509/softp11.c
@@ -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++;
diff --git a/third_party/heimdal/lib/ipc/Makefile.am b/third_party/heimdal/lib/ipc/Makefile.am
index 9338b141e17..6915175618e 100644
--- a/third_party/heimdal/lib/ipc/Makefile.am
+++ b/third_party/heimdal/lib/ipc/Makefile.am
@@ -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
diff --git a/third_party/heimdal/lib/ipc/server.c b/third_party/heimdal/lib/ipc/server.c
index 839a596388a..40601b9744f 100644
--- a/third_party/heimdal/lib/ipc/server.c
+++ b/third_party/heimdal/lib/ipc/server.c
@@ -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
diff --git a/third_party/heimdal/lib/kadm5/ad.c b/third_party/heimdal/lib/kadm5/ad.c
index 0b4ee656604..58ccf32eacd 100644
--- a/third_party/heimdal/lib/kadm5/ad.c
+++ b/third_party/heimdal/lib/kadm5/ad.c
@@ -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
diff --git a/third_party/heimdal/lib/kadm5/chpass_s.c b/third_party/heimdal/lib/kadm5/chpass_s.c
index e0d63d2ef42..c89448f4882 100644
--- a/third_party/heimdal/lib/kadm5/chpass_s.c
+++ b/third_party/heimdal/lib/kadm5/chpass_s.c
@@ -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:
diff --git a/third_party/heimdal/lib/kadm5/context_s.c b/third_party/heimdal/lib/kadm5/context_s.c
index b5674f19ab6..0c154ecfef0 100644
--- a/third_party/heimdal/lib/kadm5/context_s.c
+++ b/third_party/heimdal/lib/kadm5/context_s.c
@@ -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;
}
diff --git a/third_party/heimdal/lib/kadm5/create_s.c b/third_party/heimdal/lib/kadm5/create_s.c
index 42125e28a7e..1c2ab15f30d 100644
--- a/third_party/heimdal/lib/kadm5/create_s.c
+++ b/third_party/heimdal/lib/kadm5/create_s.c
@@ -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);
}
diff --git a/third_party/heimdal/lib/kadm5/delete_s.c b/third_party/heimdal/lib/kadm5/delete_s.c
index 6942148dbb5..aa9fdb4fc0a 100644
--- a/third_party/heimdal/lib/kadm5/delete_s.c
+++ b/third_party/heimdal/lib/kadm5/delete_s.c
@@ -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:
diff --git a/third_party/heimdal/lib/kadm5/ent_setup.c b/third_party/heimdal/lib/kadm5/ent_setup.c
index 677bda6d897..24a7983b6e1 100644
--- a/third_party/heimdal/lib/kadm5/ent_setup.c
+++ b/third_party/heimdal/lib/kadm5/ent_setup.c
@@ -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) {
diff --git a/third_party/heimdal/lib/kadm5/get_princs_s.c b/third_party/heimdal/lib/kadm5/get_princs_s.c
index f7182d7ec88..27fac2bbb0b 100644
--- a/third_party/heimdal/lib/kadm5/get_princs_s.c
+++ b/third_party/heimdal/lib/kadm5/get_princs_s.c
@@ -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) {
diff --git a/third_party/heimdal/lib/kadm5/get_s.c b/third_party/heimdal/lib/kadm5/get_s.c
index 56aec67a223..0c87343d2e1 100644
--- a/third_party/heimdal/lib/kadm5/get_s.c
+++ b/third_party/heimdal/lib/kadm5/get_s.c
@@ -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);
}
diff --git a/third_party/heimdal/lib/kadm5/init_c.c b/third_party/heimdal/lib/kadm5/init_c.c
index a0a3443898a..5d585d1a295 100644
--- a/third_party/heimdal/lib/kadm5/init_c.c
+++ b/third_party/heimdal/lib/kadm5/init_c.c
@@ -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);
diff --git a/third_party/heimdal/lib/kadm5/init_s.c b/third_party/heimdal/lib/kadm5/init_s.c
index 926c23510e9..1b1d7f2ff58 100644
--- a/third_party/heimdal/lib/kadm5/init_s.c
+++ b/third_party/heimdal/lib/kadm5/init_s.c
@@ -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;
diff --git a/third_party/heimdal/lib/kadm5/iprop-log.c b/third_party/heimdal/lib/kadm5/iprop-log.c
index 9c18f832e13..a2ad51e7d08 100644
--- a/third_party/heimdal/lib/kadm5/iprop-log.c
+++ b/third_party/heimdal/lib/kadm5/iprop-log.c
@@ -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);
diff --git a/third_party/heimdal/lib/kadm5/ipropd_common.c b/third_party/heimdal/lib/kadm5/ipropd_common.c
index be0adc1b380..1decfe3333d 100644
--- a/third_party/heimdal/lib/kadm5/ipropd_common.c
+++ b/third_party/heimdal/lib/kadm5/ipropd_common.c
@@ -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);
diff --git a/third_party/heimdal/lib/kadm5/ipropd_master.c b/third_party/heimdal/lib/kadm5/ipropd_master.c
index a27d8f75a38..b3f7d8105ea 100644
--- a/third_party/heimdal/lib/kadm5/ipropd_master.c
+++ b/third_party/heimdal/lib/kadm5/ipropd_master.c
@@ -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);
}
diff --git a/third_party/heimdal/lib/kadm5/ipropd_slave.c b/third_party/heimdal/lib/kadm5/ipropd_slave.c
index cd9a6f57a3b..2b1be00ea60 100644
--- a/third_party/heimdal/lib/kadm5/ipropd_slave.c
+++ b/third_party/heimdal/lib/kadm5/ipropd_slave.c
@@ -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)
;
diff --git a/third_party/heimdal/lib/kadm5/log.c b/third_party/heimdal/lib/kadm5/log.c
index 376cecd9e40..4f66426c4ca 100644
--- a/third_party/heimdal/lib/kadm5/log.c
+++ b/third_party/heimdal/lib/kadm5/log.c
@@ -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;
}
diff --git a/third_party/heimdal/lib/kadm5/marshall.c b/third_party/heimdal/lib/kadm5/marshall.c
index c66bcd75ae6..9d24233ba6e 100644
--- a/third_party/heimdal/lib/kadm5/marshall.c
+++ b/third_party/heimdal/lib/kadm5/marshall.c
@@ -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;
diff --git a/third_party/heimdal/lib/kadm5/modify_s.c b/third_party/heimdal/lib/kadm5/modify_s.c
index cb2e1fd1dec..2159caf5517 100644
--- a/third_party/heimdal/lib/kadm5/modify_s.c
+++ b/third_party/heimdal/lib/kadm5/modify_s.c
@@ -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:
diff --git a/third_party/heimdal/lib/kadm5/prune_s.c b/third_party/heimdal/lib/kadm5/prune_s.c
index e5d77f6cfd7..96133f242a9 100644
--- a/third_party/heimdal/lib/kadm5/prune_s.c
+++ b/third_party/heimdal/lib/kadm5/prune_s.c
@@ -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:
diff --git a/third_party/heimdal/lib/kadm5/randkey_c.c b/third_party/heimdal/lib/kadm5/randkey_c.c
index ace0687613c..cb0ec86ae57 100644
--- a/third_party/heimdal/lib/kadm5/randkey_c.c
+++ b/third_party/heimdal/lib/kadm5/randkey_c.c
@@ -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)
diff --git a/third_party/heimdal/lib/kadm5/randkey_s.c b/third_party/heimdal/lib/kadm5/randkey_s.c
index 9bb83cd14a1..cb3696720f9 100644
--- a/third_party/heimdal/lib/kadm5/randkey_s.c
+++ b/third_party/heimdal/lib/kadm5/randkey_s.c
@@ -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:
diff --git a/third_party/heimdal/lib/kadm5/rename_s.c b/third_party/heimdal/lib/kadm5/rename_s.c
index 1052042af05..9143318176b 100644
--- a/third_party/heimdal/lib/kadm5/rename_s.c
+++ b/third_party/heimdal/lib/kadm5/rename_s.c
@@ -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);
diff --git a/third_party/heimdal/lib/kadm5/set_keys.c b/third_party/heimdal/lib/kadm5/set_keys.c
index 1f458258592..c30c5d82934 100644
--- a/third_party/heimdal/lib/kadm5/set_keys.c
+++ b/third_party/heimdal/lib/kadm5/set_keys.c
@@ -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;
}
diff --git a/third_party/heimdal/lib/kadm5/setkey3_s.c b/third_party/heimdal/lib/kadm5/setkey3_s.c
index 2f8eda54c09..584c194dd18 100644
--- a/third_party/heimdal/lib/kadm5/setkey3_s.c
+++ b/third_party/heimdal/lib/kadm5/setkey3_s.c
@@ -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);
diff --git a/third_party/heimdal/lib/kafs/Makefile.am b/third_party/heimdal/lib/kafs/Makefile.am
index dd23aef7665..50d4878ae6c 100644
--- a/third_party/heimdal/lib/kafs/Makefile.am
+++ b/third_party/heimdal/lib/kafs/Makefile.am
@@ -2,6 +2,8 @@
include $(top_srcdir)/Makefile.am.common
+WFLAGS += $(WFLAGS_ENUM_CONV)
+
AM_CPPFLAGS += $(AFS_EXTRA_DEFS) $(ROKEN_RENAME)
if KRB5
diff --git a/third_party/heimdal/lib/kafs/afskrb5.c b/third_party/heimdal/lib/kafs/afskrb5.c
index 6033f2958b4..0077016f624 100644
--- a/third_party/heimdal/lib/kafs/afskrb5.c
+++ b/third_party/heimdal/lib/kafs/afskrb5.c
@@ -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;
}
diff --git a/third_party/heimdal/lib/kafs/afssys.c b/third_party/heimdal/lib/kafs/afssys.c
index ae33ff18299..b400626075c 100644
--- a/third_party/heimdal/lib/kafs/afssys.c
+++ b/third_party/heimdal/lib/kafs/afssys.c
@@ -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;
diff --git a/third_party/heimdal/lib/kafs/rxkad_kdf.c b/third_party/heimdal/lib/kafs/rxkad_kdf.c
index 174fa3a6189..5af391ed99b 100644
--- a/third_party/heimdal/lib/kafs/rxkad_kdf.c
+++ b/third_party/heimdal/lib/kafs/rxkad_kdf.c
@@ -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;
diff --git a/third_party/heimdal/lib/krb5/Makefile.am b/third_party/heimdal/lib/krb5/Makefile.am
index 99171e727ce..c1345c28a5a 100644
--- a/third_party/heimdal/lib/krb5/Makefile.am
+++ b/third_party/heimdal/lib/krb5/Makefile.am
@@ -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
diff --git a/third_party/heimdal/lib/krb5/NTMakefile b/third_party/heimdal/lib/krb5/NTMakefile
index d3202513098..40ca0fb0bcc 100644
--- a/third_party/heimdal/lib/krb5/NTMakefile
+++ b/third_party/heimdal/lib/krb5/NTMakefile
@@ -31,6 +31,8 @@
RELDIR=lib\krb5
+intcflags=-I$(SRCDIR) -I$(SRCDIR)\..\com_err -I$(SRCDIR)\..\base
+
!include ../../windows/NTMakefile.w32
libkrb5_OBJS = \
diff --git a/third_party/heimdal/lib/krb5/acache.c b/third_party/heimdal/lib/krb5/acache.c
index 5bc97626324..63d56c400bf 100644
--- a/third_party/heimdal/lib/krb5/acache.c
+++ b/third_party/heimdal/lib/krb5/acache.c
@@ -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
diff --git a/third_party/heimdal/lib/krb5/acl.c b/third_party/heimdal/lib/krb5/acl.c
index b53c179b72e..d3196148287 100644
--- a/third_party/heimdal/lib/krb5/acl.c
+++ b/third_party/heimdal/lib/krb5/acl.c
@@ -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;
diff --git a/third_party/heimdal/lib/krb5/addr_families.c b/third_party/heimdal/lib/krb5/addr_families.c
index 4d235fff431..864c9cde884 100644
--- a/third_party/heimdal/lib/krb5/addr_families.c
+++ b/third_party/heimdal/lib/krb5/addr_families.c
@@ -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;
}
diff --git a/third_party/heimdal/lib/krb5/aes-test.c b/third_party/heimdal/lib/krb5/aes-test.c
index 7bca78ab606..01522dd593a 100644
--- a/third_party/heimdal/lib/krb5/aes-test.c
+++ b/third_party/heimdal/lib/krb5/aes-test.c
@@ -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;
diff --git a/third_party/heimdal/lib/krb5/asn1_glue.c b/third_party/heimdal/lib/krb5/asn1_glue.c
index 6df8defbce9..16eda2f6f73 100644
--- a/third_party/heimdal/lib/krb5/asn1_glue.c
+++ b/third_party/heimdal/lib/krb5/asn1_glue.c
@@ -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;
+}
diff --git a/third_party/heimdal/lib/krb5/auth_context.c b/third_party/heimdal/lib/krb5/auth_context.c
index 43c762b7699..8b43b63706c 100644
--- a/third_party/heimdal/lib/krb5/auth_context.c
+++ b/third_party/heimdal/lib/krb5/auth_context.c
@@ -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);
}
diff --git a/third_party/heimdal/lib/krb5/cache.c b/third_party/heimdal/lib/krb5/cache.c
index 1920796ffc3..75083f82840 100644
--- a/third_party/heimdal/lib/krb5/cache.c
+++ b/third_party/heimdal/lib/krb5/cache.c
@@ -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) {
diff --git a/third_party/heimdal/lib/krb5/context.c b/third_party/heimdal/lib/krb5/context.c
index 51faf8de99d..4040a983518 100644
--- a/third_party/heimdal/lib/krb5/context.c
+++ b/third_party/heimdal/lib/krb5/context.c
@@ -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);
diff --git a/third_party/heimdal/lib/krb5/crypto-evp.c b/third_party/heimdal/lib/krb5/crypto-evp.c
index a16b83cb0e0..a03cdca2ebc 100644
--- a/third_party/heimdal/lib/krb5/crypto-evp.c
+++ b/third_party/heimdal/lib/krb5/crypto-evp.c
@@ -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])) {
diff --git a/third_party/heimdal/lib/krb5/crypto.c b/third_party/heimdal/lib/krb5/crypto.c
index 524b2e78681..2fb4f0620f7 100644
--- a/third_party/heimdal/lib/krb5/crypto.c
+++ b/third_party/heimdal/lib/krb5/crypto.c
@@ -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)) {
diff --git a/third_party/heimdal/lib/krb5/data.c b/third_party/heimdal/lib/krb5/data.c
index eafc4520b9e..abfa0531f0e 100644
--- a/third_party/heimdal/lib/krb5/data.c
+++ b/third_party/heimdal/lib/krb5/data.c
@@ -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;
}
/**
diff --git a/third_party/heimdal/lib/krb5/dcache.c b/third_party/heimdal/lib/krb5/dcache.c
index 22183efcafb..af88aed9156 100644
--- a/third_party/heimdal/lib/krb5/dcache.c
+++ b/third_party/heimdal/lib/krb5/dcache.c
@@ -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 &&
diff --git a/third_party/heimdal/lib/krb5/deprecated.c b/third_party/heimdal/lib/krb5/deprecated.c
index bcd07e3c2d8..0efa162702c 100644
--- a/third_party/heimdal/lib/krb5/deprecated.c
+++ b/third_party/heimdal/lib/krb5/deprecated.c
@@ -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;
}
diff --git a/third_party/heimdal/lib/krb5/enomem.c b/third_party/heimdal/lib/krb5/enomem.c
index 371b07ff583..b4444e5a2cd 100644
--- a/third_party/heimdal/lib/krb5/enomem.c
+++ b/third_party/heimdal/lib/krb5/enomem.c
@@ -33,10 +33,10 @@
#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;
}
-
diff --git a/third_party/heimdal/lib/krb5/error_string.c b/third_party/heimdal/lib/krb5/error_string.c
index 0e42f51bc21..da86b375f83 100644
--- a/third_party/heimdal/lib/krb5/error_string.c
+++ b/third_party/heimdal/lib/krb5/error_string.c
@@ -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);
}
}
diff --git a/third_party/heimdal/lib/krb5/expand_path.c b/third_party/heimdal/lib/krb5/expand_path.c
index a1f4dfcfcf7..a0402350d0f 100644
--- a/third_party/heimdal/lib/krb5/expand_path.c
+++ b/third_party/heimdal/lib/krb5/expand_path.c
@@ -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);
}
/**
diff --git a/third_party/heimdal/lib/krb5/fast.c b/third_party/heimdal/lib/krb5/fast.c
index dcca7cc5eec..617446c3634 100644
--- a/third_party/heimdal/lib/krb5/fast.c
+++ b/third_party/heimdal/lib/krb5/fast.c
@@ -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))
diff --git a/third_party/heimdal/lib/krb5/fcache.c b/third_party/heimdal/lib/krb5/fcache.c
index 08d4f4217e4..30dff35893b 100644
--- a/third_party/heimdal/lib/krb5/fcache.c
+++ b/third_party/heimdal/lib/krb5/fcache.c
@@ -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;
}
/*
diff --git a/third_party/heimdal/lib/krb5/generate_subkey.c b/third_party/heimdal/lib/krb5/generate_subkey.c
index 07047461ee7..767d94cf7fe 100644
--- a/third_party/heimdal/lib/krb5/generate_subkey.c
+++ b/third_party/heimdal/lib/krb5/generate_subkey.c
@@ -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? */
diff --git a/third_party/heimdal/lib/krb5/get_cred.c b/third_party/heimdal/lib/krb5/get_cred.c
index 3072cbf5f6b..ec757797866 100644
--- a/third_party/heimdal/lib/krb5/get_cred.c
+++ b/third_party/heimdal/lib/krb5/get_cred.c
@@ -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;
}
diff --git a/third_party/heimdal/lib/krb5/get_in_tkt.c b/third_party/heimdal/lib/krb5/get_in_tkt.c
index d6a1a9345dc..c19fc699281 100644
--- a/third_party/heimdal/lib/krb5/get_in_tkt.c
+++ b/third_party/heimdal/lib/krb5/get_in_tkt.c
@@ -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));
diff --git a/third_party/heimdal/lib/krb5/init_creds_pw.c b/third_party/heimdal/lib/krb5/init_creds_pw.c
index 4ad5deba090..e42fcf10bc1 100644
--- a/third_party/heimdal/lib/krb5/init_creds_pw.c
+++ b/third_party/heimdal/lib/krb5/init_creds_pw.c
@@ -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)
diff --git a/third_party/heimdal/lib/krb5/kcm.c b/third_party/heimdal/lib/krb5/kcm.c
index 760abf5c59d..a75fc03f985 100644
--- a/third_party/heimdal/lib/krb5/kcm.c
+++ b/third_party/heimdal/lib/krb5/kcm.c
@@ -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;
diff --git a/third_party/heimdal/lib/krb5/keytab.c b/third_party/heimdal/lib/krb5/keytab.c
index 6ec14b8e171..559d640f002 100644
--- a/third_party/heimdal/lib/krb5/keytab.c
+++ b/third_party/heimdal/lib/krb5/keytab.c
@@ -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;
diff --git a/third_party/heimdal/lib/krb5/keytab_file.c b/third_party/heimdal/lib/krb5/keytab_file.c
index 595966ed387..61b5d6d29cf 100644
--- a/third_party/heimdal/lib/krb5/keytab_file.c
+++ b/third_party/heimdal/lib/krb5/keytab_file.c
@@ -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);
diff --git a/third_party/heimdal/lib/krb5/keytab_keyfile.c b/third_party/heimdal/lib/krb5/keytab_keyfile.c
index cb865a794c0..af3ac86faf0 100644
--- a/third_party/heimdal/lib/krb5/keytab_keyfile.c
+++ b/third_party/heimdal/lib/krb5/keytab_keyfile.c
@@ -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) {
diff --git a/third_party/heimdal/lib/krb5/krb5.conf.5 b/third_party/heimdal/lib/krb5/krb5.conf.5
index bac94b5f7df..1013a78d873 100644
--- a/third_party/heimdal/lib/krb5/krb5.conf.5
+++ b/third_party/heimdal/lib/krb5/krb5.conf.5
@@ -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
diff --git a/third_party/heimdal/lib/krb5/krb5.h b/third_party/heimdal/lib/krb5/krb5.h
index 3950bd30a4e..e78edcac9af 100644
--- a/third_party/heimdal/lib/krb5/krb5.h
+++ b/third_party/heimdal/lib/krb5/krb5.h
@@ -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__ */
diff --git a/third_party/heimdal/lib/krb5/krb5_locl.h b/third_party/heimdal/lib/krb5/krb5_locl.h
index 6b74653f565..7045c5bb601 100644
--- a/third_party/heimdal/lib/krb5/krb5_locl.h
+++ b/third_party/heimdal/lib/krb5/krb5_locl.h
@@ -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
diff --git a/third_party/heimdal/lib/krb5/krbhst-test.c b/third_party/heimdal/lib/krb5/krbhst-test.c
index 873734fce77..cd388ecfaaa 100644
--- a/third_party/heimdal/lib/krb5/krbhst-test.c
+++ b/third_party/heimdal/lib/krb5/krbhst-test.c
@@ -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;
diff --git a/third_party/heimdal/lib/krb5/krbhst.c b/third_party/heimdal/lib/krb5/krbhst.c
index adb8e00e6dc..3688d6ad7ce 100644
--- a/third_party/heimdal/lib/krb5/krbhst.c
+++ b/third_party/heimdal/lib/krb5/krbhst.c
@@ -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;
diff --git a/third_party/heimdal/lib/krb5/krcache.c b/third_party/heimdal/lib/krb5/krcache.c
index dbf81850ea3..9e992216153 100644
--- a/third_party/heimdal/lib/krb5/krcache.c
+++ b/third_party/heimdal/lib/krb5/krcache.c
@@ -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 */
diff --git a/third_party/heimdal/lib/krb5/kx509.c b/third_party/heimdal/lib/krb5/kx509.c
index bd5991fcbf8..7525739f66c 100644
--- a/third_party/heimdal/lib/krb5/kx509.c
+++ b/third_party/heimdal/lib/krb5/kx509.c
@@ -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);
/*
diff --git a/third_party/heimdal/lib/krb5/libkrb5-exports.def.in b/third_party/heimdal/lib/krb5/libkrb5-exports.def.in
index 245f4b1bf43..191a0c48c86 100644
--- a/third_party/heimdal/lib/krb5/libkrb5-exports.def.in
+++ b/third_party/heimdal/lib/krb5/libkrb5-exports.def.in
@@ -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
diff --git a/third_party/heimdal/lib/krb5/mcache.c b/third_party/heimdal/lib/krb5/mcache.c
index 4ccc415a261..fdd5674c3b8 100644
--- a/third_party/heimdal/lib/krb5/mcache.c
+++ b/third_party/heimdal/lib/krb5/mcache.c
@@ -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++;
diff --git a/third_party/heimdal/lib/krb5/mk_cred.c b/third_party/heimdal/lib/krb5/mk_cred.c
index 33e62e5b0d2..41e858f8058 100644
--- a/third_party/heimdal/lib/krb5/mk_cred.c
+++ b/third_party/heimdal/lib/krb5/mk_cred.c
@@ -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);
}
diff --git a/third_party/heimdal/lib/krb5/pac.c b/third_party/heimdal/lib/krb5/pac.c
index cd9a6d6d310..2bdeae8ecd1 100644
--- a/third_party/heimdal/lib/krb5/pac.c
+++ b/third_party/heimdal/lib/krb5/pac.c
@@ -32,7 +32,10 @@
*/
#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)
diff --git a/third_party/heimdal/lib/krb5/pkinit.c b/third_party/heimdal/lib/krb5/pkinit.c
index 0198400d9eb..c9a6e3e8f8b 100644
--- a/third_party/heimdal/lib/krb5/pkinit.c
+++ b/third_party/heimdal/lib/krb5/pkinit.c
@@ -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;
diff --git a/third_party/heimdal/lib/krb5/principal.c b/third_party/heimdal/lib/krb5/principal.c
index ee25f6acb59..6080e462341 100644
--- a/third_party/heimdal/lib/krb5/principal.c
+++ b/third_party/heimdal/lib/krb5/principal.c
@@ -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;
diff --git a/third_party/heimdal/lib/krb5/rd_cred.c b/third_party/heimdal/lib/krb5/rd_cred.c
index b2497397840..f8d57362310 100644
--- a/third_party/heimdal/lib/krb5/rd_cred.c
+++ b/third_party/heimdal/lib/krb5/rd_cred.c
@@ -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;
diff --git a/third_party/heimdal/lib/krb5/rd_req.c b/third_party/heimdal/lib/krb5/rd_req.c
index bd0b68b9cfb..371037c8403 100644
--- a/third_party/heimdal/lib/krb5/rd_req.c
+++ b/third_party/heimdal/lib/krb5/rd_req.c
@@ -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);
diff --git a/third_party/heimdal/lib/krb5/replay.c b/third_party/heimdal/lib/krb5/replay.c
index d9c442bb27d..2fec8afd104 100644
--- a/third_party/heimdal/lib/krb5/replay.c
+++ b/third_party/heimdal/lib/krb5/replay.c
@@ -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)
diff --git a/third_party/heimdal/lib/krb5/salt-arcfour.c b/third_party/heimdal/lib/krb5/salt-arcfour.c
index 38aaa25024e..033128ed803 100644
--- a/third_party/heimdal/lib/krb5/salt-arcfour.c
+++ b/third_party/heimdal/lib/krb5/salt-arcfour.c
@@ -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);
diff --git a/third_party/heimdal/lib/krb5/scache.c b/third_party/heimdal/lib/krb5/scache.c
index 554f377125e..7a39664946b 100644
--- a/third_party/heimdal/lib/krb5/scache.c
+++ b/third_party/heimdal/lib/krb5/scache.c
@@ -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;
}
diff --git a/third_party/heimdal/lib/krb5/send_to_kdc.c b/third_party/heimdal/lib/krb5/send_to_kdc.c
index 704b095b535..086f2edcd5d 100644
--- a/third_party/heimdal/lib/krb5/send_to_kdc.c
+++ b/third_party/heimdal/lib/krb5/send_to_kdc.c
@@ -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");
}
diff --git a/third_party/heimdal/lib/krb5/sp800-108-kdf.c b/third_party/heimdal/lib/krb5/sp800-108-kdf.c
index 37e06dec3e8..4a12067c68b 100755
--- a/third_party/heimdal/lib/krb5/sp800-108-kdf.c
+++ b/third_party/heimdal/lib/krb5/sp800-108-kdf.c
@@ -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);
diff --git a/third_party/heimdal/lib/krb5/store.c b/third_party/heimdal/lib/krb5/store.c
index 6a287bdf950..79f8e3adbab 100644
--- a/third_party/heimdal/lib/krb5/store.c
+++ b/third_party/heimdal/lib/krb5/store.c
@@ -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;
}
diff --git a/third_party/heimdal/lib/krb5/store_emem.c b/third_party/heimdal/lib/krb5/store_emem.c
index da66e5fa75e..6a3908f7463 100644
--- a/third_party/heimdal/lib/krb5/store_emem.c
+++ b/third_party/heimdal/lib/krb5/store_emem.c
@@ -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);
}
diff --git a/third_party/heimdal/lib/krb5/store_stdio.c b/third_party/heimdal/lib/krb5/store_stdio.c
index 80323e1d8f2..dddaa924578 100644
--- a/third_party/heimdal/lib/krb5/store_stdio.c
+++ b/third_party/heimdal/lib/krb5/store_stdio.c
@@ -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)
diff --git a/third_party/heimdal/lib/krb5/test_alname.c b/third_party/heimdal/lib/krb5/test_alname.c
index 120143e51e7..36775adef1b 100644
--- a/third_party/heimdal/lib/krb5/test_alname.c
+++ b/third_party/heimdal/lib/krb5/test_alname.c
@@ -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)
diff --git a/third_party/heimdal/lib/krb5/test_ap-req.c b/third_party/heimdal/lib/krb5/test_ap-req.c
index c3aaef3606a..0fd10783397 100644
--- a/third_party/heimdal/lib/krb5/test_ap-req.c
+++ b/third_party/heimdal/lib/krb5/test_ap-req.c
@@ -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);
diff --git a/third_party/heimdal/lib/krb5/test_cc.c b/third_party/heimdal/lib/krb5/test_cc.c
index 213bb0780d9..0ca582eaaca 100644
--- a/third_party/heimdal/lib/krb5/test_cc.c
+++ b/third_party/heimdal/lib/krb5/test_cc.c
@@ -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);
diff --git a/third_party/heimdal/lib/krb5/test_hostname.c b/third_party/heimdal/lib/krb5/test_hostname.c
index fbdb5c9c322..f722353f664 100644
--- a/third_party/heimdal/lib/krb5/test_hostname.c
+++ b/third_party/heimdal/lib/krb5/test_hostname.c
@@ -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);
diff --git a/third_party/heimdal/lib/krb5/test_rfc3961.c b/third_party/heimdal/lib/krb5/test_rfc3961.c
index f1255948fc4..ed8ee9b5f3f 100644
--- a/third_party/heimdal/lib/krb5/test_rfc3961.c
+++ b/third_party/heimdal/lib/krb5/test_rfc3961.c
@@ -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
diff --git a/third_party/heimdal/lib/krb5/test_set_kvno0.c b/third_party/heimdal/lib/krb5/test_set_kvno0.c
index 526c240f1c4..0c7e6b447ae 100644
--- a/third_party/heimdal/lib/krb5/test_set_kvno0.c
+++ b/third_party/heimdal/lib/krb5/test_set_kvno0.c
@@ -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;
diff --git a/third_party/heimdal/lib/krb5/ticket.c b/third_party/heimdal/lib/krb5/ticket.c
index 11e4e84963b..e2f2ab2085c 100644
--- a/third_party/heimdal/lib/krb5/ticket.c
+++ b/third_party/heimdal/lib/krb5/ticket.c
@@ -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,
diff --git a/third_party/heimdal/lib/krb5/transited.c b/third_party/heimdal/lib/krb5/transited.c
index 35c00e65add..484fd398c29 100644
--- a/third_party/heimdal/lib/krb5/transited.c
+++ b/third_party/heimdal/lib/krb5/transited.c
@@ -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 "
diff --git a/third_party/heimdal/lib/krb5/verify_user.c b/third_party/heimdal/lib/krb5/verify_user.c
index 663196b29b1..c6ead8e42b2 100644
--- a/third_party/heimdal/lib/krb5/verify_user.c
+++ b/third_party/heimdal/lib/krb5/verify_user.c
@@ -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
diff --git a/third_party/heimdal/lib/krb5/version-script.map b/third_party/heimdal/lib/krb5/version-script.map
index ce2783c3575..f6278e9ecbf 100644
--- a/third_party/heimdal/lib/krb5/version-script.map
+++ b/third_party/heimdal/lib/krb5/version-script.map
@@ -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;
diff --git a/third_party/heimdal/lib/ntlm/digest.c b/third_party/heimdal/lib/ntlm/digest.c
index a1d6b5f3a64..761e1f497fc 100644
--- a/third_party/heimdal/lib/ntlm/digest.c
+++ b/third_party/heimdal/lib/ntlm/digest.c
@@ -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);
diff --git a/third_party/heimdal/lib/ntlm/ntlm.c b/third_party/heimdal/lib/ntlm/ntlm.c
index 9670a971830..d75752ea000 100644
--- a/third_party/heimdal/lib/ntlm/ntlm.c
+++ b/third_party/heimdal/lib/ntlm/ntlm.c
@@ -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;
}
diff --git a/third_party/heimdal/lib/otp/otp_md.c b/third_party/heimdal/lib/otp/otp_md.c
index 1d6fe959437..9338a204def 100644
--- a/third_party/heimdal/lib/otp/otp_md.c
+++ b/third_party/heimdal/lib/otp/otp_md.c
@@ -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);
diff --git a/third_party/heimdal/lib/roken/Makefile.am b/third_party/heimdal/lib/roken/Makefile.am
index a6168f944d4..35d753204e7 100644
--- a/third_party/heimdal/lib/roken/Makefile.am
+++ b/third_party/heimdal/lib/roken/Makefile.am
@@ -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
diff --git a/third_party/heimdal/lib/roken/base32-test.c b/third_party/heimdal/lib/roken/base32-test.c
index bea2866e47d..e30c193c478 100644
--- a/third_party/heimdal/lib/roken/base32-test.c
+++ b/third_party/heimdal/lib/roken/base32-test.c
@@ -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);
diff --git a/third_party/heimdal/lib/roken/base32.c b/third_party/heimdal/lib/roken/base32.c
index 638ec2925f2..ef74336d70a 100644
--- a/third_party/heimdal/lib/roken/base32.c
+++ b/third_party/heimdal/lib/roken/base32.c
@@ -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)
diff --git a/third_party/heimdal/lib/roken/base64-test.c b/third_party/heimdal/lib/roken/base64-test.c
index 86cccbb1d4f..8fb3f528001 100644
--- a/third_party/heimdal/lib/roken/base64-test.c
+++ b/third_party/heimdal/lib/roken/base64-test.c
@@ -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);
diff --git a/third_party/heimdal/lib/roken/base64.c b/third_party/heimdal/lib/roken/base64.c
index a6dacdd1d29..582d183bcf7 100644
--- a/third_party/heimdal/lib/roken/base64.c
+++ b/third_party/heimdal/lib/roken/base64.c
@@ -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)
diff --git a/third_party/heimdal/lib/roken/copyhostent.c b/third_party/heimdal/lib/roken/copyhostent.c
index 4ed630210fc..9b9dba2aea5 100644
--- a/third_party/heimdal/lib/roken/copyhostent.c
+++ b/third_party/heimdal/lib/roken/copyhostent.c
@@ -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;
}
-
diff --git a/third_party/heimdal/lib/roken/detach.c b/third_party/heimdal/lib/roken/detach.c
index 36e6cda1e02..4a00682511f 100644
--- a/third_party/heimdal/lib/roken/detach.c
+++ b/third_party/heimdal/lib/roken/detach.c
@@ -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))
diff --git a/third_party/heimdal/lib/roken/dirent-test.c b/third_party/heimdal/lib/roken/dirent-test.c
index f1035a1aed6..dc4518ad5b0 100644
--- a/third_party/heimdal/lib/roken/dirent-test.c
+++ b/third_party/heimdal/lib/roken/dirent-test.c
@@ -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;
diff --git a/third_party/heimdal/lib/roken/environment.c b/third_party/heimdal/lib/roken/environment.c
index 64c354d62bb..a14f27b8a93 100644
--- a/third_party/heimdal/lib/roken/environment.c
+++ b/third_party/heimdal/lib/roken/environment.c
@@ -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))
diff --git a/third_party/heimdal/lib/roken/fnmatch.c b/third_party/heimdal/lib/roken/fnmatch.c
index 7dfe492179d..74f35283d35 100644
--- a/third_party/heimdal/lib/roken/fnmatch.c
+++ b/third_party/heimdal/lib/roken/fnmatch.c
@@ -129,7 +129,7 @@ rk_fnmatch(const char *pattern, const char *string, int flags)
--pattern;
}
}
- /* FALLTHROUGH */
+ fallthrough;
default:
if (c != *string++)
return (FNM_NOMATCH);
diff --git a/third_party/heimdal/lib/roken/freeaddrinfo.c b/third_party/heimdal/lib/roken/freeaddrinfo.c
index 7132e95dd38..80a7487b8d5 100644
--- a/third_party/heimdal/lib/roken/freeaddrinfo.c
+++ b/third_party/heimdal/lib/roken/freeaddrinfo.c
@@ -40,7 +40,7 @@
*/
ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
-freeaddrinfo(struct addrinfo *ai)
+rk_freeaddrinfo(struct addrinfo *ai)
{
struct addrinfo *tofree;
diff --git a/third_party/heimdal/lib/roken/freehostent.c b/third_party/heimdal/lib/roken/freehostent.c
index 61fbb223b5e..05dd0fe385c 100644
--- a/third_party/heimdal/lib/roken/freehostent.c
+++ b/third_party/heimdal/lib/roken/freehostent.c
@@ -40,7 +40,7 @@
*/
ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
-freehostent (struct hostent *h)
+rk_freehostent(struct hostent *h)
{
char **p;
diff --git a/third_party/heimdal/lib/roken/getaddrinfo.c b/third_party/heimdal/lib/roken/getaddrinfo.c
index c8ed95413fe..12a26a71225 100644
--- a/third_party/heimdal/lib/roken/getaddrinfo.c
+++ b/third_party/heimdal/lib/roken/getaddrinfo.c
@@ -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
index a8dd94bef9a..00000000000
--- a/third_party/heimdal/lib/roken/getcap.c
+++ /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);
-}
diff --git a/third_party/heimdal/lib/roken/getipnodebyaddr.c b/third_party/heimdal/lib/roken/getipnodebyaddr.c
index 7d4095f1d84..afebe914950 100644
--- a/third_party/heimdal/lib/roken/getipnodebyaddr.c
+++ b/third_party/heimdal/lib/roken/getipnodebyaddr.c
@@ -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;
diff --git a/third_party/heimdal/lib/roken/getipnodebyname.c b/third_party/heimdal/lib/roken/getipnodebyname.c
index 2ff282707c2..ee430c76eb6 100644
--- a/third_party/heimdal/lib/roken/getipnodebyname.c
+++ b/third_party/heimdal/lib/roken/getipnodebyname.c
@@ -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;
diff --git a/third_party/heimdal/lib/roken/getnameinfo.c b/third_party/heimdal/lib/roken/getnameinfo.c
index b23ad01ebdd..9d118600f26 100644
--- a/third_party/heimdal/lib/roken/getnameinfo.c
+++ b/third_party/heimdal/lib/roken/getnameinfo.c
@@ -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
diff --git a/third_party/heimdal/lib/roken/getuserinfo.c b/third_party/heimdal/lib/roken/getuserinfo.c
index 76cd78241be..7fd2ca9f151 100644
--- a/third_party/heimdal/lib/roken/getuserinfo.c
+++ b/third_party/heimdal/lib/roken/getuserinfo.c
@@ -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;
diff --git a/third_party/heimdal/lib/roken/hex-test.c b/third_party/heimdal/lib/roken/hex-test.c
index a81422e1f4a..01f21c821d1 100644
--- a/third_party/heimdal/lib/roken/hex-test.c
+++ b/third_party/heimdal/lib/roken/hex-test.c
@@ -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++;
}
diff --git a/third_party/heimdal/lib/roken/hex.c b/third_party/heimdal/lib/roken/hex.c
index c66b324f790..cc47fa4d52d 100644
--- a/third_party/heimdal/lib/roken/hex.c
+++ b/third_party/heimdal/lib/roken/hex.c
@@ -39,14 +39,15 @@
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);
}
diff --git a/third_party/heimdal/lib/roken/mergesort_r.c b/third_party/heimdal/lib/roken/mergesort_r.c
index 2d551a607a2..39b0301c454 100644
--- a/third_party/heimdal/lib/roken/mergesort_r.c
+++ b/third_party/heimdal/lib/roken/mergesort_r.c
@@ -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)
diff --git a/third_party/heimdal/lib/roken/ndbm_wrap.c b/third_party/heimdal/lib/roken/ndbm_wrap.c
index f7b87f1203e..f8403da44ab 100644
--- a/third_party/heimdal/lib/roken/ndbm_wrap.c
+++ b/third_party/heimdal/lib/roken/ndbm_wrap.c
@@ -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)
diff --git a/third_party/heimdal/lib/roken/net_write.c b/third_party/heimdal/lib/roken/net_write.c
index 1e8361999ea..e66f56b7595 100644
--- a/third_party/heimdal/lib/roken/net_write.c
+++ b/third_party/heimdal/lib/roken/net_write.c
@@ -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;
diff --git a/third_party/heimdal/lib/roken/resolve-test.c b/third_party/heimdal/lib/roken/resolve-test.c
index 25cc98aafe3..581600a5937 100644
--- a/third_party/heimdal/lib/roken/resolve-test.c
+++ b/third_party/heimdal/lib/roken/resolve-test.c
@@ -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;
diff --git a/third_party/heimdal/lib/roken/roken-common.h b/third_party/heimdal/lib/roken/roken-common.h
index f05f88668f3..035b99b8b97 100644
--- a/third_party/heimdal/lib/roken/roken-common.h
+++ b/third_party/heimdal/lib/roken/roken-common.h
@@ -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);
diff --git a/third_party/heimdal/lib/roken/roken.h.in b/third_party/heimdal/lib/roken/roken.h.in
index e1aa6b7b60c..e1902f582dc 100644
--- a/third_party/heimdal/lib/roken/roken.h.in
+++ b/third_party/heimdal/lib/roken/roken.h.in
@@ -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
diff --git a/third_party/heimdal/lib/roken/snprintf.c b/third_party/heimdal/lib/roken/snprintf.c
index 620875f379c..3da48962ee3 100644
--- a/third_party/heimdal/lib/roken/snprintf.c
+++ b/third_party/heimdal/lib/roken/snprintf.c
@@ -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;
diff --git a/third_party/heimdal/lib/roken/socket.c b/third_party/heimdal/lib/roken/socket.c
index 9feb343f508..a790e082d82 100644
--- a/third_party/heimdal/lib/roken/socket.c
+++ b/third_party/heimdal/lib/roken/socket.c
@@ -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));
}
/**
diff --git a/third_party/heimdal/lib/roken/strftime.c b/third_party/heimdal/lib/roken/strftime.c
index 447c1554337..9a951dd3008 100644
--- a/third_party/heimdal/lib/roken/strftime.c
+++ b/third_party/heimdal/lib/roken/strftime.c
@@ -36,6 +36,11 @@
#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,
"%%");
diff --git a/third_party/heimdal/lib/roken/strptime.c b/third_party/heimdal/lib/roken/strptime.c
index 75c27a32877..86216d2d6dc 100644
--- a/third_party/heimdal/lib/roken/strptime.c
+++ b/third_party/heimdal/lib/roken/strptime.c
@@ -424,7 +424,7 @@ strptime (const char *buf, const char *format, struct tm *timeptr)
abort ();
case '\0' :
--format;
- /* FALLTHROUGH */
+ fallthrough;
case '%' :
if (*buf == '%')
++buf;
diff --git a/third_party/heimdal/lib/roken/strtoll.c b/third_party/heimdal/lib/roken/strtoll.c
index 0d895d54a25..96c1b250974 100644
--- a/third_party/heimdal/lib/roken/strtoll.c
+++ b/third_party/heimdal/lib/roken/strtoll.c
@@ -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 */
diff --git a/third_party/heimdal/lib/roken/strtoull.c b/third_party/heimdal/lib/roken/strtoull.c
index 94530e574d1..0516e18f913 100644
--- a/third_party/heimdal/lib/roken/strtoull.c
+++ b/third_party/heimdal/lib/roken/strtoull.c
@@ -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 */
diff --git a/third_party/heimdal/lib/roken/test-getuserinfo.c b/third_party/heimdal/lib/roken/test-getuserinfo.c
index b3f15214b56..4feae177aed 100644
--- a/third_party/heimdal/lib/roken/test-getuserinfo.c
+++ b/third_party/heimdal/lib/roken/test-getuserinfo.c
@@ -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) {
diff --git a/third_party/heimdal/lib/roken/test-mini_inetd.c b/third_party/heimdal/lib/roken/test-mini_inetd.c
index 079ace266a1..7ab996ae8b4 100644
--- a/third_party/heimdal/lib/roken/test-mini_inetd.c
+++ b/third_party/heimdal/lib/roken/test-mini_inetd.c
@@ -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;
}
diff --git a/third_party/heimdal/lib/roken/timeval.c b/third_party/heimdal/lib/roken/timeval.c
index 38b1f7ce9c3..3012513ee7d 100644
--- a/third_party/heimdal/lib/roken/timeval.c
+++ b/third_party/heimdal/lib/roken/timeval.c
@@ -39,6 +39,93 @@
#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
diff --git a/third_party/heimdal/lib/roken/version-script.map b/third_party/heimdal/lib/roken/version-script.map
index 3307341c049..be1713e8261 100644
--- a/third_party/heimdal/lib/roken/version-script.map
+++ b/third_party/heimdal/lib/roken/version-script.map
@@ -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;
diff --git a/third_party/heimdal/lib/roken/vis.c b/third_party/heimdal/lib/roken/vis.c
index c598967fb72..0fe44ae3502 100644
--- a/third_party/heimdal/lib/roken/vis.c
+++ b/third_party/heimdal/lib/roken/vis.c
@@ -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
diff --git a/third_party/heimdal/lib/sl/Makefile.am b/third_party/heimdal/lib/sl/Makefile.am
index 152b86a330a..1213d8c9df9 100644
--- a/third_party/heimdal/lib/sl/Makefile.am
+++ b/third_party/heimdal/lib/sl/Makefile.am
@@ -8,7 +8,7 @@ endif
AM_CPPFLAGS += $(ROKEN_RENAME)
-YFLAGS = -d
+YFLAGS = -d -o slc-gram.c
LFLAGS = @FLEXNOUNPUTARGS@
include_HEADERS = sl.h
diff --git a/third_party/heimdal/lib/sl/sl.c b/third_party/heimdal/lib/sl/sl.c
index 03f577b5f59..b78f9f675b2 100644
--- a/third_party/heimdal/lib/sl/sl.c
+++ b/third_party/heimdal/lib/sl/sl.c
@@ -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;
diff --git a/third_party/heimdal/lib/sl/slc-gram.y b/third_party/heimdal/lib/sl/slc-gram.y
index 767ffc833c8..38045c10048 100644
--- a/third_party/heimdal/lib/sl/slc-gram.y
+++ b/third_party/heimdal/lib/sl/slc-gram.y
@@ -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];
diff --git a/third_party/heimdal/lib/wind/idn-lookup.c b/third_party/heimdal/lib/wind/idn-lookup.c
index 1bc63a33dd8..378c912a392 100644
--- a/third_party/heimdal/lib/wind/idn-lookup.c
+++ b/third_party/heimdal/lib/wind/idn-lookup.c
@@ -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;
}
diff --git a/third_party/heimdal/lib/wind/utf8.c b/third_party/heimdal/lib/wind/utf8.c
index d69db0c0cec..452b7b260d8 100644
--- a/third_party/heimdal/lib/wind/utf8.c
+++ b/third_party/heimdal/lib/wind/utf8.c
@@ -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;
}
diff --git a/third_party/heimdal/packages/windows/installer/NTMakefile b/third_party/heimdal/packages/windows/installer/NTMakefile
index ad63ae04f4c..2923e649b96 100644
--- a/third_party/heimdal/packages/windows/installer/NTMakefile
+++ b/third_party/heimdal/packages/windows/installer/NTMakefile
@@ -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
diff --git a/third_party/heimdal/packages/windows/installer/heimdal-installer.wxs b/third_party/heimdal/packages/windows/installer/heimdal-installer.wxs
index 0b6000d1bfa..8ac6cc665fd 100644
--- a/third_party/heimdal/packages/windows/installer/heimdal-installer.wxs
+++ b/third_party/heimdal/packages/windows/installer/heimdal-installer.wxs
@@ -99,9 +99,10 @@
<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?>
@@ -127,9 +128,10 @@
<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?>
@@ -370,12 +372,12 @@
<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?>
@@ -393,7 +395,7 @@
<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?>
diff --git a/third_party/heimdal/tests/bin/setup-env.in b/third_party/heimdal/tests/bin/setup-env.in
index 954a2c1d5f5..c9291d08bf2 100644
--- a/third_party/heimdal/tests/bin/setup-env.in
+++ b/third_party/heimdal/tests/bin/setup-env.in
@@ -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"
diff --git a/third_party/heimdal/tests/gss/Makefile.am b/third_party/heimdal/tests/gss/Makefile.am
index ca40ae26bd2..2de36bfe24c 100644
--- a/third_party/heimdal/tests/gss/Makefile.am
+++ b/third_party/heimdal/tests/gss/Makefile.am
@@ -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
diff --git a/third_party/heimdal/tests/gss/check-basic.in b/third_party/heimdal/tests/gss/check-basic.in
index d4916bd46d4..c5151c4c94f 100644
--- a/third_party/heimdal/tests/gss/check-basic.in
+++ b/third_party/heimdal/tests/gss/check-basic.in
@@ -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
diff --git a/third_party/heimdal/tests/gss/check-context.in b/third_party/heimdal/tests/gss/check-context.in
index 42ea15eecb9..46c058d068b 100644
--- a/third_party/heimdal/tests/gss/check-context.in
+++ b/third_party/heimdal/tests/gss/check-context.in
@@ -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=""
diff --git a/third_party/heimdal/tests/gss/check-gssmask.in b/third_party/heimdal/tests/gss/check-gssmask.in
index 44769eff584..539e2e94e52 100644
--- a/third_party/heimdal/tests/gss/check-gssmask.in
+++ b/third_party/heimdal/tests/gss/check-gssmask.in
@@ -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
diff --git a/third_party/heimdal/tests/gss/check-ntlm.in b/third_party/heimdal/tests/gss/check-ntlm.in
index f5bf3446ae6..f953630d09d 100644
--- a/third_party/heimdal/tests/gss/check-ntlm.in
+++ b/third_party/heimdal/tests/gss/check-ntlm.in
@@ -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
diff --git a/third_party/heimdal/tests/gss/check-spnego.in b/third_party/heimdal/tests/gss/check-spnego.in
index 3cf56089602..d6e4d833152 100644
--- a/third_party/heimdal/tests/gss/check-spnego.in
+++ b/third_party/heimdal/tests/gss/check-spnego.in
@@ -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
diff --git a/third_party/heimdal/tests/gss/krb5.conf.in b/third_party/heimdal/tests/gss/krb5.conf.in
index b8e04b65159..aae031db645 100644
--- a/third_party/heimdal/tests/gss/krb5.conf.in
+++ b/third_party/heimdal/tests/gss/krb5.conf.in
@@ -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
diff --git a/third_party/heimdal/tests/java/check-kinit.in b/third_party/heimdal/tests/java/check-kinit.in
index 04043ca02e2..82033447409 100644
--- a/third_party/heimdal/tests/java/check-kinit.in
+++ b/third_party/heimdal/tests/java/check-kinit.in
@@ -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
diff --git a/third_party/heimdal/tests/kdc/Makefile.am b/third_party/heimdal/tests/kdc/Makefile.am
index a07f776eb23..f61a7e85307 100644
--- a/third_party/heimdal/tests/kdc/Makefile.am
+++ b/third_party/heimdal/tests/kdc/Makefile.am
@@ -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
diff --git a/third_party/heimdal/tests/kdc/check-bx509.in b/third_party/heimdal/tests/kdc/check-bx509.in
index 1cef2e0e766..b50239d8440 100644
--- a/third_party/heimdal/tests/kdc/check-bx509.in
+++ b/third_party/heimdal/tests/kdc/check-bx509.in
@@ -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"
diff --git a/third_party/heimdal/tests/kdc/check-canon.in b/third_party/heimdal/tests/kdc/check-canon.in
index 0bb5a413f3c..18b83a9b7a6 100644
--- a/third_party/heimdal/tests/kdc/check-canon.in
+++ b/third_party/heimdal/tests/kdc/check-canon.in
@@ -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
diff --git a/third_party/heimdal/tests/kdc/check-cc.in b/third_party/heimdal/tests/kdc/check-cc.in
index ce95b300664..46e846a10ea 100644
--- a/third_party/heimdal/tests/kdc/check-cc.in
+++ b/third_party/heimdal/tests/kdc/check-cc.in
@@ -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
diff --git a/third_party/heimdal/tests/kdc/check-delegation.in b/third_party/heimdal/tests/kdc/check-delegation.in
index 8657946168a..fdff0f6a0f0 100644
--- a/third_party/heimdal/tests/kdc/check-delegation.in
+++ b/third_party/heimdal/tests/kdc/check-delegation.in
@@ -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
diff --git a/third_party/heimdal/tests/kdc/check-des.in b/third_party/heimdal/tests/kdc/check-des.in
index d45b119dfa5..144613df4f9 100644
--- a/third_party/heimdal/tests/kdc/check-des.in
+++ b/third_party/heimdal/tests/kdc/check-des.in
@@ -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
diff --git a/third_party/heimdal/tests/kdc/check-digest.in b/third_party/heimdal/tests/kdc/check-digest.in
index 1623783eba6..d934f4e2898 100644
--- a/third_party/heimdal/tests/kdc/check-digest.in
+++ b/third_party/heimdal/tests/kdc/check-digest.in
@@ -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
diff --git a/third_party/heimdal/tests/kdc/check-fast.in b/third_party/heimdal/tests/kdc/check-fast.in
index 136bf3ed62b..3fbda813a63 100644
--- a/third_party/heimdal/tests/kdc/check-fast.in
+++ b/third_party/heimdal/tests/kdc/check-fast.in
@@ -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
diff --git a/third_party/heimdal/tests/kdc/check-hdb-mitdb.in b/third_party/heimdal/tests/kdc/check-hdb-mitdb.in
index e9de58799a3..a241aeb4a8f 100644
--- a/third_party/heimdal/tests/kdc/check-hdb-mitdb.in
+++ b/third_party/heimdal/tests/kdc/check-hdb-mitdb.in
@@ -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
diff --git a/third_party/heimdal/tests/kdc/check-httpkadmind.in b/third_party/heimdal/tests/kdc/check-httpkadmind.in
index b593925a352..f57f2af8592 100644
--- a/third_party/heimdal/tests/kdc/check-httpkadmind.in
+++ b/third_party/heimdal/tests/kdc/check-httpkadmind.in
@@ -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"
diff --git a/third_party/heimdal/tests/kdc/check-iprop.in b/third_party/heimdal/tests/kdc/check-iprop.in
index 21296877943..524379393fa 100644
--- a/third_party/heimdal/tests/kdc/check-iprop.in
+++ b/third_party/heimdal/tests/kdc/check-iprop.in
@@ -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
diff --git a/third_party/heimdal/tests/kdc/check-kadmin.in b/third_party/heimdal/tests/kdc/check-kadmin.in
index 3d3f41003d8..45d679ceb4a 100644
--- a/third_party/heimdal/tests/kdc/check-kadmin.in
+++ b/third_party/heimdal/tests/kdc/check-kadmin.in
@@ -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
diff --git a/third_party/heimdal/tests/kdc/check-kdc.in b/third_party/heimdal/tests/kdc/check-kdc.in
index 75626f6ce85..e53293b2427 100644
--- a/third_party/heimdal/tests/kdc/check-kdc.in
+++ b/third_party/heimdal/tests/kdc/check-kdc.in
@@ -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}
diff --git a/third_party/heimdal/tests/kdc/check-kinit.in b/third_party/heimdal/tests/kdc/check-kinit.in
index 35ec6deadbf..c6cb23ff6f8 100644
--- a/third_party/heimdal/tests/kdc/check-kinit.in
+++ b/third_party/heimdal/tests/kdc/check-kinit.in
@@ -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
diff --git a/third_party/heimdal/tests/kdc/check-kpasswdd.in b/third_party/heimdal/tests/kdc/check-kpasswdd.in
index 4f63ce240fa..39f12e1be8c 100644
--- a/third_party/heimdal/tests/kdc/check-kpasswdd.in
+++ b/third_party/heimdal/tests/kdc/check-kpasswdd.in
@@ -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
diff --git a/third_party/heimdal/tests/kdc/check-pkinit.in b/third_party/heimdal/tests/kdc/check-pkinit.in
index baa9fb30691..9f90fd040f9 100644
--- a/third_party/heimdal/tests/kdc/check-pkinit.in
+++ b/third_party/heimdal/tests/kdc/check-pkinit.in
@@ -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
diff --git a/third_party/heimdal/tests/kdc/check-referral.in b/third_party/heimdal/tests/kdc/check-referral.in
index d028e39ef1f..73c26c368ca 100644
--- a/third_party/heimdal/tests/kdc/check-referral.in
+++ b/third_party/heimdal/tests/kdc/check-referral.in
@@ -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
diff --git a/third_party/heimdal/tests/kdc/check-tester.in b/third_party/heimdal/tests/kdc/check-tester.in
index dba154c299b..83b48baf27f 100644
--- a/third_party/heimdal/tests/kdc/check-tester.in
+++ b/third_party/heimdal/tests/kdc/check-tester.in
@@ -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
diff --git a/third_party/heimdal/tests/kdc/check-uu.in b/third_party/heimdal/tests/kdc/check-uu.in
index 7e819a14ad0..ef831ca4d94 100644
--- a/third_party/heimdal/tests/kdc/check-uu.in
+++ b/third_party/heimdal/tests/kdc/check-uu.in
@@ -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
index 00000000000..bdcca073cc0
--- /dev/null
+++ b/third_party/heimdal/tests/kdc/krb5-kcm.conf.in
@@ -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
+ }
diff --git a/third_party/heimdal/tests/kdc/krb5.conf.in b/third_party/heimdal/tests/kdc/krb5.conf.in
index 19b4e3ef64e..a85836d76b2 100644
--- a/third_party/heimdal/tests/kdc/krb5.conf.in
+++ b/third_party/heimdal/tests/kdc/krb5.conf.in
@@ -126,6 +126,9 @@
[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
diff --git a/third_party/heimdal/tests/ldap/check-ldap.in b/third_party/heimdal/tests/ldap/check-ldap.in
index b99c951032b..f73eb6e1b88 100644
--- a/third_party/heimdal/tests/ldap/check-ldap.in
+++ b/third_party/heimdal/tests/ldap/check-ldap.in
@@ -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
diff --git a/third_party/heimdal/tests/plugin/Makefile.am b/third_party/heimdal/tests/plugin/Makefile.am
index 3fb1a2324b9..5dd43ccb04d 100644
--- a/third_party/heimdal/tests/plugin/Makefile.am
+++ b/third_party/heimdal/tests/plugin/Makefile.am
@@ -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) \
diff --git a/third_party/heimdal/tests/plugin/check-pac.in b/third_party/heimdal/tests/plugin/check-pac.in
index 60ec21a31f3..85bf8cd9a98 100644
--- a/third_party/heimdal/tests/plugin/check-pac.in
+++ b/third_party/heimdal/tests/plugin/check-pac.in
@@ -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
index 00000000000..4fcf311fddf
--- /dev/null
+++ b/third_party/heimdal/tests/plugin/kdc_test_plugin.c
@@ -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;
+}
diff --git a/third_party/heimdal/tests/plugin/krb5.conf.in b/third_party/heimdal/tests/plugin/krb5.conf.in
index 8ab2f17177c..d188c314b36 100644
--- a/third_party/heimdal/tests/plugin/krb5.conf.in
+++ b/third_party/heimdal/tests/plugin/krb5.conf.in
@@ -19,6 +19,21 @@
}
[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
index 357148019ae..00000000000
--- a/third_party/heimdal/tests/plugin/windc.c
+++ /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
index 00000000000..a9f2b30dfdf
--- /dev/null
+++ b/third_party/heimdal/windows/NTMakefile.sdk
@@ -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)
diff --git a/third_party/heimdal/windows/NTMakefile.w32 b/third_party/heimdal/windows/NTMakefile.w32
index 47df51042a2..471e783912b 100644
--- a/third_party/heimdal/windows/NTMakefile.w32
+++ b/third_party/heimdal/windows/NTMakefile.w32
@@ -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