From c0c4b7a4bd229bd36d586faec6249baaba8e7adc Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 26 May 2022 16:39:20 +1200 Subject: CVE-2022-32744 s4:kdc: Modify HDB plugin to only look up kpasswd principal This plugin is now only used by the kpasswd service. Thus, ensuring we only look up the kadmin/changepw principal means we can't be fooled into accepting tickets for other service principals. We make sure not to specify a specific kvno, to ensure that we do not accept RODC-issued tickets. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 Signed-off-by: Joseph Sutton Reviewed-by: Andreas Schneider [jsutton@samba.org Fixed knownfail conflicts] [jsutton@samba.org Renamed entry to entry_ex; fixed knownfail conflicts; retained knownfail for test_kpasswd_from_rodc which now causes the KDC to panic] --- selftest/knownfail_heimdal_kdc | 3 -- source4/kdc/hdb-samba4-plugin.c | 2 +- source4/kdc/hdb-samba4.c | 66 +++++++++++++++++++++++++++++++++++++++++ source4/kdc/kdc-glue.h | 3 ++ 4 files changed, 70 insertions(+), 4 deletions(-) diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index afb9bcf1209..0d93253f999 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -275,6 +275,3 @@ # Kpasswd tests # ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_from_rodc.ad_dc -^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key.ad_dc -^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc -^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc diff --git a/source4/kdc/hdb-samba4-plugin.c b/source4/kdc/hdb-samba4-plugin.c index 4b90a766f76..dba25e825de 100644 --- a/source4/kdc/hdb-samba4-plugin.c +++ b/source4/kdc/hdb-samba4-plugin.c @@ -36,7 +36,7 @@ static krb5_error_code hdb_samba4_create(krb5_context context, struct HDB **db, base_ctx = talloc_get_type_abort(ptr, struct samba_kdc_base_context); /* The global kdc_mem_ctx and kdc_lp_ctx, Disgusting, ugly hack, but it means one less private hook */ - nt_status = hdb_samba4_create_kdc(base_ctx, context, db); + nt_status = hdb_samba4_kpasswd_create_kdc(base_ctx, context, db); if (NT_STATUS_IS_OK(nt_status)) { return 0; diff --git a/source4/kdc/hdb-samba4.c b/source4/kdc/hdb-samba4.c index 43e836f8360..a8aae50b5b0 100644 --- a/source4/kdc/hdb-samba4.c +++ b/source4/kdc/hdb-samba4.c @@ -136,6 +136,47 @@ static krb5_error_code hdb_samba4_fetch_kvno(krb5_context context, HDB *db, return code; } +static krb5_error_code hdb_samba4_kpasswd_fetch_kvno(krb5_context context, HDB *db, + krb5_const_principal _principal, + unsigned flags, + krb5_kvno _kvno, + hdb_entry_ex *entry_ex) +{ + struct samba_kdc_db_context *kdc_db_ctx = NULL; + krb5_error_code ret; + krb5_principal kpasswd_principal = NULL; + + kdc_db_ctx = talloc_get_type_abort(db->hdb_db, + struct samba_kdc_db_context); + + ret = smb_krb5_make_principal(context, &kpasswd_principal, + lpcfg_realm(kdc_db_ctx->lp_ctx), + "kadmin", "changepw", + NULL); + if (ret) { + return ret; + } + smb_krb5_principal_set_type(context, kpasswd_principal, KRB5_NT_SRV_INST); + + /* + * For the kpasswd service, always ensure we get the latest kvno. This + * also means we (correctly) refuse RODC-issued tickets. + */ + flags &= ~HDB_F_KVNO_SPECIFIED; + + /* Don't bother looking up a client or krbtgt. */ + flags &= ~(SDB_F_GET_CLIENT|SDB_F_GET_KRBTGT); + + ret = hdb_samba4_fetch_kvno(context, db, + kpasswd_principal, + flags, + 0, + entry_ex); + + krb5_free_principal(context, kpasswd_principal); + return ret; +} + static krb5_error_code hdb_samba4_firstkey(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry) { @@ -194,6 +235,14 @@ static krb5_error_code hdb_samba4_nextkey(krb5_context context, HDB *db, unsigne return ret; } +static krb5_error_code hdb_samba4_nextkey_panic(krb5_context context, HDB *db, + unsigned flags, + hdb_entry_ex *entry) +{ + DBG_ERR("Attempt to iterate kpasswd keytab => PANIC\n"); + smb_panic("hdb_samba4_nextkey_panic: Attempt to iterate kpasswd keytab"); +} + static krb5_error_code hdb_samba4_destroy(krb5_context context, HDB *db) { talloc_free(db); @@ -522,3 +571,20 @@ NTSTATUS hdb_samba4_create_kdc(struct samba_kdc_base_context *base_ctx, return NT_STATUS_OK; } + +NTSTATUS hdb_samba4_kpasswd_create_kdc(struct samba_kdc_base_context *base_ctx, + krb5_context context, struct HDB **db) +{ + NTSTATUS nt_status; + + nt_status = hdb_samba4_create_kdc(base_ctx, context, db); + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; + } + + (*db)->hdb_fetch_kvno = hdb_samba4_kpasswd_fetch_kvno; + (*db)->hdb_firstkey = hdb_samba4_nextkey_panic; + (*db)->hdb_nextkey = hdb_samba4_nextkey_panic; + + return NT_STATUS_OK; +} diff --git a/source4/kdc/kdc-glue.h b/source4/kdc/kdc-glue.h index c083b8c6429..ff8684e1666 100644 --- a/source4/kdc/kdc-glue.h +++ b/source4/kdc/kdc-glue.h @@ -45,6 +45,9 @@ kdc_code kpasswdd_process(struct kdc_server *kdc, NTSTATUS hdb_samba4_create_kdc(struct samba_kdc_base_context *base_ctx, krb5_context context, struct HDB **db); +NTSTATUS hdb_samba4_kpasswd_create_kdc(struct samba_kdc_base_context *base_ctx, + krb5_context context, struct HDB **db); + /* from kdc-glue.c */ int kdc_check_pac(krb5_context krb5_context, DATA_BLOB server_sig, -- cgit v1.2.1