summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Sutton <josephsutton@catalyst.net.nz>2023-03-09 09:00:02 +1300
committerAndrew Bartlett <abartlet@samba.org>2023-03-31 01:48:30 +0000
commita87aae5292d1c43b987dcfa77a51b6aa5aa3e004 (patch)
treec1af6a7ddb6a196d4af09cd086815be51a709365
parentf448a1649cf4af11f1ceba55ec62e9b2a3db24f1 (diff)
downloadsamba-a87aae5292d1c43b987dcfa77a51b6aa5aa3e004.tar.gz
third_party/heimdal: Import lorikeet-heimdal-202303200103 (commit 2ee541b5e963f7cffb1ec4acd1a8cc45426a9f28)
NOTE: THIS COMMIT WON'T COMPILE/WORK ON ITS OWN! Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abartlet@samba.org>
-rw-r--r--third_party/heimdal/.github/workflows/coverity.yml20
-rw-r--r--third_party/heimdal/.github/workflows/linux-mit-interop.yml117
-rw-r--r--third_party/heimdal/.github/workflows/ubsan.yml133
-rw-r--r--third_party/heimdal/NEWS342
-rw-r--r--third_party/heimdal/admin/NTMakefile1
-rw-r--r--third_party/heimdal/admin/add.c2
-rw-r--r--third_party/heimdal/admin/get.c3
-rw-r--r--third_party/heimdal/admin/list.c1
-rw-r--r--third_party/heimdal/appl/gssmask/common.c2
-rw-r--r--third_party/heimdal/appl/test/gssapi_server.c3
-rw-r--r--third_party/heimdal/appl/test/http_client.c4
-rw-r--r--third_party/heimdal/cf/broken-realloc.m48
-rw-r--r--third_party/heimdal/cf/crypto.m417
-rw-r--r--third_party/heimdal/cf/roken-frag.m416
-rw-r--r--third_party/heimdal/cf/sunos.m41
-rw-r--r--third_party/heimdal/configure.ac7
-rw-r--r--third_party/heimdal/doc/Makefile.am4
-rw-r--r--third_party/heimdal/doc/whatis.texi26
-rw-r--r--third_party/heimdal/include/config.h.w324
-rw-r--r--third_party/heimdal/include/hcrypto/Makefile.am1
-rw-r--r--third_party/heimdal/kadmin/Makefile.am1
-rw-r--r--third_party/heimdal/kadmin/ank.c9
-rw-r--r--third_party/heimdal/kadmin/cpw.c9
-rw-r--r--third_party/heimdal/kadmin/get.c10
-rw-r--r--third_party/heimdal/kadmin/kadmin.c7
-rw-r--r--third_party/heimdal/kadmin/kadmind.c92
-rw-r--r--third_party/heimdal/kadmin/mod.c1
-rw-r--r--third_party/heimdal/kadmin/rpc.c1
-rw-r--r--third_party/heimdal/kdc/Makefile.am15
-rw-r--r--third_party/heimdal/kdc/bx509d.c173
-rw-r--r--third_party/heimdal/kdc/fast.c6
-rw-r--r--third_party/heimdal/kdc/hpropd.c38
-rw-r--r--third_party/heimdal/kdc/httpkadmind.c33
-rw-r--r--third_party/heimdal/kdc/ipc_csr_authorizer.c291
-rw-r--r--third_party/heimdal/kdc/kdc-plugin.c66
-rw-r--r--third_party/heimdal/kdc/kdc-plugin.h28
-rw-r--r--third_party/heimdal/kdc/kdc-tester.c7
-rw-r--r--third_party/heimdal/kdc/kerberos5.c8
-rw-r--r--third_party/heimdal/kdc/krb5tgs.c94
-rw-r--r--third_party/heimdal/kdc/misc.c2
-rw-r--r--third_party/heimdal/kdc/mit_dump.c4
-rw-r--r--third_party/heimdal/kdc/mssfu.c20
-rw-r--r--third_party/heimdal/kdc/pkinit-ec.c350
-rw-r--r--third_party/heimdal/kdc/simple_csr_authorizer.c343
-rw-r--r--third_party/heimdal/kdc/test_csr_authorizer.c513
-rw-r--r--third_party/heimdal/kdc/test_token_validator.c2
-rw-r--r--third_party/heimdal/kpasswd/kpasswdd.c13
-rw-r--r--third_party/heimdal/krb5.conf5
-rw-r--r--third_party/heimdal/kuser/NTMakefile1
-rw-r--r--third_party/heimdal/lib/asn1/asn1parse.y4
-rw-r--r--third_party/heimdal/lib/asn1/check-der.c13
-rw-r--r--third_party/heimdal/lib/asn1/check-gen.c59
-rw-r--r--third_party/heimdal/lib/asn1/der.h2
-rw-r--r--third_party/heimdal/lib/asn1/der_cmp.c156
-rw-r--r--third_party/heimdal/lib/asn1/der_copy.c8
-rw-r--r--third_party/heimdal/lib/asn1/der_get.c48
-rw-r--r--third_party/heimdal/lib/asn1/der_length.c4
-rw-r--r--third_party/heimdal/lib/asn1/der_print.c2
-rw-r--r--third_party/heimdal/lib/asn1/der_put.c40
-rw-r--r--third_party/heimdal/lib/asn1/gen.c48
-rw-r--r--third_party/heimdal/lib/asn1/gen_free.c3
-rw-r--r--third_party/heimdal/lib/asn1/gen_template.c2
-rw-r--r--third_party/heimdal/lib/asn1/main.c2
-rw-r--r--third_party/heimdal/lib/asn1/symbol.h1
-rw-r--r--third_party/heimdal/lib/asn1/template.c41
-rw-r--r--third_party/heimdal/lib/base/Makefile.am2
-rw-r--r--third_party/heimdal/lib/base/context.c2
-rw-r--r--third_party/heimdal/lib/base/db.c5
-rw-r--r--third_party/heimdal/lib/base/dll.c14
-rw-r--r--third_party/heimdal/lib/base/error.c3
-rw-r--r--third_party/heimdal/lib/base/heimbase-atomics.h247
-rw-r--r--third_party/heimdal/lib/base/heimbase.c75
-rw-r--r--third_party/heimdal/lib/base/heimbase.h183
-rw-r--r--third_party/heimdal/lib/base/json.c2
-rw-r--r--third_party/heimdal/lib/base/log.c10
-rw-r--r--third_party/heimdal/lib/base/test_base.c80
-rw-r--r--third_party/heimdal/lib/base/version-script.map1
-rw-r--r--third_party/heimdal/lib/gssapi/gss-token.c8
-rw-r--r--third_party/heimdal/lib/gssapi/krb5/8003.c60
-rw-r--r--third_party/heimdal/lib/gssapi/krb5/arcfour.c12
-rw-r--r--third_party/heimdal/lib/gssapi/krb5/cfx.c38
-rw-r--r--third_party/heimdal/lib/gssapi/krb5/creds.c7
-rw-r--r--third_party/heimdal/lib/gssapi/krb5/duplicate_cred.c11
-rw-r--r--third_party/heimdal/lib/gssapi/krb5/init_sec_context.c11
-rw-r--r--third_party/heimdal/lib/gssapi/krb5/inquire_sec_context_by_oid.c14
-rw-r--r--third_party/heimdal/lib/gssapi/krb5/prf.c2
-rw-r--r--third_party/heimdal/lib/gssapi/krb5/unwrap.c4
-rw-r--r--third_party/heimdal/lib/gssapi/krb5/verify_mic.c4
-rw-r--r--third_party/heimdal/lib/gssapi/mech/gss_accept_sec_context.c34
-rw-r--r--third_party/heimdal/lib/gssapi/mech/gss_krb5.c19
-rw-r--r--third_party/heimdal/lib/gssapi/mech/gss_mo.c6
-rw-r--r--third_party/heimdal/lib/gssapi/mech/gss_utils.c59
-rw-r--r--third_party/heimdal/lib/gssapi/mech/mech_locl.h1
-rw-r--r--third_party/heimdal/lib/gssapi/mech/utils.h5
-rw-r--r--third_party/heimdal/lib/gssapi/ntlm/crypto.c55
-rw-r--r--third_party/heimdal/lib/gssapi/ntlm/kdc.c2
-rw-r--r--third_party/heimdal/lib/gssapi/ntlm/ntlm.h1
-rw-r--r--third_party/heimdal/lib/gssapi/sanon/export_cred.c40
-rw-r--r--third_party/heimdal/lib/gssapi/spnego/context_storage.c14
-rw-r--r--third_party/heimdal/lib/gssapi/spnego/negoex_util.c9
-rw-r--r--third_party/heimdal/lib/gssapi/test_context.c28
-rw-r--r--third_party/heimdal/lib/hcrypto/Makefile.am5
-rw-r--r--third_party/heimdal/lib/hcrypto/NTMakefile2
-rw-r--r--third_party/heimdal/lib/hcrypto/des.c16
-rw-r--r--third_party/heimdal/lib/hcrypto/engine.h2
-rw-r--r--third_party/heimdal/lib/hcrypto/evp-cc.c26
-rw-r--r--third_party/heimdal/lib/hcrypto/evp-cc.h2
-rw-r--r--third_party/heimdal/lib/hcrypto/evp-hcrypto.c23
-rw-r--r--third_party/heimdal/lib/hcrypto/evp-hcrypto.h2
-rw-r--r--third_party/heimdal/lib/hcrypto/evp-openssl.c35
-rw-r--r--third_party/heimdal/lib/hcrypto/evp-openssl.h2
-rw-r--r--third_party/heimdal/lib/hcrypto/evp-pkcs11.c1
-rw-r--r--third_party/heimdal/lib/hcrypto/evp-pkcs11.h4
-rw-r--r--third_party/heimdal/lib/hcrypto/evp-w32.c1
-rw-r--r--third_party/heimdal/lib/hcrypto/evp-w32.h2
-rw-r--r--third_party/heimdal/lib/hcrypto/evp-wincng.c2
-rw-r--r--third_party/heimdal/lib/hcrypto/evp-wincng.h2
-rw-r--r--third_party/heimdal/lib/hcrypto/evp.c103
-rw-r--r--third_party/heimdal/lib/hcrypto/evp.h4
-rw-r--r--third_party/heimdal/lib/hcrypto/hmac.c5
-rw-r--r--third_party/heimdal/lib/hcrypto/libhcrypto-exports.def9
-rw-r--r--third_party/heimdal/lib/hcrypto/libtommath/bn_mp_log_u32.c11
-rw-r--r--third_party/heimdal/lib/hcrypto/libtommath/bn_mp_prime_rand.c2
-rw-r--r--third_party/heimdal/lib/hcrypto/libtommath/bn_mp_root_u32.c3
-rw-r--r--third_party/heimdal/lib/hcrypto/md2.c138
-rw-r--r--third_party/heimdal/lib/hcrypto/md2.h63
-rw-r--r--third_party/heimdal/lib/hcrypto/mdtest.c72
-rw-r--r--third_party/heimdal/lib/hcrypto/pkcs5.c3
-rw-r--r--third_party/heimdal/lib/hcrypto/rand-fortuna.c3
-rw-r--r--third_party/heimdal/lib/hcrypto/rsa-ltm.c16
-rw-r--r--third_party/heimdal/lib/hcrypto/test_bulk.c3
-rw-r--r--third_party/heimdal/lib/hcrypto/test_cipher.c6
-rw-r--r--third_party/heimdal/lib/hcrypto/test_crypto.in10
-rw-r--r--third_party/heimdal/lib/hcrypto/undef.h2
-rw-r--r--third_party/heimdal/lib/hcrypto/version-script.map8
-rw-r--r--third_party/heimdal/lib/hdb/common.c1
-rw-r--r--third_party/heimdal/lib/hdb/hdb.c2
-rw-r--r--third_party/heimdal/lib/hx509/ca.c4
-rw-r--r--third_party/heimdal/lib/hx509/cert.c61
-rw-r--r--third_party/heimdal/lib/hx509/collector.c10
-rw-r--r--third_party/heimdal/lib/hx509/crypto-ec.c507
-rw-r--r--third_party/heimdal/lib/hx509/crypto.c46
-rw-r--r--third_party/heimdal/lib/hx509/hx509.h1
-rw-r--r--third_party/heimdal/lib/hx509/hxtool-commands.in15
-rw-r--r--third_party/heimdal/lib/hx509/hxtool.1235
-rw-r--r--third_party/heimdal/lib/hx509/hxtool.c61
-rw-r--r--third_party/heimdal/lib/hx509/ks_file.c8
-rw-r--r--third_party/heimdal/lib/hx509/ks_p12.c22
-rw-r--r--third_party/heimdal/lib/hx509/libhx509-exports.def12
-rw-r--r--third_party/heimdal/lib/hx509/req.c8
-rw-r--r--third_party/heimdal/lib/hx509/revoke.c9
-rw-r--r--third_party/heimdal/lib/hx509/test_req.in30
-rw-r--r--third_party/heimdal/lib/hx509/version-script.map8
-rw-r--r--third_party/heimdal/lib/ipc/Makefile.am4
-rw-r--r--third_party/heimdal/lib/ipc/server.c11
-rw-r--r--third_party/heimdal/lib/kadm5/Makefile.am5
-rw-r--r--third_party/heimdal/lib/kadm5/create_s.c6
-rw-r--r--third_party/heimdal/lib/kadm5/fuzz-inputs-bin/test_marshall-ent0.binbin0 -> 191 bytes
-rw-r--r--third_party/heimdal/lib/kadm5/fuzz-inputs-bin/test_marshall-ent1.binbin0 -> 139 bytes
-rw-r--r--third_party/heimdal/lib/kadm5/fuzz-inputs-packed/test_marshall-ent0.binbin0 -> 65 bytes
-rw-r--r--third_party/heimdal/lib/kadm5/fuzz-inputs-packed/test_marshall-ent1.binbin0 -> 46 bytes
-rw-r--r--third_party/heimdal/lib/kadm5/fuzz-inputs-txt/test_marshall-ent0.txt101
-rw-r--r--third_party/heimdal/lib/kadm5/fuzz-inputs-txt/test_marshall-ent1.txt54
-rw-r--r--third_party/heimdal/lib/kadm5/get_princs_c.c14
-rw-r--r--third_party/heimdal/lib/kadm5/ipropd_master.c59
-rw-r--r--third_party/heimdal/lib/kadm5/log.c24
-rw-r--r--third_party/heimdal/lib/kadm5/marshall.c492
-rw-r--r--third_party/heimdal/lib/kadm5/version-script-client.map3
-rw-r--r--third_party/heimdal/lib/krb5/aes-test.c6
-rw-r--r--third_party/heimdal/lib/krb5/aname_to_localname.c3
-rw-r--r--third_party/heimdal/lib/krb5/context.c2
-rw-r--r--third_party/heimdal/lib/krb5/crypto-evp.c7
-rw-r--r--third_party/heimdal/lib/krb5/dcache.c13
-rw-r--r--third_party/heimdal/lib/krb5/fast.c13
-rw-r--r--third_party/heimdal/lib/krb5/fcache.c2
-rw-r--r--third_party/heimdal/lib/krb5/get_host_realm.c28
-rw-r--r--third_party/heimdal/lib/krb5/init_creds_pw.c75
-rw-r--r--third_party/heimdal/lib/krb5/kcm.c2
-rw-r--r--third_party/heimdal/lib/krb5/krb5.conf.520
-rw-r--r--third_party/heimdal/lib/krb5/krb5_locl.h1
-rw-r--r--third_party/heimdal/lib/krb5/krbhst.c9
-rw-r--r--third_party/heimdal/lib/krb5/libkrb5-exports.def.in2
-rw-r--r--third_party/heimdal/lib/krb5/pac.c26
-rw-r--r--third_party/heimdal/lib/krb5/pkinit-ec.c73
-rw-r--r--third_party/heimdal/lib/krb5/pkinit.c75
-rw-r--r--third_party/heimdal/lib/krb5/principal.c12
-rw-r--r--third_party/heimdal/lib/krb5/rd_req.c9
-rw-r--r--third_party/heimdal/lib/krb5/recvauth.c5
-rw-r--r--third_party/heimdal/lib/krb5/salt-aes-sha2.c5
-rw-r--r--third_party/heimdal/lib/krb5/salt-des.c3
-rw-r--r--third_party/heimdal/lib/krb5/salt-des3.c3
-rw-r--r--third_party/heimdal/lib/krb5/scache.c3
-rw-r--r--third_party/heimdal/lib/krb5/sendauth.c20
-rw-r--r--third_party/heimdal/lib/krb5/store.c37
-rw-r--r--third_party/heimdal/lib/krb5/store_emem.c20
-rw-r--r--third_party/heimdal/lib/krb5/store_fd.c2
-rw-r--r--third_party/heimdal/lib/krb5/store_mem.c4
-rw-r--r--third_party/heimdal/lib/krb5/store_sock.c9
-rw-r--r--third_party/heimdal/lib/krb5/store_stdio.c9
-rw-r--r--third_party/heimdal/lib/krb5/version-script.map2
-rw-r--r--third_party/heimdal/lib/otp/otp_db.c2
-rw-r--r--third_party/heimdal/lib/roken/Makefile.am3
-rw-r--r--third_party/heimdal/lib/roken/base32.c6
-rw-r--r--third_party/heimdal/lib/roken/base64.c26
-rw-r--r--third_party/heimdal/lib/roken/closefrom.c2
-rw-r--r--third_party/heimdal/lib/roken/dumpdata.c157
-rw-r--r--third_party/heimdal/lib/roken/getauxval.c12
-rw-r--r--third_party/heimdal/lib/roken/getifaddrs.c7
-rw-r--r--third_party/heimdal/lib/roken/hex.c8
-rw-r--r--third_party/heimdal/lib/roken/ifaddrs.hin4
-rw-r--r--third_party/heimdal/lib/roken/issuid.c8
-rw-r--r--third_party/heimdal/lib/roken/mergesort_r.c9
-rw-r--r--third_party/heimdal/lib/roken/mkdtemp.c3
-rw-r--r--third_party/heimdal/lib/roken/roken-common.h7
-rw-r--r--third_party/heimdal/lib/roken/roken.awk8
-rw-r--r--third_party/heimdal/lib/roken/roken.h.in80
-rw-r--r--third_party/heimdal/lib/roken/snprintf.c36
-rw-r--r--third_party/heimdal/lib/roken/socket.c5
-rw-r--r--third_party/heimdal/lib/roken/test-auxval.c17
-rw-r--r--third_party/heimdal/lib/roken/timeval.c4
-rw-r--r--third_party/heimdal/lib/roken/version-script.map3
-rw-r--r--third_party/heimdal/lib/roken/write_pid.c14
-rw-r--r--third_party/heimdal/lib/sl/sl.c39
-rw-r--r--third_party/heimdal/lib/wind/idn-lookup.c17
-rw-r--r--third_party/heimdal/packages/windows/sdk/NTMakefile1
-rw-r--r--third_party/heimdal/tests/bin/setup-env.in1
-rw-r--r--third_party/heimdal/tests/kdc/Makefile.am6
-rw-r--r--third_party/heimdal/tests/kdc/check-bx509.in275
-rw-r--r--third_party/heimdal/tests/kdc/check-fast.in12
-rw-r--r--third_party/heimdal/tests/kdc/check-httpkadmind.in103
-rw-r--r--third_party/heimdal/tests/kdc/check-pkinit.in5
-rw-r--r--third_party/heimdal/tests/kdc/krb5-bx509.conf.in5
-rw-r--r--third_party/heimdal/tests/kdc/krb5-httpkadmind.conf.in4
-rw-r--r--third_party/heimdal/tests/kdc/krb5-pkinit.conf.in4
-rw-r--r--third_party/heimdal/tests/plugin/kdc_test_plugin.c12
235 files changed, 5973 insertions, 2188 deletions
diff --git a/third_party/heimdal/.github/workflows/coverity.yml b/third_party/heimdal/.github/workflows/coverity.yml
index 5a175f52a8c..dfea060d04b 100644
--- a/third_party/heimdal/.github/workflows/coverity.yml
+++ b/third_party/heimdal/.github/workflows/coverity.yml
@@ -8,7 +8,7 @@ on:
jobs:
linux:
- if: secrets.COVERITY_SCAN_TOKEN != ''
+ #if: ${{ secrets.COVERITY_SCAN_TOKEN }} != ''
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
@@ -32,8 +32,9 @@ jobs:
- name: Download Coverity Build Tool
env:
TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
+ PROJECT: ${{ secrets.COVERITY_SCAN_PROJECT }}
run: |
- wget -q https://scan.coverity.com/download/cxx/linux64 --post-data "token=$TOKEN&project=ruby" -O cov-analysis-linux64.tar.gz
+ wget -q https://scan.coverity.com/download/cxx/linux64 --post-data "token=$TOKEN&project=$PROJECT" -O cov-analysis-linux64.tar.gz
mkdir cov-analysis-linux64
tar xzf cov-analysis-linux64.tar.gz --strip 1 -C cov-analysis-linux64
- name: Build
@@ -43,6 +44,7 @@ jobs:
CONFIGURE_OPTS: ${{ matrix.configureopts }}
run: |
/bin/sh ./autogen.sh
+ export PATH="$PWD/cov-analysis-linux64/bin:$PATH"
mkdir build
cd build
../configure --srcdir=`dirname "$PWD"` --enable-maintainer-mode --enable-developer --with-ldap $CONFIGURE_OPTS --prefix=$HOME/inst CFLAGS="-Wno-error=shadow -Wno-error=bad-function-cast -Wno-error=unused-function -Wno-error=unused-result -Wno-error=deprecated-declarations"
@@ -50,19 +52,17 @@ jobs:
# We don't want to scan-build libedit nor SQLite3 because ETOOSLOW
(cd lib/libedit && make -j4)
(cd lib/sqlite && make -j4)
- export PATH=`pwd`/cov-analysis-linux64/bin:$PATH
cov-build --dir cov-int make -j4
+ tar czvf ../heimdal.tgz cov-int
- name: Submit the result to Coverity Scan
env:
TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
EMAIL: ${{ secrets.COVERITY_SCAN_EMAIL }}
PROJECT: ${{ secrets.COVERITY_SCAN_PROJECT }}
run: |
- tar czvf heimdal.tgz cov-int
curl \
- --form project=ruby \
- --form token=$TOKEN \
- --form email=$EMAIL \
- --form file=@heimdal.tgz \
- --form version=trunk \
- --form description="`./ruby -v`" "https://scan.coverity.com/builds?project=$PROJECT"
+ --form "token=$TOKEN" \
+ --form "email=$EMAIL" \
+ --form "file=@heimdal.tgz" \
+ --form version="$(git rev-parse HEAD)" \
+ --form description="$GITHUB_REF / $GITHUB_SHA" "https://scan.coverity.com/builds?project=$PROJECT"
diff --git a/third_party/heimdal/.github/workflows/linux-mit-interop.yml b/third_party/heimdal/.github/workflows/linux-mit-interop.yml
new file mode 100644
index 00000000000..72648ee2ce0
--- /dev/null
+++ b/third_party/heimdal/.github/workflows/linux-mit-interop.yml
@@ -0,0 +1,117 @@
+name: Linux Build
+
+on:
+ push:
+ branches:
+ - 'interop-mit*'
+
+jobs:
+ unix:
+ runs-on: ${{ matrix.os }}
+ strategy:
+ fail-fast: false
+ matrix:
+ name: [linux-clang]
+ include:
+ - name: linux-clang
+ os: ubuntu-18.04
+ compiler: clang
+ cflags: ''
+ steps:
+ - name: Clone repository
+ uses: actions/checkout@v1
+ - name: Checkout MIT
+ uses: actions/checkout@v3
+ with:
+ repository: krb5/krb5
+ path: mit
+ - name: Install Heimdal dependencies
+ run: |
+ sudo apt-get update -qq
+ sudo apt-get install -y bison comerr-dev flex doxygen
+ sudo apt-get install -y libcap-ng-dev libdb-dev libedit-dev libjson-perl
+ sudo apt-get install -y libldap2-dev libncurses5-dev libperl4-corelibs-perl
+ sudo apt-get install -y libsqlite3-dev libkeyutils-dev pkg-config python
+ sudo apt-get install -y ss-dev texinfo unzip netbase keyutils ldap-utils
+ sudo apt-get install -y gdb apport curl libmicrohttpd-dev jq valgrind
+ - name: Install MIT Kerberos dependencies
+ run: |
+ sudo apt-get install -y gettext libcmocka-dev libresolv-wrapper libsasl2-dev libssl-dev python3-kdcproxy python3-pip slapd tcsh
+ pip3 install pyrad
+ # Temporary workaround for:
+ # https://github.com/actions/virtual-environments/issues/3185
+ sudo hostname localhost
+ - name: Build MIT
+ env:
+ CC: ${{ matrix.compiler }}
+ MAKEVARS: ${{ matrix.makevars }}
+ run: |
+ cd mit/src
+ autoreconf
+ ./configure --enable-maintainer-mode --with-ldap --with-crypto-impl=openssl --prefix=$HOME/mitkrb5
+ make -j4 $MAKEVARS
+ make install
+ - name: Build
+ env:
+ CC: ${{ matrix.compiler }}
+ MAKEVARS: ${{ matrix.makevars }}
+ run: |
+ /bin/sh ./autogen.sh
+ mkdir build
+ cd build
+ ../configure --srcdir=`dirname "$PWD"` --enable-maintainer-mode --enable-developer --with-ldap $CONFIGURE_OPTS --prefix=$HOME/inst CFLAGS="${{ matrix.cflags }} -Wno-error=shadow -Wno-error=bad-function-cast -Wno-error=unused-function -Wno-error=unused-result -Wno-error=deprecated-declarations" --with-mitkrb5=$HOME/mitkrb5
+ make -j4
+ - name: Test
+ env:
+ CC: ${{ matrix.compiler }}
+ MAKEVARS: ${{ matrix.makevars }}
+ run: |
+ cd build
+ ulimit -c unlimited
+ make check
+ - name: Make Install
+ env:
+ CC: ${{ matrix.compiler }}
+ MAKEVARS: ${{ matrix.makevars }}
+ run: |
+ cd build || true
+ make DESTDIR=/tmp/h5l install
+ cd /tmp/h5l
+ tar czf $HOME/heimdal-install-linux-${{ matrix.compiler }}.tgz .
+ - name: Core dump stacks
+ run: |
+ echo "thread apply all bt" > /tmp/x
+ find . -name core -print | while read core; do gdb -batch -x x `file "$core"|sed -e "s/^[^']*'//" -e "s/[ '].*$//"` "$core"; done
+ if [ "$(find . -name core -print | wc -l)" -gt 0 ]; then false; fi
+ - name: Test logs
+ run: |
+ find build -depth -name \*.trs | xargs grep -lw FAIL | sed -e 's/trs$/log/' | tar -czf $HOME/logs-linux-${{ matrix.compiler }}.tgz --verbatim-files-from --files-from -
+ find build -name \*.trs | xargs grep -lw FAIL | sed -e 's/trs$/log/' | xargs cat
+ - name: Failed Test logs
+ if: ${{ failure() }}
+ run: |
+ find build -name \*.trs | xargs grep -lw FAIL | sed -e 's/trs$/log/' | xargs cat
+ - name: Make Dist
+ run: |
+ cd build
+ make dist
+ make distclean
+ if [ "$(git ls-files -o|grep -v ^build/ | wc -l)" -ne 0 ]; then
+ echo "Files not removed by make distclean:"
+ git ls-files -o|grep -v ^build/
+ fi
+ - name: Upload Install Tarball
+ uses: actions/upload-artifact@v2
+ with:
+ name: Install Tarball
+ path: '~/heimdal-install-linux-${{ matrix.compiler }}.tgz'
+ - name: Upload Dist Tarball
+ uses: actions/upload-artifact@v2
+ with:
+ name: Dist Tarball
+ path: 'build/heimdal-*.tar.gz'
+ - name: Upload Logs Tarball
+ uses: actions/upload-artifact@v2
+ with:
+ name: Test Logs
+ path: '~/logs-linux-${{ matrix.compiler }}.tgz'
diff --git a/third_party/heimdal/.github/workflows/ubsan.yml b/third_party/heimdal/.github/workflows/ubsan.yml
new file mode 100644
index 00000000000..d4bb2eda476
--- /dev/null
+++ b/third_party/heimdal/.github/workflows/ubsan.yml
@@ -0,0 +1,133 @@
+name: Linux UBSAN Build
+
+on:
+ push:
+ branches:
+ - 'master'
+ - 'ubsan'
+ paths:
+ - '!docs/**'
+ - '!**.md'
+ - '!**.[1-9]'
+ - '**.[chly]'
+ - '**.hin'
+ - '**.in'
+ - '**.am'
+ - '**.m4'
+ - '**.ac'
+ - '**.pl'
+ - '**.py'
+ - '**.asn1'
+ - '**.opt'
+ - '**/COPYING'
+ - '**/INSTALL'
+ - '**/README*'
+ - '.github/workflows/ubsan.yml'
+ - '!appveyor.yml'
+ - '!.travis.yml'
+
+ pull_request:
+ paths:
+ - '!docs/**'
+ - '!**.md'
+ - '!**.[1-9]'
+ - '**.[chly]'
+ - '**.hin'
+ - '**.in'
+ - '**.am'
+ - '**.m4'
+ - '**.ac'
+ - '**.pl'
+ - '**.py'
+ - '**.asn1'
+ - '**.opt'
+ - '**/COPYING'
+ - '**/INSTALL'
+ - '**/README*'
+ - '.github/workflows/ubsan.yml'
+ - '!appveyor.yml'
+ - '!.travis.yml'
+
+jobs:
+ unix:
+ runs-on: ${{ matrix.os }}
+ strategy:
+ fail-fast: false
+ matrix:
+ name: [linux-clang, linux-gcc]
+ include:
+ - name: linux-clang
+ os: ubuntu-18.04
+ compiler: clang
+ cflags: '-fsanitize=undefined'
+ ldflags: ''
+ - name: linux-gcc
+ os: ubuntu-18.04
+ compiler: gcc
+ cflags: '-Wnonnull -fsanitize=undefined'
+ ldflags: ''
+ steps:
+ - name: Clone repository
+ uses: actions/checkout@v1
+ - name: Install packages
+ if: startsWith(matrix.os, 'ubuntu')
+ run: |
+ sudo apt-get update -qq
+ sudo apt-get install -y bison comerr-dev flex doxygen
+ sudo apt-get install -y libcap-ng-dev libdb-dev libedit-dev libjson-perl
+ sudo apt-get install -y libldap2-dev libncurses5-dev libperl4-corelibs-perl
+ sudo apt-get install -y libsqlite3-dev libkeyutils-dev pkg-config python
+ sudo apt-get install -y ss-dev texinfo unzip netbase keyutils ldap-utils
+ sudo apt-get install -y gdb apport curl libmicrohttpd-dev jq valgrind
+ # Temporary workaround for:
+ # https://github.com/actions/virtual-environments/issues/3185
+ sudo hostname localhost
+ - name: Build
+ env:
+ CC: ${{ matrix.compiler }}
+ MAKEVARS: ${{ matrix.makevars }}
+ run: |
+ /bin/sh ./autogen.sh
+ mkdir build
+ cd build
+ ../configure --srcdir=`dirname "$PWD"` --enable-maintainer-mode --enable-developer --enable-dynamic --disable-static --with-ldap $CONFIGURE_OPTS --prefix=$HOME/inst CFLAGS="${{ matrix.cflags }} -Wno-error=shadow -Wno-error=bad-function-cast -Wno-error=unused-function -Wno-error=unused-result -Wno-error=deprecated-declarations" LDFLAGS="${{ matrix.ldflags }}"
+ make -j4
+ - name: Test
+ env:
+ CC: ${{ matrix.compiler }}
+ MAKEVARS: ${{ matrix.makevars }}
+ run: |
+ cd build
+ ulimit -c unlimited
+ make check
+ - name: Make Install
+ env:
+ CC: ${{ matrix.compiler }}
+ MAKEVARS: ${{ matrix.makevars }}
+ run: |
+ cd build || true
+ make DESTDIR=/tmp/h5l install
+ cd /tmp/h5l
+ tar czf $HOME/heimdal-install-linux-${{ matrix.compiler }}.tgz .
+ - name: Core dump stacks
+ run: |
+ echo "thread apply all bt" > /tmp/x
+ find . -name core -print | while read core; do gdb -batch -x x `file "$core"|sed -e "s/^[^']*'//" -e "s/[ '].*$//"` "$core"; done
+ if [ "$(find . -name core -print | wc -l)" -gt 0 ]; then false; fi
+ - name: Test logs
+ run: |
+ find build -depth -name \*.trs | xargs grep -lw FAIL | sed -e 's/trs$/log/' | tar -czf $HOME/logs-linux-${{ matrix.compiler }}.tgz --verbatim-files-from --files-from -
+ find build -name \*.trs | xargs grep -lw FAIL | sed -e 's/trs$/log/' | xargs cat
+ - name: Failed Test logs
+ if: ${{ failure() }}
+ run: |
+ find build -name \*.trs | xargs grep -lw FAIL | sed -e 's/trs$/log/' | xargs cat
+ - name: All Test logs
+ if: true
+ run: |
+ find build -name \*.trs | sed -e 's/trs$/log/' | xargs cat
+ - name: Upload Logs Tarball
+ uses: actions/upload-artifact@v2
+ with:
+ name: Test Logs
+ path: '~/logs-linux-${{ matrix.compiler }}.tgz'
diff --git a/third_party/heimdal/NEWS b/third_party/heimdal/NEWS
index 79efe803a78..4bb5a703778 100644
--- a/third_party/heimdal/NEWS
+++ b/third_party/heimdal/NEWS
@@ -1,3 +1,345 @@
+
+Partial news for a future Heimdal 8.0 release -- but NOTE WELL that this is NOT
+a release at this time!
+
+Bug fixes
+
+ - Errors found by the Coverity static analysis.
+ - Errors found by the LLVM scan-build static analyzer.
+ - Errors found by the valgrind memory debugger.
+ - Fix out-of-tree SQLite3 ccache permissions / umask issues.
+ - iprop bugs, race conditions, and performance
+ - Many misc. bugs
+
+Features:
+
+ - KDC: Add FAST support for TGS.
+ - KDC: Greatly improved plugin facility for Samba.
+ - KDC: Add httpkadmind service providing a subset of kadmin
+ functionality over HTTP.
+ - KDC: Add support for virtual service principal namespaces.
+ - KDC: Add support for synthetic client principals that exist if the
+ pre-authentication mechanism (e.g., PKINIT) can authenticate
+ them, thus not requiring an HDB entry.
+ - KDC: Add experimental GSS-API pre-authentication support.
+ - KDC: Revamp and enhance kx509 support (though bx509d mostly replaces kx509).
+ - KDC: Better support for aliases and referrals.
+ - KDC: Always return the salt in the PA-ETYPE-INFO[2].
+ - KDC: Add warn_ticket_addresses configuration parameter.
+ - KDC: allow anonymous AS requests with long-term keys.
+ - KDC: Do not include PAC for anonymous AS requests.
+ - KDC: Enable keepalive mode on incoming sockets.
+ - KDC: Greatly improved logging.
+ - KDC: Remove KRB5SignedPath, to be replaced with PAC.
+ - PKIX: Add bx509d -- an online certification authority (CA) with an HTTP API.
+ - kadmin: Add HTTP-based kadmin protocol.
+ - kadmin: Add add_alias, del_alias.
+ - kadmin: Add command aliases to man page.
+ - kadmin: Add disallow-client attribute.
+ - kadmin: add --hdb / -H argument.
+ - kadmin: Allow enforcing password quality on admin password change.
+ - kadmin: Improve ext_keytab usage.
+ - kadmin: Selective pruning of historic key for principal.
+ - krb5: Add client_aware_channel_bindings option.
+ - krb5: Add constrained credential delegation option "destination TGT"
+ - krb5: Add "EFILE:" target for logging.
+ - krb5: Add include/includedir directives for krb5.conf.
+ - krb5: Complete DIR ccache collection support.
+ - krb5: Add FILE ccache collection support.
+ - krb5: Improved FILE ccache performance.
+ - krb5: Add KEYRING ccache support.
+ - krb5: Add kx509 client.
+ - krb5: Improve FILE keytab performance.
+ - krb5: Implement KRB5_TRACE environment variable.
+ - krb5: Add experimental name canonicalization rules configuration.
+ - krb5: Support start_realm ccconfig entry type.
+ - kinit: Add --default-for option for ccache collection support.
+ - kinit: Add --pk-anon-fast-armor option.
+ - kinit: Don't leave dangling temporary ccaches.
+ - klist: Better --json
+ - iprop: Many performance and scaling enhancements.
+ - iprop: Support hierarchical propagation.
+ - ASN.1: Document fuzzing process.
+ - ASN.1: Complete template backend.
+ - ASN.1: Add partial Information Object System support (template backend
+ only). This means that open type holes can be decoded recursively
+ with one codec function call.
+ - ASN.1: Add JSON encoder functionality (template backend only).
+ - ASN.1: Greatly enhanced asn1_print(1) command, which can now print a
+ JSON representation of any DER-encoded value of any type exported
+ by ASN.1 modules in Heimdal.
+ - ASN.1: Support circular types.
+ - ASN.1: Topographically sort declarations.
+ - ASN.1: Proper support for IMPLICIT tags.
+ - GSS: Import gss-token(1) command.
+ - GSS: Add advanced credential store / load functionality.
+ - GSS: Add name attributes support, with support for many basic attributes
+ and PAC buffer accessors too.
+ - GSS: Add SANON mechanism for anonymous-only key exchange using
+ elliptic curve Diffie-Hellman (ECDH) with Curve25519.
+ - GSS: Add gss_acquire_cred_from() and credential store extensions.
+ - GSS: Support fragmented tokens reassembly (for SMB).
+ - GSS: Support client keytab.
+ - GSS: Add NegoEx support.
+ - libhx509: Lots of improvements.
+ - hxtool: Add "acert" (assert cert contents) command
+ - hxtool: add cert type: https-negotiate-server
+ - hxtool: add generate-key command
+ - hxtool: Add OID symbol resolution and printing of OIDs known to hxtool.
+ - hxtool: Add print --raw-json option that shows certificates in JSON, with
+ all extensions and attributes known to Heimdal fully decoded.
+ - hxtool: Improved SAN support.
+ - hxtool: Improved CSR support.
+ - Improved plugin interfaces.
+ - hcrypto: Add X25519.
+ - hcrypto: Better RSA key generation.
+ - hcrypto: import libtommath v1.2.0.
+ - roken: Add secure_getenv() and issuid(), use them extensively.
+
+Release Notes - Heimdal - Version Heimdal 7.8
+
+ Bug fixes
+
+ - CVE-2022-42898 PAC parse integer overflows
+
+ - CVE-2022-3437 Overflows and non-constant time leaks in DES{,3} and arcfour
+ - Pass correct length to _gssapi_verify_pad()
+ - Check for overflow in _gsskrb5_get_mech()
+ - Check buffer length against overflow for DES{,3} unwrap
+ - Check the result of _gsskrb5_get_mech()
+ - Avoid undefined behaviour in _gssapi_verify_pad()
+ - Don't pass NULL pointers to memcpy() in DES unwrap
+ - Use constant-time memcmp() in unwrap_des3()
+ - Use constant-time memcmp() for arcfour unwrap
+
+ - CVE-2021-44758 NULL dereference DoS in SPNEGO acceptors
+
+ - CVE-2022-44640 Heimdal KDC: invalid free in ASN.1 codec
+
+ This is a 10.0 on the Common Vulnerability Scoring System (CVSS) v3.
+
+ Heimdal's ASN.1 compiler generates code that allows specially
+ crafted DER encodings of CHOICEs to invoke the wrong free function
+ on the decoded structure upon decode error. This is known to impact
+ the Heimdal KDC, leading to an invalid free() of an address partly
+ or wholly under the control of the attacker, in turn leading to a
+ potential remote code execution (RCE) vulnerability.
+
+ This error affects the DER codec for all CHOICE types used in
+ Heimdal, though not all cases will be exploitable. We have not
+ completed a thorough analysis of all the Heimdal components
+ affected, thus the Kerberos client, the X.509 library, and other
+ parts, may be affected as well.
+
+ This bug has been in Heimdal since 2005. It was first reported by
+ Douglas Bagnall, though it had been found independently by the
+ Heimdal maintainers via fuzzing.
+
+ While no zero-day exploit is known, such an exploit will likely be
+ available soon after public disclosure.
+
+ - Errors found by the LLVM scan-build static analyzer.
+
+ - Errors found by the valgrind memory debugger.
+
+ - Work around GCC Bug 95189 (memcmp wrongly stripped like strcmp).
+
+ - Fix Unicode normalization read of 1 bytes past end of array.
+
+ - Correct ASN.1 OID typo for SHA-384
+
+ - Fix a deadlock in in the MEMORY ccache type.
+
+ - TGS: strip forwardable and proxiable flags if the server is
+ disallowed.
+
+ - CVE-2019-14870: Validate client attributes in protocol-transition
+ - CVE-2019-14870: Apply forwardable policy in protocol-transition
+ - CVE-2019-14870: Always lookup impersonate client in DB
+
+ - Incremental HDB propagation improvements
+
+ - Refactor send_diffs making it progressive
+ - Handle partial writes on non-blocking sockets
+ - Disable Nagle in iprop master and slave
+ - Use async I/O
+ - Don't send I_HAVE in response to AYT
+ - Do not recover log in kadm5_get_principal()
+ - Don't send diffs to slaves with not yet known version
+ - Don't stutter in send_diffs
+
+ - Optional backwards-compatible anon-pkinit behaviour
+
+Release Notes - Heimdal - Version Heimdal 7.7
+
+ Bug fixes
+
+ - PKCS#11 hcrypto back-end
+ . initialize the p11_module_load function list
+ . verify that not only is a mechanism present but that its mechanism
+ info states that it offers the required encryption, decryption or
+ digest services
+ - krb5:
+ . Starting with 7.6, Heimdal permitted requesting authenticated
+ anonymous tickets. However, it did not verify that a KDC in fact
+ returned an anonymous ticket when one was requested.
+ - Cease setting the KDCOption reaquest_anonymous flag when issuing
+ S4UProxy (constrained delegation) TGS requests.
+ . when the Win2K PKINIT compatibility option is set, do
+ not require krbtgt otherName to match when validating KDC
+ certificate.
+ . set PKINIT_BTMM flag per Apple implementation
+ . use memset_s() instead of memset()
+ - kdc:
+ . When generating KRB5SignedPath in the AS, use the reply client name
+ rather than the one from the request, so validation will work
+ correctly in the TGS.
+ . allow checksum of PA-FOR-USER to be HMAC_MD5. Even if tgt used
+ an enctype with a different checksum. Per [MS-SFU] 2.2.1
+ PA-FOR-USER the checksum is always HMAC_MD5, and that's what
+ Windows and MIT clients send.
+
+ In heimdal both the client and kdc use instead the
+ checksum of the tgt, and therefore work with each other
+ but Windows and MIT clients fail against heimdal KDC.
+
+ Both Windows and MIT KDCs would allow any keyed checksum
+ to be used so Heimdal client interoperates with them.
+
+ Change Heimdal KDC to allow HMAC_MD5 even for non RC4
+ based tgt in order to support per-spec clients.
+ . use memset_s() instead of memset().
+ - Detect Heimdal 1.0 through 7.6 clients that issue S4UProxy
+ (constrained delegation) TGS Requests with the request
+ anonymous flag set. These requests will be treated as
+ S4UProxy requests and not anonymous requests.
+ - HDB:
+ . Set SQLite3 backend default page size to 8KB.
+ . Add hdb_set_sync() method
+ - kadmind:
+ . disable HDB sync during database load avoiding unnecessary disk i/o.
+ - ipropd:
+ . disable HDB sync during receive_everything. Doing an fsync
+ per-record when receiving the complete HDB is a performance
+ disaster. Among other things, if the HDB is very large, then
+ one slave receving a full HDB can cause other slaves to timeout
+ and, if HDB write activity is high enough to cause iprop log
+ truncation, then also need full syncs, which leads to a cycle of
+ full syncs for all slaves until HDB write activity drops.
+ Allowing the iprop log to be larger helps, but improving
+ receive_everything() performance helps even more.
+ - kinit:
+ . Anonymous PKINIT tickets discard the realm information used
+ to locate the issuing AS. Store the issuing realm in the
+ credentials cache in order to locate a KDC which can renew them.
+ . Do not leak the result of krb5_cc_get_config() when determining
+ anonymous PKINIT start realm.
+ - klist:
+ . Show transited-policy-checked, ok-as-delegate and anonymous
+ flags when listing credentials.
+ - tests:
+ . Regenerate certs so that they expire before the 2038 armageddon
+ so the test suite will pass on 32-bit operating systems until the
+ underlying issues can be resolved.
+ - Solaris:
+ . Define _STDC_C11_BCI for memset_s prototype
+ - build tooling:
+ . Convert from python 2 to python 3
+ - documentation
+ . rename verify-password to verify-password-quality
+ . hprop default mode is encrypt
+ . kadmind "all" permission does not include "get-keys"
+ . verify-password-quality might not be stateless
+
+Release Notes - Heimdal - Version Heimdal 7.6
+
+ Security
+
+ - CVE-2018-16860 Heimdal KDC: Reject PA-S4U2Self with unkeyed checksum
+
+ When the Heimdal KDC checks the checksum that is placed on the
+ S4U2Self packet by the server to protect the requested principal
+ against modification, it does not confirm that the checksum
+ algorithm that protects the user name (principal) in the request
+ is keyed. This allows a man-in-the-middle attacker who can
+ intercept the request to the KDC to modify the packet by replacing
+ the user name (principal) in the request with any desired user
+ name (principal) that exists in the KDC and replace the checksum
+ protecting that name with a CRC32 checksum (which requires no
+ prior knowledge to compute).
+
+ This would allow a S4U2Self ticket requested on behalf of user
+ name (principal) user@EXAMPLE.COM to any service to be changed
+ to a S4U2Self ticket with a user name (principal) of
+ Administrator@EXAMPLE.COM. This ticket would then contain the
+ PAC of the modified user name (principal).
+
+ - CVE-2019-12098, client-only:
+
+ RFC8062 Section 7 requires verification of the PA-PKINIT-KX key excahnge
+ when anonymous PKINIT is used. Failure to do so can permit an active
+ attacker to become a man-in-the-middle.
+
+ Bug fixes
+
+ - Happy eyeballs: Don't wait for responses from known-unreachable KDCs.
+ - kdc: check return copy_Realm, copy_PrincipalName, copy_EncryptionKey
+ - kinit:
+ . cleanup temporary ccaches
+ . see man page for "kinit --anonymous" command line syntax change
+ - kdc: Make anonymous AS-requests more RFC8062-compliant.
+ - Updated expired test certificates
+ - Solaris:
+ . PKCS#11 hcrypto backend broken since 7.0.1
+ . Building with Sun Pro C
+
+ Features
+
+ - kuser: support authenticated anonymous AS-REQs in kinit
+ - kdc: support for anonymous TGS-REQs
+ - kgetcred support for anonymous service tickets
+ - Support builds with OpenSSL 1.1.1
+
+Release Notes - Heimdal - Version Heimdal 7.5
+
+ Security
+
+ - Fix CVE-2017-17439, which is a remote denial of service
+ vulnerability:
+
+ In Heimdal 7.1 through 7.4, remote unauthenticated attackers
+ are able to crash the KDC by sending a crafted UDP packet
+ containing empty data fields for client name or realm.
+
+ Bug fixes
+
+ - Handle long input lines when reloading database dumps.
+
+ - In pre-forked mode (default on Unix), correctly clear
+ the process ids of exited children, allowing new child processes
+ to replace the old.
+
+ - Fixed incorrect KDC response when no-cross realm TGT exists,
+ allowing client requests to fail quickly rather than time
+ out after trying to get a correct answer from each KDC.
+
+Release Notes - Heimdal - Version Heimdal 7.4
+
+ Security
+
+ - Fix CVE-2017-11103: Orpheus' Lyre KDC-REP service name validation
+
+ This is a critical vulnerability.
+
+ In _krb5_extract_ticket() the KDC-REP service name must be obtained from
+ encrypted version stored in 'enc_part' instead of the unencrypted version
+ stored in 'ticket'. Use of the unecrypted version provides an
+ opportunity for successful server impersonation and other attacks.
+
+ Identified by Jeffrey Altman, Viktor Duchovni and Nico Williams.
+
+ See https://www.orpheus-lyre.info/ for more details.
+
Release Notes - Heimdal - Version Heimdal 7.3
Security
diff --git a/third_party/heimdal/admin/NTMakefile b/third_party/heimdal/admin/NTMakefile
index 06f90c9fdbf..f78a201a801 100644
--- a/third_party/heimdal/admin/NTMakefile
+++ b/third_party/heimdal/admin/NTMakefile
@@ -49,6 +49,7 @@ KTUTIL_OBJS= \
$(OBJ)\rename.obj
KTUTIL_LIBS= \
+ $(LIBHEIMBASE) \
$(LIBHEIMDAL) \
$(LIBKADM5SRV) \
$(LIBSL) \
diff --git a/third_party/heimdal/admin/add.c b/third_party/heimdal/admin/add.c
index 5f1920ff8be..3fba3913881 100644
--- a/third_party/heimdal/admin/add.c
+++ b/third_party/heimdal/admin/add.c
@@ -278,6 +278,7 @@ json2keytab_entry(heim_dict_t d, krb5_keytab kt, size_t idx)
(unsigned long)idx);
bad:
krb5_free_principal(context, e.principal);
+ free(buf);
}
int
@@ -296,6 +297,7 @@ kt_import(void *opt, int argc, char **argv)
err(1, "Could not open file %s", argv[0]);
json = read_file(f);
+ fclose(f);
o = heim_json_create(json, 10, flags, &json_err);
free(json);
if (o == NULL) {
diff --git a/third_party/heimdal/admin/get.c b/third_party/heimdal/admin/get.c
index ecd6f6a160e..1c0a6333a5a 100644
--- a/third_party/heimdal/admin/get.c
+++ b/third_party/heimdal/admin/get.c
@@ -109,6 +109,7 @@ parse_enctypes(struct get_options *opt,
free(s);
return krb5_enomem(context);
}
+ free(s);
s = tmp;
}
ret = krb5_string_to_keysalts2(context, s, nks, ks);
@@ -165,7 +166,7 @@ kt_get(struct get_options *opt, int argc, char **argv)
kadm5_principal_ent_rec princ;
int mask = 0;
krb5_keyblock *keys;
- int n_keys;
+ int n_keys = 0;
int created = 0;
krb5_keytab_entry entry;
diff --git a/third_party/heimdal/admin/list.c b/third_party/heimdal/admin/list.c
index 9d1e9d5d483..22ccdcac8cb 100644
--- a/third_party/heimdal/admin/list.c
+++ b/third_party/heimdal/admin/list.c
@@ -233,7 +233,6 @@ do_list1_json(struct list_options *opt,
}
heim_dict_set_value(d, HSTR("aliases"), aliases);
heim_release(aliases);
- free(s);
}
krb5_kt_free_entry(context, &entry);
diff --git a/third_party/heimdal/appl/gssmask/common.c b/third_party/heimdal/appl/gssmask/common.c
index 8d7d8fa2252..733db9013eb 100644
--- a/third_party/heimdal/appl/gssmask/common.c
+++ b/third_party/heimdal/appl/gssmask/common.c
@@ -55,7 +55,7 @@ add_list(char ****list, size_t *listlen, char **str, size_t len)
size_t i;
*list = erealloc(*list, sizeof(**list) * (*listlen + 1));
- (*list)[*listlen] = ecalloc(len, sizeof(**list));
+ (*list)[*listlen] = ecalloc(len, sizeof(***list));
for (i = 0; i < len; i++)
(*list)[*listlen][i] = str[i];
(*listlen)++;
diff --git a/third_party/heimdal/appl/test/gssapi_server.c b/third_party/heimdal/appl/test/gssapi_server.c
index baf13ecff5f..74ceb3bee2e 100644
--- a/third_party/heimdal/appl/test/gssapi_server.c
+++ b/third_party/heimdal/appl/test/gssapi_server.c
@@ -192,6 +192,9 @@ proto (int sock, const char *service)
gss_OID mech_oid;
char *mech, *p;
+ memset(&remote, 0, sizeof(remote));
+ local = remote;
+
addrlen = sizeof(local);
if (getsockname (sock, (struct sockaddr *)&local, &addrlen) < 0
|| addrlen != sizeof(local))
diff --git a/third_party/heimdal/appl/test/http_client.c b/third_party/heimdal/appl/test/http_client.c
index 24c4e6e2d06..88a8fee35e5 100644
--- a/third_party/heimdal/appl/test/http_client.c
+++ b/third_party/heimdal/appl/test/http_client.c
@@ -316,6 +316,7 @@ main(int argc, char **argv)
argc -= optind;
argv += optind;
+ memset(&req, 0, sizeof(req));
mech_oid = select_mech(mech);
if (argc != 1 && argc != 2)
@@ -346,6 +347,9 @@ main(int argc, char **argv)
}
num_headers = 0;
+ if (req.response == NULL)
+ errx(1, "Got no response");
+
if (strstr(req.response, " 200 ") != NULL) {
print_body = 1;
done = 1;
diff --git a/third_party/heimdal/cf/broken-realloc.m4 b/third_party/heimdal/cf/broken-realloc.m4
index b6d962aceba..a397e96882e 100644
--- a/third_party/heimdal/cf/broken-realloc.m4
+++ b/third_party/heimdal/cf/broken-realloc.m4
@@ -19,7 +19,9 @@ int main(int argc, char **argv)
if test "$ac_cv_func_realloc_broken" = yes ; then
AC_DEFINE(BROKEN_REALLOC, 1, [Define if realloc(NULL) doesn't work.])
fi
-AH_BOTTOM([#ifdef BROKEN_REALLOC
-#define realloc(X, Y) rk_realloc((X), (Y))
-#endif])
+dnl AH_BOTTOM([#ifdef BROKEN_REALLOC
+dnl #ifndef realloc
+dnl #define realloc(X, Y) rk_realloc((X), (Y))
+dnl #endif
+dnl #endif])
])
diff --git a/third_party/heimdal/cf/crypto.m4 b/third_party/heimdal/cf/crypto.m4
index b8b011dd154..a8ef5198411 100644
--- a/third_party/heimdal/cf/crypto.m4
+++ b/third_party/heimdal/cf/crypto.m4
@@ -134,6 +134,23 @@ if test "$with_openssl" != "no"; then
LDFLAGS="${saved_LDFLAGS}"
fi
+if test "$openssl" = "yes"; then
+ AC_CHECK_LIB([crypto],
+ [OSSL_EC_curve_nid2name],
+ [AC_DEFINE_UNQUOTED([HAVE_OPENSSL_30], 1,
+ [whether OpenSSL is 3.0 or higher])]
+ )
+ AC_CHECK_HEADERS([openssl/fips.h],
+ [AC_DEFINE_UNQUOTED([HAVE_OPENSSL_FIPS_H], 1,
+ [whether openssl/fips.h is available])]
+ )
+ AC_CHECK_LIB([crypto],
+ [FIPS_mode_set],
+ [AC_DEFINE_UNQUOTED([HAVE_OPENSSL_FIPS_MODE_SET_API], 1,
+ [whether FIPS_mode_set API is available])]
+ )
+fi
+
LIB_hcrypto='$(top_builddir)/lib/hcrypto/libhcrypto.la'
LIB_hcrypto_a='$(top_builddir)/lib/hcrypto/.libs/libhcrypto.a'
LIB_hcrypto_so='$(top_builddir)/lib/hcrypto/.libs/libhcrypto.so'
diff --git a/third_party/heimdal/cf/roken-frag.m4 b/third_party/heimdal/cf/roken-frag.m4
index 2c2ef834e7a..90e514c20e1 100644
--- a/third_party/heimdal/cf/roken-frag.m4
+++ b/third_party/heimdal/cf/roken-frag.m4
@@ -398,6 +398,8 @@ AC_BROKEN([ \
writev \
])
+rk_LIBOBJ(closefrom)
+
AM_CONDITIONAL(have_fnmatch_h,
test "$ac_cv_header_fnmatch_h" = yes -a "$ac_cv_func_fnmatch" = yes)
@@ -492,13 +494,13 @@ dnl
AC_HAVE_STRUCT_FIELD(struct sockaddr, sa_len, [#include <sys/types.h>
#include <sys/socket.h>])
-if test "$ac_cv_func_getaddrinfo" = "yes"; then
- rk_BROKEN_GETADDRINFO
- if test "$ac_cv_func_getaddrinfo_numserv" = no; then
- AC_LIBOBJ(getaddrinfo)
- AC_LIBOBJ(freeaddrinfo)
- fi
-fi
+#if test "$ac_cv_func_getaddrinfo" = "yes"; then
+# rk_BROKEN_GETADDRINFO
+# if test "$ac_cv_func_getaddrinfo_numserv" = no; then
+# AC_LIBOBJ(getaddrinfo)
+# AC_LIBOBJ(freeaddrinfo)
+# fi
+#fi
AC_NEED_PROTO([#include <stdlib.h>], setenv)
AC_NEED_PROTO([#include <stdlib.h>], unsetenv)
diff --git a/third_party/heimdal/cf/sunos.m4 b/third_party/heimdal/cf/sunos.m4
index 938fc3a5ec8..d9aa52cb642 100644
--- a/third_party/heimdal/cf/sunos.m4
+++ b/third_party/heimdal/cf/sunos.m4
@@ -26,4 +26,5 @@ if test "$sunos" != no; then
AC_DEFINE_UNQUOTED(SunOS, $sunos,
[Define to what version of SunOS you are running.])
fi
+AM_CONDITIONAL(SUNOS, test "$sunos" != no)
])
diff --git a/third_party/heimdal/configure.ac b/third_party/heimdal/configure.ac
index b946dfff4c1..e8eea4e6d3a 100644
--- a/third_party/heimdal/configure.ac
+++ b/third_party/heimdal/configure.ac
@@ -245,6 +245,13 @@ AM_CONDITIONAL([HAVE_CJSON], [test "$with_cjson" != "no"])
AC_SUBST([CJSON_CFLAGS])
AC_SUBST([CJSON_LIBS])
+dnl mitkrb5
+AC_ARG_WITH([mitkrb5],
+ AC_HELP_STRING([--with-mitkrb5], [Path to MIT Kerberos for interop testing @<:@default=check@:>@]),
+ [],
+ [with_mikrb5=check])
+AM_CONDITIONAL([MITKRB5], [test "$with_mitkrb5" != "no"])
+
dnl Check for sqlite
rk_TEST_PACKAGE(sqlite3,
[#include <sqlite3.h>
diff --git a/third_party/heimdal/doc/Makefile.am b/third_party/heimdal/doc/Makefile.am
index aa7f8130f49..60c6a8c58a1 100644
--- a/third_party/heimdal/doc/Makefile.am
+++ b/third_party/heimdal/doc/Makefile.am
@@ -6,12 +6,14 @@ AUTOMAKE_OPTIONS = no-texinfo.tex
MAKEINFOFLAGS = --css-include=$(srcdir)/heimdal.css
-TEXI2DVI = true # ARGH, make distcheck can't be disabled to not build dvifiles
+#TEXI2DVI = true # ARGH, make distcheck can't be disabled to not build dvifiles
info_TEXINFOS = heimdal.texi hx509.texi
BUILT_SOURCES = vars.texi
+#all: html pdf dvi ps info
+
dxy_subst = sed -e 's,[@]srcdir[@],$(srcdir),g' \
-e 's,[@]objdir[@],.,g' \
-e 's,[@]PACKAGE_VERSION[@],$(PACKAGE_VERSION),g'
diff --git a/third_party/heimdal/doc/whatis.texi b/third_party/heimdal/doc/whatis.texi
index 2b0e98de552..8c7770b8184 100644
--- a/third_party/heimdal/doc/whatis.texi
+++ b/third_party/heimdal/doc/whatis.texi
@@ -35,12 +35,6 @@ services can authenticate each other.
@end macro
@end ifinfo
-@iftex
-@macro sub{arg}
-@textsubscript{\arg\}
-@end macro
-@end iftex
-
@ifhtml
@macro sub{arg}
@@ -51,13 +45,19 @@ services can authenticate each other.
@end macro
@end ifhtml
-@c ifdocbook
-@c macro sub{arg}
-@c docbook
-@c <subscript>\arg\</subscript>
-@c end docbook
-@c end macro
-@c end ifdocbook
+@ifdocbook
+@macro sub{arg}
+@docbook
+@<subscript>\arg\</subscript>
+@end docbook
+@end macro
+@end ifdocbook
+
+@c @iftex
+@c @macro sub{arg}
+@c @textsubscript{\arg\}
+@c @end macro
+@c @end iftex
@quotation
@strong{Note} This discussion is about Kerberos version 4, but version
diff --git a/third_party/heimdal/include/config.h.w32 b/third_party/heimdal/include/config.h.w32
index 6e0f6bcf147..f8be38b5e29 100644
--- a/third_party/heimdal/include/config.h.w32
+++ b/third_party/heimdal/include/config.h.w32
@@ -57,6 +57,10 @@ static const char *const rcsid[] = { (const char *)rcsid, "@(#)" msg }
#define MAXPATHLEN MaxPathLen
#endif
+#if _MSC_VER < 1900
+# define __func__ __FUNCTION__
+#endif
+
#ifdef BUILD_KRB5_LIB
#ifndef KRB5_LIB
#ifdef _WIN32
diff --git a/third_party/heimdal/include/hcrypto/Makefile.am b/third_party/heimdal/include/hcrypto/Makefile.am
index f15c779a894..e9a59fd38d5 100644
--- a/third_party/heimdal/include/hcrypto/Makefile.am
+++ b/third_party/heimdal/include/hcrypto/Makefile.am
@@ -16,7 +16,6 @@ CLEANFILES = \
evp-hcrypto.h \
evp-cc.h \
hmac.h \
- md2.h \
md4.h \
md5.h \
pkcs12.h \
diff --git a/third_party/heimdal/kadmin/Makefile.am b/third_party/heimdal/kadmin/Makefile.am
index e7fe58f8d73..d9b8fee1c65 100644
--- a/third_party/heimdal/kadmin/Makefile.am
+++ b/third_party/heimdal/kadmin/Makefile.am
@@ -69,6 +69,7 @@ LDADD_common = \
$(DB3LIB) $(DB1LIB) $(LMDBLIB) $(NDBMLIB)
kadmind_LDADD = $(top_builddir)/lib/kadm5/libkadm5srv.la \
+ $(top_builddir)/lib/kadm5/libkadm5clnt.la \
../lib/gssapi/libgssapi.la \
$(LDADD_common) \
$(LIB_pidfile) \
diff --git a/third_party/heimdal/kadmin/ank.c b/third_party/heimdal/kadmin/ank.c
index 4b89ca6eedd..fba3450aa89 100644
--- a/third_party/heimdal/kadmin/ank.c
+++ b/third_party/heimdal/kadmin/ank.c
@@ -182,8 +182,13 @@ add_one_principal(const char *name,
krb5_free_keyblock_contents(context, &new_keys[i]);
if (n_keys > 0)
free(new_keys);
- kadm5_get_principal(kadm_handle, princ_ent, &princ,
- KADM5_PRINCIPAL | KADM5_KVNO | KADM5_ATTRIBUTES);
+ ret = kadm5_get_principal(kadm_handle, princ_ent, &princ,
+ KADM5_PRINCIPAL | KADM5_KVNO |
+ KADM5_ATTRIBUTES);
+ if (ret) {
+ krb5_warn(context, ret, "kadm5_get_principal");
+ goto out;
+ }
krb5_free_principal(context, princ_ent);
princ_ent = princ.principal;
princ.attributes &= (~KRB5_KDB_DISALLOW_ALL_TIX);
diff --git a/third_party/heimdal/kadmin/cpw.c b/third_party/heimdal/kadmin/cpw.c
index 7ffc828cf30..13973177710 100644
--- a/third_party/heimdal/kadmin/cpw.c
+++ b/third_party/heimdal/kadmin/cpw.c
@@ -156,8 +156,10 @@ cpw_entry(struct passwd_options *opt, int argc, char **argv)
int i;
struct cpw_entry_data data;
int num;
+ int16_t n_key_data = 0;
krb5_key_data key_data[3];
+ memset(key_data, 0, sizeof(key_data));
data.kadm_handle = NULL;
ret = kadm5_dup_context(kadm_handle, &data.kadm_handle);
if (ret)
@@ -214,6 +216,7 @@ cpw_entry(struct passwd_options *opt, int argc, char **argv)
opt->key_string, error);
return 1;
}
+ n_key_data = sizeof(key_data)/sizeof(key_data[0]);
data.key_data = key_data;
}
@@ -222,10 +225,8 @@ cpw_entry(struct passwd_options *opt, int argc, char **argv)
kadm5_destroy(data.kadm_handle);
- if (data.key_data) {
- int16_t dummy;
- kadm5_free_key_data (kadm_handle, &dummy, key_data);
- }
+ if (opt->key_string)
+ kadm5_free_key_data(kadm_handle, &n_key_data, key_data);
return ret != 0;
}
diff --git a/third_party/heimdal/kadmin/get.c b/third_party/heimdal/kadmin/get.c
index 6e8ada01ea4..1942d63894e 100644
--- a/third_party/heimdal/kadmin/get.c
+++ b/third_party/heimdal/kadmin/get.c
@@ -233,6 +233,8 @@ format_field(struct get_entry_data *data,
size_t buf_len,
int condensed)
{
+ krb5_error_code ret;
+
switch(field) {
case KADM5_PRINCIPAL:
if(condensed)
@@ -302,7 +304,10 @@ format_field(struct get_entry_data *data,
krb5_salt def_salt;
int i;
char buf2[1024];
- krb5_get_pw_salt (context, princ->principal, &def_salt);
+
+ ret = krb5_get_pw_salt(context, princ->principal, &def_salt);
+ if (ret)
+ krb5_err(context, 1, ret, "krb5_get_pw_salt");
*buf = '\0';
for (i = 0; i < princ->n_key_data; ++i) {
@@ -335,7 +340,6 @@ format_field(struct get_entry_data *data,
HDB_EncTypeList etypes;
size_t i, size;
char *str;
- int ret;
ret = decode_HDB_EncTypeList(tl->tl_data_contents,
tl->tl_data_length,
@@ -360,7 +364,6 @@ format_field(struct get_entry_data *data,
case KRB5_TL_PKINIT_ACL: {
HDB_Ext_PKINIT_acl acl;
size_t size;
- int ret;
size_t i;
ret = decode_HDB_Ext_PKINIT_acl(tl->tl_data_contents,
@@ -403,7 +406,6 @@ format_field(struct get_entry_data *data,
case KRB5_TL_ALIASES: {
HDB_Ext_Aliases alias;
size_t size;
- int ret;
size_t i;
ret = decode_HDB_Ext_Aliases(tl->tl_data_contents,
diff --git a/third_party/heimdal/kadmin/kadmin.c b/third_party/heimdal/kadmin/kadmin.c
index d2f5abadd15..607ba03e236 100644
--- a/third_party/heimdal/kadmin/kadmin.c
+++ b/third_party/heimdal/kadmin/kadmin.c
@@ -296,10 +296,13 @@ main(int argc, char **argv)
} else {
while(!exit_seen) {
ret = sl_command_loop(commands, "kadmin> ", NULL);
- if (ret == -2)
+ if (ret == -2) {
exit_seen = 1;
- else if (ret != 0)
+ } else if (ret != 0) {
exit_status = 1;
+ if (!isatty(STDIN_FILENO))
+ exit_seen = 1;
+ }
}
}
diff --git a/third_party/heimdal/kadmin/kadmind.c b/third_party/heimdal/kadmin/kadmind.c
index cf335d6dc01..4ea513e08d3 100644
--- a/third_party/heimdal/kadmin/kadmind.c
+++ b/third_party/heimdal/kadmin/kadmind.c
@@ -32,6 +32,8 @@
*/
#include "kadmin_locl.h"
+#include "heim_threads.h"
+#include "krb5-protos.h"
static char *check_library = NULL;
static char *check_function = NULL;
@@ -39,6 +41,13 @@ static getarg_strings policy_libraries = { 0, NULL };
static char *config_file;
static char sHDB[] = "HDBGET:";
static char *keytab_str = sHDB;
+#ifndef WIN32
+static char *fuzz_file;
+static char *fuzz_client_name;
+static char *fuzz_keytab_name;
+static char *fuzz_service_name;
+static char *fuzz_admin_server;
+#endif
static int help_flag;
static int version_flag;
static int debug_flag;
@@ -88,6 +97,16 @@ static struct getargs args[] = {
"ports to listen to", "port" },
{ "read-only", 0, arg_flag, &readonly_flag,
"read-only operations", NULL },
+#ifndef WIN32
+ { "fuzz-file", 0, arg_string, &fuzz_file,
+ "Kadmin RPC body for fuzzing", "FILE" },
+ { "fuzz-client", 0, arg_string, &fuzz_client_name,
+ "Client name for fuzzing", "PRINCIPAL" },
+ { "fuzz-keytab", 0, arg_string, &fuzz_keytab_name,
+ "Keytab for fuzzing", "KEYTAB" },
+ { "fuzz-server", 0, arg_string, &fuzz_admin_server,
+ "Name of kadmind self instance", "HOST:PORT" },
+#endif
{ "help", 'h', arg_flag, &help_flag, NULL, NULL },
{ "version", 'v', arg_flag, &version_flag, NULL, NULL }
};
@@ -103,6 +122,8 @@ usage(int ret)
exit (ret);
}
+static void *fuzz_thread(void *);
+
int
main(int argc, char **argv)
{
@@ -220,7 +241,78 @@ main(int argc, char **argv)
if(realm)
krb5_set_default_realm(context, realm); /* XXX */
+#ifndef WIN32
+ if (fuzz_file) {
+ HEIMDAL_THREAD_ID tid;
+
+ if (fuzz_admin_server == NULL)
+ errx(1, "If --fuzz-file is given then --fuzz-server must be too");
+ HEIMDAL_THREAD_create(&tid, fuzz_thread, NULL);
+ }
+#endif
+
kadmind_loop(context, keytab, sfd, readonly_flag);
return 0;
}
+
+#ifndef WIN32
+static void *
+fuzz_thread(void *arg)
+{
+ kadm5_config_params conf;
+ krb5_error_code ret;
+ krb5_context context2;
+ krb5_storage *sp;
+ krb5_data reply;
+ void *server_handle = NULL;
+ int fd;
+
+ memset(&conf, 0, sizeof(conf));
+ conf.admin_server = fuzz_admin_server;
+
+ fd = open(fuzz_file, O_RDONLY);
+ if (fd < 0)
+ err(1, "Could not open fuzz file %s", fuzz_file);
+ sp = krb5_storage_from_fd(fd);
+ if (sp == NULL)
+ err(1, "Could not read fuzz file %s", fuzz_file);
+ (void) close(fd);
+
+ ret = krb5_init_context(&context2);
+ if (ret)
+ errx(1, "Fuzzing failed: krb5_init_context failed: %d", ret);
+ ret = kadm5_c_init_with_skey_ctx(context2,
+ fuzz_client_name,
+ fuzz_keytab_name,
+ fuzz_service_name ?
+ fuzz_service_name :
+ KADM5_ADMIN_SERVICE,
+ &conf,
+ 0, /* struct_version */
+ 0, /* api_version */
+ &server_handle);
+ if (ret)
+ errx(1, "Fuzzing failed: kadm5_c_init_with_skey_ctx failed: %d", ret);
+
+ ret = _kadm5_connect(server_handle, 1 /* want_write */);
+ if (ret)
+ errx(1, "Fuzzing failed: Could not connect to self (%s): "
+ "_kadm5_connect failed: %d", fuzz_admin_server, ret);
+ ret = _kadm5_client_send(server_handle, sp);
+ if (ret)
+ errx(1, "Fuzzing failed: Could not send request to self (%s): "
+ "_kadm5_client_send failed: %d", fuzz_admin_server, ret);
+ krb5_data_zero(&reply);
+ ret = _kadm5_client_recv(server_handle, &reply);
+ if (ret)
+ errx(1, "Fuzzing failed: Could not read reply from self (%s): "
+ "_kadm5_client_recv failed: %d", fuzz_admin_server, ret);
+ krb5_storage_free(sp);
+ krb5_data_free(&reply);
+ fprintf(stderr, "Fuzzed with %s", fuzz_file);
+ exit(0);
+
+ return NULL;
+}
+#endif
diff --git a/third_party/heimdal/kadmin/mod.c b/third_party/heimdal/kadmin/mod.c
index 3bcd9ac31d5..2d4bd5d5077 100644
--- a/third_party/heimdal/kadmin/mod.c
+++ b/third_party/heimdal/kadmin/mod.c
@@ -262,6 +262,7 @@ add_kvno_diff(krb5_context contextp, kadm5_principal_ent_rec *princ,
if (kvno_diff > 2048)
kvno_diff = 2048;
+ ext.mandatory = 0;
if (is_svc_diff) {
ext.data.element = choice_HDB_extension_data_hist_kvno_diff_svc;
ext.data.u.hist_kvno_diff_svc = (unsigned int)kvno_diff;
diff --git a/third_party/heimdal/kadmin/rpc.c b/third_party/heimdal/kadmin/rpc.c
index 5cae3d2c239..8a176da6399 100644
--- a/third_party/heimdal/kadmin/rpc.c
+++ b/third_party/heimdal/kadmin/rpc.c
@@ -529,6 +529,7 @@ ret_principal_ent(krb5_context contextp,
CHECK(krb5_ret_uint32(sp, &flag));
ent->key_data[i].key_data_type[1] = flag;
}
+ CHECK(i == num);
return 0;
}
diff --git a/third_party/heimdal/kdc/Makefile.am b/third_party/heimdal/kdc/Makefile.am
index 48248d8248b..ca5835930dd 100644
--- a/third_party/heimdal/kdc/Makefile.am
+++ b/third_party/heimdal/kdc/Makefile.am
@@ -6,8 +6,9 @@ WFLAGS += $(WFLAGS_ENUM_CONV)
AM_CPPFLAGS += $(INCLUDE_libintl) $(INCLUDE_openssl_crypto) -I$(srcdir)/../lib/krb5
-lib_LTLIBRARIES = simple_csr_authorizer.la ipc_csr_authorizer.la \
- libkdc.la negotiate_token_validator.la
+lib_LTLIBRARIES = ipc_csr_authorizer.la \
+ negotiate_token_validator.la \
+ libkdc.la
if HAVE_CJWT
lib_LTLIBRARIES += cjwt_token_validator.la
@@ -97,8 +98,6 @@ endif
negotiate_token_validator_la_SOURCES = negotiate_token_validator.c
negotiate_token_validator_la_LDFLAGS = -module $(LIB_gssapi)
# CSR Authorizer plugins (for kdc/kx509 and bx509d)
-simple_csr_authorizer_la_SOURCES = simple_csr_authorizer.c
-simple_csr_authorizer_la_LDFLAGS = -module
ipc_csr_authorizer_la_SOURCES = ipc_csr_authorizer.c
ipc_csr_authorizer_la_LDFLAGS = -module \
$(top_builddir)/lib/krb5/libkrb5.la \
@@ -155,7 +154,6 @@ ALL_OBJECTS += $(digest_service_OBJECTS)
ALL_OBJECTS += $(bx509d_OBJECTS)
ALL_OBJECTS += $(httpkadmind_OBJECTS)
ALL_OBJECTS += $(cjwt_token_validator_la_OBJECTS)
-ALL_OBJECTS += $(simple_csr_authorizer_la_OBJECTS)
ALL_OBJECTS += $(test_token_validator_OBJECTS)
ALL_OBJECTS += $(test_csr_authorizer_OBJECTS)
ALL_OBJECTS += $(test_kdc_ca_OBJECTS)
@@ -237,7 +235,12 @@ digest_service_LDADD = \
kdc_replay_LDADD = libkdc.la $(LDADD) $(LIB_pidfile)
kdc_tester_LDADD = libkdc.la $(LDADD) $(LIB_pidfile) $(LIB_heimbase)
test_token_validator_LDADD = libkdc.la $(LDADD) $(LIB_pidfile) $(LIB_heimbase) $(LIB_gssapi)
-test_csr_authorizer_LDADD = libkdc.la $(top_builddir)/lib/hx509/libhx509.la $(LDADD) $(LIB_pidfile) $(LIB_heimbase)
+test_csr_authorizer_LDADD = libkdc.la \
+ $(top_builddir)/lib/hx509/libhx509.la \
+ $(LDADD) \
+ $(LIB_pidfile) \
+ $(LIB_heimbase) \
+ $(top_builddir)/lib/ipc/libheim-ipcs.la
test_kdc_ca_LDADD = libkdc.la $(top_builddir)/lib/hx509/libhx509.la $(LDADD) $(LIB_pidfile) $(LIB_heimbase)
include_HEADERS = kdc.h $(srcdir)/kdc-protos.h
diff --git a/third_party/heimdal/kdc/bx509d.c b/third_party/heimdal/kdc/bx509d.c
index 4d1b694a914..b7e9096f737 100644
--- a/third_party/heimdal/kdc/bx509d.c
+++ b/third_party/heimdal/kdc/bx509d.c
@@ -185,6 +185,7 @@ typedef struct bx509_request_desc {
const char *redir;
const char *method;
size_t post_data_size;
+ size_t san_idx; /* For /get-tgts */
enum k5_creds_kind cckind;
char *pkix_store;
char *tgts_filename;
@@ -260,6 +261,8 @@ get_krb5_context(krb5_context *contextp)
return 0;
if ((ret = krb5_init_context(contextp)))
return *contextp = NULL, ret;
+ if (logfac)
+ krb5_set_log_dest(*contextp, logfac);
(void) pthread_setspecific(k5ctx, *contextp);
return *contextp ? 0 : ENOMEM;
}
@@ -566,7 +569,6 @@ bad_reqv(struct bx509_request_desc *r,
va_list ap)
{
krb5_error_code ret;
- krb5_context context = NULL;
const char *k5msg = NULL;
const char *emsg = NULL;
char *formatted = NULL;
@@ -586,8 +588,10 @@ bad_reqv(struct bx509_request_desc *r,
if (code) {
if (r->context)
emsg = k5msg = krb5_get_error_message(r->context, code);
- else
+ else if (code > -1)
emsg = strerror(code);
+ else
+ emsg = "Unknown error";
}
ret = vasprintf(&formatted, fmt, ap);
@@ -600,10 +604,11 @@ bad_reqv(struct bx509_request_desc *r,
}
heim_audit_addreason((heim_svc_req_desc)r, "%s", msg);
audit_trail(r, code);
- krb5_free_error_message(context, k5msg);
+ if (r->context)
+ krb5_free_error_message(r->context, k5msg);
if (ret == -1 || msg == NULL) {
- if (context)
+ if (r->context)
krb5_log_msg(r->context, logfac, 1, NULL, "Out of memory");
return resp(r, MHD_HTTP_SERVICE_UNAVAILABLE, MHD_RESPMEM_PERSISTENT,
NULL, "Out of memory", sizeof("Out of memory") - 1, NULL);
@@ -882,7 +887,7 @@ do_CA(struct bx509_request_desc *r, const char *csr)
bytes = rk_base64_decode(csr2, d.data);
free(csr2);
if (bytes < 0)
- ret = errno;
+ ret = errno ? errno : EINVAL;
else
d.length = bytes;
if (ret) {
@@ -1360,10 +1365,12 @@ do_pkinit(struct bx509_request_desc *r, enum k5_creds_kind kind)
ret = krb5_append_addresses(r->context, &r->tgt_addresses,
&addr);
}
- if (ret == 0 && r->tgt_addresses.len == 0)
- ret = krb5_get_init_creds_opt_set_addressless(r->context, opt, 1);
- else
- krb5_get_init_creds_opt_set_address_list(opt, &r->tgt_addresses);
+ if (ret == 0) {
+ if (r->tgt_addresses.len == 0)
+ ret = krb5_get_init_creds_opt_set_addressless(r->context, opt, 1);
+ else
+ krb5_get_init_creds_opt_set_address_list(opt, &r->tgt_addresses);
+ }
if (ret == 0)
ret = krb5_get_init_creds_opt_set_pkinit(r->context, opt, p,
r->pkix_store,
@@ -1543,7 +1550,7 @@ k5_get_creds(struct bx509_request_desc *r, enum k5_creds_kind kind)
static void
acc_str(char **acc, char *adds, size_t addslen)
{
- char *tmp;
+ char *tmp = NULL;
int l = addslen <= INT_MAX ? (int)addslen : INT_MAX;
if (asprintf(&tmp, "%s%s%.*s",
@@ -1570,7 +1577,7 @@ fmt_gss_error(OM_uint32 code, gss_OID mech)
acc_str(&r, (char *)buf.value, buf.length);
gss_release_buffer(&minor, &buf);
} while (!GSS_ERROR(major) && more);
- return r ? r : "Out of memory while formatting GSS-API error";
+ return r;
}
static char *
@@ -1580,7 +1587,10 @@ fmt_gss_errors(const char *r, OM_uint32 major, OM_uint32 minor, gss_OID mech)
ma = fmt_gss_error(major, GSS_C_NO_OID);
mi = mech == GSS_C_NO_OID ? NULL : fmt_gss_error(minor, mech);
- if (asprintf(&s, "%s: %s%s%s", r, ma, mi ? ": " : "", mi ? mi : "") > -1 &&
+ if (asprintf(&s, "%s: %s%s%s", r,
+ ma ? ma : "Out of memory",
+ mi ? ": " : "",
+ mi ? mi : "") > -1 &&
s) {
free(ma);
free(mi);
@@ -1605,8 +1615,13 @@ bad_req_gss(struct bx509_request_desc *r,
if (major == GSS_S_BAD_NAME || major == GSS_S_BAD_NAMETYPE)
http_status_code = MHD_HTTP_BAD_REQUEST;
- ret = resp(r, http_status_code, MHD_RESPMEM_MUST_COPY, NULL,
- msg, strlen(msg), NULL);
+ if (msg)
+ ret = resp(r, http_status_code, MHD_RESPMEM_MUST_COPY, NULL,
+ msg, strlen(msg), NULL);
+ else
+ ret = resp(r, http_status_code, MHD_RESPMEM_MUST_COPY, NULL,
+ "Out of memory while formatting GSS error message",
+ sizeof("Out of memory while formatting GSS error message") - 1, NULL);
free(msg);
return ret;
}
@@ -1839,9 +1854,7 @@ authorize_TGT_REQ(struct bx509_request_desc *r)
if (for_cname == r->cname || strcmp(r->cname, r->for_cname) == 0)
return 0;
- ret = krb5_parse_name(r->context, r->cname, &p);
- if (ret == 0)
- ret = hx509_request_init(r->context->hx509ctx, &r->req);
+ ret = hx509_request_init(r->context->hx509ctx, &r->req);
if (ret)
return bad_500(r, ret, "Out of resources");
heim_audit_addkv((heim_svc_req_desc)r, KDC_AUDIT_VIS,
@@ -1852,9 +1865,12 @@ authorize_TGT_REQ(struct bx509_request_desc *r)
ret = hx509_request_add_pkinit(r->context->hx509ctx, r->req,
for_cname);
if (ret == 0)
+ ret = krb5_parse_name(r->context, r->cname, &p);
+ if (ret == 0)
ret = kdc_authorize_csr(r->context, "get-tgt", r->req, p);
krb5_free_principal(r->context, p);
hx509_request_free(&r->req);
+ r->req = NULL;
if (ret)
return bad_403(r, ret, "Not authorized to requested TGT");
return ret;
@@ -1972,7 +1988,7 @@ get_tgts_accumulate_ccache_write_json(struct bx509_request_desc *r,
if (o && k && v)
ret = heim_dict_set_value(o, k, v);
else
- ret = errno;
+ ret = ENOMEM;
if (ret == 0) {
heim_release(v);
@@ -1991,10 +2007,13 @@ get_tgts_accumulate_ccache_write_json(struct bx509_request_desc *r,
ret = heim_dict_set_value(o, k, v);
}
if (ret == 0 && code != 0) {
+ const char *s = krb5_get_error_message(r->context, code);
+
heim_release(v);
heim_release(k);
k = heim_string_create("error");
- v = heim_string_create(krb5_get_error_message(r->context, code));
+ v = heim_string_create(s ? s : "Out of memory");
+ krb5_free_error_message(r->context, s);
if (k && v)
ret = heim_dict_set_value(o, k, v);
}
@@ -2120,17 +2139,79 @@ get_tgts_param_execute_cb(void *d,
const char *val)
{
struct bx509_request_desc *r = d;
- heim_mhd_result res = MHD_YES;
+ hx509_san_type san_type;
krb5_error_code ret;
+ size_t san_idx = r->san_idx++;
+ const char *save_for_cname = r->for_cname;
+ char *s = NULL;
+ int res;
- if (strcmp(key, "cname") == 0 && val) {
- /* Handled upstairs */
+ /* We expect only cname=principal q-params here */
+ if (strcmp(key, "cname") != 0 || val == NULL)
+ return MHD_YES;
+
+ /*
+ * We expect the `san_idx'th SAN in the `r->req' request checked by
+ * kdc_authorize_csr() to be the same as this cname. This happens
+ * naturally because we add these SANs to `r->req' in the same order as we
+ * visit them here (unless our HTTP library somehow went crazy).
+ *
+ * Still, we check that it's the same SAN.
+ */
+ ret = hx509_request_get_san(r->req, san_idx, &san_type, &s);
+ if (ret == HX509_NO_ITEM ||
+ san_type != HX509_SAN_TYPE_PKINIT ||
+ strcmp(s, val) != 0) {
+ /*
+ * If the cname and SAN don't match, it's some weird internal error
+ * (can't happen).
+ */
+ krb5_set_error_message(r->context, r->error_code = EACCES,
+ "PKINIT SAN not granted: %s (internal error)",
+ val);
+ ret = EACCES;
+ }
+
+ /*
+ * We're going to pretend to be this SAN for the purpose of acquring a TGT
+ * for it. So we "push" `r->for_cname'.
+ */
+ if (ret == 0)
r->for_cname = val;
+
+ /*
+ * Our authorizer supports partial authorization where the whole request is
+ * rejected but some features of it are permitted.
+ *
+ * (In most end-points we don't want partial authorization, but in
+ * /get-tgts we very much do.)
+ */
+ if (ret == 0 && !hx509_request_san_authorized_p(r->req, san_idx)) {
+ heim_audit_addkv((heim_svc_req_desc)r, KDC_AUDIT_VIS,
+ "REJECT_krb5PrincipalName", "%s", val);
+ krb5_set_error_message(r->context, r->error_code = EACCES,
+ "PKINIT SAN denied: %s", val);
+ ret = EACCES;
+ }
+ if (ret == 0) {
+ heim_audit_addkv((heim_svc_req_desc)r, KDC_AUDIT_VIS,
+ "ACCEPT_krb5PrincipalName", "%s", val);
ret = k5_get_creds(r, K5_CREDS_EPHEMERAL);
- res = get_tgts_accumulate_ccache(r, ret);
- } else {
- /* Handled upstairs */
+ if (ret == 0)
+ heim_audit_addkv((heim_svc_req_desc)r, KDC_AUDIT_VIS,
+ "ISSUE_krb5PrincipalName", "%s", val);
}
+
+ /*
+ * If ret == 0 this will gather the TGT we acquired, else it will acquire
+ * the error we got.
+ */
+ res = get_tgts_accumulate_ccache(r, ret);
+
+ /* Now we "pop" `r->for_cname' */
+ r->for_cname = save_for_cname;
+
+ hx509_xfree(s);
return res;
}
@@ -2161,39 +2242,63 @@ get_tgts(struct bx509_request_desc *r)
r->error_code = 0;
res = MHD_get_connection_values(r->connection, MHD_GET_ARGUMENT_KIND,
get_tgt_param_cb, r);
- if (r->response || res == MHD_NO)
+ if (r->response || res == MHD_NO) {
+ krb5_free_principal(r->context, p);
return res;
+ }
ret = r->error_code;
}
if (ret == 0) {
- /* Authorize requested client principal names (calls bad_req()) */
+ /*
+ * Check authorization of the authenticated client to the requested
+ * client principal names (calls bad_req()).
+ */
r->error_code = 0;
res = MHD_get_connection_values(r->connection, MHD_GET_ARGUMENT_KIND,
get_tgts_param_authorize_cb, r);
- if (r->response || res == MHD_NO)
+ if (r->response || res == MHD_NO) {
+ krb5_free_principal(r->context, p);
return res;
+ }
ret = r->error_code;
if (ret == 0) {
+ /* Use the same configuration as /get-tgt (or should we?) */
ret = kdc_authorize_csr(r->context, "get-tgt", r->req, p);
+
+ /*
+ * We tolerate EACCES because we support partial approval.
+ *
+ * (KRB5_PLUGIN_NO_HANDLE means no plugin handled the authorization
+ * check.)
+ */
+ if (ret == EACCES || ret == KRB5_PLUGIN_NO_HANDLE)
+ ret = 0;
if (ret) {
krb5_free_principal(r->context, p);
return bad_403(r, ret, "Permission denied");
}
}
- hx509_request_free(&r->req);
}
if (ret == 0) {
- /* get_tgts_param_execute_cb() calls bad_req() */
+ /*
+ * Get the actual TGTs that were authorized.
+ *
+ * get_tgts_param_execute_cb() calls bad_req()
+ */
r->error_code = 0;
res = MHD_get_connection_values(r->connection, MHD_GET_ARGUMENT_KIND,
get_tgts_param_execute_cb, r);
- if (r->response || res == MHD_NO)
+ if (r->response || res == MHD_NO) {
+ krb5_free_principal(r->context, p);
return res;
+ }
ret = r->error_code;
}
krb5_free_principal(r->context, p);
+ hx509_request_free(&r->req);
+ r->req = NULL;
/*
* get_tgts_param_execute_cb() will write its JSON response to the file
@@ -2322,7 +2427,7 @@ make_csrf_token(struct bx509_request_desc *r,
if (ret == 0 && data.length > INT_MAX)
ret = ERANGE;
if (ret == 0 &&
- (dlen = rk_base64_encode(data.data, data.length, token)) < 0)
+ rk_base64_encode(data.data, data.length, token) < 0)
ret = errno;
krb5_storage_free(sp);
krb5_data_free(&data);
@@ -2420,6 +2525,7 @@ ip(void *cls,
if (ftl == NULL || keydup == NULL || valdup == NULL) {
free(ftl);
free(keydup);
+ free(valdup);
return MHD_NO;
}
ftl->freeme1 = keydup;
@@ -2494,7 +2600,7 @@ route(void *cls,
* possibly multiple times.
*/
if ((ret = set_req_desc(connection, method, url, &r)))
- return bad_503(r, ret, "Could not initialize request state");
+ return MHD_NO;
*ctx = r;
/* All requests other than /health require authentication */
@@ -2816,6 +2922,7 @@ main(int argc, char **argv)
err(1, "Could not init krb5 context");
bx509_openlog(context, "bx509d", &logfac);
+ krb5_set_log_dest(context, logfac);
load_plugins(context);
if (allow_GET_flag == -1)
diff --git a/third_party/heimdal/kdc/fast.c b/third_party/heimdal/kdc/fast.c
index 392fc966050..e6c523ced95 100644
--- a/third_party/heimdal/kdc/fast.c
+++ b/third_party/heimdal/kdc/fast.c
@@ -605,9 +605,11 @@ fast_unwrap_request(astgs_request_t r,
ticket = tgs_ticket;
}
- krb5_unparse_name(r->context, ticket->client, &armor_client_principal_name);
+ (void) krb5_unparse_name(r->context, ticket->client, &armor_client_principal_name);
kdc_audit_addkv((kdc_request_t)r, 0, "armor_client_name", "%s",
- armor_client_principal_name ? armor_client_principal_name : "<unknown>");
+ armor_client_principal_name ?
+ armor_client_principal_name :
+ "<out of memory>");
if (ac->remote_subkey == NULL) {
krb5_auth_con_free(r->context, ac);
diff --git a/third_party/heimdal/kdc/hpropd.c b/third_party/heimdal/kdc/hpropd.c
index fa06a1fd401..255d60949cc 100644
--- a/third_party/heimdal/kdc/hpropd.c
+++ b/third_party/heimdal/kdc/hpropd.c
@@ -78,7 +78,7 @@ main(int argc, char **argv)
krb5_socket_t sock = rk_INVALID_SOCKET;
HDB *db = NULL;
int optidx = 0;
- char *tmp_db;
+ char *tmp_db = NULL;
krb5_log_facility *fac;
int nprincs;
@@ -208,20 +208,15 @@ main(int argc, char **argv)
krb5_err(context, 1, ret, "krb5_kt_close");
}
- if (!print_dump) {
- int aret;
+ if (asprintf(&tmp_db, "%s~", database) < 0 || tmp_db == NULL)
+ krb5_errx(context, 1, "hdb_create: out of memory");
- aret = asprintf(&tmp_db, "%s~", database);
- if (aret == -1)
- krb5_errx(context, 1, "hdb_create: out of memory");
-
- ret = hdb_create(context, &db, tmp_db);
- if (ret)
- krb5_err(context, 1, ret, "hdb_create(%s)", tmp_db);
- ret = db->hdb_open(context, db, O_RDWR | O_CREAT | O_TRUNC, 0600);
- if (ret)
- krb5_err(context, 1, ret, "hdb_open(%s)", tmp_db);
- }
+ ret = hdb_create(context, &db, tmp_db);
+ if (ret)
+ krb5_err(context, 1, ret, "hdb_create(%s)", tmp_db);
+ ret = db->hdb_open(context, db, O_RDWR | O_CREAT | O_TRUNC, 0600);
+ if (ret)
+ krb5_err(context, 1, ret, "hdb_open(%s)", tmp_db);
nprincs = 0;
while (1){
@@ -244,14 +239,6 @@ main(int argc, char **argv)
data.length = 0;
krb5_write_priv_message(context, ac, &sock, &data);
}
- if (!print_dump) {
- ret = db->hdb_close(context, db);
- if (ret)
- krb5_err(context, 1, ret, "db_close");
- ret = db->hdb_rename(context, db, database);
- if (ret)
- krb5_err(context, 1, ret, "db_rename");
- }
break;
}
memset(&entry, 0, sizeof(entry));
@@ -284,6 +271,13 @@ main(int argc, char **argv)
if (!print_dump)
krb5_log(context, fac, 0, "Received %d principals", nprincs);
+ ret = db->hdb_close(context, db);
+ if (ret)
+ krb5_err(context, 1, ret, "db_close");
+ ret = db->hdb_rename(context, db, database);
+ if (ret)
+ krb5_err(context, 1, ret, "db_rename");
+
if (inetd_flag == 0)
rk_closesocket(sock);
diff --git a/third_party/heimdal/kdc/httpkadmind.c b/third_party/heimdal/kdc/httpkadmind.c
index 068b5acbf90..3b57539cf4b 100644
--- a/third_party/heimdal/kdc/httpkadmind.c
+++ b/third_party/heimdal/kdc/httpkadmind.c
@@ -398,9 +398,6 @@ get_kadm_handle(krb5_context context,
set_conf(conf, realm, want_realm, KADM5_CONFIG_REALM);
set_conf(conf, dbname, hdb, KADM5_CONFIG_DBNAME);
set_conf(conf, stash_file, stash_file, KADM5_CONFIG_STASH_FILE);
- set_conf(conf, admin_server, writable_kadmin_server, KADM5_CONFIG_ADMIN_SERVER);
- set_conf(conf, readonly_admin_server, kadmin_server,
- KADM5_CONFIG_READONLY_ADMIN_SERVER);
/*
* If we have a local HDB we'll use it if we can. If the local HDB is
@@ -425,6 +422,11 @@ get_kadm_handle(krb5_context context,
*
* Note that kadmin_client_keytab can be an HDB: or HDBGET: keytab.
*/
+ if (writable_kadmin_server)
+ set_conf(conf, admin_server, writable_kadmin_server, KADM5_CONFIG_ADMIN_SERVER);
+ if (kadmin_server)
+ set_conf(conf, readonly_admin_server, kadmin_server,
+ KADM5_CONFIG_READONLY_ADMIN_SERVER);
ret = kadm5_c_init_with_skey_ctx(context,
kadmin_client_name,
kadmin_client_keytab,
@@ -761,13 +763,11 @@ bad_reqv(kadmin_request_desc r,
char *formatted = NULL;
char *msg = NULL;
- if (r && r->context)
- context = r->context;
- if (r && r->hcontext && r->kv)
+ context = r->context;
+ if (r->hcontext && r->kv)
heim_audit_setkv_number((heim_svc_req_desc)r, "http-status-code",
http_status_code);
- if (r)
- (void) gettimeofday(&r->tv_end, NULL);
+ (void) gettimeofday(&r->tv_end, NULL);
if (code == ENOMEM) {
if (context)
krb5_log_msg(context, logfac, 1, NULL, "Out of memory");
@@ -790,7 +790,7 @@ bad_reqv(kadmin_request_desc r,
msg = formatted;
formatted = NULL;
}
- if (r && r->hcontext)
+ if (r->hcontext)
heim_audit_addreason((heim_svc_req_desc)r, "%s", formatted);
krb5_free_error_message(context, k5msg);
@@ -2034,7 +2034,7 @@ make_csrf_token(kadmin_request_desc r,
if (ret == 0 && data.length > INT_MAX)
ret = ERANGE;
if (ret == 0 &&
- (dlen = rk_base64_encode(data.data, data.length, token)) < 0)
+ rk_base64_encode(data.data, data.length, token) < 0)
ret = errno;
krb5_storage_free(sp);
krb5_data_free(&data);
@@ -2139,6 +2139,7 @@ ip(void *cls,
if (ftl == NULL || keydup == NULL || valdup == NULL) {
free(ftl);
free(keydup);
+ free(valdup);
return MHD_NO;
}
ftl->freeme1 = keydup;
@@ -2186,11 +2187,8 @@ route(void *cls,
* handling a POST then we'll also get called with upload_data != NULL,
* possibly multiple times.
*/
- if ((ret = set_req_desc(connection, method, url, &r))) {
- return
- bad_503(r, ret, "Could not initialize request state") == -1
- ? MHD_NO : MHD_YES;
- }
+ if ((ret = set_req_desc(connection, method, url, &r)))
+ return MHD_NO;
*ctx = r;
/*
@@ -2512,6 +2510,11 @@ main(int argc, char **argv)
if (port < 0)
errx(1, "Port number must be given");
+ if (writable_kadmin_server == NULL && kadmin_server == NULL &&
+ !local_hdb && !local_hdb_read_only)
+ errx(1, "One of --local or --local-read-only must be given, or a "
+ "remote kadmind must be given");
+
if (audiences.num_strings == 0) {
char localhost[MAXHOSTNAMELEN];
diff --git a/third_party/heimdal/kdc/ipc_csr_authorizer.c b/third_party/heimdal/kdc/ipc_csr_authorizer.c
index 7d77e7f812a..86717f6f9e0 100644
--- a/third_party/heimdal/kdc/ipc_csr_authorizer.c
+++ b/third_party/heimdal/kdc/ipc_csr_authorizer.c
@@ -197,8 +197,189 @@ cmd_append(struct rk_strpool **cmd, const char *s0, ...)
return ret;
}
+/* Like strpbrk(), but from the end of the string */
+static char *
+strrpbrk(char *s, const char *accept)
+{
+ char *last = NULL;
+ char *p = s;
+
+ do {
+ p = strpbrk(p, accept);
+ if (p != NULL) {
+ last = p;
+ p++;
+ }
+ } while (p != NULL);
+ return last;
+}
+
+/*
+ * For /get-tgts we need to support partial authorization of requests. The
+ * hx509_request APIs support that.
+ *
+ * Here we just step through the IPC server's response and mark the
+ * corresponding request elements authorized so that /get-tgts can issue or not
+ * issue TGTs according to which requested principals are authorized and which
+ * are not.
+ */
static int
-call_svc(krb5_context context, heim_ipc ipc, const char *cmd)
+mark_piecemeal_authorized(krb5_context context,
+ hx509_request csr,
+ heim_octet_string *rep)
+{
+ size_t san_idx = 0;
+ size_t eku_idx = 0;
+ char *s, *p, *rep2, *tok, *next = NULL;
+ int slow_path = 0;
+ int partial = 0;
+ int ret = 0;
+
+ /* We have a data, but we want a C string */
+ if ((rep2 = strndup(rep->data, rep->length)) == NULL)
+ return krb5_enomem(context);
+
+ /* The first token should be "denied"; skip it */
+ if ((s = strchr(rep2, ' ')) == NULL) {
+ free(rep2);
+ return EACCES;
+ }
+ s++;
+
+ while ((tok = strtok_r(s, ",", &next))) {
+ hx509_san_type san_type, san_type2;
+ char *s2 = NULL;
+
+ s = NULL; /* for strtok_r() */
+
+ if (strncmp(tok, "eku=", sizeof("eku=") -1) == 0) {
+ /*
+ * Very simplistic handling of partial authz for EKUs:
+ *
+ * - denial of an EKU -> deny the whole request
+ * - else below mark all EKUs approved
+ */
+ if (strstr(tok, ":denied")) {
+ krb5_set_error_message(context, EACCES, "CSR denied because "
+ "EKU denied: %s", tok);
+ ret = EACCES;
+ break;
+ }
+ continue;
+ }
+
+ /*
+ * For SANs we check that the nth SAN in the response matches the nth
+ * SAN in the hx509_request.
+ */
+
+ if (strncmp(tok, "san_pkinit=", sizeof("san_pkinit=") - 1) == 0) {
+ tok += sizeof("san_pkinit=") - 1;
+ san_type = HX509_SAN_TYPE_PKINIT;
+ } else if (strncmp(tok, "san_dnsname=", sizeof("san_dnsname=") -1) == 0) {
+ tok += sizeof("san_dnsname=") - 1;
+ san_type = HX509_SAN_TYPE_DNSNAME;
+ } else if (strncmp(tok, "san_email=", sizeof("san_email=") -1) == 0) {
+ tok += sizeof("san_email=") - 1;
+ san_type = HX509_SAN_TYPE_EMAIL;
+ } else if (strncmp(tok, "san_xmpp=", sizeof("san_xmpp=") -1) == 0) {
+ tok += sizeof("san_xmpp=") - 1;
+ san_type = HX509_SAN_TYPE_XMPP;
+ } else if (strncmp(tok, "san_ms_upn=", sizeof("san_ms_upn=") -1) == 0) {
+ tok += sizeof("san_ms_upn=") - 1;
+ san_type = HX509_SAN_TYPE_MS_UPN;
+ } else {
+ krb5_set_error_message(context, EACCES, "CSR denied because could "
+ "not parse token in response: %s", tok);
+ ret = EACCES;
+ break;
+ }
+
+ /*
+ * This token has to end in ":granted" or ":denied". Using our
+ * `strrpbrk()' means we can deal with principals names that have ':'
+ * in them.
+ */
+ if ((p = strrpbrk(tok, ":")) == NULL) {
+ san_idx++;
+ continue;
+ }
+ *(p++) = '\0';
+
+ /* Now we get the nth SAN from the authorization */
+ ret = hx509_request_get_san(csr, san_idx, &san_type2, &s2);
+ if (ret == HX509_NO_ITEM) {
+ /* See below */
+ slow_path = 1;
+ break;
+ }
+
+ /* And we check that it matches the SAN in this token */
+ if (ret == 0) {
+ if (san_type != san_type2 ||
+ strcmp(tok, s2) != 0) {
+ /*
+ * We expect the tokens in the reply to be in the same order as
+ * in the request. If not, we must take a slow path where we
+ * have to sort requests and responses then iterate them in
+ * order.
+ */
+ slow_path = 1;
+ hx509_xfree(s2);
+ break;
+ }
+ hx509_xfree(s2);
+
+ if (strcmp(p, "granted") == 0) {
+ ret = hx509_request_authorize_san(csr, san_idx);
+ } else {
+ partial = 1;
+ ret = hx509_request_reject_san(csr, san_idx);
+ }
+ if (ret)
+ break;
+ }
+ san_idx++;
+ }
+
+ if (slow_path) {
+ /*
+ * FIXME? Implement the slow path?
+ *
+ * Basically, we'd get all the SANs from the request into an array of
+ * {SAN, index} and sort that array, then all the SANs from the
+ * response into an array and sort it, then step a cursor through both,
+ * using the index from the first to mark SANs in the request
+ * authorized or rejected.
+ */
+ krb5_set_error_message(context, EACCES, "CSR denied because "
+ "authorizer service did not include all "
+ "piecemeal grants/denials in order");
+ ret = EACCES;
+ }
+
+ /* Mark all the EKUs authorized */
+ for (eku_idx = 0; ret == 0; eku_idx++)
+ ret = hx509_request_authorize_eku(csr, eku_idx);
+ if (ret == HX509_NO_ITEM)
+ ret = 0;
+ if (ret == 0 && partial) {
+ krb5_set_error_message(context, EACCES, "CSR partially authorized");
+ ret = EACCES;
+ }
+
+ free(rep2);
+ return ret;
+}
+
+static krb5_error_code mark_authorized(hx509_request);
+
+static int
+call_svc(krb5_context context,
+ heim_ipc ipc,
+ hx509_request csr,
+ const char *cmd,
+ int piecemeal_check_ok)
{
heim_octet_string req, resp;
int ret;
@@ -207,40 +388,66 @@ call_svc(krb5_context context, heim_ipc ipc, const char *cmd)
req.length = strlen(cmd);
resp.length = 0;
resp.data = NULL;
- if ((ret = heim_ipc_call(ipc, &req, &resp, NULL))) {
- if (resp.length && resp.length < INT_MAX) {
- krb5_set_error_message(context, ret, "CSR denied: %.*s",
- (int)resp.length, (const char *)resp.data);
- ret = EACCES;
- } else {
- krb5_set_error_message(context, EACCES, "CSR denied because could "
- "not reach CSR authorizer IPC service");
+ ret = heim_ipc_call(ipc, &req, &resp, NULL);
+
+ /* Check for all granted case */
+ if (ret == 0 &&
+ resp.length == sizeof("granted") - 1 &&
+ strncasecmp(resp.data, "granted", sizeof("granted") - 1) == 0) {
+ free(resp.data);
+ return mark_authorized(csr); /* Full approval */
+ }
+
+ /* Check for "denied ..." piecemeal authorization case */
+ if ((ret == 0 || ret == EACCES || ret == KRB5_PLUGIN_NO_HANDLE) &&
+ piecemeal_check_ok &&
+ resp.length > sizeof("denied") - 1 &&
+ strncasecmp(resp.data, "denied", sizeof("denied") - 1) == 0) {
+ /* Piecemeal authorization */
+ ret = mark_piecemeal_authorized(context, csr, &resp);
+
+ /* mark_piecemeal_authorized() should return EACCES; just in case: */
+ if (ret == 0)
ret = EACCES;
- }
+ free(resp.data);
return ret;
}
+
+ /* All other failure cases */
+
if (resp.data == NULL || resp.length == 0) {
- free(resp.data);
krb5_set_error_message(context, ret, "CSR authorizer IPC service "
"failed silently");
+ free(resp.data);
return EACCES;
}
+
+ if (resp.length == sizeof("ignore") - 1 &&
+ strncasecmp(resp.data, "ignore", sizeof("ignore") - 1) == 0) {
+ /*
+ * In this case the server is saying "I can't handle this request, try
+ * some other authorizer plugin".
+ */
+ free(resp.data);
+ return KRB5_PLUGIN_NO_HANDLE;
+ }
+
if (resp.length == sizeof("denied") - 1 &&
strncasecmp(resp.data, "denied", sizeof("denied") - 1) == 0) {
- free(resp.data);
krb5_set_error_message(context, ret, "CSR authorizer rejected %s",
cmd);
- return EACCES;
- }
- if (resp.length == sizeof("granted") - 1 &&
- strncasecmp(resp.data, "granted", sizeof("granted") - 1) == 0) {
free(resp.data);
- return 0;
+ return EACCES;
}
- krb5_set_error_message(context, ret, "CSR authorizer failed %s: %.*s",
- cmd, resp.length < INT_MAX ? (int)resp.length : 0,
- resp.data);
- return EACCES;
+
+ if (resp.length > INT_MAX)
+ krb5_set_error_message(context, ret, "CSR authorizer rejected %s", cmd);
+ else
+ krb5_set_error_message(context, ret, "CSR authorizer rejected %s: %.*s",
+ cmd, resp.length, resp.data);
+
+ free(resp.data);
+ return ret;
}
static void
@@ -294,13 +501,25 @@ authorize(void *ctx,
char *princ = NULL;
char *s = NULL;
int do_check = 0;
+ int piecemeal_check_ok = 1;
- if ((svc = krb5_config_get_string(context, NULL, app ? app : "kdc",
- "ipc_csr_authorizer", "service", NULL))
- == NULL)
+ if ((svc = krb5_config_get_string_default(context, NULL,
+ "ANY:org.h5l.csr_authorizer",
+ app ? app : "kdc",
+ "ipc_csr_authorizer", "service",
+ NULL)) == NULL)
return KRB5_PLUGIN_NO_HANDLE;
if ((ret = heim_ipc_init_context(svc, &ipc))) {
+ /*
+ * If the IPC authorizer is optional, then fallback on whatever is
+ * next.
+ */
+ if (krb5_config_get_bool_default(context, NULL, FALSE,
+ app ? app : "kdc",
+ "ipc_csr_authorizer", "optional",
+ NULL))
+ return KRB5_PLUGIN_NO_HANDLE;
krb5_set_error_message(context, ret, "Could not set up IPC client "
"end-point for service %s", svc);
return ret;
@@ -318,10 +537,22 @@ authorize(void *ctx,
for (i = 0; ret == 0; i++) {
hx509_san_type san_type;
+ size_t p;
ret = hx509_request_get_san(csr, i, &san_type, &s);
if (ret)
break;
+
+ /*
+ * We cannot do a piecemeal check if any of the SANs could make the
+ * response ambiguous.
+ */
+ p = strcspn(s, ",= ");
+ if (s[p] != '\0')
+ piecemeal_check_ok = 0;
+ if (piecemeal_check_ok && strstr(s, ":granted") != NULL)
+ piecemeal_check_ok = 0;
+
switch (san_type) {
case HX509_SAN_TYPE_EMAIL:
if ((ret = cmd_append(&cmd, " san_email=", s, NULL)))
@@ -380,15 +611,13 @@ authorize(void *ctx,
hx509_request_authorize_ku(csr, ku);
if (do_check) {
- if ((s = rk_strpoolcollect(cmd)) == NULL)
- goto enomem;
+ s = rk_strpoolcollect(cmd);
cmd = NULL;
- if ((ret = call_svc(context, ipc, s)))
+ if (s == NULL)
+ goto enomem;
+ if ((ret = call_svc(context, ipc, csr, s, piecemeal_check_ok)))
goto out;
- } /* else -> permit */
-
- if ((ret = mark_authorized(csr)))
- goto out;
+ } /* else there was nothing to check -> permit */
*result = TRUE;
ret = 0;
diff --git a/third_party/heimdal/kdc/kdc-plugin.c b/third_party/heimdal/kdc/kdc-plugin.c
index 925c250597a..c575d7df479 100644
--- a/third_party/heimdal/kdc/kdc-plugin.c
+++ b/third_party/heimdal/kdc/kdc-plugin.c
@@ -51,7 +51,7 @@ static const char *kdc_plugin_deps[] = {
static struct heim_plugin_data kdc_plugin_data = {
"krb5",
"kdc",
- KRB5_PLUGIN_KDC_VERSION_10,
+ KRB5_PLUGIN_KDC_VERSION_11,
kdc_plugin_deps,
kdc_get_instance
};
@@ -145,7 +145,8 @@ struct verify_uc {
hdb_entry *client;
hdb_entry *server;
hdb_entry *krbtgt;
- krb5_pac *pac;
+ krb5_pac pac;
+ krb5_boolean *is_trusted;
};
static krb5_error_code KRB5_LIB_CALL
@@ -162,7 +163,8 @@ verify(krb5_context context, const void *plug, void *plugctx, void *userctx)
uc->r,
uc->client_principal,
uc->delegated_proxy_principal,
- uc->client, uc->server, uc->krbtgt, uc->pac);
+ uc->client, uc->server, uc->krbtgt, uc->pac,
+ uc->is_trusted);
return ret;
}
@@ -173,7 +175,8 @@ _kdc_pac_verify(astgs_request_t r,
hdb_entry *client,
hdb_entry *server,
hdb_entry *krbtgt,
- krb5_pac *pac)
+ krb5_pac pac,
+ krb5_boolean *is_trusted)
{
struct verify_uc uc;
@@ -187,11 +190,66 @@ _kdc_pac_verify(astgs_request_t r,
uc.server = server;
uc.krbtgt = krbtgt;
uc.pac = pac;
+ uc.is_trusted = is_trusted;
return _krb5_plugin_run_f(r->context, &kdc_plugin_data,
0, &uc, verify);
}
+struct update_uc {
+ astgs_request_t r;
+ krb5_principal client_principal;
+ krb5_principal delegated_proxy_principal;
+ hdb_entry *client;
+ hdb_entry *server;
+ hdb_entry *krbtgt;
+ krb5_pac *pac;
+};
+
+static krb5_error_code KRB5_LIB_CALL
+update(krb5_context context, const void *plug, void *plugctx, void *userctx)
+{
+ const krb5plugin_kdc_ftable *ft = (const krb5plugin_kdc_ftable *)plug;
+ struct update_uc *uc = (struct update_uc *)userctx;
+ krb5_error_code ret;
+
+ if (ft->pac_update == NULL)
+ return KRB5_PLUGIN_NO_HANDLE;
+
+ ret = ft->pac_update((void *)plug,
+ uc->r,
+ uc->client_principal,
+ uc->delegated_proxy_principal,
+ uc->client, uc->server, uc->krbtgt, uc->pac);
+ return ret;
+}
+
+krb5_error_code
+_kdc_pac_update(astgs_request_t r,
+ const krb5_principal client_principal,
+ const krb5_principal delegated_proxy_principal,
+ hdb_entry *client,
+ hdb_entry *server,
+ hdb_entry *krbtgt,
+ krb5_pac *pac)
+{
+ struct update_uc uc;
+
+ if (!have_plugin)
+ return KRB5_PLUGIN_NO_HANDLE;
+
+ uc.r = r;
+ uc.client_principal = client_principal;
+ uc.delegated_proxy_principal = delegated_proxy_principal;
+ uc.client = client;
+ uc.server = server;
+ uc.krbtgt = krbtgt;
+ uc.pac = pac;
+
+ return _krb5_plugin_run_f(r->context, &kdc_plugin_data,
+ 0, &uc, update);
+}
+
static krb5_error_code KRB5_LIB_CALL
check(krb5_context context, const void *plug, void *plugctx, void *userctx)
{
diff --git a/third_party/heimdal/kdc/kdc-plugin.h b/third_party/heimdal/kdc/kdc-plugin.h
index 05286257bf7..4ec92a575b3 100644
--- a/third_party/heimdal/kdc/kdc-plugin.h
+++ b/third_party/heimdal/kdc/kdc-plugin.h
@@ -57,8 +57,9 @@ typedef krb5_error_code
/*
* Verify the PAC KDC signatures by fetching the appropriate TGS key
- * and calling krb5_pac_verify() with that key. Optionally update the
- * PAC buffers on success.
+ * and calling krb5_pac_verify() with that key. The possibly-NULL
+ * is_trusted may be set by the plugin to indicate that the PAC was
+ * issued by a trusted server, and not, for example, by an RODC.
*/
typedef krb5_error_code
@@ -69,7 +70,25 @@ typedef krb5_error_code
hdb_entry *,/* client */
hdb_entry *,/* server */
hdb_entry *,/* krbtgt */
- krb5_pac *);
+ krb5_pac, /* pac */
+ krb5_boolean *); /* is_trusted */
+
+/*
+ * Update the KDC PAC buffers. This function may be used after verifying the PAC
+ * with a call to krb5plugin_kdc_pac_verify(), and it resembles the latter
+ * function in the parameters it takes. The 'pac' parameter always points to a
+ * non-NULL PAC.
+ */
+
+typedef krb5_error_code
+(KRB5_CALLCONV *krb5plugin_kdc_pac_update)(void *,
+ astgs_request_t,
+ const krb5_principal, /* new ticket client */
+ const krb5_principal, /* delegation proxy */
+ hdb_entry *,/* client */
+ hdb_entry *,/* server */
+ hdb_entry *,/* krbtgt */
+ krb5_pac *); /* pac */
/*
* Authorize the client principal's access to the Authentication Service (AS).
@@ -117,12 +136,13 @@ typedef krb5_error_code
* Plugins should carefully check API contract notes for changes
* between plugin API versions.
*/
-#define KRB5_PLUGIN_KDC_VERSION_10 10
+#define KRB5_PLUGIN_KDC_VERSION_11 11
typedef struct krb5plugin_kdc_ftable {
HEIM_PLUGIN_FTABLE_COMMON_ELEMENTS(krb5_context);
krb5plugin_kdc_pac_generate pac_generate;
krb5plugin_kdc_pac_verify pac_verify;
+ krb5plugin_kdc_pac_update pac_update;
krb5plugin_kdc_client_access client_access;
krb5plugin_kdc_referral_policy referral_policy;
krb5plugin_kdc_finalize_reply finalize_reply;
diff --git a/third_party/heimdal/kdc/kdc-tester.c b/third_party/heimdal/kdc/kdc-tester.c
index 65d52ec66a4..beb9e1f4a23 100644
--- a/third_party/heimdal/kdc/kdc-tester.c
+++ b/third_party/heimdal/kdc/kdc-tester.c
@@ -195,11 +195,14 @@ copy_keytab(krb5_context context, krb5_keytab from, krb5_keytab to)
ret = krb5_kt_start_seq_get(context, from, &cursor);
if (ret)
return ret;
- while((ret = krb5_kt_next_entry(context, from, &entry, &cursor)) == 0){
+ while ((ret = krb5_kt_next_entry(context, from, &entry, &cursor)) == 0){
krb5_kt_add_entry(context, to, &entry);
krb5_kt_free_entry(context, &entry);
}
- return krb5_kt_end_seq_get(context, from, &cursor);
+ (void) krb5_kt_end_seq_get(context, from, &cursor);
+ if (ret == KRB5_KT_END)
+ return 0;
+ return ret;
}
/*
diff --git a/third_party/heimdal/kdc/kerberos5.c b/third_party/heimdal/kdc/kerberos5.c
index e75686c625a..ecca52cdcdd 100644
--- a/third_party/heimdal/kdc/kerberos5.c
+++ b/third_party/heimdal/kdc/kerberos5.c
@@ -2079,13 +2079,11 @@ get_local_tgs(krb5_context context,
KRB5_TGS_NAME,
realm,
NULL);
- if (ret)
- return ret;
+ if (ret == 0)
+ ret = _kdc_db_fetch(context, config, tgs_name,
+ HDB_F_GET_KRBTGT, NULL, krbtgtdb, krbtgt);
- ret = _kdc_db_fetch(context, config, tgs_name,
- HDB_F_GET_KRBTGT, NULL, krbtgtdb, krbtgt);
krb5_free_principal(context, tgs_name);
-
return ret;
}
diff --git a/third_party/heimdal/kdc/krb5tgs.c b/third_party/heimdal/kdc/krb5tgs.c
index 71991c17975..0bad42aa3b7 100644
--- a/third_party/heimdal/kdc/krb5tgs.c
+++ b/third_party/heimdal/kdc/krb5tgs.c
@@ -96,6 +96,7 @@ _kdc_check_pac(astgs_request_t r,
krb5_pac pac = NULL;
krb5_error_code ret;
krb5_boolean signedticket;
+ krb5_boolean is_trusted = FALSE;
*kdc_issued = FALSE;
*ppac = NULL;
@@ -122,32 +123,25 @@ _kdc_check_pac(astgs_request_t r,
return ret;
}
- if (pac_canon_name) {
- ret = _krb5_pac_get_canon_principal(context, pac, pac_canon_name);
- if (ret && ret != ENOENT) {
- krb5_pac_free(context, pac);
- return ret;
- }
- }
- if (pac_attributes) {
- ret = _krb5_pac_get_attributes_info(context, pac, pac_attributes);
- if (ret && ret != ENOENT) {
- krb5_pac_free(context, pac);
- return ret;
- }
- if (ret == ENOENT)
- *pac_attributes = KRB5_PAC_WAS_GIVEN_IMPLICITLY;
- }
-
/* Verify the KDC signatures. */
ret = _kdc_pac_verify(r,
client_principal, delegated_proxy_principal,
- client, server, krbtgt, &pac);
+ client, server, krbtgt, pac, &is_trusted);
if (ret == 0) {
- if (pac == NULL) {
- /* the plugin may indicate no PAC should be generated */
- *pac_attributes = 0;
+ if (is_trusted) {
+ krb5_pac_set_trusted(pac, true);
}
+
+ if (pac_canon_name) {
+ ret = _krb5_pac_get_canon_principal(context, pac, pac_canon_name);
+ if (ret && ret != ENOENT) {
+ krb5_pac_free(context, pac);
+ return ret;
+ }
+ }
+ if (pac_attributes &&
+ _krb5_pac_get_attributes_info(context, pac, pac_attributes) != 0)
+ *pac_attributes = KRB5_PAC_WAS_GIVEN_IMPLICITLY;
} else if (ret == KRB5_PLUGIN_NO_HANDLE) {
/*
* We can't verify the KDC signatures if the ticket was issued by
@@ -163,6 +157,17 @@ _kdc_check_pac(astgs_request_t r,
}
}
+ if (pac_canon_name) {
+ ret = _krb5_pac_get_canon_principal(context, pac, pac_canon_name);
+ if (ret && ret != ENOENT) {
+ krb5_pac_free(context, pac);
+ return ret;
+ }
+ }
+ if (pac_attributes &&
+ _krb5_pac_get_attributes_info(context, pac, pac_attributes) != 0)
+ *pac_attributes = KRB5_PAC_WAS_GIVEN_IMPLICITLY;
+
/* Discard the PAC if the plugin didn't handle it */
krb5_pac_free(context, pac);
ret = krb5_pac_init(context, &pac);
@@ -1051,8 +1056,9 @@ next_kvno:
} else if (ret) {
char *str = NULL, *p = NULL;
- krb5_enctype_to_string(r->context, ap_req.ticket.enc_part.etype, &str);
- krb5_unparse_name(r->context, princ, &p);
+ /* We should implement the MIT `trace_format()' concept */
+ (void) krb5_enctype_to_string(r->context, ap_req.ticket.enc_part.etype, &str);
+ (void) krb5_unparse_name(r->context, princ, &p);
kdc_log(r->context, config, 4,
"No server key with enctype %s found for %s",
str ? str : "<unknown enctype>",
@@ -1327,6 +1333,7 @@ _kdc_db_fetch_client(krb5_context context,
krb5_error_code ret;
hdb_entry *client = NULL;
+ *clientdb = NULL;
*client_out = NULL;
ret = _kdc_db_fetch(context, config, cp, HDB_F_GET_CLIENT | flags,
@@ -1382,7 +1389,7 @@ tgs_build_reply(astgs_request_t priv,
char *user2user_name = NULL;
HDB *user2user_krbtgtdb;
hdb_entry *user2user_krbtgt = NULL;
- HDB *clientdb;
+ HDB *clientdb = NULL;
HDB *serverdb = NULL;
krb5_realm ref_realm = NULL;
EncTicketPart *tgt = &priv->ticket->ticket;
@@ -1896,9 +1903,16 @@ server_lookup:
cpn, our_realm, &clientdb, &priv->client);
if (ret)
goto out;
- flags &= ~HDB_F_SYNTHETIC_OK;
+ /* flags &= ~HDB_F_SYNTHETIC_OK; */ /* `flags' is not used again below */
priv->clientdb = clientdb;
+ /* Validate armor TGT before potentially including device claims */
+ if (priv->armor_ticket) {
+ ret = _kdc_fast_check_armor_pac(priv);
+ if (ret)
+ goto out;
+ }
+
ret = _kdc_check_pac(priv, priv->client_princ, NULL,
priv->client, priv->server,
priv->krbtgt, priv->krbtgt,
@@ -1915,6 +1929,29 @@ server_lookup:
goto out;
}
+ if (priv->pac != NULL) {
+ ret = _kdc_pac_update(priv, priv->client_princ, NULL,
+ priv->client, priv->server, priv->krbtgt,
+ &priv->pac);
+ if (ret == KRB5_PLUGIN_NO_HANDLE) {
+ ret = 0;
+ }
+ if (ret) {
+ const char *msg = krb5_get_error_message(context, ret);
+ kdc_audit_addreason((kdc_request_t)priv, "PAC update failed");
+ kdc_log(context, config, 4,
+ "Update PAC failed for %s (%s) from %s with %s",
+ spn, cpn, from, msg);
+ krb5_free_error_message(context, msg);
+ goto out;
+ }
+
+ if (priv->pac == NULL) {
+ /* the plugin may indicate no PAC should be generated */
+ priv->pac_attributes = 0;
+ }
+ }
+
/*
* Process request
*/
@@ -2011,13 +2048,6 @@ server_lookup:
if (kdc_issued &&
!krb5_principal_is_krbtgt(context, priv->server->principal)) {
- /* Validate armor TGT before potentially including device claims */
- if (priv->armor_ticket) {
- ret = _kdc_fast_check_armor_pac(priv);
- if (ret)
- goto out;
- }
-
add_ticket_sig = TRUE;
}
diff --git a/third_party/heimdal/kdc/misc.c b/third_party/heimdal/kdc/misc.c
index eab8107935f..477e4fabfb2 100644
--- a/third_party/heimdal/kdc/misc.c
+++ b/third_party/heimdal/kdc/misc.c
@@ -139,6 +139,8 @@ _kdc_db_fetch(krb5_context context,
krb5_const_principal princ;
*h = NULL;
+ if (db)
+ *db = NULL;
if (!name_type_ok(context, config, principal))
return HDB_ERR_NOENTRY;
diff --git a/third_party/heimdal/kdc/mit_dump.c b/third_party/heimdal/kdc/mit_dump.c
index 32cf5dc65ce..af380bbe378 100644
--- a/third_party/heimdal/kdc/mit_dump.c
+++ b/third_party/heimdal/kdc/mit_dump.c
@@ -104,7 +104,7 @@ my_fgetln(FILE *f, char **bufp, size_t *szp, size_t *lenp)
size_t len;
size_t sz = *szp;
char *buf = *bufp;
- char *p, *n;
+ char *n;
if (!buf) {
buf = malloc(sz ? sz : 8192);
@@ -115,7 +115,7 @@ my_fgetln(FILE *f, char **bufp, size_t *szp, size_t *lenp)
}
len = 0;
- while ((p = fgets(&buf[len], sz-len, f)) != NULL) {
+ while (fgets(&buf[len], sz-len, f) != NULL) {
len += strlen(&buf[len]);
if (buf[len-1] == '\n')
break;
diff --git a/third_party/heimdal/kdc/mssfu.c b/third_party/heimdal/kdc/mssfu.c
index fda5a37b1c6..a88de097a9b 100644
--- a/third_party/heimdal/kdc/mssfu.c
+++ b/third_party/heimdal/kdc/mssfu.c
@@ -501,6 +501,26 @@ validate_constrained_delegation(astgs_request_t r)
goto out;
}
+ heim_assert(s4u_pac != NULL, "ad_kdc_issued implies the PAC is non-NULL");
+
+ ret = _kdc_pac_update(r, s4u_client_name, s4u_server_name,
+ s4u_client, r->server, r->krbtgt,
+ &s4u_pac);
+ if (ret == KRB5_PLUGIN_NO_HANDLE) {
+ ret = 0;
+ }
+ if (ret) {
+ const char *msg = krb5_get_error_message(r->context, ret);
+ kdc_audit_addreason((kdc_request_t)r,
+ "Constrained delegation ticket PAC update failed");
+ kdc_log(r->context, r->config, 4,
+ "Update delegated PAC failed to %s for client"
+ "%s (%s) as %s from %s with %s",
+ r->sname, r->cname, s4usname, s4ucname, r->from, msg);
+ krb5_free_error_message(r->context, msg);
+ goto out;
+ }
+
/*
* If the evidence ticket PAC didn't include PAC_UPN_DNS_INFO with
* the canonical client name, but the user is local to our KDC, we
diff --git a/third_party/heimdal/kdc/pkinit-ec.c b/third_party/heimdal/kdc/pkinit-ec.c
index c718aa79962..31a5fe7dec5 100644
--- a/third_party/heimdal/kdc/pkinit-ec.c
+++ b/third_party/heimdal/kdc/pkinit-ec.c
@@ -52,10 +52,16 @@
*/
#ifdef HAVE_HCRYPTO_W_OPENSSL
-#include <openssl/ec.h>
-#include <openssl/ecdh.h>
#include <openssl/evp.h>
+#include <openssl/ec.h>
+#include <openssl/ecdsa.h>
+#include <openssl/rsa.h>
#include <openssl/bn.h>
+#include <openssl/dh.h>
+#include <openssl/objects.h>
+#ifdef HAVE_OPENSSL_30
+#include <openssl/core_names.h>
+#endif
#define HEIM_NO_CRYPTO_HDRS
#endif /* HAVE_HCRYPTO_W_OPENSSL */
@@ -69,37 +75,101 @@
#include <pkinit_asn1.h>
#include <hx509.h>
-
-#ifdef HAVE_HCRYPTO_W_OPENSSL
-static void
-free_client_ec_param(krb5_context context,
- EC_KEY *ec_key_pk,
- EC_KEY *ec_key_key)
-{
- if (ec_key_pk != NULL)
- EC_KEY_free(ec_key_pk);
- if (ec_key_key != NULL)
- EC_KEY_free(ec_key_key);
-}
-#endif
+#include "../lib/hx509/hx_locl.h"
+#include <hx509-private.h>
void
_kdc_pk_free_client_ec_param(krb5_context context,
- void *ec_key_pk,
- void *ec_key_key)
+ void *k0,
+ void *k1)
{
#ifdef HAVE_HCRYPTO_W_OPENSSL
- free_client_ec_param(context, ec_key_pk, ec_key_key);
+#ifdef HAVE_OPENSSL_30
+ EVP_PKEY_free(k0);
+ EVP_PKEY_free(k1);
+#else
+ EC_KEY_free(k0);
+ EC_KEY_free(k1);
+#endif
#endif
}
#ifdef HAVE_HCRYPTO_W_OPENSSL
+#ifdef HAVE_OPENSSL_30
+static krb5_error_code
+generate_ecdh_keyblock_ossl30(krb5_context context,
+ EVP_PKEY *ec_key_pub, /* the client's public key */
+ EVP_PKEY **ec_key_priv, /* the KDC's ephemeral private */
+ unsigned char **dh_gen_key, /* shared secret */
+ size_t *dh_gen_keylen)
+{
+ EVP_PKEY_CTX *pctx = NULL;
+ EVP_PKEY *ephemeral = NULL;
+ krb5_error_code ret = 0;
+ unsigned char *p = NULL;
+ size_t size = 0;
+
+ if (ec_key_pub == NULL)
+ /* XXX This seems like an internal error that should be impossible */
+ krb5_set_error_message(context, ret = KRB5KRB_ERR_GENERIC,
+ "Missing client ECDH key agreement public key");
+ if (ret == 0 &&
+ (ephemeral =
+ EVP_EC_gen(OSSL_EC_curve_nid2name(NID_X9_62_prime256v1))) == NULL)
+ krb5_set_error_message(context, ret = KRB5KRB_ERR_GENERIC,
+ "Could not generate an ECDH key agreement private key");
+ if (ret == 0 &&
+ (pctx = EVP_PKEY_CTX_new(ephemeral, NULL)) == NULL)
+ ret = krb5_enomem(context);
+ if (ret == 0 && EVP_PKEY_derive_init(pctx) != 1)
+ ret = krb5_enomem(context);
+ if (ret == 0 &&
+ EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, EVP_PKEY_ECDH_KDF_NONE) != 1)
+ krb5_set_error_message(context, ret = KRB5KRB_ERR_GENERIC,
+ "Could not generate an ECDH key agreement private key "
+ "(EVP_PKEY_CTX_set_dh_kdf_type)");
+ if (ret == 0 &&
+ EVP_PKEY_derive_set_peer_ex(pctx, ec_key_pub, 1) != 1)
+ krb5_set_error_message(context, ret = KRB5KRB_ERR_GENERIC,
+ "Could not generate an ECDH key agreement private key "
+ "(EVP_PKEY_derive_set_peer_ex)");
+ if (ret == 0 &&
+ (EVP_PKEY_derive(pctx, NULL, &size) != 1 || size == 0))
+ krb5_set_error_message(context, ret = KRB5KRB_ERR_GENERIC,
+ "Could not generate an ECDH key agreement private key "
+ "(EVP_PKEY_derive)");
+ if (ret == 0 && (p = malloc(size)) == NULL)
+ ret = krb5_enomem(context);
+ if (ret == 0 &&
+ (EVP_PKEY_derive(pctx, p, &size) != 1 || size == 0))
+ krb5_set_error_message(context, ret = KRB5KRB_ERR_GENERIC,
+ "Could not generate an ECDH key agreement private key "
+ "(EVP_PKEY_derive)");
+
+ if (ret) {
+ EVP_PKEY_free(ephemeral);
+ ephemeral = NULL;
+ free(p);
+ p = NULL;
+ size = 0;
+ }
+
+ *ec_key_priv = ephemeral;
+ *dh_gen_keylen = size;
+ *dh_gen_key = p;
+
+ EVP_PKEY_CTX_free(pctx);
+ return ret;
+}
+#else
+
+/* The empty line above is intentional to work around an mkproto bug */
static krb5_error_code
-generate_ecdh_keyblock(krb5_context context,
- EC_KEY *ec_key_pk, /* the client's public key */
- EC_KEY **ec_key_key, /* the KDC's ephemeral private */
- unsigned char **dh_gen_key, /* shared secret */
- size_t *dh_gen_keylen)
+generate_ecdh_keyblock_ossl11(krb5_context context,
+ EC_KEY *ec_key_pk, /* the client's public key */
+ EC_KEY **ec_key_key, /* the KDC's ephemeral private */
+ unsigned char **dh_gen_key, /* shared secret */
+ size_t *dh_gen_keylen)
{
const EC_GROUP *group;
EC_KEY *ephemeral;
@@ -136,7 +206,7 @@ generate_ecdh_keyblock(krb5_context context,
EC_KEY_set_group(ephemeral, group);
if (EC_KEY_generate_key(ephemeral) != 1) {
- EC_KEY_free(ephemeral);
+ EC_KEY_free(ephemeral);
return krb5_enomem(context);
}
@@ -165,6 +235,7 @@ generate_ecdh_keyblock(krb5_context context,
return 0;
}
+#endif
#endif /* HAVE_HCRYPTO_W_OPENSSL */
krb5_error_code
@@ -175,20 +246,128 @@ _kdc_generate_ecdh_keyblock(krb5_context context,
size_t *dh_gen_keylen)
{
#ifdef HAVE_HCRYPTO_W_OPENSSL
- return generate_ecdh_keyblock(context, ec_key_pk,
- (EC_KEY **)ec_key_key,
- dh_gen_key, dh_gen_keylen);
+#ifdef HAVE_OPENSSL_30
+ return generate_ecdh_keyblock_ossl30(context, ec_key_pk,
+ (EVP_PKEY **)ec_key_key,
+ dh_gen_key, dh_gen_keylen);
+#else
+ return generate_ecdh_keyblock_ossl11(context, ec_key_pk,
+ (EC_KEY **)ec_key_key,
+ dh_gen_key, dh_gen_keylen);
+#endif
#else
return ENOTSUP;
#endif /* HAVE_HCRYPTO_W_OPENSSL */
}
#ifdef HAVE_HCRYPTO_W_OPENSSL
+#ifdef HAVE_OPENSSL_30
static krb5_error_code
-get_ecdh_param(krb5_context context,
- krb5_kdc_configuration *config,
- SubjectPublicKeyInfo *dh_key_info,
- EC_KEY **out)
+get_ecdh_param_ossl30(krb5_context context,
+ krb5_kdc_configuration *config,
+ SubjectPublicKeyInfo *dh_key_info,
+ EVP_PKEY **out)
+{
+ EVP_PKEY_CTX *pctx = NULL;
+ EVP_PKEY *template = NULL;
+ EVP_PKEY *public = NULL;
+ OSSL_PARAM params[2];
+ krb5_error_code ret = 0;
+ ECParameters ecp;
+ const unsigned char *p;
+ const char *curve_sn = NULL;
+ size_t len;
+ char *curve_sn_dup = NULL;
+ int groupnid = NID_undef;
+
+ /* XXX Algorithm agility; XXX KRB5_BADMSGTYPE?? */
+
+ /*
+ * In order for d2i_PublicKey() to work we need to create a template key
+ * that has the curve parameters for the subjectPublicKey.
+ *
+ * Or maybe we could learn to use the OSSL_DECODER(3) API. But this works,
+ * at least until OpenSSL deprecates d2i_PublicKey() and forces us to use
+ * OSSL_DECODER(3).
+ */
+
+ memset(&ecp, 0, sizeof(ecp));
+
+ if (dh_key_info->algorithm.parameters == NULL)
+ krb5_set_error_message(context, ret = KRB5_BADMSGTYPE,
+ "PKINIT missing algorithm parameter "
+ "in clientPublicValue");
+ if (ret == 0)
+ ret = decode_ECParameters(dh_key_info->algorithm.parameters->data,
+ dh_key_info->algorithm.parameters->length,
+ &ecp, &len);
+ if (ret == 0 && ecp.element != choice_ECParameters_namedCurve)
+ krb5_set_error_message(context, ret = KRB5_BADMSGTYPE,
+ "PKINIT client used an unnamed curve");
+ if (ret == 0 &&
+ (groupnid = _hx509_ossl_oid2nid(&ecp.u.namedCurve)) == NID_undef)
+ krb5_set_error_message(context, ret = KRB5_BADMSGTYPE,
+ "PKINIT client used an unsupported curve");
+ if (ret == 0 && (curve_sn = OBJ_nid2sn(groupnid)) == NULL)
+ krb5_set_error_message(context, ret = KRB5_BADMSGTYPE,
+ "Could not resolve curve NID %d to its short name",
+ groupnid);
+ if (ret == 0 && (curve_sn_dup = strdup(curve_sn)) == NULL)
+ ret = krb5_enomem(context);
+ if (ret == 0) {
+ if (der_heim_oid_cmp(&ecp.u.namedCurve, &asn1_oid_id_ec_group_secp256r1) != 0)
+ krb5_set_error_message(context, ret = KRB5_BADMSGTYPE,
+ "PKINIT client used an unsupported curve");
+ }
+ if (ret == 0) {
+ /*
+ * Apparently there's no error checking to be done here? Why does
+ * OSSL_PARAM_construct_utf8_string() want a non-const for the value?
+ * Is that a bug in OpenSSL?
+ */
+ params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
+ curve_sn_dup, 0);
+ params[1] = OSSL_PARAM_construct_end();
+
+ if ((pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL)) == NULL)
+ ret = krb5_enomem(context);
+ }
+ if (ret == 0 && EVP_PKEY_fromdata_init(pctx) != 1)
+ ret = krb5_enomem(context);
+ if (ret == 0 &&
+ EVP_PKEY_fromdata(pctx, &template, OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
+ params) != 1)
+ krb5_set_error_message(context, ret = KRB5_BADMSGTYPE,
+ "Could not set up to parse key for curve %s",
+ curve_sn);
+
+ p = dh_key_info->subjectPublicKey.data;
+ len = dh_key_info->subjectPublicKey.length / 8;
+ if (ret == 0 &&
+ (public = d2i_PublicKey(EVP_PKEY_EC, &template, &p, len)) == NULL)
+ krb5_set_error_message(context, ret = KRB5_BADMSGTYPE,
+ "Could not decode PKINIT client ECDH key");
+
+ if (ret) {
+ EVP_PKEY_free(public);
+ public = NULL;
+ }
+
+ *out = public;
+
+ /* FYI the EVP_PKEY_CTX takes ownership of the `template' key */
+ EVP_PKEY_CTX_free(pctx);
+ free_ECParameters(&ecp);
+ free(curve_sn_dup);
+ return ret;
+}
+#else
+
+static krb5_error_code
+get_ecdh_param_ossl11(krb5_context context,
+ krb5_kdc_configuration *config,
+ SubjectPublicKeyInfo *dh_key_info,
+ EC_KEY **out)
{
ECParameters ecp;
EC_KEY *public = NULL;
@@ -198,30 +377,31 @@ get_ecdh_param(krb5_context context,
int nid;
if (dh_key_info->algorithm.parameters == NULL) {
- krb5_set_error_message(context, KRB5_BADMSGTYPE,
- "PKINIT missing algorithm parameter "
- "in clientPublicValue");
- return KRB5_BADMSGTYPE;
+ krb5_set_error_message(context, KRB5_BADMSGTYPE,
+ "PKINIT missing algorithm parameter "
+ "in clientPublicValue");
+ return KRB5_BADMSGTYPE;
}
+ /* XXX Algorithm agility; XXX KRB5_BADMSGTYPE?? */
memset(&ecp, 0, sizeof(ecp));
ret = decode_ECParameters(dh_key_info->algorithm.parameters->data,
- dh_key_info->algorithm.parameters->length, &ecp, &len);
+ dh_key_info->algorithm.parameters->length, &ecp, &len);
if (ret)
- goto out;
+ goto out;
if (ecp.element != choice_ECParameters_namedCurve) {
- ret = KRB5_BADMSGTYPE;
- goto out;
+ ret = KRB5_BADMSGTYPE;
+ goto out;
}
if (der_heim_oid_cmp(&ecp.u.namedCurve, &asn1_oid_id_ec_group_secp256r1) == 0)
- nid = NID_X9_62_prime256v1;
+ nid = NID_X9_62_prime256v1;
else {
- ret = KRB5_BADMSGTYPE;
- goto out;
- }
+ ret = KRB5_BADMSGTYPE;
+ goto out;
+ }
/* XXX verify group is ok */
@@ -230,20 +410,21 @@ get_ecdh_param(krb5_context context,
p = dh_key_info->subjectPublicKey.data;
len = dh_key_info->subjectPublicKey.length / 8;
if (o2i_ECPublicKey(&public, &p, len) == NULL) {
- ret = KRB5_BADMSGTYPE;
- krb5_set_error_message(context, ret,
- "PKINIT failed to decode ECDH key");
- goto out;
+ ret = KRB5_BADMSGTYPE;
+ krb5_set_error_message(context, ret,
+ "PKINIT failed to decode ECDH key");
+ goto out;
}
*out = public;
public = NULL;
out:
if (public)
- EC_KEY_free(public);
+ EC_KEY_free(public);
free_ECParameters(&ecp);
return ret;
}
+#endif
#endif /* HAVE_HCRYPTO_W_OPENSSL */
krb5_error_code
@@ -253,7 +434,11 @@ _kdc_get_ecdh_param(krb5_context context,
void **out)
{
#ifdef HAVE_HCRYPTO_W_OPENSSL
- return get_ecdh_param(context, config, dh_key_info, (EC_KEY **)out);
+#ifdef HAVE_OPENSSL_30
+ return get_ecdh_param_ossl30(context, config, dh_key_info, (EVP_PKEY **)out);
+#else
+ return get_ecdh_param_ossl11(context, config, dh_key_info, (EC_KEY **)out);
+#endif
#else
return ENOTSUP;
#endif /* HAVE_HCRYPTO_W_OPENSSL */
@@ -265,13 +450,51 @@ _kdc_get_ecdh_param(krb5_context context,
*/
#ifdef HAVE_HCRYPTO_W_OPENSSL
+#ifdef HAVE_OPENSSL_30
static krb5_error_code
-serialize_ecdh_key(krb5_context context,
- EC_KEY *key,
- unsigned char **out,
- size_t *out_len)
+serialize_ecdh_key_ossl30(krb5_context context,
+ EVP_PKEY *key,
+ unsigned char **out,
+ size_t *out_len)
+{
+ unsigned char *p;
+ int len;
+
+ *out = NULL;
+ *out_len = 0;
+
+ len = i2d_PublicKey(key, NULL);
+ if (len <= 0) {
+ krb5_set_error_message(context, EOVERFLOW,
+ "PKINIT failed to encode ECDH key");
+ return EOVERFLOW;
+ }
+
+ *out = malloc(len);
+ if (*out == NULL)
+ return krb5_enomem(context);
+
+ p = *out;
+ len = i2d_PublicKey(key, &p);
+ if (len <= 0) {
+ free(*out);
+ *out = NULL;
+ krb5_set_error_message(context, EINVAL /* XXX Better error please */,
+ "PKINIT failed to encode ECDH key");
+ return EINVAL;
+ }
+
+ *out_len = len * 8;
+ return 0;
+}
+#else
+
+static krb5_error_code
+serialize_ecdh_key_ossl11(krb5_context context,
+ EC_KEY *key,
+ unsigned char **out,
+ size_t *out_len)
{
- krb5_error_code ret = 0;
unsigned char *p;
int len;
@@ -279,8 +502,11 @@ serialize_ecdh_key(krb5_context context,
*out_len = 0;
len = i2o_ECPublicKey(key, NULL);
- if (len <= 0)
+ if (len <= 0) {
+ krb5_set_error_message(context, EOVERFLOW,
+ "PKINIT failed to encode ECDH key");
return EOVERFLOW;
+ }
*out = malloc(len);
if (*out == NULL)
@@ -291,16 +517,16 @@ serialize_ecdh_key(krb5_context context,
if (len <= 0) {
free(*out);
*out = NULL;
- ret = EINVAL; /* XXX Better error please */
- krb5_set_error_message(context, ret,
+ krb5_set_error_message(context, EINVAL /* XXX Better error please */,
"PKINIT failed to encode ECDH key");
- return ret;
+ return EINVAL;
}
*out_len = len * 8;
- return ret;
+ return 0;
}
#endif
+#endif
krb5_error_code
_kdc_serialize_ecdh_key(krb5_context context,
@@ -309,7 +535,11 @@ _kdc_serialize_ecdh_key(krb5_context context,
size_t *out_len)
{
#ifdef HAVE_HCRYPTO_W_OPENSSL
- return serialize_ecdh_key(context, key, out, out_len);
+#ifdef HAVE_OPENSSL_30
+ return serialize_ecdh_key_ossl30(context, key, out, out_len);
+#else
+ return serialize_ecdh_key_ossl11(context, key, out, out_len);
+#endif
#else
return ENOTSUP;
#endif
diff --git a/third_party/heimdal/kdc/simple_csr_authorizer.c b/third_party/heimdal/kdc/simple_csr_authorizer.c
deleted file mode 100644
index b46a8931ad3..00000000000
--- a/third_party/heimdal/kdc/simple_csr_authorizer.c
+++ /dev/null
@@ -1,343 +0,0 @@
-/*
- * Copyright (c) 2019 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.
- */
-
-/*
- * This plugin authorizes requested certificate SANs and EKUs by checking for
- * existence of files of the form:
- *
- *
- * /<path>/<princ>/<ext>-<value>
- *
- * where <path> is the value of:
- *
- * [kdc] simple_csr_authorizer_directory = PATH
- *
- * <princ> is a requesting client principal name with all characters other than
- * alphanumeric, '-', '_', and non-leading '.' URL-encoded.
- *
- * <ext> is one of:
- *
- * - pkinit (SAN)
- * - xmpp (SAN)
- * - email (SAN)
- * - ms-upn (SAN)
- * - dnsname (SAN)
- * - eku (EKU OID)
- *
- * and <value> is a display form of the SAN or EKU OID, with SANs URL-encoded
- * just like principal names (see above).
- *
- * OIDs are of the form "1.2.3.4.5".
- *
- * Only digitalSignature and nonRepudiation key usage values are permitted.
- */
-#define _GNU_SOURCE 1
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <ctype.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <roken.h>
-#include <krb5.h>
-#include <hx509.h>
-#include <kdc.h>
-#include <common_plugin.h>
-#include <csr_authorizer_plugin.h>
-
-/*
- * string_encode_sz() and string_encode() encode a string to be safe for use as
- * a file name. They function very much like URL encoders, but '~' also gets
- * encoded, and '@', '-', '_', and non-leading '.' do not.
- *
- * A corresponding decoder is not needed.
- */
-static size_t
-string_encode_sz(const char *in)
-{
- size_t sz = strlen(in);
- int first = 1;
-
- while (*in) {
- char c = *(in++);
-
- switch (c) {
- case '@':
- case '-':
- case '_':
- break;
- case '.':
- if (first)
- sz += 2;
- break;
- default:
- if (!isalnum(c))
- sz += 2;
- }
- first = 0;
- }
- return sz;
-}
-
-static char *
-string_encode(const char *in)
-{
- size_t len = strlen(in);
- size_t sz = string_encode_sz(in);
- size_t i, k;
- char *s;
- int first = 1;
-
- if ((s = malloc(sz + 1)) == NULL)
- return NULL;
- s[sz] = '\0';
-
- for (i = k = 0; i < len; i++, first = 0) {
- unsigned char c = ((const unsigned char *)in)[i];
-
- switch (c) {
- case '@':
- case '-':
- case '_':
- s[k++] = c;
- break;
- case '.':
- if (first) {
- s[k++] = '%';
- s[k++] = "0123456789abcdef"[(c&0xff)>>4];
- s[k++] = "0123456789abcdef"[(c&0x0f)];
- } else {
- s[k++] = c;
- }
- break;
- default:
- if (isalnum(c)) {
- s[k++] = c;
- } else {
- s[k++] = '%';
- s[k++] = "0123456789abcdef"[(c&0xff)>>4];
- s[k++] = "0123456789abcdef"[(c&0x0f)];
- }
- }
- }
- return s;
-}
-
-static void
-frees(char **s)
-{
- free(*s);
- *s = NULL;
-}
-
-static KRB5_LIB_CALL krb5_error_code
-authorize(void *ctx,
- krb5_context context,
- const char *app,
- hx509_request csr,
- krb5_const_principal client,
- krb5_boolean *result)
-{
- krb5_error_code ret;
- hx509_context hx509ctx = NULL;
- KeyUsage ku;
- const char *d;
- size_t i;
- char *princ = NULL;
- char *s = NULL;
-
- if ((d = krb5_config_get_string(context, NULL, app ? app : "kdc",
- "simple_csr_authorizer_directory",
- NULL)) == NULL)
- return KRB5_PLUGIN_NO_HANDLE;
-
- if ((ret = hx509_context_init(&hx509ctx)))
- return ret;
-
- if ((ret = krb5_unparse_name(context, client, &princ)))
- goto out;
-
- s = string_encode(princ);
- free(princ);
- princ = NULL;
- if (s == NULL)
- goto enomem;
-
- princ = s;
- s = NULL;
-
- for (i = 0; ret == 0; i++) {
- hx509_san_type san_type;
- struct stat st;
- const char *prefix;
- char *san;
- char *p;
-
- ret = hx509_request_get_san(csr, i, &san_type, &s);
- if (ret)
- break;
- switch (san_type) {
- case HX509_SAN_TYPE_EMAIL:
- prefix = "email";
- break;
- case HX509_SAN_TYPE_DNSNAME:
- prefix = "dnsname";
- break;
- case HX509_SAN_TYPE_XMPP:
- prefix = "xmpp";
- break;
- case HX509_SAN_TYPE_PKINIT:
- prefix = "pkinit";
- break;
- case HX509_SAN_TYPE_MS_UPN:
- prefix = "ms-upn";
- break;
- default:
- ret = ENOTSUP;
- break;
- }
- if (ret)
- break;
-
- if ((san = string_encode(s)) == NULL ||
- asprintf(&p, "%s/%s/%s-%s", d, princ, prefix, san) == -1 ||
- p == NULL) {
- free(san);
- goto enomem;
- }
- ret = stat(p, &st) == -1 ? errno : 0;
- free(san);
- free(p);
- frees(&s);
- if (ret)
- goto skip;
- ret = hx509_request_authorize_san(csr, i);
- }
- frees(&s);
- if (ret == HX509_NO_ITEM)
- ret = 0;
- if (ret)
- goto out;
-
- for (i = 0; ret == 0; i++) {
- struct stat st;
- char *p;
-
- ret = hx509_request_get_eku(csr, i, &s);
- if (ret)
- break;
- if (asprintf(&p, "%s/%s/eku-%s", d, princ, s) == -1 || p == NULL)
- goto enomem;
- ret = stat(p, &st) == -1 ? errno : 0;
- free(p);
- frees(&s);
- if (ret)
- goto skip;
- ret = hx509_request_authorize_eku(csr, i);
- }
- if (ret == HX509_NO_ITEM)
- ret = 0;
- if (ret)
- goto out;
-
- ku = int2KeyUsage(0);
- ku.digitalSignature = 1;
- ku.nonRepudiation = 1;
- hx509_request_authorize_ku(csr, ku);
-
- *result = TRUE;
- ret = 0;
- goto out;
-
-skip:
- /* Allow another plugin to get a crack at this */
- ret = KRB5_PLUGIN_NO_HANDLE;
- goto out;
-
-enomem:
- ret = krb5_enomem(context);
- goto out;
-
-out:
- hx509_context_free(&hx509ctx);
- free(princ);
- free(s);
- return ret;
-}
-
-static KRB5_LIB_CALL krb5_error_code
-simple_csr_authorizer_init(krb5_context context, void **c)
-{
- *c = NULL;
- return 0;
-}
-
-static KRB5_LIB_CALL void
-simple_csr_authorizer_fini(void *c)
-{
-}
-
-static krb5plugin_csr_authorizer_ftable plug_desc =
- { 1, simple_csr_authorizer_init, simple_csr_authorizer_fini, authorize };
-
-static krb5plugin_csr_authorizer_ftable *plugs[] = { &plug_desc };
-
-static uintptr_t
-simple_csr_authorizer_get_instance(const char *libname)
-{
- if (strcmp(libname, "krb5") == 0)
- return krb5_get_instance(libname);
- if (strcmp(libname, "kdc") == 0)
- return kdc_get_instance(libname);
- if (strcmp(libname, "hx509") == 0)
- return hx509_get_instance(libname);
- return 0;
-}
-
-krb5_plugin_load_ft kdc_csr_authorizer_plugin_load;
-
-krb5_error_code KRB5_CALLCONV
-kdc_csr_authorizer_plugin_load(heim_pcontext context,
- krb5_get_instance_func_t *get_instance,
- size_t *num_plugins,
- krb5_plugin_common_ftable_cp **plugins)
-{
- *get_instance = simple_csr_authorizer_get_instance;
- *num_plugins = sizeof(plugs) / sizeof(plugs[0]);
- *plugins = (krb5_plugin_common_ftable_cp *)plugs;
- return 0;
-}
diff --git a/third_party/heimdal/kdc/test_csr_authorizer.c b/third_party/heimdal/kdc/test_csr_authorizer.c
index 1d526f77bb6..dbf4c421237 100644
--- a/third_party/heimdal/kdc/test_csr_authorizer.c
+++ b/third_party/heimdal/kdc/test_csr_authorizer.c
@@ -1,8 +1,84 @@
+/*
+ * Copyright (c) 2022 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
#include "kdc_locl.h"
+#include <heim-ipc.h>
+
+/*
+ * This program implements two things:
+ *
+ * - a utility for testing the `kdc_authorize_csr()' function and the plugins
+ * that uses,
+ *
+ * and
+ *
+ * - a server for the IPC authorizer.
+ *
+ * For the latter, requested certificate SANs and EKUs are authorized by
+ * checking for existence of files of the form:
+ *
+ * /<path>/<princ>/<ext>-<value>
+ *
+ * where <path> is given as an option.
+ *
+ * <princ> is a requesting client principal name with all characters other than
+ * alphanumeric, '-', '_', and non-leading '.' URL-encoded.
+ *
+ * <ext> is one of:
+ *
+ * - pkinit (SAN)
+ * - xmpp (SAN)
+ * - email (SAN)
+ * - ms-upn (SAN)
+ * - dnsname (SAN)
+ * - eku (EKU OID)
+ *
+ * and <value> is a display form of the SAN or EKU OID, with SANs URL-encoded
+ * just like principal names (see above).
+ *
+ * OIDs are of the form "1.2.3.4.5".
+ *
+ * Only digitalSignature and nonRepudiation key usage values are permitted.
+ */
static int help_flag;
static int version_flag;
+static int daemon_flag;
+static int daemon_child_flag = -1;
+static int ignore_flag = 0;
+static int server_flag = 0;
static const char *app_string = "kdc";
+static const char *socket_dir;
+static const char *authz_dir;
struct getargs args[] = {
{ "help", 'h', arg_flag, &help_flag,
@@ -11,6 +87,18 @@ struct getargs args[] = {
"Print version", NULL },
{ "app", 'a', arg_string, &app_string,
"App to test (kdc or bx509); default: kdc", "APPNAME" },
+ { "socket-dir", 'S', arg_string, &socket_dir,
+ "IPC socket directory", "DIR" },
+ { "authorization-dir", 'A', arg_string, &authz_dir,
+ "authorization directory", "DIR" },
+ { "server", '\0', arg_flag, &server_flag,
+ "Server mode", NULL },
+ { "ignore", 'I', arg_flag, &ignore_flag,
+ "ignore requests", NULL },
+ { "daemon", 'd', arg_flag, &daemon_flag,
+ "daemonize", NULL },
+ { "daemon-child", '\0', arg_flag, &daemon_child_flag,
+ "internal-use-only option", NULL },
};
size_t num_args = sizeof(args) / sizeof(args[0]);
@@ -19,9 +107,23 @@ usage(int e)
{
arg_printusage(args, num_args, NULL, "PATH-TO-DER-CSR PRINCIPAL");
fprintf(stderr,
- "\n\tExercise CSR authorization plugins for a given CSR for a\n"
- "\tgiven principal.\n"
- "\n\tExample: %s PKCS10:/tmp/csr.der foo@TEST.H5L.SE\n",
+ "\tExercise CSR authorization plugins for a given CSR for a\n"
+ "\tgiven principal.\n\n"
+ "\tServer-mode (--server) looks for files in the \n"
+ "\t--authorization-dir DIR directory named:\n"
+ "\n"
+ "\t\teku=OID\n"
+ "\t\tsan_pkinit=PRINCIPAL\n"
+ "\t\tsan_ms_upn=PRINCIPAL\n"
+ "\t\tsan_dnsname=DOMAINNAME\n"
+ "\t\tsan_xmpp=JABBER-ID\n"
+ "\t\tsan_email=EMAIL\n"
+ "\n"
+ "\tClient-mode positional arguments are:\n\n"
+ "\t\tPATH-TO-DER-CSR PRETEND-CLIENT-PRINCIPAL [...]\n\n"
+ "\twhere {...} are requested features that must be granted\n"
+ "\tif the request is only partially authorized.\n\n"
+ "\tClient example:\n\t\t%s PKCS10:/tmp/csr.der foo@TEST.H5L.SE\n",
getprogname());
exit(e);
return e;
@@ -58,6 +160,177 @@ load_plugins(krb5_context context)
#endif
}
+static char *string_encode(const char *);
+static int stat_authz(const char *, const char *);
+
+static krb5_error_code
+authorize(const char *subject, const char *thing)
+{
+ krb5_error_code ret;
+ char *s = NULL;
+
+ s = string_encode(subject);
+ if (s == NULL)
+ return ENOMEM;
+
+ ret = stat_authz(s, thing);
+ if (ret == ENOENT)
+ ret = stat_authz(s, "all");
+ if (ret == ENOENT)
+ ret = EACCES;
+ free(s);
+ return ret;
+}
+
+static void
+service(void *ctx,
+ const heim_octet_string *req,
+ const heim_icred cred,
+ heim_ipc_complete complete_cb,
+ heim_sipc_call complete_cb_data)
+{
+ krb5_error_code ret = 0;
+ struct rk_strpool *result = NULL;
+ krb5_data rep;
+ const char *subject;
+ char *cmd;
+ char *next = NULL;
+ char *res = NULL;
+ char *tok;
+ char *s;
+ int none_granted = 1;
+ int all_granted = 1;
+ int first = 1;
+
+ /*
+ * A krb5_context and log facility for logging would be nice, but this is
+ * all just for testing.
+ */
+
+ (void)ctx;
+
+ cmd = strndup(req->data, req->length);
+ if (cmd == NULL)
+ errx(1, "Out of memory");
+
+ if (strncmp(cmd, "check ", sizeof("check ") - 1) != 0) {
+ rep.data = "Invalid request command (must be \"check ...\")";
+ rep.length = sizeof("Invalid request command (must be \"check ...\")") - 1;
+ (*complete_cb)(complete_cb_data, EINVAL, &rep);
+ free(cmd);
+ return;
+ }
+
+ s = cmd + sizeof("check ") - 1;
+ subject = strtok_r(s, " ", &next);
+ s = NULL;
+
+ while ((tok = strtok_r(s, " ", &next))) {
+ int ret2;
+
+ ret2 = authorize(subject, tok);
+ result = rk_strpoolprintf(result, "%s%s:%s",
+ first ? "" : ",",
+ tok,
+ ret2 == 0 ? "granted" : "denied");
+ if (ret2 == 0)
+ none_granted = 0;
+ else
+ all_granted = 0;
+
+ if (ret2 != 0 && ret == 0)
+ ret = ret2;
+
+ first = 0;
+ }
+ free(cmd);
+
+ if (ret == 0 && all_granted) {
+ rk_strpoolfree(result);
+
+ rep.data = "granted";
+ rep.length = sizeof("granted") - 1;
+ (*complete_cb)(complete_cb_data, 0, &rep);
+ return;
+ }
+
+ if (none_granted && ignore_flag) {
+ rk_strpoolfree(result);
+
+ rep.data = "ignore";
+ rep.length = sizeof("ignore") - 1;
+ (*complete_cb)(complete_cb_data, KRB5_PLUGIN_NO_HANDLE, &rep);
+ return;
+ }
+
+ s = rk_strpoolcollect(result); /* frees `result' */
+ if (s == NULL) {
+ rep.data = "denied out-of-memory";
+ rep.length = sizeof("denied out-of-memory") - 1;
+ (*complete_cb)(complete_cb_data, KRB5_PLUGIN_NO_HANDLE, &rep);
+ return;
+ }
+
+ if (asprintf(&res, "denied %s", s) == -1)
+ errx(1, "Out of memory");
+ if (res == NULL)
+ errx(1, "Out of memory");
+
+ rep.data = res;
+ rep.length = strlen(res);
+
+ (*complete_cb)(complete_cb_data, ret, &rep);
+ free(res);
+ free(s);
+}
+
+static char *
+make_feature_argument(const char *kind,
+ hx509_san_type san_type,
+ const char *value)
+{
+ const char *san_type_str = NULL;
+ char *s = NULL;
+
+ if (strcmp(kind, "san") != 0) {
+ if (asprintf(&s, "%s=%s", kind, value) == -1 || s == NULL)
+ errx(1, "Out of memory");
+ return s;
+ }
+
+ switch (san_type) {
+ case HX509_SAN_TYPE_EMAIL:
+ san_type_str = "email";
+ break;
+ case HX509_SAN_TYPE_DNSNAME:
+ san_type_str = "dnsname";
+ break;
+ case HX509_SAN_TYPE_DN:
+ san_type_str = "dn";
+ break;
+ case HX509_SAN_TYPE_REGISTERED_ID:
+ san_type_str = "registered_id";
+ break;
+ case HX509_SAN_TYPE_XMPP:
+ san_type_str = "xmpp";
+ break;
+ case HX509_SAN_TYPE_PKINIT:
+ case HX509_SAN_TYPE_MS_UPN:
+ san_type_str = "pkinit";
+ break;
+ case HX509_SAN_TYPE_DNSSRV:
+ san_type_str = "dnssrv";
+ break;
+ default:
+ warnx("SAN type not supported");
+ return "";
+ }
+
+ if (asprintf(&s, "san_%s=%s", san_type_str, value) == -1 || s == NULL)
+ errx(1, "Out of memory");
+ return s;
+}
+
int
main(int argc, char **argv)
{
@@ -79,24 +352,143 @@ main(int argc, char **argv)
return 0;
}
- argc -= optidx;
- argv += optidx;
-
- if (argc != 2)
- usage(1);
-
if ((errno = krb5_init_context(&context)))
err(1, "Could not initialize krb5_context");
if ((ret = krb5_initlog(context, argv0, &logf)) ||
(ret = krb5_addlog_dest(context, logf, "0-5/STDERR")))
krb5_err(context, 1, ret, "Could not set up logging to stderr");
load_plugins(context);
+
+ if (server_flag && daemon_flag)
+ daemon_child_flag = roken_detach_prep(argc, argv, "--daemon-child");
+
+ argc -= optidx;
+ argv += optidx;
+
+ if (socket_dir)
+ setenv("HEIM_IPC_DIR", socket_dir, 1);
+
+ if (server_flag) {
+ const char *svc;
+ heim_sipc un;
+
+ rk_pidfile(NULL);
+
+ svc = krb5_config_get_string(context, NULL,
+ app_string ? app_string : "kdc",
+ "ipc_csr_authorizer", "service", NULL);
+ if (svc == NULL)
+ svc = "org.h5l.csr_authorizer";
+
+ /* `service' is our request handler; `argv' is its callback data */
+ ret = heim_sipc_service_unix(svc, service, NULL, &un);
+ if (ret)
+ krb5_err(context, 1, ret,
+ "Could not setup service on Unix domain socket "
+ "%s/.heim_%s-socket", socket_dir, svc);
+
+ roken_detach_finish(NULL, daemon_child_flag);
+
+ /* Enter the IPC event loop */
+ heim_ipc_main();
+ return 0;
+ }
+
+ /* Client mode */
+ if (argc < 2)
+ usage(1);
+
+ /* Parse the given CSR */
if ((ret = hx509_request_parse(context->hx509ctx, argv[0], &csr)))
krb5_err(context, 1, ret, "Could not parse PKCS#10 CSR from %s", argv[0]);
+
+ /*
+ * Parse the client principal that we'll pretend is an authenticated client
+ * principal.
+ */
if ((ret = krb5_parse_name(context, argv[1], &princ)))
krb5_err(context, 1, ret, "Could not parse principal %s", argv[1]);
- if ((ret = kdc_authorize_csr(context, app_string, csr, princ)))
- krb5_err(context, 1, ret, "Authorization failed");
+
+ /* Call the authorizer */
+ ret = kdc_authorize_csr(context, app_string, csr, princ);
+
+ if (ret) {
+ unsigned n = hx509_request_count_unauthorized(csr);
+ size_t i, k;
+ int ret2 = 0;
+ int good = -1;
+
+ /*
+ * Check partial approval of SANs.
+ *
+ * Iterate over the SANs in the request, and for each check if a) it
+ * was granted, b) it's on the remainder of our argv[].
+ */
+ for (i = 0; ret2 == 0; i++) {
+ hx509_san_type san_type;
+ char *feature = NULL;
+ char *san = NULL;
+ int granted;
+
+ ret2 = hx509_request_get_san(csr, i, &san_type, &san);
+ if (ret2)
+ break;
+
+ feature = make_feature_argument("san", san_type, san);
+
+ granted = hx509_request_san_authorized_p(csr, i);
+ for (k = 2; k < argc; k++) {
+ if (strcmp(feature, argv[k]) != 0)
+ continue;
+
+ /* The SAN is on our command line */
+ if (granted && good == -1)
+ good = 1;
+ else if (!granted)
+ good = 0;
+ break;
+ }
+
+ hx509_xfree(san);
+ }
+
+ /* Check partial approval of EKUs */
+ for (i = 0; ret2 == 0; i++) {
+ char *feature = NULL;
+ char *eku = NULL;
+ int granted;
+
+ ret2 = hx509_request_get_eku(csr, i, &eku);
+ if (ret2)
+ break;
+
+ feature = make_feature_argument("eku", 0, eku);
+
+ granted = hx509_request_eku_authorized_p(csr, i);
+ for (k = 2; k < argc; k++) {
+ if (strcmp(feature, argv[k]) != 0)
+ continue;
+
+ /* The SAN is on our command line */
+ if (granted && good == -1)
+ good = 1;
+ else if (!granted)
+ good = 0;
+ break;
+ }
+
+ hx509_xfree(eku);
+ }
+
+ if (good != 1) {
+ krb5_free_principal(context, princ);
+ _krb5_unload_plugins(context, "kdc");
+ hx509_request_free(&csr);
+ krb5_err(context, 1, ret,
+ "Authorization failed with %u rejected features", n);
+ }
+ }
+
printf("Authorized!\n");
krb5_free_principal(context, princ);
_krb5_unload_plugins(context, "kdc");
@@ -104,3 +496,102 @@ main(int argc, char **argv)
hx509_request_free(&csr);
return 0;
}
+
+/*
+ * string_encode_sz() and string_encode() encode a string to be safe for use as
+ * a file name. They function very much like URL encoders, but '~' also gets
+ * encoded, and '@', '-', '_', and non-leading '.' do not.
+ *
+ * A corresponding decoder is not needed.
+ */
+static size_t
+string_encode_sz(const char *in)
+{
+ size_t sz = strlen(in);
+ int first = 1;
+
+ while (*in) {
+ char c = *(in++);
+
+ switch (c) {
+ case '@':
+ case '-':
+ case '_':
+ break;
+ case '.':
+ if (first)
+ sz += 2;
+ break;
+ default:
+ if (!isalnum(c))
+ sz += 2;
+ }
+ first = 0;
+ }
+ return sz;
+}
+
+static char *
+string_encode(const char *in)
+{
+ size_t len = strlen(in);
+ size_t sz = string_encode_sz(in);
+ size_t i, k;
+ char *s;
+ int first = 1;
+
+ if ((s = malloc(sz + 1)) == NULL)
+ return NULL;
+ s[sz] = '\0';
+
+ for (i = k = 0; i < len; i++, first = 0) {
+ unsigned char c = ((const unsigned char *)in)[i];
+
+ switch (c) {
+ case '@':
+ case '-':
+ case '_':
+ s[k++] = c;
+ break;
+ case '.':
+ if (first) {
+ s[k++] = '%';
+ s[k++] = "0123456789abcdef"[(c&0xff)>>4];
+ s[k++] = "0123456789abcdef"[(c&0x0f)];
+ } else {
+ s[k++] = c;
+ }
+ break;
+ default:
+ if (isalnum(c)) {
+ s[k++] = c;
+ } else {
+ s[k++] = '%';
+ s[k++] = "0123456789abcdef"[(c&0xff)>>4];
+ s[k++] = "0123456789abcdef"[(c&0x0f)];
+ }
+ }
+ }
+ return s;
+}
+
+static int
+stat_authz(const char *subject,
+ const char *thing)
+{
+ struct stat st;
+ char *p = NULL;
+ int ret;
+
+ if (authz_dir == NULL)
+ return KRB5_PLUGIN_NO_HANDLE;
+ if (thing)
+ ret = asprintf(&p, "%s/%s/%s", authz_dir, subject, thing);
+ else
+ ret = asprintf(&p, "%s/%s", authz_dir, subject);
+ if (ret == -1 || p == NULL)
+ return ENOMEM;
+ ret = stat(p, &st);
+ free(p);
+ return ret == 0 ? 0 : errno;
+}
diff --git a/third_party/heimdal/kdc/test_token_validator.c b/third_party/heimdal/kdc/test_token_validator.c
index 10ea35aa242..2e4e9dca3dd 100644
--- a/third_party/heimdal/kdc/test_token_validator.c
+++ b/third_party/heimdal/kdc/test_token_validator.c
@@ -88,7 +88,7 @@ main(int argc, char **argv)
if (argc != 2)
usage(1);
- if ((ret = krb5_init_context(&context)))
+ if (krb5_init_context(&context))
err(1, "Could not initialize krb5_context");
load_plugins(context);
diff --git a/third_party/heimdal/kpasswd/kpasswdd.c b/third_party/heimdal/kpasswd/kpasswdd.c
index e04eebe46e1..43a7335898a 100644
--- a/third_party/heimdal/kpasswd/kpasswdd.c
+++ b/third_party/heimdal/kpasswd/kpasswdd.c
@@ -463,18 +463,27 @@ verify (krb5_auth_context *auth_context,
* either an invalid request or an error packet. An error packet may be
* the result of a ping-pong attacker pointing us at another kpasswdd.
*/
+ if (len < 6) {
+ krb5_warnx(context, "Message too short: %llu",
+ (unsigned long long)len);
+ return 1;
+ }
pkt_len = (msg[0] << 8) | (msg[1]);
pkt_ver = (msg[2] << 8) | (msg[3]);
ap_req_len = (msg[4] << 8) | (msg[5]);
if (pkt_len != len) {
- krb5_warnx (context, "Strange len: %ld != %ld",
- (long)pkt_len, (long)len);
+ krb5_warnx(context, "Bad packet length: %u != %llu", pkt_len,
+ (unsigned long long)len);
return 1;
}
if (ap_req_len == 0) {
krb5_warnx (context, "Request is error packet (ap_req_len == 0)");
return 1;
}
+ if (ap_req_len + 6 > len) {
+ krb5_warnx(context, "Bad AP-REQ length: %u", ap_req_len);
+ return 1;
+ }
if (pkt_ver != KRB5_KPASSWD_VERS_CHANGEPW &&
pkt_ver != KRB5_KPASSWD_VERS_SETPW) {
krb5_warnx (context, "Bad version (%d)", pkt_ver);
diff --git a/third_party/heimdal/krb5.conf b/third_party/heimdal/krb5.conf
index 103ea8c22d8..7d1a5472f16 100644
--- a/third_party/heimdal/krb5.conf
+++ b/third_party/heimdal/krb5.conf
@@ -1,3 +1,8 @@
+# The krb5.conf file can include other files using either of the following directives at the beginning of the line
+# see also krb5.conf(5)
+# include /etc/krb5-sssd.conf
+# includedir /etc/krb5.conf.d
+
[libdefaults]
default_realm = MY.REALM
clockskew = 300
diff --git a/third_party/heimdal/kuser/NTMakefile b/third_party/heimdal/kuser/NTMakefile
index 2538744dbc5..4b97b7084e7 100644
--- a/third_party/heimdal/kuser/NTMakefile
+++ b/third_party/heimdal/kuser/NTMakefile
@@ -55,6 +55,7 @@ NOINSTPROGRAMS=\
BINLIBS=\
+ $(LIBHEIMBASE) \
$(LIBGSS_PREAUTH) \
$(LIBGSSAPI) \
$(LIBHEIMDAL) \
diff --git a/third_party/heimdal/lib/asn1/asn1parse.y b/third_party/heimdal/lib/asn1/asn1parse.y
index f6f6ec0e5c4..d9e3fba2d37 100644
--- a/third_party/heimdal/lib/asn1/asn1parse.y
+++ b/third_party/heimdal/lib/asn1/asn1parse.y
@@ -1432,8 +1432,10 @@ TaggedType : Tag tagenv Type
* IMPLICIT tags of CHOICE types are EXPLICIT
* instead.
*/
- if (t->type == TChoice)
+ if (t->type == TChoice) {
+ $$->implicit_choice = 1;
$$->tag.tagenv = TE_EXPLICIT;
+ }
if($3->type == TTag && $2 == TE_IMPLICIT) {
$$->subtype = $3->subtype;
free($3);
diff --git a/third_party/heimdal/lib/asn1/check-der.c b/third_party/heimdal/lib/asn1/check-der.c
index a8956a74bd2..58c1446fd3a 100644
--- a/third_party/heimdal/lib/asn1/check-der.c
+++ b/third_party/heimdal/lib/asn1/check-der.c
@@ -67,11 +67,12 @@ test_integer (void)
{NULL, 1, "\xff", NULL },
{NULL, 2, "\xff\x01", NULL },
{NULL, 2, "\x00\xff", NULL },
+ {NULL, 2, "\xfe\x01", NULL },
{NULL, 4, "\x7f\xff\xff\xff", NULL }
};
int values[] = {0, 127, 128, 256, -128, -129, -1, -255, 255,
- 0x7fffffff};
+ -511, 0x7fffffff};
int i, ret;
int ntests = sizeof(tests) / sizeof(*tests);
@@ -153,7 +154,7 @@ test_one_int(int val)
static int
test_integer_more (void)
{
- int i, n1, n2, n3, n4, n5, n6;
+ int64_t i, n1, n2, n3, n4, n5, n6;
n2 = 0;
for (i = 0; i < (sizeof(int) * 8); i++) {
@@ -522,23 +523,27 @@ static int
test_heim_integer (void)
{
struct test_case tests[] = {
+ {NULL, 1, "\xff", NULL },
+ {NULL, 2, "\xff\x01", NULL },
{NULL, 2, "\xfe\x01", NULL },
{NULL, 2, "\xef\x01", NULL },
{NULL, 3, "\xff\x00\xff", NULL },
{NULL, 3, "\xff\x01\x00", NULL },
{NULL, 1, "\x00", NULL },
{NULL, 1, "\x01", NULL },
- {NULL, 2, "\x00\x80", NULL }
+ {NULL, 2, "\x00\x80", NULL },
};
heim_integer values[] = {
+ { 1, "\x01", 1 },
+ { 1, "\xff", 1 },
{ 2, "\x01\xff", 1 },
{ 2, "\x10\xff", 1 },
{ 2, "\xff\x01", 1 },
{ 2, "\xff\x00", 1 },
{ 0, "", 0 },
{ 1, "\x01", 0 },
- { 1, "\x80", 0 }
+ { 1, "\x80", 0 },
};
int i, ret;
int ntests = sizeof(tests) / sizeof(tests[0]);
diff --git a/third_party/heimdal/lib/asn1/check-gen.c b/third_party/heimdal/lib/asn1/check-gen.c
index 6b5c71c39f5..bba5b9db255 100644
--- a/third_party/heimdal/lib/asn1/check-gen.c
+++ b/third_party/heimdal/lib/asn1/check-gen.c
@@ -655,6 +655,12 @@ test_cert(void)
size_t i;
int ret;
+ memset(&c, 0, sizeof(c));
+ ret = copy_Certificate(&c, &c2);
+ if (ret)
+ return ret;
+ free_Certificate(&c2);
+
for (i = 0; i < sizeof(certs)/sizeof(certs[0]); i++) {
ret = decode_Certificate((unsigned char *)certs[i].cert,
@@ -1115,6 +1121,57 @@ test_decorated(void)
}
static int
+test_extensible_choice(void)
+{
+ PA_FX_FAST_REQUEST r, r2;
+ size_t len, size;
+ void *ptr;
+ int ret;
+
+ memset(&r, 0, sizeof(r));
+
+ ret = copy_PA_FX_FAST_REQUEST(&r, &r2);
+ if (ret)
+ return ret;
+ free_PA_FX_FAST_REQUEST(&r2);
+
+ r.element = 0;
+ r.u.asn1_ellipsis.data = "hello";
+ r.u.asn1_ellipsis.length = sizeof("hello") - 1;
+ ret = copy_PA_FX_FAST_REQUEST(&r, &r2);
+ if (ret)
+ errx(1, "Out of memory");
+ if (r2.element != 0)
+ errx(1, "Extensible CHOICE copy failure to set discriminant to 0");
+ if (r2.u.asn1_ellipsis.length != r.u.asn1_ellipsis.length)
+ errx(1, "Extensible CHOICE copy failure to copy extension");
+ if (memcmp(r.u.asn1_ellipsis.data, r2.u.asn1_ellipsis.data,
+ r.u.asn1_ellipsis.length) != 0)
+ errx(1, "Extensible CHOICE copy failure to copy extension (2)");
+ free_PA_FX_FAST_REQUEST(&r2);
+
+ ASN1_MALLOC_ENCODE(PA_FX_FAST_REQUEST, ptr, len, &r, &size, ret);
+ if (ret || len != size)
+ errx(1, "Extensible CHOICE encoding failure");
+
+ ret = decode_PA_FX_FAST_REQUEST(ptr, len, &r2, &size);
+ if (ret || len != size)
+ errx(1, "Extensible CHOICE decoding failure");
+
+ if (r2.element != 0)
+ errx(1, "Extensible CHOICE decode failure to set discriminant to 0");
+ if (r2.u.asn1_ellipsis.length != r.u.asn1_ellipsis.length)
+ errx(1, "Extensible CHOICE decode failure to copy extension");
+ if (memcmp(r.u.asn1_ellipsis.data, r2.u.asn1_ellipsis.data,
+ r.u.asn1_ellipsis.length) != 0)
+ errx(1, "Extensible CHOICE decode failure to copy extension (2)");
+
+ free_PA_FX_FAST_REQUEST(&r2);
+ free(ptr);
+ return 0;
+}
+
+static int
test_decorated_choice(void)
{
TESTNotDecoratedChoice tndc;
@@ -2674,6 +2731,8 @@ main(int argc, char **argv)
DO_ONE(test_default);
+ DO_ONE(test_extensible_choice);
+
DO_ONE(test_decorated_choice);
DO_ONE(test_decorated);
diff --git a/third_party/heimdal/lib/asn1/der.h b/third_party/heimdal/lib/asn1/der.h
index f7323486454..ec5603ef6c1 100644
--- a/third_party/heimdal/lib/asn1/der.h
+++ b/third_party/heimdal/lib/asn1/der.h
@@ -67,9 +67,9 @@ enum {
UT_IA5String = 22,
UT_UTCTime = 23,
UT_GeneralizedTime = 24,
- UT_UniversalString = 25,
UT_VisibleString = 26,
UT_GeneralString = 27,
+ UT_UniversalString = 28,
UT_BMPString = 30,
/* unsupported types */
UT_ObjectDescriptor = 7,
diff --git a/third_party/heimdal/lib/asn1/der_cmp.c b/third_party/heimdal/lib/asn1/der_cmp.c
index ccaf6fd0f58..f745270f3cd 100644
--- a/third_party/heimdal/lib/asn1/der_cmp.c
+++ b/third_party/heimdal/lib/asn1/der_cmp.c
@@ -38,22 +38,25 @@ der_heim_oid_cmp(const heim_oid *p, const heim_oid *q)
{
int c;
- if (p->length == q->length)
+ if (p->length == q->length) {
+ if (p->length == 0)
+ return 0;
return memcmp(p->components,
q->components,
p->length * sizeof(*p->components));
+ }
if (p->length < q->length) {
- c = memcmp(p->components,
- q->components,
- p->length * sizeof(*p->components));
- if (c == 0)
+ if (p->length == 0 ||
+ (c = memcmp(p->components,
+ q->components,
+ p->length * sizeof(*p->components))) == 0)
return -1;
return c;
}
- c = memcmp(p->components,
- q->components,
- q->length * sizeof(*p->components));
- if (c == 0)
+ if (q->length == 0 ||
+ (c = memcmp(p->components,
+ q->components,
+ q->length * sizeof(*p->components))) == 0)
return 1;
return c;
}
@@ -64,14 +67,19 @@ der_heim_octet_string_cmp(const heim_octet_string *p,
{
int c;
- if (p->length == q->length)
+ if (p->length == q->length) {
+ if (p->length == 0)
+ return 0;
return memcmp(p->data, q->data, p->length);
+ }
if (p->length < q->length) {
- if ((c = memcmp(p->data, q->data, p->length)) == 0)
+ if (p->length == 0 ||
+ (c = memcmp(p->data, q->data, p->length)) == 0)
return -1;
return c;
}
- if ((c = memcmp(p->data, q->data, q->length)) == 0)
+ if (q->length == 0 ||
+ (c = memcmp(p->data, q->data, q->length)) == 0)
return 1;
return c;
}
@@ -94,22 +102,92 @@ int ASN1CALL
der_heim_bit_string_cmp(const heim_bit_string *p,
const heim_bit_string *q)
{
- int r1, r2;
- size_t i;
- if (p->length != q->length)
- return (int)(p->length - q->length);
- i = memcmp(p->data, q->data, p->length / 8);
- if (i)
- return (int)i;
- if ((p->length % 8) == 0)
- return 0;
- i = (p->length / 8);
- r1 = ((unsigned char *)p->data)[i];
- r2 = ((unsigned char *)q->data)[i];
- i = 8 - (p->length % 8);
- r1 = r1 >> i;
- r2 = r2 >> i;
- return r1 - r2;
+ unsigned char pc, qc;
+ size_t bits;
+ int c = 0;
+
+ /* Compare prefix */
+ if (p->length == 0 && q->length == 0)
+ return 0;
+ if (p->length > 7 && q->length > 7) {
+ if (p->length < q->length)
+ c = memcmp(p->data, q->data, p->length / 8);
+ else
+ c = memcmp(p->data, q->data, q->length / 8);
+ }
+ if (c)
+ return c;
+
+ /* Prefixes are equal, c == 0 */
+
+ if (p->length == q->length && p->length % 8 == 0)
+ return 0;
+ if (p->length == 0 && q->length)
+ return -1; /* No trailing bits of p to compare to corresponding bits of q */
+ if (q->length == 0 && p->length)
+ return 1; /* No trailing bits of q to compare to corresponding bits of p */
+
+ /* c == 0, lengths are not equal, both are at least 1 bit */
+ pc = ((unsigned char *)p->data)[p->length / 8];
+ qc = ((unsigned char *)q->data)[q->length / 8];
+ if (p->length < q->length)
+ bits = p->length % 8;
+ else
+ bits = q->length % 8;
+
+ if (bits > 0) {
+ if ((pc & 0x80) == 0 && (qc & 0x80) != 0)
+ return -1;
+ if ((pc & 0x80) != 0 && (qc & 0x80) == 0)
+ return 1;
+ }
+ if (bits > 1) {
+ if ((pc & 0x40) == 0 && (qc & 0x40) != 0)
+ return -1;
+ if ((pc & 0x40) != 0 && (qc & 0x40) == 0)
+ return 1;
+ }
+ if (bits > 2) {
+ if ((pc & 0x20) == 0 && (qc & 0x20) != 0)
+ return -1;
+ if ((pc & 0x20) != 0 && (qc & 0x20) == 0)
+ return 1;
+ }
+ if (bits > 3) {
+ if ((pc & 0x10) == 0 && (qc & 0x10) != 0)
+ return -1;
+ if ((pc & 0x10) != 0 && (qc & 0x10) == 0)
+ return 1;
+ }
+ if (bits > 4) {
+ if ((pc & 0x08) == 0 && (qc & 0x08) != 0)
+ return -1;
+ if ((pc & 0x08) != 0 && (qc & 0x08) == 0)
+ return 1;
+ }
+ if (bits > 5) {
+ if ((pc & 0x04) == 0 && (qc & 0x04) != 0)
+ return -1;
+ if ((pc & 0x04) != 0 && (qc & 0x04) == 0)
+ return 1;
+ }
+ if (bits > 6) {
+ if ((pc & 0x02) == 0 && (qc & 0x02) != 0)
+ return -1;
+ if ((pc & 0x02) != 0 && (qc & 0x02) == 0)
+ return 1;
+ }
+ /*
+ * `bits' can't be 8.
+ *
+ * All leading `bits' bits of the tail of the shorter of `p' or `q' are
+ * equal.
+ */
+ if (p->length < q->length)
+ return -1;
+ if (q->length < p->length)
+ return 1;
+ return 0;
}
int ASN1CALL
@@ -128,14 +206,19 @@ der_heim_bmp_string_cmp(const heim_bmp_string *p, const heim_bmp_string *q)
{
int c;
- if (p->length == q->length)
+ if (p->length == q->length) {
+ if (p->length == 0)
+ return 0;
return memcmp(p->data, q->data, p->length * sizeof(q->data[0]));
+ }
if (p->length < q->length) {
- if ((c = memcmp(p->data, q->data, p->length * sizeof(q->data[0]))) == 0)
+ if (p->length == 0 ||
+ (c = memcmp(p->data, q->data, p->length * sizeof(q->data[0]))) == 0)
return -1;
return c;
}
- if ((c = memcmp(p->data, q->data, q->length * sizeof(q->data[0]))) == 0)
+ if (q->length == 0 ||
+ (c = memcmp(p->data, q->data, q->length * sizeof(q->data[0]))) == 0)
return 1;
return c;
}
@@ -146,14 +229,19 @@ der_heim_universal_string_cmp(const heim_universal_string *p,
{
int c;
- if (p->length == q->length)
+ if (p->length == q->length) {
+ if (p->length == 0)
+ return 0;
return memcmp(p->data, q->data, p->length * sizeof(q->data[0]));
+ }
if (p->length < q->length) {
- if ((c = memcmp(p->data, q->data, p->length * sizeof(q->data[0]))) == 0)
+ if (p->length == 0 ||
+ (c = memcmp(p->data, q->data, p->length * sizeof(q->data[0]))) == 0)
return -1;
return c;
}
- if ((c = memcmp(p->data, q->data, q->length * sizeof(q->data[0]))) == 0)
+ if (q->length == 0 ||
+ (c = memcmp(p->data, q->data, q->length * sizeof(q->data[0]))) == 0)
return 1;
return c;
}
diff --git a/third_party/heimdal/lib/asn1/der_copy.c b/third_party/heimdal/lib/asn1/der_copy.c
index 2084cef5f08..f67fff69d6b 100644
--- a/third_party/heimdal/lib/asn1/der_copy.c
+++ b/third_party/heimdal/lib/asn1/der_copy.c
@@ -167,9 +167,13 @@ int ASN1CALL
der_copy_octet_string (const heim_octet_string *from, heim_octet_string *to)
{
assert(from->length == 0 || (from->length > 0 && from->data != NULL));
- if (from->length == 0)
+ if (from->length == 0) {
+ if (from->data == NULL) {
+ *to = *from;
+ return 0;
+ }
to->data = calloc(1, 1);
- else
+ } else
to->data = malloc(from->length);
if (to->data == NULL) {
to->length = 0;
diff --git a/third_party/heimdal/lib/asn1/der_get.c b/third_party/heimdal/lib/asn1/der_get.c
index c12f8170025..06564b7cad2 100644
--- a/third_party/heimdal/lib/asn1/der_get.c
+++ b/third_party/heimdal/lib/asn1/der_get.c
@@ -86,9 +86,12 @@ der_get_integer (const unsigned char *p, size_t len,
int val = 0;
size_t oldlen = len;
- if (len > sizeof(val))
+ if (len == sizeof(val) + 1 && (p[0] == 0 || p[0] == 0xff))
+ ;
+ else if (len > sizeof(val))
return ASN1_OVERRUN;
+ /* We assume we're on a twos-complement platform */
if (len > 0) {
val = (signed char)*p++;
while (--len)
@@ -109,6 +112,7 @@ der_get_integer64 (const unsigned char *p, size_t len,
if (len > sizeof(val))
return ASN1_OVERRUN;
+ /* We assume we're on a twos-complement platform */
if (len > 0) {
val = (signed char)*p++;
while (--len)
@@ -456,13 +460,45 @@ der_get_heim_integer (const unsigned char *p, size_t len,
if (p[0] & 0x80) {
unsigned char *q;
int carry = 1;
- data->negative = 1;
+
+ /*
+ * A negative number. It's going to be a twos complement byte array.
+ * We're going to leave the positive value in `data->data', but set the
+ * `data->negative' flag. That means we need to negate the
+ * twos-complement integer received.
+ */
+ data->negative = 1;
data->length = len;
if (p[0] == 0xff) {
+ if (data->length == 1) {
+ /* One byte of all ones == -1 */
+ q = data->data = malloc(1);
+ *q = 1;
+ data->length = 1;
+ if (size)
+ *size = 1;
+ return 0;
+ }
+
p++;
data->length--;
+
+ /*
+ * We could check if the next byte's high bit is set, which would
+ * be an error ("illegal padding" in OpenSSL). However, this would
+ * mean failing to accept certificates made by certain CAs that
+ * would read 8 bytes of RNG into a buffer, slap on length 8, then
+ * slap on the tag [UNIVERSAL INTEGER], and make that the
+ * serialNumber field's encoding, which then fails to parse in
+ * around 1 in 256 certificates.
+ *
+ * So let's not.
+ *
+ * if (p[0] & 0x80)
+ * return ASN1_PARSE_ERROR; // or a new error code
+ */
}
data->data = malloc(data->length);
if (data->data == NULL) {
@@ -471,9 +507,17 @@ der_get_heim_integer (const unsigned char *p, size_t len,
*size = 0;
return ENOMEM;
}
+
+ /*
+ * Note that if `data->length' were zero, this would be UB because we
+ * underflow if data->length is zero even though we wouldn't actually
+ * dereference the byte before data->data. Thus we check above for
+ * that.
+ */
q = &((unsigned char*)data->data)[data->length - 1];
p += data->length - 1;
while (q >= (unsigned char*)data->data) {
+ /* *p XOR 0xff -> ~*p; we're dealing with twos complement */
*q = *p ^ 0xff;
if (carry)
carry = !++*q;
diff --git a/third_party/heimdal/lib/asn1/der_length.c b/third_party/heimdal/lib/asn1/der_length.c
index 9a9913311d6..cd50df84622 100644
--- a/third_party/heimdal/lib/asn1/der_length.c
+++ b/third_party/heimdal/lib/asn1/der_length.c
@@ -256,7 +256,9 @@ der_length_heim_integer (const heim_integer *k)
{
if (k->length == 0)
return 1;
- if (k->negative)
+ if (k->negative && k->length == 1 && ((unsigned char *)k->data)[0] == 1)
+ return 1;
+ else if (k->negative)
return k->length + (((~(((unsigned char *)k->data)[0])) & 0x80) ? 0 : 1);
else
return k->length + ((((unsigned char *)k->data)[0] & 0x80) ? 1 : 0);
diff --git a/third_party/heimdal/lib/asn1/der_print.c b/third_party/heimdal/lib/asn1/der_print.c
index 1d459856a61..dada747a9a7 100644
--- a/third_party/heimdal/lib/asn1/der_print.c
+++ b/third_party/heimdal/lib/asn1/der_print.c
@@ -223,7 +223,7 @@ der_print_bit_string(const heim_bit_string *k, int flags)
(void) hex_encode(k->data, k->length / 8, &s);
if (asprintf(&s2, "%llu:%s", (unsigned long long)k->length, s) == -1 || !s2)
- return NULL;
+ s2 = NULL;
free(s);
return s2;
}
diff --git a/third_party/heimdal/lib/asn1/der_put.c b/third_party/heimdal/lib/asn1/der_put.c
index 8fbd6f3da1c..106d456026c 100644
--- a/third_party/heimdal/lib/asn1/der_put.c
+++ b/third_party/heimdal/lib/asn1/der_put.c
@@ -343,7 +343,8 @@ der_put_octet_string (unsigned char *p, size_t len,
if (len < data->length)
return ASN1_OVERFLOW;
p -= data->length;
- memcpy (p+1, data->data, data->length);
+ if (data->length)
+ memcpy(p+1, data->data, data->length);
*size = data->length;
return 0;
}
@@ -378,19 +379,30 @@ der_put_heim_integer (unsigned char *p, size_t len,
if (data->negative) {
ssize_t i;
int carry;
- for (i = data->length - 1, carry = 1; i >= 0; i--) {
- *p = buf[i] ^ 0xff;
- if (carry)
- carry = !++*p;
- p--;
- }
- if (p[1] < 128) {
- if (len < 1)
- return ASN1_OVERFLOW;
- *p-- = 0xff;
- len--;
- hibitset = 1;
- }
+
+ /*
+ * We represent the parsed integer as a positive value with a
+ * negativity flag. But we need to put it on the wire as the shortest
+ * twos-complement byte sequence possible. So we're going to negate
+ * the number as go.
+ */
+ if (data->length == 1 && *(unsigned char *)data->data == 1) {
+ *(p--) = 0xff;
+ } else {
+ for (i = data->length - 1, carry = 1; i >= 0; i--) {
+ *p = buf[i] ^ 0xff;
+ if (carry)
+ carry = !++*p;
+ p--;
+ }
+ if (p[1] < 128) {
+ if (len < 1)
+ return ASN1_OVERFLOW;
+ *p-- = 0xff;
+ len--;
+ hibitset = 1;
+ }
+ }
} else {
p -= data->length;
memcpy(p + 1, buf, data->length);
diff --git a/third_party/heimdal/lib/asn1/gen.c b/third_party/heimdal/lib/asn1/gen.c
index 10153c60379..06dc6bb701b 100644
--- a/third_party/heimdal/lib/asn1/gen.c
+++ b/third_party/heimdal/lib/asn1/gen.c
@@ -1118,6 +1118,7 @@ define_open_type(int level, const char *newbasename, const char *name, const cha
/* Iterate objects in the object set, gen enum labels */
fprintf(headerfile, "enum { choice_%s_iosnumunknown = 0,\n",
newbasename);
+ fprintf(jsonfile, "\"opentypeids\":[");
for (i = 0; i < nobjs; i++) {
HEIM_TAILQ_FOREACH(of, objects[i]->objfields, objfields) {
if (strcmp(of->name, typeidfield->name) != 0)
@@ -1127,8 +1128,11 @@ define_open_type(int level, const char *newbasename, const char *name, const cha
of->name, objects[i]->symbol->name);
fprintf(headerfile, "choice_%s_iosnum_%s,\n",
newbasename, of->value->s->gen_name);
+ fprintf(jsonfile, "\"%s\"", of->value->s->gen_name);
+ fprintf(jsonfile, "%s", (i + 1) < nobjs ? "," : "");
}
}
+ fprintf(jsonfile, "],\n");
fprintf(headerfile, "} element;\n");
if (is_array_of_open_type)
@@ -1404,16 +1408,45 @@ define_type(int level, const char *name, const char *basename, Type *pt, Type *t
HEIM_TAILQ_FOREACH(m, t->members, members) {
if (m->ellipsis) {
;
- } else if (m->optional) {
- char *n = NULL;
+ } else if (m->optional || m->defval) {
+ char *n = NULL, *defval = NULL;
+ const char *namep, *defvalp;
+
+ if (m->defval) {
+ switch (m->defval->type) {
+ case stringvalue:
+ if (asprintf(&defval, "\"%s\"", m->defval->u.stringvalue) < 0 || defval == NULL)
+ errx(1, "malloc");
+ defvalp = defval;
+ break;
+ case integervalue:
+ if (asprintf(&defval, "%lld", (long long)m->defval->u.integervalue) < 0 || defval == NULL)
+ errx(1, "malloc");
+ defvalp = defval;
+ break;
+ case booleanvalue:
+ defvalp = m->defval->u.booleanvalue ? "true" : "false";
+ break;
+ default:
+ abort();
+ }
+ } else
+ defvalp = "null";
+
+ if (m->optional) {
+ if (asprintf(&n, "*%s", m->gen_name) < 0 || n == NULL)
+ errx(1, "malloc");
+ namep = n;
+ } else
+ namep = m->gen_name;
- if (asprintf(&n, "*%s", m->gen_name) < 0 || n == NULL)
- errx(1, "malloc");
fprintf(jsonfile, "{\"name\":\"%s\",\"gen_name\":\"%s\","
- "\"optional\":true,\"type\":", m->name, m->gen_name);
- define_type(level + 1, n, newbasename, t, m->type, FALSE, FALSE);
+ "\"optional\":%s,\"defval\":%s,\"type\":",
+ m->name, m->gen_name, m->optional ? "true" : "false", defvalp);
+ define_type(level + 1, namep, newbasename, t, m->type, FALSE, FALSE);
fprintf(jsonfile, "}%s", last_member_p(m));
free (n);
+ free (defval);
} else {
fprintf(jsonfile, "{\"name\":\"%s\",\"gen_name\":\"%s\","
"\"optional\":false,\"type\":", m->name, m->gen_name);
@@ -1498,6 +1531,9 @@ define_type(int level, const char *name, const char *basename, Type *pt, Type *t
fprintf(jsonfile, "\"ttype\":\"TeletexString\",\"ctype\":\"heim_general_string\"");
break;
case TTag:
+ if (t->implicit_choice) {
+ fprintf(jsonfile, "\"desired_tagenv\":\"IMPLICIT\",");
+ }
fprintf(jsonfile, "\"tagclass\":\"%s\",\"tagvalue\":%d,\"tagenv\":\"%s\",\n",
tagclassnames[t->tag.tagclass], t->tag.tagvalue,
t->tag.tagenv == TE_EXPLICIT ? "EXPLICIT" : "IMPLICIT");
diff --git a/third_party/heimdal/lib/asn1/gen_free.c b/third_party/heimdal/lib/asn1/gen_free.c
index 14e6529046c..ff80063ecec 100644
--- a/third_party/heimdal/lib/asn1/gen_free.c
+++ b/third_party/heimdal/lib/asn1/gen_free.c
@@ -56,7 +56,7 @@ free_type (const char *name, const Type *t, int preserve)
free_primitive ("heim_integer", name);
break;
}
- /* HEIM_FALLTHROUGH; */
+ HEIM_FALLTHROUGH;
case TBoolean:
case TEnumerated :
case TNull:
@@ -237,4 +237,3 @@ generate_type_free (const Symbol *s)
}
fprintf (codefile, "}\n\n");
}
-
diff --git a/third_party/heimdal/lib/asn1/gen_template.c b/third_party/heimdal/lib/asn1/gen_template.c
index ad25fcfb29d..67d18ecfff5 100644
--- a/third_party/heimdal/lib/asn1/gen_template.c
+++ b/third_party/heimdal/lib/asn1/gen_template.c
@@ -1238,7 +1238,7 @@ template_members(struct templatehead *temp,
is_primitive_type(t->subtype);
if (t->tag.tagenv == TE_IMPLICIT) {
- Type *t2 = t->subtype ? t->subtype : t->symbol->type;
+ Type *t2 = t->subtype;
while (t2->type == TType && (t2->subtype || t2->symbol->type))
t2 = t2->subtype ? t2->subtype : t2->symbol->type;
diff --git a/third_party/heimdal/lib/asn1/main.c b/third_party/heimdal/lib/asn1/main.c
index 569b4782b4d..babcc009c29 100644
--- a/third_party/heimdal/lib/asn1/main.c
+++ b/third_party/heimdal/lib/asn1/main.c
@@ -415,7 +415,7 @@ main(int argc, char **argv)
buflen = strlen(buf);
if ((ws = strspn(buf, " \t")))
- memmove(buf, buf + ws, buflen -= ws);
+ memmove(buf, buf + ws, buflen - ws);
if (buf[0] == '\0' || buf[0] == '#')
continue;
diff --git a/third_party/heimdal/lib/asn1/symbol.h b/third_party/heimdal/lib/asn1/symbol.h
index 8a24e251565..bce2e1fe421 100644
--- a/third_party/heimdal/lib/asn1/symbol.h
+++ b/third_party/heimdal/lib/asn1/symbol.h
@@ -200,6 +200,7 @@ struct type {
struct range *range;
struct constraint_spec *constraint;
unsigned long id;
+ unsigned int implicit_choice:1;
};
typedef struct type Type;
diff --git a/third_party/heimdal/lib/asn1/template.c b/third_party/heimdal/lib/asn1/template.c
index 31eb66004ec..ed215d88874 100644
--- a/third_party/heimdal/lib/asn1/template.c
+++ b/third_party/heimdal/lib/asn1/template.c
@@ -1176,6 +1176,13 @@ _asn1_decode(const struct asn1_template *t, unsigned flags,
return ret;
}
if (i >= A1_HEADER_LEN(choice) + 1 || !choice[i].tt) {
+ /*
+ * If this is an extensible CHOICE, then choice->tt will be the
+ * offset to u.ellipsis. If it's not, then this "extension" is
+ * an error and must stop parsing it. (We could be permissive
+ * and throw away the extension, though one might as well just
+ * mark such a CHOICE as extensible.)
+ */
if (choice->tt == 0)
return ASN1_BAD_ID;
@@ -1786,16 +1793,20 @@ _asn1_encode(const struct asn1_template *t, unsigned char *p, size_t len, const
}
if (*element == 0) {
- ret += der_put_octet_string(p, len,
- DPOC(data, choice->tt), &datalen);
+ if (choice->tt) {
+ /* This is an extensible CHOICE */
+ ret += der_put_octet_string(p, len,
+ DPOC(data, choice->tt), &datalen);
+ len -= datalen; p -= datalen;
+ } /* else this is really an error -- XXX what to do? */
} else {
choice += *element;
el = DPOC(data, choice->offset);
ret = _asn1_encode(choice->ptr, p, len, el, &datalen);
if (ret)
return ret;
+ len -= datalen; p -= datalen;
}
- len -= datalen; p -= datalen;
break;
}
@@ -2175,7 +2186,8 @@ _asn1_length(const struct asn1_template *t, const void *data)
break;
if (*element == 0) {
- ret += der_length_octet_string(DPOC(data, choice->tt));
+ if (choice->tt)
+ ret += der_length_octet_string(DPOC(data, choice->tt));
} else {
choice += *element;
ret += _asn1_length(choice->ptr, DPOC(data, choice->offset));
@@ -2350,7 +2362,16 @@ _asn1_free(const struct asn1_template *t, void *data)
break;
if (*element == 0) {
- der_free_octet_string(DPO(data, choice->tt));
+ /*
+ * If choice->tt != 0 then this is an extensible choice, and
+ * the offset choice->tt is the offset to u.ellipsis.
+ */
+ if (choice->tt != 0)
+ der_free_octet_string(DPO(data, choice->tt));
+ /*
+ * Else this was a not-fully initialized CHOICE. We could
+ * stand to memset clear the rest of it though...
+ */
} else {
choice += *element;
_asn1_free(choice->ptr, DPO(data, choice->offset));
@@ -2727,6 +2748,7 @@ _asn1_print(const struct asn1_template *t,
if (*element > A1_HEADER_LEN(choice)) {
r = rk_strpoolprintf(r, "null");
} else if (*element == 0) {
+ /* XXX If choice->tt then we should print the u.ellipsis */
r = rk_strpoolprintf(r, "null");
} else {
choice += *element;
@@ -2993,7 +3015,7 @@ _asn1_copy(const struct asn1_template *t, const void *from, void *to)
unsigned int i;
tel->val = calloc(fel->len, ellen);
- if (tel->val == NULL)
+ if (tel->val == NULL && fel->len > 0)
return ENOMEM;
tel->len = fel->len;
@@ -3024,7 +3046,12 @@ _asn1_copy(const struct asn1_template *t, const void *from, void *to)
*telement = *felement;
if (*felement == 0) {
- ret = der_copy_octet_string(DPOC(from, choice->tt), DPO(to, choice->tt));
+ if (choice->tt)
+ ret = der_copy_octet_string(DPOC(from, choice->tt), DPO(to, choice->tt));
+ /*
+ * Else we should really memset clear the rest of this choice,
+ * but we don't really know its size.
+ */
} else {
choice += *felement;
ret = _asn1_copy(choice->ptr,
diff --git a/third_party/heimdal/lib/base/Makefile.am b/third_party/heimdal/lib/base/Makefile.am
index 18300b3cff5..606e00a975c 100644
--- a/third_party/heimdal/lib/base/Makefile.am
+++ b/third_party/heimdal/lib/base/Makefile.am
@@ -16,6 +16,8 @@ AM_CPPFLAGS += $(ROKEN_RENAME) -I../com_err -I$(srcdir)/../com_err
lib_LTLIBRARIES = libheimbase.la
check_PROGRAMS = test_base
+test_base_CFLAGS = -Wno-string-concatenation
+
libheimbase_la_LDFLAGS = -version-info 1:0:0
if FRAMEWORK_COREFOUNDATION
diff --git a/third_party/heimdal/lib/base/context.c b/third_party/heimdal/lib/base/context.c
index fb9b442ce1e..f22ce9459f4 100644
--- a/third_party/heimdal/lib/base/context.c
+++ b/third_party/heimdal/lib/base/context.c
@@ -159,7 +159,7 @@ heim_get_debug_dest(heim_context context)
heim_error_code
heim_set_log_dest(heim_context context, heim_log_facility *fac)
{
- context->log_dest = fac;
+ context->log_dest = heim_log_ref(fac);
return 0;
}
diff --git a/third_party/heimdal/lib/base/db.c b/third_party/heimdal/lib/base/db.c
index b206ff6d766..e6f6af41a20 100644
--- a/third_party/heimdal/lib/base/db.c
+++ b/third_party/heimdal/lib/base/db.c
@@ -47,6 +47,8 @@
* memory-based rollback log is used).
*/
+#include "config.h"
+
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
@@ -1505,11 +1507,12 @@ json_db_sync(void *db, heim_error_t *error)
json = heim_json_copy_serialize(jsondb->dict, 0, &e);
if (json == NULL) {
+ ret = heim_error_get_code(e);
if (error)
*error = e;
else
heim_release(e);
- return heim_error_get_code(e);
+ return ret;
}
json_text = heim_string_get_utf8(json);
diff --git a/third_party/heimdal/lib/base/dll.c b/third_party/heimdal/lib/base/dll.c
index 59c39137b72..53f1f63bcdd 100644
--- a/third_party/heimdal/lib/base/dll.c
+++ b/third_party/heimdal/lib/base/dll.c
@@ -83,8 +83,8 @@ struct tls_values {
static HEIMDAL_THREAD_LOCAL struct tls_values values;
-static char dead_key;
-#define DEAD_KEY ((void *)&dead_key)
+static char dead_key[1];
+static void no_dtor(void *d) { (void)d; }
void
heim_w32_service_thread_detach(void *unused)
@@ -112,7 +112,7 @@ heim_w32_service_thread_detach(void *unused)
assert(i < key_defs->keys_start_idx + key_defs->keys_num);
}
dtor = key_defs->keys_dtors[i - key_defs->keys_start_idx];
- if (values.values[i] != NULL && dtor != NULL && dtor != DEAD_KEY)
+ if (values.values[i] != NULL && dtor != NULL && dtor != no_dtor)
dtor(values.values[i]);
values.values[i] = NULL;
}
@@ -151,7 +151,7 @@ heim_w32_key_create(HEIM_PRIV_thread_key *key, void (*dtor)(void *))
#if !defined(WIN32)
(void) pthread_once(&pt_once, create_pt_key);
- (void) pthread_setspecific(pt_key, DEAD_KEY);
+ (void) pthread_setspecific(pt_key, dead_key);
#endif
HEIMDAL_MUTEX_lock(&tls_key_defs_lock);
@@ -267,7 +267,7 @@ heim_w32_delete_key(HEIM_PRIV_thread_key key)
key_lookup(key, &key_defs, &dtor_idx, NULL);
if (key_defs == NULL)
return EINVAL;
- key_defs->keys_dtors[dtor_idx] = DEAD_KEY;
+ key_defs->keys_dtors[dtor_idx] = no_dtor;
return 0;
}
@@ -280,7 +280,7 @@ heim_w32_setspecific(HEIM_PRIV_thread_key key, void *value)
size_t i;
#if !defined(WIN32)
- (void) pthread_setspecific(pt_key, DEAD_KEY);
+ (void) pthread_setspecific(pt_key, dead_key);
#endif
key_lookup(key, NULL, NULL, &dtor);
@@ -305,7 +305,7 @@ heim_w32_setspecific(HEIM_PRIV_thread_key key, void *value)
assert(key < values.values_num);
- if (values.values[key] != NULL && dtor != NULL && dtor != DEAD_KEY)
+ if (values.values[key] != NULL && dtor != NULL && dtor != no_dtor)
dtor(values.values[key]);
values.values[key] = value;
diff --git a/third_party/heimdal/lib/base/error.c b/third_party/heimdal/lib/base/error.c
index 6ba3bea412d..bc289d3d910 100644
--- a/third_party/heimdal/lib/base/error.c
+++ b/third_party/heimdal/lib/base/error.c
@@ -86,6 +86,7 @@ heim_error_create_enomem(void)
void
heim_error_create_opt(heim_error_t *error, int error_code, const char *fmt, ...)
+ HEIMDAL_PRINTF_ATTRIBUTE((__printf__, 3, 4))
{
if (error) {
va_list ap;
@@ -97,6 +98,7 @@ heim_error_create_opt(heim_error_t *error, int error_code, const char *fmt, ...)
heim_error_t
heim_error_create(int error_code, const char *fmt, ...)
+ HEIMDAL_PRINTF_ATTRIBUTE((__printf__, 2, 3))
{
heim_error_t e;
va_list ap;
@@ -110,6 +112,7 @@ heim_error_create(int error_code, const char *fmt, ...)
heim_error_t
heim_error_createv(int error_code, const char *fmt, va_list ap)
+ HEIMDAL_PRINTF_ATTRIBUTE((__printf__, 2, 0))
{
heim_error_t e;
char *str;
diff --git a/third_party/heimdal/lib/base/heimbase-atomics.h b/third_party/heimdal/lib/base/heimbase-atomics.h
index 58b72ac4bc7..e468a36bda9 100644
--- a/third_party/heimdal/lib/base/heimbase-atomics.h
+++ b/third_party/heimdal/lib/base/heimbase-atomics.h
@@ -36,13 +36,15 @@
#ifndef HEIM_BASE_ATOMICS_H
#define HEIM_BASE_ATOMICS_H 1
-#include "config.h"
+#include <stdint.h>
/*
* Atomic operations
+ *
+ * (#define HEIM_BASE_ATOMICS_FALLBACK to test fallbacks.)
*/
-#if defined(HAVE_STDATOMIC_H)
+#if !defined(HEIM_BASE_ATOMICS_FALLBACK) && defined(HAVE_STDATOMIC_H)
#include <stdatomic.h>
@@ -52,23 +54,55 @@
#define heim_base_atomic(T) _Atomic(T)
-#define heim_base_atomic_inc(x) (atomic_fetch_add((x), 1) + 1)
-#define heim_base_atomic_dec(x) (atomic_fetch_sub((x), 1) - 1)
-#define heim_base_atomic_integer_type heim_base_atomic(unsigned int)
-#define heim_base_atomic_integer_max UINT_MAX
+#define heim_base_atomic_inc_32(x) (atomic_fetch_add((x), 1) + 1)
+#define heim_base_atomic_dec_32(x) (atomic_fetch_sub((x), 1) - 1)
+#define heim_base_atomic_inc_64(x) (atomic_fetch_add((x), 1) + 1)
+#define heim_base_atomic_dec_64(x) (atomic_fetch_sub((x), 1) - 1)
#define heim_base_exchange_pointer(t,v) atomic_exchange((t), (v))
#define heim_base_exchange_32(t,v) atomic_exchange((t), (v))
#define heim_base_exchange_64(t,v) atomic_exchange((t), (v))
-#elif defined(__GNUC__) && defined(HAVE___SYNC_ADD_AND_FETCH)
+/*
+ * <stdatomic.h>'s and AIX's CAS functions take a pointer to an expected value
+ * and return a boolean, setting the pointed-to variable to the old value of
+ * the target.
+ *
+ * Other CAS functions, like GCC's, Solaris'/Illumos', and Windows', return the
+ * old value and don't take a pointer to an expected value.
+ *
+ * We implement the latter semantics.
+ */
+static inline void *
+heim_base_cas_pointer_(heim_base_atomic(void *)*t, void *e, void *d)
+{
+ return atomic_compare_exchange_strong(t, &e, d), e;
+}
+
+static inline uint32_t
+heim_base_cas_32_(heim_base_atomic(uint32_t)*t, uint32_t e, uint32_t d)
+{
+ return atomic_compare_exchange_strong(t, &e, d), e;
+}
+
+static inline uint64_t
+heim_base_cas_64_(heim_base_atomic(uint64_t)*t, uint64_t e, uint64_t d)
+{
+ return atomic_compare_exchange_strong(t, &e, d), e;
+}
+
+#define heim_base_cas_pointer(t,e,d) heim_base_cas_pointer_((t), (e), (d))
+#define heim_base_cas_32(t,e,d) heim_base_cas_32_((t), (e), (d))
+#define heim_base_cas_64(t,e,d) heim_base_cas_64_((t), (e), (d))
+
+#elif !defined(HEIM_BASE_ATOMICS_FALLBACK) && defined(__GNUC__) && defined(HAVE___SYNC_ADD_AND_FETCH)
#define heim_base_atomic_barrier() __sync_synchronize()
-#define heim_base_atomic_inc(x) __sync_add_and_fetch((x), 1)
-#define heim_base_atomic_dec(x) __sync_sub_and_fetch((x), 1)
-#define heim_base_atomic_integer_type unsigned int
-#define heim_base_atomic_integer_max UINT_MAX
+#define heim_base_atomic_inc_32(x) __sync_add_and_fetch((x), 1)
+#define heim_base_atomic_dec_32(x) __sync_sub_and_fetch((x), 1)
+#define heim_base_atomic_inc_64(x) __sync_add_and_fetch((x), 1)
+#define heim_base_atomic_dec_64(x) __sync_sub_and_fetch((x), 1)
#ifndef __has_builtin
#define __has_builtin(x) 0
@@ -84,31 +118,47 @@
#define heim_base_exchange_32(t,v) heim_base_exchange_pointer((t), (v))
#define heim_base_exchange_64(t,v) heim_base_exchange_pointer((t), (v))
-#elif defined(__sun)
+#define heim_base_cas_pointer(t,e,d) __sync_val_compare_and_swap((t), (e), (d))
+#define heim_base_cas_32(t,e,d) __sync_val_compare_and_swap((t), (e), (d))
+#define heim_base_cas_64(t,e,d) __sync_val_compare_and_swap((t), (e), (d))
+
+#elif !defined(HEIM_BASE_ATOMICS_FALLBACK) && defined(__sun)
#include <sys/atomic.h>
+#include <mbarrier.h>
-#define heim_base_atomic_barrier() __machine_rw_barrier()
+static inline void __heim_base_atomic_barrier(void)
+{
+ __machine_rw_barrier();
+}
+
+#define heim_base_atomic_barrier() __heim_base_atomic_barrier()
+
+#define heim_base_atomic(T) volatile T
+
+#define heim_base_atomic_inc_32(x) atomic_inc_32_nv((x))
+#define heim_base_atomic_dec_32(x) atomic_dec_32_nv((x))
+#define heim_base_atomic_inc_64(x) atomic_inc_64_nv((x))
+#define heim_base_atomic_dec_64(x) atomic_dec_64_nv((x))
-#define heim_base_atomic_inc(x) atomic_inc_uint_nv((volatile uint_t *)(x))
-#define heim_base_atomic_dec(x) atomic_dec_uint_nv((volatile uint_t *)(x))
-#define heim_base_atomic_integer_type uint_t
-#define heim_base_atomic_integer_max UINT_MAX
+#define heim_base_exchange_pointer(t,v) atomic_swap_ptr((t), (void *)(v))
+#define heim_base_exchange_32(t,v) atomic_swap_32((t), (v))
+#define heim_base_exchange_64(t,v) atomic_swap_64((t), (v))
-#define heim_base_exchange_pointer(t,v) atomic_swap_ptr((volatile void *)(t), (void *)(v))
-#define heim_base_exchange_32(t,v) atomic_swap_32((volatile uint32_t *)(t), (v))
-#define heim_base_exchange_64(t,v) atomic_swap_64((volatile uint64_t *)(t), (v))
+#define heim_base_cas_pointer(t,e,d) atomic_cas_ptr((t), (e), (d))
+#define heim_base_cas_32(t,e,d) atomic_cas_32((t), (e), (d))
+#define heim_base_cas_64(t,e,d) atomic_cas_64((t), (e), (d))
-#elif defined(_AIX)
+#elif !defined(HEIM_BASE_ATOMICS_FALLBACK) && defined(_AIX)
#include <sys/atomic_op.h>
#define heim_base_atomic_barrier() __isync()
-#define heim_base_atomic_inc(x) (fetch_and_add((atomic_p)(x)) + 1)
-#define heim_base_atomic_dec(x) (fetch_and_add((atomic_p)(x)) - 1)
-#define heim_base_atomic_integer_type unsigned int
-#define heim_base_atomic_integer_max UINT_MAX
+#define heim_base_atomic_inc_32(x) (fetch_and_add((atomic_p)(x), 1) + 1)
+#define heim_base_atomic_dec_32(x) (fetch_and_add((atomic_p)(x), -1) - 1)
+#define heim_base_atomic_inc_64(x) (fetch_and_addlp((atomic_l)(x), 1) + 1)
+#define heim_base_atomic_dec_64(x) (fetch_and_addlp((atomic_l)(x), -1) - 1)
static inline void *
heim_base_exchange_pointer(void *p, void *newval)
@@ -143,79 +193,160 @@ heim_base_exchange_64(uint64_t *p, uint64_t newval)
return val;
}
-#elif defined(_WIN32)
+static inline void *
+heim_base_cas_pointer_(heim_base_atomic(void *)*t, void *e, void *d)
+{
+ return compare_and_swaplp((atomic_l)t, &e, d), e;
+}
+
+static inline uint32_t
+heim_base_cas_32_(heim_base_atomic(uint32_t)*t, uint32_t e, uint32_t d)
+{
+ return compare_and_swap((atomic_p)t, &e, d), e;
+}
+
+static inline uint64_t
+heim_base_cas_64_(heim_base_atomic(uint64_t)*t, uint64_t e, uint64_t d)
+{
+ return compare_and_swaplp((atomic_l)t, &e, d), e;
+}
+
+#define heim_base_cas_pointer(t,e,d) heim_base_cas_pointer_((t), (e), (d))
+#define heim_base_cas_32(t,e,d) heim_base_cas_32_((t), (e), (d))
+#define heim_base_cas_64(t,e,d) heim_base_cas_64_((t), (e), (d))
+
+#elif !defined(HEIM_BASE_ATOMICS_FALLBACK) && defined(_WIN32)
#define heim_base_atomic_barrier() MemoryBarrier()
-#define heim_base_atomic_inc(x) InterlockedIncrement(x)
-#define heim_base_atomic_dec(x) InterlockedDecrement(x)
-#define heim_base_atomic_integer_type LONG
-#define heim_base_atomic_integer_max MAXLONG
+#define heim_base_atomic_inc_32(x) InterlockedIncrement(x)
+#define heim_base_atomic_dec_32(x) InterlockedDecrement(x)
+#define heim_base_atomic_inc_64(x) InterlockedIncrement64(x)
+#define heim_base_atomic_dec_64(x) InterlockedDecrement64(x)
#define heim_base_exchange_pointer(t,v) InterlockedExchangePointer((PVOID volatile *)(t), (PVOID)(v))
#define heim_base_exchange_32(t,v) ((ULONG)InterlockedExchange((LONG volatile *)(t), (LONG)(v)))
-#define heim_base_exchange_64(t,v) ((ULONG64)InterlockedExchange64((LONG64 violatile *)(t), (LONG64)(v)))
+#define heim_base_exchange_64(t,v) ((ULONG64)InterlockedExchange64((ULONG64 volatile *)(t), (LONG64)(v)))
+
+#define heim_base_cas_pointer(t,e,d) InterlockedCompareExchangePointer((PVOID volatile *)(t), (d), (e))
+#define heim_base_cas_32(t,e,d) InterlockedCompareExchange ((LONG volatile *)(t), (d), (e))
+#define heim_base_cas_64(t,e,d) InterlockedCompareExchange64((ULONG64 volatile *)(t), (d), (e))
#else
+#define heim_base_atomic(T) volatile T
+#define heim_base_atomic_barrier()
+#define heim_base_atomic_load(x) (*(x))
+#define heim_base_atomic_init(t, v) do { (*(t) = (v)); } while (0)
+#define heim_base_atomic_store(t, v) do { (*(t) = (v)); } while (0)
+
#include <heim_threads.h>
#define HEIM_BASE_NEED_ATOMIC_MUTEX 1
-extern HEIMDAL_MUTEX _heim_base_mutex;
-#define heim_base_atomic_integer_type unsigned int
-#define heim_base_atomic_integer_max UINT_MAX
+static inline uint32_t
+heim_base_atomic_inc_32(heim_base_atomic(uint32_t) *x)
+{
+ uint32_t t;
+ HEIMDAL_MUTEX_lock(heim_base_mutex());
+ t = ++(*x);
+ HEIMDAL_MUTEX_unlock(heim_base_mutex());
+ return t;
+}
-static inline heim_base_atomic_integer_type
-heim_base_atomic_inc(heim_base_atomic_integer_type *x)
+static inline uint32_t
+heim_base_atomic_dec_32(heim_base_atomic(uint32_t) *x)
{
- heim_base_atomic_integer_type t;
- HEIMDAL_MUTEX_lock(&_heim_base_mutex);
+ uint32_t t;
+ HEIMDAL_MUTEX_lock(heim_base_mutex());
+ t = --(*x);
+ HEIMDAL_MUTEX_unlock(heim_base_mutex());
+ return t;
+}
+
+static inline uint64_t
+heim_base_atomic_inc_64(heim_base_atomic(uint64_t) *x)
+{
+ uint64_t t;
+ HEIMDAL_MUTEX_lock(heim_base_mutex());
t = ++(*x);
- HEIMDAL_MUTEX_unlock(&_heim_base_mutex);
+ HEIMDAL_MUTEX_unlock(heim_base_mutex());
return t;
}
-static inline heim_base_atomic_integer_type
-heim_base_atomic_dec(heim_base_atomic_integer_type *x)
+static inline uint64_t
+heim_base_atomic_dec_64(heim_base_atomic(uint64_t) *x)
{
- heim_base_atomic_integer_type t;
- HEIMDAL_MUTEX_lock(&_heim_base_mutex);
+ uint64_t t;
+ HEIMDAL_MUTEX_lock(heim_base_mutex());
t = --(*x);
- HEIMDAL_MUTEX_unlock(&_heim_base_mutex);
+ HEIMDAL_MUTEX_unlock(heim_base_mutex());
return t;
}
static inline void *
-heim_base_exchange_pointer(void *target, void *value)
+heim_base_exchange_pointer(heim_base_atomic(void *)target, void *value)
{
void *old;
- HEIMDAL_MUTEX_lock(&_heim_base_mutex);
+ HEIMDAL_MUTEX_lock(heim_base_mutex());
old = *(void **)target;
*(void **)target = value;
- HEIMDAL_MUTEX_unlock(&_heim_base_mutex);
+ HEIMDAL_MUTEX_unlock(heim_base_mutex());
return old;
}
static inline uint32_t
-heim_base_exchange_32(uint32_t *p, uint32_t newval)
+heim_base_exchange_32(heim_base_atomic(uint32_t) *target, uint32_t newval)
{
uint32_t old;
- HEIMDAL_MUTEX_lock(&_heim_base_mutex);
- old = *p;
- *p = newval;
- HEIMDAL_MUTEX_unlock(&_heim_base_mutex);
+ HEIMDAL_MUTEX_lock(heim_base_mutex());
+ old = *target;
+ *target = newval;
+ HEIMDAL_MUTEX_unlock(heim_base_mutex());
return old;
}
static inline uint64_t
-heim_base_exchange_64(uint64_t *p, uint64_t newval)
+heim_base_exchange_64(heim_base_atomic(uint64_t) *target, uint64_t newval)
{
uint64_t old;
- HEIMDAL_MUTEX_lock(&_heim_base_mutex);
- old = *p;
- *p = newval;
- HEIMDAL_MUTEX_unlock(&_heim_base_mutex);
+ HEIMDAL_MUTEX_lock(heim_base_mutex());
+ old = *target;
+ *target = newval;
+ HEIMDAL_MUTEX_unlock(heim_base_mutex());
+ return old;
+}
+
+static inline void *
+heim_base_cas_pointer(heim_base_atomic(void *)target, void *expected, void *desired)
+{
+ void *old;
+ HEIMDAL_MUTEX_lock(heim_base_mutex());
+ if ((old = *(void **)target) == expected)
+ *(void **)target = desired;
+ HEIMDAL_MUTEX_unlock(heim_base_mutex());
+ return old;
+}
+
+static inline uint32_t
+heim_base_cas_32(heim_base_atomic(uint32_t) *target, uint32_t expected, uint32_t desired)
+{
+ uint32_t old;
+ HEIMDAL_MUTEX_lock(heim_base_mutex());
+ if ((old = *(uint32_t *)target) == expected)
+ *target = desired;
+ HEIMDAL_MUTEX_unlock(heim_base_mutex());
+ return old;
+}
+
+static inline uint64_t
+heim_base_cas_64(heim_base_atomic(uint64_t) *target, uint64_t expected,uint64_t desired)
+{
+ uint64_t old;
+ HEIMDAL_MUTEX_lock(heim_base_mutex());
+ if ((old = *(uint64_t *)target) == expected)
+ *target = desired;
+ HEIMDAL_MUTEX_unlock(heim_base_mutex());
return old;
}
@@ -226,7 +357,7 @@ heim_base_exchange_64(uint64_t *p, uint64_t newval)
#endif
#ifndef heim_base_atomic_barrier
-#define heim_base_atomic_barrier()
+static inline void heim_base_atomic_barrier(void) { return; }
#endif
#ifndef heim_base_atomic_load
diff --git a/third_party/heimdal/lib/base/heimbase.c b/third_party/heimdal/lib/base/heimbase.c
index 1e6805a25e7..d9b15768136 100644
--- a/third_party/heimdal/lib/base/heimbase.c
+++ b/third_party/heimdal/lib/base/heimbase.c
@@ -34,13 +34,14 @@
*/
#include "baselocl.h"
+#include "heimbase-atomics.h"
#include <syslog.h>
-static heim_base_atomic_integer_type tidglobal = HEIM_TID_USER;
+static heim_base_atomic(uint32_t) tidglobal = HEIM_TID_USER;
struct heim_base {
heim_type_t isa;
- heim_base_atomic_integer_type ref_cnt;
+ heim_base_atomic(uint32_t) ref_cnt;
HEIM_TAILQ_ENTRY(heim_base) autorel;
heim_auto_release_t autorelpool;
uintptr_t isaextra[3];
@@ -49,7 +50,7 @@ struct heim_base {
/* specialized version of base */
struct heim_base_mem {
heim_type_t isa;
- heim_base_atomic_integer_type ref_cnt;
+ heim_base_atomic(uint32_t) ref_cnt;
HEIM_TAILQ_ENTRY(heim_base) autorel;
heim_auto_release_t autorelpool;
const char *name;
@@ -60,9 +61,12 @@ struct heim_base_mem {
#define PTR2BASE(ptr) (((struct heim_base *)ptr) - 1)
#define BASE2PTR(ptr) ((void *)(((struct heim_base *)ptr) + 1))
-#ifdef HEIM_BASE_NEED_ATOMIC_MUTEX
-HEIMDAL_MUTEX _heim_base_mutex = HEIMDAL_MUTEX_INITIALIZER;
-#endif
+HEIMDAL_MUTEX * HEIM_CALLCONV
+heim_base_mutex(void)
+{
+ static HEIMDAL_MUTEX _heim_base_mutex = HEIMDAL_MUTEX_INITIALIZER;
+ return &_heim_base_mutex;
+}
/*
* Auto release structure
@@ -93,10 +97,10 @@ heim_retain(heim_object_t ptr)
p = PTR2BASE(ptr);
- if (heim_base_atomic_load(&p->ref_cnt) == heim_base_atomic_integer_max)
+ if (heim_base_atomic_load(&p->ref_cnt) == UINT32_MAX)
return ptr;
- if ((heim_base_atomic_inc(&p->ref_cnt) - 1) == 0)
+ if ((heim_base_atomic_inc_32(&p->ref_cnt) - 1) == 0)
heim_abort("resurection");
return ptr;
}
@@ -110,7 +114,7 @@ heim_retain(heim_object_t ptr)
void
heim_release(void *ptr)
{
- heim_base_atomic_integer_type old;
+ heim_base_atomic(uint32_t) old;
struct heim_base *p;
if (ptr == NULL || heim_base_is_tagged(ptr))
@@ -118,10 +122,10 @@ heim_release(void *ptr)
p = PTR2BASE(ptr);
- if (heim_base_atomic_load(&p->ref_cnt) == heim_base_atomic_integer_max)
+ if (heim_base_atomic_load(&p->ref_cnt) == UINT32_MAX)
return;
- old = heim_base_atomic_dec(&p->ref_cnt) + 1;
+ old = heim_base_atomic_dec_32(&p->ref_cnt) + 1;
if (old > 1)
return;
@@ -160,7 +164,7 @@ void
_heim_make_permanent(heim_object_t ptr)
{
struct heim_base *p = PTR2BASE(ptr);
- heim_base_atomic_store(&p->ref_cnt, heim_base_atomic_integer_max);
+ heim_base_atomic_store(&p->ref_cnt, UINT32_MAX);
}
@@ -260,9 +264,12 @@ heim_cmp(heim_object_t a, heim_object_t b)
static void HEIM_CALLCONV
memory_dealloc(void *ptr)
{
- struct heim_base_mem *p = (struct heim_base_mem *)PTR2BASE(ptr);
- if (p->dealloc)
- p->dealloc(ptr);
+ if (ptr) {
+ struct heim_base_mem *p = (struct heim_base_mem *)PTR2BASE(ptr);
+
+ if (p->dealloc)
+ p->dealloc(ptr);
+ }
}
struct heim_type_data memory_object = {
@@ -318,7 +325,7 @@ _heim_create_type(const char *name,
if (type == NULL)
return NULL;
- type->tid = heim_base_atomic_inc(&tidglobal);
+ type->tid = heim_base_atomic_inc_32(&tidglobal);
type->name = name;
type->init = init;
type->dealloc = dealloc;
@@ -500,6 +507,8 @@ heim_base_once_f(heim_base_once_t *once, void *ctx, void (*func)(void *))
void
heim_abort(const char *fmt, ...)
+ HEIMDAL_NORETURN_ATTRIBUTE
+ HEIMDAL_PRINTF_ATTRIBUTE((__printf__, 1, 2))
{
va_list ap;
va_start(ap, fmt);
@@ -513,6 +522,8 @@ heim_abort(const char *fmt, ...)
void
heim_abortv(const char *fmt, va_list ap)
+ HEIMDAL_NORETURN_ATTRIBUTE
+ HEIMDAL_PRINTF_ATTRIBUTE((__printf__, 1, 0))
{
static char str[1024];
@@ -672,13 +683,14 @@ heim_object_t
heim_auto_release(heim_object_t ptr)
{
struct heim_base *p;
- struct ar_tls *tls = autorel_tls();
+ struct ar_tls *tls;
heim_auto_release_t ar;
if (ptr == NULL || heim_base_is_tagged(ptr))
return ptr;
p = PTR2BASE(ptr);
+ tls = autorel_tls();
/* drop from old pool */
if ((ar = p->autorelpool) != NULL) {
@@ -913,14 +925,14 @@ heim_path_vcreate(heim_object_t ptr, size_t size, heim_object_t leaf,
heim_abort("heim_path_vcreate() does not create root nodes");
while (path_element != NULL) {
+ int idx = -1;
+
next_path_element = va_arg(ap, heim_object_t);
node_type = heim_get_tid(node);
if (node_type == HEIM_TID_DICT) {
next_node = heim_dict_get_value(node, path_element);
} else if (node_type == HEIM_TID_ARRAY) {
- int idx = -1;
-
if (heim_get_tid(path_element) == HEIM_TID_NUMBER)
idx = heim_number_get_int(path_element);
if (idx < 0) {
@@ -931,10 +943,16 @@ heim_path_vcreate(heim_object_t ptr, size_t size, heim_object_t leaf,
"and positive");
return EINVAL;
}
- if (idx < heim_array_get_length(node))
+ if (idx < heim_array_get_length(node)) {
next_node = heim_array_get_value(node, idx);
- else
+ } else if (idx == heim_array_get_length(node)) {
next_node = NULL;
+ } else {
+ if (error)
+ *error = heim_error_create(EINVAL,
+ "Index for array in path is too large");
+ return EINVAL;
+ }
} else if (node_type == HEIM_TID_DB && next_path_element != NULL) {
if (error)
*error = heim_error_create(EINVAL, "Interior node is a DB");
@@ -946,26 +964,31 @@ heim_path_vcreate(heim_object_t ptr, size_t size, heim_object_t leaf,
/* Create missing interior node */
if (next_node == NULL) {
- next_node = heim_dict_create(size); /* no arrays or DBs, just dicts */
- if (next_node == NULL) {
+ heim_dict_t new_node;
+
+ new_node = heim_dict_create(size); /* no arrays or DBs, just dicts */
+ if (new_node == NULL) {
ret = ENOMEM;
goto err;
}
if (node_type == HEIM_TID_DICT) {
- ret = heim_dict_set_value(node, path_element, next_node);
+ ret = heim_dict_set_value(node, path_element, new_node);
+ next_node = heim_dict_get_value(node, path_element);
} else if (node_type == HEIM_TID_ARRAY &&
heim_number_get_int(path_element) <= heim_array_get_length(node)) {
ret = heim_array_insert_value(node,
heim_number_get_int(path_element),
- next_node);
+ new_node);
+ next_node = heim_array_get_value(node, idx);
} else {
ret = EINVAL;
if (error)
*error = heim_error_create(ret, "Node in path not a "
"container");
}
- heim_release(next_node);
+
+ heim_release(new_node);
if (ret)
goto err;
}
diff --git a/third_party/heimdal/lib/base/heimbase.h b/third_party/heimdal/lib/base/heimbase.h
index 5d5c4e3b75e..d2c011414c7 100644
--- a/third_party/heimdal/lib/base/heimbase.h
+++ b/third_party/heimdal/lib/base/heimbase.h
@@ -36,8 +36,6 @@
#ifndef HEIM_BASE_H
#define HEIM_BASE_H 1
-#include "config.h"
-
#include <sys/types.h>
#ifndef _WIN32
#include <sys/socket.h>
@@ -190,38 +188,8 @@ typedef long heim_base_once_t; /* XXX arch dependant */
#endif
-heim_object_t heim_retain(heim_object_t);
-void heim_release(heim_object_t);
-
-void heim_show(heim_object_t);
-
typedef void (HEIM_CALLCONV *heim_type_dealloc)(void *);
-void *
-heim_alloc(size_t size, const char *name, heim_type_dealloc dealloc);
-
-heim_tid_t
-heim_get_tid(heim_object_t object);
-
-int
-heim_cmp(heim_object_t a, heim_object_t b);
-
-uintptr_t
-heim_get_hash(heim_object_t ptr);
-
-void
-heim_base_once_f(heim_base_once_t *, void *, void (*)(void *));
-
-void
-heim_abort(const char *fmt, ...)
- HEIMDAL_NORETURN_ATTRIBUTE
- HEIMDAL_PRINTF_ATTRIBUTE((__printf__, 1, 2));
-
-void
-heim_abortv(const char *fmt, va_list ap)
- HEIMDAL_NORETURN_ATTRIBUTE
- HEIMDAL_PRINTF_ATTRIBUTE((__printf__, 1, 0));
-
#define heim_assert(e,t) \
(heim_builtin_expect(!(e), 0) ? heim_abort(t ":" #e) : (void)0)
@@ -229,70 +197,23 @@ heim_abortv(const char *fmt, va_list ap)
*
*/
-heim_null_t
-heim_null_create(void);
-
-heim_bool_t
-heim_bool_create(int);
-
-int
-heim_bool_val(heim_bool_t);
-
/*
* Array
*/
typedef struct heim_array_data *heim_array_t;
-heim_array_t heim_array_create(void);
-heim_tid_t heim_array_get_type_id(void);
-
typedef void (*heim_array_iterator_f_t)(heim_object_t, void *, int *);
typedef int (*heim_array_filter_f_t)(heim_object_t, void *);
-int heim_array_append_value(heim_array_t, heim_object_t);
-int heim_array_insert_value(heim_array_t, size_t idx, heim_object_t);
-void heim_array_iterate_f(heim_array_t, void *, heim_array_iterator_f_t);
-void heim_array_iterate_reverse_f(heim_array_t, void *, heim_array_iterator_f_t);
-#ifdef __BLOCKS__
-void heim_array_iterate(heim_array_t, void (^)(heim_object_t, int *));
-void heim_array_iterate_reverse(heim_array_t, void (^)(heim_object_t, int *));
-#endif
-size_t heim_array_get_length(heim_array_t);
-heim_object_t
- heim_array_get_value(heim_array_t, size_t);
-heim_object_t
- heim_array_copy_value(heim_array_t, size_t);
-void heim_array_set_value(heim_array_t, size_t, heim_object_t);
-void heim_array_delete_value(heim_array_t, size_t);
-void heim_array_filter_f(heim_array_t, void *, heim_array_filter_f_t);
-#ifdef __BLOCKS__
-void heim_array_filter(heim_array_t, int (^)(heim_object_t));
-#endif
-
/*
* Dict
*/
typedef struct heim_dict_data *heim_dict_t;
-heim_dict_t heim_dict_create(size_t size);
-heim_tid_t heim_dict_get_type_id(void);
-
typedef void (*heim_dict_iterator_f_t)(heim_object_t, heim_object_t, void *);
-int heim_dict_set_value(heim_dict_t, heim_object_t, heim_object_t);
-void heim_dict_iterate_f(heim_dict_t, void *, heim_dict_iterator_f_t);
-#ifdef __BLOCKS__
-void heim_dict_iterate(heim_dict_t, void (^)(heim_object_t, heim_object_t));
-#endif
-
-heim_object_t
- heim_dict_get_value(heim_dict_t, heim_object_t);
-heim_object_t
- heim_dict_copy_value(heim_dict_t, heim_object_t);
-void heim_dict_delete_key(heim_dict_t, heim_object_t);
-
/*
* String
*/
@@ -300,15 +221,6 @@ void heim_dict_delete_key(heim_dict_t, heim_object_t);
typedef struct heim_string_data *heim_string_t;
typedef void (*heim_string_free_f_t)(void *);
-heim_string_t heim_string_create(const char *);
-heim_string_t heim_string_ref_create(const char *, heim_string_free_f_t);
-heim_string_t heim_string_create_with_bytes(const void *, size_t);
-heim_string_t heim_string_ref_create_with_bytes(const void *, size_t,
- heim_string_free_f_t);
-heim_string_t heim_string_create_with_format(const char *, ...);
-heim_tid_t heim_string_get_type_id(void);
-const char * heim_string_get_utf8(heim_string_t);
-
#define HSTR(_str) (__heim_string_constant("" _str ""))
heim_string_t __heim_string_constant(const char *);
@@ -318,41 +230,10 @@ heim_string_t __heim_string_constant(const char *);
typedef struct heim_error * heim_error_t;
-heim_error_t heim_error_create_enomem(void);
-
-heim_error_t heim_error_create(int, const char *, ...)
- HEIMDAL_PRINTF_ATTRIBUTE((__printf__, 2, 3));
-
-void heim_error_create_opt(heim_error_t *error, int error_code, const char *fmt, ...)
- HEIMDAL_PRINTF_ATTRIBUTE((__printf__, 3, 4));
-
-heim_error_t heim_error_createv(int, const char *, va_list)
- HEIMDAL_PRINTF_ATTRIBUTE((__printf__, 2, 0));
-
-heim_string_t heim_error_copy_string(heim_error_t);
-int heim_error_get_code(heim_error_t);
-
-heim_error_t heim_error_append(heim_error_t, heim_error_t);
-
/*
* Path
*/
-heim_object_t heim_path_get(heim_object_t ptr, heim_error_t *error, ...);
-heim_object_t heim_path_copy(heim_object_t ptr, heim_error_t *error, ...);
-heim_object_t heim_path_vget(heim_object_t ptr, heim_error_t *error,
- va_list ap);
-heim_object_t heim_path_vcopy(heim_object_t ptr, heim_error_t *error,
- va_list ap);
-
-int heim_path_vcreate(heim_object_t ptr, size_t size, heim_object_t leaf,
- heim_error_t *error, va_list ap);
-int heim_path_create(heim_object_t ptr, size_t size, heim_object_t leaf,
- heim_error_t *error, ...);
-
-void heim_path_vdelete(heim_object_t ptr, heim_error_t *error, va_list ap);
-void heim_path_delete(heim_object_t ptr, heim_error_t *error, ...);
-
/*
* Data (octet strings)
*/
@@ -369,14 +250,6 @@ typedef struct heim_base_data heim_octet_string;
typedef struct heim_base_data * heim_data_t;
typedef void (*heim_data_free_f_t)(void *);
-heim_data_t heim_data_create(const void *, size_t);
-heim_data_t heim_data_ref_create(const void *, size_t, heim_data_free_f_t);
-heim_tid_t heim_data_get_type_id(void);
-const heim_octet_string *
- heim_data_get_data(heim_data_t);
-const void * heim_data_get_ptr(heim_data_t);
-size_t heim_data_get_length(heim_data_t);
-
/*
* DB
*/
@@ -426,53 +299,18 @@ extern struct heim_db_type heim_sorted_text_file_dbtype;
#define HEIM_DB_TYPE_VERSION_01 1
-int heim_db_register(const char *dbtype,
- void *data,
- struct heim_db_type *plugin);
-
-heim_db_t heim_db_create(const char *dbtype, const char *dbname,
- heim_dict_t options, heim_error_t *error);
-heim_db_t heim_db_clone(heim_db_t, heim_error_t *);
-int heim_db_begin(heim_db_t, int, heim_error_t *);
-int heim_db_commit(heim_db_t, heim_error_t *);
-int heim_db_rollback(heim_db_t, heim_error_t *);
-heim_tid_t heim_db_get_type_id(void);
-
-int heim_db_set_value(heim_db_t, heim_string_t, heim_data_t, heim_data_t,
- heim_error_t *);
-heim_data_t heim_db_copy_value(heim_db_t, heim_string_t, heim_data_t,
- heim_error_t *);
-int heim_db_delete_key(heim_db_t, heim_string_t, heim_data_t,
- heim_error_t *);
-void heim_db_iterate_f(heim_db_t, heim_string_t, void *,
- heim_db_iterator_f_t, heim_error_t *);
-#ifdef __BLOCKS__
-void heim_db_iterate(heim_db_t, heim_string_t,
- void (^)(heim_data_t, heim_data_t), heim_error_t *);
-#endif
-
-
/*
* Number
*/
typedef struct heim_number_data *heim_number_t;
-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);
-
/*
- *
+ * Autorelease
*/
typedef struct heim_auto_release * heim_auto_release_t;
-heim_auto_release_t heim_auto_release_create(void);
-void heim_auto_release_drain(heim_auto_release_t);
-heim_object_t heim_auto_release(heim_object_t);
-
/*
* JSON
*/
@@ -494,22 +332,10 @@ typedef enum heim_json_flags {
HEIM_JSON_F_INDENT8 = 4096,
} heim_json_flags_t;
-heim_object_t heim_json_create(const char *, size_t, heim_json_flags_t,
- heim_error_t *);
-heim_object_t heim_json_create_with_bytes(const void *, size_t, size_t,
- heim_json_flags_t,
- heim_error_t *);
-heim_string_t heim_json_copy_serialize(heim_object_t, heim_json_flags_t,
- heim_error_t *);
-
-
/*
* Debug
*/
-heim_string_t
-heim_description(heim_object_t ptr);
-
/*
* Binary search.
*
@@ -530,14 +356,7 @@ void _bsearch_file_close(bsearch_file_handle *bfh);
* Thread-specific keys
*/
-int heim_w32_key_create(unsigned long *, void (*)(void *));
-int heim_w32_delete_key(unsigned long);
-int heim_w32_setspecific(unsigned long, void *);
-void *heim_w32_getspecific(unsigned long);
-void heim_w32_service_thread_detach(void *);
-
#include <heim_threads.h>
-#include "heimbase-atomics.h"
#include <com_err.h>
/*
diff --git a/third_party/heimdal/lib/base/json.c b/third_party/heimdal/lib/base/json.c
index c7ef0658850..4fa0f2d5aff 100644
--- a/third_party/heimdal/lib/base/json.c
+++ b/third_party/heimdal/lib/base/json.c
@@ -893,7 +893,7 @@ parse_string(struct parse_ctx *ctx)
continue; /* This will cause p0 to be realloc'ed */
}
p_save = ctx->p;
- ctop = cbot = -3;
+ cbot = -3;
ctop = unescape_unicode(ctx);
if (ctop == -1 && strict)
return parse_string_error(ctx, p0, "Invalid escaped Unicode");
diff --git a/third_party/heimdal/lib/base/log.c b/third_party/heimdal/lib/base/log.c
index 1d79c7e45b9..9a97276e153 100644
--- a/third_party/heimdal/lib/base/log.c
+++ b/third_party/heimdal/lib/base/log.c
@@ -35,6 +35,7 @@
#include "baselocl.h"
#include "heim_threads.h"
+#include "heimbase-atomics.h"
#include "heimbase.h"
#include "heimbase-svc.h"
#include <assert.h>
@@ -52,7 +53,7 @@ struct heim_log_facility_internal {
struct heim_log_facility_s {
char *program;
- size_t refs;
+ heim_base_atomic(uint32_t) refs;
size_t len;
struct heim_log_facility_internal *val;
};
@@ -156,7 +157,7 @@ heim_log_facility *
heim_log_ref(heim_log_facility *fac)
{
if (fac)
- fac->refs++;
+ (void) heim_base_atomic_inc_32(&fac->refs);
return fac;
}
@@ -226,6 +227,8 @@ open_syslog(heim_context context,
close_syslog, sd);
if (ret)
free(sd);
+ else
+ sd = NULL;
return ret;
}
@@ -347,6 +350,7 @@ open_file(heim_context context, heim_log_facility *fac, int min, int max,
free(fd);
} else if (disp & FILEDISP_KEEPOPEN) {
log_file(context, NULL, NULL, fd);
+ fd = NULL;
}
return ret;
}
@@ -463,7 +467,7 @@ heim_closelog(heim_context context, heim_log_facility *fac)
{
int i;
- if (!fac || --(fac->refs))
+ if (!fac || heim_base_atomic_dec_32(&fac->refs))
return;
for (i = 0; i < fac->len; i++)
(*fac->val[i].close_func)(fac->val[i].data);
diff --git a/third_party/heimdal/lib/base/test_base.c b/third_party/heimdal/lib/base/test_base.c
index 6d0668663af..cc875d7f8b6 100644
--- a/third_party/heimdal/lib/base/test_base.c
+++ b/third_party/heimdal/lib/base/test_base.c
@@ -64,6 +64,7 @@
#include <fcntl.h>
#include "baselocl.h"
+#include "heimbase-atomics.h"
static void HEIM_CALLCONV
memory_free(heim_object_t obj)
@@ -1273,6 +1274,84 @@ test_array()
return 0;
}
+/* This function tests only that heimbase-atomics.h compiles */
+static int
+test_atomics(void)
+{
+ heim_base_atomic(void *) tptr;
+ heim_base_atomic(uint32_t) tu32;
+ heim_base_atomic(uint64_t) tu64;
+
+ heim_base_atomic_init(&tptr, NULL);
+ heim_base_atomic_init(&tu32, 0);
+ heim_base_atomic_init(&tu64, 0);
+
+ if (heim_base_atomic_load(&tptr))
+ return 1;
+ if (heim_base_atomic_load(&tu32))
+ return 1;
+ if (heim_base_atomic_load(&tu64))
+ return 1;
+
+ heim_base_atomic_store(&tptr, &tptr);
+ heim_base_atomic_store(&tu32, 1);
+ heim_base_atomic_store(&tu64, 1);
+
+ if (heim_base_atomic_load(&tptr) != &tptr)
+ return 1;
+ if (heim_base_atomic_load(&tu32) != 1)
+ return 1;
+ if (heim_base_atomic_load(&tu64) != 1)
+ return 1;
+
+ if (heim_base_atomic_inc_32(&tu32) != 2 ||
+ heim_base_atomic_load(&tu32) != 2)
+ return 1;
+ if (heim_base_atomic_inc_64(&tu64) != 2 ||
+ heim_base_atomic_load(&tu64) != 2)
+ return 1;
+
+ if (heim_base_atomic_dec_32(&tu32) != 1 ||
+ heim_base_atomic_load(&tu32) != 1)
+ return 1;
+ if (heim_base_atomic_dec_64(&tu64) != 1 ||
+ heim_base_atomic_load(&tu64) != 1)
+ return 1;
+
+ heim_base_exchange_pointer(&tptr, (void *)&tu32);
+ if (heim_base_atomic_load(&tptr) != &tu32)
+ return 1;
+ heim_base_exchange_32(&tu32, 32);
+ if (heim_base_atomic_load(&tu32) != 32)
+ return 1;
+ heim_base_exchange_64(&tu64, 64);
+ if (heim_base_atomic_load(&tu64) != 64)
+ return 1;
+
+ if (heim_base_cas_pointer(&tptr, (void *)&tu32, (void *)&tu64) != &tu32)
+ return 1;
+ if (heim_base_cas_pointer(&tptr, (void *)&tu32, (void *)&tptr) != &tu64)
+ return 1;
+ if (heim_base_atomic_load(&tptr) != (void *)&tu64)
+ return 1;
+
+ if (heim_base_cas_32(&tu32, 32, 4) != 32)
+ return 1;
+ if (heim_base_cas_32(&tu32, 32, 4) != 4)
+ return 1;
+ if (heim_base_atomic_load(&tu32) != 4)
+ return 1;
+
+ if (heim_base_cas_64(&tu64, 64, 4) != 64)
+ return 1;
+ if (heim_base_cas_64(&tu64, 64, 4) != 4)
+ return 1;
+ if (heim_base_atomic_load(&tu64) != 4)
+ return 1;
+
+ return 0;
+}
+
int
main(int argc, char **argv)
{
@@ -1295,6 +1374,7 @@ main(int argc, char **argv)
res |= test_db(NULL, NULL);
res |= test_db("json", argc > 1 ? argv[1] : "test_db.json");
res |= test_array();
+ res |= test_atomics();
return res ? 1 : 0;
}
diff --git a/third_party/heimdal/lib/base/version-script.map b/third_party/heimdal/lib/base/version-script.map
index 9493ee69236..1ba88992985 100644
--- a/third_party/heimdal/lib/base/version-script.map
+++ b/third_party/heimdal/lib/base/version-script.map
@@ -44,6 +44,7 @@ HEIMDAL_BASE_1.0 {
heim_auto_release_create;
heim_auto_release_drain;
heim_base_once_f;
+ heim_base_mutex;
heim_bool_create;
heim_bool_val;
heim_clear_error_message;
diff --git a/third_party/heimdal/lib/gssapi/gss-token.c b/third_party/heimdal/lib/gssapi/gss-token.c
index f3f90521c3b..a4c02967cf3 100644
--- a/third_party/heimdal/lib/gssapi/gss-token.c
+++ b/third_party/heimdal/lib/gssapi/gss-token.c
@@ -472,8 +472,13 @@ accept_one(gss_name_t service, const char *ccname, int negotiate)
NULL, NULL, &deleg_creds);
ret = write_and_free_token(&out, negotiate);
- if (ret)
+ if (ret) {
+ OM_uint32 junk;
+
+ (void) gss_delete_sec_context(&junk, &ctx,
+ GSS_C_NO_BUFFER);
return ret;
+ }
GBAIL("gss_accept_sec_context", maj, min);
} while (maj & GSS_S_CONTINUE_NEEDED);
@@ -491,6 +496,7 @@ accept_one(gss_name_t service, const char *ccname, int negotiate)
(char *)dname.value);
(void) gss_release_buffer(&min, &dname);
(void) gss_release_name(&min, &client);
+ (void) gss_delete_sec_context(&min, &ctx, GSS_C_NO_BUFFER);
if (ccname) {
#ifdef HAVE_GSS_STORE_CRED_INTO
diff --git a/third_party/heimdal/lib/gssapi/krb5/8003.c b/third_party/heimdal/lib/gssapi/krb5/8003.c
index bf7da11c754..0b91cf83b82 100644
--- a/third_party/heimdal/lib/gssapi/krb5/8003.c
+++ b/third_party/heimdal/lib/gssapi/krb5/8003.c
@@ -33,48 +33,6 @@
#include "gsskrb5_locl.h"
-krb5_error_code
-_gsskrb5_encode_om_uint32(OM_uint32 n, u_char *p)
-{
- p[0] = (n >> 0) & 0xFF;
- p[1] = (n >> 8) & 0xFF;
- p[2] = (n >> 16) & 0xFF;
- p[3] = (n >> 24) & 0xFF;
- return 0;
-}
-
-krb5_error_code
-_gsskrb5_encode_be_om_uint32(OM_uint32 n, u_char *p)
-{
- p[0] = (n >> 24) & 0xFF;
- p[1] = (n >> 16) & 0xFF;
- p[2] = (n >> 8) & 0xFF;
- p[3] = (n >> 0) & 0xFF;
- return 0;
-}
-
-krb5_error_code
-_gsskrb5_decode_om_uint32(const void *ptr, OM_uint32 *n)
-{
- const u_char *p = ptr;
- *n = ((uint32_t)p[0])
- | ((uint32_t)p[1] << 8)
- | ((uint32_t)p[2] << 16)
- | ((uint32_t)p[3] << 24);
- return 0;
-}
-
-krb5_error_code
-_gsskrb5_decode_be_om_uint32(const void *ptr, OM_uint32 *n)
-{
- const u_char *p = ptr;
- *n = ((uint32_t)p[0] <<24)
- | ((uint32_t)p[1] << 16)
- | ((uint32_t)p[2] << 8)
- | ((uint32_t)p[3]);
- return 0;
-}
-
static krb5_error_code
hash_input_chan_bindings (const gss_channel_bindings_t b,
u_char *p)
@@ -85,23 +43,23 @@ hash_input_chan_bindings (const gss_channel_bindings_t b,
ctx = EVP_MD_CTX_create();
EVP_DigestInit_ex(ctx, EVP_md5(), NULL);
- _gsskrb5_encode_om_uint32 (b->initiator_addrtype, num);
+ _gss_mg_encode_le_uint32 (b->initiator_addrtype, num);
EVP_DigestUpdate(ctx, num, sizeof(num));
- _gsskrb5_encode_om_uint32 (b->initiator_address.length, num);
+ _gss_mg_encode_le_uint32 (b->initiator_address.length, num);
EVP_DigestUpdate(ctx, num, sizeof(num));
if (b->initiator_address.length)
EVP_DigestUpdate(ctx,
b->initiator_address.value,
b->initiator_address.length);
- _gsskrb5_encode_om_uint32 (b->acceptor_addrtype, num);
+ _gss_mg_encode_le_uint32 (b->acceptor_addrtype, num);
EVP_DigestUpdate(ctx, num, sizeof(num));
- _gsskrb5_encode_om_uint32 (b->acceptor_address.length, num);
+ _gss_mg_encode_le_uint32 (b->acceptor_address.length, num);
EVP_DigestUpdate(ctx, num, sizeof(num));
if (b->acceptor_address.length)
EVP_DigestUpdate(ctx,
b->acceptor_address.value,
b->acceptor_address.length);
- _gsskrb5_encode_om_uint32 (b->application_data.length, num);
+ _gss_mg_encode_le_uint32 (b->application_data.length, num);
EVP_DigestUpdate(ctx, num, sizeof(num));
if (b->application_data.length)
EVP_DigestUpdate(ctx,
@@ -144,7 +102,7 @@ _gsskrb5_create_8003_checksum (
}
p = result->checksum.data;
- _gsskrb5_encode_om_uint32 (16, p);
+ _gss_mg_encode_le_uint32 (16, p);
p += 4;
if (input_chan_bindings == GSS_C_NO_CHANNEL_BINDINGS) {
memset (p, 0, 16);
@@ -152,7 +110,7 @@ _gsskrb5_create_8003_checksum (
hash_input_chan_bindings (input_chan_bindings, p);
}
p += 16;
- _gsskrb5_encode_om_uint32 (flags, p);
+ _gss_mg_encode_le_uint32 (flags, p);
p += 4;
if (fwd_data->length > 0 && (flags & GSS_C_DELEG_FLAG)) {
@@ -244,7 +202,7 @@ _gsskrb5_verify_8003_checksum(
}
p = cksum->checksum.data;
- _gsskrb5_decode_om_uint32(p, &length);
+ _gss_mg_decode_le_uint32(p, &length);
if(length != sizeof(hash)) {
*minor_status = 0;
return GSS_S_BAD_BINDINGS;
@@ -273,7 +231,7 @@ _gsskrb5_verify_8003_checksum(
p += sizeof(hash);
- _gsskrb5_decode_om_uint32(p, flags);
+ _gss_mg_decode_le_uint32(p, flags);
p += 4;
if (cksum->checksum.length > 24 && (*flags & GSS_C_DELEG_FLAG)) {
diff --git a/third_party/heimdal/lib/gssapi/krb5/arcfour.c b/third_party/heimdal/lib/gssapi/krb5/arcfour.c
index 5c754bc6d52..787a8d3d2d6 100644
--- a/third_party/heimdal/lib/gssapi/krb5/arcfour.c
+++ b/third_party/heimdal/lib/gssapi/krb5/arcfour.c
@@ -293,7 +293,7 @@ _gssapi_get_mic_arcfour(OM_uint32 * minor_status,
context_handle->auth_context,
&seq_number);
p = p0 + 8; /* SND_SEQ */
- _gsskrb5_encode_be_om_uint32(seq_number, p);
+ _gss_mg_encode_be_uint32(seq_number, p);
krb5_auth_con_setlocalseqnumber (context,
context_handle->auth_context,
@@ -385,7 +385,7 @@ _gssapi_verify_mic_arcfour(OM_uint32 * minor_status,
memset(k6_data, 0, sizeof(k6_data));
}
- _gsskrb5_decode_be_om_uint32(SND_SEQ, &seq_number);
+ _gss_mg_decode_be_uint32(SND_SEQ, &seq_number);
if (context_handle->more_flags & LOCAL)
cmp = (ct_memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4) != 0);
@@ -473,7 +473,7 @@ _gssapi_wrap_arcfour(OM_uint32 * minor_status,
context_handle->auth_context,
&seq_number);
- _gsskrb5_encode_be_om_uint32(seq_number, p0 + 8);
+ _gss_mg_encode_be_uint32(seq_number, p0 + 8);
krb5_auth_con_setlocalseqnumber (context,
context_handle->auth_context,
@@ -656,7 +656,7 @@ OM_uint32 _gssapi_unwrap_arcfour(OM_uint32 *minor_status,
memset_s(k6_data, sizeof(k6_data), 0, sizeof(k6_data));
}
- _gsskrb5_decode_be_om_uint32(SND_SEQ, &seq_number);
+ _gss_mg_decode_be_uint32(SND_SEQ, &seq_number);
if (context_handle->more_flags & LOCAL)
cmp = (ct_memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4) != 0);
@@ -1042,7 +1042,7 @@ _gssapi_wrap_iov_arcfour(OM_uint32 *minor_status,
krb5_auth_con_getlocalseqnumber(context,
ctx->auth_context,
&seq_number);
- _gsskrb5_encode_be_om_uint32(seq_number, p0 + 8);
+ _gss_mg_encode_be_uint32(seq_number, p0 + 8);
krb5_auth_con_setlocalseqnumber(context,
ctx->auth_context,
@@ -1279,7 +1279,7 @@ _gssapi_unwrap_iov_arcfour(OM_uint32 *minor_status,
memset(k6_data, 0, sizeof(k6_data));
}
- _gsskrb5_decode_be_om_uint32(snd_seq, &seq_number);
+ _gss_mg_decode_be_uint32(snd_seq, &seq_number);
if (ctx->more_flags & LOCAL) {
cmp = (ct_memcmp(&snd_seq[4], "\xff\xff\xff\xff", 4) != 0);
diff --git a/third_party/heimdal/lib/gssapi/krb5/cfx.c b/third_party/heimdal/lib/gssapi/krb5/cfx.c
index 8d806f9fbf1..cb9ea773bbb 100644
--- a/third_party/heimdal/lib/gssapi/krb5/cfx.c
+++ b/third_party/heimdal/lib/gssapi/krb5/cfx.c
@@ -276,11 +276,7 @@ _gk_verify_buffers(OM_uint32 *minor_status,
/*
* In DCE style mode we reject having a padding or trailer buffer
*/
- if (padding) {
- *minor_status = EINVAL;
- return GSS_S_FAILURE;
- }
- if (trailer) {
+ if (padding || trailer) {
*minor_status = EINVAL;
return GSS_S_FAILURE;
}
@@ -505,8 +501,8 @@ _gssapi_wrap_cfx_iov(OM_uint32 *minor_status,
krb5_auth_con_getlocalseqnumber(context,
ctx->auth_context,
&seq_number);
- _gsskrb5_encode_be_om_uint32(0, &token->SND_SEQ[0]);
- _gsskrb5_encode_be_om_uint32(seq_number, &token->SND_SEQ[4]);
+ _gss_mg_encode_be_uint32(0, &token->SND_SEQ[0]);
+ _gss_mg_encode_be_uint32(seq_number, &token->SND_SEQ[4]);
krb5_auth_con_setlocalseqnumber(context,
ctx->auth_context,
++seq_number);
@@ -817,8 +813,8 @@ _gssapi_unwrap_cfx_iov(OM_uint32 *minor_status,
/*
* Check sequence number
*/
- _gsskrb5_decode_be_om_uint32(&token->SND_SEQ[0], &seq_number_hi);
- _gsskrb5_decode_be_om_uint32(&token->SND_SEQ[4], &seq_number_lo);
+ _gss_mg_decode_be_uint32(&token->SND_SEQ[0], &seq_number_hi);
+ _gss_mg_decode_be_uint32(&token->SND_SEQ[4], &seq_number_lo);
if (seq_number_hi) {
/* no support for 64-bit sequence numbers */
*minor_status = ERANGE;
@@ -1271,8 +1267,8 @@ OM_uint32 _gssapi_wrap_cfx(OM_uint32 *minor_status,
krb5_auth_con_getlocalseqnumber(context,
ctx->auth_context,
&seq_number);
- _gsskrb5_encode_be_om_uint32(0, &token->SND_SEQ[0]);
- _gsskrb5_encode_be_om_uint32(seq_number, &token->SND_SEQ[4]);
+ _gss_mg_encode_be_uint32(0, &token->SND_SEQ[0]);
+ _gss_mg_encode_be_uint32(seq_number, &token->SND_SEQ[4]);
krb5_auth_con_setlocalseqnumber(context,
ctx->auth_context,
++seq_number);
@@ -1458,8 +1454,8 @@ OM_uint32 _gssapi_unwrap_cfx(OM_uint32 *minor_status,
/*
* Check sequence number
*/
- _gsskrb5_decode_be_om_uint32(&token->SND_SEQ[0], &seq_number_hi);
- _gsskrb5_decode_be_om_uint32(&token->SND_SEQ[4], &seq_number_lo);
+ _gss_mg_decode_be_uint32(&token->SND_SEQ[0], &seq_number_hi);
+ _gss_mg_decode_be_uint32(&token->SND_SEQ[4], &seq_number_lo);
if (seq_number_hi) {
/* no support for 64-bit sequence numbers */
*minor_status = ERANGE;
@@ -1623,7 +1619,10 @@ OM_uint32 _gssapi_mic_cfx(OM_uint32 *minor_status,
return GSS_S_FAILURE;
}
- memcpy(buf, message_buffer->value, message_buffer->length);
+ if (message_buffer->length)
+ memcpy(buf, message_buffer->value, message_buffer->length);
+ else
+ memset(buf, 0, len);
token = (gss_cfx_mic_token)(buf + message_buffer->length);
token->TOK_ID[0] = 0x04;
@@ -1639,8 +1638,8 @@ OM_uint32 _gssapi_mic_cfx(OM_uint32 *minor_status,
krb5_auth_con_getlocalseqnumber(context,
ctx->auth_context,
&seq_number);
- _gsskrb5_encode_be_om_uint32(0, &token->SND_SEQ[0]);
- _gsskrb5_encode_be_om_uint32(seq_number, &token->SND_SEQ[4]);
+ _gss_mg_encode_be_uint32(0, &token->SND_SEQ[0]);
+ _gss_mg_encode_be_uint32(seq_number, &token->SND_SEQ[4]);
krb5_auth_con_setlocalseqnumber(context,
ctx->auth_context,
++seq_number);
@@ -1733,8 +1732,8 @@ OM_uint32 _gssapi_verify_mic_cfx(OM_uint32 *minor_status,
/*
* Check sequence number
*/
- _gsskrb5_decode_be_om_uint32(&token->SND_SEQ[0], &seq_number_hi);
- _gsskrb5_decode_be_om_uint32(&token->SND_SEQ[4], &seq_number_lo);
+ _gss_mg_decode_be_uint32(&token->SND_SEQ[0], &seq_number_hi);
+ _gss_mg_decode_be_uint32(&token->SND_SEQ[4], &seq_number_lo);
if (seq_number_hi) {
*minor_status = ERANGE;
return GSS_S_UNSEQ_TOKEN;
@@ -1773,7 +1772,8 @@ OM_uint32 _gssapi_verify_mic_cfx(OM_uint32 *minor_status,
*minor_status = ENOMEM;
return GSS_S_FAILURE;
}
- memcpy(buf, message_buffer->value, message_buffer->length);
+ if (message_buffer->length)
+ memcpy(buf, message_buffer->value, message_buffer->length);
memcpy(buf + message_buffer->length, token, sizeof(*token));
ret = krb5_verify_checksum(context, ctx->crypto,
diff --git a/third_party/heimdal/lib/gssapi/krb5/creds.c b/third_party/heimdal/lib/gssapi/krb5/creds.c
index efb0a23ad92..036d9fa072a 100644
--- a/third_party/heimdal/lib/gssapi/krb5/creds.c
+++ b/third_party/heimdal/lib/gssapi/krb5/creds.c
@@ -263,10 +263,15 @@ _gsskrb5_import_cred(OM_uint32 * minor_status,
*minor_status = ENOMEM;
return GSS_S_FAILURE;
}
+ *minor_status = krb5_cc_get_principal(context, id, &handle->principal);
+ if (*minor_status) {
+ free(handle);
+ krb5_cc_close(context, id);
+ return GSS_S_FAILURE;
+ }
handle->usage = GSS_C_INITIATE;
handle->destination_realm = NULL;
- krb5_cc_get_principal(context, id, &handle->principal);
handle->ccache = id;
handle->cred_flags = flags;
diff --git a/third_party/heimdal/lib/gssapi/krb5/duplicate_cred.c b/third_party/heimdal/lib/gssapi/krb5/duplicate_cred.c
index f5b34c5144b..a44ec3b239c 100644
--- a/third_party/heimdal/lib/gssapi/krb5/duplicate_cred.c
+++ b/third_party/heimdal/lib/gssapi/krb5/duplicate_cred.c
@@ -76,12 +76,6 @@ OM_uint32 GSSAPI_CALLCONV _gsskrb5_duplicate_cred (
HEIMDAL_MUTEX_lock(&cred->cred_id_mutex);
dup->destination_realm = NULL;
- if (cred->destination_realm &&
- (dup->destination_realm = strdup(cred->destination_realm)) == NULL) {
- *minor_status = krb5_enomem(context);
- free(dup);
- return (GSS_S_FAILURE);
- }
dup->usage = cred->usage;
dup->endtime = cred->endtime;
dup->principal = NULL;
@@ -92,6 +86,11 @@ OM_uint32 GSSAPI_CALLCONV _gsskrb5_duplicate_cred (
major = GSS_S_FAILURE;
HEIMDAL_MUTEX_init(&dup->cred_id_mutex);
+ if (cred->destination_realm &&
+ (dup->destination_realm = strdup(cred->destination_realm)) == NULL) {
+ *minor_status = krb5_enomem(context);
+ goto fail;
+ }
*minor_status = krb5_copy_principal(context, cred->principal,
&dup->principal);
if (*minor_status)
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 a705d03a875..7749fc6cadd 100644
--- a/third_party/heimdal/lib/gssapi/krb5/init_sec_context.c
+++ b/third_party/heimdal/lib/gssapi/krb5/init_sec_context.c
@@ -742,6 +742,9 @@ repl_mutual
output_token->length = 0;
output_token->value = NULL;
+ if (input_token == GSS_C_NO_BUFFER)
+ return GSS_S_FAILURE;
+
if (actual_mech_type)
*actual_mech_type = GSS_KRB5_MECHANISM;
@@ -799,10 +802,10 @@ repl_mutual
*minor_status = 0;
if (time_rec)
- _gsskrb5_lifetime_left(minor_status,
- context,
- ctx->endtime,
- time_rec);
+ (void) _gsskrb5_lifetime_left(minor_status,
+ context,
+ ctx->endtime,
+ time_rec);
if (ret_flags)
*ret_flags = ctx->flags;
diff --git a/third_party/heimdal/lib/gssapi/krb5/inquire_sec_context_by_oid.c b/third_party/heimdal/lib/gssapi/krb5/inquire_sec_context_by_oid.c
index f57277422a2..49d86d11cd5 100644
--- a/third_party/heimdal/lib/gssapi/krb5/inquire_sec_context_by_oid.c
+++ b/third_party/heimdal/lib/gssapi/krb5/inquire_sec_context_by_oid.c
@@ -90,7 +90,7 @@ static OM_uint32 inquire_sec_context_tkt_flags
tkt_flags = TicketFlags2int(context_handle->ticket->ticket.flags);
HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
- _gsskrb5_encode_om_uint32(tkt_flags, buf);
+ _gss_mg_encode_le_uint32(tkt_flags, buf);
value.length = sizeof(buf);
value.value = buf;
@@ -430,8 +430,8 @@ get_authtime(OM_uint32 *minor_status,
{
gss_buffer_desc value;
- unsigned char buf[4];
- OM_uint32 authtime;
+ unsigned char buf[SIZEOF_TIME_T];
+ time_t authtime;
HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
if (ctx->ticket == NULL) {
@@ -445,7 +445,13 @@ get_authtime(OM_uint32 *minor_status,
HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
- _gsskrb5_encode_om_uint32(authtime, buf);
+#if SIZEOF_TIME_T == 8
+ _gss_mg_encode_le_uint64(authtime, buf);
+#elif SIZEOF_TIME_T == 4
+ _gss_mg_encode_le_uint32(authtime, buf);
+#else
+#error set SIZEOF_TIME_T for your platform
+#endif
value.length = sizeof(buf);
value.value = buf;
diff --git a/third_party/heimdal/lib/gssapi/krb5/prf.c b/third_party/heimdal/lib/gssapi/krb5/prf.c
index 671ab2c6d98..941d21ac600 100644
--- a/third_party/heimdal/lib/gssapi/krb5/prf.c
+++ b/third_party/heimdal/lib/gssapi/krb5/prf.c
@@ -119,7 +119,7 @@ _gsskrb5_pseudo_random(OM_uint32 *minor_status,
while(dol > 0) {
size_t tsize;
- _gsskrb5_encode_be_om_uint32(num, input.data);
+ _gss_mg_encode_be_uint32(num, input.data);
ret = krb5_crypto_prf(context, crypto, &input, &output);
if (ret) {
diff --git a/third_party/heimdal/lib/gssapi/krb5/unwrap.c b/third_party/heimdal/lib/gssapi/krb5/unwrap.c
index 64613698fa4..1eea68eace2 100644
--- a/third_party/heimdal/lib/gssapi/krb5/unwrap.c
+++ b/third_party/heimdal/lib/gssapi/krb5/unwrap.c
@@ -163,7 +163,7 @@ unwrap_des
memset (&schedule, 0, sizeof(schedule));
seq = p;
- _gsskrb5_decode_om_uint32(seq, &seq_number);
+ _gss_mg_decode_be_uint32(seq, &seq_number);
if (context_handle->more_flags & LOCAL)
cmp = ct_memcmp(&seq[4], "\xff\xff\xff\xff", 4);
@@ -335,7 +335,7 @@ unwrap_des3
}
seq = seq_data.data;
- _gsskrb5_decode_om_uint32(seq, &seq_number);
+ _gss_mg_decode_be_uint32(seq, &seq_number);
if (context_handle->more_flags & LOCAL)
cmp = ct_memcmp(&seq[4], "\xff\xff\xff\xff", 4);
diff --git a/third_party/heimdal/lib/gssapi/krb5/verify_mic.c b/third_party/heimdal/lib/gssapi/krb5/verify_mic.c
index 7070f3de46b..4a776c8099b 100644
--- a/third_party/heimdal/lib/gssapi/krb5/verify_mic.c
+++ b/third_party/heimdal/lib/gssapi/krb5/verify_mic.c
@@ -109,7 +109,7 @@ verify_mic_des
memset_s(&schedule, sizeof(schedule), 0, sizeof(schedule));
seq = p;
- _gsskrb5_decode_om_uint32(seq, &seq_number);
+ _gss_mg_decode_be_uint32(seq, &seq_number);
if (context_handle->more_flags & LOCAL)
cmp = ct_memcmp(&seq[4], "\xff\xff\xff\xff", 4);
@@ -211,7 +211,7 @@ retry:
HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
seq = seq_data.data;
- _gsskrb5_decode_om_uint32(seq, &seq_number);
+ _gss_mg_decode_be_uint32(seq, &seq_number);
if (context_handle->more_flags & LOCAL)
cmp = ct_memcmp(&seq[4], "\xff\xff\xff\xff", 4);
diff --git a/third_party/heimdal/lib/gssapi/mech/gss_accept_sec_context.c b/third_party/heimdal/lib/gssapi/mech/gss_accept_sec_context.c
index 1cb0b367aad..04d7ab538ac 100644
--- a/third_party/heimdal/lib/gssapi/mech/gss_accept_sec_context.c
+++ b/third_party/heimdal/lib/gssapi/mech/gss_accept_sec_context.c
@@ -172,7 +172,7 @@ choose_mech(struct _gss_context *ctx)
if (len == 0) {
/*
* There is the a wierd mode of SPNEGO (in CIFS and
- * SASL GSS-SPENGO where the first token is zero
+ * SASL GSS-SPENGO) where the first token is zero
* length and the acceptor returns a mech_list, lets
* hope that is what is happening now.
*
@@ -190,13 +190,17 @@ choose_mech(struct _gss_context *ctx)
* Decode the OID for the mechanism. Simplify life by
* assuming that the OID length is less than 128 bytes.
*/
- if (len < 2 || *p != 0x06)
- goto bail;
- if ((p[1] & 0x80) || p[1] > (len - 2))
- goto bail;
+ if (len < 2 || *p != 0x06) {
+ _gss_mg_log(10, "initial context token appears to be for non-standard mechanism");
+ return GSS_S_COMPLETE;
+ }
+ len -= 2;
+ if ((p[1] & 0x80) || p[1] > len) {
+ _gss_mg_log(10, "mechanism oid in initial context token is too long");
+ return GSS_S_COMPLETE;
+ }
mech.length = p[1];
p += 2;
- len -= 2;
mech.elements = p;
mech_oid = _gss_mg_support_mechanism(&mech);
@@ -209,19 +213,13 @@ gss_get_mechanism:
* and we have to try all mechs (that we have a cred element
* for, if we have a cred).
*/
- if (mech_oid != GSS_C_NO_OID) {
- log_oid("mech oid", mech_oid);
- ctx->gc_mech = __gss_get_mechanism(mech_oid);
- if (!ctx->gc_mech) {
- _gss_mg_log(10, "mechanism client used is unknown");
- return (GSS_S_BAD_MECH);
- }
- _gss_mg_log(10, "using mech \"%s\"", ctx->gc_mech->gm_name);
- return GSS_S_COMPLETE;
+ log_oid("mech oid", mech_oid);
+ ctx->gc_mech = __gss_get_mechanism(mech_oid);
+ if (!ctx->gc_mech) {
+ _gss_mg_log(10, "mechanism client used is unknown");
+ return (GSS_S_BAD_MECH);
}
-
-bail:
- _gss_mg_log(10, "no mech oid found");
+ _gss_mg_log(10, "using mech \"%s\"", ctx->gc_mech->gm_name);
return GSS_S_COMPLETE;
}
diff --git a/third_party/heimdal/lib/gssapi/mech/gss_krb5.c b/third_party/heimdal/lib/gssapi/mech/gss_krb5.c
index 78c305689f0..21bb2bffb00 100644
--- a/third_party/heimdal/lib/gssapi/mech/gss_krb5.c
+++ b/third_party/heimdal/lib/gssapi/mech/gss_krb5.c
@@ -564,17 +564,19 @@ gsskrb5_extract_authtime_from_sec_context(OM_uint32 *minor_status,
return GSS_S_FAILURE;
}
- if (data_set->elements[0].length != 4) {
+ if (data_set->elements[0].length != SIZEOF_TIME_T) {
gss_release_buffer_set(minor_status, &data_set);
*minor_status = EINVAL;
return GSS_S_FAILURE;
}
- {
- unsigned char *buf = data_set->elements[0].value;
- *authtime = ((unsigned long)buf[3] <<24) | (buf[2] << 16) |
- (buf[1] << 8) | (buf[0] << 0);
- }
+#if SIZEOF_TIME_T == 8
+ _gss_mg_decode_le_uint64(data_set->elements[0].value, (uint64_t *)authtime);
+#elif SIZEOF_TIME_T == 4
+ _gss_mg_decode_le_uint32(data_set->elements[0].value, (uint32_t *)authtime);
+#else
+#error set SIZEOF_TIME_T for your platform
+#endif
gss_release_buffer_set(minor_status, &data_set);
@@ -844,10 +846,7 @@ gss_krb5_get_tkt_flags(OM_uint32 *minor_status,
return GSS_S_FAILURE;
}
- {
- const u_char *p = data_set->elements[0].value;
- *tkt_flags = (p[0] << 0) | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
- }
+ _gss_mg_decode_le_uint32(data_set->elements[0].value, tkt_flags);
gss_release_buffer_set(minor_status, &data_set);
return GSS_S_COMPLETE;
diff --git a/third_party/heimdal/lib/gssapi/mech/gss_mo.c b/third_party/heimdal/lib/gssapi/mech/gss_mo.c
index b6ae282b13e..08cb43d37d3 100644
--- a/third_party/heimdal/lib/gssapi/mech/gss_mo.c
+++ b/third_party/heimdal/lib/gssapi/mech/gss_mo.c
@@ -453,7 +453,7 @@ gss_indicate_mechs_by_attrs(OM_uint32 * minor_status,
struct _gss_mech_switch *ms;
gss_OID_set mech_attrs = GSS_C_NO_OID_SET;
gss_OID_set known_mech_attrs = GSS_C_NO_OID_SET;
- OM_uint32 major;
+ OM_uint32 major, tmp;
major = gss_create_empty_oid_set(minor_status, mechs);
if (GSS_ERROR(major))
@@ -464,7 +464,6 @@ gss_indicate_mechs_by_attrs(OM_uint32 * minor_status,
HEIM_TAILQ_FOREACH(ms, &_gss_mechs, gm_link) {
gssapi_mech_interface mi = &ms->gm_mech;
struct gss_mech_compat_desc_struct *gmc = mi->gm_compat;
- OM_uint32 tmp;
if (gmc && gmc->gmc_inquire_attrs_for_mech) {
major = gmc->gmc_inquire_attrs_for_mech(minor_status,
@@ -493,6 +492,9 @@ gss_indicate_mechs_by_attrs(OM_uint32 * minor_status,
break;
}
+ if (major)
+ gss_release_oid_set(&tmp, mechs);
+
return major;
}
diff --git a/third_party/heimdal/lib/gssapi/mech/gss_utils.c b/third_party/heimdal/lib/gssapi/mech/gss_utils.c
index bb7e619397f..62fa262af36 100644
--- a/third_party/heimdal/lib/gssapi/mech/gss_utils.c
+++ b/third_party/heimdal/lib/gssapi/mech/gss_utils.c
@@ -178,6 +178,60 @@ _gss_secure_release_buffer_set(OM_uint32 *minor_status,
}
void
+_gss_mg_encode_le_uint64(uint64_t n, uint8_t *p)
+{
+ p[0] = (n >> 0 ) & 0xFF;
+ p[1] = (n >> 8 ) & 0xFF;
+ p[2] = (n >> 16) & 0xFF;
+ p[3] = (n >> 24) & 0xFF;
+ p[4] = (n >> 32) & 0xFF;
+ p[5] = (n >> 40) & 0xFF;
+ p[6] = (n >> 48) & 0xFF;
+ p[7] = (n >> 56) & 0xFF;
+}
+
+void
+_gss_mg_decode_le_uint64(const void *ptr, uint64_t *n)
+{
+ const uint8_t *p = ptr;
+ *n = ((uint64_t)p[0] << 0)
+ | ((uint64_t)p[1] << 8)
+ | ((uint64_t)p[2] << 16)
+ | ((uint64_t)p[3] << 24)
+ | ((uint64_t)p[4] << 32)
+ | ((uint64_t)p[5] << 40)
+ | ((uint64_t)p[6] << 48)
+ | ((uint64_t)p[7] << 56);
+}
+
+void
+_gss_mg_encode_be_uint64(uint64_t n, uint8_t *p)
+{
+ p[0] = (n >> 56) & 0xFF;
+ p[1] = (n >> 48) & 0xFF;
+ p[2] = (n >> 40) & 0xFF;
+ p[3] = (n >> 32) & 0xFF;
+ p[4] = (n >> 24) & 0xFF;
+ p[5] = (n >> 16) & 0xFF;
+ p[6] = (n >> 8 ) & 0xFF;
+ p[7] = (n >> 0 ) & 0xFF;
+}
+
+void
+_gss_mg_decode_be_uint64(const void *ptr, uint64_t *n)
+{
+ const uint8_t *p = ptr;
+ *n = ((uint64_t)p[0] << 56)
+ | ((uint64_t)p[1] << 48)
+ | ((uint64_t)p[2] << 40)
+ | ((uint64_t)p[3] << 32)
+ | ((uint64_t)p[4] << 24)
+ | ((uint64_t)p[5] << 16)
+ | ((uint64_t)p[6] << 8)
+ | ((uint64_t)p[7] << 0);
+}
+
+void
_gss_mg_encode_le_uint32(uint32_t n, uint8_t *p)
{
p[0] = (n >> 0 ) & 0xFF;
@@ -190,7 +244,10 @@ void
_gss_mg_decode_le_uint32(const void *ptr, uint32_t *n)
{
const uint8_t *p = ptr;
- *n = (p[0] << 0) | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
+ *n = ((uint32_t)p[0] << 0)
+ | ((uint32_t)p[1] << 8)
+ | ((uint32_t)p[2] << 16)
+ | ((uint32_t)p[3] << 24);
}
void
diff --git a/third_party/heimdal/lib/gssapi/mech/mech_locl.h b/third_party/heimdal/lib/gssapi/mech/mech_locl.h
index d451b87c4a7..f0cfcb5e638 100644
--- a/third_party/heimdal/lib/gssapi/mech/mech_locl.h
+++ b/third_party/heimdal/lib/gssapi/mech/mech_locl.h
@@ -42,6 +42,7 @@
#include <ctype.h>
#include <heimbase.h>
+#include "heimbase-atomics.h"
#include <gssapi_asn1.h>
#include <der.h>
diff --git a/third_party/heimdal/lib/gssapi/mech/utils.h b/third_party/heimdal/lib/gssapi/mech/utils.h
index 208a59cc85c..717ca49166a 100644
--- a/third_party/heimdal/lib/gssapi/mech/utils.h
+++ b/third_party/heimdal/lib/gssapi/mech/utils.h
@@ -36,6 +36,11 @@ OM_uint32 _gss_secure_release_buffer(OM_uint32 *minor_status,
OM_uint32 _gss_secure_release_buffer_set(OM_uint32 *minor_status,
gss_buffer_set_t *buffer_set);
+void _gss_mg_encode_le_uint64(uint64_t n, uint8_t *p);
+void _gss_mg_decode_le_uint64(const void *ptr, uint64_t *n);
+void _gss_mg_encode_be_uint64(uint64_t n, uint8_t *p);
+void _gss_mg_decode_be_uint64(const void *ptr, uint64_t *n);
+
void _gss_mg_encode_le_uint32(uint32_t n, uint8_t *p);
void _gss_mg_decode_le_uint32(const void *ptr, uint32_t *n);
void _gss_mg_encode_be_uint32(uint32_t n, uint8_t *p);
diff --git a/third_party/heimdal/lib/gssapi/ntlm/crypto.c b/third_party/heimdal/lib/gssapi/ntlm/crypto.c
index d1a115ff8e3..d2cfddf6d54 100644
--- a/third_party/heimdal/lib/gssapi/ntlm/crypto.c
+++ b/third_party/heimdal/lib/gssapi/ntlm/crypto.c
@@ -48,27 +48,6 @@ struct _krb5_key_type;
*
*/
-static void
-encode_le_uint32(uint32_t n, unsigned char *p)
-{
- p[0] = (n >> 0) & 0xFF;
- p[1] = (n >> 8) & 0xFF;
- p[2] = (n >> 16) & 0xFF;
- p[3] = (n >> 24) & 0xFF;
-}
-
-
-static void
-decode_le_uint32(const void *ptr, uint32_t *n)
-{
- const unsigned char *p = ptr;
- *n = (p[0] << 0) | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
-}
-
-/*
- *
- */
-
const char a2i_signmagic[] =
"session key to server-to-client signing key magic constant";
const char a2i_sealmagic[] =
@@ -168,11 +147,11 @@ v1_sign_message(gss_buffer_t in,
_krb5_crc_init_table();
crc = _krb5_crc_update(in->value, in->length, 0);
- encode_le_uint32(0, &sigature[0]);
- encode_le_uint32(crc, &sigature[4]);
- encode_le_uint32(seq, &sigature[8]);
+ _gss_mg_encode_le_uint32(0, &sigature[0]);
+ _gss_mg_encode_le_uint32(crc, &sigature[4]);
+ _gss_mg_encode_le_uint32(seq, &sigature[8]);
- encode_le_uint32(1, out); /* version */
+ _gss_mg_encode_le_uint32(1, out); /* version */
RC4(signkey, sizeof(sigature), sigature, out + 4);
if (RAND_bytes(out + 4, 4) != 1)
@@ -199,13 +178,13 @@ v2_sign_message(gss_buffer_t in,
return GSS_S_FAILURE;
}
- encode_le_uint32(seq, hmac);
+ _gss_mg_encode_le_uint32(seq, hmac);
HMAC_Update(&c, hmac, 4);
HMAC_Update(&c, in->value, in->length);
HMAC_Final(&c, hmac, &hmaclen);
HMAC_CTX_cleanup(&c);
- encode_le_uint32(1, &out[0]);
+ _gss_mg_encode_le_uint32(1, &out[0]);
if (sealkey)
RC4(sealkey, 8, hmac, &out[4]);
else
@@ -365,10 +344,10 @@ _gss_ntlm_get_mic
sigature = message_token->value;
- encode_le_uint32(1, &sigature[0]); /* version */
- encode_le_uint32(0, &sigature[4]);
- encode_le_uint32(0, &sigature[8]);
- encode_le_uint32(0, &sigature[12]);
+ _gss_mg_encode_le_uint32(1, &sigature[0]); /* version */
+ _gss_mg_encode_le_uint32(0, &sigature[4]);
+ _gss_mg_encode_le_uint32(0, &sigature[8]);
+ _gss_mg_encode_le_uint32(0, &sigature[12]);
return GSS_S_COMPLETE;
}
@@ -422,7 +401,7 @@ _gss_ntlm_verify_mic
if ((ctx->status & STATUS_SESSIONKEY) == 0)
return GSS_S_UNAVAILABLE;
- decode_le_uint32(token_buffer->value, &num);
+ _gss_mg_decode_le_uint32(token_buffer->value, &num);
if (num != 1)
return GSS_S_BAD_MIC;
@@ -433,10 +412,10 @@ _gss_ntlm_verify_mic
crc = _krb5_crc_update(message_buffer->value,
message_buffer->length, 0);
/* skip first 4 bytes in the encrypted checksum */
- decode_le_uint32(&sigature[4], &num);
+ _gss_mg_decode_le_uint32(&sigature[4], &num);
if (num != crc)
return GSS_S_BAD_MIC;
- decode_le_uint32(&sigature[8], &num);
+ _gss_mg_decode_le_uint32(&sigature[8], &num);
if (ctx->u.v1.crypto_recv.seq != num)
return GSS_S_BAD_MIC;
ctx->u.v1.crypto_recv.seq++;
@@ -448,13 +427,13 @@ _gss_ntlm_verify_mic
p = (unsigned char*)(token_buffer->value);
- decode_le_uint32(&p[0], &num); /* version */
+ _gss_mg_decode_le_uint32(&p[0], &num); /* version */
if (num != 1) return GSS_S_BAD_MIC;
- decode_le_uint32(&p[4], &num);
+ _gss_mg_decode_le_uint32(&p[4], &num);
if (num != 0) return GSS_S_BAD_MIC;
- decode_le_uint32(&p[8], &num);
+ _gss_mg_decode_le_uint32(&p[8], &num);
if (num != 0) return GSS_S_BAD_MIC;
- decode_le_uint32(&p[12], &num);
+ _gss_mg_decode_le_uint32(&p[12], &num);
if (num != 0) return GSS_S_BAD_MIC;
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 1bce00fc5d6..10aa2b9803a 100644
--- a/third_party/heimdal/lib/gssapi/ntlm/kdc.c
+++ b/third_party/heimdal/lib/gssapi/ntlm/kdc.c
@@ -82,7 +82,7 @@ get_ccache(krb5_context context, int *destroy, krb5_ccache *id)
ret = krb5_cc_cache_match(context, principal, id);
if (ret == 0)
- return 0;
+ goto out;
/* did not find in default credcache, lets try default keytab */
ret = krb5_kt_default(context, &kt);
diff --git a/third_party/heimdal/lib/gssapi/ntlm/ntlm.h b/third_party/heimdal/lib/gssapi/ntlm/ntlm.h
index a0ad8158418..7b16aa21d91 100644
--- a/third_party/heimdal/lib/gssapi/ntlm/ntlm.h
+++ b/third_party/heimdal/lib/gssapi/ntlm/ntlm.h
@@ -50,6 +50,7 @@
#include <gssapi_ntlm.h>
#include <gssapi_mech.h>
#include <gssapi_oid.h>
+#include <mech/utils.h>
#include <krb5.h>
#include <kcm.h>
diff --git a/third_party/heimdal/lib/gssapi/sanon/export_cred.c b/third_party/heimdal/lib/gssapi/sanon/export_cred.c
index 06c2458f722..359eefd372f 100644
--- a/third_party/heimdal/lib/gssapi/sanon/export_cred.c
+++ b/third_party/heimdal/lib/gssapi/sanon/export_cred.c
@@ -36,5 +36,43 @@ _gss_sanon_export_cred(OM_uint32 *minor,
gss_cred_id_t input_cred,
gss_buffer_t token)
{
- return _gss_sanon_export_name(minor, (gss_name_t)input_cred, token);
+ gss_buffer_desc buf;
+ krb5_storage *sp;
+ krb5_data data_out, data;
+ OM_uint32 major, junk;
+
+ token->value = NULL;
+ token->length = 0;
+
+ major = _gss_sanon_export_name(minor, (gss_name_t)input_cred, &buf);
+ if (major)
+ return major;
+
+ sp = krb5_storage_emem();
+ if (sp == NULL) {
+ gss_release_buffer(&junk, &buf);
+ *minor = ENOMEM;
+ return GSS_S_FAILURE;
+ }
+
+ major = _gss_mg_store_oid(minor, sp, GSS_SANON_X25519_MECHANISM);
+ if (major) {
+ gss_release_buffer(&junk, &buf);
+ krb5_storage_free(sp);
+ return major;
+ }
+ data_out.length = 0;
+ data_out.data = NULL;
+ data.length = buf.length;
+ data.data = buf.value;
+ *minor = krb5_store_data(sp, data);
+ if (*minor == 0)
+ *minor = krb5_storage_to_data(sp, &data_out);
+ if (*minor == 0) {
+ token->value = data_out.data;
+ token->length = data_out.length;
+ }
+ gss_release_buffer(&junk, &buf);
+ krb5_storage_free(sp);
+ return major;
}
diff --git a/third_party/heimdal/lib/gssapi/spnego/context_storage.c b/third_party/heimdal/lib/gssapi/spnego/context_storage.c
index 13e20d723e6..3924bd38395 100644
--- a/third_party/heimdal/lib/gssapi/spnego/context_storage.c
+++ b/third_party/heimdal/lib/gssapi/spnego/context_storage.c
@@ -55,6 +55,10 @@ ret_negoex_auth_mech(krb5_storage *sp, struct negoex_auth_mech **mechp);
static krb5_error_code
store_negoex_auth_mech(krb5_storage *sp, struct negoex_auth_mech *mech);
+#ifdef sc_flags
+#undef sc_flags
+#endif
+
static uint16_t
spnego_flags_to_int(struct spnego_flags flags);
static struct spnego_flags
@@ -207,7 +211,9 @@ ret_spnego_context(krb5_storage *sp, gssspnego_ctx *ctxp)
struct negoex_auth_mech *mech;
CHECK(ret, ret_negoex_auth_mech(sp, &mech));
- HEIM_TAILQ_INSERT_TAIL(&ctx->negoex_mechs, mech, links);
+ /* `mech' will not be NULL here, but quiet scan-build */
+ if (mech)
+ HEIM_TAILQ_INSERT_TAIL(&ctx->negoex_mechs, mech, links);
}
}
@@ -374,15 +380,15 @@ ret_negoex_auth_mech(krb5_storage *sp, struct negoex_auth_mech **mechp)
if (snc_flags & SNC_METADATA)
CHECK(major, _gss_mg_ret_buffer(&minor, sp, &mech->metadata));
- *mechp = mech;
-
fail:
if (ret == 0 && GSS_ERROR(major))
ret = minor ? minor : KRB5_BAD_MSIZE;
if (ret)
_gss_negoex_release_auth_mech(context, mech);
- gss_release_buffer(&minor, &buf);
+ else
+ *mechp = mech;
+ gss_release_buffer(&minor, &buf);
return ret;
}
diff --git a/third_party/heimdal/lib/gssapi/spnego/negoex_util.c b/third_party/heimdal/lib/gssapi/spnego/negoex_util.c
index aac09d4483b..e6c9a139248 100644
--- a/third_party/heimdal/lib/gssapi/spnego/negoex_util.c
+++ b/third_party/heimdal/lib/gssapi/spnego/negoex_util.c
@@ -87,10 +87,15 @@ static void
release_all_mechs(gssspnego_ctx ctx, krb5_context context)
{
struct negoex_auth_mech *mech, *next;
+ struct negoex_auth_mech *prev = NULL;
HEIM_TAILQ_FOREACH_SAFE(mech, &ctx->negoex_mechs, links, next) {
- _gss_negoex_release_auth_mech(context, mech);
+ if (prev)
+ _gss_negoex_release_auth_mech(context, prev);
+ prev = mech;
}
+ if (prev)
+ _gss_negoex_release_auth_mech(context, mech);
HEIM_TAILQ_INIT(&ctx->negoex_mechs);
}
@@ -349,7 +354,7 @@ storage_from_memory(OM_uint32 *minor,
krb5_storage **sp)
{
*sp = krb5_storage_from_readonly_mem(data, length);
- if (sp == NULL) {
+ if (*sp == NULL) {
*minor = ENOMEM;
return GSS_S_FAILURE;
}
diff --git a/third_party/heimdal/lib/gssapi/test_context.c b/third_party/heimdal/lib/gssapi/test_context.c
index 7446d15e0df..907e9c4d208 100644
--- a/third_party/heimdal/lib/gssapi/test_context.c
+++ b/third_party/heimdal/lib/gssapi/test_context.c
@@ -734,17 +734,29 @@ wrapunwrap_iov(gss_ctx_id_t cctx, gss_ctx_id_t sctx, int flags, gss_OID mechoid)
token.data = emalloc(token.length);
p = token.data;
- memcpy(p, iov[0].buffer.value, iov[0].buffer.length);
+
+ if (iov[0].buffer.length)
+ memcpy(p, iov[0].buffer.value, iov[0].buffer.length);
p += iov[0].buffer.length;
- memcpy(p, iov[1].buffer.value, iov[1].buffer.length);
+
+ if (iov[1].buffer.length)
+ memcpy(p, iov[1].buffer.value, iov[1].buffer.length);
p += iov[1].buffer.length;
- memcpy(p, iov[2].buffer.value, iov[2].buffer.length);
+
+ if (iov[2].buffer.length)
+ memcpy(p, iov[2].buffer.value, iov[2].buffer.length);
p += iov[2].buffer.length;
- memcpy(p, iov[3].buffer.value, iov[3].buffer.length);
+
+ if (iov[3].buffer.length)
+ memcpy(p, iov[3].buffer.value, iov[3].buffer.length);
p += iov[3].buffer.length;
- memcpy(p, iov[4].buffer.value, iov[4].buffer.length);
+
+ if (iov[4].buffer.length)
+ memcpy(p, iov[4].buffer.value, iov[4].buffer.length);
p += iov[4].buffer.length;
- memcpy(p, iov[5].buffer.value, iov[5].buffer.length);
+
+ if (iov[5].buffer.length)
+ memcpy(p, iov[5].buffer.value, iov[5].buffer.length);
p += iov[5].buffer.length;
assert(p - ((unsigned char *)token.data) == token.length);
@@ -1336,7 +1348,7 @@ main(int argc, char **argv)
if (out1.length != out2.length)
errx(1, "prf len mismatch");
- if (memcmp(out1.value, out2.value, out1.length) != 0)
+ if (out1.length && memcmp(out1.value, out2.value, out1.length) != 0)
errx(1, "prf data mismatch");
gss_release_buffer(&min_stat, &out1);
@@ -1346,7 +1358,7 @@ main(int argc, char **argv)
if (out1.length != out2.length)
errx(1, "prf len mismatch");
- if (memcmp(out1.value, out2.value, out1.length) != 0)
+ if (out1.length && memcmp(out1.value, out2.value, out1.length) != 0)
errx(1, "prf data mismatch");
gss_release_buffer(&min_stat, &out1);
diff --git a/third_party/heimdal/lib/hcrypto/Makefile.am b/third_party/heimdal/lib/hcrypto/Makefile.am
index bb36f745190..878525c17d0 100644
--- a/third_party/heimdal/lib/hcrypto/Makefile.am
+++ b/third_party/heimdal/lib/hcrypto/Makefile.am
@@ -21,7 +21,7 @@ WFLAGS += $(WFLAGS_UNUSED_BUT_SET_VAR)
lib_LTLIBRARIES = libhcrypto.la
check_LTLIBRARIES = libhctest.la
-libhcrypto_la_LDFLAGS = -version-info 5:0:1
+libhcrypto_la_LDFLAGS = -version-info 5:0:0
libhcrypto_la_LIBADD = \
$(top_builddir)/lib/asn1/libasn1.la \
$(LIB_dlopen) \
@@ -51,7 +51,6 @@ hcryptoinclude_HEADERS = \
evp-openssl.h \
evp-pkcs11.h \
hmac.h \
- md2.h \
md4.h \
md5.h \
pkcs12.h \
@@ -160,8 +159,6 @@ libhcrypto_la_SOURCES = \
hash.h \
hmac.c \
hmac.h \
- md2.c \
- md2.h \
md4.c \
md4.h \
md5.c \
diff --git a/third_party/heimdal/lib/hcrypto/NTMakefile b/third_party/heimdal/lib/hcrypto/NTMakefile
index ec945009ba6..e3e50a7d5ba 100644
--- a/third_party/heimdal/lib/hcrypto/NTMakefile
+++ b/third_party/heimdal/lib/hcrypto/NTMakefile
@@ -76,7 +76,6 @@ INCFILES= \
$(HCRYPTOINCLUDEDIR)\evp-wincng.h \
$(HCRYPTOINCLUDEDIR)\evp-w32.h \
$(HCRYPTOINCLUDEDIR)\hmac.h \
- $(HCRYPTOINCLUDEDIR)\md2.h \
$(HCRYPTOINCLUDEDIR)\md4.h \
$(HCRYPTOINCLUDEDIR)\md5.h \
$(HCRYPTOINCLUDEDIR)\pkcs12.h \
@@ -124,7 +123,6 @@ libhcrypto_OBJs = \
$(OBJ)\evp-w32.obj \
$(OBJ)\engine.obj \
$(OBJ)\hmac.obj \
- $(OBJ)\md2.obj \
$(OBJ)\md4.obj \
$(OBJ)\md5.obj \
$(OBJ)\pkcs5.obj \
diff --git a/third_party/heimdal/lib/hcrypto/des.c b/third_party/heimdal/lib/hcrypto/des.c
index 32f87b47137..cb9cac74b6c 100644
--- a/third_party/heimdal/lib/hcrypto/des.c
+++ b/third_party/heimdal/lib/hcrypto/des.c
@@ -344,14 +344,14 @@ load(const unsigned char *b, uint32_t v[2])
static void
store(const uint32_t v[2], unsigned char *b)
{
- b[0] = (v[0] >> 24) & 0xff;
- b[1] = (v[0] >> 16) & 0xff;
- b[2] = (v[0] >> 8) & 0xff;
- b[3] = (v[0] >> 0) & 0xff;
- b[4] = (v[1] >> 24) & 0xff;
- b[5] = (v[1] >> 16) & 0xff;
- b[6] = (v[1] >> 8) & 0xff;
- b[7] = (v[1] >> 0) & 0xff;
+ b[0] = (v[0] >> 24) & 0xffU;
+ b[1] = (v[0] >> 16) & 0xffU;
+ b[2] = (v[0] >> 8) & 0xffU;
+ b[3] = (v[0] >> 0) & 0xffU;
+ b[4] = (v[1] >> 24) & 0xffU;
+ b[5] = (v[1] >> 16) & 0xffU;
+ b[6] = (v[1] >> 8) & 0xffU;
+ b[7] = (v[1] >> 0) & 0xffU;
}
/**
diff --git a/third_party/heimdal/lib/hcrypto/engine.h b/third_party/heimdal/lib/hcrypto/engine.h
index e6fc5b92e41..27c6ab6affa 100644
--- a/third_party/heimdal/lib/hcrypto/engine.h
+++ b/third_party/heimdal/lib/hcrypto/engine.h
@@ -70,7 +70,7 @@
typedef struct hc_engine ENGINE;
-#define NID_md2 0
+/*#define NID_md2 0 */
#define NID_md4 1
#define NID_md5 2
#define NID_sha1 4
diff --git a/third_party/heimdal/lib/hcrypto/evp-cc.c b/third_party/heimdal/lib/hcrypto/evp-cc.c
index 4a377f1c3bb..7798519da18 100644
--- a/third_party/heimdal/lib/hcrypto/evp-cc.c
+++ b/third_party/heimdal/lib/hcrypto/evp-cc.c
@@ -605,32 +605,6 @@ EVP_cc_rc2_64_cbc(void)
#endif
}
-/**
- * The CommonCrypto md2 provider
- *
- * @ingroup hcrypto_evp
- */
-
-const EVP_MD *
-EVP_cc_md2(void)
-{
-#ifdef HAVE_COMMONCRYPTO_COMMONDIGEST_H
- static const struct hc_evp_md md2 = {
- CC_MD2_DIGEST_LENGTH,
- CC_MD2_BLOCK_BYTES,
- sizeof(CC_MD2_CTX),
- (hc_evp_md_init)CC_MD2_Init,
- (hc_evp_md_update)CC_MD2_Update,
- (hc_evp_md_final)CC_MD2_Final,
- (hc_evp_md_cleanup)NULL
- };
- return &md2;
-#elif HCRYPTO_FALLBACK
- return EVP_hcrypto_md2();
-#else
- return NULL;
-#endif
-}
/**
* The CommonCrypto md4 provider
diff --git a/third_party/heimdal/lib/hcrypto/evp-cc.h b/third_party/heimdal/lib/hcrypto/evp-cc.h
index 4d131de01eb..f8576459a8f 100644
--- a/third_party/heimdal/lib/hcrypto/evp-cc.h
+++ b/third_party/heimdal/lib/hcrypto/evp-cc.h
@@ -37,7 +37,6 @@
#define HEIM_EVP_CC_H 1
/* symbol renaming */
-#define EVP_cc_md2 hc_EVP_cc_md2
#define EVP_cc_md4 hc_EVP_cc_md4
#define EVP_cc_md5 hc_EVP_cc_md5
#define EVP_cc_sha1 hc_EVP_cc_sha1
@@ -67,7 +66,6 @@
HC_CPP_BEGIN
-const EVP_MD * EVP_cc_md2(void);
const EVP_MD * EVP_cc_md4(void);
const EVP_MD * EVP_cc_md5(void);
const EVP_MD * EVP_cc_sha1(void);
diff --git a/third_party/heimdal/lib/hcrypto/evp-hcrypto.c b/third_party/heimdal/lib/hcrypto/evp-hcrypto.c
index 321efb08c52..ee43e105a32 100644
--- a/third_party/heimdal/lib/hcrypto/evp-hcrypto.c
+++ b/third_party/heimdal/lib/hcrypto/evp-hcrypto.c
@@ -51,7 +51,6 @@
#include <rc4.h>
#include <sha.h>
-#include <md2.h>
#include <md4.h>
#include <md5.h>
@@ -401,28 +400,6 @@ EVP_hcrypto_md4(void)
return &md4;
}
-/**
- * The message digest MD2 - hcrypto
- *
- * @return the message digest type.
- *
- * @ingroup hcrypto_evp
- */
-
-const EVP_MD *
-EVP_hcrypto_md2(void)
-{
- static const struct hc_evp_md md2 = {
- 16,
- 16,
- sizeof(MD2_CTX),
- (hc_evp_md_init)MD2_Init,
- (hc_evp_md_update)MD2_Update,
- (hc_evp_md_final)MD2_Final,
- NULL
- };
- return &md2;
-}
/*
*
diff --git a/third_party/heimdal/lib/hcrypto/evp-hcrypto.h b/third_party/heimdal/lib/hcrypto/evp-hcrypto.h
index b7876c67c8a..6d4f1c872a2 100644
--- a/third_party/heimdal/lib/hcrypto/evp-hcrypto.h
+++ b/third_party/heimdal/lib/hcrypto/evp-hcrypto.h
@@ -37,7 +37,6 @@
#define HEIM_EVP_HCRYPTO_H 1
/* symbol renaming */
-#define EVP_hcrypto_md2 hc_EVP_hcrypto_md2
#define EVP_hcrypto_md4 hc_EVP_hcrypto_md4
#define EVP_hcrypto_md5 hc_EVP_hcrypto_md5
#define EVP_hcrypto_sha1 hc_EVP_hcrypto_sha1
@@ -67,7 +66,6 @@
HC_CPP_BEGIN
-const EVP_MD * EVP_hcrypto_md2(void);
const EVP_MD * EVP_hcrypto_md4(void);
const EVP_MD * EVP_hcrypto_md5(void);
const EVP_MD * EVP_hcrypto_sha1(void);
diff --git a/third_party/heimdal/lib/hcrypto/evp-openssl.c b/third_party/heimdal/lib/hcrypto/evp-openssl.c
index ca02862bf68..f6cf687b98b 100644
--- a/third_party/heimdal/lib/hcrypto/evp-openssl.c
+++ b/third_party/heimdal/lib/hcrypto/evp-openssl.c
@@ -80,6 +80,24 @@
#define EVP_MD_CTX_free EVP_MD_CTX_destroy
#endif
+#if defined(HAVE_OPENSSL_FIPS_H) || defined(HAVE_OPENSSL_FIPS_MODE_SET_API)
+int _heim_openssl_fips_enabled(void);
+int
+_heim_openssl_fips_enabled(void)
+{
+ static int fips_enabled_res = -1;
+
+ if (fips_enabled_res != -1)
+ return fips_enabled_res;
+
+#ifdef HAVE_OPENSSL_30
+ return fips_enabled_res = !!EVP_default_properties_is_fips_enabled(NULL);
+#else
+ return fips_enabled_res = !!FIPS_mode();
+#endif
+}
+#endif
+
/* A HEIM_BASE_ONCE argument struct for per-EVP one-time initialization */
struct once_init_cipher_ctx {
const hc_EVP_CIPHER **hc_memoizep;
@@ -158,7 +176,7 @@ cipher_do_cipher(hc_EVP_CIPHER_CTX *ctx, unsigned char *out,
struct ossl_cipher_ctx *ossl_ctx = ctx->cipher_data;
assert(ossl_ctx != NULL);
- return EVP_Cipher(ossl_ctx->ossl_cipher_ctx, out, in, len);
+ return EVP_Cipher(ossl_ctx->ossl_cipher_ctx, out, in, len) == 0 ? 0 : 1;
}
static int
@@ -438,7 +456,9 @@ OSSL_CIPHER_ALGORITHM(des_ede3_cbc, hc_EVP_CIPH_CBC_MODE)
*
* @ingroup hcrypto_evp
*/
+#ifndef HAVE_OPENSSL_30
OSSL_CIPHER_ALGORITHM(des_cbc, hc_EVP_CIPH_CBC_MODE)
+#endif
/**
* The AES-128 cipher type (OpenSSL provider)
@@ -494,6 +514,7 @@ OSSL_CIPHER_ALGORITHM(aes_192_cfb8, hc_EVP_CIPH_CFB8_MODE)
*/
OSSL_CIPHER_ALGORITHM(aes_256_cfb8, hc_EVP_CIPH_CFB8_MODE)
+#ifndef HAVE_OPENSSL_30
/*
* RC2 is only needed for tests of PKCS#12 support, which currently uses
* the RC2 PBE. So no RC2 -> tests fail.
@@ -530,6 +551,7 @@ OSSL_CIPHER_ALGORITHM(rc2_40_cbc,
OSSL_CIPHER_ALGORITHM(rc2_64_cbc,
hc_EVP_CIPH_CBC_MODE |
hc_EVP_CIPH_VARIABLE_LENGTH)
+#endif
/**
* The Camellia-128 cipher type - OpenSSL
@@ -558,6 +580,7 @@ OSSL_CIPHER_ALGORITHM(camellia_192_cbc, hc_EVP_CIPH_CBC_MODE)
*/
OSSL_CIPHER_ALGORITHM(camellia_256_cbc, hc_EVP_CIPH_CBC_MODE)
+#ifndef HAVE_OPENSSL_30
/**
* The RC4 cipher type (OpenSSL provider)
*
@@ -581,15 +604,6 @@ OSSL_CIPHER_ALGORITHM(rc4_40,
hc_EVP_CIPH_VARIABLE_LENGTH)
/**
- * The MD2 hash algorithm (OpenSSL provider)
- *
- * @return the MD2 EVP_MD pointer.
- *
- * @ingroup hcrypto_evp
- */
-OSSL_MD_ALGORITHM(md2)
-
-/**
* The MD4 hash algorithm (OpenSSL provider)
*
* @return the MD4 EVP_MD pointer.
@@ -597,6 +611,7 @@ OSSL_MD_ALGORITHM(md2)
* @ingroup hcrypto_evp
*/
OSSL_MD_ALGORITHM(md4)
+#endif
/**
* The MD5 hash algorithm (OpenSSL provider)
diff --git a/third_party/heimdal/lib/hcrypto/evp-openssl.h b/third_party/heimdal/lib/hcrypto/evp-openssl.h
index 225ff454a87..ff285adeee3 100644
--- a/third_party/heimdal/lib/hcrypto/evp-openssl.h
+++ b/third_party/heimdal/lib/hcrypto/evp-openssl.h
@@ -37,7 +37,6 @@
#define HEIM_EVP_OSSL_H 1
/* symbol renaming */
-#define EVP_ossl_md2 hc_EVP_ossl_md2
#define EVP_ossl_md4 hc_EVP_ossl_md4
#define EVP_ossl_md5 hc_EVP_ossl_md5
#define EVP_ossl_sha1 hc_EVP_ossl_sha1
@@ -67,7 +66,6 @@
HC_CPP_BEGIN
-const hc_EVP_MD * hc_EVP_ossl_md2(void);
const hc_EVP_MD * hc_EVP_ossl_md4(void);
const hc_EVP_MD * hc_EVP_ossl_md5(void);
const hc_EVP_MD * hc_EVP_ossl_sha1(void);
diff --git a/third_party/heimdal/lib/hcrypto/evp-pkcs11.c b/third_party/heimdal/lib/hcrypto/evp-pkcs11.c
index b44871fa4c4..90e2b91be4b 100644
--- a/third_party/heimdal/lib/hcrypto/evp-pkcs11.c
+++ b/third_party/heimdal/lib/hcrypto/evp-pkcs11.c
@@ -819,7 +819,6 @@ PKCS11_CIPHER_ALGORITHM(rc4_40,
0,
EVP_CIPH_STREAM_CIPHER | EVP_CIPH_VARIABLE_LENGTH)
-PKCS11_MD_ALGORITHM(md2, CKM_MD2, 16, 16)
#ifdef CKM_MD4 /* non-standard extension */
PKCS11_MD_ALGORITHM(md4, CKM_MD4, 16, 64)
#else
diff --git a/third_party/heimdal/lib/hcrypto/evp-pkcs11.h b/third_party/heimdal/lib/hcrypto/evp-pkcs11.h
index 6d8a21f528b..49d020a2f2c 100644
--- a/third_party/heimdal/lib/hcrypto/evp-pkcs11.h
+++ b/third_party/heimdal/lib/hcrypto/evp-pkcs11.h
@@ -35,7 +35,6 @@
/* symbol renaming */
-#define EVP_pkcs11_md2() hc_EVP_pkcs11_md2()
#define EVP_pkcs11_md4() hc_EVP_pkcs11_md4()
#define EVP_pkcs11_md5() hc_EVP_pkcs11_md5()
#define EVP_pkcs11_sha1() hc_EVP_pkcs11_sha1()
@@ -59,7 +58,6 @@
#define EVP_pkcs11_camellia_192_cbc() hc_EVP_pkcs11_camellia_192_cbc()
#define EVP_pkcs11_camellia_256_cbc() hc_EVP_pkcs11_camellia_256_cbc()
-#define EVP_pkcs11_hcrypto_md2() hc_EVP_pkcs11_hcrypto_md2()
#define EVP_pkcs11_hcrypto_md4() hc_EVP_pkcs11_hcrypto_md4()
#define EVP_pkcs11_hcrypto_md5() hc_EVP_pkcs11_hcrypto_md5()
#define EVP_pkcs11_hcrypto_sha1() hc_EVP_pkcs11_hcrypto_sha1()
@@ -89,7 +87,6 @@ HC_CPP_BEGIN
* Strict PKCS#11 implementations (these will return NULL if the underlying
* PKCS#11 implementation does not implement the cipher or hash).
*/
-const EVP_MD * hc_EVP_pkcs11_md2(void);
const EVP_MD * hc_EVP_pkcs11_md4(void);
const EVP_MD * hc_EVP_pkcs11_md5(void);
const EVP_MD * hc_EVP_pkcs11_sha1(void);
@@ -122,7 +119,6 @@ const EVP_CIPHER * hc_EVP_pkcs11_camellia_256_cbc(void);
/*
* PKCS#11 implementations with fallback to hcrypto.
*/
-const EVP_MD * hc_EVP_pkcs11_hcrypto_md2(void);
const EVP_MD * hc_EVP_pkcs11_hcrypto_md4(void);
const EVP_MD * hc_EVP_pkcs11_hcrypto_md5(void);
const EVP_MD * hc_EVP_pkcs11_hcrypto_sha1(void);
diff --git a/third_party/heimdal/lib/hcrypto/evp-w32.c b/third_party/heimdal/lib/hcrypto/evp-w32.c
index 7d14d1f4f30..ac2c6a53e4b 100644
--- a/third_party/heimdal/lib/hcrypto/evp-w32.c
+++ b/third_party/heimdal/lib/hcrypto/evp-w32.c
@@ -109,7 +109,6 @@ _hc_w32crypto_DllMain(HINSTANCE hinstDLL,
return hc_EVP_hcrypto_ ##name (); \
}
-EVP_W32CRYPTO_PROVIDER(EVP_MD, md2)
EVP_W32CRYPTO_PROVIDER(EVP_MD, md4)
EVP_W32CRYPTO_PROVIDER(EVP_MD, md5)
EVP_W32CRYPTO_PROVIDER(EVP_MD, sha1)
diff --git a/third_party/heimdal/lib/hcrypto/evp-w32.h b/third_party/heimdal/lib/hcrypto/evp-w32.h
index 89bfa4d0af3..6d3ba4596d3 100644
--- a/third_party/heimdal/lib/hcrypto/evp-w32.h
+++ b/third_party/heimdal/lib/hcrypto/evp-w32.h
@@ -34,7 +34,6 @@
#define HEIM_EVP_W32_H 1
/* symbol renaming */
-#define EVP_w32crypto_md2() hc_EVP_w32crypto_md2()
#define EVP_w32crypto_md4() hc_EVP_w32crypto_md4()
#define EVP_w32crypto_md5() hc_EVP_w32crypto_md5()
#define EVP_w32crypto_sha1() hc_EVP_w32crypto_sha1()
@@ -65,7 +64,6 @@
HC_CPP_BEGIN
-const EVP_MD * hc_EVP_w32crypto_md2(void);
const EVP_MD * hc_EVP_w32crypto_md4(void);
const EVP_MD * hc_EVP_w32crypto_md5(void);
const EVP_MD * hc_EVP_w32crypto_sha1(void);
diff --git a/third_party/heimdal/lib/hcrypto/evp-wincng.c b/third_party/heimdal/lib/hcrypto/evp-wincng.c
index 92974a91bb6..34ac3b32459 100644
--- a/third_party/heimdal/lib/hcrypto/evp-wincng.c
+++ b/third_party/heimdal/lib/hcrypto/evp-wincng.c
@@ -700,7 +700,6 @@ wincng_md_cleanup(EVP_MD_CTX *ctx)
} \
} while (0)
-WINCNG_MD_ALGORITHM(md2, BCRYPT_MD2_ALGORITHM);
WINCNG_MD_ALGORITHM(md4, BCRYPT_MD4_ALGORITHM);
WINCNG_MD_ALGORITHM(md5, BCRYPT_MD5_ALGORITHM);
WINCNG_MD_ALGORITHM(sha1, BCRYPT_SHA1_ALGORITHM);
@@ -711,7 +710,6 @@ WINCNG_MD_ALGORITHM(sha512, BCRYPT_SHA512_ALGORITHM);
static void
wincng_md_algorithm_cleanup(void)
{
- WINCNG_MD_ALGORITHM_CLEANUP(md2);
WINCNG_MD_ALGORITHM_CLEANUP(md4);
WINCNG_MD_ALGORITHM_CLEANUP(md5);
WINCNG_MD_ALGORITHM_CLEANUP(sha1);
diff --git a/third_party/heimdal/lib/hcrypto/evp-wincng.h b/third_party/heimdal/lib/hcrypto/evp-wincng.h
index ed7037a1145..88d98303e84 100644
--- a/third_party/heimdal/lib/hcrypto/evp-wincng.h
+++ b/third_party/heimdal/lib/hcrypto/evp-wincng.h
@@ -34,7 +34,6 @@
#define HEIM_EVP_WINCNG_H 1
/* symbol renaming */
-#define EVP_wincng_md2() EVP_wincng_md2()
#define EVP_wincng_md4() EVP_wincng_md4()
#define EVP_wincng_md5() EVP_wincng_md5()
#define EVP_wincng_sha1() EVP_wincng_sha1()
@@ -64,7 +63,6 @@
HC_CPP_BEGIN
-const EVP_MD * hc_EVP_wincng_md2(void);
const EVP_MD * hc_EVP_wincng_md4(void);
const EVP_MD * hc_EVP_wincng_md5(void);
const EVP_MD * hc_EVP_wincng_sha1(void);
diff --git a/third_party/heimdal/lib/hcrypto/evp.c b/third_party/heimdal/lib/hcrypto/evp.c
index 320e85283f7..3874179c029 100644
--- a/third_party/heimdal/lib/hcrypto/evp.c
+++ b/third_party/heimdal/lib/hcrypto/evp.c
@@ -59,6 +59,7 @@
# define HCRYPTO_DEF_PROVIDER pkcs11_hcrypto
# elif HAVE_HCRYPTO_W_OPENSSL
# define HCRYPTO_DEF_PROVIDER ossl
+# define HCRYPTO_DEF_PROVIDER_IS_OPENSSL
# else
# define HCRYPTO_DEF_PROVIDER hcrypto
# endif
@@ -69,6 +70,11 @@
#define EVP_DEF_OP(_prov,_op) HC_CONCAT4(EVP_,_prov,_,_op)()
+#if defined(HAVE_OPENSSL_FIPS_H) || defined(HAVE_OPENSSL_FIPS_MODE_SET_API)
+extern int _heim_openssl_fips_enabled(void);
+#endif
+
+
/**
* @page page_evp EVP - generic crypto interface
*
@@ -463,24 +469,16 @@ const EVP_MD *
EVP_md4(void) HC_DEPRECATED_CRYPTO
{
hcrypto_validate();
+#if defined(HCRYPTO_DEF_PROVIDER_IS_OPENSSL) && defined(HAVE_OPENSSL_30)
+#if defined(HAVE_OPENSSL_FIPS_H) || defined(HAVE_OPENSSL_FIPS_MODE_SET_API)
+ if (_heim_openssl_fips_enabled())
+ return NULL;
+#endif
+ return EVP_DEF_OP(hcrypto, md4);
+#endif
return EVP_DEF_OP(HCRYPTO_DEF_PROVIDER, md4);
}
-/**
- * The message digest MD2
- *
- * @return the message digest type.
- *
- * @ingroup hcrypto_evp
- */
-
-const EVP_MD *
-EVP_md2(void) HC_DEPRECATED_CRYPTO
-{
- hcrypto_validate();
- return EVP_DEF_OP(HCRYPTO_DEF_PROVIDER, md2);
-}
-
/*
*
*/
@@ -872,37 +870,34 @@ EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, void *out, int *outlen,
*outlen = 0;
- /**
- * If there in no spare bytes in the left from last Update and the
- * input length is on the block boundery, the EVP_CipherUpdate()
- * function can take a shortcut (and preformance gain) and
- * directly encrypt the data, otherwise we hav to fix it up and
- * store extra it the EVP_CIPHER_CTX.
+ /*
+ * If there in no bytes left over from the last Update and the
+ * input length is on a block boundary, then we can take a
+ * shortcut (and preformance gain) and directly encrypt the
+ * data.
*/
- if (ctx->buf_len == 0 && (inlen & ctx->block_mask) == 0) {
+ if (ctx->buf_len == 0 && inlen && (inlen & ctx->block_mask) == 0) {
ret = (*ctx->cipher->do_cipher)(ctx, out, in, inlen);
if (ret == 1)
*outlen = inlen;
- else
+ else
*outlen = 0;
return ret;
}
-
blocksize = EVP_CIPHER_CTX_block_size(ctx);
left = blocksize - ctx->buf_len;
assert(left > 0);
if (ctx->buf_len) {
-
- /* if total buffer is smaller then input, store locally */
+ /* If we can't fill one block in the buffer, save the input there */
if (inlen < left) {
memcpy(ctx->buf + ctx->buf_len, in, inlen);
ctx->buf_len += inlen;
return 1;
}
- /* fill in local buffer and encrypt */
+ /* Fill the buffer and encrypt */
memcpy(ctx->buf + ctx->buf_len, in, left);
ret = (*ctx->cipher->do_cipher)(ctx, out, ctx->buf, blocksize);
memset_s(ctx->buf, blocksize, 0, blocksize);
@@ -920,12 +915,16 @@ EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, void *out, int *outlen,
ctx->buf_len = (inlen & ctx->block_mask);
inlen &= ~ctx->block_mask;
- ret = (*ctx->cipher->do_cipher)(ctx, out, in, inlen);
- if (ret != 1)
- return ret;
+ if (inlen) {
+ /* Encrypt all the whole blocks of input that we have */
+ ret = (*ctx->cipher->do_cipher)(ctx, out, in, inlen);
+ if (ret != 1)
+ return ret;
+ }
*outlen += inlen;
+ /* Save the tail of the input, if any */
in = ((unsigned char *)in) + inlen;
memcpy(ctx->buf, in, ctx->buf_len);
}
@@ -984,7 +983,7 @@ EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, void *out, int *outlen)
* @param in in data to the operation.
* @param size length of data.
*
- * @return 1 on success.
+ * @return bytes encrypted on success, zero on failure.
*/
int
@@ -1063,6 +1062,13 @@ const EVP_CIPHER *
EVP_rc2_cbc(void)
{
hcrypto_validate();
+#if defined(HCRYPTO_DEF_PROVIDER_IS_OPENSSL) && defined(HAVE_OPENSSL_30)
+#if defined(HAVE_OPENSSL_FIPS_H) || defined(HAVE_OPENSSL_FIPS_MODE_SET_API)
+ if (_heim_openssl_fips_enabled())
+ return NULL;
+#endif
+ return EVP_DEF_OP(hcrypto, rc2_cbc);
+#endif
return EVP_DEF_OP(HCRYPTO_DEF_PROVIDER, rc2_cbc);
}
@@ -1078,6 +1084,13 @@ const EVP_CIPHER *
EVP_rc2_40_cbc(void)
{
hcrypto_validate();
+#if defined(HCRYPTO_DEF_PROVIDER_IS_OPENSSL) && defined(HAVE_OPENSSL_30)
+#if defined(HAVE_OPENSSL_FIPS_H) || defined(HAVE_OPENSSL_FIPS_MODE_SET_API)
+ if (_heim_openssl_fips_enabled())
+ return NULL;
+#endif
+ return EVP_DEF_OP(hcrypto, rc2_40_cbc);
+#endif
return EVP_DEF_OP(HCRYPTO_DEF_PROVIDER, rc2_40_cbc);
}
@@ -1093,6 +1106,13 @@ const EVP_CIPHER *
EVP_rc2_64_cbc(void)
{
hcrypto_validate();
+#if defined(HCRYPTO_DEF_PROVIDER_IS_OPENSSL) && defined(HAVE_OPENSSL_30)
+#if defined(HAVE_OPENSSL_FIPS_H) || defined(HAVE_OPENSSL_FIPS_MODE_SET_API)
+ if (_heim_openssl_fips_enabled())
+ return NULL;
+#endif
+ return EVP_DEF_OP(hcrypto, rc2_64_cbc);
+#endif
return EVP_DEF_OP(HCRYPTO_DEF_PROVIDER, rc2_64_cbc);
}
@@ -1108,6 +1128,13 @@ const EVP_CIPHER *
EVP_rc4(void)
{
hcrypto_validate();
+#if defined(HCRYPTO_DEF_PROVIDER_IS_OPENSSL) && defined(HAVE_OPENSSL_30)
+#if defined(HAVE_OPENSSL_FIPS_H) || defined(HAVE_OPENSSL_FIPS_MODE_SET_API)
+ if (_heim_openssl_fips_enabled())
+ return NULL;
+#endif
+ return EVP_DEF_OP(hcrypto, rc4);
+#endif
return EVP_DEF_OP(HCRYPTO_DEF_PROVIDER, rc4);
}
@@ -1123,6 +1150,13 @@ const EVP_CIPHER *
EVP_rc4_40(void)
{
hcrypto_validate();
+#if defined(HCRYPTO_DEF_PROVIDER_IS_OPENSSL) && defined(HAVE_OPENSSL_30)
+#if defined(HAVE_OPENSSL_FIPS_H) || defined(HAVE_OPENSSL_FIPS_MODE_SET_API)
+ if (_heim_openssl_fips_enabled())
+ return NULL;
+#endif
+ return EVP_DEF_OP(hcrypto, rc4_40);
+#endif
return EVP_DEF_OP(HCRYPTO_DEF_PROVIDER, rc4_40);
}
@@ -1138,6 +1172,13 @@ const EVP_CIPHER *
EVP_des_cbc(void)
{
hcrypto_validate();
+#if defined(HCRYPTO_DEF_PROVIDER_IS_OPENSSL) && defined(HAVE_OPENSSL_30)
+#if defined(HAVE_OPENSSL_FIPS_H) || defined(HAVE_OPENSSL_FIPS_MODE_SET_API)
+ if (_heim_openssl_fips_enabled())
+ return NULL;
+#endif
+ return EVP_DEF_OP(hcrypto, des_cbc);
+#endif
return EVP_DEF_OP(HCRYPTO_DEF_PROVIDER, des_cbc);
}
diff --git a/third_party/heimdal/lib/hcrypto/evp.h b/third_party/heimdal/lib/hcrypto/evp.h
index 8893362db23..7019abafd6d 100644
--- a/third_party/heimdal/lib/hcrypto/evp.h
+++ b/third_party/heimdal/lib/hcrypto/evp.h
@@ -81,7 +81,6 @@
#define EVP_des_cbc hc_EVP_des_cbc
#define EVP_des_ede3_cbc hc_EVP_des_ede3_cbc
#define EVP_enc_null hc_EVP_enc_null
-#define EVP_md2 hc_EVP_md2
#define EVP_md4 hc_EVP_md4
#define EVP_md5 hc_EVP_md5
#define EVP_md_null hc_EVP_md_null
@@ -194,7 +193,7 @@ struct hc_CIPHER_CTX {
unsigned long flags;
void *cipher_data;
int final_used;
- int block_mask;
+ unsigned block_mask;
unsigned char final[EVP_MAX_BLOCK_LENGTH];
};
@@ -250,7 +249,6 @@ HC_CPP_BEGIN
*/
const EVP_MD *EVP_md_null(void);
-HC_DEPRECATED_CRYPTO const EVP_MD *EVP_md2(void);
HC_DEPRECATED_CRYPTO const EVP_MD *EVP_md4(void);
HC_DEPRECATED_CRYPTO const EVP_MD *EVP_md5(void);
const EVP_MD *EVP_sha(void);
diff --git a/third_party/heimdal/lib/hcrypto/hmac.c b/third_party/heimdal/lib/hcrypto/hmac.c
index adccee76b26..b646d561221 100644
--- a/third_party/heimdal/lib/hcrypto/hmac.c
+++ b/third_party/heimdal/lib/hcrypto/hmac.c
@@ -113,9 +113,10 @@ HMAC_Init_ex(HMAC_CTX *ctx,
ctx->ipad = malloc(blockSize);
if (ctx->ipad)
ctx->ctx = EVP_MD_CTX_create();
- if (!ctx->buf || !ctx->opad || !ctx->ipad || !ctx->ctx)
- return 0;
}
+ /* We do this check here to quiet scan-build */
+ if (!ctx->buf || !ctx->opad || !ctx->ipad || !ctx->ctx)
+ return 0;
#if 0
ctx->engine = engine;
#endif
diff --git a/third_party/heimdal/lib/hcrypto/libhcrypto-exports.def b/third_party/heimdal/lib/hcrypto/libhcrypto-exports.def
index 9ce7082580e..b1e2d34b116 100644
--- a/third_party/heimdal/lib/hcrypto/libhcrypto-exports.def
+++ b/third_party/heimdal/lib/hcrypto/libhcrypto-exports.def
@@ -147,7 +147,6 @@ EXPORTS
hc_EVP_camellia_256_cbc
hc_EVP_enc_null
hc_EVP_get_cipherbyname
- hc_EVP_md2
hc_EVP_md4
hc_EVP_md5
hc_EVP_md_null
@@ -162,7 +161,6 @@ EXPORTS
hc_EVP_sha384
hc_EVP_sha512
-;! hc_EVP_cc_md2
;! hc_EVP_cc_md4
;! hc_EVP_cc_md5
;! hc_EVP_cc_sha1
@@ -177,7 +175,6 @@ EXPORTS
;! hc_EVP_cc_aes_192_cfb8
;! hc_EVP_cc_aes_256_cfb8
- hc_EVP_ossl_md2
hc_EVP_ossl_md4
hc_EVP_ossl_md5
hc_EVP_ossl_sha1
@@ -196,7 +193,6 @@ EXPORTS
hc_EVP_ossl_rc4
hc_EVP_ossl_rc4_40
- hc_EVP_pkcs11_md2
hc_EVP_pkcs11_md4
hc_EVP_pkcs11_md5
hc_EVP_pkcs11_sha1
@@ -214,7 +210,6 @@ EXPORTS
hc_EVP_pkcs11_rc4
hc_EVP_pkcs11_rc4_40
- hc_EVP_w32crypto_md2 ;!
hc_EVP_w32crypto_md4 ;!
hc_EVP_w32crypto_md5 ;!
hc_EVP_w32crypto_sha1 ;!
@@ -234,7 +229,6 @@ EXPORTS
hc_EVP_w32crypto_aes_192_cfb8 ;!
hc_EVP_w32crypto_aes_256_cfb8 ;!
- hc_EVP_hcrypto_md2
hc_EVP_hcrypto_md4
hc_EVP_hcrypto_md5
hc_EVP_hcrypto_sha1
@@ -265,9 +259,6 @@ EXPORTS
hc_HMAC_Init_ex
hc_HMAC_Update
hc_HMAC_size
- hc_MD2_Final
- hc_MD2_Init
- hc_MD2_Update
hc_MD4_Final
hc_MD4_Init
hc_MD4_Update
diff --git a/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_log_u32.c b/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_log_u32.c
index f7bca01ded3..c9cc157911e 100644
--- a/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_log_u32.c
+++ b/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_log_u32.c
@@ -91,13 +91,24 @@ mp_err mp_log_u32(const mp_int *a, uint32_t base, uint32_t *c)
return MP_VAL;
}
+ /* `base' is at least 2 */
+
/* A small shortcut for bases that are powers of two. */
if ((base & (base - 1u)) == 0u) {
int y, bit_count;
+
for (y=0; (y < 7) && ((base & 1u) == 0u); y++) {
+ /* We must go through this loop at least once */
base >>= 1;
}
bit_count = mp_count_bits(a) - 1;
+ /*
+ * `y' is necessarily at least 1 because `base' is a power of two and
+ * larger than 1, so we must have gone through the loop at least once, so
+ * we can't be dividing by zero.
+ *
+ * scan-build thinks we can be dividing by zero... WAT.
+ */
*c = (uint32_t)(bit_count/y);
return MP_OKAY;
}
diff --git a/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_prime_rand.c b/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_prime_rand.c
index 4530e9a5e1e..23a1c4f78dc 100644
--- a/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_prime_rand.c
+++ b/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_prime_rand.c
@@ -39,7 +39,7 @@ mp_err s_mp_prime_random_ex(mp_int *a, int t, int size, int flags, private_mp_pr
bsize = (size>>3) + ((size&7)?1:0);
/* we need a buffer of bsize bytes */
- tmp = (unsigned char *) MP_MALLOC((size_t)bsize);
+ tmp = (unsigned char *) MP_CALLOC(1, (size_t)bsize);
if (tmp == NULL) {
return MP_MEM;
}
diff --git a/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_root_u32.c b/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_root_u32.c
index ba65549c645..97b1b2ea482 100644
--- a/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_root_u32.c
+++ b/third_party/heimdal/lib/hcrypto/libtommath/bn_mp_root_u32.c
@@ -23,6 +23,9 @@ mp_err mp_root_u32(const mp_int *a, uint32_t b, mp_int *c)
if (((b & 1u) == 0u) && (a->sign == MP_NEG)) {
return MP_VAL;
}
+ if (b == 0) {
+ return MP_VAL;
+ }
if ((err = mp_init_multi(&t1, &t2, &t3, NULL)) != MP_OKAY) {
return err;
diff --git a/third_party/heimdal/lib/hcrypto/md2.c b/third_party/heimdal/lib/hcrypto/md2.c
deleted file mode 100644
index 0170d416a1c..00000000000
--- a/third_party/heimdal/lib/hcrypto/md2.c
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (c) 2006 Kungliga Tekniska Högskolan
- * (Royal Institute of Technology, Stockholm, Sweden).
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * 3. Neither the name of the Institute nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <config.h>
-#include <roken.h>
-
-#include "hash.h"
-#include "md2.h"
-
-static const unsigned char subst[256] = {
- 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6,
- 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188,
- 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24,
- 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251,
- 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63,
- 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50,
- 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165,
- 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210,
- 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157,
- 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27,
- 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
- 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197,
- 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65,
- 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123,
- 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233,
- 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228,
- 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237,
- 31, 26, 219, 153, 141, 51, 159, 17, 131, 20
-};
-
-int
-MD2_Init (struct md2 *m)
-{
- memset(m, 0, sizeof(*m));
- return 1;
-}
-
-static void
-calc(struct md2 *m, const void *v)
-{
- unsigned char x[48], L;
- const unsigned char *p = v;
- int i, j, t;
-
- L = m->checksum[15];
- for (i = 0; i < 16; i++)
- L = m->checksum[i] ^= subst[p[i] ^ L];
-
- for (i = 0; i < 16; i++) {
- x[i] = m->state[i];
- x[i + 16] = p[i];
- x[i + 32] = x[i] ^ p[i];
- }
-
- t = 0;
- for (i = 0; i < 18; i++) {
- for (j = 0; j < 48; j++)
- t = x[j] ^= subst[t];
- t = (t + i) & 0xff;
- }
-
- memcpy(m->state, x, 16);
- memset_s(x, sizeof(x), 0, sizeof(x));
-}
-
-int
-MD2_Update (struct md2 *m, const void *v, size_t len)
-{
- size_t idx = m->len & 0xf;
- const unsigned char *p = v;
-
- m->len += len;
- if (len + idx >= 16) {
- if (idx) {
- memcpy(m->data + idx, p, 16 - idx);
- calc(m, m->data);
- p += 16;
- len -= 16 - idx;
- }
- while (len >= 16) {
- calc(m, p);
- p += 16;
- len -= 16;
- }
- idx = 0;
- }
-
- memcpy(m->data + idx, p, len);
- return 1;
-}
-
-int
-MD2_Final (void *res, struct md2 *m)
-{
- unsigned char pad[16];
- size_t padlen;
-
- padlen = 16 - (m->len % 16);
- memset(pad, padlen, padlen);
-
- MD2_Update(m, pad, padlen);
- memcpy(pad, m->checksum, 16);
- MD2_Update(m, pad, 16);
-
- memcpy(res, m->state, MD2_DIGEST_LENGTH);
- memset_s(m, sizeof(*m), 0, sizeof(*m));
- return 1;
-}
diff --git a/third_party/heimdal/lib/hcrypto/md2.h b/third_party/heimdal/lib/hcrypto/md2.h
deleted file mode 100644
index d82334eac94..00000000000
--- a/third_party/heimdal/lib/hcrypto/md2.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2006 Kungliga Tekniska Högskolan
- * (Royal Institute of Technology, Stockholm, Sweden).
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * 3. Neither the name of the Institute nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/* $Id$ */
-
-#ifndef HEIM_MD2_H
-#define HEIM_MD2_H 1
-
-/* symbol renaming */
-#define MD2_Init hc_MD2_Init
-#define MD2_Update hc_MD2_Update
-#define MD2_Final hc_MD2_Final
-
-/*
- *
- */
-
-#define MD2_DIGEST_LENGTH 16
-
-struct md2 {
- size_t len;
- unsigned char data[16]; /* stored unalligned data between Update's */
- unsigned char checksum[16];
- unsigned char state[16]; /* lower 16 bytes of X */
-};
-
-typedef struct md2 MD2_CTX;
-
-int MD2_Init (struct md2 *m);
-int MD2_Update (struct md2 *m, const void *p, size_t len);
-int MD2_Final (void *res, struct md2 *m);
-
-#endif /* HEIM_MD2_H */
diff --git a/third_party/heimdal/lib/hcrypto/mdtest.c b/third_party/heimdal/lib/hcrypto/mdtest.c
index d301c5c4a42..7ad93e3560e 100644
--- a/third_party/heimdal/lib/hcrypto/mdtest.c
+++ b/third_party/heimdal/lib/hcrypto/mdtest.c
@@ -39,7 +39,6 @@
#ifdef KRB5
#include <krb5-types.h>
#endif
-#include <md2.h>
#include <md4.h>
#include <md5.h>
#include <sha.h>
@@ -51,68 +50,60 @@ struct hash_foo {
const char *name;
size_t psize;
size_t hsize;
- void (*init)(void*);
- void (*update)(void*, const void*, size_t);
- void (*final)(void*, void*);
+ int (*init)(void*);
+ int (*update)(void*, const void*, size_t);
+ int (*final)(void*, void*);
const EVP_MD * (*evp)(void);
-} md2 = {
- "MD2",
- sizeof(MD2_CTX),
- 16,
- (void (*)(void*))MD2_Init,
- (void (*)(void*,const void*, size_t))MD2_Update,
- (void (*)(void*, void*))MD2_Final,
- EVP_md2
-}, md4 = {
+} md4 = {
"MD4",
sizeof(MD4_CTX),
16,
- (void (*)(void*))MD4_Init,
- (void (*)(void*,const void*, size_t))MD4_Update,
- (void (*)(void*, void*))MD4_Final,
+ (int (*)(void*))MD4_Init,
+ (int (*)(void*,const void*, size_t))MD4_Update,
+ (int (*)(void*, void*))MD4_Final,
EVP_md4
}, md5 = {
"MD5",
sizeof(MD5_CTX),
16,
- (void (*)(void*))MD5_Init,
- (void (*)(void*,const void*, size_t))MD5_Update,
- (void (*)(void*, void*))MD5_Final,
+ (int (*)(void*))MD5_Init,
+ (int (*)(void*,const void*, size_t))MD5_Update,
+ (int (*)(void*, void*))MD5_Final,
EVP_md5
}, sha1 = {
"SHA-1",
sizeof(struct sha),
20,
- (void (*)(void*))SHA1_Init,
- (void (*)(void*,const void*, size_t))SHA1_Update,
- (void (*)(void*, void*))SHA1_Final,
+ (int (*)(void*))SHA1_Init,
+ (int (*)(void*,const void*, size_t))SHA1_Update,
+ (int (*)(void*, void*))SHA1_Final,
EVP_sha1
};
struct hash_foo sha256 = {
"SHA-256",
sizeof(SHA256_CTX),
32,
- (void (*)(void*))SHA256_Init,
- (void (*)(void*,const void*, size_t))SHA256_Update,
- (void (*)(void*, void*))SHA256_Final,
+ (int (*)(void*))SHA256_Init,
+ (int (*)(void*,const void*, size_t))SHA256_Update,
+ (int (*)(void*, void*))SHA256_Final,
EVP_sha256
};
struct hash_foo sha384 = {
"SHA-384",
sizeof(SHA384_CTX),
48,
- (void (*)(void*))SHA384_Init,
- (void (*)(void*,const void*, size_t))SHA384_Update,
- (void (*)(void*, void*))SHA384_Final,
+ (int (*)(void*))SHA384_Init,
+ (int (*)(void*,const void*, size_t))SHA384_Update,
+ (int (*)(void*, void*))SHA384_Final,
EVP_sha384
};
struct hash_foo sha512 = {
"SHA-512",
sizeof(SHA512_CTX),
64,
- (void (*)(void*))SHA512_Init,
- (void (*)(void*,const void*, size_t))SHA512_Update,
- (void (*)(void*, void*))SHA512_Final,
+ (int (*)(void*))SHA512_Init,
+ (int (*)(void*,const void*, size_t))SHA512_Update,
+ (int (*)(void*, void*))SHA512_Final,
EVP_sha512
};
@@ -121,24 +112,6 @@ struct test {
unsigned char hash[64];
};
-struct test md2_tests[] = {
- {"",
- "\x83\x50\xe5\xa3\xe2\x4c\x15\x3d\xf2\x27\x5c\x9f\x80\x69\x27\x73" },
- {"a",
- "\x32\xec\x01\xec\x4a\x6d\xac\x72\xc0\xab\x96\xfb\x34\xc0\xb5\xd1" },
- {"abc",
- "\xda\x85\x3b\x0d\x3f\x88\xd9\x9b\x30\x28\x3a\x69\xe6\xde\xd6\xbb" },
- {"message digest",
- "\xab\x4f\x49\x6b\xfb\x2a\x53\x0b\x21\x9f\xf3\x30\x31\xfe\x06\xb0" },
- {"abcdefghijklmnopqrstuvwxyz",
- "\x4e\x8d\xdf\xf3\x65\x02\x92\xab\x5a\x41\x08\xc3\xaa\x47\x94\x0b" },
- {"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
- "\xda\x33\xde\xf2\xa4\x2d\xf1\x39\x75\x35\x28\x46\xc3\x03\x38\xcd" },
- {"12345678901234567890123456789012345678901234567890123456789012345678901234567890",
- "\xd5\x97\x6f\x79\xd8\x3d\x3a\x0d\xc9\x80\x6c\x3c\x66\xf3\xef\xd8" },
- {NULL, { 0 } }
-};
-
struct test md4_tests[] = {
{"",
{0x31, 0xd6, 0xcf, 0xe0, 0xd1, 0x6a, 0xe9, 0x31, 0xb7, 0x3c, 0x59,
@@ -338,7 +311,6 @@ int
main (void)
{
return
- hash_test(&md2, md2_tests) +
hash_test(&md4, md4_tests) +
hash_test(&md5, md5_tests) +
hash_test(&sha1, sha1_tests) +
diff --git a/third_party/heimdal/lib/hcrypto/pkcs5.c b/third_party/heimdal/lib/hcrypto/pkcs5.c
index dff3ccea398..88e71c4dd53 100644
--- a/third_party/heimdal/lib/hcrypto/pkcs5.c
+++ b/third_party/heimdal/lib/hcrypto/pkcs5.c
@@ -85,7 +85,8 @@ PKCS5_PBKDF2_HMAC(const void * password, size_t password_len,
data = &tmpcksum[checksumsize];
- memcpy(data, salt, salt_len);
+ if (salt_len)
+ memcpy(data, salt, salt_len);
keypart = 1;
leftofkey = keylen;
diff --git a/third_party/heimdal/lib/hcrypto/rand-fortuna.c b/third_party/heimdal/lib/hcrypto/rand-fortuna.c
index 74ba12396fd..31f72330245 100644
--- a/third_party/heimdal/lib/hcrypto/rand-fortuna.c
+++ b/third_party/heimdal/lib/hcrypto/rand-fortuna.c
@@ -501,10 +501,9 @@ fortuna_reseed(void)
/* add /etc/shadow */
fd = open("/etc/shadow", O_RDONLY, 0);
if (fd >= 0) {
- ssize_t n;
rk_cloexec(fd);
/* add_entropy will hash the buf */
- while ((n = read(fd, (char *)u.shad, sizeof(u.shad))) > 0)
+ while (read(fd, (char *)u.shad, sizeof(u.shad)) > 0)
add_entropy(&main_state, u.shad, sizeof(u.shad));
close(fd);
}
diff --git a/third_party/heimdal/lib/hcrypto/rsa-ltm.c b/third_party/heimdal/lib/hcrypto/rsa-ltm.c
index 1d5b73e60e5..49e35f5a38a 100644
--- a/third_party/heimdal/lib/hcrypto/rsa-ltm.c
+++ b/third_party/heimdal/lib/hcrypto/rsa-ltm.c
@@ -41,7 +41,7 @@
#include "tommath.h"
#define CHECK(f) \
- do { if (ret == MP_OKAY && ((ret = f)) != MP_OKAY) { goto out; } } while (0)
+ do { where = __LINE__ + 1; if (ret == MP_OKAY && ((ret = f)) != MP_OKAY) { goto out; } } while (0)
#define FIRST(e) do { ret = (e); } while (0)
#define FIRST_ALLOC(e) \
do { where = __LINE__; ret = ((e)) ? MP_OKAY : MP_MEM; } while (0)
@@ -50,9 +50,9 @@
#define THEN_IF_MP(cond, e) \
do { where = __LINE__ + 1; if (ret == MP_OKAY && (cond)) ret = (e); } while (0)
#define THEN_IF_VOID(cond, e) \
- do { if (ret == MP_OKAY && (cond)) e; } while (0)
+ do { where = __LINE__ + 1; if (ret == MP_OKAY && (cond)) e; } while (0)
#define THEN_VOID(e) \
- do { if (ret == MP_OKAY) e; } while (0)
+ do { where = __LINE__ + 1; if (ret == MP_OKAY) e; } while (0)
#define THEN_ALLOC(e) \
do { where = __LINE__ + 1; if (ret == MP_OKAY) ret = ((e)) ? MP_OKAY : MP_MEM; } while (0)
@@ -226,7 +226,7 @@ ltm_rsa_public_decrypt(int flen, const unsigned char* from,
mp_err ret;
size_t size;
mp_int s, us, n, e;
- int where = 0;
+ int where = __LINE__;
if (padding != RSA_PKCS1_PADDING)
return -1;
@@ -250,7 +250,7 @@ ltm_rsa_public_decrypt(int flen, const unsigned char* from,
mp_clear_multi(&e, &n, &s, NULL);
mp_clear(&us);
- if (ret != MP_OKAY)
+ if (ret != MP_OKAY || size == 0)
return -where;
/* head zero was skipped by mp_to_unsigned_bin */
@@ -280,7 +280,7 @@ ltm_rsa_private_encrypt(int flen, const unsigned char* from,
size_t size;
int blinding = (rsa->flags & RSA_FLAG_NO_BLINDING) == 0;
int do_unblind = 0;
- int where = 0;
+ int where = __LINE__;
if (padding != RSA_PKCS1_PADDING)
return -1;
@@ -367,7 +367,7 @@ ltm_rsa_private_decrypt(int flen, const unsigned char* from,
mp_int in, out, n, e, b, bi;
int blinding = (rsa->flags & RSA_FLAG_NO_BLINDING) == 0;
int do_unblind = 0;
- int where = 0;
+ int where = __LINE__;
if (padding != RSA_PKCS1_PADDING)
return -1;
@@ -530,7 +530,7 @@ ltm_rsa_generate_key(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb)
mp_err ret;
uint8_t high_nibbles = 0;
int bitsp;
- int where = 0;
+ int where = __LINE__;
if (bits < 789)
return -1;
diff --git a/third_party/heimdal/lib/hcrypto/test_bulk.c b/third_party/heimdal/lib/hcrypto/test_bulk.c
index e3737fd1e95..db5aeae1ee1 100644
--- a/third_party/heimdal/lib/hcrypto/test_bulk.c
+++ b/third_party/heimdal/lib/hcrypto/test_bulk.c
@@ -201,7 +201,6 @@ test_bulk_provider_hcrypto(void)
test_bulk_cipher("hcrypto_aes_256_cfb8", EVP_hcrypto_aes_256_cfb8());
#endif
test_bulk_cipher("hcrypto_rc4", EVP_hcrypto_rc4());
- test_bulk_digest("hcrypto_md2", EVP_hcrypto_md2());
test_bulk_digest("hcrypto_md4", EVP_hcrypto_md4());
test_bulk_digest("hcrypto_md5", EVP_hcrypto_md5());
test_bulk_digest("hcrypto_sha1", EVP_hcrypto_sha1());
@@ -219,7 +218,6 @@ test_bulk_provider_cc(void)
test_bulk_cipher("cc_aes_256_cfb8", EVP_cc_aes_256_cfb8());
#endif
test_bulk_cipher("cc_rc4", EVP_cc_rc4());
- test_bulk_digest("cc_md2", EVP_cc_md2());
test_bulk_digest("cc_md4", EVP_cc_md4());
test_bulk_digest("cc_md5", EVP_cc_md5());
test_bulk_digest("cc_sha1", EVP_cc_sha1());
@@ -238,7 +236,6 @@ test_bulk_provider_w32crypto(void)
test_bulk_cipher("w32crypto_aes_256_cfb8", EVP_w32crypto_aes_256_cfb8());
#endif
test_bulk_cipher("w32crypto_rc4", EVP_w32crypto_rc4());
- test_bulk_digest("w32crypto_md2", EVP_w32crypto_md2());
test_bulk_digest("w32crypto_md4", EVP_w32crypto_md4());
test_bulk_digest("w32crypto_md5", EVP_w32crypto_md5());
test_bulk_digest("w32crypto_sha1", EVP_w32crypto_sha1());
diff --git a/third_party/heimdal/lib/hcrypto/test_cipher.c b/third_party/heimdal/lib/hcrypto/test_cipher.c
index c566e4bfd00..9be65dd16e5 100644
--- a/third_party/heimdal/lib/hcrypto/test_cipher.c
+++ b/third_party/heimdal/lib/hcrypto/test_cipher.c
@@ -422,14 +422,8 @@ main(int argc, char **argv)
ret += test_cipher(i, EVP_ossl_aes_256_cbc(), &aes_tests[i]);
for (i = 0; i < sizeof(aes_cfb_tests)/sizeof(aes_cfb_tests[0]); i++)
ret += test_cipher(i, EVP_ossl_aes_128_cfb8(), &aes_cfb_tests[i]);
- for (i = 0; i < sizeof(rc2_tests)/sizeof(rc2_tests[0]); i++)
- ret += test_cipher(i, EVP_ossl_rc2_cbc(), &rc2_tests[i]);
- for (i = 0; i < sizeof(rc2_40_tests)/sizeof(rc2_40_tests[0]); i++)
- ret += test_cipher(i, EVP_ossl_rc2_40_cbc(), &rc2_40_tests[i]);
for (i = 0; i < sizeof(des_ede3_tests)/sizeof(des_ede3_tests[0]); i++)
ret += test_cipher(i, EVP_ossl_des_ede3_cbc(), &des_ede3_tests[i]);
- for (i = 0; i < sizeof(rc4_tests)/sizeof(rc4_tests[0]); i++)
- ret += test_cipher(i, EVP_ossl_rc4(), &rc4_tests[i]);
#endif /* PKCS11_MODULE_PATH */
return ret;
diff --git a/third_party/heimdal/lib/hcrypto/test_crypto.in b/third_party/heimdal/lib/hcrypto/test_crypto.in
index d5b3893164a..91c4d8f1093 100644
--- a/third_party/heimdal/lib/hcrypto/test_crypto.in
+++ b/third_party/heimdal/lib/hcrypto/test_crypto.in
@@ -82,11 +82,11 @@ for a in unix fortuna egd w32crypto ;do
{ echo "rand output same!" ; exit 1; }
done
-./example_evp_cipher 1 ${srcdir}/test_crypto.in test-out-1 || \
- { echo "1 failed" ; exit 1; }
-
-for a in 7 15 16 17 31 32 33 ; do
- ./example_evp_cipher $a ${srcdir}/test_crypto.in test-out-$a
+for a in 1 7 15 16 17 31 32 33 ; do
+ ./example_evp_cipher $a ${srcdir}/test_crypto.in test-out-$a ||
+ { echo "$s failed" ; exit 1; }
+done
+for a in 7 15 16 17 31 32 33 ; do
cmp test-out-1 test-out-$a || { echo "cmp $a failed" ; exit 1; }
done
diff --git a/third_party/heimdal/lib/hcrypto/undef.h b/third_party/heimdal/lib/hcrypto/undef.h
index 512b8c3f02e..6de5734a28f 100644
--- a/third_party/heimdal/lib/hcrypto/undef.h
+++ b/third_party/heimdal/lib/hcrypto/undef.h
@@ -116,7 +116,6 @@
#undef EVP_des_cbc
#undef EVP_des_ede3_cbc
#undef EVP_enc_null
-#undef EVP_md2
#undef EVP_md4
#undef EVP_md5
#undef EVP_md_null
@@ -158,7 +157,6 @@
#undef EVP_CIPH_ALWAYS_CALL_INIT
#undef EVP_CIPH_RAND_KEY
#undef EVP_CTRL_RAND_KEY
-#undef NID_md2
#undef NID_md4
#undef NID_md5
#undef NID_sha1
diff --git a/third_party/heimdal/lib/hcrypto/version-script.map b/third_party/heimdal/lib/hcrypto/version-script.map
index fbd8141dbf2..b51d4bb607f 100644
--- a/third_party/heimdal/lib/hcrypto/version-script.map
+++ b/third_party/heimdal/lib/hcrypto/version-script.map
@@ -154,7 +154,6 @@ HEIMDAL_CRYPTO_1.0 {
hc_EVP_camellia_256_cbc;
hc_EVP_enc_null;
hc_EVP_get_cipherbyname;
- hc_EVP_md2;
hc_EVP_md4;
hc_EVP_md5;
hc_EVP_md_null;
@@ -169,7 +168,6 @@ HEIMDAL_CRYPTO_1.0 {
hc_EVP_sha384;
hc_EVP_sha512;
- hc_EVP_cc_md2;
hc_EVP_cc_md4;
hc_EVP_cc_md5;
hc_EVP_cc_sha1;
@@ -184,7 +182,6 @@ HEIMDAL_CRYPTO_1.0 {
hc_EVP_cc_aes_192_cfb8;
hc_EVP_cc_aes_256_cfb8;
- hc_EVP_hcrypto_md2;
hc_EVP_hcrypto_md4;
hc_EVP_hcrypto_md5;
hc_EVP_hcrypto_sha1;
@@ -201,7 +198,6 @@ HEIMDAL_CRYPTO_1.0 {
hc_EVP_hcrypto_rc4;
hc_EVP_hcrypto_rc4_40;
- hc_EVP_ossl_md2;
hc_EVP_ossl_md4;
hc_EVP_ossl_md5;
hc_EVP_ossl_sha1;
@@ -220,7 +216,6 @@ HEIMDAL_CRYPTO_1.0 {
hc_EVP_ossl_rc4;
hc_EVP_ossl_rc4_40;
- hc_EVP_pkcs11_md2;
hc_EVP_pkcs11_md4;
hc_EVP_pkcs11_md5;
hc_EVP_pkcs11_sha1;
@@ -250,9 +245,6 @@ HEIMDAL_CRYPTO_1.0 {
hc_HMAC_Init_ex;
hc_HMAC_Update;
hc_HMAC_size;
- hc_MD2_Final;
- hc_MD2_Init;
- hc_MD2_Update;
hc_MD4_Final;
hc_MD4_Init;
hc_MD4_Update;
diff --git a/third_party/heimdal/lib/hdb/common.c b/third_party/heimdal/lib/hdb/common.c
index 56e582abaa8..1c947b3cfc5 100644
--- a/third_party/heimdal/lib/hdb/common.c
+++ b/third_party/heimdal/lib/hdb/common.c
@@ -1586,6 +1586,7 @@ fix_princ_name(krb5_context context,
s,
NULL);
}
+ free(s);
return ret;
}
diff --git a/third_party/heimdal/lib/hdb/hdb.c b/third_party/heimdal/lib/hdb/hdb.c
index 171ba9e3fd3..c9c6c85bef2 100644
--- a/third_party/heimdal/lib/hdb/hdb.c
+++ b/third_party/heimdal/lib/hdb/hdb.c
@@ -333,7 +333,7 @@ hdb_next_enctype2key(krb5_context context,
krb5_error_code
hdb_enctype2key(krb5_context context,
- hdb_entry *e,
+ const hdb_entry *e,
const Keys *keyset,
krb5_enctype enctype,
Key **key)
diff --git a/third_party/heimdal/lib/hx509/ca.c b/third_party/heimdal/lib/hx509/ca.c
index 3d62b93fa57..1ca8d51da39 100644
--- a/third_party/heimdal/lib/hx509/ca.c
+++ b/third_party/heimdal/lib/hx509/ca.c
@@ -1179,6 +1179,7 @@ hx509_ca_tbs_add_san_permanentIdentifier_string(hx509_context context,
char *freeme, *p;
int ret;
+ memset(&oid, 0, sizeof(oid));
if ((freeme = strdup(str)) == NULL)
return hx509_enomem(context);
@@ -1287,6 +1288,7 @@ hx509_ca_tbs_add_san_hardwareModuleName_string(hx509_context context,
char *freeme, *p;
int ret;
+ memset(&oid, 0, sizeof(oid));
if ((freeme = strdup(str)) == NULL)
return hx509_enomem(context);
@@ -2611,7 +2613,6 @@ set_template(hx509_context context,
"template_cert", NULL);
subj_name = heim_config_get_string(context->hcontext, cf, "subject_name",
NULL);
- ekus = heim_config_get_strings(context->hcontext, cf, "ekus", NULL);
if (cert_template) {
hx509_certs certs;
@@ -2667,6 +2668,7 @@ set_template(hx509_context context,
return ret;
}
+ ekus = heim_config_get_strings(context->hcontext, cf, "ekus", NULL);
if (ekus) {
size_t i;
diff --git a/third_party/heimdal/lib/hx509/cert.c b/third_party/heimdal/lib/hx509/cert.c
index 3dda886edc5..e7e2423c54d 100644
--- a/third_party/heimdal/lib/hx509/cert.c
+++ b/third_party/heimdal/lib/hx509/cert.c
@@ -1207,12 +1207,71 @@ certificate_is_self_signed(hx509_context context,
if (ret) {
hx509_set_error_string(context, 0, ret,
"Failed to check if self signed");
- } else
+ } else if (diff == 0)
ret = _hx509_self_signed_valid(context, &cert->signatureAlgorithm);
return ret;
}
+HX509_LIB_FUNCTION int HX509_LIB_CALL
+hx509_cert_is_self_signed(hx509_context context,
+ hx509_cert c,
+ int *self_signed)
+{
+ return certificate_is_self_signed(context, c->data, self_signed);
+}
+
+HX509_LIB_FUNCTION int HX509_LIB_CALL
+hx509_cert_is_ca(hx509_context context,
+ hx509_cert c,
+ int *is_ca)
+{
+ BasicConstraints bc;
+ const Extension *e;
+ size_t size;
+ size_t i = 0;
+ int ret = 0;
+
+ *is_ca = 0;
+ if (_hx509_cert_get_version(c->data) < 3)
+ return certificate_is_self_signed(context, c->data, is_ca);
+
+ e = find_extension(c->data, &asn1_oid_id_x509_ce_basicConstraints, &i);
+ if (e == NULL) {
+ *is_ca = 0;
+ return 0;
+ }
+
+ ret = decode_BasicConstraints(e->extnValue.data,
+ e->extnValue.length, &bc,
+ &size);
+ if (ret)
+ return ret;
+
+ *is_ca = bc.cA;
+ free_BasicConstraints(&bc);
+ return 0;
+}
+
+HX509_LIB_FUNCTION int HX509_LIB_CALL
+hx509_cert_is_root(hx509_context context,
+ hx509_cert c,
+ int *is_root)
+{
+ int ret;
+
+ *is_root = 0;
+ ret = hx509_cert_is_ca(context, c, is_root);
+ if (ret)
+ return ret;
+ if (*is_root == 0)
+ /* Not a CA certificate -> not a root certificate */
+ return 0;
+
+ /* A CA certificate. If it's self-signed, it's a root certificate. */
+ return hx509_cert_is_self_signed(context, c, is_root);
+}
+
/*
* The subjectName is "null" when it's empty set of relative DBs.
*/
diff --git a/third_party/heimdal/lib/hx509/collector.c b/third_party/heimdal/lib/hx509/collector.c
index 7b46809816c..f1423aced2f 100644
--- a/third_party/heimdal/lib/hx509/collector.c
+++ b/third_party/heimdal/lib/hx509/collector.c
@@ -147,6 +147,16 @@ _hx509_collector_private_key_add(hx509_context context,
key_data->data, key_data->length,
HX509_KEY_FORMAT_DER,
&key->private_key);
+ if (ret && localKeyId) {
+ int ret2;
+
+ ret2 = hx509_parse_private_key(context, alg,
+ localKeyId->data, localKeyId->length,
+ HX509_KEY_FORMAT_PKCS8,
+ &key->private_key);
+ if (ret2 == 0)
+ ret = 0;
+ }
if (ret)
goto out;
}
diff --git a/third_party/heimdal/lib/hx509/crypto-ec.c b/third_party/heimdal/lib/hx509/crypto-ec.c
index 46e6cd8e339..bd5d01a609a 100644
--- a/third_party/heimdal/lib/hx509/crypto-ec.c
+++ b/third_party/heimdal/lib/hx509/crypto-ec.c
@@ -34,11 +34,16 @@
#include <config.h>
#ifdef HAVE_HCRYPTO_W_OPENSSL
+#include <openssl/evp.h>
#include <openssl/ec.h>
#include <openssl/ecdsa.h>
#include <openssl/rsa.h>
#include <openssl/bn.h>
#include <openssl/objects.h>
+#ifdef HAVE_OPENSSL_30
+#include <openssl/asn1.h>
+#include <openssl/core_names.h>
+#endif
#define HEIM_NO_CRYPTO_HDRS
#endif /* HAVE_HCRYPTO_W_OPENSSL */
@@ -53,43 +58,50 @@ HX509_LIB_FUNCTION void HX509_LIB_CALL
_hx509_private_eckey_free(void *eckey)
{
#ifdef HAVE_HCRYPTO_W_OPENSSL
+#ifdef HAVE_OPENSSL_30
+ EVP_PKEY_free(eckey);
+#else
EC_KEY_free(eckey);
#endif
+#endif
}
#ifdef HAVE_HCRYPTO_W_OPENSSL
-static int
-heim_oid2ecnid(heim_oid *oid)
-{
- /*
- * Now map to openssl OID fun
- */
-
- if (der_heim_oid_cmp(oid, ASN1_OID_ID_EC_GROUP_SECP256R1) == 0)
- return NID_X9_62_prime256v1;
+static struct oid2nid_st {
+ const heim_oid *oid;
+ int nid;
+} oid2nid[] = {
+ { ASN1_OID_ID_EC_GROUP_SECP256R1, NID_X9_62_prime256v1 },
#ifdef NID_secp521r1
- else if (der_heim_oid_cmp(oid, ASN1_OID_ID_EC_GROUP_SECP521R1) == 0)
- return NID_secp521r1;
+ { ASN1_OID_ID_EC_GROUP_SECP521R1, NID_secp521r1 },
#endif
#ifdef NID_secp384r1
- else if (der_heim_oid_cmp(oid, ASN1_OID_ID_EC_GROUP_SECP384R1) == 0)
- return NID_secp384r1;
+ { ASN1_OID_ID_EC_GROUP_SECP384R1, NID_secp384r1 },
#endif
#ifdef NID_secp160r1
- else if (der_heim_oid_cmp(oid, ASN1_OID_ID_EC_GROUP_SECP160R1) == 0)
- return NID_secp160r1;
+ { ASN1_OID_ID_EC_GROUP_SECP160R1, NID_secp160r1 },
#endif
#ifdef NID_secp160r2
- else if (der_heim_oid_cmp(oid, ASN1_OID_ID_EC_GROUP_SECP160R2) == 0)
- return NID_secp160r2;
+ { ASN1_OID_ID_EC_GROUP_SECP160R2, NID_secp160r2 },
#endif
+ /* XXX Add more! Add X25519! */
+};
+
+int
+_hx509_ossl_oid2nid(heim_oid *oid)
+{
+ size_t i;
+ for (i = 0; i < sizeof(oid2nid)/sizeof(oid2nid[0]); i++)
+ if (der_heim_oid_cmp(oid, oid2nid[i].oid) == 0)
+ return oid2nid[i].nid;
return NID_undef;
}
static int
-parse_ECParameters(hx509_context context,
- heim_octet_string *parameters, int *nid)
+ECParameters2nid(hx509_context context,
+ heim_octet_string *parameters,
+ int *nid)
{
ECParameters ecparam;
size_t size;
@@ -117,7 +129,7 @@ parse_ECParameters(hx509_context context,
return HX509_CRYPTO_SIG_INVALID_FORMAT;
}
- *nid = heim_oid2ecnid(&ecparam.u.namedCurve);
+ *nid = _hx509_ossl_oid2nid(&ecparam.u.namedCurve);
free_ECParameters(&ecparam);
if (*nid == NID_undef) {
hx509_set_error_string(context, 0, ret,
@@ -127,6 +139,39 @@ parse_ECParameters(hx509_context context,
return 0;
}
+#ifdef HAVE_OPENSSL_30
+static const EVP_MD *
+signature_alg2digest_evp_md(hx509_context context,
+ const AlgorithmIdentifier *digest_alg)
+{
+ if ((&digest_alg->algorithm == &asn1_oid_id_sha512 ||
+ der_heim_oid_cmp(&digest_alg->algorithm, &asn1_oid_id_sha512) == 0))
+ return EVP_sha512();
+ if ((&digest_alg->algorithm == &asn1_oid_id_sha384 ||
+ der_heim_oid_cmp(&digest_alg->algorithm, &asn1_oid_id_sha384) == 0))
+ return EVP_sha384();
+ if ((&digest_alg->algorithm == &asn1_oid_id_sha256 ||
+ der_heim_oid_cmp(&digest_alg->algorithm, &asn1_oid_id_sha256) == 0))
+ return EVP_sha256();
+ if ((&digest_alg->algorithm == &asn1_oid_id_secsig_sha_1 ||
+ der_heim_oid_cmp(&digest_alg->algorithm, &asn1_oid_id_secsig_sha_1) == 0))
+ return EVP_sha1();
+ if ((&digest_alg->algorithm == &asn1_oid_id_rsa_digest_md5 ||
+ der_heim_oid_cmp(&digest_alg->algorithm,
+ &asn1_oid_id_rsa_digest_md5) == 0))
+ return EVP_md5();
+
+ /*
+ * XXX Decode the `digest_alg->algorithm' OID and include it in the error
+ * message.
+ */
+ hx509_set_error_string(context, 0, EINVAL,
+ "Digest algorithm not found");
+ return NULL;
+}
+#endif
+
+
/*
*
@@ -140,6 +185,106 @@ ecdsa_verify_signature(hx509_context context,
const heim_octet_string *data,
const heim_octet_string *sig)
{
+#ifdef HAVE_OPENSSL_30
+ const AlgorithmIdentifier *digest_alg = sig_alg->digest_alg;
+ const EVP_MD *md = signature_alg2digest_evp_md(context, digest_alg);
+ const SubjectPublicKeyInfo *spi;
+ const char *curve_sn = NULL; /* sn == short name in OpenSSL parlance */
+ OSSL_PARAM params[2];
+ EVP_PKEY_CTX *pctx = NULL;
+ EVP_MD_CTX *mdctx = NULL;
+ EVP_PKEY *template = NULL;
+ EVP_PKEY *public = NULL;
+ const unsigned char *p;
+ size_t len;
+ char *curve_sn_dup = NULL;
+ int groupnid;
+ int ret = 0;
+
+ spi = &signer->tbsCertificate.subjectPublicKeyInfo;
+ if (der_heim_oid_cmp(&spi->algorithm.algorithm,
+ ASN1_OID_ID_ECPUBLICKEY) != 0)
+ hx509_set_error_string(context, 0,
+ ret = HX509_CRYPTO_SIG_INVALID_FORMAT,
+ /* XXX Include the OID in the message */
+ "Unsupported subjectPublicKey algorithm");
+ if (ret == 0)
+ ret = ECParameters2nid(context, spi->algorithm.parameters, &groupnid);
+ if (ret == 0 && (curve_sn = OBJ_nid2sn(groupnid)) == NULL)
+ hx509_set_error_string(context, 0,
+ ret = HX509_CRYPTO_SIG_INVALID_FORMAT,
+ "Could not resolve curve NID %d to its short name",
+ groupnid);
+ if (ret == 0 && (curve_sn_dup = strdup(curve_sn)) == NULL)
+ ret = hx509_enomem(context);
+ if (ret == 0 && (mdctx = EVP_MD_CTX_new()) == NULL)
+ ret = hx509_enomem(context);
+
+ /*
+ * In order for d2i_PublicKey() to work we need to create a template key
+ * that has the curve parameters for the subjectPublicKey.
+ *
+ * Or maybe we could learn to use the OSSL_DECODER(3) API. But this works,
+ * at least until OpenSSL deprecates d2i_PublicKey() and forces us to use
+ * OSSL_DECODER(3).
+ */
+ if (ret == 0) {
+ /*
+ * Apparently there's no error checking to be done here? Why does
+ * OSSL_PARAM_construct_utf8_string() want a non-const for the value?
+ * Is that a bug in OpenSSL?
+ */
+ params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
+ curve_sn_dup, 0);
+ params[1] = OSSL_PARAM_construct_end();
+
+ if ((pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL)) == NULL)
+ ret = hx509_enomem(context);
+ }
+ if (ret == 0 && EVP_PKEY_fromdata_init(pctx) != 1)
+ ret = hx509_enomem(context);
+ if (ret == 0 &&
+ EVP_PKEY_fromdata(pctx, &template,
+ OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS, params) != 1)
+ hx509_set_error_string(context, 0,
+ ret = HX509_CRYPTO_SIG_INVALID_FORMAT,
+ "Could not set up to parse key for curve %s",
+ curve_sn);
+
+ /* Finally we can decode the subjectPublicKey */
+ p = spi->subjectPublicKey.data;
+ len = spi->subjectPublicKey.length / 8;
+ if (ret == 0 &&
+ (public = d2i_PublicKey(EVP_PKEY_EC, &template, &p, len)) == NULL)
+ ret = HX509_CRYPTO_SIG_INVALID_FORMAT;
+
+ /* EVP_DigestVerifyInit() will allocate a new pctx */
+ EVP_PKEY_CTX_free(pctx);
+ pctx = NULL;
+
+ if (ret == 0 &&
+ EVP_DigestVerifyInit(mdctx, &pctx, md, NULL, public) != 1)
+ hx509_set_error_string(context, 0,
+ ret = HX509_CRYPTO_SIG_INVALID_FORMAT,
+ "Could not initialize "
+ "OpenSSL signature verification");
+ if (ret == 0 &&
+ EVP_DigestVerifyUpdate(mdctx, data->data, data->length) != 1)
+ hx509_set_error_string(context, 0,
+ ret = HX509_CRYPTO_SIG_INVALID_FORMAT,
+ "Could not initialize "
+ "OpenSSL signature verification");
+ if (ret == 0 &&
+ EVP_DigestVerifyFinal(mdctx, sig->data, sig->length) != 1)
+ hx509_set_error_string(context, 0,
+ ret = HX509_CRYPTO_SIG_INVALID_FORMAT,
+ "Signature verification failed");
+
+ EVP_MD_CTX_free(mdctx);
+ EVP_PKEY_free(template);
+ free(curve_sn_dup);
+ return ret;
+#else
const AlgorithmIdentifier *digest_alg;
const SubjectPublicKeyInfo *spi;
heim_octet_string digest;
@@ -153,28 +298,28 @@ ecdsa_verify_signature(hx509_context context,
digest_alg = sig_alg->digest_alg;
ret = _hx509_create_signature(context,
- NULL,
- digest_alg,
- data,
- NULL,
- &digest);
+ NULL,
+ digest_alg,
+ data,
+ NULL,
+ &digest);
if (ret)
- return ret;
+ return ret;
/* set up EC KEY */
spi = &signer->tbsCertificate.subjectPublicKeyInfo;
if (der_heim_oid_cmp(&spi->algorithm.algorithm, ASN1_OID_ID_ECPUBLICKEY) != 0)
- return HX509_CRYPTO_SIG_INVALID_FORMAT;
+ return HX509_CRYPTO_SIG_INVALID_FORMAT;
/*
* Find the group id
*/
- ret = parse_ECParameters(context, spi->algorithm.parameters, &groupnid);
+ ret = ECParameters2nid(context, spi->algorithm.parameters, &groupnid);
if (ret) {
- der_free_octet_string(&digest);
- return ret;
+ der_free_octet_string(&digest);
+ return ret;
}
/*
@@ -190,20 +335,21 @@ ecdsa_verify_signature(hx509_context context,
len = spi->subjectPublicKey.length / 8;
if (o2i_ECPublicKey(&key, &p, len) == NULL) {
- EC_KEY_free(key);
- return HX509_CRYPTO_SIG_INVALID_FORMAT;
+ EC_KEY_free(key);
+ return HX509_CRYPTO_SIG_INVALID_FORMAT;
}
ret = ECDSA_verify(-1, digest.data, digest.length,
- sig->data, sig->length, key);
+ sig->data, sig->length, key);
der_free_octet_string(&digest);
EC_KEY_free(key);
if (ret != 1) {
- ret = HX509_CRYPTO_SIG_INVALID_FORMAT;
- return ret;
+ ret = HX509_CRYPTO_SIG_INVALID_FORMAT;
+ return ret;
}
return 0;
+#endif
}
static int
@@ -215,6 +361,56 @@ ecdsa_create_signature(hx509_context context,
AlgorithmIdentifier *signatureAlgorithm,
heim_octet_string *sig)
{
+#ifdef HAVE_OPENSSL_30
+ const AlgorithmIdentifier *digest_alg = sig_alg->digest_alg;
+ const EVP_MD *md = signature_alg2digest_evp_md(context, digest_alg);
+ EVP_MD_CTX *mdctx = NULL;
+ EVP_PKEY_CTX *pctx = NULL;
+ const heim_oid *sig_oid;
+ int ret = 0;
+
+ sig->data = NULL;
+ sig->length = 0;
+ if (signer->ops && der_heim_oid_cmp(signer->ops->key_oid, ASN1_OID_ID_ECPUBLICKEY) != 0)
+ _hx509_abort("internal error passing private key to wrong ops");
+
+ sig_oid = sig_alg->sig_oid;
+ digest_alg = sig_alg->digest_alg;
+
+ if (signatureAlgorithm)
+ ret = _hx509_set_digest_alg(signatureAlgorithm, sig_oid,
+ "\x05\x00", 2);
+ mdctx = EVP_MD_CTX_new();
+ if (mdctx == NULL)
+ ret = hx509_enomem(context);
+ if (ret == 0 && EVP_DigestSignInit(mdctx, &pctx, md, NULL,
+ signer->private_key.ecdsa) != 1)
+ ret = HX509_CMS_FAILED_CREATE_SIGATURE;
+ if (ret == 0 && EVP_DigestSignUpdate(mdctx, data->data, data->length) != 1)
+ ret = HX509_CMS_FAILED_CREATE_SIGATURE;
+ if (ret == 0 && EVP_DigestSignFinal(mdctx, NULL, &sig->length) != 1)
+ ret = HX509_CMS_FAILED_CREATE_SIGATURE;
+ if (ret == 0 && (sig->data = malloc(sig->length)) == NULL)
+ ret = hx509_enomem(context);
+ if (ret == 0 && EVP_DigestSignFinal(mdctx, sig->data, &sig->length) != 1)
+ ret = HX509_CMS_FAILED_CREATE_SIGATURE;
+
+ if (ret == HX509_CMS_FAILED_CREATE_SIGATURE) {
+ /* XXX Extract error detail from OpenSSL */
+ hx509_set_error_string(context, 0, ret,
+ "ECDSA sign failed");
+ }
+
+ if (ret) {
+ if (signatureAlgorithm)
+ free_AlgorithmIdentifier(signatureAlgorithm);
+ free(sig->data);
+ sig->data = NULL;
+ sig->length = 0;
+ }
+ EVP_MD_CTX_free(mdctx);
+ return ret;
+#else
const AlgorithmIdentifier *digest_alg;
heim_octet_string indata;
const heim_oid *sig_oid;
@@ -222,7 +418,7 @@ ecdsa_create_signature(hx509_context context,
int ret;
if (signer->ops && der_heim_oid_cmp(signer->ops->key_oid, ASN1_OID_ID_ECPUBLICKEY) != 0)
- _hx509_abort("internal error passing private key to wrong ops");
+ _hx509_abort("internal error passing private key to wrong ops");
sig_oid = sig_alg->sig_oid;
digest_alg = sig_alg->digest_alg;
@@ -230,59 +426,63 @@ ecdsa_create_signature(hx509_context context,
if (signatureAlgorithm) {
ret = _hx509_set_digest_alg(signatureAlgorithm, sig_oid,
"\x05\x00", 2);
- if (ret) {
- hx509_clear_error_string(context);
- return ret;
- }
+ if (ret) {
+ hx509_clear_error_string(context);
+ return ret;
+ }
}
ret = _hx509_create_signature(context,
- NULL,
- digest_alg,
- data,
- NULL,
- &indata);
+ NULL,
+ digest_alg,
+ data,
+ NULL,
+ &indata);
if (ret)
- goto error;
+ goto error;
sig->length = ECDSA_size(signer->private_key.ecdsa);
sig->data = malloc(sig->length);
if (sig->data == NULL) {
- der_free_octet_string(&indata);
- ret = ENOMEM;
- hx509_set_error_string(context, 0, ret, "out of memory");
- goto error;
+ der_free_octet_string(&indata);
+ ret = ENOMEM;
+ hx509_set_error_string(context, 0, ret, "out of memory");
+ goto error;
}
siglen = sig->length;
ret = ECDSA_sign(-1, indata.data, indata.length,
- sig->data, &siglen, signer->private_key.ecdsa);
+ sig->data, &siglen, signer->private_key.ecdsa);
der_free_octet_string(&indata);
if (ret != 1) {
- ret = HX509_CMS_FAILED_CREATE_SIGATURE;
- hx509_set_error_string(context, 0, ret,
- "ECDSA sign failed: %d", ret);
- goto error;
+ ret = HX509_CMS_FAILED_CREATE_SIGATURE;
+ hx509_set_error_string(context, 0, ret,
+ "ECDSA sign failed: %d", ret);
+ goto error;
}
if (siglen > sig->length)
- _hx509_abort("ECDSA signature prelen longer the output len");
+ _hx509_abort("ECDSA signature prelen longer the output len");
sig->length = siglen;
return 0;
- error:
+error:
if (signatureAlgorithm)
- free_AlgorithmIdentifier(signatureAlgorithm);
+ free_AlgorithmIdentifier(signatureAlgorithm);
return ret;
+#endif
}
static int
ecdsa_available(const hx509_private_key signer,
const AlgorithmIdentifier *sig_alg)
{
+#ifdef HAVE_OPENSSL_30
const struct signature_alg *sig;
- const EC_GROUP *group;
+ size_t group_name_len = 0;
+ char group_name_buf[96];
+ EC_GROUP *group = NULL;
BN_CTX *bnctx = NULL;
BIGNUM *order = NULL;
int ret = 0;
@@ -291,34 +491,75 @@ ecdsa_available(const hx509_private_key signer,
_hx509_abort("internal error passing private key to wrong ops");
sig = _hx509_find_sig_alg(&sig_alg->algorithm);
-
if (sig == NULL || sig->digest_size == 0)
return 0;
+ if (EVP_PKEY_get_group_name(signer->private_key.ecdsa, group_name_buf,
+ sizeof(group_name_buf),
+ &group_name_len) != 1 ||
+ group_name_len >= sizeof(group_name_buf)) {
+ return 0;
+ }
+ group = EC_GROUP_new_by_curve_name(OBJ_txt2nid(group_name_buf));
+ bnctx = BN_CTX_new();
+ order = BN_new();
+ if (group && bnctx && order &&
+ EC_GROUP_get_order(group, order, bnctx) == 1)
+ ret = 1;
+
+#if 0
+ /*
+ * If anything, require a digest at least as wide as the EC key size
+ *
+ * if (BN_num_bytes(order) > sig->digest_size)
+ * ret = 0;
+ */
+#endif
+
+ BN_CTX_free(bnctx);
+ BN_clear_free(order);
+ EC_GROUP_free(group);
+ return ret;
+#else
+ const struct signature_alg *sig;
+ const EC_GROUP *group;
+ BN_CTX *bnctx = NULL;
+ BIGNUM *order = NULL;
+ int ret = 0;
+
+ if (der_heim_oid_cmp(signer->ops->key_oid, &asn1_oid_id_ecPublicKey) != 0)
+ _hx509_abort("internal error passing private key to wrong ops");
+
+ sig = _hx509_find_sig_alg(&sig_alg->algorithm);
+
+ if (sig == NULL || sig->digest_size == 0)
+ return 0;
+
group = EC_KEY_get0_group(signer->private_key.ecdsa);
if (group == NULL)
- return 0;
+ return 0;
bnctx = BN_CTX_new();
order = BN_new();
if (order == NULL)
- goto err;
+ goto err;
if (EC_GROUP_get_order(group, order, bnctx) != 1)
- goto err;
+ goto err;
#if 0
/* If anything, require a digest at least as wide as the EC key size */
if (BN_num_bytes(order) > sig->digest_size)
#endif
- ret = 1;
+ ret = 1;
err:
if (bnctx)
- BN_CTX_free(bnctx);
+ BN_CTX_free(bnctx);
if (order)
- BN_clear_free(order);
+ BN_clear_free(order);
- return ret;
+ return ret;
+#endif
}
static int
@@ -347,55 +588,119 @@ ecdsa_private_key_import(hx509_context context,
hx509_key_format_t format,
hx509_private_key private_key)
{
+#ifdef HAVE_OPENSSL_30
+ const unsigned char *p = data;
+ EVP_PKEY *key = NULL;
+ int ret = 0;
+
+ switch (format) {
+ case HX509_KEY_FORMAT_PKCS8:
+ key = d2i_PrivateKey(EVP_PKEY_EC, NULL, &p, len);
+ if (key == NULL) {
+ hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
+ "Failed to parse EC private key");
+ return HX509_PARSING_KEY_FAILED;
+ }
+ break;
+
+ default:
+ return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED;
+ }
+
+ /*
+ * We used to have to call EC_KEY_new(), then EC_KEY_set_group() the group
+ * (curve) on the resulting EC_KEY _before_ we could d2i_ECPrivateKey() the
+ * key, but that's all deprecated in OpenSSL 3.0.
+ *
+ * In fact, it's not clear how ever to assign a group to a private key,
+ * but that's what the documentation for d2i_PrivateKey() says: that
+ * its `EVP_PKEY **' argument must be non-NULL pointing to a key that
+ * has had the group set.
+ *
+ * However, from code inspection it's clear that when the ECParameters
+ * are present in the private key payload passed to d2i_PrivateKey(),
+ * the group will be taken from that.
+ *
+ * What we'll do is that if we have `keyai->parameters' we'll check if the
+ * key we got is for the same group.
+ */
+ if (keyai->parameters) {
+ size_t gname_len = 0;
+ char buf[96];
+ int got_group_nid = NID_undef;
+ int want_groupnid = NID_undef;
+
+ ret = ECParameters2nid(context, keyai->parameters, &want_groupnid);
+ if (ret == 0 &&
+ (EVP_PKEY_get_group_name(key, buf, sizeof(buf), &gname_len) != 1 ||
+ gname_len >= sizeof(buf)))
+ ret = HX509_ALG_NOT_SUPP;
+ if (ret == 0)
+ got_group_nid = OBJ_txt2nid(buf);
+ if (ret == 0 &&
+ (got_group_nid == NID_undef || want_groupnid != got_group_nid))
+ ret = HX509_ALG_NOT_SUPP;
+ }
+
+ if (ret == 0) {
+ private_key->private_key.ecdsa = key;
+ private_key->signature_alg = ASN1_OID_ID_ECDSA_WITH_SHA256;
+ key = NULL;
+ }
+
+ EVP_PKEY_free(key);
+ return ret;
+#else
const unsigned char *p = data;
EC_KEY **pkey = NULL;
EC_KEY *key;
if (keyai->parameters) {
- EC_GROUP *group;
- int groupnid;
- int ret;
-
- ret = parse_ECParameters(context, keyai->parameters, &groupnid);
- if (ret)
- return ret;
-
- key = EC_KEY_new();
- if (key == NULL)
- return ENOMEM;
-
- group = EC_GROUP_new_by_curve_name(groupnid);
- if (group == NULL) {
- EC_KEY_free(key);
- return ENOMEM;
- }
- EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
- if (EC_KEY_set_group(key, group) == 0) {
- EC_KEY_free(key);
- EC_GROUP_free(group);
- return ENOMEM;
- }
- EC_GROUP_free(group);
- pkey = &key;
+ EC_GROUP *group;
+ int groupnid;
+ int ret;
+
+ ret = ECParameters2nid(context, keyai->parameters, &groupnid);
+ if (ret)
+ return ret;
+
+ key = EC_KEY_new();
+ if (key == NULL)
+ return ENOMEM;
+
+ group = EC_GROUP_new_by_curve_name(groupnid);
+ if (group == NULL) {
+ EC_KEY_free(key);
+ return ENOMEM;
+ }
+ EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
+ if (EC_KEY_set_group(key, group) != 1) {
+ EC_KEY_free(key);
+ EC_GROUP_free(group);
+ return ENOMEM;
+ }
+ EC_GROUP_free(group);
+ pkey = &key;
}
switch (format) {
case HX509_KEY_FORMAT_DER:
- private_key->private_key.ecdsa = d2i_ECPrivateKey(pkey, &p, len);
- if (private_key->private_key.ecdsa == NULL) {
- hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
- "Failed to parse EC private key");
- return HX509_PARSING_KEY_FAILED;
- }
- private_key->signature_alg = ASN1_OID_ID_ECDSA_WITH_SHA256;
- break;
+ private_key->private_key.ecdsa = d2i_ECPrivateKey(pkey, &p, len);
+ if (private_key->private_key.ecdsa == NULL) {
+ hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
+ "Failed to parse EC private key");
+ return HX509_PARSING_KEY_FAILED;
+ }
+ private_key->signature_alg = ASN1_OID_ID_ECDSA_WITH_SHA256;
+ break;
default:
- return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED;
+ return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED;
}
return 0;
+#endif
}
static int
diff --git a/third_party/heimdal/lib/hx509/crypto.c b/third_party/heimdal/lib/hx509/crypto.c
index 8d368ed9c4d..05f694b41c5 100644
--- a/third_party/heimdal/lib/hx509/crypto.c
+++ b/third_party/heimdal/lib/hx509/crypto.c
@@ -1304,10 +1304,27 @@ hx509_parse_private_key(hx509_context context,
*private_key = NULL;
- if (format == HX509_KEY_FORMAT_PKCS8) {
+ ops = hx509_find_private_alg(&keyai->algorithm);
+ if (ops == NULL) {
+ hx509_clear_error_string(context);
+ return HX509_SIG_ALG_NO_SUPPORTED;
+ }
+
+ ret = hx509_private_key_init(private_key, ops, NULL);
+ if (ret) {
+ hx509_set_error_string(context, 0, ret, "out of memory");
+ return ret;
+ }
+
+ ret = (*ops->import)(context, keyai, data, len, format, *private_key);
+ if (ret)
+ hx509_private_key_free(private_key);
+
+ if (ret && format == HX509_KEY_FORMAT_PKCS8) {
PKCS8PrivateKeyInfo ki;
hx509_private_key key;
+ /* Re-enter to try parsing the DER-encoded key from PKCS#8 envelope */
ret = decode_PKCS8PrivateKeyInfo(data, len, &ki, NULL);
if (ret) {
hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
@@ -1315,39 +1332,18 @@ hx509_parse_private_key(hx509_context context,
"key");
return HX509_PARSING_KEY_FAILED;
}
-
- /* Re-enter to parse DER-encoded key from PKCS#8 envelope */
ret = hx509_parse_private_key(context, &ki.privateKeyAlgorithm,
ki.privateKey.data, ki.privateKey.length,
HX509_KEY_FORMAT_DER, &key);
free_PKCS8PrivateKeyInfo(&ki);
if (ret) {
- hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
- "Failed to parse RSA key from PKCS#8 "
+ hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
+ "Failed to parse RSA key from PKCS#8 "
"envelope");
- return HX509_PARSING_KEY_FAILED;
+ return HX509_PARSING_KEY_FAILED;
}
-
*private_key = key;
- return ret;
- }
-
- ops = hx509_find_private_alg(&keyai->algorithm);
- if (ops == NULL) {
- hx509_clear_error_string(context);
- return HX509_SIG_ALG_NO_SUPPORTED;
}
-
- ret = hx509_private_key_init(private_key, ops, NULL);
- if (ret) {
- hx509_set_error_string(context, 0, ret, "out of memory");
- return ret;
- }
-
- ret = (*ops->import)(context, keyai, data, len, format, *private_key);
- if (ret)
- hx509_private_key_free(private_key);
-
return ret;
}
diff --git a/third_party/heimdal/lib/hx509/hx509.h b/third_party/heimdal/lib/hx509/hx509.h
index 75d64734b27..6bd36e98b15 100644
--- a/third_party/heimdal/lib/hx509/hx509.h
+++ b/third_party/heimdal/lib/hx509/hx509.h
@@ -162,6 +162,7 @@ typedef enum {
/* flags to hx509_certs_store */
#define HX509_CERTS_STORE_NO_PRIVATE_KEYS 0x04
+#define HX509_CERTS_STORE_NO_ROOTS 0x08
/* flags to hx509_set_error_string */
diff --git a/third_party/heimdal/lib/hx509/hxtool-commands.in b/third_party/heimdal/lib/hx509/hxtool-commands.in
index 279095d270e..1bd0119ad72 100644
--- a/third_party/heimdal/lib/hx509/hxtool-commands.in
+++ b/third_party/heimdal/lib/hx509/hxtool-commands.in
@@ -363,6 +363,21 @@ command = {
argument = "password"
help = "password, prompter, or environment"
}
+ option = {
+ long = "append"
+ type = "flag"
+ help = "append source to destination"
+ }
+ option = {
+ long = "root-certs"
+ type = "-flag"
+ help = "do not copy root certificates"
+ }
+ option = {
+ long = "private-keys"
+ type = "-flag"
+ help = "do not copy private keys"
+ }
min_args="2"
argument="in-certificates-1 ... out-certificate"
help = "Copy in certificates stores into out certificate store"
diff --git a/third_party/heimdal/lib/hx509/hxtool.1 b/third_party/heimdal/lib/hx509/hxtool.1
index 377500784ec..040573f4cde 100644
--- a/third_party/heimdal/lib/hx509/hxtool.1
+++ b/third_party/heimdal/lib/hx509/hxtool.1
@@ -63,24 +63,59 @@ Supported commands:
.It help
.It list-oids
.It verify
+Verify a certificate and its certification path up to a trust
+anchor, possibly checking CRLs.
.It print
+Prints a human-readable rendering of certificates in a store.
+See
+.Sx CERTIFICATE STORES.
.It validate
+Validate a certificate (but not a full chain).
.It certificate-copy, cc
+Copy ceritificates and possibly private keys from one store to
+another.
+See
+.Sx CERTIFICATE STORES.
.It ocsp-fetch
+Fetch an OCSP response.
.It ocsp-verify
+Fetch an OCSP response chain.
.It ocsp-print
+Prints a human-readable rendering of an OCSP response chain.
.It revoke-print
+Prints a human-readable rendering of a CRL or OCSP response
+chain.
.It generate-key
+Generates a private key.
.It request-create
+Generates a Certificate Signing Request (CSR).
.It request-print
+Prints a human-readable rendering of a CSR.
.It query
+Queries a certificate store.
.It info
+Prints information about supported algorithms.
.It random-data
+Outputs entropy using a random number generator.
.It crypto-available
+Tests if a cryptographic algorithm is available.
.It crypto-select
+Selects a supported cryptographic algorithm given a peer's
+capabilities.
.It hex
+Hex-encode/decode utility.
.It certificate-sign, cert-sign, issue-certificate, ca
+Issue a certificate.
.It crl-sign
+Sign a CRL.
+.It cms-create-sd, cms-sign
+Created a CMS SignedData.
+.It cms-verify-sd
+Verifies a CMS SignedData.
+.It cms-unenvelope
+Extracts enveloped data from a CMS SignedData.
+.It cms-envelope
+Creates an enveloped CMS SignedData.
.El
Other sub-commands reported by the
.Nm help
@@ -89,48 +124,80 @@ sub-command are not stable or fully supported at this time.
Stores of certificates and/or keys have string names that can be
used with
.Nm 's
-commands.
-Sub-commands use these certificate store names to refer to files
-and tokens where keys and/or certificates are to be found or
-written.
+commands as well as in various configuration parameters and
+command-line arguments of Heimdal's Kerberos implementation (for
+PKINIT).
+.Pp
For example,
-.Sq FILE:/path/to/some/file .
+.Ql FILE:/path/to/file ,
+.Ql PEM-FILE:/path/to/file ,
+.Ql DER-FILE:/path/to/file ,
+etc.
+See below for a full list of store types.
.Pp
-Use the
-.Nm certificate-copy
-command to copy certificates from one store to another.
-This is useful for, e.g., converting DER files to PEM or
-vice-versa.
+A certificate store name starts with a store TYPE followed by a
+colon followed by a name of form specific to that store type.
+.Pp
+Private keys can be stored in the same stores as the certificates
+that certify their public keys.
.Pp
-Heimdal supports a variety of certificate and key store types:
+Private keys can also be stored in separate files, but still be
+referenced in one certificate store name by joining two with a
+comma:
+.Ql FILE:/path/to/certificate,/path/to/private/key
+.
+.Pp
+Heimdal supports a variety of certificate and private key store
+types:
.Bl -tag -width Ds -offset indent
.It PEM-FILE:/path
-If writing, PEM will be written.
-If reading, PEM will be expected.
+If writing, PEM will be written (private keys may be written in
+algorithm-specific formats or in PKCS#8).
+If reading, PEM will be expected (private keys may be in
+algorithm-specific formats or in PKCS#8).
.It DER-FILE:/path
If writing, DER will be written.
If reading, DER will be expected.
+Private keys will be in algorithm-specific formats.
.It FILE:/path
-If writing, PEM will be written.
-If reading, PEM or DER will be detected.
+If writing, PEM will be written as if
+.Ql PEM-FILE
+had been used.
+If reading, PEM or DER will be detected and read as if
+.Ql PEM-FILE
+or
+.Ql DER-FILE
+had been used.
.It PKCS12:/path
-Barely supported at this time.
+If writing, PKCS#12 will be written.
+If reading, PKCS#12 will be expected.
+Note that PKCS#12 support is currently very limited.
.It DIR:/path
OpenSSL-style hashed directory of trust anchors.
-.It MEMORY:name
-An in-memory only store, usually never used in
-.NM 's
-commands.
.It KEYCHAIN:system-anchors
On OS X this refers to the system's trust anchors.
.It KEYCHAIN:FILE:/path
On OS X this refers to an OS X keychain at the given path.
+.It PKCS11:/path/to/shared/object[,slot=NUMBER]
+Loads the given PKCS#11 provider object and uses the token at the
+given slot number, or else the first token found.
.It NULL:
An empty store.
-.It PKCS11:/path/to/shared/object,slot=NUMBER
-Loads the given PKCS#11 provider object and uses the token at the
-given slot number.
+.It MEMORY:name
+An in-memory only, ephemeral store, usually never used in
+.NM 's
+commands.
+The MEMORY store name exists primarily for internal
+.Sq hx509
+APIs.
.El
+.Pp
+Use the
+.Nm certificate-copy
+command to copy certificates from one store to another.
+This is useful for, e.g., converting DER files to PEM or
+vice-versa, removing private keys, adding certificate chains,
+and removing root certificates from chains.
.Sh CERTIFICATES
You can validate a certificate with the
.Nm validate
@@ -149,17 +216,17 @@ sub-command:
.Pp
Options:
.Bl -tag -width Ds -offset indent
-.Op Fl Fl content
-.Op Fl Fl info
-.Op Fl Fl never-fail
-.Op Fl Fl pass=password
-.Op Fl Fl raw-json
+.It Fl Fl content
+.It Fl Fl info
+.It Fl Fl never-fail
+.It Fl Fl pass=password
+.It Fl Fl raw-json
.El
.Pp
The
.Fl Fl pass=password
-option is for PKCS#12 and PKCS#11 stores, and if needed and not
-given, will be prompted for.
+option is for PKCS#8 (PEM), PKCS#12 and PKCS#11 stores, and if
+needed and not given, will be prompted for.
Note that it's not secure to pass passwords as command-line
arguments on multi-tenant systems.
.Pp
@@ -176,7 +243,14 @@ sub-command will generate a key.
.Sh CERTIFICATE SIGNING REQUESTS
The
.Nm request-create
-sub-command will create a CSR.
+sub-command will create a CSR, and has support for requesting
+subject alternative names and extended key usage extensions.
+See its
+.Fl Fl help
+option, and see
+.Sx EXAMPLES
+below.
+.Pp
The
.Nm request-print
sub-command will display a CSR.
@@ -203,5 +277,104 @@ The
.Nm crl-sign
sub-command will add certificates to a certificate revocation
list.
+.Sh EXAMPLES
+Generate an RSA key:
+.Bd -literal -offset indent
+hxtool generate-key --type=rsa --key-bits=4096 PEM-FILE:key.pem
+.Ed
+.Pp
+Create a CSR (with an empty name) for some key:
+.Bd -literal -offset indent
+hxtool request-create --subject= --key=FILE:key.pem csr.der
+.Ed
+.Pp
+Generate a key and create a CSR (with an empty name) for it:
+.Bd -literal -offset indent
+hxtool request-create \\
+ --subject= \\
+ --generate-key=rsa \\
+ --key-bits=4096 \\
+ --key=FILE:key.pem \\
+ csr.der
+.Ed
+.Pp
+Generate a key and create a CSR with an empty name but also
+requesting a specific dNSName subject alternative name (SAN) for
+it:
+.Bd -literal -offset indent
+hxtool request-create \\
+ --subject= \\
+ --generate-key=rsa \\
+ --dnsname=foo.test.h5l.se \\
+ --key=FILE:key.pem \\
+ csr.der
+.Ed
+.Pp
+Print a CSR:
+.Bd -literal -offset indent
+hxtool request-print csr.der
+.Ed
+which outputs:
+.Bd -literal -offset indent
+request print
+PKCS#10 CertificationRequest:
+ name:
+ san: dNSName: foo.test.h5l.se
+.Ed
+.Pp
+Issue a end-entity certificate for an HTTPS server given a CSR:
+.Bd -literal -offset indent
+hxtool issue-certificate \\
+ --type=https-server \\
+ --subject= \\
+ --hostname=foo.test.h5l.se \\
+ --ca-certificate=FILE:cacert.pem \\
+ --ca-private-key=FILE:cakey.pem \\
+ --req=PKCS10:csr.der \\
+ --certificate=PEM-FILE:ee.pem
+.Ed
+.Pp
+Add a chain to a PEM file:
+.Bd -literal -offset indent
+hxtool copy-certificiate \\
+ --no-private-keys \\
+ --no-root-certs \\
+ FILE:ca.pem FILE:ee.pem
+.Ed
+.Pp
+Create a self-signed end-entity certificate for an HTTPS server:
+.Bd -literal -offset indent
+hxtool issue-certificate \\
+ --self-signed \\
+ --type=https-server \\
+ --subject= \\
+ --hostname=foo.test.h5l.se \\
+ --ca-private-key=FILE:key.pem \\
+ --certificate-private-key=FILE:key.pem \\
+ --certificate=PEM-FILE:cert.pem
+.Ed
+.Pp
+Create a root certification authority certificate:
+.Bd -literal -offset indent
+hxtool issue-certificate \\
+ --issue-ca \\
+ --self-signed \\
+ --subject=CN=SomeRootCA \\
+ --ca-private-key=FILE:rootkey.pem \\
+ --certificate=PEM-FILE:rootcert.pem
+.Ed
+.Pp
+Create an intermediate certification authority certificate from a
+CSR:
+.Bd -literal -offset indent
+hxtool issue-certificate \\
+ --type=https-server \\
+ --subject=CN=SomeIntermediateCA \\
+ --ca-certificate=FILE:parent-cert.pem \\
+ --ca-private-key=FILE:parent-key.pem \\
+ --req=PKCS10:csr.der \\
+ --certificate=PEM-FILE:intermediate.pem
+.Ed
+.Pp
.Sh SEE ALSO
.Xr openssl 1
diff --git a/third_party/heimdal/lib/hx509/hxtool.c b/third_party/heimdal/lib/hx509/hxtool.c
index aa9e279c81c..866e4bfcab2 100644
--- a/third_party/heimdal/lib/hx509/hxtool.c
+++ b/third_party/heimdal/lib/hx509/hxtool.c
@@ -861,11 +861,26 @@ certificate_copy(struct certificate_copy_options *opt, int argc, char **argv)
hx509_certs certs;
hx509_lock inlock, outlock = NULL;
char *sn;
+ int flags = 0;
+ int store_flags = 0;
int ret;
hx509_lock_init(context, &inlock);
lock_strings(inlock, &opt->in_pass_strings);
+ if (!opt->root_certs_flag)
+ /*
+ * We're probably copying an EE cert, its issuer, and all intermediates
+ * up to and excluding the root.
+ */
+ store_flags |= HX509_CERTS_STORE_NO_ROOTS;
+
+ if (!opt->private_keys_flag) {
+ /* Neither read nor store private keys */
+ store_flags |= HX509_CERTS_NO_PRIVATE_KEYS;
+ flags |= HX509_CERTS_NO_PRIVATE_KEYS;
+ }
+
if (opt->out_pass_string) {
hx509_lock_init(context, &outlock);
ret = hx509_lock_command_string(outlock, opt->out_pass_string);
@@ -874,25 +889,53 @@ certificate_copy(struct certificate_copy_options *opt, int argc, char **argv)
opt->out_pass_string, ret);
}
+ if (argc < 2)
+ errx(1, "hxtool copy-certificate requires at least two positional "
+ "arguments");
+
+ /*
+ * The _last_ positional argument is the destination store. Because we use
+ * HX509_CERTS_CREATE we'll ignore its contents and then truncate to write
+ * it (well, if it's a file; see key store plugins).
+ *
+ * But note that the truncation doesn't happen until we call
+ * hx509_certs_store(), which means we still have a chance to _read_ this
+ * store. That means that one can write this:
+ *
+ * hxtool cc FILE:b FILE:a FILE:b
+ *
+ * to notionally append FILE:a to FILE:b. Still, we'll have an option to
+ * do the append anyways:
+ *
+ * hxtool cc --append FILE:a FILE:b
+ */
sn = fix_store_name(context, argv[argc - 1], "FILE");
ret = hx509_certs_init(context, sn,
- HX509_CERTS_CREATE, inlock, &certs);
+ HX509_CERTS_CREATE | flags, inlock, &certs);
if (ret)
hx509_err(context, 1, ret, "hx509_certs_init %s", sn);
+
+ if (opt->append_flag) {
+ /* Append == read the certs in the dst prior to doing anything else */
+ ret = hx509_certs_append(context, certs, inlock, sn);
+ if (ret)
+ hx509_err(context, 1, ret, "hx509_certs_append %s", sn);
+ }
free(sn);
+ /*
+ * Read all the certificate stores in all but the last positional argument.
+ */
while(argc-- > 1) {
- int retx;
-
sn = fix_store_name(context, argv[0], "FILE");
- retx = hx509_certs_append(context, certs, inlock, sn);
- if (retx)
- hx509_err(context, 1, retx, "hx509_certs_append %s", sn);
+ ret = hx509_certs_append(context, certs, inlock, sn);
+ if (ret)
+ hx509_err(context, 1, ret, "hx509_certs_append %s", sn);
free(sn);
argv++;
}
- ret = hx509_certs_store(context, certs, 0, outlock);
+ ret = hx509_certs_store(context, certs, store_flags, outlock);
if (ret)
hx509_err(context, 1, ret, "hx509_certs_store");
@@ -1450,7 +1493,9 @@ request_create(struct request_create_options *opt, int argc, char **argv)
opt->key_bits_integer,
&signer);
- hx509_request_init(context, &req);
+ ret = hx509_request_init(context, &req);
+ if (ret)
+ hx509_err(context, 1, ret, "Could not initialize CSR context");
if (opt->subject_string) {
hx509_name name = NULL;
diff --git a/third_party/heimdal/lib/hx509/ks_file.c b/third_party/heimdal/lib/hx509/ks_file.c
index 880668b4561..6d8c77bd240 100644
--- a/third_party/heimdal/lib/hx509/ks_file.c
+++ b/third_party/heimdal/lib/hx509/ks_file.c
@@ -550,6 +550,14 @@ store_func(hx509_context context, void *ctx, hx509_cert c)
heim_octet_string data;
int ret = 0;
+ if ((sc->store_flags & HX509_CERTS_STORE_NO_ROOTS)) {
+ int self_signed = 0;
+
+ ret = hx509_cert_is_self_signed(context, c, &self_signed);
+ if (ret || self_signed)
+ return ret;
+ }
+
if (hx509_cert_have_private_key_only(c)) {
data.length = 0;
data.data = NULL;
diff --git a/third_party/heimdal/lib/hx509/ks_p12.c b/third_party/heimdal/lib/hx509/ks_p12.c
index 6fd7cd10526..1e9a92a4ff5 100644
--- a/third_party/heimdal/lib/hx509/ks_p12.c
+++ b/third_party/heimdal/lib/hx509/ks_p12.c
@@ -91,14 +91,14 @@ keyBag_parser(hx509_context context,
if (ret)
return ret;
- _hx509_collector_private_key_add(context,
- c,
- &ki.privateKeyAlgorithm,
- NULL,
- &ki.privateKey,
- os);
+ ret = _hx509_collector_private_key_add(context,
+ c,
+ &ki.privateKeyAlgorithm,
+ NULL,
+ &ki.privateKey,
+ os);
free_PKCS8PrivateKeyInfo(&ki);
- return 0;
+ return ret;
}
static int
@@ -525,6 +525,14 @@ store_func(hx509_context context, void *d, hx509_cert c)
size_t size;
int ret;
+ if ((ctx->store_flags & HX509_CERTS_STORE_NO_ROOTS)) {
+ int is_root = 0;
+
+ ret = hx509_cert_is_root(context, c, &is_root);
+ if (ret || is_root)
+ return ret;
+ }
+
memset(&os, 0, sizeof(os));
memset(&cb, 0, sizeof(cb));
diff --git a/third_party/heimdal/lib/hx509/libhx509-exports.def b/third_party/heimdal/lib/hx509/libhx509-exports.def
index 745ad5a4d80..81783ff7c34 100644
--- a/third_party/heimdal/lib/hx509/libhx509-exports.def
+++ b/third_party/heimdal/lib/hx509/libhx509-exports.def
@@ -19,6 +19,11 @@ EXPORTS
_hx509_make_pkinit_san
_hx509_map_file_os
_hx509_name_from_Name
+ _hx509_private_key_export
+ _hx509_private_key_exportable
+ _hx509_private_key_get_internal
+ _hx509_private_key_oid
+ _hx509_private_key_ref
hx509_private_key2SPKI
hx509_private_key_free
_hx509_private_key_ref
@@ -41,6 +46,7 @@ EXPORTS
_hx509_private_key_get_internal
_hx509_private_key_oid
_hx509_private_key_ref
+ hx509_request_eku_authorized_p
hx509_request_free
hx509_request_get_eku
hx509_request_get_exts
@@ -55,8 +61,11 @@ EXPORTS
hx509_request_print
hx509_request_set_SubjectPublicKeyInfo
hx509_request_add_email
+ hx509_request_reject_eku
+ hx509_request_reject_san
hx509_request_set_name
hx509_request_set_ku
+ hx509_request_san_authorized_p
hx509_request_to_pkcs10
_hx509_unmap_file_os
_hx509_write_file
@@ -122,6 +131,9 @@ EXPORTS
hx509_cert_init
hx509_cert_init_data
hx509_cert_init_private_key
+ hx509_cert_is_ca
+ hx509_cert_is_root
+ hx509_cert_is_self_signed
hx509_cert_keyusage_print
hx509_cert_ref
hx509_cert_set_friendly_name
diff --git a/third_party/heimdal/lib/hx509/req.c b/third_party/heimdal/lib/hx509/req.c
index c8fa42e5f99..d0bfe91a948 100644
--- a/third_party/heimdal/lib/hx509/req.c
+++ b/third_party/heimdal/lib/hx509/req.c
@@ -669,6 +669,8 @@ hx509_request_to_pkcs10(hx509_context context,
Attribute *a = NULL; /* Quiet VC */
heim_any extns;
+ extns.data = NULL;
+ extns.length = 0;
r.certificationRequestInfo.attributes =
calloc(1, sizeof(r.certificationRequestInfo.attributes[0]));
if (r.certificationRequestInfo.attributes == NULL)
@@ -977,7 +979,7 @@ abitstring_check(abitstring a, size_t n, int idx)
size_t bytes;
if (idx >= n)
- return EINVAL;
+ return HX509_NO_ITEM;
bytes = (idx + 1) / CHAR_BIT + (((idx + 1) % CHAR_BIT) ? 1 : 0);
if (a->feat_bytes < bytes)
@@ -996,7 +998,7 @@ abitstring_set(abitstring a, size_t n, int idx)
size_t bytes;
if (idx >= n)
- return EINVAL;
+ return HX509_NO_ITEM;
bytes = n / CHAR_BIT + ((n % CHAR_BIT) ? 1 : 0);
if (a->feat_bytes < bytes) {
@@ -1026,7 +1028,7 @@ abitstring_reset(abitstring a, size_t n, int idx)
size_t bytes;
if (idx >= n)
- return EINVAL;
+ return HX509_NO_ITEM;
bytes = (idx + 1) / CHAR_BIT + (((idx + 1) % CHAR_BIT) ? 1 : 0);
if (a->feat_bytes >= bytes &&
diff --git a/third_party/heimdal/lib/hx509/revoke.c b/third_party/heimdal/lib/hx509/revoke.c
index 18b2f8f8f96..4cfdaaee48c 100644
--- a/third_party/heimdal/lib/hx509/revoke.c
+++ b/third_party/heimdal/lib/hx509/revoke.c
@@ -600,18 +600,15 @@ load_crl(hx509_context context, const char *path, time_t *t, CRLCertificateList
FILE *f;
int ret;
+ *t = 0;
memset(crl, 0, sizeof(*crl));
-
- ret = stat(path, &sb);
- if (ret)
- return errno;
-
- *t = sb.st_mtime;
if ((f = fopen(path, "r")) == NULL)
return errno;
rk_cloexec_file(f);
+ if (fstat(fileno(f), &sb) == 0)
+ *t = sb.st_mtime;
ret = hx509_pem_read(context, f, crl_parser, crl);
fclose(f);
diff --git a/third_party/heimdal/lib/hx509/test_req.in b/third_party/heimdal/lib/hx509/test_req.in
index a070b1dd9df..9288df6738f 100644
--- a/third_party/heimdal/lib/hx509/test_req.in
+++ b/third_party/heimdal/lib/hx509/test_req.in
@@ -131,5 +131,33 @@ Certificate Request:
email:foo@test.h5l.se, DNS:nutcracker.test.h5l.se, DNS:foo.nutcracker.test.h5l.se, othername:<unsupported>, othername:<unsupported>, Registered ID:1.2.3.4.5.6.9
Signature Algorithm: sha256WithRSAEncryption
EOF
- diff -w "${objdir}/expected" "${objdir}/actual" || exit 1
+ if ! diff -u -w "${objdir}/expected" "${objdir}/actual"; then
+ cat > "$objdir/expected" <<EOF
+Certificate Request:
+ Data:
+ Version: $v (0x0)
+ Subject: DC = se, DC = su, DC = it, CN = Love
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ ${k}Public-Key: (1024 bit)
+ Modulus:
+ 00:c2:aa:a2:42:b7:5b:99:a3:fd:ba:f0:9b:75:db:
+ ef:3c:9b:8c:cf:63:5f:46:d8:95:be:09:4a:a7:76:
+ 79:77:61:30:ef:0b:98:d2:47:ea:9c:09:b9:b9:b7:
+ 15:ac:4b:9c:2d:3f:f0:d9:99:9d:4d:5a:68:67:24:
+ 58:5e:65:60:13:9f:4d:dc:2f:03:1d:cd:e9:b6:33:
+ c2:5c:c6:de:c9:93:6c:ec:8d:9a:67:0e:dd:31:20:
+ ac:91:39:7a:c1:8f:39:65:ff:b3:1f:cf:7a:aa:79:
+ 8b:ed:eb:ad:a0:be:01:10:4c:5a:a7:47:1d:c6:ee:
+ 79:39:5c:c7:11:6c:b9:e7:2b
+ Exponent: 65537 (0x10001)
+ Attributes:
+ Requested Extensions:
+ X509v3 Extended Key Usage: critical
+ 1.2.3.4.5.6.7, 1.2.3.4.5.6.8, 1.2.3.4.5.6.10
+ X509v3 Subject Alternative Name:
+ email:foo@test.h5l.se, DNS:nutcracker.test.h5l.se, DNS:foo.nutcracker.test.h5l.se, othername: 1.3.6.1.5.2.2::<unsupported>, othername: 1.3.6.1.5.2.2::<unsupported>, Registered ID:1.2.3.4.5.6.9
+ Signature Algorithm: sha256WithRSAEncryption
+EOF
+ fi
fi
diff --git a/third_party/heimdal/lib/hx509/version-script.map b/third_party/heimdal/lib/hx509/version-script.map
index a6c81da1ce1..8f46b0ac051 100644
--- a/third_party/heimdal/lib/hx509/version-script.map
+++ b/third_party/heimdal/lib/hx509/version-script.map
@@ -21,6 +21,7 @@ HEIMDAL_X509_1.2 {
_hx509_make_pkinit_san;
_hx509_map_file_os;
_hx509_name_from_Name;
+ _hx509_ossl_oid2nid;
_hx509_private_key_export;
_hx509_private_key_exportable;
_hx509_private_key_get_internal;
@@ -40,7 +41,11 @@ HEIMDAL_X509_1.2 {
hx509_request_authorize_san;
hx509_request_count_unsupported;
hx509_request_count_unauthorized;
+ hx509_request_eku_authorized_p;
hx509_request_print;
+ hx509_request_reject_eku;
+ hx509_request_reject_san;
+ hx509_request_san_authorized_p;
hx509_request_to_pkcs10;
_hx509_unmap_file_os;
_hx509_write_file;
@@ -108,6 +113,9 @@ HEIMDAL_X509_1.2 {
hx509_cert_init;
hx509_cert_init_data;
hx509_cert_init_private_key;
+ hx509_cert_is_ca;
+ hx509_cert_is_root;
+ hx509_cert_is_self_signed;
hx509_cert_keyusage_print;
hx509_cert_public_encrypt;
hx509_cert_ref;
diff --git a/third_party/heimdal/lib/ipc/Makefile.am b/third_party/heimdal/lib/ipc/Makefile.am
index 6915175618e..04ff2137434 100644
--- a/third_party/heimdal/lib/ipc/Makefile.am
+++ b/third_party/heimdal/lib/ipc/Makefile.am
@@ -23,6 +23,10 @@ libheim_ipcc_la_LIBADD = \
$(LIB_roken) \
$(PTHREAD_LIBADD)
+if SUNOS
+libheim_ipcc_la_LIBADD += -lsocket
+endif
+
libheim_ipcs_la_LIBADD = $(libheim_ipcc_la_LIBADD)
TESTS = $(check_PROGRAMS)
diff --git a/third_party/heimdal/lib/ipc/server.c b/third_party/heimdal/lib/ipc/server.c
index b0b2fa1cb66..5ada75af7d1 100644
--- a/third_party/heimdal/lib/ipc/server.c
+++ b/third_party/heimdal/lib/ipc/server.c
@@ -606,7 +606,6 @@ add_new_socket(int fd,
void *userctx)
{
struct client *c;
- int fileflags;
c = calloc(1, sizeof(*c));
if (c == NULL)
@@ -628,8 +627,7 @@ add_new_socket(int fd,
c->callback = callback;
c->userctx = userctx;
- fileflags = fcntl(c->fd, F_GETFL, 0);
- fcntl(c->fd, F_SETFL, fileflags | O_NONBLOCK);
+ socket_set_nonblocking(fd, 1);
#ifdef HAVE_GCD
init_globals();
@@ -1085,6 +1083,9 @@ heim_sipc_service_unix(const char *service,
const char *d = secure_getenv("HEIM_IPC_DIR");
int fd, ret;
+ if (strncasecmp(service, "UNIX:", sizeof("UNIX:") - 1) == 0)
+ service += sizeof("UNIX:") - 1;
+
un.sun_family = AF_UNIX;
if (snprintf(un.sun_path, sizeof(un.sun_path),
@@ -1115,7 +1116,7 @@ heim_sipc_service_unix(const char *service,
return errno;
}
- chmod(un.sun_path, 0666);
+ (void) chmod(un.sun_path, 0666);
ret = heim_sipc_stream_listener(fd, HEIM_SIPC_TYPE_IPC,
callback, user, ctx);
@@ -1284,7 +1285,7 @@ heim_sipc_service_door(const char *service,
ret = errno;
goto cleanup;
}
- fchmod(dfd, 0666); /* XXX */
+ (void) fchmod(dfd, 0666); /* XXX */
if (fattach(fd, path) < 0) {
ret = errno;
diff --git a/third_party/heimdal/lib/kadm5/Makefile.am b/third_party/heimdal/lib/kadm5/Makefile.am
index a6151d51b1c..6b58c5f8fdd 100644
--- a/third_party/heimdal/lib/kadm5/Makefile.am
+++ b/third_party/heimdal/lib/kadm5/Makefile.am
@@ -15,7 +15,7 @@ libkadm5srv_la_LDFLAGS += $(LDFLAGS_VERSION_SCRIPT)$(srcdir)/version-script.map
endif
sbin_PROGRAMS = iprop-log
-check_PROGRAMS = default_keys
+check_PROGRAMS = default_keys test_marshall
noinst_PROGRAMS = test_pw_quality
noinst_LTLIBRARIES = sample_passwd_check.la sample_hook.la
@@ -37,6 +37,9 @@ libexec_PROGRAMS = ipropd-master ipropd-slave
default_keys_SOURCES = default_keys.c
default_keys_CPPFLAGS = -I$(srcdir)/../krb5
+test_marshall_SOURCES = marshall.c
+test_marshall_CPPFLAGS = -I$(srcdir)/../krb5 -DTEST
+
kadm5includedir = $(includedir)/kadm5
buildkadm5include = $(buildinclude)/kadm5
diff --git a/third_party/heimdal/lib/kadm5/create_s.c b/third_party/heimdal/lib/kadm5/create_s.c
index e603497ace2..26e4e4ca7e7 100644
--- a/third_party/heimdal/lib/kadm5/create_s.c
+++ b/third_party/heimdal/lib/kadm5/create_s.c
@@ -256,14 +256,12 @@ kadm5_s_create_principal(void *server_handle,
if ((mask & KADM5_ATTRIBUTES) &&
(princ->attributes & (KRB5_KDB_VIRTUAL_KEYS | KRB5_KDB_VIRTUAL)) &&
!(princ->attributes & KRB5_KDB_MATERIALIZE)) {
- ret = KADM5_DUP; /* XXX */
- goto out;
+ return _kadm5_error_code(KADM5_DUP); /* XXX More like EINVAL */
}
if ((mask & KADM5_ATTRIBUTES) &&
(princ->attributes & KRB5_KDB_VIRTUAL_KEYS) &&
(princ->attributes & KRB5_KDB_VIRTUAL)) {
- ret = KADM5_DUP; /* XXX */
- goto out;
+ return _kadm5_error_code(KADM5_DUP); /* XXX More like EINVAL */
}
if ((mask & KADM5_ATTRIBUTES) &&
diff --git a/third_party/heimdal/lib/kadm5/fuzz-inputs-bin/test_marshall-ent0.bin b/third_party/heimdal/lib/kadm5/fuzz-inputs-bin/test_marshall-ent0.bin
new file mode 100644
index 00000000000..2c5f72c9991
--- /dev/null
+++ b/third_party/heimdal/lib/kadm5/fuzz-inputs-bin/test_marshall-ent0.bin
Binary files differ
diff --git a/third_party/heimdal/lib/kadm5/fuzz-inputs-bin/test_marshall-ent1.bin b/third_party/heimdal/lib/kadm5/fuzz-inputs-bin/test_marshall-ent1.bin
new file mode 100644
index 00000000000..ff0b705f5d7
--- /dev/null
+++ b/third_party/heimdal/lib/kadm5/fuzz-inputs-bin/test_marshall-ent1.bin
Binary files differ
diff --git a/third_party/heimdal/lib/kadm5/fuzz-inputs-packed/test_marshall-ent0.bin b/third_party/heimdal/lib/kadm5/fuzz-inputs-packed/test_marshall-ent0.bin
new file mode 100644
index 00000000000..645fea76bbe
--- /dev/null
+++ b/third_party/heimdal/lib/kadm5/fuzz-inputs-packed/test_marshall-ent0.bin
Binary files differ
diff --git a/third_party/heimdal/lib/kadm5/fuzz-inputs-packed/test_marshall-ent1.bin b/third_party/heimdal/lib/kadm5/fuzz-inputs-packed/test_marshall-ent1.bin
new file mode 100644
index 00000000000..e64ec5a9a17
--- /dev/null
+++ b/third_party/heimdal/lib/kadm5/fuzz-inputs-packed/test_marshall-ent1.bin
Binary files differ
diff --git a/third_party/heimdal/lib/kadm5/fuzz-inputs-txt/test_marshall-ent0.txt b/third_party/heimdal/lib/kadm5/fuzz-inputs-txt/test_marshall-ent0.txt
new file mode 100644
index 00000000000..9d78e8dd07d
--- /dev/null
+++ b/third_party/heimdal/lib/kadm5/fuzz-inputs-txt/test_marshall-ent0.txt
@@ -0,0 +1,101 @@
+# The body of this file contains a representation of a very small and contrived
+# kadm5_principal_ent_rec meant for fuzzing. For fuzzing purposes, the smaller
+# the input, the better.
+#
+# To compile this input into a binary input file suitable for fuzzing:
+#
+# cd build
+# make -j4
+# cd lib/kadm5
+# make test_marshall
+# ./test_marshall --in-text --byte-order-in=packed \
+# --byte-order-out=packed \
+# --out-hex \
+# kadm5_principal_ent_rec \
+# ../../../lib/kadm5/fuzz-inputs-txt/test_marshall-ent0.txt
+#
+# then decode the hex (e.g., with xxd -r -p) and save it in a file.
+#
+# Currently we have that saved in lib/kadm5/fuzz-inputs-packed/.
+#
+# To build and fuzz with this input:
+#
+# cd build
+# AFL_HARDEN=1 make -j4 CC=afl-clang all
+# cd lib/kadm5
+# AFL_HARDEN=1 make -j4 CC=afl-clang test_marshall
+# rm -rf f; mkdir f
+# ../../libtool --mode=execute afl-fuzz \
+# -i ../../../lib/kadm5/fuzz-inputs-packed \
+# -o $PWD/f \
+# ./test_marshall --byte-order-in=packed \
+# --byte-order-out=packed \
+# --out-hex \
+# kadm5_principal_ent_rec '@@'
+#
+# A kadm5_principal_ent_rec follows:
+#
+# principal name
+int32 0
+int32 1
+string T
+string f
+# expiration
+int32 2
+# pw expiration
+int32 3
+# last pw change
+int32 4
+# max life
+int32 5
+# mod name optional (boolean, principal name)
+int32 1
+int32 0
+int32 1
+string T
+string b
+# mod time
+int32 6
+# attrs
+int32 7
+# kvno
+int32 8
+# master kvno
+int32 9
+# policy (boolean, string)
+int32 1
+string default
+# aux attrs
+int32 10
+# max renew life
+int32 11
+# last success
+int32 12
+# last fail
+int32 13
+# fail count
+int32 14
+# nkeydata
+int32 2
+# keydata[0] (ver, kvno, type, data, type, data)
+int32 15
+int32 16
+int32 17
+data 1122
+int32 18
+data 2233
+# keydata[1]
+int32 19
+int32 21
+int32 22
+data 3344
+int32 23
+data 4455
+# ntldata
+int32 2
+# ntldata[0] (type, data)
+int32 24
+data 5566
+# ntldata[1]
+int32 25
+data 6677
diff --git a/third_party/heimdal/lib/kadm5/fuzz-inputs-txt/test_marshall-ent1.txt b/third_party/heimdal/lib/kadm5/fuzz-inputs-txt/test_marshall-ent1.txt
new file mode 100644
index 00000000000..332c759b946
--- /dev/null
+++ b/third_party/heimdal/lib/kadm5/fuzz-inputs-txt/test_marshall-ent1.txt
@@ -0,0 +1,54 @@
+# See lib/kadm5/fuzz-inputs-txt/test_marshall-ent0.txt for instructions on how
+# to fuzz krb5/kadm5 marshalling.
+#
+# A truncated kadm5_principal_ent_rec follows:
+#
+# principal name
+int32 0
+int32 1
+string T
+string f
+# expiration
+int32 2
+# pw expiration
+int32 3
+# last pw change
+int32 4
+# max life
+int32 5
+# mod name optional (boolean, principal name)
+int32 1
+int32 0
+int32 1
+string T
+string b
+# mod time
+int32 6
+# attrs
+int32 7
+# kvno
+int32 8
+# master kvno
+int32 9
+# policy (boolean, string)
+int32 1
+string default
+# aux attrs
+int32 10
+# max renew life
+int32 11
+# last success
+int32 12
+# last fail
+int32 13
+# fail count
+int32 14
+# nkeydata
+int32 2
+# keydata[0] (ver, kvno, type, data, type, data)
+int32 15
+int32 16
+int32 17
+data 1122
+int32 18
+data 2233
diff --git a/third_party/heimdal/lib/kadm5/get_princs_c.c b/third_party/heimdal/lib/kadm5/get_princs_c.c
index 93d7ce7ed1b..be86cfa579e 100644
--- a/third_party/heimdal/lib/kadm5/get_princs_c.c
+++ b/third_party/heimdal/lib/kadm5/get_princs_c.c
@@ -131,6 +131,7 @@ kadm5_c_iter_principals(void *server_handle,
int32_t tmp;
krb5_data reply;
size_t i;
+ int stop = 0;
ret = _kadm5_connect(server_handle, 0 /* want_write */);
if (ret)
@@ -188,7 +189,6 @@ kadm5_c_iter_principals(void *server_handle,
if (tmp < 0) {
size_t n = -tmp;
int more = 1;
- int stop = 0;
/* The server supports online iteration, hooray! */
@@ -249,12 +249,6 @@ kadm5_c_iter_principals(void *server_handle,
}
free(princ);
}
-
- if (!more) {
- if (ret == 0)
- ret = stop;
- break;
- }
}
/* Get the final result code */
krb5_data_free(&reply);
@@ -293,10 +287,12 @@ kadm5_c_iter_principals(void *server_handle,
}
}
- out:
+out:
krb5_clear_error_message(context->context);
- out_keep_error:
+out_keep_error:
+ if (stop)
+ ret = stop;
krb5_storage_free(sp);
krb5_data_free(&reply);
return ret;
diff --git a/third_party/heimdal/lib/kadm5/ipropd_master.c b/third_party/heimdal/lib/kadm5/ipropd_master.c
index b3f7d8105ea..3d693bdfe0a 100644
--- a/third_party/heimdal/lib/kadm5/ipropd_master.c
+++ b/third_party/heimdal/lib/kadm5/ipropd_master.c
@@ -48,6 +48,7 @@ static int time_before_gone;
const char *master_hostname;
const char *pidfile_basename;
+static char hostname[128];
static krb5_socket_t
make_signal_socket (krb5_context context)
@@ -275,12 +276,11 @@ static void
add_slave (krb5_context context, krb5_keytab keytab, slave **root,
krb5_socket_t fd)
{
- krb5_principal server;
+ krb5_principal server = NULL;
krb5_error_code ret;
slave *s;
socklen_t addr_len;
krb5_ticket *ticket = NULL;
- char hostname[128];
s = calloc(1, sizeof(*s));
if (s == NULL) {
@@ -301,10 +301,18 @@ add_slave (krb5_context context, krb5_keytab keytab, slave **root,
goto error;
}
- if (master_hostname)
- strlcpy(hostname, master_hostname, sizeof(hostname));
- else
- gethostname(hostname, sizeof(hostname));
+ /*
+ * We write message lengths separately from the payload, and may do
+ * back-to-back small writes when flushing pending input and then a new
+ * update. Avoid Nagle delays.
+ */
+#if defined(IPPROTO_TCP) && defined(TCP_NODELAY)
+ {
+ int nodelay = 1;
+ (void) setsockopt(s->fd, IPPROTO_TCP, TCP_NODELAY,
+ (void *)&nodelay, sizeof(nodelay));
+ }
+#endif
ret = krb5_sname_to_principal (context, hostname, IPROP_NAME,
KRB5_NT_SRV_HST, &server);
@@ -331,26 +339,11 @@ add_slave (krb5_context context, krb5_keytab keytab, slave **root,
*/
socket_set_nonblocking(s->fd, 1);
- /*
- * We write message lengths separately from the payload, and may do
- * back-to-back small writes when flushing pending input and then a new
- * update. Avoid Nagle delays.
- */
-#if defined(IPPROTO_TCP) && defined(TCP_NODELAY)
- {
- int nodelay = 1;
- (void) setsockopt(s->fd, IPPROTO_TCP, TCP_NODELAY,
- (void *)&nodelay, sizeof(nodelay));
- }
-#endif
-
- krb5_free_principal (context, server);
if (ret) {
krb5_warn (context, ret, "krb5_recvauth");
goto error;
}
ret = krb5_unparse_name (context, ticket->client, &s->name);
- krb5_free_ticket (context, ticket);
if (ret) {
krb5_warn (context, ret, "krb5_unparse_name");
goto error;
@@ -378,6 +371,8 @@ add_slave (krb5_context context, krb5_keytab keytab, slave **root,
}
}
+ krb5_free_principal(context, server);
+ krb5_free_ticket(context, ticket);
krb5_warnx (context, "connection from %s", s->name);
s->version = 0;
@@ -389,6 +384,9 @@ add_slave (krb5_context context, krb5_keytab keytab, slave **root,
return;
error:
remove_slave(context, s, root);
+ krb5_free_principal(context, server);
+ if (ticket)
+ krb5_free_ticket(context, ticket);
}
static int
@@ -1197,10 +1195,11 @@ send_diffs(kadm5_server_context *server_context, slave *s, int log_fd,
krb5_err(context, IPROPD_RESTART_SLOW, ENOMEM, "out of memory");
return;
}
- krb5_store_uint32(sp, FOR_YOU);
+ ret = krb5_store_uint32(sp, FOR_YOU);
krb5_storage_free(sp);
- ret = mk_priv_tail(context, s, &data);
+ if (ret == 0)
+ ret = mk_priv_tail(context, s, &data);
krb5_data_free(&data);
if (ret == 0) {
/* Save the fast-path continuation */
@@ -1587,6 +1586,20 @@ main(int argc, char **argv)
exit(0);
}
+ memset(hostname, 0, sizeof(hostname));
+
+ if (master_hostname &&
+ strlcpy(hostname, master_hostname,
+ sizeof(hostname)) >= sizeof(hostname)) {
+ errx(1, "Hostname too long: %s", master_hostname);
+ } else if (master_hostname == NULL) {
+ if (gethostname(hostname, sizeof(hostname)) == -1)
+ err(1, "Could not get hostname");
+ if (hostname[sizeof(hostname) - 1] != '\0')
+ errx(1, "Hostname too long %.*s...",
+ (int)sizeof(hostname), hostname);
+ }
+
if (detach_from_console && daemon_child == -1)
daemon_child = roken_detach_prep(argc, argv, "--daemon-child");
rk_pidfile(pidfile_basename);
diff --git a/third_party/heimdal/lib/kadm5/log.c b/third_party/heimdal/lib/kadm5/log.c
index 4f66426c4ca..96d063eb90e 100644
--- a/third_party/heimdal/lib/kadm5/log.c
+++ b/third_party/heimdal/lib/kadm5/log.c
@@ -843,19 +843,19 @@ kadm5_log_signal_master(kadm5_server_context *context)
{
kadm5_log_context *log_context = &context->log_context;
#ifndef NO_UNIX_SOCKETS
- sendto(log_context->socket_fd,
- (void *)&log_context->version,
- sizeof(log_context->version),
- 0,
- (struct sockaddr *)&log_context->socket_name,
- sizeof(log_context->socket_name));
+ (void) sendto(log_context->socket_fd,
+ (void *)&log_context->version,
+ sizeof(log_context->version),
+ 0,
+ (struct sockaddr *)&log_context->socket_name,
+ sizeof(log_context->socket_name));
#else
- sendto(log_context->socket_fd,
- (void *)&log_context->version,
- sizeof(log_context->version),
- 0,
- log_context->socket_info->ai_addr,
- log_context->socket_info->ai_addrlen);
+ (void) sendto(log_context->socket_fd,
+ (void *)&log_context->version,
+ sizeof(log_context->version),
+ 0,
+ log_context->socket_info->ai_addr,
+ log_context->socket_info->ai_addrlen);
#endif
}
diff --git a/third_party/heimdal/lib/kadm5/marshall.c b/third_party/heimdal/lib/kadm5/marshall.c
index 9d24233ba6e..f979ec0f5c9 100644
--- a/third_party/heimdal/lib/kadm5/marshall.c
+++ b/third_party/heimdal/lib/kadm5/marshall.c
@@ -371,11 +371,11 @@ ret_principal_ent(krb5_storage *sp,
if (mask & KADM5_KEY_DATA) {
CHECK(krb5_ret_int32(sp, &tmp));
princ->n_key_data = tmp;
- princ->key_data = malloc(princ->n_key_data * sizeof(*princ->key_data));
+ princ->key_data = calloc(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++)
- ret = kadm5_ret_key_data(sp, &princ->key_data[i]);
+ CHECK(kadm5_ret_key_data(sp, &princ->key_data[i]));
}
if (mask & KADM5_TL_DATA) {
CHECK(krb5_ret_int32(sp, &tmp));
@@ -472,3 +472,491 @@ _kadm5_unmarshal_params(krb5_context context,
return ret;
}
+
+#ifdef TEST
+#include <getarg.h>
+#include <krb5-protos.h>
+#include <hex.h>
+
+static int version_flag;
+static int help_flag;
+static int verbose_flag;
+static int in_text_flag = 0;
+static int in_binary_flag = 0;
+static int out_hex_flag = 0;
+static int out_binary_flag = 0;
+static int must_round_trip_flag = 0;
+static char *byteorder_string_in_string;
+static char *byteorder_string_out_string;
+static struct getargs args[] = {
+ { "version", '\0', arg_flag, &version_flag,
+ "Version", NULL },
+ { "help", '\0', arg_flag, &help_flag,
+ "Show this message", NULL },
+ { "verbose", 'v', arg_flag, &verbose_flag, NULL, NULL },
+ { "in-text", '\0', arg_flag, &in_text_flag,
+ "Input is a text \"recipe\"", NULL },
+ { "in-binary", '\0', arg_flag, &in_binary_flag,
+ "Input is binary", NULL },
+ { "out-hex", '\0', arg_flag, &out_hex_flag,
+ "Output hex", NULL },
+ { "out-binary", '\0', arg_flag, &out_binary_flag,
+ "Output binary", NULL },
+ { "must-round-trip", '\0', arg_flag, &must_round_trip_flag,
+ "Check that encoding and decoding round-trip", NULL },
+ { "byte-order-out", '\0', arg_string, &byteorder_string_out_string,
+ "Output byte order", "host, network, be, or le" },
+ { "byte-order-in", '\0', arg_string, &byteorder_string_in_string,
+ "Input byte order", "host, network, packed, be, or le" },
+};
+
+#define DO_TYPE1(t, r, s) \
+ if (strcmp(type, #t) == 0) { \
+ t v; \
+ ret = r(in, &v); \
+ if (ret == 0) \
+ ret = s(out, v); \
+ return ret; \
+ }
+
+#define DO_TYPE2(t, r, s) \
+ if (strcmp(type, #t) == 0) { \
+ t v; \
+ ret = r(in, &v); \
+ if (ret == 0) \
+ ret = s(out, &v); \
+ return ret; \
+ }
+
+static krb5_error_code
+reencode(const char *type, krb5_storage *in, krb5_storage *out)
+{
+ krb5_error_code ret;
+
+ krb5_storage_seek(in, 0, SEEK_SET);
+
+ /*
+ * TODO: When --verbose print a visual representation of the value.
+ *
+ * We have functionality in lib/krb5 for that for krb5_principal and
+ * krb5_address, but not any of the others. Adding krb5_print_*()
+ * and kadm5_print_*() functions just for this program to use seems
+ * annoying.
+ */
+ DO_TYPE1(krb5_keyblock, krb5_ret_keyblock, krb5_store_keyblock);
+ DO_TYPE1(krb5_principal, krb5_ret_principal, krb5_store_principal);
+ DO_TYPE1(krb5_times, krb5_ret_times, krb5_store_times);
+ DO_TYPE1(krb5_address, krb5_ret_address, krb5_store_address);
+ DO_TYPE1(krb5_addresses, krb5_ret_addrs, krb5_store_addrs);
+ DO_TYPE1(krb5_authdata, krb5_ret_authdata, krb5_store_authdata);
+
+ DO_TYPE2(krb5_creds, krb5_ret_creds, krb5_store_creds);
+ DO_TYPE2(krb5_key_data, kadm5_ret_key_data, kadm5_store_key_data);
+ DO_TYPE2(krb5_tl_data, kadm5_ret_tl_data, kadm5_store_tl_data);
+ DO_TYPE2(kadm5_principal_ent_rec, kadm5_ret_principal_ent,
+ kadm5_store_principal_ent);
+
+ return ENOTSUP;
+}
+
+static krb5_error_code
+eval_recipe1(krb5_storage *sp, const char *typ, const char *val)
+{
+ krb5_error_code ret;
+ uint64_t vu = 0;
+ int64_t vi = 0;
+ int consumed = 0;
+
+ if (strncmp(typ, "int", sizeof("int") - 1) == 0) {
+ if (sscanf(val, "%"PRIi64"%n", &vi, &consumed) != 1)
+ return EINVAL;
+ if (consumed < 1)
+ return EINVAL;
+ while (isspace(val[consumed]))
+ consumed++;
+ if (val[consumed] != '\0')
+ return EINVAL;
+ } else if (strncmp(typ, "uint", sizeof("uint") - 1) == 0) {
+ /* There's no equally-useful equivalent of %i for unsigned */
+ if (val[0] == '0') {
+ if (val[1] == 'x') {
+ if (sscanf(val, "%"PRIx64"%n", &vu, &consumed) != 1)
+ return EINVAL;
+ } else {
+ if (sscanf(val, "%"PRIo64"%n", &vu, &consumed) != 1)
+ return EINVAL;
+ }
+ } else {
+ if (sscanf(val, "%"PRIu64"%n", &vu, &consumed) != 1)
+ return EINVAL;
+ }
+ if (consumed < 1)
+ return EINVAL;
+ while (isspace(val[consumed]))
+ consumed++;
+ if (val[consumed] != '\0')
+ return EINVAL;
+ vi = (int64_t)vu;
+ }
+#define DO_INTn(n) \
+ if (strcmp(typ, "int" #n) == 0) { \
+ if (n < 64 && vi < INT ## n ## _MIN) \
+ return EOVERFLOW; \
+ if (n < 64 && vi > INT ## n ## _MAX) \
+ return EOVERFLOW; \
+ return krb5_store_int ## n (sp, vi); \
+ }
+ DO_INTn(8);
+ DO_INTn(16);
+ DO_INTn(32);
+ DO_INTn(64);
+#define DO_UINTn(n) \
+ if (strcmp(typ, "uint" #n) == 0) { \
+ if (n < 64 && vu > INT ## n ## _MAX) \
+ return EOVERFLOW; \
+ return krb5_store_int ## n (sp, vi); \
+ }
+ DO_UINTn(8);
+ DO_UINTn(16);
+ DO_UINTn(32);
+ DO_UINTn(64);
+ if (strcmp(typ, "string") == 0)
+ return krb5_store_string(sp, val);
+ if (strcmp(typ, "stringz") == 0)
+ return krb5_store_stringz(sp, val);
+ if (strcmp(typ, "stringnl") == 0)
+ return krb5_store_stringnl(sp, val);
+ if (strcmp(typ, "data") == 0) {
+ ssize_t dsz = strlen(val);
+ krb5_data d;
+
+ /*
+ * 'data' as in 'krb5_data'.
+ *
+ * krb5_store_data() stores the length then the data.
+ */
+ if (krb5_data_alloc(&d, dsz))
+ return ENOMEM;
+ dsz = hex_decode(val, d.data, d.length);
+ if (dsz < 0)
+ return EINVAL;
+ d.length = dsz;
+ ret = krb5_store_data(sp, d);
+ krb5_data_free(&d);
+ return ret;
+ }
+ if (strcmp(typ, "rawdata") == 0) {
+ ssize_t dsz = strlen(val);
+ void *d;
+
+ /* Store the data w/o a length prefix */
+ d = malloc(dsz);
+ if (d == NULL)
+ return ENOMEM;
+ dsz = hex_decode(val, d, dsz);
+ if (dsz < 0)
+ return EINVAL;
+ ret = krb5_store_datalen(sp, d, dsz);
+ free(d);
+ return ret;
+ }
+ return ENOTSUP;
+}
+
+static krb5_storage *
+eval_recipe(char *r, int spflags)
+{
+ krb5_error_code ret;
+ krb5_storage *sp;
+ unsigned int lineno = 0;
+ char *nxt = NULL;
+ char *p;
+
+ sp = krb5_storage_emem();
+ if (sp == NULL)
+ errx(1, "Out of memory");
+ krb5_storage_set_flags(sp, spflags);
+
+ for (p = r; p && *p; p = nxt) {
+ char *typ;
+ char *val;
+
+ lineno++;
+
+ /* Terminate p at \n */
+ nxt = p;
+ do {
+ nxt = strpbrk(nxt, "\r\n");
+ if (nxt && *nxt == '\r') {
+ if (*(++nxt) != '\n')
+ continue;
+ }
+ if (nxt && *nxt == '\n') {
+ *(nxt++) = '\0';
+ break;
+ }
+ } while (nxt);
+
+ while (isspace(*p))
+ p++;
+ if (*p == '#') {
+ p = nxt;
+ continue;
+ }
+ if (*p == '\0')
+ continue;
+ typ = p;
+ val = strpbrk(p, " \t");
+ if (val) {
+ *(val++) = '\0';
+ while (isspace(*val))
+ val++;
+ }
+ ret = eval_recipe1(sp, typ, val);
+ if (ret)
+ krb5_err(NULL, 1, ret, "Error at line %u", lineno);
+ }
+ return sp;
+}
+
+static void
+usage(int code)
+{
+ if (code)
+ dup2(STDERR_FILENO, STDOUT_FILENO);
+
+ arg_printusage(args, sizeof(args) / sizeof(args[0]), "test_marshall",
+ "Usage: test_marshal [options] TYPE-NAME INPUT-FILE "
+ "[OUTPUT-FILE]\n"
+ "\tText inputs must be of the form:\n\n"
+ "\t\tsimpletype literalvalue\n\n"
+ "\twhere {simpletype} is one of:\n\n"
+ "\t\tint8\n"
+ "\t\tint16\n"
+ "\t\tint32\n"
+ "\t\tint64\n"
+ "\t\tuint8\n"
+ "\t\tuint16\n"
+ "\t\tuint32\n"
+ "\t\tuint64\n"
+ "\t\tstring\n"
+ "\t\tstringz\n"
+ "\t\tstringnl\n"
+ "\t\tdata\n"
+ "\t\trawdata\n\n"
+ "\tand {literalvalue} is as appropriate for the {simpletype}:\n\n"
+ "\t - For int types the value can be decimal, octal, or hexadecimal.\n"
+ "\t - For string types the string ends at the end of the line.\n"
+ "\t - For {data} the value is hex and will be encoded as a 32-bit\n"
+ "\t length then the raw binary data.\n"
+ "\t - For {rawdata} the value is hex and will be encoded as just the\n"
+ "\t raw binary data.\n\n"
+ "\tThe {TYPE} must be one of: krb5_keyblock, krb5_principal,\n"
+ "\tkrb5_times, krb5_address, krb5_addresses, krb5_authdata,\n"
+ "\tkrb5_creds, krb5_key_data, krb5_tl_data, or\n"
+ "\tkadm5_principal_ent_rec.\n\n"
+ "Options:\n");
+ exit(code);
+}
+
+static krb5_flags
+byteorder_flags(const char *s)
+{
+ if (s == NULL)
+ return KRB5_STORAGE_BYTEORDER_BE;
+ if (strcasecmp(s, "packed") == 0)
+ return KRB5_STORAGE_BYTEORDER_PACKED;
+ if (strcasecmp(s, "host") == 0)
+ return KRB5_STORAGE_BYTEORDER_HOST;
+ if (strcasecmp(s, "network") == 0)
+ return KRB5_STORAGE_BYTEORDER_BE;
+ if (strcasecmp(s, "be") == 0)
+ return KRB5_STORAGE_BYTEORDER_BE;
+ if (strcasecmp(s, "le") == 0)
+ return KRB5_STORAGE_BYTEORDER_LE;
+ return 0;
+}
+
+/*
+ * This program is intended to make fuzzing of krb5_ret_*() and kadm5_ret_*()
+ * possible.
+ *
+ * Inputs are either binary encodings or simplistic textual representations of
+ * XDR-ish data structures normally coded with {kadm5,krb5}_{ret,store}_*()
+ * functions.
+ *
+ * A textual representation of these structures looks like:
+ *
+ * type value
+ * ..
+ *
+ * where type is one of char, int32, etc., and where value is an appropriate
+ * literal for type.
+ */
+int
+main(int argc, char **argv)
+{
+ krb5_error_code ret = 0;
+ krb5_storage *insp = NULL;
+ krb5_storage *insp2 = NULL;
+ krb5_storage *outsp = NULL;
+ krb5_flags spflags_in = 0;
+ krb5_flags spflags_out = 0;
+ krb5_data i, i2, o;
+ size_t insz = 0;
+ char *hexout = NULL;
+ char *hexin = NULL;
+ char *intxt = NULL;
+ void *inbin = NULL;
+ int optidx = 0;
+
+ if (getarg(args, sizeof(args)/sizeof(args[0]), argc, argv, &optidx))
+ usage(1);
+
+ if (help_flag)
+ usage(0);
+
+ argc -= optidx;
+ argv += optidx;
+
+ if (argc < 1)
+ errx(1, "Missing type name argument");
+ if (argc < 2)
+ errx(1, "Missing input file argument");
+ if (argc > 3)
+ errx(1, "Too many arguments");
+
+ if ((in_text_flag && in_binary_flag) ||
+ (!in_text_flag && !in_binary_flag))
+ errx(1, "One and only one of --in-text and --in-binary must be given");
+ if (out_hex_flag && out_binary_flag)
+ errx(1, "At most one of --out-text and --out-binary must be given");
+
+ if (!out_hex_flag && !out_binary_flag) {
+ if (isatty(STDOUT_FILENO)) {
+ warnx("Will output hex because stdout is a terminal");
+ out_hex_flag = 1;
+ } else {
+ warnx("Will output binary");
+ out_binary_flag = 1;
+ }
+ }
+
+ spflags_in |= byteorder_flags(byteorder_string_in_string);
+ spflags_out |= byteorder_flags(byteorder_string_out_string);
+
+ /* Read the input */
+ if (in_text_flag)
+ errno = rk_undumptext(argv[1], &intxt, NULL);
+ else
+ errno = rk_undumpdata(argv[1], &inbin, &insz);
+ if (errno)
+ err(1, "Could not read %s", argv[1]);
+
+ /* If the input is a recipe, evaluate it */
+ if (intxt)
+ insp = eval_recipe(intxt, spflags_in);
+ else
+ insp = krb5_storage_from_mem(inbin, insz);
+ if (insp == NULL)
+ errx(1, "Out of memory");
+ krb5_storage_set_flags(insp, spflags_in);
+
+ ret = krb5_storage_to_data(insp, &i);
+ if (ret)
+ krb5_err(NULL, 1, ret, "Could not check round-tripping");
+
+ if (out_hex_flag) {
+ char *hexstr = NULL;
+
+ if (hex_encode(i.data, i.length, &hexstr) == -1)
+ err(1, "Could not hex-encode output");
+ if (argv[2]) {
+ FILE *f;
+
+ f = fopen(argv[2], "w");
+ if (f == NULL)
+ err(1, "Could not open %s for writing", argv[2]);
+ if (fprintf(f, "%s\n", hexstr) < 0 || fclose(f))
+ err(1, "Could write to %s", argv[2]);
+ } else {
+ if (printf("%s\n", hexstr) < 0)
+ err(1, "Could not write to stdout");
+ }
+ free(hexstr);
+ } else {
+ if (argv[2]) {
+ rk_dumpdata(argv[2], i.data, i.length);
+ } else {
+ if (fwrite(i.data, i.length, 1, stdout) != 1 ||
+ fflush(stdout) != 0)
+ err(1, "Could not output encoding");
+ }
+ }
+
+ outsp = krb5_storage_emem();
+ if (outsp == NULL)
+ errx(1, "Out of memory");
+ krb5_storage_set_flags(outsp, spflags_out);
+
+ ret = reencode(argv[0], insp, outsp);
+ if (ret)
+ krb5_err(NULL, 1, ret, "Could not decode and re-encode");
+
+ if (i.length == o.length && memcmp(i.data, o.data, i.length) == 0) {
+ if (verbose_flag)
+ fprintf(stderr, "Encoding round-trips!\n");
+ goto out;
+ }
+
+ ret = krb5_storage_to_data(outsp, &o);
+ if (ret)
+ krb5_err(NULL, 1, ret, "Out of memory");
+
+ /*
+ * The encoding did not round trip. Sadly kadm5_ret_principal_ent()
+ * reverses the TL data list. So try to re-encode one more time.
+ */
+
+ if (strcmp(argv[0], "kadm5_principal_ent_rec") == 0) {
+ insp2 = krb5_storage_emem();
+ if (insp2 == NULL)
+ errx(1, "Out of memory");
+
+ krb5_storage_set_flags(insp2, spflags_in);
+ ret = reencode(argv[0], outsp, insp2);
+ if (ret == 0)
+ ret = krb5_storage_to_data(insp2, &i2);
+ if (ret)
+ krb5_err(NULL, 1, ret, "Could not decode and re-encode");
+ if (i.length == i2.length && memcmp(i.data, i2.data, i.length) == 0) {
+ if (verbose_flag)
+ fprintf(stderr, "Encoding round-trips!\n");
+ goto out;
+ }
+ }
+ if (hex_encode(i.data, i.length, &hexin) < 0)
+ errx(1, "Out of memory");
+ if (hex_encode(o.data, o.length, &hexout) < 0)
+ errx(1, "Out of memory");
+ if (must_round_trip_flag) {
+ errx(1, "Encoding does not round-trip\n(in: %s)\n(out: %s)", hexin,
+ hexout);
+ } else {
+ warnx("Encoding does not round-trip\n(in: %s)\n(out: %s)", hexin,
+ hexout);
+ }
+
+out:
+
+ free(hexin);
+ free(hexout);
+ krb5_data_free(&o);
+ krb5_data_free(&i);
+ krb5_data_free(&i2);
+ krb5_storage_free(insp);
+ krb5_storage_free(outsp);
+ krb5_storage_free(insp2);
+ return ret;
+}
+#endif
diff --git a/third_party/heimdal/lib/kadm5/version-script-client.map b/third_party/heimdal/lib/kadm5/version-script-client.map
index baae30b1173..56a4ff33511 100644
--- a/third_party/heimdal/lib/kadm5/version-script-client.map
+++ b/third_party/heimdal/lib/kadm5/version-script-client.map
@@ -61,6 +61,9 @@ HEIMDAL_KADM5_CLIENT_1.0 {
kadm5_store_principal_ent;
kadm5_store_principal_ent_mask;
kadm5_store_tl_data;
+ _kadm5_client_recv;
+ _kadm5_client_send;
+ _kadm5_connect;
local:
*;
};
diff --git a/third_party/heimdal/lib/krb5/aes-test.c b/third_party/heimdal/lib/krb5/aes-test.c
index 01522dd593a..2d048e426e5 100644
--- a/third_party/heimdal/lib/krb5/aes-test.c
+++ b/third_party/heimdal/lib/krb5/aes-test.c
@@ -328,7 +328,8 @@ krb_enc(krb5_context context,
}
if (decrypt.length != clear->length ||
- memcmp(decrypt.data, clear->data, decrypt.length) != 0) {
+ (decrypt.length &&
+ memcmp(decrypt.data, clear->data, decrypt.length) != 0)) {
krb5_warnx(context, "clear text not same");
return EINVAL;
}
@@ -568,7 +569,8 @@ krb_enc_mit(krb5_context context,
return ret;
if (decrypt.length != clear->length ||
- memcmp(decrypt.data, clear->data, decrypt.length) != 0) {
+ (decrypt.length &&
+ memcmp(decrypt.data, clear->data, decrypt.length) != 0)) {
krb5_warnx(context, "clear text not same");
return EINVAL;
}
diff --git a/third_party/heimdal/lib/krb5/aname_to_localname.c b/third_party/heimdal/lib/krb5/aname_to_localname.c
index 8515c306e69..307d421daa0 100644
--- a/third_party/heimdal/lib/krb5/aname_to_localname.c
+++ b/third_party/heimdal/lib/krb5/aname_to_localname.c
@@ -31,11 +31,12 @@
* SUCH DAMAGE.
*/
-#include <string.h>
#include "krb5_locl.h"
#include "an2ln_plugin.h"
#include "db_plugin.h"
+#include <string.h>
+
/* Default plugin (DB using binary search of sorted text file) follows */
static krb5_error_code KRB5_LIB_CALL an2ln_def_plug_init(krb5_context, void **);
static void KRB5_LIB_CALL an2ln_def_plug_fini(void *);
diff --git a/third_party/heimdal/lib/krb5/context.c b/third_party/heimdal/lib/krb5/context.c
index d6ddd902d64..7d2ef5f68b4 100644
--- a/third_party/heimdal/lib/krb5/context.c
+++ b/third_party/heimdal/lib/krb5/context.c
@@ -584,7 +584,7 @@ krb5_copy_context(krb5_context context, krb5_context *out)
ret = ENOMEM;
}
if (ret == 0 && context->configured_default_cc_name) {
- free(context->configured_default_cc_name);
+ free(p->configured_default_cc_name);
if ((p->configured_default_cc_name =
strdup(context->configured_default_cc_name)) == NULL)
ret = ENOMEM;
diff --git a/third_party/heimdal/lib/krb5/crypto-evp.c b/third_party/heimdal/lib/krb5/crypto-evp.c
index a03cdca2ebc..0ed749a243c 100644
--- a/third_party/heimdal/lib/krb5/crypto-evp.c
+++ b/third_party/heimdal/lib/krb5/crypto-evp.c
@@ -82,9 +82,11 @@ _krb5_evp_digest_iov(krb5_crypto crypto,
if (ret != 1)
goto out;
+ /* Minimize EVP calls by coalescing contiguous iovec elements */
for (i = 0; i < niov; i++) {
if (_krb5_crypto_iov_should_sign(&iov[i])) {
- if ((char *)current.data + current.length == iov[i].data.data) {
+ if (current.data &&
+ (char *)current.data + current.length == iov[i].data.data) {
current.length += iov[i].data.length;
} else {
if (current.data) {
@@ -145,7 +147,8 @@ _krb5_evp_hmac_iov(krb5_context context,
for (i = 0; i < niov; i++) {
if (_krb5_crypto_iov_should_sign(&iov[i])) {
- if ((char *)current.data + current.length == iov[i].data.data) {
+ if (current.data &&
+ (char *)current.data + current.length == iov[i].data.data) {
current.length += iov[i].data.length;
} else {
if (current.data)
diff --git a/third_party/heimdal/lib/krb5/dcache.c b/third_party/heimdal/lib/krb5/dcache.c
index af88aed9156..6a4a226a6c3 100644
--- a/third_party/heimdal/lib/krb5/dcache.c
+++ b/third_party/heimdal/lib/krb5/dcache.c
@@ -273,19 +273,18 @@ verify_directory(krb5_context context, const char *path)
return EINVAL;
}
+ /* XXX should use mkdirx_np() */
+ if (rk_mkdir(path, S_IRWXU) == 0)
+ return 0;
+
if (stat(path, &sb) != 0) {
if (errno == ENOENT) {
- /* XXX should use mkdirx_np() */
- if (rk_mkdir(path, S_IRWXU) == 0)
- return 0;
-
krb5_set_error_message(context, ENOENT,
N_("DIR directory %s doesn't exists", ""), path);
return ENOENT;
} else {
- int ret = errno;
- krb5_set_error_message(context, ret,
- N_("DIR directory %s is bad: %s", ""), path, strerror(ret));
+ krb5_set_error_message(context, errno,
+ N_("DIR directory %s is bad: %s", ""), path, strerror(errno));
return errno;
}
}
diff --git a/third_party/heimdal/lib/krb5/fast.c b/third_party/heimdal/lib/krb5/fast.c
index 83893542d69..90133a7abc0 100644
--- a/third_party/heimdal/lib/krb5/fast.c
+++ b/third_party/heimdal/lib/krb5/fast.c
@@ -851,9 +851,9 @@ krb5_error_code
_krb5_fast_anon_pkinit_step(krb5_context context,
krb5_init_creds_context ctx,
struct krb5_fast_state *state,
- krb5_data *in,
+ const krb5_data *in,
krb5_data *out,
- krb5_krbhst_info *hostinfo,
+ krb5_realm *out_realm,
unsigned int *flags)
{
krb5_error_code ret;
@@ -864,6 +864,9 @@ _krb5_fast_anon_pkinit_step(krb5_context context,
krb5_creds cred;
krb5_data data = { 3, rk_UNCONST("yes") };
+ krb5_data_zero(out);
+ *out_realm = NULL;
+
memset(&cred, 0, sizeof(cred));
if (state->anon_pkinit_opt == NULL) {
@@ -877,7 +880,7 @@ _krb5_fast_anon_pkinit_step(krb5_context context,
ret = krb5_make_principal(context, &principal, realm,
KRB5_WELLKNOWN_NAME, KRB5_ANON_NAME, NULL);
if (ret)
- return ret;
+ goto out;
ret = krb5_get_init_creds_opt_set_pkinit(context,
state->anon_pkinit_opt,
@@ -899,7 +902,7 @@ _krb5_fast_anon_pkinit_step(krb5_context context,
anon_pk_ctx = state->anon_pkinit_ctx;
- ret = krb5_init_creds_step(context, anon_pk_ctx, in, out, hostinfo, flags);
+ ret = krb5_init_creds_step(context, anon_pk_ctx, in, out, out_realm, flags);
if (ret ||
(*flags & KRB5_INIT_CREDS_STEP_FLAG_CONTINUE))
goto out;
@@ -950,8 +953,6 @@ _krb5_fast_anon_pkinit_step(krb5_context context,
krb5_get_init_creds_opt_free(context, state->anon_pkinit_opt);
state->anon_pkinit_opt = NULL;
- *flags |= KRB5_INIT_CREDS_STEP_FLAG_CONTINUE;
-
out:
krb5_free_principal(context, principal);
krb5_free_cred_contents(context, &cred);
diff --git a/third_party/heimdal/lib/krb5/fcache.c b/third_party/heimdal/lib/krb5/fcache.c
index 30dff35893b..20c335db3be 100644
--- a/third_party/heimdal/lib/krb5/fcache.c
+++ b/third_party/heimdal/lib/krb5/fcache.c
@@ -581,7 +581,7 @@ again:
* locations on tmpfs "run" directories. But we don't know here
* that this is the case. Thus: no hard-links, no symlinks.
*/
- if (sb2.st_nlink != 1) {
+ if (sb2.st_nlink > 1) {
krb5_set_error_message(context, EPERM, N_("Refuses to open hardlinks for caches FILE:%s", ""), filename);
close(fd);
return EPERM;
diff --git a/third_party/heimdal/lib/krb5/get_host_realm.c b/third_party/heimdal/lib/krb5/get_host_realm.c
index 955d5462d41..fdf8513405f 100644
--- a/third_party/heimdal/lib/krb5/get_host_realm.c
+++ b/third_party/heimdal/lib/krb5/get_host_realm.c
@@ -185,20 +185,21 @@ _krb5_get_host_realm_int(krb5_context context,
{
const char *p, *q;
const char *port;
+ char *freeme = NULL;
krb5_boolean dns_locate_enable;
krb5_error_code ret = 0;
/* Strip off any trailing ":port" suffix. */
port = strchr(host, ':');
- if (port != NULL) {
- host = strndup(host, port - host);
+ if (port != NULL && port != host && port[1] != '\0') {
+ host = freeme = strndup(host, port - host);
if (host == NULL)
return krb5_enomem(context);
}
dns_locate_enable = krb5_config_get_bool_default(context, NULL, TRUE,
"libdefaults", "dns_lookup_realm", NULL);
- for (p = host; p != NULL; p = strchr (p + 1, '.')) {
+ for (p = host; p != NULL && p[0] != '\0'; p = strchr (p + 1, '.')) {
if (config_find_realm(context, p, realms) == 0) {
if (strcasecmp(*realms[0], "dns_locate") != 0)
break;
@@ -219,11 +220,20 @@ _krb5_get_host_realm_int(krb5_context context,
/*
* If 'p' is NULL, we did not find an explicit realm mapping in either the
- * configuration file or DNS. Try the hostname suffix as a last resort.
+ * configuration file or DNS. Try the hostname suffix -upcased- as a realm
+ * as a last resort.
*
- * XXX: If we implement a KDC-specific variant of this function just for
- * referrals, we could check whether we have a cross-realm TGT for the
- * realm in question, and if not try the parent (loop again).
+ * NOTE: If we implement a KDC-specific variant of this function just for
+ * referrals, we could check whether we have a cross-realm TGT for the
+ * realm in question, and if not try the parent (loop again). Such a
+ * variant would have to have access to the HDB, naturally.
+ *
+ * We should start by adding an argument to this function that
+ * indicates whether this fallback here is desired (the KDC wouldn't
+ * desire it). Then when the KDC gets KRB5_ERR_HOST_REALM_UNKNOWN
+ * from this function, the KDC would search the HDB for cross-realm
+ * krbtgt principals that denote a hierarchical path to a realm that
+ * matches the host's domain suffix (or a suffix of it...).
*/
if (p == NULL) {
p = strchr(host, '.');
@@ -246,9 +256,7 @@ _krb5_get_host_realm_int(krb5_context context,
}
}
- /* If 'port' is not NULL, we have a copy of 'host' to free. */
- if (port)
- free((void *)host);
+ free(freeme);
return ret;
}
diff --git a/third_party/heimdal/lib/krb5/init_creds_pw.c b/third_party/heimdal/lib/krb5/init_creds_pw.c
index 9257886530a..402aefd8868 100644
--- a/third_party/heimdal/lib/krb5/init_creds_pw.c
+++ b/third_party/heimdal/lib/krb5/init_creds_pw.c
@@ -1221,7 +1221,7 @@ pkinit_configure_win(krb5_context context, krb5_init_creds_context ctx, void *pa
static krb5_error_code
pkinit_step(krb5_context context, krb5_init_creds_context ctx, void *pa_ctx, PA_DATA *pa, const AS_REQ *a,
- const AS_REP *rep, const krb5_krbhst_info *hi, METHOD_DATA *in_md, METHOD_DATA *out_md)
+ const AS_REP *rep, METHOD_DATA *in_md, METHOD_DATA *out_md)
{
krb5_error_code ret = HEIM_ERR_PA_CANT_CONTINUE;
struct pkinit_context *pkinit_ctx = pa_ctx;
@@ -1245,7 +1245,6 @@ pkinit_step(krb5_context context, krb5_init_creds_context ctx, void *pa_ctx, PA_
a->req_body.realm,
ctx->pk_init_ctx,
rep->enc_part.etype,
- hi,
ctx->pk_nonce,
&ctx->req_buffer,
pa,
@@ -1374,7 +1373,6 @@ pa_gss_step(krb5_context context,
PA_DATA *pa,
const AS_REQ *a,
const AS_REP *rep,
- const krb5_krbhst_info *hi,
METHOD_DATA *in_md,
METHOD_DATA *out_md)
{
@@ -1588,7 +1586,7 @@ process_pa_info(krb5_context, const krb5_principal, const AS_REQ *, struct pa_in
static krb5_error_code
enc_chal_step(krb5_context context, krb5_init_creds_context ctx, void *pa_ctx, PA_DATA *pa, const AS_REQ *a,
- const AS_REP *rep, const krb5_krbhst_info *hi, METHOD_DATA *in_md, METHOD_DATA *out_md)
+ const AS_REP *rep, METHOD_DATA *in_md, METHOD_DATA *out_md)
{
struct pa_info_data paid, *ppaid;
krb5_keyblock challengekey;
@@ -1727,7 +1725,6 @@ static krb5_error_code
enc_ts_step(krb5_context context, krb5_init_creds_context ctx, void *pa_ctx, PA_DATA *pa,
const AS_REQ *a,
const AS_REP *rep,
- const krb5_krbhst_info *hi,
METHOD_DATA *in_md, METHOD_DATA *out_md)
{
struct enc_ts_context *pactx = (struct enc_ts_context *)pa_ctx;
@@ -1855,8 +1852,7 @@ enc_ts_release(void *pa_ctx)
static krb5_error_code
pa_pac_step(krb5_context context, krb5_init_creds_context ctx, void *pa_ctx, PA_DATA *pa, const AS_REQ *a,
- const AS_REP *rep, const krb5_krbhst_info *hi,
- METHOD_DATA *in_md, METHOD_DATA *out_md)
+ const AS_REP *rep, METHOD_DATA *in_md, METHOD_DATA *out_md)
{
size_t len = 0, length;
krb5_error_code ret;
@@ -1888,8 +1884,7 @@ pa_pac_step(krb5_context context, krb5_init_creds_context ctx, void *pa_ctx, PA_
static krb5_error_code
pa_enc_pa_rep_step(krb5_context context, krb5_init_creds_context ctx, void *pa_ctx, PA_DATA *pa, const AS_REQ *a,
- const AS_REP *rep, const krb5_krbhst_info *hi,
- METHOD_DATA *in_md, METHOD_DATA *out_md)
+ const AS_REP *rep, METHOD_DATA *in_md, METHOD_DATA *out_md)
{
if (ctx->runflags.allow_enc_pa_rep)
return krb5_padata_add(context, out_md, KRB5_PADATA_REQ_ENC_PA_REP, NULL, 0);
@@ -1904,7 +1899,6 @@ pa_fx_cookie_step(krb5_context context,
PA_DATA *pa,
const AS_REQ *a,
const AS_REP *rep,
- const krb5_krbhst_info *hi,
METHOD_DATA *in_md,
METHOD_DATA *out_md)
{
@@ -1944,7 +1938,7 @@ pa_fx_cookie_step(krb5_context context,
typedef struct pa_info_data *(*pa_salt_info_f)(krb5_context, const krb5_principal, const AS_REQ *, struct pa_info_data *, heim_octet_string *);
typedef krb5_error_code (*pa_configure_f)(krb5_context, krb5_init_creds_context, void *);
typedef krb5_error_code (*pa_restart_f)(krb5_context, krb5_init_creds_context, void *);
-typedef krb5_error_code (*pa_step_f)(krb5_context, krb5_init_creds_context, void *, PA_DATA *, const AS_REQ *, const AS_REP *, const krb5_krbhst_info *, METHOD_DATA *, METHOD_DATA *);
+typedef krb5_error_code (*pa_step_f)(krb5_context, krb5_init_creds_context, void *, PA_DATA *, const AS_REQ *, const AS_REP *, METHOD_DATA *, METHOD_DATA *);
typedef void (*pa_release_f)(void *);
struct patype {
@@ -2145,7 +2139,7 @@ pa_announce(krb5_context context,
continue;
if (patypes[n].step)
- patypes[n].step(context, ctx, NULL, NULL, NULL, NULL, NULL, in_md, out_md);
+ patypes[n].step(context, ctx, NULL, NULL, NULL, NULL, in_md, out_md);
else
ret = krb5_padata_add(context, out_md, patypes[n].type, NULL, 0);
}
@@ -2258,7 +2252,6 @@ pa_step(krb5_context context,
krb5_init_creds_context ctx,
const AS_REQ *a,
const AS_REP *rep,
- const krb5_krbhst_info *hi,
METHOD_DATA *in_md,
METHOD_DATA *out_md)
{
@@ -2310,7 +2303,7 @@ pa_step(krb5_context context,
_krb5_debug(context, 5, "Stepping pa-mech: %s", ctx->pa_mech->patype->name);
- ret = ctx->pa_mech->patype->step(context, ctx, (void *)&ctx->pa_mech->pactx[0], pa, a, rep, hi, in_md, out_md);
+ ret = ctx->pa_mech->patype->step(context, ctx, (void *)&ctx->pa_mech->pactx[0], pa, a, rep, in_md, out_md);
_krb5_debug(context, 10, "PA type %s returned %d", ctx->pa_mech->patype->name, ret);
if (ret == 0) {
struct pa_auth_mech *next_pa = ctx->pa_mech->next;
@@ -2386,7 +2379,7 @@ process_pa_data_to_md(krb5_context context,
log_kdc_pa_types(context, in_md);
- ret = pa_step(context, ctx, a, NULL, NULL, in_md, *out_md);
+ ret = pa_step(context, ctx, a, NULL, in_md, *out_md);
if (ret == HEIM_ERR_PA_CONTINUE_NEEDED) {
_krb5_debug(context, 0, "pamech need more stepping");
} else if (ret == 0) {
@@ -2419,7 +2412,6 @@ process_pa_data_to_key(krb5_context context,
krb5_creds *creds,
AS_REQ *a,
AS_REP *rep,
- const krb5_krbhst_info *hi,
krb5_keyblock **key)
{
struct pa_info_data paid, *ppaid = NULL;
@@ -2446,7 +2438,7 @@ process_pa_data_to_key(krb5_context context,
}
}
- ret = pa_step(context, ctx, a, rep, hi, rep->padata, NULL);
+ ret = pa_step(context, ctx, a, rep, rep->padata, NULL);
if (ret == HEIM_ERR_PA_CONTINUE_NEEDED) {
_krb5_debug(context, 0, "In final stretch and pa require more stepping ?");
return ret;
@@ -2966,9 +2958,9 @@ available_padata_count(METHOD_DATA *md)
static krb5_error_code
init_creds_step(krb5_context context,
krb5_init_creds_context ctx,
- krb5_data *in,
+ const krb5_data *in,
krb5_data *out,
- krb5_krbhst_info *hostinfo,
+ krb5_realm *out_realm,
unsigned int *flags)
{
struct timeval start_time, end_time;
@@ -2981,6 +2973,7 @@ init_creds_step(krb5_context context,
gettimeofday(&start_time, NULL);
krb5_data_zero(out);
+ *out_realm = NULL;
krb5_data_zero(&checksum_data);
if (ctx->as_req.req_body.cname == NULL) {
@@ -3055,7 +3048,7 @@ init_creds_step(krb5_context context,
ret = process_pa_data_to_key(context, ctx, &ctx->cred,
&ctx->as_req, &rep.kdc_rep,
- hostinfo, &ctx->fast_state.reply_key);
+ &ctx->fast_state.reply_key);
if (ret) {
free_AS_REP(&rep.kdc_rep);
goto out;
@@ -3413,8 +3406,18 @@ init_creds_step(krb5_context context,
if(len != ctx->req_buffer.length)
krb5_abortx(context, "internal error in ASN.1 encoder");
- out->data = ctx->req_buffer.data;
- out->length = ctx->req_buffer.length;
+ ret = krb5_data_copy(out,
+ ctx->req_buffer.data,
+ ctx->req_buffer.length);
+ if (ret)
+ goto out;
+
+ *out_realm = strdup(ctx->cred.client->realm);
+ if (*out_realm == NULL) {
+ krb5_data_free(out);
+ ret = ENOMEM;
+ goto out;
+ }
*flags = KRB5_INIT_CREDS_STEP_FLAG_CONTINUE;
@@ -3436,9 +3439,9 @@ init_creds_step(krb5_context context,
*
* @param context a Kerberos 5 context.
* @param ctx ctx krb5_init_creds_context context.
- * @param in input data from KDC, first round it should be reset by krb5_data_zer().
- * @param out reply to KDC.
- * @param hostinfo KDC address info, first round it can be NULL.
+ * @param in input data from KDC, first round it should be reset by krb5_data_zero().
+ * @param out reply to KDC. The caller needs to call krb5_data_free()
+ * @param out_realm the destination realm for 'out', free with krb5_xfree()
* @param flags status of the round, if
* KRB5_INIT_CREDS_STEP_FLAG_CONTINUE is set, continue one more round.
*
@@ -3451,20 +3454,22 @@ init_creds_step(krb5_context context,
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_init_creds_step(krb5_context context,
krb5_init_creds_context ctx,
- krb5_data *in,
+ const krb5_data *in,
krb5_data *out,
- krb5_krbhst_info *hostinfo,
+ krb5_realm *out_realm,
unsigned int *flags)
{
krb5_error_code ret;
krb5_data empty;
krb5_data_zero(&empty);
+ krb5_data_zero(out);
+ *out_realm = NULL;
if ((ctx->fast_state.flags & KRB5_FAST_ANON_PKINIT_ARMOR) &&
ctx->fast_state.armor_ccache == NULL) {
ret = _krb5_fast_anon_pkinit_step(context, ctx, &ctx->fast_state,
- in, out, hostinfo, flags);
+ in, out, out_realm, flags);
if (ret && (ctx->fast_state.flags & KRB5_FAST_OPTIMISTIC)) {
_krb5_debug(context, 5, "Preauth failed with optimistic "
"FAST, trying w/o FAST");
@@ -3472,14 +3477,13 @@ krb5_init_creds_step(krb5_context context,
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)
+ (*flags & KRB5_INIT_CREDS_STEP_FLAG_CONTINUE))
return ret;
in = &empty;
}
- return init_creds_step(context, ctx, in, out, hostinfo, flags);
+ return init_creds_step(context, ctx, in, out, out_realm, flags);
}
/**
@@ -3672,7 +3676,6 @@ KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_init_creds_get(krb5_context context, krb5_init_creds_context ctx)
{
krb5_sendto_ctx stctx = NULL;
- krb5_krbhst_info *hostinfo = NULL;
krb5_error_code ret;
krb5_data in, out;
unsigned int flags = 0;
@@ -3692,9 +3695,10 @@ krb5_init_creds_get(krb5_context context, krb5_init_creds_context ctx)
while (1) {
struct timeval nstart, nend;
+ krb5_realm realm = NULL;
flags = 0;
- ret = krb5_init_creds_step(context, ctx, &in, &out, hostinfo, &flags);
+ ret = krb5_init_creds_step(context, ctx, &in, &out, &realm, &flags);
krb5_data_free(&in);
if (ret)
goto out;
@@ -3704,8 +3708,9 @@ krb5_init_creds_get(krb5_context context, krb5_init_creds_context ctx)
gettimeofday(&nstart, NULL);
- ret = krb5_sendto_context (context, stctx, &out,
- ctx->cred.client->realm, &in);
+ ret = krb5_sendto_context (context, stctx, &out, realm, &in);
+ krb5_data_free(&out);
+ free(realm);
if (ret)
goto out;
diff --git a/third_party/heimdal/lib/krb5/kcm.c b/third_party/heimdal/lib/krb5/kcm.c
index f20fc51936f..17a26e34f72 100644
--- a/third_party/heimdal/lib/krb5/kcm.c
+++ b/third_party/heimdal/lib/krb5/kcm.c
@@ -1355,7 +1355,7 @@ _krb5_kcm_is_running(krb5_context context)
krb5_ccache id = &ccdata;
krb5_boolean running;
- ret = kcm_alloc(context, NULL, NULL, NULL, &id);
+ ret = kcm_alloc(context, &krb5_kcm_ops, NULL, NULL, &id);
if (ret)
return 0;
diff --git a/third_party/heimdal/lib/krb5/krb5.conf.5 b/third_party/heimdal/lib/krb5/krb5.conf.5
index 8a9623ecada..06d069d251a 100644
--- a/third_party/heimdal/lib/krb5/krb5.conf.5
+++ b/third_party/heimdal/lib/krb5/krb5.conf.5
@@ -175,6 +175,18 @@ EXAMPLE.COM = {
delegate-destination-tgt = true
}
.Ed
+.It Li pkinit_pool = Va HX509-STORE
+This is a multi-valued parameter naming one or more stores of
+intermediate certification authority (CA) certificates for the
+client's end entity certificate.
+.It Li pkinit_anchors = Va HX509-STORE ...
+This is a multi-valued parameter naming one or more stores of
+anchors for PKINIT KDC certificates.
+.It Li pkinit_revoke = Va HX509-STORE ...
+This is a multi-valued parameter naming one or more stores of
+of CRLs for the issuers of PKINIT KDC certificates.
+If no CRLs are configured, then CRLs will not be checked.
+This is because hx509 currently lacks support.
.El
.It Li [libdefaults]
.Bl -tag -width "xxx" -offset indent
@@ -875,7 +887,7 @@ See the Heimdal hx509 documentation for more information.
This is a multi-valued parameter naming one or more stores of
intermediate certification authority (CA) certificates for the
KDC's end entity certificate.
-.It Li pkinit_anchors = Va HX509-STORE
+.It Li pkinit_anchors = Va HX509-STORE ...
This is a multi-valued parameter naming one or more stores of
anchors for PKINIT client certificates.
Note that the
@@ -885,6 +897,12 @@ type of
is also supported here.
.Va DIR
type stores are OpenSSL-style CA certificate hash directories.
+.It Li pkinit_revoke = Va HX509-STORE ...
+This is a multi-valued parameter naming one or more stores of
+of CRLs for the issuers of PKINIT client certificates.
+If no CRLs are configured, then CRLs will not be checked.
+This is because the KDC will not dereference CRL distribution
+points nor request OCSP responses.
.It Li pkinit_kdc_ocsp = Va PATH
This names a file whose contents is the DER encoding of an
OCSPResponse for the KDC's end entity certificate.
diff --git a/third_party/heimdal/lib/krb5/krb5_locl.h b/third_party/heimdal/lib/krb5/krb5_locl.h
index 91751c1baba..1b037cdcba3 100644
--- a/third_party/heimdal/lib/krb5/krb5_locl.h
+++ b/third_party/heimdal/lib/krb5/krb5_locl.h
@@ -82,6 +82,7 @@ struct mbuf;
#include <com_err.h>
#include <heimbase.h>
+#include "heimbase-atomics.h"
#define HEIMDAL_TEXTDOMAIN "heimdal_krb5"
diff --git a/third_party/heimdal/lib/krb5/krbhst.c b/third_party/heimdal/lib/krb5/krbhst.c
index 3688d6ad7ce..6ce7b53c5b6 100644
--- a/third_party/heimdal/lib/krb5/krbhst.c
+++ b/third_party/heimdal/lib/krb5/krbhst.c
@@ -352,7 +352,13 @@ append_host_hostinfo(struct krb5_krbhst_data *kd, struct krb5_krbhst_info *host)
_krb5_free_krbhst_info(host);
return;
}
- *kd->end = host;
+ /*
+ * We should always initialize kd->end in common_init(), but static
+ * analyzers may not see that we do, and the compiler might conclude
+ * there's UB here.
+ */
+ if (kd->end)
+ *kd->end = host;
kd->end = &host->next;
}
@@ -571,6 +577,7 @@ fallback_get_hosts(krb5_context context, struct krb5_krbhst_data *kd,
"Realm %s needs immediate attention "
"see https://icann.org/namecollision",
kd->realm);
+ free(host);
freeaddrinfo(ai);
return KRB5_KDC_UNREACH;
}
diff --git a/third_party/heimdal/lib/krb5/libkrb5-exports.def.in b/third_party/heimdal/lib/krb5/libkrb5-exports.def.in
index 191a0c48c86..3845cd73601 100644
--- a/third_party/heimdal/lib/krb5/libkrb5-exports.def.in
+++ b/third_party/heimdal/lib/krb5/libkrb5-exports.def.in
@@ -506,7 +506,9 @@ EXPORTS
krb5_pac_get_kdc_checksum_info
krb5_pac_get_types
krb5_pac_init
+ krb5_pac_is_trusted
krb5_pac_parse
+ krb5_pac_set_trusted
krb5_pac_verify
krb5_padata_add
_krb5_parse_address_no_lookup
diff --git a/third_party/heimdal/lib/krb5/pac.c b/third_party/heimdal/lib/krb5/pac.c
index 26403e665a0..a944b9391c1 100644
--- a/third_party/heimdal/lib/krb5/pac.c
+++ b/third_party/heimdal/lib/krb5/pac.c
@@ -85,6 +85,8 @@ struct krb5_pac_data {
/* PAC_ATTRIBUTES_INFO */
uint64_t pac_attributes;
+
+ krb5_boolean is_trusted;
};
#define PAC_ALIGNMENT 8
@@ -662,6 +664,30 @@ krb5_pac_get_types(krb5_context context,
*
*/
+KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
+krb5_pac_is_trusted(krb5_const_pac p)
+{
+ return p->is_trusted;
+}
+
+/*
+ *
+ */
+
+KRB5_LIB_FUNCTION void KRB5_LIB_CALL
+krb5_pac_set_trusted(krb5_pac p, krb5_boolean is_trusted)
+{
+ p->is_trusted = is_trusted;
+}
+
+/*
+ *
+ */
+
+/*
+ *
+ */
+
KRB5_LIB_FUNCTION void KRB5_LIB_CALL
krb5_pac_free(krb5_context context, krb5_pac pac)
{
diff --git a/third_party/heimdal/lib/krb5/pkinit-ec.c b/third_party/heimdal/lib/krb5/pkinit-ec.c
index 33bc62c8dce..34cefd506fe 100644
--- a/third_party/heimdal/lib/krb5/pkinit-ec.c
+++ b/third_party/heimdal/lib/krb5/pkinit-ec.c
@@ -56,6 +56,7 @@
#include <openssl/ecdh.h>
#include <openssl/evp.h>
#include <openssl/bn.h>
+#include <openssl/dh.h>
#define HEIM_NO_CRYPTO_HDRS
#endif
@@ -125,6 +126,9 @@ _krb5_build_authpack_subjectPK_EC(krb5_context context,
if (ret)
return ret;
+#ifdef HAVE_OPENSSL_30
+ ctx->u.eckey = EVP_EC_gen(OSSL_EC_curve_nid2name(NID_X9_62_prime256v1));
+#else
ctx->u.eckey = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
if (ctx->u.eckey == NULL)
return krb5_enomem(context);
@@ -132,8 +136,13 @@ _krb5_build_authpack_subjectPK_EC(krb5_context context,
ret = EC_KEY_generate_key(ctx->u.eckey);
if (ret != 1)
return EINVAL;
+#endif
+#ifdef HAVE_OPENSSL_30
+ xlen = i2d_PublicKey(ctx->u.eckey, NULL);
+#else
xlen = i2o_ECPublicKey(ctx->u.eckey, NULL);
+#endif
if (xlen <= 0)
return EINVAL;
@@ -143,7 +152,11 @@ _krb5_build_authpack_subjectPK_EC(krb5_context context,
a->clientPublicValue->subjectPublicKey.data = p;
+#ifdef HAVE_OPENSSL_30
+ xlen = i2d_PublicKey(ctx->u.eckey, &p);
+#else
xlen = i2o_ECPublicKey(ctx->u.eckey, &p);
+#endif
if (xlen <= 0) {
a->clientPublicValue->subjectPublicKey.data = NULL;
free(p);
@@ -171,6 +184,61 @@ _krb5_pk_rd_pa_reply_ecdh_compute_key(krb5_context context,
int *out_sz)
{
#ifdef HAVE_HCRYPTO_W_OPENSSL
+#ifdef HAVE_OPENSSL_30
+ krb5_error_code ret = 0;
+ EVP_PKEY_CTX *pctx = NULL;
+ EVP_PKEY *template = NULL;
+ EVP_PKEY *public = NULL;
+ size_t shared_len = 0;
+
+ if ((template = EVP_PKEY_new()) == NULL)
+ ret = krb5_enomem(context);
+ if (ret == 0 &&
+ EVP_PKEY_copy_parameters(template, ctx->u.eckey) != 1)
+ ret = krb5_enomem(context);
+ if (ret == 0 && (pctx = EVP_PKEY_CTX_new(ctx->u.eckey, NULL)) == NULL)
+ ret = krb5_enomem(context);
+ if (ret == 0 && EVP_PKEY_derive_init(pctx) != 1)
+ ret = krb5_enomem(context);
+ if (ret == 0 &&
+ EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, EVP_PKEY_ECDH_KDF_NONE) != 1)
+ ret = krb5_enomem(context);
+ if (ret == 0 &&
+ (public = d2i_PublicKey(EVP_PKEY_EC, &template, &in, in_sz)) == NULL)
+ krb5_set_error_message(context,
+ ret = HX509_PARSING_KEY_FAILED,
+ "PKINIT: Can't parse the KDC's ECDH public key");
+ if (ret == 0 &&
+ EVP_PKEY_derive_set_peer_ex(pctx, public, 1) != 1)
+ krb5_set_error_message(context,
+ ret = KRB5KRB_ERR_GENERIC,
+ "Could not derive ECDH shared secret for PKINIT key exchange "
+ "(EVP_PKEY_derive_set_peer_ex)");
+ if (ret == 0 &&
+ (EVP_PKEY_derive(pctx, NULL, &shared_len) != 1 || shared_len == 0))
+ krb5_set_error_message(context,
+ ret = KRB5KRB_ERR_GENERIC,
+ "Could not derive ECDH shared secret for PKINIT key exchange "
+ "(EVP_PKEY_derive to get length)");
+ if (ret == 0 && shared_len > INT_MAX)
+ krb5_set_error_message(context,
+ ret = KRB5KRB_ERR_GENERIC,
+ "Could not derive ECDH shared secret for PKINIT key exchange "
+ "(shared key too large)");
+ if (ret == 0 && (*out = malloc(shared_len)) == NULL)
+ ret = krb5_enomem(context);
+ if (ret == 0 && EVP_PKEY_derive(pctx, *out, &shared_len) != 1)
+ krb5_set_error_message(context,
+ ret = KRB5KRB_ERR_GENERIC,
+ "Could not derive ECDH shared secret for PKINIT key exchange "
+ "(EVP_PKEY_derive)");
+ if (ret == 0)
+ *out_sz = shared_len;
+ EVP_PKEY_CTX_free(pctx); // move
+ EVP_PKEY_free(template);
+
+ return ret;
+#else
krb5_error_code ret = 0;
int dh_gen_keylen;
@@ -219,6 +287,7 @@ _krb5_pk_rd_pa_reply_ecdh_compute_key(krb5_context context,
*out_sz = dh_gen_keylen;
return ret;
+#endif
#else
krb5_set_error_message(context, ENOTSUP,
N_("PKINIT: ECDH not supported", ""));
@@ -230,8 +299,12 @@ void
_krb5_pk_eckey_free(void *eckey)
{
#ifdef HAVE_HCRYPTO_W_OPENSSL
+#ifdef HAVE_OPENSSL_30
+ EVP_PKEY_free(eckey);
+#else
EC_KEY_free(eckey);
#endif
+#endif
}
#else
diff --git a/third_party/heimdal/lib/krb5/pkinit.c b/third_party/heimdal/lib/krb5/pkinit.c
index 0501728d3e5..2a0979b7e12 100644
--- a/third_party/heimdal/lib/krb5/pkinit.c
+++ b/third_party/heimdal/lib/krb5/pkinit.c
@@ -1014,7 +1014,6 @@ get_reply_key(krb5_context context,
static krb5_error_code
pk_verify_host(krb5_context context,
const char *realm,
- const krb5_krbhst_info *hi,
struct krb5_pk_init_ctx_data *ctx,
struct krb5_pk_cert *host)
{
@@ -1092,18 +1091,6 @@ pk_verify_host(krb5_context context,
if (ret)
return ret;
- if (hi) {
- ret = hx509_verify_hostname(context->hx509ctx, host->cert,
- ctx->require_hostname_match,
- HX509_HN_HOSTNAME,
- hi->hostname,
- hi->ai->ai_addr, hi->ai->ai_addrlen);
-
- if (ret)
- krb5_set_error_message(context, ret,
- N_("Address mismatch in "
- "the KDC certificate", ""));
- }
return ret;
}
@@ -1115,7 +1102,6 @@ pk_rd_pa_reply_enckey(krb5_context context,
const char *realm,
krb5_pk_init_ctx ctx,
krb5_enctype etype,
- const krb5_krbhst_info *hi,
unsigned nonce,
const krb5_data *req_buffer,
PA_DATA *pa,
@@ -1219,7 +1205,7 @@ pk_rd_pa_reply_enckey(krb5_context context,
if (host) {
/* make sure that it is the kdc's certificate */
- ret = pk_verify_host(context, realm, hi, ctx, host);
+ ret = pk_verify_host(context, realm, ctx, host);
if (ret)
goto out;
@@ -1365,7 +1351,6 @@ pk_rd_pa_reply_dh(krb5_context context,
const char *realm,
krb5_pk_init_ctx ctx,
krb5_enctype etype,
- const krb5_krbhst_info *hi,
const DHNonce *c_n,
const DHNonce *k_n,
unsigned nonce,
@@ -1407,7 +1392,7 @@ pk_rd_pa_reply_dh(krb5_context context,
if (host) {
/* make sure that it is the kdc's certificate */
- ret = pk_verify_host(context, realm, hi, ctx, host);
+ ret = pk_verify_host(context, realm, ctx, host);
if (ret)
goto out;
@@ -1567,7 +1552,6 @@ _krb5_pk_rd_pa_reply(krb5_context context,
const char *realm,
void *c,
krb5_enctype etype,
- const krb5_krbhst_info *hi,
unsigned nonce,
const krb5_data *req_buffer,
PA_DATA *pa,
@@ -1658,14 +1642,14 @@ _krb5_pk_rd_pa_reply(krb5_context context,
switch (rep.element) {
case choice_PA_PK_AS_REP_dhInfo:
- ret = pk_rd_pa_reply_dh(context, &data, &oid, realm, ctx, etype, hi,
+ ret = pk_rd_pa_reply_dh(context, &data, &oid, realm, ctx, etype,
ctx->clientDHNonce,
rep.u.dhInfo.serverDHNonce,
nonce, pa, key);
break;
case choice_PA_PK_AS_REP_encKeyPack:
ret = pk_rd_pa_reply_enckey(context, PKINIT_27, &data, &oid, realm,
- ctx, etype, hi, nonce, req_buffer, pa, key);
+ ctx, etype, nonce, req_buffer, pa, key);
break;
default:
krb5_abortx(context, "pk-init as-rep case not possible to happen");
@@ -1717,7 +1701,7 @@ _krb5_pk_rd_pa_reply(krb5_context context,
}
ret = pk_rd_pa_reply_enckey(context, PKINIT_WIN2K, &data, &oid, realm,
- ctx, etype, hi, nonce, req_buffer, pa, key);
+ ctx, etype, nonce, req_buffer, pa, key);
der_free_octet_string(&data);
der_free_oid(&oid);
@@ -2124,17 +2108,22 @@ _krb5_parse_moduli_line(krb5_context context,
return ret;
}
+static void
+free_moduli_element(struct krb5_dh_moduli *element)
+{
+ free(element->name);
+ der_free_heim_integer(&element->p);
+ der_free_heim_integer(&element->g);
+ der_free_heim_integer(&element->q);
+ free(element);
+}
+
KRB5_LIB_FUNCTION void KRB5_LIB_CALL
_krb5_free_moduli(struct krb5_dh_moduli **moduli)
{
int i;
- for (i = 0; moduli[i] != NULL; i++) {
- free(moduli[i]->name);
- der_free_heim_integer(&moduli[i]->p);
- der_free_heim_integer(&moduli[i]->g);
- der_free_heim_integer(&moduli[i]->q);
- free(moduli[i]);
- }
+ for (i = 0; moduli[i] != NULL; i++)
+ free_moduli_element(moduli[i]);
free(moduli);
}
@@ -2252,29 +2241,33 @@ _krb5_parse_moduli(krb5_context context, const char *file,
buf[strcspn(buf, "\n")] = '\0';
lineno++;
+ ret = _krb5_parse_moduli_line(context, file, lineno, buf, &element);
+ if (ret)
+ break;
+ if (element == NULL)
+ continue;
+
m2 = realloc(m, (n + 2) * sizeof(m[0]));
if (m2 == NULL) {
- _krb5_free_moduli(m);
- return krb5_enomem(context);
+ free_moduli_element(element);
+ ret = krb5_enomem(context);
+ break;
}
m = m2;
- m[n] = NULL;
-
- ret = _krb5_parse_moduli_line(context, file, lineno, buf, &element);
- if (ret) {
- _krb5_free_moduli(m);
- return ret;
- }
- if (element == NULL)
- continue;
-
m[n] = element;
m[n + 1] = NULL;
n++;
}
+ if (ret) {
+ _krb5_free_moduli(m);
+ m = NULL;
+ }
+
*moduli = m;
- return 0;
+
+ (void) fclose(f);
+ return ret;
}
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
diff --git a/third_party/heimdal/lib/krb5/principal.c b/third_party/heimdal/lib/krb5/principal.c
index 91743488d9f..ec9649dfed5 100644
--- a/third_party/heimdal/lib/krb5/principal.c
+++ b/third_party/heimdal/lib/krb5/principal.c
@@ -1789,6 +1789,8 @@ _krb5_get_name_canon_rules(krb5_context context, krb5_name_canon_rule *rules)
krb5_config_free_strings(values);
if (ret)
return ret;
+ if (*rules == NULL)
+ return krb5_enomem(context);
if (krb5_config_get_bool_default(context, NULL, FALSE,
"libdefaults", "safe_name_canon", NULL))
@@ -1857,7 +1859,7 @@ apply_name_canon_rule(krb5_context context, krb5_name_canon_rule rules,
krb5_name_canon_rule_options *rule_opts)
{
krb5_name_canon_rule rule = &rules[rule_idx];
- krb5_error_code ret;
+ krb5_error_code ret = 0;
unsigned int ndots = 0;
krb5_principal nss = NULL;
const char *sname = NULL;
@@ -1902,17 +1904,17 @@ apply_name_canon_rule(krb5_context context, krb5_name_canon_rule rules,
ndots++;
}
if (rule->mindots > 0 && ndots < rule->mindots)
- return 0;
+ goto out;
if (ndots > rule->maxdots)
- return 0;
+ goto out;
if (rule->match_domain != NULL &&
!is_domain_suffix(orig_hostname, rule->match_domain))
- return 0;
+ goto out;
if (rule->match_realm != NULL &&
strcmp(rule->match_realm, in_princ->realm) != 0)
- return 0;
+ goto out;
new_realm = rule->realm;
switch (rule->type) {
diff --git a/third_party/heimdal/lib/krb5/rd_req.c b/third_party/heimdal/lib/krb5/rd_req.c
index 371037c8403..012cfefc2d8 100644
--- a/third_party/heimdal/lib/krb5/rd_req.c
+++ b/third_party/heimdal/lib/krb5/rd_req.c
@@ -1037,11 +1037,10 @@ 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 (krb5_ticket_get_authorization_data_type(context, o->ticket,
+ KRB5_AUTHDATA_KDC_ISSUED,
+ NULL) == 0)
+ o->ticket->client->nameattrs->kdc_issued_verified = 1;
/* If there is a PAC, verify its server signature */
if (inctx == NULL || inctx->check_pac) {
diff --git a/third_party/heimdal/lib/krb5/recvauth.c b/third_party/heimdal/lib/krb5/recvauth.c
index caf1451b2b1..656378309db 100644
--- a/third_party/heimdal/lib/krb5/recvauth.c
+++ b/third_party/heimdal/lib/krb5/recvauth.c
@@ -160,6 +160,11 @@ krb5_recvauth_match_version(krb5_context context,
return KRB5_SENDAUTH_BADAPPLVERS;
}
len = ntohl(len);
+ if (len > 1024 * 1024) {
+ krb5_set_error_message(context, ret = KRB5_SENDAUTH_REJECTED,
+ "AP-REQ too long");
+ return ret;
+ }
her_appl_version = malloc (len);
if (her_appl_version == NULL) {
repl = 2;
diff --git a/third_party/heimdal/lib/krb5/salt-aes-sha2.c b/third_party/heimdal/lib/krb5/salt-aes-sha2.c
index bfd726c34c1..bc674bd2dab 100644
--- a/third_party/heimdal/lib/krb5/salt-aes-sha2.c
+++ b/third_party/heimdal/lib/krb5/salt-aes-sha2.c
@@ -92,8 +92,9 @@ AES_SHA2_string_to_key(krb5_context context,
goto cleanup;
}
memcpy(saltp.data, et->name, enctypesz);
- memcpy((unsigned char *)saltp.data + enctypesz,
- salt.saltvalue.data, salt.saltvalue.length);
+ if (salt.saltvalue.length)
+ memcpy((unsigned char *)saltp.data + enctypesz,
+ salt.saltvalue.data, salt.saltvalue.length);
ret = _krb5_aes_sha2_md_for_enctype(context, enctype, &md);
if (ret)
diff --git a/third_party/heimdal/lib/krb5/salt-des.c b/third_party/heimdal/lib/krb5/salt-des.c
index d898d6c2057..474ba5d591d 100644
--- a/third_party/heimdal/lib/krb5/salt-des.c
+++ b/third_party/heimdal/lib/krb5/salt-des.c
@@ -194,7 +194,8 @@ krb5_DES_string_to_key(krb5_context context,
if (len > 0 && s == NULL)
return krb5_enomem(context);
memcpy(s, password.data, password.length);
- memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
+ if (salt.saltvalue.length)
+ memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
DES_string_to_key_int(s, len, &tmp);
key->keytype = enctype;
krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
diff --git a/third_party/heimdal/lib/krb5/salt-des3.c b/third_party/heimdal/lib/krb5/salt-des3.c
index 8cb73cf465a..a9293ccec9c 100644
--- a/third_party/heimdal/lib/krb5/salt-des3.c
+++ b/third_party/heimdal/lib/krb5/salt-des3.c
@@ -113,7 +113,8 @@ DES3_string_to_key_derived(krb5_context context,
if (len != 0 && s == NULL)
return krb5_enomem(context);
memcpy(s, password.data, password.length);
- memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
+ if (salt.saltvalue.length)
+ memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
ret = krb5_string_to_key_derived(context,
s,
len,
diff --git a/third_party/heimdal/lib/krb5/scache.c b/third_party/heimdal/lib/krb5/scache.c
index 7a39664946b..479c58b8ff1 100644
--- a/third_party/heimdal/lib/krb5/scache.c
+++ b/third_party/heimdal/lib/krb5/scache.c
@@ -1285,6 +1285,9 @@ scc_remove_cred(krb5_context context,
sqlite3_finalize(stmt);
+ if (ret)
+ return ret;
+
ret = prepare_stmt(context, s->db, &stmt,
"DELETE FROM credentials WHERE oid=?");
if (ret)
diff --git a/third_party/heimdal/lib/krb5/sendauth.c b/third_party/heimdal/lib/krb5/sendauth.c
index 5011c268089..a2c8aedb8ea 100644
--- a/third_party/heimdal/lib/krb5/sendauth.c
+++ b/third_party/heimdal/lib/krb5/sendauth.c
@@ -109,6 +109,7 @@ krb5_sendauth(krb5_context context,
ssize_t sret;
krb5_boolean my_ccache = FALSE;
+ memset(&this_cred, 0, sizeof(this_cred));
len = strlen(version) + 1;
net_len = htonl(len);
if (krb5_net_write (context, p_fd, &net_len, 4) != 4
@@ -159,7 +160,6 @@ krb5_sendauth(krb5_context context,
}
client = this_client;
}
- memset(&this_cred, 0, sizeof(this_cred));
this_cred.client = client;
this_cred.server = server;
this_cred.times.endtime = 0;
@@ -185,13 +185,6 @@ krb5_sendauth(krb5_context context,
creds,
&ap_req);
- if (out_creds)
- *out_creds = creds;
- else
- krb5_free_creds(context, creds);
- if(this_client)
- krb5_free_principal(context, this_client);
-
if (ret)
return ret;
@@ -251,5 +244,14 @@ krb5_sendauth(krb5_context context,
if (rep_result == NULL)
krb5_free_ap_rep_enc_part (context, ignore);
}
- return 0;
+
+ if (out_creds)
+ ret = krb5_copy_creds(context, creds, out_creds);
+
+ this_cred.server = NULL;
+ if (creds == &this_cred)
+ krb5_free_cred_contents(context, creds);
+ else if (creds)
+ krb5_free_creds(context, creds);
+ return ret;
}
diff --git a/third_party/heimdal/lib/krb5/store.c b/third_party/heimdal/lib/krb5/store.c
index 8b966f83e79..f95fd83aa95 100644
--- a/third_party/heimdal/lib/krb5/store.c
+++ b/third_party/heimdal/lib/krb5/store.c
@@ -300,7 +300,7 @@ krb5_storage_free(krb5_storage *sp)
}
/**
- * Copy the contnent of storage
+ * Copy the content of storage to a krb5_data.
*
* @param sp the storage to copy to a data
* @param data the copied data, free with krb5_data_free()
@@ -329,9 +329,18 @@ krb5_storage_to_data(krb5_storage *sp, krb5_data *data)
return ret;
}
if (size) {
+ ssize_t bytes;
+
sp->seek(sp, 0, SEEK_SET);
- sp->fetch(sp, data->data, data->length);
+ bytes = sp->fetch(sp, data->data, data->length);
sp->seek(sp, pos, SEEK_SET);
+
+ /* sp->fetch() really shouldn't fail */
+ if (bytes < 0)
+ return sp->eof_code;
+
+ /* Maybe the underlying file (or whatever) got truncated? */
+ data->length = bytes;
}
return 0;
}
@@ -528,6 +537,8 @@ krb5_ret_int(krb5_storage *sp,
ret = sp->fetch(sp, v, 1);
if (ret < 0)
return errno;
+ if (ret != 1)
+ return sp->eof_code;
len = unpack_int_length(v);
if (len < 1)
@@ -536,6 +547,8 @@ krb5_ret_int(krb5_storage *sp,
ret = sp->fetch(sp, v + 1, len - 1);
if (ret < 0)
return errno;
+ if (ret != len - 1)
+ return sp->eof_code;
}
ret = unpack_int(v, len, &w, &len);
if (ret)
@@ -816,10 +829,10 @@ KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_ret_int8(krb5_storage *sp,
int8_t *value)
{
- int ret;
+ ssize_t ret;
ret = sp->fetch(sp, value, sizeof(*value));
- if (ret != sizeof(*value))
+ if (ret < 0 || (size_t)ret != sizeof(*value))
return (ret<0)?errno:sp->eof_code;
return 0;
}
@@ -937,7 +950,7 @@ KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_ret_data(krb5_storage *sp,
krb5_data *data)
{
- int ret;
+ krb5_error_code ret;
int32_t size;
ret = krb5_ret_int32(sp, &size);
@@ -950,8 +963,10 @@ krb5_ret_data(krb5_storage *sp,
if (ret)
return ret;
if (size) {
- ret = sp->fetch(sp, data->data, size);
- if(ret != size) {
+ ssize_t bytes;
+
+ bytes = sp->fetch(sp, data->data, size);
+ if (bytes < 0 || bytes != size) {
krb5_data_free(data);
return (ret < 0)? errno : sp->eof_code;
}
@@ -1869,7 +1884,8 @@ _krb5_ret_data_at_offset(krb5_storage *sp,
sp->seek(sp, offset, SEEK_SET);
size = sp->fetch(sp, data->data, length);
- heim_assert(size == length, "incomplete buffer fetched");
+ if (size < 0 || (size_t)size != length)
+ return sp->eof_code;
}
cleanup:
@@ -1945,7 +1961,7 @@ _krb5_store_data_at_offset(krb5_storage *sp,
krb5_ssize_t nbytes;
off_t pos;
- if (offset == (off_t)-1) {
+ if (offset == (size_t)-1) {
if (data == NULL || data->data == NULL) {
offset = 0;
} else {
@@ -1953,7 +1969,7 @@ _krb5_store_data_at_offset(krb5_storage *sp,
offset = sp->seek(sp, 0, SEEK_END);
sp->seek(sp, pos, SEEK_SET);
- if (offset == (off_t)-1)
+ if (offset == (size_t)-1)
return HEIM_ERR_NOT_SEEKABLE;
}
}
@@ -2025,7 +2041,6 @@ _krb5_store_utf8_as_ucs2le_at_offset(krb5_storage *sp,
ucs2le = NULL;
ucs2le_size = 0;
offset = 0;
- ret = 0;
}
{
diff --git a/third_party/heimdal/lib/krb5/store_emem.c b/third_party/heimdal/lib/krb5/store_emem.c
index 6a3908f7463..daef4d793e0 100644
--- a/third_party/heimdal/lib/krb5/store_emem.c
+++ b/third_party/heimdal/lib/krb5/store_emem.c
@@ -84,7 +84,8 @@ emem_store(krb5_storage *sp, const void *data, size_t size)
s->base = base;
s->ptr = (unsigned char*)base + off;
}
- memmove(s->ptr, data, size);
+ if (size)
+ memmove(s->ptr, data, size);
sp->seek(sp, size, SEEK_CUR);
return size;
}
@@ -125,10 +126,17 @@ emem_trunc(krb5_storage *sp, off_t offset)
* shrunk more then half of the current size, adjust buffer.
*/
if (offset == 0) {
- free(s->base);
- s->size = 0;
- s->base = NULL;
- s->ptr = NULL;
+ if (s->size > 1024) {
+ void *base;
+
+ base = realloc(s->base, 1024);
+ if (base) {
+ s->base = base;
+ s->size = 1024;
+ }
+ }
+ s->len = 0;
+ s->ptr = s->base;
} else if ((size_t)offset > s->size || (s->size / 2) > (size_t)offset) {
void *base;
size_t off;
@@ -209,6 +217,6 @@ krb5_storage_emem(void)
sp->trunc = emem_trunc;
sp->fsync = NULL;
sp->free = emem_free;
- sp->max_alloc = UINT_MAX/8;
+ sp->max_alloc = UINT32_MAX/64;
return sp;
}
diff --git a/third_party/heimdal/lib/krb5/store_fd.c b/third_party/heimdal/lib/krb5/store_fd.c
index 720ed66f75b..9184e593ab6 100644
--- a/third_party/heimdal/lib/krb5/store_fd.c
+++ b/third_party/heimdal/lib/krb5/store_fd.c
@@ -195,6 +195,6 @@ krb5_storage_from_fd(int fd_in)
sp->trunc = fd_trunc;
sp->fsync = fd_sync;
sp->free = fd_free;
- sp->max_alloc = UINT_MAX/8;
+ sp->max_alloc = UINT32_MAX/64;
return sp;
}
diff --git a/third_party/heimdal/lib/krb5/store_mem.c b/third_party/heimdal/lib/krb5/store_mem.c
index ff2a570ca62..638c341a64f 100644
--- a/third_party/heimdal/lib/krb5/store_mem.c
+++ b/third_party/heimdal/lib/krb5/store_mem.c
@@ -147,7 +147,7 @@ krb5_storage_from_mem(void *buf, size_t len)
sp->trunc = mem_trunc;
sp->fsync = NULL;
sp->free = NULL;
- sp->max_alloc = UINT_MAX/8;
+ sp->max_alloc = UINT32_MAX/64;
return sp;
}
@@ -207,6 +207,6 @@ krb5_storage_from_readonly_mem(const void *buf, size_t len)
sp->trunc = mem_no_trunc;
sp->fsync = NULL;
sp->free = NULL;
- sp->max_alloc = UINT_MAX/8;
+ sp->max_alloc = UINT32_MAX/64;
return sp;
}
diff --git a/third_party/heimdal/lib/krb5/store_sock.c b/third_party/heimdal/lib/krb5/store_sock.c
index fd6fe8f4c6c..72d3e9d22bd 100644
--- a/third_party/heimdal/lib/krb5/store_sock.c
+++ b/third_party/heimdal/lib/krb5/store_sock.c
@@ -82,10 +82,13 @@ static void
socket_free(krb5_storage * sp)
{
int save_errno = errno;
- if (rk_IS_SOCKET_ERROR(rk_closesocket(SOCK(sp))))
+ if (rk_IS_SOCKET_ERROR(rk_closesocket(SOCK(sp)))) {
+#ifdef WIN32
errno = rk_SOCK_ERRNO;
- else
+#endif
+ } else {
errno = save_errno;
+ }
}
/**
@@ -155,6 +158,6 @@ krb5_storage_from_socket(krb5_socket_t sock_in)
sp->trunc = socket_trunc;
sp->fsync = socket_sync;
sp->free = socket_free;
- sp->max_alloc = UINT_MAX/8;
+ sp->max_alloc = UINT32_MAX/64;
return sp;
}
diff --git a/third_party/heimdal/lib/krb5/store_stdio.c b/third_party/heimdal/lib/krb5/store_stdio.c
index dddaa924578..9244b9e7f5f 100644
--- a/third_party/heimdal/lib/krb5/store_stdio.c
+++ b/third_party/heimdal/lib/krb5/store_stdio.c
@@ -83,6 +83,13 @@ stdio_store(krb5_storage * sp, const void *data, size_t size)
ssize_t count;
size_t rem = size;
+ /*
+ * It's possible we just went from reading to writing if the file was open
+ * for both. Per C99 (N869 final draft) section 7.18.5.3, point 6, when
+ * going from reading to writing [a file opened for both] one must seek.
+ */
+ (void) fseeko(F(sp), 0, SEEK_CUR);
+
/* similar pattern to net_write() to support pipes */
while (rem > 0) {
count = fwrite(cbuf, 1, rem, F(sp));
@@ -259,6 +266,6 @@ krb5_storage_stdio_from_fd(int fd_in, const char *mode)
sp->trunc = stdio_trunc;
sp->fsync = stdio_sync;
sp->free = stdio_free;
- sp->max_alloc = UINT_MAX/8;
+ sp->max_alloc = UINT32_MAX/64;
return sp;
}
diff --git a/third_party/heimdal/lib/krb5/version-script.map b/third_party/heimdal/lib/krb5/version-script.map
index f6278e9ecbf..a81b08fa147 100644
--- a/third_party/heimdal/lib/krb5/version-script.map
+++ b/third_party/heimdal/lib/krb5/version-script.map
@@ -499,7 +499,9 @@ HEIMDAL_KRB5_2.0 {
krb5_pac_get_kdc_checksum_info;
krb5_pac_get_types;
krb5_pac_init;
+ krb5_pac_is_trusted;
krb5_pac_parse;
+ krb5_pac_set_trusted;
krb5_pac_verify;
krb5_padata_add;
_krb5_parse_address_no_lookup;
diff --git a/third_party/heimdal/lib/otp/otp_db.c b/third_party/heimdal/lib/otp/otp_db.c
index 76daa870aa2..c7b2b763a01 100644
--- a/third_party/heimdal/lib/otp/otp_db.c
+++ b/third_party/heimdal/lib/otp/otp_db.c
@@ -226,7 +226,7 @@ otp_put (void *v, OtpContext *ctx)
return -1;
strlcpy (p, ctx->seed, rem);
p += len;
- rem -= len;
+ /* rem -= len; */
dat.dptr = buf;
dat.dsize = p - buf;
return dbm_store (dbm, key, dat, DBM_REPLACE);
diff --git a/third_party/heimdal/lib/roken/Makefile.am b/third_party/heimdal/lib/roken/Makefile.am
index f6d038f3f6e..1f530c7aee5 100644
--- a/third_party/heimdal/lib/roken/Makefile.am
+++ b/third_party/heimdal/lib/roken/Makefile.am
@@ -198,6 +198,9 @@ EXTRA_libroken_la_SOURCES = \
vis.hin
libroken_la_LIBADD = @LTLIBOBJS@ $(LIB_crypt) $(LIB_pidfile)
+if SUNOS
+libroken_la_LIBADD += -lnsl -lsocket
+endif
$(LTLIBOBJS) $(libroken_la_OBJECTS): roken.h $(XHEADERS)
diff --git a/third_party/heimdal/lib/roken/base32.c b/third_party/heimdal/lib/roken/base32.c
index 4ec86ae90f1..1a275321644 100644
--- a/third_party/heimdal/lib/roken/base32.c
+++ b/third_party/heimdal/lib/roken/base32.c
@@ -141,9 +141,7 @@ token_decode(const char *token, enum rk_base32_flags flags)
int preserve_order = !!(flags & RK_BASE32_FLAG_PRESERVE_ORDER);
int i, c;
- if (strlen(token) < 8)
- return DECODE_ERROR;
- for (i = 0; i < 8; i++) {
+ for (i = 0; i < 8 && token[i] != '\0'; i++) {
val <<= 5;
if (token[i] == '=')
marker++;
@@ -157,7 +155,7 @@ token_decode(const char *token, enum rk_base32_flags flags)
else
val |= c;
}
- if (marker > 6)
+ if (i < 8 || marker > 6)
return DECODE_ERROR;
return (marker << 40) | val;
}
diff --git a/third_party/heimdal/lib/roken/base64.c b/third_party/heimdal/lib/roken/base64.c
index 582d183bcf7..1391c828079 100644
--- a/third_party/heimdal/lib/roken/base64.c
+++ b/third_party/heimdal/lib/roken/base64.c
@@ -45,17 +45,31 @@
#include "base64.h"
#include "roken.h"
-static const char base64_chars[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+#define base64_chars "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
static int
pos(char c)
{
+#if 'A' == '\301'
const char *p;
for (p = base64_chars; *p; p++)
if (*p == c)
return p - base64_chars;
return -1;
+#else
+ if (c >= 'A' && c <= 'Z')
+ return c - 'A';
+ if (c >= 'a' && c <= 'z')
+ return ('Z' + 1 - 'A') + c - 'a';
+ if (c >= '0' && c <= '9')
+ return ('Z' + 1 - 'A') +
+ ('z' + 1 - 'a') + c - '0';
+ if (c == '+')
+ return 62;
+ if (c == '/')
+ return 63;
+ return -1;
+#endif
}
ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
@@ -112,9 +126,7 @@ token_decode(const char *token)
int i;
unsigned int val = 0;
int marker = 0;
- if (strlen(token) < 4)
- return DECODE_ERROR;
- for (i = 0; i < 4; i++) {
+ for (i = 0; i < 4 && token[i] != '\0'; i++) {
val *= 64;
if (token[i] == '=')
marker++;
@@ -123,7 +135,7 @@ token_decode(const char *token)
else
val += pos(token[i]);
}
- if (marker > 2)
+ if (i < 4 || marker > 2)
return DECODE_ERROR;
return (marker << 24) | val;
}
@@ -135,7 +147,7 @@ rk_base64_decode(const char *str, void *data)
unsigned char *q;
q = data;
- for (p = str; *p && (*p == '=' || strchr(base64_chars, *p)); p += 4) {
+ for (p = str; *p && (*p == '=' || pos(*p) != -1); p += 4) {
unsigned int val = token_decode(p);
unsigned int marker = (val >> 24) & 0xff;
if (val == DECODE_ERROR) {
diff --git a/third_party/heimdal/lib/roken/closefrom.c b/third_party/heimdal/lib/roken/closefrom.c
index 770eb2c67ac..1a950f7a867 100644
--- a/third_party/heimdal/lib/roken/closefrom.c
+++ b/third_party/heimdal/lib/roken/closefrom.c
@@ -43,7 +43,7 @@
#include "roken.h"
ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
-closefrom(int fd)
+rk_closefrom(int fd)
{
int num = getdtablesize();
diff --git a/third_party/heimdal/lib/roken/dumpdata.c b/third_party/heimdal/lib/roken/dumpdata.c
index 252744e28e2..a8b3efefcff 100644
--- a/third_party/heimdal/lib/roken/dumpdata.c
+++ b/third_party/heimdal/lib/roken/dumpdata.c
@@ -51,8 +51,86 @@ rk_dumpdata (const char *filename, const void *buf, size_t size)
close(fd);
}
+/* For not-regular files */
+static int
+undump_not_file(int fd, char **out, size_t *size, int nul_terminate)
+{
+ size_t lim = 10 * 1024 * 1024;
+ size_t bufsz = 0;
+ size_t sz = 0;
+ char *buf = NULL;
+ char *tmp;
+
+ *out = NULL;
+ if (size && *size != 0 && *size < lim)
+ lim = *size;
+ if (size)
+ *size = 0;
+
+ /*
+ * We can't use net_read() if we're on WIN32 because that really wants a
+ * socket FD, which is in a distinct FD namespace from those returned by
+ * open() on Windows.
+ */
+ do {
+ ssize_t bytes;
+
+ if (sz == bufsz) {
+ if (bufsz == 0)
+ bufsz = 1024;
+ else
+ bufsz += bufsz >> 1;
+
+ tmp = realloc(buf, bufsz);
+ if (tmp == NULL) {
+ free(buf);
+ return ENOMEM;
+ }
+ buf = tmp;
+ }
+
+ bytes = read(fd, buf + sz, bufsz - sz);
+ if (bytes == 0)
+ break;
+ if (bytes < 0 &&
+ (errno == EAGAIN || errno == EWOULDBLOCK))
+ continue;
+ if (bytes < 0) {
+ free(buf);
+ return errno;
+ }
+ sz += bytes;
+ } while (sz < lim);
+
+ *out = buf;
+ if (size)
+ *size = sz;
+
+ if (!nul_terminate)
+ return 0;
+
+ if (bufsz > sz) {
+ buf[sz] = '\0';
+ return 0;
+ }
+
+ *out = tmp = realloc(buf, bufsz + 1);
+ if (tmp == NULL) {
+ free(buf);
+ return ENOMEM;
+ }
+ buf = tmp;
+ buf[sz] = '\0';
+ return 0;
+}
+
/*
- * Read all data from a filename, care about errors.
+ * Read all data from a file, care about errors.
+ *
+ * If `*size' is not zero and the file is not a regular file, then up to that
+ * many bytes will be read.
+ *
+ * Returns zero on success or a system error code on failure.
*/
ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
@@ -71,6 +149,17 @@ rk_undumpdata(const char *filename, void **buf, size_t *size)
ret = errno;
goto out;
}
+ if (!S_ISREG(sb.st_mode)) {
+ char *char_buf;
+
+ ret = undump_not_file(fd, &char_buf, size, 0);
+ (void) close(fd);
+ *buf = char_buf;
+ return ret;
+ }
+
+ if (sb.st_size < 0)
+ sb.st_size = 0;
*buf = malloc(sb.st_size);
if (*buf == NULL) {
ret = ENOMEM;
@@ -78,7 +167,7 @@ rk_undumpdata(const char *filename, void **buf, size_t *size)
}
*size = sb.st_size;
- sret = net_read(fd, *buf, *size);
+ sret = read(fd, *buf, *size);
if (sret < 0)
ret = errno;
else if (sret != (ssize_t)*size)
@@ -94,3 +183,67 @@ rk_undumpdata(const char *filename, void **buf, size_t *size)
close(fd);
return ret;
}
+
+/*
+ * Read all text from a file.
+ *
+ * Outputs a C string. It is up to the caller to check for embedded NULs.
+ * The number of bytes read will be stored in `*size' if `size' is not NULL.
+ *
+ * If `size' is not NULL and `*size' is not zero and the file is not a regular
+ * file, then up to that many bytes will be read.
+ *
+ * Returns zero on success or a system error code on failure.
+ */
+
+ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
+rk_undumptext(const char *filename, char **out, size_t *size)
+{
+ struct stat sb;
+ int fd, ret;
+ ssize_t sret;
+ char *buf;
+
+ *out = NULL;
+
+ fd = open(filename, O_RDONLY, 0);
+ if (fd < 0)
+ return errno;
+ if (fstat(fd, &sb) != 0) {
+ (void) close(fd);
+ return errno;
+ }
+ if (!S_ISREG(sb.st_mode)) {
+ ret = undump_not_file(fd, out, size, 1);
+ (void) close(fd);
+ return ret;
+ }
+
+ if (sb.st_size < 0)
+ sb.st_size = 0;
+ buf = malloc(sb.st_size + 1);
+ if (buf == NULL) {
+ ret = ENOMEM;
+ goto out;
+ }
+ if (size)
+ *size = sb.st_size;
+
+ sret = read(fd, buf, sb.st_size);
+ if (sret < 0)
+ ret = errno;
+ else if (sret != (ssize_t)sb.st_size)
+ ret = EINVAL;
+ else
+ ret = 0;
+
+out:
+ if (ret) {
+ free(buf);
+ } else {
+ buf[sb.st_size] = '\0';
+ *out = buf;
+ }
+ close(fd);
+ return ret;
+}
diff --git a/third_party/heimdal/lib/roken/getauxval.c b/third_party/heimdal/lib/roken/getauxval.c
index f12bc932bc3..785b1618f2f 100644
--- a/third_party/heimdal/lib/roken/getauxval.c
+++ b/third_party/heimdal/lib/roken/getauxval.c
@@ -159,7 +159,6 @@ rk_getprocauxval(unsigned long type)
ROKEN_LIB_FUNCTION unsigned long ROKEN_LIB_CALL
rk_getauxval(unsigned long type)
{
- const auxv_t *a;
#ifdef HAVE_GETAUXVAL
#ifdef GETAUXVAL_SETS_ERRNO
if (rk_injected_auxv)
@@ -169,6 +168,7 @@ rk_getauxval(unsigned long type)
unsigned long ret;
unsigned long ret2;
static int getauxval_sets_errno = -1;
+ const auxv_t *a;
int save_errno = errno;
if (rk_injected_auxv)
@@ -212,13 +212,21 @@ rk_getauxval(unsigned long type)
getauxval_sets_errno = 0;
errno = save_errno;
+ if ((a = rk_getauxv(type)) == NULL) {
+ errno = ENOENT;
+ return 0;
+ }
+ return a->a_un.a_val;
#endif
-#endif
+#else
+ const auxv_t *a;
+
if ((a = rk_getauxv(type)) == NULL) {
errno = ENOENT;
return 0;
}
return a->a_un.a_val;
+#endif
}
/**
diff --git a/third_party/heimdal/lib/roken/getifaddrs.c b/third_party/heimdal/lib/roken/getifaddrs.c
index 72eb5aa6ce7..3d5584adf08 100644
--- a/third_party/heimdal/lib/roken/getifaddrs.c
+++ b/third_party/heimdal/lib/roken/getifaddrs.c
@@ -53,6 +53,11 @@ struct mbuf;
#include <ifaddrs.h>
+#ifdef HAVE_IFADDRS_H
+ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
+rk_freeifaddrs(struct ifaddrs *ifp);
+#endif
+
#ifdef __hpux
#define lifconf if_laddrconf
#define lifc_len iflc_len
@@ -853,7 +858,7 @@ rk_getifaddrs(struct ifaddrs **ifap)
return 0;
}
-void ROKEN_LIB_FUNCTION
+ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
rk_freeifaddrs(struct ifaddrs *ifp)
{
/* AF_NETLINK method uses a single allocation for all interfaces */
diff --git a/third_party/heimdal/lib/roken/hex.c b/third_party/heimdal/lib/roken/hex.c
index cc47fa4d52d..5cd202603f3 100644
--- a/third_party/heimdal/lib/roken/hex.c
+++ b/third_party/heimdal/lib/roken/hex.c
@@ -58,13 +58,7 @@ hex_encode(const void *data, size_t size, char **str)
size_t i;
char *p;
- /* check for overflow */
- if (size * 2 < size) {
- *str = NULL;
- return -1;
- }
-
- p = malloc(size * 2 + 1);
+ p = calloc(size + 1, 2);
if (p == NULL) {
*str = NULL;
return -1;
diff --git a/third_party/heimdal/lib/roken/ifaddrs.hin b/third_party/heimdal/lib/roken/ifaddrs.hin
index ef00b63bad6..88963912362 100644
--- a/third_party/heimdal/lib/roken/ifaddrs.hin
+++ b/third_party/heimdal/lib/roken/ifaddrs.hin
@@ -67,10 +67,10 @@ struct ifaddrs {
#define ifa_broadaddr ifa_dstaddr
#endif
-int ROKEN_LIB_FUNCTION
+ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
rk_getifaddrs(struct ifaddrs**);
-void ROKEN_LIB_FUNCTION
+ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
rk_freeifaddrs(struct ifaddrs*);
#define getifaddrs(a) rk_getifaddrs(a)
diff --git a/third_party/heimdal/lib/roken/issuid.c b/third_party/heimdal/lib/roken/issuid.c
index 0c503a0d6b2..b9b7440351c 100644
--- a/third_party/heimdal/lib/roken/issuid.c
+++ b/third_party/heimdal/lib/roken/issuid.c
@@ -171,7 +171,7 @@ issuid(void)
if (issetugid() == 0)
return we_are_suid = 0;
/* issetugid() == 1 might have been a false positive; fall through */
-#endif /* USE_RK_GETAUXVAL */
+#endif
#ifdef AT_EXECFN
/*
@@ -186,6 +186,9 @@ issuid(void)
* Also, this is technically a TOCTOU race, though for set-id
* programs this is exceedingly unlikely to be an actual TOCTOU
* race.
+ *
+ * TODO We should really make sure that none of the path components of the
+ * execpath are symlinks.
*/
{
unsigned long p = rk_getauxval(AT_EXECPATH);
@@ -267,10 +270,9 @@ issuid(void)
return we_are_suid = 1;
#endif
-#endif /* !defined(HAVE_GETRESUID) || !defined(HAVE_GETRESGID) */
-
errno = save_errno;
return we_are_suid = 0;
+#endif /* !defined(HAVE_GETRESUID) || !defined(HAVE_GETRESGID) */
#endif /* !defined(HAVE_ISSETUGID) */
#endif /* WIN32 */
}
diff --git a/third_party/heimdal/lib/roken/mergesort_r.c b/third_party/heimdal/lib/roken/mergesort_r.c
index 39b0301c454..4fbcd703327 100644
--- a/third_party/heimdal/lib/roken/mergesort_r.c
+++ b/third_party/heimdal/lib/roken/mergesort_r.c
@@ -100,6 +100,7 @@ mergesort_r(void *base, size_t nmemb, size_t size, cmp_t cmp, void *thunk)
int big, iflag;
u_char *f1, *f2, *t, *b, *tp2, *q, *l1, *l2;
u_char *list2, *list1, *p2, *p, *last, **p1;
+ u_char *freeme = NULL;
if (size < PSIZE / 2) { /* Pointers must fit into 2 * size. */
errno = EINVAL;
@@ -117,7 +118,7 @@ mergesort_r(void *base, size_t nmemb, size_t size, cmp_t cmp, void *thunk)
if (!(size % ISIZE) && !(((uintptr_t)base) % ISIZE))
iflag = 1;
- if ((list2 = malloc(nmemb * size + PSIZE)) == NULL)
+ if ((list2 = freeme = malloc(nmemb * size + PSIZE)) == NULL)
return (-1);
list1 = base;
@@ -219,11 +220,9 @@ COPY: b = t;
list2 = tp2;
last = list2 + nmemb*size;
}
- if (base == list2) {
+ if (base == list2)
memmove(list2, list1, nmemb*size);
- list2 = list1;
- }
- free(list2);
+ free(freeme);
return (0);
}
diff --git a/third_party/heimdal/lib/roken/mkdtemp.c b/third_party/heimdal/lib/roken/mkdtemp.c
index b106add3278..c9f7463e950 100644
--- a/third_party/heimdal/lib/roken/mkdtemp.c
+++ b/third_party/heimdal/lib/roken/mkdtemp.c
@@ -59,9 +59,8 @@ mkdtemp(char *template)
pid_t val = getpid();
for (i = 0; i < len && i < 7 && template[len - i] == 'X'; i++) {
- template[len] = '0' + val % 10;
+ template[len - i] = '0' + val % 10;
val /= 10;
- len--;
if (!val)
val = getpid();
}
diff --git a/third_party/heimdal/lib/roken/roken-common.h b/third_party/heimdal/lib/roken/roken-common.h
index 035b99b8b97..906b000336c 100644
--- a/third_party/heimdal/lib/roken/roken-common.h
+++ b/third_party/heimdal/lib/roken/roken-common.h
@@ -509,7 +509,7 @@ free_environment(char **);
#define warnerr rk_warnerr
ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
rk_warnerr(int doerrno, const char *fmt, va_list ap)
- __attribute__ ((__format__ (__printf__, 2, 0)));
+ ROKEN_PRINTF_ATTRIBUTE((__printf__, 2, 0));
ROKEN_LIB_FUNCTION void * ROKEN_LIB_CALL
rk_realloc(void *, size_t);
@@ -521,7 +521,7 @@ rk_strpoolcollect(struct rk_strpool *);
ROKEN_LIB_FUNCTION struct rk_strpool * ROKEN_LIB_CALL
rk_strpoolprintf(struct rk_strpool *, const char *, ...)
- __attribute__ ((__format__ (__printf__, 2, 3)));
+ ROKEN_PRINTF_ATTRIBUTE((__printf__, 2, 3));
ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
rk_strpoolfree(struct rk_strpool *);
@@ -532,6 +532,9 @@ rk_dumpdata (const char *, const void *, size_t);
ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
rk_undumpdata (const char *, void **, size_t *);
+ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
+rk_undumptext (const char *, char **, size_t *);
+
ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
rk_xfree (void *);
diff --git a/third_party/heimdal/lib/roken/roken.awk b/third_party/heimdal/lib/roken/roken.awk
index 47313c843af..00e60f026df 100644
--- a/third_party/heimdal/lib/roken/roken.awk
+++ b/third_party/heimdal/lib/roken/roken.awk
@@ -12,6 +12,14 @@ BEGIN {
print "#ifdef HAVE_ERRNO_H"
print "#include <errno.h>"
print "#endif"
+ print "#if !defined(__has_extension)"
+ print "#define __has_extension(x) 0"
+ print "#endif"
+ print "#ifndef ROKEN_REQUIRE_GNUC"
+ print "#define ROKEN_REQUIRE_GNUC(m,n,p) \\"
+ print " (((__GNUC__ * 10000) + (__GNUC_MINOR__ * 100) + __GNUC_PATCHLEVEL__) >= \\"
+ print " (((m) * 10000) + ((n) * 100) + (p)))"
+ print "#endif"
print ""
print "int main(int argc, char **argv)"
print "{"
diff --git a/third_party/heimdal/lib/roken/roken.h.in b/third_party/heimdal/lib/roken/roken.h.in
index e1902f582dc..c72d259a37a 100644
--- a/third_party/heimdal/lib/roken/roken.h.in
+++ b/third_party/heimdal/lib/roken/roken.h.in
@@ -96,6 +96,58 @@
# endif
# endif
+#if !defined(__has_extension)
+#define __has_extension(x) 0
+#endif
+
+#ifndef ROKEN_REQUIRE_GNUC
+#define ROKEN_REQUIRE_GNUC(m,n,p) \
+ (((__GNUC__ * 10000) + (__GNUC_MINOR__ * 100) + __GNUC_PATCHLEVEL__) >= \
+ (((m) * 10000) + ((n) * 100) + (p)))
+#endif
+
+#ifndef ROKEN_DEPRECATED
+#if __has_extension(deprecated) || ROKEN_REQUIRE_GNUC(3,1,0)
+#define ROKEN_DEPRECATED __attribute__ ((__deprecated__))
+#elif defined(_MSC_VER) && (_MSC_VER>1200)
+#define ROKEN_DEPRECATED __declspec(deprecated)
+#else
+#define ROKEN_DEPRECATED
+#endif
+#endif
+
+#ifndef ROKEN_PRINTF_ATTRIBUTE
+#if __has_extension(format) || ROKEN_REQUIRE_GNUC(3,1,0)
+#define ROKEN_PRINTF_ATTRIBUTE(x) __attribute__ ((__format__ x))
+#else
+#define ROKEN_PRINTF_ATTRIBUTE(x)
+#endif
+#endif
+
+#ifndef ROKEN_NORETURN_ATTRIBUTE
+#if __has_extension(noreturn) || ROKEN_REQUIRE_GNUC(3,1,0)
+#define ROKEN_NORETURN_ATTRIBUTE __attribute__ ((__noreturn__))
+#else
+#define ROKEN_NORETURN_ATTRIBUTE
+#endif
+#endif
+
+#ifndef ROKEN_UNUSED_ATTRIBUTE
+#if __has_extension(unused) || ROKEN_REQUIRE_GNUC(3,1,0)
+#define ROKEN_UNUSED_ATTRIBUTE __attribute__ ((__unused__))
+#else
+#define ROKEN_UNUSED_ATTRIBUTE
+#endif
+#endif
+
+#ifndef ROKEN_WARN_UNUSED_RESULT_ATTRIBUTE
+#if __has_extension(warn_unused_result) || ROKEN_REQUIRE_GNUC(3,3,0)
+#define ROKEN_WARN_UNUSED_RESULT_ATTRIBUTE __attribute__ ((__warn_unused_result__))
+#else
+#define ROKEN_WARN_UNUSED_RESULT_ATTRIBUTE
+#endif
+#endif
+
#ifdef HAVE_WINSOCK
/* Declarations for Microsoft Windows */
@@ -515,7 +567,7 @@ ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL endusershell(void);
#endif
ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
rk_snprintf (char *, size_t, const char *, ...)
- __attribute__ ((__format__ (__printf__, 3, 4)));
+ ROKEN_PRINTF_ATTRIBUTE((__printf__, 3, 4));
#endif
#if !defined(HAVE_VSNPRINTF) || defined(NEED_VSNPRINTF_PROTO)
@@ -524,7 +576,7 @@ ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
#endif
ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
rk_vsnprintf (char *, size_t, const char *, va_list)
- __attribute__ ((__format__ (__printf__, 3, 0)));
+ ROKEN_PRINTF_ATTRIBUTE((__printf__, 3, 0));
#endif
#if !defined(HAVE_ASPRINTF) || defined(NEED_ASPRINTF_PROTO)
@@ -533,7 +585,7 @@ ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
#endif
ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
rk_asprintf (char **, const char *, ...)
- __attribute__ ((__format__ (__printf__, 2, 3)));
+ ROKEN_PRINTF_ATTRIBUTE((__printf__, 2, 3));
#endif
#if !defined(HAVE_VASPRINTF) || defined(NEED_VASPRINTF_PROTO)
@@ -542,7 +594,7 @@ ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
#endif
ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
rk_vasprintf (char **, const char *, va_list)
- __attribute__ ((__format__ (__printf__, 2, 0)));
+ ROKEN_PRINTF_ATTRIBUTE((__printf__, 2, 0));
#endif
#if !defined(HAVE_ASNPRINTF) || defined(NEED_ASNPRINTF_PROTO)
@@ -551,7 +603,7 @@ ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
#endif
ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
rk_asnprintf (char **, size_t, const char *, ...)
- __attribute__ ((__format__ (__printf__, 3, 4)));
+ ROKEN_PRINTF_ATTRIBUTE((__printf__, 3, 4));
#endif
#if !defined(HAVE_VASNPRINTF) || defined(NEED_VASNPRINTF_PROTO)
@@ -560,7 +612,19 @@ ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
#endif
ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
vasnprintf (char **, size_t, const char *, va_list)
- __attribute__ ((__format__ (__printf__, 3, 0)));
+ ROKEN_PRINTF_ATTRIBUTE((__printf__, 3, 0));
+#endif
+
+#if !defined(HAVE_EVASPRINTF) || defined(NEED_EVASPRINTF_PROTO)
+#define evasprintf rk_evasprintf
+ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL
+rk_evasprintf(const char *format, va_list args);
+#endif
+
+#if !defined(HAVE_EASPRINTF) || defined(NEED_EASPRINTF_PROTO)
+#define easprintf rk_easprintf
+ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL
+rk_easprintf(const char *format, ...);
#endif
#ifndef HAVE_STRDUP
@@ -1224,9 +1288,9 @@ vis(char *, int, int, int);
#if !defined(HAVE_CLOSEFROM)
#define closefrom rk_closefrom
-ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
-closefrom(int);
#endif
+ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
+rk_closefrom(int);
#if !defined(HAVE_TIMEGM)
#define timegm rk_timegm
diff --git a/third_party/heimdal/lib/roken/snprintf.c b/third_party/heimdal/lib/roken/snprintf.c
index c8afedb2620..0b99a4b6f3e 100644
--- a/third_party/heimdal/lib/roken/snprintf.c
+++ b/third_party/heimdal/lib/roken/snprintf.c
@@ -449,13 +449,16 @@ xyzprintf (struct snprintf_state *state, const char *char_format, va_list ap)
break;
case 'd' :
case 'i' : {
- longest arg;
- u_longest num;
+ int64_t arg;
+ uint64_t num;
int minusp = 0;
PARSE_INT_FORMAT(arg, ap, signed);
- if (arg < 0) {
+ if (arg == INT64_MIN) {
+ minusp = 1;
+ num = (uint64_t)INT64_MAX + 1;
+ } else if (arg < 0) {
minusp = 1;
num = -arg;
} else
@@ -698,3 +701,30 @@ rk_vsnprintf (char *str, size_t sz, const char *format, va_list args)
return ret;
}
#endif
+
+#if !defined(HAVE_EVASPRINTF) || defined(TEST_SNPRINTF)
+ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL
+rk_evasprintf(const char *format, va_list args)
+{
+ char *s = NULL;
+
+ if (vasprintf(&s, format, args) == -1 || s == NULL)
+ errx(1, "Out of memory");
+ return s;
+}
+#endif
+
+#if !defined(HAVE_EASPRINTF) || defined(TEST_SNPRINTF)
+ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL
+rk_easprintf(const char *format, ...)
+{
+ va_list args;
+ char *s = NULL;
+
+ va_start(args, format);
+ if (vasprintf(&s, format, args) == -1 || s == NULL)
+ errx(1, "Out of memory");
+ va_end(args);
+ return s;
+}
+#endif
diff --git a/third_party/heimdal/lib/roken/socket.c b/third_party/heimdal/lib/roken/socket.c
index a790e082d82..5b578c89fac 100644
--- a/third_party/heimdal/lib/roken/socket.c
+++ b/third_party/heimdal/lib/roken/socket.c
@@ -274,10 +274,11 @@ socket_set_nonblocking(rk_socket_t sock, int nonblock)
flags |= O_NONBLOCK;
else
flags &= ~O_NONBLOCK;
- fcntl(sock, F_SETFL, flags);
+ (void) fcntl(sock, F_SETFL, flags);
#elif defined(FIOBIO)
int flags = !!nonblock;
- return ioctl(sock, FIOBIO, &flags);
+
+ (void) ioctl(sock, FIOBIO, &flags);
#endif
}
diff --git a/third_party/heimdal/lib/roken/test-auxval.c b/third_party/heimdal/lib/roken/test-auxval.c
index 69ab359920b..80ad9e08588 100644
--- a/third_party/heimdal/lib/roken/test-auxval.c
+++ b/third_party/heimdal/lib/roken/test-auxval.c
@@ -47,20 +47,19 @@ static void
check_secure_getenv(char **env)
{
size_t i;
- char *v;
+ char *v, *p;
for (i = 0; env[i] != NULL; i++) {
- if (strchr(env[i], '=') == NULL)
- continue;
if ((v = strdup(env[i])) == NULL)
err(1, "could not allocate copy of %s", env[i]);
- *strchr(v, '=') = '\0';
- if (issuid() && rk_secure_getenv(v) != NULL)
- err(1, "rk_secure_getenv() returned non-NULL when issuid()!");
- if (!issuid() && rk_secure_getenv(v) == NULL)
- err(1, "rk_secure_getenv() returned NULL when !issuid()");
+ if ((p = strchr(v, '='))) {
+ *p = '\0';
+ if (issuid() && rk_secure_getenv(v) != NULL)
+ err(1, "rk_secure_getenv() returned non-NULL when issuid()!");
+ if (!issuid() && rk_secure_getenv(v) == NULL)
+ err(1, "rk_secure_getenv() returned NULL when !issuid()");
+ }
free(v);
- return;
}
}
diff --git a/third_party/heimdal/lib/roken/timeval.c b/third_party/heimdal/lib/roken/timeval.c
index 3012513ee7d..71fdd009ff2 100644
--- a/third_party/heimdal/lib/roken/timeval.c
+++ b/third_party/heimdal/lib/roken/timeval.c
@@ -84,8 +84,8 @@ rk_time_add(time_t t, time_t delta)
#else
#error "Unexpected sizeof(time_t)"
#endif
-#endif
return t + delta;
+#endif
}
ROKEN_LIB_FUNCTION time_t ROKEN_LIB_CALL
@@ -122,8 +122,8 @@ rk_time_sub(time_t t, time_t delta)
/* Both t and delta are non-negative. */
if (delta > t)
return 0;
-#endif
return t - delta;
+#endif
}
/*
diff --git a/third_party/heimdal/lib/roken/version-script.map b/third_party/heimdal/lib/roken/version-script.map
index be1713e8261..b48e06b9e6a 100644
--- a/third_party/heimdal/lib/roken/version-script.map
+++ b/third_party/heimdal/lib/roken/version-script.map
@@ -52,12 +52,14 @@ HEIMDAL_ROKEN_2.0 {
rk_dns_string_to_type;
rk_dns_type_to_string;
rk_dumpdata;
+ rk_easprintf;
rk_ecalloc;
rk_emalloc;
rk_eread;
rk_erealloc;
rk_esetenv;
rk_estrdup;
+ rk_evasprintf;
rk_ewrite;
rk_flock;
rk_fnmatch;
@@ -169,6 +171,7 @@ HEIMDAL_ROKEN_2.0 {
rk_tsearch;
rk_twalk;
rk_undumpdata;
+ rk_undumptext;
rk_unparse_flags;
rk_unparse_time;
rk_unparse_time_approx;
diff --git a/third_party/heimdal/lib/roken/write_pid.c b/third_party/heimdal/lib/roken/write_pid.c
index cf5299b64bf..c01091236f2 100644
--- a/third_party/heimdal/lib/roken/write_pid.c
+++ b/third_party/heimdal/lib/roken/write_pid.c
@@ -43,6 +43,8 @@ ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL
pid_file_write(const char *progname)
{
const char *pidfile_dir = NULL;
+ const char *sep = "/";
+ size_t pidfile_dir_len;
char *ret = NULL;
FILE *fp;
@@ -57,7 +59,17 @@ pid_file_write(const char *progname)
if (pidfile_dir == NULL)
pidfile_dir = _PATH_VARRUN;
- if (asprintf(&ret, "%s%s.pid", pidfile_dir, progname) < 0 || ret == NULL)
+ pidfile_dir_len = strlen(pidfile_dir);
+ if (pidfile_dir_len > 1 &&
+ pidfile_dir[pidfile_dir_len - 1] == '/')
+ sep = "";
+#ifdef WIN32
+ if (pidfile_dir_len > 1 &&
+ pidfile_dir[pidfile_dir_len - 1] == '\\')
+ sep = "";
+#endif
+
+ if (asprintf(&ret, "%s%s%s.pid", pidfile_dir, sep, progname) < 0 || ret == NULL)
return NULL;
fp = fopen(ret, "w");
if (fp == NULL) {
diff --git a/third_party/heimdal/lib/sl/sl.c b/third_party/heimdal/lib/sl/sl.c
index b78f9f675b2..c67cc525f33 100644
--- a/third_party/heimdal/lib/sl/sl.c
+++ b/third_party/heimdal/lib/sl/sl.c
@@ -311,13 +311,42 @@ int
sl_command_loop(SL_cmd *cmds, const char *prompt, void **data)
{
int ret = 0;
- char *buf;
+ char *buf = NULL;
int argc;
char **argv;
+ int continued = 0;
- buf = sl_readline(prompt);
- if(buf == NULL)
- return -2;
+ do {
+ char *buf2;
+ size_t len;
+
+ buf2 = sl_readline(buf == NULL ? prompt : "> ");
+ if (buf2 == NULL) {
+ free(buf);
+ return -2;
+ }
+
+ if (buf) {
+ char *tmp = NULL;
+
+ if (asprintf(&tmp, "%s %s", buf, buf2) == -1 || tmp == NULL) {
+ fprintf(stderr, "sl_loop: out of memory\n");
+ free(buf2);
+ free(buf);
+ return -1;
+ }
+ free(buf2);
+ free(buf);
+ buf = tmp;
+ } else {
+ buf = buf2;
+ }
+
+ len = strlen(buf);
+ continued = (len > 0 && buf[len - 1] == '\\');
+ if (continued)
+ buf[len - 1] = '\0';
+ } while (continued);
if(*buf)
add_history(buf);
@@ -331,7 +360,7 @@ sl_command_loop(SL_cmd *cmds, const char *prompt, void **data)
ret = sl_command(cmds, argc, argv);
if(ret == -1) {
sl_did_you_mean(cmds, argv[0]);
- ret = 0;
+ ret = 1;
}
}
free(buf);
diff --git a/third_party/heimdal/lib/wind/idn-lookup.c b/third_party/heimdal/lib/wind/idn-lookup.c
index 378c912a392..5b71a8fed7f 100644
--- a/third_party/heimdal/lib/wind/idn-lookup.c
+++ b/third_party/heimdal/lib/wind/idn-lookup.c
@@ -69,12 +69,17 @@ lookup(const char *name)
struct addrinfo *ai;
size_t u_len = strlen(name);
- uint32_t *u = malloc(u_len * sizeof(uint32_t));
- size_t norm_len = u_len * 2;
- uint32_t *norm = malloc(norm_len * sizeof(uint32_t));
+ uint32_t *u;
+ size_t norm_len = u_len * 8;
+ uint32_t *norm;
+ if (u_len == 0)
+ return;
+
+ u = calloc(u_len, sizeof(uint32_t));
if (u == NULL && u_len != 0)
errx(1, "malloc failed");
+ norm = calloc(norm_len, sizeof(uint32_t));
if (norm == NULL && norm_len != 0)
errx(1, "malloc failed");
@@ -156,9 +161,7 @@ main(int argc, char **argv)
if (argc == 0)
usage(1);
- for (i = 0; i < argc; ++i) {
- if (argv[i][0]) /* Quiet lint */
- lookup(argv[i]);
- }
+ for (i = 0; i < argc; ++i)
+ lookup(argv[i]);
return 0;
}
diff --git a/third_party/heimdal/packages/windows/sdk/NTMakefile b/third_party/heimdal/packages/windows/sdk/NTMakefile
index 4f2d355bf61..db3af6a87bd 100644
--- a/third_party/heimdal/packages/windows/sdk/NTMakefile
+++ b/third_party/heimdal/packages/windows/sdk/NTMakefile
@@ -93,7 +93,6 @@ INCFILES=\
$(SDKINCDIR)\hcrypto\evp-hcrypto.h \
$(SDKINCDIR)\hcrypto\evp.h \
$(SDKINCDIR)\hcrypto\hmac.h \
- $(SDKINCDIR)\hcrypto\md2.h \
$(SDKINCDIR)\hcrypto\md4.h \
$(SDKINCDIR)\hcrypto\md5.h \
$(SDKINCDIR)\hcrypto\rand.h \
diff --git a/third_party/heimdal/tests/bin/setup-env.in b/third_party/heimdal/tests/bin/setup-env.in
index c9291d08bf2..8efa0e9922b 100644
--- a/third_party/heimdal/tests/bin/setup-env.in
+++ b/third_party/heimdal/tests/bin/setup-env.in
@@ -13,6 +13,7 @@ top_builddir="@top_builddir@"
top_srcdir="@top_srcdir@"
EGREP="@EGREP@"
NO_AFS="@NO_AFS@"
+MITKRB5="@MITKRB5@"
# Meant to be sourced (source or .) by the tester application, offers
# most commands in heimdal as variables
diff --git a/third_party/heimdal/tests/kdc/Makefile.am b/third_party/heimdal/tests/kdc/Makefile.am
index f61a7e85307..09f695348e9 100644
--- a/third_party/heimdal/tests/kdc/Makefile.am
+++ b/third_party/heimdal/tests/kdc/Makefile.am
@@ -80,7 +80,9 @@ do_subst = $(heim_verbose)sed $(do_dlopen) \
-e 's,[@]db_type[@],$(db_type),g' \
-e 's,[@]max_life_from_cert[@],$(pkinit_ticket_max_life_from_cert),g' \
-e 's,[@]ENABLE_AFS_STRING_TO_KEY[@],$(ENABLE_AFS_STRING_TO_KEY),' \
- -e 's,[@]EGREP[@],$(EGREP),g'
+ -e 's,[@]ENABLE_AFS_STRING_TO_KEY[@],$(ENABLE_AFS_STRING_TO_KEY),' \
+ -e 's,[@]EGREP[@],$(EGREP),g' \
+ -e 's,[@]MITKRB5[@],$(MITKRB5),g'
chmod = chmod
@@ -311,7 +313,7 @@ krb5-pkinit-win.conf: krb5-pkinit.conf.in Makefile
mv krb5-pkinit-win.conf.tmp krb5-pkinit-win.conf
clean: clean-am
- rm -rf cc_dir simple_csr_authz
+ rm -rf cc_dir authz_dir
CLEANFILES= \
$(TESTS) \
diff --git a/third_party/heimdal/tests/kdc/check-bx509.in b/third_party/heimdal/tests/kdc/check-bx509.in
index 5109854fc26..d1e63741e1a 100644
--- a/third_party/heimdal/tests/kdc/check-bx509.in
+++ b/third_party/heimdal/tests/kdc/check-bx509.in
@@ -74,11 +74,18 @@ klistjson="${klist} --json -c $cache"
klist="${klist} --hidden -v -c $cache"
kgetcred="${kgetcred} -c $cache"
kdestroy="${kdestroy} -c $cache ${afs_no_unlog}"
+test_csr_authorizer="$test_csr_authorizer -A $objdir/authz_dir -S $objdir"
kx509="${kx509} -c $cache"
KRB5_CONFIG="${objdir}/krb5-bx509.conf"
export KRB5_CONFIG
+HEIM_PIDFILE_DIR="${objdir}/"
+export HEIM_PIDFILE_DIR
+
+HEIM_IPC_DIR=$objdir
+export HEIM_IPC_DIR
+
rsa=yes
pkinit=no
if ${hxtool} info | grep 'rsa: hx509 null RSA' > /dev/null ; then
@@ -102,26 +109,26 @@ rm -f current-db*
rm -f out-*
rm -f mkey.file*
rm -f *.pem *.crt *.der
-rm -rf simple_csr_authz
+rm -rf authz_dir
-mkdir -p simple_csr_authz
+mkdir -p authz_dir
> messages.log
-# We'll avoid using a KDC for now. For testing /bx509 we only need keys for
-# Negotiate tokens, and we'll use ktutil and kimpersonate to make it possible
-# to create and accept those without a KDC. When we test /bnegotiate, however,
-# we'll start a KDC.
+kdcpid=
+bx509pid=
+test_csr_authorizer_pid=
+trap 'kill -9 ${kdcpid} ${bx509pid} ${test_csr_authorizer_pid}; echo signal killing kdc, bx509d, and test_csr_authorizer; exit 1;' EXIT
# csr_grant ext-type value grantee_principal
csr_grant() {
- mkdir -p "${objdir}/simple_csr_authz/${3}"
- touch "${objdir}/simple_csr_authz/${3}/${1}-${2}"
+ mkdir -p "${objdir}/authz_dir/${3}"
+ touch "${objdir}/authz_dir/${3}/${1}=${2}"
}
csr_revoke() {
- rm -rf "${objdir}/simple_csr_authz"
- mkdir -p "${objdir}/simple_csr_authz"
+ rm -rf "${objdir}/authz_dir"
+ mkdir -p "${objdir}/authz_dir"
}
# get_cert "" curl-opts
@@ -254,7 +261,7 @@ $hxtool ca --issue-ca --type=https-negotiate-server \
# XXX Before starting bx509d let us use kdc test programs to check that:
#
# - the negotiate token validator plugin works
-# - the simple CSR authorizer plugin works
+# - the authz_dir CSR authorizer plugin works
# - the KDC CA tester program works
echo "Check gss-token and Negotiate token validator plugin"
@@ -265,6 +272,64 @@ token=$(KRB5CCNAME=$cache $gsstoken HTTP@$server)
$test_token_validator -a datan.test.h5l.se Negotiate "$token" ||
{ echo "Negotiate token validator failed to validate valid token"; exit 2; }
+
+echo "Starting CSR authorizer IPC service"
+$test_csr_authorizer --server --daemon ||
+ { echo "Failed to start test_csr_authorizer service"; exit 2; }
+test_csr_authorizer_pid=`getpid test_csr_authorizer`
+
+# Make a CSR for foo@$R
+$hxtool request-create --subject='' --generate-key=rsa --key-bits=1024 \
+ --key=FILE:"${objdir}/k.der" --kerberos=foo@$R \
+ ${objdir}/req ||
+ { echo "Failed to make a CSR"; exit 2; }
+
+echo "Test CSR authorizer IPC service (deny foo@$R to san_pkinit=foo@$R)"
+csr_revoke
+$test_csr_authorizer PKCS10:${objdir}/req foo@$R &&
+ { echo "CSR authorizer IPC service granted foo@$R"; exit 2; }
+
+echo "Test CSR authorizer IPC service (grant foo@$R to san_pkinit=foo@$R)"
+csr_grant san_pkinit foo@$R foo@${R}
+$test_csr_authorizer PKCS10:${objdir}/req foo@$R ||
+ { echo "CSR authorizer IPC service rejected foo@$R"; exit 2; }
+
+# Make a CSR for bar@$R
+$hxtool request-create --subject='' --key-bits=1024 \
+ --key=FILE:"${objdir}/k.der" --kerberos=bar@$R \
+ ${objdir}/req ||
+ { echo "Failed to make a CSR"; exit 2; }
+
+echo "Test CSR authorizer IPC service (deny foo@$R to san_pkinit=bar@$R)"
+$test_csr_authorizer PKCS10:${objdir}/req foo@$R &&
+ { echo "CSR authorizer IPC service accepted foo@$R"; exit 2; }
+
+echo "Test CSR authorizer IPC service (grant foo@$R to san_pkinit=bar@$R)"
+csr_grant san_pkinit foo@$R bar@${R}
+$test_csr_authorizer PKCS10:${objdir}/req foo@$R &&
+ { echo "CSR authorizer IPC service accepted foo@$R"; exit 2; }
+
+# Make a CSR for foo@$R and bar@$R
+$hxtool request-create --subject='' --key-bits=1024 \
+ --key=FILE:"${objdir}/k.der" \
+ --kerberos=foo@$R --kerberos=bar@$R \
+ ${objdir}/req ||
+ { echo "Failed to make a CSR"; exit 2; }
+
+# Check that the authorizer does mark foo@$R as approved even though it denies
+# the overall request because it rejects bar@$R
+echo "Test CSR authorizer IPC service (partial authz)"
+csr_revoke
+csr_grant san_pkinit foo@$R foo@${R}
+# Check that the authorizer grants foo@$R
+$test_csr_authorizer PKCS10:${objdir}/req foo@$R san_pkinit=foo@$R ||
+ { echo "CSR authorizer IPC service partial approval check fail"; exit 2; }
+# Check that the authorizer rejects bar@$R
+$test_csr_authorizer PKCS10:${objdir}/req foo@$R san_pkinit=bar@$R &&
+ { echo "CSR authorizer IPC service partial approval check fail"; exit 2; }
+$test_csr_authorizer PKCS10:${objdir}/req foo@$R san_pkinit=foo@$R san_pkinit=bar@$R &&
+ { echo "CSR authorizer IPC service partial approval check fail"; exit 2; }
+
echo "Making a plain CSR"
$hxtool request-create --subject='' --generate-key=rsa --key-bits=1024 \
--key=FILE:"${objdir}/k.der" "${objdir}/req" ||
@@ -297,7 +362,7 @@ $hxtool request-create --subject='' --generate-key=rsa --key-bits=1024 \
$test_kdc_ca -a bx509 foo@${R} PKCS10:${objdir}/req \
PEM-FILE:${objdir}/server.pem &&
{ echo "Trivial offline CA test failed: unauthorized issuance (dNSName)"; exit 2; }
-csr_grant dnsname foo.test.h5l.se foo@${R}
+csr_grant san_dnsname foo.test.h5l.se foo@${R}
csr_grant eku 1.3.6.1.5.5.7.3.1 foo@${R}
$test_kdc_ca -a bx509 foo@${R} PKCS10:${objdir}/req \
PEM-FILE:${objdir}/server.pem ||
@@ -316,7 +381,7 @@ $hxtool request-create --subject='' --generate-key=rsa --key-bits=1024 \
$test_kdc_ca -a bx509 foo@${R} PKCS10:${objdir}/req \
PEM-FILE:${objdir}/email.pem &&
{ echo "Offline CA test failed: unauthorized issuance (dNSName)"; exit 2; }
-csr_grant email foo@test.h5l.se foo@${R}
+csr_grant san_email foo@test.h5l.se foo@${R}
csr_grant eku 1.3.6.1.5.5.7.3.2 foo@${R}
$test_kdc_ca -a bx509 foo@${R} PKCS10:${objdir}/req \
PEM-FILE:${objdir}/email.pem ||
@@ -329,30 +394,46 @@ $hxtool acert --expr="%{certificate.subject} == \"OU=Users,CN=KDC,$DCs\"" \
if ! which curl; then
echo "curl is not available -- not testing bx509d"
+ sh ${leaks_kill} test_csr_authorizer $test_csr_authorizer_pid || ec=1
+ trap '' EXIT
exit 77
fi
if ! test -x ${objdir}/../../kdc/bx509d; then
echo "Configured w/o libmicrohttpd -- not testing bx509d"
+ sh ${leaks_kill} test_csr_authorizer $test_csr_authorizer_pid || ec=1
+ trap '' EXIT
exit 77
fi
echo "Creating database"
-${kadmin} init \
- --realm-max-ticket-life=1day \
- --realm-max-renewable-life=1month \
- ${R} || exit 1
-${kadmin} add -r --use-defaults foo@${R} || exit 1
-${kadmin} add -r --use-defaults bar@${R} || exit 1
-${kadmin} add -r --use-defaults baz@${R} || exit 1
-${kadmin} modify --pkinit-acl="CN=foo,DC=test,DC=h5l,DC=se" foo@${R} || exit 1
+rm -f $kt $ukt
+${kadmin} <<EOF || exit 1
+init --realm-max-ticket-life=1day --realm-max-renewable-life=1month ${R}
+add -r --use-defaults foo@${R}
+add -r --use-defaults bar@${R}
+add -r --use-defaults baz@${R}
+add -r --use-defaults raz@${R}
+modify --pkinit-acl="CN=foo,DC=test,DC=h5l,DC=se" foo@${R}
+add -r --use-defaults HTTP/${server}@${R}
+ext_keytab -r -k $keytab HTTP/${server}@${R}
+add -r --use-defaults HTTP/${otherserver}@${R}
+ext_keytab -r -k $ukeytab foo@${R}
+EOF
+
+echo "Starting kdc";
+${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; }
+kdcpid=`getpid kdc`
+
+${kdestroy}
+${kinit} -kt $ukeytab foo@${R} || exit 1
+$klist || { echo "failed to kinit"; exit 2; }
echo "Starting bx509d"
${bx509d} --daemon || { echo "bx509 failed to start"; exit 2; }
bx509pid=`getpid bx509d`
-trap 'kill -9 ${bx509pid}; echo signal killing bx509d; exit 1;' EXIT
ec=0
rm -f trivial.pem server.pem email.pem
@@ -458,7 +539,7 @@ else
fi
echo "Fetching a server certificate with one dNSName SAN"
-csr_grant dnsname $server foo@${R}
+csr_grant san_dnsname $server foo@${R}
if (set -vx; get_cert "&dNSName=$server" -sf -o "${objdir}/server.pem"); then
$hxtool print --content "FILE:${objdir}/server.pem"
if (set -vx; $hxtool acert --expr="%{certificate.subject} == \"\"" \
@@ -478,7 +559,7 @@ else
fi
echo "Fetching a server certificate with two dNSName SANs"
-csr_grant dnsname "second-$server" foo@${R}
+csr_grant san_dnsname "second-$server" foo@${R}
if (set -vx;
get_cert "&dNSName=${server}&dNSName=second-$server" -sf \
-o "${objdir}/server2.pem"); then
@@ -502,7 +583,7 @@ else
fi
echo "Fetching an email certificate"
-csr_grant email foo@bar.example foo@${R}
+csr_grant san_email foo@bar.example foo@${R}
if (set -vx; get_cert "&rfc822Name=foo@bar.example" -sf -o "${objdir}/email.pem"); then
$hxtool print --content "FILE:${objdir}/email.pem"
if $hxtool acert --end-entity -P "foo@${R}" "FILE:${objdir}/email.pem"; then
@@ -521,22 +602,6 @@ else
exit 1
fi
-# Need to start a KDC to test this.
-rm -f $kt $ukt
-${kdestroy}
-${kadmin} add -r --use-defaults HTTP/${server}@${R} || exit 1
-${kadmin} ext_keytab -r -k $keytab HTTP/${server}@${R} || exit 1
-${kadmin} add -r --use-defaults HTTP/${otherserver}@${R} || exit 1
-${kadmin} ext_keytab -r -k $ukeytab foo@${R} || exit 1
-
-echo "Starting kdc";
-${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; }
-kdcpid=`getpid kdc`
-trap 'kill -9 ${kdcpid} ${bx509pid}; echo signal killing kdc and bx509d; exit 1;' EXIT
-
-${kinit} -kt $ukeytab foo@${R} || exit 1
-$klist || { echo "failed to kinit"; exit 2; }
-
echo "Fetch TGT (not granted for other)"
token=$(KRB5CCNAME=$cache $gsstoken HTTP@$server)
if (set -vx;
@@ -549,8 +614,8 @@ if (set -vx;
fi
echo "Fetch TGT"
-(set -vx; csr_grant pkinit foo@${R} foo@${R})
-(set -vx; csr_grant eku 1.3.6.1.5.2.3.4 foo@${R})
+csr_grant san_pkinit foo@${R} foo@${R}
+csr_grant eku 1.3.6.1.5.2.3.4 foo@${R}
token=$(KRB5CCNAME=$cache $gsstoken HTTP@$server)
if ! (set -vx;
curl -o "${cachefile2}" -Lgsf \
@@ -581,7 +646,7 @@ ${klist} | grep Addresses:.IPv4:8.8.8.8 ||
{ echo "Failed to get a TGT with /get-tgt end-point with addresses"; exit 2; }
echo "Fetch TGT (for other)"
-(set -vx; csr_grant pkinit bar@${R} foo@${R})
+csr_grant san_pkinit bar@${R} foo@${R}
${kdestroy}
token=$(KRB5CCNAME=$cache2 $gsstoken HTTP@$server)
if ! (set -vx;
@@ -599,7 +664,7 @@ ${klist} | grep Addresses:.IPv4:8.8.8.8 ||
echo "Fetch TGT (for other, w/ lifetime req under max)"
${kadmin} modify --max-ticket-life=10d krbtgt/${R}@${R}
-(set -vx; csr_grant pkinit bar@${R} foo@${R})
+csr_grant san_pkinit bar@${R} foo@${R}
${kdestroy}
token=$(KRB5CCNAME=$cache2 $gsstoken HTTP@$server)
if ! (set -vx;
@@ -625,7 +690,7 @@ fi
echo "Fetch TGT (for other, w/ lifetime req over max)"
${kadmin} modify --max-ticket-life=10d krbtgt/${R}@${R}
-(set -vx; csr_grant pkinit bar@${R} foo@${R})
+csr_grant san_pkinit bar@${R} foo@${R}
${kdestroy}
token=$(KRB5CCNAME=$cache2 $gsstoken HTTP@$server)
if ! (set -vx;
@@ -640,10 +705,10 @@ ${kgetcred} -H HTTP/${server}@${R} ||
{ echo "Fetched TGT didn't work"; exit 2; }
if which jq >/dev/null; then
if ! ${klistjson} | jq -e '
- (reduce (.tickets[0]|(.Issued,.Expires)|
- strptime("%b %e %H:%M:%S %Y")|mktime) as $t
- (0; if .==0 then $t else $t - . end) / 86400) | floor |
- . == 5'; then
+ (.tickets[0].Issued | strptime("%b %e %H:%M:%S %Y")|mktime) as $iat
+ | (.tickets[0].Expires | strptime("%b %e %H:%M:%S %Y")|mktime) as $exp
+ | (($exp - $iat) / 86400) as $life_days
+ | ($life_days > 4 and $life_days <= 5)'; then
echo "Incorrect lifetime"
exit 2
fi
@@ -651,7 +716,7 @@ fi
echo "Fetch TGT (for other, w/ lifetime req under max)"
${kadmin} modify --max-ticket-life=10d krbtgt/${R}@${R}
-(set -vx; csr_grant pkinit bar@${R} foo@${R})
+csr_grant san_pkinit bar@${R} foo@${R}
${kdestroy}
token=$(KRB5CCNAME=$cache2 $gsstoken HTTP@$server)
if ! (set -vx;
@@ -677,22 +742,115 @@ fi
echo "Fetch TGTs (batch, authz fail)"
${kadmin} modify --max-ticket-life=10d krbtgt/${R}@${R}
-(set -vx; csr_grant pkinit bar@${R} foo@${R})
+csr_revoke
${kdestroy}
token=$(KRB5CCNAME=$cache2 $gsstoken HTTP@$server)
+rm -f "${cachefile}.json"
if (set -vx;
curl -o "${cachefile}.json" -Lgsf \
--resolve ${server}:${bx509port}:127.0.0.1 \
-H "Authorization: Negotiate $token" \
"http://${server}:${bx509port}/get-tgts?cname=bar@${R}&cname=baz@${R}"); then
+ # 200 Ok is not a problem. We have to check that the result is sane.
+ true
+else
+ if grep ccache "${cachefile}.json"; then
+ echo "Got TGTs with /get-tgts end-point that should have been denied"
+ exit 2;
+ fi
+ if ! grep error_code "${cachefile}.json" > /dev/null; then
+ cat "${cachefile}.json"
+ echo "Request failed w/o error information"
+ exit 2;
+ fi
+fi
+cat "${cachefile}.json"
+if grep ccache "${cachefile}.json"; then
echo "Got TGTs with /get-tgts end-point that should have been denied"
+ exit 2;
+fi
+
+echo "Fetch TGTs (batch, partial authz with IPC authorizer)"
+${kadmin} modify --max-ticket-life=10d krbtgt/${R}@${R}
+csr_revoke
+csr_grant san_pkinit bar@${R} foo@${R}
+csr_grant san_pkinit baz@${R} foo@${R}
+${kdestroy}
+token=$(KRB5CCNAME=$cache2 $gsstoken HTTP@$server)
+if ! (set -vx;
+ curl -vvvo "${cachefile}.json" -Lgsf \
+ --resolve ${server}:${bx509port}:127.0.0.1 \
+ -H "Authorization: Negotiate $token" \
+ "http://${server}:${bx509port}/get-tgts?cname=bar@${R}&cname=raz@${R}&cname=baz@${R}"); then
+ echo "Failed to get TGTs batch including non-existent principal"
+ exit 2
+fi
+if which jq >/dev/null; then
+ set -vx
+ jq -e . "${cachefile}.json" > /dev/null ||
+ { echo "/get-tgts produced non-JSON"; exit 2; }
+ jq -es '.[]|select(.name|startswith("raz@"))|(.error_code//empty)' "${cachefile}.json" > /dev/null ||
+ { echo "No error was reported for raz@${R}!"; exit 2; }
+ jq -es '.[]|select(.name|startswith("raz@"))|(.ccache//"")|(length==0)' "${cachefile}.json" > /dev/null ||
+ { echo "Non-empty ccache included for raz@${R}!"; exit 2; }
+
+ # Check bar@$R's tickets:
+ jq -r 'select(.name|startswith("bar@")).ccache' "${cachefile}.json" |
+ $rkbase64 -d -- - > "${cachefile}"
+ ${kgetcred} -H HTTP/${server}@${R} ||
+ { echo "Fetched TGT didn't work"; exit 2; }
+ ${klistjson} | jq -e --arg p bar@$R '.principal == $p' > /dev/null ||
+ { echo "/get-tgts produced wrong TGTs"; exit 2; }
+
+ # Check baz@$R's tickets:
+ jq -r 'select(.name|startswith("baz@")).ccache' "${cachefile}.json" |
+ $rkbase64 -d -- - > "${cachefile}"
+ ${kgetcred} -H HTTP/${server}@${R} ||
+ { echo "Fetched TGT didn't work"; exit 2; }
+ ${klistjson} | jq -e --arg p baz@$R '.principal == $p' > /dev/null ||
+ { echo "/get-tgts produced wrong TGTs"; exit 2; }
+fi
+
+echo "Fetch TGTs (batch, partial authz)"
+${kadmin} modify --max-ticket-life=10d krbtgt/${R}@${R}
+csr_revoke
+csr_grant san_pkinit bar@${R} foo@${R}
+${kdestroy}
+token=$(KRB5CCNAME=$cache2 $gsstoken HTTP@$server)
+if ! (set -vx;
+ curl -vvvo "${cachefile}.json" -Lgsf \
+ --resolve ${server}:${bx509port}:127.0.0.1 \
+ -H "Authorization: Negotiate $token" \
+ "http://${server}:${bx509port}/get-tgts?cname=not@${R}&cname=bar@${R}&cname=baz@${R}"); then
+ echo "Failed to get TGTs batch including non-existent principal"
exit 2
fi
+if which jq >/dev/null; then
+ set -vx
+ jq -e . "${cachefile}.json" > /dev/null ||
+ { echo "/get-tgts produced non-JSON"; exit 2; }
+ jq -es '.[]|select(.name|startswith("not@"))|(.error_code//empty)' "${cachefile}.json" > /dev/null ||
+ { echo "No error was reported for not@${R}!"; exit 2; }
+ jq -es '.[]|select(.name|startswith("not@"))|(.ccache//"")|(length==0)' "${cachefile}.json" > /dev/null ||
+ { echo "Non-empty ccache included for not@${R}!"; exit 2; }
+ jq -es '.[]|select(.name|startswith("baz@"))|(.error_code//empty)' "${cachefile}.json" > /dev/null ||
+ { echo "No error was reported for baz@${R}!"; exit 2; }
+ jq -es '.[]|select(.name|startswith("baz@"))|(.ccache//"")|(length==0)' "${cachefile}.json" > /dev/null ||
+ { echo "Non-empty ccache included for baz@${R}!"; exit 2; }
+
+ # Check bar@$R's tickets:
+ jq -r 'select(.name|startswith("bar@")).ccache' "${cachefile}.json" |
+ $rkbase64 -d -- - > "${cachefile}"
+ ${kgetcred} -H HTTP/${server}@${R} ||
+ { echo "Fetched TGT didn't work"; exit 2; }
+ ${klistjson} | jq -e --arg p bar@$R '.principal == $p' > /dev/null ||
+ { echo "/get-tgts produced wrong TGTs"; exit 2; }
+fi
echo "Fetch TGTs (batch, authz pass)"
${kadmin} modify --max-ticket-life=10d krbtgt/${R}@${R}
-(csr_grant pkinit bar@${R} foo@${R})
-(csr_grant pkinit baz@${R} foo@${R})
+csr_grant san_pkinit bar@${R} foo@${R}
+csr_grant san_pkinit baz@${R} foo@${R}
${kdestroy}
token=$(KRB5CCNAME=$cache2 $gsstoken HTTP@$server)
if ! (set -vx;
@@ -726,9 +884,9 @@ fi
echo "Fetch TGTs (batch, authz pass, one non-existent principal)"
${kadmin} modify --max-ticket-life=10d krbtgt/${R}@${R}
-(csr_grant pkinit bar@${R} foo@${R})
-(csr_grant pkinit baz@${R} foo@${R})
-(csr_grant pkinit not@${R} foo@${R})
+csr_grant san_pkinit bar@${R} foo@${R}
+csr_grant san_pkinit baz@${R} foo@${R}
+csr_grant san_pkinit not@${R} foo@${R}
${kdestroy}
token=$(KRB5CCNAME=$cache2 $gsstoken HTTP@$server)
if ! (set -vx;
@@ -913,9 +1071,10 @@ else
exit 1
fi
-echo "killing kdc (${kdcpid}) and bx509d (${bx509pid})"
+echo "killing kdc (${kdcpid}) and bx509d (${bx509pid}) and test_csr_authorizer (${test_csr_authorizer_pid})"
sh ${leaks_kill} kdc $kdcpid || ec=1
sh ${leaks_kill} bx509d $bx509pid || ec=1
+sh ${leaks_kill} test_csr_authorizer $test_csr_authorizer_pid || ec=1
trap "" EXIT
diff --git a/third_party/heimdal/tests/kdc/check-fast.in b/third_party/heimdal/tests/kdc/check-fast.in
index 3fbda813a63..d1683f2e750 100644
--- a/third_party/heimdal/tests/kdc/check-fast.in
+++ b/third_party/heimdal/tests/kdc/check-fast.in
@@ -171,9 +171,7 @@ done
# Use MIT client tools
#
-mit=/usr/local/mitkerberos/bin
-
-if [ -f ${mit}/kinit ] ; then
+if [ -n "$MITKRB5" -a -f "${MITKRB5}/kinit" ] ; then
echo "Running MIT FAST tests"
kinitpty=${objdir}/foopassword.rkpty
@@ -183,25 +181,25 @@ password foo\n
EOF
echo "Acquire host ticket"; > messages.log
- ${rkpty} ${kinitpty} ${mit}/kinit -c ${acache} ${server}@${R} >/dev/null|| { exit 1; }
+ ${rkpty} ${kinitpty} "${MITKRB5}/kinit" -c ${acache} ${server}@${R} >/dev/null|| { exit 1; }
(${aklist} | grep ${server} > /dev/null ) || { exit 1; }
echo "Checking for FAST avail"; > messages.log
${aklist} --hidden | grep fast_avail > /dev/null || { exit 1; }
echo "Using plain to get a initial ticket"; > messages.log
- ${rkpty} ${kinitpty} ${mit}/kinit -c ${cache} foo@${R} >/dev/null|| { exit 1; }
+ ${rkpty} ${kinitpty} "${MITKRB5}/kinit" -c ${cache} foo@${R} >/dev/null|| { exit 1; }
(${klist} | grep foo > /dev/null ) || { exit 1; }
echo "Using FAST to get a initial ticket"; > messages.log
- ${rkpty} ${kinitpty} ${mit}/kinit -c ${cache} -T ${acache} foo@${R} >/dev/null || { exit 1; }
+ ${rkpty} ${kinitpty} "${MITKRB5}/kinit" -c ${cache} -T ${acache} foo@${R} >/dev/null || { exit 1; }
(${klist} | grep foo > /dev/null ) || { exit 1; }
echo "Checking for FAST avail"; > messages.log
${klist} --hidden | grep fast_avail > /dev/null || { exit 1; }
echo "Getting service ticket"; > messages.log
- ${mit}/kvno -c ${cache} ${server}@${R} || { exit 1; }
+ "${MITKRB5}/kvno" -c ${cache} ${server}@${R} || { exit 1; }
fi
diff --git a/third_party/heimdal/tests/kdc/check-httpkadmind.in b/third_party/heimdal/tests/kdc/check-httpkadmind.in
index 816f753d079..9707fc14b55 100644
--- a/third_party/heimdal/tests/kdc/check-httpkadmind.in
+++ b/third_party/heimdal/tests/kdc/check-httpkadmind.in
@@ -97,15 +97,19 @@ KRB5_CONFIG="${objdir}/krb5-httpkadmind.conf"
export KRB5_CONFIG
KRB5CCNAME=$cache
export KRB5CCNAME
+HEIM_PIDFILE_DIR=$objdir
+export HEIM_PIDFILE_DIR
+HEIM_IPC_DIR=$objdir
+export HEIM_IPC_DIR
rm -f current-db*
rm -f out-*
rm -f mkey.file*
rm -f *.pem *.crt *.der
-rm -rf simple_csr_authz
+rm -rf authz_dir
rm -f extracted_keytab*
-mkdir -p simple_csr_authz
+mkdir -p authz_dir
> messages.log
@@ -115,13 +119,13 @@ mkdir -p simple_csr_authz
# grant ext-type value grantee_principal
grant() {
- mkdir -p "${objdir}/simple_csr_authz/${3}"
- touch "${objdir}/simple_csr_authz/${3}/${1}-${2}"
+ mkdir -p "${objdir}/authz_dir/${3}"
+ touch "${objdir}/authz_dir/${3}/${1}=${2}"
}
revoke() {
- rm -rf "${objdir}/simple_csr_authz"
- mkdir -p "${objdir}/simple_csr_authz"
+ rm -rf "${objdir}/authz_dir"
+ mkdir -p "${objdir}/authz_dir"
}
if set -o|grep 'verbose.*on' > /dev/null ||
@@ -204,15 +208,18 @@ get_keytab_POST_redir() {
kdcpid=
httpkadmindpid=
httpkadmind2pid=
+test_csr_authorizer_pid=
kadmindpid=
kadmind2pid=
cleanup() {
test -n "$kdcpid" &&
{ echo signal killing kdc; kill -9 "$kdcpid"; }
+ test -n "$test_csr_authorizer_pid" &&
+ { echo signal killing test_csr_authorizer; kill -9 "$test_csr_authorizer_pid"; }
test -n "$httpkadmindpid" &&
{ echo signal killing httpkadmind; kill -9 "$httpkadmindpid"; }
test -n "$httpkadmind2pid" &&
- { echo signal killing httpkadmind; kill -9 "$httpkadmind2pid"; }
+ { echo signal killing second httpkadmind; kill -9 "$httpkadmind2pid"; }
test -n "$kadmindpid" &&
{ echo signal killing kadmind; kill -9 "$kadmindpid"; }
test -n "$kadmind2pid" &&
@@ -224,29 +231,28 @@ rm -f extracted_keytab
echo "Creating database"
rm -f $kt $ukt
-${kadmin} init \
- --realm-max-ticket-life=1day \
- --realm-max-renewable-life=1month \
- ${R} || exit 1
-${kadmin} add -r --use-defaults foo@${R} || exit 1
-${kadmin} add -r --use-defaults httpkadmind/admin@${R} || exit 1
-${kadmin} add -r --use-defaults WELLKNOWN/CSRFTOKEN@${R} || exit 1
-${kadmin} add -r --use-defaults HTTP/localhost@${R} || exit 1
-${kadmin} add -r --use-defaults host/xyz.${domain}@${R} || exit 1
-${kadmin} add -r --use-defaults HTTP/xyz.${domain}@${R} || exit 1
-${kadmin} add_ns --key-rotation-epoch=-1d --key-rotation-period=5m \
- --max-ticket-life=1d --max-renewable-life=5d \
- --attributes= HTTP/ns.${domain}@${R} || exit 1
-${kadmin} add_ns --key-rotation-epoch=-1d --key-rotation-period=5m \
- --max-ticket-life=1d --max-renewable-life=5d \
- --attributes=ok-as-delegate host/.ns2.${domain}@${R} || exit 1
-${kadmin} add -r --use-defaults HTTP/${server}@${R} || exit 1
-${kadmin} ext_keytab -r -k $keytab kadmin/admin@${R} || exit 1
-${kadmin} ext_keytab -r -k $keytab httpkadmind/admin@${R} || exit 1
-${kadmin} ext_keytab -r -k $keytab HTTP/${server}@${R} || exit 1
-${kadmin} ext_keytab -r -k $keytab HTTP/localhost@${R} || exit 1
-${kadmin} add -r --use-defaults HTTP/${otherserver}@${R} || exit 1
-${kadmin} ext_keytab -r -k $ukeytab foo@${R} || exit 1
+${kadmin} <<EOF || exit 1
+init --realm-max-ticket-life=1day --realm-max-renewable-life=1month ${R}
+add -r --use-defaults foo@${R}
+add -r --use-defaults httpkadmind/admin@${R}
+add -r --use-defaults WELLKNOWN/CSRFTOKEN@${R}
+add -r --use-defaults HTTP/localhost@${R}
+add -r --use-defaults host/xyz.${domain}@${R}
+add -r --use-defaults HTTP/xyz.${domain}@${R}
+add_ns --key-rotation-epoch=-1d --key-rotation-period=5m \
+ --max-ticket-life=1d --max-renewable-life=5d \
+ --attributes= HTTP/ns.${domain}@${R}
+add_ns --key-rotation-epoch=-1d --key-rotation-period=5m \
+ --max-ticket-life=1d --max-renewable-life=5d \
+ --attributes=ok-as-delegate host/.ns2.${domain}@${R}
+add -r --use-defaults HTTP/${server}@${R}
+ext_keytab -r -k $keytab kadmin/admin@${R}
+ext_keytab -r -k $keytab httpkadmind/admin@${R}
+ext_keytab -r -k $keytab HTTP/${server}@${R}
+ext_keytab -r -k $keytab HTTP/localhost@${R}
+add -r --use-defaults HTTP/${otherserver}@${R}
+ext_keytab -r -k $ukeytab foo@${R}
+EOF
${kdestroy}
# For a while let's not bother with a KDC
@@ -259,6 +265,12 @@ $kimpersonate -A --ccache=$cache -k $keytab -R -t aes128-cts-hmac-sha1-96 \
$klist -t >/dev/null ||
{ echo "failed to setup kimpersonate credentials"; exit 2; }
+echo "Starting test_csr_authorizer"
+${test_csr_authorizer} -A $objdir/authz_dir -S $objdir --server --daemon ||
+ { echo "test_csr_authorizer failed to start"; exit 2; }
+test_csr_authorizer_pid=`getpid test_csr_authorizer`
+ec=0
+
echo "Starting httpkadmind"
${httpkadmind} -H $server -H localhost --local -t --daemon ||
{ echo "httpkadmind failed to start"; exit 2; }
@@ -291,7 +303,7 @@ hn=xyz.${domain}
p=HTTP/$hn
echo "Fetching keytab for concrete principal $p"
rm -f extracted_keytab*
-grant dnsname $hn foo@${R}
+grant san_dnsname $hn foo@${R}
${kadmin} ext_keytab -k extracted_keytab $p ||
{ echo "Failed to get a keytab for $p with kadmin"; exit 1; }
${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.kadmin ||
@@ -307,7 +319,7 @@ hn=foo.ns.${domain}
p=HTTP/$hn
echo "Fetching keytab for virtual principal $p"
rm -f extracted_keytab*
-grant dnsname $hn foo@${R}
+grant san_dnsname $hn foo@${R}
${kadmin} ext_keytab -k extracted_keytab $p ||
{ echo "Failed to get a keytab for $p with kadmin"; exit 1; }
${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.kadmin ||
@@ -329,9 +341,9 @@ p2=HTTP/$hn2
p3=HTTP/$hn3
echo "Fetching keytabs for more than one principal"
rm -f extracted_keytab*
-grant dnsname $hn1 foo@${R}
-grant dnsname $hn2 foo@${R}
-grant dnsname $hn3 foo@${R}
+grant san_dnsname $hn1 foo@${R}
+grant san_dnsname $hn2 foo@${R}
+grant san_dnsname $hn3 foo@${R}
# Note that httpkadmind will first process dNSName q-params, then the spn
# q-params.
${kadmin} ext_keytab -k extracted_keytab $p1 ||
@@ -372,7 +384,7 @@ hn=xyz.${domain}
p=host/$hn
echo "Fetching keytab for virtual principal $p"
rm -f extracted_keytab*
-grant dnsname $hn foo@${R}
+grant san_dnsname $hn foo@${R}
get_keytab "service=host&dNSName=xyz.${domain}" -sf -o "${objdir}/extracted_keytab" &&
{ echo "Got a keytab for $p even though it is a host service!"; exit 1; }
get_keytab "spn=host/xyz.${domain}" -sf -o "${objdir}/extracted_keytab" &&
@@ -383,7 +395,7 @@ hn=xyz.${domain}
p=HTTP/$hn
echo "Checking key rotation for concrete principal $p"
rm -f extracted_keytab*
-grant dnsname $hn foo@${R}
+grant san_dnsname $hn foo@${R}
get_keytab "dNSName=${hn}" -sf -o "${objdir}/extracted_keytab" ||
{ echo "Failed to get a keytab for $p with curl"; exit 1; }
${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest1 ||
@@ -405,7 +417,7 @@ hn=xyz.${domain}
p=HTTP/$hn
echo "Checking key rotation w/ revocation for concrete principal $p"
rm -f extracted_keytab*
-grant dnsname $hn foo@${R}
+grant san_dnsname $hn foo@${R}
get_keytab "dNSName=${hn}" -sf -o "${objdir}/extracted_keytab" ||
{ echo "Failed to get a keytab for $p with curl"; exit 1; }
${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest1 ||
@@ -425,7 +437,7 @@ hn=abc.${domain}
p=HTTP/$hn
echo "Checking concrete principal creation ($p)"
rm -f extracted_keytab
-grant dnsname $hn foo@${R}
+grant san_dnsname $hn foo@${R}
get_keytab "dNSName=${hn}&create=true" -sf -o "${objdir}/extracted_keytab" &&
{ echo "GET succeeded for write operation!"; exit 1; }
get_keytab_POST "dNSName=${hn}&create=true" -s -o "${objdir}/extracted_keytab" ||
@@ -444,7 +456,7 @@ hn=bar.ns.${domain}
p=HTTP/$hn
echo "Checking materialization of virtual principal ($p)"
rm -f extracted_keytab
-grant dnsname $hn foo@${R}
+grant san_dnsname $hn foo@${R}
get_keytab "dNSName=${hn}&materialize=true" -sf -o "${objdir}/extracted_keytab" &&
{ echo "GET succeeded for write operation!"; exit 1; }
get_keytab_POST "dNSName=${hn}&materialize=true" -s -o "${objdir}/extracted_keytab" ||
@@ -471,7 +483,7 @@ p=HTTP/$hn
restport=$restport2
echo "Checking principal creation at secondary yields redirect"
rm -f extracted_keytab
-grant dnsname $hn foo@${R}
+grant san_dnsname $hn foo@${R}
get_keytab_POST_redir "dNSName=${hn}&create=true" \
-s -o "${objdir}/extracted_keytab"
${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest ||
@@ -559,7 +571,7 @@ hn=xyz.${domain}
p=HTTP/$hn
echo "Fetching keytab for concrete principal $p using remote HDB"
rm -f extracted_keytab*
-grant dnsname $hn httpkadmind/admin@${R}
+grant san_dnsname $hn httpkadmind/admin@${R}
KRB5CCNAME=$admincache ${kadmin} ext_keytab -k extracted_keytab $p ||
{ echo "Failed to get a keytab for $p with kadmin"; exit 1; }
${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.kadmin ||
@@ -575,7 +587,7 @@ hn=xyz.${domain}
p=HTTP/$hn
echo "Checking key rotation for concrete principal $p using remote HDB"
rm -f extracted_keytab*
-grant dnsname $hn foo@${R}
+grant san_dnsname $hn foo@${R}
get_keytab "dNSName=${hn}" -sf -o "${objdir}/extracted_keytab" ||
{ echo "Failed to get a keytab for $p with curl"; exit 1; }
${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest1 ||
@@ -610,7 +622,7 @@ hn=xyz.${domain}
p=HTTP/$hn
echo "Fetching keytab for concrete principal $p using local read-only HDB"
rm -f extracted_keytab*
-grant dnsname $hn httpkadmind/admin@${R}
+grant san_dnsname $hn httpkadmind/admin@${R}
KRB5CCNAME=$admincache ${kadmin} ext_keytab -k extracted_keytab $p ||
{ echo "Failed to get a keytab for $p with kadmin"; exit 1; }
${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.kadmin ||
@@ -626,7 +638,7 @@ hn=xyz.${domain}
p=HTTP/$hn
echo "Checking key rotation for concrete principal $p using local read-only HDB and remote HDB"
rm -f extracted_keytab*
-grant dnsname $hn foo@${R}
+grant san_dnsname $hn foo@${R}
get_keytab "dNSName=${hn}" -sf -o "${objdir}/extracted_keytab" ||
{ echo "Failed to get a keytab for $p with curl"; exit 1; }
${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest1 ||
@@ -810,6 +822,7 @@ KRB5CCNAME=$admincache ${kadmin} get $p |
grep 'Internal error' messages.log &&
{ echo "Internal errors in log"; exit 1; }
+sh ${leaks_kill} test_csr_authorizer $test_csr_authorizer_pid || ec=1
sh ${leaks_kill} httpkadmind $httpkadmindpid || ec=1
sh ${leaks_kill} kadmind $kadmindpid || ec=1
sh ${leaks_kill} kadmind $kadmind2pid || ec=1
diff --git a/third_party/heimdal/tests/kdc/check-pkinit.in b/third_party/heimdal/tests/kdc/check-pkinit.in
index 9f90fd040f9..571a64e9c15 100644
--- a/third_party/heimdal/tests/kdc/check-pkinit.in
+++ b/third_party/heimdal/tests/kdc/check-pkinit.in
@@ -64,6 +64,11 @@ kx509="${kx509} -c $cache"
KRB5_CONFIG="${objdir}/krb5-pkinit.conf"
export KRB5_CONFIG
+HEIM_PIDFILE_DIR=$objdir
+export HEIM_PIDFILE_DIR
+HEIM_IPC_DIR=$objdir
+export HEIM_IPC_DIR
+
rsa=yes
pkinit=no
diff --git a/third_party/heimdal/tests/kdc/krb5-bx509.conf.in b/third_party/heimdal/tests/kdc/krb5-bx509.conf.in
index 8a9d0bb4940..2cd6fef2215 100644
--- a/third_party/heimdal/tests/kdc/krb5-bx509.conf.in
+++ b/third_party/heimdal/tests/kdc/krb5-bx509.conf.in
@@ -29,9 +29,6 @@
# Locate kdc plugins for testing
plugin_dir = @objdir@/../../kdc/.libs
- # Configure kdc plugins for testing
- simple_csr_authorizer_directory = @objdir@/simple_csr_authz
-
enable-pkinit = true
pkinit_identity = PEM-FILE:@objdir@/user-issuer.pem
pkinit_anchors = PEM-FILE:@objdir@/pkinit-anchor.pem
@@ -86,7 +83,6 @@
db-dir = @objdir@
[bx509]
- simple_csr_authorizer_directory = @objdir@/simple_csr_authz
realms = {
TEST.H5L.SE = {
# Default (no cert exts requested)
@@ -127,7 +123,6 @@
[get-tgt]
no_addresses = true
allow_addresses = true
- simple_csr_authorizer_directory = @objdir@/simple_csr_authz
realms = {
TEST.H5L.SE = {
# Default (no cert exts requested)
diff --git a/third_party/heimdal/tests/kdc/krb5-httpkadmind.conf.in b/third_party/heimdal/tests/kdc/krb5-httpkadmind.conf.in
index f887e82c4f1..fb2fc6a2f08 100644
--- a/third_party/heimdal/tests/kdc/krb5-httpkadmind.conf.in
+++ b/third_party/heimdal/tests/kdc/krb5-httpkadmind.conf.in
@@ -28,9 +28,6 @@
# Locate kdc plugins for testing
plugin_dir = @objdir@/../../kdc/.libs
- # Configure kdc plugins for testing
- simple_csr_authorizer_directory = @objdir@/simple_csr_authz
-
database = {
dbname = @objdir@/current-db
realm = TEST.H5L.SE
@@ -84,7 +81,6 @@
virtual_hostbased_princ_svcs = HTTP host
[ext_keytab]
- simple_csr_authorizer_directory = @objdir@/simple_csr_authz
new_hostbased_service_principal_attributes = {
host = {
a-particular-hostname.test.h5l.se = ok-as-delegate,no-auth-data-reqd
diff --git a/third_party/heimdal/tests/kdc/krb5-pkinit.conf.in b/third_party/heimdal/tests/kdc/krb5-pkinit.conf.in
index fbc21277a3d..e2d3f3d26a8 100644
--- a/third_party/heimdal/tests/kdc/krb5-pkinit.conf.in
+++ b/third_party/heimdal/tests/kdc/krb5-pkinit.conf.in
@@ -25,7 +25,9 @@
plugin_dir = @objdir@/../../kdc/.libs
- simple_csr_authorizer_directory = @objdir@/simple_csr_authz
+ ipc_csr_authorizer = {
+ optional = true
+ }
enable_kx509 = true
require_initial_kca_tickets = false
diff --git a/third_party/heimdal/tests/plugin/kdc_test_plugin.c b/third_party/heimdal/tests/plugin/kdc_test_plugin.c
index ff33b5f7262..6df40a2b722 100644
--- a/third_party/heimdal/tests/plugin/kdc_test_plugin.c
+++ b/third_party/heimdal/tests/plugin/kdc_test_plugin.c
@@ -61,7 +61,8 @@ pac_verify(void *ctx,
hdb_entry * client,
hdb_entry * server,
hdb_entry * krbtgt,
- krb5_pac *pac)
+ krb5_pac pac,
+ krb5_boolean *is_trusted)
{
krb5_context context = kdc_request_get_context((kdc_request_t)r);
krb5_error_code ret;
@@ -73,12 +74,12 @@ pac_verify(void *ctx,
krb5_warnx(context, "pac_verify");
- ret = krb5_pac_get_buffer(context, *pac, 1, &data);
+ ret = krb5_pac_get_buffer(context, pac, 1, &data);
if (ret)
return ret;
krb5_data_free(&data);
- ret = krb5_pac_get_kdc_checksum_info(context, *pac, &cstype, &rodc_id);
+ ret = krb5_pac_get_kdc_checksum_info(context, pac, &cstype, &rodc_id);
if (ret)
return ret;
@@ -95,7 +96,7 @@ pac_verify(void *ctx,
if (ret)
return ret;
- return krb5_pac_verify(context, *pac, 0, NULL, NULL, &key->key);
+ return krb5_pac_verify(context, pac, 0, NULL, NULL, &key->key);
}
static void logit(const char *what, astgs_request_t r)
@@ -161,11 +162,12 @@ audit(void *ctx, astgs_request_t r)
}
static krb5plugin_kdc_ftable kdc_plugin = {
- KRB5_PLUGIN_KDC_VERSION_10,
+ KRB5_PLUGIN_KDC_VERSION_11,
init,
fini,
pac_generate,
pac_verify,
+ NULL, /* pac_update */
client_access,
NULL, /* referral_policy */
finalize_reply,