summaryrefslogtreecommitdiff
path: root/third_party/heimdal/lib
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/heimdal/lib')
-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
287 files changed, 9431 insertions, 4522 deletions
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;
}