summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Sutton <josephsutton@catalyst.net.nz>2021-10-27 15:51:58 +1300
committerJule Anger <janger@samba.org>2021-11-09 19:45:34 +0000
commitf08e6ac86226dcd939fd0e40b6f7dc80c5c00e79 (patch)
tree597c40d36f074bcea3465c8487a0256a7fadbd15
parentfd50fecbe99ae4fc63843c796d0a516731a1fe6a (diff)
downloadsamba-f08e6ac86226dcd939fd0e40b6f7dc80c5c00e79.tar.gz
CVE-2020-25719 heimdal:kdc: Check name in request against name in user-to-user TGT
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14873 Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abartlet@samba.org>
-rw-r--r--selftest/knownfail_heimdal_kdc3
-rw-r--r--source4/heimdal/kdc/krb5tgs.c56
2 files changed, 55 insertions, 4 deletions
diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc
index 43224fbbb81..a0a4af4aa07 100644
--- a/selftest/knownfail_heimdal_kdc
+++ b/selftest/knownfail_heimdal_kdc
@@ -114,8 +114,5 @@
^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_sid_mismatch_nonexisting
^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_sid_mismatch_existing
^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_sid_mismatch_nonexisting
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_tgt_cname_host
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_wrong_sname
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_wrong_sname_krbtgt
^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_authdata_no_pac
^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_not_revealed
diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c
index d6ca1fe601c..f59f99f369f 100644
--- a/source4/heimdal/kdc/krb5tgs.c
+++ b/source4/heimdal/kdc/krb5tgs.c
@@ -1302,9 +1302,12 @@ tgs_build_reply(krb5_context context,
krb5_error_code ret;
krb5_principal cp = NULL, sp = NULL, tp = NULL, dp = NULL;
krb5_principal krbtgt_principal = NULL;
+ krb5_principal user2user_princ = NULL;
char *spn = NULL, *cpn = NULL, *tpn = NULL, *dpn = NULL;
+ char *user2user_name = NULL;
hdb_entry_ex *server = NULL, *client = NULL, *s4u2self_impersonated_client = NULL;
HDB *clientdb, *s4u2self_impersonated_clientdb;
+ HDB *serverdb = NULL;
krb5_realm ref_realm = NULL;
EncTicketPart *tgt = &ticket->ticket;
const char *tgt_realm = /* Realm of TGT issuer */
@@ -1370,7 +1373,7 @@ tgs_build_reply(krb5_context context,
server_lookup:
ret = _kdc_db_fetch(context, config, sp, HDB_F_GET_SERVER | flags,
- NULL, NULL, &server);
+ NULL, &serverdb, &server);
if(ret == HDB_ERR_NOT_FOUND_HERE) {
kdc_log(context, config, 5, "target %s does not have secrets at this KDC, need to proxy", sp);
@@ -1511,6 +1514,7 @@ server_lookup:
krb5uint32 second_kvno = 0;
krb5uint32 *kvno_ptr = NULL;
size_t i;
+ hdb_entry_ex *user2user_client = NULL;
if(b->additional_tickets == NULL ||
b->additional_tickets->len == 0){
@@ -1559,6 +1563,53 @@ server_lookup:
if (ret)
goto out;
+ /* Fetch the name from the TGT. */
+ ret = _krb5_principalname2krb5_principal(context, &user2user_princ,
+ adtkt.cname, adtkt.crealm);
+ if (ret) {
+ goto out;
+ }
+
+ ret = krb5_unparse_name(context, user2user_princ, &user2user_name);
+ if (ret) {
+ goto out;
+ }
+
+ /* Look up the name given in the TGT in the database. */
+ ret = db_fetch_client(context, config, flags, user2user_princ, user2user_name,
+ krb5_principal_get_realm(context, krbtgt_out->entry.principal),
+ NULL, &user2user_client);
+ if (ret) {
+ goto out;
+ }
+
+ if (user2user_client != NULL) {
+ /*
+ * If the account is present in the database, check the account
+ * flags.
+ */
+ ret = kdc_check_flags(context, config,
+ user2user_client, user2user_name,
+ NULL, NULL,
+ FALSE);
+ if (ret) {
+ _kdc_free_ent(context, user2user_client);
+ goto out;
+ }
+
+ /*
+ * Also check that the account is the same one specified in the
+ * request.
+ */
+ ret = check_s4u2self(context, config, serverdb, server, user2user_client, user2user_princ);
+ if (ret) {
+ _kdc_free_ent(context, user2user_client);
+ goto out;
+ }
+ }
+
+ _kdc_free_ent(context, user2user_client);
+
ekey = &adtkt.key;
for(i = 0; i < b->etype.len; i++)
if (b->etype.val[i] == adtkt.key.keytype)
@@ -2062,6 +2113,7 @@ server_lookup:
reply);
out:
+ free(user2user_name);
if (tpn != cpn)
free(tpn);
free(spn);
@@ -2079,6 +2131,8 @@ out:
if(s4u2self_impersonated_client)
_kdc_free_ent(context, s4u2self_impersonated_client);
+ if (user2user_princ)
+ krb5_free_principal(context, user2user_princ);
if (tp && tp != cp)
krb5_free_principal(context, tp);
if (cp)