From b7fe0fb85a780fed3c54ed2539fc974db1884dc2 Mon Sep 17 00:00:00 2001 From: Isaac Boukris Date: Mon, 12 Nov 2018 20:08:06 +0200 Subject: [PATCH] kdc: allow checksum of PA-FOR-USER to be HMAC_MD5 even if tgt used an enctype with a different checksum. Per [MS-SFU] 2.2.1 PA-FOR-USER the checksum is always HMAC_MD5, and that's what Windows and MIT clients send. In heimdal both the client and kdc use instead the checksum of the tgt, and therefore work with each other but windows and MIT clients fail against heimdal KDC. Both Windows and MIT KDC would allow any keyed checksum to be used so Heimdal client work fine against it. Change Heimdal KDC to allow HMAC_MD5 even for non RC4 based tgt in order to support per-spec clients. Signed-off-by: Isaac Boukris --- kdc/krb5tgs.c | 34 +++++++++++++++++++++++++++------ lib/krb5/libkrb5-exports.def.in | 1 + lib/krb5/version-script.map | 1 + tests/kdc/check-kdc.in | 8 ++++++++ 4 files changed, 38 insertions(+), 6 deletions(-) diff --git a/kdc/krb5tgs.c b/kdc/krb5tgs.c index 14943077a..98a4092b1 100644 --- a/kdc/krb5tgs.c +++ b/kdc/krb5tgs.c @@ -2052,12 +2052,34 @@ server_lookup: goto out; } - ret = krb5_verify_checksum(context, - crypto, - KRB5_KU_OTHER_CKSUM, - datack.data, - datack.length, - &self.cksum); + /* Allow HMAC_MD5 checksum with any key type */ + if (self.cksum.cksumtype == CKSUMTYPE_HMAC_MD5) { + struct krb5_crypto_iov iov; + unsigned char csdata[16]; + Checksum cs; + + cs.checksum.length = sizeof(csdata); + cs.checksum.data = &csdata; + + iov.data.data = datack.data; + iov.data.length = datack.length; + iov.flags = KRB5_CRYPTO_TYPE_DATA; + + ret = _krb5_HMAC_MD5_checksum(context, NULL, &crypto->key, + KRB5_KU_OTHER_CKSUM, &iov, 1, + &cs); + if (ret == 0 && + krb5_data_ct_cmp(&cs.checksum, &self.cksum.checksum) != 0) + ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; + } + else { + ret = krb5_verify_checksum(context, + crypto, + KRB5_KU_OTHER_CKSUM, + datack.data, + datack.length, + &self.cksum); + } krb5_data_free(&datack); krb5_crypto_destroy(context, crypto); if (ret) { diff --git a/lib/krb5/libkrb5-exports.def.in b/lib/krb5/libkrb5-exports.def.in index c4b2cb908..9263ad608 100644 --- a/lib/krb5/libkrb5-exports.def.in +++ b/lib/krb5/libkrb5-exports.def.in @@ -781,6 +781,7 @@ EXPORTS _krb5_principalname2krb5_principal _krb5_put_int _krb5_s4u2self_to_checksumdata + _krb5_HMAC_MD5_checksum _krb5_expand_path_tokens ;! ; kinit helper diff --git a/lib/krb5/version-script.map b/lib/krb5/version-script.map index eee446def..b31f45665 100644 --- a/lib/krb5/version-script.map +++ b/lib/krb5/version-script.map @@ -772,6 +772,7 @@ HEIMDAL_KRB5_2.0 { _krb5_principalname2krb5_principal; _krb5_put_int; _krb5_s4u2self_to_checksumdata; + _krb5_HMAC_MD5_checksum; # kinit helper krb5_get_init_creds_opt_set_pkinit_user_certs; diff --git a/tests/kdc/check-kdc.in b/tests/kdc/check-kdc.in index 0f291551c..a341c6bd3 100644 --- a/tests/kdc/check-kdc.in +++ b/tests/kdc/check-kdc.in @@ -785,6 +785,14 @@ else echo "no pkinit (pkinit: $pkinit, rsa: $rsa)"; > messages.log fi +echo "test impersonate using rc4 based tgt"; > messages.log +${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}"; } + echo "tickets for impersonate test case"; > messages.log ${kinit} --forwardable --password-file=${objdir}/foopassword ${ps} || \ { ec=1 ; eval "${testfailed}"; }