From cbe156d9279effd6780fc36b620321e373217863 Mon Sep 17 00:00:00 2001 From: Nicolas Williams Date: Thu, 16 Oct 2025 13:06:15 -0500 Subject: [PATCH] Use OpenSSL 3.x _only_ and implement RFC 8636 - No more OpenSSL 1.x support - Remove 1DES and 3DES - Remove NETLOGON, NTLM (client and 'digest' service) --- admin/Makefile.am | 4 +- admin/add.c | 4 +- admin/ktutil_locl.h | 1 + appl/Makefile.am | 4 - appl/afsutil/ChangeLog | 125 - appl/afsutil/Makefile.am | 18 - appl/afsutil/NTMakefile | 35 - appl/afsutil/afslog.1 | 147 -- appl/afsutil/afslog.c | 303 --- appl/afsutil/pagsh.1 | 94 - appl/afsutil/pagsh.c | 213 -- appl/test/Makefile.am | 1 - cf/Makefile.am.common | 2 +- cf/crypto.m4 | 25 + configure.ac | 12 +- doc/Makefile.am | 11 +- doc/ntlm.din | 16 - include/Makefile.am | 4 - include/crypto-headers.h | 5 + include/gssapi/Makefile.am | 2 +- kadmin/ank.c | 6 +- kadmin/cpw.c | 6 +- kadmin/kadmin.c | 12 + kadmin/stash.c | 4 +- kcm/Makefile.am | 2 +- kcm/protocol.c | 373 +-- kdc/Makefile.am | 16 +- kdc/NTMakefile | 14 +- kdc/bx509d.c | 119 +- kdc/config.c | 14 + kdc/default_config.c | 29 +- kdc/digest-service.c | 289 --- kdc/digest.c | 1520 ------------ kdc/hprop.c | 14 + kdc/hpropd.c | 14 + kdc/httpkadmind.c | 58 +- kdc/kdc_locl.h | 2 - kdc/kstash.c | 4 +- kdc/kx509.c | 89 +- kdc/pkinit-ec.c | 525 ----- kdc/pkinit.c | 1090 ++++++--- kdc/process.c | 31 - kdc/string2key.c | 2 +- kpasswd/Makefile.am | 4 + kpasswd/kpasswd.c | 4 +- kpasswd/kpasswd_locl.h | 1 + kuser/Makefile.am | 23 +- kuser/NTMakefile | 16 - kuser/kdestroy.c | 14 - kuser/kdigest-commands.in | 280 --- kuser/kdigest-version.rc | 36 - kuser/kdigest.8 | 257 --- kuser/kdigest.c | 570 ----- kuser/kinit.c | 121 +- kuser/klist.c | 82 - kuser/kuser_locl.h | 3 - lib/Makefile.am | 7 - lib/NTMakefile | 2 +- lib/asn1/Makefile.am | 15 +- lib/asn1/NTMakefile | 8 +- lib/asn1/asn1-template.h | 2 + lib/asn1/asn1parse.y | 1 + lib/asn1/check-gen.c | 372 +-- lib/asn1/cms.asn1 | 70 +- lib/asn1/data/test_ios_cert.der | Bin 0 -> 1170 bytes lib/asn1/data/test_ios_cert.json | 1 + lib/asn1/der_get.c | 8 + lib/asn1/der_length.c | 6 + lib/asn1/der_print.c | 6 + lib/asn1/der_put.c | 7 + lib/asn1/gen.c | 1 + lib/asn1/gen_template.c | 42 +- lib/asn1/krb5.asn1 | 1 + lib/asn1/krb5.opt | 6 + lib/asn1/pkcs12.asn1 | 49 +- lib/asn1/pkinit.asn1 | 12 +- lib/asn1/pkinit.opt | 6 +- lib/asn1/rfc2459.asn1 | 144 +- lib/asn1/rfc2459.opt | 1 + lib/asn1/symbol.h | 1 + lib/asn1/template.c | 42 +- lib/base/heimbase-atomics.h | 51 +- lib/gssapi/Makefile.am | 52 +- lib/gssapi/NTMakefile | 94 +- lib/gssapi/gssapi/gssapi_ntlm.h | 41 - lib/gssapi/gssapi_mech.h | 1 - lib/gssapi/gsstool.c | 1 - lib/gssapi/krb5/arcfour.c | 252 +- lib/gssapi/krb5/get_mic.c | 248 +- lib/gssapi/krb5/unwrap.c | 376 +-- lib/gssapi/krb5/verify_mic.c | 251 +- lib/gssapi/krb5/wrap.c | 342 +-- lib/gssapi/mech/gss_mech_switch.c | 3 - lib/gssapi/netlogon/accept_sec_context.c | 89 - lib/gssapi/netlogon/acquire_cred.c | 186 -- lib/gssapi/netlogon/add_cred.c | 89 - lib/gssapi/netlogon/canonicalize_name.c | 46 - lib/gssapi/netlogon/compare_name.c | 61 - lib/gssapi/netlogon/context_time.c | 47 - lib/gssapi/netlogon/crypto.c | 733 ------ lib/gssapi/netlogon/delete_sec_context.c | 62 - lib/gssapi/netlogon/display_name.c | 67 - lib/gssapi/netlogon/display_status.c | 55 - lib/gssapi/netlogon/duplicate_cred.c | 54 - lib/gssapi/netlogon/duplicate_name.c | 77 - lib/gssapi/netlogon/export_name.c | 45 - lib/gssapi/netlogon/export_sec_context.c | 50 - lib/gssapi/netlogon/external.c | 111 - lib/gssapi/netlogon/import_name.c | 94 - lib/gssapi/netlogon/import_sec_context.c | 50 - lib/gssapi/netlogon/indicate_mechs.c | 48 - lib/gssapi/netlogon/init_sec_context.c | 289 --- lib/gssapi/netlogon/inquire_context.c | 76 - lib/gssapi/netlogon/inquire_cred.c | 68 - lib/gssapi/netlogon/inquire_cred_by_mech.c | 66 - lib/gssapi/netlogon/inquire_mechs_for_name.c | 48 - lib/gssapi/netlogon/inquire_names_for_mech.c | 58 - lib/gssapi/netlogon/iter_cred.c | 44 - lib/gssapi/netlogon/netlogon.h | 149 -- lib/gssapi/netlogon/process_context_token.c | 46 - lib/gssapi/netlogon/regen.sh | 3 - lib/gssapi/netlogon/release_cred.c | 54 - lib/gssapi/netlogon/release_name.c | 54 - lib/gssapi/ntlm/accept_sec_context.c | 256 --- lib/gssapi/ntlm/acquire_cred.c | 88 - lib/gssapi/ntlm/add_cred.c | 60 - lib/gssapi/ntlm/canonicalize_name.c | 45 - lib/gssapi/ntlm/compare_name.c | 45 - lib/gssapi/ntlm/context_time.c | 45 - lib/gssapi/ntlm/creds.c | 159 -- lib/gssapi/ntlm/crypto.c | 615 ----- lib/gssapi/ntlm/delete_sec_context.c | 69 - lib/gssapi/ntlm/display_name.c | 71 - lib/gssapi/ntlm/display_status.c | 54 - lib/gssapi/ntlm/duplicate_cred.c | 57 - lib/gssapi/ntlm/duplicate_name.c | 48 - lib/gssapi/ntlm/export_name.c | 50 - lib/gssapi/ntlm/export_sec_context.c | 50 - lib/gssapi/ntlm/external.c | 140 -- lib/gssapi/ntlm/import_name.c | 112 - lib/gssapi/ntlm/import_sec_context.c | 48 - lib/gssapi/ntlm/indicate_mechs.c | 46 - lib/gssapi/ntlm/init_sec_context.c | 536 ----- lib/gssapi/ntlm/inquire_context.c | 68 - lib/gssapi/ntlm/inquire_cred_by_mech.c | 58 - lib/gssapi/ntlm/inquire_mechs_for_name.c | 48 - lib/gssapi/ntlm/inquire_names_for_mech.c | 51 - lib/gssapi/ntlm/inquire_sec_context_by_oid.c | 90 - lib/gssapi/ntlm/iter_cred.c | 99 - lib/gssapi/ntlm/kdc.c | 435 ---- lib/gssapi/ntlm/ntlm.h | 146 -- lib/gssapi/ntlm/process_context_token.c | 44 - lib/gssapi/ntlm/release_cred.c | 66 - lib/gssapi/ntlm/release_name.c | 52 - lib/gssapi/ntlm/set_sec_context_option.c | 60 - lib/gssapi/sanon/crypto.c | 86 +- lib/gssapi/sanon/sanon_locl.h | 6 +- lib/gssapi/test_context.c | 22 - lib/gssapi/test_ntlm.c | 337 --- lib/hdb/Makefile.am | 4 +- lib/hdb/data-mkey.mit.aes256.be | Bin 0 -> 38 bytes lib/hdb/data-mkey.mit.aes256.le | Bin 0 -> 38 bytes lib/hdb/data-mkey.mit.des3.be | Bin 46 -> 0 bytes lib/hdb/data-mkey.mit.des3.le | Bin 30 -> 0 bytes lib/heimdal/NTMakefile | 2 - lib/hx509/Makefile.am | 9 +- lib/hx509/cert.c | 367 ++- lib/hx509/cms.c | 43 +- lib/hx509/crypto-ec.c | 922 ++++++-- lib/hx509/crypto.c | 1268 ++++++----- lib/hx509/data/secp256r1TestCA.cert.der | Bin 0 -> 445 bytes lib/hx509/error.c | 137 ++ lib/hx509/hx_locl.h | 56 +- lib/hx509/hxtool.1 | 1321 +++++++++-- lib/hx509/hxtool.c | 118 +- lib/hx509/ks_file.c | 18 +- lib/hx509/ks_keychain.c | 590 ++--- lib/hx509/ks_p11.c | 1450 +++--------- lib/hx509/ks_p12.c | 1 + lib/hx509/libhx509-exports.def | 4 + lib/hx509/lock.c | 236 +- lib/hx509/print.c | 6 +- lib/hx509/ref/pkcs11.h | 2 + lib/hx509/req.c | 29 +- lib/hx509/revoke.c | 5 + lib/hx509/softp11.c | 194 +- lib/hx509/test_ca.in | 184 ++ lib/hx509/test_cms.in | 162 +- lib/hx509/test_pkcs12_pbes2.in | 189 ++ lib/hx509/version-script.map | 4 + lib/kadm5/Makefile.am | 14 +- lib/kadm5/ipropd_master.c | 14 + lib/kadm5/ipropd_slave.c | 14 + lib/kafs/ChangeLog | 572 ----- lib/kafs/Makefile.am | 96 - lib/kafs/NTMakefile | 35 - lib/kafs/afskrb5.c | 353 --- lib/kafs/afsl.exp | 6 - lib/kafs/afslib.c | 53 - lib/kafs/afslib.exp | 3 - lib/kafs/afssys.c | 630 ----- lib/kafs/afssysdefs.h | 109 - lib/kafs/common.c | 469 ---- lib/kafs/kafs.3 | 296 --- lib/kafs/kafs.h | 216 -- lib/kafs/kafs_locl.h | 162 -- lib/kafs/roken_rename.h | 64 - lib/kafs/rxkad_kdf.c | 220 -- lib/krb5/Makefile.am | 18 +- lib/krb5/NTMakefile | 15 +- lib/krb5/aes-test.c | 11 +- lib/krb5/context.c | 317 ++- lib/krb5/crypto-aes-sha1.c | 28 +- lib/krb5/crypto-aes-sha2.c | 22 +- lib/krb5/crypto-algs.c | 21 - lib/krb5/crypto-arcfour.c | 76 +- lib/krb5/crypto-des-common.c | 81 - lib/krb5/crypto-des.c | 303 --- lib/krb5/crypto-des3.c | 292 --- lib/krb5/crypto-evp.c | 284 ++- lib/krb5/crypto-pk.c | 145 +- lib/krb5/crypto.c | 57 +- lib/krb5/crypto.h | 50 +- lib/krb5/deprecated.c | 2 +- lib/krb5/derived-key-test.c | 2 + lib/krb5/digest.c | 1165 ---------- lib/krb5/error_string.c | 56 + lib/krb5/fast.c | 8 +- lib/krb5/get_cred.c | 2 +- lib/krb5/get_in_tkt.c | 189 ++ lib/krb5/init_creds_pw.c | 341 ++- lib/krb5/krb5.conf.5 | 133 +- lib/krb5/krb5_digest.3 | 260 --- lib/krb5/krb5_locl.h | 65 +- lib/krb5/kx509.c | 80 +- lib/krb5/libkrb5-exports.def.in | 50 +- lib/krb5/log.c | 30 + lib/krb5/pkinit-ec.c | 403 ++-- lib/krb5/pkinit.c | 895 +++++--- lib/krb5/prompter_posix.c | 8 +- lib/krb5/salt.c | 54 +- lib/krb5/sp800-108-kdf.c | 34 +- lib/krb5/string-to-key-test.c | 10 +- lib/krb5/test_crypto_wrapping.c | 4 +- lib/krb5/test_fx.c | 2 + lib/krb5/test_pknistkdf.c | 105 +- lib/krb5/version-script.map | 41 +- lib/ntlm/ChangeLog | 120 - lib/ntlm/Makefile.am | 48 - lib/ntlm/NTMakefile | 90 - lib/ntlm/apop.c | 263 --- lib/ntlm/digest.c | 994 -------- lib/ntlm/heim-auth.h | 135 -- lib/ntlm/heimntlm.h | 166 -- lib/ntlm/libheimntlm-exports.def | 24 - lib/ntlm/libheimntlm-version.rc | 36 - lib/ntlm/ntlm.c | 2027 ----------------- lib/ntlm/ntlm_err.et | 60 - lib/ntlm/test_commonauth.c | 425 ---- lib/ntlm/test_ntlm.c | 617 ----- lib/ntlm/version-script.map | 30 - .../assembly/Heimdal.Kerberos.manifest.in | 2 - packages/windows/assembly/NTMakefile | 2 - .../windows/installer/heimdal-assemblies.wxs | 2 - packages/windows/sdk/NTMakefile | 1 - tests/db/Makefile.am | 6 +- tests/db/check-dbinfo.in | 4 +- tests/db/loaddump-db.in | 61 +- tests/db/text-dump-0.7 | 7 - tests/db/text-dump-known-ext | 7 - tests/db/text-dump-no-ext | 7 - tests/db/text-dump-unknown-ext | 7 - tests/gss/Makefile.am | 10 +- tests/gss/check-context.in | 7 +- tests/gss/check-negoex.in | 2 - tests/gss/check-ntlm.in | 167 -- tests/gss/check-spnego.in | 57 +- tests/gss/ntlm-user-file.txt | 2 - tests/java/krb5.conf.in | 1 - tests/kdc/Makefile.am | 35 +- tests/kdc/check-bx509.in | 59 +- tests/kdc/check-delegation.in | 1 + tests/kdc/check-httpkadmind.in | 49 +- tests/kdc/check-iprop.in | 4 +- tests/kdc/check-kdc.in | 100 +- tests/kdc/check-keys.in | 100 - tests/kdc/check-pkinit.in | 190 +- tests/kdc/krb5-cccol.conf.in | 4 +- tests/kdc/krb5-kcm.conf.in | 4 +- tests/kdc/krb5.conf.in | 5 +- tests/kdc/ntlm-user-file.txt | 1 - windows/NTMakefile.config | 4 +- windows/NTMakefile.sdk | 9 + windows/NTMakefile.w32 | 9 +- 294 files changed, 9592 insertions(+), 29048 deletions(-) delete mode 100644 appl/afsutil/ChangeLog delete mode 100644 appl/afsutil/Makefile.am delete mode 100644 appl/afsutil/NTMakefile delete mode 100644 appl/afsutil/afslog.1 delete mode 100644 appl/afsutil/afslog.c delete mode 100644 appl/afsutil/pagsh.1 delete mode 100644 appl/afsutil/pagsh.c delete mode 100644 doc/ntlm.din delete mode 100644 kdc/digest-service.c delete mode 100644 kdc/digest.c delete mode 100644 kdc/pkinit-ec.c delete mode 100644 kuser/kdigest-commands.in delete mode 100644 kuser/kdigest-version.rc delete mode 100644 kuser/kdigest.8 delete mode 100644 kuser/kdigest.c create mode 100644 lib/asn1/data/test_ios_cert.der create mode 100644 lib/asn1/data/test_ios_cert.json delete mode 100644 lib/gssapi/gssapi/gssapi_ntlm.h delete mode 100644 lib/gssapi/netlogon/accept_sec_context.c delete mode 100644 lib/gssapi/netlogon/acquire_cred.c delete mode 100644 lib/gssapi/netlogon/add_cred.c delete mode 100644 lib/gssapi/netlogon/canonicalize_name.c delete mode 100644 lib/gssapi/netlogon/compare_name.c delete mode 100644 lib/gssapi/netlogon/context_time.c delete mode 100644 lib/gssapi/netlogon/crypto.c delete mode 100644 lib/gssapi/netlogon/delete_sec_context.c delete mode 100644 lib/gssapi/netlogon/display_name.c delete mode 100644 lib/gssapi/netlogon/display_status.c delete mode 100644 lib/gssapi/netlogon/duplicate_cred.c delete mode 100644 lib/gssapi/netlogon/duplicate_name.c delete mode 100644 lib/gssapi/netlogon/export_name.c delete mode 100644 lib/gssapi/netlogon/export_sec_context.c delete mode 100644 lib/gssapi/netlogon/external.c delete mode 100644 lib/gssapi/netlogon/import_name.c delete mode 100644 lib/gssapi/netlogon/import_sec_context.c delete mode 100644 lib/gssapi/netlogon/indicate_mechs.c delete mode 100644 lib/gssapi/netlogon/init_sec_context.c delete mode 100644 lib/gssapi/netlogon/inquire_context.c delete mode 100644 lib/gssapi/netlogon/inquire_cred.c delete mode 100644 lib/gssapi/netlogon/inquire_cred_by_mech.c delete mode 100644 lib/gssapi/netlogon/inquire_mechs_for_name.c delete mode 100644 lib/gssapi/netlogon/inquire_names_for_mech.c delete mode 100644 lib/gssapi/netlogon/iter_cred.c delete mode 100644 lib/gssapi/netlogon/netlogon.h delete mode 100644 lib/gssapi/netlogon/process_context_token.c delete mode 100644 lib/gssapi/netlogon/regen.sh delete mode 100644 lib/gssapi/netlogon/release_cred.c delete mode 100644 lib/gssapi/netlogon/release_name.c delete mode 100644 lib/gssapi/ntlm/accept_sec_context.c delete mode 100644 lib/gssapi/ntlm/acquire_cred.c delete mode 100644 lib/gssapi/ntlm/add_cred.c delete mode 100644 lib/gssapi/ntlm/canonicalize_name.c delete mode 100644 lib/gssapi/ntlm/compare_name.c delete mode 100644 lib/gssapi/ntlm/context_time.c delete mode 100644 lib/gssapi/ntlm/creds.c delete mode 100644 lib/gssapi/ntlm/crypto.c delete mode 100644 lib/gssapi/ntlm/delete_sec_context.c delete mode 100644 lib/gssapi/ntlm/display_name.c delete mode 100644 lib/gssapi/ntlm/display_status.c delete mode 100644 lib/gssapi/ntlm/duplicate_cred.c delete mode 100644 lib/gssapi/ntlm/duplicate_name.c delete mode 100644 lib/gssapi/ntlm/export_name.c delete mode 100644 lib/gssapi/ntlm/export_sec_context.c delete mode 100644 lib/gssapi/ntlm/external.c delete mode 100644 lib/gssapi/ntlm/import_name.c delete mode 100644 lib/gssapi/ntlm/import_sec_context.c delete mode 100644 lib/gssapi/ntlm/indicate_mechs.c delete mode 100644 lib/gssapi/ntlm/init_sec_context.c delete mode 100644 lib/gssapi/ntlm/inquire_context.c delete mode 100644 lib/gssapi/ntlm/inquire_cred_by_mech.c delete mode 100644 lib/gssapi/ntlm/inquire_mechs_for_name.c delete mode 100644 lib/gssapi/ntlm/inquire_names_for_mech.c delete mode 100644 lib/gssapi/ntlm/inquire_sec_context_by_oid.c delete mode 100644 lib/gssapi/ntlm/iter_cred.c delete mode 100644 lib/gssapi/ntlm/kdc.c delete mode 100644 lib/gssapi/ntlm/ntlm.h delete mode 100644 lib/gssapi/ntlm/process_context_token.c delete mode 100644 lib/gssapi/ntlm/release_cred.c delete mode 100644 lib/gssapi/ntlm/release_name.c delete mode 100644 lib/gssapi/ntlm/set_sec_context_option.c delete mode 100644 lib/gssapi/test_ntlm.c create mode 100644 lib/hdb/data-mkey.mit.aes256.be create mode 100644 lib/hdb/data-mkey.mit.aes256.le delete mode 100644 lib/hdb/data-mkey.mit.des3.be delete mode 100644 lib/hdb/data-mkey.mit.des3.le create mode 100644 lib/hx509/data/secp256r1TestCA.cert.der create mode 100644 lib/hx509/test_pkcs12_pbes2.in delete mode 100644 lib/kafs/ChangeLog delete mode 100644 lib/kafs/Makefile.am delete mode 100644 lib/kafs/NTMakefile delete mode 100644 lib/kafs/afskrb5.c delete mode 100644 lib/kafs/afsl.exp delete mode 100644 lib/kafs/afslib.c delete mode 100644 lib/kafs/afslib.exp delete mode 100644 lib/kafs/afssys.c delete mode 100644 lib/kafs/afssysdefs.h delete mode 100644 lib/kafs/common.c delete mode 100644 lib/kafs/kafs.3 delete mode 100644 lib/kafs/kafs.h delete mode 100644 lib/kafs/kafs_locl.h delete mode 100644 lib/kafs/roken_rename.h delete mode 100644 lib/kafs/rxkad_kdf.c delete mode 100644 lib/krb5/crypto-des3.c delete mode 100644 lib/krb5/digest.c delete mode 100644 lib/krb5/krb5_digest.3 delete mode 100644 lib/ntlm/ChangeLog delete mode 100644 lib/ntlm/Makefile.am delete mode 100644 lib/ntlm/NTMakefile delete mode 100644 lib/ntlm/apop.c delete mode 100644 lib/ntlm/digest.c delete mode 100644 lib/ntlm/heim-auth.h delete mode 100644 lib/ntlm/heimntlm.h delete mode 100644 lib/ntlm/libheimntlm-exports.def delete mode 100644 lib/ntlm/libheimntlm-version.rc delete mode 100644 lib/ntlm/ntlm.c delete mode 100644 lib/ntlm/ntlm_err.et delete mode 100644 lib/ntlm/test_commonauth.c delete mode 100644 lib/ntlm/test_ntlm.c delete mode 100644 lib/ntlm/version-script.map delete mode 100644 tests/db/text-dump-0.7 delete mode 100644 tests/db/text-dump-known-ext delete mode 100644 tests/db/text-dump-no-ext delete mode 100644 tests/db/text-dump-unknown-ext delete mode 100644 tests/gss/check-ntlm.in delete mode 100644 tests/gss/ntlm-user-file.txt delete mode 100644 tests/kdc/check-keys.in delete mode 100644 tests/kdc/ntlm-user-file.txt diff --git a/admin/Makefile.am b/admin/Makefile.am index db01c3c77..6d32d0b96 100644 --- a/admin/Makefile.am +++ b/admin/Makefile.am @@ -2,12 +2,14 @@ include $(top_srcdir)/Makefile.am.common -AM_CPPFLAGS += $(INCLUDE_readline) +AM_CPPFLAGS += $(INCLUDE_readline) -I$(srcdir)/../lib/krb5 man_MANS = ktutil.1 bin_PROGRAMS = ktutil +ktutil_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/../lib/krb5 + dist_ktutil_SOURCES = \ add.c \ change.c \ diff --git a/admin/add.c b/admin/add.c index 5f3d58459..fe34957f9 100644 --- a/admin/add.c +++ b/admin/add.c @@ -96,8 +96,8 @@ kt_add(struct add_options *opt, int argc, char **argv) goto out; } if(opt->password_string == NULL && opt->random_flag == 0) { - if(UI_UTIL_read_pw_string(buf, sizeof(buf), "Password: ", - UI_UTIL_FLAG_VERIFY)) { + if(_krb5_UI_UTIL_read_pw_string(buf, sizeof(buf), "Password: ", + UI_UTIL_FLAG_VERIFY)) { ret = 1; goto out; } diff --git a/admin/ktutil_locl.h b/admin/ktutil_locl.h index 9ecee3199..dead37b85 100644 --- a/admin/ktutil_locl.h +++ b/admin/ktutil_locl.h @@ -55,6 +55,7 @@ #include "crypto-headers.h" #include +#include #include #include diff --git a/appl/Makefile.am b/appl/Makefile.am index 227c95b48..7d4abcea4 100644 --- a/appl/Makefile.am +++ b/appl/Makefile.am @@ -5,11 +5,7 @@ include $(top_srcdir)/Makefile.am.common if DCE dir_dce = dceutils endif -if !NO_AFS -dir_afsutil = afsutil -endif SUBDIRS = \ - $(dir_afsutil) \ dbutils \ gssmask \ test \ diff --git a/appl/afsutil/ChangeLog b/appl/afsutil/ChangeLog deleted file mode 100644 index 9825c55a6..000000000 --- a/appl/afsutil/ChangeLog +++ /dev/null @@ -1,125 +0,0 @@ -2007-04-11 Love Hörnquist Åstrand - - * pagsh.1,afslog.1: - options must be lexicographically ordered; - again, options without arguments must be placed before options - with arguments. - manual page cross references are done using - the macro `.Xr', not the macro `.Nm' (used for command names - instead). - - From Igor Sobrado. - -2006-10-07 Love Hörnquist Åstrand - - * Makefile.am: Add man_MANS to EXTRA_DIST - -2006-01-03 Love Hörnquist Åstrand - - * afslog.1: Document options to allow select principal or - credential cache when doing afslog. - - * afslog.c: Add options to allow select principal or credential - cache when doing afslog. - -2005-02-12 Love Hörnquist Åstrand - - * Makefile.am: man_MANS += pagsh.1 - - * pagsh.c: add --cache-type that allows the user to control the - resulting credential cache type, inherit the type from the - invoking process - - * pagsh.1: manpage for pagsh - -2004-09-03 Love Hörnquist Åstrand - - * afslog.c: use negative string help string for arg_negative_flag - Pointed out by Harald Barth - -2004-07-27 Love Hörnquist Åstrand - - * pagsh.c: use setprogname, if we stripped off -c, try use the - fallback code - -2003-10-14 Johan Danielsson - - * pagsh.c: mkstemp formats must end in exactly six X's - -2003-07-15 Love Hörnquist Åstrand - - * afslog.c (do_afslog): is cell is unset, set it "" - for error printing - - * pagsh.c: unconditionally set KRBTKFILE - -2003-04-23 Love Hörnquist Åstrand - - * afslog.c (log_func): drop the error number - -2003-04-14 Love Hörnquist Åstrand - - * afslog.c: set kafs log function if verbose is turned on - -2003-03-18 Love Hörnquist Åstrand - - * Makefile.am (LDADD): use LIB_kafs - - * afslog.1: --no-v4, --no-v5 - - * Makefile.am: always build afsutils now - - * afslog.c: make build without KRB4 - -2002-11-26 Johan Danielsson - - * afslog.c: remove plural form in help string - - * Makefile.am: add afslog manpage - - * afslog.1: manpage - - * afslog.c: try more files when trying to expand a cell name - - * afslog.c: create a list of cells to get tokens for, before - actually doing anything, and try to get tokens via krb4 if krb5 - fails, and give it a chance to work with krb4-only; also some bug - fixes, partially from Tomas Olsson. - -2002-08-23 Assar Westerlund - - * pagsh.c: make it handle --version/--help - -2001-05-17 Assar Westerlund - - * afslog.c (main): call free_getarg_strings - -2000-12-31 Assar Westerlund - - * afslog.c (main): handle krb5_init_context failure consistently - -2000-12-25 Assar Westerlund - - * afslog.c: clarify usage strings - -1999-08-04 Assar Westerlund - - * pagsh.c (main): use mkstemp to generate temporary file names. - From Miroslav Ruda - -1999-07-04 Assar Westerlund - - * afslog.c (expand_cell_name): terminate on #. From Miroslav Ruda - - -1999-06-27 Assar Westerlund - - * Makefile.am (bin_PROGRAMS): only include pagsh if KRB4 - -1999-06-26 Assar Westerlund - - * Makefile.am: add pagsh - - * pagsh.c: new file. contributed by Miroslav Ruda - -Sat Mar 27 12:49:43 1999 Johan Danielsson - - * afslog.c: cleanup option parsing diff --git a/appl/afsutil/Makefile.am b/appl/afsutil/Makefile.am deleted file mode 100644 index 5fbd428e2..000000000 --- a/appl/afsutil/Makefile.am +++ /dev/null @@ -1,18 +0,0 @@ -# $Id$ - -include $(top_srcdir)/Makefile.am.common - -bin_PROGRAMS = afslog pagsh - -afslog_SOURCES = afslog.c - -pagsh_SOURCES = pagsh.c - -man_MANS = afslog.1 pagsh.1 - -LDADD = $(LIB_kafs) \ - $(top_builddir)/lib/krb5/libkrb5.la \ - $(top_builddir)/lib/asn1/libasn1.la \ - $(LIB_roken) - -EXTRA_DIST = NTMakefile $(man_MANS) diff --git a/appl/afsutil/NTMakefile b/appl/afsutil/NTMakefile deleted file mode 100644 index f1f696c02..000000000 --- a/appl/afsutil/NTMakefile +++ /dev/null @@ -1,35 +0,0 @@ -######################################################################## -# -# Copyright (c) 2009, Secure Endpoints Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# - Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# - Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in -# the documentation and/or other materials provided with the -# distribution. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. -# - -RELDIR=appl\afsutil - -!include ../../windows/NTMakefile.w32 - diff --git a/appl/afsutil/afslog.1 b/appl/afsutil/afslog.1 deleted file mode 100644 index 779d9cd50..000000000 --- a/appl/afsutil/afslog.1 +++ /dev/null @@ -1,147 +0,0 @@ -.\" Copyright (c) 2002 - 2007 Kungliga Tekniska Högskolan -.\" (Royal Institute of Technology, Stockholm, Sweden). -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" 3. Neither the name of the Institute nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" $Id$ -.\" -.Dd November 26, 2002 -.Dt AFSLOG 1 -.Os HEIMDAL -.Sh NAME -.Nm afslog -.Nd obtain AFS tokens -.Sh SYNOPSIS -.Nm -.Op Fl h | Fl Fl help -.Op Fl Fl no-v5 -.Op Fl u | Fl Fl unlog -.Op Fl v | Fl Fl verbose -.Op Fl Fl version -.Oo Fl c Ar cell \*(Ba Xo -.Fl Fl cell= Ns Ar cell -.Xc -.Oc -.Oo Fl k Ar realm \*(Ba Xo -.Fl Fl realm= Ns Ar realm -.Xc -.Oc -.Oo Fl P Ar principal \*(Ba Xo -.Fl Fl principal= Ns Ar principal -.Xc -.Oc -.Bk -words -.Oo Fl p Ar path \*(Ba Xo -.Fl Fl file= Ns Ar path -.Xc -.Oc -.Ek -.Op Ar cell | path ... -.Sh DESCRIPTION -.Nm -obtains AFS tokens for a number of cells. What cells to get tokens for -can either be specified as an explicit list, as file paths to get -tokens for, or be left unspecified, in which case -.Nm -will use whatever magic -.Xr krb_afslog 3 -decides upon. -.Pp -Supported options: -.Bl -tag -width Ds -.It Fl Fl no-v5 -This makes -.Nm -not try using Kerberos 5. -.It Xo -.Fl P Ar principal , -.Fl Fl principal Ar principal -.Xc -select what Kerberos 5 principal to use. -.It Fl Fl cache Ar cache -select what Kerberos 5 credential cache to use. -.Fl Fl principal -overrides this option. -.It Xo -.Fl u , -.Fl Fl unlog -.Xc -Destroy tokens instead of obtaining new. If this is specified, all -other options are ignored (except for -.Fl Fl help -and -.Fl Fl version ) . -.It Xo -.Fl v , -.Fl Fl verbose -.Xc -Adds more verbosity for what is actually going on. -.It Xo -.Fl c Ar cell, -.Fl Fl cell= Ns Ar cell -.Xc -This specified one or more cell names to get tokens for. -.It Xo -.Fl k Ar realm , -.Fl Fl realm= Ns Ar realm -.Xc -This is the Kerberos realm the AFS servers live in, this should -normally not be specified. -.It Xo -.Fl p Ar path , -.Fl Fl file= Ns Ar path -.Xc -This specified one or more file paths for which tokens should be -obtained. -.El -.Pp -Instead of using -.Fl c -and -.Fl p , -you may also pass a list of cells and file paths after any other -options. These arguments are considered files if they are either -the strings -.Do . Dc -or -.Dq .. -or they contain a slash, or if there exists a file by that name. -.Sh EXAMPLES -Assuming that there is no file called -.Dq openafs.org -in the current directory, and that -.Pa /afs/openafs.org -points to that cell, the follwing should be identical: -.Bd -literal -offset indent -$ afslog -c openafs.org -$ afslog openafs.org -$ afslog /afs/openafs.org/some/file -.Ed -.Sh SEE ALSO -.Xr krb_afslog 3 diff --git a/appl/afsutil/afslog.c b/appl/afsutil/afslog.c deleted file mode 100644 index 05078ee8e..000000000 --- a/appl/afsutil/afslog.c +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright (c) 1997-2003 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifdef HAVE_CONFIG_H -#include -RCSID("$Id$"); -#endif -#include -#ifdef KRB5 -#include -#endif -#include -#include -#include -#include - -static int help_flag; -static int version_flag; -static getarg_strings cells; -static char *realm; -static getarg_strings files; -static int unlog_flag; -static int verbose; -#ifdef KRB5 -static char *client_string; -static char *cache_string; -static int use_krb5 = 1; -#endif - -struct getargs args[] = { - { "cell", 'c', arg_strings, &cells, "cells to get tokens for", "cell" }, - { "file", 'p', arg_strings, &files, "files to get tokens for", "path" }, - { "realm", 'k', arg_string, &realm, "realm for afs cell", "realm" }, - { "unlog", 'u', arg_flag, &unlog_flag, "remove tokens", NULL }, -#ifdef KRB5 - { "principal",'P',arg_string,&client_string,"principal to use","principal"}, - { "cache", 0, arg_string, &cache_string, "ccache to use", "cache"}, - { "v5", 0, arg_negative_flag, &use_krb5, "don't use Kerberos 5", - NULL }, -#endif - { "verbose",'v', arg_flag, &verbose, NULL, NULL }, - { "version", 0, arg_flag, &version_flag, NULL, NULL }, - { "help", 'h', arg_flag, &help_flag, NULL, NULL }, -}; - -static int num_args = sizeof(args) / sizeof(args[0]); - -#ifdef KRB5 -krb5_context context; -krb5_ccache id; -#endif - -static const char * -expand_one_file(FILE *f, const char *cell) -{ - static char buf[1024]; - char *p; - - while (fgets (buf, sizeof(buf), f) != NULL) { - if(buf[0] == '>') { - for(p = buf; *p && !isspace((unsigned char)*p) && *p != '#'; p++) - ; - *p = '\0'; - if(strncmp(buf + 1, cell, strlen(cell)) == 0) - return buf + 1; - } - buf[0] = '\0'; - } - return NULL; -} - -static const char * -expand_cell_name(const char *cell) -{ - FILE *f; - const char *c; - const char **fn, *fns[] = { _PATH_CELLSERVDB, - _PATH_ARLA_CELLSERVDB, - _PATH_OPENAFS_DEBIAN_CELLSERVDB, - _PATH_ARLA_DEBIAN_CELLSERVDB, - NULL }; - for(fn = fns; *fn; fn++) { - f = fopen(*fn, "r"); - if(f == NULL) - continue; - c = expand_one_file(f, cell); - fclose(f); - if(c) - return c; - } - return NULL; -} - -static void -usage(int ecode) -{ - arg_printusage(args, num_args, NULL, "[cell|path]..."); - exit(ecode); -} - -struct cell_list { - char *cell; - struct cell_list *next; -} *cell_list; - -static int -afslog_cell(const char *cell, int expand) -{ - struct cell_list *p, **q; - const char *c = cell; - if(expand){ - c = expand_cell_name(cell); - if(c == NULL){ - warnx("No cell matching \"%s\" found.", cell); - return -1; - } - if(verbose && strcmp(c, cell) != 0) - warnx("Cell \"%s\" expanded to \"%s\"", cell, c); - } - /* add to list of cells to get tokens for, and also remove - duplicates; the actual afslog takes place later */ - for(p = cell_list, q = &cell_list; p; q = &p->next, p = p->next) - if(strcmp(p->cell, c) == 0) - return 0; - p = malloc(sizeof(*p)); - if(p == NULL) - return -1; - p->cell = strdup(c); - if(p->cell == NULL) { - free(p); - return -1; - } - p->next = NULL; - *q = p; - return 0; -} - -static int -afslog_file(const char *path) -{ - char cell[64]; - if(k_afs_cell_of_file(path, cell, sizeof(cell))){ - warnx("No cell found for file \"%s\".", path); - return -1; - } - if(verbose) - warnx("File \"%s\" lives in cell \"%s\"", path, cell); - return afslog_cell(cell, 0); -} - -static int -do_afslog(const char *cell) -{ - int k5ret; - - k5ret = 0; - -#ifdef KRB5 - if(context != NULL && id != NULL && use_krb5) { - k5ret = krb5_afslog(context, id, cell, realm); - if(k5ret == 0) - return 0; - } -#endif - if (cell == NULL) - cell = ""; -#ifdef KRB5 - if (k5ret) - krb5_warn(context, k5ret, "krb5_afslog(%s)", cell); -#endif - if (k5ret) - return 1; - return 0; -} - -static void -log_func(void *ctx, const char *str) -{ - fprintf(stderr, "%s\n", str); -} - -int -main(int argc, char **argv) -{ - int optidx = 0; - int i; - int num; - int ret = 0; - int failed = 0; - struct cell_list *p; - - setprogname(argv[0]); - - if(getarg(args, num_args, argc, argv, &optidx)) - usage(1); - if(help_flag) - usage(0); - if(version_flag) { - print_version(NULL); - exit(0); - } - - if(!k_hasafs()) - errx(1, "AFS does not seem to be present on this machine"); - - if(unlog_flag){ - k_unlog(); - exit(0); - } -#ifdef KRB5 - ret = krb5_init_context(&context); - if (ret) { - context = NULL; - } else { - if (client_string) { - krb5_principal client; - - ret = krb5_parse_name(context, client_string, &client); - if (ret == 0) - ret = krb5_cc_cache_match(context, client, &id); - if (ret) - id = NULL; - } - if (id == NULL && cache_string) { - if(krb5_cc_resolve(context, cache_string, &id) != 0) { - krb5_warnx(context, "failed to open kerberos 5 cache '%s'", - cache_string); - id = NULL; - } - } - if (id == NULL) - if(krb5_cc_default(context, &id) != 0) - id = NULL; - } -#endif - - if (verbose) - kafs_set_verbose(log_func, NULL); - - num = 0; - for(i = 0; i < files.num_strings; i++){ - afslog_file(files.strings[i]); - num++; - } - free_getarg_strings (&files); - for(i = 0; i < cells.num_strings; i++){ - afslog_cell(cells.strings[i], 1); - num++; - } - free_getarg_strings (&cells); - for(i = optidx; i < argc; i++){ - num++; - if(strcmp(argv[i], ".") == 0 || - strcmp(argv[i], "..") == 0 || - strchr(argv[i], '/') || - access(argv[i], F_OK) == 0) - afslog_file(argv[i]); - else - afslog_cell(argv[i], 1); - } - if(num == 0) { - if(do_afslog(NULL)) - failed++; - } else - for(p = cell_list; p; p = p->next) { - if(verbose) - warnx("Getting tokens for cell \"%s\"", p->cell); - if(do_afslog(p->cell)) - failed++; - } - - return failed; -} diff --git a/appl/afsutil/pagsh.1 b/appl/afsutil/pagsh.1 deleted file mode 100644 index 3c1fd9643..000000000 --- a/appl/afsutil/pagsh.1 +++ /dev/null @@ -1,94 +0,0 @@ -.\" Copyright (c) 2005 Kungliga Tekniska Högskolan -.\" (Royal Institute of Technology, Stockholm, Sweden). -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" 3. Neither the name of the Institute nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" $Id$ -.\" -.Dd February 12, 2005 -.Dt PAGSH 1 -.Os -.Sh NAME -.Nm pagsh -.Nd creates a new credential cache sandbox -.Sh SYNOPSIS -.Nm -.Op Fl c Ar command-string -.Op Fl h | Fl Fl help -.Op Fl Fl version -.Op Fl Fl cache-type= Ns Ar string -.Ar command [args...] -.Sh DESCRIPTION -Supported options: -.Bl -tag -width Ds -.It Xo -.Fl c Ar command-string -Executes command(s) contained in -.Ar command-string . -.Xc -.It Xo -.Fl Fl cache-type= Ns Ar string -.Xc -.It Xo -.Fl h , -.Fl Fl help -.Xc -.It Xo -.Fl Fl version -.Xc -.El -.Pp -.Nm -creates a new credential cache sandbox for the user to live in. -If AFS is installed on the computer, the user is put in a newly -created Process Authentication Group (PAG). -.Pp -For Kerberos 5, the credential cache type that is used is the same as -the credential cache type that was used at the time of -.Nm -invocation. -The credential cache type can be controlled by the option -.Fl Fl cache-type . -.Sh EXAMPLES -Create a new sandbox where new credentials can be used, while the old -credentials can be used by other processes. -.Bd -literal -offset indent -$ klist -Credentials cache: FILE:/tmp/krb5cc_913 - Principal: lha@E.KTH.SE - - Issued Expires Principal -Feb 12 10:08:31 Feb 12 20:06:36 krbtgt/E.KTH.SE@E.KTH.SE -$ pagsh -$ klist -klist: No ticket file: /tmp/krb5cc_03014a -.Ed -.Sh SEE ALSO -.Xr afslog 1 , -.Xr kinit 1 diff --git a/appl/afsutil/pagsh.c b/appl/afsutil/pagsh.c deleted file mode 100644 index 377ac6174..000000000 --- a/appl/afsutil/pagsh.c +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright (c) 1995 - 2005 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -RCSID("$Id$"); - -#include -#include -#include -#include -#ifdef HAVE_SYS_TYPES_H -#include -#endif -#include -#ifdef HAVE_FCNTL_H -#include -#endif -#ifdef HAVE_PWD_H -#include -#endif - -#ifdef KRB5 -#include -#endif -#include - -#include -#include -#include - -#ifndef TKT_ROOT -#define TKT_ROOT "/tmp/tkt" -#endif - -static int help_flag; -static int version_flag; -static int c_flag; -#ifdef KRB5 -static char *typename_arg; -#endif - -struct getargs getargs[] = { - { NULL, 'c', arg_flag, &c_flag, NULL, NULL }, -#ifdef KRB5 - { "cache-type", 0, arg_string, &typename_arg, NULL, NULL }, -#endif - { "version", 0, arg_flag, &version_flag, NULL, NULL }, - { "help", 'h', arg_flag, &help_flag, NULL, NULL }, -}; - -static int num_args = sizeof(getargs) / sizeof(getargs[0]); - -static void -usage(int ecode) -{ - arg_printusage(getargs, num_args, NULL, "command [args...]"); - exit(ecode); -} - -/* - * Run command with a new ticket file / credentials cache / token - */ - -int -main(int argc, char **argv) -{ - int f; - char tf[1024]; - char shellbuf[MAX_PATH]; - char *p; - - char *path; - char **args; - unsigned int i; - int optidx = 0; - - setprogname(argv[0]); - if(getarg(getargs, num_args, argc, argv, &optidx)) - usage(1); - if(help_flag) - usage(0); - if(version_flag) { - print_version(NULL); - exit(0); - } - - argc -= optidx; - argv += optidx; - -#ifdef KRB5 - { - krb5_error_code ret; - krb5_context context; - krb5_ccache id; - const char *name; - - ret = krb5_init_context(&context); - if (ret) /* XXX should this really call exit ? */ - errx(1, "no kerberos 5 support"); - - ret = krb5_cc_new_unique(context, typename_arg, NULL, &id); - if (ret) - krb5_err(context, 1, ret, "Failed generating credential cache"); - - name = krb5_cc_get_name(context, id); - if (name == NULL) - krb5_errx(context, 1, "Generated credential cache have no name"); - - snprintf(tf, sizeof(tf), "%s:%s", krb5_cc_get_type(context, id), name); - - ret = krb5_cc_close(context, id); - if (ret) - krb5_err(context, 1, ret, "Failed closing credential cache"); - - krb5_free_context(context); - - esetenv("KRB5CCNAME", tf, 1); - } -#endif - - snprintf (tf, sizeof(tf), "%s_XXXXXX", TKT_ROOT); - f = mkstemp (tf); - if (f < 0) - err(1, "mkstemp failed"); - close (f); - unlink (tf); - esetenv("KRBTKFILE", tf, 1); - - i = 0; - - args = (char **) malloc((argc + 10)*sizeof(char *)); - if (args == NULL) - errx (1, "Out of memory allocating %lu bytes", - (unsigned long)((argc + 10)*sizeof(char *))); - - if(*argv == NULL) { - if (roken_get_shell(shellbuf, sizeof(shellbuf)) != NULL) - path = strdup(shellbuf); - else - path = strdup("/bin/sh"); - } else { - path = strdup(*argv++); - } - if (path == NULL) - errx (1, "Out of memory copying path"); - - p=strrchr(path, '/'); - if(p) - args[i] = strdup(p+1); - else - args[i] = strdup(path); - - if (args[i++] == NULL) - errx (1, "Out of memory copying arguments"); - - while(*argv) - args[i++] = *argv++; - - args[i++] = NULL; - - if(k_hasafs()) - k_setpag(); - - unsetenv("PAGPID"); - execvp(path, args); - if (errno == ENOENT || c_flag) { - char **sh_args = malloc ((i + 2) * sizeof(char *)); - unsigned int j; - - if (sh_args == NULL) - errx (1, "Out of memory copying sh arguments"); - for (j = 1; j < i; ++j) - sh_args[j + 2] = args[j]; - sh_args[0] = "sh"; - sh_args[1] = "-c"; - sh_args[2] = path; - execv ("/bin/sh", sh_args); - } - err (1, "execvp"); -} diff --git a/appl/test/Makefile.am b/appl/test/Makefile.am index 22b2755b6..2252b7da4 100644 --- a/appl/test/Makefile.am +++ b/appl/test/Makefile.am @@ -54,7 +54,6 @@ kinit_auditdns_LDADD = \ $(top_builddir)/lib/krb5/libkrb5.la \ $(top_builddir)/lib/gssapi/libgssapi.la \ $(top_builddir)/lib/gss_preauth/libgss_preauth.la \ - $(top_builddir)/lib/ntlm/libheimntlm.la \ $(top_builddir)/lib/asn1/libasn1.la \ $(LIB_libintl) \ $(LIB_roken) diff --git a/cf/Makefile.am.common b/cf/Makefile.am.common index 5135239b4..e614c6f49 100644 --- a/cf/Makefile.am.common +++ b/cf/Makefile.am.common @@ -4,7 +4,7 @@ SUFFIXES = .et .h .pc.in .pc DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/include -I$(top_srcdir)/include -AM_CPPFLAGS = $(INCLUDES_roken) +AM_CPPFLAGS = $(INCLUDES_roken) $(INCLUDE_openssl_crypto) if do_roken_rename ROKEN_RENAME = -DROKEN_RENAME diff --git a/cf/crypto.m4 b/cf/crypto.m4 index 4adcead3c..5a6cb01f2 100644 --- a/cf/crypto.m4 +++ b/cf/crypto.m4 @@ -10,6 +10,9 @@ m4_define([test_headers], [ #include #endif #include + #include + #include + #include #include #include #include @@ -140,6 +143,28 @@ if test "$pkcs11_module" != ""; then openssl=no fi +dnl Check for OpenSSL PKCS#11 provider (pkcs11-provider project) +dnl It installs into the OpenSSL modules directory +openssl_pkcs11_provider="" +if test "$openssl" = "yes"; then + if test "$with_openssl_lib" != ""; then + pkcs11_provider_path="${with_openssl_lib}/ossl-modules/pkcs11.so" + elif test "$with_openssl" != "" -a "$with_openssl" != "yes"; then + pkcs11_provider_path="${with_openssl}/lib/ossl-modules/pkcs11.so" + else + pkcs11_provider_path="/usr/lib/ossl-modules/pkcs11.so" + fi + AC_MSG_CHECKING([for OpenSSL PKCS11 provider]) + if test -f "$pkcs11_provider_path"; then + openssl_pkcs11_provider="$pkcs11_provider_path" + AC_MSG_RESULT([$openssl_pkcs11_provider]) + else + AC_MSG_RESULT([not found at $pkcs11_provider_path]) + fi +fi +AC_SUBST(OPENSSL_PKCS11_PROVIDER, [$openssl_pkcs11_provider]) +AM_CONDITIONAL([HAVE_OPENSSL_PKCS11_PROVIDER], [test "x$openssl_pkcs11_provider" != "x"]) + if test "$openssl" != "yes"; then AC_MSG_ERROR([OpenSSL is required]) fi diff --git a/configure.ac b/configure.ac index d7c4bcf35..f807fdda2 100644 --- a/configure.ac +++ b/configure.ac @@ -342,8 +342,14 @@ AC_SUBST(dpagaix_ldadd) AC_SUBST(dpagaix_ldflags) AC_ARG_ENABLE([afs-support], - AS_HELP_STRING([--disable-afs-support],[if you don't want support for AFS])) -if test "$enable_afs_support" = no; then + AS_HELP_STRING([--enable-afs-support],[enable support for AFS]), + [enable_afs_support=yes], + [enable_afs_support=no]) +if test "$enable_afs_support" = yes; then + NO_AFS="0" + AC_MSG_ERROR([AFS no longer supported]) +else + # XXX This is pointless now, should be removed AC_DEFINE(NO_AFS, 1, [Define if you don't wan't support for AFS.]) NO_AFS="1" fi @@ -742,7 +748,6 @@ AC_CONFIG_FILES(Makefile \ lib/hdb/Makefile \ lib/ipc/Makefile \ lib/kadm5/Makefile \ - lib/kafs/Makefile \ lib/kdfs/Makefile \ lib/krb5/Makefile \ lib/roken/Makefile \ @@ -759,7 +764,6 @@ AC_CONFIG_FILES(Makefile \ kcm/Makefile \ kdc/Makefile \ appl/Makefile \ - appl/afsutil/Makefile \ appl/dbutils/Makefile \ appl/gssmask/Makefile \ appl/test/Makefile \ diff --git a/doc/Makefile.am b/doc/Makefile.am index 90ced3099..c16779606 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -43,11 +43,6 @@ krb5.dxy: krb5.din Makefile chmod +x krb5.dxy.tmp mv krb5.dxy.tmp krb5.dxy -ntlm.dxy: ntlm.din Makefile - $(dxy_subst) < $(srcdir)/ntlm.din > ntlm.dxy.tmp - chmod +x ntlm.dxy.tmp - mv ntlm.dxy.tmp ntlm.dxy - wind.dxy: wind.din Makefile $(dxy_subst) < $(srcdir)/wind.din > wind.dxy.tmp chmod +x wind.dxy.tmp @@ -62,9 +57,9 @@ vars.texi: vars.tin Makefile chmod +x vars.texi.tmp mv vars.texi.tmp vars.texi -PROJECTS = base hdb hx509 gssapi krb5 ntlm wind +PROJECTS = base hdb hx509 gssapi krb5 wind -doxyout doxygen: base.dxy hdb.dxy hx509.dxy gssapi.dxy krb5.dxy ntlm.dxy wind.dxy +doxyout doxygen: base.dxy hdb.dxy hx509.dxy gssapi.dxy krb5.dxy wind.dxy @test -d $(srcdir)/doxyout && \ find $(srcdir)/doxyout -type d ! -perm -200 -exec chmod u+w {} ';' ; \ rm -rf $(srcdir)/doxyout ; \ @@ -135,7 +130,6 @@ EXTRA_DIST = \ base.din \ hx509.din \ krb5.din \ - ntlm.din \ init-creds \ latin1.tex \ layman.asc \ @@ -152,6 +146,5 @@ CLEANFILES = \ hdb.dxy* \ gssapi.dxy* \ krb5.dxy* \ - ntlm.dxy* \ wind.dxy* \ vars.texi* diff --git a/doc/ntlm.din b/doc/ntlm.din deleted file mode 100644 index 71dd5ffa0..000000000 --- a/doc/ntlm.din +++ /dev/null @@ -1,16 +0,0 @@ -# Doxyfile 1.5.3 - -PROJECT_NAME = Heimdal ntlm library -PROJECT_NUMBER = @PACKAGE_VERSION@ -OUTPUT_DIRECTORY = @srcdir@/doxyout/ntlm -INPUT = @srcdir@/../lib/ntlm -EXAMPLE_PATH = @srcdir@/../lib/ntlm - -WARN_IF_UNDOCUMENTED = YES - -PERL_PATH = /usr/bin/perl - -HTML_HEADER = "@srcdir@/header.html" -HTML_FOOTER = "@srcdir@/footer.html" - -@INCLUDE = "@srcdir@/doxytmpl.dxy" diff --git a/include/Makefile.am b/include/Makefile.am index 17588db79..bca303a28 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -69,8 +69,6 @@ CLEANFILES = \ heimbase.h \ heimbase-svc.h \ heimbase-protos.h \ - heimntlm-protos.h \ - heimntlm.h \ hex.h \ hx509-private.h \ hx509-protos.h \ @@ -98,7 +96,6 @@ CLEANFILES = \ kx509_err.h \ locate_plugin.h \ login-protos.h \ - ntlm_err.h \ ocsp_asn1.h \ ocsp_template_asn1.h \ parse_bytes.h \ @@ -138,7 +135,6 @@ CLEANFILES = \ gss_preauth_authorizer_plugin.h \ token_validator_plugin.h \ xdbm.h \ - x25519_ref10.h \ x690sample_asn1.h \ x690sample_template_asn1.h diff --git a/include/crypto-headers.h b/include/crypto-headers.h index d38a8a2dd..c389eaccf 100644 --- a/include/crypto-headers.h +++ b/include/crypto-headers.h @@ -21,5 +21,10 @@ #include #include #include +#include +#include +#include +#include +#include #endif /* __crypto_header__ */ diff --git a/include/gssapi/Makefile.am b/include/gssapi/Makefile.am index c0b050864..678f00ee8 100644 --- a/include/gssapi/Makefile.am +++ b/include/gssapi/Makefile.am @@ -2,6 +2,6 @@ include $(top_srcdir)/Makefile.am.common -CLEANFILES = gssapi.h gssapi_krb5.h gssapi_spnego.h gssapi_ntlm.h gssapi_oid.h +CLEANFILES = gssapi.h gssapi_krb5.h gssapi_spnego.h gssapi_oid.h EXTRA_DIST = NTMakefile diff --git a/kadmin/ank.c b/kadmin/ank.c index 0c3781291..8994fb55b 100644 --- a/kadmin/ank.c +++ b/kadmin/ank.c @@ -150,9 +150,9 @@ add_one_principal(const char *name, krb5_set_error_message(context, ret, "out of memory"); goto out; } - ret = UI_UTIL_read_pw_string (pwbuf, sizeof(pwbuf), prompt, - UI_UTIL_FLAG_VERIFY | - UI_UTIL_FLAG_VERIFY_SILENT); + ret = _krb5_UI_UTIL_read_pw_string(pwbuf, sizeof(pwbuf), prompt, + UI_UTIL_FLAG_VERIFY | + UI_UTIL_FLAG_VERIFY_SILENT); free (prompt); if (ret) { ret = KRB5_LIBOS_BADPWDMATCH; diff --git a/kadmin/cpw.c b/kadmin/cpw.c index 180207a46..2c8234175 100644 --- a/kadmin/cpw.c +++ b/kadmin/cpw.c @@ -134,9 +134,9 @@ set_password(void *dup_kadm_handle, free (princ_name); if (aret == -1) return ENOMEM; - ret = UI_UTIL_read_pw_string(pwbuf, sizeof(pwbuf), prompt, - UI_UTIL_FLAG_VERIFY | - UI_UTIL_FLAG_VERIFY_SILENT); + ret = _krb5_UI_UTIL_read_pw_string(pwbuf, sizeof(pwbuf), prompt, + UI_UTIL_FLAG_VERIFY | + UI_UTIL_FLAG_VERIFY_SILENT); free (prompt); if(ret){ return KRB5_LIBOS_BADPWDMATCH; diff --git a/kadmin/kadmin.c b/kadmin/kadmin.c index d37b4917d..88fbd9ada 100644 --- a/kadmin/kadmin.c +++ b/kadmin/kadmin.c @@ -50,6 +50,8 @@ static char *client_name; static char *keytab; static char *check_library = NULL; static char *check_function = NULL; +static char *ossl_cnf = NULL; +static char *ossl_propq = NULL; static getarg_strings policy_libraries = { 0, NULL }; static struct getargs args[] = { @@ -93,6 +95,10 @@ static struct getargs args[] = { #endif { "local", 'l', arg_flag, &local_flag, "local admin mode", NULL }, { "async", 'A', arg_flag, &async_flag, "local admin mode (no fsyncs)", NULL }, + { "ossl-cnf", 0, arg_string, &ossl_cnf, + "OpenSSL configuration file", "FILE" }, + { "ossl-propq", 0, arg_string, &ossl_propq, + "OpenSSL property query string (e.g., provider=pkcs11)", "PROPQ" }, { "help", 'h', arg_flag, &help_flag, NULL, NULL }, { "version", 'v', arg_flag, &version_flag, NULL, NULL } }; @@ -188,6 +194,12 @@ main(int argc, char **argv) argc -= optidx; argv += optidx; + if (ossl_cnf || ossl_propq) { + ret = krb5_set_ossl_cnf_propq(context, ossl_cnf, ossl_propq); + if (ret) + krb5_err(context, 1, ret, "krb5_set_ossl_cnf_propq"); + } + if (config_file == NULL) { aret = asprintf(&config_file, "%s/kdc.conf", hdb_db_dir(context)); if (aret == -1) diff --git a/kadmin/stash.c b/kadmin/stash.c index c33623038..464b9efdd 100644 --- a/kadmin/stash.c +++ b/kadmin/stash.c @@ -99,8 +99,8 @@ stash(struct stash_options *opt, int argc, char **argv) random_password (buf, sizeof(buf)); printf("Using random master stash password: %s\n", buf); } else { - if(UI_UTIL_read_pw_string(buf, sizeof(buf), "Master key: ", - UI_UTIL_FLAG_VERIFY)) { + if(_krb5_UI_UTIL_read_pw_string(buf, sizeof(buf), "Master key: ", + UI_UTIL_FLAG_VERIFY)) { hdb_free_master_key(context, mkey); return 0; } diff --git a/kcm/Makefile.am b/kcm/Makefile.am index 8237f098d..9e033a25a 100644 --- a/kcm/Makefile.am +++ b/kcm/Makefile.am @@ -35,10 +35,10 @@ man_MANS = kcm.8 LDADD = $(top_builddir)/lib/hdb/libhdb.la \ $(top_builddir)/lib/krb5/libkrb5.la \ $(top_builddir)/lib/asn1/libasn1.la \ - $(top_builddir)/lib/ntlm/libheimntlm.la \ $(top_builddir)/lib/ipc/libheim-ipcs.la \ $(LIB_roken) \ $(LIB_door_create) \ + $(LIB_openssl_crypto) \ $(LIB_pidfile) EXTRA_DIST = NTMakefile $(man_MANS) diff --git a/kcm/protocol.c b/kcm/protocol.c index 31f17623d..5dd7dbc3d 100644 --- a/kcm/protocol.c +++ b/kcm/protocol.c @@ -33,7 +33,6 @@ */ #include "kcm_locl.h" -#include static void kcm_drop_default_cache(krb5_context context, kcm_client *client, char *name); @@ -1224,28 +1223,6 @@ kcm_op_set_kdc_offset(krb5_context context, return ret; } -struct kcm_ntlm_cred { - kcmuuid_t uuid; - char *user; - char *domain; - krb5_data nthash; - uid_t uid; - pid_t session; - struct kcm_ntlm_cred *next; -}; - -static struct kcm_ntlm_cred *ntlm_head; - -static void -free_cred(struct kcm_ntlm_cred *cred) -{ - free(cred->user); - free(cred->domain); - krb5_data_free(&cred->nthash); - free(cred); -} - - /* * name * domain @@ -1255,20 +1232,6 @@ free_cred(struct kcm_ntlm_cred *cred) * uuid */ -static struct kcm_ntlm_cred * -find_ntlm_cred(const char *user, const char *domain, kcm_client *client) -{ - struct kcm_ntlm_cred *c; - - for (c = ntlm_head; c != NULL; c = c->next) - if ((user[0] == '\0' || strcmp(user, c->user) == 0) && - (domain == NULL || strcmp(domain, c->domain) == 0) && - kcm_is_same_session(client, c->uid, c->session)) - return c; - - return NULL; -} - static krb5_error_code kcm_op_add_ntlm_cred(krb5_context context, kcm_client *client, @@ -1276,52 +1239,10 @@ kcm_op_add_ntlm_cred(krb5_context context, krb5_storage *request, krb5_storage *response) { - struct kcm_ntlm_cred *cred, *c; - krb5_error_code ret; - - cred = calloc(1, sizeof(*cred)); - if (cred == NULL) - return ENOMEM; - - RAND_bytes(cred->uuid, sizeof(cred->uuid)); - - ret = krb5_ret_stringz(request, &cred->user); - if (ret) - goto error; - - ret = krb5_ret_stringz(request, &cred->domain); - if (ret) - goto error; - - ret = krb5_ret_data(request, &cred->nthash); - if (ret) - goto error; - - /* search for dups */ - c = find_ntlm_cred(cred->user, cred->domain, client); - if (c) { - krb5_data hash = c->nthash; - c->nthash = cred->nthash; - cred->nthash = hash; - free_cred(cred); - cred = c; - } else { - cred->next = ntlm_head; - ntlm_head = cred; - } - - cred->uid = client->uid; - cred->session = client->session; - /* write response */ - (void)krb5_storage_write(response, &cred->uuid, sizeof(cred->uuid)); + (void)krb5_storage_write(response, "not supported", sizeof("not supported")); - return 0; - - error: - free_cred(cred); - - return ret; + return ENOTSUP; } /* @@ -1339,33 +1260,7 @@ kcm_op_have_ntlm_cred(krb5_context context, krb5_storage *request, krb5_storage *response) { - struct kcm_ntlm_cred *c; - char *user = NULL, *domain = NULL; - krb5_error_code ret; - - ret = krb5_ret_stringz(request, &user); - if (ret) - goto error; - - ret = krb5_ret_stringz(request, &domain); - if (ret) - goto error; - - if (domain[0] == '\0') { - free(domain); - domain = NULL; - } - - c = find_ntlm_cred(user, domain, client); - if (c == NULL) - ret = ENOENT; - - error: - free(user); - if (domain) - free(domain); - - return ret; + return ENOTSUP; } /* @@ -1383,35 +1278,7 @@ kcm_op_del_ntlm_cred(krb5_context context, krb5_storage *request, krb5_storage *response) { - struct kcm_ntlm_cred **cp, *c; - char *user = NULL, *domain = NULL; - krb5_error_code ret; - - ret = krb5_ret_stringz(request, &user); - if (ret) - goto error; - - ret = krb5_ret_stringz(request, &domain); - if (ret) - goto error; - - for (cp = &ntlm_head; *cp != NULL; cp = &(*cp)->next) { - if (strcmp(user, (*cp)->user) == 0 && strcmp(domain, (*cp)->domain) == 0 && - kcm_is_same_session(client, (*cp)->uid, (*cp)->session)) - { - c = *cp; - *cp = c->next; - - free_cred(c); - break; - } - } - - error: - free(user); - free(domain); - - return ret; + return ENOTSUP; } /* @@ -1439,218 +1306,7 @@ kcm_op_do_ntlm(krb5_context context, krb5_storage *request, krb5_storage *response) { - struct kcm_ntlm_cred *c; - struct ntlm_type2 type2; - struct ntlm_type3 type3; - char *user = NULL, *domain = NULL; - struct ntlm_buf ndata, sessionkey; - krb5_data data; - krb5_error_code ret; - uint32_t flags = 0; - - memset(&type2, 0, sizeof(type2)); - memset(&type3, 0, sizeof(type3)); - sessionkey.data = NULL; - sessionkey.length = 0; - - ret = krb5_ret_stringz(request, &user); - if (ret) - goto error; - - ret = krb5_ret_stringz(request, &domain); - if (ret) - goto error; - - if (domain[0] == '\0') { - free(domain); - domain = NULL; - } - - c = find_ntlm_cred(user, domain, client); - if (c == NULL) { - ret = EINVAL; - goto error; - } - - ret = krb5_ret_data(request, &data); - if (ret) - goto error; - - ndata.data = data.data; - ndata.length = data.length; - - ret = heim_ntlm_decode_type2(&ndata, &type2); - krb5_data_free(&data); - if (ret) - goto error; - - if (domain && strcmp(domain, type2.targetname) == 0) { - ret = EINVAL; - goto error; - } - - type3.username = c->user; - type3.flags = type2.flags; - type3.targetname = type2.targetname; - type3.ws = rk_UNCONST("workstation"); - - /* - * NTLM Version 1 if no targetinfo buffer. - */ - - if (1 || type2.targetinfo.length == 0) { - struct ntlm_buf tmpsesskey; - - if (type2.flags & NTLM_NEG_NTLM2_SESSION) { - unsigned char nonce[8]; - - if (RAND_bytes(nonce, sizeof(nonce)) != 1) { - ret = EINVAL; - goto error; - } - - ret = heim_ntlm_calculate_ntlm2_sess(nonce, - type2.challenge, - c->nthash.data, - &type3.lm, - &type3.ntlm); - } else { - ret = heim_ntlm_calculate_ntlm1(c->nthash.data, - c->nthash.length, - type2.challenge, - &type3.ntlm); - - } - if (ret) - goto error; - - ret = heim_ntlm_build_ntlm1_master(c->nthash.data, - c->nthash.length, - &tmpsesskey, - &type3.sessionkey); - if (ret) { - if (type3.lm.data) - free(type3.lm.data); - if (type3.ntlm.data) - free(type3.ntlm.data); - goto error; - } - - free(tmpsesskey.data); - flags |= NTLM_FLAG_SESSIONKEY; -#if 0 - } else { - struct ntlm_buf sessionkey; - unsigned char ntlmv2[16]; - struct ntlm_targetinfo ti; - - /* verify infotarget */ - - ret = heim_ntlm_decode_targetinfo(&type2.targetinfo, 1, &ti); - if(ret) { - _gss_ntlm_delete_sec_context(minor_status, - context_handle, NULL); - *minor_status = ret; - return GSS_S_FAILURE; - } - - if (ti.domainname && strcmp(ti.domainname, name->domain) != 0) { - _gss_ntlm_delete_sec_context(minor_status, - context_handle, NULL); - *minor_status = EINVAL; - return GSS_S_FAILURE; - } - - ret = heim_ntlm_calculate_ntlm2(ctx->client->key.data, - ctx->client->key.length, - type3.username, - name->domain, - type2.challenge, - &type2.targetinfo, - ntlmv2, - &type3.ntlm); - if (ret) { - _gss_ntlm_delete_sec_context(minor_status, - context_handle, NULL); - *minor_status = ret; - return GSS_S_FAILURE; - } - - ret = heim_ntlm_build_ntlm1_master(ntlmv2, sizeof(ntlmv2), - &sessionkey, - &type3.sessionkey); - memset(ntlmv2, 0, sizeof(ntlmv2)); - if (ret) { - _gss_ntlm_delete_sec_context(minor_status, - context_handle, NULL); - *minor_status = ret; - return GSS_S_FAILURE; - } - - flags |= NTLM_FLAG_NTLM2_SESSION | - NTLM_FLAG_SESSION; - - if (type3.flags & NTLM_NEG_KEYEX) - flags |= NTLM_FLAG_KEYEX; - - ret = krb5_data_copy(&ctx->sessionkey, - sessionkey.data, sessionkey.length); - free(sessionkey.data); - if (ret) { - _gss_ntlm_delete_sec_context(minor_status, - context_handle, NULL); - *minor_status = ret; - return GSS_S_FAILURE; - } -#endif - } - -#if 0 - if (flags & NTLM_FLAG_NTLM2_SESSION) { - _gss_ntlm_set_key(&ctx->u.v2.send, 0, (ctx->flags & NTLM_NEG_KEYEX), - ctx->sessionkey.data, - ctx->sessionkey.length); - _gss_ntlm_set_key(&ctx->u.v2.recv, 1, (ctx->flags & NTLM_NEG_KEYEX), - ctx->sessionkey.data, - ctx->sessionkey.length); - } else { - flags |= NTLM_FLAG_SESSION; - RC4_set_key(&ctx->u.v1.crypto_recv.key, - ctx->sessionkey.length, - ctx->sessionkey.data); - RC4_set_key(&ctx->u.v1.crypto_send.key, - ctx->sessionkey.length, - ctx->sessionkey.data); - } -#endif - - ret = heim_ntlm_encode_type3(&type3, &ndata, NULL); - if (ret) - goto error; - - data.data = ndata.data; - data.length = ndata.length; - ret = krb5_store_data(response, data); - heim_ntlm_free_buf(&ndata); - if (ret) goto error; - - ret = krb5_store_int32(response, flags); - if (ret) goto error; - - data.data = sessionkey.data; - data.length = sessionkey.length; - - ret = krb5_store_data(response, data); - if (ret) goto error; - - error: - free(type3.username); - heim_ntlm_free_type2(&type2); - free(user); - if (domain) - free(domain); - - return ret; + return ENOTSUP; } @@ -1669,24 +1325,7 @@ kcm_op_get_ntlm_user_list(krb5_context context, krb5_storage *request, krb5_storage *response) { - struct kcm_ntlm_cred *c; - krb5_error_code ret; - - for (c = ntlm_head; c != NULL; c = c->next) { - if (!kcm_is_same_session(client, c->uid, c->session)) - continue; - - ret = krb5_store_uint32(response, 1); - if (ret) - return ret; - ret = krb5_store_stringz(response, c->user); - if (ret) - return ret; - ret = krb5_store_stringz(response, c->domain); - if (ret) - return ret; - } - return krb5_store_uint32(response, 0); + return ENOTSUP; } /* diff --git a/kdc/Makefile.am b/kdc/Makefile.am index e47f638f9..e07438c38 100644 --- a/kdc/Makefile.am +++ b/kdc/Makefile.am @@ -22,7 +22,7 @@ bin_PROGRAMS = string2key sbin_PROGRAMS = kstash -libexec_PROGRAMS = hprop hpropd kdc digest-service \ +libexec_PROGRAMS = hprop hpropd kdc \ test_token_validator test_csr_authorizer test_kdc_ca noinst_PROGRAMS = kdc-replay kdc-tester @@ -45,6 +45,7 @@ bx509d_LDADD = -ldl \ $(MICROHTTPD_LIBS) \ $(LIB_roken) \ $(LIB_heimbase) \ + $(LIB_openssl_crypto) \ $(top_builddir)/lib/sl/libsl.la \ $(top_builddir)/lib/asn1/libasn1.la \ $(top_builddir)/lib/krb5/libkrb5.la \ @@ -62,6 +63,7 @@ httpkadmind_LDADD = -ldl \ $(MICROHTTPD_LIBS) \ $(LIB_roken) \ $(LIB_heimbase) \ + $(LIB_openssl_crypto) \ $(top_builddir)/lib/sl/libsl.la \ $(top_builddir)/lib/asn1/libasn1.la \ $(top_builddir)/lib/krb5/libkrb5.la \ @@ -70,9 +72,6 @@ httpkadmind_LDADD = -ldl \ libexec_PROGRAMS += httpkadmind endif -digest_service_SOURCES = \ - digest-service.c - kdc_SOURCES = connect.c \ config.c \ announce.c \ @@ -118,13 +117,11 @@ libkdc_la_SOURCES = \ default_config.c \ ca.c \ set_dbinfo.c \ - digest.c \ fast.c \ kdc_locl.h \ kerberos5.c \ krb5tgs.c \ pkinit.c \ - pkinit-ec.c \ mssfu.c \ log.c \ misc.c \ @@ -148,7 +145,6 @@ ALL_OBJECTS += $(string2key_OBJECTS) ALL_OBJECTS += $(kstash_OBJECTS) ALL_OBJECTS += $(hprop_OBJECTS) ALL_OBJECTS += $(hpropd_OBJECTS) -ALL_OBJECTS += $(digest_service_OBJECTS) ALL_OBJECTS += $(bx509d_OBJECTS) ALL_OBJECTS += $(httpkadmind_OBJECTS) ALL_OBJECTS += $(cjwt_token_validator_la_OBJECTS) @@ -202,7 +198,6 @@ libkdc_la_LIBADD = \ $(top_builddir)/lib/gssapi/libgssapi.la \ $(top_builddir)/lib/gss_preauth/libgss_preauth.la \ $(LIB_kdb) \ - $(top_builddir)/lib/ntlm/libheimntlm.la \ $(LIB_openssl_crypto) \ $(top_builddir)/lib/asn1/libasn1.la \ $(LIB_roken) \ @@ -221,11 +216,6 @@ kdc_LDFLAGS = -framework SystemConfiguration -framework CoreFoundation endif kdc_CFLAGS = $(CAPNG_CFLAGS) -digest_service_LDADD = \ - libkdc.la \ - $(top_builddir)/lib/ntlm/libheimntlm.la \ - $(top_builddir)/lib/ipc/libheim-ipcs.la \ - $(LDADD) $(LIB_pidfile) 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) diff --git a/kdc/NTMakefile b/kdc/NTMakefile index aca65b104..696495cb8 100644 --- a/kdc/NTMakefile +++ b/kdc/NTMakefile @@ -42,8 +42,7 @@ SBINPROGRAMS=$(SBINDIR)\kstash.exe LIBEXECPROGRAMS= \ $(LIBEXECDIR)\hprop.exe \ $(LIBEXECDIR)\hpropd.exe \ - $(LIBEXECDIR)\kdc.exe \ -# $(LIBEXECDIR)\digest-service.exe + $(LIBEXECDIR)\kdc.exe NOINST_PROGRAMS=$(OBJ)\kdc-replay.exe @@ -83,10 +82,6 @@ $(BINDIR)\string2key.exe: $(OBJ)\string2key.obj $(BIN_LIBS) $(OBJ)\string2key-ve $(EXECONLINK) $(EXEPREP) -$(BINDIR)\digest-service.exe: $(OBJ)\digest-service.obj $(BIN_LIBS) - $(EXECONLINK) - $(EXEPREP) - $(LIBEXECDIR)\kdc.exe: \ $(OBJ)\connect.obj $(OBJ)\config.obj $(OBJ)\announce.obj \ $(OBJ)\main.obj $(OBJ)\kdc-version.res \ @@ -99,13 +94,11 @@ LIBKDC_OBJS=\ $(OBJ)\ca.obj \ $(OBJ)\kx509.obj \ $(OBJ)\set_dbinfo.obj \ - $(OBJ)\digest.obj \ $(OBJ)\fast.obj \ $(OBJ)\kerberos5.obj \ $(OBJ)\krb5tgs.obj \ $(OBJ)\pkinit.obj \ - $(OBJ)\pkinit-ec.obj \ - $(OBJ)\mssfu.obj \ + $(OBJ)\mssfu.obj \ $(OBJ)\log.obj \ $(OBJ)\misc.obj \ $(OBJ)\kx509.obj \ @@ -121,7 +114,6 @@ LIBKDC_LIBS=\ $(LIBGSSAPI) \ $(LIBHEIMBASE) \ $(LIBHEIMDAL) \ - $(LIBHEIMNTLM) \ $(LIB_openssl_crypto) \ $(LIBROKEN) @@ -140,13 +132,11 @@ libkdc_la_SOURCES = \ default_config.c \ ca.c \ set_dbinfo.c \ - digest.c \ fast.c \ kdc_locl.h \ kerberos5.c \ krb5tgs.c \ pkinit.c \ - pkinit-ec.c \ mssfu.c \ log.c \ misc.c \ diff --git a/kdc/bx509d.c b/kdc/bx509d.c index 793012baf..d9a3c1164 100644 --- a/kdc/bx509d.c +++ b/kdc/bx509d.c @@ -293,8 +293,12 @@ static const char *priv_key_file; static const char *cache_dir; static const char *csrf_key_file; static char *impersonation_key_fn; +static const char *impersonation_key_type; +static int impersonation_key_bits; +static const char *ossl_cnf; +static const char *ossl_propq; -static char csrf_key[16]; +static unsigned char csrf_key[16]; static krb5_error_code resp(struct bx509_request_desc *, int, enum MHD_ResponseMemoryMode, const char *, @@ -382,20 +386,37 @@ generate_key(hx509_context context, hx509_private_key key = NULL; hx509_certs certs = NULL; hx509_cert cert = NULL; + const heim_oid *key_oid; int ret; - if (strcmp(gen_type, "rsa") != 0) - errx(1, "Only RSA keys are supported at this time"); + /* Map key type string to OID */ + if (gen_type == NULL || strcasecmp(gen_type, "rsa") == 0) { + key_oid = ASN1_OID_ID_PKCS1_RSAENCRYPTION; + if (gen_bits == 0) + gen_bits = 2048; + } else if (strcasecmp(gen_type, "ec") == 0 || + strcasecmp(gen_type, "ecdsa") == 0) { + key_oid = ASN1_OID_ID_ECPUBLICKEY; + if (gen_bits == 0) + gen_bits = 256; /* P-256 by default */ + } else if (strcasecmp(gen_type, "ed25519") == 0) { + key_oid = ASN1_OID_ID_ED25519; + gen_bits = 0; /* Ed25519 has fixed size */ + } else if (strcasecmp(gen_type, "ed448") == 0) { + key_oid = ASN1_OID_ID_ED448; + gen_bits = 0; /* Ed448 has fixed size */ + } else { + errx(1, "Unsupported key type: %s (supported: rsa, ec, ed25519, ed448)", + gen_type); + } if (asprintf(fn, "PEM-FILE:%s/.%s_priv_key.pem", cache_dir, key_name) == -1 || *fn == NULL) err(1, "Could not set up private key for %s", key_name); - ret = _hx509_generate_private_key_init(context, - ASN1_OID_ID_PKCS1_RSAENCRYPTION, - &key_gen_ctx); - if (ret == 0) + ret = _hx509_generate_private_key_init(context, key_oid, &key_gen_ctx); + if (ret == 0 && gen_bits > 0) ret = _hx509_generate_private_key_bits(context, key_gen_ctx, gen_bits); if (ret == 0) ret = _hx509_generate_private_key(context, key_gen_ctx, &key); @@ -2333,35 +2354,31 @@ mac_csrf_token(struct bx509_request_desc *r, krb5_storage *sp) { krb5_error_code ret; krb5_data data; - char mac[EVP_MAX_MD_SIZE]; - unsigned int maclen = sizeof(mac); - HMAC_CTX *ctx = NULL; + unsigned char mac[EVP_MAX_MD_SIZE]; + size_t maclen = sizeof(mac); + EVP_MAC_CTX *ctx = NULL; ret = krb5_storage_to_data(sp, &data); - if (ret == 0 && (ctx = HMAC_CTX_new()) == NULL) - ret = krb5_enomem(r->context); + if (ret == 0) + ret = _krb5_hmac_start_ossl(r->context, csrf_key, sizeof(csrf_key), + EVP_sha256(), &ctx); + if (ret == ENOMEM) + ret = krb5_enomem(r->context); /* HMAC the token body and the client principal name */ - if (ret == 0) { - if (HMAC_Init_ex(ctx, csrf_key, sizeof(csrf_key), - EVP_sha256(), - NULL) == 0) { - HMAC_CTX_cleanup(ctx); - ret = krb5_enomem(r->context); - } else { - HMAC_Update(ctx, data.data, data.length); - if (r->cname) - HMAC_Update(ctx, r->cname, strlen(r->cname)); - HMAC_Final(ctx, mac, &maclen); - HMAC_CTX_cleanup(ctx); - krb5_data_free(&data); - data.length = maclen; - data.data = mac; - if (krb5_storage_write(sp, mac, maclen) != maclen) - ret = krb5_enomem(r->context); - } - } - if (ctx) - HMAC_CTX_free(ctx); + if (ret == 0) + ret = (EVP_MAC_update(ctx, data.data, data.length) == 1) ? 0 : EINVAL; + if (ret == 0 && r->cname) + ret = (EVP_MAC_update(ctx, + (unsigned char *)r->cname, + strlen(r->cname)) == 1) ? 0 : EINVAL; + if (ret == 0) + ret = (EVP_MAC_final(ctx, mac, &maclen, maclen) == 1) ? 0 : EINVAL; + EVP_MAC_CTX_free(ctx); + krb5_data_free(&data); + data.length = maclen; + data.data = mac; + if (krb5_storage_write(sp, mac, maclen) != maclen) + ret = krb5_enomem(r->context); return ret; } @@ -2742,6 +2759,14 @@ static struct getargs args[] = { "private key file path (PEM)", "HX509-STORE" }, { "thread-per-client", 't', arg_flag, &thread_per_client_flag, "thread per-client", "use thread per-client" }, + { "impersonation-key-type", 0, arg_string, &impersonation_key_type, + "impersonation key type (rsa, ec, ed25519, ed448)", "TYPE" }, + { "impersonation-key-bits", 0, arg_integer, &impersonation_key_bits, + "impersonation key size/curve (default: 2048 for RSA, 256 for EC)", "BITS" }, + { "ossl-cnf", 0, arg_string, &ossl_cnf, + "OpenSSL configuration file", "FILE" }, + { "ossl-propq", 0, arg_string, &ossl_propq, + "OpenSSL property query string (e.g., provider=pkcs11)", "PROPQ" }, { "verbose", 'v', arg_counter, &verbose_counter, "verbose", "run verbosely" } }; @@ -2921,6 +2946,12 @@ main(int argc, char **argv) if ((errno = get_krb5_context(&context))) err(1, "Could not init krb5 context"); + if (ossl_cnf || ossl_propq) { + ret = krb5_set_ossl_cnf_propq(context, ossl_cnf, ossl_propq); + if (ret) + krb5_err(context, 1, ret, "krb5_set_ossl_cnf_propq"); + } + bx509_openlog(context, "bx509d", &logfac); krb5_set_log_dest(context, logfac); load_plugins(context); @@ -2986,7 +3017,27 @@ main(int argc, char **argv) setenv("TMPDIR", cache_dir, 1); } - generate_key(context->hx509ctx, "impersonation", "rsa", 2048, &impersonation_key_fn); + /* + * Get impersonation key configuration from command line or krb5.conf. + * Supported key types: rsa, ec (ecdsa), ed25519, ed448 + * For RSA: bits is key size (default 2048) + * For EC: bits is curve size (256=P-256, 384=P-384, 521=P-521, default 256) + * For EdDSA: bits is ignored + */ + if (impersonation_key_type == NULL) + impersonation_key_type = krb5_config_get_string(context, NULL, "bx509d", + "impersonation_key_type", + NULL); + if (impersonation_key_bits == 0) + impersonation_key_bits = krb5_config_get_int_default(context, NULL, 0, + "bx509d", + "impersonation_key_bits", + NULL); + + generate_key(context->hx509ctx, "impersonation", + impersonation_key_type, + (unsigned long)impersonation_key_bits, + &impersonation_key_fn); again: if (cert_file && !priv_key_file) diff --git a/kdc/config.c b/kdc/config.c index 9fd368686..9180714eb 100644 --- a/kdc/config.c +++ b/kdc/config.c @@ -77,6 +77,8 @@ static struct getarg_strings addresses_str; /* addresses to listen on */ char *runas_string; char *chroot_string; +static char *ossl_cnf; +static char *ossl_propq; static struct getargs args[] = { @@ -123,6 +125,12 @@ static struct getargs args[] = { { "chroot", 0, arg_string, &chroot_string, "chroot directory to run in", NULL }, + { "ossl-cnf", 0, arg_string, &ossl_cnf, + "OpenSSL configuration file", "FILE" + }, + { "ossl-propq", 0, arg_string, &ossl_propq, + "OpenSSL property query string (e.g., provider=pkcs11)", "PROPQ" + }, { "testing", 0, arg_flag, &testing_flag, NULL, NULL }, { "help", 'h', arg_flag, &help_flag, NULL, NULL }, { "version", 'v', arg_flag, &version_flag, NULL, NULL } @@ -184,6 +192,12 @@ configure(krb5_context context, int argc, char **argv, int *optidx) exit(0); } + if (ossl_cnf || ossl_propq) { + ret = krb5_set_ossl_cnf_propq(context, ossl_cnf, ossl_propq); + if (ret) + krb5_err(context, 1, ret, "krb5_set_ossl_cnf_propq"); + } + if(detach_from_console == -1) detach_from_console = krb5_config_get_bool_default(context, NULL, FALSE, diff --git a/kdc/default_config.c b/kdc/default_config.c index dd6aee71b..eddf6cd0a 100644 --- a/kdc/default_config.c +++ b/kdc/default_config.c @@ -113,7 +113,7 @@ krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config) c->pkinit_max_life_bound = 0; c->synthetic_clients_max_life = 300; c->synthetic_clients_max_renew = 300; - c->pkinit_dh_min_bits = 1024; + c->pkinit_dh_min_bits = 2048; c->db = NULL; c->num_db = 0; c->logf = NULL; @@ -126,33 +126,6 @@ krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config) krb5_config_get_bool_default(context, NULL, c->require_preauth, "kdc", "require-preauth", NULL); -#ifdef DIGEST - c->enable_digest = - krb5_config_get_bool_default(context, NULL, - FALSE, - "kdc", "enable-digest", NULL); - - { - const char *digests; - - digests = krb5_config_get_string(context, NULL, - "kdc", - "digests_allowed", NULL); - if (digests == NULL) - digests = "ntlm-v2"; - c->digests_allowed = parse_flags(digests,_kdc_digestunits, 0); - if (c->digests_allowed == -1) { - kdc_log(context, c, 0, - "unparsable digest units (%s), turning off digest", - digests); - c->enable_digest = 0; - } else if (c->digests_allowed == 0) { - kdc_log(context, c, 0, "no digest enable, turning digest off"); - c->enable_digest = 0; - } - } -#endif - #ifdef KX509 c->enable_kx509 = krb5_config_get_bool_default(context, NULL, diff --git a/kdc/digest-service.c b/kdc/digest-service.c deleted file mode 100644 index 1ed6305fd..000000000 --- a/kdc/digest-service.c +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Portions Copyright (c) 2009 Apple Inc. 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 "headers.h" -#include -#include -#include -#include - -typedef struct pk_client_params pk_client_params; -typedef struct gss_client_params gss_client_params; -struct DigestREQ; -struct Kx509Request; - -#include - -krb5_kdc_configuration *config; - -static void -ntlm_service(void *ctx, const heim_idata *req, - const heim_icred cred, - heim_ipc_complete complete, - heim_sipc_call cctx) -{ - NTLMRequest2 ntq; - unsigned char sessionkey[16]; - heim_idata rep = { 0, NULL }; - krb5_context context = ctx; - hdb_entry *user = NULL; - HDB *db = NULL; - Key *key = NULL; - NTLMReply ntp; - size_t size; - int ret; - const char *domain; - - kdc_log(context, config, 4, "digest-request: uid=%d", - (int)heim_ipc_cred_get_uid(cred)); - - if (heim_ipc_cred_get_uid(cred) != 0) { - (*complete)(cctx, EPERM, NULL); - return; - } - - ntp.success = 0; - ntp.flags = 0; - ntp.sessionkey = NULL; - - ret = decode_NTLMRequest2(req->data, req->length, &ntq, NULL); - if (ret) - goto failed; - - /* XXX forward to NetrLogonSamLogonEx() if not a local domain */ - if (strcmp(ntq.loginDomainName, "BUILTIN") == 0) { - domain = ntq.loginDomainName; - } else if (strcmp(ntq.loginDomainName, "") == 0) { - domain = "BUILTIN"; - } else { - ret = EINVAL; - goto failed; - } - - kdc_log(context, config, 4, "digest-request: user=%s/%s", - ntq.loginUserName, domain); - - if (ntq.lmchallenge.length != 8) - goto failed; - - if (ntq.ntChallengeResponce.length == 0) - goto failed; - - { - krb5_principal client; - - ret = krb5_make_principal(context, &client, domain, - ntq.loginUserName, NULL); - if (ret) - goto failed; - - krb5_principal_set_type(context, client, KRB5_NT_NTLM); - - ret = _kdc_db_fetch(context, config, client, - HDB_F_GET_CLIENT, NULL, &db, &user); - krb5_free_principal(context, client); - if (ret) - goto failed; - - ret = hdb_enctype2key(context, user, NULL, - ETYPE_ARCFOUR_HMAC_MD5, &key); - if (ret) { - krb5_set_error_message(context, ret, "NTLM missing arcfour key"); - goto failed; - } - } - - kdc_log(context, config, 5, - "digest-request: found user, processing ntlm request"); - - if (ntq.ntChallengeResponce.length != 24) { - struct ntlm_buf infotarget, answer; - - answer.length = ntq.ntChallengeResponce.length; - answer.data = ntq.ntChallengeResponce.data; - - ret = heim_ntlm_verify_ntlm2(key->key.keyvalue.data, - key->key.keyvalue.length, - ntq.loginUserName, - ntq.loginDomainName, - 0, - ntq.lmchallenge.data, - &answer, - &infotarget, - sessionkey); - if (ret) { - goto failed; - } - - free(infotarget.data); - /* XXX verify info target */ - - } else { - struct ntlm_buf answer; - - if (ntq.flags & NTLM_NEG_NTLM2_SESSION) { - unsigned char sessionhash[MD5_DIGEST_LENGTH]; - EVP_MD_CTX *md5ctx; - - /* the first first 8 bytes is the challenge, what is the other 16 bytes ? */ - if (ntq.lmChallengeResponce.length != 24) - goto failed; - - md5ctx = EVP_MD_CTX_create(); - EVP_DigestInit_ex(md5ctx, EVP_md5(), NULL); - EVP_DigestUpdate(md5ctx, ntq.lmchallenge.data, 8); - EVP_DigestUpdate(md5ctx, ntq.lmChallengeResponce.data, 8); - EVP_DigestFinal_ex(md5ctx, sessionhash, NULL); - EVP_MD_CTX_destroy(md5ctx); - memcpy(ntq.lmchallenge.data, sessionhash, ntq.lmchallenge.length); - } - - ret = heim_ntlm_calculate_ntlm1(key->key.keyvalue.data, - key->key.keyvalue.length, - ntq.lmchallenge.data, &answer); - if (ret) - goto failed; - - if (ntq.ntChallengeResponce.length != answer.length || - ct_memcmp(ntq.ntChallengeResponce.data, answer.data, answer.length) != 0) { - free(answer.data); - ret = EINVAL; - goto failed; - } - free(answer.data); - - { - EVP_MD_CTX *ctxp; - - ctxp = EVP_MD_CTX_create(); - EVP_DigestInit_ex(ctxp, EVP_md4(), NULL); - EVP_DigestUpdate(ctxp, key->key.keyvalue.data, key->key.keyvalue.length); - EVP_DigestFinal_ex(ctxp, sessionkey, NULL); - EVP_MD_CTX_destroy(ctxp); - } - } - - ntp.success = 1; - - ASN1_MALLOC_ENCODE(NTLMReply, rep.data, rep.length, &ntp, &size, ret); - if (ret) - goto failed; - if (rep.length != size) - abort(); - - failed: - kdc_log(context, config, 4, "digest-request: %d", ret); - - (*complete)(cctx, ret, &rep); - - free(rep.data); - - free_NTLMRequest2(&ntq); - if (user) - _kdc_free_ent (context, db, user); -} - -static int help_flag; -static int version_flag; - -static struct getargs args[] = { - { "help", 'h', arg_flag, &help_flag, NULL, NULL }, - { "version", 'v', arg_flag, &version_flag, NULL, NULL } -}; - -static int num_args = sizeof(args) / sizeof(args[0]); - -static void -usage(int ret) -{ - arg_printusage (args, num_args, NULL, ""); - exit (ret); -} - -int -main(int argc, char **argv) -{ - krb5_context context; - int ret, optidx = 0; - - setprogname(argv[0]); - - if (getarg(args, num_args, argc, argv, &optidx)) - usage(1); - - if (help_flag) - usage(0); - - if (version_flag) { - print_version(NULL); - exit(0); - } - - ret = krb5_init_context(&context); - if (ret) - krb5_errx(context, 1, "krb5_init_context"); - - ret = krb5_kdc_get_config(context, &config); - if (ret) - krb5_err(context, 1, ret, "krb5_kdc_default_config"); - - kdc_openlog(context, "digest-service", config); - - ret = krb5_kdc_set_dbinfo(context, config); - if (ret) - krb5_err(context, 1, ret, "krb5_kdc_set_dbinfo"); - -#if __APPLE__ - { - heim_sipc mach; - heim_sipc_launchd_mach_init("org.h5l.ntlm-service", - ntlm_service, context, &mach); - heim_sipc_timeout(60); - } -#endif -#ifdef HAVE_DOOR_CREATE - { - heim_sipc door; - heim_sipc_service_door("org.h5l.ntlm-service", ntlm_service, NULL, &door); - } -#endif - { - heim_sipc un; - heim_sipc_service_unix("org.h5l.ntlm-service", ntlm_service, NULL, &un); - } - - heim_ipc_main(); - return 0; -} diff --git a/kdc/digest.c b/kdc/digest.c deleted file mode 100644 index 3285aaa54..000000000 --- a/kdc/digest.c +++ /dev/null @@ -1,1520 +0,0 @@ -/* - * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "kdc_locl.h" -#include - -#ifdef DIGEST - -#define MS_CHAP_V2 0x20 -#define CHAP_MD5 0x10 -#define DIGEST_MD5 0x08 -#define NTLM_V2 0x04 -#define NTLM_V1_SESSION 0x02 -#define NTLM_V1 0x01 - -const struct units _kdc_digestunits[] = { - {"ms-chap-v2", 1U << 5}, - {"chap-md5", 1U << 4}, - {"digest-md5", 1U << 3}, - {"ntlm-v2", 1U << 2}, - {"ntlm-v1-session", 1U << 1}, - {"ntlm-v1", 1U << 0}, - {NULL, 0} -}; - - -static krb5_error_code -get_digest_key(krb5_context context, - krb5_kdc_configuration *config, - hdb_entry *server, - krb5_crypto *crypto) -{ - krb5_error_code ret; - krb5_enctype enctype; - Key *key; - - ret = _kdc_get_preferred_key(context, - config, - server, - "digest-service", - &enctype, - &key); - if (ret) - return ret; - return krb5_crypto_init(context, &key->key, 0, crypto); -} - -/* - * - */ - -static char * -get_ntlm_targetname(krb5_context context, - hdb_entry *client) -{ - char *targetname, *p; - - targetname = strdup(krb5_principal_get_realm(context, - client->principal)); - if (targetname == NULL) - return NULL; - - p = strchr(targetname, '.'); - if (p) - *p = '\0'; - - strupr(targetname); - return targetname; -} - -static krb5_error_code -fill_targetinfo(krb5_context context, - char *targetname, - hdb_entry *client, - krb5_data *data) -{ - struct ntlm_targetinfo ti; - krb5_error_code ret; - struct ntlm_buf d; - krb5_principal p; - const char *str; - - memset(&ti, 0, sizeof(ti)); - - ti.domainname = targetname; - p = client->principal; - str = krb5_principal_get_comp_string(context, p, 0); - if (str != NULL && - (strcmp("host", str) == 0 || - strcmp("ftp", str) == 0 || - strcmp("imap", str) == 0 || - strcmp("pop", str) == 0 || - strcmp("smtp", str))) - { - str = krb5_principal_get_comp_string(context, p, 1); - ti.dnsservername = rk_UNCONST(str); - } - - ret = heim_ntlm_encode_targetinfo(&ti, 1, &d); - if (ret) - return ret; - - data->data = d.data; - data->length = d.length; - - return 0; -} - - -static const unsigned char ms_chap_v2_magic1[39] = { - 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65, - 0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67, - 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74 -}; -static const unsigned char ms_chap_v2_magic2[41] = { - 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B, - 0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F, - 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E, - 0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F, - 0x6E -}; -static const unsigned char ms_rfc3079_magic1[27] = { - 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d, - 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79 -}; - -/* - * - */ - -static krb5_error_code -get_password_entry(krb5_context context, - krb5_kdc_configuration *config, - const char *username, - char **password) -{ - krb5_principal clientprincipal; - krb5_error_code ret; - hdb_entry *user; - HDB *db; - - /* get username */ - ret = krb5_parse_name(context, username, &clientprincipal); - if (ret) - return ret; - - ret = _kdc_db_fetch(context, config, clientprincipal, - HDB_F_GET_CLIENT, NULL, &db, &user); - krb5_free_principal(context, clientprincipal); - if (ret) - return ret; - - ret = hdb_entry_get_password(context, db, user, password); - if (ret || password == NULL) { - if (ret == 0) { - ret = EINVAL; - krb5_set_error_message(context, ret, "password missing"); - } - memset(user, 0, sizeof(*user)); - } - _kdc_free_ent (context, db, user); - return ret; -} - -/* - * - */ - -krb5_error_code -_kdc_do_digest(krb5_context context, - krb5_kdc_configuration *config, - const struct DigestREQ *req, krb5_data *reply, - const char *from, struct sockaddr *addr) -{ - krb5_error_code ret = 0; - krb5_ticket *ticket = NULL; - krb5_auth_context ac = NULL; - krb5_keytab id = NULL; - krb5_crypto crypto = NULL; - DigestReqInner ireq; - DigestRepInner r; - DigestREP rep; - krb5_flags ap_req_options; - krb5_data buf; - size_t size; - krb5_storage *sp = NULL; - Checksum res; - HDB *serverdb, *userdb; - hdb_entry *server = NULL, *user = NULL; - HDB *clientdb; - hdb_entry *client = NULL; - char *client_name = NULL, *password = NULL; - krb5_data serverNonce; - - if(!config->enable_digest) { - kdc_log(context, config, 2, - "Rejected digest request (disabled) from %s", from); - return KRB5KDC_ERR_POLICY; - } - - krb5_data_zero(&buf); - krb5_data_zero(reply); - krb5_data_zero(&serverNonce); - memset(&ireq, 0, sizeof(ireq)); - memset(&r, 0, sizeof(r)); - memset(&rep, 0, sizeof(rep)); - memset(&res, 0, sizeof(res)); - - kdc_log(context, config, 3, "Digest request from %s", from); - - ret = krb5_kt_resolve(context, "HDBGET:", &id); - if (ret) { - kdc_log(context, config, 0, "Can't open database for digest"); - goto out; - } - - ret = krb5_rd_req(context, - &ac, - &req->apReq, - NULL, - id, - &ap_req_options, - &ticket); - if (ret) - goto out; - - /* check the server principal in the ticket matches digest/R@R */ - { - krb5_principal principal = NULL; - const char *p, *rr; - - ret = krb5_ticket_get_server(context, ticket, &principal); - if (ret) - goto out; - - ret = EINVAL; - krb5_set_error_message(context, ret, "Wrong digest server principal used"); - p = krb5_principal_get_comp_string(context, principal, 0); - if (p == NULL) { - krb5_free_principal(context, principal); - goto out; - } - if (strcmp(p, KRB5_DIGEST_NAME) != 0) { - krb5_free_principal(context, principal); - goto out; - } - - p = krb5_principal_get_comp_string(context, principal, 1); - if (p == NULL) { - krb5_free_principal(context, principal); - goto out; - } - rr = krb5_principal_get_realm(context, principal); - if (rr == NULL) { - krb5_free_principal(context, principal); - goto out; - } - if (strcmp(p, rr) != 0) { - krb5_free_principal(context, principal); - goto out; - } - krb5_clear_error_message(context); - - ret = _kdc_db_fetch(context, config, principal, - HDB_F_GET_SERVER, NULL, &serverdb, &server); - if (ret) - goto out; - - krb5_free_principal(context, principal); - } - - /* check the client is allowed to do digest auth */ - { - krb5_principal principal = NULL; - - ret = krb5_ticket_get_client(context, ticket, &principal); - if (ret) - goto out; - - ret = krb5_unparse_name(context, principal, &client_name); - if (ret) { - krb5_free_principal(context, principal); - goto out; - } - - ret = _kdc_db_fetch(context, config, principal, - HDB_F_GET_CLIENT, NULL, &clientdb, &client); - krb5_free_principal(context, principal); - if (ret) - goto out; - - if (client->flags.allow_digest == 0) { - kdc_log(context, config, 2, - "Client %s tried to use digest " - "but is not allowed to", - client_name); - ret = KRB5KDC_ERR_POLICY; - krb5_set_error_message(context, ret, - "Client is not permitted to use digest"); - goto out; - } - } - - /* unpack request */ - { - krb5_keyblock *key; - - ret = krb5_auth_con_getremotesubkey(context, ac, &key); - if (ret) - goto out; - if (key == NULL) { - ret = EINVAL; - krb5_set_error_message(context, ret, "digest: remote subkey not found"); - goto out; - } - - ret = krb5_crypto_init(context, key, 0, &crypto); - krb5_free_keyblock (context, key); - if (ret) - goto out; - } - - ret = krb5_decrypt_EncryptedData(context, crypto, KRB5_KU_DIGEST_ENCRYPT, - &req->innerReq, &buf); - krb5_crypto_destroy(context, crypto); - crypto = NULL; - if (ret) - goto out; - - ret = decode_DigestReqInner(buf.data, buf.length, &ireq, NULL); - krb5_data_free(&buf); - if (ret) { - krb5_set_error_message(context, ret, "Failed to decode digest inner request"); - goto out; - } - - kdc_log(context, config, 3, "Valid digest request from %s (%s)", - client_name, from); - - /* - * Process the inner request - */ - - switch (ireq.element) { - case choice_DigestReqInner_init: { - unsigned char server_nonce[16], identifier; - - RAND_pseudo_bytes(&identifier, sizeof(identifier)); - RAND_pseudo_bytes(server_nonce, sizeof(server_nonce)); - - server_nonce[0] = kdc_time & 0xff; - server_nonce[1] = (kdc_time >> 8) & 0xff; - server_nonce[2] = (kdc_time >> 16) & 0xff; - server_nonce[3] = (kdc_time >> 24) & 0xff; - - r.element = choice_DigestRepInner_initReply; - - hex_encode(server_nonce, sizeof(server_nonce), &r.u.initReply.nonce); - if (r.u.initReply.nonce == NULL) { - ret = ENOMEM; - krb5_set_error_message(context, ret, "Failed to decode server nonce"); - goto out; - } - - sp = krb5_storage_emem(); - if (sp == NULL) { - ret = ENOMEM; - krb5_set_error_message(context, ret, "malloc: out of memory"); - goto out; - } - ret = krb5_store_stringz(sp, ireq.u.init.type); - if (ret) { - krb5_clear_error_message(context); - goto out; - } - - if (ireq.u.init.channel) { - char *s; - int aret; - - aret = asprintf(&s, "%s-%s:%s", r.u.initReply.nonce, - ireq.u.init.channel->cb_type, - ireq.u.init.channel->cb_binding); - if (aret == -1 || s == NULL) { - ret = ENOMEM; - krb5_set_error_message(context, ret, - "Failed to allocate channel binding"); - goto out; - } - free(r.u.initReply.nonce); - r.u.initReply.nonce = s; - } - - ret = krb5_store_stringz(sp, r.u.initReply.nonce); - if (ret) { - krb5_clear_error_message(context); - goto out; - } - - if (strcasecmp(ireq.u.init.type, "CHAP") == 0) { - int aret; - - r.u.initReply.identifier = - malloc(sizeof(*r.u.initReply.identifier)); - if (r.u.initReply.identifier == NULL) { - ret = ENOMEM; - krb5_set_error_message(context, ret, "malloc: out of memory"); - goto out; - } - - aret = asprintf(r.u.initReply.identifier, "%02X", identifier&0xff); - if (aret == -1 || *r.u.initReply.identifier == NULL) { - ret = ENOMEM; - krb5_set_error_message(context, ret, "malloc: out of memory"); - goto out; - } - - } else - r.u.initReply.identifier = NULL; - - if (ireq.u.init.hostname) { - ret = krb5_store_stringz(sp, *ireq.u.init.hostname); - if (ret) { - krb5_clear_error_message(context); - goto out; - } - } - - ret = krb5_storage_to_data(sp, &buf); - if (ret) { - krb5_clear_error_message(context); - goto out; - } - - ret = get_digest_key(context, config, server, &crypto); - if (ret) - goto out; - - ret = krb5_create_checksum(context, - crypto, - KRB5_KU_DIGEST_OPAQUE, - 0, - buf.data, - buf.length, - &res); - krb5_crypto_destroy(context, crypto); - crypto = NULL; - krb5_data_free(&buf); - if (ret) - goto out; - - ASN1_MALLOC_ENCODE(Checksum, buf.data, buf.length, &res, &size, ret); - free_Checksum(&res); - if (ret) { - krb5_set_error_message(context, ret, "Failed to encode " - "checksum in digest request"); - goto out; - } - if (size != buf.length) - krb5_abortx(context, "ASN1 internal error"); - - hex_encode(buf.data, buf.length, &r.u.initReply.opaque); - free(buf.data); - krb5_data_zero(&buf); - if (r.u.initReply.opaque == NULL) { - krb5_clear_error_message(context); - ret = ENOMEM; - goto out; - } - - kdc_log(context, config, 3, "Digest %s init request successful from %s", - ireq.u.init.type, from); - - break; - } - case choice_DigestReqInner_digestRequest: { - sp = krb5_storage_emem(); - if (sp == NULL) { - ret = ENOMEM; - krb5_set_error_message(context, ret, "malloc: out of memory"); - goto out; - } - ret = krb5_store_stringz(sp, ireq.u.digestRequest.type); - if (ret) { - krb5_clear_error_message(context); - goto out; - } - - krb5_store_stringz(sp, ireq.u.digestRequest.serverNonce); - - if (ireq.u.digestRequest.hostname) { - ret = krb5_store_stringz(sp, *ireq.u.digestRequest.hostname); - if (ret) { - krb5_clear_error_message(context); - goto out; - } - } - - buf.length = strlen(ireq.u.digestRequest.opaque); - buf.data = malloc(buf.length); - if (buf.data == NULL) { - ret = ENOMEM; - krb5_set_error_message(context, ret, "malloc: out of memory"); - goto out; - } - - ret = hex_decode(ireq.u.digestRequest.opaque, buf.data, buf.length); - if (ret <= 0) { - ret = ENOMEM; - krb5_set_error_message(context, ret, "Failed to decode opaque"); - goto out; - } - buf.length = ret; - - ret = decode_Checksum(buf.data, buf.length, &res, NULL); - free(buf.data); - krb5_data_zero(&buf); - if (ret) { - krb5_set_error_message(context, ret, - "Failed to decode digest Checksum"); - goto out; - } - - ret = krb5_storage_to_data(sp, &buf); - if (ret) { - krb5_clear_error_message(context); - goto out; - } - - serverNonce.length = strlen(ireq.u.digestRequest.serverNonce); - serverNonce.data = malloc(serverNonce.length); - if (serverNonce.data == NULL) { - ret = ENOMEM; - krb5_set_error_message(context, ret, "malloc: out of memory"); - goto out; - } - - /* - * CHAP does the checksum of the raw nonce, but do it for all - * types, since we need to check the timestamp. - */ - { - ssize_t ssize; - - ssize = hex_decode(ireq.u.digestRequest.serverNonce, - serverNonce.data, serverNonce.length); - if (ssize <= 0) { - ret = ENOMEM; - krb5_set_error_message(context, ret, "Failed to decode serverNonce"); - goto out; - } - serverNonce.length = ssize; - } - - ret = get_digest_key(context, config, server, &crypto); - if (ret) - goto out; - - ret = _kdc_verify_checksum(context, crypto, - KRB5_KU_DIGEST_OPAQUE, - &buf, &res); - free_Checksum(&res); - krb5_data_free(&buf); - krb5_crypto_destroy(context, crypto); - crypto = NULL; - if (ret) - goto out; - - /* verify time */ - { - unsigned char *p = serverNonce.data; - uint32_t t; - - if (serverNonce.length < 4) { - ret = EINVAL; - krb5_set_error_message(context, ret, "server nonce too short"); - goto out; - } - t = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); - - if (labs((kdc_time & 0xffffffff) - t) > context->max_skew) { - ret = EINVAL; - krb5_set_error_message(context, ret, "time screw in server nonce "); - goto out; - } - } - - if (strcasecmp(ireq.u.digestRequest.type, "CHAP") == 0) { - EVP_MD_CTX *ctx; - unsigned char md[MD5_DIGEST_LENGTH]; - char *mdx; - char idx; - - if ((config->digests_allowed & CHAP_MD5) == 0) { - kdc_log(context, config, 2, "Digest CHAP MD5 not allowed"); - goto out; - } - - if (ireq.u.digestRequest.identifier == NULL) { - ret = EINVAL; - krb5_set_error_message(context, ret, "Identifier missing " - "from CHAP request"); - goto out; - } - - if (hex_decode(*ireq.u.digestRequest.identifier, &idx, 1) != 1) { - ret = EINVAL; - krb5_set_error_message(context, ret, "failed to decode identifier"); - goto out; - } - - ret = get_password_entry(context, config, - ireq.u.digestRequest.username, - &password); - if (ret) - goto out; - - ctx = EVP_MD_CTX_create(); - - EVP_DigestInit_ex(ctx, EVP_md5(), NULL); - EVP_DigestUpdate(ctx, &idx, 1); - EVP_DigestUpdate(ctx, password, strlen(password)); - EVP_DigestUpdate(ctx, serverNonce.data, serverNonce.length); - EVP_DigestFinal_ex(ctx, md, NULL); - - EVP_MD_CTX_destroy(ctx); - - hex_encode(md, sizeof(md), &mdx); - if (mdx == NULL) { - krb5_clear_error_message(context); - ret = ENOMEM; - goto out; - } - - r.element = choice_DigestRepInner_response; - - ret = strcasecmp(mdx, ireq.u.digestRequest.responseData); - free(mdx); - if (ret == 0) { - r.u.response.success = TRUE; - } else { - kdc_log(context, config, 2, - "CHAP reply mismatch for %s", - ireq.u.digestRequest.username); - r.u.response.success = FALSE; - } - - } else if (strcasecmp(ireq.u.digestRequest.type, "SASL-DIGEST-MD5") == 0) { - EVP_MD_CTX *ctx; - unsigned char md[MD5_DIGEST_LENGTH]; - char *mdx; - char *A1, *A2; - - if ((config->digests_allowed & DIGEST_MD5) == 0) { - kdc_log(context, config, 2, "Digest SASL MD5 not allowed"); - goto out; - } - - if (ireq.u.digestRequest.nonceCount == NULL) - goto out; - if (ireq.u.digestRequest.clientNonce == NULL) - goto out; - if (ireq.u.digestRequest.qop == NULL) - goto out; - if (ireq.u.digestRequest.realm == NULL) - goto out; - - ret = get_password_entry(context, config, - ireq.u.digestRequest.username, - &password); - if (ret) - goto failed; - - ctx = EVP_MD_CTX_create(); - - EVP_DigestInit_ex(ctx, EVP_md5(), NULL); - EVP_DigestUpdate(ctx, ireq.u.digestRequest.username, - strlen(ireq.u.digestRequest.username)); - EVP_DigestUpdate(ctx, ":", 1); - EVP_DigestUpdate(ctx, *ireq.u.digestRequest.realm, - strlen(*ireq.u.digestRequest.realm)); - EVP_DigestUpdate(ctx, ":", 1); - EVP_DigestUpdate(ctx, password, strlen(password)); - EVP_DigestFinal_ex(ctx, md, NULL); - - EVP_DigestInit_ex(ctx, EVP_md5(), NULL); - EVP_DigestUpdate(ctx, md, sizeof(md)); - EVP_DigestUpdate(ctx, ":", 1); - EVP_DigestUpdate(ctx, ireq.u.digestRequest.serverNonce, - strlen(ireq.u.digestRequest.serverNonce)); - EVP_DigestUpdate(ctx, ":", 1); - EVP_DigestUpdate(ctx, *ireq.u.digestRequest.nonceCount, - strlen(*ireq.u.digestRequest.nonceCount)); - if (ireq.u.digestRequest.authid) { - EVP_DigestUpdate(ctx, ":", 1); - EVP_DigestUpdate(ctx, *ireq.u.digestRequest.authid, - strlen(*ireq.u.digestRequest.authid)); - } - EVP_DigestFinal_ex(ctx, md, NULL); - hex_encode(md, sizeof(md), &A1); - if (A1 == NULL) { - ret = ENOMEM; - krb5_set_error_message(context, ret, "malloc: out of memory"); - EVP_MD_CTX_destroy(ctx); - goto failed; - } - - EVP_DigestInit_ex(ctx, EVP_md5(), NULL); - EVP_DigestUpdate(ctx, - "AUTHENTICATE:", sizeof("AUTHENTICATE:") - 1); - EVP_DigestUpdate(ctx, *ireq.u.digestRequest.uri, - strlen(*ireq.u.digestRequest.uri)); - - /* conf|int */ - if (strcmp(ireq.u.digestRequest.digest, "clear") != 0) { - static char conf_zeros[] = ":00000000000000000000000000000000"; - EVP_DigestUpdate(ctx, conf_zeros, sizeof(conf_zeros) - 1); - } - - EVP_DigestFinal_ex(ctx, md, NULL); - - hex_encode(md, sizeof(md), &A2); - if (A2 == NULL) { - ret = ENOMEM; - krb5_set_error_message(context, ret, "malloc: out of memory"); - free(A1); - goto failed; - } - - EVP_DigestInit_ex(ctx, EVP_md5(), NULL); - EVP_DigestUpdate(ctx, A1, strlen(A2)); - EVP_DigestUpdate(ctx, ":", 1); - EVP_DigestUpdate(ctx, ireq.u.digestRequest.serverNonce, - strlen(ireq.u.digestRequest.serverNonce)); - EVP_DigestUpdate(ctx, ":", 1); - EVP_DigestUpdate(ctx, *ireq.u.digestRequest.nonceCount, - strlen(*ireq.u.digestRequest.nonceCount)); - EVP_DigestUpdate(ctx, ":", 1); - EVP_DigestUpdate(ctx, *ireq.u.digestRequest.clientNonce, - strlen(*ireq.u.digestRequest.clientNonce)); - EVP_DigestUpdate(ctx, ":", 1); - EVP_DigestUpdate(ctx, *ireq.u.digestRequest.qop, - strlen(*ireq.u.digestRequest.qop)); - EVP_DigestUpdate(ctx, ":", 1); - EVP_DigestUpdate(ctx, A2, strlen(A2)); - - EVP_DigestFinal_ex(ctx, md, NULL); - - EVP_MD_CTX_destroy(ctx); - - free(A1); - free(A2); - - hex_encode(md, sizeof(md), &mdx); - if (mdx == NULL) { - krb5_clear_error_message(context); - ret = ENOMEM; - goto out; - } - - r.element = choice_DigestRepInner_response; - ret = strcasecmp(mdx, ireq.u.digestRequest.responseData); - free(mdx); - if (ret == 0) { - r.u.response.success = TRUE; - } else { - kdc_log(context, config, 2, - "DIGEST-MD5 reply mismatch for %s", - ireq.u.digestRequest.username); - r.u.response.success = FALSE; - } - - } else if (strcasecmp(ireq.u.digestRequest.type, "MS-CHAP-V2") == 0) { - unsigned char md[SHA_DIGEST_LENGTH], challenge[SHA_DIGEST_LENGTH]; - krb5_principal clientprincipal = NULL; - char *mdx; - const char *username; - struct ntlm_buf answer; - Key *key = NULL; - EVP_MD_CTX *ctp; - - if ((config->digests_allowed & MS_CHAP_V2) == 0) { - kdc_log(context, config, 2, "MS-CHAP-V2 not allowed"); - goto failed; - } - - if (ireq.u.digestRequest.clientNonce == NULL) { - ret = EINVAL; - krb5_set_error_message(context, ret, - "MS-CHAP-V2 clientNonce missing"); - goto failed; - } - if (serverNonce.length != 16) { - ret = EINVAL; - krb5_set_error_message(context, ret, - "MS-CHAP-V2 serverNonce wrong length"); - goto failed; - } - - /* strip of the domain component */ - username = strchr(ireq.u.digestRequest.username, '\\'); - if (username == NULL) - username = ireq.u.digestRequest.username; - else - username++; - - ctp = EVP_MD_CTX_create(); - - /* ChallengeHash */ - EVP_DigestInit_ex(ctp, EVP_sha1(), NULL); - { - ssize_t ssize; - krb5_data clientNonce; - - clientNonce.length = strlen(*ireq.u.digestRequest.clientNonce); - clientNonce.data = malloc(clientNonce.length); - if (clientNonce.data == NULL) { - ret = ENOMEM; - krb5_set_error_message(context, ret, - "malloc: out of memory"); - EVP_MD_CTX_destroy(ctp); - goto out; - } - - ssize = hex_decode(*ireq.u.digestRequest.clientNonce, - clientNonce.data, clientNonce.length); - if (ssize != 16) { - ret = ENOMEM; - krb5_set_error_message(context, ret, - "Failed to decode clientNonce"); - EVP_MD_CTX_destroy(ctp); - goto out; - } - EVP_DigestUpdate(ctp, clientNonce.data, ssize); - free(clientNonce.data); - } - EVP_DigestUpdate(ctp, serverNonce.data, serverNonce.length); - EVP_DigestUpdate(ctp, username, strlen(username)); - - EVP_DigestFinal_ex(ctp, challenge, NULL); - - EVP_MD_CTX_destroy(ctp); - - /* NtPasswordHash */ - ret = krb5_parse_name(context, username, &clientprincipal); - if (ret) - goto failed; - - ret = _kdc_db_fetch(context, config, clientprincipal, - HDB_F_GET_CLIENT, NULL, &userdb, &user); - krb5_free_principal(context, clientprincipal); - if (ret) { - krb5_set_error_message(context, ret, - "MS-CHAP-V2 user %s not in database", - username); - goto failed; - } - - ret = hdb_enctype2key(context, user, NULL, - ETYPE_ARCFOUR_HMAC_MD5, &key); - if (ret) { - krb5_set_error_message(context, ret, - "MS-CHAP-V2 missing arcfour key %s", - username); - goto failed; - } - - /* ChallengeResponse */ - ret = heim_ntlm_calculate_ntlm1(key->key.keyvalue.data, - key->key.keyvalue.length, - challenge, &answer); - if (ret) { - krb5_set_error_message(context, ret, "NTLM missing arcfour key"); - goto failed; - } - - hex_encode(answer.data, answer.length, &mdx); - if (mdx == NULL) { - free(answer.data); - krb5_clear_error_message(context); - ret = ENOMEM; - goto out; - } - - r.element = choice_DigestRepInner_response; - ret = strcasecmp(mdx, ireq.u.digestRequest.responseData); - if (ret == 0) { - r.u.response.success = TRUE; - } else { - kdc_log(context, config, 2, - "MS-CHAP-V2 hash mismatch for %s", - ireq.u.digestRequest.username); - r.u.response.success = FALSE; - } - free(mdx); - - if (r.u.response.success) { - unsigned char hashhash[MD4_DIGEST_LENGTH]; - EVP_MD_CTX *ctxp; - - ctxp = EVP_MD_CTX_create(); - - /* hashhash */ - { - EVP_DigestInit_ex(ctxp, EVP_md4(), NULL); - EVP_DigestUpdate(ctxp, - key->key.keyvalue.data, - key->key.keyvalue.length); - EVP_DigestFinal_ex(ctxp, hashhash, NULL); - } - - /* GenerateAuthenticatorResponse */ - EVP_DigestInit_ex(ctxp, EVP_sha1(), NULL); - EVP_DigestUpdate(ctxp, hashhash, sizeof(hashhash)); - EVP_DigestUpdate(ctxp, answer.data, answer.length); - EVP_DigestUpdate(ctxp, ms_chap_v2_magic1, - sizeof(ms_chap_v2_magic1)); - EVP_DigestFinal_ex(ctxp, md, NULL); - - EVP_DigestInit_ex(ctxp, EVP_sha1(), NULL); - EVP_DigestUpdate(ctxp, md, sizeof(md)); - EVP_DigestUpdate(ctxp, challenge, 8); - EVP_DigestUpdate(ctxp, ms_chap_v2_magic2, - sizeof(ms_chap_v2_magic2)); - EVP_DigestFinal_ex(ctxp, md, NULL); - - r.u.response.rsp = calloc(1, sizeof(*r.u.response.rsp)); - if (r.u.response.rsp == NULL) { - free(answer.data); - krb5_clear_error_message(context); - EVP_MD_CTX_destroy(ctxp); - ret = ENOMEM; - goto out; - } - - hex_encode(md, sizeof(md), r.u.response.rsp); - if (r.u.response.rsp == NULL) { - free(answer.data); - krb5_clear_error_message(context); - EVP_MD_CTX_destroy(ctxp); - ret = ENOMEM; - goto out; - } - - /* get_master, rfc 3079 3.4 */ - EVP_DigestInit_ex(ctxp, EVP_sha1(), NULL); - EVP_DigestUpdate(ctxp, hashhash, 16); - EVP_DigestUpdate(ctxp, answer.data, answer.length); - EVP_DigestUpdate(ctxp, ms_rfc3079_magic1, - sizeof(ms_rfc3079_magic1)); - EVP_DigestFinal_ex(ctxp, md, NULL); - - free(answer.data); - - EVP_MD_CTX_destroy(ctxp); - - r.u.response.session_key = - calloc(1, sizeof(*r.u.response.session_key)); - if (r.u.response.session_key == NULL) { - krb5_clear_error_message(context); - ret = ENOMEM; - goto out; - } - - ret = krb5_data_copy(r.u.response.session_key, md, 16); - if (ret) { - krb5_clear_error_message(context); - goto out; - } - } - - } else { - int aret; - - r.element = choice_DigestRepInner_error; - aret = asprintf(&r.u.error.reason, "Unsupported digest type %s", - ireq.u.digestRequest.type); - if (aret == -1 || r.u.error.reason == NULL) { - ret = ENOMEM; - krb5_set_error_message(context, ret, "malloc: out of memory"); - goto out; - } - r.u.error.code = EINVAL; - } - - kdc_log(context, config, 3, "Digest %s request successful %s", - ireq.u.digestRequest.type, ireq.u.digestRequest.username); - - break; - } - case choice_DigestReqInner_ntlmInit: - - if ((config->digests_allowed & (NTLM_V1|NTLM_V1_SESSION|NTLM_V2)) == 0) { - kdc_log(context, config, 2, "NTLM not allowed"); - goto failed; - } - - r.element = choice_DigestRepInner_ntlmInitReply; - - r.u.ntlmInitReply.flags = NTLM_NEG_UNICODE; - - if ((ireq.u.ntlmInit.flags & NTLM_NEG_UNICODE) == 0) { - kdc_log(context, config, 2, "NTLM client have no unicode"); - goto failed; - } - - if (ireq.u.ntlmInit.flags & NTLM_NEG_NTLM) - r.u.ntlmInitReply.flags |= NTLM_NEG_NTLM; - else { - kdc_log(context, config, 2, "NTLM client doesn't support NTLM"); - goto failed; - } - - r.u.ntlmInitReply.flags |= - NTLM_NEG_TARGET | - NTLM_TARGET_DOMAIN | - NTLM_ENC_128; - -#define ALL \ - NTLM_NEG_SIGN| \ - NTLM_NEG_SEAL| \ - NTLM_NEG_ALWAYS_SIGN| \ - NTLM_NEG_NTLM2_SESSION| \ - NTLM_NEG_KEYEX - - r.u.ntlmInitReply.flags |= (ireq.u.ntlmInit.flags & (ALL)); - -#undef ALL - - r.u.ntlmInitReply.targetname = - get_ntlm_targetname(context, client); - if (r.u.ntlmInitReply.targetname == NULL) { - ret = ENOMEM; - krb5_set_error_message(context, ret, "malloc: out of memory"); - goto out; - } - r.u.ntlmInitReply.challenge.data = malloc(8); - if (r.u.ntlmInitReply.challenge.data == NULL) { - ret = ENOMEM; - krb5_set_error_message(context, ret, "malloc: out of memory"); - goto out; - } - r.u.ntlmInitReply.challenge.length = 8; - if (RAND_bytes(r.u.ntlmInitReply.challenge.data, - r.u.ntlmInitReply.challenge.length) != 1) - { - ret = ENOMEM; - krb5_set_error_message(context, ret, "out of random error"); - goto out; - } - /* XXX fix targetinfo */ - ALLOC(r.u.ntlmInitReply.targetinfo); - if (r.u.ntlmInitReply.targetinfo == NULL) { - ret = ENOMEM; - krb5_set_error_message(context, ret, "malloc: out of memory"); - goto out; - } - - ret = fill_targetinfo(context, - r.u.ntlmInitReply.targetname, - client, - r.u.ntlmInitReply.targetinfo); - if (ret) { - ret = ENOMEM; - krb5_set_error_message(context, ret, "malloc: out of memory"); - goto out; - } - - /* - * Save data encryted in opaque for the second part of the - * ntlm authentication - */ - sp = krb5_storage_emem(); - if (sp == NULL) { - ret = ENOMEM; - krb5_set_error_message(context, ret, "malloc: out of memory"); - goto out; - } - - ret = krb5_storage_write(sp, r.u.ntlmInitReply.challenge.data, 8); - if (ret != 8) { - ret = ENOMEM; - krb5_set_error_message(context, ret, "storage write challenge"); - goto out; - } - ret = krb5_store_uint32(sp, r.u.ntlmInitReply.flags); - if (ret) { - krb5_clear_error_message(context); - goto out; - } - - ret = krb5_storage_to_data(sp, &buf); - if (ret) { - krb5_clear_error_message(context); - goto out; - } - - ret = get_digest_key(context, config, server, &crypto); - if (ret) - goto out; - - ret = krb5_encrypt(context, crypto, KRB5_KU_DIGEST_OPAQUE, - buf.data, buf.length, &r.u.ntlmInitReply.opaque); - krb5_data_free(&buf); - krb5_crypto_destroy(context, crypto); - crypto = NULL; - if (ret) - goto out; - - kdc_log(context, config, 3, "NTLM init from %s", from); - - break; - - case choice_DigestReqInner_ntlmRequest: { - krb5_principal clientprincipal; - unsigned char sessionkey[16]; - unsigned char challenge[8]; - uint32_t flags; - Key *key = NULL; - int version; - - r.element = choice_DigestRepInner_ntlmResponse; - r.u.ntlmResponse.success = 0; - r.u.ntlmResponse.flags = 0; - r.u.ntlmResponse.sessionkey = NULL; - r.u.ntlmResponse.tickets = NULL; - - /* get username */ - ret = krb5_parse_name(context, - ireq.u.ntlmRequest.username, - &clientprincipal); - if (ret) - goto failed; - - ret = _kdc_db_fetch(context, config, clientprincipal, - HDB_F_GET_CLIENT, NULL, &userdb, &user); - krb5_free_principal(context, clientprincipal); - if (ret) { - krb5_set_error_message(context, ret, "NTLM user %s not in database", - ireq.u.ntlmRequest.username); - goto failed; - } - - ret = get_digest_key(context, config, server, &crypto); - if (ret) - goto failed; - - ret = krb5_decrypt(context, crypto, KRB5_KU_DIGEST_OPAQUE, - ireq.u.ntlmRequest.opaque.data, - ireq.u.ntlmRequest.opaque.length, &buf); - krb5_crypto_destroy(context, crypto); - crypto = NULL; - if (ret) { - kdc_log(context, config, 2, - "Failed to decrypt nonce from %s", from); - goto failed; - } - - sp = krb5_storage_from_data(&buf); - if (sp == NULL) { - ret = ENOMEM; - krb5_set_error_message(context, ret, "malloc: out of memory"); - goto out; - } - - ret = krb5_storage_read(sp, challenge, sizeof(challenge)); - if (ret != sizeof(challenge)) { - ret = ENOMEM; - krb5_set_error_message(context, ret, "NTLM storage read challenge"); - goto out; - } - ret = krb5_ret_uint32(sp, &flags); - if (ret) { - krb5_set_error_message(context, ret, "NTLM storage read flags"); - goto out; - } - krb5_storage_free(sp); - sp = NULL; - krb5_data_free(&buf); - - if ((flags & NTLM_NEG_NTLM) == 0) { - ret = EINVAL; - krb5_set_error_message(context, ret, "NTLM not negotiated"); - goto out; - } - - ret = hdb_enctype2key(context, user, NULL, - ETYPE_ARCFOUR_HMAC_MD5, &key); - if (ret) { - krb5_set_error_message(context, ret, "NTLM missing arcfour key"); - goto out; - } - - /* check if this is NTLMv2 */ - if (ireq.u.ntlmRequest.ntlm.length != 24) { - struct ntlm_buf infotarget, answer; - char *targetname; - - if ((config->digests_allowed & NTLM_V2) == 0) { - kdc_log(context, config, 2, "NTLM v2 not allowed"); - goto out; - } - - version = 2; - - targetname = get_ntlm_targetname(context, client); - if (targetname == NULL) { - ret = ENOMEM; - krb5_set_error_message(context, ret, "malloc: out of memory"); - goto out; - } - - answer.length = ireq.u.ntlmRequest.ntlm.length; - answer.data = ireq.u.ntlmRequest.ntlm.data; - - ret = heim_ntlm_verify_ntlm2(key->key.keyvalue.data, - key->key.keyvalue.length, - ireq.u.ntlmRequest.username, - targetname, - 0, - challenge, - &answer, - &infotarget, - sessionkey); - free(targetname); - if (ret) { - krb5_set_error_message(context, ret, "NTLM v2 verify failed"); - goto failed; - } - - /* XXX verify infotarget matches client (checksum ?) */ - - free(infotarget.data); - /* */ - - } else { - struct ntlm_buf answer; - - version = 1; - - if (flags & NTLM_NEG_NTLM2_SESSION) { - unsigned char sessionhash[MD5_DIGEST_LENGTH]; - EVP_MD_CTX *ctx; - - if ((config->digests_allowed & NTLM_V1_SESSION) == 0) { - kdc_log(context, config, 2, "NTLM v1-session not allowed"); - ret = EINVAL; - goto failed; - } - - if (ireq.u.ntlmRequest.lm.length != 24) { - ret = EINVAL; - krb5_set_error_message(context, ret, "LM hash have wrong length " - "for NTLM session key"); - goto failed; - } - - ctx = EVP_MD_CTX_create(); - - EVP_DigestInit_ex(ctx, EVP_md5(), NULL); - - EVP_DigestUpdate(ctx, challenge, sizeof(challenge)); - EVP_DigestUpdate(ctx, ireq.u.ntlmRequest.lm.data, 8); - EVP_DigestFinal_ex(ctx, sessionhash, NULL); - memcpy(challenge, sessionhash, sizeof(challenge)); - - EVP_MD_CTX_destroy(ctx); - - } else { - if ((config->digests_allowed & NTLM_V1) == 0) { - kdc_log(context, config, 2, "NTLM v1 not allowed"); - goto failed; - } - } - - ret = heim_ntlm_calculate_ntlm1(key->key.keyvalue.data, - key->key.keyvalue.length, - challenge, &answer); - if (ret) { - krb5_set_error_message(context, ret, "NTLM missing arcfour key"); - goto failed; - } - - if (ireq.u.ntlmRequest.ntlm.length != answer.length || - ct_memcmp(ireq.u.ntlmRequest.ntlm.data, answer.data, answer.length) != 0) - { - free(answer.data); - ret = EINVAL; - krb5_set_error_message(context, ret, "NTLM hash mismatch"); - goto failed; - } - free(answer.data); - - { - EVP_MD_CTX *ctx; - - ctx = EVP_MD_CTX_create(); - - EVP_DigestInit_ex(ctx, EVP_md4(), NULL); - EVP_DigestUpdate(ctx, - key->key.keyvalue.data, - key->key.keyvalue.length); - EVP_DigestFinal_ex(ctx, sessionkey, NULL); - - EVP_MD_CTX_destroy(ctx); - } - } - - if (ireq.u.ntlmRequest.sessionkey) { - unsigned char masterkey[MD4_DIGEST_LENGTH]; - EVP_CIPHER_CTX rc4; - size_t len; - - if ((flags & NTLM_NEG_KEYEX) == 0) { - ret = EINVAL; - krb5_set_error_message(context, ret, - "NTLM client failed to neg key " - "exchange but still sent key"); - goto failed; - } - - len = ireq.u.ntlmRequest.sessionkey->length; - if (len != sizeof(masterkey)){ - ret = EINVAL; - krb5_set_error_message(context, ret, - "NTLM master key wrong length: %lu", - (unsigned long)len); - goto failed; - } - - - EVP_CIPHER_CTX_init(&rc4); - EVP_CipherInit_ex(&rc4, EVP_rc4(), NULL, sessionkey, NULL, 1); - EVP_Cipher(&rc4, - masterkey, ireq.u.ntlmRequest.sessionkey->data, - sizeof(masterkey)); - EVP_CIPHER_CTX_cleanup(&rc4); - - r.u.ntlmResponse.sessionkey = - malloc(sizeof(*r.u.ntlmResponse.sessionkey)); - if (r.u.ntlmResponse.sessionkey == NULL) { - ret = EINVAL; - krb5_set_error_message(context, ret, "malloc: out of memory"); - goto out; - } - - ret = krb5_data_copy(r.u.ntlmResponse.sessionkey, - masterkey, sizeof(masterkey)); - if (ret) { - krb5_set_error_message(context, ret, "malloc: out of memory"); - goto out; - } - } - - r.u.ntlmResponse.success = 1; - kdc_log(context, config, 0, "NTLM version %d successful for %s", - version, ireq.u.ntlmRequest.username); - break; - } - case choice_DigestReqInner_supportedMechs: - - kdc_log(context, config, 4, "digest supportedMechs from %s", from); - - r.element = choice_DigestRepInner_supportedMechs; - memset(&r.u.supportedMechs, 0, sizeof(r.u.supportedMechs)); - - if (config->digests_allowed & NTLM_V1) - r.u.supportedMechs.ntlm_v1 = 1; - if (config->digests_allowed & NTLM_V1_SESSION) - r.u.supportedMechs.ntlm_v1_session = 1; - if (config->digests_allowed & NTLM_V2) - r.u.supportedMechs.ntlm_v2 = 1; - if (config->digests_allowed & DIGEST_MD5) - r.u.supportedMechs.digest_md5 = 1; - if (config->digests_allowed & CHAP_MD5) - r.u.supportedMechs.chap_md5 = 1; - if (config->digests_allowed & MS_CHAP_V2) - r.u.supportedMechs.ms_chap_v2 = 1; - break; - - default: { - const char *s; - ret = EINVAL; - krb5_set_error_message(context, ret, "unknown operation to digest"); - - failed: - - s = krb5_get_error_message(context, ret); - if (s == NULL) { - krb5_clear_error_message(context); - goto out; - } - - kdc_log(context, config, 2, "Digest failed with: %s", s); - - r.element = choice_DigestRepInner_error; - r.u.error.reason = strdup("unknown error"); - krb5_free_error_message(context, s); - if (r.u.error.reason == NULL) { - ret = ENOMEM; - krb5_set_error_message(context, ret, "malloc: out of memory"); - goto out; - } - r.u.error.code = EINVAL; - break; - } - } - - ASN1_MALLOC_ENCODE(DigestRepInner, buf.data, buf.length, &r, &size, ret); - if (ret) { - krb5_set_error_message(context, ret, "Failed to encode inner digest reply"); - goto out; - } - if (size != buf.length) - krb5_abortx(context, "ASN1 internal error"); - - krb5_auth_con_addflags(context, ac, KRB5_AUTH_CONTEXT_USE_SUBKEY, NULL); - - ret = krb5_mk_rep (context, ac, &rep.apRep); - if (ret) - goto out; - - { - krb5_keyblock *key; - - ret = krb5_auth_con_getlocalsubkey(context, ac, &key); - if (ret) - goto out; - - ret = krb5_crypto_init(context, key, 0, &crypto); - krb5_free_keyblock (context, key); - if (ret) - goto out; - } - - ret = krb5_encrypt_EncryptedData(context, crypto, KRB5_KU_DIGEST_ENCRYPT, - buf.data, buf.length, 0, - &rep.innerRep); - if (ret) { - krb5_prepend_error_message(context, ret, "Failed to encrypt digest: "); - goto out; - } - - ASN1_MALLOC_ENCODE(DigestREP, reply->data, reply->length, &rep, &size, ret); - if (ret) { - krb5_set_error_message(context, ret, "Failed to encode digest reply"); - goto out; - } - if (size != reply->length) - krb5_abortx(context, "ASN1 internal error"); - - - out: - if (ac) - krb5_auth_con_free(context, ac); - if (ret) - krb5_warn(context, ret, "Digest request from %s failed", from); - if (ticket) - krb5_free_ticket(context, ticket); - if (id) - krb5_kt_close(context, id); - if (crypto) - krb5_crypto_destroy(context, crypto); - if (sp) - krb5_storage_free(sp); - if (user) - _kdc_free_ent (context, userdb, user); - if (server) - _kdc_free_ent (context, serverdb, server); - if (client) - _kdc_free_ent (context, clientdb, client); - if (password) { - memset(password, 0, strlen(password)); - free (password); - } - if (client_name) - free (client_name); - krb5_data_free(&buf); - krb5_data_free(&serverNonce); - free_Checksum(&res); - free_DigestREP(&rep); - free_DigestRepInner(&r); - free_DigestReqInner(&ireq); - - return ret; -} - -#endif /* DIGEST */ diff --git a/kdc/hprop.c b/kdc/hprop.c index d6ff6133a..51a3cdf98 100644 --- a/kdc/hprop.c +++ b/kdc/hprop.c @@ -47,6 +47,8 @@ static int decrypt_flag; static hdb_master_key mkey5; static char *source_type; +static char *ossl_cnf; +static char *ossl_propq; static char *local_realm=NULL; @@ -143,6 +145,12 @@ struct getargs args[] = { { "encrypt", 'E', arg_flag, &encrypt_flag, "encrypt keys", NULL }, { "stdout", 'n', arg_flag, &to_stdout, "dump to stdout", NULL }, { "verbose", 'v', arg_flag, &verbose_flag, NULL, NULL }, + { "ossl-cnf", 0, arg_string, &ossl_cnf, + "OpenSSL configuration file", "FILE" + }, + { "ossl-propq", 0, arg_string, &ossl_propq, + "OpenSSL property query string (e.g., provider=pkcs11)", "PROPQ" + }, { "version", 0, arg_flag, &version_flag, NULL, NULL }, { "help", 'h', arg_flag, &help_flag, NULL, NULL } }; @@ -422,6 +430,12 @@ main(int argc, char **argv) if(ret) exit(1); + if (ossl_cnf || ossl_propq) { + ret = krb5_set_ossl_cnf_propq(context, ossl_cnf, ossl_propq); + if (ret) + krb5_err(context, 1, ret, "krb5_set_ossl_cnf_propq"); + } + /* We may be reading an old database encrypted with a DES master key. */ ret = krb5_allow_weak_crypto(context, 1); if(ret) diff --git a/kdc/hpropd.c b/kdc/hpropd.c index 255d60949..5d0ca5237 100644 --- a/kdc/hpropd.c +++ b/kdc/hpropd.c @@ -41,6 +41,8 @@ static const char *database; static int from_stdin; static char *local_realm; static char *ktname = NULL; +static char *ossl_cnf = NULL; +static char *ossl_propq = NULL; struct getargs args[] = { { "database", 'd', arg_string, rk_UNCONST(&database), "database", "file" }, @@ -52,6 +54,12 @@ struct getargs args[] = { #endif { "keytab", 'k', arg_string, &ktname, "keytab to use for authentication", "keytab" }, { "realm", 'r', arg_string, &local_realm, "realm to use", NULL }, + { "ossl-cnf", 0, arg_string, &ossl_cnf, + "OpenSSL configuration file", "FILE" + }, + { "ossl-propq", 0, arg_string, &ossl_propq, + "OpenSSL property query string (e.g., provider=pkcs11)", "PROPQ" + }, { "version", 0, arg_flag, &version_flag, NULL, NULL }, { "help", 'h', arg_flag, &help_flag, NULL, NULL} }; @@ -112,6 +120,12 @@ main(int argc, char **argv) if (argc != 0) usage(1); + if (ossl_cnf || ossl_propq) { + ret = krb5_set_ossl_cnf_propq(context, ossl_cnf, ossl_propq); + if (ret) + krb5_err(context, 1, ret, "krb5_set_ossl_cnf_propq"); + } + if (database == NULL) database = hdb_default_db(context); diff --git a/kdc/httpkadmind.c b/kdc/httpkadmind.c index e99c41e93..feb8f2fb3 100644 --- a/kdc/httpkadmind.c +++ b/kdc/httpkadmind.c @@ -353,6 +353,8 @@ static const char *writable_kadmin_server; static const char *stash_file; static const char *kadmin_client_name = "httpkadmind/admin"; static const char *kadmin_client_keytab; +static const char *ossl_cnf; +static const char *ossl_propq; static struct getarg_strings auth_types; #define set_conf(c, f, v, b) \ @@ -1923,9 +1925,9 @@ mac_csrf_token(kadmin_request_desc r, krb5_storage *sp) krb5_error_code ret; krb5_principal p = NULL; krb5_data data; - char mac[EVP_MAX_MD_SIZE]; - unsigned int maclen = sizeof(mac); - HMAC_CTX *ctx = NULL; + unsigned char mac[EVP_MAX_MD_SIZE]; + size_t maclen = sizeof(mac); + EVP_MAC_CTX *ctx = NULL; size_t i = 0; int freeit = 0; @@ -1955,32 +1957,32 @@ mac_csrf_token(kadmin_request_desc r, krb5_storage *sp) if (ret == 0 && i == princ.n_key_data) i = 0; /* Weird, but can't happen */ - if (ret == 0 && (ctx = HMAC_CTX_new()) == NULL) - ret = krb5_enomem(r->context); /* HMAC the token body and the client principal name */ + if (ret == 0) + ret = _krb5_hmac_start_ossl(r->context, + princ.key_data[i].key_data_contents[0], + princ.key_data[i].key_data_length[0], + EVP_sha256(), &ctx); + if (ret == 0) + ret = (EVP_MAC_update(ctx, data.data, data.length) == 1) ? 0 : EINVAL; + if (ret == 0) + ret = (EVP_MAC_update(ctx, + (unsigned char *)r->cname, + strlen(r->cname)) == 1) ? 0 : EINVAL; + if (ret == 0) + ret = (EVP_MAC_final(ctx, mac, &maclen, maclen) == 1) ? 0 : EINVAL; + EVP_MAC_CTX_free(ctx); + + krb5_data_free(&data); + data.length = maclen; + data.data = mac; if (ret == 0) { - if (HMAC_Init_ex(ctx, princ.key_data[i].key_data_contents[0], - princ.key_data[i].key_data_length[0], EVP_sha256(), - NULL) == 0) { - HMAC_CTX_cleanup(ctx); + if (krb5_storage_write(sp, mac, maclen) != maclen) ret = krb5_enomem(r->context); - } else { - HMAC_Update(ctx, data.data, data.length); - HMAC_Update(ctx, r->cname, strlen(r->cname)); - HMAC_Final(ctx, mac, &maclen); - HMAC_CTX_cleanup(ctx); - krb5_data_free(&data); - data.length = maclen; - data.data = mac; - if (krb5_storage_write(sp, mac, maclen) != maclen) - ret = krb5_enomem(r->context); - } } krb5_free_principal(r->context, p); if (freeit) kadm5_free_principal_ent(r->kadm_handle, &princ); - if (ctx) - HMAC_CTX_free(ctx); return ret; } @@ -2343,6 +2345,12 @@ static struct getargs args[] = { "Keytab with client credentials for remote kadmind", "KEYTAB" }, { "token-authentication-type", 'T', arg_strings, &auth_types, "Token authentication type(s) supported", "HTTP-AUTH-TYPE" }, + { "ossl-cnf", 0, arg_string, &ossl_cnf, + "OpenSSL configuration file", "FILE" + }, + { "ossl-propq", 0, arg_string, &ossl_propq, + "OpenSSL property query string (e.g., provider=pkcs11)", "PROPQ" + }, { "verbose", 'v', arg_counter, &verbose_counter, "verbose", "run verbosely" } }; @@ -2549,6 +2557,12 @@ main(int argc, char **argv) if ((errno = get_krb5_context(&context))) err(1, "Could not init krb5 context (config file issue?)"); + if (ossl_cnf || ossl_propq) { + ret = krb5_set_ossl_cnf_propq(context, ossl_cnf, ossl_propq); + if (ret) + krb5_err(context, 1, ret, "krb5_set_ossl_cnf_propq"); + } + get_csrf_prot_type(context); if (!realm) { diff --git a/kdc/kdc_locl.h b/kdc/kdc_locl.h index caee019af..ede337087 100644 --- a/kdc/kdc_locl.h +++ b/kdc/kdc_locl.h @@ -231,8 +231,6 @@ extern int do_bonjour; extern int testing_flag; -extern const struct units _kdc_digestunits[]; - #define KDC_LOG_FILE "kdc.log" extern struct timeval _kdc_now; diff --git a/kdc/kstash.c b/kdc/kstash.c index 6ec1a548a..b9c120ca8 100644 --- a/kdc/kstash.c +++ b/kdc/kstash.c @@ -124,8 +124,8 @@ main(int argc, char **argv) buf[strcspn(buf, "\r\n")] = '\0'; } else { - if(UI_UTIL_read_pw_string(buf, sizeof(buf), "Master key: ", - UI_UTIL_FLAG_VERIFY)) + if (_krb5_UI_UTIL_read_pw_string(buf, sizeof(buf), "Master key: ", + UI_UTIL_FLAG_VERIFY)) exit(1); } krb5_string_to_key_salt(context, enctype, buf, salt, &key); diff --git a/kdc/kx509.c b/kdc/kx509.c index 6efd94e3a..eab68d2c9 100644 --- a/kdc/kx509.c +++ b/kdc/kx509.c @@ -147,7 +147,9 @@ verify_req_hash(krb5_context context, krb5_keyblock *key) { unsigned char digest[SHA_DIGEST_LENGTH]; - HMAC_CTX ctx; + EVP_MAC_CTX *ctx = NULL; + size_t maclen = SHA_DIGEST_LENGTH; + int ret; if (req->pk_hash.length != sizeof(digest)) { krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED, @@ -156,21 +158,29 @@ verify_req_hash(krb5_context context, return KRB5KDC_ERR_PREAUTH_FAILED; } - HMAC_CTX_init(&ctx); - if (HMAC_Init_ex(&ctx, key->keyvalue.data, key->keyvalue.length, - EVP_sha1(), NULL) == 0) { - HMAC_CTX_cleanup(&ctx); - return krb5_enomem(context); + ret = _krb5_hmac_start_ossl(context, key->keyvalue.data, key->keyvalue.length, + EVP_sha1(), &ctx); + if (ret == 0 && + EVP_MAC_update(ctx, version_2_0, sizeof(version_2_0)) != 1) { + ret = KRB5KDC_ERR_PREAUTH_FAILED; + } + if (ret == 0 && req->pk_key.length) { + if (EVP_MAC_update(ctx, req->pk_key.data, req->pk_key.length) != 1) + ret = KRB5KDC_ERR_PREAUTH_FAILED; + } else if (ret == 0) { + if (EVP_MAC_update(ctx, req->authenticator.data, + req->authenticator.length) != 1) + ret = KRB5KDC_ERR_PREAUTH_FAILED; + } + if (ret == 0 && + EVP_MAC_final(ctx, digest, &maclen, maclen) != 1) + ret = KRB5KDC_ERR_PREAUTH_FAILED; + EVP_MAC_CTX_free(ctx); + if (ret) { + krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED, + "kx509 could not compute HMAC"); + return ret; } - if (sizeof(digest) != HMAC_size(&ctx)) - krb5_abortx(context, "runtime error, hmac buffer wrong size in kx509"); - HMAC_Update(&ctx, version_2_0, sizeof(version_2_0)); - if (req->pk_key.length) - HMAC_Update(&ctx, req->pk_key.data, req->pk_key.length); - else - HMAC_Update(&ctx, req->authenticator.data, req->authenticator.length); - HMAC_Final(&ctx, digest, 0); - HMAC_CTX_cleanup(&ctx); if (ct_memcmp(req->pk_hash.data, digest, sizeof(digest)) != 0) { krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED, @@ -188,24 +198,20 @@ calculate_reply_hash(krb5_context context, krb5_keyblock *key, Kx509Response *rep) { - krb5_error_code ret = 0; - HMAC_CTX ctx; + krb5_error_code ret; + EVP_MAC_CTX *ctx = NULL; + size_t maclen = SHA_DIGEST_LENGTH; - HMAC_CTX_init(&ctx); - - if (HMAC_Init_ex(&ctx, key->keyvalue.data, key->keyvalue.length, - EVP_sha1(), NULL) == 0) + ret = _krb5_hmac_start_ossl(context, key->keyvalue.data, key->keyvalue.length, + EVP_sha1(), &ctx); + if (ret) ret = krb5_enomem(context); - if (ret == 0) - ret = krb5_data_alloc(rep->hash, HMAC_size(&ctx)); - if (ret) { - HMAC_CTX_cleanup(&ctx); - return krb5_enomem(context); - } - - HMAC_Update(&ctx, version_2_0, sizeof(version_2_0)); - { + ret = krb5_data_alloc(rep->hash, SHA_DIGEST_LENGTH); + if (ret == 0 && + EVP_MAC_update(ctx, version_2_0, sizeof(version_2_0)) != 1) + ret = EINVAL; + if (ret == 0) { int32_t t = rep->error_code; unsigned char encint[sizeof(t) + 1]; size_t k; @@ -224,16 +230,23 @@ calculate_reply_hash(krb5_context context, */ ret = der_put_integer(&encint[sizeof(encint) - 1], sizeof(encint), &t, &k); - if (ret == 0) - HMAC_Update(&ctx, &encint[sizeof(encint)] - k, k); + if (ret == 0 && + EVP_MAC_update(ctx, &encint[sizeof(encint)] - k, k) != 1) + ret = EINVAL; } - if (rep->certificate) - HMAC_Update(&ctx, rep->certificate->data, rep->certificate->length); - if (rep->e_text) - HMAC_Update(&ctx, (unsigned char *)*rep->e_text, strlen(*rep->e_text)); + if (ret == 0 && rep->certificate && + EVP_MAC_update(ctx, rep->certificate->data, + rep->certificate->length) != 1) + ret = EINVAL; + if (ret == 0 && rep->e_text && + EVP_MAC_update(ctx, (unsigned char *)*rep->e_text, + strlen(*rep->e_text)) != 1) + ret = EINVAL; - HMAC_Final(&ctx, rep->hash->data, 0); - HMAC_CTX_cleanup(&ctx); + if (ret == 0 && + EVP_MAC_final(ctx, rep->hash->data, &maclen, maclen) != 1) + ret = EINVAL; + EVP_MAC_CTX_free(ctx); return 0; } diff --git a/kdc/pkinit-ec.c b/kdc/pkinit-ec.c deleted file mode 100644 index 5ef37f4bb..000000000 --- a/kdc/pkinit-ec.c +++ /dev/null @@ -1,525 +0,0 @@ -/* - * Copyright (c) 2016 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Portions Copyright (c) 2009 Apple Inc. 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 -#include - -#ifdef PKINIT - -/* - * As with the other *-ec.c files in Heimdal, this is a bit of a hack. - * - * XXX This is no longer relevant now that we've removed hcrypto. - * - * The idea _was_ to use OpenSSL for EC because hcrypto doesn't have the - * required functionality at this time. To do this we segregate - * EC-using code into separate source files and then we arrange for them - * to get the OpenSSL headers and not the conflicting hcrypto ones. - * - * Because of auto-generated *-private.h headers, we end up needing to - * make sure various types are defined before we include them, thus the - * strange header include order here. - */ - -#include -#include -#include -#include -#include -#include -#include -#ifdef HAVE_OPENSSL_30 -#include -#endif -#define HEIM_NO_CRYPTO_HDRS - -#include "kdc_locl.h" -#include -#include -#include -#include - -#include -#include "../lib/hx509/hx_locl.h" -#include - -void -_kdc_pk_free_client_ec_param(krb5_context context, - void *k0, - void *k1) -{ -#ifdef HAVE_OPENSSL_30 - EVP_PKEY_free(k0); - EVP_PKEY_free(k1); -#else - EC_KEY_free(k0); - EC_KEY_free(k1); -#endif -} - -#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_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; - krb5_keyblock key; - krb5_error_code ret; - unsigned char *p; - size_t size; - int len; - - *dh_gen_key = NULL; - *dh_gen_keylen = 0; - *ec_key_key = NULL; - - memset(&key, 0, sizeof(key)); - - if (ec_key_pk == NULL) { - ret = KRB5KRB_ERR_GENERIC; - krb5_set_error_message(context, ret, "public_key"); - return ret; - } - - group = EC_KEY_get0_group(ec_key_pk); - if (group == NULL) { - ret = KRB5KRB_ERR_GENERIC; - krb5_set_error_message(context, ret, "failed to get the group of " - "the client's public key"); - return ret; - } - - ephemeral = EC_KEY_new(); - if (ephemeral == NULL) - return krb5_enomem(context); - - EC_KEY_set_group(ephemeral, group); - - if (EC_KEY_generate_key(ephemeral) != 1) { - EC_KEY_free(ephemeral); - return krb5_enomem(context); - } - - size = (EC_GROUP_get_degree(group) + 7) / 8; - p = malloc(size); - if (p == NULL) { - EC_KEY_free(ephemeral); - return krb5_enomem(context); - } - - len = ECDH_compute_key(p, size, - EC_KEY_get0_public_key(ec_key_pk), - ephemeral, NULL); - if (len <= 0) { - free(p); - EC_KEY_free(ephemeral); - ret = KRB5KRB_ERR_GENERIC; - krb5_set_error_message(context, ret, "Failed to compute ECDH " - "public shared secret"); - return ret; - } - - *ec_key_key = ephemeral; - *dh_gen_key = p; - *dh_gen_keylen = len; - - return 0; -} -#endif - -krb5_error_code -_kdc_generate_ecdh_keyblock(krb5_context context, - void *ec_key_pk, /* the client's public key */ - void **ec_key_key, /* the KDC's ephemeral private */ - unsigned char **dh_gen_key, /* shared secret */ - size_t *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 -} - -#ifdef HAVE_OPENSSL_30 -static krb5_error_code -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; - krb5_error_code ret; - const unsigned char *p; - size_t len; - 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; - } - /* 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); - if (ret) - goto out; - - if (ecp.element != choice_ECParameters_namedCurve) { - 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; - else { - ret = KRB5_BADMSGTYPE; - goto out; - } - - /* XXX verify group is ok */ - - public = EC_KEY_new_by_curve_name(nid); - - 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; - } - *out = public; - public = NULL; - - out: - if (public) - EC_KEY_free(public); - free_ECParameters(&ecp); - return ret; -} -#endif - -krb5_error_code -_kdc_get_ecdh_param(krb5_context context, - krb5_kdc_configuration *config, - SubjectPublicKeyInfo *dh_key_info, - void **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 -} - - -/* - * - */ - -#ifdef HAVE_OPENSSL_30 -static krb5_error_code -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) -{ - unsigned char *p; - int len; - - *out = NULL; - *out_len = 0; - - len = i2o_ECPublicKey(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 = i2o_ECPublicKey(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; -} -#endif - -krb5_error_code -_kdc_serialize_ecdh_key(krb5_context context, - void *key, - unsigned char **out, - size_t *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 -} - -#endif diff --git a/kdc/pkinit.c b/kdc/pkinit.c index fd0b20fc0..861044bfe 100644 --- a/kdc/pkinit.c +++ b/kdc/pkinit.c @@ -48,16 +48,8 @@ struct pk_client_params { enum krb5_pk_type type; enum keyex_enum keyex; - union { - struct { - BIGNUM *public_key; - DH *key; - } dh; - struct { - void *public_key; - void *key; - } ecdh; - } u; + EVP_PKEY *peer_pkey; + EVP_PKEY *us_pkey; hx509_cert cert; krb5_timestamp endtime; krb5_timestamp max_life; @@ -67,6 +59,9 @@ struct pk_client_params { hx509_peer_info peer; hx509_certs client_anchors; hx509_verify_ctx verify_ctx; + const heim_oid *kdf; + unsigned char *raw_shared_secret; + size_t raw_shared_secret_len; }; struct pk_principal_mapping { @@ -91,6 +86,342 @@ static struct { * */ +/* + * Find a KDC certificate. + * + * If the client has a certificate then prefer a KDC certificate whose SPKI + * algorithm matches the client's. This allows automatic algorithm selection: + * as clients get new certificates with better SPKI algorithms, they will work + * automatically provided the KDC has matching certificates. Administrators + * then need only provision all their KDCs with certificates with SPKI + * algorithms for all currently-in-use client certificates that the KDCs must + * accept. + * + * In all other cases pick the first available KDC certificate. + */ +static int +find_kdc_cert(krb5_context context, + krb5_kdc_configuration *config, + pk_client_params *cp, + hx509_cert *certp) +{ + AlgorithmIdentifier client_alg; + hx509_query *q; + int ret; + int have_client_alg = 0; + + *certp = NULL; + memset(&client_alg, 0, sizeof(client_alg)); + + ret = hx509_query_alloc(context->hx509ctx, &q); + if (ret) + return ret; + + hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY); + if (config->pkinit_kdc_friendly_name) + hx509_query_match_friendly_name(q, config->pkinit_kdc_friendly_name); + + /* + * If the client has a certificate, try to find a KDC certificate + * with a matching SPKI algorithm first. + */ + if (cp->cert) { + ret = hx509_cert_get_SPKI_AlgorithmIdentifier(context->hx509ctx, + cp->cert, + &client_alg); + if (ret == 0) { + have_client_alg = 1; + + ret = hx509_query_match_key_algorithm(q, &client_alg.algorithm); + if (ret) { + free_AlgorithmIdentifier(&client_alg); + hx509_query_free(context->hx509ctx, q); + return ret; + } + + ret = hx509_certs_find(context->hx509ctx, + kdc_identity->certs, + q, + certp); + if (ret == 0) { + /* Found a certificate matching client's SPKI algorithm */ + free_AlgorithmIdentifier(&client_alg); + hx509_query_free(context->hx509ctx, q); + return 0; + } + + /* Clear the key algorithm match for fallback */ + hx509_query_match_key_algorithm(q, NULL); + } + } + + /* + * Fallback: find any matching certificate without key algorithm preference + */ + ret = hx509_certs_find(context->hx509ctx, + kdc_identity->certs, + q, + certp); + + if (have_client_alg) + free_AlgorithmIdentifier(&client_alg); + hx509_query_free(context->hx509ctx, q); + return ret; +} + +static krb5_error_code +check_dh_param(krb5_context, krb5_kdc_configuration *, SubjectPublicKeyInfo *, + pk_client_params *); + +static krb5_error_code +gen_eph_for_peer_spki(astgs_request_t r, SubjectPublicKeyInfo *spki, + pk_client_params *cp, + EVP_PKEY **peer, EVP_PKEY **eph) +{ + EVP_PKEY_CTX *kctx = NULL; + krb5_error_code ret = 0; + const char *sn; + size_t clen = 0; + + *peer = *eph = NULL; + + { + const unsigned char *p = spki->_save.data; + *peer = d2i_PUBKEY(NULL, &p, spki->_save.length); + if (!*peer) { + char *s = _krb5_openssl_errors(); + + _kdc_set_e_text(r, "PKINIT: key agreement failed: " + "could not parse client key share SPKI: %s", + s ? s : ""); + free(s); + return KRB5_KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED; + } + } + + switch (EVP_PKEY_base_id(*peer)) { + case EVP_PKEY_X25519: + kdc_audit_addkv((kdc_request_t)r, 0, "keyagreement", "x25519"); + if (!krb5_config_get_bool_default(r->context, NULL, 1, "kdc", + "pkinit_allow_ecdh", "x25519", + NULL)) { + _kdc_set_e_text(r, "PKINIT: X25519 not allowed"); + ret = KRB5_KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED; + goto out; + } + break; + case EVP_PKEY_X448: + kdc_audit_addkv((kdc_request_t)r, 0, "keyagreement", "x448"); + if (!krb5_config_get_bool_default(r->context, NULL, 1, "kdc", + "pkinit_allow_ecdh", "x448", NULL)) { + _kdc_set_e_text(r, "PKINIT: X448 not allowed"); + ret = KRB5_KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED; + goto out; + } + break; + case EVP_PKEY_EC: { + char curve[128]; + if (EVP_PKEY_get_utf8_string_param(*peer, OSSL_PKEY_PARAM_GROUP_NAME, + curve, sizeof(curve), &clen) != 1) { + _kdc_set_e_text(r, "PKINIT: unknown ECDH curve"); + kdc_audit_addkv((kdc_request_t)r, 0, "keyagreement", "unknown"); + ret = KRB5_KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED; + goto out; + } + kdc_audit_addkv((kdc_request_t)r, 0, "keyagreement", "%s", curve); + if (!krb5_config_get_bool_default(r->context, NULL, 1, "kdc", + "pkinit_allow_ecdh", curve, NULL)) { + _kdc_set_e_text(r, "PKINIT: ECDH curve not allowed: %s", curve); + ret = KRB5_KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED; + goto out; + } + break; + } + case EVP_PKEY_DH: + case EVP_PKEY_DHX: { + int minbits = krb5_config_get_int_default(r->context, NULL, 0, + "kdc", "pkinit_dh_min_bits", + NULL); + int bits; + + /* + * RFC 4556 specifies X9.42 DH (id-dhpublicnumber, which OpenSSL calls + * EVP_PKEY_DHX), but a peer could send PKCS#3 DH (which OpenSSL calls + * EVP_PKEY_DH). We accept either, and either way check that the + * parameters are acceptable. + */ + bits = EVP_PKEY_get_bits(*peer); + if (minbits > 0 && bits < minbits) { + _kdc_set_e_text(r, "PKINIT: DH group too small (%d)", bits); + ret = KRB5_KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED; + goto out; + } + /* + * Check the client's choice of p/g/q against the moduli file or + * builtins + */ + ret = check_dh_param(r->context, r->config, spki, cp); + kdc_audit_addkv((kdc_request_t)r, 0, "keyagreement", "%s", + cp->dh_group_name ? cp->dh_group_name : "unknown"); + break; + } + default: + /* Unknown (to us) key agreement algorithm */ + kdc_audit_addkv((kdc_request_t)r, 0, "keyagreement", "unknown"); + sn = OBJ_nid2sn(EVP_PKEY_base_id(*peer)); + _kdc_set_e_text(r, "PKINIT: key agreement algorithm not supported: %s", + sn ? sn : ""); + ret = KRB5_KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED; + goto out; + } + + kctx = EVP_PKEY_CTX_new_from_pkey(r->context->ossl->libctx, *peer, + r->context->ossl->propq); + if (!kctx) { + ret = EINVAL; + goto out; + } + + /* This works for all key agreement types! */ + if (EVP_PKEY_keygen_init(kctx) <= 0 || + EVP_PKEY_keygen(kctx, eph) <= 0) { + ret = EINVAL; + goto out; + } + +out: + if (ret) { + EVP_PKEY_free(*peer); + *peer = NULL; + if (ret == EINVAL) { + char *s = _krb5_openssl_errors(); + + _kdc_set_e_text(r, "PKINIT: key agreement failed: %s", + s ? s : ""); + free(s); + ret = KRB5_CRYPTO_INTERNAL; + } + } + EVP_PKEY_CTX_free(kctx); + return ret; +} + +static krb5_error_code +generate_key_agreement_keyblock(astgs_request_t r, + EVP_PKEY *pub, /* the client's public key */ + EVP_PKEY *priv, /* the KDC's ephemeral private */ + unsigned char **shared_secret, /* shared secret */ + size_t *shared_secret_len) +{ + EVP_PKEY_CTX *pctx = NULL; + krb5_error_code ret = 0; + unsigned char *p = NULL; + size_t size = 0; + int oret; + + if ((pctx = EVP_PKEY_CTX_new_from_pkey(r->context->ossl->libctx, priv, + r->context->ossl->propq)) == NULL) + return krb5_enomem(r->context); + if (EVP_PKEY_derive_init(pctx) != 1) + ret = krb5_enomem(r->context); + if (ret == 0 && + (oret = EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, EVP_PKEY_ECDH_KDF_NONE)) != 1 && + oret != -2) + krb5_set_error_message(r->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, pub, 1) != 1) + krb5_set_error_message(r->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(r->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(r->context); + if (ret == 0 && + (EVP_PKEY_derive(pctx, p, &size) != 1 || size == 0)) + krb5_set_error_message(r->context, ret = KRB5KRB_ERR_GENERIC, + "Could not generate an ECDH key agreement private key " + "(EVP_PKEY_derive)"); + + if (ret) { + if (p) + memset_s(p, size, 0, size); + free(p); + p = NULL; + size = 0; + } + + *shared_secret_len = size; + *shared_secret = p; + + EVP_PKEY_CTX_free(pctx); + return ret; +} + +/* + * Serialize the public key from an EVP_PKEY for a key share. + * + * OpenSSL 3.x doesn't support i2d_PublicKey() for DH keys and + * EVP_PKEY_get_octet_string_param() doesn't work either. Instead we use + * i2d_PUBKEY() (which works for all key types) to get the SubjectPublicKeyInfo, + * then decode it to extract the subjectPublicKey bit string. + */ +static krb5_error_code +serialize_key_share(krb5_context context, + EVP_PKEY *key, + unsigned char **out, + size_t *out_len) +{ + SubjectPublicKeyInfo spki; + krb5_error_code ret; + unsigned char *buf = NULL; + unsigned char *p; + size_t len, size; + + *out = NULL; + *out_len = 0; + + /* Encode as SubjectPublicKeyInfo using i2d_PUBKEY (works for all types) */ + len = i2d_PUBKEY(key, NULL); + if (len <= 0) + return _krb5_set_error_message_openssl(context, KRB5_CRYPTO_INTERNAL, + "PKINIT failed to encode public key"); + + p = buf = malloc(len); + if (p == NULL) + return krb5_enomem(context); + + if (i2d_PUBKEY(key, &p) != (int)len) { + free(buf); + return _krb5_set_error_message_openssl(context, KRB5_CRYPTO_INTERNAL, + "PKINIT failed to encode public key"); + } + + /* Decode to extract the subjectPublicKey */ + memset(&spki, 0, sizeof(spki)); + ret = decode_SubjectPublicKeyInfo(buf, len, &spki, &size); + free(buf); + if (ret) + return ret; + + /* Copy the subjectPublicKey bit string data */ + *out = malloc((spki.subjectPublicKey.length + 7) / 8); + if (*out == NULL) { + free_SubjectPublicKeyInfo(&spki); + return krb5_enomem(context); + } + memcpy(*out, spki.subjectPublicKey.data, (spki.subjectPublicKey.length + 7) / 8); + *out_len = spki.subjectPublicKey.length; + + free_SubjectPublicKeyInfo(&spki); + return 0; +} + static krb5_error_code pk_check_pkauthenticator_win2k(krb5_context context, PKAuthenticator_Win2k *a, @@ -163,15 +494,8 @@ _kdc_pk_free_client_param(krb5_context context, pk_client_params *cp) hx509_cert_free(cp->cert); if (cp->verify_ctx) hx509_verify_destroy_ctx(cp->verify_ctx); - if (cp->keyex == USE_DH) { - if (cp->u.dh.key) - DH_free(cp->u.dh.key); - if (cp->u.dh.public_key) - BN_free(cp->u.dh.public_key); - } - if (cp->keyex == USE_ECDH) - _kdc_pk_free_client_ec_param(context, cp->u.ecdh.key, - cp->u.ecdh.public_key); + EVP_PKEY_free(cp->peer_pkey); + EVP_PKEY_free(cp->us_pkey); krb5_free_keyblock_contents(context, &cp->reply_key); if (cp->dh_group_name) free(cp->dh_group_name); @@ -179,115 +503,77 @@ _kdc_pk_free_client_param(krb5_context context, pk_client_params *cp) hx509_peer_info_free(cp->peer); if (cp->client_anchors) hx509_certs_free(&cp->client_anchors); + if (cp->raw_shared_secret) + memset_s(cp->raw_shared_secret, cp->raw_shared_secret_len, + 0, cp->raw_shared_secret_len); + free(cp->raw_shared_secret); memset(cp, 0, sizeof(*cp)); free(cp); } static krb5_error_code -generate_dh_keyblock(krb5_context context, - pk_client_params *client_params, +generate_dh_keyblock(astgs_request_t r, + pk_client_params *client_params, + void *pk_as_rep, + size_t pk_as_rep_len, krb5_enctype enctype) { - unsigned char *dh_gen_key = NULL; - krb5_keyblock key; krb5_error_code ret; - size_t dh_gen_keylen, size; + krb5_data rep; - memset(&key, 0, sizeof(key)); + rep.data = pk_as_rep; + rep.length = pk_as_rep_len; - if (client_params->keyex == USE_DH) { - - if (client_params->u.dh.public_key == NULL) { - ret = KRB5KRB_ERR_GENERIC; - krb5_set_error_message(context, ret, "missing DH public_key"); - goto out; - } - - if (!DH_generate_key(client_params->u.dh.key)) { - ret = KRB5KRB_ERR_GENERIC; - krb5_set_error_message(context, ret, - "Can't generate Diffie-Hellman keys"); - goto out; - } - - size = DH_size(client_params->u.dh.key); - - dh_gen_key = malloc(size); - if (dh_gen_key == NULL) { - ret = ENOMEM; - krb5_set_error_message(context, ret, "malloc: out of memory"); - goto out; - } - - dh_gen_keylen = DH_compute_key(dh_gen_key,client_params->u.dh.public_key, client_params->u.dh.key); - if (dh_gen_keylen == (size_t)-1) { - ret = KRB5KRB_ERR_GENERIC; - krb5_set_error_message(context, ret, - "Can't compute Diffie-Hellman key"); - goto out; - } - if (dh_gen_keylen < size) { - size -= dh_gen_keylen; - memmove(dh_gen_key + size, dh_gen_key, dh_gen_keylen); - memset(dh_gen_key, 0, size); - } - } else if (client_params->keyex == USE_ECDH) { - if (client_params->u.ecdh.public_key == NULL) { - ret = KRB5KRB_ERR_GENERIC; - krb5_set_error_message(context, ret, "missing ECDH public_key"); - goto out; - } - ret = _kdc_generate_ecdh_keyblock(context, - client_params->u.ecdh.public_key, - &client_params->u.ecdh.key, - &dh_gen_key, &dh_gen_keylen); - if (ret) - goto out; - } else { + if (client_params->keyex != USE_DH && client_params->keyex != USE_ECDH) { ret = KRB5KRB_ERR_GENERIC; - krb5_set_error_message(context, ret, + krb5_set_error_message(r->context, ret = KRB5KRB_ERR_GENERIC, "Diffie-Hellman not selected keys"); - goto out; + return ret; } - ret = _krb5_pk_octetstring2key(context, - enctype, - dh_gen_key, dh_gen_keylen, - NULL, NULL, - &client_params->reply_key); + ret = generate_key_agreement_keyblock(r, client_params->peer_pkey, + client_params->us_pkey, + &client_params->raw_shared_secret, + &client_params->raw_shared_secret_len); + if (ret) + return ret; - out: - if (dh_gen_key) - free(dh_gen_key); - if (key.keyvalue.data) - krb5_free_keyblock_contents(context, &key); + if (client_params->kdf) { + const char *n = NULL; + char *s = NULL; + (void) der_find_heim_oid_by_oid(client_params->kdf, &n); + if (n == NULL) + (void) der_print_heim_oid_sym(client_params->kdf, '.', &s); + + if (n == NULL) + n = s; + if (n == NULL) + n = "unknown"; + kdc_audit_addkv((kdc_request_t)r, 0, "kdf", "%s", n); + free(s); + } else { + kdc_audit_addkv((kdc_request_t)r, 0, "kdf", "RFC4556"); + } + + ret = _krb5_pk_kdf(r->context, client_params->kdf, + client_params->raw_shared_secret, + client_params->raw_shared_secret_len, + r->client_princ, r->server_princ, enctype, + /* We don't support DH key reuse; we expect no nonces */ + NULL, NULL, + &r->request /* or &r->kdc_req._save */, + &rep, NULL, &client_params->reply_key); return ret; } -static BIGNUM * -integer_to_BN(krb5_context context, const char *field, heim_integer *f) -{ - BIGNUM *bn; - - bn = BN_bin2bn((const unsigned char *)f->data, f->length, NULL); - if (bn == NULL) { - krb5_set_error_message(context, KRB5_BADMSGTYPE, - "PKINIT: parsing BN failed %s", field); - return NULL; - } - BN_set_negative(bn, f->negative); - return bn; -} - static krb5_error_code -get_dh_param(krb5_context context, - krb5_kdc_configuration *config, - SubjectPublicKeyInfo *dh_key_info, - pk_client_params *client_params) +check_dh_param(krb5_context context, + krb5_kdc_configuration *config, + SubjectPublicKeyInfo *dh_key_info, + pk_client_params *cp) { DomainParameters dhparam; - DH *dh = NULL; krb5_error_code ret; memset(&dhparam, 0, sizeof(dhparam)); @@ -301,10 +587,10 @@ get_dh_param(krb5_context context, } if (dh_key_info->algorithm.parameters == NULL) { - krb5_set_error_message(context, KRB5_BADMSGTYPE, + krb5_set_error_message(context, ret = KRB5_BADMSGTYPE, "PKINIT missing algorithm parameter " "in clientPublicValue"); - return KRB5_BADMSGTYPE; + goto out; } ret = decode_DomainParameters(dh_key_info->algorithm.parameters->data, @@ -319,66 +605,118 @@ get_dh_param(krb5_context context, ret = _krb5_dh_group_ok(context, config->pkinit_dh_min_bits, &dhparam.p, &dhparam.g, dhparam.q, moduli, - &client_params->dh_group_name); + &cp->dh_group_name); if (ret) { - /* XXX send back proposal of better group */ + /* + * XXX send back proposal of better group, i.e., send back a TypedData + * in e-data of type TD-DH-PARAMETERS listing: all supported curves and + * the smallest supported DH group (or all of them?). + */ goto out; } - dh = DH_new(); - if (dh == NULL) { - ret = ENOMEM; - krb5_set_error_message(context, ret, "Cannot create DH structure"); - goto out; - } - ret = KRB5_BADMSGTYPE; - dh->p = integer_to_BN(context, "DH prime", &dhparam.p); - if (dh->p == NULL) - goto out; - dh->g = integer_to_BN(context, "DH base", &dhparam.g); - if (dh->g == NULL) - goto out; - - if (dhparam.q) { - dh->q = integer_to_BN(context, "DH p-1 factor", dhparam.q); - if (dh->q == NULL) - goto out; - } - - { - heim_integer glue; - size_t size; - - ret = decode_DHPublicKey(dh_key_info->subjectPublicKey.data, - dh_key_info->subjectPublicKey.length / 8, - &glue, - &size); - if (ret) { - krb5_clear_error_message(context); - return ret; - } - - client_params->u.dh.public_key = integer_to_BN(context, - "subjectPublicKey", - &glue); - der_free_heim_integer(&glue); - if (client_params->u.dh.public_key == NULL) { - ret = KRB5_BADMSGTYPE; - goto out; - } - } - - client_params->u.dh.key = dh; - dh = NULL; - ret = 0; - out: - if (dh) - DH_free(dh); + if (ret) { + EVP_PKEY_free(cp->peer_pkey); + EVP_PKEY_free(cp->us_pkey); + cp->peer_pkey = cp->us_pkey = NULL; + } free_DomainParameters(&dhparam); return ret; } +static krb5_error_code +select_kdf(krb5_context context, + krb5_kdc_configuration *config, + AuthPack *ap, + pk_client_params *cp) +{ + krb5_boolean rfc4556_kdf = + krb5_config_get_bool_default(context, NULL, 1 /* for now */, + "kdc", "pkinit_enable_rfc4556_kdf", NULL); + krb5_boolean kdf_ah_sha1; + krb5_boolean kdf_ah_sha256; + krb5_boolean kdf_ah_sha384; + krb5_boolean kdf_ah_sha512; + size_t accepted = 0; + size_t i; + + if (ap->supportedKDFs == NULL) { + cp->kdf = NULL; + if (!rfc4556_kdf) + return KRB5_KDC_ERR_NO_ACCEPTABLE_KDF; + /* Client is or is configured to act like a pre-RFC 8636 client */ + return 0; + } + + kdf_ah_sha1 = krb5_config_get_bool_default(context, NULL, 1, "kdc", + "pkinit_enable_kdf_ah_sha1", + NULL); + kdf_ah_sha256 = krb5_config_get_bool_default(context, NULL, 1, "kdc", + "pkinit_enable_kdf_ah_sha256", + NULL); + kdf_ah_sha384 = krb5_config_get_bool_default(context, NULL, 1, "kdc", + "pkinit_enable_kdf_ah_sha384", + NULL); + kdf_ah_sha512 = krb5_config_get_bool_default(context, NULL, 1, "kdc", + "pkinit_enable_kdf_ah_sha512", + NULL); + + for (i = 0; i < ap->supportedKDFs->len; i++) { + if (der_heim_oid_cmp(&asn1_oid_id_pkinit_kdf_ah_sha1, + &ap->supportedKDFs->val[i].kdf_id) == 0) { + kdc_log(context, config, 2, "Client offered PKINIT SHA-1 KDF"); + accepted |= ((size_t)!!kdf_ah_sha1)<<0; + continue; + } + if (der_heim_oid_cmp(&asn1_oid_id_pkinit_kdf_ah_sha256, + &ap->supportedKDFs->val[i].kdf_id) == 0) { + kdc_log(context, config, 2, "Client offered PKINIT SHA-256 KDF"); + accepted |= ((size_t)!!kdf_ah_sha256)<<1; + continue; + } + if (der_heim_oid_cmp(&asn1_oid_id_pkinit_kdf_ah_sha384, + &ap->supportedKDFs->val[i].kdf_id) == 0) { + kdc_log(context, config, 2, "Client offered PKINIT SHA-384 KDF"); + accepted |= ((size_t)!!kdf_ah_sha384)<<2; + continue; + } + if (der_heim_oid_cmp(&asn1_oid_id_pkinit_kdf_ah_sha512, + &ap->supportedKDFs->val[i].kdf_id) == 0) { + kdc_log(context, config, 2, "Client offered PKINIT SHA-512 KDF"); + accepted |= ((size_t)!!kdf_ah_sha512)<<3; + } + } + + if (accepted & (1UL<<3)) { + kdc_log(context, config, 2, "Accepted PKINIT SHA-512 KDF"); + cp->kdf = &asn1_oid_id_pkinit_kdf_ah_sha512; + return 0; + } + if (accepted & (1UL<<2)) { + kdc_log(context, config, 2, "Accepted PKINIT SHA-384 KDF"); + cp->kdf = &asn1_oid_id_pkinit_kdf_ah_sha384; + return 0; + } + if (accepted & (1UL<<1)) { + kdc_log(context, config, 2, "Accepted PKINIT SHA-256 KDF"); + cp->kdf = &asn1_oid_id_pkinit_kdf_ah_sha256; + return 0; + } + if (accepted & (1UL<<0)) { + kdc_log(context, config, 2, "Accepted PKINIT SHA-1 KDF"); + cp->kdf = &asn1_oid_id_pkinit_kdf_ah_sha1; + return 0; + } + + kdc_log(context, config, 0, + "No PKINIT KDFs offered by the client accepted"); + krb5_set_error_message(context, KRB5_KDC_ERR_NO_ACCEPTABLE_KDF, + "No PKINIT KDFs offered by the client accepted"); + cp->kdf = NULL; + return KRB5_KDC_ERR_NO_ACCEPTABLE_KDF; +} + krb5_error_code _kdc_pk_rd_padata(astgs_request_t priv, const PA_DATA *pa, @@ -631,7 +969,55 @@ _kdc_pk_rd_padata(astgs_request_t priv, char *s = hx509_get_error_string(context->hx509ctx, ret); krb5_warnx(context, "PKINIT: failed to verify signature: %s: %d", s, ret); + _kdc_set_e_text(priv, "PKINIT: failed to verify signature: %s: %d", + s, ret); free(s); + /* + * An attempt at a decent mapping of hx509 errors to RFC 4120/4556 + * errors. + */ + switch (ret) { + case HX509_CRYPTO_SIG_NO_CONF: + case HX509_CRYPTO_SIG_INVALID_FORMAT: + case HX509_CRYPTO_SIGNATURE_WITHOUT_SIGNER: + case HX509_CMS_SIGNER_NOT_FOUND: + case HX509_CRYPTO_BAD_SIGNATURE: + ret = KRB5_KDC_ERR_CANT_VERIFY_CERTIFICATE; + break; + case HX509_CERT_USED_BEFORE_TIME: + case HX509_CERT_USED_AFTER_TIME: + ret = KRB5_KDC_ERR_INVALID_CERTIFICATE; + break; + case HX509_SIG_ALG_NO_SUPPORTED: + ret = KRB5_KDC_ERR_INVALID_SIG; + break; + case HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED: + /* + * We don't have a good hx509 error for distinguishing the + * digest of the signature algorithm vs. the signature + * algorithm. Oh well. + */ + ret = KRB5_KDC_ERR_DIGEST_IN_CERT_NOT_ACCEPTED; + break; + case HX509_CERT_REVOKED: + ret = KRB5_KDC_ERR_REVOKED_CERTIFICATE; + break; + case HX509_REVOKE_STATUS_MISSING: + case HX509_CERT_NOT_IN_OCSP: + ret = KRB5_KDC_ERR_REVOCATION_STATUS_UNKNOWN; + break; + case HX509_PARSING_KEY_FAILED: + case HX509_CA_PATH_TOO_DEEP: + case HX509_SIG_ALG_DONT_MATCH_KEY_ALG: + case HX509_CERT_NOT_FOUND: + case HX509_PATH_TOO_LONG: + case HX509_KU_CERT_MISSING: + case HX509_CERTIFICATE_MALFORMED: + case HX509_NO_PATH: /* and many others */ + default: + ret = KRB5_KDC_ERR_CLIENT_NOT_TRUSTED; + break; + } goto out; } @@ -721,29 +1107,60 @@ _kdc_pk_rd_padata(astgs_request_t priv, cp->nonce = ap.pkAuthenticator.nonce; if (ap.clientPublicValue) { - if (der_heim_oid_cmp(&ap.clientPublicValue->algorithm.algorithm, &asn1_oid_id_dhpublicnumber) == 0) { - cp->keyex = USE_DH; - ret = get_dh_param(context, config, - ap.clientPublicValue, cp); - } else if (der_heim_oid_cmp(&ap.clientPublicValue->algorithm.algorithm, &asn1_oid_id_ecPublicKey) == 0) { - cp->keyex = USE_ECDH; - ret = _kdc_get_ecdh_param(context, config, - ap.clientPublicValue, - &cp->u.ecdh.public_key); - } else { + const heim_oid *offered = &ap.clientPublicValue->algorithm.algorithm; + + ret = 0; + if (der_heim_oid_cmp(offered, &asn1_oid_id_dhpublicnumber) == 0) { + cp->keyex = USE_DH; + } else if (der_heim_oid_cmp(offered, &asn1_oid_id_X25519) == 0) { + cp->keyex = USE_ECDH; + } else if (der_heim_oid_cmp(offered, &asn1_oid_id_X448) == 0) { + cp->keyex = USE_ECDH; + } else if (der_heim_oid_cmp(offered, &asn1_oid_id_ecPublicKey) == 0) { + cp->keyex = USE_ECDH; + } else if (der_heim_oid_cmp(offered, &asn1_oid_id_ec_group_secp256r1) == 0) { + cp->keyex = USE_ECDH; + } else if (der_heim_oid_cmp(offered, &asn1_oid_id_ec_group_secp384r1) == 0) { + cp->keyex = USE_ECDH; + } else if (der_heim_oid_cmp(offered, &asn1_oid_id_ec_group_secp521r1) == 0) { + cp->keyex = USE_ECDH; + } else { + ret = KRB5_KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED; + goto out; + } + + /* + * Parsing the client's key share SPKI and generating an ephemeral + * for our side is now generic via OpenSSL 3.x APIs, so we do it + * here. + */ + ret = gen_eph_for_peer_spki(priv, + ap.clientPublicValue, cp, + &cp->peer_pkey, &cp->us_pkey); + if (ret) { ret = KRB5_BADMSGTYPE; krb5_set_error_message(context, ret, - "PKINIT unknown DH mechanism"); + "PKINIT unknown key agreement (DH) mechanism"); } if (ret) { free_AuthPack(&ap); goto out; } - } else - cp->keyex = USE_RSA; + } else { + if (!krb5_config_get_bool_default(context, NULL, + FALSE, + "kdc", + "pkinit_allow_rsa_key_transport", + NULL)) { + ret = KRB5_KDC_ERR_PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED; + krb5_set_error_message(context, ret, + "PKINIT RSA key transport is disabled"); + goto out; + } + cp->keyex = USE_RSA; + } - ret = hx509_peer_info_alloc(context->hx509ctx, - &cp->peer); + ret = hx509_peer_info_alloc(context->hx509ctx, &cp->peer); if (ret) { free_AuthPack(&ap); goto out; @@ -760,13 +1177,23 @@ _kdc_pk_rd_padata(astgs_request_t priv, } } else { /* assume old client */ - hx509_peer_info_add_cms_alg(context->hx509ctx, cp->peer, - hx509_crypto_des_rsdi_ede3_cbc()); - hx509_peer_info_add_cms_alg(context->hx509ctx, cp->peer, - hx509_signature_rsa_with_sha1()); - hx509_peer_info_add_cms_alg(context->hx509ctx, cp->peer, - hx509_signature_sha1()); + ret = hx509_peer_info_add_cms_alg(context->hx509ctx, cp->peer, + hx509_crypto_des_rsdi_ede3_cbc()); + if (ret) + goto out; + ret = hx509_peer_info_add_cms_alg(context->hx509ctx, cp->peer, + hx509_signature_rsa_with_sha1()); + if (ret) + goto out; + ret = hx509_peer_info_add_cms_alg(context->hx509ctx, cp->peer, + hx509_signature_sha1()); + if (ret) + goto out; } + + ret = select_kdf(context, config, &ap, cp); + if (ret) + goto out; free_AuthPack(&ap); } else krb5_abortx(context, "internal pkinit error"); @@ -805,20 +1232,6 @@ _kdc_pk_max_life(pk_client_params *pkp) * */ -static krb5_error_code -BN_to_integer(krb5_context context, BIGNUM *bn, heim_integer *integer) -{ - integer->length = BN_num_bytes(bn); - integer->data = malloc(integer->length); - if (integer->data == NULL) { - krb5_clear_error_message(context); - return ENOMEM; - } - BN_bn2bin(bn, integer->data); - integer->negative = BN_is_negative(bn); - return 0; -} - static krb5_error_code pk_mk_pa_reply_enckey(krb5_context context, krb5_kdc_configuration *config, @@ -924,22 +1337,9 @@ pk_mk_pa_reply_enckey(krb5_context context, krb5_abortx(context, "Internal ASN.1 encoder error"); { - hx509_query *q; hx509_cert cert; - ret = hx509_query_alloc(context->hx509ctx, &q); - if (ret) - goto out; - - hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY); - if (config->pkinit_kdc_friendly_name) - hx509_query_match_friendly_name(q, config->pkinit_kdc_friendly_name); - - ret = hx509_certs_find(context->hx509ctx, - kdc_identity->certs, - q, - &cert); - hx509_query_free(context->hx509ctx, q); + ret = find_kdc_cert(context, config, cp, &cert); if (ret) goto out; @@ -1011,7 +1411,7 @@ pk_mk_pa_reply_dh(krb5_context context, ContentInfo contentinfo; krb5_error_code ret; hx509_cert cert; - hx509_query *q; + unsigned char *p = NULL; size_t size = 0; memset(&contentinfo, 0, sizeof(contentinfo)); @@ -1021,37 +1421,11 @@ pk_mk_pa_reply_dh(krb5_context context, *kdc_cert = NULL; - if (cp->keyex == USE_DH) { - DH *kdc_dh = cp->u.dh.key; - heim_integer i; - - ret = BN_to_integer(context, kdc_dh->pub_key, &i); - if (ret) - return ret; - - ASN1_MALLOC_ENCODE(DHPublicKey, buf.data, buf.length, &i, &size, ret); - der_free_heim_integer(&i); - if (ret) { - krb5_set_error_message(context, ret, "ASN.1 encoding of " - "DHPublicKey failed (%d)", ret); - return ret; - } - if (buf.length != size) - krb5_abortx(context, "Internal ASN.1 encoder error"); - - dh_info.subjectPublicKey.length = buf.length * 8; - dh_info.subjectPublicKey.data = buf.data; - krb5_data_zero(&buf); - } else if (cp->keyex == USE_ECDH) { - unsigned char *p; - ret = _kdc_serialize_ecdh_key(context, cp->u.ecdh.key, &p, - &dh_info.subjectPublicKey.length); - if (ret) - goto out; - dh_info.subjectPublicKey.data = p; - } else - krb5_abortx(context, "no keyex selected ?"); - + ret = serialize_key_share(context, cp->us_pkey, + &p, &dh_info.subjectPublicKey.length); + if (ret) + goto out; + dh_info.subjectPublicKey.data = p; dh_info.nonce = cp->nonce; @@ -1070,19 +1444,7 @@ pk_mk_pa_reply_dh(krb5_context context, * filled in above */ - ret = hx509_query_alloc(context->hx509ctx, &q); - if (ret) - goto out; - - hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY); - if (config->pkinit_kdc_friendly_name) - hx509_query_match_friendly_name(q, config->pkinit_kdc_friendly_name); - - ret = hx509_certs_find(context->hx509ctx, - kdc_identity->certs, - q, - &cert); - hx509_query_free(context->hx509ctx, q); + ret = find_kdc_cert(context, config, cp, &cert); if (ret) goto out; @@ -1175,6 +1537,7 @@ _kdc_pk_mk_pa_reply(astgs_request_t r, pk_client_params *cp) if (cp->keyex == USE_RSA) { ContentInfo info; + memset(&info, 0, sizeof(info)); type = "enckey"; rep.element = choice_PA_PK_AS_REP_encKeyPack; @@ -1220,6 +1583,7 @@ _kdc_pk_mk_pa_reply(astgs_request_t r, pk_client_params *cp) } else { ContentInfo info; + memset(&info, 0, sizeof(info)); switch (cp->keyex) { case USE_DH: type = "dh"; break; case USE_ECDH: type = "ecdh"; break; @@ -1231,10 +1595,6 @@ _kdc_pk_mk_pa_reply(astgs_request_t r, pk_client_params *cp) rep.element = choice_PA_PK_AS_REP_dhInfo; - ret = generate_dh_keyblock(r->context, cp, enctype); - if (ret) - return ret; - ret = pk_mk_pa_reply_dh(r->context, config, cp, &info, @@ -1247,6 +1607,20 @@ _kdc_pk_mk_pa_reply(astgs_request_t r, pk_client_params *cp) goto out; } + if (cp->kdf) { + rep.u.dhInfo.kdf = calloc(1, sizeof(rep.u.dhInfo.kdf[0])); + if (rep.u.dhInfo.kdf == NULL) { + ret = krb5_enomem(r->context); + goto out; + } + + ret = der_copy_oid(cp->kdf, &rep.u.dhInfo.kdf->kdf_id); + if (ret) { + ret = krb5_enomem(r->context); + goto out; + } + } + ASN1_MALLOC_ENCODE(ContentInfo, rep.u.dhInfo.dhSignedData.data, rep.u.dhInfo.dhSignedData.length, &info, &size, ret); @@ -1260,89 +1634,12 @@ _kdc_pk_mk_pa_reply(astgs_request_t r, pk_client_params *cp) } if (rep.u.encKeyPack.length != size) krb5_abortx(r->context, "Internal ASN.1 encoder error"); + } - /* generate the session key using the method from RFC6112 */ - { - krb5_keyblock kdc_contribution_key; - krb5_crypto reply_crypto; - krb5_crypto kdccont_crypto; - krb5_data p1 = { strlen("PKINIT"), "PKINIT"}; - krb5_data p2 = { strlen("KEYEXCHANGE"), "KEYEXCHANGE"}; - void *kckdata; - size_t kcklen; - EncryptedData kx; - void *kxdata; - size_t kxlen; - - ret = krb5_generate_random_keyblock(r->context, sessionetype, - &kdc_contribution_key); - if (ret) { - free_PA_PK_AS_REP(&rep); - goto out; - } - ret = krb5_crypto_init(r->context, &cp->reply_key, enctype, &reply_crypto); - if (ret) { - krb5_free_keyblock_contents(r->context, &kdc_contribution_key); - free_PA_PK_AS_REP(&rep); - goto out; - } - ret = krb5_crypto_init(r->context, &kdc_contribution_key, sessionetype, &kdccont_crypto); - if (ret) { - krb5_crypto_destroy(r->context, reply_crypto); - krb5_free_keyblock_contents(r->context, &kdc_contribution_key); - free_PA_PK_AS_REP(&rep); - goto out; - } - /* KRB-FX-CF2 */ - ret = krb5_crypto_fx_cf2(r->context, kdccont_crypto, reply_crypto, - &p1, &p2, sessionetype, sessionkey); - krb5_crypto_destroy(r->context, kdccont_crypto); - if (ret) { - krb5_crypto_destroy(r->context, reply_crypto); - krb5_free_keyblock_contents(r->context, &kdc_contribution_key); - free_PA_PK_AS_REP(&rep); - goto out; - } - ASN1_MALLOC_ENCODE(EncryptionKey, kckdata, kcklen, - &kdc_contribution_key, &size, ret); - krb5_free_keyblock_contents(r->context, &kdc_contribution_key); - if (ret) { - krb5_set_error_message(r->context, ret, "encoding of PKINIT-KX Key failed %d", ret); - krb5_crypto_destroy(r->context, reply_crypto); - free_PA_PK_AS_REP(&rep); - goto out; - } - if (kcklen != size) - krb5_abortx(r->context, "Internal ASN.1 encoder error"); - ret = krb5_encrypt_EncryptedData(r->context, reply_crypto, KRB5_KU_PA_PKINIT_KX, - kckdata, kcklen, 0, &kx); - krb5_crypto_destroy(r->context, reply_crypto); - free(kckdata); - if (ret) { - free_PA_PK_AS_REP(&rep); - goto out; - } - ASN1_MALLOC_ENCODE(EncryptedData, kxdata, kxlen, - &kx, &size, ret); - free_EncryptedData(&kx); - if (ret) { - krb5_set_error_message(r->context, ret, - "encoding of PKINIT-KX failed %d", ret); - free_PA_PK_AS_REP(&rep); - goto out; - } - if (kxlen != size) - krb5_abortx(r->context, "Internal ASN.1 encoder error"); - /* Add PA-PKINIT-KX */ - ret = krb5_padata_add(r->context, md, KRB5_PADATA_PKINIT_KX, kxdata, kxlen); - if (ret) { - krb5_set_error_message(r->context, ret, - "Failed adding PKINIT-KX %d", ret); - free(buf); - goto out; - } - } - } + /* + * Since RFC 8636 we first encode the PA_PK_AS_REP _then_ derive the + * reply key. + */ #define use_btmm_with_enckey 0 if (use_btmm_with_enckey && rep.element == choice_PA_PK_AS_REP_encKeyPack) { @@ -1359,8 +1656,6 @@ _kdc_pk_mk_pa_reply(astgs_request_t r, pk_client_params *cp) } else { ASN1_MALLOC_ENCODE(PA_PK_AS_REP, buf, len, &rep, &size, ret); } - - free_PA_PK_AS_REP(&rep); if (ret) { krb5_set_error_message(r->context, ret, "encode PA-PK-AS-REP failed %d", ret); @@ -1369,12 +1664,109 @@ _kdc_pk_mk_pa_reply(astgs_request_t r, pk_client_params *cp) if (len != size) krb5_abortx(r->context, "Internal ASN.1 encoder error"); + if (cp->keyex == USE_DH || cp->keyex == USE_ECDH) { + /* + * Now that we have the PA_PK_AS_REP encoded we can compute the + * shared secret and derive the reply key from it per RFC 8636. + */ + ret = generate_dh_keyblock(r, cp, buf, len, enctype); + if (ret) { + free_PA_PK_AS_REP(&rep); + goto out; + } + } + + /* generate the session key using the method from RFC6112 */ + if (cp->keyex == USE_DH || cp->keyex == USE_ECDH) { + krb5_keyblock kdc_contribution_key; + krb5_crypto reply_crypto; + krb5_crypto kdccont_crypto; + krb5_data p1 = { strlen("PKINIT"), "PKINIT"}; + krb5_data p2 = { strlen("KEYEXCHANGE"), "KEYEXCHANGE"}; + void *kckdata; + size_t kcklen; + EncryptedData kx; + void *kxdata; + size_t kxlen; + + ret = krb5_generate_random_keyblock(r->context, sessionetype, + &kdc_contribution_key); + if (ret) { + free_PA_PK_AS_REP(&rep); + goto out; + } + ret = krb5_crypto_init(r->context, &cp->reply_key, enctype, &reply_crypto); + if (ret) { + krb5_free_keyblock_contents(r->context, &kdc_contribution_key); + free_PA_PK_AS_REP(&rep); + goto out; + } + ret = krb5_crypto_init(r->context, &kdc_contribution_key, sessionetype, &kdccont_crypto); + if (ret) { + krb5_crypto_destroy(r->context, reply_crypto); + krb5_free_keyblock_contents(r->context, &kdc_contribution_key); + free_PA_PK_AS_REP(&rep); + goto out; + } + /* KRB-FX-CF2 */ + ret = krb5_crypto_fx_cf2(r->context, kdccont_crypto, reply_crypto, + &p1, &p2, sessionetype, sessionkey); + krb5_crypto_destroy(r->context, kdccont_crypto); + if (ret) { + krb5_crypto_destroy(r->context, reply_crypto); + krb5_free_keyblock_contents(r->context, &kdc_contribution_key); + free_PA_PK_AS_REP(&rep); + goto out; + } + ASN1_MALLOC_ENCODE(EncryptionKey, kckdata, kcklen, + &kdc_contribution_key, &size, ret); + krb5_free_keyblock_contents(r->context, &kdc_contribution_key); + if (ret) { + krb5_set_error_message(r->context, ret, "encoding of PKINIT-KX Key failed %d", ret); + krb5_crypto_destroy(r->context, reply_crypto); + free_PA_PK_AS_REP(&rep); + goto out; + } + if (kcklen != size) + krb5_abortx(r->context, "Internal ASN.1 encoder error"); + ret = krb5_encrypt_EncryptedData(r->context, reply_crypto, KRB5_KU_PA_PKINIT_KX, + kckdata, kcklen, 0, &kx); + krb5_crypto_destroy(r->context, reply_crypto); + free(kckdata); + if (ret) { + free_PA_PK_AS_REP(&rep); + goto out; + } + ASN1_MALLOC_ENCODE(EncryptedData, kxdata, kxlen, + &kx, &size, ret); + free_EncryptedData(&kx); + if (ret) { + krb5_set_error_message(r->context, ret, + "encoding of PKINIT-KX failed %d", ret); + free_PA_PK_AS_REP(&rep); + goto out; + } + if (kxlen != size) + krb5_abortx(r->context, "Internal ASN.1 encoder error"); + /* Add PA-PKINIT-KX */ + ret = krb5_padata_add(r->context, md, KRB5_PADATA_PKINIT_KX, kxdata, kxlen); + if (ret) { + krb5_set_error_message(r->context, ret, + "Failed adding PKINIT-KX %d", ret); + free(buf); + goto out; + } + } + + free_PA_PK_AS_REP(&rep); + kdc_log(r->context, config, 0, "PKINIT using %s %s", type, other); } else if (cp->type == PKINIT_WIN2K) { PA_PK_AS_REP_Win2k rep; ContentInfo info; + memset(&info, 0, sizeof(info)); if (cp->keyex != USE_RSA) { ret = KRB5KRB_ERR_GENERIC; krb5_set_error_message(r->context, ret, @@ -1683,6 +2075,8 @@ _kdc_pk_check_client(astgs_request_t r, hx509_name name; size_t i; + *subject_name = NULL; + if (cp->cert == NULL) { if (!_kdc_is_anonymous(r->context, client->principal) && !config->historical_anon_realm) @@ -1718,7 +2112,7 @@ _kdc_pk_check_client(astgs_request_t r, return ret; kdc_log(r->context, config, 0, - "Trying to authorize PKINIT subject DN %s", + "Trying to authorize PKINIT subject DN \"%s\"", *subject_name); ret = hdb_entry_get_pkinit_cert(client, &pc); @@ -1736,6 +2130,8 @@ _kdc_pk_check_client(astgs_request_t r, ret = hx509_cert_cmp(cert, cp->cert); hx509_cert_free(cert); if (ret == 0) { + kdc_audit_addkv((kdc_request_t)r, 0, "authorized_by", + "exact_match_cert"); kdc_log(r->context, config, 5, "Found matching PKINIT cert in hdb"); return 0; @@ -1750,6 +2146,8 @@ _kdc_pk_check_client(astgs_request_t r, cp->cert, client->principal); if (ret == 0) { + kdc_audit_addkv((kdc_request_t)r, 0, "authorized_by", + "exact_match_PKINIT_SAN"); kdc_log(r->context, config, 5, "Found matching PKINIT SAN in certificate"); return 0; @@ -1760,6 +2158,8 @@ _kdc_pk_check_client(astgs_request_t r, clientdb, client); if (ret == 0) { + kdc_audit_addkv((kdc_request_t)r, 0, "authorized_by", + "exact_match_UPN_SAN"); kdc_log(r->context, config, 5, "Found matching MS UPN SAN in certificate"); return 0; @@ -1782,6 +2182,8 @@ _kdc_pk_check_client(astgs_request_t r, if (acl->val[0].anchor) continue; + kdc_audit_addkv((kdc_request_t)r, 0, "authorized_by", + "exact_match_cert_name"); kdc_log(r->context, config, 5, "Found matching PKINIT database ACL"); return 0; @@ -1798,6 +2200,8 @@ _kdc_pk_check_client(astgs_request_t r, continue; if (strcmp(principal_mappings.val[i].subject, *subject_name) != 0) continue; + kdc_audit_addkv((kdc_request_t)r, 0, "authorized_by", + "pkinit_mappings_file"); kdc_log(r->context, config, 5, "Found matching PKINIT FILE ACL"); return 0; @@ -1808,6 +2212,8 @@ _kdc_pk_check_client(astgs_request_t r, "PKINIT no matching principals for %s", *subject_name); + kdc_audit_addkv((kdc_request_t)r, 0, "authorized_by", + "denied"); kdc_log(r->context, config, 5, "PKINIT no matching principals for %s", *subject_name); diff --git a/kdc/process.c b/kdc/process.c index 162eb24e2..948e9c9c0 100644 --- a/kdc/process.c +++ b/kdc/process.c @@ -301,34 +301,6 @@ kdc_tgs_req(kdc_request_t *rptr, int *claim) return ret; } -#ifdef DIGEST - -static krb5_error_code -kdc_digest(kdc_request_t *rptr, int *claim) -{ - kdc_request_t r; - DigestREQ digestreq; - krb5_error_code ret; - size_t len; - - r = *rptr; - - ret = decode_DigestREQ(r->request.data, r->request.length, - &digestreq, &len); - if (ret) - return ret; - - r->use_request_t = 0; - *claim = 1; - - ret = _kdc_do_digest(r->context, r->config, &digestreq, - r->reply, r->from, r->addr); - free_DigestREQ(&digestreq); - return ret; -} - -#endif - #ifdef KX509 static krb5_error_code @@ -357,9 +329,6 @@ kdc_kx509(kdc_request_t *rptr, int *claim) static struct krb5_kdc_service services[] = { { KS_KRB5, "AS-REQ", kdc_as_req }, { KS_KRB5, "TGS-REQ", kdc_tgs_req }, -#ifdef DIGEST - { 0, "DIGEST", kdc_digest }, -#endif #ifdef KX509 { 0, "KX509", kdc_kx509 }, #endif diff --git a/kdc/string2key.c b/kdc/string2key.c index 4b9c62e5a..b332d04cb 100644 --- a/kdc/string2key.c +++ b/kdc/string2key.c @@ -157,7 +157,7 @@ main(int argc, char **argv) if(argv[0]) password = argv[0]; if(password == NULL){ - if(UI_UTIL_read_pw_string(buf, sizeof(buf), "Password: ", 0)) + if (_krb5_UI_UTIL_read_pw_string(buf, sizeof(buf), "Password: ", 0)) return 1; password = buf; } diff --git a/kpasswd/Makefile.am b/kpasswd/Makefile.am index bd94e4105..771e9b402 100644 --- a/kpasswd/Makefile.am +++ b/kpasswd/Makefile.am @@ -2,12 +2,16 @@ include $(top_srcdir)/Makefile.am.common +AM_CPPFLAGS += -I$(srcdir)/../lib/krb5 + man_MANS = kpasswd.1 kpasswdd.8 bin_PROGRAMS = kpasswd kpasswd_SOURCES = kpasswd.c kpasswd_locl.h +kpasswd_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/../lib/krb5 + libexec_PROGRAMS = kpasswdd noinst_PROGRAMS = kpasswd-generator diff --git a/kpasswd/kpasswd.c b/kpasswd/kpasswd.c index af5012fb5..c79dc76ef 100644 --- a/kpasswd/kpasswd.c +++ b/kpasswd/kpasswd.c @@ -83,8 +83,8 @@ change_password(krb5_context context, if (aret == -1 || msg == NULL) krb5_errx (context, 1, "out of memory"); - ret = UI_UTIL_read_pw_string (pwbuf, sizeof(pwbuf), msg, - UI_UTIL_FLAG_VERIFY); + ret = _krb5_UI_UTIL_read_pw_string(pwbuf, sizeof(pwbuf), msg, + UI_UTIL_FLAG_VERIFY); free(msg); if (name) free(name); diff --git a/kpasswd/kpasswd_locl.h b/kpasswd/kpasswd_locl.h index 3be2096fe..c5be64524 100644 --- a/kpasswd/kpasswd_locl.h +++ b/kpasswd/kpasswd_locl.h @@ -100,6 +100,7 @@ #include #include #include +#include #include "crypto-headers.h" /* for des_read_pw_string */ #endif /* __KPASSWD_LOCL_H__ */ diff --git a/kuser/Makefile.am b/kuser/Makefile.am index 81ecaeabe..7ce5ddbf5 100644 --- a/kuser/Makefile.am +++ b/kuser/Makefile.am @@ -16,13 +16,12 @@ man_MANS = \ klist.1 \ kdestroy.1 \ kswitch.1 \ - kdigest.8 \ kgetcred.1 \ kimpersonate.8 \ kx509.1 bin_PROGRAMS = kinit kdestroy kgetcred heimtools -libexec_PROGRAMS = kdigest kimpersonate +libexec_PROGRAMS = kimpersonate noinst_PROGRAMS = kverify kdecode_ticket generate-requests @@ -32,7 +31,6 @@ kinit_LDADD = \ $(top_builddir)/lib/krb5/libkrb5.la \ $(top_builddir)/lib/gssapi/libgssapi.la \ $(top_builddir)/lib/gss_preauth/libgss_preauth.la \ - $(top_builddir)/lib/ntlm/libheimntlm.la \ $(top_builddir)/lib/asn1/libasn1.la \ $(LIB_libintl) \ $(LIB_roken) @@ -55,25 +53,9 @@ nodist_heimtools_SOURCES = heimtools-commands.c $(heimtools_OBJECTS): heimtools-commands.h -dist_kdigest_SOURCES = kdigest.c -nodist_kdigest_SOURCES = kdigest-commands.c - -kdigest_LDADD = \ - $(top_builddir)/lib/ntlm/libheimntlm.la \ - $(top_builddir)/lib/krb5/libkrb5.la \ - $(top_builddir)/lib/asn1/libasn1.la \ - $(top_builddir)/lib/sl/libsl.la \ - $(LIB_roken) - -$(kdigest_OBJECTS): kdigest-commands.h - CLEANFILES = \ - kdigest-commands.h kdigest-commands.c \ heimtools-commands.h heimtools-commands.c -kdigest-commands.c kdigest-commands.h: kdigest-commands.in - $(SLC) $(srcdir)/kdigest-commands.in - heimtools-commands.c heimtools-commands.h: heimtools-commands.in $(SLC) $(srcdir)/heimtools-commands.in @@ -88,11 +70,10 @@ EXTRA_DIST = NTMakefile $(man_MANS) \ kdeltkt.c \ kvno.c \ kdestroy-version.rc \ - kdigest-version.rc \ kgetcred-version.rc \ kimpersonate-version.rc \ kinit-version.rc \ - kuser_locl.h heimtools-commands.in kdigest-commands.in copy_cred_cache.1 + kuser_locl.h heimtools-commands.in copy_cred_cache.1 # make sure install-exec-hook doesn't have any commands in Makefile.am.common install-exec-hook: diff --git a/kuser/NTMakefile b/kuser/NTMakefile index 4b97b7084..c0b9b7f1b 100644 --- a/kuser/NTMakefile +++ b/kuser/NTMakefile @@ -45,7 +45,6 @@ BINPROGRAMS=\ $(BINDIR)\kdeltkt.exe LIBEXECPROGRAMS=\ - $(LIBEXECDIR)\kdigest.exe \ $(LIBEXECDIR)\kimpersonate.exe NOINSTPROGRAMS=\ @@ -59,7 +58,6 @@ BINLIBS=\ $(LIBGSS_PREAUTH) \ $(LIBGSSAPI) \ $(LIBHEIMDAL) \ - $(LIBHEIMNTLM) \ $(LIBHX509) \ !if !defined(NO_AFS) $(LIBKAFS) \ @@ -103,20 +101,6 @@ $(BINDIR)\kgetcred.exe: $(OBJ)\kgetcred.obj $(BINLIBS) $(OBJ)\kgetcred-version.r $(EXECONLINK) $(EXEPREP) - -$(LIBEXECDIR)\kdigest.exe: $(OBJ)\kdigest-commands.obj $(OBJ)\kdigest.obj $(BINLIBS) $(LIBSL) $(OBJ)\kdigest-version.res - $(EXECONLINK) - $(EXEPREP) - -$(OBJ)\kdigest.obj: kdigest.c - $(C2OBJ) -I$(OBJ) - -$(OBJ)\kdigest-commands.c $(OBJ)\kdigest-commands.h: kdigest-commands.in - cd $(OBJ) - $(CP) $(SRCDIR)\kdigest-commands.in $(OBJ) - $(BINDIR)\slc.exe kdigest-commands.in - cd $(SRCDIR) - $(OBJ)\heimtools-commands.c $(OBJ)\heimtools-commands.h: heimtools-commands.in cd $(OBJ) $(CP) $(SRCDIR)\heimtools-commands.in $(OBJ) diff --git a/kuser/kdestroy.c b/kuser/kdestroy.c index 1823bf56c..6a28388bc 100644 --- a/kuser/kdestroy.c +++ b/kuser/kdestroy.c @@ -37,9 +37,6 @@ static const char *cache; static const char *credential; static int help_flag; static int version_flag; -#ifndef NO_AFS -static int unlog_flag = 1; -#endif static int dest_tkt_flag = 1; static int all_flag = 0; @@ -48,10 +45,6 @@ struct getargs args[] = { "remove one credential", "principal" }, { "cache", 'c', arg_string, rk_UNCONST(&cache), "cache to destroy", "cache" }, { "all", 'A', arg_flag, &all_flag, "destroy all caches", NULL }, -#ifndef NO_AFS - { "unlog", 0, arg_negative_flag, &unlog_flag, - "do not destroy tokens", NULL }, -#endif { "delete-v4", 0, arg_negative_flag, &dest_tkt_flag, "do not destroy v4 tickets", NULL }, { "version", 0, arg_flag, &version_flag, NULL, NULL }, @@ -161,12 +154,5 @@ main (int argc, char **argv) krb5_free_context (context); -#ifndef NO_AFS - if (unlog_flag && k_hasafs ()) { - if (k_unlog ()) - exit_val = 1; - } -#endif - return exit_val; } diff --git a/kuser/kdigest-commands.in b/kuser/kdigest-commands.in deleted file mode 100644 index 3f73f5bd5..000000000 --- a/kuser/kdigest-commands.in +++ /dev/null @@ -1,280 +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$ */ - -command = { - name = "digest-probe" - option = { - long = "realm" - type = "string" - help = "Kerberos realm to communicate with" - } - help = "probe what mech is allowed/supported for this server" -} -command = { - name = "digest-server-init" - option = { - long = "type" - type = "string" - help = "digest type" - default = "sasl" - } - option = { - long = "kerberos-realm" - type = "string" - argument = "realm" - help = "" - } - option = { - long = "digest" - type = "string" - argument = "digest-type" - help = "digest type to use in the algorithm" - } - option = { - long = "cb-type" - type = "string" - argument = "type" - help = "type of channel bindings" - } - option = { - long = "cb-value" - type = "string" - argument = "value" - help = "value of channel bindings" - } - option = { - long = "hostname" - type = "string" - argument = "hostname" - help = "hostname of the server" - } - option = { - long = "realm" - type = "string" - help = "Kerberos realm to communicate with" - } - help = "Sets up a digest context and return initial parameters" -} -command = { - name = "digest-server-request" - option = { - long = "type" - type = "string" - help = "digest type" - default = "sasl" - } - option = { - long = "kerberos-realm" - type = "string" - argument = "realm" - help = "" - } - option = { - long = "username" - type = "string" - argument = "name" - help = "digest type" - } - option = { - long = "server-nonce" - type = "string" - argument = "nonce" - help = "" - } - option = { - long = "server-identifier" - type = "string" - argument = "nonce" - help = "" - } - option = { - long = "client-nonce" - type = "string" - argument = "nonce" - help = "" - } - option = { - long = "client-response" - type = "string" - argument = "response" - help = "" - } - option = { - long = "opaque" - type = "string" - argument = "string" - help = "" - } - option = { - long = "authentication-name" - type = "string" - argument = "name" - help = "" - } - option = { - long = "realm" - type = "string" - argument = "realm" - help = "" - } - option = { - long = "method" - type = "string" - argument = "method" - help = "" - } - option = { - long = "uri" - type = "string" - argument = "uri" - help = "" - } - option = { - long = "nounce-count" - type = "string" - argument = "count" - help = "" - } - option = { - long = "qop" - type = "string" - argument = "qop" - help = "" - } - option = { - long = "ccache" - type = "string" - argument = "ccache" - help = "Where the the credential cache is created when the KDC returns tickets" - } - help = "Completes digest negotiation and return final parameters" -} -command = { - name = "digest-client-request" - option = { - long = "type" - type = "string" - help = "digest type" - default = "sasl" - } - option = { - long = "username" - type = "string" - argument = "name" - help = "digest type" - } - option = { - long = "password" - type = "string" - argument = "password" - } - option = { - long = "server-nonce" - type = "string" - argument = "nonce" - help = "" - } - option = { - long = "server-identifier" - type = "string" - argument = "nonce" - help = "" - } - option = { - long = "client-nonce" - type = "string" - argument = "nonce" - help = "" - } - option = { - long = "opaque" - type = "string" - argument = "string" - help = "" - } - option = { - long = "realm" - type = "string" - argument = "realm" - help = "" - } - option = { - long = "method" - type = "string" - argument = "method" - help = "" - } - option = { - long = "uri" - type = "string" - argument = "uri" - help = "" - } - option = { - long = "nounce-count" - type = "string" - argument = "count" - help = "" - } - option = { - long = "qop" - type = "string" - argument = "qop" - help = "" - } - help = "Client part of a digest exchange" -} -command = { - name = "ntlm-server-init" - option = { - long = "version" - type = "integer" - help = "ntlm version" - default = "1" - } - option = { - long = "kerberos-realm" - type = "string" - help = "Kerberos realm to communicate with" - } - help = "Sets up a digest context and return initial parameters" -} -command = { - name = "help" - name = "?" - argument = "[command]" - min_args = "0" - max_args = "1" - help = "Help! I need somebody." -} diff --git a/kuser/kdigest-version.rc b/kuser/kdigest-version.rc deleted file mode 100644 index 8e5b16ee2..000000000 --- a/kuser/kdigest-version.rc +++ /dev/null @@ -1,36 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2010, Secure Endpoints Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * - **********************************************************************/ - -#define RC_FILE_TYPE VFT_APP -#define RC_FILE_DESC_0409 "KDC Digest Interface Tool" -#define RC_FILE_ORIG_0409 "kdigest.exe" - -#include "../windows/version.rc" diff --git a/kuser/kdigest.8 b/kuser/kdigest.8 deleted file mode 100644 index 6b633c3f5..000000000 --- a/kuser/kdigest.8 +++ /dev/null @@ -1,257 +0,0 @@ -.\" Copyright (c) 2008 Kungliga Tekniska Högskolan -.\" (Royal Institute of Technology, Stockholm, Sweden). -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" 3. Neither the name of the Institute nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" $Id$ -.\" -.Dd September 25, 2008 -.Dt KDIGEST 8 -.Os HEIMDAL -.Sh NAME -.Nm kdigest -.Nd userland tool to access digest interface in the KDC -.Sh SYNOPSIS -.Nm -.Op Fl Fl ccache= Ns Ar string -.Op Fl Fl version -.Op Fl Fl help -command -.Op arguments -.Sh DESCRIPTION -Supported options: -.Bl -tag -width Ds -.It Xo -.Fl Fl ccache= Ns Ar string -.Xc -credential cache -.It Xo -.Fl Fl version -.Xc -print version -.It Xo -.Fl Fl help -.Xc -.El -.Pp -Available commands are: -.Bl -tag -width Ds -.It Xo digest-probe -.Op Fl Fl realm= Ns Ar string -.Op Fl h | Fl Fl help -.Xc -.Bl -tag -width Ds -.It Xo -.Fl Fl realm= Ns Ar string -.Xc -Kerberos realm to communicate with -.El -.It Xo digest-server-init -.Op Fl Fl type= Ns Ar string -.Op Fl Fl kerberos-realm= Ns Ar realm -.Op Fl Fl digest= Ns Ar digest-type -.Op Fl Fl cb-type= Ns Ar type -.Op Fl Fl cb-value= Ns Ar value -.Op Fl Fl hostname= Ns Ar hostname -.Op Fl Fl realm= Ns Ar string -.Xc -.Bl -tag -width Ds -.It Xo -.Fl Fl type= Ns Ar string -.Xc -digest type -.It Xo -.Fl Fl kerberos-realm= Ns Ar realm -.Xc -.It Xo -.Fl Fl digest= Ns Ar digest-type -.Xc -digest type to use in the algorithm -.It Xo -.Fl Fl cb-type= Ns Ar type -.Xc -type of channel bindings -.It Xo -.Fl Fl cb-value= Ns Ar value -.Xc -value of channel bindings -.It Xo -.Fl Fl hostname= Ns Ar hostname -.Xc -hostname of the server -.It Xo -.Fl Fl realm= Ns Ar string -.Xc -Kerberos realm to communicate with -.El -.It Xo digest-server-request -.Op Fl Fl type= Ns Ar string -.Op Fl Fl kerberos-realm= Ns Ar realm -.Op Fl Fl username= Ns Ar name -.Op Fl Fl server-nonce= Ns Ar nonce -.Op Fl Fl server-identifier= Ns Ar nonce -.Op Fl Fl client-nonce= Ns Ar nonce -.Op Fl Fl client-response= Ns Ar response -.Op Fl Fl opaque= Ns Ar string -.Op Fl Fl authentication-name= Ns Ar name -.Op Fl Fl realm= Ns Ar realm -.Op Fl Fl method= Ns Ar method -.Op Fl Fl uri= Ns Ar uri -.Op Fl Fl nounce-count= Ns Ar count -.Op Fl Fl qop= Ns Ar qop -.Op Fl Fl ccache= Ns Ar ccache -.Xc -.Bl -tag -width Ds -.It Xo -.Fl Fl type= Ns Ar string -.Xc -digest type -.It Xo -.Fl Fl kerberos-realm= Ns Ar realm -.Xc -.It Xo -.Fl Fl username= Ns Ar name -.Xc -digest type -.It Xo -.Fl Fl server-nonce= Ns Ar nonce -.Xc -.It Xo -.Fl Fl server-identifier= Ns Ar nonce -.Xc -.It Xo -.Fl Fl client-nonce= Ns Ar nonce -.Xc -.It Xo -.Fl Fl client-response= Ns Ar response -.Xc -.It Xo -.Fl Fl opaque= Ns Ar string -.Xc -.It Xo -.Fl Fl authentication-name= Ns Ar name -.Xc -.It Xo -.Fl Fl realm= Ns Ar realm -.Xc -.It Xo -.Fl Fl method= Ns Ar method -.Xc -.It Xo -.Fl Fl uri= Ns Ar uri -.Xc -.It Xo -.Fl Fl nounce-count= Ns Ar count -.Xc -.It Xo -.Fl Fl qop= Ns Ar qop -.Xc -.It Xo -.Fl Fl ccache= Ns Ar ccache -.Xc -Where the the credential cache is created when the KDC returns tickets -.El -.It Xo digest-client-request -.Op Fl Fl type= Ns Ar string -.Op Fl Fl username= Ns Ar name -.Op Fl Fl password= Ns Ar password -.Op Fl Fl server-nonce= Ns Ar nonce -.Op Fl Fl server-identifier= Ns Ar nonce -.Op Fl Fl client-nonce= Ns Ar nonce -.Op Fl Fl opaque= Ns Ar string -.Op Fl Fl realm= Ns Ar realm -.Op Fl Fl method= Ns Ar method -.Op Fl Fl uri= Ns Ar uri -.Op Fl Fl nounce-count= Ns Ar count -.Op Fl Fl qop= Ns Ar qop -.Xc -.Bl -tag -width Ds -.It Xo -.Fl Fl type= Ns Ar string -.Xc -digest type -.It Xo -.Fl Fl username= Ns Ar name -.Xc -digest type -.It Xo -.Fl Fl password= Ns Ar password -.Xc -.It Xo -.Fl Fl server-nonce= Ns Ar nonce -.Xc -.It Xo -.Fl Fl server-identifier= Ns Ar nonce -.Xc -.It Xo -.Fl Fl client-nonce= Ns Ar nonce -.Xc -.It Xo -.Fl Fl opaque= Ns Ar string -.Xc -.It Xo -.Fl Fl realm= Ns Ar realm -.Xc -.It Xo -.Fl Fl method= Ns Ar method -.Xc -.It Xo -.Fl Fl uri= Ns Ar uri -.Xc -.It Xo -.Fl Fl nounce-count= Ns Ar count -.Xc -.It Xo -.Fl Fl qop= Ns Ar qop -.Xc -.El -.It Xo ntlm-server-init -.Op Fl Fl version= Ns Ar integer -.Op Fl Fl kerberos-realm= Ns Ar string -.Xc -.Bl -tag -width Ds -.It Xo -.Fl Fl version= Ns Ar integer -.Xc -ntlm version -.It Xo -.Fl Fl kerberos-realm= Ns Ar string -.Xc -Kerberos realm to communicate with -.El -.El -.\".Sh ENVIRONMENT -.\".Sh FILES -.\".Sh EXAMPLES -.\".Sh DIAGNOSTICS -.\".Sh SEE ALSO -.\".Sh STANDARDS -.\".Sh HISTORY -.\".Sh AUTHORS -.\".Sh BUGS diff --git a/kuser/kdigest.c b/kuser/kdigest.c deleted file mode 100644 index 6a7771924..000000000 --- a/kuser/kdigest.c +++ /dev/null @@ -1,570 +0,0 @@ -/* - * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "kuser_locl.h" - -#include -#include -#include -#include -#include "crypto-headers.h" - -static int version_flag = 0; -static int help_flag = 0; -static char *ccache_string; -static krb5_ccache id; - -static struct getargs args[] = { - {"ccache", 0, arg_string, &ccache_string, "credential cache", NULL }, - {"version", 0, arg_flag, &version_flag, "print version", NULL }, - {"help", 0, arg_flag, &help_flag, NULL, NULL } -}; - -static void -usage (int ret) -{ - arg_printusage (args, sizeof(args)/sizeof(*args), - NULL, ""); - exit (ret); -} - -static krb5_context context; - -int -digest_probe(struct digest_probe_options *opt, - int argc, char ** argv) -{ - krb5_error_code ret; - krb5_realm realm; - unsigned flags; - - realm = opt->realm_string; - - if (realm == NULL) - errx(1, "realm missing"); - - ret = krb5_digest_probe(context, realm, id, &flags); - if (ret) - krb5_err(context, 1, ret, "digest_probe"); - - printf("flags: %u\n", flags); - - return 0; -} - -int -digest_server_init(struct digest_server_init_options *opt, - int argc, char ** argv) -{ - krb5_error_code ret; - krb5_digest digest; - - ret = krb5_digest_alloc(context, &digest); - if (ret) - krb5_err(context, 1, ret, "digest_alloc"); - - ret = krb5_digest_set_type(context, digest, opt->type_string); - if (ret) - krb5_err(context, 1, ret, "krb5_digest_set_type"); - - if (opt->cb_type_string && opt->cb_value_string) { - ret = krb5_digest_set_server_cb(context, digest, - opt->cb_type_string, - opt->cb_value_string); - if (ret) - krb5_err(context, 1, ret, "krb5_digest_set_server_cb"); - } - ret = krb5_digest_init_request(context, - digest, - opt->kerberos_realm_string, - id); - if (ret) - krb5_err(context, 1, ret, "krb5_digest_init_request"); - - printf("type=%s\n", opt->type_string); - printf("server-nonce=%s\n", - krb5_digest_get_server_nonce(context, digest)); - { - const char *s = krb5_digest_get_identifier(context, digest); - if (s) - printf("identifier=%s\n", s); - } - printf("opaque=%s\n", krb5_digest_get_opaque(context, digest)); - - krb5_digest_free(digest); - - return 0; -} - -int -digest_server_request(struct digest_server_request_options *opt, - int argc, char **argv) -{ - krb5_error_code ret; - krb5_digest digest; - const char *status, *rsp; - krb5_data session_key; - - if (opt->server_nonce_string == NULL) - errx(1, "server nonce missing"); - if (opt->type_string == NULL) - errx(1, "type missing"); - if (opt->opaque_string == NULL) - errx(1, "opaque missing"); - if (opt->client_response_string == NULL) - errx(1, "client response missing"); - - ret = krb5_digest_alloc(context, &digest); - if (ret) - krb5_err(context, 1, ret, "digest_alloc"); - - if (strcasecmp(opt->type_string, "CHAP") == 0) { - if (opt->server_identifier_string == NULL) - errx(1, "server identifier missing"); - - ret = krb5_digest_set_identifier(context, digest, - opt->server_identifier_string); - if (ret) - krb5_err(context, 1, ret, "krb5_digest_set_type"); - } - - ret = krb5_digest_set_type(context, digest, opt->type_string); - if (ret) - krb5_err(context, 1, ret, "krb5_digest_set_type"); - - ret = krb5_digest_set_username(context, digest, opt->username_string); - if (ret) - krb5_err(context, 1, ret, "krb5_digest_set_username"); - - ret = krb5_digest_set_server_nonce(context, digest, - opt->server_nonce_string); - if (ret) - krb5_err(context, 1, ret, "krb5_digest_set_server_nonce"); - - if(opt->client_nonce_string) { - ret = krb5_digest_set_client_nonce(context, digest, - opt->client_nonce_string); - if (ret) - krb5_err(context, 1, ret, "krb5_digest_set_client_nonce"); - } - - - ret = krb5_digest_set_opaque(context, digest, opt->opaque_string); - if (ret) - krb5_err(context, 1, ret, "krb5_digest_set_opaque"); - - ret = krb5_digest_set_responseData(context, digest, - opt->client_response_string); - if (ret) - krb5_err(context, 1, ret, "krb5_digest_set_responseData"); - - ret = krb5_digest_request(context, digest, - opt->kerberos_realm_string, id); - if (ret) - krb5_err(context, 1, ret, "krb5_digest_request"); - - status = krb5_digest_rep_get_status(context, digest) ? "ok" : "failed"; - rsp = krb5_digest_get_rsp(context, digest); - - printf("status=%s\n", status); - if (rsp) - printf("rsp=%s\n", rsp); - printf("tickets=no\n"); - - ret = krb5_digest_get_session_key(context, digest, &session_key); - if (ret) - krb5_err(context, 1, ret, "krb5_digest_get_session_key"); - - if (session_key.length) { - char *key; - hex_encode(session_key.data, session_key.length, &key); - if (key == NULL) - krb5_errx(context, 1, "hex_encode"); - krb5_data_free(&session_key); - printf("session-key=%s\n", key); - free(key); - } - - krb5_digest_free(digest); - - return 0; -} - -static void -client_chap(const void *server_nonce, size_t snoncelen, - unsigned char server_identifier, - const char *password) -{ - EVP_MD_CTX *ctx; - unsigned char md[MD5_DIGEST_LENGTH]; - char *h; - - ctx = EVP_MD_CTX_create(); - EVP_DigestInit_ex(ctx, EVP_md5(), NULL); - - EVP_DigestUpdate(ctx, &server_identifier, 1); - EVP_DigestUpdate(ctx, password, strlen(password)); - EVP_DigestUpdate(ctx, server_nonce, snoncelen); - EVP_DigestFinal_ex(ctx, md, NULL); - - EVP_MD_CTX_destroy(ctx); - - hex_encode(md, 16, &h); - - printf("responseData=%s\n", h); - free(h); -} - -static const unsigned char ms_chap_v2_magic1[39] = { - 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65, - 0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67, - 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74 -}; -static const unsigned char ms_chap_v2_magic2[41] = { - 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B, - 0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F, - 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E, - 0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F, - 0x6E -}; -static const unsigned char ms_rfc3079_magic1[27] = { - 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d, - 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79 -}; - -static void -client_mschapv2(const void *server_nonce, size_t snoncelen, - const void *client_nonce, size_t cnoncelen, - const char *username, - const char *password) -{ - EVP_MD_CTX *hctx, *ctx; - unsigned char md[SHA_DIGEST_LENGTH], challenge[SHA_DIGEST_LENGTH]; - unsigned char hmd[MD4_DIGEST_LENGTH]; - struct ntlm_buf answer; - int i, len, ret; - char *h; - - ctx = EVP_MD_CTX_create(); - EVP_DigestInit_ex(ctx, EVP_sha1(), NULL); - - EVP_DigestUpdate(ctx, client_nonce, cnoncelen); - EVP_DigestUpdate(ctx, server_nonce, snoncelen); - EVP_DigestUpdate(ctx, username, strlen(username)); - EVP_DigestFinal_ex(ctx, md, NULL); - - - hctx = EVP_MD_CTX_create(); - EVP_DigestInit_ex(hctx, EVP_md4(), NULL); - len = strlen(password); - for (i = 0; i < len; i++) { - EVP_DigestUpdate(hctx, &password[i], 1); - EVP_DigestUpdate(hctx, &password[len], 1); - } - EVP_DigestFinal_ex(hctx, hmd, NULL); - - - /* ChallengeResponse */ - ret = heim_ntlm_calculate_ntlm1(hmd, sizeof(hmd), md, &answer); - if (ret) - errx(1, "heim_ntlm_calculate_ntlm1"); - - hex_encode(answer.data, answer.length, &h); - printf("responseData=%s\n", h); - free(h); - - /* PasswordHash */ - EVP_DigestInit_ex(hctx, EVP_md4(), NULL); - EVP_DigestUpdate(hctx, hmd, sizeof(hmd)); - EVP_DigestFinal_ex(hctx, hmd, NULL); - - - /* GenerateAuthenticatorResponse */ - EVP_DigestInit_ex(ctx, EVP_sha1(), NULL); - EVP_DigestUpdate(ctx, hmd, sizeof(hmd)); - EVP_DigestUpdate(ctx, answer.data, answer.length); - EVP_DigestUpdate(ctx, ms_chap_v2_magic1, sizeof(ms_chap_v2_magic1)); - EVP_DigestFinal_ex(ctx, md, NULL); - - /* ChallengeHash */ - EVP_DigestInit_ex(ctx, EVP_sha1(), NULL); - EVP_DigestUpdate(ctx, client_nonce, cnoncelen); - EVP_DigestUpdate(ctx, server_nonce, snoncelen); - EVP_DigestUpdate(ctx, username, strlen(username)); - EVP_DigestFinal_ex(ctx, challenge, NULL); - - EVP_DigestInit_ex(ctx, EVP_sha1(), NULL); - EVP_DigestUpdate(ctx, md, sizeof(md)); - EVP_DigestUpdate(ctx, challenge, 8); - EVP_DigestUpdate(ctx, ms_chap_v2_magic2, sizeof(ms_chap_v2_magic2)); - EVP_DigestFinal_ex(ctx, md, NULL); - - hex_encode(md, sizeof(md), &h); - printf("AuthenticatorResponse=%s\n", h); - free(h); - - /* get_master, rfc 3079 3.4 */ - EVP_DigestInit_ex(ctx, EVP_sha1(), NULL); - EVP_DigestUpdate(ctx, hmd, sizeof(hmd)); - EVP_DigestUpdate(ctx, answer.data, answer.length); - EVP_DigestUpdate(ctx, ms_rfc3079_magic1, sizeof(ms_rfc3079_magic1)); - EVP_DigestFinal_ex(ctx, md, NULL); - - free(answer.data); - - hex_encode(md, 16, &h); - printf("session-key=%s\n", h); - free(h); - - EVP_MD_CTX_destroy(hctx); - EVP_MD_CTX_destroy(ctx); -} - - -int -digest_client_request(struct digest_client_request_options *opt, - int argc, char **argv) -{ - char *server_nonce, *client_nonce = NULL, server_identifier; - ssize_t snoncelen, cnoncelen = 0; - - if (opt->server_nonce_string == NULL) - errx(1, "server nonce missing"); - if (opt->password_string == NULL) - errx(1, "password missing"); - - if (opt->opaque_string == NULL) - errx(1, "opaque missing"); - - snoncelen = strlen(opt->server_nonce_string); - server_nonce = malloc(snoncelen); - if (server_nonce == NULL) - errx(1, "server_nonce"); - - snoncelen = hex_decode(opt->server_nonce_string, server_nonce, snoncelen); - if (snoncelen <= 0) - errx(1, "server nonce wrong"); - - if (opt->client_nonce_string) { - cnoncelen = strlen(opt->client_nonce_string); - client_nonce = malloc(cnoncelen); - if (client_nonce == NULL) - errx(1, "client_nonce"); - - cnoncelen = hex_decode(opt->client_nonce_string, - client_nonce, cnoncelen); - if (cnoncelen <= 0) - errx(1, "client nonce wrong"); - } - - if (opt->server_identifier_string) { - int ret; - - ret = hex_decode(opt->server_identifier_string, &server_identifier, 1); - if (ret != 1) - errx(1, "server identifier wrong length"); - } - - if (strcasecmp(opt->type_string, "CHAP") == 0) { - if (opt->server_identifier_string == NULL) - errx(1, "server identifier missing"); - - client_chap(server_nonce, snoncelen, server_identifier, - opt->password_string); - - } else if (strcasecmp(opt->type_string, "MS-CHAP-V2") == 0) { - if (opt->client_nonce_string == NULL) - errx(1, "client nonce missing"); - if (opt->username_string == NULL) - errx(1, "client nonce missing"); - - client_mschapv2(server_nonce, snoncelen, - client_nonce, cnoncelen, - opt->username_string, - opt->password_string); - } - if (client_nonce) - free(client_nonce); - free(server_nonce); - - return 0; -} - -#include - -int -ntlm_server_init(struct ntlm_server_init_options *opt, - int argc, char ** argv) -{ - krb5_error_code ret; - krb5_ntlm ntlm; - struct ntlm_type2 type2; - krb5_data challenge, opaque; - struct ntlm_buf data; - char *s; - static char zero2[] = "\x00\x00"; - - memset(&type2, 0, sizeof(type2)); - - ret = krb5_ntlm_alloc(context, &ntlm); - if (ret) - krb5_err(context, 1, ret, "krb5_ntlm_alloc"); - - ret = krb5_ntlm_init_request(context, - ntlm, - opt->kerberos_realm_string, - id, - NTLM_NEG_UNICODE|NTLM_NEG_NTLM, - "NUTCRACKER", - "L"); - if (ret) - krb5_err(context, 1, ret, "krb5_ntlm_init_request"); - - /* - * - */ - - ret = krb5_ntlm_init_get_challenge(context, ntlm, &challenge); - if (ret) - krb5_err(context, 1, ret, "krb5_ntlm_init_get_challenge"); - - if (challenge.length != sizeof(type2.challenge)) - krb5_errx(context, 1, "ntlm challenge have wrong length"); - memcpy(type2.challenge, challenge.data, sizeof(type2.challenge)); - krb5_data_free(&challenge); - - ret = krb5_ntlm_init_get_flags(context, ntlm, &type2.flags); - if (ret) - krb5_err(context, 1, ret, "krb5_ntlm_init_get_flags"); - - krb5_ntlm_init_get_targetname(context, ntlm, &type2.targetname); - type2.targetinfo.data = zero2; - type2.targetinfo.length = 2; - - ret = heim_ntlm_encode_type2(&type2, &data); - if (ret) - krb5_errx(context, 1, "heim_ntlm_encode_type2"); - - free(type2.targetname); - - /* - * - */ - - rk_base64_encode(data.data, data.length, &s); - free(data.data); - printf("type2=%s\n", s); - free(s); - - /* - * - */ - - ret = krb5_ntlm_init_get_opaque(context, ntlm, &opaque); - if (ret) - krb5_err(context, 1, ret, "krb5_ntlm_init_get_opaque"); - - rk_base64_encode(opaque.data, opaque.length, &s); - krb5_data_free(&opaque); - printf("opaque=%s\n", s); - free(s); - - /* - * - */ - - krb5_ntlm_free(context, ntlm); - - return 0; -} - - -/* - * - */ - -int -help(void *opt, int argc, char **argv) -{ - sl_slc_help(commands, argc, argv); - return 0; -} - -int -main(int argc, char **argv) -{ - krb5_error_code ret; - int optidx = 0; - - setprogname(argv[0]); - - ret = krb5_init_context (&context); - if (ret == KRB5_CONFIG_BADFORMAT) - errx (1, "krb5_init_context failed to parse configuration file"); - else if (ret) - errx(1, "krb5_init_context failed: %d", ret); - - if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) - usage(1); - - if (help_flag) - usage (0); - - if(version_flag){ - print_version(NULL); - exit(0); - } - - argc -= optidx; - argv += optidx; - - if (argc == 0) { - help(NULL, argc, argv); - return 1; - } - - if (ccache_string) { - ret = krb5_cc_resolve(context, ccache_string, &id); - if (ret) - krb5_err(context, 1, ret, "krb5_cc_resolve"); - } - - ret = sl_command (commands, argc, argv); - if (ret == -1) { - help(NULL, argc, argv); - return 1; - } - return ret; -} diff --git a/kuser/kinit.c b/kuser/kinit.c index 017b120de..d0691ca9f 100644 --- a/kuser/kinit.c +++ b/kuser/kinit.c @@ -40,9 +40,6 @@ #include #endif -#ifndef NO_NTLM -#include "heimntlm.h" -#endif #ifndef SIGINFO #define SIGINFO SIGUSR1 @@ -88,10 +85,12 @@ static int enterprise_flag = 0; static int ok_as_delegate_flag = 0; static char *fast_armor_cache_string = NULL; static int use_referrals_flag = 0; +static char *dh_alg = NULL; +static char *sig_alg = NULL; +static char *kdf_alg = NULL; +static char *ossl_cnf = NULL; +static char *ossl_propq = NULL; static int windows_flag = 0; -#ifndef NO_NTLM -static char *ntlm_domain; -#endif static struct getargs args[] = { @@ -202,11 +201,6 @@ static struct getargs args[] = { { "kdc-hostname", 0, arg_string, &kdc_hostname, NP_("KDC host name", ""), "hostname" }, -#ifndef NO_NTLM - { "ntlm-domain", 0, arg_string, &ntlm_domain, - NP_("NTLM domain", ""), "domain" }, -#endif - { "change-default", 0, arg_negative_flag, &switch_cache_flags, NP_("switch the default cache to the new credentials cache", ""), NULL }, @@ -222,6 +216,23 @@ static struct getargs args[] = { { "use-referrals", 0, arg_flag, &use_referrals_flag, NP_("only use referrals, no dns canonicalisation", ""), NULL }, + { "key-agreement", 0, arg_string, &dh_alg, + "request given PKINIT key agreement algorithm", "ALGORITHM" }, + + { "signature-algorithm", 0, arg_string, &sig_alg, + "prefer PKINIT certificate with given key algorithm (ed25519, ed448, rsa)", "ALGORITHM" }, + + { "kdf", 0, arg_string, &kdf_alg, + "request given PKINIT key derivation algorithm", "ALGORITHM" }, + + { "ossl-cnf", 0, arg_string, &ossl_cnf, + "OpenSSL configuration file", "FILE" + }, + + { "ossl-propq", 0, arg_string, &ossl_propq, + "OpenSSL property query string (e.g., provider=pkcs11)", "PROPQ" + }, + { "windows", 0, arg_flag, &windows_flag, NP_("get windows behavior", ""), NULL }, @@ -684,41 +695,6 @@ out: return ret; } -#ifndef NO_NTLM - -static krb5_error_code -store_ntlmkey(krb5_context context, krb5_ccache id, - const char *domain, struct ntlm_buf *buf) -{ - krb5_error_code ret; - krb5_data data; - char *name; - int aret; - - ret = krb5_cc_get_config(context, id, NULL, "default-ntlm-domain", &data); - if (ret == 0) { - krb5_data_free(&data); - } else { - data.length = strlen(domain); - data.data = rk_UNCONST(domain); - ret = krb5_cc_set_config(context, id, NULL, "default-ntlm-domain", &data); - if (ret != 0) - return ret; - } - - aret = asprintf(&name, "ntlm-key-%s", domain); - if (aret == -1 || name == NULL) - return krb5_enomem(context); - - data.length = buf->length; - data.data = buf->data; - - ret = krb5_cc_set_config(context, id, NULL, name, &data); - free(name); - return ret; -} -#endif - static krb5_error_code get_new_tickets(krb5_context context, krb5_principal principal, @@ -742,10 +718,6 @@ get_new_tickets(krb5_context context, gss_OID gss_mech = GSS_C_NO_OID; krb5_principal federated_name = NULL; -#ifndef NO_NTLM - struct ntlm_buf ntlmkey; - memset(&ntlmkey, 0, sizeof(ntlmkey)); -#endif passwd[0] = '\0'; if (!interactive) @@ -900,6 +872,15 @@ get_new_tickets(krb5_context context, } if (ent_user_id) krb5_get_init_creds_opt_set_pkinit_user_certs(context, opt, ent_user_id); + if (dh_alg || sig_alg || kdf_alg) { + ret = krb5_get_init_creds_opt_set_pkinit_allowed_algs(context, opt, + dh_alg, sig_alg, + kdf_alg); + if (ret) { + krb5_warn(context, ret, "krb5_get_init_creds_opt_set_pkinit_allowed_algs"); + goto out; + } + } } if (addrs_flag != -1) @@ -1072,7 +1053,7 @@ get_new_tickets(krb5_context context, if (aret == -1) errx(1, "failed to generate passwd prompt: not enough memory"); - if (UI_UTIL_read_pw_string(passwd, sizeof(passwd)-1, prompt, 0)){ + if (_krb5_UI_UTIL_read_pw_string(passwd, sizeof(passwd)-1, prompt, 0)) { memset(passwd, 0, sizeof(passwd)); errx(1, "failed to read password"); } @@ -1090,10 +1071,6 @@ get_new_tickets(krb5_context context, ret = krb5_init_creds_get(context, ctx); -#ifndef NO_NTLM - if (ntlm_domain && passwd[0]) - heim_ntlm_nt_key(passwd, &ntlmkey); -#endif memset_s(passwd, sizeof(passwd), 0, sizeof(passwd)); switch(ret){ @@ -1184,10 +1161,6 @@ get_new_tickets(krb5_context context, if (switch_cache_flags) krb5_cc_switch(context, ccache); -#ifndef NO_NTLM - if (ntlm_domain && ntlmkey.data) - store_ntlmkey(context, ccache, ntlm_domain, &ntlmkey); -#endif if (ok_as_delegate_flag || windows_flag || use_referrals_flag) { unsigned char d = 0; @@ -1378,11 +1351,6 @@ renew_func(void *ptr) if (ret == 0) { expire = ticket_lifetime(ctx->context, ctx->ccache, ctx->principal, server_str, &renew_expire); - -#ifndef NO_AFS - if (server_str == NULL && do_afslog && k_hasafs()) - krb5_afslog(ctx->context, ctx->ccache, NULL, NULL); -#endif } update_siginfo_msg(expire, server_str); @@ -1714,6 +1682,12 @@ main(int argc, char **argv) argc -= optidx; argv += optidx; + if (ossl_cnf || ossl_propq) { + ret = krb5_set_ossl_cnf_propq(context, ossl_cnf, ossl_propq); + if (ret) + krb5_err(context, 1, ret, "krb5_set_ossl_cnf_propq"); + } + krb5_appdefault_boolean(context, "kinit", NULL, "historical_anon_pkinit", FALSE, &historical_anon_pkinit); @@ -1870,11 +1844,6 @@ main(int argc, char **argv) if (ret) krb5_err(context, 1, ret, N_("resolving credentials cache", "")); -#ifndef NO_AFS - if (argc > 1 && k_hasafs()) - k_setpag(); -#endif - if (lifetime) { int tmp = parse_time(lifetime, "s"); if (tmp < 0) @@ -1908,11 +1877,6 @@ main(int argc, char **argv) default_for ? TRUE : FALSE, server_str, ticket_life); -#ifndef NO_AFS - if (ret == 0 && server_str == NULL && do_afslog && k_hasafs()) - krb5_afslog(context, ccache, NULL, NULL); -#endif - if (unique_ccache) krb5_cc_destroy(context, ccache); exit(ret != 0); @@ -1926,11 +1890,6 @@ main(int argc, char **argv) exit(1); } -#ifndef NO_AFS - if (ret == 0 && server_str == NULL && do_afslog && k_hasafs()) - krb5_afslog(context, ccache, NULL, NULL); -#endif - if (argc > 1) { struct renew_ctx ctx; time_t timeout; @@ -1965,10 +1924,6 @@ main(int argc, char **argv) krb5_warnx(context, N_("command not found: %s", ""), argv[1]); krb5_cc_destroy(context, ccache); -#ifndef NO_AFS - if (k_hasafs()) - k_unlog(); -#endif } else { krb5_cc_close(context, ccache); ret = 0; diff --git a/kuser/klist.c b/kuser/klist.c index 62224ef87..ef333c2dc 100644 --- a/kuser/klist.c +++ b/kuser/klist.c @@ -605,78 +605,6 @@ check_expiration(krb5_context context, return 0; } -/* - * Print a list of all AFS tokens - */ - -#ifndef NO_AFS - -static void -display_tokens(int do_verbose) -{ - uint32_t i; - unsigned char t[4096]; - struct ViceIoctl parms; - - parms.in = (void *)&i; - parms.in_size = sizeof(i); - parms.out = (void *)t; - parms.out_size = sizeof(t); - - for (i = 0;; i++) { - int32_t size_secret_tok, size_public_tok; - unsigned char *cell; - struct ClearToken ct; - unsigned char *r = t; - struct timeval tv; - char buf1[20], buf2[20]; - - if(k_pioctl(NULL, VIOCGETTOK, &parms, 0) < 0) { - if(errno == EDOM) - break; - continue; - } - if(parms.out_size > sizeof(t)) - continue; - if(parms.out_size < sizeof(size_secret_tok)) - continue; - t[min(parms.out_size,sizeof(t)-1)] = 0; - memcpy(&size_secret_tok, r, sizeof(size_secret_tok)); - /* don't bother about the secret token */ - r += size_secret_tok + sizeof(size_secret_tok); - if (parms.out_size < (r - t) + sizeof(size_public_tok)) - continue; - memcpy(&size_public_tok, r, sizeof(size_public_tok)); - r += sizeof(size_public_tok); - if (parms.out_size < (r - t) + size_public_tok + sizeof(int32_t)) - continue; - memcpy(&ct, r, size_public_tok); - r += size_public_tok; - /* there is a int32_t with length of cellname, but we don't read it */ - r += sizeof(int32_t); - cell = r; - - gettimeofday (&tv, NULL); - strlcpy (buf1, printable_time(ct.BeginTimestamp), - sizeof(buf1)); - if (do_verbose || tv.tv_sec < ct.EndTimestamp) - strlcpy (buf2, printable_time(ct.EndTimestamp), - sizeof(buf2)); - else - strlcpy (buf2, N_(">>> Expired <<<", ""), sizeof(buf2)); - - printf("%s %s ", buf1, buf2); - - if ((ct.EndTimestamp - ct.BeginTimestamp) & 1) - printf(N_("User's (AFS ID %d) tokens for %s", ""), ct.ViceId, cell); - else - printf(N_("Tokens for %s", ""), cell); - if (do_verbose) - printf(" (%d)", ct.AuthHandle); - putchar('\n'); - } -} -#endif /* * display the ccache in `cred_cache' @@ -978,15 +906,5 @@ klist(struct klist_options *opt, int argc, char **argv) heim_release(s); } - if (!do_test) { -#ifndef NO_AFS - if (opt->tokens_flag && k_hasafs()) { - if (opt->v5_flag) - printf("\n"); - display_tokens(opt->verbose_flag); - } -#endif - } - return exit_status; } diff --git a/kuser/kuser_locl.h b/kuser/kuser_locl.h index 8218a6f09..24b0b5bc4 100644 --- a/kuser/kuser_locl.h +++ b/kuser/kuser_locl.h @@ -84,9 +84,6 @@ #ifdef HAVE_SYS_IOCCOM_H #include #endif -#ifndef NO_AFS -#include -#endif #include "crypto-headers.h" /* for UI_UTIL_read_pw_string */ #include diff --git a/lib/Makefile.am b/lib/Makefile.am index 0c993938c..dcc9f7dad 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -1,5 +1,3 @@ -# $Id$ - include $(top_srcdir)/Makefile.am.common if LIBEDIT @@ -17,9 +15,6 @@ endif if MAINTAINER_MODE dir_sqlite = sqlite endif -if !NO_AFS -dir_afs = kafs -endif SUBDIRS = \ roken \ @@ -34,8 +29,6 @@ SUBDIRS = \ ipc \ hx509 \ krb5 \ - ntlm \ - $(dir_afs) \ gssapi \ gss_preauth \ hdb \ diff --git a/lib/NTMakefile b/lib/NTMakefile index 79be5f093..ef7f9ee50 100644 --- a/lib/NTMakefile +++ b/lib/NTMakefile @@ -48,7 +48,7 @@ assembly=..\packages\windows\assembly !endif SUBDIRS = roken vers com_err base sl wind asn1 sqlite \ - hx509 krb5 heimdal ntlm kafs gssapi gss_preauth \ + hx509 krb5 heimdal gssapi gss_preauth \ hdb kadm5 $(dir_dce) $(plugin) $(assembly) !include ../windows/NTMakefile.w32 diff --git a/lib/asn1/Makefile.am b/lib/asn1/Makefile.am index e5af4ba20..bb741d9a0 100644 --- a/lib/asn1/Makefile.am +++ b/lib/asn1/Makefile.am @@ -100,6 +100,8 @@ bin_PROGRAMS = asn1_compile asn1_print TESTS = check-der check-gen check-gen-template check-timegm check-ber check-template check_PROGRAMS = $(TESTS) +AM_TESTS_ENVIRONMENT = HEIM_TOP_SRCDIR='$(top_srcdir)'; export HEIM_TOP_SRCDIR; HEIM_SRCDIR='$(srcdir)'; export HEIM_SRCDIR; + asn1_gen_SOURCES = asn1_gen.c asn1_print_SOURCES = asn1_print.c asn1_print_SOURCES += $(gen_files_x690sample_template) @@ -405,8 +407,10 @@ ocsp_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/ocsp.asn1 $(ASN1_COMPILE) --one-code-file --template --option-file=$(srcdir)/ocsp.opt $(srcdir)/ocsp.asn1 ocsp_template_asn1 || (rm -f ocsp_template_asn1_files ; exit 1) @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_ocsp_template_asn1.c -pkinit_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkinit.asn1 - $(ASN1_COMPILE) --one-code-file --template $(srcdir)/pkinit.asn1 pkinit_template_asn1 || (rm -f pkinit_template_asn1_files ; exit 1) +pkinit_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkinit.asn1 $(srcdir)/pkinit.opt + $(ASN1_COMPILE) --one-code-file --template \ + --option-file=$(srcdir)/pkinit.opt \ + $(srcdir)/pkinit.asn1 pkinit_template_asn1 || (rm -f pkinit_template_asn1_files ; exit 1) @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_pkinit_template_asn1.c pkcs8_template_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkcs8.asn1 @@ -459,8 +463,10 @@ ocsp_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/ocsp.asn1 $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) --option-file=$(srcdir)/ocsp.opt $(srcdir)/ocsp.asn1 ocsp_asn1 || (rm -f ocsp_asn1_files ; exit 1) @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_ocsp_asn1.c -pkinit_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkinit.asn1 - $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) $(srcdir)/pkinit.asn1 pkinit_asn1 || (rm -f pkinit_asn1_files ; exit 1) +pkinit_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkinit.asn1 $(srcdir)/pkinit.opt + $(ASN1_COMPILE) --one-code-file $(TEMPLATE_OPTION) \ + --option-file=$(srcdir)/pkinit.opt \ + $(srcdir)/pkinit.asn1 pkinit_asn1 || (rm -f pkinit_asn1_files ; exit 1) @$(CLANG_FORMAT) -style=$(CLANG_FORMAT_STYLE) -i asn1_pkinit_asn1.c pkcs8_asn1_files: asn1_compile$(EXEEXT) $(srcdir)/pkcs8.asn1 @@ -531,6 +537,7 @@ EXTRA_DIST = \ pkcs8.asn1 \ pkcs9.asn1 \ pkinit.asn1 \ + pkinit.opt \ pku2u.asn1 \ rfc2459.asn1 \ rfc2459.opt \ diff --git a/lib/asn1/NTMakefile b/lib/asn1/NTMakefile index 0c9d6ac9a..ac53cc5f0 100644 --- a/lib/asn1/NTMakefile +++ b/lib/asn1/NTMakefile @@ -299,9 +299,13 @@ $(OBJ)\asn1_ocsp_asn1.c $(OBJ)\ocsp_asn1.h: $(BINDIR)\asn1_compile.exe ocsp.asn1 || ($(RM) $(OBJ)\ocsp_asn1.h ; exit /b 1) cd $(SRCDIR) -$(OBJ)\asn1_pkinit_asn1.c $(OBJ)\pkinit_asn1.h: $(BINDIR)\asn1_compile.exe pkinit.asn1 +$(OBJ)\asn1_pkinit_asn1.c $(OBJ)\pkinit_asn1.h: $(BINDIR)\asn1_compile.exe pkinit.asn1 pkinit.opt cd $(OBJ) - $(BINDIR)\asn1_compile.exe --template --one-code-file $(SRCDIR)\pkinit.asn1 pkinit_asn1 \ + $(BINDIR)\asn1_compile.exe \ + --template \ + --one-code-file \ + --option-file=$(SRCDIR)\pkinit.opt \ + $(SRCDIR)\pkinit.asn1 pkinit_asn1 \ || ($(RM) $(OBJ)\pkinit_asn1.h ; exit /b 1) cd $(SRCDIR) diff --git a/lib/asn1/asn1-template.h b/lib/asn1/asn1-template.h index c3a21a13f..9656602d9 100644 --- a/lib/asn1/asn1-template.h +++ b/lib/asn1/asn1-template.h @@ -180,6 +180,7 @@ #define A1_OS_IS_SORTED (0x01000000) #define A1_OS_OT_IS_ARRAY (0x02000000) #define A1_OTI_IS_INTEGER (0x04000000) +#define A1_OTF_IS_OPTIONAL (0x08000000) /* Open type field is optional */ struct asn1_template { @@ -232,6 +233,7 @@ enum template_types { A1T_BOOLEAN, A1T_OID, A1T_TELETEX_STRING, + A1T_NULL, A1T_NUM_ENTRY }; diff --git a/lib/asn1/asn1parse.y b/lib/asn1/asn1parse.y index d9e3fba2d..33ba15809 100644 --- a/lib/asn1/asn1parse.y +++ b/lib/asn1/asn1parse.y @@ -1919,6 +1919,7 @@ new_type_field(char *n, int optional, Type *t) Field *f; f = ecalloc(1, sizeof(*f)); + f->opentype = 1; f->optional = optional; f->unique = 0; f->defval = 0; diff --git a/lib/asn1/check-gen.c b/lib/asn1/check-gen.c index 4941c7442..9ef295d3b 100644 --- a/lib/asn1/check-gen.c +++ b/lib/asn1/check-gen.c @@ -2282,321 +2282,50 @@ test_x690sample(void) } #if ASN1_IOS_SUPPORTED +/* + * Read a file from a given file in lib/asn1/data, NUL-terminated in case + * the file's contents are meant to be text. + */ +static void * +read_file(const char *top_srcdir_rel_fn, size_t *szp) +{ + struct stat st; + unsigned char *s; + char *fn = NULL; + ssize_t bytes; + int fd; + + if (getenv("HEIM_TOP_SRCDIR") == NULL) + errx(1, "Missing HEIM_TOP_SRCDIR environment variable!"); + + if (asprintf(&fn, "%s/lib/asn1/data/%s", + getenv("HEIM_TOP_SRCDIR"), top_srcdir_rel_fn) == -1 || + fn == NULL || + (fd = open(fn, O_RDONLY)) == -1 || + fstat(fd, &st) == -1 || + st.st_size > 10 * 1024 * 1024 || + (s = malloc(st.st_size + 1 /* 1 for a NUL */)) == NULL || + (bytes = read(fd, s, st.st_size)) == -1) + err(1, "Could not read %s/lib/asn1/data/%s", + getenv("HEIM_TOP_SRCDIR"), top_srcdir_rel_fn); + + (void) close(fd); + if (bytes != st.st_size) + errx(1, "Could not read %s/lib/asn1/data/%s", + getenv("HEIM_TOP_SRCDIR"), top_srcdir_rel_fn); + s[st.st_size] = '\0'; + if (szp) + *szp = st.st_size; + return s; +} + static int test_ios(void) { - unsigned char encoded_sample[] = { - 0x30, 0x82, 0x04, 0x8e, 0x30, 0x82, 0x03, 0x76, - 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x14, 0x6a, - 0x05, 0x97, 0xba, 0x71, 0xd7, 0xe6, 0xd3, 0xac, - 0x0e, 0xdc, 0x9e, 0xdc, 0x95, 0xa1, 0x5b, 0x99, - 0x8d, 0xe4, 0x0a, 0x30, 0x0d, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, - 0x05, 0x00, 0x30, 0x55, 0x31, 0x0b, 0x30, 0x09, - 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x43, - 0x48, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x13, 0x15, 0x53, 0x54, 0x4d, 0x69, - 0x63, 0x72, 0x6f, 0x65, 0x6c, 0x65, 0x63, 0x74, - 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x73, 0x20, 0x4e, - 0x56, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, - 0x04, 0x03, 0x13, 0x1d, 0x53, 0x54, 0x4d, 0x20, - 0x54, 0x50, 0x4d, 0x20, 0x45, 0x4b, 0x20, 0x49, - 0x6e, 0x74, 0x65, 0x72, 0x6d, 0x65, 0x64, 0x69, - 0x61, 0x74, 0x65, 0x20, 0x43, 0x41, 0x20, 0x30, - 0x35, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x38, 0x31, - 0x32, 0x31, 0x34, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x5a, 0x17, 0x0d, 0x32, 0x38, 0x31, 0x32, - 0x31, 0x34, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x5a, 0x30, 0x00, 0x30, 0x82, 0x01, 0x22, 0x30, - 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, - 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, - 0x82, 0x01, 0x01, 0x00, 0xcc, 0x14, 0xeb, 0x27, - 0xa7, 0x8c, 0xeb, 0x0e, 0xa4, 0x86, 0xfa, 0x2d, - 0xf7, 0x83, 0x5f, 0x5f, 0xa8, 0xe9, 0x05, 0xb0, - 0x97, 0x01, 0x2b, 0x5b, 0xde, 0x50, 0x38, 0x0c, - 0x35, 0x5b, 0x1a, 0x2a, 0x72, 0x1b, 0xbc, 0x3d, - 0x08, 0xdd, 0x21, 0x79, 0x6c, 0xdb, 0x23, 0x9f, - 0xa9, 0x53, 0x10, 0x65, 0x1b, 0x1b, 0x56, 0xfd, - 0x2c, 0xfe, 0x53, 0xc8, 0x73, 0x52, 0xeb, 0xd9, - 0x96, 0xe3, 0x32, 0x56, 0x16, 0x04, 0x04, 0xce, - 0x93, 0x02, 0xa0, 0x80, 0x66, 0x80, 0x1e, 0x78, - 0x6a, 0x2f, 0x86, 0xe1, 0x81, 0xf9, 0x49, 0x96, - 0x6f, 0x49, 0x2a, 0x85, 0xb5, 0x8e, 0xaa, 0x4a, - 0x6a, 0x8c, 0xb3, 0x69, 0x75, 0x51, 0xbb, 0x23, - 0x6e, 0x87, 0xcc, 0x7b, 0xf8, 0xec, 0x13, 0x47, - 0x87, 0x1c, 0x91, 0xe1, 0x54, 0x37, 0xe8, 0xf2, - 0x66, 0xbf, 0x1e, 0xa5, 0xeb, 0x27, 0x1f, 0xdc, - 0xf3, 0x74, 0xd8, 0xb4, 0x7d, 0xf8, 0xbc, 0xe8, - 0x9e, 0x1f, 0xad, 0x61, 0xc2, 0xa0, 0x88, 0xcb, - 0x40, 0x36, 0xb3, 0x59, 0xcb, 0x72, 0xa2, 0x94, - 0x97, 0x3f, 0xed, 0xcc, 0xf0, 0xc3, 0x40, 0xaf, - 0xfd, 0x14, 0xb6, 0x4f, 0x04, 0x11, 0x65, 0x58, - 0x1a, 0xca, 0x34, 0x14, 0x7c, 0x1c, 0x75, 0x61, - 0x70, 0x47, 0x05, 0x8f, 0x7e, 0xd7, 0xd6, 0x03, - 0xe0, 0x32, 0x50, 0x80, 0x94, 0xfa, 0x73, 0xe8, - 0xb9, 0x15, 0x3d, 0xa3, 0xbf, 0x25, 0x5d, 0x2c, - 0xbb, 0xc5, 0xdf, 0x30, 0x1b, 0xa8, 0xf7, 0x4d, - 0x19, 0x8b, 0xeb, 0xce, 0x86, 0x04, 0x0f, 0xc1, - 0xd2, 0x92, 0x7c, 0x76, 0x57, 0x41, 0x44, 0x90, - 0xd8, 0x02, 0xf4, 0x82, 0xf3, 0xeb, 0xf2, 0xde, - 0x35, 0xee, 0x14, 0x9a, 0x1a, 0x6d, 0xe8, 0xd1, - 0x68, 0x91, 0xfb, 0xfb, 0xa0, 0x2a, 0x18, 0xaf, - 0xe5, 0x9f, 0x9d, 0x6f, 0x14, 0x97, 0x44, 0xe5, - 0xf0, 0xd5, 0x59, 0xb1, 0x02, 0x03, 0x01, 0x00, - 0x01, 0xa3, 0x82, 0x01, 0xa9, 0x30, 0x82, 0x01, - 0xa5, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, - 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x1a, 0xdb, - 0x99, 0x4a, 0xb5, 0x8b, 0xe5, 0x7a, 0x0c, 0xc9, - 0xb9, 0x00, 0xe7, 0x85, 0x1e, 0x1a, 0x43, 0xc0, - 0x86, 0x60, 0x30, 0x42, 0x06, 0x03, 0x55, 0x1d, - 0x20, 0x04, 0x3b, 0x30, 0x39, 0x30, 0x37, 0x06, - 0x04, 0x55, 0x1d, 0x20, 0x00, 0x30, 0x2f, 0x30, - 0x2d, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, - 0x07, 0x02, 0x01, 0x16, 0x21, 0x68, 0x74, 0x74, - 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, - 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x54, - 0x50, 0x4d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x6f, 0x72, 0x79, 0x2f, 0x30, 0x59, - 0x06, 0x03, 0x55, 0x1d, 0x11, 0x01, 0x01, 0xff, - 0x04, 0x4f, 0x30, 0x4d, 0xa4, 0x4b, 0x30, 0x49, - 0x31, 0x16, 0x30, 0x14, 0x06, 0x05, 0x67, 0x81, - 0x05, 0x02, 0x01, 0x0c, 0x0b, 0x69, 0x64, 0x3a, - 0x35, 0x33, 0x35, 0x34, 0x34, 0x44, 0x32, 0x30, - 0x31, 0x17, 0x30, 0x15, 0x06, 0x05, 0x67, 0x81, - 0x05, 0x02, 0x02, 0x0c, 0x0c, 0x53, 0x54, 0x33, - 0x33, 0x48, 0x54, 0x50, 0x48, 0x41, 0x48, 0x43, - 0x30, 0x31, 0x16, 0x30, 0x14, 0x06, 0x05, 0x67, - 0x81, 0x05, 0x02, 0x03, 0x0c, 0x0b, 0x69, 0x64, - 0x3a, 0x30, 0x30, 0x34, 0x39, 0x30, 0x30, 0x30, - 0x38, 0x30, 0x67, 0x06, 0x03, 0x55, 0x1d, 0x09, - 0x04, 0x60, 0x30, 0x5e, 0x30, 0x17, 0x06, 0x05, - 0x67, 0x81, 0x05, 0x02, 0x10, 0x31, 0x0e, 0x30, - 0x0c, 0x0c, 0x03, 0x32, 0x2e, 0x30, 0x02, 0x01, - 0x00, 0x02, 0x02, 0x00, 0x8a, 0x30, 0x43, 0x06, - 0x05, 0x67, 0x81, 0x05, 0x02, 0x12, 0x31, 0x3a, - 0x30, 0x38, 0x02, 0x01, 0x00, 0x01, 0x01, 0xff, - 0xa0, 0x03, 0x0a, 0x01, 0x01, 0xa1, 0x03, 0x0a, - 0x01, 0x00, 0xa2, 0x03, 0x0a, 0x01, 0x00, 0xa3, - 0x10, 0x30, 0x0e, 0x16, 0x03, 0x33, 0x2e, 0x31, - 0x0a, 0x01, 0x04, 0x0a, 0x01, 0x02, 0x01, 0x01, - 0xff, 0xa4, 0x0f, 0x30, 0x0d, 0x16, 0x05, 0x31, - 0x34, 0x30, 0x2d, 0x32, 0x0a, 0x01, 0x02, 0x01, - 0x01, 0x00, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, - 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, - 0x05, 0x20, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, - 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, - 0x30, 0x10, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, - 0x09, 0x30, 0x07, 0x06, 0x05, 0x67, 0x81, 0x05, - 0x08, 0x01, 0x30, 0x4a, 0x06, 0x08, 0x2b, 0x06, - 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x3e, - 0x30, 0x3c, 0x30, 0x3a, 0x06, 0x08, 0x2b, 0x06, - 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x2e, - 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x73, - 0x65, 0x63, 0x75, 0x72, 0x65, 0x2e, 0x67, 0x6c, - 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x69, 0x67, 0x6e, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x74, 0x6d, - 0x74, 0x70, 0x6d, 0x65, 0x6b, 0x69, 0x6e, 0x74, - 0x30, 0x35, 0x2e, 0x63, 0x72, 0x74, 0x30, 0x0d, - 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, - 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, - 0x01, 0x00, 0x3d, 0x4c, 0x38, 0x1e, 0x5b, 0x4f, - 0x1b, 0xcb, 0xe0, 0x9c, 0x63, 0xd5, 0x2f, 0x1f, - 0x04, 0x57, 0x0c, 0xae, 0xa1, 0x42, 0xfd, 0x9c, - 0xd9, 0x42, 0x04, 0x3b, 0x11, 0xf8, 0xe3, 0xbd, - 0xcf, 0x50, 0x00, 0x7a, 0xe1, 0x6c, 0xf8, 0x86, - 0x90, 0x13, 0x04, 0x1e, 0x92, 0xcd, 0xd3, 0x28, - 0x0b, 0xa4, 0xb5, 0x1f, 0xbb, 0xd4, 0x05, 0x82, - 0xed, 0x75, 0x02, 0x19, 0xe2, 0x61, 0xa6, 0x95, - 0x09, 0x56, 0x74, 0x85, 0x5a, 0xac, 0xeb, 0x52, - 0x0a, 0xda, 0xff, 0x9e, 0x7e, 0x90, 0x84, 0x80, - 0xa3, 0x9c, 0xdc, 0xf9, 0x00, 0x46, 0x2d, 0x91, - 0x71, 0x96, 0x0f, 0xfe, 0x55, 0xd3, 0xac, 0x49, - 0xe8, 0xc9, 0x81, 0x34, 0x1b, 0xbd, 0x2e, 0xfb, - 0xcc, 0x25, 0x2a, 0x4c, 0x18, 0xa4, 0xf3, 0xb7, - 0xc8, 0x4c, 0xce, 0x42, 0xce, 0x70, 0xa2, 0x08, - 0xc8, 0x4d, 0x26, 0x30, 0xa7, 0xab, 0xfb, 0xe7, - 0x2d, 0x62, 0x71, 0xe7, 0x5b, 0x9f, 0xf1, 0xc9, - 0x71, 0xd2, 0x0e, 0xb3, 0xdb, 0xd7, 0x63, 0xf1, - 0xe0, 0x4d, 0x83, 0x4e, 0xaa, 0x69, 0x2d, 0x2e, - 0x40, 0x01, 0xbb, 0xf4, 0x73, 0x0a, 0x3e, 0x3f, - 0xda, 0x97, 0x11, 0xae, 0x38, 0x65, 0x24, 0xd9, - 0x1c, 0x63, 0xbe, 0x0e, 0x51, 0x6d, 0x00, 0xd5, - 0xc6, 0x14, 0x1f, 0xcc, 0xf6, 0xc5, 0x39, 0xf3, - 0x51, 0x8e, 0x18, 0x00, 0x49, 0x86, 0x5b, 0xe1, - 0x6b, 0x69, 0xca, 0xe1, 0xf8, 0xcb, 0x7f, 0xdc, - 0x47, 0x4b, 0x38, 0xf7, 0xee, 0x56, 0xcb, 0xe7, - 0xd8, 0xa8, 0x9d, 0x9b, 0xa9, 0x9b, 0x65, 0xd5, - 0x26, 0x5a, 0xef, 0x32, 0xaa, 0x62, 0x42, 0x6b, - 0x10, 0xe6, 0xd7, 0x5b, 0xb8, 0x67, 0x7e, 0xc4, - 0x4f, 0x75, 0x5b, 0xbc, 0x28, 0x06, 0xfd, 0x2b, - 0x4e, 0x04, 0xbd, 0xf5, 0xd4, 0x42, 0x59, 0xdb, - 0xea, 0xa4, 0x2b, 0x6f, 0x56, 0x3d, 0xf7, 0xaa, - 0x75, 0x06, - }; - char cert_json[] = { - "{\"_type\":\"Certificate\",\"tbsCertificate\":{\"_type\":\"TBSCertificate" - "\",\"_save\":\"30820376A00302010202146A0597BA71D7E6D3AC0EDC9EDC95A15" - "B998DE40A300D06092A864886F70D01010B05003055310B30090603550406130" - "24348311E301C060355040A131553544D6963726F656C656374726F6E6963732" - "04E56312630240603550403131D53544D2054504D20454B20496E7465726D656" - "469617465204341203035301E170D3138313231343030303030305A170D32383" - "13231343030303030305A300030820122300D06092A864886F70D01010105000" - "382010F003082010A0282010100CC14EB27A78CEB0EA486FA2DF7835F5FA8E90" - "5B097012B5BDE50380C355B1A2A721BBC3D08DD21796CDB239FA95310651B1B5" - "6FD2CFE53C87352EBD996E33256160404CE9302A08066801E786A2F86E181F94" - "9966F492A85B58EAA4A6A8CB3697551BB236E87CC7BF8EC1347871C91E15437E" - "8F266BF1EA5EB271FDCF374D8B47DF8BCE89E1FAD61C2A088CB4036B359CB72A" - "294973FEDCCF0C340AFFD14B64F041165581ACA34147C1C75617047058F7ED7D" - "603E032508094FA73E8B9153DA3BF255D2CBBC5DF301BA8F74D198BEBCE86040" - "FC1D2927C7657414490D802F482F3EBF2DE35EE149A1A6DE8D16891FBFBA02A1" - "8AFE59F9D6F149744E5F0D559B10203010001A38201A9308201A5301F0603551" - "D230418301680141ADB994AB58BE57A0CC9B900E7851E1A43C08660304206035" - "51D20043B303930370604551D2000302F302D06082B060105050702011621687" - "474703A2F2F7777772E73742E636F6D2F54504D2F7265706F7369746F72792F3" - "0590603551D110101FF044F304DA44B304931163014060567810502010C0B696" - "43A353335343444323031173015060567810502020C0C5354333348545048414" - "8433031163014060567810502030C0B69643A303034393030303830670603551" - "D090460305E301706056781050210310E300C0C03322E300201000202008A304" - "306056781050212313A30380201000101FFA0030A0101A1030A0100A2030A010" - "0A310300E1603332E310A01040A01020101FFA40F300D16053134302D320A010" - "2010100300E0603551D0F0101FF040403020520300C0603551D130101FF04023" - "00030100603551D250409300706056781050801304A06082B060105050701010" - "43E303C303A06082B06010505073002862E687474703A2F2F7365637572652E6" - "76C6F62616C7369676E2E636F6D2F73746D74706D656B696E7430352E637274\"" - ",\"version\":\"rfc3280_version_3\",\"serialNumber\":\"6A0597BA71D7E6D3A" - "C0EDC9EDC95A15B998DE40A\",\"signature\":{\"_type\":\"AlgorithmIdentifi" - "er\",\"algorithm\":{\"_type\":\"OBJECT IDENTIFIER\",\"oid\":\"1.2.840.1135" - "49.1.1.11\",\"components\":[1,2,840,113549,1,1,11],\"name\":\"id-pkcs1" - "-sha256WithRSAEncryption\"},\"parameters\":\"0500\"},\"issuer\":{\"_choi" - "ce\":\"rdnSequence\",\"value\":[[{\"_type\":\"AttributeTypeAndValue\",\"ty" - "pe\":{\"_type\":\"OBJECT IDENTIFIER\",\"oid\":\"2.5.4.6\",\"components\":[2" - ",5,4,6],\"name\":\"id-at-countryName\"},\"value\":{\"_choice\":\"printabl" - "eString\",\"value\":\"CH\"}}],[{\"_type\":\"AttributeTypeAndValue\",\"type" - "\":{\"_type\":\"OBJECT IDENTIFIER\",\"oid\":\"2.5.4.10\",\"components\":[2," - "5,4,10],\"name\":\"id-at-organizationName\"},\"value\":{\"_choice\":\"pri" - "ntableString\",\"value\":\"STMicroelectronics NV\"}}],[{\"_type\":\"Attr" - "ibuteTypeAndValue\",\"type\":{\"_type\":\"OBJECT IDENTIFIER\",\"oid\":\"2." - "5.4.3\",\"components\":[2,5,4,3],\"name\":\"id-at-commonName\"},\"value\"" - ":{\"_choice\":\"printableString\",\"value\":\"STM TPM EK Intermediate C" - "A 05\"}}]]},\"validity\":{\"_type\":\"Validity\",\"notBefore\":{\"_choice\"" - ":\"utcTime\",\"value\":\"2018-12-14T00:00:00Z\"},\"notAfter\":{\"_choice\"" - ":\"utcTime\",\"value\":\"2028-12-14T00:00:00Z\"}},\"subject\":{\"_choice\"" - ":\"rdnSequence\",\"value\":[]},\"subjectPublicKeyInfo\":{\"_type\":\"Subj" - "ectPublicKeyInfo\",\"algorithm\":{\"_type\":\"AlgorithmIdentifier\",\"al" - "gorithm\":{\"_type\":\"OBJECT IDENTIFIER\",\"oid\":\"1.2.840.113549.1.1." - "1\",\"components\":[1,2,840,113549,1,1,1],\"name\":\"id-pkcs1-rsaEncry" - "ption\"},\"parameters\":\"0500\"},\"subjectPublicKey\":\"2160:3082010A02" - "82010100CC14EB27A78CEB0EA486FA2DF7835F5FA8E905B097012B5BDE50380C" - "355B1A2A721BBC3D08DD21796CDB239FA95310651B1B56FD2CFE53C87352EBD9" - "96E33256160404CE9302A08066801E786A2F86E181F949966F492A85B58EAA4A" - "6A8CB3697551BB236E87CC7BF8EC1347871C91E15437E8F266BF1EA5EB271FDC" - "F374D8B47DF8BCE89E1FAD61C2A088CB4036B359CB72A294973FEDCCF0C340AF" - "FD14B64F041165581ACA34147C1C75617047058F7ED7D603E032508094FA73E8" - "B9153DA3BF255D2CBBC5DF301BA8F74D198BEBCE86040FC1D2927C7657414490" - "D802F482F3EBF2DE35EE149A1A6DE8D16891FBFBA02A18AFE59F9D6F149744E5" - "F0D559B10203010001\"},\"issuerUniqueID\":null,\"subjectUniqueID\":nul" - "l,\"extensions\":[{\"_type\":\"Extension\",\"extnID\":{\"_type\":\"OBJECT I" - "DENTIFIER\",\"oid\":\"2.5.29.35\",\"components\":[2,5,29,35],\"name\":\"id" - "-x509-ce-authorityKeyIdentifier\"},\"critical\":false,\"extnValue\":\"" - "301680141ADB994AB58BE57A0CC9B900E7851E1A43C08660\",\"_extnValue_ch" - "oice\":\"ext-AuthorityKeyIdentifier\",\"_extnValue\":{\"_type\":\"Author" - "ityKeyIdentifier\",\"keyIdentifier\":\"1ADB994AB58BE57A0CC9B900E7851" - "E1A43C08660\",\"authorityCertIssuer\":null,\"authorityCertSerialNumb" - "er\":null}},{\"_type\":\"Extension\",\"extnID\":{\"_type\":\"OBJECT IDENTI" - "FIER\",\"oid\":\"2.5.29.32\",\"components\":[2,5,29,32],\"name\":\"id-x509" - "-ce-certificatePolicies\"},\"critical\":false,\"extnValue\":\"30393037" - "0604551D2000302F302D06082B060105050702011621687474703A2F2F777777" - "2E73742E636F6D2F54504D2F7265706F7369746F72792F\",\"_extnValue_choi" - "ce\":\"ext-CertificatePolicies\",\"_extnValue\":[{\"_type\":\"PolicyInfo" - "rmation\",\"policyIdentifier\":{\"_type\":\"OBJECT IDENTIFIER\",\"oid\":\"" - "2.5.29.32.0\",\"components\":[2,5,29,32,0],\"name\":\"id-x509-ce-certi" - "ficatePolicies-anyPolicy\"},\"policyQualifiers\":[{\"_type\":\"PolicyQ" - "ualifierInfo\",\"policyQualifierId\":{\"_type\":\"OBJECT IDENTIFIER\",\"" - "oid\":\"1.3.6.1.5.5.7.2.1\",\"components\":[1,3,6,1,5,5,7,2,1],\"name\"" - ":\"id-pkix-qt-cps\"},\"qualifier\":\"1621687474703A2F2F7777772E73742E" - "636F6D2F54504D2F7265706F7369746F72792F\",\"_qualifier_choice\":\"pq-" - "CPS\"}]}]},{\"_type\":\"Extension\",\"extnID\":{\"_type\":\"OBJECT IDENTIF" - "IER\",\"oid\":\"2.5.29.17\",\"components\":[2,5,29,17],\"name\":\"id-x509-" - "ce-subjectAltName\"},\"critical\":true,\"extnValue\":\"304DA44B3049311" - "63014060567810502010C0B69643A35333534344432303117301506056781050" - "2020C0C53543333485450484148433031163014060567810502030C0B69643A3" - "030343930303038\",\"_extnValue_choice\":\"ext-SubjectAltName\",\"_extn" - "Value\":[{\"_choice\":\"directoryName\",\"value\":{\"_choice\":\"rdnSequen" - "ce\",\"value\":[[{\"_type\":\"AttributeTypeAndValue\",\"type\":{\"_type\":\"" - "OBJECT IDENTIFIER\",\"oid\":\"2.23.133.2.1\",\"components\":[2,23,133,2" - ",1],\"name\":\"tcg-at-tpmManufacturer\"},\"value\":{\"_choice\":\"utf8Str" - "ing\",\"value\":\"id:53544D20\"}}],[{\"_type\":\"AttributeTypeAndValue\"," - "\"type\":{\"_type\":\"OBJECT IDENTIFIER\",\"oid\":\"2.23.133.2.2\",\"compon" - "ents\":[2,23,133,2,2],\"name\":\"tcg-at-tpmModel\"},\"value\":{\"_choice" - "\":\"utf8String\",\"value\":\"ST33HTPHAHC0\"}}],[{\"_type\":\"AttributeTyp" - "eAndValue\",\"type\":{\"_type\":\"OBJECT IDENTIFIER\",\"oid\":\"2.23.133.2" - ".3\",\"components\":[2,23,133,2,3],\"name\":\"tcg-at-tpmVersion\"},\"val" - "ue\":{\"_choice\":\"utf8String\",\"value\":\"id:00490008\"}}]]}}]},{\"_typ" - "e\":\"Extension\",\"extnID\":{\"_type\":\"OBJECT IDENTIFIER\",\"oid\":\"2.5." - "29.9\",\"components\":[2,5,29,9],\"name\":\"id-x509-ce-subjectDirector" - "yAttributes\"},\"critical\":false,\"extnValue\":\"305E3017060567810502" - "10310E300C0C03322E300201000202008A304306056781050212313A30380201" - "000101FFA0030A0101A1030A0100A2030A0100A310300E1603332E310A01040A" - "01020101FFA40F300D16053134302D320A0102010100\",\"_extnValue_choice" - "\":\"ext-SubjectDirectoryAttributes\",\"_extnValue\":[{\"_type\":\"Attri" - "buteSet\",\"type\":{\"_type\":\"OBJECT IDENTIFIER\",\"oid\":\"2.23.133.2.1" - "6\",\"components\":[2,23,133,2,16],\"name\":\"tcg-at-tpmSpecification\"" - "},\"values\":[\"300C0C03322E300201000202008A\"],\"_values_choice\":\"at" - "-TPMSpecification\",\"_values\":[{\"_type\":\"TPMSpecification\",\"famil" - "y\":\"2.0\",\"level\":0,\"revision\":138}]},{\"_type\":\"AttributeSet\",\"ty" - "pe\":{\"_type\":\"OBJECT IDENTIFIER\",\"oid\":\"2.23.133.2.18\",\"componen" - "ts\":[2,23,133,2,18],\"name\":\"tcg-at-tpmSecurityAssertions\"},\"valu" - "es\":[\"30380201000101FFA0030A0101A1030A0100A2030A0100A310300E1603" - "332E310A01040A01020101FFA40F300D16053134302D320A0102010100\"],\"_v" - "alues_choice\":\"at-TPMSecurityAssertions\",\"_values\":[{\"_type\":\"TP" - "MSecurityAssertions\",\"version\":0,\"fieldUpgradable\":true,\"ekGener" - "ationType\":\"ekgt-injected\",\"ekGenerationLocation\":\"tpmManufactur" - "er\",\"ekCertificateGenerationLocation\":\"tpmManufacturer\",\"ccInfo\"" - ":{\"_type\":\"CommonCriteriaMeasures\",\"version\":\"3.1\",\"assurancelev" - "el\":\"ealevel4\",\"evaluationStatus\":\"evaluationCompleted\",\"plus\":t" - "rue,\"strengthOfFunction\":null,\"profileOid\":null,\"profileUri\":nul" - "l,\"targetOid\":null,\"targetUri\":null},\"fipsLevel\":{\"_type\":\"FIPSL" - "evel\",\"version\":\"140-2\",\"level\":\"sllevel2\",\"plus\":false},\"iso900" - "0Certified\":false,\"iso9000Uri\":null}]}]},{\"_type\":\"Extension\",\"e" - "xtnID\":{\"_type\":\"OBJECT IDENTIFIER\",\"oid\":\"2.5.29.15\",\"component" - "s\":[2,5,29,15],\"name\":\"id-x509-ce-keyUsage\"},\"critical\":true,\"ex" - "tnValue\":\"03020520\",\"_extnValue_choice\":\"ext-KeyUsage\",\"_extnVal" - "ue\":[\"keyEncipherment\"]},{\"_type\":\"Extension\",\"extnID\":{\"_type\":" - "\"OBJECT IDENTIFIER\",\"oid\":\"2.5.29.19\",\"components\":[2,5,29,19],\"" - "name\":\"id-x509-ce-basicConstraints\"},\"critical\":true,\"extnValue\"" - ":\"3000\",\"_extnValue_choice\":\"ext-BasicConstraints\",\"_extnValue\":" - "{\"_type\":\"BasicConstraints\",\"cA\":false,\"pathLenConstraint\":null}" - "},{\"_type\":\"Extension\",\"extnID\":{\"_type\":\"OBJECT IDENTIFIER\",\"oi" - "d\":\"2.5.29.37\",\"components\":[2,5,29,37],\"name\":\"id-x509-ce-extKe" - "yUsage\"},\"critical\":false,\"extnValue\":\"300706056781050801\",\"_ext" - "nValue_choice\":\"ext-ExtKeyUsage\",\"_extnValue\":[{\"_type\":\"OBJECT " - "IDENTIFIER\",\"oid\":\"2.23.133.8.1\",\"components\":[2,23,133,8,1],\"na" - "me\":\"tcg-kp-EKCertificate\"}]},{\"_type\":\"Extension\",\"extnID\":{\"_t" - "ype\":\"OBJECT IDENTIFIER\",\"oid\":\"1.3.6.1.5.5.7.1.1\",\"components\":" - "[1,3,6,1,5,5,7,1,1],\"name\":\"id-pkix-pe-authorityInfoAccess\"},\"cr" - "itical\":false,\"extnValue\":\"303C303A06082B06010505073002862E68747" - "4703A2F2F7365637572652E676C6F62616C7369676E2E636F6D2F73746D74706" - "D656B696E7430352E637274\",\"_extnValue_choice\":\"ext-AuthorityInfoA" - "ccess\",\"_extnValue\":[{\"_type\":\"AccessDescription\",\"accessMethod\"" - ":{\"_type\":\"OBJECT IDENTIFIER\",\"oid\":\"1.3.6.1.5.5.7.48.2\",\"compon" - "ents\":[1,3,6,1,5,5,7,48,2],\"name\":\"id-pkix-ad-caIssuers\"},\"acces" - "sLocation\":{\"_choice\":\"uniformResourceIdentifier\",\"value\":\"http:" - "//secure.globalsign.com/stmtpmekint05.crt\"}}]}]},\"signatureAlgor" - "ithm\":{\"_type\":\"AlgorithmIdentifier\",\"algorithm\":{\"_type\":\"OBJEC" - "T IDENTIFIER\",\"oid\":\"1.2.840.113549.1.1.11\",\"components\":[1,2,84" - "0,113549,1,1,11],\"name\":\"id-pkcs1-sha256WithRSAEncryption\"},\"par" - "ameters\":\"0500\"},\"signatureValue\":\"2048:3D4C381E5B4F1BCBE09C63D5" - "2F1F04570CAEA142FD9CD942043B11F8E3BDCF50007AE16CF8869013041E92CD" - "D3280BA4B51FBBD40582ED750219E261A695095674855AACEB520ADAFF9E7E90" - "8480A39CDCF900462D9171960FFE55D3AC49E8C981341BBD2EFBCC252A4C18A4" - "F3B7C84CCE42CE70A208C84D2630A7ABFBE72D6271E75B9FF1C971D20EB3DBD7" - "63F1E04D834EAA692D2E4001BBF4730A3E3FDA9711AE386524D91C63BE0E516D" - "00D5C6141FCCF6C539F3518E180049865BE16B69CAE1F8CB7FDC474B38F7EE56" - "CBE7D8A89D9BA99B65D5265AEF32AA62426B10E6D75BB8677EC44F755BBC2806" - "FD2B4E04BDF5D44259DBEAA42B6F563DF7AA7506\"" - "}" - }; + size_t cert_der_sz = 0; + size_t cert_json_sz = 0; + unsigned char *cert_der = read_file("test_ios_cert.der", &cert_der_sz); + char *cert_json = read_file("test_ios_cert.json", &cert_json_sz); heim_octet_string os; Certificate c0, c1; size_t i, nknown, size; @@ -2609,16 +2338,17 @@ test_ios(void) * Decode a value that has plenty of open types with values of known * alternatives in them, then check that we got what we wanted. */ - ret = decode_Certificate(encoded_sample, sizeof(encoded_sample), - &c0, &size); + ret = decode_Certificate(cert_der, cert_der_sz, &c0, &size); if (ret) return 1; - if (size != sizeof(encoded_sample)) + if (size != cert_der_sz) return 1; s = print_Certificate(&c0, 0); if (!s) return 1; + if (cert_json[cert_json_sz - 1] == '\n') + cert_json[--cert_json_sz] = '\0'; /* Trim trailing newline */ if (strcmp(s, cert_json) != 0) return 1; free(s); @@ -2657,9 +2387,9 @@ test_ios(void) ASN1_MALLOC_ENCODE(Certificate, os.data, os.length, &c1, &size, ret); if (ret) return 1; - if (os.length != size || size != sizeof(encoded_sample)) + if (os.length != size || size != cert_der_sz) return 1; - if (memcmp(os.data, encoded_sample, os.length) != 0) + if (memcmp(os.data, cert_der, os.length) != 0) return 1; der_free_octet_string(&os); @@ -2674,9 +2404,9 @@ test_ios(void) ASN1_MALLOC_ENCODE(Certificate, os.data, os.length, &c0, &size, ret); if (ret) return 1; - if (os.length != size || size != sizeof(encoded_sample)) + if (os.length != size || size != cert_der_sz) return 1; - if (memcmp(os.data, encoded_sample, os.length) != 0) + if (memcmp(os.data, cert_der, os.length) != 0) return 1; der_free_octet_string(&os); @@ -2690,9 +2420,9 @@ test_ios(void) ASN1_MALLOC_ENCODE(Certificate, os.data, os.length, &c1, &size, ret); if (ret) return 1; - if (os.length != size || size != sizeof(encoded_sample)) + if (os.length != size || size != cert_der_sz) return 1; - if (memcmp(os.data, encoded_sample, os.length) != 0) + if (memcmp(os.data, cert_der, os.length) != 0) return 1; der_free_octet_string(&os); diff --git a/lib/asn1/cms.asn1 b/lib/asn1/cms.asn1 index ae547e573..578ffca01 100644 --- a/lib/asn1/cms.asn1 +++ b/lib/asn1/cms.asn1 @@ -32,17 +32,18 @@ SignatureAlgorithmIdentifier ::= AlgorithmIdentifier ContentType ::= OBJECT IDENTIFIER MessageDigest ::= OCTET STRING -ContentInfo ::= SEQUENCE { - contentType ContentType, - content [0] EXPLICIT HEIM_ANY OPTIONAL -- DEFINED BY contentType -} - EncapsulatedContentInfo ::= SEQUENCE { eContentType ContentType, eContent [0] EXPLICIT OCTET STRING OPTIONAL } -CertificateSet ::= SET OF HEIM_ANY +CertificateChoices ::= CHOICE { + certificate Certificate, + any HEIM_ANY +} + +-- Really, for us this is strictly a Certificate. See RFC 5911. +CertificateSet ::= SET OF CertificateChoices CertificateList ::= Certificate @@ -146,4 +147,61 @@ CMSRC2CBCParameter ::= SEQUENCE { CMSCBCParameter ::= OCTET STRING +-- We don't have a) a builtin TYPE-IDENTIFIER class, b) class equality +-- assignment yet! +_CONTENT-TYPE ::= CLASS { + &id OBJECT IDENTIFIER UNIQUE, + &Type OPTIONAL +} + +ContentInfo{_CONTENT-TYPE:ContentSet} ::= SEQUENCE { + contentType _CONTENT-TYPE.&id({ContentSet}), + content [0] EXPLICIT _CONTENT-TYPE.&Type({ContentSet}{@contentType}) OPTIONAL +} + +-- Content Type Object Identifiers and Objects + +id-ct-contentInfo OBJECT IDENTIFIER ::= { iso(1) member-body(2) + us(840) rsadsi(113549) pkcs(1) pkcs9(9) smime(16) ct(1) 6 } + +id-data OBJECT IDENTIFIER ::= { iso(1) member-body(2) + us(840) rsadsi(113549) pkcs(1) pkcs7(7) 1 } + +OctetString ::= OCTET STRING -- workaround compiler bug +ct-Data _CONTENT-TYPE ::= { &id id-data, &Type OctetString } + +id-signedData OBJECT IDENTIFIER ::= { iso(1) member-body(2) + us(840) rsadsi(113549) pkcs(1) pkcs7(7) 2 } + +ct-SignedData _CONTENT-TYPE ::= { &id id-signedData, &Type SignedData } + +id-envelopedData OBJECT IDENTIFIER ::= { iso(1) member-body(2) + us(840) rsadsi(113549) pkcs(1) pkcs7(7) 3 } + +ct-EnvelopedData _CONTENT-TYPE ::= { &id id-envelopedData, &Type EnvelopedData } + +id-digestedData OBJECT IDENTIFIER ::= { iso(1) member-body(2) + us(840) rsadsi(113549) pkcs(1) pkcs7(7) 5 } +-- ct-DigestedData _CONTENT-TYPE ::= { &id id-digestedData, &Type DigestedData } + +id-encryptedData OBJECT IDENTIFIER ::= { iso(1) member-body(2) + us(840) rsadsi(113549) pkcs(1) pkcs7(7) 6 } + +-- ct-EncryptedData _CONTENT-TYPE ::= { &id id-encryptedData, &Type EncryptedData } + +id-ct-authData OBJECT IDENTIFIER ::= { iso(1) member-body(2) +us(840) rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) ct(1) 2 } + +-- ct-AuthenticatedData _CONTENT-TYPE ::= +-- { &id id-ct-authData, &Type AuthenticatedData } + +ContentSet _CONTENT-TYPE ::= { + -- Define the set of content types to be recognized. + ct-Data | ct-SignedData | ct-EnvelopedData + -- | ct-EncryptedData + -- | ct-AuthenticatedData | ct-DigestedData +} + +ContentInfo ::= ContentInfo{ContentSet} + END diff --git a/lib/asn1/data/test_ios_cert.der b/lib/asn1/data/test_ios_cert.der new file mode 100644 index 0000000000000000000000000000000000000000..94c15ee9d4d2a1b3d8024742c91dc455caa1f9bb GIT binary patch literal 1170 zcmXqLV(BwzVlG?2%*4pVB$CBCeOKZ2XP4LT-I;f1>cZ%my-&Cdc-c6$+C196^D;7W zvoaWj8gd(OvN4CUun99cdls3Dj~atk(GhDiIE>9&c)Qk$jER;&@sf4JbVlvydjS?a zrqNPbMbdk0IqoV}=G<1EzcN@LRa!diug<^V6U9NVZ%%t`6eh;Pa&9uyf`+sPxr!|P zwug;BJ*VY+YPD|dTjiD2vpKUgaJO<^`o*Xr_jK9}6s zQu|}ii+S>E6AvxuIPGAzIr4PTqAAnu-=6t!*kS!&k!}7gf~gTwr%Xg@WJ(hY+*$kU zu3uw*U=+|W^^$mKzhY@U&-#*=h|5K4_=y7Qx@*%GT{c(m!{9J zKixBZCo)Sa_r=AGiNAj@(2`jHbpG6Yk?Af^KU|I6$i&RZz__@Haiu{M<5B~8Hs(-S zWflnou?7*T+cUkkc0aA+Ik}VJd8?e1^MSSm11FFI1r}=qO9OK@mQYy*1_ONqT{aGF zHbz!fb|ywK#f*}Y0xNy}^73-M;u5{&{9OHz0AKy0)Pnrt%#!?~N_~S!kQsuEjQ?5u z4Sbh)8+aOu8Hlj4rZ=)OG4gO{rdXL8o0^!o7#SFf8;C;0nRs}DLyV0*LIOM-J)8{? z8koTv3=B*x4Gat{4AMbHbFw5D#2JV~bP5>q8SwBh8|fJ^F)}bQF?1O?LnMR@tqd%f z7#SED|1V(XVq{#%%*DvC2t+IvFyIqoHr6xbVr1cBWMX9ezl7g_SB%xr#6Z^wEWlvE z2eODCOSzzW7UU~1EY z23c`xa%oYjUV2V`QesYVW_lht^omPzOA2yRvorHb3{3Tsi%O7_GdDOnGcwrvSja{D zOP_u)C;6(rJWDvwx`j@E=iGE+u@?OCc<=cDhN_1-KiVb;v&c<4ds%~f$yWK@S6G|g zmNH2`N?bOTGpwXFYR&5)u3P`-)lFz=SUl&>PX;&LiG|bn|Ak&&vP>^!$$}3or3)zI{FU;{)Gjzg3yKdJc@c zzZ7%X+25KjxXvO~<)%#XKEA+QhO5U!^PlCa-E&5@0=BbB2PS@XY_qO={ zF6{L48!P6{UO7AUs#?^0qg6>x*#gh5NAF0lJK|p&y+?!XueKk{-mh1jB5%K1qMaXR J`+Zd@8vvKZkM;ln literal 0 HcmV?d00001 diff --git a/lib/asn1/data/test_ios_cert.json b/lib/asn1/data/test_ios_cert.json new file mode 100644 index 000000000..691848535 --- /dev/null +++ b/lib/asn1/data/test_ios_cert.json @@ -0,0 +1 @@ +{"_type":"Certificate","tbsCertificate":{"_type":"TBSCertificate","_save":"30820376A00302010202146A0597BA71D7E6D3AC0EDC9EDC95A15B998DE40A300D06092A864886F70D01010B05003055310B3009060355040613024348311E301C060355040A131553544D6963726F656C656374726F6E696373204E56312630240603550403131D53544D2054504D20454B20496E7465726D656469617465204341203035301E170D3138313231343030303030305A170D3238313231343030303030305A300030820122300D06092A864886F70D01010105000382010F003082010A0282010100CC14EB27A78CEB0EA486FA2DF7835F5FA8E905B097012B5BDE50380C355B1A2A721BBC3D08DD21796CDB239FA95310651B1B56FD2CFE53C87352EBD996E33256160404CE9302A08066801E786A2F86E181F949966F492A85B58EAA4A6A8CB3697551BB236E87CC7BF8EC1347871C91E15437E8F266BF1EA5EB271FDCF374D8B47DF8BCE89E1FAD61C2A088CB4036B359CB72A294973FEDCCF0C340AFFD14B64F041165581ACA34147C1C75617047058F7ED7D603E032508094FA73E8B9153DA3BF255D2CBBC5DF301BA8F74D198BEBCE86040FC1D2927C7657414490D802F482F3EBF2DE35EE149A1A6DE8D16891FBFBA02A18AFE59F9D6F149744E5F0D559B10203010001A38201A9308201A5301F0603551D230418301680141ADB994AB58BE57A0CC9B900E7851E1A43C0866030420603551D20043B303930370604551D2000302F302D06082B060105050702011621687474703A2F2F7777772E73742E636F6D2F54504D2F7265706F7369746F72792F30590603551D110101FF044F304DA44B304931163014060567810502010C0B69643A353335343444323031173015060567810502020C0C53543333485450484148433031163014060567810502030C0B69643A303034393030303830670603551D090460305E301706056781050210310E300C0C03322E300201000202008A304306056781050212313A30380201000101FFA0030A0101A1030A0100A2030A0100A310300E1603332E310A01040A01020101FFA40F300D16053134302D320A0102010100300E0603551D0F0101FF040403020520300C0603551D130101FF0402300030100603551D250409300706056781050801304A06082B06010505070101043E303C303A06082B06010505073002862E687474703A2F2F7365637572652E676C6F62616C7369676E2E636F6D2F73746D74706D656B696E7430352E637274","version":"rfc3280_version_3","serialNumber":"6A0597BA71D7E6D3AC0EDC9EDC95A15B998DE40A","signature":{"_type":"AlgorithmIdentifier","algorithm":{"_type":"OBJECT IDENTIFIER","oid":"1.2.840.113549.1.1.11","components":[1,2,840,113549,1,1,11],"name":"id-pkcs1-sha256WithRSAEncryption"},"parameters":"0500","_parameters_choice":"sa-sha256WithRSAEncryption","_parameters":"null"},"issuer":{"_choice":"rdnSequence","value":[[{"_type":"AttributeTypeAndValue","type":{"_type":"OBJECT IDENTIFIER","oid":"2.5.4.6","components":[2,5,4,6],"name":"id-at-countryName"},"value":{"_choice":"printableString","value":"CH"}}],[{"_type":"AttributeTypeAndValue","type":{"_type":"OBJECT IDENTIFIER","oid":"2.5.4.10","components":[2,5,4,10],"name":"id-at-organizationName"},"value":{"_choice":"printableString","value":"STMicroelectronics NV"}}],[{"_type":"AttributeTypeAndValue","type":{"_type":"OBJECT IDENTIFIER","oid":"2.5.4.3","components":[2,5,4,3],"name":"id-at-commonName"},"value":{"_choice":"printableString","value":"STM TPM EK Intermediate CA 05"}}]]},"validity":{"_type":"Validity","notBefore":{"_choice":"utcTime","value":"2018-12-14T00:00:00Z"},"notAfter":{"_choice":"utcTime","value":"2028-12-14T00:00:00Z"}},"subject":{"_choice":"rdnSequence","value":[]},"subjectPublicKeyInfo":{"_type":"SubjectPublicKeyInfo","_save":"30820122300D06092A864886F70D01010105000382010F003082010A0282010100CC14EB27A78CEB0EA486FA2DF7835F5FA8E905B097012B5BDE50380C355B1A2A721BBC3D08DD21796CDB239FA95310651B1B56FD2CFE53C87352EBD996E33256160404CE9302A08066801E786A2F86E181F949966F492A85B58EAA4A6A8CB3697551BB236E87CC7BF8EC1347871C91E15437E8F266BF1EA5EB271FDCF374D8B47DF8BCE89E1FAD61C2A088CB4036B359CB72A294973FEDCCF0C340AFFD14B64F041165581ACA34147C1C75617047058F7ED7D603E032508094FA73E8B9153DA3BF255D2CBBC5DF301BA8F74D198BEBCE86040FC1D2927C7657414490D802F482F3EBF2DE35EE149A1A6DE8D16891FBFBA02A18AFE59F9D6F149744E5F0D559B10203010001","algorithm":{"_type":"AlgorithmIdentifier","algorithm":{"_type":"OBJECT IDENTIFIER","oid":"1.2.840.113549.1.1.1","components":[1,2,840,113549,1,1,1],"name":"id-pkcs1-rsaEncryption"},"parameters":"0500","_parameters_choice":""},"subjectPublicKey":"2160:3082010A0282010100CC14EB27A78CEB0EA486FA2DF7835F5FA8E905B097012B5BDE50380C355B1A2A721BBC3D08DD21796CDB239FA95310651B1B56FD2CFE53C87352EBD996E33256160404CE9302A08066801E786A2F86E181F949966F492A85B58EAA4A6A8CB3697551BB236E87CC7BF8EC1347871C91E15437E8F266BF1EA5EB271FDCF374D8B47DF8BCE89E1FAD61C2A088CB4036B359CB72A294973FEDCCF0C340AFFD14B64F041165581ACA34147C1C75617047058F7ED7D603E032508094FA73E8B9153DA3BF255D2CBBC5DF301BA8F74D198BEBCE86040FC1D2927C7657414490D802F482F3EBF2DE35EE149A1A6DE8D16891FBFBA02A18AFE59F9D6F149744E5F0D559B10203010001"},"issuerUniqueID":null,"subjectUniqueID":null,"extensions":[{"_type":"Extension","extnID":{"_type":"OBJECT IDENTIFIER","oid":"2.5.29.35","components":[2,5,29,35],"name":"id-x509-ce-authorityKeyIdentifier"},"critical":false,"extnValue":"301680141ADB994AB58BE57A0CC9B900E7851E1A43C08660","_extnValue_choice":"ext-AuthorityKeyIdentifier","_extnValue":{"_type":"AuthorityKeyIdentifier","keyIdentifier":"1ADB994AB58BE57A0CC9B900E7851E1A43C08660","authorityCertIssuer":null,"authorityCertSerialNumber":null}},{"_type":"Extension","extnID":{"_type":"OBJECT IDENTIFIER","oid":"2.5.29.32","components":[2,5,29,32],"name":"id-x509-ce-certificatePolicies"},"critical":false,"extnValue":"303930370604551D2000302F302D06082B060105050702011621687474703A2F2F7777772E73742E636F6D2F54504D2F7265706F7369746F72792F","_extnValue_choice":"ext-CertificatePolicies","_extnValue":[{"_type":"PolicyInformation","policyIdentifier":{"_type":"OBJECT IDENTIFIER","oid":"2.5.29.32.0","components":[2,5,29,32,0],"name":"id-x509-ce-certificatePolicies-anyPolicy"},"policyQualifiers":[{"_type":"PolicyQualifierInfo","policyQualifierId":{"_type":"OBJECT IDENTIFIER","oid":"1.3.6.1.5.5.7.2.1","components":[1,3,6,1,5,5,7,2,1],"name":"id-pkix-qt-cps"},"qualifier":"1621687474703A2F2F7777772E73742E636F6D2F54504D2F7265706F7369746F72792F","_qualifier_choice":"pq-CPS"}]}]},{"_type":"Extension","extnID":{"_type":"OBJECT IDENTIFIER","oid":"2.5.29.17","components":[2,5,29,17],"name":"id-x509-ce-subjectAltName"},"critical":true,"extnValue":"304DA44B304931163014060567810502010C0B69643A353335343444323031173015060567810502020C0C53543333485450484148433031163014060567810502030C0B69643A3030343930303038","_extnValue_choice":"ext-SubjectAltName","_extnValue":[{"_choice":"directoryName","value":{"_choice":"rdnSequence","value":[[{"_type":"AttributeTypeAndValue","type":{"_type":"OBJECT IDENTIFIER","oid":"2.23.133.2.1","components":[2,23,133,2,1],"name":"tcg-at-tpmManufacturer"},"value":{"_choice":"utf8String","value":"id:53544D20"}}],[{"_type":"AttributeTypeAndValue","type":{"_type":"OBJECT IDENTIFIER","oid":"2.23.133.2.2","components":[2,23,133,2,2],"name":"tcg-at-tpmModel"},"value":{"_choice":"utf8String","value":"ST33HTPHAHC0"}}],[{"_type":"AttributeTypeAndValue","type":{"_type":"OBJECT IDENTIFIER","oid":"2.23.133.2.3","components":[2,23,133,2,3],"name":"tcg-at-tpmVersion"},"value":{"_choice":"utf8String","value":"id:00490008"}}]]}}]},{"_type":"Extension","extnID":{"_type":"OBJECT IDENTIFIER","oid":"2.5.29.9","components":[2,5,29,9],"name":"id-x509-ce-subjectDirectoryAttributes"},"critical":false,"extnValue":"305E301706056781050210310E300C0C03322E300201000202008A304306056781050212313A30380201000101FFA0030A0101A1030A0100A2030A0100A310300E1603332E310A01040A01020101FFA40F300D16053134302D320A0102010100","_extnValue_choice":"ext-SubjectDirectoryAttributes","_extnValue":[{"_type":"AttributeSet","type":{"_type":"OBJECT IDENTIFIER","oid":"2.23.133.2.16","components":[2,23,133,2,16],"name":"tcg-at-tpmSpecification"},"values":["300C0C03322E300201000202008A"],"_values_choice":"at-TPMSpecification","_values":[{"_type":"TPMSpecification","family":"2.0","level":0,"revision":138}]},{"_type":"AttributeSet","type":{"_type":"OBJECT IDENTIFIER","oid":"2.23.133.2.18","components":[2,23,133,2,18],"name":"tcg-at-tpmSecurityAssertions"},"values":["30380201000101FFA0030A0101A1030A0100A2030A0100A310300E1603332E310A01040A01020101FFA40F300D16053134302D320A0102010100"],"_values_choice":"at-TPMSecurityAssertions","_values":[{"_type":"TPMSecurityAssertions","version":0,"fieldUpgradable":true,"ekGenerationType":"ekgt-injected","ekGenerationLocation":"tpmManufacturer","ekCertificateGenerationLocation":"tpmManufacturer","ccInfo":{"_type":"CommonCriteriaMeasures","version":"3.1","assurancelevel":"ealevel4","evaluationStatus":"evaluationCompleted","plus":true,"strengthOfFunction":null,"profileOid":null,"profileUri":null,"targetOid":null,"targetUri":null},"fipsLevel":{"_type":"FIPSLevel","version":"140-2","level":"sllevel2","plus":false},"iso9000Certified":false,"iso9000Uri":null}]}]},{"_type":"Extension","extnID":{"_type":"OBJECT IDENTIFIER","oid":"2.5.29.15","components":[2,5,29,15],"name":"id-x509-ce-keyUsage"},"critical":true,"extnValue":"03020520","_extnValue_choice":"ext-KeyUsage","_extnValue":["keyEncipherment"]},{"_type":"Extension","extnID":{"_type":"OBJECT IDENTIFIER","oid":"2.5.29.19","components":[2,5,29,19],"name":"id-x509-ce-basicConstraints"},"critical":true,"extnValue":"3000","_extnValue_choice":"ext-BasicConstraints","_extnValue":{"_type":"BasicConstraints","cA":false,"pathLenConstraint":null}},{"_type":"Extension","extnID":{"_type":"OBJECT IDENTIFIER","oid":"2.5.29.37","components":[2,5,29,37],"name":"id-x509-ce-extKeyUsage"},"critical":false,"extnValue":"300706056781050801","_extnValue_choice":"ext-ExtKeyUsage","_extnValue":[{"_type":"OBJECT IDENTIFIER","oid":"2.23.133.8.1","components":[2,23,133,8,1],"name":"tcg-kp-EKCertificate"}]},{"_type":"Extension","extnID":{"_type":"OBJECT IDENTIFIER","oid":"1.3.6.1.5.5.7.1.1","components":[1,3,6,1,5,5,7,1,1],"name":"id-pkix-pe-authorityInfoAccess"},"critical":false,"extnValue":"303C303A06082B06010505073002862E687474703A2F2F7365637572652E676C6F62616C7369676E2E636F6D2F73746D74706D656B696E7430352E637274","_extnValue_choice":"ext-AuthorityInfoAccess","_extnValue":[{"_type":"AccessDescription","accessMethod":{"_type":"OBJECT IDENTIFIER","oid":"1.3.6.1.5.5.7.48.2","components":[1,3,6,1,5,5,7,48,2],"name":"id-pkix-ad-caIssuers"},"accessLocation":{"_choice":"uniformResourceIdentifier","value":"http://secure.globalsign.com/stmtpmekint05.crt"}}]}]},"signatureAlgorithm":{"_type":"AlgorithmIdentifier","algorithm":{"_type":"OBJECT IDENTIFIER","oid":"1.2.840.113549.1.1.11","components":[1,2,840,113549,1,1,11],"name":"id-pkcs1-sha256WithRSAEncryption"},"parameters":"0500","_parameters_choice":"sa-sha256WithRSAEncryption","_parameters":"null"},"signatureValue":"2048:3D4C381E5B4F1BCBE09C63D52F1F04570CAEA142FD9CD942043B11F8E3BDCF50007AE16CF8869013041E92CDD3280BA4B51FBBD40582ED750219E261A695095674855AACEB520ADAFF9E7E908480A39CDCF900462D9171960FFE55D3AC49E8C981341BBD2EFBCC252A4C18A4F3B7C84CCE42CE70A208C84D2630A7ABFBE72D6271E75B9FF1C971D20EB3DBD763F1E04D834EAA692D2E4001BBF4730A3E3FDA9711AE386524D91C63BE0E516D00D5C6141FCCF6C539F3518E180049865BE16B69CAE1F8CB7FDC474B38F7EE56CBE7D8A89D9BA99B65D5265AEF32AA62426B10E6D75BB8677EC44F755BBC2806FD2B4E04BDF5D44259DBEAA42B6F563DF7AA7506"} diff --git a/lib/asn1/der_get.c b/lib/asn1/der_get.c index 06564b7ca..5cdcebaf1 100644 --- a/lib/asn1/der_get.c +++ b/lib/asn1/der_get.c @@ -158,6 +158,14 @@ der_get_length (const unsigned char *p, size_t len, return 0; } +int ASN1CALL +der_get_null(const unsigned char *p, size_t len, int *data, size_t *size) +{ + *data = 0; + *size = 0; + return 0; +} + int ASN1CALL der_get_boolean(const unsigned char *p, size_t len, int *data, size_t *size) { diff --git a/lib/asn1/der_length.c b/lib/asn1/der_length.c index cd50df846..0503cfda7 100644 --- a/lib/asn1/der_length.c +++ b/lib/asn1/der_length.c @@ -294,6 +294,12 @@ der_length_utctime (const time_t *t) return ret; } +size_t ASN1CALL +der_length_null(const int *k) +{ + return 0; +} + size_t ASN1CALL der_length_boolean (const int *k) { diff --git a/lib/asn1/der_print.c b/lib/asn1/der_print.c index dada747a9..e9a82eb62 100644 --- a/lib/asn1/der_print.c +++ b/lib/asn1/der_print.c @@ -44,6 +44,12 @@ der_print_general_string(const heim_general_string *str, int flags) return strdup(*str); } +char * ASN1CALL +der_print_null(const int *i, int flags) +{ + return strdup("null"); +} + char * ASN1CALL der_print_boolean(const int *i, int flags) { diff --git a/lib/asn1/der_put.c b/lib/asn1/der_put.c index 106d45602..12e174179 100644 --- a/lib/asn1/der_put.c +++ b/lib/asn1/der_put.c @@ -227,6 +227,13 @@ der_put_length (unsigned char *p, size_t len, size_t val, size_t *size) return 0; } +int ASN1CALL +der_put_null(unsigned char *p, size_t len, const int *v, size_t *size) +{ + *size = 0; + return 0; +} + int ASN1CALL der_put_boolean(unsigned char *p, size_t len, const int *data, size_t *size) { diff --git a/lib/asn1/gen.c b/lib/asn1/gen.c index 2fa394657..e8d8fc848 100644 --- a/lib/asn1/gen.c +++ b/lib/asn1/gen.c @@ -1125,6 +1125,7 @@ define_open_type(int level, const char *newbasename, const char *name, const cha fprintf(jsonfile, "\"objectsetname\":\"%s\",", os->symbol->name); fprintf(jsonfile, "\"typeidmember\":\"%s\",", typeidmember->name); fprintf(jsonfile, "\"opentypemember\":\"%s\",", opentypemember->name); + /* XXX We need to include more metadata about the fields */ fprintf(jsonfile, "\"typeidfield\":\"%s\",", typeidfield->name); fprintf(jsonfile, "\"opentypefield\":\"%s\",", opentypefield->name); diff --git a/lib/asn1/gen_template.c b/lib/asn1/gen_template.c index 67d18ecff..d8d57598b 100644 --- a/lib/asn1/gen_template.c +++ b/lib/asn1/gen_template.c @@ -714,10 +714,16 @@ sort_object_set(IOSObjectSet *os, /* Object set to sort fields of */ { IOSObject **objects; IOSObject *o; + Field *f; size_t i, nobjs = 0; + int opentypefield_is_optional = 0; *objectsp = NULL; + HEIM_TAILQ_FOREACH(f, os->iosclass->fields, fields) { + if (f->opentype && f->optional) + opentypefield_is_optional = 1; + } HEIM_TAILQ_FOREACH(o, os->objects, objects) { ObjectField *typeidobjf = NULL; ObjectField *of; @@ -726,7 +732,7 @@ sort_object_set(IOSObjectSet *os, /* Object set to sort fields of */ if (strcmp(of->name, typeidfield->name) == 0) typeidobjf = of; } - if (!typeidobjf) { + if (!typeidobjf && !opentypefield_is_optional) { warnx("Ignoring incomplete object specification of %s " "(missing type ID field)", o->symbol ? o->symbol->name : ""); @@ -764,8 +770,15 @@ template_object_set(IOSObjectSet *os, Field *typeidfield, Field *opentypefield) { IOSObject **objects = NULL; IOSObject *o; + Field *f; struct tlist *tl; size_t nobjs, i; + int opentypefield_is_optional = 0; + + HEIM_TAILQ_FOREACH(f, os->iosclass->fields, fields) { + if (f->opentype && f->optional) + opentypefield_is_optional = 1; + } if (os->symbol->emitted_template) return; @@ -789,7 +802,7 @@ template_object_set(IOSObjectSet *os, Field *typeidfield, Field *opentypefield) } if (!typeidobjf) continue; /* We've warned about this one already when sorting */ - if (!opentypeobjf) { + if (!opentypeobjf && !opentypefield_is_optional) { warnx("Ignoring incomplete object specification of %s " "(missing open type field)", o->symbol ? o->symbol->name : ""); @@ -820,12 +833,18 @@ template_object_set(IOSObjectSet *os, Field *typeidfield, Field *opentypefield) "for open type type-ID fields"); } - if (asprintf(&s, "sizeof(%s)", - opentypeobjf->type->symbol->gen_name) == -1 || !s) - err(1, "Out of memory"); - add_line_pointer_reference(&tl->template, - opentypeobjf->type->symbol->gen_name, s, - "A1_OP_OPENTYPE"); + if (!opentypeobjf) { + if (asprintf(&s, "0") == -1 || !s) + err(1, "Out of memory"); + add_line(&tl->template, "{ A1_OP_OPENTYPE, 0, 0 }"); + } else { + if (asprintf(&s, "sizeof(%s)", + opentypeobjf->type->symbol->gen_name) == -1 || !s) + err(1, "Out of memory"); + add_line_pointer_reference(&tl->template, + opentypeobjf->type->symbol->gen_name, s, + "A1_OP_OPENTYPE"); + } free(s); } free(objects); @@ -862,7 +881,8 @@ template_open_type(struct templatehead *temp, * We always sort object sets for now as we can't import * values yet, so they must all be known. */ - "A1_OP_OPENTYPE_OBJSET | A1_OS_IS_SORTED |%s | (%llu << 10) | %llu", + "A1_OP_OPENTYPE_OBJSET | A1_OS_IS_SORTED | %s | %s | (%llu << 10) | %llu", + opentypefield->optional ? "A1_OTF_IS_OPTIONAL" : "0", is_array_of_open_type ? "A1_OS_OT_IS_ARRAY" : "0", (unsigned long long)opentypeidx, (unsigned long long)typeididx); @@ -1022,6 +1042,7 @@ template_members(struct templatehead *temp, add_line(temp, "{ A1_PARSE_T(A1T_OID), %s, NULL }", poffset); break; case TNull: + add_line(temp, "{ A1_PARSE_T(A1T_NULL), %s, NULL }", poffset); break; case TBitString: { struct templatehead template; @@ -1176,6 +1197,9 @@ template_members(struct templatehead *temp, if (typeidmember == m) typeididx = i; if (opentypemember == m) opentypeidx = i; + if (opentypemember && opentypemember == m) + m->optional = opentypemember->optional; + if (name) { if (asprintf(&newbasename, "%s_%s", basetype, name) < 0) errx(1, "malloc"); diff --git a/lib/asn1/krb5.asn1 b/lib/asn1/krb5.asn1 index 00a0acbc0..58039225d 100644 --- a/lib/asn1/krb5.asn1 +++ b/lib/asn1/krb5.asn1 @@ -77,6 +77,7 @@ EXPORTS TicketFlags, TransitedEncoding, TypedData, + TYPED-DATA, KrbFastResponse, KrbFastFinished, KrbFastReq, diff --git a/lib/asn1/krb5.opt b/lib/asn1/krb5.opt index a8bd85c52..b61098f44 100644 --- a/lib/asn1/krb5.opt +++ b/lib/asn1/krb5.opt @@ -5,5 +5,11 @@ --sequence=ETYPE-INFO --sequence=ETYPE-INFO2 --preserve-binary=KDC-REQ-BODY +# We need to preserve KDC-REQ for, e.g., RFC 8636, where the KDF takes the +# encoded AS-REQ (which is a KDC-REQ) as an input, so we'll a) use the _save +# field of the generated KDC_REQ to store that encoded AS-REQ on the client +# side, and b) because we'll be saving it on decode in the _save field we can +# also use it on the KDC side. +--preserve-binary=KDC-REQ --decorate=PrincipalNameAttrs:void *:pac --decorate=Principal:PrincipalNameAttrs:nameattrs? diff --git a/lib/asn1/pkcs12.asn1 b/lib/asn1/pkcs12.asn1 index 61d3e2ca9..8278d0d6a 100644 --- a/lib/asn1/pkcs12.asn1 +++ b/lib/asn1/pkcs12.asn1 @@ -5,7 +5,7 @@ PKCS12 DEFINITIONS ::= BEGIN IMPORTS ContentInfo FROM cms - DigestInfo FROM rfc2459 + DigestInfo, AlgorithmIdentifier FROM rfc2459 HEIM_ANY, HEIM_ANY_SET FROM heim; -- The PFX PDU @@ -78,4 +78,51 @@ PKCS12-OctetString ::= OCTET STRING -- KeyBag ::= PrivateKeyInfo -- PKCS8ShroudedKeyBag ::= EncryptedPrivateKeyInfo +-- PKCS#5 v2.0/v2.1 (RFC 8018) definitions for modern PKCS#12 PBE + +id-pkcs-5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) + rsadsi(113549) pkcs(1) pkcs-5(5) } + +id-PBES2 OBJECT IDENTIFIER ::= { id-pkcs-5 13 } +id-PBKDF2 OBJECT IDENTIFIER ::= { id-pkcs-5 12 } + +-- PBKDF2 PRF algorithm OIDs (from RFC 8018, using RSA DigestAlgorithm arc) +-- id-rsadsi OBJECT IDENTIFIER ::= { 1 2 840 113549 } +-- id-digestAlgorithm OBJECT IDENTIFIER ::= { id-rsadsi 2 } +id-hmacWithSHA1 OBJECT IDENTIFIER ::= + { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 7 } +id-hmacWithSHA256 OBJECT IDENTIFIER ::= + { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 9 } +id-hmacWithSHA384 OBJECT IDENTIFIER ::= + { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 10 } +id-hmacWithSHA512 OBJECT IDENTIFIER ::= + { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 11 } + +-- PBES2 encryption scheme OIDs (from RFC 8018 / NIST) +id-aes128-CBC OBJECT IDENTIFIER ::= + { joint-iso-itu-t(2) country(16) us(840) organization(1) + gov(101) csor(3) nistAlgorithms(4) aes(1) 2 } +id-aes192-CBC OBJECT IDENTIFIER ::= + { joint-iso-itu-t(2) country(16) us(840) organization(1) + gov(101) csor(3) nistAlgorithms(4) aes(1) 22 } +id-aes256-CBC OBJECT IDENTIFIER ::= + { joint-iso-itu-t(2) country(16) us(840) organization(1) + gov(101) csor(3) nistAlgorithms(4) aes(1) 42 } + +-- PBKDF2-params (RFC 8018, Section A.2) +-- Note: salt can be CHOICE { specified OCTET STRING, otherSource AlgorithmIdentifier } +-- but in practice it's always an OCTET STRING, so we simplify +PBKDF2-params ::= SEQUENCE { + salt OCTET STRING, + iterationCount INTEGER (1..4294967295), + keyLength INTEGER (1..4294967295) OPTIONAL, + prf AlgorithmIdentifier OPTIONAL -- default id-hmacWithSHA1 +} + +-- PBES2-params (RFC 8018, Section A.4) +PBES2-params ::= SEQUENCE { + keyDerivationFunc AlgorithmIdentifier, -- id-PBKDF2 + encryptionScheme AlgorithmIdentifier -- e.g., id-aes256-CBC +} + END diff --git a/lib/asn1/pkinit.asn1 b/lib/asn1/pkinit.asn1 index 9de00596b..a57500605 100644 --- a/lib/asn1/pkinit.asn1 +++ b/lib/asn1/pkinit.asn1 @@ -2,7 +2,7 @@ PKINIT DEFINITIONS ::= BEGIN -IMPORTS EncryptionKey, PrincipalName, Realm, KerberosTime, Checksum, Ticket FROM krb5 +IMPORTS EncryptionKey, PrincipalName, Realm, KerberosTime, Checksum FROM krb5 IssuerAndSerialNumber FROM cms SubjectPublicKeyInfo, AlgorithmIdentifier FROM rfc2459 HEIM_ANY FROM heim; @@ -26,6 +26,7 @@ id-pkinit-kdf OBJECT IDENTIFIER ::= { id-pkinit 6 } id-pkinit-kdf-ah-sha1 OBJECT IDENTIFIER ::= { id-pkinit-kdf 1 } id-pkinit-kdf-ah-sha256 OBJECT IDENTIFIER ::= { id-pkinit-kdf 2 } id-pkinit-kdf-ah-sha512 OBJECT IDENTIFIER ::= { id-pkinit-kdf 3 } +id-pkinit-kdf-ah-sha384 OBJECT IDENTIFIER ::= { id-pkinit-kdf 4 } id-pkinit-san OBJECT IDENTIFIER ::= { iso(1) org(3) dod(6) internet(1) security(5) kerberosv5(2) @@ -86,13 +87,15 @@ PKAuthenticator ::= SEQUENCE { ... } +SupportedKDFs ::= SEQUENCE OF KDFAlgorithmId + AuthPack ::= SEQUENCE { pkAuthenticator [0] PKAuthenticator, clientPublicValue [1] SubjectPublicKeyInfo OPTIONAL, supportedCMSTypes [2] SEQUENCE OF AlgorithmIdentifier OPTIONAL, clientDHNonce [3] DHNonce OPTIONAL, ..., - supportedKDFs [4] SEQUENCE OF KDFAlgorithmId OPTIONAL, + supportedKDFs [4] SupportedKDFs OPTIONAL, ... } @@ -130,6 +133,9 @@ ReplyKeyPack ::= SEQUENCE { TD-DH-PARAMETERS ::= SEQUENCE OF AlgorithmIdentifier +-- No need for this one since it's the same as TD-DH-PARAMETERS: +-- TD-CMS-DIGEST-ALGORITHMS-DATA ::= SEQUENCE OF AlgorithmIdentifier + -- Windows compat glue -- @@ -193,7 +199,7 @@ PkinitSuppPubInfo ::= SEQUENCE { enctype [0] INTEGER (-2147483648..2147483647), as-REQ [1] OCTET STRING, pk-as-rep [2] OCTET STRING, - ticket [3] Ticket, + -- ticket [3] Ticket, (removed prior to publication of RFC 8636) ... } diff --git a/lib/asn1/pkinit.opt b/lib/asn1/pkinit.opt index a55ecc331..c6e73bebf 100644 --- a/lib/asn1/pkinit.opt +++ b/lib/asn1/pkinit.opt @@ -1 +1,5 @@ ---sequence=TD_DH_PARAMETERS +--sequence=TD-DH-PARAMETERS +--sequence=SupportedKDFs +# RFC 8636 takes an encoded PA-PK-AS-REP as an input, so we need to preserve it +# on decode on the client side. +--preserve-binary=PA-PK-AS-REP diff --git a/lib/asn1/rfc2459.asn1 b/lib/asn1/rfc2459.asn1 index 7ceefe330..473cd56e9 100644 --- a/lib/asn1/rfc2459.asn1 +++ b/lib/asn1/rfc2459.asn1 @@ -29,7 +29,10 @@ id-pkcs1-rsaEncryption OBJECT IDENTIFIER ::= { id-pkcs-1 1 } id-pkcs1-md2WithRSAEncryption OBJECT IDENTIFIER ::= { id-pkcs-1 2 } id-pkcs1-md5WithRSAEncryption OBJECT IDENTIFIER ::= { id-pkcs-1 4 } id-pkcs1-sha1WithRSAEncryption OBJECT IDENTIFIER ::= { id-pkcs-1 5 } +-- 1.2.840.113549.1.1.5 id-pkcs1-sha256WithRSAEncryption OBJECT IDENTIFIER ::= { id-pkcs-1 11 } +-- 1.2.840.113549.1.1.11 +-- 1.2.840.10046.4.3 id-pkcs1-sha384WithRSAEncryption OBJECT IDENTIFIER ::= { id-pkcs-1 12 } id-pkcs1-sha512WithRSAEncryption OBJECT IDENTIFIER ::= { id-pkcs-1 13 } @@ -69,7 +72,7 @@ id-secsig-sha-1WithRSAEncryption OBJECT IDENTIFIER ::= { iso(1) identified-organ id-nistAlgorithm OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) 4 } - + id-nist-aes-algs OBJECT IDENTIFIER ::= { id-nistAlgorithm 1 } id-aes-128-cbc OBJECT IDENTIFIER ::= { id-nist-aes-algs 2 } @@ -121,6 +124,11 @@ id-ecdsa-with-SHA1 OBJECT IDENTIFIER ::= { -- some EC group ids +id-X25519 OBJECT IDENTIFIER ::= { 1 3 101 110 } +id-X448 OBJECT IDENTIFIER ::= { 1 3 101 111 } +id-Ed25519 OBJECT IDENTIFIER ::= { 1 3 101 112 } +id-Ed448 OBJECT IDENTIFIER ::= { 1 3 101 113 } + id-ec-group-secp256r1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 7 } @@ -184,11 +192,86 @@ id-at-emailAddress AttributeType ::= id-x509-ce OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 29} -AlgorithmIdentifier ::= SEQUENCE { - algorithm OBJECT IDENTIFIER, - parameters HEIM_ANY OPTIONAL +-- Cryptographic parameter types we might refer to from object sets for +-- parameterizing AlgorithmIdentifier. +ECParameters ::= CHOICE { + namedCurve OBJECT IDENTIFIER + -- implicitCurve NULL + -- specifiedCurve SpecifiedECDomain } +DSAParams ::= SEQUENCE { + p INTEGER, + q INTEGER, + g INTEGER +} + +ValidationParms ::= SEQUENCE { + seed BIT STRING, + pgenCounter INTEGER +} + +DomainParameters ::= SEQUENCE { + p INTEGER, -- odd prime, p=jq +1 + g INTEGER, -- generator, g + q INTEGER OPTIONAL, -- factor of p-1 + j INTEGER OPTIONAL, -- subgroup factor + validationParms ValidationParms OPTIONAL -- ValidationParms +} + +-- As defined by PKCS3 +DHParameter ::= SEQUENCE { + prime INTEGER, -- odd prime, p=jq +1 + base INTEGER, -- generator, g + privateValueLength INTEGER OPTIONAL +} + +ParamOptions ::= ENUMERATED { + -- rfc 5911 + required (0), -- Parameters MUST be encoded in structure + preferredPresent (1), -- Parameters SHOULD be encoded in structure + preferredAbsent (2), -- Parameters SHOULD NOT be encoded in structure + absent (3), -- Parameters MUST NOT be encoded in structure + inheritable (4), -- Parameters are inherited if not present + optional (5), -- Parameters MAY be encoded in the structure + ... +} + +-- Our compiler is not yet ready for this because it doesn't yet support +-- OPTIONAL (nor DEFAULT) in CLASS definitions, much less WITH SYNTAX: + +_ALGORITHM ::= CLASS { -- rfc 5911 + &algorithm OBJECT IDENTIFIER UNIQUE, + &Params OPTIONAL + -- ¶mPresence ParamOptions DEFAULT absent, + -- &smimeCaps SMIME-CAPS OPTIONAL +} -- WITH SYNTAX { + -- IDENTIFIER &id + -- [PARAMS [TYPE &Params] ARE ¶mPresence] + -- [SMIME-CAPS &smimeCaps] + -- } + +AlgorithmIdentifier{_ALGORITHM:AlgorithmSet} ::= SEQUENCE { + algorithm _ALGORITHM.&algorithm({AlgorithmSet}), + parameters _ALGORITHM.&Params({AlgorithmSet}{@algorithm}) OPTIONAL +} + +-- But it would be _really_ nice to be able to support the ALGORITHM class. + +--AlgorithmIdentifier ::= SEQUENCE { +-- algorithm OBJECT IDENTIFIER, +-- parameters HEIM_ANY OPTIONAL +--} + +NullType ::= NULL -- workaround bug in the compiler +sa-dsaWithSHA1 _ALGORITHM ::= { &algorithm id-dsa-with-sha1, &Params NullType } +sa-rsaWithSHA1 _ALGORITHM ::= { &algorithm id-pkcs1-sha1WithRSAEncryption, &Params NullType } +sa-sha256WithRSAEncryption _ALGORITHM ::= {&algorithm id-pkcs1-sha256WithRSAEncryption, &Params NullType } +KnownAlgorithms _ALGORITHM ::= { + sa-dsaWithSHA1 | sa-rsaWithSHA1 | sa-sha256WithRSAEncryption +} +AlgorithmIdentifier ::= AlgorithmIdentifier{KnownAlgorithms} + AttributeType ::= OBJECT IDENTIFIER AttributeValue ::= HEIM_ANY @@ -326,26 +409,6 @@ Certificate ::= SEQUENCE { Certificates ::= SEQUENCE OF Certificate -ValidationParms ::= SEQUENCE { - seed BIT STRING, - pgenCounter INTEGER -} - -DomainParameters ::= SEQUENCE { - p INTEGER, -- odd prime, p=jq +1 - g INTEGER, -- generator, g - q INTEGER OPTIONAL, -- factor of p-1 - j INTEGER OPTIONAL, -- subgroup factor - validationParms ValidationParms OPTIONAL -- ValidationParms -} - --- As defined by PKCS3 -DHParameter ::= SEQUENCE { - prime INTEGER, -- odd prime, p=jq +1 - base INTEGER, -- generator, g - privateValueLength INTEGER OPTIONAL -} - DHPublicKey ::= INTEGER GeneralName ::= CHOICE { @@ -544,22 +607,35 @@ DSASigValue ::= SEQUENCE { DSAPublicKey ::= INTEGER -DSAParams ::= SEQUENCE { - p INTEGER, - q INTEGER, - g INTEGER +-- rfc4055 + +-- XXX We don't currently support values of SEQUENCE types, so we can't uses +-- these in the below DEFAULTs which are therefore commented out. +-- +-- sha1Identifier AlgorithmIdentifier ::= { id-sha1, NULL } +-- sha224Identifier AlgorithmIdentifier ::= { id-sha224, NULL } +-- sha256Identifier AlgorithmIdentifier ::= { id-sha256, NULL } +-- sha384Identifier AlgorithmIdentifier ::= { id-sha384, NULL } +-- sha512Identifier AlgorithmIdentifier ::= { id-sha512, NULL } + +RSASSA-PSS-params ::= SEQUENCE { + hashAlgorithm [0] AlgorithmIdentifier OPTIONAL -- DEFAULT sha1Identifier -- , + maskGenAlgorithm [1] AlgorithmIdentifier OPTIONAL -- DEFAULT mgf1SHA1Identifier --, + saltLength [2] INTEGER (0..4294967295) DEFAULT 20, + trailerField [3] INTEGER (0..4294967295) DEFAULT 1 } +RSAES-OAEP-params ::= SEQUENCE { + hashFunc [0] AlgorithmIdentifier OPTIONAL -- DEFAULT sha1Identifier -- , + maskGenFunc [1] AlgorithmIdentifier OPTIONAL -- DEFAULT mgf1SHA1Identifier -- , + pSourceFunc [2] AlgorithmIdentifier OPTIONAL -- DEFAULT pSpecifiedEmptyIdentifier +} + + -- draft-ietf-pkix-ecc-subpubkeyinfo-11 ECPoint ::= OCTET STRING -ECParameters ::= CHOICE { - namedCurve OBJECT IDENTIFIER - -- implicitCurve NULL - -- specifiedCurve SpecifiedECDomain -} - ECDSA-Sig-Value ::= SEQUENCE { r INTEGER, s INTEGER diff --git a/lib/asn1/rfc2459.opt b/lib/asn1/rfc2459.opt index 207056847..4dbd168bb 100644 --- a/lib/asn1/rfc2459.opt +++ b/lib/asn1/rfc2459.opt @@ -1,6 +1,7 @@ --preserve-binary=Name --preserve-binary=TBSCertificate --preserve-binary=TBSCRLCertList +--preserve-binary=SubjectPublicKeyInfo --sequence=AttributeValues --sequence=CRLDistributionPoints --sequence=Extensions diff --git a/lib/asn1/symbol.h b/lib/asn1/symbol.h index 108749b92..337dfd82b 100644 --- a/lib/asn1/symbol.h +++ b/lib/asn1/symbol.h @@ -132,6 +132,7 @@ struct iosclassfield { unsigned long id; unsigned int optional:1; unsigned int unique:1; + unsigned int opentype:1; }; typedef struct iosclassfield Field; diff --git a/lib/asn1/template.c b/lib/asn1/template.c index ed215d888..5d74e9a17 100644 --- a/lib/asn1/template.c +++ b/lib/asn1/template.c @@ -88,6 +88,11 @@ struct asn1_type_func asn1_template_prim[A1T_NUM_ENTRY] = { }, el(oid, heim_oid), el(general_string, heim_general_string), + { (asn1_type_encode)der_put_null, (asn1_type_decode)der_get_null, + (asn1_type_length)der_length_null, (asn1_type_copy)der_copy_integer, + (asn1_type_release)der_free_integer, (asn1_type_print)der_print_null, + sizeof(int) + }, #undef el #undef elber }; @@ -632,10 +637,37 @@ _asn1_decode_open_type(const struct asn1_template *t, * ... * } ... * } + * + * Of course, the open type member could be OPTIONAL, in which case we + * will have: + * + * typedef struct SingleAttribute { + * heim_oid type; + * -------->HEIM_ANY *value; // HERE + * struct { + * ... + * } ... + * } + * + * and we'll have to dereference that value pointer if it's not NULL. */ - const struct heim_base_data *d = DPOC(data, topentype->offset); + const struct heim_base_data *d; void *o; + if (t->tt & A1_OTF_IS_OPTIONAL) { + struct heim_base_data *const *od = DPOC(data, topentype->offset); + + if (*od == NULL) + /* + * Nothing to do. The user has to check the open type field + * before they check the _ios_choice field. + */ + return 0; + d = *od; + } else { + d = DPOC(data, topentype->offset); + } + if (d->data && d->length) { if ((o = calloc(1, tactual_type->offset)) == NULL) return ENOMEM; @@ -2432,7 +2464,7 @@ _asn1_print_open_type(const struct asn1_template *t, /* object set template */ /* XXX We assume sizeof(enum) == sizeof(int) */ if (!*elementp || *elementp >= A1_HEADER_LEN(tos) + 1) { - r = rk_strpoolprintf(r, ",%s\"_%s_choice\":\"_ERROR_DECODING_\"", + r = rk_strpoolprintf(r, ",%s\"_%s_choice\":\"\"", indents ? indents : "", opentype_name); free(indents); return r; @@ -2448,10 +2480,8 @@ _asn1_print_open_type(const struct asn1_template *t, /* object set template */ } if (!(t->tt & A1_OS_OT_IS_ARRAY)) { - dp = DPOC(data, t->offset + sizeof(*elementp)); - while (sizeof(void *) != sizeof(*elementp) && - ((uintptr_t)dp) % sizeof(void *) != 0) - dp = (void *)(((char *)dp) + sizeof(*elementp)); + unsigned align = 8 - ((t->offset + sizeof(*elementp)) & 0x7); + dp = DPOC(data, t->offset + sizeof(*elementp) + align); if (*dp) { struct rk_strpool *r2 = NULL; char *s = NULL; diff --git a/lib/base/heimbase-atomics.h b/lib/base/heimbase-atomics.h index e468a36bd..6c6d9d96b 100644 --- a/lib/base/heimbase-atomics.h +++ b/lib/base/heimbase-atomics.h @@ -36,6 +36,12 @@ #ifndef HEIM_BASE_ATOMICS_H #define HEIM_BASE_ATOMICS_H 1 +#if defined(__has_include) +# if __has_include() +# define HEIM_HAVE_STDATOMIC 1 +# endif +#endif + #include /* @@ -54,15 +60,28 @@ #define heim_base_atomic(T) _Atomic(T) -#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) +/* + * These have to be inlined functions instead of macros as otherwise we get + * errors when the caller ignores the result of these. + */ +static inline uint32_t heim_base_atomic_inc_32(heim_base_atomic(uint32_t)*x) + { return atomic_fetch_add((x), 1) + 1; } +static inline uint32_t heim_base_atomic_dec_32(heim_base_atomic(uint32_t)*x) + { return atomic_fetch_sub((x), 1) - 1; } +static inline uint64_t heim_base_atomic_inc_64(heim_base_atomic(uint64_t)*x) + { return atomic_fetch_add((x), 1) + 1; } +static inline uint64_t heim_base_atomic_dec_64(heim_base_atomic(uint64_t)*x) + { return 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)) +#define heim_base_consumer_barrier() atomic_thread_fence(memory_order_acquire) +#define heim_base_producer_barrier() atomic_thread_fence(memory_order_release) +#define heim_base_full_barrier() atomic_thread_fence(memory_order_seq_cst) +#define heim_base_atomic_barrier() atomic_thread_fence(memory_order_seq_cst) + /* * '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 @@ -98,6 +117,9 @@ heim_base_cas_64_(heim_base_atomic(uint64_t)*t, uint64_t e, uint64_t 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_consumer_barrier() __sync_synchronize() +#define heim_base_producer_barrier() __sync_synchronize() +#define heim_base_full_barrier() __sync_synchronize() #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) @@ -129,10 +151,14 @@ heim_base_cas_64_(heim_base_atomic(uint64_t)*t, uint64_t e, uint64_t d) static inline void __heim_base_atomic_barrier(void) { - __machine_rw_barrier(); + membar_producer(); + membar_consumer(); } -#define heim_base_atomic_barrier() __heim_base_atomic_barrier() +#define heim_base_atomic_barrier() __heim_base_atomic_barrier() +#define heim_base_consumer_barrier() membar_consumer() +#define heim_base_producer_barrier() membar_producer() +#define heim_base_full_barrier() __heim_base_atomic_barrier() #define heim_base_atomic(T) volatile T @@ -154,6 +180,9 @@ static inline void __heim_base_atomic_barrier(void) #include #define heim_base_atomic_barrier() __isync() +#define heim_base_consumer_barrier() __isync() +#define heim_base_producer_barrier() __isync() +#define heim_base_full_barrier() __isync() #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) @@ -218,6 +247,9 @@ heim_base_cas_64_(heim_base_atomic(uint64_t)*t, uint64_t e, uint64_t d) #elif !defined(HEIM_BASE_ATOMICS_FALLBACK) && defined(_WIN32) #define heim_base_atomic_barrier() MemoryBarrier() +#define heim_base_consumer_barrier() _ReadBarrier() +#define heim_base_producer_barrier() _WriteBarrier() +#define heim_base_full_barrier() MemoryBarrier() #define heim_base_atomic_inc_32(x) InterlockedIncrement(x) #define heim_base_atomic_dec_32(x) InterlockedDecrement(x) @@ -236,6 +268,9 @@ heim_base_cas_64_(heim_base_atomic(uint64_t)*t, uint64_t e, uint64_t d) #define heim_base_atomic(T) volatile T #define heim_base_atomic_barrier() +#define heim_base_consumer_barrier() +#define heim_base_producer_barrier() +#define heim_base_full_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) @@ -358,6 +393,10 @@ heim_base_cas_64(heim_base_atomic(uint64_t) *target, uint64_t expected,uint64_t #ifndef heim_base_atomic_barrier static inline void heim_base_atomic_barrier(void) { return; } +#define heim_base_atomic_barrier() heim_base_atomic_barrier() +#define heim_base_consumer_barrier() heim_base_atomic_barrier() +#define heim_base_producer_barrier() heim_base_atomic_barrier() +#define heim_base_full_barrier() heim_base_atomic_barrier() #endif #ifndef heim_base_atomic_load diff --git a/lib/gssapi/Makefile.am b/lib/gssapi/Makefile.am index be38852f0..5ba60241e 100644 --- a/lib/gssapi/Makefile.am +++ b/lib/gssapi/Makefile.am @@ -12,7 +12,6 @@ AM_CPPFLAGS += \ -I$(srcdir) \ -I$(srcdir)/gssapi \ -I$(srcdir)/mech \ - -I$(srcdir)/ntlm \ -I$(srcdir)/krb5 \ -I$(srcdir)/spnego \ -I$(srcdir)/sanon \ @@ -186,42 +185,6 @@ spnegosrc = \ spnego/negoex_locl.h \ $(srcdir)/spnego/spnego-private.h -ntlmsrc = \ - ntlm/accept_sec_context.c \ - ntlm/acquire_cred.c \ - ntlm/add_cred.c \ - ntlm/canonicalize_name.c \ - ntlm/compare_name.c \ - ntlm/context_time.c \ - ntlm/creds.c \ - ntlm/crypto.c \ - ntlm/delete_sec_context.c \ - ntlm/display_name.c \ - ntlm/display_status.c \ - ntlm/duplicate_name.c \ - ntlm/export_name.c \ - ntlm/export_sec_context.c \ - ntlm/external.c \ - ntlm/ntlm.h \ - ntlm/import_name.c \ - ntlm/import_sec_context.c \ - ntlm/indicate_mechs.c \ - ntlm/init_sec_context.c \ - ntlm/inquire_context.c \ - ntlm/inquire_cred_by_mech.c \ - ntlm/inquire_mechs_for_name.c \ - ntlm/inquire_names_for_mech.c \ - ntlm/inquire_sec_context_by_oid.c \ - ntlm/iter_cred.c \ - ntlm/process_context_token.c \ - ntlm/release_cred.c \ - ntlm/release_name.c \ - ntlm/set_sec_context_option.c \ - ntlm/kdc.c - -$(srcdir)/ntlm/ntlm-private.h: $(ntlmsrc) - cd $(srcdir) && perl ../../cf/make-proto.pl -q -P comment -p ntlm/ntlm-private.h $(ntlmsrc) || rm -f ntlm/ntlm-private.h - sanonsrc = \ sanon/accept_sec_context.c \ sanon/acquire_cred.c \ @@ -259,7 +222,6 @@ sanonsrc = \ dist_libgssapi_la_SOURCES = \ $(krb5src) \ $(mechsrc) \ - $(ntlmsrc) \ $(spnegosrc) \ $(sanonsrc) @@ -275,7 +237,6 @@ libgssapi_la_LDFLAGS += $(LDFLAGS_VERSION_SCRIPT)$(srcdir)/version-script.map endif libgssapi_la_LIBADD = \ - $(top_builddir)/lib/ntlm/libheimntlm.la \ $(top_builddir)/lib/krb5/libkrb5.la \ $(top_builddir)/lib/asn1/libasn1.la \ $(LIB_com_err) \ @@ -287,7 +248,6 @@ include_HEADERS = gssapi.h noinst_HEADERS = \ gssapi_asn1.h \ gssapi_mech.h \ - $(srcdir)/ntlm/ntlm-private.h \ $(srcdir)/spnego/spnego-private.h \ $(srcdir)/sanon/sanon-private.h \ $(srcdir)/krb5/gsskrb5-private.h @@ -295,7 +255,6 @@ noinst_HEADERS = \ nobase_include_HEADERS = \ gssapi/gssapi.h \ gssapi/gssapi_krb5.h \ - gssapi/gssapi_ntlm.h \ gssapi/gssapi_oid.h \ gssapi/gssapi_spnego.h @@ -320,8 +279,7 @@ spnego_files = \ BUILTHEADERS = \ $(srcdir)/krb5/gsskrb5-private.h \ $(srcdir)/spnego/spnego-private.h \ - $(srcdir)/sanon/sanon-private.h \ - $(srcdir)/ntlm/ntlm-private.h + $(srcdir)/sanon/sanon-private.h $(libgssapi_la_OBJECTS): $(BUILTHEADERS) $(test_context_OBJECTS): $(BUILTHEADERS) @@ -383,10 +341,9 @@ test_cfx_SOURCES = krb5/test_cfx.c check_PROGRAMS = test_acquire_cred test_acquire_cred_auditdns $(TESTS) bin_PROGRAMS = gsstool gss-token -noinst_PROGRAMS = test_cred test_kcred test_context test_ntlm test_add_store_cred +noinst_PROGRAMS = test_cred test_kcred test_context test_add_store_cred test_context_SOURCES = test_context.c test_common.c test_common.h -test_ntlm_SOURCES = test_ntlm.c test_common.c test_common.h test_acquire_cred_SOURCES = test_acquire_cred.c test_common.c test_common.h test_acquire_cred_auditdns_SOURCES = \ test_acquire_cred.c test_common.c test_common.h \ @@ -394,10 +351,6 @@ test_acquire_cred_auditdns_SOURCES = \ test_add_store_cred_SOURCES = test_add_store_cred.c -test_ntlm_LDADD = \ - $(top_builddir)/lib/ntlm/libheimntlm.la \ - $(LDADD) - LDADD = libgssapi.la \ $(top_builddir)/lib/krb5/libkrb5.la \ $(LIB_roken) @@ -433,7 +386,6 @@ EXTRA_DIST = \ libgssapi-exports.def \ $(man_MANS) \ gen-oid.pl \ - gssapi/gssapi_netlogon.h \ krb5/test_acquire_cred.c \ krb5/test_cred.c \ krb5/test_kcred.c \ diff --git a/lib/gssapi/NTMakefile b/lib/gssapi/NTMakefile index ffba9d52b..f950cdcc1 100644 --- a/lib/gssapi/NTMakefile +++ b/lib/gssapi/NTMakefile @@ -199,40 +199,6 @@ spnegosrc = \ spnego/spnego_locl.h \ spnego/negoex_locl.h -ntlmsrc = \ - ntlm/accept_sec_context.c \ - ntlm/acquire_cred.c \ - ntlm/add_cred.c \ - ntlm/canonicalize_name.c \ - ntlm/compare_name.c \ - ntlm/context_time.c \ - ntlm/creds.c \ - ntlm/crypto.c \ - ntlm/delete_sec_context.c \ - ntlm/display_name.c \ - ntlm/display_status.c \ - ntlm/duplicate_name.c \ - ntlm/duplicate_cred.c \ - ntlm/export_name.c \ - ntlm/export_sec_context.c \ - ntlm/external.c \ - ntlm/ntlm.h \ - ntlm/import_name.c \ - ntlm/import_sec_context.c \ - ntlm/indicate_mechs.c \ - ntlm/init_sec_context.c \ - ntlm/inquire_context.c \ - ntlm/inquire_cred_by_mech.c \ - ntlm/inquire_mechs_for_name.c \ - ntlm/inquire_names_for_mech.c \ - ntlm/inquire_sec_context_by_oid.c \ - ntlm/iter_cred.c \ - ntlm/process_context_token.c \ - ntlm/release_cred.c \ - ntlm/release_name.c \ - ntlm/set_sec_context_option.c \ - ntlm/kdc.c - sanonsrc = \ sanon/accept_sec_context.c \ sanon/acquire_cred.c \ @@ -265,9 +231,6 @@ sanonsrc = \ sanon/release_cred.c \ sanon/release_name.c -$(OBJ)\ntlm\ntlm-private.h: $(ntlmsrc) - $(PERL) ../../cf/make-proto.pl -q -P remove -p $@ $(ntlmsrc) - $(OBJ)\krb5\gsskrb5-private.h: $(krb5src) $(PERL) ../../cf/make-proto.pl -q -P remove -p $@ $(krb5src) @@ -307,10 +270,8 @@ INCFILES= \ $(INCDIR)\gssapi\gssapi.h \ $(INCDIR)\gssapi\gssapi_krb5.h \ $(INCDIR)\gssapi\gssapi_oid.h \ - $(INCDIR)\gssapi\gssapi_ntlm.h \ $(INCDIR)\gssapi\gssapi_spnego.h \ $(INCDIR)\gssapi\gkrb5_err.h \ - $(OBJ)\ntlm\ntlm-private.h \ $(OBJ)\spnego\spnego-private.h \ $(OBJ)\sanon\sanon-private.h \ $(OBJ)\krb5\gsskrb5-private.h \ @@ -470,37 +431,6 @@ libgssapi_OBJs = \ $(OBJ)\spnego/init_sec_context.obj \ $(OBJ)\spnego/negoex_ctx.obj \ $(OBJ)\spnego/negoex_util.obj \ - $(OBJ)\ntlm/accept_sec_context.obj \ - $(OBJ)\ntlm/acquire_cred.obj \ - $(OBJ)\ntlm/add_cred.obj \ - $(OBJ)\ntlm/canonicalize_name.obj \ - $(OBJ)\ntlm/compare_name.obj \ - $(OBJ)\ntlm/context_time.obj \ - $(OBJ)\ntlm/creds.obj \ - $(OBJ)\ntlm/crypto.obj \ - $(OBJ)\ntlm/delete_sec_context.obj \ - $(OBJ)\ntlm/display_name.obj \ - $(OBJ)\ntlm/display_status.obj \ - $(OBJ)\ntlm/duplicate_cred.obj \ - $(OBJ)\ntlm/duplicate_name.obj \ - $(OBJ)\ntlm/export_name.obj \ - $(OBJ)\ntlm/export_sec_context.obj \ - $(OBJ)\ntlm/external.obj \ - $(OBJ)\ntlm/import_name.obj \ - $(OBJ)\ntlm/import_sec_context.obj \ - $(OBJ)\ntlm/indicate_mechs.obj \ - $(OBJ)\ntlm/init_sec_context.obj \ - $(OBJ)\ntlm/inquire_context.obj \ - $(OBJ)\ntlm/inquire_cred_by_mech.obj \ - $(OBJ)\ntlm/inquire_mechs_for_name.obj \ - $(OBJ)\ntlm/inquire_names_for_mech.obj \ - $(OBJ)\ntlm/inquire_sec_context_by_oid.obj \ - $(OBJ)\ntlm/iter_cred.obj \ - $(OBJ)\ntlm/process_context_token.obj \ - $(OBJ)\ntlm/release_cred.obj \ - $(OBJ)\ntlm/release_name.obj \ - $(OBJ)\ntlm/set_sec_context_option.obj \ - $(OBJ)\ntlm/kdc.obj \ $(OBJ)\sanon/accept_sec_context.obj \ $(OBJ)\sanon/acquire_cred.obj \ $(OBJ)\sanon/add_cred.obj \ @@ -550,12 +480,6 @@ GCOPTS=-I$(SRCDIR) -I$(OBJ) -Igssapi -DBUILD_GSSAPI_LIB {mech}.c{$(OBJ)\mech}.obj:: $(C2OBJ_NP) -Fo$(OBJ)\mech\ -Fd$(OBJ)\mech\ -I$(OBJ)\mech -I$(OBJ)\gssapi $(GCOPTS) -DASN1_LIB -{$(OBJ)\ntlm}.c{$(OBJ)\ntlm}.obj:: - $(C2OBJ_NP) -Fo$(OBJ)\ntlm\ -Fd$(OBJ)\ntlm\ -I$(OBJ)\ntlm $(GCOPTS) - -{ntlm}.c{$(OBJ)\ntlm}.obj:: - $(C2OBJ_NP) -Fo$(OBJ)\ntlm\ -Fd$(OBJ)\ntlm\ -I$(OBJ)\ntlm $(GCOPTS) -DASN1_LIB - {$(OBJ)\spnego}.c{$(OBJ)\spnego}.obj:: $(C2OBJ_NP) -Fo$(OBJ)\spnego\ -Fd$(OBJ)\spnego\ -I$(OBJ)\spnego $(GCOPTS) @@ -584,8 +508,8 @@ LIBGSSAPI_LIBS=\ $(LIBHEIMBASE) \ $(LIBROKEN) \ $(LIBHEIMDAL) \ - $(LIBHEIMNTLM) \ - $(LIBCOMERR) + $(LIBCOMERR) \ + $(LIB_openssl_crypto) LIBGSSAPI_SDKLIBS=\ $(PTHREAD_LIB) \ @@ -628,9 +552,6 @@ clean:: prep:: mkdirs-gss mkdirs-gss: -!if !exist($(OBJ)\ntlm) - $(MKDIR) $(OBJ)\ntlm -!endif !if !exist($(OBJ)\krb5) $(MKDIR) $(OBJ)\krb5 !endif @@ -648,7 +569,6 @@ mkdirs-gss: !endif clean:: - -$(RM) $(OBJ)\ntlm\*.* -$(RM) $(OBJ)\krb5\*.* -$(RM) $(OBJ)\spnego\*.* -$(RM) $(OBJ)\mech\*.* @@ -676,7 +596,7 @@ $(OBJ)\gss-commands.c $(OBJ)\gss-commands.h: gss-commands.in "\t$(OBJ)\\negoex_err.obj \\\n" "\t$(OBJ)\\spnego\\asn1_spnego_asn1.obj \\\n" "\t$(OBJ)\\gssapi\\asn1_gssapi_asn1.obj") - "krb5src" "mechsrc" "spnegosrc" "ntlmsrc") + "krb5src" "mechsrc" "spnegosrc") !endif test-exports: @@ -692,8 +612,7 @@ TEST_BINARIES=\ $(OBJ)\test_acquire_cred.exe \ $(OBJ)\test_cred.exe \ $(OBJ)\test_kcred.exe \ - $(OBJ)\test_context.exe \ - $(OBJ)\test_ntlm.exe + $(OBJ)\test_context.exe $(OBJ)\test_oid.exe: $(OBJ)\test_oid.obj $(LIBGSSAPI) $(LIBROKEN) $(EXECONLINK) @@ -726,11 +645,6 @@ $(OBJ)\test_context.exe: $(OBJ)\test_context.obj $(OBJ)\test_common.obj \ $(EXECONLINK) $(EXEPREP_NODIST) -$(OBJ)\test_ntlm.exe: $(OBJ)\test_ntlm.obj $(OBJ)\test_common.obj \ - $(LIBGSSAPI) $(LIBHEIMNTLM) $(LIBROKEN) $(LIBVERS) - $(EXECONLINK) - $(EXEPREP_NODIST) - {}.c{$(OBJ)}.obj:: $(C2OBJ_P) -I$(OBJ)\krb5 -I$(OBJ) -I$(SRCDIR) -I$(SRCDIR)\gssapi diff --git a/lib/gssapi/gssapi/gssapi_ntlm.h b/lib/gssapi/gssapi/gssapi_ntlm.h deleted file mode 100644 index e37c003c7..000000000 --- a/lib/gssapi/gssapi/gssapi_ntlm.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2006 - 2009 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 GSSAPI_NTLM_H_ -#define GSSAPI_NTLM_H_ - -#include - -#endif /* GSSAPI_NTLM_H_ */ diff --git a/lib/gssapi/gssapi_mech.h b/lib/gssapi/gssapi_mech.h index ced27b517..33261ef55 100644 --- a/lib/gssapi/gssapi_mech.h +++ b/lib/gssapi/gssapi_mech.h @@ -647,7 +647,6 @@ _gss_mg_support_mechanism(gss_const_OID mech); gssapi_mech_interface __gss_spnego_initialize(void); gssapi_mech_interface __gss_krb5_initialize(void); -gssapi_mech_interface __gss_ntlm_initialize(void); gssapi_mech_interface __gss_sanon_initialize(void); void gss_mg_collect_error(gss_OID, OM_uint32, OM_uint32); diff --git a/lib/gssapi/gsstool.c b/lib/gssapi/gsstool.c index 8df39535e..10e80176b 100644 --- a/lib/gssapi/gsstool.c +++ b/lib/gssapi/gsstool.c @@ -40,7 +40,6 @@ #include #include #include -#include #include #include #include diff --git a/lib/gssapi/krb5/arcfour.c b/lib/gssapi/krb5/arcfour.c index 02780b621..f06d12144 100644 --- a/lib/gssapi/krb5/arcfour.c +++ b/lib/gssapi/krb5/arcfour.c @@ -240,7 +240,7 @@ _gssapi_get_mic_arcfour(OM_uint32 * minor_status, int32_t seq_number; size_t len, total_len; u_char k6_data[16], *p0, *p; - EVP_CIPHER_CTX rc4_key; + EVP_CIPHER_CTX *rc4_key; _gsskrb5_encap_length (22, &len, &total_len, GSS_KRB5_MECHANISM); @@ -302,10 +302,19 @@ _gssapi_get_mic_arcfour(OM_uint32 * minor_status, memset (p + 4, (context_handle->more_flags & LOCAL) ? 0 : 0xff, 4); - EVP_CIPHER_CTX_init(&rc4_key); - EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1); - EVP_Cipher(&rc4_key, p, p, 8); - EVP_CIPHER_CTX_cleanup(&rc4_key); + if ((rc4_key = EVP_CIPHER_CTX_new()) == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + if (EVP_CIPHER_CTX_init(rc4_key) != 1 || + EVP_CipherInit_ex(rc4_key, context->ossl->rc4, NULL, k6_data, NULL, 1) != 1 || + EVP_Cipher(rc4_key, p, p, 8) != 1) { + EVP_CIPHER_CTX_free(rc4_key); + _krb5_debug_openssl(context, 4, "Could not encrypt with RC4 with OpenSSL"); + *minor_status = KRB5_CRYPTO_INTERNAL; + return GSS_S_FAILURE; + } + EVP_CIPHER_CTX_free(rc4_key); memset_s(k6_data, sizeof(k6_data), 0, sizeof(k6_data)); @@ -375,14 +384,22 @@ _gssapi_verify_mic_arcfour(OM_uint32 * minor_status, } { - EVP_CIPHER_CTX rc4_key; + EVP_CIPHER_CTX *rc4_key; - EVP_CIPHER_CTX_init(&rc4_key); - EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, (void *)k6_data, NULL, 0); - EVP_Cipher(&rc4_key, SND_SEQ, p, 8); - EVP_CIPHER_CTX_cleanup(&rc4_key); + if ((rc4_key = EVP_CIPHER_CTX_new()) == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + if (EVP_CIPHER_CTX_init(rc4_key) != 1 || + EVP_CipherInit_ex(rc4_key, context->ossl->rc4, NULL, (void *)k6_data, NULL, 0) != 1 || + EVP_Cipher(rc4_key, SND_SEQ, p, 8) != 1) { + _krb5_debug_openssl(context, 4, "Could not encrypt with RC4 with OpenSSL"); + *minor_status = KRB5_CRYPTO_INTERNAL; + return GSS_S_FAILURE; + } + EVP_CIPHER_CTX_free(rc4_key); - memset(k6_data, 0, sizeof(k6_data)); + memset_s(k6_data, sizeof(k6_data), 0, sizeof(k6_data)); } _gss_mg_decode_be_uint32(SND_SEQ, &seq_number); @@ -528,14 +545,23 @@ _gssapi_wrap_arcfour(OM_uint32 * minor_status, if(conf_req_flag) { - EVP_CIPHER_CTX rc4_key; + EVP_CIPHER_CTX *rc4_key; - EVP_CIPHER_CTX_init(&rc4_key); - EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1); - EVP_Cipher(&rc4_key, p0 + 24, p0 + 24, 8 + datalen); - EVP_CIPHER_CTX_cleanup(&rc4_key); + if ((rc4_key = EVP_CIPHER_CTX_new()) == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + if (EVP_CIPHER_CTX_init(rc4_key) != 1 || + EVP_CipherInit_ex(rc4_key, context->ossl->rc4, NULL, k6_data, NULL, 1) != 1 || + EVP_Cipher(rc4_key, p0 + 24, p0 + 24, 8 + datalen) != 1) { + EVP_CIPHER_CTX_free(rc4_key); + _krb5_debug_openssl(context, 4, "Could not encrypt with RC4 with OpenSSL"); + *minor_status = KRB5_CRYPTO_INTERNAL; + return GSS_S_FAILURE; + } + EVP_CIPHER_CTX_free(rc4_key); } - memset(k6_data, 0, sizeof(k6_data)); + memset_s(k6_data, sizeof(k6_data), 0, sizeof(k6_data)); ret = arcfour_mic_key(context, key, p0 + 16, 8, /* SGN_CKSUM */ @@ -547,12 +573,21 @@ _gssapi_wrap_arcfour(OM_uint32 * minor_status, } { - EVP_CIPHER_CTX rc4_key; + EVP_CIPHER_CTX *rc4_key; - EVP_CIPHER_CTX_init(&rc4_key); - EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1); - EVP_Cipher(&rc4_key, p0 + 8, p0 + 8 /* SND_SEQ */, 8); - EVP_CIPHER_CTX_cleanup(&rc4_key); + if ((rc4_key = EVP_CIPHER_CTX_new()) == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + if (EVP_CIPHER_CTX_init(rc4_key) != 1 || + EVP_CipherInit_ex(rc4_key, context->ossl->rc4, NULL, k6_data, NULL, 1) != 1 || + EVP_Cipher(rc4_key, p0 + 8, p0 + 8 /* SND_SEQ */, 8) != 1) { + EVP_CIPHER_CTX_free(rc4_key); + _krb5_debug_openssl(context, 4, "Could not encrypt with RC4 with OpenSSL"); + *minor_status = KRB5_CRYPTO_INTERNAL; + return GSS_S_FAILURE; + } + EVP_CIPHER_CTX_free(rc4_key); memset_s(k6_data, sizeof(k6_data), 0, sizeof(k6_data)); } @@ -647,12 +682,21 @@ OM_uint32 _gssapi_unwrap_arcfour(OM_uint32 *minor_status, } { - EVP_CIPHER_CTX rc4_key; + EVP_CIPHER_CTX *rc4_key; - EVP_CIPHER_CTX_init(&rc4_key); - EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1); - EVP_Cipher(&rc4_key, SND_SEQ, p0 + 8, 8); - EVP_CIPHER_CTX_cleanup(&rc4_key); + if ((rc4_key = EVP_CIPHER_CTX_new()) == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + if (EVP_CIPHER_CTX_init(rc4_key) != 1 || + EVP_CipherInit_ex(rc4_key, context->ossl->rc4, NULL, k6_data, NULL, 1) != 1 || + EVP_Cipher(rc4_key, SND_SEQ, p0 + 8, 8) != 1) { + EVP_CIPHER_CTX_free(rc4_key); + _krb5_debug_openssl(context, 4, "Could not decrypt with RC4 with OpenSSL"); + *minor_status = KRB5_CRYPTO_INTERNAL; + return GSS_S_FAILURE; + } + EVP_CIPHER_CTX_free(rc4_key); memset_s(k6_data, sizeof(k6_data), 0, sizeof(k6_data)); } @@ -695,20 +739,29 @@ OM_uint32 _gssapi_unwrap_arcfour(OM_uint32 *minor_status, output_message_buffer->length = datalen; if(conf_flag) { - EVP_CIPHER_CTX rc4_key; + EVP_CIPHER_CTX *rc4_key; - EVP_CIPHER_CTX_init(&rc4_key); - EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1); - EVP_Cipher(&rc4_key, Confounder, p0 + 24, 8); - EVP_Cipher(&rc4_key, output_message_buffer->value, p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE, datalen); - EVP_CIPHER_CTX_cleanup(&rc4_key); + if ((rc4_key = EVP_CIPHER_CTX_new()) == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + if (EVP_CIPHER_CTX_init(rc4_key) != 1 || + EVP_CipherInit_ex(rc4_key, context->ossl->rc4, NULL, k6_data, NULL, 1) != 1 || + EVP_Cipher(rc4_key, Confounder, p0 + 24, 8) != 1 || + EVP_Cipher(rc4_key, output_message_buffer->value, p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE, datalen) != 1) { + EVP_CIPHER_CTX_free(rc4_key); + _krb5_debug_openssl(context, 4, "Could not decrypt with RC4 with OpenSSL"); + *minor_status = KRB5_CRYPTO_INTERNAL; + return GSS_S_FAILURE; + } + EVP_CIPHER_CTX_free(rc4_key); } else { memcpy(Confounder, p0 + 24, 8); /* Confounder */ memcpy(output_message_buffer->value, p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE, datalen); } - memset(k6_data, 0, sizeof(k6_data)); + memset_s(k6_data, sizeof(k6_data), 0, sizeof(k6_data)); if (!IS_DCE_STYLE(context_handle)) { ret = _gssapi_verify_pad(output_message_buffer, datalen, &padlen); @@ -1087,13 +1140,21 @@ _gssapi_wrap_iov_arcfour(OM_uint32 *minor_status, } if (conf_req_flag) { - EVP_CIPHER_CTX rc4_key; + EVP_CIPHER_CTX *rc4_key; - EVP_CIPHER_CTX_init(&rc4_key); - EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1); - - /* Confounder */ - EVP_Cipher(&rc4_key, p0 + 24, p0 + 24, 8); + if ((rc4_key = EVP_CIPHER_CTX_new()) == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + if (EVP_CIPHER_CTX_init(rc4_key) != 1 || + EVP_CipherInit_ex(rc4_key, context->ossl->rc4, NULL, k6_data, NULL, 1) != 1 || + /* Confounder */ + EVP_Cipher(rc4_key, p0 + 24, p0 + 24, 8) != 1) { + EVP_CIPHER_CTX_free(rc4_key); + _krb5_debug_openssl(context, 4, "Could not encrypt with RC4 with OpenSSL"); + *minor_status = KRB5_CRYPTO_INTERNAL; + return GSS_S_FAILURE; + } /* Seal Data */ for (i=0; i < iov_count; i++) { @@ -1104,19 +1165,28 @@ _gssapi_wrap_iov_arcfour(OM_uint32 *minor_status, continue; } - EVP_Cipher(&rc4_key, iov[i].buffer.value, - iov[i].buffer.value, iov[i].buffer.length); + if (EVP_Cipher(rc4_key, iov[i].buffer.value, + iov[i].buffer.value, iov[i].buffer.length) != 1) { + EVP_CIPHER_CTX_free(rc4_key); + _krb5_debug_openssl(context, 4, "Could not encrypt with RC4 with OpenSSL"); + *minor_status = KRB5_CRYPTO_INTERNAL; + return GSS_S_FAILURE; + } } /* Padding */ - if (padding) { - EVP_Cipher(&rc4_key, padding->buffer.value, - padding->buffer.value, padding->buffer.length); + if (padding && + EVP_Cipher(rc4_key, padding->buffer.value, + padding->buffer.value, padding->buffer.length) != 1) { + EVP_CIPHER_CTX_free(rc4_key); + _krb5_debug_openssl(context, 4, "Could not encrypt with RC4 with OpenSSL"); + *minor_status = KRB5_CRYPTO_INTERNAL; + return GSS_S_FAILURE; } - EVP_CIPHER_CTX_cleanup(&rc4_key); + EVP_CIPHER_CTX_free(rc4_key); } - memset(k6_data, 0, sizeof(k6_data)); + memset_s(k6_data, sizeof(k6_data), 0, sizeof(k6_data)); kret = arcfour_mic_key(context, key, p0 + 16, 8, /* SGN_CKSUM */ @@ -1128,14 +1198,23 @@ _gssapi_wrap_iov_arcfour(OM_uint32 *minor_status, } { - EVP_CIPHER_CTX rc4_key; + EVP_CIPHER_CTX *rc4_key; - EVP_CIPHER_CTX_init(&rc4_key); - EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1); - EVP_Cipher(&rc4_key, p0 + 8, p0 + 8, 8); /* SND_SEQ */ - EVP_CIPHER_CTX_cleanup(&rc4_key); + if ((rc4_key = EVP_CIPHER_CTX_new()) == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + if (EVP_CIPHER_CTX_init(rc4_key) != 1 || + EVP_CipherInit_ex(rc4_key, context->ossl->rc4, NULL, k6_data, NULL, 1) != 1 || + EVP_Cipher(rc4_key, p0 + 8, p0 + 8, 8) != 1 /* SND_SEQ */) { + EVP_CIPHER_CTX_free(rc4_key); + _krb5_debug_openssl(context, 4, "Could not encrypt with RC4 with OpenSSL"); + *minor_status = KRB5_CRYPTO_INTERNAL; + return GSS_S_FAILURE; + } + EVP_CIPHER_CTX_free(rc4_key); - memset(k6_data, 0, sizeof(k6_data)); + memset_s(k6_data, sizeof(k6_data), 0, sizeof(k6_data)); } if (conf_state) @@ -1201,7 +1280,8 @@ _gssapi_unwrap_iov_arcfour(OM_uint32 *minor_status, } if (padding != NULL && padding->buffer.length != 1) { - *minor_status = EINVAL; + _krb5_debug(context, 4, "Padding does not match"); + *minor_status = KRB5_CRYPTO_INTERNAL; return GSS_S_FAILURE; } @@ -1269,14 +1349,23 @@ _gssapi_unwrap_iov_arcfour(OM_uint32 *minor_status, } { - EVP_CIPHER_CTX rc4_key; + EVP_CIPHER_CTX *rc4_key; - EVP_CIPHER_CTX_init(&rc4_key); - EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1); - EVP_Cipher(&rc4_key, snd_seq, p0 + 8, 8); /* SND_SEQ */ - EVP_CIPHER_CTX_cleanup(&rc4_key); + if ((rc4_key = EVP_CIPHER_CTX_new()) == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + if (EVP_CIPHER_CTX_init(rc4_key) != 1 || + EVP_CipherInit_ex(rc4_key, context->ossl->rc4, NULL, k6_data, NULL, 1) != 1 || + EVP_Cipher(rc4_key, snd_seq, p0 + 8, 8) != 1 /* SND_SEQ */) { + EVP_CIPHER_CTX_free(rc4_key); + _krb5_debug_openssl(context, 4, "Could not decrypt with RC4 with OpenSSL"); + *minor_status = KRB5_CRYPTO_INTERNAL; + return GSS_S_FAILURE; + } + EVP_CIPHER_CTX_free(rc4_key); - memset(k6_data, 0, sizeof(k6_data)); + memset_s(k6_data, sizeof(k6_data), 0, sizeof(k6_data)); } _gss_mg_decode_be_uint32(snd_seq, &seq_number); @@ -1312,13 +1401,21 @@ _gssapi_unwrap_iov_arcfour(OM_uint32 *minor_status, } if (conf_state == 1) { - EVP_CIPHER_CTX rc4_key; + EVP_CIPHER_CTX *rc4_key; - EVP_CIPHER_CTX_init(&rc4_key); - EVP_CipherInit_ex(&rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1); - - /* Confounder */ - EVP_Cipher(&rc4_key, Confounder, p0 + 24, 8); + if ((rc4_key = EVP_CIPHER_CTX_new()) == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + if (EVP_CIPHER_CTX_init(rc4_key) != 1 || + EVP_CipherInit_ex(rc4_key, context->ossl->rc4, NULL, k6_data, NULL, 1) != 1 || + /* Confounder */ + EVP_Cipher(rc4_key, Confounder, p0 + 24, 8) != 1) { + EVP_CIPHER_CTX_free(rc4_key); + _krb5_debug_openssl(context, 4, "Could not decrypt with RC4 with OpenSSL"); + *minor_status = KRB5_CRYPTO_INTERNAL; + return GSS_S_FAILURE; + } /* Data */ for (i = 0; i < iov_count; i++) { @@ -1329,22 +1426,31 @@ _gssapi_unwrap_iov_arcfour(OM_uint32 *minor_status, continue; } - EVP_Cipher(&rc4_key, iov[i].buffer.value, - iov[i].buffer.value, iov[i].buffer.length); + if (EVP_Cipher(rc4_key, iov[i].buffer.value, + iov[i].buffer.value, iov[i].buffer.length) != 1) { + EVP_CIPHER_CTX_free(rc4_key); + _krb5_debug_openssl(context, 4, "Could not decrypt with RC4 with OpenSSL"); + *minor_status = KRB5_CRYPTO_INTERNAL; + return GSS_S_FAILURE; + } } /* Padding */ - if (padding) { - EVP_Cipher(&rc4_key, padding->buffer.value, - padding->buffer.value, padding->buffer.length); + if (padding && + EVP_Cipher(rc4_key, padding->buffer.value, + padding->buffer.value, padding->buffer.length) != 1) { + EVP_CIPHER_CTX_free(rc4_key); + _krb5_debug_openssl(context, 4, "Could not encrypt with RC4 with OpenSSL"); + *minor_status = KRB5_CRYPTO_INTERNAL; + return GSS_S_FAILURE; } - EVP_CIPHER_CTX_cleanup(&rc4_key); + EVP_CIPHER_CTX_free(rc4_key); } else { /* Confounder */ memcpy(Confounder, p0 + 24, 8); } - memset(k6_data, 0, sizeof(k6_data)); + memset_s(k6_data, sizeof(k6_data), 0, sizeof(k6_data)); /* Prepare the buffer for signing */ kret = arcfour_mic_cksum_iov(context, diff --git a/lib/gssapi/krb5/get_mic.c b/lib/gssapi/krb5/get_mic.c index d9cf9d700..47b0a4ac7 100644 --- a/lib/gssapi/krb5/get_mic.c +++ b/lib/gssapi/krb5/get_mic.c @@ -33,246 +33,6 @@ #include "gsskrb5_locl.h" -#ifdef HEIM_WEAK_CRYPTO - -static OM_uint32 -mic_des - (OM_uint32 * minor_status, - const gsskrb5_ctx ctx, - krb5_context context, - gss_qop_t qop_req, - const gss_buffer_t message_buffer, - gss_buffer_t message_token, - krb5_keyblock *key - ) -{ - u_char *p; - EVP_MD_CTX *md5; - u_char hash[16]; - DES_key_schedule schedule; - EVP_CIPHER_CTX des_ctx; - DES_cblock deskey; - DES_cblock zero; - int32_t seq_number; - size_t len, total_len; - - _gsskrb5_encap_length (22, &len, &total_len, GSS_KRB5_MECHANISM); - - message_token->length = total_len; - message_token->value = malloc (total_len); - if (message_token->value == NULL) { - message_token->length = 0; - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - - p = _gsskrb5_make_header(message_token->value, - len, - "\x01\x01", /* TOK_ID */ - GSS_KRB5_MECHANISM); - - memcpy (p, "\x00\x00", 2); /* SGN_ALG = DES MAC MD5 */ - p += 2; - - memcpy (p, "\xff\xff\xff\xff", 4); /* Filler */ - p += 4; - - /* Fill in later (SND-SEQ) */ - memset (p, 0, 16); - p += 16; - - /* checksum */ - md5 = EVP_MD_CTX_create(); - EVP_DigestInit_ex(md5, EVP_md5(), NULL); - EVP_DigestUpdate(md5, p - 24, 8); - EVP_DigestUpdate(md5, message_buffer->value, message_buffer->length); - EVP_DigestFinal_ex(md5, hash, NULL); - EVP_MD_CTX_destroy(md5); - - memset (&zero, 0, sizeof(zero)); - memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); - DES_set_key_unchecked (&deskey, &schedule); - DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash), - &schedule, &zero); - memcpy (p - 8, hash, 8); /* SGN_CKSUM */ - - HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); - /* sequence number */ - krb5_auth_con_getlocalseqnumber (context, - ctx->auth_context, - &seq_number); - - p -= 16; /* SND_SEQ */ - p[0] = (seq_number >> 0) & 0xFF; - p[1] = (seq_number >> 8) & 0xFF; - p[2] = (seq_number >> 16) & 0xFF; - p[3] = (seq_number >> 24) & 0xFF; - memset (p + 4, - (ctx->more_flags & LOCAL) ? 0 : 0xFF, - 4); - - EVP_CIPHER_CTX_init(&des_ctx); - EVP_CipherInit_ex(&des_ctx, EVP_des_cbc(), NULL, key->keyvalue.data, p + 8, 1); - EVP_Cipher(&des_ctx, p, p, 8); - EVP_CIPHER_CTX_cleanup(&des_ctx); - - krb5_auth_con_setlocalseqnumber (context, - ctx->auth_context, - ++seq_number); - HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); - - memset_s(deskey, sizeof(deskey), 0, sizeof(deskey)); - memset_s(&schedule, sizeof(schedule), 0, sizeof(schedule)); - - *minor_status = 0; - return GSS_S_COMPLETE; -} -#endif - -static OM_uint32 -mic_des3 - (OM_uint32 * minor_status, - const gsskrb5_ctx ctx, - krb5_context context, - gss_qop_t qop_req, - const gss_buffer_t message_buffer, - gss_buffer_t message_token, - krb5_keyblock *key - ) -{ - u_char *p; - Checksum cksum; - u_char seq[8]; - - int32_t seq_number; - size_t len, total_len; - - krb5_crypto crypto; - krb5_error_code kret; - krb5_data encdata; - char *tmp; - char ivec[8]; - - _gsskrb5_encap_length (36, &len, &total_len, GSS_KRB5_MECHANISM); - - message_token->length = total_len; - message_token->value = malloc (total_len); - if (message_token->value == NULL) { - message_token->length = 0; - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - - p = _gsskrb5_make_header(message_token->value, - len, - "\x01\x01", /* TOK-ID */ - GSS_KRB5_MECHANISM); - - memcpy (p, "\x04\x00", 2); /* SGN_ALG = HMAC SHA1 DES3-KD */ - p += 2; - - memcpy (p, "\xff\xff\xff\xff", 4); /* filler */ - p += 4; - - /* this should be done in parts */ - - tmp = malloc (message_buffer->length + 8); - if (tmp == NULL) { - free (message_token->value); - message_token->value = NULL; - message_token->length = 0; - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - memcpy (tmp, p - 8, 8); - memcpy (tmp + 8, message_buffer->value, message_buffer->length); - - kret = krb5_crypto_init(context, key, 0, &crypto); - if (kret) { - free (message_token->value); - message_token->value = NULL; - message_token->length = 0; - free (tmp); - *minor_status = kret; - return GSS_S_FAILURE; - } - - kret = krb5_create_checksum (context, - crypto, - KRB5_KU_USAGE_SIGN, - 0, - tmp, - message_buffer->length + 8, - &cksum); - free (tmp); - krb5_crypto_destroy (context, crypto); - if (kret) { - free (message_token->value); - message_token->value = NULL; - message_token->length = 0; - *minor_status = kret; - return GSS_S_FAILURE; - } - - memcpy (p + 8, cksum.checksum.data, cksum.checksum.length); - - HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); - /* sequence number */ - krb5_auth_con_getlocalseqnumber (context, - ctx->auth_context, - &seq_number); - - seq[0] = (seq_number >> 0) & 0xFF; - seq[1] = (seq_number >> 8) & 0xFF; - seq[2] = (seq_number >> 16) & 0xFF; - seq[3] = (seq_number >> 24) & 0xFF; - memset (seq + 4, - (ctx->more_flags & LOCAL) ? 0 : 0xFF, - 4); - - kret = krb5_crypto_init(context, key, - ETYPE_DES3_CBC_NONE, &crypto); - if (kret) { - free (message_token->value); - message_token->value = NULL; - message_token->length = 0; - *minor_status = kret; - return GSS_S_FAILURE; - } - - if (ctx->more_flags & COMPAT_OLD_DES3) - memset(ivec, 0, 8); - else - memcpy(ivec, p + 8, 8); - - kret = krb5_encrypt_ivec (context, - crypto, - KRB5_KU_USAGE_SEQ, - seq, 8, &encdata, ivec); - krb5_crypto_destroy (context, crypto); - if (kret) { - free (message_token->value); - message_token->value = NULL; - message_token->length = 0; - *minor_status = kret; - return GSS_S_FAILURE; - } - - assert (encdata.length == 8); - - memcpy (p, encdata.data, encdata.length); - krb5_data_free (&encdata); - - krb5_auth_con_setlocalseqnumber (context, - ctx->auth_context, - ++seq_number); - HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); - - free_Checksum (&cksum); - *minor_status = 0; - return GSS_S_COMPLETE; -} - OM_uint32 GSSAPI_CALLCONV _gsskrb5_get_mic (OM_uint32 * minor_status, gss_const_ctx_id_t context_handle, @@ -304,17 +64,11 @@ OM_uint32 GSSAPI_CALLCONV _gsskrb5_get_mic case KRB5_ENCTYPE_DES_CBC_CRC : case KRB5_ENCTYPE_DES_CBC_MD4 : case KRB5_ENCTYPE_DES_CBC_MD5 : -#ifdef HEIM_WEAK_CRYPTO - ret = mic_des (minor_status, ctx, context, qop_req, - message_buffer, message_token, key); -#else ret = GSS_S_FAILURE; -#endif break; case KRB5_ENCTYPE_DES3_CBC_MD5 : case KRB5_ENCTYPE_DES3_CBC_SHA1 : - ret = mic_des3 (minor_status, ctx, context, qop_req, - message_buffer, message_token, key); + ret = GSS_S_FAILURE; break; case KRB5_ENCTYPE_ARCFOUR_HMAC_MD5: case KRB5_ENCTYPE_ARCFOUR_HMAC_MD5_56: diff --git a/lib/gssapi/krb5/unwrap.c b/lib/gssapi/krb5/unwrap.c index 9e45fbd27..23fa6aab7 100644 --- a/lib/gssapi/krb5/unwrap.c +++ b/lib/gssapi/krb5/unwrap.c @@ -33,372 +33,6 @@ #include "gsskrb5_locl.h" -#ifdef HEIM_WEAK_CRYPTO - -static OM_uint32 -unwrap_des - (OM_uint32 * minor_status, - const gsskrb5_ctx context_handle, - const gss_buffer_t input_message_buffer, - gss_buffer_t output_message_buffer, - int * conf_state, - gss_qop_t * qop_state, - krb5_keyblock *key - ) -{ - u_char *p, *seq; - size_t len; - EVP_MD_CTX *md5; - u_char hash[16]; - EVP_CIPHER_CTX des_ctx; - DES_key_schedule schedule; - DES_cblock deskey; - DES_cblock zero; - size_t i; - uint32_t seq_number; - size_t padlength; - OM_uint32 ret, seq_err; - int cstate; - int cmp; - int token_len; - - if (IS_DCE_STYLE(context_handle)) { - token_len = 22 + 8 + 15; /* 45 */ - if (input_message_buffer->length < token_len) - return GSS_S_BAD_MECH; - } else { - token_len = input_message_buffer->length; - } - - p = input_message_buffer->value; - ret = _gsskrb5_verify_header (&p, - token_len, - "\x02\x01", - GSS_KRB5_MECHANISM); - if (ret) - return ret; - - len = (p - (u_char *)input_message_buffer->value) - + 22 + 8; - if (input_message_buffer->length < len) - return GSS_S_BAD_MECH; - - if (memcmp (p, "\x00\x00", 2) != 0) - return GSS_S_BAD_SIG; - p += 2; - if (memcmp (p, "\x00\x00", 2) == 0) { - cstate = 1; - } else if (memcmp (p, "\xFF\xFF", 2) == 0) { - cstate = 0; - } else - return GSS_S_BAD_MIC; - p += 2; - if(conf_state != NULL) - *conf_state = cstate; - if (memcmp (p, "\xff\xff", 2) != 0) - return GSS_S_DEFECTIVE_TOKEN; - p += 2; - p += 16; - - len = p - (u_char *)input_message_buffer->value; - - if(cstate) { - /* decrypt data */ - memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); - memset (&zero, 0, sizeof(zero)); - - for (i = 0; i < sizeof(deskey); ++i) - deskey[i] ^= 0xf0; - - - EVP_CIPHER_CTX_init(&des_ctx); - EVP_CipherInit_ex(&des_ctx, EVP_des_cbc(), NULL, deskey, zero, 0); - EVP_Cipher(&des_ctx, p, p, input_message_buffer->length - len); - EVP_CIPHER_CTX_cleanup(&des_ctx); - - memset (&deskey, 0, sizeof(deskey)); - } - - if (IS_DCE_STYLE(context_handle)) { - padlength = 0; - } else { - /* check pad */ - ret = _gssapi_verify_pad(input_message_buffer, - input_message_buffer->length - len - 8, - &padlength); - if (ret) - return ret; - } - - md5 = EVP_MD_CTX_create(); - EVP_DigestInit_ex(md5, EVP_md5(), NULL); - EVP_DigestUpdate(md5, p - 24, 8); - EVP_DigestUpdate(md5, p, input_message_buffer->length - len); - EVP_DigestFinal_ex(md5, hash, NULL); - EVP_MD_CTX_destroy(md5); - - memset (&zero, 0, sizeof(zero)); - memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); - DES_set_key_unchecked (&deskey, &schedule); - DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash), - &schedule, &zero); - if (ct_memcmp (p - 8, hash, 8) != 0) { - memset_s(&deskey, sizeof(deskey), 0, sizeof(deskey)); - memset_s(&schedule, sizeof(schedule), 0, sizeof(schedule)); - return GSS_S_BAD_MIC; - } - - /* verify sequence number */ - - HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); - - p -= 16; - - EVP_CIPHER_CTX_init(&des_ctx); - EVP_CipherInit_ex(&des_ctx, EVP_des_cbc(), NULL, key->keyvalue.data, hash, 0); - EVP_Cipher(&des_ctx, p, p, 8); - EVP_CIPHER_CTX_cleanup(&des_ctx); - - memset (deskey, 0, sizeof(deskey)); - memset (&schedule, 0, sizeof(schedule)); - - seq = p; - _gss_mg_decode_be_uint32(seq, &seq_number); - - if (context_handle->more_flags & LOCAL) - cmp = ct_memcmp(&seq[4], "\xff\xff\xff\xff", 4); - else - cmp = ct_memcmp(&seq[4], "\x00\x00\x00\x00", 4); - - if (cmp != 0) { - HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); - return GSS_S_BAD_MIC; - } - - seq_err = _gssapi_msg_order_check(context_handle->order, seq_number); - if (seq_err == GSS_S_FAILURE) { - HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); - return seq_err; - } - - HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); - - /* copy out data */ - - output_message_buffer->length = input_message_buffer->length - - len - padlength - 8; - output_message_buffer->value = malloc(output_message_buffer->length); - if(output_message_buffer->length != 0 && output_message_buffer->value == NULL) - return GSS_S_FAILURE; - if (output_message_buffer->value != NULL) - memcpy (output_message_buffer->value, - p + 24, - output_message_buffer->length); - return GSS_S_COMPLETE | seq_err; -} -#endif - -static OM_uint32 -unwrap_des3 - (OM_uint32 * minor_status, - const gsskrb5_ctx context_handle, - krb5_context context, - const gss_buffer_t input_message_buffer, - gss_buffer_t output_message_buffer, - int * conf_state, - gss_qop_t * qop_state, - krb5_keyblock *key - ) -{ - u_char *p; - size_t len; - u_char *seq; - krb5_data seq_data; - u_char cksum[20]; - uint32_t seq_number; - size_t padlength; - OM_uint32 ret, seq_err; - int cstate; - krb5_crypto crypto; - Checksum csum; - int cmp; - int token_len; - - if (IS_DCE_STYLE(context_handle)) { - token_len = 34 + 8 + 15; /* 57 */ - if (input_message_buffer->length < token_len) - return GSS_S_BAD_MECH; - } else { - token_len = input_message_buffer->length; - } - - p = input_message_buffer->value; - ret = _gsskrb5_verify_header (&p, - token_len, - "\x02\x01", - GSS_KRB5_MECHANISM); - if (ret) - return ret; - - len = (p - (u_char *)input_message_buffer->value) - + 34 + 8; - if (input_message_buffer->length < len) - return GSS_S_BAD_MECH; - - if (ct_memcmp (p, "\x04\x00", 2) != 0) /* HMAC SHA1 DES3_KD */ - return GSS_S_BAD_SIG; - p += 2; - if (ct_memcmp (p, "\x02\x00", 2) == 0) { - cstate = 1; - } else if (ct_memcmp (p, "\xff\xff", 2) == 0) { - cstate = 0; - } else - return GSS_S_BAD_MIC; - p += 2; - if(conf_state != NULL) - *conf_state = cstate; - if (ct_memcmp (p, "\xff\xff", 2) != 0) - return GSS_S_DEFECTIVE_TOKEN; - p += 2; - p += 28; - - len = p - (u_char *)input_message_buffer->value; - - if(cstate) { - /* decrypt data */ - krb5_data tmp; - - ret = krb5_crypto_init(context, key, - ETYPE_DES3_CBC_NONE, &crypto); - if (ret) { - *minor_status = ret; - return GSS_S_FAILURE; - } - ret = krb5_decrypt(context, crypto, KRB5_KU_USAGE_SEAL, - p, input_message_buffer->length - len, &tmp); - krb5_crypto_destroy(context, crypto); - if (ret) { - *minor_status = ret; - return GSS_S_FAILURE; - } - assert (tmp.length == input_message_buffer->length - len); - - memcpy (p, tmp.data, tmp.length); - krb5_data_free(&tmp); - } - - if (IS_DCE_STYLE(context_handle)) { - padlength = 0; - } else { - /* check pad */ - ret = _gssapi_verify_pad(input_message_buffer, - input_message_buffer->length - len - 8, - &padlength); - if (ret) - return ret; - } - - /* verify sequence number */ - - HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); - - p -= 28; - - ret = krb5_crypto_init(context, key, - ETYPE_DES3_CBC_NONE, &crypto); - if (ret) { - *minor_status = ret; - HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); - return GSS_S_FAILURE; - } - { - DES_cblock ivec; - - memcpy(&ivec, p + 8, 8); - ret = krb5_decrypt_ivec (context, - crypto, - KRB5_KU_USAGE_SEQ, - p, 8, &seq_data, - &ivec); - } - krb5_crypto_destroy (context, crypto); - if (ret) { - *minor_status = ret; - HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); - return GSS_S_FAILURE; - } - if (seq_data.length != 8) { - krb5_data_free (&seq_data); - *minor_status = 0; - HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); - return GSS_S_BAD_MIC; - } - - seq = seq_data.data; - _gss_mg_decode_be_uint32(seq, &seq_number); - - if (context_handle->more_flags & LOCAL) - cmp = ct_memcmp(&seq[4], "\xff\xff\xff\xff", 4); - else - cmp = ct_memcmp(&seq[4], "\x00\x00\x00\x00", 4); - - krb5_data_free (&seq_data); - if (cmp != 0) { - *minor_status = 0; - HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); - return GSS_S_BAD_MIC; - } - - seq_err = _gssapi_msg_order_check(context_handle->order, seq_number); - if (seq_err == GSS_S_FAILURE) { - *minor_status = 0; - HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); - return seq_err; - } - - HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); - - /* verify checksum */ - - memcpy (cksum, p + 8, 20); - - memcpy (p + 20, p - 8, 8); - - csum.cksumtype = CKSUMTYPE_HMAC_SHA1_DES3; - csum.checksum.length = 20; - csum.checksum.data = cksum; - - ret = krb5_crypto_init(context, key, 0, &crypto); - if (ret) { - *minor_status = ret; - return GSS_S_FAILURE; - } - - ret = krb5_verify_checksum (context, crypto, - KRB5_KU_USAGE_SIGN, - p + 20, - input_message_buffer->length - len + 8, - &csum); - krb5_crypto_destroy (context, crypto); - if (ret) { - *minor_status = ret; - return GSS_S_FAILURE; - } - - /* copy out data */ - - output_message_buffer->length = input_message_buffer->length - - len - padlength - 8; - output_message_buffer->value = malloc(output_message_buffer->length); - if(output_message_buffer->length != 0 && output_message_buffer->value == NULL) - return GSS_S_FAILURE; - if (output_message_buffer->value != NULL) - memcpy (output_message_buffer->value, - p + 36, - output_message_buffer->length); - return GSS_S_COMPLETE | seq_err; -} - OM_uint32 GSSAPI_CALLCONV _gsskrb5_unwrap (OM_uint32 * minor_status, gss_const_ctx_id_t context_handle, @@ -439,19 +73,11 @@ OM_uint32 GSSAPI_CALLCONV _gsskrb5_unwrap case KRB5_ENCTYPE_DES_CBC_CRC : case KRB5_ENCTYPE_DES_CBC_MD4 : case KRB5_ENCTYPE_DES_CBC_MD5 : -#ifdef HEIM_WEAK_CRYPTO - ret = unwrap_des (minor_status, ctx, - input_message_buffer, output_message_buffer, - conf_state, qop_state, key); -#else ret = GSS_S_FAILURE; -#endif break; case KRB5_ENCTYPE_DES3_CBC_MD5 : case KRB5_ENCTYPE_DES3_CBC_SHA1 : - ret = unwrap_des3 (minor_status, ctx, context, - input_message_buffer, output_message_buffer, - conf_state, qop_state, key); + ret = GSS_S_FAILURE; break; case KRB5_ENCTYPE_ARCFOUR_HMAC_MD5: case KRB5_ENCTYPE_ARCFOUR_HMAC_MD5_56: diff --git a/lib/gssapi/krb5/verify_mic.c b/lib/gssapi/krb5/verify_mic.c index 3b97a9059..73f654720 100644 --- a/lib/gssapi/krb5/verify_mic.c +++ b/lib/gssapi/krb5/verify_mic.c @@ -33,245 +33,6 @@ #include "gsskrb5_locl.h" -#ifdef HEIM_WEAK_CRYPTO - -static OM_uint32 -verify_mic_des - (OM_uint32 * minor_status, - const gsskrb5_ctx context_handle, - krb5_context context, - const gss_buffer_t message_buffer, - const gss_buffer_t token_buffer, - gss_qop_t * qop_state, - krb5_keyblock *key, - const char *type - ) -{ - u_char *p; - EVP_MD_CTX *md5; - u_char hash[16], *seq; - DES_key_schedule schedule; - EVP_CIPHER_CTX des_ctx; - DES_cblock zero; - DES_cblock deskey; - uint32_t seq_number; - OM_uint32 ret; - int cmp; - - p = token_buffer->value; - ret = _gsskrb5_verify_header (&p, - token_buffer->length, - type, - GSS_KRB5_MECHANISM); - if (ret) - return ret; - - if (memcmp(p, "\x00\x00", 2) != 0) - return GSS_S_BAD_SIG; - p += 2; - if (memcmp (p, "\xff\xff\xff\xff", 4) != 0) - return GSS_S_BAD_MIC; - p += 4; - p += 16; - - /* verify checksum */ - md5 = EVP_MD_CTX_create(); - EVP_DigestInit_ex(md5, EVP_md5(), NULL); - EVP_DigestUpdate(md5, p - 24, 8); - EVP_DigestUpdate(md5, message_buffer->value, message_buffer->length); - EVP_DigestFinal_ex(md5, hash, NULL); - EVP_MD_CTX_destroy(md5); - - memset (&zero, 0, sizeof(zero)); - memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); - - DES_set_key_unchecked (&deskey, &schedule); - DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash), - &schedule, &zero); - if (ct_memcmp (p - 8, hash, 8) != 0) { - memset_s(deskey, sizeof(deskey), 0, sizeof(deskey)); - memset_s(&schedule, sizeof(schedule), 0, sizeof(schedule)); - return GSS_S_BAD_MIC; - } - - /* verify sequence number */ - - HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); - - p -= 16; - - EVP_CIPHER_CTX_init(&des_ctx); - EVP_CipherInit_ex(&des_ctx, EVP_des_cbc(), NULL, key->keyvalue.data, hash, 0); - EVP_Cipher(&des_ctx, p, p, 8); - EVP_CIPHER_CTX_cleanup(&des_ctx); - - memset_s(deskey, sizeof(deskey), 0, sizeof(deskey)); - memset_s(&schedule, sizeof(schedule), 0, sizeof(schedule)); - - seq = p; - _gss_mg_decode_be_uint32(seq, &seq_number); - - if (context_handle->more_flags & LOCAL) - cmp = ct_memcmp(&seq[4], "\xff\xff\xff\xff", 4); - else - cmp = ct_memcmp(&seq[4], "\x00\x00\x00\x00", 4); - - if (cmp != 0) { - HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); - return GSS_S_BAD_MIC; - } - - ret = _gssapi_msg_order_check(context_handle->order, seq_number); - if (ret) { - HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); - return ret; - } - - HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); - - return GSS_S_COMPLETE; -} -#endif - -static OM_uint32 -verify_mic_des3 - (OM_uint32 * minor_status, - const gsskrb5_ctx context_handle, - krb5_context context, - const gss_buffer_t message_buffer, - const gss_buffer_t token_buffer, - gss_qop_t * qop_state, - krb5_keyblock *key, - const char *type - ) -{ - u_char *p; - u_char *seq; - uint32_t seq_number; - OM_uint32 ret, seq_err; - krb5_crypto crypto; - krb5_data seq_data; - int cmp, docompat; - Checksum csum; - char *tmp; - char ivec[8]; - - p = token_buffer->value; - ret = _gsskrb5_verify_header (&p, - token_buffer->length, - type, - GSS_KRB5_MECHANISM); - if (ret) - return ret; - - if (memcmp(p, "\x04\x00", 2) != 0) /* SGN_ALG = HMAC SHA1 DES3-KD */ - return GSS_S_BAD_SIG; - p += 2; - if (memcmp (p, "\xff\xff\xff\xff", 4) != 0) - return GSS_S_BAD_MIC; - p += 4; - - ret = krb5_crypto_init(context, key, - ETYPE_DES3_CBC_NONE, &crypto); - if (ret){ - *minor_status = ret; - return GSS_S_FAILURE; - } - - /* verify sequence number */ - docompat = 0; -retry: - if (docompat) - memset(ivec, 0, 8); - else - memcpy(ivec, p + 8, 8); - - ret = krb5_decrypt_ivec (context, - crypto, - KRB5_KU_USAGE_SEQ, - p, 8, &seq_data, ivec); - if (ret) { - if (docompat++) { - krb5_crypto_destroy (context, crypto); - *minor_status = ret; - return GSS_S_FAILURE; - } else - goto retry; - } - - if (seq_data.length != 8) { - krb5_data_free (&seq_data); - if (docompat++) { - krb5_crypto_destroy (context, crypto); - return GSS_S_BAD_MIC; - } else - goto retry; - } - - HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); - - seq = seq_data.data; - _gss_mg_decode_be_uint32(seq, &seq_number); - - if (context_handle->more_flags & LOCAL) - cmp = ct_memcmp(&seq[4], "\xff\xff\xff\xff", 4); - else - cmp = ct_memcmp(&seq[4], "\x00\x00\x00\x00", 4); - - krb5_data_free (&seq_data); - if (cmp != 0) { - krb5_crypto_destroy (context, crypto); - *minor_status = 0; - HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); - return GSS_S_BAD_MIC; - } - - seq_err = _gssapi_msg_order_check(context_handle->order, seq_number); - if (seq_err == GSS_S_FAILURE) { - krb5_crypto_destroy (context, crypto); - *minor_status = 0; - HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); - return ret; - } - - /* verify checksum */ - - tmp = malloc (message_buffer->length + 8); - if (tmp == NULL) { - krb5_crypto_destroy (context, crypto); - HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - - memcpy (tmp, p - 8, 8); - memcpy (tmp + 8, message_buffer->value, message_buffer->length); - - csum.cksumtype = CKSUMTYPE_HMAC_SHA1_DES3; - csum.checksum.length = 20; - csum.checksum.data = p + 8; - - krb5_crypto_destroy (context, crypto); - ret = krb5_crypto_init(context, key, - ETYPE_DES3_CBC_SHA1, &crypto); - if (ret == 0) - ret = krb5_verify_checksum(context, crypto, - KRB5_KU_USAGE_SIGN, - tmp, message_buffer->length + 8, - &csum); - free (tmp); - if (ret) { - krb5_crypto_destroy (context, crypto); - *minor_status = ret; - HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); - return GSS_S_BAD_MIC; - } - HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); - - krb5_crypto_destroy (context, crypto); - return GSS_S_COMPLETE | seq_err; -} - OM_uint32 _gsskrb5_verify_mic_internal (OM_uint32 * minor_status, @@ -304,19 +65,11 @@ _gsskrb5_verify_mic_internal case KRB5_ENCTYPE_DES_CBC_CRC : case KRB5_ENCTYPE_DES_CBC_MD4 : case KRB5_ENCTYPE_DES_CBC_MD5 : -#ifdef HEIM_WEAK_CRYPTO - ret = verify_mic_des (minor_status, ctx, context, - message_buffer, token_buffer, qop_state, key, - type); -#else - ret = GSS_S_FAILURE; -#endif + ret = GSS_S_FAILURE; break; case KRB5_ENCTYPE_DES3_CBC_MD5 : case KRB5_ENCTYPE_DES3_CBC_SHA1 : - ret = verify_mic_des3 (minor_status, ctx, context, - message_buffer, token_buffer, qop_state, key, - type); + ret = GSS_S_FAILURE; break; case KRB5_ENCTYPE_ARCFOUR_HMAC_MD5: case KRB5_ENCTYPE_ARCFOUR_HMAC_MD5_56: diff --git a/lib/gssapi/krb5/wrap.c b/lib/gssapi/krb5/wrap.c index 481e30375..1709a8727 100644 --- a/lib/gssapi/krb5/wrap.c +++ b/lib/gssapi/krb5/wrap.c @@ -193,338 +193,6 @@ _gsskrb5_wrap_size_limit ( return ret; } -#ifdef HEIM_WEAK_CRYPTO - -static OM_uint32 -wrap_des - (OM_uint32 * minor_status, - const gsskrb5_ctx ctx, - krb5_context context, - int conf_req_flag, - gss_qop_t qop_req, - const gss_buffer_t input_message_buffer, - int * conf_state, - gss_buffer_t output_message_buffer, - krb5_keyblock *key - ) -{ - u_char *p; - EVP_MD_CTX *md5; - u_char hash[16]; - DES_key_schedule schedule; - EVP_CIPHER_CTX des_ctx; - DES_cblock deskey; - DES_cblock zero; - size_t i; - int32_t seq_number; - size_t len, total_len, padlength, datalen; - - if (IS_DCE_STYLE(ctx)) { - padlength = 0; - datalen = input_message_buffer->length; - len = 22 + 8; - _gsskrb5_encap_length (len, &len, &total_len, GSS_KRB5_MECHANISM); - total_len += datalen; - datalen += 8; - } else { - padlength = 8 - (input_message_buffer->length % 8); - datalen = input_message_buffer->length + padlength + 8; - len = datalen + 22; - _gsskrb5_encap_length (len, &len, &total_len, GSS_KRB5_MECHANISM); - } - - output_message_buffer->length = total_len; - output_message_buffer->value = malloc (total_len); - if (output_message_buffer->value == NULL) { - output_message_buffer->length = 0; - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - - p = _gsskrb5_make_header(output_message_buffer->value, - len, - "\x02\x01", /* TOK_ID */ - GSS_KRB5_MECHANISM); - - /* SGN_ALG */ - memcpy (p, "\x00\x00", 2); - p += 2; - /* SEAL_ALG */ - if(conf_req_flag) - memcpy (p, "\x00\x00", 2); - else - memcpy (p, "\xff\xff", 2); - p += 2; - /* Filler */ - memcpy (p, "\xff\xff", 2); - p += 2; - - /* fill in later */ - memset (p, 0, 16); - p += 16; - - /* confounder + data + pad */ - krb5_generate_random_block(p, 8); - memcpy (p + 8, input_message_buffer->value, - input_message_buffer->length); - memset (p + 8 + input_message_buffer->length, padlength, padlength); - - /* checksum */ - md5 = EVP_MD_CTX_create(); - EVP_DigestInit_ex(md5, EVP_md5(), NULL); - EVP_DigestUpdate(md5, p - 24, 8); - EVP_DigestUpdate(md5, p, datalen); - EVP_DigestFinal_ex(md5, hash, NULL); - EVP_MD_CTX_destroy(md5); - - memset (&zero, 0, sizeof(zero)); - memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); - DES_set_key_unchecked (&deskey, &schedule); - DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash), - &schedule, &zero); - memcpy (p - 8, hash, 8); - - /* sequence number */ - HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); - krb5_auth_con_getlocalseqnumber (context, - ctx->auth_context, - &seq_number); - - p -= 16; - p[0] = (seq_number >> 0) & 0xFF; - p[1] = (seq_number >> 8) & 0xFF; - p[2] = (seq_number >> 16) & 0xFF; - p[3] = (seq_number >> 24) & 0xFF; - memset (p + 4, - (ctx->more_flags & LOCAL) ? 0 : 0xFF, - 4); - - EVP_CIPHER_CTX_init(&des_ctx); - EVP_CipherInit_ex(&des_ctx, EVP_des_cbc(), NULL, key->keyvalue.data, p + 8, 1); - EVP_Cipher(&des_ctx, p, p, 8); - EVP_CIPHER_CTX_cleanup(&des_ctx); - - krb5_auth_con_setlocalseqnumber (context, - ctx->auth_context, - ++seq_number); - HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); - - /* encrypt the data */ - p += 16; - - if(conf_req_flag) { - memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); - - for (i = 0; i < sizeof(deskey); ++i) - deskey[i] ^= 0xf0; - - EVP_CIPHER_CTX_init(&des_ctx); - EVP_CipherInit_ex(&des_ctx, EVP_des_cbc(), NULL, deskey, zero, 1); - EVP_Cipher(&des_ctx, p, p, datalen); - EVP_CIPHER_CTX_cleanup(&des_ctx); - } - memset (deskey, 0, sizeof(deskey)); - memset (&schedule, 0, sizeof(schedule)); - - if(conf_state != NULL) - *conf_state = conf_req_flag; - *minor_status = 0; - return GSS_S_COMPLETE; -} - -#endif - -static OM_uint32 -wrap_des3 - (OM_uint32 * minor_status, - const gsskrb5_ctx ctx, - krb5_context context, - int conf_req_flag, - gss_qop_t qop_req, - const gss_buffer_t input_message_buffer, - int * conf_state, - gss_buffer_t output_message_buffer, - krb5_keyblock *key - ) -{ - u_char *p; - u_char seq[8]; - int32_t seq_number; - size_t len, total_len, padlength, datalen; - uint32_t ret; - krb5_crypto crypto; - Checksum cksum; - krb5_data encdata; - - if (IS_DCE_STYLE(ctx)) { - padlength = 0; - datalen = input_message_buffer->length; - len = 34 + 8; - _gsskrb5_encap_length (len, &len, &total_len, GSS_KRB5_MECHANISM); - total_len += datalen; - datalen += 8; - } else { - padlength = 8 - (input_message_buffer->length % 8); - datalen = input_message_buffer->length + padlength + 8; - len = datalen + 34; - _gsskrb5_encap_length (len, &len, &total_len, GSS_KRB5_MECHANISM); - } - - output_message_buffer->length = total_len; - output_message_buffer->value = malloc (total_len); - if (output_message_buffer->value == NULL) { - output_message_buffer->length = 0; - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - - p = _gsskrb5_make_header(output_message_buffer->value, - len, - "\x02\x01", /* TOK_ID */ - GSS_KRB5_MECHANISM); - - /* SGN_ALG */ - memcpy (p, "\x04\x00", 2); /* HMAC SHA1 DES3-KD */ - p += 2; - /* SEAL_ALG */ - if(conf_req_flag) - memcpy (p, "\x02\x00", 2); /* DES3-KD */ - else - memcpy (p, "\xff\xff", 2); - p += 2; - /* Filler */ - memcpy (p, "\xff\xff", 2); - p += 2; - - /* calculate checksum (the above + confounder + data + pad) */ - - memcpy (p + 20, p - 8, 8); - krb5_generate_random_block(p + 28, 8); - memcpy (p + 28 + 8, input_message_buffer->value, - input_message_buffer->length); - memset (p + 28 + 8 + input_message_buffer->length, padlength, padlength); - - ret = krb5_crypto_init(context, key, 0, &crypto); - if (ret) { - free (output_message_buffer->value); - output_message_buffer->length = 0; - output_message_buffer->value = NULL; - *minor_status = ret; - return GSS_S_FAILURE; - } - - ret = krb5_create_checksum (context, - crypto, - KRB5_KU_USAGE_SIGN, - 0, - p + 20, - datalen + 8, - &cksum); - krb5_crypto_destroy (context, crypto); - if (ret) { - free (output_message_buffer->value); - output_message_buffer->length = 0; - output_message_buffer->value = NULL; - *minor_status = ret; - return GSS_S_FAILURE; - } - - /* zero out SND_SEQ + SGN_CKSUM in case */ - memset (p, 0, 28); - - memcpy (p + 8, cksum.checksum.data, cksum.checksum.length); - free_Checksum (&cksum); - - HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); - /* sequence number */ - krb5_auth_con_getlocalseqnumber (context, - ctx->auth_context, - &seq_number); - - seq[0] = (seq_number >> 0) & 0xFF; - seq[1] = (seq_number >> 8) & 0xFF; - seq[2] = (seq_number >> 16) & 0xFF; - seq[3] = (seq_number >> 24) & 0xFF; - memset (seq + 4, - (ctx->more_flags & LOCAL) ? 0 : 0xFF, - 4); - - - ret = krb5_crypto_init(context, key, ETYPE_DES3_CBC_NONE, - &crypto); - if (ret) { - free (output_message_buffer->value); - output_message_buffer->length = 0; - output_message_buffer->value = NULL; - *minor_status = ret; - return GSS_S_FAILURE; - } - - { - DES_cblock ivec; - - memcpy (&ivec, p + 8, 8); - ret = krb5_encrypt_ivec (context, - crypto, - KRB5_KU_USAGE_SEQ, - seq, 8, &encdata, - &ivec); - } - krb5_crypto_destroy (context, crypto); - if (ret) { - free (output_message_buffer->value); - output_message_buffer->length = 0; - output_message_buffer->value = NULL; - *minor_status = ret; - return GSS_S_FAILURE; - } - - assert (encdata.length == 8); - - memcpy (p, encdata.data, encdata.length); - krb5_data_free (&encdata); - - krb5_auth_con_setlocalseqnumber (context, - ctx->auth_context, - ++seq_number); - HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); - - /* encrypt the data */ - p += 28; - - if(conf_req_flag) { - krb5_data tmp; - - ret = krb5_crypto_init(context, key, - ETYPE_DES3_CBC_NONE, &crypto); - if (ret) { - free (output_message_buffer->value); - output_message_buffer->length = 0; - output_message_buffer->value = NULL; - *minor_status = ret; - return GSS_S_FAILURE; - } - ret = krb5_encrypt(context, crypto, KRB5_KU_USAGE_SEAL, - p, datalen, &tmp); - krb5_crypto_destroy(context, crypto); - if (ret) { - free (output_message_buffer->value); - output_message_buffer->length = 0; - output_message_buffer->value = NULL; - *minor_status = ret; - return GSS_S_FAILURE; - } - assert (tmp.length == datalen); - - memcpy (p, tmp.data, datalen); - krb5_data_free(&tmp); - } - if(conf_state != NULL) - *conf_state = conf_req_flag; - *minor_status = 0; - return GSS_S_COMPLETE; -} - OM_uint32 GSSAPI_CALLCONV _gsskrb5_wrap (OM_uint32 * minor_status, @@ -563,19 +231,11 @@ _gsskrb5_wrap case KRB5_ENCTYPE_DES_CBC_CRC : case KRB5_ENCTYPE_DES_CBC_MD4 : case KRB5_ENCTYPE_DES_CBC_MD5 : -#ifdef HEIM_WEAK_CRYPTO - ret = wrap_des (minor_status, ctx, context, conf_req_flag, - qop_req, input_message_buffer, conf_state, - output_message_buffer, key); -#else ret = GSS_S_FAILURE; -#endif break; case KRB5_ENCTYPE_DES3_CBC_MD5 : case KRB5_ENCTYPE_DES3_CBC_SHA1 : - ret = wrap_des3 (minor_status, ctx, context, conf_req_flag, - qop_req, input_message_buffer, conf_state, - output_message_buffer, key); + ret = GSS_S_FAILURE; break; case KRB5_ENCTYPE_ARCFOUR_HMAC_MD5: case KRB5_ENCTYPE_ARCFOUR_HMAC_MD5_56: diff --git a/lib/gssapi/mech/gss_mech_switch.c b/lib/gssapi/mech/gss_mech_switch.c index 3151efe42..245aaad81 100644 --- a/lib/gssapi/mech/gss_mech_switch.c +++ b/lib/gssapi/mech/gss_mech_switch.c @@ -304,9 +304,6 @@ _gss_load_mech(void) if (add_builtin(__gss_spnego_initialize())) _gss_mg_log(1, "Out of memory while adding builtin SPNEGO " "mechanism to the GSS mechanism switch"); - if (add_builtin(__gss_ntlm_initialize())) - _gss_mg_log(1, "Out of memory while adding builtin NTLM " - "mechanism to the GSS mechanism switch"); #ifdef HAVE_DLOPEN fp = fopen(conf ? conf : _PATH_GSS_MECH, "r"); diff --git a/lib/gssapi/netlogon/accept_sec_context.c b/lib/gssapi/netlogon/accept_sec_context.c deleted file mode 100644 index 06ddfd507..000000000 --- a/lib/gssapi/netlogon/accept_sec_context.c +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2009 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Portions Copyright (c) 2009 Apple Inc. 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 "netlogon.h" - -/* - * Not implemented: this is needed only by domain controllers. - */ - -OM_uint32 -_netlogon_accept_sec_context -(OM_uint32 * minor_status, - gss_ctx_id_t * context_handle, - gss_const_cred_id_t acceptor_cred_handle, - const gss_buffer_t input_token_buffer, - const gss_channel_bindings_t input_chan_bindings, - gss_name_t * src_name, - gss_OID * mech_type, - gss_buffer_t output_token, - OM_uint32 * ret_flags, - OM_uint32 * time_rec, - gss_cred_id_t * delegated_cred_handle - ) -{ - - output_token->value = NULL; - output_token->length = 0; - - *minor_status = 0; - - if (context_handle == NULL) - return GSS_S_FAILURE; - - if (input_token_buffer == GSS_C_NO_BUFFER) - return GSS_S_FAILURE; - - if (src_name) - *src_name = GSS_C_NO_NAME; - if (mech_type) - *mech_type = GSS_C_NO_OID; - if (ret_flags) - *ret_flags = 0; - if (time_rec) - *time_rec = 0; - if (delegated_cred_handle) - *delegated_cred_handle = GSS_C_NO_CREDENTIAL; - - if (*context_handle == GSS_C_NO_CONTEXT) { - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } else { - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - - return GSS_S_UNAVAILABLE; -} diff --git a/lib/gssapi/netlogon/acquire_cred.c b/lib/gssapi/netlogon/acquire_cred.c deleted file mode 100644 index d790d08e1..000000000 --- a/lib/gssapi/netlogon/acquire_cred.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (c) 2010 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Portions Copyright (c) 2010 Apple Inc. 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 "netlogon.h" -#include - -OM_uint32 -_netlogon_acquire_cred(OM_uint32 * min_stat, - gss_const_name_t desired_name, - OM_uint32 time_req, - const gss_OID_set desired_mechs, - gss_cred_usage_t cred_usage, - gss_cred_id_t * output_cred_handle, - gss_OID_set * actual_mechs, - OM_uint32 * time_rec) -{ - OM_uint32 ret; - gssnetlogon_cred cred; - - /* only initiator support so far */ - if (cred_usage != GSS_C_INITIATE) - return GSS_S_FAILURE; - - if (desired_name == GSS_C_NO_NAME) - return GSS_S_BAD_NAME; - - cred = (gssnetlogon_cred)calloc(1, sizeof(*cred)); - if (cred == NULL) { - *min_stat = ENOMEM; - return GSS_S_FAILURE; - } - cred->SignatureAlgorithm = NL_SIGN_ALG_HMAC_MD5; - cred->SealAlgorithm = NL_SEAL_ALG_RC4; - - ret = _netlogon_duplicate_name(min_stat, desired_name, - (gss_name_t *)&cred->Name); - if (GSS_ERROR(ret)) { - free(cred); - return ret; - } - - *output_cred_handle = (gss_cred_id_t)cred; - if (actual_mechs != NULL) - *actual_mechs = GSS_C_NO_OID_SET; - if (time_rec != NULL) - *time_rec = GSS_C_INDEFINITE; - - return GSS_S_COMPLETE; -} - -OM_uint32 -_netlogon_acquire_cred_ex(gss_status_id_t status, - gss_const_name_t desired_name, - OM_uint32 flags, - OM_uint32 time_req, - gss_cred_usage_t cred_usage, - gss_auth_identity_t identity, - void *ctx, - void (*complete)(void *, OM_uint32, gss_status_id_t, gss_cred_id_t, OM_uint32)) -{ - return GSS_S_UNAVAILABLE; -} - -/* - * value contains 16 byte session key - */ -static OM_uint32 -_netlogon_set_session_key(OM_uint32 *minor_status, - gss_cred_id_t *cred_handle, - const gss_buffer_t value) -{ - gssnetlogon_cred cred; - - if (*cred_handle == GSS_C_NO_CREDENTIAL) { - *minor_status = EINVAL; - return GSS_S_FAILURE; - } - - cred = (gssnetlogon_cred)*cred_handle; - - if (value->length != sizeof(cred->SessionKey)) { - *minor_status = ERANGE; - return GSS_S_FAILURE; - } - - memcpy(cred->SessionKey, value->value, value->length); - - *minor_status = 0; - return GSS_S_COMPLETE; -} - -/* - * value contains 16 bit little endian encoded seal algorithm - */ -static OM_uint32 -_netlogon_set_sign_algorithm(OM_uint32 *minor_status, - gss_cred_id_t *cred_handle, - const gss_buffer_t value) -{ - gssnetlogon_cred cred; - uint16_t alg; - const uint8_t *p; - - if (*cred_handle == GSS_C_NO_CREDENTIAL) { - *minor_status = EINVAL; - return GSS_S_FAILURE; - } - - cred = (gssnetlogon_cred)*cred_handle; - - if (value->length != 2) { - *minor_status = ERANGE; - return GSS_S_FAILURE; - } - - p = (const uint8_t *)value->value; - alg = (p[0] << 0) | (p[1] << 8); - - if (alg != NL_SIGN_ALG_HMAC_MD5 && alg != NL_SIGN_ALG_SHA256) { - *minor_status = EINVAL; - return GSS_S_FAILURE; - } - - cred->SignatureAlgorithm = alg; - if (alg == NL_SIGN_ALG_SHA256) - cred->SealAlgorithm = NL_SEAL_ALG_AES128; - else - cred->SealAlgorithm = NL_SEAL_ALG_RC4; - - *minor_status = 0; - return GSS_S_COMPLETE; -} - -OM_uint32 -_netlogon_set_cred_option - (OM_uint32 *minor_status, - gss_cred_id_t *cred_handle, - const gss_OID desired_object, - const gss_buffer_t value) -{ - if (value == GSS_C_NO_BUFFER) { - *minor_status = EINVAL; - return GSS_S_FAILURE; - } - - if (gss_oid_equal(desired_object, GSS_NETLOGON_SET_SESSION_KEY_X)) - return _netlogon_set_session_key(minor_status, cred_handle, value); - else if (gss_oid_equal(desired_object, GSS_NETLOGON_SET_SIGN_ALGORITHM_X)) - return _netlogon_set_sign_algorithm(minor_status, cred_handle, value); - - *minor_status = EINVAL; - return GSS_S_FAILURE; -} - diff --git a/lib/gssapi/netlogon/add_cred.c b/lib/gssapi/netlogon/add_cred.c deleted file mode 100644 index 022230319..000000000 --- a/lib/gssapi/netlogon/add_cred.c +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2010 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Portions Copyright (c) 2010 Apple Inc. 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 "netlogon.h" - -OM_uint32 _netlogon_add_cred ( - OM_uint32 *minor_status, - gss_const_cred_id_t input_cred_handle, - gss_const_name_t desired_name, - const gss_OID desired_mech, - gss_cred_usage_t cred_usage, - OM_uint32 initiator_time_req, - OM_uint32 acceptor_time_req, - gss_cred_id_t *output_cred_handle, - gss_OID_set *actual_mechs, - OM_uint32 *initiator_time_rec, - OM_uint32 *acceptor_time_rec) -{ - OM_uint32 ret; - int equal; - const gssnetlogon_cred src = (const gssnetlogon_cred)input_cred_handle; - gssnetlogon_cred dst; - - if (desired_name != GSS_C_NO_NAME) { - if (input_cred_handle != GSS_C_NO_CREDENTIAL) { - ret = _netlogon_compare_name(minor_status, desired_name, - (gss_name_t)src->Name, &equal); - if (GSS_ERROR(ret)) - return ret; - - if (!equal) - return GSS_S_BAD_NAME; - } - } - - ret = _netlogon_acquire_cred(minor_status, - input_cred_handle ? (gss_name_t)src->Name : desired_name, - initiator_time_req, GSS_C_NO_OID_SET, cred_usage, - output_cred_handle, actual_mechs, initiator_time_rec); - if (GSS_ERROR(ret)) - return ret; - - dst = (gssnetlogon_cred)*output_cred_handle; - - if (src != NULL) { - dst->SignatureAlgorithm = src->SignatureAlgorithm; - dst->SealAlgorithm = src->SealAlgorithm; - - memcpy(dst->SessionKey, src->SessionKey, sizeof(src->SessionKey)); - } - - if (acceptor_time_rec != NULL) - *acceptor_time_rec = 0; - - return GSS_S_COMPLETE; -} - diff --git a/lib/gssapi/netlogon/canonicalize_name.c b/lib/gssapi/netlogon/canonicalize_name.c deleted file mode 100644 index 1e8087a7c..000000000 --- a/lib/gssapi/netlogon/canonicalize_name.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2009 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Portions Copyright (c) 2009 Apple Inc. 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 "netlogon.h" - -OM_uint32 _netlogon_canonicalize_name ( - OM_uint32 * minor_status, - gss_const_name_t input_name, - const gss_OID mech_type, - gss_name_t * output_name - ) -{ - return _netlogon_duplicate_name(minor_status, input_name, output_name); -} diff --git a/lib/gssapi/netlogon/compare_name.c b/lib/gssapi/netlogon/compare_name.c deleted file mode 100644 index 986c3b045..000000000 --- a/lib/gssapi/netlogon/compare_name.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2010 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Portions Copyright (c) 2010 Apple Inc. 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 "netlogon.h" - -OM_uint32 _netlogon_compare_name - (OM_uint32 * minor_status, - gss_const_name_t name1, - gss_const_name_t name2, - int * name_equal - ) -{ - const gssnetlogon_name n1 = (const gssnetlogon_name)name1; - const gssnetlogon_name n2 = (const gssnetlogon_name)name2; - - *name_equal = 0; - - if (n1->NetbiosName.value != NULL && n2->NetbiosName.value != NULL) - *name_equal = (strcasecmp((char *)n1->NetbiosName.value, - (char *)n2->NetbiosName.value) == 0); - - if (n1->DnsName.value != NULL && n2->DnsName.value != NULL) - *name_equal = (strcasecmp((char *)n1->DnsName.value, - (char *)n2->DnsName.value) == 0); - - *minor_status = 0; - return GSS_S_COMPLETE; -} - diff --git a/lib/gssapi/netlogon/context_time.c b/lib/gssapi/netlogon/context_time.c deleted file mode 100644 index c7bf9eb14..000000000 --- a/lib/gssapi/netlogon/context_time.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2009 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Portions Copyright (c) 2009 Apple Inc. 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 "netlogon.h" - -OM_uint32 _netlogon_context_time - (OM_uint32 * minor_status, - gss_const_ctx_id_t context_handle, - OM_uint32 * time_rec - ) -{ - if (time_rec != NULL) - *time_rec = GSS_C_INDEFINITE; - return GSS_S_COMPLETE; -} diff --git a/lib/gssapi/netlogon/crypto.c b/lib/gssapi/netlogon/crypto.c deleted file mode 100644 index 6147eec55..000000000 --- a/lib/gssapi/netlogon/crypto.c +++ /dev/null @@ -1,733 +0,0 @@ -/* - * Copyright (c) 2010 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Portions Copyright (c) 2010 Apple Inc. 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 "netlogon.h" - -static uint8_t zeros[4]; - -static void -_netlogon_encode_sequence_number(uint64_t SequenceNumber, uint8_t *p, - int initiatorFlag) -{ - uint32_t LowPart, HighPart; - - LowPart = (SequenceNumber >> 0 ) & 0xFFFFFFFF; - HighPart = (SequenceNumber >> 32) & 0xFFFFFFFF; - - _gss_mg_encode_be_uint32(LowPart, &p[0]); - _gss_mg_encode_be_uint32(HighPart, &p[4]); - - if (initiatorFlag) - p[4] |= 0x80; -} - -static int -_netlogon_decode_sequence_number(void *ptr, uint64_t *n, - int initiatorFlag) -{ - uint8_t *p = ptr; - uint32_t LowPart, HighPart; - int gotInitiatorFlag; - - gotInitiatorFlag = (p[4] & 0x80) != 0; - if (gotInitiatorFlag != initiatorFlag) - return -1; - - p[4] &= 0x7F; /* clear initiator bit */ - - _gss_mg_decode_be_uint32(&p[0], &LowPart); - _gss_mg_decode_be_uint32(&p[4], &HighPart); - - *n = (LowPart << 0) | ((uint64_t)HighPart << 32); - - return 0; -} - -static inline size_t -_netlogon_checksum_length(NL_AUTH_SIGNATURE *sig) -{ -#if 0 - return (sig->SignatureAlgorithm == NL_SIGN_ALG_SHA256) ? 32 : 8; -#else - /* Owing to a bug in Windows it always uses the old value */ - return 8; -#endif -} - -static inline size_t -_netlogon_signature_length(uint16_t alg, int conf_req_flag) -{ - return NL_AUTH_SIGNATURE_COMMON_LENGTH + - (alg == NL_SIGN_ALG_SHA256 ? 32 : 8) + - (conf_req_flag ? 8 : 0); -} - -static inline uint8_t * -_netlogon_confounder(NL_AUTH_SIGNATURE *sig) -{ - size_t cksumlen = _netlogon_checksum_length(sig); - - return &sig->Checksum[cksumlen]; -} - -static int -_netlogon_encode_NL_AUTH_SIGNATURE(NL_AUTH_SIGNATURE *sig, - uint8_t *p, size_t len) -{ - *p++ = (sig->SignatureAlgorithm >> 0) & 0xFF; - *p++ = (sig->SignatureAlgorithm >> 8) & 0xFF; - *p++ = (sig->SealAlgorithm >> 0) & 0xFF; - *p++ = (sig->SealAlgorithm >> 8) & 0xFF; - *p++ = (sig->Pad >> 0) & 0xFF; - *p++ = (sig->Pad >> 8) & 0xFF; - *p++ = (sig->Flags >> 0) & 0xFF; - *p++ = (sig->Flags >> 8) & 0xFF; - - if (len > NL_AUTH_SIGNATURE_HEADER_LENGTH) { - memcpy(p, sig->SequenceNumber, 8); - p += 8; - } - - if (len > NL_AUTH_SIGNATURE_COMMON_LENGTH) { - size_t cksumlen = _netlogon_checksum_length(sig); - - memcpy(p, sig->Checksum, cksumlen); - p += cksumlen; - - /* Confounder, if present, is immediately after checksum */ - if (sig->SealAlgorithm != NL_SEAL_ALG_NONE) { - memcpy(p, &sig->Checksum[cksumlen], 8); - } - } - - return 0; -} - -static int -_netlogon_decode_NL_AUTH_SIGNATURE(const uint8_t *ptr, - size_t len, - NL_AUTH_SIGNATURE *sig) -{ - const uint8_t *p = ptr; - size_t cksumlen; - - if (len < NL_AUTH_SIGNATURE_COMMON_LENGTH) - return KRB5_BAD_MSIZE; - - sig->SignatureAlgorithm = (p[0] << 0) | (p[1] << 8); - sig->SealAlgorithm = (p[2] << 0) | (p[3] << 8); - sig->Pad = (p[4] << 0) | (p[5] << 8); - sig->Flags = (p[6] << 0) | (p[7] << 8); - p += 8; - - memcpy(sig->SequenceNumber, p, 8); - p += 8; - - /* Validate signature algorithm is known and matches enctype */ - switch (sig->SignatureAlgorithm) { - case NL_SIGN_ALG_HMAC_MD5: - cksumlen = NL_AUTH_SIGNATURE_LENGTH; - break; - case NL_SIGN_ALG_SHA256: - cksumlen = NL_AUTH_SHA2_SIGNATURE_LENGTH; - break; - default: - return EINVAL; - break; - } - - if (sig->SealAlgorithm == NL_SEAL_ALG_NONE) - cksumlen -= 8; /* confounder is optional if no sealing */ - - if (len < cksumlen) - return KRB5_BAD_MSIZE; - - /* Copy variable length checksum */ - cksumlen = _netlogon_checksum_length(sig); - memcpy(sig->Checksum, p, cksumlen); - p += cksumlen; - - /* Copy confounder in past checksum */ - if (sig->SealAlgorithm != NL_SEAL_ALG_NONE) - memcpy(&sig->Checksum[cksumlen], p, 8); - - return 0; -} - -static void -_netlogon_derive_rc4_hmac_key(uint8_t key[16], - uint8_t *salt, - size_t saltLength, - EVP_CIPHER_CTX *rc4Key, - int enc) -{ - uint8_t tmpData[MD5_DIGEST_LENGTH]; - uint8_t derivedKey[MD5_DIGEST_LENGTH]; - unsigned int len = MD5_DIGEST_LENGTH; - - HMAC(EVP_md5(), key, 16, zeros, sizeof(zeros), tmpData, &len); - HMAC(EVP_md5(), tmpData, MD5_DIGEST_LENGTH, - salt, saltLength, derivedKey, &len); - - assert(len == MD5_DIGEST_LENGTH); - - EVP_CipherInit_ex(rc4Key, EVP_rc4(), NULL, derivedKey, NULL, enc); - - memset(derivedKey, 0, sizeof(derivedKey)); -} - -static void -_netlogon_derive_rc4_seal_key(gssnetlogon_ctx ctx, - NL_AUTH_SIGNATURE *sig, - EVP_CIPHER_CTX *sealkey, - int enc) -{ - uint8_t xorKey[16]; - int i; - - for (i = 0; i < sizeof(xorKey); i++) { - xorKey[i] = ctx->SessionKey[i] ^ 0xF0; - } - - _netlogon_derive_rc4_hmac_key(xorKey, - sig->SequenceNumber, sizeof(sig->SequenceNumber), sealkey, enc); - - memset(xorKey, 0, sizeof(xorKey)); -} - -static void -_netlogon_derive_rc4_seq_key(gssnetlogon_ctx ctx, - NL_AUTH_SIGNATURE *sig, - EVP_CIPHER_CTX *seqkey, - int enc) -{ - _netlogon_derive_rc4_hmac_key(ctx->SessionKey, - sig->Checksum, sizeof(sig->Checksum), seqkey, enc); -} - -static void -_netlogon_derive_aes_seal_key(gssnetlogon_ctx ctx, - NL_AUTH_SIGNATURE *sig, - EVP_CIPHER_CTX *sealkey, - int enc) -{ - uint8_t encryptionKey[16]; - uint8_t ivec[16]; - int i; - - for (i = 0; i < sizeof(encryptionKey); i++) { - encryptionKey[i] = ctx->SessionKey[i] ^ 0xF0; - } - - memcpy(&ivec[0], sig->SequenceNumber, 8); - memcpy(&ivec[8], sig->SequenceNumber, 8); - - EVP_CipherInit_ex(sealkey, EVP_aes_128_cfb8(), - NULL, encryptionKey, ivec, enc); - - memset(encryptionKey, 0, sizeof(encryptionKey)); -} - -static void -_netlogon_derive_aes_seq_key(gssnetlogon_ctx ctx, - NL_AUTH_SIGNATURE *sig, - EVP_CIPHER_CTX *seqkey, - int enc) -{ - uint8_t ivec[16]; - - memcpy(&ivec[0], sig->Checksum, 8); - memcpy(&ivec[8], sig->Checksum, 8); - - EVP_CipherInit_ex(seqkey, EVP_aes_128_cfb8(), - NULL, ctx->SessionKey, ivec, enc); -} - -static void -_netlogon_seal(gssnetlogon_ctx ctx, - NL_AUTH_SIGNATURE *sig, - gss_iov_buffer_desc *iov, - int iov_count, - int enc) -{ - EVP_CIPHER_CTX sealkey; - int i; - uint8_t *confounder = _netlogon_confounder(sig); - - EVP_CIPHER_CTX_init(&sealkey); - - if (sig->SealAlgorithm == NL_SEAL_ALG_AES128) - _netlogon_derive_aes_seal_key(ctx, sig, &sealkey, enc); - else - _netlogon_derive_rc4_seal_key(ctx, sig, &sealkey, enc); - - EVP_Cipher(&sealkey, confounder, confounder, 8); - - /* - * For RC4, Windows resets the cipherstate after encrypting - * the confounder, thus defeating the purpose of the confounder - */ - if (sig->SealAlgorithm == NL_SEAL_ALG_RC4) { - EVP_CipherFinal_ex(&sealkey, NULL, &i); - _netlogon_derive_rc4_seal_key(ctx, sig, &sealkey, enc); - } - - for (i = 0; i < iov_count; i++) { - gss_iov_buffer_t iovp = &iov[i]; - - switch (GSS_IOV_BUFFER_TYPE(iovp->type)) { - case GSS_IOV_BUFFER_TYPE_DATA: - case GSS_IOV_BUFFER_TYPE_PADDING: - EVP_Cipher(&sealkey, iovp->buffer.value, iovp->buffer.value, - iovp->buffer.length); - break; - default: - break; - } - } - - EVP_CipherFinal_ex(&sealkey, NULL, &i); - EVP_CIPHER_CTX_cleanup(&sealkey); -} - -static void -_netlogon_seq(gssnetlogon_ctx ctx, - NL_AUTH_SIGNATURE *sig, - int enc) -{ - EVP_CIPHER_CTX seqkey; - - EVP_CIPHER_CTX_init(&seqkey); - - if (sig->SignatureAlgorithm == NL_SIGN_ALG_SHA256) - _netlogon_derive_aes_seq_key(ctx, sig, &seqkey, enc); - else - _netlogon_derive_rc4_seq_key(ctx, sig, &seqkey, enc); - - EVP_Cipher(&seqkey, sig->SequenceNumber, sig->SequenceNumber, 8); - - EVP_CIPHER_CTX_cleanup(&seqkey); -} - -static void -_netlogon_digest_md5(gssnetlogon_ctx ctx, - NL_AUTH_SIGNATURE *sig, - gss_iov_buffer_desc *iov, - int iov_count, - uint8_t *md) -{ - EVP_MD_CTX *md5; - uint8_t header[NL_AUTH_SIGNATURE_HEADER_LENGTH]; - uint8_t digest[MD5_DIGEST_LENGTH]; - unsigned int md_len = MD5_DIGEST_LENGTH; - int i; - - _netlogon_encode_NL_AUTH_SIGNATURE(sig, header, sizeof(header)); - - md5 = EVP_MD_CTX_create(); - EVP_DigestInit_ex(md5, EVP_md5(), NULL); - EVP_DigestUpdate(md5, zeros, sizeof(zeros)); - EVP_DigestUpdate(md5, header, sizeof(header)); - - if (sig->SealAlgorithm != NL_SEAL_ALG_NONE) { - EVP_DigestUpdate(md5, sig->Confounder, sizeof(sig->Confounder)); - } - - for (i = 0; i < iov_count; i++) { - gss_iov_buffer_t iovp = &iov[i]; - - switch (GSS_IOV_BUFFER_TYPE(iovp->type)) { - case GSS_IOV_BUFFER_TYPE_DATA: - case GSS_IOV_BUFFER_TYPE_PADDING: - case GSS_IOV_BUFFER_TYPE_SIGN_ONLY: - EVP_DigestUpdate(md5, iovp->buffer.value, iovp->buffer.length); - break; - default: - break; - } - } - - EVP_DigestFinal_ex(md5, digest, NULL); - EVP_MD_CTX_destroy(md5); - - HMAC(EVP_md5(), ctx->SessionKey, sizeof(ctx->SessionKey), - digest, sizeof(digest), digest, &md_len); - memcpy(md, digest, 8); -} - -static void -_netlogon_digest_sha256(gssnetlogon_ctx ctx, - NL_AUTH_SIGNATURE *sig, - gss_iov_buffer_desc *iov, - int iov_count, - uint8_t *md) -{ - HMAC_CTX hmac; - uint8_t header[NL_AUTH_SIGNATURE_HEADER_LENGTH]; - uint8_t digest[SHA256_DIGEST_LENGTH]; - unsigned int md_len = SHA256_DIGEST_LENGTH; - int i; - - /* Encode first 8 bytes of signature into header */ - _netlogon_encode_NL_AUTH_SIGNATURE(sig, header, sizeof(header)); - - HMAC_CTX_init(&hmac); - HMAC_Init_ex(&hmac, ctx->SessionKey, sizeof(ctx->SessionKey), - EVP_sha256(), NULL); - HMAC_Update(&hmac, header, sizeof(header)); - - if (sig->SealAlgorithm != NL_SEAL_ALG_NONE) { - /* - * If the checksum length bug is ever fixed, then be sure to - * update this code to point to &sig->Checksum[32] as that is - * where the confounder is supposed to be. - */ - HMAC_Update(&hmac, sig->Confounder, 8); - } - - for (i = 0; i < iov_count; i++) { - gss_iov_buffer_t iovp = &iov[i]; - - switch (GSS_IOV_BUFFER_TYPE(iovp->type)) { - case GSS_IOV_BUFFER_TYPE_DATA: - case GSS_IOV_BUFFER_TYPE_PADDING: - case GSS_IOV_BUFFER_TYPE_SIGN_ONLY: - HMAC_Update(&hmac, iovp->buffer.value, iovp->buffer.length); - break; - default: - break; - } - } - - HMAC_Final(&hmac, digest, &md_len); - HMAC_CTX_cleanup(&hmac); - memcpy(md, digest, 8); -} - -static void -_netlogon_digest(gssnetlogon_ctx ctx, - NL_AUTH_SIGNATURE *sig, - gss_iov_buffer_desc *iov, - int iov_count, - uint8_t *md) -{ - if (sig->SignatureAlgorithm == NL_SIGN_ALG_SHA256) - _netlogon_digest_sha256(ctx, sig, iov, iov_count, md); - else - _netlogon_digest_md5(ctx, sig, iov, iov_count, md); -} - -OM_uint32 -_netlogon_wrap_iov(OM_uint32 * minor_status, - gss_ctx_id_t context_handle, - int conf_req_flag, - gss_qop_t qop_req, - int *conf_state, - gss_iov_buffer_desc *iov, - int iov_count) -{ - OM_uint32 ret; - gss_iov_buffer_t header; - NL_AUTH_SIGNATURE_U sigbuf = { { 0 } }; - NL_AUTH_SIGNATURE *sig = NL_AUTH_SIGNATURE_P(&sigbuf); - gssnetlogon_ctx ctx = (gssnetlogon_ctx)context_handle; - size_t size; - uint8_t *seqdata; - - if (ctx->State != NL_AUTH_ESTABLISHED) { - *minor_status = EINVAL; - return GSS_S_FAILURE; - } - - header = _gss_mg_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); - if (header == NULL) { - *minor_status = EINVAL; - return GSS_S_FAILURE; - } - - size = _netlogon_signature_length(ctx->SignatureAlgorithm, conf_req_flag); - - if (GSS_IOV_BUFFER_FLAGS(header->type) & GSS_IOV_BUFFER_FLAG_ALLOCATE) { - ret = _gss_mg_allocate_buffer(minor_status, header, size); - if (GSS_ERROR(ret)) - return ret; - } else if (header->buffer.length < size) { - *minor_status = KRB5_BAD_MSIZE; - return GSS_S_FAILURE; - } else { - header->buffer.length = size; - } - - memset(header->buffer.value, 0, header->buffer.length); - - sig->SignatureAlgorithm = ctx->SignatureAlgorithm; - sig->SealAlgorithm = conf_req_flag ? ctx->SealAlgorithm : NL_SEAL_ALG_NONE; - - if (conf_req_flag) - krb5_generate_random_block(_netlogon_confounder(sig), 8); - - sig->Pad = 0xFFFF; /* [MS-NRPC] 3.3.4.2.1.3 */ - sig->Flags = 0; /* [MS-NRPC] 3.3.4.2.1.4 */ - HEIMDAL_MUTEX_lock(&ctx->Mutex); - _netlogon_encode_sequence_number(ctx->SequenceNumber, sig->SequenceNumber, - ctx->LocallyInitiated); - ctx->SequenceNumber++; - HEIMDAL_MUTEX_unlock(&ctx->Mutex); - - /* [MS-NRPC] 3.3.4.2.1.7: sign header, optional confounder and data */ - _netlogon_digest(ctx, sig, iov, iov_count, sig->Checksum); - - /* [MS-NRPC] 3.3.4.2.1.8: optionally encrypt confounder and data */ - if (conf_req_flag) - _netlogon_seal(ctx, sig, iov, iov_count, 1); - - /* [MS-NRPC] 3.3.4.2.1.9: encrypt sequence number */ - _netlogon_seq(ctx, sig, 1); - - _netlogon_encode_NL_AUTH_SIGNATURE(sig, header->buffer.value, - header->buffer.length); - - if (conf_state != NULL) - *conf_state = conf_req_flag; - - *minor_status = 0; - return GSS_S_COMPLETE; -} - -OM_uint32 -_netlogon_unwrap_iov(OM_uint32 *minor_status, - gss_ctx_id_t context_handle, - int *conf_state, - gss_qop_t *qop_state, - gss_iov_buffer_desc *iov, - int iov_count) -{ - OM_uint32 ret; - gss_iov_buffer_t header; - NL_AUTH_SIGNATURE_U sigbuf; - NL_AUTH_SIGNATURE *sig = NL_AUTH_SIGNATURE_P(&sigbuf); - gssnetlogon_ctx ctx = (gssnetlogon_ctx)context_handle; - uint8_t checksum[SHA256_DIGEST_LENGTH]; - uint64_t SequenceNumber; - - if (ctx->State != NL_AUTH_ESTABLISHED) { - *minor_status = EINVAL; - return GSS_S_FAILURE; - } - - header = _gss_mg_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); - if (header == NULL) { - *minor_status = EINVAL; - return GSS_S_FAILURE; - } - - ret = _netlogon_decode_NL_AUTH_SIGNATURE(header->buffer.value, - header->buffer.length, - sig); - if (ret != 0) { - *minor_status = ret; - return GSS_S_DEFECTIVE_TOKEN; - } - - /* [MS-NRPC] 3.3.4.2.2.1: verify signature algorithm selection */ - if (sig->SignatureAlgorithm != ctx->SignatureAlgorithm) - return GSS_S_BAD_SIG; - - /* [MS-NRPC] 3.3.4.2.2.2: verify encryption algorithm selection */ - if (sig->SealAlgorithm != NL_SEAL_ALG_NONE && - sig->SealAlgorithm != ctx->SealAlgorithm) - return GSS_S_DEFECTIVE_TOKEN; - - /* [MS-NRPC] 3.3.4.2.2.3: verify Pad bytes */ - if (sig->Pad != 0xFFFF) - return GSS_S_DEFECTIVE_TOKEN; - - /* [MS-NRPC] 3.3.4.2.2.5: decrypt sequence number */ - _netlogon_seq(ctx, sig, 0); - - /* [MS-NRPC] 3.3.4.2.2.6: decode sequence number */ - if (_netlogon_decode_sequence_number(sig->SequenceNumber, &SequenceNumber, - !ctx->LocallyInitiated) != 0) - return GSS_S_UNSEQ_TOKEN; - - /* [MS-NRPC] 3.3.4.2.2.9: decrypt confounder and data */ - if (sig->SealAlgorithm != NL_SEAL_ALG_NONE) - _netlogon_seal(ctx, sig, iov, iov_count, 0); - - /* [MS-NRPC] 3.3.4.2.2.10: verify signature */ - _netlogon_digest(ctx, sig, iov, iov_count, checksum); - if (ct_memcmp(sig->Checksum, checksum, _netlogon_checksum_length(sig)) != 0) - return GSS_S_BAD_SIG; - - HEIMDAL_MUTEX_lock(&ctx->Mutex); - if (SequenceNumber != ctx->SequenceNumber) { - /* [MS-NRPC] 3.3.4.2.2.7: check sequence number */ - ret = GSS_S_UNSEQ_TOKEN; - } else { - /* [MS-NRPC] 3.3.4.2.2.8: increment sequence number */ - ctx->SequenceNumber++; - ret = GSS_S_COMPLETE; - } - HEIMDAL_MUTEX_unlock(&ctx->Mutex); - - if (conf_state != NULL) - *conf_state = (sig->SealAlgorithm != NL_SEAL_ALG_NONE); - if (qop_state != NULL) - *qop_state = GSS_C_QOP_DEFAULT; - - *minor_status = 0; - return ret; -} - -OM_uint32 -_netlogon_wrap_iov_length(OM_uint32 * minor_status, - gss_ctx_id_t context_handle, - int conf_req_flag, - gss_qop_t qop_req, - int *conf_state, - gss_iov_buffer_desc *iov, - int iov_count) -{ - OM_uint32 ret; - gss_iov_buffer_t iovp; - gssnetlogon_ctx ctx = (gssnetlogon_ctx)context_handle; - size_t len; - - iovp = _gss_mg_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); - if (iovp == NULL) { - *minor_status = EINVAL; - return GSS_S_FAILURE; - } - - len = NL_AUTH_SIGNATURE_COMMON_LENGTH; - if (ctx->SignatureAlgorithm == NL_SIGN_ALG_SHA256) - len += 32; /* SHA2 checksum size */ - else - len += 8; /* HMAC checksum size */ - if (conf_req_flag) - len += 8; /* counfounder */ - - iovp->buffer.length = len; - - iovp = _gss_mg_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING); - if (iovp != NULL) - iovp->buffer.length = 0; - - iovp = _gss_mg_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); - if (iovp != NULL) - iovp->buffer.length = 0; - - if (conf_state != NULL) - *conf_state = conf_req_flag; - - *minor_status = 0; - return GSS_S_COMPLETE; -} - -OM_uint32 _netlogon_get_mic - (OM_uint32 * minor_status, - gss_const_ctx_id_t context_handle, - gss_qop_t qop_req, - const gss_buffer_t message_buffer, - gss_buffer_t message_token - ) -{ - gss_iov_buffer_desc iov[2]; - OM_uint32 ret; - - iov[0].type = GSS_IOV_BUFFER_TYPE_DATA; - iov[0].buffer = *message_buffer; - iov[1].type = GSS_IOV_BUFFER_TYPE_HEADER | GSS_IOV_BUFFER_FLAG_ALLOCATE; - iov[1].buffer.length = 0; - iov[1].buffer.value = NULL; - - ret = _netlogon_wrap_iov(minor_status, context_handle, 0, - qop_req, NULL, iov, 2); - if (ret == GSS_S_COMPLETE) - *message_token = iov[1].buffer; - - return ret; -} - -OM_uint32 -_netlogon_verify_mic - (OM_uint32 * minor_status, - gss_const_ctx_id_t context_handle, - const gss_buffer_t message_buffer, - const gss_buffer_t token_buffer, - gss_qop_t * qop_state - ) -{ - gss_iov_buffer_desc iov[2]; - - iov[0].type = GSS_IOV_BUFFER_TYPE_DATA; - iov[0].buffer = *message_buffer; - iov[1].type = GSS_IOV_BUFFER_TYPE_HEADER; - iov[1].buffer = *token_buffer; - - return _netlogon_unwrap_iov(minor_status, context_handle, - NULL, qop_state, iov, 2); -} - -OM_uint32 -_netlogon_wrap_size_limit ( - OM_uint32 * minor_status, - gss_const_ctx_id_t context_handle, - int conf_req_flag, - gss_qop_t qop_req, - OM_uint32 req_output_size, - OM_uint32 *max_input_size - ) -{ - gss_iov_buffer_desc iov[1]; - OM_uint32 ret; - - iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER; - iov[0].buffer.length = 0; - - ret = _netlogon_wrap_iov_length(minor_status, context_handle, - conf_req_flag, qop_req, NULL, - iov, sizeof(iov)/sizeof(iov[0])); - if (GSS_ERROR(ret)) - return ret; - - if (req_output_size < iov[0].buffer.length) - *max_input_size = 0; - else - *max_input_size = req_output_size - iov[0].buffer.length; - - return GSS_S_COMPLETE; -} - diff --git a/lib/gssapi/netlogon/delete_sec_context.c b/lib/gssapi/netlogon/delete_sec_context.c deleted file mode 100644 index 8710416a6..000000000 --- a/lib/gssapi/netlogon/delete_sec_context.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2010 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Portions Copyright (c) 2010 Apple Inc. 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 "netlogon.h" - -OM_uint32 -_netlogon_delete_sec_context(OM_uint32 * minor_status, - gss_ctx_id_t * context_handle, - gss_buffer_t output_token) -{ - if (context_handle != NULL && *context_handle != GSS_C_NO_CONTEXT) { - gssnetlogon_ctx ctx = (gssnetlogon_ctx)*context_handle; - - *context_handle = GSS_C_NO_CONTEXT; - - _netlogon_release_name(minor_status, (gss_name_t *)&ctx->SourceName); - _netlogon_release_name(minor_status, (gss_name_t *)&ctx->TargetName); - HEIMDAL_MUTEX_destroy(&ctx->Mutex); - memset(ctx, 0, sizeof(*ctx)); - free(ctx); - } - - if (output_token != GSS_C_NO_BUFFER) { - output_token->length = 0; - output_token->value = NULL; - } - - *minor_status = 0; - return GSS_S_COMPLETE; -} diff --git a/lib/gssapi/netlogon/display_name.c b/lib/gssapi/netlogon/display_name.c deleted file mode 100644 index 7b0e223e5..000000000 --- a/lib/gssapi/netlogon/display_name.c +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2010 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Portions Copyright (c) 2010 Apple Inc. 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 "netlogon.h" - -OM_uint32 _netlogon_display_name - (OM_uint32 * minor_status, - gss_const_name_t input_name, - gss_buffer_t output_name_buffer, - gss_OID * output_name_type - ) -{ - const gssnetlogon_name name = (const gssnetlogon_name)input_name; - gss_buffer_t namebuf; - - if (output_name_type != NULL) - *output_name_type = GSS_C_NO_OID; - - if (output_name_buffer != NULL) { - namebuf = name->DnsName.length ? &name->DnsName : &name->NetbiosName; - - output_name_buffer->value = malloc(namebuf->length + 1); - if (output_name_buffer->value == NULL) { - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - memcpy(output_name_buffer->value, namebuf->value, namebuf->length); - ((char *)output_name_buffer->value)[namebuf->length] = '\0'; - output_name_buffer->length = namebuf->length; - } - - *minor_status = 0; - return GSS_S_COMPLETE; -} - diff --git a/lib/gssapi/netlogon/display_status.c b/lib/gssapi/netlogon/display_status.c deleted file mode 100644 index 68946e537..000000000 --- a/lib/gssapi/netlogon/display_status.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2009 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Portions Copyright (c) 2009 Apple Inc. 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 "netlogon.h" - -OM_uint32 _netlogon_display_status - (OM_uint32 *minor_status, - OM_uint32 status_value, - int status_type, - const gss_OID mech_type, - OM_uint32 *message_context, - gss_buffer_t status_string) -{ - if (minor_status) - *minor_status = 0; - if (status_string) { - status_string->length = 0; - status_string->value = NULL; - } - if (message_context) - *message_context = 0; - return GSS_S_COMPLETE; -} diff --git a/lib/gssapi/netlogon/duplicate_cred.c b/lib/gssapi/netlogon/duplicate_cred.c deleted file mode 100644 index 0271fb2b4..000000000 --- a/lib/gssapi/netlogon/duplicate_cred.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2010-2018 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Portions Copyright (c) 2010 Apple Inc. 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 "netlogon.h" - -OM_uint32 -_netlogon_duplicate_cred(OM_uint32 *minor_status, - gss_const_cred_id_t input_cred_handle, - gss_cred_id_t *output_cred_handle) -{ - gssnetlogon_const_cred src = (gssnetlogon_const_cred)input_cred_handle; - gssnetlogon_cred dst; - - dst = calloc(1, sizeof(*dst)); - if (dst == NULL) { - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - - *dst = *src; - return _netlogon_duplicate_name(minor_status, (gss_name_t)&src->Name, &dst->Name) -} diff --git a/lib/gssapi/netlogon/duplicate_name.c b/lib/gssapi/netlogon/duplicate_name.c deleted file mode 100644 index 1365e7667..000000000 --- a/lib/gssapi/netlogon/duplicate_name.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2010 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Portions Copyright (c) 2010 Apple Inc. 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 "netlogon.h" - -OM_uint32 _netlogon_duplicate_name ( - OM_uint32 * minor_status, - gss_const_name_t src_name, - gss_name_t * dest_name - ) -{ - const gssnetlogon_name src = (const gssnetlogon_name)src_name; - gssnetlogon_name dst = NULL; - - dst = calloc(1, sizeof(*dst)); - if (dst == NULL) - goto fail; - - dst->NetbiosName.value = malloc(src->NetbiosName.length + 1); - if (dst->NetbiosName.value == NULL) - goto fail; - memcpy(dst->NetbiosName.value, src->NetbiosName.value, - src->NetbiosName.length); - dst->NetbiosName.length = src->NetbiosName.length; - ((char *)dst->NetbiosName.value)[dst->NetbiosName.length] = '\0'; - - if (src->DnsName.length != 0) { - dst->DnsName.value = malloc(src->DnsName.length + 1); - if (dst->DnsName.value == NULL) - goto fail; - memcpy(dst->DnsName.value, src->DnsName.value, src->DnsName.length); - dst->DnsName.length = src->DnsName.length; - ((char *)dst->DnsName.value)[dst->DnsName.length] = '\0'; - } - - *minor_status = 0; - *dest_name = (gss_name_t)dst; - return GSS_S_COMPLETE; - -fail: - _netlogon_release_name(minor_status, (gss_name_t *)&dst); - *minor_status = ENOMEM; - return GSS_S_FAILURE; -} - diff --git a/lib/gssapi/netlogon/export_name.c b/lib/gssapi/netlogon/export_name.c deleted file mode 100644 index 9984f8bfe..000000000 --- a/lib/gssapi/netlogon/export_name.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2009 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Portions Copyright (c) 2009 Apple Inc. 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 "netlogon.h" - -OM_uint32 _netlogon_export_name - (OM_uint32 * minor_status, - gss_const_name_t input_name, - gss_buffer_t exported_name - ) -{ - return GSS_S_UNAVAILABLE; -} diff --git a/lib/gssapi/netlogon/export_sec_context.c b/lib/gssapi/netlogon/export_sec_context.c deleted file mode 100644 index 7e410aaaa..000000000 --- a/lib/gssapi/netlogon/export_sec_context.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2010 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Portions Copyright (c) 2010 Apple Inc. 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 "netlogon.h" - -OM_uint32 -_netlogon_export_sec_context ( - OM_uint32 * minor_status, - gss_ctx_id_t * context_handle, - gss_buffer_t interprocess_token - ) -{ - if (interprocess_token != GSS_C_NO_BUFFER) { - interprocess_token->length = 0; - interprocess_token->value = NULL; - } - return GSS_S_UNAVAILABLE; -} diff --git a/lib/gssapi/netlogon/external.c b/lib/gssapi/netlogon/external.c deleted file mode 100644 index 14f471e8d..000000000 --- a/lib/gssapi/netlogon/external.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2010-2018 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Portions Copyright (c) 2010 Apple Inc. 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 "netlogon.h" - -static gssapi_mech_interface_desc netlogon_mech = { - GMI_VERSION, - "netlogon", - {6, rk_UNCONST("\x2a\x85\x70\x2b\x0e\x02") }, - 0, - _netlogon_acquire_cred, - _netlogon_release_cred, - _netlogon_init_sec_context, - _netlogon_accept_sec_context, - _netlogon_process_context_token, - _netlogon_delete_sec_context, - _netlogon_context_time, - _netlogon_get_mic, - _netlogon_verify_mic, - NULL, - NULL, - _netlogon_display_status, - NULL, - _netlogon_compare_name, - _netlogon_display_name, - _netlogon_import_name, - _netlogon_export_name, - _netlogon_release_name, - _netlogon_inquire_cred, - _netlogon_inquire_context, - _netlogon_wrap_size_limit, - _netlogon_add_cred, - _netlogon_inquire_cred_by_mech, - _netlogon_export_sec_context, - _netlogon_import_sec_context, - _netlogon_inquire_names_for_mech, - _netlogon_inquire_mechs_for_name, - _netlogon_canonicalize_name, - _netlogon_duplicate_name, - NULL, - NULL, - NULL, - _netlogon_set_cred_option, - NULL, - _netlogon_wrap_iov, - _netlogon_unwrap_iov, - _netlogon_wrap_iov_length, - NULL, /* gm_store_cred */ - NULL, /* gm_export_cred */ - NULL, /* gm_import_cred */ - NULL, /* gm_acquire_cred_from */ - NULL, /* gm_acquire_cred_impersonate_name */ - NULL, /* gm_iter_creds */ - NULL, /* gm_destroy_cred */ - NULL, /* gm_cred_hold */ - NULL, /* gm_cred_unhold */ - NULL, /* gm_cred_label_get */ - NULL, /* gm_cred_label_set */ - NULL, /* gm_mo */ - 0, /* gm_mo_num */ - NULL, /* gm_localname */ - NULL, /* gm_authorize_localname */ - NULL, /* gm_display_name_ext */ - NULL, /* gm_inquire_name */ - NULL, /* gm_get_name_attribute */ - NULL, /* gm_set_name_attribute */ - NULL, /* gm_delete_name_attribute */ - NULL, /* gm_export_name_composite */ - NULL, /* gm_duplicate_cred */ - NULL, /* gm_add_cred_from */ - NULL, /* gm_store_cred_into */ - NULL /* gm_compat */ -}; - -gssapi_mech_interface -__gss_netlogon_initialize(void) -{ - return &netlogon_mech; -} diff --git a/lib/gssapi/netlogon/import_name.c b/lib/gssapi/netlogon/import_name.c deleted file mode 100644 index 8d46486f9..000000000 --- a/lib/gssapi/netlogon/import_name.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2010 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Portions Copyright (c) 2010 Apple Inc. 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 "netlogon.h" -#include - -OM_uint32 _netlogon_import_name - (OM_uint32 * minor_status, - const gss_buffer_t input_name_buffer, - const gss_OID input_name_type, - gss_name_t * output_name - ) -{ - gssnetlogon_name name; - const char *netbiosName; - const char *dnsName = NULL; - size_t len, i; - - if (!gss_oid_equal(input_name_type, GSS_NETLOGON_NT_NETBIOS_DNS_NAME)) { - return GSS_S_BAD_NAME; - } - - /* encoding is NetBIOS name \0 DNS name \0 */ - - netbiosName = input_name_buffer->value; - len = strlen(netbiosName); - if (len < input_name_buffer->length) - dnsName = netbiosName + len + 1; - - name = (gssnetlogon_name)calloc(1, sizeof(*name)); - if (name == NULL) - goto cleanup; - - name->NetbiosName.value = malloc(len + 1); - if (name->NetbiosName.value == NULL) - goto cleanup; - memcpy(name->NetbiosName.value, netbiosName, len + 1); - name->NetbiosName.length = len; - - /* normalise name to uppercase XXX UTF-8 OK? */ - for (i = 0; i < len; i++) { - ((unsigned char *)name->NetbiosName.value)[i] = - toupper(((unsigned char *)name->NetbiosName.value)[i]); - } - - if (dnsName != NULL && dnsName[0] != '\0') { - name->DnsName.value = strdup(dnsName); - if (name->DnsName.value == NULL) - goto cleanup; - name->DnsName.length = strlen(dnsName); - } - - *output_name = (gss_name_t)name; - *minor_status = 0; - return GSS_S_COMPLETE; - -cleanup: - _netlogon_release_name(minor_status, (gss_name_t *)&name); - *minor_status = ENOMEM; - return GSS_S_FAILURE; -} - diff --git a/lib/gssapi/netlogon/import_sec_context.c b/lib/gssapi/netlogon/import_sec_context.c deleted file mode 100644 index 0415b3939..000000000 --- a/lib/gssapi/netlogon/import_sec_context.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2010 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Portions Copyright (c) 2010 Apple Inc. 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 "netlogon.h" - -OM_uint32 -_netlogon_import_sec_context ( - OM_uint32 * minor_status, - const gss_buffer_t interprocess_token, - gss_ctx_id_t * context_handle - ) -{ - *minor_status = 0; - if (context_handle != NULL) - *context_handle = GSS_C_NO_CONTEXT; - - return GSS_S_UNAVAILABLE; -} diff --git a/lib/gssapi/netlogon/indicate_mechs.c b/lib/gssapi/netlogon/indicate_mechs.c deleted file mode 100644 index 9192e4272..000000000 --- a/lib/gssapi/netlogon/indicate_mechs.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2010 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Portions Copyright (c) 2010 Apple Inc. 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 "netlogon.h" - -OM_uint32 _netlogon_indicate_mechs -(OM_uint32 * minor_status, - gss_OID_set * mech_set - ) -{ - *minor_status = 0; - if (mech_set != NULL) - *mech_set = GSS_C_NO_OID_SET; - - return GSS_S_COMPLETE; -} diff --git a/lib/gssapi/netlogon/init_sec_context.c b/lib/gssapi/netlogon/init_sec_context.c deleted file mode 100644 index 906f45744..000000000 --- a/lib/gssapi/netlogon/init_sec_context.c +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright (c) 2010 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Portions Copyright (c) 2010 Apple Inc. 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 "netlogon.h" -#include - -static OM_uint32 -_netlogon_encode_dns_string(OM_uint32 *minor_status, - const gss_buffer_t str, - gss_buffer_t buffer) -{ - int ret; - - memset(buffer->value, 0, buffer->length); - - ret = ns_name_compress((const char *)str->value, - (uint8_t *)buffer->value, buffer->length, - NULL, NULL); - if (ret < 0) { - *minor_status = errno; - return GSS_S_FAILURE; - } - - buffer->length = ret; - - *minor_status = 0; - return GSS_S_COMPLETE; -} - -static OM_uint32 -_netlogon_make_initial_auth_message(OM_uint32 *minor_status, - gssnetlogon_ctx ctx, - gss_buffer_t output_token) -{ - uint32_t flags = 0; -#define MAX_NL_NAMES 5 - gss_buffer_desc names[MAX_NL_NAMES]; - uint8_t comp_names[3][MAXHOSTNAMELEN * 2]; - size_t n = 0, i = 0, len; - OM_uint32 ret; - uint8_t *p; - - if (ctx->TargetName->NetbiosName.length) { - flags |= NL_FLAG_NETBIOS_DOMAIN_NAME; - names[n] = ctx->TargetName->NetbiosName; /* OEM encoding */ - names[n].length++; - n++; - } - if (ctx->SourceName->NetbiosName.length) { - flags |= NL_FLAG_NETBIOS_COMPUTER_NAME; - names[n] = ctx->SourceName->NetbiosName; /* OEM encoding */ - names[n].length++; - n++; - } - if (ctx->TargetName->DnsName.length) { - flags |= NL_FLAG_DNS_DOMAIN_NAME; - names[n].value = comp_names[i++]; - names[n].length = MAXHOSTNAMELEN * 2; - ret = _netlogon_encode_dns_string(minor_status, - &ctx->TargetName->DnsName, - &names[n]); - if (GSS_ERROR(ret)) - return ret; - n++; - } - if (ctx->SourceName->DnsName.length) { - flags |= NL_FLAG_DNS_HOST_NAME; - names[n].value = comp_names[i++]; - names[n].length = MAXHOSTNAMELEN * 2; - ret = _netlogon_encode_dns_string(minor_status, - &ctx->SourceName->DnsName, - &names[n]); - if (GSS_ERROR(ret)) - return ret; - n++; - } - if (ctx->SourceName->NetbiosName.length) { - flags |= NL_FLAG_UTF8_COMPUTER_NAME; - names[n].value = comp_names[i++]; - names[n].length = MAXHOSTNAMELEN * 2; - ret = _netlogon_encode_dns_string(minor_status, - &ctx->SourceName->NetbiosName, - &names[n]); - if (GSS_ERROR(ret)) - return ret; - n++; - } - - for (i = 0, len = NL_AUTH_MESSAGE_LENGTH; i < n; i++) { - len += names[i].length; - } - - output_token->value = malloc(len); - if (output_token->value == NULL) { - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - - p = (uint8_t *)output_token->value; - _gss_mg_encode_le_uint32(NL_NEGOTIATE_REQUEST_MESSAGE, p); - _gss_mg_encode_le_uint32(flags, p + 4); - p += 8; - - for (i = 0; i < n; i++) { - assert(names[i].length != 0); - assert(((char *)names[i].value)[names[i].length - 1] == '\0'); - memcpy(p, names[i].value, names[i].length); - p += names[i].length; - } - - output_token->length = len; - assert(p == (uint8_t *)output_token->value + len); - - *minor_status = 0; - return GSS_S_CONTINUE_NEEDED; -} - -static OM_uint32 -_netlogon_read_initial_auth_message(OM_uint32 *minor_status, - gssnetlogon_ctx ctx, - const gss_buffer_t input_token) -{ - NL_AUTH_MESSAGE msg; - const uint8_t *p = (const uint8_t *)input_token->value; - - if (ctx->State != NL_AUTH_NEGOTIATE) { - *minor_status = EINVAL; - return GSS_S_FAILURE; - } - - if (input_token->length < NL_AUTH_MESSAGE_LENGTH) - return GSS_S_DEFECTIVE_TOKEN; - - _gss_mg_decode_le_uint32(&p[0], &msg.MessageType); - _gss_mg_decode_le_uint32(&p[4], &msg.Flags); - - if (msg.MessageType != NL_NEGOTIATE_RESPONSE_MESSAGE || - msg.Flags != 0) - return GSS_S_DEFECTIVE_TOKEN; - - ctx->State = NL_AUTH_ESTABLISHED; - - *minor_status = 0; - return GSS_S_COMPLETE; -} - -static OM_uint32 -_netlogon_alloc_context(OM_uint32 *minor_status, - gssnetlogon_ctx *pContext) -{ - gssnetlogon_ctx ctx; - - ctx = (gssnetlogon_ctx)calloc(1, sizeof(*ctx)); - if (ctx == NULL) { - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - - ctx->State = NL_AUTH_NEGOTIATE; - ctx->LocallyInitiated = 1; - ctx->MessageBlockSize = 1; - - HEIMDAL_MUTEX_init(&ctx->Mutex); - - *pContext = ctx; - - return GSS_S_COMPLETE; -} - -OM_uint32 -_netlogon_init_sec_context(OM_uint32 * minor_status, - gss_const_cred_id_t initiator_cred_handle, - gss_ctx_id_t * context_handle, - gss_const_name_t target_name, - const gss_OID mech_type, - OM_uint32 req_flags, - OM_uint32 time_req, - const gss_channel_bindings_t input_chan_bindings, - const gss_buffer_t input_token, - gss_OID * actual_mech_type, - gss_buffer_t output_token, - OM_uint32 * ret_flags, - OM_uint32 * time_rec) -{ - const gssnetlogon_cred cred = (const gssnetlogon_cred)initiator_cred_handle; - gssnetlogon_ctx ctx = (gssnetlogon_ctx)*context_handle; - const gssnetlogon_name target = (const gssnetlogon_name)target_name; - OM_uint32 ret; - - *minor_status = 0; - - output_token->value = NULL; - output_token->length = 0; - - /* Validate arguments */ - if (cred == NULL) - return GSS_S_NO_CRED; - else if (target == NULL) - return GSS_S_BAD_NAME; - - if (ctx == NULL) { - if (input_token->length != 0) - return GSS_S_DEFECTIVE_TOKEN; - - ret = _netlogon_alloc_context(minor_status, &ctx); - if (GSS_ERROR(ret)) - goto cleanup; - - HEIMDAL_MUTEX_lock(&ctx->Mutex); - *context_handle = (gss_ctx_id_t)ctx; - - ctx->GssFlags = req_flags & (GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | - GSS_C_SEQUENCE_FLAG | GSS_C_CONF_FLAG | - GSS_C_INTEG_FLAG | GSS_C_DCE_STYLE); - ctx->SignatureAlgorithm = cred->SignatureAlgorithm; - ctx->SealAlgorithm = cred->SealAlgorithm; - - ret = _netlogon_duplicate_name(minor_status, (gss_name_t)cred->Name, - (gss_name_t *)&ctx->SourceName); - if (GSS_ERROR(ret)) - goto cleanup; - - ret = _netlogon_duplicate_name(minor_status, (gss_name_t)target, - (gss_name_t *)&ctx->TargetName); - if (GSS_ERROR(ret)) - goto cleanup; - - memcpy(ctx->SessionKey, cred->SessionKey, sizeof(cred->SessionKey)); - - ret = _netlogon_make_initial_auth_message(minor_status, ctx, - output_token); - if (GSS_ERROR(ret)) - goto cleanup; - } else { - HEIMDAL_MUTEX_lock(&ctx->Mutex); - ret = _netlogon_read_initial_auth_message(minor_status, ctx, - input_token); - } - - if (ret_flags != NULL) - *ret_flags = ctx->GssFlags; - if (time_rec != NULL) - *time_rec = GSS_C_INDEFINITE; - if (actual_mech_type != NULL) - *actual_mech_type = GSS_NETLOGON_MECHANISM; - -cleanup: - HEIMDAL_MUTEX_unlock(&ctx->Mutex); - - if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) { - OM_uint32 tmp; - _netlogon_delete_sec_context(&tmp, context_handle, NULL); - } - - return ret; -} - diff --git a/lib/gssapi/netlogon/inquire_context.c b/lib/gssapi/netlogon/inquire_context.c deleted file mode 100644 index 24995c2a5..000000000 --- a/lib/gssapi/netlogon/inquire_context.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2010 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Portions Copyright (c) 2010 Apple Inc. 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 "netlogon.h" - -OM_uint32 _netlogon_inquire_context ( - OM_uint32 * minor_status, - gss_const_ctx_id_t context_handle, - gss_name_t * src_name, - gss_name_t * targ_name, - OM_uint32 * lifetime_rec, - gss_OID * mech_type, - OM_uint32 * ctx_flags, - int * locally_initiated, - int * open_context - ) -{ - const gssnetlogon_ctx ctx = (const gssnetlogon_ctx)context_handle; - OM_uint32 ret; - - if (src_name != NULL) { - ret = _netlogon_duplicate_name(minor_status, (gss_name_t)ctx->SourceName, - (gss_name_t *)src_name); - if (GSS_ERROR(ret)) - return ret; - } - if (targ_name != NULL) { - ret = _netlogon_duplicate_name(minor_status, (gss_name_t)ctx->TargetName, - (gss_name_t *)targ_name); - if (GSS_ERROR(ret)) - return ret; - } - if (mech_type != NULL) - *mech_type = GSS_NETLOGON_MECHANISM; - if (ctx_flags != NULL) - *ctx_flags = ctx->GssFlags; - if (locally_initiated != NULL) - *locally_initiated = ctx->LocallyInitiated; - if (open_context != NULL) - *open_context = (ctx->State == NL_AUTH_ESTABLISHED); - - return GSS_S_COMPLETE; -} - diff --git a/lib/gssapi/netlogon/inquire_cred.c b/lib/gssapi/netlogon/inquire_cred.c deleted file mode 100644 index 6c7ca34b1..000000000 --- a/lib/gssapi/netlogon/inquire_cred.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2010 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Portions Copyright (c) 2010 Apple Inc. 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 "netlogon.h" - -OM_uint32 _netlogon_inquire_cred - (OM_uint32 * minor_status, - gss_const_cred_id_t cred_handle, - gss_name_t * name, - OM_uint32 * lifetime, - gss_cred_usage_t * cred_usage, - gss_OID_set * mechanisms - ) -{ - OM_uint32 ret; - const gssnetlogon_cred cred = (const gssnetlogon_cred)cred_handle; - - *minor_status = 0; - - if (cred == NULL) - return GSS_S_NO_CRED; - - if (name != NULL) { - ret = _netlogon_duplicate_name(minor_status, - (gss_const_name_t)cred->Name, name); - if (GSS_ERROR(ret)) - return ret; - } - if (lifetime != NULL) - *lifetime = GSS_C_INDEFINITE; - if (cred_usage != NULL) - *cred_usage = GSS_C_INITIATE; - if (mechanisms != NULL) - *mechanisms = GSS_C_NO_OID_SET; - return GSS_S_COMPLETE; -} diff --git a/lib/gssapi/netlogon/inquire_cred_by_mech.c b/lib/gssapi/netlogon/inquire_cred_by_mech.c deleted file mode 100644 index f36310fdc..000000000 --- a/lib/gssapi/netlogon/inquire_cred_by_mech.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2010 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Portions Copyright (c) 2010 Apple Inc. 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 "netlogon.h" - -OM_uint32 _netlogon_inquire_cred_by_mech ( - OM_uint32 * minor_status, - gss_const_cred_id_t cred_handle, - const gss_OID mech_type, - gss_name_t * name, - OM_uint32 * initiator_lifetime, - OM_uint32 * acceptor_lifetime, - gss_cred_usage_t * cred_usage - ) -{ - OM_uint32 ret; - const gssnetlogon_cred cred = (const gssnetlogon_cred)cred_handle; - - if (name != NULL) { - ret = _netlogon_duplicate_name(minor_status, - (gss_const_name_t)cred->Name, name); - if (GSS_ERROR(ret)) - return ret; - } - if (initiator_lifetime != NULL) - *initiator_lifetime = GSS_C_INDEFINITE; - if (acceptor_lifetime != NULL) - *acceptor_lifetime = GSS_C_INDEFINITE; - if (cred_usage != NULL) - *cred_usage = GSS_C_INITIATE; - *minor_status = 0; - return GSS_S_COMPLETE; -} - diff --git a/lib/gssapi/netlogon/inquire_mechs_for_name.c b/lib/gssapi/netlogon/inquire_mechs_for_name.c deleted file mode 100644 index dbf385cdd..000000000 --- a/lib/gssapi/netlogon/inquire_mechs_for_name.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2010 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Portions Copyright (c) 2010 Apple Inc. 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 "netlogon.h" - -OM_uint32 _netlogon_inquire_mechs_for_name ( - OM_uint32 * minor_status, - gss_const_name_t input_name, - gss_OID_set * mech_types - ) -{ - if (mech_types != NULL) - *mech_types = GSS_C_NO_OID_SET; - *minor_status = 0; - return GSS_S_COMPLETE; -} diff --git a/lib/gssapi/netlogon/inquire_names_for_mech.c b/lib/gssapi/netlogon/inquire_names_for_mech.c deleted file mode 100644 index 9802e5326..000000000 --- a/lib/gssapi/netlogon/inquire_names_for_mech.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2010 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Portions Copyright (c) 2010 Apple Inc. 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 "netlogon.h" - -OM_uint32 _netlogon_inquire_names_for_mech ( - OM_uint32 * minor_status, - const gss_OID mechanism, - gss_OID_set * name_types - ) -{ - OM_uint32 ret, tmp; - - ret = gss_create_empty_oid_set(minor_status, name_types); - if (ret != GSS_S_COMPLETE) - return ret; - - ret = gss_add_oid_set_member(minor_status, GSS_NETLOGON_NT_NETBIOS_DNS_NAME, name_types); - if (ret != GSS_S_COMPLETE) { - gss_release_oid_set(&tmp, name_types); - return ret; - } - - *minor_status = 0; - return GSS_S_COMPLETE; -} diff --git a/lib/gssapi/netlogon/iter_cred.c b/lib/gssapi/netlogon/iter_cred.c deleted file mode 100644 index 93a8d59ab..000000000 --- a/lib/gssapi/netlogon/iter_cred.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2009 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Portions Copyright (c) 2009 Apple Inc. 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 "netlogon.h" -#include - -void -_netlogon_iter_creds_f(OM_uint32 flags, - void *userctx , - void (*cred_iter)(void *, gss_OID, gss_cred_id_t)) -{ -} diff --git a/lib/gssapi/netlogon/netlogon.h b/lib/gssapi/netlogon/netlogon.h deleted file mode 100644 index 59a20a7ea..000000000 --- a/lib/gssapi/netlogon/netlogon.h +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (c) 2010-2018 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Portions Copyright (c) 2010 Apple Inc. 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. - */ - -#ifndef NETLOGON_NETLOGON_H -#define NETLOGON_NETLOGON_H - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include -#include - -#include "crypto-headers.h" - -/* - * - */ - -typedef struct { -#define NL_NEGOTIATE_REQUEST_MESSAGE 0x00000000 -#define NL_NEGOTIATE_RESPONSE_MESSAGE 0x00000001 - uint32_t MessageType; -#define NL_FLAG_NETBIOS_DOMAIN_NAME 0x00000001 -#define NL_FLAG_NETBIOS_COMPUTER_NAME 0x00000002 -#define NL_FLAG_DNS_DOMAIN_NAME 0x00000004 -#define NL_FLAG_DNS_HOST_NAME 0x00000008 /* not used */ -#define NL_FLAG_UTF8_COMPUTER_NAME 0x00000010 - uint32_t Flags; - char *Buffer[0]; -} NL_AUTH_MESSAGE; - -#define NL_AUTH_MESSAGE_LENGTH 8 - -/* SignatureAlgorithm */ -#define NL_SIGN_ALG_HMAC_MD5 0x0077 -#define NL_SIGN_ALG_SHA256 0x0013 - -/* SealAlgorithm */ -#define NL_SEAL_ALG_RC4 0x007A -#define NL_SEAL_ALG_AES128 0x001A -#define NL_SEAL_ALG_NONE 0xFFFF - -typedef struct { - uint16_t SignatureAlgorithm; - uint16_t SealAlgorithm; - uint16_t Pad; - uint16_t Flags; - uint8_t SequenceNumber[8]; - uint8_t Checksum[8]; - uint8_t Confounder[8]; -} NL_AUTH_SIGNATURE; - -#define NL_AUTH_SIGNATURE_HEADER_LENGTH 8 -#define NL_AUTH_SIGNATURE_COMMON_LENGTH 16 -#define NL_AUTH_SIGNATURE_LENGTH 32 - -typedef struct { - uint16_t SignatureAlgorithm; - uint16_t SealAlgorithm; - uint16_t Pad; - uint16_t Flags; - uint8_t SequenceNumber[8]; - uint8_t Checksum[32]; - uint8_t Confounder[8]; -} NL_AUTH_SHA2_SIGNATURE; - -#define NL_AUTH_SHA2_SIGNATURE_LENGTH 56 - -typedef union { - NL_AUTH_SIGNATURE Signature; - NL_AUTH_SHA2_SIGNATURE SHA2Signature; -} NL_AUTH_SIGNATURE_U; - -#define NL_AUTH_SIGNATURE_P(_u) (&(_u)->Signature) - -typedef struct gssnetlogon_name { - gss_buffer_desc NetbiosName; - gss_buffer_desc DnsName; -} *gssnetlogon_name; -typedef const struct gssnetlogon_name *gssnetlogon_const_name; - -typedef struct gssnetlogon_cred { - gssnetlogon_name *Name; - uint16_t SignatureAlgorithm; - uint16_t SealAlgorithm; - uint8_t SessionKey[16]; -} *gssnetlogon_cred; -typedef const struct gssnetlogon_cred *gssnetlogon_const_cred; - -typedef struct gssnetlogon_ctx { - HEIMDAL_MUTEX Mutex; - enum { NL_AUTH_NEGOTIATE, NL_AUTH_ESTABLISHED } State; - OM_uint32 GssFlags; - uint8_t LocallyInitiated; - uint32_t MessageBlockSize; - uint16_t SignatureAlgorithm; - uint16_t SealAlgorithm; - uint64_t SequenceNumber; - gssnetlogon_name SourceName; - gssnetlogon_name TargetName; - uint8_t SessionKey[16]; -} *gssnetlogon_ctx; - -#include - -#endif /* NETLOGON_NETLOGON_H */ diff --git a/lib/gssapi/netlogon/process_context_token.c b/lib/gssapi/netlogon/process_context_token.c deleted file mode 100644 index 0f8361337..000000000 --- a/lib/gssapi/netlogon/process_context_token.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2009 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Portions Copyright (c) 2009 Apple Inc. 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 "netlogon.h" - -OM_uint32 _netlogon_process_context_token ( - OM_uint32 *minor_status, - gss_const_ctx_id_t context_handle, - const gss_buffer_t token_buffer - ) -{ - *minor_status = 0; - return GSS_S_COMPLETE; -} diff --git a/lib/gssapi/netlogon/regen.sh b/lib/gssapi/netlogon/regen.sh deleted file mode 100644 index b034dbfe9..000000000 --- a/lib/gssapi/netlogon/regen.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -perl ../../../cf/make-proto.pl -q -P comment -p netlogon-private.h *.c diff --git a/lib/gssapi/netlogon/release_cred.c b/lib/gssapi/netlogon/release_cred.c deleted file mode 100644 index 7db71b691..000000000 --- a/lib/gssapi/netlogon/release_cred.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2010 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Portions Copyright (c) 2010 Apple Inc. 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 "netlogon.h" - -OM_uint32 _netlogon_release_cred - (OM_uint32 * minor_status, - gss_cred_id_t * cred_handle - ) -{ - gssnetlogon_cred cred = (gssnetlogon_cred)*cred_handle; - - if (cred != NULL) { - _netlogon_release_name(minor_status, (gss_name_t *)&cred->Name); - memset(cred, 0, sizeof(*cred)); - free(cred); - *cred_handle = GSS_C_NO_CREDENTIAL; - } - - return GSS_S_COMPLETE; -} - diff --git a/lib/gssapi/netlogon/release_name.c b/lib/gssapi/netlogon/release_name.c deleted file mode 100644 index 27ca018b1..000000000 --- a/lib/gssapi/netlogon/release_name.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2010 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Portions Copyright (c) 2010 Apple Inc. 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 "netlogon.h" - -OM_uint32 _netlogon_release_name - (OM_uint32 * minor_status, - gss_name_t * input_name - ) -{ - gssnetlogon_name name = (gssnetlogon_name)*input_name; - - if (name != NULL) { - gss_release_buffer(minor_status, &name->NetbiosName); - gss_release_buffer(minor_status, &name->DnsName); - free(name); - *input_name = GSS_C_NO_NAME; - } - - *minor_status = 0; - return GSS_S_COMPLETE; -} diff --git a/lib/gssapi/ntlm/accept_sec_context.c b/lib/gssapi/ntlm/accept_sec_context.c deleted file mode 100644 index 6a3e8899e..000000000 --- a/lib/gssapi/ntlm/accept_sec_context.c +++ /dev/null @@ -1,256 +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 "ntlm.h" - -/* - * - */ - -OM_uint32 -_gss_ntlm_allocate_ctx(OM_uint32 *minor_status, ntlm_ctx *ctx) -{ - OM_uint32 maj_stat; - struct ntlm_server_interface *ns_interface = NULL; - -#ifdef DIGEST - ns_interface = &ntlmsspi_kdc_digest; -#endif - if (ns_interface == NULL) - return GSS_S_FAILURE; - - *ctx = calloc(1, sizeof(**ctx)); - if (*ctx == NULL) { - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - - (*ctx)->server = ns_interface; - - maj_stat = (*(*ctx)->server->nsi_init)(minor_status, &(*ctx)->ictx); - if (maj_stat == GSS_S_COMPLETE) - return GSS_S_COMPLETE; - - if (*ctx) - free(*ctx); - (*ctx) = NULL; - - return maj_stat; -} - -/* - * - */ - -OM_uint32 GSSAPI_CALLCONV -_gss_ntlm_accept_sec_context -(OM_uint32 * minor_status, - gss_ctx_id_t * context_handle, - gss_const_cred_id_t acceptor_cred_handle, - const gss_buffer_t input_token_buffer, - const gss_channel_bindings_t input_chan_bindings, - gss_name_t * src_name, - gss_OID * mech_type, - gss_buffer_t output_token, - OM_uint32 * ret_flags, - OM_uint32 * time_rec, - gss_cred_id_t * delegated_cred_handle - ) -{ - krb5_error_code ret; - struct ntlm_buf data; - OM_uint32 junk; - ntlm_ctx ctx; - - output_token->value = NULL; - output_token->length = 0; - - *minor_status = 0; - - if (context_handle == NULL) - return GSS_S_FAILURE; - - if (input_token_buffer == GSS_C_NO_BUFFER) - return GSS_S_FAILURE; - - if (src_name) - *src_name = GSS_C_NO_NAME; - if (mech_type) - *mech_type = GSS_C_NO_OID; - if (ret_flags) - *ret_flags = 0; - if (time_rec) - *time_rec = 0; - if (delegated_cred_handle) - *delegated_cred_handle = GSS_C_NO_CREDENTIAL; - - if (*context_handle == GSS_C_NO_CONTEXT) { - struct ntlm_type1 type1; - OM_uint32 major_status; - OM_uint32 retflags; - struct ntlm_buf out; - - major_status = _gss_ntlm_allocate_ctx(minor_status, &ctx); - if (major_status) - return major_status; - *context_handle = (gss_ctx_id_t)ctx; - - /* check if the mechs is allowed by remote service */ - major_status = (*ctx->server->nsi_probe)(minor_status, ctx->ictx, NULL); - if (major_status) { - _gss_ntlm_delete_sec_context(minor_status, context_handle, NULL); - return major_status; - } - - data.data = input_token_buffer->value; - data.length = input_token_buffer->length; - - ret = heim_ntlm_decode_type1(&data, &type1); - if (ret) { - _gss_ntlm_delete_sec_context(minor_status, context_handle, NULL); - *minor_status = ret; - return GSS_S_DEFECTIVE_TOKEN; - } - - if ((type1.flags & NTLM_NEG_UNICODE) == 0) { - heim_ntlm_free_type1(&type1); - _gss_ntlm_delete_sec_context(minor_status, context_handle, NULL); - *minor_status = EINVAL; - return GSS_S_FAILURE; - } - - if (type1.flags & NTLM_NEG_SIGN) - ctx->gssflags |= GSS_C_CONF_FLAG; - if (type1.flags & NTLM_NEG_SIGN) - ctx->gssflags |= GSS_C_INTEG_FLAG; - - major_status = (*ctx->server->nsi_type2)(minor_status, - ctx->ictx, - type1.flags, - type1.hostname, - type1.domain, - &retflags, - &out); - heim_ntlm_free_type1(&type1); - if (major_status != GSS_S_COMPLETE) { - OM_uint32 gunk; - _gss_ntlm_delete_sec_context(&gunk, context_handle, NULL); - return major_status; - } - - output_token->value = malloc(out.length); - if (output_token->value == NULL && out.length != 0) { - OM_uint32 gunk; - heim_ntlm_free_buf(&out); - _gss_ntlm_delete_sec_context(&gunk, context_handle, NULL); - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - memcpy(output_token->value, out.data, out.length); - output_token->length = out.length; - heim_ntlm_free_buf(&out); - - ctx->flags = retflags; - - return GSS_S_CONTINUE_NEEDED; - } else { - OM_uint32 maj_stat; - struct ntlm_type3 type3; - struct ntlm_buf session; - - ctx = (ntlm_ctx)*context_handle; - - data.data = input_token_buffer->value; - data.length = input_token_buffer->length; - - ret = heim_ntlm_decode_type3(&data, 1, &type3); - if (ret) { - _gss_ntlm_delete_sec_context(minor_status, context_handle, NULL); - *minor_status = ret; - return GSS_S_DEFECTIVE_TOKEN; - } - - maj_stat = (*ctx->server->nsi_type3)(minor_status, - ctx->ictx, - &type3, - &session); - if (maj_stat) { - heim_ntlm_free_type3(&type3); - _gss_ntlm_delete_sec_context(minor_status, context_handle, NULL); - return maj_stat; - } - - if (src_name) { - ntlm_name n = calloc(1, sizeof(*n)); - if (n) { - n->user = strdup(type3.username); - n->domain = strdup(type3.targetname); - } - if (n == NULL || n->user == NULL || n->domain == NULL) { - gss_name_t tempn = (gss_name_t)n; - _gss_ntlm_release_name(&junk, &tempn); - heim_ntlm_free_type3(&type3); - _gss_ntlm_delete_sec_context(minor_status, - context_handle, NULL); - return maj_stat; - } - *src_name = (gss_name_t)n; - } - - heim_ntlm_free_type3(&type3); - - ret = krb5_data_copy(&ctx->sessionkey, - session.data, session.length); - if (ret) { - if (src_name) - _gss_ntlm_release_name(&junk, src_name); - _gss_ntlm_delete_sec_context(minor_status, context_handle, NULL); - *minor_status = ret; - return GSS_S_FAILURE; - } - - _gss_ntlm_set_keys(ctx); - - if (mech_type) - *mech_type = GSS_NTLM_MECHANISM; - if (time_rec) - *time_rec = GSS_C_INDEFINITE; - - ctx->status |= STATUS_OPEN; - - if (ret_flags) - *ret_flags = ctx->gssflags; - - return GSS_S_COMPLETE; - } -} diff --git a/lib/gssapi/ntlm/acquire_cred.c b/lib/gssapi/ntlm/acquire_cred.c deleted file mode 100644 index a6b151f7a..000000000 --- a/lib/gssapi/ntlm/acquire_cred.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "ntlm.h" - -OM_uint32 GSSAPI_CALLCONV -_gss_ntlm_acquire_cred_from(OM_uint32 *min_stat, - gss_const_name_t desired_name, - OM_uint32 time_req, - const gss_OID_set desired_mechs, - gss_cred_usage_t cred_usage, - gss_const_key_value_set_t cred_store, - gss_cred_id_t *output_cred_handle, - gss_OID_set *actual_mechs, - OM_uint32 *time_rec) -{ - ntlm_name name = (ntlm_name) desired_name; - OM_uint32 maj_stat; - ntlm_ctx ctx; - - *min_stat = 0; - *output_cred_handle = GSS_C_NO_CREDENTIAL; - if (actual_mechs) - *actual_mechs = GSS_C_NO_OID_SET; - if (time_rec) - *time_rec = GSS_C_INDEFINITE; - - if (cred_usage == GSS_C_BOTH || cred_usage == GSS_C_ACCEPT) { - int ret; - - maj_stat = _gss_ntlm_allocate_ctx(min_stat, &ctx); - if (maj_stat != GSS_S_COMPLETE) - return maj_stat; - - ret = (*ctx->server->nsi_probe)(min_stat, ctx->ictx, NULL); - { - gss_ctx_id_t context = (gss_ctx_id_t)ctx; - OM_uint32 junk; - _gss_ntlm_delete_sec_context(&junk, &context, NULL); - } - if (ret) { - *min_stat = ret; - return GSS_S_NO_CRED; - } - } - if (cred_usage == GSS_C_BOTH || cred_usage == GSS_C_INITIATE) { - ntlm_cred cred; - - *min_stat = _gss_ntlm_get_user_cred(name, &cred); - if (*min_stat) - return GSS_S_NO_CRED; - cred->usage = cred_usage; - - *output_cred_handle = (gss_cred_id_t)cred; - } - - return (GSS_S_COMPLETE); -} diff --git a/lib/gssapi/ntlm/add_cred.c b/lib/gssapi/ntlm/add_cred.c deleted file mode 100644 index 151723262..000000000 --- a/lib/gssapi/ntlm/add_cred.c +++ /dev/null @@ -1,60 +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 "ntlm.h" - -OM_uint32 GSSAPI_CALLCONV _gss_ntlm_add_cred ( - OM_uint32 *minor_status, - gss_const_cred_id_t input_cred_handle, - gss_const_name_t desired_name, - const gss_OID desired_mech, - gss_cred_usage_t cred_usage, - OM_uint32 initiator_time_req, - OM_uint32 acceptor_time_req, - gss_cred_id_t *output_cred_handle, - gss_OID_set *actual_mechs, - OM_uint32 *initiator_time_rec, - OM_uint32 *acceptor_time_rec) -{ - if (minor_status) - *minor_status = 0; - if (output_cred_handle) - *output_cred_handle = GSS_C_NO_CREDENTIAL; - if (actual_mechs) - *actual_mechs = GSS_C_NO_OID_SET; - if (initiator_time_rec) - *initiator_time_rec = 0; - if (acceptor_time_rec) - *acceptor_time_rec = 0; - return GSS_S_COMPLETE; -} diff --git a/lib/gssapi/ntlm/canonicalize_name.c b/lib/gssapi/ntlm/canonicalize_name.c deleted file mode 100644 index 3409b3b75..000000000 --- a/lib/gssapi/ntlm/canonicalize_name.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 1997 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "ntlm.h" - -OM_uint32 GSSAPI_CALLCONV -_gss_ntlm_canonicalize_name ( - OM_uint32 * minor_status, - gss_const_name_t input_name, - const gss_OID mech_type, - gss_name_t * output_name - ) -{ - return gss_duplicate_name (minor_status, input_name, output_name); -} diff --git a/lib/gssapi/ntlm/compare_name.c b/lib/gssapi/ntlm/compare_name.c deleted file mode 100644 index d185ab940..000000000 --- a/lib/gssapi/ntlm/compare_name.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 1997-2003 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "ntlm.h" - -OM_uint32 GSSAPI_CALLCONV _gss_ntlm_compare_name - (OM_uint32 * minor_status, - gss_const_name_t name1, - gss_const_name_t name2, - int * name_equal - ) -{ - *minor_status = 0; - return GSS_S_COMPLETE; -} diff --git a/lib/gssapi/ntlm/context_time.c b/lib/gssapi/ntlm/context_time.c deleted file mode 100644 index 589ee2a71..000000000 --- a/lib/gssapi/ntlm/context_time.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "ntlm.h" - -OM_uint32 GSSAPI_CALLCONV _gss_ntlm_context_time - (OM_uint32 * minor_status, - gss_const_ctx_id_t context_handle, - OM_uint32 * time_rec - ) -{ - if (time_rec) - *time_rec = GSS_C_INDEFINITE; - return GSS_S_COMPLETE; -} diff --git a/lib/gssapi/ntlm/creds.c b/lib/gssapi/ntlm/creds.c deleted file mode 100644 index 57940156c..000000000 --- a/lib/gssapi/ntlm/creds.c +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (c) 2006 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Portions Copyright (c) 2009 Apple Inc. 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 "ntlm.h" - -OM_uint32 GSSAPI_CALLCONV -_gss_ntlm_inquire_cred - (OM_uint32 * minor_status, - gss_const_cred_id_t cred_handle, - gss_name_t * name, - OM_uint32 * lifetime, - gss_cred_usage_t * cred_usage, - gss_OID_set * mechanisms - ) -{ - OM_uint32 ret, junk; - - *minor_status = 0; - - if (cred_handle == NULL) - return GSS_S_NO_CRED; - - if (name) { - ntlm_name n = calloc(1, sizeof(*n)); - ntlm_cred c = (ntlm_cred)cred_handle; - if (n) { - n->user = strdup(c->username); - n->domain = strdup(c->domain); - } - if (n == NULL || n->user == NULL || n->domain == NULL) { - if (n) { - free(n->user); - free(n->domain); - free(n); - } - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - *name = (gss_name_t)n; - } - if (lifetime) - *lifetime = GSS_C_INDEFINITE; - if (cred_usage) - *cred_usage = 0; - if (mechanisms) - *mechanisms = GSS_C_NO_OID_SET; - if (mechanisms) { - ret = gss_create_empty_oid_set(minor_status, mechanisms); - if (ret) - goto out; - ret = gss_add_oid_set_member(minor_status, - GSS_NTLM_MECHANISM, - mechanisms); - if (ret) - goto out; - } - - return GSS_S_COMPLETE; -out: - gss_release_oid_set(&junk, mechanisms); - return ret; -} - -#ifdef HAVE_KCM -static OM_uint32 -_gss_ntlm_destroy_kcm_cred(gss_cred_id_t *cred_handle) -{ - krb5_storage *request, *response; - krb5_data response_data; - krb5_context context; - krb5_error_code ret; - ntlm_cred cred; - - cred = (ntlm_cred)*cred_handle; - - ret = krb5_init_context(&context); - if (ret) - return ret; - - ret = krb5_kcm_storage_request(context, KCM_OP_DEL_NTLM_CRED, &request); - if (ret) - goto out; - - ret = krb5_store_stringz(request, cred->username); - if (ret) - goto out; - - ret = krb5_store_stringz(request, cred->domain); - if (ret) - goto out; - - ret = krb5_kcm_call(context, request, &response, &response_data); - if (ret) - goto out; - - krb5_storage_free(request); - krb5_storage_free(response); - krb5_data_free(&response_data); - - out: - krb5_free_context(context); - - return ret; -} -#endif /* HAVE_KCM */ - -OM_uint32 GSSAPI_CALLCONV -_gss_ntlm_destroy_cred(OM_uint32 *minor_status, - gss_cred_id_t *cred_handle) -{ -#ifdef HAVE_KCM - krb5_error_code ret; -#endif - - if (cred_handle == NULL || *cred_handle == GSS_C_NO_CREDENTIAL) - return GSS_S_COMPLETE; - -#ifdef HAVE_KCM - ret = _gss_ntlm_destroy_kcm_cred(cred_handle); - if (ret) { - *minor_status = ret; - return GSS_S_FAILURE; - } -#endif - - return _gss_ntlm_release_cred(minor_status, cred_handle); -} diff --git a/lib/gssapi/ntlm/crypto.c b/lib/gssapi/ntlm/crypto.c deleted file mode 100644 index d2cfddf6d..000000000 --- a/lib/gssapi/ntlm/crypto.c +++ /dev/null @@ -1,615 +0,0 @@ -/* - * Copyright (c) 2006-2016 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 "ntlm.h" -struct hx509_certs_data; -struct krb5_pk_identity; -struct krb5_pk_cert; -struct ContentInfo; -struct AlgorithmIdentifier; -struct _krb5_krb_auth_data; -struct krb5_dh_moduli; -struct _krb5_key_data; -struct _krb5_encryption_type; -struct _krb5_key_type; -#include "krb5_locl.h" - -/* - * - */ - -const char a2i_signmagic[] = - "session key to server-to-client signing key magic constant"; -const char a2i_sealmagic[] = - "session key to server-to-client sealing key magic constant"; -const char i2a_signmagic[] = - "session key to client-to-server signing key magic constant"; -const char i2a_sealmagic[] = - "session key to client-to-server sealing key magic constant"; - - -void -_gss_ntlm_set_key(struct ntlmv2_key *key, int acceptor, int sealsign, - unsigned char *data, size_t len) -{ - unsigned char out[16]; - EVP_MD_CTX *ctx; - const char *signmagic; - const char *sealmagic; - - if (acceptor) { - signmagic = a2i_signmagic; - sealmagic = a2i_sealmagic; - } else { - signmagic = i2a_signmagic; - sealmagic = i2a_sealmagic; - } - - key->seq = 0; - - ctx = EVP_MD_CTX_create(); - EVP_DigestInit_ex(ctx, EVP_md5(), NULL); - EVP_DigestUpdate(ctx, data, len); - EVP_DigestUpdate(ctx, signmagic, strlen(signmagic) + 1); - EVP_DigestFinal_ex(ctx, key->signkey, NULL); - - EVP_DigestInit_ex(ctx, EVP_md5(), NULL); - EVP_DigestUpdate(ctx, data, len); - EVP_DigestUpdate(ctx, sealmagic, strlen(sealmagic) + 1); - EVP_DigestFinal_ex(ctx, out, NULL); - EVP_MD_CTX_destroy(ctx); - - RC4_set_key(&key->sealkey, 16, out); - if (sealsign) - key->signsealkey = &key->sealkey; -} - -/* - * Set (or reset) keys - */ - -void -_gss_ntlm_set_keys(ntlm_ctx ctx) -{ - int acceptor; - - if (ctx->sessionkey.length == 0) - return; - - acceptor = !(ctx->status & STATUS_CLIENT); - - ctx->status |= STATUS_SESSIONKEY; - - if (ctx->flags & NTLM_NEG_NTLM2_SESSION) { - _gss_ntlm_set_key(&ctx->u.v2.send, acceptor, - (ctx->flags & NTLM_NEG_KEYEX), - ctx->sessionkey.data, - ctx->sessionkey.length); - _gss_ntlm_set_key(&ctx->u.v2.recv, !acceptor, - (ctx->flags & NTLM_NEG_KEYEX), - ctx->sessionkey.data, - ctx->sessionkey.length); - } else { - ctx->u.v1.crypto_send.seq = 0; - RC4_set_key(&ctx->u.v1.crypto_send.key, - ctx->sessionkey.length, - ctx->sessionkey.data); - ctx->u.v1.crypto_recv.seq = 0; - RC4_set_key(&ctx->u.v1.crypto_recv.key, - ctx->sessionkey.length, - ctx->sessionkey.data); - } -} - -/* - * - */ - -static OM_uint32 -v1_sign_message(gss_buffer_t in, - RC4_KEY *signkey, - uint32_t seq, - unsigned char out[16]) -{ - unsigned char sigature[12]; - uint32_t crc; - - _krb5_crc_init_table(); - crc = _krb5_crc_update(in->value, in->length, 0); - - _gss_mg_encode_le_uint32(0, &sigature[0]); - _gss_mg_encode_le_uint32(crc, &sigature[4]); - _gss_mg_encode_le_uint32(seq, &sigature[8]); - - _gss_mg_encode_le_uint32(1, out); /* version */ - RC4(signkey, sizeof(sigature), sigature, out + 4); - - if (RAND_bytes(out + 4, 4) != 1) - return GSS_S_UNAVAILABLE; - - return 0; -} - - -static OM_uint32 -v2_sign_message(gss_buffer_t in, - unsigned char signkey[16], - RC4_KEY *sealkey, - uint32_t seq, - unsigned char out[16]) -{ - unsigned char hmac[16]; - unsigned int hmaclen; - HMAC_CTX c; - - HMAC_CTX_init(&c); - if (HMAC_Init_ex(&c, signkey, 16, EVP_md5(), NULL) == 0) { - HMAC_CTX_cleanup(&c); - return GSS_S_FAILURE; - } - - _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); - - _gss_mg_encode_le_uint32(1, &out[0]); - if (sealkey) - RC4(sealkey, 8, hmac, &out[4]); - else - memcpy(&out[4], hmac, 8); - - memset(&out[12], 0, 4); - - return GSS_S_COMPLETE; -} - -static OM_uint32 -v2_verify_message(gss_buffer_t in, - unsigned char signkey[16], - RC4_KEY *sealkey, - uint32_t seq, - const unsigned char checksum[16]) -{ - OM_uint32 ret; - unsigned char out[16]; - - ret = v2_sign_message(in, signkey, sealkey, seq, out); - if (ret) - return ret; - - if (ct_memcmp(checksum, out, 16) != 0) - return GSS_S_BAD_MIC; - - return GSS_S_COMPLETE; -} - -static OM_uint32 -v2_seal_message(const gss_buffer_t in, - unsigned char signkey[16], - uint32_t seq, - RC4_KEY *sealkey, - gss_buffer_t out) -{ - unsigned char *p; - OM_uint32 ret; - - if (in->length + 16 < in->length) - return EINVAL; - - p = malloc(in->length + 16); - if (p == NULL) - return ENOMEM; - - RC4(sealkey, in->length, in->value, p); - - ret = v2_sign_message(in, signkey, sealkey, seq, &p[in->length]); - if (ret) { - free(p); - return ret; - } - - out->value = p; - out->length = in->length + 16; - - return 0; -} - -static OM_uint32 -v2_unseal_message(gss_buffer_t in, - unsigned char signkey[16], - uint32_t seq, - RC4_KEY *sealkey, - gss_buffer_t out) -{ - OM_uint32 ret; - - if (in->length < 16) - return GSS_S_BAD_MIC; - - out->length = in->length - 16; - out->value = malloc(out->length); - if (out->value == NULL) - return GSS_S_BAD_MIC; - - RC4(sealkey, out->length, in->value, out->value); - - ret = v2_verify_message(out, signkey, sealkey, seq, - ((const unsigned char *)in->value) + out->length); - if (ret) { - OM_uint32 junk; - gss_release_buffer(&junk, out); - } - return ret; -} - -/* - * - */ - -#define CTX_FLAGS_ISSET(_ctx,_flags) \ - (((_ctx)->flags & (_flags)) == (_flags)) - -/* - * - */ - -OM_uint32 GSSAPI_CALLCONV -_gss_ntlm_get_mic - (OM_uint32 * minor_status, - gss_const_ctx_id_t context_handle, - gss_qop_t qop_req, - const gss_buffer_t message_buffer, - gss_buffer_t message_token - ) -{ - ntlm_ctx ctx = (ntlm_ctx)context_handle; - OM_uint32 junk; - - *minor_status = 0; - - message_token->value = malloc(16); - message_token->length = 16; - if (message_token->value == NULL) { - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - - if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SIGN|NTLM_NEG_NTLM2_SESSION)) { - OM_uint32 ret; - - if ((ctx->status & STATUS_SESSIONKEY) == 0) { - gss_release_buffer(&junk, message_token); - return GSS_S_UNAVAILABLE; - } - - ret = v2_sign_message(message_buffer, - ctx->u.v2.send.signkey, - ctx->u.v2.send.signsealkey, - ctx->u.v2.send.seq++, - message_token->value); - if (ret) - gss_release_buffer(&junk, message_token); - return ret; - - } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SIGN)) { - OM_uint32 ret; - - if ((ctx->status & STATUS_SESSIONKEY) == 0) { - gss_release_buffer(&junk, message_token); - return GSS_S_UNAVAILABLE; - } - - ret = v1_sign_message(message_buffer, - &ctx->u.v1.crypto_send.key, - ctx->u.v1.crypto_send.seq++, - message_token->value); - if (ret) - gss_release_buffer(&junk, message_token); - return ret; - - } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_ALWAYS_SIGN)) { - unsigned char *sigature; - - sigature = message_token->value; - - _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; - } - gss_release_buffer(&junk, message_token); - - return GSS_S_UNAVAILABLE; -} - -/* - * - */ - -OM_uint32 GSSAPI_CALLCONV -_gss_ntlm_verify_mic - (OM_uint32 * minor_status, - gss_const_ctx_id_t context_handle, - const gss_buffer_t message_buffer, - const gss_buffer_t token_buffer, - gss_qop_t * qop_state - ) -{ - ntlm_ctx ctx = (ntlm_ctx)context_handle; - - if (qop_state != NULL) - *qop_state = GSS_C_QOP_DEFAULT; - *minor_status = 0; - - if (token_buffer->length != 16) - return GSS_S_BAD_MIC; - - if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SIGN|NTLM_NEG_NTLM2_SESSION)) { - OM_uint32 ret; - - if ((ctx->status & STATUS_SESSIONKEY) == 0) - return GSS_S_UNAVAILABLE; - - ret = v2_verify_message(message_buffer, - ctx->u.v2.recv.signkey, - ctx->u.v2.recv.signsealkey, - ctx->u.v2.recv.seq++, - token_buffer->value); - if (ret) - return ret; - - return GSS_S_COMPLETE; - } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SIGN)) { - - unsigned char sigature[12]; - uint32_t crc, num; - - if ((ctx->status & STATUS_SESSIONKEY) == 0) - return GSS_S_UNAVAILABLE; - - _gss_mg_decode_le_uint32(token_buffer->value, &num); - if (num != 1) - return GSS_S_BAD_MIC; - - RC4(&ctx->u.v1.crypto_recv.key, sizeof(sigature), - ((unsigned char *)token_buffer->value) + 4, sigature); - - _krb5_crc_init_table(); - crc = _krb5_crc_update(message_buffer->value, - message_buffer->length, 0); - /* skip first 4 bytes in the encrypted checksum */ - _gss_mg_decode_le_uint32(&sigature[4], &num); - if (num != crc) - return GSS_S_BAD_MIC; - _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++; - - return GSS_S_COMPLETE; - } else if (ctx->flags & NTLM_NEG_ALWAYS_SIGN) { - uint32_t num; - unsigned char *p; - - p = (unsigned char*)(token_buffer->value); - - _gss_mg_decode_le_uint32(&p[0], &num); /* version */ - if (num != 1) return GSS_S_BAD_MIC; - _gss_mg_decode_le_uint32(&p[4], &num); - if (num != 0) return GSS_S_BAD_MIC; - _gss_mg_decode_le_uint32(&p[8], &num); - if (num != 0) return GSS_S_BAD_MIC; - _gss_mg_decode_le_uint32(&p[12], &num); - if (num != 0) return GSS_S_BAD_MIC; - - return GSS_S_COMPLETE; - } - - return GSS_S_UNAVAILABLE; -} - -/* - * - */ - -OM_uint32 GSSAPI_CALLCONV -_gss_ntlm_wrap_size_limit ( - OM_uint32 * minor_status, - gss_const_ctx_id_t context_handle, - int conf_req_flag, - gss_qop_t qop_req, - OM_uint32 req_output_size, - OM_uint32 * max_input_size - ) -{ - ntlm_ctx ctx = (ntlm_ctx)context_handle; - - *minor_status = 0; - - if(ctx->flags & NTLM_NEG_SEAL) { - - if (req_output_size < 16) - *max_input_size = 0; - else - *max_input_size = req_output_size - 16; - - return GSS_S_COMPLETE; - } - - return GSS_S_UNAVAILABLE; -} - -/* - * - */ - -OM_uint32 GSSAPI_CALLCONV -_gss_ntlm_wrap -(OM_uint32 * minor_status, - gss_const_ctx_id_t context_handle, - int conf_req_flag, - gss_qop_t qop_req, - const gss_buffer_t input_message_buffer, - int * conf_state, - gss_buffer_t output_message_buffer - ) -{ - ntlm_ctx ctx = (ntlm_ctx)context_handle; - OM_uint32 ret; - - *minor_status = 0; - if (conf_state) - *conf_state = 0; - if (output_message_buffer == GSS_C_NO_BUFFER) - return GSS_S_FAILURE; - - - if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SEAL|NTLM_NEG_NTLM2_SESSION)) { - - return v2_seal_message(input_message_buffer, - ctx->u.v2.send.signkey, - ctx->u.v2.send.seq++, - &ctx->u.v2.send.sealkey, - output_message_buffer); - - } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SEAL)) { - gss_buffer_desc trailer; - OM_uint32 junk; - - output_message_buffer->length = input_message_buffer->length + 16; - output_message_buffer->value = malloc(output_message_buffer->length); - if (output_message_buffer->value == NULL) { - output_message_buffer->length = 0; - return GSS_S_FAILURE; - } - - - RC4(&ctx->u.v1.crypto_send.key, input_message_buffer->length, - input_message_buffer->value, output_message_buffer->value); - - ret = _gss_ntlm_get_mic(minor_status, context_handle, - 0, input_message_buffer, - &trailer); - if (ret) { - gss_release_buffer(&junk, output_message_buffer); - return ret; - } - if (trailer.length != 16) { - gss_release_buffer(&junk, output_message_buffer); - gss_release_buffer(&junk, &trailer); - return GSS_S_FAILURE; - } - memcpy(((unsigned char *)output_message_buffer->value) + - input_message_buffer->length, - trailer.value, trailer.length); - gss_release_buffer(&junk, &trailer); - - return GSS_S_COMPLETE; - } - - return GSS_S_UNAVAILABLE; -} - -/* - * - */ - -OM_uint32 GSSAPI_CALLCONV -_gss_ntlm_unwrap - (OM_uint32 * minor_status, - gss_const_ctx_id_t context_handle, - const gss_buffer_t input_message_buffer, - gss_buffer_t output_message_buffer, - int * conf_state, - gss_qop_t * qop_state - ) -{ - ntlm_ctx ctx = (ntlm_ctx)context_handle; - OM_uint32 ret; - - *minor_status = 0; - output_message_buffer->value = NULL; - output_message_buffer->length = 0; - - if (conf_state) - *conf_state = 0; - if (qop_state) - *qop_state = 0; - - if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SEAL|NTLM_NEG_NTLM2_SESSION)) { - - return v2_unseal_message(input_message_buffer, - ctx->u.v2.recv.signkey, - ctx->u.v2.recv.seq++, - &ctx->u.v2.recv.sealkey, - output_message_buffer); - - } else if (CTX_FLAGS_ISSET(ctx, NTLM_NEG_SEAL)) { - - gss_buffer_desc trailer; - OM_uint32 junk; - - if (input_message_buffer->length < 16) - return GSS_S_BAD_MIC; - - output_message_buffer->length = input_message_buffer->length - 16; - output_message_buffer->value = malloc(output_message_buffer->length); - if (output_message_buffer->value == NULL) { - output_message_buffer->length = 0; - return GSS_S_FAILURE; - } - - RC4(&ctx->u.v1.crypto_recv.key, output_message_buffer->length, - input_message_buffer->value, output_message_buffer->value); - - trailer.value = ((unsigned char *)input_message_buffer->value) + - output_message_buffer->length; - trailer.length = 16; - - ret = _gss_ntlm_verify_mic(minor_status, context_handle, - output_message_buffer, - &trailer, NULL); - if (ret) { - gss_release_buffer(&junk, output_message_buffer); - return ret; - } - - return GSS_S_COMPLETE; - } - - return GSS_S_UNAVAILABLE; -} diff --git a/lib/gssapi/ntlm/delete_sec_context.c b/lib/gssapi/ntlm/delete_sec_context.c deleted file mode 100644 index 57587a020..000000000 --- a/lib/gssapi/ntlm/delete_sec_context.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "ntlm.h" - -OM_uint32 GSSAPI_CALLCONV _gss_ntlm_delete_sec_context - (OM_uint32 * minor_status, - gss_ctx_id_t * context_handle, - gss_buffer_t output_token - ) -{ - OM_uint32 min; - - if (context_handle) { - ntlm_ctx ctx = (ntlm_ctx)*context_handle; - gss_cred_id_t cred = (gss_cred_id_t)ctx->client; - - *context_handle = GSS_C_NO_CONTEXT; - - if (ctx->server) - (*ctx->server->nsi_destroy)(minor_status, ctx->ictx); - - _gss_ntlm_release_cred(NULL, &cred); - memset_s(ctx->sessionkey.data, ctx->sessionkey.length, 0, - ctx->sessionkey.length); - krb5_data_free(&ctx->sessionkey); - gss_release_buffer(&min, &ctx->pac); - - memset(ctx, 0, sizeof(*ctx)); - free(ctx); - } - if (output_token) { - output_token->length = 0; - output_token->value = NULL; - } - - *minor_status = 0; - return GSS_S_COMPLETE; -} diff --git a/lib/gssapi/ntlm/display_name.c b/lib/gssapi/ntlm/display_name.c deleted file mode 100644 index 59d2c8471..000000000 --- a/lib/gssapi/ntlm/display_name.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "ntlm.h" - -OM_uint32 GSSAPI_CALLCONV -_gss_ntlm_display_name - (OM_uint32 * minor_status, - gss_const_name_t input_name, - gss_buffer_t output_name_buffer, - gss_OID * output_name_type - ) -{ - *minor_status = 0; - - if (output_name_type) - *output_name_type = GSS_NTLM_MECHANISM; - - if (output_name_buffer) { - ntlm_name n = (ntlm_name)input_name; - char *str = NULL; - int len; - - output_name_buffer->length = 0; - output_name_buffer->value = NULL; - - if (n == NULL) { - *minor_status = 0; - return GSS_S_BAD_NAME; - } - - len = asprintf(&str, "%s@%s", n->user, n->domain); - if (len < 0 || str == NULL) { - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - output_name_buffer->length = len; - output_name_buffer->value = str; - } - return GSS_S_COMPLETE; -} diff --git a/lib/gssapi/ntlm/display_status.c b/lib/gssapi/ntlm/display_status.c deleted file mode 100644 index c9e1792d3..000000000 --- a/lib/gssapi/ntlm/display_status.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 1998 - 2005 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "ntlm.h" - -OM_uint32 GSSAPI_CALLCONV -_gss_ntlm_display_status - (OM_uint32 *minor_status, - OM_uint32 status_value, - int status_type, - const gss_OID mech_type, - OM_uint32 *message_context, - gss_buffer_t status_string) -{ - if (minor_status) - *minor_status = 0; - if (status_string) { - status_string->length = 0; - status_string->value = NULL; - } - if (message_context) - *message_context = 0; - return GSS_S_COMPLETE; -} diff --git a/lib/gssapi/ntlm/duplicate_cred.c b/lib/gssapi/ntlm/duplicate_cred.c deleted file mode 100644 index d05f9fad8..000000000 --- a/lib/gssapi/ntlm/duplicate_cred.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2006-2018 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 "ntlm.h" - -OM_uint32 GSSAPI_CALLCONV -_gss_ntlm_duplicate_cred(OM_uint32 *minor_status, - gss_const_cred_id_t input_cred_handle, - gss_cred_id_t *output_cred_handle) -{ - ntlm_const_cred cred = (ntlm_const_cred)input_cred_handle; - ntlm_cred new_cred; - OM_uint32 junk; - - if (input_cred_handle == GSS_C_NO_CREDENTIAL) - return _gss_ntlm_acquire_cred_from(minor_status, GSS_C_NO_NAME, - GSS_C_INDEFINITE, GSS_C_NO_OID_SET, - GSS_C_BOTH, GSS_C_NO_CRED_STORE, - output_cred_handle, NULL, NULL); - - *output_cred_handle = GSS_C_NO_CREDENTIAL; - - *minor_status = _gss_ntlm_copy_cred((ntlm_cred)input_cred_handle, - (ntlm_cred *)output_cred_handle); - - return *minor_status == 0 ? GSS_S_COMPLETE : GSS_S_FAILURE; -} diff --git a/lib/gssapi/ntlm/duplicate_name.c b/lib/gssapi/ntlm/duplicate_name.c deleted file mode 100644 index 060fa5593..000000000 --- a/lib/gssapi/ntlm/duplicate_name.c +++ /dev/null @@ -1,48 +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 "ntlm.h" - -OM_uint32 GSSAPI_CALLCONV -_gss_ntlm_duplicate_name ( - OM_uint32 * minor_status, - gss_const_name_t src_name, - gss_name_t * dest_name - ) -{ - if (minor_status) - *minor_status = 0; - if (dest_name) - *dest_name = NULL; - return GSS_S_COMPLETE; -} diff --git a/lib/gssapi/ntlm/export_name.c b/lib/gssapi/ntlm/export_name.c deleted file mode 100644 index e5bdca4c9..000000000 --- a/lib/gssapi/ntlm/export_name.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 1997, 1999, 2003 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "ntlm.h" - -OM_uint32 GSSAPI_CALLCONV -_gss_ntlm_export_name - (OM_uint32 * minor_status, - gss_const_name_t input_name, - gss_buffer_t exported_name - ) -{ - if (minor_status) - *minor_status = 0; - if (exported_name) { - exported_name->length = 0; - exported_name->value = NULL; - } - return GSS_S_COMPLETE; -} diff --git a/lib/gssapi/ntlm/export_sec_context.c b/lib/gssapi/ntlm/export_sec_context.c deleted file mode 100644 index 027a9210e..000000000 --- a/lib/gssapi/ntlm/export_sec_context.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 1999 - 2003 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "ntlm.h" - -OM_uint32 GSSAPI_CALLCONV -_gss_ntlm_export_sec_context ( - OM_uint32 * minor_status, - gss_ctx_id_t * context_handle, - gss_buffer_t interprocess_token - ) -{ - if (minor_status) - *minor_status = 0; - if (interprocess_token) { - interprocess_token->length = 0; - interprocess_token->value = NULL; - } - return GSS_S_COMPLETE; -} diff --git a/lib/gssapi/ntlm/external.c b/lib/gssapi/ntlm/external.c deleted file mode 100644 index ff2cd2d1f..000000000 --- a/lib/gssapi/ntlm/external.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 2006-2018 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 "ntlm.h" - -static gss_mo_desc ntlm_mo[] = { - { - GSS_C_MA_SASL_MECH_NAME, - GSS_MO_MA, - "SASL mech name", - rk_UNCONST("NTLM"), - _gss_mo_get_ctx_as_string, - NULL - }, - { - GSS_C_MA_MECH_NAME, - GSS_MO_MA, - "Mechanism name", - rk_UNCONST("NTLMSPP"), - _gss_mo_get_ctx_as_string, - NULL - }, - { - GSS_C_MA_MECH_DESCRIPTION, - GSS_MO_MA, - "Mechanism description", - rk_UNCONST("Heimdal NTLMSSP Mechanism"), - _gss_mo_get_ctx_as_string, - NULL - } -}; - -static gssapi_mech_interface_desc ntlm_mech = { - GMI_VERSION, - "ntlm", - {10, rk_UNCONST("\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a") }, - 0, - NULL, - _gss_ntlm_release_cred, - _gss_ntlm_init_sec_context, - _gss_ntlm_accept_sec_context, - _gss_ntlm_process_context_token, - _gss_ntlm_delete_sec_context, - _gss_ntlm_context_time, - _gss_ntlm_get_mic, - _gss_ntlm_verify_mic, - _gss_ntlm_wrap, - _gss_ntlm_unwrap, - _gss_ntlm_display_status, - NULL, - _gss_ntlm_compare_name, - _gss_ntlm_display_name, - _gss_ntlm_import_name, - _gss_ntlm_export_name, - _gss_ntlm_release_name, - _gss_ntlm_inquire_cred, - _gss_ntlm_inquire_context, - _gss_ntlm_wrap_size_limit, - _gss_ntlm_add_cred, - _gss_ntlm_inquire_cred_by_mech, - _gss_ntlm_export_sec_context, - _gss_ntlm_import_sec_context, - _gss_ntlm_inquire_names_for_mech, - _gss_ntlm_inquire_mechs_for_name, - _gss_ntlm_canonicalize_name, - _gss_ntlm_duplicate_name, - _gss_ntlm_inquire_sec_context_by_oid, - NULL, - _gss_ntlm_set_sec_context_option, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - _gss_ntlm_acquire_cred_from, - NULL, /* gm_acquire_cred_impersonate_name */ - _gss_ntlm_iter_creds_f, - _gss_ntlm_destroy_cred, - NULL, - NULL, - NULL, - NULL, - ntlm_mo, - sizeof(ntlm_mo) / sizeof(ntlm_mo[0]), - NULL, /* gm_localname */ - NULL, /* gm_authorize_localname */ - NULL, /* gm_display_name_ext */ - NULL, /* gm_inquire_name */ - NULL, /* gm_get_name_attribute */ - NULL, /* gm_set_name_attribute */ - NULL, /* gm_delete_name_attribute */ - NULL, /* gm_export_name_composite */ - NULL, /* gm_duplicate_cred */ - NULL, /* gm_add_cred_from */ - NULL, /* gm_store_cred_into */ - NULL, /* gm_query_mechanism_info */ - NULL, /* gm_query_meta_data */ - NULL, /* gm_exchange_meta_data */ - NULL, /* gm_store_cred_into2 */ - NULL, /* gm_compat */ -}; - -gssapi_mech_interface -__gss_ntlm_initialize(void) -{ - return &ntlm_mech; -} diff --git a/lib/gssapi/ntlm/import_name.c b/lib/gssapi/ntlm/import_name.c deleted file mode 100644 index e75388d91..000000000 --- a/lib/gssapi/ntlm/import_name.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "ntlm.h" - -OM_uint32 GSSAPI_CALLCONV -_gss_ntlm_import_name - (OM_uint32 * minor_status, - const gss_buffer_t input_name_buffer, - const gss_OID input_name_type, - gss_name_t * output_name - ) -{ - char *name, *p, *p2; - int is_hostnamed; - int is_username; - ntlm_name n; - - *minor_status = 0; - - if (output_name == NULL) - return GSS_S_CALL_INACCESSIBLE_WRITE; - - *output_name = GSS_C_NO_NAME; - - is_hostnamed = gss_oid_equal(input_name_type, GSS_C_NT_HOSTBASED_SERVICE); - is_username = gss_oid_equal(input_name_type, GSS_C_NT_USER_NAME); - - if (!is_hostnamed && !is_username) - return GSS_S_BAD_NAMETYPE; - - name = malloc(input_name_buffer->length + 1); - if (name == NULL) { - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - memcpy(name, input_name_buffer->value, input_name_buffer->length); - name[input_name_buffer->length] = '\0'; - - /* find "domain" part of the name and uppercase it */ - p = strchr(name, '@'); - if (p == NULL) { - free(name); - return GSS_S_BAD_NAME; - } - p[0] = '\0'; - p++; - p2 = strchr(p, '.'); - if (p2 && p2[1] != '\0') { - if (is_hostnamed) { - p = p2 + 1; - p2 = strchr(p, '.'); - } - if (p2) - *p2 = '\0'; - } - strupr(p); - - n = calloc(1, sizeof(*n)); - if (n == NULL) { - free(name); - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - - n->user = strdup(name); - n->domain = strdup(p); - - free(name); - - if (n->user == NULL || n->domain == NULL) { - free(n->user); - free(n->domain); - free(n); - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - - *output_name = (gss_name_t)n; - - return GSS_S_COMPLETE; -} diff --git a/lib/gssapi/ntlm/import_sec_context.c b/lib/gssapi/ntlm/import_sec_context.c deleted file mode 100644 index fe637c077..000000000 --- a/lib/gssapi/ntlm/import_sec_context.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 1999 - 2003 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "ntlm.h" - -OM_uint32 GSSAPI_CALLCONV -_gss_ntlm_import_sec_context ( - OM_uint32 * minor_status, - const gss_buffer_t interprocess_token, - gss_ctx_id_t * context_handle - ) -{ - if (minor_status) - *minor_status = 0; - if (context_handle) - *context_handle = GSS_C_NO_CONTEXT; - return GSS_S_FAILURE; -} diff --git a/lib/gssapi/ntlm/indicate_mechs.c b/lib/gssapi/ntlm/indicate_mechs.c deleted file mode 100644 index 7cda47580..000000000 --- a/lib/gssapi/ntlm/indicate_mechs.c +++ /dev/null @@ -1,46 +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 "ntlm.h" - -OM_uint32 _gss_ntlm_indicate_mechs -(OM_uint32 * minor_status, - gss_OID_set * mech_set - ) -{ - if (minor_status) - *minor_status = 0; - if (mech_set) - *mech_set = GSS_C_NO_OID_SET; - return GSS_S_COMPLETE; -} diff --git a/lib/gssapi/ntlm/init_sec_context.c b/lib/gssapi/ntlm/init_sec_context.c deleted file mode 100644 index be9c987c4..000000000 --- a/lib/gssapi/ntlm/init_sec_context.c +++ /dev/null @@ -1,536 +0,0 @@ -/* - * Copyright (c) 2006 - 2008 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "ntlm.h" - -static int -from_file(const char *fn, const char *target_domain, - char **domainp, char **usernamep, struct ntlm_buf *key) -{ - char *str, buf[1024]; - FILE *f; - - *domainp = NULL; - - f = fopen(fn, "r"); - if (f == NULL) - return ENOENT; - rk_cloexec_file(f); - - while (fgets(buf, sizeof(buf), f) != NULL) { - char *d, *u, *p; - buf[strcspn(buf, "\r\n")] = '\0'; - if (buf[0] == '#') - continue; - str = NULL; - d = strtok_r(buf, ":", &str); - free(*domainp); - *domainp = NULL; - if (!d) - continue; - if (d && target_domain != NULL && strcasecmp(target_domain, d) != 0) - continue; - *domainp = strdup(d); - if (*domainp == NULL) { - fclose(f); - return ENOMEM; - } - u = strtok_r(NULL, ":", &str); - p = strtok_r(NULL, ":", &str); - if (u == NULL || p == NULL) - continue; - - *usernamep = strdup(u); - if (*usernamep == NULL) { - fclose(f); - return ENOMEM; - } - heim_ntlm_nt_key(p, key); - - memset_s(buf, sizeof(buf), 0, sizeof(buf)); - fclose(f); - return 0; - } - memset_s(buf, sizeof(buf), 0, sizeof(buf)); - fclose(f); - return ENOENT; -} - -static int -get_user_file(const ntlm_name target_name, - char **domainp, char **usernamep, struct ntlm_buf *key) -{ - const char *domain; - const char *fn; - - *domainp = NULL; - - domain = target_name != NULL ? target_name->domain : NULL; - - fn = secure_getenv("NTLM_USER_FILE"); - if (fn == NULL) - return ENOENT; - if (from_file(fn, domain, domainp, usernamep, key) == 0) - return 0; - - return ENOENT; -} - -/* - * Pick up the ntlm cred from the default krb5 credential cache. - */ - -static int -get_user_ccache(const ntlm_name name, char **domainp, char **usernamep, struct ntlm_buf *key) -{ - krb5_context context = NULL; - krb5_principal client; - krb5_ccache id = NULL; - krb5_error_code ret; - char *confname; - krb5_data data; - int aret; - - *domainp = NULL; - *usernamep = NULL; - krb5_data_zero(&data); - key->length = 0; - key->data = NULL; - - ret = krb5_init_context(&context); - if (ret) - return ret; - - ret = krb5_cc_default(context, &id); - if (ret) - goto out; - - ret = krb5_cc_get_principal(context, id, &client); - if (ret) - goto out; - - ret = krb5_unparse_name_flags(context, client, - KRB5_PRINCIPAL_UNPARSE_NO_REALM, - usernamep); - krb5_free_principal(context, client); - if (ret) - goto out; - - if (name != NULL) { - *domainp = strdup(name->domain); - } else { - krb5_data data_domain; - - krb5_data_zero(&data_domain); - ret = krb5_cc_get_config(context, id, NULL, "default-ntlm-domain", - &data_domain); - if (ret) - goto out; - - *domainp = strndup(data_domain.data, data_domain.length); - krb5_data_free(&data_domain); - } - - if (*domainp == NULL) { - ret = krb5_enomem(context); - goto out; - } - - aret = asprintf(&confname, "ntlm-key-%s", *domainp); - if (aret == -1) { - ret = krb5_enomem(context); - goto out; - } - - ret = krb5_cc_get_config(context, id, NULL, confname, &data); - if (ret) - goto out; - - key->data = malloc(data.length); - if (key->data == NULL) { - ret = ENOMEM; - goto out; - } - key->length = data.length; - memcpy(key->data, data.data, data.length); - - out: - krb5_data_free(&data); - if (id) - krb5_cc_close(context, id); - - krb5_free_context(context); - - return ret; -} - -int -_gss_ntlm_get_user_cred(const ntlm_name target_name, - ntlm_cred *rcred) -{ - ntlm_cred cred; - int ret; - - cred = calloc(1, sizeof(*cred)); - if (cred == NULL) - return ENOMEM; - - ret = get_user_file(target_name, - &cred->domain, &cred->username, &cred->key); - if (ret) - ret = get_user_ccache(target_name, - &cred->domain, &cred->username, &cred->key); - if (ret) { - OM_uint32 tmp; - _gss_ntlm_release_cred(&tmp, (gss_cred_id_t *)&cred); - return ret; - } - - *rcred = cred; - - return ret; -} - -int -_gss_ntlm_copy_cred(ntlm_cred from, ntlm_cred *to) -{ - *to = calloc(1, sizeof(**to)); - if (*to == NULL) - return ENOMEM; - (*to)->usage = from->usage; - (*to)->username = strdup(from->username); - if ((*to)->username == NULL) { - free(*to); - return ENOMEM; - } - (*to)->domain = strdup(from->domain); - if ((*to)->domain == NULL) { - free((*to)->username); - free(*to); - return ENOMEM; - } - (*to)->key.data = malloc(from->key.length); - if ((*to)->key.data == NULL) { - free((*to)->domain); - free((*to)->username); - free(*to); - return ENOMEM; - } - memcpy((*to)->key.data, from->key.data, from->key.length); - (*to)->key.length = from->key.length; - - return 0; -} - -OM_uint32 GSSAPI_CALLCONV -_gss_ntlm_init_sec_context - (OM_uint32 * minor_status, - gss_const_cred_id_t initiator_cred_handle, - gss_ctx_id_t * context_handle, - gss_const_name_t target_name, - const gss_OID mech_type, - OM_uint32 req_flags, - OM_uint32 time_req, - const gss_channel_bindings_t input_chan_bindings, - const gss_buffer_t input_token, - gss_OID * actual_mech_type, - gss_buffer_t output_token, - OM_uint32 * ret_flags, - OM_uint32 * time_rec - ) -{ - ntlm_ctx ctx; - ntlm_name name = (ntlm_name)target_name; - - *minor_status = 0; - - if (ret_flags) - *ret_flags = 0; - if (time_rec) - *time_rec = 0; - if (actual_mech_type) - *actual_mech_type = GSS_C_NO_OID; - - if (*context_handle == GSS_C_NO_CONTEXT) { - struct ntlm_type1 type1; - struct ntlm_buf data; - uint32_t flags = 0; - int ret; - - ctx = calloc(1, sizeof(*ctx)); - if (ctx == NULL) { - *minor_status = EINVAL; - return GSS_S_FAILURE; - } - ctx->status = STATUS_CLIENT; - *context_handle = (gss_ctx_id_t)ctx; - - if (initiator_cred_handle != GSS_C_NO_CREDENTIAL) { - ntlm_cred cred = (ntlm_cred)initiator_cred_handle; - ret = _gss_ntlm_copy_cred(cred, &ctx->client); - } else - ret = _gss_ntlm_get_user_cred(name, &ctx->client); - - if (ret) { - _gss_ntlm_delete_sec_context(minor_status, context_handle, NULL); - *minor_status = ret; - return GSS_S_FAILURE; - } - - if (req_flags & GSS_C_CONF_FLAG) - flags |= NTLM_NEG_SEAL; - if (req_flags & GSS_C_INTEG_FLAG) - flags |= NTLM_NEG_SIGN; - else - flags |= NTLM_NEG_ALWAYS_SIGN; - - flags |= NTLM_NEG_UNICODE; - flags |= NTLM_NEG_NTLM; - flags |= NTLM_NEG_NTLM2_SESSION; - flags |= NTLM_NEG_KEYEX; - - memset(&type1, 0, sizeof(type1)); - - type1.flags = flags; - type1.domain = name->domain; - type1.hostname = NULL; - type1.os[0] = 0; - type1.os[1] = 0; - - ret = heim_ntlm_encode_type1(&type1, &data); - if (ret) { - _gss_ntlm_delete_sec_context(minor_status, context_handle, NULL); - *minor_status = ret; - return GSS_S_FAILURE; - } - - output_token->value = data.data; - output_token->length = data.length; - - return GSS_S_CONTINUE_NEEDED; - } else { - krb5_error_code ret; - struct ntlm_type2 type2; - struct ntlm_type3 type3; - struct ntlm_buf data; - - ctx = (ntlm_ctx)*context_handle; - - data.data = input_token->value; - data.length = input_token->length; - - ret = heim_ntlm_decode_type2(&data, &type2); - if (ret) { - _gss_ntlm_delete_sec_context(minor_status, context_handle, NULL); - *minor_status = ret; - return GSS_S_DEFECTIVE_TOKEN; - } - - ctx->flags = type2.flags; - - /* XXX check that type2.targetinfo matches `target_name´ */ - /* XXX check verify targetinfo buffer */ - - memset(&type3, 0, sizeof(type3)); - - type3.username = ctx->client->username; - type3.flags = type2.flags; - type3.targetname = type2.targetname; - type3.ws = rk_UNCONST("workstation"); - - /* - * NTLM Version 1 if no targetinfo buffer. - */ - - if (1 || type2.targetinfo.length == 0) { - struct ntlm_buf sessionkey; - - if (type2.flags & NTLM_NEG_NTLM2_SESSION) { - unsigned char nonce[8]; - - if (RAND_bytes(nonce, sizeof(nonce)) != 1) { - _gss_ntlm_delete_sec_context(minor_status, - context_handle, NULL); - heim_ntlm_free_type2(&type2); - *minor_status = EINVAL; - return GSS_S_FAILURE; - } - - ret = heim_ntlm_calculate_ntlm2_sess(nonce, - type2.challenge, - ctx->client->key.data, - &type3.lm, - &type3.ntlm); - } else { - ret = heim_ntlm_calculate_ntlm1(ctx->client->key.data, - ctx->client->key.length, - type2.challenge, - &type3.ntlm); - - } - if (ret) { - _gss_ntlm_delete_sec_context(minor_status,context_handle,NULL); - heim_ntlm_free_type2(&type2); - *minor_status = ret; - return GSS_S_FAILURE; - } - - ret = heim_ntlm_build_ntlm1_master(ctx->client->key.data, - ctx->client->key.length, - &sessionkey, - &type3.sessionkey); - if (ret) { - if (type3.lm.data) - free(type3.lm.data); - if (type3.ntlm.data) - free(type3.ntlm.data); - _gss_ntlm_delete_sec_context(minor_status,context_handle,NULL); - heim_ntlm_free_type2(&type2); - *minor_status = ret; - return GSS_S_FAILURE; - } - - ret = krb5_data_copy(&ctx->sessionkey, - sessionkey.data, sessionkey.length); - free(sessionkey.data); - if (ret) { - if (type3.lm.data) - free(type3.lm.data); - if (type3.ntlm.data) - free(type3.ntlm.data); - _gss_ntlm_delete_sec_context(minor_status,context_handle,NULL); - heim_ntlm_free_type2(&type2); - *minor_status = ret; - return GSS_S_FAILURE; - } - ctx->status |= STATUS_SESSIONKEY; - - } else { - struct ntlm_buf sessionkey; - unsigned char ntlmv2[16]; - struct ntlm_targetinfo ti; - - /* verify infotarget */ - - ret = heim_ntlm_decode_targetinfo(&type2.targetinfo, 1, &ti); - if(ret) { - _gss_ntlm_delete_sec_context(minor_status, - context_handle, NULL); - heim_ntlm_free_type2(&type2); - *minor_status = ret; - return GSS_S_DEFECTIVE_TOKEN; - } - - if (ti.domainname && strcmp(ti.domainname, name->domain) != 0) { - _gss_ntlm_delete_sec_context(minor_status, - context_handle, NULL); - heim_ntlm_free_type2(&type2); - *minor_status = EINVAL; - return GSS_S_FAILURE; - } - - ret = heim_ntlm_calculate_ntlm2(ctx->client->key.data, - ctx->client->key.length, - ctx->client->username, - name->domain, - type2.challenge, - &type2.targetinfo, - ntlmv2, - &type3.ntlm); - if (ret) { - _gss_ntlm_delete_sec_context(minor_status, - context_handle, NULL); - heim_ntlm_free_type2(&type2); - *minor_status = ret; - return GSS_S_FAILURE; - } - - ret = heim_ntlm_build_ntlm1_master(ntlmv2, sizeof(ntlmv2), - &sessionkey, - &type3.sessionkey); - memset_s(ntlmv2, sizeof(ntlmv2), 0, sizeof(ntlmv2)); - if (ret) { - _gss_ntlm_delete_sec_context(minor_status, - context_handle, NULL); - heim_ntlm_free_type2(&type2); - *minor_status = ret; - return GSS_S_FAILURE; - } - - ctx->flags |= NTLM_NEG_NTLM2_SESSION; - - ret = krb5_data_copy(&ctx->sessionkey, - sessionkey.data, sessionkey.length); - free(sessionkey.data); - if (ret) { - _gss_ntlm_delete_sec_context(minor_status, - context_handle, NULL); - heim_ntlm_free_type2(&type2); - *minor_status = ret; - return GSS_S_FAILURE; - } - } - - - _gss_ntlm_set_keys(ctx); - - - ret = heim_ntlm_encode_type3(&type3, &data, NULL); - free(type3.sessionkey.data); - if (type3.lm.data) - free(type3.lm.data); - if (type3.ntlm.data) - free(type3.ntlm.data); - if (ret) { - _gss_ntlm_delete_sec_context(minor_status, context_handle, NULL); - heim_ntlm_free_type2(&type2); - *minor_status = ret; - return GSS_S_FAILURE; - } - - output_token->length = data.length; - output_token->value = data.data; - - if (actual_mech_type) - *actual_mech_type = GSS_NTLM_MECHANISM; - if (ret_flags) - *ret_flags = 0; - if (time_rec) - *time_rec = GSS_C_INDEFINITE; - - ctx->status |= STATUS_OPEN; - - heim_ntlm_free_type2(&type2); - return GSS_S_COMPLETE; - } -} diff --git a/lib/gssapi/ntlm/inquire_context.c b/lib/gssapi/ntlm/inquire_context.c deleted file mode 100644 index 741ad6e14..000000000 --- a/lib/gssapi/ntlm/inquire_context.c +++ /dev/null @@ -1,68 +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 "ntlm.h" - -OM_uint32 GSSAPI_CALLCONV -_gss_ntlm_inquire_context ( - OM_uint32 * minor_status, - gss_const_ctx_id_t context_handle, - gss_name_t * src_name, - gss_name_t * targ_name, - OM_uint32 * lifetime_rec, - gss_OID * mech_type, - OM_uint32 * ctx_flags, - int * locally_initiated, - int * open_context - ) -{ - ntlm_ctx ctx = (ntlm_ctx)context_handle; - - *minor_status = 0; - if (src_name) - *src_name = GSS_C_NO_NAME; - if (targ_name) - *targ_name = GSS_C_NO_NAME; - if (lifetime_rec) - *lifetime_rec = GSS_C_INDEFINITE; - if (mech_type) - *mech_type = GSS_NTLM_MECHANISM; - if (ctx_flags) - *ctx_flags = ctx->gssflags; - if (locally_initiated) - *locally_initiated = (ctx->status & STATUS_CLIENT) ? 1 : 0; - if (open_context) - *open_context = (ctx->status & STATUS_OPEN) ? 1 : 0; - - return GSS_S_COMPLETE; -} diff --git a/lib/gssapi/ntlm/inquire_cred_by_mech.c b/lib/gssapi/ntlm/inquire_cred_by_mech.c deleted file mode 100644 index ed42094c9..000000000 --- a/lib/gssapi/ntlm/inquire_cred_by_mech.c +++ /dev/null @@ -1,58 +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 "ntlm.h" - -OM_uint32 GSSAPI_CALLCONV -_gss_ntlm_inquire_cred_by_mech ( - OM_uint32 * minor_status, - gss_const_cred_id_t cred_handle, - const gss_OID mech_type, - gss_name_t * name, - OM_uint32 * initiator_lifetime, - OM_uint32 * acceptor_lifetime, - gss_cred_usage_t * cred_usage - ) -{ - if (minor_status) - *minor_status = 0; - if (name) - *name = GSS_C_NO_NAME; - if (initiator_lifetime) - *initiator_lifetime = 0; - if (acceptor_lifetime) - *acceptor_lifetime = 0; - if (cred_usage) - *cred_usage = 0; - return GSS_S_UNAVAILABLE; -} diff --git a/lib/gssapi/ntlm/inquire_mechs_for_name.c b/lib/gssapi/ntlm/inquire_mechs_for_name.c deleted file mode 100644 index 25450ab17..000000000 --- a/lib/gssapi/ntlm/inquire_mechs_for_name.c +++ /dev/null @@ -1,48 +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 "ntlm.h" - -OM_uint32 GSSAPI_CALLCONV -_gss_ntlm_inquire_mechs_for_name ( - OM_uint32 * minor_status, - gss_const_name_t input_name, - gss_OID_set * mech_types - ) -{ - if (minor_status) - *minor_status = 0; - if (mech_types) - *mech_types = GSS_C_NO_OID_SET; - return GSS_S_COMPLETE; -} diff --git a/lib/gssapi/ntlm/inquire_names_for_mech.c b/lib/gssapi/ntlm/inquire_names_for_mech.c deleted file mode 100644 index 7f49b33ca..000000000 --- a/lib/gssapi/ntlm/inquire_names_for_mech.c +++ /dev/null @@ -1,51 +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 "ntlm.h" - -OM_uint32 GSSAPI_CALLCONV -_gss_ntlm_inquire_names_for_mech ( - OM_uint32 * minor_status, - const gss_OID mechanism, - gss_OID_set * name_types - ) -{ - OM_uint32 ret; - - ret = gss_create_empty_oid_set(minor_status, name_types); - if (ret != GSS_S_COMPLETE) - return ret; - - *minor_status = 0; - return GSS_S_COMPLETE; -} diff --git a/lib/gssapi/ntlm/inquire_sec_context_by_oid.c b/lib/gssapi/ntlm/inquire_sec_context_by_oid.c deleted file mode 100644 index 2b42b1f51..000000000 --- a/lib/gssapi/ntlm/inquire_sec_context_by_oid.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2006 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Portions Copyright (c) 2009 Apple Inc. 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 "ntlm.h" - -OM_uint32 GSSAPI_CALLCONV -_gss_ntlm_inquire_sec_context_by_oid(OM_uint32 *minor_status, - gss_const_ctx_id_t context_handle, - const gss_OID desired_object, - gss_buffer_set_t *data_set) -{ - ntlm_ctx ctx = (ntlm_ctx)context_handle; - - if (ctx == NULL) { - *minor_status = 0; - return GSS_S_NO_CONTEXT; - } - - if (gss_oid_equal(desired_object, GSS_NTLM_GET_SESSION_KEY_X) || - gss_oid_equal(desired_object, GSS_C_INQ_SSPI_SESSION_KEY)) { - gss_buffer_desc value; - - value.length = ctx->sessionkey.length; - value.value = ctx->sessionkey.data; - - return gss_add_buffer_set_member(minor_status, - &value, - data_set); - } else if (gss_oid_equal(desired_object, GSS_C_INQ_WIN2K_PAC_X)) { - if (ctx->pac.length == 0) { - *minor_status = ENOENT; - return GSS_S_FAILURE; - } - - return gss_add_buffer_set_member(minor_status, - &ctx->pac, - data_set); - - } else if (gss_oid_equal(desired_object, GSS_C_NTLM_AVGUEST)) { - gss_buffer_desc value; - uint32_t num; - - if (ctx->kcmflags & KCM_NTLM_FLAG_AV_GUEST) - num = 1; - else - num = 0; - - value.length = sizeof(num); - value.value = # - - return gss_add_buffer_set_member(minor_status, - &value, - data_set); - } else { - *minor_status = 0; - return GSS_S_FAILURE; - } -} diff --git a/lib/gssapi/ntlm/iter_cred.c b/lib/gssapi/ntlm/iter_cred.c deleted file mode 100644 index ee5ec172c..000000000 --- a/lib/gssapi/ntlm/iter_cred.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2006 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Portions Copyright (c) 2009 Apple Inc. 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 "ntlm.h" - -void GSSAPI_CALLCONV -_gss_ntlm_iter_creds_f(OM_uint32 flags, - void *userctx , - void (*cred_iter)(void *, gss_OID, gss_cred_id_t)) -{ -#ifdef HAVE_KCM - krb5_error_code ret; - krb5_context context = NULL; - krb5_storage *request, *response; - krb5_data response_data; - - ret = krb5_init_context(&context); - if (ret) - goto done; - - ret = krb5_kcm_storage_request(context, KCM_OP_GET_NTLM_USER_LIST, &request); - if (ret) - goto done; - - ret = krb5_kcm_call(context, request, &response, &response_data); - krb5_storage_free(request); - if (ret) - goto done; - - while (1) { - uint32_t morep; - char *user = NULL, *domain = NULL; - ntlm_cred dn; - - ret = krb5_ret_uint32(response, &morep); - if (ret) goto out; - - if (!morep) goto out; - - ret = krb5_ret_stringz(response, &user); - if (ret) goto out; - ret = krb5_ret_stringz(response, &domain); - if (ret) { - free(user); - goto out; - } - - dn = calloc(1, sizeof(*dn)); - if (dn == NULL) { - free(user); - free(domain); - goto out; - } - dn->username = user; - dn->domain = domain; - - cred_iter(userctx, GSS_NTLM_MECHANISM, (gss_cred_id_t)dn); - } - out: - krb5_storage_free(response); - krb5_data_free(&response_data); - done: - if (context) - krb5_free_context(context); -#endif /* HAVE_KCM */ - (*cred_iter)(userctx, NULL, NULL); -} diff --git a/lib/gssapi/ntlm/kdc.c b/lib/gssapi/ntlm/kdc.c deleted file mode 100644 index 10aa2b980..000000000 --- a/lib/gssapi/ntlm/kdc.c +++ /dev/null @@ -1,435 +0,0 @@ -/* - * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "ntlm.h" - -#ifdef DIGEST - -/* - * - */ - -struct ntlmkrb5 { - krb5_context context; - krb5_ntlm ntlm; - krb5_realm kerberos_realm; - krb5_ccache id; - krb5_data opaque; - int destroy; - OM_uint32 flags; - struct ntlm_buf key; - krb5_data sessionkey; -}; - -static OM_uint32 kdc_destroy(OM_uint32 *, void *); - -/* - * Get credential cache that the ntlm code can use to talk to the KDC - * using the digest API. - */ - -static krb5_error_code -get_ccache(krb5_context context, int *destroy, krb5_ccache *id) -{ - krb5_principal principal = NULL; - krb5_error_code ret; - krb5_keytab kt = NULL; - const char *cache = secure_getenv("NTLM_ACCEPTOR_CCACHE"); - - *id = NULL; - - if (cache) { - ret = krb5_cc_resolve(context, cache, id); - if (ret) - goto out; - return 0; - } - - ret = krb5_sname_to_principal(context, NULL, "host", - KRB5_NT_SRV_HST, &principal); - if (ret) - goto out; - - ret = krb5_cc_cache_match(context, principal, id); - if (ret == 0) - goto out; - - /* did not find in default credcache, lets try default keytab */ - ret = krb5_kt_default(context, &kt); - if (ret) - goto out; - - /* XXX check in keytab */ - { - krb5_get_init_creds_opt *opt; - krb5_creds cred; - - memset(&cred, 0, sizeof(cred)); - - ret = krb5_cc_new_unique(context, "MEMORY", NULL, id); - if (ret) - goto out; - *destroy = 1; - ret = krb5_get_init_creds_opt_alloc(context, &opt); - if (ret) - goto out; - ret = krb5_get_init_creds_keytab (context, - &cred, - principal, - kt, - 0, - NULL, - opt); - krb5_get_init_creds_opt_free(context, opt); - if (ret) - goto out; - ret = krb5_cc_initialize (context, *id, cred.client); - if (ret) { - krb5_free_cred_contents (context, &cred); - goto out; - } - ret = krb5_cc_store_cred (context, *id, &cred); - krb5_free_cred_contents (context, &cred); - if (ret) - goto out; - } - - krb5_kt_close(context, kt); - - return 0; - -out: - if (*id) { - if (*destroy) - krb5_cc_destroy(context, *id); - else - krb5_cc_close(context, *id); - *id = NULL; - } - - if (kt) - krb5_kt_close(context, kt); - - if (principal) - krb5_free_principal(context, principal); - return ret; -} - -/* - * - */ - -static OM_uint32 -kdc_alloc(OM_uint32 *minor, void **ctx) -{ - krb5_error_code ret; - struct ntlmkrb5 *c; - OM_uint32 junk; - - c = calloc(1, sizeof(*c)); - if (c == NULL) { - *minor = ENOMEM; - return GSS_S_FAILURE; - } - - ret = krb5_init_context(&c->context); - if (ret) { - kdc_destroy(&junk, c); - *minor = ret; - return GSS_S_FAILURE; - } - - ret = get_ccache(c->context, &c->destroy, &c->id); - if (ret) { - kdc_destroy(&junk, c); - *minor = ret; - return GSS_S_FAILURE; - } - - ret = krb5_ntlm_alloc(c->context, &c->ntlm); - if (ret) { - kdc_destroy(&junk, c); - *minor = ret; - return GSS_S_FAILURE; - } - - *ctx = c; - - return GSS_S_COMPLETE; -} - -static int -kdc_probe(OM_uint32 *minor, void *ctx, const char *realm) -{ - struct ntlmkrb5 *c = ctx; - krb5_error_code ret; - unsigned flags; - - ret = krb5_digest_probe(c->context, rk_UNCONST(realm), c->id, &flags); - if (ret) - return ret; - - if ((flags & (1|2|4)) == 0) - return EINVAL; - - return 0; -} - -/* - * - */ - -static OM_uint32 -kdc_destroy(OM_uint32 *minor, void *ctx) -{ - struct ntlmkrb5 *c = ctx; - krb5_data_free(&c->opaque); - krb5_data_free(&c->sessionkey); - if (c->ntlm) - krb5_ntlm_free(c->context, c->ntlm); - if (c->id) { - if (c->destroy) - krb5_cc_destroy(c->context, c->id); - else - krb5_cc_close(c->context, c->id); - } - if (c->context) - krb5_free_context(c->context); - memset(c, 0, sizeof(*c)); - free(c); - - return GSS_S_COMPLETE; -} - -/* - * - */ - -static OM_uint32 -kdc_type2(OM_uint32 *minor_status, - void *ctx, - uint32_t flags, - const char *hostname, - const char *domain, - uint32_t *ret_flags, - struct ntlm_buf *out) -{ - struct ntlmkrb5 *c = ctx; - krb5_error_code ret; - struct ntlm_type2 type2; - krb5_data challenge; - struct ntlm_buf data; - krb5_data ti; - - memset(&type2, 0, sizeof(type2)); - memset(out, 0, sizeof(*out)); - - /* - * Request data for type 2 packet from the KDC. - */ - ret = krb5_ntlm_init_request(c->context, - c->ntlm, - NULL, - c->id, - flags, - hostname, - domain); - if (ret) { - *minor_status = ret; - return GSS_S_FAILURE; - } - - /* - * - */ - - ret = krb5_ntlm_init_get_opaque(c->context, c->ntlm, &c->opaque); - if (ret) { - *minor_status = ret; - return GSS_S_FAILURE; - } - - /* - * - */ - - ret = krb5_ntlm_init_get_flags(c->context, c->ntlm, &type2.flags); - if (ret) { - *minor_status = ret; - return GSS_S_FAILURE; - } - *ret_flags = type2.flags; - - ret = krb5_ntlm_init_get_challenge(c->context, c->ntlm, &challenge); - if (ret) { - *minor_status = ret; - return GSS_S_FAILURE; - } - - if (challenge.length != sizeof(type2.challenge)) { - *minor_status = EINVAL; - return GSS_S_FAILURE; - } - memcpy(type2.challenge, challenge.data, sizeof(type2.challenge)); - krb5_data_free(&challenge); - - ret = krb5_ntlm_init_get_targetname(c->context, c->ntlm, - &type2.targetname); - if (ret) { - *minor_status = ret; - return GSS_S_FAILURE; - } - - ret = krb5_ntlm_init_get_targetinfo(c->context, c->ntlm, &ti); - if (ret) { - free(type2.targetname); - *minor_status = ret; - return GSS_S_FAILURE; - } - - type2.targetinfo.data = ti.data; - type2.targetinfo.length = ti.length; - - ret = heim_ntlm_encode_type2(&type2, &data); - free(type2.targetname); - krb5_data_free(&ti); - if (ret) { - *minor_status = ret; - return GSS_S_FAILURE; - } - - out->data = data.data; - out->length = data.length; - - return GSS_S_COMPLETE; -} - -/* - * - */ - -static OM_uint32 -kdc_type3(OM_uint32 *minor_status, - void *ctx, - const struct ntlm_type3 *type3, - struct ntlm_buf *sessionkey) -{ - struct ntlmkrb5 *c = ctx; - krb5_error_code ret; - - sessionkey->data = NULL; - sessionkey->length = 0; - - ret = krb5_ntlm_req_set_flags(c->context, c->ntlm, type3->flags); - if (ret) goto out; - ret = krb5_ntlm_req_set_username(c->context, c->ntlm, type3->username); - if (ret) goto out; - ret = krb5_ntlm_req_set_targetname(c->context, c->ntlm, - type3->targetname); - if (ret) goto out; - ret = krb5_ntlm_req_set_lm(c->context, c->ntlm, - type3->lm.data, type3->lm.length); - if (ret) goto out; - ret = krb5_ntlm_req_set_ntlm(c->context, c->ntlm, - type3->ntlm.data, type3->ntlm.length); - if (ret) goto out; - ret = krb5_ntlm_req_set_opaque(c->context, c->ntlm, &c->opaque); - if (ret) goto out; - - if (type3->sessionkey.length) { - ret = krb5_ntlm_req_set_session(c->context, c->ntlm, - type3->sessionkey.data, - type3->sessionkey.length); - if (ret) goto out; - } - - /* - * Verify with the KDC the type3 packet is ok - */ - ret = krb5_ntlm_request(c->context, - c->ntlm, - NULL, - c->id); - if (ret) - goto out; - - if (krb5_ntlm_rep_get_status(c->context, c->ntlm) != TRUE) { - ret = EINVAL; - goto out; - } - - if (type3->sessionkey.length) { - ret = krb5_ntlm_rep_get_sessionkey(c->context, - c->ntlm, - &c->sessionkey); - if (ret) - goto out; - - sessionkey->data = c->sessionkey.data; - sessionkey->length = c->sessionkey.length; - } - - return 0; - - out: - *minor_status = ret; - return GSS_S_FAILURE; -} - -/* - * - */ - -static void -kdc_free_buffer(struct ntlm_buf *sessionkey) -{ - if (sessionkey->data) - free(sessionkey->data); - sessionkey->data = NULL; - sessionkey->length = 0; -} - -/* - * - */ - -struct ntlm_server_interface ntlmsspi_kdc_digest = { - kdc_alloc, - kdc_destroy, - kdc_probe, - kdc_type2, - kdc_type3, - kdc_free_buffer -}; - -#endif /* DIGEST */ diff --git a/lib/gssapi/ntlm/ntlm.h b/lib/gssapi/ntlm/ntlm.h deleted file mode 100644 index 170ea3496..000000000 --- a/lib/gssapi/ntlm/ntlm.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (c) 2006-2018 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 NTLM_NTLM_H -#define NTLM_NTLM_H - -#include - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include "crypto-headers.h" - -typedef OM_uint32 -(*ntlm_interface_init)(OM_uint32 *, void **); - -typedef OM_uint32 -(*ntlm_interface_destroy)(OM_uint32 *, void *); - -typedef int -(*ntlm_interface_probe)(OM_uint32 *, void *, const char *); - -typedef OM_uint32 -(*ntlm_interface_type2)(OM_uint32 *, void *, uint32_t, const char *, - const char *, uint32_t *, struct ntlm_buf *); - -typedef OM_uint32 -(*ntlm_interface_type3)(OM_uint32 *, void *, const struct ntlm_type3 *, - struct ntlm_buf *); - -typedef void -(*ntlm_interface_free_buffer)(struct ntlm_buf *); - -struct ntlm_server_interface { - ntlm_interface_init nsi_init; - ntlm_interface_destroy nsi_destroy; - ntlm_interface_probe nsi_probe; - ntlm_interface_type2 nsi_type2; - ntlm_interface_type3 nsi_type3; - ntlm_interface_free_buffer nsi_free_buffer; -}; - - -struct ntlmv2_key { - uint32_t seq; - RC4_KEY sealkey; - RC4_KEY *signsealkey; - unsigned char signkey[16]; -}; - -extern struct ntlm_server_interface ntlmsspi_kdc_digest; - -typedef struct ntlm_cred { - gss_cred_usage_t usage; - char *username; - char *domain; - struct ntlm_buf key; -} *ntlm_cred; -typedef const struct ntlm_cred *ntlm_const_cred; - -typedef struct { - struct ntlm_server_interface *server; - void *ictx; - ntlm_cred client; - OM_uint32 gssflags; - uint32_t kcmflags; - uint32_t flags; - uint32_t status; -#define STATUS_OPEN 1 -#define STATUS_CLIENT 2 -#define STATUS_SESSIONKEY 4 - krb5_data sessionkey; - - gss_buffer_desc pac; - - union { - struct { - struct { - uint32_t seq; - RC4_KEY key; - } crypto_send, crypto_recv; - } v1; - struct { - struct ntlmv2_key send, recv; - } v2; - } u; -} *ntlm_ctx; - -typedef struct { - char *user; - char *domain; -} *ntlm_name; - -#include - - -#endif /* NTLM_NTLM_H */ diff --git a/lib/gssapi/ntlm/process_context_token.c b/lib/gssapi/ntlm/process_context_token.c deleted file mode 100644 index 2add53b6d..000000000 --- a/lib/gssapi/ntlm/process_context_token.c +++ /dev/null @@ -1,44 +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 "ntlm.h" - -OM_uint32 GSSAPI_CALLCONV _gss_ntlm_process_context_token ( - OM_uint32 *minor_status, - gss_const_ctx_id_t context_handle, - const gss_buffer_t token_buffer - ) -{ - *minor_status = 0; - return GSS_S_COMPLETE; -} diff --git a/lib/gssapi/ntlm/release_cred.c b/lib/gssapi/ntlm/release_cred.c deleted file mode 100644 index e31a31611..000000000 --- a/lib/gssapi/ntlm/release_cred.c +++ /dev/null @@ -1,66 +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 "ntlm.h" - -OM_uint32 GSSAPI_CALLCONV _gss_ntlm_release_cred - (OM_uint32 * minor_status, - gss_cred_id_t * cred_handle - ) -{ - ntlm_cred cred; - - if (minor_status) - *minor_status = 0; - - if (cred_handle == NULL || *cred_handle == GSS_C_NO_CREDENTIAL) - return GSS_S_COMPLETE; - - cred = (ntlm_cred)*cred_handle; - *cred_handle = GSS_C_NO_CREDENTIAL; - - if (cred->username) - free(cred->username); - if (cred->domain) - free(cred->domain); - if (cred->key.data) { - memset(cred->key.data, 0, cred->key.length); - free(cred->key.data); - } - - memset(cred, 0, sizeof(*cred)); - free(cred); - - return GSS_S_COMPLETE; -} - diff --git a/lib/gssapi/ntlm/release_name.c b/lib/gssapi/ntlm/release_name.c deleted file mode 100644 index 4a5c56d3d..000000000 --- a/lib/gssapi/ntlm/release_name.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "ntlm.h" - -OM_uint32 GSSAPI_CALLCONV -_gss_ntlm_release_name - (OM_uint32 * minor_status, - gss_name_t * input_name - ) -{ - if (minor_status) - *minor_status = 0; - if (input_name && *input_name) { - ntlm_name n = (ntlm_name)*input_name; - *input_name = GSS_C_NO_NAME; - free(n->user); - free(n->domain); - free(n); - } - return GSS_S_COMPLETE; -} diff --git a/lib/gssapi/ntlm/set_sec_context_option.c b/lib/gssapi/ntlm/set_sec_context_option.c deleted file mode 100644 index f97443d9e..000000000 --- a/lib/gssapi/ntlm/set_sec_context_option.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2006 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Portions Copyright (c) 2009 Apple Inc. 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 "ntlm.h" - -OM_uint32 GSSAPI_CALLCONV -_gss_ntlm_set_sec_context_option(OM_uint32 *minor_status, - gss_ctx_id_t *context_handle, - const gss_OID object, - const gss_buffer_t value) -{ - ntlm_ctx ctx; - - if (context_handle == NULL) - return GSS_S_UNAVAILABLE; - - *minor_status = 0; - - ctx = (ntlm_ctx)*context_handle; - if (ctx == NULL) - return GSS_S_NO_CONTEXT; - - if (gss_oid_equal(object, GSS_C_NTLM_RESET_CRYPTO)) { - _gss_ntlm_set_keys(ctx); - return GSS_S_COMPLETE; - } else - return GSS_S_UNAVAILABLE; -} diff --git a/lib/gssapi/sanon/crypto.c b/lib/gssapi/sanon/crypto.c index 0c7a67f70..298fb411f 100644 --- a/lib/gssapi/sanon/crypto.c +++ b/lib/gssapi/sanon/crypto.c @@ -220,14 +220,44 @@ _gss_sanon_pseudo_random(OM_uint32 *minor, OM_uint32 _gss_sanon_curve25519_base(OM_uint32 *minor, sanon_ctx sc) { - krb5_generate_random_block(sc->sk, crypto_scalarmult_curve25519_BYTES); + OM_uint32 maj = GSS_S_FAILURE; + krb5_context context; + EVP_PKEY_CTX *kctx = NULL; + EVP_PKEY *pkey = NULL; + size_t pklen = X25519_LEN, sklen = X25519_LEN; - if (crypto_scalarmult_curve25519_base(sc->pk, sc->sk) != 0) { - *minor = EINVAL; - return GSS_S_FAILURE; + if (krb5_init_context(&context)) { + *minor = ENOMEM; + return GSS_S_FAILURE; } - return GSS_S_COMPLETE; + /* Create an X25519 keypair */ + kctx = EVP_PKEY_CTX_new_from_name(context->ossl->libctx, "X25519", + context->ossl->propq); + if (kctx == NULL || + EVP_PKEY_keygen_init(kctx) <= 0 || + EVP_PKEY_keygen(kctx, &pkey) <= 0) { + EVP_PKEY_CTX_free(kctx); + krb5_free_context(context); + *minor = ENOMEM; // XXX + return GSS_S_FAILURE; + } + + /* Export raw public & private (32 bytes each) into sc->pk / sc->sk */ + if (EVP_PKEY_get_raw_public_key(pkey, sc->pk, &pklen) != 1 || + pklen != X25519_LEN || + EVP_PKEY_get_raw_private_key(pkey, sc->sk, &sklen) != 1 || + sklen != X25519_LEN) { + *minor = EINVAL; // XXX + } else { + *minor = 0; + maj = GSS_S_COMPLETE; + } + + EVP_PKEY_free(pkey); + EVP_PKEY_CTX_free(kctx); + krb5_free_context(context); + return maj; } /* @@ -243,25 +273,59 @@ _gss_sanon_curve25519(OM_uint32 *minor, const gss_channel_bindings_t input_chan_bindings, gss_buffer_t session_key) { - uint8_t shared[crypto_scalarmult_curve25519_BYTES], *p; + uint8_t shared[X25519_LEN], *p; + size_t shlen = X25519_LEN; krb5_error_code ret; krb5_context context; krb5_data kdf_K1, kdf_label, kdf_context, keydata; + EVP_PKEY *sk, *peer; + EVP_PKEY_CTX *dctx; _mg_buffer_zero(session_key); - if (pk == GSS_C_NO_BUFFER || pk->length != crypto_scalarmult_curve25519_BYTES) + if (pk == GSS_C_NO_BUFFER || pk->length != X25519_LEN) return GSS_S_DEFECTIVE_TOKEN; - if (crypto_scalarmult_curve25519(shared, sc->sk, pk->value) != 0) - return GSS_S_FAILURE; - ret = krb5_init_context(&context); if (ret != 0) { *minor = ret; return GSS_S_FAILURE; } + sk = EVP_PKEY_new_raw_private_key_ex(context->ossl->libctx, "X25519", + context->ossl->propq, sc->sk, + X25519_LEN); + peer = EVP_PKEY_new_raw_public_key_ex(context->ossl->libctx, "X25519", + context->ossl->propq, + (const unsigned char *)pk->value, + X25519_LEN); + if (sk == NULL || peer == NULL) { + *minor = EINVAL; + EVP_PKEY_free(sk); + krb5_free_context(context); + return GSS_S_FAILURE; + } + + dctx = EVP_PKEY_CTX_new_from_pkey(context->ossl->libctx, sk, + context->ossl->propq); + if (dctx == NULL || + EVP_PKEY_derive_init(dctx) != 1 || + EVP_PKEY_derive_set_peer(dctx, peer) != 1 || + EVP_PKEY_derive(dctx, shared, &shlen) != 1 || + shlen != X25519_LEN) + { + *minor = EINVAL; + EVP_PKEY_CTX_free(dctx); + EVP_PKEY_free(peer); + EVP_PKEY_free(sk); + krb5_free_context(context); + return GSS_S_FAILURE; + } + + EVP_PKEY_CTX_free(dctx); + EVP_PKEY_free(peer); + EVP_PKEY_free(sk); + kdf_K1.data = shared; kdf_K1.length = sizeof(shared); @@ -269,7 +333,7 @@ _gss_sanon_curve25519(OM_uint32 *minor, kdf_label.length = sizeof("sanon-x25519") - 1; ret = krb5_data_alloc(&kdf_context, - 2 * crypto_scalarmult_curve25519_BYTES + 8 + + 2 * X25519_LEN + 8 + (input_chan_bindings ? input_chan_bindings->application_data.length : 0)); if (ret != 0) { krb5_free_context(context); diff --git a/lib/gssapi/sanon/sanon_locl.h b/lib/gssapi/sanon/sanon_locl.h index 08ad82994..9f8577d24 100644 --- a/lib/gssapi/sanon/sanon_locl.h +++ b/lib/gssapi/sanon/sanon_locl.h @@ -36,14 +36,14 @@ #include /* for _krb5_SP800_108_HMAC_KDF() */ -/* XXX Use OpenSSL 3.x */ -#include - #include #include /* for GSS_KRB5_S_XXX */ #include "mech/mech_locl.h" +#define crypto_scalarmult_curve25519_BYTES 32 +#define X25519_LEN 32 + typedef struct sanon_ctx_desc { /* X25519 ECDH secret key */ uint8_t sk[crypto_scalarmult_curve25519_BYTES]; diff --git a/lib/gssapi/test_context.c b/lib/gssapi/test_context.c index d2d37d3c6..c7bc42c14 100644 --- a/lib/gssapi/test_context.c +++ b/lib/gssapi/test_context.c @@ -37,7 +37,6 @@ #include #include #include -#include #include "test_common.h" #ifdef NOTYET @@ -1101,27 +1100,6 @@ main(int argc, char **argv) mechoid = string_to_oid(mech_string); if (mechs_string == NULL) { - /* - * We ought to be able to use the OID set of the one mechanism - * OID given. But there's some breakage that conspires to make - * that fail though it should succeed: - * - * - the NTLM gss_acquire_cred() refuses to work with - * desired_name == GSS_C_NO_NAME - * - gss_acquire_cred() with desired_mechs == GSS_C_NO_OID_SET - * does work here because we happen to have Kerberos - * credentials in check-ntlm, and the subsequent - * gss_init_sec_context() call finds no cred element for NTLM - * but plows on anyways, surprisingly enough, and then the - * NTLM gss_init_sec_context() just works. - * - * In summary, there's some breakage in gss_init_sec_context() - * and some breakage in NTLM that conspires against us here. - * - * We work around this in check-ntlm and check-spnego by adding - * --client-name=user1@${R} to the invocations of this test - * program that require it. - */ oids[0] = *mechoid; mechoid_descs.elements = &oids[0]; mechoid_descs.count = 1; diff --git a/lib/gssapi/test_ntlm.c b/lib/gssapi/test_ntlm.c deleted file mode 100644 index de3a8dd88..000000000 --- a/lib/gssapi/test_ntlm.c +++ /dev/null @@ -1,337 +0,0 @@ -/* - * Copyright (c) 2006 - 2008 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of KTH nor the names of its contributors may be - * used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include "test_common.h" - -#include -#include - -static int -test_libntlm_v1(int flags) -{ - const char *user = "foo", - *domain = "mydomain", - *password = "digestpassword"; - OM_uint32 maj_stat, min_stat; - gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; - gss_buffer_desc input, output; - struct ntlm_type1 type1; - struct ntlm_type2 type2; - struct ntlm_type3 type3; - struct ntlm_buf data; - krb5_error_code ret; - gss_name_t src_name = GSS_C_NO_NAME; - - memset(&type1, 0, sizeof(type1)); - memset(&type2, 0, sizeof(type2)); - memset(&type3, 0, sizeof(type3)); - - type1.flags = NTLM_NEG_UNICODE|NTLM_NEG_TARGET|NTLM_NEG_NTLM|flags; - type1.domain = strdup(domain); - type1.hostname = NULL; - type1.os[0] = 0; - type1.os[1] = 0; - - ret = heim_ntlm_encode_type1(&type1, &data); - if (ret) - errx(1, "heim_ntlm_encode_type1"); - - input.value = data.data; - input.length = data.length; - - output.length = 0; - output.value = NULL; - - maj_stat = gss_accept_sec_context(&min_stat, - &ctx, - GSS_C_NO_CREDENTIAL, - &input, - GSS_C_NO_CHANNEL_BINDINGS, - NULL, - NULL, - &output, - NULL, - NULL, - NULL); - free(data.data); - if (GSS_ERROR(maj_stat)) - errx(1, "accept_sec_context v1: %s", - gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); - - if (output.length == 0) - errx(1, "output.length == 0"); - - data.data = output.value; - data.length = output.length; - - ret = heim_ntlm_decode_type2(&data, &type2); - if (ret) - errx(1, "heim_ntlm_decode_type2"); - - gss_release_buffer(&min_stat, &output); - - type3.flags = type2.flags; - type3.username = rk_UNCONST(user); - type3.targetname = type2.targetname; - type3.ws = rk_UNCONST("workstation"); - - { - struct ntlm_buf key; - - heim_ntlm_nt_key(password, &key); - - heim_ntlm_calculate_ntlm1(key.data, key.length, - type2.challenge, - &type3.ntlm); - - if (flags & NTLM_NEG_KEYEX) { - struct ntlm_buf sessionkey; - heim_ntlm_build_ntlm1_master(key.data, key.length, - &sessionkey, - &type3.sessionkey); - free(sessionkey.data); - } - free(key.data); - } - - ret = heim_ntlm_encode_type3(&type3, &data, NULL); - if (ret) - errx(1, "heim_ntlm_encode_type3"); - - input.length = data.length; - input.value = data.data; - - maj_stat = gss_accept_sec_context(&min_stat, - &ctx, - GSS_C_NO_CREDENTIAL, - &input, - GSS_C_NO_CHANNEL_BINDINGS, - &src_name, - NULL, - &output, - NULL, - NULL, - NULL); - free(input.value); - if (maj_stat != GSS_S_COMPLETE) - errx(1, "accept_sec_context v1 2 %s", - gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); - - gss_release_buffer(&min_stat, &output); - gss_delete_sec_context(&min_stat, &ctx, NULL); - - if (src_name == GSS_C_NO_NAME) - errx(1, "no source name!"); - - gss_display_name(&min_stat, src_name, &output, NULL); - - printf("src_name: %.*s\n", (int)output.length, (char*)output.value); - - gss_release_name(&min_stat, &src_name); - gss_release_buffer(&min_stat, &output); - - return 0; -} - -static int -test_libntlm_v2(int flags) -{ - const char *user = "foo", - *domain = "mydomain", - *password = "digestpassword"; - OM_uint32 maj_stat, min_stat; - gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; - gss_buffer_desc input, output; - struct ntlm_type1 type1; - struct ntlm_type2 type2; - struct ntlm_type3 type3; - struct ntlm_buf data; - krb5_error_code ret; - - memset(&type1, 0, sizeof(type1)); - memset(&type2, 0, sizeof(type2)); - memset(&type3, 0, sizeof(type3)); - - type1.flags = NTLM_NEG_UNICODE|NTLM_NEG_NTLM|flags; - type1.domain = strdup(domain); - type1.hostname = NULL; - type1.os[0] = 0; - type1.os[1] = 0; - - ret = heim_ntlm_encode_type1(&type1, &data); - if (ret) - errx(1, "heim_ntlm_encode_type1"); - - input.value = data.data; - input.length = data.length; - - output.length = 0; - output.value = NULL; - - maj_stat = gss_accept_sec_context(&min_stat, - &ctx, - GSS_C_NO_CREDENTIAL, - &input, - GSS_C_NO_CHANNEL_BINDINGS, - NULL, - NULL, - &output, - NULL, - NULL, - NULL); - free(data.data); - if (GSS_ERROR(maj_stat)) - errx(1, "accept_sec_context v2 %s", - gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); - - if (output.length == 0) - errx(1, "output.length == 0"); - - data.data = output.value; - data.length = output.length; - - ret = heim_ntlm_decode_type2(&data, &type2); - if (ret) - errx(1, "heim_ntlm_decode_type2"); - - type3.flags = type2.flags; - type3.username = rk_UNCONST(user); - type3.targetname = type2.targetname; - type3.ws = rk_UNCONST("workstation"); - - { - struct ntlm_buf key; - unsigned char ntlmv2[16]; - - heim_ntlm_nt_key(password, &key); - - heim_ntlm_calculate_ntlm2(key.data, key.length, - user, - type2.targetname, - type2.challenge, - &type2.targetinfo, - ntlmv2, - &type3.ntlm); - free(key.data); - - if (flags & NTLM_NEG_KEYEX) { - struct ntlm_buf sessionkey; - heim_ntlm_build_ntlm1_master(ntlmv2, sizeof(ntlmv2), - &sessionkey, - &type3.sessionkey); - free(sessionkey.data); - } - } - - ret = heim_ntlm_encode_type3(&type3, &data, NULL); - if (ret) - errx(1, "heim_ntlm_encode_type3"); - - input.length = data.length; - input.value = data.data; - - maj_stat = gss_accept_sec_context(&min_stat, - &ctx, - GSS_C_NO_CREDENTIAL, - &input, - GSS_C_NO_CHANNEL_BINDINGS, - NULL, - NULL, - &output, - NULL, - NULL, - NULL); - free(input.value); - if (maj_stat != GSS_S_COMPLETE) - errx(1, "accept_sec_context v2 2 %s", - gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); - - gss_delete_sec_context(&min_stat, &ctx, NULL); - - return 0; -} - - - -static int version_flag = 0; -static int help_flag = 0; - -static struct getargs args[] = { - {"version", 0, arg_flag, &version_flag, "print version", NULL }, - {"help", 0, arg_flag, &help_flag, NULL, NULL } -}; - -static void -usage (int ret) -{ - arg_printusage (args, sizeof(args)/sizeof(*args), - NULL, ""); - exit (ret); -} - -int -main(int argc, char **argv) -{ - int ret = 0, optidx = 0; - - setprogname(argv[0]); - - if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) - usage(1); - - if (help_flag) - usage (0); - - if(version_flag){ - print_version(NULL); - exit(0); - } - - argc -= optidx; - argv += optidx; - - ret += test_libntlm_v1(0); - ret += test_libntlm_v1(NTLM_NEG_KEYEX); - - ret += test_libntlm_v2(0); - ret += test_libntlm_v2(NTLM_NEG_KEYEX); - - return ret; -} diff --git a/lib/hdb/Makefile.am b/lib/hdb/Makefile.am index b23d08dbc..6fae72a4e 100644 --- a/lib/hdb/Makefile.am +++ b/lib/hdb/Makefile.am @@ -170,5 +170,5 @@ EXTRA_DIST = \ hdb_err.et \ hdb.schema \ version-script.map \ - data-mkey.mit.des3.le \ - data-mkey.mit.des3.be + data-mkey.mit.aes256.le \ + data-mkey.mit.aes256.be diff --git a/lib/hdb/data-mkey.mit.aes256.be b/lib/hdb/data-mkey.mit.aes256.be new file mode 100644 index 0000000000000000000000000000000000000000..1a32d583650434b42205a043dce8b632cf711431 GIT binary patch literal 38 OcmZP&VqjoUAOrwN-~=-O literal 0 HcmV?d00001 diff --git a/lib/hdb/data-mkey.mit.aes256.le b/lib/hdb/data-mkey.mit.aes256.le new file mode 100644 index 0000000000000000000000000000000000000000..943f8ae020d4f10380247eceddcd62cbf0b7e63c GIT binary patch literal 38 PcmWe)P+(wSP#^#RNm2we literal 0 HcmV?d00001 diff --git a/lib/hdb/data-mkey.mit.des3.be b/lib/hdb/data-mkey.mit.des3.be deleted file mode 100644 index 4278ed339e520328e37626f1c42e785c5264a243..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 46 QcmZP&U|?X7P#_Wj0Bu$UDF6Tf diff --git a/lib/hdb/data-mkey.mit.des3.le b/lib/hdb/data-mkey.mit.des3.le deleted file mode 100644 index 19fdc93b40d485d6e258692f6e9becfee489b691..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30 PcmWe&kYHe7P{08IDjowV diff --git a/lib/heimdal/NTMakefile b/lib/heimdal/NTMakefile index 15a580c81..685c5b01a 100644 --- a/lib/heimdal/NTMakefile +++ b/lib/heimdal/NTMakefile @@ -43,8 +43,6 @@ DLLDEPS= \ $(LIBROKEN) \ $(LIBSQLITE) \ $(LIBWIND) \ - $(LIBLTM) \ - $(LIBX25519) \ $(LIBHEIMBASE) DLLSDKDEPS= \ diff --git a/lib/hx509/Makefile.am b/lib/hx509/Makefile.am index 832d339b8..e647a3e18 100644 --- a/lib/hx509/Makefile.am +++ b/lib/hx509/Makefile.am @@ -124,6 +124,7 @@ $(hxtool_OBJECTS): hxtool-commands.h $(nodist_include_HEADERS) hxtool_LDADD = \ libhx509template.la \ $(top_builddir)/lib/asn1/libasn1.la \ + $(LIB_openssl_crypto) \ $(LIB_roken) \ $(top_builddir)/lib/sl/libsl.la @@ -175,10 +176,10 @@ SCRIPT_TESTS = \ test_crypto \ test_nist \ test_nist2 \ - test_pkcs11 \ test_java_pkcs11 \ test_nist_cert \ test_nist_pkcs12 \ + test_pkcs12_pbes2 \ test_req \ test_windows \ test_query @@ -242,6 +243,11 @@ test_nist_pkcs12: test_nist_pkcs12.in Makefile $(heim_verbose)chmod +x test_nist_pkcs12.tmp mv test_nist_pkcs12.tmp test_nist_pkcs12 +test_pkcs12_pbes2: test_pkcs12_pbes2.in Makefile + $(do_subst) < $(srcdir)/test_pkcs12_pbes2.in > test_pkcs12_pbes2.tmp + $(heim_verbose)chmod +x test_pkcs12_pbes2.tmp + mv test_pkcs12_pbes2.tmp test_pkcs12_pbes2 + test_req: test_req.in Makefile $(do_subst) < $(srcdir)/test_req.in > test_req.tmp $(heim_verbose)chmod +x test_req.tmp @@ -274,6 +280,7 @@ EXTRA_DIST = \ test_nist2.in \ test_nist_cert.in \ test_nist_pkcs12.in \ + test_pkcs12_pbes2.in \ test_pkcs11.in \ test_java_pkcs11.in \ test_query.in \ diff --git a/lib/hx509/cert.c b/lib/hx509/cert.c index 9c7997dc4..58b3b14c3 100644 --- a/lib/hx509/cert.c +++ b/lib/hx509/cert.c @@ -93,12 +93,263 @@ typedef struct hx509_name_constraints { #define GeneralSubtrees_SET(g,var) \ (g)->len = (var)->len, (g)->val = (var)->val; +/* + * OpenSSL provider management for hx509. + * + * We load both the default and legacy providers during context init: + * - default: needed for standard crypto (RSA, EC, AES, SHA, etc.) + * - legacy: needed for PKCS#12 weak crypto (RC2, 3DES-CBC, etc.) + * + * We also fetch and cache commonly used algorithms (EVP_MD, EVP_CIPHER) to + * avoid repeated fetching and to ensure proper cleanup. + * + * Note: In OpenSSL 3.x, explicitly loading any provider on the global context + * disables the auto-loading behavior, so we must explicitly load the default + * provider when we load the legacy provider. + * + * Contexts are cached globally in a singly-linked list keyed by (cnf, propq). + * This allows sharing across multiple hx509_context instances and avoids + * repeated algorithm fetching when propq is set to the same value. + */ + +/* Global cache of OpenSSL contexts, keyed by (cnf, propq) */ +static heim_base_atomic(hx509_context_ossl) cached_ossl_hx509; + +/* Helper to compare two nullable strings for equality */ +static int +str_equal(const char *a, const char *b) +{ + if (a == b) + return 1; + if (a == NULL || b == NULL) + return 0; + return strcmp(a, b) == 0; +} + +/* Check if an ossl context matches the given (cnf, propq) tuple */ +static int +ossl_matches(hx509_context_ossl p, const char *cnf, const char *propq) +{ + return str_equal(p->cnf, cnf) && str_equal(p->propq, propq); +} + +/* + * Create a new OpenSSL context with the given cnf and propq. + * Does not add to the global cache. + */ +static int +make_openssl_hx509(hx509_context context, + const char *cnf, + const char *propq, + hx509_context_ossl *osslp) +{ + hx509_context_ossl ossl; + + *osslp = NULL; + + if ((ossl = calloc(1, sizeof(*ossl))) == NULL) + return ENOMEM; + ossl->refs = 1; + + /* + * Use the global default library context. We could make this + * configurable via hx509.conf in the future if needed. + */ + ossl->libctx = OSSL_LIB_CTX_get0_global_default(); + + /* Store cnf and propq for cache lookup */ + if (cnf && (ossl->cnf = strdup(cnf)) == NULL) { + free(ossl); + return ENOMEM; + } + if (propq && (ossl->propq = strdup(propq)) == NULL) { + free(ossl->cnf); + free(ossl); + return ENOMEM; + } + + /* + * Load the default provider first - this is required because in OpenSSL + * 3.x, explicitly loading any provider disables auto-loading of the + * default provider. + */ + ossl->openssl_def = OSSL_PROVIDER_load(ossl->libctx, "default"); + + /* + * Load the legacy provider for PKCS#12 weak crypto support. + * This is needed for algorithms like RC2, 3DES-CBC, etc. that are + * commonly used in PKCS#12 files. + */ + ossl->openssl_leg = OSSL_PROVIDER_load(ossl->libctx, "legacy"); + + /* + * Fetch and cache message digests. + * We ignore failures here - the algorithms will be NULL if not available. + */ + ossl->md5 = EVP_MD_fetch(ossl->libctx, "MD5", ossl->propq); + ossl->sha1 = EVP_MD_fetch(ossl->libctx, "SHA1", ossl->propq); + ossl->sha256 = EVP_MD_fetch(ossl->libctx, "SHA256", ossl->propq); + ossl->sha384 = EVP_MD_fetch(ossl->libctx, "SHA384", ossl->propq); + ossl->sha512 = EVP_MD_fetch(ossl->libctx, "SHA512", ossl->propq); + + /* + * Fetch and cache ciphers - legacy (PKCS#12). + * These come from the legacy provider. + */ + ossl->rc2_40_cbc = EVP_CIPHER_fetch(ossl->libctx, "RC2-40-CBC", ossl->propq); + ossl->rc2_64_cbc = EVP_CIPHER_fetch(ossl->libctx, "RC2-64-CBC", ossl->propq); + ossl->rc2_cbc = EVP_CIPHER_fetch(ossl->libctx, "RC2-CBC", ossl->propq); + ossl->rc4_40 = EVP_CIPHER_fetch(ossl->libctx, "RC4-40", ossl->propq); + ossl->rc4 = EVP_CIPHER_fetch(ossl->libctx, "RC4", ossl->propq); + ossl->des_ede3_cbc = EVP_CIPHER_fetch(ossl->libctx, "DES-EDE3-CBC", ossl->propq); + + /* + * Fetch and cache ciphers - standard. + */ + ossl->aes_128_cbc = EVP_CIPHER_fetch(ossl->libctx, "AES-128-CBC", ossl->propq); + ossl->aes_192_cbc = EVP_CIPHER_fetch(ossl->libctx, "AES-192-CBC", ossl->propq); + ossl->aes_256_cbc = EVP_CIPHER_fetch(ossl->libctx, "AES-256-CBC", ossl->propq); + + *osslp = ossl; + return 0; +} + +static void +free_openssl_hx509(hx509_context_ossl *osslp) +{ + hx509_context_ossl p = *osslp; + + *osslp = NULL; + if (p == NULL) + return; + + /* Decrement refcount; only free if we're the last reference */ + if (heim_base_atomic_dec_32(&p->refs) != 0) + return; + + /* Free fetched message digests */ + EVP_MD_free(p->md5); + EVP_MD_free(p->sha1); + EVP_MD_free(p->sha256); + EVP_MD_free(p->sha384); + EVP_MD_free(p->sha512); + + /* Free fetched ciphers - legacy */ + EVP_CIPHER_free(p->rc2_40_cbc); + EVP_CIPHER_free(p->rc2_64_cbc); + EVP_CIPHER_free(p->rc2_cbc); + EVP_CIPHER_free(p->rc4_40); + EVP_CIPHER_free(p->rc4); + EVP_CIPHER_free(p->des_ede3_cbc); + + /* Free fetched ciphers - standard */ + EVP_CIPHER_free(p->aes_128_cbc); + EVP_CIPHER_free(p->aes_192_cbc); + EVP_CIPHER_free(p->aes_256_cbc); + + /* Unload providers */ + if (p->openssl_leg) + OSSL_PROVIDER_unload(p->openssl_leg); + if (p->openssl_def) + OSSL_PROVIDER_unload(p->openssl_def); + + /* Note: we don't free libctx if it's the global default */ + free(p->cnf); + free(p->propq); + free(p); +} + +/* + * Look up or create an OpenSSL context with the given propq. + * The cnf comes from the hx509.conf config file. + * Contexts are cached globally and shared via refcounting. + */ +static int +init_openssl_hx509_with_propq(hx509_context context, + const char *cnf, + const char *propq, + hx509_context_ossl *osslp) +{ + hx509_context_ossl first, p, ossl; + int ret; + int done = 0; + + *osslp = NULL; + + /* + * Ensure that all writes to the list are visible to us before we + * dereference the members of the list. + */ + first = heim_base_atomic_load(&cached_ossl_hx509); + heim_base_consumer_barrier(); + for (p = first; p; p = p->next) { + if (ossl_matches(p, cnf, propq)) { + (void) heim_base_atomic_inc_32(&p->refs); + *osslp = p; + return 0; + } + } + + /* Not found in cache, create a new one */ + ret = make_openssl_hx509(context, cnf, propq, &ossl); + if (ret) + return ret; + + /* Finish all stores before we publish */ + heim_base_producer_barrier(); + + while (!done) { + hx509_context_ossl old = first; + + /* Try to publish */ + ossl->next = first; + if ((old = heim_base_cas_pointer((void *)&cached_ossl_hx509, + first, ossl)) == first) { + /* + * Published! Take one more ref for the reference from the global + * list. + */ + heim_base_consumer_barrier(); + (void) heim_base_atomic_inc_32(&ossl->refs); + *osslp = ossl; + return 0; + } + heim_base_consumer_barrier(); + + /* Lost a race; try again */ + first = old; + ossl->next = first; + for (p = first; p; p = p->next) { + if (ossl_matches(p, cnf, propq)) { + (void) heim_base_atomic_inc_32(&p->refs); + *osslp = p; + free_openssl_hx509(&ossl); /* Found a better one */ + return 0; + } + } + /* Did not find a better one, so try to publish again */ + } + return 0; +} + +static int +init_openssl_hx509(hx509_context context, hx509_context_ossl *osslp) +{ + const char *cnf = + heim_config_get_string_default(context->hcontext, context->cf, + secure_getenv("HX509_OPENSSL_CNF"), + "libdefaults", "openssl_cnf", + NULL); + const char *propq = + heim_config_get_string_default(context->hcontext, context->cf, + secure_getenv("HX509_OPENSSL_PROPQ"), + "libdefaults", "openssl_propq", NULL); + return init_openssl_hx509_with_propq(context, cnf, propq, osslp); +} + static void init_context_once(void *ignored) { - - ENGINE_add_conf_module(); - OpenSSL_add_all_algorithms(); } /** @@ -201,6 +452,15 @@ hx509_context_init(hx509_context *contextp) initialize_hx_error_table_r(&context->et_list); initialize_asn1_error_table_r(&context->et_list); + /* Initialize OpenSSL provider context (legacy provider for PKCS#12) */ + if ((ret = init_openssl_hx509(context, &context->ossl))) { + free_error_table(context->et_list); + heim_config_file_free(context->hcontext, context->cf); + heim_context_free(&context->hcontext); + free(context); + return ret; + } + #ifdef HX509_DEFAULT_ANCHORS anchors = heim_config_get_string_default(context->hcontext, context->cf, HX509_DEFAULT_ANCHORS, @@ -257,6 +517,52 @@ hx509_context_set_missing_revoke(hx509_context context, int flag) context->flags &= ~HX509_CTX_VERIFY_MISSING_OK; } +/** + * Set the OpenSSL configuration and/or property query string for algorithm + * fetching. + * + * This allows selecting specific provider implementations (e.g., "fips=yes") + * and amortizes the cost of OpenSSL algorithm "fetching". + * + * This function looks up or creates an OpenSSL context with the specified + * propq and re-fetches all algorithms using that propq. Contexts are cached + * globally and shared via refcounting. + * + * This must be called after hx509_context_init() and before any cryptographic + * operations using the resulting context. + * + * @param context hx509 context + * @param cnf OpenSSL configuration file (NULL for OpenSSL default) + * @param propq OpenSSL property query string (NULL for OpenSSL default) + * + * @return 0 on success, ENOMEM on allocation failure + * + * @ingroup hx509 + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_context_set_ossl_cnf_propq(hx509_context context, + const char *cnf, + const char *propq) +{ + hx509_context_ossl new_ossl = NULL; + int ret; + + if (context == NULL) + return EINVAL; + + /* Look up or create a cached OpenSSL context with the new propq */ + ret = init_openssl_hx509_with_propq(context, cnf, propq, &new_ossl); + if (ret) + return ret; + + /* Release the old context and use the new one */ + free_openssl_hx509(&context->ossl); + context->ossl = new_ossl; + + return 0; +} + /** * Free the context allocated by hx509_context_init(). * @@ -281,6 +587,7 @@ hx509_context_free(hx509_context *context) if ((*context)->querystat) free((*context)->querystat); hx509_certs_free(&(*context)->default_trust_anchors); + free_openssl_hx509(&(*context)->ossl); heim_config_file_free((*context)->hcontext, (*context)->cf); heim_context_free(&(*context)->hcontext); memset(*context, 0, sizeof(**context)); @@ -2722,7 +3029,7 @@ hx509_verify_signature(hx509_context context, const heim_octet_string *data, const heim_octet_string *sig) { - return _hx509_verify_signature(context, signer, alg, data, sig); + return _hx509_verify_signature(context, signer, alg, NULL, data, sig); } HX509_LIB_FUNCTION int HX509_LIB_CALL @@ -2743,7 +3050,7 @@ _hx509_verify_signature_bitstring(hx509_context context, os.data = sig->data; os.length = sig->length / 8; - return _hx509_verify_signature(context, signer, alg, data, &os); + return _hx509_verify_signature(context, signer, alg, NULL, data, &os); } @@ -3245,6 +3552,42 @@ hx509_query_match_cmp_func(hx509_query *q, return 0; } +/** + * Set the query controller to match certificates with the specified + * public key algorithm. + * + * @param q a hx509 query controller + * @param oid the public key algorithm OID to match, or NULL to clear + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ + +HX509_LIB_FUNCTION int HX509_LIB_CALL +hx509_query_match_key_algorithm(hx509_query *q, const heim_oid *oid) +{ + if (q->key_alg) { + der_free_oid(q->key_alg); + free(q->key_alg); + q->key_alg = NULL; + } + if (oid) { + q->key_alg = malloc(sizeof(*q->key_alg)); + if (q->key_alg == NULL) + return ENOMEM; + if (der_copy_oid(oid, q->key_alg)) { + free(q->key_alg); + q->key_alg = NULL; + return ENOMEM; + } + q->match |= HX509_QUERY_MATCH_KEY_ALG; + } else { + q->match &= ~HX509_QUERY_MATCH_KEY_ALG; + } + return 0; +} + /** * Free the query controller. * @@ -3276,6 +3619,10 @@ hx509_query_free(hx509_context context, hx509_query *q) free(q->friendlyname); if (q->expr) _hx509_expr_free(q->expr); + if (q->key_alg) { + der_free_oid(q->key_alg); + free(q->key_alg); + } memset(q, 0, sizeof(*q)); free(q); @@ -3393,6 +3740,7 @@ _hx509_query_match_cert(hx509_context context, const hx509_query *q, hx509_cert ret = _hx509_verify_signature(context, NULL, hx509_signature_sha1(), + NULL, &os, q->keyhash_sha1); if (ret != 0) @@ -3427,6 +3775,14 @@ _hx509_query_match_cert(hx509_context context, const hx509_query *q, hx509_cert return 0; } + if (q->match & HX509_QUERY_MATCH_KEY_ALG) { + const AlgorithmIdentifier *alg; + + alg = &c->tbsCertificate.subjectPublicKeyInfo.algorithm; + if (der_heim_oid_cmp(&alg->algorithm, q->key_alg) != 0) + return 0; + } + if (q->match & ~HX509_QUERY_MASK) return 0; @@ -3849,6 +4205,7 @@ _hx509_cert_to_env(hx509_context context, hx509_cert cert, hx509_env *env) ret = _hx509_create_signature(context, NULL, hx509_signature_sha1(), + NULL, &os, NULL, &sig); diff --git a/lib/hx509/cms.c b/lib/hx509/cms.c index 1723f3a64..31cba0ed4 100644 --- a/lib/hx509/cms.c +++ b/lib/hx509/cms.c @@ -740,10 +740,12 @@ any_to_certs(hx509_context context, const SignedData *sd, hx509_certs certs) heim_error_t error; hx509_cert c; - c = hx509_cert_init_data(context, - sd->certificates->val[i].data, - sd->certificates->val[i].length, - &error); + if (sd->certificates->val[i].element != + choice_CertificateChoices_certificate) + continue; + c = hx509_cert_init(context, + &sd->certificates->val[i].u.certificate, + &error); if (c == NULL) { ret = heim_error_get_code(error); heim_release(error); @@ -1004,6 +1006,7 @@ hx509_cms_verify_signed_ext(hx509_context context, ret = _hx509_verify_signature(context, NULL, &signer_info->digestAlgorithm, + NULL, content, &os); der_free_octet_string(&os); @@ -1079,11 +1082,12 @@ hx509_cms_verify_signed_ext(hx509_context context, der_free_oid(&decode_oid); if (ret == 0) { - ret = hx509_verify_signature(context, - cert, - &signer_info->signatureAlgorithm, - &signed_data, - &signer_info->signature); + ret = _hx509_verify_signature(context, + cert, + &signer_info->signatureAlgorithm, + &signer_info->digestAlgorithm, + &signed_data, + &signer_info->signature); if (ret) hx509_set_error_string(context, HX509_ERROR_APPEND, ret, "Failed to verify signature in " @@ -1345,6 +1349,7 @@ sig_process(hx509_context context, void *ctx, hx509_cert cert) ret = _hx509_create_signature(context, NULL, &digest, + NULL, &sigctx->content, NULL, &sig); @@ -1429,6 +1434,7 @@ sig_process(hx509_context context, void *ctx, hx509_cert cert) ret = _hx509_create_signature(context, _hx509_cert_private_key(cert), &sigalg, + &digest, &sigdata, &signer_info->signatureAlgorithm, &signer_info->signature); @@ -1484,20 +1490,27 @@ cert_process(hx509_context context, void *ctx, hx509_cert cert) { struct sigctx *sigctx = ctx; const unsigned int i = sigctx->sd.certificates->len; + Certificate cc, *c; void *ptr; int ret; + if ((c = _hx509_get_cert(cert)) == NULL) + return 0; + + memset(&cc, 0, sizeof(cc)); + ret = copy_Certificate(c, &cc); + if (ret) + return ret; + + ptr = realloc(sigctx->sd.certificates->val, (i + 1) * sizeof(sigctx->sd.certificates->val[0])); if (ptr == NULL) return ENOMEM; sigctx->sd.certificates->val = ptr; - - ret = hx509_cert_binary(context, cert, - &sigctx->sd.certificates->val[i]); - if (ret == 0) - sigctx->sd.certificates->len++; - + sigctx->sd.certificates->val[i].element = choice_CertificateChoices_certificate; + sigctx->sd.certificates->val[i].u.certificate = cc; + sigctx->sd.certificates->len++; return ret; } diff --git a/lib/hx509/crypto-ec.c b/lib/hx509/crypto-ec.c index f43554d10..9fea73d8d 100644 --- a/lib/hx509/crypto-ec.c +++ b/lib/hx509/crypto-ec.c @@ -39,10 +39,9 @@ #include #include #include -#ifdef HAVE_OPENSSL_30 #include #include -#endif +#include #define HEIM_NO_CRYPTO_HDRS #include "hx_locl.h" @@ -55,11 +54,7 @@ extern const AlgorithmIdentifier _hx509_signature_sha1_data; HX509_LIB_FUNCTION void HX509_LIB_CALL _hx509_private_eckey_free(void *eckey) { -#ifdef HAVE_OPENSSL_30 EVP_PKEY_free(eckey); -#else - EC_KEY_free(eckey); -#endif } static struct oid2nid_st { @@ -134,27 +129,27 @@ ECParameters2nid(hx509_context context, return 0; } -#ifdef HAVE_OPENSSL_30 static const EVP_MD * signature_alg2digest_evp_md(hx509_context context, const AlgorithmIdentifier *digest_alg) { + /* Use cached digests from the context if available */ if ((&digest_alg->algorithm == &asn1_oid_id_sha512 || der_heim_oid_cmp(&digest_alg->algorithm, &asn1_oid_id_sha512) == 0)) - return EVP_sha512(); + return context->ossl ? context->ossl->sha512 : 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(); + return context->ossl ? context->ossl->sha384 : 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(); + return context->ossl ? context->ossl->sha256 : 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(); + return context->ossl ? context->ossl->sha1 : 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(); + return context->ossl ? context->ossl->md5 : EVP_md5(); /* * XXX Decode the `digest_alg->algorithm' OID and include it in the error @@ -164,7 +159,6 @@ signature_alg2digest_evp_md(hx509_context context, "Digest algorithm not found"); return NULL; } -#endif @@ -177,12 +171,11 @@ ecdsa_verify_signature(hx509_context context, const struct signature_alg *sig_alg, const Certificate *signer, const AlgorithmIdentifier *alg, + const EVP_MD *md, 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]; @@ -196,6 +189,9 @@ ecdsa_verify_signature(hx509_context context, int groupnid; int ret = 0; + //md = md ? md : signature_alg2digest_evp_md(context, digest_alg); + md = signature_alg2digest_evp_md(context, digest_alg); + spi = &signer->tbsCertificate.subjectPublicKeyInfo; if (der_heim_oid_cmp(&spi->algorithm.algorithm, ASN1_OID_ID_ECPUBLICKEY) != 0) @@ -233,7 +229,8 @@ ecdsa_verify_signature(hx509_context context, curve_sn_dup, 0); params[1] = OSSL_PARAM_construct_end(); - if ((pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL)) == NULL) + if ((pctx = EVP_PKEY_CTX_new_from_name(context->ossl->libctx, "EC", + context->ossl->propq)) == NULL) ret = hx509_enomem(context); } if (ret == 0 && EVP_PKEY_fromdata_init(pctx) != 1) @@ -279,72 +276,6 @@ ecdsa_verify_signature(hx509_context context, EVP_PKEY_free(template); free(curve_sn_dup); return ret; -#else - const AlgorithmIdentifier *digest_alg; - const SubjectPublicKeyInfo *spi; - heim_octet_string digest; - int ret; - EC_KEY *key = NULL; - int groupnid; - EC_GROUP *group; - const unsigned char *p; - long len; - - digest_alg = sig_alg->digest_alg; - - ret = _hx509_create_signature(context, - NULL, - digest_alg, - data, - NULL, - &digest); - if (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; - - /* - * Find the group id - */ - - ret = ECParameters2nid(context, spi->algorithm.parameters, &groupnid); - if (ret) { - der_free_octet_string(&digest); - return ret; - } - - /* - * Create group, key, parse key - */ - - key = EC_KEY_new(); - group = EC_GROUP_new_by_curve_name(groupnid); - EC_KEY_set_group(key, group); - EC_GROUP_free(group); - - p = spi->subjectPublicKey.data; - len = spi->subjectPublicKey.length / 8; - - if (o2i_ECPublicKey(&key, &p, len) == NULL) { - EC_KEY_free(key); - return HX509_CRYPTO_SIG_INVALID_FORMAT; - } - - ret = ECDSA_verify(-1, digest.data, digest.length, - 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; - } - - return 0; -#endif } static int @@ -352,18 +283,19 @@ ecdsa_create_signature(hx509_context context, const struct signature_alg *sig_alg, const hx509_private_key signer, const AlgorithmIdentifier *alg, + const EVP_MD *md, const heim_octet_string *data, 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; + //md = md ? md : signature_alg2digest_evp_md(context, digest_alg); + md = signature_alg2digest_evp_md(context, digest_alg); sig->data = NULL; sig->length = 0; if (signer->ops && der_heim_oid_cmp(signer->ops->key_oid, ASN1_OID_ID_ECPUBLICKEY) != 0) @@ -379,7 +311,7 @@ ecdsa_create_signature(hx509_context context, if (mdctx == NULL) ret = hx509_enomem(context); if (ret == 0 && EVP_DigestSignInit(mdctx, &pctx, md, NULL, - signer->private_key.ecdsa) != 1) + signer->private_key.pkey) != 1) ret = HX509_CMS_FAILED_CREATE_SIGATURE; if (ret == 0 && EVP_DigestSignUpdate(mdctx, data->data, data->length) != 1) ret = HX509_CMS_FAILED_CREATE_SIGATURE; @@ -405,75 +337,12 @@ ecdsa_create_signature(hx509_context context, } EVP_MD_CTX_free(mdctx); return ret; -#else - const AlgorithmIdentifier *digest_alg; - heim_octet_string indata; - const heim_oid *sig_oid; - unsigned int siglen; - 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"); - - 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); - if (ret) { - hx509_clear_error_string(context); - return ret; - } - } - - ret = _hx509_create_signature(context, - NULL, - digest_alg, - data, - NULL, - &indata); - if (ret) - 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; - } - - siglen = sig->length; - - ret = ECDSA_sign(-1, indata.data, indata.length, - 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; - } - if (siglen > sig->length) - _hx509_abort("ECDSA signature prelen longer than output len"); - - sig->length = siglen; - - return 0; -error: - if (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; size_t group_name_len = 0; char group_name_buf[96]; @@ -489,7 +358,7 @@ ecdsa_available(const hx509_private_key signer, if (sig == NULL || sig->digest_size == 0) return 0; - if (EVP_PKEY_get_group_name(signer->private_key.ecdsa, group_name_buf, + if (EVP_PKEY_get_group_name(signer->private_key.pkey, group_name_buf, sizeof(group_name_buf), &group_name_len) != 1 || group_name_len >= sizeof(group_name_buf)) { @@ -515,46 +384,6 @@ ecdsa_available(const hx509_private_key signer, 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; - - bnctx = BN_CTX_new(); - order = BN_new(); - if (order == NULL) - goto err; - - if (EC_GROUP_get_order(group, order, bnctx) != 1) - 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; - err: - if (bnctx) - BN_CTX_free(bnctx); - if (order) - BN_clear_free(order); - - return ret; -#endif } static int @@ -562,8 +391,118 @@ ecdsa_private_key2SPKI(hx509_context context, hx509_private_key private_key, SubjectPublicKeyInfo *spki) { + unsigned char *pub = NULL; + size_t publen = 0; + size_t group_name_len = 0; + char group_name_buf[96]; + int nid; + int ret; + memset(spki, 0, sizeof(*spki)); - return ENOMEM; + + /* Get the group/curve name */ + if (EVP_PKEY_get_group_name(private_key->private_key.pkey, group_name_buf, + sizeof(group_name_buf), &group_name_len) != 1 || + group_name_len >= sizeof(group_name_buf)) { + hx509_set_error_string(context, 0, HX509_CRYPTO_SIG_INVALID_FORMAT, + "Could not get EC group name"); + return HX509_CRYPTO_SIG_INVALID_FORMAT; + } + + nid = OBJ_txt2nid(group_name_buf); + if (nid == NID_undef) { + hx509_set_error_string(context, 0, HX509_CRYPTO_SIG_INVALID_FORMAT, + "Unknown EC group: %s", group_name_buf); + return HX509_CRYPTO_SIG_INVALID_FORMAT; + } + + /* Set the algorithm OID to ecPublicKey */ + ret = der_copy_oid(ASN1_OID_ID_ECPUBLICKEY, &spki->algorithm.algorithm); + if (ret) + return ret; + + /* Set the EC parameters (curve OID) */ + { + ECParameters ecparam; + size_t size; + const heim_oid *curve_oid = NULL; + + /* Map NID to OID */ + switch (nid) { + case NID_X9_62_prime256v1: + curve_oid = ASN1_OID_ID_EC_GROUP_SECP256R1; + break; +#ifdef NID_secp384r1 + case NID_secp384r1: + curve_oid = ASN1_OID_ID_EC_GROUP_SECP384R1; + break; +#endif +#ifdef NID_secp521r1 + case NID_secp521r1: + curve_oid = ASN1_OID_ID_EC_GROUP_SECP521R1; + break; +#endif + default: + free_AlgorithmIdentifier(&spki->algorithm); + hx509_set_error_string(context, 0, HX509_CRYPTO_SIG_INVALID_FORMAT, + "Unsupported EC curve NID: %d", nid); + return HX509_CRYPTO_SIG_INVALID_FORMAT; + } + + spki->algorithm.parameters = calloc(1, sizeof(*spki->algorithm.parameters)); + if (spki->algorithm.parameters == NULL) { + free_AlgorithmIdentifier(&spki->algorithm); + return hx509_enomem(context); + } + + ecparam.element = choice_ECParameters_namedCurve; + ret = der_copy_oid(curve_oid, &ecparam.u.namedCurve); + if (ret) { + free_AlgorithmIdentifier(&spki->algorithm); + return ret; + } + + ASN1_MALLOC_ENCODE(ECParameters, spki->algorithm.parameters->data, + spki->algorithm.parameters->length, + &ecparam, &size, ret); + free_ECParameters(&ecparam); + if (ret) { + free_AlgorithmIdentifier(&spki->algorithm); + return ret; + } + } + + /* Get the public key in uncompressed point format */ + if (EVP_PKEY_get_octet_string_param(private_key->private_key.pkey, + OSSL_PKEY_PARAM_PUB_KEY, + NULL, 0, &publen) != 1) { + free_AlgorithmIdentifier(&spki->algorithm); + hx509_set_error_string(context, 0, HX509_CRYPTO_SIG_INVALID_FORMAT, + "Could not get EC public key size"); + return HX509_CRYPTO_SIG_INVALID_FORMAT; + } + + pub = malloc(publen); + if (pub == NULL) { + free_AlgorithmIdentifier(&spki->algorithm); + return hx509_enomem(context); + } + + if (EVP_PKEY_get_octet_string_param(private_key->private_key.pkey, + OSSL_PKEY_PARAM_PUB_KEY, + pub, publen, &publen) != 1) { + free(pub); + free_AlgorithmIdentifier(&spki->algorithm); + hx509_set_error_string(context, 0, HX509_CRYPTO_SIG_INVALID_FORMAT, + "Could not get EC public key"); + return HX509_CRYPTO_SIG_INVALID_FORMAT; + } + + /* Set the public key as a BIT STRING */ + spki->subjectPublicKey.data = pub; + spki->subjectPublicKey.length = publen * 8; + + return 0; } static int @@ -572,7 +511,52 @@ ecdsa_private_key_export(hx509_context context, hx509_key_format_t format, heim_octet_string *data) { - return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED; + unsigned char *p = NULL; + size_t size = 0; + int ret; + + data->data = NULL; + data->length = 0; + + switch (format) { + case HX509_KEY_FORMAT_DER: { + /* EC private keys are exported in PKCS#8 format */ + OSSL_ENCODER_CTX *ctx = + OSSL_ENCODER_CTX_new_for_pkey(key->private_key.pkey, + OSSL_KEYMGMT_SELECT_PRIVATE_KEY, + "DER", + "PrivateKeyInfo", /* PKCS#8 */ + NULL); + if (ctx == NULL) { + _hx509_set_error_string_openssl(context, 0, ENOMEM, + "Could not allocate EC private key encoder"); + return ENOMEM; + } + + ret = OSSL_ENCODER_to_data(ctx, &p, &size); + OSSL_ENCODER_CTX_free(ctx); + if (ret != 1) { + _hx509_set_error_string_openssl(context, 0, EINVAL, + "Could not encode EC private key"); + return EINVAL; + } + + data->data = malloc(size); + if (data->data == NULL) { + OPENSSL_free(p); + hx509_set_error_string(context, 0, ENOMEM, "malloc out of memory"); + return ENOMEM; + } + data->length = size; + memcpy(data->data, p, size); + OPENSSL_free(p); + break; + } + default: + return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED; + } + + return 0; } static int @@ -583,7 +567,6 @@ 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; @@ -638,64 +621,13 @@ ecdsa_private_key_import(hx509_context context, } if (ret == 0) { - private_key->private_key.ecdsa = key; + private_key->private_key.pkey = 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 = 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; - - default: - return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED; - } - - return 0; -#endif } static int @@ -703,7 +635,75 @@ ecdsa_generate_private_key(hx509_context context, struct hx509_generate_private_context *ctx, hx509_private_key private_key) { - return ENOMEM; + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *pctx = NULL; + int nid; + + /* + * Map key size to curve NID. + * Default to P-256 if no size specified. + */ + switch (ctx->num_bits) { + case 0: + case 256: + nid = NID_X9_62_prime256v1; /* P-256 / secp256r1 */ + break; + case 384: + nid = NID_secp384r1; /* P-384 */ + break; + case 521: + nid = NID_secp521r1; /* P-521 */ + break; + default: + hx509_set_error_string(context, 0, EINVAL, + "Unsupported EC key size %lu " + "(supported: 256, 384, 521)", + ctx->num_bits); + return EINVAL; + } + + pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); + if (pctx == NULL) + return hx509_enomem(context); + + if (EVP_PKEY_keygen_init(pctx) <= 0) { + EVP_PKEY_CTX_free(pctx); + _hx509_set_error_string_openssl(context, 0, HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED, + "Failed to initialize EC key generation"); + return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED; + } + + if (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, nid) <= 0) { + EVP_PKEY_CTX_free(pctx); + _hx509_set_error_string_openssl(context, 0, HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED, + "Failed to set EC curve"); + return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED; + } + + if (EVP_PKEY_keygen(pctx, &pkey) <= 0) { + EVP_PKEY_CTX_free(pctx); + _hx509_set_error_string_openssl(context, 0, HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED, + "Failed to generate EC key"); + return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED; + } + + EVP_PKEY_CTX_free(pctx); + private_key->private_key.pkey = pkey; + + /* Select appropriate signature algorithm based on curve */ + switch (nid) { + case NID_secp521r1: + private_key->signature_alg = ASN1_OID_ID_ECDSA_WITH_SHA512; + break; + case NID_secp384r1: + private_key->signature_alg = ASN1_OID_ID_ECDSA_WITH_SHA384; + break; + default: + private_key->signature_alg = ASN1_OID_ID_ECDSA_WITH_SHA256; + break; + } + + return 0; } static BIGNUM * @@ -716,27 +716,27 @@ ecdsa_get_internal(hx509_context context, static const unsigned ecPublicKey[] ={ 1, 2, 840, 10045, 2, 1 }; const AlgorithmIdentifier _hx509_signature_ecPublicKey = { - { 6, rk_UNCONST(ecPublicKey) }, NULL + { 6, rk_UNCONST(ecPublicKey) }, NULL, {0} }; static const unsigned ecdsa_with_sha256_oid[] ={ 1, 2, 840, 10045, 4, 3, 2 }; const AlgorithmIdentifier _hx509_signature_ecdsa_with_sha256_data = { - { 7, rk_UNCONST(ecdsa_with_sha256_oid) }, NULL + { 7, rk_UNCONST(ecdsa_with_sha256_oid) }, NULL, {0} }; static const unsigned ecdsa_with_sha384_oid[] ={ 1, 2, 840, 10045, 4, 3, 3 }; const AlgorithmIdentifier _hx509_signature_ecdsa_with_sha384_data = { - { 7, rk_UNCONST(ecdsa_with_sha384_oid) }, NULL + { 7, rk_UNCONST(ecdsa_with_sha384_oid) }, NULL, {0} }; static const unsigned ecdsa_with_sha512_oid[] ={ 1, 2, 840, 10045, 4, 3, 4 }; const AlgorithmIdentifier _hx509_signature_ecdsa_with_sha512_data = { - { 7, rk_UNCONST(ecdsa_with_sha512_oid) }, NULL + { 7, rk_UNCONST(ecdsa_with_sha512_oid) }, NULL, {0} }; static const unsigned ecdsa_with_sha1_oid[] ={ 1, 2, 840, 10045, 4, 1 }; const AlgorithmIdentifier _hx509_signature_ecdsa_with_sha1_data = { - { 6, rk_UNCONST(ecdsa_with_sha1_oid) }, NULL + { 6, rk_UNCONST(ecdsa_with_sha1_oid) }, NULL, {0} }; hx509_private_key_ops ecdsa_private_key_ops = { @@ -821,3 +821,425 @@ hx509_signature_ecdsa_with_sha256(void) { return &_hx509_signature_ecdsa_with_sha256_data; } + +/* + * EdDSA (Ed25519 and Ed448) support + * + * EdDSA is a "pure" signature scheme - there is no separate digest step. + * The signature algorithm OID is also the key algorithm OID. + * + * Ed25519: OID 1.3.101.112 + * Ed448: OID 1.3.101.113 + */ + +/* Ed25519: 1.3.101.112 */ +static const unsigned ed25519_oid[] = { 1, 3, 101, 112 }; +const AlgorithmIdentifier _hx509_signature_ed25519_data = { + { 4, rk_UNCONST(ed25519_oid) }, NULL, {0} +}; + +/* Ed448: 1.3.101.113 */ +static const unsigned ed448_oid[] = { 1, 3, 101, 113 }; +const AlgorithmIdentifier _hx509_signature_ed448_data = { + { 4, rk_UNCONST(ed448_oid) }, NULL, {0} +}; + +static int +eddsa_verify_signature(hx509_context context, + const struct signature_alg *sig_alg, + const Certificate *signer, + const AlgorithmIdentifier *alg, + const EVP_MD *md, + const heim_octet_string *data, + const heim_octet_string *sig) +{ + const SubjectPublicKeyInfo *spi; + EVP_MD_CTX *mdctx = NULL; + EVP_PKEY *public = NULL; + const unsigned char *p; + size_t len; + int ret = 0; + + spi = &signer->tbsCertificate.subjectPublicKeyInfo; + + /* Verify the key OID matches what we expect */ + if (der_heim_oid_cmp(&spi->algorithm.algorithm, sig_alg->key_oid) != 0) { + hx509_set_error_string(context, 0, HX509_CRYPTO_SIG_INVALID_FORMAT, + "EdDSA key OID mismatch"); + return HX509_CRYPTO_SIG_INVALID_FORMAT; + } + + /* EdDSA public keys are encoded directly as BIT STRING */ + p = spi->subjectPublicKey.data; + /* BIT STRING length is in bits, convert to bytes */ + len = spi->subjectPublicKey.length / 8; + + if (der_heim_oid_cmp(sig_alg->key_oid, ASN1_OID_ID_ED25519) == 0) + public = EVP_PKEY_new_raw_public_key_ex(context->ossl->libctx, "ED25519", + context->ossl->propq, p, len); + else if (der_heim_oid_cmp(sig_alg->key_oid, ASN1_OID_ID_ED448) == 0) + public = EVP_PKEY_new_raw_public_key_ex(context->ossl->libctx, "ED448", + context->ossl->propq, p, len); + + if (public == NULL) { + _hx509_set_error_string_openssl(context, 0, HX509_CRYPTO_SIG_INVALID_FORMAT, + "Could not parse EdDSA public key"); + return HX509_CRYPTO_SIG_INVALID_FORMAT; + } + + mdctx = EVP_MD_CTX_new(); + if (mdctx == NULL) { + EVP_PKEY_free(public); + return hx509_enomem(context); + } + + /* EdDSA uses NULL for the md parameter - "pure" signing */ + if (EVP_DigestVerifyInit(mdctx, NULL, NULL, NULL, public) != 1) { + hx509_set_error_string(context, 0, HX509_CRYPTO_SIG_INVALID_FORMAT, + "EdDSA verify init failed"); + ret = HX509_CRYPTO_SIG_INVALID_FORMAT; + } else if (EVP_DigestVerify(mdctx, sig->data, sig->length, + data->data, data->length) != 1) { + hx509_set_error_string(context, 0, HX509_CRYPTO_SIG_INVALID_FORMAT, + "EdDSA signature verification failed"); + ret = HX509_CRYPTO_SIG_INVALID_FORMAT; + } + + EVP_MD_CTX_free(mdctx); + EVP_PKEY_free(public); + return ret; +} + +static int +eddsa_create_signature(hx509_context context, + const struct signature_alg *sig_alg, + const hx509_private_key signer, + const AlgorithmIdentifier *alg, + const EVP_MD *md, + const heim_octet_string *data, + AlgorithmIdentifier *signatureAlgorithm, + heim_octet_string *sig) +{ + EVP_MD_CTX *mdctx = NULL; + int ret = 0; + + sig->data = NULL; + sig->length = 0; + + if (signatureAlgorithm) { + /* EdDSA has no parameters */ + ret = _hx509_set_digest_alg(signatureAlgorithm, sig_alg->sig_oid, + NULL, 0); + if (ret) + return ret; + } + + mdctx = EVP_MD_CTX_new(); + if (mdctx == NULL) + return hx509_enomem(context); + + /* EdDSA uses NULL for the md parameter - "pure" signing */ + if (EVP_DigestSignInit(mdctx, NULL, NULL, NULL, + signer->private_key.pkey) != 1) { + hx509_set_error_string(context, 0, HX509_CMS_FAILED_CREATE_SIGATURE, + "EdDSA sign init failed"); + ret = HX509_CMS_FAILED_CREATE_SIGATURE; + goto out; + } + + /* First call to get the signature length */ + if (EVP_DigestSign(mdctx, NULL, &sig->length, + data->data, data->length) != 1) { + hx509_set_error_string(context, 0, HX509_CMS_FAILED_CREATE_SIGATURE, + "EdDSA sign length failed"); + ret = HX509_CMS_FAILED_CREATE_SIGATURE; + goto out; + } + + sig->data = malloc(sig->length); + if (sig->data == NULL) { + ret = hx509_enomem(context); + goto out; + } + + /* Second call to actually sign */ + if (EVP_DigestSign(mdctx, sig->data, &sig->length, + data->data, data->length) != 1) { + _hx509_set_error_string_openssl(context, 0, HX509_CMS_FAILED_CREATE_SIGATURE, + "EdDSA sign failed"); + ret = HX509_CMS_FAILED_CREATE_SIGATURE; + free(sig->data); + sig->data = NULL; + sig->length = 0; + } + +out: + if (ret && signatureAlgorithm) + free_AlgorithmIdentifier(signatureAlgorithm); + EVP_MD_CTX_free(mdctx); + return ret; +} + +static int +eddsa_available(const hx509_private_key signer, + const AlgorithmIdentifier *sig_alg) +{ + int pkey_id; + + if (signer->private_key.pkey == NULL) + return 0; + + pkey_id = EVP_PKEY_base_id(signer->private_key.pkey); + + /* Ed25519 key can only use Ed25519 signature */ + if (pkey_id == EVP_PKEY_ED25519) + return der_heim_oid_cmp(&sig_alg->algorithm, ASN1_OID_ID_ED25519) == 0; + + /* Ed448 key can only use Ed448 signature */ + if (pkey_id == EVP_PKEY_ED448) + return der_heim_oid_cmp(&sig_alg->algorithm, ASN1_OID_ID_ED448) == 0; + + return 0; +} + +static int +eddsa_private_key2SPKI(hx509_context context, + hx509_private_key private_key, + SubjectPublicKeyInfo *spki) +{ + unsigned char *pub = NULL; + size_t publen = 0; + int ret; + + memset(spki, 0, sizeof(*spki)); + + /* Get the raw public key */ + if (EVP_PKEY_get_raw_public_key(private_key->private_key.pkey, + NULL, &publen) != 1) + return HX509_CRYPTO_SIG_INVALID_FORMAT; + + pub = malloc(publen); + if (pub == NULL) + return hx509_enomem(context); + + if (EVP_PKEY_get_raw_public_key(private_key->private_key.pkey, + pub, &publen) != 1) { + free(pub); + return HX509_CRYPTO_SIG_INVALID_FORMAT; + } + + /* Set the algorithm OID */ + ret = der_copy_oid(private_key->ops->key_oid, &spki->algorithm.algorithm); + if (ret) { + free(pub); + return ret; + } + + /* EdDSA has no algorithm parameters */ + spki->algorithm.parameters = NULL; + + /* Set the public key as a BIT STRING */ + spki->subjectPublicKey.data = pub; + spki->subjectPublicKey.length = publen * 8; + + return 0; +} + +static int +eddsa_private_key_export(hx509_context context, + const hx509_private_key key, + hx509_key_format_t format, + heim_octet_string *data) +{ + unsigned char *p = NULL; + size_t size = 0; + int ret; + + data->data = NULL; + data->length = 0; + + switch (format) { + case HX509_KEY_FORMAT_DER: { + /* EdDSA private keys are exported in PKCS#8 format */ + OSSL_ENCODER_CTX *ctx = + OSSL_ENCODER_CTX_new_for_pkey(key->private_key.pkey, + OSSL_KEYMGMT_SELECT_PRIVATE_KEY, + "DER", + "PrivateKeyInfo", /* PKCS#8 */ + NULL); + if (ctx == NULL) { + _hx509_set_error_string_openssl(context, 0, ENOMEM, + "Could not allocate EdDSA private key encoder"); + return ENOMEM; + } + + ret = OSSL_ENCODER_to_data(ctx, &p, &size); + OSSL_ENCODER_CTX_free(ctx); + if (ret != 1) { + _hx509_set_error_string_openssl(context, 0, EINVAL, + "Could not encode EdDSA private key"); + return EINVAL; + } + + data->data = malloc(size); + if (data->data == NULL) { + OPENSSL_free(p); + hx509_set_error_string(context, 0, ENOMEM, "malloc out of memory"); + return ENOMEM; + } + data->length = size; + memcpy(data->data, p, size); + OPENSSL_free(p); + break; + } + default: + return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED; + } + + return 0; +} + +static int +eddsa_private_key_import(hx509_context context, + const AlgorithmIdentifier *keyai, + const void *data, + size_t len, + hx509_key_format_t format, + hx509_private_key private_key) +{ + const unsigned char *p = data; + EVP_PKEY *key = NULL; + int pkey_type; + + /* Determine key type from algorithm OID */ + if (der_heim_oid_cmp(&keyai->algorithm, ASN1_OID_ID_ED25519) == 0) + pkey_type = EVP_PKEY_ED25519; + else if (der_heim_oid_cmp(&keyai->algorithm, ASN1_OID_ID_ED448) == 0) + pkey_type = EVP_PKEY_ED448; + else + return HX509_ALG_NOT_SUPP; + + switch (format) { + case HX509_KEY_FORMAT_PKCS8: + key = d2i_PrivateKey(pkey_type, NULL, &p, len); + if (key == NULL) { + _hx509_set_error_string_openssl(context, 0, HX509_PARSING_KEY_FAILED, + "Failed to parse EdDSA private key"); + return HX509_PARSING_KEY_FAILED; + } + break; + + default: + return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED; + } + + private_key->private_key.pkey = key; + private_key->signature_alg = &keyai->algorithm; + + return 0; +} + +static int +eddsa_generate_private_key(hx509_context context, + struct hx509_generate_private_context *ctx, + hx509_private_key private_key) +{ + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *pctx = NULL; + int pkey_type; + + if (der_heim_oid_cmp(ctx->key_oid, ASN1_OID_ID_ED25519) == 0) + pkey_type = EVP_PKEY_ED25519; + else if (der_heim_oid_cmp(ctx->key_oid, ASN1_OID_ID_ED448) == 0) + pkey_type = EVP_PKEY_ED448; + else + return HX509_ALG_NOT_SUPP; + + pctx = EVP_PKEY_CTX_new_id(pkey_type, NULL); + if (pctx == NULL) + return hx509_enomem(context); + + if (EVP_PKEY_keygen_init(pctx) <= 0 || + EVP_PKEY_keygen(pctx, &pkey) <= 0) { + EVP_PKEY_CTX_free(pctx); + _hx509_set_error_string_openssl(context, 0, HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED, + "Failed to generate EdDSA key"); + return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED; + } + + EVP_PKEY_CTX_free(pctx); + private_key->private_key.pkey = pkey; + private_key->signature_alg = ctx->key_oid; + + return 0; +} + +static BIGNUM * +eddsa_get_internal(hx509_context context, + hx509_private_key key, + const char *type) +{ + return NULL; +} + +hx509_private_key_ops ed25519_private_key_ops = { + "PRIVATE KEY", /* Use PKCS#8 PEM format for compatibility */ + ASN1_OID_ID_ED25519, + eddsa_available, + eddsa_private_key2SPKI, + eddsa_private_key_export, + eddsa_private_key_import, + eddsa_generate_private_key, + eddsa_get_internal +}; + +hx509_private_key_ops ed448_private_key_ops = { + "PRIVATE KEY", /* Use PKCS#8 PEM format for compatibility */ + ASN1_OID_ID_ED448, + eddsa_available, + eddsa_private_key2SPKI, + eddsa_private_key_export, + eddsa_private_key_import, + eddsa_generate_private_key, + eddsa_get_internal +}; + +const struct signature_alg ed25519_alg = { + "ed25519", + ASN1_OID_ID_ED25519, + &_hx509_signature_ed25519_data, + ASN1_OID_ID_ED25519, /* key_oid == sig_oid for EdDSA */ + NULL, /* No separate digest algorithm */ + PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG|SELF_SIGNED_OK, + 0, + NULL, /* No EVP_MD for EdDSA */ + eddsa_verify_signature, + eddsa_create_signature, + 64 /* Ed25519 signature size */ +}; + +const struct signature_alg ed448_alg = { + "ed448", + ASN1_OID_ID_ED448, + &_hx509_signature_ed448_data, + ASN1_OID_ID_ED448, /* key_oid == sig_oid for EdDSA */ + NULL, /* No separate digest algorithm */ + PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG|SELF_SIGNED_OK, + 0, + NULL, /* No EVP_MD for EdDSA */ + eddsa_verify_signature, + eddsa_create_signature, + 114 /* Ed448 signature size */ +}; + +HX509_LIB_FUNCTION const AlgorithmIdentifier * HX509_LIB_CALL +hx509_signature_ed25519(void) +{ + return &_hx509_signature_ed25519_data; +} + +HX509_LIB_FUNCTION const AlgorithmIdentifier * HX509_LIB_CALL +hx509_signature_ed448(void) +{ + return &_hx509_signature_ed448_data; +} diff --git a/lib/hx509/crypto.c b/lib/hx509/crypto.c index 11dab9659..a3d7f49f1 100644 --- a/lib/hx509/crypto.c +++ b/lib/hx509/crypto.c @@ -45,83 +45,84 @@ static const heim_octet_string null_entry_oid = { 2, rk_UNCONST("\x05\x00") }; static const unsigned sha512_oid_tree[] = { 2, 16, 840, 1, 101, 3, 4, 2, 3 }; const AlgorithmIdentifier _hx509_signature_sha512_data = { - { 9, rk_UNCONST(sha512_oid_tree) }, rk_UNCONST(&null_entry_oid) + { 9, rk_UNCONST(sha512_oid_tree) }, rk_UNCONST(&null_entry_oid), {0} }; static const unsigned sha384_oid_tree[] = { 2, 16, 840, 1, 101, 3, 4, 2, 2 }; const AlgorithmIdentifier _hx509_signature_sha384_data = { - { 9, rk_UNCONST(sha384_oid_tree) }, rk_UNCONST(&null_entry_oid) + { 9, rk_UNCONST(sha384_oid_tree) }, rk_UNCONST(&null_entry_oid), {0} }; static const unsigned sha256_oid_tree[] = { 2, 16, 840, 1, 101, 3, 4, 2, 1 }; const AlgorithmIdentifier _hx509_signature_sha256_data = { - { 9, rk_UNCONST(sha256_oid_tree) }, rk_UNCONST(&null_entry_oid) + { 9, rk_UNCONST(sha256_oid_tree) }, rk_UNCONST(&null_entry_oid), {0} }; static const unsigned sha1_oid_tree[] = { 1, 3, 14, 3, 2, 26 }; const AlgorithmIdentifier _hx509_signature_sha1_data = { - { 6, rk_UNCONST(sha1_oid_tree) }, rk_UNCONST(&null_entry_oid) + { 6, rk_UNCONST(sha1_oid_tree) }, rk_UNCONST(&null_entry_oid), {0} }; static const unsigned md5_oid_tree[] = { 1, 2, 840, 113549, 2, 5 }; const AlgorithmIdentifier _hx509_signature_md5_data = { - { 6, rk_UNCONST(md5_oid_tree) }, rk_UNCONST(&null_entry_oid) + { 6, rk_UNCONST(md5_oid_tree) }, rk_UNCONST(&null_entry_oid), {0} }; static const unsigned rsa_with_sha512_oid[] ={ 1, 2, 840, 113549, 1, 1, 13 }; const AlgorithmIdentifier _hx509_signature_rsa_with_sha512_data = { - { 7, rk_UNCONST(rsa_with_sha512_oid) }, rk_UNCONST(&null_entry_oid) + { 7, rk_UNCONST(rsa_with_sha512_oid) }, rk_UNCONST(&null_entry_oid), {0} }; static const unsigned rsa_with_sha384_oid[] ={ 1, 2, 840, 113549, 1, 1, 12 }; const AlgorithmIdentifier _hx509_signature_rsa_with_sha384_data = { - { 7, rk_UNCONST(rsa_with_sha384_oid) }, rk_UNCONST(&null_entry_oid) + { 7, rk_UNCONST(rsa_with_sha384_oid) }, rk_UNCONST(&null_entry_oid), {0} }; static const unsigned rsa_with_sha256_oid[] ={ 1, 2, 840, 113549, 1, 1, 11 }; const AlgorithmIdentifier _hx509_signature_rsa_with_sha256_data = { - { 7, rk_UNCONST(rsa_with_sha256_oid) }, rk_UNCONST(&null_entry_oid) + { 7, rk_UNCONST(rsa_with_sha256_oid) }, rk_UNCONST(&null_entry_oid), {0} }; static const unsigned rsa_with_sha1_oid[] ={ 1, 2, 840, 113549, 1, 1, 5 }; const AlgorithmIdentifier _hx509_signature_rsa_with_sha1_data = { - { 7, rk_UNCONST(rsa_with_sha1_oid) }, rk_UNCONST(&null_entry_oid) + { 7, rk_UNCONST(rsa_with_sha1_oid) }, rk_UNCONST(&null_entry_oid), {0} }; static const unsigned rsa_with_md5_oid[] ={ 1, 2, 840, 113549, 1, 1, 4 }; const AlgorithmIdentifier _hx509_signature_rsa_with_md5_data = { - { 7, rk_UNCONST(rsa_with_md5_oid) }, rk_UNCONST(&null_entry_oid) + { 7, rk_UNCONST(rsa_with_md5_oid) }, rk_UNCONST(&null_entry_oid), {0} }; static const unsigned rsa_oid[] ={ 1, 2, 840, 113549, 1, 1, 1 }; const AlgorithmIdentifier _hx509_signature_rsa_data = { - { 7, rk_UNCONST(rsa_oid) }, NULL + { 7, rk_UNCONST(rsa_oid) }, NULL, {0} }; static const unsigned rsa_pkcs1_x509_oid[] ={ 1, 2, 752, 43, 16, 1 }; const AlgorithmIdentifier _hx509_signature_rsa_pkcs1_x509_data = { - { 6, rk_UNCONST(rsa_pkcs1_x509_oid) }, NULL + { 6, rk_UNCONST(rsa_pkcs1_x509_oid) }, NULL, {0} }; static const unsigned des_rsdi_ede3_cbc_oid[] ={ 1, 2, 840, 113549, 3, 7 }; const AlgorithmIdentifier _hx509_des_rsdi_ede3_cbc_oid = { - { 6, rk_UNCONST(des_rsdi_ede3_cbc_oid) }, NULL + { 6, rk_UNCONST(des_rsdi_ede3_cbc_oid) }, NULL, {0} }; static const unsigned aes128_cbc_oid[] ={ 2, 16, 840, 1, 101, 3, 4, 1, 2 }; const AlgorithmIdentifier _hx509_crypto_aes128_cbc_data = { - { 9, rk_UNCONST(aes128_cbc_oid) }, NULL + { 9, rk_UNCONST(aes128_cbc_oid) }, NULL, {0} }; static const unsigned aes256_cbc_oid[] ={ 2, 16, 840, 1, 101, 3, 4, 1, 42 }; const AlgorithmIdentifier _hx509_crypto_aes256_cbc_data = { - { 9, rk_UNCONST(aes256_cbc_oid) }, NULL + { 9, rk_UNCONST(aes256_cbc_oid) }, NULL, {0} }; /* * */ +#if 0 static BIGNUM * heim_int2BN(const heim_integer *i) { @@ -131,6 +132,7 @@ heim_int2BN(const heim_integer *i) BN_set_negative(bn, i->negative); return bn; } +#endif /* * @@ -169,7 +171,9 @@ _hx509_set_digest_alg(DigestAlgorithmIdentifier *id, } /* - * + * XXX This is becoming generic, but making it fully so is painful, so we'll + * retain signature verification and creation functions for RSA PKCS#1 + * v1.5, v2.0, ECDSA, and EdDSA. */ static int @@ -177,110 +181,63 @@ rsa_verify_signature(hx509_context context, const struct signature_alg *sig_alg, const Certificate *signer, const AlgorithmIdentifier *alg, + const EVP_MD *md, const heim_octet_string *data, const heim_octet_string *sig) { - const SubjectPublicKeyInfo *spi; - DigestInfo di; - unsigned char *to; - int tosize, retsize; - int ret; - RSA *rsa; - size_t size; + EVP_PKEY_CTX *pctx = NULL; + EVP_MD_CTX *mctx = NULL; + EVP_PKEY *pkey = NULL; const unsigned char *p; + size_t size; + int ret = HX509_CRYPTO_INTERNAL_ERROR; - memset(&di, 0, sizeof(di)); + ERR_clear_error(); /* Clear any pre-existing errors */ + md = md ? md : (sig_alg->evp_md ? sig_alg->evp_md() : NULL); - spi = &signer->tbsCertificate.subjectPublicKeyInfo; + p = signer->tbsCertificate.subjectPublicKeyInfo._save.data; + size = signer->tbsCertificate.subjectPublicKeyInfo._save.length; - p = spi->subjectPublicKey.data; - size = spi->subjectPublicKey.length / 8; - - rsa = d2i_RSAPublicKey(NULL, &p, size); - if (rsa == NULL) { - ret = ENOMEM; - hx509_set_error_string(context, 0, ret, "out of memory"); + pkey = d2i_PUBKEY(NULL, &p, size); + if (pkey == NULL) { + _hx509_set_error_string_openssl(context, 0, ret, "Could not parse SubjectPublicKeyInfo (RSA)"); goto out; } - tosize = RSA_size(rsa); - to = malloc(tosize); - if (to == NULL) { - ret = ENOMEM; - hx509_set_error_string(context, 0, ret, "out of memory"); - goto out; + if (EVP_PKEY_base_id(pkey) != EVP_PKEY_RSA) { + ret = HX509_CRYPTO_SIG_INVALID_FORMAT; // Can't happen + hx509_set_error_string(context, 0, ret, "public key is not RSA"); + goto out; } - retsize = RSA_public_decrypt(sig->length, (unsigned char *)sig->data, - to, rsa, RSA_PKCS1_PADDING); - if (retsize <= 0) { - ret = HX509_CRYPTO_SIG_INVALID_FORMAT; - hx509_set_error_string(context, 0, ret, - "RSA public decrypt failed: %d", retsize); - free(to); - goto out; + if ((mctx = EVP_MD_CTX_new()) == NULL) { + ret = ENOMEM; + _hx509_set_error_string_openssl(context, 0, ret, "out of memory"); + goto out; } - if (retsize > tosize) - _hx509_abort("internal rsa decryption failure: ret > tosize"); - if (sig_alg->flags & RA_RSA_USES_DIGEST_INFO) { + if (EVP_DigestVerifyInit(mctx, &pctx, md, NULL, pkey) <= 0) { + ret = HX509_CRYPTO_SIG_INVALID_FORMAT; + hx509_set_error_string(context, 0, ret, "digest_verify_init"); + goto out; + } - ret = decode_DigestInfo(to, retsize, &di, &size); - free(to); - if (ret) { - goto out; - } - - /* Check for extra data inside the sigature */ - if (size != (size_t)retsize) { - ret = HX509_CRYPTO_SIG_INVALID_FORMAT; - hx509_set_error_string(context, 0, ret, "size from decryption mismatch"); - goto out; - } - - if (sig_alg->digest_alg && - der_heim_oid_cmp(&di.digestAlgorithm.algorithm, - &sig_alg->digest_alg->algorithm) != 0) - { - ret = HX509_CRYPTO_OID_MISMATCH; - hx509_set_error_string(context, 0, ret, "object identifier in RSA sig mismatch"); - goto out; - } - - /* verify that the parameters are NULL or the NULL-type */ - if (di.digestAlgorithm.parameters != NULL && - (di.digestAlgorithm.parameters->length != 2 || - memcmp(di.digestAlgorithm.parameters->data, "\x05\x00", 2) != 0)) - { - ret = HX509_CRYPTO_SIG_INVALID_FORMAT; - hx509_set_error_string(context, 0, ret, "Extra parameters inside RSA signature"); - goto out; - } - - ret = _hx509_verify_signature(context, - NULL, - &di.digestAlgorithm, - data, - &di.digest); - if (ret) - goto out; + if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PADDING) <= 0) { + ret = HX509_CRYPTO_SIG_INVALID_FORMAT; + hx509_set_error_string(context, 0, ret, "setting RSA PKCS#1.5 padding failed"); + goto out; + } + if (EVP_DigestVerify(mctx /* frees */, sig->data, sig->length, + data->data, data->length) == 1) { + ret = 0; } else { - if ((size_t)retsize != data->length || - ct_memcmp(to, data->data, retsize) != 0) - { - ret = HX509_CRYPTO_SIG_INVALID_FORMAT; - hx509_set_error_string(context, 0, ret, "RSA Signature incorrect"); - goto out; - } - free(to); - ret = 0; + _hx509_set_error_string_openssl(context, 0, ret, "signature validation failed"); } - out: - free_DigestInfo(&di); - if (rsa) - RSA_free(rsa); +out: + EVP_MD_CTX_free(mctx); /* Also frees pctx */ + EVP_PKEY_free(pkey); return ret; } @@ -289,13 +246,15 @@ rsa_create_signature(hx509_context context, const struct signature_alg *sig_alg, const hx509_private_key signer, const AlgorithmIdentifier *alg, + const EVP_MD *md, const heim_octet_string *data, AlgorithmIdentifier *signatureAlgorithm, heim_octet_string *sig) { const AlgorithmIdentifier *digest_alg; - heim_octet_string indata; const heim_oid *sig_oid; + EVP_PKEY_CTX *pctx = NULL; + EVP_MD_CTX *mctx = NULL; size_t size; int ret; @@ -307,28 +266,43 @@ rsa_create_signature(hx509_context context, else sig_oid = signer->signature_alg; - if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_SHA512WITHRSAENCRYPTION) == 0) { - digest_alg = hx509_signature_sha512(); - } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_SHA384WITHRSAENCRYPTION) == 0) { - digest_alg = hx509_signature_sha384(); - } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_SHA256WITHRSAENCRYPTION) == 0) { - digest_alg = hx509_signature_sha256(); - } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_SHA1WITHRSAENCRYPTION) == 0) { - digest_alg = hx509_signature_sha1(); - } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_MD5WITHRSAENCRYPTION) == 0) { - digest_alg = hx509_signature_md5(); - } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_MD5WITHRSAENCRYPTION) == 0) { - digest_alg = hx509_signature_md5(); - } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_DSA_WITH_SHA1) == 0) { - digest_alg = hx509_signature_sha1(); - } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_RSAENCRYPTION) == 0) { - digest_alg = hx509_signature_sha1(); - } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_HEIM_RSA_PKCS1_X509) == 0) { - digest_alg = NULL; - } else - return HX509_ALG_NOT_SUPP; + if (md == NULL) { + if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_SHA512WITHRSAENCRYPTION) == 0) { + digest_alg = hx509_signature_sha512(); + } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_SHA384WITHRSAENCRYPTION) == 0) { + digest_alg = hx509_signature_sha384(); + } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_SHA256WITHRSAENCRYPTION) == 0) { + digest_alg = hx509_signature_sha256(); + } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_SHA1WITHRSAENCRYPTION) == 0) { + digest_alg = hx509_signature_sha1(); + } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_MD5WITHRSAENCRYPTION) == 0) { + digest_alg = hx509_signature_md5(); + } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_MD5WITHRSAENCRYPTION) == 0) { + digest_alg = hx509_signature_md5(); + } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_DSA_WITH_SHA1) == 0) { + digest_alg = hx509_signature_sha1(); + } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_RSAENCRYPTION) == 0) { + digest_alg = hx509_signature_sha1(); + } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_HEIM_RSA_PKCS1_X509) == 0) { + digest_alg = NULL; + } else // TODO Add ECDSA and EdDSA and PQ hybrids here! + return HX509_ALG_NOT_SUPP; + + if (digest_alg) { + const struct signature_alg *d; + + if ((d = _hx509_find_sig_alg(&digest_alg->algorithm)) == NULL) + return HX509_ALG_NOT_SUPP; + md = d->evp_md(); + } + } if (signatureAlgorithm) { + // XXX Mutates signatureAlgorithm to set params to NULL, which is what + // "\x05\x00" is (the DER encoding of NULL). + // XXX This is a mistake. We should instead let OpenSSL 3.x APIs give + // us a DER-encoded AlgorithmIdentifier (that we would then + // decode). ret = _hx509_set_digest_alg(signatureAlgorithm, sig_oid, "\x05\x00", 2); if (ret) { @@ -337,65 +311,57 @@ rsa_create_signature(hx509_context context, } } - if (digest_alg) { - DigestInfo di; - memset(&di, 0, sizeof(di)); - - ret = _hx509_create_signature(context, - NULL, - digest_alg, - data, - &di.digestAlgorithm, - &di.digest); - if (ret) - return ret; - ASN1_MALLOC_ENCODE(DigestInfo, - indata.data, - indata.length, - &di, - &size, - ret); - free_DigestInfo(&di); - if (ret) { - hx509_set_error_string(context, 0, ret, "out of memory"); - return ret; - } - if (indata.length != size) - _hx509_abort("internal ASN.1 encoder error"); - } else { - indata = *data; - } - - sig->length = RSA_size(signer->private_key.rsa); - sig->data = malloc(sig->length); - if (sig->data == NULL) { - der_free_octet_string(&indata); - hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + if ((mctx = EVP_MD_CTX_new()) == NULL || + EVP_DigestSignInit(mctx, &pctx, md, NULL, signer->private_key.pkey) <= 0 || + EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PADDING) <= 0 || + EVP_DigestSign(mctx, + NULL, &size, + data->data, data->length) <= 0) { + _hx509_set_error_string_openssl(context, 0, ENOMEM, + "Could not set up to create a signature"); + EVP_MD_CTX_free(mctx); return ENOMEM; } - ret = RSA_private_encrypt(indata.length, indata.data, - sig->data, - signer->private_key.rsa, - RSA_PKCS1_PADDING); - if (indata.data != data->data) - der_free_octet_string(&indata); - if (ret <= 0) { - ret = HX509_CMS_FAILED_CREATE_SIGATURE; - hx509_set_error_string(context, 0, ret, - "RSA private encrypt failed: %d", ret); - return ret; - } - if (sig->length > (size_t)ret) { - size = sig->length - ret; - memmove((uint8_t *)sig->data + size, sig->data, ret); - memset(sig->data, 0, size); - } else if (sig->length < (size_t)ret) - _hx509_abort("RSA signature prelen longer than output len"); + sig->length = size; + sig->data = malloc(sig->length); + if (sig->data == NULL) { + hx509_set_error_string(context, 0, ENOMEM, + "Could not set up to create a signature"); + EVP_MD_CTX_free(mctx); + return ENOMEM; + } + + if (EVP_DigestSign(mctx, + sig->data, &size, + data->data, data->length) <= 0) { + _hx509_set_error_string_openssl(context, 0, + HX509_CMS_FAILED_CREATE_SIGATURE, + "Could not create a signature"); + EVP_MD_CTX_free(mctx); + return HX509_CMS_FAILED_CREATE_SIGATURE; + } + + if (sig->length != size) { + hx509_set_error_string(context, 0, + HX509_CMS_FAILED_CREATE_SIGATURE, + "Could not create a signature (OpenSSL length mismatch)"); + EVP_MD_CTX_free(mctx); + return HX509_CMS_FAILED_CREATE_SIGATURE; + } + + EVP_MD_CTX_free(mctx); return 0; } +static EVP_PKEY * +evp_from_rsa_pkcs1_der(const unsigned char *der, size_t der_len) +{ + return d2i_PrivateKey_ex(EVP_PKEY_RSA, NULL, &der, der_len, + /* libctx */ NULL, /* propq */ NULL); +} + static int rsa_private_key_import(hx509_context context, const AlgorithmIdentifier *keyai, @@ -406,11 +372,9 @@ rsa_private_key_import(hx509_context context, { switch (format) { case HX509_KEY_FORMAT_DER: { - const unsigned char *p = data; - - private_key->private_key.rsa = - d2i_RSAPrivateKey(NULL, &p, len); - if (private_key->private_key.rsa == NULL) { + private_key->private_key.pkey = + evp_from_rsa_pkcs1_der(data, len); + if (private_key->private_key.pkey == NULL) { hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED, "Failed to parse RSA key"); return HX509_PARSING_KEY_FAILED; @@ -431,76 +395,85 @@ rsa_private_key2SPKI(hx509_context context, hx509_private_key private_key, SubjectPublicKeyInfo *spki) { + unsigned char *d = NULL; + unsigned char *p = NULL; + size_t size = 0; int len, ret; memset(spki, 0, sizeof(*spki)); - len = i2d_RSAPublicKey(private_key->private_key.rsa, NULL); + len = i2d_PUBKEY(private_key->private_key.pkey, NULL); if (len < 0) return -1; - spki->subjectPublicKey.data = malloc(len); - if (spki->subjectPublicKey.data == NULL) { - hx509_set_error_string(context, 0, ENOMEM, "malloc - out of memory"); + if ((d = p = malloc(len)) == NULL) { + hx509_set_error_string(context, 0, ENOMEM, + "Could not produce SubjectPublicKeyInfo for private key"); return ENOMEM; } - spki->subjectPublicKey.length = len * 8; - ret = _hx509_set_digest_alg(&spki->algorithm, - ASN1_OID_ID_PKCS1_RSAENCRYPTION, - "\x05\x00", 2); - if (ret) { - hx509_set_error_string(context, 0, ret, "malloc - out of memory"); - free(spki->subjectPublicKey.data); - spki->subjectPublicKey.data = NULL; - spki->subjectPublicKey.length = 0; - return ret; + if (i2d_PUBKEY(private_key->private_key.pkey, &p) < 0) { + _hx509_set_error_string_openssl(context, 0, ENOMEM, + "Could not produce SubjectPublicKeyInfo for private key"); + free(d); + return ENOMEM; } - { - unsigned char *pp = spki->subjectPublicKey.data; - i2d_RSAPublicKey(private_key->private_key.rsa, &pp); + ret = decode_SubjectPublicKeyInfo(d, len, spki, &size); + free(d); + if (ret || size != (size_t)len) { + hx509_set_error_string(context, 0, ret, + "Could not decode a SubjectPublicKeyInfo value from OpenSSL%s", + ret == 0 ? " (length mismatch)" : ""); + free_SubjectPublicKeyInfo(spki); + return ret; } return 0; } +static EVP_PKEY * +generate_rsa_pkey(int bits, int pss) +{ + EVP_PKEY_CTX *ctx = NULL; + EVP_PKEY *pkey = NULL; + + ctx = pss + ? EVP_PKEY_CTX_new_id(EVP_PKEY_RSA_PSS, NULL) + : EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL); + + if (ctx == NULL || + EVP_PKEY_keygen_init(ctx) <= 0 || + EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, bits) <= 0 || + EVP_PKEY_keygen(ctx, &pkey) <= 0) { + + EVP_PKEY_free(pkey); + pkey = NULL; + } + + EVP_PKEY_CTX_free(ctx); + return pkey; +} + static int rsa_generate_private_key(hx509_context context, struct hx509_generate_private_context *ctx, hx509_private_key private_key) { - BIGNUM *e; - int ret; - unsigned long bits; + unsigned long bits = ctx->num_bits ? ctx->num_bits : 2048; - static const int default_rsa_e = 65537; - static const int default_rsa_bits = 2048; - - private_key->private_key.rsa = RSA_new(); - if (private_key->private_key.rsa == NULL) { + private_key->private_key.pkey = generate_rsa_pkey(bits, 0); + if (private_key->private_key.pkey == NULL) { hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED, "Failed to generate RSA key"); return HX509_PARSING_KEY_FAILED; } - e = BN_new(); - BN_set_word(e, default_rsa_e); - - bits = default_rsa_bits; - - if (ctx->num_bits) - bits = ctx->num_bits; - - ret = RSA_generate_key_ex(private_key->private_key.rsa, bits, e, NULL); - BN_free(e); - if (ret != 1) { - hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED, - "Failed to generate RSA key"); - return HX509_PARSING_KEY_FAILED; - } + // XXX Parameterize the digest!! Well, the caller can change this anyways + // since the pkey doesn't know what digest we wanted anyways. + // + // At the very least don't default to SHA-1? private_key->signature_alg = ASN1_OID_ID_PKCS1_SHA1WITHRSAENCRYPTION; - return 0; } @@ -510,35 +483,48 @@ rsa_private_key_export(hx509_context context, hx509_key_format_t format, heim_octet_string *data) { + unsigned char *p = NULL; + size_t size = 0; int ret; data->data = NULL; data->length = 0; switch (format) { - case HX509_KEY_FORMAT_DER: + case HX509_KEY_FORMAT_DER: { - ret = i2d_RSAPrivateKey(key->private_key.rsa, NULL); - if (ret <= 0) { - ret = EINVAL; - hx509_set_error_string(context, 0, ret, - "Private key is not exportable"); - return ret; - } + OSSL_ENCODER_CTX *ctx = + OSSL_ENCODER_CTX_new_for_pkey(key->private_key.pkey, + OSSL_KEYMGMT_SELECT_PRIVATE_KEY, + "DER", + "type-specific", // PKCS#1 for RSA + NULL); + if (ctx == NULL) { + _hx509_set_error_string_openssl(context, 0, ENOMEM, + "Could not allocate a private key encoder"); + return ENOMEM; + } - data->data = malloc(ret); + ret = OSSL_ENCODER_to_data(ctx, &p, &size); + OSSL_ENCODER_CTX_free(ctx); + if (ret != 1) { + _hx509_set_error_string_openssl(context, 0, HX509_CRYPTO_INTERNAL_ERROR, + "Could not encode a private key"); + return HX509_CRYPTO_INTERNAL_ERROR; + } + + data->data = malloc(size); if (data->data == NULL) { ret = ENOMEM; hx509_set_error_string(context, 0, ret, "malloc out of memory"); return ret; } - data->length = ret; + data->length = size; + memcpy(data->data, p, size); - { - unsigned char *p = data->data; - i2d_RSAPrivateKey(key->private_key.rsa, &p); - } + OPENSSL_free(p); break; + } default: return HX509_CRYPTO_KEY_FORMAT_UNSUPPORTED; } @@ -546,21 +532,6 @@ rsa_private_key_export(hx509_context context, return 0; } -static BIGNUM * -rsa_get_internal(hx509_context context, - hx509_private_key key, - const char *type) -{ - if (strcasecmp(type, "rsa-modulus") == 0) { - return BN_dup(key->private_key.rsa->n); - } else if (strcasecmp(type, "rsa-exponent") == 0) { - return BN_dup(key->private_key.rsa->e); - } else - return NULL; -} - - - static hx509_private_key_ops rsa_private_key_ops = { "RSA PRIVATE KEY", ASN1_OID_ID_PKCS1_RSAENCRYPTION, @@ -569,7 +540,7 @@ static hx509_private_key_ops rsa_private_key_ops = { rsa_private_key_export, rsa_private_key_import, rsa_generate_private_key, - rsa_get_internal + NULL }; /* @@ -581,106 +552,69 @@ dsa_verify_signature(hx509_context context, const struct signature_alg *sig_alg, const Certificate *signer, const AlgorithmIdentifier *alg, + const EVP_MD *md, const heim_octet_string *data, const heim_octet_string *sig) { - const SubjectPublicKeyInfo *spi; - DSAPublicKey pk; - DSAParams param; + EVP_PKEY_CTX *pctx = NULL; + EVP_MD_CTX *mctx = NULL; + EVP_PKEY *pkey = NULL; + const unsigned char *p; size_t size; - DSA *dsa; - int ret; + int ret = HX509_CRYPTO_INTERNAL_ERROR; - spi = &signer->tbsCertificate.subjectPublicKeyInfo; + md = md ? md : (sig_alg->evp_md ? sig_alg->evp_md() : NULL); + p = signer->tbsCertificate.subjectPublicKeyInfo._save.data; + size = signer->tbsCertificate.subjectPublicKeyInfo._save.length / 8; - dsa = DSA_new(); - if (dsa == NULL) { - hx509_set_error_string(context, 0, ENOMEM, "out of memory"); - return ENOMEM; - } - - ret = decode_DSAPublicKey(spi->subjectPublicKey.data, - spi->subjectPublicKey.length / 8, - &pk, &size); - if (ret) - goto out; - - dsa->pub_key = heim_int2BN(&pk); - - free_DSAPublicKey(&pk); - - if (dsa->pub_key == NULL) { - ret = ENOMEM; - hx509_set_error_string(context, 0, ret, "out of memory"); + pkey = d2i_PUBKEY(NULL, &p, size); + if (pkey == NULL) { + ret = ENOMEM; // XXX Maybe it's not ENOMEM... + _hx509_set_error_string_openssl(context, 0, ret, "Could not parse SubjectPublicKeyInfo (RSA)"); goto out; } - if (spi->algorithm.parameters == NULL) { - ret = HX509_CRYPTO_SIG_INVALID_FORMAT; - hx509_set_error_string(context, 0, ret, "DSA parameters missing"); - goto out; + if ((mctx = EVP_MD_CTX_new()) == NULL) { + ret = ENOMEM; + _hx509_set_error_string_openssl(context, 0, ret, "out of memory"); + goto out; } - ret = decode_DSAParams(spi->algorithm.parameters->data, - spi->algorithm.parameters->length, - ¶m, - &size); - if (ret) { - hx509_set_error_string(context, 0, ret, "DSA parameters failed to decode"); - goto out; + if (EVP_DigestVerifyInit(mctx, &pctx, md, NULL, pkey) <= 0) { + ret = HX509_CRYPTO_SIG_INVALID_FORMAT; + hx509_set_error_string(context, 0, ret, "digest_verify_init"); + goto out; } - dsa->p = heim_int2BN(¶m.p); - dsa->q = heim_int2BN(¶m.q); - dsa->g = heim_int2BN(¶m.g); - - free_DSAParams(¶m); - - if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL) { - ret = ENOMEM; - hx509_set_error_string(context, 0, ret, "out of memory"); - goto out; - } - - ret = DSA_verify(-1, data->data, data->length, - (unsigned char*)sig->data, sig->length, - dsa); - if (ret == 1) - ret = 0; - else if (ret == 0 || ret == -1) { - ret = HX509_CRYPTO_BAD_SIGNATURE; - hx509_set_error_string(context, 0, ret, "BAD DSA sigature"); - } else { - ret = HX509_CRYPTO_SIG_INVALID_FORMAT; - hx509_set_error_string(context, 0, ret, "Invalid format of DSA sigature"); - } - - out: - DSA_free(dsa); + if (EVP_DigestVerify(mctx, sig->data, sig->length, data->data, data->length) == 1) + ret = 0; +out: + EVP_MD_CTX_free(mctx); /* Also frees pctx */ + EVP_PKEY_free(pkey); return ret; } #if 0 +/* We don't have a dsa_private_key_ops yet, and might never want to */ +static EVP_PKEY * +evp_from_dsa_pkcs1_der(const unsigned char *der, size_t der_len) +{ + return pkey = d2i_PrivateKey_ex(EVP_PKEY_DSA, NULL, &der, der_len, + /* libctx */ NULL, /* propq */ NULL); +} + static int dsa_parse_private_key(hx509_context context, const void *data, size_t len, hx509_private_key private_key) { - const unsigned char *p = data; - - private_key->private_key.dsa = - d2i_DSAPrivateKey(NULL, &p, len); - if (private_key->private_key.dsa == NULL) + private_key->private_key.pkey = evp_from_dsa_pkcs1_der(data, len); + if (private_key->private_key.pkey == NULL) return EINVAL; private_key->signature_alg = ASN1_OID_ID_DSA_WITH_SHA1; - return 0; -/* else */ - hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED, - "No support to parse DSA keys"); - return HX509_PARSING_KEY_FAILED; } #endif @@ -689,6 +623,7 @@ evp_md_create_signature(hx509_context context, const struct signature_alg *sig_alg, const hx509_private_key signer, const AlgorithmIdentifier *alg, + const EVP_MD *md, const heim_octet_string *data, AlgorithmIdentifier *signatureAlgorithm, heim_octet_string *sig) @@ -696,6 +631,8 @@ evp_md_create_signature(hx509_context context, size_t sigsize = EVP_MD_size(sig_alg->evp_md()); EVP_MD_CTX *ctx; + md = md ? md : (sig_alg->evp_md ? sig_alg->evp_md() : NULL); + memset(sig, 0, sizeof(*sig)); if (signatureAlgorithm) { @@ -715,7 +652,7 @@ evp_md_create_signature(hx509_context context, sig->length = sigsize; ctx = EVP_MD_CTX_create(); - EVP_DigestInit_ex(ctx, sig_alg->evp_md(), NULL); + EVP_DigestInit_ex(ctx, md, NULL); EVP_DigestUpdate(ctx, data->data, data->length); EVP_DigestFinal_ex(ctx, sig->data, NULL); EVP_MD_CTX_destroy(ctx); @@ -729,6 +666,7 @@ evp_md_verify_signature(hx509_context context, const struct signature_alg *sig_alg, const Certificate *signer, const AlgorithmIdentifier *alg, + const EVP_MD *md, const heim_octet_string *data, const heim_octet_string *sig) { @@ -736,6 +674,8 @@ evp_md_verify_signature(hx509_context context, EVP_MD_CTX *ctx; size_t sigsize = EVP_MD_size(sig_alg->evp_md()); + md = md ? md : (sig_alg->evp_md ? sig_alg->evp_md() : NULL); + if (sig->length != sigsize || sigsize > sizeof(digest)) { hx509_set_error_string(context, 0, HX509_CRYPTO_SIG_INVALID_FORMAT, "SHA256 sigature has wrong length"); @@ -743,7 +683,7 @@ evp_md_verify_signature(hx509_context context, } ctx = EVP_MD_CTX_create(); - EVP_DigestInit_ex(ctx, sig_alg->evp_md(), NULL); + EVP_DigestInit_ex(ctx, md, NULL); EVP_DigestUpdate(ctx, data->data, data->length); EVP_DigestFinal_ex(ctx, digest, NULL); EVP_MD_CTX_destroy(ctx); @@ -783,7 +723,7 @@ static const struct signature_alg pkcs1_rsa_sha1_alg = { NULL, PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK, 0, - NULL, + EVP_sha1, rsa_verify_signature, rsa_create_signature, 0 @@ -797,7 +737,7 @@ static const struct signature_alg rsa_with_sha512_alg = { &_hx509_signature_sha512_data, PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK, 0, - NULL, + EVP_sha512, rsa_verify_signature, rsa_create_signature, 0 @@ -811,7 +751,7 @@ static const struct signature_alg rsa_with_sha384_alg = { &_hx509_signature_sha384_data, PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK, 0, - NULL, + EVP_sha384, rsa_verify_signature, rsa_create_signature, 0 @@ -825,7 +765,7 @@ static const struct signature_alg rsa_with_sha256_alg = { &_hx509_signature_sha256_data, PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK, 0, - NULL, + EVP_sha256, rsa_verify_signature, rsa_create_signature, 0 @@ -839,7 +779,7 @@ static const struct signature_alg rsa_with_sha1_alg = { &_hx509_signature_sha1_data, PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK, 0, - NULL, + EVP_sha1, rsa_verify_signature, rsa_create_signature, 0 @@ -853,7 +793,7 @@ static const struct signature_alg rsa_with_sha1_alg_secsig = { &_hx509_signature_sha1_data, PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK, 0, - NULL, + EVP_sha1, rsa_verify_signature, rsa_create_signature, 0 @@ -867,7 +807,7 @@ static const struct signature_alg rsa_with_md5_alg = { &_hx509_signature_md5_data, PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|WEAK_SIG_ALG, 1230739889, - NULL, + EVP_md5, rsa_verify_signature, rsa_create_signature, 0 @@ -881,7 +821,7 @@ static const struct signature_alg dsa_sha1_alg = { &_hx509_signature_sha1_data, PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG, 0, - NULL, + EVP_sha1, dsa_verify_signature, /* create_signature */ NULL, 0 @@ -962,7 +902,16 @@ static const struct signature_alg md5_alg = { * compatible" type (type is ECDSA, RSA, DSA, none, etc) */ +extern const struct signature_alg ecdsa_with_sha512_alg; +extern const struct signature_alg ecdsa_with_sha384_alg; +extern const struct signature_alg ecdsa_with_sha256_alg; +extern const struct signature_alg ecdsa_with_sha1_alg; +extern const struct signature_alg ed25519_alg; +extern const struct signature_alg ed448_alg; + static const struct signature_alg *sig_algs[] = { + &ed25519_alg, + &ed448_alg, &ecdsa_with_sha512_alg, &ecdsa_with_sha384_alg, &ecdsa_with_sha256_alg, @@ -1027,10 +976,14 @@ alg_for_privatekey(const hx509_private_key pk, int type) * */ extern hx509_private_key_ops ecdsa_private_key_ops; +extern hx509_private_key_ops ed25519_private_key_ops; +extern hx509_private_key_ops ed448_private_key_ops; static struct hx509_private_key_ops *private_algs[] = { &rsa_private_key_ops, &ecdsa_private_key_ops, + &ed25519_private_key_ops, + &ed448_private_key_ops, NULL }; @@ -1095,64 +1048,87 @@ HX509_LIB_FUNCTION int HX509_LIB_CALL _hx509_verify_signature(hx509_context context, const hx509_cert cert, const AlgorithmIdentifier *alg, + const AlgorithmIdentifier *digest_alg, const heim_octet_string *data, const heim_octet_string *sig) { - const struct signature_alg *md; + const struct signature_alg *md = NULL; + const struct signature_alg *sa; const Certificate *signer = NULL; + const EVP_MD *evp_md; if (cert) signer = _hx509_get_cert(cert); - md = _hx509_find_sig_alg(&alg->algorithm); - if (md == NULL) { + if (digest_alg && + (md = _hx509_find_sig_alg(&digest_alg->algorithm)) == NULL) { hx509_clear_error_string(context); return HX509_SIG_ALG_NO_SUPPORTED; } - if (signer && (md->flags & PROVIDE_CONF) == 0) { + + evp_md = md ? md->evp_md() : NULL; + + sa = _hx509_find_sig_alg(&alg->algorithm); + if (sa == NULL) { + hx509_clear_error_string(context); + return HX509_SIG_ALG_NO_SUPPORTED; + } + if (signer && (sa->flags & PROVIDE_CONF) == 0) { hx509_clear_error_string(context); return HX509_CRYPTO_SIG_NO_CONF; } - if (signer == NULL && (md->flags & REQUIRE_SIGNER)) { + if (signer == NULL && (sa->flags & REQUIRE_SIGNER)) { hx509_clear_error_string(context); return HX509_CRYPTO_SIGNATURE_WITHOUT_SIGNER; } - if (md->key_oid && signer) { + if (sa->key_oid && signer) { const SubjectPublicKeyInfo *spi; spi = &signer->tbsCertificate.subjectPublicKeyInfo; - if (der_heim_oid_cmp(&spi->algorithm.algorithm, md->key_oid) != 0) { + if (der_heim_oid_cmp(&spi->algorithm.algorithm, sa->key_oid) != 0) { hx509_clear_error_string(context); return HX509_SIG_ALG_DONT_MATCH_KEY_ALG; } } - return (*md->verify_signature)(context, md, signer, alg, data, sig); + return (*sa->verify_signature)(context, sa, signer, alg, evp_md, + data, sig); } HX509_LIB_FUNCTION int HX509_LIB_CALL _hx509_create_signature(hx509_context context, const hx509_private_key signer, const AlgorithmIdentifier *alg, + const AlgorithmIdentifier *digest_alg, const heim_octet_string *data, AlgorithmIdentifier *signatureAlgorithm, heim_octet_string *sig) { - const struct signature_alg *md; + const struct signature_alg *md = NULL; + const struct signature_alg *sa; + const EVP_MD *evp_md; - md = _hx509_find_sig_alg(&alg->algorithm); - if (md == NULL) { + if (digest_alg && + (md = _hx509_find_sig_alg(&digest_alg->algorithm)) == NULL) { + hx509_clear_error_string(context); + return HX509_SIG_ALG_NO_SUPPORTED; + } + + evp_md = md ? md->evp_md() : NULL; + + sa = _hx509_find_sig_alg(&alg->algorithm); + if (sa == NULL) { hx509_set_error_string(context, 0, HX509_SIG_ALG_NO_SUPPORTED, "algorithm no supported"); return HX509_SIG_ALG_NO_SUPPORTED; } - if (signer && (md->flags & PROVIDE_CONF) == 0) { + if (signer && (sa->flags & PROVIDE_CONF) == 0) { hx509_set_error_string(context, 0, HX509_SIG_ALG_NO_SUPPORTED, "algorithm provides no conf"); return HX509_CRYPTO_SIG_NO_CONF; } - return (*md->create_signature)(context, md, signer, alg, data, + return (*sa->create_signature)(context, sa, signer, alg, evp_md, data, signatureAlgorithm, sig); } @@ -1167,7 +1143,7 @@ _hx509_create_signature_bitstring(hx509_context context, heim_octet_string os; int ret; - ret = _hx509_create_signature(context, signer, alg, + ret = _hx509_create_signature(context, signer, alg, NULL, data, signatureAlgorithm, &os); if (ret) return ret; @@ -1184,100 +1160,129 @@ _hx509_public_encrypt(hx509_context context, heim_octet_string *ciphertext) { const SubjectPublicKeyInfo *spi; - unsigned char *to; - int tosize; - int ret; - RSA *rsa; - size_t size; const unsigned char *p; + unsigned char *to; + size_t size, tosize = 0; + EVP_PKEY_CTX *pctx; + EVP_PKEY *pkey; + int ret; ciphertext->data = NULL; ciphertext->length = 0; spi = &cert->tbsCertificate.subjectPublicKeyInfo; - p = spi->subjectPublicKey.data; - size = spi->subjectPublicKey.length / 8; + p = spi->_save.data; + size = spi->_save.length; - rsa = d2i_RSAPublicKey(NULL, &p, size); - if (rsa == NULL) { + pkey = d2i_PUBKEY(NULL, &p, size); + if (pkey == NULL) { + _hx509_set_error_string_openssl(context, 0, HX509_CRYPTO_INTERNAL_ERROR, + "Could not parse SubjectPublicKeyInfo"); + return HX509_CRYPTO_INTERNAL_ERROR; + } + + pctx = EVP_PKEY_CTX_new_from_pkey(context->ossl->libctx, pkey, + context->ossl->propq); + if (pctx == NULL || + // XXX Want OEAP instead pls + EVP_PKEY_encrypt_init(pctx) != 1 || + EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PADDING) <= 0 || + EVP_PKEY_encrypt(pctx, + NULL, &tosize, + cleartext->data, cleartext->length) <= 0) { + + _hx509_set_error_string_openssl(context, 0, ENOMEM, + "Could not set up to encrypt to a public key"); + EVP_PKEY_CTX_free(pctx); + EVP_PKEY_free(pkey); + return ENOMEM; + } + + if ((to = malloc(tosize)) == NULL) { + EVP_PKEY_CTX_free(pctx); + EVP_PKEY_free(pkey); hx509_set_error_string(context, 0, ENOMEM, "out of memory"); return ENOMEM; } - tosize = RSA_size(rsa); - to = malloc(tosize); - if (to == NULL) { - RSA_free(rsa); - hx509_set_error_string(context, 0, ENOMEM, "out of memory"); - return ENOMEM; + if (EVP_PKEY_encrypt(pctx, + to, &tosize, + cleartext->data, cleartext->length) <= 0) { + _hx509_set_error_string_openssl(context, 0, HX509_CRYPTO_INTERNAL_ERROR, + "Could not encrypt to a public key"); + EVP_PKEY_CTX_free(pctx); + EVP_PKEY_free(pkey); + return HX509_CRYPTO_INTERNAL_ERROR; } - ret = RSA_public_encrypt(cleartext->length, - (unsigned char *)cleartext->data, - to, rsa, RSA_PKCS1_PADDING); - RSA_free(rsa); - if (ret <= 0) { - free(to); - hx509_set_error_string(context, 0, HX509_CRYPTO_RSA_PUBLIC_ENCRYPT, - "RSA public encrypt failed with %d", ret); - return HX509_CRYPTO_RSA_PUBLIC_ENCRYPT; - } - if (ret > tosize) - _hx509_abort("internal rsa decryption failure: ret > tosize"); - - ciphertext->length = ret; + ciphertext->length = tosize; ciphertext->data = to; + // XXX Want OEAP instead pls ret = der_copy_oid(ASN1_OID_ID_PKCS1_RSAENCRYPTION, encryption_oid); if (ret) { der_free_octet_string(ciphertext); hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + EVP_PKEY_CTX_free(pctx); + EVP_PKEY_free(pkey); return ENOMEM; } + EVP_PKEY_CTX_free(pctx); + EVP_PKEY_free(pkey); return 0; } HX509_LIB_FUNCTION int HX509_LIB_CALL hx509_private_key_private_decrypt(hx509_context context, - const heim_octet_string *ciphertext, - const heim_oid *encryption_oid, - hx509_private_key p, - heim_octet_string *cleartext) + const heim_octet_string *ciphertext, + const heim_oid *encryption_oid, + hx509_private_key p, + heim_octet_string *cleartext) { - int ret; + EVP_PKEY_CTX *pctx; + size_t len; cleartext->data = NULL; cleartext->length = 0; - if (p->private_key.rsa == NULL) { + if (p->private_key.pkey == NULL) { hx509_set_error_string(context, 0, HX509_PRIVATE_KEY_MISSING, - "Private RSA key missing"); + "Private key missing"); return HX509_PRIVATE_KEY_MISSING; } - cleartext->length = RSA_size(p->private_key.rsa); - cleartext->data = malloc(cleartext->length); + pctx = EVP_PKEY_CTX_new_from_pkey(context->ossl->libctx, p->private_key.pkey, + context->ossl->propq); + if (pctx == NULL || + EVP_PKEY_decrypt_init(pctx) != 1 || + EVP_PKEY_decrypt(pctx, + NULL, &len, + ciphertext->data, ciphertext->length) < 0) { + _hx509_set_error_string_openssl(context, 0, ENOMEM, + "Could not set up to decrypt with a private key"); + EVP_PKEY_CTX_free(pctx); + return ENOMEM; + } + + cleartext->length = len; + cleartext->data = malloc(len); if (cleartext->data == NULL) { - hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + hx509_set_error_string(context, 0, ENOMEM, + "Could not set up to decrypt with a private key"); + EVP_PKEY_CTX_free(pctx); return ENOMEM; } - ret = RSA_private_decrypt(ciphertext->length, ciphertext->data, - cleartext->data, - p->private_key.rsa, - RSA_PKCS1_PADDING); - if (ret <= 0) { - der_free_octet_string(cleartext); - hx509_set_error_string(context, 0, HX509_CRYPTO_RSA_PRIVATE_DECRYPT, - "Failed to decrypt using private key: %d", ret); - return HX509_CRYPTO_RSA_PRIVATE_DECRYPT; + + if (EVP_PKEY_decrypt(pctx, cleartext->data, &cleartext->length, + ciphertext->data, ciphertext->length) < 0) { + hx509_set_error_string(context, 0, HX509_CRYPTO_INTERNAL_ERROR, + "Could not decrypt with a private key"); + EVP_PKEY_CTX_free(pctx); + return HX509_CRYPTO_INTERNAL_ERROR; } - if (cleartext->length < (size_t)ret) - _hx509_abort("internal rsa decryption failure: ret > tosize"); - - cleartext->length = ret; - + EVP_PKEY_CTX_free(pctx); return 0; } @@ -1363,10 +1368,14 @@ _hx509_generate_private_key_init(hx509_context context, { *ctx = NULL; - if (der_heim_oid_cmp(oid, ASN1_OID_ID_PKCS1_RSAENCRYPTION) != 0) { - hx509_set_error_string(context, 0, EINVAL, - "private key not an RSA key"); - return EINVAL; + /* Check that we support this key type */ + if (der_heim_oid_cmp(oid, ASN1_OID_ID_PKCS1_RSAENCRYPTION) != 0 && + der_heim_oid_cmp(oid, ASN1_OID_ID_ECPUBLICKEY) != 0 && + der_heim_oid_cmp(oid, ASN1_OID_ID_ED25519) != 0 && + der_heim_oid_cmp(oid, ASN1_OID_ID_ED448) != 0) { + hx509_set_error_string(context, 0, HX509_ALG_NOT_SUPP, + "unsupported key type for generation"); + return HX509_ALG_NOT_SUPP; } *ctx = calloc(1, sizeof(**ctx)); @@ -1517,12 +1526,12 @@ hx509_private_key_init(hx509_private_key *key, hx509_private_key_ops *ops, void *keydata) { + (void) keydata; *key = calloc(1, sizeof(**key)); if (*key == NULL) return ENOMEM; (*key)->ref = 1; (*key)->ops = ops; - (*key)->private_key.keydata = keydata; return 0; } @@ -1544,36 +1553,31 @@ _hx509_private_pem_name(hx509_private_key key) } HX509_LIB_FUNCTION int HX509_LIB_CALL -hx509_private_key_free(hx509_private_key *key) +hx509_private_key_free(hx509_private_key *keyp) { - if (key == NULL || *key == NULL) + hx509_private_key key; + + if (keyp == NULL || (key = *keyp) == NULL) return 0; - if ((*key)->ref == 0) + *keyp = NULL; + if (key->ref == 0) // XXX Use atomics; don't check for zero anyways _hx509_abort("key refcount == 0 on free"); - if (--(*key)->ref > 0) + if (--key->ref > 0) // XXX Use atomics return 0; - if ((*key)->ops && der_heim_oid_cmp((*key)->ops->key_oid, ASN1_OID_ID_PKCS1_RSAENCRYPTION) == 0) { - if ((*key)->private_key.rsa) - RSA_free((*key)->private_key.rsa); - } else if ((*key)->ops && der_heim_oid_cmp((*key)->ops->key_oid, - ASN1_OID_ID_ECPUBLICKEY) == 0 && - (*key)->private_key.ecdsa != NULL) { - _hx509_private_eckey_free((*key)->private_key.ecdsa); - } - (*key)->private_key.rsa = NULL; - free(*key); - *key = NULL; + EVP_PKEY_free(key->private_key.pkey); + key->private_key.pkey = NULL; + free(key); return 0; } HX509_LIB_FUNCTION void HX509_LIB_CALL hx509_private_key_assign_rsa(hx509_private_key key, void *ptr) { - if (key->private_key.rsa) - RSA_free(key->private_key.rsa); - key->private_key.rsa = ptr; + if (key->private_key.pkey) + EVP_PKEY_free(key->private_key.pkey); + key->private_key.pkey = ptr; key->signature_alg = ASN1_OID_ID_PKCS1_SHA1WITHRSAENCRYPTION; key->md = &pkcs1_rsa_sha1_alg; } @@ -1598,14 +1602,13 @@ _hx509_private_key_exportable(hx509_private_key key) return 1; } +/* XXX Remove */ HX509_LIB_FUNCTION BIGNUM * HX509_LIB_CALL _hx509_private_key_get_internal(hx509_context context, hx509_private_key key, const char *type) { - if (key->ops->get_internal == NULL) - return NULL; - return (*key->ops->get_internal)(context, key, type); + return NULL; } HX509_LIB_FUNCTION int HX509_LIB_CALL @@ -1652,7 +1655,7 @@ _hx509_private_key_export(hx509_context context, &ki, &size, ret); free_PKCS8PrivateKeyInfo(&ki); if (ret == 0 && size != data->length) - ret = EINVAL; + ret = HX509_CRYPTO_INTERNAL_ERROR; if (ret) hx509_set_error_string(context, 0, ret, "Private key PKCS#8 encoding failed"); @@ -1805,15 +1808,15 @@ CMSRC2CBCParam_set(hx509_context context, const heim_octet_string *param, } switch(rc2param.rc2ParameterVersion) { case 160: - crypto->c = EVP_rc2_40_cbc(); + crypto->c = context->ossl ? context->ossl->rc2_40_cbc : EVP_rc2_40_cbc(); p->maximum_effective_key = 40; break; case 120: - crypto->c = EVP_rc2_64_cbc(); + crypto->c = context->ossl ? context->ossl->rc2_64_cbc : EVP_rc2_64_cbc(); p->maximum_effective_key = 64; break; case 58: - crypto->c = EVP_rc2_cbc(); + crypto->c = context->ossl ? context->ossl->rc2_cbc : EVP_rc2_cbc(); p->maximum_effective_key = 128; break; default: @@ -2124,7 +2127,7 @@ hx509_crypto_encrypt(hx509_crypto crypto, const heim_octet_string *ivec, heim_octet_string **ciphertext) { - EVP_CIPHER_CTX evp; + EVP_CIPHER_CTX *evp; size_t padsize, bsize; int ret; @@ -2136,13 +2139,10 @@ hx509_crypto_encrypt(hx509_crypto crypto, assert(EVP_CIPHER_iv_length(crypto->c) == (int)ivec->length); - EVP_CIPHER_CTX_init(&evp); - - ret = EVP_CipherInit_ex(&evp, crypto->c, NULL, - crypto->key.data, ivec->data, 1); - if (ret != 1) { - EVP_CIPHER_CTX_cleanup(&evp); - ret = HX509_CRYPTO_INTERNAL_ERROR; + if ((evp = EVP_CIPHER_CTX_new()) == NULL || + EVP_CipherInit_ex(evp, crypto->c, NULL, + crypto->key.data, ivec->data, 1) <= 0) { + ret = ENOMEM; goto out; } @@ -2181,10 +2181,10 @@ hx509_crypto_encrypt(hx509_crypto crypto, *p++ = padsize; } - ret = EVP_Cipher(&evp, (*ciphertext)->data, + ret = EVP_Cipher(evp, (*ciphertext)->data, (*ciphertext)->data, length + padsize); - if (ret != 1) { + if (ret != length + padsize) { ret = HX509_CRYPTO_INTERNAL_ERROR; goto out; } @@ -2200,7 +2200,7 @@ hx509_crypto_encrypt(hx509_crypto crypto, *ciphertext = NULL; } } - EVP_CIPHER_CTX_cleanup(&evp); + EVP_CIPHER_CTX_free(evp); return ret; } @@ -2212,7 +2212,7 @@ hx509_crypto_decrypt(hx509_crypto crypto, heim_octet_string *ivec, heim_octet_string *clear) { - EVP_CIPHER_CTX evp; + EVP_CIPHER_CTX *evp = NULL; void *idata = NULL; int ret; @@ -2223,6 +2223,12 @@ hx509_crypto_decrypt(hx509_crypto crypto, (crypto->flags & ALLOW_WEAK) == 0) return HX509_CRYPTO_ALGORITHM_BEST_BEFORE; + /* + * Note: The legacy provider for weak crypto (RC2, 3DES-CBC, etc.) used in + * PKCS#12 is now loaded during hx509_context_init() and unloaded during + * hx509_context_free(). This ensures proper cleanup without memory leaks. + */ + if (ivec && EVP_CIPHER_iv_length(crypto->c) < (int)ivec->length) return HX509_CRYPTO_INTERNAL_ERROR; @@ -2232,27 +2238,25 @@ hx509_crypto_decrypt(hx509_crypto crypto, if (ivec) idata = ivec->data; - EVP_CIPHER_CTX_init(&evp); + if ((evp = EVP_CIPHER_CTX_new()) == NULL) + return ENOMEM; - ret = EVP_CipherInit_ex(&evp, crypto->c, NULL, - crypto->key.data, idata, 0); - if (ret != 1) { - EVP_CIPHER_CTX_cleanup(&evp); - return HX509_CRYPTO_INTERNAL_ERROR; + if (EVP_CipherInit_ex(evp, crypto->c, NULL, crypto->key.data, idata, 0) <= 0) { + ret = HX509_CRYPTO_INTERNAL_ERROR; + goto out; } clear->length = length; clear->data = malloc(length); if (clear->data == NULL) { - EVP_CIPHER_CTX_cleanup(&evp); - clear->length = 0; - return ENOMEM; + ret = ENOMEM; + goto out; } - if (EVP_Cipher(&evp, clear->data, data, length) != 1) { - return HX509_CRYPTO_INTERNAL_ERROR; + if (EVP_Cipher(evp, clear->data, data, length) <= 0) { + ret = HX509_CRYPTO_INTERNAL_ERROR; + goto out; } - EVP_CIPHER_CTX_cleanup(&evp); if ((crypto->flags & PADDING_PKCS7) && EVP_CIPHER_block_size(crypto->c) > 1) { int padsize; @@ -2280,9 +2284,11 @@ hx509_crypto_decrypt(hx509_crypto crypto, } } + EVP_CIPHER_CTX_free(evp); return 0; out: + EVP_CIPHER_CTX_free(evp); if (clear->data) free(clear->data); clear->data = NULL; @@ -2361,54 +2367,57 @@ out: } static const heim_oid * -find_string2key(const heim_oid *oid, +find_string2key(hx509_context context, + const heim_oid *oid, const EVP_CIPHER **c, const EVP_MD **md, PBE_string2key_func *s2k) { + hx509_context_ossl ossl = context ? context->ossl : NULL; + if (der_heim_oid_cmp(oid, ASN1_OID_ID_PBEWITHSHAAND40BITRC2_CBC) == 0) { - *c = EVP_rc2_40_cbc(); + *c = ossl ? ossl->rc2_40_cbc : EVP_rc2_40_cbc(); if (*c == NULL) return NULL; - *md = EVP_sha1(); + *md = ossl ? ossl->sha1 : EVP_sha1(); if (*md == NULL) return NULL; *s2k = PBE_string2key; return &asn1_oid_private_rc2_40; } else if (der_heim_oid_cmp(oid, ASN1_OID_ID_PBEWITHSHAAND128BITRC2_CBC) == 0) { - *c = EVP_rc2_cbc(); + *c = ossl ? ossl->rc2_cbc : EVP_rc2_cbc(); if (*c == NULL) return NULL; - *md = EVP_sha1(); + *md = ossl ? ossl->sha1 : EVP_sha1(); if (*md == NULL) return NULL; *s2k = PBE_string2key; return ASN1_OID_ID_PKCS3_RC2_CBC; #if 0 } else if (der_heim_oid_cmp(oid, ASN1_OID_ID_PBEWITHSHAAND40BITRC4) == 0) { - *c = EVP_rc4_40(); + *c = ossl ? ossl->rc4_40 : EVP_rc4_40(); if (*c == NULL) return NULL; - *md = EVP_sha1(); + *md = ossl ? ossl->sha1 : EVP_sha1(); if (*md == NULL) return NULL; *s2k = PBE_string2key; return NULL; } else if (der_heim_oid_cmp(oid, ASN1_OID_ID_PBEWITHSHAAND128BITRC4) == 0) { - *c = EVP_rc4(); + *c = ossl ? ossl->rc4 : EVP_rc4(); if (*c == NULL) return NULL; - *md = EVP_sha1(); + *md = ossl ? ossl->sha1 : EVP_sha1(); if (*md == NULL) return NULL; *s2k = PBE_string2key; return ASN1_OID_ID_PKCS3_RC4; #endif } else if (der_heim_oid_cmp(oid, ASN1_OID_ID_PBEWITHSHAAND3_KEYTRIPLEDES_CBC) == 0) { - *c = EVP_des_ede3_cbc(); + *c = ossl ? ossl->des_ede3_cbc : EVP_des_ede3_cbc(); if (*c == NULL) return NULL; - *md = EVP_sha1(); + *md = ossl ? ossl->sha1 : EVP_sha1(); if (*md == NULL) return NULL; *s2k = PBE_string2key; @@ -2433,6 +2442,240 @@ _hx509_pbe_encrypt(hx509_context context, return EINVAL; } +/* + * Try PBES2 decryption - returns 1 if handled (success or error), 0 if not PBES2 + */ +static int +try_pbes2_decrypt(hx509_context context, + hx509_lock lock, + const AlgorithmIdentifier *ai, + const heim_octet_string *econtent, + heim_octet_string *content) +{ + const struct _hx509_password *pw; + PBES2_params pbes2; + PBKDF2_params pbkdf2; + const EVP_MD *prf_md = NULL; + const EVP_CIPHER *cipher = NULL; + const heim_oid *enc_oid = NULL; + hx509_context_ossl ossl = context ? context->ossl : NULL; + heim_octet_string key, iv, iv_param; + int ret; + size_t i; + + memset(&pbes2, 0, sizeof(pbes2)); + memset(&pbkdf2, 0, sizeof(pbkdf2)); + memset(&key, 0, sizeof(key)); + memset(&iv, 0, sizeof(iv)); + memset(&iv_param, 0, sizeof(iv_param)); + memset(content, 0, sizeof(*content)); + + /* Check if this is PBES2 */ + if (der_heim_oid_cmp(&ai->algorithm, ASN1_OID_ID_PBES2) != 0) + return -1; /* Not PBES2, caller should try legacy PBE */ + + if (ai->parameters == NULL) { + hx509_set_error_string(context, 0, HX509_ALG_NOT_SUPP, + "PBES2 missing parameters"); + return HX509_ALG_NOT_SUPP; + } + + ret = decode_PBES2_params(ai->parameters->data, ai->parameters->length, + &pbes2, NULL); + if (ret) { + hx509_set_error_string(context, 0, ret, + "Failed to decode PBES2 parameters"); + return ret; + } + + /* Check that the KDF is PBKDF2 */ + if (der_heim_oid_cmp(&pbes2.keyDerivationFunc.algorithm, + ASN1_OID_ID_PBKDF2) != 0) { + hx509_set_error_string(context, 0, HX509_ALG_NOT_SUPP, + "PBES2 KDF algorithm not supported (only PBKDF2)"); + ret = HX509_ALG_NOT_SUPP; + goto out; + } + + /* Decode PBKDF2 parameters */ + if (pbes2.keyDerivationFunc.parameters == NULL) { + hx509_set_error_string(context, 0, HX509_ALG_NOT_SUPP, + "PBKDF2 missing parameters"); + ret = HX509_ALG_NOT_SUPP; + goto out; + } + + ret = decode_PBKDF2_params(pbes2.keyDerivationFunc.parameters->data, + pbes2.keyDerivationFunc.parameters->length, + &pbkdf2, NULL); + if (ret) { + hx509_set_error_string(context, 0, ret, + "Failed to decode PBKDF2 parameters"); + goto out; + } + + /* Determine the PRF (defaults to HMAC-SHA1) */ + if (pbkdf2.prf == NULL) { + prf_md = ossl ? ossl->sha1 : EVP_sha1(); + } else if (der_heim_oid_cmp(&pbkdf2.prf->algorithm, + ASN1_OID_ID_HMACWITHSHA1) == 0) { + prf_md = ossl ? ossl->sha1 : EVP_sha1(); + } else if (der_heim_oid_cmp(&pbkdf2.prf->algorithm, + ASN1_OID_ID_HMACWITHSHA256) == 0) { + prf_md = ossl ? ossl->sha256 : EVP_sha256(); + } else if (der_heim_oid_cmp(&pbkdf2.prf->algorithm, + ASN1_OID_ID_HMACWITHSHA384) == 0) { + prf_md = ossl ? ossl->sha384 : EVP_sha384(); + } else if (der_heim_oid_cmp(&pbkdf2.prf->algorithm, + ASN1_OID_ID_HMACWITHSHA512) == 0) { + prf_md = ossl ? ossl->sha512 : EVP_sha512(); + } else { + hx509_set_error_string(context, 0, HX509_ALG_NOT_SUPP, + "PBKDF2 PRF algorithm not supported"); + ret = HX509_ALG_NOT_SUPP; + goto out; + } + + if (prf_md == NULL) { + ret = HX509_ALG_NOT_SUPP; + goto out; + } + + /* Determine the encryption cipher + * Note: Use the rfc2459 OID macros (ASN1_OID_ID_AES_*_CBC) for enc_oid + * since those are what hx509_crypto_init() uses for cipher lookup + */ + if (der_heim_oid_cmp(&pbes2.encryptionScheme.algorithm, + ASN1_OID_ID_AES_128_CBC) == 0) { + cipher = ossl ? ossl->aes_128_cbc : EVP_aes_128_cbc(); + enc_oid = ASN1_OID_ID_AES_128_CBC; + } else if (der_heim_oid_cmp(&pbes2.encryptionScheme.algorithm, + ASN1_OID_ID_AES_192_CBC) == 0) { + cipher = ossl ? ossl->aes_192_cbc : EVP_aes_192_cbc(); + enc_oid = ASN1_OID_ID_AES_192_CBC; + } else if (der_heim_oid_cmp(&pbes2.encryptionScheme.algorithm, + ASN1_OID_ID_AES_256_CBC) == 0) { + cipher = ossl ? ossl->aes_256_cbc : EVP_aes_256_cbc(); + enc_oid = ASN1_OID_ID_AES_256_CBC; + } else if (der_heim_oid_cmp(&pbes2.encryptionScheme.algorithm, + ASN1_OID_ID_PKCS3_DES_EDE3_CBC) == 0) { + cipher = ossl ? ossl->des_ede3_cbc : EVP_des_ede3_cbc(); + enc_oid = ASN1_OID_ID_PKCS3_DES_EDE3_CBC; + } else { + hx509_set_error_string(context, 0, HX509_ALG_NOT_SUPP, + "PBES2 encryption algorithm not supported"); + ret = HX509_ALG_NOT_SUPP; + goto out; + } + + if (cipher == NULL) { + ret = HX509_ALG_NOT_SUPP; + goto out; + } + + /* Extract the IV from the encryption scheme parameters */ + if (pbes2.encryptionScheme.parameters == NULL) { + hx509_set_error_string(context, 0, HX509_CRYPTO_INTERNAL_ERROR, + "PBES2 encryption scheme missing IV"); + ret = HX509_CRYPTO_INTERNAL_ERROR; + goto out; + } + + ret = decode_PKCS12_OctetString(pbes2.encryptionScheme.parameters->data, + pbes2.encryptionScheme.parameters->length, + &iv_param, NULL); + if (ret) { + hx509_set_error_string(context, 0, ret, + "Failed to decode PBES2 IV"); + goto out; + } + + if (iv_param.length != (size_t)EVP_CIPHER_iv_length(cipher)) { + hx509_set_error_string(context, 0, HX509_CRYPTO_INTERNAL_ERROR, + "PBES2 IV length mismatch"); + ret = HX509_CRYPTO_INTERNAL_ERROR; + goto out; + } + + /* Allocate key and IV buffers */ + key.length = EVP_CIPHER_key_length(cipher); + key.data = malloc(key.length); + if (key.data == NULL) { + ret = ENOMEM; + hx509_clear_error_string(context); + goto out; + } + + iv.length = EVP_CIPHER_iv_length(cipher); + iv.data = malloc(iv.length); + if (iv.data == NULL) { + ret = ENOMEM; + hx509_clear_error_string(context); + goto out; + } + memcpy(iv.data, iv_param.data, iv.length); + + pw = _hx509_lock_get_passwords(lock); + + ret = HX509_CRYPTO_INTERNAL_ERROR; + for (i = 0; i < pw->len + 1; i++) { + hx509_crypto crypto; + const char *password; + int passwordlen; + + if (i < pw->len) + password = pw->val[i]; + else if (i < pw->len + 1) + password = ""; + else + password = NULL; + + passwordlen = password ? strlen(password) : 0; + + /* Derive the key using PBKDF2 */ + if (PKCS5_PBKDF2_HMAC(password, passwordlen, + pbkdf2.salt.data, pbkdf2.salt.length, + pbkdf2.iterationCount, + prf_md, + key.length, key.data) != 1) { + hx509_set_error_string(context, 0, HX509_CRYPTO_INTERNAL_ERROR, + "PBKDF2 key derivation failed"); + ret = HX509_CRYPTO_INTERNAL_ERROR; + goto out; + } + + /* Create the crypto context */ + ret = hx509_crypto_init(context, NULL, enc_oid, &crypto); + if (ret) + goto out; + + ret = hx509_crypto_set_key_data(crypto, key.data, key.length); + if (ret) { + hx509_crypto_destroy(crypto); + goto out; + } + + ret = hx509_crypto_decrypt(crypto, + econtent->data, + econtent->length, + &iv, + content); + hx509_crypto_destroy(crypto); + if (ret == 0) + goto out; + } + +out: + free_PBES2_params(&pbes2); + free_PBKDF2_params(&pbkdf2); + der_free_octet_string(&iv_param); + if (key.data) + der_free_octet_string(&key); + if (iv.data) + der_free_octet_string(&iv); + return ret; +} + /* * */ @@ -2453,12 +2696,18 @@ _hx509_pbe_decrypt(hx509_context context, int ret = 0; size_t i; + /* First try PBES2 (modern PKCS#12) */ + ret = try_pbes2_decrypt(context, lock, ai, econtent, content); + if (ret != -1) + return ret; /* PBES2, either error or success */ + + /* Fall back to legacy PKCS#12 PBE */ memset(&key, 0, sizeof(key)); memset(&iv, 0, sizeof(iv)); memset(content, 0, sizeof(*content)); - enc_oid = find_string2key(&ai->algorithm, &c, &md, &s2k); + enc_oid = find_string2key(context, &ai->algorithm, &c, &md, &s2k); if (enc_oid == NULL) { hx509_set_error_string(context, 0, HX509_ALG_NOT_SUPP, "String to key algorithm not supported"); @@ -2523,81 +2772,26 @@ out: * */ - -static int -match_keys_rsa(hx509_cert c, hx509_private_key private_key) -{ - const Certificate *cert; - const SubjectPublicKeyInfo *spi; - RSAPublicKey pk; - RSA *rsa; - size_t size; - int ret; - - if (private_key->private_key.rsa == NULL) - return 0; - - rsa = private_key->private_key.rsa; - if (rsa->d == NULL || rsa->p == NULL || rsa->q == NULL) - return 0; - - cert = _hx509_get_cert(c); - spi = &cert->tbsCertificate.subjectPublicKeyInfo; - - rsa = RSA_new(); - if (rsa == NULL) - return 0; - - ret = decode_RSAPublicKey(spi->subjectPublicKey.data, - spi->subjectPublicKey.length / 8, - &pk, &size); - if (ret) { - RSA_free(rsa); - return 0; - } - rsa->n = heim_int2BN(&pk.modulus); - rsa->e = heim_int2BN(&pk.publicExponent); - - free_RSAPublicKey(&pk); - - rsa->d = BN_dup(private_key->private_key.rsa->d); - rsa->p = BN_dup(private_key->private_key.rsa->p); - rsa->q = BN_dup(private_key->private_key.rsa->q); - rsa->dmp1 = BN_dup(private_key->private_key.rsa->dmp1); - rsa->dmq1 = BN_dup(private_key->private_key.rsa->dmq1); - rsa->iqmp = BN_dup(private_key->private_key.rsa->iqmp); - - if (rsa->n == NULL || rsa->e == NULL || - rsa->d == NULL || rsa->p == NULL|| rsa->q == NULL || - rsa->dmp1 == NULL || rsa->dmq1 == NULL) { - RSA_free(rsa); - return 0; - } - - ret = RSA_check_key(rsa); - RSA_free(rsa); - - return ret == 1; -} - -static int -match_keys_ec(hx509_cert c, hx509_private_key private_key) -{ - return 1; /* XXX use EC_KEY_check_key */ -} - - HX509_LIB_FUNCTION int HX509_LIB_CALL _hx509_match_keys(hx509_cert c, hx509_private_key key) { - if (!key->ops) - return 0; - if (der_heim_oid_cmp(key->ops->key_oid, ASN1_OID_ID_PKCS1_RSAENCRYPTION) == 0) - return match_keys_rsa(c, key); - if (der_heim_oid_cmp(key->ops->key_oid, ASN1_OID_ID_ECPUBLICKEY) == 0) - return match_keys_ec(c, key); - return 0; + const SubjectPublicKeyInfo *spi; + const Certificate *cert; + const unsigned char *p; + EVP_PKEY *pkey; + size_t size; + int ret = 0; + cert = _hx509_get_cert(c); + spi = &cert->tbsCertificate.subjectPublicKeyInfo; + p = spi->_save.data; + size = spi->_save.length; + + if ((pkey = d2i_PUBKEY(NULL, &p, size))) + ret = EVP_PKEY_eq(key->private_key.pkey, pkey); + + EVP_PKEY_free(pkey); + return ret; } diff --git a/lib/hx509/data/secp256r1TestCA.cert.der b/lib/hx509/data/secp256r1TestCA.cert.der new file mode 100644 index 0000000000000000000000000000000000000000..c6b8d46736ae5b5ea82e1c34126539cdf2dfdad9 GIT binary patch literal 445 zcmXqLV%%xa#F(&vnTe5!iILHOi;Y98&EuRc3p0~}nIX3UCmVAp3!5-gu&bef0UwCN z#l!BAnwguDm}4kvAPf>==HYR6R47hOE-*4RD>5`t5a%_tG%z*-0aGK>C<%Te17iyV zLy(}MiGf)Z*(OIC2(z(+-N(cTbtp3A|pQSmjpvrnzMs$8Y#Nn1$7VnUV3o z0XK-p&%(mY#K?vmuFUQX1};nr@h5#Z>UTYp*(u0+Hbe3chrI6FHSUZG-g;9CSo@M9 qQerror = msg; } +/** + * Internal function to get OpenSSL errors as one string, and reset them. + * + * @return a string that must be freed. + * + * @ingroup hx509_error + */ + +struct ossl_err_buf { + size_t len; + char *s; + int ret; +}; + +static int err_append_cb(const char *s, size_t len, void *u) +{ + struct ossl_err_buf *b = u; + char *tmp; + + if ((tmp = realloc(b->s, b->len + len + 1)) == NULL) { + b->ret = ENOMEM; + return 0; + } + + memcpy(tmp + b->len, s, len); + tmp[b->len + len] = '\0'; + b->s = tmp; + b->len += len; + b->ret = 0; + return 1; +} + +int +_hx509_openssl_errors(char **out) +{ + struct ossl_err_buf b; + + *out = NULL; + + if (ERR_peek_last_error() == 0) + return 0; + + /* NOTE: Dequeues the errors */ + b.s = NULL; + b.len = 0; + b.ret = 0; + ERR_print_errors_cb(err_append_cb, &b); + *out = b.s; + return b.ret; +} + +/** + * Internal function. Add an error message to the hx509 context. + * + * @param context A hx509 context. + * @param flags + * - HX509_ERROR_APPEND appends the error string to the old messages + (code is updated). + * @param code error code related to error message + * @param fmt error message format + * @param ap arguments to error message format + * + * @ingroup hx509_error + */ + +HX509_LIB_FUNCTION void HX509_LIB_CALL +_hx509_set_error_stringv_openssl(hx509_context context, int flags, int code, + const char *fmt, va_list ap) +{ + heim_error_t msg, msg2; + char *s = NULL; + int e; + + if (context == NULL) + return; + + e = _hx509_openssl_errors(&s); + + if (e) { + msg2 = heim_error_create(e, "(Could not display OpenSSL error)"); + } else if (s) { + msg2 = heim_error_create(e, "OpenSSL error: \n%s", s); + } else { + msg2 = heim_error_create(e, "(OpenSSL error: )"); + } + free(s); + + msg = heim_error_createv(code, fmt, ap); + + if (msg2 == NULL) { + if (msg) { + if (flags & HX509_ERROR_APPEND) + heim_error_append(msg, context->error); + heim_release(context->error); + context->error = msg; + } + return; + } else if (msg == NULL) { + heim_release(msg2); + return; + } else { + heim_error_append(msg, msg2); + heim_release(msg2); + } + + if (flags & HX509_ERROR_APPEND) { + heim_error_append(msg, context->error); + heim_release(context->error); + } + context->error = msg; +} + /** * See hx509_set_error_stringv(). * @@ -119,6 +231,31 @@ hx509_set_error_string(hx509_context context, int flags, int code, va_end(ap); } +/** + * Internal function; see hx509_set_error_stringv(). + * + * @param context A hx509 context. + * @param flags + * - HX509_ERROR_APPEND appends the error string to the old messages + (code is updated). + * @param code error code related to error message + * @param fmt error message format + * @param ... arguments to error message format + * + * @ingroup hx509_error + */ + +HX509_LIB_FUNCTION void HX509_LIB_CALL +_hx509_set_error_string_openssl(hx509_context context, int flags, int code, + const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + _hx509_set_error_stringv_openssl(context, flags, code, fmt, ap); + va_end(ap); +} + /** * Sets ENOMEM as the error on a hx509 context. * diff --git a/lib/hx509/hx_locl.h b/lib/hx509/hx_locl.h index d461f6469..6b1e75c88 100644 --- a/lib/hx509/hx_locl.h +++ b/lib/hx509/hx_locl.h @@ -96,6 +96,7 @@ struct hx509_generate_private_context; typedef struct hx509_path hx509_path; #include +#include "heimbase-atomics.h" #include @@ -154,7 +155,8 @@ struct hx509_query_data { #define HX509_QUERY_MATCH_TIME 0x200000 #define HX509_QUERY_MATCH_EKU 0x400000 #define HX509_QUERY_MATCH_EXPR 0x800000 -#define HX509_QUERY_MASK 0xffffff +#define HX509_QUERY_MATCH_KEY_ALG 0x1000000 +#define HX509_QUERY_MASK 0x1ffffff Certificate *subject; Certificate *certificate; heim_integer *serial; @@ -170,6 +172,7 @@ struct hx509_query_data { time_t timenow; heim_oid *eku; struct hx_expr *expr; + heim_oid *key_alg; }; struct hx509_keyset_ops { @@ -199,6 +202,46 @@ struct _hx509_password { extern hx509_lock _hx509_empty_lock; +/* + * OpenSSL provider context for hx509. + * This is used to cache providers and fetched algorithms: + * - default: for standard crypto (RSA, EC, AES, SHA, etc.) + * - legacy: for weak crypto used in PKCS#12 (RC2, 3DES-CBC, etc.) + * - Fetched message digests (EVP_MD) for SHA-512, SHA-384, SHA-256, SHA-1, MD5 + * - Fetched ciphers (EVP_CIPHER) for RC2, RC4, 3DES-CBC, AES + * + * Contexts are cached globally in a singly-linked list keyed by (cnf, propq). + * This allows sharing across multiple hx509_context instances and avoids + * repeated algorithm fetching when propq is set to the same value. + */ +typedef struct hx509_context_ossl_data *hx509_context_ossl; +struct hx509_context_ossl_data { + struct hx509_context_ossl_data *next; /* Next in global cache list */ + heim_base_atomic(uint32_t) refs; /* Reference count */ + char *cnf; /* OpenSSL config file path */ + OSSL_LIB_CTX *libctx; /* OpenSSL library context */ + char *propq; /* OpenSSL property query string */ + OSSL_PROVIDER *openssl_def; /* Default provider for standard crypto */ + OSSL_PROVIDER *openssl_leg; /* Legacy provider for weak crypto */ + /* Message digests */ + EVP_MD *md5; + EVP_MD *sha1; + EVP_MD *sha256; + EVP_MD *sha384; + EVP_MD *sha512; + /* Ciphers - legacy/weak (PKCS#12) */ + EVP_CIPHER *rc2_40_cbc; + EVP_CIPHER *rc2_64_cbc; + EVP_CIPHER *rc2_cbc; + EVP_CIPHER *rc4_40; + EVP_CIPHER *rc4; + EVP_CIPHER *des_ede3_cbc; + /* Ciphers - standard */ + EVP_CIPHER *aes_128_cbc; + EVP_CIPHER *aes_192_cbc; + EVP_CIPHER *aes_256_cbc; +}; + struct hx509_context_data { struct hx509_keyset_ops **ks_ops; int ks_num_ops; @@ -212,6 +255,7 @@ struct hx509_context_data { hx509_certs default_trust_anchors; heim_context hcontext; heim_config_section *cf; + hx509_context_ossl ossl; /* OpenSSL provider context */ }; /* _hx509_calculate_path flag field */ @@ -271,15 +315,13 @@ struct hx509_private_key_ops { }; struct hx509_private_key { - unsigned int ref; const struct signature_alg *md; const heim_oid *signature_alg; union { - RSA *rsa; - void *keydata; - void *ecdsa; /* EC_KEY */ - } private_key; + EVP_PKEY *pkey; + } private_key; // XXX Remove the union wrapper hx509_private_key_ops *ops; + uint32_t ref; }; /* @@ -310,12 +352,14 @@ struct signature_alg { const struct signature_alg *, const Certificate *, const AlgorithmIdentifier *, + const EVP_MD *, const heim_octet_string *, const heim_octet_string *); int (*create_signature)(hx509_context, const struct signature_alg *, const hx509_private_key, const AlgorithmIdentifier *, + const EVP_MD *, const heim_octet_string *, AlgorithmIdentifier *, heim_octet_string *); diff --git a/lib/hx509/hxtool.1 b/lib/hx509/hxtool.1 index 040573f4c..dbc2a345a 100644 --- a/lib/hx509/hxtool.1 +++ b/lib/hx509/hxtool.1 @@ -31,7 +31,7 @@ .\" .\" $Id$ .\" -.Dd February 22, 2022 +.Dd December 23, 2025 .Dt HXTOOL 1 .Os HEIMDAL .Sh NAME @@ -39,91 +39,1151 @@ .Nd PKIX command-line utility .Sh SYNOPSIS .Nm -.Bk -words .Oo Fl Fl version Oc .Oo Fl Fl help Oc +.Oo Fl Fl openssl-cnf=file Oc +.Oo Fl Fl openssl-propq=propq Oc .Op Ar sub-command -.Ek +.Nm +.Ic list-oids +.Nm +.Ic cms-create-sd +.Op Fl c Ar certificate-store | Fl Fl certificate Ns = Ns Ar certificate-store +.Op Fl s Ar signer-friendly-name | Fl Fl signer Ns = Ns Ar signer-friendly-name +.Op Fl Fl anchors Ns = Ns Ar certificate-store +.Op Fl Fl pool Ns = Ns Ar certificate-pool +.Op Fl Fl pass Ns = Ns Ar PASS:password +.Op Fl Fl pass Ns = Ns Ar FILE:path +.Op Fl Fl pass Ns = Ns Ar PROMPT +.Op Fl Fl peer-alg Ns = Ns Ar oid +.Op Fl Fl content-type Ns = Ns Ar oid +.Op Fl Fl content-info +.Op Fl Fl pem +.Op Fl Fl detached-signature +.Op Fl Fl signer +.Op Fl Fl id-by-name +.Op Fl Fl embedded-certs +.Op Fl Fl embed-leaf-only +.Ar in-file out-file +.Nm +.Ic cms-verify-sd +.Op Fl D Ar certificate-store | Fl Fl anchors Ns = Ns Ar certificate-store +.Op Fl c Ar certificate-store | Fl Fl certificate Ns = Ns Ar certificate-store +.Op Fl Fl pass Ns = Ns Ar PASS:password +.Op Fl Fl pass Ns = Ns Ar FILE:path +.Op Fl Fl pass Ns = Ns Ar PROMPT +.Op Fl Fl missing-revoke +.Op Fl Fl content-info +.Op Fl Fl pem +.Op Fl Fl signer-allowed +.Op Fl Fl allow-wrong-oid +.Op Fl Fl signed-content Ns = Ns Ar value +.Op Fl Fl oid-sym +.Ar in-file Op Ar out-file +.Nm +.Ic cms-unenvelope +.Op Fl c Ar certificate-store | Fl Fl certificate Ns = Ns Ar certificate-store +.Op Fl Fl pass Ns = Ns Ar PASS:password +.Op Fl Fl pass Ns = Ns Ar FILE:path +.Op Fl Fl pass Ns = Ns Ar PROMPT +.Op Fl Fl content-info +.Op Fl Fl allow-weak-crypto +.Ar in-file out-file +.Nm +.Ic cms-envelope +.Op Fl c Ar certificate-store | Fl Fl certificate Ns = Ns Ar certificate-store +.Op Fl Fl pass Ns = Ns Ar PASS:password +.Op Fl Fl pass Ns = Ns Ar FILE:path +.Op Fl Fl pass Ns = Ns Ar PROMPT +.Op Fl Fl encryption-type Ns = Ns Ar enctype +.Op Fl Fl content-type Ns = Ns Ar oid +.Op Fl Fl content-info +.Op Fl Fl allow-weak-crypto +.Ar in-file out-file +.Nm +.Ic verify +.Op Fl Fl pass Ns = Ns Ar PASS:password +.Op Fl Fl pass Ns = Ns Ar FILE:path +.Op Fl Fl pass Ns = Ns Ar PROMPT +.Op Fl Fl allow-proxy-certificate +.Op Fl Fl missing-revoke +.Op Fl Fl time Ns = Ns Ar value +.Op Fl v | Fl Fl verbose +.Op Fl Fl max-depth Ns = Ns Ar value +.Op Fl Fl hostname Ns = Ns Ar value +.Ar cert:foo chain:cert1 chain:cert2 anchor:anchor1 anchor:anchor2 +.Nm +.Ic print +.Op Fl Fl pass Ns = Ns Ar PASS:password +.Op Fl Fl pass Ns = Ns Ar FILE:path +.Op Fl Fl pass Ns = Ns Ar PROMPT +.Op Fl Fl content +.Op Fl Fl raw-json +.Op Fl Fl never-fail +.Op Fl Fl info +.Ar certificate ... +.Nm +.Ic validate +.Op Fl Fl pass Ns = Ns Ar PASS:password +.Op Fl Fl pass Ns = Ns Ar FILE:path +.Op Fl Fl pass Ns = Ns Ar PROMPT +.Ar certificate ... +.Nm +.Ic certificate-copy +.Op Fl Fl in-pass Ns = Ns Ar PASS:password +.Op Fl Fl in-pass Ns = Ns Ar FILE:path +.Op Fl Fl in-pass Ns = Ns Ar PROMPT +.Op Fl Fl out-pass Ns = Ns Ar PASS:password +.Op Fl Fl out-pass Ns = Ns Ar FILE:path +.Op Fl Fl out-pass Ns = Ns Ar PROMPT +.Op Fl Fl append +.Op Fl Fl root-certs +.Op Fl Fl private-keys +.Ar in-certificates-1 ... out-certificate +.Nm +.Ic ocsp-fetch +.Op Fl Fl pass Ns = Ns Ar PASS:password +.Op Fl Fl pass Ns = Ns Ar FILE:path +.Op Fl Fl pass Ns = Ns Ar PROMPT +.Op Fl Fl sign Ns = Ns Ar certificate +.Op Fl Fl url-path Ns = Ns Ar url +.Op Fl Fl nonce +.Op Fl Fl pool Ns = Ns Ar certificate-store +.Ar outfile certs ... +.Nm +.Ic ocsp-verify +.Op Fl Fl ocsp-file Ns = Ns Ar value +.Ar certificates ... +.Nm +.Ic ocsp-print +.Op Fl Fl verbose +.Ar ocsp-response-file ... +.Nm +.Ic revoke-print +.Op Fl Fl verbose +.Ar ocsp/crl files +.Nm +.Ic generate-key +.Op Fl Fl type Ns = Ns Ar value +.Op Fl Fl key-bits Ns = Ns Ar value +.Op Fl Fl verbose +.Ar output-file +.Nm +.Ic request-create +.Op Fl Fl ca +.Op Fl Fl ca-path-length Ns = Ns Ar value +.Op Fl Fl ee +.Op Fl Fl subject Ns = Ns Ar value +.Op Fl Fl eku Ns = Ns Ar oid-string +.Op Fl Fl email Ns = Ns Ar value +.Op Fl Fl jid Ns = Ns Ar value +.Op Fl Fl dnsname Ns = Ns Ar value +.Op Fl Fl kerberos Ns = Ns Ar value +.Op Fl Fl ms-kerberos Ns = Ns Ar value +.Op Fl Fl registered Ns = Ns Ar value +.Op Fl Fl dn Ns = Ns Ar value +.Op Fl Fl type Ns = Ns Ar value +.Op Fl Fl key Ns = Ns Ar value +.Op Fl Fl generate-key Ns = Ns Ar value +.Op Fl Fl key-bits Ns = Ns Ar value +.Op Fl Fl verbose +.Ar output-file +.Nm +.Ic request-print +.Op Fl Fl verbose +.Ar requests ... +.Nm +.Ic query +.Op Fl Fl exact +.Op Fl Fl private-key +.Op Fl Fl friendlyname Ns = Ns Ar name +.Op Fl Fl eku Ns = Ns Ar oid-string +.Op Fl Fl expr Ns = Ns Ar expression +.Op Fl Fl keyEncipherment +.Op Fl Fl digitalSignature +.Op Fl Fl print +.Op Fl Fl pass Ns = Ns Ar PASS:password +.Op Fl Fl pass Ns = Ns Ar FILE:path +.Op Fl Fl pass Ns = Ns Ar PROMPT +.Ar certificates ... +.Nm +.Ic info +.Nm +.Ic random-data +.Ar bytes +.Nm +.Ic crypto-available +.Op Fl Fl type Ns = Ns Ar value +.Op Fl Fl oid-syms +.Nm +.Ic crypto-select +.Op Fl Fl type Ns = Ns Ar value +.Op Fl Fl certificate Ns = Ns Ar value +.Op Fl Fl peer-cmstype Ns = Ns Ar value +.Op Fl Fl oid-sym +.Nm +.Ic hex +.Op Fl d | Fl Fl decode +.Nm +.Ic certificate-sign +.Op Fl Fl issue-ca +.Op Fl Fl issue-proxy +.Op Fl Fl domain-controller +.Op Fl Fl subject Ns = Ns Ar value +.Op Fl Fl ca-certificate Ns = Ns Ar value +.Op Fl Fl self-signed +.Op Fl Fl ca-private-key Ns = Ns Ar value +.Op Fl Fl certificate Ns = Ns Ar value +.Op Fl Fl type Ns = Ns Ar value +.Op Fl Fl lifetime Ns = Ns Ar value +.Op Fl Fl signature-algorithm Ns = Ns Ar value +.Op Fl Fl serial-number Ns = Ns Ar value +.Op Fl Fl path-length Ns = Ns Ar value +.Op Fl Fl eku Ns = Ns Ar oid-string +.Op Fl Fl ku Ns = Ns Ar value +.Op Fl Fl hostname Ns = Ns Ar value +.Op Fl Fl dnssrv Ns = Ns Ar value +.Op Fl Fl email Ns = Ns Ar value +.Op Fl Fl pk-init-principal Ns = Ns Ar value +.Op Fl Fl ms-upn Ns = Ns Ar value +.Op Fl Fl jid Ns = Ns Ar value +.Op Fl Fl permanent-id Ns = Ns Ar value +.Op Fl Fl hardware-module-name Ns = Ns Ar value +.Op Fl Fl policy Ns = Ns Ar value +.Op Fl Fl policy-mapping Ns = Ns Ar value +.Op Fl Fl pkinit-max-life Ns = Ns Ar value +.Op Fl Fl req Ns = Ns Ar value +.Op Fl Fl certificate-private-key Ns = Ns Ar value +.Op Fl Fl generate-key Ns = Ns Ar value +.Op Fl Fl key-bits Ns = Ns Ar value +.Op Fl Fl crl-uri Ns = Ns Ar value +.Op Fl Fl template-certificate Ns = Ns Ar value +.Op Fl Fl template-fields Ns = Ns Ar value +.Nm +.Ic test-crypto +.Op Fl Fl pass Ns = Ns Ar PASS:password +.Op Fl Fl pass Ns = Ns Ar FILE:path +.Op Fl Fl pass Ns = Ns Ar PROMPT +.Op Fl Fl verbose +.Ar certificates... +.Nm +.Ic statistic-print +.Op Fl Fl type Ns = Ns Ar value +.Nm +.Ic crl-sign +.Op Fl Fl signer Ns = Ns Ar value +.Op Fl Fl pass Ns = Ns Ar PASS:password +.Op Fl Fl pass Ns = Ns Ar FILE:path +.Op Fl Fl pass Ns = Ns Ar PROMPT +.Op Fl Fl crl-file Ns = Ns Ar value +.Op Fl Fl lifetime Ns = Ns Ar value +.Ar certificates... +.Nm +.Ic acert +.Op Fl v | Fl Fl verbose +.Op Fl Fl end-entity +.Op Fl Fl ca +.Op Fl Fl cert-num Ns = Ns Ar value +.Op Fl Fl expr Ns = Ns Ar expression +.Op Fl M Ar EMAIL | Fl Fl has-email-san Ns = Ns Ar EMAIL +.Op Fl X Ar jabber-address | Fl Fl has-xmpp-san Ns = Ns Ar jabber-address +-Op Fl U Ar UPN | Fl Fl has-ms-upn-san Ns = Ns Ar UPN +.Op Fl D Ar FQDN | Fl Fl has-dnsname-san Ns = Ns Ar FQDN +.Op Fl P Ar PRINCIPAL | Fl Fl has-pkinit-san Ns = Ns Ar PRINCIPAL +.Op Fl R Ar OID | Fl Fl has-registeredID-san Ns = Ns Ar OID +.Op Fl E Ar OID | Fl Fl has-eku Ns = Ns Ar OID +.Op Fl K Ar key usage element | Fl Fl has-ku Ns = Ns Ar key usage element +.Op Fl Fl exact +.Op Fl n | Fl Fl valid-now +.Op Fl Fl valid-at Ns = Ns Ar datetime +.Op Fl Fl not-after-eq Ns = Ns Ar datetime +.Op Fl Fl not-after-lt Ns = Ns Ar datetime +.Op Fl Fl not-after-gt Ns = Ns Ar datetime +.Op Fl Fl not-before-eq Ns = Ns Ar datetime +.Op Fl Fl not-before-lt Ns = Ns Ar datetime +.Op Fl Fl not-before-gt Ns = Ns Ar datetime +.Op Fl Fl has-private-key +.Op Fl Fl lacks-private-key +.Ar certificate-store +.Nm +.Ic jwt-sign +.Op Fl a Ar algorithm | Fl Fl algorithm Ns = Ns Ar algorithm +.Op Fl k Ar file | Fl Fl private-key Ns = Ns Ar file +.Op Fl i Ar issuer | Fl Fl issuer Ns = Ns Ar issuer +.Op Fl s Ar subject | Fl Fl subject Ns = Ns Ar subject +.Op Fl A Ar audience | Fl Fl audience Ns = Ns Ar audience +.Op Fl l Ar seconds | Fl Fl lifetime Ns = Ns Ar seconds +.Op Fl o Ar file | Fl Fl output Ns = Ns Ar file +.Nm +.Ic jwt-verify +.Op Fl k Ar file | Fl Fl public-key Ns = Ns Ar file +.Op Fl A Ar audience | Fl Fl audience Ns = Ns Ar audience +.Op Fl t Ar token | Fl Fl token Ns = Ns Ar token +.Nm +.Ic pem-to-jwk +.Op Fl i Ar file | Fl Fl input Ns = Ns Ar file +.Op Fl o Ar file | Fl Fl output Ns = Ns Ar file +.Ar Op Ar pem-file +.Nm +.Ic help +.Ar Op Ar command .Sh DESCRIPTION .Nm -is a utility for making certificate sigining requests (CSRs), -displaying CSRs, signing certificates, etc. -are given, then the value will be parsed and displayed using just -the self-describing nature of DER. +is a command-line utility for making certificate signing requests +(CSRs), displaying CSRs, displaying certificates, signing +certificates, validating certificates, managing certificate +revocation lists (CRLs), etc. .Pp -All sub-commands have their own help message, shown when invoked +Every sub-command has its own help message, shown when invoked with the .Fl Fl help or .Fl h option. .Pp -Supported commands: +Many sub-commands' command-line options refer to certificate and +private key stores, supporting DER, PEM, and PKCS#12 files, as +well as PKCS#11 hard and soft tokens, and others certificate +stores. +See +.Sx CERTIFICATE STORES +below for how to refer to certificates and private keys. +.Pp +The +.Fl Fl pass Ns = Ns Ar PASS:password , +.Fl Fl pass Ns = Ns Ar FILE:path , +and +.Fl Fl pass Ns = Ns Ar PROMPT +options are for specifying passwords for PKCS#8 (PEM) and PKCS#12 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. +For PKCS#11 stores the details of how a PIN is provided varies by +OpenSSL provider. +See +.Sx CERTIFICATE STORES +for details of how to specify PINs for PKCS#11 tokens. +.Pp +The +.Fl Fl openssl-cnf=file +option is for specifying an alternative OpenSSL configuration +file, which can be useful for enabling FIPS or PKCS#11 providers +for this program but not by default for all programs. +The +.Fl Fl openssl-propq=propq +option is for specifying OpenSSL property queries. +See +.Xr property 7 . +.Pp +.Sh SUPPORTED COMMANDS .Bl -tag -width Ds -offset indent -.It help -.It list-oids -.It verify +.It Ic list-oids +List known OIDs. +.It Ic cms-create-sd , Ic cms-sign +Wrap a file within a SignedData object. +.It Ic cms-verify-sd +Verify a file within a SignedData object. +.It Ic cms-unenvelope +Unenvelope a file containing an EnvelopedData object. +.It Ic cms-envelope +Envelope a file containing an EnvelopedData object. +.It Ic 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. +.It Ic print +Print 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 +.Sx CERTIFICATE STORES . +.It Ic validate +Validate content of a certificate (but not a full chain). +.It Ic certificate-copy , Ic cc +Copy certificates 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. +.Sx CERTIFICATE STORES . +.It Ic ocsp-fetch +Fetch OCSP responses for the given certificates. +.It Ic ocsp-verify +Verify that certificates are in OCSP file and valid. +.It Ic ocsp-print +Print a human-readable rendering of OCSP responses. +.It Ic revoke-print +Print a human-readable rendering of a CRL or OCSP response chain. +.It Ic generate-key +Generate a private key. +.It Ic request-create +Create a CRMF or PKCS#10 request (CSR). +.It Ic request-print +Print a human-readable rendering of a CSR. +.It Ic query +Query a certificate store for matching certificates. +.It Ic info +Print information about supported algorithms. +.It Ic random-data +Generate random bytes and print them to standard output. +.It Ic crypto-available +Print available CMS crypto types. +.It Ic crypto-select +Print selected CMS type based on peer capabilities. +.It Ic hex +Hex-encode or decode input. +.It Ic certificate-sign , Ic cert-sign , Ic issue-certificate , Ic ca +Issue a certificate, signing it with a Certification Authority +(CA) certificate, or self-signing it. +This can issue End Entity (EE), intermediate Certification +Authority (CA), and root (self-signed) CA certificates. +.It Ic test-crypto +Test crypto system related to the certificates. +.It Ic statistic-print +Print statistics. +.It Ic crl-sign +Create or update a CRL. +.It Ic acert +Assert certificate content (for testing). +.It Ic jwt-sign +Create a signed JWT. +This is used mainly for testing \(em this is not intended for +implementing a security token service (STS). +Users who wish to implement an STS should use +.Xr hx509_jws_sign 3 . +.It Ic jwt-verify +Verify a JWT and print claims. +This is used mainly for testing \(em this is not intended for +implementing Bearer token acceptors. +Users who wish to implement Bearer token acceptors should use +.Xr hx509_jws_verify 3 . +.It Ic pem-to-jwk +Convert PEM key to JWK format. +.It Ic help , Ic \&? +Show help. .El +.Pp Other sub-commands reported by the -.Nm help +.Ic help sub-command are not stable or fully supported at this time. +.Sh COMMAND OPTIONS +.Ss list-oids +List known OIDs. +.\" +.\" TODO: Add description +.\" +.Ss cms-create-sd +Wrap a file within a CMS SignedData object. +.Bl -tag -width Ds -compact +.It Fl c Ar certificate-store , Fl Fl certificate Ns = Ns Ar certificate-store +Certificate stores to pull certificates from. +.It Fl s Ar signer-friendly-name , Fl Fl signer Ns = Ns Ar signer-friendly-name +Certificate to sign with. +.It Fl Fl anchors Ns = Ns Ar certificate-store +Trust anchors. +.It Fl Fl pool Ns = Ns Ar certificate-pool +Certificate store to pull certificates from. +.It Fl Fl pass Ns = Ns Ar PASS:password +.It Fl Fl pass Ns = Ns Ar FILE:path +.It Fl Fl pass Ns = Ns Ar PROMPT +.It Fl Fl peer-alg Ns = Ns Ar oid +OID that the peer supports. +.It Fl Fl content-type Ns = Ns Ar oid +Content type OID. +.It Fl Fl content-info +Wrap output data in a ContentInfo. +.It Fl Fl pem +Wrap output data in PEM armor. +.It Fl Fl detached-signature +Create a detached signature. +.It Fl Fl signer +Do not sign. +.It Fl Fl id-by-name +Use subject name for CMS Identifier. +.It Fl Fl embedded-certs +Don't embed certificates. +.It Fl Fl embed-leaf-only +Only embed leaf certificate. +.El +.\" +.\" TODO: Add description +.\" +.Ss cms-verify-sd +Verify a file within a CMS SignedData object. +.Bl -tag -width Ds -compact +.It Fl D Ar certificate-store , Fl Fl anchors Ns = Ns Ar certificate-store +Trust anchors. +.It Fl c Ar certificate-store , Fl Fl certificate Ns = Ns Ar certificate-store +Certificate store to pull certificates from. +.Op Fl Fl pass Ns = Ns Ar PASS:password +.Op Fl Fl pass Ns = Ns Ar FILE:path +.Op Fl Fl pass Ns = Ns Ar PROMPT +.It Fl Fl missing-revoke +Missing CRL/OCSP is ok. +.It Fl Fl content-info +Unwrap input data that's in a ContentInfo. +.It Fl Fl pem +Unwrap input data from PEM armor. +.It Fl Fl signer-allowed +Allow no signer. +.It Fl Fl allow-wrong-oid +Allow wrong OID flag. +.It Fl Fl signed-content Ns = Ns Ar value +File containing content. +.It Fl Fl oid-sym +Show symbolic name for OID. +.El +.\" +.\" TODO: Add description +.\" +.Ss cms-unenvelope +Unenvelope a file containing an EnvelopedData object. +.Bl -tag -width Ds -compact +.It Fl c Ar certificate-store , Fl Fl certificate Ns = Ns Ar certificate-store +Certificate used to decrypt the data. +.Op Fl Fl pass Ns = Ns Ar PASS:password +.Op Fl Fl pass Ns = Ns Ar FILE:path +.Op Fl Fl pass Ns = Ns Ar PROMPT +.It Fl Fl content-info +Wrapped output data in a ContentInfo. +.It Fl Fl allow-weak-crypto +Allow weak crypto. +.El +.\" +.\" TODO: Add description +.\" +.Ss cms-envelope +Envelope a file as an EnvelopedData object. +.Bl -tag -width Ds -compact +.It Fl c Ar certificate-store , Fl Fl certificate Ns = Ns Ar certificate-store +Certificates used to receive the data. +.Op Fl Fl pass Ns = Ns Ar PASS:password +.Op Fl Fl pass Ns = Ns Ar FILE:path +.Op Fl Fl pass Ns = Ns Ar PROMPT +.It Fl Fl encryption-type Ns = Ns Ar enctype +Encryption type. +.It Fl Fl content-type Ns = Ns Ar oid +Content type OID. +.It Fl Fl content-info +Wrap output data in a ContentInfo. +.It Fl Fl allow-weak-crypto +Allow weak crypto. +.El +.\" +.\" TODO: Add description +.\" +.Ss verify +Verify certificate chain. +.Bl -tag -width Ds -compact +.Op Fl Fl pass Ns = Ns Ar PASS:password +.Op Fl Fl pass Ns = Ns Ar PROMPT +Password. +.It Fl Fl allow-proxy-certificate +Allow proxy certificates. +.It Fl Fl missing-revoke +Missing CRL/OCSP is ok. +.It Fl Fl time Ns = Ns Ar value +Time when to validate the chain. +.It Fl v , Fl Fl verbose +Verbose logging. +.It Fl Fl max-depth Ns = Ns Ar value +Maximum search length of certificate trust anchor. +.It Fl Fl hostname Ns = Ns Ar value +Match hostname to certificate. +.El +.\" +.\" TODO: Add description +.\" +.Ss print +Print certificates. +.Bl -tag -width Ds -compact +.Op Fl Fl pass Ns = Ns Ar PASS:password +.Op Fl Fl pass Ns = Ns Ar FILE:path +.Op Fl Fl pass Ns = Ns Ar PROMPT +Password. +.It Fl Fl content +Print the content of the certificates. +.It Fl Fl raw-json +Print the DER content of the certificates as JSON. +.It Fl Fl never-fail +Never fail with an error code. +.It Fl Fl info +Print information about the certificate store. +.El +.Pp +The +.Fl Fl raw-json +option prints the certificate(s) in the given store as a JSON dump +of their DER using an experimental (i.e., unstable) schema. +.Ss validate +Validate content of certificates. +.Bl -tag -width Ds -compact +.It Fl Fl pass Ns = Ns Ar password +Password, prompter, or environment. +.El +.\" +.\" TODO: Add description +.\" +.Ss certificate-copy +Copy certificates and keys from one store to another. +.Bl -tag -width Ds -compact +.It Fl Fl in-pass Ns = Ns Ar password +Password, prompter, or environment for input store. +.It Fl Fl out-pass Ns = Ns Ar password +Password, prompter, or environment for output store. +.It Fl Fl append +Append source to destination. +.It Fl Fl root-certs +Do not copy root certificates. +.It Fl Fl private-keys +Do not copy private keys. +.El +.Pp +Use the +.Ic 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. +.Ss ocsp-fetch +Fetch OCSP responses for the given certificates. +.Bl -tag -width Ds -compact +.It Fl Fl pass Ns = Ns Ar password +Password, prompter, or environment. +.It Fl Fl sign Ns = Ns Ar certificate +Certificate used to sign the request. +.It Fl Fl url-path Ns = Ns Ar url +Part after host in URL to put in the request. +.It Fl Fl nonce +Don't include nonce in request. +.It Fl Fl pool Ns = Ns Ar certificate-store +Pool to find parent certificate in. +.El +.\" +.\" TODO: Add description +.\" +.Ss ocsp-verify +Verify OCSP responses. +.Bl -tag -width Ds -compact +.It Fl Fl ocsp-file Ns = Ns Ar value +OCSP file. +.El +.\" +.\" TODO: Add description +.\" +.Ss ocsp-print +Print OCSP responses. +.Bl -tag -width Ds -compact +.It Fl Fl verbose +Verbose output. +.El +.\" +.\" TODO: Add description +.\" +.Ss revoke-print +Print OCSP/CRL files. +.Bl -tag -width Ds -compact +.It Fl Fl verbose +Verbose output. +.El +.\" +.\" TODO: Add description +.\" +.Ss generate-key +Generate a private key. +.Bl -tag -width Ds -compact +.It Fl Fl type Ns = Ns Ar value +Key type. +.It Fl Fl key-bits Ns = Ns Ar value +Number of bits in the generated key. +.It Fl Fl verbose +Verbose status. +.El +.\" +.\" TODO: Add description +.\" +.Ss request-create +Create a CRMF or PKCS#10 request. +.Bl -tag -width Ds -compact +.It Fl Fl ca +Request CA certificate. +.It Fl Fl ca-path-length Ns = Ns Ar value +Path length constraint for CA certificate. +.It Fl Fl ee +Include BasicConstraints with cA set to false. +.It Fl Fl subject Ns = Ns Ar value +Subject DN. +.It Fl Fl eku Ns = Ns Ar oid-string +Add Extended Key Usage OID. +.It Fl Fl email Ns = Ns Ar value +Email address in SubjectAltName. +.It Fl Fl jid Ns = Ns Ar value +XMPP (Jabber) address in SubjectAltName. +.It Fl Fl dnsname Ns = Ns Ar value +Hostname or domainname in SubjectAltName. +.It Fl Fl kerberos Ns = Ns Ar value +Kerberos principal name as SubjectAltName. +.It Fl Fl ms-kerberos Ns = Ns Ar value +Kerberos principal name as SubjectAltName (Microsoft variant). +.It Fl Fl registered Ns = Ns Ar value +Registered object ID as SubjectAltName. +.It Fl Fl dn Ns = Ns Ar value +Directory name as SubjectAltName. +.It Fl Fl type Ns = Ns Ar value +Type of request CRMF or PKCS10, defaults to PKCS10. +.It Fl Fl key Ns = Ns Ar value +Key-pair. +.It Fl Fl generate-key Ns = Ns Ar value +Key type. +.It Fl Fl key-bits Ns = Ns Ar value +Number of bits in the generated key. +.It Fl Fl verbose +Verbose status. +.El +.\" +.\" TODO: Add description +.\" +.Ss request-print +Print requests. +.Bl -tag -width Ds -compact +.It Fl Fl verbose +Verbose printing. +.El +.\" +.\" TODO: Add description +.\" +.Ss query +Query certificates for a match. +.Bl -tag -width Ds -compact +.It Fl Fl exact +Exact match. +.It Fl Fl private-key +Search for private key. +.It Fl Fl friendlyname Ns = Ns Ar name +Match on friendly name. +.It Fl Fl eku Ns = Ns Ar oid-string +Match on EKU. +.It Fl Fl expr Ns = Ns Ar expression +Match on expression. +.It Fl Fl keyEncipherment +Match keyEncipherment certificates. +.It Fl Fl digitalSignature +Match digitalSignature certificates. +.It Fl Fl print +Print matches. +.It Fl Fl pass Ns = Ns Ar password +Password, prompter, or environment. +.El +.\" +.\" TODO: Add description +.\" +.Ss info +Print information about supported algorithms. +.\" +.\" TODO: Add description +.\" +.Ss random-data +Generate random bytes and print them to standard output. +.\" +.\" TODO: Add description +.\" +.Ss crypto-available +Print available CMS crypto types. +.Bl -tag -width Ds -compact +.It Fl Fl type Ns = Ns Ar value +Type of CMS algorithm. +.It Fl Fl oid-syms +Show symbolic names for OIDs. +.El +.\" +.\" TODO: Add description +.\" +.Ss crypto-select +Print selected CMS type. +.Bl -tag -width Ds -compact +.It Fl Fl type Ns = Ns Ar value +Type of CMS algorithm. +.It Fl Fl certificate Ns = Ns Ar value +Source certificate limiting the choices. +.It Fl Fl peer-cmstype Ns = Ns Ar value +Peer limiting CMS types. +.It Fl Fl oid-sym +Show symbolic name for OID. +.El +.\" +.\" TODO: Add description +.\" +.Ss hex +Encode input to hex. +.Bl -tag -width Ds -compact +.It Fl d , Fl Fl decode +Decode instead of encode. +.El +.Ss certificate-sign , Ss cert-sign , Ss issue-certificate , Ss ca +Issue a certificate, signing it with a Certification Authority +(CA) certificate, or self-signing it. +This can issue End Entity (EE), intermediate Certification +Authority (CA), and root (self-signed) CA certificates. +This command is intended to be used to operate a CA. +.Bl -tag -width Ds -compact +.It Fl Fl issue-ca +Issue a CA certificate. +If this option is not used then an EE certificate will be issued. +.It Fl Fl issue-proxy +Issue a proxy certificate. +.It Fl Fl ca-certificate Ns = Ns Ar value +The certificate of the CA that will sign the certificate to be +issued. +For example, +.Fl Fl ca-private-key Ns = Ns Ar PEM-FILE:/path/to/file , +.Fl Fl ca-private-key Ns = Ns Ar DER-FILE:/path/to/file , +.Fl Fl ca-private-key Ns = Ns Ar PKCS12:/path/to/file . +.It Fl Fl self-signed +Issue a self-signed certificate. +.It Fl Fl ca-private-key Ns = Ns Ar value +Private key for the signer of the certificate. +This is a CA's private key when +.Fl Fl self-signed +is not used, or a proxy signer if +.Fl Fl issue-proxy +is used. +For example, +.Fl Fl ca-private-key Ns = Ns Ar PEM-FILE:/path/to/file , +.Fl Fl ca-private-key Ns = Ns Ar DER-FILE:/path/to/file , +.Fl Fl ca-private-key Ns = Ns Ar PKCS12:/path/to/file , +.Fl Fl ca-private-key Ns = Ns Ar PKCS11: . +See +.Sx CERTIFICATE STORES +for more details. +.It Fl Fl req Ns = Ns Ar value +A certificate signing request (CSR). +For example, +.Fl Fl req Ns = Ns Ar PKCS10:/path/to/file +where the file contains a DER-encoded PKCS#10 +.Ar CertificationRequest . +Note that extensions requested by the CSR are ignored, though you +can view the CSR's requested extensions with the +.Nm Nm request-print +command. +.It Fl Fl type Ns = Ns Ar value +Types of certificate to issue (can be used more than once). +Available types: +.Bl -tag -width Ds -offset indent +.It Li https-server +Issue a certificate suitable for an HTTPS server (because it has +the +.Sq id-kp-serverAuth +Extended Key Usage (EKU) object identifier (OID)). +.It Li https-client +Issue a certificate suitable for an HTTPS client (because it has +the +.Sq id-kp-clientAuth +EKU). +.It Li email-client +Issue a certificate suitable for SUBMIT, IMAP, and S/MIME +(because it has the +.Sq id-kp-emailProtection +EKU). +.It Li pkinit-client +Issue a certificate suitable for a PKINIT client user (because it +has the +.Sq id-pkinit-KPClientAuth , +.Sq id-kp-clientAuth , +and +.Sq id-pkinit-ms-eku , +EKUs). +.It Li pkinit-kdc +Issue a certificate suitable for a KDC (for PKINIT) (because it +has the +.Sq id-pkinig-keyPurposeKdc +EKU). +.El +.It Fl Fl certificate Ns = Ns Ar value +Where to write the certificate to be issued. +See +.Fl Fl ca-certificate Ns = Ns Ar value . +.It Fl Fl generate-key Ns = Ns Ar value +Generate a private key of the given type whose public key will be +the subject public key (SPK) of the certificate to be issued. +.It Fl Fl key-bits Ns = Ns Ar value +Number of bits in the generated key. +Use this when using +.Fl Fl generate-key Ns = Ns Ar rsa . +.It Fl Fl certificate-private-key Ns = Ns Ar value +Where to store the private key, if +.Fl Fl generate-key Ns = Ns Ar value +is given, or where to read the private key from. +See +.Fl Fl ca-private-key Ns = Ns Ar value . +.It Fl Fl template-certificate Ns = Ns Ar value +Use the given certificate as a template. +See +.Fl Fl ca-certificate Ns = Ns Ar value . +.It Fl Fl template-fields Ns = Ns Ar value +This option can be given multiple times, each one having one of +the following values indicating that an item from the +.It Fl Fl crl-uri Ns = Ns Ar value +URI to certificate revocation list (CRL). +This will be included in the certificate to be issued, and will +be used by relying parties to check the revocation status of the +issued certificate. +.It Fl Fl policy Ns = Ns Ar value +Certificate Policy OID and optional URI and/or notice +(OID:URInotice_text). +.It Fl Fl policy-mapping Ns = Ns Ar value +Certificate Policy mapping (OID:OID). +.It Fl Fl template-certificate Ns = Ns Ar value +certificate is to be used as part of the template: +.Bl -tag -width Ds -offset indent +.It Li ExtendedKeyUsage +I.e., include the EKU OIDs from the template certificate in the +certificate to be issued. +.It Li KeyUsage +I.e., include the KUs from the template certificate in the +certificate to be issued. +.It Li SPKI +This is useful for issuing additional certificates for the same +subject public key of an existing certificate. +.It Li notBefore +.It Li notAfter +These copy the corresponding certificate constraints from the +template. +(These are not useful. A future version will add a template +field value for certificate lifetime where by the difference +between notAfter and notBefore will be used to set the new +certificate's notAfter.) +.It Li pkinitMaxLife +Take the PKINIT ticket max life extension value from the template +certificate. +.It Li subject +Take the subject name from the template certificate. +.El +.It Fl Fl lifetime Ns = Ns Ar value +Lifetime of to-be-issued certificate. +.It Fl Fl serial-number Ns = Ns Ar value +Serial number of certificate. +(Do not use. +Allow the CA to choose the serial number randomly instead.) +.It Fl Fl subject Ns = Ns Ar value +Subject name of issued certificate. +The subject name can and should be left empty when subject +alternative names are included in the certificate. +.It Fl Fl eku Ns = Ns Ar oid-string +Add a given Extended Key Usage (EKU) OID. +Note that the +.Fl Fl type = Ns Ar TYPE +option allows for certain EKU OIDs to be added without having to +name them. +OIDs can be referenced by name, such as +.Dq id-pkix-kp-serverAuth +or as a sequence of numeric arcs separated by spaces or periods. +E.g., +.Fl Fl eku=id-pkix-kp-serverAuth , +.Fl Fl eku=1.2.3.4.5.6 . +.It Fl Fl ku Ns = Ns Ar value +Key Usage (digitalSignature, keyEncipherment, dataEncipherment, +keyAgreement, keyCertSign, cRLSign, encipherOnly, decipherOnly). +.It Fl Fl signature-algorithm Ns = Ns Ar value +Signature algorithm to use. +.It Fl Fl path-length Ns = Ns Ar value +Maximum path length (CA and proxy certificates); use -1 for no +limit. +.It Fl Fl hostname Ns = Ns Ar value +Adds a +.Va dNSName +subject alternative name (SAN) to the certificate to be issued. +These are the DNS names this certificate is allowed to serve. +.It Fl Fl dnssrv Ns = Ns Ar value +Adds a DNS SRV SAN to the certificate to be issued. +These are the DNS SRV names this certificate is allowed to serve. +.It Fl Fl email Ns = Ns Ar value +Adds an +.Va rfc8222Name +SAN to the certificate to be issued. +These are the email addresses assigned to this certificate, which +can be used for authorization in email-related protocols such as +SUBMIT, IMAP, and S/MIME. +.It Fl Fl pk-init-principal Ns = Ns Ar PRINCIPAL-NAME +Adds a Kerberos principal name SAN to the certificate to be +issued. +For +.Fl Fl type Ns = Ns Ar pkinit-client +certificates these are the client principals the certificate +holder can use to get tickets for using PKINIT. +For +.Fl Fl type Ns = Ns Ar pkinit-kdc +certificates these are the service principals (typically +.Sq krbtgt +principals) the certificate holder can be a Kerberos +Authentication Service (AS) for when using PKINIT. +.It Fl Fl pkinit-max-life Ns = Ns Ar value +Maximum Kerberos ticket lifetime extension for PKINIT. +This is a Heimdal-specific certificate extension with OID +.Ar id-heim-ce-pkinit-princ-max-life +/ +.Ar 1.2.752.43.16.4 +whose value is a DER-encoded INTEGER count of seconds ranging +from 0 to 4294967295. +Kerberos KDCs that support this extension will bound the lifetime +of any tickets issued to the client to be no more than the +lifetime in this extension (note that the KDC may further +restrict the lifetime). +.It Fl Fl ms-upn Ns = Ns Ar UPN +Adds a Microsoft user principal name (UPN) SAN to the certificate +to be issued. +These are UPNs that the certificate holder can use to get tickets +for using PKINIT. +.It Fl Fl jid Ns = Ns Ar value +Adds an XMPP / Jabber ID SAN to the certificate to be issued. +These are the names that the certificate holder can use when +connected to XMPP / Jabber instant messaging. +.It Fl Fl permanent-id Ns = Ns Ar value +PermanentIdentifier ([oid]:[serial]). +.It Fl Fl hardware-module-name Ns = Ns Ar value +HardwareModuleName (oid:serial). +.It Fl Fl domain-controller +Issue a certificate suitable for authenticating an Active +Directory domain controller. +.El +.\" +.\" TODO: Add description +.\" +.Ss test-crypto +Test crypto system related to the certificates. +.Bl -tag -width Ds -compact +.It Fl Fl pass Ns = Ns Ar password +Password, prompter, or environment. +.It Fl Fl verbose +Verbose printing. +.El +.\" +.\" TODO: Add description +.\" +.Ss statistic-print +Print statistics. +.Bl -tag -width Ds -compact +.It Fl Fl type Ns = Ns Ar value +Type of statistics. +.El +.\" +.\" TODO: Add description +.\" +.Ss crl-sign +Create a CRL. +.Bl -tag -width Ds -compact +.It Fl Fl signer Ns = Ns Ar value +Signer certificate. +.It Fl Fl pass Ns = Ns Ar password +Password, prompter, or environment. +.It Fl Fl crl-file Ns = Ns Ar value +CRL output file. +.It Fl Fl lifetime Ns = Ns Ar value +Time the CRL will be valid. +.El +.\" +.\" TODO: Add description +.\" +.Ss acert +Assert certificate content. +.Bl -tag -width Ds -compact +.It Fl v , Fl Fl verbose +Verbose output. +.It Fl Fl end-entity +Check the first EE certificate in the store. +.It Fl Fl ca +Check the first CA certificate in the store. +.It Fl Fl cert-num Ns = Ns Ar value +Check the nth certificate in the store. +.It Fl Fl expr Ns = Ns Ar expression +Test the first certificate matching expression. +.It Fl M Ar email-address , Fl Fl has-email-san Ns = Ns Ar email-address +Check that cert has email SAN. +.It Fl X Ar jabber address , Fl Fl has-xmpp-san Ns = Ns Ar jabber address +Check that cert has XMPP SAN. +.It Fl U Ar UPN , Fl Fl has-ms-upn-san Ns = Ns Ar UPN +Check that cert has UPN SAN. +.It Fl D Ar domainname , Fl Fl has-dnsname-san Ns = Ns Ar domainname +Check that cert has domainname SAN. +.It Fl P Ar Kerberos principal name , Fl Fl has-pkinit-san Ns = Ns Ar Kerberos principal name +Check that cert has PKINIT SAN. +.It Fl R Ar OID , Fl Fl has-registeredID-san Ns = Ns Ar OID +Check that cert has registeredID SAN. +.It Fl E Ar OID , Fl Fl has-eku Ns = Ns Ar OID +Check that cert has EKU. +.It Fl K Ar key usage element , Fl Fl has-ku Ns = Ns Ar key usage element +Check that cert has key usage. +.It Fl Fl exact +Check that cert has only given SANs/EKUs/KUs. +.It Fl n , Fl Fl valid-now +Check that current time is in certificate's validity period. +.It Fl Fl valid-at Ns = Ns Ar datetime +Check that the certificate is valid at given time. +.It Fl Fl not-after-eq Ns = Ns Ar datetime +Check that the certificate's notAfter is as given. +.It Fl Fl not-after-lt Ns = Ns Ar datetime +Check that the certificate's notAfter is before the given time. +.It Fl Fl not-after-gt Ns = Ns Ar datetime +Check that the certificate's notAfter is after the given time. +.It Fl Fl not-before-eq Ns = Ns Ar datetime +Check that the certificate's notBefore is as given. +.It Fl Fl not-before-lt Ns = Ns Ar datetime +Check that the certificate's notBefore is before the given time. +.It Fl Fl not-before-gt Ns = Ns Ar datetime +Check that the certificate's notBefore is after the given time. +.It Fl Fl has-private-key +Check that the certificate has a private key. +.It Fl Fl lacks-private-key +Check that the certificate does not have a private key. +.El +.\" +.\" TODO: Add description +.\" +.Ss jwt-sign +Create a signed JWT. +.Bl -tag -width Ds -compact +.It Fl a Ar algorithm , Fl Fl algorithm Ns = Ns Ar algorithm +Signature algorithm (RS256, ES256, EdDSA, etc.). +.It Fl k Ar file , Fl Fl private-key Ns = Ns Ar file +Private key file (PEM format). +.It Fl i Ar issuer , Fl Fl issuer Ns = Ns Ar issuer +Issuer claim (iss). +.It Fl s Ar subject , Fl Fl subject Ns = Ns Ar subject +Subject claim (sub). +.It Fl A Ar audience , Fl Fl audience Ns = Ns Ar audience +Audience claim (aud). +.It Fl l Ar seconds , Fl Fl lifetime Ns = Ns Ar seconds +Token lifetime in seconds. +.It Fl o Ar file , Fl Fl output Ns = Ns Ar file +Output file (default: stdout). +.El +.\" +.\" TODO: Add description +.\" +.Ss jwt-verify +Verify a JWT and print claims. +.Bl -tag -width Ds -compact +.It Fl k Ar file , Fl Fl public-key Ns = Ns Ar file +Public key file(s) (PEM format). +.It Fl A Ar audience , Fl Fl audience Ns = Ns Ar audience +Required audience. +.It Fl t Ar token , Fl Fl token Ns = Ns Ar token +JWT token (or read from stdin). +.El +.\" +.\" TODO: Add description +.\" +.Ss pem-to-jwk +Convert PEM key to JWK format. +.Bl -tag -width Ds -compact +.It Fl i Ar file , Fl Fl input Ns = Ns Ar file +PEM key file. +.It Fl o Ar file , Fl Fl output Ns = Ns Ar file +Output file (default: stdout). +.El +.\" +.\" TODO: Add description +.\" +.Ss help +Show help. .Sh CERTIFICATE STORES Stores of certificates and/or keys have string names that can be used with -.Nm 's +.Nm Ap s commands as well as in various configuration parameters and command-line arguments of Heimdal's Kerberos implementation (for PKINIT). @@ -178,105 +1238,52 @@ OpenSSL-style hashed directory of trust 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 PKCS11:[,config=/path-to-openssl.cnf] +Loads the given PKCS#11 object using the configured OpenSSL +provider. +When using the Latchset OpenSSL PKCS#11 provider, +.Lk https://github.com/latchset/pkcs11-provider , +for example, +then +.Va +identifier is a PKCS#11 URI (see RFC 7512). +Examples: +.Bl -tag -width Ds -offset indent +.It Va PKCS11:pkcs11:token=MyToken +.It Va PKCS11:pkcs11:slot-id=0;object=MyCert +.It Va PKCS11:pkcs11:token=SmartCard,config=/etc/op11.cnf +.El +The +.Va config=PATH +option is Heimdal-specific and not part of the PKCS#11 URI. +Use the +.Va config=PATH +option to refer to an OpenSSL configuration other than the +default, such as when you want to configure the PKCS#11 provider +but not enable it by default. +The OpenSSL configuration file path must not contain a comma. +.Pp +Note that +.Nm +will not itself prompt for PINs with which to unlock tokens, +however OpenSSL providers that use PKCS#11 URIs can take the PIN +from the +.Dq pin-value +attribute or obtain the PIN from the +.Dq pin-source +attribute (which allows one to specify a file or a program to +execute which might then prompt). +See RFC 7512. .It NULL: An empty store. .It MEMORY:name -An in-memory only, ephemeral store, usually never used in -.NM 's +An in-memory only, ephemeral store, usually not used in +.Nm Ap 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 -sub-command, or verify a certificate and its certification path -with the -.Nm verify -sub-command. -.Pp -You can display a certificate using the -.Nm print -sub-command: -.Pp -.Nm print -.Oo options Oc -.Ar STORE -.Pp -Options: -.Bl -tag -width Ds -offset indent -.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#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 -The -.Fl Fl raw-json -option prints the certificate(s) in the given -.Ar STORE -as a JSON dump of their DER using an experimental (i.e., -unstable) schema. -.Sh KEYS -The -.Nm generate-key -sub-command will generate a key. -.Sh CERTIFICATE SIGNING REQUESTS -The -.Nm request-create -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. -.Sh CERTIFICATE ISSUANCE / CERTIFICATION AUTHORITY -The -.Nm certificate-sign -sub-command will issue a certificate. -See its usage message. -.Sh ONLINE CERTIFICATE STATUS PROTOCOL -The -.Nm ocsp-fetch -sub-command will fetch OCSP Responses for the given -certificates. -.Pp -The -.Nm ocsp-verify -sub-command will verify OCSP Responses. -.Pp -The -.Nm ocsp-print -sub-command will display OCSP Responses. -.Sh CERTIFICATE REVOCATION LIST -The -.Nm crl-sign -sub-command will add certificates to a certificate revocation -list. .Sh EXAMPLES Generate an RSA key: .Bd -literal -offset indent @@ -322,7 +1329,7 @@ PKCS#10 CertificationRequest: san: dNSName: foo.test.h5l.se .Ed .Pp -Issue a end-entity certificate for an HTTPS server given a CSR: +Issue an end-entity certificate for an HTTPS server given a CSR: .Bd -literal -offset indent hxtool issue-certificate \\ --type=https-server \\ @@ -336,7 +1343,7 @@ hxtool issue-certificate \\ .Pp Add a chain to a PEM file: .Bd -literal -offset indent -hxtool copy-certificiate \\ +hxtool certificate-copy \\ --no-private-keys \\ --no-root-certs \\ FILE:ca.pem FILE:ee.pem @@ -375,6 +1382,6 @@ hxtool issue-certificate \\ --req=PKCS10:csr.der \\ --certificate=PEM-FILE:intermediate.pem .Ed -.Pp .Sh SEE ALSO -.Xr openssl 1 +.Xr openssl 1 , +.Xr property 7 diff --git a/lib/hx509/hxtool.c b/lib/hx509/hxtool.c index 14b645d73..0a06cc781 100644 --- a/lib/hx509/hxtool.c +++ b/lib/hx509/hxtool.c @@ -42,11 +42,17 @@ static hx509_context context; static char *stat_file_string; +static char *ossl_cnf_string; +static char *ossl_propq_string; static int version_flag; static int help_flag; struct getargs args[] = { { "statistic-file", 0, arg_string, &stat_file_string, NULL, NULL }, + { "ossl-cnf", 0, arg_string, &ossl_cnf_string, + "OpenSSL configuration file", "FILE" }, + { "ossl-propq", 0, arg_string, &ossl_propq_string, + "OpenSSL property query string", "PROPQ" }, { "version", 0, arg_flag, &version_flag, NULL, NULL }, { "help", 0, arg_flag, &help_flag, NULL, NULL } }; @@ -679,7 +685,7 @@ cms_create_enveloped(struct cms_envelope_options *opt, int argc, char **argv) ret = hx509_cms_envelope_1(context, flags, cert, p, sz, enctype, &contentType, &o); if (ret) - errx(1, "hx509_cms_envelope_1: %d", ret); + hx509_err(context, 1, ret, "hx509_cms_envelope_1: %d", ret); hx509_cert_free(cert); hx509_certs_free(&certs); @@ -1354,7 +1360,7 @@ ocsp_verify(struct ocsp_verify_options *opt, int argc, char **argv) ret = _hx509_map_file_os(opt->ocsp_file_string, &os); if (ret) - err(1, "map_file: %s: %d", argv[0], ret); + hx509_err(context, 1, ret, "map_file: %s: %d", argv[0], ret); ret = hx509_certs_init(context, "MEMORY:test-certs", 0, NULL, &certs); if (ret) hx509_err(context, 1, ret, "hx509_certs_init: MEMORY"); @@ -1413,14 +1419,22 @@ get_key(const char *fn, const char *type, int optbits, if (type) { struct hx509_generate_private_context *gen_ctx = NULL; + const heim_oid *key_oid; - if (strcasecmp(type, "rsa") != 0) - errx(1, "can only handle rsa keys for now"); + if (strcasecmp(type, "rsa") == 0) { + key_oid = ASN1_OID_ID_PKCS1_RSAENCRYPTION; + } else if (strcasecmp(type, "ec") == 0 || strcasecmp(type, "ecdsa") == 0) { + key_oid = ASN1_OID_ID_ECPUBLICKEY; + } else if (strcasecmp(type, "ed25519") == 0) { + key_oid = ASN1_OID_ID_ED25519; + } else if (strcasecmp(type, "ed448") == 0) { + key_oid = ASN1_OID_ID_ED448; + } else { + errx(1, "unsupported key type: %s (supported: rsa, ec, ed25519, ed448)", type); + } - ret = _hx509_generate_private_key_init(context, - ASN1_OID_ID_PKCS1_RSAENCRYPTION, - &gen_ctx); - if (ret == 0) + ret = _hx509_generate_private_key_init(context, key_oid, &gen_ctx); + if (ret == 0 && optbits > 0) ret = _hx509_generate_private_key_bits(context, gen_ctx, optbits); if (ret == 0) ret = _hx509_generate_private_key(context, gen_ctx, signer); @@ -1455,7 +1469,7 @@ get_key(const char *fn, const char *type, int optbits, } } else { if (fn == NULL) - err(1, "no private key"); + errx(1, "no private key"); ret = read_private_key(fn, signer); if (ret) hx509_err(context, 1, ret, "failed to read private key from %s", @@ -1647,24 +1661,73 @@ int info(void *opt, int argc, char **argv) { - ENGINE_add_conf_module(); + OSSL_LIB_CTX *libctx = NULL; /* use the default libctx */ + const char *propq = NULL; /* no property query; change to "fips=yes" if needed */ + /* RSA */ { - const RSA_METHOD *m = RSA_get_default_method(); - if (m != NULL) - printf("rsa: %s\n", m->name); + EVP_KEYMGMT *km = EVP_KEYMGMT_fetch(libctx, "RSA", propq); + if (km) { + const OSSL_PROVIDER *prov = EVP_KEYMGMT_get0_provider(km); + const char *pname = prov ? OSSL_PROVIDER_get0_name(prov) : "unknown"; + printf("rsa: %s\n", pname); + EVP_KEYMGMT_free(km); + } else { + printf("rsa: unavailable\n"); + } } + + /* DH */ { - const DH_METHOD *m = DH_get_default_method(); - if (m != NULL) - printf("dh: %s\n", m->name); + EVP_KEYMGMT *km = EVP_KEYMGMT_fetch(libctx, "DH", propq); + if (km) { + const OSSL_PROVIDER *prov = EVP_KEYMGMT_get0_provider(km); + const char *pname = prov ? OSSL_PROVIDER_get0_name(prov) : "unknown"; + printf("dh: %s\n", pname); + EVP_KEYMGMT_free(km); + } else { + printf("dh: unavailable\n"); + } } + + /* DHX */ { - printf("ecdsa: ECDSA_METHOD\n"); + EVP_KEYMGMT *km = EVP_KEYMGMT_fetch(libctx, "DHX", propq); + if (km) { + const OSSL_PROVIDER *prov = EVP_KEYMGMT_get0_provider(km); + const char *pname = prov ? OSSL_PROVIDER_get0_name(prov) : "unknown"; + printf("dh: %s\n", pname); + EVP_KEYMGMT_free(km); + } else { + printf("dh: unavailable\n"); + } } + + /* ECDSA (signature algorithm). If not available, fall back to EC key management. */ { - int ret = RAND_status(); - printf("rand: %s\n", ret == 1 ? "ok" : "not available"); + EVP_SIGNATURE *sig = EVP_SIGNATURE_fetch(libctx, "ECDSA", propq); + if (sig) { + const OSSL_PROVIDER *prov = EVP_SIGNATURE_get0_provider(sig); + const char *pname = prov ? OSSL_PROVIDER_get0_name(prov) : "unknown"; + printf("ecdsa: %s\n", pname); + EVP_SIGNATURE_free(sig); + } else { + EVP_KEYMGMT *ec = EVP_KEYMGMT_fetch(libctx, "EC", propq); + if (ec) { + const OSSL_PROVIDER *prov = EVP_KEYMGMT_get0_provider(ec); + const char *pname = prov ? OSSL_PROVIDER_get0_name(prov) : "unknown"; + printf("ecdsa: %s\n", pname); + EVP_KEYMGMT_free(ec); + } else { + printf("ecdsa: unavailable\n"); + } + } + } + + /* Random source status (still fine to use in 3.x) */ + { + int ret = RAND_status(); + printf("rand: %s\n", ret == 1 ? "ok" : "not available"); } return 0; @@ -2212,8 +2275,16 @@ hxtool_ca(struct certificate_sign_options *opt, int argc, char **argv) sigalg = hx509_signature_rsa_with_sha1(); else if (strcasecmp(opt->signature_algorithm_string, "rsa-with-sha256") == 0) sigalg = hx509_signature_rsa_with_sha256(); + else if (strcasecmp(opt->signature_algorithm_string, "rsa-with-sha384") == 0) + sigalg = hx509_signature_rsa_with_sha384(); + else if (strcasecmp(opt->signature_algorithm_string, "rsa-with-sha512") == 0) + sigalg = hx509_signature_rsa_with_sha512(); + else if (strcasecmp(opt->signature_algorithm_string, "ed25519") == 0) + sigalg = hx509_signature_ed25519(); + else if (strcasecmp(opt->signature_algorithm_string, "ed448") == 0) + sigalg = hx509_signature_ed448(); else - errx(1, "unsupported sigature algorithm"); + errx(1, "unsupported signature algorithm"); hx509_ca_tbs_set_signature_algorithm(context, tbs, sigalg); } @@ -3232,6 +3303,13 @@ main(int argc, char **argv) if (ret) errx(1, "hx509_context_init failed with %d", ret); + if (ossl_cnf_string || ossl_propq_string) { + ret = hx509_context_set_ossl_cnf_propq(context, ossl_cnf_string, + ossl_propq_string); + if (ret) + errx(1, "hx509_context_set_ossl_cnf_propq failed with %d", ret); + } + if (stat_file_string) hx509_query_statistic_file(context, stat_file_string); diff --git a/lib/hx509/ks_file.c b/lib/hx509/ks_file.c index 2d766dca8..b1fe1f8b7 100644 --- a/lib/hx509/ks_file.c +++ b/lib/hx509/ks_file.c @@ -84,6 +84,7 @@ try_decrypt(hx509_context context, size_t len) { heim_octet_string clear; + EVP_CIPHER_CTX *ctx = NULL; size_t keylen; void *key; int ret; @@ -115,13 +116,17 @@ try_decrypt(hx509_context context, } clear.length = len; - { - EVP_CIPHER_CTX ctx; - EVP_CIPHER_CTX_init(&ctx); - EVP_CipherInit_ex(&ctx, c, NULL, key, ivdata, 0); - EVP_Cipher(&ctx, clear.data, cipher, len); - EVP_CIPHER_CTX_cleanup(&ctx); + if ((ctx = EVP_CIPHER_CTX_new()) == NULL || + EVP_CipherInit_ex(ctx, c, NULL, key, ivdata, 0) <= 0 || + EVP_Cipher(ctx, clear.data, cipher, len) <= 0) { + hx509_set_error_string(context, 0, ENOMEM, + "Out of memory to decrypt for private key"); + ret = ENOMEM; + free(clear.data); + goto out; } + EVP_CIPHER_CTX_free(ctx); + ctx = NULL; if (!(flags & HX509_CERTS_NO_PRIVATE_KEYS)) ret = _hx509_collector_private_key_add(context, collector, alg, NULL, @@ -130,6 +135,7 @@ try_decrypt(hx509_context context, memset_s(clear.data, clear.length, 0, clear.length); free(clear.data); out: + EVP_CIPHER_CTX_free(ctx); memset_s(key, keylen, 0, keylen); free(key); return ret; diff --git a/lib/hx509/ks_keychain.c b/lib/hx509/ks_keychain.c index 3243ee8b2..17223acfd 100644 --- a/lib/hx509/ks_keychain.c +++ b/lib/hx509/ks_keychain.c @@ -35,278 +35,170 @@ #ifdef HAVE_FRAMEWORK_SECURITY +#include + +/* Suppress deprecation warnings for SecKeychain APIs - still needed for file-based keychains */ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" -#include - -/* Missing function decls in pre Leopard */ -#ifdef NEED_SECKEYGETCSPHANDLE_PROTO -OSStatus SecKeyGetCSPHandle(SecKeyRef, CSSM_CSP_HANDLE *); -OSStatus SecKeyGetCredentials(SecKeyRef, CSSM_ACL_AUTHORIZATION_TAG, - int, const CSSM_ACCESS_CREDENTIALS **); -#define kSecCredentialTypeDefault 0 -#define CSSM_SIZE uint32_t -#endif - - -static int -getAttribute(SecKeychainItemRef itemRef, SecItemAttr item, - SecKeychainAttributeList **attrs) -{ - SecKeychainAttributeInfo attrInfo; - UInt32 attrFormat = 0; - OSStatus ret; - - *attrs = NULL; - - attrInfo.count = 1; - attrInfo.tag = &item; - attrInfo.format = &attrFormat; - - ret = SecKeychainItemCopyAttributesAndData(itemRef, &attrInfo, NULL, - attrs, NULL, NULL); - if (ret) - return EINVAL; - return 0; -} - - /* - * + * Convert a SecKeyRef to an EVP_PKEY by exporting and re-importing. + * Returns NULL if the key cannot be exported (e.g., hardware-backed keys). */ - -struct kc_rsa { - SecKeychainItemRef item; - size_t keysize; -}; - - -static int -kc_rsa_public_encrypt(int flen, - const unsigned char *from, - unsigned char *to, - RSA *rsa, - int padding) +static EVP_PKEY * +seckey_to_evp_pkey(hx509_context context, SecKeyRef seckey) { - return -1; + CFDictionaryRef attrs = NULL; + CFDataRef keydata = NULL; + CFErrorRef error = NULL; + EVP_PKEY *pkey = NULL; + CFStringRef keytype; + const unsigned char *p; + + attrs = SecKeyCopyAttributes(seckey); + if (attrs == NULL) + return NULL; + + keytype = CFDictionaryGetValue(attrs, kSecAttrKeyType); + if (keytype == NULL) { + CFRelease(attrs); + return NULL; + } + + /* Try to export the key - this fails for hardware-backed keys */ + keydata = SecKeyCopyExternalRepresentation(seckey, &error); + if (keydata == NULL) { + if (error) + CFRelease(error); + CFRelease(attrs); + return NULL; + } + + p = CFDataGetBytePtr(keydata); + + if (CFEqual(keytype, kSecAttrKeyTypeRSA)) { + /* RSA keys are exported in PKCS#1 format */ + pkey = d2i_PrivateKey(EVP_PKEY_RSA, NULL, &p, CFDataGetLength(keydata)); + } else if (CFEqual(keytype, kSecAttrKeyTypeECSECPrimeRandom)) { + /* EC keys are exported in ANSI X9.63 format, need to convert */ + CFNumberRef keysizeRef; + int keysize = 0; + size_t coord_len = 0; + OSSL_PARAM_BLD *bld = NULL; + OSSL_PARAM *params = NULL; + EVP_PKEY_CTX *pctx = NULL; + BIGNUM *priv = NULL; + const char *group_name = NULL; + + keysizeRef = CFDictionaryGetValue(attrs, kSecAttrKeySizeInBits); + if (keysizeRef) + CFNumberGetValue(keysizeRef, kCFNumberIntType, &keysize); + + switch (keysize) { + case 256: + group_name = "prime256v1"; + coord_len = 32; + break; + case 384: + group_name = "secp384r1"; + coord_len = 48; + break; + case 521: + group_name = "secp521r1"; + coord_len = 66; + break; + default: + goto ec_out; + } + + /* + * X9.63 private key format: 04 || X || Y || D + * where X, Y are public key coordinates and D is private key + */ + if ((size_t)CFDataGetLength(keydata) != 1 + 3 * coord_len) + goto ec_out; + if (p[0] != 0x04) + goto ec_out; + + /* Build EC key using OSSL_PARAM */ + bld = OSSL_PARAM_BLD_new(); + if (bld == NULL) + goto ec_out; + + /* Private key is after the public point (04 || X || Y) */ + priv = BN_bin2bn(p + 1 + 2 * coord_len, coord_len, NULL); + if (priv == NULL) + goto ec_out; + + if (!OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_GROUP_NAME, + group_name, 0) || + !OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_PUB_KEY, + p, 1 + 2 * coord_len) || + !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PRIV_KEY, priv)) + goto ec_out; + + params = OSSL_PARAM_BLD_to_param(bld); + if (params == NULL) + goto ec_out; + + pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL); + if (pctx == NULL) + goto ec_out; + + if (EVP_PKEY_fromdata_init(pctx) <= 0 || + EVP_PKEY_fromdata(pctx, &pkey, EVP_PKEY_KEYPAIR, params) <= 0) + pkey = NULL; + + ec_out: + BN_free(priv); + OSSL_PARAM_free(params); + OSSL_PARAM_BLD_free(bld); + EVP_PKEY_CTX_free(pctx); + } + + CFRelease(keydata); + CFRelease(attrs); + return pkey; } -static int -kc_rsa_public_decrypt(int flen, - const unsigned char *from, - unsigned char *to, - RSA *rsa, - int padding) -{ - return -1; -} - - -static int -kc_rsa_private_encrypt(int flen, - const unsigned char *from, - unsigned char *to, - RSA *rsa, - int padding) -{ - struct kc_rsa *kc = RSA_get_app_data(rsa); - - CSSM_RETURN cret; - OSStatus ret; - const CSSM_ACCESS_CREDENTIALS *creds; - SecKeyRef privKeyRef = (SecKeyRef)kc->item; - CSSM_CSP_HANDLE cspHandle; - const CSSM_KEY *cssmKey; - CSSM_CC_HANDLE sigHandle = 0; - CSSM_DATA sig, in; - int fret = 0; - - if (padding != RSA_PKCS1_PADDING) - return -1; - - cret = SecKeyGetCSSMKey(privKeyRef, &cssmKey); - if(cret) abort(); - - cret = SecKeyGetCSPHandle(privKeyRef, &cspHandle); - if(cret) abort(); - - ret = SecKeyGetCredentials(privKeyRef, CSSM_ACL_AUTHORIZATION_SIGN, - kSecCredentialTypeDefault, &creds); - if(ret) abort(); - - ret = CSSM_CSP_CreateSignatureContext(cspHandle, CSSM_ALGID_RSA, - creds, cssmKey, &sigHandle); - if(ret) abort(); - - in.Data = (uint8 *)from; - in.Length = flen; - - sig.Data = (uint8 *)to; - sig.Length = kc->keysize; - - cret = CSSM_SignData(sigHandle, &in, 1, CSSM_ALGID_NONE, &sig); - if(cret) { - /* cssmErrorString(cret); */ - fret = -1; - } else - fret = sig.Length; - - if(sigHandle) - CSSM_DeleteContext(sigHandle); - - return fret; -} - -static int -kc_rsa_private_decrypt(int flen, const unsigned char *from, unsigned char *to, - RSA * rsa, int padding) -{ - struct kc_rsa *kc = RSA_get_app_data(rsa); - - CSSM_RETURN cret; - OSStatus ret; - const CSSM_ACCESS_CREDENTIALS *creds; - SecKeyRef privKeyRef = (SecKeyRef)kc->item; - CSSM_CSP_HANDLE cspHandle; - const CSSM_KEY *cssmKey; - CSSM_CC_HANDLE handle = 0; - CSSM_DATA out, in, rem; - int fret = 0; - CSSM_SIZE outlen = 0; - char remdata[1024]; - - if (padding != RSA_PKCS1_PADDING) - return -1; - - cret = SecKeyGetCSSMKey(privKeyRef, &cssmKey); - if(cret) abort(); - - cret = SecKeyGetCSPHandle(privKeyRef, &cspHandle); - if(cret) abort(); - - ret = SecKeyGetCredentials(privKeyRef, CSSM_ACL_AUTHORIZATION_DECRYPT, - kSecCredentialTypeDefault, &creds); - if(ret) abort(); - - - ret = CSSM_CSP_CreateAsymmetricContext (cspHandle, - CSSM_ALGID_RSA, - creds, - cssmKey, - CSSM_PADDING_PKCS1, - &handle); - if(ret) abort(); - - in.Data = (uint8 *)from; - in.Length = flen; - - out.Data = (uint8 *)to; - out.Length = kc->keysize; - - rem.Data = (uint8 *)remdata; - rem.Length = sizeof(remdata); - - cret = CSSM_DecryptData(handle, &in, 1, &out, 1, &outlen, &rem); - if(cret) { - /* cssmErrorString(cret); */ - fret = -1; - } else - fret = out.Length; - - if(handle) - CSSM_DeleteContext(handle); - - return fret; -} - -static int -kc_rsa_init(RSA *rsa) -{ - return 1; -} - -static int -kc_rsa_finish(RSA *rsa) -{ - struct kc_rsa *kc_rsa = RSA_get_app_data(rsa); - CFRelease(kc_rsa->item); - memset(kc_rsa, 0, sizeof(*kc_rsa)); - free(kc_rsa); - return 1; -} - -static const RSA_METHOD kc_rsa_pkcs1_method = { - "hx509 Keychain PKCS#1 RSA", - kc_rsa_public_encrypt, - kc_rsa_public_decrypt, - kc_rsa_private_encrypt, - kc_rsa_private_decrypt, - NULL, - NULL, - kc_rsa_init, - kc_rsa_finish, - 0, - NULL, - NULL, - NULL, - NULL -}; - static int set_private_key(hx509_context context, - SecKeychainItemRef itemRef, - hx509_cert cert) + SecKeyRef keyRef, + hx509_cert cert) { - struct kc_rsa *kc; hx509_private_key key; - RSA *rsa; + EVP_PKEY *pkey; + int pkey_type; int ret; - ret = hx509_private_key_init(&key, NULL, NULL); - if (ret) - return ret; - - kc = calloc(1, sizeof(*kc)); - if (kc == NULL) - _hx509_abort("out of memory"); - - kc->item = itemRef; - - rsa = RSA_new(); - if (rsa == NULL) - _hx509_abort("out of memory"); - - /* Argh, fake modulus since OpenSSL API is on crack */ - { - SecKeychainAttributeList *attrs = NULL; - uint32_t size; - void *data; - - rsa->n = BN_new(); - if (rsa->n == NULL) abort(); - - ret = getAttribute(itemRef, kSecKeyKeySizeInBits, &attrs); - if (ret) abort(); - - size = *(uint32_t *)attrs->attr[0].data; - SecKeychainItemFreeAttributesAndData(attrs, NULL); - - kc->keysize = (size + 7) / 8; - - data = malloc(kc->keysize); - memset(data, 0xe0, kc->keysize); - BN_bin2bn(data, kc->keysize, rsa->n); - free(data); + pkey = seckey_to_evp_pkey(context, keyRef); + if (pkey == NULL) { + /* Key couldn't be exported - likely hardware-backed */ + return 0; } - rsa->e = NULL; - RSA_set_method(rsa, &kc_rsa_pkcs1_method); - ret = RSA_set_app_data(rsa, kc); - if (ret != 1) - _hx509_abort("RSA_set_app_data"); + ret = hx509_private_key_init(&key, NULL, NULL); + if (ret) { + EVP_PKEY_free(pkey); + return ret; + } + + /* Assign EVP_PKEY directly */ + key->private_key.pkey = pkey; + + /* Set default signature algorithm based on key type */ + pkey_type = EVP_PKEY_base_id(pkey); + switch (pkey_type) { + case EVP_PKEY_RSA: + key->signature_alg = ASN1_OID_ID_PKCS1_SHA256WITHRSAENCRYPTION; + break; + case EVP_PKEY_EC: + key->signature_alg = ASN1_OID_ID_ECDSA_WITH_SHA256; + break; + default: + break; + } - hx509_private_key_assign_rsa(key, rsa); _hx509_cert_assign_key(cert, key); return 0; @@ -328,13 +220,6 @@ keychain_init(hx509_context context, { struct ks_keychain *ctx; - if (flags & HX509_CERTS_NO_PRIVATE_KEYS) { - hx509_set_error_string(context, 0, ENOTSUP, - "KEYCHAIN store does not support not reading " - "private keys"); - return ENOTSUP; - } - ctx = calloc(1, sizeof(*ctx)); if (ctx == NULL) { hx509_clear_error_string(context); @@ -388,7 +273,8 @@ keychain_free(hx509_certs certs, void *data) struct iter { hx509_certs certs; void *cursor; - SecKeychainSearchRef searchRef; + CFArrayRef search_result; + CFIndex search_index; }; static int @@ -407,7 +293,7 @@ keychain_iter_start(hx509_context context, if (ctx->anchors) { CFArrayRef anchors; int ret; - int i; + CFIndex i; ret = hx509_certs_init(context, "MEMORY:ks-file-create", 0, NULL, &iter->certs); @@ -426,14 +312,19 @@ keychain_iter_start(hx509_context context, } for (i = 0; i < CFArrayGetCount(anchors); i++) { SecCertificateRef cr; + CFDataRef certData; hx509_cert cert; - CSSM_DATA cssm; - cr = (SecCertificateRef)CFArrayGetValueAtIndex(anchors, i); + cr = (SecCertificateRef)(uintptr_t)CFArrayGetValueAtIndex(anchors, i); + certData = SecCertificateCopyData(cr); + if (certData == NULL) + continue; - SecCertificateGetData(cr, &cssm); - - cert = hx509_cert_init_data(context, cssm.Data, cssm.Length, NULL); + cert = hx509_cert_init_data(context, + CFDataGetBytePtr(certData), + CFDataGetLength(certData), + NULL); + CFRelease(certData); if (cert == NULL) continue; @@ -441,6 +332,46 @@ keychain_iter_start(hx509_context context, hx509_cert_free(cert); } CFRelease(anchors); + } else if (ctx->keychain) { + /* Search for certificates in the specified keychain */ + CFMutableDictionaryRef query; + CFArrayRef searchList; + OSStatus ret; + + query = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + if (query == NULL) { + free(iter); + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + return ENOMEM; + } + + CFDictionarySetValue(query, kSecClass, kSecClassCertificate); + CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitAll); + CFDictionarySetValue(query, kSecReturnRef, kCFBooleanTrue); + + { + const void *keychains[1] = { ctx->keychain }; + searchList = CFArrayCreate(kCFAllocatorDefault, + keychains, 1, + &kCFTypeArrayCallBacks); + } + if (searchList) { + CFDictionarySetValue(query, kSecMatchSearchList, searchList); + CFRelease(searchList); + } + + ret = SecItemCopyMatching(query, (CFTypeRef *)&iter->search_result); + CFRelease(query); + + if (ret != errSecSuccess && ret != errSecItemNotFound) { + free(iter); + hx509_set_error_string(context, 0, EINVAL, + "Failed to search keychain"); + return EINVAL; + } + iter->search_index = 0; } if (iter->certs) { @@ -451,19 +382,6 @@ keychain_iter_start(hx509_context context, free(iter); return ret; } - } else { - OSStatus ret; - - ret = SecKeychainSearchCreateFromAttributes(ctx->keychain, - kSecCertificateItemClass, - NULL, - &iter->searchRef); - if (ret) { - free(iter); - hx509_set_error_string(context, 0, ret, - "Failed to start search for attributes"); - return ENOMEM; - } } *cursor = iter; @@ -478,91 +396,61 @@ static int keychain_iter(hx509_context context, hx509_certs certs, void *data, void *cursor, hx509_cert *cert) { - SecKeychainAttributeList *attrs = NULL; - SecKeychainAttributeInfo attrInfo; - UInt32 attrFormat[1] = { 0 }; - SecKeychainItemRef itemRef; - SecItemAttr item[1]; - heim_error_t error = NULL; struct iter *iter = cursor; - OSStatus ret; - UInt32 len; - void *ptr = NULL; if (iter->certs) return hx509_certs_next_cert(context, iter->certs, iter->cursor, cert); *cert = NULL; - ret = SecKeychainSearchCopyNext(iter->searchRef, &itemRef); - if (ret == errSecItemNotFound) + if (iter->search_result == NULL) return 0; - else if (ret != 0) - return EINVAL; - /* - * Pick out certificate and matching "keyid" - */ + while (iter->search_index < CFArrayGetCount(iter->search_result)) { + SecCertificateRef certRef; + SecIdentityRef identity = NULL; + CFDataRef certData; + heim_error_t error = NULL; + OSStatus ret; - item[0] = kSecPublicKeyHashItemAttr; + certRef = (SecCertificateRef)(uintptr_t)CFArrayGetValueAtIndex( + iter->search_result, iter->search_index++); - attrInfo.count = 1; - attrInfo.tag = item; - attrInfo.format = attrFormat; + certData = SecCertificateCopyData(certRef); + if (certData == NULL) + continue; - ret = SecKeychainItemCopyAttributesAndData(itemRef, &attrInfo, NULL, - &attrs, &len, &ptr); - if (ret) - return EINVAL; + *cert = hx509_cert_init_data(context, + CFDataGetBytePtr(certData), + CFDataGetLength(certData), + &error); + CFRelease(certData); - *cert = hx509_cert_init_data(context, ptr, len, &error); - if (*cert == NULL) { - ret = heim_error_get_code(error); - heim_release(error); - goto out; - } - - /* - * Find related private key if there is one by looking at - * kSecPublicKeyHashItemAttr == kSecKeyLabel - */ - { - SecKeychainSearchRef search; - SecKeychainAttribute attrKeyid; - SecKeychainAttributeList attrList; - - attrKeyid.tag = kSecKeyLabel; - attrKeyid.length = attrs->attr[0].length; - attrKeyid.data = attrs->attr[0].data; - - attrList.count = 1; - attrList.attr = &attrKeyid; - - ret = SecKeychainSearchCreateFromAttributes(NULL, - CSSM_DL_DB_RECORD_PRIVATE_KEY, - &attrList, - &search); - if (ret) { - ret = 0; - goto out; + if (*cert == NULL) { + if (error) + heim_release(error); + continue; } - ret = SecKeychainSearchCopyNext(search, &itemRef); - CFRelease(search); - if (ret == errSecItemNotFound) { - ret = 0; - goto out; - } else if (ret) { - ret = EINVAL; - goto out; + /* + * Try to find a matching private key via SecIdentity + */ + ret = SecIdentityCreateWithCertificate(NULL, certRef, &identity); + if (ret == errSecSuccess && identity) { + SecKeyRef keyRef = NULL; + + ret = SecIdentityCopyPrivateKey(identity, &keyRef); + if (ret == errSecSuccess && keyRef) { + set_private_key(context, keyRef, *cert); + CFRelease(keyRef); + } + CFRelease(identity); } - set_private_key(context, itemRef, *cert); + + return 0; } -out: - SecKeychainItemFreeAttributesAndData(attrs, ptr); - - return ret; + return 0; } /* @@ -580,9 +468,9 @@ keychain_iter_end(hx509_context context, if (iter->certs) { hx509_certs_end_seq(context, iter->certs, iter->cursor); hx509_certs_free(&iter->certs); - } else { - CFRelease(iter->searchRef); } + if (iter->search_result) + CFRelease(iter->search_result); memset(iter, 0, sizeof(*iter)); free(iter); diff --git a/lib/hx509/ks_p11.c b/lib/hx509/ks_p11.c index 265523b38..5f894b0db 100644 --- a/lib/hx509/ks_p11.c +++ b/lib/hx509/ks_p11.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 - 2008 Kungliga Tekniska Högskolan + * Copyright (c) 2004 - 2024 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -31,1174 +31,460 @@ * SUCH DAMAGE. */ +/* + * PKCS#11 keystore using OpenSSL provider (OSSL_STORE) API, and as a result we + * do no PKCS#11 calls here. + * + * We test with the Latchset PKCS#11 OpenSSL 3.x provider, which allows us to + * refer to objects via PKCS#11 URIs [RFC 7512]. + * + * Thus for hx509 a PKCS#11 object is referenced as + * + * PKCS11:[,config=] + * + * when using the Latchset provider. Alternative providers might use other + * ways to reference PKCS#11 objects, though using anything other than PKCS#11 + * URIs would not be user-friendly. + * + * The Latchset provider is at https://github.com/latchset/pkcs11-provider + * + * URI format: PKCS11:[,config=] + * + * Examples: + * PKCS11:pkcs11:token=MyToken + * PKCS11:pkcs11:slot-id=0;object=MyCert + * PKCS11:pkcs11:token=SmartCard,config=/etc/openssl-pkcs11.cnf + */ + #include "hx_locl.h" -#ifdef HAVE_DLOPEN - -#include "ref/pkcs11.h" - -struct p11_slot { - uint64_t flags; -#define P11_SESSION 1 -#define P11_SESSION_IN_USE 2 -#define P11_LOGIN_REQ 4 -#define P11_LOGIN_DONE 8 -#define P11_TOKEN_PRESENT 16 - CK_SESSION_HANDLE session; - CK_SLOT_ID id; - CK_BBOOL token; - char *name; - hx509_certs certs; - char *pin; - struct { - CK_MECHANISM_TYPE_PTR list; - CK_ULONG num; - CK_MECHANISM_INFO_PTR *infos; - } mechs; -}; +#include +#include +#include struct p11_module { - void *dl_handle; - CK_FUNCTION_LIST_PTR funcs; - CK_ULONG num_slots; - unsigned int ref; - unsigned int selected_slot; - struct p11_slot *slot; + char *uri; /* PKCS#11 URI (RFC 7512) */ + OSSL_LIB_CTX *libctx; /* OpenSSL library context */ + OSSL_PROVIDER *defprov; /* Default provider */ + OSSL_PROVIDER *p11prov; /* PKCS#11 provider */ + hx509_certs certs; /* In-memory cache of loaded certs */ + hx509_private_key *keys; /* Loaded private keys */ }; -#define P11FUNC(module,f,args) (*(module)->funcs->C_##f)args - -static int p11_get_session(hx509_context, - struct p11_module *, - struct p11_slot *, - hx509_lock, - CK_SESSION_HANDLE *); -static int p11_put_session(struct p11_module *, - struct p11_slot *, - CK_SESSION_HANDLE); -static void p11_release_module(struct p11_module *); - -static int p11_list_keys(hx509_context, - struct p11_module *, - struct p11_slot *, - CK_SESSION_HANDLE, - hx509_lock, - hx509_certs *); - -/* - * - */ - -struct p11_rsa { - struct p11_module *p; - struct p11_slot *slot; - CK_OBJECT_HANDLE private_key; - CK_OBJECT_HANDLE public_key; -}; - -static int -p11_rsa_public_encrypt(int flen, - const unsigned char *from, - unsigned char *to, - RSA *rsa, - int padding) -{ - return -1; -} - -static int -p11_rsa_public_decrypt(int flen, - const unsigned char *from, - unsigned char *to, - RSA *rsa, - int padding) -{ - return -1; -} - - -static int -p11_rsa_private_encrypt(int flen, - const unsigned char *from, - unsigned char *to, - RSA *rsa, - int padding) -{ - struct p11_rsa *p11rsa = RSA_get_app_data(rsa); - CK_OBJECT_HANDLE key = p11rsa->private_key; - CK_SESSION_HANDLE session; - CK_MECHANISM mechanism; - CK_ULONG ck_sigsize; - int ret; - - if (padding != RSA_PKCS1_PADDING) - return -1; - - memset(&mechanism, 0, sizeof(mechanism)); - mechanism.mechanism = CKM_RSA_PKCS; - - ck_sigsize = RSA_size(rsa); - - ret = p11_get_session(NULL, p11rsa->p, p11rsa->slot, NULL, &session); - if (ret) - return -1; - - ret = P11FUNC(p11rsa->p, SignInit, (session, &mechanism, key)); - if (ret != CKR_OK) { - p11_put_session(p11rsa->p, p11rsa->slot, session); - return -1; - } - - ret = P11FUNC(p11rsa->p, Sign, - (session, (CK_BYTE *)(intptr_t)from, flen, to, &ck_sigsize)); - p11_put_session(p11rsa->p, p11rsa->slot, session); - if (ret != CKR_OK) - return -1; - - return ck_sigsize; -} - -static int -p11_rsa_private_decrypt(int flen, const unsigned char *from, unsigned char *to, - RSA * rsa, int padding) -{ - struct p11_rsa *p11rsa = RSA_get_app_data(rsa); - CK_OBJECT_HANDLE key = p11rsa->private_key; - CK_SESSION_HANDLE session; - CK_MECHANISM mechanism; - CK_ULONG ck_sigsize; - int ret; - - if (padding != RSA_PKCS1_PADDING) - return -1; - - memset(&mechanism, 0, sizeof(mechanism)); - mechanism.mechanism = CKM_RSA_PKCS; - - ck_sigsize = RSA_size(rsa); - - ret = p11_get_session(NULL, p11rsa->p, p11rsa->slot, NULL, &session); - if (ret) - return -1; - - ret = P11FUNC(p11rsa->p, DecryptInit, (session, &mechanism, key)); - if (ret != CKR_OK) { - p11_put_session(p11rsa->p, p11rsa->slot, session); - return -1; - } - - ret = P11FUNC(p11rsa->p, Decrypt, - (session, (CK_BYTE *)(intptr_t)from, flen, to, &ck_sigsize)); - p11_put_session(p11rsa->p, p11rsa->slot, session); - if (ret != CKR_OK) - return -1; - - return ck_sigsize; -} - -static int -p11_rsa_init(RSA *rsa) -{ - return 1; -} - -static int -p11_rsa_finish(RSA *rsa) -{ - struct p11_rsa *p11rsa = RSA_get_app_data(rsa); - p11_release_module(p11rsa->p); - free(p11rsa); - return 1; -} - -static const RSA_METHOD p11_rsa_pkcs1_method = { - "hx509 PKCS11 PKCS#1 RSA", - p11_rsa_public_encrypt, - p11_rsa_public_decrypt, - p11_rsa_private_encrypt, - p11_rsa_private_decrypt, - NULL, - NULL, - p11_rsa_init, - p11_rsa_finish, - 0, - NULL, - NULL, - NULL, - NULL -}; - -/* - * - */ - -static int -p11_mech_info(hx509_context context, - struct p11_module *p, - struct p11_slot *slot, - int num) -{ - CK_ULONG i; - int ret; - - ret = P11FUNC(p, GetMechanismList, (slot->id, NULL_PTR, &i)); - if (ret) { - hx509_set_error_string(context, 0, HX509_PKCS11_NO_MECH, - "Failed to get mech list count for slot %d", - num); - return HX509_PKCS11_NO_MECH; - } - if (i == 0) { - hx509_set_error_string(context, 0, HX509_PKCS11_NO_MECH, - "no mech supported for slot %d", num); - return HX509_PKCS11_NO_MECH; - } - slot->mechs.list = calloc(i, sizeof(slot->mechs.list[0])); - if (slot->mechs.list == NULL) { - hx509_set_error_string(context, 0, ENOMEM, - "out of memory"); - return ENOMEM; - } - slot->mechs.num = i; - ret = P11FUNC(p, GetMechanismList, (slot->id, slot->mechs.list, &i)); - if (ret) { - hx509_set_error_string(context, 0, HX509_PKCS11_NO_MECH, - "Failed to get mech list for slot %d", - num); - return HX509_PKCS11_NO_MECH; - } - assert(i == slot->mechs.num); - - slot->mechs.infos = calloc(i, sizeof(*slot->mechs.infos)); - if (slot->mechs.list == NULL) { - hx509_set_error_string(context, 0, ENOMEM, - "out of memory"); - return ENOMEM; - } - - for (i = 0; i < slot->mechs.num; i++) { - slot->mechs.infos[i] = calloc(1, sizeof(*(slot->mechs.infos[0]))); - if (slot->mechs.infos[i] == NULL) { - hx509_set_error_string(context, 0, ENOMEM, - "out of memory"); - return ENOMEM; - } - ret = P11FUNC(p, GetMechanismInfo, (slot->id, slot->mechs.list[i], - slot->mechs.infos[i])); - if (ret) { - hx509_set_error_string(context, 0, HX509_PKCS11_NO_MECH, - "Failed to get mech info for slot %d", - num); - return HX509_PKCS11_NO_MECH; - } - } - - return 0; -} - -static int -p11_init_slot(hx509_context context, - struct p11_module *p, - hx509_lock lock, - CK_SLOT_ID id, - int num, - struct p11_slot *slot) -{ - CK_SESSION_HANDLE session; - CK_SLOT_INFO slot_info; - CK_TOKEN_INFO token_info; - size_t i; - int ret; - - slot->certs = NULL; - slot->id = id; - - ret = P11FUNC(p, GetSlotInfo, (slot->id, &slot_info)); - if (ret) { - hx509_set_error_string(context, 0, HX509_PKCS11_TOKEN_CONFUSED, - "Failed to init PKCS11 slot %d", - num); - return HX509_PKCS11_TOKEN_CONFUSED; - } - - for (i = sizeof(slot_info.slotDescription) - 1; i > 0; i--) { - char c = slot_info.slotDescription[i]; - if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\0') - continue; - i++; - break; - } - - ret = asprintf(&slot->name, "%.*s", (int)i, - slot_info.slotDescription); - if (ret == -1) - return ENOMEM; - - if ((slot_info.flags & CKF_TOKEN_PRESENT) == 0) - return 0; - - ret = P11FUNC(p, GetTokenInfo, (slot->id, &token_info)); - if (ret) { - hx509_set_error_string(context, 0, HX509_PKCS11_NO_TOKEN, - "Failed to init PKCS11 slot %d " - "with error 0x%08x", - num, ret); - return HX509_PKCS11_NO_TOKEN; - } - slot->flags |= P11_TOKEN_PRESENT; - - if (token_info.flags & CKF_LOGIN_REQUIRED) - slot->flags |= P11_LOGIN_REQ; - - ret = p11_get_session(context, p, slot, lock, &session); - if (ret) - return ret; - - ret = p11_mech_info(context, p, slot, num); - if (ret) - goto out; - - ret = p11_list_keys(context, p, slot, session, lock, &slot->certs); - out: - p11_put_session(p, slot, session); - - return ret; -} - -static int -p11_get_session(hx509_context context, - struct p11_module *p, - struct p11_slot *slot, - hx509_lock lock, - CK_SESSION_HANDLE *psession) -{ - CK_RV ret; - - if (slot->flags & P11_SESSION_IN_USE) - _hx509_abort("slot already in session"); - - if (slot->flags & P11_SESSION) { - slot->flags |= P11_SESSION_IN_USE; - *psession = slot->session; - return 0; - } - - ret = P11FUNC(p, OpenSession, (slot->id, - CKF_SERIAL_SESSION, - NULL, - NULL, - &slot->session)); - if (ret != CKR_OK) { - if (context) - hx509_set_error_string(context, 0, HX509_PKCS11_OPEN_SESSION, - "Failed to OpenSession for slot id %d " - "with error: 0x%08x", - (int)slot->id, ret); - return HX509_PKCS11_OPEN_SESSION; - } - - slot->flags |= P11_SESSION; - - /* - * If we have have to login, and haven't tried before and have a - * prompter or known to work pin code. - * - * This code is very conversative and only uses the prompter in - * the hx509_lock, the reason is that it's bad to try many - * passwords on a pkcs11 token, it might lock up and have to be - * unlocked by a administrator. - * - * XXX try harder to not use pin several times on the same card. - */ - - if ( (slot->flags & P11_LOGIN_REQ) - && (slot->flags & P11_LOGIN_DONE) == 0 - && (lock || slot->pin)) - { - hx509_prompt prompt; - char pin[20]; - char *str; - - if (slot->pin == NULL) { - - memset(&prompt, 0, sizeof(prompt)); - - ret = asprintf(&str, "PIN code for %s: ", slot->name); - if (ret == -1 || str == NULL) { - if (context) - hx509_set_error_string(context, 0, ENOMEM, "out of memory"); - return ENOMEM; - } - prompt.prompt = str; - prompt.type = HX509_PROMPT_TYPE_PASSWORD; - prompt.reply.data = pin; - prompt.reply.length = sizeof(pin); - - ret = hx509_lock_prompt(lock, &prompt); - if (ret) { - free(str); - if (context) - hx509_set_error_string(context, 0, ret, - "Failed to get pin code for slot " - "id %d with error: %d", - (int)slot->id, ret); - return ret; - } - free(str); - } else { - strlcpy(pin, slot->pin, sizeof(pin)); - } - - ret = P11FUNC(p, Login, (slot->session, CKU_USER, - (unsigned char*)pin, strlen(pin))); - if (ret != CKR_OK) { - if (context) - hx509_set_error_string(context, 0, HX509_PKCS11_LOGIN, - "Failed to login on slot id %d " - "with error: 0x%08x", - (int)slot->id, ret); - switch(ret) { - case CKR_PIN_LOCKED: - return HX509_PKCS11_PIN_LOCKED; - case CKR_PIN_EXPIRED: - return HX509_PKCS11_PIN_EXPIRED; - case CKR_PIN_INCORRECT: - return HX509_PKCS11_PIN_INCORRECT; - case CKR_USER_PIN_NOT_INITIALIZED: - return HX509_PKCS11_PIN_NOT_INITIALIZED; - default: - return HX509_PKCS11_LOGIN; - } - } else - slot->flags |= P11_LOGIN_DONE; - - if (slot->pin == NULL) { - slot->pin = strdup(pin); - if (slot->pin == NULL) { - if (context) - hx509_set_error_string(context, 0, ENOMEM, - "out of memory"); - return ENOMEM; - } - } - } else - slot->flags |= P11_LOGIN_DONE; - - slot->flags |= P11_SESSION_IN_USE; - - *psession = slot->session; - - return 0; -} - -static int -p11_put_session(struct p11_module *p, - struct p11_slot *slot, - CK_SESSION_HANDLE session) -{ - if ((slot->flags & P11_SESSION_IN_USE) == 0) - _hx509_abort("slot not in session"); - slot->flags &= ~P11_SESSION_IN_USE; - - return 0; -} - -static int -iterate_entries(hx509_context context, - struct p11_module *p, struct p11_slot *slot, - CK_SESSION_HANDLE session, - CK_ATTRIBUTE *search_data, int num_search_data, - CK_ATTRIBUTE *query, int num_query, - int (*func)(hx509_context, - struct p11_module *, struct p11_slot *, - CK_SESSION_HANDLE session, - CK_OBJECT_HANDLE object, - void *, CK_ATTRIBUTE *, int), void *ptr) -{ - CK_OBJECT_HANDLE object; - CK_ULONG object_count; - int ret, ret2, i; - - ret = P11FUNC(p, FindObjectsInit, (session, search_data, num_search_data)); - if (ret != CKR_OK) { - return -1; - } - while (1) { - ret = P11FUNC(p, FindObjects, (session, &object, 1, &object_count)); - if (ret != CKR_OK) { - return -1; - } - if (object_count == 0) - break; - - for (i = 0; i < num_query; i++) - query[i].pValue = NULL; - - ret = P11FUNC(p, GetAttributeValue, - (session, object, query, num_query)); - if (ret != CKR_OK) { - return -1; - } - for (i = 0; i < num_query; i++) { - query[i].pValue = malloc(query[i].ulValueLen); - if (query[i].pValue == NULL) { - ret = ENOMEM; - goto out; - } - } - ret = P11FUNC(p, GetAttributeValue, - (session, object, query, num_query)); - if (ret != CKR_OK) { - ret = -1; - goto out; - } - - ret = (*func)(context, p, slot, session, object, ptr, query, num_query); - if (ret) - goto out; - - for (i = 0; i < num_query; i++) { - if (query[i].pValue) - free(query[i].pValue); - query[i].pValue = NULL; - } - } - out: - - for (i = 0; i < num_query; i++) { - if (query[i].pValue) - free(query[i].pValue); - query[i].pValue = NULL; - } - - ret2 = P11FUNC(p, FindObjectsFinal, (session)); - if (ret2 != CKR_OK) { - return ret2; - } - - return ret; -} - -static BIGNUM * -getattr_bn(struct p11_module *p, - struct p11_slot *slot, - CK_SESSION_HANDLE session, - CK_OBJECT_HANDLE object, - unsigned int type) -{ - CK_ATTRIBUTE query; - BIGNUM *bn; - int ret; - - query.type = type; - query.pValue = NULL; - query.ulValueLen = 0; - - ret = P11FUNC(p, GetAttributeValue, - (session, object, &query, 1)); - if (ret != CKR_OK) - return NULL; - - query.pValue = malloc(query.ulValueLen); - - ret = P11FUNC(p, GetAttributeValue, - (session, object, &query, 1)); - if (ret != CKR_OK) { - free(query.pValue); - return NULL; - } - bn = BN_bin2bn(query.pValue, query.ulValueLen, NULL); - free(query.pValue); - - return bn; -} - -static int -collect_private_key(hx509_context context, - struct p11_module *p, struct p11_slot *slot, - CK_SESSION_HANDLE session, - CK_OBJECT_HANDLE object, - void *ptr, CK_ATTRIBUTE *query, int num_query) -{ - struct hx509_collector *collector = ptr; - hx509_private_key key; - heim_octet_string localKeyId; - int ret; - RSA *rsa; - struct p11_rsa *p11rsa; - - localKeyId.data = query[0].pValue; - localKeyId.length = query[0].ulValueLen; - - ret = hx509_private_key_init(&key, NULL, NULL); - if (ret) - return ret; - - rsa = RSA_new(); - if (rsa == NULL) - _hx509_abort("out of memory"); - - /* - * The exponent and modulus should always be present according to - * the pkcs11 specification, but some smartcards leaves it out, - * let ignore any failure to fetch it. - */ - rsa->n = getattr_bn(p, slot, session, object, CKA_MODULUS); - rsa->e = getattr_bn(p, slot, session, object, CKA_PUBLIC_EXPONENT); - - p11rsa = calloc(1, sizeof(*p11rsa)); - if (p11rsa == NULL) - _hx509_abort("out of memory"); - - p11rsa->p = p; - p11rsa->slot = slot; - p11rsa->private_key = object; - - if (p->ref == 0) - _hx509_abort("pkcs11 ref == 0 on alloc"); - p->ref++; - if (p->ref == UINT_MAX) - _hx509_abort("pkcs11 ref == UINT_MAX on alloc"); - - RSA_set_method(rsa, &p11_rsa_pkcs1_method); - ret = RSA_set_app_data(rsa, p11rsa); - if (ret != 1) - _hx509_abort("RSA_set_app_data"); - - hx509_private_key_assign_rsa(key, rsa); - - ret = _hx509_collector_private_key_add(context, - collector, - hx509_signature_rsa(), - key, - NULL, - &localKeyId); - - if (ret) { - hx509_private_key_free(&key); - return ret; - } - return 0; -} - static void -p11_cert_release(hx509_cert cert, void *ctx) +p11_module_free(struct p11_module *p) { - struct p11_module *p = ctx; - p11_release_module(p); + int i; + + if (p == NULL) + return; + if (p->certs) + hx509_certs_free(&p->certs); + for (i = 0; p->keys && p->keys[i]; i++) + hx509_private_key_free(&p->keys[i]); + free(p->keys); + if (p->p11prov) + OSSL_PROVIDER_unload(p->p11prov); + if (p->defprov) + OSSL_PROVIDER_unload(p->defprov); + if (p->libctx) + OSSL_LIB_CTX_free(p->libctx); + free(p->uri); + free(p); } - +/* + * Add an X.509 certificate to the collector + */ static int -collect_cert(hx509_context context, - struct p11_module *p, struct p11_slot *slot, - CK_SESSION_HANDLE session, - CK_OBJECT_HANDLE object, - void *ptr, CK_ATTRIBUTE *query, int num_query) +add_cert(hx509_context context, struct hx509_collector *c, + OSSL_STORE_INFO *info) { - struct hx509_collector *collector = ptr; - heim_error_t error = NULL; + X509 *x509; + unsigned char *der = NULL; + int der_len; hx509_cert cert; + heim_error_t error = NULL; int ret; - if ((CK_LONG)query[0].ulValueLen == -1 || - (CK_LONG)query[1].ulValueLen == -1) - { - return 0; - } + x509 = OSSL_STORE_INFO_get1_CERT(info); + if (x509 == NULL) + return 0; + + der_len = i2d_X509(x509, &der); + X509_free(x509); + if (der_len <= 0) + return HX509_CERTIFICATE_MALFORMED; + + cert = hx509_cert_init_data(context, der, der_len, &error); + OPENSSL_free(der); - cert = hx509_cert_init_data(context, query[1].pValue, - query[1].ulValueLen, &error); if (cert == NULL) { - ret = heim_error_get_code(error); - heim_release(error); - return ret; + ret = error ? heim_error_get_code(error) : ENOMEM; + heim_release(error); + return ret; } - if (p->ref == 0) - _hx509_abort("pkcs11 ref == 0 on alloc"); - p->ref++; - if (p->ref == UINT_MAX) - _hx509_abort("pkcs11 ref to high"); - - _hx509_cert_set_release(cert, p11_cert_release, p); - - { - heim_octet_string data; - - data.data = query[0].pValue; - data.length = query[0].ulValueLen; - - _hx509_set_cert_attribute(context, - cert, - &asn1_oid_id_pkcs_9_at_localKeyId, - &data); - } - - if ((CK_LONG)query[2].ulValueLen != -1) { - char *str; - - ret = asprintf(&str, "%.*s", - (int)query[2].ulValueLen, (char *)query[2].pValue); - if (ret != -1 && str) { - hx509_cert_set_friendly_name(cert, str); - free(str); - } - } - - ret = _hx509_collector_certs_add(context, collector, cert); + ret = _hx509_collector_certs_add(context, c, cert); hx509_cert_free(cert); - return ret; } - +/* + * Add a private key to the collector + */ static int -p11_list_keys(hx509_context context, - struct p11_module *p, - struct p11_slot *slot, - CK_SESSION_HANDLE session, - hx509_lock lock, - hx509_certs *certs) +add_pkey(hx509_context context, struct hx509_collector *c, + OSSL_STORE_INFO *info) { - struct hx509_collector *collector; - CK_OBJECT_CLASS key_class; - CK_ATTRIBUTE search_data[] = { - {CKA_CLASS, NULL, 0}, - }; - CK_ATTRIBUTE query_data[3] = { - {CKA_ID, NULL, 0}, - {CKA_VALUE, NULL, 0}, - {CKA_LABEL, NULL, 0} - }; - int ret; + EVP_PKEY *pkey; + hx509_private_key key = NULL; + AlgorithmIdentifier alg; + int pkey_id, ret; - search_data[0].pValue = &key_class; - search_data[0].ulValueLen = sizeof(key_class); + pkey = OSSL_STORE_INFO_get1_PKEY(info); + if (pkey == NULL) + return 0; - if (lock == NULL) - lock = _hx509_empty_lock; + pkey_id = EVP_PKEY_base_id(pkey); + memset(&alg, 0, sizeof(alg)); - ret = _hx509_collector_alloc(context, lock, &collector); + /* Set algorithm OID based on key type */ + switch (pkey_id) { + case EVP_PKEY_RSA: + case EVP_PKEY_RSA_PSS: + ret = der_copy_oid(&asn1_oid_id_pkcs1_rsaEncryption, &alg.algorithm); + break; + case EVP_PKEY_EC: + ret = der_copy_oid(&asn1_oid_id_ecPublicKey, &alg.algorithm); + break; + case EVP_PKEY_ED25519: + ret = der_copy_oid(&asn1_oid_id_Ed25519, &alg.algorithm); + break; + case EVP_PKEY_ED448: + ret = der_copy_oid(&asn1_oid_id_Ed448, &alg.algorithm); + break; + default: + EVP_PKEY_free(pkey); + return HX509_SIG_ALG_NO_SUPPORTED; + } + if (ret) { + EVP_PKEY_free(pkey); + return ret; + } + + ret = hx509_private_key_init(&key, NULL, NULL); + if (ret) { + free_AlgorithmIdentifier(&alg); + EVP_PKEY_free(pkey); + return ret; + } + + /* Assign EVP_PKEY directly - provider handles all crypto ops */ + key->private_key.pkey = pkey; /* Takes ownership */ + + /* Set default signature algorithm */ + switch (pkey_id) { + case EVP_PKEY_RSA: + case EVP_PKEY_RSA_PSS: + key->signature_alg = ASN1_OID_ID_PKCS1_SHA256WITHRSAENCRYPTION; + break; + case EVP_PKEY_EC: + key->signature_alg = ASN1_OID_ID_ECDSA_WITH_SHA256; + break; + case EVP_PKEY_ED25519: + key->signature_alg = ASN1_OID_ID_ED25519; + break; + case EVP_PKEY_ED448: + key->signature_alg = ASN1_OID_ID_ED448; + break; + default: + break; + } + + /* Add to collector - matching with certs happens in collect_certs */ + ret = _hx509_collector_private_key_add(context, c, &alg, key, NULL, NULL); if (ret) - return ret; - - key_class = CKO_PRIVATE_KEY; - ret = iterate_entries(context, p, slot, session, - search_data, 1, - query_data, 1, - collect_private_key, collector); - if (ret) - goto out; - - key_class = CKO_CERTIFICATE; - ret = iterate_entries(context, p, slot, session, - search_data, 1, - query_data, 3, - collect_cert, collector); - if (ret) - goto out; - - ret = _hx509_collector_collect_certs(context, collector, &slot->certs); - -out: - _hx509_collector_free(collector); + hx509_private_key_free(&key); + free_AlgorithmIdentifier(&alg); return ret; } +/* + * Parse options from the residue after the PKCS#11 URI. + * Format: pkcs11:...[,config=/path/to/openssl.cnf] + */ +static int +parse_options(const char *residue, char **uri, char **config) +{ + const char *comma; + size_t uri_len; + + *uri = NULL; + *config = NULL; + + if (residue == NULL || residue[0] == '\0') + return EINVAL; + + /* Find comma separator for options */ + comma = strchr(residue, ','); + if (comma) { + uri_len = comma - residue; + *uri = strndup(residue, uri_len); + if (*uri == NULL) + return ENOMEM; + + /* Parse config= option */ + comma++; + while (*comma) { + if (strncmp(comma, "config=", 7) == 0) { + const char *end; + comma += 7; + end = strchr(comma, ','); + if (end) + *config = strndup(comma, end - comma); + else + *config = strdup(comma); + if (*config == NULL) { + free(*uri); + *uri = NULL; + return ENOMEM; + } + break; + } + comma = strchr(comma, ','); + if (comma) + comma++; + else + break; + } + } else { + *uri = strdup(residue); + if (*uri == NULL) + return ENOMEM; + } + + return 0; +} static int p11_init(hx509_context context, - hx509_certs certs, void **data, int flags, - const char *residue, hx509_lock lock) + hx509_certs certs, void **data, int flags, + const char *residue, hx509_lock lock) { - CK_C_GetFunctionList getFuncs; - struct p11_module *p; - char *list, *str; + struct p11_module *p = NULL; + struct hx509_collector *c = NULL; + OSSL_STORE_CTX *store = NULL; + char *uri = NULL; + char *config = NULL; int ret; *data = NULL; - if (flags & HX509_CERTS_NO_PRIVATE_KEYS) { - hx509_set_error_string(context, 0, ENOTSUP, - "PKCS#11 store does not support " - "HX509_CERTS_NO_PRIVATE_KEYS flag"); - return ENOTSUP; + ret = parse_options(residue, &uri, &config); + if (ret) { + hx509_set_error_string(context, 0, ret, + "Failed to parse PKCS#11 store specification"); + return ret; } - if (residue == NULL || residue[0] == '\0') { - hx509_set_error_string(context, 0, EINVAL, - "PKCS#11 store not specified"); - return EINVAL; - } - list = strdup(residue); - if (list == NULL) - return ENOMEM; - p = calloc(1, sizeof(*p)); if (p == NULL) { - free(list); - return ENOMEM; + ret = ENOMEM; + goto out; } - p->ref = 1; - p->selected_slot = 0; + p->uri = uri; + uri = NULL; /* p owns it now */ - str = strchr(list, ','); - if (str) - *str++ = '\0'; - while (str) { - char *strnext; - strnext = strchr(str, ','); - if (strnext) - *strnext++ = '\0'; - if (strncasecmp(str, "slot=", 5) == 0) - p->selected_slot = atoi(str + 5); - str = strnext; + /* Create a separate library context for PKCS#11 */ + p->libctx = OSSL_LIB_CTX_new(); + if (p->libctx == NULL) { + ret = HX509_PKCS11_LOAD; + _hx509_set_error_string_openssl(context, 0, ret, + "Failed to create OpenSSL library context"); + goto out; } - p->dl_handle = dlopen(list, RTLD_NOW | RTLD_LOCAL | RTLD_GROUP); - if (p->dl_handle == NULL) { - ret = HX509_PKCS11_LOAD; - hx509_set_error_string(context, 0, ret, - "Failed to open %s: %s", list, dlerror()); - goto out; + /* Load configuration if specified */ + if (config) { + if (!OSSL_LIB_CTX_load_config(p->libctx, config)) { + ret = HX509_PKCS11_LOAD; + _hx509_set_error_string_openssl(context, 0, ret, + "Failed to load OpenSSL config: %s", + config); + goto out; + } } - getFuncs = (CK_C_GetFunctionList) dlsym(p->dl_handle, "C_GetFunctionList"); - if (getFuncs == NULL) { - ret = HX509_PKCS11_LOAD; - hx509_set_error_string(context, 0, ret, - "C_GetFunctionList missing in %s: %s", - list, dlerror()); - goto out; + /* Explicitly load the default and pkcs11 providers */ + p->defprov = OSSL_PROVIDER_load(p->libctx, "default"); + if (p->defprov == NULL) { + ret = HX509_PKCS11_LOAD; + _hx509_set_error_string_openssl(context, 0, ret, + "Failed to load OpenSSL default provider"); + goto out; } - ret = (*getFuncs)(&p->funcs); - if (ret) { - ret = HX509_PKCS11_LOAD; - hx509_set_error_string(context, 0, ret, - "C_GetFunctionList failed in %s", list); - goto out; + p->p11prov = OSSL_PROVIDER_load(p->libctx, "pkcs11"); + if (p->p11prov == NULL) { + ret = HX509_PKCS11_LOAD; + _hx509_set_error_string_openssl(context, 0, ret, + "Failed to load OpenSSL pkcs11 provider. " + "Ensure pkcs11-provider is installed."); + goto out; } - ret = P11FUNC(p, Initialize, (NULL_PTR)); - if (ret != CKR_OK) { - ret = HX509_PKCS11_TOKEN_CONFUSED; - hx509_set_error_string(context, 0, ret, - "Failed initialize the PKCS11 module"); - goto out; + /* Initialize in-memory cert cache */ + ret = hx509_certs_init(context, "MEMORY:pkcs11-cache", 0, NULL, &p->certs); + if (ret) + goto out; + + /* Open PKCS#11 store via provider */ + store = OSSL_STORE_open_ex(p->uri, p->libctx, NULL, + NULL, NULL, NULL, NULL, NULL); + if (store == NULL) { + ret = HX509_PKCS11_LOAD; + _hx509_set_error_string_openssl(context, 0, ret, + "Failed to open PKCS#11 store: %s", p->uri); + goto out; } - ret = P11FUNC(p, GetSlotList, (FALSE, NULL, &p->num_slots)); - if (ret) { - ret = HX509_PKCS11_TOKEN_CONFUSED; - hx509_set_error_string(context, 0, ret, - "Failed to get number of PKCS11 slots"); - goto out; + /* Create collector for cert/key matching */ + ret = _hx509_collector_alloc(context, lock, &c); + if (ret) + goto out; + + /* Load all objects from the store */ + for (;;) { + OSSL_STORE_INFO *info = OSSL_STORE_load(store); + if (info == NULL) { + if (OSSL_STORE_eof(store)) + break; + ret = HX509_PKCS11_TOKEN_CONFUSED; + _hx509_set_error_string_openssl(context, 0, ret, + "Error loading from PKCS#11 store"); + goto out; + } + + switch (OSSL_STORE_INFO_get_type(info)) { + case OSSL_STORE_INFO_CERT: + ret = add_cert(context, c, info); + break; + case OSSL_STORE_INFO_PKEY: + if (!(flags & HX509_CERTS_NO_PRIVATE_KEYS)) + ret = add_pkey(context, c, info); + break; + default: + /* Ignore other object types */ + break; + } + OSSL_STORE_INFO_free(info); + if (ret) + goto out; } - if (p->num_slots == 0) { - ret = HX509_PKCS11_NO_SLOT; - hx509_set_error_string(context, 0, ret, - "Selected PKCS11 module have no slots"); - goto out; - } + /* Finalize: match keys to certs, populate p->certs */ + ret = _hx509_collector_collect_certs(context, c, &p->certs); + if (ret) + goto out; - - { - CK_SLOT_ID_PTR slot_ids; - int num_tokens = 0; - size_t i; - - slot_ids = malloc(p->num_slots * sizeof(*slot_ids)); - if (slot_ids == NULL) { - hx509_clear_error_string(context); - ret = ENOMEM; - goto out; - } - - ret = P11FUNC(p, GetSlotList, (FALSE, slot_ids, &p->num_slots)); - if (ret) { - free(slot_ids); - hx509_set_error_string(context, 0, HX509_PKCS11_TOKEN_CONFUSED, - "Failed getting slot-list from " - "PKCS11 module"); - ret = HX509_PKCS11_TOKEN_CONFUSED; - goto out; - } - - p->slot = calloc(p->num_slots, sizeof(p->slot[0])); - if (p->slot == NULL) { - free(slot_ids); - hx509_set_error_string(context, 0, ENOMEM, - "Failed to get memory for slot-list"); - ret = ENOMEM; - goto out; - } - - for (i = 0; i < p->num_slots; i++) { - if ((p->selected_slot != 0) && (slot_ids[i] != (p->selected_slot - 1))) - continue; - ret = p11_init_slot(context, p, lock, slot_ids[i], i, &p->slot[i]); - if (!ret) { - if (p->slot[i].flags & P11_TOKEN_PRESENT) - num_tokens++; - } - } - free(slot_ids); - if (ret) - goto out; - if (num_tokens == 0) { - ret = HX509_PKCS11_NO_TOKEN; - goto out; - } - } - - free(list); + /* Also collect any unmatched private keys */ + ret = _hx509_collector_collect_private_keys(context, c, &p->keys); + if (ret) + goto out; *data = p; + p = NULL; /* Success - don't free */ + ret = 0; - return 0; - out: - if (list) - free(list); - p11_release_module(p); +out: + if (store) + OSSL_STORE_close(store); + if (c) + _hx509_collector_free(c); + free(config); + free(uri); + p11_module_free(p); return ret; } -static void -p11_release_module(struct p11_module *p) -{ - size_t i; - - if (p->ref == 0) - _hx509_abort("pkcs11 ref to low"); - if (--p->ref > 0) - return; - - for (i = 0; i < p->num_slots; i++) { - if (p->slot[i].flags & P11_SESSION_IN_USE) - _hx509_abort("pkcs11 module release while session in use"); - if (p->slot[i].flags & P11_SESSION) { - P11FUNC(p, CloseSession, (p->slot[i].session)); - } - - if (p->slot[i].name) - free(p->slot[i].name); - if (p->slot[i].pin) { - memset(p->slot[i].pin, 0, strlen(p->slot[i].pin)); - free(p->slot[i].pin); - } - if (p->slot[i].mechs.num) { - free(p->slot[i].mechs.list); - - if (p->slot[i].mechs.infos) { - size_t j; - - for (j = 0 ; j < p->slot[i].mechs.num ; j++) - free(p->slot[i].mechs.infos[j]); - free(p->slot[i].mechs.infos); - } - } - } - free(p->slot); - - if (p->funcs) - P11FUNC(p, Finalize, (NULL)); - - if (p->dl_handle) - dlclose(p->dl_handle); - - memset(p, 0, sizeof(*p)); - free(p); -} - static int p11_free(hx509_certs certs, void *data) { - struct p11_module *p = data; - size_t i; - - for (i = 0; i < p->num_slots; i++) { - if (p->slot[i].certs) - hx509_certs_free(&p->slot[i].certs); - } - p11_release_module(p); + p11_module_free(data); return 0; } -struct p11_cursor { - hx509_certs certs; - void *cursor; -}; - static int p11_iter_start(hx509_context context, - hx509_certs certs, void *data, void **cursor) + hx509_certs certs, void *data, void **cursor) { struct p11_module *p = data; - struct p11_cursor *c; - int ret; - size_t i; - - c = malloc(sizeof(*c)); - if (c == NULL) { - hx509_clear_error_string(context); - return ENOMEM; - } - ret = hx509_certs_init(context, "MEMORY:pkcs11-iter", 0, NULL, &c->certs); - if (ret) { - free(c); - return ret; - } - - for (i = 0 ; i < p->num_slots; i++) { - if (p->slot[i].certs == NULL) - continue; - ret = hx509_certs_merge(context, c->certs, p->slot[i].certs); - if (ret) { - hx509_certs_free(&c->certs); - free(c); - return ret; - } - } - - ret = hx509_certs_start_seq(context, c->certs, &c->cursor); - if (ret) { - hx509_certs_free(&c->certs); - free(c); - return 0; - } - *cursor = c; - - return 0; + return hx509_certs_start_seq(context, p->certs, cursor); } static int p11_iter(hx509_context context, - hx509_certs certs, void *data, void *cursor, hx509_cert *cert) + hx509_certs certs, void *data, void *cursor, hx509_cert *cert) { - struct p11_cursor *c = cursor; - return hx509_certs_next_cert(context, c->certs, c->cursor, cert); + struct p11_module *p = data; + return hx509_certs_next_cert(context, p->certs, cursor, cert); } static int p11_iter_end(hx509_context context, - hx509_certs certs, void *data, void *cursor) + hx509_certs certs, void *data, void *cursor) { - struct p11_cursor *c = cursor; - int ret; - ret = hx509_certs_end_seq(context, c->certs, c->cursor); - hx509_certs_free(&c->certs); - free(c); - return ret; + struct p11_module *p = data; + return hx509_certs_end_seq(context, p->certs, cursor); } -#define MECHFLAG(x) { "unknown-flag-" #x, x } -static struct units mechflags[] = { - MECHFLAG(0x80000000), - MECHFLAG(0x40000000), - MECHFLAG(0x20000000), - MECHFLAG(0x10000000), - MECHFLAG(0x08000000), - MECHFLAG(0x04000000), - {"ec-compress", 0x2000000 }, - {"ec-uncompress", 0x1000000 }, - {"ec-namedcurve", 0x0800000 }, - {"ec-ecparameters", 0x0400000 }, - {"ec-f-2m", 0x0200000 }, - {"ec-f-p", 0x0100000 }, - {"derive", 0x0080000 }, - {"unwrap", 0x0040000 }, - {"wrap", 0x0020000 }, - {"genereate-key-pair", 0x0010000 }, - {"generate", 0x0008000 }, - {"verify-recover", 0x0004000 }, - {"verify", 0x0002000 }, - {"sign-recover", 0x0001000 }, - {"sign", 0x0000800 }, - {"digest", 0x0000400 }, - {"decrypt", 0x0000200 }, - {"encrypt", 0x0000100 }, - MECHFLAG(0x00080), - MECHFLAG(0x00040), - MECHFLAG(0x00020), - MECHFLAG(0x00010), - MECHFLAG(0x00008), - MECHFLAG(0x00004), - MECHFLAG(0x00002), - {"hw", 0x0000001 }, - { NULL, 0x0000000 } -}; -#undef MECHFLAG +static int +p11_getkeys(hx509_context context, + hx509_certs certs, void *data, + hx509_private_key **keys) +{ + struct p11_module *p = data; + int i, nkeys; + + for (nkeys = 0; p->keys && p->keys[nkeys]; nkeys++) + ; + + *keys = calloc(nkeys + 1, sizeof(**keys)); + if (*keys == NULL) { + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + return ENOMEM; + } + + for (i = 0; i < nkeys; i++) { + (*keys)[i] = _hx509_private_key_ref(p->keys[i]); + if ((*keys)[i] == NULL) { + while (--i >= 0) + hx509_private_key_free(&(*keys)[i]); + free(*keys); + *keys = NULL; + hx509_set_error_string(context, 0, ENOMEM, "out of memory"); + return ENOMEM; + } + } + (*keys)[nkeys] = NULL; + return 0; +} static int p11_printinfo(hx509_context context, - hx509_certs certs, - void *data, - int (*func)(void *, const char *), - void *ctx) + hx509_certs certs, + void *data, + int (*func)(void *, const char *), + void *ctx) { struct p11_module *p = data; - size_t i, j; - - _hx509_pi_printf(func, ctx, "pkcs11 driver with %d slot%s", - p->num_slots, p->num_slots > 1 ? "s" : ""); - - for (i = 0; i < p->num_slots; i++) { - struct p11_slot *s = &p->slot[i]; - - _hx509_pi_printf(func, ctx, "slot %d: id: %d name: %s flags: %08x", - i, (int)s->id, s->name, s->flags); - - _hx509_pi_printf(func, ctx, "number of supported mechanisms: %lu", - (unsigned long)s->mechs.num); - for (j = 0; j < s->mechs.num; j++) { - const char *mechname = "unknown"; - char flags[256], unknownname[40]; -#define MECHNAME(s,n) case s: mechname = n; break - switch(s->mechs.list[j]) { - MECHNAME(CKM_RSA_PKCS_KEY_PAIR_GEN, "rsa-pkcs-key-pair-gen"); - MECHNAME(CKM_RSA_PKCS, "rsa-pkcs"); - MECHNAME(CKM_RSA_X_509, "rsa-x-509"); - MECHNAME(CKM_MD5_RSA_PKCS, "md5-rsa-pkcs"); - MECHNAME(CKM_SHA1_RSA_PKCS, "sha1-rsa-pkcs"); - MECHNAME(CKM_SHA256_RSA_PKCS, "sha256-rsa-pkcs"); - MECHNAME(CKM_SHA384_RSA_PKCS, "sha384-rsa-pkcs"); - MECHNAME(CKM_SHA512_RSA_PKCS, "sha512-rsa-pkcs"); - MECHNAME(CKM_RIPEMD160_RSA_PKCS, "ripemd160-rsa-pkcs"); - MECHNAME(CKM_RSA_PKCS_OAEP, "rsa-pkcs-oaep"); - MECHNAME(CKM_SHA512_HMAC, "sha512-hmac"); - MECHNAME(CKM_SHA512, "sha512"); - MECHNAME(CKM_SHA384_HMAC, "sha384-hmac"); - MECHNAME(CKM_SHA384, "sha384"); - MECHNAME(CKM_SHA256_HMAC, "sha256-hmac"); - MECHNAME(CKM_SHA256, "sha256"); - MECHNAME(CKM_SHA_1, "sha1"); - MECHNAME(CKM_MD5, "md5"); - MECHNAME(CKM_RIPEMD160, "ripemd-160"); - MECHNAME(CKM_DES_ECB, "des-ecb"); - MECHNAME(CKM_DES_CBC, "des-cbc"); - MECHNAME(CKM_AES_ECB, "aes-ecb"); - MECHNAME(CKM_AES_CBC, "aes-cbc"); - MECHNAME(CKM_DH_PKCS_PARAMETER_GEN, "dh-pkcs-parameter-gen"); - default: - snprintf(unknownname, sizeof(unknownname), - "unknown-mech-%lu", - (unsigned long)s->mechs.list[j]); - mechname = unknownname; - break; - } -#undef MECHNAME - unparse_flags(s->mechs.infos[j]->flags, mechflags, - flags, sizeof(flags)); - - _hx509_pi_printf(func, ctx, " %s: %s", mechname, flags); - } - } + _hx509_pi_printf(func, ctx, "PKCS#11 store: %s", p->uri); + _hx509_pi_printf(func, ctx, " Provider: %s", + p->p11prov ? OSSL_PROVIDER_get0_name(p->p11prov) : "none"); return 0; } @@ -1206,25 +492,21 @@ static struct hx509_keyset_ops keyset_pkcs11 = { "PKCS11", 0, p11_init, - NULL, + NULL, /* store */ p11_free, - NULL, - NULL, + NULL, /* add */ + NULL, /* query */ p11_iter_start, p11_iter, p11_iter_end, p11_printinfo, - NULL, - NULL, - NULL + p11_getkeys, + NULL, /* addkey */ + NULL /* destroy */ }; -#endif /* HAVE_DLOPEN */ - HX509_LIB_FUNCTION void HX509_LIB_CALL _hx509_ks_pkcs11_register(hx509_context context) { -#ifdef HAVE_DLOPEN _hx509_ks_register(context, &keyset_pkcs11); -#endif } diff --git a/lib/hx509/ks_p12.c b/lib/hx509/ks_p12.c index 1e9a92a4f..92bb7386c 100644 --- a/lib/hx509/ks_p12.c +++ b/lib/hx509/ks_p12.c @@ -489,6 +489,7 @@ addBag(hx509_context context, return ENOMEM; } as->val = ptr; + memset(&as->val[as->len], 0, sizeof(as->val[0])); ret = der_copy_oid(oid, &as->val[as->len].contentType); if (ret) { diff --git a/lib/hx509/libhx509-exports.def b/lib/hx509/libhx509-exports.def index 12c45daf7..1dc603851 100644 --- a/lib/hx509/libhx509-exports.def +++ b/lib/hx509/libhx509-exports.def @@ -172,6 +172,7 @@ EXPORTS hx509_context_free hx509_context_init hx509_context_set_missing_revoke + hx509_context_set_ossl_cnf_propq hx509_crl_add_revoked_certs hx509_crl_alloc hx509_crl_free @@ -257,6 +258,7 @@ EXPORTS hx509_query_match_expr hx509_query_match_friendly_name hx509_query_match_issuer_serial + hx509_query_match_key_algorithm hx509_query_match_option hx509_query_statistic_file hx509_query_unparse_stats @@ -269,6 +271,8 @@ EXPORTS hx509_revoke_verify hx509_set_error_string hx509_set_error_stringv + hx509_signature_ed25519 + hx509_signature_ed448 hx509_signature_md5 hx509_signature_rsa hx509_signature_rsa_with_md5 diff --git a/lib/hx509/lock.c b/lib/hx509/lock.c index 7f767d236..ec49e4001 100644 --- a/lib/hx509/lock.c +++ b/lib/hx509/lock.c @@ -33,6 +33,198 @@ #include "hx_locl.h" +/* + * lib/hcrypto.ui.c code here + */ +#include +#ifdef HAVE_TERMIOS_H +#include +#endif + +#define UI_UTIL_FLAG_VERIFY 0x1 /* ask to verify password */ +#define UI_UTIL_FLAG_VERIFY_SILENT 0x2 /* silence on verify failure */ + +#ifdef HAVE_CONIO_H +#include +#endif + +static sig_atomic_t intr_flag; + +static void +intr(int sig) +{ + intr_flag++; +} + +#ifdef HAVE_CONIO_H + +/* + * Windows does console slightly different then then unix case. + */ + +static int +read_string(const char *preprompt, const char *prompt, + char *buf, size_t len, int echo) +{ + int of = 0; + int c; + char *p; + void (*oldsigintr)(int); + + printf("%s%s", preprompt, prompt); + fflush(stdout); + + oldsigintr = signal(SIGINT, intr); + + p = buf; + while(intr_flag == 0){ + c = ((echo)? _getche(): _getch()); + if(c == '\n' || c == '\r') + break; + if(of == 0) + *p++ = c; + of = (p == buf + len); + } + if(of) + p--; + *p = 0; + + if(echo == 0){ + printf("\n"); + } + + signal(SIGINT, oldsigintr); + + if(intr_flag) + return -2; + if(of) + return -1; + return 0; +} + +#else /* !HAVE_CONIO_H */ + +#ifndef NSIG +#define NSIG 47 +#endif + +static int +read_string(const char *preprompt, const char *prompt, + char *buf, size_t len, int echo) +{ + struct sigaction sigs[NSIG]; + int oksigs[NSIG]; + struct sigaction sa; + FILE *tty; + int ret = 0; + int of = 0; + int i; + int c; + char *p; + + struct termios t_new, t_old; + + memset(&oksigs, 0, sizeof(oksigs)); + + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = intr; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + for(i = 1; i < sizeof(sigs) / sizeof(sigs[0]); i++) + if (i != SIGALRM) + if (sigaction(i, &sa, &sigs[i]) == 0) + oksigs[i] = 1; + + if((tty = fopen("/dev/tty", "r")) != NULL) + rk_cloexec_file(tty); + else + tty = stdin; + + fprintf(stderr, "%s%s", preprompt, prompt); + fflush(stderr); + + if(echo == 0){ + tcgetattr(fileno(tty), &t_old); + memcpy(&t_new, &t_old, sizeof(t_new)); + t_new.c_lflag &= ~ECHO; + tcsetattr(fileno(tty), TCSANOW, &t_new); + } + intr_flag = 0; + p = buf; + while(intr_flag == 0){ + c = getc(tty); + if(c == EOF){ + if(!ferror(tty)) + ret = 1; + break; + } + if(c == '\n') + break; + if(of == 0) + *p++ = c; + of = (p == buf + len); + } + if(of) + p--; + *p = 0; + + if(echo == 0){ + fprintf(stderr, "\n"); + tcsetattr(fileno(tty), TCSANOW, &t_old); + } + + if(tty != stdin) + fclose(tty); + + for(i = 1; i < sizeof(sigs) / sizeof(sigs[0]); i++) + if (oksigs[i]) + sigaction(i, &sigs[i], NULL); + + if(ret) + return -3; + if(intr_flag) + return -2; + if(of) + return -1; + return 0; +} + +#endif /* HAVE_CONIO_H */ + +int +_hx509_UI_UTIL_read_pw_string(char *buf, int length, const char *prompt, int verify) +{ + int ret; + + ret = read_string("", prompt, buf, length, 0); + if (ret) + return ret; + + if (verify & UI_UTIL_FLAG_VERIFY) { + char *buf2; + buf2 = malloc(length); + if (buf2 == NULL) + return 1; + + ret = read_string("Verify password - ", prompt, buf2, length, 0); + if (ret) { + free(buf2); + return ret; + } + if (strcmp(buf2, buf) != 0) { + if (!(verify & UI_UTIL_FLAG_VERIFY_SILENT)) { + fprintf(stderr, "Verify failure\n"); + fflush(stderr); + } + ret = 1; + } + free(buf2); + } + return ret; +} + +/* lib/hcrypto/ui.c code over */ + /** * @page page_lock Locking and unlocking certificates and encrypted data. * @@ -187,10 +379,10 @@ static int default_prompter(void *data, const hx509_prompt *prompter) { if (hx509_prompt_hidden(prompter->type)) { - if(UI_UTIL_read_pw_string(prompter->reply.data, - prompter->reply.length, - prompter->prompt, - 0)) + if(_hx509_UI_UTIL_read_pw_string(prompter->reply.data, + prompter->reply.length, + prompter->prompt, + 0)) return 1; } else { char *s = prompter->reply.data; @@ -239,11 +431,47 @@ hx509_prompt_hidden(hx509_prompt_type type) } } +static char * +read_password_file(const char *fn) +{ + size_t n = 0; + char *s = NULL; + FILE *f; + int save_errno; + + if ((f = fopen(fn, "r")) == NULL) + return NULL; + + if (getline(&s, &n, f) > -1) { + char *nl = strchr(s, '\n'); + + if (nl) { + *nl = '\0'; + if (nl > s && nl[-1] == '\r') + nl[-1] = '\0'; + } + } + save_errno = errno; + (void) fclose(f); + errno = save_errno; + return s; +} + HX509_LIB_FUNCTION int HX509_LIB_CALL hx509_lock_command_string(hx509_lock lock, const char *string) { if (strncasecmp(string, "PASS:", 5) == 0) { hx509_lock_add_password(lock, string + 5); + } else if (strncasecmp(string, "FILE:", 5) == 0) { + char *pass = read_password_file(string + sizeof("FILE:") - 1); + + if (pass == NULL) { + warn("Could not read password from %s", string); + return errno; + } + hx509_lock_add_password(lock, pass); + memset(pass, 0, strlen(pass)); + free(pass); } else if (strcasecmp(string, "PROMPT") == 0) { hx509_lock_set_prompter(lock, default_prompter, NULL); } else diff --git a/lib/hx509/print.c b/lib/hx509/print.c index 3309913f3..ca84c20c6 100644 --- a/lib/hx509/print.c +++ b/lib/hx509/print.c @@ -1129,12 +1129,14 @@ hx509_validate_cert(hx509_context context, &c->signatureAlgorithm, &c->tbsCertificate._save, &c->signatureValue); - if (ret == 0) + if (ret == 0) { validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "Self-signed certificate was self-signed\n"); - else + } else { validate_print(ctx, HX509_VALIDATE_F_VALIDATE, "Self-signed certificate NOT really self-signed!\n"); + hx509_clear_error_string(context); + } } hx509_name_free(&subject); diff --git a/lib/hx509/ref/pkcs11.h b/lib/hx509/ref/pkcs11.h index a294c5e94..3d6b2bd55 100644 --- a/lib/hx509/ref/pkcs11.h +++ b/lib/hx509/ref/pkcs11.h @@ -476,6 +476,7 @@ typedef unsigned long ck_attribute_type_t; #define CKA_EXPONENT_1 (0x126) #define CKA_EXPONENT_2 (0x127) #define CKA_COEFFICIENT (0x128) +#define CKA_PUBLIC_KEY_INFO (0x129) #define CKA_PRIME (0x130) #define CKA_SUBPRIME (0x131) #define CKA_BASE (0x132) @@ -491,6 +492,7 @@ typedef unsigned long ck_attribute_type_t; #define CKA_KEY_GEN_MECHANISM (0x166) #define CKA_MODIFIABLE (0x170) #define CKA_COPYABLE (0x171) +#define CKA_DESTROYABLE (0x172) #define CKA_ECDSA_PARAMS (0x180) #define CKA_EC_PARAMS (0x180) #define CKA_EC_POINT (0x181) diff --git a/lib/hx509/req.c b/lib/hx509/req.c index 5ac1ea7a3..e7e94551b 100644 --- a/lib/hx509/req.c +++ b/lib/hx509/req.c @@ -775,11 +775,30 @@ hx509_request_to_pkcs10(hx509_context context, /* Self-sign CSR body */ if (ret == 0) { - ret = _hx509_create_signature_bitstring(context, signer, - _hx509_crypto_default_sig_alg, - &data, - &r.signatureAlgorithm, - &r.signature); + const AlgorithmIdentifier *sigalg; + heim_oid key_oid; + + /* + * Select signature algorithm based on the key type. + * For EdDSA keys, the signature OID is the same as the key OID. + * For RSA keys, use the default (RSA with SHA-256). + */ + ret = _hx509_private_key_oid(context, signer, &key_oid); + if (ret == 0) { + if (der_heim_oid_cmp(&key_oid, ASN1_OID_ID_ED25519) == 0) + sigalg = hx509_signature_ed25519(); + else if (der_heim_oid_cmp(&key_oid, ASN1_OID_ID_ED448) == 0) + sigalg = hx509_signature_ed448(); + else + sigalg = _hx509_crypto_default_sig_alg; + der_free_oid(&key_oid); + + ret = _hx509_create_signature_bitstring(context, signer, + sigalg, + &data, + &r.signatureAlgorithm, + &r.signature); + } } free(data.data); diff --git a/lib/hx509/revoke.c b/lib/hx509/revoke.c index ade0bd342..98dc56ad6 100644 --- a/lib/hx509/revoke.c +++ b/lib/hx509/revoke.c @@ -755,6 +755,7 @@ hx509_revoke_verify(hx509_context context, ret = _hx509_verify_signature(context, NULL, &ocsp->ocsp.tbsResponseData.responses.val[i].certID.hashAlgorithm, + NULL, &c->tbsCertificate.issuer._save, &ocsp->ocsp.tbsResponseData.responses.val[i].certID.issuerNameHash); if (ret != 0) @@ -766,6 +767,7 @@ hx509_revoke_verify(hx509_context context, ret = _hx509_verify_signature(context, NULL, &ocsp->ocsp.tbsResponseData.responses.val[j].certID.hashAlgorithm, + NULL, &os, &ocsp->ocsp.tbsResponseData.responses.val[j].certID.issuerKeyHash); if (ret != 0) @@ -942,6 +944,7 @@ add_to_req(hx509_context context, void *ptr, hx509_cert cert) ret = _hx509_create_signature(context, NULL, &one->reqCert.hashAlgorithm, + NULL, &c->tbsCertificate.issuer._save, NULL, &one->reqCert.issuerNameHash); @@ -955,6 +958,7 @@ add_to_req(hx509_context context, void *ptr, hx509_cert cert) ret = _hx509_create_signature(context, NULL, &one->reqCert.hashAlgorithm, + NULL, &os, NULL, &one->reqCert.issuerKeyHash); @@ -1323,6 +1327,7 @@ hx509_ocsp_verify(hx509_context context, ret = _hx509_verify_signature(context, NULL, &basic.tbsResponseData.responses.val[i].certID.hashAlgorithm, + NULL, &c->tbsCertificate.issuer._save, &basic.tbsResponseData.responses.val[i].certID.issuerNameHash); if (ret != 0) diff --git a/lib/hx509/softp11.c b/lib/hx509/softp11.c index 3ad830e37..4230b4e4d 100644 --- a/lib/hx509/softp11.c +++ b/lib/hx509/softp11.c @@ -35,6 +35,7 @@ #include "hx_locl.h" #include "ref/pkcs11.h" +#include #define OBJECT_ID_MASK 0xfff #define HANDLE_OBJECT_ID(h) ((h) & OBJECT_ID_MASK) @@ -367,51 +368,72 @@ static CK_RV add_pubkey_info(hx509_context hxctx, struct st_object *o, CK_KEY_TYPE key_type, hx509_cert cert) { - BIGNUM *num; - CK_BYTE *modulus = NULL; - size_t modulus_len = 0; - CK_ULONG modulus_bits = 0; - CK_BYTE *exponent = NULL; - size_t exponent_len = 0; + SubjectPublicKeyInfo spki; + size_t spki_len; + void *spki_data; + int ret; - if (key_type != CKK_RSA) - return CKR_OK; - if (_hx509_cert_private_key(cert) == NULL) - return CKR_OK; + /* Add CKA_PUBLIC_KEY_INFO (PKCS#11 3.0) for all key types */ + ret = hx509_cert_get_SPKI(hxctx, cert, &spki); + if (ret == 0) { + ASN1_MALLOC_ENCODE(SubjectPublicKeyInfo, spki_data, spki_len, + &spki, &spki_len, ret); + if (ret == 0 && spki_data) { + add_object_attribute(o, 0, CKA_PUBLIC_KEY_INFO, spki_data, spki_len); + free(spki_data); + } + free_SubjectPublicKeyInfo(&spki); + } - num = _hx509_private_key_get_internal(context, - _hx509_cert_private_key(cert), - "rsa-modulus"); - if (num == NULL) - return CKR_GENERAL_ERROR; - modulus_bits = BN_num_bits(num); + /* For RSA keys, extract modulus and exponent from certificate's public key */ + if (key_type == CKK_RSA) { + Certificate *c = _hx509_get_cert(cert); + EVP_PKEY *pkey = NULL; + const unsigned char *p; + BIGNUM *n = NULL, *e = NULL; + CK_BYTE *modulus = NULL; + CK_BYTE *exponent = NULL; + size_t modulus_len, exponent_len; + CK_ULONG modulus_bits; - modulus_len = BN_num_bytes(num); - modulus = malloc(modulus_len); - BN_bn2bin(num, modulus); - BN_free(num); + /* Decode public key from certificate SPKI */ + p = c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data; + pkey = d2i_PublicKey(EVP_PKEY_RSA, NULL, &p, + c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.length / 8); + if (pkey == NULL) { + st_logf("add_pubkey_info: failed to decode RSA public key\n"); + return CKR_OK; /* Not fatal, just skip RSA attrs */ + } - add_object_attribute(o, 0, CKA_MODULUS, modulus, modulus_len); - add_object_attribute(o, 0, CKA_MODULUS_BITS, - &modulus_bits, sizeof(modulus_bits)); + /* Get modulus and exponent using OpenSSL 3.0 API */ + if (EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_N, &n) && + EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_E, &e)) { - free(modulus); + modulus_bits = BN_num_bits(n); + modulus_len = BN_num_bytes(n); + modulus = malloc(modulus_len); + if (modulus) { + BN_bn2bin(n, modulus); + add_object_attribute(o, 0, CKA_MODULUS, modulus, modulus_len); + add_object_attribute(o, 0, CKA_MODULUS_BITS, &modulus_bits, sizeof(modulus_bits)); + free(modulus); + } - num = _hx509_private_key_get_internal(context, - _hx509_cert_private_key(cert), - "rsa-exponent"); - if (num == NULL) - return CKR_GENERAL_ERROR; + exponent_len = BN_num_bytes(e); + exponent = malloc(exponent_len); + if (exponent) { + BN_bn2bin(e, exponent); + add_object_attribute(o, 0, CKA_PUBLIC_EXPONENT, exponent, exponent_len); + free(exponent); + } - exponent_len = BN_num_bytes(num); - exponent = malloc(exponent_len); - BN_bn2bin(num, exponent); - BN_free(num); + st_logf("add_pubkey_info: added RSA modulus (%zu bytes) and exponent\n", modulus_len); + } - add_object_attribute(o, 0, CKA_PUBLIC_EXPONENT, - exponent, exponent_len); - - free(exponent); + BN_free(n); + BN_free(e); + EVP_PKEY_free(pkey); + } return CKR_OK; } @@ -538,6 +560,8 @@ add_cert(hx509_context hxctx, void *ctx, hx509_cert cert) add_object_attribute(o, 0, CKA_VERIFY_RECOVER, &bool_false, sizeof(bool_false)); add_object_attribute(o, 0, CKA_WRAP, &bool_true, sizeof(bool_true)); add_object_attribute(o, 0, CKA_TRUSTED, &bool_true, sizeof(bool_true)); + add_object_attribute(o, 0, CKA_COPYABLE, &bool_false, sizeof(bool_false)); + add_object_attribute(o, 0, CKA_DESTROYABLE, &bool_false, sizeof(bool_false)); add_pubkey_info(hxctx, o, key_type, cert); @@ -583,6 +607,10 @@ add_cert(hx509_context hxctx, void *ctx, hx509_cert cert) add_object_attribute(o, 0, CKA_UNWRAP, &bool_true, sizeof(bool_true)); add_object_attribute(o, 0, CKA_EXTRACTABLE, &bool_true, sizeof(bool_true)); add_object_attribute(o, 0, CKA_NEVER_EXTRACTABLE, &bool_false, sizeof(bool_false)); + add_object_attribute(o, 0, CKA_COPYABLE, &bool_false, sizeof(bool_false)); + add_object_attribute(o, 0, CKA_DESTROYABLE, &bool_false, sizeof(bool_false)); + add_object_attribute(o, 0, CKA_ALWAYS_SENSITIVE, &bool_false, sizeof(bool_false)); + add_object_attribute(o, 0, CKA_ALWAYS_AUTHENTICATE, &bool_false, sizeof(bool_false)); add_pubkey_info(hxctx, o, key_type, cert); } @@ -1468,7 +1496,7 @@ C_SignInit(CK_SESSION_HANDLE hSession, CK_RV ret; INIT_CONTEXT(); - st_logf("SignInit\n"); + st_logf("SignInit: mechanism 0x%lx\n", (unsigned long)pMechanism->mechanism); VERIFY_SESSION_HANDLE(hSession, &state); ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]), @@ -1494,17 +1522,11 @@ C_Sign(CK_SESSION_HANDLE hSession, struct session_state *state; struct st_object *o; CK_RV ret; - int hret; - const AlgorithmIdentifier *alg; - heim_octet_string sig, data; INIT_CONTEXT(); - st_logf("Sign\n"); + st_logf("Sign: dataLen=%lu\n", (unsigned long)ulDataLen); VERIFY_SESSION_HANDLE(hSession, &state); - sig.data = NULL; - sig.length = 0; - if (state->sign_object == -1) return CKR_ARGUMENTS_BAD; @@ -1528,38 +1550,67 @@ C_Sign(CK_SESSION_HANDLE hSession, } switch(state->sign_mechanism->mechanism) { - case CKM_RSA_PKCS: - alg = hx509_signature_rsa_pkcs1_x509(); - break; + case CKM_RSA_PKCS: { + /* + * CKM_RSA_PKCS: The input is already a DigestInfo (or any data to be + * signed raw). We need raw RSA PKCS#1 v1.5 signing, not digest+sign. + */ + hx509_private_key privkey = _hx509_cert_private_key(o->cert); + EVP_PKEY *pkey = privkey->private_key.pkey; + EVP_PKEY_CTX *pctx; + size_t siglen; + + pctx = EVP_PKEY_CTX_new(pkey, NULL); + if (pctx == NULL) { + st_logf("Sign: EVP_PKEY_CTX_new failed\n"); + ret = CKR_DEVICE_ERROR; + goto out; + } + + if (EVP_PKEY_sign_init(pctx) <= 0) { + st_logf("Sign: EVP_PKEY_sign_init failed\n"); + EVP_PKEY_CTX_free(pctx); + ret = CKR_DEVICE_ERROR; + goto out; + } + + if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PADDING) <= 0) { + st_logf("Sign: EVP_PKEY_CTX_set_rsa_padding failed\n"); + EVP_PKEY_CTX_free(pctx); + ret = CKR_DEVICE_ERROR; + goto out; + } + + /* First call to get signature length */ + siglen = 0; + if (EVP_PKEY_sign(pctx, NULL, &siglen, pData, ulDataLen) <= 0) { + st_logf("Sign: EVP_PKEY_sign (get length) failed\n"); + EVP_PKEY_CTX_free(pctx); + ret = CKR_DEVICE_ERROR; + goto out; + } + + *pulSignatureLen = siglen; + st_logf("Sign: sigLen=%lu\n", (unsigned long)siglen); + + if (pSignature != NULL_PTR) { + if (EVP_PKEY_sign(pctx, pSignature, &siglen, pData, ulDataLen) <= 0) { + st_logf("Sign: EVP_PKEY_sign failed\n"); + EVP_PKEY_CTX_free(pctx); + ret = CKR_DEVICE_ERROR; + goto out; + } + } + EVP_PKEY_CTX_free(pctx); + ret = CKR_OK; + goto out; + } default: ret = CKR_FUNCTION_NOT_SUPPORTED; goto out; } - data.data = pData; - data.length = ulDataLen; - - hret = _hx509_create_signature(context, - _hx509_cert_private_key(o->cert), - alg, - &data, - NULL, - &sig); - if (hret) { - ret = CKR_DEVICE_ERROR; - goto out; - } - *pulSignatureLen = sig.length; - - if (pSignature != NULL_PTR) - memcpy(pSignature, sig.data, sig.length); - - ret = CKR_OK; out: - if (sig.data) { - memset(sig.data, 0, sig.length); - der_free_octet_string(&sig); - } return ret; } @@ -1657,6 +1708,7 @@ C_Verify(CK_SESSION_HANDLE hSession, hret = _hx509_verify_signature(context, o->cert, alg, + NULL, &data, &sig); if (hret) { diff --git a/lib/hx509/test_ca.in b/lib/hx509/test_ca.in index 9346f61a6..bff83916d 100644 --- a/lib/hx509/test_ca.in +++ b/lib/hx509/test_ca.in @@ -470,4 +470,188 @@ ${hxtool} verify --missing-revoke \ cert:FILE:cert-ee.pem \ anchor:FILE:cert-ca.pem > /dev/null || exit 1 +echo "+++++++++++ test Ed25519" + +echo "issue self-signed Ed25519 ca cert" +${hxtool} issue-certificate \ + --self-signed \ + --issue-ca \ + --generate-key=ed25519 \ + --signature-algorithm=ed25519 \ + --subject="cn=ed25519-ca" \ + --certificate="FILE:cert-ed25519-ca.pem" || exit 1 +${hxtool} print --content FILE:cert-ed25519-ca.pem || exit 1 + +echo "verify Ed25519 CA cert with openssl" +openssl x509 -in cert-ed25519-ca.pem -noout -text > /dev/null || exit 1 +# Check signature algorithm is ED25519 +openssl x509 -in cert-ed25519-ca.pem -noout -text | grep -q "Signature Algorithm: ED25519" || exit 1 +# Check public key algorithm is ED25519 +openssl x509 -in cert-ed25519-ca.pem -noout -text | grep -q "Public Key Algorithm: ED25519" || exit 1 + +echo "issue Ed25519 ee cert" +${hxtool} issue-certificate \ + --ca-certificate=FILE:cert-ed25519-ca.pem \ + --generate-key=ed25519 \ + --signature-algorithm=ed25519 \ + --subject="cn=ed25519-ee" \ + --certificate="FILE:cert-ed25519-ee.pem" || exit 1 +${hxtool} print --content FILE:cert-ed25519-ee.pem || exit 1 + +echo "verify Ed25519 EE cert with openssl" +openssl x509 -in cert-ed25519-ee.pem -noout -text > /dev/null || exit 1 +# Check signature algorithm is ED25519 +openssl x509 -in cert-ed25519-ee.pem -noout -text | grep -q "Signature Algorithm: ED25519" || exit 1 +# Check public key algorithm is ED25519 +openssl x509 -in cert-ed25519-ee.pem -noout -text | grep -q "Public Key Algorithm: ED25519" || exit 1 + +echo "verify Ed25519 chain with openssl" +# Extract just the certificate (skip private key) +openssl x509 -in cert-ed25519-ca.pem -out cert-ed25519-ca-only.pem || exit 1 +openssl x509 -in cert-ed25519-ee.pem -out cert-ed25519-ee-only.pem || exit 1 +openssl verify -CAfile cert-ed25519-ca-only.pem cert-ed25519-ee-only.pem || exit 1 + +echo "verify Ed25519 certificate" +${hxtool} verify --missing-revoke \ + cert:FILE:cert-ed25519-ee.pem \ + anchor:FILE:cert-ed25519-ca.pem > /dev/null || exit 1 + +echo "sign CMS signature (Ed25519)" +${hxtool} cms-create-sd \ + --certificate=FILE:cert-ed25519-ee.pem \ + "$srcdir/test_name.c" \ + sd-ed25519.data > /dev/null || exit 1 + +echo "verify CMS signature (Ed25519)" +${hxtool} cms-verify-sd \ + --missing-revoke \ + --anchors=FILE:cert-ed25519-ca.pem \ + sd-ed25519.data sd-ed25519.data.out > /dev/null || exit 1 +cmp "$srcdir/test_name.c" sd-ed25519.data.out || exit 1 + +echo "+++++++++++ test Ed448" + +echo "issue self-signed Ed448 ca cert" +${hxtool} issue-certificate \ + --self-signed \ + --issue-ca \ + --generate-key=ed448 \ + --signature-algorithm=ed448 \ + --subject="cn=ed448-ca" \ + --certificate="FILE:cert-ed448-ca.pem" || exit 1 +${hxtool} print --content FILE:cert-ed448-ca.pem || exit 1 + +echo "verify Ed448 CA cert with openssl" +openssl x509 -in cert-ed448-ca.pem -noout -text > /dev/null || exit 1 +# Check signature algorithm is ED448 +openssl x509 -in cert-ed448-ca.pem -noout -text | grep -q "Signature Algorithm: ED448" || exit 1 +# Check public key algorithm is ED448 +openssl x509 -in cert-ed448-ca.pem -noout -text | grep -q "Public Key Algorithm: ED448" || exit 1 + +echo "issue Ed448 ee cert" +${hxtool} issue-certificate \ + --ca-certificate=FILE:cert-ed448-ca.pem \ + --generate-key=ed448 \ + --signature-algorithm=ed448 \ + --subject="cn=ed448-ee" \ + --certificate="FILE:cert-ed448-ee.pem" || exit 1 +${hxtool} print --content FILE:cert-ed448-ee.pem || exit 1 + +echo "verify Ed448 EE cert with openssl" +openssl x509 -in cert-ed448-ee.pem -noout -text > /dev/null || exit 1 +# Check signature algorithm is ED448 +openssl x509 -in cert-ed448-ee.pem -noout -text | grep -q "Signature Algorithm: ED448" || exit 1 +# Check public key algorithm is ED448 +openssl x509 -in cert-ed448-ee.pem -noout -text | grep -q "Public Key Algorithm: ED448" || exit 1 + +echo "verify Ed448 chain with openssl" +# Extract just the certificate (skip private key) +openssl x509 -in cert-ed448-ca.pem -out cert-ed448-ca-only.pem || exit 1 +openssl x509 -in cert-ed448-ee.pem -out cert-ed448-ee-only.pem || exit 1 +openssl verify -CAfile cert-ed448-ca-only.pem cert-ed448-ee-only.pem || exit 1 + +echo "verify Ed448 certificate" +${hxtool} verify --missing-revoke \ + cert:FILE:cert-ed448-ee.pem \ + anchor:FILE:cert-ed448-ca.pem > /dev/null || exit 1 + +echo "sign CMS signature (Ed448)" +${hxtool} cms-create-sd \ + --certificate=FILE:cert-ed448-ee.pem \ + "$srcdir/test_name.c" \ + sd-ed448.data > /dev/null || exit 1 + +echo "verify CMS signature (Ed448)" +${hxtool} cms-verify-sd \ + --missing-revoke \ + --anchors=FILE:cert-ed448-ca.pem \ + sd-ed448.data sd-ed448.data.out > /dev/null || exit 1 +cmp "$srcdir/test_name.c" sd-ed448.data.out || exit 1 + +echo "+++++++++++ test OpenSSL-generated Ed25519 certs" + +echo "generate Ed25519 CA key with openssl" +openssl genpkey -algorithm Ed25519 -out ossl-ed25519-ca.key || exit 1 + +echo "generate self-signed Ed25519 CA cert with openssl" +openssl req -new -x509 -key ossl-ed25519-ca.key -out ossl-ed25519-ca.pem \ + -days 365 -subj "/CN=OpenSSL Ed25519 CA" \ + -addext "basicConstraints=critical,CA:TRUE" \ + -addext "keyUsage=critical,keyCertSign,cRLSign" || exit 1 + +echo "generate Ed25519 EE key with openssl" +openssl genpkey -algorithm Ed25519 -out ossl-ed25519-ee.key || exit 1 + +echo "generate Ed25519 EE CSR with openssl" +openssl req -new -key ossl-ed25519-ee.key -out ossl-ed25519-ee.csr \ + -subj "/CN=OpenSSL Ed25519 EE" || exit 1 + +echo "sign Ed25519 EE cert with openssl CA" +openssl x509 -req -in ossl-ed25519-ee.csr -CA ossl-ed25519-ca.pem \ + -CAkey ossl-ed25519-ca.key -CAcreateserial \ + -out ossl-ed25519-ee.pem -days 365 || exit 1 + +echo "verify OpenSSL Ed25519 CA cert with hxtool" +${hxtool} verify --missing-revoke \ + cert:FILE:ossl-ed25519-ca.pem \ + anchor:FILE:ossl-ed25519-ca.pem > /dev/null || exit 1 + +echo "verify OpenSSL Ed25519 EE cert with hxtool" +${hxtool} verify --missing-revoke \ + cert:FILE:ossl-ed25519-ee.pem \ + anchor:FILE:ossl-ed25519-ca.pem > /dev/null || exit 1 + +echo "+++++++++++ test OpenSSL-generated Ed448 certs" + +echo "generate Ed448 CA key with openssl" +openssl genpkey -algorithm Ed448 -out ossl-ed448-ca.key || exit 1 + +echo "generate self-signed Ed448 CA cert with openssl" +openssl req -new -x509 -key ossl-ed448-ca.key -out ossl-ed448-ca.pem \ + -days 365 -subj "/CN=OpenSSL Ed448 CA" \ + -addext "basicConstraints=critical,CA:TRUE" \ + -addext "keyUsage=critical,keyCertSign,cRLSign" || exit 1 + +echo "generate Ed448 EE key with openssl" +openssl genpkey -algorithm Ed448 -out ossl-ed448-ee.key || exit 1 + +echo "generate Ed448 EE CSR with openssl" +openssl req -new -key ossl-ed448-ee.key -out ossl-ed448-ee.csr \ + -subj "/CN=OpenSSL Ed448 EE" || exit 1 + +echo "sign Ed448 EE cert with openssl CA" +openssl x509 -req -in ossl-ed448-ee.csr -CA ossl-ed448-ca.pem \ + -CAkey ossl-ed448-ca.key -CAcreateserial \ + -out ossl-ed448-ee.pem -days 365 || exit 1 + +echo "verify OpenSSL Ed448 CA cert with hxtool" +${hxtool} verify --missing-revoke \ + cert:FILE:ossl-ed448-ca.pem \ + anchor:FILE:ossl-ed448-ca.pem > /dev/null || exit 1 + +echo "verify OpenSSL Ed448 EE cert with hxtool" +${hxtool} verify --missing-revoke \ + cert:FILE:ossl-ed448-ee.pem \ + anchor:FILE:ossl-ed448-ca.pem > /dev/null || exit 1 + exit 0 diff --git a/lib/hx509/test_cms.in b/lib/hx509/test_cms.in index b1fb4ec4e..47984a61d 100644 --- a/lib/hx509/test_cms.in +++ b/lib/hx509/test_cms.in @@ -45,134 +45,134 @@ echo "create signed data (ec)" ${hxtool} cms-create-sd \ --certificate=FILE:$srcdir/data/secp256r2TestClient.pem \ "$srcdir/test_chain.in" \ - sd.data > /dev/null || exit 1 + sd.data > /dev/null || { echo Fail at $LINENO; exit 1; } echo "verify signed data (ec)" ${hxtool} cms-verify-sd \ --missing-revoke \ --anchors=FILE:$srcdir/data/secp256r1TestCA.cert.pem \ - sd.data sd.data.out > /dev/null || exit 1 -cmp "$srcdir/test_chain.in" sd.data.out || exit 1 - + sd.data sd.data.out > /dev/null || { echo Fail at $LINENO; exit 1; } +cmp "$srcdir/test_chain.in" sd.data.out || { echo Fail at $LINENO; exit 1; } + echo "create signed data" ${hxtool} cms-create-sd \ --certificate=FILE:$srcdir/data/test.crt,$srcdir/data/test.key \ "$srcdir/test_chain.in" \ - sd.data > /dev/null || exit 1 + sd.data > /dev/null || { echo Fail at $LINENO; exit 1; } echo "verify signed data" ${hxtool} cms-verify-sd \ --missing-revoke \ --anchors=FILE:$srcdir/data/ca.crt \ - sd.data sd.data.out > /dev/null || exit 1 -cmp "$srcdir/test_chain.in" sd.data.out || exit 1 + sd.data sd.data.out > /dev/null || { echo Fail at $LINENO; exit 1; } +cmp "$srcdir/test_chain.in" sd.data.out || { echo Fail at $LINENO; exit 1; } echo "create signed data (no signer)" ${hxtool} cms-create-sd \ --no-signer \ --certificate=FILE:$srcdir/data/test.crt,$srcdir/data/test.key \ "$srcdir/test_chain.in" \ - sd.data > /dev/null || exit 1 + sd.data > /dev/null || { echo Fail at $LINENO; exit 1; } echo "verify signed data (no signer)" ${hxtool} cms-verify-sd \ --missing-revoke \ --no-signer-allowed \ --anchors=FILE:$srcdir/data/ca.crt \ - sd.data sd.data.out > signer.tmp || exit 1 -cmp "$srcdir/test_chain.in" sd.data.out || exit 1 -grep "unsigned" signer.tmp > /dev/null || exit 1 + sd.data sd.data.out > signer.tmp || { echo Fail at $LINENO; exit 1; } +cmp "$srcdir/test_chain.in" sd.data.out || { echo Fail at $LINENO; exit 1; } +grep "unsigned" signer.tmp > /dev/null || { echo Fail at $LINENO; exit 1; } echo "verify signed data (no signer) (test failure)" ${hxtool} cms-verify-sd \ --missing-revoke \ --anchors=FILE:$srcdir/data/ca.crt \ sd.data sd.data.out 2> signer.tmp && exit 1 -grep "No signers were found" signer.tmp > /dev/null || exit 1 +grep "No signers were found" signer.tmp > /dev/null || { echo Fail at $LINENO; exit 1; } echo "create signed data (id-by-name)" ${hxtool} cms-create-sd \ --certificate=FILE:$srcdir/data/test.crt,$srcdir/data/test.key \ --id-by-name \ "$srcdir/test_chain.in" \ - sd.data > /dev/null || exit 1 + sd.data > /dev/null || { echo Fail at $LINENO; exit 1; } echo "verify signed data" ${hxtool} cms-verify-sd \ --missing-revoke \ --anchors=FILE:$srcdir/data/ca.crt \ - sd.data sd.data.out > /dev/null || exit 1 -cmp "$srcdir/test_chain.in" sd.data.out || exit 1 + sd.data sd.data.out > /dev/null || { echo Fail at $LINENO; exit 1; } +cmp "$srcdir/test_chain.in" sd.data.out || { echo Fail at $LINENO; exit 1; } echo "verify signed data (EE cert as anchor)" ${hxtool} cms-verify-sd \ --missing-revoke \ --anchors=FILE:$srcdir/data/test.crt \ - sd.data sd.data.out > /dev/null || exit 1 -cmp "$srcdir/test_chain.in" sd.data.out || exit 1 + sd.data sd.data.out > /dev/null || { echo Fail at $LINENO; exit 1; } +cmp "$srcdir/test_chain.in" sd.data.out || { echo Fail at $LINENO; exit 1; } echo "create signed data (password)" ${hxtool} cms-create-sd \ --pass=PASS:foobar \ --certificate=FILE:$srcdir/data/test.crt,$srcdir/data/test-pw.key \ "$srcdir/test_chain.in" \ - sd.data > /dev/null || exit 1 + sd.data > /dev/null || { echo Fail at $LINENO; exit 1; } echo "verify signed data" ${hxtool} cms-verify-sd \ --missing-revoke \ --anchors=FILE:$srcdir/data/ca.crt \ - sd.data sd.data.out > /dev/null || exit 1 -cmp "$srcdir/test_chain.in" sd.data.out || exit 1 + sd.data sd.data.out > /dev/null || { echo Fail at $LINENO; exit 1; } +cmp "$srcdir/test_chain.in" sd.data.out || { echo Fail at $LINENO; exit 1; } echo "create signed data (combined)" ${hxtool} cms-create-sd \ --certificate=FILE:$srcdir/data/test.combined.crt \ "$srcdir/test_chain.in" \ - sd.data > /dev/null || exit 1 + sd.data > /dev/null || { echo Fail at $LINENO; exit 1; } echo "verify signed data" ${hxtool} cms-verify-sd \ --missing-revoke \ --anchors=FILE:$srcdir/data/ca.crt \ - sd.data sd.data.out > /dev/null || exit 1 -cmp "$srcdir/test_chain.in" sd.data.out || exit 1 + sd.data sd.data.out > /dev/null || { echo Fail at $LINENO; exit 1; } +cmp "$srcdir/test_chain.in" sd.data.out || { echo Fail at $LINENO; exit 1; } echo "create signed data (content info)" ${hxtool} cms-create-sd \ --certificate=FILE:$srcdir/data/test.crt,$srcdir/data/test.key \ --content-info \ "$srcdir/test_chain.in" \ - sd.data > /dev/null || exit 1 + sd.data > /dev/null || { echo Fail at $LINENO; exit 1; } echo "verify signed data (content info)" ${hxtool} cms-verify-sd \ --missing-revoke \ --anchors=FILE:$srcdir/data/ca.crt \ --content-info \ - sd.data sd.data.out > /dev/null || exit 1 -cmp "$srcdir/test_chain.in" sd.data.out || exit 1 + sd.data sd.data.out > /dev/null || { echo Fail at $LINENO; exit 1; } +cmp "$srcdir/test_chain.in" sd.data.out || { echo Fail at $LINENO; exit 1; } echo "create signed data (content type)" ${hxtool} cms-create-sd \ --certificate=FILE:$srcdir/data/test.crt,$srcdir/data/test.key \ --content-type=1.1.1.1 \ "$srcdir/test_chain.in" \ - sd.data > /dev/null || exit 1 + sd.data > /dev/null || { echo Fail at $LINENO; exit 1; } echo "verify signed data (content type)" ${hxtool} cms-verify-sd \ --missing-revoke \ --anchors=FILE:$srcdir/data/ca.crt \ - sd.data sd.data.out > /dev/null || exit 1 -cmp "$srcdir/test_chain.in" sd.data.out || exit 1 + sd.data sd.data.out > /dev/null || { echo Fail at $LINENO; exit 1; } +cmp "$srcdir/test_chain.in" sd.data.out || { echo Fail at $LINENO; exit 1; } echo "create signed data (pem)" ${hxtool} cms-create-sd \ --certificate=FILE:$srcdir/data/test.crt,$srcdir/data/test.key \ --pem \ "$srcdir/test_chain.in" \ - sd.data > /dev/null || exit 1 + sd.data > /dev/null || { echo Fail at $LINENO; exit 1; } echo "verify signed data (pem)" ${hxtool} cms-verify-sd \ @@ -180,7 +180,7 @@ ${hxtool} cms-verify-sd \ --anchors=FILE:$srcdir/data/ca.crt \ --pem \ sd.data sd.data.out > /dev/null -cmp "$srcdir/test_chain.in" sd.data.out || exit 1 +cmp "$srcdir/test_chain.in" sd.data.out || { echo Fail at $LINENO; exit 1; } echo "create signed data (pem, detached)" ${hxtool} cms-create-sd \ @@ -188,7 +188,7 @@ ${hxtool} cms-create-sd \ --detached-signature \ --pem \ "$srcdir/test_chain.in" \ - sd.data > /dev/null || exit 1 + sd.data > /dev/null || { echo Fail at $LINENO; exit 1; } echo "verify signed data (pem, detached)" ${hxtool} cms-verify-sd \ @@ -197,7 +197,7 @@ ${hxtool} cms-verify-sd \ --pem \ --signed-content="$srcdir/test_chain.in" \ sd.data sd.data.out > /dev/null -cmp "$srcdir/test_chain.in" sd.data.out || exit 1 +cmp "$srcdir/test_chain.in" sd.data.out || { echo Fail at $LINENO; exit 1; } echo "create signed data (p12)" ${hxtool} cms-create-sd \ @@ -205,23 +205,23 @@ ${hxtool} cms-create-sd \ --certificate=PKCS12:$srcdir/data/test.p12 \ --signer=friendlyname-test \ "$srcdir/test_chain.in" \ - sd.data > /dev/null || exit 1 + sd.data > /dev/null || { echo Fail at $LINENO; exit 1; } echo "verify signed data" ${hxtool} cms-verify-sd \ --missing-revoke \ --anchors=FILE:$srcdir/data/ca.crt \ --content-info \ - "$srcdir/data/test-signed-data" sd.data.out > /dev/null || exit 1 -cmp "$srcdir/data/static-file" sd.data.out || exit 1 + "$srcdir/data/test-signed-data" sd.data.out > /dev/null || { echo Fail at $LINENO; exit 1; } +cmp "$srcdir/data/static-file" sd.data.out || { echo Fail at $LINENO; exit 1; } echo "verify signed data (no attr)" ${hxtool} cms-verify-sd \ --missing-revoke \ --anchors=FILE:$srcdir/data/ca.crt \ --content-info \ - "$srcdir/data/test-signed-data-noattr" sd.data.out > /dev/null || exit 1 -cmp "$srcdir/data/static-file" sd.data.out || exit 1 + "$srcdir/data/test-signed-data-noattr" sd.data.out > /dev/null || { echo Fail at $LINENO; exit 1; } +cmp "$srcdir/data/static-file" sd.data.out || { echo Fail at $LINENO; exit 1; } echo "verify failure signed data (no attr, no certs)" ${hxtool} cms-verify-sd \ @@ -238,39 +238,39 @@ ${hxtool} cms-verify-sd \ --certificate=FILE:$srcdir/data/test.crt \ --content-info \ "$srcdir/data/test-signed-data-noattr-nocerts" \ - sd.data.out > /dev/null || exit 1 -cmp "$srcdir/data/static-file" sd.data.out || exit 1 + sd.data.out > /dev/null || { echo Fail at $LINENO; exit 1; } +cmp "$srcdir/data/static-file" sd.data.out || { echo Fail at $LINENO; exit 1; } echo "verify signed data - sha1" ${hxtool} cms-verify-sd \ --missing-revoke \ --anchors=FILE:$srcdir/data/ca.crt \ --content-info \ - "$srcdir/data/test-signed-sha-1" sd.data.out > /dev/null || exit 1 -cmp "$srcdir/data/static-file" sd.data.out || exit 1 + "$srcdir/data/test-signed-sha-1" sd.data.out > /dev/null || { echo Fail at $LINENO; exit 1; } +cmp "$srcdir/data/static-file" sd.data.out || { echo Fail at $LINENO; exit 1; } echo "verify signed data - sha256" ${hxtool} cms-verify-sd \ --missing-revoke \ --anchors=FILE:$srcdir/data/ca.crt \ --content-info \ - "$srcdir/data/test-signed-sha-256" sd.data.out > /dev/null || exit 1 -cmp "$srcdir/data/static-file" sd.data.out || exit 1 + "$srcdir/data/test-signed-sha-256" sd.data.out > /dev/null || { echo Fail at $LINENO; exit 1; } +cmp "$srcdir/data/static-file" sd.data.out || { echo Fail at $LINENO; exit 1; } #echo "verify signed data - sha512" #${hxtool} cms-verify-sd \ # --missing-revoke \ # --anchors=FILE:$srcdir/data/ca.crt \ # --content-info \ -# "$srcdir/data/test-signed-sha-512" sd.data.out > /dev/null || exit 1 -#cmp "$srcdir/data/static-file" sd.data.out || exit 1 +# "$srcdir/data/test-signed-sha-512" sd.data.out > /dev/null || { echo Fail at $LINENO; exit 1; } +#cmp "$srcdir/data/static-file" sd.data.out || { echo Fail at $LINENO; exit 1; } echo "create signed data (subcert, no certs)" ${hxtool} cms-create-sd \ --certificate=FILE:$srcdir/data/sub-cert.crt,$srcdir/data/sub-cert.key \ "$srcdir/test_chain.in" \ - sd.data > /dev/null || exit 1 + sd.data > /dev/null || { echo Fail at $LINENO; exit 1; } echo "verify failure signed data" ${hxtool} cms-verify-sd \ @@ -283,8 +283,8 @@ ${hxtool} cms-verify-sd \ --missing-revoke \ --certificate=FILE:$srcdir/data/sub-ca.crt \ --anchors=FILE:$srcdir/data/ca.crt \ - sd.data sd.data.out > /dev/null || exit 1 -cmp "$srcdir/test_chain.in" sd.data.out || exit 1 + sd.data sd.data.out > /dev/null || { echo Fail at $LINENO; exit 1; } +cmp "$srcdir/test_chain.in" sd.data.out || { echo Fail at $LINENO; exit 1; } echo "create signed data (subcert, certs)" ${hxtool} cms-create-sd \ @@ -292,34 +292,34 @@ ${hxtool} cms-create-sd \ --pool=FILE:$srcdir/data/sub-ca.crt \ --anchors=FILE:$srcdir/data/ca.crt \ "$srcdir/test_chain.in" \ - sd.data > /dev/null || exit 1 + sd.data > /dev/null || { echo Fail at $LINENO; exit 1; } echo "verify success signed data" ${hxtool} cms-verify-sd \ --missing-revoke \ --anchors=FILE:$srcdir/data/ca.crt \ - sd.data sd.data.out > /dev/null || exit 1 -cmp "$srcdir/test_chain.in" sd.data.out || exit 1 + sd.data sd.data.out > /dev/null || { echo Fail at $LINENO; exit 1; } +cmp "$srcdir/test_chain.in" sd.data.out || { echo Fail at $LINENO; exit 1; } echo "create signed data (subcert, certs, no-root)" ${hxtool} cms-create-sd \ --certificate=FILE:$srcdir/data/sub-cert.crt,$srcdir/data/sub-cert.key \ --pool=FILE:$srcdir/data/sub-ca.crt \ "$srcdir/test_chain.in" \ - sd.data > /dev/null || exit 1 + sd.data > /dev/null || { echo Fail at $LINENO; exit 1; } echo "verify success signed data" ${hxtool} cms-verify-sd \ --missing-revoke \ --anchors=FILE:$srcdir/data/ca.crt \ - sd.data sd.data.out > /dev/null || exit 1 -cmp "$srcdir/test_chain.in" sd.data.out || exit 1 + sd.data sd.data.out > /dev/null || { echo Fail at $LINENO; exit 1; } +cmp "$srcdir/test_chain.in" sd.data.out || { echo Fail at $LINENO; exit 1; } echo "create signed data (subcert, no-subca, no-root)" ${hxtool} cms-create-sd \ --certificate=FILE:$srcdir/data/sub-cert.crt,$srcdir/data/sub-cert.key \ "$srcdir/test_chain.in" \ - sd.data > /dev/null || exit 1 + sd.data > /dev/null || { echo Fail at $LINENO; exit 1; } echo "verify failure signed data" ${hxtool} cms-verify-sd \ @@ -331,7 +331,7 @@ echo "create signed data (sd cert)" ${hxtool} cms-create-sd \ --certificate=FILE:$srcdir/data/test-ds-only.crt,$srcdir/data/test-ds-only.key \ "$srcdir/test_chain.in" \ - sd.data > /dev/null || exit 1 + sd.data > /dev/null || { echo Fail at $LINENO; exit 1; } echo "create signed data (ke cert)" ${hxtool} cms-create-sd \ @@ -344,29 +344,29 @@ ${hxtool} cms-create-sd \ --certificate=FILE:$srcdir/data/test-ke-only.crt,$srcdir/data/test-ke-only.key \ --certificate=FILE:$srcdir/data/test-ds-only.crt,$srcdir/data/test-ds-only.key \ "$srcdir/test_chain.in" \ - sd.data > /dev/null || exit 1 + sd.data > /dev/null || { echo Fail at $LINENO; exit 1; } echo "create signed data (ke + sd certs)" ${hxtool} cms-create-sd \ --certificate=FILE:$srcdir/data/test-ds-only.crt,$srcdir/data/test-ds-only.key \ --certificate=FILE:$srcdir/data/test-ke-only.crt,$srcdir/data/test-ke-only.key \ "$srcdir/test_chain.in" \ - sd.data > /dev/null || exit 1 + sd.data > /dev/null || { echo Fail at $LINENO; exit 1; } echo "create signed data (detached)" ${hxtool} cms-create-sd \ --certificate=FILE:$srcdir/data/test.crt,$srcdir/data/test.key \ --detached-signature \ "$srcdir/test_chain.in" \ - sd.data > /dev/null || exit 1 + sd.data > /dev/null || { echo Fail at $LINENO; exit 1; } echo "verify signed data (detached)" ${hxtool} cms-verify-sd \ --missing-revoke \ --signed-content="$srcdir/test_chain.in" \ --anchors=FILE:$srcdir/data/ca.crt \ - sd.data sd.data.out > /dev/null || exit 1 -cmp "$srcdir/test_chain.in" sd.data.out || exit 1 + sd.data sd.data.out > /dev/null || { echo Fail at $LINENO; exit 1; } +cmp "$srcdir/test_chain.in" sd.data.out || { echo Fail at $LINENO; exit 1; } echo "verify failure signed data (detached)" ${hxtool} cms-verify-sd \ @@ -379,14 +379,14 @@ ${hxtool} cms-create-sd \ --peer-alg=1.2.840.113549.1.1.1 \ --certificate=FILE:$srcdir/data/test.crt,$srcdir/data/test.key \ "$srcdir/test_chain.in" \ - sd.data > /dev/null || exit 1 + sd.data > /dev/null || { echo Fail at $LINENO; exit 1; } echo "verify signed data (rsa)" ${hxtool} cms-verify-sd \ --missing-revoke \ --anchors=FILE:$srcdir/data/ca.crt \ - sd.data sd.data.out > /dev/null 2>/dev/null || exit 1 -cmp "$srcdir/test_chain.in" sd.data.out || exit 1 + sd.data sd.data.out > /dev/null 2>/dev/null || { echo Fail at $LINENO; exit 1; } +cmp "$srcdir/test_chain.in" sd.data.out || { echo Fail at $LINENO; exit 1; } echo "create signed data (pem, detached)" cp "$srcdir/test_chain.in" sd @@ -394,7 +394,7 @@ ${hxtool} cms-sign \ --certificate=FILE:$srcdir/data/test.crt,$srcdir/data/test.key \ --detached-signature \ --pem \ - sd > /dev/null || exit 1 + sd > /dev/null || { echo Fail at $LINENO; exit 1; } echo "verify signed data (pem, detached)" ${hxtool} cms-verify-sd \ @@ -410,7 +410,7 @@ ${hxtool} cms-sign \ --detached-signature \ --no-embedded-certs \ "$srcdir/data/static-file" \ - sd > /dev/null || exit 1 + sd > /dev/null || { echo Fail at $LINENO; exit 1; } echo "create signed data (leif only, detached sig)" cp "$srcdir/test_chain.in" sd @@ -419,7 +419,7 @@ ${hxtool} cms-sign \ --detached-signature \ --embed-leaf-only \ "$srcdir/data/static-file" \ - sd > /dev/null || exit 1 + sd > /dev/null || { echo Fail at $LINENO; exit 1; } echo "create signed data (no certs, detached sig, 2 signers)" cp "$srcdir/test_chain.in" sd @@ -429,7 +429,7 @@ ${hxtool} cms-sign \ --detached-signature \ --no-embedded-certs \ "$srcdir/data/static-file" \ - sd > /dev/null || exit 1 + sd > /dev/null || { echo Fail at $LINENO; exit 1; } echo "create signed data (no certs, detached sig, 3 signers)" cp "$srcdir/test_chain.in" sd @@ -440,36 +440,36 @@ ${hxtool} cms-sign \ --detached-signature \ --no-embedded-certs \ "$srcdir/data/static-file" \ - sd > /dev/null || exit 1 + sd > /dev/null || { echo Fail at $LINENO; exit 1; } echo "envelope data (content-type)" ${hxtool} cms-envelope \ --certificate=FILE:$srcdir/data/test.crt \ --content-type=1.1.1.1 \ "$srcdir/data/static-file" \ - ev.data > /dev/null || exit 1 + ev.data > /dev/null || { echo Fail at $LINENO; exit 1; } echo "unenvelope data (content-type)" ${hxtool} cms-unenvelope \ --certificate=FILE:$srcdir/data/test.crt,$srcdir/data/test.key \ ev.data ev.data.out \ - FILE:$srcdir/data/test.crt,$srcdir/data/test.key > /dev/null || exit 1 -cmp "$srcdir/data/static-file" ev.data.out || exit 1 + FILE:$srcdir/data/test.crt,$srcdir/data/test.key > /dev/null || { echo Fail at $LINENO; exit 1; } +cmp "$srcdir/data/static-file" ev.data.out || { echo Fail at $LINENO; exit 1; } echo "envelope data (content-info)" ${hxtool} cms-envelope \ --certificate=FILE:$srcdir/data/test.crt \ --content-info \ "$srcdir/data/static-file" \ - ev.data > /dev/null || exit 1 + ev.data > /dev/null || { echo Fail at $LINENO; exit 1; } echo "unenvelope data (content-info)" ${hxtool} cms-unenvelope \ --certificate=FILE:$srcdir/data/test.crt,$srcdir/data/test.key \ --content-info \ ev.data ev.data.out \ - FILE:$srcdir/data/test.crt,$srcdir/data/test.key > /dev/null || exit 1 -cmp "$srcdir/data/static-file" ev.data.out || exit 1 + FILE:$srcdir/data/test.crt,$srcdir/data/test.key > /dev/null || { echo Fail at $LINENO; exit 1; } +cmp "$srcdir/data/static-file" ev.data.out || { echo Fail at $LINENO; exit 1; } for a in des-ede3 aes-128 aes-256; do @@ -479,13 +479,13 @@ for a in des-ede3 aes-128 aes-256; do --encryption-type="$a-cbc" \ --certificate=FILE:$srcdir/data/test.crt \ "$srcdir/data/static-file" \ - ev.data || exit 1 + ev.data || { echo Fail at $LINENO; exit 1; } echo "unenvelope data ($a)" ${hxtool} cms-unenvelope \ --certificate=FILE:$srcdir/data/test.crt,$srcdir/data/test.key \ - ev.data ev.data.out > /dev/null || exit 1 - cmp "$srcdir/data/static-file" ev.data.out || exit 1 + ev.data ev.data.out > /dev/null || { echo Fail at $LINENO; exit 1; } + cmp "$srcdir/data/static-file" ev.data.out || { echo Fail at $LINENO; exit 1; } done for a in rc2-40 rc2-64 rc2-128 des-ede3 aes-128 aes-256; do @@ -496,8 +496,8 @@ for a in rc2-40 rc2-64 rc2-128 des-ede3 aes-128 aes-256; do --certificate=FILE:$srcdir/data/test.crt,$srcdir/data/test.key \ --content-info \ --allow-weak \ - "$srcdir/data/test-enveloped-$a" ev.data.out > /dev/null || exit 1 - cmp "$srcdir/data/static-file" ev.data.out || exit 1 + "$srcdir/data/test-enveloped-$a" ev.data.out > /dev/null || { echo Fail at $LINENO; exit 1; } + cmp "$srcdir/data/static-file" ev.data.out || { echo Fail at $LINENO; exit 1; } done exit 0 diff --git a/lib/hx509/test_pkcs12_pbes2.in b/lib/hx509/test_pkcs12_pbes2.in new file mode 100644 index 000000000..f86caa406 --- /dev/null +++ b/lib/hx509/test_pkcs12_pbes2.in @@ -0,0 +1,189 @@ +#!/bin/sh +# +# Copyright (c) 2024 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. +# +# Test PKCS#12 PBES2 interoperability with OpenSSL +# + +srcdir="@srcdir@" +objdir="@objdir@" + +stat="--statistic-file=${objdir}/statfile" + +hxtool="${TESTS_ENVIRONMENT} ./hxtool ${stat}" + +# Check if openssl is available +openssl version > /dev/null 2>&1 || { echo "OpenSSL not found, skipping"; exit 77; } + +# Test password +PASS="testpassword123" + +echo "Testing PKCS#12 PBES2 (modern encryption) support" + +# +# Test 1: Heimdal reads OpenSSL-created PBES2 PKCS#12 (default: AES-256-CBC) +# +echo "Test 1: Create PBES2 PKCS#12 with OpenSSL (AES-256-CBC), read with Heimdal" +openssl pkcs12 -export \ + -in $srcdir/data/test.crt \ + -inkey $srcdir/data/test.key \ + -out pbes2-aes256.p12 \ + -passout pass:$PASS \ + 2>/dev/null || { echo "OpenSSL pkcs12 export failed"; exit 1; } + +${hxtool} print --pass=PASS:$PASS PKCS12:pbes2-aes256.p12 > /dev/null || \ + { echo "Failed to read OpenSSL PBES2 AES-256-CBC PKCS#12"; exit 1; } +echo " OK: Heimdal read PBES2 AES-256-CBC PKCS#12" + +# Verify certificate content +${hxtool} print --pass=PASS:$PASS PKCS12:pbes2-aes256.p12 2>/dev/null | \ + grep -q "private key: yes" || \ + { echo "Failed: private key not found in PBES2 PKCS#12"; exit 1; } +echo " OK: Private key extracted from PBES2 PKCS#12" + +# +# Test 2: Heimdal reads OpenSSL-created PBES2 PKCS#12 with AES-128-CBC +# +echo "Test 2: Create PBES2 PKCS#12 with OpenSSL (AES-128-CBC), read with Heimdal" +openssl pkcs12 -export \ + -in $srcdir/data/test.crt \ + -inkey $srcdir/data/test.key \ + -out pbes2-aes128.p12 \ + -passout pass:$PASS \ + -keypbe aes-128-cbc \ + -certpbe aes-128-cbc \ + 2>/dev/null || { echo "OpenSSL pkcs12 export with AES-128 failed"; exit 1; } + +${hxtool} print --pass=PASS:$PASS PKCS12:pbes2-aes128.p12 > /dev/null || \ + { echo "Failed to read OpenSSL PBES2 AES-128-CBC PKCS#12"; exit 1; } +echo " OK: Heimdal read PBES2 AES-128-CBC PKCS#12" + +# +# Test 3: Heimdal reads OpenSSL-created legacy PKCS#12 (3DES/RC2) +# Note: This test is optional - LibreSSL and some OpenSSL 3.x builds +# don't support the -legacy flag or legacy algorithms +# +echo "Test 3: Create legacy PKCS#12 with OpenSSL (3DES), read with Heimdal" +if openssl pkcs12 -export \ + -in $srcdir/data/test.crt \ + -inkey $srcdir/data/test.key \ + -out legacy-3des.p12 \ + -passout pass:$PASS \ + -legacy \ + 2>/dev/null; then + ${hxtool} print --pass=PASS:$PASS PKCS12:legacy-3des.p12 > /dev/null || \ + { echo "Failed to read OpenSSL legacy 3DES PKCS#12"; exit 1; } + echo " OK: Heimdal read legacy 3DES PKCS#12" +else + echo " SKIP: OpenSSL does not support -legacy flag (LibreSSL or no legacy provider)" +fi + +# +# Test 4: Heimdal creates PKCS#12, OpenSSL reads it +# +echo "Test 4: Create PKCS#12 with Heimdal, read with OpenSSL" +${hxtool} certificate-copy \ + --out-pass=PASS:$PASS \ + FILE:$srcdir/data/test.crt,$srcdir/data/test.key \ + PKCS12:heimdal-created.p12 || \ + { echo "Failed to create PKCS#12 with Heimdal"; exit 1; } + +# Heimdal creates unencrypted PKCS#12 without MAC, so we need -nomacver +openssl pkcs12 -in heimdal-created.p12 -nomacver -passin pass:dummy -noout 2>/dev/null || \ + { echo "OpenSSL failed to read Heimdal-created PKCS#12"; exit 1; } +echo " OK: OpenSSL read Heimdal-created PKCS#12" + +# +# Test 5: Round-trip test - OpenSSL PBES2 -> Heimdal -> verify content +# +echo "Test 5: Round-trip verification with PBES2" +CERT_SUBJECT=$(${hxtool} print --pass=PASS:$PASS PKCS12:pbes2-aes256.p12 2>/dev/null | \ + grep "subject:" | head -1) +echo "$CERT_SUBJECT" | grep -q "Test cert" || \ + { echo "Failed: certificate subject mismatch"; exit 1; } +echo " OK: Certificate subject verified: $CERT_SUBJECT" + +# +# Test 6: Test PBES2 with SHA-256 HMAC PRF (if OpenSSL supports -macalg) +# +echo "Test 6: Create PBES2 PKCS#12 with SHA-256 MAC, read with Heimdal" +openssl pkcs12 -export \ + -in $srcdir/data/test.crt \ + -inkey $srcdir/data/test.key \ + -out pbes2-sha256mac.p12 \ + -passout pass:$PASS \ + -macalg sha256 \ + 2>/dev/null +if [ -f pbes2-sha256mac.p12 ]; then + ${hxtool} print --pass=PASS:$PASS PKCS12:pbes2-sha256mac.p12 > /dev/null || \ + { echo "Failed to read PBES2 PKCS#12 with SHA-256 MAC"; exit 1; } + echo " OK: Heimdal read PBES2 PKCS#12 with SHA-256 MAC" +else + echo " SKIP: OpenSSL does not support -macalg sha256" +fi + +# +# Test 7: Test with multiple certificates +# +echo "Test 7: Multiple certificates in PBES2 PKCS#12" +# Combine CA and end-entity cert +cat $srcdir/data/test.crt $srcdir/data/ca.crt > combined-certs.pem 2>/dev/null || true +if [ -f combined-certs.pem ] && [ -s combined-certs.pem ]; then + openssl pkcs12 -export \ + -in combined-certs.pem \ + -inkey $srcdir/data/test.key \ + -out pbes2-multi.p12 \ + -passout pass:$PASS \ + 2>/dev/null + if [ -f pbes2-multi.p12 ]; then + CERT_COUNT=$(${hxtool} print --pass=PASS:$PASS PKCS12:pbes2-multi.p12 2>/dev/null | \ + grep -c "^cert:" || echo 0) + if [ "$CERT_COUNT" -ge 1 ]; then + echo " OK: Read $CERT_COUNT certificate(s) from multi-cert PBES2 PKCS#12" + else + echo " WARN: Expected multiple certificates, got $CERT_COUNT" + fi + else + echo " SKIP: Could not create multi-cert PKCS#12" + fi +else + echo " SKIP: CA certificate not available for multi-cert test" +fi + +# Cleanup +rm -f pbes2-aes256.p12 pbes2-aes128.p12 legacy-3des.p12 heimdal-created.p12 \ + pbes2-sha256mac.p12 pbes2-multi.p12 combined-certs.pem 2>/dev/null + +echo "" +echo "All PKCS#12 PBES2 tests passed!" + +exit 0 diff --git a/lib/hx509/version-script.map b/lib/hx509/version-script.map index 27f5f51f7..698ddc6fb 100644 --- a/lib/hx509/version-script.map +++ b/lib/hx509/version-script.map @@ -151,6 +151,7 @@ HEIMDAL_X509_1.2 { hx509_context_free; hx509_context_init; hx509_context_set_missing_revoke; + hx509_context_set_ossl_cnf_propq; hx509_crl_add_revoked_certs; hx509_crl_alloc; hx509_crl_free; @@ -242,6 +243,7 @@ HEIMDAL_X509_1.2 { hx509_query_match_expr; hx509_query_match_friendly_name; hx509_query_match_issuer_serial; + hx509_query_match_key_algorithm; hx509_query_match_option; hx509_query_statistic_file; hx509_query_unparse_stats; @@ -271,6 +273,8 @@ HEIMDAL_X509_1.2 { hx509_revoke_print; hx509_set_error_string; hx509_set_error_stringv; + hx509_signature_ed25519; + hx509_signature_ed448; hx509_signature_md5; hx509_signature_rsa; hx509_signature_rsa_with_md5; diff --git a/lib/kadm5/Makefile.am b/lib/kadm5/Makefile.am index f4fb89e23..9f425dfb5 100644 --- a/lib/kadm5/Makefile.am +++ b/lib/kadm5/Makefile.am @@ -2,8 +2,8 @@ include $(top_srcdir)/Makefile.am.common -libkadm5srv_la_CPPFLAGS = -I$(srcdir)/../krb5 -libkadm5clnt_la_CPPFLAGS = -I$(srcdir)/../krb5 +libkadm5srv_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/../krb5 +libkadm5clnt_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/../krb5 lib_LTLIBRARIES = libkadm5srv.la libkadm5clnt.la libkadm5srv_la_LDFLAGS = -version-info 8:1:0 @@ -35,10 +35,10 @@ libkadm5clnt_la_LIBADD = \ libexec_PROGRAMS = ipropd-master ipropd-slave default_keys_SOURCES = default_keys.c -default_keys_CPPFLAGS = -I$(srcdir)/../krb5 +default_keys_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/../krb5 test_marshall_SOURCES = marshall.c -test_marshall_CPPFLAGS = -I$(srcdir)/../krb5 -DTEST +test_marshall_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/../krb5 -DTEST kadm5includedir = $(includedir)/kadm5 buildkadm5include = $(buildinclude)/kadm5 @@ -135,10 +135,10 @@ dist_iprop_log_SOURCES = iprop-log.c nodist_iprop_log_SOURCES = iprop-commands.c ipropd_master_SOURCES = ipropd_master.c ipropd_common.c iprop.h kadm5_locl.h -ipropd_master_CPPFLAGS = -I$(srcdir)/../krb5 +ipropd_master_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/../krb5 ipropd_slave_SOURCES = ipropd_slave.c ipropd_common.c iprop.h kadm5_locl.h -ipropd_slave_CPPFLAGS = -I$(srcdir)/../krb5 +ipropd_slave_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/../krb5 man_MANS = kadm5_pwcheck.3 iprop.8 iprop-log.8 @@ -165,7 +165,7 @@ iprop_log_LDADD = \ $(LIB_dlopen) \ $(LIB_pidfile) -iprop_log_CPPFLAGS = -I$(srcdir)/../krb5 +iprop_log_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/../krb5 iprop-commands.c iprop-commands.h: iprop-commands.in $(SLC) $(srcdir)/iprop-commands.in diff --git a/lib/kadm5/ipropd_master.c b/lib/kadm5/ipropd_master.c index 3d693bdfe..6914c43cd 100644 --- a/lib/kadm5/ipropd_master.c +++ b/lib/kadm5/ipropd_master.c @@ -1523,6 +1523,8 @@ static char *keytab_str = sHDB; static char *database; static char *config_file; static char *port_str; +static char *ossl_cnf; +static char *ossl_propq; static int detach_from_console; static int daemon_child = -1; @@ -1548,6 +1550,12 @@ static struct getargs args[] = { "basename of pidfile; private argument for testing", "NAME" }, { "hostname", 0, arg_string, rk_UNCONST(&master_hostname), "hostname of master (if not same as hostname)", "hostname" }, + { "ossl-cnf", 0, arg_string, &ossl_cnf, + "OpenSSL configuration file", "FILE" + }, + { "ossl-propq", 0, arg_string, &ossl_propq, + "OpenSSL property query string (e.g., provider=pkcs11)", "PROPQ" + }, { "verbose", 0, arg_flag, &verbose, NULL, NULL }, { "version", 0, arg_flag, &version_flag, NULL, NULL }, { "help", 0, arg_flag, &help_flag, NULL, NULL } @@ -1608,6 +1616,12 @@ main(int argc, char **argv) if (ret) errx(1, "krb5_init_context failed: %d", ret); + if (ossl_cnf || ossl_propq) { + ret = krb5_set_ossl_cnf_propq(context, ossl_cnf, ossl_propq); + if (ret) + krb5_err(context, 1, ret, "krb5_set_ossl_cnf_propq"); + } + setup_signal(); if (config_file == NULL) { diff --git a/lib/kadm5/ipropd_slave.c b/lib/kadm5/ipropd_slave.c index 549bb6cfb..ee4b1a14c 100644 --- a/lib/kadm5/ipropd_slave.c +++ b/lib/kadm5/ipropd_slave.c @@ -724,6 +724,8 @@ static char *config_file; static int version_flag; static int help_flag; static char *port_str; +static char *ossl_cnf; +static char *ossl_propq; static int detach_from_console; static int daemon_child = -1; @@ -752,6 +754,12 @@ static struct getargs args[] = { { "async-hdb", 'a', arg_flag, &async_hdb, NULL, NULL }, { "hostname", 0, arg_string, rk_UNCONST(&slave_str), "hostname of slave (if not same as hostname)", "hostname" }, + { "ossl-cnf", 0, arg_string, &ossl_cnf, + "OpenSSL configuration file", "FILE" + }, + { "ossl-propq", 0, arg_string, &ossl_propq, + "OpenSSL property query string (e.g., provider=pkcs11)", "PROPQ" + }, { "verbose", 0, arg_flag, &verbose, NULL, NULL }, { "version", 0, arg_flag, &version_flag, NULL, NULL }, { "help", 0, arg_flag, &help_flag, NULL, NULL } @@ -810,6 +818,12 @@ main(int argc, char **argv) if (ret) errx (1, "krb5_init_context failed: %d", ret); + if (ossl_cnf || ossl_propq) { + ret = krb5_set_ossl_cnf_propq(context, ossl_cnf, ossl_propq); + if (ret) + krb5_err(context, 1, ret, "krb5_set_ossl_cnf_propq"); + } + setup_signal(); if (config_file == NULL) { diff --git a/lib/kafs/ChangeLog b/lib/kafs/ChangeLog deleted file mode 100644 index ab7f0a052..000000000 --- a/lib/kafs/ChangeLog +++ /dev/null @@ -1,572 +0,0 @@ -2008-07-17 Love Hörnquist Åstrand - - * common.c: Try afs/cell@REALM before afs@REALM since that is what - OpenAFS folks have been saying is best pratices for some time - now. Patch from Derrick Brashear. - -2008-04-15 Love Hörnquist Åstrand - * afssys.c: Avoid using entry points depending on _IOWR if there - is no _IOWR (on cygwin). - -2007-07-10 Love Hörnquist Åstrand - - * Makefile.am: New library version. - -2007-05-10 Love Hörnquist Åstrand - - * kafs.h: Add VIOCSETTOK2 - -2006-10-21 Love Hörnquist Åstrand - - * Makefile.am: unbreak previous - - * Makefile.am: split dist and nodist sources - -2006-10-20 Love Hörnquist Åstrand - - * Makefile.am: add more files - -2006-05-01 Love Hörnquist Åstrand - - * kafs.3: Spelling, from Björn Sandell. - -2006-04-11 Love Hörnquist Åstrand - - * afssys.c: use afs_ioctlnum, From Tomas Olsson - -2006-04-10 Love Hörnquist Åstrand - - * afssys.c: Try harder to get the pioctl to work via the /proc or - /dev interface, OpenAFS choose to reuse the same ioctl number, - while Arla didn't. Also, try new ioctl before the the old - syscalls. - - * afskrb5.c (afslog_uid_int): use the simpler - krb5_principal_get_realm function. - -2005-12-21 Love Hörnquist Åstrand - - * Makefile.am: Remove dependency on config.h, breaks IRIX build, - could depend on libkafs_la_OBJECTS, but that is just asking for - trubble. - -2005-10-20 Love Hörnquist Åstrand - - * afssys.c (k_hasafs_recheck): new function, allow rechecking if - AFS client have started now, internaly it resets the internal - state from k_hasafs() and retry retry the probing. The problem - with calling k_hasaf() is that is plays around with signals, and - that cases problem for some systems/applications. - -2005-10-02 Love Hörnquist Åstrand - - * kafs_locl.h: Maybe include . - - * afssys.c: Mac OS X 10.4 needs a runtime check if we are going to - use the syscall, there is no cpp define to use to check the - version. Every after 10.0 (darwin 8.0) uses the /dev/ version of - the pioctl. - -2005-10-01 Love Hörnquist Åstrand - - * afssys.c: Support the new MacOS X 10.4 ioctl interface that is a - device node. Patched from Tomas Olson . - -2005-08-26 Love Hörnquist Åstrand - - * afskrb5.c: Default to use 2b tokens. - -2005-06-17 Love Hörnquist Åstrand - - * common.c: rename index to idx - - * afssys.c (k_afs_cell_of_file): unconst path - -2005-06-02 Love Hörnquist Åstrand - - * use struct kafs_data everywhere, don't mix with the typedef - kafs_data - - * roken_rename.h: rename more resolve.c symbols - - * afssys.c: Don't building map_syscall_name_to_number where its - not used. - -2005-02-24 Love Hörnquist Åstrand - - * Makefile.am: bump version to 4:1:4 - -2005-02-03 Love Hörnquist Åstrand - - * kafs.h: de-__P - -2004-12-06 Love Hörnquist Åstrand - - * afskrb5.c: s/KEYTYPE_DES/ETYPE_DES_CBC_CRC/ - -2004-08-09 Love Hörnquist Åstrand - - * afssysdefs.h: ifdef protect AFS_SYSCALL for DragonFly since they - still define __FreeBSD__ (and __FreeBSD_version), but claim that - they will stop doing it some time... - - * afssysdefs.h: dragonflybsd uses 339 just like freebsd5 - -2004-06-22 Love Hörnquist Åstrand - - * afssys.c: s/arla/nnpfs/ - - * afssys.c: support the linux /proc/fs/mumel/afs_ioctl afs - "syscall" interface - -2004-01-22 Love Hörnquist Åstrand - - * common.c: search paths for AFS configuration files for the - OpenAFS MacOS X, fix comment - - * kafs.h: search paths for AFS configuration files for the OpenAFS - MacOS X - -2003-12-02 Love Hörnquist Åstrand - - * common.c: add _PATH_ARLA_OPENBSD & c/o - - * kafs.h: add _PATH_ARLA_OPENBSD & c/o - -2003-11-14 Love Hörnquist Åstrand - - * common.c: typo, Bruno Rohee - -2003-11-08 Love Hörnquist Åstrand - - * kafs.3: spelling, partly from jmc - -2003-09-30 Love Hörnquist Åstrand - - * afskrb5.c (krb5_afslog_uid_home): be even more friendly to the - user and fetch context and id ourself - -2003-09-23 Love Hörnquist Åstrand - - * afskrb5.c (afslog_uid_int): just belive that realm hint the user - passed us - -2003-07-23 Love Hörnquist Åstrand - - * Makefile.am: always include v4 symbols - - * afskrb.c: provide dummy krb_ function to there is no need to - bump major - -2003-06-22 Love Hörnquist Åstrand - - * afskrb5.c (v5_convert): rename one of the two c to cred4 - -2003-04-23 Love Hörnquist Åstrand - - * common.c, kafs.h: drop the int argument (the error code) from - the logging function - -2003-04-22 Johan Danielsson - - * afskrb5.c (v5_convert): better match what other functions do - with values from krb5.conf, like case insensitivity - -2003-04-16 Love Hörnquist Åstrand - - * kafs.3: Change .Fd #include to .In header.h - from Thomas Klausner - -2003-04-14 Love Hörnquist Åstrand - - * Makefile.am: (libkafs_la_LDFLAGS): update version - - * Makefile.am (ROKEN_SRCS): drop strupr.c - - * kafs.3: document kafs_set_verbose - - * common.c (kafs_set_verbose): add function that (re)sets the - logging function - (_kafs_try_get_cred): add function that does (krb_data->get_cred) to - make logging easier (that is now done in this function) - (*): use _kafs_try_get_cred - - * afskrb5.c (get_cred): handle that inst can be the empty string too - (v5_convert): use _kafs_foldup - (krb5_afslog_uid_home): set name - (krb5_afslog_uid_home): ditto - - * afskrb.c (krb_afslog_uid_home): set name - (krb_afslog_uid_home): ditto - - * kafs_locl.h (kafs_data): add name - (_kafs_foldup): internally export - -2003-04-11 Love Hörnquist Åstrand - - * kafs.3: tell that cell-name is uppercased - - * Makefile.am: add INCLUDE_krb4 when using krb4, add INCLUDE_des - when using krb5, add strupr.c - - * afskrb5.c: Check the cell part of the name, not the realm part - when checking if 2b should be used. The reson is afs@REALM might - have updated their servers but not afs/cell@REALM. Add constant - KAFS_RXKAD_2B_KVNO. - -2003-04-06 Love Hörnquist Åstrand - - * kafs.3: s/kerberos/Kerberos/ - -2003-03-19 Love Hörnquist Åstrand - - * kafs.3: spelling, from - - * kafs.3: document the kafs_settoken functions write about the - krb5_appdefault option for kerberos 5 afs tokens fix prototypes - -2003-03-18 Love Hörnquist Åstrand - - * afskrb5.c (kafs_settoken5): change signature to include a - krb5_context, use v5_convert - (v5_convert): new function, converts a krb5_ccreds to a kafs_token in - three diffrent ways, not at all, local 524/2b, and using 524 - (v5_to_kt): add code to do local 524/2b - (get_cred): use v5_convert - - - * kafs.h (kafs_settoken5): change signature to include a - krb5_context - - * Makefile.am: always build the libkafs library now that the - kerberos 5 can stand on their own - - * kafs.3: expose the krb5 functions - - * common.c (kafs_settoken_rxkad): move all content kerberos - version from kafs_settoken to kafs_settoken_rxkad - (_kafs_fixup_viceid): move the fixup the timestamp to make client - happy code here. - (_kafs_v4_to_kt): move all the kerberos 4 dependent parts from - kafs_settoken here. - (*): adapt to kafs_token - - * afskrb5.c (kafs_settoken5): new function, inserts a krb5_creds - into kernel - (v5_to_kt): new function, stores a krb5_creds in struct kafs_token - (get_cred): add a appdefault boolean ("libkafs", realm, "afs-use-524") - that can used to toggle if there should v5 token should be used - directly or converted via 524 first. - - * afskrb.c: move kafs_settoken here, use struct kafs_token - - * kafs_locl.h: include krb5-v4compat.h if needed, define an - internal structure struct kafs_token that carries around for rxkad - data that is independent of kerberos version - -2003-02-18 Love Hörnquist Åstrand - - * dlfcn.h: s/intialize/initialize, from - - -2003-02-08 Assar Westerlund - - * afssysdefs.h: fix FreeBSD section - -2003-02-06 Love Hörnquist Åstrand - - * afssysdefs.h: use syscall 208 on openbsd (all version) use - syscall 339 on freebsd 5.0 and later, use 210 on 4.x and earlier - -2002-08-28 Johan Danielsson - - * kafs.3: move around sections (from NetBSD) - -2002-05-31 Assar Westerlund - - * common.c: remove the trial of afs@REALM for cell != realm, it - tries to use the wrong key for foreign cells - -2002-05-20 Johan Danielsson - - * Makefile.am: version number - -2002-04-18 Johan Danielsson - - * common.c (find_cells): make file parameter const - -2001-11-01 Assar Westerlund - - * add strsep, and bump version to 3:3:3 - -2001-10-27 Assar Westerlund - - * Makefile.am (libkafs_la_LDFLAGS): set version to 3:2:3 - -2001-10-24 Assar Westerlund - - * afskrb.c (afslog_uid_int): handle krb_get_tf_fullname that - cannot take NULLs - (such as the MIT one) - -2001-10-22 Assar Westerlund - - * Makefile.am (ROKEN_SRCS): add strlcpy.c - -2001-10-09 Assar Westerlund - - * Makefile.am (ROKEN_SRCS): add strtok_r.c - * roken_rename.h (dns_srv_order): rename correctly - (strtok_r): add renaming - -2001-09-10 Assar Westerlund - - * kafs.h, common.c: look for configuration files in /etc/arla (the - location in debian's arla package) - -2001-08-26 Assar Westerlund - - * Makefile.am: handle both krb5 and krb4 cases - -2001-07-19 Assar Westerlund - - * Makefile.am (libkafs_la_LDFLAGS): set version to 3:0:3 - -2001-07-12 Assar Westerlund - - * common.c: look in /etc/openafs for debian openafs - * kafs.h: add paths for openafs debian (/etc/openafs) - - * Makefile.am: add required library dependencies - -2001-07-03 Assar Westerlund - - * Makefile.am (libkafs_la_LDFLAGS): set versoin to 2:4:2 - -2001-06-19 Assar Westerlund - - * common.c (_kafs_realm_of_cell): changed to first try exact match - in CellServDB, then exact match in DNS, and finally in-exact match - in CellServDB - -2001-05-18 Johan Danielsson - - * Makefile.am: only build resolve.c if doing renaming - -2001-02-12 Assar Westerlund - - * Makefile.am, roken_rename.h: add rename of dns functions - -2000-12-11 Assar Westerlund - - * Makefile.am (libkafs_la_LDFLAGS): set version to 2:3:2 - -2000-11-17 Assar Westerlund - - * afssysdefs.h: solaris 8 apperently uses 65 - -2000-09-19 Assar Westerlund - - * Makefile.am (libkafs_la_LDFLAGS): bump version to 2:2:2 - -2000-09-12 Johan Danielsson - - * dlfcn.c: correct arguments to some snprintf:s - -2000-07-25 Johan Danielsson - - * Makefile.am: bump version to 2:1:2 - -2000-04-03 Assar Westerlund - - * Makefile.am: set version to 2:0:2 - -2000-03-20 Assar Westerlund - - * afssysdefs.h: make versions later than 5.7 of solaris also use - 73 - -2000-03-16 Assar Westerlund - - * afskrb.c (afslog_uid_int): use krb_get_tf_fullname instead of - krb_get_default_principal - -2000-03-15 Assar Westerlund - - * afssys.c (map_syscall_name_to_number): ignore # at - beginning-of-line - -2000-03-13 Assar Westerlund - - * afssysdefs.h: add 230 for MacOS X per information from - - -1999-12-06 Assar Westerlund - - * Makefile.am: set version to 1:2:1 - -1999-11-22 Assar Westerlund - - * afskrb5.c (afslog_uid_int): handle d->realm == NULL - -1999-11-17 Assar Westerlund - - * afskrb5.c (afslog_uid_int): don't look at the local realm at - all. just use the realm from the ticket file. - -1999-10-20 Assar Westerlund - - * Makefile.am: set version to 1:1:1 - - * afskrb5.c (get_cred): always request a DES key - -Mon Oct 18 17:40:21 1999 Bjoern Groenvall - - * common.c (find_cells): Trim trailing whitespace from - cellname. Lines starting with # are regarded as comments. - -Fri Oct 8 18:17:22 1999 Bjoern Groenvall - - * afskrb.c, common.c : Change code to make a clear distinction - between hinted realm and ticket realm. - - * kafs_locl.h: Added argument realm_hint. - - * common.c (_kafs_get_cred): Change code to acquire the ``best'' - possible ticket. Use cross-cell authentication only as method of - last resort. - - * afskrb.c (afslog_uid_int): Add realm_hint argument and extract - realm from ticket file. - - * afskrb5.c (afslog_uid_int): Added argument realm_hint. - -1999-10-03 Assar Westerlund - - * afskrb5.c (get_cred): update to new krb524_convert_creds_kdc - -1999-08-12 Johan Danielsson - - * Makefile.am: ignore the comlicated aix construct if !krb4 - -1999-07-26 Assar Westerlund - - * Makefile.am: set version to 1:0:1 - -1999-07-22 Assar Westerlund - - * afssysdefs.h: define AFS_SYSCALL to 73 for Solaris 2.7 - -1999-07-07 Assar Westerlund - - * afskrb5.c (krb5_realm_of_cell): new function - - * afskrb.c (krb_realm_of_cell): new function - (afslog_uid_int): call krb_get_lrealm correctly - -1999-06-15 Assar Westerlund - - * common.c (realm_of_cell): rename to _kafs_realm_of_cell and - un-staticize - -Fri Mar 19 14:52:29 1999 Johan Danielsson - - * Makefile.am: add version-info - -Thu Mar 18 11:24:02 1999 Johan Danielsson - - * Makefile.am: include Makefile.am.common - -Sat Feb 27 19:46:21 1999 Johan Danielsson - - * Makefile.am: remove EXTRA_DATA (as of autoconf 2.13/automake - 1.4) - -Thu Feb 11 22:57:37 1999 Johan Danielsson - - * Makefile.am: set AIX_SRC also if !AIX - -Tue Dec 1 14:45:15 1998 Johan Danielsson - - * Makefile.am: fix AIX linkage - -Sun Nov 22 10:40:44 1998 Assar Westerlund - - * Makefile.in (WFLAGS): set - -Sat Nov 21 16:55:19 1998 Johan Danielsson - - * afskrb5.c: add homedir support - -Sun Sep 6 20:16:27 1998 Assar Westerlund - - * add new functionality for specifying the homedir to krb_afslog - et al - -Thu Jul 16 01:27:19 1998 Assar Westerlund - - * afssys.c: reorganize order of definitions. - (try_one, try_two): conditionalize - -Thu Jul 9 18:31:52 1998 Johan Danielsson - - * common.c (realm_of_cell): make the dns fallback work - -Wed Jul 8 01:39:44 1998 Assar Westerlund - - * afssys.c (map_syscall_name_to_number): new function for finding - the number of a syscall given the name on solaris - (k_hasafs): try using map_syscall_name_to_number - -Tue Jun 30 17:19:00 1998 Assar Westerlund - - * afssys.c: rewrite and add support for environment variable - AFS_SYSCALL - - * Makefile.in (distclean): don't remove roken_rename.h - -Fri May 29 19:03:20 1998 Assar Westerlund - - * Makefile.in (roken_rename.h): remove dependency - -Mon May 25 05:25:54 1998 Assar Westerlund - - * Makefile.in (clean): try to remove shared library debris - -Sun Apr 19 09:58:40 1998 Assar Westerlund - - * Makefile.in: add symlink magic for linux - -Sat Apr 4 15:08:48 1998 Assar Westerlund - - * kafs.h: add arla paths - - * common.c (_kafs_afslog_all_local_cells): Try _PATH_ARLA_* - (_realm_of_cell): Try _PATH_ARLA_CELLSERVDB - -Thu Feb 19 14:50:22 1998 Johan Danielsson - - * common.c: Don't store expired tokens (this broke when using - pag-less rsh-sessions, and `non-standard' ticket files). - -Thu Feb 12 11:20:15 1998 Johan Danielsson - - * Makefile.in: Install/uninstall one library at a time. - -Thu Feb 12 05:38:58 1998 Assar Westerlund - - * Makefile.in (install): one library at a time. - -Mon Feb 9 23:40:32 1998 Assar Westerlund - - * common.c (find_cells): ignore empty lines - -Tue Jan 6 04:25:58 1998 Assar Westerlund - - * afssysdefs.h (AFS_SYSCALL): add FreeBSD - -Fri Jan 2 17:08:24 1998 Assar Westerlund - - * kafs.h: new VICEIOCTL's. From - - * afssysdefs.h: Add OpenBSD diff --git a/lib/kafs/Makefile.am b/lib/kafs/Makefile.am deleted file mode 100644 index d3c314195..000000000 --- a/lib/kafs/Makefile.am +++ /dev/null @@ -1,96 +0,0 @@ -# $Id$ - -include $(top_srcdir)/Makefile.am.common - -WFLAGS += $(WFLAGS_ENUM_CONV) - -AM_CPPFLAGS += $(AFS_EXTRA_DEFS) $(ROKEN_RENAME) - -if KRB5 -DEPLIB_krb5 = ../krb5/libkrb5.la -krb5_am_workaround = -I$(top_srcdir)/lib/krb5 -else -DEPLIB_krb5 = -krb5_am_workaround = -endif # KRB5 -AM_CPPFLAGS += $(krb5_am_workaround) - - -if AIX -AFSL_EXP = $(srcdir)/afsl.exp - -if AIX4 -AFS_EXTRA_LD = -bnoentry -else -AFS_EXTRA_LD = -e _nostart -endif - -if AIX_DYNAMIC_AFS -AIX_SRC = -AFS_EXTRA_LIBS = afslib.so -AFS_EXTRA_DEFS = -else -AIX_SRC = afslib.c -AFS_EXTRA_LIBS = -AFS_EXTRA_DEFS = -DSTATIC_AFS -endif - -else -AFSL_EXP = -AIX_SRC = -endif # AIX - -libkafs_la_LIBADD = $(DEPLIB_krb5) $(LIBADD_roken) - -lib_LTLIBRARIES = libkafs.la -libkafs_la_LDFLAGS = -version-info 5:1:5 -foodir = $(libdir) -foo_DATA = $(AFS_EXTRA_LIBS) -# EXTRA_DATA = afslib.so - -CLEANFILES= $(AFS_EXTRA_LIBS) $(ROKEN_SRCS) - -include_HEADERS = kafs.h - -if KRB5 -afskrb5_c = -endif - -if do_roken_rename -ROKEN_SRCS = resolve.c strtok_r.c strlcpy.c strsep.c -endif - -dist_libkafs_la_SOURCES = \ - afssys.c \ - afskrb5.c \ - rxkad_kdf.c \ - common.c \ - $(AIX_SRC) \ - kafs_locl.h \ - afssysdefs.h \ - roken_rename.h - -nodist_libkafs_la_SOURCES = $(ROKEN_SRCS) - -EXTRA_libkafs_la_SOURCES = afskrb5.c afslib.c - -EXTRA_DIST = NTMakefile afsl.exp afslib.exp $(man_MANS) - -man_MANS = kafs.3 - -# AIX: this almost works with gcc, but somehow it fails to use the -# correct ld, use ld instead -afslib.so: afslib.o - ld -o $@ -bM:SRE -bI:$(srcdir)/afsl.exp -bE:$(srcdir)/afslib.exp $(AFS_EXTRA_LD) afslib.o -lc - -resolve.c: - $(LN_S) $(srcdir)/../roken/resolve.c . - -strtok_r.c: - $(LN_S) $(srcdir)/../roken/strtok_r.c . - -strlcpy.c: - $(LN_S) $(srcdir)/../roken/strlcpy.c . - -strsep.c: - $(LN_S) $(srcdir)/../roken/strsep.c . diff --git a/lib/kafs/NTMakefile b/lib/kafs/NTMakefile deleted file mode 100644 index 4cff3426f..000000000 --- a/lib/kafs/NTMakefile +++ /dev/null @@ -1,35 +0,0 @@ -######################################################################## -# -# Copyright (c) 2009, Secure Endpoints Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# - Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# - Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in -# the documentation and/or other materials provided with the -# distribution. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. -# - -RELDIR=lib\kafs - -!include ../../windows/NTMakefile.w32 - diff --git a/lib/kafs/afskrb5.c b/lib/kafs/afskrb5.c deleted file mode 100644 index 0077016f6..000000000 --- a/lib/kafs/afskrb5.c +++ /dev/null @@ -1,353 +0,0 @@ -/* - * Copyright (c) 1995-2003 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "kafs_locl.h" - -struct krb5_kafs_data { - krb5_context context; - krb5_ccache id; - krb5_const_realm realm; -}; - -enum { - KAFS_RXKAD_2B_KVNO = 213, - KAFS_RXKAD_K5_KVNO = 256 -}; - -static int -v5_to_kt(krb5_creds *cred, uid_t uid, struct kafs_token *kt, int local524) -{ - int kvno, ret; - - kt->ticket = NULL; - - if (local524) { - Ticket t; - unsigned char *buf; - size_t buf_len; - size_t len; - - kvno = KAFS_RXKAD_2B_KVNO; - - ret = decode_Ticket(cred->ticket.data, cred->ticket.length, &t, &len); - if (ret) - return ret; - if (t.tkt_vno != 5) - return -1; - - ASN1_MALLOC_ENCODE(EncryptedData, buf, buf_len, &t.enc_part, - &len, ret); - free_Ticket(&t); - if (ret) - return ret; - if(buf_len != len) { - free(buf); - return KRB5KRB_ERR_GENERIC; - } - - kt->ticket = buf; - kt->ticket_len = buf_len; - - } else { - kvno = KAFS_RXKAD_K5_KVNO; - kt->ticket = malloc(cred->ticket.length); - if (kt->ticket == NULL) - return ENOMEM; - kt->ticket_len = cred->ticket.length; - memcpy(kt->ticket, cred->ticket.data, kt->ticket_len); - } - - - /* - * Build a struct ClearToken - */ - - ret = _kafs_derive_des_key(cred->session.keytype, - cred->session.keyvalue.data, - cred->session.keyvalue.length, - kt->ct.HandShakeKey); - if (ret) { - free(kt->ticket); - kt->ticket = NULL; - return ret; - } - kt->ct.AuthHandle = kvno; - kt->ct.ViceId = uid; - kt->ct.BeginTimestamp = cred->times.starttime; - kt->ct.EndTimestamp = cred->times.endtime; - - _kafs_fixup_viceid(&kt->ct, uid); - - return 0; -} - -static krb5_error_code -v5_convert(krb5_context context, krb5_ccache id, - krb5_creds *cred, uid_t uid, - const char *cell, - struct kafs_token *kt) -{ - krb5_error_code ret; - char *c, *val; - - c = strdup(cell); - if (c == NULL) - return ENOMEM; - _kafs_foldup(c, c); - krb5_appdefault_string (context, "libkafs", - c, - "afs-use-524", "2b", &val); - free(c); - - if (strcasecmp(val, "local") == 0 || - strcasecmp(val, "2b") == 0) - ret = v5_to_kt(cred, uid, kt, 1); - else - ret = v5_to_kt(cred, uid, kt, 0); - - free(val); - return ret; -} - - -/* - * - */ - -static int -get_cred(struct kafs_data *data, const char *name, const char *inst, - const char *realm, uid_t uid, struct kafs_token *kt) -{ - krb5_error_code ret; - krb5_creds in_creds, *out_creds; - struct krb5_kafs_data *d = data->data; - int invalid; - - memset(&in_creds, 0, sizeof(in_creds)); - - ret = krb5_make_principal(d->context, &in_creds.server, - realm, name, inst, NULL); - if(ret) - return ret; - ret = krb5_cc_get_principal(d->context, d->id, &in_creds.client); - if(ret){ - krb5_free_principal(d->context, in_creds.server); - return ret; - } - - /* check if des is disable, and in that case enable it for afs */ - invalid = krb5_enctype_valid(d->context, ETYPE_DES_CBC_CRC); - if (invalid) - krb5_enctype_enable(d->context, ETYPE_DES_CBC_CRC); - - ret = krb5_get_credentials(d->context, 0, d->id, &in_creds, &out_creds); - - if (invalid) - krb5_enctype_disable(d->context, ETYPE_DES_CBC_CRC); - - krb5_free_principal(d->context, in_creds.server); - krb5_free_principal(d->context, in_creds.client); - if(ret) - return ret; - - ret = v5_convert(d->context, d->id, out_creds, uid, - (inst != NULL && inst[0] != '\0') ? inst : realm, kt); - krb5_free_creds(d->context, out_creds); - - return ret; -} - -static const char * -get_error(struct kafs_data *data, int error) -{ - struct krb5_kafs_data *d = data->data; - return krb5_get_error_message(d->context, error); -} - -static void -free_error(struct kafs_data *data, const char *str) -{ - struct krb5_kafs_data *d = data->data; - krb5_free_error_message(d->context, str); -} - -static krb5_error_code -afslog_uid_int(struct kafs_data *data, const char *cell, const char *rh, - uid_t uid, const char *homedir) -{ - krb5_error_code ret; - struct kafs_token kt; - krb5_principal princ; - const char *trealm; /* ticket realm */ - struct krb5_kafs_data *d = data->data; - - if (cell == 0 || cell[0] == 0) - return _kafs_afslog_all_local_cells (data, uid, homedir); - - ret = krb5_cc_get_principal (d->context, d->id, &princ); - if (ret) - return ret; - - trealm = krb5_principal_get_realm (d->context, princ); - - kt.ticket = NULL; - ret = _kafs_get_cred(data, cell, d->realm, trealm, uid, &kt); - krb5_free_principal (d->context, princ); - - if(ret == 0) { - ret = kafs_settoken_rxkad(cell, &kt.ct, kt.ticket, kt.ticket_len); - free(kt.ticket); - } - return ret; -} - -static char * -get_realm(struct kafs_data *data, const char *host) -{ - struct krb5_kafs_data *d = data->data; - krb5_realm *realms; - char *r; - if(krb5_get_host_realm(d->context, host, &realms)) - return NULL; - r = strdup(realms[0]); - krb5_free_host_realm(d->context, realms); - return r; -} - -krb5_error_code -krb5_afslog_uid_home(krb5_context context, - krb5_ccache id, - const char *cell, - krb5_const_realm realm, - uid_t uid, - const char *homedir) -{ - struct kafs_data kd; - struct krb5_kafs_data d; - krb5_error_code ret; - - kd.name = "krb5"; - kd.afslog_uid = afslog_uid_int; - kd.get_cred = get_cred; - kd.get_realm = get_realm; - kd.get_error = get_error; - kd.free_error = free_error; - kd.data = &d; - if (context == NULL) { - ret = krb5_init_context(&d.context); - if (ret) - return ret; - } else - d.context = context; - if (id == NULL) { - ret = krb5_cc_default(d.context, &d.id); - if (ret) - goto out; - } else - d.id = id; - d.realm = realm; - ret = afslog_uid_int(&kd, cell, 0, uid, homedir); - if (id == NULL) - krb5_cc_close(context, d.id); - out: - if (context == NULL) - krb5_free_context(d.context); - return ret; -} - -krb5_error_code -krb5_afslog_uid(krb5_context context, - krb5_ccache id, - const char *cell, - krb5_const_realm realm, - uid_t uid) -{ - return krb5_afslog_uid_home (context, id, cell, realm, uid, NULL); -} - -krb5_error_code -krb5_afslog(krb5_context context, - krb5_ccache id, - const char *cell, - krb5_const_realm realm) -{ - return krb5_afslog_uid (context, id, cell, realm, getuid()); -} - -krb5_error_code -krb5_afslog_home(krb5_context context, - krb5_ccache id, - const char *cell, - krb5_const_realm realm, - const char *homedir) -{ - return krb5_afslog_uid_home (context, id, cell, realm, getuid(), homedir); -} - -/* - * - */ - -krb5_error_code -krb5_realm_of_cell(const char *cell, char **realm) -{ - struct kafs_data kd; - - kd.name = "krb5"; - kd.get_realm = get_realm; - kd.get_error = get_error; - kd.free_error = free_error; - return _kafs_realm_of_cell(&kd, cell, realm); -} - -/* - * - */ - -int -kafs_settoken5(krb5_context context, const char *cell, uid_t uid, - krb5_creds *cred) -{ - struct kafs_token kt; - int ret; - - ret = v5_convert(context, NULL, cred, uid, cell, &kt); - if (ret) - return ret; - - ret = kafs_settoken_rxkad(cell, &kt.ct, kt.ticket, kt.ticket_len); - - free(kt.ticket); - - return ret; -} diff --git a/lib/kafs/afsl.exp b/lib/kafs/afsl.exp deleted file mode 100644 index 4d2b00e28..000000000 --- a/lib/kafs/afsl.exp +++ /dev/null @@ -1,6 +0,0 @@ -#!/unix - -* This mumbo jumbo creates entry points to syscalls in _AIX - -lpioctl syscall -lsetpag syscall diff --git a/lib/kafs/afslib.c b/lib/kafs/afslib.c deleted file mode 100644 index f2ef8481e..000000000 --- a/lib/kafs/afslib.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* - * This file is only used with AIX - */ - -#include "kafs_locl.h" - -int -aix_pioctl(char *a_path, - int o_opcode, - struct ViceIoctl *a_paramsP, - int a_followSymlinks) -{ - return lpioctl(a_path, o_opcode, a_paramsP, a_followSymlinks); -} - -int -aix_setpag(void) -{ - return lsetpag(); -} diff --git a/lib/kafs/afslib.exp b/lib/kafs/afslib.exp deleted file mode 100644 index f28871770..000000000 --- a/lib/kafs/afslib.exp +++ /dev/null @@ -1,3 +0,0 @@ -#! -aix_pioctl -aix_setpag diff --git a/lib/kafs/afssys.c b/lib/kafs/afssys.c deleted file mode 100644 index b40062607..000000000 --- a/lib/kafs/afssys.c +++ /dev/null @@ -1,630 +0,0 @@ -/* - * Copyright (c) 1995 - 2000, 2002, 2004, 2005 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "kafs_locl.h" - -struct procdata { - unsigned long param4; - unsigned long param3; - unsigned long param2; - unsigned long param1; - unsigned long syscall; -}; -#ifdef __GNU__ -#define _IOT_procdata _IOT(_IOTS(long), 5, 0, 0, 0, 0) -#define VIOC_SYSCALL_PROC _IOW('C', 1, struct procdata) -#else -#define VIOC_SYSCALL_PROC _IOW('C', 1, void *) -#endif - -struct devdata { - unsigned long syscall; - unsigned long param1; - unsigned long param2; - unsigned long param3; - unsigned long param4; - unsigned long param5; - unsigned long param6; - unsigned long retval; -}; -#ifdef __GNU__ -#define _IOT_devdata _IOT(_IOTS(long), 8, 0, 0, 0, 0) -#endif -#ifdef _IOWR -#define VIOC_SYSCALL_DEV _IOWR('C', 2, struct devdata) -#define VIOC_SYSCALL_DEV_OPENAFS _IOWR('C', 1, struct devdata) -#endif - -#ifdef _IOW -#ifdef _ILP32 -struct sundevdata { - uint32_t param6; - uint32_t param5; - uint32_t param4; - uint32_t param3; - uint32_t param2; - uint32_t param1; - uint32_t syscall; -}; -#define VIOC_SUN_SYSCALL_DEV _IOW('C', 2, struct sundevdata) -#else -struct sundevdata { - uint64_t param6; - uint64_t param5; - uint64_t param4; - uint64_t param3; - uint64_t param2; - uint64_t param1; - uint64_t syscall; -}; -#define VIOC_SUN_SYSCALL_DEV _IOW('C', 1, struct sundevdata) -#endif -#endif /* _IOW */ - - -int _kafs_debug; /* this should be done in a better way */ - -#define UNKNOWN_ENTRY_POINT (-1) -#define NO_ENTRY_POINT 0 -#define SINGLE_ENTRY_POINT 1 -#define MULTIPLE_ENTRY_POINT 2 -#define SINGLE_ENTRY_POINT2 3 -#define SINGLE_ENTRY_POINT3 4 -#define LINUX_PROC_POINT 5 -#define AIX_ENTRY_POINTS 6 -#define MACOS_DEV_POINT 7 -#define SUN_PROC_POINT 8 - -static int afs_entry_point = UNKNOWN_ENTRY_POINT; -#if defined(AFS_SYSCALL) || defined(AFS_SYSCALL2) || defined(AFS_SYSCALL3) || defined(AFS_PIOCTL) -static int afs_syscalls[2]; -#endif -static char *afs_ioctlpath; -static unsigned long afs_ioctlnum; - -/* Magic to get AIX syscalls to work */ -#ifdef _AIX - -static int (*Pioctl)(char*, int, struct ViceIoctl*, int); -static int (*Setpag)(void); - -#include "dlfcn.h" - -/* - * - */ - -static int -try_aix(void) -{ -#ifdef STATIC_AFS_SYSCALLS - Pioctl = aix_pioctl; - Setpag = aix_setpag; -#else - void *ptr; - char path[MaxPathLen], *p; - /* - * If we are root or running setuid don't trust AFSLIBPATH! - */ - if (getuid() != 0 && (p = secure_getenv("AFSLIBPATH")) != NULL) - strlcpy(path, p, sizeof(path)); - else - snprintf(path, sizeof(path), "%s/afslib.so", LIBDIR); - - ptr = dlopen(path, RTLD_NOW); - if(ptr == NULL) { - if(_kafs_debug) { - if(errno == ENOEXEC && (p = dlerror()) != NULL) - fprintf(stderr, "dlopen(%s): %s\n", path, p); - else if (errno != ENOENT) - fprintf(stderr, "dlopen(%s): %s\n", path, strerror(errno)); - } - return 1; - } - Setpag = (int (*)(void))dlsym(ptr, "aix_setpag"); - Pioctl = (int (*)(char*, int, - struct ViceIoctl*, int))dlsym(ptr, "aix_pioctl"); -#endif - afs_entry_point = AIX_ENTRY_POINTS; - return 0; -} -#endif /* _AIX */ - -/* - * This probably only works under Solaris and could get confused if - * there's a /etc/name_to_sysnum file. - */ - -#if defined(AFS_SYSCALL) || defined(AFS_SYSCALL2) || defined(AFS_SYSCALL3) - -#define _PATH_ETC_NAME_TO_SYSNUM "/etc/name_to_sysnum" - -static int -map_syscall_name_to_number (const char *str, int *res) -{ - FILE *f; - char buf[256]; - size_t str_len = strlen (str); - - f = fopen (_PATH_ETC_NAME_TO_SYSNUM, "r"); - if (f == NULL) - return -1; - while (fgets (buf, sizeof(buf), f) != NULL) { - if (buf[0] == '#') - continue; - - if (strncmp (str, buf, str_len) == 0) { - char *begptr = buf + str_len; - char *endptr; - long val = strtol (begptr, &endptr, 0); - - if (val != 0 && endptr != begptr) { - fclose (f); - *res = val; - return 0; - } - } - } - fclose (f); - return -1; -} -#endif - -static int -try_ioctlpath(const char *path, unsigned long ioctlnum, int entrypoint) -{ - int fd, ret, saved_errno; - - fd = open(path, O_RDWR); - if (fd < 0) - return 1; - switch (entrypoint) { - case LINUX_PROC_POINT: { - struct procdata data = { 0, 0, 0, 0, AFSCALL_PIOCTL }; - data.param2 = (unsigned long)VIOCGETTOK; - ret = ioctl(fd, ioctlnum, &data); - break; - } - case MACOS_DEV_POINT: { - struct devdata data = { AFSCALL_PIOCTL, 0, 0, 0, 0, 0, 0, 0 }; - data.param2 = (unsigned long)VIOCGETTOK; - ret = ioctl(fd, ioctlnum, &data); - break; - } - case SUN_PROC_POINT: { - struct sundevdata data = { 0, 0, 0, 0, 0, 0, AFSCALL_PIOCTL }; - data.param2 = (unsigned long)VIOCGETTOK; - ret = ioctl(fd, ioctlnum, &data); - break; - } - default: - abort(); - } - saved_errno = errno; - close(fd); - /* - * Be quite liberal in what error are ok, the first is the one - * that should trigger given that params is NULL. - */ - if (ret && - (saved_errno != EFAULT && - saved_errno != EDOM && - saved_errno != ENOTCONN)) - return 1; - afs_ioctlnum = ioctlnum; - afs_ioctlpath = strdup(path); - if (afs_ioctlpath == NULL) - return 1; - afs_entry_point = entrypoint; - return 0; -} - -static int -do_ioctl(void *data) -{ - int fd, ret, saved_errno; - fd = open(afs_ioctlpath, O_RDWR); - if (fd < 0) { - errno = EINVAL; - return -1; - } - ret = ioctl(fd, afs_ioctlnum, data); - saved_errno = errno; - close(fd); - errno = saved_errno; - return ret; -} - -int -k_pioctl(char *a_path, - int o_opcode, - struct ViceIoctl *a_paramsP, - int a_followSymlinks) -{ -#ifndef NO_AFS - switch(afs_entry_point){ -#if defined(AFS_SYSCALL) || defined(AFS_SYSCALL2) || defined(AFS_SYSCALL3) - case SINGLE_ENTRY_POINT: - case SINGLE_ENTRY_POINT2: - case SINGLE_ENTRY_POINT3: - return syscall(afs_syscalls[0], AFSCALL_PIOCTL, - a_path, o_opcode, a_paramsP, a_followSymlinks); -#endif -#if defined(AFS_PIOCTL) - case MULTIPLE_ENTRY_POINT: - return syscall(afs_syscalls[0], - a_path, o_opcode, a_paramsP, a_followSymlinks); -#endif - case LINUX_PROC_POINT: { - struct procdata data = { 0, 0, 0, 0, AFSCALL_PIOCTL }; - data.param1 = (unsigned long)a_path; - data.param2 = (unsigned long)o_opcode; - data.param3 = (unsigned long)a_paramsP; - data.param4 = (unsigned long)a_followSymlinks; - return do_ioctl(&data); - } - case MACOS_DEV_POINT: { - struct devdata data = { AFSCALL_PIOCTL, 0, 0, 0, 0, 0, 0, 0 }; - int ret; - - data.param1 = (unsigned long)a_path; - data.param2 = (unsigned long)o_opcode; - data.param3 = (unsigned long)a_paramsP; - data.param4 = (unsigned long)a_followSymlinks; - - ret = do_ioctl(&data); - if (ret) - return ret; - - return data.retval; - } - case SUN_PROC_POINT: { - struct sundevdata data = { 0, 0, 0, 0, 0, 0, AFSCALL_PIOCTL }; - data.param1 = (unsigned long)a_path; - data.param2 = (unsigned long)o_opcode; - data.param3 = (unsigned long)a_paramsP; - data.param4 = (unsigned long)a_followSymlinks; - return do_ioctl(&data); - } -#ifdef _AIX - case AIX_ENTRY_POINTS: - return Pioctl(a_path, o_opcode, a_paramsP, a_followSymlinks); -#endif - } - errno = ENOSYS; -#ifdef SIGSYS - kill(getpid(), SIGSYS); /* You lose! */ -#endif -#endif /* NO_AFS */ - return -1; -} - -int -k_afs_cell_of_file(const char *path, char *cell, int len) -{ - struct ViceIoctl parms; - parms.in = NULL; - parms.in_size = 0; - parms.out = cell; - parms.out_size = len; - return k_pioctl(rk_UNCONST(path), VIOC_FILE_CELL_NAME, &parms, 1); -} - -int -k_unlog(void) -{ - struct ViceIoctl parms; - memset(&parms, 0, sizeof(parms)); - return k_pioctl(0, VIOCUNLOG, &parms, 0); -} - -int -k_setpag(void) -{ -#ifndef NO_AFS - switch(afs_entry_point){ -#if defined(AFS_SYSCALL) || defined(AFS_SYSCALL2) || defined(AFS_SYSCALL3) - case SINGLE_ENTRY_POINT: - case SINGLE_ENTRY_POINT2: - case SINGLE_ENTRY_POINT3: - return syscall(afs_syscalls[0], AFSCALL_SETPAG); -#endif -#if defined(AFS_PIOCTL) - case MULTIPLE_ENTRY_POINT: - return syscall(afs_syscalls[1]); -#endif - case LINUX_PROC_POINT: { - struct procdata data = { 0, 0, 0, 0, AFSCALL_SETPAG }; - return do_ioctl(&data); - } - case MACOS_DEV_POINT: { - struct devdata data = { AFSCALL_SETPAG, 0, 0, 0, 0, 0, 0, 0 }; - int ret = do_ioctl(&data); - if (ret) - return ret; - return data.retval; - } - case SUN_PROC_POINT: { - struct sundevdata data = { 0, 0, 0, 0, 0, 0, AFSCALL_SETPAG }; - return do_ioctl(&data); - } -#ifdef _AIX - case AIX_ENTRY_POINTS: - return Setpag(); -#endif - } - - errno = ENOSYS; -#ifdef SIGSYS - kill(getpid(), SIGSYS); /* You lose! */ -#endif -#endif /* NO_AFS */ - return -1; -} - -static jmp_buf catch_SIGSYS; - -#ifdef SIGSYS - -static RETSIGTYPE -SIGSYS_handler(int sig) -{ - errno = 0; - signal(SIGSYS, SIGSYS_handler); /* Need to reinstall handler on SYSV */ - longjmp(catch_SIGSYS, 1); -} - -#endif - -/* - * Try to see if `syscall' is a pioctl. Return 0 iff succesful. - */ - -#if defined(AFS_SYSCALL) || defined(AFS_SYSCALL2) || defined(AFS_SYSCALL3) -static int -try_one (int syscall_num) -{ - struct ViceIoctl parms; - memset(&parms, 0, sizeof(parms)); - - if (setjmp(catch_SIGSYS) == 0) { - syscall(syscall_num, AFSCALL_PIOCTL, - 0, VIOCSETTOK, &parms, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - if (errno == EINVAL) { - afs_entry_point = SINGLE_ENTRY_POINT; - afs_syscalls[0] = syscall_num; - return 0; - } - } - return 1; -} -#endif - -/* - * Try to see if `syscall_pioctl' is a pioctl syscall. Return 0 iff - * succesful. - * - */ - -#ifdef AFS_PIOCTL -static int -try_two (int syscall_pioctl, int syscall_setpag) -{ - struct ViceIoctl parms; - memset(&parms, 0, sizeof(parms)); - - if (setjmp(catch_SIGSYS) == 0) { - syscall(syscall_pioctl, - 0, VIOCSETTOK, &parms, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - if (errno == EINVAL) { - afs_entry_point = MULTIPLE_ENTRY_POINT; - afs_syscalls[0] = syscall_pioctl; - afs_syscalls[1] = syscall_setpag; - return 0; - } - } - return 1; -} -#endif - -int -k_hasafs(void) -{ -#if !defined(NO_AFS) && defined(SIGSYS) - RETSIGTYPE (*saved_func)(int); -#endif - int saved_errno, ret; - char *env = NULL; - - env = secure_getenv("AFS_SYSCALL"); - - /* - * Already checked presence of AFS syscalls? - */ - if (afs_entry_point != UNKNOWN_ENTRY_POINT) - return afs_entry_point != NO_ENTRY_POINT; - - /* - * Probe kernel for AFS specific syscalls, - * they (currently) come in two flavors. - * If the syscall is absent we recive a SIGSYS. - */ - afs_entry_point = NO_ENTRY_POINT; - - saved_errno = errno; -#ifndef NO_AFS -#ifdef SIGSYS - saved_func = signal(SIGSYS, SIGSYS_handler); -#endif - if (env && strstr(env, "..") == NULL) { - - if (strncmp("/proc/", env, 6) == 0) { - if (try_ioctlpath(env, VIOC_SYSCALL_PROC, LINUX_PROC_POINT) == 0) - goto done; - } - if (strncmp("/dev/", env, 5) == 0) { -#ifdef VIOC_SYSCALL_DEV - if (try_ioctlpath(env, VIOC_SYSCALL_DEV, MACOS_DEV_POINT) == 0) - goto done; -#endif -#ifdef VIOC_SYSCALL_DEV_OPENAFS - if (try_ioctlpath(env,VIOC_SYSCALL_DEV_OPENAFS,MACOS_DEV_POINT) ==0) - goto done; -#endif - } - } - - ret = try_ioctlpath("/proc/fs/openafs/afs_ioctl", - VIOC_SYSCALL_PROC, LINUX_PROC_POINT); - if (ret == 0) - goto done; - ret = try_ioctlpath("/proc/fs/nnpfs/afs_ioctl", - VIOC_SYSCALL_PROC, LINUX_PROC_POINT); - if (ret == 0) - goto done; - -#ifdef VIOC_SYSCALL_DEV_OPENAFS - ret = try_ioctlpath("/dev/openafs_ioctl", - VIOC_SYSCALL_DEV_OPENAFS, MACOS_DEV_POINT); - if (ret == 0) - goto done; -#endif -#ifdef VIOC_SYSCALL_DEV - ret = try_ioctlpath("/dev/nnpfs_ioctl", VIOC_SYSCALL_DEV, MACOS_DEV_POINT); - if (ret == 0) - goto done; -#endif -#ifdef VIOC_SUN_SYSCALL_DEV - ret = try_ioctlpath("/dev/afs", VIOC_SUN_SYSCALL_DEV, SUN_PROC_POINT); - if (ret == 0) - goto done; -#endif - - -#if defined(AFS_SYSCALL) || defined(AFS_SYSCALL2) || defined(AFS_SYSCALL3) - { - int tmp; - - if (env != NULL) { - if (sscanf (env, "%d", &tmp) == 1) { - if (try_one (tmp) == 0) - goto done; - } else { - char *end = NULL; - char *p; - char *s = strdup (env); - - if (s != NULL) { - for (p = strtok_r (s, ",", &end); - p != NULL; - p = strtok_r (NULL, ",", &end)) { - if (map_syscall_name_to_number (p, &tmp) == 0) - if (try_one (tmp) == 0) { - free (s); - goto done; - } - } - free (s); - } - } - } - } -#endif /* AFS_SYSCALL || AFS_SYSCALL2 || AFS_SYSCALL3 */ - -#ifdef AFS_SYSCALL - if (try_one (AFS_SYSCALL) == 0) - goto done; -#endif /* AFS_SYSCALL */ - -#ifdef AFS_PIOCTL - { - int tmp[2]; - - if (env != NULL && sscanf (env, "%d%d", &tmp[0], &tmp[1]) == 2) - if (try_two (tmp[0], tmp[1]) == 2) - goto done; - } -#endif /* AFS_PIOCTL */ - -#ifdef AFS_PIOCTL - if (try_two (AFS_PIOCTL, AFS_SETPAG) == 0) - goto done; -#endif /* AFS_PIOCTL */ - -#ifdef AFS_SYSCALL2 - if (try_one (AFS_SYSCALL2) == 0) - goto done; -#endif /* AFS_SYSCALL2 */ - -#ifdef AFS_SYSCALL3 - if (try_one (AFS_SYSCALL3) == 0) - goto done; -#endif /* AFS_SYSCALL3 */ - -#ifdef _AIX -#if 0 - if (env != NULL) { - char *pos = NULL; - char *pioctl_name; - char *setpag_name; - - pioctl_name = strtok_r (env, ", \t", &pos); - if (pioctl_name != NULL) { - setpag_name = strtok_r (NULL, ", \t", &pos); - if (setpag_name != NULL) - if (try_aix (pioctl_name, setpag_name) == 0) - goto done; - } - } -#endif - - if(try_aix() == 0) - goto done; -#endif - - -done: -#ifdef SIGSYS - signal(SIGSYS, saved_func); -#endif -#endif /* NO_AFS */ - errno = saved_errno; - return afs_entry_point != NO_ENTRY_POINT; -} - -int -k_hasafs_recheck(void) -{ - afs_entry_point = UNKNOWN_ENTRY_POINT; - return k_hasafs(); -} diff --git a/lib/kafs/afssysdefs.h b/lib/kafs/afssysdefs.h deleted file mode 100644 index 18734e36b..000000000 --- a/lib/kafs/afssysdefs.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 1995 - 2003 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* $Id$ */ - -/* - * This section is for machines using single entry point AFS syscalls! - * and/or - * This section is for machines using multiple entry point AFS syscalls! - * - * SunOS 4 is an example of single entry point and sgi of multiple - * entry point syscalls. - */ - -#if SunOS == 40 -#define AFS_SYSCALL 31 -#endif - -#if SunOS >= 50 && SunOS < 57 -#define AFS_SYSCALL 105 -#endif - -#if SunOS == 57 -#define AFS_SYSCALL 73 -#endif - -#if SunOS >= 58 -#define AFS_SYSCALL 65 -#endif - -#if defined(__hpux) -#define AFS_SYSCALL 50 -#define AFS_SYSCALL2 49 -#define AFS_SYSCALL3 48 -#endif - -#if defined(_AIX) -/* _AIX is too weird */ -#endif - -#if defined(__sgi) -#define AFS_PIOCTL (64+1000) -#define AFS_SETPAG (65+1000) -#endif - -#if defined(__osf__) -#define AFS_SYSCALL 232 -#define AFS_SYSCALL2 258 -#endif - -#if defined(__ultrix) -#define AFS_SYSCALL 31 -#endif - -#if defined(__FreeBSD__) -#if __FreeBSD_version >= 500000 -#define AFS_SYSCALL 339 -#else -#define AFS_SYSCALL 210 -#endif -#endif /* __FreeBSD__ */ - -#ifdef __DragonFly__ -#ifndef AFS_SYSCALL -#define AFS_SYSCALL 339 -#endif -#endif - -#ifdef __OpenBSD__ -#define AFS_SYSCALL 208 -#endif - -#if defined(__NetBSD__) -#define AFS_SYSCALL 210 -#endif - -#ifdef SYS_afs_syscall -#define AFS_SYSCALL3 SYS_afs_syscall -#endif diff --git a/lib/kafs/common.c b/lib/kafs/common.c deleted file mode 100644 index ff42cf7ec..000000000 --- a/lib/kafs/common.c +++ /dev/null @@ -1,469 +0,0 @@ -/* - * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "kafs_locl.h" - -#define AUTH_SUPERUSER "afs" - -/* - * Here only ASCII characters are relevant. - */ - -#define IsAsciiLower(c) ('a' <= (c) && (c) <= 'z') - -#define ToAsciiUpper(c) ((c) - 'a' + 'A') - -static void (*kafs_verbose)(void *, const char *); -static void *kafs_verbose_ctx; - -void -_kafs_foldup(char *a, const char *b) -{ - for (; *b; a++, b++) - if (IsAsciiLower(*b)) - *a = ToAsciiUpper(*b); - else - *a = *b; - *a = '\0'; -} - -void -kafs_set_verbose(void (*f)(void *, const char *), void *ctx) -{ - if (f) { - kafs_verbose = f; - kafs_verbose_ctx = ctx; - } -} - -int -kafs_settoken_rxkad(const char *cell, struct ClearToken *ct, - void *ticket, size_t ticket_len) -{ - struct ViceIoctl parms; - char buf[2048], *t; - int32_t sizeof_x; - - t = buf; - /* - * length of secret token followed by secret token - */ - sizeof_x = ticket_len; - memcpy(t, &sizeof_x, sizeof(sizeof_x)); - t += sizeof(sizeof_x); - memcpy(t, ticket, sizeof_x); - t += sizeof_x; - /* - * length of clear token followed by clear token - */ - sizeof_x = sizeof(*ct); - memcpy(t, &sizeof_x, sizeof(sizeof_x)); - t += sizeof(sizeof_x); - memcpy(t, ct, sizeof_x); - t += sizeof_x; - - /* - * do *not* mark as primary cell - */ - sizeof_x = 0; - memcpy(t, &sizeof_x, sizeof(sizeof_x)); - t += sizeof(sizeof_x); - /* - * follow with cell name - */ - sizeof_x = strlen(cell) + 1; - memcpy(t, cell, sizeof_x); - t += sizeof_x; - - /* - * Build argument block - */ - parms.in = buf; - parms.in_size = t - buf; - parms.out = 0; - parms.out_size = 0; - - return k_pioctl(0, VIOCSETTOK, &parms, 0); -} - -void -_kafs_fixup_viceid(struct ClearToken *ct, uid_t uid) -{ -#define ODD(x) ((x) & 1) - /* According to Transarc conventions ViceId is valid iff - * (EndTimestamp - BeginTimestamp) is odd. By decrementing EndTime - * the transformations: - * - * (issue_date, life) -> (StartTime, EndTime) -> (issue_date, life) - * preserves the original values. - */ - if (uid != 0) /* valid ViceId */ - { - if (!ODD(ct->EndTimestamp - ct->BeginTimestamp)) - ct->EndTimestamp--; - } - else /* not valid ViceId */ - { - if (ODD(ct->EndTimestamp - ct->BeginTimestamp)) - ct->EndTimestamp--; - } -} - -/* Try to get a db-server for an AFS cell from a AFSDB record */ - -static int -dns_find_cell(const char *cell, char *dbserver, size_t len) -{ - struct rk_dns_reply *r; - int ok = -1; - r = rk_dns_lookup(cell, "afsdb"); - if(r){ - struct rk_resource_record *rr = r->head; - while(rr){ - if(rr->type == rk_ns_t_afsdb && rr->u.afsdb->preference == 1){ - strlcpy(dbserver, - rr->u.afsdb->domain, - len); - ok = 0; - break; - } - rr = rr->next; - } - rk_dns_free_data(r); - } - return ok; -} - - -/* - * Try to find the cells we should try to klog to in "file". - */ -static void -find_cells(const char *file, char ***cells, int *idx) -{ - FILE *f; - char cell[64]; - int i; - int ind = *idx; - - f = fopen(file, "r"); - if (f == NULL) - return; - while (fgets(cell, sizeof(cell), f)) { - char *t; - t = cell + strlen(cell); - for (; t >= cell; t--) - if (*t == '\n' || *t == '\t' || *t == ' ') - *t = 0; - if (cell[0] == '\0' || cell[0] == '#') - continue; - for(i = 0; i < ind; i++) - if(strcmp((*cells)[i], cell) == 0) - break; - if(i == ind){ - char **tmp; - - tmp = realloc(*cells, (ind + 1) * sizeof(**cells)); - if (tmp == NULL) - break; - *cells = tmp; - (*cells)[ind] = strdup(cell); - if ((*cells)[ind] == NULL) - break; - ++ind; - } - } - fclose(f); - *idx = ind; -} - -/* - * Get tokens for all cells[] - */ -static int -afslog_cells(struct kafs_data *data, char **cells, int max, uid_t uid, - const char *homedir) -{ - int ret = 0; - int i; - for (i = 0; i < max; i++) { - int er = (*data->afslog_uid)(data, cells[i], 0, uid, homedir); - if (er) - ret = er; - } - return ret; -} - -int -_kafs_afslog_all_local_cells(struct kafs_data *data, - uid_t uid, const char *homedir) -{ - int ret; - char **cells = NULL; - int idx = 0; - - if (homedir == NULL) - homedir = getenv("HOME"); - if (homedir != NULL) { - char home[MaxPathLen]; - snprintf(home, sizeof(home), "%s/.TheseCells", homedir); - find_cells(home, &cells, &idx); - } - find_cells(_PATH_THESECELLS, &cells, &idx); - find_cells(_PATH_THISCELL, &cells, &idx); - find_cells(_PATH_ARLA_THESECELLS, &cells, &idx); - find_cells(_PATH_ARLA_THISCELL, &cells, &idx); - find_cells(_PATH_OPENAFS_DEBIAN_THESECELLS, &cells, &idx); - find_cells(_PATH_OPENAFS_DEBIAN_THISCELL, &cells, &idx); - find_cells(_PATH_OPENAFS_MACOSX_THESECELLS, &cells, &idx); - find_cells(_PATH_OPENAFS_MACOSX_THISCELL, &cells, &idx); - find_cells(_PATH_ARLA_DEBIAN_THESECELLS, &cells, &idx); - find_cells(_PATH_ARLA_DEBIAN_THISCELL, &cells, &idx); - find_cells(_PATH_ARLA_OPENBSD_THESECELLS, &cells, &idx); - find_cells(_PATH_ARLA_OPENBSD_THISCELL, &cells, &idx); - - ret = afslog_cells(data, cells, idx, uid, homedir); - while(idx > 0) - free(cells[--idx]); - free(cells); - return ret; -} - - -static int -file_find_cell(struct kafs_data *data, - const char *cell, char **realm, int exact) -{ - FILE *F; - char buf[1024]; - char *p; - int ret = -1; - - if ((F = fopen(_PATH_CELLSERVDB, "r")) - || (F = fopen(_PATH_ARLA_CELLSERVDB, "r")) - || (F = fopen(_PATH_OPENAFS_DEBIAN_CELLSERVDB, "r")) - || (F = fopen(_PATH_OPENAFS_MACOSX_CELLSERVDB, "r")) - || (F = fopen(_PATH_ARLA_DEBIAN_CELLSERVDB, "r"))) { - while (fgets(buf, sizeof(buf), F)) { - int cmp; - - if (buf[0] != '>') - continue; /* Not a cell name line, try next line */ - p = buf; - strsep(&p, " \t\n#"); - - if (exact) - cmp = strcmp(buf + 1, cell); - else - cmp = strncmp(buf + 1, cell, strlen(cell)); - - if (cmp == 0) { - /* - * We found the cell name we're looking for. - * Read next line on the form ip-address '#' hostname - */ - if (fgets(buf, sizeof(buf), F) == NULL) - break; /* Read failed, give up */ - p = strchr(buf, '#'); - if (p == NULL) - break; /* No '#', give up */ - p++; - if (buf[strlen(buf) - 1] == '\n') - buf[strlen(buf) - 1] = '\0'; - *realm = (*data->get_realm)(data, p); - if (*realm && **realm != '\0') - ret = 0; - break; /* Won't try any more */ - } - } - fclose(F); - } - return ret; -} - -/* Find the realm associated with cell. Do this by opening CellServDB - file and getting the realm-of-host for the first VL-server for the - cell. - - This does not work when the VL-server is living in one realm, but - the cell it is serving is living in another realm. - - Return 0 on success, -1 otherwise. - */ - -int -_kafs_realm_of_cell(struct kafs_data *data, - const char *cell, char **realm) -{ - char buf[1024]; - int ret; - - ret = file_find_cell(data, cell, realm, 1); - if (ret == 0) - return ret; - if (dns_find_cell(cell, buf, sizeof(buf)) == 0) { - *realm = (*data->get_realm)(data, buf); - if(*realm != NULL) - return 0; - } - return file_find_cell(data, cell, realm, 0); -} - -static int -_kafs_try_get_cred(struct kafs_data *data, const char *user, const char *cell, - const char *realm, uid_t uid, struct kafs_token *kt) -{ - int ret; - - ret = (*data->get_cred)(data, user, cell, realm, uid, kt); - if (kafs_verbose) { - const char *estr = (*data->get_error)(data, ret); - char *str; - int aret; - - aret = asprintf(&str, "%s tried afs%s%s@%s -> %s (%d)", - data->name, cell ? "/" : "", - cell ? cell : "", realm, estr ? estr : "unknown", ret); - if (aret != -1) { - (*kafs_verbose)(kafs_verbose_ctx, str); - free(str); - } else { - (*kafs_verbose)(kafs_verbose_ctx, "out of memory"); - } - if (estr) - (*data->free_error)(data, estr); - } - - return ret; -} - - -int -_kafs_get_cred(struct kafs_data *data, - const char *cell, - const char *realm_hint, - const char *realm, - uid_t uid, - struct kafs_token *kt) -{ - int ret = -1; - char *vl_realm; - char CELL[64]; - - /* We're about to find the realm that holds the key for afs in - * the specified cell. The problem is that null-instance - * afs-principals are common and that hitting the wrong realm might - * yield the wrong afs key. The following assumptions were made. - * - * Any realm passed to us is preferred. - * - * If there is a realm with the same name as the cell, it is most - * likely the correct realm to talk to. - * - * In most (maybe even all) cases the database servers of the cell - * will live in the realm we are looking for. - * - * Try the local realm, but if the previous cases fail, this is - * really a long shot. - * - */ - - /* comments on the ordering of these tests */ - - /* If the user passes a realm, she probably knows something we don't - * know and we should try afs@realm_hint. - */ - - if (realm_hint) { - ret = _kafs_try_get_cred(data, AUTH_SUPERUSER, - cell, realm_hint, uid, kt); - if (ret == 0) return 0; - ret = _kafs_try_get_cred(data, AUTH_SUPERUSER, - NULL, realm_hint, uid, kt); - if (ret == 0) return 0; - } - - _kafs_foldup(CELL, cell); - - /* - * If the AFS servers have a file /usr/afs/etc/krb.conf containing - * REALM we still don't have to resort to cross-cell authentication. - * Try afs.cell@REALM. - */ - ret = _kafs_try_get_cred(data, AUTH_SUPERUSER, - cell, realm, uid, kt); - if (ret == 0) return 0; - - /* - * If cell == realm we don't need no cross-cell authentication. - * Try afs@REALM. - */ - if (strcmp(CELL, realm) == 0) { - ret = _kafs_try_get_cred(data, AUTH_SUPERUSER, - NULL, realm, uid, kt); - if (ret == 0) return 0; - } - - /* - * We failed to get ``first class tickets'' for afs, - * fall back to cross-cell authentication. - * Try afs@CELL. - * Try afs.cell@CELL. - */ - ret = _kafs_try_get_cred(data, AUTH_SUPERUSER, - NULL, CELL, uid, kt); - if (ret == 0) return 0; - ret = _kafs_try_get_cred(data, AUTH_SUPERUSER, - cell, CELL, uid, kt); - if (ret == 0) return 0; - - /* - * Perhaps the cell doesn't correspond to any realm? - * Use realm of first volume location DB server. - * Try afs.cell@VL_REALM. - * Try afs@VL_REALM??? - */ - if (_kafs_realm_of_cell(data, cell, &vl_realm) == 0 - && strcmp(vl_realm, realm) != 0 - && strcmp(vl_realm, CELL) != 0) { - ret = _kafs_try_get_cred(data, AUTH_SUPERUSER, - cell, vl_realm, uid, kt); - if (ret) - ret = _kafs_try_get_cred(data, AUTH_SUPERUSER, - NULL, vl_realm, uid, kt); - free(vl_realm); - if (ret == 0) return 0; - } - - return ret; -} diff --git a/lib/kafs/kafs.3 b/lib/kafs/kafs.3 deleted file mode 100644 index d44e35e8c..000000000 --- a/lib/kafs/kafs.3 +++ /dev/null @@ -1,296 +0,0 @@ -.\" Copyright (c) 1998 - 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$ -.\" -.Dd May 1, 2006 -.Os HEIMDAL -.Dt KAFS 3 -.Sh NAME -.Nm k_hasafs , -.Nm k_hasafs_recheck , -.Nm k_pioctl , -.Nm k_unlog , -.Nm k_setpag , -.Nm k_afs_cell_of_file , -.Nm kafs_set_verbose , -.Nm kafs_settoken_rxkad , -.Nm kafs_settoken , -.Nm krb_afslog , -.Nm krb_afslog_uid , -.Nm kafs_settoken5 , -.Nm krb5_afslog , -.Nm krb5_afslog_uid -.Nd AFS library -.Sh LIBRARY -AFS cache manager access library (libkafs, -lkafs) -.Sh SYNOPSIS -.In kafs.h -.Ft int -.Fn k_afs_cell_of_file "const char *path" "char *cell" "int len" -.Ft int -.Fn k_hasafs "void" -.Ft int -.Fn k_hasafs_recheck "void" -.Ft int -.Fn k_pioctl "char *a_path" "int o_opcode" "struct ViceIoctl *a_paramsP" "int a_followSymlinks" -.Ft int -.Fn k_setpag "void" -.Ft int -.Fn k_unlog "void" -.Ft void -.Fn kafs_set_verbose "void (*func)(void *, const char *, int)" "void *" -.Ft int -.Fn kafs_settoken_rxkad "const char *cell" "struct ClearToken *token" "void *ticket" "size_t ticket_len" -.Ft int -.Fn kafs_settoken "const char *cell" "uid_t uid" "CREDENTIALS *c" -.Fn krb_afslog "char *cell" "char *realm" -.Ft int -.Fn krb_afslog_uid "char *cell" "char *realm" "uid_t uid" -.Ft krb5_error_code -.Fn krb5_afslog_uid "krb5_context context" "krb5_ccache id" "const char *cell" "krb5_const_realm realm" "uid_t uid" -.Ft int -.Fn kafs_settoken5 "const char *cell" "uid_t uid" "krb5_creds *c" -.Ft krb5_error_code -.Fn krb5_afslog "krb5_context context" "krb5_ccache id" "const char *cell" "krb5_const_realm realm" -.Sh DESCRIPTION -.Fn k_hasafs -initializes some library internal structures, and tests for the -presence of AFS in the kernel, none of the other functions should be -called before -.Fn k_hasafs -is called, or if it fails. -.Pp -.Fn k_hasafs_recheck -forces a recheck if a AFS client has started since last time -.Fn k_hasafs -or -.Fn k_hasafs_recheck -was called. -.Pp -.Fn kafs_set_verbose -set a log function that will be called each time the kafs library does -something important so that the application using libkafs can output -verbose logging. -Calling the function -.Fa kafs_set_verbose -with the function argument set to -.Dv NULL -will stop libkafs from calling the logging function (if set). -.Pp -.Fn kafs_settoken_rxkad -set -.Li rxkad -with the -.Fa token -and -.Fa ticket -(that have the length -.Fa ticket_len ) -for a given -.Fa cell . -.Pp -.Fn kafs_settoken -and -.Fn kafs_settoken5 -work the same way as -.Fn kafs_settoken_rxkad -but internally converts the Kerberos 4 or 5 credential to a afs -cleartoken and ticket. -.Pp -.Fn krb_afslog , -and -.Fn krb_afslog_uid -obtains new tokens (and possibly tickets) for the specified -.Fa cell -and -.Fa realm . -If -.Fa cell -is -.Dv NULL , -the local cell is used. If -.Fa realm -is -.Dv NULL , -the function tries to guess what realm to use. Unless you have some good knowledge of what cell or realm to use, you should pass -.Dv NULL . -.Fn krb_afslog -will use the real user-id for the -.Dv ViceId -field in the token, -.Fn krb_afslog_uid -will use -.Fa uid . -.Pp -.Fn krb5_afslog , -and -.Fn krb5_afslog_uid -are the Kerberos 5 equivalents of -.Fn krb_afslog , -and -.Fn krb_afslog_uid . -.Pp -.Fn krb5_afslog , -.Fn kafs_settoken5 -can be configured to behave differently via a -.Nm krb5_appdefault -option -.Li afs-use-524 -in -.Pa krb5.conf . -Possible values for -.Li afs-use-524 -are: -.Bl -tag -width local -.It yes -use the 524 server in the realm to convert the ticket -.It no -use the Kerberos 5 ticket directly, can be used with if the afs cell -support 2b token. -.It local, 2b -convert the Kerberos 5 credential to a 2b token locally (the same work -as a 2b 524 server should have done). -.El -.Pp -Example: -.Pp -.Bd -literal -[appdefaults] - SU.SE = { afs-use-524 = local } - PDC.KTH.SE = { afs-use-524 = yes } - afs-use-524 = yes -.Ed -.Pp -libkafs will use the -.Li libkafs -as application name when running the -.Nm krb5_appdefault -function call. -.Pp -The (uppercased) cell name is used as the realm to the -.Nm krb5_appdefault function. -.Pp -.\" The extra arguments are the ubiquitous context, and the cache id where -.\" to store any obtained tickets. Since AFS servers normally can't handle -.\" Kerberos 5 tickets directly, these functions will first obtain version -.\" 5 tickets for the requested cells, and then convert them to version 4 -.\" tickets, that can be stashed in the kernel. To convert tickets the -.\" .Fn krb524_convert_creds_kdc -.\" function will be used. -.\" .Pp -.Fn k_afs_cell_of_file -will in -.Fa cell -return the cell of a specified file, no more than -.Fa len -characters is put in -.Fa cell . -.Pp -.Fn k_pioctl -does a -.Fn pioctl -system call with the specified arguments. This function is equivalent to -.Fn lpioctl . -.Pp -.Fn k_setpag -initializes a new PAG. -.Pp -.Fn k_unlog -removes destroys all tokens in the current PAG. -.Sh RETURN VALUES -.Fn k_hasafs -returns 1 if AFS is present in the kernel, 0 otherwise. -.Fn krb_afslog -and -.Fn krb_afslog_uid -returns 0 on success, or a Kerberos error number on failure. -.Fn k_afs_cell_of_file , -.Fn k_pioctl , -.Fn k_setpag , -and -.Fn k_unlog -all return the value of the underlaying system call, 0 on success. -.Sh ENVIRONMENT -The following environment variable affect the mode of operation of -.Nm kafs : -.Bl -tag -width AFS_SYSCALL -.It Ev AFS_SYSCALL -Normally, -.Nm kafs -will try to figure out the correct system call(s) that are used by AFS -by itself. If it does not manage to do that, or does it incorrectly, -you can set this variable to the system call number or list of system -call numbers that should be used. -.El -.Sh EXAMPLES -The following code from -.Nm login -will obtain a new PAG and tokens for the local cell and the cell of -the users home directory. -.Bd -literal -if (k_hasafs()) { - char cell[64]; - k_setpag(); - if(k_afs_cell_of_file(pwd->pw_dir, cell, sizeof(cell)) == 0) - krb_afslog(cell, NULL); - krb_afslog(NULL, NULL); -} -.Ed -.Sh ERRORS -If any of these functions (apart from -.Fn k_hasafs ) -is called without AFS being present in the kernel, the process will -usually (depending on the operating system) receive a SIGSYS signal. -.Sh SEE ALSO -.Xr krb5_appdefault 3 , -.Xr krb5.conf 5 -.Rs -.%A Transarc Corporation -.%J AFS-3 Programmer's Reference -.%T File Server/Cache Manager Interface -.%D 1991 -.Re -.Sh FILES -libkafs will search for -.Pa ThisCell and -.Pa TheseCells -in the following locations: -.Pa /usr/vice/etc , -.Pa /etc/openafs , -.Pa /var/db/openafs/etc , -.Pa /usr/arla/etc , -.Pa /etc/arla , -and -.Pa /etc/afs -.Sh BUGS -.Ev AFS_SYSCALL -has no effect under AIX. diff --git a/lib/kafs/kafs.h b/lib/kafs/kafs.h deleted file mode 100644 index 6f6eb631d..000000000 --- a/lib/kafs/kafs.h +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (c) 1995 - 2001, 2003 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* $Id$ */ - -#ifndef __KAFS_H -#define __KAFS_H - -/* XXX must include krb5.h or krb.h */ - -/* sys/ioctl.h must be included manually before kafs.h */ - -/* - */ -#define AFSCALL_PIOCTL 20 -#define AFSCALL_SETPAG 21 - -#ifndef _VICEIOCTL -#ifdef __GNU__ -#define _IOT_ViceIoctl _IOT(_IOTS(caddr_t), 2, _IOTS(short), 2, 0, 0) -#endif -#define _VICEIOCTL(id) ((unsigned int ) _IOW('V', id, struct ViceIoctl)) -#define _AFSCIOCTL(id) ((unsigned int ) _IOW('C', id, struct ViceIoctl)) -#endif /* _VICEIOCTL */ - -#define VIOCSETAL _VICEIOCTL(1) -#define VIOCGETAL _VICEIOCTL(2) -#define VIOCSETTOK _VICEIOCTL(3) -#define VIOCGETVOLSTAT _VICEIOCTL(4) -#define VIOCSETVOLSTAT _VICEIOCTL(5) -#define VIOCFLUSH _VICEIOCTL(6) -#define VIOCGETTOK _VICEIOCTL(8) -#define VIOCUNLOG _VICEIOCTL(9) -#define VIOCCKSERV _VICEIOCTL(10) -#define VIOCCKBACK _VICEIOCTL(11) -#define VIOCCKCONN _VICEIOCTL(12) -#define VIOCWHEREIS _VICEIOCTL(14) -#define VIOCACCESS _VICEIOCTL(20) -#define VIOCUNPAG _VICEIOCTL(21) -#define VIOCGETFID _VICEIOCTL(22) -#define VIOCSETCACHESIZE _VICEIOCTL(24) -#define VIOCFLUSHCB _VICEIOCTL(25) -#define VIOCNEWCELL _VICEIOCTL(26) -#define VIOCGETCELL _VICEIOCTL(27) -#define VIOC_AFS_DELETE_MT_PT _VICEIOCTL(28) -#define VIOC_AFS_STAT_MT_PT _VICEIOCTL(29) -#define VIOC_FILE_CELL_NAME _VICEIOCTL(30) -#define VIOC_GET_WS_CELL _VICEIOCTL(31) -#define VIOC_AFS_MARINER_HOST _VICEIOCTL(32) -#define VIOC_GET_PRIMARY_CELL _VICEIOCTL(33) -#define VIOC_VENUSLOG _VICEIOCTL(34) -#define VIOC_GETCELLSTATUS _VICEIOCTL(35) -#define VIOC_SETCELLSTATUS _VICEIOCTL(36) -#define VIOC_FLUSHVOLUME _VICEIOCTL(37) -#define VIOC_AFS_SYSNAME _VICEIOCTL(38) -#define VIOC_EXPORTAFS _VICEIOCTL(39) -#define VIOCGETCACHEPARAMS _VICEIOCTL(40) -#define VIOC_GCPAGS _VICEIOCTL(48) - -#define VIOCGETTOK2 _AFSCIOCTL(7) -#define VIOCSETTOK2 _AFSCIOCTL(8) - -struct ViceIoctl { - caddr_t in, out; - unsigned short in_size; - unsigned short out_size; -}; - -struct ClearToken { - int32_t AuthHandle; - char HandShakeKey[8]; - int32_t ViceId; - int32_t BeginTimestamp; - int32_t EndTimestamp; -}; - -/* Use k_hasafs() to probe if the machine supports AFS syscalls. - The other functions will generate a SIGSYS if AFS is not supported */ - -int k_hasafs (void); -int k_hasafs_recheck (void); - -int krb_afslog (const char *cell, const char *realm); -int krb_afslog_uid (const char *cell, const char *realm, uid_t uid); -int krb_afslog_home (const char *cell, const char *realm, - const char *homedir); -int krb_afslog_uid_home (const char *cell, const char *realm, uid_t uid, - const char *homedir); - -int krb_realm_of_cell (const char *cell, char **realm); - -/* compat */ -#define k_afsklog krb_afslog -#define k_afsklog_uid krb_afslog_uid - -int k_pioctl (char *a_path, - int o_opcode, - struct ViceIoctl *a_paramsP, - int a_followSymlinks); -int k_unlog (void); -int k_setpag (void); -int k_afs_cell_of_file (const char *path, char *cell, int len); - - - -/* XXX */ -#ifdef KFAILURE -#define KRB_H_INCLUDED -#endif - -#ifdef KRB5_RECVAUTH_IGNORE_VERSION -#define KRB5_H_INCLUDED -#endif - -void kafs_set_verbose (void (*kafs_verbose)(void *, const char *), void *); -int kafs_settoken_rxkad (const char *, struct ClearToken *, - void *ticket, size_t ticket_len); -#ifdef KRB_H_INCLUDED -int kafs_settoken (const char*, uid_t, CREDENTIALS*); -#endif -#ifdef KRB5_H_INCLUDED -int kafs_settoken5 (krb5_context, const char*, uid_t, krb5_creds*); -#endif - - -#ifdef KRB5_H_INCLUDED -krb5_error_code krb5_afslog_uid (krb5_context context, - krb5_ccache id, - const char *cell, - krb5_const_realm realm, - uid_t uid); -krb5_error_code krb5_afslog (krb5_context context, - krb5_ccache id, - const char *cell, - krb5_const_realm realm); -krb5_error_code krb5_afslog_uid_home (krb5_context context, - krb5_ccache id, - const char *cell, - krb5_const_realm realm, - uid_t uid, - const char *homedir); - -krb5_error_code krb5_afslog_home (krb5_context context, - krb5_ccache id, - const char *cell, - krb5_const_realm realm, - const char *homedir); - -krb5_error_code krb5_realm_of_cell (const char *cell, char **realm); - -#endif - - -#define _PATH_VICE "/usr/vice/etc/" -#define _PATH_THISCELL _PATH_VICE "ThisCell" -#define _PATH_CELLSERVDB _PATH_VICE "CellServDB" -#define _PATH_THESECELLS _PATH_VICE "TheseCells" - -#define _PATH_ARLA_VICE "/usr/arla/etc/" -#define _PATH_ARLA_THISCELL _PATH_ARLA_VICE "ThisCell" -#define _PATH_ARLA_CELLSERVDB _PATH_ARLA_VICE "CellServDB" -#define _PATH_ARLA_THESECELLS _PATH_ARLA_VICE "TheseCells" - -#define _PATH_OPENAFS_DEBIAN_VICE "/etc/openafs/" -#define _PATH_OPENAFS_DEBIAN_THISCELL _PATH_OPENAFS_DEBIAN_VICE "ThisCell" -#define _PATH_OPENAFS_DEBIAN_CELLSERVDB _PATH_OPENAFS_DEBIAN_VICE "CellServDB" -#define _PATH_OPENAFS_DEBIAN_THESECELLS _PATH_OPENAFS_DEBIAN_VICE "TheseCells" - -#define _PATH_OPENAFS_MACOSX_VICE "/var/db/openafs/etc/" -#define _PATH_OPENAFS_MACOSX_THISCELL _PATH_OPENAFS_MACOSX_VICE "ThisCell" -#define _PATH_OPENAFS_MACOSX_CELLSERVDB _PATH_OPENAFS_MACOSX_VICE "CellServDB" -#define _PATH_OPENAFS_MACOSX_THESECELLS _PATH_OPENAFS_MACOSX_VICE "TheseCells" - -#define _PATH_ARLA_DEBIAN_VICE "/etc/arla/" -#define _PATH_ARLA_DEBIAN_THISCELL _PATH_ARLA_DEBIAN_VICE "ThisCell" -#define _PATH_ARLA_DEBIAN_CELLSERVDB _PATH_ARLA_DEBIAN_VICE "CellServDB" -#define _PATH_ARLA_DEBIAN_THESECELLS _PATH_ARLA_DEBIAN_VICE "TheseCells" - -#define _PATH_ARLA_OPENBSD_VICE "/etc/afs/" -#define _PATH_ARLA_OPENBSD_THISCELL _PATH_ARLA_OPENBSD_VICE "ThisCell" -#define _PATH_ARLA_OPENBSD_CELLSERVDB _PATH_ARLA_OPENBSD_VICE "CellServDB" -#define _PATH_ARLA_OPENBSD_THESECELLS _PATH_ARLA_OPENBSD_VICE "TheseCells" - -extern int _kafs_debug; - -#endif /* __KAFS_H */ diff --git a/lib/kafs/kafs_locl.h b/lib/kafs/kafs_locl.h deleted file mode 100644 index f4e2f64b4..000000000 --- a/lib/kafs/kafs_locl.h +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* $Id$ */ - -#ifndef __KAFS_LOCL_H__ -#define __KAFS_LOCL_H__ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_SYS_TYPES_H -#include -#endif -#ifdef HAVE_UNISTD_H -#include -#endif -#if defined(HAVE_SYS_IOCTL_H) && SunOS != 40 -#include -#endif -#ifdef HAVE_SYS_FILIO_H -#include -#endif -#ifdef HAVE_SYS_SYSCTL_H -#include -#endif - -#ifdef HAVE_SYS_SYSCALL_H -#include -#endif -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#ifdef HAVE_NETINET_IN_H -#include -#endif -#ifdef HAVE_NETINET_IN6_H -#include -#endif -#ifdef HAVE_NETINET6_IN6_H -#include -#endif - -#ifdef HAVE_NETDB_H -#include -#endif - -#ifdef HAVE_ARPA_NAMESER_H -#include -#endif -#ifdef HAVE_RESOLV_H -#include -#endif -#include - -#ifdef KRB5 -#include -#endif -#ifdef KRB5 -#include "crypto-headers.h" -typedef struct credentials CREDENTIALS; -#endif /* KRB5 */ -#ifndef NO_AFS -#include -#endif - -#include - -#include "afssysdefs.h" - -struct kafs_data; -struct kafs_token; -typedef int (*afslog_uid_func_t)(struct kafs_data *, - const char *, - const char *, - uid_t, - const char *); - -typedef int (*get_cred_func_t)(struct kafs_data*, const char*, const char*, - const char*, uid_t, struct kafs_token *); - -typedef char* (*get_realm_func_t)(struct kafs_data*, const char*); - -struct kafs_data { - const char *name; - afslog_uid_func_t afslog_uid; - get_cred_func_t get_cred; - get_realm_func_t get_realm; - const char *(*get_error)(struct kafs_data *, int); - void (*free_error)(struct kafs_data *, const char *); - void *data; -}; - -struct kafs_token { - struct ClearToken ct; - void *ticket; - size_t ticket_len; -}; - -void _kafs_foldup(char *, const char *); - -int _kafs_afslog_all_local_cells(struct kafs_data*, uid_t, const char*); - -int _kafs_get_cred(struct kafs_data*, const char*, const char*, const char *, - uid_t, struct kafs_token *); - -int -_kafs_realm_of_cell(struct kafs_data *, const char *, char **); - -int -_kafs_v4_to_kt(CREDENTIALS *, uid_t, struct kafs_token *); - -void -_kafs_fixup_viceid(struct ClearToken *, uid_t); - -int -_kafs_derive_des_key(krb5_enctype, void *, size_t, char[8]); - -#ifdef _AIX -int aix_pioctl(char*, int, struct ViceIoctl*, int); -int aix_setpag(void); -#endif - -#endif /* __KAFS_LOCL_H__ */ diff --git a/lib/kafs/roken_rename.h b/lib/kafs/roken_rename.h deleted file mode 100644 index 26da26567..000000000 --- a/lib/kafs/roken_rename.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2001-2002 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* $Id$ */ - -#ifndef __roken_rename_h__ -#define __roken_rename_h__ - -/* - * Libroken routines that are added libkafs - */ - -#define _resolve_debug _kafs_resolve_debug - -#define rk_dns_free_data _kafs_dns_free_data -#define rk_dns_lookup _kafs_dns_lookup -#define rk_dns_string_to_type _kafs_dns_string_to_type -#define rk_dns_type_to_string _kafs_dns_type_to_string -#define rk_dns_srv_order _kafs_dns_srv_order -#define rk_dns_make_query _kafs_dns_make_query -#define rk_dns_free_query _kafs_dns_free_query -#define rk_dns_parse_reply _kafs_dns_parse_reply - -#ifndef HAVE_STRTOK_R -#define rk_strtok_r _kafs_strtok_r -#endif -#ifndef HAVE_STRLCPY -#define rk_strlcpy _kafs_strlcpy -#endif -#ifndef HAVE_STRSEP -#define rk_strsep _kafs_strsep -#endif - -#endif /* __roken_rename_h__ */ diff --git a/lib/kafs/rxkad_kdf.c b/lib/kafs/rxkad_kdf.c deleted file mode 100644 index b1ebdc1ea..000000000 --- a/lib/kafs/rxkad_kdf.c +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright (c) 1995-2003 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Portions Copyright (c) 2013-2014 Carnegie Mellon University - * All rights reserved. - * - * Portions Copyright (c) 2013 by the Massachusetts Institute of Technology - * 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 "kafs_locl.h" - -static int rxkad_derive_des_key(const void *, size_t, char[8]); -static int compress_parity_bits(void *, size_t *); - -/** - * Use NIST SP800-108 with HMAC(MD5) in counter mode as the PRF to derive a - * des key from another type of key. - * - * L is 64, as we take 64 random bits and turn them into a 56-bit des key. - * The output of hmac_md5 is 128 bits; we take the first 64 only, so n - * properly should be 1. However, we apply a slight variation due to the - * possibility of producing a weak des key. If the output key is weak, do NOT - * simply correct it, instead, the counter is advanced and the next output - * used. As such, we code so as to have n be the full 255 permitted by our - * encoding of the counter i in an 8-bit field. L itself is encoded as a - * 32-bit field, big-endian. We use the constant string "rxkad" as a label - * for this key derivation, the standard NUL byte separator, and omit a - * key-derivation context. The input key is unique to the krb5 service ticket, - * which is unlikely to be used in an other location. If it is used in such - * a fashion, both locations will derive the same des key from the PRF, but - * this is no different from if a krb5 des key had been used in the same way, - * as traditional krb5 rxkad uses the ticket session key directly as the token - * key. - * - * @param[in] in pointer to input key data - * @param[in] insize length of input key data - * @param[out] out 8-byte buffer to hold the derived key - * - * @return Returns 0 to indicate success, or an error code. - * - * @retval KRB5DES_WEAK_KEY Successive derivation attempts with all - * 255 possible counter values each produced weak DES keys. This input - * cannot be used to produce a usable key. - */ -static int -rxkad_derive_des_key(const void *in, size_t insize, char out[8]) -{ - unsigned char i; - static unsigned char label[] = "rxkad"; - /* bits of output, as 32 bit word, MSB first */ - static unsigned char Lbuf[4] = { 0, 0, 0, 64 }; - /* only needs to be 16 for md5, but lets be sure it fits */ - unsigned char tmp[64]; - unsigned int mdsize; - DES_cblock ktmp; - HMAC_CTX mctx; - - /* stop when 8 bit counter wraps to 0 */ - for (i = 1; i; i++) { - HMAC_CTX_init(&mctx); - if (HMAC_Init_ex(&mctx, in, insize, EVP_md5(), NULL) == 0) { - HMAC_CTX_cleanup(&mctx); - return ENOMEM; - } - HMAC_Update(&mctx, &i, 1); - HMAC_Update(&mctx, label, sizeof(label)); /* includes label and separator */ - HMAC_Update(&mctx, Lbuf, 4); - mdsize = sizeof(tmp); - HMAC_Final(&mctx, tmp, &mdsize); - HMAC_CTX_cleanup(&mctx); - memcpy(ktmp, tmp, 8); - DES_set_odd_parity(&ktmp); - if (!DES_is_weak_key(&ktmp)) { - memcpy(out, ktmp, 8); - return 0; - } - } - return KRB5DES_WEAK_KEY; -} - -/** - * This is the inverse of the random-to-key for 3des specified in - * rfc3961, converting blocks of 8 bytes to blocks of 7 bytes by distributing - * the bits of each 8th byte as the lsb of the previous 7 bytes. - * - * @param[in,out] buffer Buffer containing the key to be converted - * @param[in,out] bufsiz Points to the size of the key data. On - * return, this is updated to reflect the size of the compressed data. - * - * @return Returns 0 to indicate success, or an error code. - * - * @retval KRB5_BAD_KEYSIZE The key size was not a multiple of 8 bytes. - */ -static int -compress_parity_bits(void *buffer, size_t *bufsiz) -{ - unsigned char *cb, tmp; - int i, j, nk; - - if (*bufsiz % 8 != 0) - return KRB5_BAD_KEYSIZE; - cb = (unsigned char *)buffer; - nk = *bufsiz / 8; - for (i = 0; i < nk; i++) { - tmp = cb[8 * i + 7] >> 1; - for (j = 0; j < 7; j++) { - cb[8 * i + j] &= 0xfe; - cb[8 * i + j] |= tmp & 0x1; - tmp >>= 1; - } - } - for (i = 1; i < nk; i++) - memmove(cb + 7 * i, cb + 8 * i, 7); - *bufsiz = 7 * nk; - return 0; -} - -/** - * Derive a DES key for use with rxkad and fcrypt from a given Kerberos - * key of (almost) any type. This function encodes enctype-specific - * knowledge about how to derive a DES key from a given key type. - * If given a des key, use it directly; otherwise, perform any parity - * fixup that may be needed and pass through to the hmad-md5 bits. - * - * @param[in] enctype Kerberos enctype of the input key - * @param[in] keydata Input key data - * @param[in] keylen Size of input key data - * @param[out] output 8-byte buffer to hold the derived key - * - * @return Returns 0 to indicate success, or an error code. - * - * @retval KRB5_PROG_ETYPE_NOSUPP The enctype is one for which rxkad-kdf - * is not supported. This includes several reserved enctypes, enctype - * values used in PKINIT to stand for CMS algorithm identifiers, and all - * private-use (negative) enctypes. - * - * @retval KRB5_BAD_KEYSIZE The key size was not a multiple of 8 bytes - * (for 3DES key types), exactly 8 bytes (for DES key types), or at least - * 8 bytes (for other key types). - * - * @retval KRB5DES_WEAK_KEY Successive derivation attempts with all - * 255 possible counter values each produced weak DES keys. This input - * cannot be used to produce a usable key. - */ -int -_kafs_derive_des_key(krb5_enctype enctype, void *keydata, size_t keylen, - char output[8]) -{ - int ret = 0; - - switch ((int)enctype) { - case ETYPE_DES_CBC_CRC: - case ETYPE_DES_CBC_MD4: - case ETYPE_DES_CBC_MD5: - if (keylen != 8) - return KRB5_BAD_KEYSIZE; - - /* Extract session key */ - memcpy(output, keydata, 8); - break; - case ETYPE_NULL: - case 4: - case 6: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - case 15: - return KRB5_PROG_ETYPE_NOSUPP; - /*In order to become a "Cryptographic Key" as specified in - * SP800-108, it must be indistinguishable from a random bitstring. */ - case ETYPE_DES3_CBC_MD5: - case ETYPE_OLD_DES3_CBC_SHA1: - case ETYPE_DES3_CBC_SHA1: - ret = compress_parity_bits(keydata, &keylen); - if (ret) - return ret; - HEIM_FALLTHROUGH; - default: - if (enctype < 0) - return KRB5_PROG_ETYPE_NOSUPP; - if (keylen < 7) - return KRB5_BAD_KEYSIZE; - ret = rxkad_derive_des_key(keydata, keylen, output); - } - return ret; -} diff --git a/lib/krb5/Makefile.am b/lib/krb5/Makefile.am index 065e5a838..ecb075bd5 100644 --- a/lib/krb5/Makefile.am +++ b/lib/krb5/Makefile.am @@ -66,6 +66,8 @@ else test_cc_LDADD = $(LDADD) endif +aes_test_LDADD = $(LDADD) $(LIB_openssl_crypto) + if PKINIT LIB_pkinit = ../hx509/libhx509.la endif @@ -140,15 +142,14 @@ dist_libkrb5_la_SOURCES = \ copy_host_realm.c \ crc.c \ creds.c \ + crypto-des-common.c \ + crypto-des.c \ crypto.c \ crypto.h \ crypto-aes-sha1.c \ crypto-aes-sha2.c \ crypto-algs.c \ crypto-arcfour.c \ - crypto-des.c \ - crypto-des-common.c \ - crypto-des3.c \ crypto-evp.c \ crypto-null.c \ crypto-pk.c \ @@ -159,7 +160,6 @@ dist_libkrb5_la_SOURCES = \ db_plugin.h \ dcache.c \ deprecated.c \ - digest.c \ eai_to_heim_errno.c \ enomem.c \ error_string.c \ @@ -230,8 +230,6 @@ dist_libkrb5_la_SOURCES = \ salt-aes-sha1.c \ salt-aes-sha2.c \ salt-arcfour.c \ - salt-des.c \ - salt-des3.c \ sp800-108-kdf.c \ scache.c \ send_to_kdc.c \ @@ -291,15 +289,14 @@ $(ALL_OBJECTS): krb5_err.h k524_err.h k5e1_err.h \ librfc3961_la_SOURCES = \ crc.c \ + crypto-des-common.c \ + crypto-des.c \ crypto.c \ crypto.h \ crypto-aes-sha1.c \ crypto-aes-sha2.c \ crypto-algs.c \ crypto-arcfour.c \ - crypto-des.c \ - crypto-des-common.c \ - crypto-des3.c \ crypto-evp.c \ crypto-null.c \ crypto-pk.c \ @@ -314,8 +311,6 @@ librfc3961_la_SOURCES = \ salt-aes-sha1.c \ salt-aes-sha2.c \ salt-arcfour.c \ - salt-des.c \ - salt-des3.c \ sp800-108-kdf.c \ store-int.c \ warn.c @@ -352,7 +347,6 @@ man_MANS = \ krb5_check_transited.3 \ krb5_create_checksum.3 \ krb5_creds.3 \ - krb5_digest.3 \ krb5_eai_to_heim_errno.3 \ krb5_encrypt.3 \ krb5_find_padata.3 \ diff --git a/lib/krb5/NTMakefile b/lib/krb5/NTMakefile index 993e76fcc..081aedd43 100644 --- a/lib/krb5/NTMakefile +++ b/lib/krb5/NTMakefile @@ -64,7 +64,6 @@ libkrb5_OBJS = \ $(OBJ)\crypto-arcfour.obj \ $(OBJ)\crypto-des-common.obj \ $(OBJ)\crypto-des.obj \ - $(OBJ)\crypto-des3.obj \ $(OBJ)\crypto-evp.obj \ $(OBJ)\crypto-null.obj \ $(OBJ)\crypto-pk.obj \ @@ -73,7 +72,6 @@ libkrb5_OBJS = \ $(OBJ)\dcache.obj \ $(OBJ)\db_plugin.obj \ $(OBJ)\deprecated.obj \ - $(OBJ)\digest.obj \ $(OBJ)\dll.obj \ $(OBJ)\eai_to_heim_errno.obj \ $(OBJ)\enomem.obj \ @@ -141,8 +139,6 @@ libkrb5_OBJS = \ $(OBJ)\salt-aes-sha1.obj \ $(OBJ)\salt-aes-sha2.obj \ $(OBJ)\salt-arcfour.obj \ - $(OBJ)\salt-des.obj \ - $(OBJ)\salt-des3.obj \ $(OBJ)\salt.obj \ $(OBJ)\scache.obj \ $(OBJ)\send_to_kdc.obj \ @@ -226,7 +222,6 @@ dist_libkrb5_la_SOURCES = \ crypto-arcfour.c \ crypto-des.c \ crypto-des-common.c \ - crypto-des3.c \ crypto-evp.c \ crypto-pk.c \ crypto-rand.c \ @@ -235,7 +230,6 @@ dist_libkrb5_la_SOURCES = \ data.c \ dcache.c \ deprecated.c \ - digest.c \ eai_to_heim_errno.c \ enomem.c \ error_string.c \ @@ -304,8 +298,6 @@ dist_libkrb5_la_SOURCES = \ salt-aes-sha1.c \ salt-aes-sha2.c \ salt-arcfour.c \ - salt-des.c \ - salt-des3.c \ scache.c \ send_to_kdc.c \ sendauth.c \ @@ -398,7 +390,6 @@ librfc3961_OBJS=\ $(OBJ)\crypto-arcfour.obj \ $(OBJ)\crypto-des.obj \ $(OBJ)\crypto-des-common.obj \ - $(OBJ)\crypto-des3.obj \ $(OBJ)\crypto-evp.obj \ $(OBJ)\crypto-null.obj \ $(OBJ)\crypto-pk.obj \ @@ -412,8 +403,6 @@ librfc3961_OBJS=\ $(OBJ)\salt-aes-sha1.obj \ $(OBJ)\salt-aes-sha2.obj \ $(OBJ)\salt-arcfour.obj \ - $(OBJ)\salt-des.obj \ - $(OBJ)\salt-des3.obj \ $(OBJ)\sp800-108-kdf.obj \ $(OBJ)\store-int.obj \ $(OBJ)\warn.obj @@ -526,11 +515,11 @@ test-run: cd $(SRCDIR) $(test_binaries): $$(@R).obj $(LIBHEIMDAL) $(LIBVERS) $(LIBROKEN) $(LIBHEIMBASE) - $(EXECONLINK) + $(EXECONLINK) $(LIB_openssl_crypto) $(EXEPREP_NODIST) $(OBJ)\test_rfc3961.exe: $(OBJ)\test_rfc3961.obj $(LIBRFC3961) $(LIBHEIMDAL) $(LIBVERS) $(LIBCOMERR) $(LIBROKEN) $(LIBHEIMBASE) - $(EXECONLINK) + $(EXECONLINK) $(LIB_openssl_crypto) $(EXEPREP_NODIST) $(test_binaries:.exe=.obj): $$(@B).c diff --git a/lib/krb5/aes-test.c b/lib/krb5/aes-test.c index 2d048e426..b3f3df2dc 100644 --- a/lib/krb5/aes-test.c +++ b/lib/krb5/aes-test.c @@ -1000,7 +1000,7 @@ random_to_key(krb5_context context) krb5_keyblock key; ret = krb5_random_to_key(context, - ETYPE_DES3_CBC_SHA1, + ETYPE_AES128_CTS_HMAC_SHA256_128, "\x21\x39\x04\x58\x6A\xBD\x7F" "\x21\x39\x04\x58\x6A\xBD\x7F" "\x21\x39\x04\x58\x6A\xBD\x7F", @@ -1010,14 +1010,13 @@ random_to_key(krb5_context context) krb5_warn(context, ret, "random_to_key"); return 1; } - if (key.keyvalue.length != 24) + if (key.keyvalue.length != 16) return 1; if (memcmp(key.keyvalue.data, - "\x20\x38\x04\x58\x6b\xbc\x7f\xc7" - "\x20\x38\x04\x58\x6b\xbc\x7f\xc7" - "\x20\x38\x04\x58\x6b\xbc\x7f\xc7", - 24) != 0) + "\x21\x39\x04\x58\x6a\xbd\x7f\x21" + "\x39\x04\x58\x6a\xbd\x7f\x21\x39", + 16) != 0) return 1; krb5_free_keyblock_contents(context, &key); diff --git a/lib/krb5/context.c b/lib/krb5/context.c index 034b8c425..2868c07e2 100644 --- a/lib/krb5/context.c +++ b/lib/krb5/context.c @@ -96,6 +96,235 @@ set_etypes (krb5_context context, return 0; } +// XXX Maybe move the OpenSSL libctx cache to lib/base so it can be shared with +// lib/hx509! +// Or move it to lib/hx509 and use it here. +// Or maybe clone this in lib/hx509. We should be able to have different +// OpenSSL configs for hx509 and krb5, for example. + +/* + * This is a singly-linked list (stack, really) of OpenSSL libctx values, one + * per OpenSSL cnf (config) file path. I.e., this is a collection indexed by + * path, though maybe it should be indexed by st_dev/st_ino so that we can + * automatically re-read (to some degree) OpenSSL configs when they change. + */ +static heim_base_atomic(krb5_context_ossl) cached_ossl; + +/* + * Create a new OpenSSL context with the given cnf and propq. + * Does not add to the global cache. + */ +static krb5_error_code +make_openssl_context(krb5_context context, + const char *cnf, + const char *propq, + krb5_context_ossl *osslp) +{ + krb5_context_ossl ossl; + + *osslp = NULL; + + if ((ossl = calloc(1, sizeof(*ossl))) == NULL) + return krb5_enomem(context); + ossl->refs = 1; + + /* From here on we ignore all failures */ + + if (cnf == NULL) { + ossl->libctx = OSSL_LIB_CTX_get0_global_default(); + if (ossl->libctx == NULL) { + krb5_debug(context, 1, + "Could not load default OpenSSL configuration; ignoring"); + } + } else { + if ((ossl->libctx = OSSL_LIB_CTX_new()) == NULL) { + krb5_debug(context, 1, + "Could not load OpenSSL configuration %s; ignoring", + cnf); + } else { + if (OSSL_LIB_CTX_load_config(ossl->libctx, cnf) != 1) { + krb5_debug(context, 1, + "Could not load OpenSSL configuration %s; ignoring", + cnf); + OSSL_LIB_CTX_free(ossl->libctx); + ossl->libctx = NULL; + } + ossl->openssl_def = OSSL_PROVIDER_load(ossl->libctx, "default"); + } + } + if (cnf) + ossl->cnf = strdup(cnf); + if (propq) + ossl->propq = strdup(propq); + if (ossl->libctx) { + if (krb5_config_get_bool_default(context, NULL, 0, + "libdefaults", + "fips", NULL)) + ossl->openssl_fips = OSSL_PROVIDER_load(ossl->libctx, "fips"); + if (krb5_config_get_bool_default(context, NULL, FALSE, + "libdefaults", + "allow_weak_crypto", NULL)) + ossl->openssl_leg = OSSL_PROVIDER_load(ossl->libctx, "legacy"); + } + + // for now + ossl->openssl_leg = OSSL_PROVIDER_load(ossl->libctx, "legacy"); + + ossl->rc4 = EVP_CIPHER_fetch(ossl->libctx, "RC4", ossl->propq); + ossl->aes128_cbc = EVP_CIPHER_fetch(ossl->libctx, "AES-128-CBC", ossl->propq); + ossl->aes192_cbc = EVP_CIPHER_fetch(ossl->libctx, "AES-192-CBC", ossl->propq); + ossl->aes256_cbc = EVP_CIPHER_fetch(ossl->libctx, "AES-256-CBC", ossl->propq); + ossl->aes128_cts = EVP_CIPHER_fetch(ossl->libctx, "AES-128-CBC-CTS", ossl->propq); + ossl->aes192_cts = EVP_CIPHER_fetch(ossl->libctx, "AES-192-CBC-CTS", ossl->propq); + ossl->aes256_cts = EVP_CIPHER_fetch(ossl->libctx, "AES-256-CBC-CTS", ossl->propq); + ossl->hmac = EVP_MAC_fetch(ossl->libctx, "HMAC", ossl->propq); + ossl->md5 = EVP_MD_fetch(ossl->libctx, "MD5", ossl->propq); + ossl->sha1 = EVP_MD_fetch(ossl->libctx, "SHA1", ossl->propq); + ossl->sha256 = EVP_MD_fetch(ossl->libctx, "SHA256", ossl->propq); + ossl->sha384 = EVP_MD_fetch(ossl->libctx, "SHA384", ossl->propq); + ossl->sha512 = EVP_MD_fetch(ossl->libctx, "SHA512", ossl->propq); + *osslp = ossl; + return 0; +} + +static void +free_openssl(krb5_context_ossl *osslp) +{ + krb5_context_ossl p = *osslp; + + *osslp = NULL; + if (p == NULL) + return; + if (heim_base_atomic_dec_32(&p->refs) != 0) + return; + EVP_CIPHER_free(p->rc4); + EVP_CIPHER_free(p->aes128_cbc); + EVP_CIPHER_free(p->aes192_cbc); + EVP_CIPHER_free(p->aes256_cbc); + EVP_CIPHER_free(p->aes128_cts); + EVP_CIPHER_free(p->aes192_cts); + EVP_CIPHER_free(p->aes256_cts); + EVP_MAC_free(p->hmac); + EVP_MD_free(p->md5); + EVP_MD_free(p->sha1); + EVP_MD_free(p->sha256); + EVP_MD_free(p->sha384); + EVP_MD_free(p->sha512); + if (p->openssl_leg) + OSSL_PROVIDER_unload(p->openssl_leg); + if (p->openssl_fips) + OSSL_PROVIDER_unload(p->openssl_fips); + if (p->openssl_def) + OSSL_PROVIDER_unload(p->openssl_def); + OSSL_LIB_CTX_free(p->libctx); + free(p->propq); + + /* + * Remove from the global cache? This happens atexit() if at all, so + * perhaps no need to remove from the global cache, which is a nice + * simplification. + */ + free(p); +} + +/* Helper to compare two nullable strings for equality */ +static int +str_equal(const char *a, const char *b) +{ + if (a == b) + return 1; + if (a == NULL || b == NULL) + return 0; + return strcmp(a, b) == 0; +} + +/* Check if an ossl context matches the given (cnf, propq) tuple */ +static int +ossl_matches(krb5_context_ossl p, const char *cnf, const char *propq) +{ + return str_equal(p->cnf, cnf) && str_equal(p->propq, propq); +} + +static krb5_error_code +init_openssl_with_propq(krb5_context context, + const char *cnf, + const char *propq, + krb5_context_ossl *osslp) +{ + krb5_context_ossl first, p, ossl; + krb5_error_code ret; + int done = 0; + + *osslp = NULL; + + /* + * Ensure that all writes to the list are visible to us before we + * derefernce the members of the list. + */ + first = heim_base_atomic_load(&cached_ossl); + heim_base_consumer_barrier(); + for (p = first; p; p = p->next) { + if (ossl_matches(p, cnf, propq)) { + (void) heim_base_atomic_inc_32(&p->refs); + *osslp = p; + return 0; + } + } + + ret = make_openssl_context(context, cnf, propq, &ossl); + if (ret) + return ret; + + /* Finish all stores before we publish */ + heim_base_producer_barrier(); + + while (!done) { + krb5_context_ossl old = first; + + /* Try to publish */ + if ((old = heim_base_cas_pointer((void *)&cached_ossl, + first, ossl)) == first) { + /* + * Published! Take one more ref for the reference from the global + * list. + */ + heim_base_consumer_barrier(); + (void) heim_base_atomic_inc_32(&ossl->refs); + *osslp = ossl; + return 0; + } + heim_base_consumer_barrier(); + + /* Lost a race; try again */ + first = old; + ossl->next = first; + for (p = first; p; p = p->next) { + if (ossl_matches(p, cnf, propq)) { + (void) heim_base_atomic_inc_32(&p->refs); + *osslp = p; + free_openssl(&ossl); /* Found a better one */ + return 0; + } + } + /* Did not find a better one, so try to publish again */ + } + return 0; +} + +static krb5_error_code +init_openssl(krb5_context context, krb5_context_ossl *osslp) +{ + const char *cnf = + krb5_config_get_string_default(context, NULL, + secure_getenv("KRB5_OPENSSL_CNF"), + "libdefaults", "openssl_cnf", NULL); + const char *propq = + krb5_config_get_string_default(context, NULL, + secure_getenv("KRB5_OPENSSL_PROPQ"), + "libdefaults", "openssl_propq", NULL); + return init_openssl_with_propq(context, cnf, propq, osslp); +} + /* * read variables from the configuration file and set in `context' */ @@ -115,16 +344,15 @@ init_context_from_config_file(krb5_context context) INIT_FIELD(context, string, http_proxy, NULL, "http_proxy"); + ret = init_openssl(context, &context->ossl); + if (ret) + return ret; + ret = krb5_config_get_bool_default(context, NULL, FALSE, "libdefaults", "allow_weak_crypto", NULL); if (ret) { - krb5_enctype_enable(context, ETYPE_DES_CBC_CRC); - krb5_enctype_enable(context, ETYPE_DES_CBC_MD4); - krb5_enctype_enable(context, ETYPE_DES_CBC_MD5); - krb5_enctype_enable(context, ETYPE_DES_CBC_NONE); - krb5_enctype_enable(context, ETYPE_DES_CFB64_NONE); - krb5_enctype_enable(context, ETYPE_DES_PCBC_NONE); + krb5_enctype_enable(context, ETYPE_ARCFOUR_HMAC_MD5); } ret = set_etypes (context, "default_etypes", &tmptypes); @@ -658,6 +886,9 @@ krb5_copy_context(krb5_context context, krb5_context *out) if (ret == 0) ret = _krb5_copy_send_to_kdc_func(p, context); + if (ret == 0) + heim_base_atomic_inc_32(&p->ossl->refs); + if (ret == 0) *out = p; else @@ -697,6 +928,9 @@ krb5_free_context(krb5_context context) krb5_set_ignore_addresses(context, NULL); krb5_set_send_to_kdc_func(context, NULL, NULL); + if (context->ossl) + free_openssl(&context->ossl); + #ifdef PKINIT hx509_context_free(&context->hx509ctx); #endif @@ -855,12 +1089,11 @@ krb5_free_config_files(char **filenames) KRB5_LIB_FUNCTION const krb5_enctype * KRB5_LIB_CALL krb5_kerberos_enctypes(krb5_context context) { - static const krb5_enctype p[] = { + static const krb5_enctype strong[] = { ETYPE_AES256_CTS_HMAC_SHA384_192, ETYPE_AES128_CTS_HMAC_SHA256_128, ETYPE_AES256_CTS_HMAC_SHA1_96, ETYPE_AES128_CTS_HMAC_SHA1_96, - ETYPE_ARCFOUR_HMAC_MD5, ETYPE_NULL }; @@ -873,23 +1106,10 @@ krb5_kerberos_enctypes(krb5_context context) ETYPE_NULL }; - /* - * if the list of enctypes enabled by "allow_weak_crypto" - * are valid, then return the former default enctype list - * that contained the weak entries. - * - * XXX We should nuke all traces of dead code like this that references - * 1DES and 3DES. - */ - if (krb5_enctype_valid(context, ETYPE_DES_CBC_CRC) == 0 && - krb5_enctype_valid(context, ETYPE_DES_CBC_MD4) == 0 && - krb5_enctype_valid(context, ETYPE_DES_CBC_MD5) == 0 && - krb5_enctype_valid(context, ETYPE_DES_CBC_NONE) == 0 && - krb5_enctype_valid(context, ETYPE_DES_CFB64_NONE) == 0 && - krb5_enctype_valid(context, ETYPE_DES_PCBC_NONE) == 0) + if (krb5_enctype_valid(context, ETYPE_ARCFOUR_HMAC_MD5)) return weak; - return p; + return strong; } /* @@ -1501,3 +1721,54 @@ krb5_set_home_dir_access(krb5_context context, krb5_boolean allow) return old; } +/** + * Set the OpenSSL configuration file and/or property query string for both the + * krb5 and hx509 contexts. + * + * This is used to select algorithm implementations from specific providers + * (e.g., "provider=pkcs11" for hardware tokens, or "fips=yes" for FIPS mode). + * + * This function looks up or creates a cached OpenSSL context with the + * specified propq. If the same (cnf, propq) combination is used by multiple + * krb5 contexts, they will share the same cached OpenSSL context. This + * amortizes the cost of "fetching" algorithms in OpenSSL, as that can be a + * slow operation. + * + * This function must be called after krb5_init_context() and before any + * cryptographic operations using the resulting context. + * + * @param context a Kerberos 5 context + * @param cnf the OpenSSL configuration file, or NULL to use the OpenSSL default + * @param propq the OpenSSL property query string, or NULL to use the OpenSSL default + * @return 0 on success, or an error code + * + * @ingroup krb5 + */ + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_set_ossl_cnf_propq(krb5_context context, + const char *cnf, + const char *propq) +{ + krb5_error_code ret = 0; + krb5_context_ossl new_ossl = NULL; + + if (context == NULL) + return EINVAL; + + /* Look up or create a cached OpenSSL context with the new propq */ + ret = init_openssl_with_propq(context, cnf, propq, &new_ossl); + if (ret) + return ret; + + /* Release the old context and use the new one */ + free_openssl(&context->ossl); + context->ossl = new_ossl; + +#ifdef PKINIT + /* Also set propq on the hx509 context for PKINIT */ + ret = hx509_context_set_ossl_cnf_propq(context->hx509ctx, cnf, propq); +#endif + return ret; +} + diff --git a/lib/krb5/crypto-aes-sha1.c b/lib/krb5/crypto-aes-sha1.c index 1f3760d18..7c9125a86 100644 --- a/lib/krb5/crypto-aes-sha1.c +++ b/lib/krb5/crypto-aes-sha1.c @@ -37,6 +37,12 @@ * AES */ +static EVP_CIPHER * +heim_EVP_aes_128_cbc(krb5_context context) +{ + return context->ossl->aes128_cbc; +} + static struct _krb5_key_type keytype_aes128_sha1 = { KRB5_ENCTYPE_AES128_CTS_HMAC_SHA1_96, "aes-128", @@ -48,9 +54,15 @@ static struct _krb5_key_type keytype_aes128_sha1 = { _krb5_AES_SHA1_salt, NULL, _krb5_evp_cleanup, - EVP_aes_128_cbc + heim_EVP_aes_128_cbc }; +static EVP_CIPHER * +heim_EVP_aes_256_cbc(krb5_context context) +{ + return context->ossl->aes256_cbc; +} + static struct _krb5_key_type keytype_aes256_sha1 = { KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96, "aes-256", @@ -62,7 +74,7 @@ static struct _krb5_key_type keytype_aes256_sha1 = { _krb5_AES_SHA1_salt, NULL, _krb5_evp_cleanup, - EVP_aes_256_cbc + heim_EVP_aes_256_cbc }; struct _krb5_checksum_type _krb5_checksum_hmac_sha1_aes128 = { @@ -126,14 +138,14 @@ AES_SHA1_PRF(krb5_context context, krb5_abortx(context, "malloc failed"); { - const EVP_CIPHER *c = (*crypto->et->keytype->evp)(); - EVP_CIPHER_CTX ctx; + const EVP_CIPHER *c = (*crypto->et->keytype->evp)(context); + EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); - EVP_CIPHER_CTX_init(&ctx); /* ivec all zero */ - EVP_CipherInit_ex(&ctx, c, NULL, derived->keyvalue.data, NULL, 1); - EVP_Cipher(&ctx, out->data, result.checksum.data, + EVP_CIPHER_CTX_init(ctx); /* ivec all zero */ + EVP_CipherInit_ex(ctx, c, NULL, derived->keyvalue.data, NULL, 1); + EVP_Cipher(ctx, out->data, result.checksum.data, crypto->et->blocksize); - EVP_CIPHER_CTX_cleanup(&ctx); + EVP_CIPHER_CTX_free(ctx); } krb5_data_free(&result.checksum); diff --git a/lib/krb5/crypto-aes-sha2.c b/lib/krb5/crypto-aes-sha2.c index 94ec9a1d6..dc2e33bdc 100644 --- a/lib/krb5/crypto-aes-sha2.c +++ b/lib/krb5/crypto-aes-sha2.c @@ -44,10 +44,10 @@ _krb5_aes_sha2_md_for_enctype(krb5_context context, { switch (enctype) { case ETYPE_AES128_CTS_HMAC_SHA256_128: - *md = EVP_sha256(); + *md = context->ossl->sha256; break; case ETYPE_AES256_CTS_HMAC_SHA384_192: - *md = EVP_sha384(); + *md = context->ossl->sha384; break; default: return KRB5_PROG_ETYPE_NOSUPP; @@ -75,7 +75,7 @@ SP_HMAC_SHA2_checksum(krb5_context context, return ret; ret = _krb5_evp_hmac_iov(context, crypto, key, iov, niov, hmac, - &hmaclen, md, NULL); + &hmaclen, md); if (ret) return ret; @@ -86,6 +86,12 @@ SP_HMAC_SHA2_checksum(krb5_context context, return 0; } +static EVP_CIPHER * +heim_EVP_aes_128_cbc(krb5_context context) +{ + return context->ossl->aes128_cbc; +} + static struct _krb5_key_type keytype_aes128_sha2 = { KRB5_ENCTYPE_AES128_CTS_HMAC_SHA256_128, "aes-128-sha2", @@ -97,9 +103,15 @@ static struct _krb5_key_type keytype_aes128_sha2 = { _krb5_AES_SHA2_salt, NULL, _krb5_evp_cleanup, - EVP_aes_128_cbc + heim_EVP_aes_128_cbc }; +static EVP_CIPHER * +heim_EVP_aes_256_cbc(krb5_context context) +{ + return context->ossl->aes256_cbc; +} + static struct _krb5_key_type keytype_aes256_sha2 = { KRB5_ENCTYPE_AES256_CTS_HMAC_SHA384_192, "aes-256-sha2", @@ -111,7 +123,7 @@ static struct _krb5_key_type keytype_aes256_sha2 = { _krb5_AES_SHA2_salt, NULL, _krb5_evp_cleanup, - EVP_aes_256_cbc + heim_EVP_aes_256_cbc }; struct _krb5_checksum_type _krb5_checksum_hmac_sha256_128_aes128 = { diff --git a/lib/krb5/crypto-algs.c b/lib/krb5/crypto-algs.c index eb21fcef0..8e2482d51 100644 --- a/lib/krb5/crypto-algs.c +++ b/lib/krb5/crypto-algs.c @@ -41,16 +41,9 @@ struct _krb5_checksum_type *_krb5_checksum_types[] = { &_krb5_checksum_none, #ifdef HEIM_WEAK_CRYPTO &_krb5_checksum_crc32, - &_krb5_checksum_rsa_md4, - &_krb5_checksum_rsa_md4_des, - &_krb5_checksum_rsa_md5_des, -#endif -#ifdef DES3_OLD_ENCTYPE - &_krb5_checksum_rsa_md5_des3, #endif &_krb5_checksum_rsa_md5, &_krb5_checksum_sha1, - &_krb5_checksum_hmac_sha1_des3, &_krb5_checksum_hmac_sha1_aes128, &_krb5_checksum_hmac_sha1_aes256, &_krb5_checksum_hmac_sha256_128_aes128, @@ -73,21 +66,7 @@ struct _krb5_encryption_type *_krb5_etypes[] = { &_krb5_enctype_aes128_cts_hmac_sha256_128, &_krb5_enctype_aes256_cts_hmac_sha1, &_krb5_enctype_aes128_cts_hmac_sha1, - &_krb5_enctype_des3_cbc_sha1, - &_krb5_enctype_des3_cbc_none, /* used by the gss-api mech */ &_krb5_enctype_arcfour_hmac_md5, -#ifdef DES3_OLD_ENCTYPE - &_krb5_enctype_des3_cbc_md5, - &_krb5_enctype_old_des3_cbc_sha1, -#endif -#ifdef HEIM_WEAK_CRYPTO - &_krb5_enctype_des_cbc_md5, - &_krb5_enctype_des_cbc_md4, - &_krb5_enctype_des_cbc_crc, - &_krb5_enctype_des_cbc_none, - &_krb5_enctype_des_cfb64_none, - &_krb5_enctype_des_pcbc_none, -#endif &_krb5_enctype_null }; diff --git a/lib/krb5/crypto-arcfour.c b/lib/krb5/crypto-arcfour.c index 28fc52e4c..acc6c7ddd 100644 --- a/lib/krb5/crypto-arcfour.c +++ b/lib/krb5/crypto-arcfour.c @@ -37,6 +37,12 @@ #include "krb5_locl.h" +static EVP_CIPHER * +heim_EVP_rc4(krb5_context context) +{ + return context->ossl->rc4; +} + static struct _krb5_key_type keytype_arcfour = { KRB5_ENCTYPE_ARCFOUR_HMAC_MD5, "arcfour", @@ -48,7 +54,7 @@ static struct _krb5_key_type keytype_arcfour = { _krb5_arcfour_salt, NULL, _krb5_evp_cleanup, - EVP_rc4 + heim_EVP_rc4 }; /* @@ -82,8 +88,11 @@ _krb5_HMAC_MD5_checksum(krb5_context context, if (crypto->mdctx == NULL) return krb5_enomem(context); m = crypto->mdctx; - } else + } else { m = EVP_MD_CTX_create(); + if (m == NULL) + return krb5_enomem(context); + } ksign_c.checksum.length = sizeof(ksign_c_data); ksign_c.checksum.data = ksign_c_data; @@ -94,17 +103,21 @@ _krb5_HMAC_MD5_checksum(krb5_context context, ksign.key = &kb; kb.keyvalue = ksign_c.checksum; - EVP_DigestInit_ex(m, EVP_md5(), NULL); + if (EVP_DigestInit_ex(m, context->ossl->md5, NULL) != 1) + goto out; t[0] = (usage >> 0) & 0xFF; t[1] = (usage >> 8) & 0xFF; t[2] = (usage >> 16) & 0xFF; t[3] = (usage >> 24) & 0xFF; - EVP_DigestUpdate(m, t, 4); + if (EVP_DigestUpdate(m, t, 4) != 1) + goto out; for (i = 0; i < niov; i++) { - if (_krb5_crypto_iov_should_sign(&iov[i])) - EVP_DigestUpdate(m, iov[i].data.data, iov[i].data.length); + if (_krb5_crypto_iov_should_sign(&iov[i]) && + EVP_DigestUpdate(m, iov[i].data.data, iov[i].data.length) != 1) + goto out; } - EVP_DigestFinal_ex (m, tmp, NULL); + if (EVP_DigestFinal_ex(m, tmp, NULL) != 1) + goto out; ret = _krb5_internal_hmac(context, crypto, c, tmp, sizeof(tmp), 0, &ksign, result); out: @@ -138,7 +151,8 @@ ARCFOUR_subencrypt(krb5_context context, unsigned usage, void *ivec) { - EVP_CIPHER_CTX ctx; + EVP_CIPHER_CTX *ctx; + EVP_CIPHER *cipher; struct _krb5_checksum_type *c = _krb5_find_checksum (CKSUMTYPE_RSA_MD5); Checksum k1_c, k2_c, k3_c, cksum; struct _krb5_key_data ke; @@ -152,6 +166,14 @@ ARCFOUR_subencrypt(krb5_context context, return KRB5KRB_AP_ERR_INAPP_CKSUM; } + cipher = heim_EVP_rc4(context); + if (cipher == NULL) + return krb5_enomem(context); + + ctx = EVP_CIPHER_CTX_new(); + if (ctx == NULL) + return krb5_enomem(context); + t[0] = (usage >> 0) & 0xFF; t[1] = (usage >> 8) & 0xFF; t[2] = (usage >> 16) & 0xFF; @@ -189,11 +211,15 @@ ARCFOUR_subencrypt(krb5_context context, if (ret) krb5_abortx(context, "hmac failed"); - EVP_CIPHER_CTX_init(&ctx); - - EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, k3_c.checksum.data, NULL, 1); - EVP_Cipher(&ctx, cdata + 16, cdata + 16, len - 16); - EVP_CIPHER_CTX_cleanup(&ctx); + if (EVP_CipherInit_ex(ctx, cipher, NULL, k3_c.checksum.data, NULL, 1) != 1 || + EVP_Cipher(ctx, cdata + 16, cdata + 16, len - 16) < 0) { + EVP_CIPHER_CTX_free(ctx); + memset_s(k1_c_data, sizeof(k1_c_data), 0, sizeof(k1_c_data)); + memset_s(k2_c_data, sizeof(k2_c_data), 0, sizeof(k2_c_data)); + memset_s(k3_c_data, sizeof(k3_c_data), 0, sizeof(k3_c_data)); + return krb5_enomem(context); + } + EVP_CIPHER_CTX_free(ctx); memset_s(k1_c_data, sizeof(k1_c_data), 0, sizeof(k1_c_data)); memset_s(k2_c_data, sizeof(k2_c_data), 0, sizeof(k2_c_data)); @@ -209,7 +235,8 @@ ARCFOUR_subdecrypt(krb5_context context, unsigned usage, void *ivec) { - EVP_CIPHER_CTX ctx; + EVP_CIPHER_CTX *ctx; + EVP_CIPHER *cipher; struct _krb5_checksum_type *c = _krb5_find_checksum (CKSUMTYPE_RSA_MD5); Checksum k1_c, k2_c, k3_c, cksum; struct _krb5_key_data ke; @@ -224,6 +251,14 @@ ARCFOUR_subdecrypt(krb5_context context, return KRB5KRB_AP_ERR_INAPP_CKSUM; } + cipher = heim_EVP_rc4(context); + if (cipher == NULL) + return krb5_enomem(context); + + ctx = EVP_CIPHER_CTX_new(); + if (ctx == NULL) + return krb5_enomem(context); + t[0] = (usage >> 0) & 0xFF; t[1] = (usage >> 8) & 0xFF; t[2] = (usage >> 16) & 0xFF; @@ -251,10 +286,15 @@ ARCFOUR_subdecrypt(krb5_context context, if (ret) krb5_abortx(context, "hmac failed"); - EVP_CIPHER_CTX_init(&ctx); - EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, k3_c.checksum.data, NULL, 0); - EVP_Cipher(&ctx, cdata + 16, cdata + 16, len - 16); - EVP_CIPHER_CTX_cleanup(&ctx); + if (EVP_CipherInit_ex(ctx, cipher, NULL, k3_c.checksum.data, NULL, 0) != 1 || + EVP_Cipher(ctx, cdata + 16, cdata + 16, len - 16) < 0) { + EVP_CIPHER_CTX_free(ctx); + memset_s(k1_c_data, sizeof(k1_c_data), 0, sizeof(k1_c_data)); + memset_s(k2_c_data, sizeof(k2_c_data), 0, sizeof(k2_c_data)); + memset_s(k3_c_data, sizeof(k3_c_data), 0, sizeof(k3_c_data)); + return krb5_enomem(context); + } + EVP_CIPHER_CTX_free(ctx); ke.key = &kb; kb.keyvalue = k2_c.checksum; diff --git a/lib/krb5/crypto-des-common.c b/lib/krb5/crypto-des-common.c index a8344ae5b..c7bc8916c 100644 --- a/lib/krb5/crypto-des-common.c +++ b/lib/krb5/crypto-des-common.c @@ -31,8 +31,6 @@ * SUCH DAMAGE. */ -/* Functions which are used by both single and triple DES enctypes */ - #include "krb5_locl.h" /* @@ -52,85 +50,6 @@ _krb5_xor8(unsigned char *a, const unsigned char *b) a[7] ^= b[7]; } -#if defined(DES3_OLD_ENCTYPE) || defined(HEIM_WEAK_CRYPTO) -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -_krb5_des_checksum(krb5_context context, - const EVP_MD *evp_md, - struct _krb5_key_data *key, - const struct krb5_crypto_iov *iov, - int niov, - Checksum *cksum) -{ - struct _krb5_evp_schedule *ctx = key->schedule->data; - EVP_MD_CTX *m; - DES_cblock ivec; - int i; - unsigned char *p = cksum->checksum.data; - - krb5_generate_random_block(p, 8); - - m = EVP_MD_CTX_create(); - if (m == NULL) - return krb5_enomem(context); - - EVP_DigestInit_ex(m, evp_md, NULL); - EVP_DigestUpdate(m, p, 8); - for (i = 0; i < niov; i++) { - if (_krb5_crypto_iov_should_sign(&iov[i])) - EVP_DigestUpdate(m, iov[i].data.data, iov[i].data.length); - } - EVP_DigestFinal_ex (m, p + 8, NULL); - EVP_MD_CTX_destroy(m); - memset_s(&ivec, sizeof(ivec), 0, sizeof(ivec)); - EVP_CipherInit_ex(&ctx->ectx, NULL, NULL, NULL, (void *)&ivec, -1); - EVP_Cipher(&ctx->ectx, p, p, 24); - - return 0; -} - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -_krb5_des_verify(krb5_context context, - const EVP_MD *evp_md, - struct _krb5_key_data *key, - const struct krb5_crypto_iov *iov, - int niov, - Checksum *C) -{ - struct _krb5_evp_schedule *ctx = key->schedule->data; - EVP_MD_CTX *m; - unsigned char tmp[24]; - unsigned char res[16]; - DES_cblock ivec; - krb5_error_code ret = 0; - int i; - - m = EVP_MD_CTX_create(); - if (m == NULL) - return krb5_enomem(context); - - memset_s(&ivec, sizeof(ivec), 0, sizeof(ivec)); - EVP_CipherInit_ex(&ctx->dctx, NULL, NULL, NULL, (void *)&ivec, -1); - EVP_Cipher(&ctx->dctx, tmp, C->checksum.data, 24); - - EVP_DigestInit_ex(m, evp_md, NULL); - EVP_DigestUpdate(m, tmp, 8); /* confounder */ - for (i = 0; i < niov; i++) { - if (_krb5_crypto_iov_should_sign(&iov[i])) - EVP_DigestUpdate(m, iov[i].data.data, iov[i].data.length); - } - EVP_DigestFinal_ex (m, res, NULL); - EVP_MD_CTX_destroy(m); - if(ct_memcmp(res, tmp + 8, sizeof(res)) != 0) { - krb5_clear_error_message (context); - ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; - } - memset_s(tmp, sizeof(tmp), 0, sizeof(tmp)); - memset_s(res, sizeof(res), 0, sizeof(res)); - return ret; -} - -#endif - static krb5_error_code RSA_MD5_checksum(krb5_context context, krb5_crypto crypto, diff --git a/lib/krb5/crypto-des.c b/lib/krb5/crypto-des.c index c5692954c..2b0aa5e2a 100644 --- a/lib/krb5/crypto-des.c +++ b/lib/krb5/crypto-des.c @@ -35,67 +35,6 @@ #ifdef HEIM_WEAK_CRYPTO - -static void -krb5_DES_random_key(krb5_context context, - krb5_keyblock *key) -{ - DES_cblock *k = key->keyvalue.data; - do { - krb5_generate_random_block(k, sizeof(DES_cblock)); - DES_set_odd_parity(k); - } while(DES_is_weak_key(k)); -} - -static void -krb5_DES_schedule_old(krb5_context context, - struct _krb5_key_type *kt, - struct _krb5_key_data *key) -{ - DES_set_key_unchecked(key->key->keyvalue.data, key->schedule->data); -} - -static void -krb5_DES_random_to_key(krb5_context context, - krb5_keyblock *key, - const void *data, - size_t size) -{ - DES_cblock *k = key->keyvalue.data; - memcpy(k, data, key->keyvalue.length); - DES_set_odd_parity(k); - if(DES_is_weak_key(k)) - _krb5_xor8(*k, (const unsigned char*)"\0\0\0\0\0\0\0\xf0"); -} - -static struct _krb5_key_type keytype_des_old = { - ETYPE_DES_CBC_CRC, - "des-old", - 56, - 8, - sizeof(DES_key_schedule), - krb5_DES_random_key, - krb5_DES_schedule_old, - _krb5_des_salt, - krb5_DES_random_to_key, - NULL, - NULL -}; - -static struct _krb5_key_type keytype_des = { - ETYPE_DES_CBC_CRC, - "des", - 56, - 8, - sizeof(struct _krb5_evp_schedule), - krb5_DES_random_key, - _krb5_evp_schedule, - _krb5_des_salt, - krb5_DES_random_to_key, - _krb5_evp_cleanup, - EVP_des_cbc -}; - static krb5_error_code CRC32_checksum(krb5_context context, krb5_crypto crypto, @@ -138,54 +77,6 @@ RSA_MD4_checksum(krb5_context context, return 0; } -static krb5_error_code -RSA_MD4_DES_checksum(krb5_context context, - krb5_crypto crypto, - struct _krb5_key_data *key, - unsigned usage, - const struct krb5_crypto_iov *iov, - int niov, - Checksum *cksum) -{ - return _krb5_des_checksum(context, EVP_md4(), key, iov, niov, cksum); -} - -static krb5_error_code -RSA_MD4_DES_verify(krb5_context context, - krb5_crypto crypto, - struct _krb5_key_data *key, - unsigned usage, - const struct krb5_crypto_iov *iov, - int niov, - Checksum *C) -{ - return _krb5_des_verify(context, EVP_md4(), key, iov, niov, C); -} - -static krb5_error_code -RSA_MD5_DES_checksum(krb5_context context, - krb5_crypto crypto, - struct _krb5_key_data *key, - unsigned usage, - const struct krb5_crypto_iov *iov, - int niov, - Checksum *C) -{ - return _krb5_des_checksum(context, EVP_md5(), key, iov, niov, C); -} - -static krb5_error_code -RSA_MD5_DES_verify(krb5_context context, - krb5_crypto crypto, - struct _krb5_key_data *key, - unsigned usage, - const struct krb5_crypto_iov *iov, - int niov, - Checksum *C) -{ - return _krb5_des_verify(context, EVP_md5(), key, iov, niov, C); -} - struct _krb5_checksum_type _krb5_checksum_crc32 = { CKSUMTYPE_CRC32, "crc32", @@ -206,198 +97,4 @@ struct _krb5_checksum_type _krb5_checksum_rsa_md4 = { NULL }; -struct _krb5_checksum_type _krb5_checksum_rsa_md4_des = { - CKSUMTYPE_RSA_MD4_DES, - "rsa-md4-des", - 64, - 24, - F_KEYED | F_CPROOF | F_VARIANT, - RSA_MD4_DES_checksum, - RSA_MD4_DES_verify -}; - -struct _krb5_checksum_type _krb5_checksum_rsa_md5_des = { - CKSUMTYPE_RSA_MD5_DES, - "rsa-md5-des", - 64, - 24, - F_KEYED | F_CPROOF | F_VARIANT, - RSA_MD5_DES_checksum, - RSA_MD5_DES_verify -}; - -static krb5_error_code -evp_des_encrypt_null_ivec(krb5_context context, - struct _krb5_key_data *key, - void *data, - size_t len, - krb5_boolean encryptp, - int usage, - void *ignore_ivec) -{ - struct _krb5_evp_schedule *ctx = key->schedule->data; - EVP_CIPHER_CTX *c; - DES_cblock ivec; - memset(&ivec, 0, sizeof(ivec)); - c = encryptp ? &ctx->ectx : &ctx->dctx; - EVP_CipherInit_ex(c, NULL, NULL, NULL, (void *)&ivec, -1); - EVP_Cipher(c, data, data, len); - return 0; -} - -static krb5_error_code -evp_des_encrypt_key_ivec(krb5_context context, - struct _krb5_key_data *key, - void *data, - size_t len, - krb5_boolean encryptp, - int usage, - void *ignore_ivec) -{ - struct _krb5_evp_schedule *ctx = key->schedule->data; - EVP_CIPHER_CTX *c; - DES_cblock ivec; - memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec)); - c = encryptp ? &ctx->ectx : &ctx->dctx; - EVP_CipherInit_ex(c, NULL, NULL, NULL, (void *)&ivec, -1); - EVP_Cipher(c, data, data, len); - return 0; -} - -static krb5_error_code -DES_CFB64_encrypt_null_ivec(krb5_context context, - struct _krb5_key_data *key, - void *data, - size_t len, - krb5_boolean encryptp, - int usage, - void *ignore_ivec) -{ - DES_cblock ivec; - int num = 0; - DES_key_schedule *s = key->schedule->data; - memset(&ivec, 0, sizeof(ivec)); - - DES_cfb64_encrypt(data, data, len, s, &ivec, &num, encryptp); - return 0; -} - -static krb5_error_code -DES_PCBC_encrypt_key_ivec(krb5_context context, - struct _krb5_key_data *key, - void *data, - size_t len, - krb5_boolean encryptp, - int usage, - void *ignore_ivec) -{ - DES_cblock ivec; - DES_key_schedule *s = key->schedule->data; - memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec)); - - DES_pcbc_encrypt(data, data, len, s, &ivec, encryptp); - return 0; -} - -struct _krb5_encryption_type _krb5_enctype_des_cbc_crc = { - ETYPE_DES_CBC_CRC, - "des-cbc-crc", - NULL, - 8, - 8, - 8, - &keytype_des, - &_krb5_checksum_crc32, - NULL, - F_DISABLED|F_WEAK|F_OLD, - evp_des_encrypt_key_ivec, - NULL, - 0, - NULL -}; - -struct _krb5_encryption_type _krb5_enctype_des_cbc_md4 = { - ETYPE_DES_CBC_MD4, - "des-cbc-md4", - NULL, - 8, - 8, - 8, - &keytype_des, - &_krb5_checksum_rsa_md4, - &_krb5_checksum_rsa_md4_des, - F_DISABLED|F_WEAK|F_OLD, - evp_des_encrypt_null_ivec, - NULL, - 0, - NULL -}; - -struct _krb5_encryption_type _krb5_enctype_des_cbc_md5 = { - ETYPE_DES_CBC_MD5, - "des-cbc-md5", - NULL, - 8, - 8, - 8, - &keytype_des, - &_krb5_checksum_rsa_md5, - &_krb5_checksum_rsa_md5_des, - F_DISABLED|F_WEAK|F_OLD, - evp_des_encrypt_null_ivec, - NULL, - 0, - NULL -}; - -struct _krb5_encryption_type _krb5_enctype_des_cbc_none = { - ETYPE_DES_CBC_NONE, - "des-cbc-none", - NULL, - 8, - 8, - 0, - &keytype_des, - &_krb5_checksum_none, - NULL, - F_PSEUDO|F_DISABLED|F_WEAK|F_OLD, - evp_des_encrypt_null_ivec, - NULL, - 0, - NULL -}; - -struct _krb5_encryption_type _krb5_enctype_des_cfb64_none = { - ETYPE_DES_CFB64_NONE, - "des-cfb64-none", - NULL, - 1, - 1, - 0, - &keytype_des_old, - &_krb5_checksum_none, - NULL, - F_PSEUDO|F_DISABLED|F_WEAK|F_OLD, - DES_CFB64_encrypt_null_ivec, - NULL, - 0, - NULL -}; - -struct _krb5_encryption_type _krb5_enctype_des_pcbc_none = { - ETYPE_DES_PCBC_NONE, - "des-pcbc-none", - NULL, - 8, - 8, - 0, - &keytype_des_old, - &_krb5_checksum_none, - NULL, - F_PSEUDO|F_DISABLED|F_WEAK|F_OLD, - DES_PCBC_encrypt_key_ivec, - NULL, - 0, - NULL -}; #endif /* HEIM_WEAK_CRYPTO */ diff --git a/lib/krb5/crypto-des3.c b/lib/krb5/crypto-des3.c deleted file mode 100644 index d231921d6..000000000 --- a/lib/krb5/crypto-des3.c +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "krb5_locl.h" - -/* - * - */ - -static void -DES3_random_key(krb5_context context, - krb5_keyblock *key) -{ - DES_cblock *k = key->keyvalue.data; - do { - krb5_generate_random_block(k, 3 * sizeof(DES_cblock)); - DES_set_odd_parity(&k[0]); - DES_set_odd_parity(&k[1]); - DES_set_odd_parity(&k[2]); - } while(DES_is_weak_key(&k[0]) || - DES_is_weak_key(&k[1]) || - DES_is_weak_key(&k[2])); -} - -static krb5_error_code -DES3_prf(krb5_context context, - krb5_crypto crypto, - const krb5_data *in, - krb5_data *out) -{ - struct _krb5_checksum_type *ct = crypto->et->checksum; - struct krb5_crypto_iov iov[1]; - krb5_error_code ret; - Checksum result; - krb5_keyblock *derived; - - result.cksumtype = ct->type; - ret = krb5_data_alloc(&result.checksum, ct->checksumsize); - if (ret) { - krb5_set_error_message(context, ret, N_("malloc: out memory", "")); - return ret; - } - - iov[0].data = *in; - iov[0].flags = KRB5_CRYPTO_TYPE_DATA; - ret = (*ct->checksum)(context, crypto, NULL, 0, iov, 1, &result); - if (ret) { - krb5_data_free(&result.checksum); - return ret; - } - - if (result.checksum.length < crypto->et->blocksize) - krb5_abortx(context, "internal prf error"); - - derived = NULL; - ret = krb5_derive_key(context, crypto->key.key, - crypto->et->type, "prf", 3, &derived); - if (ret) - krb5_abortx(context, "krb5_derive_key"); - - ret = krb5_data_alloc(out, crypto->et->prf_length); - if (ret) - krb5_abortx(context, "malloc failed"); - - { - const EVP_CIPHER *c = (*crypto->et->keytype->evp)(); - EVP_CIPHER_CTX ctx; - - EVP_CIPHER_CTX_init(&ctx); /* ivec all zero */ - EVP_CipherInit_ex(&ctx, c, NULL, derived->keyvalue.data, NULL, 1); - EVP_Cipher(&ctx, out->data, result.checksum.data, - crypto->et->prf_length); - EVP_CIPHER_CTX_cleanup(&ctx); - } - - krb5_data_free(&result.checksum); - krb5_free_keyblock(context, derived); - - return ret; -} - -#ifdef DES3_OLD_ENCTYPE -static struct _krb5_key_type keytype_des3 = { - ETYPE_OLD_DES3_CBC_SHA1, - "des3", - 168, - 24, - sizeof(struct _krb5_evp_schedule), - DES3_random_key, - _krb5_evp_schedule, - _krb5_des3_salt, - _krb5_DES3_random_to_key, - _krb5_evp_cleanup, - EVP_des_ede3_cbc -}; -#endif - -static struct _krb5_key_type keytype_des3_derived = { - ETYPE_OLD_DES3_CBC_SHA1, - "des3", - 168, - 24, - sizeof(struct _krb5_evp_schedule), - DES3_random_key, - _krb5_evp_schedule, - _krb5_des3_salt_derived, - _krb5_DES3_random_to_key, - _krb5_evp_cleanup, - EVP_des_ede3_cbc -}; - -#ifdef DES3_OLD_ENCTYPE -static krb5_error_code -RSA_MD5_DES3_checksum(krb5_context context, - krb5_crypto crypto, - struct _krb5_key_data *key, - unsigned usage, - const struct krb5_crypto_iov *iov, - int niov, - Checksum *C) -{ - return _krb5_des_checksum(context, EVP_md5(), key, iov, niov, C); -} - -static krb5_error_code -RSA_MD5_DES3_verify(krb5_context context, - krb5_crypto crypto, - struct _krb5_key_data *key, - unsigned usage, - const struct krb5_crypto_iov *iov, - int niov, - Checksum *C) -{ - return _krb5_des_verify(context, EVP_md5(), key, iov, niov, C); -} - -struct _krb5_checksum_type _krb5_checksum_rsa_md5_des3 = { - CKSUMTYPE_RSA_MD5_DES3, - "rsa-md5-des3", - 64, - 24, - F_KEYED | F_CPROOF | F_VARIANT, - RSA_MD5_DES3_checksum, - RSA_MD5_DES3_verify -}; -#endif - -struct _krb5_checksum_type _krb5_checksum_hmac_sha1_des3 = { - CKSUMTYPE_HMAC_SHA1_DES3, - "hmac-sha1-des3", - 64, - 20, - F_KEYED | F_CPROOF | F_DERIVED, - _krb5_SP_HMAC_SHA1_checksum, - NULL -}; - -#ifdef DES3_OLD_ENCTYPE -struct _krb5_encryption_type _krb5_enctype_des3_cbc_md5 = { - ETYPE_DES3_CBC_MD5, - "des3-cbc-md5", - NULL, - 8, - 8, - 8, - &keytype_des3, - &_krb5_checksum_rsa_md5, - &_krb5_checksum_rsa_md5_des3, - F_OLD, - _krb5_evp_encrypt, - _krb5_evp_encrypt_iov, - 0, - NULL -}; -#endif - -struct _krb5_encryption_type _krb5_enctype_des3_cbc_sha1 = { - ETYPE_DES3_CBC_SHA1, - "des3-cbc-sha1", - NULL, - 8, - 8, - 8, - &keytype_des3_derived, - &_krb5_checksum_sha1, - &_krb5_checksum_hmac_sha1_des3, - F_DERIVED | F_RFC3961_ENC | F_RFC3961_KDF | F_OLD, - _krb5_evp_encrypt, - _krb5_evp_encrypt_iov, - 16, - DES3_prf -}; - -#ifdef DES3_OLD_ENCTYPE -struct _krb5_encryption_type _krb5_enctype_old_des3_cbc_sha1 = { - ETYPE_OLD_DES3_CBC_SHA1, - "old-des3-cbc-sha1", - NULL, - 8, - 8, - 8, - &keytype_des3, - &_krb5_checksum_sha1, - &_krb5_checksum_hmac_sha1_des3, - F_OLD, - _krb5_evp_encrypt, - _krb5_evp_encrypt_iov, - 0, - NULL -}; -#endif - -struct _krb5_encryption_type _krb5_enctype_des3_cbc_none = { - ETYPE_DES3_CBC_NONE, - "des3-cbc-none", - NULL, - 8, - 8, - 0, - &keytype_des3_derived, - &_krb5_checksum_none, - NULL, - F_PSEUDO | F_OLD, - _krb5_evp_encrypt, - _krb5_evp_encrypt_iov, - 0, - NULL -}; - -void -_krb5_DES3_random_to_key(krb5_context context, - krb5_keyblock *key, - const void *data, - size_t size) -{ - unsigned char *x = key->keyvalue.data; - const u_char *q = data; - DES_cblock *k; - int i, j; - - memset(key->keyvalue.data, 0, key->keyvalue.length); - for (i = 0; i < 3; ++i) { - unsigned char foo; - for (j = 0; j < 7; ++j) { - unsigned char b = q[7 * i + j]; - - x[8 * i + j] = b; - } - foo = 0; - for (j = 6; j >= 0; --j) { - foo |= q[7 * i + j] & 1; - foo <<= 1; - } - x[8 * i + 7] = foo; - } - k = key->keyvalue.data; - for (i = 0; i < 3; i++) { - DES_set_odd_parity(&k[i]); - if(DES_is_weak_key(&k[i])) - _krb5_xor8(k[i], (const unsigned char*)"\0\0\0\0\0\0\0\xf0"); - } -} diff --git a/lib/krb5/crypto-evp.c b/lib/krb5/crypto-evp.c index 82237f151..2d7b7d1d2 100644 --- a/lib/krb5/crypto-evp.c +++ b/lib/krb5/crypto-evp.c @@ -33,27 +33,50 @@ #include "krb5_locl.h" -void +int _krb5_evp_schedule(krb5_context context, struct _krb5_key_type *kt, struct _krb5_key_data *kd) { struct _krb5_evp_schedule *key = kd->schedule->data; - const EVP_CIPHER *c = (*kt->evp)(); + const EVP_CIPHER *c = (*kt->evp)(context); - EVP_CIPHER_CTX_init(&key->ectx); - EVP_CIPHER_CTX_init(&key->dctx); + if (c == NULL) { + krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, + "Encryption type disabled or not available: %s", + kt->name); + return KRB5_PROG_ETYPE_NOSUPP; + } - EVP_CipherInit_ex(&key->ectx, c, NULL, kd->key->keyvalue.data, NULL, 1); - EVP_CipherInit_ex(&key->dctx, c, NULL, kd->key->keyvalue.data, NULL, 0); + if (key->ectx == NULL) { + if ((key->ectx = EVP_CIPHER_CTX_new()) == NULL) + return krb5_enomem(context); + EVP_CIPHER_CTX_init(key->ectx); + } + if (key->dctx == NULL) { + if ((key->dctx = EVP_CIPHER_CTX_new()) == NULL) + return krb5_enomem(context); + EVP_CIPHER_CTX_init(key->dctx); + } + + if (EVP_CipherInit_ex(key->ectx, c, NULL, + kd->key->keyvalue.data, NULL, 1) != 1 || + EVP_CipherInit_ex(key->dctx, c, NULL, + kd->key->keyvalue.data, NULL, 0) != 1) { + return _krb5_set_error_message_openssl(context, KRB5_CRYPTO_INTERNAL, + "Failed to encrypt"); + } + return 0; } void _krb5_evp_cleanup(krb5_context context, struct _krb5_key_data *kd) { struct _krb5_evp_schedule *key = kd->schedule->data; - EVP_CIPHER_CTX_cleanup(&key->ectx); - EVP_CIPHER_CTX_cleanup(&key->dctx); + EVP_CIPHER_CTX_free(key->ectx); + EVP_CIPHER_CTX_free(key->dctx); + key->ectx = NULL; + key->dctx = NULL; } int @@ -122,27 +145,63 @@ _krb5_evp_hmac_iov(krb5_context context, int niov, void *hmac, unsigned int *hmaclen, - const EVP_MD *md, - ENGINE *engine) + const EVP_MD *md) { - HMAC_CTX *ctx; + EVP_MAC *mac; + EVP_MAC_CTX *ctx; + const char *mdname = EVP_MD_get0_name(md); // can't be NULL can it krb5_data current = {0, NULL}; + OSSL_PARAM params[] = { + OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, (char *)mdname, 0), + OSSL_PARAM_END + }; + size_t outlen = 0; + int ret = EINVAL; int i; - if (crypto != NULL) { - if (crypto->hmacctx == NULL) - crypto->hmacctx = HMAC_CTX_new(); - ctx = crypto->hmacctx; - } else { - ctx = HMAC_CTX_new(); - } - if (ctx == NULL) - return krb5_enomem(context); +#if 0 + int dlen = EVP_MD_get_size(md); - if (HMAC_Init_ex(ctx, key->key->keyvalue.data, key->key->keyvalue.length, - md, engine) == 0) { - HMAC_CTX_free(ctx); - return krb5_enomem(context); + if (mdname == NULL) { + krb5_set_error_message(context, EINVAL, + "Unknown digest for HMAC"); + return EINVAL; + } + if (dlen < 1) { + krb5_set_error_message(context, EINVAL, + "Digest %s length invalid", mdname); + return EINVAL; + } + if (hmaclen < (unsigned int)dlen) { + krb5_set_error_message(context, EINVAL, + "HMAC buffer length too small (need %d, got %u)", + dlen, hmaclen); + return EINVAL; + } +#endif + + if (crypto != NULL) { + if (crypto->mac == NULL) + crypto->mac = EVP_MAC_fetch(context->ossl->libctx, "HMAC", + context->ossl->propq); + if (crypto->hmacctx == NULL) + crypto->hmacctx = EVP_MAC_CTX_new(crypto->mac); + ctx = crypto->hmacctx; + mac = crypto->mac; + } else { + mac = EVP_MAC_fetch(context->ossl->libctx, "HMAC", context->ossl->propq); + ctx = EVP_MAC_CTX_new(mac); + } + if (ctx == NULL) { + ret = krb5_enomem(context); + goto out; + } + + if (EVP_MAC_init(ctx, key->key->keyvalue.data, key->key->keyvalue.length, + params) != 1) { + ret = _krb5_set_error_message_openssl(context, KRB5_CRYPTO_INTERNAL, + "Failed to initialize HMAC"); + goto out; } for (i = 0; i < niov; i++) { @@ -151,22 +210,31 @@ _krb5_evp_hmac_iov(krb5_context context, (char *)current.data + current.length == iov[i].data.data) { current.length += iov[i].data.length; } else { - if (current.data) - HMAC_Update(ctx, current.data, current.length); + if (current.data && + EVP_MAC_update(ctx, current.data, current.length) != 1) + goto out; current = iov[i].data; } } } - if (current.data) - HMAC_Update(ctx, current.data, current.length); + if (current.data && + EVP_MAC_update(ctx, current.data, current.length) != 1) + goto out; - HMAC_Final(ctx, hmac, hmaclen); + if (EVP_MAC_final(ctx, hmac, &outlen, *hmaclen) != 1) + goto out; - if (crypto == NULL) - HMAC_CTX_free(ctx); + *hmaclen = outlen; + ret = 0; - return 0; +out: + if (crypto == NULL) { + EVP_MAC_CTX_free(ctx); + EVP_MAC_free(mac); + } + + return ret; } krb5_error_code @@ -180,7 +248,9 @@ _krb5_evp_encrypt(krb5_context context, { struct _krb5_evp_schedule *ctx = key->schedule->data; EVP_CIPHER_CTX *c; - c = encryptp ? &ctx->ectx : &ctx->dctx; + int ret = 0; + + c = encryptp ? ctx->ectx : ctx->dctx; if (ivec == NULL) { /* alloca ? */ size_t len2 = EVP_CIPHER_CTX_iv_length(c); @@ -188,12 +258,17 @@ _krb5_evp_encrypt(krb5_context context, if (loiv == NULL) return krb5_enomem(context); memset(loiv, 0, len2); - EVP_CipherInit_ex(c, NULL, NULL, NULL, loiv, -1); + if (EVP_CipherInit_ex(c, NULL, NULL, NULL, loiv, -1) != 1) { + ret = _krb5_set_error_message_openssl(context, KRB5_CRYPTO_INTERNAL, + "Failed to initialize cipher"); + } free(loiv); - } else - EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1); + } else if (EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1) != 1) { + ret = _krb5_set_error_message_openssl(context, KRB5_CRYPTO_INTERNAL, + "Failed to initialize cipher"); + } EVP_Cipher(c, data, data, len); - return 0; + return ret; } struct _krb5_evp_iov_cursor @@ -370,17 +445,21 @@ _krb5_evp_encrypt_iov(krb5_context context, unsigned char tmp[EVP_MAX_BLOCK_LENGTH]; EVP_CIPHER_CTX *c; struct _krb5_evp_iov_cursor cursor; + int oret; - c = encryptp ? &ctx->ectx : &ctx->dctx; + c = encryptp ? ctx->ectx : ctx->dctx; blocksize = EVP_CIPHER_CTX_block_size(c); blockmask = ~(blocksize - 1); if (ivec) - EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1); + oret = EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1); else - EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1); + oret = EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1); + if (oret != 1) + return _krb5_set_error_message_openssl(context, KRB5_CRYPTO_INTERNAL, + "Failed to initialize cipher"); _krb5_evp_iov_cursor_init(&cursor, iov, niov); @@ -390,8 +469,11 @@ _krb5_evp_encrypt_iov(krb5_context context, wholeblocks = cursor.current.length & ~blockmask; if (wholeblocks != 0) { - EVP_Cipher(c, cursor.current.data, - cursor.current.data, wholeblocks); + if (EVP_Cipher(c, cursor.current.data, + cursor.current.data, wholeblocks) != wholeblocks) + return _krb5_set_error_message_openssl(context, + KRB5_CRYPTO_INTERNAL, + "Failed to encrypt"); _krb5_evp_iov_cursor_advance(&cursor, wholeblocks); } @@ -402,7 +484,10 @@ _krb5_evp_encrypt_iov(krb5_context context, * pointing at where we started */ _krb5_evp_iov_cursor_fillbuf(&cursor, tmp, blocksize, NULL); - EVP_Cipher(c, tmp, tmp, blocksize); + if (EVP_Cipher(c, tmp, tmp, blocksize) != blocksize) + return _krb5_set_error_message_openssl(context, + KRB5_CRYPTO_INTERNAL, + "Failed to encrypt"); /* Copy the data in tmp back into the iovecs that it came from, * advancing the cursor */ @@ -429,9 +514,9 @@ _krb5_evp_encrypt_iov_cts(krb5_context context, unsigned char tmp[EVP_MAX_BLOCK_LENGTH], tmp2[EVP_MAX_BLOCK_LENGTH]; unsigned char tmp3[EVP_MAX_BLOCK_LENGTH], ivec2[EVP_MAX_BLOCK_LENGTH]; EVP_CIPHER_CTX *c; - int i; + int oret, i; - c = encryptp ? &ctx->ectx : &ctx->dctx; + c = encryptp ? ctx->ectx : ctx->dctx; blocksize = EVP_CIPHER_CTX_block_size(c); blockmask = ~(blocksize - 1); @@ -449,9 +534,12 @@ _krb5_evp_encrypt_iov_cts(krb5_context context, encryptp, usage, ivec); if (ivec) - EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1); + oret = EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1); else - EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1); + oret = EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1); + if (oret != 1) + return _krb5_set_error_message_openssl(context, EINVAL, + "Failed to encrypt"); if (encryptp) { /* On our first pass, we want to process everything but the @@ -476,7 +564,10 @@ _krb5_evp_encrypt_iov_cts(krb5_context context, while (remaining > 0) { /* If the iovec has more data than we need, just use it */ if (cursor.current.length >= remaining) { - EVP_Cipher(c, cursor.current.data, cursor.current.data, remaining); + if (EVP_Cipher(c, cursor.current.data, cursor.current.data, + remaining) != remaining) + return _krb5_set_error_message_openssl(context, EINVAL, + "Failed to encrypt"); if (encryptp) { /* We've just encrypted the last block of data. Make a copy @@ -493,8 +584,10 @@ _krb5_evp_encrypt_iov_cts(krb5_context context, wholeblocks = cursor.current.length & blockmask; if (wholeblocks > 0) { - EVP_Cipher(c, cursor.current.data, cursor.current.data, - wholeblocks); + if (EVP_Cipher(c, cursor.current.data, cursor.current.data, + wholeblocks) != wholeblocks) + return _krb5_set_error_message_openssl(context, EINVAL, + "Failed to encrypt"); _krb5_evp_iov_cursor_advance(&cursor, wholeblocks); remaining -= wholeblocks; } @@ -506,7 +599,9 @@ _krb5_evp_encrypt_iov_cts(krb5_context context, lastpos = cursor; _krb5_evp_iov_cursor_fillbuf(&cursor, ivec2, blocksize, NULL); - EVP_Cipher(c, ivec2, ivec2, blocksize); + if (EVP_Cipher(c, ivec2, ivec2, blocksize) != blocksize) + return _krb5_set_error_message_openssl(context, EINVAL, + "Failed to encrypt"); _krb5_evp_iov_cursor_fillvec(&cursor, ivec2, blocksize); remaining -= blocksize; @@ -525,8 +620,10 @@ _krb5_evp_encrypt_iov_cts(krb5_context context, for (; i < blocksize; i++) tmp[i] = 0 ^ ivec2[i]; /* XOR 0s if partial block exhausted */ - EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1); - EVP_Cipher(c, tmp, tmp, blocksize); + if (EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1) != 1 || + EVP_Cipher(c, tmp, tmp, blocksize) != blocksize) + return _krb5_set_error_message_openssl(context, EINVAL, + "Failed to encrypt"); _krb5_evp_iov_cursor_fillvec(&lastpos, tmp, blocksize); _krb5_evp_iov_cursor_fillvec(&cursor, ivec2, partiallen); @@ -548,14 +645,18 @@ _krb5_evp_encrypt_iov_cts(krb5_context context, memcpy(ivec2, zero_ivec, blocksize); } else { _krb5_evp_iov_cursor_fillbuf(&cursor, ivec2, blocksize, NULL); - EVP_Cipher(c, tmp, ivec2, blocksize); + if (EVP_Cipher(c, tmp, ivec2, blocksize) != blocksize) + return _krb5_set_error_message_openssl(context, EINVAL, + "Failed to encrypt"); _krb5_evp_iov_cursor_fillvec(&cursor, tmp, blocksize); } lastpos = cursor; /* Remember where the last block is */ _krb5_evp_iov_cursor_fillbuf(&cursor, tmp, blocksize, &cursor); - EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1); - EVP_Cipher(c, tmp2, tmp, blocksize); /* tmp eventually becomes output ivec */ + if (EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1) != 1 || + EVP_Cipher(c, tmp2, tmp, blocksize) != blocksize) /* tmp eventually becomes output ivec */ + return _krb5_set_error_message_openssl(context, EINVAL, + "Failed to encrypt"); _krb5_evp_iov_cursor_fillbuf(&cursor, tmp3, partiallen, NULL); @@ -565,8 +666,10 @@ _krb5_evp_encrypt_iov_cts(krb5_context context, _krb5_evp_iov_cursor_fillvec(&cursor, tmp2, partiallen); - EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1); - EVP_Cipher(c, tmp3, tmp3, blocksize); + if (EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1) != 1 || + EVP_Cipher(c, tmp3, tmp3, blocksize) != blocksize) + return _krb5_set_error_message_openssl(context, EINVAL, + "Failed to encrypt"); for (i = 0; i < blocksize; i++) tmp3[i] ^= ivec2[i]; @@ -579,6 +682,36 @@ _krb5_evp_encrypt_iov_cts(krb5_context context, return 0; } +// XXX Maybe use OpenSSL's support for CTS. The pattern is: +// (Note that the variant of CTS used in Kerberos is CS3.) + +#if 0 + EVP_CIPHER *cbc = EVP_CIPHER_fetch(libctx, "AES-128-CBC", propq); + EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); + + /* init */ + EVP_EncryptInit_ex2(ctx, cbc, key, iv, NULL); + + /* CTS, no PKCS#7 padding */ + EVP_CIPHER_CTX_set_padding(ctx, 0); + + int cts_mode = OSSL_CIPHER_CTS_MODE_CS3; + OSSL_PARAM params[] = { + OSSL_PARAM_construct_int(OSSL_CIPHER_PARAM_CTS_MODE, &cts_mode), + OSSL_PARAM_END + }; + EVP_CIPHER_CTX_set_params(ctx, params); + + /* 'in' must already include the confounder block (caller responsibility) */ + int outl; + EVP_EncryptUpdate(ctx, out, &outl, in, inlen); + int finl; EVP_EncryptFinal_ex(ctx, out + outl, &finl); + + /* cleanup */ + EVP_CIPHER_CTX_free(ctx); + EVP_CIPHER_free(cbc); +#endif + krb5_error_code _krb5_evp_encrypt_cts(krb5_context context, struct _krb5_key_data *key, @@ -593,8 +726,9 @@ _krb5_evp_encrypt_cts(krb5_context context, unsigned char tmp[EVP_MAX_BLOCK_LENGTH], ivec2[EVP_MAX_BLOCK_LENGTH]; EVP_CIPHER_CTX *c; unsigned char *p; + int oret; - c = encryptp ? &ctx->ectx : &ctx->dctx; + c = encryptp ? ctx->ectx : ctx->dctx; blocksize = EVP_CIPHER_CTX_block_size(c); @@ -603,18 +737,22 @@ _krb5_evp_encrypt_cts(krb5_context context, "message block too short"); return EINVAL; } else if (len == blocksize) { - EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1); - EVP_Cipher(c, data, data, len); + if (EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1) != 1 || + EVP_Cipher(c, data, data, len) != len) + return _krb5_set_error_message_openssl(context, EINVAL, + "Failed to encrypt"); return 0; } if (ivec) - EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1); + oret = EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1); else - EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1); + oret = EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1); + if (oret != 1) + return _krb5_set_error_message_openssl(context, EINVAL, + "Failed to encrypt"); if (encryptp) { - p = data; i = ((len - 1) / blocksize) * blocksize; EVP_Cipher(c, p, p, i); @@ -627,8 +765,10 @@ _krb5_evp_encrypt_cts(krb5_context context, for (; i < blocksize; i++) tmp[i] = 0 ^ ivec2[i]; - EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1); - EVP_Cipher(c, p, tmp, blocksize); + if (EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1) != 1 || + EVP_Cipher(c, p, tmp, blocksize) != blocksize) + return _krb5_set_error_message_openssl(context, EINVAL, + "Failed to encrypt"); memcpy(p + blocksize, ivec2, len); if (ivec) @@ -653,8 +793,10 @@ _krb5_evp_encrypt_cts(krb5_context context, } memcpy(tmp, p, blocksize); - EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1); - EVP_Cipher(c, tmp2, p, blocksize); + if (EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1) != 1 || + EVP_Cipher(c, tmp2, p, blocksize) != blocksize) + return _krb5_set_error_message_openssl(context, EINVAL, + "Failed to encrypt"); memcpy(tmp3, p + blocksize, len); memcpy(tmp3 + len, tmp2 + len, blocksize - len); /* xor 0 */ @@ -662,8 +804,10 @@ _krb5_evp_encrypt_cts(krb5_context context, for (i = 0; i < len; i++) p[i + blocksize] = tmp2[i] ^ tmp3[i]; - EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1); - EVP_Cipher(c, p, tmp3, blocksize); + if (EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1) != 1 || + EVP_Cipher(c, p, tmp3, blocksize) != blocksize) + return _krb5_set_error_message_openssl(context, EINVAL, + "Failed to encrypt"); for (i = 0; i < blocksize; i++) p[i] ^= ivec2[i]; diff --git a/lib/krb5/crypto-pk.c b/lib/krb5/crypto-pk.c index a98d908ab..a7b9ab6cb 100644 --- a/lib/krb5/crypto-pk.c +++ b/lib/krb5/crypto-pk.c @@ -72,7 +72,7 @@ _krb5_pk_octetstring2key(krb5_context context, counter = 0; offset = 0; - do { + do { // RFC 4556 octet2string function -- yes, it uses SHA-1; switch to _krb5_pk_kdf()! EVP_DigestInit_ex(m, EVP_sha1(), NULL); EVP_DigestUpdate(m, &counter, 1); @@ -127,13 +127,12 @@ encode_uvinfo(krb5_context context, krb5_const_principal p, krb5_data *data) static krb5_error_code encode_otherinfo(krb5_context context, - const AlgorithmIdentifier *ai, + const heim_oid *ai, krb5_const_principal client, krb5_const_principal server, krb5_enctype enctype, const krb5_data *as_req, const krb5_data *pk_as_rep, - const Ticket *ticket, krb5_data *other) { PkinitSP80056AOtherInfo otherinfo; @@ -149,7 +148,6 @@ encode_otherinfo(krb5_context context, pubinfo.enctype = enctype; pubinfo.as_REQ = *as_req; pubinfo.pk_as_rep = *pk_as_rep; - pubinfo.ticket = *ticket; ASN1_MALLOC_ENCODE(PkinitSuppPubInfo, pub.data, pub.length, &pubinfo, &size, ret); if (ret) { @@ -171,7 +169,9 @@ encode_otherinfo(krb5_context context, return ret; } - otherinfo.algorithmID = *ai; + /* See https://www.rfc-editor.org/errata/eid8639 re: parameters */ + otherinfo.algorithmID.algorithm = *ai; + otherinfo.algorithmID.parameters = NULL; otherinfo.suppPubInfo = &pub; ASN1_MALLOC_ENCODE(PkinitSP80056AOtherInfo, other->data, other->length, @@ -189,22 +189,69 @@ encode_otherinfo(krb5_context context, return 0; } +/* + * This wrapper around _krb5_pk_kdf() uses the DER encodings of AS_REQ and + * PA_PK_AS_REP found in the _save fields of those structures. It also uses + * the client and server principal names from the AS_REQ structure. It also + * uses the server nonce from the PA_PK_AS_REP' dhInfo. The client nonce + * however has to be provided by the caller. + */ +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +_krb5_pk_kdf2(krb5_context context, + const AS_REQ *a, + const PA_PK_AS_REP *rep, + const void *dhdata, + size_t dhsize, + krb5_enctype enctype, + const heim_octet_string *c_n, + krb5_keyblock *key) +{ + krb5_error_code ret; + krb5_principal c = NULL; + krb5_principal s = NULL; + const heim_oid *kdf; + + if (rep->element != choice_PA_PK_AS_REP_dhInfo) + return EINVAL; /* Doesn't happen */ + + kdf = rep->u.dhInfo.kdf ? &rep->u.dhInfo.kdf->kdf_id : NULL; + + ret = _krb5_principalname2krb5_principal(context, &c, + *(a->req_body.cname), + a->req_body.realm); + + if (ret == 0) + ret = _krb5_principalname2krb5_principal(context, &s, + *(a->req_body.sname), + a->req_body.realm); + + if (ret == 0) + ret = _krb5_pk_kdf(context, kdf, dhdata, dhsize, c, s, enctype, c_n, + rep->u.dhInfo.serverDHNonce, &a->_save, &rep->_save, + NULL, key); + + krb5_free_principal(context, c); + krb5_free_principal(context, s); + return ret; +} KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL _krb5_pk_kdf(krb5_context context, - const struct AlgorithmIdentifier *ai, + const heim_oid *ai, const void *dhdata, size_t dhsize, krb5_const_principal client, krb5_const_principal server, krb5_enctype enctype, + const heim_octet_string *c_n, + const heim_octet_string *k_n, const krb5_data *as_req, const krb5_data *pk_as_rep, - const Ticket *ticket, + krb5_data *out, krb5_keyblock *key) { - struct _krb5_encryption_type *et; + struct _krb5_encryption_type *et = _krb5_find_enctype(enctype); krb5_error_code ret; krb5_data other; size_t keylen, offset; @@ -212,44 +259,54 @@ _krb5_pk_kdf(krb5_context context, unsigned char *keydata; unsigned char shaoutput[SHA512_DIGEST_LENGTH]; const EVP_MD *md; + const char *mdname = NULL; EVP_MD_CTX *m; - if (der_heim_oid_cmp(&asn1_oid_id_pkinit_kdf_ah_sha1, &ai->algorithm) == 0) { - md = EVP_sha1(); - } else if (der_heim_oid_cmp(&asn1_oid_id_pkinit_kdf_ah_sha256, &ai->algorithm) == 0) { - md = EVP_sha256(); - } else if (der_heim_oid_cmp(&asn1_oid_id_pkinit_kdf_ah_sha512, &ai->algorithm) == 0) { - md = EVP_sha512(); + if (out) { + out->data = NULL; + out->length = 0; + } + + if (ai == NULL) + return _krb5_pk_octetstring2key(context, enctype, dhdata, dhsize, + NULL, NULL, key); + if (der_heim_oid_cmp(&asn1_oid_id_pkinit_kdf_ah_sha1, ai) == 0) { + md = context->ossl->sha1; + mdname = "SHA-1"; + } else if (der_heim_oid_cmp(&asn1_oid_id_pkinit_kdf_ah_sha256, ai) == 0) { + md = context->ossl->sha256; + mdname = "SHA-256"; + } else if (der_heim_oid_cmp(&asn1_oid_id_pkinit_kdf_ah_sha384, ai) == 0) { + md = context->ossl->sha384; + mdname = "SHA-384"; + } else if (der_heim_oid_cmp(&asn1_oid_id_pkinit_kdf_ah_sha512, ai) == 0) { + md = context->ossl->sha512; + mdname = "SHA-512"; } else { krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, N_("KDF not supported", "")); return KRB5_PROG_ETYPE_NOSUPP; } - if (ai->parameters != NULL && - (ai->parameters->length != 2 || - memcmp(ai->parameters->data, "\x05\x00", 2) != 0)) - { - krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, - N_("kdf params not NULL or the NULL-type", - "")); - return KRB5_PROG_ETYPE_NOSUPP; - } - - et = _krb5_find_enctype(enctype); - if(et == NULL) { - krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, - N_("encryption type %d not supported", ""), - enctype); - return KRB5_PROG_ETYPE_NOSUPP; + if (md == NULL) { + krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, + "Digest %s for negotiated PKINIT KDF is disabled in OpenSSL", + mdname); + return KRB5_PROG_ETYPE_NOSUPP; } - keylen = (et->keytype->bits + 7) / 8; + + if (et) + keylen = (et->keytype->bits + 7) / 8; + else if (enctype == KRB5_ENCTYPE_DES3_CBC_SHA1) + keylen = 21; /* hack to support RFC 8636 test vectors */ + else + return KRB5_PROG_ETYPE_NOSUPP; keydata = malloc(keylen); if (keydata == NULL) return krb5_enomem(context); ret = encode_otherinfo(context, ai, client, server, - enctype, as_req, pk_as_rep, ticket, &other); + enctype, as_req, pk_as_rep, &other); if (ret) { free(keydata); return ret; @@ -287,9 +344,27 @@ _krb5_pk_kdf(krb5_context context, EVP_MD_CTX_destroy(m); free(other.data); - ret = krb5_random_to_key(context, enctype, keydata, keylen, key); - memset_s(keydata, keylen, 0, keylen); - free(keydata); + if (out) { + /* + * We have this feature so we can do test vectors for 3DES w/o having + * to have a 3DES enctype, as then krb5_random_to_key() would fail with + * KRB5_PROG_ETYPE_NOSUPP. + */ + out->data = keydata; + out->length = keylen; + } + + if (key) + ret = krb5_random_to_key(context, enctype, keydata, keylen, key); + + if (ret || out == NULL) { + memset_s(keydata, keylen, 0, keylen); + free(keydata); + if (out) { + out->data = NULL; + out->length = 0; + } + } return ret; } diff --git a/lib/krb5/crypto.c b/lib/krb5/crypto.c index af86f7c45..352082ef9 100644 --- a/lib/krb5/crypto.c +++ b/lib/krb5/crypto.c @@ -158,6 +158,7 @@ _key_schedule(krb5_context context, key->schedule = NULL; return ret; } + memset(key->schedule->data, 0, kt->schedule_size); (*kt->schedule)(context, kt, key); return 0; } @@ -338,6 +339,51 @@ krb5_hmac(krb5_context context, return ret; } +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +_krb5_hmac_start_ossl(krb5_context context, + const unsigned char *key, size_t keylen, + const EVP_MD *md, EVP_MAC_CTX **ctx) +{ + const char *mdname = EVP_MD_get0_name(md); // can't be NULL can it + OSSL_PARAM params[] = { + OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, (char *)mdname, 0), + OSSL_PARAM_END + }; + EVP_MAC *mac; + + *ctx = NULL; + mac = EVP_MAC_fetch(context->ossl->libctx, "HMAC", context->ossl->propq); + if ((*ctx = EVP_MAC_CTX_new(mac)) == NULL || + EVP_MAC_init(*ctx, key, keylen, params) != 1) { + EVP_MAC_free(mac); + return ENOMEM; + } + + return 0; +} + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +_krb5_hmac_ossl(krb5_context context, + const unsigned char *key, size_t keylen, + const unsigned char *in, unsigned int inlen, + unsigned char *out, size_t *outlen, + const EVP_MD *md) +{ + EVP_MAC_CTX *ctx; + int ret; + + ret = _krb5_hmac_start_ossl(context, key, keylen, md, &ctx); + if (ret) + return ret; + + if (EVP_MAC_update(ctx, in, inlen) != 1 || + EVP_MAC_final(ctx, out, outlen, *outlen) != 1) + ret = KRB5_CRYPTO_INTERNAL; + + EVP_MAC_CTX_free(ctx); + return ret; +} + krb5_error_code _krb5_SP_HMAC_SHA1_checksum(krb5_context context, krb5_crypto crypto, @@ -352,7 +398,7 @@ _krb5_SP_HMAC_SHA1_checksum(krb5_context context, unsigned int hmaclen = sizeof(hmac); ret = _krb5_evp_hmac_iov(context, crypto, key, iov, niov, hmac, &hmaclen, - EVP_sha1(), NULL); + EVP_sha1()); if (ret) return ret; @@ -378,7 +424,7 @@ _krb5_SP_HMAC_SHA1_verify(krb5_context context, krb5_data data; ret = _krb5_evp_hmac_iov(context, crypto, key, iov, niov, hmac, &hmaclen, - EVP_sha1(), NULL); + EVP_sha1()); if (ret) return ret; @@ -2362,10 +2408,7 @@ derive_key_rfc3961(krb5_context context, } } - if (kt->type == KRB5_ENCTYPE_OLD_DES3_CBC_SHA1) - _krb5_DES3_random_to_key(context, key->key, k, nblocks * et->blocksize); - else - memcpy(key->key->keyvalue.data, k, key->key->keyvalue.length); + memcpy(key->key->keyvalue.data, k, key->key->keyvalue.length); out: if (k) { @@ -2642,7 +2685,7 @@ krb5_crypto_destroy(krb5_context context, EVP_MD_CTX_destroy(crypto->mdctx); if (crypto->hmacctx) - HMAC_CTX_free(crypto->hmacctx); + EVP_MAC_CTX_free(crypto->hmacctx); free (crypto); return 0; diff --git a/lib/krb5/crypto.h b/lib/krb5/crypto.h index 58effa8b9..05b2d8d4a 100644 --- a/lib/krb5/crypto.h +++ b/lib/krb5/crypto.h @@ -77,11 +77,11 @@ struct _krb5_key_type { size_t size; size_t schedule_size; void (*random_key)(krb5_context, krb5_keyblock*); - void (*schedule)(krb5_context, struct _krb5_key_type *, struct _krb5_key_data *); + int (*schedule)(krb5_context, struct _krb5_key_type *, struct _krb5_key_data *); struct salt_type *string_to_key; void (*random_to_key)(krb5_context, krb5_keyblock*, const void*, size_t); void (*cleanup)(krb5_context, struct _krb5_key_data *); - const EVP_CIPHER *(*evp)(void); + EVP_CIPHER *(*evp)(krb5_context); }; struct _krb5_checksum_type { @@ -140,12 +140,7 @@ struct _krb5_encryption_type { extern struct _krb5_checksum_type _krb5_checksum_none; extern struct _krb5_checksum_type _krb5_checksum_crc32; -extern struct _krb5_checksum_type _krb5_checksum_rsa_md4; -extern struct _krb5_checksum_type _krb5_checksum_rsa_md4_des; -extern struct _krb5_checksum_type _krb5_checksum_rsa_md5_des; -extern struct _krb5_checksum_type _krb5_checksum_rsa_md5_des3; extern struct _krb5_checksum_type _krb5_checksum_rsa_md5; -extern struct _krb5_checksum_type _krb5_checksum_hmac_sha1_des3; extern struct _krb5_checksum_type _krb5_checksum_hmac_sha1_aes128; extern struct _krb5_checksum_type _krb5_checksum_hmac_sha1_aes256; extern struct _krb5_checksum_type _krb5_checksum_hmac_sha256_128_aes128; @@ -164,9 +159,6 @@ extern int _krb5_num_checksums; extern struct salt_type _krb5_AES_SHA1_salt[]; extern struct salt_type _krb5_AES_SHA2_salt[]; extern struct salt_type _krb5_arcfour_salt[]; -extern struct salt_type _krb5_des_salt[]; -extern struct salt_type _krb5_des3_salt[]; -extern struct salt_type _krb5_des3_salt_derived[]; /* Encryption types */ @@ -174,18 +166,7 @@ extern struct _krb5_encryption_type _krb5_enctype_aes256_cts_hmac_sha1; extern struct _krb5_encryption_type _krb5_enctype_aes128_cts_hmac_sha1; extern struct _krb5_encryption_type _krb5_enctype_aes128_cts_hmac_sha256_128; extern struct _krb5_encryption_type _krb5_enctype_aes256_cts_hmac_sha384_192; -extern struct _krb5_encryption_type _krb5_enctype_des3_cbc_sha1; -extern struct _krb5_encryption_type _krb5_enctype_des3_cbc_md5; -extern struct _krb5_encryption_type _krb5_enctype_des3_cbc_none; extern struct _krb5_encryption_type _krb5_enctype_arcfour_hmac_md5; -extern struct _krb5_encryption_type _krb5_enctype_des_cbc_md5; -extern struct _krb5_encryption_type _krb5_enctype_old_des3_cbc_sha1; -extern struct _krb5_encryption_type _krb5_enctype_des_cbc_crc; -extern struct _krb5_encryption_type _krb5_enctype_des_cbc_md4; -extern struct _krb5_encryption_type _krb5_enctype_des_cbc_md5; -extern struct _krb5_encryption_type _krb5_enctype_des_cbc_none; -extern struct _krb5_encryption_type _krb5_enctype_des_cfb64_none; -extern struct _krb5_encryption_type _krb5_enctype_des_pcbc_none; extern struct _krb5_encryption_type _krb5_enctype_null; extern struct _krb5_encryption_type *_krb5_etypes[]; @@ -199,3 +180,30 @@ _krb5_crypto_iov_should_sign(const struct krb5_crypto_iov *iov) || iov->flags == KRB5_CRYPTO_TYPE_HEADER || iov->flags == KRB5_CRYPTO_TYPE_PADDING); } + +/* Interface to the EVP crypto layer provided by hcrypto */ +struct _krb5_evp_schedule { + /* + * Normally we'd say EVP_CIPHER_CTX here, but! this header gets + * included in lib/krb5/pkinit-ec.c + */ + EVP_CIPHER_CTX *ectx; + EVP_CIPHER_CTX *dctx; +}; + +struct krb5_crypto_data { + struct _krb5_encryption_type *et; + struct _krb5_key_data key; + EVP_MAC_CTX *hmacctx; + EVP_MD_CTX *mdctx; + EVP_MAC *mac; + int num_key_usage; + struct _krb5_key_usage *key_usage; + krb5_flags flags; +}; + +/* + * Allow generation and verification of unkeyed checksums even when + * key material is available. + */ +#define KRB5_CRYPTO_FLAG_ALLOW_UNKEYED_CHECKSUM 0x01 diff --git a/lib/krb5/deprecated.c b/lib/krb5/deprecated.c index 172f08917..e236422c9 100644 --- a/lib/krb5/deprecated.c +++ b/lib/krb5/deprecated.c @@ -199,7 +199,7 @@ krb5_password_key_proc (krb5_context context, if (*key == NULL) return krb5_enomem(context); if (password == NULL) { - if(UI_UTIL_read_pw_string (buf, sizeof(buf), "Password: ", 0)) { + if (_krb5_UI_UTIL_read_pw_string(buf, sizeof(buf), "Password: ", 0)) { free (*key); krb5_clear_error_message(context); return KRB5_LIBOS_PWDINTR; diff --git a/lib/krb5/derived-key-test.c b/lib/krb5/derived-key-test.c index 0e927643f..ba9bc19b9 100644 --- a/lib/krb5/derived-key-test.c +++ b/lib/krb5/derived-key-test.c @@ -42,6 +42,7 @@ static struct testcase { unsigned char key[MAXSIZE]; unsigned char res[MAXSIZE]; } tests[] = { +#if 0 {ETYPE_DES3_CBC_SHA1, {0x00, 0x00, 0x00, 0x01, 0x55}, 5, {0xdc, 0xe0, 0x6b, 0x1f, 0x64, 0xc8, 0x57, 0xa1, 0x1c, 0x3d, 0xb5, 0x7c, 0x51, 0x89, 0x9b, 0x2c, 0xc1, 0x79, 0x10, 0x08, 0xce, 0x97, 0x3b, 0x92}, {0x92, 0x51, 0x79, 0xd0, 0x45, 0x91, 0xa7, 0x9b, 0x5d, 0x31, 0x92, 0xc4, 0xa7, 0xe9, 0xc2, 0x89, 0xb0, 0x49, 0xc7, 0x1f, 0x6e, 0xe6, 0x04, 0xcd}}, @@ -72,6 +73,7 @@ static struct testcase { {ETYPE_DES3_CBC_SHA1, {0x00, 0x00, 0x00, 0x01, 0xaa}, 5, {0x26, 0xdc, 0xe3, 0x34, 0xb5, 0x45, 0x29, 0x2f, 0x2f, 0xea, 0xb9, 0xa8, 0x70, 0x1a, 0x89, 0xa4, 0xb9, 0x9e, 0xb9, 0x94, 0x2c, 0xec, 0xd0, 0x16}, {0xf4, 0x8f, 0xfd, 0x6e, 0x83, 0xf8, 0x3e, 0x73, 0x54, 0xe6, 0x94, 0xfd, 0x25, 0x2c, 0xf8, 0x3b, 0xfe, 0x58, 0xf7, 0xd5, 0xba, 0x37, 0xec, 0x5d}}, +#endif {ETYPE_AES128_CTS_HMAC_SHA256_128, {0x00, 0x00, 0x00, 0x02, 0x99}, 5, {0x37, 0x05, 0xD9, 0x60, 0x80, 0xC1, 0x77, 0x28, 0xA0, 0xE8, 0x00, 0xEA, 0xB6, 0xE0, 0xD2, 0x3C}, {0xB3, 0x1A, 0x01, 0x8A, 0x48, 0xF5, 0x47, 0x76, 0xF4, 0x03, 0xE9, 0xA3, 0x96, 0x32, 0x5D, 0xC3}}, diff --git a/lib/krb5/digest.c b/lib/krb5/digest.c deleted file mode 100644 index cc37c6d8e..000000000 --- a/lib/krb5/digest.c +++ /dev/null @@ -1,1165 +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 "krb5_locl.h" -#include "digest_asn1.h" - -#ifndef HEIMDAL_SMALLER - -struct krb5_digest_data { - char *cbtype; - char *cbbinding; - - DigestInit init; - DigestInitReply initReply; - DigestRequest request; - DigestResponse response; -}; - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_digest_alloc(krb5_context context, krb5_digest *digest) -{ - krb5_digest d; - - d = calloc(1, sizeof(*d)); - if (d == NULL) { - *digest = NULL; - return krb5_enomem(context); - } - *digest = d; - - return 0; -} - -KRB5_LIB_FUNCTION void KRB5_LIB_CALL -krb5_digest_free(krb5_digest digest) -{ - if (digest == NULL) - return; - free_DigestInit(&digest->init); - free_DigestInitReply(&digest->initReply); - free_DigestRequest(&digest->request); - free_DigestResponse(&digest->response); - memset(digest, 0, sizeof(*digest)); - free(digest); - return; -} - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_digest_set_server_cb(krb5_context context, - krb5_digest digest, - const char *type, - const char *binding) -{ - if (digest->init.channel) { - krb5_set_error_message(context, EINVAL, - N_("server channel binding already set", "")); - return EINVAL; - } - digest->init.channel = calloc(1, sizeof(*digest->init.channel)); - if (digest->init.channel == NULL) - goto error; - - digest->init.channel->cb_type = strdup(type); - if (digest->init.channel->cb_type == NULL) - goto error; - - digest->init.channel->cb_binding = strdup(binding); - if (digest->init.channel->cb_binding == NULL) - goto error; - return 0; - error: - if (digest->init.channel) { - free(digest->init.channel->cb_type); - free(digest->init.channel->cb_binding); - free(digest->init.channel); - digest->init.channel = NULL; - } - return krb5_enomem(context); -} - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_digest_set_type(krb5_context context, - krb5_digest digest, - const char *type) -{ - if (digest->init.type) { - krb5_set_error_message(context, EINVAL, "client type already set"); - return EINVAL; - } - digest->init.type = strdup(type); - if (digest->init.type == NULL) - return krb5_enomem(context); - return 0; -} - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_digest_set_hostname(krb5_context context, - krb5_digest digest, - const char *hostname) -{ - if (digest->init.hostname) { - krb5_set_error_message(context, EINVAL, "server hostname already set"); - return EINVAL; - } - digest->init.hostname = malloc(sizeof(*digest->init.hostname)); - if (digest->init.hostname == NULL) - return krb5_enomem(context); - *digest->init.hostname = strdup(hostname); - if (*digest->init.hostname == NULL) { - free(digest->init.hostname); - digest->init.hostname = NULL; - return krb5_enomem(context); - } - return 0; -} - -KRB5_LIB_FUNCTION const char * KRB5_LIB_CALL -krb5_digest_get_server_nonce(krb5_context context, - krb5_digest digest) -{ - return digest->initReply.nonce; -} - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_digest_set_server_nonce(krb5_context context, - krb5_digest digest, - const char *nonce) -{ - if (digest->request.serverNonce) { - krb5_set_error_message(context, EINVAL, N_("nonce already set", "")); - return EINVAL; - } - digest->request.serverNonce = strdup(nonce); - if (digest->request.serverNonce == NULL) - return krb5_enomem(context); - return 0; -} - -KRB5_LIB_FUNCTION const char * KRB5_LIB_CALL -krb5_digest_get_opaque(krb5_context context, - krb5_digest digest) -{ - return digest->initReply.opaque; -} - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_digest_set_opaque(krb5_context context, - krb5_digest digest, - const char *opaque) -{ - if (digest->request.opaque) { - krb5_set_error_message(context, EINVAL, "opaque already set"); - return EINVAL; - } - digest->request.opaque = strdup(opaque); - if (digest->request.opaque == NULL) - return krb5_enomem(context); - return 0; -} - -KRB5_LIB_FUNCTION const char * KRB5_LIB_CALL -krb5_digest_get_identifier(krb5_context context, - krb5_digest digest) -{ - if (digest->initReply.identifier == NULL) - return NULL; - return *digest->initReply.identifier; -} - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_digest_set_identifier(krb5_context context, - krb5_digest digest, - const char *id) -{ - if (digest->request.identifier) { - krb5_set_error_message(context, EINVAL, N_("identifier already set", "")); - return EINVAL; - } - digest->request.identifier = calloc(1, sizeof(*digest->request.identifier)); - if (digest->request.identifier == NULL) - return krb5_enomem(context); - *digest->request.identifier = strdup(id); - if (*digest->request.identifier == NULL) { - free(digest->request.identifier); - digest->request.identifier = NULL; - return krb5_enomem(context); - } - return 0; -} - -static krb5_error_code -digest_request(krb5_context context, - krb5_realm realm, - krb5_ccache ccache, - krb5_key_usage usage, - const DigestReqInner *ireq, - DigestRepInner *irep) -{ - DigestREQ req; - DigestREP rep; - krb5_error_code ret; - krb5_data data, data2; - size_t size = 0; - krb5_crypto crypto = NULL; - krb5_auth_context ac = NULL; - krb5_principal principal = NULL; - krb5_ccache id = NULL; - krb5_realm r = NULL; - - krb5_data_zero(&data); - krb5_data_zero(&data2); - memset(&req, 0, sizeof(req)); - memset(&rep, 0, sizeof(rep)); - - if (ccache == NULL) { - ret = krb5_cc_default(context, &id); - if (ret) - goto out; - } else - id = ccache; - - if (realm == NULL) { - ret = krb5_get_default_realm(context, &r); - if (ret) - goto out; - } else - r = realm; - - /* - * - */ - - ret = krb5_make_principal(context, &principal, - r, KRB5_DIGEST_NAME, r, NULL); - if (ret) - goto out; - - ASN1_MALLOC_ENCODE(DigestReqInner, data.data, data.length, - ireq, &size, ret); - if (ret) { - krb5_set_error_message(context, ret, - N_("Failed to encode digest inner request", "")); - goto out; - } - if (size != data.length) - krb5_abortx(context, "ASN.1 internal encoder error"); - - ret = krb5_mk_req_exact(context, &ac, - AP_OPTS_USE_SUBKEY|AP_OPTS_MUTUAL_REQUIRED, - principal, NULL, id, &req.apReq); - if (ret) - goto out; - - { - krb5_keyblock *key; - - ret = krb5_auth_con_getlocalsubkey(context, ac, &key); - if (ret) - goto out; - if (key == NULL) { - ret = EINVAL; - krb5_set_error_message(context, ret, - N_("Digest failed to get local subkey", "")); - goto out; - } - - ret = krb5_crypto_init(context, key, 0, &crypto); - krb5_free_keyblock (context, key); - if (ret) - goto out; - } - - ret = krb5_encrypt_EncryptedData(context, crypto, usage, - data.data, data.length, 0, - &req.innerReq); - if (ret) - goto out; - - krb5_data_free(&data); - - ASN1_MALLOC_ENCODE(DigestREQ, data.data, data.length, - &req, &size, ret); - if (ret) { - krb5_set_error_message(context, ret, - N_("Failed to encode DigestREQest", "")); - goto out; - } - if (size != data.length) - krb5_abortx(context, "ASN.1 internal encoder error"); - - ret = krb5_sendto_kdc(context, &data, &r, &data2); - if (ret) - goto out; - - ret = decode_DigestREP(data2.data, data2.length, &rep, NULL); - if (ret) { - krb5_set_error_message(context, ret, - N_("Failed to parse digest response", "")); - goto out; - } - - { - krb5_ap_rep_enc_part *repl; - - ret = krb5_rd_rep(context, ac, &rep.apRep, &repl); - if (ret) - goto out; - - krb5_free_ap_rep_enc_part(context, repl); - } - { - krb5_keyblock *key; - - ret = krb5_auth_con_getremotesubkey(context, ac, &key); - if (ret) - goto out; - if (key == NULL) { - ret = EINVAL; - krb5_set_error_message(context, ret, - N_("Digest reply has no remote subkey", "")); - goto out; - } - - krb5_crypto_destroy(context, crypto); - ret = krb5_crypto_init(context, key, 0, &crypto); - krb5_free_keyblock (context, key); - if (ret) - goto out; - } - - krb5_data_free(&data); - ret = krb5_decrypt_EncryptedData(context, crypto, usage, - &rep.innerRep, &data); - if (ret) - goto out; - - ret = decode_DigestRepInner(data.data, data.length, irep, NULL); - if (ret) { - krb5_set_error_message(context, ret, - N_("Failed to decode digest inner reply", "")); - goto out; - } - - out: - if (ccache == NULL && id) - krb5_cc_close(context, id); - if (realm == NULL && r) - free(r); - if (crypto) - krb5_crypto_destroy(context, crypto); - if (ac) - krb5_auth_con_free(context, ac); - if (principal) - krb5_free_principal(context, principal); - - krb5_data_free(&data); - krb5_data_free(&data2); - - free_DigestREQ(&req); - free_DigestREP(&rep); - - return ret; -} - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_digest_init_request(krb5_context context, - krb5_digest digest, - krb5_realm realm, - krb5_ccache ccache) -{ - DigestReqInner ireq; - DigestRepInner irep; - krb5_error_code ret; - - memset(&ireq, 0, sizeof(ireq)); - memset(&irep, 0, sizeof(irep)); - - if (digest->init.type == NULL) { - krb5_set_error_message(context, EINVAL, - N_("Type missing from init req", "")); - return EINVAL; - } - - ireq.element = choice_DigestReqInner_init; - ireq.u.init = digest->init; - - ret = digest_request(context, realm, ccache, - KRB5_KU_DIGEST_ENCRYPT, &ireq, &irep); - if (ret) - goto out; - - if (irep.element == choice_DigestRepInner_error) { - ret = irep.u.error.code; - krb5_set_error_message(context, ret, N_("Digest init error: %s", ""), - irep.u.error.reason); - goto out; - } - - if (irep.element != choice_DigestRepInner_initReply) { - ret = EINVAL; - krb5_set_error_message(context, ret, - N_("digest reply not an initReply", "")); - goto out; - } - - ret = copy_DigestInitReply(&irep.u.initReply, &digest->initReply); - if (ret) { - krb5_set_error_message(context, ret, - N_("Failed to copy initReply", "")); - goto out; - } - - out: - free_DigestRepInner(&irep); - - return ret; -} - - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_digest_set_client_nonce(krb5_context context, - krb5_digest digest, - const char *nonce) -{ - if (digest->request.clientNonce) { - krb5_set_error_message(context, EINVAL, - N_("clientNonce already set", "")); - return EINVAL; - } - digest->request.clientNonce = - calloc(1, sizeof(*digest->request.clientNonce)); - if (digest->request.clientNonce == NULL) - return krb5_enomem(context); - *digest->request.clientNonce = strdup(nonce); - if (*digest->request.clientNonce == NULL) { - free(digest->request.clientNonce); - digest->request.clientNonce = NULL; - return krb5_enomem(context); - } - return 0; -} - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_digest_set_digest(krb5_context context, - krb5_digest digest, - const char *dgst) -{ - if (digest->request.digest) { - krb5_set_error_message(context, EINVAL, - N_("digest already set", "")); - return EINVAL; - } - digest->request.digest = strdup(dgst); - if (digest->request.digest == NULL) - return krb5_enomem(context); - return 0; -} - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_digest_set_username(krb5_context context, - krb5_digest digest, - const char *username) -{ - if (digest->request.username) { - krb5_set_error_message(context, EINVAL, "username already set"); - return EINVAL; - } - digest->request.username = strdup(username); - if (digest->request.username == NULL) - return krb5_enomem(context); - return 0; -} - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_digest_set_authid(krb5_context context, - krb5_digest digest, - const char *authid) -{ - if (digest->request.authid) { - krb5_set_error_message(context, EINVAL, "authid already set"); - return EINVAL; - } - digest->request.authid = malloc(sizeof(*digest->request.authid)); - if (digest->request.authid == NULL) - return krb5_enomem(context); - *digest->request.authid = strdup(authid); - if (*digest->request.authid == NULL) { - free(digest->request.authid); - digest->request.authid = NULL; - return krb5_enomem(context); - } - return 0; -} - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_digest_set_authentication_user(krb5_context context, - krb5_digest digest, - krb5_principal authentication_user) -{ - krb5_error_code ret; - - if (digest->request.authentication_user) { - krb5_set_error_message(context, EINVAL, - N_("authentication_user already set", "")); - return EINVAL; - } - ret = krb5_copy_principal(context, - authentication_user, - &digest->request.authentication_user); - if (ret) - return ret; - return 0; -} - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_digest_set_realm(krb5_context context, - krb5_digest digest, - const char *realm) -{ - if (digest->request.realm) { - krb5_set_error_message(context, EINVAL, "realm already set"); - return EINVAL; - } - digest->request.realm = malloc(sizeof(*digest->request.realm)); - if (digest->request.realm == NULL) - return krb5_enomem(context); - *digest->request.realm = strdup(realm); - if (*digest->request.realm == NULL) { - free(digest->request.realm); - digest->request.realm = NULL; - return krb5_enomem(context); - } - return 0; -} - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_digest_set_method(krb5_context context, - krb5_digest digest, - const char *method) -{ - if (digest->request.method) { - krb5_set_error_message(context, EINVAL, - N_("method already set", "")); - return EINVAL; - } - digest->request.method = malloc(sizeof(*digest->request.method)); - if (digest->request.method == NULL) - return krb5_enomem(context); - *digest->request.method = strdup(method); - if (*digest->request.method == NULL) { - free(digest->request.method); - digest->request.method = NULL; - return krb5_enomem(context); - } - return 0; -} - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_digest_set_uri(krb5_context context, - krb5_digest digest, - const char *uri) -{ - if (digest->request.uri) { - krb5_set_error_message(context, EINVAL, N_("uri already set", "")); - return EINVAL; - } - digest->request.uri = malloc(sizeof(*digest->request.uri)); - if (digest->request.uri == NULL) - return krb5_enomem(context); - *digest->request.uri = strdup(uri); - if (*digest->request.uri == NULL) { - free(digest->request.uri); - digest->request.uri = NULL; - return krb5_enomem(context); - } - return 0; -} - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_digest_set_nonceCount(krb5_context context, - krb5_digest digest, - const char *nonce_count) -{ - if (digest->request.nonceCount) { - krb5_set_error_message(context, EINVAL, - N_("nonceCount already set", "")); - return EINVAL; - } - digest->request.nonceCount = - malloc(sizeof(*digest->request.nonceCount)); - if (digest->request.nonceCount == NULL) - return krb5_enomem(context); - *digest->request.nonceCount = strdup(nonce_count); - if (*digest->request.nonceCount == NULL) { - free(digest->request.nonceCount); - digest->request.nonceCount = NULL; - return krb5_enomem(context); - } - return 0; -} - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_digest_set_qop(krb5_context context, - krb5_digest digest, - const char *qop) -{ - if (digest->request.qop) { - krb5_set_error_message(context, EINVAL, "qop already set"); - return EINVAL; - } - digest->request.qop = malloc(sizeof(*digest->request.qop)); - if (digest->request.qop == NULL) - return krb5_enomem(context); - *digest->request.qop = strdup(qop); - if (*digest->request.qop == NULL) { - free(digest->request.qop); - digest->request.qop = NULL; - return krb5_enomem(context); - } - return 0; -} - -KRB5_LIB_FUNCTION int KRB5_LIB_CALL -krb5_digest_set_responseData(krb5_context context, - krb5_digest digest, - const char *response) -{ - digest->request.responseData = strdup(response); - if (digest->request.responseData == NULL) - return krb5_enomem(context); - return 0; -} - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_digest_request(krb5_context context, - krb5_digest digest, - krb5_realm realm, - krb5_ccache ccache) -{ - DigestReqInner ireq; - DigestRepInner irep; - krb5_error_code ret; - - memset(&ireq, 0, sizeof(ireq)); - memset(&irep, 0, sizeof(irep)); - - ireq.element = choice_DigestReqInner_digestRequest; - ireq.u.digestRequest = digest->request; - - if (digest->request.type == NULL) { - if (digest->init.type == NULL) { - krb5_set_error_message(context, EINVAL, - N_("Type missing from req", "")); - return EINVAL; - } - ireq.u.digestRequest.type = digest->init.type; - } - - if (ireq.u.digestRequest.digest == NULL) { - static char md5[] = "md5"; - ireq.u.digestRequest.digest = md5; - } - - ret = digest_request(context, realm, ccache, - KRB5_KU_DIGEST_ENCRYPT, &ireq, &irep); - if (ret) - return ret; - - if (irep.element == choice_DigestRepInner_error) { - ret = irep.u.error.code; - krb5_set_error_message(context, ret, - N_("Digest response error: %s", ""), - irep.u.error.reason); - goto out; - } - - if (irep.element != choice_DigestRepInner_response) { - krb5_set_error_message(context, EINVAL, - N_("digest reply not an DigestResponse", "")); - ret = EINVAL; - goto out; - } - - ret = copy_DigestResponse(&irep.u.response, &digest->response); - if (ret) { - krb5_set_error_message(context, ret, - N_("Failed to copy initReply,", "")); - goto out; - } - - out: - free_DigestRepInner(&irep); - - return ret; -} - -KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL -krb5_digest_rep_get_status(krb5_context context, - krb5_digest digest) -{ - return digest->response.success ? TRUE : FALSE; -} - -KRB5_LIB_FUNCTION const char * KRB5_LIB_CALL -krb5_digest_get_rsp(krb5_context context, - krb5_digest digest) -{ - if (digest->response.rsp == NULL) - return NULL; - return *digest->response.rsp; -} - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_digest_get_tickets(krb5_context context, - krb5_digest digest, - Ticket **tickets) -{ - *tickets = NULL; - return 0; -} - - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_digest_get_client_binding(krb5_context context, - krb5_digest digest, - char **type, - char **binding) -{ - if (digest->response.channel) { - *type = strdup(digest->response.channel->cb_type); - *binding = strdup(digest->response.channel->cb_binding); - if (*type == NULL || *binding == NULL) { - free(*type); - free(*binding); - return krb5_enomem(context); - } - } else { - *type = NULL; - *binding = NULL; - } - return 0; -} - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_digest_get_session_key(krb5_context context, - krb5_digest digest, - krb5_data *data) -{ - krb5_error_code ret; - - krb5_data_zero(data); - if (digest->response.session_key == NULL) - return 0; - ret = der_copy_octet_string(digest->response.session_key, data); - if (ret) - krb5_clear_error_message(context); - - return ret; -} - -struct krb5_ntlm_data { - NTLMInit init; - NTLMInitReply initReply; - NTLMRequest request; - NTLMResponse response; -}; - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_ntlm_alloc(krb5_context context, - krb5_ntlm *ntlm) -{ - *ntlm = calloc(1, sizeof(**ntlm)); - if (*ntlm == NULL) - return krb5_enomem(context); - return 0; -} - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_ntlm_free(krb5_context context, krb5_ntlm ntlm) -{ - free_NTLMInit(&ntlm->init); - free_NTLMInitReply(&ntlm->initReply); - free_NTLMRequest(&ntlm->request); - free_NTLMResponse(&ntlm->response); - memset(ntlm, 0, sizeof(*ntlm)); - free(ntlm); - return 0; -} - - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_ntlm_init_request(krb5_context context, - krb5_ntlm ntlm, - krb5_realm realm, - krb5_ccache ccache, - uint32_t flags, - const char *hostname, - const char *domainname) -{ - DigestReqInner ireq; - DigestRepInner irep; - krb5_error_code ret; - - memset(&ireq, 0, sizeof(ireq)); - memset(&irep, 0, sizeof(irep)); - - ntlm->init.flags = flags; - if (hostname) { - ALLOC(ntlm->init.hostname, 1); - *ntlm->init.hostname = strdup(hostname); - } - if (domainname) { - ALLOC(ntlm->init.domain, 1); - *ntlm->init.domain = strdup(domainname); - } - - ireq.element = choice_DigestReqInner_ntlmInit; - ireq.u.ntlmInit = ntlm->init; - - ret = digest_request(context, realm, ccache, - KRB5_KU_DIGEST_ENCRYPT, &ireq, &irep); - if (ret) - goto out; - - if (irep.element == choice_DigestRepInner_error) { - ret = irep.u.error.code; - krb5_set_error_message(context, ret, N_("Digest init error: %s", ""), - irep.u.error.reason); - goto out; - } - - if (irep.element != choice_DigestRepInner_ntlmInitReply) { - ret = EINVAL; - krb5_set_error_message(context, ret, - N_("ntlm reply not an initReply", "")); - goto out; - } - - ret = copy_NTLMInitReply(&irep.u.ntlmInitReply, &ntlm->initReply); - if (ret) { - krb5_set_error_message(context, ret, - N_("Failed to copy initReply", "")); - goto out; - } - - out: - free_DigestRepInner(&irep); - - return ret; -} - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_ntlm_init_get_flags(krb5_context context, - krb5_ntlm ntlm, - uint32_t *flags) -{ - *flags = ntlm->initReply.flags; - return 0; -} - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_ntlm_init_get_challenge(krb5_context context, - krb5_ntlm ntlm, - krb5_data *challenge) -{ - krb5_error_code ret; - - ret = der_copy_octet_string(&ntlm->initReply.challenge, challenge); - if (ret) - krb5_clear_error_message(context); - - return ret; -} - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_ntlm_init_get_opaque(krb5_context context, - krb5_ntlm ntlm, - krb5_data *opaque) -{ - krb5_error_code ret; - - ret = der_copy_octet_string(&ntlm->initReply.opaque, opaque); - if (ret) - krb5_clear_error_message(context); - - return ret; -} - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_ntlm_init_get_targetname(krb5_context context, - krb5_ntlm ntlm, - char **name) -{ - *name = strdup(ntlm->initReply.targetname); - if (*name == NULL) - return krb5_enomem(context); - return 0; -} - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_ntlm_init_get_targetinfo(krb5_context context, - krb5_ntlm ntlm, - krb5_data *data) -{ - krb5_error_code ret; - - if (ntlm->initReply.targetinfo == NULL) { - krb5_data_zero(data); - return 0; - } - - ret = krb5_data_copy(data, - ntlm->initReply.targetinfo->data, - ntlm->initReply.targetinfo->length); - if (ret) { - krb5_clear_error_message(context); - return ret; - } - return 0; -} - - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_ntlm_request(krb5_context context, - krb5_ntlm ntlm, - krb5_realm realm, - krb5_ccache ccache) -{ - DigestReqInner ireq; - DigestRepInner irep; - krb5_error_code ret; - - memset(&ireq, 0, sizeof(ireq)); - memset(&irep, 0, sizeof(irep)); - - ireq.element = choice_DigestReqInner_ntlmRequest; - ireq.u.ntlmRequest = ntlm->request; - - ret = digest_request(context, realm, ccache, - KRB5_KU_DIGEST_ENCRYPT, &ireq, &irep); - if (ret) - return ret; - - if (irep.element == choice_DigestRepInner_error) { - ret = irep.u.error.code; - krb5_set_error_message(context, ret, - N_("NTLM response error: %s", ""), - irep.u.error.reason); - goto out; - } - - if (irep.element != choice_DigestRepInner_ntlmResponse) { - ret = EINVAL; - krb5_set_error_message(context, ret, - N_("NTLM reply not an NTLMResponse", "")); - goto out; - } - - ret = copy_NTLMResponse(&irep.u.ntlmResponse, &ntlm->response); - if (ret) { - krb5_set_error_message(context, ret, - N_("Failed to copy NTLMResponse", "")); - goto out; - } - - out: - free_DigestRepInner(&irep); - - return ret; -} - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_ntlm_req_set_flags(krb5_context context, - krb5_ntlm ntlm, - uint32_t flags) -{ - ntlm->request.flags = flags; - return 0; -} - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_ntlm_req_set_username(krb5_context context, - krb5_ntlm ntlm, - const char *username) -{ - ntlm->request.username = strdup(username); - if (ntlm->request.username == NULL) - return krb5_enomem(context); - return 0; -} - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_ntlm_req_set_targetname(krb5_context context, - krb5_ntlm ntlm, - const char *targetname) -{ - ntlm->request.targetname = strdup(targetname); - if (ntlm->request.targetname == NULL) - return krb5_enomem(context); - return 0; -} - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_ntlm_req_set_lm(krb5_context context, - krb5_ntlm ntlm, - void *hash, size_t len) -{ - ntlm->request.lm.data = malloc(len); - if (ntlm->request.lm.data == NULL && len != 0) - return krb5_enomem(context); - ntlm->request.lm.length = len; - memcpy(ntlm->request.lm.data, hash, len); - return 0; -} - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_ntlm_req_set_ntlm(krb5_context context, - krb5_ntlm ntlm, - void *hash, size_t len) -{ - ntlm->request.ntlm.data = malloc(len); - if (ntlm->request.ntlm.data == NULL && len != 0) - return krb5_enomem(context); - ntlm->request.ntlm.length = len; - memcpy(ntlm->request.ntlm.data, hash, len); - return 0; -} - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_ntlm_req_set_opaque(krb5_context context, - krb5_ntlm ntlm, - krb5_data *opaque) -{ - ntlm->request.opaque.data = malloc(opaque->length); - if (ntlm->request.opaque.data == NULL && opaque->length != 0) - return krb5_enomem(context); - ntlm->request.opaque.length = opaque->length; - memcpy(ntlm->request.opaque.data, opaque->data, opaque->length); - return 0; -} - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_ntlm_req_set_session(krb5_context context, - krb5_ntlm ntlm, - void *sessionkey, size_t length) -{ - ntlm->request.sessionkey = calloc(1, sizeof(*ntlm->request.sessionkey)); - if (ntlm->request.sessionkey == NULL) - return krb5_enomem(context); - ntlm->request.sessionkey->data = malloc(length); - if (ntlm->request.sessionkey->data == NULL && length != 0) - return krb5_enomem(context); - memcpy(ntlm->request.sessionkey->data, sessionkey, length); - ntlm->request.sessionkey->length = length; - return 0; -} - -KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL -krb5_ntlm_rep_get_status(krb5_context context, - krb5_ntlm ntlm) -{ - return ntlm->response.success ? TRUE : FALSE; -} - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_ntlm_rep_get_sessionkey(krb5_context context, - krb5_ntlm ntlm, - krb5_data *data) -{ - if (ntlm->response.sessionkey == NULL) { - krb5_set_error_message(context, EINVAL, - N_("no ntlm session key", "")); - return EINVAL; - } - krb5_clear_error_message(context); - return krb5_data_copy(data, - ntlm->response.sessionkey->data, - ntlm->response.sessionkey->length); -} - -/** - * Get the supported/allowed mechanism for this principal. - * - * @param context A Keberos context. - * @param realm The realm of the KDC. - * @param ccache The credential cache to use when talking to the KDC. - * @param flags The supported mechanism. - * - * @return Return an error code or 0. - * - * @ingroup krb5_digest - */ - -KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL -krb5_digest_probe(krb5_context context, - krb5_realm realm, - krb5_ccache ccache, - unsigned *flags) -{ - DigestReqInner ireq; - DigestRepInner irep; - krb5_error_code ret; - - memset(&ireq, 0, sizeof(ireq)); - memset(&irep, 0, sizeof(irep)); - - ireq.element = choice_DigestReqInner_supportedMechs; - - ret = digest_request(context, realm, ccache, - KRB5_KU_DIGEST_ENCRYPT, &ireq, &irep); - if (ret) - goto out; - - if (irep.element == choice_DigestRepInner_error) { - ret = irep.u.error.code; - krb5_set_error_message(context, ret, "Digest probe error: %s", - irep.u.error.reason); - goto out; - } - - if (irep.element != choice_DigestRepInner_supportedMechs) { - ret = EINVAL; - krb5_set_error_message(context, ret, "Digest reply not an probe"); - goto out; - } - - *flags = DigestTypes2int(irep.u.supportedMechs); - - out: - free_DigestRepInner(&irep); - - return ret; -} - -#endif /* HEIMDAL_SMALLER */ diff --git a/lib/krb5/error_string.c b/lib/krb5/error_string.c index da86b375f..5b7cccaad 100644 --- a/lib/krb5/error_string.c +++ b/lib/krb5/error_string.c @@ -76,6 +76,27 @@ krb5_set_error_message(krb5_context context, krb5_error_code ret, va_end(ap); } +KRB5_LIB_FUNCTION int KRB5_LIB_CALL +_krb5_set_error_message_openssl(krb5_context context, krb5_error_code ret, + const char *fmt, ...) + __attribute__ ((__format__ (__printf__, 3, 4))) +{ + va_list ap; + char *omsg; + + if (context == NULL) + return ret; + + omsg = _krb5_openssl_errors(); + krb5_set_error_message(context, ret, "OpenSSL error:\n%s", omsg); + + va_start(ap, fmt); + krb5_vprepend_error_message(context, ret, fmt, ap); + va_end(ap); + free(omsg); + return ret; +} + /** * Set the context full error string for a specific error code. * @@ -234,3 +255,38 @@ krb5_get_err_text(krb5_context context, krb5_error_code code) { return krb5_get_error_message(context, code); } + +struct krb5_ossl_err_buf { + size_t len; + char *s; +}; + +static int err_append_cb(const char *s, size_t len, void *u) +{ + struct krb5_ossl_err_buf *b = u; + char *tmp; + + if ((tmp = realloc(b->s, b->len + len + 1)) == NULL) + return 0; + + memcpy(tmp + b->len, s, len); + tmp[b->len + len] = '\0'; + b->s = tmp; + b->len += len; + return 1; +} + +KRB5_LIB_FUNCTION char * KRB5_LIB_CALL +_krb5_openssl_errors(void) +{ + struct krb5_ossl_err_buf b; + + if (ERR_peek_last_error() == 0) + return NULL; + + /* NOTE: Dequeues the errors */ + b.s = NULL; + b.len = 0; + ERR_print_errors_cb(err_append_cb, &b); + return b.s; +} diff --git a/lib/krb5/fast.c b/lib/krb5/fast.c index 575b96483..50f846ecb 100644 --- a/lib/krb5/fast.c +++ b/lib/krb5/fast.c @@ -676,11 +676,12 @@ _krb5_fast_unwrap_error(krb5_context context, int32_t nonce, struct krb5_fast_state *state, METHOD_DATA *md, + TYPED_DATA *td, KRB_ERROR *error) { KrbFastResponse fastrep; krb5_error_code ret; - PA_DATA *pa; + PA_DATA *pa = NULL; int idx; if (state->armor_crypto == NULL) @@ -692,7 +693,8 @@ _krb5_fast_unwrap_error(krb5_context context, _krb5_debug(context, 10, "using FAST without FAST outer error code"); idx = 0; - pa = krb5_find_padata(md->val, md->len, KRB5_PADATA_FX_FAST, &idx); + if (md) + pa = krb5_find_padata(md->val, md->len, KRB5_PADATA_FX_FAST, &idx); if (pa == NULL) { /* * Typically _krb5_fast_wrap_req() has set KRB5_FAST_EXPECTED, which @@ -840,6 +842,8 @@ _krb5_fast_free(krb5_context context, struct krb5_fast_state *state) krb5_crypto_destroy(context, state->armor_crypto); if (state->strengthen_key) krb5_free_keyblock(context, state->strengthen_key); + if (state->reply_key) + krb5_free_keyblock(context, state->reply_key); krb5_free_keyblock_contents(context, &state->armor_key); if (state->armor_data) { free_KrbFastArmor(state->armor_data); diff --git a/lib/krb5/get_cred.c b/lib/krb5/get_cred.c index b508f759e..a2e10f5f7 100644 --- a/lib/krb5/get_cred.c +++ b/lib/krb5/get_cred.c @@ -729,7 +729,7 @@ get_cred_kdc(krb5_context context, } } - ret = _krb5_fast_unwrap_error(context, nonce, fast_state, &md, &rep.error); + ret = _krb5_fast_unwrap_error(context, nonce, fast_state, &md, NULL, &rep.error); free_METHOD_DATA(&md); if (ret) goto out; diff --git a/lib/krb5/get_in_tkt.c b/lib/krb5/get_in_tkt.c index 476844cc8..04a2bbda7 100644 --- a/lib/krb5/get_in_tkt.c +++ b/lib/krb5/get_in_tkt.c @@ -35,6 +35,195 @@ #include "krb5_locl.h" +/* + * lib/hcrypto.ui.c code here + */ +#include +#ifdef HAVE_TERMIOS_H +#include +#endif + +#ifdef HAVE_CONIO_H +#include +#endif + +static sig_atomic_t intr_flag; + +static void +intr(int sig) +{ + intr_flag++; +} + +#ifdef HAVE_CONIO_H + +/* + * Windows does console slightly different then then unix case. + */ + +static int +read_string(const char *preprompt, const char *prompt, + char *buf, size_t len, int echo) +{ + int of = 0; + int c; + char *p; + void (*oldsigintr)(int); + + printf("%s%s", preprompt, prompt); + fflush(stdout); + + oldsigintr = signal(SIGINT, intr); + + p = buf; + while(intr_flag == 0){ + c = ((echo)? _getche(): _getch()); + if(c == '\n' || c == '\r') + break; + if(of == 0) + *p++ = c; + of = (p == buf + len); + } + if(of) + p--; + *p = 0; + + if(echo == 0){ + printf("\n"); + } + + signal(SIGINT, oldsigintr); + + if(intr_flag) + return -2; + if(of) + return -1; + return 0; +} + +#else /* !HAVE_CONIO_H */ + +#ifndef NSIG +#define NSIG 47 +#endif + +static int +read_string(const char *preprompt, const char *prompt, + char *buf, size_t len, int echo) +{ + struct sigaction sigs[NSIG]; + int oksigs[NSIG]; + struct sigaction sa; + FILE *tty; + int ret = 0; + int of = 0; + int i; + int c; + char *p; + + struct termios t_new, t_old; + + memset(&oksigs, 0, sizeof(oksigs)); + + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = intr; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + for(i = 1; i < sizeof(sigs) / sizeof(sigs[0]); i++) + if (i != SIGALRM) + if (sigaction(i, &sa, &sigs[i]) == 0) + oksigs[i] = 1; + + if((tty = fopen("/dev/tty", "r")) != NULL) + rk_cloexec_file(tty); + else + tty = stdin; + + fprintf(stderr, "%s%s", preprompt, prompt); + fflush(stderr); + + if(echo == 0){ + tcgetattr(fileno(tty), &t_old); + memcpy(&t_new, &t_old, sizeof(t_new)); + t_new.c_lflag &= ~ECHO; + tcsetattr(fileno(tty), TCSANOW, &t_new); + } + intr_flag = 0; + p = buf; + while(intr_flag == 0){ + c = getc(tty); + if(c == EOF){ + if(!ferror(tty)) + ret = 1; + break; + } + if(c == '\n') + break; + if(of == 0) + *p++ = c; + of = (p == buf + len); + } + if(of) + p--; + *p = 0; + + if(echo == 0){ + fprintf(stderr, "\n"); + tcsetattr(fileno(tty), TCSANOW, &t_old); + } + + if(tty != stdin) + fclose(tty); + + for(i = 1; i < sizeof(sigs) / sizeof(sigs[0]); i++) + if (oksigs[i]) + sigaction(i, &sigs[i], NULL); + + if(ret) + return -3; + if(intr_flag) + return -2; + if(of) + return -1; + return 0; +} + +#endif /* HAVE_CONIO_H */ + +int +_krb5_UI_UTIL_read_pw_string(char *buf, int length, const char *prompt, int verify) +{ + int ret; + + ret = read_string("", prompt, buf, length, 0); + if (ret) + return ret; + + if (verify & UI_UTIL_FLAG_VERIFY) { + char *buf2; + buf2 = malloc(length); + if (buf2 == NULL) + return 1; + + ret = read_string("Verify password - ", prompt, buf2, length, 0); + if (ret) { + free(buf2); + return ret; + } + if (strcmp(buf2, buf) != 0) { + if (!(verify & UI_UTIL_FLAG_VERIFY_SILENT)) { + fprintf(stderr, "Verify failure\n"); + fflush(stderr); + } + ret = 1; + } + free(buf2); + } + return ret; +} + +/* lib/hcrypto/ui.c code over */ + #ifndef HEIMDAL_SMALLER static krb5_error_code diff --git a/lib/krb5/init_creds_pw.c b/lib/krb5/init_creds_pw.c index c88e6da59..e1ae65912 100644 --- a/lib/krb5/init_creds_pw.c +++ b/lib/krb5/init_creds_pw.c @@ -98,6 +98,7 @@ struct krb5_get_init_creds_ctx { struct pa_info_data paid; METHOD_DATA md; + TYPED_DATA td; KRB_ERROR error; EncKDCRepPart enc_part; @@ -208,6 +209,7 @@ free_init_creds_ctx(krb5_context context, krb5_init_creds_context ctx) krb5_data_free(&ctx->req_buffer); krb5_free_cred_contents(context, &ctx->cred); free_METHOD_DATA(&ctx->md); + free_TYPED_DATA(&ctx->td); free_EncKDCRepPart(&ctx->enc_part); free_KRB_ERROR(&ctx->error); free_AS_REQ(&ctx->as_req); @@ -1160,6 +1162,7 @@ pa_data_to_key_plain(krb5_context context, } struct pkinit_context { + unsigned int tries : 4; unsigned int win2k : 1; unsigned int used_pkinit : 1; }; @@ -1171,6 +1174,8 @@ pa_data_to_md_pkinit(krb5_context context, const krb5_principal client, int win2k, krb5_init_creds_context ctx, + krb5_error_code error_code, + TYPED_DATA *td, METHOD_DATA *md) { if (ctx->pk_init_ctx == NULL) @@ -1182,7 +1187,9 @@ pa_data_to_md_pkinit(krb5_context context, win2k, &a->req_body, ctx->pk_nonce, - md); + error_code, + td, + md); #else krb5_set_error_message(context, EINVAL, N_("no support for PKINIT compiled in", "")); @@ -1217,32 +1224,185 @@ pkinit_configure_win(krb5_context context, krb5_init_creds_context ctx, void *pa return 0; } +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +_krb5_typed_data_get_dh_params(krb5_context context, + TYPED_DATA *td, + int td_type, + TD_DH_PARAMETERS **out) +{ + krb5_error_code ret; + size_t i; + + if (*out) { + free_TD_DH_PARAMETERS(*out); + } + if (td == NULL) { + if (*out) + free(*out); + *out = NULL; + return ENOENT; + } + for (i = 0; i < td->len; i++) { + if (td->val[0].data_type != td_type) + continue; + if (td->val[0].data_value == NULL) + continue; + if (*out == NULL && (*out = calloc(1, sizeof(**out))) == NULL) + return krb5_enomem(context); + ret = decode_TD_DH_PARAMETERS(td->val[0].data_value->data, + td->val[0].data_value->length, + *out, NULL); + if (ret == 0) + return 0; + + /* + * FIXME: We need a version of _krb5_debug() that takes a + * krb5_error_code. + */ + _krb5_debug(context, 1, "Could not decode TD-DH-PARAMETERS"); + } + return ENOENT; +} + 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, METHOD_DATA *in_md, METHOD_DATA *out_md) +pkinit_step(krb5_context context, + krb5_init_creds_context ctx, + void *pa_ctx, + PA_DATA *pa, + const AS_REQ *a, + const AS_REP *rep, + krb5_error_code error_code, + METHOD_DATA *in_md, + TYPED_DATA *td, + METHOD_DATA *out_md) { krb5_error_code ret = HEIM_ERR_PA_CANT_CONTINUE; struct pkinit_context *pkinit_ctx = pa_ctx; - if (rep == NULL) { - if (pkinit_ctx->used_pkinit) { + if (rep == NULL || error_code) { + if (pkinit_ctx->tries > 2) { krb5_set_error_message(context, KRB5_GET_IN_TKT_LOOP, - "Already tried PKINIT(%s), looping", + "Tried PKINIT(%s) too many times", pkinit_ctx->win2k ? "win2k" : "ietf"); - } else { - ret = pa_data_to_md_pkinit(context, a, ctx->cred.client, - (pkinit_ctx->win2k != 0), - ctx, out_md); - if (ret == 0) - ret = HEIM_ERR_PA_CONTINUE_NEEDED; + return error_code ? + error_code : + KRB5_GET_IN_TKT_LOOP; /* Not the best error code... */ + } + switch (error_code) { + case KRB5_KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED: + /* + * In PKINIT the client picks a key agreement group/curve and the + * KDC can reject it, listing alternatives to try. That makes this + * error retriable: just try a different key agreement group/curve. + * + * We'll achieve that by stashing away a copy of the offered key + * agreement algorithms in the pk_init_ctx. + */ + if (ctx->pk_init_ctx->want_dh_alg) { + _krb5_debug(context, 1, "KDC rejected requested key agreement algorithm"); + krb5_set_error_message(context, error_code, + "KDC rejected requested key agreement algorithm"); + return error_code; + } + _krb5_debug(context, 1, "KDC rejected key agreement algorithm; retrying"); + ret = _krb5_typed_data_get_dh_params(context, td, td_dh_parameters, + &ctx->pk_init_ctx->kdc_dh_algs); + if (ret) + /* _krb5_typed_data_get_dh_params() will have traced why */ + return error_code; + break; + case KRB5_KDC_ERR_NO_ACCEPTABLE_KDF: + /* + * In PKINIT the server (KDC) picks a KDF to use. The client tells + * it which KDFs it supports. If the KDC rejects all of the + * client's KDFs then there is nothing else to be done other than + * to add support for or enable one (or more) of the KDC's + * supported KDFs, but we can't do that here. + * + * FIXME: What we could and should do here is make the error + * message list the KDC's supported KDF OIDs. Then the user + * would have enough information to act. + */ + _krb5_debug(context, 1, "KDC rejected offered PKINIT KDFs"); + return error_code; + case KRB5_KDC_ERR_CANT_VERIFY_CERTIFICATE: + /* + * The KDC can't find a validation path for the client's + * certificate to a KDC-side trust anchor. In principle if the + * client has multiple certificates then we could use the + * associated TYPED-DATA to pick a better certificate and retry. + * In practice that's a lot of work for not much gain: the user can + * just make sure to have the certificates that will work in the + * certificate store provided to kinit or whatever is calling + * krb5_get_init_creds*(). + * + * Therefore we do not try to retry in this case. + */ + _krb5_debug(context, 1, "KDC could not verify client certificate (issuer not trusted)"); + return error_code; + case KRB5_KDC_ERR_INVALID_CERTIFICATE: + /* + * Similar to KRB5_KDC_ERR_CANT_VERIFY_CERTIFICATE, only there was + * some other defect with the client's certificate or one of the + * intermediates. We don't try to retry for the same reasons. + */ + _krb5_debug(context, 1, "KDC could not verify client certificate (invalid signature)"); + return error_code; + case KRB5_KDC_ERR_DIGEST_IN_CERT_NOT_ACCEPTED: + /* + * Similar to KRB5_KDC_ERR_CANT_VERIFY_CERTIFICATE, only there was + * some other defect with the client's certificate or one of the + * intermediates. + * + * FIXME: It's possible to retry in this case since all we need to + * do is change the certificate store search criteria. + */ + _krb5_debug(context, 1, "KDC rejected certificate algorithm(s)"); + return error_code; + case KRB5_KDC_ERR_PA_CHECKSUM_MUST_BE_INCLUDED: + /* Can't happen now */ + _krb5_debug(context, 1, "KDC thinks we did not include a PA checksum!"); + return error_code; + case KRB5_KDC_ERR_DIGEST_IN_SIGNED_DATA_NOT_ACCEPTED: + /* + * Similar to KRB5_KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED and + * eminently retriable. + */ + if (ctx->pk_init_ctx->want_sig_alg) { + _krb5_debug(context, 1, "KDC rejected requested signature algorithm"); + krb5_set_error_message(context, error_code, + "KDC rejected requested signature algorithm"); + return error_code; + } + ret = _krb5_typed_data_get_dh_params(context, td, td_dh_parameters, + &ctx->pk_init_ctx->kdc_sig_algs); + if (ret) + /* _krb5_typed_data_get_dh_params() will have traced why */ + return error_code; + /* FIXME! Add support for picking a better algorithm! */ + krb5_set_error_message(context, error_code, + "KDC rejected requested signature algorithm " + "(negotiation support incomplete on client s3ide)"); + return error_code; + case 0: + break; + default: + _krb5_debug(context, 1, "Unknown KDC error while trying PKINIT"); + return error_code; + } + ret = pa_data_to_md_pkinit(context, a, ctx->cred.client, + (pkinit_ctx->win2k != 0), + ctx, error_code, td, out_md); + if (ret == 0) + ret = HEIM_ERR_PA_CONTINUE_NEEDED; - pkinit_ctx->used_pkinit = 1; - } - } else if (pa) { + pkinit_ctx->used_pkinit = 1; + pkinit_ctx->tries++; + } else if (rep && pa) { ret = _krb5_pk_rd_pa_reply(context, - a->req_body.realm, ctx->pk_init_ctx, - rep->enc_part.etype, + a, + rep, ctx->pk_nonce, &ctx->req_buffer, pa, @@ -1371,7 +1531,9 @@ pa_gss_step(krb5_context context, PA_DATA *pa, const AS_REQ *a, const AS_REP *rep, + krb5_error_code error_code, METHOD_DATA *in_md, + TYPED_DATA *td, METHOD_DATA *out_md) { krb5_error_code ret; @@ -1583,8 +1745,16 @@ 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, METHOD_DATA *in_md, METHOD_DATA *out_md) +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, + krb5_error_code error_code, + METHOD_DATA *in_md, + TYPED_DATA *td, + METHOD_DATA *out_md) { struct pa_info_data paid, *ppaid; krb5_keyblock challengekey; @@ -1720,10 +1890,16 @@ enc_ts_restart(krb5_context context, krb5_init_creds_context ctx, void *pa_ctx) } static krb5_error_code -enc_ts_step(krb5_context context, krb5_init_creds_context ctx, void *pa_ctx, PA_DATA *pa, +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, - METHOD_DATA *in_md, METHOD_DATA *out_md) + krb5_error_code error_code, + METHOD_DATA *in_md, + TYPED_DATA *td, + METHOD_DATA *out_md) { struct enc_ts_context *pactx = (struct enc_ts_context *)pa_ctx; struct pa_info_data paid, *ppaid; @@ -1849,8 +2025,16 @@ 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, METHOD_DATA *in_md, METHOD_DATA *out_md) +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, + krb5_error_code error_code, + METHOD_DATA *in_md, + TYPED_DATA *td, + METHOD_DATA *out_md) { size_t len = 0, length; krb5_error_code ret; @@ -1881,8 +2065,16 @@ 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, METHOD_DATA *in_md, METHOD_DATA *out_md) +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, + krb5_error_code error_code, + METHOD_DATA *in_md, + TYPED_DATA *td, + 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); @@ -1897,7 +2089,9 @@ pa_fx_cookie_step(krb5_context context, PA_DATA *pa, const AS_REQ *a, const AS_REP *rep, + krb5_error_code error_code, METHOD_DATA *in_md, + TYPED_DATA *td, METHOD_DATA *out_md) { krb5_error_code ret; @@ -1936,7 +2130,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 *, 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 *, krb5_error_code, METHOD_DATA *, TYPED_DATA *, METHOD_DATA *); typedef void (*pa_release_f)(void *); static const struct patype { @@ -2137,7 +2331,8 @@ pa_announce(krb5_context context, continue; if (patypes[n].step) - patypes[n].step(context, ctx, NULL, NULL, NULL, NULL, in_md, out_md); + patypes[n].step(context, ctx, NULL, NULL, NULL, NULL, 0, in_md, + NULL, out_md); else ret = krb5_padata_add(context, out_md, patypes[n].type, NULL, 0); } @@ -2250,7 +2445,9 @@ pa_step(krb5_context context, krb5_init_creds_context ctx, const AS_REQ *a, const AS_REP *rep, + krb5_error_code error_code, METHOD_DATA *in_md, + TYPED_DATA *td, METHOD_DATA *out_md) { krb5_error_code ret; @@ -2301,7 +2498,9 @@ 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, in_md, out_md); + ret = ctx->pa_mech->patype->step(context, ctx, + (void *)&ctx->pa_mech->pactx[0], pa, a, + rep, error_code, in_md, td, 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; @@ -2363,7 +2562,9 @@ process_pa_data_to_md(krb5_context context, const krb5_creds *creds, const AS_REQ *a, krb5_init_creds_context ctx, + krb5_error_code error_code, METHOD_DATA *in_md, + TYPED_DATA *td, METHOD_DATA **out_md) { krb5_error_code ret; @@ -2377,7 +2578,7 @@ process_pa_data_to_md(krb5_context context, log_kdc_pa_types(context, in_md); - ret = pa_step(context, ctx, a, NULL, in_md, *out_md); + ret = pa_step(context, ctx, a, NULL, error_code, in_md, td, *out_md); if (ret == HEIM_ERR_PA_CONTINUE_NEEDED) { _krb5_debug(context, 0, "pamech need more stepping"); } else if (ret == 0) { @@ -2436,7 +2637,7 @@ process_pa_data_to_key(krb5_context context, } } - ret = pa_step(context, ctx, a, rep, rep->padata, NULL); + ret = pa_step(context, ctx, a, rep, ctx->error.error_code, rep->padata, &ctx->td, NULL); if (ret == HEIM_ERR_PA_CONTINUE_NEEDED) { _krb5_debug(context, 0, "In final stretch and pa require more stepping ?"); return ret; @@ -2963,7 +3164,7 @@ init_creds_step(krb5_context context, { struct timeval start_time, end_time; krb5_data checksum_data; - krb5_error_code ret; + krb5_error_code ret, ret2; size_t len = 0; size_t size; AS_REQ req2; @@ -3016,6 +3217,8 @@ init_creds_step(krb5_context context, unsigned eflags = EXTRACT_TICKET_AS_REQ | EXTRACT_TICKET_TIMESYNC; krb5_data data; + ctx->error.error_code = 0; + /* * Unwrap AS-REP */ @@ -3140,25 +3343,44 @@ init_creds_step(krb5_context context, * wrapped version if we are using FAST. */ - free_METHOD_DATA(&ctx->md); - memset(&ctx->md, 0, sizeof(ctx->md)); + switch (ctx->error.error_code) { + case KRB5KDC_ERR_PREAUTH_REQUIRED: + case KRB5_KDC_ERR_MORE_PREAUTH_DATA_REQUIRED: + if (!ctx->error.e_data) { + _krb5_debug(context, 5, "KRB-ERROR missing expected METHOD-DATA in e-data"); + break; + } + free_METHOD_DATA(&ctx->md); + memset(&ctx->md, 0, sizeof(ctx->md)); - if (ctx->error.e_data) { - krb5_error_code ret2; - - ret2 = decode_METHOD_DATA(ctx->error.e_data->data, - ctx->error.e_data->length, - &ctx->md, - NULL); - if (ret2) { - /* - * Just ignore any error, the error will be pushed - * out from krb5_error_from_rd_error() if there - * was one. - */ - _krb5_debug(context, 5, N_("Failed to decode METHOD-DATA", "")); - } - } + ret2 = decode_METHOD_DATA(ctx->error.e_data->data, + ctx->error.e_data->length, + &ctx->md, NULL); + /* Just ignore any errors here */ + if (ret2) + _krb5_debug(context, 5, "Failed to decode METHOD-DATA"); + break; + case KRB5_KDC_ERR_CANT_VERIFY_CERTIFICATE: + case KRB5_KDC_ERR_INVALID_CERTIFICATE: + case KRB5_KDC_ERR_DIGEST_IN_CERT_NOT_ACCEPTED: + case KRB5_KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED: + case KRB5_KDC_ERR_PA_CHECKSUM_MUST_BE_INCLUDED: + case KRB5_KDC_ERR_DIGEST_IN_SIGNED_DATA_NOT_ACCEPTED: + if (!ctx->error.e_data) { + _krb5_debug(context, 5, "KRB-ERROR missing expected TYPED-DATA in e-data"); + break; + } + free_TYPED_DATA(&ctx->td); + memset(&ctx->td, 0, sizeof(ctx->td)); + ret2 = decode_TYPED_DATA(ctx->error.e_data->data, + ctx->error.e_data->length, + &ctx->td, NULL); + if (ret2) + _krb5_debug(context, 5, "Failed to decode TYPED-DATA"); + break; + default: + break; + } /* * Unwrap KRB-ERROR, we are always calling this so that @@ -3167,7 +3389,7 @@ init_creds_step(krb5_context context, * in the KDC). */ ret = _krb5_fast_unwrap_error(context, ctx->nonce, &ctx->fast_state, - &ctx->md, &ctx->error); + &ctx->md, &ctx->td, &ctx->error); if (ret) goto out; @@ -3208,6 +3430,15 @@ init_creds_step(krb5_context context, "options sent by KDC", "")); goto out; } + } else if (ret == KRB5_KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED) { + /* + * Retriable PKINIT error (due to negotiation of algorithms) -> + * retry. + */ + _krb5_debug(context, 5, "init_creds: retrying PKINIT"); + + pa_restart(context, ctx); + } else if (ret == KRB5KRB_AP_ERR_SKEW && context->kdc_sec_offset == 0) { /* * Try adapt to timeskrew when we are using pre-auth, and @@ -3371,7 +3602,8 @@ init_creds_step(krb5_context context, */ ret = process_pa_data_to_md(context, &ctx->cred, &ctx->as_req, ctx, - &ctx->md, &ctx->as_req.padata); + ctx->error.error_code, &ctx->md, &ctx->td, + &ctx->as_req.padata); if (ret) goto out; @@ -3404,6 +3636,13 @@ init_creds_step(krb5_context context, if(len != ctx->req_buffer.length) krb5_abortx(context, "internal error in ASN.1 encoder"); + /* + * Save the encoded AS-REQ where we can find it w/o having to refactor the + * pre-auth service API (struct patype). + */ + der_free_octet_string(&ctx->as_req._save); + ret = der_copy_octet_string(&ctx->req_buffer, &ctx->as_req._save); + ret = krb5_data_copy(out, ctx->req_buffer.data, ctx->req_buffer.length); diff --git a/lib/krb5/krb5.conf.5 b/lib/krb5/krb5.conf.5 index f12eda17f..3c0ace1a6 100644 --- a/lib/krb5/krb5.conf.5 +++ b/lib/krb5/krb5.conf.5 @@ -258,6 +258,13 @@ A list of default encryption types to use in TGS requests. (Default: the value of default_etypes.) .It Li default_etypes_des = Va etypes ... A list of default encryption types to use when requesting a DES credential. +.It Li openssl_cnf = Va FILE +Path to OpenSSL configuration to use if not the default. +.It Li openssl_propq = Va PROPQ +Property query string for OpenSSL. +Use this to enable FIPS mode, for example. +.It Li fips = Va BOOL +If true this causes the OpenSSL FIPS provider to be loaded. .It Li default_keytab_name = Va keytab The keytab to use if no other is specified, default is .Dq FILE:/etc/krb5.keytab . @@ -403,6 +410,20 @@ be allowed to run. .It Li fcache_strict_checking strict checking in FILE credential caches that owner, no symlink and permissions is correct. +.It Li pkinit_prefer_ec = Va BOOL +If set to true then the client will prefer EC/ECC curves for +PKINIT key agreement, otherwise it will prefer DH. +Defaults to true. +The default curve (see below) is +.Dq X25519 . +.It Li pkinit_dh_trust_modp_kdc_choice = Va BOOL +If set to true and the KDC offers one or more modular DH groups +not known to the client, then pick the first one, else ignore +such offers. +.It Li pkinit_dh_use_modp = Va BOOL +If set to true and +.Li pkinit_prefer_ec +is set to false, then default to using a modp 2048 group. .It Li moduli = Va FILE Names a file that contains acceptable modular Diffie-Hellman groups for PKINIT. @@ -415,6 +436,51 @@ are comments. .It Li pkinit_dh_min_bits = Va NUMBER PKINIT client's minimum acceptable modular Diffie-Hellman public key size in bits. +This can be set to curve names like +.Dq prime256v1 +or +.Dq P-256 +for NIST P-256, +.Dq prime384v1 +or +.Dq P-384 +for NIST P-384, +.Dq secp521r1 +or +.Dq P-521 +for NIST P-521, +.Dq X25519 , +and +.Dq X448. +It can also be set to a modular DH group size in bits, such as +.Va 2048 . +By default the client will prefer +.Dq X25519 . +.It Li pkinit_allow_ecdh = { +.Bl -tag -width "xxx" -offset indent +.It Va CURVE Li = Va BOOL +Enables/disables ECDH curves. +Curve names include +.Dq prime256v1 +and +.Dq P-256 +for NIST P-256, +.Dq prime384v1 +and +.Dq P-384 +for NIST P-384, +.Dq secp521r1 +and +.Dq P-521 +for NIST P-521, +.Dq X25519 , +and +.Dq X448 . +.El +.It Li } +.It Li pkinit_kdfs = Va KDF-names +Set to one or more RFC 8636 KDFs that are accepted. +By default all RFC 8636 KDFs are accepted. .It Li enable-kx509 = Va boolean Enable use of kx509 so that every TGT that can has a corresponding PKIX certificate. Default: false. @@ -873,6 +939,15 @@ Enabled by default for now, but in a future release will be disabled. .It Li enable-pkinit = Va BOOL Enable PKINIT (disabled by default). +.It Li pkinit_allow_rsa_key_transport = Va BOOL +Enable RSA key transport. +This is disabled by default as using Diffie-Hellman key agreement +is more secure. +.It Li pkinit_enable_rfc4556_kdf-pkinit = Va BOOL +Enable or disable interoperability with clients that do not +implement RFC 8636 (PKINIT algorithm agility). +Note that the RFC 4556 KDF is based on SHA-1, and RFC 4556 has +security issues that are fixed in RFC 8636. .It Li allow-anonymous = Va BOOL If the kdc is allowed to hand out anonymous tickets. .It Li synthetic_clients = Va BOOL @@ -955,6 +1030,34 @@ Defaults to .It Li pkinit_dh_min_bits = Va NUMBER Minimum acceptable modular Diffie-Hellman public key size in bits. +.It Li pkinit_allow_ecdh = { +.Bl -tag -width "xxx" -offset indent +.It Va CURVE Li = Va BOOL +Indicates whether the given curve will be allowed. +Curve names include +.Dq prime256v1 +and +.Dq P-256 +for NIST P-256, +.Dq prime384v1 +and +.Dq P-384 +for NIST P-384, +.Dq secp521r1 +and +.Dq P-521 +for NIST P-521, +.Dq X25519 , +and +.Dq X448 . +.El +.It Li } +.It Li pkinit_enable_kdf_ah_sha1 = Va BOOL +.It Li pkinit_enable_kdf_ah_sha256 = Va BOOL +.It Li pkinit_enable_kdf_ah_sha384 = Va BOOL +.It Li pkinit_enable_kdf_ah_sha512 = Va BOOL +By default all PKINIT KDFs are enabled, but you may disable them +with these parameters. .It Li pkinit_max_life_from_cert_extension = Va BOOL If set to .Va true @@ -1308,6 +1411,18 @@ service will include the client's IP address in the TGT it issues it. Defaults to .Va true . +.It Li impersonation_key_type = Va KEYTYPE +Specifies what key type to use for PKINIT client certificates for impersonating +users for the +.Li /get-tgt +end-point. +.It Li impersonation_key_bits = Va NUMBER +Specifies the key size when the +.Li impersonation_key_type +parameter is set to +.Dq rsa . +.Va /get-tgt +end-point. .It Li allow_addresses = Va BOOL If set to .Va true @@ -1439,8 +1554,24 @@ Per user Heimdal configuration file path. Common Heimdal configuration file path. .El .Sh ENVIRONMENT -.Ev KRB5_CONFIG +.Bl -tag -width "xxx" -offset indent +.It Ev KRB5CCNAME +names the credentials cache to use. +.It Ev KRB5_TRACE +names a file to write tracing messages to. +See also +.Xr krb5_openlog 3 . +.It Ev KRB5_KTNAME +names the keytab to use (server-side). +.It Ev KRB5_CLIENT_KTNAME +names the keytab to use (client-side). +.It Ev KRB5_OPENSSL_CNF +names the OpenSSL configuration file to use. +.It Ev KRB5_OPENSSL_PROPQ +names the OpenSSL provider property query to use. +.It Ev KRB5_CONFIG points to the configuration file to read. +.El .Sh FILES .Bl -tag -width "/etc/krb5.conf" .It Pa /etc/krb5.conf diff --git a/lib/krb5/krb5_digest.3 b/lib/krb5/krb5_digest.3 deleted file mode 100644 index 11d4db460..000000000 --- a/lib/krb5/krb5_digest.3 +++ /dev/null @@ -1,260 +0,0 @@ -.\" Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan -.\" (Royal Institute of Technology, Stockholm, Sweden). -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" 3. Neither the name of the Institute nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" $Id$ -.\" -.Dd February 18, 2007 -.Dt KRB5_DIGEST 3 -.Os HEIMDAL -.Sh NAME -.Nm krb5_digest , -.Nm krb5_digest_alloc , -.Nm krb5_digest_free , -.Nm krb5_digest_set_server_cb , -.Nm krb5_digest_set_type , -.Nm krb5_digest_set_hostname , -.Nm krb5_digest_get_server_nonce , -.Nm krb5_digest_set_server_nonce , -.Nm krb5_digest_get_opaque , -.Nm krb5_digest_set_opaque , -.Nm krb5_digest_get_identifier , -.Nm krb5_digest_set_identifier , -.Nm krb5_digest_init_request , -.Nm krb5_digest_set_client_nonce , -.Nm krb5_digest_set_digest , -.Nm krb5_digest_set_username , -.Nm krb5_digest_set_authid , -.Nm krb5_digest_set_authentication_user , -.Nm krb5_digest_set_realm , -.Nm krb5_digest_set_method , -.Nm krb5_digest_set_uri , -.Nm krb5_digest_set_nonceCount , -.Nm krb5_digest_set_qop , -.Nm krb5_digest_request , -.Nm krb5_digest_get_responseData , -.Nm krb5_digest_get_rsp , -.Nm krb5_digest_get_tickets , -.Nm krb5_digest_get_client_binding , -.Nm krb5_digest_get_a1_hash -.Nd remote digest (HTTP-DIGEST, SASL, CHAP) support -.Sh LIBRARY -Kerberos 5 Library (libkrb5, -lkrb5) -.Sh SYNOPSIS -.In krb5.h -.Pp -.Li "typedef struct krb5_digest *krb5_digest;" -.Pp -.Ft krb5_error_code -.Fo krb5_digest_alloc -.Fa "krb5_context context" -.Fa "krb5_digest *digest" -.Fc -.Ft void -.Fo krb5_digest_free -.Fa "krb5_digest digest" -.Fc -.Ft krb5_error_code -.Fo krb5_digest_set_type -.Fa "krb5_context context" -.Fa "krb5_digest digest" -.Fa "const char *type" -.Fc -.Ft krb5_error_code -.Fo krb5_digest_set_server_cb -.Fa "krb5_context context" -.Fa "krb5_digest digest" -.Fa "const char *type" -.Fa "const char *binding" -.Fc -.Ft krb5_error_code -.Fo krb5_digest_set_hostname -.Fa "krb5_context context" -.Fa "krb5_digest digest" -.Fa "const char *hostname" -.Fc -.Ft "const char *" -.Fo krb5_digest_get_server_nonce -.Fa "krb5_context context" -.Fa "krb5_digest digest" -.Fc -.Ft krb5_error_code -.Fo krb5_digest_set_server_nonce -.Fa "krb5_context context" -.Fa "krb5_digest digest" -.Fa "const char *nonce" -.Fc -.Ft "const char *" -.Fo krb5_digest_get_opaque -.Fa "krb5_context context" -.Fa "krb5_digest digest" -.Fc -.Ft krb5_error_code -.Fo krb5_digest_set_opaque -.Fa "krb5_context context" -.Fa "krb5_digest digest" -.Fa "const char *opaque" -.Fc -.Ft "const char *" -.Fo krb5_digest_get_identifier -.Fa "krb5_context context" -.Fa "krb5_digest digest" -.Fc -.Ft krb5_error_code -.Fo krb5_digest_set_identifier -.Fa "krb5_context context" -.Fa "krb5_digest digest" -.Fa "const char *id" -.Fc -.Ft krb5_error_code -.Fo krb5_digest_init_request -.Fa "krb5_context context" -.Fa "krb5_digest digest" -.Fa "krb5_realm realm" -.Fa "krb5_ccache ccache" -.Fc -.Ft krb5_error_code -.Fo krb5_digest_set_client_nonce -.Fa "krb5_context context" -.Fa "krb5_digest digest" -.Fa "const char *nonce" -.Fc -.Ft krb5_error_code -.Fo krb5_digest_set_digest -.Fa "krb5_context context" -.Fa "krb5_digest digest" -.Fa "const char *dgst" -.Fc -.Ft krb5_error_code -.Fo krb5_digest_set_username -.Fa "krb5_context context" -.Fa "krb5_digest digest" -.Fa "const char *username" -.Fc -.Ft krb5_error_code -.Fo krb5_digest_set_authid -.Fa "krb5_context context" -.Fa "krb5_digest digest" -.Fa "const char *authid" -.Fc -.Ft krb5_error_code -.Fo krb5_digest_set_authentication_user -.Fa "krb5_context context" -.Fa "krb5_digest digest" -.Fa "krb5_principal authentication_user" -.Fc -.Ft krb5_error_code -.Fo krb5_digest_set_realm -.Fa "krb5_context context" -.Fa "krb5_digest digest" -.Fa "const char *realm" -.Fc -.Ft krb5_error_code -.Fo krb5_digest_set_method -.Fa "krb5_context context" -.Fa "krb5_digest digest" -.Fa "const char *method" -.Fc -.Ft krb5_error_code -.Fo krb5_digest_set_uri -.Fa "krb5_context context" -.Fa "krb5_digest digest" -.Fa "const char *uri" -.Fc -.Ft krb5_error_code -.Fo krb5_digest_set_nonceCount -.Fa "krb5_context context" -.Fa "krb5_digest digest" -.Fa "const char *nonce_count" -.Fc -.Ft krb5_error_code -.Fo krb5_digest_set_qop -.Fa "krb5_context context" -.Fa "krb5_digest digest" -.Fa "const char *qop" -.Fc -.Ft krb5_error_code -.Fo krb5_digest_request -.Fa "krb5_context context" -.Fa "krb5_digest digest" -.Fa "krb5_realm realm" -.Fa "krb5_ccache ccache" -.Fc -.Ft "const char *" -.Fo krb5_digest_get_responseData -.Fa "krb5_context context" -.Fa "krb5_digest digest" -.Fc -.Ft "const char *" -.Fo krb5_digest_get_rsp -.Fa "krb5_context context" -.Fa "krb5_digest digest" -.Fc -.Ft krb5_error_code -.Fo krb5_digest_get_tickets -.Fa "krb5_context context" -.Fa "krb5_digest digest" -.Fa "Ticket **tickets" -.Fc -.Ft krb5_error_code -.Fo krb5_digest_get_client_binding -.Fa "krb5_context context" -.Fa "krb5_digest digest" -.Fa "char **type" -.Fa "char **binding" -.Fc -.Ft krb5_error_code -.Fo krb5_digest_get_a1_hash -.Fa "krb5_context context" -.Fa "krb5_digest digest" -.Fa "krb5_data *data" -.Fc -.Sh DESCRIPTION -The -.Fn krb5_digest_alloc -function allocatates the -.Fa digest -structure. The structure should be freed with -.Fn krb5_digest_free -when it is no longer being used. -.Pp -.Fn krb5_digest_alloc -returns 0 to indicate success. -Otherwise an kerberos code is returned and the pointer that -.Fa digest -points to is set to -.Dv NULL . -.Pp -.Fn krb5_digest_free -free the structure -.Fa digest . -.Sh SEE ALSO -.Xr krb5 3 , -.Xr kerberos 8 diff --git a/lib/krb5/krb5_locl.h b/lib/krb5/krb5_locl.h index 2f85ce9e3..e52a54c9d 100644 --- a/lib/krb5/krb5_locl.h +++ b/lib/krb5/krb5_locl.h @@ -146,6 +146,9 @@ struct gss_OID_desc_struct; #include +#define UI_UTIL_FLAG_VERIFY 0x1 /* ask to verify password */ +#define UI_UTIL_FLAG_VERIFY_SILENT 0x2 /* silence on verify failure */ + #include #include #include @@ -259,6 +262,50 @@ struct _krb5_get_init_creds_opt_private { typedef uint32_t krb5_enctype_set; +/* + * Functions like EVP_sha256() are slow. Instead we should use EVP_x_fetch() + * and cache the result. Similarly OSSL_LIB_CTX_load_config() is slow, so if + * we have a krb5-specific OpenSSL cnf then we want to cache the result of + * loading it. But there are no up_ref/dec_ref OpenSSL functions for any of + * the things in this structure(!), so we build our own. + * + * We could also have a thread-safe global cache of these things to further + * reduce the cost of all these OpenSSL function calls by caching their results + * even more aggressively, and eventually we will, just not right now. + * + * Notes: + * + * - krb5_context is, unfortunately, mutable, so we can't share it between + * threads + * + * - OSSL_LIB_CTX * and all the EVPs we cache here are immutable, so we _can_ + * share them between threads to amortize the cost of creating them + */ +typedef struct krb5_context_ossl_data *krb5_context_ossl; +struct krb5_context_ossl_data { + OSSL_LIB_CTX *libctx; /* OpenSSL library context */ + char *propq; + char *cnf; + heim_base_atomic(uint32_t) refs; + krb5_context_ossl next; /* thread-safe global cache */ + OSSL_PROVIDER *openssl_def; + OSSL_PROVIDER *openssl_fips; + OSSL_PROVIDER *openssl_leg; + EVP_CIPHER *rc4; + EVP_CIPHER *aes128_cbc; + EVP_CIPHER *aes192_cbc; + EVP_CIPHER *aes256_cbc; + EVP_CIPHER *aes128_cts; + EVP_CIPHER *aes192_cts; + EVP_CIPHER *aes256_cts; + EVP_MAC *hmac; + EVP_MD *md5; + EVP_MD *sha1; + EVP_MD *sha256; + EVP_MD *sha384; + EVP_MD *sha512; +}; + /* * Do not remove or reorder the fields of this structure. * Fields that are no longer used should be marked "deprecated". @@ -328,6 +375,9 @@ typedef struct krb5_context_data { krb5_name_canon_rule name_canon_rules; size_t config_include_depth; krb5_boolean no_ticket_store; /* Don't store service tickets */ + + /* OpenSSL 3.x */ + krb5_context_ossl ossl; } krb5_context_data; #define KRB5_DEFAULT_CCNAME_FILE "FILE:%{TEMP}/krb5cc_%{uid}" @@ -401,16 +451,23 @@ enum krb5_pk_type { enum keyex_enum { USE_RSA, USE_DH, USE_ECDH }; struct krb5_pk_init_ctx_data { + TD_DH_PARAMETERS *kdc_sig_algs; + TD_DH_PARAMETERS *kdc_dh_algs; + const heim_oid *want_sig_alg; + const heim_oid *want_dh_alg; + const heim_oid *want_kdf_alg; struct krb5_pk_identity *id; enum keyex_enum keyex; - union { - DH *dh; - void *eckey; - } u; + EVP_PKEY *pkey; krb5_data *clientDHNonce; struct krb5_dh_moduli **m; hx509_peer_info peer; + krb5_principal client; + krb5_principal server; + krb5_data as_req; + krb5_data pk_as_rep; enum krb5_pk_type type; + unsigned int kdc_dh_alg_idx:8; /* 256 is plenty */ unsigned int require_binding:1; unsigned int require_eku:1; unsigned int require_krbtgt_otherName:1; diff --git a/lib/krb5/kx509.c b/lib/krb5/kx509.c index 3bacdf10d..6c4cc302d 100644 --- a/lib/krb5/kx509.c +++ b/lib/krb5/kx509.c @@ -771,10 +771,17 @@ mk_kx509_req(krb5_context context, krb5_error_code ret = 0; krb5_creds this_cred; krb5_creds *cred = NULL; - HMAC_CTX ctx; + EVP_MAC *mac = NULL; + EVP_MAC_CTX *ctx = NULL; + const EVP_MD *md = EVP_sha1(); + const char *mdname = EVP_MD_get0_name(md); const char *hostname; + OSSL_PARAM params[] = { + OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, (char *)mdname, 0), + OSSL_PARAM_END + }; char *start_realm = NULL; - size_t len = 0; + size_t len; krb5_data_zero(&pre_req); memset(&spki, 0, sizeof(spki)); @@ -853,25 +860,41 @@ mk_kx509_req(krb5_context context, goto out; /* Add the the key and HMAC to the message */ - HMAC_CTX_init(&ctx); - if (HMAC_Init_ex(&ctx, kx509_ctx->hmac_key->keyvalue.data, + mac = EVP_MAC_fetch(context->ossl->libctx, "HMAC", context->ossl->propq); + ctx = EVP_MAC_CTX_new(mac); + if (EVP_MAC_init(ctx, kx509_ctx->hmac_key->keyvalue.data, kx509_ctx->hmac_key->keyvalue.length, - EVP_sha1(), NULL) == 0) { - HMAC_CTX_cleanup(&ctx); + params) != 1) { ret = krb5_enomem(context); } else { - HMAC_Update(&ctx, version_2_0, sizeof(version_2_0)); + if (EVP_MAC_update(ctx, version_2_0, sizeof(version_2_0)) != 1) { + ret = krb5_enomem(context); + goto out; + } if (private_key || kx509_ctx->given_csr.data) { - HMAC_Update(&ctx, kx509_req.pk_key.data, kx509_req.pk_key.length); + if (EVP_MAC_update(ctx, kx509_req.pk_key.data, + kx509_req.pk_key.length) != 1) { + ret = krb5_enomem(context); + goto out; + } } else { /* Probe */ - HMAC_Update(&ctx, kx509_req.authenticator.data, kx509_req.authenticator.length); + if (EVP_MAC_update(ctx, kx509_req.authenticator.data, + kx509_req.authenticator.length) != 1) { + ret = krb5_enomem(context); + goto out; + } } - HMAC_Final(&ctx, kx509_req.pk_hash.data, 0); - HMAC_CTX_cleanup(&ctx); + if (EVP_MAC_final(ctx, kx509_req.pk_hash.data, &len, + kx509_req.pk_hash.length) != 1) { + ret = krb5_enomem(context); + goto out; + } + // assert(len == kx509_req.pk_hash.length); } /* Encode the message, prefix `version_2_0', output the result */ + len = 0; if (ret == 0) ASN1_MALLOC_ENCODE(Kx509Request, pre_req.data, pre_req.length, &kx509_req, &len, ret); if (ret == 0) @@ -883,6 +906,8 @@ mk_kx509_req(krb5_context context, } out: + EVP_MAC_CTX_free(ctx); + EVP_MAC_free(mac); free(start_realm); free(pre_req.data); krb5_free_creds(context, cred); @@ -972,7 +997,14 @@ rd_kx509_resp(krb5_context context, heim_string_t hestr; heim_error_t herr = NULL; const char *estr; - HMAC_CTX ctx; + EVP_MAC *mac = NULL; + EVP_MAC_CTX *ctx = NULL; + const EVP_MD *md = EVP_sha1(); + const char *mdname = EVP_MD_get0_name(md); + OSSL_PARAM params[] = { + OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, (char *)mdname, 0), + OSSL_PARAM_END + }; size_t hdr_len = sizeof(version_2_0); size_t len; @@ -996,15 +1028,18 @@ rd_kx509_resp(krb5_context context, return ret; } - HMAC_CTX_init(&ctx); - if (HMAC_Init_ex(&ctx, kx509_ctx->hmac_key->keyvalue.data, - kx509_ctx->hmac_key->keyvalue.length, EVP_sha1(), NULL) == 0) { + mac = EVP_MAC_fetch(context->ossl->libctx, "HMAC", context->ossl->propq); + ctx = EVP_MAC_CTX_new(mac); + if (EVP_MAC_init(ctx, kx509_ctx->hmac_key->keyvalue.data, + kx509_ctx->hmac_key->keyvalue.length, + params) != 1) { + EVP_MAC_CTX_free(ctx); + EVP_MAC_free(mac); free_Kx509Response(&r); - HMAC_CTX_cleanup(&ctx); return krb5_enomem(context); } - HMAC_Update(&ctx, version_2_0, sizeof(version_2_0)); + EVP_MAC_update(ctx, version_2_0, sizeof(version_2_0)); { int32_t t = r.error_code; @@ -1026,7 +1061,7 @@ rd_kx509_resp(krb5_context context, ret = der_put_integer(&encint[sizeof(encint) - 1], sizeof(encint), &t, &k); if (ret == 0) - HMAC_Update(&ctx, &encint[sizeof(encint)] - k, k); + EVP_MAC_update(ctx, &encint[sizeof(encint)] - k, k); /* Normalize error code */ if (r.error_code == 0) { @@ -1056,11 +1091,12 @@ rd_kx509_resp(krb5_context context, } } if (r.certificate) - HMAC_Update(&ctx, r.certificate->data, r.certificate->length); + EVP_MAC_update(ctx, r.certificate->data, r.certificate->length); if (r.e_text) - HMAC_Update(&ctx, *r.e_text, strlen(*r.e_text)); - HMAC_Final(&ctx, &digest, 0); - HMAC_CTX_cleanup(&ctx); + EVP_MAC_update(ctx, (const unsigned char *)*r.e_text, strlen(*r.e_text)); + EVP_MAC_final(ctx, digest, &len, sizeof(digest)); + EVP_MAC_CTX_free(ctx); + EVP_MAC_free(mac); if (r.hash == NULL) { /* diff --git a/lib/krb5/libkrb5-exports.def.in b/lib/krb5/libkrb5-exports.def.in index 1e117360a..4196fdb05 100644 --- a/lib/krb5/libkrb5-exports.def.in +++ b/lib/krb5/libkrb5-exports.def.in @@ -207,6 +207,8 @@ EXPORTS krb5_data_realloc krb5_data_zero krb5_debug + _krb5_debug + _krb5_debug_openssl krb5_decode_Authenticator krb5_decode_ETYPE_INFO2 krb5_decode_ETYPE_INFO @@ -221,36 +223,6 @@ EXPORTS krb5_decrypt_ivec krb5_decrypt_ticket krb5_derive_key - krb5_digest_alloc - krb5_digest_free - krb5_digest_get_client_binding - krb5_digest_get_identifier - krb5_digest_get_opaque - krb5_digest_get_rsp - krb5_digest_get_server_nonce - krb5_digest_get_session_key - krb5_digest_get_tickets - krb5_digest_init_request - krb5_digest_probe - krb5_digest_rep_get_status - krb5_digest_request - krb5_digest_set_authentication_user - krb5_digest_set_authid - krb5_digest_set_client_nonce - krb5_digest_set_digest - krb5_digest_set_hostname - krb5_digest_set_identifier - krb5_digest_set_method - krb5_digest_set_nonceCount - krb5_digest_set_opaque - krb5_digest_set_qop - krb5_digest_set_realm - krb5_digest_set_responseData - krb5_digest_set_server_cb - krb5_digest_set_server_nonce - krb5_digest_set_type - krb5_digest_set_uri - krb5_digest_set_username krb5_domain_x500_decode krb5_domain_x500_encode krb5_eai_to_heim_errno @@ -365,6 +337,7 @@ EXPORTS krb5_get_init_creds_opt_set_pa_password krb5_get_init_creds_opt_set_pac_request krb5_get_init_creds_opt_set_pkinit + krb5_get_init_creds_opt_set_pkinit_allowed_algs krb5_get_init_creds_opt_set_preauth_list krb5_get_init_creds_opt_set_process_last_req krb5_get_init_creds_opt_set_proxiable @@ -610,6 +583,7 @@ EXPORTS krb5_set_kdc_sec_offset krb5_set_log_dest krb5_set_max_time_skew + krb5_set_ossl_cnf_propq krb5_set_password krb5_set_password_using_ccache krb5_set_real_time @@ -869,8 +843,14 @@ EXPORTS _krb5_fast_explicit_armor_key ; Recent additions - krb5_cc_type_dcc; - krb5_dcc_ops; - _krb5_expand_path_tokensv; - _krb5_find_capath; - _krb5_free_capath; + krb5_cc_type_dcc + krb5_dcc_ops + _krb5_expand_path_tokensv + _krb5_find_capath + _krb5_free_capath + + ; Other + _krb5_UI_UTIL_read_pw_string + _krb5_hmac_start_ossl + _krb5_openssl_errors + _krb5_hmac_ossl diff --git a/lib/krb5/log.c b/lib/krb5/log.c index 306431a5c..aeb357d95 100644 --- a/lib/krb5/log.c +++ b/lib/krb5/log.c @@ -224,6 +224,36 @@ krb5_debug(krb5_context context, va_end(ap); } +void KRB5_LIB_FUNCTION +_krb5_debug_openssl(krb5_context context, + int level, + const char *fmt, + ...) + __attribute__ ((__format__ (__printf__, 3, 4))) +{ + va_list ap; + char *fmt2 = NULL; + char *omsg; + + va_start(ap, fmt); + if (!context || !context->hcontext) { + va_end(ap); + return; + } + if ((omsg = _krb5_openssl_errors())) { + if (asprintf(&fmt2, "%s: %s", fmt, omsg) < 0 || fmt2 == NULL) { + heim_vdebug(context->hcontext, level, fmt, ap); + } else { + heim_vdebug(context->hcontext, level, fmt2, ap); + } + } else { + heim_vdebug(context->hcontext, level, fmt, ap); + } + va_end(ap); + free(omsg); + free(fmt2); +} + KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL _krb5_have_debug(krb5_context context, int level) { diff --git a/lib/krb5/pkinit-ec.c b/lib/krb5/pkinit-ec.c index 7043049f6..c3bf6ba31 100644 --- a/lib/krb5/pkinit-ec.c +++ b/lib/krb5/pkinit-ec.c @@ -43,7 +43,6 @@ #include #include #include -#define HEIM_NO_CRYPTO_HDRS #include "krb5_locl.h" #include @@ -55,123 +54,284 @@ #include -krb5_error_code -_krb5_build_authpack_subjectPK_EC(krb5_context context, - krb5_pk_init_ctx ctx, - AuthPack *a) +static const char * +ec_oid2nidname(const heim_oid *oid) { - krb5_error_code ret; - ECParameters ecp; - unsigned char *p; - size_t size; - int xlen; + if (der_heim_oid_cmp(oid, &asn1_oid_id_X25519) == 0) + return "X25519"; + if (der_heim_oid_cmp(oid, &asn1_oid_id_X448) == 0) + return "X448"; + if (der_heim_oid_cmp(oid, &asn1_oid_id_ec_group_secp256r1) == 0) + return "prime256v1"; + if (der_heim_oid_cmp(oid, &asn1_oid_id_ec_group_secp384r1) == 0) + return "secp384r1"; + if (der_heim_oid_cmp(oid, &asn1_oid_id_ec_group_secp521r1) == 0) + return "secp521r1"; + return NULL; +} - /* copy in public key, XXX find the best curve that the server support or use the clients curve if possible */ +const heim_oid * +_krb5_ec_nidname2heim_oid(const char *sn) +{ + if (strcmp(sn, "X25519") == 0) + return &asn1_oid_id_X25519; + if (strcmp(sn, "X448") == 0) + return &asn1_oid_id_X448; + if (strcmp(sn, "prime256v1") == 0 || strcmp(sn, "P-256") == 0) + return &asn1_oid_id_ec_group_secp256r1; + if (strcmp(sn, "secp384r1") == 0 || strcmp(sn, "P-384") == 0) + return &asn1_oid_id_ec_group_secp384r1; + if (strcmp(sn, "secp521r1") == 0 || strcmp(sn, "P-521") == 0) + return &asn1_oid_id_ec_group_secp521r1; + return NULL; +} - ecp.element = choice_ECParameters_namedCurve; - ret = der_copy_oid(&asn1_oid_id_ec_group_secp256r1, - &ecp.u.namedCurve); - if (ret) - return ret; +const heim_oid * +_krb5_pkinit_pick_curve(krb5_context context, krb5_pk_init_ctx ctx) +{ + TD_DH_PARAMETERS *p = ctx->kdc_dh_algs; + const char *curve = NULL; + const char *dh_min_bits = krb5_config_get_string(context, NULL, + "libdefaults", + "pkinit_dh_min_bits", + NULL); + const heim_oid *oid; + size_t i; - ALLOC(a->clientPublicValue->algorithm.parameters, 1); - if (a->clientPublicValue->algorithm.parameters == NULL) { - free_ECParameters(&ecp); - return krb5_enomem(context); - } - ASN1_MALLOC_ENCODE(ECParameters, p, xlen, &ecp, &size, ret); - free_ECParameters(&ecp); - if (ret) - return ret; - if ((int)size != xlen) - krb5_abortx(context, "asn1 internal error"); + /* + * The user wants a specific curve (this is great for interop testing via + * kinit(1)). + */ + if (ctx->want_dh_alg && (curve = ec_oid2nidname(ctx->want_dh_alg))) + return ctx->want_dh_alg; - a->clientPublicValue->algorithm.parameters->data = p; - a->clientPublicValue->algorithm.parameters->length = size; + /* + * If the server indicated supported DH groups and/or curves, pick the + * first one of those that is a curve that we also allow per local + * configuration. + */ + for (i = 0; p && i < p->len; i++) { + oid = &p->val[i].algorithm; - /* copy in public key */ + if (der_heim_oid_cmp(oid, &asn1_oid_id_ecPublicKey) == 0 && + p->val[i].parameters) { + ECParameters ecp; - ret = der_copy_oid(&asn1_oid_id_ecPublicKey, - &a->clientPublicValue->algorithm.algorithm); - 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); - - 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; - - p = malloc(xlen); - if (p == NULL) - return krb5_enomem(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); - return EINVAL; + memset(&ecp, 0, sizeof(ecp)); + if (decode_ECParameters(p->val[i].parameters->data, + p->val[i].parameters->length, + &ecp, NULL)) + continue; + if (ecp.element != choice_ECParameters_namedCurve) { + free_ECParameters(&ecp); + continue; + } + curve = ec_oid2nidname(&ecp.u.namedCurve); + if (krb5_config_get_bool_default(context, NULL, 1, "libdefaults", + "pkinit_allow_ecdh", curve, NULL)) + return _krb5_ec_nidname2heim_oid(curve); + } else if ((curve = ec_oid2nidname(oid)) && + krb5_config_get_bool_default(context, NULL, 1, "libdefaults", + "pkinit_allow_ecdh", curve, NULL)) + /* Normalize to constant OID */ + return _krb5_ec_nidname2heim_oid(curve); } - a->clientPublicValue->subjectPublicKey.length = xlen * 8; - - return 0; - - /* XXX verify that this is right with RFC3279 */ + if (dh_min_bits && (oid = _krb5_ec_nidname2heim_oid(dh_min_bits))) + return oid; /* MIT Kerberos config compat */ + if (krb5_config_get_bool_default(context, NULL, 1, "libdefaults", + "pkinit_allow_ecdh", "X25519", NULL)) + return &asn1_oid_id_X25519; + if (krb5_config_get_bool_default(context, NULL, 1, "libdefaults", + "pkinit_allow_ecdh", "X448", NULL)) + return &asn1_oid_id_X448; + if (krb5_config_get_bool_default(context, NULL, 1, "libdefaults", + "pkinit_allow_ecdh", "prime256v1", NULL)) + return &asn1_oid_id_ec_group_secp256r1; + if (krb5_config_get_bool_default(context, NULL, 1, "libdefaults", + "pkinit_allow_ecdh", "secp384r1", NULL)) + return &asn1_oid_id_ec_group_secp384r1; + if (krb5_config_get_bool_default(context, NULL, 1, "libdefaults", + "pkinit_allow_ecdh", "secp521r1", NULL)) + return &asn1_oid_id_ec_group_secp521r1; + return &asn1_oid_id_X25519; } krb5_error_code -_krb5_pk_rd_pa_reply_ecdh_compute_key(krb5_context context, +_krb5_pkinit_make_ecdh_key(krb5_context context, + OSSL_LIB_CTX *libctx, + const char *propq, + const heim_oid *alg, + EVP_PKEY **pkeyp) +{ + EVP_PKEY_CTX *pctx = NULL; + EVP_PKEY_CTX *kctx = NULL; + EVP_PKEY *params = NULL; + EVP_PKEY *pkey = NULL; + const char *curve = ec_oid2nidname(alg); + krb5_error_code ret = HX509_CRYPTO_INTERNAL_ERROR; + + *pkeyp = NULL; + curve = (curve) ? curve : "prime256v1"; + + if (strcmp(curve, "X25519") == 0 || strcmp(curve, "X448") == 0) { + if ((kctx = EVP_PKEY_CTX_new_from_name(libctx, curve, propq)) == NULL || + EVP_PKEY_keygen_init(kctx) <= 0 || + EVP_PKEY_keygen(kctx, &pkey) <= 0) { + char *omsg = _krb5_openssl_errors(); + krb5_set_error_message(context, ret, + "PKINIT: Could not make a PKEY for %s: %s", + curve, omsg ? omsg : ""); + free(omsg); + EVP_PKEY_CTX_free(kctx); + return ret; + } + EVP_PKEY_CTX_free(kctx); + *pkeyp = pkey; + return 0; + } + + OSSL_PARAM p[] = { + OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, + (char *)curve, 0), + OSSL_PARAM_END + }; + + if ((pctx = EVP_PKEY_CTX_new_from_name(libctx, "EC", propq)) == NULL) + return _krb5_set_error_message_openssl(context, ret, + "PKINIT: Could not create EC context"); + if (EVP_PKEY_paramgen_init(pctx) <= 0 || + EVP_PKEY_CTX_set_params(pctx, p) <= 0 || + EVP_PKEY_paramgen(pctx, ¶ms) <= 0 || + (kctx = EVP_PKEY_CTX_new_from_pkey(libctx, params, propq)) == NULL || + EVP_PKEY_keygen_init(kctx) <= 0 || + EVP_PKEY_keygen(kctx, &pkey) <= 0) { + char *omsg = _krb5_openssl_errors(); + krb5_set_error_message(context, + ret, + "PKINIT: Could not make a PKEY for EC curve: %s: %s", + curve, omsg ? omsg : ""); + free(omsg); + goto out; + } + + ret = 0; + +out: + *pkeyp = pkey; + + EVP_PKEY_CTX_free(kctx); + EVP_PKEY_CTX_free(pctx); + EVP_PKEY_free(params); + return ret; +} + +/* + * OpenSSL does not support use of i2d_PublicKey()/d2i_PublicKey() for all key + * agreement types, instead requiring a more complex API with special cases for + * EC, DH, DHX, and X25519/X448. Instead we do something very fancy and silly: + * use our pkey to format an SPKI with i2d_PUBKEY(), decode it, replace the + * SPK, then import with d2i_PUBKEY(). A bit gross, but less gross than lots + * of special cases. + */ +krb5_error_code +_krb5_ossl_d2i_PublicKey(krb5_context context, + const EVP_PKEY *ours, + heim_bit_string their_spk, + EVP_PKEY **theirs) +{ + SubjectPublicKeyInfo spki; + krb5_error_code ret; + const unsigned char *p; + size_t size; + + memset(&spki, 0, sizeof(spki)); + + /* Transform ours into a decoded SPKI */ + ret = _krb5_pkinit_pkey2SubjectPublicKeyInfo(context, ours, &spki); + if (ret) + return ret; + + /* Replace the decoded SPKI's subjectPublicKey (ours) with theirs */ + der_free_bit_string(&spki.subjectPublicKey); + spki.subjectPublicKey = their_spk; + + /* + * Encode the SPKI, using the _save as a convenient place to put the + * encoding. + */ + der_free_octet_string(&spki._save); + ASN1_MALLOC_ENCODE(SubjectPublicKeyInfo, spki._save.data, + spki._save.length, &spki, &size, ret); + + /* + * Finally! Call d2i_PUBKEY(), which will work. + * + * Look 'ma! No special cases needed for all the kinds of key agreement + * protocols. We did pay a price: having to encode, decode, encode -- a + * bit silly, but the real silliness lies in OpenSSL's API. + */ + p = spki._save.data; + *theirs = d2i_PUBKEY(NULL, &p, size); + + spki.subjectPublicKey.data = NULL; + spki.subjectPublicKey.length = 0; + free_SubjectPublicKeyInfo(&spki); + + if (*theirs == NULL) { + char *omsg = _krb5_openssl_errors(); + + krb5_set_error_message(context, + ret = HX509_PARSING_KEY_FAILED, + "PKINIT: Can't parse the KDC's ECDH public key: %s", + omsg ? omsg : ""); + free(omsg); + return ret; + } + + return 0; +} + +krb5_error_code +_krb5_pk_rd_pa_reply_ossl_compute_key(krb5_context context, krb5_pk_init_ctx ctx, - const unsigned char *in, - size_t in_sz, + heim_bit_string in, unsigned char **out, int *out_sz) { -#ifdef HAVE_OPENSSL_30 - krb5_error_code ret = 0; + krb5_error_code ret; EVP_PKEY_CTX *pctx = NULL; EVP_PKEY *template = NULL; EVP_PKEY *public = NULL; size_t shared_len = 0; + int oret; + + ret = _krb5_ossl_d2i_PublicKey(context, ctx->pkey, in, &public); + if (ret) + return ret; if ((template = EVP_PKEY_new()) == NULL) ret = krb5_enomem(context); if (ret == 0 && - EVP_PKEY_copy_parameters(template, ctx->u.eckey) != 1) + EVP_PKEY_copy_parameters(template, ctx->pkey) != 1) ret = krb5_enomem(context); - if (ret == 0 && (pctx = EVP_PKEY_CTX_new(ctx->u.eckey, NULL)) == NULL) + if (ret == 0 && (pctx = EVP_PKEY_CTX_new(ctx->pkey, 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"); + + /* Set the KDF to no KDF because PKINIT does its own KDF */ + if (ctx->keyex == USE_DH) { + if (ret == 0 && + EVP_PKEY_CTX_set_dh_kdf_type(pctx, EVP_PKEY_DH_KDF_NONE) != 1) + ret = krb5_enomem(context); + } else { + if (ret == 0 && + (oret = EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, EVP_PKEY_ECDH_KDF_NONE)) <= 0 && + oret != -2) + ret = krb5_enomem(context); + } + if (ret == 0 && EVP_PKEY_derive_set_peer_ex(pctx, public, 1) != 1) krb5_set_error_message(context, @@ -198,70 +358,11 @@ _krb5_pk_rd_pa_reply_ecdh_compute_key(krb5_context context, "(EVP_PKEY_derive)"); if (ret == 0) *out_sz = shared_len; - EVP_PKEY_CTX_free(pctx); // move + EVP_PKEY_CTX_free(pctx); EVP_PKEY_free(template); + EVP_PKEY_free(public); return ret; -#else - krb5_error_code ret = 0; - int dh_gen_keylen; - - const EC_GROUP *group; - EC_KEY *public = NULL; - - group = EC_KEY_get0_group(ctx->u.eckey); - - public = EC_KEY_new(); - if (public == NULL) - return krb5_enomem(context); - if (EC_KEY_set_group(public, group) != 1) { - EC_KEY_free(public); - return krb5_enomem(context); - } - - if (o2i_ECPublicKey(&public, &in, in_sz) == NULL) { - EC_KEY_free(public); - ret = KRB5KRB_ERR_GENERIC; - krb5_set_error_message(context, ret, - N_("PKINIT: Can't parse ECDH public key", "")); - return ret; - } - - *out_sz = (EC_GROUP_get_degree(group) + 7) / 8; - if (*out_sz < 0) - return EOVERFLOW; - *out = malloc(*out_sz); - if (*out == NULL) { - EC_KEY_free(public); - return krb5_enomem(context); - } - dh_gen_keylen = ECDH_compute_key(*out, *out_sz, - EC_KEY_get0_public_key(public), - ctx->u.eckey, NULL); - EC_KEY_free(public); - if (dh_gen_keylen <= 0) { - ret = KRB5KRB_ERR_GENERIC; - dh_gen_keylen = 0; - krb5_set_error_message(context, ret, - N_("PKINIT: Can't compute ECDH public key", "")); - free(*out); - *out = NULL; - *out_sz = 0; - } - *out_sz = dh_gen_keylen; - - return ret; -#endif -} - -void -_krb5_pk_eckey_free(void *eckey) -{ -#ifdef HAVE_OPENSSL_30 - EVP_PKEY_free(eckey); -#else - EC_KEY_free(eckey); -#endif } #else diff --git a/lib/krb5/pkinit.c b/lib/krb5/pkinit.c index 1b34c18ab..ad3b86a8b 100644 --- a/lib/krb5/pkinit.c +++ b/lib/krb5/pkinit.c @@ -43,8 +43,6 @@ struct krb5_dh_moduli { heim_integer q; }; -#ifdef PKINIT - #include #include #include @@ -54,6 +52,200 @@ struct krb5_dh_moduli { #include +#include +#include + +krb5_error_code +_krb5_pkinit_pkey2SubjectPublicKeyInfo(krb5_context context, + const EVP_PKEY *pkey, + SubjectPublicKeyInfo *spki) +{ + unsigned char *buf = NULL; + unsigned char *p; + size_t len, size; + krb5_error_code ret; + + len = i2d_PUBKEY(pkey, NULL); + if (len <= 0) + return _krb5_set_error_message_openssl(context, + HX509_CRYPTO_INTERNAL_ERROR, + "Failed to encode public key"); + + p = buf = malloc(len); + if (p == NULL) + return krb5_enomem(context); + + if (i2d_PUBKEY(pkey, &p) != len) { + free(buf); + return _krb5_set_error_message_openssl(context, + HX509_CRYPTO_INTERNAL_ERROR, + "Failed to encode public key"); + } + + ret = decode_SubjectPublicKeyInfo(buf, len, spki, &size); + free(buf); + return ret; +} + +/* Makes a EVP_PKEY * params object from modp DH p, g, q (q is optional) */ +static EVP_PKEY * +dh_params_from_pg(krb5_context context, + const unsigned char *p, size_t plen, + const unsigned char *g, size_t glen, + const unsigned char *q, size_t qlen) +{ + EVP_PKEY *params = NULL; + EVP_PKEY_CTX *ctx = NULL; + BIGNUM *p_bn = NULL; + BIGNUM *g_bn = NULL; + BIGNUM *q_bn = NULL; + OSSL_PARAM_BLD *bld = NULL; + OSSL_PARAM *par = NULL; + + /* Convert raw bytes to BIGNUMs - OpenSSL 3.x requires BN for FFC params */ + p_bn = BN_bin2bn(p, plen, NULL); + g_bn = BN_bin2bn(g, glen, NULL); + if (q && qlen) + q_bn = BN_bin2bn(q, qlen, NULL); + + if (!p_bn || !g_bn || (q && qlen && !q_bn)) + goto out; + + /* Build OSSL_PARAM array */ + bld = OSSL_PARAM_BLD_new(); + if (!bld) + goto out; + if (!OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_P, p_bn) || + !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_G, g_bn)) + goto out; + if (q_bn && !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_Q, q_bn)) + goto out; + par = OSSL_PARAM_BLD_to_param(bld); + if (!par) + goto out; + + /* + * Always use DHX (X9.42 DH) for PKINIT - this produces the + * id-dhpublicnumber OID (1.2.840.10046.2.1) that PKINIT requires, + * rather than the PKCS#3 OID (1.2.840.113549.1.3.1) that "DH" uses. + */ + ctx = EVP_PKEY_CTX_new_from_name(context->ossl->libctx, "DHX", + context->ossl->propq); + if (!ctx) + goto out; + if (EVP_PKEY_fromdata_init(ctx) <= 0) + goto out; + if (EVP_PKEY_fromdata(ctx, ¶ms, EVP_PKEY_KEY_PARAMETERS, par) <= 0) + params = NULL; + +out: + OSSL_PARAM_free(par); + OSSL_PARAM_BLD_free(bld); + EVP_PKEY_CTX_free(ctx); + BN_free(p_bn); + BN_free(g_bn); + BN_free(q_bn); + return params; +} + +/* + * Produce OpenSSL 3.x params from the p, g, q in a modp DH + * AlgorithmIdentifier returned by a KDC. + * + * Note that we don't validate the domain parameters. + */ +static krb5_error_code +dh_params_from_AI(krb5_context context, + heim_octet_string *ai_params, + EVP_PKEY **out) +{ + DomainParameters dp; + krb5_error_code ret; + const unsigned char *p, *g, *q; + size_t plen, glen, qlen; + + *out = NULL; + ret = decode_DomainParameters(ai_params->data, ai_params->length, &dp, NULL); + if (ret) + return ret; + + /* + * heim_integer has the DER-encoding of the INTEGER. OpenSSL wants the + * unsigned, unpadded DER-encoding of the INTEGER. So we reject negative + * numbers and remove any padding, then use dh_params_from_pg(). + */ + + if (dp.p.negative || dp.g.negative || (dp.q && dp.q->negative)) + return EINVAL; + + p = dp.p.data; + plen = dp.p.length; + g = dp.g.data; + glen = dp.g.length; + q = dp.q ? dp.q->data : NULL; + qlen = dp.q ? dp.q->length : 0; + + if (dp.p.length > 1 && p[0] == 0) { p++; plen--; } + if (dp.g.length > 1 && g[0] == 0) { g++; glen--; } + if (q && dp.q->length > 1 && q[0] == 0) { q++; qlen--; } + + *out = dh_params_from_pg(context, p, plen, g, glen, q, qlen); + free_DomainParameters(&dp); + if (*out) + return 0; + return EINVAL; +} + +static krb5_error_code +pkinit_make_dh_key(krb5_context context, + EVP_PKEY *params_in, + const char *group, + EVP_PKEY **pkey) +{ + EVP_PKEY_CTX *pctx = NULL; + EVP_PKEY_CTX *kctx = NULL; + EVP_PKEY *params = NULL; + OSSL_PARAM p[] = { + OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, + (char *)group, 0), + OSSL_PARAM_END + }; + + *pkey = NULL; + if (params_in) { + if ((kctx = EVP_PKEY_CTX_new_from_pkey(context->ossl->libctx, params_in, + context->ossl->propq)) == NULL || + EVP_PKEY_keygen_init(kctx) <= 0 || + EVP_PKEY_keygen(kctx, pkey) <= 0) + *pkey = NULL; + } else { + if ((pctx = EVP_PKEY_CTX_new_from_name(context->ossl->libctx, "DHX", + context->ossl->propq)) == NULL || + EVP_PKEY_paramgen_init(pctx) <= 0 || + EVP_PKEY_CTX_set_params(pctx, p) <= 0 || + EVP_PKEY_paramgen(pctx, ¶ms) <= 0 || + (kctx = EVP_PKEY_CTX_new_from_pkey(context->ossl->libctx, params, + context->ossl->propq)) == NULL || + EVP_PKEY_keygen_init(kctx) <= 0 || + EVP_PKEY_keygen(kctx, pkey) <= 0) + *pkey = NULL; + } + + EVP_PKEY_CTX_free(kctx); + EVP_PKEY_CTX_free(pctx); + EVP_PKEY_free(params); + if (*pkey == NULL) { + char *s = _krb5_openssl_errors(); + + krb5_set_error_message(context, HX509_CRYPTO_INTERNAL_ERROR, + "Could not make a DH keyshare: %s", + s ? s : ""); + free(s); + return HX509_CRYPTO_INTERNAL_ERROR; + } + return 0; +} + struct krb5_pk_cert { hx509_cert cert; }; @@ -79,40 +271,134 @@ _krb5_pk_cert_free(struct krb5_pk_cert *cert) free(cert); } -static krb5_error_code -BN_to_integer(krb5_context context, BIGNUM *bn, heim_integer *integer) +static enum keyex_enum +select_dh_type(krb5_context context, krb5_pk_init_ctx ctx) { - integer->length = BN_num_bytes(bn); - integer->data = malloc(integer->length); - if (integer->data == NULL) { - krb5_clear_error_message(context); - return ENOMEM; - } - BN_bn2bin(bn, integer->data); - integer->negative = BN_is_negative(bn); - return 0; -} + TD_DH_PARAMETERS *p = ctx->kdc_dh_algs; + hx509_cert cert = ctx->id->cert; + size_t i; + int seen_ec = 0; + int seen_modp = 0; + int prefer_ec = + krb5_config_get_bool_default(context, NULL, -1, + "libdefaults", "pkinit_prefer_ec", NULL); -static BIGNUM * -integer_to_BN(krb5_context context, const char *field, const heim_integer *f) -{ - BIGNUM *bn; + /* + * The KDC offered key agreement algorithms; pick one we like. We + * prefer EC to modp DH. + */ + if (p) { + for (i = 0; i < p->len; i++) { + const heim_oid *oid = &p->val[i].algorithm; - bn = BN_bin2bn((const unsigned char *)f->data, f->length, NULL); - if (bn == NULL) { - krb5_set_error_message(context, ENOMEM, - N_("PKINIT: parsing BN failed %s", ""), field); - return NULL; + if (der_heim_oid_cmp(oid, &asn1_oid_id_X25519) == 0 || + der_heim_oid_cmp(oid, &asn1_oid_id_X448) == 0 || + der_heim_oid_cmp(oid, &asn1_oid_id_ec_group_secp256r1) == 0 || + der_heim_oid_cmp(oid, &asn1_oid_id_ec_group_secp384r1) == 0 || + der_heim_oid_cmp(oid, &asn1_oid_id_ec_group_secp521r1) == 0) + seen_ec = 1; + else if (der_heim_oid_cmp(oid, &asn1_oid_id_dhpublicnumber) == 0 && + p->val[i].parameters != NULL) + seen_modp = 1; + } } - BN_set_negative(bn, f->negative); - return bn; + + if (prefer_ec == -1 && cert) { + AlgorithmIdentifier alg; + + /* Cert indicates EC support -> then use ECDH */ + if (hx509_cert_get_SPKI_AlgorithmIdentifier(context->hx509ctx, cert, + &alg) == 0) { + if (der_heim_oid_cmp(&alg.algorithm, &asn1_oid_id_ecPublicKey) == 0) + prefer_ec = 1; + else if (der_heim_oid_cmp(&alg.algorithm, &asn1_oid_id_Ed25519) == 0) + prefer_ec = 1; + else if (der_heim_oid_cmp(&alg.algorithm, &asn1_oid_id_Ed448) == 0) + prefer_ec = 1; + free_AlgorithmIdentifier(&alg); + } + } + + /* Whichever we preferred, if the KDC offered it, use that */ + if (prefer_ec > 0 && seen_ec) + return USE_ECDH; + if (prefer_ec == 0 && seen_modp) + return USE_DH; + /* Whichever we preferred, if the KDC only offered the other, use that */ + if (seen_ec) + return USE_ECDH; + if (seen_modp) + return USE_DH; + + /* + * The KDC offered nothing (yet, perhaps because we have not yet tried, or + * perhaps it doesn't support telling us its preference). + * + * Prefer EC/X DH then. + */ + if (prefer_ec == -1) + prefer_ec = 1; + + return prefer_ec ? USE_ECDH : USE_DH; } static krb5_error_code -select_dh_group(krb5_context context, DH *dh, unsigned long min_bits, - struct krb5_dh_moduli **moduli) +select_dh_group(krb5_context context, EVP_PKEY **params, const char **group, + unsigned long min_bits, krb5_pk_init_ctx ctx) { const struct krb5_dh_moduli *m; + struct krb5_dh_moduli **moduli = ctx->m; + TD_DH_PARAMETERS *p = ctx->kdc_dh_algs; + krb5_error_code ret; + + if (p) { + size_t i; + + /* + * Pick the first DH modp group offered by the KDC. We do not validate + * this group if [libdefaults] pkinit_dh_trust_modp_kdc_choice is set + * to true. Since we're going to get a signature from the KDC and we + * validate the KDC's certificate, we can default this to TRUE. + * + * NOTE: If we ever try to build something like PKU2U w/ anonymous + * server support then we'll need to default this to FALSE for + * that case! + */ + if (!krb5_config_get_bool_default(context, NULL, TRUE, + "libdefaults", + "pkinit_dh_trust_modp_kdc_choice", NULL)) + return KRB5_KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED; + for (i = 0; i < p->len; i++) { + if (der_heim_oid_cmp(&p->val[i].algorithm, + &asn1_oid_id_dhpublicnumber) != 0 || + p->val[i].parameters == NULL) + continue; + ret = dh_params_from_AI(context, p->val[i].parameters, params); + if (ret) + // XXX More trace/error info would be nice + return KRB5_KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED; + return 0; + } + return KRB5_KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED; + } + + if (krb5_config_get_bool_default(context, NULL, TRUE, + "libdefaults", + "pkinit_dh_use_modp", NULL)) { + /* + * Use RFC 3526 Oakley groups (modp_*). MIT Kerberos only supports + * 1024 (disabled by default), 2048, and 4096. Default to 2048. + */ + if (min_bits == 0 || min_bits <= 2048) { + *group = "modp_2048"; + return 0; + } + if (min_bits <= 4096) { + *group = "modp_4096"; + return 0; + } + /* Larger sizes not supported by MIT, fall through to moduli file */ + } if (moduli[0] == NULL) { krb5_set_error_message(context, EINVAL, @@ -123,9 +409,7 @@ select_dh_group(krb5_context context, DH *dh, unsigned long min_bits, } if (min_bits == 0) { - m = moduli[1]; /* XXX */ - if (m == NULL) - m = moduli[0]; /* XXX */ + m = moduli[0]; } else { int i; for (i = 0; moduli[i] != NULL; i++) { @@ -142,16 +426,9 @@ select_dh_group(krb5_context context, DH *dh, unsigned long min_bits, m = moduli[i]; } - dh->p = integer_to_BN(context, "p", &m->p); - if (dh->p == NULL) - return ENOMEM; - dh->g = integer_to_BN(context, "g", &m->g); - if (dh->g == NULL) - return ENOMEM; - dh->q = integer_to_BN(context, "q", &m->q); - if (dh->q == NULL) - return ENOMEM; - + *params = dh_params_from_pg(context, m->p.data, m->p.length, + m->g.data, m->g.length, + m->q.data ? m->q.data : NULL, m->q.length); return 0; } @@ -347,6 +624,96 @@ build_edi(krb5_context context, return hx509_certs_iter_f(hx509ctx, certs, cert2epi, ids); } +static krb5_error_code +make_supportedKDFs(krb5_context context, krb5_pk_init_ctx ctx, AuthPack *a) +{ + char **kdfs; + krb5_error_code ret; + KDFAlgorithmId kdf; + + memset(&kdf, 0, sizeof(kdf)); + + if (ctx->want_kdf_alg && + der_heim_oid_cmp(ctx->want_kdf_alg, &asn1_oid_id_pkinit_kdf) == 0) { + if (a->supportedKDFs) + free_SupportedKDFs(a->supportedKDFs); + free(a->supportedKDFs); + a->supportedKDFs = NULL; + return 0; + } + + if (a->supportedKDFs) + free_SupportedKDFs(a->supportedKDFs); + else if ((a->supportedKDFs = + calloc(1, sizeof(*a->supportedKDFs))) == NULL) + return krb5_enomem(context); + + if (ctx->want_kdf_alg) { + ret = der_copy_oid(ctx->want_kdf_alg, &kdf.kdf_id); + if (ret) + return ret; + ret = add_SupportedKDFs(a->supportedKDFs, &kdf); + der_free_oid(&kdf.kdf_id); + return ret; + } + + kdfs = krb5_config_get_strings(context, NULL, "libdefaults", "pkinit_kdfs", + NULL); + if (kdfs) { + const heim_oid *oid = NULL; + size_t i; + + /* XXX Extract this if-strcmp ladder into a utility function */ + for (i = 0; kdfs[i]; i++) { + if (strcmp(kdfs[i], "ah-sha1") == 0) + oid = &asn1_oid_id_pkinit_kdf_ah_sha1; + else if (strcmp(kdfs[i], "ah-sha256") == 0) + oid = &asn1_oid_id_pkinit_kdf_ah_sha256; + else if (strcmp(kdfs[i], "ah-sha384") == 0) + oid = &asn1_oid_id_pkinit_kdf_ah_sha384; + else if (strcmp(kdfs[i], "ah-sha512") == 0) + oid = &asn1_oid_id_pkinit_kdf_ah_sha512; + if (oid == NULL) + continue; // XXX debug trace or error! + ret = der_copy_oid(oid, &kdf.kdf_id); + if (ret) + return ret; + ret = add_SupportedKDFs(a->supportedKDFs, &kdf); + der_free_oid(&kdf.kdf_id); + if (ret) + return ret; + } + krb5_config_free_strings(kdfs); + return 0; + } + + /* + * Indicate support for all of them. RFC 4556 is what we'll get if the KDC + * doesn't support any of these RFC 8636 ones. + */ + ret = der_copy_oid(&asn1_oid_id_pkinit_kdf_ah_sha256, &kdf.kdf_id); + if (ret == 0) + ret = add_SupportedKDFs(a->supportedKDFs, &kdf); + der_free_oid(&kdf.kdf_id); + + ret = der_copy_oid(&asn1_oid_id_pkinit_kdf_ah_sha384, &kdf.kdf_id); + if (ret == 0) + ret = add_SupportedKDFs(a->supportedKDFs, &kdf); + der_free_oid(&kdf.kdf_id); + + ret = der_copy_oid(&asn1_oid_id_pkinit_kdf_ah_sha512, &kdf.kdf_id); + if (ret == 0) + ret = add_SupportedKDFs(a->supportedKDFs, &kdf); + der_free_oid(&kdf.kdf_id); + + ret = der_copy_oid(&asn1_oid_id_pkinit_kdf_ah_sha1, &kdf.kdf_id); + if (ret == 0) + ret = add_SupportedKDFs(a->supportedKDFs, &kdf); + der_free_oid(&kdf.kdf_id); + + return ret; +} + static krb5_error_code build_auth_pack(krb5_context context, unsigned nonce, @@ -369,6 +736,10 @@ build_auth_pack(krb5_context context, a->pkAuthenticator.ctime = sec; a->pkAuthenticator.nonce = nonce; + ret = make_supportedKDFs(context, ctx, a); + if (ret) + return ret; + ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, body, &len, ret); if (ret) return ret; @@ -398,45 +769,11 @@ build_auth_pack(krb5_context context, return ret; if (ctx->keyex == USE_DH || ctx->keyex == USE_ECDH) { - const char *moduli_file; - unsigned long dh_min_bits; + EVP_PKEY *params = NULL; krb5_data dhbuf; - size_t size = 0; krb5_data_zero(&dhbuf); - - - moduli_file = krb5_config_get_string(context, NULL, - "libdefaults", - "moduli", - NULL); - - dh_min_bits = - krb5_config_get_int_default(context, NULL, 0, - "libdefaults", - "pkinit_dh_min_bits", - NULL); - - ret = _krb5_parse_moduli(context, moduli_file, &ctx->m); - if (ret) - return ret; - - ctx->u.dh = DH_new(); - if (ctx->u.dh == NULL) - return krb5_enomem(context); - - ret = select_dh_group(context, ctx->u.dh, dh_min_bits, ctx->m); - if (ret) - return ret; - - if (DH_generate_key(ctx->u.dh) != 1) { - krb5_set_error_message(context, ENOMEM, - N_("pkinit: failed to generate DH key", "")); - return ENOMEM; - } - - if (1 /* support_cached_dh */) { ALLOC(a->clientDHNonce, 1); if (a->clientDHNonce == NULL) { @@ -457,94 +794,72 @@ build_auth_pack(krb5_context context, return ret; } - ALLOC(a->clientPublicValue, 1); - if (a->clientPublicValue == NULL) - return ENOMEM; - if (ctx->keyex == USE_DH) { - DH *dh = ctx->u.dh; - DomainParameters dp; - heim_integer dh_pub_key; + const char *group = NULL; + const char *moduli_file = + krb5_config_get_string(context, NULL, "libdefaults", "moduli", + NULL); + unsigned long dh_min_bits = + krb5_config_get_int_default(context, NULL, 0, + "libdefaults", + "pkinit_dh_min_bits", + NULL); - ret = der_copy_oid(&asn1_oid_id_dhpublicnumber, - &a->clientPublicValue->algorithm.algorithm); - if (ret) - return ret; - - memset(&dp, 0, sizeof(dp)); - - ret = BN_to_integer(context, dh->p, &dp.p); - if (ret) { - free_DomainParameters(&dp); - return ret; - } - ret = BN_to_integer(context, dh->g, &dp.g); - if (ret) { - free_DomainParameters(&dp); - return ret; - } - if (dh->q && BN_num_bits(dh->q)) { - /* - * The q parameter is required, but MSFT made it optional. - * It's only required in order to verify the domain parameters - * -- the security of the DH group --, but we validate groups - * against known groups rather than accepting arbitrary groups - * chosen by the peer, so we really don't need to have put it - * on the wire. Because these are Oakley groups, and the - * primes are Sophie Germain primes, q is p>>1 and we can - * compute it on the fly like MIT Kerberos does, but we'd have - * to implement BN_rshift1(). - */ - dp.q = calloc(1, sizeof(*dp.q)); - if (dp.q == NULL) { - free_DomainParameters(&dp); - return ENOMEM; - } - ret = BN_to_integer(context, dh->q, dp.q); - if (ret) { - free_DomainParameters(&dp); - return ret; - } - } - dp.j = NULL; - dp.validationParms = NULL; - - a->clientPublicValue->algorithm.parameters = - malloc(sizeof(*a->clientPublicValue->algorithm.parameters)); - if (a->clientPublicValue->algorithm.parameters == NULL) { - free_DomainParameters(&dp); - return ret; - } - - ASN1_MALLOC_ENCODE(DomainParameters, - a->clientPublicValue->algorithm.parameters->data, - a->clientPublicValue->algorithm.parameters->length, - &dp, &size, ret); - free_DomainParameters(&dp); - if (ret) - return ret; - if (size != a->clientPublicValue->algorithm.parameters->length) - krb5_abortx(context, "Internal ASN1 encoder error"); - - ret = BN_to_integer(context, dh->pub_key, &dh_pub_key); - if (ret) - return ret; - - ASN1_MALLOC_ENCODE(DHPublicKey, dhbuf.data, dhbuf.length, - &dh_pub_key, &size, ret); - der_free_heim_integer(&dh_pub_key); - if (ret) - return ret; - if (size != dhbuf.length) - krb5_abortx(context, "asn1 internal error"); - a->clientPublicValue->subjectPublicKey.length = dhbuf.length * 8; - a->clientPublicValue->subjectPublicKey.data = dhbuf.data; - } else if (ctx->keyex == USE_ECDH) { - ret = _krb5_build_authpack_subjectPK_EC(context, ctx, a); + ret = _krb5_parse_moduli(context, moduli_file, &ctx->m); if (ret) return ret; - } else - krb5_abortx(context, "internal error"); + + ret = select_dh_group(context, ¶ms, &group, dh_min_bits, ctx); + if (ret) + return ret; + + ret = pkinit_make_dh_key(context, params, group, &ctx->pkey); + if (ret) + return ret; + + /* + * Prior to removing hcrypto and switching to OpenSSL 3.x we had + * this comment: + * + * | The q parameter is required, but MSFT made it optional. + * | It's only required in order to verify the domain parameters + * | -- the security of the DH group --, but we validate groups + * | against known groups rather than accepting arbitrary groups + * | chosen by the peer, so we really don't need to have put it + * | on the wire. Because these are Oakley groups, and the + * | primes are Sophie Germain primes, q is p>>1 and we can + * | compute it on the fly like MIT Kerberos does, but we'd have + * | to implement BN_rshift1(). + * + * We use X9.42 DH (EVP_PKEY_DHX) which produces the + * id-dhpublicnumber OID (1.2.840.10046.2.1) per RFC 3279 as + * referenced by RFC 4556. + * + * The q parameter is optional on the wire -- RFC 4556 requires it + * but Microsoft treats it as optional. We include q when available + * (OpenSSL includes it if provided at key generation time). When + * validating received params we don't care if q is missing because + * we only accept configured groups anyways, so we don't need to + * validate the peer's group. + * + * Note: the old comment about computing q = p>>1 for Sophie + * Germain primes only applies to Oakley Group 2 (RFC 2409). The + * RFC 3526 MODP groups are NOT Sophie Germain primes. + */ + } else { + ret = _krb5_pkinit_make_ecdh_key(context, NULL, NULL, + _krb5_pkinit_pick_curve(context, + ctx), + &ctx->pkey); + if (ret) + return ret; + } + + ALLOC(a->clientPublicValue, 1); + ret = _krb5_pkinit_pkey2SubjectPublicKeyInfo(context, ctx->pkey, + a->clientPublicValue); + if (ret) + return ret; } { @@ -758,6 +1073,8 @@ _krb5_pk_mk_padata(krb5_context context, int win2k, const KDC_REQ_BODY *req_body, unsigned nonce, + krb5_error_code error_code, + TYPED_DATA *td, METHOD_DATA *md) { krb5_pk_init_ctx ctx = c; @@ -1350,16 +1667,17 @@ static krb5_error_code pk_rd_pa_reply_dh(krb5_context context, const heim_octet_string *indata, const heim_oid *dataType, - const char *realm, + const AS_REQ *a, krb5_pk_init_ctx ctx, - krb5_enctype etype, + const AS_REP *kdc_rep, + const PA_PK_AS_REP *pk_rep, const DHNonce *c_n, const DHNonce *k_n, unsigned nonce, + const heim_oid *kdf, PA_DATA *pa, krb5_keyblock **key) { - const unsigned char *p; unsigned char *dh_gen_key = NULL; struct krb5_pk_cert *host = NULL; BIGNUM *kdc_dh_pubkey = NULL; @@ -1370,6 +1688,13 @@ pk_rd_pa_reply_dh(krb5_context context, int dh_gen_keylen = 0; size_t size; + if (ctx->want_kdf_alg && kdf && + der_heim_oid_cmp(ctx->want_kdf_alg, kdf) != 0) { + krb5_set_error_message(context, ENOTSUP, + "PKINIT: The KDC chose a PKINIT KDF other than the one requested by the user"); + return ENOTSUP; + } + krb5_data_zero(&content); memset(&kdc_dh_info, 0, sizeof(kdc_dh_info)); @@ -1394,7 +1719,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, ctx, host); + ret = pk_verify_host(context, a->req_body.realm, ctx, host); if (ret) goto out; @@ -1454,56 +1779,13 @@ pk_rd_pa_reply_dh(krb5_context context, } - p = kdc_dh_info.subjectPublicKey.data; - size = (kdc_dh_info.subjectPublicKey.length + 7) / 8; - - if (ctx->keyex == USE_DH) { - DHPublicKey k; - ret = decode_DHPublicKey(p, size, &k, NULL); - if (ret) { - krb5_set_error_message(context, ret, - N_("pkinit: can't decode " - "without key expiration", "")); - goto out; - } - - kdc_dh_pubkey = integer_to_BN(context, "DHPublicKey", &k); - free_DHPublicKey(&k); - if (kdc_dh_pubkey == NULL) { - ret = ENOMEM; - goto out; - } - - - size = DH_size(ctx->u.dh); - - dh_gen_key = malloc(size); - if (dh_gen_key == NULL) { - ret = krb5_enomem(context); - goto out; - } - - dh_gen_keylen = DH_compute_key(dh_gen_key, kdc_dh_pubkey, ctx->u.dh); - if (dh_gen_keylen == -1) { - ret = KRB5KRB_ERR_GENERIC; - dh_gen_keylen = 0; - krb5_set_error_message(context, ret, - N_("PKINIT: Can't compute Diffie-Hellman key", "")); - goto out; - } - if (dh_gen_keylen < (int)size) { - size -= dh_gen_keylen; - memmove(dh_gen_key + size, dh_gen_key, dh_gen_keylen); - memset(dh_gen_key, 0, size); - } - - } else { - ret = _krb5_pk_rd_pa_reply_ecdh_compute_key(context, ctx, p, - size, &dh_gen_key, - &dh_gen_keylen); - if (ret) - goto out; - } + /* Almost exactly the same with OpenSSL 3.x APIs for DH and ECDH */ + ret = _krb5_pk_rd_pa_reply_ossl_compute_key(context, ctx, + kdc_dh_info.subjectPublicKey, + &dh_gen_key, + &dh_gen_keylen); + if (ret) + goto out; if (dh_gen_keylen <= 0) { ret = EINVAL; @@ -1519,11 +1801,8 @@ pk_rd_pa_reply_dh(krb5_context context, goto out; } - ret = _krb5_pk_octetstring2key(context, - etype, - dh_gen_key, dh_gen_keylen, - c_n, k_n, - *key); + ret = _krb5_pk_kdf2(context, a, pk_rep, dh_gen_key, dh_gen_keylen, + kdc_rep->enc_part.etype, c_n, *key); if (ret) { krb5_set_error_message(context, ret, N_("PKINIT: can't create key from DH key", "")); @@ -1551,9 +1830,9 @@ pk_rd_pa_reply_dh(krb5_context context, KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL _krb5_pk_rd_pa_reply(krb5_context context, - const char *realm, void *c, - krb5_enctype etype, + const AS_REQ *a, + const AS_REP *kdc_rep, unsigned nonce, const krb5_data *req_buffer, PA_DATA *pa, @@ -1644,14 +1923,18 @@ _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, + ret = pk_rd_pa_reply_dh(context, &data, &oid, a, ctx, kdc_rep, &rep, ctx->clientDHNonce, rep.u.dhInfo.serverDHNonce, - nonce, pa, key); + nonce, + rep.u.dhInfo.kdf ? &rep.u.dhInfo.kdf->kdf_id : NULL, + pa, key); break; case choice_PA_PK_AS_REP_encKeyPack: - ret = pk_rd_pa_reply_enckey(context, PKINIT_27, &data, &oid, realm, - ctx, etype, nonce, req_buffer, pa, key); + ret = pk_rd_pa_reply_enckey(context, PKINIT_27, &data, &oid, + a->req_body.realm, ctx, + kdc_rep->enc_part.etype, nonce, req_buffer, + pa, key); break; default: krb5_abortx(context, "pk-init as-rep case not possible to happen"); @@ -1702,8 +1985,10 @@ _krb5_pk_rd_pa_reply(krb5_context context, return ret; } - ret = pk_rd_pa_reply_enckey(context, PKINIT_WIN2K, &data, &oid, realm, - ctx, etype, nonce, req_buffer, pa, key); + ret = pk_rd_pa_reply_enckey(context, PKINIT_WIN2K, &data, &oid, + a->req_body.realm, ctx, + kdc_rep->enc_part.etype, nonce, req_buffer, + pa, key); der_free_octet_string(&data); der_free_oid(&oid); @@ -1797,6 +2082,16 @@ _krb5_pk_set_user_id(krb5_context context, hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY); hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE); + if (ctx->want_sig_alg) { + ret = hx509_query_match_key_algorithm(q, ctx->want_sig_alg); + if (ret) { + pk_copy_error(context, context->hx509ctx, ret, + "Failed setting key algorithm query"); + hx509_query_free(context->hx509ctx, q); + return ret; + } + } + if (principal && strncmp("LKDC:SHA1.", krb5_principal_get_realm(context, principal), 9) == 0) { ctx->id->flags |= PKINIT_BTMM; } @@ -2278,11 +2573,22 @@ _krb5_dh_group_ok(krb5_context context, unsigned long bits, struct krb5_dh_moduli **moduli, char **name) { + unsigned long dh_min_bits = krb5_config_get_int_default(context, NULL, 0, + "libdefaults", + "pkinit_dh_min_bits", + NULL); int i; if (name) *name = NULL; + if (dh_min_bits > 0 && bits < dh_min_bits) { + krb5_set_error_message(context, + KRB5_KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED, + N_("PKINIT: DH group parameter not ok (group too small)", "")); + return KRB5_KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED; + } + for (i = 0; moduli[i] != NULL; i++) { if (der_heim_integer_cmp(&moduli[i]->g, g) == 0 && der_heim_integer_cmp(&moduli[i]->p, p) == 0 && @@ -2308,12 +2614,10 @@ _krb5_dh_group_ok(krb5_context context, unsigned long bits, N_("PKINIT: DH group parameter not ok", "")); return KRB5_KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED; } -#endif /* PKINIT */ KRB5_LIB_FUNCTION void KRB5_LIB_CALL _krb5_get_init_creds_opt_free_pkinit(krb5_get_init_creds_opt *opt) { -#ifdef PKINIT krb5_pk_init_ctx ctx; if (opt->opt_private == NULL || opt->opt_private->pk_init_ctx == NULL) @@ -2321,15 +2625,11 @@ _krb5_get_init_creds_opt_free_pkinit(krb5_get_init_creds_opt *opt) ctx = opt->opt_private->pk_init_ctx; switch (ctx->keyex) { case USE_DH: - if (ctx->u.dh) - DH_free(ctx->u.dh); + case USE_ECDH: + EVP_PKEY_free(ctx->pkey); break; case USE_RSA: break; - case USE_ECDH: - if (ctx->u.eckey) - _krb5_pk_eckey_free(ctx->u.eckey); - break; } if (ctx->id) { hx509_verify_destroy_ctx(ctx->id->verify_ctx); @@ -2349,7 +2649,81 @@ _krb5_get_init_creds_opt_free_pkinit(krb5_get_init_creds_opt *opt) } free(opt->opt_private->pk_init_ctx); opt->opt_private->pk_init_ctx = NULL; -#endif +} + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_get_init_creds_opt_set_pkinit_allowed_algs(krb5_context context, + krb5_get_init_creds_opt *opt, + const char *dh_alg, + const char *sig_alg, + const char *kdf_alg) +{ + const heim_oid *oid = NULL; + + if (sig_alg) { + /* + * Signature algorithm preferences select certificates by public key + * algorithm OID. + */ + if (strcasecmp(sig_alg, "ed25519") == 0) + oid = ASN1_OID_ID_ED25519; + else if (strcasecmp(sig_alg, "ed448") == 0) + oid = ASN1_OID_ID_ED448; + else if (strcasecmp(sig_alg, "rsa") == 0 || + strcasecmp(sig_alg, "rsa-sha256") == 0) + oid = &asn1_oid_id_pkcs1_rsaEncryption; + else if ((oid = _krb5_ec_nidname2heim_oid(sig_alg)) == NULL) { + krb5_set_error_message(context, KRB5_KDC_ERR_INVALID_HASH_ALG, + "PKINIT: Signature/key algorithm %s unknown", + sig_alg); + return KRB5_KDC_ERR_INVALID_HASH_ALG; + } + opt->opt_private->pk_init_ctx->want_sig_alg = oid; + } + + if (dh_alg) { + if ((oid = _krb5_ec_nidname2heim_oid(dh_alg))) { + opt->opt_private->pk_init_ctx->keyex = USE_ECDH; + } else if (strncmp(dh_alg, "modp", sizeof("modp") - 1) == 0) { + oid = &asn1_oid_id_dhpublicnumber; + opt->opt_private->pk_init_ctx->keyex = USE_DH; + } + if (oid == NULL) { + krb5_set_error_message(context, KRB5_KDC_ERR_INVALID_HASH_ALG, + "PKINIT: Key agreement algorithm %s unknown", + dh_alg); + return KRB5_KDC_ERR_INVALID_HASH_ALG; + } + opt->opt_private->pk_init_ctx->want_dh_alg = oid; + } + + if (kdf_alg) { + if (strcmp(kdf_alg, "ah-sha1") == 0) + oid = &asn1_oid_id_pkinit_kdf_ah_sha1; + else if (strcmp(kdf_alg, "ah-sha256") == 0) + oid = &asn1_oid_id_pkinit_kdf_ah_sha256; + else if (strcmp(kdf_alg, "ah-sha384") == 0) + oid = &asn1_oid_id_pkinit_kdf_ah_sha384; + else if (strcmp(kdf_alg, "ah-sha512") == 0) + oid = &asn1_oid_id_pkinit_kdf_ah_sha512; + else if (strcmp(kdf_alg, "RFC4556") == 0) + /* + * asn1_oid_id_pkinit_kdf is not a thing, but we'll use it + * internally to mean "use only the RFC4556 KDF", and that we want + * only for testing purposes (to test interop with older Heimdal + * and MIT Kerberos KDCs). + */ + oid = &asn1_oid_id_pkinit_kdf; + if (oid == NULL) { + krb5_set_error_message(context, KRB5_KDC_ERR_INVALID_HASH_ALG, + "PKINIT: Key derivation function algorithm %s unknown", + kdf_alg); + return KRB5_KDC_ERR_INVALID_HASH_ALG; + } + opt->opt_private->pk_init_ctx->want_kdf_alg = oid; + } + + return 0; } KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL @@ -2365,7 +2739,6 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context, void *prompter_data, char *password) { -#ifdef PKINIT krb5_error_code ret; char **freeme1 = NULL; char **freeme2 = NULL; @@ -2378,9 +2751,9 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context, } opt->opt_private->pk_init_ctx = - calloc(1, sizeof(*opt->opt_private->pk_init_ctx)); + calloc(1, sizeof(*opt->opt_private->pk_init_ctx)); if (opt->opt_private->pk_init_ctx == NULL) - return krb5_enomem(context); + return krb5_enomem(context); opt->opt_private->pk_init_ctx->require_binding = 0; opt->opt_private->pk_init_ctx->require_eku = 1; opt->opt_private->pk_init_ctx->require_krbtgt_otherName = 1; @@ -2451,26 +2824,11 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context, opt->opt_private->pk_init_ctx->id->cert = NULL; if ((flags & KRB5_GIC_OPT_PKINIT_USE_ENCKEY) == 0) { - hx509_context hx509ctx = context->hx509ctx; - hx509_cert cert = opt->opt_private->pk_init_ctx->id->cert; - - opt->opt_private->pk_init_ctx->keyex = USE_DH; - - /* - * If its a ECDSA certs, lets select ECDSA as the keyex algorithm. - */ - if (cert) { - AlgorithmIdentifier alg; - - ret = hx509_cert_get_SPKI_AlgorithmIdentifier(hx509ctx, cert, &alg); - if (ret == 0) { - if (der_heim_oid_cmp(&alg.algorithm, &asn1_oid_id_ecPublicKey) == 0) - opt->opt_private->pk_init_ctx->keyex = USE_ECDH; - free_AlgorithmIdentifier(&alg); - } - } - + /* Use key agreement (modp DH) or ECDH (including X curves) */ + opt->opt_private->pk_init_ctx->keyex = + select_dh_type(context, opt->opt_private->pk_init_ctx); } else { + /* Use RSA key transport */ opt->opt_private->pk_init_ctx->keyex = USE_RSA; if (opt->opt_private->pk_init_ctx->id->certs == NULL) { @@ -2481,11 +2839,6 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context, } return 0; -#else - krb5_set_error_message(context, EINVAL, - N_("no support for PKINIT compiled in", "")); - return EINVAL; -#endif } krb5_error_code KRB5_LIB_FUNCTION @@ -2493,7 +2846,6 @@ krb5_get_init_creds_opt_set_pkinit_user_certs(krb5_context context, krb5_get_init_creds_opt *opt, struct hx509_certs_data *certs) { -#ifdef PKINIT if (opt->opt_private == NULL) { krb5_set_error_message(context, EINVAL, N_("PKINIT: on non extendable opt", "")); @@ -2506,15 +2858,8 @@ krb5_get_init_creds_opt_set_pkinit_user_certs(krb5_context context, } return _krb5_pk_set_user_id(context, NULL, opt->opt_private->pk_init_ctx, certs); -#else - krb5_set_error_message(context, EINVAL, - N_("no support for PKINIT compiled in", "")); - return EINVAL; -#endif } -#ifdef PKINIT - static int get_ms_san(hx509_context context, hx509_cert cert, char **upn) { @@ -2552,10 +2897,6 @@ find_ms_san(hx509_context context, hx509_cert cert, void *ctx) return ret; } - - -#endif - /* * Private since it need to be redesigned using krb5_get_init_creds() */ @@ -2567,7 +2908,6 @@ krb5_pk_enterprise_cert(krb5_context context, krb5_principal *principal, struct hx509_certs_data **res) { -#ifdef PKINIT krb5_error_code ret; hx509_certs certs, result; hx509_cert cert = NULL; @@ -2649,11 +2989,6 @@ krb5_pk_enterprise_cert(krb5_context context, hx509_cert_free(cert); return ret; -#else - krb5_set_error_message(context, EINVAL, - N_("no support for PKINIT compiled in", "")); - return EINVAL; -#endif } KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL diff --git a/lib/krb5/prompter_posix.c b/lib/krb5/prompter_posix.c index 1bf748c51..925518957 100644 --- a/lib/krb5/prompter_posix.c +++ b/lib/krb5/prompter_posix.c @@ -51,10 +51,10 @@ krb5_prompter_posix (krb5_context context, fflush(stderr); for (i = 0; i < num_prompts; ++i) { if (prompts[i].hidden) { - if(UI_UTIL_read_pw_string(prompts[i].reply->data, - prompts[i].reply->length, - prompts[i].prompt, - 0)) + if (_krb5_UI_UTIL_read_pw_string(prompts[i].reply->data, + prompts[i].reply->length, + prompts[i].prompt, + 0)) return 1; } else { char *s = prompts[i].reply->data; diff --git a/lib/krb5/salt.c b/lib/krb5/salt.c index fa926f3d6..e2ebfc182 100644 --- a/lib/krb5/salt.c +++ b/lib/krb5/salt.c @@ -309,54 +309,8 @@ krb5_string_to_key_derived(krb5_context context, krb5_enctype etype, krb5_keyblock *key) { - struct _krb5_encryption_type *et = _krb5_find_enctype(etype); - krb5_error_code ret; - struct _krb5_key_data kd; - size_t keylen; - u_char *tmp; - - if(et == NULL) { - krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP, - N_("encryption type %d not supported", ""), - etype); - return KRB5_PROG_ETYPE_NOSUPP; - } - keylen = et->keytype->bits / 8; - - ALLOC(kd.key, 1); - if (kd.key == NULL) - return krb5_enomem(context); - ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size); - if(ret) { - free(kd.key); - return ret; - } - kd.key->keytype = etype; - tmp = malloc (keylen); - if(tmp == NULL) { - krb5_free_keyblock(context, kd.key); - return krb5_enomem(context); - } - ret = _krb5_n_fold(str, len, tmp, keylen); - if (ret) { - free(tmp); - krb5_enomem(context); - return ret; - } - kd.schedule = NULL; - _krb5_DES3_random_to_key(context, kd.key, tmp, keylen); - memset(tmp, 0, keylen); - free(tmp); - ret = _krb5_derive_key(context, - et, - &kd, - "kerberos", /* XXX well known constant */ - strlen("kerberos")); - if (ret) { - _krb5_free_key_data(context, &kd, et); - return ret; - } - ret = krb5_copy_keyblock_contents(context, kd.key, key); - _krb5_free_key_data(context, &kd, et); - return ret; + krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP, + N_("encryption type %d not supported", ""), + etype); + return KRB5_PROG_ETYPE_NOSUPP; } diff --git a/lib/krb5/sp800-108-kdf.c b/lib/krb5/sp800-108-kdf.c index 4a12067c6..04cfb34b8 100755 --- a/lib/krb5/sp800-108-kdf.c +++ b/lib/krb5/sp800-108-kdf.c @@ -56,16 +56,23 @@ _krb5_SP800_108_HMAC_KDF(krb5_context context, const EVP_MD *md, krb5_data *kdf_K0) { - HMAC_CTX c; + EVP_MAC *mac = NULL; + EVP_MAC_CTX *ctx = NULL; + const char *mdname = EVP_MD_get0_name(md); + OSSL_PARAM params[] = { + OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, (char *)mdname, 0), + OSSL_PARAM_END + }; unsigned char *p = kdf_K0->data; size_t i, n, left = kdf_K0->length; + size_t h = EVP_MD_size(md); unsigned char hmac[EVP_MAX_MD_SIZE]; - unsigned int h = EVP_MD_size(md); const size_t L = kdf_K0->length; heim_assert(md != NULL, "SP800-108 KDF internal error"); - HMAC_CTX_init(&c); + mac = EVP_MAC_fetch(context->ossl->libctx, "HMAC", context->ossl->propq); + ctx = EVP_MAC_CTX_new(mac); n = L / h; @@ -73,28 +80,29 @@ _krb5_SP800_108_HMAC_KDF(krb5_context context, unsigned char tmp[4]; size_t len; - if (HMAC_Init_ex(&c, kdf_K1->data, kdf_K1->length, md, NULL) == 0) { - HMAC_CTX_cleanup(&c); + if (EVP_MAC_init(ctx, kdf_K1->data, kdf_K1->length, params) != 1) { + EVP_MAC_CTX_free(ctx); + EVP_MAC_free(mac); return krb5_enomem(context); } _krb5_put_int(tmp, i + 1, 4); - HMAC_Update(&c, tmp, 4); - HMAC_Update(&c, kdf_label->data, kdf_label->length); - HMAC_Update(&c, (unsigned char *)"", 1); + EVP_MAC_update(ctx, tmp, 4); + EVP_MAC_update(ctx, kdf_label->data, kdf_label->length); + EVP_MAC_update(ctx, (unsigned char *)"", 1); if (kdf_context) - HMAC_Update(&c, kdf_context->data, kdf_context->length); + EVP_MAC_update(ctx, kdf_context->data, kdf_context->length); _krb5_put_int(tmp, L * 8, 4); - HMAC_Update(&c, tmp, 4); + EVP_MAC_update(ctx, tmp, 4); - HMAC_Final(&c, hmac, &h); + EVP_MAC_final(ctx, hmac, &h, sizeof(hmac)); len = h > left ? left : h; memcpy(p, hmac, len); p += len; left -= len; } - HMAC_CTX_cleanup(&c); - + EVP_MAC_CTX_free(ctx); + EVP_MAC_free(mac); return 0; } diff --git a/lib/krb5/string-to-key-test.c b/lib/krb5/string-to-key-test.c index 898857591..302d9dea1 100644 --- a/lib/krb5/string-to-key-test.c +++ b/lib/krb5/string-to-key-test.c @@ -41,7 +41,7 @@ static struct testcase { krb5_enctype enctype; unsigned char res[MAXSIZE]; } tests[] = { -#ifdef HEIM_WEAK_CRYPTO +#if 0 // ifdef HEIM_WEAK_CRYPTO {"@", "", ETYPE_DES_CBC_MD5, {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xf1}}, {"nisse@FOO.SE", "hej", ETYPE_DES_CBC_MD5, @@ -67,6 +67,7 @@ static struct testcase { 0x73, 0x62, 0x64, 0x73, 0x4f, 0x6e, 0x73, 0xce, 0xa2, 0x2f, 0x9b, 0x52, 0x57}}, #endif +#if 0 {"nisse@FOO.SE", "hej", ETYPE_DES3_CBC_SHA1, {0x0e, 0xbc, 0x23, 0x9d, 0x68, 0x46, 0xf2, 0xd5, 0x51, 0x98, 0x5b, 0x57, 0xc1, 0x57, 0x01, 0x79, 0x04, 0xc4, 0xe9, 0xfe, 0xc1, 0x0e, @@ -75,9 +76,6 @@ static struct testcase { {0x7f, 0x40, 0x67, 0xb9, 0xbc, 0xc4, 0x40, 0xfb, 0x43, 0x73, 0xd9, 0xd3, 0xcd, 0x7c, 0xc7, 0x67, 0xe6, 0x79, 0x94, 0xd0, 0xa8, 0x34, 0xdf, 0x62}}, - {"does/not@MATTER", "foo", ETYPE_ARCFOUR_HMAC_MD5, - {0xac, 0x8e, 0x65, 0x7f, 0x83, 0xdf, 0x82, 0xbe, - 0xea, 0x5d, 0x43, 0xbd, 0xaf, 0x78, 0x00, 0xcc}}, {"raeburn@ATHENA.MIT.EDU", "password", ETYPE_DES3_CBC_SHA1, {0x85, 0x0b, 0xb5, 0x13, 0x58, 0x54, 0x8c, 0xd0, 0x5e, 0x86, 0x76, 0x8c, 0x31, 0x3e, 0x3b, 0xfe, 0xf7, 0x51, 0x19, 0x37, 0xdc, 0xf7, 0x2c, 0x3e}}, {"danny@WHITEHOUSE.GOV", "potatoe", ETYPE_DES3_CBC_SHA1, @@ -86,6 +84,10 @@ static struct testcase { {0x6d, 0x2f, 0xcd, 0xf2, 0xd6, 0xfb, 0xbc, 0x3d, 0xdc, 0xad, 0xb5, 0xda, 0x57, 0x10, 0xa2, 0x34, 0x89, 0xb0, 0xd3, 0xb6, 0x9d, 0x5d, 0x9d, 0x4a}}, {"Juri\xc5\xa1i\xc4\x87@ATHENA.MIT.EDU", "\xc3\x9f", ETYPE_DES3_CBC_SHA1, {0x16, 0xd5, 0xa4, 0x0e, 0x1c, 0xe3, 0xba, 0xcb, 0x61, 0xb9, 0xdc, 0xe0, 0x04, 0x70, 0x32, 0x4c, 0x83, 0x19, 0x73, 0xa7, 0xb9, 0x52, 0xfe, 0xb0}}, +#endif + {"does/not@MATTER", "foo", ETYPE_ARCFOUR_HMAC_MD5, + {0xac, 0x8e, 0x65, 0x7f, 0x83, 0xdf, 0x82, 0xbe, + 0xea, 0x5d, 0x43, 0xbd, 0xaf, 0x78, 0x00, 0xcc}}, {NULL, NULL, 0, {0}} }; diff --git a/lib/krb5/test_crypto_wrapping.c b/lib/krb5/test_crypto_wrapping.c index aff4e8d50..dcaf4f66f 100644 --- a/lib/krb5/test_crypto_wrapping.c +++ b/lib/krb5/test_crypto_wrapping.c @@ -123,12 +123,14 @@ main(int argc, char **argv) int i, optidx = 0; krb5_enctype enctypes[] = { -#ifdef HEIM_WEAK_CRYPTO +#if 0 // ifdef HEIM_WEAK_CRYPTO ETYPE_DES_CBC_CRC, ETYPE_DES_CBC_MD4, ETYPE_DES_CBC_MD5, #endif +#if 0 ETYPE_DES3_CBC_SHA1, +#endif ETYPE_ARCFOUR_HMAC_MD5, ETYPE_AES128_CTS_HMAC_SHA1_96, ETYPE_AES256_CTS_HMAC_SHA1_96, diff --git a/lib/krb5/test_fx.c b/lib/krb5/test_fx.c index 68f00dc63..fb55e0de4 100644 --- a/lib/krb5/test_fx.c +++ b/lib/krb5/test_fx.c @@ -90,6 +90,7 @@ struct { "\x24\xd7\xf6\xb6\xba\xe4\xe5\xc0\x0d\x20\x82\xc5\xeb\xab\x36\x72", 16 }, +#if 0 /* We don't yet have a PRF for 1DES in Heimdal */ { "key1", "a", ETYPE_DES_CBC_CRC, @@ -106,6 +107,7 @@ struct { "\xf7\x3e\x62\x83\x4f\xe5\x4a\x01", 24 }, +#endif }; diff --git a/lib/krb5/test_pknistkdf.c b/lib/krb5/test_pknistkdf.c index f97dddf38..52bc03171 100644 --- a/lib/krb5/test_pknistkdf.c +++ b/lib/krb5/test_pknistkdf.c @@ -46,7 +46,6 @@ struct testcase { krb5_enctype enctype; krb5_data as_req; krb5_data pk_as_rep; - krb5_data ticket; krb5_data key; } tests[] = { @@ -83,17 +82,10 @@ struct testcase { 9, "\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB" }, - { /* ticket */ - 55, - "\x61\x35\x30\x33\xa0\x03\x02\x01\x05\xa1\x07\x1b\x05\x53\x55\x2e" - "\x53\x45\xa2\x10\x30\x0e\xa0\x03\x02\x01\x01\xa1\x07\x30\x05\x1b" - "\x03\x6c\x68\x61\xa3\x11\x30\x0f\xa0\x03\x02\x01\x12\xa2\x08\x04" - "\x06\x68\x65\x6a\x68\x65\x6a" - }, { /* key */ 32, - "\xc7\x62\x89\xec\x4b\x28\xa6\x91\xff\xce\x80\xbb\xb7\xec\x82\x41" - "\x52\x3f\x99\xb1\x90\xcf\x2d\x34\x8f\x54\xa8\x65\x81\x2c\x32\x73" + "\xe6\xab\x38\xc9\x41\x3e\x03\x5b\xb0\x79\x20\x1e\xd0\xb6\xb7\x3d" + "\x8d\x49\xa8\x14\xa7\x37\xc0\x4e\xe6\x64\x96\x14\x20\x6f\x73\xad" } }, /* 1 */ @@ -129,20 +121,52 @@ struct testcase { 9, "\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB" }, - { /* ticket */ - 55, - "\x61\x35\x30\x33\xa0\x03\x02\x01\x05\xa1\x07\x1b\x05\x53\x55\x2e" - "\x53\x45\xa2\x10\x30\x0e\xa0\x03\x02\x01\x01\xa1\x07\x30\x05\x1b" - "\x03\x6c\x68\x61\xa3\x11\x30\x0f\xa0\x03\x02\x01\x12\xa2\x08\x04" - "\x06\x68\x65\x6a\x68\x65\x6a" - }, { /* key */ 32, - "\x59\xf3\xca\x77\x5b\x20\x17\xe9\xad\x36\x3f\x47\xca\xbd\x43\xb8" - "\x8c\xb8\x90\x35\x8d\xc6\x0d\x52\x0d\x11\x9f\xb0\xdc\x24\x0b\x61" + "\x77\xef\x4e\x48\xc4\x20\xae\x3f\xec\x75\x10\x9d\x79\x81\x69\x7e" + "\xed\x5d\x29\x5c\x90\xc6\x25\x64\xf7\xbf\xd1\x01\xfa\x9B\xc1\xd5" } }, /* 2 */ + { + NULL, /* AlgorithmIdentifier */ + { /* Z */ + 256, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + }, + "lha@SU.SE", /* client, partyUInfo */ + "krbtgt/SU.SE@SU.SE", /* server, partyVInfo */ + KRB5_ENCTYPE_DES3_CBC_SHA1, /* enctype */ + { /* as_req */ + 10, + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + }, + { /* pk_as_rep */ + 9, + "\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB" + }, + { /* key */ + 21, + "\xd3\xc7\x8b\x78\xd7\x53\x13\xe9\xa9\x26\xf7\x5d\xfb\x01\x23\x63" + "\xfa\x17\xfa\x01\xdb" + } + }, + /* 3 */ { NULL, /* AlgorithmIdentifier */ { /* Z */ @@ -175,17 +199,10 @@ struct testcase { 9, "\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB" }, - { /* ticket */ - 55, - "\x61\x35\x30\x33\xa0\x03\x02\x01\x05\xa1\x07\x1b\x05\x53\x55\x2e" - "\x53\x45\xa2\x10\x30\x0e\xa0\x03\x02\x01\x01\xa1\x07\x30\x05\x1b" - "\x03\x6c\x68\x61\xa3\x11\x30\x0f\xa0\x03\x02\x01\x12\xa2\x08\x04" - "\x06\x68\x65\x6a\x68\x65\x6a" - }, { /* key */ 32, - "\x8a\x9a\xc5\x5f\x45\xda\x1a\x73\xd9\x1e\xe9\x88\x1f\xa9\x48\x81" - "\xce\xac\x66\x2d\xb1\xd3\xb9\x0a\x9d\x0e\x52\x83\xdf\xe1\x84\x3d" + "\x2d\xa9\x82\x4c\xa4\x29\xcc\xda\xeb\x55\x3a\x09\x72\x73\x46\x73" + "\x0a\x0a\x6c\x6a\x89\xa0\x1b\x3c\x2e\x49\x87\xfc\x70\x80\x0d\xa2" } } }; @@ -223,20 +240,8 @@ static void test_dh2key(krb5_context context, int i, struct testcase *c) { krb5_error_code ret; - krb5_keyblock key; krb5_principal client, server; - Ticket ticket; - AlgorithmIdentifier ai; - size_t size; - - memset(&ticket, 0, sizeof(ticket)); - - ai.algorithm = *c->oid; - ai.parameters = NULL; - - ret = decode_Ticket(c->ticket.data, c->ticket.length, &ticket, &size); - if (ret) - krb5_errx(context, 1, "decode ticket: %d", ret); + krb5_data key; ret = krb5_parse_name(context, c->client, &client); if (ret) @@ -267,22 +272,20 @@ test_dh2key(krb5_context context, int i, struct testcase *c) hex_encode(c->pk_as_rep.data, c->pk_as_rep.length, &str); printf("pk-as-rep: %s\n", str); free(str); - hex_encode(c->ticket.data, c->ticket.length, &str); - printf("ticket: %s\n", str); free(str); } ret = _krb5_pk_kdf(context, - &ai, + c->oid, c->Z.data, c->Z.length, client, server, c->enctype, + NULL, NULL, /* We lack test vectors for RFC 4556 */ &c->as_req, &c->pk_as_rep, - &ticket, - &key); + &key, NULL); krb5_free_principal(context, client); krb5_free_principal(context, server); if (ret) @@ -290,17 +293,16 @@ test_dh2key(krb5_context context, int i, struct testcase *c) if (verbose_flag) { char *str; - hex_encode(key.keyvalue.data, key.keyvalue.length, &str); + hex_encode(key.data, key.length, &str); printf("key: %s\n", str); free(str); } - if (key.keyvalue.length != c->key.length || - memcmp(key.keyvalue.data, c->key.data, c->key.length) != 0) + if (key.length != c->key.length || + memcmp(key.data, c->key.data, c->key.length) != 0) krb5_errx(context, 1, "resulting key wrong: %d", i); - krb5_free_keyblock_contents(context, &key); - free_Ticket(&ticket); + krb5_data_free(&key); } @@ -363,6 +365,7 @@ main(int argc, char **argv) tests[0].oid = &asn1_oid_id_pkinit_kdf_ah_sha1; tests[1].oid = &asn1_oid_id_pkinit_kdf_ah_sha256; tests[2].oid = &asn1_oid_id_pkinit_kdf_ah_sha512; + tests[3].oid = &asn1_oid_id_pkinit_kdf_ah_sha384; for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) test_dh2key(context, i, &tests[i]); diff --git a/lib/krb5/version-script.map b/lib/krb5/version-script.map index 9e910b659..75cf58a5b 100644 --- a/lib/krb5/version-script.map +++ b/lib/krb5/version-script.map @@ -204,6 +204,8 @@ HEIMDAL_KRB5_2.0 { krb5_data_realloc; krb5_data_zero; krb5_debug; + _krb5_debug; + _krb5_debug_openssl; krb5_decode_Authenticator; krb5_decode_ETYPE_INFO2; krb5_decode_ETYPE_INFO; @@ -218,36 +220,6 @@ HEIMDAL_KRB5_2.0 { krb5_decrypt_ivec; krb5_decrypt_ticket; krb5_derive_key; - krb5_digest_alloc; - krb5_digest_free; - krb5_digest_get_client_binding; - krb5_digest_get_identifier; - krb5_digest_get_opaque; - krb5_digest_get_rsp; - krb5_digest_get_server_nonce; - krb5_digest_get_session_key; - krb5_digest_get_tickets; - krb5_digest_init_request; - krb5_digest_probe; - krb5_digest_rep_get_status; - krb5_digest_request; - krb5_digest_set_authentication_user; - krb5_digest_set_authid; - krb5_digest_set_client_nonce; - krb5_digest_set_digest; - krb5_digest_set_hostname; - krb5_digest_set_identifier; - krb5_digest_set_method; - krb5_digest_set_nonceCount; - krb5_digest_set_opaque; - krb5_digest_set_qop; - krb5_digest_set_realm; - krb5_digest_set_responseData; - krb5_digest_set_server_cb; - krb5_digest_set_server_nonce; - krb5_digest_set_type; - krb5_digest_set_uri; - krb5_digest_set_username; krb5_domain_x500_decode; krb5_domain_x500_encode; krb5_eai_to_heim_errno; @@ -361,6 +333,7 @@ HEIMDAL_KRB5_2.0 { krb5_get_init_creds_opt_set_pa_password; krb5_get_init_creds_opt_set_pac_request; krb5_get_init_creds_opt_set_pkinit; + krb5_get_init_creds_opt_set_pkinit_allowed_algs; krb5_get_init_creds_opt_set_preauth_list; krb5_get_init_creds_opt_set_process_last_req; krb5_get_init_creds_opt_set_proxiable; @@ -595,6 +568,7 @@ HEIMDAL_KRB5_2.0 { krb5_set_dns_canonicalize_hostname; krb5_set_error_message; krb5_set_error_string; + _krb5_set_error_message_openssl; krb5_set_extra_addresses; krb5_set_fcache_version; krb5_set_home_dir_access; @@ -602,6 +576,7 @@ HEIMDAL_KRB5_2.0 { krb5_set_kdc_sec_offset; krb5_set_log_dest; krb5_set_max_time_skew; + krb5_set_ossl_cnf_propq; krb5_set_password; krb5_set_password_using_ccache; krb5_set_real_time; @@ -861,6 +836,12 @@ HEIMDAL_KRB5_2.0 { _krb5_find_capath; _krb5_free_capath; + # Other + _krb5_UI_UTIL_read_pw_string; + _krb5_hmac_start_ossl; + _krb5_openssl_errors; + _krb5_hmac_ossl; + local: *; }; diff --git a/lib/ntlm/ChangeLog b/lib/ntlm/ChangeLog deleted file mode 100644 index b2e151ac4..000000000 --- a/lib/ntlm/ChangeLog +++ /dev/null @@ -1,120 +0,0 @@ -2008-05-14 Love Hornquist Astrand - - * ntlm.c: replace hashes with keys. - -2008-04-27 Love Hörnquist Åstrand - - * ntlm.c: Use DES_set_key_unchecked(). - -2007-12-28 Love Hörnquist Åstrand - - * heimntlm.h: Add NTLM_TARGET_* - - * ntlm.c: Make heim_ntlm_decode_type3 more useful and provide a - username. From Ming Yang. - -2007-11-11 Love Hörnquist Åstrand - - * move doxygen into the main file - - * write doxygen documentation - - * export heim_ntlm_free_buf, start doxygen documentation - -2007-07-17 Love Hörnquist Åstrand - - * ntlm.c: Use unsigned char * as argument to HMAC_Update to please - OpenSSL and gcc. - - * test_ntlm.c: more verbose what we are testing. - -2007-07-10 Love Hörnquist Åstrand - - * Makefile.am: New library version. - -2007-06-20 Love Hörnquist Åstrand - - * test_ntlm.c: heim_ntlm_calculate_ntlm2_sess_resp - - * ntlm.c: Change prototype to match other heim_ntlm_calculate - functions. - - * test_ntlm.c: Its ok if infotarget2 length is longer. - - * ntlm.c: Merge in changes from Puneet Mehra and make work again. - - * ntlm.c (heim_ntlm_ntlmv2_key): target should be uppercase. - From Puneet Mehra. - - * version-script.map: Add heim_ntlm_calculate_ntlm2_sess_resp from - Puneet Mehra. - - * ntlm.c: Add heim_ntlm_calculate_ntlm2_sess_resp from Puneet - Mehra. - - * test_ntlm.c: Test heim_ntlm_calculate_ntlm2_sess_resp from - Puneet Mehra. - -2007-06-08 Love Hörnquist Åstrand - - * Makefile.am: EXTRA_DIST += version-script.map. - -2007-06-03 Love Hörnquist Åstrand - - * test_ntlm.c: Free memory diffrently. - - * ntlm.c: Make free functions free memory. - -2007-04-22 Love Hörnquist Åstrand - - * Makefile.am: symbol versioning. - - * version-script.map: symbol versioning. - -2007-01-31 Love Hörnquist Åstrand - - * test_ntlm.c: No need to include . - -2007-01-04 Love Hörnquist Åstrand - - * Makefile.am: add LIB_roken for test_ntlm - -2006-12-26 Love Hörnquist Åstrand - - * test_ntlm.c: Verify infotarget. - - * ntlm.c: Extract the infotarget from the answer. - - * ntlm.c (heim_ntlm_verify_ntlm2): verify the ntlmv2 reply - -2006-12-22 Dave Love - - * ntlm.c: Include . - -2006-12-20 Love Hörnquist Åstrand - - * test_ntlm.c: add some new tests. - - * ntlm.c: Add ntlmv2 answer calculating functions. - - * ntlm.c: sent lm hashes, needed for NTLM2 session - - * heimntlm.h: Add NTLM_NEG_NTLM2_SESSION, NTLMv2 session security. - -2006-12-19 Love Hörnquist Åstrand - - * ntlm.c (heim_ntlm_build_ntlm1_master): return session master - key. - -2006-12-18 Love Hörnquist Åstrand - - * ntlm.c (heim_ntlm_build_ntlm1_master): calculate the ntlm - version 1 "master" key. - -2006-12-13 Love Hörnquist Åstrand - - * test_ntlm.c: Add simple parser test app. - - * inital version of a NTLM library, only handles ntml version 1 and - ascii strings for now - diff --git a/lib/ntlm/Makefile.am b/lib/ntlm/Makefile.am deleted file mode 100644 index 6c0e492bd..000000000 --- a/lib/ntlm/Makefile.am +++ /dev/null @@ -1,48 +0,0 @@ -# $Id$ - -include $(top_srcdir)/Makefile.am.common - -lib_LTLIBRARIES = libheimntlm.la - -dist_include_HEADERS = heimntlm.h $(srcdir)/heimntlm-protos.h - -nodist_include_HEADERS = ntlm_err.h - -dist_libheimntlm_la_SOURCES = ntlm.c heimntlm.h - -nodist_libheimntlm_la_SOURCES = ntlm_err.c - -libheimntlm_la_LDFLAGS = -version-info 1:0:1 - -if versionscript -libheimntlm_la_LDFLAGS += $(LDFLAGS_VERSION_SCRIPT)$(srcdir)/version-script.map -endif -$(libheimntlm_la_OBJECTS): $(srcdir)/version-script.map - -libheimntlm_la_LIBADD = \ - ../krb5/libkrb5.la \ - $(top_builddir)/lib/wind/libwind.la \ - $(LIBADD_roken) - -$(srcdir)/heimntlm-protos.h: $(dist_libheimntlm_la_SOURCES) - cd $(srcdir) && perl ../../cf/make-proto.pl -q -P comment -o heimntlm-protos.h $(dist_libheimntlm_la_SOURCES) || rm -f heimntlm-protos.h - -$(libheimntlm_la_OBJECTS): $(srcdir)/heimntlm-protos.h ntlm_err.h - -TESTS = test_ntlm - -check_PROGRAMS = test_ntlm - -LDADD = libheimntlm.la $(LIB_roken) - -EXTRA_DIST = \ - NTMakefile \ - libheimntlm-version.rc \ - libheimntlm-exports.def \ - version-script.map \ - ntlm_err.et - -CLEANFILES = \ - ntlm_err.c ntlm_err.h - -ntlm_err.h: ntlm_err.et diff --git a/lib/ntlm/NTMakefile b/lib/ntlm/NTMakefile deleted file mode 100644 index 527fc8912..000000000 --- a/lib/ntlm/NTMakefile +++ /dev/null @@ -1,90 +0,0 @@ -######################################################################## -# -# Copyright (c) 2009, Secure Endpoints Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# - Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# - Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in -# the documentation and/or other materials provided with the -# distribution. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. -# - -RELDIR=lib\ntlm - -!include ../../windows/NTMakefile.w32 - -INCFILES= \ - $(INCDIR)\heimntlm.h \ - $(INCDIR)\heimntlm-protos.h \ - $(INCDIR)\ntlm_err.h - -libheimntlm_la_SOURCES = ntlm.c heimntlm.h - -$(OBJ)\heimntlm-protos.h: $(libheimntlm_la_SOURCES) - $(PERL) ../../cf/make-proto.pl -q -P remove -o $(OBJ)\heimntlm-protos.h $(libheimntlm_la_SOURCES) - -$(OBJ)\ntlm_err.c $(OBJ)\ntlm_err.h: ntlm_err.et - cd $(OBJ) - $(BINDIR)\compile_et.exe $(SRCDIR)\ntlm_err.et - cd $(SRCDIR) - -!ifndef STATICLIBS - -RES=$(OBJ)\libheimntlm-version.res - -$(LIBHEIMNTLM): $(BINDIR)\heimntlm.dll - -$(BINDIR)\heimntlm.dll: $(OBJ)\ntlm.obj $(OBJ)\ntlm_err.obj $(LIBHEIMDAL) $(LIBROKEN) $(LIBCOMERR) $(RES) - $(DLLGUILINK) -def:libheimntlm-exports.def -implib:$(LIBHEIMNTLM) - $(DLLPREP_NODIST) - -clean:: - -$(RM) $(BINDIR)\heimntlm.* - -!else - -$(LIBHEIMNTLM): $(OBJ)\ntlm.obj $(OBJ)\ntlm_err.obj - $(LIBCON) - -!endif - -all:: $(INCFILES) $(LIBHEIMNTLM) - - -test-binaries: $(OBJ)\test_ntlm.exe - -test-run: - cd $(OBJ) - -test_ntlm.exe - cd $(SRCDIR) - -$(OBJ)\test_ntlm.exe: $(OBJ)\test_ntlm.obj $(LIBHEIMNTLM) $(LIBHEIMDAL) $(LIBVERS) $(LIBROKEN) - $(EXECONLINK) - $(EXEPREP_NODIST) - -test:: test-binaries test-run - -test-exports: - $(PERL) ..\..\cf\w32-check-exported-symbols.pl --vs version-script.map --def libheimntlm-exports.def - -test:: test-exports diff --git a/lib/ntlm/apop.c b/lib/ntlm/apop.c deleted file mode 100644 index b3632394a..000000000 --- a/lib/ntlm/apop.c +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Copyright (c) 2010 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Portions Copyright (c) 2010 Apple Inc. 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 -#include -#include -#include -#include -#include -#include -#include "heim-auth.h" -#include "ntlm_err.h" - -char * -heim_generate_challenge(const char *hostname) -{ - char host[MAXHOSTNAMELEN], *str = NULL; - uint32_t num, t; - - if (hostname == NULL) { - if (gethostname(host, sizeof(host))) - return NULL; - hostname = host; - } - - t = (uint32_t)time(NULL); - num = rk_random(); - - asprintf(&str, "<%lu%lu@%s>", (unsigned long)t, - (unsigned long)num, hostname); - - return str; -} - -char * -heim_apop_create(const char *challenge, const char *password) -{ - char *str = NULL; - uint8_t hash[CC_MD5_DIGEST_LENGTH]; - CC_MD5_CTX ctx; - - CC_MD5_Init(&ctx); - CC_MD5_Update(&ctx, challenge, (CC_LONG)strlen(challenge)); - CC_MD5_Update(&ctx, password, (CC_LONG)strlen(password)); - - CC_MD5_Final(hash, &ctx); - - hex_encode(hash, sizeof(hash), &str); - if (str) - strlwr(str); - - return str; -} - -int -heim_apop_verify(const char *challenge, const char *password, const char *response) -{ - char *str; - int res; - - str = heim_apop_create(challenge, password); - if (str == NULL) - return ENOMEM; - - res = (strcasecmp(str, response) != 0); - free(str); - - if (res) - return HNTLM_ERR_INVALID_APOP; - return 0; -} - -struct heim_cram_md5_data { - CC_MD5_CTX ipad; - CC_MD5_CTX opad; -}; - - -void -heim_cram_md5_export(const char *password, heim_CRAM_MD5_STATE *state) -{ - size_t keylen = strlen(password); - uint8_t key[CC_MD5_BLOCK_BYTES]; - uint8_t pad[CC_MD5_BLOCK_BYTES]; - struct heim_cram_md5_data ctx; - size_t n; - - memset(&ctx, 0, sizeof(ctx)); - - if (keylen > CC_MD5_BLOCK_BYTES) { - CC_MD5(password, (CC_LONG)keylen, key); - keylen = sizeof(keylen); - } else { - memcpy(key, password, keylen); - } - - memset(pad, 0x36, sizeof(pad)); - for (n = 0; n < keylen; n++) - pad[n] ^= key[n]; - - CC_MD5_Init(&ctx.ipad); - CC_MD5_Init(&ctx.opad); - - CC_MD5_Update(&ctx.ipad, pad, sizeof(pad)); - - memset(pad, 0x5c, sizeof(pad)); - for (n = 0; n < keylen; n++) - pad[n] ^= key[n]; - - CC_MD5_Update(&ctx.opad, pad, sizeof(pad)); - - memset(pad, 0, sizeof(pad)); - memset(key, 0, sizeof(key)); - - state->istate[0] = htonl(ctx.ipad.A); - state->istate[1] = htonl(ctx.ipad.B); - state->istate[2] = htonl(ctx.ipad.C); - state->istate[3] = htonl(ctx.ipad.D); - - state->ostate[0] = htonl(ctx.opad.A); - state->ostate[1] = htonl(ctx.opad.B); - state->ostate[2] = htonl(ctx.opad.C); - state->ostate[3] = htonl(ctx.opad.D); - - memset(&ctx, 0, sizeof(ctx)); -} - - -heim_cram_md5 -heim_cram_md5_import(void *data, size_t len) -{ - heim_CRAM_MD5_STATE state; - heim_cram_md5 ctx; - - if (len != sizeof(state)) - return NULL; - - ctx = calloc(1, sizeof(*ctx)); - if (ctx == NULL) - return NULL; - - memcpy(&state, data, sizeof(state)); - - ctx->ipad.A = ntohl(state.istate[0]); - ctx->ipad.B = ntohl(state.istate[1]); - ctx->ipad.C = ntohl(state.istate[2]); - ctx->ipad.D = ntohl(state.istate[3]); - - ctx->opad.A = ntohl(state.ostate[0]); - ctx->opad.B = ntohl(state.ostate[1]); - ctx->opad.C = ntohl(state.ostate[2]); - ctx->opad.D = ntohl(state.ostate[3]); - - ctx->ipad.Nl = ctx->opad.Nl = 512; - ctx->ipad.Nh = ctx->opad.Nh = 0; - ctx->ipad.num = ctx->opad.num = 0; - - return ctx; -} - -int -heim_cram_md5_verify_ctx(heim_cram_md5 ctx, const char *challenge, const char *response) -{ - uint8_t hash[CC_MD5_DIGEST_LENGTH]; - char *str = NULL; - int res; - - CC_MD5_Update(&ctx->ipad, challenge, (CC_LONG)strlen(challenge)); - CC_MD5_Final(hash, &ctx->ipad); - - CC_MD5_Update(&ctx->opad, hash, sizeof(hash)); - CC_MD5_Final(hash, &ctx->opad); - - hex_encode(hash, sizeof(hash), &str); - if (str == NULL) - return ENOMEM; - - res = (strcasecmp(str, response) != 0); - free(str); - - if (res) - return HNTLM_ERR_INVALID_CRAM_MD5; - return 0; -} - -void -heim_cram_md5_free(heim_cram_md5 ctx) -{ - memset(ctx, 0, sizeof(*ctx)); - free(ctx); -} - - -char * -heim_cram_md5_create(const char *challenge, const char *password) -{ - CCHmacContext ctx; - uint8_t hash[CC_MD5_DIGEST_LENGTH]; - char *str = NULL; - - CCHmacInit(&ctx, kCCHmacAlgMD5, password, strlen(password)); - CCHmacUpdate(&ctx, challenge, strlen(challenge)); - CCHmacFinal(&ctx, hash); - - memset(&ctx, 0, sizeof(ctx)); - - hex_encode(hash, sizeof(hash), &str); - if (str) - strlwr(str); - - return str; -} - - int -heim_cram_md5_verify(const char *challenge, const char *password, const char *response) -{ - char *str; - int res; - - str = heim_cram_md5_create(challenge, password); - if (str == NULL) - return ENOMEM; - - res = (strcasecmp(str, response) != 0); - free(str); - - if (res) - return HNTLM_ERR_INVALID_CRAM_MD5; - return 0; -} - diff --git a/lib/ntlm/digest.c b/lib/ntlm/digest.c deleted file mode 100644 index 42c39ff23..000000000 --- a/lib/ntlm/digest.c +++ /dev/null @@ -1,994 +0,0 @@ -/* - * Copyright (c) 2006 - 2008 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Portions Copyright (c) 2010 Apple Inc. 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 -#include -#include -#include -#include -#include -#include -#include -#include "heim-auth.h" -#include "ntlm_err.h" - -struct heim_digest_desc { -#define F_SERVER 1 -#define F_HAVE_HASH 2 -#define F_HAVE_HA1 4 -#define F_USE_PREFIX 8 - int flags; - int type; - char *password; - uint8_t SecretHash[CC_MD5_DIGEST_LENGTH]; - char *serverNonce; - char *serverRealm; - char *serverQOP; - char *serverMethod; - char *serverMaxbuf; - char *serverOpaque; - char *clientUsername; - char *clientResponse; - char *clientURI; - char *clientRealm; - char *clientNonce; - char *clientQOP; - char *clientNC; - char *serverAlgorithm; - char *auth_id; - - /* internally allocated objects returned to caller */ - char *serverChallenge; - char *clientReply; - char *serverReply; -}; - -#define FREE_AND_CLEAR(x) do { if ((x)) { free((x)); (x) = NULL; } } while(0) -#define MEMSET_FREE_AND_CLEAR(x) do { if ((x)) { memset(x, 0, strlen(x)); free((x)); (x) = NULL; } } while(0) - -static const char digest_prefix[] = "Digest "; - -static void -clear_context(heim_digest_t context) -{ - MEMSET_FREE_AND_CLEAR(context->password); - memset(context->SecretHash, 0, sizeof(context->SecretHash)); - context->flags &= ~(F_HAVE_HASH); - FREE_AND_CLEAR(context->serverNonce); - FREE_AND_CLEAR(context->serverRealm); - FREE_AND_CLEAR(context->serverQOP); - FREE_AND_CLEAR(context->serverMethod); - FREE_AND_CLEAR(context->serverMaxbuf); - FREE_AND_CLEAR(context->serverOpaque); - FREE_AND_CLEAR(context->clientUsername); - FREE_AND_CLEAR(context->clientResponse); - FREE_AND_CLEAR(context->clientURI); - FREE_AND_CLEAR(context->clientRealm); - FREE_AND_CLEAR(context->clientNonce); - FREE_AND_CLEAR(context->clientQOP); - FREE_AND_CLEAR(context->clientNC); - FREE_AND_CLEAR(context->serverAlgorithm); - FREE_AND_CLEAR(context->auth_id); - - FREE_AND_CLEAR(context->serverChallenge); - FREE_AND_CLEAR(context->clientReply); - FREE_AND_CLEAR(context->serverReply); -} - -static void -digest_userhash(const char *user, const char *realm, const char *password, - unsigned char md[CC_MD5_DIGEST_LENGTH]) -{ - CC_MD5_CTX ctx; - - CC_MD5_Init(&ctx); - CC_MD5_Update(&ctx, user, (CC_LONG)strlen(user)); - CC_MD5_Update(&ctx, ":", 1); - CC_MD5_Update(&ctx, realm, (CC_LONG)strlen(realm)); - CC_MD5_Update(&ctx, ":", 1); - CC_MD5_Update(&ctx, password, (CC_LONG)strlen(password)); - CC_MD5_Final(md, &ctx); -} - -static char * -build_A1_hash(heim_digest_t context) -{ - unsigned char md[CC_MD5_DIGEST_LENGTH]; - CC_MD5_CTX ctx; - char *A1; - - if (context->flags & F_HAVE_HA1) { - memcpy(md, context->SecretHash, sizeof(md)); - } else if (context->flags & F_HAVE_HASH) { - memcpy(md, context->SecretHash, sizeof(md)); - } else if (context->password) { - if (context->clientUsername == NULL) - return NULL; - if (context->serverRealm == NULL) - return NULL; - digest_userhash(context->clientUsername, - context->serverRealm, - context->password, - md); - } else - return NULL; - - if ((context->type == HEIM_DIGEST_TYPE_RFC2617_MD5_SESS || context->type == HEIM_DIGEST_TYPE_RFC2831) && (context->flags & F_HAVE_HA1) == 0) { - if (context->serverNonce == NULL) - return NULL; - - CC_MD5_Init(&ctx); - CC_MD5_Update(&ctx, md, sizeof(md)); - memset(md, 0, sizeof(md)); - CC_MD5_Update(&ctx, ":", 1); - CC_MD5_Update(&ctx, context->serverNonce, (CC_LONG)strlen(context->serverNonce)); - if (context->clientNonce) { - CC_MD5_Update(&ctx, ":", 1); - CC_MD5_Update(&ctx, context->clientNonce, (CC_LONG)strlen(context->clientNonce)); - } - if (context->type == HEIM_DIGEST_TYPE_RFC2831 && context->auth_id) { - CC_MD5_Update(&ctx, ":", 1); - CC_MD5_Update(&ctx, context->auth_id, (CC_LONG)strlen(context->auth_id)); - } - CC_MD5_Final(md, &ctx); - } - hex_encode(md, sizeof(md), &A1); - if (A1) - strlwr(A1); - - return A1; -} - -static char * -build_A2_hash(heim_digest_t context, const char *method) -{ - unsigned char md[CC_MD5_DIGEST_LENGTH]; - CC_MD5_CTX ctx; - char *A2; - - CC_MD5_Init(&ctx); - if (method) - CC_MD5_Update(&ctx, method, (CC_LONG)strlen(method)); - CC_MD5_Update(&ctx, ":", 1); - CC_MD5_Update(&ctx, context->clientURI, (CC_LONG)strlen(context->clientURI)); - - /* conf|int */ - if (context->type == HEIM_DIGEST_TYPE_RFC2831) { - if (strcasecmp(context->clientQOP, "auth-int") == 0 || strcasecmp(context->clientQOP, "auth-conf") == 0) { - /* XXX if we have a body hash, use that */ - static char conf_zeros[] = ":00000000000000000000000000000000"; - CC_MD5_Update(&ctx, conf_zeros, sizeof(conf_zeros) - 1); - } - } else { - /* support auth-int ? */ - if (context->clientQOP && strcasecmp(context->clientQOP, "auth") != 0) - return NULL; - } - - CC_MD5_Final(md, &ctx); - - hex_encode(md, sizeof(md), &A2); - if (A2) - strlwr(A2); - - return A2; -} - -/* - * - */ - -struct md5_value { - char *mv_name; - char *mv_value; - struct md5_value *mv_next; -}; - -static void -free_values(struct md5_value *val) -{ - struct md5_value *v; - while(val) { - v = val->mv_next; - if (val->mv_name) - free(val->mv_name); - if (val->mv_value) - free(val->mv_value); - free(val); - val = v; - } -} - -/* - * Search for entry, if found, remove entry and return string to be freed. - */ - -static char * -values_find(struct md5_value **val, const char *v) -{ - struct md5_value *cur; - char *str; - - while (*val != NULL) { - if (strcasecmp(v, (*val)->mv_name) == 0) - break; - val = &(*val)->mv_next; - } - if (*val == NULL) - return NULL; - cur = *val; - *val = (*val)->mv_next; - - str = cur->mv_value; - free(cur->mv_name); - free(cur); - - return str; -} - -static int -parse_values(const char *string, struct md5_value **val) -{ - struct md5_value *v; - size_t size; - char *str, *p1, *p2; - size_t sz; - - *val = NULL; - - if ((str = strdup(string)) == NULL) - return ENOMEM; - - size = strlen(str); - - p1 = str; - - while (p1 - str < size) { - sz = strspn(p1, " \t\n\r,"); - if (p1[sz] == '\0') - break; - p1 += sz; - sz = strcspn(p1, " \t\n\r="); - if (sz == 0 || p1[sz] == '\0') - goto error; - p2 = p1 + sz; - - if ((v = malloc(sizeof(*v))) == NULL) - goto nomem; - v->mv_name = v->mv_value = NULL; - v->mv_next = *val; - *val = v; - if ((v->mv_name = malloc(p2 - p1 + 1)) == NULL) - goto nomem; - strncpy(v->mv_name, p1, p2 - p1); - v->mv_name[p2 - p1] = '\0'; - - sz = strspn(p2, " \t\n\r"); - if (p2[sz] == '\0') - goto error; - p2 += sz; - - if (*p2 != '=') - goto error; - p2++; - - sz = strspn(p2, " \t\n\r"); - if (p2[sz] == '\0') - goto error; - p2 += sz; - p1 = p2; - - if (*p2 == '"') { - p1++; - while (*p2 == '"') { - p2++; - p2 = strchr(p2, '\"'); - if (p2 == NULL) - goto error; - if (p2[0] == '\0') - goto error; - if (p2[-1] != '\\') - break; - } - } else { - sz = strcspn(p2, " \t\n\r=,"); - p2 += sz; - } - -#if 0 /* allow empty values */ - if (p1 == p2) - goto error; -#endif - - if ((v->mv_value = malloc(p2 - p1 + 1)) == NULL) - goto nomem; - strncpy(v->mv_value, p1, p2 - p1); - v->mv_value[p2 - p1] = '\0'; - - if (p2[0] == '\0') - break; - if (p2[0] == '"') - p2++; - - sz = strspn(p2, " \t\n\r"); - if (p2[sz] == '\0') - break; - p2 += sz; - - if (p2[0] == '\0') - break; - if (p2[0] != ',') - goto error; - p1 = p2; - } - - free(str); - - return 0; - error: - free_values(*val); - *val = NULL; - free(str); - return EINVAL; - nomem: - free_values(*val); - *val = NULL; - free(str); - return ENOMEM; -} - -/* - * - */ - -static const char * -check_prefix(heim_digest_t context, const char *challenge) -{ - if (strncasecmp(digest_prefix, challenge, sizeof(digest_prefix) - 1) == 0) { - - challenge += sizeof(digest_prefix) - 1; - while (*challenge == 0x20) /* remove extra space */ - challenge++; - context->flags |= F_USE_PREFIX; - } - - return challenge; -} - -/* - * - */ - -heim_digest_t -heim_digest_create(int server, int type) -{ - heim_digest_t context; - - context = calloc(1, sizeof(*context)); - if (context == NULL) - return NULL; - context->flags |= F_SERVER; - context->type = type; - - return context; -} - -static char * -generate_nonce(void) -{ - uint8_t rand[8]; - char *nonce; - - if (CCRandomCopyBytes(kCCRandomDefault, rand, sizeof(rand)) != kCCSuccess) - return NULL; - - if (rk_hex_encode(rand, sizeof(rand), &nonce) < 0) - return NULL; - - return nonce; -} - -/** - * Generate a challange, needs to set serverRealm before calling this function. - * - * If type is set to HEIM_DIGEST_TYPE_AUTO, the HEIM_DIGEST_TYPE_RFC2831 will be used instead. - * - * For RFC2617 and RFC2831 QOP is required, so if any qop other then "auth" is requested, it need to be set with heim_diest_set_key(). - * - * @return returns the challenge or NULL on error or failure to build the string. the lifetime - * of the string is manage by heim_digest and last until the the context is - * freed or until next call to heim_digest_generate_challenge(). - */ - -const char * -heim_digest_generate_challenge(heim_digest_t context) -{ - char *challenge = NULL; - - if (context->serverRealm == NULL) - return NULL; - - if (context->serverNonce == NULL) { - if ((context->serverNonce = generate_nonce()) == NULL) - return NULL; - } - - if (context->serverQOP == NULL) { - if ((context->serverQOP = strdup("auth")) == NULL) - return NULL; - } - - if (context->serverMaxbuf == NULL) { - if ((context->serverMaxbuf = strdup("65536")) == NULL) - return NULL; - } - - switch(context->type) { - case HEIM_DIGEST_TYPE_RFC2617_MD5: - asprintf(&challenge, "realm=\"%s\",nonce=\"%s\",algorithm=md5,qop=\"%s\"", - context->serverRealm, context->serverNonce, - context->serverQOP); - break; - case HEIM_DIGEST_TYPE_RFC2617_MD5_SESS: - asprintf(&challenge, "realm=\"%s\",nonce=\"%s\",algorithm=md5-sess,qop=\"%s\"", - context->serverRealm, context->serverNonce, context->serverQOP); - break; - case HEIM_DIGEST_TYPE_RFC2069: - asprintf(&challenge, "realm=\"%s\",nonce=\"%s\"", - context->serverRealm, context->serverNonce); - break; - case HEIM_DIGEST_TYPE_AUTO: - context->type = HEIM_DIGEST_TYPE_RFC2831; - HEIM_FALLTHROUGH; - case HEIM_DIGEST_TYPE_RFC2831: - asprintf(&challenge, "realm=\"%s\",nonce=\"%s\",qop=\"%s\",algorithm=md5-sess,charset=utf-8,maxbuf=%s", - context->serverRealm, context->serverNonce, context->serverQOP, context->serverMaxbuf); - break; - } - - FREE_AND_CLEAR(context->serverChallenge); - context->serverChallenge = challenge; - - return challenge; -} - -int -heim_digest_parse_challenge(heim_digest_t context, const char *challenge) -{ - struct md5_value *val = NULL; - int ret, type; - - challenge = check_prefix(context, challenge); - - ret = parse_values(challenge, &val); - if (ret) - goto out; - - ret = 1; - - context->serverNonce = values_find(&val, "nonce"); - if (context->serverNonce == NULL) goto out; - - context->serverRealm = values_find(&val, "realm"); - if (context->serverRealm == NULL) goto out; - - /* check alg */ - - context->serverAlgorithm = values_find(&val, "algorithm"); - if (context->serverAlgorithm == NULL || strcasecmp(context->serverAlgorithm, "md5") == 0) { - type = HEIM_DIGEST_TYPE_RFC2617_MD5; - } else if (strcasecmp(context->serverAlgorithm, "md5-sess") == 0) { - type = HEIM_DIGEST_TYPE_RFC2617_OR_RFC2831; - } else { - goto out; - } - - context->serverQOP = values_find(&val, "qop"); - if (context->serverQOP == NULL) - type = HEIM_DIGEST_TYPE_RFC2069; - - context->serverOpaque = values_find(&val, "opaque"); - - if (context->type != HEIM_DIGEST_TYPE_AUTO && (context->type & type) == 0) - goto out; - else if (context->type == HEIM_DIGEST_TYPE_AUTO) - context->type = type; - - ret = 0; - out: - free_values(val); - if (ret) - clear_context(context); - return ret; -} - - -static void -set_auth_method(heim_digest_t context) -{ - - if (context->serverMethod == NULL) { - if (context->type == HEIM_DIGEST_TYPE_RFC2831) - context->serverMethod = strdup("AUTHENTICATE"); - else - context->serverMethod = strdup("GET"); - } -} - -int -heim_digest_parse_response(heim_digest_t context, const char *response) -{ - struct md5_value *val = NULL; - char *nonce; - int ret; - - response = check_prefix(context, response); - - ret = parse_values(response, &val); - if (ret) - goto out; - - ret = 1; - - if (context->type == HEIM_DIGEST_TYPE_AUTO) { - goto out; - } else if (context->type == HEIM_DIGEST_TYPE_RFC2617_OR_RFC2831) { - context->clientURI = values_find(&val, "uri"); - if (context->clientURI) { - context->type = HEIM_DIGEST_TYPE_RFC2617_MD5_SESS; - } else { - context->clientURI = values_find(&val, "digest-uri"); - context->type = HEIM_DIGEST_TYPE_RFC2831; - } - } else if (context->type == HEIM_DIGEST_TYPE_RFC2831) { - context->clientURI = values_find(&val, "digest-uri"); - } else { - context->clientURI = values_find(&val, "uri"); - } - - if (context->clientURI == NULL) - goto out; - - context->clientUsername = values_find(&val, "username"); - if (context->clientUsername == NULL) goto out; - - /* if client sent realm, make sure its the same of serverRealm if its set */ - context->clientRealm = values_find(&val, "realm"); - if (context->clientRealm && context->serverRealm && strcmp(context->clientRealm, context->serverRealm) != 0) - goto out; - - context->clientResponse = values_find(&val, "response"); - if (context->clientResponse == NULL) goto out; - - nonce = values_find(&val, "nonce"); - if (nonce == NULL) goto out; - - if (strcmp(nonce, context->serverNonce) != 0) { - free(nonce); - goto out; - } - free(nonce); - - if (context->type != HEIM_DIGEST_TYPE_RFC2069) { - - context->clientQOP = values_find(&val, "qop"); - if (context->clientQOP == NULL) goto out; - - /* - * If we have serverQOP, lets check that clientQOP exists - * in the list of server entries. - */ - - if (context->serverQOP) { - Boolean found = false; - char *b, *e; - size_t len, clen = strlen(context->clientQOP); - - b = context->serverQOP; - while (b && !found) { - e = strchr(b, ','); - if (e == NULL) - len = strlen(b); - else { - len = e - b; - e += 1; - } - if (clen == len && strncmp(b, context->clientQOP, len) == 0) - found = true; - b = e; - } - if (!found) - goto out; - } - - context->clientNC = values_find(&val, "nc"); - if (context->clientNC == NULL) goto out; - - context->clientNonce = values_find(&val, "cnonce"); - if (context->clientNonce == NULL) goto out; - } - - set_auth_method(context); - - ret = 0; - out: - free_values(val); - return ret; -} - -char * -heim_digest_userhash(const char *user, const char *realm, const char *password) -{ - unsigned char md[CC_MD5_DIGEST_LENGTH]; - char *str = NULL; - - digest_userhash(user, realm, password, md); - - hex_encode(md, sizeof(md), &str); - if (str) - strlwr(str); - return str; -} - -static char * -build_digest(heim_digest_t context, const char *a1, const char *method) -{ - CC_MD5_CTX ctx; - uint8_t md[CC_MD5_DIGEST_LENGTH]; - char *a2, *str = NULL; - - a2 = build_A2_hash(context, method); - if (a2 == NULL) - return NULL; - - CC_MD5_Init(&ctx); - CC_MD5_Update(&ctx, a1, (CC_LONG)strlen(a1)); - CC_MD5_Update(&ctx, ":", 1); - CC_MD5_Update(&ctx, context->serverNonce, (CC_LONG)strlen(context->serverNonce)); - if (context->type != HEIM_DIGEST_TYPE_RFC2069) { - CC_MD5_Update(&ctx, ":", 1); - CC_MD5_Update(&ctx, context->clientNC, (CC_LONG)strlen(context->clientNC)); - CC_MD5_Update(&ctx, ":", 1); - CC_MD5_Update(&ctx, context->clientNonce, (CC_LONG)strlen(context->clientNonce)); - CC_MD5_Update(&ctx, ":", 1); - CC_MD5_Update(&ctx, context->clientQOP, (CC_LONG)strlen(context->clientQOP)); - } - CC_MD5_Update(&ctx, ":", 1); - CC_MD5_Update(&ctx, a2, (CC_LONG)strlen(a2)); - CC_MD5_Final(md, &ctx); - - free(a2); - - hex_encode(md, sizeof(md), &str); - if (str) - strlwr(str); - - return str; -} - -static void -build_server_response(heim_digest_t context, char *a1, char **response) -{ - char *str; - - str = build_digest(context, a1, NULL); - if (str == NULL) - return; - - FREE_AND_CLEAR(context->serverReply); - asprintf(&context->serverReply, "%srspauth=%s", - (context->flags & F_USE_PREFIX) ? digest_prefix : "", - str); - free(str); - if (response) - *response = context->serverReply; -} - - -/** - * Create response from server to client to server, server verification is in response. - * clientUsername and clientURI have to be given. - * If realm is not set, its used from server. - */ - -const char * -heim_digest_create_response(heim_digest_t context, char **response) -{ - char *a1, *str, *cnonce = NULL, *opaque = NULL, *uri = NULL, *nc = NULL; - - if (response) - *response = NULL; - - if (context->clientUsername == NULL || context->clientURI == NULL) - return NULL; - - if (context->clientRealm == NULL) { - if (context->serverRealm == NULL) - return NULL; - if ((context->clientRealm = strdup(context->serverRealm)) == NULL) - return NULL; - } - - if (context->type != HEIM_DIGEST_TYPE_RFC2069) { - if (context->clientNC == NULL) { - if ((context->clientNC = strdup("00000001")) == NULL) - return NULL; - } - if (context->clientNonce == NULL) { - if ((context->clientNonce = generate_nonce()) == NULL) - return NULL; - } - - /** - * If using non RFC2069, appropriate QOP should be set. - * - * Pick QOP from server if not given, if its a list, pick the first entry - */ - if (context->clientQOP == NULL) { - char *r; - if (context->serverQOP == NULL) - return NULL; - r = strchr(context->serverQOP, ','); - if (r == NULL) { - if ((context->clientQOP = strdup(context->serverQOP)) == NULL) - return NULL; - } else { - size_t len = (r - context->serverQOP) + 1; - if ((context->clientQOP = malloc(len)) == NULL) - return NULL; - strlcpy(context->clientQOP, context->serverQOP, len); - } - } - } - - set_auth_method(context); - - a1 = build_A1_hash(context); - if (a1 == NULL) - return NULL; - - str = build_digest(context, a1, context->serverMethod); - if (str == NULL) { - MEMSET_FREE_AND_CLEAR(a1); - return NULL; - } - - MEMSET_FREE_AND_CLEAR(context->clientResponse); - context->clientResponse = str; - - if (context->clientURI) { - const char *name = "digest-uri"; - if (context->type != HEIM_DIGEST_TYPE_RFC2831) - name = "uri"; - asprintf(&uri, ",%s=\"%s\"", name, context->clientURI); - } - - if (context->serverOpaque) - asprintf(&opaque, ",opaque=\"%s\"", context->serverOpaque); - - if (context->clientNonce) - asprintf(&cnonce, ",cnonce=\"%s\"", context->clientNonce); - - if (context->clientNC) - asprintf(&nc, ",nc=%s", context->clientNC); - - asprintf(&context->clientReply, - "username=%s,realm=%s,nonce=\"%s\",qop=\"%s\"%s%s%s,response=\"%s\"%s", - context->clientUsername, context->clientRealm, - context->serverNonce, - context->clientQOP, - uri ? uri : "", - cnonce ? cnonce : "", - nc ? nc : "", - context->clientResponse, - opaque ? opaque : ""); - - build_server_response(context, a1, response); - MEMSET_FREE_AND_CLEAR(a1); - FREE_AND_CLEAR(uri); - FREE_AND_CLEAR(opaque); - FREE_AND_CLEAR(cnonce); - FREE_AND_CLEAR(nc); - - return context->clientReply; -} - -int -heim_digest_verify(heim_digest_t context, char **response) -{ - char *a1; - char *str; - int res; - - if (response) - *response = NULL; - - set_auth_method(context); - - a1 = build_A1_hash(context); - if (a1 == NULL) - return ENOMEM; - - str = build_digest(context, a1, context->serverMethod); - if (str == NULL) { - MEMSET_FREE_AND_CLEAR(a1); - return ENOMEM; - } - - res = (strcmp(str, context->clientResponse) == 0) ? 0 : EINVAL; - free(str); - if (res) { - MEMSET_FREE_AND_CLEAR(a1); - return res; - } - - /* build server_response */ - build_server_response(context, a1, response); - MEMSET_FREE_AND_CLEAR(a1); - /* XXX break ABI and return internally allocated string instead */ - if (response) - *response = strdup(*response); - - return 0; -} - -/** - * Create a rspauth= response. - * Assumes that the A1hash/password serverNonce, clientNC, clientNonce, clientQOP is set. - * - * @return the rspauth string (including rspauth), return key are stored in serverReply and will be invalid after another call to heim_digest_* - */ - -const char * -heim_digest_server_response(heim_digest_t context) -{ - char *a1; - - if (context->serverNonce == NULL) - return NULL; - if (context->clientURI == NULL) - return NULL; - - a1 = build_A1_hash(context); - if (a1 == NULL) - return NULL; - - build_server_response(context, a1, NULL); - MEMSET_FREE_AND_CLEAR(a1); - - return context->serverReply; -} - -void -heim_digest_get_session_key(heim_digest_t context, void **key, size_t *keySize) -{ -} - -void -heim_digest_release(heim_digest_t context) -{ - clear_context(context); - free(context); -} - -struct { - char *name; - size_t offset; -} keys[] = { -#define KVN(value) { #value, offsetof(struct heim_digest_desc, value) } - KVN(serverNonce), - KVN(serverRealm), - KVN(serverQOP), - KVN(serverMethod), - { "method", offsetof(struct heim_digest_desc, serverMethod) }, - KVN(serverMaxbuf), - KVN(clientUsername), - { "username", offsetof(struct heim_digest_desc, clientUsername) }, - KVN(clientResponse), - KVN(clientURI), - { "uri", offsetof(struct heim_digest_desc, clientURI) }, - KVN(clientRealm), - { "realm", offsetof(struct heim_digest_desc, clientRealm) }, - KVN(clientNonce), - KVN(clientQOP), - KVN(clientNC), - KVN(serverAlgorithm), - KVN(auth_id) -#undef KVN -}; - -const char * -heim_digest_get_key(heim_digest_t context, const char *key) -{ - size_t n; - - for (n = 0; n < sizeof(keys) / sizeof(keys[0]); n++) { - if (strcasecmp(key, keys[n].name) == 0) { - char **ptr = (char **)((((char *)context) + keys[n].offset)); - return *ptr; - } - } - return NULL; -} - -int -heim_digest_set_key(heim_digest_t context, const char *key, const char *value) -{ - - if (strcmp(key, "password") == 0) { - FREE_AND_CLEAR(context->password); - if ((context->password = strdup(value)) == NULL) - return ENOMEM; - context->flags &= ~(F_HAVE_HASH|F_HAVE_HA1); - } else if (strcmp(key, "userhash") == 0) { - ssize_t ret; - FREE_AND_CLEAR(context->password); - - ret = hex_decode(value, context->SecretHash, sizeof(context->SecretHash)); - if (ret != sizeof(context->SecretHash)) - return EINVAL; - context->flags &= ~F_HAVE_HA1; - context->flags |= F_HAVE_HASH; - } else if (strcmp(key, "H(A1)") == 0) { - ssize_t ret; - FREE_AND_CLEAR(context->password); - - ret = hex_decode(value, context->SecretHash, sizeof(context->SecretHash)); - if (ret != sizeof(context->SecretHash)) - return EINVAL; - context->flags &= ~F_HAVE_HASH; - context->flags |= F_HAVE_HA1; - } else if (strcmp(key, "method") == 0) { - FREE_AND_CLEAR(context->serverMethod); - if ((context->serverMethod = strdup(value)) == NULL) - return ENOMEM; - } else { - size_t n; - - for (n = 0; n < sizeof(keys) / sizeof(keys[0]); n++) { - if (strcasecmp(key, keys[n].name) == 0) { - char **ptr = (char **)((((char *)context) + keys[n].offset)); - FREE_AND_CLEAR(*ptr); - if (((*ptr) = strdup(value)) == NULL) - return ENOMEM; - break; - } - } - if (n == sizeof(keys) / sizeof(keys[0])) - return ENOENT; - } - return 0; -} - diff --git a/lib/ntlm/heim-auth.h b/lib/ntlm/heim-auth.h deleted file mode 100644 index a828de302..000000000 --- a/lib/ntlm/heim-auth.h +++ /dev/null @@ -1,135 +0,0 @@ -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Generate challange for APOP and CRAM-MD5 - */ - -char * -heim_generate_challenge(const char *hostname); /* hostname can be NULL, the local hostname is used */ - -/* - * APOP - */ - -char * -heim_apop_create(const char *challenge, const char *password); - -int -heim_apop_verify(const char *challenge, const char *password, const char *response); - -/* - * CRAM-MD5 - */ - -typedef struct heim_HMAC_MD5_STATE_s { - uint32_t istate[4]; - uint32_t ostate[4]; -} heim_CRAM_MD5_STATE; - -typedef struct heim_cram_md5_data *heim_cram_md5; - -char * -heim_cram_md5_create(const char *challenge, const char *password); - -int -heim_cram_md5_verify(const char *challenge, const char *password, const char *response); - -void -heim_cram_md5_export(const char *password, heim_CRAM_MD5_STATE *state); - -heim_cram_md5 -heim_cram_md5_import(void *data, size_t len); - -int -heim_cram_md5_verify_ctx(heim_cram_md5 ctx, const char *challenge, const char *response); - -void -heim_cram_md5_free(heim_cram_md5 ctx); - -/* - * DIGEST-MD5 - * - * heim_digest_t d; - * - * d = heim_digest_create(1, HEIM_DIGEST_TYPE_DIGEST_MD5_HTTP); - * - * if ((s = heim_digest_generate_challange(d)) != NULL) abort(); - * send_to_client(s); - * response = read_from_client(); - * - * heim_digest_parse_response(d, response); - * const char *user = heim_digest_get_key(d, "username"); - * heim_digest_set_key(d, "password", "sommar17"); - * - * if (heim_digest_verify(d, &response)) abort(); - * - * send_to_client(response); - * - * heim_digest_release(d); - */ - -typedef struct heim_digest_desc *heim_digest_t; - -heim_digest_t -heim_digest_create(int server, int type); - -#define HEIM_DIGEST_TYPE_AUTO 0 -#define HEIM_DIGEST_TYPE_RFC2069 1 -#define HEIM_DIGEST_TYPE_RFC2617_MD5 2 -#define HEIM_DIGEST_TYPE_RFC2617_MD5_SESS 4 -#define HEIM_DIGEST_TYPE_RFC2831 8 - -#define HEIM_DIGEST_TYPE_RFC2617_OR_RFC2831 12 - -/* old deprecated names, use the two above instead */ -#define HEIM_DIGEST_TYPE_MD5 2 -#define HEIM_DIGEST_TYPE_MD5_SESS 4 - -void -heim_digest_init_set_key(heim_digest_t context, const char *key, const char *value); - -const char * -heim_digest_generate_challenge(heim_digest_t context); - -int -heim_digest_parse_challenge(heim_digest_t context, const char *challenge); - -int -heim_digest_parse_response(heim_digest_t context, const char *response); - -const char * -heim_digest_get_key(heim_digest_t context, const char *key); - -int -heim_digest_set_key(heim_digest_t context, const char *key, const char *value); - -void -heim_digest_set_user_password(heim_digest_t context, const char *password); - -void -heim_digest_set_user_h1hash(heim_digest_t context, void *ptr, size_t size); - -int -heim_digest_verify(heim_digest_t context, char **response); - -const char * -heim_digest_create_response(heim_digest_t context, char **response); - -void -heim_digest_get_session_key(heim_digest_t context, void **key, size_t *keySize); - -void -heim_digest_release(heim_digest_t context); - -char * -heim_digest_userhash(const char *user, const char *realm, const char *password); - -const char * -heim_digest_server_response(heim_digest_t context); - -#ifdef __cplusplus -} -#endif diff --git a/lib/ntlm/heimntlm.h b/lib/ntlm/heimntlm.h deleted file mode 100644 index 6b24649df..000000000 --- a/lib/ntlm/heimntlm.h +++ /dev/null @@ -1,166 +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_NTLM_H -#define HEIM_NTLM_H - -/** - * Buffer for storing data in the NTLM library. When filled in by the - * library it should be freed with heim_ntlm_free_buf(). - */ -struct ntlm_buf { - size_t length; /**< length buffer data */ - void *data; /**< pointer to the data itself */ -}; - -#define NTLM_NEG_UNICODE 0x00000001 -#define NTLM_NEG_OEM 0x00000002 -#define NTLM_NEG_TARGET 0x00000004 -#define NTLM_MBZ9 0x00000008 - -#define NTLM_NEG_SIGN 0x00000010 -#define NTLM_NEG_SEAL 0x00000020 -#define NTLM_NEG_DATAGRAM 0x00000040 -#define NTLM_NEG_LM_KEY 0x00000080 -#define NTLM_NEG_NTLM 0x00000200 -#define NTLM_NEG_ANONYMOUS 0x00000800 - -#define NTLM_MBZ8 0x00000100 -#define NTLM_NEG_NTLM 0x00000200 -#define NTLM_NEG_NT_ONLY 0x00000400 -#define NTLM_MBZ7 0x00000800 /* anon ? */ - -#define NTLM_OEM_SUPPLIED_DOMAIN 0x00001000 -#define NTLM_OEM_SUPPLIED_WORKSTATION 0x00002000 -#define NTLM_MBZ6 0x00004000 /* local call ? */ -#define NTLM_NEG_ALWAYS_SIGN 0x00008000 - -#define NTLM_TARGET_DOMAIN 0x00010000 -#define NTLM_TARGET_SERVER 0x00020000 - -#define NTLM_TARGET_SHARE 0x00040000 /* mbz */ -#define NTLM_NEG_NTLM2_SESSION 0x00080000 /* EXTENDED_SESSIONSECURITY */ -#define NTLM_NEG_NTLM2 0x00080000 - -#define NTLM_NEG_IDENTIFY 0x00100000 -#define NTLM_MBZ5 0x00200000 -#define NTLM_NON_NT_SESSION_KEY 0x00400000 -#define NTLM_NEG_TARGET_INFO 0x00800000 - -#define NTLM_MBZ4 0x01000000 -#define NTLM_NEG_VERSION 0x02000000 -#define NTLM_MBZ3 0x04000000 -#define NTLM_MBZ2 0x08000000 - -#define NTLM_MBZ1 0x10000000 -#define NTLM_ENC_128 0x20000000 -#define NTLM_NEG_KEYEX 0x40000000 -#define NTLM_ENC_56 0x80000000 - -/** - * Struct for the NTLM target info, the strings is assumed to be in - * UTF8. When filled in by the library it should be freed with - * heim_ntlm_free_targetinfo(). - */ - -/* avflags */ -#define NTLM_TI_AV_FLAG_GUEST 0x00000001 -#define NTLM_TI_AV_FLAG_MIC 0x00000002 - -struct ntlm_targetinfo { - char *servername; /**< */ - char *domainname; /**< */ - char *dnsdomainname; /**< */ - char *dnsservername; /**< */ - char *dnstreename; /**< */ - uint32_t avflags; /**< */ - char *targetname; - struct ntlm_buf channel_bindings; - uint64_t timestamp; -}; - -/** - * Struct for the NTLM type1 message info, the strings is assumed to - * be in UTF8. When filled in by the library it should be freed with - * heim_ntlm_free_type1(). - */ - -struct ntlm_type1 { - uint32_t flags; /**< */ - char *domain; /**< */ - char *hostname; /**< */ - uint32_t os[2]; /**< */ -}; - -/** - * Struct for the NTLM type2 message info, the strings is assumed to - * be in UTF8. When filled in by the library it should be freed with - * heim_ntlm_free_type2(). - */ - -struct ntlm_type2 { - uint32_t flags; /**< */ - char *targetname; /**< */ - struct ntlm_buf targetinfo; /**< */ - unsigned char challenge[8]; /**< */ - uint32_t context[2]; /**< */ - uint32_t os[2]; /**< */ -}; - -/** - * Struct for the NTLM type3 message info, the strings is assumed to - * be in UTF8. When filled in by the library it should be freed with - * heim_ntlm_free_type3(). - */ - -struct ntlm_type3 { - uint32_t flags; /**< */ - char *username; /**< */ - char *targetname; /**< */ - struct ntlm_buf lm; /**< */ - struct ntlm_buf ntlm; /**< */ - struct ntlm_buf sessionkey; /**< */ - char *ws; /**< */ - uint32_t os[2]; /**< */ - size_t mic_offset; - uint8_t mic[16]; -}; - -extern time_t heim_ntlm_time_skew; - -#include -#include - -#endif /* NTLM_NTLM_H */ diff --git a/lib/ntlm/libheimntlm-exports.def b/lib/ntlm/libheimntlm-exports.def deleted file mode 100644 index 33ac09e70..000000000 --- a/lib/ntlm/libheimntlm-exports.def +++ /dev/null @@ -1,24 +0,0 @@ -EXPORTS - heim_ntlm_build_ntlm1_master - heim_ntlm_calculate_lm2 - heim_ntlm_calculate_ntlm1 - heim_ntlm_calculate_ntlm2 - heim_ntlm_calculate_ntlm2_sess - heim_ntlm_decode_targetinfo - heim_ntlm_decode_type1 - heim_ntlm_decode_type2 - heim_ntlm_decode_type3 - heim_ntlm_encode_targetinfo - heim_ntlm_encode_type1 - heim_ntlm_encode_type2 - heim_ntlm_encode_type3 - heim_ntlm_free_buf - heim_ntlm_free_targetinfo - heim_ntlm_free_type1 - heim_ntlm_free_type2 - heim_ntlm_free_type3 - heim_ntlm_nt_key - heim_ntlm_ntlmv2_key - heim_ntlm_verify_ntlm2 - heim_ntlm_unparse_flags - initialize_ntlm_error_table_r diff --git a/lib/ntlm/libheimntlm-version.rc b/lib/ntlm/libheimntlm-version.rc deleted file mode 100644 index 2055c9d67..000000000 --- a/lib/ntlm/libheimntlm-version.rc +++ /dev/null @@ -1,36 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2010, Secure Endpoints Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * - **********************************************************************/ - -#define RC_FILE_TYPE VFT_DLL -#define RC_FILE_DESC_0409 "Heimdal NTLM Support Library" -#define RC_FILE_ORIG_0409 "libheimntlm.dll" - -#include "../../windows/version.rc" diff --git a/lib/ntlm/ntlm.c b/lib/ntlm/ntlm.c deleted file mode 100644 index a6b9ce405..000000000 --- a/lib/ntlm/ntlm.c +++ /dev/null @@ -1,2027 +0,0 @@ -/* - * Copyright (c) 2006 - 2008 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Portions Copyright (c) 2010 Apple Inc. 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 - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include "krb5-types.h" -#include "crypto-headers.h" - -#include - -/*! \mainpage Heimdal NTLM library - * - * \section intro Introduction - * - * Heimdal libheimntlm library is a implementation of the NTLM - * protocol, both version 1 and 2. The GSS-API mech that uses this - * library adds support for transport encryption and integrity - * checking. - * - * NTLM is a protocol for mutual authentication, its still used in - * many protocol where Kerberos is not support, one example is - * EAP/X802.1x mechanism LEAP from Microsoft and Cisco. - * - * This is a support library for the core protocol, its used in - * Heimdal to implement and GSS-API mechanism. There is also support - * in the KDC to do remote digest authenticiation, this to allow - * services to authenticate users w/o direct access to the users ntlm - * hashes (same as Kerberos arcfour enctype keys). - * - * More information about the NTLM protocol can found here - * http://davenport.sourceforge.net/ntlm.html . - * - * The Heimdal projects web page: http://www.h5l.org/ - * - * @section ntlm_example NTLM Example - * - * Example to to use @ref test_ntlm.c . - * - * @example test_ntlm.c - * - * Example how to use the NTLM primitives. - * - */ - -/** @defgroup ntlm_core Heimdal NTLM library - * - * The NTLM core functions implement the string2key generation - * function, message encode and decode function, and the hash function - * functions. - */ - -struct sec_buffer { - uint16_t length; - uint16_t allocated; - uint32_t offset; -}; - -static const unsigned char ntlmsigature[8] = "NTLMSSP\x00"; - -time_t heim_ntlm_time_skew = 300; - -/* - * - */ - -#define CHECK(f, e) \ - do { \ - ret = f; \ - if (ret != (ssize_t)(e)) { \ - ret = HNTLM_ERR_DECODE; \ - goto out; \ - } \ - } while(/*CONSTCOND*/0) - -#define CHECK_SIZE(f, e) \ - do { \ - ssize_t sret = f; \ - if (sret != (ssize_t)(e)) { \ - ret = HNTLM_ERR_DECODE; \ - goto out; \ - } \ - } while(/*CONSTCOND*/0) - -#define CHECK_OFFSET(f, e) \ - do { \ - off_t sret = f; \ - if (sret != (e)) { \ - ret = HNTLM_ERR_DECODE; \ - goto out; \ - } \ - } while(/*CONSTCOND*/0) - - -static struct units ntlm_flag_units[] = { -#define ntlm_flag(x) { #x, NTLM_##x } - ntlm_flag(ENC_56), - ntlm_flag(NEG_KEYEX), - ntlm_flag(ENC_128), - ntlm_flag(MBZ1), - ntlm_flag(MBZ2), - ntlm_flag(MBZ3), - ntlm_flag(NEG_VERSION), - ntlm_flag(MBZ4), - ntlm_flag(NEG_TARGET_INFO), - ntlm_flag(NON_NT_SESSION_KEY), - ntlm_flag(MBZ5), - ntlm_flag(NEG_IDENTIFY), - ntlm_flag(NEG_NTLM2), - ntlm_flag(TARGET_SHARE), - ntlm_flag(TARGET_SERVER), - ntlm_flag(TARGET_DOMAIN), - ntlm_flag(NEG_ALWAYS_SIGN), - ntlm_flag(MBZ6), - ntlm_flag(OEM_SUPPLIED_WORKSTATION), - ntlm_flag(OEM_SUPPLIED_DOMAIN), - ntlm_flag(NEG_ANONYMOUS), - ntlm_flag(NEG_NT_ONLY), - ntlm_flag(NEG_NTLM), - ntlm_flag(MBZ8), - ntlm_flag(NEG_LM_KEY), - ntlm_flag(NEG_DATAGRAM), - ntlm_flag(NEG_SEAL), - ntlm_flag(NEG_SIGN), - ntlm_flag(MBZ9), - ntlm_flag(NEG_TARGET), - ntlm_flag(NEG_OEM), - ntlm_flag(NEG_UNICODE), -#undef ntlm_flag - {NULL, 0} -}; - -size_t -heim_ntlm_unparse_flags(uint32_t flags, char *s, size_t len) -{ - return unparse_flags(flags, ntlm_flag_units, s, len); -} - - -/** - * heim_ntlm_free_buf frees the ntlm buffer - * - * @param p buffer to be freed - * - * @ingroup ntlm_core - */ - -void -heim_ntlm_free_buf(struct ntlm_buf *p) -{ - if (p->data) - free(p->data); - p->data = NULL; - p->length = 0; -} - - -static int -ascii2ucs2le(const char *string, int up, struct ntlm_buf *buf) -{ - uint16_t *data; - size_t len, n; - uint8_t *p; - int ret; - - ret = wind_utf8ucs2_length(string, &len); - if (ret) - return ret; - if (len > UINT_MAX / sizeof(data[0])) - return ERANGE; - - data = malloc(len * sizeof(data[0])); - if (data == NULL) - return ENOMEM; - - ret = wind_utf8ucs2(string, data, &len); - if (ret) { - free(data); - return ret; - } - - if (len == 0) { - free(data); - buf->data = NULL; - buf->length = 0; - return 0; - } - - /* uppercase string, only handle ascii right now */ - if (up) { - for (n = 0; n < len ; n++) { - if (data[n] < 128) - data[n] = toupper((int)data[n]); - } - } - - buf->length = len * 2; - p = buf->data = malloc(buf->length); - if (buf->data == NULL && len != 0) { - free(data); - heim_ntlm_free_buf(buf); - return ENOMEM; - } - - for (n = 0; n < len ; n++) { - p[(n * 2) + 0] = (data[n] ) & 0xff; - p[(n * 2) + 1] = (data[n] >> 8) & 0xff; - } - memset(data, 0, sizeof(data[0]) * len); - free(data); - - return 0; -} - -/* - * Sizes in bytes - */ - -#define SIZE_SEC_BUFFER (2+2+4) -#define SIZE_OS_VERSION (8) - -/* - * - */ - -static krb5_error_code -ret_sec_buffer(krb5_storage *sp, struct sec_buffer *buf) -{ - krb5_error_code ret; - CHECK(krb5_ret_uint16(sp, &buf->length), 0); - CHECK(krb5_ret_uint16(sp, &buf->allocated), 0); - CHECK(krb5_ret_uint32(sp, &buf->offset), 0); -out: - return ret; -} - -static krb5_error_code -store_sec_buffer(krb5_storage *sp, const struct sec_buffer *buf) -{ - krb5_error_code ret; - CHECK(krb5_store_uint16(sp, buf->length), 0); - CHECK(krb5_store_uint16(sp, buf->allocated), 0); - CHECK(krb5_store_uint32(sp, buf->offset), 0); -out: - return ret; -} - -/* - * Strings are either OEM or UNICODE. The later is encoded as ucs2 on - * wire, but using utf8 in memory. - */ - -static size_t -len_string(int ucs2, const char *s) -{ - if (ucs2) { - size_t len; - int ret; - - ret = wind_utf8ucs2_length(s, &len); - if (ret == 0) - return len * 2; - return strlen(s) * 5 * 2; - } else { - return strlen(s); - } -} - -/* - * - */ - -static krb5_error_code -ret_string(krb5_storage *sp, int ucs2, size_t len, char **s) -{ - krb5_error_code ret; - uint16_t *data = NULL; - - *s = malloc(len + 1); - if (*s == NULL) - return ENOMEM; - CHECK_SIZE(krb5_storage_read(sp, *s, len), len); - - (*s)[len] = '\0'; - - if (ucs2) { - unsigned int flags = WIND_RW_LE; - size_t utf16len = len / 2; - size_t utf8len; - - data = malloc(utf16len * sizeof(data[0])); - if (data == NULL) { - free(*s); *s = NULL; - ret = ENOMEM; - goto out; - } - - ret = wind_ucs2read(*s, len, &flags, data, &utf16len); - free(*s); *s = NULL; - if (ret) { - goto out; - } - - CHECK(wind_ucs2utf8_length(data, utf16len, &utf8len), 0); - - utf8len += 1; - - *s = malloc(utf8len); - if (*s == NULL) { - ret = ENOMEM; - goto out; - } - - CHECK(wind_ucs2utf8(data, utf16len, *s, &utf8len), 0); - } - ret = 0; - out: - if (data) - free(data); - - return ret; -} - - - -static krb5_error_code -ret_sec_string(krb5_storage *sp, int ucs2, struct sec_buffer *desc, char **s) -{ - krb5_error_code ret = 0; - CHECK_OFFSET(krb5_storage_seek(sp, desc->offset, SEEK_SET), desc->offset); - CHECK(ret_string(sp, ucs2, desc->length, s), 0); - out: - return ret; -} - -static krb5_error_code -put_string(krb5_storage *sp, int ucs2, const char *s) -{ - krb5_error_code ret; - struct ntlm_buf buf; - - if (ucs2) { - ret = ascii2ucs2le(s, 0, &buf); - if (ret) - return ret; - } else { - buf.data = rk_UNCONST(s); - buf.length = strlen(s); - } - - CHECK_SIZE(krb5_storage_write(sp, buf.data, buf.length), buf.length); - if (ucs2) - heim_ntlm_free_buf(&buf); - ret = 0; -out: - return ret; -} - -/* - * - */ - -static krb5_error_code -ret_buf(krb5_storage *sp, struct sec_buffer *desc, struct ntlm_buf *buf) -{ - krb5_error_code ret; - - buf->data = malloc(desc->length); - buf->length = desc->length; - CHECK_OFFSET(krb5_storage_seek(sp, desc->offset, SEEK_SET), desc->offset); - CHECK_SIZE(krb5_storage_read(sp, buf->data, buf->length), buf->length); - ret = 0; -out: - return ret; -} - -static krb5_error_code -put_buf(krb5_storage *sp, const struct ntlm_buf *buf) -{ - krb5_error_code ret; - CHECK_SIZE(krb5_storage_write(sp, buf->data, buf->length), buf->length); - ret = 0; -out: - return ret; -} - -/** - * Frees the ntlm_targetinfo message - * - * @param ti targetinfo to be freed - * - * @ingroup ntlm_core - */ - -void -heim_ntlm_free_targetinfo(struct ntlm_targetinfo *ti) -{ - free(ti->servername); - free(ti->domainname); - free(ti->dnsdomainname); - free(ti->dnsservername); - free(ti->dnstreename); - free(ti->targetname); - heim_ntlm_free_buf(&ti->channel_bindings); - memset(ti, 0, sizeof(*ti)); -} - -static int -encode_ti_string(krb5_storage *out, uint16_t type, int ucs2, char *s) -{ - krb5_error_code ret; - CHECK(krb5_store_uint16(out, type), 0); - CHECK(krb5_store_uint16(out, len_string(ucs2, s)), 0); - CHECK(put_string(out, ucs2, s), 0); -out: - return ret; -} - -/** - * Encodes a ntlm_targetinfo message. - * - * @param ti the ntlm_targetinfo message to encode. - * @param ucs2 ignored - * @param data is the return buffer with the encoded message, should be - * freed with heim_ntlm_free_buf(). - * - * @return In case of success 0 is return, an errors, a errno in what - * went wrong. - * - * @ingroup ntlm_core - */ - -int -heim_ntlm_encode_targetinfo(const struct ntlm_targetinfo *ti, - int ucs2, - struct ntlm_buf *data) -{ - krb5_error_code ret; - krb5_storage *out; - - data->data = NULL; - data->length = 0; - - out = krb5_storage_emem(); - if (out == NULL) - return ENOMEM; - - krb5_storage_set_byteorder(out, KRB5_STORAGE_BYTEORDER_LE); - - if (ti->servername) - CHECK(encode_ti_string(out, 1, ucs2, ti->servername), 0); - if (ti->domainname) - CHECK(encode_ti_string(out, 2, ucs2, ti->domainname), 0); - if (ti->dnsservername) - CHECK(encode_ti_string(out, 3, ucs2, ti->dnsservername), 0); - if (ti->dnsdomainname) - CHECK(encode_ti_string(out, 4, ucs2, ti->dnsdomainname), 0); - if (ti->dnstreename) - CHECK(encode_ti_string(out, 5, ucs2, ti->dnstreename), 0); - if (ti->avflags) { - CHECK(krb5_store_uint16(out, 6), 0); - CHECK(krb5_store_uint16(out, 4), 0); - CHECK(krb5_store_uint32(out, ti->avflags), 0); - } - if (ti->timestamp) { - CHECK(krb5_store_uint16(out, 7), 0); - CHECK(krb5_store_uint16(out, 8), 0); - CHECK(krb5_store_uint32(out, ti->timestamp & 0xffffffff), 0); - CHECK(krb5_store_uint32(out, (ti->timestamp >> 32) & 0xffffffff), 0); - } - if (ti->targetname) { - CHECK(encode_ti_string(out, 9, ucs2, ti->targetname), 0); - } - if (ti->channel_bindings.length) { - CHECK(krb5_store_uint16(out, 10), 0); - CHECK(krb5_store_uint16(out, ti->channel_bindings.length), 0); - CHECK_SIZE(krb5_storage_write(out, ti->channel_bindings.data, ti->channel_bindings.length), ti->channel_bindings.length); - } - - /* end tag */ - CHECK(krb5_store_int16(out, 0), 0); - CHECK(krb5_store_int16(out, 0), 0); - - { - krb5_data d; - ret = krb5_storage_to_data(out, &d); - data->data = d.data; - data->length = d.length; - } -out: - krb5_storage_free(out); - return ret; -} - -/** - * Decodes an NTLM targetinfo message - * - * @param data input data buffer with the encode NTLM targetinfo message - * @param ucs2 if the strings should be encoded with ucs2 (selected by flag in message). - * @param ti the decoded target info, should be freed with heim_ntlm_free_targetinfo(). - * - * @return In case of success 0 is return, an errors, a errno in what - * went wrong. - * - * @ingroup ntlm_core - */ - -int -heim_ntlm_decode_targetinfo(const struct ntlm_buf *data, - int ucs2, - struct ntlm_targetinfo *ti) -{ - uint16_t type, len; - krb5_storage *in; - int ret = 0, done = 0; - - memset(ti, 0, sizeof(*ti)); - - if (data->length == 0) - return 0; - - in = krb5_storage_from_readonly_mem(data->data, data->length); - if (in == NULL) - return ENOMEM; - krb5_storage_set_byteorder(in, KRB5_STORAGE_BYTEORDER_LE); - - while (!done) { - CHECK(krb5_ret_uint16(in, &type), 0); - CHECK(krb5_ret_uint16(in, &len), 0); - - switch (type) { - case 0: - done = 1; - break; - case 1: - CHECK(ret_string(in, ucs2, len, &ti->servername), 0); - break; - case 2: - CHECK(ret_string(in, ucs2, len, &ti->domainname), 0); - break; - case 3: - CHECK(ret_string(in, ucs2, len, &ti->dnsservername), 0); - break; - case 4: - CHECK(ret_string(in, ucs2, len, &ti->dnsdomainname), 0); - break; - case 5: - CHECK(ret_string(in, ucs2, len, &ti->dnstreename), 0); - break; - case 6: - CHECK(krb5_ret_uint32(in, &ti->avflags), 0); - break; - case 7: { - uint32_t tmp; - CHECK(krb5_ret_uint32(in, &tmp), 0); - ti->timestamp = tmp; - CHECK(krb5_ret_uint32(in, &tmp), 0); - ti->timestamp |= ((uint64_t)tmp) << 32; - break; - } - case 9: - CHECK(ret_string(in, 1, len, &ti->targetname), 0); - break; - case 10: - ti->channel_bindings.data = malloc(len); - if (ti->channel_bindings.data == NULL) { - ret = ENOMEM; - goto out; - } - ti->channel_bindings.length = len; - CHECK_SIZE(krb5_storage_read(in, ti->channel_bindings.data, len), len); - break; - default: - krb5_storage_seek(in, len, SEEK_CUR); - break; - } - } - out: - if (in) - krb5_storage_free(in); - return ret; -} - -static krb5_error_code -encode_os_version(krb5_storage *out) -{ - krb5_error_code ret; - CHECK(krb5_store_uint8(out, 0x06), 0); - CHECK(krb5_store_uint8(out, 0x01), 0); - CHECK(krb5_store_uint16(out, 0x1db0), 0); - CHECK(krb5_store_uint8(out, 0x00), 0); - CHECK(krb5_store_uint8(out, 0x00), 0); - CHECK(krb5_store_uint8(out, 0x00), 0); - CHECK(krb5_store_uint8(out, 0x0f), 0); /* ntlm version 15 */ - out: - return ret; -} - -/** - * Frees the ntlm_type1 message - * - * @param data message to be freed - * - * @ingroup ntlm_core - */ - -void -heim_ntlm_free_type1(struct ntlm_type1 *data) -{ - if (data->domain) - free(data->domain); - if (data->hostname) - free(data->hostname); - memset(data, 0, sizeof(*data)); -} - -int -heim_ntlm_decode_type1(const struct ntlm_buf *buf, struct ntlm_type1 *data) -{ - krb5_error_code ret; - unsigned char sig[8]; - uint32_t type; - struct sec_buffer domain, hostname; - krb5_storage *in; - int ucs2; - - memset(data, 0, sizeof(*data)); - - in = krb5_storage_from_readonly_mem(buf->data, buf->length); - if (in == NULL) { - ret = ENOMEM; - goto out; - } - krb5_storage_set_byteorder(in, KRB5_STORAGE_BYTEORDER_LE); - - CHECK_SIZE(krb5_storage_read(in, sig, sizeof(sig)), sizeof(sig)); - CHECK(ct_memcmp(ntlmsigature, sig, sizeof(ntlmsigature)), 0); - CHECK(krb5_ret_uint32(in, &type), 0); - CHECK(type, 1); - CHECK(krb5_ret_uint32(in, &data->flags), 0); - - ucs2 = !!(data->flags & NTLM_NEG_UNICODE); - - /* - * domain and hostname are unconditionally encoded regardless of - * NTLMSSP_NEGOTIATE_OEM_{HOSTNAME,WORKSTATION}_SUPPLIED flag - */ - CHECK(ret_sec_buffer(in, &domain), 0); - CHECK(ret_sec_buffer(in, &hostname), 0); - - if (data->flags & NTLM_NEG_VERSION) { - CHECK(krb5_ret_uint32(in, &data->os[0]), 0); - CHECK(krb5_ret_uint32(in, &data->os[1]), 0); - } - - if (data->flags & NTLM_OEM_SUPPLIED_DOMAIN) - CHECK(ret_sec_string(in, ucs2, &domain, &data->domain), 0); - if (data->flags & NTLM_OEM_SUPPLIED_WORKSTATION) - CHECK(ret_sec_string(in, ucs2, &hostname, &data->hostname), 0); - -out: - if (in) - krb5_storage_free(in); - if (ret) - heim_ntlm_free_type1(data); - - return ret; -} - -/** - * Encodes an ntlm_type1 message. - * - * @param type1 the ntlm_type1 message to encode. - * @param data is the return buffer with the encoded message, should be - * freed with heim_ntlm_free_buf(). - * - * @return In case of success 0 is return, an errors, a errno in what - * went wrong. - * - * @ingroup ntlm_core - */ - -int -heim_ntlm_encode_type1(const struct ntlm_type1 *type1, struct ntlm_buf *data) -{ - krb5_error_code ret; - struct sec_buffer domain, hostname; - krb5_storage *out; - uint32_t base, flags; - int ucs2 = 0; - - flags = type1->flags; - base = 16; - - if (flags & NTLM_NEG_UNICODE) - ucs2 = 1; - - if (type1->domain) { - base += SIZE_SEC_BUFFER; - flags |= NTLM_OEM_SUPPLIED_DOMAIN; - } - if (type1->hostname) { - base += SIZE_SEC_BUFFER; - flags |= NTLM_OEM_SUPPLIED_WORKSTATION; - } - if (flags & NTLM_NEG_VERSION) - base += SIZE_OS_VERSION; /* os */ - - if (type1->domain) { - domain.offset = base; - domain.length = len_string(ucs2, type1->domain); - domain.allocated = domain.length; - } else { - domain.offset = 0; - domain.length = 0; - domain.allocated = 0; - } - - if (type1->hostname) { - hostname.offset = domain.allocated + domain.offset; - hostname.length = len_string(ucs2, type1->hostname); - hostname.allocated = hostname.length; - } else { - hostname.offset = 0; - hostname.length = 0; - hostname.allocated = 0; - } - - out = krb5_storage_emem(); - if (out == NULL) - return ENOMEM; - - krb5_storage_set_byteorder(out, KRB5_STORAGE_BYTEORDER_LE); - CHECK_SIZE(krb5_storage_write(out, ntlmsigature, sizeof(ntlmsigature)), - sizeof(ntlmsigature)); - CHECK(krb5_store_uint32(out, 1), 0); - CHECK(krb5_store_uint32(out, flags), 0); - - CHECK(store_sec_buffer(out, &domain), 0); - CHECK(store_sec_buffer(out, &hostname), 0); - - if (flags & NTLM_NEG_VERSION) { - CHECK(encode_os_version(out), 0); - } - if (type1->domain) - CHECK(put_string(out, ucs2, type1->domain), 0); - if (type1->hostname) - CHECK(put_string(out, ucs2, type1->hostname), 0); - - { - krb5_data d; - ret = krb5_storage_to_data(out, &d); - data->data = d.data; - data->length = d.length; - } -out: - krb5_storage_free(out); - - return ret; -} - -/** - * Frees the ntlm_type2 message - * - * @param data message to be freed - * - * @ingroup ntlm_core - */ - -void -heim_ntlm_free_type2(struct ntlm_type2 *data) -{ - if (data->targetname) - free(data->targetname); - heim_ntlm_free_buf(&data->targetinfo); - memset(data, 0, sizeof(*data)); -} - -int -heim_ntlm_decode_type2(const struct ntlm_buf *buf, struct ntlm_type2 *type2) -{ - krb5_error_code ret; - unsigned char sig[8]; - uint32_t type, ctx[2]; - struct sec_buffer targetname, targetinfo; - krb5_storage *in; - int ucs2 = 0; - - memset(type2, 0, sizeof(*type2)); - - in = krb5_storage_from_readonly_mem(buf->data, buf->length); - if (in == NULL) { - ret = ENOMEM; - goto out; - } - krb5_storage_set_byteorder(in, KRB5_STORAGE_BYTEORDER_LE); - - CHECK_SIZE(krb5_storage_read(in, sig, sizeof(sig)), sizeof(sig)); - CHECK(ct_memcmp(ntlmsigature, sig, sizeof(ntlmsigature)), 0); - CHECK(krb5_ret_uint32(in, &type), 0); - CHECK(type, 2); - - CHECK(ret_sec_buffer(in, &targetname), 0); - CHECK(krb5_ret_uint32(in, &type2->flags), 0); - if (type2->flags & NTLM_NEG_UNICODE) - ucs2 = 1; - CHECK_SIZE(krb5_storage_read(in, type2->challenge, sizeof(type2->challenge)), - sizeof(type2->challenge)); - CHECK(krb5_ret_uint32(in, &ctx[0]), 0); /* context */ - CHECK(krb5_ret_uint32(in, &ctx[1]), 0); - CHECK(ret_sec_buffer(in, &targetinfo), 0); - /* os version */ - if (type2->flags & NTLM_NEG_VERSION) { - CHECK(krb5_ret_uint32(in, &type2->os[0]), 0); - CHECK(krb5_ret_uint32(in, &type2->os[1]), 0); - } - - CHECK(ret_sec_string(in, ucs2, &targetname, &type2->targetname), 0); - CHECK(ret_buf(in, &targetinfo, &type2->targetinfo), 0); - ret = 0; - -out: - if (in) - krb5_storage_free(in); - if (ret) - heim_ntlm_free_type2(type2); - - return ret; -} - -/** - * Encodes an ntlm_type2 message. - * - * @param type2 the ntlm_type2 message to encode. - * @param data is the return buffer with the encoded message, should be - * freed with heim_ntlm_free_buf(). - * - * @return In case of success 0 is return, an errors, a errno in what - * went wrong. - * - * @ingroup ntlm_core - */ - -int -heim_ntlm_encode_type2(const struct ntlm_type2 *type2, struct ntlm_buf *data) -{ - struct sec_buffer targetname, targetinfo; - krb5_error_code ret; - krb5_storage *out = NULL; - uint32_t base; - int ucs2 = 0; - - base = 48; - - if (type2->flags & NTLM_NEG_VERSION) - base += SIZE_OS_VERSION; - - if (type2->flags & NTLM_NEG_UNICODE) - ucs2 = 1; - - targetname.offset = base; - targetname.length = len_string(ucs2, type2->targetname); - targetname.allocated = targetname.length; - - targetinfo.offset = targetname.allocated + targetname.offset; - targetinfo.length = type2->targetinfo.length; - targetinfo.allocated = type2->targetinfo.length; - - out = krb5_storage_emem(); - if (out == NULL) - return ENOMEM; - - krb5_storage_set_byteorder(out, KRB5_STORAGE_BYTEORDER_LE); - CHECK_SIZE(krb5_storage_write(out, ntlmsigature, sizeof(ntlmsigature)), - sizeof(ntlmsigature)); - CHECK(krb5_store_uint32(out, 2), 0); - CHECK(store_sec_buffer(out, &targetname), 0); - CHECK(krb5_store_uint32(out, type2->flags), 0); - CHECK_SIZE(krb5_storage_write(out, type2->challenge, sizeof(type2->challenge)), - sizeof(type2->challenge)); - CHECK(krb5_store_uint32(out, 0), 0); /* context */ - CHECK(krb5_store_uint32(out, 0), 0); - CHECK(store_sec_buffer(out, &targetinfo), 0); - /* os version */ - if (type2->flags & NTLM_NEG_VERSION) { - CHECK(encode_os_version(out), 0); - } - CHECK(put_string(out, ucs2, type2->targetname), 0); - CHECK_SIZE(krb5_storage_write(out, type2->targetinfo.data, - type2->targetinfo.length), - type2->targetinfo.length); - - { - krb5_data d; - ret = krb5_storage_to_data(out, &d); - data->data = d.data; - data->length = d.length; - } - -out: - krb5_storage_free(out); - - return ret; -} - -/** - * Frees the ntlm_type3 message - * - * @param data message to be freed - * - * @ingroup ntlm_core - */ - -void -heim_ntlm_free_type3(struct ntlm_type3 *data) -{ - heim_ntlm_free_buf(&data->lm); - heim_ntlm_free_buf(&data->ntlm); - if (data->targetname) - free(data->targetname); - if (data->username) - free(data->username); - if (data->ws) - free(data->ws); - heim_ntlm_free_buf(&data->sessionkey); - memset(data, 0, sizeof(*data)); -} - -/* - * - */ - -int -heim_ntlm_decode_type3(const struct ntlm_buf *buf, - int ucs2, - struct ntlm_type3 *type3) -{ - krb5_error_code ret; - unsigned char sig[8]; - uint32_t type; - krb5_storage *in; - struct sec_buffer lm, ntlm, target, username, sessionkey, ws; - uint32_t min_offset = 0xffffffff; - - memset(type3, 0, sizeof(*type3)); - memset(&sessionkey, 0, sizeof(sessionkey)); - - in = krb5_storage_from_readonly_mem(buf->data, buf->length); - if (in == NULL) { - ret = ENOMEM; - goto out; - } - krb5_storage_set_byteorder(in, KRB5_STORAGE_BYTEORDER_LE); - - CHECK_SIZE(krb5_storage_read(in, sig, sizeof(sig)), sizeof(sig)); - CHECK(ct_memcmp(ntlmsigature, sig, sizeof(ntlmsigature)), 0); - CHECK(krb5_ret_uint32(in, &type), 0); - CHECK(type, 3); - CHECK(ret_sec_buffer(in, &lm), 0); - if (lm.allocated) - min_offset = min(min_offset, lm.offset); - CHECK(ret_sec_buffer(in, &ntlm), 0); - if (ntlm.allocated) - min_offset = min(min_offset, ntlm.offset); - CHECK(ret_sec_buffer(in, &target), 0); - min_offset = min(min_offset, target.offset); - CHECK(ret_sec_buffer(in, &username), 0); - min_offset = min(min_offset, username.offset); - CHECK(ret_sec_buffer(in, &ws), 0); - if (ws.allocated) - min_offset = min(min_offset, ws.offset); - - if (min_offset >= 52) { - CHECK(ret_sec_buffer(in, &sessionkey), 0); - min_offset = min(min_offset, sessionkey.offset); - CHECK(krb5_ret_uint32(in, &type3->flags), 0); - } - if (min_offset >= 52 + SIZE_SEC_BUFFER + 4 + SIZE_OS_VERSION) { - CHECK(krb5_ret_uint32(in, &type3->os[0]), 0); - CHECK(krb5_ret_uint32(in, &type3->os[1]), 0); - } - if (min_offset >= 52 + SIZE_SEC_BUFFER + 4 + SIZE_OS_VERSION + 16) { - type3->mic_offset = 52 + SIZE_SEC_BUFFER + 4 + SIZE_OS_VERSION; - CHECK_SIZE(krb5_storage_read(in, type3->mic, sizeof(type3->mic)), sizeof(type3->mic)); - } else - type3->mic_offset = 0; - CHECK(ret_buf(in, &lm, &type3->lm), 0); - CHECK(ret_buf(in, &ntlm, &type3->ntlm), 0); - CHECK(ret_sec_string(in, ucs2, &target, &type3->targetname), 0); - CHECK(ret_sec_string(in, ucs2, &username, &type3->username), 0); - CHECK(ret_sec_string(in, ucs2, &ws, &type3->ws), 0); - if (sessionkey.offset) - CHECK(ret_buf(in, &sessionkey, &type3->sessionkey), 0); - -out: - if (in) - krb5_storage_free(in); - if (ret) - heim_ntlm_free_type3(type3); - - return ret; -} - -/** - * Encodes an ntlm_type3 message. - * - * @param type3 the ntlm_type3 message to encode. - * @param data is the return buffer with the encoded message, should be - * @param[out] mic_offset offset of message integrity code - * freed with heim_ntlm_free_buf(). - * - * @return In case of success 0 is return, an errors, a errno in what - * went wrong. - * - * @ingroup ntlm_core - */ - -int -heim_ntlm_encode_type3(const struct ntlm_type3 *type3, struct ntlm_buf *data, size_t *mic_offset) -{ - struct sec_buffer lm, ntlm, target, username, sessionkey, ws; - krb5_error_code ret; - krb5_storage *out = NULL; - uint32_t base; - int ucs2 = 0; - - memset(&lm, 0, sizeof(lm)); - memset(&ntlm, 0, sizeof(ntlm)); - memset(&target, 0, sizeof(target)); - memset(&username, 0, sizeof(username)); - memset(&ws, 0, sizeof(ws)); - memset(&sessionkey, 0, sizeof(sessionkey)); - - base = 52; - - base += 8; /* sessionkey sec buf */ - base += 4; /* flags */ - if (type3->flags & NTLM_NEG_VERSION) - base += SIZE_OS_VERSION; /* os flags */ - - if (mic_offset) { - *mic_offset = base; - base += 16; - } - - if (type3->flags & NTLM_NEG_UNICODE) - ucs2 = 1; - - target.offset = base; - target.length = len_string(ucs2, type3->targetname); - target.allocated = target.length; - - username.offset = target.offset + target.allocated; - username.length = len_string(ucs2, type3->username); - username.allocated = username.length; - - ws.offset = username.offset + username.allocated; - ws.length = len_string(ucs2, type3->ws); - ws.allocated = ws.length; - - lm.offset = ws.offset + ws.allocated; - lm.length = type3->lm.length; - lm.allocated = type3->lm.length; - - ntlm.offset = lm.offset + lm.allocated; - ntlm.length = type3->ntlm.length; - ntlm.allocated = ntlm.length; - - sessionkey.offset = ntlm.offset + ntlm.allocated; - sessionkey.length = type3->sessionkey.length; - sessionkey.allocated = type3->sessionkey.length; - - out = krb5_storage_emem(); - if (out == NULL) - return ENOMEM; - - krb5_storage_set_byteorder(out, KRB5_STORAGE_BYTEORDER_LE); - CHECK_SIZE(krb5_storage_write(out, ntlmsigature, sizeof(ntlmsigature)), - sizeof(ntlmsigature)); - CHECK(krb5_store_uint32(out, 3), 0); - - CHECK(store_sec_buffer(out, &lm), 0); - CHECK(store_sec_buffer(out, &ntlm), 0); - CHECK(store_sec_buffer(out, &target), 0); - CHECK(store_sec_buffer(out, &username), 0); - CHECK(store_sec_buffer(out, &ws), 0); - CHECK(store_sec_buffer(out, &sessionkey), 0); - CHECK(krb5_store_uint32(out, type3->flags), 0); - - /* os version */ - if (type3->flags & NTLM_NEG_VERSION) { - CHECK(encode_os_version(out), 0); - } - - if (mic_offset) { - static const uint8_t buf[16] = { 0 }; - CHECK_SIZE(krb5_storage_write(out, buf, sizeof(buf)), sizeof(buf)); - } - - CHECK(put_string(out, ucs2, type3->targetname), 0); - CHECK(put_string(out, ucs2, type3->username), 0); - CHECK(put_string(out, ucs2, type3->ws), 0); - CHECK(put_buf(out, &type3->lm), 0); - CHECK(put_buf(out, &type3->ntlm), 0); - CHECK(put_buf(out, &type3->sessionkey), 0); - - { - krb5_data d; - ret = krb5_storage_to_data(out, &d); - data->data = d.data; - data->length = d.length; - } - -out: - krb5_storage_free(out); - - return ret; -} - - -/* - * - */ - -static void -splitandenc(unsigned char *hash, - unsigned char *challenge, - unsigned char *answer) -{ - EVP_CIPHER_CTX ctx; - unsigned char key[8]; - - key[0] = hash[0]; - key[1] = (hash[0] << 7) | (hash[1] >> 1); - key[2] = (hash[1] << 6) | (hash[2] >> 2); - key[3] = (hash[2] << 5) | (hash[3] >> 3); - key[4] = (hash[3] << 4) | (hash[4] >> 4); - key[5] = (hash[4] << 3) | (hash[5] >> 5); - key[6] = (hash[5] << 2) | (hash[6] >> 6); - key[7] = (hash[6] << 1); - - EVP_CIPHER_CTX_init(&ctx); - - EVP_CipherInit_ex(&ctx, EVP_des_cbc(), NULL, key, NULL, 1); - EVP_Cipher(&ctx, answer, challenge, 8); - EVP_CIPHER_CTX_cleanup(&ctx); - memset_s(key, sizeof(key), 0, sizeof(key)); -} - -/** - * Calculate the NTLM key, the password is assumed to be in UTF8. - * - * @param password password to calcute the key for. - * @param key calcuted key, should be freed with heim_ntlm_free_buf(). - * - * @return In case of success 0 is return, an errors, a errno in what - * went wrong. - * - * @ingroup ntlm_core - */ - -int -heim_ntlm_nt_key(const char *password, struct ntlm_buf *key) -{ - struct ntlm_buf buf; - EVP_MD_CTX *m; - int ret; - - key->data = malloc(MD4_DIGEST_LENGTH); - if (key->data == NULL) - return ENOMEM; - key->length = MD4_DIGEST_LENGTH; - - ret = ascii2ucs2le(password, 0, &buf); - if (ret) { - heim_ntlm_free_buf(key); - return ret; - } - - m = EVP_MD_CTX_create(); - if (m == NULL) { - heim_ntlm_free_buf(key); - heim_ntlm_free_buf(&buf); - return ENOMEM; - } - - EVP_DigestInit_ex(m, EVP_md4(), NULL); - EVP_DigestUpdate(m, buf.data, buf.length); - EVP_DigestFinal_ex(m, key->data, NULL); - EVP_MD_CTX_destroy(m); - - heim_ntlm_free_buf(&buf); - return 0; -} - -/** - * Calculate NTLMv1 response hash - * - * @param key the ntlm v1 key - * @param len length of key - * @param challenge sent by the server - * @param answer calculated answer, should be freed with heim_ntlm_free_buf(). - * - * @return In case of success 0 is return, an errors, a errno in what - * went wrong. - * - * @ingroup ntlm_core - */ - -int -heim_ntlm_calculate_ntlm1(void *key, size_t len, - unsigned char challenge[8], - struct ntlm_buf *answer) -{ - unsigned char res[21]; - - if (len != MD4_DIGEST_LENGTH) - return HNTLM_ERR_INVALID_LENGTH; - - memcpy(res, key, len); - memset(&res[MD4_DIGEST_LENGTH], 0, sizeof(res) - MD4_DIGEST_LENGTH); - - answer->data = malloc(24); - if (answer->data == NULL) - return ENOMEM; - answer->length = 24; - - splitandenc(&res[0], challenge, ((unsigned char *)answer->data) + 0); - splitandenc(&res[7], challenge, ((unsigned char *)answer->data) + 8); - splitandenc(&res[14], challenge, ((unsigned char *)answer->data) + 16); - - return 0; -} - -int -heim_ntlm_v1_base_session(void *key, size_t len, - struct ntlm_buf *session) -{ - EVP_MD_CTX *m; - - session->length = MD4_DIGEST_LENGTH; - session->data = malloc(session->length); - if (session->data == NULL) { - session->length = 0; - return ENOMEM; - } - - m = EVP_MD_CTX_create(); - if (m == NULL) { - heim_ntlm_free_buf(session); - return ENOMEM; - } - EVP_DigestInit_ex(m, EVP_md4(), NULL); - EVP_DigestUpdate(m, key, len); - EVP_DigestFinal_ex(m, session->data, NULL); - EVP_MD_CTX_destroy(m); - - return 0; -} - -int -heim_ntlm_v2_base_session(void *key, size_t len, - struct ntlm_buf *ntlmResponse, - struct ntlm_buf *session) -{ - unsigned int hmaclen; - HMAC_CTX c; - - if (ntlmResponse->length <= 16) - return HNTLM_ERR_INVALID_LENGTH; - - session->data = malloc(16); - if (session->data == NULL) - return ENOMEM; - session->length = 16; - - /* Note: key is the NTLMv2 key */ - HMAC_CTX_init(&c); - if (HMAC_Init_ex(&c, key, len, EVP_md5(), NULL) == 0) { - HMAC_CTX_cleanup(&c); - return ENOMEM; - } - HMAC_Update(&c, ntlmResponse->data, 16); - HMAC_Final(&c, session->data, &hmaclen); - HMAC_CTX_cleanup(&c); - - return 0; -} - - -int -heim_ntlm_keyex_wrap(struct ntlm_buf *base_session, - struct ntlm_buf *session, - struct ntlm_buf *encryptedSession) -{ - EVP_CIPHER_CTX c; - int ret; - - if (base_session->length != MD4_DIGEST_LENGTH) - return HNTLM_ERR_INVALID_LENGTH; - - session->length = MD4_DIGEST_LENGTH; - session->data = malloc(session->length); - if (session->data == NULL) { - session->length = 0; - return ENOMEM; - } - encryptedSession->length = MD4_DIGEST_LENGTH; - encryptedSession->data = malloc(encryptedSession->length); - if (encryptedSession->data == NULL) { - heim_ntlm_free_buf(session); - encryptedSession->length = 0; - return ENOMEM; - } - - EVP_CIPHER_CTX_init(&c); - - ret = EVP_CipherInit_ex(&c, EVP_rc4(), NULL, base_session->data, NULL, 1); - if (ret != 1) { - EVP_CIPHER_CTX_cleanup(&c); - heim_ntlm_free_buf(encryptedSession); - heim_ntlm_free_buf(session); - return HNTLM_ERR_CRYPTO; - } - - if (RAND_bytes(session->data, session->length) != 1) { - EVP_CIPHER_CTX_cleanup(&c); - heim_ntlm_free_buf(encryptedSession); - heim_ntlm_free_buf(session); - return HNTLM_ERR_RAND; - } - - EVP_Cipher(&c, encryptedSession->data, session->data, encryptedSession->length); - EVP_CIPHER_CTX_cleanup(&c); - - return 0; - - - -} - -/** - * Generates an NTLMv1 session random with assosited session master key. - * - * @param key the ntlm v1 key - * @param len length of key - * @param session generated session nonce, should be freed with heim_ntlm_free_buf(). - * @param master calculated session master key, should be freed with heim_ntlm_free_buf(). - * - * @return In case of success 0 is return, an errors, a errno in what - * went wrong. - * - * @ingroup ntlm_core - */ - -int -heim_ntlm_build_ntlm1_master(void *key, size_t len, - struct ntlm_buf *session, - struct ntlm_buf *master) -{ - struct ntlm_buf sess; - int ret; - - ret = heim_ntlm_v1_base_session(key, len, &sess); - if (ret) - return ret; - - ret = heim_ntlm_keyex_wrap(&sess, session, master); - heim_ntlm_free_buf(&sess); - - return ret; -} - -/** - * Generates an NTLMv2 session random with associated session master key. - * - * @param key the NTLMv2 key - * @param len length of key - * @param blob the NTLMv2 "blob" - * @param session generated session nonce, should be freed with heim_ntlm_free_buf(). - * @param master calculated session master key, should be freed with heim_ntlm_free_buf(). - * - * @return In case of success 0 is return, an errors, a errno in what - * went wrong. - * - * @ingroup ntlm_core - */ - - -int -heim_ntlm_build_ntlm2_master(void *key, size_t len, - struct ntlm_buf *blob, - struct ntlm_buf *session, - struct ntlm_buf *master) -{ - struct ntlm_buf sess; - int ret; - - ret = heim_ntlm_v2_base_session(key, len, blob, &sess); - if (ret) - return ret; - - ret = heim_ntlm_keyex_wrap(&sess, session, master); - heim_ntlm_free_buf(&sess); - - return ret; -} - -/** - * Given a key and encrypted session, unwrap the session key - * - * @param baseKey the sessionBaseKey - * @param encryptedSession encrypted session, type3.session field. - * @param session generated session nonce, should be freed with heim_ntlm_free_buf(). - * - * @return In case of success 0 is return, an errors, a errno in what - * went wrong. - * - * @ingroup ntlm_core - */ - -int -heim_ntlm_keyex_unwrap(struct ntlm_buf *baseKey, - struct ntlm_buf *encryptedSession, - struct ntlm_buf *session) -{ - EVP_CIPHER_CTX c; - - memset(session, 0, sizeof(*session)); - - if (encryptedSession->length != MD4_DIGEST_LENGTH) - return HNTLM_ERR_INVALID_LENGTH; - if (baseKey->length != MD4_DIGEST_LENGTH) - return HNTLM_ERR_INVALID_LENGTH; - - session->length = MD4_DIGEST_LENGTH; - session->data = malloc(session->length); - if (session->data == NULL) { - session->length = 0; - return ENOMEM; - } - EVP_CIPHER_CTX_init(&c); - - if (EVP_CipherInit_ex(&c, EVP_rc4(), NULL, baseKey->data, NULL, 0) != 1) { - EVP_CIPHER_CTX_cleanup(&c); - heim_ntlm_free_buf(session); - return HNTLM_ERR_CRYPTO; - } - - EVP_Cipher(&c, session->data, encryptedSession->data, session->length); - EVP_CIPHER_CTX_cleanup(&c); - - return 0; -} - - -/** - * Generates an NTLMv2 session key. - * - * @param key the ntlm key - * @param len length of key - * @param username name of the user, as sent in the message, assumed to be in UTF8. - * @param target the name of the target, assumed to be in UTF8. - * @param upper_case_target upper case the target, should not be used only for legacy systems - * @param ntlmv2 the ntlmv2 session key - * - * @return 0 on success, or an error code on failure. - * - * @ingroup ntlm_core - */ - -int -heim_ntlm_ntlmv2_key(const void *key, size_t len, - const char *username, - const char *target, - int upper_case_target, - unsigned char ntlmv2[16]) -{ - int ret; - unsigned int hmaclen; - struct ntlm_buf buf; - HMAC_CTX c; - - HMAC_CTX_init(&c); - if (HMAC_Init_ex(&c, key, len, EVP_md5(), NULL) == 0) { - ret = ENOMEM; - goto out; - } - /* uppercase username and turn it into ucs2-le */ - ret = ascii2ucs2le(username, 1, &buf); - if (ret) - goto out; - HMAC_Update(&c, buf.data, buf.length); - free(buf.data); - /* turn target into ucs2-le */ - ret = ascii2ucs2le(target, upper_case_target, &buf); - if (ret) - goto out; - HMAC_Update(&c, buf.data, buf.length); - free(buf.data); - HMAC_Final(&c, ntlmv2, &hmaclen); - out: - HMAC_CTX_cleanup(&c); - memset(&c, 0, sizeof(c)); - - return ret; -} - -/* - * - */ - -#define NTTIME_EPOCH 0x019DB1DED53E8000LL - -uint64_t -heim_ntlm_unix2ts_time(time_t unix_time) -{ - long long wt; - wt = unix_time * (uint64_t)10000000 + (uint64_t)NTTIME_EPOCH; - return wt; -} - -time_t -heim_ntlm_ts2unixtime(uint64_t t) -{ - t = ((t - (uint64_t)NTTIME_EPOCH) / (uint64_t)10000000); - if (t > (((uint64_t)(time_t)(~(uint64_t)0)) >> 1)) - return 0; - return (time_t)t; -} - -/** - * Calculate LMv2 response - * - * @param key the ntlm key - * @param len length of key - * @param username name of the user, as sent in the message, assumed to be in UTF8. - * @param target the name of the target, assumed to be in UTF8. - * @param serverchallenge challenge as sent by the server in the type2 message. - * @param ntlmv2 calculated session key - * @param answer ntlm response answer, should be freed with heim_ntlm_free_buf(). - * - * @return In case of success 0 is return, an errors, a errno in what - * went wrong. - * - * @ingroup ntlm_core - */ - -int -heim_ntlm_calculate_lm2(const void *key, size_t len, - const char *username, - const char *target, - const unsigned char serverchallenge[8], - unsigned char ntlmv2[16], - struct ntlm_buf *answer) -{ - unsigned char clientchallenge[8]; - krb5_error_code ret; - - if (RAND_bytes(clientchallenge, sizeof(clientchallenge)) != 1) - return HNTLM_ERR_RAND; - - /* calculate ntlmv2 key */ - - heim_ntlm_ntlmv2_key(key, len, username, target, 0, ntlmv2); - - answer->data = malloc(24); - if (answer->data == NULL) - return ENOMEM; - answer->length = 24; - - ret = heim_ntlm_derive_ntlm2_sess(ntlmv2, clientchallenge, 8, - serverchallenge, answer->data); - if (ret == 0) - memcpy(((unsigned char *)answer->data) + 16, clientchallenge, 8); - - return ret; -} - - -/** - * Calculate NTLMv2 response - * - * @param key the ntlm key - * @param len length of key - * @param username name of the user, as sent in the message, assumed to be in UTF8. - * @param target the name of the target, assumed to be in UTF8. - * @param serverchallenge challenge as sent by the server in the type2 message. - * @param infotarget infotarget as sent by the server in the type2 message. - * @param ntlmv2 calculated session key - * @param answer ntlm response answer, should be freed with heim_ntlm_free_buf(). - * - * @return In case of success 0 is return, an errors, a errno in what - * went wrong. - * - * @ingroup ntlm_core - */ - -int -heim_ntlm_calculate_ntlm2(const void *key, size_t len, - const char *username, - const char *target, - const unsigned char serverchallenge[8], - const struct ntlm_buf *infotarget, - unsigned char ntlmv2[16], - struct ntlm_buf *answer) -{ - krb5_error_code ret; - krb5_data data; - unsigned char ntlmv2answer[16]; - krb5_storage *sp; - unsigned char clientchallenge[8]; - uint64_t t; - - t = heim_ntlm_unix2ts_time(time(NULL)); - - if (RAND_bytes(clientchallenge, sizeof(clientchallenge)) != 1) - return HNTLM_ERR_RAND; - - /* calculate ntlmv2 key */ - - heim_ntlm_ntlmv2_key(key, len, username, target, 0, ntlmv2); - - /* calculate and build ntlmv2 answer */ - - sp = krb5_storage_emem(); - if (sp == NULL) - return ENOMEM; - krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE); - - CHECK(krb5_store_uint32(sp, 0x00000101), 0); - CHECK(krb5_store_uint32(sp, 0), 0); - /* timestamp le 64 bit ts */ - CHECK(krb5_store_uint32(sp, t & 0xffffffff), 0); - CHECK(krb5_store_uint32(sp, t >> 32), 0); - - CHECK_SIZE(krb5_storage_write(sp, clientchallenge, 8), 8); - - CHECK(krb5_store_uint32(sp, 0), 0); /* Z(4) */ - CHECK_SIZE(krb5_storage_write(sp, infotarget->data, infotarget->length), - infotarget->length); - - /* - * These last 4 bytes(Z(4)) are not documented by MicroSoft and - * SnowLeopard doesn't send them, Lion expected them to be there, - * so we have to continue to send them. That is ok, since everyone - * else (except Snow) seems to do that too. - */ - CHECK(krb5_store_uint32(sp, 0), 0); /* Z(4) */ - - CHECK(krb5_storage_to_data(sp, &data), 0); - krb5_storage_free(sp); - sp = NULL; - - ret = heim_ntlm_derive_ntlm2_sess(ntlmv2, data.data, data.length, - serverchallenge, ntlmv2answer); - if (ret) - return ret; - - sp = krb5_storage_emem(); - if (sp == NULL) { - krb5_data_free(&data); - return ENOMEM; - } - - CHECK_SIZE(krb5_storage_write(sp, ntlmv2answer, 16), 16); - CHECK_SIZE(krb5_storage_write(sp, data.data, data.length), data.length); - krb5_data_free(&data); - - CHECK(krb5_storage_to_data(sp, &data), 0); - krb5_storage_free(sp); - sp = NULL; - - answer->data = data.data; - answer->length = data.length; - - return 0; -out: - if (sp) - krb5_storage_free(sp); - return ret; -} - -static const int authtimediff = 3600 * 2; /* 2 hours */ - -static int -verify_ntlm2(const void *key, size_t len, - const char *username, - const char *target, - int upper_case_target, - time_t now, - const unsigned char serverchallenge[8], - const struct ntlm_buf *answer, - struct ntlm_buf *infotarget, - unsigned char ntlmv2[16]) -{ - krb5_error_code ret; - unsigned char clientanswer[16]; - unsigned char clientnonce[8]; - unsigned char serveranswer[16]; - krb5_storage *sp; - uint64_t t; - time_t authtime; - uint32_t temp; - - infotarget->length = 0; - infotarget->data = NULL; - - if (answer->length < 16) - return HNTLM_ERR_INVALID_LENGTH; - - if (now == 0) - now = time(NULL); - - /* calculate ntlmv2 key */ - - heim_ntlm_ntlmv2_key(key, len, username, target, upper_case_target, ntlmv2); - - /* calculate and build ntlmv2 answer */ - - sp = krb5_storage_from_readonly_mem(answer->data, answer->length); - if (sp == NULL) - return ENOMEM; - krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE); - - CHECK_SIZE(krb5_storage_read(sp, clientanswer, 16), 16); - - CHECK(krb5_ret_uint32(sp, &temp), 0); - CHECK(temp, 0x00000101); - CHECK(krb5_ret_uint32(sp, &temp), 0); - CHECK(temp, 0); - /* timestamp le 64 bit ts */ - CHECK(krb5_ret_uint32(sp, &temp), 0); - t = temp; - CHECK(krb5_ret_uint32(sp, &temp), 0); - t |= ((uint64_t)temp)<< 32; - - authtime = heim_ntlm_ts2unixtime(t); - - if (labs((int)(authtime - now)) > authtimediff) { - ret = HNTLM_ERR_TIME_SKEW; - goto out; - } - - /* client challenge */ - CHECK_SIZE(krb5_storage_read(sp, clientnonce, 8), 8); - - CHECK(krb5_ret_uint32(sp, &temp), 0); /* Z(4) */ - - /* let pick up targetinfo */ - infotarget->length = answer->length - (size_t)krb5_storage_seek(sp, 0, SEEK_CUR); - if (infotarget->length < 4) { - ret = HNTLM_ERR_INVALID_LENGTH; - goto out; - } - infotarget->data = malloc(infotarget->length); - if (infotarget->data == NULL) { - ret = ENOMEM; - goto out; - } - CHECK_SIZE(krb5_storage_read(sp, infotarget->data, infotarget->length), - infotarget->length); - - krb5_storage_free(sp); - sp = NULL; - - if (answer->length < 16) { - ret = HNTLM_ERR_INVALID_LENGTH; - goto out; - } - - ret = heim_ntlm_derive_ntlm2_sess(ntlmv2, - ((unsigned char *)answer->data) + 16, - answer->length - 16, - serverchallenge, - serveranswer); - if (ret) - goto out; - - if (ct_memcmp(serveranswer, clientanswer, 16) != 0) { - heim_ntlm_free_buf(infotarget); - return HNTLM_ERR_AUTH; - } - - return 0; -out: - heim_ntlm_free_buf(infotarget); - if (sp) - krb5_storage_free(sp); - return ret; -} - -/** - * Verify NTLMv2 response. - * - * @param key the ntlm key - * @param len length of key - * @param username name of the user, as sent in the message, assumed to be in UTF8. - * @param target the name of the target, assumed to be in UTF8. - * @param now the time now (0 if the library should pick it up itself) - * @param serverchallenge challenge as sent by the server in the type2 message. - * @param answer ntlm response answer, should be freed with heim_ntlm_free_buf(). - * @param infotarget infotarget as sent by the server in the type2 message. - * @param ntlmv2 calculated session key - * - * @return In case of success 0 is return, an errors, a errno in what - * went wrong. - * - * @ingroup ntlm_core - */ - -int -heim_ntlm_verify_ntlm2(const void *key, size_t len, - const char *username, - const char *target, - time_t now, - const unsigned char serverchallenge[8], - const struct ntlm_buf *answer, - struct ntlm_buf *infotarget, - unsigned char ntlmv2[16]) -{ - int ret; - - /** - * First check with the domain as the client passed it to the function. - */ - - ret = verify_ntlm2(key, len, username, target, 0, now, - serverchallenge, answer, infotarget, ntlmv2); - - /** - * Second check with domain uppercased. - */ - - if (ret) - ret = verify_ntlm2(key, len, username, target, 1, now, - serverchallenge, answer, infotarget, ntlmv2); - - /** - * Third check with empty domain. - */ - if (ret) - ret = verify_ntlm2(key, len, username, "", 0, now, - serverchallenge, answer, infotarget, ntlmv2); - return ret; -} - -/* - * Calculate the NTLM2 Session Response - * - * @param clnt_nonce client nonce - * @param svr_chal server challage - * @param ntlm2_hash ntlm hash - * @param lm The LM response, should be freed with heim_ntlm_free_buf(). - * @param ntlm The NTLM response, should be freed with heim_ntlm_free_buf(). - * - * @return In case of success 0 is return, an errors, a errno in what - * went wrong. - * - * @ingroup ntlm_core - */ - -int -heim_ntlm_calculate_ntlm2_sess(const unsigned char clnt_nonce[8], - const unsigned char svr_chal[8], - const unsigned char ntlm_hash[16], - struct ntlm_buf *lm, - struct ntlm_buf *ntlm) -{ - unsigned char ntlm2_sess_hash[8]; - unsigned char res[21], *resp; - int code; - - code = heim_ntlm_calculate_ntlm2_sess_hash(clnt_nonce, svr_chal, - ntlm2_sess_hash); - if (code) { - return code; - } - - lm->data = malloc(24); - if (lm->data == NULL) { - return ENOMEM; - } - lm->length = 24; - - ntlm->data = malloc(24); - if (ntlm->data == NULL) { - free(lm->data); - lm->data = NULL; - return ENOMEM; - } - ntlm->length = 24; - - /* first setup the lm resp */ - memset(lm->data, 0, 24); - memcpy(lm->data, clnt_nonce, 8); - - memset(res, 0, sizeof(res)); - memcpy(res, ntlm_hash, 16); - - resp = ntlm->data; - splitandenc(&res[0], ntlm2_sess_hash, resp + 0); - splitandenc(&res[7], ntlm2_sess_hash, resp + 8); - splitandenc(&res[14], ntlm2_sess_hash, resp + 16); - - return 0; -} - - -/* - * Calculate the NTLM2 Session "Verifier" - * - * @param clnt_nonce client nonce - * @param svr_chal server challage - * @param hash The NTLM session verifier - * - * @return In case of success 0 is return, an errors, a errno in what - * went wrong. - * - * @ingroup ntlm_core - */ - -int -heim_ntlm_calculate_ntlm2_sess_hash(const unsigned char clnt_nonce[8], - const unsigned char svr_chal[8], - unsigned char verifier[8]) -{ - unsigned char ntlm2_sess_hash[MD5_DIGEST_LENGTH]; - EVP_MD_CTX *m; - - m = EVP_MD_CTX_create(); - if (m == NULL) - return ENOMEM; - - EVP_DigestInit_ex(m, EVP_md5(), NULL); - EVP_DigestUpdate(m, svr_chal, 8); /* session nonce part 1 */ - EVP_DigestUpdate(m, clnt_nonce, 8); /* session nonce part 2 */ - EVP_DigestFinal_ex(m, ntlm2_sess_hash, NULL); /* will only use first 8 bytes */ - EVP_MD_CTX_destroy(m); - - memcpy(verifier, ntlm2_sess_hash, 8); - - return 0; -} - - -/* - * Derive a NTLM2 session key - * - * @param sessionkey session key from domain controller - * @param clnt_nonce client nonce - * @param svr_chal server challenge - * @param derivedkey salted session key - * - * @return In case of success 0 is return, an errors, a errno in what - * went wrong. - * - * @ingroup ntlm_core - */ - -int -heim_ntlm_derive_ntlm2_sess(const unsigned char sessionkey[16], - const unsigned char *clnt_nonce, size_t clnt_nonce_length, - const unsigned char svr_chal[8], - unsigned char derivedkey[16]) -{ - unsigned int hmaclen; - HMAC_CTX c; - - /* HMAC(Ksession, serverchallenge || clientchallenge) */ - HMAC_CTX_init(&c); - if (HMAC_Init_ex(&c, sessionkey, 16, EVP_md5(), NULL) == 0) { - HMAC_CTX_cleanup(&c); - return ENOMEM; - } - HMAC_Update(&c, svr_chal, 8); - HMAC_Update(&c, clnt_nonce, clnt_nonce_length); - HMAC_Final(&c, derivedkey, &hmaclen); - HMAC_CTX_cleanup(&c); - memset(&c, 0, sizeof(c)); - return 0; -} diff --git a/lib/ntlm/ntlm_err.et b/lib/ntlm/ntlm_err.et deleted file mode 100644 index fd39aa31f..000000000 --- a/lib/ntlm/ntlm_err.et +++ /dev/null @@ -1,60 +0,0 @@ -# -# Error messages for the ntlm library -# -# This might look like a com_err file, but is not -# - -error_table ntlm - -prefix HNTLM_ERR -error_code DECODE, "Failed to decode packet" -error_code INVALID_LENGTH, "Input length invalid" -error_code CRYPTO, "Failed crypto primitive" -error_code RAND, "Random generator failed" -error_code AUTH, "NTLM authentication failed" -error_code TIME_SKEW, "Client time skewed to server" -error_code OEM, "Client set OEM string" -error_code MISSING_NAME_SEPARATOR, "missing @ or \\\\ in name" -error_code MISSING_BUFFER, "missing expected buffer" -error_code INVALID_APOP, "Invalid APOP response" -error_code INVALID_CRAM_MD5, "Invalid CRAM-MD5 response" -error_code INVALID_DIGEST_MD5, "Invalid DIGEST-MD5 response" -error_code INVALID_DIGEST_MD5_RSPAUTH, "Invalid DIGEST-MD5 rspauth" -error_code INVALID_CHANNEL_BINDINGS, "Invalid channel bindings" -error_code INVALID_MIC, "Invalid MIC" -error_code INVALID_SESSIONKEY, "Invalid session key" - - -# -# NTLM/GSS error codes -# -index 64 -error_code NOT_CONFIGURED, "NTLM not configured" - -error_code INVALID_CHALLANGE, "Invalid client challenge" -error_code INVALID_LMv1_RESPONSE, "Invalid client LMv1 response" -error_code INVALID_NT_RESPONSE, "Invalid client NT response" -error_code INVALID_LMv2_RESPONSE, "Invalid client LMv2 response" -error_code INVALID_NTv1_RESPONSE, "Invalid client NTv1 response" -error_code INVALID_NTv2_RESPONSE, "Invalid client NTv2 response" -error_code INVALID_NTv1_ANSWER, "Invalid client NTv1 answer" -error_code INVALID_NTv2_ANSWER, "Invalid client NTv2 answer" -error_code INVALID_SESSION_KEY, "Invalid session key" - -error_code INVALID_NO_GUEST, "Invalid guest login request" - -error_code NO_NETR_CONFIGURED, "No NETR configured" - - -# -# Scram errors -# -prefix HSCRAM_ERR -index 128 - -error_code INVALID_MESSAGE, "Invalid SCRAM message" -error_code INVALID_PROOF, "Invalid SCRAM proof" -error_code INVALID_ROLE, "Invalid SCRAM role" - - -end diff --git a/lib/ntlm/test_commonauth.c b/lib/ntlm/test_commonauth.c deleted file mode 100644 index 89b8c7e57..000000000 --- a/lib/ntlm/test_commonauth.c +++ /dev/null @@ -1,425 +0,0 @@ -/* - * Copyright (c) 2006 - 2008 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Portions Copyright (c) 2010 Apple Inc. 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 -#include -#include -#include -#include -#include "heim-auth.h" - -static int -test_sasl_digest_md5(void) -{ - heim_digest_t ctx; - const char *user, *challenge, *resp; - char *r; - - if ((ctx = heim_digest_create(1, HEIM_DIGEST_TYPE_AUTO)) == NULL) - abort(); - - if (heim_digest_parse_challenge(ctx, "realm=\"elwood.innosoft.com\",nonce=\"OA6MG9tEQGm2hh\",qop=\"auth\",algorithm=md5-sess,charset=utf-8")) - abort(); - - /* check that server detects changing QOP */ - if (!heim_digest_parse_response(ctx, "charset=utf-8,username=\"chris\",realm=\"elwood.innosoft.com\",nonce=\"OA6MG9tEQGm2hh\",nc=00000001,cnonce=\"OA6MHXh6VqTrRk\",digest-uri=\"imap/elwood.innosoft.com\",response=d388dad90d4bbd760a152321f2143af7,qop=auth-int")) - errx(1, "don't detect changing qop"); - - /* should pass */ - if (heim_digest_parse_response(ctx, "charset=utf-8,username=\"chris\",realm=\"elwood.innosoft.com\",nonce=\"OA6MG9tEQGm2hh\",nc=00000001,cnonce=\"OA6MHXh6VqTrRk\",digest-uri=\"imap/elwood.innosoft.com\",response=d388dad90d4bbd760a152321f2143af7,qop=auth")) - abort(); - - if ((user = heim_digest_get_key(ctx, "username")) == NULL) - abort(); - if (strcmp(user, "chris") != 0) - abort(); - - /* - * check password - */ - - heim_digest_set_key(ctx, "password", "secret"); - - if (heim_digest_verify(ctx, &r)) - abort(); - - if (strcmp(r, "rspauth=ea40f60335c427b5527b84dbabcdfffd") != 0) - abort(); - - free(r); - - /* - * Also check userhash - */ - - r = heim_digest_userhash("chris", "elwood.innosoft.com", "secret"); - if (strcmp(r, "eb5a750053e4d2c34aa84bbc9b0b6ee7") != 0) - abort(); - - heim_digest_set_key(ctx, "userhash", r); - free(r); - - if (heim_digest_verify(ctx, &r)) - abort(); - - if (strcmp(r, "rspauth=ea40f60335c427b5527b84dbabcdfffd") != 0) - abort(); - - free(r); - - /* check that it failes */ - - heim_digest_set_key(ctx, "username", "notright"); - heim_digest_set_key(ctx, "password", "secret"); - - if (heim_digest_verify(ctx, &r) == 0) - abort(); - - if ((user = heim_digest_get_key(ctx, "username")) == NULL) - abort(); - if (strcmp(user, "notright") != 0) - abort(); - - - /* Done */ - - heim_digest_release(ctx); - - - /* - * Check heim_digest_generate_challenge() - */ - - if ((ctx = heim_digest_create(1, HEIM_DIGEST_TYPE_RFC2831)) == NULL) - abort(); - - heim_digest_set_key(ctx, "serverRealm", "elwood.innosoft.com"); - heim_digest_set_key(ctx, "serverNonce", "OA6MG9tEQGm2hh"); - heim_digest_set_key(ctx, "serverQOP", "auth,auth-int"); - - challenge = heim_digest_generate_challenge(ctx); - if (challenge == NULL) - abort(); - - if (heim_digest_parse_challenge(ctx, challenge)) - abort(); - - /* check that server detects changing QOP */ - if (!heim_digest_parse_response(ctx, "charset=utf-8,username=\"chris\",realm=\"elwood.innosoft.com\",nonce=\"OA6MG9tEQGm2hh\",nc=00000001,cnonce=\"OA6MHXh6VqTrRk\",digest-uri=\"imap/elwood.innosoft.com\",response=d388dad90d4bbd760a152321f2143af7,qop=auth-conf")) - abort(); - - if (heim_digest_parse_response(ctx, "charset=utf-8,username=\"chris\",realm=\"elwood.innosoft.com\",nonce=\"OA6MG9tEQGm2hh\",nc=00000001,cnonce=\"OA6MHXh6VqTrRk\",digest-uri=\"imap/elwood.innosoft.com\",response=d388dad90d4bbd760a152321f2143af7,qop=auth")) - abort(); - - heim_digest_set_key(ctx, "password", "secret"); - - if (heim_digest_verify(ctx, &r)) - abort(); - - if (strcmp(r, "rspauth=ea40f60335c427b5527b84dbabcdfffd") != 0) - abort(); - - free(r); - - heim_digest_release(ctx); - - /* - * Validate heim_digest_service_response() - */ - - if ((ctx = heim_digest_create(1, HEIM_DIGEST_TYPE_RFC2831)) == NULL) - abort(); - - heim_digest_set_key(ctx, "clientNonce", "OA6MHXh6VqTrRk"); - heim_digest_set_key(ctx, "clientQOP", "auth"); - heim_digest_set_key(ctx, "clientNC", "00000001"); - heim_digest_set_key(ctx, "serverNonce", "OA6MG9tEQGm2hh"); - heim_digest_set_key(ctx, "clientURI", "imap/elwood.innosoft.com"); - heim_digest_set_key(ctx, "serverRealm", "elwood.innosoft.com"); - heim_digest_set_key(ctx, "serverNonce", "OA6MG9tEQGm2hh"); - heim_digest_set_key(ctx, "H(A1)", "a2549853149b0536f01f0b850c643c57"); - - resp = heim_digest_server_response(ctx); - - if (resp == NULL || strcmp(resp, "rspauth=ea40f60335c427b5527b84dbabcdfffd") != 0) - abort(); - - heim_digest_release(ctx); - - if ((ctx = heim_digest_create(1, HEIM_DIGEST_TYPE_RFC2831)) == NULL) - abort(); - - heim_digest_set_key(ctx, "clientNonce", "OA6MHXh6VqTrRk"); - heim_digest_set_key(ctx, "clientQOP", "auth"); - heim_digest_set_key(ctx, "clientNC", "00000001"); - heim_digest_set_key(ctx, "serverNonce", "OA6MG9tEQGm2hh"); - heim_digest_set_key(ctx, "clientURI", "imap/elwood.innosoft.com"); - heim_digest_set_key(ctx, "serverRealm", "elwood.innosoft.com"); - heim_digest_set_key(ctx, "serverNonce", "OA6MG9tEQGm2hh"); - heim_digest_set_key(ctx, "password", "secret"); - heim_digest_set_key(ctx, "username", "chris"); - - resp = heim_digest_server_response(ctx); - - if (resp == NULL || strcmp(resp, "rspauth=ea40f60335c427b5527b84dbabcdfffd") != 0) - abort(); - - heim_digest_release(ctx); - - return 0; -} - -static int -test_http_digest_md5(void) -{ - heim_digest_t ctx, ctx2; - const char *user, *chal, *resp; - char *serverresp, *serverresp2; - - if ((ctx = heim_digest_create(1, HEIM_DIGEST_TYPE_AUTO)) == NULL) - abort(); - - if (heim_digest_parse_challenge(ctx, "realm=\"testrealm@host.com\"," - "nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\"," - "opaque=\"5ccc069c403ebaf9f0171e9517f40e41\"")) - abort(); - - if (heim_digest_parse_response(ctx, "username=\"Mufasa\"," - "realm=\"testrealm@host.com\"," - "nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\"," - "uri=\"/dir/index.html\"," - "response=\"1949323746fe6a43ef61f9606e7febea\"," - "opaque=\"5ccc069c403ebaf9f0171e9517f40e41\"")) - abort(); - - if ((user = heim_digest_get_key(ctx, "username")) == NULL) - abort(); - if (strcmp(user, "Mufasa") != 0) - abort(); - - if ((user = heim_digest_get_key(ctx, "clientUsername")) == NULL) - abort(); - if (strcmp(user, "Mufasa") != 0) - abort(); - - heim_digest_set_key(ctx, "password", "CircleOfLife"); - - if (heim_digest_verify(ctx, NULL)) - abort(); - - /* Verify failure */ - - heim_digest_set_key(ctx, "username", "Oskar"); - - if (heim_digest_verify(ctx, NULL) == 0) - abort(); - - heim_digest_release(ctx); - - /* - * Check myself - */ - - /* server */ - if ((ctx = heim_digest_create(1, HEIM_DIGEST_TYPE_RFC2831)) == NULL) - abort(); - - heim_digest_set_key(ctx, "serverRealm", "myrealmhahaha"); - heim_digest_set_key(ctx, "serverQOP", "auth,auth-int"); - - chal = heim_digest_generate_challenge(ctx); - if (chal == NULL) - abort(); - - /* client */ - if ((ctx2 = heim_digest_create(1, HEIM_DIGEST_TYPE_RFC2831)) == NULL) - abort(); - - if (heim_digest_parse_challenge(ctx2, chal)) - abort(); - - heim_digest_set_key(ctx2, "username", "lha"); - heim_digest_set_key(ctx2, "password", "passw0rd"); - heim_digest_set_key(ctx2, "uri", "/uri"); - - resp = heim_digest_create_response(ctx2, &serverresp); - if (resp == NULL) - abort(); - - /* server */ - if (heim_digest_parse_response(ctx, resp)) - abort(); - - heim_digest_set_key(ctx, "password", "passw0rd"); - heim_digest_verify(ctx, &serverresp2); - - - /* client */ - if (strcmp(serverresp, serverresp2) != 0) - abort(); - - heim_digest_release(ctx); - heim_digest_release(ctx2); - - /* - * check prefix - */ - - if ((ctx = heim_digest_create(1, HEIM_DIGEST_TYPE_AUTO)) == NULL) - abort(); - - if (heim_digest_parse_challenge(ctx, "Digest realm=\"testrealm@host.com\"," - "nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\"," - "opaque=\"5ccc069c403ebaf9f0171e9517f40e41\"")) - abort(); - - heim_digest_release(ctx); - - /* - * check prefix - */ - - if ((ctx = heim_digest_create(1, HEIM_DIGEST_TYPE_AUTO)) == NULL) - abort(); - - if (heim_digest_parse_challenge(ctx, "Digest realm=\"testrealm@host.com\"," - "nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\"," - "opaque=\"5ccc069c403ebaf9f0171e9517f40e41\"")) - abort(); - - heim_digest_release(ctx); - - return 0; -} - -static int -test_cram_md5(void) -{ - const char *chal = "<1896.697170952@postoffice.reston.mci.net>"; - const char *secret = "tanstaaftanstaaf"; - const char *resp = "b913a602c7eda7a495b4e6e7334d3890"; - heim_CRAM_MD5_STATE state; - heim_cram_md5 ctx; - char *t; - - const uint8_t *prestate = (uint8_t *) - "\x87\x1E\x24\x10\xB4\x0C\x72\x5D\xA3\x95\x2D\x5B\x8B\xFC\xDD\xE1" - "\x29\x90\xCB\xA7\x66\xF6\xB3\x40\xE8\xAC\x48\x2C\xE4\xE3\xA4\x40"; - - /* - * Test prebuild blobs - */ - - if (sizeof(state) != 32) - abort(); - - heim_cram_md5_export("foo", &state); - - if (memcmp(prestate, &state, 32) != 0) - abort(); - - /* - * Check example - */ - - - if (heim_cram_md5_verify(chal, secret, resp) != 0) - abort(); - - - /* - * Do it ourself - */ - - t = heim_cram_md5_create(chal, secret); - if (t == NULL) - abort(); - - if (strcmp(resp, t) != 0) - abort(); - - heim_cram_md5_export(secret, &state); - /* here you can store the memcpy-ed version of state somewhere else */ - - ctx = heim_cram_md5_import(&state, sizeof(state)); - - memset(&state, 0, sizeof(state)); - - if (heim_cram_md5_verify_ctx(ctx, chal, resp) != 0) - abort(); - - heim_cram_md5_free(ctx); - - free(t); - - return 0; -} - -static int -test_apop(void) -{ - const char *chal = "<1896.697170952@dbc.mtview.ca.us>"; - const char *secret = "tanstaaf"; - const char *resp = "c4c9334bac560ecc979e58001b3e22fb"; - char *t; - - t = heim_apop_create(chal, secret); - if (t == NULL) - abort(); - - if (strcmp(resp, t) != 0) - abort(); - - if (heim_apop_verify(chal, secret, resp) != 0) - abort(); - - free(t); - - return 0; -} - - -int -main(int argc, char **argv) -{ - int ret = 0; - - ret |= test_sasl_digest_md5(); - ret |= test_http_digest_md5(); - ret |= test_cram_md5(); - ret |= test_apop(); - - return ret; -} diff --git a/lib/ntlm/test_ntlm.c b/lib/ntlm/test_ntlm.c deleted file mode 100644 index e7d723727..000000000 --- a/lib/ntlm/test_ntlm.c +++ /dev/null @@ -1,617 +0,0 @@ -/* - * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of KTH nor the names of its contributors may be - * used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#include -#include -#include -#include - -#include /* or */ -#include - -static int dumpdata_flag; - -static int -test_parse(void) -{ - const char *user = "foo", - *domain = "mydomain", - *hostname = "myhostname", - *password = "digestpassword", - *target = "DOMAIN"; - struct ntlm_type1 type1; - struct ntlm_type2 type2; - struct ntlm_type3 type3; - struct ntlm_buf data; - int ret, flags; - - memset(&type1, 0, sizeof(type1)); - - type1.flags = NTLM_NEG_UNICODE|NTLM_NEG_TARGET|NTLM_NEG_NTLM|NTLM_NEG_VERSION; - type1.domain = rk_UNCONST(domain); - type1.hostname = rk_UNCONST(hostname); - type1.os[0] = 0; - type1.os[1] = 0; - - ret = heim_ntlm_encode_type1(&type1, &data); - if (ret) - errx(1, "heim_ntlm_encode_type1"); - - memset(&type1, 0, sizeof(type1)); - - if (dumpdata_flag) - rk_dumpdata("ntlm-type1", data.data, data.length); - - ret = heim_ntlm_decode_type1(&data, &type1); - free(data.data); - if (ret) - errx(1, "heim_ntlm_encode_type1"); - - if (strcmp(type1.domain, domain) != 0) - errx(1, "parser got domain wrong: %s", type1.domain); - - if (strcmp(type1.hostname, hostname) != 0) - errx(1, "parser got hostname wrong: %s", type1.hostname); - - heim_ntlm_free_type1(&type1); - - /* - * - */ - - memset(&type2, 0, sizeof(type2)); - - flags = NTLM_NEG_UNICODE | NTLM_NEG_NTLM | NTLM_TARGET_DOMAIN; - type2.flags = flags; - - memset(type2.challenge, 0x7f, sizeof(type2.challenge)); - type2.targetname = rk_UNCONST(target); - type2.targetinfo.data = NULL; - type2.targetinfo.length = 0; - - ret = heim_ntlm_encode_type2(&type2, &data); - if (ret) - errx(1, "heim_ntlm_encode_type2"); - - memset(&type2, 0, sizeof(type2)); - - if (dumpdata_flag) - rk_dumpdata("ntlm-type2", data.data, data.length); - - ret = heim_ntlm_decode_type2(&data, &type2); - free(data.data); - if (ret) - errx(1, "heim_ntlm_decode_type2"); - - heim_ntlm_free_type2(&type2); - - /* - * - */ - - memset(&type3, 0, sizeof(type3)); - - type3.flags = flags; - type3.username = rk_UNCONST(user); - type3.targetname = rk_UNCONST(target); - type3.ws = rk_UNCONST("workstation"); - - { - struct ntlm_buf key; - heim_ntlm_nt_key(password, &key); - - heim_ntlm_calculate_ntlm1(key.data, key.length, - type2.challenge, - &type3.ntlm); - free(key.data); - } - - ret = heim_ntlm_encode_type3(&type3, &data, NULL); - if (ret) - errx(1, "heim_ntlm_encode_type3"); - - free(type3.ntlm.data); - - memset(&type3, 0, sizeof(type3)); - - if (dumpdata_flag) - rk_dumpdata("ntlm-type3", data.data, data.length); - - ret = heim_ntlm_decode_type3(&data, 1, &type3); - free(data.data); - if (ret) - errx(1, "heim_ntlm_decode_type3"); - - if (strcmp("workstation", type3.ws) != 0) - errx(1, "type3 ws wrong"); - - if (strcmp(target, type3.targetname) != 0) - errx(1, "type3 targetname wrong"); - - if (strcmp(user, type3.username) != 0) - errx(1, "type3 username wrong"); - - - heim_ntlm_free_type3(&type3); - - /* - * NTLMv2 - */ - - memset(&type2, 0, sizeof(type2)); - - flags = NTLM_NEG_UNICODE | NTLM_NEG_NTLM | NTLM_TARGET_DOMAIN; - type2.flags = flags; - - memset(type2.challenge, 0x7f, sizeof(type2.challenge)); - type2.targetname = rk_UNCONST(target); - type2.targetinfo.data = "\x00\x00"; - type2.targetinfo.length = 2; - - ret = heim_ntlm_encode_type2(&type2, &data); - if (ret) - errx(1, "heim_ntlm_encode_type2"); - - memset(&type2, 0, sizeof(type2)); - - ret = heim_ntlm_decode_type2(&data, &type2); - free(data.data); - if (ret) - errx(1, "heim_ntlm_decode_type2"); - - heim_ntlm_free_type2(&type2); - - return 0; -} - -static int -test_keys(void) -{ - const char - *username = "test", - *password = "test1234", - *target = "TESTNT"; - const unsigned char - serverchallenge[8] = "\x67\x7f\x1c\x55\x7a\x5e\xe9\x6c"; - struct ntlm_buf infotarget, infotarget2, answer, key; - unsigned char ntlmv2[16], ntlmv2_1[16]; - int ret; - - infotarget.length = 70; - infotarget.data = - "\x02\x00\x0c\x00\x54\x00\x45\x00\x53\x00\x54\x00\x4e\x00\x54\x00" - "\x01\x00\x0c\x00\x4d\x00\x45\x00\x4d\x00\x42\x00\x45\x00\x52\x00" - "\x03\x00\x1e\x00\x6d\x00\x65\x00\x6d\x00\x62\x00\x65\x00\x72\x00" - "\x2e\x00\x74\x00\x65\x00\x73\x00\x74\x00\x2e\x00\x63\x00\x6f" - "\x00\x6d\x00" - "\x00\x00\x00\x00"; - - answer.length = 0; - answer.data = NULL; - - heim_ntlm_nt_key(password, &key); - - ret = heim_ntlm_calculate_ntlm2(key.data, - key.length, - username, - target, - serverchallenge, - &infotarget, - ntlmv2, - &answer); - if (ret) - errx(1, "heim_ntlm_calculate_ntlm2"); - - ret = heim_ntlm_verify_ntlm2(key.data, - key.length, - username, - target, - 0, - serverchallenge, - &answer, - &infotarget2, - ntlmv2_1); - if (ret) - errx(1, "heim_ntlm_verify_ntlm2"); - - if (memcmp(ntlmv2, ntlmv2_1, sizeof(ntlmv2)) != 0) - errx(1, "ntlm master key not same"); - - if (infotarget.length > infotarget2.length) - errx(1, "infotarget length"); - - if (memcmp(infotarget.data, infotarget2.data, infotarget.length) != 0) - errx(1, "infotarget not the same"); - - free(key.data); - free(answer.data); - free(infotarget2.data); - - return 0; -} - -static int -test_ntlm2_session_resp(void) -{ - int ret; - struct ntlm_buf lm, ntlm; - - const unsigned char lm_resp[24] = - "\xff\xff\xff\x00\x11\x22\x33\x44" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00"; - const unsigned char ntlm2_sess_resp[24] = - "\x10\xd5\x50\x83\x2d\x12\xb2\xcc" - "\xb7\x9d\x5a\xd1\xf4\xee\xd3\xdf" - "\x82\xac\xa4\xc3\x68\x1d\xd4\x55"; - - const unsigned char client_nonce[8] = - "\xff\xff\xff\x00\x11\x22\x33\x44"; - const unsigned char server_challenge[8] = - "\x01\x23\x45\x67\x89\xab\xcd\xef"; - - const unsigned char ntlm_hash[16] = - "\xcd\x06\xca\x7c\x7e\x10\xc9\x9b" - "\x1d\x33\xb7\x48\x5a\x2e\xd8\x08"; - - ret = heim_ntlm_calculate_ntlm2_sess(client_nonce, - server_challenge, - ntlm_hash, - &lm, - &ntlm); - if (ret) - errx(1, "heim_ntlm_calculate_ntlm2_sess_resp"); - - if (lm.length != 24 || memcmp(lm.data, lm_resp, 24) != 0) - errx(1, "lm_resp wrong"); - if (ntlm.length != 24 || memcmp(ntlm.data, ntlm2_sess_resp, 24) != 0) - errx(1, "ntlm2_sess_resp wrong"); - - free(lm.data); - free(ntlm.data); - - - return 0; -} - -static int -test_ntlmv2(void) -{ - unsigned char type3[413] = - "\x4e\x54\x4c\x4d\x53\x53\x50\x00\x03\x00\x00\x00\x18\x00\x18\x00" - "\x80\x00\x00\x00\x9e\x00\x9e\x00\x98\x00\x00\x00\x14\x00\x14\x00" - "\x48\x00\x00\x00\x10\x00\x10\x00\x5c\x00\x00\x00\x14\x00\x14\x00" - "\x6c\x00\x00\x00\x00\x00\x00\x00\x36\x01\x00\x00\x05\x82\x88\xa2" - "\x05\x01\x28\x0a\x00\x00\x00\x0f\x43\x00\x4f\x00\x4c\x00\x4c\x00" - "\x45\x00\x59\x00\x2d\x00\x58\x00\x50\x00\x34\x00\x54\x00\x45\x00" - "\x53\x00\x54\x00\x55\x00\x53\x00\x45\x00\x52\x00\x43\x00\x4f\x00" - "\x4c\x00\x4c\x00\x45\x00\x59\x00\x2d\x00\x58\x00\x50\x00\x34\x00" - "\x2f\x96\xec\x0a\xf7\x9f\x2e\x24\xba\x09\x48\x10\xa5\x22\xd4\xe1" - "\x16\x6a\xca\x58\x74\x9a\xc1\x4f\x54\x6f\xee\x40\x96\xce\x43\x6e" - "\xdf\x99\x20\x71\x6c\x9a\xda\x2a\x01\x01\x00\x00\x00\x00\x00\x00" - "\x8d\xc0\x57\xc9\x79\x5e\xcb\x01\x16\x6a\xca\x58\x74\x9a\xc1\x4f" - "\x00\x00\x00\x00\x02\x00\x14\x00\x4e\x00\x55\x00\x54\x00\x43\x00" - "\x52\x00\x41\x00\x43\x00\x4b\x00\x45\x00\x52\x00\x01\x00\x14\x00" - "\x4e\x00\x55\x00\x54\x00\x43\x00\x52\x00\x41\x00\x43\x00\x4b\x00" - "\x45\x00\x52\x00\x04\x00\x12\x00\x61\x00\x70\x00\x70\x00\x6c\x00" - "\x65\x00\x2e\x00\x63\x00\x6f\x00\x6d\x00\x03\x00\x20\x00\x68\x00" - "\x75\x00\x6d\x00\x6d\x00\x65\x00\x6c\x00\x2e\x00\x61\x00\x70\x00" - "\x70\x00\x6c\x00\x65\x00\x2e\x00\x63\x00\x6f\x00\x6d\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x57\x00\x69\x00\x6e\x00\x64\x00\x6f" - "\x00\x77\x00\x73\x00\x20\x00\x32\x00\x30\x00\x30\x00\x32\x00\x20" - "\x00\x53\x00\x65\x00\x72\x00\x76\x00\x69\x00\x63\x00\x65\x00\x20" - "\x00\x50\x00\x61\x00\x63\x00\x6b\x00\x20\x00\x33\x00\x20\x00\x32" - "\x00\x36\x00\x30\x00\x30\x00\x00\x00\x57\x00\x69\x00\x6e\x00\x64" - "\x00\x6f\x00\x77\x00\x73\x00\x20\x00\x32\x00\x30\x00\x30\x00\x32" - "\x00\x20\x00\x35\x00\x2e\x00\x31\x00\x00\x00\x00\x00"; - const unsigned char challenge[8] = - "\xe4\x9c\x6a\x12\xe1\xbd\xde\x6a"; - unsigned char sessionkey[16]; - - const char key[16] = "\xD1\x83\x98\x3E\xAE\xA7\xBE\x99\x59\xC8\xF4\xC1\x98\xED\x0E\x68"; - - struct ntlm_buf data; - struct ntlm_type3 t3; - int ret; - - struct ntlm_targetinfo ti; - - unsigned char timsg[114] = - "\002\000\024\000N\000U\000T\000C\000R\000A\000C\000K\000E\000R\000\001\000\024\000N\000U\000T\000C\000R\000A\000C\000K\000E\000R\000\004\000\022\000a\000p\000p\000l\000e\000.\000c\000o\000m\000\003\000 \000h\000u\000m\000m\000e\000l\000.\000a\000p\000p\000l\000e\000.\000c\000o\000m\000\000\000\000\000\000\000\000"; - - - data.data = type3; - data.length = sizeof(type3); - - ret = heim_ntlm_decode_type3(&data, 1, &t3); - if (ret) - errx(1, "heim_ntlm_decode_type3"); - - memset(&ti, 0, sizeof(ti)); - - data.data = timsg; - data.length = sizeof(timsg); - - ret = heim_ntlm_decode_targetinfo(&data, 1, &ti); - if (ret) - return ret; - - ret = heim_ntlm_verify_ntlm2(key, sizeof(key), - t3.username, - t3.targetname, - 1285615547, - challenge, - &t3.ntlm, - &data, - sessionkey); - if (ret) - errx(1, "verify_ntlmv2"); - - if (sizeof(timsg) != data.length || memcmp(timsg, data.data, sizeof(timsg)) != 0) - errx(1, "target info wrong: %d != %d", - (int)sizeof(timsg), (int)data.length); - - heim_ntlm_free_type3(&t3); - heim_ntlm_free_targetinfo(&ti); - - return 0; -} - -static int -test_targetinfo(void) -{ - struct ntlm_targetinfo ti; - struct ntlm_buf buf; - const char *dnsservername = "dnsservername"; - const char *targetname = "targetname"; - const char z16[16] = { 0 }; - int ret; - - memset(&ti, 0, sizeof(ti)); - - ti.dnsservername = rk_UNCONST(dnsservername); - ti.avflags = 1; - ti.targetname = rk_UNCONST(targetname); - ti.channel_bindings.data = rk_UNCONST(z16); - ti.channel_bindings.length = sizeof(z16); - - ret = heim_ntlm_encode_targetinfo(&ti, 1, &buf); - if (ret) - return ret; - - memset(&ti, 0, sizeof(ti)); - - ret = heim_ntlm_decode_targetinfo(&buf, 1, &ti); - if (ret) - return ret; - - if (ti.dnsservername == NULL || - strcmp(ti.dnsservername, dnsservername) != 0) - errx(1, "ti.dnshostname != %s", dnsservername); - if (ti.avflags != 1) - errx(1, "ti.avflags != 1"); - if (ti.targetname == NULL || - strcmp(ti.targetname, targetname) != 0) - errx(1, "ti.targetname != %s", targetname); - - if (ti.channel_bindings.length != sizeof(z16) || - memcmp(ti.channel_bindings.data, z16, sizeof(z16)) != 0) - errx(1, "ti.channel_bindings != Z(16)"); - - heim_ntlm_free_targetinfo(&ti); - - return 0; -} - -static int -test_string2key(void) -{ - const char *pw = "山田"; - struct ntlm_buf buf; - - unsigned char key[16] = { - 0xc6, 0x5d, 0xc7, 0x61, 0xa1, 0x34, 0x17, 0xa1, - 0x17, 0x08, 0x9c, 0x1b, 0xb0, 0x0d, 0x0f, 0x19 - }; - - if (heim_ntlm_nt_key(pw, &buf) != 0) - errx(1, "heim_ntlmv_nt_key(jp)"); - - if (buf.length != 16 || memcmp(buf.data, key, 16) != 0) - errx(1, "compare failed"); - - heim_ntlm_free_buf(&buf); - - return 0; -} - -static int -test_jp(void) -{ - char buf2[220] = - "\x4e\x54\x4c\x4d\x53\x53\x50\x00\x02\x00\x00\x00\x06\x00\x06\x00" - "\x38\x00\x00\x00\x05\x02\x89\x62\x62\x94\xb1\xf3\x56\x80\xb0\xf9" - "\x00\x00\x00\x00\x00\x00\x00\x00\x9e\x00\x9e\x00\x3e\x00\x00\x00" - "\x06\x01\xb0\x1d\x00\x00\x00\x0f\x43\x00\x4f\x00\x53\x00\x02\x00" - "\x06\x00\x43\x00\x4f\x00\x53\x00\x01\x00\x12\x00\x43\x00\x4f\x00" - "\x53\x00\x57\x00\x49\x00\x4e\x00\x37\x00\x4a\x00\x50\x00\x04\x00" - "\x1a\x00\x63\x00\x6f\x00\x73\x00\x2e\x00\x61\x00\x70\x00\x70\x00" - "\x6c\x00\x65\x00\x2e\x00\x63\x00\x6f\x00\x6d\x00\x03\x00\x2e\x00" - "\x63\x00\x6f\x00\x73\x00\x77\x00\x69\x00\x6e\x00\x37\x00\x6a\x00" - "\x70\x00\x2e\x00\x63\x00\x6f\x00\x73\x00\x2e\x00\x61\x00\x70\x00" - "\x70\x00\x6c\x00\x65\x00\x2e\x00\x63\x00\x6f\x00\x6d\x00\x05\x00" - "\x1a\x00\x63\x00\x6f\x00\x73\x00\x2e\x00\x61\x00\x70\x00\x70\x00" - "\x6c\x00\x65\x00\x2e\x00\x63\x00\x6f\x00\x6d\x00\x07\x00\x08\x00" - "\x94\x51\xf0\xbd\xdc\x61\xcb\x01\x00\x00\x00\x00"; - - char buf3[362] = - "\x4e\x54\x4c\x4d\x53\x53\x50\x00\x03\x00\x00\x00\x18\x00\x18\x00" - "\x74\x00\x00\x00\xce\x00\xce\x00\x8c\x00\x00\x00\x1a\x00\x1a\x00" - "\x40\x00\x00\x00\x04\x00\x04\x00\x5a\x00\x00\x00\x16\x00\x16\x00" - "\x5e\x00\x00\x00\x10\x00\x10\x00\x5a\x01\x00\x00\x05\x02\x89\x62" - "\x31\x00\x37\x00\x2e\x00\x32\x00\x30\x00\x31\x00\x2e\x00\x35\x00" - "\x37\x00\x2e\x00\x31\x00\x32\x00\x31\x00\x71\x5c\x30\x75\x77\x00" - "\x6f\x00\x72\x00\x6b\x00\x73\x00\x74\x00\x61\x00\x74\x00\x69\x00" - "\x6f\x00\x6e\x00\xab\xad\xeb\x72\x01\xd4\x5f\xdf\x59\x07\x5f\xa9" - "\xfd\x54\x98\x2d\xfa\x17\xbb\xf1\x3c\x8f\xf5\x20\xe6\x8f\xd7\x0a" - "\xc9\x19\x3e\x94\x61\x31\xdb\x0f\x55\xe8\xe2\x53\x01\x01\x00\x00" - "\x00\x00\x00\x00\x00\x06\x3e\x30\xe4\x61\xcb\x01\x71\x98\x10\x6b" - "\x4c\x82\xec\xb3\x00\x00\x00\x00\x02\x00\x06\x00\x43\x00\x4f\x00" - "\x53\x00\x01\x00\x12\x00\x43\x00\x4f\x00\x53\x00\x57\x00\x49\x00" - "\x4e\x00\x37\x00\x4a\x00\x50\x00\x04\x00\x1a\x00\x63\x00\x6f\x00" - "\x73\x00\x2e\x00\x61\x00\x70\x00\x70\x00\x6c\x00\x65\x00\x2e\x00" - "\x63\x00\x6f\x00\x6d\x00\x03\x00\x2e\x00\x63\x00\x6f\x00\x73\x00" - "\x77\x00\x69\x00\x6e\x00\x37\x00\x6a\x00\x70\x00\x2e\x00\x63\x00" - "\x6f\x00\x73\x00\x2e\x00\x61\x00\x70\x00\x70\x00\x6c\x00\x65\x00" - "\x2e\x00\x63\x00\x6f\x00\x6d\x00\x05\x00\x1a\x00\x63\x00\x6f\x00" - "\x73\x00\x2e\x00\x61\x00\x70\x00\x70\x00\x6c\x00\x65\x00\x2e\x00" - "\x63\x00\x6f\x00\x6d\x00\x07\x00\x08\x00\xab\xec\xcc\x30\xe4\x61" - "\xcb\x01\x00\x00\x00\x00\x00\x00\x00\x00\xbc\x2e\xba\x3f\xd1\xb1" - "\xa7\x70\x00\x9d\x55\xa0\x59\x74\x2b\x78"; - - - struct ntlm_type2 type2; - struct ntlm_type3 type3; - struct ntlm_buf data; - int ret; - - data.length = sizeof(buf2); - data.data = buf2; - - memset(&type2, 0, sizeof(type2)); - - ret = heim_ntlm_decode_type2(&data, &type2); - if (ret) - errx(1, "heim_ntlm_decode_type2(jp): %d", ret); - - data.data = NULL; - data.length = 0; - - ret = heim_ntlm_encode_type2(&type2, &data); - if (ret) - errx(1, "heim_ntlm_encode_type2(jp): %d", ret); - - heim_ntlm_free_type2(&type2); - heim_ntlm_free_buf(&data); - - data.length = sizeof(buf3); - data.data = buf3; - - memset(&type3, 0, sizeof(type3)); - - ret = heim_ntlm_decode_type3(&data, 1, &type3); - if (ret) - errx(1, "heim_ntlm_decode_type2(jp): %d", ret); - - data.data = NULL; - data.length = 0; - - ret = heim_ntlm_encode_type3(&type3, &data, NULL); - if (ret) - errx(1, "heim_ntlm_decode_type2(jp): %d", ret); - - heim_ntlm_free_type3(&type3); - heim_ntlm_free_buf(&data); - - return 0; -} - - -static int verbose_flag = 0; -static int version_flag = 0; -static int help_flag = 0; - -static struct getargs args[] = { - {"verbose", 0, arg_flag, &verbose_flag, "verbose printing", NULL }, - {"version", 0, arg_flag, &version_flag, "print version", NULL }, - {"help", 0, arg_flag, &help_flag, NULL, NULL } -}; - -static void -usage (int ret) -{ - arg_printusage (args, sizeof(args)/sizeof(*args), - NULL, ""); - exit (ret); -} - -int -main(int argc, char **argv) -{ - int ret = 0, optidx = 0; - - setprogname(argv[0]); - - if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) - usage(1); - - if (help_flag) - usage (0); - - if(version_flag){ - print_version(NULL); - exit(0); - } - - if (verbose_flag) - printf("test_parse\n"); - ret |= test_parse(); - - if (verbose_flag) - printf("test_keys\n"); - ret |= test_keys(); - - if (verbose_flag) - printf("test_ntlm2_session_resp\n"); - ret |= test_ntlm2_session_resp(); - - if (verbose_flag) - printf("test_targetinfo\n"); - ret |= test_targetinfo(); - - if (verbose_flag) - printf("test_ntlmv2\n"); - ret |= test_ntlmv2(); - - if (verbose_flag) - printf("test_string2key\n"); - ret |= test_string2key(); - - if (verbose_flag) - printf("test_jp\n"); - ret |= test_jp(); - - return ret; -} diff --git a/lib/ntlm/version-script.map b/lib/ntlm/version-script.map deleted file mode 100644 index 6fe67a618..000000000 --- a/lib/ntlm/version-script.map +++ /dev/null @@ -1,30 +0,0 @@ -# $Id$ - -HEIMDAL_NTLM_1.0 { - global: - heim_ntlm_build_ntlm1_master; - heim_ntlm_calculate_lm2; - heim_ntlm_calculate_ntlm1; - heim_ntlm_calculate_ntlm2; - heim_ntlm_calculate_ntlm2_sess; - heim_ntlm_decode_targetinfo; - heim_ntlm_decode_type1; - heim_ntlm_decode_type2; - heim_ntlm_decode_type3; - heim_ntlm_encode_targetinfo; - heim_ntlm_encode_type1; - heim_ntlm_encode_type2; - heim_ntlm_encode_type3; - heim_ntlm_free_buf; - heim_ntlm_free_targetinfo; - heim_ntlm_free_type1; - heim_ntlm_free_type2; - heim_ntlm_free_type3; - heim_ntlm_nt_key; - heim_ntlm_ntlmv2_key; - heim_ntlm_verify_ntlm2; - heim_ntlm_unparse_flags; - initialize_ntlm_error_table_r; - local: - *; -}; diff --git a/packages/windows/assembly/Heimdal.Kerberos.manifest.in b/packages/windows/assembly/Heimdal.Kerberos.manifest.in index 515b441c8..ba2cdb93c 100644 --- a/packages/windows/assembly/Heimdal.Kerberos.manifest.in +++ b/packages/windows/assembly/Heimdal.Kerberos.manifest.in @@ -6,13 +6,11 @@ publicKeyToken="@pkt@" /> - - diff --git a/packages/windows/assembly/NTMakefile b/packages/windows/assembly/NTMakefile index 183856e0e..37ce5553d 100644 --- a/packages/windows/assembly/NTMakefile +++ b/packages/windows/assembly/NTMakefile @@ -58,13 +58,11 @@ ASMKRBMAN=$(ASMKRBNAME).manifest ASMKRBBINS=\ $(ASMKRBDIR)\heimdal.dll \ $(ASMKRBDIR)\com_err.dll \ - $(ASMKRBDIR)\heimntlm.dll \ $(ASMKRBDIR)\gssapi.dll \ $(ASMKRBDIR)\libhdb.dll \ $(ASMKRBDIR)\libkadm5srv.dll \ $(ASMKRBDIR)\heimdal.pdb \ $(ASMKRBDIR)\com_err.pdb \ - $(ASMKRBDIR)\heimntlm.pdb \ $(ASMKRBDIR)\gssapi.pdb \ $(ASMKRBDIR)\libhdb.pdb \ $(ASMKRBDIR)\libkadm5srv.pdb diff --git a/packages/windows/installer/heimdal-assemblies.wxs b/packages/windows/installer/heimdal-assemblies.wxs index b846218d8..4a318f5e9 100644 --- a/packages/windows/installer/heimdal-assemblies.wxs +++ b/packages/windows/installer/heimdal-assemblies.wxs @@ -32,13 +32,11 @@ - - diff --git a/packages/windows/sdk/NTMakefile b/packages/windows/sdk/NTMakefile index dcacca5aa..64eccbec1 100644 --- a/packages/windows/sdk/NTMakefile +++ b/packages/windows/sdk/NTMakefile @@ -105,7 +105,6 @@ INCFILES=\ $(SDKINCDIR)\gssapi\gssapi.h \ $(SDKINCDIR)\gssapi\gssapi_krb5.h \ $(SDKINCDIR)\gssapi\gssapi_oid.h \ - $(SDKINCDIR)\gssapi\gssapi_ntlm.h \ $(SDKINCDIR)\gssapi\gssapi_spnego.h \ $(SDKINCDIR)\Heimdal.Application.$(MCPU).manifest \ diff --git a/tests/db/Makefile.am b/tests/db/Makefile.am index d1cf761bc..5e9fe0039 100644 --- a/tests/db/Makefile.am +++ b/tests/db/Makefile.am @@ -97,9 +97,5 @@ EXTRA_DIST = \ add-modify-delete.in \ have-db.in \ krb5.conf.in \ - krb5-mit.conf.in \ - text-dump-0.7 \ - text-dump-known-ext \ - text-dump-no-ext \ - text-dump-unknown-ext + krb5-mit.conf.in diff --git a/tests/db/check-dbinfo.in b/tests/db/check-dbinfo.in index 0949051a4..a5f7c5185 100644 --- a/tests/db/check-dbinfo.in +++ b/tests/db/check-dbinfo.in @@ -45,8 +45,8 @@ export KRB5_CONFIG ../../lib/hdb/test_dbinfo > dbinfo.out || exit 1 -../../lib/hdb/test_mkey --mkey-file="${srcdir}/../../lib/hdb/data-mkey.mit.des3.le" || exit 1 -../../lib/hdb/test_mkey --mkey-file="${srcdir}/../../lib/hdb/data-mkey.mit.des3.be" || exit 1 +../../lib/hdb/test_mkey --mkey-file="${srcdir}/../../lib/hdb/data-mkey.mit.aes256.le" || exit 1 +../../lib/hdb/test_mkey --mkey-file="${srcdir}/../../lib/hdb/data-mkey.mit.aes256.be" || exit 1 exit 0 diff --git a/tests/db/loaddump-db.in b/tests/db/loaddump-db.in index a4d138bbc..7ed23ec15 100644 --- a/tests/db/loaddump-db.in +++ b/tests/db/loaddump-db.in @@ -74,61 +74,24 @@ ${kadmin} dump out-current-db2 || exit 1 sort out-current-db2 > out-current-db2-sort cmp out-current-db-sort out-current-db2-sort || exit 1 -rm -f current-db* - -# check with no extensions -${kadmin} load ${srcdir}/text-dump-0.7 || exit 1 -${propdb} > db-dump.tmp|| exit 1 -rm -f current-db* -${propddb} < db-dump.tmp || exit 1 -${kadmin} dump | sort | sed 's/[0-9]* -$//' > out-text-dump-0.7 || exit 1 -sort < ${srcdir}/text-dump-0.7 | \ - sed 's/[0-9]*$//' > out-text-dump-0.7-orig || exit 1 -cmp out-text-dump-0.7-orig out-text-dump-0.7 || exit 1 - -# check with no extensions -${kadmin} load ${srcdir}/text-dump-no-ext || exit 1 -${propdb} > db-dump.tmp || exit 1 -${propddb} < db-dump.tmp || exit 1 -${kadmin} dump | sort | \ - awk '{$11=""; print;}' > out-text-dump-no-ext || exit 1 -sort < ${srcdir}/text-dump-no-ext | \ - awk '{$11=""; print;}' > out-text-dump-no-ext-orig || exit 1 -cmp out-text-dump-no-ext-orig out-text-dump-no-ext || exit 1 - -# check with known extensions -${kadmin} load ${srcdir}/text-dump-known-ext || exit 1 -${propdb} > db-dump.tmp || exit 1 -${propddb} < db-dump.tmp || exit 1 -${kadmin} dump | sort | \ - awk '{$11=""; print;}' > out-text-dump-known-ext || exit 1 -sort < ${srcdir}/text-dump-known-ext | \ - awk '{$11=""; print;}' > out-text-dump-known-ext-orig || exit 1 -cmp out-text-dump-known-ext-orig out-text-dump-known-ext || exit 1 - -# check with unknown extensions -${kadmin} load ${srcdir}/text-dump-unknown-ext || exit 1 -${propdb} > db-dump.tmp || exit 1 -${propddb} < db-dump.tmp || exit 1 -${kadmin} dump | sort | \ - awk '{$11=""; print;}' > out-text-dump-unknown-ext || exit 1 -sort < ${srcdir}/text-dump-unknown-ext | \ - awk '{$11=""; print;}' > out-text-dump-unknown-ext-orig || exit 1 -cmp out-text-dump-unknown-ext-orig out-text-dump-unknown-ext || exit 1 +# We no longer test the upgrade path from pre 7.8. +# use a master key +${kadmin} dump | sort | + awk '{$11=""; print;}' > dump-no-mkey ${kstash} -e aes256-cts-hmac-sha1-96 --random-key -k ./mkey.file >/dev/null 2>/dev/null || exit 1 - -# remove masterkey -${kadmin} load ${srcdir}/text-dump-0.7 || exit 1 -${propdb} > db-dump.tmp|| exit 1 +${propdb} -m mkey.file -E > db-dump.tmp || exit 1 ${propddb} < db-dump.tmp || exit 1 +${kadmin} dump > dump-w-mkey +# remove master key ${propdb} -m mkey.file -D > db-dump.tmp || exit 1 mv mkey.file mkey.file.no || exit 1 ${propddb} < db-dump.tmp || exit 1 ${kadmin} dump | sort | \ - awk '{$11=""; print;}' > out-text-dump-0.7 || exit 1 -sort < ${srcdir}/text-dump-unknown-ext | \ - awk '{$11=""; print;}' > out-text-dump-0.7-orig || exit 1 -cmp out-text-dump-0.7 out-text-dump-0.7-orig || exit 1 + awk '{$11=""; print;}' > dump-no-mkey2 || exit 1 +# check that w/o mkey it's the same before and after +cmp dump-no-mkey dump-no-mkey2 || exit 1 +# check that dump-w-mkey is from dump-no-mkey +cmp dump-w-mkey dump-no-mkey2 && exit 1 exit 0 diff --git a/tests/db/text-dump-0.7 b/tests/db/text-dump-0.7 deleted file mode 100644 index 4aff11dde..000000000 --- a/tests/db/text-dump-0.7 +++ /dev/null @@ -1,7 +0,0 @@ -changepw/kerberos@EXAMPLE.ORG 1::3:2376E6A4C1D5456D:-::2:2376E6A4C1D5456D:-::1:2376E6A4C1D5456D:-::18:39C3D293A6B0CEE734C7874764A8B5449F348AC00A6EA94F7451D07BE31EF239:-::16:108373F74F105875DCCE866B160886C7BC6780E526D0DAEA:-::23:D279B73431AA349F63594EA800397195:- 20050728203748:kadmin/admin@EXAMPLE.ORG 20050728203748:kadmin/admin@EXAMPLE.ORG - - - 3600 3600 639 20050728203748:743456:2 -default@EXAMPLE.ORG 0::3:3B2A671585E93D6B:3/"EXAMPLE.ORGdefault"::2:3B2A671585E93D6B:3/"EXAMPLE.ORGdefault"::1:3B2A671585E93D6B:3/"EXAMPLE.ORGdefault"::18:AF401411D3F29C204611A9BA1EF54AEDEC43A01B0123C57B994B2EE104E7F127:3/"EXAMPLE.ORGdefault"::16:02401CAD7A92760E464025760BCD3BE5DF616DD5A798C719:3/"EXAMPLE.ORGdefault"::23:31D6CFE0D16AE931B73C59D7E0C089C0:3/"EXAMPLE.ORGdefault" 20050728203748:kadmin/admin@EXAMPLE.ORG - - - - 86400 604800 254 20050728203748:863727:0 -kadmin/admin@EXAMPLE.ORG 1::3:2FCD23DCC2C726CE:-::2:2FCD23DCC2C726CE:-::1:2FCD23DCC2C726CE:-::18:1675F5E5BAD61428DE51F7C8EDCD53F23426D90F4F0BB4F9C73514D317E0482A:-::16:C79D6B0879B6ABADCE4A9B436B5B4A4F792679CDBC7F5D10:-::23:265C712FED225A85567BAF8CD9A4C4ED:- 20050728203748:kadmin/admin@EXAMPLE.ORG 20050728203748:kadmin/admin@EXAMPLE.ORG - - - 3600 3600 382 20050728203748:682995:2 -kadmin/changepw@EXAMPLE.ORG 1::3:57A132CB9D7F4F37:-::2:57A132CB9D7F4F37:-::1:57A132CB9D7F4F37:-::18:B8252C9E3EC99969053631C238BBF88A0AAA082A8F1C4ED8D1729170C79519B8:-::16:10CE89987A1FD0986E6D836DB3F473E04C648C34F17CBCE3:-::23:A6D2BCA6F54B1C1AA5E875F116EEDE82:- 20050728203748:kadmin/admin@EXAMPLE.ORG 20050728203748:kadmin/admin@EXAMPLE.ORG - - - 300 300 867 20050728203748:623022:2 -kadmin/hprop@EXAMPLE.ORG 1::3:76DC5751EFE52931:-::2:76DC5751EFE52931:-::1:76DC5751EFE52931:-::18:9B4D02F7D74790AB929E607BE5940CFF66801C237840EE968FDEFD7ED1387350:-::16:4CD575703D197F2991D5233704BAE379DF4FFBE616256762:-::23:E3D49F7E3462823492F33FAD8F0A754F:- 20050728203748:kadmin/admin@EXAMPLE.ORG 20050728203748:kadmin/admin@EXAMPLE.ORG - - - 3600 3600 383 20050728203748:803541:2 -krbtgt/EXAMPLE.ORG@EXAMPLE.ORG 1::3:C219830E0E73DCEC:-::2:C219830E0E73DCEC:-::1:C219830E0E73DCEC:-::18:56CD702EE58B6EF4CAF758DA0BA1B92B21EFC1D2E9FCC0785009BC391F8571B8:-::16:29E9A2F45B2561D5B592C1070708B94A894AE046D091CE7C:-::23:30A2FB86CDC17B4EC625DC66C47AAF37:- 20050728203748:kadmin/admin@EXAMPLE.ORG 20050728203748:kadmin/admin@EXAMPLE.ORG - - - 86400 2592000 126 20050728203748:560639:2 -lha@EXAMPLE.ORG 1::3:80AB08A261D6A82F:3/"EXAMPLE.ORGlha"::2:80AB08A261D6A82F:3/"EXAMPLE.ORGlha"::1:80AB08A261D6A82F:3/"EXAMPLE.ORGlha"::18:96653BEA5A46E5DF97D535C6C49F007E02F0E56B21F498C14F8C014871FE9889:3/"EXAMPLE.ORGlha"::16:7545202640A81304AE987F231FCB1F625D02CE7FF8A4ABEA:3/"EXAMPLE.ORGlha"::23:AC8E657F83DF82BEEA5D43BDAF7800CC:3/"EXAMPLE.ORGlha" 20050728203752:kadmin/admin@EXAMPLE.ORG 20050728203758:kadmin/admin@EXAMPLE.ORG - - - 86400 604800 126 20050728203752:988968:1 diff --git a/tests/db/text-dump-known-ext b/tests/db/text-dump-known-ext deleted file mode 100644 index 8c3649c64..000000000 --- a/tests/db/text-dump-known-ext +++ /dev/null @@ -1,7 +0,0 @@ -changepw/kerberos@EXAMPLE.ORG 1::3:2376E6A4C1D5456D:-::2:2376E6A4C1D5456D:-::1:2376E6A4C1D5456D:-::18:39C3D293A6B0CEE734C7874764A8B5449F348AC00A6EA94F7451D07BE31EF239:-::16:108373F74F105875DCCE866B160886C7BC6780E526D0DAEA:-::23:D279B73431AA349F63594EA800397195:- 20050728203748:kadmin/admin@EXAMPLE.ORG 20050728203748:kadmin/admin@EXAMPLE.ORG - - - 3600 3600 639 20050728203748:743456:2 - -default@EXAMPLE.ORG 0::3:3B2A671585E93D6B:3/"EXAMPLE.ORGdefault"::2:3B2A671585E93D6B:3/"EXAMPLE.ORGdefault"::1:3B2A671585E93D6B:3/"EXAMPLE.ORGdefault"::18:AF401411D3F29C204611A9BA1EF54AEDEC43A01B0123C57B994B2EE104E7F127:3/"EXAMPLE.ORGdefault"::16:02401CAD7A92760E464025760BCD3BE5DF616DD5A798C719:3/"EXAMPLE.ORGdefault"::23:31D6CFE0D16AE931B73C59D7E0C089C0:3/"EXAMPLE.ORGdefault" 20050728203748:kadmin/admin@EXAMPLE.ORG - - - - 86400 604800 254 20050728203748:863727:0 - -kadmin/admin@EXAMPLE.ORG 1::3:2FCD23DCC2C726CE:-::2:2FCD23DCC2C726CE:-::1:2FCD23DCC2C726CE:-::18:1675F5E5BAD61428DE51F7C8EDCD53F23426D90F4F0BB4F9C73514D317E0482A:-::16:C79D6B0879B6ABADCE4A9B436B5B4A4F792679CDBC7F5D10:-::23:265C712FED225A85567BAF8CD9A4C4ED:- 20050728203748:kadmin/admin@EXAMPLE.ORG 20050728203748:kadmin/admin@EXAMPLE.ORG - - - 3600 3600 382 20050728203748:682995:2 - -kadmin/changepw@EXAMPLE.ORG 1::3:57A132CB9D7F4F37:-::2:57A132CB9D7F4F37:-::1:57A132CB9D7F4F37:-::18:B8252C9E3EC99969053631C238BBF88A0AAA082A8F1C4ED8D1729170C79519B8:-::16:10CE89987A1FD0986E6D836DB3F473E04C648C34F17CBCE3:-::23:A6D2BCA6F54B1C1AA5E875F116EEDE82:- 20050728203748:kadmin/admin@EXAMPLE.ORG 20050728203748:kadmin/admin@EXAMPLE.ORG - - - 300 300 867 20050728203748:623022:2 - -kadmin/hprop@EXAMPLE.ORG 1::3:76DC5751EFE52931:-::2:76DC5751EFE52931:-::1:76DC5751EFE52931:-::18:9B4D02F7D74790AB929E607BE5940CFF66801C237840EE968FDEFD7ED1387350:-::16:4CD575703D197F2991D5233704BAE379DF4FFBE616256762:-::23:E3D49F7E3462823492F33FAD8F0A754F:- 20050728203748:kadmin/admin@EXAMPLE.ORG 20050728203748:kadmin/admin@EXAMPLE.ORG - - - 3600 3600 383 20050728203748:803541:2 - -krbtgt/EXAMPLE.ORG@EXAMPLE.ORG 1::3:C219830E0E73DCEC:-::2:C219830E0E73DCEC:-::1:C219830E0E73DCEC:-::18:56CD702EE58B6EF4CAF758DA0BA1B92B21EFC1D2E9FCC0785009BC391F8571B8:-::16:29E9A2F45B2561D5B592C1070708B94A894AE046D091CE7C:-::23:30A2FB86CDC17B4EC625DC66C47AAF37:- 20050728203748:kadmin/admin@EXAMPLE.ORG 20050728203748:kadmin/admin@EXAMPLE.ORG - - - 86400 2592000 126 20050728203748:560639:2 - -lha@EXAMPLE.ORG 1::3:80AB08A261D6A82F:3/"EXAMPLE.ORGlha"::2:80AB08A261D6A82F:3/"EXAMPLE.ORGlha"::1:80AB08A261D6A82F:3/"EXAMPLE.ORGlha"::18:96653BEA5A46E5DF97D535C6C49F007E02F0E56B21F498C14F8C014871FE9889:3/"EXAMPLE.ORGlha"::16:7545202640A81304AE987F231FCB1F625D02CE7FF8A4ABEA:3/"EXAMPLE.ORGlha"::23:AC8E657F83DF82BEEA5D43BDAF7800CC:3/"EXAMPLE.ORGlha" 20050728203752:kadmin/admin@EXAMPLE.ORG 20050728203758:kadmin/admin@EXAMPLE.ORG - - - 86400 604800 126 20050728203752:988968:1 - diff --git a/tests/db/text-dump-no-ext b/tests/db/text-dump-no-ext deleted file mode 100644 index 8c3649c64..000000000 --- a/tests/db/text-dump-no-ext +++ /dev/null @@ -1,7 +0,0 @@ -changepw/kerberos@EXAMPLE.ORG 1::3:2376E6A4C1D5456D:-::2:2376E6A4C1D5456D:-::1:2376E6A4C1D5456D:-::18:39C3D293A6B0CEE734C7874764A8B5449F348AC00A6EA94F7451D07BE31EF239:-::16:108373F74F105875DCCE866B160886C7BC6780E526D0DAEA:-::23:D279B73431AA349F63594EA800397195:- 20050728203748:kadmin/admin@EXAMPLE.ORG 20050728203748:kadmin/admin@EXAMPLE.ORG - - - 3600 3600 639 20050728203748:743456:2 - -default@EXAMPLE.ORG 0::3:3B2A671585E93D6B:3/"EXAMPLE.ORGdefault"::2:3B2A671585E93D6B:3/"EXAMPLE.ORGdefault"::1:3B2A671585E93D6B:3/"EXAMPLE.ORGdefault"::18:AF401411D3F29C204611A9BA1EF54AEDEC43A01B0123C57B994B2EE104E7F127:3/"EXAMPLE.ORGdefault"::16:02401CAD7A92760E464025760BCD3BE5DF616DD5A798C719:3/"EXAMPLE.ORGdefault"::23:31D6CFE0D16AE931B73C59D7E0C089C0:3/"EXAMPLE.ORGdefault" 20050728203748:kadmin/admin@EXAMPLE.ORG - - - - 86400 604800 254 20050728203748:863727:0 - -kadmin/admin@EXAMPLE.ORG 1::3:2FCD23DCC2C726CE:-::2:2FCD23DCC2C726CE:-::1:2FCD23DCC2C726CE:-::18:1675F5E5BAD61428DE51F7C8EDCD53F23426D90F4F0BB4F9C73514D317E0482A:-::16:C79D6B0879B6ABADCE4A9B436B5B4A4F792679CDBC7F5D10:-::23:265C712FED225A85567BAF8CD9A4C4ED:- 20050728203748:kadmin/admin@EXAMPLE.ORG 20050728203748:kadmin/admin@EXAMPLE.ORG - - - 3600 3600 382 20050728203748:682995:2 - -kadmin/changepw@EXAMPLE.ORG 1::3:57A132CB9D7F4F37:-::2:57A132CB9D7F4F37:-::1:57A132CB9D7F4F37:-::18:B8252C9E3EC99969053631C238BBF88A0AAA082A8F1C4ED8D1729170C79519B8:-::16:10CE89987A1FD0986E6D836DB3F473E04C648C34F17CBCE3:-::23:A6D2BCA6F54B1C1AA5E875F116EEDE82:- 20050728203748:kadmin/admin@EXAMPLE.ORG 20050728203748:kadmin/admin@EXAMPLE.ORG - - - 300 300 867 20050728203748:623022:2 - -kadmin/hprop@EXAMPLE.ORG 1::3:76DC5751EFE52931:-::2:76DC5751EFE52931:-::1:76DC5751EFE52931:-::18:9B4D02F7D74790AB929E607BE5940CFF66801C237840EE968FDEFD7ED1387350:-::16:4CD575703D197F2991D5233704BAE379DF4FFBE616256762:-::23:E3D49F7E3462823492F33FAD8F0A754F:- 20050728203748:kadmin/admin@EXAMPLE.ORG 20050728203748:kadmin/admin@EXAMPLE.ORG - - - 3600 3600 383 20050728203748:803541:2 - -krbtgt/EXAMPLE.ORG@EXAMPLE.ORG 1::3:C219830E0E73DCEC:-::2:C219830E0E73DCEC:-::1:C219830E0E73DCEC:-::18:56CD702EE58B6EF4CAF758DA0BA1B92B21EFC1D2E9FCC0785009BC391F8571B8:-::16:29E9A2F45B2561D5B592C1070708B94A894AE046D091CE7C:-::23:30A2FB86CDC17B4EC625DC66C47AAF37:- 20050728203748:kadmin/admin@EXAMPLE.ORG 20050728203748:kadmin/admin@EXAMPLE.ORG - - - 86400 2592000 126 20050728203748:560639:2 - -lha@EXAMPLE.ORG 1::3:80AB08A261D6A82F:3/"EXAMPLE.ORGlha"::2:80AB08A261D6A82F:3/"EXAMPLE.ORGlha"::1:80AB08A261D6A82F:3/"EXAMPLE.ORGlha"::18:96653BEA5A46E5DF97D535C6C49F007E02F0E56B21F498C14F8C014871FE9889:3/"EXAMPLE.ORGlha"::16:7545202640A81304AE987F231FCB1F625D02CE7FF8A4ABEA:3/"EXAMPLE.ORGlha"::23:AC8E657F83DF82BEEA5D43BDAF7800CC:3/"EXAMPLE.ORGlha" 20050728203752:kadmin/admin@EXAMPLE.ORG 20050728203758:kadmin/admin@EXAMPLE.ORG - - - 86400 604800 126 20050728203752:988968:1 - diff --git a/tests/db/text-dump-unknown-ext b/tests/db/text-dump-unknown-ext deleted file mode 100644 index 8c3649c64..000000000 --- a/tests/db/text-dump-unknown-ext +++ /dev/null @@ -1,7 +0,0 @@ -changepw/kerberos@EXAMPLE.ORG 1::3:2376E6A4C1D5456D:-::2:2376E6A4C1D5456D:-::1:2376E6A4C1D5456D:-::18:39C3D293A6B0CEE734C7874764A8B5449F348AC00A6EA94F7451D07BE31EF239:-::16:108373F74F105875DCCE866B160886C7BC6780E526D0DAEA:-::23:D279B73431AA349F63594EA800397195:- 20050728203748:kadmin/admin@EXAMPLE.ORG 20050728203748:kadmin/admin@EXAMPLE.ORG - - - 3600 3600 639 20050728203748:743456:2 - -default@EXAMPLE.ORG 0::3:3B2A671585E93D6B:3/"EXAMPLE.ORGdefault"::2:3B2A671585E93D6B:3/"EXAMPLE.ORGdefault"::1:3B2A671585E93D6B:3/"EXAMPLE.ORGdefault"::18:AF401411D3F29C204611A9BA1EF54AEDEC43A01B0123C57B994B2EE104E7F127:3/"EXAMPLE.ORGdefault"::16:02401CAD7A92760E464025760BCD3BE5DF616DD5A798C719:3/"EXAMPLE.ORGdefault"::23:31D6CFE0D16AE931B73C59D7E0C089C0:3/"EXAMPLE.ORGdefault" 20050728203748:kadmin/admin@EXAMPLE.ORG - - - - 86400 604800 254 20050728203748:863727:0 - -kadmin/admin@EXAMPLE.ORG 1::3:2FCD23DCC2C726CE:-::2:2FCD23DCC2C726CE:-::1:2FCD23DCC2C726CE:-::18:1675F5E5BAD61428DE51F7C8EDCD53F23426D90F4F0BB4F9C73514D317E0482A:-::16:C79D6B0879B6ABADCE4A9B436B5B4A4F792679CDBC7F5D10:-::23:265C712FED225A85567BAF8CD9A4C4ED:- 20050728203748:kadmin/admin@EXAMPLE.ORG 20050728203748:kadmin/admin@EXAMPLE.ORG - - - 3600 3600 382 20050728203748:682995:2 - -kadmin/changepw@EXAMPLE.ORG 1::3:57A132CB9D7F4F37:-::2:57A132CB9D7F4F37:-::1:57A132CB9D7F4F37:-::18:B8252C9E3EC99969053631C238BBF88A0AAA082A8F1C4ED8D1729170C79519B8:-::16:10CE89987A1FD0986E6D836DB3F473E04C648C34F17CBCE3:-::23:A6D2BCA6F54B1C1AA5E875F116EEDE82:- 20050728203748:kadmin/admin@EXAMPLE.ORG 20050728203748:kadmin/admin@EXAMPLE.ORG - - - 300 300 867 20050728203748:623022:2 - -kadmin/hprop@EXAMPLE.ORG 1::3:76DC5751EFE52931:-::2:76DC5751EFE52931:-::1:76DC5751EFE52931:-::18:9B4D02F7D74790AB929E607BE5940CFF66801C237840EE968FDEFD7ED1387350:-::16:4CD575703D197F2991D5233704BAE379DF4FFBE616256762:-::23:E3D49F7E3462823492F33FAD8F0A754F:- 20050728203748:kadmin/admin@EXAMPLE.ORG 20050728203748:kadmin/admin@EXAMPLE.ORG - - - 3600 3600 383 20050728203748:803541:2 - -krbtgt/EXAMPLE.ORG@EXAMPLE.ORG 1::3:C219830E0E73DCEC:-::2:C219830E0E73DCEC:-::1:C219830E0E73DCEC:-::18:56CD702EE58B6EF4CAF758DA0BA1B92B21EFC1D2E9FCC0785009BC391F8571B8:-::16:29E9A2F45B2561D5B592C1070708B94A894AE046D091CE7C:-::23:30A2FB86CDC17B4EC625DC66C47AAF37:- 20050728203748:kadmin/admin@EXAMPLE.ORG 20050728203748:kadmin/admin@EXAMPLE.ORG - - - 86400 2592000 126 20050728203748:560639:2 - -lha@EXAMPLE.ORG 1::3:80AB08A261D6A82F:3/"EXAMPLE.ORGlha"::2:80AB08A261D6A82F:3/"EXAMPLE.ORGlha"::1:80AB08A261D6A82F:3/"EXAMPLE.ORGlha"::18:96653BEA5A46E5DF97D535C6C49F007E02F0E56B21F498C14F8C014871FE9889:3/"EXAMPLE.ORGlha"::16:7545202640A81304AE987F231FCB1F625D02CE7FF8A4ABEA:3/"EXAMPLE.ORGlha"::23:AC8E657F83DF82BEEA5D43BDAF7800CC:3/"EXAMPLE.ORGlha" 20050728203752:kadmin/admin@EXAMPLE.ORG 20050728203758:kadmin/admin@EXAMPLE.ORG - - - 86400 604800 126 20050728203752:988968:1 - diff --git a/tests/gss/Makefile.am b/tests/gss/Makefile.am index c5d85e721..6dc7f78da 100644 --- a/tests/gss/Makefile.am +++ b/tests/gss/Makefile.am @@ -6,7 +6,7 @@ include $(top_srcdir)/Makefile.am.common noinst_DATA = krb5.conf krb5-nodns.conf new_clients_k5.conf mech -SCRIPT_TESTS = check-basic check-nodns check-gss check-gssmask check-context check-spnego check-ntlm check-negoex +SCRIPT_TESTS = check-basic check-nodns check-gss check-gssmask check-context check-spnego check-negoex TESTS = $(SCRIPT_TESTS) @@ -52,11 +52,6 @@ check-nodns: check-nodns.in Makefile chmod +x check-nodns.tmp && \ mv check-nodns.tmp check-nodns -check-ntlm: check-ntlm.in Makefile - $(do_subst) < $(srcdir)/check-ntlm.in > check-ntlm.tmp && \ - chmod +x check-ntlm.tmp && \ - mv check-ntlm.tmp check-ntlm - check-negoex: check-negoex.in Makefile $(do_subst) < $(srcdir)/check-negoex.in > check-negoex.tmp && \ chmod +x check-negoex.tmp && \ @@ -97,7 +92,6 @@ CLEANFILES= \ check-gss.tmp \ check-gssmask.tmp \ check-spnego.tmp \ - check-ntlm.tmp \ check-context.tmp EXTRA_DIST = \ @@ -107,10 +101,8 @@ EXTRA_DIST = \ check-gss.in \ check-gssmask.in \ check-spnego.in \ - check-ntlm.in \ check-context.in \ check-negoex.in \ - ntlm-user-file.txt \ krb5.conf.in \ include-krb5.conf \ new_clients_k5.conf.in \ diff --git a/tests/gss/check-context.in b/tests/gss/check-context.in index f6a00add4..8888a0e7d 100644 --- a/tests/gss/check-context.in +++ b/tests/gss/check-context.in @@ -80,6 +80,7 @@ echo Creating database # XXX ext should ext aliases too ${kadmin} < messages.log ${kinit} --password-file=${objdir}/foopassword user1@${R} || \ diff --git a/tests/gss/check-negoex.in b/tests/gss/check-negoex.in index e44e26cbf..4d9146e79 100644 --- a/tests/gss/check-negoex.in +++ b/tests/gss/check-negoex.in @@ -58,8 +58,6 @@ KRB5_KTNAME="${keytab}-no" export KRB5_KTNAME KRB5CCNAME="${cache}-no" export KRB5CCNAME -unset NTLM_ACCEPTOR_CCACHE -unset NTLM_USER_FILE GSSAPI_SPNEGO_NAME=host@host.test.h5l.se export GSSAPI_SPNEGO_NAME diff --git a/tests/gss/check-ntlm.in b/tests/gss/check-ntlm.in deleted file mode 100644 index 56eb591b4..000000000 --- a/tests/gss/check-ntlm.in +++ /dev/null @@ -1,167 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan -# (Royal Institute of Technology, Stockholm, Sweden). -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# 3. Neither the name of the Institute nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. -# -# $Id$ -# - -env_setup="@env_setup@" -srcdir="@srcdir@" -objdir="@objdir@" - -. ${env_setup} - -# If there is no useful db support compiled in, disable test -../db/have-db || exit 77 - -R=TEST.H5L.SE - -port=@port@ - -keytabfile=${objdir}/server.keytab -keytab="FILE:${keytabfile}" -cache="FILE:krb5ccfile" -cacheds="FILE:krb5ccfile-ds" - -kinit="${TESTS_ENVIRONMENT} ../../kuser/kinit -c $cache ${afs_no_afslog}" -kinitds="${TESTS_ENVIRONMENT} ../../kuser/kinit -c $cacheds ${afs_no_afslog}" -kadmin="${TESTS_ENVIRONMENT} ../../kadmin/kadmin -l -r $R" -kdc="${TESTS_ENVIRONMENT} ../../kdc/kdc --addresses=localhost -P $port" -kdigest="${TESTS_ENVIRONMENT} ../../kuser/kdigest" - -context="${TESTS_ENVIRONMENT} ../../lib/gssapi/test_context" - -KRB5_CONFIG="${objdir}/krb5.conf" -export KRB5_CONFIG - -KRB5CCNAME=${cache} -KRB5_KTNAME="${keytab}" -export KRB5_KTNAME -KRB5CCNAME="${cache}" -export KRB5CCNAME -NTLM_ACCEPTOR_CCACHE="${cacheds}" -export NTLM_ACCEPTOR_CCACHE -NTLM_USER_FILE="${srcdir}/ntlm-user-file.txt" -export NTLM_USER_FILE - -GSSAPI_SPNEGO_NAME=host@host.test.h5l.se -export GSSAPI_SPNEGO_NAME - -rm -f ${keytabfile} -rm -f current-db* -rm -f out-* -rm -f mkey.file* - -> messages.log - -echo Creating database -${kadmin} < ${objdir}/foopassword -echo ds > ${objdir}/barpassword - -echo Starting kdc -${kdc} --detach --testing || { echo "kdc failed to start"; cat messages.log; exit 1; } -kdcpid=`getpid kdc` - -cleanup() { - echo signal killing kdc - kill -9 ${kdcpid} - trap '' EXIT INT TERM - cat messages.log - exit 1 -} -trap cleanup EXIT INT TERM - -exitcode=0 - -echo "Getting client initial tickets" -${kinit} --password-file=${objdir}/foopassword user1@${R} || exitcode=1 -echo "Getting digestserver initial tickets" -${kinitds} --password-file=${objdir}/barpassword digestserver@${R} || exitcode=1 - -echo "======probe" -KRB5CCNAME="$cacheds" - - ${kdigest} digest-probe --realm=${R} > /dev/null || \ - { exitcode=1; echo "test failed"; } - -echo "======context building ntlm" - -NTLM_USER_FILE="${srcdir}/ntlm-user-file.txt-no" -KRB5CCNAME="$cache" - -echo "no NTLM initiator creds" -${context} --mech-type=ntlm \ - --mutual \ - --name-type=hostbased-service \ - --ret-mech-type=ntlm \ - host@host.test.h5l.se 2> /dev/null && \ - { exitcode=1 ; echo "test failed"; } - -echo "Getting client initial tickets (with ntlm creds)" -${kinit} --password-file=${objdir}/foopassword --ntlm-domain=TEST user1@${R} || exitcode=1 - -echo "NTLM initiator krb5 creds" -${context} --mech-type=ntlm \ - --mutual \ - --name-type=hostbased-service \ - --ret-mech-type=ntlm \ - host@host.test.h5l.se || \ - { exitcode=1 ; echo "test failed"; } - -echo "NTLM initiator krb5 creds (getverifymic, wrapunwrap)" -${context} --mech-type=ntlm \ - --mutual \ - --name-type=hostbased-service \ - --ret-mech-type=ntlm \ - --getverifymic --wrapunwrap \ - host@host.test.h5l.se || \ - { exitcode=1 ; echo "test failed"; } - -trap "" EXIT - -echo "killing kdc (${kdcpid})" -kill ${kdcpid} 2> /dev/null - -exit $exitcode - - diff --git a/tests/gss/check-spnego.in b/tests/gss/check-spnego.in index e26b46290..8e4884432 100644 --- a/tests/gss/check-spnego.in +++ b/tests/gss/check-spnego.in @@ -50,10 +50,8 @@ port=@port@ keytabfile=${objdir}/server.keytab keytab="FILE:${keytabfile}" cache="FILE:krb5ccfile" -cacheds="FILE:krb5ccfile-ds" kinit="${TESTS_ENVIRONMENT} ../../kuser/kinit -c $cache ${afs_no_afslog} --forwardable" -kinitds="${TESTS_ENVIRONMENT} ../../kuser/kinit -c $cacheds ${afs_no_afslog}" kadmin="${TESTS_ENVIRONMENT} ../../kadmin/kadmin -l -A -r $R" kdc="${TESTS_ENVIRONMENT} ../../kdc/kdc --addresses=localhost -P $port" @@ -67,14 +65,12 @@ KRB5_KTNAME="${keytab}" export KRB5_KTNAME KRB5CCNAME="${cache}" export KRB5CCNAME -NTLM_ACCEPTOR_CCACHE="${cacheds}" -export NTLM_ACCEPTOR_CCACHE -NTLM_USER_FILE="${srcdir}/ntlm-user-file.txt" -export NTLM_USER_FILE GSSAPI_SPNEGO_NAME=host@host.test.h5l.se export GSSAPI_SPNEGO_NAME +testfailed="exitcode=1; echo test failed; cat messages.log; exit 1" + rm -f ${keytabfile} rm -f current-db* rm -f out-* @@ -115,17 +111,16 @@ exitcode=0 echo "Getting client initial tickets" ${kinit} --password-file=${objdir}/foopassword user1@${R} || exitcode=1 echo "Getting digestserver initial tickets" -${kinitds} --password-file=${objdir}/barpassword digestserver@${R} || exitcode=1 echo "======context building for each mech" -for mech in ntlm krb5 ; do +for mech in krb5 ; do echo "${mech}" ${context} --mech-type=${mech} --ret-mech-type=${mech} \ --client-ccache="${cache}" \ --gsskrb5-acceptor-identity="${keytab}" \ --name-type=hostbased-service host@host.test.h5l.se || \ - { exitcode=1 ; echo test failed; } + { eval "$testfailed"; } done echo "spnego" @@ -136,7 +131,7 @@ ${context} \ --name-type=hostbased-service \ --export-import-context \ host@host.test.h5l.se || \ - { exitcode=1 ; echo test failed; } + { eval "$testfailed"; } echo "spnego (split tokens)" ${context} \ @@ -147,18 +142,18 @@ ${context} \ --name-type=hostbased-service \ --export-import-context \ host@host.test.h5l.se || \ - { exitcode=1 ; echo test failed; } + { eval "$testfailed"; } echo "test failure cases" -${context} --mech-type=ntlm --ret-mech-type=krb5 \ +${context} --mech-type=sanon-x25519 --ret-mech-type=krb5 \ --client-ccache="${cache}" \ --name-type=hostbased-service host@host.test.h5l.se 2> /dev/null && \ - { exitcode=1 ; echo test failed; } + { eval "$testfailed"; } -${context} --mech-type=krb5 --ret-mech-type=ntlm \ +${context} --mech-type=krb5 --ret-mech-type=sanon-x25519 \ --client-ccache="${cache}" \ --name-type=hostbased-service host@host.test.h5l.se 2> /dev/null && \ - { exitcode=1 ; echo test failed; } + { eval "$testfailed"; } echo "======spnego variants context building" @@ -171,25 +166,13 @@ for arg in \ "--mutual --getverifymic --wrapunwrap" \ ; do - echo "no NTLM acceptor cred ${arg}" - NTLM_ACCEPTOR_CCACHE="${cacheds}-no" + echo "with krb5 creds ${arg}" ${context} --mech-type=spnego \ $arg \ --name-type=hostbased-service \ --ret-mech-type=krb5 \ host@host.test.h5l.se || \ - { exitcode=1 ; echo test failed; } - NTLM_ACCEPTOR_CCACHE="${cacheds}" - - echo "no NTLM initiator cred ${arg}" - NTLM_USER_FILE="${srcdir}/ntlm-user-file.txt-no" - ${context} --mech-type=spnego \ - $arg \ - --name-type=hostbased-service \ - --ret-mech-type=krb5 \ - host@host.test.h5l.se || \ - { exitcode=1 ; echo test failed; } - NTLM_USER_FILE="${srcdir}/ntlm-user-file.txt" + { eval "$testfailed"; } echo "no krb5 acceptor cred ${arg}" KRB5_KTNAME="${keytab}-no" @@ -197,9 +180,9 @@ for arg in \ $arg \ --server-no-delegate \ --name-type=hostbased-service \ - --ret-mech-type=ntlm \ - host@host.test.h5l.se || \ - { exitcode=1 ; echo test failed; } + --ret-mech-type=sanon-x25519 \ + host@host.test.h5l.se && \ + { eval "$testfailed"; } KRB5_KTNAME="${keytab}" echo "no explicit krb5 acceptor cred ${arg}" @@ -210,7 +193,7 @@ for arg in \ --name-type=hostbased-service \ --ret-mech-type=krb5 \ host@host.test.h5l.se 2>/dev/null && \ - { exitcode=1 ; echo test failed; } + { eval "$testfailed"; } echo "no krb5 initiator cred ${arg}" KRB5CCNAME="${cache}-no" @@ -218,9 +201,9 @@ for arg in \ $arg \ --server-no-delegate \ --name-type=hostbased-service \ - --ret-mech-type=ntlm \ - host@host.test.h5l.se || \ - { exitcode=1 ; echo test failed; } + --ret-mech-type=sanon-x25519 \ + host@host.test.h5l.se && \ + { eval "$testfailed"; } KRB5CCNAME="${cache}" echo "no explicit krb5 initiator cred ${arg}" @@ -231,7 +214,7 @@ for arg in \ --name-type=hostbased-service \ --ret-mech-type=krb5 \ host@host.test.h5l.se 2>/dev/null && \ - { exitcode=1 ; echo test failed; } + { eval "$testfailed"; } done diff --git a/tests/gss/ntlm-user-file.txt b/tests/gss/ntlm-user-file.txt deleted file mode 100644 index cd2c654b4..000000000 --- a/tests/gss/ntlm-user-file.txt +++ /dev/null @@ -1,2 +0,0 @@ -# $Id$ -TEST:user1:u1 diff --git a/tests/java/krb5.conf.in b/tests/java/krb5.conf.in index ca6b74f3d..aeea248ea 100644 --- a/tests/java/krb5.conf.in +++ b/tests/java/krb5.conf.in @@ -29,4 +29,3 @@ [kadmin] default_keys = aes256-cts-hmac-sha1-96:pw-salt default_keys = aes128-cts-hmac-sha1-96:pw-salt - default_keys = des3-cbc-sha1:pw-salt diff --git a/tests/kdc/Makefile.am b/tests/kdc/Makefile.am index b74c011ba..0271777d4 100644 --- a/tests/kdc/Makefile.am +++ b/tests/kdc/Makefile.am @@ -29,14 +29,11 @@ SCRIPT_TESTS = \ check-canon \ check-cc \ check-delegation \ - check-des \ - check-digest \ check-fast \ check-kadmin \ check-hdb-mitdb \ check-kdc \ check-kdc-weak \ - check-keys \ check-kpasswdd \ check-pkinit \ check-bx509 \ @@ -84,7 +81,8 @@ do_subst = $(heim_verbose)sed $(do_dlopen) \ -e 's,[@]ENABLE_AFS_STRING_TO_KEY[@],$(ENABLE_AFS_STRING_TO_KEY),' \ -e 's,[@]ENABLE_AFS_STRING_TO_KEY[@],$(ENABLE_AFS_STRING_TO_KEY),' \ -e 's,[@]EGREP[@],$(EGREP),g' \ - -e 's,[@]MITKRB5[@],$(MITKRB5),g' + -e 's,[@]MITKRB5[@],$(MITKRB5),g' \ + -e 's,[@]OPENSSL_PKCS11_PROVIDER[@],$(OPENSSL_PKCS11_PROVIDER),g' chmod = chmod @@ -110,11 +108,6 @@ check-delegation: check-delegation.in Makefile $(chmod) +x check-delegation.tmp && \ mv check-delegation.tmp check-delegation -check-des: check-des.in Makefile krb5.conf - $(do_subst) < $(srcdir)/check-des.in > check-des.tmp && \ - $(chmod) +x check-des.tmp && \ - mv check-des.tmp check-des - check-hdb-mitdb: check-hdb-mitdb.in Makefile krb5-hdb-mitdb.conf $(do_subst) < $(srcdir)/check-hdb-mitdb.in > check-hdb-mitdb.tmp && \ $(chmod) +x check-hdb-mitdb.tmp && \ @@ -130,7 +123,7 @@ check-kdc: check-kdc.in Makefile $(chmod) +x check-kdc.tmp && \ mv check-kdc.tmp check-kdc -check-kdc-weak: check-kdc-weak.in Makefile +check-kdc-weak: check-kdc krb5-weak.conf check-kdc-weak.in Makefile $(do_subst) < $(srcdir)/check-kdc-weak.in > check-kdc-weak.tmp && \ $(chmod) +x check-kdc-weak.tmp && \ mv check-kdc-weak.tmp check-kdc-weak @@ -140,11 +133,6 @@ check-tester: check-tester.in kdc-tester4.json Makefile $(chmod) +x check-tester.tmp && \ mv check-tester.tmp check-tester -check-keys: check-keys.in Makefile - $(do_subst) < $(srcdir)/check-keys.in > check-keys.tmp && \ - $(chmod) +x check-keys.tmp && \ - mv check-keys.tmp check-keys - check-kinit: check-kinit.in Makefile $(do_subst) < $(srcdir)/check-kinit.in > check-kinit.tmp && \ $(chmod) +x check-kinit.tmp && \ @@ -180,11 +168,6 @@ check-iprop: check-iprop.in Makefile krb5.conf krb5-master2.conf krb5-slave.conf $(chmod) +x check-iprop.tmp && \ mv check-iprop.tmp check-iprop -check-digest: check-digest.in Makefile - $(do_subst) < $(srcdir)/check-digest.in > check-digest.tmp && \ - $(chmod) +x check-digest.tmp && \ - mv check-digest.tmp check-digest - check-referral: check-referral.in Makefile $(do_subst) < $(srcdir)/check-referral.in > check-referral.tmp && \ $(chmod) +x check-referral.tmp && \ @@ -255,7 +238,7 @@ krb5-hdb-mitdb.conf: krb5-hdb-mitdb.conf.in Makefile krb5-weak.conf: krb5.conf.in Makefile $(do_subst) \ -e 's,[@]WEAK[@],true,g' \ - -e 's,[@]dk[@],default_keys = aes256-cts-hmac-sha1-96:pw-salt arcfour-hmac-md5:pw-salt des3-cbc-sha1:pw-salt des:pw-salt,g' \ + -e 's,[@]dk[@],default_keys = aes256-cts-hmac-sha1-96:pw-salt aes256-cts-hmac-sha384-192:pw-salt arcfour-hmac-md5:pw-salt,g' \ -e 's,[@]messages[@],messages,g' \ -e 's,[@]signalsocket[@],signal,g' \ -e 's,[@]ipropstats[@],iprop-stats,g' \ @@ -330,12 +313,10 @@ CLEANFILES= \ ca.crt \ cache.krb5 \ cache2.krb5 \ - cdigest-reply \ client-cache \ curlheaders \ current-db* \ current.log* \ - digest-reply \ extracted_config \ extracted_keytab* \ foopassword \ @@ -373,15 +354,11 @@ CLEANFILES= \ negotiate-token \ notfoopassword \ o2cache.krb5 \ - o2digest-reply \ ocache.krb5 \ out-log \ req \ response-headers \ - s2digest-reply \ sdb \ - sdigest-init \ - sdigest-reply \ server.keytab \ signal \ signal2 \ @@ -399,8 +376,6 @@ EXTRA_DIST = \ check-canon.in \ check-cc.in \ check-delegation.in \ - check-des.in \ - check-digest.in \ check-fast.in \ check-hdb-mitdb.in \ check-httpkadmind.in \ @@ -408,7 +383,6 @@ EXTRA_DIST = \ check-kadmin.in \ check-kdc-weak.in \ check-kdc.in \ - check-keys.in \ check-kinit.in \ check-kpasswdd.in \ check-pkinit.in \ @@ -439,7 +413,6 @@ EXTRA_DIST = \ krb5.conf.in \ krb5.conf.keys.in \ leaks-kill.sh \ - ntlm-user-file.txt \ pki-mapping \ uuserver.txt \ wait-kdc.sh diff --git a/tests/kdc/check-bx509.in b/tests/kdc/check-bx509.in index 105e70410..55ddb1e43 100644 --- a/tests/kdc/check-bx509.in +++ b/tests/kdc/check-bx509.in @@ -198,12 +198,12 @@ get_via_POST() { } rm -f $kt $ukt -$ktutil -k $keytab add -r -V 1 -e aes128-cts-hmac-sha1-96 \ +$ktutil -k $keytab add -r -V 1 -e aes256-cts-hmac-sha1-96 \ -p HTTP/datan.test.h5l.se@${R} || { echo "failed to setup kimpersonate credentials"; exit 2; } $ktutil -k $keytab list || { echo "failed to setup kimpersonate credentials"; exit 2; } -$kimpersonate --ccache=$cache -k $keytab -R -t aes128-cts-hmac-sha1-96 \ +$kimpersonate --ccache=$cache -k $keytab -R -t aes256-cts-hmac-sha1-96 \ -c foo@${R} -s HTTP/datan.test.h5l.se@${R} || { echo "failed to setup kimpersonate credentials"; exit 2; } $klist || @@ -655,6 +655,61 @@ else exit 1 fi +echo "Making an Ed25519 CSR" +csr_revoke +$hxtool request-create --subject='' --generate-key=ed25519 \ + --key=FILE:"${objdir}/k-ed25519.der" "${objdir}/req-ed25519" || + { echo "Failed to make an Ed25519 CSR"; exit 2; } + +echo "Fetching a trivial user certificate with Ed25519 key" +csr=$($rkbase64 -- ${objdir}/req-ed25519 | $rkvis -h --stdin) +token=$(KRB5CCNAME=$cache $gsstoken HTTP@$server) +if (set -vx; get_cert '' -sf -o "${objdir}/trivial-ed25519.pem"); then + $hxtool print --content "FILE:${objdir}/trivial-ed25519.pem" + # Check that the certificate has an Ed25519 public key + if openssl x509 -in "${objdir}/trivial-ed25519.pem" -noout -text | grep -q "Public Key Algorithm: ED25519"; then + echo 'Certificate has Ed25519 public key!' + else + echo 'FAIL: Certificate does not have Ed25519 public key' + exit 1 + fi + if $hxtool acert --end-entity \ + --expr="%{certificate.subject} == \"CN=foo,$DCs\"" \ + -P "foo@${R}" "FILE:${objdir}/trivial-ed25519.pem"; then + echo 'Successfully obtained an Ed25519 client certificate!' + else + echo 'FAIL: Obtained an Ed25519 certificate w/o expected PKINIT SAN)' + exit 1 + fi +else + echo 'Failed to get an Ed25519 certificate!' + exit 1 +fi + +echo "Fetching an Ed25519 server certificate with one dNSName SAN" +csr_grant san_dnsname $server foo@${R} +csr=$($rkbase64 -- ${objdir}/req-ed25519 | $rkvis -h --stdin) +token=$(KRB5CCNAME=$cache $gsstoken HTTP@$server) +if (set -vx; get_cert "&dNSName=$server" -sf -o "${objdir}/server-ed25519.pem"); then + $hxtool print --content "FILE:${objdir}/server-ed25519.pem" + # Check that the certificate has an Ed25519 public key + if openssl x509 -in "${objdir}/server-ed25519.pem" -noout -text | grep -q "Public Key Algorithm: ED25519"; then + echo 'Server certificate has Ed25519 public key!' + else + echo 'FAIL: Server certificate does not have Ed25519 public key' + exit 1 + fi + if $hxtool acert --end-entity -D $server "FILE:${objdir}/server-ed25519.pem"; then + echo 'Successfully obtained an Ed25519 server certificate!' + else + echo 'Got a broken Ed25519 server certificate' + exit 1 + fi +else + echo 'Failed to get an Ed25519 server certificate!' + exit 1 +fi + echo "Fetch TGT (not granted for other)" token=$(KRB5CCNAME=$cache $gsstoken HTTP@$server) if (set -vx; diff --git a/tests/kdc/check-delegation.in b/tests/kdc/check-delegation.in index 5ec749986..bd70b443e 100644 --- a/tests/kdc/check-delegation.in +++ b/tests/kdc/check-delegation.in @@ -81,6 +81,7 @@ add -p foo --use-defaults foo@${R} add -p cross1 --use-defaults krbtgt/${R2}@${R} add -p cross2 --use-defaults krbtgt/${R3}@${R2} add -p cross3 --use-defaults krbtgt/${R4}@${R3} +modify --attributes=+ok-as-delegate krbtgt/${R}@${R} modify --attributes=+ok-as-delegate krbtgt/${R2}@${R} modify --attributes=+ok-as-delegate krbtgt/${R3}@${R2} add -p foo --use-defaults host/server.test3.h5l.se@${R3} diff --git a/tests/kdc/check-httpkadmind.in b/tests/kdc/check-httpkadmind.in index 759bdc9d5..776decbae 100644 --- a/tests/kdc/check-httpkadmind.in +++ b/tests/kdc/check-httpkadmind.in @@ -136,10 +136,15 @@ else fi # HTTP curl-opts +# Note: We use gss-token instead of curl's --negotiate because curl uses the +# system's GSS-API library which may do DNS lookups for principal name +# canonicalization, causing timeouts in test environments. Heimdal's gss-token +# respects the krb5.conf name_canon_rules and rdns settings. HTTP() { - curl -g --resolve ${server}:${restport2}:127.0.0.1 \ - --resolve ${server}:${restport}:127.0.0.1 \ - -u: --negotiate $verbose \ + curl -g --resolve ${server}:${restport1}:127.0.0.1 \ + --resolve ${server}:${restport2}:127.0.0.1 \ + -H "Authorization: Negotiate $(${gsstoken} HTTP@${server})" \ + $verbose \ -D response-headers \ "$@" } @@ -197,12 +202,25 @@ get_keytab_POST() { get_keytab_POST_redir() { url="http://${server}:${restport}/get-keys?$1" shift + > response-headers HTTP -X POST --data-binary @/dev/null "$@" "$url" grep ^X-CSRF-Token: response-headers >/dev/null || { echo "POST w/o CSRF token had response w/o CSRF token!"; return 1; } HTTP -X POST --data-binary @/dev/null -f \ -H "$(sed -e 's/\r//' response-headers | grep ^X-CSRF-Token:)" \ - --location --location-trusted "$@" "$url" + "$@" "$url" + grep '^HTTP/1.1 307 Temporary Redirect' response-headers || + { echo "POST to secondary did not yield a redirect to primary!"; return 1; } + grep '^Location: ' response-headers || + { echo "POST to secondary did not yield a redirect to primary!"; return 1; } + url=$(sed -e 's/\r//' response-headers | grep '^Location: ' | sed -e's/^Location:.//' ) + > response-headers + HTTP -X POST --data-binary @/dev/null "$@" "$url" + grep ^X-CSRF-Token: response-headers >/dev/null || + { echo "POST w/o CSRF token had response w/o CSRF token!"; return 1; } + HTTP -X POST --data-binary @/dev/null -f \ + -H "$(sed -e 's/\r//' response-headers | grep ^X-CSRF-Token:)" \ + "$@" "$url" } kdcpid= @@ -257,10 +275,10 @@ EOF ${kdestroy} # For a while let's not bother with a KDC -$kimpersonate --ccache=$cache -k $keytab -R -t aes128-cts-hmac-sha1-96 \ +$kimpersonate --ccache=$cache -k $keytab -R -t aes256-cts-hmac-sha1-96 \ -c foo@${R} -s HTTP/datan.test.h5l.se@${R} || { echo "failed to setup kimpersonate credentials"; exit 2; } -$kimpersonate -A --ccache=$cache -k $keytab -R -t aes128-cts-hmac-sha1-96 \ +$kimpersonate -A --ccache=$cache -k $keytab -R -t aes256-cts-hmac-sha1-96 \ -c foo@${R} -s HTTP/localhost@${R} || { echo "failed to setup kimpersonate credentials"; exit 2; } $klist -t >/dev/null || @@ -401,7 +419,7 @@ 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 || { echo "Failed to list keytab for $p"; exit 1; } -test "$(grep $p extracted_keytab.rest1 | wc -l)" -eq 1 || +test "$(grep $p extracted_keytab.rest1 | wc -l)" -eq 2 || { echo "Wrong number of new keys!"; exit 1; } get_keytab "dNSName=${hn}&rotate=true" -sf -o "${objdir}/extracted_keytab" && { echo "GET succeeded for write operation!"; exit 1; } @@ -411,7 +429,7 @@ ${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest2 | { echo "Failed to list keytab for $p"; exit 1; } cmp extracted_keytab.rest1 extracted_keytab.rest2 > /dev/null && { echo "Keys for $p did not change!"; exit 1; } -test "$(grep $p extracted_keytab.rest2 | wc -l)" -eq 2 || +test "$(grep $p extracted_keytab.rest2 | wc -l)" -eq 4 || { echo "Wrong number of new keys!"; exit 1; } hn=xyz.${domain} @@ -431,7 +449,7 @@ ${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest2 | { echo "Failed to list keytab for $p"; exit 1; } cmp extracted_keytab.rest1 extracted_keytab.rest2 > /dev/null && { echo "Keys for $p did not change!"; exit 1; } -test "$(grep $p extracted_keytab.rest2 | wc -l)" -eq 1 || +test "$(grep $p extracted_keytab.rest2 | wc -l)" -eq 2 || { echo "Wrong number of new keys!"; exit 1; } hn=abc.${domain} @@ -473,7 +491,7 @@ cmp extracted_keytab.kadmin extracted_keytab.rest || { echo "Keytabs for $p don't match!"; exit 1; } echo "Starting secondary httpkadmind to test HTTP redirection" -${httpkadmind2} --primary-server-uri=http://localhost:$restport \ +${httpkadmind2} --primary-server-uri=http://${server}:$restport \ -H $server --local --local-read-only -t --daemon || { echo "httpkadmind failed to start"; exit 2; } httpkadmind2pid=`getpid httpkadmind` @@ -515,7 +533,7 @@ ${kadmind2} || kadmind2pid=`getpid kadmind` # Make a ccache for use with kadmin(1) -$kimpersonate --ticket-flags=initial --ccache=$admincache -k $keytab -t aes128-cts-hmac-sha1-96 \ +$kimpersonate --ticket-flags=initial --ccache=$admincache -k $keytab -t aes256-cts-hmac-sha1-96 \ -c httpkadmind/admin@${R} -s kadmin/admin@${R} || { echo "failed to setup kimpersonate credentials"; exit 2; } $adminklist -t >/dev/null || @@ -593,7 +611,7 @@ 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 || { echo "Failed to list keytab for $p"; exit 1; } -test "$(grep $p extracted_keytab.rest1 | wc -l)" -eq 1 || +test "$(grep $p extracted_keytab.rest1 | wc -l)" -eq 2 || { echo "Wrong number of new keys!"; exit 1; } get_keytab "dNSName=${hn}&rotate=true" -sf -o "${objdir}/extracted_keytab" && { echo "GET succeeded for write operation!"; exit 1; } @@ -603,7 +621,7 @@ ${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest2 | { echo "Failed to list keytab for $p"; exit 1; } cmp extracted_keytab.rest1 extracted_keytab.rest2 > /dev/null && { echo "Keys for $p did not change!"; exit 1; } -test "$(grep $p extracted_keytab.rest2 | wc -l)" -eq 2 || +test "$(grep $p extracted_keytab.rest2 | wc -l)" -eq 4 || { echo "Wrong number of new keys!"; exit 1; } sh ${leaks_kill} httpkadmind $httpkadmindpid || ec=1 @@ -613,6 +631,7 @@ echo "Starting httpkadmind with local read-only HDB and remote read-write HDB" ${httpkadmind} -H $server -H localhost -t --daemon \ --local-read-only \ --writable-admin-server=$(uname -n):$admport \ + --read-only-admin-server=$(uname -n):$admport2 \ --kadmin-client-name=httpkadmind/admin@${R} \ --kadmin-client-keytab=$keytab || { echo "httpkadmind failed to start"; exit 2; } @@ -644,7 +663,7 @@ 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 || { echo "Failed to list keytab for $p"; exit 1; } -test "$(grep $p extracted_keytab.rest1 | wc -l)" -eq 2 || +test "$(grep $p extracted_keytab.rest1 | wc -l)" -eq 4 || { echo "Wrong number of new keys!"; exit 1; } get_keytab "dNSName=${hn}&rotate=true" -sf -o "${objdir}/extracted_keytab" && { echo "GET succeeded for write operation!"; exit 1; } @@ -654,7 +673,7 @@ ${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest2 | { echo "Failed to list keytab for $p"; exit 1; } cmp extracted_keytab.rest1 extracted_keytab.rest2 > /dev/null && { echo "Keys for $p did not change!"; exit 1; } -test "$(grep $p extracted_keytab.rest2 | wc -l)" -eq 3 || +test "$(grep $p extracted_keytab.rest2 | wc -l)" -eq 6 || { echo "Wrong number of new keys!"; exit 1; } echo "Checking that host services as clients can self-create" diff --git a/tests/kdc/check-iprop.in b/tests/kdc/check-iprop.in index bb45694dd..2242d0871 100644 --- a/tests/kdc/check-iprop.in +++ b/tests/kdc/check-iprop.in @@ -381,7 +381,7 @@ slave_get host/foo@${R} | \ wait_for_slave2 4 echo "Delete 3DES keys" -${kadmin} -l del_enctype host/foo@${R} des3-cbc-sha1 +${kadmin} -l del_enctype host/foo@${R} aes256-cts-hmac-sha1-96 wait_for_slave KRB5_CONFIG="${objdir}/krb5-slave.conf" \ ${kadmin} -l get host/foo@${R} | \ @@ -390,7 +390,7 @@ ${kadmin} -l get host/foo@${R} | \ ' | ${EGREP} 1234 > /dev/null || exit 1 KRB5_CONFIG="${objdir}/krb5-slave.conf" \ ${kadmin} -l get host/foo@${R} | \ - ${EGREP} 'Keytypes:.*des3-cbc-sha1' > /dev/null && exit 1 + ${EGREP} 'Keytypes:.*aes256-cts-hmac-sha1-96' > /dev/null && exit 1 echo "Change policy host" ${kadmin} -l modify --policy=default host/foo@${R} || exit 1 diff --git a/tests/kdc/check-kdc.in b/tests/kdc/check-kdc.in index f12c45180..e69a9deed 100644 --- a/tests/kdc/check-kdc.in +++ b/tests/kdc/check-kdc.in @@ -37,10 +37,16 @@ objdir="@objdir@" . ${env_setup} +if [ $# -eq 0 ]; then + weak=false +else + weak=true +fi + KRB5_CONFIG="${1-${objdir}/krb5.conf}" export KRB5_CONFIG -testfailed="echo test failed; cat messages.log; exit 1" +testfailed="echo test failed; exit 1" # If there is no useful db support compiled in, disable test ${have_db} || exit 77 @@ -151,11 +157,10 @@ add -p foo --use-defaults remove@${R} add -p nop --use-defaults ${server}@${R} cpw -p bla --keepold ${server}@${R} cpw -p kaka --keepold ${server}@${R} -add -p kaka --use-defaults ${server}-des3@${R} -add -p kaka --use-defaults kt-des3@${R} -add -p kaka --use-defaults foo/des3-only@${R} -add -p kaka --use-defaults bar/des3-only@${R} -add -p kaka --use-defaults foo/aes-only@${R} +add -p kaka --use-defaults ${server}-aes@${R} +add -p kaka --use-defaults kt-aes@${R} +add -p kaka --use-defaults foo/aes-sha1-only@${R} +add -p kaka --use-defaults foo/aes-sha2-only@${R} add -p sens --use-defaults --attributes=disallow-forwardable sensitive@${R} add -p foo --use-defaults ${ps} modify --attributes=+trusted-for-delegation ${ps} @@ -262,29 +267,46 @@ ${EGREP} -v '^FILE:' tempfile | ${EGREP} -v '^Vno' | ${EGREP} -v '^$' | \ ${kadmin} get foo@${R} > tempfile || exit 1 -enctypes=`grep Keytypes: tempfile | sed 's/(pw-salt)//g' | sed 's/,//g' | sed 's/Keytypes://' | sed 's/\[[0-9]*\]//g'` +enctypes=`grep Keytypes: tempfile | + sed 's/(pw-salt)//g' | + sed 's/(pw-salt([^)]*))//' | + sed 's/,//g' | + sed 's/Keytypes://' | + sed 's/\[[0-9]*\]//g'` -enctype_sans_aes=`echo $enctypes | sed 's/aes[^ ]*//g'` -enctype_sans_des3=`echo $enctypes | sed 's/des3-cbc-sha1//g'` +enctype_sans_aes_sha2=`echo $enctypes | sed 's/aes[^ ]*sha384[^ ]*//g'` +enctype_sans_aes_sha1=`echo $enctypes | sed 's/aes[^ ]*sha1[^ ]*//g'` -echo "deleting all but des enctypes on kt-des3 in keytab" -${kadmin} ext -k ${keytab} kt-des3@${R} || exit 1 -for a in ${enctype_sans_des3} ; do - ${ktutil} -k ${keytab} remove -p kt-des3@${R} -e $a +echo "deleting all but sha1 enctypes on kt-aes in keytab" +${kadmin} ext -k ${keytab} kt-aes@${R} || exit 1 +for a in ${enctype_sans_aes_sha1}; do + ${ktutil} -k ${keytab} remove -p kt-aes@${R} -e $a done echo "checking globbing keys rules" -${kadmin} get foo/des3-only@${R} > tempfile || exit 1 -enctypes=`grep Keytypes: tempfile | sed 's/(pw-salt)//g' | sed 's/,//g' | sed 's/Keytypes://' | sed 's/\[[0-9]*\]//g' | sed 's/ //g'` -if [ X"$enctypes" != Xdes3-cbc-sha1 ] ; then - echo "des3 only is not only des3: $enctypes" +${kadmin} get foo/aes-sha1-only@${R} > tempfile || exit 1 +enctypes=`grep Keytypes: tempfile | + sed 's/(pw-salt)//g' | + sed 's/(pw-salt([^)]*))//' | + sed 's/,//g' | + sed 's/Keytypes://' | + sed 's/ //g' | + sed 's/\[[0-9]*\]//g'` +if [ X"$enctypes" != Xaes256-cts-hmac-sha1-96 ] ; then + echo "aes-sha1 only is not only aes-sha1: $enctypes" exit 1 fi -${kadmin} get foo/aes-only@${R} > tempfile || exit 1 -enctypes=`grep Keytypes: tempfile | sed 's/(pw-salt)//g' | sed 's/,//g' | sed 's/Keytypes://' | sed 's/\[[0-9]*\]//g' | sed 's/ //g'` -if [ X"$enctypes" != Xaes256-cts-hmac-sha1-96 ] ; then - echo "aes only is not only aes: $enctypes" +${kadmin} get foo/aes-sha2-only@${R} > tempfile || exit 1 +enctypes=`grep Keytypes: tempfile | + sed 's/(pw-salt)//g' | + sed 's/(pw-salt([^)]*))//' | + sed 's/,//g' | + sed 's/Keytypes://' | + sed 's/ //g' | + sed 's/\[[0-9]*\]//g'` +if [ X"$enctypes" != Xaes256-cts-hmac-sha384-192 ] ; then + echo "aes-sha2 only is not only aes-sha2: $enctypes" exit 1 fi @@ -658,8 +680,8 @@ ${klist} | grep "Principal: ${server}" > /dev/null || \ ${kdestroy} echo "Getting key for key that are a subset in keytab compared to kdb" -${kinit} --keytab=${keytab} kt-des3@${R} -${klist} | grep "Principal: kt-des3" > /dev/null || \ +${kinit} --keytab=${keytab} kt-aes@${R} +${klist} | grep "Principal: kt-aes" > /dev/null || \ { ec=1 ; eval "${testfailed}"; } ${kdestroy} @@ -702,11 +724,11 @@ ${kdestroy} ${kadmin} delete rename@${R2} || exit 1 echo deleting all but aes enctypes on krbtgt -${kadmin} del_enctype krbtgt/${R}@${R} ${enctype_sans_aes} || exit 1 +${kadmin} del_enctype krbtgt/${R}@${R} ${enctype_sans_aes_sha2} || exit 1 -echo deleting all but des enctypes on server-des3 -${kadmin} del_enctype ${server}-des3@${R} ${enctype_sans_des3} || exit 1 -${kadmin} ext -k ${keytab} ${server}-des3@${R} || exit 1 +echo deleting all but aes-sha1 enctypes on server-aes +${kadmin} del_enctype ${server}-aes@${R} ${enctype_sans_aes_sha1} || exit 1 +${kadmin} ext -k ${keytab} ${server}-aes@${R} || exit 1 echo "try all permutations (only aes)"; > messages.log for a in $enctypes; do @@ -720,14 +742,14 @@ for a in $enctypes; do ${test_ap_req} ${server}@${R} ${keytab} ${cache} || \ { ec=1 ; eval "${testfailed}"; } - echo "Getting tickets ($a -> $b) (server des3 only)"; > messages.log - ${kgetcred} ${server}-des3@${R} || \ + echo "Getting tickets ($a -> $b) (server aes-sha1 only)"; > messages.log + ${kgetcred} ${server}-aes@${R} || \ { ec=1 ; eval "${testfailed}"; } - ${test_ap_req} ${server}-des3@${R} ${keytab} ${cache} || \ + ${test_ap_req} ${server}-aes@${R} ${keytab} ${cache} || \ { ec=1 ; eval "${testfailed}"; } ${kdestroy} --credential=${server}@${R} - ${kdestroy} --credential=${server}-des3@${R} + ${kdestroy} --credential=${server}-aes@${R} done ${kdestroy} done @@ -735,6 +757,8 @@ done echo deleting all enctypes on krbtgt ${kadmin} del_enctype krbtgt/${R}@${R} aes256-cts-hmac-sha1-96 || \ { ec=1 ; eval "${testfailed}"; } +${kadmin} del_enctype krbtgt/${R}@${R} aes256-cts-hmac-sha384-192 || \ + { ec=1 ; eval "${testfailed}"; } echo "try initial ticket w/o and keys on krbtgt" ${kinit} --password-file=${objdir}/foopassword foo@${R} 2>/dev/null && \ { ec=1 ; eval "${testfailed}"; } @@ -803,9 +827,19 @@ else echo "no pkinit (pkinit: $pkinit, rsa: $rsa)"; > messages.log fi +if $weak; then echo "test impersonate using rc4 based tgt"; > messages.log -${kinit} -e arcfour-hmac-md5 --forwardable --password-file=${objdir}/foopassword ${ps} || \ - { ec=1 ; eval "${testfailed}"; } + ${kinit} -e arcfour-hmac-md5 --forwardable --password-file=${objdir}/foopassword ${ps} || \ + { ec=1 ; eval "${testfailed}"; } + ${kgetcred_imp} --impersonate=bar@${R} ${ps} || \ + { ec=1 ; eval "${testfailed}"; } + ${test_ap_req} ${ps} ${keytab} ${ocache} || \ + { ec=1 ; eval "${testfailed}"; } +fi + +echo "test impersonate"; > messages.log +${kinit} --forwardable --password-file=${objdir}/foopassword ${ps} || \ + { bash -i; ec=1 ; eval "${testfailed}"; } ${kgetcred_imp} --impersonate=bar@${R} ${ps} || \ { ec=1 ; eval "${testfailed}"; } ${test_ap_req} ${ps} ${keytab} ${ocache} || \ diff --git a/tests/kdc/check-keys.in b/tests/kdc/check-keys.in deleted file mode 100644 index 78cc70b3d..000000000 --- a/tests/kdc/check-keys.in +++ /dev/null @@ -1,100 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2007 Kungliga Tekniska Högskolan -# (Royal Institute of Technology, Stockholm, Sweden). -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# 3. Neither the name of the Institute nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. - -top_builddir="@top_builddir@" -env_setup="@env_setup@" -objdir="." - -. ${env_setup} - -srcdir="${top_srcdir}/tests/kdc" - -# If there is no useful db support compiled in, disable test -${have_db} || exit 77 - -R=TEST.H5L.SE -principal=host/datan.test.h5l.se@${R} - -kadmin="${kadmin} -l -r $R" - -CIN=${srcdir}/krb5.conf.keys.in -COUT=${objdir}/krb5.conf.keys - -sedvars="-e s,[@]srcdir[@],${srcdir},g -e s,[@]objdir[@],${objdir},g" - -KRB5_CONFIG="${COUT}" -export KRB5_CONFIG - -rm -f ${COUT} -rm -f current-db* -rm -f out-* -rm -f mkey.file* -rm -f messages.log - -sed -e 's/@keys@/v5/' \ - ${sedvars} < ${CIN} > ${COUT} - -echo Creating database -${kadmin} < ${COUT} -${kadmin} cpw -p foo ${principal} || exit 1 - -sed -e 's/@keys@/v4 v5/' \ - ${sedvars} < ${CIN} > ${COUT} -${kadmin} cpw -p foo ${principal} || exit 1 - -sed -e 's/@keys@/v5 v4/' \ - ${sedvars} < ${CIN} > ${COUT} -${kadmin} cpw -p foo ${principal} || exit 1 - -sed -e 's/@keys@/des:pw-salt:/' \ - ${sedvars} < ${CIN} > ${COUT} -${kadmin} cpw -p foo ${principal} || exit 1 - -if [ 'X@ENABLE_AFS_STRING_TO_KEY@' = "X1" ]; then - sed -e 's/@keys@/des-cbc-crc:afs3-salt:test.h5l.se/' \ - ${sedvars} < ${CIN} > ${COUT} - ${kadmin} cpw -p foo ${principal} || exit 1 - - sed -e 's/@keys@/des:afs3-salt:test.h5l.se/' \ - ${sedvars} < ${CIN} > ${COUT} - ${kadmin} cpw -p foo ${principal} || exit 1 -fi - -exit 0 diff --git a/tests/kdc/check-pkinit.in b/tests/kdc/check-pkinit.in index d278739e3..b1370a44a 100644 --- a/tests/kdc/check-pkinit.in +++ b/tests/kdc/check-pkinit.in @@ -322,6 +322,106 @@ ${kinit} --canonicalize \ ${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; } ${kdestroy} +echo "Testing DH group and KDF algorithm options" + +# Helper function to check that the KDC used the expected key agreement algorithm +check_keyagreement() { + expected="$1" + if grep "AS-REQ SUCCESS" messages.log | grep -q "keyagreement=${expected}"; then + echo " OK: keyagreement=${expected}" + else + echo " FAIL: expected keyagreement=${expected}" + grep "AS-REQ SUCCESS" messages.log | head -1 + ec=1 + fi +} + +# Helper function to check that the KDC used the expected KDF +check_kdf() { + expected="$1" + if grep "AS-REQ SUCCESS" messages.log | grep -q "kdf=${expected}"; then + echo " OK: kdf=${expected}" + else + echo " FAIL: expected kdf=${expected}" + grep "AS-REQ SUCCESS" messages.log | head -1 + ec=1 + fi +} + +# Test various DH groups (RFC 3526 MODP groups) +# Note: The KDC logs the moduli name from its built-in/configured moduli file, +# not the client's requested group name. The default built-in is rfc3526-MODP-group14. +for dh_group in modp_2048 modp_3072; do + echo "Trying pk-init with --key-agreement=${dh_group}"; > messages.log + ${kinit} --key-agreement=${dh_group} \ + -C FILE:${base}/pkinit.crt,${keyfile2} bar@${R} || \ + { ec=1 ; eval "${testfailed}"; } + # The KDC uses its configured moduli; default is rfc3526-MODP-group14 + check_keyagreement "rfc3526-MODP-group14" + ${kdestroy} +done + +# Test ECDH curves (NIST curves) +# Note: OpenSSL uses different names internally (prime256v1, secp384r1, secp521r1) +for curve in P-256:prime256v1 P-384:secp384r1 P-521:secp521r1; do + cli_name="${curve%%:*}" + log_name="${curve##*:}" + echo "Trying pk-init with --key-agreement=${cli_name}"; > messages.log + ${kinit} --key-agreement=${cli_name} \ + -C FILE:${base}/pkinit.crt,${keyfile2} bar@${R} || \ + { ec=1 ; eval "${testfailed}"; } + check_keyagreement "${log_name}" + ${kdestroy} +done + +# Test RFC 8636 KDF algorithms +for kdf in ah-sha256:id_pkinit_kdf_ah_sha256 ah-sha384:id_pkinit_kdf_ah_sha384 ah-sha512:id_pkinit_kdf_ah_sha512; do + cli_name="${kdf%%:*}" + log_name="${kdf##*:}" + echo "Trying pk-init with --kdf=${cli_name}"; > messages.log + ${kinit} --kdf=${cli_name} \ + -C FILE:${base}/pkinit.crt,${keyfile2} bar@${R} || \ + { ec=1 ; eval "${testfailed}"; } + check_kdf "${log_name}" + ${kdestroy} +done + +# Test legacy RFC 4556 KDF (SHA-1 based octetstring2key) +echo "Trying pk-init with --kdf=RFC4556 (legacy)"; > messages.log +${kinit} --kdf=RFC4556 \ + -C FILE:${base}/pkinit.crt,${keyfile2} bar@${R} || \ + { ec=1 ; eval "${testfailed}"; } +check_kdf "RFC4556" +${kdestroy} + +# Test combinations of DH group and KDF +echo "Trying pk-init with --key-agreement=P-256 --kdf=ah-sha256"; > messages.log +${kinit} --key-agreement=P-256 --kdf=ah-sha256 \ + -C FILE:${base}/pkinit.crt,${keyfile2} bar@${R} || \ + { ec=1 ; eval "${testfailed}"; } +check_keyagreement "prime256v1" +check_kdf "id_pkinit_kdf_ah_sha256" +${kdestroy} + +echo "Trying pk-init with --key-agreement=modp_3072 --kdf=ah-sha384"; > messages.log +${kinit} --key-agreement=modp_3072 --kdf=ah-sha384 \ + -C FILE:${base}/pkinit.crt,${keyfile2} bar@${R} || \ + { ec=1 ; eval "${testfailed}"; } +# The KDC uses its configured moduli; default is rfc3526-MODP-group14 +check_keyagreement "rfc3526-MODP-group14" +check_kdf "id_pkinit_kdf_ah_sha384" +${kdestroy} + +# Test X25519 if available (may fail if not supported by OpenSSL build) +echo "Trying pk-init with --key-agreement=X25519 (may skip if unsupported)"; > messages.log +if ${kinit} --key-agreement=X25519 \ + -C FILE:${base}/pkinit.crt,${keyfile2} bar@${R} 2>/dev/null; then + check_keyagreement "x25519" + ${kdestroy} +else + echo "X25519 not supported (skipped)" +fi + KRB5_CONFIG="${objdir}/krb5-pkinit-win.conf" export KRB5_CONFIG @@ -356,37 +456,85 @@ ${kdestroy} KRB5_CONFIG="${objdir}/krb5-pkinit.conf" export KRB5_CONFIG -echo "Trying PKCS11 support" +# PKCS#11 support via OpenSSL pkcs11-provider +# Requires --with-openssl-pkcs11-provider=path to be set at configure time +openssl_pkcs11_provider="@OPENSSL_PKCS11_PROVIDER@" -cat > test-rc-file.rc < ${objdir}/test-rc-file.rc < ${objdir}/openssl-pkcs11.cnf < messages.log + ${kinit} -C "PKCS11:pkcs11:" foo@${R} || \ + { ec=1 ; eval "${testfailed}"; } + ${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; } + ${kdestroy} + + unset PKCS11_PROVIDER_MODULE + unset OPENSSL_CONF + unset SOFTPKCS11RC + + else + echo "Skipping PKCS#11 test: soft PKCS#11 module not found" fi -done - -if [ X"$file" != X -a @DLOPEN@ ] ; then - - echo "Trying pk-init (principal in pki-mapping file) "; > messages.log - ${kinit} -C PKCS11:${file} foo@${R} || \ - { ec=1 ; eval "${testfailed}"; } - ${kgetcred} ${server}@${R} || { ec=1 ; eval "${testfailed}"; } - ${kdestroy} +else + echo "Skipping PKCS#11 test: --with-openssl-pkcs11-provider not configured" fi - echo "killing kdc (${kdcpid})" sh ${leaks_kill} kdc $kdcpid || ec=1 diff --git a/tests/kdc/krb5-cccol.conf.in b/tests/kdc/krb5-cccol.conf.in index 819de8007..142ffa377 100644 --- a/tests/kdc/krb5-cccol.conf.in +++ b/tests/kdc/krb5-cccol.conf.in @@ -136,8 +136,8 @@ [kadmin] save-password = true default_key_rules = { - */des3-only@* = des3-cbc-sha1:pw-salt - */aes-only@* = aes256-cts-hmac-sha1-96:pw-salt + */aes-sha1-only@* = aes256-cts-hmac-sha1-96:pw-salt + */aes-sha2-only@* = aes256-cts-hmac-sha384-192:pw-salt } @dk@ diff --git a/tests/kdc/krb5-kcm.conf.in b/tests/kdc/krb5-kcm.conf.in index bdcca073c..ae7a218a3 100644 --- a/tests/kdc/krb5-kcm.conf.in +++ b/tests/kdc/krb5-kcm.conf.in @@ -136,8 +136,8 @@ [kadmin] save-password = true default_key_rules = { - */des3-only@* = des3-cbc-sha1:pw-salt - */aes-only@* = aes256-cts-hmac-sha1-96:pw-salt + */aes-sha1-only@* = aes256-cts-hmac-sha1-96:pw-salt + */aes-sha2-only@* = aes256-cts-hmac-sha384-192:pw-salt } @dk@ diff --git a/tests/kdc/krb5.conf.in b/tests/kdc/krb5.conf.in index ce2feb3c0..354e14677 100644 --- a/tests/kdc/krb5.conf.in +++ b/tests/kdc/krb5.conf.in @@ -83,6 +83,7 @@ allow-anonymous = true digests_allowed = chap-md5,digest-md5,ntlm-v1,ntlm-v1-session,ntlm-v2,ms-chap-v2 strict-nametypes = true + pkinit_allow_rsa_key_transport = true enable-http = true @@ -147,8 +148,8 @@ [kadmin] save-password = true default_key_rules = { - */des3-only@* = des3-cbc-sha1:pw-salt - */aes-only@* = aes256-cts-hmac-sha1-96:pw-salt + */aes-sha1-only@* = aes256-cts-hmac-sha1-96:pw-salt + */aes-sha2-only@* = aes256-cts-hmac-sha384-192:pw-salt } @dk@ diff --git a/tests/kdc/ntlm-user-file.txt b/tests/kdc/ntlm-user-file.txt deleted file mode 100644 index d8071273e..000000000 --- a/tests/kdc/ntlm-user-file.txt +++ /dev/null @@ -1 +0,0 @@ -TEST:foo:digestpassword diff --git a/windows/NTMakefile.config b/windows/NTMakefile.config index 5ff4e5ce7..1041ded45 100644 --- a/windows/NTMakefile.config +++ b/windows/NTMakefile.config @@ -43,8 +43,8 @@ PKINIT=1 NO_AFS=1 # OpenSSL (mostly not needed on Windows, but should work) -# INCLUDE_openssl_crypto= -# LIB_openssl_crypto= +INCLUDE_openssl_crypto="C:\Program Files\OpenSSL\include" +LIB_openssl_crypto="C:\Program Files\OpenSSL\lib\VC\x64\MD\libcrypto.lib" # OpenLDAP package is available # OPENLDAP=1 diff --git a/windows/NTMakefile.sdk b/windows/NTMakefile.sdk index a9f2b30df..7abf44cf0 100644 --- a/windows/NTMakefile.sdk +++ b/windows/NTMakefile.sdk @@ -57,11 +57,20 @@ NMAKE_WINVER=0x0A00 !error Unknown value for APPVER !endif +!ifdef CC +cc = $(CC) +!else cc = cl +!endif link = link implib = lib +!if "$(cc)" == "clang-cl" +# clang-cl: use clang warnings, not MSVC /W4 +cflags = -c -DCRTAPI1=_cdecl -DCRTAPI2=_cdecl -nologo -Wall -Wno-unknown-pragmas +!else cflags = -c -DCRTAPI1=_cdecl -DCRTAPI2=_cdecl -nologo -GS -W4 +!endif !if "$(CPU)" == "i386" cflags = $(cflags) -D_X86_=1 diff --git a/windows/NTMakefile.w32 b/windows/NTMakefile.w32 index fd921930c..07ccd8b50 100644 --- a/windows/NTMakefile.w32 +++ b/windows/NTMakefile.w32 @@ -156,10 +156,12 @@ LIGHT=$(LIGHT_CMD) -nologo pthreadinc= -I$(PTHREAD_INC) !endif +opensslinc= -I$(INCLUDE_openssl_crypto) + #---------------------------------------------------------------- # Build options -cincdirs=$(cincdirs) -I$(INCDIR) -I$(INCDIR)\krb5 $(pthreadinc) +cincdirs=$(cincdirs) -I$(INCDIR) -I$(INCDIR)\krb5 $(pthreadinc) $(opensslinc) cdefines=$(cdefines) -DHAVE_CONFIG_H # Windows CNG provider cdebug=$(cdebug) /Zi @@ -565,7 +567,7 @@ DLLPREP_NODIST=\ ( $(_VC_MANIFEST_EMBED_DLL) && $(_VC_MANIFEST_CLEAN) && $(SYMSTORE_IMPORT) ) || ( $(RM) $@ && exit /b 1 ) DLLPREP_MERGE=\ -( ( $(_MERGE_MANIFEST_DLL) || $(_INSERT_APPMANIFEST_DLL) && $(SYMSTORE_IMPORT) ) && $(_CODESIGN) && $(_CODESIGN_SHA256) ) || ( $(RM) $@ && exit /b 1 ) +( ( $(_MERGE_MANIFEST_DLL) || $(_INSERT_APPMANIFEST_DLL) ) && $(SYMSTORE_IMPORT) && $(_CODESIGN) && $(_CODESIGN_SHA256) ) || ( $(RM) $@ && exit /b 1 ) #---------------------------------------------------------------------- # Convenience macros for import libraries and assemblies @@ -582,12 +584,10 @@ LIBHEIMBASE =$(LIBDIR)\libheimbase.lib LIBHEIMDAL =$(LIBDIR)\heimdal.lib LIBHEIMIPCC =$(LIBDIR)\libheim-ipcc.lib LIBHEIMIPCS =$(LIBDIR)\libheim-ipcs.lib -LIBHEIMNTLM =$(LIBDIR)\libheimntlm.lib LIBHX509 =$(LIBDIR)\libhx509.lib LIBKADM5CLNT=$(LIBDIR)\libkadm5clnt.lib LIBKADM5SRV =$(LIBDIR)\libkadm5srv.lib LIBKDC =$(LIBDIR)\libkdc.lib -LIBLTM =$(LIBDIR)\libltm.lib LIBKRB5 =$(LIBDIR)\libkrb5.lib LIBRFC3961 =$(LIBDIR)\librfc3961.lib LIBROKEN =$(LIBDIR)\libroken.lib @@ -595,7 +595,6 @@ LIBSL =$(LIBDIR)\libsl.lib LIBSQLITE =$(LIBDIR)\libsqlite.lib LIBVERS =$(LIBDIR)\libvers.lib LIBWIND =$(LIBDIR)\libwind.lib -LIBX25519 =$(LIBDIR)\libx25519.lib !ifdef VER_DEBUG ASM_DBG=.Debug